diff mbox series

[kvm-unit-tests,v3,01/17] x86: Move IDT, GDT and TSS to desc.c

Message ID 20211004204931.1537823-2-zxwang42@gmail.com (mailing list archive)
State New, archived
Headers show
Series x86_64 UEFI and AMD SEV/SEV-ES support | expand

Commit Message

Zixuan Wang Oct. 4, 2021, 8:49 p.m. UTC
From: Zixuan Wang <zixuanwang@google.com>

Move the IDT, GDT and TSS data structures from x86/cstart64.S to
lib/x86/desc.c, so that the follow-up UEFI support commits can reuse
these definitions, without re-defining them in UEFI's boot up assembly
code.

In this commit, tss_descr is defined as a pointer, instead of an
assembly label. This type change leads to several updates in the
x86/vmx.c. Fortunately x86/vmx.c is only used in x86_64, so it is not
necessary to be compatible with i386's tss_descr type which is an
assembly label.

Signed-off-by: Zixuan Wang <zixuanwang@google.com>
---
 lib/x86/asm/setup.h |  8 +++++
 lib/x86/desc.c      | 46 ++++++++++++++++++++++++++-
 lib/x86/desc.h      |  6 +++-
 lib/x86/setup.c     | 43 +++++++++++++++++++++++++
 x86/cstart64.S      | 77 ++-------------------------------------------
 x86/vmx.c           |  8 ++---
 6 files changed, 107 insertions(+), 81 deletions(-)
 create mode 100644 lib/x86/asm/setup.h

Comments

Paolo Bonzini Oct. 20, 2021, 3:26 p.m. UTC | #1
On 04/10/21 22:49, Zixuan Wang wrote:
> +/* In gdt64, there are 16 entries before TSS entries */
> +#define GDT64_PRE_TSS_ENTRIES (16)
> +#define GDT64_TSS_OFFSET (GDT64_PRE_TSS_ENTRIES)

No need to have both; in fact the definition can also be changed to 
TSS_MAIN/8.

tss_descr is completely broken in the current code, I'll send a patch to 
fix it so you don't have to deal with it.

Paolo

> +extern gdt_entry_t gdt64[];
Zixuan Wang Oct. 20, 2021, 5:56 p.m. UTC | #2
On Wed, Oct 20, 2021 at 8:26 AM Paolo Bonzini <pbonzini@redhat.com> wrote:
>
> On 04/10/21 22:49, Zixuan Wang wrote:
> > +/* In gdt64, there are 16 entries before TSS entries */
> > +#define GDT64_PRE_TSS_ENTRIES (16)
> > +#define GDT64_TSS_OFFSET (GDT64_PRE_TSS_ENTRIES)
>
> No need to have both; in fact the definition can also be changed to
> TSS_MAIN/8.

I did not realize there is a TSS_MAIN, I will update this part.

> tss_descr is completely broken in the current code, I'll send a patch to
> fix it so you don't have to deal with it.
>
> Paolo

I just noticed the new patchset to fix the tss_descr, I will build the
V4 patchset based on that fix.

Best regards,
Zixuan
Paolo Bonzini Oct. 21, 2021, 11:50 a.m. UTC | #3
On 20/10/21 19:56, Zixuan Wang wrote:
>> tss_descr is completely broken in the current code, I'll send a patch to
>> fix it so you don't have to deal with it.
>>
>> Paolo
> I just noticed the new patchset to fix the tss_descr, I will build the
> V4 patchset based on that fix.

Don't worry, there's a lot more work to cleanup GDT/TSS/IDT and I don't 
want to "force" you to do that.  Let me go on with the review of this 
series so that you can concentrate on the UEFI bits.

Paolo
diff mbox series

Patch

