在arm32的时候,在grub中通过调用bios提供的create_event 来产生时间戳,源码路径如下:grub-core/kernel/arm/efi/init.c
increment_timer (grub_efi_event_t event __attribute__ ((unused)),
void *context __attribute__ ((unused)))
{
tmr += 10;
}
void
grub_machine_init (void)
{
grub_efi_boot_services_t *b;
grub_efi_init ();
b = grub_efi_system_table->boot_services;
efi_call_5 (b->create_event, GRUB_EFI_EVT_TIMER | GRUB_EFI_EVT_NOTIFY_SIGNAL,
GRUB_EFI_TPL_CALLBACK, increment_timer, NULL, &tmr_evt);
efi_call_3 (b->set_timer, tmr_evt, GRUB_EFI_TIMER_PERIODIC, 100000);
grub_install_get_time_ms (grub_efi_get_time_ms);
}
grub_uint64_t
grub_get_time_ms (void)
{
return get_time_ms_func ();
}
void
grub_install_get_time_ms (get_time_ms_func_t func)
{
get_time_ms_func = func;
}
后续在driver中只要调用grub_get_time_ms 就可以获得时间,例如下面这段code
if (! (hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_OS_OWNED))
{
grub_uint64_t endtime;
grub_dprintf ("ahci", "Requesting AHCI ownership\n");
hba->bios_handoff = (hba->bios_handoff & ~GRUB_AHCI_BIOS_HANDOFF_RWC)
| GRUB_AHCI_BIOS_HANDOFF_OS_OWNED;
grub_dprintf ("ahci", "Waiting for BIOS to give up ownership\n");
endtime = grub_get_time_ms () + 1000;
}
而在arm64的时候就直接可以通过寄存器获得时间戳了,源码路径grub-core/kernel/arm64/efi/init.c
static grub_uint64_t
grub_efi_get_time_ms (void)
{
grub_uint64_t tmr;
asm volatile("mrs %0, cntvct_el0" : "=r" (tmr));
return tmr / timer_frequency_in_khz;
}
void
grub_machine_init (void)
{
grub_uint64_t timer_frequency;
grub_efi_init ();
asm volatile("mrs %0, cntfrq_el0" : "=r" (timer_frequency));
timer_frequency_in_khz = timer_frequency / 1000;
grub_install_get_time_ms (grub_efi_get_time_ms);
}
可见只要读取cntvct_el0 这个寄存器就可以获得时间
increment_timer (grub_efi_event_t event __attribute__ ((unused)),
void *context __attribute__ ((unused)))
{
tmr += 10;
}
void
grub_machine_init (void)
{
grub_efi_boot_services_t *b;
grub_efi_init ();
b = grub_efi_system_table->boot_services;
efi_call_5 (b->create_event, GRUB_EFI_EVT_TIMER | GRUB_EFI_EVT_NOTIFY_SIGNAL,
GRUB_EFI_TPL_CALLBACK, increment_timer, NULL, &tmr_evt);
efi_call_3 (b->set_timer, tmr_evt, GRUB_EFI_TIMER_PERIODIC, 100000);
grub_install_get_time_ms (grub_efi_get_time_ms);
}
grub_uint64_t
grub_get_time_ms (void)
{
return get_time_ms_func ();
}
void
grub_install_get_time_ms (get_time_ms_func_t func)
{
get_time_ms_func = func;
}
后续在driver中只要调用grub_get_time_ms 就可以获得时间,例如下面这段code
if (! (hba->bios_handoff & GRUB_AHCI_BIOS_HANDOFF_OS_OWNED))
{
grub_uint64_t endtime;
grub_dprintf ("ahci", "Requesting AHCI ownership\n");
hba->bios_handoff = (hba->bios_handoff & ~GRUB_AHCI_BIOS_HANDOFF_RWC)
| GRUB_AHCI_BIOS_HANDOFF_OS_OWNED;
grub_dprintf ("ahci", "Waiting for BIOS to give up ownership\n");
endtime = grub_get_time_ms () + 1000;
}
而在arm64的时候就直接可以通过寄存器获得时间戳了,源码路径grub-core/kernel/arm64/efi/init.c
static grub_uint64_t
grub_efi_get_time_ms (void)
{
grub_uint64_t tmr;
asm volatile("mrs %0, cntvct_el0" : "=r" (tmr));
return tmr / timer_frequency_in_khz;
}
void
grub_machine_init (void)
{
grub_uint64_t timer_frequency;
grub_efi_init ();
asm volatile("mrs %0, cntfrq_el0" : "=r" (timer_frequency));
timer_frequency_in_khz = timer_frequency / 1000;
grub_install_get_time_ms (grub_efi_get_time_ms);
}
可见只要读取cntvct_el0 这个寄存器就可以获得时间