aboutsummaryrefslogtreecommitdiff
path: root/sys/arm64
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arm64')
-rw-r--r--sys/arm64/apple/apple_pinctrl.c3
-rw-r--r--sys/arm64/arm64/efirt_machdep.c19
-rw-r--r--sys/arm64/arm64/elf32_machdep.c2
-rw-r--r--sys/arm64/arm64/elf_machdep.c17
-rw-r--r--sys/arm64/arm64/exec_machdep.c31
-rw-r--r--sys/arm64/arm64/genassym.c1
-rw-r--r--sys/arm64/arm64/pmap.c19
-rw-r--r--sys/arm64/arm64/ptrauth.c4
-rw-r--r--sys/arm64/arm64/swtch.S12
-rw-r--r--sys/arm64/arm64/vm_machdep.c3
-rw-r--r--sys/arm64/conf/std.dev1
-rw-r--r--sys/arm64/include/cpu.h3
-rw-r--r--sys/arm64/include/elf.h3
-rw-r--r--sys/arm64/include/proc.h7
-rw-r--r--sys/arm64/include/vmm.h1
-rw-r--r--sys/arm64/include/vmparam.h3
-rw-r--r--sys/arm64/rockchip/rk_gpio.c3
-rw-r--r--sys/arm64/rockchip/rk_grf_gpio.c3
-rw-r--r--sys/arm64/vmm/vmm_arm64.c2
19 files changed, 124 insertions, 13 deletions
diff --git a/sys/arm64/apple/apple_pinctrl.c b/sys/arm64/apple/apple_pinctrl.c
index ebaaccea1d99..c28b1c62d78c 100644
--- a/sys/arm64/apple/apple_pinctrl.c
+++ b/sys/arm64/apple/apple_pinctrl.c
@@ -171,12 +171,13 @@ apple_pinctrl_attach(device_t dev)
OF_xref_from_node(ofw_bus_get_node(dev)));
}
- sc->sc_busdev = gpiobus_attach_bus(dev);
+ sc->sc_busdev = gpiobus_add_bus(dev);
if (sc->sc_busdev == NULL) {
device_printf(dev, "failed to attach gpiobus\n");
goto error;
}
+ bus_attach_children(dev);
return (0);
error:
mtx_destroy(&sc->sc_mtx);
diff --git a/sys/arm64/arm64/efirt_machdep.c b/sys/arm64/arm64/efirt_machdep.c
index 0f46e44f5d6a..0301eb91c9ef 100644
--- a/sys/arm64/arm64/efirt_machdep.c
+++ b/sys/arm64/arm64/efirt_machdep.c
@@ -241,6 +241,7 @@ fail:
int
efi_arch_enter(void)
{
+ uint64_t tcr;
CRITICAL_ASSERT(curthread);
curthread->td_md.md_efirt_dis_pf = vm_fault_disable_pagefaults();
@@ -249,7 +250,17 @@ efi_arch_enter(void)
* Temporarily switch to EFI's page table. However, we leave curpmap
* unchanged in order to prevent its ASID from being reclaimed before
* we switch back to its page table in efi_arch_leave().
+ *
+ * UEFI sdoesn't care about TBI, so enable it. It's more likely
+ * userspace will have TBI on as it's only disabled for backwards
+ * compatibility.
*/
+ tcr = READ_SPECIALREG(tcr_el1);
+ if ((tcr & MD_TCR_FIELDS) != TCR_TBI0) {
+ tcr &= ~MD_TCR_FIELDS;
+ tcr |= TCR_TBI0;
+ WRITE_SPECIALREG(tcr_el1, tcr);
+ }
set_ttbr0(efi_ttbr0);
if (PCPU_GET(bcast_tlbi_workaround) != 0)
invalidate_local_icache();
@@ -260,6 +271,7 @@ efi_arch_enter(void)
void
efi_arch_leave(void)
{
+ uint64_t proc_tcr, tcr;
/*
* Restore the pcpu pointer. Some UEFI implementations trash it and
@@ -271,6 +283,13 @@ efi_arch_leave(void)
__asm __volatile(
"mrs x18, tpidr_el1 \n"
);
+ proc_tcr = curthread->td_proc->p_md.md_tcr;
+ tcr = READ_SPECIALREG(tcr_el1);
+ if ((tcr & MD_TCR_FIELDS) != proc_tcr) {
+ tcr &= ~MD_TCR_FIELDS;
+ tcr |= proc_tcr;
+ WRITE_SPECIALREG(tcr_el1, tcr);
+ }
set_ttbr0(pmap_to_ttbr0(PCPU_GET(curpmap)));
if (PCPU_GET(bcast_tlbi_workaround) != 0)
invalidate_local_icache();
diff --git a/sys/arm64/arm64/elf32_machdep.c b/sys/arm64/arm64/elf32_machdep.c
index 7cd5327b9f1b..5c81c6cdce3d 100644
--- a/sys/arm64/arm64/elf32_machdep.c
+++ b/sys/arm64/arm64/elf32_machdep.c
@@ -195,7 +195,7 @@ freebsd32_fetch_syscall_args(struct thread *td)
register_t *ap;
struct syscall_args *sa;
int error, i, nap, narg;
- unsigned int args[4];
+ unsigned int args[6];
nap = 4;
p = td->td_proc;
diff --git a/sys/arm64/arm64/elf_machdep.c b/sys/arm64/arm64/elf_machdep.c
index 970dba0ca7d9..13af5c5065d6 100644
--- a/sys/arm64/arm64/elf_machdep.c
+++ b/sys/arm64/arm64/elf_machdep.c
@@ -65,7 +65,13 @@ u_long __read_frequently linux_elf_hwcap2;
u_long __read_frequently linux_elf_hwcap3;
u_long __read_frequently linux_elf_hwcap4;
-struct arm64_addr_mask elf64_addr_mask;
+struct arm64_addr_mask elf64_addr_mask = {
+ .code = TBI_ADDR_MASK,
+ .data = TBI_ADDR_MASK,
+};
+#ifdef COMPAT_FREEBSD14
+struct arm64_addr_mask elf64_addr_mask_14;
+#endif
static void arm64_exec_protect(struct image_params *, int);
@@ -136,7 +142,14 @@ get_arm64_addr_mask(struct regset *rs, struct thread *td, void *buf,
if (buf != NULL) {
KASSERT(*sizep == sizeof(elf64_addr_mask),
("%s: invalid size", __func__));
- memcpy(buf, &elf64_addr_mask, sizeof(elf64_addr_mask));
+#ifdef COMPAT_FREEBSD14
+ /* running an old binary use the old address mask */
+ if (td->td_proc->p_osrel < TBI_VERSION)
+ memcpy(buf, &elf64_addr_mask_14,
+ sizeof(elf64_addr_mask_14));
+ else
+#endif
+ memcpy(buf, &elf64_addr_mask, sizeof(elf64_addr_mask));
}
*sizep = sizeof(elf64_addr_mask);
diff --git a/sys/arm64/arm64/exec_machdep.c b/sys/arm64/arm64/exec_machdep.c
index 751329affd91..7c50dc93fdb4 100644
--- a/sys/arm64/arm64/exec_machdep.c
+++ b/sys/arm64/arm64/exec_machdep.c
@@ -51,6 +51,7 @@
#include <vm/vm_map.h>
#include <machine/armreg.h>
+#include <machine/elf.h>
#include <machine/kdb.h>
#include <machine/md_var.h>
#include <machine/pcb.h>
@@ -411,6 +412,7 @@ exec_setregs(struct thread *td, struct image_params *imgp, uintptr_t stack)
{
struct trapframe *tf = td->td_frame;
struct pcb *pcb = td->td_pcb;
+ uint64_t new_tcr, tcr;
memset(tf, 0, sizeof(struct trapframe));
@@ -433,6 +435,35 @@ exec_setregs(struct thread *td, struct image_params *imgp, uintptr_t stack)
*/
bzero(&pcb->pcb_dbg_regs, sizeof(pcb->pcb_dbg_regs));
+ /* If the process is new enough enable TBI */
+ if (td->td_proc->p_osrel >= TBI_VERSION)
+ new_tcr = TCR_TBI0;
+ else
+ new_tcr = 0;
+ td->td_proc->p_md.md_tcr = new_tcr;
+
+ /* TODO: should create a pmap function for this... */
+ tcr = READ_SPECIALREG(tcr_el1);
+ if ((tcr & MD_TCR_FIELDS) != new_tcr) {
+ uint64_t asid;
+
+ tcr &= ~MD_TCR_FIELDS;
+ tcr |= new_tcr;
+ WRITE_SPECIALREG(tcr_el1, tcr);
+ isb();
+
+ /*
+ * TCR_EL1.TBI0 is permitted to be cached in the TLB, so
+ * we need to perform a TLB invalidation.
+ */
+ asid = READ_SPECIALREG(ttbr0_el1) & TTBR_ASID_MASK;
+ __asm __volatile(
+ "tlbi aside1is, %0 \n"
+ "dsb ish \n"
+ "isb \n"
+ : : "r" (asid));
+ }
+
/* Generate new pointer authentication keys */
ptrauth_exec(td);
}
diff --git a/sys/arm64/arm64/genassym.c b/sys/arm64/arm64/genassym.c
index e3977798b046..22696796e69d 100644
--- a/sys/arm64/arm64/genassym.c
+++ b/sys/arm64/arm64/genassym.c
@@ -64,6 +64,7 @@ ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault));
ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags));
ASSYM(P_PID, offsetof(struct proc, p_pid));
+ASSYM(P_MD_TCR, offsetof(struct proc, p_md.md_tcr));
ASSYM(SF_UC, offsetof(struct sigframe, sf_uc));
diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c
index 07955866bd1c..ec89c4573799 100644
--- a/sys/arm64/arm64/pmap.c
+++ b/sys/arm64/arm64/pmap.c
@@ -469,7 +469,7 @@ static pv_entry_t pmap_pvh_remove(struct md_page *pvh, pmap_t pmap,
vm_offset_t va);
static void pmap_abort_ptp(pmap_t pmap, vm_offset_t va, vm_page_t mpte);
-static bool pmap_activate_int(pmap_t pmap);
+static bool pmap_activate_int(struct thread *td, pmap_t pmap);
static void pmap_alloc_asid(pmap_t pmap);
static int pmap_change_props_locked(vm_offset_t va, vm_size_t size,
vm_prot_t prot, int mode, bool skip_unmapped);
@@ -9113,7 +9113,7 @@ pmap_init_cnp(void *dummy __unused)
SYSINIT(pmap_init_cnp, SI_SUB_SMP, SI_ORDER_ANY, pmap_init_cnp, NULL);
static bool
-pmap_activate_int(pmap_t pmap)
+pmap_activate_int(struct thread *td, pmap_t pmap)
{
struct asid_set *set;
int epoch;
@@ -9152,6 +9152,15 @@ pmap_activate_int(pmap_t pmap)
pmap_alloc_asid(pmap);
if (pmap->pm_stage == PM_STAGE1) {
+ uint64_t new_tcr, tcr;
+
+ new_tcr = td->td_proc->p_md.md_tcr;
+ tcr = READ_SPECIALREG(tcr_el1);
+ if ((tcr & MD_TCR_FIELDS) != new_tcr) {
+ tcr &= ~MD_TCR_FIELDS;
+ tcr |= new_tcr;
+ WRITE_SPECIALREG(tcr_el1, tcr);
+ }
set_ttbr0(pmap_to_ttbr0(pmap));
if (PCPU_GET(bcast_tlbi_workaround) != 0)
invalidate_local_icache();
@@ -9165,7 +9174,7 @@ pmap_activate_vm(pmap_t pmap)
PMAP_ASSERT_STAGE2(pmap);
- (void)pmap_activate_int(pmap);
+ (void)pmap_activate_int(NULL, pmap);
}
void
@@ -9176,7 +9185,7 @@ pmap_activate(struct thread *td)
pmap = vmspace_pmap(td->td_proc->p_vmspace);
PMAP_ASSERT_STAGE1(pmap);
critical_enter();
- (void)pmap_activate_int(pmap);
+ (void)pmap_activate_int(td, pmap);
critical_exit();
}
@@ -9202,7 +9211,7 @@ pmap_switch(struct thread *new)
* to a user process.
*/
- if (pmap_activate_int(vmspace_pmap(new->td_proc->p_vmspace))) {
+ if (pmap_activate_int(new, vmspace_pmap(new->td_proc->p_vmspace))) {
/*
* Stop userspace from training the branch predictor against
* other processes. This will call into a CPU specific
diff --git a/sys/arm64/arm64/ptrauth.c b/sys/arm64/arm64/ptrauth.c
index 767b7e115479..dbe0c69b8d60 100644
--- a/sys/arm64/arm64/ptrauth.c
+++ b/sys/arm64/arm64/ptrauth.c
@@ -149,6 +149,10 @@ ptrauth_enable(const struct cpu_feat *feat __unused,
enable_ptrauth = true;
elf64_addr_mask.code |= PAC_ADDR_MASK;
elf64_addr_mask.data |= PAC_ADDR_MASK;
+#ifdef COMPAT_FREEBSD14
+ elf64_addr_mask_14.code |= PAC_ADDR_MASK_14;
+ elf64_addr_mask_14.data |= PAC_ADDR_MASK_14;
+#endif
}
diff --git a/sys/arm64/arm64/swtch.S b/sys/arm64/arm64/swtch.S
index 7b6010a5f51f..a461fded929c 100644
--- a/sys/arm64/arm64/swtch.S
+++ b/sys/arm64/arm64/swtch.S
@@ -37,6 +37,8 @@
#include <machine/asm.h>
#include <machine/armreg.h>
+#include <machine/proc.h>
+
.macro clear_step_flag pcbflags, tmp
tbz \pcbflags, #PCB_SINGLE_STEP_SHIFT, 999f
mrs \tmp, mdscr_el1
@@ -239,6 +241,16 @@ ENTRY(fork_trampoline)
msr daifset, #(DAIF_D | DAIF_INTR)
ldr x0, [x18, #PC_CURTHREAD]
+
+ /* Set the per-process tcr_el1 fields */
+ ldr x10, [x0, #TD_PROC]
+ ldr x10, [x10, #P_MD_TCR]
+ mrs x11, tcr_el1
+ and x11, x11, #(~MD_TCR_FIELDS)
+ orr x11, x11, x10
+ msr tcr_el1, x11
+ /* No isb as the eret below is the context-synchronising event */
+
bl ptrauth_enter_el0
/* Restore sp, lr, elr, and spsr */
diff --git a/sys/arm64/arm64/vm_machdep.c b/sys/arm64/arm64/vm_machdep.c
index 38a126ff602f..0134feb65b6a 100644
--- a/sys/arm64/arm64/vm_machdep.c
+++ b/sys/arm64/arm64/vm_machdep.c
@@ -120,6 +120,9 @@ cpu_fork(struct thread *td1, struct proc *p2, struct thread *td2, int flags)
td2->td_md.md_spinlock_count = 1;
td2->td_md.md_saved_daif = PSR_DAIF_DEFAULT;
+ /* Copy the TCR_EL1 value */
+ td2->td_proc->p_md.md_tcr = td1->td_proc->p_md.md_tcr;
+
#if defined(PERTHREAD_SSP)
/* Set the new canary */
arc4random_buf(&td2->td_md.md_canary, sizeof(td2->td_md.md_canary));
diff --git a/sys/arm64/conf/std.dev b/sys/arm64/conf/std.dev
index c5c364ffda04..719f272426dd 100644
--- a/sys/arm64/conf/std.dev
+++ b/sys/arm64/conf/std.dev
@@ -115,6 +115,7 @@ device mmcsd # mmc/sd flash cards
options HID_DEBUG # enable debug msgs
device hid # Generic HID support
device hidbus # Generic HID Bus
+options U2F_MAKE_UHID_ALIAS # install /dev/uhid alias for /dev/u2f/
# Firmware
device mmio_sram # Generic on-chip SRAM
diff --git a/sys/arm64/include/cpu.h b/sys/arm64/include/cpu.h
index 935e3754bf25..59cda36f275e 100644
--- a/sys/arm64/include/cpu.h
+++ b/sys/arm64/include/cpu.h
@@ -226,6 +226,9 @@ extern uint64_t __cpu_affinity[];
struct arm64_addr_mask;
extern struct arm64_addr_mask elf64_addr_mask;
+#ifdef COMPAT_FREEBSD14
+extern struct arm64_addr_mask elf64_addr_mask_14;
+#endif
typedef void (*cpu_reset_hook_t)(void);
extern cpu_reset_hook_t cpu_reset_hook;
diff --git a/sys/arm64/include/elf.h b/sys/arm64/include/elf.h
index d6328c143585..81ee7392f866 100644
--- a/sys/arm64/include/elf.h
+++ b/sys/arm64/include/elf.h
@@ -93,6 +93,9 @@ __ElfType(Auxinfo);
#define ET_DYN_LOAD_ADDR 0x100000
#endif
+/* First __FreeBSD_version that supports Top Byte Ignore (TBI) */
+#define TBI_VERSION 1500058
+
/* HWCAP */
#define HWCAP_FP (1 << 0)
#define HWCAP_ASIMD (1 << 1)
diff --git a/sys/arm64/include/proc.h b/sys/arm64/include/proc.h
index dc2fa2df654d..184743d4cc80 100644
--- a/sys/arm64/include/proc.h
+++ b/sys/arm64/include/proc.h
@@ -35,6 +35,7 @@
#ifndef _MACHINE_PROC_H_
#define _MACHINE_PROC_H_
+#ifndef LOCORE
struct ptrauth_key {
uint64_t pa_key_lo;
uint64_t pa_key_hi;
@@ -73,8 +74,12 @@ struct mdthread {
};
struct mdproc {
- long md_dummy;
+ uint64_t md_tcr; /* TCR_EL1 fields to update */
};
+#endif /* !LOCORE */
+
+/* Fields that can be set in md_tcr */
+#define MD_TCR_FIELDS TCR_TBI0
#define KINFO_PROC_SIZE 1088
#define KINFO_PROC32_SIZE 816
diff --git a/sys/arm64/include/vmm.h b/sys/arm64/include/vmm.h
index 1d783cdacb0d..73b5b4a09591 100644
--- a/sys/arm64/include/vmm.h
+++ b/sys/arm64/include/vmm.h
@@ -89,6 +89,7 @@ enum vm_reg_name {
VM_REG_GUEST_TTBR1_EL1,
VM_REG_GUEST_TCR_EL1,
VM_REG_GUEST_TCR2_EL1,
+ VM_REG_GUEST_MPIDR_EL1,
VM_REG_LAST
};
diff --git a/sys/arm64/include/vmparam.h b/sys/arm64/include/vmparam.h
index c30ca1b2bff4..781602306436 100644
--- a/sys/arm64/include/vmparam.h
+++ b/sys/arm64/include/vmparam.h
@@ -209,7 +209,8 @@
#define KMSAN_ORIG_MAX_ADDRESS (0xffff028000000000UL)
/* The address bits that hold a pointer authentication code */
-#define PAC_ADDR_MASK (0xff7f000000000000UL)
+#define PAC_ADDR_MASK (0x007f000000000000UL)
+#define PAC_ADDR_MASK_14 (0xff7f000000000000UL)
/* The top-byte ignore address bits */
#define TBI_ADDR_MASK 0xff00000000000000UL
diff --git a/sys/arm64/rockchip/rk_gpio.c b/sys/arm64/rockchip/rk_gpio.c
index 847bc7394dd0..61614f532634 100644
--- a/sys/arm64/rockchip/rk_gpio.c
+++ b/sys/arm64/rockchip/rk_gpio.c
@@ -371,12 +371,13 @@ rk_gpio_attach(device_t dev)
sc->swporta_ddr = rk_gpio_read_4(sc, RK_GPIO_SWPORTA_DDR);
RK_GPIO_UNLOCK(sc);
- sc->sc_busdev = gpiobus_attach_bus(dev);
+ sc->sc_busdev = gpiobus_add_bus(dev);
if (sc->sc_busdev == NULL) {
rk_gpio_detach(dev);
return (ENXIO);
}
+ bus_attach_children(dev);
return (0);
}
diff --git a/sys/arm64/rockchip/rk_grf_gpio.c b/sys/arm64/rockchip/rk_grf_gpio.c
index 6818bd85bb95..6ac419889614 100644
--- a/sys/arm64/rockchip/rk_grf_gpio.c
+++ b/sys/arm64/rockchip/rk_grf_gpio.c
@@ -181,11 +181,12 @@ rk_grf_gpio_attach(device_t dev)
return (ENXIO);
}
- sc->sc_busdev = gpiobus_attach_bus(dev);
+ sc->sc_busdev = gpiobus_add_bus(dev);
if (sc->sc_busdev == NULL) {
return (ENXIO);
}
+ bus_attach_children(dev);
return (0);
}
diff --git a/sys/arm64/vmm/vmm_arm64.c b/sys/arm64/vmm/vmm_arm64.c
index de2425aae0a1..e293c99a6646 100644
--- a/sys/arm64/vmm/vmm_arm64.c
+++ b/sys/arm64/vmm/vmm_arm64.c
@@ -1251,6 +1251,8 @@ hypctx_regptr(struct hypctx *hypctx, int reg)
return (&hypctx->tcr_el1);
case VM_REG_GUEST_TCR2_EL1:
return (&hypctx->tcr2_el1);
+ case VM_REG_GUEST_MPIDR_EL1:
+ return (&hypctx->vmpidr_el2);
default:
break;
}