summaryrefslogtreecommitdiff
path: root/sys/arch/arm64
diff options
context:
space:
mode:
authorPatrick Wildt <patrick@cvs.openbsd.org>2018-08-16 15:36:05 +0000
committerPatrick Wildt <patrick@cvs.openbsd.org>2018-08-16 15:36:05 +0000
commit577d00bcb7b5db048595c72cff4e24869992e377 (patch)
tree20d04ff804cd587c076e6c00108545e58b97836d /sys/arch/arm64
parent8369e261743b75d62d04a0c10d727ab536e9b593 (diff)
Make pmap_allocate_asid() mpsafe. Since between checking the ASID
table and setting the bits atomically another core can select the same ASID as we did it currently would not be safe to run it without the kernel lock. This replaces the atomic_setbits_int(9) call with atomic_cas_uint(9) where we can check that the table entry has not been changed since we evaluted it. Also modify pmap_free_asid() to use the same concept. ok kettenis@
Diffstat (limited to 'sys/arch/arm64')
-rw-r--r--sys/arch/arm64/arm64/pmap.c26
1 files changed, 19 insertions, 7 deletions
diff --git a/sys/arch/arm64/arm64/pmap.c b/sys/arch/arm64/arm64/pmap.c
index af2294bead1..df734710e98 100644
--- a/sys/arch/arm64/arm64/pmap.c
+++ b/sys/arch/arm64/arm64/pmap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.c,v 1.55 2018/08/15 20:18:31 kettenis Exp $ */
+/* $OpenBSD: pmap.c,v 1.56 2018/08/16 15:36:04 patrick Exp $ */
/*
* Copyright (c) 2008-2009,2014-2016 Dale Rahn <drahn@dalerahn.com>
*
@@ -2174,20 +2174,27 @@ uint32_t pmap_asid[NUM_ASID / 32];
void
pmap_allocate_asid(pmap_t pm)
{
+ uint32_t bits;
int asid, bit;
- do {
- asid = arc4random() & (NUM_ASID - 2);
- bit = (asid & (32 - 1));
- } while (asid == 0 || (pmap_asid[asid / 32] & (3U << bit)));
+ for (;;) {
+ do {
+ asid = arc4random() & (NUM_ASID - 2);
+ bit = (asid & (32 - 1));
+ bits = pmap_asid[asid / 32];
+ } while (asid == 0 || (bits & (3U << bit)));
- atomic_setbits_int(&pmap_asid[asid / 32], 3U << bit);
+ if (atomic_cas_uint(&pmap_asid[asid / 32], bits,
+ bits | (3U << bit)) == bits)
+ break;
+ }
pm->pm_asid = asid;
}
void
pmap_free_asid(pmap_t pm)
{
+ uint32_t bits;
int bit;
KASSERT(pm != curcpu()->ci_curpm);
@@ -2195,7 +2202,12 @@ pmap_free_asid(pmap_t pm)
cpu_tlb_flush_asid_all((uint64_t)(pm->pm_asid | ASID_USER) << 48);
bit = (pm->pm_asid & (32 - 1));
- atomic_clearbits_int(&pmap_asid[pm->pm_asid / 32], 3U << bit);
+ for (;;) {
+ bits = pmap_asid[pm->pm_asid / 32];
+ if (atomic_cas_uint(&pmap_asid[pm->pm_asid / 32], bits,
+ bits & ~(3U << bit)) == bits)
+ break;
+ }
}
void