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@citrix.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
Andrew Cooper committed 2023-08-02 16:25:24 +01:00
1 parent 51588938e0
commit 26638cd9ef
1 file changed
+78 -79
+78 -79
View File
@@ -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)
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.