• Matt Fleming's avatar
    x86/efi: Avoid triple faults during EFI mixed mode calls · c4f934bc
    Matt Fleming authored
    commit 96738c69 upstream.
    
    Andy pointed out that if an NMI or MCE is received while we're in the
    middle of an EFI mixed mode call a triple fault will occur. This can
    happen, for example, when issuing an EFI mixed mode call while running
    perf.
    
    The reason for the triple fault is that we execute the mixed mode call
    in 32-bit mode with paging disabled but with 64-bit kernel IDT handlers
    installed throughout the call.
    
    At Andy's suggestion, stop playing the games we currently do at runtime,
    such as disabling paging and installing a 32-bit GDT for __KERNEL_CS. We
    can simply switch to the __KERNEL32_CS descriptor before invoking
    firmware services, and run in compatibility mode. This way, if an
    NMI/MCE does occur the kernel IDT handler will execute correctly, since
    it'll jump to __KERNEL_CS automatically.
    
    However, this change is only possible post-ExitBootServices(). Before
    then the firmware "owns" the machine and expects for its 32-bit IDT
    handlers to be left intact to service interrupts, etc.
    
    So, we now need to distinguish between early boot and runtime
    invocations of EFI services. During early boot, we need to restore the
    GDT that the firmware expects to be present. We can only jump to the
    __KERNEL32_CS code segment for mixed mode calls after ExitBootServices()
    has been invoked.
    
    A liberal sprinkling of comments in the thunking code should make the
    differences in early and late environments more apparent.
    Reported-by: default avatarAndy Lutomirski <luto@amacapital.net>
    Tested-by: default avatarBorislav Petkov <bp@suse.de>
    Signed-off-by: default avatarMatt Fleming <matt.fleming@intel.com>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    c4f934bc
efi_stub_64.S 1.86 KB