aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2009-04-14 09:36:29 -0400
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2009-04-14 09:37:27 -0400
commitab96e798cbd562a53edd802272e49a5100b29efb (patch)
tree4b3558bc97f5c2fc5c63789431deef79534e3bd3 /arch/s390/kernel
parentb6112ccbff5ec580d46b584ecc3c3a773b830da2 (diff)
[S390] boot cputime accounting
Start the cpu time accounting very early to catch the cpu time spent for the initial kernel setup. To make the output of /proc/uptime match the sum of all cpu accounting values of the boot cpu reset xtime and wall_to_monotonic to sane values based on the TOD clock. The values set by timekeeping_init are off by up to a second. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r--arch/s390/kernel/head.S8
-rw-r--r--arch/s390/kernel/setup.c8
-rw-r--r--arch/s390/kernel/time.c36
-rw-r--r--arch/s390/kernel/vtime.c8
4 files changed, 43 insertions, 17 deletions
diff --git a/arch/s390/kernel/head.S b/arch/s390/kernel/head.S
index 16f8975325ed..bba14494ee00 100644
--- a/arch/s390/kernel/head.S
+++ b/arch/s390/kernel/head.S
@@ -473,7 +473,10 @@ startup:basr %r13,0 # get base
473 xc 0x300(256),0x300 473 xc 0x300(256),0x300
474 l %r1,5f-.LPG0(%r13) 474 l %r1,5f-.LPG0(%r13)
475 stck 0(%r1) 475 stck 0(%r1)
476 476 spt 6f-.LPG0(%r13)
477 mvc __LC_LAST_UPDATE_CLOCK(8),0(%r1)
478 mvc __LC_LAST_UPDATE_TIMER(8),6f-.LPG0(%r13)
479 mvc __LC_EXIT_TIMER(8),5f-.LPG0(%r13)
477#ifndef CONFIG_MARCH_G5 480#ifndef CONFIG_MARCH_G5
478 # check processor version against MARCH_{G5,Z900,Z990,Z9_109,Z10} 481 # check processor version against MARCH_{G5,Z900,Z990,Z9_109,Z10}
479 stidp __LC_CPUID # store cpuid 482 stidp __LC_CPUID # store cpuid
@@ -500,8 +503,11 @@ startup:basr %r13,0 # get base
500 503
501 l %r13,4f-.LPG0(%r13) 504 l %r13,4f-.LPG0(%r13)
502 b 0(%r13) 505 b 0(%r13)
506 .align 4
5034: .long startup_continue 5074: .long startup_continue
5045: .long sched_clock_base_cc 5085: .long sched_clock_base_cc
509 .align 8
5106: .long 0x7fffffff,0xffffffff
505 511
506# 512#
507# params at 10400 (setup.h) 513# params at 10400 (setup.h)
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 163bdfe5a6be..7402b6a39ead 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -434,6 +434,14 @@ setup_lowcore(void)
434#else 434#else
435 lc->vdso_per_cpu_data = (unsigned long) &lc->paste[0]; 435 lc->vdso_per_cpu_data = (unsigned long) &lc->paste[0];
436#endif 436#endif
437 lc->sync_enter_timer = S390_lowcore.sync_enter_timer;
438 lc->async_enter_timer = S390_lowcore.async_enter_timer;
439 lc->exit_timer = S390_lowcore.exit_timer;
440 lc->user_timer = S390_lowcore.user_timer;
441 lc->system_timer = S390_lowcore.system_timer;
442 lc->steal_timer = S390_lowcore.steal_timer;
443 lc->last_update_timer = S390_lowcore.last_update_timer;
444 lc->last_update_clock = S390_lowcore.last_update_clock;
437 set_prefix((u32)(unsigned long) lc); 445 set_prefix((u32)(unsigned long) lc);
438 lowcore_ptr[0] = lc; 446 lowcore_ptr[0] = lc;
439} 447}
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 369ff02c4ab2..6ded50dfa75a 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -253,32 +253,52 @@ void update_vsyscall_tz(void)
253 */ 253 */
254void __init time_init(void) 254void __init time_init(void)
255{ 255{
256 struct timespec ts;
257 unsigned long flags;
258 cycle_t now;
259
256 /* Reset time synchronization interfaces. */ 260 /* Reset time synchronization interfaces. */
257 etr_reset(); 261 etr_reset();
258 stp_reset(); 262 stp_reset();
259 263
260 /* set xtime */
261 tod_to_timeval(sched_clock_base_cc - TOD_UNIX_EPOCH, &xtime);
262 set_normalized_timespec(&wall_to_monotonic,
263 -xtime.tv_sec, -xtime.tv_nsec);
264
265 /* request the clock comparator external interrupt */ 264 /* request the clock comparator external interrupt */
266 if (register_early_external_interrupt(0x1004, 265 if (register_early_external_interrupt(0x1004,
267 clock_comparator_interrupt, 266 clock_comparator_interrupt,
268 &ext_int_info_cc) != 0) 267 &ext_int_info_cc) != 0)
269 panic("Couldn't request external interrupt 0x1004"); 268 panic("Couldn't request external interrupt 0x1004");
270 269
271 if (clocksource_register(&clocksource_tod) != 0)
272 panic("Could not register TOD clock source");
273
274 /* request the timing alert external interrupt */ 270 /* request the timing alert external interrupt */
275 if (register_early_external_interrupt(0x1406, 271 if (register_early_external_interrupt(0x1406,
276 timing_alert_interrupt, 272 timing_alert_interrupt,
277 &ext_int_etr_cc) != 0) 273 &ext_int_etr_cc) != 0)
278 panic("Couldn't request external interrupt 0x1406"); 274 panic("Couldn't request external interrupt 0x1406");
279 275
276 if (clocksource_register(&clocksource_tod) != 0)
277 panic("Could not register TOD clock source");
278
279 /*
280 * The TOD clock is an accurate clock. The xtime should be
281 * initialized in a way that the difference between TOD and
282 * xtime is reasonably small. Too bad that timekeeping_init
283 * sets xtime.tv_nsec to zero. In addition the clock source
284 * change from the jiffies clock source to the TOD clock
285 * source add another error of up to 1/HZ second. The same
286 * function sets wall_to_monotonic to a value that is too
287 * small for /proc/uptime to be accurate.
288 * Reset xtime and wall_to_monotonic to sane values.
289 */
290 write_seqlock_irqsave(&xtime_lock, flags);
291 now = get_clock();
292 tod_to_timeval(now - TOD_UNIX_EPOCH, &xtime);
293 clocksource_tod.cycle_last = now;
294 clocksource_tod.raw_time = xtime;
295 tod_to_timeval(sched_clock_base_cc - TOD_UNIX_EPOCH, &ts);
296 set_normalized_timespec(&wall_to_monotonic, -ts.tv_sec, -ts.tv_nsec);
297 write_sequnlock_irqrestore(&xtime_lock, flags);
298
280 /* Enable TOD clock interrupts on the boot cpu. */ 299 /* Enable TOD clock interrupts on the boot cpu. */
281 init_cpu_timer(); 300 init_cpu_timer();
301
282 /* Enable cpu timer interrupts on the boot cpu. */ 302 /* Enable cpu timer interrupts on the boot cpu. */
283 vtime_init(); 303 vtime_init();
284} 304}
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index c0870a61f90f..38ea92ff04f9 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -527,16 +527,8 @@ EXPORT_SYMBOL(del_virt_timer);
527 */ 527 */
528void init_cpu_vtimer(void) 528void init_cpu_vtimer(void)
529{ 529{
530 struct thread_info *ti = current_thread_info();
531 struct vtimer_queue *vq; 530 struct vtimer_queue *vq;
532 531
533 S390_lowcore.user_timer = ti->user_timer;
534 S390_lowcore.system_timer = ti->system_timer;
535
536 /* kick the virtual timer */
537 asm volatile ("STCK %0" : "=m" (S390_lowcore.last_update_clock));
538 asm volatile ("STPT %0" : "=m" (S390_lowcore.last_update_timer));
539
540 /* initialize per cpu vtimer structure */ 532 /* initialize per cpu vtimer structure */
541 vq = &__get_cpu_var(virt_cpu_timer); 533 vq = &__get_cpu_var(virt_cpu_timer);
542 INIT_LIST_HEAD(&vq->list); 534 INIT_LIST_HEAD(&vq->list);