From patchwork Tue Apr 4 16:02:36 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ard Biesheuvel X-Patchwork-Id: 96739 Delivered-To: patch@linaro.org Received: by 10.140.89.233 with SMTP id v96csp263267qgd; Tue, 4 Apr 2017 09:03:34 -0700 (PDT) X-Received: by 10.98.76.140 with SMTP id e12mr23504103pfj.82.1491321814703; Tue, 04 Apr 2017 09:03:34 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id c1si7404096pge.59.2017.04.04.09.03.34; Tue, 04 Apr 2017 09:03:34 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754868AbdDDQDR (ORCPT + 25 others); Tue, 4 Apr 2017 12:03:17 -0400 Received: from mail-wm0-f54.google.com ([74.125.82.54]:37217 "EHLO mail-wm0-f54.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754800AbdDDQDN (ORCPT ); Tue, 4 Apr 2017 12:03:13 -0400 Received: by mail-wm0-f54.google.com with SMTP id x124so32343197wmf.0 for ; Tue, 04 Apr 2017 09:03:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=U+WcXNNxOdeqTQzwVPkjnWf2u5+ZA2LVDyTUb4kg0H0=; b=BdyYFI2uYpmc5atnR3ADJ6vsL3kpqNCrlX81P/f0IA4QvZQSqomvaYrPpuXogCC+kh dk9q3fuhfrm1Pskpd0rGL36kiZQ0UTX1oIZspos2o/WkvCzI9OD85voNSZQ7i5P4NM+G +f/fErblg+MVwCjddJpNuWW6JwbVTRKCZ1eU8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=U+WcXNNxOdeqTQzwVPkjnWf2u5+ZA2LVDyTUb4kg0H0=; b=KBj0nEDdV9z2HUf2CL7ElD87wn7J3+TfqdnM8lyO0ndQW1Jkw4uRxysUCAt79MtPUl l70biaQvliV8SCiwgB+v7ygI1VeatqUl43gijzcZGP1QU1GLPCFLl++A8HnO49Gc9qUl ldsmFw/RrAW3YwU5jLRRKOmdUxNGeMmetnrY+7n4/f4qr9nnI3rB9SRzReoXPfirfL6d HYderdxWFj8XreaybGVxYNgEQIBah0BcjTJKUKy0/+QfRd2/1wB6sdMGSM7yuE0br6Qh pJ1FdfP0wxK4LlHdt138Zt+zdCVI2VBUR5VawjK/FUX8izVVam1p7wsX20QaJP5+wzU7 h2nQ== X-Gm-Message-State: AFeK/H3kg+tfvrJx8XkRWqJNYk1sATvWbIxq8zVUAZ0JolPenmKl98bu2kf9ZmisgZn12qv7 X-Received: by 10.28.157.150 with SMTP id g144mr15612454wme.89.1491321791652; Tue, 04 Apr 2017 09:03:11 -0700 (PDT) Received: from localhost.localdomain ([160.163.145.113]) by smtp.gmail.com with ESMTPSA id z88sm19686465wrb.1.2017.04.04.09.03.09 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 04 Apr 2017 09:03:10 -0700 (PDT) From: Ard Biesheuvel To: linux-efi@vger.kernel.org, Ingo Molnar , Thomas Gleixner , "H . Peter Anvin" Cc: Andy Lutomirski , Ard Biesheuvel , linux-kernel@vger.kernel.org Subject: [PATCH 01/12] x86/efi: Clean up efi CR3 save/restore Date: Tue, 4 Apr 2017 17:02:36 +0100 Message-Id: <20170404160245.27812-3-ard.biesheuvel@linaro.org> X-Mailer: git-send-email 2.9.3 In-Reply-To: <20170404160245.27812-1-ard.biesheuvel@linaro.org> References: <20170404160245.27812-1-ard.biesheuvel@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Andy Lutomirski efi_call_phys_prolog() used to return a "pgd_t *" that meant one of three different things depending on kernel and system configuration. Clean it up so it uses a union and is more explicit about what's going on. Signed-off-by: Andy Lutomirski Cc: Ard Biesheuvel Cc: Borislav Petkov Cc: Andy Lutomirski Cc: Ingo Molnar Signed-off-by: Matt Fleming Signed-off-by: Ard Biesheuvel --- arch/x86/include/asm/efi.h | 17 +++++++++++++++-- arch/x86/platform/efi/efi.c | 6 +++--- arch/x86/platform/efi/efi_32.c | 12 ++++++------ arch/x86/platform/efi/efi_64.c | 22 ++++++++++++---------- 4 files changed, 36 insertions(+), 21 deletions(-) -- 2.9.3 diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 2f77bcefe6b4..6d74cc3802e6 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -111,11 +111,24 @@ extern void __iomem *__init efi_ioremap(unsigned long addr, unsigned long size, #endif /* CONFIG_X86_32 */ +union efi_saved_pgd { + /* + * If !EFI_OLD_MEMMAP or we're 32-bit, this is a verbatim saved CR3 + * value. + */ + unsigned long cr3; + +#ifdef CONFIG_X86_64 + /* If EFI_OLD_MEMMAP, this is a kmalloced copy of the pgd. */ + pgd_t *pgd; +#endif +}; + extern struct efi_scratch efi_scratch; extern void __init efi_set_executable(efi_memory_desc_t *md, bool executable); extern int __init efi_memblock_x86_reserve_range(void); -extern pgd_t * __init efi_call_phys_prolog(void); -extern void __init efi_call_phys_epilog(pgd_t *save_pgd); +extern union efi_saved_pgd __init efi_call_phys_prolog(void); +extern void __init efi_call_phys_epilog(union efi_saved_pgd saved_pgd); extern void __init efi_print_memmap(void); extern void __init efi_memory_uc(u64 addr, unsigned long size); extern void __init efi_map_region(efi_memory_desc_t *md); diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 565dff3c9a12..217dc166c649 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -81,9 +81,9 @@ static efi_status_t __init phys_efi_set_virtual_address_map( { efi_status_t status; unsigned long flags; - pgd_t *save_pgd; + union efi_saved_pgd saved_pgd; - save_pgd = efi_call_phys_prolog(); + saved_pgd = efi_call_phys_prolog(); /* Disable interrupts around EFI calls: */ local_irq_save(flags); @@ -92,7 +92,7 @@ static efi_status_t __init phys_efi_set_virtual_address_map( descriptor_version, virtual_map); local_irq_restore(flags); - efi_call_phys_epilog(save_pgd); + efi_call_phys_epilog(saved_pgd); return status; } diff --git a/arch/x86/platform/efi/efi_32.c b/arch/x86/platform/efi/efi_32.c index cef39b097649..9b1abcf6e7bb 100644 --- a/arch/x86/platform/efi/efi_32.c +++ b/arch/x86/platform/efi/efi_32.c @@ -58,13 +58,13 @@ void __init efi_map_region(efi_memory_desc_t *md) void __init efi_map_region_fixed(efi_memory_desc_t *md) {} void __init parse_efi_setup(u64 phys_addr, u32 data_len) {} -pgd_t * __init efi_call_phys_prolog(void) +union efi_saved_pgd __init efi_call_phys_prolog(void) { struct desc_ptr gdt_descr; - pgd_t *save_pgd; + union efi_saved_pgd saved_pgd; /* Current pgd is swapper_pg_dir, we'll restore it later: */ - save_pgd = swapper_pg_dir; + saved_pgd.cr3 = __pa(swapper_pg_dir); load_cr3(initial_page_table); __flush_tlb_all(); @@ -72,10 +72,10 @@ pgd_t * __init efi_call_phys_prolog(void) gdt_descr.size = GDT_SIZE - 1; load_gdt(&gdt_descr); - return save_pgd; + return saved_pgd; } -void __init efi_call_phys_epilog(pgd_t *save_pgd) +void __init efi_call_phys_epilog(union efi_saved_pgd saved_pgd) { struct desc_ptr gdt_descr; @@ -83,7 +83,7 @@ void __init efi_call_phys_epilog(pgd_t *save_pgd) gdt_descr.size = GDT_SIZE - 1; load_gdt(&gdt_descr); - load_cr3(save_pgd); + write_cr3(saved_pgd.cr3); __flush_tlb_all(); } diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index a4695da42d77..d56dd864fb1c 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c @@ -69,16 +69,16 @@ static void __init early_code_mapping_set_exec(int executable) } } -pgd_t * __init efi_call_phys_prolog(void) +union efi_saved_pgd __init efi_call_phys_prolog(void) { unsigned long vaddress; - pgd_t *save_pgd; + union efi_saved_pgd saved_pgd; int pgd; int n_pgds; if (!efi_enabled(EFI_OLD_MEMMAP)) { - save_pgd = (pgd_t *)read_cr3(); + saved_pgd.cr3 = read_cr3(); write_cr3((unsigned long)efi_scratch.efi_pgt); goto out; } @@ -86,20 +86,21 @@ pgd_t * __init efi_call_phys_prolog(void) early_code_mapping_set_exec(1); n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE); - save_pgd = kmalloc_array(n_pgds, sizeof(*save_pgd), GFP_KERNEL); + saved_pgd.pgd = kmalloc_array(n_pgds, sizeof(*saved_pgd.pgd), + GFP_KERNEL); for (pgd = 0; pgd < n_pgds; pgd++) { - save_pgd[pgd] = *pgd_offset_k(pgd * PGDIR_SIZE); + saved_pgd.pgd[pgd] = *pgd_offset_k(pgd * PGDIR_SIZE); vaddress = (unsigned long)__va(pgd * PGDIR_SIZE); set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), *pgd_offset_k(vaddress)); } out: __flush_tlb_all(); - return save_pgd; + return saved_pgd; } -void __init efi_call_phys_epilog(pgd_t *save_pgd) +void __init efi_call_phys_epilog(union efi_saved_pgd saved_pgd) { /* * After the lock is released, the original page table is restored. @@ -108,7 +109,7 @@ void __init efi_call_phys_epilog(pgd_t *save_pgd) int nr_pgds; if (!efi_enabled(EFI_OLD_MEMMAP)) { - write_cr3((unsigned long)save_pgd); + write_cr3(saved_pgd.cr3); __flush_tlb_all(); return; } @@ -116,9 +117,10 @@ void __init efi_call_phys_epilog(pgd_t *save_pgd) nr_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT) , PGDIR_SIZE); for (pgd_idx = 0; pgd_idx < nr_pgds; pgd_idx++) - set_pgd(pgd_offset_k(pgd_idx * PGDIR_SIZE), save_pgd[pgd_idx]); + set_pgd(pgd_offset_k(pgd_idx * PGDIR_SIZE), + saved_pgd.pgd[pgd_idx]); - kfree(save_pgd); + kfree(saved_pgd.pgd); __flush_tlb_all(); early_code_mapping_set_exec(0);