Skip to content

Commit a97a65d

Browse files
npigginmpe
authored andcommitted
KVM: PPC: Book3S: 64-bit CONFIG_RELOCATABLE support for interrupts
64-bit Book3S exception handlers must find the dynamic kernel base to add to the target address when branching beyond __end_interrupts, in order to support kernel running at non-0 physical address. Support this in KVM by branching with CTR, similarly to regular interrupt handlers. The guest CTR saved in HSTATE_SCRATCH1 and restored after the branch. Without this, the host kernel hangs and crashes randomly when it is running at a non-0 address and a KVM guest is started. Signed-off-by: Nicholas Piggin <[email protected]> Acked-by: Paul Mackerras <[email protected]> Signed-off-by: Michael Ellerman <[email protected]>
1 parent 7ede531 commit a97a65d

File tree

4 files changed

+58
-8
lines changed

4 files changed

+58
-8
lines changed

arch/powerpc/include/asm/exception-64s.h

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,15 @@
9797
ld reg,PACAKBASE(r13); \
9898
ori reg,reg,(ABS_ADDR(label))@l;
9999

100+
/*
101+
* Branches from unrelocated code (e.g., interrupts) to labels outside
102+
* head-y require >64K offsets.
103+
*/
104+
#define __LOAD_FAR_HANDLER(reg, label) \
105+
ld reg,PACAKBASE(r13); \
106+
ori reg,reg,(ABS_ADDR(label))@l; \
107+
addis reg,reg,(ABS_ADDR(label))@h;
108+
100109
/* Exception register prefixes */
101110
#define EXC_HV H
102111
#define EXC_STD
@@ -227,12 +236,40 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
227236
mtctr reg; \
228237
bctr
229238

239+
/*
240+
* KVM requires __LOAD_FAR_HANDLER.
241+
*
242+
* __BRANCH_TO_KVM_EXIT branches are also a special case because they
243+
* explicitly use r9 then reload it from PACA before branching. Hence
244+
* the double-underscore.
245+
*/
246+
#define __BRANCH_TO_KVM_EXIT(area, label) \
247+
mfctr r9; \
248+
std r9,HSTATE_SCRATCH1(r13); \
249+
__LOAD_FAR_HANDLER(r9, label); \
250+
mtctr r9; \
251+
ld r9,area+EX_R9(r13); \
252+
bctr
253+
254+
#define BRANCH_TO_KVM(reg, label) \
255+
__LOAD_FAR_HANDLER(reg, label); \
256+
mtctr reg; \
257+
bctr
258+
230259
#else
231260
#define BRANCH_TO_COMMON(reg, label) \
232261
b label
233262

263+
#define BRANCH_TO_KVM(reg, label) \
264+
b label
265+
266+
#define __BRANCH_TO_KVM_EXIT(area, label) \
267+
ld r9,area+EX_R9(r13); \
268+
b label
269+
234270
#endif
235271

272+
236273
#define __KVM_HANDLER(area, h, n) \
237274
BEGIN_FTR_SECTION_NESTED(947) \
238275
ld r10,area+EX_CFAR(r13); \
@@ -246,8 +283,8 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
246283
std r12,HSTATE_SCRATCH0(r13); \
247284
sldi r12,r9,32; \
248285
ori r12,r12,(n); \
249-
ld r9,area+EX_R9(r13); \
250-
b kvmppc_interrupt
286+
/* This reloads r9 before branching to kvmppc_interrupt */ \
287+
__BRANCH_TO_KVM_EXIT(area, kvmppc_interrupt)
251288

252289
#define __KVM_HANDLER_SKIP(area, h, n) \
253290
cmpwi r10,KVM_GUEST_MODE_SKIP; \
@@ -260,8 +297,8 @@ END_FTR_SECTION_NESTED(ftr,ftr,943)
260297
std r12,HSTATE_SCRATCH0(r13); \
261298
sldi r12,r9,32; \
262299
ori r12,r12,(n); \
263-
ld r9,area+EX_R9(r13); \
264-
b kvmppc_interrupt; \
300+
/* This reloads r9 before branching to kvmppc_interrupt */ \
301+
__BRANCH_TO_KVM_EXIT(area, kvmppc_interrupt); \
265302
89: mtocrf 0x80,r9; \
266303
ld r9,area+EX_R9(r13); \
267304
ld r10,area+EX_R10(r13); \

