public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Juergen Gross <jgross@suse.com>
To: linux-kernel@vger.kernel.org, x86@kernel.org
Cc: Juergen Gross <jgross@suse.com>,
	Boris Ostrovsky <boris.ostrovsky@oracle.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	"H. Peter Anvin" <hpa@zytor.com>,
	xen-devel@lists.xenproject.org
Subject: [PATCH v3 05/12] x86/xen: set MTRR state when running as Xen PV initial domain
Date: Thu, 23 Feb 2023 10:32:36 +0100	[thread overview]
Message-ID: <20230223093243.1180-6-jgross@suse.com> (raw)
In-Reply-To: <20230223093243.1180-1-jgross@suse.com>

When running as Xen PV initial domain (aka dom0), MTRRs are disabled
by the hypervisor, but the system should nevertheless use correct
cache memory types. This has always kind of worked, as disabled MTRRs
resulted in disabled PAT, too, so that the kernel avoided code paths
resulting in inconsistencies. This bypassed all of the sanity checks
the kernel is doing with enabled MTRRs in order to avoid memory
mappings with conflicting memory types.

This has been changed recently, leading to PAT being accepted to be
enabled, while MTRRs stayed disabled. The result is that
mtrr_type_lookup() no longer is accepting all memory type requests,
but started to return WB even if UC- was requested. This led to
driver failures during initialization of some devices.

In reality MTRRs are still in effect, but they are under complete
control of the Xen hypervisor. It is possible, however, to retrieve
the MTRR settings from the hypervisor.

In order to fix those problems, overwrite the MTRR state via
mtrr_overwrite_state() with the MTRR data from the hypervisor, if the
system is running as a Xen dom0.

Fixes: 72cbc8f04fe2 ("x86/PAT: Have pat_enabled() properly reflect state when running on Xen")
Signed-off-by: Juergen Gross <jgross@suse.com>
---
V2:
- new patch
V3:
- move the call of mtrr_overwrite_state() to xen_pv_init_platform()
---
 arch/x86/xen/enlighten_pv.c | 50 +++++++++++++++++++++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
index bb59cc6ddb2d..729fb447a5b6 100644
--- a/arch/x86/xen/enlighten_pv.c
+++ b/arch/x86/xen/enlighten_pv.c
@@ -68,6 +68,7 @@
 #include <asm/reboot.h>
 #include <asm/hypervisor.h>
 #include <asm/mach_traps.h>
+#include <asm/mtrr.h>
 #include <asm/mwait.h>
 #include <asm/pci_x86.h>
 #include <asm/cpu.h>
@@ -119,6 +120,52 @@ static int __init parse_xen_msr_safe(char *str)
 }
 early_param("xen_msr_safe", parse_xen_msr_safe);
 
+/* Get MTRR settings from Xen and put them into mtrr_state. */
+static void __init xen_set_mtrr_data(void)
+{
+#ifdef CONFIG_MTRR
+	struct xen_platform_op op = {
+		.cmd = XENPF_read_memtype,
+		.interface_version = XENPF_INTERFACE_VERSION,
+	};
+	unsigned int reg;
+	unsigned long mask;
+	uint32_t eax, width;
+	static struct mtrr_var_range var[MTRR_MAX_VAR_RANGES] __initdata;
+
+	/* Get physical address width (only 64-bit cpus supported). */
+	width = 36;
+	eax = cpuid_eax(0x80000000);
+	if ((eax >> 16) == 0x8000 && eax >= 0x80000008) {
+		eax = cpuid_eax(0x80000008);
+		width = eax & 0xff;
+	}
+
+	for (reg = 0; reg < MTRR_MAX_VAR_RANGES; reg++) {
+		op.u.read_memtype.reg = reg;
+		if (HYPERVISOR_platform_op(&op))
+			break;
+
+		/*
+		 * Only called in dom0, which has all RAM PFNs mapped at
+		 * RAM MFNs, and all PCI space etc. is identity mapped.
+		 * This means we can treat MFN == PFN regarding MTTR settings.
+		 */
+		var[reg].base_lo = op.u.read_memtype.type;
+		var[reg].base_lo |= op.u.read_memtype.mfn << PAGE_SHIFT;
+		var[reg].base_hi = op.u.read_memtype.mfn >> (32 - PAGE_SHIFT);
+		mask = ~((op.u.read_memtype.nr_mfns << PAGE_SHIFT) - 1);
+		mask &= (1UL << width) - 1;
+		if (mask)
+			mask |= 1 << 11;
+		var[reg].mask_lo = mask;
+		var[reg].mask_hi = mask >> 32;
+	}
+
+	mtrr_overwrite_state(var, reg, MTRR_TYPE_UNCACHABLE);
+#endif
+}
+
 static void __init xen_pv_init_platform(void)
 {
 	/* PV guests can't operate virtio devices without grants. */
@@ -135,6 +182,9 @@ static void __init xen_pv_init_platform(void)
 
 	/* pvclock is in shared info area */
 	xen_init_time_ops();
+
+	if (xen_initial_domain())
+		xen_set_mtrr_data();
 }
 
 static void __init xen_pv_guest_late_init(void)
