diff options
author | Alan Cox <alc@FreeBSD.org> | 2019-09-21 19:51:57 +0000 |
---|---|---|
committer | Alan Cox <alc@FreeBSD.org> | 2019-09-21 19:51:57 +0000 |
commit | 2b28ec59ac8d477fab864f6610f794038e72046c (patch) | |
tree | 5ecc211560dde71dfecc3841121e6b3b7191ef2c /sys | |
parent | cbba2cb367c2e8ebbf99b9e74a96fa1501f70093 (diff) | |
download | src-2b28ec59ac8d477fab864f6610f794038e72046c.tar.gz src-2b28ec59ac8d477fab864f6610f794038e72046c.zip |
In case a translation fault on the kernel address space occurs from
within a critical section, we must perform a lock-free check on the
faulting address.
Reported by: andrew
Reviewed by: andrew, markj
X-MFC with: r350579
Differential Revision: https://reviews.freebsd.org/D21685
Notes
Notes:
svn path=/head/; revision=352584
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arm64/arm64/pmap.c | 40 |
1 files changed, 25 insertions, 15 deletions
diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c index 919537e86b84..d9753073e17b 100644 --- a/sys/arm64/arm64/pmap.c +++ b/sys/arm64/arm64/pmap.c @@ -5810,23 +5810,33 @@ pmap_fault(pmap_t pmap, uint64_t esr, uint64_t far) case ISS_DATA_DFSC_TF_L1: case ISS_DATA_DFSC_TF_L2: case ISS_DATA_DFSC_TF_L3: - PMAP_LOCK(pmap); - /* Ask the MMU to check the address */ - intr = intr_disable(); - if (pmap == kernel_pmap) - par = arm64_address_translate_s1e1r(far); - else - par = arm64_address_translate_s1e0r(far); - intr_restore(intr); - PMAP_UNLOCK(pmap); - /* - * If the translation was successful the address was invalid - * due to a break-before-make sequence. We can unlock and - * return success to the trap handler. + * Retry the translation. A break-before-make sequence can + * produce a transient fault. */ - if (PAR_SUCCESS(par)) - rv = KERN_SUCCESS; + if (pmap == kernel_pmap) { + /* + * The translation fault may have occurred within a + * critical section. Therefore, we must check the + * address without acquiring the kernel pmap's lock. + */ + if (pmap_kextract(far) != 0) + rv = KERN_SUCCESS; + } else { + PMAP_LOCK(pmap); + /* Ask the MMU to check the address. */ + intr = intr_disable(); + par = arm64_address_translate_s1e0r(far); + intr_restore(intr); + PMAP_UNLOCK(pmap); + + /* + * If the translation was successful, then we can + * return success to the trap handler. + */ + if (PAR_SUCCESS(par)) + rv = KERN_SUCCESS; + } break; } |