diff options
Diffstat (limited to 'arch/powerpc/kvm/book3s_64_rmhandlers.S')
-rw-r--r-- | arch/powerpc/kvm/book3s_64_rmhandlers.S | 119 |
1 files changed, 96 insertions, 23 deletions
diff --git a/arch/powerpc/kvm/book3s_64_rmhandlers.S b/arch/powerpc/kvm/book3s_64_rmhandlers.S index fb7dd2e9ac88..c83c60ad96c5 100644 --- a/arch/powerpc/kvm/book3s_64_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_64_rmhandlers.S | |||
@@ -45,36 +45,25 @@ kvmppc_trampoline_\intno: | |||
45 | * To distinguish, we check a magic byte in the PACA | 45 | * To distinguish, we check a magic byte in the PACA |
46 | */ | 46 | */ |
47 | mfspr r13, SPRN_SPRG_PACA /* r13 = PACA */ | 47 | mfspr r13, SPRN_SPRG_PACA /* r13 = PACA */ |
48 | std r12, (PACA_EXMC + EX_R12)(r13) | 48 | std r12, PACA_KVM_SCRATCH0(r13) |
49 | mfcr r12 | 49 | mfcr r12 |
50 | stw r12, (PACA_EXMC + EX_CCR)(r13) | 50 | stw r12, PACA_KVM_SCRATCH1(r13) |
51 | lbz r12, PACA_KVM_IN_GUEST(r13) | 51 | lbz r12, PACA_KVM_IN_GUEST(r13) |
52 | cmpwi r12, 0 | 52 | cmpwi r12, KVM_GUEST_MODE_NONE |
53 | bne ..kvmppc_handler_hasmagic_\intno | 53 | bne ..kvmppc_handler_hasmagic_\intno |
54 | /* No KVM guest? Then jump back to the Linux handler! */ | 54 | /* No KVM guest? Then jump back to the Linux handler! */ |
55 | lwz r12, (PACA_EXMC + EX_CCR)(r13) | 55 | lwz r12, PACA_KVM_SCRATCH1(r13) |
56 | mtcr r12 | 56 | mtcr r12 |
57 | ld r12, (PACA_EXMC + EX_R12)(r13) | 57 | ld r12, PACA_KVM_SCRATCH0(r13) |
58 | mfspr r13, SPRN_SPRG_SCRATCH0 /* r13 = original r13 */ | 58 | mfspr r13, SPRN_SPRG_SCRATCH0 /* r13 = original r13 */ |
59 | b kvmppc_resume_\intno /* Get back original handler */ | 59 | b kvmppc_resume_\intno /* Get back original handler */ |
60 | 60 | ||
61 | /* Now we know we're handling a KVM guest */ | 61 | /* Now we know we're handling a KVM guest */ |
62 | ..kvmppc_handler_hasmagic_\intno: | 62 | ..kvmppc_handler_hasmagic_\intno: |
63 | /* Unset guest state */ | ||
64 | li r12, 0 | ||
65 | stb r12, PACA_KVM_IN_GUEST(r13) | ||
66 | 63 | ||
67 | std r1, (PACA_EXMC+EX_R9)(r13) | 64 | /* Should we just skip the faulting instruction? */ |
68 | std r10, (PACA_EXMC+EX_R10)(r13) | 65 | cmpwi r12, KVM_GUEST_MODE_SKIP |
69 | std r11, (PACA_EXMC+EX_R11)(r13) | 66 | beq kvmppc_handler_skip_ins |
70 | std r2, (PACA_EXMC+EX_R13)(r13) | ||
71 | |||
72 | mfsrr0 r10 | ||
73 | mfsrr1 r11 | ||
74 | |||
75 | /* Restore R1/R2 so we can handle faults */ | ||
76 | ld r1, PACAR1(r13) | ||
77 | ld r2, (PACA_EXMC+EX_SRR0)(r13) | ||
78 | 67 | ||
79 | /* Let's store which interrupt we're handling */ | 68 | /* Let's store which interrupt we're handling */ |
80 | li r12, \intno | 69 | li r12, \intno |
@@ -102,23 +91,107 @@ INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_ALTIVEC | |||
102 | INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_VSX | 91 | INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_VSX |
103 | 92 | ||
104 | /* | 93 | /* |
94 | * Bring us back to the faulting code, but skip the | ||
95 | * faulting instruction. | ||
96 | * | ||
97 | * This is a generic exit path from the interrupt | ||
98 | * trampolines above. | ||
99 | * | ||
100 | * Input Registers: | ||
101 | * | ||
102 | * R12 = free | ||
103 | * R13 = PACA | ||
104 | * PACA.KVM.SCRATCH0 = guest R12 | ||
105 | * PACA.KVM.SCRATCH1 = guest CR | ||
106 | * SPRG_SCRATCH0 = guest R13 | ||
107 | * | ||
108 | */ | ||
109 | kvmppc_handler_skip_ins: | ||
110 | |||
111 | /* Patch the IP to the next instruction */ | ||
112 | mfsrr0 r12 | ||
113 | addi r12, r12, 4 | ||
114 | mtsrr0 r12 | ||
115 | |||
116 | /* Clean up all state */ | ||
117 | lwz r12, PACA_KVM_SCRATCH1(r13) | ||
118 | mtcr r12 | ||
119 | ld r12, PACA_KVM_SCRATCH0(r13) | ||
120 | mfspr r13, SPRN_SPRG_SCRATCH0 | ||
121 | |||
122 | /* And get back into the code */ | ||
123 | RFI | ||
124 | |||
125 | /* | ||
105 | * This trampoline brings us back to a real mode handler | 126 | * This trampoline brings us back to a real mode handler |
106 | * | 127 | * |
107 | * Input Registers: | 128 | * Input Registers: |
108 | * | 129 | * |
109 | * R6 = SRR0 | 130 | * R5 = SRR0 |
110 | * R7 = SRR1 | 131 | * R6 = SRR1 |
111 | * LR = real-mode IP | 132 | * LR = real-mode IP |
112 | * | 133 | * |
113 | */ | 134 | */ |
114 | .global kvmppc_handler_lowmem_trampoline | 135 | .global kvmppc_handler_lowmem_trampoline |
115 | kvmppc_handler_lowmem_trampoline: | 136 | kvmppc_handler_lowmem_trampoline: |
116 | 137 | ||
117 | mtsrr0 r6 | 138 | mtsrr0 r5 |
118 | mtsrr1 r7 | 139 | mtsrr1 r6 |
119 | blr | 140 | blr |
120 | kvmppc_handler_lowmem_trampoline_end: | 141 | kvmppc_handler_lowmem_trampoline_end: |
121 | 142 | ||
143 | /* | ||
144 | * Call a function in real mode | ||
145 | * | ||
146 | * Input Registers: | ||
147 | * | ||
148 | * R3 = function | ||
149 | * R4 = MSR | ||
150 | * R5 = CTR | ||
151 | * | ||
152 | */ | ||
153 | _GLOBAL(kvmppc_rmcall) | ||
154 | mtmsr r4 /* Disable relocation, so mtsrr | ||
155 | doesn't get interrupted */ | ||
156 | mtctr r5 | ||
157 | mtsrr0 r3 | ||
158 | mtsrr1 r4 | ||
159 | RFI | ||
160 | |||
161 | /* | ||
162 | * Activate current's external feature (FPU/Altivec/VSX) | ||
163 | */ | ||
164 | #define define_load_up(what) \ | ||
165 | \ | ||
166 | _GLOBAL(kvmppc_load_up_ ## what); \ | ||
167 | subi r1, r1, INT_FRAME_SIZE; \ | ||
168 | mflr r3; \ | ||
169 | std r3, _LINK(r1); \ | ||
170 | mfmsr r4; \ | ||
171 | std r31, GPR3(r1); \ | ||
172 | mr r31, r4; \ | ||
173 | li r5, MSR_DR; \ | ||
174 | oris r5, r5, MSR_EE@h; \ | ||
175 | andc r4, r4, r5; \ | ||
176 | mtmsr r4; \ | ||
177 | \ | ||
178 | bl .load_up_ ## what; \ | ||
179 | \ | ||
180 | mtmsr r31; \ | ||
181 | ld r3, _LINK(r1); \ | ||
182 | ld r31, GPR3(r1); \ | ||
183 | addi r1, r1, INT_FRAME_SIZE; \ | ||
184 | mtlr r3; \ | ||
185 | blr | ||
186 | |||
187 | define_load_up(fpu) | ||
188 | #ifdef CONFIG_ALTIVEC | ||
189 | define_load_up(altivec) | ||
190 | #endif | ||
191 | #ifdef CONFIG_VSX | ||
192 | define_load_up(vsx) | ||
193 | #endif | ||
194 | |||
122 | .global kvmppc_trampoline_lowmem | 195 | .global kvmppc_trampoline_lowmem |
123 | kvmppc_trampoline_lowmem: | 196 | kvmppc_trampoline_lowmem: |
124 | .long kvmppc_handler_lowmem_trampoline - _stext | 197 | .long kvmppc_handler_lowmem_trampoline - _stext |