linux/arch/s390/numa/numa.c
<<
>>
Prefs
   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