On 22/05/20 18:32, Babu Moger wrote: > [Backported upstream commit 37486135d3a7b03acc7755b63627a130437f066a] > > Though rdpkru and wrpkru are contingent upon CR4.PKE, the PKRU > resource isn't. It can be read with XSAVE and written with XRSTOR. > So, if we don't set the guest PKRU value here(kvm_load_guest_xsave_state), > the guest can read the host value. > > In case of kvm_load_host_xsave_state, guest with CR4.PKE clear could > potentially use XRSTOR to change the host PKRU value. > > While at it, move pkru state save/restore to common code and the > host_pkru field to kvm_vcpu_arch. This will let SVM support protection keys. > > Cc: stable@xxxxxxxxxxxxxxx > Reported-by: Jim Mattson <jmattson@xxxxxxxxxx> > Signed-off-by: Babu Moger <babu.moger@xxxxxxx> > Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx> > --- > arch/x86/include/asm/kvm_host.h | 1 + > arch/x86/kvm/vmx/vmx.c | 18 ------------------ > arch/x86/kvm/x86.c | 17 +++++++++++++++++ > 3 files changed, 18 insertions(+), 18 deletions(-) > > diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h > index 4fc61483919a..e204c43ed4b0 100644 > --- a/arch/x86/include/asm/kvm_host.h > +++ b/arch/x86/include/asm/kvm_host.h > @@ -550,6 +550,7 @@ struct kvm_vcpu_arch { > unsigned long cr4; > unsigned long cr4_guest_owned_bits; > unsigned long cr8; > + u32 host_pkru; > u32 pkru; > u32 hflags; > u64 efer; > diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c > index 04a8212704c1..728758880cb6 100644 > --- a/arch/x86/kvm/vmx/vmx.c > +++ b/arch/x86/kvm/vmx/vmx.c > @@ -1384,7 +1384,6 @@ void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu) > > vmx_vcpu_pi_load(vcpu, cpu); > > - vmx->host_pkru = read_pkru(); > vmx->host_debugctlmsr = get_debugctlmsr(); > } > > @@ -6541,11 +6540,6 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu) > > kvm_load_guest_xcr0(vcpu); > > - if (static_cpu_has(X86_FEATURE_PKU) && > - kvm_read_cr4_bits(vcpu, X86_CR4_PKE) && > - vcpu->arch.pkru != vmx->host_pkru) > - __write_pkru(vcpu->arch.pkru); > - > pt_guest_enter(vmx); > > atomic_switch_perf_msrs(vmx); > @@ -6634,18 +6628,6 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu) > > pt_guest_exit(vmx); > > - /* > - * eager fpu is enabled if PKEY is supported and CR4 is switched > - * back on host, so it is safe to read guest PKRU from current > - * XSAVE. > - */ > - if (static_cpu_has(X86_FEATURE_PKU) && > - kvm_read_cr4_bits(vcpu, X86_CR4_PKE)) { > - vcpu->arch.pkru = rdpkru(); > - if (vcpu->arch.pkru != vmx->host_pkru) > - __write_pkru(vmx->host_pkru); > - } > - > kvm_put_guest_xcr0(vcpu); > > vmx->nested.nested_run_pending = 0; > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index 5d530521f11d..502a23313e7b 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > @@ -821,11 +821,25 @@ void kvm_load_guest_xcr0(struct kvm_vcpu *vcpu) > xsetbv(XCR_XFEATURE_ENABLED_MASK, vcpu->arch.xcr0); > vcpu->guest_xcr0_loaded = 1; > } > + > + if (static_cpu_has(X86_FEATURE_PKU) && > + (kvm_read_cr4_bits(vcpu, X86_CR4_PKE) || > + (vcpu->arch.xcr0 & XFEATURE_MASK_PKRU)) && > + vcpu->arch.pkru != vcpu->arch.host_pkru) > + __write_pkru(vcpu->arch.pkru); > } > EXPORT_SYMBOL_GPL(kvm_load_guest_xcr0); > > void kvm_put_guest_xcr0(struct kvm_vcpu *vcpu) > { > + if (static_cpu_has(X86_FEATURE_PKU) && > + (kvm_read_cr4_bits(vcpu, X86_CR4_PKE) || > + (vcpu->arch.xcr0 & XFEATURE_MASK_PKRU))) { > + vcpu->arch.pkru = rdpkru(); > + if (vcpu->arch.pkru != vcpu->arch.host_pkru) > + __write_pkru(vcpu->arch.host_pkru); > + } > + > if (vcpu->guest_xcr0_loaded) { > if (vcpu->arch.xcr0 != host_xcr0) > xsetbv(XCR_XFEATURE_ENABLED_MASK, host_xcr0); > @@ -3437,6 +3451,9 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) > > kvm_x86_ops->vcpu_load(vcpu, cpu); > > + /* Save host pkru register if supported */ > + vcpu->arch.host_pkru = read_pkru(); > + > fpregs_assert_state_consistent(); > if (test_thread_flag(TIF_NEED_FPU_LOAD)) > switch_fpu_return(); > Acked-by: Paolo Bonzini <pbonzini@xxxxxxxxxx>