aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/include/asm/cputime.h9
-rw-r--r--arch/s390/include/asm/lowcore.h98
-rw-r--r--arch/s390/kernel/asm-offsets.c2
-rw-r--r--arch/s390/kernel/entry.S54
-rw-r--r--arch/s390/kernel/entry64.S54
-rw-r--r--arch/s390/kernel/nmi.c3
-rw-r--r--arch/s390/kernel/s390_ext.c3
-rw-r--r--arch/s390/kernel/vtime.c15
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
189DECLARE_PER_CPU(struct s390_idle_data, s390_idle); 189DECLARE_PER_CPU(struct s390_idle_data, s390_idle);
190 190
191void vtime_start_cpu(void); 191void vtime_start_cpu(__u64 int_clock, __u64 enter_timer);
192cputime64_t s390_get_idle_time(int cpu); 192cputime64_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
196static inline void s390_idle_check(void) 196static 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
202static inline int s390_nohz_delay(int cpu) 203static 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
744mcck_int_handler: 744mcck_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
7660: spt 0(%r14) 7650: spt 0(%r14)
767 mvc __LC_ASYNC_ENTER_TIMER(8),0(%r14) 766 mvc __LC_MCCK_ENTER_TIMER(8),0(%r14)
7681: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? 7671: 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
792mcck_no_vtime: 791mcck_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:
811mcck_return: 810mcck_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
935cleanup_system_call: 933cleanup_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)
9410: la %r12,__LC_SAVE_AREA+32
9421:
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
9410: c %r12,BASED(.Lmck_old_psw)
942 la %r12,__LC_SAVE_AREA+32
943 be BASED(0f)
944 la %r12,__LC_SAVE_AREA+16
9460: clc __LC_RETURN_PSW+4(4),BASED(cleanup_system_call_insn+8) 9450: 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:
984cleanup_sysc_restore: 983cleanup_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) 9900: 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
9950: mvc __LC_SAVE_AREA+16(16),SP_R12(%r15) 9971: mvc 0(16,%r12),SP_R12(%r15)
9961: 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)
9982: la %r12,__LC_RETURN_PSW 10002: la %r12,__LC_RETURN_PSW
999 br %r14 1001 br %r14
@@ -1009,19 +1011,15 @@ cleanup_io_tif:
1009 1011
1010cleanup_io_restore: 1012cleanup_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)
10210: mvc __LC_SAVE_AREA+16(16),SP_R12(%r15)
10221: lm %r0,%r11,SP_R0(%r15)
1023 l %r15,SP_R15(%r15) 1021 l %r15,SP_R15(%r15)
10242: la %r12,__LC_RETURN_PSW 10221: la %r12,__LC_RETURN_PSW
1025 br %r14 1023 br %r14
1026cleanup_io_restore_insn: 1024cleanup_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
727mcck_int_handler: 727mcck_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
7510: spt 0(%r14) 7500: spt 0(%r14)
752 mvc __LC_ASYNC_ENTER_TIMER(8),0(%r14) 751 mvc __LC_MCCK_ENTER_TIMER(8),0(%r14)
7531: tm __LC_MCCK_CODE+2,0x09 # mwp + ia of old psw valid? 7521: 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
776mcck_no_vtime: 775mcck_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
910cleanup_system_call: 908cleanup_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
9160: la %r12,__LC_SAVE_AREA+64
9171:
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
9160: cghi %r12,__LC_MCK_OLD_PSW
917 la %r12,__LC_SAVE_AREA+64
918 je 0f
919 la %r12,__LC_SAVE_AREA+32
9210: clc __LC_RETURN_PSW+8(8),BASED(cleanup_system_call_insn+16) 9200: 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
959cleanup_sysc_restore: 958cleanup_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
9650: mvc __LC_RETURN_PSW(16),SP_PSW(%r15) 9670: 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
9701: mvc __LC_SAVE_AREA+32(32),SP_R12(%r15) 9721: mvc 0(32,%r12),SP_R12(%r15)
9712: 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)
9733: la %r12,__LC_RETURN_PSW 9752: la %r12,__LC_RETURN_PSW
974 br %r14 976 br %r14
975cleanup_sysc_restore_insn: 977cleanup_sysc_restore_insn:
976 .quad sysc_done - 4 978 .quad sysc_done - 4
@@ -984,19 +986,15 @@ cleanup_io_tif:
984 986
985cleanup_io_restore: 987cleanup_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
9910: mvc __LC_RETURN_PSW(16),SP_PSW(%r15) 9930: 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)
9961: mvc __LC_SAVE_AREA+32(32),SP_R12(%r15)
9972: lmg %r0,%r11,SP_R0(%r15)
998 lg %r15,SP_R15(%r15) 996 lg %r15,SP_R15(%r15)
9993: la %r12,__LC_RETURN_PSW 9971: la %r12,__LC_RETURN_PSW
1000 br %r14 998 br %r14
1001cleanup_io_restore_insn: 999cleanup_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}
122EXPORT_SYMBOL_GPL(account_system_vtime); 122EXPORT_SYMBOL_GPL(account_system_vtime);
123 123
124void vtime_start_cpu(void) 124void 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++;