Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F143105765
D21922.id63074.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
15 KB
Referenced Files
None
Subscribers
None
D21922.id63074.diff
View Options
Index: arm64/arm64/cpufunc_asm.S
===================================================================
--- arm64/arm64/cpufunc_asm.S
+++ arm64/arm64/cpufunc_asm.S
@@ -93,14 +93,6 @@
* Generic functions to read/modify/write the internal coprocessor registers
*/
-ENTRY(arm64_setttb)
- dsb ish
- msr ttbr0_el1, x0
- dsb ish
- isb
- ret
-END(arm64_setttb)
-
ENTRY(arm64_tlb_flushID)
dsb ishst
#ifdef SMP
Index: arm64/arm64/efirt_machdep.c
===================================================================
--- arm64/arm64/efirt_machdep.c
+++ arm64/arm64/efirt_machdep.c
@@ -47,6 +47,7 @@
#include <sys/rwlock.h>
#include <sys/systm.h>
#include <sys/vmmeter.h>
+#include <sys/ktr.h>
#include <machine/metadata.h>
#include <machine/pcb.h>
@@ -62,9 +63,9 @@
#include <vm/vm_pager.h>
static vm_object_t obj_1t1_pt;
-static vm_page_t efi_l0_page;
+static vm_pindex_t efi_1t1_idx;
static pd_entry_t *efi_l0;
-static vm_pindex_t efi_1t1_idx;
+static uint64_t efi_ttbr0;
void
efi_destroy_1t1_map(void)
@@ -81,8 +82,9 @@
}
obj_1t1_pt = NULL;
+ efi_1t1_idx = 0;
efi_l0 = NULL;
- efi_l0_page = NULL;
+ efi_ttbr0 = 0;
}
static vm_page_t
@@ -164,6 +166,7 @@
struct efi_md *p;
pt_entry_t *l3, l3_attr;
vm_offset_t va;
+ vm_page_t efi_l0_page;
uint64_t idx;
int i, mode;
@@ -172,10 +175,11 @@
L0_ENTRIES * Ln_ENTRIES * Ln_ENTRIES * Ln_ENTRIES,
VM_PROT_ALL, 0, NULL);
VM_OBJECT_WLOCK(obj_1t1_pt);
- efi_1t1_idx = 0;
efi_l0_page = efi_1t1_page();
VM_OBJECT_WUNLOCK(obj_1t1_pt);
efi_l0 = (pd_entry_t *)PHYS_TO_DMAP(VM_PAGE_TO_PHYS(efi_l0_page));
+ efi_ttbr0 = ASID_TO_OPERAND(ASID_RESERVED_FOR_EFI) |
+ VM_PAGE_TO_PHYS(efi_l0_page);
for (i = 0, p = map; i < ndesc; i++, p = efi_next_descriptor(p,
descsz)) {
@@ -213,7 +217,7 @@
printf("MAP %lx mode %x pages %lu\n", p->md_phys, mode, p->md_pages);
l3_attr = ATTR_DEFAULT | ATTR_IDX(mode) | ATTR_AP(ATTR_AP_RW) |
- L3_PAGE;
+ ATTR_nG | L3_PAGE;
if (mode == VM_MEMATTR_DEVICE || p->md_attr & EFI_MD_ATTR_XP)
l3_attr |= ATTR_UXN | ATTR_PXN;
@@ -236,15 +240,10 @@
efi_arch_enter(void)
{
- __asm __volatile(
- "msr ttbr0_el1, %0 \n"
- "isb \n"
- "dsb ishst \n"
- "tlbi vmalle1is \n"
- "dsb ish \n"
- "isb \n"
- : : "r"(VM_PAGE_TO_PHYS(efi_l0_page)));
+ CTR1(KTR_SPARE5, "%s: xxx", __func__);
+ set_ttbr0(efi_ttbr0);
+
return (0);
}
@@ -264,14 +263,11 @@
"mrs x18, tpidr_el1 \n"
);
td = curthread;
- __asm __volatile(
- "msr ttbr0_el1, %0 \n"
- "isb \n"
- "dsb ishst \n"
- "tlbi vmalle1is \n"
- "dsb ish \n"
- "isb \n"
- : : "r"(td->td_proc->p_md.md_l0addr));
+ set_ttbr0(td->td_proc->p_md.md_ttbr0);
+
+ CTR3(KTR_SPARE5, "%s: pid=%d, ttbr0=%lx", __func__,
+ td->td_proc->p_pid,
+ td->td_proc->p_md.md_ttbr0);
}
int
Index: arm64/arm64/genassym.c
===================================================================
--- arm64/arm64/genassym.c
+++ arm64/arm64/genassym.c
@@ -35,7 +35,6 @@
#include <machine/frame.h>
#include <machine/pcb.h>
-#include <machine/vmparam.h>
ASSYM(TDF_ASTPENDING, TDF_ASTPENDING);
ASSYM(TDF_NEEDRESCHED, TDF_NEEDRESCHED);
@@ -54,9 +53,6 @@
ASSYM(PCB_ONFAULT, offsetof(struct pcb, pcb_onfault));
ASSYM(PCB_FLAGS, offsetof(struct pcb, pcb_flags));
-ASSYM(P_MD, offsetof(struct proc, p_md));
-ASSYM(MD_L0ADDR, offsetof(struct mdproc, md_l0addr));
-
ASSYM(SF_UC, offsetof(struct sigframe, sf_uc));
ASSYM(TD_PROC, offsetof(struct thread, td_proc));
Index: arm64/arm64/locore.S
===================================================================
--- arm64/arm64/locore.S
+++ arm64/arm64/locore.S
@@ -501,6 +501,9 @@
* x9 = PA start (trashed)
* x10 = Entry count
* x11, x12 and x13 are trashed
+ *
+ * XXX Currently, this function is only used to create mappings for the
+ * ttbr0 table, so we unconditionally set ATTR_nG.
*/
build_l1_block_pagetable:
/*
@@ -517,6 +520,7 @@
#ifdef SMP
orr x12, x12, ATTR_SH(ATTR_SH_IS)
#endif
+ orr x12, x12, #(ATTR_nG)
/* Only use the output address bits */
lsr x9, x9, #L1_SHIFT
@@ -597,11 +601,17 @@
msr mair_el1, x2
/*
- * Setup TCR according to PARange bits from ID_AA64MMFR0_EL1.
+ * Setup TCR according to the PARange and ASIDBits fields
+ * from ID_AA64MMFR0_EL1. More precisely, set TCR_EL1.AS
+ * to 1 only if the ASIDBits field equals 0b0010.
*/
ldr x2, tcr
mrs x3, id_aa64mmfr0_el1
bfi x2, x3, #32, #3
+ and x3, x3, #0xF0
+ cmp x3, #0x20
+ cset x3, eq
+ bfi x2, x3, #36, #1
msr tcr_el1, x2
/* Setup SCTLR */
@@ -622,7 +632,7 @@
MAIR_ATTR(MAIR_NORMAL_WB, 2) | \
MAIR_ATTR(MAIR_NORMAL_WT, 3)
tcr:
- .quad (TCR_TxSZ(64 - VIRT_BITS) | TCR_ASID_16 | TCR_TG1_4K | \
+ .quad (TCR_TxSZ(64 - VIRT_BITS) | TCR_TG1_4K | \
TCR_CACHE_ATTRS | TCR_SMP_ATTRS)
sctlr_set:
/* Bits to set */
Index: arm64/arm64/machdep.c
===================================================================
--- arm64/arm64/machdep.c
+++ arm64/arm64/machdep.c
@@ -753,7 +753,7 @@
pcpup->pc_curpcb = thread0.td_pcb;
/* Set the base address of translation table 0. */
- thread0.td_proc->p_md.md_l0addr = READ_SPECIALREG(ttbr0_el1);
+ thread0.td_proc->p_md.md_ttbr0 = READ_SPECIALREG(ttbr0_el1);
}
typedef struct {
Index: arm64/arm64/pmap.c
===================================================================
--- arm64/arm64/pmap.c
+++ arm64/arm64/pmap.c
@@ -276,6 +276,13 @@
static SYSCTL_NODE(_vm, OID_AUTO, pmap, CTLFLAG_RD, 0, "VM/pmap parameters");
+/* ASID allocator */
+static struct unrhdr asid_unr;
+static struct mtx asid_mtx;
+static int asid_bits;
+SYSCTL_INT(_vm_pmap, OID_AUTO, asid_bits, CTLFLAG_RD, &asid_bits, 0,
+ "The number of bits in an ASID");
+
static int superpages_enabled = 1;
SYSCTL_INT(_vm_pmap, OID_AUTO, superpages_enabled,
CTLFLAG_RDTUN | CTLFLAG_NOFETCH, &superpages_enabled, 0,
@@ -786,6 +793,10 @@
uint64_t kern_delta;
int i;
+ /* Verify that the ASID is set through TTBR0. */
+ KASSERT((READ_SPECIALREG(tcr_el1) & TCR_A1) == 0,
+ ("pmap_bootstrap: TCR_EL1.A1 != 0"));
+
kern_delta = KERNBASE - kernstart;
printf("pmap_bootstrap %lx %lx %lx\n", l1pt, kernstart, kernlen);
@@ -794,6 +805,7 @@
/* Set this early so we can use the pagetable walking functions */
kernel_pmap_store.pm_l0 = (pd_entry_t *)l0pt;
+ kernel_pmap->pm_asid = -1;
PMAP_LOCK_INIT(kernel_pmap);
/* Assume the address we were loaded to is a valid physical address */
@@ -908,6 +920,11 @@
int i, pv_npg;
/*
+ * Determine whether an ASID is 8 or 16 bits in size.
+ */
+ asid_bits = (READ_SPECIALREG(tcr_el1) & TCR_ASID_16) != 0 ? 16 : 8;
+
+ /*
* Are large page mappings enabled?
*/
TUNABLE_INT_FETCH("vm.pmap.superpages_enabled", &superpages_enabled);
@@ -918,6 +935,13 @@
}
/*
+ * Initialize the ASID allocator.
+ */
+ mtx_init(&asid_mtx, "asid", NULL, MTX_DEF);
+ init_unrhdr(&asid_unr, ASID_FIRST_AVAILABLE, (1 << asid_bits) - 1,
+ &asid_mtx);
+
+ /*
* Initialize the pv chunk list mutex.
*/
mtx_init(&pv_chunks_mutex, "pmap pv chunk list", NULL, MTX_DEF);
@@ -971,30 +995,42 @@
static __inline void
pmap_invalidate_page(pmap_t pmap, vm_offset_t va)
{
+ uint64_t r;
sched_pin();
- __asm __volatile(
- "dsb ishst \n"
- "tlbi vaae1is, %0 \n"
- "dsb ish \n"
- "isb \n"
- : : "r"(va >> PAGE_SHIFT));
+ dsb(ishst);
+ if (pmap == kernel_pmap) {
+ r = atop(va);
+ __asm __volatile("tlbi vaae1is, %0" : : "r" (r));
+ } else {
+ r = ASID_TO_OPERAND(pmap->pm_asid) | atop(va);
+ __asm __volatile("tlbi vae1is, %0" : : "r" (r));
+ }
+ dsb(ish);
+ isb();
sched_unpin();
}
static __inline void
pmap_invalidate_range_nopin(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
{
- vm_offset_t addr;
+ uint64_t end, r, start;
dsb(ishst);
- for (addr = sva; addr < eva; addr += PAGE_SIZE) {
- __asm __volatile(
- "tlbi vaae1is, %0" : : "r"(addr >> PAGE_SHIFT));
+ if (pmap == kernel_pmap) {
+ start = atop(sva);
+ end = atop(eva);
+ for (r = start; r < end; r++)
+ __asm __volatile("tlbi vaae1is, %0" : : "r" (r));
+ } else {
+ start = end = ASID_TO_OPERAND(pmap->pm_asid);
+ start |= atop(sva);
+ end |= atop(eva);
+ for (r = start; r < end; r++)
+ __asm __volatile("tlbi vae1is, %0" : : "r" (r));
}
- __asm __volatile(
- "dsb ish \n"
- "isb \n");
+ dsb(ish);
+ isb();
}
static __inline void
@@ -1009,13 +1045,18 @@
static __inline void
pmap_invalidate_all(pmap_t pmap)
{
+ uint64_t r;
sched_pin();
- __asm __volatile(
- "dsb ishst \n"
- "tlbi vmalle1is \n"
- "dsb ish \n"
- "isb \n");
+ dsb(ishst);
+ if (pmap == kernel_pmap) {
+ __asm __volatile("tlbi vmalle1is");
+ } else {
+ r = ASID_TO_OPERAND(pmap->pm_asid);
+ __asm __volatile("tlbi aside1is, %0" : : "r" (r));
+ }
+ dsb(ish);
+ isb();
sched_unpin();
}
@@ -1442,9 +1483,14 @@
pmap_pinit0(pmap_t pmap)
{
+ printf("pmap_kextract(kernel_pmap->pm_l0) = %lx\n",
+ pmap_kextract((vm_offset_t)kernel_pmap->pm_l0));
+ printf("ttbr0 = %lx\n", READ_SPECIALREG(ttbr0_el1));
+
PMAP_LOCK_INIT(pmap);
bzero(&pmap->pm_stats, sizeof(pmap->pm_stats));
- pmap->pm_l0 = kernel_pmap->pm_l0;
+ pmap->pm_l0 = (pd_entry_t *)PHYS_TO_DMAP(READ_SPECIALREG(ttbr0_el1));
+ pmap->pm_asid = ASID_RESERVED_FOR_PID_0;
pmap->pm_root.rt_root = 0;
}
@@ -1467,6 +1513,9 @@
if ((l0pt->flags & PG_ZERO) == 0)
pagezero(pmap->pm_l0);
+ if ((pmap->pm_asid = alloc_unr(&asid_unr)) == -1)
+ panic("alloc_unr: ASID allocation failed");
+
pmap->pm_root.rt_root = 0;
bzero(&pmap->pm_stats, sizeof(pmap->pm_stats));
@@ -1717,6 +1766,9 @@
KASSERT(vm_radix_is_empty(&pmap->pm_root),
("pmap_release: pmap has reserved page table page(s)"));
+ free_unr(&asid_unr, pmap->pm_asid);
+ pmap->pm_asid = -1;
+
m = PHYS_TO_VM_PAGE(DMAP_TO_PHYS((vm_offset_t)pmap->pm_l0));
vm_page_unwire_noq(m);
@@ -3194,6 +3246,8 @@
new_l3 |= ATTR_SW_WIRED;
if (va < VM_MAXUSER_ADDRESS)
new_l3 |= ATTR_AP(ATTR_AP_USER) | ATTR_PXN;
+ if (pmap != kernel_pmap)
+ new_l3 |= ATTR_nG;
if ((m->oflags & VPO_UNMANAGED) == 0) {
new_l3 |= ATTR_SW_MANAGED;
if ((prot & VM_PROT_WRITE) != 0) {
@@ -3456,6 +3510,8 @@
new_l2 |= ATTR_XN;
if (va < VM_MAXUSER_ADDRESS)
new_l2 |= ATTR_AP(ATTR_AP_USER) | ATTR_PXN;
+ if (pmap != kernel_pmap)
+ new_l2 |= ATTR_nG;
return (pmap_enter_l2(pmap, va, new_l2, PMAP_ENTER_NOSLEEP |
PMAP_ENTER_NOREPLACE | PMAP_ENTER_NORECLAIM, NULL, lockp) ==
KERN_SUCCESS);
@@ -3754,6 +3810,8 @@
l3_val |= ATTR_XN;
if (va < VM_MAXUSER_ADDRESS)
l3_val |= ATTR_AP(ATTR_AP_USER) | ATTR_PXN;
+ if (pmap != kernel_pmap)
+ l3_val |= ATTR_nG;
/*
* Now validate mapping with RO protection
@@ -5679,20 +5737,28 @@
return (val);
}
+uint64_t
+pmap_to_ttbr0(pmap_t pmap)
+{
+
+ return (ASID_TO_OPERAND(pmap->pm_asid) |
+ pmap_kextract((vm_offset_t)pmap->pm_l0));
+}
+
void
pmap_activate(struct thread *td)
{
- pmap_t pmap;
+ struct proc *p;
critical_enter();
- pmap = vmspace_pmap(td->td_proc->p_vmspace);
- td->td_proc->p_md.md_l0addr = vtophys(pmap->pm_l0);
- __asm __volatile(
- "msr ttbr0_el1, %0 \n"
- "isb \n"
- : : "r"(td->td_proc->p_md.md_l0addr));
- pmap_invalidate_all(pmap);
+ p = td->td_proc;
+ p->p_md.md_ttbr0 = pmap_to_ttbr0(vmspace_pmap(p->p_vmspace));
+ set_ttbr0(p->p_md.md_ttbr0);
critical_exit();
+
+ CTR3(KTR_SPARE5, "%s: pid=%d, ttbr0=%lx", __func__,
+ p->p_pid,
+ p->p_md.md_ttbr0);
}
struct pcb *
@@ -5714,18 +5780,12 @@
*/
if (old == NULL ||
- old->td_proc->p_md.md_l0addr != new->td_proc->p_md.md_l0addr) {
- __asm __volatile(
- /* Switch to the new pmap */
- "msr ttbr0_el1, %0 \n"
- "isb \n"
+ old->td_proc->p_md.md_ttbr0 != new->td_proc->p_md.md_ttbr0) {
+ set_ttbr0(new->td_proc->p_md.md_ttbr0);
- /* Invalidate the TLB */
- "dsb ishst \n"
- "tlbi vmalle1is \n"
- "dsb ish \n"
- "isb \n"
- : : "r"(new->td_proc->p_md.md_l0addr));
+ CTR3(KTR_SPARE5, "%s: pid=%d, ttbr0=%lx", __func__,
+ new->td_proc->p_pid,
+ new->td_proc->p_md.md_ttbr0);
/*
* Stop userspace from training the branch predictor against
Index: arm64/arm64/vm_machdep.c
===================================================================
--- arm64/arm64/vm_machdep.c
+++ arm64/arm64/vm_machdep.c
@@ -91,8 +91,8 @@
td2->td_pcb = pcb2;
bcopy(td1->td_pcb, pcb2, sizeof(*pcb2));
- td2->td_proc->p_md.md_l0addr =
- vtophys(vmspace_pmap(td2->td_proc->p_vmspace)->pm_l0);
+ td2->td_proc->p_md.md_ttbr0 =
+ pmap_to_ttbr0(vmspace_pmap(td2->td_proc->p_vmspace));
tf = (struct trapframe *)STACKALIGN((struct trapframe *)pcb2 - 1);
bcopy(td1->td_frame, tf, sizeof(*tf));
Index: arm64/include/armreg.h
===================================================================
--- arm64/include/armreg.h
+++ arm64/include/armreg.h
@@ -597,7 +597,7 @@
#define PSR_FLAGS 0xf0000000
/* TCR_EL1 - Translation Control Register */
-#define TCR_ASID_16 (1 << 36)
+#define TCR_ASID_16 (0x1UL << 36)
#define TCR_IPS_SHIFT 32
#define TCR_IPS_32BIT (0 << TCR_IPS_SHIFT)
@@ -618,6 +618,8 @@
#define TCR_ORGN1_WBWA (0x1UL << TCR_ORGN1_SHIFT)
#define TCR_IRGN1_SHIFT 24
#define TCR_IRGN1_WBWA (0x1UL << TCR_IRGN1_SHIFT)
+#define TCR_A1_SHIFT 22
+#define TCR_A1 (0x1UL << TCR_A1_SHIFT)
#define TCR_SH0_SHIFT 12
#define TCR_SH0_IS (0x3UL << TCR_SH0_SHIFT)
#define TCR_ORGN0_SHIFT 10
Index: arm64/include/cpufunc.h
===================================================================
--- arm64/include/cpufunc.h
+++ arm64/include/cpufunc.h
@@ -178,6 +178,17 @@
__asm __volatile("clrex" : : : "memory");
}
+static __inline void
+set_ttbr0(uint64_t ttbr0)
+{
+
+ __asm __volatile(
+ "msr ttbr0_el1, %0 \n"
+ "isb \n"
+ :
+ : "r" (ttbr0));
+}
+
extern int64_t dcache_line_size;
extern int64_t icache_line_size;
extern int64_t idcache_line_size;
@@ -185,7 +196,6 @@
#define cpu_nullop() arm64_nullop()
#define cpufunc_nullop() arm64_nullop()
-#define cpu_setttb(a) arm64_setttb(a)
#define cpu_tlb_flushID() arm64_tlb_flushID()
@@ -198,7 +208,6 @@
#define cpu_icache_sync_range_checked(a, s) arm64_icache_sync_range_checked((a), (s))
void arm64_nullop(void);
-void arm64_setttb(vm_offset_t);
void arm64_tlb_flushID(void);
void arm64_icache_sync_range(vm_offset_t, vm_size_t);
int arm64_icache_sync_range_checked(vm_offset_t, vm_size_t);
Index: arm64/include/pmap.h
===================================================================
--- arm64/include/pmap.h
+++ arm64/include/pmap.h
@@ -83,6 +83,7 @@
pd_entry_t *pm_l0;
TAILQ_HEAD(,pv_chunk) pm_pvchunk; /* list of mappings in pmap */
struct vm_radix pm_root; /* spare page table pages */
+ int pm_asid;
};
typedef struct pmap *pmap_t;
@@ -132,6 +133,15 @@
#define PMAP_TRYLOCK(pmap) mtx_trylock(&(pmap)->pm_mtx)
#define PMAP_UNLOCK(pmap) mtx_unlock(&(pmap)->pm_mtx)
+#define ASID_RESERVED_FOR_PID_0 0
+#define ASID_RESERVED_FOR_EFI 1
+#define ASID_FIRST_AVAILABLE (ASID_RESERVED_FOR_EFI + 1)
+#define ASID_TO_OPERAND_SHIFT 48
+#define ASID_TO_OPERAND(asid) ({ \
+ KASSERT((asid) != -1, ("invalid ASID")); \
+ (uint64_t)(asid) << ASID_TO_OPERAND_SHIFT; \
+})
+
extern vm_offset_t virtual_avail;
extern vm_offset_t virtual_end;
@@ -144,6 +154,7 @@
void pmap_bootstrap(vm_offset_t, vm_offset_t, vm_paddr_t, vm_size_t);
int pmap_change_attr(vm_offset_t va, vm_size_t size, int mode);
+uint64_t pmap_to_ttbr0(pmap_t pmap);
void pmap_kenter(vm_offset_t sva, vm_size_t size, vm_paddr_t pa, int mode);
void pmap_kenter_device(vm_offset_t, vm_size_t, vm_paddr_t);
vm_paddr_t pmap_kextract(vm_offset_t va);
Index: arm64/include/proc.h
===================================================================
--- arm64/include/proc.h
+++ arm64/include/proc.h
@@ -40,7 +40,7 @@
};
struct mdproc {
- vm_offset_t md_l0addr;
+ uint64_t md_ttbr0;
};
#define KINFO_PROC_SIZE 1088
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Jan 27, 1:17 AM (3 h, 24 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28047706
Default Alt Text
D21922.id63074.diff (15 KB)
Attached To
Mode
D21922: A patch for using ASIDs in the arm64 pmap
Attached
Detach File
Event Timeline
Log In to Comment