Received: by 2002:a05:6a10:a852:0:0:0:0 with SMTP id d18csp3872188pxy; Tue, 4 May 2021 11:48:14 -0700 (PDT) X-Google-Smtp-Source: ABdhPJw6kt2EmiBErJ31mbtiP7w6B3CbTA9rR1AE2HfJQoNmOBnFRh3iRmENSnuFZiPvKzSqrFmf X-Received: by 2002:aa7:cb84:: with SMTP id r4mr3445195edt.187.1620154094418; Tue, 04 May 2021 11:48:14 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1620154094; cv=none; d=google.com; s=arc-20160816; b=OpWuLQzUa2URul0cSfdlQqkBYZy27tlkML6zUcg1+MG2fSWgSgCxMMdl5e3804WsLM Cs700q6zZSLkCRvV8OMbSGRE0XJf8s8zGojoB39+0qQ1JmpTO+3F7qQEM0FUEftoXMg2 ji0mMqOkdz8S8cRdKQfpXlDS3gGN7+SpQzJgD0U+t5fddvbmYiJE9JC4ZQb6PrrRU29t 1Uu7GKDvrCUsph0tFBeMtEKulXFCCTgIMA9+ecBLgAQZHIhX+5YENo4WDcaQU5E7Q0p7 FNbyaNRKMtnaiCuSOz/YJRkmqod2G0P9Oj49N9h9VCo9BgsXxZ9GF9zTyGZj9H6FyMoy 2WxQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:cc:to:from:subject:references:mime-version :message-id:in-reply-to:date:reply-to:dkim-signature; bh=BuFmFez9jUwRrnImsJ+azB1vrZijd6DUJ5M+cWbALfs=; b=HPQKKXVKUalvWa2RQh4fz7hwhjHV+mQTqdkgv2+h2gXMUvLVKctIJ1K7CpR0rOt5G5 QDY/wZZHQ7D9erqc3elF1ZKizcR8/Uhsjze9QmdIBRjRyG6B9iF2lRNEDbq8ZEF9GLil vu1LZbKsf2PC8D2PEK/Xl7C2Bw7u713OqF0e8ip95PaOqVz0+fXQaPKdxepgXyG0dPJP kIAp1BQ5xroa3yr11UKfR0T6XLyJNMxxsVT0/ZJ0+y934JR9+QG80MVgMhQOrBk6EUC2 07nxethND48NxmHMQkjmyZ+juyGAwK7V23Oiz8BRMrI345IAg7JQKRv3be1rWXaGyDJO xcWQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=PIfalVHC; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id zg9si3850261ejb.436.2021.05.04.11.47.50; Tue, 04 May 2021 11:48:14 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@google.com header.s=20161025 header.b=PIfalVHC; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=REJECT sp=REJECT dis=NONE) header.from=google.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232141AbhEDRTM (ORCPT + 99 others); Tue, 4 May 2021 13:19:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39660 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232183AbhEDRS5 (ORCPT ); Tue, 4 May 2021 13:18:57 -0400 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6BF60C06138C for ; Tue, 4 May 2021 10:18:02 -0700 (PDT) Received: by mail-yb1-xb49.google.com with SMTP id i201-20020a25d1d20000b02904ed4c01f82bso12702935ybg.20 for ; Tue, 04 May 2021 10:18:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=reply-to:date:in-reply-to:message-id:mime-version:references :subject:from:to:cc; bh=BuFmFez9jUwRrnImsJ+azB1vrZijd6DUJ5M+cWbALfs=; b=PIfalVHC3CmdnOo5mB3aYhbwxb1wXrQpggHTflDbp6Uh83tVVd+KOzlWt1oSBY493K 9FnzGeEcc9Y9Ro58Pc567FMkCbJYMGyMy0Z7EYWWrenzyg5qKNzMevOGakrh7kFzJEXx 9pCf8KAH845t6dr/gtKuc7T5Ct6jH6xiu/BEhzgd2wOPw6acO9Chl0Mw+ZElTupOYZmm pBccjs7Knx/aXfVGK2S1pYOL+rSYV0xi1jndG2/aSrRJ6mWrkPwsGxRxL8Vi/6hJhg0R l7wFb1vxrSi5NtojsrOULz6I4wCiWaIAImJA+yclYjN5OFuBIo+QSVYozmmVXrB5TroK E+BA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:reply-to:date:in-reply-to:message-id :mime-version:references:subject:from:to:cc; bh=BuFmFez9jUwRrnImsJ+azB1vrZijd6DUJ5M+cWbALfs=; b=Pvf/iAPX7eqqYARL6C3mXk56bEEGPqVtkSxqHVtdPSoreq9In6nqEjua2MHxo3Rmdu 9FWuMkzCYC8+pmEqsa/m4fS4aFyar71UlFcRmLXDnmkH6FQsleY3oj56nc0AsCqA4IDF s8kC2mZ227WBjCZZrmk2Wxtimt13mzt9kpeg3thPJJyD7Ge3ghDPtzv9+ENLOrA2GuzS jVv3vWL+N0whlG0m742wrUraSQl8i5N6G3wLvqrb3k8zLEp0/nlRmATRIN8c21rHfdkZ vHQlCOtvvfFBQEplDgCm+HLgwzskeKB9mEOoCKc0l41+rqkzr6lIQmU3SvILDaI7m74a tO+A== X-Gm-Message-State: AOAM530vVLjRDV8GsSOiBKhSgz46kipBzL0FTKUhxyBQbvLNTgHQBFOc Yp05ycfQXlq9JXC5Q3oepMzC4exD4GM= X-Received: from seanjc798194.pdx.corp.google.com ([2620:15c:f:10:df57:48cb:ea33:a156]) (user=seanjc job=sendgmr) by 2002:a5b:802:: with SMTP id x2mr35901294ybp.28.1620148681694; Tue, 04 May 2021 10:18:01 -0700 (PDT) Reply-To: Sean Christopherson Date: Tue, 4 May 2021 10:17:27 -0700 In-Reply-To: <20210504171734.1434054-1-seanjc@google.com> Message-Id: <20210504171734.1434054-9-seanjc@google.com> Mime-Version: 1.0 References: <20210504171734.1434054-1-seanjc@google.com> X-Mailer: git-send-email 2.31.1.527.g47e6f16901-goog Subject: [PATCH 08/15] KVM: VMX: Configure list of user return MSRs at module init From: Sean Christopherson To: Paolo Bonzini Cc: Sean Christopherson , Vitaly Kuznetsov , Wanpeng Li , Jim Mattson , Joerg Roedel , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Xiaoyao Li , Reiji Watanabe Content-Type: text/plain; charset="UTF-8" Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Configure the list of user return MSRs that are actually supported at module init instead of reprobing the list of possible MSRs every time a vCPU is created. Curating the list on a per-vCPU basis is pointless; KVM is completely hosed if the set of supported MSRs changes after module init, or if the set of MSRs differs per physical PCU. The per-vCPU lists also increase complexity (see __vmx_find_uret_msr()) and creates corner cases that _should_ be impossible, but theoretically exist in KVM, e.g. advertising RDTSCP to userspace without actually being able to virtualize RDTSCP if probing MSR_TSC_AUX fails. Signed-off-by: Sean Christopherson --- arch/x86/kvm/vmx/vmx.c | 61 ++++++++++++++++++++++++++++-------------- arch/x86/kvm/vmx/vmx.h | 10 ++++++- 2 files changed, 50 insertions(+), 21 deletions(-) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 42e4bbaa299a..68454b0de2b1 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -461,7 +461,7 @@ static unsigned long host_idt_base; * support this emulation, IA32_STAR must always be included in * vmx_uret_msrs_list[], even in i386 builds. */ -static const u32 vmx_uret_msrs_list[] = { +static u32 vmx_uret_msrs_list[] = { #ifdef CONFIG_X86_64 MSR_SYSCALL_MASK, MSR_LSTAR, MSR_CSTAR, #endif @@ -469,6 +469,12 @@ static const u32 vmx_uret_msrs_list[] = { MSR_IA32_TSX_CTRL, }; +/* + * Number of user return MSRs that are actually supported in hardware. + * vmx_uret_msrs_list is modified when KVM is loaded to drop unsupported MSRs. + */ +static int vmx_nr_uret_msrs; + #if IS_ENABLED(CONFIG_HYPERV) static bool __read_mostly enlightened_vmcs = true; module_param(enlightened_vmcs, bool, 0444); @@ -700,9 +706,16 @@ static inline int __vmx_find_uret_msr(struct vcpu_vmx *vmx, u32 msr) { int i; - for (i = 0; i < vmx->nr_uret_msrs; ++i) + /* + * Note, vmx->guest_uret_msrs is the same size as vmx_uret_msrs_list, + * but is ordered differently. The MSR is matched against the list of + * supported uret MSRs using "slot", but the index that is returned is + * the index into guest_uret_msrs. + */ + for (i = 0; i < vmx_nr_uret_msrs; ++i) { if (vmx_uret_msrs_list[vmx->guest_uret_msrs[i].slot] == msr) return i; + } return -1; } @@ -6929,18 +6942,10 @@ static int vmx_create_vcpu(struct kvm_vcpu *vcpu) goto free_vpid; } - BUILD_BUG_ON(ARRAY_SIZE(vmx_uret_msrs_list) != MAX_NR_USER_RETURN_MSRS); + for (i = 0; i < vmx_nr_uret_msrs; ++i) { + vmx->guest_uret_msrs[i].data = 0; - for (i = 0; i < ARRAY_SIZE(vmx_uret_msrs_list); ++i) { - u32 index = vmx_uret_msrs_list[i]; - int j = vmx->nr_uret_msrs; - - if (kvm_probe_user_return_msr(index)) - continue; - - vmx->guest_uret_msrs[j].slot = i; - vmx->guest_uret_msrs[j].data = 0; - switch (index) { + switch (vmx_uret_msrs_list[i]) { case MSR_IA32_TSX_CTRL: /* * TSX_CTRL_CPUID_CLEAR is handled in the CPUID @@ -6954,15 +6959,14 @@ static int vmx_create_vcpu(struct kvm_vcpu *vcpu) * host so that TSX remains always disabled. */ if (boot_cpu_has(X86_FEATURE_RTM)) - vmx->guest_uret_msrs[j].mask = ~(u64)TSX_CTRL_CPUID_CLEAR; + vmx->guest_uret_msrs[i].mask = ~(u64)TSX_CTRL_CPUID_CLEAR; else - vmx->guest_uret_msrs[j].mask = 0; + vmx->guest_uret_msrs[i].mask = 0; break; default: - vmx->guest_uret_msrs[j].mask = -1ull; + vmx->guest_uret_msrs[i].mask = -1ull; break; } - ++vmx->nr_uret_msrs; } err = alloc_loaded_vmcs(&vmx->vmcs01); @@ -7821,17 +7825,34 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = { .vcpu_deliver_sipi_vector = kvm_vcpu_deliver_sipi_vector, }; +static __init void vmx_setup_user_return_msrs(void) +{ + u32 msr; + int i; + + BUILD_BUG_ON(ARRAY_SIZE(vmx_uret_msrs_list) != MAX_NR_USER_RETURN_MSRS); + + for (i = 0; i < ARRAY_SIZE(vmx_uret_msrs_list); ++i) { + msr = vmx_uret_msrs_list[i]; + + if (kvm_probe_user_return_msr(msr)) + continue; + + kvm_define_user_return_msr(vmx_nr_uret_msrs, msr); + vmx_uret_msrs_list[vmx_nr_uret_msrs++] = msr; + } +} + static __init int hardware_setup(void) { unsigned long host_bndcfgs; struct desc_ptr dt; - int r, i, ept_lpage_level; + int r, ept_lpage_level; store_idt(&dt); host_idt_base = dt.address; - for (i = 0; i < ARRAY_SIZE(vmx_uret_msrs_list); ++i) - kvm_define_user_return_msr(i, vmx_uret_msrs_list[i]); + vmx_setup_user_return_msrs(); if (setup_vmcs_config(&vmcs_config, &vmx_capability) < 0) return -EIO; diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h index 008cb87ff088..d71ed8b425c5 100644 --- a/arch/x86/kvm/vmx/vmx.h +++ b/arch/x86/kvm/vmx/vmx.h @@ -245,8 +245,16 @@ struct vcpu_vmx { u32 idt_vectoring_info; ulong rflags; + /* + * User return MSRs are always emulated when enabled in the guest, but + * only loaded into hardware when necessary, e.g. SYSCALL #UDs outside + * of 64-bit mode or if EFER.SCE=1, thus the SYSCALL MSRs don't need to + * be loaded into hardware if those conditions aren't met. + * nr_active_uret_msrs tracks the number of MSRs that need to be loaded + * into hardware when running the guest. guest_uret_msrs[] is resorted + * whenever the number of "active" uret MSRs is modified. + */ struct vmx_uret_msr guest_uret_msrs[MAX_NR_USER_RETURN_MSRS]; - int nr_uret_msrs; int nr_active_uret_msrs; bool guest_uret_msrs_loaded; #ifdef CONFIG_X86_64 -- 2.31.1.527.g47e6f16901-goog