Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F106099610
D32026.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
5 KB
Referenced Files
None
Subscribers
None
D32026.diff
View Options
diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c
--- a/sys/arm64/arm64/pmap.c
+++ b/sys/arm64/arm64/pmap.c
@@ -382,7 +382,8 @@
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 void pmap_alloc_asid(pmap_t pmap);
-static int pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode);
+static int pmap_change_props_locked(vm_offset_t va, vm_size_t size,
+ vm_prot_t prot, int mode);
static pt_entry_t *pmap_demote_l1(pmap_t pmap, pt_entry_t *l1, vm_offset_t va);
static pt_entry_t *pmap_demote_l2_locked(pmap_t pmap, pt_entry_t *l2,
vm_offset_t va, struct rwlock **lockp);
@@ -5949,17 +5950,41 @@
int error;
PMAP_LOCK(kernel_pmap);
- error = pmap_change_attr_locked(va, size, mode);
+ error = pmap_change_props_locked(va, size, PROT_NONE, mode);
+ PMAP_UNLOCK(kernel_pmap);
+ return (error);
+}
+
+/*
+ * Changes the specified virtual address range's protections to those
+ * specified by "prot". Like pmap_change_attr(), protections for aliases
+ * in the direct map are updated as well. Protections on aliasing mappings may
+ * be a subset of the requested protections; for example, mappings in the direct
+ * map are never executable.
+ */
+int
+pmap_change_prot(vm_offset_t va, vm_size_t size, vm_prot_t prot)
+{
+ int error;
+
+ /* Only supported within the kernel map. */
+ if (va < VM_MIN_KERNEL_ADDRESS)
+ return (EINVAL);
+
+ PMAP_LOCK(kernel_pmap);
+ error = pmap_change_props_locked(va, size, prot, -1);
PMAP_UNLOCK(kernel_pmap);
return (error);
}
static int
-pmap_change_attr_locked(vm_offset_t va, vm_size_t size, int mode)
+pmap_change_props_locked(vm_offset_t va, vm_size_t size, vm_prot_t prot,
+ int mode)
{
vm_offset_t base, offset, tmpva;
pt_entry_t l3, *pte, *newpte;
- int lvl;
+ pt_entry_t bits, mask;
+ int lvl, rv;
PMAP_LOCK_ASSERT(kernel_pmap, MA_OWNED);
base = trunc_page(va);
@@ -5970,12 +5995,44 @@
!(base >= VM_MIN_KERNEL_ADDRESS && base < VM_MAX_KERNEL_ADDRESS))
return (EINVAL);
+ bits = 0;
+ mask = 0;
+ if (mode != -1) {
+ bits = ATTR_S1_IDX(mode);
+ mask = ATTR_S1_IDX_MASK;
+ if (mode == VM_MEMATTR_DEVICE) {
+ mask |= ATTR_S1_XN;
+ bits |= ATTR_S1_XN;
+ }
+ }
+ if (prot != VM_PROT_NONE) {
+ /* Don't mark the DMAP as executable. It never is on arm64. */
+ if (VIRT_IN_DMAP(base)) {
+ prot &= ~VM_PROT_EXECUTE;
+ /*
+ * XXX Mark the DMAP as writable for now. We rely
+ * on this in ddb & dtrace to insert breakpoint
+ * instructions.
+ */
+ prot |= VM_PROT_WRITE;
+ }
+
+ if ((prot & VM_PROT_WRITE) == 0) {
+ bits |= ATTR_S1_AP(ATTR_S1_AP_RO);
+ }
+ if ((prot & VM_PROT_EXECUTE) == 0) {
+ bits |= ATTR_S1_PXN;
+ }
+ bits |= ATTR_S1_UXN;
+ mask |= ATTR_S1_AP_MASK | ATTR_S1_XN;
+ }
+
for (tmpva = base; tmpva < base + size; ) {
pte = pmap_pte(kernel_pmap, tmpva, &lvl);
if (pte == NULL)
return (EINVAL);
- if ((pmap_load(pte) & ATTR_S1_IDX_MASK) == ATTR_S1_IDX(mode)) {
+ if ((pmap_load(pte) & mask) == bits) {
/*
* We already have the correct attribute,
* ignore this entry.
@@ -6016,14 +6073,23 @@
case 3:
/* Update the entry */
l3 = pmap_load(pte);
- l3 &= ~ATTR_S1_IDX_MASK;
- l3 |= ATTR_S1_IDX(mode);
- if (mode == VM_MEMATTR_DEVICE)
- l3 |= ATTR_S1_XN;
+ l3 &= ~mask;
+ l3 |= bits;
pmap_update_entry(kernel_pmap, pte, l3, tmpva,
PAGE_SIZE);
+ if (!VIRT_IN_DMAP(tmpva)) {
+ /*
+ * Keep the DMAP memory in sync.
+ */
+ rv = pmap_change_props_locked(
+ PHYS_TO_DMAP(l3 & ~ATTR_MASK),
+ L3_SIZE, prot, mode);
+ if (rv != 0)
+ return (rv);
+ }
+
/*
* If moving to a non-cacheable entry flush
* the cache.
@@ -6185,12 +6251,14 @@
/*
* If the page table page is missing and the mapping
* is for a kernel address, the mapping must belong to
- * the direct map. Page table pages are preallocated
- * for every other part of the kernel address space,
- * so the direct map region is the only part of the
+ * either the direct map or the early kernel memory.
+ * Page table pages are preallocated for every other
+ * part of the kernel address space, so the direct map
+ * region and early kernel memory are the only parts of the
* kernel address space that must be handled here.
*/
- KASSERT(!ADDR_IS_KERNEL(va) || VIRT_IN_DMAP(va),
+ KASSERT(!ADDR_IS_KERNEL(va) || VIRT_IN_DMAP(va) ||
+ (va >= VM_MIN_KERNEL_ADDRESS && va < kernel_vm_end),
("pmap_demote_l2: No saved mpte for va %#lx", va));
/*
diff --git a/sys/arm64/include/pmap.h b/sys/arm64/include/pmap.h
--- a/sys/arm64/include/pmap.h
+++ b/sys/arm64/include/pmap.h
@@ -167,6 +167,7 @@
void pmap_activate_vm(pmap_t);
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);
+int pmap_change_prot(vm_offset_t va, vm_size_t size, vm_prot_t prot);
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);
bool pmap_klookup(vm_offset_t va, vm_paddr_t *pa);
diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c
--- a/sys/kern/link_elf.c
+++ b/sys/kern/link_elf.c
@@ -769,7 +769,7 @@
static int
preload_protect(elf_file_t ef, vm_prot_t prot)
{
-#ifdef __amd64__
+#if defined(__aarch64__) || defined(__amd64__)
Elf_Ehdr *hdr;
Elf_Phdr *phdr, *phlimit;
vm_prot_t nprot;
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Dec 26, 9:42 AM (11 h, 13 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15603461
Default Alt Text
D32026.diff (5 KB)
Attached To
Mode
D32026: Add pmap_change_prot on arm64
Attached
Detach File
Event Timeline
Log In to Comment