summaryrefslogtreecommitdiffstats
path: root/sys/powerpc/aim/copyinout.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/powerpc/aim/copyinout.c')
-rw-r--r--sys/powerpc/aim/copyinout.c35
1 files changed, 22 insertions, 13 deletions
diff --git a/sys/powerpc/aim/copyinout.c b/sys/powerpc/aim/copyinout.c
index ab2d1f32..15623ed 100644
--- a/sys/powerpc/aim/copyinout.c
+++ b/sys/powerpc/aim/copyinout.c
@@ -81,9 +81,7 @@ static __inline void
set_user_sr(pmap_t pm, const void *addr)
{
struct slb *slb;
- register_t esid, vsid, slb1, slb2;
-
- esid = USER_ADDR >> ADDR_SR_SHFT;
+ register_t slbv;
/* Try lockless look-up first */
slb = user_va_to_slb_entry(pm, (vm_offset_t)addr);
@@ -91,20 +89,24 @@ set_user_sr(pmap_t pm, const void *addr)
if (slb == NULL) {
/* If it isn't there, we need to pre-fault the VSID */
PMAP_LOCK(pm);
- vsid = va_to_vsid(pm, (vm_offset_t)addr);
+ slbv = va_to_vsid(pm, (vm_offset_t)addr) << SLBV_VSID_SHIFT;
PMAP_UNLOCK(pm);
} else {
- vsid = slb->slbv >> SLBV_VSID_SHIFT;
+ slbv = slb->slbv;
}
- slb1 = vsid << SLBV_VSID_SHIFT;
- slb2 = (esid << SLBE_ESID_SHIFT) | SLBE_VALID | USER_SR;
+ /* Mark segment no-execute */
+ slbv |= SLBV_N;
+
+ /* If we have already set this VSID, we can just return */
+ if (curthread->td_pcb->pcb_cpu.aim.usr_vsid == slbv)
+ return;
+ __asm __volatile ("isync; slbie %0; slbmte %1, %2; isync" ::
+ "r"(USER_ADDR), "r"(slbv), "r"(USER_SLB_SLBE));
curthread->td_pcb->pcb_cpu.aim.usr_segm =
(uintptr_t)addr >> ADDR_SR_SHFT;
- __asm __volatile ("slbie %0; slbmte %1, %2" :: "r"(esid << 28),
- "r"(slb1), "r"(slb2));
- isync();
+ curthread->td_pcb->pcb_cpu.aim.usr_vsid = slbv;
}
#else
static __inline void
@@ -114,9 +116,16 @@ set_user_sr(pmap_t pm, const void *addr)
vsid = va_to_vsid(pm, (vm_offset_t)addr);
- isync();
- __asm __volatile ("mtsr %0,%1" :: "n"(USER_SR), "r"(vsid));
- isync();
+ /* If we have already set this VSID, we can just return */
+ if (curthread->td_pcb->pcb_cpu.aim.usr_vsid == vsid)
+ return;
+
+ /* Mark segment no-execute */
+ vsid |= SR_N;
+
+ __asm __volatile("isync");
+ curthread->td_pcb->pcb_cpu.aim.usr_vsid = vsid;
+ __asm __volatile("mtsr %0,%1; isync" :: "n"(USER_SR), "r"(vsid));
}
#endif
OpenPOWER on IntegriCloud