git: e72c41772352 - main - arm: Use the correct irq when in the hypervisor
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 17 May 2024 16:12:51 UTC
The branch main has been updated by andrew: URL: https://cgit.FreeBSD.org/src/commit/?id=e72c41772352e1165711900c4f8df6b15b842ba8 commit e72c41772352e1165711900c4f8df6b15b842ba8 Author: Andrew Turner <andrew@FreeBSD.org> AuthorDate: 2024-01-11 17:13:12 +0000 Commit: Andrew Turner <andrew@FreeBSD.org> 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;