From: Matt Fleming <matt@console-pimps.org>
To: linux-kernel@vger.kernel.org
Cc: linux-efi@vger.kernel.org, "H. Peter Anvin" <hpa@zytor.com>,
"Matthew Garrett" <mjg@redhat.com>,
"Jan Beulich" <jbeulich@suse.com>,
x86@kernel.org, "Ingo Molnar" <mingo@kernel.org>,
"Matt Fleming" <matt.fleming@intel.com>,
JérômeCarretero <cJ-ko@zougloub.eu>,
"Vasco Dias" <rafa.vasco@gmail.com>
Subject: [PATCH 2/3] x86, efi: 1:1 pagetable mapping for virtual EFI calls
Date: Wed, 3 Oct 2012 13:59:16 +0100 [thread overview]
Message-ID: <1349269157-25956-3-git-send-email-matt@console-pimps.org> (raw)
In-Reply-To: <1349269157-25956-1-git-send-email-matt@console-pimps.org>
From: Matt Fleming <matt.fleming@intel.com>
Some firmware still needs a 1:1 (virt->phys) mapping even after we've
called SetVirtualAddressMap(). So install the mapping alongside our
existing kernel mapping whenever we make EFI calls in virtual mode.
This bug was discovered on ASUS machines where the firmware
implementation of GetTime() accesses the RTC device via physical
addresses, even though that's bogus per the UEFI spec since we've
informed the firmware via SetVirtualAddressMap() that the boottime
memory map is no longer valid.
This bug seems to be present in a lot of consumer devices, so there's
not a lot we can do about this spec violation apart from workaround
it.
Cc: JérômeCarretero <cJ-ko@zougloub.eu>
Cc: Vasco Dias <rafa.vasco@gmail.com>
Signed-off-by: Matt Fleming <matt.fleming@intel.com>
---
arch/x86/include/asm/efi.h | 28 +++++++++++++++++++++-------
arch/x86/platform/efi/efi_64.c | 15 +++++++++++++++
2 files changed, 36 insertions(+), 7 deletions(-)
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index c9dcc18..ae3bf3b 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -69,23 +69,37 @@ extern u64 efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3,
efi_call6((void *)(f), (u64)(a1), (u64)(a2), (u64)(a3), \
(u64)(a4), (u64)(a5), (u64)(a6))
+extern unsigned long efi_call_virt_prelog(void);
+extern void efi_call_virt_epilog(unsigned long);
+
+#define efi_callx(x, func, ...) \
+ ({ \
+ efi_status_t __status; \
+ unsigned long __pgd; \
+ \
+ __pgd = efi_call_virt_prelog(); \
+ __status = efi_call##x(func, __VA_ARGS__); \
+ efi_call_virt_epilog(__pgd); \
+ __status; \
+ })
+
#define efi_call_virt0(f) \
- efi_call0((void *)(efi.systab->runtime->f))
+ efi_callx(0, (void *)(efi.systab->runtime->f))
#define efi_call_virt1(f, a1) \
- efi_call1((void *)(efi.systab->runtime->f), (u64)(a1))
+ efi_callx(1, (void *)(efi.systab->runtime->f), (u64)(a1))
#define efi_call_virt2(f, a1, a2) \
- efi_call2((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2))
+ efi_callx(2, (void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2))
#define efi_call_virt3(f, a1, a2, a3) \
- efi_call3((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
+ efi_callx(3, (void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
(u64)(a3))
#define efi_call_virt4(f, a1, a2, a3, a4) \
- efi_call4((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
+ efi_callx(4, (void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
(u64)(a3), (u64)(a4))
#define efi_call_virt5(f, a1, a2, a3, a4, a5) \
- efi_call5((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
+ efi_callx(5, (void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
(u64)(a3), (u64)(a4), (u64)(a5))
#define efi_call_virt6(f, a1, a2, a3, a4, a5, a6) \
- efi_call6((void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
+ efi_callx(6, (void *)(efi.systab->runtime->f), (u64)(a1), (u64)(a2), \
(u64)(a3), (u64)(a4), (u64)(a5), (u64)(a6))
extern void __iomem *efi_ioremap(unsigned long addr, unsigned long size,
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index ac3aa54..ddb0174 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -58,6 +58,21 @@ static void __init early_code_mapping_set_exec(int executable)
}
}
+unsigned long efi_call_virt_prelog(void)
+{
+ unsigned long saved;
+
+ saved = read_cr3();
+ write_cr3(real_mode_header->trampoline_pgd);
+
+ return saved;
+}
+
+void efi_call_virt_epilog(unsigned long saved)
+{
+ write_cr3(saved);
+}
+
void __init efi_call_phys_prelog(void)
{
unsigned long vaddress;
--
1.7.11.4
next prev parent reply other threads:[~2012-10-03 12:59 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-10-03 12:59 [PATCH 0/3] x86/efi: Identity mapping pagetable Matt Fleming
2012-10-03 12:59 ` [PATCH 1/3] x86, mm: Include the entire kernel memory map in trampoline_pgd Matt Fleming
2012-10-03 13:31 ` Jan Beulich
2012-10-03 14:03 ` Matt Fleming
2012-10-04 6:32 ` Jan Beulich
2012-10-04 9:18 ` Matt Fleming
2012-10-04 10:01 ` Jan Beulich
2012-10-10 10:45 ` Matt Fleming
2012-10-15 7:22 ` Jan Beulich
2012-10-04 21:08 ` H. Peter Anvin
2012-10-05 6:39 ` Jan Beulich
2012-10-05 6:48 ` Matt Fleming
2012-10-05 8:19 ` Jan Beulich
2012-10-05 16:28 ` H. Peter Anvin
2012-10-07 8:16 ` Jan Beulich
2012-10-07 10:26 ` H. Peter Anvin
2012-10-08 6:43 ` Jan Beulich
2012-10-03 12:59 ` Matt Fleming [this message]
2012-10-03 12:59 ` [PATCH 3/3] x86/kernel: remove tboot 1:1 page table creation code Matt Fleming
-- strict thread matches above, loose matches on Subject: below --
2012-10-05 13:14 [PATCH v2 0/3] x86/efi: Identity mapping pagetable Matt Fleming
2012-10-05 13:14 ` [PATCH 2/3] x86, efi: 1:1 pagetable mapping for virtual EFI calls Matt Fleming
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=1349269157-25956-3-git-send-email-matt@console-pimps.org \
--to=matt@console-pimps.org \
--cc=cJ-ko@zougloub.eu \
--cc=hpa@zytor.com \
--cc=jbeulich@suse.com \
--cc=linux-efi@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=matt.fleming@intel.com \
--cc=mingo@kernel.org \
--cc=mjg@redhat.com \
--cc=rafa.vasco@gmail.com \
--cc=x86@kernel.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 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).