diff options
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/include/asm/paca.h | 18 | ||||
-rw-r--r-- | arch/powerpc/kernel/head_64.S | 6 | ||||
-rw-r--r-- | arch/powerpc/kernel/paca.c | 93 | ||||
-rw-r--r-- | arch/powerpc/kernel/prom.c | 3 | ||||
-rw-r--r-- | arch/powerpc/kernel/setup-common.c | 3 | ||||
-rw-r--r-- | arch/powerpc/kernel/setup_64.c | 12 | ||||
-rw-r--r-- | arch/powerpc/platforms/iseries/exception.S | 25 |
7 files changed, 118 insertions, 42 deletions
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index d8a693109c82..a011603d4079 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h | |||
@@ -14,6 +14,9 @@ | |||
14 | #define _ASM_POWERPC_PACA_H | 14 | #define _ASM_POWERPC_PACA_H |
15 | #ifdef __KERNEL__ | 15 | #ifdef __KERNEL__ |
16 | 16 | ||
17 | #ifdef CONFIG_PPC64 | ||
18 | |||
19 | #include <linux/init.h> | ||
17 | #include <asm/types.h> | 20 | #include <asm/types.h> |
18 | #include <asm/lppaca.h> | 21 | #include <asm/lppaca.h> |
19 | #include <asm/mmu.h> | 22 | #include <asm/mmu.h> |
@@ -145,8 +148,19 @@ struct paca_struct { | |||
145 | #endif | 148 | #endif |
146 | }; | 149 | }; |
147 | 150 | ||
148 | extern struct paca_struct paca[]; | 151 | extern struct paca_struct *paca; |
149 | extern void initialise_pacas(void); | 152 | extern __initdata struct paca_struct boot_paca; |
153 | extern void initialise_paca(struct paca_struct *new_paca, int cpu); | ||
154 | |||
155 | extern void allocate_pacas(void); | ||
156 | extern void free_unused_pacas(void); | ||
157 | |||
158 | #else /* CONFIG_PPC64 */ | ||
159 | |||
160 | static inline void allocate_pacas(void) { }; | ||
161 | static inline void free_unused_pacas(void) { }; | ||
162 | |||
163 | #endif /* CONFIG_PPC64 */ | ||
150 | 164 | ||
151 | #endif /* __KERNEL__ */ | 165 | #endif /* __KERNEL__ */ |
152 | #endif /* _ASM_POWERPC_PACA_H */ | 166 | #endif /* _ASM_POWERPC_PACA_H */ |
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 925807488022..b24b7001ae19 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
@@ -219,7 +219,8 @@ generic_secondary_common_init: | |||
219 | * physical cpu id in r24, we need to search the pacas to find | 219 | * physical cpu id in r24, we need to search the pacas to find |
220 | * which logical id maps to our physical one. | 220 | * which logical id maps to our physical one. |
221 | */ | 221 | */ |
222 | LOAD_REG_ADDR(r13, paca) /* Get base vaddr of paca array */ | 222 | LOAD_REG_ADDR(r13, paca) /* Load paca pointer */ |
223 | ld r13,0(r13) /* Get base vaddr of paca array */ | ||
223 | li r5,0 /* logical cpu id */ | 224 | li r5,0 /* logical cpu id */ |
224 | 1: lhz r6,PACAHWCPUID(r13) /* Load HW procid from paca */ | 225 | 1: lhz r6,PACAHWCPUID(r13) /* Load HW procid from paca */ |
225 | cmpw r6,r24 /* Compare to our id */ | 226 | cmpw r6,r24 /* Compare to our id */ |
@@ -536,7 +537,8 @@ _GLOBAL(pmac_secondary_start) | |||
536 | mtmsrd r3 /* RI on */ | 537 | mtmsrd r3 /* RI on */ |
537 | 538 | ||
538 | /* Set up a paca value for this processor. */ | 539 | /* Set up a paca value for this processor. */ |
539 | LOAD_REG_ADDR(r4,paca) /* Get base vaddr of paca array */ | 540 | LOAD_REG_ADDR(r4,paca) /* Load paca pointer */ |
541 | ld r4,0(r4) /* Get base vaddr of paca array */ | ||
540 | mulli r13,r24,PACA_SIZE /* Calculate vaddr of right paca */ | 542 | mulli r13,r24,PACA_SIZE /* Calculate vaddr of right paca */ |
541 | add r13,r13,r4 /* for this processor. */ | 543 | add r13,r13,r4 /* for this processor. */ |
542 | mtspr SPRN_SPRG_PACA,r13 /* Save vaddr of paca in an SPRG*/ | 544 | mtspr SPRN_SPRG_PACA,r13 /* Save vaddr of paca in an SPRG*/ |
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c index d16b1ea55d44..0c40c6f476fe 100644 --- a/arch/powerpc/kernel/paca.c +++ b/arch/powerpc/kernel/paca.c | |||
@@ -9,11 +9,15 @@ | |||
9 | 9 | ||
10 | #include <linux/threads.h> | 10 | #include <linux/threads.h> |
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/lmb.h> | ||
12 | 13 | ||
14 | #include <asm/firmware.h> | ||
13 | #include <asm/lppaca.h> | 15 | #include <asm/lppaca.h> |
14 | #include <asm/paca.h> | 16 | #include <asm/paca.h> |
15 | #include <asm/sections.h> | 17 | #include <asm/sections.h> |
16 | #include <asm/pgtable.h> | 18 | #include <asm/pgtable.h> |
19 | #include <asm/iseries/lpar_map.h> | ||
20 | #include <asm/iseries/hv_types.h> | ||
17 | 21 | ||
18 | /* This symbol is provided by the linker - let it fill in the paca | 22 | /* This symbol is provided by the linker - let it fill in the paca |
19 | * field correctly */ | 23 | * field correctly */ |
@@ -70,37 +74,82 @@ struct slb_shadow slb_shadow[] __cacheline_aligned = { | |||
70 | * processors. The processor VPD array needs one entry per physical | 74 | * processors. The processor VPD array needs one entry per physical |
71 | * processor (not thread). | 75 | * processor (not thread). |
72 | */ | 76 | */ |
73 | struct paca_struct paca[NR_CPUS]; | 77 | struct paca_struct *paca; |
74 | EXPORT_SYMBOL(paca); | 78 | EXPORT_SYMBOL(paca); |
75 | 79 | ||
76 | void __init initialise_pacas(void) | 80 | struct paca_struct boot_paca; |
77 | { | ||
78 | int cpu; | ||
79 | 81 | ||
80 | /* The TOC register (GPR2) points 32kB into the TOC, so that 64kB | 82 | void __init initialise_paca(struct paca_struct *new_paca, int cpu) |
81 | * of the TOC can be addressed using a single machine instruction. | 83 | { |
82 | */ | 84 | /* The TOC register (GPR2) points 32kB into the TOC, so that 64kB |
85 | * of the TOC can be addressed using a single machine instruction. | ||
86 | */ | ||
83 | unsigned long kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL; | 87 | unsigned long kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL; |
84 | 88 | ||
85 | /* Can't use for_each_*_cpu, as they aren't functional yet */ | ||
86 | for (cpu = 0; cpu < NR_CPUS; cpu++) { | ||
87 | struct paca_struct *new_paca = &paca[cpu]; | ||
88 | |||
89 | #ifdef CONFIG_PPC_BOOK3S | 89 | #ifdef CONFIG_PPC_BOOK3S |
90 | new_paca->lppaca_ptr = &lppaca[cpu]; | 90 | new_paca->lppaca_ptr = &lppaca[cpu]; |
91 | #else | 91 | #else |
92 | new_paca->kernel_pgd = swapper_pg_dir; | 92 | new_paca->kernel_pgd = swapper_pg_dir; |
93 | #endif | 93 | #endif |
94 | new_paca->lock_token = 0x8000; | 94 | new_paca->lock_token = 0x8000; |
95 | new_paca->paca_index = cpu; | 95 | new_paca->paca_index = cpu; |
96 | new_paca->kernel_toc = kernel_toc; | 96 | new_paca->kernel_toc = kernel_toc; |
97 | new_paca->kernelbase = (unsigned long) _stext; | 97 | new_paca->kernelbase = (unsigned long) _stext; |
98 | new_paca->kernel_msr = MSR_KERNEL; | 98 | new_paca->kernel_msr = MSR_KERNEL; |
99 | new_paca->hw_cpu_id = 0xffff; | 99 | new_paca->hw_cpu_id = 0xffff; |
100 | new_paca->__current = &init_task; | 100 | new_paca->__current = &init_task; |
101 | #ifdef CONFIG_PPC_STD_MMU_64 | 101 | #ifdef CONFIG_PPC_STD_MMU_64 |
102 | new_paca->slb_shadow_ptr = &slb_shadow[cpu]; | 102 | new_paca->slb_shadow_ptr = &slb_shadow[cpu]; |
103 | #endif /* CONFIG_PPC_STD_MMU_64 */ | 103 | #endif /* CONFIG_PPC_STD_MMU_64 */ |
104 | } | ||
105 | |||
106 | static int __initdata paca_size; | ||
107 | |||
108 | void __init allocate_pacas(void) | ||
109 | { | ||
110 | int nr_cpus, cpu, limit; | ||
111 | |||
112 | /* | ||
113 | * We can't take SLB misses on the paca, and we want to access them | ||
114 | * in real mode, so allocate them within the RMA and also within | ||
115 | * the first segment. On iSeries they must be within the area mapped | ||
116 | * by the HV, which is HvPagesToMap * HVPAGESIZE bytes. | ||
117 | */ | ||
118 | limit = min(0x10000000ULL, lmb.rmo_size); | ||
119 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | ||
120 | limit = min(limit, HvPagesToMap * HVPAGESIZE); | ||
121 | |||
122 | nr_cpus = NR_CPUS; | ||
123 | /* On iSeries we know we can never have more than 64 cpus */ | ||
124 | if (firmware_has_feature(FW_FEATURE_ISERIES)) | ||
125 | nr_cpus = min(64, nr_cpus); | ||
126 | |||
127 | paca_size = PAGE_ALIGN(sizeof(struct paca_struct) * nr_cpus); | ||
128 | |||
129 | paca = __va(lmb_alloc_base(paca_size, PAGE_SIZE, limit)); | ||
130 | memset(paca, 0, paca_size); | ||
131 | |||
132 | printk(KERN_DEBUG "Allocated %u bytes for %d pacas at %p\n", | ||
133 | paca_size, nr_cpus, paca); | ||
134 | |||
135 | /* Can't use for_each_*_cpu, as they aren't functional yet */ | ||
136 | for (cpu = 0; cpu < nr_cpus; cpu++) | ||
137 | initialise_paca(&paca[cpu], cpu); | ||
138 | } | ||
139 | |||
140 | void __init free_unused_pacas(void) | ||
141 | { | ||
142 | int new_size; | ||
143 | |||
144 | new_size = PAGE_ALIGN(sizeof(struct paca_struct) * num_possible_cpus()); | ||
145 | |||
146 | if (new_size >= paca_size) | ||
147 | return; | ||
148 | |||
149 | lmb_free(__pa(paca) + new_size, paca_size - new_size); | ||
150 | |||
151 | printk(KERN_DEBUG "Freed %u bytes for unused pacas\n", | ||
152 | paca_size - new_size); | ||
104 | 153 | ||
105 | } | 154 | paca_size = new_size; |
106 | } | 155 | } |
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 43238b2054b6..05131d634e73 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <asm/smp.h> | 43 | #include <asm/smp.h> |
44 | #include <asm/system.h> | 44 | #include <asm/system.h> |
45 | #include <asm/mmu.h> | 45 | #include <asm/mmu.h> |
46 | #include <asm/paca.h> | ||
46 | #include <asm/pgtable.h> | 47 | #include <asm/pgtable.h> |
47 | #include <asm/pci.h> | 48 | #include <asm/pci.h> |
48 | #include <asm/iommu.h> | 49 | #include <asm/iommu.h> |
@@ -721,6 +722,8 @@ void __init early_init_devtree(void *params) | |||
721 | * FIXME .. and the initrd too? */ | 722 | * FIXME .. and the initrd too? */ |
722 | move_device_tree(); | 723 | move_device_tree(); |
723 | 724 | ||
725 | allocate_pacas(); | ||
726 | |||
724 | DBG("Scanning CPUs ...\n"); | 727 | DBG("Scanning CPUs ...\n"); |
725 | 728 | ||
726 | /* Retreive CPU related informations from the flat tree | 729 | /* Retreive CPU related informations from the flat tree |
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 03dd6a248198..48f0a008b20b 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/lmb.h> | 36 | #include <linux/lmb.h> |
37 | #include <linux/of_platform.h> | 37 | #include <linux/of_platform.h> |
38 | #include <asm/io.h> | 38 | #include <asm/io.h> |
39 | #include <asm/paca.h> | ||
39 | #include <asm/prom.h> | 40 | #include <asm/prom.h> |
40 | #include <asm/processor.h> | 41 | #include <asm/processor.h> |
41 | #include <asm/vdso_datapage.h> | 42 | #include <asm/vdso_datapage.h> |
@@ -493,6 +494,8 @@ void __init smp_setup_cpu_maps(void) | |||
493 | * here will have to be reworked | 494 | * here will have to be reworked |
494 | */ | 495 | */ |
495 | cpu_init_thread_core_maps(nthreads); | 496 | cpu_init_thread_core_maps(nthreads); |
497 | |||
498 | free_unused_pacas(); | ||
496 | } | 499 | } |
497 | #endif /* CONFIG_SMP */ | 500 | #endif /* CONFIG_SMP */ |
498 | 501 | ||
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 6568406b2a30..63547394048c 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -144,9 +144,9 @@ early_param("smt-enabled", early_smt_enabled); | |||
144 | #endif /* CONFIG_SMP */ | 144 | #endif /* CONFIG_SMP */ |
145 | 145 | ||
146 | /* Put the paca pointer into r13 and SPRG_PACA */ | 146 | /* Put the paca pointer into r13 and SPRG_PACA */ |
147 | void __init setup_paca(int cpu) | 147 | static void __init setup_paca(struct paca_struct *new_paca) |
148 | { | 148 | { |
149 | local_paca = &paca[cpu]; | 149 | local_paca = new_paca; |
150 | mtspr(SPRN_SPRG_PACA, local_paca); | 150 | mtspr(SPRN_SPRG_PACA, local_paca); |
151 | #ifdef CONFIG_PPC_BOOK3E | 151 | #ifdef CONFIG_PPC_BOOK3E |
152 | mtspr(SPRN_SPRG_TLB_EXFRAME, local_paca->extlb); | 152 | mtspr(SPRN_SPRG_TLB_EXFRAME, local_paca->extlb); |
@@ -176,14 +176,12 @@ void __init early_setup(unsigned long dt_ptr) | |||
176 | { | 176 | { |
177 | /* -------- printk is _NOT_ safe to use here ! ------- */ | 177 | /* -------- printk is _NOT_ safe to use here ! ------- */ |
178 | 178 | ||
179 | /* Fill in any unititialised pacas */ | ||
180 | initialise_pacas(); | ||
181 | |||
182 | /* Identify CPU type */ | 179 | /* Identify CPU type */ |
183 | identify_cpu(0, mfspr(SPRN_PVR)); | 180 | identify_cpu(0, mfspr(SPRN_PVR)); |
184 | 181 | ||
185 | /* Assume we're on cpu 0 for now. Don't write to the paca yet! */ | 182 | /* Assume we're on cpu 0 for now. Don't write to the paca yet! */ |
186 | setup_paca(0); | 183 | initialise_paca(&boot_paca, 0); |
184 | setup_paca(&boot_paca); | ||
187 | 185 | ||
188 | /* Initialize lockdep early or else spinlocks will blow */ | 186 | /* Initialize lockdep early or else spinlocks will blow */ |
189 | lockdep_init(); | 187 | lockdep_init(); |
@@ -203,7 +201,7 @@ void __init early_setup(unsigned long dt_ptr) | |||
203 | early_init_devtree(__va(dt_ptr)); | 201 | early_init_devtree(__va(dt_ptr)); |
204 | 202 | ||
205 | /* Now we know the logical id of our boot cpu, setup the paca. */ | 203 | /* Now we know the logical id of our boot cpu, setup the paca. */ |
206 | setup_paca(boot_cpuid); | 204 | setup_paca(&paca[boot_cpuid]); |
207 | 205 | ||
208 | /* Fix up paca fields required for the boot cpu */ | 206 | /* Fix up paca fields required for the boot cpu */ |
209 | get_paca()->cpu_start = 1; | 207 | get_paca()->cpu_start = 1; |
diff --git a/arch/powerpc/platforms/iseries/exception.S b/arch/powerpc/platforms/iseries/exception.S index 5369653dcf6a..fba5bf915073 100644 --- a/arch/powerpc/platforms/iseries/exception.S +++ b/arch/powerpc/platforms/iseries/exception.S | |||
@@ -43,17 +43,14 @@ system_reset_iSeries: | |||
43 | LOAD_REG_ADDR(r23, alpaca) | 43 | LOAD_REG_ADDR(r23, alpaca) |
44 | li r0,ALPACA_SIZE | 44 | li r0,ALPACA_SIZE |
45 | sub r23,r13,r23 | 45 | sub r23,r13,r23 |
46 | divdu r23,r23,r0 /* r23 has cpu number */ | 46 | divdu r24,r23,r0 /* r24 has cpu number */ |
47 | LOAD_REG_ADDR(r13, paca) | ||
48 | mulli r0,r23,PACA_SIZE | ||
49 | add r13,r13,r0 | ||
50 | mtspr SPRN_SPRG_PACA,r13 /* Save it away for the future */ | ||
51 | mfmsr r24 | ||
52 | ori r24,r24,MSR_RI | ||
53 | mtmsrd r24 /* RI on */ | ||
54 | mr r24,r23 | ||
55 | cmpwi 0,r24,0 /* Are we processor 0? */ | 47 | cmpwi 0,r24,0 /* Are we processor 0? */ |
56 | bne 1f | 48 | bne 1f |
49 | LOAD_REG_ADDR(r13, boot_paca) | ||
50 | mtspr SPRN_SPRG_PACA,r13 /* Save it away for the future */ | ||
51 | mfmsr r23 | ||
52 | ori r23,r23,MSR_RI | ||
53 | mtmsrd r23 /* RI on */ | ||
57 | b .__start_initialization_iSeries /* Start up the first processor */ | 54 | b .__start_initialization_iSeries /* Start up the first processor */ |
58 | 1: mfspr r4,SPRN_CTRLF | 55 | 1: mfspr r4,SPRN_CTRLF |
59 | li r5,CTRL_RUNLATCH /* Turn off the run light */ | 56 | li r5,CTRL_RUNLATCH /* Turn off the run light */ |
@@ -86,6 +83,16 @@ system_reset_iSeries: | |||
86 | #endif | 83 | #endif |
87 | 84 | ||
88 | 2: | 85 | 2: |
86 | /* Load our paca now that it's been allocated */ | ||
87 | LOAD_REG_ADDR(r13, paca) | ||
88 | ld r13,0(r13) | ||
89 | mulli r0,r24,PACA_SIZE | ||
90 | add r13,r13,r0 | ||
91 | mtspr SPRN_SPRG_PACA,r13 /* Save it away for the future */ | ||
92 | mfmsr r23 | ||
93 | ori r23,r23,MSR_RI | ||
94 | mtmsrd r23 /* RI on */ | ||
95 | |||
89 | HMT_LOW | 96 | HMT_LOW |
90 | #ifdef CONFIG_SMP | 97 | #ifdef CONFIG_SMP |
91 | lbz r23,PACAPROCSTART(r13) /* Test if this processor | 98 | lbz r23,PACAPROCSTART(r13) /* Test if this processor |