Skip to content

Commit 339fa4a

Browse files
paulusmackgregkh
authored andcommitted
KVM: PPC: Book3S HV: Context-switch EBB registers properly
commit ca8efa1 upstream. This adds code to save the values of three SPRs (special-purpose registers) used by userspace to control event-based branches (EBBs), which are essentially interrupts that get delivered directly to userspace. These registers are loaded up with guest values when entering the guest, and their values are saved when exiting the guest, but we were not saving the host values and restoring them before going back to userspace. On POWER8 this would only affect userspace programs which explicitly request the use of EBBs and also use the KVM_RUN ioctl, since the only source of EBBs on POWER8 is the PMU, and there is an explicit enable bit in the PMU registers (and those PMU registers do get properly context-switched between host and guest). On POWER9 there is provision for externally-generated EBBs, and these are not subject to the control in the PMU registers. Since these registers only affect userspace, we can save them when we first come in from userspace and restore them before returning to userspace, rather than saving/restoring the host values on every guest entry/exit. Similarly, we don't need to worry about their values on offline secondary threads since they execute in the context of the idle task, which never executes in userspace. Fixes: b005255 ("KVM: PPC: Book3S HV: Context-switch new POWER8 SPRs", 2014-01-08) Signed-off-by: Paul Mackerras <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 29da136 commit 339fa4a

File tree

1 file changed

+16
-0
lines changed

1 file changed

+16
-0
lines changed

arch/powerpc/kvm/book3s_hv.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2687,6 +2687,7 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu)
26872687
{
26882688
int r;
26892689
int srcu_idx;
2690+
unsigned long ebb_regs[3] = {}; /* shut up GCC */
26902691

26912692
if (!vcpu->arch.sane) {
26922693
run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
@@ -2736,6 +2737,14 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu)
27362737
flush_fp_to_thread(current);
27372738
flush_altivec_to_thread(current);
27382739
flush_vsx_to_thread(current);
2740+
2741+
/* Save userspace EBB register values */
2742+
if (cpu_has_feature(CPU_FTR_ARCH_207S)) {
2743+
ebb_regs[0] = mfspr(SPRN_EBBHR);
2744+
ebb_regs[1] = mfspr(SPRN_EBBRR);
2745+
ebb_regs[2] = mfspr(SPRN_BESCR);
2746+
}
2747+
27392748
vcpu->arch.wqp = &vcpu->arch.vcore->wq;
27402749
vcpu->arch.pgdir = current->mm->pgd;
27412750
vcpu->arch.state = KVMPPC_VCPU_BUSY_IN_HOST;
@@ -2757,6 +2766,13 @@ static int kvmppc_vcpu_run_hv(struct kvm_run *run, struct kvm_vcpu *vcpu)
27572766
}
27582767
} while (is_kvmppc_resume_guest(r));
27592768

2769+
/* Restore userspace EBB register values */
2770+
if (cpu_has_feature(CPU_FTR_ARCH_207S)) {
2771+
mtspr(SPRN_EBBHR, ebb_regs[0]);
2772+
mtspr(SPRN_EBBRR, ebb_regs[1]);
2773+
mtspr(SPRN_BESCR, ebb_regs[2]);
2774+
}
2775+
27602776
out:
27612777
vcpu->arch.state = KVMPPC_VCPU_NOTREADY;
27622778
atomic_dec(&vcpu->kvm->arch.vcpus_running);

0 commit comments

Comments
 (0)