diff options
| author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-07-05 13:13:03 -0400 |
|---|---|---|
| committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2006-07-05 13:13:03 -0400 |
| commit | 5e66dd6d66ffe758b39b6dcadf2330753ee1159b (patch) | |
| tree | a72cdcff4448e4af9425cc213ddf56ab23e697fe /arch/s390/kernel | |
| parent | 026477c1141b67e98e3bd8bdedb7d4b88a3ecd09 (diff) | |
| parent | ca78f6baca863afe2e6a244a0fe94b3a70211d46 (diff) | |
Merge branch 'master' of /home/trondmy/kernel/linux-2.6/
Diffstat (limited to 'arch/s390/kernel')
| -rw-r--r-- | arch/s390/kernel/Makefile | 1 | ||||
| -rw-r--r-- | arch/s390/kernel/entry.S | 29 | ||||
| -rw-r--r-- | arch/s390/kernel/entry64.S | 21 | ||||
| -rw-r--r-- | arch/s390/kernel/irq.c | 8 | ||||
| -rw-r--r-- | arch/s390/kernel/process.c | 1 | ||||
| -rw-r--r-- | arch/s390/kernel/stacktrace.c | 90 |
6 files changed, 141 insertions, 9 deletions
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 9269b5788fac..eabf00a6f770 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile | |||
| @@ -21,6 +21,7 @@ obj-$(CONFIG_COMPAT) += compat_linux.o compat_signal.o \ | |||
| 21 | obj-$(CONFIG_BINFMT_ELF32) += binfmt_elf32.o | 21 | obj-$(CONFIG_BINFMT_ELF32) += binfmt_elf32.o |
| 22 | 22 | ||
| 23 | obj-$(CONFIG_VIRT_TIMER) += vtime.o | 23 | obj-$(CONFIG_VIRT_TIMER) += vtime.o |
| 24 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | ||
| 24 | 25 | ||
| 25 | # Kexec part | 26 | # Kexec part |
| 26 | S390_KEXEC_OBJS := machine_kexec.o crash.o | 27 | S390_KEXEC_OBJS := machine_kexec.o crash.o |
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index d8948c342caf..5b5799ac8f83 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S | |||
| @@ -58,6 +58,21 @@ STACK_SIZE = 1 << STACK_SHIFT | |||
| 58 | 58 | ||
| 59 | #define BASED(name) name-system_call(%r13) | 59 | #define BASED(name) name-system_call(%r13) |
| 60 | 60 | ||
| 61 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
| 62 | .macro TRACE_IRQS_ON | ||
| 63 | l %r1,BASED(.Ltrace_irq_on) | ||
| 64 | basr %r14,%r1 | ||
| 65 | .endm | ||
| 66 | |||
| 67 | .macro TRACE_IRQS_OFF | ||
| 68 | l %r1,BASED(.Ltrace_irq_off) | ||
| 69 | basr %r14,%r1 | ||
| 70 | .endm | ||
| 71 | #else | ||
| 72 | #define TRACE_IRQS_ON | ||
| 73 | #define TRACE_IRQS_OFF | ||
| 74 | #endif | ||
| 75 | |||
| 61 | /* | 76 | /* |
| 62 | * Register usage in interrupt handlers: | 77 | * Register usage in interrupt handlers: |
| 63 | * R9 - pointer to current task structure | 78 | * R9 - pointer to current task structure |
| @@ -361,6 +376,7 @@ ret_from_fork: | |||
| 361 | st %r15,SP_R15(%r15) # store stack pointer for new kthread | 376 | st %r15,SP_R15(%r15) # store stack pointer for new kthread |
| 362 | 0: l %r1,BASED(.Lschedtail) | 377 | 0: l %r1,BASED(.Lschedtail) |
| 363 | basr %r14,%r1 | 378 | basr %r14,%r1 |
| 379 | TRACE_IRQS_ON | ||
| 364 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts | 380 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts |
| 365 | b BASED(sysc_return) | 381 | b BASED(sysc_return) |
| 366 | 382 | ||
| @@ -516,6 +532,7 @@ pgm_no_vtime3: | |||
| 516 | mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS | 532 | mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS |
| 517 | mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID | 533 | mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID |
| 518 | oi __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP | 534 | oi __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP |
| 535 | TRACE_IRQS_ON | ||
| 519 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts | 536 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts |
| 520 | b BASED(sysc_do_svc) | 537 | b BASED(sysc_do_svc) |
| 521 | 538 | ||
| @@ -539,9 +556,11 @@ io_int_handler: | |||
| 539 | io_no_vtime: | 556 | io_no_vtime: |
| 540 | #endif | 557 | #endif |
| 541 | l %r9,__LC_THREAD_INFO # load pointer to thread_info struct | 558 | l %r9,__LC_THREAD_INFO # load pointer to thread_info struct |
| 559 | TRACE_IRQS_OFF | ||
| 542 | l %r1,BASED(.Ldo_IRQ) # load address of do_IRQ | 560 | l %r1,BASED(.Ldo_IRQ) # load address of do_IRQ |
| 543 | la %r2,SP_PTREGS(%r15) # address of register-save area | 561 | la %r2,SP_PTREGS(%r15) # address of register-save area |
| 544 | basr %r14,%r1 # branch to standard irq handler | 562 | basr %r14,%r1 # branch to standard irq handler |
| 563 | TRACE_IRQS_ON | ||
| 545 | 564 | ||
| 546 | io_return: | 565 | io_return: |
| 547 | tm SP_PSW+1(%r15),0x01 # returning to user ? | 566 | tm SP_PSW+1(%r15),0x01 # returning to user ? |
| @@ -651,10 +670,12 @@ ext_int_handler: | |||
| 651 | ext_no_vtime: | 670 | ext_no_vtime: |
| 652 | #endif | 671 | #endif |
| 653 | l %r9,__LC_THREAD_INFO # load pointer to thread_info struct | 672 | l %r9,__LC_THREAD_INFO # load pointer to thread_info struct |
| 673 | TRACE_IRQS_OFF | ||
| 654 | la %r2,SP_PTREGS(%r15) # address of register-save area | 674 | la %r2,SP_PTREGS(%r15) # address of register-save area |
| 655 | lh %r3,__LC_EXT_INT_CODE # get interruption code | 675 | lh %r3,__LC_EXT_INT_CODE # get interruption code |
| 656 | l %r1,BASED(.Ldo_extint) | 676 | l %r1,BASED(.Ldo_extint) |
| 657 | basr %r14,%r1 | 677 | basr %r14,%r1 |
| 678 | TRACE_IRQS_ON | ||
| 658 | b BASED(io_return) | 679 | b BASED(io_return) |
| 659 | 680 | ||
| 660 | __critical_end: | 681 | __critical_end: |
| @@ -731,8 +752,10 @@ mcck_no_vtime: | |||
| 731 | stosm __SF_EMPTY(%r15),0x04 # turn dat on | 752 | stosm __SF_EMPTY(%r15),0x04 # turn dat on |
| 732 | tm __TI_flags+3(%r9),_TIF_MCCK_PENDING | 753 | tm __TI_flags+3(%r9),_TIF_MCCK_PENDING |
| 733 | bno BASED(mcck_return) | 754 | bno BASED(mcck_return) |
| 755 | TRACE_IRQS_OFF | ||
| 734 | l %r1,BASED(.Ls390_handle_mcck) | 756 | l %r1,BASED(.Ls390_handle_mcck) |
| 735 | basr %r14,%r1 # call machine check handler | 757 | basr %r14,%r1 # call machine check handler |
| 758 | TRACE_IRQS_ON | ||
| 736 | mcck_return: | 759 | mcck_return: |
| 737 | mvc __LC_RETURN_MCCK_PSW(8),SP_PSW(%r15) # move return PSW | 760 | mvc __LC_RETURN_MCCK_PSW(8),SP_PSW(%r15) # move return PSW |
| 738 | ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit | 761 | ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit |
| @@ -1012,7 +1035,11 @@ cleanup_io_leave_insn: | |||
| 1012 | .Lvfork: .long sys_vfork | 1035 | .Lvfork: .long sys_vfork |
| 1013 | .Lschedtail: .long schedule_tail | 1036 | .Lschedtail: .long schedule_tail |
| 1014 | .Lsysc_table: .long sys_call_table | 1037 | .Lsysc_table: .long sys_call_table |
| 1015 | 1038 | #ifdef CONFIG_TRACE_IRQFLAGS | |
| 1039 | .Ltrace_irq_on:.long trace_hardirqs_on | ||
| 1040 | .Ltrace_irq_off: | ||
| 1041 | .long trace_hardirqs_off | ||
| 1042 | #endif | ||
| 1016 | .Lcritical_start: | 1043 | .Lcritical_start: |
| 1017 | .long __critical_start + 0x80000000 | 1044 | .long __critical_start + 0x80000000 |
| 1018 | .Lcritical_end: | 1045 | .Lcritical_end: |
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 1ca499fa54b4..56f5f613b868 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
| @@ -58,6 +58,19 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \ | |||
| 58 | 58 | ||
| 59 | #define BASED(name) name-system_call(%r13) | 59 | #define BASED(name) name-system_call(%r13) |
| 60 | 60 | ||
| 61 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
| 62 | .macro TRACE_IRQS_ON | ||
| 63 | brasl %r14,trace_hardirqs_on | ||
| 64 | .endm | ||
| 65 | |||
| 66 | .macro TRACE_IRQS_OFF | ||
| 67 | brasl %r14,trace_hardirqs_off | ||
| 68 | .endm | ||
| 69 | #else | ||
| 70 | #define TRACE_IRQS_ON | ||
| 71 | #define TRACE_IRQS_OFF | ||
| 72 | #endif | ||
| 73 | |||
| 61 | .macro STORE_TIMER lc_offset | 74 | .macro STORE_TIMER lc_offset |
| 62 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 75 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
| 63 | stpt \lc_offset | 76 | stpt \lc_offset |
| @@ -354,6 +367,7 @@ ret_from_fork: | |||
| 354 | jo 0f | 367 | jo 0f |
| 355 | stg %r15,SP_R15(%r15) # store stack pointer for new kthread | 368 | stg %r15,SP_R15(%r15) # store stack pointer for new kthread |
| 356 | 0: brasl %r14,schedule_tail | 369 | 0: brasl %r14,schedule_tail |
| 370 | TRACE_IRQS_ON | ||
| 357 | stosm 24(%r15),0x03 # reenable interrupts | 371 | stosm 24(%r15),0x03 # reenable interrupts |
| 358 | j sysc_return | 372 | j sysc_return |
| 359 | 373 | ||
| @@ -535,6 +549,7 @@ pgm_no_vtime3: | |||
| 535 | mvc __THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS | 549 | mvc __THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS |
| 536 | mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID | 550 | mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID |
| 537 | oi __TI_flags+7(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP | 551 | oi __TI_flags+7(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP |
| 552 | TRACE_IRQS_ON | ||
| 538 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts | 553 | stosm __SF_EMPTY(%r15),0x03 # reenable interrupts |
| 539 | j sysc_do_svc | 554 | j sysc_do_svc |
| 540 | 555 | ||
| @@ -557,8 +572,10 @@ io_int_handler: | |||
| 557 | io_no_vtime: | 572 | io_no_vtime: |
| 558 | #endif | 573 | #endif |
| 559 | lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct | 574 | lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct |
| 575 | TRACE_IRQS_OFF | ||
| 560 | la %r2,SP_PTREGS(%r15) # address of register-save area | 576 | la %r2,SP_PTREGS(%r15) # address of register-save area |
| 561 | brasl %r14,do_IRQ # call standard irq handler | 577 | brasl %r14,do_IRQ # call standard irq handler |
| 578 | TRACE_IRQS_ON | ||
| 562 | 579 | ||
| 563 | io_return: | 580 | io_return: |
| 564 | tm SP_PSW+1(%r15),0x01 # returning to user ? | 581 | tm SP_PSW+1(%r15),0x01 # returning to user ? |
| @@ -665,9 +682,11 @@ ext_int_handler: | |||
| 665 | ext_no_vtime: | 682 | ext_no_vtime: |
| 666 | #endif | 683 | #endif |
| 667 | lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct | 684 | lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct |
| 685 | TRACE_IRQS_OFF | ||
| 668 | la %r2,SP_PTREGS(%r15) # address of register-save area | 686 | la %r2,SP_PTREGS(%r15) # address of register-save area |
| 669 | llgh %r3,__LC_EXT_INT_CODE # get interruption code | 687 | llgh %r3,__LC_EXT_INT_CODE # get interruption code |
| 670 | brasl %r14,do_extint | 688 | brasl %r14,do_extint |
| 689 | TRACE_IRQS_ON | ||
| 671 | j io_return | 690 | j io_return |
| 672 | 691 | ||
| 673 | __critical_end: | 692 | __critical_end: |
| @@ -743,7 +762,9 @@ mcck_no_vtime: | |||
| 743 | stosm __SF_EMPTY(%r15),0x04 # turn dat on | 762 | stosm __SF_EMPTY(%r15),0x04 # turn dat on |
| 744 | tm __TI_flags+7(%r9),_TIF_MCCK_PENDING | 763 | tm __TI_flags+7(%r9),_TIF_MCCK_PENDING |
| 745 | jno mcck_return | 764 | jno mcck_return |
| 765 | TRACE_IRQS_OFF | ||
| 746 | brasl %r14,s390_handle_mcck | 766 | brasl %r14,s390_handle_mcck |
| 767 | TRACE_IRQS_ON | ||
| 747 | mcck_return: | 768 | mcck_return: |
| 748 | mvc __LC_RETURN_MCCK_PSW(16),SP_PSW(%r15) # move return PSW | 769 | mvc __LC_RETURN_MCCK_PSW(16),SP_PSW(%r15) # move return PSW |
| 749 | ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit | 770 | ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit |
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index 480b6a5fef3a..1eef50918615 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c | |||
| @@ -69,10 +69,6 @@ asmlinkage void do_softirq(void) | |||
| 69 | 69 | ||
| 70 | local_irq_save(flags); | 70 | local_irq_save(flags); |
| 71 | 71 | ||
| 72 | account_system_vtime(current); | ||
| 73 | |||
| 74 | local_bh_disable(); | ||
| 75 | |||
| 76 | if (local_softirq_pending()) { | 72 | if (local_softirq_pending()) { |
| 77 | /* Get current stack pointer. */ | 73 | /* Get current stack pointer. */ |
| 78 | asm volatile("la %0,0(15)" : "=a" (old)); | 74 | asm volatile("la %0,0(15)" : "=a" (old)); |
| @@ -95,10 +91,6 @@ asmlinkage void do_softirq(void) | |||
| 95 | __do_softirq(); | 91 | __do_softirq(); |
| 96 | } | 92 | } |
| 97 | 93 | ||
| 98 | account_system_vtime(current); | ||
| 99 | |||
| 100 | __local_bh_enable(); | ||
| 101 | |||
| 102 | local_irq_restore(flags); | 94 | local_irq_restore(flags); |
| 103 | } | 95 | } |
| 104 | 96 | ||
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 1f9399191794..78c8e5548caf 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c | |||
| @@ -142,6 +142,7 @@ static void default_idle(void) | |||
| 142 | return; | 142 | return; |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | trace_hardirqs_on(); | ||
| 145 | /* Wait for external, I/O or machine check interrupt. */ | 146 | /* Wait for external, I/O or machine check interrupt. */ |
| 146 | __load_psw_mask(PSW_KERNEL_BITS | PSW_MASK_WAIT | | 147 | __load_psw_mask(PSW_KERNEL_BITS | PSW_MASK_WAIT | |
| 147 | PSW_MASK_IO | PSW_MASK_EXT); | 148 | PSW_MASK_IO | PSW_MASK_EXT); |
diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c new file mode 100644 index 000000000000..de83f38288d0 --- /dev/null +++ b/arch/s390/kernel/stacktrace.c | |||
| @@ -0,0 +1,90 @@ | |||
| 1 | /* | ||
| 2 | * arch/s390/kernel/stacktrace.c | ||
| 3 | * | ||
| 4 | * Stack trace management functions | ||
| 5 | * | ||
| 6 | * Copyright (C) IBM Corp. 2006 | ||
| 7 | * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com> | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/sched.h> | ||
| 11 | #include <linux/stacktrace.h> | ||
| 12 | #include <linux/kallsyms.h> | ||
| 13 | |||
| 14 | static inline unsigned long save_context_stack(struct stack_trace *trace, | ||
| 15 | unsigned int *skip, | ||
| 16 | unsigned long sp, | ||
| 17 | unsigned long low, | ||
| 18 | unsigned long high) | ||
| 19 | { | ||
| 20 | struct stack_frame *sf; | ||
| 21 | struct pt_regs *regs; | ||
| 22 | unsigned long addr; | ||
| 23 | |||
| 24 | while(1) { | ||
| 25 | sp &= PSW_ADDR_INSN; | ||
| 26 | if (sp < low || sp > high) | ||
| 27 | return sp; | ||
| 28 | sf = (struct stack_frame *)sp; | ||
| 29 | while(1) { | ||
| 30 | addr = sf->gprs[8] & PSW_ADDR_INSN; | ||
| 31 | if (!(*skip)) | ||
| 32 | trace->entries[trace->nr_entries++] = addr; | ||
| 33 | else | ||
| 34 | (*skip)--; | ||
| 35 | if (trace->nr_entries >= trace->max_entries) | ||
| 36 | return sp; | ||
| 37 | low = sp; | ||
| 38 | sp = sf->back_chain & PSW_ADDR_INSN; | ||
| 39 | if (!sp) | ||
| 40 | break; | ||
| 41 | if (sp <= low || sp > high - sizeof(*sf)) | ||
| 42 | return sp; | ||
| 43 | sf = (struct stack_frame *)sp; | ||
| 44 | } | ||
| 45 | /* Zero backchain detected, check for interrupt frame. */ | ||
| 46 | sp = (unsigned long)(sf + 1); | ||
| 47 | if (sp <= low || sp > high - sizeof(*regs)) | ||
| 48 | return sp; | ||
| 49 | regs = (struct pt_regs *)sp; | ||
| 50 | addr = regs->psw.addr & PSW_ADDR_INSN; | ||
| 51 | if (!(*skip)) | ||
| 52 | trace->entries[trace->nr_entries++] = addr; | ||
| 53 | else | ||
| 54 | (*skip)--; | ||
| 55 | if (trace->nr_entries >= trace->max_entries) | ||
| 56 | return sp; | ||
| 57 | low = sp; | ||
| 58 | sp = regs->gprs[15]; | ||
| 59 | } | ||
| 60 | } | ||
| 61 | |||
| 62 | void save_stack_trace(struct stack_trace *trace, | ||
| 63 | struct task_struct *task, int all_contexts, | ||
| 64 | unsigned int skip) | ||
| 65 | { | ||
| 66 | register unsigned long sp asm ("15"); | ||
| 67 | unsigned long orig_sp; | ||
| 68 | |||
| 69 | sp &= PSW_ADDR_INSN; | ||
| 70 | orig_sp = sp; | ||
| 71 | |||
| 72 | sp = save_context_stack(trace, &skip, sp, | ||
| 73 | S390_lowcore.panic_stack - PAGE_SIZE, | ||
| 74 | S390_lowcore.panic_stack); | ||
| 75 | if ((sp != orig_sp) && !all_contexts) | ||
| 76 | return; | ||
| 77 | sp = save_context_stack(trace, &skip, sp, | ||
| 78 | S390_lowcore.async_stack - ASYNC_SIZE, | ||
| 79 | S390_lowcore.async_stack); | ||
| 80 | if ((sp != orig_sp) && !all_contexts) | ||
| 81 | return; | ||
| 82 | if (task) | ||
| 83 | save_context_stack(trace, &skip, sp, | ||
| 84 | (unsigned long) task_stack_page(task), | ||
| 85 | (unsigned long) task_stack_page(task) + THREAD_SIZE); | ||
| 86 | else | ||
| 87 | save_context_stack(trace, &skip, sp, S390_lowcore.thread_info, | ||
| 88 | S390_lowcore.thread_info + THREAD_SIZE); | ||
| 89 | return; | ||
| 90 | } | ||
