aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kvm/e500_tlb.c69
1 files changed, 41 insertions, 28 deletions
diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c
index 8efb2acee2bf..3777167e5f31 100644
--- a/arch/powerpc/kvm/e500_tlb.c
+++ b/arch/powerpc/kvm/e500_tlb.c
@@ -432,7 +432,7 @@ static inline void kvmppc_e500_setup_stlbe(
432#endif 432#endif
433} 433}
434 434
435static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500, 435static inline int kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
436 u64 gvaddr, gfn_t gfn, struct kvm_book3e_206_tlb_entry *gtlbe, 436 u64 gvaddr, gfn_t gfn, struct kvm_book3e_206_tlb_entry *gtlbe,
437 int tlbsel, struct kvm_book3e_206_tlb_entry *stlbe, 437 int tlbsel, struct kvm_book3e_206_tlb_entry *stlbe,
438 struct tlbe_ref *ref) 438 struct tlbe_ref *ref)
@@ -551,7 +551,7 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
551 if (is_error_noslot_pfn(pfn)) { 551 if (is_error_noslot_pfn(pfn)) {
552 printk(KERN_ERR "Couldn't get real page for gfn %lx!\n", 552 printk(KERN_ERR "Couldn't get real page for gfn %lx!\n",
553 (long)gfn); 553 (long)gfn);
554 return; 554 return -EINVAL;
555 } 555 }
556 556
557 /* Align guest and physical address to page map boundaries */ 557 /* Align guest and physical address to page map boundaries */
@@ -571,22 +571,33 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
571 571
572 /* Drop refcount on page, so that mmu notifiers can clear it */ 572 /* Drop refcount on page, so that mmu notifiers can clear it */
573 kvm_release_pfn_clean(pfn); 573 kvm_release_pfn_clean(pfn);
574
575 return 0;
574} 576}
575 577
576/* XXX only map the one-one case, for now use TLB0 */ 578/* XXX only map the one-one case, for now use TLB0 */
577static void kvmppc_e500_tlb0_map(struct kvmppc_vcpu_e500 *vcpu_e500, 579static int kvmppc_e500_tlb0_map(struct kvmppc_vcpu_e500 *vcpu_e500,
578 int esel, 580 int esel,
579 struct kvm_book3e_206_tlb_entry *stlbe) 581 struct kvm_book3e_206_tlb_entry *stlbe)
580{ 582{
581 struct kvm_book3e_206_tlb_entry *gtlbe; 583 struct kvm_book3e_206_tlb_entry *gtlbe;
582 struct tlbe_ref *ref; 584 struct tlbe_ref *ref;
585 int stlbsel = 0;
586 int sesel = 0;
587 int r;
583 588
584 gtlbe = get_entry(vcpu_e500, 0, esel); 589 gtlbe = get_entry(vcpu_e500, 0, esel);
585 ref = &vcpu_e500->gtlb_priv[0][esel].ref; 590 ref = &vcpu_e500->gtlb_priv[0][esel].ref;
586 591
587 kvmppc_e500_shadow_map(vcpu_e500, get_tlb_eaddr(gtlbe), 592 r = kvmppc_e500_shadow_map(vcpu_e500, get_tlb_eaddr(gtlbe),
588 get_tlb_raddr(gtlbe) >> PAGE_SHIFT, 593 get_tlb_raddr(gtlbe) >> PAGE_SHIFT,
589 gtlbe, 0, stlbe, ref); 594 gtlbe, 0, stlbe, ref);
595 if (r)
596 return r;
597
598 write_stlbe(vcpu_e500, gtlbe, stlbe, stlbsel, sesel);
599
600 return 0;
590} 601}
591 602
592/* Caller must ensure that the specified guest TLB entry is safe to insert into 603/* Caller must ensure that the specified guest TLB entry is safe to insert into
@@ -597,25 +608,32 @@ static int kvmppc_e500_tlb1_map(struct kvmppc_vcpu_e500 *vcpu_e500,
597 struct kvm_book3e_206_tlb_entry *stlbe, int esel) 608 struct kvm_book3e_206_tlb_entry *stlbe, int esel)
598{ 609{
599 struct tlbe_ref *ref; 610 struct tlbe_ref *ref;
600 unsigned int victim; 611 unsigned int sesel;
612 int r;
613 int stlbsel = 1;
601 614
602 victim = vcpu_e500->host_tlb1_nv++; 615 sesel = vcpu_e500->host_tlb1_nv++;
603 616
604 if (unlikely(vcpu_e500->host_tlb1_nv >= tlb1_max_shadow_size())) 617 if (unlikely(vcpu_e500->host_tlb1_nv >= tlb1_max_shadow_size()))
605 vcpu_e500->host_tlb1_nv = 0; 618 vcpu_e500->host_tlb1_nv = 0;
606 619
607 ref = &vcpu_e500->tlb_refs[1][victim]; 620 ref = &vcpu_e500->tlb_refs[1][sesel];
608 kvmppc_e500_shadow_map(vcpu_e500, gvaddr, gfn, gtlbe, 1, stlbe, ref); 621 r = kvmppc_e500_shadow_map(vcpu_e500, gvaddr, gfn, gtlbe, 1, stlbe,
622 ref);
623 if (r)
624 return r;
609 625
610 vcpu_e500->g2h_tlb1_map[esel] |= (u64)1 << victim; 626 vcpu_e500->g2h_tlb1_map[esel] |= (u64)1 << sesel;
611 vcpu_e500->gtlb_priv[1][esel].ref.flags |= E500_TLB_BITMAP; 627 vcpu_e500->gtlb_priv[1][esel].ref.flags |= E500_TLB_BITMAP;
612 if (vcpu_e500->h2g_tlb1_rmap[victim]) { 628 if (vcpu_e500->h2g_tlb1_rmap[sesel]) {
613 unsigned int idx = vcpu_e500->h2g_tlb1_rmap[victim]; 629 unsigned int idx = vcpu_e500->h2g_tlb1_rmap[sesel];
614 vcpu_e500->g2h_tlb1_map[idx] &= ~(1ULL << victim); 630 vcpu_e500->g2h_tlb1_map[idx] &= ~(1ULL << sesel);
615 } 631 }
616 vcpu_e500->h2g_tlb1_rmap[victim] = esel; 632 vcpu_e500->h2g_tlb1_rmap[sesel] = esel;
617 633
618 return victim; 634 write_stlbe(vcpu_e500, gtlbe, stlbe, stlbsel, sesel);
635
636 return 0;
619} 637}
620 638
621static void kvmppc_recalc_tlb1map_range(struct kvmppc_vcpu_e500 *vcpu_e500) 639static void kvmppc_recalc_tlb1map_range(struct kvmppc_vcpu_e500 *vcpu_e500)
@@ -1034,30 +1052,27 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 eaddr, gpa_t gpaddr,
1034 struct kvm_book3e_206_tlb_entry *gtlbe, stlbe; 1052 struct kvm_book3e_206_tlb_entry *gtlbe, stlbe;
1035 int tlbsel = tlbsel_of(index); 1053 int tlbsel = tlbsel_of(index);
1036 int esel = esel_of(index); 1054 int esel = esel_of(index);
1037 int stlbsel, sesel;
1038 1055
1039 gtlbe = get_entry(vcpu_e500, tlbsel, esel); 1056 gtlbe = get_entry(vcpu_e500, tlbsel, esel);
1040 1057
1041 switch (tlbsel) { 1058 switch (tlbsel) {
1042 case 0: 1059 case 0:
1043 stlbsel = 0;
1044 sesel = 0; /* unused */
1045 priv = &vcpu_e500->gtlb_priv[tlbsel][esel]; 1060 priv = &vcpu_e500->gtlb_priv[tlbsel][esel];
1046 1061
1047 /* Only triggers after clear_tlb_refs */ 1062 /* Triggers after clear_tlb_refs or on initial mapping */
1048 if (unlikely(!(priv->ref.flags & E500_TLB_VALID))) 1063 if (!(priv->ref.flags & E500_TLB_VALID)) {
1049 kvmppc_e500_tlb0_map(vcpu_e500, esel, &stlbe); 1064 kvmppc_e500_tlb0_map(vcpu_e500, esel, &stlbe);
1050 else 1065 } else {
1051 kvmppc_e500_setup_stlbe(vcpu, gtlbe, BOOK3E_PAGESZ_4K, 1066 kvmppc_e500_setup_stlbe(vcpu, gtlbe, BOOK3E_PAGESZ_4K,
1052 &priv->ref, eaddr, &stlbe); 1067 &priv->ref, eaddr, &stlbe);
1068 write_stlbe(vcpu_e500, gtlbe, &stlbe, 0, 0);
1069 }
1053 break; 1070 break;
1054 1071
1055 case 1: { 1072 case 1: {
1056 gfn_t gfn = gpaddr >> PAGE_SHIFT; 1073 gfn_t gfn = gpaddr >> PAGE_SHIFT;
1057 1074 kvmppc_e500_tlb1_map(vcpu_e500, eaddr, gfn, gtlbe, &stlbe,
1058 stlbsel = 1; 1075 esel);
1059 sesel = kvmppc_e500_tlb1_map(vcpu_e500, eaddr, gfn,
1060 gtlbe, &stlbe, esel);
1061 break; 1076 break;
1062 } 1077 }
1063 1078
@@ -1065,8 +1080,6 @@ void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 eaddr, gpa_t gpaddr,
1065 BUG(); 1080 BUG();
1066 break; 1081 break;
1067 } 1082 }
1068
1069 write_stlbe(vcpu_e500, gtlbe, &stlbe, stlbsel, sesel);
1070} 1083}
1071 1084
1072/************* MMU Notifiers *************/ 1085/************* MMU Notifiers *************/