From patchwork Thu Mar 28 17:55:53 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sean Christopherson X-Patchwork-Id: 10875633 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id B39681708 for ; Thu, 28 Mar 2019 17:56:13 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 99CF428CC0 for ; Thu, 28 Mar 2019 17:56:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8DEAC28D17; Thu, 28 Mar 2019 17:56:13 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D231628CC7 for ; Thu, 28 Mar 2019 17:56:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727670AbfC1R4K (ORCPT ); Thu, 28 Mar 2019 13:56:10 -0400 Received: from mga09.intel.com ([134.134.136.24]:7265 "EHLO mga09.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727462AbfC1R4I (ORCPT ); Thu, 28 Mar 2019 13:56:08 -0400 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 28 Mar 2019 10:56:05 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.60,281,1549958400"; d="scan'208";a="144691208" Received: from sjchrist-coffee.jf.intel.com ([10.54.74.181]) by FMSMGA003.fm.intel.com with ESMTP; 28 Mar 2019 10:56:05 -0700 From: Sean Christopherson To: Paolo Bonzini , =?utf-8?b?UmFkaW0gS3LEjW3DocWZ?= , Joerg Roedel Cc: kvm@vger.kernel.org, Jon Doron , Jim Mattson , Liran Alon , Vitaly Kuznetsov Subject: [RFC PATCH 14/18] KVM: x86: Use kvm_set_segment() directly when leaving SMM Date: Thu, 28 Mar 2019 10:55:53 -0700 Message-Id: <20190328175557.14408-15-sean.j.christopherson@intel.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190328175557.14408-1-sean.j.christopherson@intel.com> References: <20190328175557.14408-1-sean.j.christopherson@intel.com> MIME-Version: 1.0 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Signed-off-by: Sean Christopherson --- arch/x86/kvm/x86.c | 131 ++++++++++++++++++++++++--------------------- 1 file changed, 70 insertions(+), 61 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index aa769bb36f3b..55687273d428 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -7564,22 +7564,38 @@ static void enter_smm(struct kvm_vcpu *vcpu) __val; \ }) -static void rsm_set_desc_flags(struct desc_struct *desc, u32 flags) +static void rsm_set_seg(struct kvm_vcpu *vcpu, int seg, u16 sel, u64 base, + u32 limit, u32 flags) { - desc->g = (flags >> 23) & 1; - desc->d = (flags >> 22) & 1; - desc->l = (flags >> 21) & 1; - desc->avl = (flags >> 20) & 1; - desc->p = (flags >> 15) & 1; - desc->dpl = (flags >> 13) & 3; - desc->s = (flags >> 12) & 1; - desc->type = (flags >> 8) & 15; + struct kvm_segment var; + + var.selector = sel; + var.base = base; + var.limit = limit; + var.g = (flags >> 23) & 1; + var.db = (flags >> 22) & 1; + var.l = (flags >> 21) & 1; + var.avl = (flags >> 20) & 1; + var.present = (flags >> 15) & 1; + var.dpl = (flags >> 13) & 3; + var.s = (flags >> 12) & 1; + var.type = (flags >> 8) & 15; + var.unusable = !var.present; + var.padding = 0; + if (var.g) + var.limit = (var.limit << 12) | 0xfff; + + kvm_set_segment(vcpu, &var, seg); +} + +static void rsm_set_seg_64(struct kvm_vcpu *vcpu, int seg, u16 sel, + u64 base_lo, u64 base_hi, u32 limit, u32 flags) +{ + rsm_set_seg(vcpu, seg, sel, base_lo | (base_hi << 32), limit, flags); } -static int rsm_load_seg_32(struct x86_emulate_ctxt *ctxt, u64 smbase, int n) +static int rsm_load_seg_32(struct kvm_vcpu *vcpu, u64 smbase, int n) { - struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt); - struct desc_struct desc; int offset; u16 selector; @@ -7590,30 +7606,27 @@ static int rsm_load_seg_32(struct x86_emulate_ctxt *ctxt, u64 smbase, int n) else offset = 0x7f2c + (n - 3) * 12; - set_desc_base(&desc, GET_SMSTATE(u32, smbase, offset + 8)); - set_desc_limit(&desc, GET_SMSTATE(u32, smbase, offset + 4)); - rsm_set_desc_flags(&desc, GET_SMSTATE(u32, smbase, offset)); - ctxt->ops->set_segment(ctxt, selector, &desc, 0, n); + rsm_set_seg(vcpu, n, selector, + GET_SMSTATE(u32, smbase, offset + 8), + GET_SMSTATE(u32, smbase, offset + 4), + GET_SMSTATE(u32, smbase, offset)); + return X86EMUL_CONTINUE; } -static int rsm_load_seg_64(struct x86_emulate_ctxt *ctxt, u64 smbase, int n) +static int rsm_load_seg_64(struct kvm_vcpu *vcpu, u64 smbase, int n) { - struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt); - struct desc_struct desc; int offset; - u16 selector; - u32 base3; offset = 0x7e00 + n * 16; - selector = GET_SMSTATE(u16, smbase, offset); - rsm_set_desc_flags(&desc, GET_SMSTATE(u16, smbase, offset + 2) << 8); - set_desc_limit(&desc, GET_SMSTATE(u32, smbase, offset + 4)); - set_desc_base(&desc, GET_SMSTATE(u32, smbase, offset + 8)); - base3 = GET_SMSTATE(u32, smbase, offset + 12); + rsm_set_seg_64(vcpu, n, + GET_SMSTATE(u16, smbase, offset), + GET_SMSTATE(u32, smbase, offset + 8), + GET_SMSTATE(u32, smbase, offset + 12), + GET_SMSTATE(u32, smbase, offset + 4), + GET_SMSTATE(u16, smbase, offset + 2) << 8); - ctxt->ops->set_segment(ctxt, selector, &desc, base3, n); return X86EMUL_CONTINUE; } @@ -7672,9 +7685,7 @@ static ulong *reg_write(struct x86_emulate_ctxt *ctxt, unsigned nr) static int rsm_load_state_32(struct x86_emulate_ctxt *ctxt, u64 smbase) { struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt); - struct desc_struct desc; struct desc_ptr dt; - u16 selector; u32 val, cr0, cr3, cr4; int i; @@ -7691,17 +7702,17 @@ static int rsm_load_state_32(struct x86_emulate_ctxt *ctxt, u64 smbase) val = GET_SMSTATE(u32, smbase, 0x7fc8); __kvm_set_dr(vcpu, 7, (val & DR7_VOLATILE) | DR7_FIXED_1); - selector = GET_SMSTATE(u32, smbase, 0x7fc4); - set_desc_base(&desc, GET_SMSTATE(u32, smbase, 0x7f64)); - set_desc_limit(&desc, GET_SMSTATE(u32, smbase, 0x7f60)); - rsm_set_desc_flags(&desc, GET_SMSTATE(u32, smbase, 0x7f5c)); - ctxt->ops->set_segment(ctxt, selector, &desc, 0, VCPU_SREG_TR); + rsm_set_seg(vcpu, VCPU_SREG_TR, + GET_SMSTATE(u32, smbase, 0x7fc4), + GET_SMSTATE(u32, smbase, 0x7f64), + GET_SMSTATE(u32, smbase, 0x7f60), + GET_SMSTATE(u32, smbase, 0x7f5c)); - selector = GET_SMSTATE(u32, smbase, 0x7fc0); - set_desc_base(&desc, GET_SMSTATE(u32, smbase, 0x7f80)); - set_desc_limit(&desc, GET_SMSTATE(u32, smbase, 0x7f7c)); - rsm_set_desc_flags(&desc, GET_SMSTATE(u32, smbase, 0x7f78)); - ctxt->ops->set_segment(ctxt, selector, &desc, 0, VCPU_SREG_LDTR); + rsm_set_seg(vcpu, VCPU_SREG_LDTR, + GET_SMSTATE(u32, smbase, 0x7fc0), + GET_SMSTATE(u32, smbase, 0x7f80), + GET_SMSTATE(u32, smbase, 0x7f7c), + GET_SMSTATE(u32, smbase, 0x7f78)); dt.address = GET_SMSTATE(u32, smbase, 0x7f74); dt.size = GET_SMSTATE(u32, smbase, 0x7f70); @@ -7712,7 +7723,7 @@ static int rsm_load_state_32(struct x86_emulate_ctxt *ctxt, u64 smbase) kvm_x86_ops->set_idt(vcpu, &dt); for (i = 0; i < 6; i++) { - int r = rsm_load_seg_32(ctxt, smbase, i); + int r = rsm_load_seg_32(vcpu, smbase, i); if (r != X86EMUL_CONTINUE) return r; } @@ -7727,11 +7738,8 @@ static int rsm_load_state_32(struct x86_emulate_ctxt *ctxt, u64 smbase) static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, u64 smbase) { struct kvm_vcpu *vcpu = emul_to_vcpu(ctxt); - struct desc_struct desc; struct desc_ptr dt; u64 val, cr0, cr3, cr4; - u32 base3; - u16 selector; int i, r; for (i = 0; i < 16; i++) @@ -7752,23 +7760,23 @@ static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, u64 smbase) val = GET_SMSTATE(u64, smbase, 0x7ed0); emulator_set_msr(ctxt, MSR_EFER, val & ~EFER_LMA); - selector = GET_SMSTATE(u32, smbase, 0x7e90); - rsm_set_desc_flags(&desc, GET_SMSTATE(u32, smbase, 0x7e92) << 8); - set_desc_limit(&desc, GET_SMSTATE(u32, smbase, 0x7e94)); - set_desc_base(&desc, GET_SMSTATE(u32, smbase, 0x7e98)); - base3 = GET_SMSTATE(u32, smbase, 0x7e9c); - ctxt->ops->set_segment(ctxt, selector, &desc, base3, VCPU_SREG_TR); + rsm_set_seg_64(vcpu, VCPU_SREG_TR, + GET_SMSTATE(u32, smbase, 0x7e90), + GET_SMSTATE(u32, smbase, 0x7e98), + GET_SMSTATE(u32, smbase, 0x7e9c), + GET_SMSTATE(u32, smbase, 0x7e94), + GET_SMSTATE(u32, smbase, 0x7e92) << 8); dt.size = GET_SMSTATE(u32, smbase, 0x7e84); dt.address = GET_SMSTATE(u64, smbase, 0x7e88); kvm_x86_ops->set_idt(vcpu, &dt); - selector = GET_SMSTATE(u32, smbase, 0x7e70); - rsm_set_desc_flags(&desc, GET_SMSTATE(u32, smbase, 0x7e72) << 8); - set_desc_limit(&desc, GET_SMSTATE(u32, smbase, 0x7e74)); - set_desc_base(&desc, GET_SMSTATE(u32, smbase, 0x7e78)); - base3 = GET_SMSTATE(u32, smbase, 0x7e7c); - ctxt->ops->set_segment(ctxt, selector, &desc, base3, VCPU_SREG_LDTR); + rsm_set_seg_64(vcpu, VCPU_SREG_LDTR, + GET_SMSTATE(u32, smbase, 0x7e70), + GET_SMSTATE(u32, smbase, 0x7e78), + GET_SMSTATE(u32, smbase, 0x7e7c), + GET_SMSTATE(u32, smbase, 0x7e74), + GET_SMSTATE(u32, smbase, 0x7e72) << 8); dt.size = GET_SMSTATE(u32, smbase, 0x7e64); dt.address = GET_SMSTATE(u64, smbase, 0x7e68); @@ -7779,7 +7787,7 @@ static int rsm_load_state_64(struct x86_emulate_ctxt *ctxt, u64 smbase) return r; for (i = 0; i < 6; i++) { - r = rsm_load_seg_64(ctxt, smbase, i); + r = rsm_load_seg_64(vcpu, smbase, i); if (r != X86EMUL_CONTINUE) return r; } @@ -7801,7 +7809,7 @@ static int leave_smm(struct kvm_vcpu *vcpu) */ cr4 = kvm_read_cr4(vcpu); if (guest_cpuid_has(vcpu, X86_FEATURE_LM)) { - struct desc_struct cs_desc; + struct kvm_segment cs_seg; /* Zero CR4.PCIDE before CR0.PG. */ if (cr4 & X86_CR4_PCIDE) { @@ -7810,10 +7818,11 @@ static int leave_smm(struct kvm_vcpu *vcpu) } /* A 32-bit code segment is required to clear EFER.LMA. */ - memset(&cs_desc, 0, sizeof(cs_desc)); - cs_desc.type = 0xb; - cs_desc.s = cs_desc.g = cs_desc.p = 1; - ctxt->ops->set_segment(ctxt, 0, &cs_desc, 0, VCPU_SREG_CS); + memset(&cs_seg, 0, sizeof(cs_seg)); + cs_seg.type = 0xb; + cs_seg.s = cs_seg.g = cs_seg.present = 1; + cs_seg.limit = 0xffffffff; + kvm_set_segment(vcpu, &cs_seg, VCPU_SREG_CS); } /* For the 64-bit case, this will clear EFER.LMA. */