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