1 /******************************************************************************
2  * asm/debugger.h
3  *
4  * Generic hooks into arch-dependent Xen.
5  *
6  * Each debugger should define two functions here:
7  *
8  * 1. debugger_trap_entry():
9  *  Called at start of any synchronous fault or trap, before any other work
10  *  is done. The idea is that if your debugger deliberately caused the trap
11  *  (e.g. to implement breakpoints or data watchpoints) then you can take
12  *  appropriate action and return a non-zero value to cause early exit from
13  *  the trap function.
14  *
15  * 2. debugger_trap_fatal():
16  *  Called when Xen is about to give up and crash. Typically you will use this
17  *  hook to drop into a debug session. It can also be used to hook off
18  *  deliberately caused traps (which you then handle and return non-zero).
19  *
20  * 3. debugger_trap_immediate():
21  *  Called if we want to drop into a debugger now.  This is essentially the
22  *  same as debugger_trap_fatal, except that we use the current register state
23  *  rather than the state which was in effect when we took the trap.
24  *  For example: if we're dying because of an unhandled exception, we call
25  *  debugger_trap_fatal; if we're dying because of a panic() we call
26  *  debugger_trap_immediate().
27  */
28 
29 #ifndef __X86_DEBUGGER_H__
30 #define __X86_DEBUGGER_H__
31 
32 #include <xen/sched.h>
33 #include <asm/regs.h>
34 #include <asm/processor.h>
35 
36 #ifdef CONFIG_CRASH_DEBUG
37 
38 #include <xen/gdbstub.h>
39 
debugger_trap_fatal(unsigned int vector,struct cpu_user_regs * regs)40 static inline bool debugger_trap_fatal(
41     unsigned int vector, struct cpu_user_regs *regs)
42 {
43     int rc = __trap_to_gdb(regs, vector);
44     return ((rc == 0) || (vector == TRAP_int3));
45 }
46 
47 /* Int3 is a trivial way to gather cpu_user_regs context. */
48 #define debugger_trap_immediate() __asm__ __volatile__ ( "int3" );
49 
50 #else
51 
debugger_trap_fatal(unsigned int vector,struct cpu_user_regs * regs)52 static inline bool debugger_trap_fatal(
53     unsigned int vector, struct cpu_user_regs *regs)
54 {
55     return false;
56 }
57 
58 #define debugger_trap_immediate() ((void)0)
59 
60 #endif
61 
debugger_trap_entry(unsigned int vector,struct cpu_user_regs * regs)62 static inline bool debugger_trap_entry(
63     unsigned int vector, struct cpu_user_regs *regs)
64 {
65     /*
66      * This function is called before any checks are made.  Amongst other
67      * things, be aware that during early boot, current is not a safe pointer
68      * to follow.
69      */
70     struct vcpu *v = current;
71 
72     if ( vector != TRAP_int3 && vector != TRAP_debug )
73         return false;
74 
75     if ( guest_mode(regs) && guest_kernel_mode(v, regs) &&
76          v->domain->debugger_attached  )
77     {
78         if ( vector != TRAP_debug ) /* domain pause is good enough */
79             current->arch.gdbsx_vcpu_event = vector;
80         domain_pause_for_debugger();
81         return true;
82     }
83 
84     return false;
85 }
86 
87 unsigned int dbg_rw_mem(void * __user addr, void * __user buf,
88                         unsigned int len, domid_t domid, bool toaddr,
89                         uint64_t pgd3);
90 
91 #endif /* __X86_DEBUGGER_H__ */
92