This is an example driver with little bit of kernel hack to test
ZONE_DEVICE based device memory management on POWER.
Signed-off-by: Anshuman Khandual
---
arch/powerpc/mm/init_64.c | 12 ++-
arch/powerpc/platforms/pseries/Makefile | 2 +-
arch/powerpc/platforms/pseries/rmem.c | 186
3 files changed, 198 insertions(+), 2 deletions(-)
create mode 100644 arch/powerpc/platforms/pseries/rmem.c
diff --git a/arch/powerpc/mm/init_64.c b/arch/powerpc/mm/init_64.c
index db73708..5cc286d 100644
--- a/arch/powerpc/mm/init_64.c
+++ b/arch/powerpc/mm/init_64.c
@@ -351,6 +351,17 @@ int __meminit vmemmap_populate(unsigned long start,
unsigned long end, int node)
}
#ifdef CONFIG_MEMORY_HOTPLUG
+void dump_vmemmap(void)
+{
+ struct vmemmap_backing *vmem_back = vmemmap_list;
+
+ for (; vmem_back; vmem_back = vmem_back->list) {
+ printk("RMEM: vmemmap backing (%lx %lx)\n",
+ vmem_back->virt_addr, vmem_back->phys);
+ }
+}
+EXPORT_SYMBOL(dump_vmemmap);
+
static unsigned long vmemmap_list_free(unsigned long start)
{
struct vmemmap_backing *vmem_back, *vmem_back_prev;
@@ -482,5 +493,4 @@ struct page *realmode_pfn_to_page(unsigned long pfn)
return page;
}
EXPORT_SYMBOL_GPL(realmode_pfn_to_page);
-
#endif /* CONFIG_SPARSEMEM_VMEMMAP/CONFIG_FLATMEM */
diff --git a/arch/powerpc/platforms/pseries/Makefile
b/arch/powerpc/platforms/pseries/Makefile
index fedc2ccf0..20a5e23 100644
--- a/arch/powerpc/platforms/pseries/Makefile
+++ b/arch/powerpc/platforms/pseries/Makefile
@@ -5,7 +5,7 @@ obj-y := lpar.o hvCall.o nvram.o reconfig.o \
of_helpers.o \
setup.o iommu.o event_sources.o ras.o \
firmware.o power.o dlpar.o mobility.o rng.o \
- pci.o pci_dlpar.o eeh_pseries.o msi.o
+ pci.o pci_dlpar.o eeh_pseries.o msi.o rmem.o
obj-$(CONFIG_SMP) += smp.o
obj-$(CONFIG_SCANLOG) += scanlog.o
obj-$(CONFIG_KEXEC)+= kexec.o
diff --git a/arch/powerpc/platforms/pseries/rmem.c
b/arch/powerpc/platforms/pseries/rmem.c
new file mode 100644
index 000..8c2287a
--- /dev/null
+++ b/arch/powerpc/platforms/pseries/rmem.c
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2016 Anshuman Khandual (khand...@linux.vnet.ibm.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define DEVM_MAP_SIZE (1UL << PA_SECTION_SHIFT) * 8
+
+extern void dump_vmemmap(void);
+extern struct resmem rmem;
+
+unsigned long devmem_start;
+unsigned long devmem_end;
+
+void driver_test_devmem(void)
+{
+ unsigned long i;
+ unsigned long start = devmem_start >> PAGE_SHIFT;
+ unsigned long end = devmem_end >> PAGE_SHIFT;
+
+ for(i = start; i < end; i++)
+ *(unsigned long *)i = (char)i;
+
+ for(i = start; i < end; i++) {
+ if (*(unsigned long *)i != (char)i)
+ printk("RMEM: Error data miscompare at %lx\n", i);
+ }
+ printk("RMEM: Data integrity test successful\n");
+}
+
+void driver_memory(unsigned long start_pfn, unsigned long end_pfn)
+{
+ printk("RMEM: Driver now owns PFN(%lx%lx)\n", start_pfn, end_pfn);
+
+ devmem_start = start_pfn;
+ devmem_end = end_pfn;
+ driver_test_devmem();
+}
+
+static void dump_reserved(void)
+{
+ unsigned long i;
+
+ printk("RMEM: Reserved memory sections\n");
+ for (i = 0; i < rmem.nr; i++) {
+ printk("RMEM: Base %llx Size: %llx Node: %llu\n",
+ rmem.mem[i][MEM_BASE], rmem.mem[i][MEM_SIZE],
+ rmem.mem[i][MEM_NODE]);
+ }
+}
+
+static void dump_devmap(resource_size_t start)
+{
+ struct vmem_altmap *altmap;
+ struct dev_pagemap *pgmap;
+ struct page_map *pmap;
+ struct page *page;
+ unsigned long pfn;
+
+ altmap = to_vmem_altmap((unsigned long)pfn_to_page(start >>
PAGE_SHIFT));
+ if (altmap) {
+ printk("RMEM: altmap->base_pfn %lu\n", altmap->base_pfn);
+ printk("RMEM: altmap->reserve %lu\n", altmap->reserve);
+ printk("RMEM: altmap->free %lu\n", altmap->free);
+ printk("RMEM: altmap->align %lu\n", altmap->align);
+ printk("RMEM: altmap->alloc %lu\n", altmap->alloc);
+ }
+ pmap = find_pagemap(start);
+ rcu_read_lock();
+ pgmap = find_dev_pagemap(start);
+ rcu_read_unlock();
+ printk("RMEM: pagemap (%lx)\n", (unsigned long)pmap);
+ printk("R