[kvm-unit-tests RFC v2 05/18] x86 TDX: Add exception table support

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

 



From: Zhenzhong Duan <zhenzhong.duan@xxxxxxxxx>

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

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

Move struct ex_record, exception_table_[start|end] to 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>
Link: https://lore.kernel.org/r/20220303071907.650203-5-zhenzhong.duan@xxxxxxxxx
Signed-off-by: Qian Wen <qian.wen@xxxxxxxxx>
---
 lib/x86/desc.c |  7 -------
 lib/x86/desc.h |  6 ++++++
 lib/x86/tdx.c  | 23 ++++++++++++++++++++++-
 3 files changed, 28 insertions(+), 8 deletions(-)

diff --git a/lib/x86/desc.c b/lib/x86/desc.c
index 5b41549e..14edac0c 100644
--- a/lib/x86/desc.c
+++ b/lib/x86/desc.c
@@ -100,13 +100,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 7778a0f8..54b3166f 100644
--- a/lib/x86/desc.h
+++ b/lib/x86/desc.h
@@ -237,6 +237,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);
 unsigned exception_error_code(void);
 bool exception_rflags_rf(void);
diff --git a/lib/x86/tdx.c b/lib/x86/tdx.c
index d10e02b9..4f8bbad7 100644
--- a/lib/x86/tdx.c
+++ b/lib/x86/tdx.c
@@ -303,6 +303,22 @@ done:
 	return !!tdx_guest;
 }
 
+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_args args = {};
@@ -334,8 +350,13 @@ static bool tdx_get_ve_info(struct ve_info *ve)
 static bool tdx_handle_virt_exception(struct ex_regs *regs,
 		struct ve_info *ve)
 {
+	unsigned int ex_val;
 	int insn_len = -EIO;
 
+	/* #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:
 		insn_len = handle_halt(regs, ve);
@@ -357,7 +378,7 @@ static bool tdx_handle_virt_exception(struct ex_regs *regs,
 		return false;
 	}
 	if (insn_len < 0)
-		return false;
+		return tdx_check_exception_table(regs);
 
 	/* After successful #VE handling, move the IP */
 	regs->rip += insn_len;
-- 
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