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