[kvm-unit-tests PATCH v3 07/17] x86 UEFI: Load GDT and TSS after UEFI boot up

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: Zixuan Wang <zixuanwang@xxxxxxxxxx>

Global Descriptor Table (GDT) defines x86 memory areas, e.g. memory area
for data or code. UEFI has a different GDT compared to KVM-Unit-Tests,
e.g., in UEFI, 3rd GDT entry defines a code segment, while in
KVM-Unit-Tests, 3rd GDT entry is data segment.

Without loading KVM-Unit-Tests GDT, the UEFI GDT is used and is
incompatible with KVM-Unit-Tests. This causes QEMU to silently crash
when a test case changes segments.

This commit fixes this issue by loading KVM-Unit-Tests GDT to replace
UEFI GDT. And since Task State Segment (TSS) is tightly coupled with
GDT, this commit also loads TSS on boot-up.

In this commit, x86/debug.c can run in UEFI and pass all sub-tests.

Co-developed-by: Varad Gautam <varad.gautam@xxxxxxxx>
Signed-off-by: Varad Gautam <varad.gautam@xxxxxxxx>
Signed-off-by: Zixuan Wang <zixuanwang@xxxxxxxxxx>
---
 lib/x86/setup.c      | 10 ++++++++++
 x86/efi/efistart64.S | 42 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 52 insertions(+)

diff --git a/lib/x86/setup.c b/lib/x86/setup.c
index 8606fe8..f4f9e1b 100644
--- a/lib/x86/setup.c
+++ b/lib/x86/setup.c
@@ -165,10 +165,20 @@ void setup_multiboot(struct mbi_bootinfo *bi)
 
 /* From x86/efi/efistart64.S */
 extern void load_idt(void);
+extern void load_gdt_tss(size_t tss_offset);
+
+static void setup_gdt_tss(void)
+{
+	size_t tss_offset;
+
+	tss_offset = setup_tss();
+	load_gdt_tss(tss_offset);
+}
 
 void setup_efi(void)
 {
 	reset_apic();
+	setup_gdt_tss();
 	setup_idt();
 	load_idt();
 	mask_pic_interrupts();
diff --git a/x86/efi/efistart64.S b/x86/efi/efistart64.S
index 41e9185..57299a5 100644
--- a/x86/efi/efistart64.S
+++ b/x86/efi/efistart64.S
@@ -1,7 +1,22 @@
 /* Startup code and pre-defined data structures */
 
+#include "apic-defs.h"
+#include "asm-generic/page.h"
 #include "crt0-efi-x86_64.S"
 
+.globl ring0stacktop
+.globl ring0stacksize
+
+max_cpus = MAX_TEST_CPUS
+ring0stacksize = PAGE_SIZE
+
+.bss
+
+.globl ring0stacktop
+	. = . + ring0stacksize * max_cpus
+	.align 16
+ring0stacktop:
+
 .section .init
 .code64
 .text
@@ -10,3 +25,30 @@
 load_idt:
 	lidtq idt_descr(%rip)
 	retq
+
+.globl load_gdt_tss
+load_gdt_tss:
+	/* Load GDT */
+	lgdt gdt64_desc(%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
-- 
2.33.0




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux