[PATCH] drvlib: Explain why we need cobalt_machine.prefault

Richard Weinberger richard at nod.at
Mon Sep 28 14:33:59 CEST 2020


It is not obvious why cobalt_machine.prefault is needed
and why only for ARM.
One would expect that mlockall() would do it too.

Signed-off-by: Richard Weinberger <richard at nod.at>
---
Note: I think we can make mach_arm_prefault() a no-op on arm64
if cpu_has_hw_af() returns true.
But I need to test it first. B-)
---
 kernel/cobalt/arch/arm/machine.c   |  5 +++++
 kernel/cobalt/arch/arm64/machine.c |  5 +++++
 kernel/cobalt/rtdm/drvlib.c        | 13 +++++++++++++
 3 files changed, 23 insertions(+)

diff --git a/kernel/cobalt/arch/arm/machine.c b/kernel/cobalt/arch/arm/machine.c
index 721567182f49..be56b2b84e2e 100644
--- a/kernel/cobalt/arch/arm/machine.c
+++ b/kernel/cobalt/arch/arm/machine.c
@@ -35,6 +35,11 @@ static void mach_arm_prefault(struct vm_area_struct *vma)
 		flags = (vma->vm_flags & VM_MAYWRITE) ? FAULT_FLAG_WRITE : 0;
 		for (addr = vma->vm_start;
 		     addr != vma->vm_end; addr += PAGE_SIZE)
+			/*
+			 * Explicitly mark pages dirty such that future writes
+			 * won't trigger a page fault due to PTE dirty bit
+			 * emulation.
+			 */
 #if LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0)
 			handle_mm_fault(vma->vm_mm, vma, addr, flags);
 #else
diff --git a/kernel/cobalt/arch/arm64/machine.c b/kernel/cobalt/arch/arm64/machine.c
index cb2867492360..f820e63624ec 100644
--- a/kernel/cobalt/arch/arm64/machine.c
+++ b/kernel/cobalt/arch/arm64/machine.c
@@ -35,6 +35,11 @@ static void mach_arm_prefault(struct vm_area_struct *vma)
 		flags = (vma->vm_flags & VM_MAYWRITE) ? FAULT_FLAG_WRITE : 0;
 		for (addr = vma->vm_start;
 		     addr != vma->vm_end; addr += PAGE_SIZE)
+			/*
+			 * Explicitly mark pages dirty such that future writes
+			 * won't trigger a page fault due to PTE dirty bit
+			 * emulation.
+			 */
 #if LINUX_VERSION_CODE < KERNEL_VERSION(4,8,0)
 			handle_mm_fault(vma->vm_mm, vma, addr, flags);
 #else
diff --git a/kernel/cobalt/rtdm/drvlib.c b/kernel/cobalt/rtdm/drvlib.c
index 5778ad559ced..674292d89b71 100644
--- a/kernel/cobalt/rtdm/drvlib.c
+++ b/kernel/cobalt/rtdm/drvlib.c
@@ -1695,6 +1695,19 @@ static int mmap_kmem_helper(struct vm_area_struct *vma, void *va)
 		}
 	}
 
+	/*
+	 * Extra prefaulting is needed for two reasons on ARMv8 (and older):
+	 *
+	 * 1. ARM does not have a dirty PTE flag in hardware, upon first write
+	 * a page fault exception happens and Linux marks the page as dirty.
+	 * On x86 this is not the case and therefore the prefault handler can
+	 * be NULL.
+	 *
+	 * 2. __mm_populate() (via mlock/all()) does not dirty MAP_SHARED
+	 * memory mappings, this would trigger a lot of IO due to write back.
+	 * As of today, __mm_populate() cannot distinguish between MAP_SHARED
+	 * with and without possible write back.
+	 */
 	if (cobalt_machine.prefault)
 		cobalt_machine.prefault(vma);
 #endif
-- 
2.26.2




More information about the Xenomai mailing list