aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm/booke.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kvm/booke.c')
-rw-r--r--arch/powerpc/kvm/booke.c50
1 files changed, 30 insertions, 20 deletions
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 35485dd6927e..642e4204cf25 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -30,10 +30,8 @@
30#include <asm/kvm_ppc.h> 30#include <asm/kvm_ppc.h>
31#include "timing.h" 31#include "timing.h"
32#include <asm/cacheflush.h> 32#include <asm/cacheflush.h>
33#include <asm/kvm_44x.h>
34 33
35#include "booke.h" 34#include "booke.h"
36#include "44x_tlb.h"
37 35
38unsigned long kvmppc_booke_handlers; 36unsigned long kvmppc_booke_handlers;
39 37
@@ -120,6 +118,9 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu,
120 case BOOKE_IRQPRIO_DATA_STORAGE: 118 case BOOKE_IRQPRIO_DATA_STORAGE:
121 case BOOKE_IRQPRIO_INST_STORAGE: 119 case BOOKE_IRQPRIO_INST_STORAGE:
122 case BOOKE_IRQPRIO_FP_UNAVAIL: 120 case BOOKE_IRQPRIO_FP_UNAVAIL:
121 case BOOKE_IRQPRIO_SPE_UNAVAIL:
122 case BOOKE_IRQPRIO_SPE_FP_DATA:
123 case BOOKE_IRQPRIO_SPE_FP_ROUND:
123 case BOOKE_IRQPRIO_AP_UNAVAIL: 124 case BOOKE_IRQPRIO_AP_UNAVAIL:
124 case BOOKE_IRQPRIO_ALIGNMENT: 125 case BOOKE_IRQPRIO_ALIGNMENT:
125 allowed = 1; 126 allowed = 1;
@@ -165,7 +166,7 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu)
165 unsigned int priority; 166 unsigned int priority;
166 167
167 priority = __ffs(*pending); 168 priority = __ffs(*pending);
168 while (priority <= BOOKE_MAX_INTERRUPT) { 169 while (priority <= BOOKE_IRQPRIO_MAX) {
169 if (kvmppc_booke_irqprio_deliver(vcpu, priority)) 170 if (kvmppc_booke_irqprio_deliver(vcpu, priority))
170 break; 171 break;
171 172
@@ -263,6 +264,21 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
263 r = RESUME_GUEST; 264 r = RESUME_GUEST;
264 break; 265 break;
265 266
267 case BOOKE_INTERRUPT_SPE_UNAVAIL:
268 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SPE_UNAVAIL);
269 r = RESUME_GUEST;
270 break;
271
272 case BOOKE_INTERRUPT_SPE_FP_DATA:
273 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SPE_FP_DATA);
274 r = RESUME_GUEST;
275 break;
276
277 case BOOKE_INTERRUPT_SPE_FP_ROUND:
278 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_SPE_FP_ROUND);
279 r = RESUME_GUEST;
280 break;
281
266 case BOOKE_INTERRUPT_DATA_STORAGE: 282 case BOOKE_INTERRUPT_DATA_STORAGE:
267 vcpu->arch.dear = vcpu->arch.fault_dear; 283 vcpu->arch.dear = vcpu->arch.fault_dear;
268 vcpu->arch.esr = vcpu->arch.fault_esr; 284 vcpu->arch.esr = vcpu->arch.fault_esr;
@@ -284,29 +300,27 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
284 r = RESUME_GUEST; 300 r = RESUME_GUEST;
285 break; 301 break;
286 302
287 /* XXX move to a 440-specific file. */
288 case BOOKE_INTERRUPT_DTLB_MISS: { 303 case BOOKE_INTERRUPT_DTLB_MISS: {
289 struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
290 struct kvmppc_44x_tlbe *gtlbe;
291 unsigned long eaddr = vcpu->arch.fault_dear; 304 unsigned long eaddr = vcpu->arch.fault_dear;
292 int gtlb_index; 305 int gtlb_index;
306 gpa_t gpaddr;
293 gfn_t gfn; 307 gfn_t gfn;
294 308
295 /* Check the guest TLB. */ 309 /* Check the guest TLB. */
296 gtlb_index = kvmppc_44x_dtlb_index(vcpu, eaddr); 310 gtlb_index = kvmppc_mmu_dtlb_index(vcpu, eaddr);
297 if (gtlb_index < 0) { 311 if (gtlb_index < 0) {
298 /* The guest didn't have a mapping for it. */ 312 /* The guest didn't have a mapping for it. */
299 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DTLB_MISS); 313 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_DTLB_MISS);
300 vcpu->arch.dear = vcpu->arch.fault_dear; 314 vcpu->arch.dear = vcpu->arch.fault_dear;
301 vcpu->arch.esr = vcpu->arch.fault_esr; 315 vcpu->arch.esr = vcpu->arch.fault_esr;
316 kvmppc_mmu_dtlb_miss(vcpu);
302 kvmppc_account_exit(vcpu, DTLB_REAL_MISS_EXITS); 317 kvmppc_account_exit(vcpu, DTLB_REAL_MISS_EXITS);
303 r = RESUME_GUEST; 318 r = RESUME_GUEST;
304 break; 319 break;
305 } 320 }
306 321
307 gtlbe = &vcpu_44x->guest_tlb[gtlb_index]; 322 gpaddr = kvmppc_mmu_xlate(vcpu, gtlb_index, eaddr);
308 vcpu->arch.paddr_accessed = tlb_xlate(gtlbe, eaddr); 323 gfn = gpaddr >> PAGE_SHIFT;
309 gfn = vcpu->arch.paddr_accessed >> PAGE_SHIFT;
310 324
311 if (kvm_is_visible_gfn(vcpu->kvm, gfn)) { 325 if (kvm_is_visible_gfn(vcpu->kvm, gfn)) {
312 /* The guest TLB had a mapping, but the shadow TLB 326 /* The guest TLB had a mapping, but the shadow TLB
@@ -315,13 +329,13 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
315 * b) the guest used a large mapping which we're faking 329 * b) the guest used a large mapping which we're faking
316 * Either way, we need to satisfy the fault without 330 * Either way, we need to satisfy the fault without
317 * invoking the guest. */ 331 * invoking the guest. */
318 kvmppc_mmu_map(vcpu, eaddr, vcpu->arch.paddr_accessed, gtlbe->tid, 332 kvmppc_mmu_map(vcpu, eaddr, gpaddr, gtlb_index);
319 gtlbe->word2, get_tlb_bytes(gtlbe), gtlb_index);
320 kvmppc_account_exit(vcpu, DTLB_VIRT_MISS_EXITS); 333 kvmppc_account_exit(vcpu, DTLB_VIRT_MISS_EXITS);
321 r = RESUME_GUEST; 334 r = RESUME_GUEST;
322 } else { 335 } else {
323 /* Guest has mapped and accessed a page which is not 336 /* Guest has mapped and accessed a page which is not
324 * actually RAM. */ 337 * actually RAM. */
338 vcpu->arch.paddr_accessed = gpaddr;
325 r = kvmppc_emulate_mmio(run, vcpu); 339 r = kvmppc_emulate_mmio(run, vcpu);
326 kvmppc_account_exit(vcpu, MMIO_EXITS); 340 kvmppc_account_exit(vcpu, MMIO_EXITS);
327 } 341 }
@@ -329,10 +343,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
329 break; 343 break;
330 } 344 }
331 345
332 /* XXX move to a 440-specific file. */
333 case BOOKE_INTERRUPT_ITLB_MISS: { 346 case BOOKE_INTERRUPT_ITLB_MISS: {
334 struct kvmppc_vcpu_44x *vcpu_44x = to_44x(vcpu);
335 struct kvmppc_44x_tlbe *gtlbe;
336 unsigned long eaddr = vcpu->arch.pc; 347 unsigned long eaddr = vcpu->arch.pc;
337 gpa_t gpaddr; 348 gpa_t gpaddr;
338 gfn_t gfn; 349 gfn_t gfn;
@@ -341,18 +352,18 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
341 r = RESUME_GUEST; 352 r = RESUME_GUEST;
342 353
343 /* Check the guest TLB. */ 354 /* Check the guest TLB. */
344 gtlb_index = kvmppc_44x_itlb_index(vcpu, eaddr); 355 gtlb_index = kvmppc_mmu_itlb_index(vcpu, eaddr);
345 if (gtlb_index < 0) { 356 if (gtlb_index < 0) {
346 /* The guest didn't have a mapping for it. */ 357 /* The guest didn't have a mapping for it. */
347 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_ITLB_MISS); 358 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_ITLB_MISS);
359 kvmppc_mmu_itlb_miss(vcpu);
348 kvmppc_account_exit(vcpu, ITLB_REAL_MISS_EXITS); 360 kvmppc_account_exit(vcpu, ITLB_REAL_MISS_EXITS);
349 break; 361 break;
350 } 362 }
351 363
352 kvmppc_account_exit(vcpu, ITLB_VIRT_MISS_EXITS); 364 kvmppc_account_exit(vcpu, ITLB_VIRT_MISS_EXITS);
353 365
354 gtlbe = &vcpu_44x->guest_tlb[gtlb_index]; 366 gpaddr = kvmppc_mmu_xlate(vcpu, gtlb_index, eaddr);
355 gpaddr = tlb_xlate(gtlbe, eaddr);
356 gfn = gpaddr >> PAGE_SHIFT; 367 gfn = gpaddr >> PAGE_SHIFT;
357 368
358 if (kvm_is_visible_gfn(vcpu->kvm, gfn)) { 369 if (kvm_is_visible_gfn(vcpu->kvm, gfn)) {
@@ -362,8 +373,7 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu,
362 * b) the guest used a large mapping which we're faking 373 * b) the guest used a large mapping which we're faking
363 * Either way, we need to satisfy the fault without 374 * Either way, we need to satisfy the fault without
364 * invoking the guest. */ 375 * invoking the guest. */
365 kvmppc_mmu_map(vcpu, eaddr, gpaddr, gtlbe->tid, 376 kvmppc_mmu_map(vcpu, eaddr, gpaddr, gtlb_index);
366 gtlbe->word2, get_tlb_bytes(gtlbe), gtlb_index);
367 } else { 377 } else {
368 /* Guest mapped and leaped at non-RAM! */ 378 /* Guest mapped and leaped at non-RAM! */
369 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_MACHINE_CHECK); 379 kvmppc_booke_queue_irqprio(vcpu, BOOKE_IRQPRIO_MACHINE_CHECK);