Message ID | 20230719144131.29052-9-binbin.wu@linux.intel.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Linear Address Masking (LAM) KVM Enabling | expand |
On Wed, Jul 19, 2023, Binbin Wu wrote: > index abf6d42672cd..f18e610c4363 100644 > --- a/arch/x86/kvm/vmx/vmx.c > +++ b/arch/x86/kvm/vmx/vmx.c > @@ -8177,8 +8177,7 @@ static void vmx_vm_destroy(struct kvm *kvm) > free_pages((unsigned long)kvm_vmx->pid_table, vmx_get_pid_table_order(kvm)); > } > > -static gva_t vmx_get_untagged_addr(struct kvm_vcpu *vcpu, gva_t gva, > - unsigned int flags) > +gva_t vmx_get_untagged_addr(struct kvm_vcpu *vcpu, gva_t gva, unsigned int flags) > { > unsigned long cr3_bits; > int lam_bit; > diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h > index 32384ba38499..6fb612355769 100644 > --- a/arch/x86/kvm/vmx/vmx.h > +++ b/arch/x86/kvm/vmx/vmx.h > @@ -421,6 +421,8 @@ void vmx_enable_intercept_for_msr(struct kvm_vcpu *vcpu, u32 msr, int type); > u64 vmx_get_l2_tsc_offset(struct kvm_vcpu *vcpu); > u64 vmx_get_l2_tsc_multiplier(struct kvm_vcpu *vcpu); > > +gva_t vmx_get_untagged_addr(struct kvm_vcpu *vcpu, gva_t gva, unsigned int flags); > + I think it makes sense to squash this with whatever patch first adds vmx_get_untagged_addr(). It'll make that initial "virtual LAM_*" patch a fair bit bigger, but overall I think the series/patches will be easier to review, e.g. the rules for LAM_SUP will mostly be captured in a single patch. One could even make an argument for squashing LAM_U* support with the LAM_SUP patch, but my vote is to keep them separate.
On Wed, Jul 19, 2023, Binbin Wu wrote: > Untag address for 64-bit memory operand in VMExit handlers when LAM is applicable. > > For VMExit handlers related to 64-bit linear address: > - Cases need to untag address (handled in get_vmx_mem_address()) > Operand(s) of VMX instructions and INVPCID. > Operand(s) of SGX ENCLS. > - Cases LAM doesn't apply to (no change needed) > Operand of INVLPG. > Linear address in INVPCID descriptor. > Linear address in INVVPID descriptor. > BASEADDR specified in SESC of ECREATE. > > Note: > LAM doesn't apply to the writes to control registers or MSRs. > LAM masking applies before paging, so the faulting linear address in CR2 > doesn't contain the metadata. > The guest linear address saved in VMCS doesn't contain metadata. > > Signed-off-by: Binbin Wu <binbin.wu@linux.intel.com> > Reviewed-by: Chao Gao <chao.gao@intel.com> > --- > arch/x86/kvm/vmx/nested.c | 2 ++ > arch/x86/kvm/vmx/sgx.c | 1 + > arch/x86/kvm/vmx/vmx.c | 3 +-- > arch/x86/kvm/vmx/vmx.h | 2 ++ > arch/x86/kvm/x86.c | 1 + > 5 files changed, 7 insertions(+), 2 deletions(-) > > diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c > index 76c9904c6625..bd2c8936953a 100644 > --- a/arch/x86/kvm/vmx/nested.c > +++ b/arch/x86/kvm/vmx/nested.c > @@ -4980,6 +4980,7 @@ int get_vmx_mem_address(struct kvm_vcpu *vcpu, unsigned long exit_qualification, > else > *ret = off; > > + *ret = vmx_get_untagged_addr(vcpu, *ret, 0); > /* Long mode: #GP(0)/#SS(0) if the memory address is in a > * non-canonical form. This is the only check on the memory > * destination for long mode! > @@ -5797,6 +5798,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu) > vpid02 = nested_get_vpid02(vcpu); > switch (type) { > case VMX_VPID_EXTENT_INDIVIDUAL_ADDR: > + /* LAM doesn't apply to the address in descriptor of invvpid */ Nit, if we're going to bother with a comment, I think it makes sense to explain that LAM doesn't apply to any TLB invalidation input, i.e. as opposed to just saying the INVVPID is special. /* * LAM doesn't apply to addresses that are inputs to TLB * invalidation. */ And then when LAM and LASS collide: /* * LAM and LASS don't apply to ... */ > if (!operand.vpid || > is_noncanonical_address(operand.gla, vcpu)) > return nested_vmx_fail(vcpu, > diff --git a/arch/x86/kvm/vmx/sgx.c b/arch/x86/kvm/vmx/sgx.c > index 3e822e582497..6fef01e0536e 100644 > --- a/arch/x86/kvm/vmx/sgx.c > +++ b/arch/x86/kvm/vmx/sgx.c > @@ -37,6 +37,7 @@ static int sgx_get_encls_gva(struct kvm_vcpu *vcpu, unsigned long offset, > if (!IS_ALIGNED(*gva, alignment)) { > fault = true; > } else if (likely(is_64_bit_mode(vcpu))) { > + *gva = vmx_get_untagged_addr(vcpu, *gva, 0); > fault = is_noncanonical_address(*gva, vcpu); > } else { > *gva &= 0xffffffff; > diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c > index abf6d42672cd..f18e610c4363 100644 > --- a/arch/x86/kvm/vmx/vmx.c > +++ b/arch/x86/kvm/vmx/vmx.c > @@ -8177,8 +8177,7 @@ static void vmx_vm_destroy(struct kvm *kvm) > free_pages((unsigned long)kvm_vmx->pid_table, vmx_get_pid_table_order(kvm)); > } > > -static gva_t vmx_get_untagged_addr(struct kvm_vcpu *vcpu, gva_t gva, > - unsigned int flags) > +gva_t vmx_get_untagged_addr(struct kvm_vcpu *vcpu, gva_t gva, unsigned int flags) > { > unsigned long cr3_bits; > int lam_bit; > diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h > index 32384ba38499..6fb612355769 100644 > --- a/arch/x86/kvm/vmx/vmx.h > +++ b/arch/x86/kvm/vmx/vmx.h > @@ -421,6 +421,8 @@ void vmx_enable_intercept_for_msr(struct kvm_vcpu *vcpu, u32 msr, int type); > u64 vmx_get_l2_tsc_offset(struct kvm_vcpu *vcpu); > u64 vmx_get_l2_tsc_multiplier(struct kvm_vcpu *vcpu); > > +gva_t vmx_get_untagged_addr(struct kvm_vcpu *vcpu, gva_t gva, unsigned int flags); > + > static inline void vmx_set_intercept_for_msr(struct kvm_vcpu *vcpu, u32 msr, > int type, bool value) > { > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index 339a113b45af..d2a0cdfb77a5 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > @@ -13370,6 +13370,7 @@ int kvm_handle_invpcid(struct kvm_vcpu *vcpu, unsigned long type, gva_t gva) > > switch (type) { > case INVPCID_TYPE_INDIV_ADDR: > + /* LAM doesn't apply to the address in descriptor of invpcid */ Same thing here. > if ((!pcid_enabled && (operand.pcid != 0)) || > is_noncanonical_address(operand.gla, vcpu)) { > kvm_inject_gp(vcpu, 0); > -- > 2.25.1 >
diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c index 76c9904c6625..bd2c8936953a 100644 --- a/arch/x86/kvm/vmx/nested.c +++ b/arch/x86/kvm/vmx/nested.c @@ -4980,6 +4980,7 @@ int get_vmx_mem_address(struct kvm_vcpu *vcpu, unsigned long exit_qualification, else *ret = off; + *ret = vmx_get_untagged_addr(vcpu, *ret, 0); /* Long mode: #GP(0)/#SS(0) if the memory address is in a * non-canonical form. This is the only check on the memory * destination for long mode! @@ -5797,6 +5798,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu) vpid02 = nested_get_vpid02(vcpu); switch (type) { case VMX_VPID_EXTENT_INDIVIDUAL_ADDR: + /* LAM doesn't apply to the address in descriptor of invvpid */ if (!operand.vpid || is_noncanonical_address(operand.gla, vcpu)) return nested_vmx_fail(vcpu, diff --git a/arch/x86/kvm/vmx/sgx.c b/arch/x86/kvm/vmx/sgx.c index 3e822e582497..6fef01e0536e 100644 --- a/arch/x86/kvm/vmx/sgx.c +++ b/arch/x86/kvm/vmx/sgx.c @@ -37,6 +37,7 @@ static int sgx_get_encls_gva(struct kvm_vcpu *vcpu, unsigned long offset, if (!IS_ALIGNED(*gva, alignment)) { fault = true; } else if (likely(is_64_bit_mode(vcpu))) { + *gva = vmx_get_untagged_addr(vcpu, *gva, 0); fault = is_noncanonical_address(*gva, vcpu); } else { *gva &= 0xffffffff; diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index abf6d42672cd..f18e610c4363 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -8177,8 +8177,7 @@ static void vmx_vm_destroy(struct kvm *kvm) free_pages((unsigned long)kvm_vmx->pid_table, vmx_get_pid_table_order(kvm)); } -static gva_t vmx_get_untagged_addr(struct kvm_vcpu *vcpu, gva_t gva, - unsigned int flags) +gva_t vmx_get_untagged_addr(struct kvm_vcpu *vcpu, gva_t gva, unsigned int flags) { unsigned long cr3_bits; int lam_bit; diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index 32384ba38499..6fb612355769 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -421,6 +421,8 @@ void vmx_enable_intercept_for_msr(struct kvm_vcpu *vcpu, u32 msr, int type); u64 vmx_get_l2_tsc_offset(struct kvm_vcpu *vcpu); u64 vmx_get_l2_tsc_multiplier(struct kvm_vcpu *vcpu); +gva_t vmx_get_untagged_addr(struct kvm_vcpu *vcpu, gva_t gva, unsigned int flags); + static inline void vmx_set_intercept_for_msr(struct kvm_vcpu *vcpu, u32 msr, int type, bool value) { diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 339a113b45af..d2a0cdfb77a5 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -13370,6 +13370,7 @@ int kvm_handle_invpcid(struct kvm_vcpu *vcpu, unsigned long type, gva_t gva) switch (type) { case INVPCID_TYPE_INDIV_ADDR: + /* LAM doesn't apply to the address in descriptor of invpcid */ if ((!pcid_enabled && (operand.pcid != 0)) || is_noncanonical_address(operand.gla, vcpu)) { kvm_inject_gp(vcpu, 0);