From patchwork Wed Sep 4 12:30:39 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Beulich X-Patchwork-Id: 13790758 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3338BCD37B4 for ; Wed, 4 Sep 2024 12:37:01 +0000 (UTC) Received: from list by lists.xenproject.org with outflank-mailman.790232.1199960 (Exim 4.92) (envelope-from ) id 1slpFg-0002r9-AB; Wed, 04 Sep 2024 12:36:48 +0000 X-Outflank-Mailman: Message body and most headers restored to incoming version Received: by outflank-mailman (output) from mailman id 790232.1199960; Wed, 04 Sep 2024 12:36:48 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1slpFg-0002r2-4Q; Wed, 04 Sep 2024 12:36:48 +0000 Received: by outflank-mailman (input) for mailman id 790232; Wed, 04 Sep 2024 12:36:46 +0000 Received: from se1-gles-flk1-in.inumbo.com ([94.247.172.50] helo=se1-gles-flk1.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1slp9n-0005XG-3t for xen-devel@lists.xenproject.org; Wed, 04 Sep 2024 12:30:43 +0000 Received: from mail-lj1-x231.google.com (mail-lj1-x231.google.com [2a00:1450:4864:20::231]) by se1-gles-flk1.inumbo.com (Halon) with ESMTPS id 7f7c2990-6ab9-11ef-99a1-01e77a169b0f; Wed, 04 Sep 2024 14:30:41 +0200 (CEST) Received: by mail-lj1-x231.google.com with SMTP id 38308e7fff4ca-2f40a1a2c1aso62139981fa.3 for ; Wed, 04 Sep 2024 05:30:41 -0700 (PDT) Received: from [10.156.60.236] (ip-037-024-206-209.um08.pools.vodafone-ip.de. [37.24.206.209]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-5c226c7bf90sm7566891a12.43.2024.09.04.05.30.39 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 04 Sep 2024 05:30:40 -0700 (PDT) X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" X-Inumbo-ID: 7f7c2990-6ab9-11ef-99a1-01e77a169b0f DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=google; t=1725453041; x=1726057841; darn=lists.xenproject.org; h=content-transfer-encoding:in-reply-to:autocrypt:content-language :references:cc:to:from:subject:user-agent:mime-version:date :message-id:from:to:cc:subject:date:message-id:reply-to; bh=O5PxfaOxzCw4T0YiZOMmVYpCv4HEtsQlFWSGRt4PEms=; b=YA5+oh9DzuaahrMl3Z8wttV8MGO4XTK+7DbmvF5YDHYY7av4qlOsR7JAaeY0OLSoJZ hguM/X//QH4RobrvJAzSEhOnJ5D8CKoPaYCN7Fetld2lkwtJqYcTAQhqVOkFx/Rw4fGl 5fMSYyaeCd6eklaVDcj3cIGv2oU+5gWrtepbuBeqJ6JZZlWm1q35FxwS1F8tuTs8DYkZ +uvxiIr5u046Umk66vW2mRA0BIgJCBIZlglIb/YutooDLk0PoeFqmsnw6BiByvKwbliS e8Fdfc8nVDJQ5jc9HI1zPZpT5QFPGPUJE/B5DTOyXueq5gJigzhxq3Ji3/tpQGCYXCRE i1FQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1725453041; x=1726057841; h=content-transfer-encoding:in-reply-to:autocrypt:content-language :references:cc:to:from:subject:user-agent:mime-version:date :message-id:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=O5PxfaOxzCw4T0YiZOMmVYpCv4HEtsQlFWSGRt4PEms=; b=UpZKNFdLxQBRa4I0u0LJ/QFWLyG2cxVcyyWt3YAbpjNplbKZOlOG/uplXL5vsgeP+m uIRmPj2NWgbvrMfcm9pNki7wD564aF//h9/mqVBrHkQXAiYrdanpiSrb7kPKui3Dlzve xXEV1UO4XrKqgQtZ2Jh/ECSRiKy2PSfPQijnCyhWqvQdre9/gUZLQVj1CHYPO9S30GNi hrgJbwr+zgrjWrqZxGpT99rwV+xLmTTegycgqUWdYsas/g+b7RAhOtoSc6jlhuDfd3qA ValkfOT9dHrH73RmxopvOE/jfx5j/TFkAZYnoUEnOF5+Ls1ZHghPmZN3+vNuf0S9EPVg VeZA== X-Gm-Message-State: AOJu0YxdUoPN4fZo9aP0iUMg16Hgw5BmYShBf8c7XfvWAohhNmy/+KvB 7fre9elw1CpP17fWHpH7/2G/NvvP7b9dNVpVRJbIQeI8Oi0+O27dpA/mtB1lvydPYKNhGZsWd/E = X-Google-Smtp-Source: AGHT+IGvA7QBKwlIcUMw05ZU3GiTn9R76ek29VYfnUIjQBOnbMfPGx5MVUCI5DWTnI0n81K3nQf29g== X-Received: by 2002:a05:651c:198d:b0:2f3:e2f0:fa8 with SMTP id 38308e7fff4ca-2f61038c68amr167232971fa.9.1725453040313; Wed, 04 Sep 2024 05:30:40 -0700 (PDT) Message-ID: <6606b4a6-0b9b-449b-8026-bc228d2fcf13@suse.com> Date: Wed, 4 Sep 2024 14:30:39 +0200 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH v5 7/7] VMX: support USER_MSR From: Jan Beulich To: "xen-devel@lists.xenproject.org" Cc: Andrew Cooper , Wei Liu , =?utf-8?q?Roger_Pau_Monn=C3=A9?= References: <0b9a0ae8-a39c-49d8-b4e7-f2a463128058@suse.com> Content-Language: en-US Autocrypt: addr=jbeulich@suse.com; keydata= xsDiBFk3nEQRBADAEaSw6zC/EJkiwGPXbWtPxl2xCdSoeepS07jW8UgcHNurfHvUzogEq5xk hu507c3BarVjyWCJOylMNR98Yd8VqD9UfmX0Hb8/BrA+Hl6/DB/eqGptrf4BSRwcZQM32aZK 7Pj2XbGWIUrZrd70x1eAP9QE3P79Y2oLrsCgbZJfEwCgvz9JjGmQqQkRiTVzlZVCJYcyGGsD /0tbFCzD2h20ahe8rC1gbb3K3qk+LpBtvjBu1RY9drYk0NymiGbJWZgab6t1jM7sk2vuf0Py O9Hf9XBmK0uE9IgMaiCpc32XV9oASz6UJebwkX+zF2jG5I1BfnO9g7KlotcA/v5ClMjgo6Gl MDY4HxoSRu3i1cqqSDtVlt+AOVBJBACrZcnHAUSuCXBPy0jOlBhxPqRWv6ND4c9PH1xjQ3NP nxJuMBS8rnNg22uyfAgmBKNLpLgAGVRMZGaGoJObGf72s6TeIqKJo/LtggAS9qAUiuKVnygo 3wjfkS9A3DRO+SpU7JqWdsveeIQyeyEJ/8PTowmSQLakF+3fote9ybzd880fSmFuIEJldWxp Y2ggPGpiZXVsaWNoQHN1c2UuY29tPsJgBBMRAgAgBQJZN5xEAhsDBgsJCAcDAgQVAggDBBYC AwECHgECF4AACgkQoDSui/t3IH4J+wCfQ5jHdEjCRHj23O/5ttg9r9OIruwAn3103WUITZee e7Sbg12UgcQ5lv7SzsFNBFk3nEQQCACCuTjCjFOUdi5Nm244F+78kLghRcin/awv+IrTcIWF hUpSs1Y91iQQ7KItirz5uwCPlwejSJDQJLIS+QtJHaXDXeV6NI0Uef1hP20+y8qydDiVkv6l IreXjTb7DvksRgJNvCkWtYnlS3mYvQ9NzS9PhyALWbXnH6sIJd2O9lKS1Mrfq+y0IXCP10eS FFGg+Av3IQeFatkJAyju0PPthyTqxSI4lZYuJVPknzgaeuJv/2NccrPvmeDg6Coe7ZIeQ8Yj t0ARxu2xytAkkLCel1Lz1WLmwLstV30g80nkgZf/wr+/BXJW/oIvRlonUkxv+IbBM3dX2OV8 AmRv1ySWPTP7AAMFB/9PQK/VtlNUJvg8GXj9ootzrteGfVZVVT4XBJkfwBcpC/XcPzldjv+3 HYudvpdNK3lLujXeA5fLOH+Z/G9WBc5pFVSMocI71I8bT8lIAzreg0WvkWg5V2WZsUMlnDL9 mpwIGFhlbM3gfDMs7MPMu8YQRFVdUvtSpaAs8OFfGQ0ia3LGZcjA6Ik2+xcqscEJzNH+qh8V m5jjp28yZgaqTaRbg3M/+MTbMpicpZuqF4rnB0AQD12/3BNWDR6bmh+EkYSMcEIpQmBM51qM EKYTQGybRCjpnKHGOxG0rfFY1085mBDZCH5Kx0cl0HVJuQKC+dV2ZY5AqjcKwAxpE75MLFkr wkkEGBECAAkFAlk3nEQCGwwACgkQoDSui/t3IH7nnwCfcJWUDUFKdCsBH/E5d+0ZnMQi+G0A nAuWpQkjM1ASeQwSHEeAWPgskBQL In-Reply-To: <0b9a0ae8-a39c-49d8-b4e7-f2a463128058@suse.com> Hook up the new VM exit codes and handle guest accesses, context switch, and save/restore. At least for now don't allow the guest direct access to the control MSR; this may need changing if guests were to frequently access it (e.g. on their own context switch path). While there also correct a one-off in union ldt_or_tr_instr_info's comment. Signed-off-by: Jan Beulich --- Needing to change two places in hvm.c continues to be unhelpful; I recall I already did forget to also adjust hvm_load_cpu_msrs() for XFD. Considering that MSRs typically arrive in the order the table has it, couldn't we incrementally look up the incoming MSR index there, falling back to a full lookup only when the incremental lookup failed (and thus not normally re-iterating through the initial part of the array)? Said comment in union ldt_or_tr_instr_info is further odd (same for union gdt_or_idt_instr_info's) in that Instruction Information is only a 32-bit field. Hence bits 32-63 aren't undefined, but simply don't exist. RFC: The wee attempt to "deal" with nested is likely wrong, but I'm afraid I simply don't know where such enforcement would be done properly. Returning an error there is also commented out, for domain_cpu_policy_changed() returning void without "x86/xstate: re-size save area when CPUID policy changes" in place. --- v5: Introduce user_msr_gpr(). v4: New. --- a/xen/arch/x86/cpu-policy.c +++ b/xen/arch/x86/cpu-policy.c @@ -750,6 +750,12 @@ static void __init calculate_hvm_max_pol * situations until someone has cross-checked the behaviour for safety. */ __clear_bit(X86_FEATURE_PKS, fs); + + /* + * Don't expose USER_MSR until it is known how (if at all) it is + * virtualized on SVM. + */ + __clear_bit(X86_FEATURE_USER_MSR, fs); } if ( !cpu_has_vmx_msrlist ) --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -447,6 +447,10 @@ void domain_cpu_policy_changed(struct do } } + /* Nested doesn't have the necessary processing, yet. */ + if ( nestedhvm_enabled(d) && p->feat.user_msr ) + return /* -EINVAL */; + for_each_vcpu ( d, v ) { cpu_policy_updated(v); --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -1372,6 +1372,7 @@ static int cf_check hvm_load_cpu_xsave_s #define HVM_CPU_MSR_SIZE(cnt) offsetof(struct hvm_msr, msr[cnt]) static const uint32_t msrs_to_send[] = { + MSR_USER_MSR_CTL, MSR_SPEC_CTRL, MSR_INTEL_MISC_FEATURES_ENABLES, MSR_PKRS, @@ -1526,6 +1527,7 @@ static int cf_check hvm_load_cpu_msrs(st { int rc; + case MSR_USER_MSR_CTL: case MSR_SPEC_CTRL: case MSR_INTEL_MISC_FEATURES_ENABLES: case MSR_PKRS: --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -676,13 +676,18 @@ static void cf_check vmx_vcpu_destroy(st } /* - * To avoid MSR save/restore at every VM exit/entry time, we restore - * the x86_64 specific MSRs at domain switch time. Since these MSRs - * are not modified once set for para domains, we don't save them, - * but simply reset them to values set in percpu_traps_init(). + * To avoid MSR save/restore at every VM exit/entry time, we restore the + * x86_64 specific MSRs at vcpu switch time. Since these MSRs are not + * modified once set for para domains, we don't save them, but simply clear + * them or reset them to values set in percpu_traps_init(). */ -static void vmx_restore_host_msrs(void) +static void vmx_restore_host_msrs(const struct vcpu *v) { + const struct vcpu_msrs *msrs = v->arch.msrs; + + if ( msrs->user_msr_ctl.enable ) + wrmsrl(MSR_USER_MSR_CTL, 0); + /* No PV guests? No need to restore host SYSCALL infrastructure. */ if ( !IS_ENABLED(CONFIG_PV) ) return; @@ -736,6 +741,9 @@ static void vmx_restore_guest_msrs(struc if ( cp->feat.pks ) wrpkrs(msrs->pkrs); + + if ( msrs->user_msr_ctl.enable ) + wrmsrl(MSR_USER_MSR_CTL, msrs->user_msr_ctl.raw); } void vmx_update_cpu_exec_control(struct vcpu *v) @@ -1178,7 +1186,7 @@ static void cf_check vmx_ctxt_switch_fro if ( !v->arch.fully_eager_fpu ) vmx_fpu_leave(v); vmx_save_guest_msrs(v); - vmx_restore_host_msrs(); + vmx_restore_host_msrs(v); vmx_save_dr(v); if ( v->domain->arch.hvm.pi_ops.flags & PI_CSW_FROM ) @@ -4080,6 +4088,14 @@ static int vmx_handle_apic_write(void) return vlapic_apicv_write(current, exit_qualification & 0xfff); } +static unsigned int user_msr_gpr(void) +{ + user_msr_instr_info_t info; + + __vmread(VMX_INSTRUCTION_INFO, &info.raw); + return info.gpr; +} + static void undo_nmis_unblocked_by_iret(void) { unsigned long guest_info; @@ -4580,6 +4596,41 @@ void asmlinkage vmx_vmexit_handler(struc hvm_inject_hw_exception(X86_EXC_GP, 0); break; + case EXIT_REASON_URDMSR: + { + uint64_t msr_content = 0; + + __vmread(EXIT_QUALIFICATION, &exit_qualification); + switch ( hvm_msr_read_intercept(exit_qualification, &msr_content) ) + { + case X86EMUL_OKAY: + *decode_gpr(regs, user_msr_gpr()) = msr_content; + update_guest_eip(); /* Safe: URDMSR */ + break; + + case X86EMUL_EXCEPTION: + hvm_inject_hw_exception(X86_EXC_GP, 0); + break; + } + break; + } + + case EXIT_REASON_UWRMSR: + __vmread(EXIT_QUALIFICATION, &exit_qualification); + switch ( hvm_msr_write_intercept(exit_qualification, + *decode_gpr(regs, user_msr_gpr()), + true) ) + { + case X86EMUL_OKAY: + update_guest_eip(); /* Safe: UWRMSR */ + break; + + case X86EMUL_EXCEPTION: + hvm_inject_hw_exception(X86_EXC_GP, 0); + break; + } + break; + case EXIT_REASON_VMXOFF: case EXIT_REASON_VMXON: case EXIT_REASON_VMCLEAR: --- a/xen/arch/x86/include/asm/hvm/vmx/vmx.h +++ b/xen/arch/x86/include/asm/hvm/vmx/vmx.h @@ -203,6 +203,8 @@ static inline void pi_clear_sn(struct pi #define EXIT_REASON_NOTIFY 75 #define EXIT_REASON_RDMSRLIST 78 #define EXIT_REASON_WRMSRLIST 79 +#define EXIT_REASON_URDMSR 80 +#define EXIT_REASON_UWRMSR 81 /* Remember to also update VMX_PERF_EXIT_REASON_SIZE! */ /* @@ -674,8 +676,18 @@ typedef union ldt_or_tr_instr_info { base_reg_invalid :1, /* bit 27 - Base register invalid */ instr_identity :1, /* bit 28 - 0:LDT, 1:TR */ instr_write :1, /* bit 29 - 0:store, 1:load */ - :34; /* bits 31:63 - Undefined */ + :34; /* bits 30:63 - Undefined */ }; } ldt_or_tr_instr_info_t; +/* VM-Exit instruction info for URDMSR and UWRMSR */ +typedef union user_msr_instr_info { + unsigned long raw; + struct { + unsigned int :3, /* Bits 0:2 - Undefined */ + gpr :4, /* Bits 3:6 - Source/Destination register */ + :25; /* bits 7:31 - Undefined */ + }; +} user_msr_instr_info_t; + #endif /* __ASM_X86_HVM_VMX_VMX_H__ */ --- a/xen/arch/x86/include/asm/msr.h +++ b/xen/arch/x86/include/asm/msr.h @@ -296,6 +296,20 @@ uint64_t msr_spec_ctrl_valid_bits(const struct vcpu_msrs { /* + * 0x0000001c - MSR_USER_MSR_CTL + * + * Value is guest chosen, and always loaded in vcpu context. + */ + union { + uint64_t raw; + struct { + bool enable:1; + unsigned int :11; + unsigned long bitmap:52; + }; + } user_msr_ctl; + + /* * 0x00000048 - MSR_SPEC_CTRL * 0xc001011f - MSR_VIRT_SPEC_CTRL (if X86_FEATURE_AMD_SSBD) * --- a/xen/arch/x86/include/asm/perfc_defn.h +++ b/xen/arch/x86/include/asm/perfc_defn.h @@ -6,7 +6,7 @@ PERFCOUNTER_ARRAY(exceptions, #ifdef CONFIG_HVM -#define VMX_PERF_EXIT_REASON_SIZE 80 +#define VMX_PERF_EXIT_REASON_SIZE 82 #define VMEXIT_NPF_PERFC 143 #define SVM_PERF_EXIT_REASON_SIZE (VMEXIT_NPF_PERFC + 1) PERFCOUNTER_ARRAY(vmexits, "vmexits", --- a/xen/arch/x86/msr.c +++ b/xen/arch/x86/msr.c @@ -206,6 +206,12 @@ int guest_rdmsr(struct vcpu *v, uint32_t *val = msrs->xss.raw; break; + case MSR_USER_MSR_CTL: + if ( !cp->feat.user_msr ) + goto gp_fault; + *val = msrs->user_msr_ctl.raw; + break; + case 0x40000000 ... 0x400001ff: if ( is_viridian_domain(d) ) { @@ -536,6 +542,19 @@ int guest_wrmsr(struct vcpu *v, uint32_t msrs->xss.raw = val; break; + case MSR_USER_MSR_CTL: + if ( !cp->feat.user_msr ) + goto gp_fault; + + if ( (val & ~(USER_MSR_ENABLE | USER_MSR_ADDR_MASK)) || + !is_canonical_address(val) ) + goto gp_fault; + + msrs->user_msr_ctl.raw = val; + if ( v == curr ) + wrmsrl(MSR_USER_MSR_CTL, val); + break; + case 0x40000000 ... 0x400001ff: if ( is_viridian_domain(d) ) { --- a/xen/include/public/arch-x86/cpufeatureset.h +++ b/xen/include/public/arch-x86/cpufeatureset.h @@ -337,7 +337,7 @@ XEN_CPUFEATURE(AVX_VNNI_INT8, 15*32 XEN_CPUFEATURE(AVX_NE_CONVERT, 15*32+ 5) /*A AVX-NE-CONVERT Instructions */ XEN_CPUFEATURE(AVX_VNNI_INT16, 15*32+10) /*A AVX-VNNI-INT16 Instructions */ XEN_CPUFEATURE(PREFETCHI, 15*32+14) /*A PREFETCHIT{0,1} Instructions */ -XEN_CPUFEATURE(USER_MSR, 15*32+15) /* U{RD,WR}MSR Instructions */ +XEN_CPUFEATURE(USER_MSR, 15*32+15) /*s U{RD,WR}MSR Instructions */ XEN_CPUFEATURE(CET_SSS, 15*32+18) /* CET Supervisor Shadow Stacks safe to use */ /* Intel-defined CPU features, MSR_ARCH_CAPS 0x10a.eax, word 16 */