| From ed7cd17fc559d4572a2b6cb7235d63b7a4a7f347 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 19 Feb 2021 12:00:52 +0100 |
| Subject: s390: enable HAVE_IOREMAP_PROT |
| |
| From: Niklas Schnelle <schnelle@linux.ibm.com> |
| |
| [ 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 | 1 + |
| arch/s390/include/asm/pgtable.h | 19 +++++++++++++++++++ |
| 2 files changed, 20 insertions(+) |
| |
| diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig |
| index dc5c3e6fd200..7105d44a335b 100644 |
| --- a/arch/s390/Kconfig |
| +++ b/arch/s390/Kconfig |
| @@ -154,6 +154,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 |
| diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h |
| index b5dbae78969b..2338345912a3 100644 |
| --- a/arch/s390/include/asm/pgtable.h |
| +++ b/arch/s390/include/asm/pgtable.h |
| @@ -864,6 +864,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 |
| */ |
| -- |
| 2.30.2 |
| |