1212#include <linux/memblock.h>
1313#include <linux/module.h>
1414#include <linux/of.h>
15+ #include <linux/numa_memblks.h>
1516
1617#include <asm/sections.h>
1718
18- nodemask_t numa_nodes_parsed __initdata ;
1919static int cpu_to_node_map [NR_CPUS ] = { [0 ... NR_CPUS - 1 ] = NUMA_NO_NODE };
2020
21- static int numa_distance_cnt ;
22- static u8 * numa_distance ;
2321bool numa_off ;
2422
2523static __init int numa_parse_early_param (char * opt )
@@ -28,6 +26,8 @@ static __init int numa_parse_early_param(char *opt)
2826 return - EINVAL ;
2927 if (str_has_prefix (opt , "off" ))
3028 numa_off = true;
29+ if (!strncmp (opt , "fake=" , 5 ))
30+ return numa_emu_cmdline (opt + 5 );
3131
3232 return 0 ;
3333}
@@ -59,6 +59,7 @@ EXPORT_SYMBOL(cpumask_of_node);
5959
6060#endif
6161
62+ #ifndef CONFIG_NUMA_EMU
6263static void numa_update_cpu (unsigned int cpu , bool remove )
6364{
6465 int nid = cpu_to_node (cpu );
@@ -81,6 +82,7 @@ void numa_remove_cpu(unsigned int cpu)
8182{
8283 numa_update_cpu (cpu , true);
8384}
85+ #endif
8486
8587void numa_clear_node (unsigned int cpu )
8688{
@@ -142,7 +144,7 @@ void __init early_map_cpu_to_node(unsigned int cpu, int nid)
142144unsigned long __per_cpu_offset [NR_CPUS ] __read_mostly ;
143145EXPORT_SYMBOL (__per_cpu_offset );
144146
145- int __init early_cpu_to_node (int cpu )
147+ int early_cpu_to_node (int cpu )
146148{
147149 return cpu_to_node_map [cpu ];
148150}
@@ -187,30 +189,6 @@ void __init setup_per_cpu_areas(void)
187189}
188190#endif
189191
190- /**
191- * numa_add_memblk() - Set node id to memblk
192- * @nid: NUMA node ID of the new memblk
193- * @start: Start address of the new memblk
194- * @end: End address of the new memblk
195- *
196- * RETURNS:
197- * 0 on success, -errno on failure.
198- */
199- int __init numa_add_memblk (int nid , u64 start , u64 end )
200- {
201- int ret ;
202-
203- ret = memblock_set_node (start , (end - start ), & memblock .memory , nid );
204- if (ret < 0 ) {
205- pr_err ("memblock [0x%llx - 0x%llx] failed to add on node %d\n" ,
206- start , (end - 1 ), nid );
207- return ret ;
208- }
209-
210- node_set (nid , numa_nodes_parsed );
211- return ret ;
212- }
213-
214192/*
215193 * Initialize NODE_DATA for a node on the local memory
216194 */
@@ -226,116 +204,9 @@ static void __init setup_node_data(int nid, u64 start_pfn, u64 end_pfn)
226204 NODE_DATA (nid )-> node_spanned_pages = end_pfn - start_pfn ;
227205}
228206
229- /*
230- * numa_free_distance
231- *
232- * The current table is freed.
233- */
234- void __init numa_free_distance (void )
235- {
236- size_t size ;
237-
238- if (!numa_distance )
239- return ;
240-
241- size = numa_distance_cnt * numa_distance_cnt *
242- sizeof (numa_distance [0 ]);
243-
244- memblock_free (numa_distance , size );
245- numa_distance_cnt = 0 ;
246- numa_distance = NULL ;
247- }
248-
249- /*
250- * Create a new NUMA distance table.
251- */
252- static int __init numa_alloc_distance (void )
253- {
254- size_t size ;
255- int i , j ;
256-
257- size = nr_node_ids * nr_node_ids * sizeof (numa_distance [0 ]);
258- numa_distance = memblock_alloc (size , PAGE_SIZE );
259- if (WARN_ON (!numa_distance ))
260- return - ENOMEM ;
261-
262- numa_distance_cnt = nr_node_ids ;
263-
264- /* fill with the default distances */
265- for (i = 0 ; i < numa_distance_cnt ; i ++ )
266- for (j = 0 ; j < numa_distance_cnt ; j ++ )
267- numa_distance [i * numa_distance_cnt + j ] = i == j ?
268- LOCAL_DISTANCE : REMOTE_DISTANCE ;
269-
270- pr_debug ("Initialized distance table, cnt=%d\n" , numa_distance_cnt );
271-
272- return 0 ;
273- }
274-
275- /**
276- * numa_set_distance() - Set inter node NUMA distance from node to node.
277- * @from: the 'from' node to set distance
278- * @to: the 'to' node to set distance
279- * @distance: NUMA distance
280- *
281- * Set the distance from node @from to @to to @distance.
282- * If distance table doesn't exist, a warning is printed.
283- *
284- * If @from or @to is higher than the highest known node or lower than zero
285- * or @distance doesn't make sense, the call is ignored.
286- */
287- void __init numa_set_distance (int from , int to , int distance )
288- {
289- if (!numa_distance ) {
290- pr_warn_once ("Warning: distance table not allocated yet\n" );
291- return ;
292- }
293-
294- if (from >= numa_distance_cnt || to >= numa_distance_cnt ||
295- from < 0 || to < 0 ) {
296- pr_warn_once ("Warning: node ids are out of bound, from=%d to=%d distance=%d\n" ,
297- from , to , distance );
298- return ;
299- }
300-
301- if ((u8 )distance != distance ||
302- (from == to && distance != LOCAL_DISTANCE )) {
303- pr_warn_once ("Warning: invalid distance parameter, from=%d to=%d distance=%d\n" ,
304- from , to , distance );
305- return ;
306- }
307-
308- numa_distance [from * numa_distance_cnt + to ] = distance ;
309- }
310-
311- /*
312- * Return NUMA distance @from to @to
313- */
314- int __node_distance (int from , int to )
315- {
316- if (from >= numa_distance_cnt || to >= numa_distance_cnt )
317- return from == to ? LOCAL_DISTANCE : REMOTE_DISTANCE ;
318- return numa_distance [from * numa_distance_cnt + to ];
319- }
320- EXPORT_SYMBOL (__node_distance );
321-
322207static int __init numa_register_nodes (void )
323208{
324209 int nid ;
325- struct memblock_region * mblk ;
326-
327- /* Check that valid nid is set to memblks */
328- for_each_mem_region (mblk ) {
329- int mblk_nid = memblock_get_region_node (mblk );
330- phys_addr_t start = mblk -> base ;
331- phys_addr_t end = mblk -> base + mblk -> size - 1 ;
332-
333- if (mblk_nid == NUMA_NO_NODE || mblk_nid >= MAX_NUMNODES ) {
334- pr_warn ("Warning: invalid memblk node %d [mem %pap-%pap]\n" ,
335- mblk_nid , & start , & end );
336- return - EINVAL ;
337- }
338- }
339210
340211 /* Finally register nodes. */
341212 for_each_node_mask (nid , numa_nodes_parsed ) {
@@ -360,11 +231,7 @@ static int __init numa_init(int (*init_func)(void))
360231 nodes_clear (node_possible_map );
361232 nodes_clear (node_online_map );
362233
363- ret = numa_alloc_distance ();
364- if (ret < 0 )
365- return ret ;
366-
367- ret = init_func ();
234+ ret = numa_memblks_init (init_func , /* memblock_force_top_down */ false);
368235 if (ret < 0 )
369236 goto out_free_distance ;
370237
@@ -382,7 +249,7 @@ static int __init numa_init(int (*init_func)(void))
382249
383250 return 0 ;
384251out_free_distance :
385- numa_free_distance ();
252+ numa_reset_distance ();
386253 return ret ;
387254}
388255
@@ -412,6 +279,7 @@ static int __init dummy_numa_init(void)
412279 pr_err ("NUMA init failed\n" );
413280 return ret ;
414281 }
282+ node_set (0 , numa_nodes_parsed );
415283
416284 numa_off = true;
417285 return 0 ;
@@ -454,3 +322,54 @@ void __init arch_numa_init(void)
454322
455323 numa_init (dummy_numa_init );
456324}
325+
326+ #ifdef CONFIG_NUMA_EMU
327+ void __init numa_emu_update_cpu_to_node (int * emu_nid_to_phys ,
328+ unsigned int nr_emu_nids )
329+ {
330+ int i , j ;
331+
332+ /*
333+ * Transform cpu_to_node_map table to use emulated nids by
334+ * reverse-mapping phys_nid. The maps should always exist but fall
335+ * back to zero just in case.
336+ */
337+ for (i = 0 ; i < ARRAY_SIZE (cpu_to_node_map ); i ++ ) {
338+ if (cpu_to_node_map [i ] == NUMA_NO_NODE )
339+ continue ;
340+ for (j = 0 ; j < nr_emu_nids ; j ++ )
341+ if (cpu_to_node_map [i ] == emu_nid_to_phys [j ])
342+ break ;
343+ cpu_to_node_map [i ] = j < nr_emu_nids ? j : 0 ;
344+ }
345+ }
346+
347+ u64 __init numa_emu_dma_end (void )
348+ {
349+ return memblock_start_of_DRAM () + SZ_4G ;
350+ }
351+
352+ void debug_cpumask_set_cpu (unsigned int cpu , int node , bool enable )
353+ {
354+ struct cpumask * mask ;
355+
356+ if (node == NUMA_NO_NODE )
357+ return ;
358+
359+ mask = node_to_cpumask_map [node ];
360+ if (!cpumask_available (mask )) {
361+ pr_err ("node_to_cpumask_map[%i] NULL\n" , node );
362+ dump_stack ();
363+ return ;
364+ }
365+
366+ if (enable )
367+ cpumask_set_cpu (cpu , mask );
368+ else
369+ cpumask_clear_cpu (cpu , mask );
370+
371+ pr_debug ("%s cpu %d node %d: mask now %*pbl\n" ,
372+ enable ? "numa_add_cpu" : "numa_remove_cpu" ,
373+ cpu , node , cpumask_pr_args (mask ));
374+ }
375+ #endif /* CONFIG_NUMA_EMU */
0 commit comments