Blame view
arch/powerpc/kernel/paca.c
5.97 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 |
/* * c 2001 PPC 64 Team, IBM Corp * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ |
2cd947f17 powerpc: Use nr_c... |
9 |
#include <linux/smp.h> |
4b16f8e2d powerpc: various ... |
10 |
#include <linux/export.h> |
95f72d1ed lmb: rename to me... |
11 |
#include <linux/memblock.h> |
1da177e4c Linux-2.6.12-rc2 |
12 |
|
1426d5a3b powerpc: Dynamica... |
13 |
#include <asm/firmware.h> |
1da177e4c Linux-2.6.12-rc2 |
14 |
#include <asm/lppaca.h> |
1da177e4c Linux-2.6.12-rc2 |
15 |
#include <asm/paca.h> |
549e8152d powerpc: Make the... |
16 |
#include <asm/sections.h> |
dce6670aa powerpc: Add PACA... |
17 |
#include <asm/pgtable.h> |
1426d5a3b powerpc: Dynamica... |
18 19 |
#include <asm/iseries/lpar_map.h> #include <asm/iseries/hv_types.h> |
1fc711f7f powerpc/kexec: Fi... |
20 |
#include <asm/kexec.h> |
1da177e4c Linux-2.6.12-rc2 |
21 22 23 24 |
/* This symbol is provided by the linker - let it fill in the paca * field correctly */ extern unsigned long __toc_start; |
91c60b5b8 powerpc: Separate... |
25 |
#ifdef CONFIG_PPC_BOOK3S |
3356bb9f7 [PATCH] powerpc: ... |
26 |
/* |
30ff2e87e [POWERPC] iSeries... |
27 |
* The structure which the hypervisor knows about - this structure |
3356bb9f7 [PATCH] powerpc: ... |
28 29 |
* should not cross a page boundary. The vpa_init/register_vpa call * is now known to fail if the lppaca structure crosses a page |
30ff2e87e [POWERPC] iSeries... |
30 31 32 33 |
* boundary. The lppaca is also used on legacy iSeries and POWER5 * pSeries boxes. The lppaca is 640 bytes long, and cannot readily * change since the hypervisor knows its layout, so a 1kB alignment * will suffice to ensure that it doesn't cross a page boundary. |
3356bb9f7 [PATCH] powerpc: ... |
34 35 |
*/ struct lppaca lppaca[] = { |
93c22703e powerpc: Dynamica... |
36 |
[0 ... (NR_LPPACAS-1)] = { |
3356bb9f7 [PATCH] powerpc: ... |
37 38 39 40 41 42 43 44 |
.desc = 0xd397d781, /* "LpPa" */ .size = sizeof(struct lppaca), .dyn_proc_status = 2, .decr_val = 0x00ff0000, .fpregs_in_use = 1, .end_of_quantum = 0xfffffffffffffffful, .slb_count = 64, .vmxregs_in_use = 0, |
409001948 powerpc: Update p... |
45 |
.page_ins = 0, |
3356bb9f7 [PATCH] powerpc: ... |
46 47 |
}, }; |
93c22703e powerpc: Dynamica... |
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
static struct lppaca *extra_lppacas; static long __initdata lppaca_size; static void allocate_lppacas(int nr_cpus, unsigned long limit) { if (nr_cpus <= NR_LPPACAS) return; lppaca_size = PAGE_ALIGN(sizeof(struct lppaca) * (nr_cpus - NR_LPPACAS)); extra_lppacas = __va(memblock_alloc_base(lppaca_size, PAGE_SIZE, limit)); } static struct lppaca *new_lppaca(int cpu) { struct lppaca *lp; if (cpu < NR_LPPACAS) return &lppaca[cpu]; lp = extra_lppacas + (cpu - NR_LPPACAS); *lp = lppaca[0]; return lp; } static void free_lppacas(void) { long new_size = 0, nr; if (!lppaca_size) return; nr = num_possible_cpus() - NR_LPPACAS; if (nr > 0) new_size = PAGE_ALIGN(nr * sizeof(struct lppaca)); if (new_size >= lppaca_size) return; memblock_free(__pa(extra_lppacas) + new_size, lppaca_size - new_size); lppaca_size = new_size; } #else |
3c4b76449 powerpc: Fix comp... |
92 |
static inline void allocate_lppacas(int nr_cpus, unsigned long limit) { } |
93c22703e powerpc: Dynamica... |
93 |
static inline void free_lppacas(void) { } |
91c60b5b8 powerpc: Separate... |
94 95 96 |
#endif /* CONFIG_PPC_BOOK3S */ #ifdef CONFIG_PPC_STD_MMU_64 |
2f6093c84 [POWERPC] Impleme... |
97 98 99 100 101 102 103 104 105 106 |
/* * 3 persistent SLBs are registered here. The buffer will be zero * initially, hence will all be invaild until we actually write them. */ struct slb_shadow slb_shadow[] __cacheline_aligned = { [0 ... (NR_CPUS-1)] = { .persistent = SLB_NUM_BOLTED, .buffer_length = sizeof(struct slb_shadow), }, }; |
91c60b5b8 powerpc: Separate... |
107 |
#endif /* CONFIG_PPC_STD_MMU_64 */ |
8882a4da1 [PATCH] powerpc: ... |
108 |
/* The Paca is an array with one entry per processor. Each contains an |
1da177e4c Linux-2.6.12-rc2 |
109 |
* lppaca, which contains the information shared between the |
1888e7b51 [PATCH] powerpc: ... |
110 |
* hypervisor and Linux. |
1da177e4c Linux-2.6.12-rc2 |
111 112 113 114 115 116 |
* On systems with hardware multi-threading, there are two threads * per processor. The Paca array must contain an entry for each thread. * The VPD Areas will give a max logical processors = 2 * max physical * processors. The processor VPD array needs one entry per physical * processor (not thread). */ |
1426d5a3b powerpc: Dynamica... |
117 |
struct paca_struct *paca; |
1da177e4c Linux-2.6.12-rc2 |
118 |
EXPORT_SYMBOL(paca); |
90035fe37 [POWERPC] Raise t... |
119 |
|
1426d5a3b powerpc: Dynamica... |
120 |
struct paca_struct boot_paca; |
90035fe37 [POWERPC] Raise t... |
121 |
|
1426d5a3b powerpc: Dynamica... |
122 123 124 125 126 |
void __init initialise_paca(struct paca_struct *new_paca, int cpu) { /* The TOC register (GPR2) points 32kB into the TOC, so that 64kB * of the TOC can be addressed using a single machine instruction. */ |
90035fe37 [POWERPC] Raise t... |
127 |
unsigned long kernel_toc = (unsigned long)(&__toc_start) + 0x8000UL; |
91c60b5b8 powerpc: Separate... |
128 |
#ifdef CONFIG_PPC_BOOK3S |
93c22703e powerpc: Dynamica... |
129 |
new_paca->lppaca_ptr = new_lppaca(cpu); |
dce6670aa powerpc: Add PACA... |
130 |
#else |
1426d5a3b powerpc: Dynamica... |
131 |
new_paca->kernel_pgd = swapper_pg_dir; |
91c60b5b8 powerpc: Separate... |
132 |
#endif |
1426d5a3b powerpc: Dynamica... |
133 134 135 136 137 138 |
new_paca->lock_token = 0x8000; new_paca->paca_index = cpu; new_paca->kernel_toc = kernel_toc; new_paca->kernelbase = (unsigned long) _stext; new_paca->kernel_msr = MSR_KERNEL; new_paca->hw_cpu_id = 0xffff; |
1fc711f7f powerpc/kexec: Fi... |
139 |
new_paca->kexec_state = KEXEC_STATE_NONE; |
1426d5a3b powerpc: Dynamica... |
140 |
new_paca->__current = &init_task; |
91c60b5b8 powerpc: Separate... |
141 |
#ifdef CONFIG_PPC_STD_MMU_64 |
1426d5a3b powerpc: Dynamica... |
142 |
new_paca->slb_shadow_ptr = &slb_shadow[cpu]; |
91c60b5b8 powerpc: Separate... |
143 |
#endif /* CONFIG_PPC_STD_MMU_64 */ |
1426d5a3b powerpc: Dynamica... |
144 |
} |
fc53b4202 powerpc/kexec: Sw... |
145 146 147 |
/* Put the paca pointer into r13 and SPRG_PACA */ void setup_paca(struct paca_struct *new_paca) { |
2dd60d79e powerpc: In HV mo... |
148 |
/* Setup r13 */ |
fc53b4202 powerpc/kexec: Sw... |
149 |
local_paca = new_paca; |
2dd60d79e powerpc: In HV mo... |
150 |
|
fc53b4202 powerpc/kexec: Sw... |
151 |
#ifdef CONFIG_PPC_BOOK3E |
2dd60d79e powerpc: In HV mo... |
152 |
/* On Book3E, initialize the TLB miss exception frames */ |
fc53b4202 powerpc/kexec: Sw... |
153 |
mtspr(SPRN_SPRG_TLB_EXFRAME, local_paca->extlb); |
2dd60d79e powerpc: In HV mo... |
154 155 156 157 158 |
#else /* In HV mode, we setup both HPACA and PACA to avoid problems * if we do a GET_PACA() before the feature fixups have been * applied */ |
969391c58 powerpc, KVM: Spl... |
159 |
if (cpu_has_feature(CPU_FTR_HVMODE)) |
2dd60d79e powerpc: In HV mo... |
160 |
mtspr(SPRN_SPRG_HPACA, local_paca); |
fc53b4202 powerpc/kexec: Sw... |
161 |
#endif |
2dd60d79e powerpc: In HV mo... |
162 |
mtspr(SPRN_SPRG_PACA, local_paca); |
fc53b4202 powerpc/kexec: Sw... |
163 |
} |
1426d5a3b powerpc: Dynamica... |
164 165 166 167 |
static int __initdata paca_size; void __init allocate_pacas(void) { |
2cd947f17 powerpc: Use nr_c... |
168 |
int cpu, limit; |
1426d5a3b powerpc: Dynamica... |
169 170 171 172 173 174 175 |
/* * We can't take SLB misses on the paca, and we want to access them * in real mode, so allocate them within the RMA and also within * the first segment. On iSeries they must be within the area mapped * by the HV, which is HvPagesToMap * HVPAGESIZE bytes. */ |
cd3db0c4c memblock: Remove ... |
176 |
limit = min(0x10000000ULL, ppc64_rma_size); |
1426d5a3b powerpc: Dynamica... |
177 178 |
if (firmware_has_feature(FW_FEATURE_ISERIES)) limit = min(limit, HvPagesToMap * HVPAGESIZE); |
2cd947f17 powerpc: Use nr_c... |
179 |
paca_size = PAGE_ALIGN(sizeof(struct paca_struct) * nr_cpu_ids); |
1426d5a3b powerpc: Dynamica... |
180 |
|
95f72d1ed lmb: rename to me... |
181 |
paca = __va(memblock_alloc_base(paca_size, PAGE_SIZE, limit)); |
1426d5a3b powerpc: Dynamica... |
182 183 184 185 |
memset(paca, 0, paca_size); printk(KERN_DEBUG "Allocated %u bytes for %d pacas at %p ", |
2cd947f17 powerpc: Use nr_c... |
186 |
paca_size, nr_cpu_ids, paca); |
1426d5a3b powerpc: Dynamica... |
187 |
|
2cd947f17 powerpc: Use nr_c... |
188 |
allocate_lppacas(nr_cpu_ids, limit); |
93c22703e powerpc: Dynamica... |
189 |
|
1426d5a3b powerpc: Dynamica... |
190 |
/* Can't use for_each_*_cpu, as they aren't functional yet */ |
2cd947f17 powerpc: Use nr_c... |
191 |
for (cpu = 0; cpu < nr_cpu_ids; cpu++) |
1426d5a3b powerpc: Dynamica... |
192 193 194 195 196 197 |
initialise_paca(&paca[cpu], cpu); } void __init free_unused_pacas(void) { int new_size; |
c1854e007 powerpc: Set nr_c... |
198 |
new_size = PAGE_ALIGN(sizeof(struct paca_struct) * nr_cpu_ids); |
1426d5a3b powerpc: Dynamica... |
199 200 201 |
if (new_size >= paca_size) return; |
95f72d1ed lmb: rename to me... |
202 |
memblock_free(__pa(paca) + new_size, paca_size - new_size); |
1426d5a3b powerpc: Dynamica... |
203 204 205 206 |
printk(KERN_DEBUG "Freed %u bytes for unused pacas ", paca_size - new_size); |
90035fe37 [POWERPC] Raise t... |
207 |
|
1426d5a3b powerpc: Dynamica... |
208 |
paca_size = new_size; |
93c22703e powerpc: Dynamica... |
209 210 |
free_lppacas(); |
90035fe37 [POWERPC] Raise t... |
211 |
} |