All of lore.kernel.org
 help / color / mirror / Atom feed
From: Matt Fleming <matt@codeblueprint.co.uk>
To: Ingo Molnar <mingo@kernel.org>,
	Thomas Gleixner <tglx@linutronix.de>,
	"H . Peter Anvin" <hpa@zytor.com>
Cc: Matt Fleming <matt@codeblueprint.co.uk>,
	Ard Biesheuvel <ard.biesheuvel@linaro.org>,
	linux-kernel@vger.kernel.org, linux-efi@vger.kernel.org,
	Borislav Petkov <bp@alien8.de>, Dave Young <dyoung@redhat.com>,
	Leif Lindholm <leif.lindholm@linaro.org>,
	Mark Rutland <mark.rutland@arm.com>,
	Peter Jones <pjones@redhat.com>
Subject: [PATCH 03/29] efi: Refactor efi_memmap_init_early() into arch-neutral code
Date: Fri,  9 Sep 2016 16:18:25 +0100	[thread overview]
Message-ID: <20160909151851.27577-4-matt@codeblueprint.co.uk> (raw)
In-Reply-To: <20160909151851.27577-1-matt@codeblueprint.co.uk>

Every EFI architecture apart from ia64 needs to setup the EFI memory
map at efi.memmap, and the code for doing that is essentially the same
across all implementations. Therefore, it makes sense to factor this
out into the common code under drivers/firmware/efi/.

The only slight variation is the data structure out of which we pull
the initial memory map information, such as physical address, memory
descriptor size and version, etc. We can address this by passing a
generic data structure (struct efi_memory_map_data) as the argument to
efi_memmap_init_early() which contains the minimum info required for
initialising the memory map.

In the process, this patch also fixes a few undesirable implementation
differences:

 - ARM and arm64 were failing to clear the EFI_MEMMAP bit when
   unmapping the early EFI memory map. EFI_MEMMAP indicates whether
   the EFI memory map is mapped (not the regions contained within) and
   can be traversed.  It's more correct to set the bit as soon as we
   memremap() the passed in EFI memmap.

 - Rename efi_unmmap_memmap() to efi_memmap_unmap() to adhere to the
   regular naming scheme.

This patch also uses a read-write mapping for the memory map instead
of the read-only mapping currently used on ARM and arm64. x86 needs
the ability to update the memory map in-place when assigning virtual
addresses to regions (efi_map_region()) and tagging regions when
reserving boot services (efi_reserve_boot_services()).

There's no way for the generic fake_mem code to know which mapping to
use without introducing some arch-specific constant/hook, so just use
read-write since read-only is of dubious value for the EFI memory map.

Tested-by: Dave Young <dyoung@redhat.com> [kexec/kdump]
Tested-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> [arm]
Acked-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Leif Lindholm <leif.lindholm@linaro.org>
Cc: Peter Jones <pjones@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Matt Fleming <matt@codeblueprint.co.uk>
---
 arch/x86/include/asm/efi.h         |  1 -
 arch/x86/platform/efi/efi.c        | 66 ++++++++++----------------------------
 arch/x86/platform/efi/quirks.c     |  4 +--
 drivers/firmware/efi/arm-init.c    | 17 +++++-----
 drivers/firmware/efi/arm-runtime.c |  2 +-
 drivers/firmware/efi/efi.c         | 46 ++++++++++++++++++++++++++
 drivers/firmware/efi/fake_mem.c    | 15 +++++----
 include/linux/efi.h                | 16 +++++++++
 8 files changed, 99 insertions(+), 68 deletions(-)

diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index d0bb76d81402..4630e2bfa8fb 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -117,7 +117,6 @@ 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 void __init efi_print_memmap(void);
-extern void __init efi_unmap_memmap(void);
 extern void __init efi_memory_uc(u64 addr, unsigned long size);
 extern void __init efi_map_region(efi_memory_desc_t *md);
 extern void __init efi_map_region_fixed(efi_memory_desc_t *md);
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 625ec729b4e8..5ccde8b6cdd1 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -172,7 +172,9 @@ static void __init do_add_efi_memmap(void)
 int __init efi_memblock_x86_reserve_range(void)
 {
 	struct efi_info *e = &boot_params.efi_info;
+	struct efi_memory_map_data data;
 	phys_addr_t pmap;
+	int rv;
 
 	if (efi_enabled(EFI_PARAVIRT))
 		return 0;
@@ -187,11 +189,17 @@ int __init efi_memblock_x86_reserve_range(void)
 #else
 	pmap = (e->efi_memmap |	((__u64)e->efi_memmap_hi << 32));
 #endif
-	efi.memmap.phys_map	= pmap;
-	efi.memmap.nr_map	= e->efi_memmap_size /
-				  e->efi_memdesc_size;
-	efi.memmap.desc_size	= e->efi_memdesc_size;
-	efi.memmap.desc_version	= e->efi_memdesc_version;
+	data.phys_map		= pmap;
+	data.size 		= e->efi_memmap_size;
+	data.desc_size		= e->efi_memdesc_size;
+	data.desc_version	= e->efi_memdesc_version;
+
+	rv = efi_memmap_init_early(&data);
+	if (rv)
+		return rv;
+
+	if (add_efi_memmap)
+		do_add_efi_memmap();
 
 	WARN(efi.memmap.desc_version != 1,
 	     "Unexpected EFI_MEMORY_DESCRIPTOR version %ld",
@@ -218,19 +226,6 @@ void __init efi_print_memmap(void)
 	}
 }
 
-void __init efi_unmap_memmap(void)
-{
-	unsigned long size;
-
-	clear_bit(EFI_MEMMAP, &efi.flags);
-
-	size = efi.memmap.nr_map * efi.memmap.desc_size;
-	if (efi.memmap.map) {
-		early_memunmap(efi.memmap.map, size);
-		efi.memmap.map = NULL;
-	}
-}
-
 static int __init efi_systab_init(void *phys)
 {
 	if (efi_enabled(EFI_64BIT)) {
@@ -414,33 +409,6 @@ static int __init efi_runtime_init(void)
 	return 0;
 }
 
-static int __init efi_memmap_init(void)
-{
-	unsigned long addr, size;
-
-	if (efi_enabled(EFI_PARAVIRT))
-		return 0;
-
-	/* Map the EFI memory map */
-	size = efi.memmap.nr_map * efi.memmap.desc_size;
-	addr = (unsigned long)efi.memmap.phys_map;
-
-	efi.memmap.map = early_memremap(addr, size);
-	if (efi.memmap.map == NULL) {
-		pr_err("Could not map the memory map!\n");
-		return -ENOMEM;
-	}
-
-	efi.memmap.map_end = efi.memmap.map + size;
-
-	if (add_efi_memmap)
-		do_add_efi_memmap();
-
-	set_bit(EFI_MEMMAP, &efi.flags);
-
-	return 0;
-}
-
 void __init efi_init(void)
 {
 	efi_char16_t *c16;
@@ -498,11 +466,11 @@ void __init efi_init(void)
 	if (!efi_runtime_supported())
 		pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n");
 	else {
-		if (efi_runtime_disabled() || efi_runtime_init())
+		if (efi_runtime_disabled() || efi_runtime_init()) {
+			efi_memmap_unmap();
 			return;
+		}
 	}
-	if (efi_memmap_init())
-		return;
 
 	if (efi_enabled(EFI_DBG))
 		efi_print_memmap();
@@ -839,7 +807,7 @@ static void __init kexec_enter_virtual_mode(void)
 	 * non-native EFI
 	 */
 	if (!efi_is_native()) {
-		efi_unmap_memmap();
+		efi_memmap_unmap();
 		clear_bit(EFI_RUNTIME_SERVICES, &efi.flags);
 		return;
 	}
diff --git a/arch/x86/platform/efi/quirks.c b/arch/x86/platform/efi/quirks.c
index 89d1146f5a6f..47b99108ff8e 100644
--- a/arch/x86/platform/efi/quirks.c
+++ b/arch/x86/platform/efi/quirks.c
@@ -287,7 +287,7 @@ void __init efi_free_boot_services(void)
 		free_bootmem_late(start, size);
 	}
 
-	efi_unmap_memmap();
+	efi_memmap_unmap();
 }
 
 /*
@@ -365,7 +365,7 @@ void __init efi_apply_memmap_quirks(void)
 	 */
 	if (!efi_runtime_supported()) {
 		pr_info("Setup done, disabling due to 32/64-bit mismatch\n");
-		efi_unmap_memmap();
+		efi_memmap_unmap();
 	}
 
 	/* UV2+ BIOS has a fix for this issue.  UV1 still needs the quirk. */
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index c49d50e68aee..5a2df3fefccc 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -211,12 +211,11 @@ static __init void reserve_regions(void)
 			memblock_mark_nomap(paddr, size);
 
 	}
