lkml.org 
[lkml]   [2021]   [Dec]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[tip: x86/mm] x86/mm: Flush global TLB when switching to trampoline page-table
    The following commit has been merged into the x86/mm branch of tip:

    Commit-ID: 71d5049b053876afbde6c3273250b76935494ab2
    Gitweb: https://git.kernel.org/tip/71d5049b053876afbde6c3273250b76935494ab2
    Author: Joerg Roedel <jroedel@suse.de>
    AuthorDate: Thu, 02 Dec 2021 16:32:25 +01:00
    Committer: Borislav Petkov <bp@suse.de>
    CommitterDate: Mon, 06 Dec 2021 09:54:10 +01:00

    x86/mm: Flush global TLB when switching to trampoline page-table

    Move the switching code into a function so that it can be re-used and
    add a global TLB flush. This makes sure that usage of memory which is
    not mapped in the trampoline page-table is reliably caught.

    Also move the clearing of CR4.PCIDE before the CR3 switch because the
    cr4_clear_bits() function will access data not mapped into the
    trampoline page-table.

    Signed-off-by: Joerg Roedel <jroedel@suse.de>
    Signed-off-by: Borislav Petkov <bp@suse.de>
    Link: https://lore.kernel.org/r/20211202153226.22946-4-joro@8bytes.org
    ---
    arch/x86/include/asm/realmode.h | 1 +
    arch/x86/kernel/reboot.c | 12 ++----------
    arch/x86/realmode/init.c | 26 ++++++++++++++++++++++++++
    3 files changed, 29 insertions(+), 10 deletions(-)

    diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h
    index 5db5d08..331474b 100644
    --- a/arch/x86/include/asm/realmode.h
    +++ b/arch/x86/include/asm/realmode.h
    @@ -89,6 +89,7 @@ static inline void set_real_mode_mem(phys_addr_t mem)
    }

    void reserve_real_mode(void);
    +void load_trampoline_pgtable(void);

    #endif /* __ASSEMBLY__ */

    diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
    index 0a40df6..fa700b4 100644
    --- a/arch/x86/kernel/reboot.c
    +++ b/arch/x86/kernel/reboot.c
    @@ -113,17 +113,9 @@ void __noreturn machine_real_restart(unsigned int type)
    spin_unlock(&rtc_lock);

    /*
    - * Switch back to the initial page table.
    + * Switch to the trampoline page table.
    */
    -#ifdef CONFIG_X86_32
    - load_cr3(initial_page_table);
    -#else
    - write_cr3(real_mode_header->trampoline_pgd);
    -
    - /* Exiting long mode will fail if CR4.PCIDE is set. */
    - if (boot_cpu_has(X86_FEATURE_PCID))
    - cr4_clear_bits(X86_CR4_PCIDE);
    -#endif
    + load_trampoline_pgtable();

    /* Jump to the identity-mapped low memory code */
    #ifdef CONFIG_X86_32
    diff --git a/arch/x86/realmode/init.c b/arch/x86/realmode/init.c
    index 4a3da75..6d98609 100644
    --- a/arch/x86/realmode/init.c
    +++ b/arch/x86/realmode/init.c
    @@ -17,6 +17,32 @@ u32 *trampoline_cr4_features;
    /* Hold the pgd entry used on booting additional CPUs */
    pgd_t trampoline_pgd_entry;

    +void load_trampoline_pgtable(void)
    +{
    +#ifdef CONFIG_X86_32
    + load_cr3(initial_page_table);
    +#else
    + /*
    + * This function is called before exiting to real-mode and that will
    + * fail with CR4.PCIDE still set.
    + */
    + if (boot_cpu_has(X86_FEATURE_PCID))
    + cr4_clear_bits(X86_CR4_PCIDE);
    +
    + write_cr3(real_mode_header->trampoline_pgd);
    +#endif
    +
    + /*
    + * The CR3 write above will not flush global TLB entries.
    + * Stale, global entries from previous page tables may still be
    + * present. Flush those stale entries.
    + *
    + * This ensures that memory accessed while running with
    + * trampoline_pgd is *actually* mapped into trampoline_pgd.
    + */
    + __flush_tlb_all();
    +}
    +
    void __init reserve_real_mode(void)
    {
    phys_addr_t mem;
    \
     
     \ /
      Last update: 2021-12-06 22:58    [W:9.121 / U:0.264 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site