Index: sys/compat/linuxkpi/common/include/linux/mm.h =================================================================== --- sys/compat/linuxkpi/common/include/linux/mm.h +++ sys/compat/linuxkpi/common/include/linux/mm.h @@ -82,6 +82,9 @@ #define VM_FAULT_RETRY (1 << 9) #define VM_FAULT_FALLBACK (1 << 10) +#define VM_FAULT_ERROR (VM_FAULT_OOM | VM_FAULT_SIGBUS | VM_FAULT_SIGSEGV | \ + VM_FAULT_HWPOISON |VM_FAULT_HWPOISON_LARGE | VM_FAULT_FALLBACK) + #define FAULT_FLAG_WRITE (1 << 0) #define FAULT_FLAG_MKWRITE (1 << 1) #define FAULT_FLAG_ALLOW_RETRY (1 << 2) @@ -183,6 +186,25 @@ return (0); } +vm_fault_t +lkpi_vmf_insert_pfn_prot_locked(struct vm_area_struct *vma, unsigned long addr, + unsigned long pfn, pgprot_t prot); + +static inline vm_fault_t +vmf_insert_pfn_prot(struct vm_area_struct *vma, unsigned long addr, + unsigned long pfn, pgprot_t prot) +{ + vm_fault_t ret; + + VM_OBJECT_WLOCK(vma->vm_obj); + ret = lkpi_vmf_insert_pfn_prot_locked(vma, addr, pfn, prot); + VM_OBJECT_WUNLOCK(vma->vm_obj); + + return (ret); +} +#define vmf_insert_pfn_prot(...) \ + _Static_assert(false, "Consider using of locked version") + static inline int apply_to_page_range(struct mm_struct *mm, unsigned long address, unsigned long size, pte_fn_t fn, void *data) Index: sys/compat/linuxkpi/common/src/linux_page.c =================================================================== --- sys/compat/linuxkpi/common/src/linux_page.c +++ sys/compat/linuxkpi/common/src/linux_page.c @@ -275,3 +275,35 @@ { return (vtoslab((vm_offset_t)addr & ~UMA_SLAB_MASK) != NULL); } + +vm_fault_t +lkpi_vmf_insert_pfn_prot_locked(struct vm_area_struct *vma, unsigned long addr, + unsigned long pfn, pgprot_t prot) +{ + vm_object_t vm_obj = vma->vm_obj; + vm_page_t page; + vm_pindex_t pindex; + + VM_OBJECT_ASSERT_WLOCKED(vm_obj); + pindex = OFF_TO_IDX(addr - vma->vm_start); + if (vma->vm_pfn_count == 0) + vma->vm_pfn_first = pindex; + MPASS(pindex <= OFF_TO_IDX(vma->vm_end)); + +retry: + page = vm_page_grab(vm_obj, pindex, VM_ALLOC_NOCREAT); + if (page == NULL) { + page = PHYS_TO_VM_PAGE(IDX_TO_OFF(pfn)); + if (!vm_page_busy_acquire(page, VM_ALLOC_WAITFAIL)) + goto retry; + if (vm_page_insert(page, vm_obj, pindex)) { + vm_page_xunbusy(page); + return (VM_FAULT_OOM); + } + vm_page_valid(page); + } + pmap_page_set_memattr(page, pgprot2cachemode(prot)); + vma->vm_pfn_count++; + + return (VM_FAULT_NOPAGE); +}