2020-02-20 03:43:44

by Jing Xiangfeng

[permalink] [raw]
Subject: [PATCH 0/2] arm64: Support to find mirrored memory ranges

This series enable finding mirrored memory ranges
functionality on arm64 platform. This feature has been
implemented on the x86 platform, so we move some
functions from x86.

Jing Xiangfeng (2):
efi: allow EFI_FAKE_MEMMAP on arm64 platform
arm64/efi: support to find mirrored memory ranges

arch/x86/include/asm/efi.h | 5 -----
arch/x86/platform/efi/efi.c | 39 ---------------------------------------
drivers/firmware/efi/Kconfig | 2 +-
drivers/firmware/efi/arm-init.c | 2 ++
drivers/firmware/efi/efi.c | 23 +++++++++++++++++++++++
drivers/firmware/efi/memmap.c | 16 ++++++++++++++++
include/linux/efi.h | 5 +++++
7 files changed, 47 insertions(+), 45 deletions(-)

--
1.8.3.1


2020-02-20 03:44:09

by Jing Xiangfeng

[permalink] [raw]
Subject: [PATCH 2/2] arm64/efi: support to find mirrored memory ranges

Commit b05b9f5f9dcf ("x86, mirror: x86 enabling - find
mirrored memory ranges") introduced the efi_find_mirror
on x86. Now we can scan the memory map and find mirrored
memory ranges by calling efi_find_mirror on arm64 platform.

For example, if "efi_fake_mem=4G@1G:0x10000,4G@7G:0x10000"
is specified, the original (firmware provided) EFI memmap will be
updated so that the specified memory regions have
EFI_MEMORY_MORE_RELIABLE attribute (0x10000):

<original>
efi: mem02: [Conventional Memory| | | | | | | | | |WB|
| | ] range=[0x0000000040000000-0x00000001b5035fff] (5968MB)

efi: mem28: [Conventional Memory| | | | | | | | | |WB|
| | ] range=[0x00000001c0000000-0x00000002843fffff] (3140MB)
efi: mem29: [Loader Data | | | | | | | | | |WB|
| | ] range=[0x0000000284400000-0x0000000285f18fff] (27MB)
efi: mem30: [Conventional Memory| | | | | | | | | |WB|
| | ] range=[0x0000000285f19000-0x000000033fbfffff] (2972MB)
<updated>
efi: mem02: [Conventional Memory| |MR| | | | | | | |WB|
| | ] range=[0x0000000040000000-0x000000013fffffff] (4096MB)
efi: mem03: [Conventional Memory| | | | | | | | | |WB|
| | ] range=[0x0000000140000000-0x00000001b5035fff] (1872MB)

efi: mem29: [Conventional Memory| |MR| | | | | | | |WB|
| | ] range=[0x00000001c0000000-0x00000002843fffff] (3140MB)
efi: mem30: [Loader Data | |MR| | | | | | | |WB|
| | ] range=[0x0000000284400000-0x0000000285f18fff] (27MB)
efi: mem31: [Conventional Memory| |MR| | | | | | | |WB|
| | ] range=[0x0000000285f19000-0x00000002bfffffff] (928MB)

And you will find that the following message is output:

efi: Memory: 8192M/12352M mirrored memory

Signed-off-by: Jing Xiangfeng <[email protected]>
---
arch/x86/include/asm/efi.h | 4 ----
arch/x86/platform/efi/efi.c | 23 -----------------------
drivers/firmware/efi/arm-init.c | 1 +
drivers/firmware/efi/efi.c | 23 +++++++++++++++++++++++
include/linux/efi.h | 4 ++++
5 files changed, 28 insertions(+), 27 deletions(-)

diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 127977f..24fa6a9 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -330,7 +330,6 @@ static inline void *efi64_zero_upper(void *p)
extern bool efi_reboot_required(void);
extern bool efi_is_table_address(unsigned long phys_addr);

-extern void efi_find_mirror(void);
extern void efi_reserve_boot_services(void);
#else
static inline void parse_efi_setup(u64 phys_addr, u32 data_len) {}
@@ -342,9 +341,6 @@ static inline bool efi_is_table_address(unsigned long phys_addr)
{
return false;
}
-static inline void efi_find_mirror(void)
-{
-}
static inline void efi_reserve_boot_services(void)
{
}
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 4c8793d..c06603d 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -97,29 +97,6 @@ static int __init setup_add_efi_memmap(char *arg)
}
early_param("add_efi_memmap", setup_add_efi_memmap);

-void __init efi_find_mirror(void)
-{
- efi_memory_desc_t *md;
- u64 mirror_size = 0, total_size = 0;
-
- if (!efi_enabled(EFI_MEMMAP))
- return;
-
- for_each_efi_memory_desc(md) {
- unsigned long long start = md->phys_addr;
- unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
-
- total_size += size;
- if (md->attribute & EFI_MEMORY_MORE_RELIABLE) {
- memblock_mark_mirror(start, size);
- mirror_size += size;
- }
- }
- if (mirror_size)
- pr_info("Memory: %lldM/%lldM mirrored memory\n",
- mirror_size>>20, total_size>>20);
-}
-
/*
* Tell the kernel about the EFI memory map. This might include
* more than the max 128 entries that can fit in the passed in e820
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index ac00e7c..f86e73e 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -266,6 +266,7 @@ void __init efi_init(void)

reserve_regions();
efi_fake_memmap();
+ efi_find_mirror();
efi_esrt_init();

memblock_reserve(params.mmap & PAGE_MASK,
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 621220a..664d01d 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -394,6 +394,29 @@ static int __init efisubsys_init(void)

subsys_initcall(efisubsys_init);

+void __init efi_find_mirror(void)
+{
+ efi_memory_desc_t *md;
+ u64 mirror_size = 0, total_size = 0;
+
+ if (!efi_enabled(EFI_MEMMAP))
+ return;
+
+ for_each_efi_memory_desc(md) {
+ unsigned long long start = md->phys_addr;
+ unsigned long long size = md->num_pages << EFI_PAGE_SHIFT;
+
+ total_size += size;
+ if (md->attribute & EFI_MEMORY_MORE_RELIABLE) {
+ memblock_mark_mirror(start, size);
+ mirror_size += size;
+ }
+ }
+ if (mirror_size)
+ pr_info("Memory: %lldM/%lldM mirrored memory\n",
+ mirror_size>>20, total_size>>20);
+}
+
/*
* Find the efi memory descriptor for a given physical address. Given a
* physical address, determine if it exists within an EFI Memory Map entry,
diff --git a/include/linux/efi.h b/include/linux/efi.h
index bf101e5..bb32e37 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1143,6 +1143,7 @@ static inline bool __pure efi_soft_reserve_enabled(void)
&& __efi_soft_reserve_enabled();
}
extern void __init efi_print_memmap(void);
+extern void efi_find_mirror(void);
#else
static inline bool efi_enabled(int feature)
{
@@ -1161,6 +1162,9 @@ static inline bool efi_soft_reserve_enabled(void)
{
return false;
}
+static inline void efi_find_mirror(void)
+{
+}
#endif

extern int efi_status_to_err(efi_status_t status);
--
1.8.3.1

2020-02-20 03:45:08

by Jing Xiangfeng

[permalink] [raw]
Subject: [PATCH 1/2] efi: allow EFI_FAKE_MEMMAP on arm64 platform

Add a efi_fake_memmap call in efi_init on arm64.This is useful for
debugging of Address Range Mirroring feature on arm64 platform.

Signed-off-by: Jing Xiangfeng <[email protected]>
---
arch/x86/include/asm/efi.h | 1 -
arch/x86/platform/efi/efi.c | 16 ----------------
drivers/firmware/efi/Kconfig | 2 +-
drivers/firmware/efi/arm-init.c | 1 +
drivers/firmware/efi/memmap.c | 16 ++++++++++++++++
include/linux/efi.h | 1 +
6 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 86169a2..127977f 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -158,7 +158,6 @@ extern void __iomem *__init efi_ioremap(unsigned long addr, unsigned long size,
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 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);
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 ae923ee..4c8793d 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -317,22 +317,6 @@ static void __init efi_clean_memmap(void)
}
}

-void __init efi_print_memmap(void)
-{
- efi_memory_desc_t *md;
- int i = 0;
-
- for_each_efi_memory_desc(md) {
- char buf[64];
-
- pr_info("mem%02u: %s range=[0x%016llx-0x%016llx] (%lluMB)\n",
- i++, efi_md_typeattr_format(buf, sizeof(buf), md),
- md->phys_addr,
- md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1,
- (md->num_pages >> (20 - EFI_PAGE_SHIFT)));
- }
-}
-
static int __init efi_systab_init(u64 phys)
{
int size = efi_enabled(EFI_64BIT) ? sizeof(efi_system_table_64_t)
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index ecc83e2..9cf9a96 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -55,7 +55,7 @@ config EFI_RUNTIME_MAP

config EFI_FAKE_MEMMAP
bool "Enable EFI fake memory map"
- depends on EFI && X86
+ depends on EFI && (X86 || ARM64)
default n
help
Saying Y here will enable "efi_fake_mem" boot option.
diff --git a/drivers/firmware/efi/arm-init.c b/drivers/firmware/efi/arm-init.c
index d99f5b0..ac00e7c 100644
--- a/drivers/firmware/efi/arm-init.c
+++ b/drivers/firmware/efi/arm-init.c
@@ -265,6 +265,7 @@ void __init efi_init(void)
}

reserve_regions();
+ efi_fake_memmap();
efi_esrt_init();

memblock_reserve(params.mmap & PAGE_MASK,
diff --git a/drivers/firmware/efi/memmap.c b/drivers/firmware/efi/memmap.c
index 2ff1883..0155bf0 100644
--- a/drivers/firmware/efi/memmap.c
+++ b/drivers/firmware/efi/memmap.c
@@ -376,3 +376,19 @@ void __init efi_memmap_insert(struct efi_memory_map *old_memmap, void *buf,
}
}
}
+
+void __init efi_print_memmap(void)
+{
+ efi_memory_desc_t *md;
+ int i = 0;
+
+ for_each_efi_memory_desc(md) {
+ char buf[64];
+
+ pr_info("mem%02u: %s range=[0x%016llx-0x%016llx] (%lluMB)\n",
+ i++, efi_md_typeattr_format(buf, sizeof(buf), md),
+ md->phys_addr,
+ md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1,
+ (md->num_pages >> (20 - EFI_PAGE_SHIFT)));
+ }
+}
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 7efd707..bf101e5 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1142,6 +1142,7 @@ static inline bool __pure efi_soft_reserve_enabled(void)
return IS_ENABLED(CONFIG_EFI_SOFT_RESERVE)
&& __efi_soft_reserve_enabled();
}
+extern void __init efi_print_memmap(void);
#else
static inline bool efi_enabled(int feature)
{
--
1.8.3.1

2020-02-20 09:22:11

by Ard Biesheuvel

[permalink] [raw]
Subject: Re: [PATCH 0/2] arm64: Support to find mirrored memory ranges

On Thu, 20 Feb 2020 at 04:43, Jing Xiangfeng <[email protected]> wrote:
>
> This series enable finding mirrored memory ranges
> functionality on arm64 platform. This feature has been
> implemented on the x86 platform, so we move some
> functions from x86.
>

Hello Jing Xiangfeng,

Could you explain your use case a bit better? Usually, the firmware is
a better place to make modifications to the EFI memory map.

The reason I am asking is that currently, on ARM and arm64, we never
make *any* changes to the firmware provided tables (EFI system table,
EFI memory map, DT/ACPI/SMBIOS tables etc), in order to ensure that
kexec is idempotent, i.e., it will always see the exact same state as
far as the firmware is concerned. This is a bit different from x86,
where the memory map is already modified for various other reasons, so
using it for fake memory regions is not such a big deal.

Do you see a use case for this in production?

> Jing Xiangfeng (2):
> efi: allow EFI_FAKE_MEMMAP on arm64 platform
> arm64/efi: support to find mirrored memory ranges
>
> arch/x86/include/asm/efi.h | 5 -----
> arch/x86/platform/efi/efi.c | 39 ---------------------------------------
> drivers/firmware/efi/Kconfig | 2 +-
> drivers/firmware/efi/arm-init.c | 2 ++
> drivers/firmware/efi/efi.c | 23 +++++++++++++++++++++++
> drivers/firmware/efi/memmap.c | 16 ++++++++++++++++
> include/linux/efi.h | 5 +++++
> 7 files changed, 47 insertions(+), 45 deletions(-)
>
> --
> 1.8.3.1
>