diff options
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r-- | arch/powerpc/kernel/head_64.S | 26 | ||||
-rw-r--r-- | arch/powerpc/kernel/paca.c | 21 | ||||
-rw-r--r-- | arch/powerpc/kernel/prom.c | 83 | ||||
-rw-r--r-- | arch/powerpc/kernel/setup-common.c | 16 | ||||
-rw-r--r-- | arch/powerpc/kernel/setup_64.c | 12 |
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 | ||
97 | struct paca_struct paca[] = { | 84 | struct 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 | |||
858 | static int __init early_init_dt_scan_cpus(unsigned long node, | 857 | static 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 | */ |
356 | void __init smp_setup_cpu_maps(void) | 358 | void __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 | ||
74 | int have_of = 1; | 74 | int have_of = 1; |
75 | int boot_cpuid = 0; | 75 | int boot_cpuid = 0; |
76 | int boot_cpuid_phys = 0; | ||
77 | dev_t boot_dev; | 76 | dev_t boot_dev; |
78 | u64 ppc64_pft_size; | 77 | u64 ppc64_pft_size; |
79 | 78 | ||
@@ -208,7 +207,6 @@ static struct machdep_calls __initdata *machines[] = { | |||
208 | 207 | ||
209 | void __init early_setup(unsigned long dt_ptr) | 208 | void __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"); |