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), 8);
  61        memset(res, 0, sizeof(pg_data_t));
  62        return res;
  63}
  64
  65/*
  66 * numa_setup_memory() - Assign bootmem to nodes
  67 *
  68 * The memory is first added to memblock without any respect to nodes.
  69 * This is fixed before remaining memblock memory is handed over to the
  70 * buddy allocator.
  71 * An important side effect is that large bootmem allocations might easily
  72 * cross node boundaries, which can be needed for large allocations with
  73 * smaller memory stripes in each node (i.e. when using NUMA emulation).
  74 *
  75 * Memory defines nodes:
  76 * Therefore this routine also sets the nodes online with memory.
  77 */
  78static void __init numa_setup_memory(void)
  79{
  80        unsigned long cur_base, align, end_of_dram;
  81        int nid = 0;
  82
  83        end_of_dram = memblock_end_of_DRAM();
  84        align = mode->align ? mode->align() : ULONG_MAX;
  85
  86        /*
  87         * Step through all available memory and assign it to the nodes
  88         * indicated by the mode implementation.
  89         * All nodes which are seen here will be set online.
  90         */
  91        cur_base = 0;
  92        do {
  93                nid = numa_pfn_to_nid(PFN_DOWN(cur_base));
  94                node_set_online(nid);
  95                memblock_set_node(cur_base, align, &memblock.memory, nid);
  96                cur_base += align;
  97        } while (cur_base < end_of_dram);
  98
  99        /* Allocate and fill out node_data */
 100        for (nid = 0; nid < MAX_NUMNODES; nid++)
 101                NODE_DATA(nid) = alloc_node_data();
 102
 103        for_each_online_node(nid) {
 104                unsigned long start_pfn, end_pfn;
 105                unsigned long t_start, t_end;
 106                int i;
 107
 108                start_pfn = ULONG_MAX;
 109                end_pfn = 0;
 110                for_each_mem_pfn_range(i, nid, &t_start, &t_end, NULL) {
 111                        if (t_start < start_pfn)
 112                                start_pfn = t_start;
 113                        if (t_end > end_pfn)
 114                                end_pfn = t_end;
 115                }
 116                NODE_DATA(nid)->node_spanned_pages = end_pfn - start_pfn;
 117                NODE_DATA(nid)->node_id = nid;
 118        }
 119}
 120
 121/*
 122 * numa_setup() - Earliest initialization
 123 *
 124 * Assign the mode and call the mode's setup routine.
 125 */
 126void __init numa_setup(void)
 127{
 128        pr_info("NUMA mode: %s\n", mode->name);
 129        if (mode->setup)
 130                mode->setup();
 131        numa_setup_memory();
 132        memblock_dump_all();
 133}
 134
 135
 136/*
 137 * numa_init_early() - Initialization initcall
 138 *
 139 * This runs when only one CPU is online and before the first
 140 * topology update is called for by the scheduler.
 141 */
 142static int __init numa_init_early(void)
 143{
 144        /* Attach all possible CPUs to node 0 for now. */
 145        cpumask_copy(&node_to_cpumask_map[0], cpu_possible_mask);
 146        return 0;
 147}
 148early_initcall(numa_init_early);
 149
 150/*
 151 * numa_init_late() - Initialization initcall
 152 *
 153 * Register NUMA nodes.
 154 */
 155static int __init numa_init_late(void)
 156{
 157        int nid;
 158
 159        for_each_online_node(nid)
 160                register_one_node(nid);
 161        return 0;
 162}
 163arch_initcall(numa_init_late);
 164
 165static int __init parse_debug(char *parm)
 166{
 167        numa_debug_enabled = 1;
 168        return 0;
 169}
 170early_param("numa_debug", parse_debug);
 171
 172static int __init parse_numa(char *parm)
 173{
 174        if (strcmp(parm, numa_mode_plain.name) == 0)
 175                mode = &numa_mode_plain;
 176#ifdef CONFIG_NUMA_EMU
 177        if (strcmp(parm, numa_mode_emu.name) == 0)
 178                mode = &numa_mode_emu;
 179#endif
 180        return 0;
 181}
 182early_param("numa", parse_numa);
 183