lkml.org 
[lkml]   [2017]   [Nov]   [24]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 05/43] x86/fixmap: Generalize the GDT fixmap mechanism
    Date
    From: Andy Lutomirski <luto@kernel.org>

    Currently, the GDT is an ad-hoc array of pages, one per CPU, in the
    fixmap. Generalize it to be an array of a new struct cpu_entry_area
    so that we can cleanly add new things to it.

    Signed-off-by: Andy Lutomirski <luto@kernel.org>
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
    Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
    Cc: Borislav Petkov <bpetkov@suse.de>
    Cc: Brian Gerst <brgerst@gmail.com>
    Cc: Dave Hansen <dave.hansen@intel.com>
    Cc: Josh Poimboeuf <jpoimboe@redhat.com>
    Cc: Linus Torvalds <torvalds@linux-foundation.org>
    Cc: Peter Zijlstra <peterz@infradead.org>
    Link: https://lkml.kernel.org/r/22571d77ba1f3c714df9fa37db9a58218bc17597.1511497875.git.luto@kernel.org
    Signed-off-by: Ingo Molnar <mingo@kernel.org>
    ---
    arch/x86/include/asm/desc.h | 9 +--------
    arch/x86/include/asm/fixmap.h | 34 ++++++++++++++++++++++++++++++++--
    arch/x86/kernel/cpu/common.c | 14 +++++++-------
    arch/x86/xen/mmu_pv.c | 2 +-
    4 files changed, 41 insertions(+), 18 deletions(-)

    diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h
    index 95cd95eb7285..194ffab00ebe 100644
    --- a/arch/x86/include/asm/desc.h
    +++ b/arch/x86/include/asm/desc.h
    @@ -60,17 +60,10 @@ static inline struct desc_struct *get_current_gdt_rw(void)
    return this_cpu_ptr(&gdt_page)->gdt;
    }

    -/* Get the fixmap index for a specific processor */
    -static inline unsigned int get_cpu_gdt_ro_index(int cpu)
    -{
    - return FIX_GDT_REMAP_END - cpu;
    -}
    -
    /* Provide the fixmap address of the remapped GDT */
    static inline struct desc_struct *get_cpu_gdt_ro(int cpu)
    {
    - unsigned int idx = get_cpu_gdt_ro_index(cpu);
    - return (struct desc_struct *)__fix_to_virt(idx);
    + return (struct desc_struct *)&get_cpu_entry_area(cpu)->gdt;
    }

    /* Provide the current read-only GDT */
    diff --git a/arch/x86/include/asm/fixmap.h b/arch/x86/include/asm/fixmap.h
    index dcd9fb55e679..0f4c92f02968 100644
    --- a/arch/x86/include/asm/fixmap.h
    +++ b/arch/x86/include/asm/fixmap.h
    @@ -44,6 +44,16 @@ extern unsigned long __FIXADDR_TOP;
    PAGE_SIZE)
    #endif

    +/*
    + * cpu_entry_area is a percpu region in the fixmap that contains things
    + * needed by the CPU and early entry/exit code. Real types aren't used
    + * for all fields here to avoid circular header dependencies.
    + */
    +struct cpu_entry_area {
    + char gdt[PAGE_SIZE];
    +};
    +
    +#define CPU_ENTRY_AREA_PAGES (sizeof(struct cpu_entry_area) / PAGE_SIZE)

    /*
    * Here we define all the compile-time 'special' virtual
    @@ -101,8 +111,8 @@ enum fixed_addresses {
    FIX_LNW_VRTC,
    #endif
    /* Fixmap entries to remap the GDTs, one per processor. */
    - FIX_GDT_REMAP_BEGIN,
    - FIX_GDT_REMAP_END = FIX_GDT_REMAP_BEGIN + NR_CPUS - 1,
    + FIX_CPU_ENTRY_AREA_TOP,
    + FIX_CPU_ENTRY_AREA_BOTTOM = FIX_CPU_ENTRY_AREA_TOP + (CPU_ENTRY_AREA_PAGES * NR_CPUS) - 1,

    __end_of_permanent_fixed_addresses,

    @@ -185,5 +195,25 @@ void __init *early_memremap_decrypted_wp(resource_size_t phys_addr,
    void __early_set_fixmap(enum fixed_addresses idx,
    phys_addr_t phys, pgprot_t flags);

    +static inline unsigned int __get_cpu_entry_area_page_index(int cpu, int page)
    +{
    + BUILD_BUG_ON(sizeof(struct cpu_entry_area) % PAGE_SIZE != 0);
    +
    + return FIX_CPU_ENTRY_AREA_BOTTOM - cpu*CPU_ENTRY_AREA_PAGES - page;
    +}
    +
    +#define __get_cpu_entry_area_offset_index(cpu, offset) ({ \
    + BUILD_BUG_ON(offset % PAGE_SIZE != 0); \
    + __get_cpu_entry_area_page_index(cpu, offset / PAGE_SIZE); \
    + })
    +
    +#define get_cpu_entry_area_index(cpu, field) \
    + __get_cpu_entry_area_offset_index((cpu), offsetof(struct cpu_entry_area, field))
    +
    +static inline struct cpu_entry_area *get_cpu_entry_area(int cpu)
    +{
    + return (struct cpu_entry_area *)__fix_to_virt(__get_cpu_entry_area_page_index(cpu, 0));
    +}
    +
    #endif /* !__ASSEMBLY__ */
    #endif /* _ASM_X86_FIXMAP_H */
    diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
    index ccb5f66c4e5b..c0fb3eb37ee0 100644
    --- a/arch/x86/kernel/cpu/common.c
    +++ b/arch/x86/kernel/cpu/common.c
    @@ -490,12 +490,12 @@ void load_percpu_segment(int cpu)
    load_stack_canary_segment();
    }

    -/* Setup the fixmap mapping only once per-processor */
    -static inline void setup_fixmap_gdt(int cpu)
    +/* Setup the fixmap mappings only once per-processor */
    +static inline void setup_cpu_entry_area(int cpu)
    {
    #ifdef CONFIG_X86_64
    /* On 64-bit systems, we use a read-only fixmap GDT. */
    - pgprot_t prot = PAGE_KERNEL_RO;
    + pgprot_t gdt_prot = PAGE_KERNEL_RO;
    #else
    /*
    * On native 32-bit systems, the GDT cannot be read-only because
    @@ -506,11 +506,11 @@ static inline void setup_fixmap_gdt(int cpu)
    * On Xen PV, the GDT must be read-only because the hypervisor requires
    * it.
    */
    - pgprot_t prot = boot_cpu_has(X86_FEATURE_XENPV) ?
    + pgprot_t gdt_prot = boot_cpu_has(X86_FEATURE_XENPV) ?
    PAGE_KERNEL_RO : PAGE_KERNEL;
    #endif

    - __set_fixmap(get_cpu_gdt_ro_index(cpu), get_cpu_gdt_paddr(cpu), prot);
    + __set_fixmap(get_cpu_entry_area_index(cpu, gdt), get_cpu_gdt_paddr(cpu), gdt_prot);
    }

    /* Load the original GDT from the per-cpu structure */
    @@ -1614,7 +1614,7 @@ void cpu_init(void)
    if (is_uv_system())
    uv_cpu_init();

    - setup_fixmap_gdt(cpu);
    + setup_cpu_entry_area(cpu);
    load_fixmap_gdt(cpu);
    }

    @@ -1676,7 +1676,7 @@ void cpu_init(void)

    fpu__init_cpu();

    - setup_fixmap_gdt(cpu);
    + setup_cpu_entry_area(cpu);
    load_fixmap_gdt(cpu);
    }
    #endif
    diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c
    index 2ccdaba31a07..c2454237fa67 100644
    --- a/arch/x86/xen/mmu_pv.c
    +++ b/arch/x86/xen/mmu_pv.c
    @@ -2272,7 +2272,7 @@ static void xen_set_fixmap(unsigned idx, phys_addr_t phys, pgprot_t prot)
    #endif
    case FIX_TEXT_POKE0:
    case FIX_TEXT_POKE1:
    - case FIX_GDT_REMAP_BEGIN ... FIX_GDT_REMAP_END:
    + case FIX_CPU_ENTRY_AREA_TOP ... FIX_CPU_ENTRY_AREA_BOTTOM:
    /* All local page mappings */
    pte = pfn_pte(phys, prot);
    break;
    --
    2.14.1
    \
     
     \ /
      Last update: 2017-11-24 18:34    [W:5.508 / U:0.220 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site