[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen master] x86/traps: Move do_general_protection() earlier
commit 26638cd9efaea4fea3322914efc2611981e001fe Author: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> AuthorDate: Fri Feb 17 23:06:37 2023 +0000 Commit: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> CommitDate: Wed Aug 2 16:25:24 2023 +0100 x86/traps: Move do_general_protection() earlier ... in order to clean up the declarations without needing to forward declare it for handle_gdt_ldt_mapping_fault() No functional change. Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> Acked-by: Jan Beulich <jbeulich@xxxxxxxx> --- xen/arch/x86/traps.c | 157 +++++++++++++++++++++++++-------------------------- 1 file changed, 78 insertions(+), 79 deletions(-) diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index f11239fd0f..80e8c2fb1f 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -1223,6 +1223,84 @@ void do_int3(struct cpu_user_regs *regs) pv_inject_hw_exception(X86_EXC_BP, X86_EVENT_NO_EC); } +void do_general_protection(struct cpu_user_regs *regs) +{ +#ifdef CONFIG_PV + struct vcpu *v = current; +#endif + + if ( regs->error_code & X86_XEC_EXT ) + goto hardware_gp; + + if ( !guest_mode(regs) ) + goto gp_in_kernel; + +#ifdef CONFIG_PV + /* + * Cunning trick to allow arbitrary "INT n" handling. + * + * We set DPL == 0 on all vectors in the IDT. This prevents any INT <n> + * instruction from trapping to the appropriate vector, when that might not + * be expected by Xen or the guest OS. For example, that entry might be for + * a fault handler (unlike traps, faults don't increment EIP), or might + * expect an error code on the stack (which a software trap never + * provides), or might be a hardware interrupt handler that doesn't like + * being called spuriously. + * + * Instead, a GPF occurs with the faulting IDT vector in the error code. + * Bit 1 is set to indicate that an IDT entry caused the fault. Bit 0 is + * clear (which got already checked above) to indicate that it's a software + * fault, not a hardware one. + * + * NOTE: Vectors 3 and 4 are dealt with from their own handler. This is + * okay because they can only be triggered by an explicit DPL-checked + * instruction. The DPL specified by the guest OS for these vectors is NOT + * CHECKED!! + */ + if ( regs->error_code & X86_XEC_IDT ) + { + /* This fault must be due to <INT n> instruction. */ + uint8_t vector = regs->error_code >> 3; + const struct trap_info *ti = &v->arch.pv.trap_ctxt[vector]; + + if ( permit_softint(TI_GET_DPL(ti), v, regs) ) + { + regs->rip += 2; + pv_inject_sw_interrupt(vector); + return; + } + } + else if ( is_pv_32bit_vcpu(v) && regs->error_code ) + { + pv_emulate_gate_op(regs); + return; + } + + /* Emulate some simple privileged and I/O instructions. */ + if ( (regs->error_code == 0) && + pv_emulate_privileged_op(regs) ) + { + trace_trap_one_addr(TRC_PV_EMULATE_PRIVOP, regs->rip); + return; + } + + /* Pass on GPF as is. */ + pv_inject_hw_exception(X86_EXC_GP, regs->error_code); + return; +#endif + + gp_in_kernel: + if ( likely(extable_fixup(regs, true)) ) + return; + + hardware_gp: + if ( debugger_trap_fatal(X86_EXC_GP, regs) ) + return; + + show_execution_state(regs); + panic("GENERAL PROTECTION FAULT\n[error_code=%04x]\n", regs->error_code); +} + #ifdef CONFIG_PV static int handle_ldt_mapping_fault(unsigned int offset, struct cpu_user_regs *regs) @@ -1588,85 +1666,6 @@ void __init do_early_page_fault(struct cpu_user_regs *regs) } } -void do_general_protection(struct cpu_user_regs *regs) -{ -#ifdef CONFIG_PV - struct vcpu *v = current; -#endif - - if ( regs->error_code & X86_XEC_EXT ) - goto hardware_gp; - - if ( !guest_mode(regs) ) - goto gp_in_kernel; - -#ifdef CONFIG_PV - /* - * Cunning trick to allow arbitrary "INT n" handling. - * - * We set DPL == 0 on all vectors in the IDT. This prevents any INT <n> - * instruction from trapping to the appropriate vector, when that might not - * be expected by Xen or the guest OS. For example, that entry might be for - * a fault handler (unlike traps, faults don't increment EIP), or might - * expect an error code on the stack (which a software trap never - * provides), or might be a hardware interrupt handler that doesn't like - * being called spuriously. - * - * Instead, a GPF occurs with the faulting IDT vector in the error code. - * Bit 1 is set to indicate that an IDT entry caused the fault. Bit 0 is - * clear (which got already checked above) to indicate that it's a software - * fault, not a hardware one. - * - * NOTE: Vectors 3 and 4 are dealt with from their own handler. This is - * okay because they can only be triggered by an explicit DPL-checked - * instruction. The DPL specified by the guest OS for these vectors is NOT - * CHECKED!! - */ - if ( regs->error_code & X86_XEC_IDT ) - { - /* This fault must be due to <INT n> instruction. */ - uint8_t vector = regs->error_code >> 3; - const struct trap_info *ti = &v->arch.pv.trap_ctxt[vector]; - - if ( permit_softint(TI_GET_DPL(ti), v, regs) ) - { - regs->rip += 2; - pv_inject_sw_interrupt(vector); - return; - } - } - else if ( is_pv_32bit_vcpu(v) && regs->error_code ) - { - pv_emulate_gate_op(regs); - return; - } - - /* Emulate some simple privileged and I/O instructions. */ - if ( (regs->error_code == 0) && - pv_emulate_privileged_op(regs) ) - { - trace_trap_one_addr(TRC_PV_EMULATE_PRIVOP, regs->rip); - return; - } - - /* Pass on GPF as is. */ - pv_inject_hw_exception(X86_EXC_GP, regs->error_code); - return; -#endif - - gp_in_kernel: - - if ( likely(extable_fixup(regs, true)) ) - return; - - hardware_gp: - if ( debugger_trap_fatal(X86_EXC_GP, regs) ) - return; - - show_execution_state(regs); - panic("GENERAL PROTECTION FAULT\n[error_code=%04x]\n", regs->error_code); -} - static bool pci_serr_cont; static bool pci_serr_nmicont(void) -- generated by git-patchbot for /home/xen/git/xen.git#master
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |