svn commit: r328530 - in head/sys/powerpc: aim booke include powerpc
Nathan Whitehorn
nwhitehorn at FreeBSD.org
Mon Jan 29 04:33:42 UTC 2018
Author: nwhitehorn
Date: Mon Jan 29 04:33:41 2018
New Revision: 328530
URL: https://svnweb.freebsd.org/changeset/base/328530
Log:
Remove hard-coded trap-handling logic involving the segmented memory model
used with hashed page tables on AIM and place it into a new, modular pmap
function called pmap_decode_kernel_ptr(). This function is the inverse
of pmap_map_user_ptr(). With POWER9 radix tables, which mapping to use
becomes more complex than just AIM/BOOKE and it is best to have it in
the same place as pmap_map_user_ptr().
Reviewed by: jhibbits
Modified:
head/sys/powerpc/aim/mmu_oea.c
head/sys/powerpc/aim/mmu_oea64.c
head/sys/powerpc/booke/pmap.c
head/sys/powerpc/include/pmap.h
head/sys/powerpc/powerpc/mmu_if.m
head/sys/powerpc/powerpc/pmap_dispatch.c
head/sys/powerpc/powerpc/trap.c
Modified: head/sys/powerpc/aim/mmu_oea.c
==============================================================================
--- head/sys/powerpc/aim/mmu_oea.c Mon Jan 29 04:04:52 2018 (r328529)
+++ head/sys/powerpc/aim/mmu_oea.c Mon Jan 29 04:33:41 2018 (r328530)
@@ -322,6 +322,8 @@ vm_offset_t moea_quick_enter_page(mmu_t mmu, vm_page_t
void moea_quick_remove_page(mmu_t mmu, vm_offset_t addr);
static int moea_map_user_ptr(mmu_t mmu, pmap_t pm,
volatile const void *uaddr, void **kaddr, size_t ulen, size_t *klen);
+static int moea_decode_kernel_ptr(mmu_t mmu, vm_offset_t addr,
+ int *is_user, vm_offset_t *decoded_addr);
static mmu_method_t moea_methods[] = {
@@ -374,6 +376,7 @@ static mmu_method_t moea_methods[] = {
MMUMETHOD(mmu_scan_init, moea_scan_init),
MMUMETHOD(mmu_dumpsys_map, moea_dumpsys_map),
MMUMETHOD(mmu_map_user_ptr, moea_map_user_ptr),
+ MMUMETHOD(mmu_decode_kernel_ptr, moea_decode_kernel_ptr),
{ 0, 0 }
};
@@ -1583,6 +1586,31 @@ moea_map_user_ptr(mmu_t mmu, pmap_t pm, volatile const
(uintptr_t)uaddr >> ADDR_SR_SHFT;
curthread->td_pcb->pcb_cpu.aim.usr_vsid = vsid;
__asm __volatile("mtsr %0,%1; isync" :: "n"(USER_SR), "r"(vsid));
+
+ return (0);
+}
+
+/*
+ * Figure out where a given kernel pointer (usually in a fault) points
+ * to from the VM's perspective, potentially remapping into userland's
+ * address space.
+ */
+static int
+moea_decode_kernel_ptr(mmu_t mmu, vm_offset_t addr, int *is_user,
+ vm_offset_t *decoded_addr)
+{
+ vm_offset_t user_sr;
+
+ if ((addr >> ADDR_SR_SHFT) == (USER_ADDR >> ADDR_SR_SHFT)) {
+ user_sr = curthread->td_pcb->pcb_cpu.aim.usr_segm;
+ addr &= ADDR_PIDX | ADDR_POFF;
+ addr |= user_sr << ADDR_SR_SHFT;
+ *decoded_addr = addr;
+ *is_user = 1;
+ } else {
+ *decoded_addr = addr;
+ *is_user = 0;
+ }
return (0);
}
Modified: head/sys/powerpc/aim/mmu_oea64.c
==============================================================================
--- head/sys/powerpc/aim/mmu_oea64.c Mon Jan 29 04:04:52 2018 (r328529)
+++ head/sys/powerpc/aim/mmu_oea64.c Mon Jan 29 04:33:41 2018 (r328530)
@@ -288,6 +288,8 @@ vm_offset_t moea64_quick_enter_page(mmu_t mmu, vm_page
void moea64_quick_remove_page(mmu_t mmu, vm_offset_t addr);
static int moea64_map_user_ptr(mmu_t mmu, pmap_t pm,
volatile const void *uaddr, void **kaddr, size_t ulen, size_t *klen);
+static int moea64_decode_kernel_ptr(mmu_t mmu, vm_offset_t addr,
+ int *is_user, vm_offset_t *decoded_addr);
static mmu_method_t moea64_methods[] = {
@@ -339,6 +341,7 @@ static mmu_method_t moea64_methods[] = {
MMUMETHOD(mmu_scan_init, moea64_scan_init),
MMUMETHOD(mmu_dumpsys_map, moea64_dumpsys_map),
MMUMETHOD(mmu_map_user_ptr, moea64_map_user_ptr),
+ MMUMETHOD(mmu_decode_kernel_ptr, moea64_decode_kernel_ptr),
{ 0, 0 }
};
@@ -1905,6 +1908,31 @@ moea64_map_user_ptr(mmu_t mmu, pmap_t pm, volatile con
#else
__asm __volatile("mtsr %0,%1; isync" :: "n"(USER_SR), "r"(slbv));
#endif
+
+ return (0);
+}
+
+/*
+ * Figure out where a given kernel pointer (usually in a fault) points
+ * to from the VM's perspective, potentially remapping into userland's
+ * address space.
+ */
+static int
+moea64_decode_kernel_ptr(mmu_t mmu, vm_offset_t addr, int *is_user,
+ vm_offset_t *decoded_addr)
+{
+ vm_offset_t user_sr;
+
+ if ((addr >> ADDR_SR_SHFT) == (USER_ADDR >> ADDR_SR_SHFT)) {
+ user_sr = curthread->td_pcb->pcb_cpu.aim.usr_segm;
+ addr &= ADDR_PIDX | ADDR_POFF;
+ addr |= user_sr << ADDR_SR_SHFT;
+ *decoded_addr = addr;
+ *is_user = 1;
+ } else {
+ *decoded_addr = addr;
+ *is_user = 0;
+ }
return (0);
}
Modified: head/sys/powerpc/booke/pmap.c
==============================================================================
--- head/sys/powerpc/booke/pmap.c Mon Jan 29 04:04:52 2018 (r328529)
+++ head/sys/powerpc/booke/pmap.c Mon Jan 29 04:33:41 2018 (r328530)
@@ -382,6 +382,8 @@ static int mmu_booke_change_attr(mmu_t mmu, vm_offset
vm_size_t sz, vm_memattr_t mode);
static int mmu_booke_map_user_ptr(mmu_t mmu, pmap_t pm,
volatile const void *uaddr, void **kaddr, size_t ulen, size_t *klen);
+static int mmu_booke_decode_kernel_ptr(mmu_t mmu, vm_offset_t addr,
+ int *is_user, vm_offset_t *decoded_addr);
static mmu_method_t mmu_booke_methods[] = {
@@ -436,6 +438,7 @@ static mmu_method_t mmu_booke_methods[] = {
MMUMETHOD(mmu_unmapdev, mmu_booke_unmapdev),
MMUMETHOD(mmu_change_attr, mmu_booke_change_attr),
MMUMETHOD(mmu_map_user_ptr, mmu_booke_map_user_ptr),
+ MMUMETHOD(mmu_decode_kernel_ptr, mmu_booke_decode_kernel_ptr),
/* dumpsys() support */
MMUMETHOD(mmu_dumpsys_map, mmu_booke_dumpsys_map),
@@ -2288,6 +2291,25 @@ mmu_booke_map_user_ptr(mmu_t mmu, pmap_t pm, volatile
if (klen)
*klen = ulen;
+ return (0);
+}
+
+/*
+ * Figure out where a given kernel pointer (usually in a fault) points
+ * to from the VM's perspective, potentially remapping into userland's
+ * address space.
+ */
+static int
+mmu_booke_decode_kernel_ptr(mmu_t mmu, vm_offset_t addr, int *is_user,
+ vm_offset_t *decoded_addr)
+{
+
+ if (addr < VM_MAXUSER_ADDRESS)
+ *is_user = 1;
+ else
+ *is_user = 0;
+
+ *decoded_addr = addr;
return (0);
}
Modified: head/sys/powerpc/include/pmap.h
==============================================================================
--- head/sys/powerpc/include/pmap.h Mon Jan 29 04:04:52 2018 (r328529)
+++ head/sys/powerpc/include/pmap.h Mon Jan 29 04:33:41 2018 (r328530)
@@ -262,6 +262,8 @@ void pmap_page_set_memattr(vm_page_t, vm_memattr_t);
int pmap_change_attr(vm_offset_t, vm_size_t, vm_memattr_t);
int pmap_map_user_ptr(pmap_t pm, volatile const void *uaddr,
void **kaddr, size_t ulen, size_t *klen);
+int pmap_decode_kernel_ptr(vm_offset_t addr, int *is_user,
+ vm_offset_t *decoded_addr);
void pmap_deactivate(struct thread *);
vm_paddr_t pmap_kextract(vm_offset_t);
int pmap_dev_direct_mapped(vm_paddr_t, vm_size_t);
Modified: head/sys/powerpc/powerpc/mmu_if.m
==============================================================================
--- head/sys/powerpc/powerpc/mmu_if.m Mon Jan 29 04:04:52 2018 (r328529)
+++ head/sys/powerpc/powerpc/mmu_if.m Mon Jan 29 04:33:41 2018 (r328530)
@@ -840,6 +840,21 @@ METHOD int map_user_ptr {
};
/**
+ * @brief Decode a kernel pointer, as visible to the current thread,
+ * by setting whether it corresponds to a user or kernel address and
+ * the address in the respective memory maps to which the address as
+ * seen in the kernel corresponds. This is essentially the inverse of
+ * MMU_MAP_USER_PTR() above and is used in kernel-space fault handling.
+ * Returns 0 on success or EFAULT if the address could not be mapped.
+ */
+METHOD int decode_kernel_ptr {
+ mmu_t _mmu;
+ vm_offset_t addr;
+ int *is_user;
+ vm_offset_t *decoded_addr;
+};
+
+/**
* @brief Reverse-map a kernel virtual address
*
* @param _va kernel virtual address to reverse-map
@@ -998,3 +1013,4 @@ METHOD int change_attr {
vm_size_t _sz;
vm_memattr_t _mode;
} DEFAULT mmu_null_change_attr;
+
Modified: head/sys/powerpc/powerpc/pmap_dispatch.c
==============================================================================
--- head/sys/powerpc/powerpc/pmap_dispatch.c Mon Jan 29 04:04:52 2018 (r328529)
+++ head/sys/powerpc/powerpc/pmap_dispatch.c Mon Jan 29 04:33:41 2018 (r328530)
@@ -520,6 +520,14 @@ pmap_map_user_ptr(pmap_t pm, volatile const void *uadd
return (MMU_MAP_USER_PTR(mmu_obj, pm, uaddr, kaddr, ulen, klen));
}
+int
+pmap_decode_kernel_ptr(vm_offset_t addr, int *is_user, vm_offset_t *decoded)
+{
+
+ CTR2(KTR_PMAP, "%s(%#jx)", __func__, (uintmax_t)addr);
+ return (MMU_DECODE_KERNEL_PTR(mmu_obj, addr, is_user, decoded));
+}
+
boolean_t
pmap_dev_direct_mapped(vm_paddr_t pa, vm_size_t size)
{
Modified: head/sys/powerpc/powerpc/trap.c
==============================================================================
--- head/sys/powerpc/powerpc/trap.c Mon Jan 29 04:04:52 2018 (r328529)
+++ head/sys/powerpc/powerpc/trap.c Mon Jan 29 04:33:41 2018 (r328530)
@@ -393,7 +393,8 @@ trap(struct trapframe *frame)
break;
#if defined(__powerpc64__) && defined(AIM)
case EXC_DSE:
- if ((frame->dar & SEGMENT_MASK) == USER_ADDR) {
+ if (td->td_pcb->pcb_cpu.aim.usr_vsid != 0 &&
+ (frame->dar & SEGMENT_MASK) == USER_ADDR) {
__asm __volatile ("slbmte %0, %1" ::
"r"(td->td_pcb->pcb_cpu.aim.usr_vsid),
"r"(USER_SLB_SLBE));
@@ -731,10 +732,7 @@ trap_pfault(struct trapframe *frame, int user)
struct proc *p;
vm_map_t map;
vm_prot_t ftype;
- int rv;
-#ifdef AIM
- register_t user_sr;
-#endif
+ int rv, is_user;
td = curthread;
p = td->td_proc;
@@ -759,21 +757,14 @@ trap_pfault(struct trapframe *frame, int user)
KASSERT(p->p_vmspace != NULL, ("trap_pfault: vmspace NULL"));
map = &p->p_vmspace->vm_map;
} else {
-#ifdef BOOKE
- if (eva < VM_MAXUSER_ADDRESS) {
-#else
- if ((eva >> ADDR_SR_SHFT) == (USER_ADDR >> ADDR_SR_SHFT)) {
-#endif
- map = &p->p_vmspace->vm_map;
+ rv = pmap_decode_kernel_ptr(eva, &is_user, &eva);
+ if (rv != 0)
+ return (SIGSEGV);
-#ifdef AIM
- user_sr = td->td_pcb->pcb_cpu.aim.usr_segm;
- eva &= ADDR_PIDX | ADDR_POFF;
- eva |= user_sr << ADDR_SR_SHFT;
-#endif
- } else {
+ if (is_user)
+ map = &p->p_vmspace->vm_map;
+ else
map = kernel_map;
- }
}
va = trunc_page(eva);
More information about the svn-src-all
mailing list