1 /* 2 * arch/s390/kernel/vtime.c 3 * Virtual cpu timer based timer functions. 4 * 5 * S390 version 6 * Copyright (C) 2004 IBM Deutschland Entwicklung GmbH, IBM Corporation 7 * Author(s): Jan Glauber <jan.glauber@de.ibm.com> 8 */ 9 10 #include <linux/config.h> 11 #include <linux/module.h> 12 #include <linux/kernel.h> 13 #include <linux/time.h> 14 #include <linux/delay.h> 15 #include <linux/init.h> 16 #include <linux/smp.h> 17 #include <linux/types.h> 18 #include <linux/timex.h> 19 #include <linux/notifier.h> 20 #include <linux/kernel_stat.h> 21 #include <linux/rcupdate.h> 22 #include <linux/posix-timers.h> 23 24 #include <asm/s390_ext.h> 25 #include <asm/timer.h> 26 27 static ext_int_info_t ext_int_info_timer; 28 DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer); 29 30 #ifdef CONFIG_VIRT_CPU_ACCOUNTING 31 /* 32 * Update process times based on virtual cpu times stored by entry.S 33 * to the lowcore fields user_timer, system_timer & steal_clock. 34 */ 35 void account_user_vtime(struct task_struct *tsk) 36 { 37 cputime_t cputime; 38 __u64 timer, clock; 39 int rcu_user_flag; 40 41 timer = S390_lowcore.last_update_timer; 42 clock = S390_lowcore.last_update_clock; 43 asm volatile (" STPT %0\n" /* Store current cpu timer value */ 44 " STCK %1" /* Store current tod clock value */ 45 : "=m" (S390_lowcore.last_update_timer), 46 "=m" (S390_lowcore.last_update_clock) ); 47 S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer; 48 S390_lowcore.steal_clock += S390_lowcore.last_update_clock - clock; 49 50 cputime = S390_lowcore.user_timer >> 12; 51 rcu_user_flag = cputime != 0; 52 S390_lowcore.user_timer -= cputime << 12; 53 S390_lowcore.steal_clock -= cputime << 12; 54 account_user_time(tsk, cputime); 55 56 cputime = S390_lowcore.system_timer >> 12; 57 S390_lowcore.system_timer -= cputime << 12; 58 S390_lowcore.steal_clock -= cputime << 12; 59 account_system_time(tsk, HARDIRQ_OFFSET, cputime); 60 61 cputime = S390_lowcore.steal_clock; 62 if ((__s64) cputime > 0) { 63 cputime >>= 12; 64 S390_lowcore.steal_clock -= cputime << 12; 65 account_steal_time(tsk, cputime); 66 } 67 68 run_local_timers(); 69 if (rcu_pending(smp_processor_id())) 70 rcu_check_callbacks(smp_processor_id(), rcu_user_flag); 71 scheduler_tick(); 72 run_posix_cpu_timers(tsk); 73 } 74 75 /* 76 * Update process times based on virtual cpu times stored by entry.S 77 * to the lowcore fields user_timer, system_timer & steal_clock. 78 */ 79 void account_system_vtime(struct task_struct *tsk) 80 { 81 cputime_t cputime; 82 __u64 timer; 83 84 timer = S390_lowcore.last_update_timer; 85 asm volatile (" STPT %0" /* Store current cpu timer value */ 86 : "=m" (S390_lowcore.last_update_timer) ); 87 S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer; 88 89 cputime = S390_lowcore.system_timer >> 12; 90 S390_lowcore.system_timer -= cputime << 12; 91 S390_lowcore.steal_clock -= cputime << 12; 92 account_system_time(tsk, 0, cputime); 93 } 94 95 static inline void set_vtimer(__u64 expires) 96 { 97 __u64 timer; 98 99 asm volatile (" STPT %0\n" /* Store current cpu timer value */ 100 " SPT %1" /* Set new value immediatly afterwards */ 101 : "=m" (timer) : "m" (expires) ); 102 S390_lowcore.system_timer += S390_lowcore.last_update_timer - timer; 103 S390_lowcore.last_update_timer = expires; 104 105 /* store expire time for this CPU timer */ 106 per_cpu(virt_cpu_timer, smp_processor_id()).to_expire = expires; 107 } 108 #else 109 static inline void set_vtimer(__u64 expires) 110 { 111 S390_lowcore.last_update_timer = expires; 112 asm volatile ("SPT %0" : : "m" (S390_lowcore.last_update_timer)); 113 114 /* store expire time for this CPU timer */ 115 per_cpu(virt_cpu_timer, smp_processor_id()).to_expire = expires; 116 } 117 #endif 118 119 static void start_cpu_timer(void) 120 { 121 struct vtimer_queue *vt_list; 122 123 vt_list = &per_cpu(virt_cpu_timer, smp_processor_id()); 124 125 /* CPU timer interrupt is pending, don't reprogramm it */ 126 if (vt_list->idle & 1LL<<63) 127 return; 128 129 if (!list_empty(&vt_list->list)) 130 set_vtimer(vt_list->idle); 131 } 132 133 static void stop_cpu_timer(void) 134 { 135 struct vtimer_queue *vt_list; 136 137 vt_list = &per_cpu(virt_cpu_timer, smp_processor_id()); 138 139 /* nothing to do */ 140 if (list_empty(&vt_list->list)) { 141 vt_list->idle = VTIMER_MAX_SLICE; 142 goto fire; 143 } 144 145 /* store the actual expire value */ 146 asm volatile ("STPT %0" : "=m" (vt_list->idle)); 147 148 /* 149 * If the CPU timer is negative we don't reprogramm 150 * it because we will get instantly an interrupt. 151 */ 152 if (vt_list->idle & 1LL<<63) 153 return; 154 155 vt_list->offset += vt_list->to_expire - vt_list->idle; 156 157 /* 158 * We cannot halt the CPU timer, we just write a value that 159 * nearly never expires (only after 71 years) and re-write 160 * the stored expire value if we continue the timer 161 */ 162 fire: 163 set_vtimer(VTIMER_MAX_SLICE); 164 } 165 166 /* 167 * Sorted add to a list. List is linear searched until first bigger 168 * element is found. 169 */ 170 static void list_add_sorted(struct vtimer_list *timer, struct list_head *head) 171 { 172 struct vtimer_list *event; 173 174 list_for_each_entry(event, head, entry) { 175 if (event->expires > timer->expires) { 176 list_add_tail(&timer->entry, &event->entry); 177 return; 178 } 179 } 180 list_add_tail(&timer->entry, head); 181 } 182 183 /* 184 * Do the callback functions of expired vtimer events. 185 * Called from within the interrupt handler. 186 */ 187 static void do_callbacks(struct list_head *cb_list, struct pt_regs *regs) 188 { 189 struct vtimer_queue *vt_list; 190 struct vtimer_list *event, *tmp; 191 void (*fn)(unsigned long, struct pt_regs*); 192 unsigned long data; 193 194 if (list_empty(cb_list)) 195 return; 196 197 vt_list = &per_cpu(virt_cpu_timer, smp_processor_id()); 198 199 list_for_each_entry_safe(event, tmp, cb_list, entry) { 200 fn = event->function; 201 data = event->data; 202 fn(data, regs); 203 204 if (!event->interval) 205 /* delete one shot timer */ 206 list_del_init(&event->entry); 207 else { 208 /* move interval timer back to list */ 209 spin_lock(&vt_list->lock); 210 list_del_init(&event->entry); 211 list_add_sorted(event, &vt_list->list); 212 spin_unlock(&vt_list->lock); 213 } 214 } 215 } 216 217 /* 218 * Handler for the virtual CPU timer. 219 */ 220 static void do_cpu_timer_interrupt(struct pt_regs *regs, __u16 error_code) 221 { 222 int cpu; 223 __u64 next, delta; 224 struct vtimer_queue *vt_list; 225 struct vtimer_list *event, *tmp; 226 struct list_head *ptr; 227 /* the callback queue */ 228 struct list_head cb_list; 229 230 INIT_LIST_HEAD(&cb_list); 231 cpu = smp_processor_id(); 232 vt_list = &per_cpu(virt_cpu_timer, cpu); 233 234 /* walk timer list, fire all expired events */ 235 spin_lock(&vt_list->lock); 236 237 if (vt_list->to_expire < VTIMER_MAX_SLICE) 238 vt_list->offset += vt_list->to_expire; 239 240 list_for_each_entry_safe(event, tmp, &vt_list->list, entry) { 241 if (event->expires > vt_list->offset) 242 /* found first unexpired event, leave */ 243 break; 244 245 /* re-charge interval timer, we have to add the offset */ 246 if (event->interval) 247 event->expires = event->interval + vt_list->offset; 248 249 /* move expired timer to the callback queue */ 250 list_move_tail(&event->entry, &cb_list); 251 } 252 spin_unlock(&vt_list->lock); 253 do_callbacks(&cb_list, regs); 254 255 /* next event is first in list */ 256 spin_lock(&vt_list->lock); 257 if (!list_empty(&vt_list->list)) { 258 ptr = vt_list->list.next; 259 event = list_entry(ptr, struct vtimer_list, entry); 260 next = event->expires - vt_list->offset; 261 262 /* add the expired time from this interrupt handler 263 * and the callback functions 264 */ 265 asm volatile ("STPT %0" : "=m" (delta)); 266 delta = 0xffffffffffffffffLL - delta + 1; 267 vt_list->offset += delta; 268 next -= delta; 269 } else { 270 vt_list->offset = 0; 271 next = VTIMER_MAX_SLICE; 272 } 273 spin_unlock(&vt_list->lock); 274 set_vtimer(next); 275 } 276 277 void init_virt_timer(struct vtimer_list *timer) 278 { 279 timer->function = NULL; 280 INIT_LIST_HEAD(&timer->entry); 281 spin_lock_init(&timer->lock); 282 } 283 EXPORT_SYMBOL(init_virt_timer); 284 285 static inline int vtimer_pending(struct vtimer_list *timer) 286 { 287 return (!list_empty(&timer->entry)); 288 } 289 290 /* 291 * this function should only run on the specified CPU 292 */ 293 static void internal_add_vtimer(struct vtimer_list *timer) 294 { 295 unsigned long flags; 296 __u64 done; 297 struct vtimer_list *event; 298 struct vtimer_queue *vt_list; 299 300 vt_list = &per_cpu(virt_cpu_timer, timer->cpu); 301 spin_lock_irqsave(&vt_list->lock, flags); 302 303 if (timer->cpu != smp_processor_id()) 304 printk("internal_add_vtimer: BUG, running on wrong CPU"); 305 306 /* if list is empty we only have to set the timer */ 307 if (list_empty(&vt_list->list)) { 308 /* reset the offset, this may happen if the last timer was 309 * just deleted by mod_virt_timer and the interrupt 310 * didn't happen until here 311 */ 312 vt_list->offset = 0; 313 goto fire; 314 } 315 316 /* save progress */ 317 asm volatile ("STPT %0" : "=m" (done)); 318 319 /* calculate completed work */ 320 done = vt_list->to_expire - done + vt_list->offset; 321 vt_list->offset = 0; 322 323 list_for_each_entry(event, &vt_list->list, entry) 324 event->expires -= done; 325 326 fire: 327 list_add_sorted(timer, &vt_list->list); 328 329 /* get first element, which is the next vtimer slice */ 330 event = list_entry(vt_list->list.next, struct vtimer_list, entry); 331 332 set_vtimer(event->expires); 333 spin_unlock_irqrestore(&vt_list->lock, flags); 334 /* release CPU aquired in prepare_vtimer or mod_virt_timer() */ 335 put_cpu(); 336 } 337 338 static inline int prepare_vtimer(struct vtimer_list *timer) 339 { 340 if (!timer->function) { 341 printk("add_virt_timer: uninitialized timer\n"); 342 return -EINVAL; 343 } 344 345 if (!timer->expires || timer->expires > VTIMER_MAX_SLICE) { 346 printk("add_virt_timer: invalid timer expire value!\n"); 347 return -EINVAL; 348 } 349 350 if (vtimer_pending(timer)) { 351 printk("add_virt_timer: timer pending\n"); 352 return -EBUSY; 353 } 354 355 timer->cpu = get_cpu(); 356 return 0; 357 } 358 359 /* 360 * add_virt_timer - add an oneshot virtual CPU timer 361 */ 362 void add_virt_timer(void *new) 363 { 364 struct vtimer_list *timer; 365 366 timer = (struct vtimer_list *)new; 367 368 if (prepare_vtimer(timer) < 0) 369 return; 370 371 timer->interval = 0; 372 internal_add_vtimer(timer); 373 } 374 EXPORT_SYMBOL(add_virt_timer); 375 376 /* 377 * add_virt_timer_int - add an interval virtual CPU timer 378 */ 379 void add_virt_timer_periodic(void *new) 380 { 381 struct vtimer_list *timer; 382 383 timer = (struct vtimer_list *)new; 384 385 if (prepare_vtimer(timer) < 0) 386 return; 387 388 timer->interval = timer->expires; 389 internal_add_vtimer(timer); 390 } 391 EXPORT_SYMBOL(add_virt_timer_periodic); 392 393 /* 394 * If we change a pending timer the function must be called on the CPU 395 * where the timer is running on, e.g. by smp_call_function_on() 396 * 397 * The original mod_timer adds the timer if it is not pending. For compatibility 398 * we do the same. The timer will be added on the current CPU as a oneshot timer. 399 * 400 * returns whether it has modified a pending timer (1) or not (0) 401 */ 402 int mod_virt_timer(struct vtimer_list *timer, __u64 expires) 403 { 404 struct vtimer_queue *vt_list; 405 unsigned long flags; 406 int cpu; 407 408 if (!timer->function) { 409 printk("mod_virt_timer: uninitialized timer\n"); 410 return -EINVAL; 411 } 412 413 if (!expires || expires > VTIMER_MAX_SLICE) { 414 printk("mod_virt_timer: invalid expire range\n"); 415 return -EINVAL; 416 } 417 418 /* 419 * This is a common optimization triggered by the 420 * networking code - if the timer is re-modified 421 * to be the same thing then just return: 422 */ 423 if (timer->expires == expires && vtimer_pending(timer)) 424 return 1; 425 426 cpu = get_cpu(); 427 vt_list = &per_cpu(virt_cpu_timer, cpu); 428 429 /* disable interrupts before test if timer is pending */ 430 spin_lock_irqsave(&vt_list->lock, flags); 431 432 /* if timer isn't pending add it on the current CPU */ 433 if (!vtimer_pending(timer)) { 434 spin_unlock_irqrestore(&vt_list->lock, flags); 435 /* we do not activate an interval timer with mod_virt_timer */ 436 timer->interval = 0; 437 timer->expires = expires; 438 timer->cpu = cpu; 439 internal_add_vtimer(timer); 440 return 0; 441 } 442 443 /* check if we run on the right CPU */ 444 if (timer->cpu != cpu) { 445 printk("mod_virt_timer: running on wrong CPU, check your code\n"); 446 spin_unlock_irqrestore(&vt_list->lock, flags); 447 put_cpu(); 448 return -EINVAL; 449 } 450 451 list_del_init(&timer->entry); 452 timer->expires = expires; 453 454 /* also change the interval if we have an interval timer */ 455 if (timer->interval) 456 timer->interval = expires; 457 458 /* the timer can't expire anymore so we can release the lock */ 459 spin_unlock_irqrestore(&vt_list->lock, flags); 460 internal_add_vtimer(timer); 461 return 1; 462 } 463 EXPORT_SYMBOL(mod_virt_timer); 464 465 /* 466 * delete a virtual timer 467 * 468 * returns whether the deleted timer was pending (1) or not (0) 469 */ 470 int del_virt_timer(struct vtimer_list *timer) 471 { 472 unsigned long flags; 473 struct vtimer_queue *vt_list; 474 475 /* check if timer is pending */ 476 if (!vtimer_pending(timer)) 477 return 0; 478 479 vt_list = &per_cpu(virt_cpu_timer, timer->cpu); 480 spin_lock_irqsave(&vt_list->lock, flags); 481 482 /* we don't interrupt a running timer, just let it expire! */ 483 list_del_init(&timer->entry); 484 485 /* last timer removed */ 486 if (list_empty(&vt_list->list)) { 487 vt_list->to_expire = 0; 488 vt_list->offset = 0; 489 } 490 491 spin_unlock_irqrestore(&vt_list->lock, flags); 492 return 1; 493 } 494 EXPORT_SYMBOL(del_virt_timer); 495 496 /* 497 * Start the virtual CPU timer on the current CPU. 498 */ 499 void init_cpu_vtimer(void) 500 { 501 struct vtimer_queue *vt_list; 502 unsigned long cr0; 503 504 /* kick the virtual timer */ 505 S390_lowcore.exit_timer = VTIMER_MAX_SLICE; 506 S390_lowcore.last_update_timer = VTIMER_MAX_SLICE; 507 asm volatile ("SPT %0" : : "m" (S390_lowcore.last_update_timer)); 508 asm volatile ("STCK %0" : "=m" (S390_lowcore.last_update_clock)); 509 __ctl_store(cr0, 0, 0); 510 cr0 |= 0x400; 511 __ctl_load(cr0, 0, 0); 512 513 vt_list = &per_cpu(virt_cpu_timer, smp_processor_id()); 514 INIT_LIST_HEAD(&vt_list->list); 515 spin_lock_init(&vt_list->lock); 516 vt_list->to_expire = 0; 517 vt_list->offset = 0; 518 vt_list->idle = 0; 519 520 } 521 522 static int vtimer_idle_notify(struct notifier_block *self, 523 unsigned long action, void *hcpu) 524 { 525 switch (action) { 526 case CPU_IDLE: 527 stop_cpu_timer(); 528 break; 529 case CPU_NOT_IDLE: 530 start_cpu_timer(); 531 break; 532 } 533 return NOTIFY_OK; 534 } 535 536 static struct notifier_block vtimer_idle_nb = { 537 .notifier_call = vtimer_idle_notify, 538 }; 539 540 void __init vtime_init(void) 541 { 542 /* request the cpu timer external interrupt */ 543 if (register_early_external_interrupt(0x1005, do_cpu_timer_interrupt, 544 &ext_int_info_timer) != 0) 545 panic("Couldn't request external interrupt 0x1005"); 546 547 if (register_idle_notifier(&vtimer_idle_nb)) 548 panic("Couldn't register idle notifier"); 549 550 init_cpu_vtimer(); 551 } 552 553