The branch main has been updated by andrew:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=e72c41772352e1165711900c4f8df6b15b842ba8

commit e72c41772352e1165711900c4f8df6b15b842ba8
Author:     Andrew Turner <[email protected]>
AuthorDate: 2024-01-11 17:13:12 +0000
Commit:     Andrew Turner <[email protected]>
CommitDate: 2024-05-17 16:07:16 +0000

    arm: Use the correct irq when in the hypervisor
    
    When booting in the hypervisor state we need to use the hypervisor
    interrupt in the generic timer. In this case the registers we access
    in the kernel are remapped to the EL2 versions, however this causes
    an unexpected interrupt to trigger.
    
    Sponsored by:   Arm Ltd
    Differential Revision:  https://reviews.freebsd.org/D43975
---
 sys/arm/arm/generic_timer.c | 25 ++++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)

diff --git a/sys/arm/arm/generic_timer.c b/sys/arm/arm/generic_timer.c
index bad0939b6ab9..d3e264527a7f 100644
--- a/sys/arm/arm/generic_timer.c
+++ b/sys/arm/arm/generic_timer.c
@@ -171,12 +171,14 @@ static struct timecounter arm_tmr_timecount = {
 #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 @@ arm_tmr_attach(device_t dev)
 #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;

Reply via email to