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 <[email protected]> --- 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
