diff options
Diffstat (limited to 'arch/s390')
-rw-r--r-- | arch/s390/kernel/debug.c | 52 | ||||
-rw-r--r-- | arch/s390/kernel/entry.S | 116 | ||||
-rw-r--r-- | arch/s390/kernel/entry64.S | 117 | ||||
-rw-r--r-- | arch/s390/kernel/time.c | 5 | ||||
-rw-r--r-- | arch/s390/mm/fault.c | 5 |
5 files changed, 213 insertions, 82 deletions
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index 960ba6029c3a..bc59282da762 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c | |||
@@ -62,7 +62,7 @@ typedef struct | |||
62 | } debug_sprintf_entry_t; | 62 | } debug_sprintf_entry_t; |
63 | 63 | ||
64 | 64 | ||
65 | extern void tod_to_timeval(uint64_t todval, struct timeval *xtime); | 65 | extern void tod_to_timeval(uint64_t todval, struct timespec *xtime); |
66 | 66 | ||
67 | /* internal function prototyes */ | 67 | /* internal function prototyes */ |
68 | 68 | ||
@@ -374,9 +374,24 @@ debug_info_copy(debug_info_t* in, int mode) | |||
374 | { | 374 | { |
375 | int i,j; | 375 | int i,j; |
376 | debug_info_t* rc; | 376 | debug_info_t* rc; |
377 | unsigned long flags; | ||
378 | |||
379 | /* get a consistent copy of the debug areas */ | ||
380 | do { | ||
381 | rc = debug_info_alloc(in->name, in->pages_per_area, | ||
382 | in->nr_areas, in->buf_size, in->level, mode); | ||
383 | spin_lock_irqsave(&in->lock, flags); | ||
384 | if(!rc) | ||
385 | goto out; | ||
386 | /* has something changed in the meantime ? */ | ||
387 | if((rc->pages_per_area == in->pages_per_area) && | ||
388 | (rc->nr_areas == in->nr_areas)) { | ||
389 | break; | ||
390 | } | ||
391 | spin_unlock_irqrestore(&in->lock, flags); | ||
392 | debug_info_free(rc); | ||
393 | } while (1); | ||
377 | 394 | ||
378 | rc = debug_info_alloc(in->name, in->pages_per_area, in->nr_areas, | ||
379 | in->buf_size, in->level, mode); | ||
380 | if(!rc || (mode == NO_AREAS)) | 395 | if(!rc || (mode == NO_AREAS)) |
381 | goto out; | 396 | goto out; |
382 | 397 | ||
@@ -386,6 +401,7 @@ debug_info_copy(debug_info_t* in, int mode) | |||
386 | } | 401 | } |
387 | } | 402 | } |
388 | out: | 403 | out: |
404 | spin_unlock_irqrestore(&in->lock, flags); | ||
389 | return rc; | 405 | return rc; |
390 | } | 406 | } |
391 | 407 | ||
@@ -593,19 +609,15 @@ debug_open(struct inode *inode, struct file *file) | |||
593 | debug_info_t *debug_info, *debug_info_snapshot; | 609 | debug_info_t *debug_info, *debug_info_snapshot; |
594 | 610 | ||
595 | down(&debug_lock); | 611 | down(&debug_lock); |
596 | 612 | debug_info = (struct debug_info*)file->f_dentry->d_inode->u.generic_ip; | |
597 | /* find debug log and view */ | 613 | /* find debug view */ |
598 | debug_info = debug_area_first; | 614 | for (i = 0; i < DEBUG_MAX_VIEWS; i++) { |
599 | while(debug_info != NULL){ | 615 | if (!debug_info->views[i]) |
600 | for (i = 0; i < DEBUG_MAX_VIEWS; i++) { | 616 | continue; |
601 | if (!debug_info->views[i]) | 617 | else if (debug_info->debugfs_entries[i] == |
602 | continue; | 618 | file->f_dentry) { |
603 | else if (debug_info->debugfs_entries[i] == | 619 | goto found; /* found view ! */ |
604 | file->f_dentry) { | ||
605 | goto found; /* found view ! */ | ||
606 | } | ||
607 | } | 620 | } |
608 | debug_info = debug_info->next; | ||
609 | } | 621 | } |
610 | /* no entry found */ | 622 | /* no entry found */ |
611 | rc = -EINVAL; | 623 | rc = -EINVAL; |
@@ -833,7 +845,7 @@ extern inline void | |||
833 | debug_finish_entry(debug_info_t * id, debug_entry_t* active, int level, | 845 | debug_finish_entry(debug_info_t * id, debug_entry_t* active, int level, |
834 | int exception) | 846 | int exception) |
835 | { | 847 | { |
836 | STCK(active->id.stck); | 848 | active->id.stck = get_clock(); |
837 | active->id.fields.cpuid = smp_processor_id(); | 849 | active->id.fields.cpuid = smp_processor_id(); |
838 | active->caller = __builtin_return_address(0); | 850 | active->caller = __builtin_return_address(0); |
839 | active->id.fields.exception = exception; | 851 | active->id.fields.exception = exception; |
@@ -1078,7 +1090,7 @@ debug_register_view(debug_info_t * id, struct debug_view *view) | |||
1078 | if (view->input_proc) | 1090 | if (view->input_proc) |
1079 | mode |= S_IWUSR; | 1091 | mode |= S_IWUSR; |
1080 | pde = debugfs_create_file(view->name, mode, id->debugfs_root_entry, | 1092 | pde = debugfs_create_file(view->name, mode, id->debugfs_root_entry, |
1081 | NULL, &debug_file_ops); | 1093 | id , &debug_file_ops); |
1082 | if (!pde){ | 1094 | if (!pde){ |
1083 | printk(KERN_WARNING "debug: debugfs_create_file() failed!"\ | 1095 | printk(KERN_WARNING "debug: debugfs_create_file() failed!"\ |
1084 | " Cannot register view %s/%s\n", id->name,view->name); | 1096 | " Cannot register view %s/%s\n", id->name,view->name); |
@@ -1432,7 +1444,7 @@ int | |||
1432 | debug_dflt_header_fn(debug_info_t * id, struct debug_view *view, | 1444 | debug_dflt_header_fn(debug_info_t * id, struct debug_view *view, |
1433 | int area, debug_entry_t * entry, char *out_buf) | 1445 | int area, debug_entry_t * entry, char *out_buf) |
1434 | { | 1446 | { |
1435 | struct timeval time_val; | 1447 | struct timespec time_spec; |
1436 | unsigned long long time; | 1448 | unsigned long long time; |
1437 | char *except_str; | 1449 | char *except_str; |
1438 | unsigned long caller; | 1450 | unsigned long caller; |
@@ -1443,7 +1455,7 @@ debug_dflt_header_fn(debug_info_t * id, struct debug_view *view, | |||
1443 | time = entry->id.stck; | 1455 | time = entry->id.stck; |
1444 | /* adjust todclock to 1970 */ | 1456 | /* adjust todclock to 1970 */ |
1445 | time -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096); | 1457 | time -= 0x8126d60e46000000LL - (0x3c26700LL * 1000000 * 4096); |
1446 | tod_to_timeval(time, &time_val); | 1458 | tod_to_timeval(time, &time_spec); |
1447 | 1459 | ||
1448 | if (entry->id.fields.exception) | 1460 | if (entry->id.fields.exception) |
1449 | except_str = "*"; | 1461 | except_str = "*"; |
@@ -1451,7 +1463,7 @@ debug_dflt_header_fn(debug_info_t * id, struct debug_view *view, | |||
1451 | except_str = "-"; | 1463 | except_str = "-"; |
1452 | caller = ((unsigned long) entry->caller) & PSW_ADDR_INSN; | 1464 | caller = ((unsigned long) entry->caller) & PSW_ADDR_INSN; |
1453 | rc += sprintf(out_buf, "%02i %011lu:%06lu %1u %1s %02i %p ", | 1465 | rc += sprintf(out_buf, "%02i %011lu:%06lu %1u %1s %02i %p ", |
1454 | area, time_val.tv_sec, time_val.tv_usec, level, | 1466 | area, time_spec.tv_sec, time_spec.tv_nsec / 1000, level, |
1455 | except_str, entry->id.fields.cpuid, (void *) caller); | 1467 | except_str, entry->id.fields.cpuid, (void *) caller); |
1456 | return rc; | 1468 | return rc; |
1457 | } | 1469 | } |
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 1a271b16cb5c..cbe7d6a2d02c 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S | |||
@@ -138,14 +138,14 @@ STACK_SIZE = 1 << STACK_SHIFT | |||
138 | st %r12,__SF_BACKCHAIN(%r15) # clear back chain | 138 | st %r12,__SF_BACKCHAIN(%r15) # clear back chain |
139 | .endm | 139 | .endm |
140 | 140 | ||
141 | .macro RESTORE_ALL sync | 141 | .macro RESTORE_ALL psworg,sync |
142 | mvc __LC_RETURN_PSW(8),SP_PSW(%r15) # move user PSW to lowcore | 142 | mvc \psworg(8),SP_PSW(%r15) # move user PSW to lowcore |
143 | .if !\sync | 143 | .if !\sync |
144 | ni __LC_RETURN_PSW+1,0xfd # clear wait state bit | 144 | ni \psworg+1,0xfd # clear wait state bit |
145 | .endif | 145 | .endif |
146 | lm %r0,%r15,SP_R0(%r15) # load gprs 0-15 of user | 146 | lm %r0,%r15,SP_R0(%r15) # load gprs 0-15 of user |
147 | STORE_TIMER __LC_EXIT_TIMER | 147 | STORE_TIMER __LC_EXIT_TIMER |
148 | lpsw __LC_RETURN_PSW # back to caller | 148 | lpsw \psworg # back to caller |
149 | .endm | 149 | .endm |
150 | 150 | ||
151 | /* | 151 | /* |
@@ -235,7 +235,7 @@ sysc_return: | |||
235 | tm __TI_flags+3(%r9),_TIF_WORK_SVC | 235 | tm __TI_flags+3(%r9),_TIF_WORK_SVC |
236 | bnz BASED(sysc_work) # there is work to do (signals etc.) | 236 | bnz BASED(sysc_work) # there is work to do (signals etc.) |
237 | sysc_leave: | 237 | sysc_leave: |
238 | RESTORE_ALL 1 | 238 | RESTORE_ALL __LC_RETURN_PSW,1 |
239 | 239 | ||
240 | # | 240 | # |
241 | # recheck if there is more work to do | 241 | # recheck if there is more work to do |
@@ -312,8 +312,6 @@ sysc_singlestep: | |||
312 | la %r14,BASED(sysc_return) # load adr. of system return | 312 | la %r14,BASED(sysc_return) # load adr. of system return |
313 | br %r1 # branch to do_single_step | 313 | br %r1 # branch to do_single_step |
314 | 314 | ||
315 | __critical_end: | ||
316 | |||
317 | # | 315 | # |
318 | # call trace before and after sys_call | 316 | # call trace before and after sys_call |
319 | # | 317 | # |
@@ -571,7 +569,8 @@ io_return: | |||
571 | tm __TI_flags+3(%r9),_TIF_WORK_INT | 569 | tm __TI_flags+3(%r9),_TIF_WORK_INT |
572 | bnz BASED(io_work) # there is work to do (signals etc.) | 570 | bnz BASED(io_work) # there is work to do (signals etc.) |
573 | io_leave: | 571 | io_leave: |
574 | RESTORE_ALL 0 | 572 | RESTORE_ALL __LC_RETURN_PSW,0 |
573 | io_done: | ||
575 | 574 | ||
576 | #ifdef CONFIG_PREEMPT | 575 | #ifdef CONFIG_PREEMPT |
577 | io_preempt: | 576 | io_preempt: |
@@ -621,7 +620,7 @@ io_work_loop: | |||
621 | # | 620 | # |
622 | io_mcck_pending: | 621 | io_mcck_pending: |
623 | l %r1,BASED(.Ls390_handle_mcck) | 622 | l %r1,BASED(.Ls390_handle_mcck) |
624 | l %r14,BASED(io_work_loop) | 623 | la %r14,BASED(io_work_loop) |
625 | br %r1 # TIF bit will be cleared by handler | 624 | br %r1 # TIF bit will be cleared by handler |
626 | 625 | ||
627 | # | 626 | # |
@@ -674,6 +673,8 @@ ext_no_vtime: | |||
674 | basr %r14,%r1 | 673 | basr %r14,%r1 |
675 | b BASED(io_return) | 674 | b BASED(io_return) |
676 | 675 | ||
676 | __critical_end: | ||
677 | |||
677 | /* | 678 | /* |
678 | * Machine check handler routines | 679 | * Machine check handler routines |
679 | */ | 680 | */ |
@@ -681,6 +682,7 @@ ext_no_vtime: | |||
681 | .globl mcck_int_handler | 682 | .globl mcck_int_handler |
682 | mcck_int_handler: | 683 | mcck_int_handler: |
683 | spt __LC_CPU_TIMER_SAVE_AREA # revalidate cpu timer | 684 | spt __LC_CPU_TIMER_SAVE_AREA # revalidate cpu timer |
685 | mvc __LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA | ||
684 | lm %r0,%r15,__LC_GPREGS_SAVE_AREA # revalidate gprs | 686 | lm %r0,%r15,__LC_GPREGS_SAVE_AREA # revalidate gprs |
685 | SAVE_ALL_BASE __LC_SAVE_AREA+32 | 687 | SAVE_ALL_BASE __LC_SAVE_AREA+32 |
686 | la %r12,__LC_MCK_OLD_PSW | 688 | la %r12,__LC_MCK_OLD_PSW |
@@ -693,17 +695,8 @@ mcck_int_handler: | |||
693 | mvc __LC_ASYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER | 695 | mvc __LC_ASYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER |
694 | mvc __LC_SYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER | 696 | mvc __LC_SYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER |
695 | mvc __LC_EXIT_TIMER(8),__LC_LAST_UPDATE_TIMER | 697 | mvc __LC_EXIT_TIMER(8),__LC_LAST_UPDATE_TIMER |
696 | 0: tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid? | ||
697 | bno BASED(mcck_no_vtime) # no -> skip cleanup critical | ||
698 | tm __LC_MCK_OLD_PSW+1,0x01 # interrupting from user ? | ||
699 | bz BASED(mcck_no_vtime) | ||
700 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER | ||
701 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | ||
702 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER | ||
703 | mcck_no_vtime: | ||
704 | #endif | 698 | #endif |
705 | 0: | 699 | 0: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? |
706 | tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? | ||
707 | bno BASED(mcck_int_main) # no -> skip cleanup critical | 700 | bno BASED(mcck_int_main) # no -> skip cleanup critical |
708 | tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit | 701 | tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit |
709 | bnz BASED(mcck_int_main) # from user -> load async stack | 702 | bnz BASED(mcck_int_main) # from user -> load async stack |
@@ -720,6 +713,16 @@ mcck_int_main: | |||
720 | be BASED(0f) | 713 | be BASED(0f) |
721 | l %r15,__LC_PANIC_STACK # load panic stack | 714 | l %r15,__LC_PANIC_STACK # load panic stack |
722 | 0: CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+32 | 715 | 0: CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+32 |
716 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
717 | tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid? | ||
718 | bno BASED(mcck_no_vtime) # no -> skip cleanup critical | ||
719 | tm __LC_MCK_OLD_PSW+1,0x01 # interrupting from user ? | ||
720 | bz BASED(mcck_no_vtime) | ||
721 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER | ||
722 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | ||
723 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER | ||
724 | mcck_no_vtime: | ||
725 | #endif | ||
723 | l %r9,__LC_THREAD_INFO # load pointer to thread_info struct | 726 | l %r9,__LC_THREAD_INFO # load pointer to thread_info struct |
724 | la %r2,SP_PTREGS(%r15) # load pt_regs | 727 | la %r2,SP_PTREGS(%r15) # load pt_regs |
725 | l %r1,BASED(.Ls390_mcck) | 728 | l %r1,BASED(.Ls390_mcck) |
@@ -737,7 +740,7 @@ mcck_int_main: | |||
737 | l %r1,BASED(.Ls390_handle_mcck) | 740 | l %r1,BASED(.Ls390_handle_mcck) |
738 | basr %r14,%r1 # call machine check handler | 741 | basr %r14,%r1 # call machine check handler |
739 | mcck_return: | 742 | mcck_return: |
740 | RESTORE_ALL 0 | 743 | RESTORE_ALL __LC_RETURN_MCCK_PSW,0 |
741 | 744 | ||
742 | #ifdef CONFIG_SMP | 745 | #ifdef CONFIG_SMP |
743 | /* | 746 | /* |
@@ -803,6 +806,10 @@ cleanup_table_sysc_leave: | |||
803 | .long sysc_leave + 0x80000000, sysc_work_loop + 0x80000000 | 806 | .long sysc_leave + 0x80000000, sysc_work_loop + 0x80000000 |
804 | cleanup_table_sysc_work_loop: | 807 | cleanup_table_sysc_work_loop: |
805 | .long sysc_work_loop + 0x80000000, sysc_reschedule + 0x80000000 | 808 | .long sysc_work_loop + 0x80000000, sysc_reschedule + 0x80000000 |
809 | cleanup_table_io_leave: | ||
810 | .long io_leave + 0x80000000, io_done + 0x80000000 | ||
811 | cleanup_table_io_work_loop: | ||
812 | .long io_work_loop + 0x80000000, io_mcck_pending + 0x80000000 | ||
806 | 813 | ||
807 | cleanup_critical: | 814 | cleanup_critical: |
808 | clc 4(4,%r12),BASED(cleanup_table_system_call) | 815 | clc 4(4,%r12),BASED(cleanup_table_system_call) |
@@ -825,10 +832,26 @@ cleanup_critical: | |||
825 | clc 4(4,%r12),BASED(cleanup_table_sysc_work_loop+4) | 832 | clc 4(4,%r12),BASED(cleanup_table_sysc_work_loop+4) |
826 | bl BASED(cleanup_sysc_return) | 833 | bl BASED(cleanup_sysc_return) |
827 | 0: | 834 | 0: |
835 | clc 4(4,%r12),BASED(cleanup_table_io_leave) | ||
836 | bl BASED(0f) | ||
837 | clc 4(4,%r12),BASED(cleanup_table_io_leave+4) | ||
838 | bl BASED(cleanup_io_leave) | ||
839 | 0: | ||
840 | clc 4(4,%r12),BASED(cleanup_table_io_work_loop) | ||
841 | bl BASED(0f) | ||
842 | clc 4(4,%r12),BASED(cleanup_table_io_work_loop+4) | ||
843 | bl BASED(cleanup_io_return) | ||
844 | 0: | ||
828 | br %r14 | 845 | br %r14 |
829 | 846 | ||
830 | cleanup_system_call: | 847 | cleanup_system_call: |
831 | mvc __LC_RETURN_PSW(8),0(%r12) | 848 | mvc __LC_RETURN_PSW(8),0(%r12) |
849 | c %r12,BASED(.Lmck_old_psw) | ||
850 | be BASED(0f) | ||
851 | la %r12,__LC_SAVE_AREA+16 | ||
852 | b BASED(1f) | ||
853 | 0: la %r12,__LC_SAVE_AREA+32 | ||
854 | 1: | ||
832 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 855 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
833 | clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+4) | 856 | clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+4) |
834 | bh BASED(0f) | 857 | bh BASED(0f) |
@@ -838,11 +861,13 @@ cleanup_system_call: | |||
838 | #endif | 861 | #endif |
839 | clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn) | 862 | clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn) |
840 | bh BASED(0f) | 863 | bh BASED(0f) |
841 | mvc __LC_SAVE_AREA(16),__LC_SAVE_AREA+16 | 864 | mvc __LC_SAVE_AREA(16),0(%r12) |
842 | 0: st %r13,__LC_SAVE_AREA+20 | 865 | 0: st %r13,4(%r12) |
866 | st %r12,__LC_SAVE_AREA+48 # argh | ||
843 | SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 | 867 | SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 |
844 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 868 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
845 | st %r15,__LC_SAVE_AREA+28 | 869 | l %r12,__LC_SAVE_AREA+48 # argh |
870 | st %r15,12(%r12) | ||
846 | lh %r7,0x8a | 871 | lh %r7,0x8a |
847 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 872 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
848 | cleanup_vtime: | 873 | cleanup_vtime: |
@@ -879,17 +904,21 @@ cleanup_sysc_return: | |||
879 | 904 | ||
880 | cleanup_sysc_leave: | 905 | cleanup_sysc_leave: |
881 | clc 4(4,%r12),BASED(cleanup_sysc_leave_insn) | 906 | clc 4(4,%r12),BASED(cleanup_sysc_leave_insn) |
882 | be BASED(0f) | 907 | be BASED(2f) |
883 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 908 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
884 | mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER | 909 | mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER |
885 | clc 4(4,%r12),BASED(cleanup_sysc_leave_insn+4) | 910 | clc 4(4,%r12),BASED(cleanup_sysc_leave_insn+4) |
886 | be BASED(0f) | 911 | be BASED(2f) |
887 | #endif | 912 | #endif |
888 | mvc __LC_RETURN_PSW(8),SP_PSW(%r15) | 913 | mvc __LC_RETURN_PSW(8),SP_PSW(%r15) |
889 | mvc __LC_SAVE_AREA+16(16),SP_R12(%r15) | 914 | c %r12,BASED(.Lmck_old_psw) |
890 | lm %r0,%r11,SP_R0(%r15) | 915 | bne BASED(0f) |
916 | mvc __LC_SAVE_AREA+32(16),SP_R12(%r15) | ||
917 | b BASED(1f) | ||
918 | 0: mvc __LC_SAVE_AREA+16(16),SP_R12(%r15) | ||
919 | 1: lm %r0,%r11,SP_R0(%r15) | ||
891 | l %r15,SP_R15(%r15) | 920 | l %r15,SP_R15(%r15) |
892 | 0: la %r12,__LC_RETURN_PSW | 921 | 2: la %r12,__LC_RETURN_PSW |
893 | br %r14 | 922 | br %r14 |
894 | cleanup_sysc_leave_insn: | 923 | cleanup_sysc_leave_insn: |
895 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 924 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
@@ -897,6 +926,36 @@ cleanup_sysc_leave_insn: | |||
897 | #endif | 926 | #endif |
898 | .long sysc_leave + 10 + 0x80000000 | 927 | .long sysc_leave + 10 + 0x80000000 |
899 | 928 | ||
929 | cleanup_io_return: | ||
930 | mvc __LC_RETURN_PSW(4),0(%r12) | ||
931 | mvc __LC_RETURN_PSW+4(4),BASED(cleanup_table_io_work_loop) | ||
932 | la %r12,__LC_RETURN_PSW | ||
933 | br %r14 | ||
934 | |||
935 | cleanup_io_leave: | ||
936 | clc 4(4,%r12),BASED(cleanup_io_leave_insn) | ||
937 | be BASED(2f) | ||
938 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
939 | mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER | ||
940 | clc 4(4,%r12),BASED(cleanup_io_leave_insn+4) | ||
941 | be BASED(2f) | ||
942 | #endif | ||
943 | mvc __LC_RETURN_PSW(8),SP_PSW(%r15) | ||
944 | c %r12,BASED(.Lmck_old_psw) | ||
945 | bne BASED(0f) | ||
946 | mvc __LC_SAVE_AREA+32(16),SP_R12(%r15) | ||
947 | b BASED(1f) | ||
948 | 0: mvc __LC_SAVE_AREA+16(16),SP_R12(%r15) | ||
949 | 1: lm %r0,%r11,SP_R0(%r15) | ||
950 | l %r15,SP_R15(%r15) | ||
951 | 2: la %r12,__LC_RETURN_PSW | ||
952 | br %r14 | ||
953 | cleanup_io_leave_insn: | ||
954 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
955 | .long io_leave + 18 + 0x80000000 | ||
956 | #endif | ||
957 | .long io_leave + 14 + 0x80000000 | ||
958 | |||
900 | /* | 959 | /* |
901 | * Integer constants | 960 | * Integer constants |
902 | */ | 961 | */ |
@@ -918,6 +977,7 @@ cleanup_sysc_leave_insn: | |||
918 | .Ls390_mcck: .long s390_do_machine_check | 977 | .Ls390_mcck: .long s390_do_machine_check |
919 | .Ls390_handle_mcck: | 978 | .Ls390_handle_mcck: |
920 | .long s390_handle_mcck | 979 | .long s390_handle_mcck |
980 | .Lmck_old_psw: .long __LC_MCK_OLD_PSW | ||
921 | .Ldo_IRQ: .long do_IRQ | 981 | .Ldo_IRQ: .long do_IRQ |
922 | .Ldo_extint: .long do_extint | 982 | .Ldo_extint: .long do_extint |
923 | .Ldo_signal: .long do_signal | 983 | .Ldo_signal: .long do_signal |
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index d9f22915008c..fb77b72ab262 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
@@ -131,14 +131,14 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_MCCK_PENDING) | |||
131 | stg %r12,__SF_BACKCHAIN(%r15) | 131 | stg %r12,__SF_BACKCHAIN(%r15) |
132 | .endm | 132 | .endm |
133 | 133 | ||
134 | .macro RESTORE_ALL sync | 134 | .macro RESTORE_ALL psworg,sync |
135 | mvc __LC_RETURN_PSW(16),SP_PSW(%r15) # move user PSW to lowcore | 135 | mvc \psworg(16),SP_PSW(%r15) # move user PSW to lowcore |
136 | .if !\sync | 136 | .if !\sync |
137 | ni __LC_RETURN_PSW+1,0xfd # clear wait state bit | 137 | ni \psworg+1,0xfd # clear wait state bit |
138 | .endif | 138 | .endif |
139 | lmg %r0,%r15,SP_R0(%r15) # load gprs 0-15 of user | 139 | lmg %r0,%r15,SP_R0(%r15) # load gprs 0-15 of user |
140 | STORE_TIMER __LC_EXIT_TIMER | 140 | STORE_TIMER __LC_EXIT_TIMER |
141 | lpswe __LC_RETURN_PSW # back to caller | 141 | lpswe \psworg # back to caller |
142 | .endm | 142 | .endm |
143 | 143 | ||
144 | /* | 144 | /* |
@@ -214,8 +214,8 @@ sysc_nr_ok: | |||
214 | sysc_do_restart: | 214 | sysc_do_restart: |
215 | larl %r10,sys_call_table | 215 | larl %r10,sys_call_table |
216 | #ifdef CONFIG_S390_SUPPORT | 216 | #ifdef CONFIG_S390_SUPPORT |
217 | tm SP_PSW+3(%r15),0x01 # are we running in 31 bit mode ? | 217 | tm __TI_flags+5(%r9),(_TIF_31BIT>>16) # running in 31 bit mode ? |
218 | jo sysc_noemu | 218 | jno sysc_noemu |
219 | larl %r10,sys_call_table_emu # use 31 bit emulation system calls | 219 | larl %r10,sys_call_table_emu # use 31 bit emulation system calls |
220 | sysc_noemu: | 220 | sysc_noemu: |
221 | #endif | 221 | #endif |
@@ -233,7 +233,7 @@ sysc_return: | |||
233 | tm __TI_flags+7(%r9),_TIF_WORK_SVC | 233 | tm __TI_flags+7(%r9),_TIF_WORK_SVC |
234 | jnz sysc_work # there is work to do (signals etc.) | 234 | jnz sysc_work # there is work to do (signals etc.) |
235 | sysc_leave: | 235 | sysc_leave: |
236 | RESTORE_ALL 1 | 236 | RESTORE_ALL __LC_RETURN_PSW,1 |
237 | 237 | ||
238 | # | 238 | # |
239 | # recheck if there is more work to do | 239 | # recheck if there is more work to do |
@@ -308,8 +308,6 @@ sysc_singlestep: | |||
308 | jg do_single_step # branch to do_sigtrap | 308 | jg do_single_step # branch to do_sigtrap |
309 | 309 | ||
310 | 310 | ||
311 | __critical_end: | ||
312 | |||
313 | # | 311 | # |
314 | # call syscall_trace before and after system call | 312 | # call syscall_trace before and after system call |
315 | # special linkage: %r12 contains the return address for trace_svc | 313 | # special linkage: %r12 contains the return address for trace_svc |
@@ -612,7 +610,8 @@ io_return: | |||
612 | tm __TI_flags+7(%r9),_TIF_WORK_INT | 610 | tm __TI_flags+7(%r9),_TIF_WORK_INT |
613 | jnz io_work # there is work to do (signals etc.) | 611 | jnz io_work # there is work to do (signals etc.) |
614 | io_leave: | 612 | io_leave: |
615 | RESTORE_ALL 0 | 613 | RESTORE_ALL __LC_RETURN_PSW,0 |
614 | io_done: | ||
616 | 615 | ||
617 | #ifdef CONFIG_PREEMPT | 616 | #ifdef CONFIG_PREEMPT |
618 | io_preempt: | 617 | io_preempt: |
@@ -711,6 +710,8 @@ ext_no_vtime: | |||
711 | brasl %r14,do_extint | 710 | brasl %r14,do_extint |
712 | j io_return | 711 | j io_return |
713 | 712 | ||
713 | __critical_end: | ||
714 | |||
714 | /* | 715 | /* |
715 | * Machine check handler routines | 716 | * Machine check handler routines |
716 | */ | 717 | */ |
@@ -718,6 +719,7 @@ ext_no_vtime: | |||
718 | mcck_int_handler: | 719 | mcck_int_handler: |
719 | la %r1,4095 # revalidate r1 | 720 | la %r1,4095 # revalidate r1 |
720 | spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer | 721 | spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer |
722 | mvc __LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA-4095(%r1) | ||
721 | lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs | 723 | lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs |
722 | SAVE_ALL_BASE __LC_SAVE_AREA+64 | 724 | SAVE_ALL_BASE __LC_SAVE_AREA+64 |
723 | la %r12,__LC_MCK_OLD_PSW | 725 | la %r12,__LC_MCK_OLD_PSW |
@@ -730,17 +732,8 @@ mcck_int_handler: | |||
730 | mvc __LC_ASYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER | 732 | mvc __LC_ASYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER |
731 | mvc __LC_SYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER | 733 | mvc __LC_SYNC_ENTER_TIMER(8),__LC_LAST_UPDATE_TIMER |
732 | mvc __LC_EXIT_TIMER(8),__LC_LAST_UPDATE_TIMER | 734 | mvc __LC_EXIT_TIMER(8),__LC_LAST_UPDATE_TIMER |
733 | 0: tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid? | ||
734 | jno mcck_no_vtime # no -> no timer update | ||
735 | tm __LC_MCK_OLD_PSW+1,0x01 # interrupting from user ? | ||
736 | jz mcck_no_vtime | ||
737 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER | ||
738 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | ||
739 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER | ||
740 | mcck_no_vtime: | ||
741 | #endif | 735 | #endif |
742 | 0: | 736 | 0: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? |
743 | tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? | ||
744 | jno mcck_int_main # no -> skip cleanup critical | 737 | jno mcck_int_main # no -> skip cleanup critical |
745 | tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit | 738 | tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit |
746 | jnz mcck_int_main # from user -> load kernel stack | 739 | jnz mcck_int_main # from user -> load kernel stack |
@@ -756,6 +749,16 @@ mcck_int_main: | |||
756 | jz 0f | 749 | jz 0f |
757 | lg %r15,__LC_PANIC_STACK # load panic stack | 750 | lg %r15,__LC_PANIC_STACK # load panic stack |
758 | 0: CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64 | 751 | 0: CREATE_STACK_FRAME __LC_MCK_OLD_PSW,__LC_SAVE_AREA+64 |
752 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
753 | tm __LC_MCCK_CODE+2,0x08 # mwp of old psw valid? | ||
754 | jno mcck_no_vtime # no -> no timer update | ||
755 | tm __LC_MCK_OLD_PSW+1,0x01 # interrupting from user ? | ||
756 | jz mcck_no_vtime | ||
757 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER | ||
758 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | ||
759 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER | ||
760 | mcck_no_vtime: | ||
761 | #endif | ||
759 | lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct | 762 | lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct |
760 | la %r2,SP_PTREGS(%r15) # load pt_regs | 763 | la %r2,SP_PTREGS(%r15) # load pt_regs |
761 | brasl %r14,s390_do_machine_check | 764 | brasl %r14,s390_do_machine_check |
@@ -771,7 +774,7 @@ mcck_int_main: | |||
771 | jno mcck_return | 774 | jno mcck_return |
772 | brasl %r14,s390_handle_mcck | 775 | brasl %r14,s390_handle_mcck |
773 | mcck_return: | 776 | mcck_return: |
774 | RESTORE_ALL 0 | 777 | RESTORE_ALL __LC_RETURN_MCCK_PSW,0 |
775 | 778 | ||
776 | #ifdef CONFIG_SMP | 779 | #ifdef CONFIG_SMP |
777 | /* | 780 | /* |
@@ -833,6 +836,10 @@ cleanup_table_sysc_leave: | |||
833 | .quad sysc_leave, sysc_work_loop | 836 | .quad sysc_leave, sysc_work_loop |
834 | cleanup_table_sysc_work_loop: | 837 | cleanup_table_sysc_work_loop: |
835 | .quad sysc_work_loop, sysc_reschedule | 838 | .quad sysc_work_loop, sysc_reschedule |
839 | cleanup_table_io_leave: | ||
840 | .quad io_leave, io_done | ||
841 | cleanup_table_io_work_loop: | ||
842 | .quad io_work_loop, io_mcck_pending | ||
836 | 843 | ||
837 | cleanup_critical: | 844 | cleanup_critical: |
838 | clc 8(8,%r12),BASED(cleanup_table_system_call) | 845 | clc 8(8,%r12),BASED(cleanup_table_system_call) |
@@ -855,10 +862,26 @@ cleanup_critical: | |||
855 | clc 8(8,%r12),BASED(cleanup_table_sysc_work_loop+8) | 862 | clc 8(8,%r12),BASED(cleanup_table_sysc_work_loop+8) |
856 | jl cleanup_sysc_return | 863 | jl cleanup_sysc_return |
857 | 0: | 864 | 0: |
865 | clc 8(8,%r12),BASED(cleanup_table_io_leave) | ||
866 | jl 0f | ||
867 | clc 8(8,%r12),BASED(cleanup_table_io_leave+8) | ||
868 | jl cleanup_io_leave | ||
869 | 0: | ||
870 | clc 8(8,%r12),BASED(cleanup_table_io_work_loop) | ||
871 | jl 0f | ||
872 | clc 8(8,%r12),BASED(cleanup_table_io_work_loop+8) | ||
873 | jl cleanup_io_return | ||
874 | 0: | ||
858 | br %r14 | 875 | br %r14 |
859 | 876 | ||
860 | cleanup_system_call: | 877 | cleanup_system_call: |
861 | mvc __LC_RETURN_PSW(16),0(%r12) | 878 | mvc __LC_RETURN_PSW(16),0(%r12) |
879 | cghi %r12,__LC_MCK_OLD_PSW | ||
880 | je 0f | ||
881 | la %r12,__LC_SAVE_AREA+32 | ||
882 | j 1f | ||
883 | 0: la %r12,__LC_SAVE_AREA+64 | ||
884 | 1: | ||
862 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 885 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
863 | clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+8) | 886 | clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+8) |
864 | jh 0f | 887 | jh 0f |
@@ -868,11 +891,13 @@ cleanup_system_call: | |||
868 | #endif | 891 | #endif |
869 | clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn) | 892 | clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn) |
870 | jh 0f | 893 | jh 0f |
871 | mvc __LC_SAVE_AREA(32),__LC_SAVE_AREA+32 | 894 | mvc __LC_SAVE_AREA(32),0(%r12) |
872 | 0: stg %r13,__LC_SAVE_AREA+40 | 895 | 0: stg %r13,8(%r12) |
896 | stg %r12,__LC_SAVE_AREA+96 # argh | ||
873 | SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 | 897 | SAVE_ALL __LC_SVC_OLD_PSW,__LC_SAVE_AREA,1 |
874 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA | 898 | CREATE_STACK_FRAME __LC_SVC_OLD_PSW,__LC_SAVE_AREA |
875 | stg %r15,__LC_SAVE_AREA+56 | 899 | lg %r12,__LC_SAVE_AREA+96 # argh |
900 | stg %r15,24(%r12) | ||
876 | llgh %r7,__LC_SVC_INT_CODE | 901 | llgh %r7,__LC_SVC_INT_CODE |
877 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 902 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
878 | cleanup_vtime: | 903 | cleanup_vtime: |
@@ -909,17 +934,21 @@ cleanup_sysc_return: | |||
909 | 934 | ||
910 | cleanup_sysc_leave: | 935 | cleanup_sysc_leave: |
911 | clc 8(8,%r12),BASED(cleanup_sysc_leave_insn) | 936 | clc 8(8,%r12),BASED(cleanup_sysc_leave_insn) |
912 | je 0f | 937 | je 2f |
913 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 938 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
914 | mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER | 939 | mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER |
915 | clc 8(8,%r12),BASED(cleanup_sysc_leave_insn+8) | 940 | clc 8(8,%r12),BASED(cleanup_sysc_leave_insn+8) |
916 | je 0f | 941 | je 2f |
917 | #endif | 942 | #endif |
918 | mvc __LC_RETURN_PSW(16),SP_PSW(%r15) | 943 | mvc __LC_RETURN_PSW(16),SP_PSW(%r15) |
919 | mvc __LC_SAVE_AREA+32(32),SP_R12(%r15) | 944 | cghi %r12,__LC_MCK_OLD_PSW |
920 | lmg %r0,%r11,SP_R0(%r15) | 945 | jne 0f |
946 | mvc __LC_SAVE_AREA+64(32),SP_R12(%r15) | ||
947 | j 1f | ||
948 | 0: mvc __LC_SAVE_AREA+32(32),SP_R12(%r15) | ||
949 | 1: lmg %r0,%r11,SP_R0(%r15) | ||
921 | lg %r15,SP_R15(%r15) | 950 | lg %r15,SP_R15(%r15) |
922 | 0: la %r12,__LC_RETURN_PSW | 951 | 2: la %r12,__LC_RETURN_PSW |
923 | br %r14 | 952 | br %r14 |
924 | cleanup_sysc_leave_insn: | 953 | cleanup_sysc_leave_insn: |
925 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | 954 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING |
@@ -927,6 +956,36 @@ cleanup_sysc_leave_insn: | |||
927 | #endif | 956 | #endif |
928 | .quad sysc_leave + 12 | 957 | .quad sysc_leave + 12 |
929 | 958 | ||
959 | cleanup_io_return: | ||
960 | mvc __LC_RETURN_PSW(8),0(%r12) | ||
961 | mvc __LC_RETURN_PSW+8(8),BASED(cleanup_table_io_work_loop) | ||
962 | la %r12,__LC_RETURN_PSW | ||
963 | br %r14 | ||
964 | |||
965 | cleanup_io_leave: | ||
966 | clc 8(8,%r12),BASED(cleanup_io_leave_insn) | ||
967 | je 2f | ||
968 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
969 | mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER | ||
970 | clc 8(8,%r12),BASED(cleanup_io_leave_insn+8) | ||
971 | je 2f | ||
972 | #endif | ||
973 | mvc __LC_RETURN_PSW(16),SP_PSW(%r15) | ||
974 | cghi %r12,__LC_MCK_OLD_PSW | ||
975 | jne 0f | ||
976 | mvc __LC_SAVE_AREA+64(32),SP_R12(%r15) | ||
977 | j 1f | ||
978 | 0: mvc __LC_SAVE_AREA+32(32),SP_R12(%r15) | ||
979 | 1: lmg %r0,%r11,SP_R0(%r15) | ||
980 | lg %r15,SP_R15(%r15) | ||
981 | 2: la %r12,__LC_RETURN_PSW | ||
982 | br %r14 | ||
983 | cleanup_io_leave_insn: | ||
984 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
985 | .quad io_leave + 20 | ||
986 | #endif | ||
987 | .quad io_leave + 16 | ||
988 | |||
930 | /* | 989 | /* |
931 | * Integer constants | 990 | * Integer constants |
932 | */ | 991 | */ |
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 8ca485676780..2fd75da15495 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c | |||
@@ -139,10 +139,7 @@ int do_settimeofday(struct timespec *tv) | |||
139 | set_normalized_timespec(&xtime, sec, nsec); | 139 | set_normalized_timespec(&xtime, sec, nsec); |
140 | set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); | 140 | set_normalized_timespec(&wall_to_monotonic, wtm_sec, wtm_nsec); |
141 | 141 | ||
142 | time_adjust = 0; /* stop active adjtime() */ | 142 | ntp_clear(); |
143 | time_status |= STA_UNSYNC; | ||
144 | time_maxerror = NTP_PHASE_LIMIT; | ||
145 | time_esterror = NTP_PHASE_LIMIT; | ||
146 | write_sequnlock_irq(&xtime_lock); | 143 | write_sequnlock_irq(&xtime_lock); |
147 | clock_was_set(); | 144 | clock_was_set(); |
148 | return 0; | 145 | return 0; |
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 75fde949d125..856a971759b1 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c | |||
@@ -563,12 +563,14 @@ pfault_interrupt(struct pt_regs *regs, __u16 error_code) | |||
563 | * interrupt. pfault_wait is valid. Set pfault_wait | 563 | * interrupt. pfault_wait is valid. Set pfault_wait |
564 | * back to zero and wake up the process. This can | 564 | * back to zero and wake up the process. This can |
565 | * safely be done because the task is still sleeping | 565 | * safely be done because the task is still sleeping |
566 | * and can't procude new pfaults. */ | 566 | * and can't produce new pfaults. */ |
567 | tsk->thread.pfault_wait = 0; | 567 | tsk->thread.pfault_wait = 0; |
568 | wake_up_process(tsk); | 568 | wake_up_process(tsk); |
569 | put_task_struct(tsk); | ||
569 | } | 570 | } |
570 | } else { | 571 | } else { |
571 | /* signal bit not set -> a real page is missing. */ | 572 | /* signal bit not set -> a real page is missing. */ |
573 | get_task_struct(tsk); | ||
572 | set_task_state(tsk, TASK_UNINTERRUPTIBLE); | 574 | set_task_state(tsk, TASK_UNINTERRUPTIBLE); |
573 | if (xchg(&tsk->thread.pfault_wait, 1) != 0) { | 575 | if (xchg(&tsk->thread.pfault_wait, 1) != 0) { |
574 | /* Completion interrupt was faster than the initial | 576 | /* Completion interrupt was faster than the initial |
@@ -578,6 +580,7 @@ pfault_interrupt(struct pt_regs *regs, __u16 error_code) | |||
578 | * mode and can't produce new pfaults. */ | 580 | * mode and can't produce new pfaults. */ |
579 | tsk->thread.pfault_wait = 0; | 581 | tsk->thread.pfault_wait = 0; |
580 | set_task_state(tsk, TASK_RUNNING); | 582 | set_task_state(tsk, TASK_RUNNING); |
583 | put_task_struct(tsk); | ||
581 | } else | 584 | } else |
582 | set_tsk_need_resched(tsk); | 585 | set_tsk_need_resched(tsk); |
583 | } | 586 | } |