All of lore.kernel.org
 help / color / mirror / Atom feed
From: Zixuan Wang <zixuanwang@google.com>
To: kvm@vger.kernel.org, pbonzini@redhat.com, drjones@redhat.com
Cc: marcorr@google.com, baekhw@google.com, tmroeder@google.com,
	erdemaktas@google.com, rientjes@google.com, seanjc@google.com,
	brijesh.singh@amd.com, Thomas.Lendacky@amd.com,
	varad.gautam@suse.com, jroedel@suse.de, bp@suse.de
Subject: [kvm-unit-tests PATCH v2 06/17] x86 UEFI: Load GDT and TSS after UEFI boot up
Date: Fri, 27 Aug 2021 03:12:11 +0000	[thread overview]
Message-ID: <20210827031222.2778522-7-zixuanwang@google.com> (raw)
In-Reply-To: <20210827031222.2778522-1-zixuanwang@google.com>

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.

The GDT and TSS loading function is originally written in assembly code,
see cstart64.S load_tss function. This commit provides a similar C
function setup_gdt_tss() which is more readable and easier to modify.

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

Co-developed-by: Varad Gautam <varad.gautam@suse.com>
Signed-off-by: Varad Gautam <varad.gautam@suse.com>
Signed-off-by: Zixuan Wang <zixuanwang@google.com>
---
 lib/x86/setup.c      | 44 ++++++++++++++++++++++
 x86/efi/efistart64.S | 88 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 132 insertions(+)

