linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>
To: linux-efi@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: ricardo.ner@intel.com, matt@codeblueprint.co.uk,
	Sai Praneeth <sai.praneeth.prakhya@intel.com>,
	Lee Chun-Yi <jlee@suse.com>, Al Stone <astone@redhat.com>,
	Borislav Petkov <bp@alien8.de>, Ingo Molnar <mingo@kernel.org>,
	Andy Lutomirski <luto@kernel.org>,
	Bhupesh Sharma <bhsharma@redhat.com>,
	Peter Zijlstra <peterz@infradead.org>,
	Ard Biesheuvel <ard.biesheuvel@linaro.org>
Subject: [PATCH V1 3/6] x86/efi: Permanently save the EFI_MEMORY_MAP passed by the firmware
Date: Wed,  8 Aug 2018 21:31:14 -0700	[thread overview]
Message-ID: <1533789077-16156-4-git-send-email-sai.praneeth.prakhya@intel.com> (raw)
In-Reply-To: <1533789077-16156-1-git-send-email-sai.praneeth.prakhya@intel.com>

From: Sai Praneeth <sai.praneeth.prakhya@intel.com>

The efi page fault handler that fixes up page faults caused by the
firmware needs the original memory map passed by the firmware. It looks
up this memory map to find the type of the memory region at which the
page fault occurred. Presently, EFI subsystem discards the original
memory map passed by the firmware and replaces it with a new memory map
that has only EFI_RUNTIME_SERVICES_<CODE/DATA> regions. But illegal
accesses by firmware can occur at any region. Hence, _only_ if
CONFIG_EFI_WARN_ON_ILLEGAL_ACCESSES is defined, create a backup of the
original memory map passed by the firmware, so that efi page fault
handler could detect/fix illegal accesses to *any* efi region.

Suggested-by: Matt Fleming <matt@codeblueprint.co.uk>
Based-on-code-from: Ricardo Neri <ricardo.neri@intel.com>
Signed-off-by: Sai Praneeth Prakhya <sai.praneeth.prakhya@intel.com>
Cc: Lee Chun-Yi <jlee@suse.com>
Cc: Al Stone <astone@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Bhupesh Sharma <bhsharma@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
---
 arch/x86/include/asm/efi.h     |  6 ++++++
 arch/x86/platform/efi/efi.c    |  2 ++
 arch/x86/platform/efi/quirks.c | 49 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 57 insertions(+)

diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 9b70743400f3..c97f2e955cab 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -142,6 +142,12 @@ 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);
 
+#ifdef CONFIG_EFI_WARN_ON_ILLEGAL_ACCESSES
+extern void __init efi_save_original_memmap(void);
+#else
+static inline void __init efi_save_original_memmap(void) { }
+#endif /* CONFIG_EFI_WARN_ON_ILLEGAL_ACCESSES */
+
 struct efi_setup_data {
 	u64 fw_vendor;
 	u64 runtime;
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 439c2c40bf03..7d18b7ed5d41 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -946,6 +946,8 @@ static void __init __efi_enter_virtual_mode(void)
 
 	pa = __pa(new_memmap);
 
+	efi_save_original_memmap();
+
 	/*
 	 * Unregister the early EFI memmap from efi_init() and install
 	 * the new EFI memory map that we are about to pass to the
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 844d31cb8a0c..84b213a1460a 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -654,3 +654,52 @@ int efi_capsule_setup_info(struct capsule_info *cap_info, void *kbuff,
 }
 
 #endif
+
+#ifdef CONFIG_EFI_WARN_ON_ILLEGAL_ACCESSES
+
+static bool original_memory_map_present;
+static struct efi_memory_map original_memory_map;
+
+/*
+ * The page fault handler that fixes up page faults caused by buggy
+ * firmware needs original memory map (memory map passed by firmware).
+ * Hence, build a new EFI memmap that has *all* entries and save it for
+ * later use.
+ */
+void __init efi_save_original_memmap(void)
+{
+	efi_memory_desc_t *md;
+	void *remapped_phys, *new_md;
+	phys_addr_t new_phys, new_size;
+
+	new_size = efi.memmap.desc_size * efi.memmap.nr_map;
+	new_phys = efi_memmap_alloc(efi.memmap.nr_map);
+	if (!new_phys) {
+		pr_err("Failed to allocate new EFI memmap\n");
+		return;
+	}
+
+	remapped_phys = memremap(new_phys, new_size, MEMREMAP_WB);
+	if (!remapped_phys) {
+		pr_err("Failed to remap new EFI memmap\n");
+		__free_pages(pfn_to_page(PHYS_PFN(new_phys)), get_order(new_size));
+		return;
+	}
+
+	new_md = remapped_phys;
+	for_each_efi_memory_desc(md) {
+		memcpy(new_md, md, efi.memmap.desc_size);
+		new_md += efi.memmap.desc_size;
+	}
+
+	original_memory_map.late = 1;
+	original_memory_map.phys_map = new_phys;
+	original_memory_map.map = remapped_phys;
+	original_memory_map.nr_map = efi.memmap.nr_map;
+	original_memory_map.desc_size = efi.memmap.desc_size;
+	original_memory_map.map_end = remapped_phys + new_size;
+	original_memory_map.desc_version = efi.memmap.desc_version;
+
+	original_memory_map_present = true;
+}
+#endif /* CONFIG_EFI_WARN_ON_ILLEGAL_ACCESSES */
-- 
2.7.4


  parent reply	other threads:[~2018-08-09  4:32 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-08-09  4:31 [PATCH V1 0/6] Add efi page fault handler to fix/recover from Sai Praneeth Prakhya
2018-08-09  4:31 ` [PATCH V1 1/6] efi: Make efi_rts_work accessible to efi page fault handler Sai Praneeth Prakhya
2018-08-09  4:31 ` [PATCH V1 2/6] x86/efi: Remove __init attribute from memory mapping functions Sai Praneeth Prakhya
2018-08-09  4:31 ` Sai Praneeth Prakhya [this message]
2018-08-09  4:31 ` [PATCH V1 4/6] x86/efi: Add efi page fault handler to fixup/recover from page faults caused by firmware Sai Praneeth Prakhya
2018-08-09  4:31 ` [PATCH V1 5/6] x86/mm: If in_atomic(), allocate pages without sleeping Sai Praneeth Prakhya
2018-08-09  4:31 ` [PATCH V1 6/6] x86/efi: Introduce EFI_WARN_ON_ILLEGAL_ACCESSES Sai Praneeth Prakhya
2018-08-10 11:42   ` Bhupesh Sharma
2018-08-10 17:34     ` Prakhya, Sai Praneeth
2018-08-10 18:30       ` Bhupesh Sharma

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1533789077-16156-4-git-send-email-sai.praneeth.prakhya@intel.com \
    --to=sai.praneeth.prakhya@intel.com \
    --cc=ard.biesheuvel@linaro.org \
    --cc=astone@redhat.com \
    --cc=bhsharma@redhat.com \
    --cc=bp@alien8.de \
    --cc=jlee@suse.com \
    --cc=linux-efi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=luto@kernel.org \
    --cc=matt@codeblueprint.co.uk \
    --cc=mingo@kernel.org \
    --cc=peterz@infradead.org \
    --cc=ricardo.ner@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).