Hacking the code in ioremap entry and page fault handler entry to integrate mmiotrace.
Signed-off-by: Jialong Yang <jialong.y...@shingroup.cn> --- arch/powerpc/mm/fault.c | 17 +++++++++++++++++ arch/powerpc/mm/ioremap_64.c | 11 +++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index 215690452495..b03cba73de92 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -22,6 +22,7 @@ #include <linux/ptrace.h> #include <linux/mman.h> #include <linux/mm.h> +#include <linux/mmiotrace.h> #include <linux/interrupt.h> #include <linux/highmem.h> #include <linux/extable.h> @@ -50,6 +51,19 @@ * do_page_fault error handling helpers */ +/* + * Returns 0 if mmiotrace is disabled, or if the fault is not + * handled by mmiotrace: + */ +static nokprobe_inline int +kmmio_fault(struct pt_regs *regs, unsigned long addr) +{ + if (unlikely(is_kmmio_active())) + if (kmmio_handler(regs, addr) == 1) + return -1; + return 0; +} + static int __bad_area_nosemaphore(struct pt_regs *regs, unsigned long address, int si_code) { @@ -422,6 +436,9 @@ static int ___do_page_fault(struct pt_regs *regs, unsigned long address, vm_fault_t fault, major = 0; bool kprobe_fault = kprobe_page_fault(regs, 11); + if (unlikely(kmmio_fault(regs, address))) + return 0; + if (unlikely(debugger_fault_handler(regs) || kprobe_fault)) return 0; diff --git a/arch/powerpc/mm/ioremap_64.c b/arch/powerpc/mm/ioremap_64.c index d24e5f166723..f5f717bf35df 100644 --- a/arch/powerpc/mm/ioremap_64.c +++ b/arch/powerpc/mm/ioremap_64.c @@ -3,12 +3,15 @@ #include <linux/io.h> #include <linux/slab.h> #include <linux/vmalloc.h> +#include <linux/mmiotrace.h> void __iomem *__ioremap_caller(phys_addr_t addr, unsigned long size, pgprot_t prot, void *caller) { phys_addr_t paligned, offset; void __iomem *ret; + phys_addr_t unaligned_phys_addr = addr; + const unsigned long unaligned_size = size; int err; /* We don't support the 4K PFN hack with ioremap */ @@ -28,8 +31,11 @@ void __iomem *__ioremap_caller(phys_addr_t addr, unsigned long size, if (size == 0 || paligned == 0) return NULL; - if (slab_is_available()) - return generic_ioremap_prot(addr, size, prot); + if (slab_is_available()) { + ret = generic_ioremap_prot(addr, size, prot); + mmiotrace_ioremap(unaligned_phys_addr, unaligned_size, ret); + return ret; + } pr_warn("ioremap() called early from %pS. Use early_ioremap() instead\n", caller); @@ -52,6 +58,7 @@ void iounmap(volatile void __iomem *token) if (!slab_is_available()) return; + mmiotrace_iounmap(token); generic_iounmap(PCI_FIX_ADDR(token)); } EXPORT_SYMBOL(iounmap); -- 2.34.1