Patch "x86/xen: Set MTRR state when running as Xen PV initial domain" has been added to the 6.3-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    x86/xen: Set MTRR state when running as Xen PV initial domain

to the 6.3-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     x86-xen-set-mtrr-state-when-running-as-xen-pv-initia.patch
and it can be found in the queue-6.3 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 22aa133bd32a604b2b06af017af76dcd9d30d96e
Author: Juergen Gross <jgross@xxxxxxxx>
Date:   Tue May 2 14:09:20 2023 +0200

    x86/xen: Set MTRR state when running as Xen PV initial domain
    
    [ Upstream commit a153f254e5cdf8fa3a1df90a6ffed3063fede154 ]
    
    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@xxxxxxxx>
    Signed-off-by: Borislav Petkov (AMD) <bp@xxxxxxxxx>
    Reviewed-by: Boris Ostrovsky <boris.ostrovsky@xxxxxxxxxx>
    Tested-by: Michael Kelley <mikelley@xxxxxxxxxxxxx>
    Link: https://lore.kernel.org/r/20230502120931.20719-6-jgross@xxxxxxxx
    Signed-off-by: Borislav Petkov (AMD) <bp@xxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
index 093b78c8bbec0..8732b85d56505 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,54 @@ 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 MTRR 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 |= MTRR_PHYSMASK_V;
+		var[reg].mask_lo = mask;
+		var[reg].mask_hi = mask >> 32;
+	}
+
+	/* Only overwrite MTRR state if any MTRR could be got from Xen. */
+	if (reg)
+		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 +184,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)



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux