x86: implement kernel page table isolation

Implement a set of per-cpu trampoline stacks which all
interrupts and exceptions will initially land on, and also
as an intermediate stack for privilege changes as we need
some stack space to swap page tables.

Set up the special trampoline page which contains all the
trampoline stacks, TSS, and GDT. This page needs to be
present in the user page tables or interrupts don't work.

CPU exceptions, with KPTI turned on, are treated as interrupts
and not traps so that we have IRQs locked on exception entry.

Add some additional macros for defining IDT entries.

Add special handling of locore text/rodata sections when
creating user mode page tables on x86-64.

Restore qemu_x86_64 to use KPTI, and remove restrictions on
enabling user mode on x86-64.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2019-12-18 23:57:25 -08:00 committed by Anas Nashif
commit e34f1cee06
12 changed files with 493 additions and 139 deletions

View file

@ -36,8 +36,35 @@ SECTIONS
*(.lorodata)
MMU_PAGE_ALIGN
_lodata_start = .;
*(.tss)
*(.lodata)
#ifdef CONFIG_X86_KPTI
/* Special page containing supervisor data that is still mapped in
* user mode page tables. GDT, TSSes, trampoline stack, and
* any LDT must go here as they always must live in a page that is
* marked 'present'. Still not directly user accessible, but
* no sensitive data should be here as Meltdown exploits may read it.
*
* On x86-64 the IDT is in rodata and doesn't need to be in the
* trampoline page.
*/
MMU_PAGE_ALIGN
z_shared_kernel_page_start = .;
#endif /* CONFIG_X86_KPTI */
*(.tss)
*(.gdt)
#ifdef CONFIG_X86_KPTI
*(.trampolines)
MMU_PAGE_ALIGN
z_shared_kernel_page_end = .;
ASSERT(z_shared_kernel_page_end - z_shared_kernel_page_start == 4096,
"shared kernel area is not one memory page");
#endif /* CONFIG_X86_KPTI */
MMU_PAGE_ALIGN
_lodata_end = .;
}

View file

@ -84,7 +84,7 @@ struct x86_tss64 {
/* Storage area for user mode stack pointer when doing a syscall */
char *usp;
#endif
#endif /* CONFIG_USERSPACE */
} __packed __aligned(8);
typedef struct x86_tss64 x86_tss64_t;