From: Varad Gautam <varad.gautam@xxxxxxxx> Split load_gdt_tss() functionality into: 1. Load gdt/tss 2. Setup segments in 64-bit mode and update %cs via far-return and move load_gdt_tss() to desc.c to share this code between EFI and non-EFI tests. Move the segment setup code specific to EFI into setup.c:setup_segments64(). Signed-off-by: Varad Gautam <varad.gautam@xxxxxxxx> Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx> --- lib/x86/desc.c | 6 ++++++ lib/x86/desc.h | 1 + lib/x86/setup.c | 25 +++++++++++++++++++++++-- x86/efi/efistart64.S | 27 --------------------------- 4 files changed, 30 insertions(+), 29 deletions(-) diff --git a/lib/x86/desc.c b/lib/x86/desc.c index 9512363..a7c3480 100644 --- a/lib/x86/desc.c +++ b/lib/x86/desc.c @@ -361,6 +361,12 @@ void set_gdt_entry(int sel, unsigned long base, u32 limit, u8 type, u8 flags) #endif } +void load_gdt_tss(size_t tss_offset) +{ + lgdt(&gdt_descr); + ltr(tss_offset); +} + #ifndef __x86_64__ void set_gdt_task_gate(u16 sel, u16 tss_sel) { diff --git a/lib/x86/desc.h b/lib/x86/desc.h index 1dc1ea0..9dcc92b 100644 --- a/lib/x86/desc.h +++ b/lib/x86/desc.h @@ -223,6 +223,7 @@ void set_idt_entry(int vec, void *addr, int dpl); void set_idt_sel(int vec, u16 sel); void set_idt_dpl(int vec, u16 dpl); void set_gdt_entry(int sel, unsigned long base, u32 limit, u8 access, u8 gran); +void load_gdt_tss(size_t tss_offset); void set_intr_alt_stack(int e, void *fn); void print_current_tss_info(void); handler handle_exception(u8 v, handler fn); diff --git a/lib/x86/setup.c b/lib/x86/setup.c index dd2b916..9724465 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -169,8 +169,27 @@ void setup_multiboot(struct mbi_bootinfo *bi) #ifdef CONFIG_EFI -/* From x86/efi/efistart64.S */ -extern void load_gdt_tss(size_t tss_offset); +static void setup_segments64(void) +{ + /* Update data segments */ + write_ds(KERNEL_DS); + write_es(KERNEL_DS); + write_fs(KERNEL_DS); + write_gs(KERNEL_DS); + write_ss(KERNEL_DS); + + /* + * Update the code segment by putting it on the stack before the return + * address, then doing a far return: this will use the new code segment + * along with the address. + */ + asm volatile("pushq %1\n\t" + "lea 1f(%%rip), %0\n\t" + "pushq %0\n\t" + "lretq\n\t" + "1:" + :: "r" ((u64)KERNEL_DS), "i" (KERNEL_CS)); +} static efi_status_t setup_memory_allocator(efi_bootinfo_t *efi_bootinfo) { @@ -275,6 +294,8 @@ static void setup_gdt_tss(void) /* 64-bit setup_tss does not use the stacktop argument. */ tss_offset = setup_tss(NULL); load_gdt_tss(tss_offset); + + setup_segments64(); } efi_status_t setup_efi(efi_bootinfo_t *efi_bootinfo) diff --git a/x86/efi/efistart64.S b/x86/efi/efistart64.S index 98cc965..b94c5ab 100644 --- a/x86/efi/efistart64.S +++ b/x86/efi/efistart64.S @@ -26,33 +26,6 @@ ptl4: .code64 .text -.globl load_gdt_tss -load_gdt_tss: - /* Load GDT */ - lgdt gdt_descr(%rip) - - /* Load TSS */ - mov %rdi, %rax - ltr %ax - - /* Update data segments */ - mov $0x10, %ax /* 3rd entry in gdt64: 32/64-bit data segment */ - mov %ax, %ds - mov %ax, %es - mov %ax, %fs - mov %ax, %gs - mov %ax, %ss - - /* - * Update the code segment by putting it on the stack before the return - * address, then doing a far return: this will use the new code segment - * along with the address. - */ - popq %rdi - pushq $0x08 /* 2nd entry in gdt64: 64-bit code segment */ - pushq %rdi - lretq - .code16 .globl rm_trampoline -- 2.36.1.476.g0c4daa206d-goog