linux/arch/x86/kernel/setup_percpu.c
<<
>>
Prefs
   1#include <linux/kernel.h>
   2#include <linux/module.h>
   3#include <linux/init.h>
   4#include <linux/bootmem.h>
   5#include <linux/percpu.h>
   6#include <linux/kexec.h>
   7#include <linux/crash_dump.h>
   8#include <linux/smp.h>
   9#include <linux/topology.h>
  10#include <linux/pfn.h>
  11#include <asm/sections.h>
  12#include <asm/processor.h>
  13#include <asm/setup.h>
  14#include <asm/mpspec.h>
  15#include <asm/apicdef.h>
  16#include <asm/highmem.h>
  17#include <asm/proto.h>
  18#include <asm/cpumask.h>
  19#include <asm/cpu.h>
  20#include <asm/stackprotector.h>
  21
  22#ifdef CONFIG_DEBUG_PER_CPU_MAPS
  23# define DBG(x...) printk(KERN_DEBUG x)
  24#else
  25# define DBG(x...)
  26#endif
  27
  28DEFINE_PER_CPU(int, cpu_number);
  29EXPORT_PER_CPU_SYMBOL(cpu_number);
  30
  31#ifdef CONFIG_X86_64
  32#define BOOT_PERCPU_OFFSET ((unsigned long)__per_cpu_load)
  33#else
  34#define BOOT_PERCPU_OFFSET 0
  35#endif
  36
  37DEFINE_PER_CPU(unsigned long, this_cpu_off) = BOOT_PERCPU_OFFSET;
  38EXPORT_PER_CPU_SYMBOL(this_cpu_off);
  39
  40unsigned long __per_cpu_offset[NR_CPUS] __read_mostly = {
  41        [0 ... NR_CPUS-1] = BOOT_PERCPU_OFFSET,
  42};
  43EXPORT_SYMBOL(__per_cpu_offset);
  44
  45/*
  46 * On x86_64 symbols referenced from code should be reachable using
  47 * 32bit relocations.  Reserve space for static percpu variables in
  48 * modules so that they are always served from the first chunk which
  49 * is located at the percpu segment base.  On x86_32, anything can
  50 * address anywhere.  No need to reserve space in the first chunk.
  51 */
  52#ifdef CONFIG_X86_64
  53#define PERCPU_FIRST_CHUNK_RESERVE      PERCPU_MODULE_RESERVE
  54#else
  55#define PERCPU_FIRST_CHUNK_RESERVE      0
  56#endif
  57
  58#ifdef CONFIG_X86_32
  59/**
  60 * pcpu_need_numa - determine percpu allocation needs to consider NUMA
  61 *
  62 * If NUMA is not configured or there is only one NUMA node available,
  63 * there is no reason to consider NUMA.  This function determines
  64 * whether percpu allocation should consider NUMA or not.
  65 *
  66 * RETURNS:
  67 * true if NUMA should be considered; otherwise, false.
  68 */
  69static bool __init pcpu_need_numa(void)
  70{
  71#ifdef CONFIG_NEED_MULTIPLE_NODES
  72        pg_data_t *last = NULL;
  73        unsigned int cpu;
  74
  75        for_each_possible_cpu(cpu) {
  76                int node = early_cpu_to_node(cpu);
  77
  78                if (node_online(node) && NODE_DATA(node) &&
  79                    last && last != NODE_DATA(node))
  80                        return true;
  81
  82                last = NODE_DATA(node);
  83        }
  84#endif
  85        return false;
  86}
  87#endif
  88
  89/**
  90 * pcpu_alloc_bootmem - NUMA friendly alloc_bootmem wrapper for percpu
  91 * @cpu: cpu to allocate for
  92 * @size: size allocation in bytes
  93 * @align: alignment
  94 *
  95 * Allocate @size bytes aligned at @align for cpu @cpu.  This wrapper
  96 * does the right thing for NUMA regardless of the current
  97 * configuration.
  98 *
  99 * RETURNS:
 100 * Pointer to the allocated area on success, NULL on failure.
 101 */
 102static void * __init pcpu_alloc_bootmem(unsigned int cpu, unsigned long size,
 103                                        unsigned long align)
 104{
 105        const unsigned long goal = __pa(MAX_DMA_ADDRESS);
 106#ifdef CONFIG_NEED_MULTIPLE_NODES
 107        int node = early_cpu_to_node(cpu);
 108        void *ptr;
 109
 110        if (!node_online(node) || !NODE_DATA(node)) {
 111                ptr = __alloc_bootmem_nopanic(size, align, goal);
 112                pr_info("cpu %d has no node %d or node-local memory\n",
 113                        cpu, node);
 114                pr_debug("per cpu data for cpu%d %lu bytes at %016lx\n",
 115                         cpu, size, __pa(ptr));
 116        } else {
 117                ptr = __alloc_bootmem_node_nopanic(NODE_DATA(node),
 118                                                   size, align, goal);
 119                pr_debug("per cpu data for cpu%d %lu bytes on node%d at "
 120                         "%016lx\n", cpu, size, node, __pa(ptr));
 121        }
 122        return ptr;
 123#else
 124        return __alloc_bootmem_nopanic(size, align, goal);
 125#endif
 126}
 127
 128/*
 129 * Helpers for first chunk memory allocation
 130 */
 131static void * __init pcpu_fc_alloc(unsigned int cpu, size_t size, size_t align)
 132{
 133        return pcpu_alloc_bootmem(cpu, size, align);
 134}
 135
 136static void __init pcpu_fc_free(void *ptr, size_t size)
 137{
 138        free_bootmem(__pa(ptr), size);
 139}
 140
 141static int __init pcpu_cpu_distance(unsigned int from, unsigned int to)
 142{
 143#ifdef CONFIG_NEED_MULTIPLE_NODES
 144        if (early_cpu_to_node(from) == early_cpu_to_node(to))
 145                return LOCAL_DISTANCE;
 146        else
 147                return REMOTE_DISTANCE;
 148#else
 149        return LOCAL_DISTANCE;
 150#endif
 151}
 152
 153static void __init pcpup_populate_pte(unsigned long addr)
 154{
 155        populate_extra_pte(addr);
 156}
 157
 158static inline void setup_percpu_segment(int cpu)
 159{
 160#ifdef CONFIG_X86_32
 161        struct desc_struct gdt;
 162
 163        pack_descriptor(&gdt, per_cpu_offset(cpu), 0xFFFFF,
 164                        0x2 | DESCTYPE_S, 0x8);
 165        gdt.s = 1;
 166        write_gdt_entry(get_cpu_gdt_table(cpu),
 167                        GDT_ENTRY_PERCPU, &gdt, DESCTYPE_S);
 168#endif
 169}
 170
 171void __init setup_per_cpu_areas(void)
 172{
 173        unsigned int cpu;
 174        unsigned long delta;
 175        int rc;
 176
 177        pr_info("NR_CPUS:%d nr_cpumask_bits:%d nr_cpu_ids:%d nr_node_ids:%d\n",
 178                NR_CPUS, nr_cpumask_bits, nr_cpu_ids, nr_node_ids);
 179
 180        /*
 181         * Allocate percpu area.  Embedding allocator is our favorite;
 182         * however, on NUMA configurations, it can result in very
 183         * sparse unit mapping and vmalloc area isn't spacious enough
 184         * on 32bit.  Use page in that case.
 185         */
 186#ifdef CONFIG_X86_32
 187        if (pcpu_chosen_fc == PCPU_FC_AUTO && pcpu_need_numa())
 188                pcpu_chosen_fc = PCPU_FC_PAGE;
 189#endif
 190        rc = -EINVAL;
 191        if (pcpu_chosen_fc != PCPU_FC_PAGE) {
 192                const size_t atom_size = cpu_has_pse ? PMD_SIZE : PAGE_SIZE;
 193                const size_t dyn_size = PERCPU_MODULE_RESERVE +
 194                        PERCPU_DYNAMIC_RESERVE - PERCPU_FIRST_CHUNK_RESERVE;
 195
 196                rc = pcpu_embed_first_chunk(PERCPU_FIRST_CHUNK_RESERVE,
 197                                            dyn_size, atom_size,
 198                                            pcpu_cpu_distance,
 199                                            pcpu_fc_alloc, pcpu_fc_free);
 200                if (rc < 0)
 201                        pr_warning("PERCPU: %s allocator failed (%d), "
 202                                   "falling back to page size\n",
 203                                   pcpu_fc_names[pcpu_chosen_fc], rc);
 204        }
 205        if (rc < 0)
 206                rc = pcpu_page_first_chunk(PERCPU_FIRST_CHUNK_RESERVE,
 207                                           pcpu_fc_alloc, pcpu_fc_free,
 208                                           pcpup_populate_pte);
 209        if (rc < 0)
 210                panic("cannot initialize percpu area (err=%d)", rc);
 211
 212        /* alrighty, percpu areas up and running */
 213        delta = (unsigned long)pcpu_base_addr - (unsigned long)__per_cpu_start;
 214        for_each_possible_cpu(cpu) {
 215                per_cpu_offset(cpu) = delta + pcpu_unit_offsets[cpu];
 216                per_cpu(this_cpu_off, cpu) = per_cpu_offset(cpu);
 217                per_cpu(cpu_number, cpu) = cpu;
 218                setup_percpu_segment(cpu);
 219                setup_stack_canary_segment(cpu);
 220                /*
 221                 * Copy data used in early init routines from the
 222                 * initial arrays to the per cpu data areas.  These
 223                 * arrays then become expendable and the *_early_ptr's
 224                 * are zeroed indicating that the static arrays are
 225                 * gone.
 226                 */
 227#ifdef CONFIG_X86_LOCAL_APIC
 228                per_cpu(x86_cpu_to_apicid, cpu) =
 229                        early_per_cpu_map(x86_cpu_to_apicid, cpu);
 230                per_cpu(x86_bios_cpu_apicid, cpu) =
 231                        early_per_cpu_map(x86_bios_cpu_apicid, cpu);
 232#endif
 233#ifdef CONFIG_X86_64
 234                per_cpu(irq_stack_ptr, cpu) =
 235                        per_cpu(irq_stack_union.irq_stack, cpu) +
 236                        IRQ_STACK_SIZE - 64;
 237#ifdef CONFIG_NUMA
 238                per_cpu(x86_cpu_to_node_map, cpu) =
 239                        early_per_cpu_map(x86_cpu_to_node_map, cpu);
 240#endif
 241#endif
 242                /*
 243                 * Up to this point, the boot CPU has been using .data.init
 244                 * area.  Reload any changed state for the boot CPU.
 245                 */
 246                if (cpu == boot_cpu_id)
 247                        switch_to_new_gdt(cpu);
 248        }
 249
 250        /* indicate the early static arrays will soon be gone */
 251#ifdef CONFIG_X86_LOCAL_APIC
 252        early_per_cpu_ptr(x86_cpu_to_apicid) = NULL;
 253        early_per_cpu_ptr(x86_bios_cpu_apicid) = NULL;
 254#endif
 255#if defined(CONFIG_X86_64) && defined(CONFIG_NUMA)
 256        early_per_cpu_ptr(x86_cpu_to_node_map) = NULL;
 257#endif
 258
 259#if defined(CONFIG_X86_64) && defined(CONFIG_NUMA)
 260        /*
 261         * make sure boot cpu node_number is right, when boot cpu is on the
 262         * node that doesn't have mem installed
 263         */
 264        per_cpu(node_number, boot_cpu_id) = cpu_to_node(boot_cpu_id);
 265#endif
 266
 267        /* Setup node to cpumask map */
 268        setup_node_to_cpumask_map();
 269
 270        /* Setup cpu initialized, callin, callout masks */
 271        setup_cpu_local_masks();
 272}
 273