Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[linux-drm-fsl-dcu.git] / arch / powerpc / kvm / book3s_interrupts.S
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/page.h>
24 #include <asm/asm-offsets.h>
25 #include <asm/exception-64s.h>
26
27 #if defined(CONFIG_PPC_BOOK3S_64)
28 #define FUNC(name)              GLUE(.,name)
29 #define GET_SHADOW_VCPU(reg)    addi    reg, r13, PACA_SVCPU
30
31 #elif defined(CONFIG_PPC_BOOK3S_32)
32 #define FUNC(name)              name
33 #define GET_SHADOW_VCPU(reg)    lwz     reg, (THREAD + THREAD_KVM_SVCPU)(r2)
34
35 #endif /* CONFIG_PPC_BOOK3S_XX */
36
37 #define VCPU_LOAD_NVGPRS(vcpu) \
38         PPC_LL  r14, VCPU_GPR(R14)(vcpu); \
39         PPC_LL  r15, VCPU_GPR(R15)(vcpu); \
40         PPC_LL  r16, VCPU_GPR(R16)(vcpu); \
41         PPC_LL  r17, VCPU_GPR(R17)(vcpu); \
42         PPC_LL  r18, VCPU_GPR(R18)(vcpu); \
43         PPC_LL  r19, VCPU_GPR(R19)(vcpu); \
44         PPC_LL  r20, VCPU_GPR(R20)(vcpu); \
45         PPC_LL  r21, VCPU_GPR(R21)(vcpu); \
46         PPC_LL  r22, VCPU_GPR(R22)(vcpu); \
47         PPC_LL  r23, VCPU_GPR(R23)(vcpu); \
48         PPC_LL  r24, VCPU_GPR(R24)(vcpu); \
49         PPC_LL  r25, VCPU_GPR(R25)(vcpu); \
50         PPC_LL  r26, VCPU_GPR(R26)(vcpu); \
51         PPC_LL  r27, VCPU_GPR(R27)(vcpu); \
52         PPC_LL  r28, VCPU_GPR(R28)(vcpu); \
53         PPC_LL  r29, VCPU_GPR(R29)(vcpu); \
54         PPC_LL  r30, VCPU_GPR(R30)(vcpu); \
55         PPC_LL  r31, VCPU_GPR(R31)(vcpu); \
56
57 /*****************************************************************************
58  *                                                                           *
59  *     Guest entry / exit code that is in kernel module memory (highmem)     *
60  *                                                                           *
61  ****************************************************************************/
62
63 /* Registers:
64  *  r3: kvm_run pointer
65  *  r4: vcpu pointer
66  */
67 _GLOBAL(__kvmppc_vcpu_run)
68
69 kvm_start_entry:
70         /* Write correct stack frame */
71         mflr    r0
72         PPC_STL r0,PPC_LR_STKOFF(r1)
73
74         /* Save host state to the stack */
75         PPC_STLU r1, -SWITCH_FRAME_SIZE(r1)
76
77         /* Save r3 (kvm_run) and r4 (vcpu) */
78         SAVE_2GPRS(3, r1)
79
80         /* Save non-volatile registers (r14 - r31) */
81         SAVE_NVGPRS(r1)
82
83         /* Save CR */
84         mfcr    r14
85         stw     r14, _CCR(r1)
86
87         /* Save LR */
88         PPC_STL r0, _LINK(r1)
89
90         /* Load non-volatile guest state from the vcpu */
91         VCPU_LOAD_NVGPRS(r4)
92
93 kvm_start_lightweight:
94         /* Copy registers into shadow vcpu so we can access them in real mode */
95         GET_SHADOW_VCPU(r3)
96         bl      FUNC(kvmppc_copy_to_svcpu)
97         nop
98         REST_GPR(4, r1)
99
100 #ifdef CONFIG_PPC_BOOK3S_64
101         /* Get the dcbz32 flag */
102         PPC_LL  r3, VCPU_HFLAGS(r4)
103         rldicl  r3, r3, 0, 63           /* r3 &= 1 */
104         stb     r3, HSTATE_RESTORE_HID5(r13)
105
106         /* Load up guest SPRG3 value, since it's user readable */
107         ld      r3, VCPU_SHARED(r4)
108         ld      r3, VCPU_SHARED_SPRG3(r3)
109         mtspr   SPRN_SPRG3, r3
110 #endif /* CONFIG_PPC_BOOK3S_64 */
111
112         PPC_LL  r4, VCPU_SHADOW_MSR(r4) /* get shadow_msr */
113
114         /* Jump to segment patching handler and into our guest */
115         bl      FUNC(kvmppc_entry_trampoline)
116         nop
117
118 /*
119  * This is the handler in module memory. It gets jumped at from the
120  * lowmem trampoline code, so it's basically the guest exit code.
121  *
122  */
123
124         /*
125          * Register usage at this point:
126          *
127          * R1       = host R1
128          * R2       = host R2
129          * R12      = exit handler id
130          * R13      = PACA
131          * SVCPU.*  = guest *
132          * MSR.EE   = 1
133          *
134          */
135
136         PPC_LL  r3, GPR4(r1)            /* vcpu pointer */
137
138         /*
139          * kvmppc_copy_from_svcpu can clobber volatile registers, save
140          * the exit handler id to the vcpu and restore it from there later.
141          */
142         stw     r12, VCPU_TRAP(r3)
143
144         /* Transfer reg values from shadow vcpu back to vcpu struct */
145         /* On 64-bit, interrupts are still off at this point */
146
147         GET_SHADOW_VCPU(r4)
148         bl      FUNC(kvmppc_copy_from_svcpu)
149         nop
150
151 #ifdef CONFIG_PPC_BOOK3S_64
152         /*
153          * Reload kernel SPRG3 value.
154          * No need to save guest value as usermode can't modify SPRG3.
155          */
156         ld      r3, PACA_SPRG3(r13)
157         mtspr   SPRN_SPRG3, r3
158 #endif /* CONFIG_PPC_BOOK3S_64 */
159
160         /* R7 = vcpu */
161         PPC_LL  r7, GPR4(r1)
162
163         PPC_STL r14, VCPU_GPR(R14)(r7)
164         PPC_STL r15, VCPU_GPR(R15)(r7)
165         PPC_STL r16, VCPU_GPR(R16)(r7)
166         PPC_STL r17, VCPU_GPR(R17)(r7)
167         PPC_STL r18, VCPU_GPR(R18)(r7)
168         PPC_STL r19, VCPU_GPR(R19)(r7)
169         PPC_STL r20, VCPU_GPR(R20)(r7)
170         PPC_STL r21, VCPU_GPR(R21)(r7)
171         PPC_STL r22, VCPU_GPR(R22)(r7)
172         PPC_STL r23, VCPU_GPR(R23)(r7)
173         PPC_STL r24, VCPU_GPR(R24)(r7)
174         PPC_STL r25, VCPU_GPR(R25)(r7)
175         PPC_STL r26, VCPU_GPR(R26)(r7)
176         PPC_STL r27, VCPU_GPR(R27)(r7)
177         PPC_STL r28, VCPU_GPR(R28)(r7)
178         PPC_STL r29, VCPU_GPR(R29)(r7)
179         PPC_STL r30, VCPU_GPR(R30)(r7)
180         PPC_STL r31, VCPU_GPR(R31)(r7)
181
182         /* Pass the exit number as 3rd argument to kvmppc_handle_exit */
183         lwz     r5, VCPU_TRAP(r7)
184
185         /* Restore r3 (kvm_run) and r4 (vcpu) */
186         REST_2GPRS(3, r1)
187         bl      FUNC(kvmppc_handle_exit_pr)
188
189         /* If RESUME_GUEST, get back in the loop */
190         cmpwi   r3, RESUME_GUEST
191         beq     kvm_loop_lightweight
192
193         cmpwi   r3, RESUME_GUEST_NV
194         beq     kvm_loop_heavyweight
195
196 kvm_exit_loop:
197
198         PPC_LL  r4, _LINK(r1)
199         mtlr    r4
200
201         lwz     r14, _CCR(r1)
202         mtcr    r14
203
204         /* Restore non-volatile host registers (r14 - r31) */
205         REST_NVGPRS(r1)
206
207         addi    r1, r1, SWITCH_FRAME_SIZE
208         blr
209
210 kvm_loop_heavyweight:
211
212         PPC_LL  r4, _LINK(r1)
213         PPC_STL r4, (PPC_LR_STKOFF + SWITCH_FRAME_SIZE)(r1)
214
215         /* Load vcpu and cpu_run */
216         REST_2GPRS(3, r1)
217
218         /* Load non-volatile guest state from the vcpu */
219         VCPU_LOAD_NVGPRS(r4)
220
221         /* Jump back into the beginning of this function */
222         b       kvm_start_lightweight
223
224 kvm_loop_lightweight:
225
226         /* We'll need the vcpu pointer */
227         REST_GPR(4, r1)
228
229         /* Jump back into the beginning of this function */
230         b       kvm_start_lightweight