[kvm-unit-tests RFC PATCH 04/17] x86 TDX: Add exception table support

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

 



Exception table is used to fixup from a faulty instruction
execution.

In TDX scenario, some instructions trigger #VE and simulated
through tdvmcall. If the simulation fail, the instruction is
treated as faulty and should be checked with the exception
table to fixup.

Move struct ex_record, exception_table_[start|end] in lib/x86/desc.h
as it's a general declaration and will be used in TDX.

Signed-off-by: Zhenzhong Duan <zhenzhong.duan@xxxxxxxxx>
Reviewed-by: Yu Zhang <yu.c.zhang@xxxxxxxxx>
---
 lib/x86/desc.c |  7 -------
 lib/x86/desc.h |  6 ++++++
 lib/x86/tdx.c  | 23 +++++++++++++++++++++++
 3 files changed, 29 insertions(+), 7 deletions(-)

diff --git a/lib/x86/desc.c b/lib/x86/desc.c
index b35274e44a8d..52eb4152385a 100644
--- a/lib/x86/desc.c
+++ b/lib/x86/desc.c
@@ -84,13 +84,6 @@ void set_idt_sel(int vec, u16 sel)
     e->selector = sel;
 }
 
-struct ex_record {
-    unsigned long rip;
-    unsigned long handler;
-};
-
-extern struct ex_record exception_table_start, exception_table_end;
-
 const char* exception_mnemonic(int vector)
 {
 	switch(vector) {
diff --git a/lib/x86/desc.h b/lib/x86/desc.h
index ad6277ba600a..068ec2394df9 100644
--- a/lib/x86/desc.h
+++ b/lib/x86/desc.h
@@ -212,6 +212,12 @@ extern tss64_t tss[];
 #endif
 extern gdt_entry_t gdt[];
 
+struct ex_record {
+	unsigned long rip;
+	unsigned long handler;
+};
+extern struct ex_record exception_table_start, exception_table_end;
+
 unsigned exception_vector(void);
 int write_cr4_checking(unsigned long val);
 unsigned exception_error_code(void);
diff --git a/lib/x86/tdx.c b/lib/x86/tdx.c
index 42ab25f47e57..62e0e2842822 100644
--- a/lib/x86/tdx.c
+++ b/lib/x86/tdx.c
@@ -267,6 +267,22 @@ static bool tdx_handle_io(struct ex_regs *regs, u32 exit_qual)
 	return ret ? false : true;
 }
 
+static bool tdx_check_exception_table(struct ex_regs *regs)
+{
+	struct ex_record *ex;
+
+	for (ex = &exception_table_start; ex != &exception_table_end; ++ex) {
+		if (ex->rip == regs->rip) {
+			regs->rip = ex->handler;
+			return true;
+		}
+	}
+	unhandled_exception(regs, false);
+
+	/* never reached */
+	return false;
+}
+
 static bool tdx_get_ve_info(struct ve_info *ve)
 {
 	struct tdx_module_output out;
@@ -298,10 +314,15 @@ static bool tdx_get_ve_info(struct ve_info *ve)
 static bool tdx_handle_virtualization_exception(struct ex_regs *regs,
 		struct ve_info *ve)
 {
+	unsigned int ex_val;
 	bool ret = true;
 	u64 val = ~0ULL;
 	bool do_sti;
 
+	/* #VE exit_reason in bit16-32 */
+	ex_val = regs->vector | (ve->exit_reason << 16);
+	asm("mov %0, %%gs:4" : : "r"(ex_val));
+
 	switch (ve->exit_reason) {
 	case EXIT_REASON_HLT:
 		do_sti = !!(regs->rflags & X86_EFLAGS_IF);
@@ -333,6 +354,8 @@ static bool tdx_handle_virtualization_exception(struct ex_regs *regs,
 	/* After successful #VE handling, move the IP */
 	if (ret)
 		regs->rip += ve->instr_len;
+	else
+		ret = tdx_check_exception_table(regs);
 
 	return ret;
 }
-- 
2.25.1




[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