aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/vtime.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel/vtime.c')
-rw-r--r--arch/s390/kernel/vtime.c83
1 files changed, 51 insertions, 32 deletions
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c
index ecf0304e61c1..c87f59bd8246 100644
--- a/arch/s390/kernel/vtime.c
+++ b/arch/s390/kernel/vtime.c
@@ -134,6 +134,8 @@ void vtime_start_cpu(void)
134 /* Account time spent with enabled wait psw loaded as idle time. */ 134 /* Account time spent with enabled wait psw loaded as idle time. */
135 idle_time = S390_lowcore.int_clock - idle->idle_enter; 135 idle_time = S390_lowcore.int_clock - idle->idle_enter;
136 account_idle_time(idle_time); 136 account_idle_time(idle_time);
137 S390_lowcore.steal_timer +=
138 idle->idle_enter - S390_lowcore.last_update_clock;
137 S390_lowcore.last_update_clock = S390_lowcore.int_clock; 139 S390_lowcore.last_update_clock = S390_lowcore.int_clock;
138 140
139 /* Account system time spent going idle. */ 141 /* Account system time spent going idle. */
@@ -238,6 +240,22 @@ void vtime_stop_cpu(void)
238 } 240 }
239} 241}
240 242
243cputime64_t s390_get_idle_time(int cpu)
244{
245 struct s390_idle_data *idle;
246 unsigned long long now, idle_time, idle_enter;
247
248 idle = &per_cpu(s390_idle, cpu);
249 spin_lock(&idle->lock);
250 now = get_clock();
251 idle_time = 0;
252 idle_enter = idle->idle_enter;
253 if (idle_enter != 0ULL && idle_enter < now)
254 idle_time = now - idle_enter;
255 spin_unlock(&idle->lock);
256 return idle_time;
257}
258
241/* 259/*
242 * Sorted add to a list. List is linear searched until first bigger 260 * Sorted add to a list. List is linear searched until first bigger
243 * element is found. 261 * element is found.
@@ -425,17 +443,7 @@ void add_virt_timer_periodic(void *new)
425} 443}
426EXPORT_SYMBOL(add_virt_timer_periodic); 444EXPORT_SYMBOL(add_virt_timer_periodic);
427 445
428/* 446int __mod_vtimer(struct vtimer_list *timer, __u64 expires, int periodic)
429 * If we change a pending timer the function must be called on the CPU
430 * where the timer is running on, e.g. by smp_call_function_single()
431 *
432 * The original mod_timer adds the timer if it is not pending. For
433 * compatibility we do the same. The timer will be added on the current
434 * CPU as a oneshot timer.
435 *
436 * returns whether it has modified a pending timer (1) or not (0)
437 */
438int mod_virt_timer(struct vtimer_list *timer, __u64 expires)
439{ 447{
440 struct vtimer_queue *vq; 448 struct vtimer_queue *vq;
441 unsigned long flags; 449 unsigned long flags;
@@ -444,39 +452,35 @@ int mod_virt_timer(struct vtimer_list *timer, __u64 expires)
444 BUG_ON(!timer->function); 452 BUG_ON(!timer->function);
445 BUG_ON(!expires || expires > VTIMER_MAX_SLICE); 453 BUG_ON(!expires || expires > VTIMER_MAX_SLICE);
446 454
447 /*
448 * This is a common optimization triggered by the
449 * networking code - if the timer is re-modified
450 * to be the same thing then just return:
451 */
452 if (timer->expires == expires && vtimer_pending(timer)) 455 if (timer->expires == expires && vtimer_pending(timer))
453 return 1; 456 return 1;
454 457
455 cpu = get_cpu(); 458 cpu = get_cpu();
456 vq = &per_cpu(virt_cpu_timer, cpu); 459 vq = &per_cpu(virt_cpu_timer, cpu);
457 460
458 /* check if we run on the right CPU */
459 BUG_ON(timer->cpu != cpu);
460
461 /* disable interrupts before test if timer is pending */ 461 /* disable interrupts before test if timer is pending */
462 spin_lock_irqsave(&vq->lock, flags); 462 spin_lock_irqsave(&vq->lock, flags);
463 463
464 /* if timer isn't pending add it on the current CPU */ 464 /* if timer isn't pending add it on the current CPU */
465 if (!vtimer_pending(timer)) { 465 if (!vtimer_pending(timer)) {
466 spin_unlock_irqrestore(&vq->lock, flags); 466 spin_unlock_irqrestore(&vq->lock, flags);
467 /* we do not activate an interval timer with mod_virt_timer */ 467
468 timer->interval = 0; 468 if (periodic)
469 timer->interval = expires;
470 else
471 timer->interval = 0;
469 timer->expires = expires; 472 timer->expires = expires;
470 timer->cpu = cpu; 473 timer->cpu = cpu;
471 internal_add_vtimer(timer); 474 internal_add_vtimer(timer);
472 return 0; 475 return 0;
473 } 476 }
474 477
478 /* check if we run on the right CPU */
479 BUG_ON(timer->cpu != cpu);
480
475 list_del_init(&timer->entry); 481 list_del_init(&timer->entry);
476 timer->expires = expires; 482 timer->expires = expires;
477 483 if (periodic)
478 /* also change the interval if we have an interval timer */
479 if (timer->interval)
480 timer->interval = expires; 484 timer->interval = expires;
481 485
482 /* the timer can't expire anymore so we can release the lock */ 486 /* the timer can't expire anymore so we can release the lock */
@@ -484,9 +488,32 @@ int mod_virt_timer(struct vtimer_list *timer, __u64 expires)
484 internal_add_vtimer(timer); 488 internal_add_vtimer(timer);
485 return 1; 489 return 1;
486} 490}
491
492/*
493 * If we change a pending timer the function must be called on the CPU
494 * where the timer is running on.
495 *
496 * returns whether it has modified a pending timer (1) or not (0)
497 */
498int mod_virt_timer(struct vtimer_list *timer, __u64 expires)
499{
500 return __mod_vtimer(timer, expires, 0);
501}
487EXPORT_SYMBOL(mod_virt_timer); 502EXPORT_SYMBOL(mod_virt_timer);
488 503
489/* 504/*
505 * If we change a pending timer the function must be called on the CPU
506 * where the timer is running on.
507 *
508 * returns whether it has modified a pending timer (1) or not (0)
509 */
510int mod_virt_timer_periodic(struct vtimer_list *timer, __u64 expires)
511{
512 return __mod_vtimer(timer, expires, 1);
513}
514EXPORT_SYMBOL(mod_virt_timer_periodic);
515
516/*
490 * delete a virtual timer 517 * delete a virtual timer
491 * 518 *
492 * returns whether the deleted timer was pending (1) or not (0) 519 * returns whether the deleted timer was pending (1) or not (0)
@@ -516,16 +543,8 @@ EXPORT_SYMBOL(del_virt_timer);
516 */ 543 */
517void init_cpu_vtimer(void) 544void init_cpu_vtimer(void)
518{ 545{
519 struct thread_info *ti = current_thread_info();
520 struct vtimer_queue *vq; 546 struct vtimer_queue *vq;
521 547
522 S390_lowcore.user_timer = ti->user_timer;
523 S390_lowcore.system_timer = ti->system_timer;
524
525 /* kick the virtual timer */
526 asm volatile ("STCK %0" : "=m" (S390_lowcore.last_update_clock));
527 asm volatile ("STPT %0" : "=m" (S390_lowcore.last_update_timer));
528
529 /* initialize per cpu vtimer structure */ 548 /* initialize per cpu vtimer structure */
530 vq = &__get_cpu_var(virt_cpu_timer); 549 vq = &__get_cpu_var(virt_cpu_timer);
531 INIT_LIST_HEAD(&vq->list); 550 INIT_LIST_HEAD(&vq->list);