aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm/book3s_hv_rm_mmu.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kvm/book3s_hv_rm_mmu.c')
-rw-r--r--arch/powerpc/kvm/book3s_hv_rm_mmu.c45
1 files changed, 26 insertions, 19 deletions
diff --git a/arch/powerpc/kvm/book3s_hv_rm_mmu.c b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
index ba4a1376b331..91b45a03f438 100644
--- a/arch/powerpc/kvm/book3s_hv_rm_mmu.c
+++ b/arch/powerpc/kvm/book3s_hv_rm_mmu.c
@@ -87,15 +87,17 @@ EXPORT_SYMBOL_GPL(kvmppc_add_revmap_chain);
87 87
88/* Remove this HPTE from the chain for a real page */ 88/* Remove this HPTE from the chain for a real page */
89static void remove_revmap_chain(struct kvm *kvm, long pte_index, 89static void remove_revmap_chain(struct kvm *kvm, long pte_index,
90 unsigned long hpte_v) 90 struct revmap_entry *rev,
91 unsigned long hpte_v, unsigned long hpte_r)
91{ 92{
92 struct revmap_entry *rev, *next, *prev; 93 struct revmap_entry *next, *prev;
93 unsigned long gfn, ptel, head; 94 unsigned long gfn, ptel, head;
94 struct kvm_memory_slot *memslot; 95 struct kvm_memory_slot *memslot;
95 unsigned long *rmap; 96 unsigned long *rmap;
97 unsigned long rcbits;
96 98
97 rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]); 99 rcbits = hpte_r & (HPTE_R_R | HPTE_R_C);
98 ptel = rev->guest_rpte; 100 ptel = rev->guest_rpte |= rcbits;
99 gfn = hpte_rpn(ptel, hpte_page_size(hpte_v, ptel)); 101 gfn = hpte_rpn(ptel, hpte_page_size(hpte_v, ptel));
100 memslot = builtin_gfn_to_memslot(kvm, gfn); 102 memslot = builtin_gfn_to_memslot(kvm, gfn);
101 if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID)) 103 if (!memslot || (memslot->flags & KVM_MEMSLOT_INVALID))
@@ -116,6 +118,7 @@ static void remove_revmap_chain(struct kvm *kvm, long pte_index,
116 else 118 else
117 *rmap = (*rmap & ~KVMPPC_RMAP_INDEX) | head; 119 *rmap = (*rmap & ~KVMPPC_RMAP_INDEX) | head;
118 } 120 }
121 *rmap |= rcbits << KVMPPC_RMAP_RC_SHIFT;
119 unlock_rmap(rmap); 122 unlock_rmap(rmap);
120} 123}
121 124
@@ -162,6 +165,7 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
162 pte_t pte; 165 pte_t pte;
163 unsigned int writing; 166 unsigned int writing;
164 unsigned long mmu_seq; 167 unsigned long mmu_seq;
168 unsigned long rcbits;
165 bool realmode = vcpu->arch.vcore->vcore_state == VCORE_RUNNING; 169 bool realmode = vcpu->arch.vcore->vcore_state == VCORE_RUNNING;
166 170
167 psize = hpte_page_size(pteh, ptel); 171 psize = hpte_page_size(pteh, ptel);
@@ -320,6 +324,9 @@ long kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
320 } else { 324 } else {
321 kvmppc_add_revmap_chain(kvm, rev, rmap, pte_index, 325 kvmppc_add_revmap_chain(kvm, rev, rmap, pte_index,
322 realmode); 326 realmode);
327 /* Only set R/C in real HPTE if already set in *rmap */
328 rcbits = *rmap >> KVMPPC_RMAP_RC_SHIFT;
329 ptel &= rcbits | ~(HPTE_R_R | HPTE_R_C);
323 } 330 }
324 } 331 }
325 332
@@ -394,7 +401,8 @@ long kvmppc_h_remove(struct kvm_vcpu *vcpu, unsigned long flags,
394 asm volatile("tlbiel %0" : : "r" (rb)); 401 asm volatile("tlbiel %0" : : "r" (rb));
395 asm volatile("ptesync" : : : "memory"); 402 asm volatile("ptesync" : : : "memory");
396 } 403 }
397 remove_revmap_chain(kvm, pte_index, v); 404 /* Read PTE low word after tlbie to get final R/C values */
405 remove_revmap_chain(kvm, pte_index, rev, v, hpte[1]);
398 } 406 }
399 r = rev->guest_rpte; 407 r = rev->guest_rpte;
400 unlock_hpte(hpte, 0); 408 unlock_hpte(hpte, 0);
@@ -469,12 +477,13 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
469 477
470 args[j] = ((0x80 | flags) << 56) + pte_index; 478 args[j] = ((0x80 | flags) << 56) + pte_index;
471 rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]); 479 rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]);
472 /* insert R and C bits from guest PTE */
473 rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C);
474 args[j] |= rcbits << (56 - 5);
475 480
476 if (!(hp[0] & HPTE_V_VALID)) 481 if (!(hp[0] & HPTE_V_VALID)) {
482 /* insert R and C bits from PTE */
483 rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C);
484 args[j] |= rcbits << (56 - 5);
477 continue; 485 continue;
486 }
478 487
479 hp[0] &= ~HPTE_V_VALID; /* leave it locked */ 488 hp[0] &= ~HPTE_V_VALID; /* leave it locked */
480 tlbrb[n] = compute_tlbie_rb(hp[0], hp[1], pte_index); 489 tlbrb[n] = compute_tlbie_rb(hp[0], hp[1], pte_index);
@@ -505,13 +514,16 @@ long kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu)
505 asm volatile("ptesync" : : : "memory"); 514 asm volatile("ptesync" : : : "memory");
506 } 515 }
507 516
517 /* Read PTE low words after tlbie to get final R/C values */
508 for (k = 0; k < n; ++k) { 518 for (k = 0; k < n; ++k) {
509 j = indexes[k]; 519 j = indexes[k];
510 pte_index = args[j] & ((1ul << 56) - 1); 520 pte_index = args[j] & ((1ul << 56) - 1);
511 hp = hptes[k]; 521 hp = hptes[k];
512 rev = revs[k]; 522 rev = revs[k];
513 remove_revmap_chain(kvm, pte_index, hp[0]); 523 remove_revmap_chain(kvm, pte_index, rev, hp[0], hp[1]);
514 unlock_hpte(hp, 0); 524 rcbits = rev->guest_rpte & (HPTE_R_R|HPTE_R_C);
525 args[j] |= rcbits << (56 - 5);
526 hp[0] = 0;
515 } 527 }
516 } 528 }
517 529
@@ -595,8 +607,7 @@ long kvmppc_h_read(struct kvm_vcpu *vcpu, unsigned long flags,
595 pte_index &= ~3; 607 pte_index &= ~3;
596 n = 4; 608 n = 4;
597 } 609 }
598 if (flags & H_R_XLATE) 610 rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]);
599 rev = real_vmalloc_addr(&kvm->arch.revmap[pte_index]);
600 for (i = 0; i < n; ++i, ++pte_index) { 611 for (i = 0; i < n; ++i, ++pte_index) {
601 hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4)); 612 hpte = (unsigned long *)(kvm->arch.hpt_virt + (pte_index << 4));
602 v = hpte[0] & ~HPTE_V_HVLOCK; 613 v = hpte[0] & ~HPTE_V_HVLOCK;
@@ -605,12 +616,8 @@ long kvmppc_h_read(struct kvm_vcpu *vcpu, unsigned long flags,
605 v &= ~HPTE_V_ABSENT; 616 v &= ~HPTE_V_ABSENT;
606 v |= HPTE_V_VALID; 617 v |= HPTE_V_VALID;
607 } 618 }
608 if (v & HPTE_V_VALID) { 619 if (v & HPTE_V_VALID)
609 if (rev) 620 r = rev[i].guest_rpte | (r & (HPTE_R_R | HPTE_R_C));
610 r = rev[i].guest_rpte;
611 else
612 r = hpte[1] | HPTE_R_RPN;
613 }
614 vcpu->arch.gpr[4 + i * 2] = v; 621 vcpu->arch.gpr[4 + i * 2] = v;
615 vcpu->arch.gpr[5 + i * 2] = r; 622 vcpu->arch.gpr[5 + i * 2] = r;
616 } 623 }