^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Written by Pekka Paalanen, 2008-2009 <pq@iki.fi>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/mmiotrace.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/security.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) static unsigned long mmio_address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) module_param_hw(mmio_address, ulong, iomem, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) MODULE_PARM_DESC(mmio_address, " Start address of the mapping of 16 kB "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) "(or 8 MB if read_far is non-zero).");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) static unsigned long read_far = 0x400100;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) module_param(read_far, ulong, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) MODULE_PARM_DESC(read_far, " Offset of a 32-bit read within 8 MB "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) "(default: 0x400100).");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) static unsigned v16(unsigned i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) return i * 12 + 7;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static unsigned v32(unsigned i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) return i * 212371 + 13;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static void do_write_test(void __iomem *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) pr_info("write test.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) mmiotrace_printk("Write test.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) for (i = 0; i < 256; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) iowrite8(i, p + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) for (i = 1024; i < (5 * 1024); i += 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) iowrite16(v16(i), p + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) for (i = (5 * 1024); i < (16 * 1024); i += 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) iowrite32(v32(i), p + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) static void do_read_test(void __iomem *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) unsigned errs[3] = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) pr_info("read test.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) mmiotrace_printk("Read test.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) for (i = 0; i < 256; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) if (ioread8(p + i) != i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) ++errs[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) for (i = 1024; i < (5 * 1024); i += 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) if (ioread16(p + i) != v16(i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) ++errs[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) for (i = (5 * 1024); i < (16 * 1024); i += 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) if (ioread32(p + i) != v32(i))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) ++errs[2];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) mmiotrace_printk("Read errors: 8-bit %d, 16-bit %d, 32-bit %d.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) errs[0], errs[1], errs[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) static void do_read_far_test(void __iomem *p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) pr_info("read far test.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) mmiotrace_printk("Read far test.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) ioread32(p + read_far);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) static void do_test(unsigned long size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) void __iomem *p = ioremap(mmio_address, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (!p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) pr_err("could not ioremap, aborting.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) mmiotrace_printk("ioremap returned %p.\n", p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) do_write_test(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) do_read_test(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) if (read_far && read_far < size - 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) do_read_far_test(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) iounmap(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * Tests how mmiotrace behaves in face of multiple ioremap / iounmaps in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * a short time. We had a bug in deferred freeing procedure which tried
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * to free this region multiple times (ioremap can reuse the same address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * for many mappings).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static void do_test_bulk_ioremapping(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) void __iomem *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) for (i = 0; i < 10; ++i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) p = ioremap(mmio_address, PAGE_SIZE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) if (p)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) iounmap(p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) /* Force freeing. If it will crash we will know why. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) synchronize_rcu();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) static int __init init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) unsigned long size = (read_far) ? (8 << 20) : (16 << 10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) int ret = security_locked_down(LOCKDOWN_MMIOTRACE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) if (mmio_address == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) pr_err("you have to use the module argument mmio_address.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) pr_err("DO NOT LOAD THIS MODULE UNLESS YOU REALLY KNOW WHAT YOU ARE DOING!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) pr_warn("WARNING: mapping %lu kB @ 0x%08lx in PCI address space, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) "and writing 16 kB of rubbish in there.\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) size >> 10, mmio_address);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) do_test(size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) do_test_bulk_ioremapping();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) pr_info("All done.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static void __exit cleanup(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) pr_debug("unloaded.\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) module_init(init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) module_exit(cleanup);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) MODULE_LICENSE("GPL");