From patchwork Thu Feb 23 09:32:34 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Juergen Gross X-Patchwork-Id: 60871 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:5915:0:0:0:0:0 with SMTP id v21csp223011wrd; Thu, 23 Feb 2023 01:43:09 -0800 (PST) X-Google-Smtp-Source: AK7set921LtiuLy4vC1UvhJMapTMMd3VWxUP9/Pmrqxd/31RmlLioi+FLEqpKTFNK4nO2MSWNh7X X-Received: by 2002:a17:906:74dd:b0:887:dbe1:25ac with SMTP id z29-20020a17090674dd00b00887dbe125acmr19957811ejl.0.1677145389610; Thu, 23 Feb 2023 01:43:09 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1677145389; cv=none; d=google.com; s=arc-20160816; b=Zyj7WJ5V3uzdyiJR4SctvCKIMW3cwDTcaZ+Zv/8GmRIlb+1rm8OE11PCttAXJOmSFd kYSq+1o94Hy1MMpK77sEkeQqANy6/pTI/CXLyYsNGS6J0eBh8pm9WDeRlL7cB+DMj82y dwsFArTt36KXMB6gDX6pSR9PyWB08sdq2bFdDr4J5wOZGCx1aNNUX/QDULZmnkf/RoXx mGTVR2kts5mtoLfHbvVdoTKDNMmvoAiwzpVdOAWcw9QM72TSYAmWjViil+/XNT4plCzh M3Hjk+g/eycz0NVouhex4TICj7WiSNjCgDYhjEo6cac8mun8Nu14V1s8GnnJst3/uLzK Jhow== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=ItpVqMgiQCpppFp9dWoKaB6tj+B5hU2FSza1i+uQ26c=; b=rJtWafU+ydSmhWf8ZfslIY8zRO2BL5X53mUcMIbcs9LbDPG1ecUDTNkQaSvhq+xyzH jjSlzgiW9+bkLtDLTH5CGNG78HwFApj0nHMelN7VGTeVxvBYNnVf87oZbj8wBiWdg9vw AXijRaYBY8zqsPT5Q51tAyetqGcq1yAf9SmXtYvjDcGovKjz0vLUZAa8eyRa8ap7t5h6 pkt9uLKFmuouXQ64BGR5qai+tV7edT2gJeNnqRqmqhXFZoxUc96YD26j4qSXiYV5asUH tfRFND2o+eOi0N3YqPyufJyZG1sWCnQeZ7sftb7LFNmtcV2YEM1d1QB99EZwwORZXJ3W 88cA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@suse.com header.s=susede1 header.b="eRIL/D1S"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=suse.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id ui42-20020a170907c92a00b008cf02438e0dsi13802366ejc.683.2023.02.23.01.42.46; Thu, 23 Feb 2023 01:43:09 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@suse.com header.s=susede1 header.b="eRIL/D1S"; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=suse.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234009AbjBWJdZ (ORCPT + 99 others); Thu, 23 Feb 2023 04:33:25 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:32984 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233715AbjBWJdV (ORCPT ); Thu, 23 Feb 2023 04:33:21 -0500 Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.220.29]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7452B4C6F1 for ; Thu, 23 Feb 2023 01:33:05 -0800 (PST) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id D800F5BE9F; Thu, 23 Feb 2023 09:33:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.com; s=susede1; t=1677144783; h=from:from:reply-to:date:date:message-id:message-id:to:to:cc:cc: mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ItpVqMgiQCpppFp9dWoKaB6tj+B5hU2FSza1i+uQ26c=; b=eRIL/D1Se7ozMqQCWqcbCU3+3sFQpz3L7hMR02NRDKXmRWzZHhaWqt9mnrm/kiKt1Xi1Uo Z7vCuPZdApPPG1KBomKD2hl39isOxsl9jZu3HSYgR0xeZj6rcIePI/tdDUlpkT074XG3XT kZUbgwfGFXD2zPF/jwZog4PJ02smTPM= Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id 9D0E713928; Thu, 23 Feb 2023 09:33:03 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id xfrSJM8y92OLbAAAMHmgww (envelope-from ); Thu, 23 Feb 2023 09:33:03 +0000 From: Juergen Gross To: linux-kernel@vger.kernel.org, x86@kernel.org Cc: Juergen Gross , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H. Peter Anvin" Subject: [PATCH v3 03/12] x86/mtrr: support setting MTRR state for software defined MTRRs Date: Thu, 23 Feb 2023 10:32:34 +0100 Message-Id: <20230223093243.1180-4-jgross@suse.com> X-Mailer: git-send-email 2.35.3 In-Reply-To: <20230223093243.1180-1-jgross@suse.com> References: <20230223093243.1180-1-jgross@suse.com> MIME-Version: 1.0 X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED,SPF_HELO_NONE, SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1758614404013028833?= X-GMAIL-MSGID: =?utf-8?q?1758614404013028833?= When running virtualized, MTRR access can be reduced (e.g. in Xen PV guests or when running as a SEV-SNP guest under Hyper-V). Typically the hypervisor will reset the MTRR feature in CPUID data, resulting in no MTRR memory type information being available for the kernel. This has turned out to result in problems: - Hyper-V SEV-SNP guests using uncached mappings where they shouldn't - Xen PV dom0 mapping memory as WB which should be UC- instead Solve those problems by supporting to set a static MTRR state, overwriting the empty state used today. In case such a state has been set, don't call get_mtrr_state() in mtrr_bp_init(). The set state will only be used by mtrr_type_lookup(), as in all other cases mtrr_enabled() is being checked, which will return false. Accept the overwrite call only for selected cases when running as a guest. Disable X86_FEATURE_MTRR in order to avoid any MTRR modifications by just refusing them. Signed-off-by: Juergen Gross --- V2: - new patch V3: - omit fixed MTRRs, as those are currently not needed - disable X86_FEATURE_MTRR instead of testing it - provide a stub for !CONFIG_MTRR (Michael Kelley) - use cpu_feature_enabled() (Boris Petkov) - add tests for mtrr_overwrite_state() being allowed (Boris Petkov) --- arch/x86/include/asm/mtrr.h | 8 ++++++ arch/x86/kernel/cpu/mtrr/generic.c | 43 ++++++++++++++++++++++++++++++ arch/x86/kernel/cpu/mtrr/mtrr.c | 9 +++++++ arch/x86/kernel/setup.c | 2 ++ 4 files changed, 62 insertions(+) diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h index f0eeaf6e5f5f..f1cb81330a64 100644 --- a/arch/x86/include/asm/mtrr.h +++ b/arch/x86/include/asm/mtrr.h @@ -31,6 +31,8 @@ */ # ifdef CONFIG_MTRR void mtrr_bp_init(void); +void mtrr_overwrite_state(struct mtrr_var_range *var, unsigned int num_var, + mtrr_type def_type); extern u8 mtrr_type_lookup(u64 addr, u64 end, u8 *uniform); extern void mtrr_save_fixed_ranges(void *); extern void mtrr_save_state(void); @@ -48,6 +50,12 @@ void mtrr_disable(void); void mtrr_enable(void); void mtrr_generic_set_state(void); # else +static inline void mtrr_overwrite_state(struct mtrr_var_range *var, + unsigned int num_var, + mtrr_type def_type) +{ +} + static inline u8 mtrr_type_lookup(u64 addr, u64 end, u8 *uniform) { /* diff --git a/arch/x86/kernel/cpu/mtrr/generic.c b/arch/x86/kernel/cpu/mtrr/generic.c index ee09d359e08f..40c59d522f57 100644 --- a/arch/x86/kernel/cpu/mtrr/generic.c +++ b/arch/x86/kernel/cpu/mtrr/generic.c @@ -8,10 +8,12 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -240,6 +242,47 @@ static u8 mtrr_type_lookup_variable(u64 start, u64 end, u64 *partial_end, return mtrr_state.def_type; } +/** + * mtrr_overwrite_state - set static MTRR state + * + * Used to set MTRR state via different means (e.g. with data obtained from + * a hypervisor). + * Is allowed only for special cases when running virtualized. Must be called + * from the x86_init.hyper.init_platform() hook. X86_FEATURE_MTRR must be off. + */ +void mtrr_overwrite_state(struct mtrr_var_range *var, unsigned int num_var, + mtrr_type def_type) +{ + unsigned int i; + + if (WARN_ON(mtrr_state_set || + hypervisor_is_type(X86_HYPER_NATIVE) || + !cpu_feature_enabled(X86_FEATURE_HYPERVISOR) || + (!cc_platform_has(CC_ATTR_GUEST_SEV_SNP) && + !cpu_feature_enabled(X86_FEATURE_XENPV) && + !cpu_feature_enabled(X86_FEATURE_TDX_GUEST)))) + return; + + /* Disable MTRR in order to disable MTRR modifications. */ + setup_clear_cpu_cap(X86_FEATURE_MTRR); + + if (var) { + if (num_var > MTRR_MAX_VAR_RANGES) { + pr_warn("Trying to overwrite MTRR state with %u variable entries\n", + num_var); + num_var = MTRR_MAX_VAR_RANGES; + } + for (i = 0; i < num_var; i++) + mtrr_state.var_ranges[i] = var[i]; + num_var_ranges = num_var; + } + + mtrr_state.def_type = def_type; + mtrr_state.enabled |= MTRR_STATE_MTRR_ENABLED; + + mtrr_state_set = 1; +} + /** * mtrr_type_lookup - look up memory type in MTRR * diff --git a/arch/x86/kernel/cpu/mtrr/mtrr.c b/arch/x86/kernel/cpu/mtrr/mtrr.c index 7596ebeab929..5fe62ee0361b 100644 --- a/arch/x86/kernel/cpu/mtrr/mtrr.c +++ b/arch/x86/kernel/cpu/mtrr/mtrr.c @@ -666,6 +666,15 @@ void __init mtrr_bp_init(void) const char *why = "(not available)"; unsigned int phys_addr; + if (mtrr_state.enabled) { + /* Software overwrite of MTRR state, only for generic case. */ + mtrr_calc_physbits(true); + init_table(); + pr_info("MTRRs set to read-only\n"); + + return; + } + phys_addr = mtrr_calc_physbits(boot_cpu_has(X86_FEATURE_MTRR)); if (boot_cpu_has(X86_FEATURE_MTRR)) { diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 16babff771bd..0cccfeb67c3a 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -1037,6 +1037,8 @@ void __init setup_arch(char **cmdline_p) /* * VMware detection requires dmi to be available, so this * needs to be done after dmi_setup(), for the boot CPU. + * For some guest types (Xen PV, SEV-SNP, TDX) it is required to be + * called before cache_bp_init() for setting up MTRR state. */ init_hypervisor_platform();