Received: by 10.223.176.46 with SMTP id f43csp12739wra; Thu, 18 Jan 2018 13:08:49 -0800 (PST) X-Google-Smtp-Source: ACJfBovOrDpTTZ8uWvrvk6yAGSBdEVjwbD+CjqH1LZloJ4GBMNfEUH99N837kd6V2hua6eltYl+e X-Received: by 10.99.38.6 with SMTP id m6mr38704269pgm.12.1516309729282; Thu, 18 Jan 2018 13:08:49 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1516309729; cv=none; d=google.com; s=arc-20160816; b=JXaSeqAwRVq5DkUcvO8Zi7PKaq4mUFQeQGDTowW/gPilTyfvZ0cppGaqEV7IXx52V4 Bfeol6RBjRohwUihLLQTtakWPKRMZxJvqRoQiYGVAYMetTSDGtIRw4LwEPzHYWIY5hg8 YZGMQ+irYct6jkpuuH1KZUuFeHK9gHBKwUZumd5KbWj0WP2JFsapuFv60XCL8U7do6T/ i5uwd8JcrUQUNvGxlZICBwrxt0nFPuylYqEiXZO4vERE+7nQwmElhnbRL2Uh0cP/j+3u 8IX54QQwo5kqebdWCCF7nVapbYMj9XpwwVIwc5lNOqmbTNLMQHvSwtfyu1mVTvHPFfE3 2Z1w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:message-id:date:subject:cc:to:from :arc-authentication-results; bh=n7vmsMKmBuVAWoQXh6SsytjAFijyjG84ugEu86DS3gI=; b=xX408+pd1x/ub+8JIn2RLJAocf+RmEsLn8CXm3SxSqUP0nSnDt3BPBCLyy9vsNKCXs r6ZrOqw6LMNwu1lT75Td6vsiXCmX+CkhwP0GF7Ye371wQvPxaVnnUlQ4LOffNpJXxs55 7La662Xp7wD9yhknGw6nZsXC2kuXRQO/czDEAS8Q79p5YjnAJpTFlrh+GGbuGWv1oo89 UO2ui69QhWwdy1tmCtQ7e8syul3lA2rV2HWyXjRYxlEY7p2MfWGeE/UiZi8I0PCJhcND jyg49S2+AAVI9GfqvF7Oy0rkhjbLPsc3+UGfzUJyz56j/7gO0qIf+u1RaxBhc+YVY/0z K9aQ== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id x10si6888480pgc.192.2018.01.18.13.08.34; Thu, 18 Jan 2018 13:08:49 -0800 (PST) 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; 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 Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S932866AbeARVHv (ORCPT + 99 others); Thu, 18 Jan 2018 16:07:51 -0500 Received: from mga11.intel.com ([192.55.52.93]:58753 "EHLO mga11.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S932837AbeARVHm (ORCPT ); Thu, 18 Jan 2018 16:07:42 -0500 X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga007.jf.intel.com ([10.7.209.58]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 18 Jan 2018 13:07:42 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.46,378,1511856000"; d="scan'208";a="10845406" Received: from saipraneeth.sc.intel.com ([143.183.140.145]) by orsmga007.jf.intel.com with ESMTP; 18 Jan 2018 13:07:41 -0800 From: Sai Praneeth Prakhya To: linux-efi@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Sai Praneeth , "Lee, Chun-Yi" , Borislav Petkov , Tony Luck , Andy Lutomirski , "Michael S. Tsirkin" , Bhupesh Sharma , Ricardo Neri , Matt Fleming , Ard Biesheuvel , Ravi Shankar Subject: [PATCH V4 3/3] x86/efi: Use efi_switch_mm() rather than manually twiddling with %cr3 Date: Thu, 18 Jan 2018 13:01:45 -0800 Message-Id: <1516309305-24066-1-git-send-email-sai.praneeth.prakhya@intel.com> X-Mailer: git-send-email 2.1.4 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Sai Praneeth Use helper function (efi_switch_mm()) to switch to/from efi_mm. We switch to efi_mm before calling 1. efi_set_virtual_address_map() and 2. Invoking any efi_runtime_service() Likewise, we need to switch back to previous mm (mm context stolen by efi_mm) after the above calls return successfully. We can use efi_switch_mm() helper function only with x86_64 kernel and "efi=old_map" disabled because, x86_32 and efi=old_map doesn't use efi_pgd, rather they use swapper_pg_dir. Signed-off-by: Sai Praneeth Prakhya Cc: Lee, Chun-Yi Cc: Borislav Petkov Cc: Tony Luck Cc: Andy Lutomirski Cc: Michael S. Tsirkin Cc: Bhupesh Sharma Cc: Ricardo Neri Cc: Matt Fleming Cc: Ard Biesheuvel Cc: Ravi Shankar Tested-by: Bhupesh Sharma --- arch/x86/include/asm/efi.h | 25 +++++++++------------- arch/x86/platform/efi/efi_64.c | 40 +++++++++++++++++++----------------- arch/x86/platform/efi/efi_thunk_64.S | 2 +- 3 files changed, 32 insertions(+), 35 deletions(-) diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h index 00f977ddd718..cda9940bed7a 100644 --- a/arch/x86/include/asm/efi.h +++ b/arch/x86/include/asm/efi.h @@ -62,14 +62,13 @@ extern asmlinkage u64 efi_call(void *fp, ...); #define efi_call_phys(f, args...) efi_call((f), args) /* - * Scratch space used for switching the pagetable in the EFI stub + * struct efi_scratch - Scratch space used while switching to/from efi_mm + * @phys_stack: stack used during EFI Mixed Mode + * @prev_mm: store/restore stolen mm_struct while switching to/from efi_mm */ struct efi_scratch { - u64 r15; - u64 prev_cr3; - pgd_t *efi_pgt; - bool use_pgd; - u64 phys_stack; + u64 phys_stack; + struct mm_struct *prev_mm; } __packed; #define arch_efi_call_virt_setup() \ @@ -78,11 +77,8 @@ struct efi_scratch { preempt_disable(); \ __kernel_fpu_begin(); \ \ - if (efi_scratch.use_pgd) { \ - efi_scratch.prev_cr3 = __read_cr3(); \ - write_cr3((unsigned long)efi_scratch.efi_pgt); \ - __flush_tlb_all(); \ - } \ + if (!efi_enabled(EFI_OLD_MEMMAP)) \ + efi_switch_mm(&efi_mm); \ }) #define arch_efi_call_virt(p, f, args...) \ @@ -90,10 +86,8 @@ struct efi_scratch { #define arch_efi_call_virt_teardown() \ ({ \ - if (efi_scratch.use_pgd) { \ - write_cr3(efi_scratch.prev_cr3); \ - __flush_tlb_all(); \ - } \ + if (!efi_enabled(EFI_OLD_MEMMAP)) \ + efi_switch_mm(efi_scratch.prev_mm); \ \ __kernel_fpu_end(); \ preempt_enable(); \ @@ -135,6 +129,7 @@ extern void __init efi_dump_pagetable(void); extern void __init efi_apply_memmap_quirks(void); extern int __init efi_reuse_config(u64 tables, int nr_tables); extern void efi_delete_dummy_variable(void); +extern void efi_switch_mm(struct mm_struct *mm); struct efi_setup_data { u64 fw_vendor; diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index c93f59731608..d6892ad2a693 100644 --- a/arch/x86/platform/efi/efi_64.c +++ b/arch/x86/platform/efi/efi_64.c @@ -82,9 +82,8 @@ pgd_t * __init efi_call_phys_prolog(void) int n_pgds, i, j; if (!efi_enabled(EFI_OLD_MEMMAP)) { - save_pgd = (pgd_t *)__read_cr3(); - write_cr3((unsigned long)efi_scratch.efi_pgt); - goto out; + efi_switch_mm(&efi_mm); + return NULL; } early_code_mapping_set_exec(1); @@ -156,8 +155,7 @@ void __init efi_call_phys_epilog(pgd_t *save_pgd) pud_t *pud; if (!efi_enabled(EFI_OLD_MEMMAP)) { - write_cr3((unsigned long)save_pgd); - __flush_tlb_all(); + efi_switch_mm(efi_scratch.prev_mm); return; } @@ -346,13 +344,6 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages) return 0; /* - * Since the PGD is encrypted, set the encryption mask so that when - * this value is loaded into cr3 the PGD will be decrypted during - * the pagetable walk. - */ - efi_scratch.efi_pgt = (pgd_t *)__sme_pa(pgd); - - /* * It can happen that the physical address of new_memmap lands in memory * which is not mapped in the EFI page table. Therefore we need to go * and ident-map those pages containing the map before calling @@ -365,8 +356,6 @@ int __init efi_setup_page_tables(unsigned long pa_memmap, unsigned num_pages) return 1; } - efi_scratch.use_pgd = true; - /* * Certain firmware versions are way too sentimential and still believe * they are exclusive and unquestionable owners of the first physical page, @@ -625,6 +614,22 @@ void __init efi_dump_pagetable(void) #endif } +/* + * Makes the calling thread switch to/from efi_mm context. Can be used + * for SetVirtualAddressMap() i.e. current->active_mm == init_mm as well + * as during efi runtime calls i.e current->active_mm == current_mm. + * We are not mm_dropping()/mm_grabbing() any mm, because we are not + * losing/creating any references. + */ +void efi_switch_mm(struct mm_struct *mm) +{ + task_lock(current); + efi_scratch.prev_mm = current->active_mm; + current->active_mm = mm; + switch_mm(efi_scratch.prev_mm, mm, NULL); + task_unlock(current); +} + #ifdef CONFIG_EFI_MIXED extern efi_status_t efi64_thunk(u32, ...); @@ -678,16 +683,13 @@ efi_status_t efi_thunk_set_virtual_address_map( efi_sync_low_kernel_mappings(); local_irq_save(flags); - efi_scratch.prev_cr3 = __read_cr3(); - write_cr3((unsigned long)efi_scratch.efi_pgt); - __flush_tlb_all(); + efi_switch_mm(&efi_mm); func = (u32)(unsigned long)phys_set_virtual_address_map; status = efi64_thunk(func, memory_map_size, descriptor_size, descriptor_version, virtual_map); - write_cr3(efi_scratch.prev_cr3); - __flush_tlb_all(); + efi_switch_mm(efi_scratch.prev_mm); local_irq_restore(flags); return status; diff --git a/arch/x86/platform/efi/efi_thunk_64.S b/arch/x86/platform/efi/efi_thunk_64.S index 189b218da87c..46c58b08739c 100644 --- a/arch/x86/platform/efi/efi_thunk_64.S +++ b/arch/x86/platform/efi/efi_thunk_64.S @@ -33,7 +33,7 @@ ENTRY(efi64_thunk) * Switch to 1:1 mapped 32-bit stack pointer. */ movq %rsp, efi_saved_sp(%rip) - movq efi_scratch+25(%rip), %rsp + movq efi_scratch(%rip), %rsp /* * Calculate the physical address of the kernel text. -- 2.1.4