diff --git a/lib/x86/asm/setup.h b/lib/x86/asm/setup.h
new file mode 100644
index 0000000..19ded12
--- /dev/null
+++ b/lib/x86/asm/setup.h
@@ -0,0 +1,8 @@ 
+#ifndef _X86_ASM_SETUP_H_
+#define _X86_ASM_SETUP_H_
+
+#ifdef __x86_64__
+unsigned long setup_tss(void);
+#endif /* __x86_64__ */
+
+#endif /* _X86_ASM_SETUP_H_ */
diff --git a/lib/x86/desc.c b/lib/x86/desc.c
index e7378c1..d1eb97b 100644
--- a/lib/x86/desc.c
+++ b/lib/x86/desc.c
@@ -3,6 +3,50 @@ 
 #include "processor.h"
 #include <setjmp.h>
 
+#ifdef __x86_64__
+#include "apic-defs.h"
+
+/* Boot-related data structures */
+
+/* IDT and IDT descriptor */
+idt_entry_t boot_idt[256] = {0};
+
+struct descriptor_table_ptr idt_descr = {
+	.limit = sizeof(boot_idt) - 1,
+	.base = (phys_addr_t)boot_idt,
+};
+
+/* GDT, TSS and descriptors */
+gdt_entry_t gdt64[GDT64_PRE_TSS_ENTRIES + MAX_TEST_CPUS * 2] = {
+	{     0, 0, 0, 0x00, 0x00, 0}, /* 0x00 null */
+	{0xffff, 0, 0, 0x9b, 0xaf, 0}, /* 0x08 64-bit code segment */
+	{0xffff, 0, 0, 0x93, 0xcf, 0}, /* 0x10 32/64-bit data segment */
+	{0xffff, 0, 0, 0x1b, 0xaf, 0}, /* 0x18 64-bit code segment, not present */
+	{0xffff, 0, 0, 0x9b, 0xcf, 0}, /* 0x20 32-bit code segment */
+	{0xffff, 0, 0, 0x9b, 0x8f, 0}, /* 0x28 16-bit code segment */
+	{0xffff, 0, 0, 0x93, 0x8f, 0}, /* 0x30 16-bit data segment */
+	{0xffff, 0, 0, 0xfb, 0xcf, 0}, /* 0x38 32-bit code segment (user) */
+	{0xffff, 0, 0, 0xf3, 0xcf, 0}, /* 0x40 32/64-bit data segment (user) */
+	{0xffff, 0, 0, 0xfb, 0xaf, 0}, /* 0x48 64-bit code segment (user) */
+	{     0, 0, 0, 0x00, 0x00, 0}, /* 0x50 null */
+	{     0, 0, 0, 0x00, 0x00, 0}, /* 0x58 null */
+	{     0, 0, 0, 0x00, 0x00, 0}, /* 0x60 null */
+	{     0, 0, 0, 0x00, 0x00, 0}, /* 0x68 null */
+	{     0, 0, 0, 0x00, 0x00, 0}, /* 0x70 null */
+	{     0, 0, 0, 0x00, 0x00, 0}, /* 0x78 null */
+};
+
+struct descriptor_table_ptr gdt64_desc = {
+	.limit = sizeof(gdt64) - 1,
+	.base = (phys_addr_t)gdt64,
+};
+
+struct descriptor_table_ptr *tss_descr =
+	(struct descriptor_table_ptr *)&gdt64[GDT64_PRE_TSS_ENTRIES];
+
+tss64_t tss[MAX_TEST_CPUS] = {0};
+#endif
+
 #ifndef __x86_64__
 __attribute__((regparm(1)))
 #endif
@@ -374,7 +418,7 @@  void set_intr_alt_stack(int e, void *addr)
 
 void setup_alt_stack(void)
 {
-	tss.ist1 = (u64)intr_alt_stack + 4096;
+	tss[0].ist1 = (u64)intr_alt_stack + 4096;
 }
 #endif
 
diff --git a/lib/x86/desc.h b/lib/x86/desc.h
index a6ffb38..c7ee881 100644
--- a/lib/x86/desc.h
+++ b/lib/x86/desc.h
@@ -208,7 +208,11 @@  void set_idt_task_gate(int vec, u16 sel);
 void set_intr_task_gate(int vec, void *fn);
 void setup_tss32(void);
 #else