arch/powerpc/kernel/exceptions-64s.S

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_300)
142142
lbz r0,HSTATE_HWTHREAD_REQ(r13)
143143
cmpwi r0,0
144144
beq 1f
145-
b kvm_start_guest
145+
BRANCH_TO_KVM(r10, kvm_start_guest)
146146
1:
147147
#endif
148148

arch/powerpc/kvm/book3s_hv_rmhandlers.S

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,15 +1060,16 @@ kvmppc_interrupt_hv:
10601060
* R12 = (guest CR << 32) | interrupt vector
10611061
* R13 = PACA
10621062
* guest R12 saved in shadow VCPU SCRATCH0
1063+
* guest CTR saved in shadow VCPU SCRATCH1 if RELOCATABLE
10631064
* guest R13 saved in SPRN_SCRATCH0
10641065
*/
1065-
std r9, HSTATE_SCRATCH1(r13)
1066+
std r9, HSTATE_SCRATCH2(r13)
10661067
lbz r9, HSTATE_IN_GUEST(r13)
10671068
cmpwi r9, KVM_GUEST_MODE_HOST_HV
10681069
beq kvmppc_bad_host_intr
10691070
#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
10701071
cmpwi r9, KVM_GUEST_MODE_GUEST
1071-
ld r9, HSTATE_SCRATCH1(r13)
1072+
ld r9, HSTATE_SCRATCH2(r13)
10721073
beq kvmppc_interrupt_pr
10731074
#endif
10741075
/* We're now back in the host but in guest MMU context */
@@ -1088,7 +1089,7 @@ kvmppc_interrupt_hv:
10881089
std r6, VCPU_GPR(R6)(r9)
10891090
std r7, VCPU_GPR(R7)(r9)
10901091
std r8, VCPU_GPR(R8)(r9)
1091-
ld r0, HSTATE_SCRATCH1(r13)
1092+
ld r0, HSTATE_SCRATCH2(r13)
10921093
std r0, VCPU_GPR(R9)(r9)
10931094
std r10, VCPU_GPR(R10)(r9)
10941095
std r11, VCPU_GPR(R11)(r9)
@@ -1151,7 +1152,12 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
11511152
11: stw r3,VCPU_HEIR(r9)
11521153

11531154
/* these are volatile across C function calls */
1155+
#ifdef CONFIG_RELOCATABLE
1156+
ld r3, HSTATE_SCRATCH1(r13)
1157+
mtctr r3
1158+
#else
11541159
mfctr r3
1160+
#endif
11551161
mfxer r4
11561162
std r3, VCPU_CTR(r9)
11571163
std r4, VCPU_XER(r9)

arch/powerpc/kvm/book3s_segment.S

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,9 +175,16 @@ kvmppc_interrupt_pr:
175175
* R12 = (guest CR << 32) | exit handler id
176176
* R13 = PACA
177177
* HSTATE.SCRATCH0 = guest R12
178+
* HSTATE.SCRATCH1 = guest CTR if RELOCATABLE
178179
*/
179180
#ifdef CONFIG_PPC64
180181
/* Match 32-bit entry */
182+
#ifdef CONFIG_RELOCATABLE
183+
std r9, HSTATE_SCRATCH2(r13)
184+
ld r9, HSTATE_SCRATCH1(r13)
185+
mtctr r9
186+
ld r9, HSTATE_SCRATCH2(r13)
187+
#endif
181188
rotldi r12, r12, 32 /* Flip R12 halves for stw */
182189
stw r12, HSTATE_SCRATCH1(r13) /* CR is now in the low half */
183190
srdi r12, r12, 32 /* shift trap into low half */

0 commit comments

Comments
 (0)