root/arch/mips/loongson64/loongson-3/numa.c

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

DEFINITIONS

This source file includes following definitions.
  1. enable_lpa
  2. cpu_node_probe
  3. compute_node_distance
  4. init_topology_matrix
  5. nid_to_addroffset
  6. szmem
  7. node_mem_init
  8. prom_meminit
  9. paging_init
  10. mem_init
  11. pcibus_to_node
  12. prom_init_numa_memory

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Copyright (C) 2010 Loongson Inc. & Lemote Inc. &
   4  *                    Institute of Computing Technology
   5  * Author:  Xiang Gao, gaoxiang@ict.ac.cn
   6  *          Huacai Chen, chenhc@lemote.com
   7  *          Xiaofu Meng, Shuangshuang Zhang
   8  */
   9 #include <linux/init.h>
  10 #include <linux/kernel.h>
  11 #include <linux/mm.h>
  12 #include <linux/mmzone.h>
  13 #include <linux/export.h>
  14 #include <linux/nodemask.h>
  15 #include <linux/swap.h>
  16 #include <linux/memblock.h>
  17 #include <linux/pfn.h>
  18 #include <linux/highmem.h>
  19 #include <asm/page.h>
  20 #include <asm/pgalloc.h>
  21 #include <asm/sections.h>
  22 #include <linux/irq.h>
  23 #include <asm/bootinfo.h>
  24 #include <asm/mc146818-time.h>
  25 #include <asm/time.h>
  26 #include <asm/wbflush.h>
  27 #include <boot_param.h>
  28 
  29 static struct node_data prealloc__node_data[MAX_NUMNODES];
  30 unsigned char __node_distances[MAX_NUMNODES][MAX_NUMNODES];
  31 EXPORT_SYMBOL(__node_distances);
  32 struct node_data *__node_data[MAX_NUMNODES];
  33 EXPORT_SYMBOL(__node_data);
  34 
  35 static void enable_lpa(void)
  36 {
  37         unsigned long value;
  38 
  39         value = __read_32bit_c0_register($16, 3);
  40         value |= 0x00000080;
  41         __write_32bit_c0_register($16, 3, value);
  42         value = __read_32bit_c0_register($16, 3);
  43         pr_info("CP0_Config3: CP0 16.3 (0x%lx)\n", value);
  44 
  45         value = __read_32bit_c0_register($5, 1);
  46         value |= 0x20000000;
  47         __write_32bit_c0_register($5, 1, value);
  48         value = __read_32bit_c0_register($5, 1);
  49         pr_info("CP0_PageGrain: CP0 5.1 (0x%lx)\n", value);
  50 }
  51 
  52 static void cpu_node_probe(void)
  53 {
  54         int i;
  55 
  56         nodes_clear(node_possible_map);
  57         nodes_clear(node_online_map);
  58         for (i = 0; i < loongson_sysconf.nr_nodes; i++) {
  59                 node_set_state(num_online_nodes(), N_POSSIBLE);
  60                 node_set_online(num_online_nodes());
  61         }
  62 
  63         pr_info("NUMA: Discovered %d cpus on %d nodes\n",
  64                 loongson_sysconf.nr_cpus, num_online_nodes());
  65 }
  66 
  67 static int __init compute_node_distance(int row, int col)
  68 {
  69         int package_row = row * loongson_sysconf.cores_per_node /
  70                                 loongson_sysconf.cores_per_package;
  71         int package_col = col * loongson_sysconf.cores_per_node /
  72                                 loongson_sysconf.cores_per_package;
  73 
  74         if (col == row)
  75                 return 0;
  76         else if (package_row == package_col)
  77                 return 40;
  78         else
  79                 return 100;
  80 }
  81 
  82 static void __init init_topology_matrix(void)
  83 {
  84         int row, col;
  85 
  86         for (row = 0; row < MAX_NUMNODES; row++)
  87                 for (col = 0; col < MAX_NUMNODES; col++)
  88                         __node_distances[row][col] = -1;
  89 
  90         for_each_online_node(row) {
  91                 for_each_online_node(col) {
  92                         __node_distances[row][col] =
  93                                 compute_node_distance(row, col);
  94                 }
  95         }
  96 }
  97 
  98 static unsigned long nid_to_addroffset(unsigned int nid)
  99 {
 100         unsigned long result;
 101         switch (nid) {
 102         case 0:
 103         default:
 104                 result = NODE0_ADDRSPACE_OFFSET;
 105                 break;
 106         case 1:
 107                 result = NODE1_ADDRSPACE_OFFSET;
 108                 break;
 109         case 2:
 110                 result = NODE2_ADDRSPACE_OFFSET;
 111                 break;
 112         case 3:
 113                 result = NODE3_ADDRSPACE_OFFSET;
 114                 break;
 115         }
 116         return result;
 117 }
 118 
 119 static void __init szmem(unsigned int node)
 120 {
 121         u32 i, mem_type;
 122         static unsigned long num_physpages = 0;
 123         u64 node_id, node_psize, start_pfn, end_pfn, mem_start, mem_size;
 124 
 125         /* Parse memory information and activate */
 126         for (i = 0; i < loongson_memmap->nr_map; i++) {
 127                 node_id = loongson_memmap->map[i].node_id;
 128                 if (node_id != node)
 129                         continue;
 130 
 131                 mem_type = loongson_memmap->map[i].mem_type;
 132                 mem_size = loongson_memmap->map[i].mem_size;
 133                 mem_start = loongson_memmap->map[i].mem_start;
 134 
 135                 switch (mem_type) {
 136                 case SYSTEM_RAM_LOW:
 137                         start_pfn = ((node_id << 44) + mem_start) >> PAGE_SHIFT;
 138                         node_psize = (mem_size << 20) >> PAGE_SHIFT;
 139                         end_pfn  = start_pfn + node_psize;
 140                         num_physpages += node_psize;
 141                         pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
 142                                 (u32)node_id, mem_type, mem_start, mem_size);
 143                         pr_info("       start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n",
 144                                 start_pfn, end_pfn, num_physpages);
 145                         memblock_add_node(PFN_PHYS(start_pfn),
 146                                 PFN_PHYS(end_pfn - start_pfn), node);
 147                         break;
 148                 case SYSTEM_RAM_HIGH:
 149                         start_pfn = ((node_id << 44) + mem_start) >> PAGE_SHIFT;
 150                         node_psize = (mem_size << 20) >> PAGE_SHIFT;
 151                         end_pfn  = start_pfn + node_psize;
 152                         num_physpages += node_psize;
 153                         pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
 154                                 (u32)node_id, mem_type, mem_start, mem_size);
 155                         pr_info("       start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n",
 156                                 start_pfn, end_pfn, num_physpages);
 157                         memblock_add_node(PFN_PHYS(start_pfn),
 158                                 PFN_PHYS(end_pfn - start_pfn), node);
 159                         break;
 160                 case SYSTEM_RAM_RESERVED:
 161                         pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
 162                                 (u32)node_id, mem_type, mem_start, mem_size);
 163                         memblock_reserve(((node_id << 44) + mem_start),
 164                                 mem_size << 20);
 165                         break;
 166                 }
 167         }
 168 }
 169 
 170 static void __init node_mem_init(unsigned int node)
 171 {
 172         unsigned long node_addrspace_offset;
 173         unsigned long start_pfn, end_pfn;
 174 
 175         node_addrspace_offset = nid_to_addroffset(node);
 176         pr_info("Node%d's addrspace_offset is 0x%lx\n",
 177                         node, node_addrspace_offset);
 178 
 179         get_pfn_range_for_nid(node, &start_pfn, &end_pfn);
 180         pr_info("Node%d: start_pfn=0x%lx, end_pfn=0x%lx\n",
 181                 node, start_pfn, end_pfn);
 182 
 183         __node_data[node] = prealloc__node_data + node;
 184 
 185         NODE_DATA(node)->node_start_pfn = start_pfn;
 186         NODE_DATA(node)->node_spanned_pages = end_pfn - start_pfn;
 187 
 188         if (node == 0) {
 189                 /* kernel end address */
 190                 unsigned long kernel_end_pfn = PFN_UP(__pa_symbol(&_end));
 191 
 192                 /* used by finalize_initrd() */
 193                 max_low_pfn = end_pfn;
 194 
 195                 /* Reserve the kernel text/data/bss */
 196                 memblock_reserve(start_pfn << PAGE_SHIFT,
 197                                  ((kernel_end_pfn - start_pfn) << PAGE_SHIFT));
 198 
 199                 /* Reserve 0xfe000000~0xffffffff for RS780E integrated GPU */
 200                 if (node_end_pfn(0) >= (0xffffffff >> PAGE_SHIFT))
 201                         memblock_reserve((node_addrspace_offset | 0xfe000000),
 202                                          32 << 20);
 203         }
 204 }
 205 
 206 static __init void prom_meminit(void)
 207 {
 208         unsigned int node, cpu, active_cpu = 0;
 209 
 210         cpu_node_probe();
 211         init_topology_matrix();
 212 
 213         for (node = 0; node < loongson_sysconf.nr_nodes; node++) {
 214                 if (node_online(node)) {
 215                         szmem(node);
 216                         node_mem_init(node);
 217                         cpumask_clear(&__node_data[(node)]->cpumask);
 218                 }
 219         }
 220         memblocks_present();
 221         max_low_pfn = PHYS_PFN(memblock_end_of_DRAM());
 222 
 223         for (cpu = 0; cpu < loongson_sysconf.nr_cpus; cpu++) {
 224                 node = cpu / loongson_sysconf.cores_per_node;
 225                 if (node >= num_online_nodes())
 226                         node = 0;
 227 
 228                 if (loongson_sysconf.reserved_cpus_mask & (1<<cpu))
 229                         continue;
 230 
 231                 cpumask_set_cpu(active_cpu, &__node_data[(node)]->cpumask);
 232                 pr_info("NUMA: set cpumask cpu %d on node %d\n", active_cpu, node);
 233 
 234                 active_cpu++;
 235         }
 236 }
 237 
 238 void __init paging_init(void)
 239 {
 240         unsigned long zones_size[MAX_NR_ZONES] = {0, };
 241 
 242         pagetable_init();
 243 #ifdef CONFIG_ZONE_DMA32
 244         zones_size[ZONE_DMA32] = MAX_DMA32_PFN;
 245 #endif
 246         zones_size[ZONE_NORMAL] = max_low_pfn;
 247         free_area_init_nodes(zones_size);
 248 }
 249 
 250 void __init mem_init(void)
 251 {
 252         high_memory = (void *) __va(get_num_physpages() << PAGE_SHIFT);
 253         memblock_free_all();
 254         setup_zero_pages();     /* This comes from node 0 */
 255         mem_init_print_info(NULL);
 256 }
 257 
 258 /* All PCI device belongs to logical Node-0 */
 259 int pcibus_to_node(struct pci_bus *bus)
 260 {
 261         return 0;
 262 }
 263 EXPORT_SYMBOL(pcibus_to_node);
 264 
 265 void __init prom_init_numa_memory(void)
 266 {
 267         enable_lpa();
 268         prom_meminit();
 269 }
 270 EXPORT_SYMBOL(prom_init_numa_memory);

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