diff options
author | 2025-03-08 22:04:20 +0800 | |
---|---|---|
committer | 2025-03-08 22:04:20 +0800 | |
commit | a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a (patch) | |
tree | 84f21bd0bf7071bc5fc7dd989e77d7ceb5476682 /arch/mips/loongson64/numa.c | |
download | ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.tar.gz ohosKernel-a07bb8fd1299070229f0e8f3dcb57ffd5ef9870a.zip |
Initial commit: OpenHarmony-v4.0-ReleaseOpenHarmony-v4.0-Release
Diffstat (limited to 'arch/mips/loongson64/numa.c')
-rw-r--r-- | arch/mips/loongson64/numa.c | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/arch/mips/loongson64/numa.c b/arch/mips/loongson64/numa.c new file mode 100644 index 000000000..e4c461df3 --- /dev/null +++ b/arch/mips/loongson64/numa.c | |||
@@ -0,0 +1,252 @@ | |||
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 pglist_data prealloc__node_data[MAX_NUMNODES]; | ||
30 | unsigned char __node_distances[MAX_NUMNODES][MAX_NUMNODES]; | ||
31 | EXPORT_SYMBOL(__node_distances); | ||
32 | struct pglist_data *__node_data[MAX_NUMNODES]; | ||
33 | EXPORT_SYMBOL(__node_data); | ||
34 | |||
35 | cpumask_t __node_cpumask[MAX_NUMNODES]; | ||
36 | EXPORT_SYMBOL(__node_cpumask); | ||
37 | |||
38 | static void enable_lpa(void) | ||
39 | { | ||
40 | unsigned long value; | ||
41 | |||
42 | value = __read_32bit_c0_register($16, 3); | ||
43 | value |= 0x00000080; | ||
44 | __write_32bit_c0_register($16, 3, value); | ||
45 | value = __read_32bit_c0_register($16, 3); | ||
46 | pr_info("CP0_Config3: CP0 16.3 (0x%lx)\n", value); | ||
47 | |||
48 | value = __read_32bit_c0_register($5, 1); | ||
49 | value |= 0x20000000; | ||
50 | __write_32bit_c0_register($5, 1, value); | ||
51 | value = __read_32bit_c0_register($5, 1); | ||
52 | pr_info("CP0_PageGrain: CP0 5.1 (0x%lx)\n", value); | ||
53 | } | ||
54 | |||
55 | static void cpu_node_probe(void) | ||
56 | { | ||
57 | int i; | ||
58 | |||
59 | nodes_clear(node_possible_map); | ||
60 | nodes_clear(node_online_map); | ||
61 | for (i = 0; i < loongson_sysconf.nr_nodes; i++) { | ||
62 | node_set_state(num_online_nodes(), N_POSSIBLE); | ||
63 | node_set_online(num_online_nodes()); | ||
64 | } | ||
65 | |||
66 | pr_info("NUMA: Discovered %d cpus on %d nodes\n", | ||
67 | loongson_sysconf.nr_cpus, num_online_nodes()); | ||
68 | } | ||
69 | |||
70 | static int __init compute_node_distance(int row, int col) | ||
71 | { | ||
72 | int package_row = row * loongson_sysconf.cores_per_node / | ||
73 | loongson_sysconf.cores_per_package; | ||
74 | int package_col = col * loongson_sysconf.cores_per_node / | ||
75 | loongson_sysconf.cores_per_package; | ||
76 | |||
77 | if (col == row) | ||
78 | return LOCAL_DISTANCE; | ||
79 | else if (package_row == package_col) | ||
80 | return 40; | ||
81 | else | ||
82 | return 100; | ||
83 | } | ||
84 | |||
85 | static void __init init_topology_matrix(void) | ||
86 | { | ||
87 | int row, col; | ||
88 | |||
89 | for (row = 0; row < MAX_NUMNODES; row++) | ||
90 | for (col = 0; col < MAX_NUMNODES; col++) | ||
91 | __node_distances[row][col] = -1; | ||
92 | |||
93 | for_each_online_node(row) { | ||
94 | for_each_online_node(col) { | ||
95 | __node_distances[row][col] = | ||
96 | compute_node_distance(row, col); | ||
97 | } | ||
98 | } | ||
99 | } | ||
100 | |||
101 | static void __init szmem(unsigned int node) | ||
102 | { | ||
103 | u32 i, mem_type; | ||
104 | static unsigned long num_physpages; | ||
105 | u64 node_id, node_psize, start_pfn, end_pfn, mem_start, mem_size; | ||
106 | |||
107 | /* Parse memory information and activate */ | ||
108 | for (i = 0; i < loongson_memmap->nr_map; i++) { | ||
109 | node_id = loongson_memmap->map[i].node_id; | ||
110 | if (node_id != node) | ||
111 | continue; | ||
112 | |||
113 | mem_type = loongson_memmap->map[i].mem_type; | ||
114 | mem_size = loongson_memmap->map[i].mem_size; | ||
115 | mem_start = loongson_memmap->map[i].mem_start; | ||
116 | |||
117 | switch (mem_type) { | ||
118 | case SYSTEM_RAM_LOW: | ||
119 | start_pfn = ((node_id << 44) + mem_start) >> PAGE_SHIFT; | ||
120 | node_psize = (mem_size << 20) >> PAGE_SHIFT; | ||
121 | end_pfn = start_pfn + node_psize; | ||
122 | num_physpages += node_psize; | ||
123 | pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n", | ||
124 | (u32)node_id, mem_type, mem_start, mem_size); | ||
125 | pr_info(" start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n", | ||
126 | start_pfn, end_pfn, num_physpages); | ||
127 | memblock_add_node(PFN_PHYS(start_pfn), | ||
128 | PFN_PHYS(node_psize), node); | ||
129 | break; | ||
130 | case SYSTEM_RAM_HIGH: | ||
131 | start_pfn = ((node_id << 44) + mem_start) >> PAGE_SHIFT; | ||
132 | node_psize = (mem_size << 20) >> PAGE_SHIFT; | ||
133 | end_pfn = start_pfn + node_psize; | ||
134 | num_physpages += node_psize; | ||
135 | pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n", | ||
136 | (u32)node_id, mem_type, mem_start, mem_size); | ||
137 | pr_info(" start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n", | ||
138 | start_pfn, end_pfn, num_physpages); | ||
139 | memblock_add_node(PFN_PHYS(start_pfn), | ||
140 | PFN_PHYS(node_psize), node); | ||
141 | break; | ||
142 | case SYSTEM_RAM_RESERVED: | ||
143 | pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n", | ||
144 | (u32)node_id, mem_type, mem_start, mem_size); | ||
145 | memblock_reserve(((node_id << 44) + mem_start), | ||
146 | mem_size << 20); | ||
147 | break; | ||
148 | } | ||
149 | } | ||
150 | } | ||
151 | |||
152 | static void __init node_mem_init(unsigned int node) | ||
153 | { | ||
154 | unsigned long node_addrspace_offset; | ||
155 | unsigned long start_pfn, end_pfn; | ||
156 | |||
157 | node_addrspace_offset = nid_to_addrbase(node); | ||
158 | pr_info("Node%d's addrspace_offset is 0x%lx\n", | ||
159 | node, node_addrspace_offset); | ||
160 | |||
161 | get_pfn_range_for_nid(node, &start_pfn, &end_pfn); | ||
162 | pr_info("Node%d: start_pfn=0x%lx, end_pfn=0x%lx\n", | ||
163 | node, start_pfn, end_pfn); | ||
164 | |||
165 | __node_data[node] = prealloc__node_data + node; | ||
166 | |||
167 | NODE_DATA(node)->node_start_pfn = start_pfn; | ||
168 | NODE_DATA(node)->node_spanned_pages = end_pfn - start_pfn; | ||
169 | |||
170 | if (node == 0) { | ||
171 | /* kernel end address */ | ||
172 | unsigned long kernel_end_pfn = PFN_UP(__pa_symbol(&_end)); | ||
173 | |||
174 | /* used by finalize_initrd() */ | ||
175 | max_low_pfn = end_pfn; | ||
176 | |||
177 | /* Reserve the kernel text/data/bss */ | ||
178 | memblock_reserve(start_pfn << PAGE_SHIFT, | ||
179 | ((kernel_end_pfn - start_pfn) << PAGE_SHIFT)); | ||
180 | |||
181 | /* Reserve 0xfe000000~0xffffffff for RS780E integrated GPU */ | ||
182 | if (node_end_pfn(0) >= (0xffffffff >> PAGE_SHIFT)) | ||
183 | memblock_reserve((node_addrspace_offset | 0xfe000000), | ||
184 | 32 << 20); | ||
185 | |||
186 | /* Reserve pfn range 0~node[0]->node_start_pfn */ | ||
187 | memblock_reserve(0, PAGE_SIZE * start_pfn); | ||
188 | } | ||
189 | } | ||
190 | |||
191 | static __init void prom_meminit(void) | ||
192 | { | ||
193 | unsigned int node, cpu, active_cpu = 0; | ||
194 | |||
195 | cpu_node_probe(); | ||
196 | init_topology_matrix(); | ||
197 | |||
198 | for (node = 0; node < loongson_sysconf.nr_nodes; node++) { | ||
199 | if (node_online(node)) { | ||
200 | szmem(node); | ||
201 | node_mem_init(node); | ||
202 | cpumask_clear(&__node_cpumask[node]); | ||
203 | } | ||
204 | } | ||
205 | max_low_pfn = PHYS_PFN(memblock_end_of_DRAM()); | ||
206 | |||
207 | for (cpu = 0; cpu < loongson_sysconf.nr_cpus; cpu++) { | ||
208 | node = cpu / loongson_sysconf.cores_per_node; | ||
209 | if (node >= num_online_nodes()) | ||
210 | node = 0; | ||
211 | |||
212 | if (loongson_sysconf.reserved_cpus_mask & (1<<cpu)) | ||
213 | continue; | ||
214 | |||
215 | cpumask_set_cpu(active_cpu, &__node_cpumask[node]); | ||
216 | pr_info("NUMA: set cpumask cpu %d on node %d\n", active_cpu, node); | ||
217 | |||
218 | active_cpu++; | ||
219 | } | ||
220 | } | ||
221 | |||
222 | void __init paging_init(void) | ||
223 | { | ||
224 | unsigned long zones_size[MAX_NR_ZONES] = {0, }; | ||
225 | |||
226 | pagetable_init(); | ||
227 | zones_size[ZONE_DMA32] = MAX_DMA32_PFN; | ||
228 | zones_size[ZONE_NORMAL] = max_low_pfn; | ||
229 | free_area_init(zones_size); | ||
230 | } | ||
231 | |||
232 | void __init mem_init(void) | ||
233 | { | ||
234 | high_memory = (void *) __va(get_num_physpages() << PAGE_SHIFT); | ||
235 | memblock_free_all(); | ||
236 | setup_zero_pages(); /* This comes from node 0 */ | ||
237 | mem_init_print_info(NULL); | ||
238 | } | ||
239 | |||
240 | /* All PCI device belongs to logical Node-0 */ | ||
241 | int pcibus_to_node(struct pci_bus *bus) | ||
242 | { | ||
243 | return 0; | ||
244 | } | ||
245 | EXPORT_SYMBOL(pcibus_to_node); | ||
246 | |||
247 | void __init prom_init_numa_memory(void) | ||
248 | { | ||
249 | enable_lpa(); | ||
250 | prom_meminit(); | ||
251 | } | ||
252 | EXPORT_SYMBOL(prom_init_numa_memory); | ||