1/* SPDX-License-Identifier: GPL-2.0-only */ 2/* 3 * 4 * Copyright SUSE Linux Products GmbH 2009 5 * 6 * Authors: Alexander Graf <agraf@suse.de> 7 */ 8 9#include <asm/ppc_asm.h> 10#include <asm/kvm_asm.h> 11#include <asm/reg.h> 12#include <asm/mmu.h> 13#include <asm/page.h> 14#include <asm/asm-offsets.h> 15#include <asm/asm-compat.h> 16 17#ifdef CONFIG_PPC_BOOK3S_64 18#include <asm/exception-64s.h> 19#endif 20 21/***************************************************************************** 22 * * 23 * Real Mode handlers that need to be in low physical memory * 24 * * 25 ****************************************************************************/ 26 27#if defined(CONFIG_PPC_BOOK3S_64) 28 29#ifdef CONFIG_PPC64_ELF_ABI_V2 30#define FUNC(name) name 31#else 32#define FUNC(name) GLUE(.,name) 33#endif 34 35#elif defined(CONFIG_PPC_BOOK3S_32) 36 37#define FUNC(name) name 38 39#define RFI_TO_KERNEL rfi 40#define RFI_TO_GUEST rfi 41 42.macro INTERRUPT_TRAMPOLINE intno 43 44.global kvmppc_trampoline_\intno 45kvmppc_trampoline_\intno: 46 47 mtspr SPRN_SPRG_SCRATCH0, r13 /* Save r13 */ 48 49 /* 50 * First thing to do is to find out if we're coming 51 * from a KVM guest or a Linux process. 52 * 53 * To distinguish, we check a magic byte in the PACA/current 54 */ 55 mfspr r13, SPRN_SPRG_THREAD 56 lwz r13, THREAD_KVM_SVCPU(r13) 57 /* PPC32 can have a NULL pointer - let's check for that */ 58 mtspr SPRN_SPRG_SCRATCH1, r12 /* Save r12 */ 59 mfcr r12 60 cmpwi r13, 0 61 bne 1f 622: mtcr r12 63 mfspr r12, SPRN_SPRG_SCRATCH1 64 mfspr r13, SPRN_SPRG_SCRATCH0 /* r13 = original r13 */ 65 b kvmppc_resume_\intno /* Get back original handler */ 66 671: tophys(r13, r13) 68 stw r12, HSTATE_SCRATCH1(r13) 69 mfspr r12, SPRN_SPRG_SCRATCH1 70 stw r12, HSTATE_SCRATCH0(r13) 71 lbz r12, HSTATE_IN_GUEST(r13) 72 cmpwi r12, KVM_GUEST_MODE_NONE 73 bne ..kvmppc_handler_hasmagic_\intno 74 /* No KVM guest? Then jump back to the Linux handler! */ 75 lwz r12, HSTATE_SCRATCH1(r13) 76 b 2b 77 78 /* Now we know we're handling a KVM guest */ 79..kvmppc_handler_hasmagic_\intno: 80 81 /* Should we just skip the faulting instruction? */ 82 cmpwi r12, KVM_GUEST_MODE_SKIP 83 beq kvmppc_handler_skip_ins 84 85 /* Let's store which interrupt we're handling */ 86 li r12, \intno 87 88 /* Jump into the SLB exit code that goes to the highmem handler */ 89 b kvmppc_handler_trampoline_exit 90 91.endm 92 93INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_SYSTEM_RESET 94INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_MACHINE_CHECK 95INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_DATA_STORAGE 96INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_INST_STORAGE 97INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_EXTERNAL 98INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_ALIGNMENT 99INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_PROGRAM 100INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_FP_UNAVAIL 101INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_DECREMENTER 102INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_SYSCALL 103INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_TRACE 104INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_PERFMON 105INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_ALTIVEC 106 107/* 108 * Bring us back to the faulting code, but skip the 109 * faulting instruction. 110 * 111 * This is a generic exit path from the interrupt 112 * trampolines above. 113 * 114 * Input Registers: 115 * 116 * R12 = free 117 * R13 = Shadow VCPU (PACA) 118 * HSTATE.SCRATCH0 = guest R12 119 * HSTATE.SCRATCH1 = guest CR 120 * SPRG_SCRATCH0 = guest R13 121 * 122 */ 123kvmppc_handler_skip_ins: 124 125 /* Patch the IP to the next instruction */ 126 mfsrr0 r12 127 addi r12, r12, 4 128 mtsrr0 r12 129 130 /* Clean up all state */ 131 lwz r12, HSTATE_SCRATCH1(r13) 132 mtcr r12 133 PPC_LL r12, HSTATE_SCRATCH0(r13) 134 GET_SCRATCH0(r13) 135 136 /* And get back into the code */ 137 RFI_TO_KERNEL 138#endif 139 140/* 141 * Call kvmppc_handler_trampoline_enter in real mode 142 * 143 * On entry, r4 contains the guest shadow MSR 144 * MSR.EE has to be 0 when calling this function 145 */ 146_GLOBAL_TOC(kvmppc_entry_trampoline) 147 mfmsr r5 148 LOAD_REG_ADDR(r7, kvmppc_handler_trampoline_enter) 149 toreal(r7) 150 151 li r6, MSR_IR | MSR_DR 152 andc r6, r5, r6 /* Clear DR and IR in MSR value */ 153 /* 154 * Set EE in HOST_MSR so that it's enabled when we get into our 155 * C exit handler function. 156 */ 157 ori r5, r5, MSR_EE 158 mtsrr0 r7 159 mtsrr1 r6 160 RFI_TO_KERNEL 161 162#include "book3s_segment.S" 163