From: Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>
To: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Cc: "linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org"
<linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org>,
"linux-efi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org"
<linux-efi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>,
"leif.lindholm-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org"
<leif.lindholm-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>,
"roy.franz-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org"
<roy.franz-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>,
Catalin Marinas <Catalin.Marinas-5wv7dgnIgG8@public.gmane.org>,
Will Deacon <Will.Deacon-5wv7dgnIgG8@public.gmane.org>,
"matt.fleming-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org"
<matt.fleming-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>,
"bp-Gina5bIWoIWzQB+pC5nmwQ@public.gmane.org"
<bp-Gina5bIWoIWzQB+pC5nmwQ@public.gmane.org>,
"dyoung-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org"
<dyoung-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>,
"geoff.levand-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org"
<geoff.levand-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>,
"msalter-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org"
<msalter-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
Subject: Re: [PATCH v4 6/8] arm64/efi: move SetVirtualAddressMap() to UEFI stub
Date: Mon, 5 Jan 2015 16:20:16 +0000 [thread overview]
Message-ID: <20150105162016.GD26699@leverpostej> (raw)
In-Reply-To: <1419245944-2424-7-git-send-email-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
Hi Ard,
I have a few (minor) comments below.
On Mon, Dec 22, 2014 at 10:59:02AM +0000, Ard Biesheuvel wrote:
> In order to support kexec, the kernel needs to be able to deal with the
> state of the UEFI firmware after SetVirtualAddressMap() has been called.
> To avoid having separate code paths for non-kexec and kexec, let's move
> the call to SetVirtualAddressMap() to the stub: this will guarantee us
> that it will only be called once (since the stub is not executed during
> kexec), and ensures that the UEFI state is identical between kexec and
> normal boot.
>
> This implies that the layout of the virtual mapping needs to be created
> by the stub as well. All regions are rounded up to a naturally aligned
> multiple of 64 KB (for compatibility with 64k pages kernels) and recorded
> in the UEFI memory map. The kernel proper reads those values and installs
> the mappings in a dedicated set of page tables that are swapped in during
> UEFI Runtime Services calls.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
> ---
> arch/arm64/include/asm/efi.h | 20 +++-
> arch/arm64/kernel/efi.c | 223 ++++++++++++++++++++-----------------
> arch/arm64/kernel/setup.c | 1 +
> drivers/firmware/efi/libstub/fdt.c | 137 ++++++++++++++++++++++-
> 4 files changed, 270 insertions(+), 111 deletions(-)
[...]
> +static void efi_set_pgd(struct mm_struct *mm)
> +{
> + cpu_switch_mm(mm->pgd, mm);
> + flush_tlb_all();
> + if (icache_is_aivivt())
> + __flush_icache_all();
> +}
Do we have any idea how often we call runtime services?
I assume not all that often (read the RTC at boot, set/get variables).
If we're nuking the TLBs and I-cache a lot we'll probably need to
reserve an asid for the EFI virtmap.
[...]
> +void __init efi_virtmap_init(void)
> +{
> + efi_memory_desc_t *md;
> +
> + if (!efi_enabled(EFI_BOOT))
> + return;
> +
> + for_each_efi_memory_desc(&memmap, md) {
> + u64 paddr, npages, size;
> + pgprot_t prot;
> +
> + if (!(md->attribute & EFI_MEMORY_RUNTIME))
> + continue;
> + if (WARN(md->virt_addr == 0,
> + "UEFI virtual mapping incomplete or missing -- no entry found for 0x%llx\n",
> + md->phys_addr))
> + return;
I wonder if we might want to use a different address to signal a bad
mapping (e.g. 0UL-1 as it's not even EFI_PAGE_SIZE aligned), just in
case we have to handle a valid use of zero in future for some reason --
perhaps coming from another OS.
> +
> + paddr = md->phys_addr;
> + npages = md->num_pages;
> + memrange_efi_to_native(&paddr, &npages);
> + size = npages << PAGE_SHIFT;
> +
> + pr_info(" EFI remap 0x%012llx => %p\n",
Why not use %016llx? We might only have 48-bit PAs currently, but we may
as well keep the VA and PA equally long when printing out -- that'll
also help to identify issues with garbage in the upper 16 bits of the
PA field.
[...]
> +/*
> + * This is the base address at which to start allocating virtual memory ranges
> + * for UEFI Runtime Services. This is a userland range so that we can use any
> + * allocation we choose, and eliminate the risk of a conflict after kexec.
> + */
> +#define EFI_RT_VIRTUAL_BASE 0x40000000
Nit: I'm not keen on the term "userland" here. You can map stuff to EL0
in the high half of the address space if you wanted, so TTBR0/TTBR1
aren't architecturally user/kernel.
s/userland/low half/, perhaps?
It might also be worth pointing out that the arbitrary base address
isn't zero so as to be less likely to be an idmap.
> +
> +static void update_memory_map(efi_memory_desc_t *memory_map,
> + unsigned long map_size, unsigned long desc_size,
> + int *count)
> +{
> + u64 efi_virt_base = EFI_RT_VIRTUAL_BASE;
> + efi_memory_desc_t *out = (void *)memory_map + map_size;
> + int l;
> +
> + for (l = 0; l < map_size; l += desc_size) {
> + efi_memory_desc_t *in = (void *)memory_map + l;
> + u64 paddr, size;
> +
> + if (!(in->attribute & EFI_MEMORY_RUNTIME))
> + continue;
> +
> + /*
> + * Make the mapping compatible with 64k pages: this allows
> + * a 4k page size kernel to kexec a 64k page size kernel and
> + * vice versa.
> + */
> + paddr = round_down(in->phys_addr, SZ_64K);
> + size = round_up(in->num_pages * EFI_PAGE_SIZE +
> + in->phys_addr - paddr, SZ_64K);
> +
> + /*
> + * Avoid wasting memory on PTEs by choosing a virtual base that
> + * is compatible with section mappings if this region has the
> + * appropriate size and physical alignment. (Sections are 2 MB
> + * on 4k granule kernels)
> + */
> + if (IS_ALIGNED(in->phys_addr, SZ_2M) && size >= SZ_2M)
> + efi_virt_base = round_up(efi_virt_base, SZ_2M);
> +
> + in->virt_addr = efi_virt_base + in->phys_addr - paddr;
> + efi_virt_base += size;
> +
> + memcpy(out, in, desc_size);
> + out = (void *)out + desc_size;
> + ++*count;
> + }
> +}
This feels like this should live in arch/arm64, or under some other
directory specific to arm/arm64. That said, I guess the fdt stuff is
currently arm-specific anyway, so perhaps this is fine.
[...]
> @@ -248,12 +337,52 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
> }
> }
>
> + /*
> + * Update the memory map with virtual addresses. The function will also
> + * populate the spare second half of the memory_map allocation with
> + * copies of just the EFI_MEMORY_RUNTIME entries so that we can pass it
> + * straight into SetVirtualAddressMap()
> + */
> + update_memory_map(memory_map, map_size, desc_size,
> + &runtime_entry_count);
> +
> + pr_efi(sys_table,
> + "Exiting boot services and installing virtual address map...\n");
I believe that the memory map is allowed to change as a result of this
call, so I think this needs to be moved before update_memory_map.
Thanks,
Mark.
WARNING: multiple messages have this Message-ID (diff)
From: mark.rutland@arm.com (Mark Rutland)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v4 6/8] arm64/efi: move SetVirtualAddressMap() to UEFI stub
Date: Mon, 5 Jan 2015 16:20:16 +0000 [thread overview]
Message-ID: <20150105162016.GD26699@leverpostej> (raw)
In-Reply-To: <1419245944-2424-7-git-send-email-ard.biesheuvel@linaro.org>
Hi Ard,
I have a few (minor) comments below.
On Mon, Dec 22, 2014 at 10:59:02AM +0000, Ard Biesheuvel wrote:
> In order to support kexec, the kernel needs to be able to deal with the
> state of the UEFI firmware after SetVirtualAddressMap() has been called.
> To avoid having separate code paths for non-kexec and kexec, let's move
> the call to SetVirtualAddressMap() to the stub: this will guarantee us
> that it will only be called once (since the stub is not executed during
> kexec), and ensures that the UEFI state is identical between kexec and
> normal boot.
>
> This implies that the layout of the virtual mapping needs to be created
> by the stub as well. All regions are rounded up to a naturally aligned
> multiple of 64 KB (for compatibility with 64k pages kernels) and recorded
> in the UEFI memory map. The kernel proper reads those values and installs
> the mappings in a dedicated set of page tables that are swapped in during
> UEFI Runtime Services calls.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
> ---
> arch/arm64/include/asm/efi.h | 20 +++-
> arch/arm64/kernel/efi.c | 223 ++++++++++++++++++++-----------------
> arch/arm64/kernel/setup.c | 1 +
> drivers/firmware/efi/libstub/fdt.c | 137 ++++++++++++++++++++++-
> 4 files changed, 270 insertions(+), 111 deletions(-)
[...]
> +static void efi_set_pgd(struct mm_struct *mm)
> +{
> + cpu_switch_mm(mm->pgd, mm);
> + flush_tlb_all();
> + if (icache_is_aivivt())
> + __flush_icache_all();
> +}
Do we have any idea how often we call runtime services?
I assume not all that often (read the RTC at boot, set/get variables).
If we're nuking the TLBs and I-cache a lot we'll probably need to
reserve an asid for the EFI virtmap.
[...]
> +void __init efi_virtmap_init(void)
> +{
> + efi_memory_desc_t *md;
> +
> + if (!efi_enabled(EFI_BOOT))
> + return;
> +
> + for_each_efi_memory_desc(&memmap, md) {
> + u64 paddr, npages, size;
> + pgprot_t prot;
> +
> + if (!(md->attribute & EFI_MEMORY_RUNTIME))
> + continue;
> + if (WARN(md->virt_addr == 0,
> + "UEFI virtual mapping incomplete or missing -- no entry found for 0x%llx\n",
> + md->phys_addr))
> + return;
I wonder if we might want to use a different address to signal a bad
mapping (e.g. 0UL-1 as it's not even EFI_PAGE_SIZE aligned), just in
case we have to handle a valid use of zero in future for some reason --
perhaps coming from another OS.
> +
> + paddr = md->phys_addr;
> + npages = md->num_pages;
> + memrange_efi_to_native(&paddr, &npages);
> + size = npages << PAGE_SHIFT;
> +
> + pr_info(" EFI remap 0x%012llx => %p\n",
Why not use %016llx? We might only have 48-bit PAs currently, but we may
as well keep the VA and PA equally long when printing out -- that'll
also help to identify issues with garbage in the upper 16 bits of the
PA field.
[...]
> +/*
> + * This is the base address at which to start allocating virtual memory ranges
> + * for UEFI Runtime Services. This is a userland range so that we can use any
> + * allocation we choose, and eliminate the risk of a conflict after kexec.
> + */
> +#define EFI_RT_VIRTUAL_BASE 0x40000000
Nit: I'm not keen on the term "userland" here. You can map stuff to EL0
in the high half of the address space if you wanted, so TTBR0/TTBR1
aren't architecturally user/kernel.
s/userland/low half/, perhaps?
It might also be worth pointing out that the arbitrary base address
isn't zero so as to be less likely to be an idmap.
> +
> +static void update_memory_map(efi_memory_desc_t *memory_map,
> + unsigned long map_size, unsigned long desc_size,
> + int *count)
> +{
> + u64 efi_virt_base = EFI_RT_VIRTUAL_BASE;
> + efi_memory_desc_t *out = (void *)memory_map + map_size;
> + int l;
> +
> + for (l = 0; l < map_size; l += desc_size) {
> + efi_memory_desc_t *in = (void *)memory_map + l;
> + u64 paddr, size;
> +
> + if (!(in->attribute & EFI_MEMORY_RUNTIME))
> + continue;
> +
> + /*
> + * Make the mapping compatible with 64k pages: this allows
> + * a 4k page size kernel to kexec a 64k page size kernel and
> + * vice versa.
> + */
> + paddr = round_down(in->phys_addr, SZ_64K);
> + size = round_up(in->num_pages * EFI_PAGE_SIZE +
> + in->phys_addr - paddr, SZ_64K);
> +
> + /*
> + * Avoid wasting memory on PTEs by choosing a virtual base that
> + * is compatible with section mappings if this region has the
> + * appropriate size and physical alignment. (Sections are 2 MB
> + * on 4k granule kernels)
> + */
> + if (IS_ALIGNED(in->phys_addr, SZ_2M) && size >= SZ_2M)
> + efi_virt_base = round_up(efi_virt_base, SZ_2M);
> +
> + in->virt_addr = efi_virt_base + in->phys_addr - paddr;
> + efi_virt_base += size;
> +
> + memcpy(out, in, desc_size);
> + out = (void *)out + desc_size;
> + ++*count;
> + }
> +}
This feels like this should live in arch/arm64, or under some other
directory specific to arm/arm64. That said, I guess the fdt stuff is
currently arm-specific anyway, so perhaps this is fine.
[...]
> @@ -248,12 +337,52 @@ efi_status_t allocate_new_fdt_and_exit_boot(efi_system_table_t *sys_table,
> }
> }
>
> + /*
> + * Update the memory map with virtual addresses. The function will also
> + * populate the spare second half of the memory_map allocation with
> + * copies of just the EFI_MEMORY_RUNTIME entries so that we can pass it
> + * straight into SetVirtualAddressMap()
> + */
> + update_memory_map(memory_map, map_size, desc_size,
> + &runtime_entry_count);
> +
> + pr_efi(sys_table,
> + "Exiting boot services and installing virtual address map...\n");
I believe that the memory map is allowed to change as a result of this
call, so I think this needs to be moved before update_memory_map.
Thanks,
Mark.
next prev parent reply other threads:[~2015-01-05 16:20 UTC|newest]
Thread overview: 60+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-12-22 10:58 [PATCH v4 0/8] stable UEFI virtual mappings for kexec Ard Biesheuvel
2014-12-22 10:58 ` Ard Biesheuvel
[not found] ` <1419245944-2424-1-git-send-email-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2014-12-22 10:58 ` [PATCH v4 1/8] arm64/mm: add explicit struct_mm argument to __create_mapping() Ard Biesheuvel
2014-12-22 10:58 ` Ard Biesheuvel
2014-12-22 10:58 ` [PATCH v4 2/8] arm64/mm: add create_pgd_mapping() to create private page tables Ard Biesheuvel
2014-12-22 10:58 ` Ard Biesheuvel
2014-12-22 10:58 ` [PATCH v4 3/8] efi: split off remapping code from efi_config_init() Ard Biesheuvel
2014-12-22 10:58 ` Ard Biesheuvel
[not found] ` <1419245944-2424-4-git-send-email-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2015-01-05 14:55 ` Matt Fleming
2015-01-05 14:55 ` Matt Fleming
2015-01-05 21:56 ` Borislav Petkov
2015-01-05 21:56 ` Borislav Petkov
2014-12-22 10:59 ` [PATCH v4 4/8] efi: efistub: allow allocation alignment larger than EFI_PAGE_SIZE Ard Biesheuvel
2014-12-22 10:59 ` Ard Biesheuvel
[not found] ` <1419245944-2424-5-git-send-email-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2014-12-23 16:45 ` Borislav Petkov
2014-12-23 16:45 ` Borislav Petkov
[not found] ` <20141223164549.GB3810-fF5Pk5pvG8Y@public.gmane.org>
2014-12-29 9:25 ` Ard Biesheuvel
2014-12-29 9:25 ` Ard Biesheuvel
[not found] ` <CAKv+Gu_+scCHYuXccgsvn9THsbP24OfyjvjN9XtEVe4nMdQtig-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-12-29 9:47 ` Borislav Petkov
2014-12-29 9:47 ` Borislav Petkov
[not found] ` <20141229094732.GA16051-K5JNixvcfoxupOikMc4+xw@public.gmane.org>
2015-01-05 11:24 ` Ard Biesheuvel
2015-01-05 11:24 ` Ard Biesheuvel
2014-12-22 10:59 ` [PATCH v4 5/8] arm64/efi: set EFI_ALLOC_ALIGN to 64 KB Ard Biesheuvel
2014-12-22 10:59 ` Ard Biesheuvel
2015-01-06 16:37 ` Leif Lindholm
2015-01-06 16:37 ` Leif Lindholm
2014-12-22 10:59 ` [PATCH v4 6/8] arm64/efi: move SetVirtualAddressMap() to UEFI stub Ard Biesheuvel
2014-12-22 10:59 ` Ard Biesheuvel
[not found] ` <1419245944-2424-7-git-send-email-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2015-01-05 16:20 ` Mark Rutland [this message]
2015-01-05 16:20 ` Mark Rutland
2015-01-06 17:13 ` Leif Lindholm
2015-01-06 17:13 ` Leif Lindholm
2015-01-07 18:05 ` Ard Biesheuvel
2015-01-07 18:05 ` Ard Biesheuvel
2015-01-05 16:54 ` Matt Fleming
2015-01-05 16:54 ` Matt Fleming
[not found] ` <20150105165402.GE3163-HNK1S37rvNbeXh+fF434Mdi2O/JbrIOy@public.gmane.org>
2015-01-06 18:01 ` Leif Lindholm
2015-01-06 18:01 ` Leif Lindholm
[not found] ` <20150106180120.GF3827-t77nlHhSwNqAroYi2ySoxKxOck334EZe@public.gmane.org>
2015-01-12 10:43 ` Matt Fleming
2015-01-12 10:43 ` Matt Fleming
2015-01-07 18:15 ` Ard Biesheuvel
2015-01-07 18:15 ` Ard Biesheuvel
2015-01-07 12:06 ` Leif Lindholm
2015-01-07 12:06 ` Leif Lindholm
[not found] ` <20150107120608.GJ3827-t77nlHhSwNqAroYi2ySoxKxOck334EZe@public.gmane.org>
2015-01-07 12:16 ` Ard Biesheuvel
2015-01-07 12:16 ` Ard Biesheuvel
[not found] ` <CAKv+Gu_k0_anqvm24P8J4WaMrFLMxOhQETAfUb6xmzaJ+Z2vBQ-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-01-07 12:25 ` Leif Lindholm
2015-01-07 12:25 ` Leif Lindholm
[not found] ` <20150107122515.GK3827-t77nlHhSwNqAroYi2ySoxKxOck334EZe@public.gmane.org>
2015-01-07 12:30 ` Ard Biesheuvel
2015-01-07 12:30 ` Ard Biesheuvel
[not found] ` <CAKv+Gu-aRkoRj5zVXrsBc0APCehZ9W926J6fxH380K9EURXe_Q-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2015-01-07 12:56 ` Leif Lindholm
2015-01-07 12:56 ` Leif Lindholm
2014-12-22 10:59 ` [PATCH v4 7/8] arm64/efi: remove free_boot_services() and friends Ard Biesheuvel
2014-12-22 10:59 ` Ard Biesheuvel
[not found] ` <1419245944-2424-8-git-send-email-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2015-01-06 18:06 ` Leif Lindholm
2015-01-06 18:06 ` Leif Lindholm
2014-12-22 10:59 ` [PATCH v4 8/8] arm64/efi: remove idmap manipulations from UEFI code Ard Biesheuvel
2014-12-22 10:59 ` Ard Biesheuvel
[not found] ` <1419245944-2424-9-git-send-email-ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>
2015-01-06 18:17 ` Leif Lindholm
2015-01-06 18:17 ` Leif Lindholm
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=20150105162016.GD26699@leverpostej \
--to=mark.rutland-5wv7dgnigg8@public.gmane.org \
--cc=Catalin.Marinas-5wv7dgnIgG8@public.gmane.org \
--cc=Will.Deacon-5wv7dgnIgG8@public.gmane.org \
--cc=ard.biesheuvel-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org \
--cc=bp-Gina5bIWoIWzQB+pC5nmwQ@public.gmane.org \
--cc=dyoung-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org \
--cc=geoff.levand-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org \
--cc=leif.lindholm-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org \
--cc=linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
--cc=linux-efi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=matt.fleming-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
--cc=msalter-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org \
--cc=roy.franz-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org \
/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.