Skip to content

Commit 5cf2360

Browse files
committed
Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull KVM fix from Radim Krčmář: "Fix PPC HV host crash that can occur as a result of resizing the guest hashed page table" * tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm: KVM: PPC: Book3S HV: Fix exclusion between HPT resizing and other HPT updates
2 parents a579e94 + d850a25 commit 5cf2360

File tree

2 files changed

+29
-10
lines changed

2 files changed

+29
-10
lines changed

arch/powerpc/kvm/book3s_64_mmu_hv.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,16 @@ int kvmppc_book3s_hv_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu,
646646
hnow_v = hpte_new_to_old_v(hnow_v, hnow_r);
647647
hnow_r = hpte_new_to_old_r(hnow_r);
648648
}
649+
650+
/*
651+
* If the HPT is being resized, don't update the HPTE,
652+
* instead let the guest retry after the resize operation is complete.
653+
* The synchronization for hpte_setup_done test vs. set is provided
654+
* by the HPTE lock.
655+
*/
656+
if (!kvm->arch.hpte_setup_done)
657+
goto out_unlock;
658+
649659
if ((hnow_v & ~HPTE_V_HVLOCK) != hpte[0] || hnow_r != hpte[1] ||
650660
rev->guest_rpte != hpte[2])
651661
/* HPTE has been changed under us; let the guest retry */

arch/powerpc/kvm/book3s_hv.c

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2705,11 +2705,14 @@ static noinline void kvmppc_run_core(struct kvmppc_vcore *vc)
27052705
* Hard-disable interrupts, and check resched flag and signals.
27062706
* If we need to reschedule or deliver a signal, clean up
27072707
* and return without going into the guest(s).
2708+
* If the hpte_setup_done flag has been cleared, don't go into the
2709+
* guest because that means a HPT resize operation is in progress.
27082710
*/
27092711
local_irq_disable();
27102712
hard_irq_disable();
27112713
if (lazy_irq_pending() || need_resched() ||
2712-
recheck_signals(&core_info)) {
2714+
recheck_signals(&core_info) ||
2715+
(!kvm_is_radix(vc->kvm) && !vc->kvm->arch.hpte_setup_done)) {
27132716
local_irq_enable();
27142717
vc->vcore_state = VCORE_INACTIVE;
27152718
/* Unlock all except the primary vcore */
@@ -3078,7 +3081,7 @@ static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc)
30783081

30793082
static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
30803083
{
3081-
int n_ceded, i;
3084+
int n_ceded, i, r;
30823085
struct kvmppc_vcore *vc;
30833086
struct kvm_vcpu *v;
30843087

@@ -3132,6 +3135,20 @@ static int kvmppc_run_vcpu(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
31323135

31333136
while (vcpu->arch.state == KVMPPC_VCPU_RUNNABLE &&
31343137
!signal_pending(current)) {
3138+
/* See if the HPT and VRMA are ready to go */
3139+
if (!kvm_is_radix(vcpu->kvm) &&
3140+
!vcpu->kvm->arch.hpte_setup_done) {
3141+
spin_unlock(&vc->lock);
3142+
r = kvmppc_hv_setup_htab_rma(vcpu);
3143+
spin_lock(&vc->lock);
3144+
if (r) {
3145+
kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY;
3146+
kvm_run->fail_entry.hardware_entry_failure_reason = 0;
3147+
vcpu->arch.ret = r;
3148+
break;
3149+
}
3150+
}
3151+
31353152
if (vc->vcore_state == VCORE_PREEMPT && vc->runner == NULL)
31363153
kvmppc_vcore_end_preempt(vc);
31373154

@@ -3249,13 +3266,6 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu)
32493266
/* Order vcpus_running vs. hpte_setup_done, see kvmppc_alloc_reset_hpt */
32503267
smp_mb();
32513268

3252-
/* On the first time here, set up HTAB and VRMA */
3253-
if (!kvm_is_radix(vcpu->kvm) && !vcpu->kvm->arch.hpte_setup_done) {
3254-
r = kvmppc_hv_setup_htab_rma(vcpu);
3255-
if (r)
3256-
goto out;
3257-
}
3258-
32593269
flush_all_to_thread(current);
32603270

32613271
/* Save userspace EBB and other register values */
@@ -3303,7 +3313,6 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu)
33033313
}
33043314
mtspr(SPRN_VRSAVE, user_vrsave);
33053315

3306-
out:
33073316
vcpu->arch.state = KVMPPC_VCPU_NOTREADY;
33083317
atomic_dec(&vcpu->kvm->arch.vcpus_running);
33093318
return r;

0 commit comments

Comments
 (0)