Commit d976f680 authored by Michael Ellerman's avatar Michael Ellerman

KVM: PPC: Book3S HV: Context switch AMR on Power9

kvmhv_p9_guest_entry() implements a fast-path guest entry for Power9
when guest and host are both running with the Radix MMU.

Currently in that path we don't save the host AMR (Authority Mask
Register) value, and we always restore 0 on return to the host. That
is OK at the moment because the AMR is not used for storage keys with
the Radix MMU.

However we plan to start using the AMR on Radix to prevent the kernel
from reading/writing to userspace outside of copy_to/from_user(). In
order to make that work we need to save/restore the AMR value.

We only restore the value if it is different from the guest value,
which is already in the register when we exit to the host. This should
mean we rarely need to actually restore the value when running a
modern Linux as a guest, because it will be using the same value as
us.
Signed-off-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Tested-by: default avatarRussell Currey <ruscur@russell.cc>
parent 1c7fc5cb
...@@ -3455,6 +3455,7 @@ int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit, ...@@ -3455,6 +3455,7 @@ int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit,
unsigned long host_dscr = mfspr(SPRN_DSCR); unsigned long host_dscr = mfspr(SPRN_DSCR);
unsigned long host_tidr = mfspr(SPRN_TIDR); unsigned long host_tidr = mfspr(SPRN_TIDR);
unsigned long host_iamr = mfspr(SPRN_IAMR); unsigned long host_iamr = mfspr(SPRN_IAMR);
unsigned long host_amr = mfspr(SPRN_AMR);
s64 dec; s64 dec;
u64 tb; u64 tb;
int trap, save_pmu; int trap, save_pmu;
...@@ -3571,13 +3572,15 @@ int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit, ...@@ -3571,13 +3572,15 @@ int kvmhv_p9_guest_entry(struct kvm_vcpu *vcpu, u64 time_limit,
mtspr(SPRN_PSPB, 0); mtspr(SPRN_PSPB, 0);
mtspr(SPRN_WORT, 0); mtspr(SPRN_WORT, 0);
mtspr(SPRN_AMR, 0);
mtspr(SPRN_UAMOR, 0); mtspr(SPRN_UAMOR, 0);
mtspr(SPRN_DSCR, host_dscr); mtspr(SPRN_DSCR, host_dscr);
mtspr(SPRN_TIDR, host_tidr); mtspr(SPRN_TIDR, host_tidr);
mtspr(SPRN_IAMR, host_iamr); mtspr(SPRN_IAMR, host_iamr);
mtspr(SPRN_PSPB, 0); mtspr(SPRN_PSPB, 0);
if (host_amr != vcpu->arch.amr)
mtspr(SPRN_AMR, host_amr);
msr_check_and_set(MSR_FP | MSR_VEC | MSR_VSX); msr_check_and_set(MSR_FP | MSR_VEC | MSR_VSX);
store_fp_state(&vcpu->arch.fp); store_fp_state(&vcpu->arch.fp);
#ifdef CONFIG_ALTIVEC #ifdef CONFIG_ALTIVEC
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment