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