/* * These are branched to from interrupt handlers in exception-64s.S which set * IKVM_REAL or IKVM_VIRT, if HSTATE_IN_GUEST was found to be non-zero.
*/
/* * This is a hcall, so register convention is as * Documentation/arch/powerpc/papr_hcalls.rst. * * This may also be a syscall from PR-KVM userspace that is to be * reflected to the PR guest kernel, so registers may be set up for * a system call rather than hcall. We don't currently clobber * anything here, but the 0xc00 handler has already clobbered CTR * and CR0, so PR-KVM can not support a guest kernel that preserves * those registers across its system calls. * * The state of registers is as kvmppc_interrupt, except CFAR is not * saved, R13 is not in SCRATCH0, and R10 does not contain the trap.
*/
.global kvmppc_hcall
.balign IFETCH_ALIGN_BYTES
kvmppc_hcall:
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
lbz r10,HSTATE_IN_GUEST(r13)
cmpwi r10,KVM_GUEST_MODE_HV_P9
beq kvmppc_p9_exit_hcall
#endif ld r10,PACA_EXGEN+EX_R13(r13)
SET_SCRATCH0(r10)
li r10,0xc00 /* Now we look like kvmppc_interrupt */
li r11,PACA_EXGEN
b .Lgot_save_area
/* * KVM interrupt entry occurs after GEN_INT_ENTRY runs, and follows that * call convention: * * guest R9-R13, CTR, CFAR, PPR saved in PACA EX_xxx save area * guest (H)DAR, (H)DSISR are also in the save area for relevant interrupts * guest R13 also saved in SCRATCH0 * R13 = PACA * R11 = (H)SRR0 * R12 = (H)SRR1 * R9 = guest CR * PPR is set to medium * * With the addition for KVM: * R10 = trap vector
*/
.global kvmppc_interrupt
.balign IFETCH_ALIGN_BYTES
kvmppc_interrupt:
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
std r10,HSTATE_SCRATCH0(r13)
lbz r10,HSTATE_IN_GUEST(r13)
cmpwi r10,KVM_GUEST_MODE_HV_P9
beq kvmppc_p9_exit_interrupt ld r10,HSTATE_SCRATCH0(r13)
#endif
li r11,PACA_EXGEN
cmpdi r10,0x200
bgt+ .Lgot_save_area
li r11,PACA_EXMC
beq .Lgot_save_area
li r11,PACA_EXNMI
.Lgot_save_area:
add r11,r11,r13
BEGIN_FTR_SECTION ld r12,EX_CFAR(r11)
std r12,HSTATE_CFAR(r13)
END_FTR_SECTION_IFSET(CPU_FTR_CFAR) ld r12,EX_CTR(r11)
mtctr r12
BEGIN_FTR_SECTION ld r12,EX_PPR(r11)
std r12,HSTATE_PPR(r13)
END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) ld r12,EX_R12(r11)
std r12,HSTATE_SCRATCH0(r13)
sldi r12,r9,32
or r12,r12,r10 ld r9,EX_R9(r11) ld r10,EX_R10(r11) ld r11,EX_R11(r11)
/* * Hcalls and other interrupts come here after normalising register * contents and save locations: * * R12 = (guest CR << 32) | interrupt vector * R13 = PACA * guest R12 saved in shadow HSTATE_SCRATCH0 * guest R13 saved in SPRN_SCRATCH0
*/
std r9,HSTATE_SCRATCH2(r13)
lbz r9,HSTATE_IN_GUEST(r13)
cmpwi r9,KVM_GUEST_MODE_SKIP
beq- .Lmaybe_skip
.Lno_skip:
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE
cmpwi r9,KVM_GUEST_MODE_GUEST
beq kvmppc_interrupt_pr
#endif
b kvmppc_interrupt_hv
#else
b kvmppc_interrupt_pr
#endif
/* * "Skip" interrupts are part of a trick KVM uses a with hash guests to load * the faulting instruction in guest memory from the hypervisor without * walking page tables. * * When the guest takes a fault that requires the hypervisor to load the * instruction (e.g., MMIO emulation), KVM is running in real-mode with HV=1 * and the guest MMU context loaded. It sets KVM_GUEST_MODE_SKIP, and sets * MSR[DR]=1 while leaving MSR[IR]=0, so it continues to fetch HV instructions * but loads and stores will access the guest context. This is used to load * the faulting instruction using the faulting guest effective address. * * However the guest context may not be able to translate, or it may cause a * machine check or other issue, which results in a fault in the host * (even with KVM-HV). * * These faults come here because KVM_GUEST_MODE_SKIP was set, so if they * are (or are likely) caused by that load, the instruction is skipped by * just returning with the PC advanced +4, where it is noticed the load did * not execute and it goes to the slow path which walks the page tables to * read guest memory.
*/
.Lmaybe_skip:
cmpwi r12,BOOK3S_INTERRUPT_MACHINE_CHECK
beq 1f
cmpwi r12,BOOK3S_INTERRUPT_DATA_STORAGE
beq 1f
cmpwi r12,BOOK3S_INTERRUPT_DATA_SEGMENT
beq 1f
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE /* HSRR interrupts get 2 added to interrupt number */
cmpwi r12,BOOK3S_INTERRUPT_H_DATA_STORAGE | 0x2
beq 2f
#endif
b .Lno_skip
1: mfspr r9,SPRN_SRR0
addi r9,r9,4
mtspr SPRN_SRR0,r9 ld r12,HSTATE_SCRATCH0(r13) ld r9,HSTATE_SCRATCH2(r13)
GET_SCRATCH0(r13)
RFI_TO_KERNEL
#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
2: mfspr r9,SPRN_HSRR0
addi r9,r9,4
mtspr SPRN_HSRR0,r9 ld r12,HSTATE_SCRATCH0(r13) ld r9,HSTATE_SCRATCH2(r13)
GET_SCRATCH0(r13)
HRFI_TO_KERNEL
#endif
/* * void kvmppc_p9_enter_guest(struct vcpu *vcpu); * * Enter the guest on a ISAv3.0 or later system.
*/
.balign IFETCH_ALIGN_BYTES
_GLOBAL(kvmppc_p9_enter_guest)
EXPORT_SYMBOL_GPL(kvmppc_p9_enter_guest)
mflr r0
std r0,PPC_LR_STKOFF(r1)
stdu r1,-SFS(r1)
/* * Use UV_RETURN ultracall to return control back to the Ultravisor * after processing an hypercall or interrupt that was forwarded * (a.k.a. reflected) to the Hypervisor. * * All registers have already been reloaded except the ucall requires: * R0 = hcall result * R2 = SRR1, so UV can detect a synthesized interrupt (if any) * R3 = UV_RETURN
*/
.Lret_to_ultra:
mtcr r1 ld r1,VCPU_GPR(R1)(r3)
/* * kvmppc_p9_exit_hcall and kvmppc_p9_exit_interrupt are branched to from * above if the interrupt was taken for a guest that was entered via * kvmppc_p9_enter_guest(). * * The exit code recovers the host stack and vcpu pointer, saves all guest GPRs * and CR, LR, XER as well as guest MSR and NIA into the VCPU, then re- * establishes the host stack and registers to return from the * kvmppc_p9_enter_guest() function, which saves CTR and other guest registers * (SPRs and FP, VEC, etc).
*/
.balign IFETCH_ALIGN_BYTES
kvmppc_p9_exit_hcall:
mfspr r11,SPRN_SRR0
mfspr r12,SPRN_SRR1
li r10,0xc00
std r10,HSTATE_SCRATCH0(r13)
.balign IFETCH_ALIGN_BYTES
kvmppc_p9_exit_interrupt: /* * If set to KVM_GUEST_MODE_HV_P9 but we're still in the * hypervisor, that means we can't return from the entry stack.
*/
rldicl. r10,r12,64-MSR_HV_LG,63
bne- kvmppc_p9_bad_interrupt
/* * Flush the link stack here, before executing the first blr on the * way out of the guest. * * The link stack won't match coming out of the guest anyway so the * only cost is the flush itself. The call clobbers r0.
*/
1: nop
patch_site 1b patch__call_kvm_flush_link_stack_p9
/* * Took an interrupt somewhere right before HRFID to guest, so registers are * in a bad way. Return things hopefully enough to run host virtual code and * run the Linux interrupt handler (SRESET or MCE) to print something useful. * * We could be really clever and save all host registers in known locations * before setting HSTATE_IN_GUEST, then restoring them all here, and setting * return address to a fixup that sets them up again. But that's a lot of * effort for a small bit of code. Lots of other things to do first.
*/
kvmppc_p9_bad_interrupt:
BEGIN_MMU_FTR_SECTION /* * Hash host doesn't try to recover MMU (requires host SLB reload)
*/
b .
END_MMU_FTR_SECTION_IFCLR(MMU_FTR_TYPE_RADIX) /* * Clean up guest registers to give host a chance to run.
*/
li r10,0
mtspr SPRN_AMR,r10
mtspr SPRN_IAMR,r10
mtspr SPRN_CIABR,r10
mtspr SPRN_DAWRX0,r10
BEGIN_FTR_SECTION
mtspr SPRN_DAWRX1,r10
END_FTR_SECTION_IFSET(CPU_FTR_DAWR1)
/* * Switch to host MMU mode (don't have the real host PID but we aren't * going back to userspace).
*/
hwsync
isync
/* * Set GUEST_MODE_NONE so the handler won't branch to KVM, and clear * MSR_RI in r12 ([H]SRR1) so the handler won't try to return.
*/
li r10,KVM_GUEST_MODE_NONE
stb r10,HSTATE_IN_GUEST(r13)
li r10,MSR_RI
andc r12,r12,r10
/* * Go back to interrupt handler. MCE and SRESET have their specific * PACA save area so they should be used directly. They set up their * own stack. The other handlers all use EXGEN. They will use the * guest r1 if it looks like a kernel stack, so just load the * emergency stack and go to program check for all other interrupts.
*/ ld r10,HSTATE_SCRATCH0(r13)
cmpwi r10,BOOK3S_INTERRUPT_MACHINE_CHECK
beq .Lcall_machine_check_common
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.