aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2017-10-23 10:20:00 -0400
committerDan Williams <dan.j.williams@intel.com>2018-01-19 19:50:53 -0500
commit785a3fab4adbf91b2189c928a59ae219c54ba95e (patch)
tree7a3f3342c336eb99cbc7ddbe09741af78d7e99b2
parent77dd66a3c67c93ab401ccc15efff25578be281fd (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.c2
-rw-r--r--drivers/s390/block/dcssblk.c3
-rw-r--r--include/linux/pfn_t.h13
-rw-r--r--mm/memory.c16
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
126static inline bool pfn_t_special(pfn_t pfn)
127{
128 return (pfn.val & PFN_SPECIAL) == PFN_SPECIAL;
129}
130#else
131static 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}
1898EXPORT_SYMBOL(vm_insert_pfn_prot); 1898EXPORT_SYMBOL(vm_insert_pfn_prot);
1899 1899
1900static 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
1900static int __vm_insert_mixed(struct vm_area_struct *vma, unsigned long addr, 1914static 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;