diff options
Diffstat (limited to 'arch/s390')
-rw-r--r-- | arch/s390/include/asm/cputime.h | 9 | ||||
-rw-r--r-- | arch/s390/include/asm/lowcore.h | 98 | ||||
-rw-r--r-- | arch/s390/kernel/asm-offsets.c | 2 | ||||
-rw-r--r-- | arch/s390/kernel/entry.S | 54 | ||||
-rw-r--r-- | arch/s390/kernel/entry64.S | 54 | ||||
-rw-r--r-- | arch/s390/kernel/nmi.c | 3 | ||||
-rw-r--r-- | arch/s390/kernel/s390_ext.c | 3 | ||||
-rw-r--r-- | arch/s390/kernel/vtime.c | 15 |
8 files changed, 123 insertions, 115 deletions
diff --git a/arch/s390/include/asm/cputime.h b/arch/s390/include/asm/cputime.h index 258ba88b7b50..8b1a52a137c5 100644 --- a/arch/s390/include/asm/cputime.h +++ b/arch/s390/include/asm/cputime.h | |||
@@ -188,15 +188,16 @@ struct s390_idle_data { | |||
188 | 188 | ||
189 | DECLARE_PER_CPU(struct s390_idle_data, s390_idle); | 189 | DECLARE_PER_CPU(struct s390_idle_data, s390_idle); |
190 | 190 | ||
191 | void vtime_start_cpu(void); | 191 | void vtime_start_cpu(__u64 int_clock, __u64 enter_timer); |
192 | cputime64_t s390_get_idle_time(int cpu); | 192 | cputime64_t s390_get_idle_time(int cpu); |
193 | 193 | ||
194 | #define arch_idle_time(cpu) s390_get_idle_time(cpu) | 194 | #define arch_idle_time(cpu) s390_get_idle_time(cpu) |
195 | 195 | ||
196 | static inline void s390_idle_check(void) | 196 | static inline void s390_idle_check(struct pt_regs *regs, __u64 int_clock, |
197 | __u64 enter_timer) | ||
197 | { | 198 | { |
198 | if ((&__get_cpu_var(s390_idle))->idle_enter != 0ULL) | 199 | if (regs->psw.mask & PSW_MASK_WAIT) |
199 | vtime_start_cpu(); | 200 | vtime_start_cpu(int_clock, enter_timer); |
200 | } | 201 | } |
201 | 202 | ||
202 | static inline int s390_nohz_delay(int cpu) | 203 | static inline int s390_nohz_delay(int cpu) |
diff --git a/arch/s390/include/asm/lowcore.h b/arch/s390/include/asm/lowcore.h index f7e78c79b8b1..2c02d46c3588 100644 --- a/arch/s390/include/asm/lowcore.h +++ b/arch/s390/include/asm/lowcore.h | |||
@@ -104,37 +104,39 @@ struct _lowcore { | |||
104 | /* CPU time accounting values */ | 104 | /* CPU time accounting values */ |
105 | __u64 sync_enter_timer; /* 0x0250 */ | 105 | __u64 sync_enter_timer; /* 0x0250 */ |
106 | __u64 async_enter_timer; /* 0x0258 */ | 106 | __u64 async_enter_timer; /* 0x0258 */ |
107 | __u64 exit_timer; /* 0x0260 */ | 107 | __u64 mcck_enter_timer; /* 0x0260 */ |
108 | __u64 user_timer; /* 0x0268 */ | 108 | __u64 exit_timer; /* 0x0268 */ |
109 | __u64 system_timer; /* 0x0270 */ | 109 | __u64 user_timer; /* 0x0270 */ |
110 | __u64 steal_timer; /* 0x0278 */ | 110 | __u64 system_timer; /* 0x0278 */ |
111 | __u64 last_update_timer; /* 0x0280 */ | 111 | __u64 steal_timer; /* 0x0280 */ |
112 | __u64 last_update_clock; /* 0x0288 */ | 112 | __u64 last_update_timer; /* 0x0288 */ |
113 | __u64 last_update_clock; /* 0x0290 */ | ||
113 | 114 | ||
114 | /* Current process. */ | 115 | /* Current process. */ |
115 | __u32 current_task; /* 0x0290 */ | 116 | __u32 current_task; /* 0x0298 */ |
116 | __u32 thread_info; /* 0x0294 */ | 117 | __u32 thread_info; /* 0x029c */ |
117 | __u32 kernel_stack; /* 0x0298 */ | 118 | __u32 kernel_stack; /* 0x02a0 */ |
118 | 119 | ||
119 | /* Interrupt and panic stack. */ | 120 | /* Interrupt and panic stack. */ |
120 | __u32 async_stack; /* 0x029c */ | 121 | __u32 async_stack; /* 0x02a4 */ |
121 | __u32 panic_stack; /* 0x02a0 */ | 122 | __u32 panic_stack; /* 0x02a8 */ |
122 | 123 | ||
123 | /* Address space pointer. */ | 124 | /* Address space pointer. */ |
124 | __u32 kernel_asce; /* 0x02a4 */ | 125 | __u32 kernel_asce; /* 0x02ac */ |
125 | __u32 user_asce; /* 0x02a8 */ | 126 | __u32 user_asce; /* 0x02b0 */ |
126 | __u32 user_exec_asce; /* 0x02ac */ | 127 | __u32 user_exec_asce; /* 0x02b4 */ |
127 | 128 | ||
128 | /* SMP info area */ | 129 | /* SMP info area */ |
129 | __u32 cpu_nr; /* 0x02b0 */ | 130 | __u32 cpu_nr; /* 0x02b8 */ |
130 | __u32 softirq_pending; /* 0x02b4 */ | 131 | __u32 softirq_pending; /* 0x02bc */ |
131 | __u32 percpu_offset; /* 0x02b8 */ | 132 | __u32 percpu_offset; /* 0x02c0 */ |
132 | __u32 ext_call_fast; /* 0x02bc */ | 133 | __u32 ext_call_fast; /* 0x02c4 */ |
133 | __u64 int_clock; /* 0x02c0 */ | 134 | __u64 int_clock; /* 0x02c8 */ |
134 | __u64 clock_comparator; /* 0x02c8 */ | 135 | __u64 mcck_clock; /* 0x02d0 */ |
135 | __u32 machine_flags; /* 0x02d0 */ | 136 | __u64 clock_comparator; /* 0x02d8 */ |
136 | __u32 ftrace_func; /* 0x02d4 */ | 137 | __u32 machine_flags; /* 0x02e0 */ |
137 | __u8 pad_0x02d8[0x0300-0x02d8]; /* 0x02d8 */ | 138 | __u32 ftrace_func; /* 0x02e4 */ |
139 | __u8 pad_0x02e8[0x0300-0x02e8]; /* 0x02e8 */ | ||
138 | 140 | ||
139 | /* Interrupt response block */ | 141 | /* Interrupt response block */ |
140 | __u8 irb[64]; /* 0x0300 */ | 142 | __u8 irb[64]; /* 0x0300 */ |
@@ -232,38 +234,40 @@ struct _lowcore { | |||
232 | /* CPU accounting and timing values. */ | 234 | /* CPU accounting and timing values. */ |
233 | __u64 sync_enter_timer; /* 0x02a0 */ | 235 | __u64 sync_enter_timer; /* 0x02a0 */ |
234 | __u64 async_enter_timer; /* 0x02a8 */ | 236 | __u64 async_enter_timer; /* 0x02a8 */ |
235 | __u64 exit_timer; /* 0x02b0 */ | 237 | __u64 mcck_enter_timer; /* 0x02b0 */ |
236 | __u64 user_timer; /* 0x02b8 */ | 238 | __u64 exit_timer; /* 0x02b8 */ |
237 | __u64 system_timer; /* 0x02c0 */ | 239 | __u64 user_timer; /* 0x02c0 */ |
238 | __u64 steal_timer; /* 0x02c8 */ | 240 | __u64 system_timer; /* 0x02c8 */ |
239 | __u64 last_update_timer; /* 0x02d0 */ | 241 | __u64 steal_timer; /* 0x02d0 */ |
240 | __u64 last_update_clock; /* 0x02d8 */ | 242 | __u64 last_update_timer; /* 0x02d8 */ |
243 | __u64 last_update_clock; /* 0x02e0 */ | ||
241 | 244 | ||
242 | /* Current process. */ | 245 | /* Current process. */ |
243 | __u64 current_task; /* 0x02e0 */ | 246 | __u64 current_task; /* 0x02e8 */ |
244 | __u64 thread_info; /* 0x02e8 */ | 247 | __u64 thread_info; /* 0x02f0 */ |
245 | __u64 kernel_stack; /* 0x02f0 */ | 248 | __u64 kernel_stack; /* 0x02f8 */ |
246 | 249 | ||
247 | /* Interrupt and panic stack. */ | 250 | /* Interrupt and panic stack. */ |
248 | __u64 async_stack; /* 0x02f8 */ | 251 | __u64 async_stack; /* 0x0300 */ |
249 | __u64 panic_stack; /* 0x0300 */ | 252 | __u64 panic_stack; /* 0x0308 */ |
250 | 253 | ||
251 | /* Address space pointer. */ | 254 | /* Address space pointer. */ |
252 | __u64 kernel_asce; /* 0x0308 */ | 255 | __u64 kernel_asce; /* 0x0310 */ |
253 | __u64 user_asce; /* 0x0310 */ | 256 | __u64 user_asce; /* 0x0318 */ |
254 | __u64 user_exec_asce; /* 0x0318 */ | 257 | __u64 user_exec_asce; /* 0x0320 */ |
255 | 258 | ||
256 | /* SMP info area */ | 259 | /* SMP info area */ |
257 | __u32 cpu_nr; /* 0x0320 */ | 260 | __u32 cpu_nr; /* 0x0328 */ |
258 | __u32 softirq_pending; /* 0x0324 */ | 261 | __u32 softirq_pending; /* 0x032c */ |
259 | __u64 percpu_offset; /* 0x0328 */ | 262 | __u64 percpu_offset; /* 0x0330 */ |
260 | __u64 ext_call_fast; /* 0x0330 */ | 263 | __u64 ext_call_fast; /* 0x0338 */ |
261 | __u64 int_clock; /* 0x0338 */ | 264 | __u64 int_clock; /* 0x0340 */ |
262 | __u64 clock_comparator; /* 0x0340 */ | 265 | __u64 mcck_clock; /* 0x0348 */ |
263 | __u64 vdso_per_cpu_data; /* 0x0348 */ | 266 | __u64 clock_comparator; /* 0x0350 */ |
264 | __u64 machine_flags; /* 0x0350 */ | 267 | __u64 vdso_per_cpu_data; /* 0x0358 */ |
265 | __u64 ftrace_func; /* 0x0358 */ | 268 | __u64 machine_flags; /* 0x0360 */ |
266 | __u8 pad_0x0368[0x0380-0x0360]; /* 0x0360 */ | 269 | __u64 ftrace_func; /* 0x0368 */ |
270 | __u8 pad_0x0370[0x0380-0x0370]; /* 0x0370 */ | ||
267 | 271 | ||
268 | /* Interrupt response block. */ | 272 | /* Interrupt response block. */ |
269 | __u8 irb[64]; /* 0x0380 */ | 273 | __u8 irb[64]; /* 0x0380 */ |
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index 32b1ede69858..816d81f479c0 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c | |||
@@ -112,6 +112,7 @@ int main(void) | |||
112 | DEFINE(__LC_RETURN_MCCK_PSW, offsetof(struct _lowcore, return_mcck_psw)); | 112 | DEFINE(__LC_RETURN_MCCK_PSW, offsetof(struct _lowcore, return_mcck_psw)); |
113 | DEFINE(__LC_SYNC_ENTER_TIMER, offsetof(struct _lowcore, sync_enter_timer)); | 113 | DEFINE(__LC_SYNC_ENTER_TIMER, offsetof(struct _lowcore, sync_enter_timer)); |
114 | DEFINE(__LC_ASYNC_ENTER_TIMER, offsetof(struct _lowcore, async_enter_timer)); | 114 | DEFINE(__LC_ASYNC_ENTER_TIMER, offsetof(struct _lowcore, async_enter_timer)); |
115 | DEFINE(__LC_MCCK_ENTER_TIMER, offsetof(struct _lowcore, mcck_enter_timer)); | ||
115 | DEFINE(__LC_EXIT_TIMER, offsetof(struct _lowcore, exit_timer)); | 116 | DEFINE(__LC_EXIT_TIMER, offsetof(struct _lowcore, exit_timer)); |
116 | DEFINE(__LC_USER_TIMER, offsetof(struct _lowcore, user_timer)); | 117 | DEFINE(__LC_USER_TIMER, offsetof(struct _lowcore, user_timer)); |
117 | DEFINE(__LC_SYSTEM_TIMER, offsetof(struct _lowcore, system_timer)); | 118 | DEFINE(__LC_SYSTEM_TIMER, offsetof(struct _lowcore, system_timer)); |
@@ -127,6 +128,7 @@ int main(void) | |||
127 | DEFINE(__LC_USER_ASCE, offsetof(struct _lowcore, user_asce)); | 128 | DEFINE(__LC_USER_ASCE, offsetof(struct _lowcore, user_asce)); |
128 | DEFINE(__LC_USER_EXEC_ASCE, offsetof(struct _lowcore, user_exec_asce)); | 129 | DEFINE(__LC_USER_EXEC_ASCE, offsetof(struct _lowcore, user_exec_asce)); |
129 | DEFINE(__LC_INT_CLOCK, offsetof(struct _lowcore, int_clock)); | 130 | DEFINE(__LC_INT_CLOCK, offsetof(struct _lowcore, int_clock)); |
131 | DEFINE(__LC_MCCK_CLOCK, offsetof(struct _lowcore, mcck_clock)); | ||
130 | DEFINE(__LC_MACHINE_FLAGS, offsetof(struct _lowcore, machine_flags)); | 132 | DEFINE(__LC_MACHINE_FLAGS, offsetof(struct _lowcore, machine_flags)); |
131 | DEFINE(__LC_FTRACE_FUNC, offsetof(struct _lowcore, ftrace_func)); | 133 | DEFINE(__LC_FTRACE_FUNC, offsetof(struct _lowcore, ftrace_func)); |
132 | DEFINE(__LC_IRB, offsetof(struct _lowcore, irb)); | 134 | DEFINE(__LC_IRB, offsetof(struct _lowcore, irb)); |
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 07d849995dac..0e2b16241dfa 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S | |||
@@ -742,15 +742,14 @@ __critical_end: | |||
742 | 742 | ||
743 | .globl mcck_int_handler | 743 | .globl mcck_int_handler |
744 | mcck_int_handler: | 744 | mcck_int_handler: |
745 | stck __LC_INT_CLOCK | 745 | stck __LC_MCCK_CLOCK |
746 | spt __LC_CPU_TIMER_SAVE_AREA # revalidate cpu timer | 746 | spt __LC_CPU_TIMER_SAVE_AREA # revalidate cpu timer |
747 | lm %r0,%r15,__LC_GPREGS_SAVE_AREA # revalidate gprs | 747 | lm %r0,%r15,__LC_GPREGS_SAVE_AREA # revalidate gprs |
748 | SAVE_ALL_BASE __LC_SAVE_AREA+32 | 748 | SAVE_ALL_BASE __LC_SAVE_AREA+32 |
749 | la %r12,__LC_MCK_OLD_PSW | 749 | la %r12,__LC_MCK_OLD_PSW |
750 | tm __LC_MCCK_CODE,0x80 # system damage? | 750 | tm __LC_MCCK_CODE,0x80 # system damage? |
751 | bo BASED(mcck_int_main) # yes -> rest of mcck code invalid | 751 | bo BASED(mcck_int_main) # yes -> rest of mcck code invalid |
752 | mvc __LC_SAVE_AREA+52(8),__LC_ASYNC_ENTER_TIMER | 752 | mvc __LC_MCCK_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA |
753 | mvc __LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA | ||
754 | tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid? | 753 | tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid? |
755 | bo BASED(1f) | 754 | bo BASED(1f) |
756 | la %r14,__LC_SYNC_ENTER_TIMER | 755 | la %r14,__LC_SYNC_ENTER_TIMER |
@@ -764,7 +763,7 @@ mcck_int_handler: | |||
764 | bl BASED(0f) | 763 | bl BASED(0f) |
765 | la %r14,__LC_LAST_UPDATE_TIMER | 764 | la %r14,__LC_LAST_UPDATE_TIMER |
766 | 0: spt 0(%r14) | 765 | 0: spt 0(%r14) |
767 | mvc __LC_ASYNC_ENTER_TIMER(8),0(%r14) | 766 | mvc __LC_MCCK_ENTER_TIMER(8),0(%r14) |
768 | 1: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? | 767 | 1: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? |
769 | bno BASED(mcck_int_main) # no -> skip cleanup critical | 768 | bno BASED(mcck_int_main) # no -> skip cleanup critical |
770 | tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit | 769 | tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit |
@@ -786,9 +785,9 @@ mcck_int_main: | |||
786 | bno BASED(mcck_no_vtime) # no -> skip cleanup critical | 785 | bno BASED(mcck_no_vtime) # no -> skip cleanup critical |
787 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 786 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
788 | bz BASED(mcck_no_vtime) | 787 | bz BASED(mcck_no_vtime) |
789 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER | 788 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_MCCK_ENTER_TIMER,__LC_USER_TIMER |
790 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | 789 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER |
791 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER | 790 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_MCCK_ENTER_TIMER |
792 | mcck_no_vtime: | 791 | mcck_no_vtime: |
793 | l %r9,__LC_THREAD_INFO # load pointer to thread_info struct | 792 | l %r9,__LC_THREAD_INFO # load pointer to thread_info struct |
794 | la %r2,SP_PTREGS(%r15) # load pt_regs | 793 | la %r2,SP_PTREGS(%r15) # load pt_regs |
@@ -811,7 +810,6 @@ mcck_no_vtime: | |||
811 | mcck_return: | 810 | mcck_return: |
812 | mvc __LC_RETURN_MCCK_PSW(8),SP_PSW(%r15) # move return PSW | 811 | mvc __LC_RETURN_MCCK_PSW(8),SP_PSW(%r15) # move return PSW |
813 | ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit | 812 | ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit |
814 | mvc __LC_ASYNC_ENTER_TIMER(8),__LC_SAVE_AREA+52 | ||
815 | tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ? | 813 | tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ? |
816 | bno BASED(0f) | 814 | bno BASED(0f) |
817 | lm %r0,%r15,SP_R0(%r15) # load gprs 0-15 | 815 | lm %r0,%r15,SP_R0(%r15) # load gprs 0-15 |
@@ -934,15 +932,16 @@ cleanup_critical: | |||
934 | 932 | ||
935 | cleanup_system_call: | 933 | cleanup_system_call: |
936 | mvc __LC_RETURN_PSW(8),0(%r12) | 934 | mvc __LC_RETURN_PSW(8),0(%r12) |
937 | c %r12,BASED(.Lmck_old_psw) | ||
938 | be BASED(0f) | ||
939 | la %r12,__LC_SAVE_AREA+16 | ||
940 | b BASED(1f) | ||
941 | 0: la %r12,__LC_SAVE_AREA+32 | ||
942 | 1: | ||
943 | clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+4) | 935 | clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+4) |
944 | bh BASED(0f) | 936 | bh BASED(0f) |
937 | mvc __LC_SYNC_ENTER_TIMER(8),__LC_MCCK_ENTER_TIMER | ||
938 | c %r12,BASED(.Lmck_old_psw) | ||
939 | be BASED(0f) | ||
945 | mvc __LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER | 940 | mvc __LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER |
941 | 0: c %r12,BASED(.Lmck_old_psw) | ||
942 | la %r12,__LC_SAVE_AREA+32 | ||
943 | be BASED(0f) | ||
944 | la %r12,__LC_SAVE_AREA+16 | ||
946 | 0: clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+8) | 945 | 0: clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+8) |
947 | bhe BASED(cleanup_vtime) | 946 | bhe BASED(cleanup_vtime) |
948 | clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn) | 947 | clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn) |
@@ -984,16 +983,19 @@ cleanup_sysc_tif: | |||
984 | cleanup_sysc_restore: | 983 | cleanup_sysc_restore: |
985 | clc 4(4,%r12),BASED(cleanup_sysc_restore_insn) | 984 | clc 4(4,%r12),BASED(cleanup_sysc_restore_insn) |
986 | be BASED(2f) | 985 | be BASED(2f) |
986 | mvc __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER | ||
987 | c %r12,BASED(.Lmck_old_psw) | ||
988 | be BASED(0f) | ||
987 | mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER | 989 | mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER |
988 | clc 4(4,%r12),BASED(cleanup_sysc_restore_insn+4) | 990 | 0: clc 4(4,%r12),BASED(cleanup_sysc_restore_insn+4) |
989 | be BASED(2f) | 991 | be BASED(2f) |
990 | mvc __LC_RETURN_PSW(8),SP_PSW(%r15) | 992 | mvc __LC_RETURN_PSW(8),SP_PSW(%r15) |
991 | c %r12,BASED(.Lmck_old_psw) | 993 | c %r12,BASED(.Lmck_old_psw) |
992 | bne BASED(0f) | 994 | la %r12,__LC_SAVE_AREA+32 |
993 | mvc __LC_SAVE_AREA+32(16),SP_R12(%r15) | 995 | be BASED(1f) |
994 | b BASED(1f) | 996 | la %r12,__LC_SAVE_AREA+16 |
995 | 0: mvc __LC_SAVE_AREA+16(16),SP_R12(%r15) | 997 | 1: mvc 0(16,%r12),SP_R12(%r15) |
996 | 1: lm %r0,%r11,SP_R0(%r15) | 998 | lm %r0,%r11,SP_R0(%r15) |
997 | l %r15,SP_R15(%r15) | 999 | l %r15,SP_R15(%r15) |
998 | 2: la %r12,__LC_RETURN_PSW | 1000 | 2: la %r12,__LC_RETURN_PSW |
999 | br %r14 | 1001 | br %r14 |
@@ -1009,19 +1011,15 @@ cleanup_io_tif: | |||
1009 | 1011 | ||
1010 | cleanup_io_restore: | 1012 | cleanup_io_restore: |
1011 | clc 4(4,%r12),BASED(cleanup_io_restore_insn) | 1013 | clc 4(4,%r12),BASED(cleanup_io_restore_insn) |
1012 | be BASED(2f) | 1014 | be BASED(1f) |
1013 | mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER | 1015 | mvc __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER |
1014 | clc 4(4,%r12),BASED(cleanup_io_restore_insn+4) | 1016 | clc 4(4,%r12),BASED(cleanup_io_restore_insn+4) |
1015 | be BASED(2f) | 1017 | be BASED(1f) |
1016 | mvc __LC_RETURN_PSW(8),SP_PSW(%r15) | 1018 | mvc __LC_RETURN_PSW(8),SP_PSW(%r15) |
1017 | c %r12,BASED(.Lmck_old_psw) | ||
1018 | bne BASED(0f) | ||
1019 | mvc __LC_SAVE_AREA+32(16),SP_R12(%r15) | 1019 | mvc __LC_SAVE_AREA+32(16),SP_R12(%r15) |
1020 | b BASED(1f) | 1020 | lm %r0,%r11,SP_R0(%r15) |
1021 | 0: mvc __LC_SAVE_AREA+16(16),SP_R12(%r15) | ||
1022 | 1: lm %r0,%r11,SP_R0(%r15) | ||
1023 | l %r15,SP_R15(%r15) | 1021 | l %r15,SP_R15(%r15) |
1024 | 2: la %r12,__LC_RETURN_PSW | 1022 | 1: la %r12,__LC_RETURN_PSW |
1025 | br %r14 | 1023 | br %r14 |
1026 | cleanup_io_restore_insn: | 1024 | cleanup_io_restore_insn: |
1027 | .long io_done - 4 + 0x80000000 | 1025 | .long io_done - 4 + 0x80000000 |
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 860cea1d1c8a..6536f5ca46f5 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
@@ -725,7 +725,7 @@ __critical_end: | |||
725 | */ | 725 | */ |
726 | .globl mcck_int_handler | 726 | .globl mcck_int_handler |
727 | mcck_int_handler: | 727 | mcck_int_handler: |
728 | stck __LC_INT_CLOCK | 728 | stck __LC_MCCK_CLOCK |
729 | la %r1,4095 # revalidate r1 | 729 | la %r1,4095 # revalidate r1 |
730 | spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer | 730 | spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer |
731 | lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs | 731 | lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs |
@@ -734,8 +734,7 @@ mcck_int_handler: | |||
734 | tm __LC_MCCK_CODE,0x80 # system damage? | 734 | tm __LC_MCCK_CODE,0x80 # system damage? |
735 | jo mcck_int_main # yes -> rest of mcck code invalid | 735 | jo mcck_int_main # yes -> rest of mcck code invalid |
736 | la %r14,4095 | 736 | la %r14,4095 |
737 | mvc __LC_SAVE_AREA+104(8),__LC_ASYNC_ENTER_TIMER | 737 | mvc __LC_MCCK_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA-4095(%r14) |
738 | mvc __LC_ASYNC_ENTER_TIMER(8),__LC_CPU_TIMER_SAVE_AREA-4095(%r14) | ||
739 | tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid? | 738 | tm __LC_MCCK_CODE+5,0x02 # stored cpu timer value valid? |
740 | jo 1f | 739 | jo 1f |
741 | la %r14,__LC_SYNC_ENTER_TIMER | 740 | la %r14,__LC_SYNC_ENTER_TIMER |
@@ -749,7 +748,7 @@ mcck_int_handler: | |||
749 | jl 0f | 748 | jl 0f |
750 | la %r14,__LC_LAST_UPDATE_TIMER | 749 | la %r14,__LC_LAST_UPDATE_TIMER |
751 | 0: spt 0(%r14) | 750 | 0: spt 0(%r14) |
752 | mvc __LC_ASYNC_ENTER_TIMER(8),0(%r14) | 751 | mvc __LC_MCCK_ENTER_TIMER(8),0(%r14) |
753 | 1: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? | 752 | 1: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? |
754 | jno mcck_int_main # no -> skip cleanup critical | 753 | jno mcck_int_main # no -> skip cleanup critical |
755 | tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit | 754 | tm __LC_MCK_OLD_PSW+1,0x01 # test problem state bit |
@@ -770,9 +769,9 @@ mcck_int_main: | |||
770 | jno mcck_no_vtime # no -> no timer update | 769 | jno mcck_no_vtime # no -> no timer update |
771 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? | 770 | tm SP_PSW+1(%r15),0x01 # interrupting from user ? |
772 | jz mcck_no_vtime | 771 | jz mcck_no_vtime |
773 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_ASYNC_ENTER_TIMER,__LC_USER_TIMER | 772 | UPDATE_VTIME __LC_EXIT_TIMER,__LC_MCCK_ENTER_TIMER,__LC_USER_TIMER |
774 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER | 773 | UPDATE_VTIME __LC_LAST_UPDATE_TIMER,__LC_EXIT_TIMER,__LC_SYSTEM_TIMER |
775 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_ASYNC_ENTER_TIMER | 774 | mvc __LC_LAST_UPDATE_TIMER(8),__LC_MCCK_ENTER_TIMER |
776 | mcck_no_vtime: | 775 | mcck_no_vtime: |
777 | lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct | 776 | lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct |
778 | la %r2,SP_PTREGS(%r15) # load pt_regs | 777 | la %r2,SP_PTREGS(%r15) # load pt_regs |
@@ -794,7 +793,6 @@ mcck_return: | |||
794 | mvc __LC_RETURN_MCCK_PSW(16),SP_PSW(%r15) # move return PSW | 793 | mvc __LC_RETURN_MCCK_PSW(16),SP_PSW(%r15) # move return PSW |
795 | ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit | 794 | ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit |
796 | lmg %r0,%r15,SP_R0(%r15) # load gprs 0-15 | 795 | lmg %r0,%r15,SP_R0(%r15) # load gprs 0-15 |
797 | mvc __LC_ASYNC_ENTER_TIMER(8),__LC_SAVE_AREA+104 | ||
798 | tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ? | 796 | tm __LC_RETURN_MCCK_PSW+1,0x01 # returning to user ? |
799 | jno 0f | 797 | jno 0f |
800 | stpt __LC_EXIT_TIMER | 798 | stpt __LC_EXIT_TIMER |
@@ -909,15 +907,16 @@ cleanup_critical: | |||
909 | 907 | ||
910 | cleanup_system_call: | 908 | cleanup_system_call: |
911 | mvc __LC_RETURN_PSW(16),0(%r12) | 909 | mvc __LC_RETURN_PSW(16),0(%r12) |
912 | cghi %r12,__LC_MCK_OLD_PSW | ||
913 | je 0f | ||
914 | la %r12,__LC_SAVE_AREA+32 | ||
915 | j 1f | ||
916 | 0: la %r12,__LC_SAVE_AREA+64 | ||
917 | 1: | ||
918 | clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+8) | 910 | clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+8) |
919 | jh 0f | 911 | jh 0f |
912 | mvc __LC_SYNC_ENTER_TIMER(8),__LC_MCCK_ENTER_TIMER | ||
913 | cghi %r12,__LC_MCK_OLD_PSW | ||
914 | je 0f | ||
920 | mvc __LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER | 915 | mvc __LC_SYNC_ENTER_TIMER(8),__LC_ASYNC_ENTER_TIMER |
916 | 0: cghi %r12,__LC_MCK_OLD_PSW | ||
917 | la %r12,__LC_SAVE_AREA+64 | ||
918 | je 0f | ||
919 | la %r12,__LC_SAVE_AREA+32 | ||
921 | 0: clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+16) | 920 | 0: clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+16) |
922 | jhe cleanup_vtime | 921 | jhe cleanup_vtime |
923 | clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn) | 922 | clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn) |
@@ -958,19 +957,22 @@ cleanup_sysc_tif: | |||
958 | 957 | ||
959 | cleanup_sysc_restore: | 958 | cleanup_sysc_restore: |
960 | clc 8(8,%r12),BASED(cleanup_sysc_restore_insn) | 959 | clc 8(8,%r12),BASED(cleanup_sysc_restore_insn) |
961 | je 3f | 960 | je 2f |
962 | clc 8(8,%r12),BASED(cleanup_sysc_restore_insn+8) | 961 | clc 8(8,%r12),BASED(cleanup_sysc_restore_insn+8) |
963 | jhe 0f | 962 | jhe 0f |
963 | mvc __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER | ||
964 | cghi %r12,__LC_MCK_OLD_PSW | ||
965 | je 0f | ||
964 | mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER | 966 | mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER |
965 | 0: mvc __LC_RETURN_PSW(16),SP_PSW(%r15) | 967 | 0: mvc __LC_RETURN_PSW(16),SP_PSW(%r15) |
966 | cghi %r12,__LC_MCK_OLD_PSW | 968 | cghi %r12,__LC_MCK_OLD_PSW |
967 | jne 1f | 969 | la %r12,__LC_SAVE_AREA+64 |
968 | mvc __LC_SAVE_AREA+64(32),SP_R12(%r15) | 970 | je 1f |
969 | j 2f | 971 | la %r12,__LC_SAVE_AREA+32 |
970 | 1: mvc __LC_SAVE_AREA+32(32),SP_R12(%r15) | 972 | 1: mvc 0(32,%r12),SP_R12(%r15) |
971 | 2: lmg %r0,%r11,SP_R0(%r15) | 973 | lmg %r0,%r11,SP_R0(%r15) |
972 | lg %r15,SP_R15(%r15) | 974 | lg %r15,SP_R15(%r15) |
973 | 3: la %r12,__LC_RETURN_PSW | 975 | 2: la %r12,__LC_RETURN_PSW |
974 | br %r14 | 976 | br %r14 |
975 | cleanup_sysc_restore_insn: | 977 | cleanup_sysc_restore_insn: |
976 | .quad sysc_done - 4 | 978 | .quad sysc_done - 4 |
@@ -984,19 +986,15 @@ cleanup_io_tif: | |||
984 | 986 | ||
985 | cleanup_io_restore: | 987 | cleanup_io_restore: |
986 | clc 8(8,%r12),BASED(cleanup_io_restore_insn) | 988 | clc 8(8,%r12),BASED(cleanup_io_restore_insn) |
987 | je 3f | 989 | je 1f |
988 | clc 8(8,%r12),BASED(cleanup_io_restore_insn+8) | 990 | clc 8(8,%r12),BASED(cleanup_io_restore_insn+8) |
989 | jhe 0f | 991 | jhe 0f |
990 | mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER | 992 | mvc __LC_EXIT_TIMER(8),__LC_MCCK_ENTER_TIMER |
991 | 0: mvc __LC_RETURN_PSW(16),SP_PSW(%r15) | 993 | 0: mvc __LC_RETURN_PSW(16),SP_PSW(%r15) |
992 | cghi %r12,__LC_MCK_OLD_PSW | ||
993 | jne 1f | ||
994 | mvc __LC_SAVE_AREA+64(32),SP_R12(%r15) | 994 | mvc __LC_SAVE_AREA+64(32),SP_R12(%r15) |
995 | j 2f | 995 | lmg %r0,%r11,SP_R0(%r15) |
996 | 1: mvc __LC_SAVE_AREA+32(32),SP_R12(%r15) | ||
997 | 2: lmg %r0,%r11,SP_R0(%r15) | ||
998 | lg %r15,SP_R15(%r15) | 996 | lg %r15,SP_R15(%r15) |
999 | 3: la %r12,__LC_RETURN_PSW | 997 | 1: la %r12,__LC_RETURN_PSW |
1000 | br %r14 | 998 | br %r14 |
1001 | cleanup_io_restore_insn: | 999 | cleanup_io_restore_insn: |
1002 | .quad io_done - 4 | 1000 | .quad io_done - 4 |
diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c index 015e27da40eb..ac151399ef34 100644 --- a/arch/s390/kernel/nmi.c +++ b/arch/s390/kernel/nmi.c | |||
@@ -255,7 +255,8 @@ void notrace s390_do_machine_check(struct pt_regs *regs) | |||
255 | int umode; | 255 | int umode; |
256 | 256 | ||
257 | nmi_enter(); | 257 | nmi_enter(); |
258 | s390_idle_check(); | 258 | s390_idle_check(regs, S390_lowcore.mcck_clock, |
259 | S390_lowcore.mcck_enter_timer); | ||
259 | 260 | ||
260 | mci = (struct mci *) &S390_lowcore.mcck_interruption_code; | 261 | mci = (struct mci *) &S390_lowcore.mcck_interruption_code; |
261 | mcck = &__get_cpu_var(cpu_mcck); | 262 | mcck = &__get_cpu_var(cpu_mcck); |
diff --git a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c index 59618bcd99b7..9ce641b5291f 100644 --- a/arch/s390/kernel/s390_ext.c +++ b/arch/s390/kernel/s390_ext.c | |||
@@ -120,7 +120,8 @@ void __irq_entry do_extint(struct pt_regs *regs, unsigned short code) | |||
120 | struct pt_regs *old_regs; | 120 | struct pt_regs *old_regs; |
121 | 121 | ||
122 | old_regs = set_irq_regs(regs); | 122 | old_regs = set_irq_regs(regs); |
123 | s390_idle_check(); | 123 | s390_idle_check(regs, S390_lowcore.int_clock, |
124 | S390_lowcore.async_enter_timer); | ||
124 | irq_enter(); | 125 | irq_enter(); |
125 | if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) | 126 | if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) |
126 | /* Serve timer interrupts first. */ | 127 | /* Serve timer interrupts first. */ |
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index b59a812a010e..3479f1b0d4e0 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c | |||
@@ -121,32 +121,35 @@ void account_system_vtime(struct task_struct *tsk) | |||
121 | } | 121 | } |
122 | EXPORT_SYMBOL_GPL(account_system_vtime); | 122 | EXPORT_SYMBOL_GPL(account_system_vtime); |
123 | 123 | ||
124 | void vtime_start_cpu(void) | 124 | void vtime_start_cpu(__u64 int_clock, __u64 enter_timer) |
125 | { | 125 | { |
126 | struct s390_idle_data *idle = &__get_cpu_var(s390_idle); | 126 | struct s390_idle_data *idle = &__get_cpu_var(s390_idle); |
127 | struct vtimer_queue *vq = &__get_cpu_var(virt_cpu_timer); | 127 | struct vtimer_queue *vq = &__get_cpu_var(virt_cpu_timer); |
128 | __u64 idle_time, expires; | 128 | __u64 idle_time, expires; |
129 | 129 | ||
130 | if (idle->idle_enter == 0ULL) | ||
131 | return; | ||
132 | |||
130 | /* Account time spent with enabled wait psw loaded as idle time. */ | 133 | /* Account time spent with enabled wait psw loaded as idle time. */ |
131 | idle_time = S390_lowcore.int_clock - idle->idle_enter; | 134 | idle_time = int_clock - idle->idle_enter; |
132 | account_idle_time(idle_time); | 135 | account_idle_time(idle_time); |
133 | S390_lowcore.steal_timer += | 136 | S390_lowcore.steal_timer += |
134 | idle->idle_enter - S390_lowcore.last_update_clock; | 137 | idle->idle_enter - S390_lowcore.last_update_clock; |
135 | S390_lowcore.last_update_clock = S390_lowcore.int_clock; | 138 | S390_lowcore.last_update_clock = int_clock; |
136 | 139 | ||
137 | /* Account system time spent going idle. */ | 140 | /* Account system time spent going idle. */ |
138 | S390_lowcore.system_timer += S390_lowcore.last_update_timer - vq->idle; | 141 | S390_lowcore.system_timer += S390_lowcore.last_update_timer - vq->idle; |
139 | S390_lowcore.last_update_timer = S390_lowcore.async_enter_timer; | 142 | S390_lowcore.last_update_timer = enter_timer; |
140 | 143 | ||
141 | /* Restart vtime CPU timer */ | 144 | /* Restart vtime CPU timer */ |
142 | if (vq->do_spt) { | 145 | if (vq->do_spt) { |
143 | /* Program old expire value but first save progress. */ | 146 | /* Program old expire value but first save progress. */ |
144 | expires = vq->idle - S390_lowcore.async_enter_timer; | 147 | expires = vq->idle - enter_timer; |
145 | expires += get_vtimer(); | 148 | expires += get_vtimer(); |
146 | set_vtimer(expires); | 149 | set_vtimer(expires); |
147 | } else { | 150 | } else { |
148 | /* Don't account the CPU timer delta while the cpu was idle. */ | 151 | /* Don't account the CPU timer delta while the cpu was idle. */ |
149 | vq->elapsed -= vq->idle - S390_lowcore.async_enter_timer; | 152 | vq->elapsed -= vq->idle - enter_timer; |
150 | } | 153 | } |
151 | 154 | ||
152 | idle->sequence++; | 155 | idle->sequence++; |