x86: Add support for SW-switched segment-based protection domains
This patch extends the protection domain framework with a third plugin that is a hybrid of the previous two. The hardware task switching mechanism has a strictly-defined format for TSS data structures that causes more space to be consumed than would otherwise be required. This patch defines a smaller data structure that is allocated for each protection domain, only requiring 32 bytes instead of 128 bytes. It uses the same multi-segment memory layout as the TSS-based plugin and leaves paging disabled. However, it uses a similar mechanism as the paging plugin to perform system call dispatches and returns. For additional information, please refer to cpu/x86/mm/README.md.
This commit is contained in:
parent
4cdb7ba9b6
commit
e0aefd11d9
13 changed files with 335 additions and 38 deletions
|
@ -33,6 +33,10 @@
|
|||
#include "gdt-layout.h"
|
||||
#include "stacks.h"
|
||||
|
||||
/* Must match definitions (plus the trailing 's') in multi-segment.h */
|
||||
#define SEG_MMIO fs
|
||||
#define SEG_KERN fs
|
||||
|
||||
.text
|
||||
|
||||
/* Invoke the system call return dispatcher from the default privilege
|
||||
|
@ -42,21 +46,57 @@
|
|||
prot_domains_sysret_stub:
|
||||
int $PROT_DOMAINS_SYSRET_DISPATCH_INT
|
||||
|
||||
.macro save_segs
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__SWSEG
|
||||
/* Save (and restore, in restore_segs) MMIO segment register into
|
||||
* callee-saved register in case a system call was invoked from a region in
|
||||
* which MMIO is enabled.
|
||||
*/
|
||||
push %SEG_MMIO
|
||||
#endif
|
||||
.endm
|
||||
|
||||
.macro restore_segs
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__SWSEG
|
||||
pop %SEG_MMIO
|
||||
#endif
|
||||
.endm
|
||||
|
||||
/* Refresh most of the segment registers in case they were corrupted by
|
||||
* userspace code to prevent that from corrupting the operation of the
|
||||
* privileged code.
|
||||
*/
|
||||
.macro load_kern_segs
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__SWSEG
|
||||
mov $GDT_SEL_DATA, %eax
|
||||
mov %eax, %ds
|
||||
mov %eax, %es
|
||||
mov $GDT_SEL_DATA_KERN_EXC, %eax
|
||||
mov %eax, %SEG_KERN
|
||||
#endif
|
||||
.endm
|
||||
|
||||
/* Invoke the system call dispatcher C routine */
|
||||
.global prot_domains_syscall_dispatcher
|
||||
prot_domains_syscall_dispatcher:
|
||||
mov %esp, %ecx /*< interrupt_stack_t *intr_stk */
|
||||
/* EDX already set to "dom_client_data_t to_dcd" by syscall stub */
|
||||
push %eax /*< syscalls_id_t syscall_id */
|
||||
save_segs
|
||||
push %eax /*< syscalls_entrypoint_t *syscall */
|
||||
load_kern_segs
|
||||
call prot_domains_syscall_dispatcher_impl
|
||||
/* fastcall convention, so callee pops arguments */
|
||||
restore_segs
|
||||
iret
|
||||
|
||||
/* Invoke the system call return dispatcher C routine */
|
||||
.global prot_domains_sysret_dispatcher
|
||||
prot_domains_sysret_dispatcher:
|
||||
mov %esp, %ecx /*< interrupt_stack_t *intr_stk */
|
||||
save_segs
|
||||
load_kern_segs
|
||||
call prot_domains_sysret_dispatcher_impl
|
||||
restore_segs
|
||||
/* Zero caller-saved registers in case they contain secrets. The system call
|
||||
* handlers and dispatchers need to preserve the callee-saved registers.
|
||||
*/
|
||||
|
@ -67,11 +107,17 @@ prot_domains_sysret_dispatcher:
|
|||
|
||||
.global prot_domains_launch_kernel
|
||||
prot_domains_launch_kernel:
|
||||
#if X86_CONF_PROT_DOMAINS == X86_CONF_PROT_DOMAINS__PAGING
|
||||
mov $GDT_SEL_DATA, %eax
|
||||
mov %eax, %ds
|
||||
mov %eax, %es
|
||||
mov %eax, %fs
|
||||
mov %eax, %gs
|
||||
#else
|
||||
mov $GDT_SEL_LDT(DOM_ID_kern), %eax
|
||||
lldt %ax
|
||||
call multi_segment_launch_kernel
|
||||
#endif
|
||||
/* init interrupt return stack: */
|
||||
pushl $GDT_SEL_STK
|
||||
lea stacks_main, %eax
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue