aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel
diff options
context:
space:
mode:
authorAnton Blanchard <anton@samba.org>2006-03-25 01:25:17 -0500
committerPaul Mackerras <paulus@samba.org>2006-03-26 22:48:48 -0500
commit4df20460a3ff0d60280738b094945c56cb5567a5 (patch)
tree39f831cf5f778b14a08b3453a8f798b2b8be8813 /arch/powerpc/kernel
parentb4f382a3e5e20ba867e7aa5b01189a3fd40eea2c (diff)
[PATCH] powerpc: Allow non zero boot cpuids
We currently have a hack to flip the boot cpu and its secondary thread to logical cpuid 0 and 1. This means the logical - physical mapping will differ depending on which cpu is boot cpu. This is most apparent on kexec, where we might kexec on any cpu and therefore change the mapping from boot to boot. The patch below does a first pass early on to work out the logical cpuid of the boot thread. We then fix up some paca structures to match. Ive also removed the boot_cpuid_phys variable for ppc64, to be consistent we use get_hard_smp_processor_id(boot_cpuid) everywhere. Signed-off-by: Anton Blanchard <anton@samba.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r--arch/powerpc/kernel/head_64.S26
-rw-r--r--arch/powerpc/kernel/paca.c21
-rw-r--r--arch/powerpc/kernel/prom.c83
-rw-r--r--arch/powerpc/kernel/setup-common.c16
-rw-r--r--arch/powerpc/kernel/setup_64.c12
5 files changed, 82 insertions, 76 deletions
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 7e7f7d243304..a5ae04a57c78 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -1851,21 +1851,6 @@ _STATIC(start_here_multiplatform)
1851 bl .__save_cpu_setup 1851 bl .__save_cpu_setup
1852 sync 1852 sync
1853 1853
1854 /* Setup a valid physical PACA pointer in SPRG3 for early_setup
1855 * note that boot_cpuid can always be 0 nowadays since there is
1856 * nowhere it can be initialized differently before we reach this
1857 * code
1858 */
1859 LOAD_REG_IMMEDIATE(r27, boot_cpuid)
1860 add r27,r27,r26
1861 lwz r27,0(r27)
1862
1863 LOAD_REG_IMMEDIATE(r24, paca) /* Get base vaddr of paca array */
1864 mulli r13,r27,PACA_SIZE /* Calculate vaddr of right paca */
1865 add r13,r13,r24 /* for this processor. */
1866 add r13,r13,r26 /* convert to physical addr */
1867 mtspr SPRN_SPRG3,r13
1868
1869 /* Do very early kernel initializations, including initial hash table, 1854 /* Do very early kernel initializations, including initial hash table,
1870 * stab and slb setup before we turn on relocation. */ 1855 * stab and slb setup before we turn on relocation. */
1871 1856
@@ -1934,6 +1919,17 @@ _STATIC(start_here_common)
1934 /* Not reached */ 1919 /* Not reached */
1935 BUG_OPCODE 1920 BUG_OPCODE
1936 1921
1922/* Put the paca pointer into r13 and SPRG3 */
1923_GLOBAL(setup_boot_paca)
1924 LOAD_REG_IMMEDIATE(r3, boot_cpuid)
1925 lwz r3,0(r3)
1926 LOAD_REG_IMMEDIATE(r4, paca) /* Get base vaddr of paca array */
1927 mulli r3,r3,PACA_SIZE /* Calculate vaddr of right paca */
1928 add r13,r3,r4 /* for this processor. */
1929 mtspr SPRN_SPRG3,r13
1930
1931 blr
1932
1937/* 1933/*
1938 * We put a few things here that have to be page-aligned. 1934 * We put a few things here that have to be page-aligned.
1939 * This stuff goes at the beginning of the bss, which is page-aligned. 1935 * This stuff goes at the beginning of the bss, which is page-aligned.
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index 5d1b708086bd..f505a8827e3e 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -56,14 +56,11 @@ struct lppaca lppaca[] = {
56 * processors. The processor VPD array needs one entry per physical 56 * processors. The processor VPD array needs one entry per physical
57 * processor (not thread). 57 * processor (not thread).
58 */ 58 */
59#define PACA_INIT_COMMON(number, start, asrr, asrv) \ 59#define PACA_INIT_COMMON(number) \
60 .lppaca_ptr = &lppaca[number], \ 60 .lppaca_ptr = &lppaca[number], \
61 .lock_token = 0x8000, \ 61 .lock_token = 0x8000, \
62 .paca_index = (number), /* Paca Index */ \ 62 .paca_index = (number), /* Paca Index */ \
63 .kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL, \ 63 .kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL, \
64 .stab_real = (asrr), /* Real pointer to segment table */ \
65 .stab_addr = (asrv), /* Virt pointer to segment table */ \
66 .cpu_start = (start), /* Processor start */ \
67 .hw_cpu_id = 0xffff, 64 .hw_cpu_id = 0xffff,
68 65
69#ifdef CONFIG_PPC_ISERIES 66#ifdef CONFIG_PPC_ISERIES
@@ -72,30 +69,20 @@ struct lppaca lppaca[] = {
72 69
73#define PACA_INIT(number) \ 70#define PACA_INIT(number) \
74{ \ 71{ \
75 PACA_INIT_COMMON(number, 0, 0, 0) \ 72 PACA_INIT_COMMON(number) \
76 PACA_INIT_ISERIES(number) \
77}
78
79#define BOOTCPU_PACA_INIT(number) \
80{ \
81 PACA_INIT_COMMON(number, 1, 0, (u64)&initial_stab) \
82 PACA_INIT_ISERIES(number) \ 73 PACA_INIT_ISERIES(number) \
83} 74}
84 75
85#else 76#else
86#define PACA_INIT(number) \ 77#define PACA_INIT(number) \
87{ \ 78{ \
88 PACA_INIT_COMMON(number, 0, 0, 0) \ 79 PACA_INIT_COMMON(number) \
89} 80}
90 81
91#define BOOTCPU_PACA_INIT(number) \
92{ \
93 PACA_INIT_COMMON(number, 1, STAB0_PHYS_ADDR, (u64)&initial_stab) \
94}
95#endif 82#endif
96 83
97struct paca_struct paca[] = { 84struct paca_struct paca[] = {
98 BOOTCPU_PACA_INIT(0), 85 PACA_INIT(0),
99#if NR_CPUS > 1 86#if NR_CPUS > 1
100 PACA_INIT( 1), PACA_INIT( 2), PACA_INIT( 3), 87 PACA_INIT( 1), PACA_INIT( 2), PACA_INIT( 3),
101#if NR_CPUS > 4 88#if NR_CPUS > 4
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index d63cd562d9d5..5a24415a2e3c 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -854,35 +854,70 @@ void __init unflatten_device_tree(void)
854 DBG(" <- unflatten_device_tree()\n"); 854 DBG(" <- unflatten_device_tree()\n");
855} 855}
856 856
857
858static int __init early_init_dt_scan_cpus(unsigned long node, 857static int __init early_init_dt_scan_cpus(unsigned long node,
859 const char *uname, int depth, void *data) 858 const char *uname, int depth,
859 void *data)
860{ 860{
861 u32 *prop; 861 static int logical_cpuid = 0;
862 unsigned long size; 862 char *type = of_get_flat_dt_prop(node, "device_type", NULL);
863 char *type = of_get_flat_dt_prop(node, "device_type", &size); 863 u32 *prop, *intserv;
864 int i, nthreads;
865 unsigned long len;
866 int found = 0;
864 867
865 /* We are scanning "cpu" nodes only */ 868 /* We are scanning "cpu" nodes only */
866 if (type == NULL || strcmp(type, "cpu") != 0) 869 if (type == NULL || strcmp(type, "cpu") != 0)
867 return 0; 870 return 0;
868 871
869 boot_cpuid = 0; 872 /* Get physical cpuid */
870 boot_cpuid_phys = 0; 873 intserv = of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", &len);
871 if (initial_boot_params && initial_boot_params->version >= 2) { 874 if (intserv) {
872 /* version 2 of the kexec param format adds the phys cpuid 875 nthreads = len / sizeof(int);
873 * of booted proc.
874 */
875 boot_cpuid_phys = initial_boot_params->boot_cpuid_phys;
876 } else { 876 } else {
877 /* Check if it's the boot-cpu, set it's hw index now */ 877 intserv = of_get_flat_dt_prop(node, "reg", NULL);
878 if (of_get_flat_dt_prop(node, 878 nthreads = 1;
879 }
880
881 /*
882 * Now see if any of these threads match our boot cpu.
883 * NOTE: This must match the parsing done in smp_setup_cpu_maps.
884 */
885 for (i = 0; i < nthreads; i++) {
886 /*
887 * version 2 of the kexec param format adds the phys cpuid of
888 * booted proc.
889 */
890 if (initial_boot_params && initial_boot_params->version >= 2) {
891 if (intserv[i] ==
892 initial_boot_params->boot_cpuid_phys) {
893 found = 1;
894 break;
895 }
896 } else {
897 /*
898 * Check if it's the boot-cpu, set it's hw index now,
899 * unfortunately this format did not support booting
900 * off secondary threads.
901 */
902 if (of_get_flat_dt_prop(node,
879 "linux,boot-cpu", NULL) != NULL) { 903 "linux,boot-cpu", NULL) != NULL) {
880 prop = of_get_flat_dt_prop(node, "reg", NULL); 904 found = 1;
881 if (prop != NULL) 905 break;
882 boot_cpuid_phys = *prop; 906 }
883 } 907 }
908
909#ifdef CONFIG_SMP
910 /* logical cpu id is always 0 on UP kernels */
911 logical_cpuid++;
912#endif
913 }
914
915 if (found) {
916 DBG("boot cpu: logical %d physical %d\n", logical_cpuid,
917 intserv[i]);
918 boot_cpuid = logical_cpuid;
919 set_hard_smp_processor_id(boot_cpuid, intserv[i]);
884 } 920 }
885 set_hard_smp_processor_id(0, boot_cpuid_phys);
886 921
887#ifdef CONFIG_ALTIVEC 922#ifdef CONFIG_ALTIVEC
888 /* Check if we have a VMX and eventually update CPU features */ 923 /* Check if we have a VMX and eventually update CPU features */
@@ -901,16 +936,10 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
901#endif /* CONFIG_ALTIVEC */ 936#endif /* CONFIG_ALTIVEC */
902 937
903#ifdef CONFIG_PPC_PSERIES 938#ifdef CONFIG_PPC_PSERIES
904 /* 939 if (nthreads > 1)
905 * Check for an SMT capable CPU and set the CPU feature. We do
906 * this by looking at the size of the ibm,ppc-interrupt-server#s
907 * property
908 */
909 prop = (u32 *)of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s",
910 &size);
911 cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT;
912 if (prop && ((size / sizeof(u32)) > 1))
913 cur_cpu_spec->cpu_features |= CPU_FTR_SMT; 940 cur_cpu_spec->cpu_features |= CPU_FTR_SMT;
941 else
942 cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT;
914#endif 943#endif
915 944
916 return 0; 945 return 0;
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index c1d62bf11f29..b17630ad4ac7 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -352,12 +352,13 @@ void __init check_for_initrd(void)
352 * must be called before using this. 352 * must be called before using this.
353 * 353 *
354 * While we're here, we may as well set the "physical" cpu ids in the paca. 354 * While we're here, we may as well set the "physical" cpu ids in the paca.
355 *
356 * NOTE: This must match the parsing done in early_init_dt_scan_cpus.
355 */ 357 */
356void __init smp_setup_cpu_maps(void) 358void __init smp_setup_cpu_maps(void)
357{ 359{
358 struct device_node *dn = NULL; 360 struct device_node *dn = NULL;
359 int cpu = 0; 361 int cpu = 0;
360 int swap_cpuid = 0;
361 362
362 while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) { 363 while ((dn = of_find_node_by_type(dn, "cpu")) && cpu < NR_CPUS) {
363 int *intserv; 364 int *intserv;
@@ -376,24 +377,11 @@ void __init smp_setup_cpu_maps(void)
376 for (j = 0; j < nthreads && cpu < NR_CPUS; j++) { 377 for (j = 0; j < nthreads && cpu < NR_CPUS; j++) {
377 cpu_set(cpu, cpu_present_map); 378 cpu_set(cpu, cpu_present_map);
378 set_hard_smp_processor_id(cpu, intserv[j]); 379 set_hard_smp_processor_id(cpu, intserv[j]);
379
380 if (intserv[j] == boot_cpuid_phys)
381 swap_cpuid = cpu;
382 cpu_set(cpu, cpu_possible_map); 380 cpu_set(cpu, cpu_possible_map);
383 cpu++; 381 cpu++;
384 } 382 }
385 } 383 }
386 384
387 /* Swap CPU id 0 with boot_cpuid_phys, so we can always assume that
388 * boot cpu is logical 0.
389 */
390 if (boot_cpuid_phys != get_hard_smp_processor_id(0)) {
391 u32 tmp;
392 tmp = get_hard_smp_processor_id(0);
393 set_hard_smp_processor_id(0, boot_cpuid_phys);
394 set_hard_smp_processor_id(swap_cpuid, tmp);
395 }
396
397#ifdef CONFIG_PPC64 385#ifdef CONFIG_PPC64
398 /* 386 /*
399 * On pSeries LPAR, we need to know how many cpus 387 * On pSeries LPAR, we need to know how many cpus
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 2f3fdad35594..6c9b093c23a5 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -73,7 +73,6 @@
73 73
74int have_of = 1; 74int have_of = 1;
75int boot_cpuid = 0; 75int boot_cpuid = 0;
76int boot_cpuid_phys = 0;
77dev_t boot_dev; 76dev_t boot_dev;
78u64 ppc64_pft_size; 77u64 ppc64_pft_size;
79 78
@@ -208,7 +207,6 @@ static struct machdep_calls __initdata *machines[] = {
208 207
209void __init early_setup(unsigned long dt_ptr) 208void __init early_setup(unsigned long dt_ptr)
210{ 209{
211 struct paca_struct *lpaca = get_paca();
212 static struct machdep_calls **mach; 210 static struct machdep_calls **mach;
213 211
214 /* Enable early debugging if any specified (see udbg.h) */ 212 /* Enable early debugging if any specified (see udbg.h) */
@@ -223,6 +221,14 @@ void __init early_setup(unsigned long dt_ptr)
223 */ 221 */
224 early_init_devtree(__va(dt_ptr)); 222 early_init_devtree(__va(dt_ptr));
225 223
224 /* Now we know the logical id of our boot cpu, setup the paca. */
225 setup_boot_paca();
226
227 /* Fix up paca fields required for the boot cpu */
228 get_paca()->cpu_start = 1;
229 get_paca()->stab_real = __pa((u64)&initial_stab);
230 get_paca()->stab_addr = (u64)&initial_stab;
231
226 /* 232 /*
227 * Iterate all ppc_md structures until we find the proper 233 * Iterate all ppc_md structures until we find the proper
228 * one for the current machine type 234 * one for the current machine type
@@ -260,7 +266,7 @@ void __init early_setup(unsigned long dt_ptr)
260 if (cpu_has_feature(CPU_FTR_SLB)) 266 if (cpu_has_feature(CPU_FTR_SLB))
261 slb_initialize(); 267 slb_initialize();
262 else 268 else
263 stab_initialize(lpaca->stab_real); 269 stab_initialize(get_paca()->stab_real);
264 } 270 }
265 271
266 DBG(" <- early_setup()\n"); 272 DBG(" <- early_setup()\n");