diff --git a/sys/arm/arm/generic_timer.c b/sys/arm/arm/generic_timer.c --- a/sys/arm/arm/generic_timer.c +++ b/sys/arm/arm/generic_timer.c @@ -171,12 +171,14 @@ #define set_el0(x, val) cp15_## x ##_set(val) #define set_el1(x, val) cp15_## x ##_set(val) #define HAS_PHYS true +#define IN_VHE false #else /* __aarch64__ */ #define get_el0(x) READ_SPECIALREG(x ##_el0) #define get_el1(x) READ_SPECIALREG(x ##_el1) #define set_el0(x, val) WRITE_SPECIALREG(x ##_el0, val) #define set_el1(x, val) WRITE_SPECIALREG(x ##_el1, val) #define HAS_PHYS has_hyp() +#define IN_VHE in_vhe() #endif static int @@ -678,13 +680,22 @@ #endif #ifdef __aarch64__ - /* - * Use the virtual timer when we can't use the hypervisor. - * A hypervisor guest may change the virtual timer registers while - * executing so any use of the virtual timer interrupt needs to be - * coordinated with the virtual machine manager. - */ - if (!HAS_PHYS) { + if (IN_VHE) { + /* + * The kernel is running at EL2. The EL0 timer registers are + * re-mapped to the EL2 version. Because of this we need to + * use the EL2 interrupt. + */ + sc->physical_sys = true; + first_timer = GT_HYP_PHYS; + last_timer = GT_HYP_PHYS; + } else if (!HAS_PHYS) { + /* + * Use the virtual timer when we can't use the hypervisor. + * A hypervisor guest may change the virtual timer registers + * while executing so any use of the virtual timer interrupt + * needs to be coordinated with the virtual machine manager. + */ sc->physical_sys = false; first_timer = GT_VIRT; last_timer = GT_VIRT;