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