Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86, NUMA: Enable emulation on 32bit too

Now that NUMA init path is unified, NUMA emulation can be enabled on
32bit. Make numa_emluation.c safe on 32bit by doing the followings.

* Define MAX_DMA32_PFN on 32bit too.

* Include bootmem.h for max_pfn declaration.

* Use u64 explicitly and always use PFN_PHYS() when converting page
number to address.

* Avoid __udivdi3() generation on 32bit by doing number of pages
calculation instead in split_nodes_interleave().

And drop X86_64 dependency from Kconfig.

Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Yinghai Lu <yinghai@kernel.org>
Cc: David Rientjes <rientjes@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>

Tejun Heo 1b7e03ef 2706a0bf

+16 -14
+1 -1
arch/x86/Kconfig
··· 1201 1201 1202 1202 config NUMA_EMU 1203 1203 bool "NUMA emulation" 1204 - depends on X86_64 && NUMA 1204 + depends on NUMA 1205 1205 ---help--- 1206 1206 Enable NUMA emulation. A flat machine will be split 1207 1207 into virtual nodes when booted with "numa=fake=N", where N is the
+4 -8
arch/x86/include/asm/dma.h
··· 72 72 /* 16MB ISA DMA zone */ 73 73 #define MAX_DMA_PFN ((16 * 1024 * 1024) >> PAGE_SHIFT) 74 74 75 - #ifdef CONFIG_X86_32 76 - 77 - /* The maximum address that we can perform a DMA transfer to on this platform */ 78 - #define MAX_DMA_ADDRESS (PAGE_OFFSET + 0x1000000) 79 - 80 - #else 81 - 82 75 /* 4GB broken PCI/AGP hardware bus master zone */ 83 76 #define MAX_DMA32_PFN ((4UL * 1024 * 1024 * 1024) >> PAGE_SHIFT) 84 77 78 + #ifdef CONFIG_X86_32 79 + /* The maximum address that we can perform a DMA transfer to on this platform */ 80 + #define MAX_DMA_ADDRESS (PAGE_OFFSET + 0x1000000) 81 + #else 85 82 /* Compat define for old dma zone */ 86 83 #define MAX_DMA_ADDRESS ((unsigned long)__va(MAX_DMA_PFN << PAGE_SHIFT)) 87 - 88 84 #endif 89 85 90 86 /* 8237 DMA controllers */
+11 -5
arch/x86/mm/numa_emulation.c
··· 5 5 #include <linux/errno.h> 6 6 #include <linux/topology.h> 7 7 #include <linux/memblock.h> 8 + #include <linux/bootmem.h> 8 9 #include <asm/dma.h> 9 10 10 11 #include "numa_internal.h" ··· 85 84 nr_nodes = MAX_NUMNODES; 86 85 } 87 86 88 - size = (max_addr - addr - memblock_x86_hole_size(addr, max_addr)) / nr_nodes; 87 + /* 88 + * Calculate target node size. x86_32 freaks on __udivdi3() so do 89 + * the division in ulong number of pages and convert back. 90 + */ 91 + size = max_addr - addr - memblock_x86_hole_size(addr, max_addr); 92 + size = PFN_PHYS((unsigned long)(size >> PAGE_SHIFT) / nr_nodes); 93 + 89 94 /* 90 95 * Calculate the number of big nodes that can be allocated as a result 91 96 * of consolidating the remainder. ··· 233 226 */ 234 227 while (nodes_weight(physnode_mask)) { 235 228 for_each_node_mask(i, physnode_mask) { 236 - u64 dma32_end = MAX_DMA32_PFN << PAGE_SHIFT; 229 + u64 dma32_end = PFN_PHYS(MAX_DMA32_PFN); 237 230 u64 start, limit, end; 238 231 int phys_blk; 239 232 ··· 305 298 { 306 299 static struct numa_meminfo ei __initdata; 307 300 static struct numa_meminfo pi __initdata; 308 - const u64 max_addr = max_pfn << PAGE_SHIFT; 301 + const u64 max_addr = PFN_PHYS(max_pfn); 309 302 u8 *phys_dist = NULL; 310 303 size_t phys_size = numa_dist_cnt * numa_dist_cnt * sizeof(phys_dist[0]); 311 304 int max_emu_nid, dfl_phys_nid; ··· 349 342 if (numa_dist_cnt) { 350 343 u64 phys; 351 344 352 - phys = memblock_find_in_range(0, 353 - (u64)max_pfn_mapped << PAGE_SHIFT, 345 + phys = memblock_find_in_range(0, PFN_PHYS(max_pfn_mapped), 354 346 phys_size, PAGE_SIZE); 355 347 if (phys == MEMBLOCK_ERROR) { 356 348 pr_warning("NUMA: Warning: can't allocate copy of distance table, disabling emulation\n");