Using NMI to synchronize timestamp counter between cores?
Posted: Tue Jun 01, 2010 2:44 am
I read up on all the different methods proposed for synchronizing time stamp counter (TSC) between cores. In my mini-PC that I currently target, this doesn't seem to be an issue at all since it only has an Intel Atom processor with hyperthreading. It probably has only a single TSC implemented. As I move on to my other PCs (one is a dual core AMD Athlon), I think the need for synchronization will arise. I have some trouble on that platform that could be related to TSC.
Anyway, NMI is an attractive option as it is non-maskable (predictable processing times), and the utility of the hardware NMI signal seems to be zero. First I would disable hardware NMI in the local Apic, just in case there is real hardware NMI activity.
Some possible implementation (in partial pseudocode):
In the null-thread before starting SMP (Measuring response-time for NMI handler):
On the BSP, start a timer:
In the timer handler (always runs on BSP):
AP code initialization:
The NMI handler (less some register pushing / loads):
The code that reads the timestamp would be modified to:
Does this look reasonable?
Anyway, NMI is an attractive option as it is non-maskable (predictable processing times), and the utility of the hardware NMI signal seems to be zero. First I would disable hardware NMI in the local Apic, just in case there is real hardware NMI activity.
Some possible implementation (in partial pseudocode):
In the null-thread before starting SMP (Measuring response-time for NMI handler):
Code: Select all
rdtsc
mov curr_time,eax
int 2
Code: Select all
GetSystemTime
add eax,1193
adc edx,0
mov di,OFFSET sync_tsc
StartTimer ; invoke handler in 1 ms
Code: Select all
sync_tsc:
rdtsc
mov curr_time,eax
SendNmiToAllExceptSelf (send an IPI with an NMI to all cores except self)
add eax,1193000
adc edx,0
mov di,OFFSET sync_tsc
StartTimer ; invoke again in 1s
Code: Select all
cli
hlt (wait for NMI)
jmp InitFirstThread
Code: Select all
rdtsc
sub eax,curr_time
GetProcessor
mov fs:diff_time,eax
iretd
Code: Select all
GetProcessor
rdtsc
add eax,fs:diff_time