Core mappings are the minimal mappings we need to be able to enter isolation and handle an isolation abort or exit. This includes the kernel code, the GDT and the percpu ASI sessions. We also need a stack so we map the current stack when entering isolation and unmap it on exit/abort. Signed-off-by: Alexandre Chartre <alexandre.chartre@xxxxxxxxxx> --- arch/x86/include/asm/asi.h | 2 ++ arch/x86/mm/asi.c | 57 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/arch/x86/include/asm/asi.h b/arch/x86/include/asm/asi.h index ac0594d4f549..eafed750e07f 100644 --- a/arch/x86/include/asm/asi.h +++ b/arch/x86/include/asm/asi.h @@ -45,6 +45,7 @@ #include <linux/export.h> #include <asm/asi_session.h> +#include <asm/dpt.h> /* * ASI_NR_DYN_ASIDS is the same as TLB_NR_DYN_ASIDS. We can't directly @@ -150,6 +151,7 @@ extern void asi_destroy(struct asi *asi); extern void asi_set_pagetable(struct asi *asi, pgd_t *pagetable); extern int asi_enter(struct asi *asi); extern void asi_exit(struct asi *asi); +extern int asi_init_dpt(struct dpt *dpt); #ifdef CONFIG_PAGE_TABLE_ISOLATION DECLARE_ASI_TYPE(user); diff --git a/arch/x86/mm/asi.c b/arch/x86/mm/asi.c index b63a0a883293..8b670ed13729 100644 --- a/arch/x86/mm/asi.c +++ b/arch/x86/mm/asi.c @@ -162,6 +162,63 @@ void asi_set_pagetable(struct asi *asi, pgd_t *pagetable) } EXPORT_SYMBOL(asi_set_pagetable); +/* + * asi_init_dpt - Initialize a decorated page-table with the minimum + * mappings for using an ASI. Note that this function doesn't map any + * stack. If the stack of the task entering an ASI is not mapped then + * this will trigger a double-fault as soon as the task tries to access + * its stack. + */ +int asi_init_dpt(struct dpt *dpt) +{ + int err; + + /* + * Map the kernel. + * + * XXX We should check if we can map only kernel text, i.e. map with + * size = _etext - _text + */ + err = dpt_map(dpt, (void *)__START_KERNEL_map, KERNEL_IMAGE_SIZE); + if (err) + return err; + + /* + * Map the cpu_entry_area because we need the GDT to be mapped. + * Not sure we need anything else from cpu_entry_area. + */ + err = dpt_map_range(dpt, (void *)CPU_ENTRY_AREA_PER_CPU, P4D_SIZE, + PGT_LEVEL_P4D); + if (err) + return err; + + /* + * Map fixed_percpu_data to get the stack canary. + */ + if (IS_ENABLED(CONFIG_STACKPROTECTOR)) { + err = DPT_MAP_CPUVAR(dpt, fixed_percpu_data); + if (err) + return err; + } + + /* Map current_task, we need it for __schedule() */ + err = DPT_MAP_CPUVAR(dpt, current_task); + if (err) + return err; + + /* + * Map the percpu ASI tlbstate. This also maps the asi_session + * which is used by interrupt handlers to figure out if we have + * entered isolation and switch back to the kernel address space. + */ + err = DPT_MAP_CPUVAR(dpt, cpu_tlbstate); + if (err) + return err; + + return 0; +} +EXPORT_SYMBOL(asi_init_dpt); + /* * Update ASI TLB flush information for the specified ASI CR3 value. * Return an updated ASI CR3 value which specified if TLB needs to -- 2.18.2