summaryrefslogtreecommitdiffstats
path: root/sys/powerpc/aim/slb.c
diff options
context:
space:
mode:
authornwhitehorn <nwhitehorn@FreeBSD.org>2010-10-30 23:07:30 +0000
committernwhitehorn <nwhitehorn@FreeBSD.org>2010-10-30 23:07:30 +0000
commitecfb41d217524c5063edf0b482d8a603a030456e (patch)
tree0b009d2d4242dfd1e8103a4713058f59b3f62915 /sys/powerpc/aim/slb.c
parentcaa01e3c92e993d78c971129c5b8d000237337a4 (diff)
downloadFreeBSD-src-ecfb41d217524c5063edf0b482d8a603a030456e.zip
FreeBSD-src-ecfb41d217524c5063edf0b482d8a603a030456e.tar.gz
Restructure the way the copyin/copyout segment is stored to prevent a
concurrency bug. Since all SLB/SR entries were invalidated during an exception, a decrementer exception could cause the user segment to be invalidated during a copyin()/copyout() without a thread switch that would cause it to be restored from the PCB, potentially causing the operation to continue on invalid memory. This is now handled by explicit restoration of segment 12 from the PCB on 32-bit systems and a check in the Data Segment Exception handler on 64-bit. While here, cause copyin()/copyout() to check whether the requested user segment is already installed, saving some pipeline flushes, and fix the synchronization primitives around the mtsr and slbmte instructions to prevent accessing stale segments. MFC after: 2 weeks
Diffstat (limited to 'sys/powerpc/aim/slb.c')
-rw-r--r--sys/powerpc/aim/slb.c14
1 files changed, 7 insertions, 7 deletions
diff --git a/sys/powerpc/aim/slb.c b/sys/powerpc/aim/slb.c
index e7bdaf8..9d8828a 100644
--- a/sys/powerpc/aim/slb.c
+++ b/sys/powerpc/aim/slb.c
@@ -200,7 +200,7 @@ kernel_va_to_slbv(vm_offset_t va)
esid = (uintptr_t)va >> ADDR_SR_SHFT;
/* Set kernel VSID to deterministic value */
- slbv = va_to_vsid(kernel_pmap, va) << SLBV_VSID_SHIFT;
+ slbv = (KERNEL_VSID((uintptr_t)va >> ADDR_SR_SHFT)) << SLBV_VSID_SHIFT;
/* Figure out if this is a large-page mapping */
if (hw_direct_map && va < VM_MIN_KERNEL_ADDRESS) {
@@ -421,19 +421,19 @@ slb_insert_kernel(uint64_t slbe, uint64_t slbv)
slbcache = PCPU_GET(slb);
- /* Check for an unused slot, abusing the USER_SR slot as a full flag */
- if (slbcache[USER_SR].slbe == 0) {
- for (i = 0; i < USER_SR; i++) {
+ /* Check for an unused slot, abusing the user slot as a full flag */
+ if (slbcache[USER_SLB_SLOT].slbe == 0) {
+ for (i = 0; i < USER_SLB_SLOT; i++) {
if (!(slbcache[i].slbe & SLBE_VALID))
goto fillkernslb;
}
- if (i == USER_SR)
- slbcache[USER_SR].slbe = 1;
+ if (i == USER_SLB_SLOT)
+ slbcache[USER_SLB_SLOT].slbe = 1;
}
for (i = mftb() % 64, j = 0; j < 64; j++, i = (i+1) % 64) {
- if (i == USER_SR)
+ if (i == USER_SLB_SLOT)
continue;
if (SLB_SPILLABLE(slbcache[i].slbe))
OpenPOWER on IntegriCloud