| Date | Fri, 15 Apr 2022 17:07:10 +0200 | Subject | Re: [RFC PATCH v5 095/104] KVM: TDX: Implement callbacks for MSR operations for TDX | From | Paolo Bonzini <> |
| |
On 3/4/22 20:49, isaku.yamahata@intel.com wrote: > From: Isaku Yamahata <isaku.yamahata@intel.com> > > Implements set_msr/get_msr/has_emulated_msr methods for TDX to handle > hypercall from guest TD for paravirtualized rdmsr and wrmsr. The TDX > module virtualizes MSRs. For some MSRs, it injects #VE to the guest TD > upon RDMSR or WRMSR. The exact list of such MSRs are defined in the spec. > > Upon #VE, the guest TD may execute hypercalls, > TDG.VP.VMCALL<INSTRUCTION.RDMSR> and TDG.VP.VMCALL<INSTRUCTION.WRMSR>, > which are defined in GHCI (Guest-Host Communication Interface) so that the > host VMM (e.g. KVM) can virtualizes the MSRs. > > Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com> > --- > arch/x86/kvm/vmx/main.c | 34 +++++++++++++++++-- > arch/x86/kvm/vmx/tdx.c | 68 ++++++++++++++++++++++++++++++++++++++ > arch/x86/kvm/vmx/x86_ops.h | 6 ++++ > 3 files changed, 105 insertions(+), 3 deletions(-) > > diff --git a/arch/x86/kvm/vmx/main.c b/arch/x86/kvm/vmx/main.c > index 1e65406e3882..a528cfdbce54 100644 > --- a/arch/x86/kvm/vmx/main.c > +++ b/arch/x86/kvm/vmx/main.c > @@ -165,6 +165,34 @@ static void vt_handle_exit_irqoff(struct kvm_vcpu *vcpu) > vmx_handle_exit_irqoff(vcpu); > } > > +static int vt_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) > +{ > + if (unlikely(is_td_vcpu(vcpu))) > + return tdx_set_msr(vcpu, msr_info); > + > + return vmx_set_msr(vcpu, msr_info); > +} > + > +/* > + * The kvm parameter can be NULL (module initialization, or invocation before > + * VM creation). Be sure to check the kvm parameter before using it. > + */ > +static bool vt_has_emulated_msr(struct kvm *kvm, u32 index) > +{ > + if (kvm && is_td(kvm)) > + return tdx_is_emulated_msr(index, true); > + > + return vmx_has_emulated_msr(kvm, index); > +} > + > +static int vt_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) > +{ > + if (unlikely(is_td_vcpu(vcpu))) > + return tdx_get_msr(vcpu, msr_info); > + > + return vmx_get_msr(vcpu, msr_info); > +} > + > static void vt_apicv_post_state_restore(struct kvm_vcpu *vcpu) > { > if (is_td_vcpu(vcpu)) > @@ -393,7 +421,7 @@ struct kvm_x86_ops vt_x86_ops __initdata = { > .hardware_enable = vt_hardware_enable, > .hardware_disable = vt_hardware_disable, > .cpu_has_accelerated_tpr = report_flexpriority, > - .has_emulated_msr = vmx_has_emulated_msr, > + .has_emulated_msr = vt_has_emulated_msr, > > .is_vm_type_supported = vt_is_vm_type_supported, > .vm_size = sizeof(struct kvm_vmx), > @@ -411,8 +439,8 @@ struct kvm_x86_ops vt_x86_ops __initdata = { > > .update_exception_bitmap = vmx_update_exception_bitmap, > .get_msr_feature = vmx_get_msr_feature, > - .get_msr = vmx_get_msr, > - .set_msr = vmx_set_msr, > + .get_msr = vt_get_msr, > + .set_msr = vt_set_msr, > .get_segment_base = vmx_get_segment_base, > .get_segment = vmx_get_segment, > .set_segment = vmx_set_segment, > diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c > index 914af5da4805..cec2660206bd 100644 > --- a/arch/x86/kvm/vmx/tdx.c > +++ b/arch/x86/kvm/vmx/tdx.c > @@ -1517,6 +1517,74 @@ void tdx_get_exit_info(struct kvm_vcpu *vcpu, u32 *reason, > *error_code = 0; > } > > +bool tdx_is_emulated_msr(u32 index, bool write) > +{ > + switch (index) { > + case MSR_IA32_UCODE_REV: > + case MSR_IA32_ARCH_CAPABILITIES: > + case MSR_IA32_POWER_CTL: > + case MSR_MTRRcap: > + case 0x200 ... 0x26f: > + /* IA32_MTRR_PHYS{BASE, MASK}, IA32_MTRR_FIX*_* */ > + case MSR_IA32_CR_PAT: > + case MSR_MTRRdefType: > + case MSR_IA32_TSC_DEADLINE: > + case MSR_IA32_MISC_ENABLE: > + case MSR_KVM_STEAL_TIME: > + case MSR_KVM_POLL_CONTROL: > + case MSR_PLATFORM_INFO: > + case MSR_MISC_FEATURES_ENABLES: > + case MSR_IA32_MCG_CAP: > + case MSR_IA32_MCG_STATUS: > + case MSR_IA32_MCG_CTL: > + case MSR_IA32_MCG_EXT_CTL: > + case MSR_IA32_MC0_CTL ... MSR_IA32_MCx_MISC(28) - 1: > + /* MSR_IA32_MCx_{CTL, STATUS, ADDR, MISC} */ > + return true; > + case APIC_BASE_MSR ... APIC_BASE_MSR + 0xff: > + /* > + * x2APIC registers that are virtualized by the CPU can't be > + * emulated, KVM doesn't have access to the virtual APIC page. > + */ > + switch (index) { > + case X2APIC_MSR(APIC_TASKPRI): > + case X2APIC_MSR(APIC_PROCPRI): > + case X2APIC_MSR(APIC_EOI): > + case X2APIC_MSR(APIC_ISR) ... X2APIC_MSR(APIC_ISR + APIC_ISR_NR): > + case X2APIC_MSR(APIC_TMR) ... X2APIC_MSR(APIC_TMR + APIC_ISR_NR): > + case X2APIC_MSR(APIC_IRR) ... X2APIC_MSR(APIC_IRR + APIC_ISR_NR): > + return false; > + default: > + return true; > + } > + case MSR_IA32_APICBASE: > + case MSR_EFER: > + return !write; > + case MSR_IA32_MCx_CTL2(0) ... MSR_IA32_MCx_CTL2(31): > + /* > + * 0x280 - 0x29f: The x86 common code doesn't emulate MCx_CTL2. > + * Refer to kvm_{get,set}_msr_common(), > + * kvm_mtrr_{get, set}_msr(), and msr_mtrr_valid(). > + */ > + default: > + return false; > + } > +} > + > +int tdx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) > +{ > + if (tdx_is_emulated_msr(msr->index, false)) > + return kvm_get_msr_common(vcpu, msr); > + return 1; > +} > + > +int tdx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) > +{ > + if (tdx_is_emulated_msr(msr->index, true)) > + return kvm_set_msr_common(vcpu, msr); > + return 1; > +} > + > static int tdx_capabilities(struct kvm *kvm, struct kvm_tdx_cmd *cmd) > { > struct kvm_tdx_capabilities __user *user_caps; > diff --git a/arch/x86/kvm/vmx/x86_ops.h b/arch/x86/kvm/vmx/x86_ops.h > index c0a34186bc37..dcaa5806802e 100644 > --- a/arch/x86/kvm/vmx/x86_ops.h > +++ b/arch/x86/kvm/vmx/x86_ops.h > @@ -156,6 +156,9 @@ void tdx_deliver_interrupt(struct kvm_lapic *apic, int delivery_mode, > void tdx_inject_nmi(struct kvm_vcpu *vcpu); > void tdx_get_exit_info(struct kvm_vcpu *vcpu, u32 *reason, > u64 *info1, u64 *info2, u32 *intr_info, u32 *error_code); > +bool tdx_is_emulated_msr(u32 index, bool write); > +int tdx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr); > +int tdx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr); > > int tdx_vm_ioctl(struct kvm *kvm, void __user *argp); > int tdx_vcpu_ioctl(struct kvm_vcpu *vcpu, void __user *argp); > @@ -193,6 +196,9 @@ static inline void tdx_inject_nmi(struct kvm_vcpu *vcpu) {} > static inline void tdx_get_exit_info( > struct kvm_vcpu *vcpu, u32 *reason, u64 *info1, u64 *info2, > u32 *intr_info, u32 *error_code) {} > +static inline bool tdx_is_emulated_msr(u32 index, bool write) { return false; } > +static inline int tdx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) { return 1; } > +static inline int tdx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr) { return 1; } > > static inline int tdx_vm_ioctl(struct kvm *kvm, void __user *argp) { return -EOPNOTSUPP; } > static inline int tdx_vcpu_ioctl(struct kvm_vcpu *vcpu, void __user *argp) { return -EOPNOTSUPP; }
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
|