diff --git a/lib/x86/setup.c b/lib/x86/setup.c
index 5e369ea..0a065fe 100644
--- a/lib/x86/setup.c
+++ b/lib/x86/setup.c
@@ -125,10 +125,54 @@ 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);
+extern phys_addr_t tss_descr;
+extern phys_addr_t ring0stacktop;
+extern gdt_entry_t gdt64[];
+extern size_t ring0stacksize;
+
+static void setup_gdt_tss(void)
+{
+	gdt_entry_t *tss_lo, *tss_hi;
+	tss64_t *curr_tss;
+	phys_addr_t curr_tss_addr;
+	u32 id;
+	size_t tss_offset;
+	size_t pre_tss_entries;
+
+	/* Get APIC ID, see also x86/cstart64.S:load_tss */
+	id = apic_id();
+
+	/* Get number of GDT entries before TSS-related GDT entry */
+	pre_tss_entries = (size_t)((u8 *)&(tss_descr) - (u8 *)gdt64) / sizeof(gdt_entry_t);
+
+	/* Each TSS descriptor takes up 2 GDT entries */
+	tss_offset = (pre_tss_entries + id * 2) * sizeof(gdt_entry_t);
+	tss_lo = &(gdt64[pre_tss_entries + id * 2 + 0]);
+	tss_hi = &(gdt64[pre_tss_entries + id * 2 + 1]);
+
+	/* Runtime address of current TSS */
+	curr_tss_addr = (((phys_addr_t)&tss) + (phys_addr_t)(id * sizeof(tss64_t)));
+
+	/* Use runtime address for ring0stacktop, see also x86/cstart64.S:tss */
+	curr_tss = (tss64_t *)curr_tss_addr;
+	curr_tss->rsp0 = (u64)((u8*)&ring0stacktop - id * ring0stacksize);
+
+	/* Update TSS descriptors */
+	tss_lo->limit_low = sizeof(tss64_t);
+	tss_lo->base_low = (u16)(curr_tss_addr & 0xffff);
+	tss_lo->base_middle = (u8)((curr_tss_addr >> 16) & 0xff);
+	tss_lo->base_high = (u8)((curr_tss_addr >> 24) & 0xff);
+	tss_hi->limit_low = (u16)((curr_tss_addr >> 32) & 0xffff);
+	tss_hi->base_low = (u16)((curr_tss_addr >> 48) & 0xffff);
+
+	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 ec607da..a14bd46 100644
--- a/x86/efi/efistart64.S
+++ b/x86/efi/efistart64.S
@@ -1,9 +1,24 @@
 /* Startup code and pre-defined data structures */
 
+#include "apic-defs.h"
+#include "asm-generic/page.h"
 #include "crt0-efi-x86_64.S"
 
 .globl boot_idt
 .globl idt_descr
+.globl tss_descr
+.globl gdt64_desc
+.globl ring0stacksize
+
+max_cpus = MAX_TEST_CPUS
+ring0stacksize = PAGE_SIZE
+
+.bss
+
+.globl ring0stacktop
+	. = . + ring0stacksize * max_cpus
+	.align 16
+ring0stacktop:
 
 .data
 
@@ -18,6 +33,48 @@ idt_descr:
 	.word end_boot_idt - boot_idt - 1
 	.quad 0 /* To be filled with runtime addr of boot_idt(%rip) */
 
+gdt64_desc:
+	.word gdt64_end - gdt64 - 1
+	.quad 0 /* To be filled with runtime addr of gdt64(%rip) */
+
+.globl gdt64
+gdt64:
+	.quad 0
+	.quad 0x00af9b000000ffff /* 64-bit code segment */
+	.quad 0x00cf93000000ffff /* 32/64-bit data segment */
+	.quad 0x00af1b000000ffff /* 64-bit code segment, not present */
+	.quad 0x00cf9b000000ffff /* 32-bit code segment */
+	.quad 0x008f9b000000FFFF /* 16-bit code segment */
+	.quad 0x008f93000000FFFF /* 16-bit data segment */
+	.quad 0x00cffb000000ffff /* 32-bit code segment (user) */
+	.quad 0x00cff3000000ffff /* 32/64-bit data segment (user) */
+	.quad 0x00affb000000ffff /* 64-bit code segment (user) */
+
+	.quad 0			 /* 6 spare selectors */
+	.quad 0
+	.quad 0
+	.quad 0
+	.quad 0
+	.quad 0
+
+tss_descr:
+	.rept max_cpus
+	.quad 0x000089000000ffff /* 64-bit avail tss */
+	.quad 0                  /* tss high addr */
+	.endr
+gdt64_end:
+
+.globl tss
+tss:
+	.rept max_cpus
+	.long 0
+	.quad 0
+	.quad 0, 0
+	.quad 0, 0, 0, 0, 0, 0, 0, 0
+	.long 0, 0, 0
+	.endr
+tss_end:
+
 .section .init
 .code64
 .text
@@ -32,3 +89,34 @@ load_idt:
 	lidtq idt_descr(%rip)
 
 	retq
+
+.globl load_gdt_tss
+load_gdt_tss:
+	/* Set GDT runtime address */
+	lea gdt64(%rip), %rax
+	mov %rax, gdt64_desc+2(%rip)
+
+	/* 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.259.gc128427fd7-goog


  parent reply	other threads:[~2021-08-27  3:12 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-08-27  3:12 [kvm-unit-tests PATCH v2 00/17] x86_64 UEFI and AMD SEV/SEV-ES support Zixuan Wang
2021-08-27  3:12 ` [kvm-unit-tests PATCH v2 01/17] x86 UEFI: Copy code from Linux Zixuan Wang
2021-09-20 14:33   ` Paolo Bonzini
2021-09-21  3:58     ` Zixuan Wang
2021-09-21  6:37       ` Varad Gautam
2021-09-21 16:33   ` Andrew Jones
2021-09-22 20:10     ` Zixuan Wang
2021-08-27  3:12 ` [kvm-unit-tests PATCH v2 02/17] x86 UEFI: Implement UEFI function calls Zixuan Wang
2021-09-21 16:43   ` Andrew Jones
2021-09-22 20:17     ` Zixuan Wang
2021-08-27  3:12 ` [kvm-unit-tests PATCH v2 03/17] x86 UEFI: Copy code from GNU-EFI Zixuan Wang
2021-10-04 12:44   ` Andrew Jones
2021-10-04 22:09     ` Zixuan Wang
2021-10-05  5:58       ` Andrew Jones
2021-08-27  3:12 ` [kvm-unit-tests PATCH v2 04/17] x86 UEFI: Boot from UEFI Zixuan Wang
2021-10-04 12:55   ` Andrew Jones
2021-10-04 21:30     ` Zixuan Wang
2021-08-27  3:12 ` [kvm-unit-tests PATCH v2 05/17] x86 UEFI: Load IDT after UEFI boot up Zixuan Wang
2021-08-27  3:12 ` Zixuan Wang [this message]
2021-09-20 15:40   ` [kvm-unit-tests PATCH v2 06/17] x86 UEFI: Load GDT and TSS " Paolo Bonzini
2021-09-21  4:15     ` Zixuan Wang
2021-08-27  3:12 ` [kvm-unit-tests PATCH v2 07/17] x86 UEFI: Set up memory allocator Zixuan Wang
2021-10-04 13:06   ` Andrew Jones
2021-10-04 21:43     ` Zixuan Wang
2021-10-05  6:05       ` Andrew Jones
2021-08-27  3:12 ` [kvm-unit-tests PATCH v2 08/17] x86 UEFI: Set up RSDP after UEFI boot up Zixuan Wang
2021-10-04 13:21   ` Andrew Jones
2021-10-04 21:58     ` Zixuan Wang
2021-08-27  3:12 ` [kvm-unit-tests PATCH v2 09/17] x86 UEFI: Set up page tables Zixuan Wang
2021-09-20 15:43   ` Paolo Bonzini
2021-09-21  4:31     ` Zixuan Wang
2021-08-27  3:12 ` [kvm-unit-tests PATCH v2 10/17] x86 UEFI: Convert x86 test cases to PIC Zixuan Wang
2021-08-27  3:12 ` [kvm-unit-tests PATCH v2 11/17] x86 AMD SEV: Initial support Zixuan Wang
2021-08-27 14:51   ` Tom Lendacky
2021-08-31 19:36     ` Zixuan Wang
2021-08-27  3:12 ` [kvm-unit-tests PATCH v2 12/17] x86 AMD SEV: Page table with c-bit Zixuan Wang
2021-08-27  3:12 ` [kvm-unit-tests PATCH v2 13/17] x86 AMD SEV-ES: Check SEV-ES status Zixuan Wang
2021-08-27 14:55   ` Tom Lendacky
2021-08-31 19:38     ` Zixuan Wang
2021-08-27  3:12 ` [kvm-unit-tests PATCH v2 14/17] x86 AMD SEV-ES: Load GDT with UEFI segments Zixuan Wang
2021-09-20 16:00   ` Paolo Bonzini
2021-09-21  4:41     ` Zixuan Wang
2021-08-27  3:12 ` [kvm-unit-tests PATCH v2 15/17] x86 AMD SEV-ES: Copy UEFI #VC IDT entry Zixuan Wang
2021-08-27  3:12 ` [kvm-unit-tests PATCH v2 16/17] x86 AMD SEV-ES: Set up GHCB page Zixuan Wang
2021-08-27  3:12 ` [kvm-unit-tests PATCH v2 17/17] x86 AMD SEV-ES: Add test cases Zixuan Wang
2021-10-04 13:27 ` [kvm-unit-tests PATCH v2 00/17] x86_64 UEFI and AMD SEV/SEV-ES support Andrew Jones
2021-10-04 20:54   ` Zixuan Wang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210827031222.2778522-7-zixuanwang@google.com \
    --to=zixuanwang@google.com \
    --cc=Thomas.Lendacky@amd.com \
    --cc=baekhw@google.com \
    --cc=bp@suse.de \
    --cc=brijesh.singh@amd.com \
    --cc=drjones@redhat.com \
    --cc=erdemaktas@google.com \
    --cc=jroedel@suse.de \
    --cc=kvm@vger.kernel.org \
    --cc=marcorr@google.com \
    --cc=pbonzini@redhat.com \
    --cc=rientjes@google.com \
    --cc=seanjc@google.com \
    --cc=tmroeder@google.com \
    --cc=varad.gautam@suse.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.