1f3601156SNicholas Piggin/* SPDX-License-Identifier: GPL-2.0-only */ 2f3601156SNicholas Piggin#include <asm/asm-offsets.h> 3f3601156SNicholas Piggin#include <asm/cache.h> 4f33e0702SNicholas Piggin#include <asm/exception-64s.h> 5f3601156SNicholas Piggin#include <asm/kvm_asm.h> 6f3601156SNicholas Piggin#include <asm/kvm_book3s_asm.h> 7f3601156SNicholas Piggin#include <asm/ppc_asm.h> 8f3601156SNicholas Piggin#include <asm/reg.h> 9f3601156SNicholas Piggin 10f3601156SNicholas Piggin/* 1131c67cfeSNicholas Piggin * These are branched to from interrupt handlers in exception-64s.S which set 12f3601156SNicholas Piggin * IKVM_REAL or IKVM_VIRT, if HSTATE_IN_GUEST was found to be non-zero. 13f3601156SNicholas Piggin */ 1431c67cfeSNicholas Piggin.global kvmppc_hcall 1531c67cfeSNicholas Piggin.balign IFETCH_ALIGN_BYTES 1631c67cfeSNicholas Pigginkvmppc_hcall: 1704ece7b6SNicholas Piggin /* 1804ece7b6SNicholas Piggin * This is a hcall, so register convention is as 1904ece7b6SNicholas Piggin * Documentation/powerpc/papr_hcalls.rst, with these additions: 2004ece7b6SNicholas Piggin * R13 = PACA 2104ece7b6SNicholas Piggin * guest R13 saved in SPRN_SCRATCH0 2204ece7b6SNicholas Piggin * R10 = free 2304ece7b6SNicholas Piggin * guest r10 saved in PACA_EXGEN 2404ece7b6SNicholas Piggin * 2504ece7b6SNicholas Piggin * This may also be a syscall from PR-KVM userspace that is to be 2604ece7b6SNicholas Piggin * reflected to the PR guest kernel, so registers may be set up for 2704ece7b6SNicholas Piggin * a system call rather than hcall. We don't currently clobber 2804ece7b6SNicholas Piggin * anything here, but the 0xc00 handler has already clobbered CTR 2904ece7b6SNicholas Piggin * and CR0, so PR-KVM can not support a guest kernel that preserves 3004ece7b6SNicholas Piggin * those registers across its system calls. 3104ece7b6SNicholas Piggin */ 3204ece7b6SNicholas Piggin /* 3304ece7b6SNicholas Piggin * Save the PPR (on systems that support it) before changing to 3404ece7b6SNicholas Piggin * HMT_MEDIUM. That allows the KVM code to save that value into the 3504ece7b6SNicholas Piggin * guest state (it is the guest's PPR value). 3604ece7b6SNicholas Piggin */ 3704ece7b6SNicholas PigginBEGIN_FTR_SECTION 3804ece7b6SNicholas Piggin mfspr r10,SPRN_PPR 3904ece7b6SNicholas Piggin std r10,HSTATE_PPR(r13) 4004ece7b6SNicholas PigginEND_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) 4104ece7b6SNicholas Piggin HMT_MEDIUM 4204ece7b6SNicholas Piggin mfcr r10 4304ece7b6SNicholas Piggin std r12,HSTATE_SCRATCH0(r13) 4404ece7b6SNicholas Piggin sldi r12,r10,32 4504ece7b6SNicholas Piggin ori r12,r12,0xc00 4604ece7b6SNicholas Piggin ld r10,PACA_EXGEN+EX_R10(r13) 47*69fdd674SNicholas Piggin b do_kvm_interrupt 4831c67cfeSNicholas Piggin 49*69fdd674SNicholas Piggin/* 50*69fdd674SNicholas Piggin * KVM interrupt entry occurs after GEN_INT_ENTRY runs, and follows that 51*69fdd674SNicholas Piggin * call convention: 52*69fdd674SNicholas Piggin * 53*69fdd674SNicholas Piggin * guest R9-R13, CTR, CFAR, PPR saved in PACA EX_xxx save area 54*69fdd674SNicholas Piggin * guest (H)DAR, (H)DSISR are also in the save area for relevant interrupts 55*69fdd674SNicholas Piggin * guest R13 also saved in SCRATCH0 56*69fdd674SNicholas Piggin * R13 = PACA 57*69fdd674SNicholas Piggin * R11 = (H)SRR0 58*69fdd674SNicholas Piggin * R12 = (H)SRR1 59*69fdd674SNicholas Piggin * R9 = guest CR 60*69fdd674SNicholas Piggin * PPR is set to medium 61*69fdd674SNicholas Piggin * 62*69fdd674SNicholas Piggin * With the addition for KVM: 63*69fdd674SNicholas Piggin * R10 = trap vector 64*69fdd674SNicholas Piggin */ 65f3601156SNicholas Piggin.global kvmppc_interrupt 66f3601156SNicholas Piggin.balign IFETCH_ALIGN_BYTES 67f3601156SNicholas Pigginkvmppc_interrupt: 68*69fdd674SNicholas Piggin li r11,PACA_EXGEN 69*69fdd674SNicholas Piggin cmpdi r10,0x200 70*69fdd674SNicholas Piggin bgt+ 1f 71*69fdd674SNicholas Piggin li r11,PACA_EXMC 72*69fdd674SNicholas Piggin beq 1f 73*69fdd674SNicholas Piggin li r11,PACA_EXNMI 74*69fdd674SNicholas Piggin1: add r11,r11,r13 75*69fdd674SNicholas Piggin 76*69fdd674SNicholas PigginBEGIN_FTR_SECTION 77*69fdd674SNicholas Piggin ld r12,EX_CFAR(r11) 78*69fdd674SNicholas Piggin std r12,HSTATE_CFAR(r13) 79*69fdd674SNicholas PigginEND_FTR_SECTION_IFSET(CPU_FTR_CFAR) 80*69fdd674SNicholas Piggin ld r12,EX_CTR(r11) 81*69fdd674SNicholas Piggin mtctr r12 82*69fdd674SNicholas PigginBEGIN_FTR_SECTION 83*69fdd674SNicholas Piggin ld r12,EX_PPR(r11) 84*69fdd674SNicholas Piggin std r12,HSTATE_PPR(r13) 85*69fdd674SNicholas PigginEND_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) 86*69fdd674SNicholas Piggin ld r12,EX_R12(r11) 87*69fdd674SNicholas Piggin std r12,HSTATE_SCRATCH0(r13) 88*69fdd674SNicholas Piggin sldi r12,r9,32 89*69fdd674SNicholas Piggin or r12,r12,r10 90*69fdd674SNicholas Piggin ld r9,EX_R9(r11) 91*69fdd674SNicholas Piggin ld r10,EX_R10(r11) 92*69fdd674SNicholas Piggin ld r11,EX_R11(r11) 93*69fdd674SNicholas Piggin 94*69fdd674SNicholas Piggindo_kvm_interrupt: 95f3601156SNicholas Piggin /* 96*69fdd674SNicholas Piggin * Hcalls and other interrupts come here after normalising register 97*69fdd674SNicholas Piggin * contents and save locations: 98*69fdd674SNicholas Piggin * 99f3601156SNicholas Piggin * R12 = (guest CR << 32) | interrupt vector 100f3601156SNicholas Piggin * R13 = PACA 101*69fdd674SNicholas Piggin * guest R12 saved in shadow HSTATE_SCRATCH0 102f3601156SNicholas Piggin * guest R13 saved in SPRN_SCRATCH0 103f3601156SNicholas Piggin */ 104f3601156SNicholas Piggin std r9,HSTATE_SCRATCH2(r13) 105f3601156SNicholas Piggin lbz r9,HSTATE_IN_GUEST(r13) 106f33e0702SNicholas Piggin cmpwi r9,KVM_GUEST_MODE_SKIP 107f33e0702SNicholas Piggin beq- .Lmaybe_skip 108f33e0702SNicholas Piggin.Lno_skip: 109f33e0702SNicholas Piggin#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE 110f3601156SNicholas Piggin cmpwi r9,KVM_GUEST_MODE_HOST_HV 111f3601156SNicholas Piggin beq kvmppc_bad_host_intr 112f3601156SNicholas Piggin#ifdef CONFIG_KVM_BOOK3S_PR_POSSIBLE 113f3601156SNicholas Piggin cmpwi r9,KVM_GUEST_MODE_GUEST 114f3601156SNicholas Piggin ld r9,HSTATE_SCRATCH2(r13) 115f3601156SNicholas Piggin beq kvmppc_interrupt_pr 116f3601156SNicholas Piggin#endif 117f3601156SNicholas Piggin b kvmppc_interrupt_hv 118f3601156SNicholas Piggin#else 119f33e0702SNicholas Piggin ld r9,HSTATE_SCRATCH2(r13) 120f3601156SNicholas Piggin b kvmppc_interrupt_pr 121f3601156SNicholas Piggin#endif 122f33e0702SNicholas Piggin 123f33e0702SNicholas Piggin/* 124f33e0702SNicholas Piggin * "Skip" interrupts are part of a trick KVM uses a with hash guests to load 125f33e0702SNicholas Piggin * the faulting instruction in guest memory from the the hypervisor without 126f33e0702SNicholas Piggin * walking page tables. 127f33e0702SNicholas Piggin * 128f33e0702SNicholas Piggin * When the guest takes a fault that requires the hypervisor to load the 129f33e0702SNicholas Piggin * instruction (e.g., MMIO emulation), KVM is running in real-mode with HV=1 130f33e0702SNicholas Piggin * and the guest MMU context loaded. It sets KVM_GUEST_MODE_SKIP, and sets 131f33e0702SNicholas Piggin * MSR[DR]=1 while leaving MSR[IR]=0, so it continues to fetch HV instructions 132f33e0702SNicholas Piggin * but loads and stores will access the guest context. This is used to load 133f33e0702SNicholas Piggin * the faulting instruction using the faulting guest effective address. 134f33e0702SNicholas Piggin * 135f33e0702SNicholas Piggin * However the guest context may not be able to translate, or it may cause a 136f33e0702SNicholas Piggin * machine check or other issue, which results in a fault in the host 137f33e0702SNicholas Piggin * (even with KVM-HV). 138f33e0702SNicholas Piggin * 139f33e0702SNicholas Piggin * These faults come here because KVM_GUEST_MODE_SKIP was set, so if they 140f33e0702SNicholas Piggin * are (or are likely) caused by that load, the instruction is skipped by 141f33e0702SNicholas Piggin * just returning with the PC advanced +4, where it is noticed the load did 142f33e0702SNicholas Piggin * not execute and it goes to the slow path which walks the page tables to 143f33e0702SNicholas Piggin * read guest memory. 144f33e0702SNicholas Piggin */ 145f33e0702SNicholas Piggin.Lmaybe_skip: 146f33e0702SNicholas Piggin cmpwi r12,BOOK3S_INTERRUPT_MACHINE_CHECK 147f33e0702SNicholas Piggin beq 1f 148f33e0702SNicholas Piggin cmpwi r12,BOOK3S_INTERRUPT_DATA_STORAGE 149f33e0702SNicholas Piggin beq 1f 150f33e0702SNicholas Piggin cmpwi r12,BOOK3S_INTERRUPT_DATA_SEGMENT 151f33e0702SNicholas Piggin beq 1f 152f33e0702SNicholas Piggin#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE 153f33e0702SNicholas Piggin /* HSRR interrupts get 2 added to interrupt number */ 154f33e0702SNicholas Piggin cmpwi r12,BOOK3S_INTERRUPT_H_DATA_STORAGE | 0x2 155f33e0702SNicholas Piggin beq 2f 156f33e0702SNicholas Piggin#endif 157f33e0702SNicholas Piggin b .Lno_skip 158f33e0702SNicholas Piggin1: mfspr r9,SPRN_SRR0 159f33e0702SNicholas Piggin addi r9,r9,4 160f33e0702SNicholas Piggin mtspr SPRN_SRR0,r9 161f33e0702SNicholas Piggin ld r12,HSTATE_SCRATCH0(r13) 162f33e0702SNicholas Piggin ld r9,HSTATE_SCRATCH2(r13) 163f33e0702SNicholas Piggin GET_SCRATCH0(r13) 164f33e0702SNicholas Piggin RFI_TO_KERNEL 165f33e0702SNicholas Piggin#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE 166f33e0702SNicholas Piggin2: mfspr r9,SPRN_HSRR0 167f33e0702SNicholas Piggin addi r9,r9,4 168f33e0702SNicholas Piggin mtspr SPRN_HSRR0,r9 169f33e0702SNicholas Piggin ld r12,HSTATE_SCRATCH0(r13) 170f33e0702SNicholas Piggin ld r9,HSTATE_SCRATCH2(r13) 171f33e0702SNicholas Piggin GET_SCRATCH0(r13) 172f33e0702SNicholas Piggin HRFI_TO_KERNEL 173f33e0702SNicholas Piggin#endif 174