aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorHuacai Chen <chenhc@lemote.com>2014-06-25 23:41:28 -0400
committerRalf Baechle <ralf@linux-mips.org>2014-07-30 15:46:19 -0400
commitc46173183657bbdbe0d54a981c28807581648422 (patch)
tree554d75cfc577d82c043b3e2fca17819abd63033b /arch
parent140e39c1e3d29f50e161f55cca60f60b80408c2a (diff)
MIPS: Add NUMA support for Loongson-3
Multiple Loongson-3A chips can be interconnected with HT0-bus. This is a CC-NUMA system that every chip (node) has its own local memory and cache coherency is maintained by hardware. The 64-bit physical memory address format is as follows: 0x-0000-YZZZ-ZZZZ-ZZZZ The high 16 bits should be 0, which means the real physical address supported by Loongson-3 is 48-bit. The "Y" bits is the base address of each node, which can be also considered as the node-id. The "Z" bits is the address offset within a node, which means every node has a 44 bits address space. Macros XPHYSADDR and MAX_PHYSMEM_BITS are modified unconditionally, because many other MIPS CPUs have also extended their address spaces. Signed-off-by: Huacai Chen <chenhc@lemote.com> Cc: John Crispin <john@phrozen.org> Cc: Steven J. Hill <Steven.Hill@imgtec.com> Cc: Aurelien Jarno <aurelien@aurel32.net> Cc: linux-mips@linux-mips.org Cc: Fuxin Zhang <zhangfx@lemote.com> Cc: Zhangjin Wu <wuzhangjin@gmail.com> Patchwork: https://patchwork.linux-mips.org/patch/7187/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/mips/include/asm/addrspace.h2
-rw-r--r--arch/mips/include/asm/mach-loongson/boot_param.h3
-rw-r--r--arch/mips/include/asm/mach-loongson/kernel-entry-init.h52
-rw-r--r--arch/mips/include/asm/mach-loongson/mmzone.h53
-rw-r--r--arch/mips/include/asm/mach-loongson/topology.h23
-rw-r--r--arch/mips/include/asm/sparsemem.h2
-rw-r--r--arch/mips/kernel/setup.c2
-rw-r--r--arch/mips/loongson/Kconfig1
-rw-r--r--arch/mips/loongson/common/env.c7
-rw-r--r--arch/mips/loongson/common/init.c4
-rw-r--r--arch/mips/loongson/loongson-3/Makefile2
-rw-r--r--arch/mips/loongson/loongson-3/numa.c291
-rw-r--r--arch/mips/loongson/loongson-3/smp.c8
13 files changed, 445 insertions, 5 deletions
diff --git a/arch/mips/include/asm/addrspace.h b/arch/mips/include/asm/addrspace.h
index 3f745459fdb5..3b0e51d5a613 100644
--- a/arch/mips/include/asm/addrspace.h
+++ b/arch/mips/include/asm/addrspace.h
@@ -52,7 +52,7 @@
52 */ 52 */
53#define CPHYSADDR(a) ((_ACAST32_(a)) & 0x1fffffff) 53#define CPHYSADDR(a) ((_ACAST32_(a)) & 0x1fffffff)
54#define XPHYSADDR(a) ((_ACAST64_(a)) & \ 54#define XPHYSADDR(a) ((_ACAST64_(a)) & \
55 _CONST64_(0x000000ffffffffff)) 55 _CONST64_(0x0000ffffffffffff))
56 56
57#ifdef CONFIG_64BIT 57#ifdef CONFIG_64BIT
58 58
diff --git a/arch/mips/include/asm/mach-loongson/boot_param.h b/arch/mips/include/asm/mach-loongson/boot_param.h
index 829a7ec185fb..8b06c96cce1f 100644
--- a/arch/mips/include/asm/mach-loongson/boot_param.h
+++ b/arch/mips/include/asm/mach-loongson/boot_param.h
@@ -146,6 +146,9 @@ struct boot_params {
146 146
147struct loongson_system_configuration { 147struct loongson_system_configuration {
148 u32 nr_cpus; 148 u32 nr_cpus;
149 u32 nr_nodes;
150 int cores_per_node;
151 int cores_per_package;
149 enum loongson_cpu_type cputype; 152 enum loongson_cpu_type cputype;
150 u64 ht_control_base; 153 u64 ht_control_base;
151 u64 pci_mem_start_addr; 154 u64 pci_mem_start_addr;
diff --git a/arch/mips/include/asm/mach-loongson/kernel-entry-init.h b/arch/mips/include/asm/mach-loongson/kernel-entry-init.h
new file mode 100644
index 000000000000..df5fca8eeb80
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/kernel-entry-init.h
@@ -0,0 +1,52 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2005 Embedded Alley Solutions, Inc
7 * Copyright (C) 2005 Ralf Baechle (ralf@linux-mips.org)
8 * Copyright (C) 2009 Jiajie Chen (chenjiajie@cse.buaa.edu.cn)
9 * Copyright (C) 2012 Huacai Chen (chenhc@lemote.com)
10 */
11#ifndef __ASM_MACH_LOONGSON_KERNEL_ENTRY_H
12#define __ASM_MACH_LOONGSON_KERNEL_ENTRY_H
13
14/*
15 * Override macros used in arch/mips/kernel/head.S.
16 */
17 .macro kernel_entry_setup
18#ifdef CONFIG_CPU_LOONGSON3
19 .set push
20 .set mips64
21 /* Set LPA on LOONGSON3 config3 */
22 mfc0 t0, $16, 3
23 or t0, (0x1 << 7)
24 mtc0 t0, $16, 3
25 /* Set ELPA on LOONGSON3 pagegrain */
26 li t0, (0x1 << 29)
27 mtc0 t0, $5, 1
28 _ehb
29 .set pop
30#endif
31 .endm
32
33/*
34 * Do SMP slave processor setup.
35 */
36 .macro smp_slave_setup
37#ifdef CONFIG_CPU_LOONGSON3
38 .set push
39 .set mips64
40 /* Set LPA on LOONGSON3 config3 */
41 mfc0 t0, $16, 3
42 or t0, (0x1 << 7)
43 mtc0 t0, $16, 3
44 /* Set ELPA on LOONGSON3 pagegrain */
45 li t0, (0x1 << 29)
46 mtc0 t0, $5, 1
47 _ehb
48 .set pop
49#endif
50 .endm
51
52#endif /* __ASM_MACH_LOONGSON_KERNEL_ENTRY_H */
diff --git a/arch/mips/include/asm/mach-loongson/mmzone.h b/arch/mips/include/asm/mach-loongson/mmzone.h
new file mode 100644
index 000000000000..37c08a27b4f0
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/mmzone.h
@@ -0,0 +1,53 @@
1/*
2 * Copyright (C) 2010 Loongson Inc. & Lemote Inc. &
3 * Insititute of Computing Technology
4 * Author: Xiang Gao, gaoxiang@ict.ac.cn
5 * Huacai Chen, chenhc@lemote.com
6 * Xiaofu Meng, Shuangshuang Zhang
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13#ifndef _ASM_MACH_MMZONE_H
14#define _ASM_MACH_MMZONE_H
15
16#include <boot_param.h>
17#define NODE_ADDRSPACE_SHIFT 44
18#define NODE0_ADDRSPACE_OFFSET 0x000000000000UL
19#define NODE1_ADDRSPACE_OFFSET 0x100000000000UL
20#define NODE2_ADDRSPACE_OFFSET 0x200000000000UL
21#define NODE3_ADDRSPACE_OFFSET 0x300000000000UL
22
23#define pa_to_nid(addr) (((addr) & 0xf00000000000) >> NODE_ADDRSPACE_SHIFT)
24
25#define LEVELS_PER_SLICE 128
26
27struct slice_data {
28 unsigned long irq_enable_mask[2];
29 int level_to_irq[LEVELS_PER_SLICE];
30};
31
32struct hub_data {
33 cpumask_t h_cpus;
34 unsigned long slice_map;
35 unsigned long irq_alloc_mask[2];
36 struct slice_data slice[2];
37};
38
39struct node_data {
40 struct pglist_data pglist;
41 struct hub_data hub;
42 cpumask_t cpumask;
43};
44
45extern struct node_data *__node_data[];
46
47#define NODE_DATA(n) (&__node_data[(n)]->pglist)
48#define hub_data(n) (&__node_data[(n)]->hub)
49
50extern void setup_zero_pages(void);
51extern void __init prom_init_numa_memory(void);
52
53#endif /* _ASM_MACH_MMZONE_H */
diff --git a/arch/mips/include/asm/mach-loongson/topology.h b/arch/mips/include/asm/mach-loongson/topology.h
new file mode 100644
index 000000000000..5598ba77d2ef
--- /dev/null
+++ b/arch/mips/include/asm/mach-loongson/topology.h
@@ -0,0 +1,23 @@
1#ifndef _ASM_MACH_TOPOLOGY_H
2#define _ASM_MACH_TOPOLOGY_H
3
4#ifdef CONFIG_NUMA
5
6#define cpu_to_node(cpu) ((cpu) >> 2)
7#define parent_node(node) (node)
8#define cpumask_of_node(node) (&__node_data[(node)]->cpumask)
9
10struct pci_bus;
11extern int pcibus_to_node(struct pci_bus *);
12
13#define cpumask_of_pcibus(bus) (cpu_online_mask)
14
15extern unsigned char __node_distances[MAX_NUMNODES][MAX_NUMNODES];
16
17#define node_distance(from, to) (__node_distances[(from)][(to)])
18
19#endif
20
21#include <asm-generic/topology.h>
22
23#endif /* _ASM_MACH_TOPOLOGY_H */
diff --git a/arch/mips/include/asm/sparsemem.h b/arch/mips/include/asm/sparsemem.h
index d2da53c2c2f8..b1071c1e54f5 100644
--- a/arch/mips/include/asm/sparsemem.h
+++ b/arch/mips/include/asm/sparsemem.h
@@ -11,7 +11,7 @@
11#else 11#else
12# define SECTION_SIZE_BITS 28 12# define SECTION_SIZE_BITS 28
13#endif 13#endif
14#define MAX_PHYSMEM_BITS 35 14#define MAX_PHYSMEM_BITS 48
15 15
16#endif /* CONFIG_SPARSEMEM */ 16#endif /* CONFIG_SPARSEMEM */
17#endif /* _MIPS_SPARSEMEM_H */ 17#endif /* _MIPS_SPARSEMEM_H */
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 2f01201b158c..7c1fe2b42d40 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -282,7 +282,7 @@ static unsigned long __init init_initrd(void)
282 * Initialize the bootmem allocator. It also setup initrd related data 282 * Initialize the bootmem allocator. It also setup initrd related data
283 * if needed. 283 * if needed.
284 */ 284 */
285#ifdef CONFIG_SGI_IP27 285#if defined(CONFIG_SGI_IP27) || (defined(CONFIG_CPU_LOONGSON3) && defined(CONFIG_NUMA))
286 286
287static void __init bootmem_init(void) 287static void __init bootmem_init(void)
288{ 288{
diff --git a/arch/mips/loongson/Kconfig b/arch/mips/loongson/Kconfig
index e6a86ccc4421..a14a50d009d4 100644
--- a/arch/mips/loongson/Kconfig
+++ b/arch/mips/loongson/Kconfig
@@ -79,6 +79,7 @@ config LEMOTE_MACH3A
79 select SYS_HAS_EARLY_PRINTK 79 select SYS_HAS_EARLY_PRINTK
80 select SYS_SUPPORTS_SMP 80 select SYS_SUPPORTS_SMP
81 select SYS_SUPPORTS_HOTPLUG_CPU 81 select SYS_SUPPORTS_HOTPLUG_CPU
82 select SYS_SUPPORTS_NUMA
82 select SYS_SUPPORTS_64BIT_KERNEL 83 select SYS_SUPPORTS_64BIT_KERNEL
83 select SYS_SUPPORTS_HIGHMEM 84 select SYS_SUPPORTS_HIGHMEM
84 select SYS_SUPPORTS_LITTLE_ENDIAN 85 select SYS_SUPPORTS_LITTLE_ENDIAN
diff --git a/arch/mips/loongson/common/env.c b/arch/mips/loongson/common/env.c
index dc592412f764..33a13b9e436c 100644
--- a/arch/mips/loongson/common/env.c
+++ b/arch/mips/loongson/common/env.c
@@ -80,17 +80,24 @@ void __init prom_init_env(void)
80 cpu_clock_freq = ecpu->cpu_clock_freq; 80 cpu_clock_freq = ecpu->cpu_clock_freq;
81 loongson_sysconf.cputype = ecpu->cputype; 81 loongson_sysconf.cputype = ecpu->cputype;
82 if (ecpu->cputype == Loongson_3A) { 82 if (ecpu->cputype == Loongson_3A) {
83 loongson_sysconf.cores_per_node = 4;
84 loongson_sysconf.cores_per_package = 4;
83 loongson_chipcfg[0] = 0x900000001fe00180; 85 loongson_chipcfg[0] = 0x900000001fe00180;
84 loongson_chipcfg[1] = 0x900010001fe00180; 86 loongson_chipcfg[1] = 0x900010001fe00180;
85 loongson_chipcfg[2] = 0x900020001fe00180; 87 loongson_chipcfg[2] = 0x900020001fe00180;
86 loongson_chipcfg[3] = 0x900030001fe00180; 88 loongson_chipcfg[3] = 0x900030001fe00180;
87 } else { 89 } else {
90 loongson_sysconf.cores_per_node = 1;
91 loongson_sysconf.cores_per_package = 1;
88 loongson_chipcfg[0] = 0x900000001fe00180; 92 loongson_chipcfg[0] = 0x900000001fe00180;
89 } 93 }
90 94
91 loongson_sysconf.nr_cpus = ecpu->nr_cpus; 95 loongson_sysconf.nr_cpus = ecpu->nr_cpus;
92 if (ecpu->nr_cpus > NR_CPUS || ecpu->nr_cpus == 0) 96 if (ecpu->nr_cpus > NR_CPUS || ecpu->nr_cpus == 0)
93 loongson_sysconf.nr_cpus = NR_CPUS; 97 loongson_sysconf.nr_cpus = NR_CPUS;
98 loongson_sysconf.nr_nodes = (loongson_sysconf.nr_cpus +
99 loongson_sysconf.cores_per_node - 1) /
100 loongson_sysconf.cores_per_node;
94 101
95 loongson_sysconf.pci_mem_start_addr = eirq_source->pci_mem_start_addr; 102 loongson_sysconf.pci_mem_start_addr = eirq_source->pci_mem_start_addr;
96 loongson_sysconf.pci_mem_end_addr = eirq_source->pci_mem_end_addr; 103 loongson_sysconf.pci_mem_end_addr = eirq_source->pci_mem_end_addr;
diff --git a/arch/mips/loongson/common/init.c b/arch/mips/loongson/common/init.c
index f37fe5413b73..f6af3aba4c86 100644
--- a/arch/mips/loongson/common/init.c
+++ b/arch/mips/loongson/common/init.c
@@ -30,7 +30,11 @@ void __init prom_init(void)
30 set_io_port_base((unsigned long) 30 set_io_port_base((unsigned long)
31 ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE)); 31 ioremap(LOONGSON_PCIIO_BASE, LOONGSON_PCIIO_SIZE));
32 32
33#ifdef CONFIG_NUMA
34 prom_init_numa_memory();
35#else
33 prom_init_memory(); 36 prom_init_memory();
37#endif
34 38
35 /*init the uart base address */ 39 /*init the uart base address */
36 prom_init_uart_base(); 40 prom_init_uart_base();
diff --git a/arch/mips/loongson/loongson-3/Makefile b/arch/mips/loongson/loongson-3/Makefile
index 70152b252ddc..471b0f2af079 100644
--- a/arch/mips/loongson/loongson-3/Makefile
+++ b/arch/mips/loongson/loongson-3/Makefile
@@ -4,3 +4,5 @@
4obj-y += irq.o 4obj-y += irq.o
5 5
6obj-$(CONFIG_SMP) += smp.o 6obj-$(CONFIG_SMP) += smp.o
7
8obj-$(CONFIG_NUMA) += numa.o
diff --git a/arch/mips/loongson/loongson-3/numa.c b/arch/mips/loongson/loongson-3/numa.c
new file mode 100644
index 000000000000..ca025a6ba559
--- /dev/null
+++ b/arch/mips/loongson/loongson-3/numa.c
@@ -0,0 +1,291 @@
1/*
2 * Copyright (C) 2010 Loongson Inc. & Lemote Inc. &
3 * Insititute of Computing Technology
4 * Author: Xiang Gao, gaoxiang@ict.ac.cn
5 * Huacai Chen, chenhc@lemote.com
6 * Xiaofu Meng, Shuangshuang Zhang
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13#include <linux/init.h>
14#include <linux/kernel.h>
15#include <linux/mm.h>
16#include <linux/mmzone.h>
17#include <linux/module.h>
18#include <linux/nodemask.h>
19#include <linux/swap.h>
20#include <linux/memblock.h>
21#include <linux/bootmem.h>
22#include <linux/pfn.h>
23#include <linux/highmem.h>
24#include <asm/page.h>
25#include <asm/pgalloc.h>
26#include <asm/sections.h>
27#include <linux/bootmem.h>
28#include <linux/init.h>
29#include <linux/irq.h>
30#include <asm/bootinfo.h>
31#include <asm/mc146818-time.h>
32#include <asm/time.h>
33#include <asm/wbflush.h>
34#include <boot_param.h>
35
36static struct node_data prealloc__node_data[MAX_NUMNODES];
37unsigned char __node_distances[MAX_NUMNODES][MAX_NUMNODES];
38struct node_data *__node_data[MAX_NUMNODES];
39EXPORT_SYMBOL(__node_data);
40
41static void enable_lpa(void)
42{
43 unsigned long value;
44
45 value = __read_32bit_c0_register($16, 3);
46 value |= 0x00000080;
47 __write_32bit_c0_register($16, 3, value);
48 value = __read_32bit_c0_register($16, 3);
49 pr_info("CP0_Config3: CP0 16.3 (0x%lx)\n", value);
50
51 value = __read_32bit_c0_register($5, 1);
52 value |= 0x20000000;
53 __write_32bit_c0_register($5, 1, value);
54 value = __read_32bit_c0_register($5, 1);
55 pr_info("CP0_PageGrain: CP0 5.1 (0x%lx)\n", value);
56}
57
58static void cpu_node_probe(void)
59{
60 int i;
61
62 nodes_clear(node_possible_map);
63 nodes_clear(node_online_map);
64 for (i = 0; i < loongson_sysconf.nr_nodes; i++) {
65 node_set_state(num_online_nodes(), N_POSSIBLE);
66 node_set_online(num_online_nodes());
67 }
68
69 pr_info("NUMA: Discovered %d cpus on %d nodes\n",
70 loongson_sysconf.nr_cpus, num_online_nodes());
71}
72
73static int __init compute_node_distance(int row, int col)
74{
75 int package_row = row * loongson_sysconf.cores_per_node /
76 loongson_sysconf.cores_per_package;
77 int package_col = col * loongson_sysconf.cores_per_node /
78 loongson_sysconf.cores_per_package;
79
80 if (col == row)
81 return 0;
82 else if (package_row == package_col)
83 return 40;
84 else
85 return 100;
86}
87
88static void __init init_topology_matrix(void)
89{
90 int row, col;
91
92 for (row = 0; row < MAX_NUMNODES; row++)
93 for (col = 0; col < MAX_NUMNODES; col++)
94 __node_distances[row][col] = -1;
95
96 for_each_online_node(row) {
97 for_each_online_node(col) {
98 __node_distances[row][col] =
99 compute_node_distance(row, col);
100 }
101 }
102}
103
104static unsigned long nid_to_addroffset(unsigned int nid)
105{
106 unsigned long result;
107 switch (nid) {
108 case 0:
109 default:
110 result = NODE0_ADDRSPACE_OFFSET;
111 break;
112 case 1:
113 result = NODE1_ADDRSPACE_OFFSET;
114 break;
115 case 2:
116 result = NODE2_ADDRSPACE_OFFSET;
117 break;
118 case 3:
119 result = NODE3_ADDRSPACE_OFFSET;
120 break;
121 }
122 return result;
123}
124
125static void __init szmem(unsigned int node)
126{
127 u32 i, mem_type;
128 static unsigned long num_physpages = 0;
129 u64 node_id, node_psize, start_pfn, end_pfn, mem_start, mem_size;
130
131 /* Parse memory information and activate */
132 for (i = 0; i < loongson_memmap->nr_map; i++) {
133 node_id = loongson_memmap->map[i].node_id;
134 if (node_id != node)
135 continue;
136
137 mem_type = loongson_memmap->map[i].mem_type;
138 mem_size = loongson_memmap->map[i].mem_size;
139 mem_start = loongson_memmap->map[i].mem_start;
140
141 switch (mem_type) {
142 case SYSTEM_RAM_LOW:
143 start_pfn = ((node_id << 44) + mem_start) >> PAGE_SHIFT;
144 node_psize = (mem_size << 20) >> PAGE_SHIFT;
145 end_pfn = start_pfn + node_psize;
146 num_physpages += node_psize;
147 pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
148 (u32)node_id, mem_type, mem_start, mem_size);
149 pr_info(" start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n",
150 start_pfn, end_pfn, num_physpages);
151 add_memory_region((node_id << 44) + mem_start,
152 (u64)mem_size << 20, BOOT_MEM_RAM);
153 memblock_add_node(PFN_PHYS(start_pfn),
154 PFN_PHYS(end_pfn - start_pfn), node);
155 break;
156 case SYSTEM_RAM_HIGH:
157 start_pfn = ((node_id << 44) + mem_start) >> PAGE_SHIFT;
158 node_psize = (mem_size << 20) >> PAGE_SHIFT;
159 end_pfn = start_pfn + node_psize;
160 num_physpages += node_psize;
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 pr_info(" start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n",
164 start_pfn, end_pfn, num_physpages);
165 add_memory_region((node_id << 44) + mem_start,
166 (u64)mem_size << 20, BOOT_MEM_RAM);
167 memblock_add_node(PFN_PHYS(start_pfn),
168 PFN_PHYS(end_pfn - start_pfn), node);
169 break;
170 case MEM_RESERVED:
171 pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
172 (u32)node_id, mem_type, mem_start, mem_size);
173 add_memory_region((node_id << 44) + mem_start,
174 (u64)mem_size << 20, BOOT_MEM_RESERVED);
175 memblock_reserve(((node_id << 44) + mem_start),
176 mem_size << 20);
177 break;
178 }
179 }
180}
181
182static void __init node_mem_init(unsigned int node)
183{
184 unsigned long bootmap_size;
185 unsigned long node_addrspace_offset;
186 unsigned long start_pfn, end_pfn, freepfn;
187
188 node_addrspace_offset = nid_to_addroffset(node);
189 pr_info("Node%d's addrspace_offset is 0x%lx\n",
190 node, node_addrspace_offset);
191
192 get_pfn_range_for_nid(node, &start_pfn, &end_pfn);
193 freepfn = start_pfn;
194 if (node == 0)
195 freepfn = PFN_UP(__pa_symbol(&_end)); /* kernel end address */
196 pr_info("Node%d: start_pfn=0x%lx, end_pfn=0x%lx, freepfn=0x%lx\n",
197 node, start_pfn, end_pfn, freepfn);
198
199 __node_data[node] = prealloc__node_data + node;
200
201 NODE_DATA(node)->bdata = &bootmem_node_data[node];
202 NODE_DATA(node)->node_start_pfn = start_pfn;
203 NODE_DATA(node)->node_spanned_pages = end_pfn - start_pfn;
204
205 bootmap_size = init_bootmem_node(NODE_DATA(node), freepfn,
206 start_pfn, end_pfn);
207 free_bootmem_with_active_regions(node, end_pfn);
208 if (node == 0) /* used by finalize_initrd() */
209 max_low_pfn = end_pfn;
210
211 /* This is reserved for the kernel and bdata->node_bootmem_map */
212 reserve_bootmem_node(NODE_DATA(node), start_pfn << PAGE_SHIFT,
213 ((freepfn - start_pfn) << PAGE_SHIFT) + bootmap_size,
214 BOOTMEM_DEFAULT);
215
216 if (node == 0 && node_end_pfn(0) >= (0xffffffff >> PAGE_SHIFT)) {
217 /* Reserve 0xff800000~0xffffffff for RS780E integrated GPU */
218 reserve_bootmem_node(NODE_DATA(node),
219 (node_addrspace_offset | 0xff800000),
220 8 << 20, BOOTMEM_DEFAULT);
221 }
222
223 sparse_memory_present_with_active_regions(node);
224}
225
226static __init void prom_meminit(void)
227{
228 unsigned int node, cpu;
229
230 cpu_node_probe();
231 init_topology_matrix();
232
233 for (node = 0; node < loongson_sysconf.nr_nodes; node++) {
234 if (node_online(node)) {
235 szmem(node);
236 node_mem_init(node);
237 cpus_clear(__node_data[(node)]->cpumask);
238 }
239 }
240 for (cpu = 0; cpu < loongson_sysconf.nr_cpus; cpu++) {
241 node = cpu / loongson_sysconf.cores_per_node;
242 if (node >= num_online_nodes())
243 node = 0;
244 pr_info("NUMA: set cpumask cpu %d on node %d\n", cpu, node);
245 cpu_set(cpu, __node_data[(node)]->cpumask);
246 }
247}
248
249void __init paging_init(void)
250{
251 unsigned node;
252 unsigned long zones_size[MAX_NR_ZONES] = {0, };
253
254 pagetable_init();
255
256 for_each_online_node(node) {
257 unsigned long start_pfn, end_pfn;
258
259 get_pfn_range_for_nid(node, &start_pfn, &end_pfn);
260
261 if (end_pfn > max_low_pfn)
262 max_low_pfn = end_pfn;
263 }
264#ifdef CONFIG_ZONE_DMA32
265 zones_size[ZONE_DMA32] = MAX_DMA32_PFN;
266#endif
267 zones_size[ZONE_NORMAL] = max_low_pfn;
268 free_area_init_nodes(zones_size);
269}
270
271void __init mem_init(void)
272{
273 high_memory = (void *) __va(get_num_physpages() << PAGE_SHIFT);
274 free_all_bootmem();
275 setup_zero_pages(); /* This comes from node 0 */
276 mem_init_print_info(NULL);
277}
278
279/* All PCI device belongs to logical Node-0 */
280int pcibus_to_node(struct pci_bus *bus)
281{
282 return 0;
283}
284EXPORT_SYMBOL(pcibus_to_node);
285
286void __init prom_init_numa_memory(void)
287{
288 enable_lpa();
289 prom_meminit();
290}
291EXPORT_SYMBOL(prom_init_numa_memory);
diff --git a/arch/mips/loongson/loongson-3/smp.c b/arch/mips/loongson/loongson-3/smp.c
index 3c320e709e91..ed0e2d0f87ab 100644
--- a/arch/mips/loongson/loongson-3/smp.c
+++ b/arch/mips/loongson/loongson-3/smp.c
@@ -203,6 +203,8 @@ static void loongson3_init_secondary(void)
203 for (i = 0; i < loongson_sysconf.nr_cpus; i++) 203 for (i = 0; i < loongson_sysconf.nr_cpus; i++)
204 loongson3_ipi_write32(0xffffffff, ipi_en0_regs[i]); 204 loongson3_ipi_write32(0xffffffff, ipi_en0_regs[i]);
205 205
206 cpu_data[cpu].package = cpu / loongson_sysconf.cores_per_package;
207 cpu_data[cpu].core = cpu % loongson_sysconf.cores_per_package;
206 per_cpu(cpu_state, cpu) = CPU_ONLINE; 208 per_cpu(cpu_state, cpu) = CPU_ONLINE;
207 209
208 i = 0; 210 i = 0;
@@ -394,17 +396,19 @@ static int loongson3_cpu_callback(struct notifier_block *nfb,
394 unsigned long action, void *hcpu) 396 unsigned long action, void *hcpu)
395{ 397{
396 unsigned int cpu = (unsigned long)hcpu; 398 unsigned int cpu = (unsigned long)hcpu;
399 uint64_t core_id = cpu_data[cpu].core;
400 uint64_t package_id = cpu_data[cpu].package;
397 401
398 switch (action) { 402 switch (action) {
399 case CPU_POST_DEAD: 403 case CPU_POST_DEAD:
400 case CPU_POST_DEAD_FROZEN: 404 case CPU_POST_DEAD_FROZEN:
401 pr_info("Disable clock for CPU#%d\n", cpu); 405 pr_info("Disable clock for CPU#%d\n", cpu);
402 LOONGSON_CHIPCFG(0) &= ~(1 << (12 + cpu)); 406 LOONGSON_CHIPCFG(package_id) &= ~(1 << (12 + core_id));
403 break; 407 break;
404 case CPU_UP_PREPARE: 408 case CPU_UP_PREPARE:
405 case CPU_UP_PREPARE_FROZEN: 409 case CPU_UP_PREPARE_FROZEN:
406 pr_info("Enable clock for CPU#%d\n", cpu); 410 pr_info("Enable clock for CPU#%d\n", cpu);
407 LOONGSON_CHIPCFG(0) |= 1 << (12 + cpu); 411 LOONGSON_CHIPCFG(package_id) |= 1 << (12 + core_id);
408 break; 412 break;
409 } 413 }
410 414