diff options
author | Matt Fleming <matt.fleming@intel.com> | 2012-09-07 18:28:04 +0100 |
---|---|---|
committer | Matt Fleming <matt.fleming@intel.com> | 2012-10-30 10:39:19 +0000 |
commit | 185034e72d591f9465e5e18f937ed642e7ea0070 (patch) | |
tree | ecb81fad559d790db1a0d390a8fa6e209662c315 /arch/x86/platform | |
parent | 53b87cf088e2ea68d7c59619d0214cc15bb76133 (diff) | |
download | blackbird-op-linux-185034e72d591f9465e5e18f937ed642e7ea0070.tar.gz blackbird-op-linux-185034e72d591f9465e5e18f937ed642e7ea0070.zip |
x86, efi: 1:1 pagetable mapping for virtual EFI calls
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>
Acked-by: Jan Beulich <jbeulich@suse.com>
Signed-off-by: Matt Fleming <matt.fleming@intel.com>
Diffstat (limited to 'arch/x86/platform')
-rw-r--r-- | arch/x86/platform/efi/efi_64.c | 15 |
1 files changed, 15 insertions, 0 deletions
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c index ac3aa54e2654..ddb0174cf093 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; |