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