Received: by 2002:a05:6a10:6d25:0:0:0:0 with SMTP id gq37csp1670377pxb; Mon, 13 Sep 2021 02:55:40 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxFFK53Sfl5O4v0l1kKh669rktpDvEWuRCgjk+Opq63zA76nfpcfJq4SJ2f9k9B8iclDYC+ X-Received: by 2002:a6b:24d:: with SMTP id 74mr8474537ioc.134.1631526939974; Mon, 13 Sep 2021 02:55:39 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1631526939; cv=none; d=google.com; s=arc-20160816; b=Ym05WBOx5rTkpT8dhjkbKtc6Ztry9ac7g0LgxJnCHiRuHv9Y3j9ulP2tP6AWzhEoUn 50m0NvzCl6GTpsl+LEixRIiIi7BsM8Br+RGODA2cSH5zUB9ggssS09+HKuCP5FbD4O+V fMNGEhb/rzlEdPYDYQM8a6Zz8PRZPRA2pOLQ9bhYfAmsRXTSxDJ8YPLC4zSpZQ/2fAgA WwjOifQCBvcnysBh5qlQ6FNRzuThIIctorLxuQcM5GJ6uWBjWlHgPaSwVziweVD/TVJJ ssuokH/LGnlt9jzwa2KvWiYi/L87XLoO1h+GTQBSiFN2zzLALftXKRLX12EScORByR+k 4TXA== 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 :message-id:date:subject:cc:to:from; bh=68RF8gybbjgAWxlKKiuBuaTXReCRzSqVp9WHZBcY8eU=; b=Yp0E7gX88uXnIuAhxpTMFvucoFwRZj20y8+g+/mXPYQZ4eQRatHz+vs5gE/8/9t2mK qBJdSsctLWiYNTc99rmANWMf3t4Ug9bqEIKWzPoCzyOCCF97Euqw4tvZaMFJjhnkjYOZ lck44JKPsrIscuuEIECKbeL88TBWXkF2HgoMTuoeyK2jmo8OsbrVeH1JxS3M/DR2w7oC 6AOFJcMqSkfKzRiisXaunEBNtVt5Ruc0GMvoIhT7Hj0b+xybsACaRfHqgaCoBMyncEPD my4q9245YCgIUv5uHroAqdALY+h8N+OllyV5xADZ/Pcuy1sltx69XmX9C0uYXmR8mHUS USrw== 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=8bytes.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id t10si6628544iof.42.2021.09.13.02.55.10; Mon, 13 Sep 2021 02:55:39 -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=8bytes.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238118AbhIMJyA (ORCPT + 99 others); Mon, 13 Sep 2021 05:54:00 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:38688 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234476AbhIMJx7 (ORCPT ); Mon, 13 Sep 2021 05:53:59 -0400 Received: from theia.8bytes.org (8bytes.org [IPv6:2a01:238:4383:600:38bc:a715:4b6d:a889]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4BB37C061574; Mon, 13 Sep 2021 02:52:43 -0700 (PDT) Received: from cap.home.8bytes.org (p549ada98.dip0.t-ipconnect.de [84.154.218.152]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by theia.8bytes.org (Postfix) with ESMTPSA id D045A7F; Mon, 13 Sep 2021 11:52:40 +0200 (CEST) From: Joerg Roedel To: x86@kernel.org Cc: Thomas Gleixner , Ingo Molnar , Borislav Petkov , hpa@zytor.com, jroedel@suse.de, Mike Rapoport , Andrew Morton , Brijesh Singh , linux-kernel@vger.kernel.org, joro@8bytes.org, stable@vger.kernel.org Subject: [PATCH] x86/64/mm: Map all kernel memory into trampoline_pgd Date: Mon, 13 Sep 2021 11:52:36 +0200 Message-Id: <20210913095236.24937-1-joro@8bytes.org> X-Mailer: git-send-email 2.33.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Joerg Roedel The trampoline_pgd only maps the 0xfffffff000000000-0xffffffffffffffff range of kernel memory (with 4-level paging). This range contains the kernels text+data+bss mappings and the module mapping space, but not the direct mapping and the vmalloc area. This is enough to get an application processors out of real-mode, but for code that switches back to real-mode the trampoline_pgd is missing important parts of the address space. For example, consider this code from arch/x86/kernel/reboot.c, function machine_real_restart() for a 64-bit kernel: #ifdef CONFIG_X86_32 load_cr3(initial_page_table); #else write_cr3(real_mode_header->trampoline_pgd); /* Exiting long mode will fail if CR4.PCIDE is set. */ if (boot_cpu_has(X86_FEATURE_PCID)) cr4_clear_bits(X86_CR4_PCIDE); #endif /* Jump to the identity-mapped low memory code */ #ifdef CONFIG_X86_32 asm volatile("jmpl *%0" : : "rm" (real_mode_header->machine_real_restart_asm), "a" (type)); #else asm volatile("ljmpl *%0" : : "m" (real_mode_header->machine_real_restart_asm), "D" (type)); #endif The code switches to the trampoline_pgd, which unmaps the direct mapping and also the kernel stack. The call to cr4_clear_bits() will find no stack and crash the machine. The real_mode_header pointer below points into the direct mapping, and dereferencing it also causes a crash. The reason this does not crash always is only that kernel mappings are global and the CR3 switch does not flush those mappings. But if theses mappings are not in the TLB already, the above code will crash before it can jump to the real-mode stub. Extend the trampoline_pgd to contain all kernel mappings to prevent these crashes and to make code which runs on this page-table more robust. Cc: stable@vger.kernel.org Signed-off-by: Joerg Roedel --- arch/x86/realmode/init.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c index 31b5856010cb..7a08c96cb42a 100644 --- a/arch/x86/realmode/init.c +++ b/arch/x86/realmode/init.c @@ -72,6 +72,7 @@ static void __init setup_real_mode(void) #ifdef CONFIG_X86_64 u64 *trampoline_pgd; u64 efer; + int i; #endif base = (unsigned char *)real_mode_header; @@ -128,8 +129,17 @@ static void __init setup_real_mode(void) trampoline_header->flags = 0; trampoline_pgd = (u64 *) __va(real_mode_header->trampoline_pgd); + + /* + * Map all of kernel memory into the trampoline PGD so that it includes + * the direct mapping and vmalloc space. This is needed to keep the + * stack and real_mode_header mapped when switching to this page table. + */ + for (i = pgd_index(__PAGE_OFFSET); i < PTRS_PER_PGD; i++) + trampoline_pgd[i] = init_top_pgt[i].pgd; + + /* Map the real mode stub as virtual == physical */ trampoline_pgd[0] = trampoline_pgd_entry.pgd; - trampoline_pgd[511] = init_top_pgt[511].pgd; #endif sme_sev_setup_real_mode(trampoline_header); -- 2.33.0