kernel/arm64: Use virtual rather than physical timers.

* Fixes exception in arch_init_timer on boot when trying to write
  CNTP_CTL_EL0 under virtualization on M1 Max.
* Update TIMER_IRQ to match.
* Boot now proceeds before crashing with an invalid page fault in
  device manager.

Change-Id: I82f080bdc671258a1a35bf998d906e9010a6736e
Reviewed-on: https://review.haiku-os.org/c/haiku/+/8091
Tested-by: Commit checker robot <[email protected]>
Haiku-Format: Haiku-format Bot <[email protected]>
Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
Owen Anderson
2024-08-23 15:16:21 +00:00
committed by waddlesplash
parent 764365384d
commit 653d40cc93
+10 -7
View File
@@ -14,10 +14,11 @@
static uint64 sTimerTicksUS; static uint64 sTimerTicksUS;
static bigtime_t sTimerMaxInterval; static bigtime_t sTimerMaxInterval;
static uint64 sBootTime;
#define TIMER_ARMED (1) #define TIMER_ARMED (1)
#define TIMER_MASKED (2 | 1) #define TIMER_MASKED (2 | 1)
#define TIMER_IRQ 30 #define TIMER_IRQ 27
void void
@@ -26,22 +27,22 @@ arch_timer_set_hardware_timer(bigtime_t timeout)
if (timeout > sTimerMaxInterval) if (timeout > sTimerMaxInterval)
timeout = sTimerMaxInterval; timeout = sTimerMaxInterval;
WRITE_SPECIALREG(CNTP_TVAL_EL0, timeout * sTimerTicksUS); WRITE_SPECIALREG(CNTV_TVAL_EL0, timeout * sTimerTicksUS);
WRITE_SPECIALREG(CNTP_CTL_EL0, TIMER_ARMED); WRITE_SPECIALREG(CNTV_CTL_EL0, TIMER_ARMED);
} }
void void
arch_timer_clear_hardware_timer() arch_timer_clear_hardware_timer()
{ {
WRITE_SPECIALREG(CNTP_CTL_EL0, TIMER_MASKED); WRITE_SPECIALREG(CNTV_CTL_EL0, TIMER_MASKED);
} }
int32 int32
arch_timer_interrupt(void *data) arch_timer_interrupt(void *data)
{ {
WRITE_SPECIALREG(CNTP_CTL_EL0, TIMER_MASKED); WRITE_SPECIALREG(CNTV_CTL_EL0, TIMER_MASKED);
return timer_interrupt(); return timer_interrupt();
} }
@@ -52,9 +53,11 @@ arch_init_timer(kernel_args *args)
sTimerTicksUS = READ_SPECIALREG(CNTFRQ_EL0) / 1000000; sTimerTicksUS = READ_SPECIALREG(CNTFRQ_EL0) / 1000000;
sTimerMaxInterval = INT32_MAX / sTimerTicksUS; sTimerMaxInterval = INT32_MAX / sTimerTicksUS;
WRITE_SPECIALREG(CNTP_CTL_EL0, TIMER_MASKED); WRITE_SPECIALREG(CNTV_CTL_EL0, TIMER_MASKED);
install_io_interrupt_handler(TIMER_IRQ, &arch_timer_interrupt, NULL, 0); install_io_interrupt_handler(TIMER_IRQ, &arch_timer_interrupt, NULL, 0);
sBootTime = READ_SPECIALREG(CNTPCT_EL0);
return B_OK; return B_OK;
} }
@@ -62,5 +65,5 @@ arch_init_timer(kernel_args *args)
bigtime_t bigtime_t
system_time(void) system_time(void)
{ {
return READ_SPECIALREG(CNTPCT_EL0) / sTimerTicksUS; return (READ_SPECIALREG(CNTPCT_EL0) - sBootTime) / sTimerTicksUS;
} }