-- 
2.35.3


  parent reply	other threads:[~2023-02-23  9:33 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-23  9:32 [PATCH v3 00/12] x86/mtrr: fix handling with PAT but without MTRR Juergen Gross
2023-02-23  9:32 ` [PATCH v3 01/12] x86/mtrr: split off physical address size calculation Juergen Gross
2023-02-23  9:32 ` [PATCH v3 02/12] x86/mtrr: optimize mtrr_calc_physbits() Juergen Gross
2023-02-23  9:32 ` [PATCH v3 03/12] x86/mtrr: support setting MTRR state for software defined MTRRs Juergen Gross
2023-02-26 17:12   ` Michael Kelley (LINUX)
2023-02-27  7:13     ` Juergen Gross
2023-02-23  9:32 ` [PATCH v3 04/12] x86/hyperv: set MTRR state when running as SEV-SNP Hyper-V guest Juergen Gross
2023-02-23  9:32 ` Juergen Gross [this message]
     [not found]   ` <a7897030-d420-a741-074a-6e21e7c1629b@oracle.com>
2023-02-27  7:12     ` [PATCH v3 05/12] x86/xen: set MTRR state when running as Xen PV initial domain Juergen Gross
2023-02-27 13:52       ` Boris Ostrovsky
2023-02-27 13:56         ` Juergen Gross
2023-02-23  9:32 ` [PATCH v3 06/12] x86/mtrr: replace vendor tests in MTRR code Juergen Gross
2023-02-23  9:32 ` [PATCH v3 07/12] x86/mtrr: allocate mtrr_value array dynamically Juergen Gross
2023-02-23  9:32 ` [PATCH v3 08/12] x86/mtrr: add get_effective_type() service function Juergen Gross
2023-02-23  9:32 ` [PATCH v3 09/12] x86/mtrr: construct a memory map with cache modes Juergen Gross
2023-02-23  9:32 ` [PATCH v3 10/12] x86/mtrr: use new cache_map in mtrr_type_lookup() Juergen Gross
2023-02-23 19:24   ` Michael Kelley (LINUX)
2023-02-24  5:48     ` Juergen Gross
2023-02-24  6:37   ` [PATCH v3.1 " Juergen Gross
2023-02-26 17:00     ` Michael Kelley (LINUX)
2023-02-27  7:11       ` Juergen Gross
2023-02-23  9:32 ` [PATCH v3 11/12] x86/mtrr: don't let mtrr_type_lookup() return MTRR_TYPE_INVALID Juergen Gross
2023-02-23  9:32 ` [PATCH v3 12/12] x86/mm: only check uniform after calling mtrr_type_lookup() Juergen Gross

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230223093243.1180-6-jgross@suse.com \
    --to=jgross@suse.com \
    --cc=boris.ostrovsky@oracle.com \
    --cc=bp@alien8.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=hpa@zytor.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=tglx@linutronix.de \
    --cc=x86@kernel.org \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox