# HG changeset patch
# User kfraser@xxxxxxxxxxxxxxxxxxxxx
# Date 1172068837 0
# Node ID 43e9952b07ea6e92306a224ac259a440fe9d4891
# Parent bca284f67702cf46502809f29eb634e2ab6d294f
x86: Better BUG() and ASSERT() logging.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
---
xen/arch/x86/extable.c | 13 +----
xen/arch/x86/traps.c | 95 +++++++++++++++++++++++++++------------
xen/include/asm-x86/bug.h | 12 ++++
xen/include/asm-x86/x86_32/bug.h | 27 +++++++----
xen/include/asm-x86/x86_64/bug.h | 27 +++++++----
xen/include/xen/lib.h | 22 ++++-----
6 files changed, 128 insertions(+), 68 deletions(-)
diff -r bca284f67702 -r 43e9952b07ea xen/arch/x86/extable.c
--- a/xen/arch/x86/extable.c Wed Feb 21 10:13:40 2007 +0000
+++ b/xen/arch/x86/extable.c Wed Feb 21 14:40:37 2007 +0000
@@ -1,13 +1,8 @@
#include <xen/config.h>
+#include <xen/perfc.h>
#include <xen/spinlock.h>
#include <asm/uaccess.h>
-
-#ifdef PERF_COUNTERS
-#include <xen/sched.h>
-#include <xen/perfc.h>
-#include <asm/current.h>
-#endif
extern struct exception_table_entry __start___ex_table[];
extern struct exception_table_entry __stop___ex_table[];
@@ -74,10 +69,10 @@ search_pre_exception_table(struct cpu_us
unsigned long addr = (unsigned long)regs->eip;
unsigned long fixup = search_one_table(
__start___pre_ex_table, __stop___pre_ex_table-1, addr);
- dprintk(XENLOG_INFO, "Pre-exception: %p -> %p\n", _p(addr), _p(fixup));
-#ifdef PERF_COUNTERS
if ( fixup )
+ {
+ dprintk(XENLOG_INFO, "Pre-exception: %p -> %p\n", _p(addr), _p(fixup));
perfc_incrc(exception_fixed);
-#endif
+ }
return fixup;
}
diff -r bca284f67702 -r 43e9952b07ea xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c Wed Feb 21 10:13:40 2007 +0000
+++ b/xen/arch/x86/traps.c Wed Feb 21 14:40:37 2007 +0000
@@ -618,40 +618,77 @@ static int emulate_forced_invalid_op(str
asmlinkage int do_invalid_op(struct cpu_user_regs *regs)
{
- int rc;
+ struct bug_frame bug;
+ struct bug_frame_str bug_str;
+ char *filename, *predicate, *eip = (char *)regs->eip;
+ int rc, id, lineno;
DEBUGGER_trap_entry(TRAP_invalid_op, regs);
- if ( unlikely(!guest_mode(regs)) )
- {
- struct bug_frame bug;
- if ( is_kernel(regs->eip) &&
- (__copy_from_user(&bug, (char *)regs->eip, sizeof(bug)) == 0) &&
- (memcmp(bug.ud2, "\xf\xb", sizeof(bug.ud2)) == 0) &&
- (memcmp(bug.mov, BUG_MOV_STR, sizeof(bug.mov)) == 0) &&
- (bug.ret == 0xc2) )
- {
- char *filename = (char *)bug.filename;
- unsigned int line = bug.line & 0x7fff;
- int is_bug = !(bug.line & 0x8000);
- printk("Xen %s at %.50s:%d\n",
- is_bug ? "BUG" : "State Dump", filename, line);
- if ( !is_bug )
- {
- show_execution_state(regs);
- regs->eip += sizeof(bug);
- return EXCRET_fault_fixed;
- }
- }
+ if ( likely(guest_mode(regs)) )
+ {
+ if ( (rc = emulate_forced_invalid_op(regs)) != 0 )
+ return rc;
+ return do_guest_trap(TRAP_invalid_op, regs, 0);
+ }
+
+ if ( !is_kernel(eip) ||
+ __copy_from_user(&bug, eip, sizeof(bug)) ||
+ memcmp(bug.ud2, "\xf\xb", sizeof(bug.ud2)) ||
+ (bug.ret != 0xc2) )
+ goto die;
+
+ id = bug.id & 3;
+ if ( id == BUGFRAME_rsvd )
+ goto die;
+
+ if ( id == BUGFRAME_dump )
+ {
+ show_execution_state(regs);
+ regs->eip += sizeof(bug);
+ return EXCRET_fault_fixed;
+ }
+
+ /* BUG() or ASSERT(): decode the filename pointer and line number. */
+ ASSERT((id == BUGFRAME_bug) || (id == BUGFRAME_assert));
+ eip += sizeof(bug);
+ if ( !is_kernel(eip) ||
+ __copy_from_user(&bug_str, eip, sizeof(bug_str)) ||
+ memcmp(bug_str.mov, BUG_MOV_STR, sizeof(bug_str.mov)) )
+ goto die;
+
+ filename = is_kernel(bug_str.str) ? (char *)bug_str.str : "<unknown>";
+ lineno = bug.id >> 2;
+
+ if ( id == BUGFRAME_bug )
+ {
+ printk("Xen BUG at %.50s:%d\n", filename, lineno);
DEBUGGER_trap_fatal(TRAP_invalid_op, regs);
show_execution_state(regs);
- panic("FATAL TRAP: vector = %d (invalid opcode)\n", TRAP_invalid_op);
- }
-
- if ( (rc = emulate_forced_invalid_op(regs)) != 0 )
- return rc;
-
- return do_guest_trap(TRAP_invalid_op, regs, 0);
+ panic("Xen BUG at %.50s:%d\n", filename, lineno);
+ }
+
+ /* ASSERT(): decode the predicate string pointer. */
+ ASSERT(id == BUGFRAME_assert);
+ eip += sizeof(bug_str);
+ if ( !is_kernel(eip) ||
+ __copy_from_user(&bug_str, eip, sizeof(bug_str)) ||
+ memcmp(bug_str.mov, BUG_MOV_STR, sizeof(bug_str.mov)) )
+ goto die;
+
+ 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);
+ panic("Assertion '%s' failed at %.50s:%d\n",
+ predicate, filename, lineno);
+
+ die:
+ DEBUGGER_trap_fatal(TRAP_invalid_op, regs);
+ show_execution_state(regs);
+ panic("FATAL TRAP: vector = %d (invalid opcode)\n", TRAP_invalid_op);
+ return 0;
}
asmlinkage int do_int3(struct cpu_user_regs *regs)
diff -r bca284f67702 -r 43e9952b07ea xen/include/asm-x86/bug.h
--- a/xen/include/asm-x86/bug.h Wed Feb 21 10:13:40 2007 +0000
+++ b/xen/include/asm-x86/bug.h Wed Feb 21 14:40:37 2007 +0000
@@ -7,7 +7,15 @@
#include <asm/x86_32/bug.h>
#endif
-#define BUG() __BUG(__FILE__, __LINE__)
-#define dump_execution_state() __BUG(__FILE__, __LINE__ | 0x8000)
+struct bug_frame {
+ unsigned char ud2[2];
+ unsigned char ret;
+ unsigned short id; /* BUGFRAME_??? */
+} __attribute__((packed));
+
+#define BUGFRAME_dump 0
+#define BUGFRAME_bug 1
+#define BUGFRAME_assert 2
+#define BUGFRAME_rsvd 3
#endif /* __X86_BUG_H__ */
diff -r bca284f67702 -r 43e9952b07ea xen/include/asm-x86/x86_32/bug.h
--- a/xen/include/asm-x86/x86_32/bug.h Wed Feb 21 10:13:40 2007 +0000
+++ b/xen/include/asm-x86/x86_32/bug.h Wed Feb 21 14:40:37 2007 +0000
@@ -1,19 +1,28 @@
#ifndef __X86_32_BUG_H__
#define __X86_32_BUG_H__
-struct bug_frame {
- unsigned char ud2[2];
+struct bug_frame_str {
unsigned char mov[1];
- unsigned long filename;
- unsigned char ret;
- unsigned short line;
+ unsigned long str;
} __attribute__((packed));
-
#define BUG_MOV_STR "\xbc"
-#define __BUG(file, line) \
+#define dump_execution_state() \
asm volatile ( \
- "ud2 ; .byte 0xbc ; .long %c1 ; ret $%c0" \
- : : "i" (line), "i" (file) )
+ "ud2 ; ret $%c0" \
+ : : "i" (BUGFRAME_dump) )
+
+#define BUG() \
+ asm volatile ( \
+ "ud2 ; ret $%c0 ; .byte 0xbc ; .long %c1" \
+ : : "i" (BUGFRAME_bug | (__LINE__<<2)), \
+ "i" (__FILE__) )
+
+#define assert_failed(p) \
+ asm volatile ( \
+ "ud2 ; ret $%c0 ; .byte 0xbc ; .long %c1" \
+ " ; .byte 0xbc ; .long %c2" \
+ : : "i" (BUGFRAME_assert | (__LINE__<<2)), \
+ "i" (__FILE__), "i" (#p) )
#endif /* __X86_32_BUG_H__ */
diff -r bca284f67702 -r 43e9952b07ea xen/include/asm-x86/x86_64/bug.h
--- a/xen/include/asm-x86/x86_64/bug.h Wed Feb 21 10:13:40 2007 +0000
+++ b/xen/include/asm-x86/x86_64/bug.h Wed Feb 21 14:40:37 2007 +0000
@@ -1,19 +1,28 @@
#ifndef __X86_64_BUG_H__
#define __X86_64_BUG_H__
-struct bug_frame {
- unsigned char ud2[2];
+struct bug_frame_str {
unsigned char mov[2];
- unsigned long filename;
- unsigned char ret;
- unsigned short line;
+ unsigned long str;
} __attribute__((packed));
-
#define BUG_MOV_STR "\x48\xbc"
-#define __BUG(file, line) \
+#define dump_execution_state() \
asm volatile ( \
- "ud2 ; .byte 0x48,0xbc ; .quad %c1 ; ret $%c0" \
- : : "i" (line), "i" (file) )
+ "ud2 ; ret $%c0" \
+ : : "i" (BUGFRAME_dump) )
+
+#define BUG() \
+ asm volatile ( \
+ "ud2 ; ret $%c0 ; .byte 0x48,0xbc ; .quad %c1" \
+ : : "i" (BUGFRAME_bug | (__LINE__<<2)), \
+ "i" (__FILE__) )
+
+#define assert_failed(p) \
+ asm volatile ( \
+ "ud2 ; ret $%c0 ; .byte 0x48,0xbc ; .quad %c1" \
+ " ; .byte 0x48,0xbc ; .quad %c2" \
+ : : "i" (BUGFRAME_assert | (__LINE__<<2)), \
+ "i" (__FILE__), "i" (#p) )
#endif /* __X86_64_BUG_H__ */
diff -r bca284f67702 -r 43e9952b07ea xen/include/xen/lib.h
--- a/xen/include/xen/lib.h Wed Feb 21 10:13:40 2007 +0000
+++ b/xen/include/xen/lib.h Wed Feb 21 14:40:37 2007 +0000
@@ -16,18 +16,20 @@ void __bug(char *file, int line) __attri
/* Force a compilation error if condition is true */
#define BUILD_BUG_ON(condition) ((void)sizeof(char[1 - 2 * !!(condition)]))
+#ifndef assert_failed
+#define assert_failed(p) \
+do { \
+ printk("Assertion '%s' failed, line %d, file %s\n", #p , \
+ __LINE__, __FILE__); \
+ BUG(); \
+} while (0)
+#endif
+
#ifndef NDEBUG
-#define ASSERT(_p) \
- do { \
- if ( unlikely(!(_p)) ) \
- { \
- printk("Assertion '%s' failed, line %d, file %s\n", #_p , \
- __LINE__, __FILE__); \
- BUG(); \
- } \
- } while ( 0 )
+#define ASSERT(p) \
+ do { if ( unlikely(!(p)) ) assert_failed(p); } while (0)
#else
-#define ASSERT(_p) ((void)0)
+#define ASSERT(p) ((void)0)
#endif
#define SWAP(_a, _b) \
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|