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#define FUNC(name) GLUE(.,name) 40#define MTMSR_EERI(reg) mtmsrd (reg),1 41 42 .globl kvmppc_skip_interrupt 43kvmppc_skip_interrupt: 44 /* 45 * Here all GPRs are unchanged from when the interrupt happened 46 * except for r13, which is saved in SPRG_SCRATCH0. 47 */ 48 mfspr r13, SPRN_SRR0 49 addi r13, r13, 4 50 mtspr SPRN_SRR0, r13 51 GET_SCRATCH0(r13) 52 rfid 53 b . 54 55 .globl kvmppc_skip_Hinterrupt 56kvmppc_skip_Hinterrupt: 57 /* 58 * Here all GPRs are unchanged from when the interrupt happened 59 * except for r13, which is saved in SPRG_SCRATCH0. 60 */ 61 mfspr r13, SPRN_HSRR0 62 addi r13, r13, 4 63 mtspr SPRN_HSRR0, r13 64 GET_SCRATCH0(r13) 65 hrfid 66 b . 67 68#elif defined(CONFIG_PPC_BOOK3S_32) 69 70#define FUNC(name) name 71#define MTMSR_EERI(reg) mtmsr (reg) 72 73.macro INTERRUPT_TRAMPOLINE intno 74 75.global kvmppc_trampoline_\intno 76kvmppc_trampoline_\intno: 77 78 mtspr SPRN_SPRG_SCRATCH0, r13 /* Save r13 */ 79 80 /* 81 * First thing to do is to find out if we're coming 82 * from a KVM guest or a Linux process. 83 * 84 * To distinguish, we check a magic byte in the PACA/current 85 */ 86 mfspr r13, SPRN_SPRG_THREAD 87 lwz r13, THREAD_KVM_SVCPU(r13) 88 /* PPC32 can have a NULL pointer - let's check for that */ 89 mtspr SPRN_SPRG_SCRATCH1, r12 /* Save r12 */ 90 mfcr r12 91 cmpwi r13, 0 92 bne 1f 932: mtcr r12 94 mfspr r12, SPRN_SPRG_SCRATCH1 95 mfspr r13, SPRN_SPRG_SCRATCH0 /* r13 = original r13 */ 96 b kvmppc_resume_\intno /* Get back original handler */ 97 981: tophys(r13, r13) 99 stw r12, HSTATE_SCRATCH1(r13) 100 mfspr r12, SPRN_SPRG_SCRATCH1 101 stw r12, HSTATE_SCRATCH0(r13) 102 lbz r12, HSTATE_IN_GUEST(r13) 103 cmpwi r12, KVM_GUEST_MODE_NONE 104 bne ..kvmppc_handler_hasmagic_\intno 105 /* No KVM guest? Then jump back to the Linux handler! */ 106 lwz r12, HSTATE_SCRATCH1(r13) 107 b 2b 108 109 /* Now we know we're handling a KVM guest */ 110..kvmppc_handler_hasmagic_\intno: 111 112 /* Should we just skip the faulting instruction? */ 113 cmpwi r12, KVM_GUEST_MODE_SKIP 114 beq kvmppc_handler_skip_ins 115 116 /* Let's store which interrupt we're handling */ 117 li r12, \intno 118 119 /* Jump into the SLB exit code that goes to the highmem handler */ 120 b kvmppc_handler_trampoline_exit 121 122.endm 123 124INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_SYSTEM_RESET 125INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_MACHINE_CHECK 126INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_DATA_STORAGE 127INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_INST_STORAGE 128INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_EXTERNAL 129INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_ALIGNMENT 130INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_PROGRAM 131INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_FP_UNAVAIL 132INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_DECREMENTER 133INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_SYSCALL 134INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_TRACE 135INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_PERFMON 136INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_ALTIVEC 137 138/* 139 * Bring us back to the faulting code, but skip the 140 * faulting instruction. 141 * 142 * This is a generic exit path from the interrupt 143 * trampolines above. 144 * 145 * Input Registers: 146 * 147 * R12 = free 148 * R13 = Shadow VCPU (PACA) 149 * HSTATE.SCRATCH0 = guest R12 150 * HSTATE.SCRATCH1 = guest CR 151 * SPRG_SCRATCH0 = guest R13 152 * 153 */ 154kvmppc_handler_skip_ins: 155 156 /* Patch the IP to the next instruction */ 157 mfsrr0 r12 158 addi r12, r12, 4 159 mtsrr0 r12 160 161 /* Clean up all state */ 162 lwz r12, HSTATE_SCRATCH1(r13) 163 mtcr r12 164 PPC_LL r12, HSTATE_SCRATCH0(r13) 165 GET_SCRATCH0(r13) 166 167 /* And get back into the code */ 168 RFI 169#endif 170 171/* 172 * Call kvmppc_handler_trampoline_enter in real mode 173 * 174 * On entry, r4 contains the guest shadow MSR 175 */ 176_GLOBAL(kvmppc_entry_trampoline) 177 mfmsr r5 178 LOAD_REG_ADDR(r7, kvmppc_handler_trampoline_enter) 179 toreal(r7) 180 181 li r9, MSR_RI 182 ori r9, r9, MSR_EE 183 andc r9, r5, r9 /* Clear EE and RI in MSR value */ 184 li r6, MSR_IR | MSR_DR 185 ori r6, r6, MSR_EE 186 andc r6, r5, r6 /* Clear EE, DR and IR in MSR value */ 187 MTMSR_EERI(r9) /* Clear EE and RI in MSR */ 188 mtsrr0 r7 /* before we set srr0/1 */ 189 mtsrr1 r6 190 RFI 191 192#if defined(CONFIG_PPC_BOOK3S_32) 193#define STACK_LR INT_FRAME_SIZE+4 194 195/* load_up_xxx have to run with MSR_DR=0 on Book3S_32 */ 196#define MSR_EXT_START \ 197 PPC_STL r20, _NIP(r1); \ 198 mfmsr r20; \ 199 LOAD_REG_IMMEDIATE(r3, MSR_DR|MSR_EE); \ 200 andc r3,r20,r3; /* Disable DR,EE */ \ 201 mtmsr r3; \ 202 sync 203 204#define MSR_EXT_END \ 205 mtmsr r20; /* Enable DR,EE */ \ 206 sync; \ 207 PPC_LL r20, _NIP(r1) 208 209#elif defined(CONFIG_PPC_BOOK3S_64) 210#define STACK_LR _LINK 211#define MSR_EXT_START 212#define MSR_EXT_END 213#endif 214 215/* 216 * Activate current's external feature (FPU/Altivec/VSX) 217 */ 218#define define_load_up(what) \ 219 \ 220_GLOBAL(kvmppc_load_up_ ## what); \ 221 PPC_STLU r1, -INT_FRAME_SIZE(r1); \ 222 mflr r3; \ 223 PPC_STL r3, STACK_LR(r1); \ 224 MSR_EXT_START; \ 225 \ 226 bl FUNC(load_up_ ## what); \ 227 \ 228 MSR_EXT_END; \ 229 PPC_LL r3, STACK_LR(r1); \ 230 mtlr r3; \ 231 addi r1, r1, INT_FRAME_SIZE; \ 232 blr 233 234define_load_up(fpu) 235#ifdef CONFIG_ALTIVEC 236define_load_up(altivec) 237#endif 238#ifdef CONFIG_VSX 239define_load_up(vsx) 240#endif 241 242#include "book3s_segment.S" 243