]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
s390: enable HAVE_IOREMAP_PROT
authorNiklas Schnelle <schnelle@linux.ibm.com>
Fri, 19 Feb 2021 11:00:52 +0000 (12:00 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 14 Jul 2021 15:00:18 +0000 (17:00 +0200)
[ Upstream commit d460bb6c6417588dd8b0907d34f69b237918812a ]

In commit b02002cc4c0f ("s390/pci: Implement ioremap_wc/prot() with
MIO") we implemented both ioremap_wc() and ioremap_prot() however until
now we had not set HAVE_IOREMAP_PROT in Kconfig, do so now.

This also requires implementing pte_pgprot() as this is used in the
generic_access_phys() code enabled by CONFIG_HAVE_IOREMAP_PROT. As with
ioremap_wc() we need to take the MMIO Write Back bit index into account.

Moreover since the pgprot value returned from pte_pgprot() is to be used
for mappings into kernel address space we must make sure that it uses
appropriate kernel page table protection bits. In particular a pgprot
value originally coming from userspace could have the _PAGE_PROTECT
bit set to enable fault based dirty bit accounting which would then make
the mapping inaccessible when used in kernel address space.

Fixes: b02002cc4c0f ("s390/pci: Implement ioremap_wc/prot() with MIO")
Reviewed-by: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
arch/s390/Kconfig
arch/s390/include/asm/pgtable.h

index c1ff874e6c2e63e278dd9a894b70f0f3df1b93ed..d6676197276c92a489cb36aa7165e0f5d5df0b50 100644 (file)
@@ -160,6 +160,7 @@ config S390
        select HAVE_FUTEX_CMPXCHG if FUTEX
        select HAVE_GCC_PLUGINS
        select HAVE_GENERIC_VDSO
+       select HAVE_IOREMAP_PROT if PCI
        select HAVE_IRQ_EXIT_ON_IRQ_STACK
        select HAVE_KERNEL_BZIP2
        select HAVE_KERNEL_GZIP
index b38f7b7815649cf4f3889d998cb8d3bbed04beb4..adea53f69bfd366a80eea379832e9f9b1df1586a 100644 (file)
@@ -863,6 +863,25 @@ static inline int pte_unused(pte_t pte)
        return pte_val(pte) & _PAGE_UNUSED;
 }
 
+/*
+ * Extract the pgprot value from the given pte while at the same time making it
+ * usable for kernel address space mappings where fault driven dirty and
+ * young/old accounting is not supported, i.e _PAGE_PROTECT and _PAGE_INVALID
+ * must not be set.
+ */
+static inline pgprot_t pte_pgprot(pte_t pte)
+{
+       unsigned long pte_flags = pte_val(pte) & _PAGE_CHG_MASK;
+
+       if (pte_write(pte))
+               pte_flags |= pgprot_val(PAGE_KERNEL);
+       else
+               pte_flags |= pgprot_val(PAGE_KERNEL_RO);
+       pte_flags |= pte_val(pte) & mio_wb_bit_mask;
+
+       return __pgprot(pte_flags);
+}
+
 /*
  * pgd/pmd/pte modification functions
  */