diff options
author | Dan Williams <dan.j.williams@intel.com> | 2017-10-23 10:20:00 -0400 |
---|---|---|
committer | Dan Williams <dan.j.williams@intel.com> | 2018-01-19 19:50:53 -0500 |
commit | 785a3fab4adbf91b2189c928a59ae219c54ba95e (patch) | |
tree | 7a3f3342c336eb99cbc7ddbe09741af78d7e99b2 | |
parent | 77dd66a3c67c93ab401ccc15efff25578be281fd (diff) |
mm, dax: introduce pfn_t_special()
In support of removing the VM_MIXEDMAP indication from DAX VMAs,
introduce pfn_t_special() for drivers to indicate that _PAGE_SPECIAL
should be used for DAX ptes. This also helps identify drivers like
dccssblk that only want to use DAX in a read-only fashion without
get_user_pages() support.
Ideally we could delete axonram and dcssblk DAX support, but if we need
to keep it better make it explicit that axonram and dcssblk only support
a sub-set of DAX due to missing _PAGE_DEVMAP support.
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Martin Schwidefsky <schwidefsky@de.ibm.com>
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
-rw-r--r-- | arch/powerpc/sysdev/axonram.c | 2 | ||||
-rw-r--r-- | drivers/s390/block/dcssblk.c | 3 | ||||
-rw-r--r-- | include/linux/pfn_t.h | 13 | ||||
-rw-r--r-- | mm/memory.c | 16 |
4 files changed, 31 insertions, 3 deletions
diff --git a/arch/powerpc/sysdev/axonram.c b/arch/powerpc/sysdev/axonram.c index 1b307c80b401..cdbb0e59b3d3 100644 --- a/arch/powerpc/sysdev/axonram.c +++ b/arch/powerpc/sysdev/axonram.c | |||
@@ -151,7 +151,7 @@ __axon_ram_direct_access(struct axon_ram_bank *bank, pgoff_t pgoff, long nr_page | |||
151 | resource_size_t offset = pgoff * PAGE_SIZE; | 151 | resource_size_t offset = pgoff * PAGE_SIZE; |
152 | 152 | ||
153 | *kaddr = (void *) bank->io_addr + offset; | 153 | *kaddr = (void *) bank->io_addr + offset; |
154 | *pfn = phys_to_pfn_t(bank->ph_addr + offset, PFN_DEV); | 154 | *pfn = phys_to_pfn_t(bank->ph_addr + offset, PFN_DEV|PFN_SPECIAL); |
155 | return (bank->size - offset) / PAGE_SIZE; | 155 | return (bank->size - offset) / PAGE_SIZE; |
156 | } | 156 | } |
157 | 157 | ||
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 6aaefb780436..9cae08b36b80 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c | |||
@@ -916,7 +916,8 @@ __dcssblk_direct_access(struct dcssblk_dev_info *dev_info, pgoff_t pgoff, | |||
916 | 916 | ||
917 | dev_sz = dev_info->end - dev_info->start + 1; | 917 | dev_sz = dev_info->end - dev_info->start + 1; |
918 | *kaddr = (void *) dev_info->start + offset; | 918 | *kaddr = (void *) dev_info->start + offset; |
919 | *pfn = __pfn_to_pfn_t(PFN_DOWN(dev_info->start + offset), PFN_DEV); | 919 | *pfn = __pfn_to_pfn_t(PFN_DOWN(dev_info->start + offset), |
920 | PFN_DEV|PFN_SPECIAL); | ||
920 | 921 | ||
921 | return (dev_sz - offset) / PAGE_SIZE; | 922 | return (dev_sz - offset) / PAGE_SIZE; |
922 | } | 923 | } |
diff --git a/include/linux/pfn_t.h b/include/linux/pfn_t.h index 43b1d7648e82..a03c2642a87c 100644 --- a/include/linux/pfn_t.h +++ b/include/linux/pfn_t.h | |||
@@ -15,8 +15,10 @@ | |||
15 | #define PFN_SG_LAST (1ULL << (BITS_PER_LONG_LONG - 2)) | 15 | #define PFN_SG_LAST (1ULL << (BITS_PER_LONG_LONG - 2)) |
16 | #define PFN_DEV (1ULL << (BITS_PER_LONG_LONG - 3)) | 16 | #define PFN_DEV (1ULL << (BITS_PER_LONG_LONG - 3)) |
17 | #define PFN_MAP (1ULL << (BITS_PER_LONG_LONG - 4)) | 17 | #define PFN_MAP (1ULL << (BITS_PER_LONG_LONG - 4)) |
18 | #define PFN_SPECIAL (1ULL << (BITS_PER_LONG_LONG - 5)) | ||
18 | 19 | ||
19 | #define PFN_FLAGS_TRACE \ | 20 | #define PFN_FLAGS_TRACE \ |
21 | { PFN_SPECIAL, "SPECIAL" }, \ | ||
20 | { PFN_SG_CHAIN, "SG_CHAIN" }, \ | 22 | { PFN_SG_CHAIN, "SG_CHAIN" }, \ |
21 | { PFN_SG_LAST, "SG_LAST" }, \ | 23 | { PFN_SG_LAST, "SG_LAST" }, \ |
22 | { PFN_DEV, "DEV" }, \ | 24 | { PFN_DEV, "DEV" }, \ |
@@ -120,4 +122,15 @@ pud_t pud_mkdevmap(pud_t pud); | |||
120 | #endif | 122 | #endif |
121 | #endif /* __HAVE_ARCH_PTE_DEVMAP */ | 123 | #endif /* __HAVE_ARCH_PTE_DEVMAP */ |
122 | 124 | ||
125 | #ifdef __HAVE_ARCH_PTE_SPECIAL | ||
126 | static inline bool pfn_t_special(pfn_t pfn) | ||
127 | { | ||
128 | return (pfn.val & PFN_SPECIAL) == PFN_SPECIAL; | ||
129 | } | ||
130 | #else | ||
131 | static inline bool pfn_t_special(pfn_t pfn) | ||
132 | { | ||
133 | return false; | ||
134 | } | ||
135 | #endif /* __HAVE_ARCH_PTE_SPECIAL */ | ||
123 | #endif /* _LINUX_PFN_T_H_ */ | 136 | #endif /* _LINUX_PFN_T_H_ */ |
diff --git a/mm/memory.c b/mm/memory.c index ca5674cbaff2..46b6c33b7f04 100644 --- a/mm/memory.c +++ b/mm/memory.c | |||
@@ -1897,12 +1897,26 @@ int vm_insert_pfn_prot(struct vm_area_struct *vma, unsigned long addr, | |||
1897 | } | 1897 | } |
1898 | EXPORT_SYMBOL(vm_insert_pfn_prot); | 1898 | EXPORT_SYMBOL(vm_insert_pfn_prot); |
1899 | 1899 | ||
1900 | static bool vm_mixed_ok(struct vm_area_struct *vma, pfn_t pfn) | ||
1901 | { | ||
1902 | /* these checks mirror the abort conditions in vm_normal_page */ | ||
1903 | if (vma->vm_flags & VM_MIXEDMAP) | ||
1904 | return true; | ||
1905 | if (pfn_t_devmap(pfn)) | ||
1906 | return true; | ||
1907 | if (pfn_t_special(pfn)) | ||
1908 | return true; | ||
1909 | if (is_zero_pfn(pfn_t_to_pfn(pfn))) | ||
1910 | return true; | ||
1911 | return false; | ||
1912 | } | ||
1913 | |||
1900 | static int __vm_insert_mixed(struct vm_area_struct *vma, unsigned long addr, | 1914 | static int __vm_insert_mixed(struct vm_area_struct *vma, unsigned long addr, |
1901 | pfn_t pfn, bool mkwrite) | 1915 | pfn_t pfn, bool mkwrite) |
1902 | { | 1916 | { |
1903 | pgprot_t pgprot = vma->vm_page_prot; | 1917 | pgprot_t pgprot = vma->vm_page_prot; |
1904 | 1918 | ||
1905 | BUG_ON(!(vma->vm_flags & VM_MIXEDMAP)); | 1919 | BUG_ON(!vm_mixed_ok(vma, pfn)); |
1906 | 1920 | ||
1907 | if (addr < vma->vm_start || addr >= vma->vm_end) | 1921 | if (addr < vma->vm_start || addr >= vma->vm_end) |
1908 | return -EFAULT; | 1922 | return -EFAULT; |