1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * Copyright (C) IBM Corporation, 2014, 2017 4 * Anton Blanchard, Rashmica Gupta. 5 */ 6 7 #define pr_fmt(fmt) "memtrace: " fmt 8 9 #include <linux/bitops.h> 10 #include <linux/string.h> 11 #include <linux/memblock.h> 12 #include <linux/init.h> 13 #include <linux/moduleparam.h> 14 #include <linux/fs.h> 15 #include <linux/debugfs.h> 16 #include <linux/slab.h> 17 #include <linux/memory.h> 18 #include <linux/memory_hotplug.h> 19 #include <linux/numa.h> 20 #include <asm/machdep.h> 21 #include <asm/cacheflush.h> 22 23 /* This enables us to keep track of the memory removed from each node. */ 24 struct memtrace_entry { 25 void *mem; 26 u64 start; 27 u64 size; 28 u32 nid; 29 struct dentry *dir; 30 char name[16]; 31 }; 32 33 static DEFINE_MUTEX(memtrace_mutex); 34 static u64 memtrace_size; 35 36 static struct memtrace_entry *memtrace_array; 37 static unsigned int memtrace_array_nr; 38 39 40 static ssize_t memtrace_read(struct file *filp, char __user *ubuf, 41 size_t count, loff_t *ppos) 42 { 43 struct memtrace_entry *ent = filp->private_data; 44 45 return simple_read_from_buffer(ubuf, count, ppos, ent->mem, ent->size); 46 } 47 48 static int memtrace_mmap(struct file *filp, struct vm_area_struct *vma) 49 { 50 struct memtrace_entry *ent = filp->private_data; 51 unsigned long ent_nrpages = ent->size >> PAGE_SHIFT; 52 unsigned long vma_nrpages = vma_pages(vma); 53 54 /* The requested page offset should be within object's page count */ 55 if (vma->vm_pgoff >= ent_nrpages) 56 return -EINVAL; 57 58 /* The requested mapping range should remain within the bounds */ 59 if (vma_nrpages > ent_nrpages - vma->vm_pgoff) 60 return -EINVAL; 61 62 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); 63 return remap_pfn_range(vma, vma->vm_start, PHYS_PFN(ent->start) + vma->vm_pgoff, 64 vma->vm_end - vma->vm_start, vma->vm_page_prot); 65 } 66 67 static const struct file_operations memtrace_fops = { 68 .llseek = default_llseek, 69 .read = memtrace_read, 70 .open = simple_open, 71 .mmap = memtrace_mmap, 72 }; 73 74 #define FLUSH_CHUNK_SIZE SZ_1G 75 /** 76 * flush_dcache_range_chunked(): Write any modified data cache blocks out to 77 * memory and invalidate them, in chunks of up to FLUSH_CHUNK_SIZE 78 * Does not invalidate the corresponding instruction cache blocks. 79 * 80 * @start: the start address 81 * @stop: the stop address (exclusive) 82 * @chunk: the max size of the chunks 83 */ 84 static void flush_dcache_range_chunked(unsigned long start, unsigned long stop, 85 unsigned long chunk) 86 { 87 unsigned long i; 88 89 for (i = start; i < stop; i += chunk) { 90 flush_dcache_range(i, min(stop, i + chunk)); 91 cond_resched(); 92 } 93 } 94 95 static u64 memtrace_alloc_node(u32 nid, u64 size) 96 { 97 const unsigned long nr_pages = PHYS_PFN(size); 98 unsigned long pfn, start_pfn; 99 struct page *page; 100 101 /* 102 * Trace memory needs to be aligned to the size, which is guaranteed 103 * by alloc_contig_pages(). 104 */ 105 page = alloc_contig_pages(nr_pages, GFP_KERNEL | __GFP_THISNODE | 106 __GFP_NOWARN | __GFP_ZERO, nid, NULL); 107 if (!page) 108 return 0; 109 start_pfn = page_to_pfn(page); 110 111 /* 112 * Before we go ahead and use this range as cache inhibited range 113 * flush the cache. 114 */ 115 flush_dcache_range_chunked((unsigned long)pfn_to_kaddr(start_pfn), 116 (unsigned long)pfn_to_kaddr(start_pfn + nr_pages), 117 FLUSH_CHUNK_SIZE); 118 119 /* 120 * Set pages PageOffline(), to indicate that nobody (e.g., hibernation, 121 * dumping, ...) should be touching these pages. 122 */ 123 for (pfn = start_pfn; pfn < start_pfn + nr_pages; pfn++) 124 __SetPageOffline(pfn_to_page(pfn)); 125 126 arch_remove_linear_mapping(PFN_PHYS(start_pfn), size); 127 128 return PFN_PHYS(start_pfn); 129 } 130 131 static int memtrace_init_regions_runtime(u64 size) 132 { 133 u32 nid; 134 u64 m; 135 136 memtrace_array = kzalloc_objs(struct memtrace_entry, num_online_nodes()); 137 if (!memtrace_array) { 138 pr_err("Failed to allocate memtrace_array\n"); 139 return -EINVAL; 140 } 141 142 for_each_online_node(nid) { 143 m = memtrace_alloc_node(nid, size); 144 145 /* 146 * A node might not have any local memory, so warn but 147 * continue on. 148 */ 149 if (!m) { 150 pr_err("Failed to allocate trace memory on node %d\n", nid); 151 continue; 152 } 153 154 pr_info("Allocated trace memory on node %d at 0x%016llx\n", nid, m); 155 156 memtrace_array[memtrace_array_nr].start = m; 157 memtrace_array[memtrace_array_nr].size = size; 158 memtrace_array[memtrace_array_nr].nid = nid; 159 memtrace_array_nr++; 160 } 161 162 return 0; 163 } 164 165 static struct dentry *memtrace_debugfs_dir; 166 167 static int memtrace_init_debugfs(void) 168 { 169 int ret = 0; 170 int i; 171 172 for (i = 0; i < memtrace_array_nr; i++) { 173 struct dentry *dir; 174 struct memtrace_entry *ent = &memtrace_array[i]; 175 176 ent->mem = ioremap(ent->start, ent->size); 177 /* Warn but continue on */ 178 if (!ent->mem) { 179 pr_err("Failed to map trace memory at 0x%llx\n", 180 ent->start); 181 ret = -1; 182 continue; 183 } 184 185 snprintf(ent->name, 16, "%08x", ent->nid); 186 dir = debugfs_create_dir(ent->name, memtrace_debugfs_dir); 187 188 ent->dir = dir; 189 debugfs_create_file_unsafe("trace", 0600, dir, ent, &memtrace_fops); 190 debugfs_create_x64("start", 0400, dir, &ent->start); 191 debugfs_create_x64("size", 0400, dir, &ent->size); 192 } 193 194 return ret; 195 } 196 197 static int memtrace_free(int nid, u64 start, u64 size) 198 { 199 struct mhp_params params = { .pgprot = PAGE_KERNEL }; 200 const unsigned long nr_pages = PHYS_PFN(size); 201 const unsigned long start_pfn = PHYS_PFN(start); 202 unsigned long pfn; 203 int ret; 204 205 ret = arch_create_linear_mapping(nid, start, size, ¶ms); 206 if (ret) 207 return ret; 208 209 for (pfn = start_pfn; pfn < start_pfn + nr_pages; pfn++) 210 __ClearPageOffline(pfn_to_page(pfn)); 211 212 free_contig_range(start_pfn, nr_pages); 213 return 0; 214 } 215 216 /* 217 * Iterate through the chunks of memory we allocated and attempt to expose 218 * them back to the kernel. 219 */ 220 static int memtrace_free_regions(void) 221 { 222 int i, ret = 0; 223 struct memtrace_entry *ent; 224 225 for (i = memtrace_array_nr - 1; i >= 0; i--) { 226 ent = &memtrace_array[i]; 227 228 /* We have freed this chunk previously */ 229 if (ent->nid == NUMA_NO_NODE) 230 continue; 231 232 /* Remove from io mappings */ 233 if (ent->mem) { 234 iounmap(ent->mem); 235 ent->mem = 0; 236 } 237 238 if (memtrace_free(ent->nid, ent->start, ent->size)) { 239 pr_err("Failed to free trace memory on node %d\n", 240 ent->nid); 241 ret += 1; 242 continue; 243 } 244 245 /* 246 * Memory was freed successfully so clean up references to it 247 * so on reentry we can tell that this chunk was freed. 248 */ 249 debugfs_remove_recursive(ent->dir); 250 pr_info("Freed trace memory back on node %d\n", ent->nid); 251 ent->size = ent->start = ent->nid = NUMA_NO_NODE; 252 } 253 if (ret) 254 return ret; 255 256 /* If all chunks of memory were freed successfully, reset globals */ 257 kfree(memtrace_array); 258 memtrace_array = NULL; 259 memtrace_size = 0; 260 memtrace_array_nr = 0; 261 return 0; 262 } 263 264 static int memtrace_enable_set(void *data, u64 val) 265 { 266 int rc = -EAGAIN; 267 u64 bytes; 268 269 /* 270 * Don't attempt to do anything if size isn't aligned to a memory 271 * block or equal to zero. 272 */ 273 bytes = memory_block_size_bytes(); 274 if (val & (bytes - 1)) { 275 pr_err("Value must be aligned with 0x%llx\n", bytes); 276 return -EINVAL; 277 } 278 279 mutex_lock(&memtrace_mutex); 280 281 /* Free all previously allocated memory. */ 282 if (memtrace_size && memtrace_free_regions()) 283 goto out_unlock; 284 285 if (!val) { 286 rc = 0; 287 goto out_unlock; 288 } 289 290 /* Allocate memory. */ 291 if (memtrace_init_regions_runtime(val)) 292 goto out_unlock; 293 294 if (memtrace_init_debugfs()) 295 goto out_unlock; 296 297 memtrace_size = val; 298 rc = 0; 299 out_unlock: 300 mutex_unlock(&memtrace_mutex); 301 return rc; 302 } 303 304 static int memtrace_enable_get(void *data, u64 *val) 305 { 306 *val = memtrace_size; 307 return 0; 308 } 309 310 DEFINE_SIMPLE_ATTRIBUTE(memtrace_init_fops, memtrace_enable_get, 311 memtrace_enable_set, "0x%016llx\n"); 312 313 static int memtrace_init(void) 314 { 315 memtrace_debugfs_dir = debugfs_create_dir("memtrace", 316 arch_debugfs_dir); 317 318 debugfs_create_file("enable", 0600, memtrace_debugfs_dir, 319 NULL, &memtrace_init_fops); 320 321 return 0; 322 } 323 machine_device_initcall(powernv, memtrace_init); 324