linux-stable/arch/x86/include/asm/realmode.h
Sean Christopherson ff2e64684f x86/boot: Add a trampoline for booting APs via firmware handoff
Historically, x86 platforms have booted secondary processors (APs)
using INIT followed by the start up IPI (SIPI) messages. In regular
VMs, this boot sequence is supported by the VMM emulation. But such a
wakeup model is fatal for secure VMs like TDX in which VMM is an
untrusted entity. To address this issue, a new wakeup model was added
in ACPI v6.4, in which firmware (like TDX virtual BIOS) will help boot
the APs. More details about this wakeup model can be found in ACPI
specification v6.4, the section titled "Multiprocessor Wakeup Structure".

Since the existing trampoline code requires processors to boot in real
mode with 16-bit addressing, it will not work for this wakeup model
(because it boots the AP in 64-bit mode). To handle it, extend the
trampoline code to support 64-bit mode firmware handoff. Also, extend
IDT and GDT pointers to support 64-bit mode hand off.

There is no TDX-specific detection for this new boot method. The kernel
will rely on it as the sole boot method whenever the new ACPI structure
is present.

The ACPI table parser for the MADT multiprocessor wake up structure and
the wakeup method that uses this structure will be added by the following
patch in this series.

Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: Andi Kleen <ak@linux.intel.com>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/20220405232939.73860-21-kirill.shutemov@linux.intel.com
2022-04-07 08:27:52 -07:00

97 lines
2.1 KiB
C

/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ARCH_X86_REALMODE_H
#define _ARCH_X86_REALMODE_H
/*
* Flag bit definitions for use with the flags field of the trampoline header
* in the CONFIG_X86_64 variant.
*/
#define TH_FLAGS_SME_ACTIVE_BIT 0
#define TH_FLAGS_SME_ACTIVE BIT(TH_FLAGS_SME_ACTIVE_BIT)
#ifndef __ASSEMBLY__
#include <linux/types.h>
#include <asm/io.h>
/* This must match data at realmode/rm/header.S */
struct real_mode_header {
u32 text_start;
u32 ro_end;
/* SMP trampoline */
u32 trampoline_start;
u32 trampoline_header;
#ifdef CONFIG_AMD_MEM_ENCRYPT
u32 sev_es_trampoline_start;
#endif
#ifdef CONFIG_X86_64
u32 trampoline_start64;
u32 trampoline_pgd;
#endif
/* ACPI S3 wakeup */
#ifdef CONFIG_ACPI_SLEEP
u32 wakeup_start;
u32 wakeup_header;
#endif
/* APM/BIOS reboot */
u32 machine_real_restart_asm;
#ifdef CONFIG_X86_64
u32 machine_real_restart_seg;
#endif
};
/* This must match data at realmode/rm/trampoline_{32,64}.S */
struct trampoline_header {
#ifdef CONFIG_X86_32
u32 start;
u16 gdt_pad;
u16 gdt_limit;
u32 gdt_base;
#else
u64 start;
u64 efer;
u32 cr4;
u32 flags;
#endif
};
extern struct real_mode_header *real_mode_header;
extern unsigned char real_mode_blob_end[];
extern unsigned long initial_code;
extern unsigned long initial_gs;
extern unsigned long initial_stack;
#ifdef CONFIG_AMD_MEM_ENCRYPT
extern unsigned long initial_vc_handler;
#endif
extern unsigned char real_mode_blob[];
extern unsigned char real_mode_relocs[];
#ifdef CONFIG_X86_32
extern unsigned char startup_32_smp[];
extern unsigned char boot_gdt[];
#else
extern unsigned char secondary_startup_64[];
extern unsigned char secondary_startup_64_no_verify[];
#endif
static inline size_t real_mode_size_needed(void)
{
if (real_mode_header)
return 0; /* already allocated. */
return ALIGN(real_mode_blob_end - real_mode_blob, PAGE_SIZE);
}
static inline void set_real_mode_mem(phys_addr_t mem)
{
real_mode_header = (struct real_mode_header *) __va(mem);
}
void reserve_real_mode(void);
void load_trampoline_pgtable(void);
#endif /* __ASSEMBLY__ */
#endif /* _ARCH_X86_REALMODE_H */