aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
authorMark Brown <broonie@kernel.org>2026-05-29 23:14:24 +0100
committerMark Brown <broonie@kernel.org>2026-05-29 23:14:24 +0100
commit133bffdb994e146623bb3aca55c83bd2a83946f3 (patch)
treec59bc65b68b2c5166d2320d784f8c0ae54c857cb /arch
parenta7a99e76d203e7f6621804f33148cb7afa7818f2 (diff)
parent7a035678fc2bdee81881170764ef08a91a076147 (diff)
downloadlinux-next-history-133bffdb994e146623bb3aca55c83bd2a83946f3.tar.gz
Merge branch 'hyperv-next' of https://git.kernel.org/pub/scm/linux/kernel/git/hyperv/linux.git
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/hyperv/hv_vtl.c38
-rw-r--r--arch/x86/include/asm/acpi.h16
-rw-r--r--arch/x86/include/asm/topology.h3
-rw-r--r--arch/x86/include/asm/x86_init.h3
-rw-r--r--arch/x86/kernel/acpi/madt_wakeup.c16
-rw-r--r--arch/x86/kernel/devicetree.c47
-rw-r--r--arch/x86/kernel/x86_init.c3
-rw-r--r--arch/x86/realmode/init.c7
8 files changed, 125 insertions, 8 deletions
diff --git a/arch/x86/hyperv/hv_vtl.c b/arch/x86/hyperv/hv_vtl.c
index 9b6a9bc4ab760..07fac3d687c39 100644
--- a/arch/x86/hyperv/hv_vtl.c
+++ b/arch/x86/hyperv/hv_vtl.c
@@ -6,6 +6,9 @@
* Saurabh Sengar <ssengar@microsoft.com>
*/
+#include <linux/acpi.h>
+
+#include <asm/acpi.h>
#include <asm/apic.h>
#include <asm/boot.h>
#include <asm/desc.h>
@@ -59,6 +62,18 @@ static void __noreturn hv_vtl_restart(char __maybe_unused *cmd)
hv_vtl_emergency_restart();
}
+static inline bool within_page(u64 addr, u64 start)
+{
+ return addr >= start && addr < (start + PAGE_SIZE);
+}
+
+static bool hv_vtl_is_private_mmio_tdx(u64 addr)
+{
+ u64 mb_addr = acpi_get_mp_wakeup_mailbox_paddr();
+
+ return mb_addr && within_page(addr, mb_addr);
+}
+
void __init hv_vtl_init_platform(void)
{
/*
@@ -68,8 +83,16 @@ void __init hv_vtl_init_platform(void)
*/
pr_info("Linux runs in Hyper-V Virtual Trust Level %d\n", ms_hyperv.vtl);
- x86_platform.realmode_reserve = x86_init_noop;
- x86_platform.realmode_init = x86_init_noop;
+ /* There is no paravisor present if we are here. */
+ if (hv_isolation_type_tdx()) {
+ x86_init.resources.realmode_limit = SZ_4G;
+ x86_platform.hyper.is_private_mmio = hv_vtl_is_private_mmio_tdx;
+
+ } else {
+ x86_platform.realmode_reserve = x86_init_noop;
+ x86_platform.realmode_init = x86_init_noop;
+ real_mode_header = &hv_vtl_real_mode_header;
+ }
x86_init.irqs.pre_vector_init = x86_init_noop;
x86_init.timers.timer_init = x86_init_noop;
x86_init.resources.probe_roms = x86_init_noop;
@@ -251,8 +274,15 @@ int __init hv_vtl_early_init(void)
panic("XSAVE has to be disabled as it is not supported by this module.\n"
"Please add 'noxsave' to the kernel command line.\n");
- real_mode_header = &hv_vtl_real_mode_header;
- apic_update_callback(wakeup_secondary_cpu_64, hv_vtl_wakeup_secondary_cpu);
+ /*
+ * TDX confidential VMs do not trust the hypervisor and cannot use it to
+ * boot secondary CPUs. Instead, they will be booted using the wakeup
+ * mailbox if detected during boot. See setup_arch().
+ *
+ * There is no paravisor present if we are here.
+ */
+ if (!hv_isolation_type_tdx())
+ apic_update_callback(wakeup_secondary_cpu_64, hv_vtl_wakeup_secondary_cpu);
return 0;
}
diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h
index a03aa6f999d15..c4e6459bd56b1 100644
--- a/arch/x86/include/asm/acpi.h
+++ b/arch/x86/include/asm/acpi.h
@@ -182,6 +182,10 @@ void __iomem *x86_acpi_os_ioremap(acpi_physical_address phys, acpi_size size);
#define acpi_os_ioremap acpi_os_ioremap
#endif
+void acpi_setup_mp_wakeup_mailbox(u64 addr);
+struct acpi_madt_multiproc_wakeup_mailbox *acpi_get_mp_wakeup_mailbox(void);
+u64 acpi_get_mp_wakeup_mailbox_paddr(void);
+
#else /* !CONFIG_ACPI */
#define acpi_lapic 0
@@ -200,6 +204,18 @@ static inline u64 x86_default_get_root_pointer(void)
return 0;
}
+static inline void acpi_setup_mp_wakeup_mailbox(u64 addr) { }
+
+static inline struct acpi_madt_multiproc_wakeup_mailbox *acpi_get_mp_wakeup_mailbox(void)
+{
+ return NULL;
+}
+
+static inline u64 acpi_get_mp_wakeup_mailbox_paddr(void)
+{
+ return 0;
+}
+
#endif /* !CONFIG_ACPI */
#define ARCH_HAS_POWER_INIT 1
diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h
index 0ba9bdb998717..8fb61d2465eb8 100644
--- a/arch/x86/include/asm/topology.h
+++ b/arch/x86/include/asm/topology.h
@@ -157,6 +157,8 @@ extern unsigned int __num_threads_per_package;
extern unsigned int __num_cores_per_package;
extern unsigned int __num_nodes_per_package;
+struct cpuinfo_x86;
+
const char *get_topology_cpu_type_name(struct cpuinfo_x86 *c);
enum x86_topology_cpu_type get_topology_cpu_type(struct cpuinfo_x86 *c);
@@ -265,6 +267,7 @@ extern bool x86_topology_update;
#ifdef CONFIG_SCHED_MC_PRIO
#include <asm/percpu.h>
+#include <linux/cache.h>
DECLARE_PER_CPU_READ_MOSTLY(int, sched_core_priority);
extern bool __read_mostly sysctl_sched_itmt_enabled;
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
index 6c8a6ead84f6e..953d3199408ae 100644
--- a/arch/x86/include/asm/x86_init.h
+++ b/arch/x86/include/asm/x86_init.h
@@ -31,12 +31,15 @@ struct x86_init_mpparse {
* platform
* @memory_setup: platform specific memory setup
* @dmi_setup: platform specific DMI setup
+ * @realmode_limit: platform specific address limit for the real mode trampoline
+ * (default 1M)
*/
struct x86_init_resources {
void (*probe_roms)(void);
void (*reserve_resources)(void);
char *(*memory_setup)(void);
void (*dmi_setup)(void);
+ unsigned long realmode_limit;
};
/**
diff --git a/arch/x86/kernel/acpi/madt_wakeup.c b/arch/x86/kernel/acpi/madt_wakeup.c
index 6d7603511f52c..48734e4a6e8f5 100644
--- a/arch/x86/kernel/acpi/madt_wakeup.c
+++ b/arch/x86/kernel/acpi/madt_wakeup.c
@@ -247,3 +247,19 @@ int __init acpi_parse_mp_wake(union acpi_subtable_headers *header,
return 0;
}
+
+void __init acpi_setup_mp_wakeup_mailbox(u64 mailbox_paddr)
+{
+ acpi_mp_wake_mailbox_paddr = mailbox_paddr;
+ apic_update_callback(wakeup_secondary_cpu_64, acpi_wakeup_cpu);
+}
+
+struct acpi_madt_multiproc_wakeup_mailbox *acpi_get_mp_wakeup_mailbox(void)
+{
+ return acpi_mp_wake_mailbox;
+}
+
+u64 acpi_get_mp_wakeup_mailbox_paddr(void)
+{
+ return acpi_mp_wake_mailbox_paddr;
+}
diff --git a/arch/x86/kernel/devicetree.c b/arch/x86/kernel/devicetree.c
index dd8748c45529a..318acaecb5ca1 100644
--- a/arch/x86/kernel/devicetree.c
+++ b/arch/x86/kernel/devicetree.c
@@ -18,6 +18,7 @@
#include <linux/of_pci.h>
#include <linux/initrd.h>
+#include <asm/acpi.h>
#include <asm/irqdomain.h>
#include <asm/hpet.h>
#include <asm/apic.h>
@@ -125,6 +126,51 @@ static void __init dtb_setup_hpet(void)
#endif
}
+#if defined(CONFIG_X86_64) && defined(CONFIG_SMP)
+
+#define WAKEUP_MAILBOX_SIZE 0x1000
+#define WAKEUP_MAILBOX_ALIGN 0x1000
+
+/** dtb_wakeup_mailbox_setup() - Parse the wakeup mailbox from the device tree
+ *
+ * Look for the presence of a wakeup mailbox in the DeviceTree. The mailbox is
+ * expected to follow the structure and operation described in the Multiprocessor
+ * Wakeup Structure of the ACPI specification.
+ */
+static void __init dtb_wakeup_mailbox_setup(void)
+{
+ struct device_node *node;
+ struct resource res;
+
+ node = of_find_compatible_node(NULL, NULL, "intel,wakeup-mailbox");
+ if (!node)
+ return;
+
+ if (of_address_to_resource(node, 0, &res))
+ goto done;
+
+ /* The mailbox is a 4KB-aligned region.*/
+ if (res.start & (WAKEUP_MAILBOX_ALIGN - 1))
+ goto done;
+
+ /* The mailbox has a size of 4KB. */
+ if (res.end - res.start + 1 != WAKEUP_MAILBOX_SIZE)
+ goto done;
+
+ /* Not supported when the mailbox is used. */
+ cpu_hotplug_disable_offlining();
+
+ acpi_setup_mp_wakeup_mailbox(res.start);
+done:
+ of_node_put(node);
+}
+#else /* !CONFIG_X86_64 || !CONFIG_SMP */
+static inline int dtb_wakeup_mailbox_setup(void)
+{
+ return -EOPNOTSUPP;
+}
+#endif /* CONFIG_X86_64 && CONFIG_SMP */
+
#ifdef CONFIG_X86_LOCAL_APIC
static void __init dtb_cpu_setup(void)
@@ -287,6 +333,7 @@ static void __init x86_dtb_parse_smp_config(void)
dtb_setup_hpet();
dtb_apic_setup();
+ dtb_wakeup_mailbox_setup();
}
void __init x86_flattree_get_config(void)
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
index ebefb77c37bbd..252c5827d0634 100644
--- a/arch/x86/kernel/x86_init.c
+++ b/arch/x86/kernel/x86_init.c
@@ -9,6 +9,7 @@
#include <linux/export.h>
#include <linux/pci.h>
#include <linux/acpi.h>
+#include <linux/sizes.h>
#include <asm/acpi.h>
#include <asm/bios_ebda.h>
@@ -69,6 +70,8 @@ struct x86_init_ops x86_init __initdata = {
.reserve_resources = reserve_standard_io_resources,
.memory_setup = e820__memory_setup_default,
.dmi_setup = dmi_setup,
+ /* Has to be under 1M so we can execute real-mode AP code. */
+ .realmode_limit = SZ_1M,
},
.mpparse = {
diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
index 88be32026768c..694d80a5c68e1 100644
--- a/arch/x86/realmode/init.c
+++ b/arch/x86/realmode/init.c
@@ -46,7 +46,7 @@ void load_trampoline_pgtable(void)
void __init reserve_real_mode(void)
{
- phys_addr_t mem;
+ phys_addr_t mem, limit = x86_init.resources.realmode_limit;
size_t size = real_mode_size_needed();
if (!size)
@@ -54,10 +54,9 @@ void __init reserve_real_mode(void)
WARN_ON(slab_is_available());
- /* Has to be under 1M so we can execute real-mode AP code. */
- mem = memblock_phys_alloc_range(size, PAGE_SIZE, 0, 1<<20);
+ mem = memblock_phys_alloc_range(size, PAGE_SIZE, 0, limit);
if (!mem)
- pr_info("No sub-1M memory is available for the trampoline\n");
+ pr_info("No memory below %pa for the real-mode trampoline\n", &limit);
else
set_real_mode_mem(mem);