Commit | Line | Data |
---|---|---|
f9ff0f30 SR |
1 | #ifndef _ASM_POWERPC_EXCEPTION_H |
2 | #define _ASM_POWERPC_EXCEPTION_H | |
3 | /* | |
4 | * Extracted from head_64.S | |
5 | * | |
6 | * PowerPC version | |
7 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | |
8 | * | |
9 | * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP | |
10 | * Copyright (C) 1996 Cort Dougan <cort@cs.nmt.edu> | |
11 | * Adapted for Power Macintosh by Paul Mackerras. | |
12 | * Low-level exception handlers and MMU support | |
13 | * rewritten by Paul Mackerras. | |
14 | * Copyright (C) 1996 Paul Mackerras. | |
15 | * | |
16 | * Adapted for 64bit PowerPC by Dave Engebretsen, Peter Bergner, and | |
17 | * Mike Corrigan {engebret|bergner|mikejc}@us.ibm.com | |
18 | * | |
19 | * This file contains the low-level support and setup for the | |
20 | * PowerPC-64 platform, including trap and interrupt dispatch. | |
21 | * | |
22 | * This program is free software; you can redistribute it and/or | |
23 | * modify it under the terms of the GNU General Public License | |
24 | * as published by the Free Software Foundation; either version | |
25 | * 2 of the License, or (at your option) any later version. | |
26 | */ | |
27 | /* | |
28 | * The following macros define the code that appears as | |
29 | * the prologue to each of the exception handlers. They | |
30 | * are split into two parts to allow a single kernel binary | |
31 | * to be used for pSeries and iSeries. | |
32 | * | |
33 | * We make as much of the exception code common between native | |
34 | * exception handlers (including pSeries LPAR) and iSeries LPAR | |
35 | * implementations as possible. | |
36 | */ | |
da2bc464 | 37 | #include <asm/head-64.h> |
2c86cd18 | 38 | #include <asm/feature-fixups.h> |
f9ff0f30 | 39 | |
8c388514 | 40 | /* PACA save area offsets (exgen, exmc, etc) */ |
f9ff0f30 SR |
41 | #define EX_R9 0 |
42 | #define EX_R10 8 | |
43 | #define EX_R11 16 | |
44 | #define EX_R12 24 | |
45 | #define EX_R13 32 | |
36670fcf NP |
46 | #define EX_DAR 40 |
47 | #define EX_DSISR 48 | |
48 | #define EX_CCR 52 | |
635942ae NP |
49 | #define EX_CFAR 56 |
50 | #define EX_PPR 64 | |
8568f1e0 | 51 | #if defined(CONFIG_RELOCATABLE) |
635942ae | 52 | #define EX_CTR 72 |
635942ae | 53 | #define EX_SIZE 10 /* size in u64 units */ |
8568f1e0 NP |
54 | #else |
55 | #define EX_SIZE 9 /* size in u64 units */ | |
56 | #endif | |
dbeea1d6 | 57 | |
ba41e1e1 BS |
58 | /* |
59 | * maximum recursive depth of MCE exceptions | |
60 | */ | |
61 | #define MAX_MCE_DEPTH 4 | |
62 | ||
635942ae NP |
63 | /* |
64 | * EX_R3 is only used by the bad_stack handler. bad_stack reloads and | |
65 | * saves DAR from SPRN_DAR, and EX_DAR is not used. So EX_R3 can overlap | |
66 | * with EX_DAR. | |
67 | */ | |
68 | #define EX_R3 EX_DAR | |
69 | ||
a048a07d NP |
70 | #define STF_ENTRY_BARRIER_SLOT \ |
71 | STF_ENTRY_BARRIER_FIXUP_SECTION; \ | |
72 | nop; \ | |
73 | nop; \ | |
74 | nop | |
75 | ||
76 | #define STF_EXIT_BARRIER_SLOT \ | |
77 | STF_EXIT_BARRIER_FIXUP_SECTION; \ | |
78 | nop; \ | |
79 | nop; \ | |
80 | nop; \ | |
81 | nop; \ | |
82 | nop; \ | |
83 | nop | |
84 | ||
85 | /* | |
86 | * r10 must be free to use, r13 must be paca | |
87 | */ | |
88 | #define INTERRUPT_TO_KERNEL \ | |
89 | STF_ENTRY_BARRIER_SLOT | |
90 | ||
aa8a5e00 ME |
91 | /* |
92 | * Macros for annotating the expected destination of (h)rfid | |
93 | * | |
94 | * The nop instructions allow us to insert one or more instructions to flush the | |
95 | * L1-D cache when returning to userspace or a guest. | |
96 | */ | |
97 | #define RFI_FLUSH_SLOT \ | |
98 | RFI_FLUSH_FIXUP_SECTION; \ | |
99 | nop; \ | |
100 | nop; \ | |
101 | nop | |
50e51c13 NP |
102 | |
103 | #define RFI_TO_KERNEL \ | |
104 | rfid | |
105 | ||
106 | #define RFI_TO_USER \ | |
a048a07d | 107 | STF_EXIT_BARRIER_SLOT; \ |
aa8a5e00 ME |
108 | RFI_FLUSH_SLOT; \ |
109 | rfid; \ | |
110 | b rfi_flush_fallback | |
50e51c13 NP |
111 | |
112 | #define RFI_TO_USER_OR_KERNEL \ | |
a048a07d | 113 | STF_EXIT_BARRIER_SLOT; \ |
aa8a5e00 ME |
114 | RFI_FLUSH_SLOT; \ |
115 | rfid; \ | |
116 | b rfi_flush_fallback | |
50e51c13 NP |
117 | |
118 | #define RFI_TO_GUEST \ | |
a048a07d | 119 | STF_EXIT_BARRIER_SLOT; \ |
aa8a5e00 ME |
120 | RFI_FLUSH_SLOT; \ |
121 | rfid; \ | |
122 | b rfi_flush_fallback | |
50e51c13 NP |
123 | |
124 | #define HRFI_TO_KERNEL \ | |
125 | hrfid | |
126 | ||
127 | #define HRFI_TO_USER \ | |
a048a07d | 128 | STF_EXIT_BARRIER_SLOT; \ |
aa8a5e00 ME |
129 | RFI_FLUSH_SLOT; \ |
130 | hrfid; \ | |
131 | b hrfi_flush_fallback | |
50e51c13 NP |
132 | |
133 | #define HRFI_TO_USER_OR_KERNEL \ | |
a048a07d | 134 | STF_EXIT_BARRIER_SLOT; \ |
aa8a5e00 ME |
135 | RFI_FLUSH_SLOT; \ |
136 | hrfid; \ | |
137 | b hrfi_flush_fallback | |
50e51c13 NP |
138 | |
139 | #define HRFI_TO_GUEST \ | |
a048a07d | 140 | STF_EXIT_BARRIER_SLOT; \ |
aa8a5e00 ME |
141 | RFI_FLUSH_SLOT; \ |
142 | hrfid; \ | |
143 | b hrfi_flush_fallback | |
50e51c13 NP |
144 | |
145 | #define HRFI_TO_UNKNOWN \ | |
a048a07d | 146 | STF_EXIT_BARRIER_SLOT; \ |
aa8a5e00 ME |
147 | RFI_FLUSH_SLOT; \ |
148 | hrfid; \ | |
149 | b hrfi_flush_fallback | |
50e51c13 | 150 | |
4700dfaf | 151 | #ifdef CONFIG_RELOCATABLE |
6ebb9397 | 152 | #define __EXCEPTION_PROLOG_2_RELON(label, h) \ |
4700dfaf MN |
153 | mfspr r11,SPRN_##h##SRR0; /* save SRR0 */ \ |
154 | LOAD_HANDLER(r12,label); \ | |
bc2e6c6a | 155 | mtctr r12; \ |
4700dfaf MN |
156 | mfspr r12,SPRN_##h##SRR1; /* and SRR1 */ \ |
157 | li r10,MSR_RI; \ | |
158 | mtmsrd r10,1; /* Set RI (EE=0) */ \ | |
bc2e6c6a | 159 | bctr; |
4700dfaf MN |
160 | #else |
161 | /* If not relocatable, we can jump directly -- and save messing with LR */ | |
6ebb9397 | 162 | #define __EXCEPTION_PROLOG_2_RELON(label, h) \ |
4700dfaf MN |
163 | mfspr r11,SPRN_##h##SRR0; /* save SRR0 */ \ |
164 | mfspr r12,SPRN_##h##SRR1; /* and SRR1 */ \ | |
165 | li r10,MSR_RI; \ | |
166 | mtmsrd r10,1; /* Set RI (EE=0) */ \ | |
167 | b label; | |
168 | #endif | |
6ebb9397 ME |
169 | #define EXCEPTION_PROLOG_2_RELON(label, h) \ |
170 | __EXCEPTION_PROLOG_2_RELON(label, h) | |
4700dfaf MN |
171 | |
172 | /* | |
bdf08e1d ME |
173 | * As EXCEPTION_PROLOG(), except we've already got relocation on so no need to |
174 | * rfid. Save LR in case we're CONFIG_RELOCATABLE, in which case | |
175 | * EXCEPTION_PROLOG_2_RELON will be using LR. | |
4700dfaf | 176 | */ |
270373f1 | 177 | #define EXCEPTION_RELON_PROLOG(area, label, h, extra, vec) \ |
92b6d65c | 178 | SET_SCRATCH0(r13); /* save r13 */ \ |
1707dd16 | 179 | EXCEPTION_PROLOG_0(area); \ |
4700dfaf | 180 | EXCEPTION_PROLOG_1(area, extra, vec); \ |
6ebb9397 | 181 | EXCEPTION_PROLOG_2_RELON(label, h) |
4700dfaf | 182 | |
f9ff0f30 SR |
183 | /* |
184 | * We're short on space and time in the exception prolog, so we can't | |
27510235 ME |
185 | * use the normal LOAD_REG_IMMEDIATE macro to load the address of label. |
186 | * Instead we get the base of the kernel from paca->kernelbase and or in the low | |
187 | * part of label. This requires that the label be within 64KB of kernelbase, and | |
188 | * that kernelbase be 64K aligned. | |
f9ff0f30 | 189 | */ |
f9ff0f30 | 190 | #define LOAD_HANDLER(reg, label) \ |
d8d42b05 | 191 | ld reg,PACAKBASE(r13); /* get high part of &label */ \ |
4b1f5ccc | 192 | ori reg,reg,FIXED_SYMBOL_ABS_ADDR(label) |
f9ff0f30 | 193 | |
fb479e44 NP |
194 | #define __LOAD_HANDLER(reg, label) \ |
195 | ld reg,PACAKBASE(r13); \ | |
4b1f5ccc | 196 | ori reg,reg,(ABS_ADDR(label))@l |
fb479e44 | 197 | |
a97a65d5 NP |
198 | /* |
199 | * Branches from unrelocated code (e.g., interrupts) to labels outside | |
200 | * head-y require >64K offsets. | |
201 | */ | |
202 | #define __LOAD_FAR_HANDLER(reg, label) \ | |
203 | ld reg,PACAKBASE(r13); \ | |
204 | ori reg,reg,(ABS_ADDR(label))@l; \ | |
4b1f5ccc | 205 | addis reg,reg,(ABS_ADDR(label))@h |
a97a65d5 | 206 | |
a5d4f3ad BH |
207 | /* Exception register prefixes */ |
208 | #define EXC_HV H | |
209 | #define EXC_STD | |
210 | ||
4700dfaf MN |
211 | #if defined(CONFIG_RELOCATABLE) |
212 | /* | |
bc2e6c6a MN |
213 | * If we support interrupts with relocation on AND we're a relocatable kernel, |
214 | * we need to use CTR to get to the 2nd level handler. So, save/restore it | |
215 | * when required. | |
4700dfaf | 216 | */ |
bc2e6c6a MN |
217 | #define SAVE_CTR(reg, area) mfctr reg ; std reg,area+EX_CTR(r13) |
218 | #define GET_CTR(reg, area) ld reg,area+EX_CTR(r13) | |
219 | #define RESTORE_CTR(reg, area) ld reg,area+EX_CTR(r13) ; mtctr reg | |
4700dfaf | 220 | #else |
bc2e6c6a MN |
221 | /* ...else CTR is unused and in register. */ |
222 | #define SAVE_CTR(reg, area) | |
223 | #define GET_CTR(reg, area) mfctr reg | |
224 | #define RESTORE_CTR(reg, area) | |
4700dfaf MN |
225 | #endif |
226 | ||
13e7a8e8 HM |
227 | /* |
228 | * PPR save/restore macros used in exceptions_64s.S | |
229 | * Used for P7 or later processors | |
230 | */ | |
4c2de74c | 231 | #define SAVE_PPR(area, ra) \ |
13e7a8e8 | 232 | BEGIN_FTR_SECTION_NESTED(940) \ |
4c2de74c NP |
233 | ld ra,area+EX_PPR(r13); /* Read PPR from paca */ \ |
234 | std ra,_PPR(r1); \ | |
13e7a8e8 HM |
235 | END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,940) |
236 | ||
237 | #define RESTORE_PPR_PACA(area, ra) \ | |
238 | BEGIN_FTR_SECTION_NESTED(941) \ | |
239 | ld ra,area+EX_PPR(r13); \ | |
240 | mtspr SPRN_PPR,ra; \ | |
241 | END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,941) | |
242 | ||
13e7a8e8 | 243 | /* |
1707dd16 | 244 | * Get an SPR into a register if the CPU has the given feature |
13e7a8e8 | 245 | */ |
1707dd16 | 246 | #define OPT_GET_SPR(ra, spr, ftr) \ |
13e7a8e8 | 247 | BEGIN_FTR_SECTION_NESTED(943) \ |
1707dd16 PM |
248 | mfspr ra,spr; \ |
249 | END_FTR_SECTION_NESTED(ftr,ftr,943) | |
13e7a8e8 | 250 | |
d410ae21 MS |
251 | /* |
252 | * Set an SPR from a register if the CPU has the given feature | |
253 | */ | |
254 | #define OPT_SET_SPR(ra, spr, ftr) \ | |
255 | BEGIN_FTR_SECTION_NESTED(943) \ | |
256 | mtspr spr,ra; \ | |
257 | END_FTR_SECTION_NESTED(ftr,ftr,943) | |
258 | ||
1707dd16 PM |
259 | /* |
260 | * Save a register to the PACA if the CPU has the given feature | |
261 | */ | |
262 | #define OPT_SAVE_REG_TO_PACA(offset, ra, ftr) \ | |
263 | BEGIN_FTR_SECTION_NESTED(943) \ | |
264 | std ra,offset(r13); \ | |
265 | END_FTR_SECTION_NESTED(ftr,ftr,943) | |
266 | ||
544686ca NP |
267 | #define EXCEPTION_PROLOG_0(area) \ |
268 | GET_PACA(r13); \ | |
44e9309f | 269 | std r9,area+EX_R9(r13); /* save r9 */ \ |
1707dd16 PM |
270 | OPT_GET_SPR(r9, SPRN_PPR, CPU_FTR_HAS_PPR); \ |
271 | HMT_MEDIUM; \ | |
44e9309f | 272 | std r10,area+EX_R10(r13); /* save r10 - r12 */ \ |
1707dd16 PM |
273 | OPT_GET_SPR(r10, SPRN_CFAR, CPU_FTR_CFAR) |
274 | ||
f14e953b | 275 | #define __EXCEPTION_PROLOG_1_PRE(area) \ |
1707dd16 PM |
276 | OPT_SAVE_REG_TO_PACA(area+EX_PPR, r9, CPU_FTR_HAS_PPR); \ |
277 | OPT_SAVE_REG_TO_PACA(area+EX_CFAR, r10, CPU_FTR_CFAR); \ | |
a048a07d | 278 | INTERRUPT_TO_KERNEL; \ |
bc2e6c6a | 279 | SAVE_CTR(r10, area); \ |
4b1f5ccc | 280 | mfcr r9 |
f14e953b MS |
281 | |
282 | #define __EXCEPTION_PROLOG_1_POST(area) \ | |
b01c8b54 PM |
283 | std r11,area+EX_R11(r13); \ |
284 | std r12,area+EX_R12(r13); \ | |
285 | GET_SCRATCH0(r10); \ | |
286 | std r10,area+EX_R13(r13) | |
f14e953b MS |
287 | |
288 | /* | |
289 | * This version of the EXCEPTION_PROLOG_1 will carry | |
290 | * addition parameter called "bitmask" to support | |
291 | * checking of the interrupt maskable level in the SOFTEN_TEST. | |
292 | * Intended to be used in MASKABLE_EXCPETION_* macros. | |
293 | */ | |
294 | #define MASKABLE_EXCEPTION_PROLOG_1(area, extra, vec, bitmask) \ | |
295 | __EXCEPTION_PROLOG_1_PRE(area); \ | |
296 | extra(vec, bitmask); \ | |
4b1f5ccc | 297 | __EXCEPTION_PROLOG_1_POST(area) |
f14e953b MS |
298 | |
299 | /* | |
300 | * This version of the EXCEPTION_PROLOG_1 is intended | |
301 | * to be used in STD_EXCEPTION* macros | |
302 | */ | |
303 | #define _EXCEPTION_PROLOG_1(area, extra, vec) \ | |
304 | __EXCEPTION_PROLOG_1_PRE(area); \ | |
305 | extra(vec); \ | |
4b1f5ccc | 306 | __EXCEPTION_PROLOG_1_POST(area) |
f14e953b | 307 | |
b01c8b54 | 308 | #define EXCEPTION_PROLOG_1(area, extra, vec) \ |
f14e953b | 309 | _EXCEPTION_PROLOG_1(area, extra, vec) |
7180e3e6 | 310 | |
cb58a4a4 | 311 | #define __EXCEPTION_PROLOG_2(label, h) \ |
1f6a93e4 | 312 | ld r10,PACAKMSR(r13); /* get MSR value for kernel */ \ |
a5d4f3ad | 313 | mfspr r11,SPRN_##h##SRR0; /* save SRR0 */ \ |
4b1f5ccc | 314 | LOAD_HANDLER(r12,label); \ |
a5d4f3ad BH |
315 | mtspr SPRN_##h##SRR0,r12; \ |
316 | mfspr r12,SPRN_##h##SRR1; /* and SRR1 */ \ | |
317 | mtspr SPRN_##h##SRR1,r10; \ | |
222f20f1 | 318 | h##RFI_TO_KERNEL; \ |
f9ff0f30 | 319 | b . /* prevent speculative execution */ |
cb58a4a4 ME |
320 | #define EXCEPTION_PROLOG_2(label, h) \ |
321 | __EXCEPTION_PROLOG_2(label, h) | |
f9ff0f30 | 322 | |
83a980f7 | 323 | /* _NORI variant keeps MSR_RI clear */ |
94f3cc8e | 324 | #define __EXCEPTION_PROLOG_2_NORI(label, h) \ |
83a980f7 NP |
325 | ld r10,PACAKMSR(r13); /* get MSR value for kernel */ \ |
326 | xori r10,r10,MSR_RI; /* Clear MSR_RI */ \ | |
327 | mfspr r11,SPRN_##h##SRR0; /* save SRR0 */ \ | |
4b1f5ccc | 328 | LOAD_HANDLER(r12,label); \ |
83a980f7 NP |
329 | mtspr SPRN_##h##SRR0,r12; \ |
330 | mfspr r12,SPRN_##h##SRR1; /* and SRR1 */ \ | |
331 | mtspr SPRN_##h##SRR1,r10; \ | |
222f20f1 | 332 | h##RFI_TO_KERNEL; \ |
83a980f7 NP |
333 | b . /* prevent speculative execution */ |
334 | ||
94f3cc8e ME |
335 | #define EXCEPTION_PROLOG_2_NORI(label, h) \ |
336 | __EXCEPTION_PROLOG_2_NORI(label, h) | |
83a980f7 | 337 | |
bdf08e1d | 338 | #define EXCEPTION_PROLOG(area, label, h, extra, vec) \ |
4a7a0a84 | 339 | SET_SCRATCH0(r13); /* save r13 */ \ |
1707dd16 | 340 | EXCEPTION_PROLOG_0(area); \ |
b01c8b54 | 341 | EXCEPTION_PROLOG_1(area, extra, vec); \ |
4b1f5ccc | 342 | EXCEPTION_PROLOG_2(label, h) |
c5a8c0c9 | 343 | |
da2bc464 ME |
344 | #define __KVMTEST(h, n) \ |
345 | lbz r10,HSTATE_IN_GUEST(r13); \ | |
b01c8b54 | 346 | cmpwi r10,0; \ |
da2bc464 | 347 | bne do_kvm_##h##n |
b01c8b54 | 348 | |
dd96b2c2 AK |
349 | #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE |
350 | /* | |
351 | * If hv is possible, interrupts come into to the hv version | |
352 | * of the kvmppc_interrupt code, which then jumps to the PR handler, | |
353 | * kvmppc_interrupt_pr, if the guest is a PR guest. | |
354 | */ | |
355 | #define kvmppc_interrupt kvmppc_interrupt_hv | |
356 | #else | |
357 | #define kvmppc_interrupt kvmppc_interrupt_pr | |
358 | #endif | |
359 | ||
b51351e2 NP |
360 | /* |
361 | * Branch to label using its 0xC000 address. This results in instruction | |
362 | * address suitable for MSR[IR]=0 or 1, which allows relocation to be turned | |
363 | * on using mtmsr rather than rfid. | |
364 | * | |
365 | * This could set the 0xc bits for !RELOCATABLE as an immediate, rather than | |
366 | * load KBASE for a slight optimisation. | |
367 | */ | |
368 | #define BRANCH_TO_C000(reg, label) \ | |
369 | __LOAD_HANDLER(reg, label); \ | |
370 | mtctr reg; \ | |
371 | bctr | |
372 | ||
fb479e44 NP |
373 | #ifdef CONFIG_RELOCATABLE |
374 | #define BRANCH_TO_COMMON(reg, label) \ | |
375 | __LOAD_HANDLER(reg, label); \ | |
376 | mtctr reg; \ | |
377 | bctr | |
378 | ||
be5c5e84 ME |
379 | #define BRANCH_LINK_TO_FAR(label) \ |
380 | __LOAD_FAR_HANDLER(r12, label); \ | |
381 | mtctr r12; \ | |
2337d207 NP |
382 | bctrl |
383 | ||
a97a65d5 NP |
384 | /* |
385 | * KVM requires __LOAD_FAR_HANDLER. | |
386 | * | |
387 | * __BRANCH_TO_KVM_EXIT branches are also a special case because they | |
388 | * explicitly use r9 then reload it from PACA before branching. Hence | |
389 | * the double-underscore. | |
390 | */ | |
391 | #define __BRANCH_TO_KVM_EXIT(area, label) \ | |
392 | mfctr r9; \ | |
393 | std r9,HSTATE_SCRATCH1(r13); \ | |
394 | __LOAD_FAR_HANDLER(r9, label); \ | |
395 | mtctr r9; \ | |
396 | ld r9,area+EX_R9(r13); \ | |
397 | bctr | |
398 | ||
fb479e44 NP |
399 | #else |
400 | #define BRANCH_TO_COMMON(reg, label) \ | |
401 | b label | |
402 | ||
be5c5e84 | 403 | #define BRANCH_LINK_TO_FAR(label) \ |
2337d207 NP |
404 | bl label |
405 | ||
a97a65d5 NP |
406 | #define __BRANCH_TO_KVM_EXIT(area, label) \ |
407 | ld r9,area+EX_R9(r13); \ | |
408 | b label | |
409 | ||
fb479e44 NP |
410 | #endif |
411 | ||
c4f3b52c | 412 | /* Do not enable RI */ |
94f3cc8e | 413 | #define EXCEPTION_PROLOG_NORI(area, label, h, extra, vec) \ |
c4f3b52c NP |
414 | EXCEPTION_PROLOG_0(area); \ |
415 | EXCEPTION_PROLOG_1(area, extra, vec); \ | |
4b1f5ccc | 416 | EXCEPTION_PROLOG_2_NORI(label, h) |
c4f3b52c | 417 | |
a97a65d5 | 418 | |
d3918e7f | 419 | #define __KVM_HANDLER(area, h, n) \ |
0acb9111 PM |
420 | BEGIN_FTR_SECTION_NESTED(947) \ |
421 | ld r10,area+EX_CFAR(r13); \ | |
422 | std r10,HSTATE_CFAR(r13); \ | |
423 | END_FTR_SECTION_NESTED(CPU_FTR_CFAR,CPU_FTR_CFAR,947); \ | |
4b8473c9 PM |
424 | BEGIN_FTR_SECTION_NESTED(948) \ |
425 | ld r10,area+EX_PPR(r13); \ | |
426 | std r10,HSTATE_PPR(r13); \ | |
427 | END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,948); \ | |
b01c8b54 | 428 | ld r10,area+EX_R10(r13); \ |
0acb9111 | 429 | std r12,HSTATE_SCRATCH0(r13); \ |
d3918e7f NP |
430 | sldi r12,r9,32; \ |
431 | ori r12,r12,(n); \ | |
a97a65d5 NP |
432 | /* This reloads r9 before branching to kvmppc_interrupt */ \ |
433 | __BRANCH_TO_KVM_EXIT(area, kvmppc_interrupt) | |
b01c8b54 PM |
434 | |
435 | #define __KVM_HANDLER_SKIP(area, h, n) \ | |
b01c8b54 | 436 | cmpwi r10,KVM_GUEST_MODE_SKIP; \ |
b01c8b54 | 437 | beq 89f; \ |
4b8473c9 | 438 | BEGIN_FTR_SECTION_NESTED(948) \ |
d3918e7f NP |
439 | ld r10,area+EX_PPR(r13); \ |
440 | std r10,HSTATE_PPR(r13); \ | |
4b8473c9 | 441 | END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,948); \ |
d3918e7f | 442 | ld r10,area+EX_R10(r13); \ |
da2bc464 | 443 | std r12,HSTATE_SCRATCH0(r13); \ |
d3918e7f NP |
444 | sldi r12,r9,32; \ |
445 | ori r12,r12,(n); \ | |
a97a65d5 NP |
446 | /* This reloads r9 before branching to kvmppc_interrupt */ \ |
447 | __BRANCH_TO_KVM_EXIT(area, kvmppc_interrupt); \ | |
b01c8b54 PM |
448 | 89: mtocrf 0x80,r9; \ |
449 | ld r9,area+EX_R9(r13); \ | |
d3918e7f | 450 | ld r10,area+EX_R10(r13); \ |
b01c8b54 PM |
451 | b kvmppc_skip_##h##interrupt |
452 | ||
453 | #ifdef CONFIG_KVM_BOOK3S_64_HANDLER | |
da2bc464 | 454 | #define KVMTEST(h, n) __KVMTEST(h, n) |
b01c8b54 PM |
455 | #define KVM_HANDLER(area, h, n) __KVM_HANDLER(area, h, n) |
456 | #define KVM_HANDLER_SKIP(area, h, n) __KVM_HANDLER_SKIP(area, h, n) | |
457 | ||
458 | #else | |
da2bc464 | 459 | #define KVMTEST(h, n) |
b01c8b54 PM |
460 | #define KVM_HANDLER(area, h, n) |
461 | #define KVM_HANDLER_SKIP(area, h, n) | |
462 | #endif | |
463 | ||
464 | #define NOTEST(n) | |
465 | ||
a4087a4d NP |
466 | #define EXCEPTION_PROLOG_COMMON_1() \ |
467 | std r9,_CCR(r1); /* save CR in stackframe */ \ | |
468 | std r11,_NIP(r1); /* save SRR0 in stackframe */ \ | |
469 | std r12,_MSR(r1); /* save SRR1 in stackframe */ \ | |
470 | std r10,0(r1); /* make stack chain pointer */ \ | |
471 | std r0,GPR0(r1); /* save r0 in stackframe */ \ | |
472 | std r10,GPR1(r1); /* save r1 in stackframe */ \ | |
473 | ||
474 | ||
f9ff0f30 SR |
475 | /* |
476 | * The common exception prolog is used for all except a few exceptions | |
477 | * such as a segment miss on a kernel address. We have to be prepared | |
478 | * to take another exception from the point where we first touch the | |
479 | * kernel stack onwards. | |
480 | * | |
481 | * On entry r13 points to the paca, r9-r13 are saved in the paca, | |
482 | * r9 contains the saved CR, r11 and r12 contain the saved SRR0 and | |
483 | * SRR1, and relocation is on. | |
484 | */ | |
485 | #define EXCEPTION_PROLOG_COMMON(n, area) \ | |
486 | andi. r10,r12,MSR_PR; /* See if coming from user */ \ | |
487 | mr r10,r1; /* Save r1 */ \ | |
488 | subi r1,r1,INT_FRAME_SIZE; /* alloc frame on kernel stack */ \ | |
489 | beq- 1f; \ | |
490 | ld r1,PACAKSAVE(r13); /* kernel stack to use */ \ | |
90ff5d68 | 491 | 1: cmpdi cr1,r1,-INT_FRAME_SIZE; /* check if r1 is in userspace */ \ |
1977b502 PM |
492 | blt+ cr1,3f; /* abort if it is */ \ |
493 | li r1,(n); /* will be reloaded later */ \ | |
f9ff0f30 | 494 | sth r1,PACA_TRAP_SAVE(r13); \ |
1977b502 PM |
495 | std r3,area+EX_R3(r13); \ |
496 | addi r3,r13,area; /* r3 -> where regs are saved*/ \ | |
bc2e6c6a | 497 | RESTORE_CTR(r1, area); \ |
f9ff0f30 | 498 | b bad_stack; \ |
a4087a4d | 499 | 3: EXCEPTION_PROLOG_COMMON_1(); \ |
890274c2 | 500 | kuap_save_amr_and_lock r9, r10, cr1, cr0; \ |
5d75b264 | 501 | beq 4f; /* if from kernel mode */ \ |
c223c903 | 502 | ACCOUNT_CPU_USER_ENTRY(r13, r9, r10); \ |
4c2de74c | 503 | SAVE_PPR(area, r9); \ |
b14a7253 MS |
504 | 4: EXCEPTION_PROLOG_COMMON_2(area) \ |
505 | EXCEPTION_PROLOG_COMMON_3(n) \ | |
506 | ACCOUNT_STOLEN_TIME | |
507 | ||
508 | /* Save original regs values from save area to stack frame. */ | |
509 | #define EXCEPTION_PROLOG_COMMON_2(area) \ | |
f9ff0f30 SR |
510 | ld r9,area+EX_R9(r13); /* move r9, r10 to stackframe */ \ |
511 | ld r10,area+EX_R10(r13); \ | |
512 | std r9,GPR9(r1); \ | |
513 | std r10,GPR10(r1); \ | |
514 | ld r9,area+EX_R11(r13); /* move r11 - r13 to stackframe */ \ | |
515 | ld r10,area+EX_R12(r13); \ | |
516 | ld r11,area+EX_R13(r13); \ | |
517 | std r9,GPR11(r1); \ | |
518 | std r10,GPR12(r1); \ | |
519 | std r11,GPR13(r1); \ | |
48404f2e PM |
520 | BEGIN_FTR_SECTION_NESTED(66); \ |
521 | ld r10,area+EX_CFAR(r13); \ | |
522 | std r10,ORIG_GPR3(r1); \ | |
523 | END_FTR_SECTION_NESTED(CPU_FTR_CFAR, CPU_FTR_CFAR, 66); \ | |
b14a7253 MS |
524 | GET_CTR(r10, area); \ |
525 | std r10,_CTR(r1); | |
526 | ||
527 | #define EXCEPTION_PROLOG_COMMON_3(n) \ | |
528 | std r2,GPR2(r1); /* save r2 in stackframe */ \ | |
529 | SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \ | |
530 | SAVE_2GPRS(7, r1); /* save r7, r8 in stackframe */ \ | |
bc2e6c6a | 531 | mflr r9; /* Get LR, later save to stack */ \ |
f9ff0f30 | 532 | ld r2,PACATOC(r13); /* get kernel TOC into r2 */ \ |
f9ff0f30 | 533 | std r9,_LINK(r1); \ |
4e26bc4a | 534 | lbz r10,PACAIRQSOFTMASK(r13); \ |
f9ff0f30 SR |
535 | mfspr r11,SPRN_XER; /* save XER in stackframe */ \ |
536 | std r10,SOFTE(r1); \ | |
537 | std r11,_XER(r1); \ | |
538 | li r9,(n)+1; \ | |
539 | std r9,_TRAP(r1); /* set trap number */ \ | |
540 | li r10,0; \ | |
541 | ld r11,exception_marker@toc(r2); \ | |
542 | std r10,RESULT(r1); /* clear regs->result */ \ | |
b14a7253 | 543 | std r11,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame */ |
f9ff0f30 SR |
544 | |
545 | /* | |
546 | * Exception vectors. | |
547 | */ | |
e899fce5 | 548 | #define STD_EXCEPTION(vec, label) \ |
bdf08e1d | 549 | EXCEPTION_PROLOG(PACA_EXGEN, label, EXC_STD, KVMTEST_PR, vec); |
f9ff0f30 | 550 | |
1707dd16 | 551 | /* Version of above for when we have to branch out-of-line */ |
da2bc464 | 552 | #define __OOL_EXCEPTION(vec, label, hdlr) \ |
4b1f5ccc NP |
553 | SET_SCRATCH0(r13); \ |
554 | EXCEPTION_PROLOG_0(PACA_EXGEN); \ | |
555 | b hdlr | |
da2bc464 | 556 | |
75e8bef3 | 557 | #define STD_EXCEPTION_OOL(vec, label) \ |
da2bc464 | 558 | EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST_PR, vec); \ |
cb58a4a4 | 559 | EXCEPTION_PROLOG_2(label, EXC_STD) |
da2bc464 ME |
560 | |
561 | #define STD_EXCEPTION_HV(loc, vec, label) \ | |
4b1f5ccc | 562 | EXCEPTION_PROLOG(PACA_EXGEN, label, EXC_HV, KVMTEST_HV, vec) |
f9ff0f30 | 563 | |
da2bc464 ME |
564 | #define STD_EXCEPTION_HV_OOL(vec, label) \ |
565 | EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST_HV, vec); \ | |
cb58a4a4 | 566 | EXCEPTION_PROLOG_2(label, EXC_HV) |
1707dd16 | 567 | |
e42389c5 | 568 | #define STD_RELON_EXCEPTION(loc, vec, label) \ |
4700dfaf | 569 | /* No guest interrupts come through here */ \ |
4b1f5ccc | 570 | EXCEPTION_RELON_PROLOG(PACA_EXGEN, label, EXC_STD, NOTEST, vec) |
4700dfaf | 571 | |
b706f423 | 572 | #define STD_RELON_EXCEPTION_OOL(vec, label) \ |
c9f69518 | 573 | EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, vec); \ |
6ebb9397 | 574 | EXCEPTION_PROLOG_2_RELON(label, EXC_STD) |
1707dd16 | 575 | |
4700dfaf | 576 | #define STD_RELON_EXCEPTION_HV(loc, vec, label) \ |
4b1f5ccc | 577 | EXCEPTION_RELON_PROLOG(PACA_EXGEN, label, EXC_HV, KVMTEST_HV, vec) |
4700dfaf | 578 | |
1707dd16 | 579 | #define STD_RELON_EXCEPTION_HV_OOL(vec, label) \ |
bc355125 | 580 | EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST_HV, vec); \ |
6ebb9397 | 581 | EXCEPTION_PROLOG_2_RELON(label, EXC_HV) |
1707dd16 | 582 | |
7230c564 BH |
583 | /* This associate vector numbers with bits in paca->irq_happened */ |
584 | #define SOFTEN_VALUE_0x500 PACA_IRQ_EE | |
7230c564 | 585 | #define SOFTEN_VALUE_0x900 PACA_IRQ_DEC |
1dbdafec | 586 | #define SOFTEN_VALUE_0xa00 PACA_IRQ_DBELL |
655bb3f4 | 587 | #define SOFTEN_VALUE_0xe80 PACA_IRQ_DBELL |
0869b6fd | 588 | #define SOFTEN_VALUE_0xe60 PACA_IRQ_HMI |
9baaef0a | 589 | #define SOFTEN_VALUE_0xea0 PACA_IRQ_EE |
f442d004 | 590 | #define SOFTEN_VALUE_0xf00 PACA_IRQ_PMI |
7230c564 | 591 | |
f14e953b | 592 | #define __SOFTEN_TEST(h, vec, bitmask) \ |
4e26bc4a | 593 | lbz r10,PACAIRQSOFTMASK(r13); \ |
f14e953b | 594 | andi. r10,r10,bitmask; \ |
7230c564 | 595 | li r10,SOFTEN_VALUE_##vec; \ |
01417c6c | 596 | bne masked_##h##interrupt |
da2bc464 | 597 | |
f14e953b | 598 | #define _SOFTEN_TEST(h, vec, bitmask) __SOFTEN_TEST(h, vec, bitmask) |
b01c8b54 | 599 | |
f14e953b | 600 | #define SOFTEN_TEST_PR(vec, bitmask) \ |
da2bc464 | 601 | KVMTEST(EXC_STD, vec); \ |
f14e953b | 602 | _SOFTEN_TEST(EXC_STD, vec, bitmask) |
b01c8b54 | 603 | |
f14e953b | 604 | #define SOFTEN_TEST_HV(vec, bitmask) \ |
da2bc464 | 605 | KVMTEST(EXC_HV, vec); \ |
f14e953b | 606 | _SOFTEN_TEST(EXC_HV, vec, bitmask) |
b01c8b54 | 607 | |
da2bc464 ME |
608 | #define KVMTEST_PR(vec) \ |
609 | KVMTEST(EXC_STD, vec) | |
610 | ||
611 | #define KVMTEST_HV(vec) \ | |
612 | KVMTEST(EXC_HV, vec) | |
613 | ||
f14e953b MS |
614 | #define SOFTEN_NOTEST_PR(vec, bitmask) _SOFTEN_TEST(EXC_STD, vec, bitmask) |
615 | #define SOFTEN_NOTEST_HV(vec, bitmask) _SOFTEN_TEST(EXC_HV, vec, bitmask) | |
4700dfaf | 616 | |
0a55c241 | 617 | #define __MASKABLE_EXCEPTION(vec, label, h, extra, bitmask) \ |
b01c8b54 | 618 | SET_SCRATCH0(r13); /* save r13 */ \ |
1707dd16 | 619 | EXCEPTION_PROLOG_0(PACA_EXGEN); \ |
f14e953b | 620 | MASKABLE_EXCEPTION_PROLOG_1(PACA_EXGEN, extra, vec, bitmask); \ |
4b1f5ccc | 621 | EXCEPTION_PROLOG_2(label, h) |
1707dd16 | 622 | |
b536da7c | 623 | #define MASKABLE_EXCEPTION(vec, label, bitmask) \ |
0a55c241 | 624 | __MASKABLE_EXCEPTION(vec, label, EXC_STD, SOFTEN_TEST_PR, bitmask) |
b3e6b5df | 625 | |
0a55c241 | 626 | #define MASKABLE_EXCEPTION_OOL(vec, label, bitmask) \ |
f14e953b | 627 | MASKABLE_EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_TEST_PR, vec, bitmask);\ |
cb58a4a4 | 628 | EXCEPTION_PROLOG_2(label, EXC_STD) |
da2bc464 | 629 | |
b536da7c | 630 | #define MASKABLE_EXCEPTION_HV(vec, label, bitmask) \ |
0a55c241 | 631 | __MASKABLE_EXCEPTION(vec, label, EXC_HV, SOFTEN_TEST_HV, bitmask) |
f9ff0f30 | 632 | |
f14e953b MS |
633 | #define MASKABLE_EXCEPTION_HV_OOL(vec, label, bitmask) \ |
634 | MASKABLE_EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_TEST_HV, vec, bitmask);\ | |
cb58a4a4 | 635 | EXCEPTION_PROLOG_2(label, EXC_HV) |
1707dd16 | 636 | |
0a55c241 | 637 | #define __MASKABLE_RELON_EXCEPTION(vec, label, h, extra, bitmask) \ |
4700dfaf | 638 | SET_SCRATCH0(r13); /* save r13 */ \ |
1707dd16 | 639 | EXCEPTION_PROLOG_0(PACA_EXGEN); \ |
f14e953b | 640 | MASKABLE_EXCEPTION_PROLOG_1(PACA_EXGEN, extra, vec, bitmask); \ |
6ebb9397 | 641 | EXCEPTION_PROLOG_2_RELON(label, h) |
da2bc464 | 642 | |
b536da7c | 643 | #define MASKABLE_RELON_EXCEPTION(vec, label, bitmask) \ |
0a55c241 | 644 | __MASKABLE_RELON_EXCEPTION(vec, label, EXC_STD, SOFTEN_NOTEST_PR, bitmask) |
4700dfaf | 645 | |
0a55c241 | 646 | #define MASKABLE_RELON_EXCEPTION_OOL(vec, label, bitmask) \ |
f442d004 | 647 | MASKABLE_EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_NOTEST_PR, vec, bitmask);\ |
4b1f5ccc | 648 | EXCEPTION_PROLOG_2(label, EXC_STD) |
f442d004 | 649 | |
b536da7c | 650 | #define MASKABLE_RELON_EXCEPTION_HV(vec, label, bitmask) \ |
0a55c241 | 651 | __MASKABLE_RELON_EXCEPTION(vec, label, EXC_HV, SOFTEN_TEST_HV, bitmask) |
4700dfaf | 652 | |
f14e953b | 653 | #define MASKABLE_RELON_EXCEPTION_HV_OOL(vec, label, bitmask) \ |
5c11d1e5 | 654 | MASKABLE_EXCEPTION_PROLOG_1(PACA_EXGEN, SOFTEN_TEST_HV, vec, bitmask);\ |
6ebb9397 | 655 | EXCEPTION_PROLOG_2_RELON(label, EXC_HV) |
1707dd16 | 656 | |
1b701179 BH |
657 | /* |
658 | * Our exception common code can be passed various "additions" | |
659 | * to specify the behaviour of interrupts, whether to kick the | |
660 | * runlatch, etc... | |
661 | */ | |
662 | ||
9daf112b ME |
663 | /* |
664 | * This addition reconciles our actual IRQ state with the various software | |
665 | * flags that track it. This may call C code. | |
666 | */ | |
667 | #define ADD_RECONCILE RECONCILE_IRQ_STATE(r10,r11) | |
f9ff0f30 | 668 | |
fe1952fc | 669 | #define ADD_NVGPRS \ |
b1576fec | 670 | bl save_nvgprs |
fe1952fc BH |
671 | |
672 | #define RUNLATCH_ON \ | |
673 | BEGIN_FTR_SECTION \ | |
c911d2e1 | 674 | ld r3, PACA_THREAD_INFO(r13); \ |
fe1952fc BH |
675 | ld r4,TI_LOCAL_FLAGS(r3); \ |
676 | andi. r0,r4,_TLF_RUNLATCH; \ | |
677 | beql ppc64_runlatch_on_trampoline; \ | |
678 | END_FTR_SECTION_IFSET(CPU_FTR_CTRL) | |
679 | ||
a3d96f70 NP |
680 | #define EXCEPTION_COMMON(area, trap, label, hdlr, ret, additions) \ |
681 | EXCEPTION_PROLOG_COMMON(trap, area); \ | |
a1d711c5 | 682 | /* Volatile regs are potentially clobbered here */ \ |
fe1952fc BH |
683 | additions; \ |
684 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | |
685 | bl hdlr; \ | |
686 | b ret | |
687 | ||
b1ee8a3d NP |
688 | /* |
689 | * Exception where stack is already set in r1, r1 is saved in r10, and it | |
690 | * continues rather than returns. | |
691 | */ | |
692 | #define EXCEPTION_COMMON_NORET_STACK(area, trap, label, hdlr, additions) \ | |
693 | EXCEPTION_PROLOG_COMMON_1(); \ | |
890274c2 | 694 | kuap_save_amr_and_lock r9, r10, cr1; \ |
b1ee8a3d NP |
695 | EXCEPTION_PROLOG_COMMON_2(area); \ |
696 | EXCEPTION_PROLOG_COMMON_3(trap); \ | |
697 | /* Volatile regs are potentially clobbered here */ \ | |
698 | additions; \ | |
699 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | |
700 | bl hdlr | |
701 | ||
fe1952fc | 702 | #define STD_EXCEPTION_COMMON(trap, label, hdlr) \ |
a3d96f70 NP |
703 | EXCEPTION_COMMON(PACA_EXGEN, trap, label, hdlr, \ |
704 | ret_from_except, ADD_NVGPRS;ADD_RECONCILE) | |
f9ff0f30 SR |
705 | |
706 | /* | |
707 | * Like STD_EXCEPTION_COMMON, but for exceptions that can occur | |
7450f6f0 BH |
708 | * in the idle task and therefore need the special idle handling |
709 | * (finish nap and runlatch) | |
f9ff0f30 | 710 | */ |
a3d96f70 NP |
711 | #define STD_EXCEPTION_COMMON_ASYNC(trap, label, hdlr) \ |
712 | EXCEPTION_COMMON(PACA_EXGEN, trap, label, hdlr, \ | |
713 | ret_from_except_lite, FINISH_NAP;ADD_RECONCILE;RUNLATCH_ON) | |
f9ff0f30 SR |
714 | |
715 | /* | |
716 | * When the idle code in power4_idle puts the CPU into NAP mode, | |
717 | * it has to do so in a loop, and relies on the external interrupt | |
718 | * and decrementer interrupt entry code to get it out of the loop. | |
719 | * It sets the _TLF_NAPPING bit in current_thread_info()->local_flags | |
720 | * to signal that it is in the loop and needs help to get out. | |
721 | */ | |
722 | #ifdef CONFIG_PPC_970_NAP | |
723 | #define FINISH_NAP \ | |
724 | BEGIN_FTR_SECTION \ | |
c911d2e1 | 725 | ld r11, PACA_THREAD_INFO(r13); \ |
f9ff0f30 SR |
726 | ld r9,TI_LOCAL_FLAGS(r11); \ |
727 | andi. r10,r9,_TLF_NAPPING; \ | |
728 | bnel power4_fixup_nap; \ | |
729 | END_FTR_SECTION_IFSET(CPU_FTR_CAN_NAP) | |
730 | #else | |
731 | #define FINISH_NAP | |
732 | #endif | |
733 | ||
734 | #endif /* _ASM_POWERPC_EXCEPTION_H */ |