-extern tss64_t tss;
+extern tss64_t tss[];
+/* In gdt64, there are 16 entries before TSS entries */
+#define GDT64_PRE_TSS_ENTRIES (16)
+#define GDT64_TSS_OFFSET (GDT64_PRE_TSS_ENTRIES)
+extern gdt_entry_t gdt64[];
 #endif
 
 unsigned exception_vector(void);
diff --git a/lib/x86/setup.c b/lib/x86/setup.c
index 7befe09..8c73156 100644
--- a/lib/x86/setup.c
+++ b/lib/x86/setup.c
@@ -2,6 +2,7 @@ 
  * Initialize machine setup information
  *
  * Copyright (C) 2017, Red Hat Inc, Andrew Jones <drjones@redhat.com>
+ * Copyright (C) 2021, Google Inc, Zixuan Wang <zixuanwang@google.com>
  *
  * This work is licensed under the terms of the GNU LGPL, version 2.
  */
@@ -9,6 +10,10 @@ 
 #include "fwcfg.h"
 #include "alloc_phys.h"
 #include "argv.h"
+#include "desc.h"
+#include "apic.h"
+#include "apic-defs.h"
+#include "asm/setup.h"
 
 extern char edata;
 
@@ -97,6 +102,44 @@  void find_highmem(void)
 		phys_alloc_init(best_start, best_end - best_start);
 	}
 }
+
+extern phys_addr_t ring0stacktop;
+
+/* Setup TSS for the current processor, and return TSS offset within gdt64 */
+unsigned long setup_tss(void)
+{
+	u32 id;
+	gdt_entry_t *gdt_entry_lo, *gdt_entry_hi;
+	tss64_t *tss_entry;
+	phys_addr_t tss_entry_addr;
+
+	id = apic_id();
+
+	/* Runtime address of current TSS */
+	tss_entry = &tss[id];
+	tss_entry_addr = (phys_addr_t)tss_entry;
+
+	/* Update TSS */
+	memset((void *)tss_entry, 0, sizeof(tss64_t));
+	tss_entry->rsp0 = (u64)((u8*)&ring0stacktop - id * 4096);
+
+	/* Each TSS descriptor takes up 2 GDT entries */
+	gdt_entry_lo = &gdt64[GDT64_PRE_TSS_ENTRIES + id * 2 + 0];
+	gdt_entry_hi = &gdt64[GDT64_PRE_TSS_ENTRIES + id * 2 + 1];
+
+	/* Update TSS descriptors */
+	memset((void *)gdt_entry_lo, 0, sizeof(gdt_entry_t));
+	memset((void *)gdt_entry_hi, 0, sizeof(gdt_entry_t));
+	gdt_entry_lo->access      = 0x89;
+	gdt_entry_lo->limit_low   = 0xffff;
+	gdt_entry_lo->base_low    = (u16)(tss_entry_addr & 0xffff);
+	gdt_entry_lo->base_middle =  (u8)((tss_entry_addr >> 16) & 0xff);
+	gdt_entry_lo->base_high   =  (u8)((tss_entry_addr >> 24) & 0xff);
+	gdt_entry_hi->limit_low   = (u16)((tss_entry_addr >> 32) & 0xffff);
+	gdt_entry_hi->base_low    = (u16)((tss_entry_addr >> 48) & 0xffff);
+
+	return (GDT64_PRE_TSS_ENTRIES + id * 2) * sizeof(gdt_entry_t);
+}
 #endif
 
 void setup_multiboot(struct mbi_bootinfo *bi)
diff --git a/x86/cstart64.S b/x86/cstart64.S
index 5c6ad38..57383c1 100644
--- a/x86/cstart64.S
+++ b/x86/cstart64.S
@@ -1,11 +1,7 @@ 
 
 #include "apic-defs.h"
 
-.globl boot_idt
-
-.globl idt_descr
-.globl tss_descr
-.globl gdt64_desc
+.globl ring0stacktop
 .globl online_cpus
 .globl cpu_online_count
 
@@ -51,56 +47,6 @@  ptl5:
 
 .align 4096
 
