aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2007-12-12 11:27:15 +0000
committerKeir Fraser <keir.fraser@citrix.com>2007-12-12 11:27:15 +0000
commitbfeddb6751d4cdb7337170176c1cb55230a95b18 (patch)
tree548a80cacfb6f1c9fe64fbc3a42c9d3dcff7bca3
parent73f67c0d9a0a3dff0fe27e977706492316126a1e (diff)
downloadxen-bfeddb6751d4cdb7337170176c1cb55230a95b18.tar.gz
xen-bfeddb6751d4cdb7337170176c1cb55230a95b18.tar.bz2
xen-bfeddb6751d4cdb7337170176c1cb55230a95b18.zip
Fix gdb debugging of hypervisor.
This patch: * enables the gdbstubs to properly access hypervisor memory; * prevents an assertion failure in __spurious_page_fault's call to map_domain_page if such accesses fail, by testing in_irq(); * prints some additional helpful messages; * fixes the endianness of register transfers from the gdbstubs so that gdb is much less confused. * fixes the documentation in docs/misc/crashdb.txt Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
-rw-r--r--docs/misc/crashdb.txt67
-rw-r--r--xen/arch/x86/gdbstub.c10
-rw-r--r--xen/arch/x86/traps.c10
-rw-r--r--xen/common/gdbstub.c19
-rw-r--r--xen/common/keyhandler.c1
-rw-r--r--xen/include/xen/gdbstub.h1
6 files changed, 73 insertions, 35 deletions
diff --git a/docs/misc/crashdb.txt b/docs/misc/crashdb.txt
index a366f72f5d..b41a538adb 100644
--- a/docs/misc/crashdb.txt
+++ b/docs/misc/crashdb.txt
@@ -5,31 +5,46 @@ Xen has a simple gdb stub for doing post-mortem debugging i.e. once
you've crashed it, you get to poke around and find out why. There's
also a special key handler for making it crash, which is handy.
-You need to have crash_debug=y set when compiling to enable the crash
-debugger (so go ``export crash_debug=y; make'', or ``crash_debug=y
-make'' or ``make crash_debug=y''), and you also need to enable it on
-the Xen command line, by going e.g. cdb=com1. If you need to have a
-serial port shared between cdb and the console, try cdb=com1H. CDB
-will then set the high bit on every byte it sends, and only respond to
-bytes with the high bit set. Similarly for com2.
-
-The next step depends on your individual setup. This is how to do
-it for a normal test box in the SRG:
-
--- Make your test machine crash. Either a normal panic or hitting
- 'C-A C-A C-A %' on the serial console will do.
--- Start gdb as ``gdb ./xen-syms''
--- Go ``target remote serial.srg:12331'', where 12331 is the second port
- reported for that machine by xenuse. (In this case, the machine is
- bombjack)
--- Go ``add-symbol-file vmlinux''
--- Debug as if you had a core file
--- When you're finished, go and reboot your test box. Hitting 'R' on the
- serial console won't work.
-
-At one stage, it was sometimes possible to resume after entering the
-debugger from the serial console. This seems to have rotted, however,
-and I'm not terribly interested in putting it back.
+You need to have crash_debug=y set when compiling , and you also need
+to enable it on the Xen command line, eg by gdb=com1.
+
+If you need to have a serial port shared between gdb and the console,
+you can use gdb=com1H. CDB will then set the high bit on every byte
+it sends, and only respond to bytes with the high bit set. Similarly
+for com2. If you do this you will need a demultiplexing program on
+the debugging workstation, such as perhaps tools/misc/nsplitd.
+
+The next step depends on your individual setup. This is how to do it
+if you have a simple null modem connection between the test box and
+the workstation, and aren't using a H/L split console:
+
+ * Set debug=y in Config.mk
+ * Set crash_debug=y in xen/Rules.mk
+ * Make the changes in the attached patch, and build.
+ * Arrange to pass gdb=com1 as a hypervisor command line argument
+ (I already have com1=38400,8n1 console=com1,vga sync_console)
+
+ * Boot the system with minicom (or your favourite terminal program)
+ connected from your workstation via a null modem cable in the
+ usual way.
+ * In minicom, give the escape character (^A by default) three times
+ to talk to Xen (Xen prints `(XEN) *** Serial input -> Xen...').
+ * Press % and observe the messages
+ (XEN) '%' pressed -> trapping into debugger
+ (XEN) GDB connection activated.
+ (XEN) Waiting for GDB to attach...
+ * Disconnect from minicom without allowing minicom to send any
+ modem control sequences.
+ * Start gdb with gdb /path/to/build/tree/xen/xen-syms and then
+ (gdb) set remotebaud 38400
+ Remote debugging using /dev/ttyS0
+ 0xff124d61 in idle_loop () at domain.c:78
+ 78 safe_halt();
+ (gdb)
+
+There is code which was once intended to make it possible to resume
+after entering the debugger. However this does not presently work; it
+has been nonfunctional for quite some time.
As soon as you reach the debugger, we disable interrupts, the
watchdog, and every other CPU, so the state of the world shouldn't
@@ -44,7 +59,5 @@ Reasons why we might fail to reach the debugger:
you're screwed.
-- If the page tables are wrong, you're screwed
-- If the serial port setup is wrong, badness happens
--- We acquire the console lock at one stage XXX this is unnecessary and
- stupid
-- Obviously, the low level processor state can be screwed in any
number of wonderful ways
diff --git a/xen/arch/x86/gdbstub.c b/xen/arch/x86/gdbstub.c
index a3af473ee2..3d0d0d0429 100644
--- a/xen/arch/x86/gdbstub.c
+++ b/xen/arch/x86/gdbstub.c
@@ -71,18 +71,20 @@ gdb_arch_read_reg(unsigned long regnum, struct cpu_user_regs *regs,
gdb_send_reply("", ctx);
}
-/* Like copy_from_user, but safe to call with interrupts disabled.
- Trust me, and don't look behind the curtain. */
+/*
+ * Use __copy_*_user to make us page-fault safe, but not otherwise restrict
+ * our access to the full virtual address space.
+ */
unsigned int
gdb_arch_copy_from_user(void *dest, const void *src, unsigned len)
{
- return copy_from_user(dest, src, len);
+ return __copy_from_user(dest, src, len);
}
unsigned int
gdb_arch_copy_to_user(void *dest, const void *src, unsigned len)
{
- return copy_to_user(dest, src, len);
+ return __copy_to_user(dest, src, len);
}
void
diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c
index 9cc1669116..73a146eb73 100644
--- a/xen/arch/x86/traps.c
+++ b/xen/arch/x86/traps.c
@@ -783,8 +783,8 @@ asmlinkage void do_invalid_op(struct cpu_user_regs *regs)
predicate = is_kernel(bug_str.str) ? (char *)bug_str.str : "<unknown>";
printk("Assertion '%s' failed at %.50s:%d\n",
predicate, filename, lineno);
- DEBUGGER_trap_fatal(TRAP_invalid_op, regs);
show_execution_state(regs);
+ DEBUGGER_trap_fatal(TRAP_invalid_op, regs);
panic("Assertion '%s' failed at %.50s:%d\n",
predicate, filename, lineno);
@@ -912,6 +912,14 @@ static int __spurious_page_fault(
l1_pgentry_t l1e, *l1t;
unsigned int required_flags, disallowed_flags;
+ /*
+ * We do not take spurious page faults in IRQ handlers as we do not
+ * modify page tables in IRQ context. We therefore bail here because
+ * map_domain_page() is not IRQ-safe.
+ */
+ if ( in_irq() )
+ return 0;
+
/* Reserved bit violations are never spurious faults. */
if ( regs->error_code & PFEC_reserved_bit )
return 0;
diff --git a/xen/common/gdbstub.c b/xen/common/gdbstub.c
index 51a2d6cb7d..c0b2f4c474 100644
--- a/xen/common/gdbstub.c
+++ b/xen/common/gdbstub.c
@@ -43,6 +43,7 @@
#include <xen/smp.h>
#include <xen/console.h>
#include <xen/errno.h>
+#include <asm/byteorder.h>
/* Printk isn't particularly safe just after we've trapped to the
debugger. so avoid it. */
@@ -215,8 +216,7 @@ void
gdb_write_to_packet_hex(unsigned long x, int int_size, struct gdb_context *ctx)
{
char buf[sizeof(unsigned long) * 2 + 1];
- int i = sizeof(unsigned long) * 2;
- int width = int_size * 2;
+ int i, width = int_size * 2;
buf[sizeof(unsigned long) * 2] = 0;
@@ -233,6 +233,8 @@ gdb_write_to_packet_hex(unsigned long x, int int_size, struct gdb_context *ctx)
break;
}
+#ifdef __BIG_ENDIAN
+ i = sizeof(unsigned long) * 2
do {
buf[--i] = hex2char(x & 15);
x >>= 4;
@@ -242,6 +244,17 @@ gdb_write_to_packet_hex(unsigned long x, int int_size, struct gdb_context *ctx)
buf[--i] = '0';
gdb_write_to_packet(&buf[i], width, ctx);
+#elif defined(__LITTLE_ENDIAN)
+ i = 0;
+ while (i < width) {
+ buf[i++] = hex2char(x>>4);
+ buf[i++] = hex2char(x);
+ x >>= 8;
+ }
+ gdb_write_to_packet(buf, width, ctx);
+#else
+# error unknown endian
+#endif
}
static int
@@ -512,7 +525,7 @@ __trap_to_gdb(struct cpu_user_regs *regs, unsigned long cookie)
if ( gdb_ctx->serhnd < 0 )
{
- dbg_printk("Debugger not ready yet.\n");
+ printk("Debugging connection not set up.\n");
return -EBUSY;
}
diff --git a/xen/common/keyhandler.c b/xen/common/keyhandler.c
index f7756cd324..14ed246703 100644
--- a/xen/common/keyhandler.c
+++ b/xen/common/keyhandler.c
@@ -275,6 +275,7 @@ extern void perfc_reset(unsigned char key);
static void do_debug_key(unsigned char key, struct cpu_user_regs *regs)
{
+ printk("'%c' pressed -> trapping into debugger\n", key);
(void)debugger_trap_fatal(0xf001, regs);
nop(); /* Prevent the compiler doing tail call
optimisation, as that confuses xendbg a
diff --git a/xen/include/xen/gdbstub.h b/xen/include/xen/gdbstub.h
index 46e4815e44..09af6f3642 100644
--- a/xen/include/xen/gdbstub.h
+++ b/xen/include/xen/gdbstub.h
@@ -53,6 +53,7 @@ void gdb_write_to_packet(
const char *buf, int count, struct gdb_context *ctx);
void gdb_write_to_packet_hex(
unsigned long x, int int_size, struct gdb_context *ctx);
+ /* ... writes in target native byte order as required by gdb spec. */
void gdb_send_packet(struct gdb_context *ctx);
void gdb_send_reply(const char *buf, struct gdb_context *ctx);