@@ -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) {
@@ -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);
@@ -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;
}