x86: use MSRs for %gs

We don't need to set up GDT data descriptors for setting
%gs. Instead, we use the x86 MSRs to set GS_BASE and
KERNEL_GS_BASE.

We don't currently allow user mode to set %gs on its own,
but later on if we do, we have everything set up to issue
'swapgs' instructions on syscall or IRQ.

Unused entries in the GDT have been removed.

Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2019-11-12 17:56:21 -08:00 committed by Anas Nashif
commit 692fda47fc
5 changed files with 40 additions and 75 deletions

View file

@ -65,7 +65,7 @@ extern struct x86_page_tables z_x86_flat_ptables;
struct x86_cpuboot x86_cpuboot[] = {
{
.tr = X86_KERNEL_CPU0_TR,
.gs = X86_KERNEL_CPU0_GS,
.gs_base = &tss0,
.sp = (u64_t) _interrupt_stack + CONFIG_ISR_STACK_SIZE,
.fn = z_x86_prep_c,
#ifdef CONFIG_X86_MMU
@ -75,19 +75,19 @@ struct x86_cpuboot x86_cpuboot[] = {
#if CONFIG_MP_NUM_CPUS > 1
{
.tr = X86_KERNEL_CPU1_TR,
.gs = X86_KERNEL_CPU1_GS,
.gs_base = &tss1
},
#endif
#if CONFIG_MP_NUM_CPUS > 2
{
.tr = X86_KERNEL_CPU2_TR,
.gs = X86_KERNEL_CPU2_GS,
.gs_base = &tss2
},
#endif
#if CONFIG_MP_NUM_CPUS > 3
{
.tr = X86_KERNEL_CPU3_TR,
.gs = X86_KERNEL_CPU3_GS,
.gs_base = &tss3
},
#endif
};

View file

@ -41,7 +41,6 @@ x86_ap_start:
movw %ax, %es
movw %ax, %ss
movw %ax, %fs
movw %ax, %gs
/*
* Now, reverse-map our local APIC ID to our logical CPU ID
@ -135,16 +134,24 @@ go64: movl %cr4, %eax /* enable PAE and SSE */
movw __x86_cpuboot_t_tr_OFFSET(%rbp), %ax
ltr %ax
movw __x86_cpuboot_t_gs_OFFSET(%rbp), %ax
movw %ax, %gs
/* Set up MSRs for GS / KERNEL_GS base */
movq __x86_cpuboot_t_gs_base_OFFSET(%rbp), %rax
movq %rax, %rdx
shrq $32, %rdx
/* X86_KERNEL_GS_BASE and X86_GS_BASE are swapped by the 'swapgs'
* instruction.
*/
movl $X86_KERNEL_GS_BASE, %ecx
wrmsr
/* X86_GS_BASE shadows base fields of %gs, effectively setting %gs */
movl $X86_GS_BASE, %ecx
wrmsr
movq __x86_cpuboot_t_sp_OFFSET(%rbp), %rsp
movq %rsp, %gs:__x86_tss64_t_ist1_OFFSET
/*
* finally, complete environment for the C runtime and go.
*/
/* finally, complete environment for the C runtime and go. */
cld /* GCC presumes a clear direction flag */
#ifdef CONFIG_INIT_STACKS
@ -602,85 +609,47 @@ pdp: .long 0x00000083 /* 0x83 = 1GB, R/W, P */
/*
* GDT - a single GDT is shared by all threads (and, eventually, all CPUs).
* This layout must agree with the selectors in intel64/kernel_arch_data.h.
* This layout must agree with the selectors in
* include/arch/x86/intel64/thread.h.
*
* The 64-bit kernel code and data segment descriptors must be in sequence as
* required by 'syscall'
*
* The 32-bit user code, 64-bit user code, and 64-bit user data segment
* descriptors must be in sequence as required by 'sysret'
*/
.align 8
gdt:
.word 0, 0, 0, 0 /* 0x00: null descriptor */
.word 0, 0, 0, 0 /* 0x00: null descriptor */
.word 0xFFFF, 0, 0x9A00, 0x00CF /* 0x08: 32-bit kernel code */
.word 0xFFFF, 0, 0x9200, 0x00CF /* 0x10: 32-bit kernel data */
.word 0, 0, 0x9800, 0x0020 /* 0x18: 64-bit kernel code */
.word 0, 0, 0x9200, 0x0000 /* 0x20: 64-bit kernel data */
.word 0, 0, 0x9800, 0x0020 /* 0x18: 64-bit kernel code */
.word 0, 0, 0x9200, 0x0000 /* 0x20: 64-bit kernel data */
.word 0, 0, 0, 0 /* 0x28: unused */
/* Remaining entries are TSS for each enabled CPU */
/*
* CPU 0 task state segment descriptors
*/
.word 0 /* 0x30: 64-bit TSS data (for GS) */
.word tss0
.word 0x9200
.word 0
.word 0, 0, 0, 0 /* 0x38: unused */
.word __X86_TSS64_SIZEOF-1 /* 0x40: 64-bit TSS (16-byte entry) */
.word __X86_TSS64_SIZEOF-1 /* 0x28: 64-bit TSS (16-byte entry) */
.word tss0
.word 0x8900
.word 0, 0, 0, 0, 0
#if CONFIG_MP_NUM_CPUS > 1
/*
* CPU 1 task state segment descriptors
*/
.word 0 /* 0x50: 64-bit TSS data (for GS) */
.word tss1
.word 0x9200
.word 0
.word 0, 0, 0, 0 /* 0x58: unused */
.word __X86_TSS64_SIZEOF-1 /* 0x60: 64-bit TSS (16-byte entry) */
.word __X86_TSS64_SIZEOF-1 /* 0x38: 64-bit TSS (16-byte entry) */
.word tss1
.word 0x8900
.word 0, 0, 0, 0, 0
#endif
#if CONFIG_MP_NUM_CPUS > 2
/*
* CPU 2 task state segment descriptors
*/
.word 0 /* 0x70: 64-bit TSS data (for GS) */
.word tss2
.word 0x9200
.word 0
.word 0, 0, 0, 0 /* 0x78: unused */
.word __X86_TSS64_SIZEOF-1 /* 0x80: 64-bit TSS (16-byte entry) */
.word __X86_TSS64_SIZEOF-1 /* 0x48: 64-bit TSS (16-byte entry) */
.word tss2
.word 0x8900
.word 0, 0, 0, 0, 0
#endif
#if CONFIG_MP_NUM_CPUS > 3
/*
* CPU 3 task state segment descriptors
*/
.word 0 /* 0x90: 64-bit TSS data (for GS) */
.word tss3
.word 0x9200
.word 0
.word 0, 0, 0, 0 /* 0x98: unused */
.word __X86_TSS64_SIZEOF-1 /* 0xA0: 64-bit TSS (16-byte entry) */
.word __X86_TSS64_SIZEOF-1 /* 0x58: 64-bit TSS (16-byte entry) */
.word tss3
.word 0x8900
.word 0, 0, 0, 0, 0

View file

@ -30,7 +30,7 @@ GEN_ABSOLUTE_SYM(__X86_TSS64_SIZEOF, sizeof(x86_tss64_t));
GEN_OFFSET_SYM(x86_cpuboot_t, ready);
GEN_OFFSET_SYM(x86_cpuboot_t, tr);
GEN_OFFSET_SYM(x86_cpuboot_t, gs);
GEN_OFFSET_SYM(x86_cpuboot_t, gs_base);
GEN_OFFSET_SYM(x86_cpuboot_t, sp);
GEN_OFFSET_SYM(x86_cpuboot_t, fn);
GEN_OFFSET_SYM(x86_cpuboot_t, arg);

View file

@ -21,7 +21,7 @@ extern char _locore_start[], _locore_end[];
struct x86_cpuboot {
volatile int ready; /* CPU has started */
u16_t tr; /* selector for task register */
u16_t gs; /* selector for GS */
struct x86_tss64 *gs_base; /* Base address for GS segment */
u64_t sp; /* initial stack pointer */
void *fn; /* kernel entry function */
void *arg; /* argument for above function */

View file

@ -17,14 +17,10 @@
#define X86_KERNEL_CS 0x18 /* 64-bit kernel code */
#define X86_KERNEL_DS 0x20 /* 64-bit kernel data */
#define X86_KERNEL_CPU0_GS 0x30 /* data selector covering TSS */
#define X86_KERNEL_CPU0_TR 0x40 /* 64-bit task state segment */
#define X86_KERNEL_CPU1_GS 0x50 /* data selector covering TSS */
#define X86_KERNEL_CPU1_TR 0x60 /* 64-bit task state segment */
#define X86_KERNEL_CPU2_GS 0x70 /* data selector covering TSS */
#define X86_KERNEL_CPU2_TR 0x80 /* 64-bit task state segment */
#define X86_KERNEL_CPU3_GS 0x90 /* data selector covering TSS */
#define X86_KERNEL_CPU3_TR 0xA0 /* 64-bit task state segment */
#define X86_KERNEL_CPU0_TR 0x28 /* 64-bit task state segment */
#define X86_KERNEL_CPU1_TR 0x38 /* 64-bit task state segment */
#define X86_KERNEL_CPU2_TR 0x48 /* 64-bit task state segment */
#define X86_KERNEL_CPU3_TR 0x58 /* 64-bit task state segment */
/*
* Some SSE definitions. Ideally these will ultimately be shared with 32-bit.