I think this patch fixes the interrupt path with the new out-of-line
save_args function.  I didn't find any way to deal with a function that
modifies the stack and where the caller needs to know the new stack
state.

If someone knows a better way to handle this then I'd be interested.

I still haven't worked my way through the changes to the exception path.

mh


From: Martin Hicks <[email protected]>
Date: Wed, 4 Feb 2009 14:38:55 -0600
Subject: [PATCH] fix bb analysis for save_args and common_interrupt

save_args became a function which is called by the interrupt stubs.
This complicates life quite a bit because save_args backs up the
registers but also switches to the interrupt stack before returning
to call do_IRQ.

Signed-off-by: Martin Hicks <[email protected]>
---
 arch/x86/kdb/kdba_bt.c |   46 ++++++++++++++++++++++++++++++++++++----------
 1 files changed, 36 insertions(+), 10 deletions(-)

diff --git a/arch/x86/kdb/kdba_bt.c b/arch/x86/kdb/kdba_bt.c
index 62a8444..631357a 100644
--- a/arch/x86/kdb/kdba_bt.c
+++ b/arch/x86/kdb/kdba_bt.c
@@ -253,7 +253,7 @@ struct bb_name_state {
                .skip_mem.bits[0] = iskip_mem, \
                .skip_regs.bits[0] = iskip_regs, \
                .osp_offset = iosp_offset, \
-                       .address = 0 \
+               .address = 0 \
        }
 
 /* Shorter forms for the common cases */
@@ -576,6 +576,7 @@ static struct bb_name_state bb_special_cases[] = {
        NS("general_protection", error_code, all_regs, 0, 0, 0),
        NS("error_entry", error_code_rax, all_regs, 0, BB_SKIP(RAX), -0x10),
        NS("common_interrupt", error_code, all_regs, 0, 0, -0x8),
+       NS("save_args", error_code, all_regs, 0, 0, -0x50),
 };
 
 static const char *bb_spurious[] = {
@@ -1352,7 +1353,8 @@ static struct bb_actual bb_actual[KDB_INT_REGISTERS];
 static bfd_vma bb_func_start, bb_func_end;
 static bfd_vma bb_common_interrupt, bb_error_entry, bb_ret_from_intr,
               bb_thread_return, bb_sync_regs, bb_save_v86_state,
-              bb__sched_text_start, bb__sched_text_end;
+              bb__sched_text_start, bb__sched_text_end,
+              bb_save_args;
 
 /* Record jmp instructions, both conditional and unconditional.  These form the
  * arcs between the basic blocks.  This is also used to record the state when
@@ -3447,20 +3449,42 @@ bb_usage(void)
                }
                break;
        case BBOU_CALL:
-               /* Invalidate the scratch registers.  Functions sync_regs and
-                * save_v86_state are special, their return value is the new
-                * stack pointer.
-                */
                bb_reg_state_print(bb_reg_state);
-               bb_invalidate_scratch_reg();
                if (bb_is_static_disp(src)) {
+                       /* Function sync_regs and save_v86_state are special.
+                        * Their return value is the new stack pointer
+                        */
                        if (src->disp == bb_sync_regs) {
                                bb_reg_set_reg(BBRG_RAX, BBRG_RSP);
                        } else if (src->disp == bb_save_v86_state) {
                                bb_reg_set_reg(BBRG_RAX, BBRG_RSP);
                                bb_adjust_osp(BBRG_RAX, +KDB_WORD_SIZE);
                        }
+                       /* Function save_args is special also.  It saves
+                        * a partial pt_regs onto the stack and switches
+                        * to the interrupt stack.
+                        */
+                       else if (src->disp == bb_save_args) {
+                               bb_memory_set_reg(BBRG_RSP, BBRG_RDI, 0x48);
+                               bb_memory_set_reg(BBRG_RSP, BBRG_RSI, 0x40);
+                               bb_memory_set_reg(BBRG_RSP, BBRG_RDX, 0x38);
+                               bb_memory_set_reg(BBRG_RSP, BBRG_RCX, 0x30);
+                               bb_memory_set_reg(BBRG_RSP, BBRG_RAX, 0x28);
+                               bb_memory_set_reg(BBRG_RSP, BBRG_R8,  0x20);
+                               bb_memory_set_reg(BBRG_RSP, BBRG_R9,  0x18);
+                               bb_memory_set_reg(BBRG_RSP, BBRG_R10, 0x10);
+                               bb_memory_set_reg(BBRG_RSP, BBRG_R11, 0x08);
+                               bb_memory_set_reg(BBRG_RSP, BBRG_RBP, 0);
+                               /* This is actually on the interrupt stack,
+                                * but we fudge it so the unwind works.
+                                */
+                               bb_memory_set_reg_value(BBRG_RSP, -0x8, 
BBRG_RBP, 0);
+                               bb_reg_set_reg(BBRG_RBP, BBRG_RSP);
+                               bb_adjust_osp(BBRG_RSP, -KDB_WORD_SIZE);
+                       }
                }
+               /* Invalidate the scratch registers */
+               bb_invalidate_scratch_reg();
                usage = BBOU_NOP;
                break;
        case BBOU_CBW:
@@ -3784,7 +3808,8 @@ bb_usage(void)
                    strcmp(bb_func_name, "relocate_kernel") == 0 ||
                    strcmp(bb_func_name, "identity_mapped") == 0 ||
                    strcmp(bb_func_name, "xen_iret_crit_fixup") == 0 ||
-                   strcmp(bb_func_name, "math_abort") == 0)
+                   strcmp(bb_func_name, "math_abort") == 0 ||
+                   strcmp(bb_func_name, "save_args") == 0)
                        break;
                bb_sanity_check(0);
                break;
@@ -4452,7 +4477,7 @@ bb_actual_rollback(const struct kdb_activation_record *ar)
                           __FUNCTION__, bb_actual_value(BBRG_RSP));
        i = BBRG_RSP;
        if (!bb_is_osp_defined(i)) {
-               for (i = BBRG_RAX; i < BBRG_RAX + KDB_INT_REGISTERS; ++i) {
+               for (i = BBRG_RAX; i < BBRG_RAX + KDB_INT_REGISTERS; ++i) {
                        if (bb_is_osp_defined(i) && bb_actual_valid(i))
                                break;
                }
@@ -5176,7 +5201,7 @@ static void
 kdba_bt_new_stack(struct kdb_activation_record *ar, kdb_machreg_t *rsp,
                   int *count, int *suppress)
 {
-       /* Nasty: common_interrupt builds a partial pt_regs, with r15 through
+       /* Nasty: save_args builds a partial pt_regs, with r15 through
         * rbx not being filled in.  It passes struct pt_regs* to do_IRQ (in
         * rdi) but the stack pointer is not adjusted to account for r15
         * through rbx.  This has two effects :-
@@ -5573,6 +5598,7 @@ static int __init kdba_bt_x86_init(void)
        bb_save_v86_state = kallsyms_lookup_name("save_v86_state");
        bb__sched_text_start = kallsyms_lookup_name("__sched_text_start");
        bb__sched_text_end = kallsyms_lookup_name("__sched_text_end");
+       bb_save_args = kallsyms_lookup_name("save_args");
        for (i = 0, r = bb_special_cases;
             i < ARRAY_SIZE(bb_special_cases);
             ++i, ++r) {
-- 
1.5.4.rc3


_______________________________________________
kdb mailing list
[email protected]
http://oss.sgi.com/mailman/listinfo/kdb

Reply via email to