lkml.org 
[lkml]   [2022]   [Oct]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
SubjectRe: [PATCH v2 2/8] KVM: x86: move SMM entry to a new file
From
Date
On Thu, 2022-09-29 at 13:20 -0400, Paolo Bonzini wrote:
> Some users of KVM implement the UEFI variable store through a paravirtual
> device that does not require the "SMM lockbox" component of edk2, and
> would like to compile out system management mode. In preparation for
> that, move the SMM entry code out of x86.c and into a new file.
>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
> arch/x86/include/asm/kvm_host.h | 1 +
> arch/x86/kvm/smm.c | 235 +++++++++++++++++++++++++++++++
> arch/x86/kvm/smm.h | 1 +
> arch/x86/kvm/x86.c | 239 +-------------------------------
> 4 files changed, 239 insertions(+), 237 deletions(-)
>
> diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
> index 0ca8f28854ab..b7d078cd768d 100644
> --- a/arch/x86/include/asm/kvm_host.h
> +++ b/arch/x86/include/asm/kvm_host.h
> @@ -1838,6 +1838,7 @@ int kvm_emulate_ap_reset_hold(struct kvm_vcpu *vcpu);
> int kvm_emulate_wbinvd(struct kvm_vcpu *vcpu);
>
> void kvm_get_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg);
> +void kvm_set_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg);
> int kvm_load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, int seg);
> void kvm_vcpu_deliver_sipi_vector(struct kvm_vcpu *vcpu, u8 vector);
>
> diff --git a/arch/x86/kvm/smm.c b/arch/x86/kvm/smm.c
> index b91c48d91f6e..26a6859e421f 100644
> --- a/arch/x86/kvm/smm.c
> +++ b/arch/x86/kvm/smm.c
> @@ -5,6 +5,7 @@
> #include "kvm_cache_regs.h"
> #include "kvm_emulate.h"
> #include "smm.h"
> +#include "cpuid.h"
> #include "trace.h"
>
> void kvm_smm_changed(struct kvm_vcpu *vcpu, bool entering_smm)
> @@ -35,3 +36,237 @@ void process_smi(struct kvm_vcpu *vcpu)
> vcpu->arch.smi_pending = true;
> kvm_make_request(KVM_REQ_EVENT, vcpu);
> }
> +
> +static u32 enter_smm_get_segment_flags(struct kvm_segment *seg)
> +{
> + u32 flags = 0;
> + flags |= seg->g << 23;
> + flags |= seg->db << 22;
> + flags |= seg->l << 21;
> + flags |= seg->avl << 20;
> + flags |= seg->present << 15;
> + flags |= seg->dpl << 13;
> + flags |= seg->s << 12;
> + flags |= seg->type << 8;
> + return flags;
> +}
> +
> +static void enter_smm_save_seg_32(struct kvm_vcpu *vcpu, char *buf, int n)
> +{
> + struct kvm_segment seg;
> + int offset;
> +
> + kvm_get_segment(vcpu, &seg, n);
> + PUT_SMSTATE(u32, buf, 0x7fa8 + n * 4, seg.selector);
> +
> + if (n < 3)
> + offset = 0x7f84 + n * 12;
> + else
> + offset = 0x7f2c + (n - 3) * 12;
> +
> + PUT_SMSTATE(u32, buf, offset + 8, seg.base);
> + PUT_SMSTATE(u32, buf, offset + 4, seg.limit);
> + PUT_SMSTATE(u32, buf, offset, enter_smm_get_segment_flags(&seg));
> +}
> +
> +#ifdef CONFIG_X86_64
> +static void enter_smm_save_seg_64(struct kvm_vcpu *vcpu, char *buf, int n)
> +{
> + struct kvm_segment seg;
> + int offset;
> + u16 flags;
> +
> + kvm_get_segment(vcpu, &seg, n);
> + offset = 0x7e00 + n * 16;
> +
> + flags = enter_smm_get_segment_flags(&seg) >> 8;
> + PUT_SMSTATE(u16, buf, offset, seg.selector);
> + PUT_SMSTATE(u16, buf, offset + 2, flags);
> + PUT_SMSTATE(u32, buf, offset + 4, seg.limit);
> + PUT_SMSTATE(u64, buf, offset + 8, seg.base);
> +}
> +#endif
> +
> +static void enter_smm_save_state_32(struct kvm_vcpu *vcpu, char *buf)
> +{
> + struct desc_ptr dt;
> + struct kvm_segment seg;
> + unsigned long val;
> + int i;
> +
> + PUT_SMSTATE(u32, buf, 0x7ffc, kvm_read_cr0(vcpu));
> + PUT_SMSTATE(u32, buf, 0x7ff8, kvm_read_cr3(vcpu));
> + PUT_SMSTATE(u32, buf, 0x7ff4, kvm_get_rflags(vcpu));
> + PUT_SMSTATE(u32, buf, 0x7ff0, kvm_rip_read(vcpu));
> +
> + for (i = 0; i < 8; i++)
> + PUT_SMSTATE(u32, buf, 0x7fd0 + i * 4, kvm_register_read_raw(vcpu, i));
> +
> + kvm_get_dr(vcpu, 6, &val);
> + PUT_SMSTATE(u32, buf, 0x7fcc, (u32)val);
> + kvm_get_dr(vcpu, 7, &val);
> + PUT_SMSTATE(u32, buf, 0x7fc8, (u32)val);
> +
> + kvm_get_segment(vcpu, &seg, VCPU_SREG_TR);
> + PUT_SMSTATE(u32, buf, 0x7fc4, seg.selector);
> + PUT_SMSTATE(u32, buf, 0x7f64, seg.base);
> + PUT_SMSTATE(u32, buf, 0x7f60, seg.limit);
> + PUT_SMSTATE(u32, buf, 0x7f5c, enter_smm_get_segment_flags(&seg));
> +
> + kvm_get_segment(vcpu, &seg, VCPU_SREG_LDTR);
> + PUT_SMSTATE(u32, buf, 0x7fc0, seg.selector);
> + PUT_SMSTATE(u32, buf, 0x7f80, seg.base);
> + PUT_SMSTATE(u32, buf, 0x7f7c, seg.limit);
> + PUT_SMSTATE(u32, buf, 0x7f78, enter_smm_get_segment_flags(&seg));
> +
> + static_call(kvm_x86_get_gdt)(vcpu, &dt);
> + PUT_SMSTATE(u32, buf, 0x7f74, dt.address);
> + PUT_SMSTATE(u32, buf, 0x7f70, dt.size);
> +
> + static_call(kvm_x86_get_idt)(vcpu, &dt);
> + PUT_SMSTATE(u32, buf, 0x7f58, dt.address);
> + PUT_SMSTATE(u32, buf, 0x7f54, dt.size);
> +
> + for (i = 0; i < 6; i++)
> + enter_smm_save_seg_32(vcpu, buf, i);
> +
> + PUT_SMSTATE(u32, buf, 0x7f14, kvm_read_cr4(vcpu));
> +
> + /* revision id */
> + PUT_SMSTATE(u32, buf, 0x7efc, 0x00020000);
> + PUT_SMSTATE(u32, buf, 0x7ef8, vcpu->arch.smbase);
> +}
> +
> +#ifdef CONFIG_X86_64
> +static void enter_smm_save_state_64(struct kvm_vcpu *vcpu, char *buf)
> +{
> + struct desc_ptr dt;
> + struct kvm_segment seg;
> + unsigned long val;
> + int i;
> +
> + for (i = 0; i < 16; i++)
> + PUT_SMSTATE(u64, buf, 0x7ff8 - i * 8, kvm_register_read_raw(vcpu, i));
> +
> + PUT_SMSTATE(u64, buf, 0x7f78, kvm_rip_read(vcpu));
> + PUT_SMSTATE(u32, buf, 0x7f70, kvm_get_rflags(vcpu));
> +
> + kvm_get_dr(vcpu, 6, &val);
> + PUT_SMSTATE(u64, buf, 0x7f68, val);
> + kvm_get_dr(vcpu, 7, &val);
> + PUT_SMSTATE(u64, buf, 0x7f60, val);
> +
> + PUT_SMSTATE(u64, buf, 0x7f58, kvm_read_cr0(vcpu));
> + PUT_SMSTATE(u64, buf, 0x7f50, kvm_read_cr3(vcpu));
> + PUT_SMSTATE(u64, buf, 0x7f48, kvm_read_cr4(vcpu));
> +
> + PUT_SMSTATE(u32, buf, 0x7f00, vcpu->arch.smbase);
> +
> + /* revision id */
> + PUT_SMSTATE(u32, buf, 0x7efc, 0x00020064);
> +
> + PUT_SMSTATE(u64, buf, 0x7ed0, vcpu->arch.efer);
> +
> + kvm_get_segment(vcpu, &seg, VCPU_SREG_TR);
> + PUT_SMSTATE(u16, buf, 0x7e90, seg.selector);
> + PUT_SMSTATE(u16, buf, 0x7e92, enter_smm_get_segment_flags(&seg) >> 8);
> + PUT_SMSTATE(u32, buf, 0x7e94, seg.limit);
> + PUT_SMSTATE(u64, buf, 0x7e98, seg.base);
> +
> + static_call(kvm_x86_get_idt)(vcpu, &dt);
> + PUT_SMSTATE(u32, buf, 0x7e84, dt.size);
> + PUT_SMSTATE(u64, buf, 0x7e88, dt.address);
> +
> + kvm_get_segment(vcpu, &seg, VCPU_SREG_LDTR);
> + PUT_SMSTATE(u16, buf, 0x7e70, seg.selector);
> + PUT_SMSTATE(u16, buf, 0x7e72, enter_smm_get_segment_flags(&seg) >> 8);
> + PUT_SMSTATE(u32, buf, 0x7e74, seg.limit);
> + PUT_SMSTATE(u64, buf, 0x7e78, seg.base);
> +
> + static_call(kvm_x86_get_gdt)(vcpu, &dt);
> + PUT_SMSTATE(u32, buf, 0x7e64, dt.size);
> + PUT_SMSTATE(u64, buf, 0x7e68, dt.address);
> +
> + for (i = 0; i < 6; i++)
> + enter_smm_save_seg_64(vcpu, buf, i);
> +}
> +#endif
> +
> +void enter_smm(struct kvm_vcpu *vcpu)
> +{
> + struct kvm_segment cs, ds;
> + struct desc_ptr dt;
> + unsigned long cr0;
> + char buf[512];
> +
> + memset(buf, 0, 512);
> +#ifdef CONFIG_X86_64
> + if (guest_cpuid_has(vcpu, X86_FEATURE_LM))
> + enter_smm_save_state_64(vcpu, buf);
> + else
> +#endif
> + enter_smm_save_state_32(vcpu, buf);
> +
> + /*
> + * Give enter_smm() a chance to make ISA-specific changes to the vCPU
> + * state (e.g. leave guest mode) after we've saved the state into the
> + * SMM state-save area.
> + */
> + static_call(kvm_x86_enter_smm)(vcpu, buf);
> +
> + kvm_smm_changed(vcpu, true);
> + kvm_vcpu_write_guest(vcpu, vcpu->arch.smbase + 0xfe00, buf, sizeof(buf));
> +
> + if (static_call(kvm_x86_get_nmi_mask)(vcpu))
> + vcpu->arch.hflags |= HF_SMM_INSIDE_NMI_MASK;
> + else
> + static_call(kvm_x86_set_nmi_mask)(vcpu, true);
> +
> + kvm_set_rflags(vcpu, X86_EFLAGS_FIXED);
> + kvm_rip_write(vcpu, 0x8000);
> +
> + cr0 = vcpu->arch.cr0 & ~(X86_CR0_PE | X86_CR0_EM | X86_CR0_TS | X86_CR0_PG);
> + static_call(kvm_x86_set_cr0)(vcpu, cr0);
> + vcpu->arch.cr0 = cr0;
> +
> + static_call(kvm_x86_set_cr4)(vcpu, 0);
> +
> + /* Undocumented: IDT limit is set to zero on entry to SMM. */
> + dt.address = dt.size = 0;
> + static_call(kvm_x86_set_idt)(vcpu, &dt);
> +
> + kvm_set_dr(vcpu, 7, DR7_FIXED_1);
> +
> + cs.selector = (vcpu->arch.smbase >> 4) & 0xffff;
> + cs.base = vcpu->arch.smbase;
> +
> + ds.selector = 0;
> + ds.base = 0;
> +
> + cs.limit = ds.limit = 0xffffffff;
> + cs.type = ds.type = 0x3;
> + cs.dpl = ds.dpl = 0;
> + cs.db = ds.db = 0;
> + cs.s = ds.s = 1;
> + cs.l = ds.l = 0;
> + cs.g = ds.g = 1;
> + cs.avl = ds.avl = 0;
> + cs.present = ds.present = 1;
> + cs.unusable = ds.unusable = 0;
> + cs.padding = ds.padding = 0;
> +
> + kvm_set_segment(vcpu, &cs, VCPU_SREG_CS);
> + kvm_set_segment(vcpu, &ds, VCPU_SREG_DS);
> + kvm_set_segment(vcpu, &ds, VCPU_SREG_ES);
> + kvm_set_segment(vcpu, &ds, VCPU_SREG_FS);
> + kvm_set_segment(vcpu, &ds, VCPU_SREG_GS);
> + kvm_set_segment(vcpu, &ds, VCPU_SREG_SS);
> +
> +#ifdef CONFIG_X86_64
> + if (guest_cpuid_has(vcpu, X86_FEATURE_LM))
> + static_call(kvm_x86_set_efer)(vcpu, 0);
> +#endif
> +
> + kvm_update_cpuid_runtime(vcpu);
> + kvm_mmu_reset_context(vcpu);
> +}
> diff --git a/arch/x86/kvm/smm.h b/arch/x86/kvm/smm.h
> index d85d4ccd32dd..aacc6dac2c99 100644
> --- a/arch/x86/kvm/smm.h
> +++ b/arch/x86/kvm/smm.h
> @@ -20,6 +20,7 @@ static inline bool is_smm(struct kvm_vcpu *vcpu)
> }
>
> void kvm_smm_changed(struct kvm_vcpu *vcpu, bool in_smm);
> +void enter_smm(struct kvm_vcpu *vcpu);
> void process_smi(struct kvm_vcpu *vcpu);
>
> #endif
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index e0e461958c81..476b4a6e81ab 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -120,7 +120,6 @@ static u64 __read_mostly cr4_reserved_bits = CR4_RESERVED_BITS;
>
> static void update_cr8_intercept(struct kvm_vcpu *vcpu);
> static void process_nmi(struct kvm_vcpu *vcpu);
> -static void enter_smm(struct kvm_vcpu *vcpu);
> static void __kvm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags);
> static void store_regs(struct kvm_vcpu *vcpu);
> static int sync_regs(struct kvm_vcpu *vcpu);
> @@ -7043,8 +7042,8 @@ static int vcpu_mmio_read(struct kvm_vcpu *vcpu, gpa_t addr, int len, void *v)
> return handled;
> }
>
> -static void kvm_set_segment(struct kvm_vcpu *vcpu,
> - struct kvm_segment *var, int seg)
> +void kvm_set_segment(struct kvm_vcpu *vcpu,
> + struct kvm_segment *var, int seg)
> {
> static_call(kvm_x86_set_segment)(vcpu, var, seg);
> }
> @@ -9968,240 +9967,6 @@ static void process_nmi(struct kvm_vcpu *vcpu)
> kvm_make_request(KVM_REQ_EVENT, vcpu);
> }
>
> -static u32 enter_smm_get_segment_flags(struct kvm_segment *seg)
> -{
> - u32 flags = 0;
> - flags |= seg->g << 23;
> - flags |= seg->db << 22;
> - flags |= seg->l << 21;
> - flags |= seg->avl << 20;
> - flags |= seg->present << 15;
> - flags |= seg->dpl << 13;
> - flags |= seg->s << 12;
> - flags |= seg->type << 8;
> - return flags;
> -}
> -
> -static void enter_smm_save_seg_32(struct kvm_vcpu *vcpu, char *buf, int n)
> -{
> - struct kvm_segment seg;
> - int offset;
> -
> - kvm_get_segment(vcpu, &seg, n);
> - PUT_SMSTATE(u32, buf, 0x7fa8 + n * 4, seg.selector);
> -
> - if (n < 3)
> - offset = 0x7f84 + n * 12;
> - else
> - offset = 0x7f2c + (n - 3) * 12;
> -
> - PUT_SMSTATE(u32, buf, offset + 8, seg.base);
> - PUT_SMSTATE(u32, buf, offset + 4, seg.limit);
> - PUT_SMSTATE(u32, buf, offset, enter_smm_get_segment_flags(&seg));
> -}
> -
> -#ifdef CONFIG_X86_64
> -static void enter_smm_save_seg_64(struct kvm_vcpu *vcpu, char *buf, int n)
> -{
> - struct kvm_segment seg;
> - int offset;
> - u16 flags;
> -
> - kvm_get_segment(vcpu, &seg, n);
> - offset = 0x7e00 + n * 16;
> -
> - flags = enter_smm_get_segment_flags(&seg) >> 8;
> - PUT_SMSTATE(u16, buf, offset, seg.selector);
> - PUT_SMSTATE(u16, buf, offset + 2, flags);
> - PUT_SMSTATE(u32, buf, offset + 4, seg.limit);
> - PUT_SMSTATE(u64, buf, offset + 8, seg.base);
> -}
> -#endif
> -
> -static void enter_smm_save_state_32(struct kvm_vcpu *vcpu, char *buf)
> -{
> - struct desc_ptr dt;
> - struct kvm_segment seg;
> - unsigned long val;
> - int i;
> -
> - PUT_SMSTATE(u32, buf, 0x7ffc, kvm_read_cr0(vcpu));
> - PUT_SMSTATE(u32, buf, 0x7ff8, kvm_read_cr3(vcpu));
> - PUT_SMSTATE(u32, buf, 0x7ff4, kvm_get_rflags(vcpu));
> - PUT_SMSTATE(u32, buf, 0x7ff0, kvm_rip_read(vcpu));
> -
> - for (i = 0; i < 8; i++)
> - PUT_SMSTATE(u32, buf, 0x7fd0 + i * 4, kvm_register_read_raw(vcpu, i));
> -
> - kvm_get_dr(vcpu, 6, &val);
> - PUT_SMSTATE(u32, buf, 0x7fcc, (u32)val);
> - kvm_get_dr(vcpu, 7, &val);
> - PUT_SMSTATE(u32, buf, 0x7fc8, (u32)val);
> -
> - kvm_get_segment(vcpu, &seg, VCPU_SREG_TR);
> - PUT_SMSTATE(u32, buf, 0x7fc4, seg.selector);
> - PUT_SMSTATE(u32, buf, 0x7f64, seg.base);
> - PUT_SMSTATE(u32, buf, 0x7f60, seg.limit);
> - PUT_SMSTATE(u32, buf, 0x7f5c, enter_smm_get_segment_flags(&seg));
> -
> - kvm_get_segment(vcpu, &seg, VCPU_SREG_LDTR);
> - PUT_SMSTATE(u32, buf, 0x7fc0, seg.selector);
> - PUT_SMSTATE(u32, buf, 0x7f80, seg.base);
> - PUT_SMSTATE(u32, buf, 0x7f7c, seg.limit);
> - PUT_SMSTATE(u32, buf, 0x7f78, enter_smm_get_segment_flags(&seg));
> -
> - static_call(kvm_x86_get_gdt)(vcpu, &dt);
> - PUT_SMSTATE(u32, buf, 0x7f74, dt.address);
> - PUT_SMSTATE(u32, buf, 0x7f70, dt.size);
> -
> - static_call(kvm_x86_get_idt)(vcpu, &dt);
> - PUT_SMSTATE(u32, buf, 0x7f58, dt.address);
> - PUT_SMSTATE(u32, buf, 0x7f54, dt.size);
> -
> - for (i = 0; i < 6; i++)
> - enter_smm_save_seg_32(vcpu, buf, i);
> -
> - PUT_SMSTATE(u32, buf, 0x7f14, kvm_read_cr4(vcpu));
> -
> - /* revision id */
> - PUT_SMSTATE(u32, buf, 0x7efc, 0x00020000);
> - PUT_SMSTATE(u32, buf, 0x7ef8, vcpu->arch.smbase);
> -}
> -
> -#ifdef CONFIG_X86_64
> -static void enter_smm_save_state_64(struct kvm_vcpu *vcpu, char *buf)
> -{
> - struct desc_ptr dt;
> - struct kvm_segment seg;
> - unsigned long val;
> - int i;
> -
> - for (i = 0; i < 16; i++)
> - PUT_SMSTATE(u64, buf, 0x7ff8 - i * 8, kvm_register_read_raw(vcpu, i));
> -
> - PUT_SMSTATE(u64, buf, 0x7f78, kvm_rip_read(vcpu));
> - PUT_SMSTATE(u32, buf, 0x7f70, kvm_get_rflags(vcpu));
> -
> - kvm_get_dr(vcpu, 6, &val);
> - PUT_SMSTATE(u64, buf, 0x7f68, val);
> - kvm_get_dr(vcpu, 7, &val);
> - PUT_SMSTATE(u64, buf, 0x7f60, val);
> -
> - PUT_SMSTATE(u64, buf, 0x7f58, kvm_read_cr0(vcpu));
> - PUT_SMSTATE(u64, buf, 0x7f50, kvm_read_cr3(vcpu));
> - PUT_SMSTATE(u64, buf, 0x7f48, kvm_read_cr4(vcpu));
> -
> - PUT_SMSTATE(u32, buf, 0x7f00, vcpu->arch.smbase);
> -
> - /* revision id */
> - PUT_SMSTATE(u32, buf, 0x7efc, 0x00020064);
> -
> - PUT_SMSTATE(u64, buf, 0x7ed0, vcpu->arch.efer);
> -
> - kvm_get_segment(vcpu, &seg, VCPU_SREG_TR);
> - PUT_SMSTATE(u16, buf, 0x7e90, seg.selector);
> - PUT_SMSTATE(u16, buf, 0x7e92, enter_smm_get_segment_flags(&seg) >> 8);
> - PUT_SMSTATE(u32, buf, 0x7e94, seg.limit);
> - PUT_SMSTATE(u64, buf, 0x7e98, seg.base);
> -
> - static_call(kvm_x86_get_idt)(vcpu, &dt);
> - PUT_SMSTATE(u32, buf, 0x7e84, dt.size);
> - PUT_SMSTATE(u64, buf, 0x7e88, dt.address);
> -
> - kvm_get_segment(vcpu, &seg, VCPU_SREG_LDTR);
> - PUT_SMSTATE(u16, buf, 0x7e70, seg.selector);
> - PUT_SMSTATE(u16, buf, 0x7e72, enter_smm_get_segment_flags(&seg) >> 8);
> - PUT_SMSTATE(u32, buf, 0x7e74, seg.limit);
> - PUT_SMSTATE(u64, buf, 0x7e78, seg.base);
> -
> - static_call(kvm_x86_get_gdt)(vcpu, &dt);
> - PUT_SMSTATE(u32, buf, 0x7e64, dt.size);
> - PUT_SMSTATE(u64, buf, 0x7e68, dt.address);
> -
> - for (i = 0; i < 6; i++)
> - enter_smm_save_seg_64(vcpu, buf, i);
> -}
> -#endif
> -
> -static void enter_smm(struct kvm_vcpu *vcpu)
> -{
> - struct kvm_segment cs, ds;
> - struct desc_ptr dt;
> - unsigned long cr0;
> - char buf[512];
> -
> - memset(buf, 0, 512);
> -#ifdef CONFIG_X86_64
> - if (guest_cpuid_has(vcpu, X86_FEATURE_LM))
> - enter_smm_save_state_64(vcpu, buf);
> - else
> -#endif
> - enter_smm_save_state_32(vcpu, buf);
> -
> - /*
> - * Give enter_smm() a chance to make ISA-specific changes to the vCPU
> - * state (e.g. leave guest mode) after we've saved the state into the
> - * SMM state-save area.
> - */
> - static_call(kvm_x86_enter_smm)(vcpu, buf);
> -
> - kvm_smm_changed(vcpu, true);
> - kvm_vcpu_write_guest(vcpu, vcpu->arch.smbase + 0xfe00, buf, sizeof(buf));
> -
> - if (static_call(kvm_x86_get_nmi_mask)(vcpu))
> - vcpu->arch.hflags |= HF_SMM_INSIDE_NMI_MASK;
> - else
> - static_call(kvm_x86_set_nmi_mask)(vcpu, true);
> -
> - kvm_set_rflags(vcpu, X86_EFLAGS_FIXED);
> - kvm_rip_write(vcpu, 0x8000);
> -
> - cr0 = vcpu->arch.cr0 & ~(X86_CR0_PE | X86_CR0_EM | X86_CR0_TS | X86_CR0_PG);
> - static_call(kvm_x86_set_cr0)(vcpu, cr0);
> - vcpu->arch.cr0 = cr0;
> -
> - static_call(kvm_x86_set_cr4)(vcpu, 0);
> -
> - /* Undocumented: IDT limit is set to zero on entry to SMM. */
> - dt.address = dt.size = 0;
> - static_call(kvm_x86_set_idt)(vcpu, &dt);
> -
> - kvm_set_dr(vcpu, 7, DR7_FIXED_1);
> -
> - cs.selector = (vcpu->arch.smbase >> 4) & 0xffff;
> - cs.base = vcpu->arch.smbase;
> -
> - ds.selector = 0;
> - ds.base = 0;
> -
> - cs.limit = ds.limit = 0xffffffff;
> - cs.type = ds.type = 0x3;
> - cs.dpl = ds.dpl = 0;
> - cs.db = ds.db = 0;
> - cs.s = ds.s = 1;
> - cs.l = ds.l = 0;
> - cs.g = ds.g = 1;
> - cs.avl = ds.avl = 0;
> - cs.present = ds.present = 1;
> - cs.unusable = ds.unusable = 0;
> - cs.padding = ds.padding = 0;
> -
> - kvm_set_segment(vcpu, &cs, VCPU_SREG_CS);
> - kvm_set_segment(vcpu, &ds, VCPU_SREG_DS);
> - kvm_set_segment(vcpu, &ds, VCPU_SREG_ES);
> - kvm_set_segment(vcpu, &ds, VCPU_SREG_FS);
> - kvm_set_segment(vcpu, &ds, VCPU_SREG_GS);
> - kvm_set_segment(vcpu, &ds, VCPU_SREG_SS);
> -
> -#ifdef CONFIG_X86_64
> - if (guest_cpuid_has(vcpu, X86_FEATURE_LM))
> - static_call(kvm_x86_set_efer)(vcpu, 0);
> -#endif
> -
> - kvm_update_cpuid_runtime(vcpu);
> - kvm_mmu_reset_context(vcpu);
> -}
> -
> void kvm_make_scan_ioapic_request_mask(struct kvm *kvm,
> unsigned long *vcpu_bitmap)
> {


Looks OK to me, but I might have missed something.

Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>

Best regards,
Maxim Levitsky


\
 
 \ /
  Last update: 2022-10-25 00:57    [W:0.229 / U:0.472 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site