aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorAlan Cox <alc@FreeBSD.org>2019-09-21 19:51:57 +0000
committerAlan Cox <alc@FreeBSD.org>2019-09-21 19:51:57 +0000
commit2b28ec59ac8d477fab864f6610f794038e72046c (patch)
tree5ecc211560dde71dfecc3841121e6b3b7191ef2c /sys
parentcbba2cb367c2e8ebbf99b9e74a96fa1501f70093 (diff)
downloadsrc-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.c40
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;
}