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 /* Note that prefixed instructions are disabled in PR KVM for now */ 127 mfsrr0 r12 128 addi r12, r12, 4 129 mtsrr0 r12 130 131 /* Clean up all state */ 132 lwz r12, HSTATE_SCRATCH1(r13) 133 mtcr r12 134 PPC_LL r12, HSTATE_SCRATCH0(r13) 135 GET_SCRATCH0(r13) 136 137 /* And get back into the code */ 138 RFI_TO_KERNEL 139#endif 140 141/* 142 * Call kvmppc_handler_trampoline_enter in real mode 143 * 144 * On entry, r4 contains the guest shadow MSR 145 * MSR.EE has to be 0 when calling this function 146 */ 147_GLOBAL_TOC(kvmppc_entry_trampoline) 148 mfmsr r5 149 LOAD_REG_ADDR(r7, kvmppc_handler_trampoline_enter) 150 toreal(r7) 151 152 li r6, MSR_IR | MSR_DR 153 andc r6, r5, r6 /* Clear DR and IR in MSR value */ 154 /* 155 * Set EE in HOST_MSR so that it's enabled when we get into our 156 * C exit handler function. 157 */ 158 ori r5, r5, MSR_EE 159 mtsrr0 r7 160 mtsrr1 r6 161 RFI_TO_KERNEL 162 163#include "book3s_segment.S" 164