From d2ae03bae2add82124973876dec95eb126ff34c8 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Fri, 3 Mar 2023 11:02:19 -0600 Subject: arm64: disable the physical timer for now if HCR_EL2.E2H is set On some hardware, we can't clear HCR_EL2.E2H so accesses to the physical timer hopelessly trap to EL2. Stash off the value of HCR_EL2 and use it in has_hyp() to avoid this. Reviewed by: andrew Differential Revision: https://reviews.freebsd.org/D38884 --- sys/arm64/arm64/genassym.c | 1 + sys/arm64/arm64/locore.S | 5 +++-- sys/arm64/arm64/machdep.c | 9 ++++++++- sys/arm64/include/machdep.h | 1 + 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/sys/arm64/arm64/genassym.c b/sys/arm64/arm64/genassym.c index bd359699eca9..e444d0166360 100644 --- a/sys/arm64/arm64/genassym.c +++ b/sys/arm64/arm64/genassym.c @@ -45,6 +45,7 @@ ASSYM(BP_KERN_DELTA, offsetof(struct arm64_bootparams, kern_delta)); ASSYM(BP_KERN_STACK, offsetof(struct arm64_bootparams, kern_stack)); ASSYM(BP_KERN_TTBR0, offsetof(struct arm64_bootparams, kern_ttbr0)); ASSYM(BP_BOOT_EL, offsetof(struct arm64_bootparams, boot_el)); +ASSYM(BP_HCR_EL2, offsetof(struct arm64_bootparams, hcr_el2)); ASSYM(PCPU_SIZE, sizeof(struct pcpu)); ASSYM(PC_CURPCB, offsetof(struct pcpu, pc_curpcb)); diff --git a/sys/arm64/arm64/locore.S b/sys/arm64/arm64/locore.S index da3001711955..1080ebc6217e 100644 --- a/sys/arm64/arm64/locore.S +++ b/sys/arm64/arm64/locore.S @@ -146,6 +146,7 @@ virtdone: str x25, [x0, #BP_KERN_STACK] str x27, [x0, #BP_KERN_TTBR0] str x23, [x0, #BP_BOOT_EL] + str x4, [x0, #BP_HCR_EL2] /* trace back starts here */ mov fp, #0 @@ -286,8 +287,8 @@ LENTRY(drop_to_el1) */ tst x4, #HCR_E2H mov x3, #CPTR_RES1 /* HCR_E2H == 0 */ - mov x4, #CPTR_FPEN /* HCR_E2H == 1 */ - csel x2, x3, x4, eq + mov x5, #CPTR_FPEN /* HCR_E2H == 1 */ + csel x2, x3, x5, eq msr cptr_el2, x2 /* Don't trap to EL2 for CP15 traps */ diff --git a/sys/arm64/arm64/machdep.c b/sys/arm64/arm64/machdep.c index 19fa7cd913a0..a076bd0a046a 100644 --- a/sys/arm64/arm64/machdep.c +++ b/sys/arm64/arm64/machdep.c @@ -78,6 +78,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -124,6 +125,7 @@ static struct trapframe proc0_tf; int early_boot = 1; int cold = 1; static int boot_el; +static uint64_t hcr_el2; struct kva_md_info kmi; @@ -191,7 +193,11 @@ bool has_hyp(void) { - return (boot_el == 2); + /* + * XXX The E2H check is wrong, but it's close enough for now. Needs to + * be re-evaluated once we're running regularly in EL2. + */ + return (boot_el == 2 && (hcr_el2 & HCR_E2H) == 0); } static void @@ -865,6 +871,7 @@ initarm(struct arm64_bootparams *abp) TSRAW(&thread0, TS_ENTER, __func__, NULL); boot_el = abp->boot_el; + hcr_el2 = abp->hcr_el2; /* Parse loader or FDT boot parametes. Determine last used address. */ lastaddr = parse_boot_param(abp); diff --git a/sys/arm64/include/machdep.h b/sys/arm64/include/machdep.h index 112390bb27ef..69babfff8467 100644 --- a/sys/arm64/include/machdep.h +++ b/sys/arm64/include/machdep.h @@ -36,6 +36,7 @@ struct arm64_bootparams { uint64_t kern_delta; vm_offset_t kern_stack; vm_paddr_t kern_ttbr0; + uint64_t hcr_el2; int boot_el; /* EL the kernel booted from */ int pad; }; -- cgit v1.2.3