-
-	set_bit(EFI_MEMMAP, &efi.flags);
 }
 
 void __init efi_init(void)
 {
+	struct efi_memory_map_data data;
 	struct efi_fdt_params params;
 
 	/* Grab UEFI information placed in FDT by stub */
@@ -225,9 +224,12 @@ void __init efi_init(void)
 
 	efi_system_table = params.system_table;
 
-	efi.memmap.phys_map = params.mmap;
-	efi.memmap.map = early_memremap_ro(params.mmap, params.mmap_size);
-	if (efi.memmap.map == NULL) {
+	data.desc_version = params.desc_ver;
+	data.desc_size = params.desc_size;
+	data.size = params.mmap_size;
+	data.phys_map = params.mmap;
+
+	if (efi_memmap_init_early(&data) < 0) {
 		/*
 		* If we are booting via UEFI, the UEFI memory map is the only
 		* description of memory we have, so there is little point in
@@ -235,9 +237,6 @@ void __init efi_init(void)
 		*/
 		panic("Unable to map EFI memory map.\n");
 	}
-	efi.memmap.map_end = efi.memmap.map + params.mmap_size;
-	efi.memmap.desc_size = params.desc_size;
-	efi.memmap.desc_version = params.desc_ver;
 
 	WARN(efi.memmap.desc_version != 1,
 	     "Unexpected EFI_MEMORY_DESCRIPTOR version %ld",
@@ -248,7 +247,7 @@ void __init efi_init(void)
 
 	reserve_regions();
 	efi_memattr_init();
-	early_memunmap(efi.memmap.map, params.mmap_size);
+	efi_memmap_unmap();
 
 	memblock_reserve(params.mmap & PAGE_MASK,
 			 PAGE_ALIGN(params.mmap_size +
diff --git a/drivers/firmware/efi/arm-runtime.c b/drivers/firmware/efi/arm-runtime.c
index c394b81fe452..eedb30351a68 100644
--- a/drivers/firmware/efi/arm-runtime.c
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -114,7 +114,7 @@ static int __init arm_enable_runtime_services(void)
 
 	pr_info("Remapping and enabling EFI services.\n");
 
-	mapsize = efi.memmap.map_end - efi.memmap.map;
+	mapsize = efi.memmap.desc_size * efi.memmap.nr_map;
 
 	efi.memmap.map = memremap(efi.memmap.phys_map, mapsize, MEMREMAP_WB);
 	if (!efi.memmap.map) {
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 5a2631af7410..c1879999abe7 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -544,6 +544,52 @@ int __init efi_config_init(efi_config_table_type_t *arch_tables)
 	return ret;
 }
 
+/**
+ * efi_memmap_init_early - Map the EFI memory map data structure
+ * @data: EFI memory map data
+ *
+ * Use early_memremap() to map the passed in EFI memory map and assign
+ * it to efi.memmap.
+ */
+int __init efi_memmap_init_early(struct efi_memory_map_data *data)
+{
+	struct efi_memory_map map;
+
+	if (efi_enabled(EFI_PARAVIRT))
+		return 0;
+
+	map.phys_map = data->phys_map;
+
+	map.map = early_memremap(data->phys_map, data->size);
+	if (!map.map) {
+		pr_err("Could not map the memory map!\n");
+		return -ENOMEM;
+	}
+
+	map.nr_map = data->size / data->desc_size;
+	map.map_end = map.map + data->size;
+
+	map.desc_version = data->desc_version;
+	map.desc_size = data->desc_size;
+
+	set_bit(EFI_MEMMAP, &efi.flags);
+
+	efi.memmap = map;
+
+	return 0;
+}
+
+void __init efi_memmap_unmap(void)
+{
+	unsigned long size;
+
+	size = efi.memmap.desc_size * efi.memmap.nr_map;
+
+	early_memunmap(efi.memmap.map, size);
+	efi.memmap.map = NULL;
+	clear_bit(EFI_MEMMAP, &efi.flags);
+}
+
 #ifdef CONFIG_EFI_VARS_MODULE
 static int __init efi_load_efivars(void)
 {
diff --git a/drivers/firmware/efi/fake_mem.c b/drivers/firmware/efi/fake_mem.c
index c437388a7b85..939eec47139f 100644
--- a/drivers/firmware/efi/fake_mem.c
+++ b/drivers/firmware/efi/fake_mem.c
@@ -57,6 +57,7 @@ static int __init cmp_fake_mem(const void *x1, const void *x2)
 void __init efi_fake_memmap(void)
 {
 	u64 start, end, m_start, m_end, m_attr;
+	struct efi_memory_map_data data;
 	int new_nr_map = efi.memmap.nr_map;
 	efi_memory_desc_t *md;
 	phys_addr_t new_memmap_phy;
@@ -180,12 +181,14 @@ void __init efi_fake_memmap(void)
 	}
 
 	/* swap into new EFI memmap */
-	efi_unmap_memmap();
-	efi.memmap.map = new_memmap;
-	efi.memmap.phys_map = new_memmap_phy;
-	efi.memmap.nr_map = new_nr_map;
-	efi.memmap.map_end = efi.memmap.map + efi.memmap.nr_map * efi.memmap.desc_size;
-	set_bit(EFI_MEMMAP, &efi.flags);
+	early_memunmap(new_memmap, efi.memmap.desc_size * new_nr_map);
+	efi_memmap_unmap();
+
+	data.phys_map = new_memmap_phy;
+	data.size = efi.memmap.desc_size * new_nr_map;
+	data.desc_version = efi.memmap.desc_version;
+	data.desc_size = efi.memmap.desc_size;
+	efi_memmap_init_early(&data);
 
 	/* print new EFI memmap */
 	efi_print_memmap();
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 7f5a58225385..d862d4998580 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -669,6 +669,18 @@ typedef struct {
 	unsigned long tables;
 } efi_system_table_t;
 
+/*
+ * Architecture independent structure for describing a memory map for the
+ * benefit of efi_memmap_init_early(), saving us the need to pass four
+ * parameters.
+ */
+struct efi_memory_map_data {
+	phys_addr_t phys_map;
+	unsigned long size;
+	unsigned long desc_version;
+	unsigned long desc_size;
+};
+
 struct efi_memory_map {
 	phys_addr_t phys_map;
 	void *map;
@@ -900,6 +912,10 @@ static inline efi_status_t efi_query_variable_store(u32 attributes,
 }
 #endif
 extern void __iomem *efi_lookup_mapped_addr(u64 phys_addr);
+
+extern int __init efi_memmap_init_early(struct efi_memory_map_data *data);
+extern void __init efi_memmap_unmap(void);
+
 extern int efi_config_init(efi_config_table_type_t *arch_tables);
 #ifdef CONFIG_EFI_ESRT
 extern void __init efi_esrt_init(void);
-- 
2.9.3

  parent reply	other threads:[~2016-09-09 15:25 UTC|newest]

Thread overview: 57+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-09 15:18 [GIT PULL 00/29] EFI changes for v4.9 Matt Fleming
2016-09-09 15:18 ` Matt Fleming
2016-09-09 15:18 ` [PATCH 01/29] x86/efi: Test for EFI_MEMMAP functionality when iterating EFI memmap Matt Fleming
2016-09-09 15:18 ` [PATCH 02/29] x86/efi: Consolidate region mapping logic Matt Fleming
2016-09-09 15:18   ` Matt Fleming
2016-09-09 15:18 ` Matt Fleming [this message]
2016-09-09 15:18 ` [PATCH 04/29] efi: Add efi_memmap_init_late() for permanent EFI memmap Matt Fleming
2016-09-09 15:18   ` Matt Fleming
2016-09-09 15:18 ` [PATCH 05/29] efi/fake_mem: Refactor main two code chunks into functions Matt Fleming
2016-09-09 15:18 ` [PATCH 06/29] efi: Split out EFI memory map functions into new file Matt Fleming
2016-09-09 15:18 ` [PATCH 07/29] efi: Add efi_memmap_install() for installing new EFI memory maps Matt Fleming
2016-09-09 15:18   ` Matt Fleming
2016-09-09 15:18 ` [PATCH 08/29] efi: Allow drivers to reserve boot services forever Matt Fleming
2017-01-04  2:48   ` Dan Williams
2017-01-04  5:28     ` Dave Young
2017-01-04  5:28       ` Dave Young
2017-01-04 14:25     ` Peter Jones
2017-01-04 14:25       ` Peter Jones
2017-01-04 17:45     ` Nicolai Stange
2017-01-04 17:45       ` Nicolai Stange
2017-01-04 18:40       ` Dan Williams
2016-09-09 15:18 ` [PATCH 09/29] efi/runtime-map: Use efi.memmap directly instead of a copy Matt Fleming
2016-09-09 15:18 ` [PATCH 10/29] efi/esrt: Use efi_mem_reserve() and avoid a kmalloc() Matt Fleming
2016-09-09 15:18   ` Matt Fleming
2016-09-09 15:18 ` [PATCH 11/29] x86/efi-bgrt: Use efi_mem_reserve() to avoid copying image data Matt Fleming
2016-09-09 15:18 ` [PATCH 12/29] efi/esrt: Use memremap not ioremap to access ESRT table in memory Matt Fleming
2016-09-09 15:18   ` Matt Fleming
2016-09-09 15:18 ` [PATCH 13/29] efi/arm*: esrt: Add missing call to efi_esrt_init() Matt Fleming
2016-09-09 15:18   ` Matt Fleming
2016-09-09 15:18 ` [PATCH 14/29] efi: Use a file local lock for efivars Matt Fleming
2016-09-09 15:18 ` [PATCH 15/29] efi: Don't use spinlocks for efi vars Matt Fleming
2016-09-09 15:18   ` Matt Fleming
2016-09-09 15:18 ` [PATCH 16/29] efi: Replace runtime services spinlock with semaphore Matt Fleming
2016-09-09 15:18 ` [PATCH 17/29] x86/efi: Initialize status to ensure garbage is not returned on small size Matt Fleming
2016-09-09 15:18 ` [PATCH 18/29] firmware-gsmi: Delete an unnecessary check before the function call "dma_pool_destroy" Matt Fleming
2016-09-09 15:18   ` Matt Fleming
2016-09-09 15:18 ` [PATCH 19/29] lib/ucs2_string: Speed up ucs2_utf8size() Matt Fleming
2016-09-09 15:18 ` [PATCH 20/29] x86/efi: Map in physical addresses in efi_map_region_fixed Matt Fleming
2016-09-09 15:18   ` Matt Fleming
2016-09-09 15:18 ` [PATCH 21/29] fs/efivarfs: Fix double kfree() in error path Matt Fleming
2016-09-09 15:18 ` [PATCH 22/29] x86/efi: Remove unused find_bits() function Matt Fleming
2016-09-09 15:18 ` [PATCH 23/29] efi/arm64: Add debugfs node to dump UEFI runtime page tables Matt Fleming
2016-09-09 15:18 ` [PATCH 24/29] x86/efi: Defer efi_esrt_init until after memblock_x86_fill Matt Fleming
2016-09-09 15:18   ` Matt Fleming
2016-09-09 15:18 ` [PATCH 25/29] efi: Add efi_test driver for exporting UEFI runtime service interfaces Matt Fleming
2016-09-09 15:18 ` [PATCH 26/29] efi/arm64: Treat regions with WT/WC set but WB cleared as memory Matt Fleming
2016-09-09 15:18   ` Matt Fleming
2016-09-09 15:18 ` [PATCH 27/29] x86/efi: Use kmalloc_array() in efi_call_phys_prolog() Matt Fleming
2016-09-09 15:18 ` [PATCH 28/29] x86/efi: Optimize away setup_gop32/64 if unused Matt Fleming
2016-09-09 15:18   ` Matt Fleming
2016-09-09 15:18 ` [PATCH 29/29] x86/efi: Allow invocation of arbitrary boot services Matt Fleming
2016-09-12 10:58 ` [GIT PULL 00/29] EFI changes for v4.9 Matt Fleming
2016-09-12 10:58   ` Matt Fleming
2016-09-12 11:42   ` Ingo Molnar
2016-09-12 11:42     ` Ingo Molnar
2016-09-13 18:32 ` Ingo Molnar
2016-09-13 18:32   ` Ingo Molnar

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=20160909151851.27577-4-matt@codeblueprint.co.uk \
    --to=matt@codeblueprint.co.uk \
    --cc=ard.biesheuvel@linaro.org \
    --cc=bp@alien8.de \
    --cc=dyoung@redhat.com \
    --cc=hpa@zytor.com \
    --cc=leif.lindholm@linaro.org \
    --cc=linux-efi@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mingo@kernel.org \
    --cc=pjones@redhat.com \
    --cc=tglx@linutronix.de \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.