@@ -362,6 +362,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)
{
@@ -222,6 +222,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);
@@ -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)
@@ -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
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@suse.com> --- 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(-)