x86: use per-thread page tables

Previously, context switching on x86 with memory protection
enabled involved walking the page tables, de-configuring all
the partitions in the outgoing thread's memory domain, and
then configuring all the partitions in the incoming thread's
domain, on a global set of page tables.

We now have a much faster design. Each thread has reserved in
its stack object a number of pages to store page directories
and page tables pertaining to the system RAM area. Each
thread also has a toplevel PDPT which is configured to use
the per-thread tables for system RAM, and the global tables
for the rest of the address space.

The result of this is on context switch, at most we just have
to update the CR3 register to the incoming thread's PDPT.

The x86_mmu_api test was making too many assumptions and has
been adjusted to work with the new design.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2019-07-29 18:22:30 -07:00 committed by Carles Cufí
commit 8014e075f4
10 changed files with 558 additions and 318 deletions

View file

@ -35,6 +35,7 @@
#ifndef _ASMLANGUAGE
#include <stdint.h>
#include <ia32/mmustructs.h>
/*
* The following structure defines the set of 'non-volatile' integer registers.
@ -221,6 +222,24 @@ struct _thread_arch {
* struct without ill effect.
*/
tPreempFloatReg preempFloatReg; /* volatile float register storage */
#ifdef CONFIG_USERSPACE
/* Per-thread page directory pointer table when a thread is running
* in user mode.
*
* With KPTI enabled, any privilege elevation while that thread is
* running, or ISR will switch to the master kernel pdpt at
* z_x86_kernel_pdpt; the memory domain policy will not apply at
* all.
*
* With KPTI disabled, this pdpt will be active at all times when
* the thread is running. This has implications for memory domain
* partitions that are read-only!!
*
* See #17833 for more discussion.
*/
__aligned(0x20) struct x86_mmu_pdpt user_pdpt;
#endif /* CONFIG_USERSPACE */
};
typedef struct _thread_arch _thread_arch_t;