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 45 kvmppc_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 62 2: 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 67 1: 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 93 INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_SYSTEM_RESET 94 INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_MACHINE_CHECK 95 INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_DATA_STORAGE 96 INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_INST_STORAGE 97 INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_EXTERNAL 98 INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_ALIGNMENT 99 INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_PROGRAM 100 INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_FP_UNAVAIL 101 INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_DECREMENTER 102 INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_SYSCALL 103 INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_TRACE 104 INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_PERFMON 105 INTERRUPT_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 */ 123 kvmppc_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"
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.