mca.c (9336b0836bf789136b51caf9ddd49dcbf1726cf4) | mca.c (e9ac054daaecf8a11f2113b60f2b6ce381c4f131) |
---|---|
1/* 2 * File: mca.c 3 * Purpose: Generic MCA handling layer 4 * 5 * Updated for latest kernel 6 * Copyright (C) 2003 Hewlett-Packard Co 7 * David Mosberger-Tang <davidm@hpl.hp.com> 8 * --- 616 unchanged lines hidden (view full) --- 625 *tr = *fr; 626 fslot = ((unsigned long)fr >> 3) & 63; 627 tslot = ((unsigned long)tr >> 3) & 63; 628 *tnat &= ~(1UL << tslot); 629 nat = (fnat >> fslot) & 1; 630 *tnat |= (nat << tslot); 631} 632 | 1/* 2 * File: mca.c 3 * Purpose: Generic MCA handling layer 4 * 5 * Updated for latest kernel 6 * Copyright (C) 2003 Hewlett-Packard Co 7 * David Mosberger-Tang <davidm@hpl.hp.com> 8 * --- 616 unchanged lines hidden (view full) --- 625 *tr = *fr; 626 fslot = ((unsigned long)fr >> 3) & 63; 627 tslot = ((unsigned long)tr >> 3) & 63; 628 *tnat &= ~(1UL << tslot); 629 nat = (fnat >> fslot) & 1; 630 *tnat |= (nat << tslot); 631} 632 |
633/* Change the comm field on the MCA/INT task to include the pid that 634 * was interrupted, it makes for easier debugging. If that pid was 0 635 * (swapper or nested MCA/INIT) then use the start of the previous comm 636 * field suffixed with its cpu. 637 */ 638 639static void 640ia64_mca_modify_comm(const task_t *previous_current) 641{ 642 char *p, comm[sizeof(current->comm)]; 643 if (previous_current->pid) 644 snprintf(comm, sizeof(comm), "%s %d", 645 current->comm, previous_current->pid); 646 else { 647 int l; 648 if ((p = strchr(previous_current->comm, ' '))) 649 l = p - previous_current->comm; 650 else 651 l = strlen(previous_current->comm); 652 snprintf(comm, sizeof(comm), "%s %*s %d", 653 current->comm, l, previous_current->comm, 654 task_thread_info(previous_current)->cpu); 655 } 656 memcpy(current->comm, comm, sizeof(current->comm)); 657} 658 |
|
633/* On entry to this routine, we are running on the per cpu stack, see 634 * mca_asm.h. The original stack has not been touched by this event. Some of 635 * the original stack's registers will be in the RBS on this stack. This stack 636 * also contains a partial pt_regs and switch_stack, the rest of the data is in 637 * PAL minstate. 638 * 639 * The first thing to do is modify the original stack to look like a blocked 640 * task so we can run backtrace on the original task. Also mark the per cpu 641 * stack as current to ensure that we use the correct task state, it also means 642 * that we can do backtrace on the MCA/INIT handler code itself. 643 */ 644 645static task_t * 646ia64_mca_modify_original_stack(struct pt_regs *regs, 647 const struct switch_stack *sw, 648 struct ia64_sal_os_state *sos, 649 const char *type) 650{ | 659/* On entry to this routine, we are running on the per cpu stack, see 660 * mca_asm.h. The original stack has not been touched by this event. Some of 661 * the original stack's registers will be in the RBS on this stack. This stack 662 * also contains a partial pt_regs and switch_stack, the rest of the data is in 663 * PAL minstate. 664 * 665 * The first thing to do is modify the original stack to look like a blocked 666 * task so we can run backtrace on the original task. Also mark the per cpu 667 * stack as current to ensure that we use the correct task state, it also means 668 * that we can do backtrace on the MCA/INIT handler code itself. 669 */ 670 671static task_t * 672ia64_mca_modify_original_stack(struct pt_regs *regs, 673 const struct switch_stack *sw, 674 struct ia64_sal_os_state *sos, 675 const char *type) 676{ |
651 char *p, comm[sizeof(current->comm)]; | 677 char *p; |
652 ia64_va va; 653 extern char ia64_leave_kernel[]; /* Need asm address, not function descriptor */ 654 const pal_min_state_area_t *ms = sos->pal_min_state; 655 task_t *previous_current; 656 struct pt_regs *old_regs; 657 struct switch_stack *old_sw; 658 unsigned size = sizeof(struct pt_regs) + 659 sizeof(struct switch_stack) + 16; --- 56 unchanged lines hidden (view full) --- 716 slots = ia64_rse_num_regs(old_bspstore, old_bsp); 717 new_bspstore = (u64 *)((u64)current + IA64_RBS_OFFSET); 718 new_bsp = ia64_rse_skip_regs(new_bspstore, slots); 719 regs->loadrs = (new_bsp - new_bspstore) * 8 << 16; 720 721 /* Verify the previous stack state before we change it */ 722 if (user_mode(regs)) { 723 msg = "occurred in user space"; | 678 ia64_va va; 679 extern char ia64_leave_kernel[]; /* Need asm address, not function descriptor */ 680 const pal_min_state_area_t *ms = sos->pal_min_state; 681 task_t *previous_current; 682 struct pt_regs *old_regs; 683 struct switch_stack *old_sw; 684 unsigned size = sizeof(struct pt_regs) + 685 sizeof(struct switch_stack) + 16; --- 56 unchanged lines hidden (view full) --- 742 slots = ia64_rse_num_regs(old_bspstore, old_bsp); 743 new_bspstore = (u64 *)((u64)current + IA64_RBS_OFFSET); 744 new_bsp = ia64_rse_skip_regs(new_bspstore, slots); 745 regs->loadrs = (new_bsp - new_bspstore) * 8 << 16; 746 747 /* Verify the previous stack state before we change it */ 748 if (user_mode(regs)) { 749 msg = "occurred in user space"; |
750 /* previous_current is guaranteed to be valid when the task was 751 * in user space, so ... 752 */ 753 ia64_mca_modify_comm(previous_current); |
|
724 goto no_mod; 725 } 726 if (r13 != sos->prev_IA64_KR_CURRENT) { 727 msg = "inconsistent previous current and r13"; 728 goto no_mod; 729 } 730 if ((r12 - r13) >= KERNEL_STACK_SIZE) { 731 msg = "inconsistent r12 and r13"; --- 13 unchanged lines hidden (view full) --- 745 goto no_mod; 746 } 747 size += (ia64_rse_skip_regs(old_bspstore, slots) - old_bspstore) * 8; 748 if (ar_bspstore + size > r12) { 749 msg = "no room for blocked state"; 750 goto no_mod; 751 } 752 | 754 goto no_mod; 755 } 756 if (r13 != sos->prev_IA64_KR_CURRENT) { 757 msg = "inconsistent previous current and r13"; 758 goto no_mod; 759 } 760 if ((r12 - r13) >= KERNEL_STACK_SIZE) { 761 msg = "inconsistent r12 and r13"; --- 13 unchanged lines hidden (view full) --- 775 goto no_mod; 776 } 777 size += (ia64_rse_skip_regs(old_bspstore, slots) - old_bspstore) * 8; 778 if (ar_bspstore + size > r12) { 779 msg = "no room for blocked state"; 780 goto no_mod; 781 } 782 |
753 /* Change the comm field on the MCA/INT task to include the pid that 754 * was interrupted, it makes for easier debugging. If that pid was 0 755 * (swapper or nested MCA/INIT) then use the start of the previous comm 756 * field suffixed with its cpu. 757 */ 758 if (previous_current->pid) 759 snprintf(comm, sizeof(comm), "%s %d", 760 current->comm, previous_current->pid); 761 else { 762 int l; 763 if ((p = strchr(previous_current->comm, ' '))) 764 l = p - previous_current->comm; 765 else 766 l = strlen(previous_current->comm); 767 snprintf(comm, sizeof(comm), "%s %*s %d", 768 current->comm, l, previous_current->comm, 769 task_thread_info(previous_current)->cpu); 770 } 771 memcpy(current->comm, comm, sizeof(current->comm)); | 783 ia64_mca_modify_comm(previous_current); |
772 773 /* Make the original task look blocked. First stack a struct pt_regs, 774 * describing the state at the time of interrupt. mca_asm.S built a 775 * partial pt_regs, copy it and fill in the blanks using minstate. 776 */ 777 p = (char *)r12 - sizeof(*regs); 778 old_regs = (struct pt_regs *)p; 779 memcpy(old_regs, regs, sizeof(*regs)); --- 965 unchanged lines hidden --- | 784 785 /* Make the original task look blocked. First stack a struct pt_regs, 786 * describing the state at the time of interrupt. mca_asm.S built a 787 * partial pt_regs, copy it and fill in the blanks using minstate. 788 */ 789 p = (char *)r12 - sizeof(*regs); 790 old_regs = (struct pt_regs *)p; 791 memcpy(old_regs, regs, sizeof(*regs)); --- 965 unchanged lines hidden --- |