powerpc/eeh: Handle hugepages in ioremap space [Linux 4.9.187]

This Linux kernel change "powerpc/eeh: Handle hugepages in ioremap space" is included in the Linux 4.9.187 release. This change is authored by Oliver O'Halloran <oohall [at] gmail.com> on Thu Jul 11 01:05:17 2019 +1000. The commit for this change in Linux stable tree is bce3e3e (patch) which is from upstream commit 3343962. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 3343962.

powerpc/eeh: Handle hugepages in ioremap space

[ Upstream commit 33439620680be5225c1b8806579a291e0d761ca0 ]

In commit 4a7b06c157a2 ("powerpc/eeh: Handle hugepages in ioremap
space") support for using hugepages in the vmalloc and ioremap areas was
enabled for radix. Unfortunately this broke EEH MMIO error checking.

Detection works by inserting a hook which checks the results of the
ioreadXX() set of functions.  When a read returns a 0xFFs response we
need to check for an error which we do by mapping the (virtual) MMIO
address back to a physical address, then mapping physical address to a
PCI device via an interval tree.

When translating virt -> phys we currently assume the ioremap space is
only populated by PAGE_SIZE mappings. If a hugepage mapping is found we
emit a WARN_ON(), but otherwise handles the check as though a normal
page was found. In pathalogical cases such as copying a buffer
containing a lot of 0xFFs from BAR memory this can result in the system
not booting because it's too busy printing WARN_ON()s.

There's no real reason to assume huge pages can't be present and we're
prefectly capable of handling them, so do that.

Fixes: 4a7b06c157a2 ("powerpc/eeh: Handle hugepages in ioremap space")
Reported-by: Sachin Sant <[email protected]>
Signed-off-by: Oliver O'Halloran <[email protected]>
Tested-by: Sachin Sant <[email protected]>
Signed-off-by: Michael Ellerman <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Sasha Levin <[email protected]>

There are 15 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 arch/powerpc/kernel/eeh.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index 8336b90..a7f229e 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -362,10 +362,19 @@ static inline unsigned long eeh_token_to_phys(unsigned long token)
                       NULL, &hugepage_shift);
    if (!ptep)
        return token;
-   WARN_ON(hugepage_shift);
-   pa = pte_pfn(*ptep) << PAGE_SHIFT;

-   return pa | (token & (PAGE_SIZE-1));
+   pa = pte_pfn(*ptep);
+
+   /* On radix we can do hugepage mappings for io, so handle that */
+   if (hugepage_shift) {
+       pa <<= hugepage_shift;
+       pa |= token & ((1ul << hugepage_shift) - 1);
+   } else {
+       pa <<= PAGE_SHIFT;
+       pa |= token & (PAGE_SIZE - 1);
+   }
+
+   return pa;
 }

 /*

Leave a Reply

Your email address will not be published. Required fields are marked *