Received: by 2002:a05:6520:2586:b029:fa:41f3:c225 with SMTP id u6csp27255lky; Wed, 9 Jun 2021 14:53:20 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwnt80INjnqlB1wBpz7bOZv+BFN9F8y8hz/gILFY9yG9TDWY716hqSWHb5ANGRAbX2I/51I X-Received: by 2002:a17:906:2510:: with SMTP id i16mr1658137ejb.218.1623275599890; Wed, 09 Jun 2021 14:53:19 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1623275599; cv=none; d=google.com; s=arc-20160816; b=PKUrBpyk5PhxVxvKgILSPv0E1jepJF8QC13xm7rSTOd1zxBNQwoeyn44YTkaZLA/WE 3lljgF48seIKbD/ZQ2r3KsGFNb5/rupX7UDWX+VUcaAbCZ5LWDwGnXwFDi/3j8qAl8w6 3sTZFZeoEYRSCJUZqznl8wKKGeIUDe9vxEyrJbqZDL845dzBcCOXfSeo0qxRlADKeR9v WgutbJ/suWsaQjBu4A65eqe0OnjUk9DxdW4Rko8gRmBpRTurMbKxiR6WyNHR5G7RdGGK NQh6ovv34uv3JO0piea9njk9980TOPLmwJMJ/8I2dsBYmTXgW/oGaXpKYsVX8pVjsXOH u2Gw== 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 :ironport-sdr:ironport-sdr; bh=3uiT03NLvo+dFrV6Fb8/81xr5OgU5bk3Ng5QnIyLDbA=; b=E7DB378C4OKW9Gia9pOhVw4JG/Ry74jDO0ddckQjtz/vQoaMP1F03L4QV+7rIb/XHV XZmy1JFKCYIEUFMp57kj4IhMAgHHfCkRD9JiERLqsn16P0+SDvlL73MHm17XgdzhxVQv tf5cdxLUBIzLER9gO98QMUGg6EQmSwXh3SzIqUvSK/z9J7Z7xgojsSbJ5RDqlX6/au7F J89l7cu9MBGOyE7AF177tIy7e0lN3BYIM+U/sPsu00oSiyumWfykdLkgxi7tKbSZ9jfz rVebdAhE4HPZSNbtmR99QF9o+ugXnT64Zn0sY1B9iSUqgRiq/JAXJUx6Gp+INduldYai F4jQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id n24si631071eds.571.2021.06.09.14.52.56; Wed, 09 Jun 2021 14:53:19 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S229678AbhFIVxF (ORCPT + 99 others); Wed, 9 Jun 2021 17:53:05 -0400 Received: from mga03.intel.com ([134.134.136.65]:1471 "EHLO mga03.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229941AbhFIVxE (ORCPT ); Wed, 9 Jun 2021 17:53:04 -0400 IronPort-SDR: MbWhlUfLtqQF7pflsxHDIJPZI3Kh/yKbhal83qVVjhlk3AzX0J/nuChf65OLvXYfNJhzoluoZS YT+KCNoyn65A== X-IronPort-AV: E=McAfee;i="6200,9189,10010"; a="205207599" X-IronPort-AV: E=Sophos;i="5.83,261,1616482800"; d="scan'208";a="205207599" Received: from orsmga001.jf.intel.com ([10.7.209.18]) by orsmga103.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Jun 2021 14:51:06 -0700 IronPort-SDR: mjB6c7HVYEUvNSD9jmEVPAUPhYEZw6i3Fr9gAhcTwhdWuO3idZnA7p0+aAFCMivAnCdcpZv3I8 GgI04rye04pg== X-IronPort-AV: E=Sophos;i="5.83,261,1616482800"; d="scan'208";a="482553391" Received: from qwang4-mobl1.ccr.corp.intel.com (HELO skuppusw-desk1.amr.corp.intel.com) ([10.254.35.228]) by orsmga001-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 09 Jun 2021 14:51:05 -0700 From: Kuppuswamy Sathyanarayanan To: Thomas Gleixner , Ingo Molnar , Borislav Petkov , Peter Zijlstra , Andy Lutomirski Cc: Peter H Anvin , Dave Hansen , Tony Luck , Dan Williams , Andi Kleen , Kirill Shutemov , Sean Christopherson , Kuppuswamy Sathyanarayanan , x86@kernel.org, linux-kernel@vger.kernel.org, Sean Christopherson , Kai Huang Subject: [PATCH v1 1/5] x86/boot: Add a trampoline for APs booting in 64-bit mode Date: Wed, 9 Jun 2021 14:50:43 -0700 Message-Id: <20210609215047.1955866-2-sathyanarayanan.kuppuswamy@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210609215047.1955866-1-sathyanarayanan.kuppuswamy@linux.intel.com> References: <20210609215047.1955866-1-sathyanarayanan.kuppuswamy@linux.intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Sean Christopherson Add a trampoline for booting APs in 64-bit mode via a software handoff with BIOS, and use the new trampoline for the ACPI MP wake protocol used by TDX. You can find MADT MP wake protocol details in ACPI specification r6.4, sec 5.2.12.19. Extend the real mode IDT pointer by four bytes to support LIDT in 64-bit mode. For the GDT pointer, create a new entry as the existing storage for the pointer occupies the zero entry in the GDT itself. Reported-by: Kai Huang Signed-off-by: Sean Christopherson Reviewed-by: Andi Kleen Reviewed-by: Dan Williams Signed-off-by: Kuppuswamy Sathyanarayanan --- arch/x86/include/asm/realmode.h | 11 +++++++ arch/x86/kernel/smpboot.c | 2 +- arch/x86/realmode/rm/header.S | 1 + arch/x86/realmode/rm/trampoline_64.S | 38 ++++++++++++++++++++++++ arch/x86/realmode/rm/trampoline_common.S | 12 +++++++- 5 files changed, 62 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h index 5db5d083c873..0f707521b797 100644 --- a/arch/x86/include/asm/realmode.h +++ b/arch/x86/include/asm/realmode.h @@ -25,6 +25,7 @@ struct real_mode_header { u32 sev_es_trampoline_start; #endif #ifdef CONFIG_X86_64 + u32 trampoline_start64; u32 trampoline_pgd; #endif /* ACPI S3 wakeup */ @@ -88,6 +89,16 @@ static inline void set_real_mode_mem(phys_addr_t mem) real_mode_header = (struct real_mode_header *) __va(mem); } +/* Common helper function to get start IP address */ +static inline unsigned long get_trampoline_start_ip(struct real_mode_header *rmh) +{ +#ifdef CONFIG_X86_64 + if (is_tdx_guest()) + return rmh->trampoline_start64; +#endif + return rmh->trampoline_start; +} + void reserve_real_mode(void); #endif /* __ASSEMBLY__ */ diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 7770245cc7fa..3cde58849d70 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1033,7 +1033,7 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle, int *cpu0_nmi_registered) { /* start_ip had better be page-aligned! */ - unsigned long start_ip = real_mode_header->trampoline_start; + unsigned long start_ip = get_trampoline_start_ip(real_mode_header); unsigned long boot_error = 0; unsigned long timeout; diff --git a/arch/x86/realmode/rm/header.S b/arch/x86/realmode/rm/header.S index 8c1db5bf5d78..2eb62be6d256 100644 --- a/arch/x86/realmode/rm/header.S +++ b/arch/x86/realmode/rm/header.S @@ -24,6 +24,7 @@ SYM_DATA_START(real_mode_header) .long pa_sev_es_trampoline_start #endif #ifdef CONFIG_X86_64 + .long pa_trampoline_start64 .long pa_trampoline_pgd; #endif /* ACPI S3 wakeup */ diff --git a/arch/x86/realmode/rm/trampoline_64.S b/arch/x86/realmode/rm/trampoline_64.S index cc8391f86cdb..ae112a91592f 100644 --- a/arch/x86/realmode/rm/trampoline_64.S +++ b/arch/x86/realmode/rm/trampoline_64.S @@ -161,6 +161,19 @@ SYM_CODE_START(startup_32) ljmpl $__KERNEL_CS, $pa_startup_64 SYM_CODE_END(startup_32) +SYM_CODE_START(pa_trampoline_compat) + /* + * In compatibility mode. Prep ESP and DX for startup_32, then disable + * paging and complete the switch to legacy 32-bit mode. + */ + movl $rm_stack_end, %esp + movw $__KERNEL_DS, %dx + + movl $X86_CR0_PE, %eax + movl %eax, %cr0 + ljmpl $__KERNEL32_CS, $pa_startup_32 +SYM_CODE_END(pa_trampoline_compat) + .section ".text64","ax" .code64 .balign 4 @@ -169,6 +182,20 @@ SYM_CODE_START(startup_64) jmpq *tr_start(%rip) SYM_CODE_END(startup_64) +SYM_CODE_START(trampoline_start64) + /* + * APs start here on a direct transfer from 64-bit BIOS with identity + * mapped page tables. Load the kernel's GDT in order to gear down to + * 32-bit mode (to handle 4-level vs. 5-level paging), and to (re)load + * segment registers. Load the zero IDT so any fault triggers a + * shutdown instead of jumping back into BIOS. + */ + lidt tr_idt(%rip) + lgdt tr_gdt64(%rip) + + ljmpl *tr_compat(%rip) +SYM_CODE_END(trampoline_start64) + .section ".rodata","a" # Duplicate the global descriptor table # so the kernel can live anywhere @@ -182,6 +209,17 @@ SYM_DATA_START(tr_gdt) .quad 0x00cf93000000ffff # __KERNEL_DS SYM_DATA_END_LABEL(tr_gdt, SYM_L_LOCAL, tr_gdt_end) +SYM_DATA_START(tr_gdt64) + .short tr_gdt_end - tr_gdt - 1 # gdt limit + .long pa_tr_gdt + .long 0 +SYM_DATA_END(tr_gdt64) + +SYM_DATA_START(tr_compat) + .long pa_trampoline_compat + .short __KERNEL32_CS +SYM_DATA_END(tr_compat) + .bss .balign PAGE_SIZE SYM_DATA(trampoline_pgd, .space PAGE_SIZE) diff --git a/arch/x86/realmode/rm/trampoline_common.S b/arch/x86/realmode/rm/trampoline_common.S index 5033e640f957..4331c32c47f8 100644 --- a/arch/x86/realmode/rm/trampoline_common.S +++ b/arch/x86/realmode/rm/trampoline_common.S @@ -1,4 +1,14 @@ /* SPDX-License-Identifier: GPL-2.0 */ .section ".rodata","a" .balign 16 -SYM_DATA_LOCAL(tr_idt, .fill 1, 6, 0) + +/* + * When a bootloader hands off to the kernel in 32-bit mode an + * IDT with a 2-byte limit and 4-byte base is needed. When a boot + * loader hands off to a kernel 64-bit mode the base address + * extends to 8-bytes. Reserve enough space for either scenario. + */ +SYM_DATA_START_LOCAL(tr_idt) + .short 0 + .quad 0 +SYM_DATA_END(tr_idt) -- 2.25.1