xref: /openbmc/linux/arch/s390/kernel/vtime.c (revision b04b4f78)
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/module.h>
11 #include <linux/kernel.h>
12 #include <linux/time.h>
13 #include <linux/delay.h>
14 #include <linux/init.h>
15 #include <linux/smp.h>
16 #include <linux/types.h>
17 #include <linux/timex.h>
18 #include <linux/notifier.h>
19 #include <linux/kernel_stat.h>
20 #include <linux/rcupdate.h>
21 #include <linux/posix-timers.h>
22 
23 #include <asm/s390_ext.h>
24 #include <asm/timer.h>
25 #include <asm/irq_regs.h>
26 #include <asm/cpu.h>
27 
28 static ext_int_info_t ext_int_info_timer;
29 
30 static DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer);
31 
32 DEFINE_PER_CPU(struct s390_idle_data, s390_idle) = {
33 	.lock = __SPIN_LOCK_UNLOCKED(s390_idle.lock)
34 };
35 
36 static inline __u64 get_vtimer(void)
37 {
38 	__u64 timer;
39 
40 	asm volatile("STPT %0" : "=m" (timer));
41 	return timer;
42 }
43 
44 static inline void set_vtimer(__u64 expires)
45 {
46 	__u64 timer;
47 
48 	asm volatile ("  STPT %0\n"  /* Store current cpu timer value */
49 		      "  SPT %1"     /* Set new value immediatly afterwards */
50 		      : "=m" (timer) : "m" (expires) );
51 	S390_lowcore.system_timer += S390_lowcore.last_update_timer - timer;
52 	S390_lowcore.last_update_timer = expires;
53 }
54 
55 /*
56  * Update process times based on virtual cpu times stored by entry.S
57  * to the lowcore fields user_timer, system_timer & steal_clock.
58  */
59 static void do_account_vtime(struct task_struct *tsk, int hardirq_offset)
60 {
61 	struct thread_info *ti = task_thread_info(tsk);
62 	__u64 timer, clock, user, system, steal;
63 
64 	timer = S390_lowcore.last_update_timer;
65 	clock = S390_lowcore.last_update_clock;
66 	asm volatile ("  STPT %0\n"    /* Store current cpu timer value */
67 		      "  STCK %1"      /* Store current tod clock value */
68 		      : "=m" (S390_lowcore.last_update_timer),
69 		        "=m" (S390_lowcore.last_update_clock) );
70 	S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer;
71 	S390_lowcore.steal_timer += S390_lowcore.last_update_clock - clock;
72 
73 	user = S390_lowcore.user_timer - ti->user_timer;
74 	S390_lowcore.steal_timer -= user;
75 	ti->user_timer = S390_lowcore.user_timer;
76 	account_user_time(tsk, user, user);
77 
78 	system = S390_lowcore.system_timer - ti->system_timer;
79 	S390_lowcore.steal_timer -= system;
80 	ti->system_timer = S390_lowcore.system_timer;
81 	account_system_time(tsk, hardirq_offset, system, system);
82 
83 	steal = S390_lowcore.steal_timer;
84 	if ((s64) steal > 0) {
85 		S390_lowcore.steal_timer = 0;
86 		account_steal_time(steal);
87 	}
88 }
89 
90 void account_vtime(struct task_struct *prev, struct task_struct *next)
91 {
92 	struct thread_info *ti;
93 
94 	do_account_vtime(prev, 0);
95 	ti = task_thread_info(prev);
96 	ti->user_timer = S390_lowcore.user_timer;
97 	ti->system_timer = S390_lowcore.system_timer;
98 	ti = task_thread_info(next);
99 	S390_lowcore.user_timer = ti->user_timer;
100 	S390_lowcore.system_timer = ti->system_timer;
101 }
102 
103 void account_process_tick(struct task_struct *tsk, int user_tick)
104 {
105 	do_account_vtime(tsk, HARDIRQ_OFFSET);
106 }
107 
108 /*
109  * Update process times based on virtual cpu times stored by entry.S
110  * to the lowcore fields user_timer, system_timer & steal_clock.
111  */
112 void account_system_vtime(struct task_struct *tsk)
113 {
114 	struct thread_info *ti = task_thread_info(tsk);
115 	__u64 timer, system;
116 
117 	timer = S390_lowcore.last_update_timer;
118 	S390_lowcore.last_update_timer = get_vtimer();
119 	S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer;
120 
121 	system = S390_lowcore.system_timer - ti->system_timer;
122 	S390_lowcore.steal_timer -= system;
123 	ti->system_timer = S390_lowcore.system_timer;
124 	account_system_time(tsk, 0, system, system);
125 }
126 EXPORT_SYMBOL_GPL(account_system_vtime);
127 
128 void vtime_start_cpu(void)
129 {
130 	struct s390_idle_data *idle = &__get_cpu_var(s390_idle);
131 	struct vtimer_queue *vq = &__get_cpu_var(virt_cpu_timer);
132 	__u64 idle_time, expires;
133 
134 	/* Account time spent with enabled wait psw loaded as idle time. */
135 	idle_time = S390_lowcore.int_clock - idle->idle_enter;
136 	account_idle_time(idle_time);
137 	S390_lowcore.steal_timer +=
138 		idle->idle_enter - S390_lowcore.last_update_clock;
139 	S390_lowcore.last_update_clock = S390_lowcore.int_clock;
140 
141 	/* Account system time spent going idle. */
142 	S390_lowcore.system_timer += S390_lowcore.last_update_timer - vq->idle;
143 	S390_lowcore.last_update_timer = S390_lowcore.async_enter_timer;
144 
145 	/* Restart vtime CPU timer */
146 	if (vq->do_spt) {
147 		/* Program old expire value but first save progress. */
148 		expires = vq->idle - S390_lowcore.async_enter_timer;
149 		expires += get_vtimer();
150 		set_vtimer(expires);
151 	} else {
152 		/* Don't account the CPU timer delta while the cpu was idle. */
153 		vq->elapsed -= vq->idle - S390_lowcore.async_enter_timer;
154 	}
155 
156 	spin_lock(&idle->lock);
157 	idle->idle_time += idle_time;
158 	idle->idle_enter = 0ULL;
159 	idle->idle_count++;
160 	spin_unlock(&idle->lock);
161 }
162 
163 void vtime_stop_cpu(void)
164 {
165 	struct s390_idle_data *idle = &__get_cpu_var(s390_idle);
166 	struct vtimer_queue *vq = &__get_cpu_var(virt_cpu_timer);
167 	psw_t psw;
168 
169 	/* Wait for external, I/O or machine check interrupt. */
170 	psw.mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_IO | PSW_MASK_EXT;
171 
172 	/* Check if the CPU timer needs to be reprogrammed. */
173 	if (vq->do_spt) {
174 		__u64 vmax = VTIMER_MAX_SLICE;
175 		/*
176 		 * The inline assembly is equivalent to
177 		 *	vq->idle = get_cpu_timer();
178 		 *	set_cpu_timer(VTIMER_MAX_SLICE);
179 		 *	idle->idle_enter = get_clock();
180 		 *	__load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT |
181 		 *			   PSW_MASK_IO | PSW_MASK_EXT);
182 		 * The difference is that the inline assembly makes sure that
183 		 * the last three instruction are stpt, stck and lpsw in that
184 		 * order. This is done to increase the precision.
185 		 */
186 		asm volatile(
187 #ifndef CONFIG_64BIT
188 			"	basr	1,0\n"
189 			"0:	ahi	1,1f-0b\n"
190 			"	st	1,4(%2)\n"
191 #else /* CONFIG_64BIT */
192 			"	larl	1,1f\n"
193 			"	stg	1,8(%2)\n"
194 #endif /* CONFIG_64BIT */
195 			"	stpt	0(%4)\n"
196 			"	spt	0(%5)\n"
197 			"	stck	0(%3)\n"
198 #ifndef CONFIG_64BIT
199 			"	lpsw	0(%2)\n"
200 #else /* CONFIG_64BIT */
201 			"	lpswe	0(%2)\n"
202 #endif /* CONFIG_64BIT */
203 			"1:"
204 			: "=m" (idle->idle_enter), "=m" (vq->idle)
205 			: "a" (&psw), "a" (&idle->idle_enter),
206 			  "a" (&vq->idle), "a" (&vmax), "m" (vmax), "m" (psw)
207 			: "memory", "cc", "1");
208 	} else {
209 		/*
210 		 * The inline assembly is equivalent to
211 		 *	vq->idle = get_cpu_timer();
212 		 *	idle->idle_enter = get_clock();
213 		 *	__load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT |
214 		 *			   PSW_MASK_IO | PSW_MASK_EXT);
215 		 * The difference is that the inline assembly makes sure that
216 		 * the last three instruction are stpt, stck and lpsw in that
217 		 * order. This is done to increase the precision.
218 		 */
219 		asm volatile(
220 #ifndef CONFIG_64BIT
221 			"	basr	1,0\n"
222 			"0:	ahi	1,1f-0b\n"
223 			"	st	1,4(%2)\n"
224 #else /* CONFIG_64BIT */
225 			"	larl	1,1f\n"
226 			"	stg	1,8(%2)\n"
227 #endif /* CONFIG_64BIT */
228 			"	stpt	0(%4)\n"
229 			"	stck	0(%3)\n"
230 #ifndef CONFIG_64BIT
231 			"	lpsw	0(%2)\n"
232 #else /* CONFIG_64BIT */
233 			"	lpswe	0(%2)\n"
234 #endif /* CONFIG_64BIT */
235 			"1:"
236 			: "=m" (idle->idle_enter), "=m" (vq->idle)
237 			: "a" (&psw), "a" (&idle->idle_enter),
238 			  "a" (&vq->idle), "m" (psw)
239 			: "memory", "cc", "1");
240 	}
241 }
242 
243 cputime64_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 
259 /*
260  * Sorted add to a list. List is linear searched until first bigger
261  * element is found.
262  */
263 static void list_add_sorted(struct vtimer_list *timer, struct list_head *head)
264 {
265 	struct vtimer_list *event;
266 
267 	list_for_each_entry(event, head, entry) {
268 		if (event->expires > timer->expires) {
269 			list_add_tail(&timer->entry, &event->entry);
270 			return;
271 		}
272 	}
273 	list_add_tail(&timer->entry, head);
274 }
275 
276 /*
277  * Do the callback functions of expired vtimer events.
278  * Called from within the interrupt handler.
279  */
280 static void do_callbacks(struct list_head *cb_list)
281 {
282 	struct vtimer_queue *vq;
283 	struct vtimer_list *event, *tmp;
284 
285 	if (list_empty(cb_list))
286 		return;
287 
288 	vq = &__get_cpu_var(virt_cpu_timer);
289 
290 	list_for_each_entry_safe(event, tmp, cb_list, entry) {
291 		list_del_init(&event->entry);
292 		(event->function)(event->data);
293 		if (event->interval) {
294 			/* Recharge interval timer */
295 			event->expires = event->interval + vq->elapsed;
296 			spin_lock(&vq->lock);
297 			list_add_sorted(event, &vq->list);
298 			spin_unlock(&vq->lock);
299 		}
300 	}
301 }
302 
303 /*
304  * Handler for the virtual CPU timer.
305  */
306 static void do_cpu_timer_interrupt(__u16 error_code)
307 {
308 	struct vtimer_queue *vq;
309 	struct vtimer_list *event, *tmp;
310 	struct list_head cb_list;	/* the callback queue */
311 	__u64 elapsed, next;
312 
313 	INIT_LIST_HEAD(&cb_list);
314 	vq = &__get_cpu_var(virt_cpu_timer);
315 
316 	/* walk timer list, fire all expired events */
317 	spin_lock(&vq->lock);
318 
319 	elapsed = vq->elapsed + (vq->timer - S390_lowcore.async_enter_timer);
320 	BUG_ON((s64) elapsed < 0);
321 	vq->elapsed = 0;
322 	list_for_each_entry_safe(event, tmp, &vq->list, entry) {
323 		if (event->expires < elapsed)
324 			/* move expired timer to the callback queue */
325 			list_move_tail(&event->entry, &cb_list);
326 		else
327 			event->expires -= elapsed;
328 	}
329 	spin_unlock(&vq->lock);
330 
331 	vq->do_spt = list_empty(&cb_list);
332 	do_callbacks(&cb_list);
333 
334 	/* next event is first in list */
335 	next = VTIMER_MAX_SLICE;
336 	spin_lock(&vq->lock);
337 	if (!list_empty(&vq->list)) {
338 		event = list_first_entry(&vq->list, struct vtimer_list, entry);
339 		next = event->expires;
340 	} else
341 		vq->do_spt = 0;
342 	spin_unlock(&vq->lock);
343 	/*
344 	 * To improve precision add the time spent by the
345 	 * interrupt handler to the elapsed time.
346 	 * Note: CPU timer counts down and we got an interrupt,
347 	 *	 the current content is negative
348 	 */
349 	elapsed = S390_lowcore.async_enter_timer - get_vtimer();
350 	set_vtimer(next - elapsed);
351 	vq->timer = next - elapsed;
352 	vq->elapsed = elapsed;
353 }
354 
355 void init_virt_timer(struct vtimer_list *timer)
356 {
357 	timer->function = NULL;
358 	INIT_LIST_HEAD(&timer->entry);
359 }
360 EXPORT_SYMBOL(init_virt_timer);
361 
362 static inline int vtimer_pending(struct vtimer_list *timer)
363 {
364 	return (!list_empty(&timer->entry));
365 }
366 
367 /*
368  * this function should only run on the specified CPU
369  */
370 static void internal_add_vtimer(struct vtimer_list *timer)
371 {
372 	struct vtimer_queue *vq;
373 	unsigned long flags;
374 	__u64 left, expires;
375 
376 	vq = &per_cpu(virt_cpu_timer, timer->cpu);
377 	spin_lock_irqsave(&vq->lock, flags);
378 
379 	BUG_ON(timer->cpu != smp_processor_id());
380 
381 	if (list_empty(&vq->list)) {
382 		/* First timer on this cpu, just program it. */
383 		list_add(&timer->entry, &vq->list);
384 		set_vtimer(timer->expires);
385 		vq->timer = timer->expires;
386 		vq->elapsed = 0;
387 	} else {
388 		/* Check progress of old timers. */
389 		expires = timer->expires;
390 		left = get_vtimer();
391 		if (likely((s64) expires < (s64) left)) {
392 			/* The new timer expires before the current timer. */
393 			set_vtimer(expires);
394 			vq->elapsed += vq->timer - left;
395 			vq->timer = expires;
396 		} else {
397 			vq->elapsed += vq->timer - left;
398 			vq->timer = left;
399 		}
400 		/* Insert new timer into per cpu list. */
401 		timer->expires += vq->elapsed;
402 		list_add_sorted(timer, &vq->list);
403 	}
404 
405 	spin_unlock_irqrestore(&vq->lock, flags);
406 	/* release CPU acquired in prepare_vtimer or mod_virt_timer() */
407 	put_cpu();
408 }
409 
410 static inline void prepare_vtimer(struct vtimer_list *timer)
411 {
412 	BUG_ON(!timer->function);
413 	BUG_ON(!timer->expires || timer->expires > VTIMER_MAX_SLICE);
414 	BUG_ON(vtimer_pending(timer));
415 	timer->cpu = get_cpu();
416 }
417 
418 /*
419  * add_virt_timer - add an oneshot virtual CPU timer
420  */
421 void add_virt_timer(void *new)
422 {
423 	struct vtimer_list *timer;
424 
425 	timer = (struct vtimer_list *)new;
426 	prepare_vtimer(timer);
427 	timer->interval = 0;
428 	internal_add_vtimer(timer);
429 }
430 EXPORT_SYMBOL(add_virt_timer);
431 
432 /*
433  * add_virt_timer_int - add an interval virtual CPU timer
434  */
435 void add_virt_timer_periodic(void *new)
436 {
437 	struct vtimer_list *timer;
438 
439 	timer = (struct vtimer_list *)new;
440 	prepare_vtimer(timer);
441 	timer->interval = timer->expires;
442 	internal_add_vtimer(timer);
443 }
444 EXPORT_SYMBOL(add_virt_timer_periodic);
445 
446 int __mod_vtimer(struct vtimer_list *timer, __u64 expires, int periodic)
447 {
448 	struct vtimer_queue *vq;
449 	unsigned long flags;
450 	int cpu;
451 
452 	BUG_ON(!timer->function);
453 	BUG_ON(!expires || expires > VTIMER_MAX_SLICE);
454 
455 	if (timer->expires == expires && vtimer_pending(timer))
456 		return 1;
457 
458 	cpu = get_cpu();
459 	vq = &per_cpu(virt_cpu_timer, cpu);
460 
461 	/* disable interrupts before test if timer is pending */
462 	spin_lock_irqsave(&vq->lock, flags);
463 
464 	/* if timer isn't pending add it on the current CPU */
465 	if (!vtimer_pending(timer)) {
466 		spin_unlock_irqrestore(&vq->lock, flags);
467 
468 		if (periodic)
469 			timer->interval = expires;
470 		else
471 			timer->interval = 0;
472 		timer->expires = expires;
473 		timer->cpu = cpu;
474 		internal_add_vtimer(timer);
475 		return 0;
476 	}
477 
478 	/* check if we run on the right CPU */
479 	BUG_ON(timer->cpu != cpu);
480 
481 	list_del_init(&timer->entry);
482 	timer->expires = expires;
483 	if (periodic)
484 		timer->interval = expires;
485 
486 	/* the timer can't expire anymore so we can release the lock */
487 	spin_unlock_irqrestore(&vq->lock, flags);
488 	internal_add_vtimer(timer);
489 	return 1;
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  */
498 int mod_virt_timer(struct vtimer_list *timer, __u64 expires)
499 {
500 	return __mod_vtimer(timer, expires, 0);
501 }
502 EXPORT_SYMBOL(mod_virt_timer);
503 
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  */
510 int mod_virt_timer_periodic(struct vtimer_list *timer, __u64 expires)
511 {
512 	return __mod_vtimer(timer, expires, 1);
513 }
514 EXPORT_SYMBOL(mod_virt_timer_periodic);
515 
516 /*
517  * delete a virtual timer
518  *
519  * returns whether the deleted timer was pending (1) or not (0)
520  */
521 int del_virt_timer(struct vtimer_list *timer)
522 {
523 	unsigned long flags;
524 	struct vtimer_queue *vq;
525 
526 	/* check if timer is pending */
527 	if (!vtimer_pending(timer))
528 		return 0;
529 
530 	vq = &per_cpu(virt_cpu_timer, timer->cpu);
531 	spin_lock_irqsave(&vq->lock, flags);
532 
533 	/* we don't interrupt a running timer, just let it expire! */
534 	list_del_init(&timer->entry);
535 
536 	spin_unlock_irqrestore(&vq->lock, flags);
537 	return 1;
538 }
539 EXPORT_SYMBOL(del_virt_timer);
540 
541 /*
542  * Start the virtual CPU timer on the current CPU.
543  */
544 void init_cpu_vtimer(void)
545 {
546 	struct vtimer_queue *vq;
547 
548 	/* initialize per cpu vtimer structure */
549 	vq = &__get_cpu_var(virt_cpu_timer);
550 	INIT_LIST_HEAD(&vq->list);
551 	spin_lock_init(&vq->lock);
552 
553 	/* enable cpu timer interrupts */
554 	__ctl_set_bit(0,10);
555 }
556 
557 void __init vtime_init(void)
558 {
559 	/* request the cpu timer external interrupt */
560 	if (register_early_external_interrupt(0x1005, do_cpu_timer_interrupt,
561 					      &ext_int_info_timer) != 0)
562 		panic("Couldn't request external interrupt 0x1005");
563 
564 	/* Enable cpu timer interrupts on the boot cpu. */
565 	init_cpu_vtimer();
566 }
567 
568