1/* 2 * NUMA support for s390 3 * 4 * Implement NUMA core code. 5 * 6 * Copyright IBM Corp. 2015 7 */ 8 9#define KMSG_COMPONENT "numa" 10#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 11 12#include <linux/kernel.h> 13#include <linux/mmzone.h> 14#include <linux/cpumask.h> 15#include <linux/bootmem.h> 16#include <linux/memblock.h> 17#include <linux/slab.h> 18#include <linux/node.h> 19 20#include <asm/numa.h> 21#include "numa_mode.h" 22 23pg_data_t *node_data[MAX_NUMNODES]; 24EXPORT_SYMBOL(node_data); 25 26cpumask_t node_to_cpumask_map[MAX_NUMNODES]; 27EXPORT_SYMBOL(node_to_cpumask_map); 28 29const struct numa_mode numa_mode_plain = { 30 .name = "plain", 31}; 32 33static const struct numa_mode *mode = &numa_mode_plain; 34 35int numa_pfn_to_nid(unsigned long pfn) 36{ 37 return mode->__pfn_to_nid ? mode->__pfn_to_nid(pfn) : 0; 38} 39 40void numa_update_cpu_topology(void) 41{ 42 if (mode->update_cpu_topology) 43 mode->update_cpu_topology(); 44} 45 46int __node_distance(int a, int b) 47{ 48 return mode->distance ? mode->distance(a, b) : 0; 49} 50 51int numa_debug_enabled; 52 53/* 54 * alloc_node_data() - Allocate node data 55 */ 56static __init pg_data_t *alloc_node_data(void) 57{ 58 pg_data_t *res; 59 60 res = (pg_data_t *) memblock_alloc(sizeof(pg_data_t), 1); 61 if (!res) 62 panic("Could not allocate memory for node data!\n"); 63 memset(res, 0, sizeof(pg_data_t)); 64 return res; 65} 66 67/* 68 * numa_setup_memory() - Assign bootmem to nodes 69 * 70 * The memory is first added to memblock without any respect to nodes. 71 * This is fixed before remaining memblock memory is handed over to the 72 * buddy allocator. 73 * An important side effect is that large bootmem allocations might easily 74 * cross node boundaries, which can be needed for large allocations with 75 * smaller memory stripes in each node (i.e. when using NUMA emulation). 76 * 77 * Memory defines nodes: 78 * Therefore this routine also sets the nodes online with memory. 79 */ 80static void __init numa_setup_memory(void) 81{ 82 unsigned long cur_base, align, end_of_dram; 83 int nid = 0; 84 85 end_of_dram = memblock_end_of_DRAM(); 86 align = mode->align ? mode->align() : ULONG_MAX; 87 88 /* 89 * Step through all available memory and assign it to the nodes 90 * indicated by the mode implementation. 91 * All nodes which are seen here will be set online. 92 */ 93 cur_base = 0; 94 do { 95 nid = numa_pfn_to_nid(PFN_DOWN(cur_base)); 96 node_set_online(nid); 97 memblock_set_node(cur_base, align, &memblock.memory, nid); 98 cur_base += align; 99 } while (cur_base < end_of_dram); 100 101 /* Allocate and fill out node_data */ 102 for (nid = 0; nid < MAX_NUMNODES; nid++) 103 NODE_DATA(nid) = alloc_node_data(); 104 105 for_each_online_node(nid) { 106 unsigned long start_pfn, end_pfn; 107 unsigned long t_start, t_end; 108 int i; 109 110 start_pfn = ULONG_MAX; 111 end_pfn = 0; 112 for_each_mem_pfn_range(i, nid, &t_start, &t_end, NULL) { 113 if (t_start < start_pfn) 114 start_pfn = t_start; 115 if (t_end > end_pfn) 116 end_pfn = t_end; 117 } 118 NODE_DATA(nid)->node_spanned_pages = end_pfn - start_pfn; 119 NODE_DATA(nid)->node_id = nid; 120 } 121} 122 123/* 124 * numa_setup() - Earliest initialization 125 * 126 * Assign the mode and call the mode's setup routine. 127 */ 128void __init numa_setup(void) 129{ 130 pr_info("NUMA mode: %s\n", mode->name); 131 if (mode->setup) 132 mode->setup(); 133 numa_setup_memory(); 134 memblock_dump_all(); 135} 136 137 138/* 139 * numa_init_early() - Initialization initcall 140 * 141 * This runs when only one CPU is online and before the first 142 * topology update is called for by the scheduler. 143 */ 144static int __init numa_init_early(void) 145{ 146 /* Attach all possible CPUs to node 0 for now. */ 147 cpumask_copy(&node_to_cpumask_map[0], cpu_possible_mask); 148 return 0; 149} 150early_initcall(numa_init_early); 151 152/* 153 * numa_init_late() - Initialization initcall 154 * 155 * Register NUMA nodes. 156 */ 157static int __init numa_init_late(void) 158{ 159 int nid; 160 161 for_each_online_node(nid) 162 register_one_node(nid); 163 return 0; 164} 165device_initcall(numa_init_late); 166 167static int __init parse_debug(char *parm) 168{ 169 numa_debug_enabled = 1; 170 return 0; 171} 172early_param("numa_debug", parse_debug); 173 174static int __init parse_numa(char *parm) 175{ 176 if (strcmp(parm, numa_mode_plain.name) == 0) 177 mode = &numa_mode_plain; 178#ifdef CONFIG_NUMA_EMU 179 if (strcmp(parm, numa_mode_emu.name) == 0) 180 mode = &numa_mode_emu; 181#endif 182 return 0; 183} 184early_param("numa", parse_numa); 185