[PATCH kvm-unit-tests 09/18] x86: desc: support ISTs for alternate stacks in 64-bit mode

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

 



Introduce a new API that replaces setup_tss32 and set_intr_task_gate
in tests that run in both modes.  This will enable three more tests in
eventinj to run in 64-bit mode.

Signed-off-by: Paolo Bonzini <pbonzini@xxxxxxxxxx>
---
 lib/x86/desc.c | 26 ++++++++++++++++++++++++--
 lib/x86/desc.h | 34 ++++++++++++++++++++++++++--------
 x86/cstart64.S |  1 +
 x86/eventinj.c |  6 +++---
 4 files changed, 54 insertions(+), 13 deletions(-)

diff --git a/lib/x86/desc.c b/lib/x86/desc.c
index ec1fda3..9a80f48 100644
--- a/lib/x86/desc.c
+++ b/lib/x86/desc.c
@@ -187,6 +187,8 @@ unsigned exception_error_code(void)
     return error_code;
 }
 
+static char intr_alt_stack[4096];
+
 #ifndef __x86_64__
 /*
  * GDT, with 6 entries:
@@ -243,7 +245,6 @@ void set_idt_task_gate(int vec, u16 sel)
  */
 
 tss32_t tss_intr;
-static char tss_stack[4096];
 
 void setup_tss32(void)
 {
@@ -253,7 +254,7 @@ void setup_tss32(void)
 	tss_intr.cr3 = read_cr3();
 	tss_intr.ss0 = tss_intr.ss1 = tss_intr.ss2 = 0x10;
 	tss_intr.esp = tss_intr.esp0 = tss_intr.esp1 = tss_intr.esp2 =
-		(u32)tss_stack + 4096;
+		(u32)intr_alt_stack + 4096;
 	tss_intr.cs = 0x08;
 	tss_intr.ds = tss_intr.es = tss_intr.fs = tss_intr.gs = tss_intr.ss = 0x10;
 	tss_intr.iomap_base = (u16)desc_size;
@@ -266,6 +267,16 @@ void set_intr_task_gate(int e, void *fn)
 	set_idt_task_gate(e, TSS_INTR);
 }
 
+void setup_alt_stack(void)
+{
+	setup_tss32();
+}
+
+void set_intr_alt_stack(int e, void *fn)
+{
+	set_intr_task_gate(e, fn);
+}
+
 void print_current_tss_info(void)
 {
 	u16 tr = str();
@@ -276,6 +287,17 @@ void print_current_tss_info(void)
 		printf("TR=%x (%s) Main TSS back link %x. Intr TSS back link %x\n",
 		       tr, tr ? "interrupt" : "main", tss.prev, tss_intr.prev);
 }
+#else
+void set_intr_alt_stack(int e, void *addr)
+{
+	set_idt_entry(e, addr, 0);
+	boot_idt[e].ist = 1;
+}
+
+void setup_alt_stack(void)
+{
+	tss.ist1 = (u64)intr_alt_stack + 4096;
+}
 #endif
 
 static bool exception;
diff --git a/lib/x86/desc.h b/lib/x86/desc.h
index cd41a74..33e721c 100644
--- a/lib/x86/desc.h
+++ b/lib/x86/desc.h
@@ -2,11 +2,7 @@
 #define __IDT_TEST__
 
 void setup_idt(void);
-#ifndef __x86_64__
-void setup_tss32(void);
-#else
-static inline void setup_tss32(void){}
-#endif
+void setup_alt_stack(void);
 
 struct ex_regs {
     unsigned long rax, rcx, rdx, rbx;
@@ -57,6 +53,24 @@ typedef struct {
 	u16 iomap_base;
 } tss32_t;
 
+typedef struct  __attribute__((packed)) {
+	u32 res1;
+	u64 rsp0;
+	u64 rsp1;
+	u64 rsp2;
+	u64 res2;
+	u64 ist1;
+	u64 ist2;
+	u64 ist3;
+	u64 ist4;
+	u64 ist5;
+	u64 ist6;
+	u64 ist7;
+	u64 res3;
+	u16 res4;
+	u16 iomap_base;
+} tss64_t;
+
 #define ASM_TRY(catch)                                  \
     "movl $0, %%gs:4 \n\t"                              \
     ".pushsection .data.ex \n\t"                        \
@@ -109,6 +123,12 @@ extern idt_entry_t boot_idt[256];
 extern gdt_entry_t gdt32[];
 extern tss32_t tss;
 extern tss32_t tss_intr;
+void set_gdt_task_gate(u16 tss_sel, u16 sel);
+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;
 #endif
 
 unsigned exception_vector(void);
@@ -116,9 +136,7 @@ unsigned exception_error_code(void);
 void set_idt_entry(int vec, void *addr, int dpl);
 void set_idt_sel(int vec, u16 sel);
 void set_gdt_entry(int sel, u32 base,  u32 limit, u8 access, u8 gran);
-void set_gdt_task_gate(u16 tss_sel, u16 sel);
-void set_idt_task_gate(int vec, u16 sel);
-void set_intr_task_gate(int e, void *fn);
+void set_intr_alt_stack(int e, void *fn);
 void print_current_tss_info(void);
 void handle_exception(u8 v, void (*func)(struct ex_regs *regs));
 
diff --git a/x86/cstart64.S b/x86/cstart64.S
index 1a0c85e..7a1d79d 100644
--- a/x86/cstart64.S
+++ b/x86/cstart64.S
@@ -77,6 +77,7 @@ tss_descr:
 gdt64_end:
 
 i = 0
+.globl tss
 tss:
 	.rept max_cpus
 	.long 0
diff --git a/x86/eventinj.c b/x86/eventinj.c
index 900cfda..2124bdf 100644
--- a/x86/eventinj.c
+++ b/x86/eventinj.c
@@ -183,7 +183,7 @@ int main()
 
 	setup_vm();
 	setup_idt();
-	setup_tss32();
+	setup_alt_stack();
 
 	handle_irq(32, tirq0);
 	handle_irq(33, tirq1);
@@ -344,7 +344,7 @@ int main()
 
 	/* Generate DE and PF exceptions serially */
 	test_divider = 0;
-	set_intr_task_gate(14, pf_tss);
+	set_intr_alt_stack(14, pf_tss);
 	handle_exception(0, de_isr);
 	printf("Try to divide by 0\n");
 	/* install read only pte */
@@ -363,7 +363,7 @@ int main()
 	/* Generate NP and PF exceptions serially */
 	printf("Before NP test\n");
 	test_count = 0;
-	set_intr_task_gate(14, pf_tss);
+	set_intr_alt_stack(14, pf_tss);
 	handle_exception(11, np_isr);
 	set_idt_sel(33, NP_SEL);
 	/* install read only pte */
-- 
1.8.3.1


--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[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