root/arch/arm64/kernel/acpi_numa.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. acpi_numa_get_nid
  2. get_cpu_for_acpi_id
  3. acpi_parse_gicc_pxm
  4. acpi_map_cpus_to_nodes
  5. acpi_numa_gicc_affinity_init
  6. arm64_acpi_numa_init

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * ACPI 5.1 based NUMA setup for ARM64
   4  * Lots of code was borrowed from arch/x86/mm/srat.c
   5  *
   6  * Copyright 2004 Andi Kleen, SuSE Labs.
   7  * Copyright (C) 2013-2016, Linaro Ltd.
   8  *              Author: Hanjun Guo <hanjun.guo@linaro.org>
   9  *
  10  * Reads the ACPI SRAT table to figure out what memory belongs to which CPUs.
  11  *
  12  * Called from acpi_numa_init while reading the SRAT and SLIT tables.
  13  * Assumes all memory regions belonging to a single proximity domain
  14  * are in one chunk. Holes between them will be included in the node.
  15  */
  16 
  17 #define pr_fmt(fmt) "ACPI: NUMA: " fmt
  18 
  19 #include <linux/acpi.h>
  20 #include <linux/bitmap.h>
  21 #include <linux/kernel.h>
  22 #include <linux/mm.h>
  23 #include <linux/memblock.h>
  24 #include <linux/mmzone.h>
  25 #include <linux/module.h>
  26 #include <linux/topology.h>
  27 
  28 #include <asm/numa.h>
  29 
  30 static int acpi_early_node_map[NR_CPUS] __initdata = { NUMA_NO_NODE };
  31 
  32 int __init acpi_numa_get_nid(unsigned int cpu)
  33 {
  34         return acpi_early_node_map[cpu];
  35 }
  36 
  37 static inline int get_cpu_for_acpi_id(u32 uid)
  38 {
  39         int cpu;
  40 
  41         for (cpu = 0; cpu < nr_cpu_ids; cpu++)
  42                 if (uid == get_acpi_id_for_cpu(cpu))
  43                         return cpu;
  44 
  45         return -EINVAL;
  46 }
  47 
  48 static int __init acpi_parse_gicc_pxm(union acpi_subtable_headers *header,
  49                                       const unsigned long end)
  50 {
  51         struct acpi_srat_gicc_affinity *pa;
  52         int cpu, pxm, node;
  53 
  54         if (srat_disabled())
  55                 return -EINVAL;
  56 
  57         pa = (struct acpi_srat_gicc_affinity *)header;
  58         if (!pa)
  59                 return -EINVAL;
  60 
  61         if (!(pa->flags & ACPI_SRAT_GICC_ENABLED))
  62                 return 0;
  63 
  64         pxm = pa->proximity_domain;
  65         node = pxm_to_node(pxm);
  66 
  67         /*
  68          * If we can't map the UID to a logical cpu this
  69          * means that the UID is not part of possible cpus
  70          * so we do not need a NUMA mapping for it, skip
  71          * the SRAT entry and keep parsing.
  72          */
  73         cpu = get_cpu_for_acpi_id(pa->acpi_processor_uid);
  74         if (cpu < 0)
  75                 return 0;
  76 
  77         acpi_early_node_map[cpu] = node;
  78         pr_info("SRAT: PXM %d -> MPIDR 0x%llx -> Node %d\n", pxm,
  79                 cpu_logical_map(cpu), node);
  80 
  81         return 0;
  82 }
  83 
  84 void __init acpi_map_cpus_to_nodes(void)
  85 {
  86         acpi_table_parse_entries(ACPI_SIG_SRAT, sizeof(struct acpi_table_srat),
  87                                             ACPI_SRAT_TYPE_GICC_AFFINITY,
  88                                             acpi_parse_gicc_pxm, 0);
  89 }
  90 
  91 /* Callback for Proximity Domain -> ACPI processor UID mapping */
  92 void __init acpi_numa_gicc_affinity_init(struct acpi_srat_gicc_affinity *pa)
  93 {
  94         int pxm, node;
  95 
  96         if (srat_disabled())
  97                 return;
  98 
  99         if (pa->header.length < sizeof(struct acpi_srat_gicc_affinity)) {
 100                 pr_err("SRAT: Invalid SRAT header length: %d\n",
 101                         pa->header.length);
 102                 bad_srat();
 103                 return;
 104         }
 105 
 106         if (!(pa->flags & ACPI_SRAT_GICC_ENABLED))
 107                 return;
 108 
 109         pxm = pa->proximity_domain;
 110         node = acpi_map_pxm_to_node(pxm);
 111 
 112         if (node == NUMA_NO_NODE || node >= MAX_NUMNODES) {
 113                 pr_err("SRAT: Too many proximity domains %d\n", pxm);
 114                 bad_srat();
 115                 return;
 116         }
 117 
 118         node_set(node, numa_nodes_parsed);
 119 }
 120 
 121 int __init arm64_acpi_numa_init(void)
 122 {
 123         int ret;
 124 
 125         ret = acpi_numa_init();
 126         if (ret) {
 127                 pr_info("Failed to initialise from firmware\n");
 128                 return ret;
 129         }
 130 
 131         return srat_disabled() ? -EINVAL : 0;
 132 }

/* [<][>][^][v][top][bottom][index][help] */