mirror of
https://github.com/opnsense/src.git
synced 2026-06-09 00:32:25 -04:00
LinuxKPI: Factor out vmf_insert_pfn_prot() routine
from GEM and TTM page fault handlers and move it in to base system. This code is tightly integrated with LKPI mmap support to belong to drm-kmod. As this routine requires associated vm_object to be locked, it got additional _locked suffix. Reviewed by: hselasky, markj MFC after: 2 weeks Differential revision: https://reviews.freebsd.org/D32068
This commit is contained in:
parent
7d92d48358
commit
f6823dac8f
2 changed files with 55 additions and 0 deletions
|
|
@ -82,6 +82,9 @@ CTASSERT((VM_PROT_ALL & -(1 << 8)) == 0);
|
|||
#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,26 @@ io_remap_pfn_range(struct vm_area_struct *vma,
|
|||
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, \
|
||||
"This function is always called in a loop. Consider using the 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)
|
||||
|
|
|
|||
|
|
@ -275,3 +275,35 @@ is_vmalloc_addr(const void *addr)
|
|||
{
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue