debuggers.hg

changeset 21015:8cb6e7eff2ba

x86: Generalise BUGFRAME_dump mechanism to allow polled UART irq to
get proper regs argument.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Feb 24 10:44:30 2010 +0000 (2010-02-24)
parents 351a34c2fd48
children ec5c9373e821
files xen/arch/x86/traps.c xen/drivers/acpi/utilities/utglobal.c xen/drivers/char/ns16550.c xen/include/asm-x86/bug.h xen/include/asm-x86/processor.h
line diff
     1.1 --- a/xen/arch/x86/traps.c	Wed Feb 24 09:38:35 2010 +0000
     1.2 +++ b/xen/arch/x86/traps.c	Wed Feb 24 10:44:30 2010 +0000
     1.3 @@ -892,6 +892,7 @@ asmlinkage void do_invalid_op(struct cpu
     1.4  {
     1.5      struct bug_frame bug;
     1.6      struct bug_frame_str bug_str;
     1.7 +    const void *p;
     1.8      const char *filename, *predicate, *eip = (char *)regs->eip;
     1.9      unsigned long fixup;
    1.10      int id, lineno;
    1.11 @@ -913,26 +914,29 @@ asmlinkage void do_invalid_op(struct cpu
    1.12          goto die;
    1.13      eip += sizeof(bug);
    1.14  
    1.15 +    /* Decode first pointer argument. */
    1.16 +    if ( !is_kernel(eip) ||
    1.17 +         __copy_from_user(&bug_str, eip, sizeof(bug_str)) ||
    1.18 +         (bug_str.mov != 0xbc) )
    1.19 +        goto die;
    1.20 +    p = bug_str(bug_str, eip);
    1.21 +    if ( !is_kernel(p) )
    1.22 +        goto die;
    1.23 +    eip += sizeof(bug_str);
    1.24 +
    1.25      id = bug.id & 3;
    1.26  
    1.27 -    if ( id == BUGFRAME_dump )
    1.28 +    if ( id == BUGFRAME_run_fn )
    1.29      {
    1.30 -        show_execution_state(regs);
    1.31 +        const void (*fn)(struct cpu_user_regs *) = p;
    1.32 +        (*fn)(regs);
    1.33          regs->eip = (unsigned long)eip;
    1.34          return;
    1.35      }
    1.36  
    1.37      /* WARN, BUG or ASSERT: decode the filename pointer and line number. */
    1.38 -    if ( !is_kernel(eip) ||
    1.39 -         __copy_from_user(&bug_str, eip, sizeof(bug_str)) ||
    1.40 -         (bug_str.mov != 0xbc) )
    1.41 -        goto die;
    1.42 -    filename = bug_str(bug_str, eip);
    1.43 -    eip += sizeof(bug_str);
    1.44 -
    1.45 -    if ( !is_kernel(filename) )
    1.46 -        filename = "<unknown>";
    1.47 -    lineno   = bug.id >> 2;
    1.48 +    filename = p;
    1.49 +    lineno = bug.id >> 2;
    1.50  
    1.51      if ( id == BUGFRAME_warn )
    1.52      {
     2.1 --- a/xen/drivers/acpi/utilities/utglobal.c	Wed Feb 24 09:38:35 2010 +0000
     2.2 +++ b/xen/drivers/acpi/utilities/utglobal.c	Wed Feb 24 10:44:30 2010 +0000
     2.3 @@ -45,6 +45,7 @@
     2.4  
     2.5  #include <xen/config.h>
     2.6  #include <xen/lib.h>
     2.7 +#include <asm/processor.h>
     2.8  #include <acpi/acpi.h>
     2.9  #include <acpi/acnamesp.h>
    2.10  
     3.1 --- a/xen/drivers/char/ns16550.c	Wed Feb 24 09:38:35 2010 +0000
     3.2 +++ b/xen/drivers/char/ns16550.c	Wed Feb 24 10:44:30 2010 +0000
     3.3 @@ -145,11 +145,13 @@ static void ns16550_interrupt(
     3.4      }
     3.5  }
     3.6  
     3.7 -static void ns16550_poll(void *data)
     3.8 +/* Safe: ns16550_poll() runs in softirq context so not reentrant on a given CPU. */
     3.9 +static DEFINE_PER_CPU(struct serial_port *, poll_port);
    3.10 +
    3.11 +static void __ns16550_poll(struct cpu_user_regs *regs)
    3.12  {
    3.13 -    struct serial_port *port = data;
    3.14 +    struct serial_port *port = this_cpu(poll_port);
    3.15      struct ns16550 *uart = port->uart;
    3.16 -    struct cpu_user_regs *regs = guest_cpu_user_regs();
    3.17  
    3.18      if ( uart->intr_works )
    3.19          return;     /* Interrupts work - no more polling */
    3.20 @@ -169,6 +171,16 @@ static void ns16550_poll(void *data)
    3.21      set_timer(&uart->timer, NOW() + MILLISECS(uart->timeout_ms));
    3.22  }
    3.23  
    3.24 +static void ns16550_poll(void *data)
    3.25 +{
    3.26 +    this_cpu(poll_port) = data;
    3.27 +#ifdef run_in_exception_handler
    3.28 +    run_in_exception_handler(__ns16550_poll);
    3.29 +#else
    3.30 +    __ns16550_poll(guest_cpu_user_regs());
    3.31 +#endif
    3.32 +}
    3.33 +
    3.34  static int ns16550_tx_empty(struct serial_port *port)
    3.35  {
    3.36      struct ns16550 *uart = port->uart;
     4.1 --- a/xen/include/asm-x86/bug.h	Wed Feb 24 09:38:35 2010 +0000
     4.2 +++ b/xen/include/asm-x86/bug.h	Wed Feb 24 10:44:30 2010 +0000
     4.3 @@ -13,15 +13,16 @@ struct bug_frame {
     4.4      unsigned short id; /* BUGFRAME_??? */
     4.5  } __attribute__((packed));
     4.6  
     4.7 -#define BUGFRAME_dump   0
     4.8 +#define BUGFRAME_run_fn 0
     4.9  #define BUGFRAME_warn   1
    4.10  #define BUGFRAME_bug    2
    4.11  #define BUGFRAME_assert 3
    4.12  
    4.13 -#define dump_execution_state()                     \
    4.14 +#define run_in_exception_handler(fn)               \
    4.15      asm volatile (                                 \
    4.16 -        "ud2 ; ret $0"                             \
    4.17 -        : : "i" (BUGFRAME_dump) )
    4.18 +        "ud2 ; ret %0" BUG_STR(1)                  \
    4.19 +        : : "i" (BUGFRAME_run_fn),                 \
    4.20 +            "i" (fn) )
    4.21  
    4.22  #define WARN()                                     \
    4.23      asm volatile (                                 \
     5.1 --- a/xen/include/asm-x86/processor.h	Wed Feb 24 09:38:35 2010 +0000
     5.2 +++ b/xen/include/asm-x86/processor.h	Wed Feb 24 10:44:30 2010 +0000
     5.3 @@ -535,6 +535,7 @@ void show_stack(struct cpu_user_regs *re
     5.4  void show_stack_overflow(unsigned int cpu, unsigned long esp);
     5.5  void show_registers(struct cpu_user_regs *regs);
     5.6  void show_execution_state(struct cpu_user_regs *regs);
     5.7 +#define dump_execution_state() run_in_exception_handler(show_execution_state)
     5.8  void show_page_walk(unsigned long addr);
     5.9  asmlinkage void fatal_trap(int trapnr, struct cpu_user_regs *regs);
    5.10