diff options
| author | Andrew Turner <andrew@FreeBSD.org> | 2026-04-29 11:34:39 +0000 |
|---|---|---|
| committer | Andrew Turner <andrew@FreeBSD.org> | 2026-04-29 11:34:39 +0000 |
| commit | 01ff0fa77d33dde6b6f6a0ff83b0028f76243796 (patch) | |
| tree | 1dc1e7e4842557dd30c06ff872a99c4d6d654ad6 | |
| parent | 91bfba010bcda665cc24a76af631cc85fcb0c688 (diff) | |
arm64: Support some per-thread sctlr_el1 fields
This will be used to enable MTE from userspace.
Sponsored by: Arm Ltd
Differential Revision: https://reviews.freebsd.org/D55950
| -rw-r--r-- | sys/arm64/arm64/exec_machdep.c | 1 | ||||
| -rw-r--r-- | sys/arm64/arm64/pmap.c | 11 | ||||
| -rw-r--r-- | sys/arm64/arm64/vm_machdep.c | 4 | ||||
| -rw-r--r-- | sys/arm64/include/armreg.h | 1 | ||||
| -rw-r--r-- | sys/arm64/include/proc.h | 3 |
5 files changed, 19 insertions, 1 deletions
diff --git a/sys/arm64/arm64/exec_machdep.c b/sys/arm64/arm64/exec_machdep.c index 9f9b74e6a0e5..a2e1e42249b4 100644 --- a/sys/arm64/arm64/exec_machdep.c +++ b/sys/arm64/arm64/exec_machdep.c @@ -445,6 +445,7 @@ exec_setregs(struct thread *td, struct image_params *imgp, uintptr_t stack) else new_tcr = 0; td->td_proc->p_md.md_tcr = new_tcr; + td->td_md.md_sctlr = 0; /* TODO: should create a pmap function for this... */ tcr = READ_SPECIALREG(tcr_el1); diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c index 4ba2fb6f6678..595fba2da411 100644 --- a/sys/arm64/arm64/pmap.c +++ b/sys/arm64/arm64/pmap.c @@ -9325,6 +9325,7 @@ pmap_switch(struct thread *new) { pcpu_bp_harden bp_harden; struct pcb *pcb; + uint64_t sctlr; /* Store the new curthread */ PCPU_SET(curthread, new); @@ -9333,6 +9334,16 @@ pmap_switch(struct thread *new) pcb = new->td_pcb; PCPU_SET(curpcb, pcb); + if ((new->td_proc->p_flag & P_KPROC) == 0) { + sctlr = READ_SPECIALREG(sctlr_el1); + if ((sctlr & SCTLR_USER_MASK) != new->td_md.md_sctlr) { + sctlr &= ~SCTLR_USER_MASK; + sctlr |= new->td_md.md_sctlr; + WRITE_SPECIALREG(sctlr_el1, sctlr); + isb(); + } + } + /* * TODO: We may need to flush the cache here if switching * to a user process. diff --git a/sys/arm64/arm64/vm_machdep.c b/sys/arm64/arm64/vm_machdep.c index b46cb8793409..4cb87ca9856e 100644 --- a/sys/arm64/arm64/vm_machdep.c +++ b/sys/arm64/arm64/vm_machdep.c @@ -123,6 +123,8 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags) /* Copy the TCR_EL1 value */ td2->td_proc->p_md.md_tcr = td1->td_proc->p_md.md_tcr; + td2->td_md.md_sctlr = td1->td_md.md_sctlr; + #if defined(PERTHREAD_SSP) /* Set the new canary */ arc4random_buf(&td2->td_md.md_canary, sizeof(td2->td_md.md_canary)); @@ -192,6 +194,8 @@ cpu_copy_thread(struct thread *td, struct thread *td0) td->td_md.md_spinlock_count = 1; td->td_md.md_saved_daif = PSR_DAIF_DEFAULT; + td->td_md.md_sctlr = td0->td_md.md_sctlr; + #if defined(PERTHREAD_SSP) /* Set the new canary */ arc4random_buf(&td->td_md.md_canary, sizeof(td->td_md.md_canary)); diff --git a/sys/arm64/include/armreg.h b/sys/arm64/include/armreg.h index 6447f0064d33..4233a01d143c 100644 --- a/sys/arm64/include/armreg.h +++ b/sys/arm64/include/armreg.h @@ -2803,6 +2803,7 @@ SCTLR_SA | \ SCTLR_C | \ SCTLR_M) +#define SCTLR_USER_MASK (SCTLR_ATA0 | SCTLR_TCF0_MASK) /* SCTLR_EL12 */ #define SCTLR_EL12_REG MRS_REG_ALT_NAME(SCTLR_EL12) diff --git a/sys/arm64/include/proc.h b/sys/arm64/include/proc.h index b40990e89385..d5879a794269 100644 --- a/sys/arm64/include/proc.h +++ b/sys/arm64/include/proc.h @@ -70,7 +70,8 @@ struct mdthread { int md_efirt_dis_pf; int md_reserved0; - uint64_t md_reserved[2]; + uint64_t md_sctlr; + uint64_t md_reserved1; }; struct mdproc { |
