Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright (C) 2010 Loongson Inc. & Lemote Inc. &
0004  *                    Institute of Computing Technology
0005  * Author:  Xiang Gao, gaoxiang@ict.ac.cn
0006  *          Huacai Chen, chenhc@lemote.com
0007  *          Xiaofu Meng, Shuangshuang Zhang
0008  */
0009 #include <linux/init.h>
0010 #include <linux/kernel.h>
0011 #include <linux/mm.h>
0012 #include <linux/mmzone.h>
0013 #include <linux/export.h>
0014 #include <linux/nodemask.h>
0015 #include <linux/swap.h>
0016 #include <linux/memblock.h>
0017 #include <linux/pfn.h>
0018 #include <linux/highmem.h>
0019 #include <asm/page.h>
0020 #include <asm/pgalloc.h>
0021 #include <asm/sections.h>
0022 #include <linux/irq.h>
0023 #include <asm/bootinfo.h>
0024 #include <asm/mc146818-time.h>
0025 #include <asm/time.h>
0026 #include <asm/wbflush.h>
0027 #include <boot_param.h>
0028 #include <loongson.h>
0029 
0030 unsigned char __node_distances[MAX_NUMNODES][MAX_NUMNODES];
0031 EXPORT_SYMBOL(__node_distances);
0032 struct pglist_data *__node_data[MAX_NUMNODES];
0033 EXPORT_SYMBOL(__node_data);
0034 
0035 cpumask_t __node_cpumask[MAX_NUMNODES];
0036 EXPORT_SYMBOL(__node_cpumask);
0037 
0038 static void cpu_node_probe(void)
0039 {
0040     int i;
0041 
0042     nodes_clear(node_possible_map);
0043     nodes_clear(node_online_map);
0044     for (i = 0; i < loongson_sysconf.nr_nodes; i++) {
0045         node_set_state(num_online_nodes(), N_POSSIBLE);
0046         node_set_online(num_online_nodes());
0047     }
0048 
0049     pr_info("NUMA: Discovered %d cpus on %d nodes\n",
0050         loongson_sysconf.nr_cpus, num_online_nodes());
0051 }
0052 
0053 static int __init compute_node_distance(int row, int col)
0054 {
0055     int package_row = row * loongson_sysconf.cores_per_node /
0056                 loongson_sysconf.cores_per_package;
0057     int package_col = col * loongson_sysconf.cores_per_node /
0058                 loongson_sysconf.cores_per_package;
0059 
0060     if (col == row)
0061         return LOCAL_DISTANCE;
0062     else if (package_row == package_col)
0063         return 40;
0064     else
0065         return 100;
0066 }
0067 
0068 static void __init init_topology_matrix(void)
0069 {
0070     int row, col;
0071 
0072     for (row = 0; row < MAX_NUMNODES; row++)
0073         for (col = 0; col < MAX_NUMNODES; col++)
0074             __node_distances[row][col] = -1;
0075 
0076     for_each_online_node(row) {
0077         for_each_online_node(col) {
0078             __node_distances[row][col] =
0079                 compute_node_distance(row, col);
0080         }
0081     }
0082 }
0083 
0084 static void __init node_mem_init(unsigned int node)
0085 {
0086     struct pglist_data *nd;
0087     unsigned long node_addrspace_offset;
0088     unsigned long start_pfn, end_pfn;
0089     unsigned long nd_pa;
0090     int tnid;
0091     const size_t nd_size = roundup(sizeof(pg_data_t), SMP_CACHE_BYTES);
0092 
0093     node_addrspace_offset = nid_to_addrbase(node);
0094     pr_info("Node%d's addrspace_offset is 0x%lx\n",
0095             node, node_addrspace_offset);
0096 
0097     get_pfn_range_for_nid(node, &start_pfn, &end_pfn);
0098     pr_info("Node%d: start_pfn=0x%lx, end_pfn=0x%lx\n",
0099         node, start_pfn, end_pfn);
0100 
0101     nd_pa = memblock_phys_alloc_try_nid(nd_size, SMP_CACHE_BYTES, node);
0102     if (!nd_pa)
0103         panic("Cannot allocate %zu bytes for node %d data\n",
0104               nd_size, node);
0105     nd = __va(nd_pa);
0106     memset(nd, 0, sizeof(struct pglist_data));
0107     tnid = early_pfn_to_nid(nd_pa >> PAGE_SHIFT);
0108     if (tnid != node)
0109         pr_info("NODE_DATA(%d) on node %d\n", node, tnid);
0110     __node_data[node] = nd;
0111     NODE_DATA(node)->node_start_pfn = start_pfn;
0112     NODE_DATA(node)->node_spanned_pages = end_pfn - start_pfn;
0113 
0114     if (node == 0) {
0115         /* kernel start address */
0116         unsigned long kernel_start_pfn = PFN_DOWN(__pa_symbol(&_text));
0117 
0118         /* kernel end address */
0119         unsigned long kernel_end_pfn = PFN_UP(__pa_symbol(&_end));
0120 
0121         /* used by finalize_initrd() */
0122         max_low_pfn = end_pfn;
0123 
0124         /* Reserve the kernel text/data/bss */
0125         memblock_reserve(kernel_start_pfn << PAGE_SHIFT,
0126                  ((kernel_end_pfn - kernel_start_pfn) << PAGE_SHIFT));
0127 
0128         /* Reserve 0xfe000000~0xffffffff for RS780E integrated GPU */
0129         if (node_end_pfn(0) >= (0xffffffff >> PAGE_SHIFT))
0130             memblock_reserve((node_addrspace_offset | 0xfe000000),
0131                      32 << 20);
0132 
0133         /* Reserve pfn range 0~node[0]->node_start_pfn */
0134         memblock_reserve(0, PAGE_SIZE * start_pfn);
0135     }
0136 }
0137 
0138 static __init void prom_meminit(void)
0139 {
0140     unsigned int node, cpu, active_cpu = 0;
0141 
0142     cpu_node_probe();
0143     init_topology_matrix();
0144 
0145     for (node = 0; node < loongson_sysconf.nr_nodes; node++) {
0146         if (node_online(node)) {
0147             szmem(node);
0148             node_mem_init(node);
0149             cpumask_clear(&__node_cpumask[node]);
0150         }
0151     }
0152     max_low_pfn = PHYS_PFN(memblock_end_of_DRAM());
0153 
0154     for (cpu = 0; cpu < loongson_sysconf.nr_cpus; cpu++) {
0155         node = cpu / loongson_sysconf.cores_per_node;
0156         if (node >= num_online_nodes())
0157             node = 0;
0158 
0159         if (loongson_sysconf.reserved_cpus_mask & (1<<cpu))
0160             continue;
0161 
0162         cpumask_set_cpu(active_cpu, &__node_cpumask[node]);
0163         pr_info("NUMA: set cpumask cpu %d on node %d\n", active_cpu, node);
0164 
0165         active_cpu++;
0166     }
0167 }
0168 
0169 void __init paging_init(void)
0170 {
0171     unsigned long zones_size[MAX_NR_ZONES] = {0, };
0172 
0173     pagetable_init();
0174     zones_size[ZONE_DMA32] = MAX_DMA32_PFN;
0175     zones_size[ZONE_NORMAL] = max_low_pfn;
0176     free_area_init(zones_size);
0177 }
0178 
0179 void __init mem_init(void)
0180 {
0181     high_memory = (void *) __va(get_num_physpages() << PAGE_SHIFT);
0182     memblock_free_all();
0183     setup_zero_pages(); /* This comes from node 0 */
0184 }
0185 
0186 /* All PCI device belongs to logical Node-0 */
0187 int pcibus_to_node(struct pci_bus *bus)
0188 {
0189     return 0;
0190 }
0191 EXPORT_SYMBOL(pcibus_to_node);
0192 
0193 void __init prom_init_numa_memory(void)
0194 {
0195     pr_info("CP0_Config3: CP0 16.3 (0x%x)\n", read_c0_config3());
0196     pr_info("CP0_PageGrain: CP0 5.1 (0x%x)\n", read_c0_pagegrain());
0197     prom_meminit();
0198 }
0199 
0200 pg_data_t * __init arch_alloc_nodedata(int nid)
0201 {
0202     return memblock_alloc(sizeof(pg_data_t), SMP_CACHE_BYTES);
0203 }
0204 
0205 void arch_refresh_nodedata(int nid, pg_data_t *pgdat)
0206 {
0207     __node_data[nid] = pgdat;
0208 }