From: Matt Fleming <matt@console-pimps.org>
To: Borislav Petkov <bp@alien8.de>
Cc: LKML <linux-kernel@vger.kernel.org>,
"H. Peter Anvin" <hpa@zytor.com>,
David Woodhouse <dwmw2@infradead.org>,
Matthew Garrett <matthew.garrett@nebula.com>,
Borislav Petkov <bp@suse.de>
Subject: Re: [RFC PATCH 2/2] x86, efi: Add 1:1 mapping of runtime services
Date: Fri, 26 Apr 2013 14:09:19 +0100 [thread overview]
Message-ID: <20130426130919.GA23038@console-pimps.org> (raw)
In-Reply-To: <1366712152-8097-3-git-send-email-bp@alien8.de>
On Tue, 23 Apr, at 12:15:52PM, Borislav Petkov wrote:
> From: Borislav Petkov <bp@suse.de>
>
> Map EFI runtime services 1:1 into the trampoline pgd so that all those
> functions can be used in a kexec kernel. As we all know, the braindead
> design of SetVirtualAddressMap() doesn't allow a subsequent call to this
> function to reestablish virtual mappings, leading us to do all kinds of
> crazy dances in the kernel.
>
> 64-bit only for now.
>
> Signed-off-by: Borislav Petkov <bp@suse.de>
> ---
> arch/x86/include/asm/efi.h | 2 +
> arch/x86/platform/efi/efi.c | 84 +++++++++++++++++++++++++++----------
> arch/x86/platform/efi/efi_stub_64.S | 39 +++++++++++++++++
> 3 files changed, 102 insertions(+), 23 deletions(-)
[...]
> diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
> index 4b70be21fe0a..9e45eac3c33a 100644
> --- a/arch/x86/platform/efi/efi.c
> +++ b/arch/x86/platform/efi/efi.c
> @@ -649,15 +649,24 @@ static int __init efi_runtime_init(void)
> pr_err("Could not map the runtime service table!\n");
> return -ENOMEM;
> }
> - /*
> - * We will only need *early* access to the following
> - * two EFI runtime services before set_virtual_address_map
> - * is invoked.
> - */
> - efi_phys.get_time = (efi_get_time_t *)runtime->get_time;
> - efi_phys.set_virtual_address_map =
> - (efi_set_virtual_address_map_t *)
> - runtime->set_virtual_address_map;
> +
> +#define efi_phys_assign(f) \
> + efi_phys.f = (efi_ ##f## _t *)runtime->f
> +
> + efi_phys_assign(get_time);
> + efi_phys_assign(set_time);
> + efi_phys_assign(get_wakeup_time);
> + efi_phys_assign(set_wakeup_time);
> + efi_phys_assign(get_variable);
> + efi_phys_assign(get_next_variable);
> + efi_phys_assign(set_variable);
> + efi_phys_assign(get_next_high_mono_count);
> + efi_phys_assign(reset_system);
> + efi_phys_assign(set_virtual_address_map);
> + efi_phys_assign(query_variable_info);
> + efi_phys_assign(update_capsule);
> + efi_phys_assign(query_capsule_caps);
> +
Why is this change needed? We still don't access these other functions
via their early addresses.
> /*
> * Make efi_get_time can be called before entering
> * virtual mode.
> @@ -845,9 +854,10 @@ void efi_memory_uc(u64 addr, unsigned long size)
> */
> void __init efi_enter_virtual_mode(void)
> {
> + pgd_t *pgd = (pgd_t *)__va(real_mode_header->trampoline_pgd);
> efi_memory_desc_t *md, *prev_md = NULL;
> efi_status_t status;
> - unsigned long size;
> + unsigned long size, page_flags;
> u64 end, systab, start_pfn, end_pfn;
> void *p, *va, *new_memmap = NULL;
> int count = 0;
> @@ -895,7 +905,8 @@ void __init efi_enter_virtual_mode(void)
> md = p;
> if (!(md->attribute & EFI_MEMORY_RUNTIME) &&
> md->type != EFI_BOOT_SERVICES_CODE &&
> - md->type != EFI_BOOT_SERVICES_DATA)
> + md->type != EFI_BOOT_SERVICES_DATA &&
> + md->type != EFI_CONVENTIONAL_MEMORY)
> continue;
>
> size = md->num_pages << EFI_PAGE_SHIFT;
> @@ -920,11 +931,26 @@ void __init efi_enter_virtual_mode(void)
> continue;
> }
>
> + page_flags = 0;
> +
> + if (md->type == EFI_RUNTIME_SERVICES_DATA ||
> + md->type == EFI_BOOT_SERVICES_DATA)
> + page_flags = _PAGE_NX;
> +
> + if (!(md->attribute & EFI_MEMORY_WB))
> + page_flags |= _PAGE_PCD;
> +
> + kernel_map_pages_in_pgd(pgd, md->phys_addr,
> + md->num_pages, page_flags);
> +
> systab = (u64) (unsigned long) efi_phys.systab;
> if (md->phys_addr <= systab && systab < end) {
> systab += md->virt_addr - md->phys_addr;
> efi.systab = (efi_system_table_t *) (unsigned long) systab;
> }
> +
> + md->virt_addr = md->phys_addr;
> +
Now we have the EFI regions mapped in two places synchronisation is
probably required, e.g. mappings are accessible via the direct kernel
mapping/ioremap space, and via the 1:1 mapping. Also, you'll want to
look at fixing efi_lookup_mapped_addr() which assumes it can access
md->virt_addr in the current pgd.
Actually, I _think_ we can get away with only double mapping those
regions that we use as ram, see do_add_efi_memmap() and exit_boot() in
arch/x86/boot/compressed/eboot.c. We can probably skip the ioremap()
calls now, since they're only for the benefit of firmware. Which in
turn should mean we can delete efi_ioremap().
--
Matt Fleming, Intel Open Source Technology Center
next prev parent reply other threads:[~2013-04-26 13:09 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-04-23 10:15 [RFC PATCH 0/2] EFI runtime services 1:1 mapping Borislav Petkov
2013-04-23 10:15 ` [RFC PATCH 1/2] x86, cpa: Map in an arbitrary pgd Borislav Petkov
2013-04-23 10:15 ` [RFC PATCH 2/2] x86, efi: Add 1:1 mapping of runtime services Borislav Petkov
2013-04-26 13:09 ` Matt Fleming [this message]
2013-04-29 23:11 ` Borislav Petkov
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=20130426130919.GA23038@console-pimps.org \
--to=matt@console-pimps.org \
--cc=bp@alien8.de \
--cc=bp@suse.de \
--cc=dwmw2@infradead.org \
--cc=hpa@zytor.com \
--cc=linux-kernel@vger.kernel.org \
--cc=matthew.garrett@nebula.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