diff options
author | Hans Petter Selasky <hselasky@FreeBSD.org> | 2017-04-06 09:34:54 +0000 |
---|---|---|
committer | Hans Petter Selasky <hselasky@FreeBSD.org> | 2017-04-06 09:34:54 +0000 |
commit | 1ea4c85781e9404e78b9444f27cf4f8ed3915649 (patch) | |
tree | 138c3bb83d0e8e006c09e00b5f341add3f65a7e6 /sys/compat/linuxkpi/common/include/linux | |
parent | e54b103e700fe6c38316cecd39957561197379a6 (diff) | |
download | src-1ea4c85781e9404e78b9444f27cf4f8ed3915649.tar.gz src-1ea4c85781e9404e78b9444f27cf4f8ed3915649.zip |
Implement proper support for memory map operations in the LinuxKPI,
like open, close and fault using the character device pager.
Some notes about the implementation:
1) Linux drivers set the vm_ops and vm_private_data fields during a
mmap() call to indicate that the driver wants to use the LinuxKPI VM
operations. Else these operations are not used.
2) The vm_private_data pointer is associated with a VM area structure
and inserted into an internal LinuxKPI list. If the vm_private_data
pointer already exists, the existing VM area structure is used instead
of the allocated one which gets freed.
3) The LinuxKPI's vm_private_data pointer is used as the callback
handle for the FreeBSD VM object. The VM subsystem in FreeBSD has a
similar list to identify equal handles and will only call the
character device pager's close function once.
4) All LinuxKPI VM operations are serialized through the mmap_sem
sempaphore, which is per procedure, which prevents simultaneous access
to the shared VM area structure when receiving page faults.
Obtained from: kmacy @
MFC after: 1 week
Sponsored by: Mellanox Technologies
Notes
Notes:
svn path=/head/; revision=316562
Diffstat (limited to 'sys/compat/linuxkpi/common/include/linux')
-rw-r--r-- | sys/compat/linuxkpi/common/include/linux/mm.h | 26 | ||||
-rw-r--r-- | sys/compat/linuxkpi/common/include/linux/page.h | 22 |
2 files changed, 42 insertions, 6 deletions
diff --git a/sys/compat/linuxkpi/common/include/linux/mm.h b/sys/compat/linuxkpi/common/include/linux/mm.h index f652e3be325e..67ac02daff76 100644 --- a/sys/compat/linuxkpi/common/include/linux/mm.h +++ b/sys/compat/linuxkpi/common/include/linux/mm.h @@ -38,6 +38,7 @@ #include <linux/kernel.h> #include <linux/mm_types.h> #include <linux/pfn.h> +#include <linux/list.h> #include <asm/pgtable.h> @@ -89,12 +90,25 @@ CTASSERT((VM_PROT_ALL & -(1 << 8)) == 0); typedef int (*pte_fn_t)(pte_t *, pgtable_t, unsigned long addr, void *data); struct vm_area_struct { - vm_offset_t vm_start; - vm_offset_t vm_end; - vm_offset_t vm_pgoff; - vm_paddr_t vm_pfn; /* PFN For mmap. */ - vm_size_t vm_len; /* length for mmap. */ - vm_memattr_t vm_page_prot; + vm_offset_t vm_start; + vm_offset_t vm_end; + vm_offset_t vm_pgoff; + pgprot_t vm_page_prot; + unsigned long vm_flags; + struct mm_struct *vm_mm; + void *vm_private_data; + const struct vm_operations_struct *vm_ops; + struct linux_file *vm_file; + + /* internal operation */ + vm_paddr_t vm_pfn; /* PFN for memory map */ + vm_size_t vm_len; /* length for memory map */ + vm_pindex_t vm_pfn_first; + int vm_pfn_count; + int *vm_pfn_pcount; + vm_object_t vm_obj; + vm_map_t vm_cached_map; + TAILQ_ENTRY(vm_area_struct) vm_entry; }; struct vm_fault { diff --git a/sys/compat/linuxkpi/common/include/linux/page.h b/sys/compat/linuxkpi/common/include/linux/page.h index 7e84e0440451..a40308e44dee 100644 --- a/sys/compat/linuxkpi/common/include/linux/page.h +++ b/sys/compat/linuxkpi/common/include/linux/page.h @@ -47,6 +47,28 @@ typedef unsigned long pgprot_t; #define page vm_page +#define LINUXKPI_PROT_VALID (1 << 4) +#define LINUXKPI_CACHE_MODE_SHIFT 3 + +static inline pgprot_t +cachemode2protval(vm_memattr_t attr) +{ + return ((attr | LINUXKPI_PROT_VALID) << LINUXKPI_CACHE_MODE_SHIFT); +} + +static inline vm_memattr_t +pgprot2cachemode(pgprot_t prot) +{ + int val; + + val = prot >> LINUXKPI_CACHE_MODE_SHIFT; + + if (val & LINUXKPI_PROT_VALID) + return (val & ~LINUXKPI_PROT_VALID); + else + return (VM_MEMATTR_DEFAULT); +} + #define virt_to_page(x) PHYS_TO_VM_PAGE(vtophys((x))) #define page_to_pfn(pp) (VM_PAGE_TO_PHYS((pp)) >> PAGE_SHIFT) #define pfn_to_page(pfn) (PHYS_TO_VM_PAGE((pfn) << PAGE_SHIFT)) |