KVM: x86: Introduce get_untagged_addr() in kvm_x86_ops and call it in emulator
authorBinbin Wu <binbin.wu@linux.intel.com>
Wed, 13 Sep 2023 12:42:19 +0000 (20:42 +0800)
committerSean Christopherson <seanjc@google.com>
Wed, 29 Nov 2023 01:54:06 +0000 (17:54 -0800)
Introduce a new interface get_untagged_addr() to kvm_x86_ops to untag
the metadata from linear address.  Call the interface in linearization
of instruction emulator for 64-bit mode.

When enabled feature like Intel Linear Address Masking (LAM) or AMD Upper
Address Ignore (UAI), linear addresses may be tagged with metadata that
needs to be dropped prior to canonicality checks, i.e. the metadata is
ignored.

Introduce get_untagged_addr() to kvm_x86_ops to hide the vendor specific
code, as sadly LAM and UAI have different semantics.  Pass the emulator
flags to allow vendor specific implementation to precisely identify the
access type (LAM doesn't untag certain accesses).

Signed-off-by: Binbin Wu <binbin.wu@linux.intel.com>
Reviewed-by: Chao Gao <chao.gao@intel.com>
Tested-by: Xuelian Guo <xuelian.guo@intel.com>
Link: https://lore.kernel.org/r/20230913124227.12574-9-binbin.wu@linux.intel.com
[sean: massage changelog]
Signed-off-by: Sean Christopherson <seanjc@google.com>
arch/x86/include/asm/kvm-x86-ops.h
arch/x86/include/asm/kvm_host.h
arch/x86/kvm/emulate.c
arch/x86/kvm/kvm_emulate.h
arch/x86/kvm/x86.c

index 26b628d84594b93fea349b0a738768cfb9a9a15b..756791665117b983defc43a97b3c2e820ddbb026 100644 (file)
@@ -135,6 +135,7 @@ KVM_X86_OP(msr_filter_changed)
 KVM_X86_OP(complete_emulated_msr)
 KVM_X86_OP(vcpu_deliver_sipi_vector)
 KVM_X86_OP_OPTIONAL_RET0(vcpu_get_apicv_inhibit_reasons);
+KVM_X86_OP_OPTIONAL(get_untagged_addr)
 
 #undef KVM_X86_OP
 #undef KVM_X86_OP_OPTIONAL
index a565a2e70f30f91cdfebd337206038f90d2363aa..8d042f27d644573338e207516fffb2c41278d202 100644 (file)
@@ -1762,6 +1762,8 @@ struct kvm_x86_ops {
         * Returns vCPU specific APICv inhibit reasons
         */
        unsigned long (*vcpu_get_apicv_inhibit_reasons)(struct kvm_vcpu *vcpu);
+
+       gva_t (*get_untagged_addr)(struct kvm_vcpu *vcpu, gva_t gva, unsigned int flags);
 };
 
 struct kvm_x86_nested_ops {
index ceec8c5f9687400e7e966ade082c8d077d76120c..e223043ef5b26f23be5b2f0606641f66c5cd18aa 100644 (file)
@@ -701,7 +701,7 @@ static __always_inline int __linearize(struct x86_emulate_ctxt *ctxt,
        *max_size = 0;
        switch (mode) {
        case X86EMUL_MODE_PROT64:
-               *linear = la;
+               *linear = la = ctxt->ops->get_untagged_addr(ctxt, la, flags);
                va_bits = ctxt_virt_addr_bits(ctxt);
                if (!__is_canonical_address(la, va_bits))
                        goto bad;
index 8bd9b23543cc7ab34843d395a793293160ba3475..e6d149825169dda3ace396ca979923c4a2d108e8 100644 (file)
@@ -230,6 +230,9 @@ struct x86_emulate_ops {
        int (*leave_smm)(struct x86_emulate_ctxt *ctxt);
        void (*triple_fault)(struct x86_emulate_ctxt *ctxt);
        int (*set_xcr)(struct x86_emulate_ctxt *ctxt, u32 index, u64 xcr);
+
+       gva_t (*get_untagged_addr)(struct x86_emulate_ctxt *ctxt, gva_t addr,
+                                  unsigned int flags);
 };
 
 /* Type, address-of, and value of an instruction's operand. */
index 3a648b6e632d3e86e61bd290a6dd1d0e530e3138..557872c0331a14e4d9ccfc481d1befd01ffa4d35 100644 (file)
@@ -8445,6 +8445,15 @@ static void emulator_vm_bugged(struct x86_emulate_ctxt *ctxt)
                kvm_vm_bugged(kvm);
 }
 
+static gva_t emulator_get_untagged_addr(struct x86_emulate_ctxt *ctxt,
+                                       gva_t addr, unsigned int flags)
+{
+       if (!kvm_x86_ops.get_untagged_addr)
+               return addr;
+
+       return static_call(kvm_x86_get_untagged_addr)(emul_to_vcpu(ctxt), addr, flags);
+}
+
 static const struct x86_emulate_ops emulate_ops = {
        .vm_bugged           = emulator_vm_bugged,
        .read_gpr            = emulator_read_gpr,
@@ -8489,6 +8498,7 @@ static const struct x86_emulate_ops emulate_ops = {
        .leave_smm           = emulator_leave_smm,
        .triple_fault        = emulator_triple_fault,
        .set_xcr             = emulator_set_xcr,
+       .get_untagged_addr   = emulator_get_untagged_addr,
 };
 
 static void toggle_interruptibility(struct kvm_vcpu *vcpu, u32 mask)