-boot_idt:
-	.rept 256
-	.quad 0
-	.quad 0
-	.endr
-end_boot_idt:
-
-gdt64_desc:
-	.word gdt64_end - gdt64 - 1
-	.quad 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:
-
-i = 0
-.globl tss
-tss:
-	.rept max_cpus
-	.long 0
-	.quad ring0stacktop - i * 4096
-	.quad 0, 0
-	.quad 0, 0, 0, 0, 0, 0, 0, 0
-	.long 0, 0, 0
-i = i + 1
-	.endr
-tss_end:
-
 mb_boot_info:	.quad 0
 
 pt_root:	.quad ptl4
@@ -291,31 +237,12 @@  setup_5level_page_table:
 lvl5:
 	retq
 
-idt_descr:
-	.word end_boot_idt - boot_idt - 1
-	.quad boot_idt
-
 online_cpus:
 	.fill (max_cpus + 7) / 8, 1, 0
 
 load_tss:
 	lidtq idt_descr
-	mov $(APIC_DEFAULT_PHYS_BASE + APIC_ID), %eax
-	mov (%rax), %eax
-	shr $24, %eax
-	mov %eax, %ebx
-	shl $4, %ebx
-	mov $((tss_end - tss) / max_cpus), %edx
-	imul %edx
-	add $tss, %rax
-	mov %ax, tss_descr+2(%rbx)
-	shr $16, %rax
-	mov %al, tss_descr+4(%rbx)
-	shr $8, %rax
-	mov %al, tss_descr+7(%rbx)
-	shr $8, %rax
-	mov %eax, tss_descr+8(%rbx)
-	lea tss_descr-gdt64(%rbx), %rax
+	call setup_tss
 	ltr %ax
 	ret
 
diff --git a/x86/vmx.c b/x86/vmx.c
index f0b853a..37aff12 100644
--- a/x86/vmx.c
+++ b/x86/vmx.c
@@ -75,7 +75,7 @@  union vmx_ept_vpid  ept_vpid;
 
 extern struct descriptor_table_ptr gdt64_desc;
 extern struct descriptor_table_ptr idt_descr;
-extern struct descriptor_table_ptr tss_descr;
+extern struct descriptor_table_ptr *tss_descr;
 extern void *vmx_return;
 extern void *entry_sysenter;
 extern void *guest_entry;
@@ -1276,7 +1276,7 @@  static void init_vmcs_host(void)
 	vmcs_write(HOST_SEL_FS, KERNEL_DS);
 	vmcs_write(HOST_SEL_GS, KERNEL_DS);
 	vmcs_write(HOST_SEL_TR, TSS_MAIN);
-	vmcs_write(HOST_BASE_TR, tss_descr.base);
+	vmcs_write(HOST_BASE_TR, tss_descr->base);
 	vmcs_write(HOST_BASE_GDTR, gdt64_desc.base);
 	vmcs_write(HOST_BASE_IDTR, idt_descr.base);
 	vmcs_write(HOST_BASE_FS, 0);
@@ -1332,7 +1332,7 @@  static void init_vmcs_guest(void)
 	vmcs_write(GUEST_BASE_DS, 0);
 	vmcs_write(GUEST_BASE_FS, 0);
 	vmcs_write(GUEST_BASE_GS, 0);
-	vmcs_write(GUEST_BASE_TR, tss_descr.base);
+	vmcs_write(GUEST_BASE_TR, tss_descr->base);
 	vmcs_write(GUEST_BASE_LDTR, 0);
 
 	vmcs_write(GUEST_LIMIT_CS, 0xFFFFFFFF);
@@ -1342,7 +1342,7 @@  static void init_vmcs_guest(void)
 	vmcs_write(GUEST_LIMIT_FS, 0xFFFFFFFF);
 	vmcs_write(GUEST_LIMIT_GS, 0xFFFFFFFF);
 	vmcs_write(GUEST_LIMIT_LDTR, 0xffff);
-	vmcs_write(GUEST_LIMIT_TR, tss_descr.limit);
+	vmcs_write(GUEST_LIMIT_TR, tss_descr->limit);
 
 	vmcs_write(GUEST_AR_CS, 0xa09b);
 	vmcs_write(GUEST_AR_DS, 0xc093);