Merge branch 'cputime' of git://git390.osdl.marist.edu/pub/scm/linux-2.6

* 'cputime' of git://git390.osdl.marist.edu/pub/scm/linux-2.6:
[PATCH] fast vdso implementation for CLOCK_THREAD_CPUTIME_ID
[PATCH] improve idle cputime accounting
[PATCH] improve precision of idle time detection.
[PATCH] improve precision of process accounting.
[PATCH] idle cputime accounting
[PATCH] fix scaled & unscaled cputime accounting

+691 -464
+10 -8
arch/ia64/kernel/time.c
··· 93 93 now = ia64_get_itc(); 94 94 95 95 delta_stime = cycle_to_cputime(pi->ac_stime + (now - pi->ac_stamp)); 96 - account_system_time(prev, 0, delta_stime); 97 - account_system_time_scaled(prev, delta_stime); 96 + if (idle_task(smp_processor_id()) != prev) 97 + account_system_time(prev, 0, delta_stime, delta_stime); 98 + else 99 + account_idle_time(delta_stime); 98 100 99 101 if (pi->ac_utime) { 100 102 delta_utime = cycle_to_cputime(pi->ac_utime); 101 - account_user_time(prev, delta_utime); 102 - account_user_time_scaled(prev, delta_utime); 103 + account_user_time(prev, delta_utime, delta_utime); 103 104 } 104 105 105 106 pi->ac_stamp = ni->ac_stamp = now; ··· 123 122 now = ia64_get_itc(); 124 123 125 124 delta_stime = cycle_to_cputime(ti->ac_stime + (now - ti->ac_stamp)); 126 - account_system_time(tsk, 0, delta_stime); 127 - account_system_time_scaled(tsk, delta_stime); 125 + if (irq_count() || idle_task(smp_processor_id()) != tsk) 126 + account_system_time(tsk, 0, delta_stime, delta_stime); 127 + else 128 + account_idle_time(delta_stime); 128 129 ti->ac_stime = 0; 129 130 130 131 ti->ac_stamp = now; ··· 146 143 147 144 if (ti->ac_utime) { 148 145 delta_utime = cycle_to_cputime(ti->ac_utime); 149 - account_user_time(p, delta_utime); 150 - account_user_time_scaled(p, delta_utime); 146 + account_user_time(p, delta_utime, delta_utime); 151 147 ti->ac_utime = 0; 152 148 } 153 149 }
+1
arch/powerpc/kernel/process.c
··· 33 33 #include <linux/mqueue.h> 34 34 #include <linux/hardirq.h> 35 35 #include <linux/utsname.h> 36 + #include <linux/kernel_stat.h> 36 37 37 38 #include <asm/pgtable.h> 38 39 #include <asm/uaccess.h>
+11 -7
arch/powerpc/kernel/time.c
··· 256 256 delta += sys_time; 257 257 get_paca()->system_time = 0; 258 258 } 259 - account_system_time(tsk, 0, delta); 260 - account_system_time_scaled(tsk, deltascaled); 259 + if (in_irq() || idle_task(smp_processor_id()) != tsk) 260 + account_system_time(tsk, 0, delta, deltascaled); 261 + else 262 + account_idle_time(delta); 261 263 per_cpu(cputime_last_delta, smp_processor_id()) = delta; 262 264 per_cpu(cputime_scaled_last_delta, smp_processor_id()) = deltascaled; 263 265 local_irq_restore(flags); ··· 277 275 278 276 utime = get_paca()->user_time; 279 277 get_paca()->user_time = 0; 280 - account_user_time(tsk, utime); 281 - 282 278 utimescaled = cputime_to_scaled(utime); 283 - account_user_time_scaled(tsk, utimescaled); 279 + account_user_time(tsk, utime, utimescaled); 284 280 } 285 281 286 282 /* ··· 338 338 tb = mftb(); 339 339 purr = mfspr(SPRN_PURR); 340 340 stolen = (tb - pme->tb) - (purr - pme->purr); 341 - if (stolen > 0) 342 - account_steal_time(current, stolen); 341 + if (stolen > 0) { 342 + if (idle_task(smp_processor_id()) != current) 343 + account_steal_time(stolen); 344 + else 345 + account_idle_time(stolen); 346 + } 343 347 pme->tb = tb; 344 348 pme->purr = purr; 345 349 }
+3 -4
arch/s390/include/asm/cpu.h
··· 14 14 15 15 struct s390_idle_data { 16 16 spinlock_t lock; 17 - unsigned int in_idle; 18 17 unsigned long long idle_count; 19 18 unsigned long long idle_enter; 20 19 unsigned long long idle_time; ··· 21 22 22 23 DECLARE_PER_CPU(struct s390_idle_data, s390_idle); 23 24 24 - void s390_idle_leave(void); 25 + void vtime_start_cpu(void); 25 26 26 27 static inline void s390_idle_check(void) 27 28 { 28 - if ((&__get_cpu_var(s390_idle))->in_idle) 29 - s390_idle_leave(); 29 + if ((&__get_cpu_var(s390_idle))->idle_enter != 0ULL) 30 + vtime_start_cpu(); 30 31 } 31 32 32 33 #endif /* _ASM_S390_CPU_H_ */
+21 -21
arch/s390/include/asm/cputime.h
··· 11 11 12 12 #include <asm/div64.h> 13 13 14 - /* We want to use micro-second resolution. */ 14 + /* We want to use full resolution of the CPU timer: 2**-12 micro-seconds. */ 15 15 16 16 typedef unsigned long long cputime_t; 17 17 typedef unsigned long long cputime64_t; ··· 53 53 #define cputime_ge(__a, __b) ((__a) >= (__b)) 54 54 #define cputime_lt(__a, __b) ((__a) < (__b)) 55 55 #define cputime_le(__a, __b) ((__a) <= (__b)) 56 - #define cputime_to_jiffies(__ct) (__div((__ct), 1000000 / HZ)) 56 + #define cputime_to_jiffies(__ct) (__div((__ct), 4096000000ULL / HZ)) 57 57 #define cputime_to_scaled(__ct) (__ct) 58 - #define jiffies_to_cputime(__hz) ((cputime_t)(__hz) * (1000000 / HZ)) 58 + #define jiffies_to_cputime(__hz) ((cputime_t)(__hz) * (4096000000ULL / HZ)) 59 59 60 60 #define cputime64_zero (0ULL) 61 61 #define cputime64_add(__a, __b) ((__a) + (__b)) ··· 64 64 static inline u64 65 65 cputime64_to_jiffies64(cputime64_t cputime) 66 66 { 67 - do_div(cputime, 1000000 / HZ); 67 + do_div(cputime, 4096000000ULL / HZ); 68 68 return cputime; 69 69 } 70 70 ··· 74 74 static inline unsigned int 75 75 cputime_to_msecs(const cputime_t cputime) 76 76 { 77 - return __div(cputime, 1000); 77 + return __div(cputime, 4096000); 78 78 } 79 79 80 80 static inline cputime_t 81 81 msecs_to_cputime(const unsigned int m) 82 82 { 83 - return (cputime_t) m * 1000; 83 + return (cputime_t) m * 4096000; 84 84 } 85 85 86 86 /* ··· 89 89 static inline unsigned int 90 90 cputime_to_secs(const cputime_t cputime) 91 91 { 92 - return __div(cputime, 1000000); 92 + return __div(cputime, 2048000000) >> 1; 93 93 } 94 94 95 95 static inline cputime_t 96 96 secs_to_cputime(const unsigned int s) 97 97 { 98 - return (cputime_t) s * 1000000; 98 + return (cputime_t) s * 4096000000ULL; 99 99 } 100 100 101 101 /* ··· 104 104 static inline cputime_t 105 105 timespec_to_cputime(const struct timespec *value) 106 106 { 107 - return value->tv_nsec / 1000 + (u64) value->tv_sec * 1000000; 107 + return value->tv_nsec * 4096 / 1000 + (u64) value->tv_sec * 4096000000ULL; 108 108 } 109 109 110 110 static inline void ··· 114 114 register_pair rp; 115 115 116 116 rp.pair = cputime >> 1; 117 - asm ("dr %0,%1" : "+d" (rp) : "d" (1000000 >> 1)); 118 - value->tv_nsec = rp.subreg.even * 1000; 117 + asm ("dr %0,%1" : "+d" (rp) : "d" (2048000000UL)); 118 + value->tv_nsec = rp.subreg.even * 1000 / 4096; 119 119 value->tv_sec = rp.subreg.odd; 120 120 #else 121 - value->tv_nsec = (cputime % 1000000) * 1000; 122 - value->tv_sec = cputime / 1000000; 121 + value->tv_nsec = (cputime % 4096000000ULL) * 1000 / 4096; 122 + value->tv_sec = cputime / 4096000000ULL; 123 123 #endif 124 124 } 125 125 ··· 131 131 static inline cputime_t 132 132 timeval_to_cputime(const struct timeval *value) 133 133 { 134 - return value->tv_usec + (u64) value->tv_sec * 1000000; 134 + return value->tv_usec * 4096 + (u64) value->tv_sec * 4096000000ULL; 135 135 } 136 136 137 137 static inline void ··· 141 141 register_pair rp; 142 142 143 143 rp.pair = cputime >> 1; 144 - asm ("dr %0,%1" : "+d" (rp) : "d" (1000000 >> 1)); 145 - value->tv_usec = rp.subreg.even; 144 + asm ("dr %0,%1" : "+d" (rp) : "d" (2048000000UL)); 145 + value->tv_usec = rp.subreg.even / 4096; 146 146 value->tv_sec = rp.subreg.odd; 147 147 #else 148 - value->tv_usec = cputime % 1000000; 149 - value->tv_sec = cputime / 1000000; 148 + value->tv_usec = cputime % 4096000000ULL; 149 + value->tv_sec = cputime / 4096000000ULL; 150 150 #endif 151 151 } 152 152 ··· 156 156 static inline clock_t 157 157 cputime_to_clock_t(cputime_t cputime) 158 158 { 159 - return __div(cputime, 1000000 / USER_HZ); 159 + return __div(cputime, 4096000000ULL / USER_HZ); 160 160 } 161 161 162 162 static inline cputime_t 163 163 clock_t_to_cputime(unsigned long x) 164 164 { 165 - return (cputime_t) x * (1000000 / USER_HZ); 165 + return (cputime_t) x * (4096000000ULL / USER_HZ); 166 166 } 167 167 168 168 /* ··· 171 171 static inline clock_t 172 172 cputime64_to_clock_t(cputime64_t cputime) 173 173 { 174 - return __div(cputime, 1000000 / USER_HZ); 174 + return __div(cputime, 4096000000ULL / USER_HZ); 175 175 } 176 176 177 177 #endif /* _S390_CPUTIME_H */
+28 -21
arch/s390/include/asm/lowcore.h
··· 67 67 #define __LC_SYNC_ENTER_TIMER 0x248 68 68 #define __LC_ASYNC_ENTER_TIMER 0x250 69 69 #define __LC_EXIT_TIMER 0x258 70 - #define __LC_LAST_UPDATE_TIMER 0x260 71 - #define __LC_USER_TIMER 0x268 72 - #define __LC_SYSTEM_TIMER 0x270 73 - #define __LC_LAST_UPDATE_CLOCK 0x278 74 - #define __LC_STEAL_CLOCK 0x280 70 + #define __LC_USER_TIMER 0x260 71 + #define __LC_SYSTEM_TIMER 0x268 72 + #define __LC_STEAL_TIMER 0x270 73 + #define __LC_LAST_UPDATE_TIMER 0x278 74 + #define __LC_LAST_UPDATE_CLOCK 0x280 75 75 #define __LC_RETURN_MCCK_PSW 0x288 76 76 #define __LC_KERNEL_STACK 0xC40 77 77 #define __LC_THREAD_INFO 0xC44 ··· 89 89 #define __LC_SYNC_ENTER_TIMER 0x250 90 90 #define __LC_ASYNC_ENTER_TIMER 0x258 91 91 #define __LC_EXIT_TIMER 0x260 92 - #define __LC_LAST_UPDATE_TIMER 0x268 93 - #define __LC_USER_TIMER 0x270 94 - #define __LC_SYSTEM_TIMER 0x278 95 - #define __LC_LAST_UPDATE_CLOCK 0x280 96 - #define __LC_STEAL_CLOCK 0x288 92 + #define __LC_USER_TIMER 0x268 93 + #define __LC_SYSTEM_TIMER 0x270 94 + #define __LC_STEAL_TIMER 0x278 95 + #define __LC_LAST_UPDATE_TIMER 0x280 96 + #define __LC_LAST_UPDATE_CLOCK 0x288 97 97 #define __LC_RETURN_MCCK_PSW 0x290 98 98 #define __LC_KERNEL_STACK 0xD40 99 99 #define __LC_THREAD_INFO 0xD48 ··· 106 106 #define __LC_IPLDEV 0xDB8 107 107 #define __LC_CURRENT 0xDD8 108 108 #define __LC_INT_CLOCK 0xDE8 109 + #define __LC_VDSO_PER_CPU 0xE38 109 110 #endif /* __s390x__ */ 110 111 112 + #define __LC_PASTE 0xE40 111 113 112 114 #define __LC_PANIC_MAGIC 0xE00 113 115 #ifndef __s390x__ ··· 254 252 __u64 sync_enter_timer; /* 0x248 */ 255 253 __u64 async_enter_timer; /* 0x250 */ 256 254 __u64 exit_timer; /* 0x258 */ 257 - __u64 last_update_timer; /* 0x260 */ 258 - __u64 user_timer; /* 0x268 */ 259 - __u64 system_timer; /* 0x270 */ 260 - __u64 last_update_clock; /* 0x278 */ 261 - __u64 steal_clock; /* 0x280 */ 255 + __u64 user_timer; /* 0x260 */ 256 + __u64 system_timer; /* 0x268 */ 257 + __u64 steal_timer; /* 0x270 */ 258 + __u64 last_update_timer; /* 0x278 */ 259 + __u64 last_update_clock; /* 0x280 */ 262 260 psw_t return_mcck_psw; /* 0x288 */ 263 261 __u8 pad8[0xc00-0x290]; /* 0x290 */ 264 262 ··· 345 343 __u64 sync_enter_timer; /* 0x250 */ 346 344 __u64 async_enter_timer; /* 0x258 */ 347 345 __u64 exit_timer; /* 0x260 */ 348 - __u64 last_update_timer; /* 0x268 */ 349 - __u64 user_timer; /* 0x270 */ 350 - __u64 system_timer; /* 0x278 */ 351 - __u64 last_update_clock; /* 0x280 */ 352 - __u64 steal_clock; /* 0x288 */ 346 + __u64 user_timer; /* 0x268 */ 347 + __u64 system_timer; /* 0x270 */ 348 + __u64 steal_timer; /* 0x278 */ 349 + __u64 last_update_timer; /* 0x280 */ 350 + __u64 last_update_clock; /* 0x288 */ 353 351 psw_t return_mcck_psw; /* 0x290 */ 354 352 __u8 pad8[0xc00-0x2a0]; /* 0x2a0 */ 355 353 /* System info area */ ··· 383 381 /* whether the kernel died with panic() or not */ 384 382 __u32 panic_magic; /* 0xe00 */ 385 383 386 - __u8 pad13[0x11b8-0xe04]; /* 0xe04 */ 384 + /* Per cpu primary space access list */ 385 + __u8 pad_0xe04[0xe3c-0xe04]; /* 0xe04 */ 386 + __u32 vdso_per_cpu_data; /* 0xe3c */ 387 + __u32 paste[16]; /* 0xe40 */ 388 + 389 + __u8 pad13[0x11b8-0xe80]; /* 0xe80 */ 387 390 388 391 /* 64 bit extparam used for pfault, diag 250 etc */ 389 392 __u64 ext_params2; /* 0x11B8 */
+2 -2
arch/s390/include/asm/system.h
··· 99 99 prev = __switch_to(prev,next); \ 100 100 } while (0) 101 101 102 - extern void account_vtime(struct task_struct *); 102 + extern void account_vtime(struct task_struct *, struct task_struct *); 103 103 extern void account_tick_vtime(struct task_struct *); 104 104 extern void account_system_vtime(struct task_struct *); 105 105 ··· 121 121 122 122 #define finish_arch_switch(prev) do { \ 123 123 set_fs(current->thread.mm_segment); \ 124 - account_vtime(prev); \ 124 + account_vtime(prev, current); \ 125 125 } while (0) 126 126 127 127 #define nop() asm volatile("nop")
+2
arch/s390/include/asm/thread_info.h
··· 47 47 unsigned int cpu; /* current CPU */ 48 48 int preempt_count; /* 0 => preemptable, <0 => BUG */ 49 49 struct restart_block restart_block; 50 + __u64 user_timer; 51 + __u64 system_timer; 50 52 }; 51 53 52 54 /*
+7 -9
arch/s390/include/asm/timer.h
··· 23 23 __u64 expires; 24 24 __u64 interval; 25 25 26 - spinlock_t lock; 27 - unsigned long magic; 28 - 29 26 void (*function)(unsigned long); 30 27 unsigned long data; 31 28 }; 32 29 33 - /* the offset value will wrap after ca. 71 years */ 30 + /* the vtimer value will wrap after ca. 71 years */ 34 31 struct vtimer_queue { 35 32 struct list_head list; 36 33 spinlock_t lock; 37 - __u64 to_expire; /* current event expire time */ 38 - __u64 offset; /* list offset to zero */ 39 - __u64 idle; /* temp var for idle */ 34 + __u64 timer; /* last programmed timer */ 35 + __u64 elapsed; /* elapsed time of timer expire values */ 36 + __u64 idle; /* temp var for idle */ 37 + int do_spt; /* =1: reprogram cpu timer in idle */ 40 38 }; 41 39 42 40 extern void init_virt_timer(struct vtimer_list *timer); ··· 46 48 extern void init_cpu_vtimer(void); 47 49 extern void vtime_init(void); 48 50 49 - extern void vtime_start_cpu_timer(void); 50 - extern void vtime_stop_cpu_timer(void); 51 + extern void vtime_stop_cpu(void); 52 + extern void vtime_start_leave(void); 51 53 52 54 #endif /* __KERNEL__ */ 53 55
+13 -2
arch/s390/include/asm/vdso.h
··· 12 12 #ifndef __ASSEMBLY__ 13 13 14 14 /* 15 - * Note about this structure: 15 + * Note about the vdso_data and vdso_per_cpu_data structures: 16 16 * 17 - * NEVER USE THIS IN USERSPACE CODE DIRECTLY. The layout of this 17 + * NEVER USE THEM IN USERSPACE CODE DIRECTLY. The layout of the 18 18 * structure is supposed to be known only to the function in the vdso 19 19 * itself and may change without notice. 20 20 */ ··· 28 28 __u64 wtom_clock_nsec; /* 0x28 */ 29 29 __u32 tz_minuteswest; /* Minutes west of Greenwich 0x30 */ 30 30 __u32 tz_dsttime; /* Type of dst correction 0x34 */ 31 + __u32 ectg_available; 32 + }; 33 + 34 + struct vdso_per_cpu_data { 35 + __u64 ectg_timer_base; 36 + __u64 ectg_user_time; 31 37 }; 32 38 33 39 extern struct vdso_data *vdso_data; 40 + 41 + #ifdef CONFIG_64BIT 42 + int vdso_alloc_per_cpu(int cpu, struct _lowcore *lowcore); 43 + void vdso_free_per_cpu(int cpu, struct _lowcore *lowcore); 44 + #endif 34 45 35 46 #endif /* __ASSEMBLY__ */ 36 47
+5
arch/s390/kernel/asm-offsets.c
··· 48 48 DEFINE(__VDSO_WTOM_SEC, offsetof(struct vdso_data, wtom_clock_sec)); 49 49 DEFINE(__VDSO_WTOM_NSEC, offsetof(struct vdso_data, wtom_clock_nsec)); 50 50 DEFINE(__VDSO_TIMEZONE, offsetof(struct vdso_data, tz_minuteswest)); 51 + DEFINE(__VDSO_ECTG_OK, offsetof(struct vdso_data, ectg_available)); 52 + DEFINE(__VDSO_ECTG_BASE, 53 + offsetof(struct vdso_per_cpu_data, ectg_timer_base)); 54 + DEFINE(__VDSO_ECTG_USER, 55 + offsetof(struct vdso_per_cpu_data, ectg_user_time)); 51 56 /* constants used by the vdso */ 52 57 DEFINE(CLOCK_REALTIME, CLOCK_REALTIME); 53 58 DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC);
+3 -2
arch/s390/kernel/entry.S
··· 583 583 584 584 .globl io_int_handler 585 585 io_int_handler: 586 - stpt __LC_ASYNC_ENTER_TIMER 587 586 stck __LC_INT_CLOCK 587 + stpt __LC_ASYNC_ENTER_TIMER 588 588 SAVE_ALL_BASE __LC_SAVE_AREA+16 589 589 SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+16 590 590 CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+16 ··· 723 723 724 724 .globl ext_int_handler 725 725 ext_int_handler: 726 - stpt __LC_ASYNC_ENTER_TIMER 727 726 stck __LC_INT_CLOCK 727 + stpt __LC_ASYNC_ENTER_TIMER 728 728 SAVE_ALL_BASE __LC_SAVE_AREA+16 729 729 SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16 730 730 CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+16 ··· 750 750 751 751 .globl mcck_int_handler 752 752 mcck_int_handler: 753 + stck __LC_INT_CLOCK 753 754 spt __LC_CPU_TIMER_SAVE_AREA # revalidate cpu timer 754 755 lm %r0,%r15,__LC_GPREGS_SAVE_AREA # revalidate gprs 755 756 SAVE_ALL_BASE __LC_SAVE_AREA+32
+27 -23
arch/s390/kernel/entry64.S
··· 177 177 .if !\sync 178 178 ni \psworg+1,0xfd # clear wait state bit 179 179 .endif 180 - lmg %r0,%r15,SP_R0(%r15) # load gprs 0-15 of user 180 + lg %r14,__LC_VDSO_PER_CPU 181 + lmg %r0,%r13,SP_R0(%r15) # load gprs 0-13 of user 181 182 stpt __LC_EXIT_TIMER 183 + mvc __VDSO_ECTG_BASE(16,%r14),__LC_EXIT_TIMER 184 + lmg %r14,%r15,SP_R14(%r15) # load grps 14-15 of user 182 185 lpswe \psworg # back to caller 183 186 .endm 184 187 ··· 562 559 */ 563 560 .globl io_int_handler 564 561 io_int_handler: 565 - stpt __LC_ASYNC_ENTER_TIMER 566 562 stck __LC_INT_CLOCK 563 + stpt __LC_ASYNC_ENTER_TIMER 567 564 SAVE_ALL_BASE __LC_SAVE_AREA+32 568 565 SAVE_ALL_ASYNC __LC_IO_OLD_PSW,__LC_SAVE_AREA+32 569 566 CREATE_STACK_FRAME __LC_IO_OLD_PSW,__LC_SAVE_AREA+32 ··· 724 721 */ 725 722 .globl ext_int_handler 726 723 ext_int_handler: 727 - stpt __LC_ASYNC_ENTER_TIMER 728 724 stck __LC_INT_CLOCK 725 + stpt __LC_ASYNC_ENTER_TIMER 729 726 SAVE_ALL_BASE __LC_SAVE_AREA+32 730 727 SAVE_ALL_ASYNC __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32 731 728 CREATE_STACK_FRAME __LC_EXT_OLD_PSW,__LC_SAVE_AREA+32 ··· 749 746 */ 750 747 .globl mcck_int_handler 751 748 mcck_int_handler: 749 + stck __LC_INT_CLOCK 752 750 la %r1,4095 # revalidate r1 753 751 spt __LC_CPU_TIMER_SAVE_AREA-4095(%r1) # revalidate cpu timer 754 752 lmg %r0,%r15,__LC_GPREGS_SAVE_AREA-4095(%r1)# revalidate gprs ··· 983 979 984 980 cleanup_sysc_leave: 985 981 clc 8(8,%r12),BASED(cleanup_sysc_leave_insn) 986 - je 2f 987 - mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER 982 + je 3f 988 983 clc 8(8,%r12),BASED(cleanup_sysc_leave_insn+8) 989 - je 2f 990 - mvc __LC_RETURN_PSW(16),SP_PSW(%r15) 984 + jhe 0f 985 + mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER 986 + 0: mvc __LC_RETURN_PSW(16),SP_PSW(%r15) 991 987 cghi %r12,__LC_MCK_OLD_PSW 992 - jne 0f 988 + jne 1f 993 989 mvc __LC_SAVE_AREA+64(32),SP_R12(%r15) 994 - j 1f 995 - 0: mvc __LC_SAVE_AREA+32(32),SP_R12(%r15) 996 - 1: lmg %r0,%r11,SP_R0(%r15) 990 + j 2f 991 + 1: mvc __LC_SAVE_AREA+32(32),SP_R12(%r15) 992 + 2: lmg %r0,%r11,SP_R0(%r15) 997 993 lg %r15,SP_R15(%r15) 998 - 2: la %r12,__LC_RETURN_PSW 994 + 3: la %r12,__LC_RETURN_PSW 999 995 br %r14 1000 996 cleanup_sysc_leave_insn: 1001 997 .quad sysc_done - 4 1002 - .quad sysc_done - 8 998 + .quad sysc_done - 16 1003 999 1004 1000 cleanup_io_return: 1005 1001 mvc __LC_RETURN_PSW(8),0(%r12) ··· 1009 1005 1010 1006 cleanup_io_leave: 1011 1007 clc 8(8,%r12),BASED(cleanup_io_leave_insn) 1012 - je 2f 1013 - mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER 1008 + je 3f 1014 1009 clc 8(8,%r12),BASED(cleanup_io_leave_insn+8) 1015 - je 2f 1016 - mvc __LC_RETURN_PSW(16),SP_PSW(%r15) 1010 + jhe 0f 1011 + mvc __LC_EXIT_TIMER(8),__LC_ASYNC_ENTER_TIMER 1012 + 0: mvc __LC_RETURN_PSW(16),SP_PSW(%r15) 1017 1013 cghi %r12,__LC_MCK_OLD_PSW 1018 - jne 0f 1014 + jne 1f 1019 1015 mvc __LC_SAVE_AREA+64(32),SP_R12(%r15) 1020 - j 1f 1021 - 0: mvc __LC_SAVE_AREA+32(32),SP_R12(%r15) 1022 - 1: lmg %r0,%r11,SP_R0(%r15) 1016 + j 2f 1017 + 1: mvc __LC_SAVE_AREA+32(32),SP_R12(%r15) 1018 + 2: lmg %r0,%r11,SP_R0(%r15) 1023 1019 lg %r15,SP_R15(%r15) 1024 - 2: la %r12,__LC_RETURN_PSW 1020 + 3: la %r12,__LC_RETURN_PSW 1025 1021 br %r14 1026 1022 cleanup_io_leave_insn: 1027 1023 .quad io_done - 4 1028 - .quad io_done - 8 1024 + .quad io_done - 16 1029 1025 1030 1026 /* 1031 1027 * Integer constants
+2
arch/s390/kernel/head64.S
··· 87 87 lg %r12,.Lparmaddr-.LPG1(%r13) # pointer to parameter area 88 88 # move IPL device to lowcore 89 89 mvc __LC_IPLDEV(4),IPL_DEVICE+4-PARMAREA(%r12) 90 + lghi %r0,__LC_PASTE 91 + stg %r0,__LC_VDSO_PER_CPU 90 92 # 91 93 # Setup stack 92 94 #
+4 -39
arch/s390/kernel/process.c
··· 38 38 #include <linux/utsname.h> 39 39 #include <linux/tick.h> 40 40 #include <linux/elfcore.h> 41 + #include <linux/kernel_stat.h> 41 42 #include <asm/uaccess.h> 42 43 #include <asm/pgtable.h> 43 44 #include <asm/system.h> ··· 46 45 #include <asm/processor.h> 47 46 #include <asm/irq.h> 48 47 #include <asm/timer.h> 49 - #include <asm/cpu.h> 50 48 #include "entry.h" 51 49 52 50 asmlinkage void ret_from_fork(void) asm ("ret_from_fork"); ··· 75 75 return sf->gprs[8]; 76 76 } 77 77 78 - DEFINE_PER_CPU(struct s390_idle_data, s390_idle) = { 79 - .lock = __SPIN_LOCK_UNLOCKED(s390_idle.lock) 80 - }; 81 - 82 - static int s390_idle_enter(void) 83 - { 84 - struct s390_idle_data *idle; 85 - 86 - idle = &__get_cpu_var(s390_idle); 87 - spin_lock(&idle->lock); 88 - idle->idle_count++; 89 - idle->in_idle = 1; 90 - idle->idle_enter = get_clock(); 91 - spin_unlock(&idle->lock); 92 - vtime_stop_cpu_timer(); 93 - return NOTIFY_OK; 94 - } 95 - 96 - void s390_idle_leave(void) 97 - { 98 - struct s390_idle_data *idle; 99 - 100 - vtime_start_cpu_timer(); 101 - idle = &__get_cpu_var(s390_idle); 102 - spin_lock(&idle->lock); 103 - idle->idle_time += get_clock() - idle->idle_enter; 104 - idle->in_idle = 0; 105 - spin_unlock(&idle->lock); 106 - } 107 - 108 78 extern void s390_handle_mcck(void); 109 79 /* 110 80 * The idle loop on a S390... ··· 87 117 local_irq_enable(); 88 118 return; 89 119 } 90 - if (s390_idle_enter() == NOTIFY_BAD) { 91 - local_irq_enable(); 92 - return; 93 - } 94 120 #ifdef CONFIG_HOTPLUG_CPU 95 121 if (cpu_is_offline(smp_processor_id())) { 96 122 preempt_enable_no_resched(); ··· 96 130 local_mcck_disable(); 97 131 if (test_thread_flag(TIF_MCCK_PENDING)) { 98 132 local_mcck_enable(); 99 - s390_idle_leave(); 100 133 local_irq_enable(); 101 134 s390_handle_mcck(); 102 135 return; ··· 103 138 trace_hardirqs_on(); 104 139 /* Don't trace preempt off for idle. */ 105 140 stop_critical_timings(); 106 - /* Wait for external, I/O or machine check interrupt. */ 107 - __load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT | 108 - PSW_MASK_IO | PSW_MASK_EXT); 141 + /* Stop virtual timer and halt the cpu. */ 142 + vtime_stop_cpu(); 143 + /* Reenable preemption tracer. */ 109 144 start_critical_timings(); 110 145 } 111 146
+1 -1
arch/s390/kernel/s390_ext.c
··· 119 119 struct pt_regs *old_regs; 120 120 121 121 old_regs = set_irq_regs(regs); 122 - irq_enter(); 123 122 s390_idle_check(); 123 + irq_enter(); 124 124 if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) 125 125 /* Serve timer interrupts first. */ 126 126 clock_comparator_work();
+2
arch/s390/kernel/setup.c
··· 427 427 /* enable extended save area */ 428 428 __ctl_set_bit(14, 29); 429 429 } 430 + #else 431 + lc->vdso_per_cpu_data = (unsigned long) &lc->paste[0]; 430 432 #endif 431 433 set_prefix((u32)(unsigned long) lc); 432 434 }
+22 -12
arch/s390/kernel/smp.c
··· 47 47 #include <asm/lowcore.h> 48 48 #include <asm/sclp.h> 49 49 #include <asm/cpu.h> 50 + #include <asm/vdso.h> 50 51 #include "entry.h" 51 52 52 53 /* ··· 501 500 goto out; 502 501 lowcore->extended_save_area_addr = (u32) save_area; 503 502 } 503 + #else 504 + if (vdso_alloc_per_cpu(cpu, lowcore)) 505 + goto out; 504 506 #endif 505 507 lowcore_ptr[cpu] = lowcore; 506 508 return 0; ··· 526 522 #ifndef CONFIG_64BIT 527 523 if (MACHINE_HAS_IEEE) 528 524 free_page((unsigned long) lowcore->extended_save_area_addr); 525 + #else 526 + vdso_free_per_cpu(cpu, lowcore); 529 527 #endif 530 528 free_page(lowcore->panic_stack - PAGE_SIZE); 531 529 free_pages(lowcore->async_stack - ASYNC_SIZE, ASYNC_ORDER); ··· 670 664 lowcore = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, lc_order); 671 665 panic_stack = __get_free_page(GFP_KERNEL); 672 666 async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER); 667 + BUG_ON(!lowcore || !panic_stack || !async_stack); 673 668 #ifndef CONFIG_64BIT 674 669 if (MACHINE_HAS_IEEE) 675 670 save_area = get_zeroed_page(GFP_KERNEL); ··· 684 677 #ifndef CONFIG_64BIT 685 678 if (MACHINE_HAS_IEEE) 686 679 lowcore->extended_save_area_addr = (u32) save_area; 680 + #else 681 + BUG_ON(vdso_alloc_per_cpu(smp_processor_id(), lowcore)); 687 682 #endif 688 683 set_prefix((u32)(unsigned long) lowcore); 689 684 local_mcck_enable(); ··· 854 845 unsigned long long idle_count; 855 846 856 847 idle = &per_cpu(s390_idle, dev->id); 857 - spin_lock_irq(&idle->lock); 848 + spin_lock(&idle->lock); 858 849 idle_count = idle->idle_count; 859 - spin_unlock_irq(&idle->lock); 850 + if (idle->idle_enter) 851 + idle_count++; 852 + spin_unlock(&idle->lock); 860 853 return sprintf(buf, "%llu\n", idle_count); 861 854 } 862 855 static SYSDEV_ATTR(idle_count, 0444, show_idle_count, NULL); ··· 867 856 struct sysdev_attribute *attr, char *buf) 868 857 { 869 858 struct s390_idle_data *idle; 870 - unsigned long long new_time; 859 + unsigned long long now, idle_time, idle_enter; 871 860 872 861 idle = &per_cpu(s390_idle, dev->id); 873 - spin_lock_irq(&idle->lock); 874 - if (idle->in_idle) { 875 - new_time = get_clock(); 876 - idle->idle_time += new_time - idle->idle_enter; 877 - idle->idle_enter = new_time; 878 - } 879 - new_time = idle->idle_time; 880 - spin_unlock_irq(&idle->lock); 881 - return sprintf(buf, "%llu\n", new_time >> 12); 862 + spin_lock(&idle->lock); 863 + now = get_clock(); 864 + idle_time = idle->idle_time; 865 + idle_enter = idle->idle_enter; 866 + if (idle_enter != 0ULL && idle_enter < now) 867 + idle_time += now - idle_enter; 868 + spin_unlock(&idle->lock); 869 + return sprintf(buf, "%llu\n", idle_time >> 12); 882 870 } 883 871 static SYSDEV_ATTR(idle_time_us, 0444, show_idle_time, NULL); 884 872
+120 -3
arch/s390/kernel/vdso.c
··· 31 31 #include <asm/sections.h> 32 32 #include <asm/vdso.h> 33 33 34 - /* Max supported size for symbol names */ 35 - #define MAX_SYMNAME 64 36 - 37 34 #if defined(CONFIG_32BIT) || defined(CONFIG_COMPAT) 38 35 extern char vdso32_start, vdso32_end; 39 36 static void *vdso32_kbase = &vdso32_start; ··· 66 69 u8 page[PAGE_SIZE]; 67 70 } vdso_data_store __attribute__((__section__(".data.page_aligned"))); 68 71 struct vdso_data *vdso_data = &vdso_data_store.data; 72 + 73 + /* 74 + * Setup vdso data page. 75 + */ 76 + static void vdso_init_data(struct vdso_data *vd) 77 + { 78 + unsigned int facility_list; 79 + 80 + facility_list = stfl(); 81 + vd->ectg_available = switch_amode && (facility_list & 1); 82 + } 83 + 84 + #ifdef CONFIG_64BIT 85 + /* 86 + * Setup per cpu vdso data page. 87 + */ 88 + static void vdso_init_per_cpu_data(int cpu, struct vdso_per_cpu_data *vpcd) 89 + { 90 + } 91 + 92 + /* 93 + * Allocate/free per cpu vdso data. 94 + */ 95 + #ifdef CONFIG_64BIT 96 + #define SEGMENT_ORDER 2 97 + #else 98 + #define SEGMENT_ORDER 1 99 + #endif 100 + 101 + int vdso_alloc_per_cpu(int cpu, struct _lowcore *lowcore) 102 + { 103 + unsigned long segment_table, page_table, page_frame; 104 + u32 *psal, *aste; 105 + int i; 106 + 107 + lowcore->vdso_per_cpu_data = __LC_PASTE; 108 + 109 + if (!switch_amode || !vdso_enabled) 110 + return 0; 111 + 112 + segment_table = __get_free_pages(GFP_KERNEL, SEGMENT_ORDER); 113 + page_table = get_zeroed_page(GFP_KERNEL | GFP_DMA); 114 + page_frame = get_zeroed_page(GFP_KERNEL); 115 + if (!segment_table || !page_table || !page_frame) 116 + goto out; 117 + 118 + clear_table((unsigned long *) segment_table, _SEGMENT_ENTRY_EMPTY, 119 + PAGE_SIZE << SEGMENT_ORDER); 120 + clear_table((unsigned long *) page_table, _PAGE_TYPE_EMPTY, 121 + 256*sizeof(unsigned long)); 122 + 123 + *(unsigned long *) segment_table = _SEGMENT_ENTRY + page_table; 124 + *(unsigned long *) page_table = _PAGE_RO + page_frame; 125 + 126 + psal = (u32 *) (page_table + 256*sizeof(unsigned long)); 127 + aste = psal + 32; 128 + 129 + for (i = 4; i < 32; i += 4) 130 + psal[i] = 0x80000000; 131 + 132 + lowcore->paste[4] = (u32)(addr_t) psal; 133 + psal[0] = 0x20000000; 134 + psal[2] = (u32)(addr_t) aste; 135 + *(unsigned long *) (aste + 2) = segment_table + 136 + _ASCE_TABLE_LENGTH + _ASCE_USER_BITS + _ASCE_TYPE_SEGMENT; 137 + aste[4] = (u32)(addr_t) psal; 138 + lowcore->vdso_per_cpu_data = page_frame; 139 + 140 + vdso_init_per_cpu_data(cpu, (struct vdso_per_cpu_data *) page_frame); 141 + return 0; 142 + 143 + out: 144 + free_page(page_frame); 145 + free_page(page_table); 146 + free_pages(segment_table, SEGMENT_ORDER); 147 + return -ENOMEM; 148 + } 149 + 150 + #ifdef CONFIG_HOTPLUG_CPU 151 + void vdso_free_per_cpu(int cpu, struct _lowcore *lowcore) 152 + { 153 + unsigned long segment_table, page_table, page_frame; 154 + u32 *psal, *aste; 155 + 156 + if (!switch_amode || !vdso_enabled) 157 + return; 158 + 159 + psal = (u32 *)(addr_t) lowcore->paste[4]; 160 + aste = (u32 *)(addr_t) psal[2]; 161 + segment_table = *(unsigned long *)(aste + 2) & PAGE_MASK; 162 + page_table = *(unsigned long *) segment_table; 163 + page_frame = *(unsigned long *) page_table; 164 + 165 + free_page(page_frame); 166 + free_page(page_table); 167 + free_pages(segment_table, SEGMENT_ORDER); 168 + } 169 + #endif /* CONFIG_HOTPLUG_CPU */ 170 + 171 + static void __vdso_init_cr5(void *dummy) 172 + { 173 + unsigned long cr5; 174 + 175 + cr5 = offsetof(struct _lowcore, paste); 176 + __ctl_load(cr5, 5, 5); 177 + } 178 + 179 + static void vdso_init_cr5(void) 180 + { 181 + if (switch_amode && vdso_enabled) 182 + on_each_cpu(__vdso_init_cr5, NULL, 1); 183 + } 184 + #endif /* CONFIG_64BIT */ 69 185 70 186 /* 71 187 * This is called from binfmt_elf, we create the special vma for the ··· 282 172 { 283 173 int i; 284 174 175 + if (!vdso_enabled) 176 + return 0; 177 + vdso_init_data(vdso_data); 285 178 #if defined(CONFIG_32BIT) || defined(CONFIG_COMPAT) 286 179 /* Calculate the size of the 32 bit vDSO */ 287 180 vdso32_pages = ((&vdso32_end - &vdso32_start ··· 321 208 } 322 209 vdso64_pagelist[vdso64_pages - 1] = virt_to_page(vdso_data); 323 210 vdso64_pagelist[vdso64_pages] = NULL; 211 + #ifndef CONFIG_SMP 212 + BUG_ON(vdso_alloc_per_cpu(0, S390_lowcore)); 213 + #endif 214 + vdso_init_cr5(); 324 215 #endif /* CONFIG_64BIT */ 325 216 326 217 get_page(virt_to_page(vdso_data));
+5
arch/s390/kernel/vdso64/clock_getres.S
··· 22 22 cghi %r2,CLOCK_REALTIME 23 23 je 0f 24 24 cghi %r2,CLOCK_MONOTONIC 25 + je 0f 26 + cghi %r2,-2 /* CLOCK_THREAD_CPUTIME_ID for this thread */ 25 27 jne 2f 28 + larl %r5,_vdso_data 29 + icm %r0,15,__LC_ECTG_OK(%r5) 30 + jz 2f 26 31 0: ltgr %r3,%r3 27 32 jz 1f /* res == NULL */ 28 33 larl %r1,3f
+34 -5
arch/s390/kernel/vdso64/clock_gettime.S
··· 22 22 larl %r5,_vdso_data 23 23 cghi %r2,CLOCK_REALTIME 24 24 je 4f 25 + cghi %r2,-2 /* CLOCK_THREAD_CPUTIME_ID for this thread */ 26 + je 9f 25 27 cghi %r2,CLOCK_MONOTONIC 26 - jne 9f 28 + jne 12f 27 29 28 30 /* CLOCK_MONOTONIC */ 29 31 ltgr %r3,%r3 ··· 44 42 alg %r0,__VDSO_WTOM_SEC(%r5) 45 43 clg %r4,__VDSO_UPD_COUNT(%r5) /* check update counter */ 46 44 jne 0b 47 - larl %r5,10f 45 + larl %r5,13f 48 46 1: clg %r1,0(%r5) 49 47 jl 2f 50 48 slg %r1,0(%r5) ··· 70 68 lg %r0,__VDSO_XTIME_SEC(%r5) 71 69 clg %r4,__VDSO_UPD_COUNT(%r5) /* check update counter */ 72 70 jne 5b 73 - larl %r5,10f 71 + larl %r5,13f 74 72 6: clg %r1,0(%r5) 75 73 jl 7f 76 74 slg %r1,0(%r5) ··· 81 79 8: lghi %r2,0 82 80 br %r14 83 81 82 + /* CLOCK_THREAD_CPUTIME_ID for this thread */ 83 + 9: icm %r0,15,__VDSO_ECTG_OK(%r5) 84 + jz 12f 85 + ear %r2,%a4 86 + llilh %r4,0x0100 87 + sar %a4,%r4 88 + lghi %r4,0 89 + sacf 512 /* Magic ectg instruction */ 90 + .insn ssf,0xc80100000000,__VDSO_ECTG_BASE(4),__VDSO_ECTG_USER(4),4 91 + sacf 0 92 + sar %a4,%r2 93 + algr %r1,%r0 /* r1 = cputime as TOD value */ 94 + mghi %r1,1000 /* convert to nanoseconds */ 95 + srlg %r1,%r1,12 /* r1 = cputime in nanosec */ 96 + lgr %r4,%r1 97 + larl %r5,13f 98 + srlg %r1,%r1,9 /* divide by 1000000000 */ 99 + mlg %r0,8(%r5) 100 + srlg %r0,%r0,11 /* r0 = tv_sec */ 101 + stg %r0,0(%r3) 102 + msg %r0,0(%r5) /* calculate tv_nsec */ 103 + slgr %r4,%r0 /* r4 = tv_nsec */ 104 + stg %r4,8(%r3) 105 + lghi %r2,0 106 + br %r14 107 + 84 108 /* Fallback to system call */ 85 - 9: lghi %r1,__NR_clock_gettime 109 + 12: lghi %r1,__NR_clock_gettime 86 110 svc 0 87 111 br %r14 88 112 89 - 10: .quad 1000000000 113 + 13: .quad 1000000000 114 + 14: .quad 19342813113834067 90 115 .cfi_endproc 91 116 .size __kernel_clock_gettime,.-__kernel_clock_gettime
+270 -232
arch/s390/kernel/vtime.c
··· 23 23 #include <asm/s390_ext.h> 24 24 #include <asm/timer.h> 25 25 #include <asm/irq_regs.h> 26 + #include <asm/cpu.h> 26 27 27 28 static ext_int_info_t ext_int_info_timer; 29 + 28 30 static DEFINE_PER_CPU(struct vtimer_queue, virt_cpu_timer); 29 31 30 - /* 31 - * Update process times based on virtual cpu times stored by entry.S 32 - * to the lowcore fields user_timer, system_timer & steal_clock. 33 - */ 34 - void account_process_tick(struct task_struct *tsk, int user_tick) 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) 35 37 { 36 - cputime_t cputime; 37 - __u64 timer, clock; 38 - int rcu_user_flag; 39 - 40 - timer = S390_lowcore.last_update_timer; 41 - clock = S390_lowcore.last_update_clock; 42 - asm volatile (" STPT %0\n" /* Store current cpu timer value */ 43 - " STCK %1" /* Store current tod clock value */ 44 - : "=m" (S390_lowcore.last_update_timer), 45 - "=m" (S390_lowcore.last_update_clock) ); 46 - S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer; 47 - S390_lowcore.steal_clock += S390_lowcore.last_update_clock - clock; 48 - 49 - cputime = S390_lowcore.user_timer >> 12; 50 - rcu_user_flag = cputime != 0; 51 - S390_lowcore.user_timer -= cputime << 12; 52 - S390_lowcore.steal_clock -= cputime << 12; 53 - account_user_time(tsk, cputime); 54 - 55 - cputime = S390_lowcore.system_timer >> 12; 56 - S390_lowcore.system_timer -= cputime << 12; 57 - S390_lowcore.steal_clock -= cputime << 12; 58 - account_system_time(tsk, HARDIRQ_OFFSET, cputime); 59 - 60 - cputime = S390_lowcore.steal_clock; 61 - if ((__s64) cputime > 0) { 62 - cputime >>= 12; 63 - S390_lowcore.steal_clock -= cputime << 12; 64 - account_steal_time(tsk, cputime); 65 - } 66 - } 67 - 68 - /* 69 - * Update process times based on virtual cpu times stored by entry.S 70 - * to the lowcore fields user_timer, system_timer & steal_clock. 71 - */ 72 - void account_vtime(struct task_struct *tsk) 73 - { 74 - cputime_t cputime; 75 38 __u64 timer; 76 39 77 - timer = S390_lowcore.last_update_timer; 78 - asm volatile (" STPT %0" /* Store current cpu timer value */ 79 - : "=m" (S390_lowcore.last_update_timer) ); 80 - S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer; 81 - 82 - cputime = S390_lowcore.user_timer >> 12; 83 - S390_lowcore.user_timer -= cputime << 12; 84 - S390_lowcore.steal_clock -= cputime << 12; 85 - account_user_time(tsk, cputime); 86 - 87 - cputime = S390_lowcore.system_timer >> 12; 88 - S390_lowcore.system_timer -= cputime << 12; 89 - S390_lowcore.steal_clock -= cputime << 12; 90 - account_system_time(tsk, 0, cputime); 40 + asm volatile("STPT %0" : "=m" (timer)); 41 + return timer; 91 42 } 92 - 93 - /* 94 - * Update process times based on virtual cpu times stored by entry.S 95 - * to the lowcore fields user_timer, system_timer & steal_clock. 96 - */ 97 - void account_system_vtime(struct task_struct *tsk) 98 - { 99 - cputime_t cputime; 100 - __u64 timer; 101 - 102 - timer = S390_lowcore.last_update_timer; 103 - asm volatile (" STPT %0" /* Store current cpu timer value */ 104 - : "=m" (S390_lowcore.last_update_timer) ); 105 - S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer; 106 - 107 - cputime = S390_lowcore.system_timer >> 12; 108 - S390_lowcore.system_timer -= cputime << 12; 109 - S390_lowcore.steal_clock -= cputime << 12; 110 - account_system_time(tsk, 0, cputime); 111 - } 112 - EXPORT_SYMBOL_GPL(account_system_vtime); 113 43 114 44 static inline void set_vtimer(__u64 expires) 115 45 { ··· 50 120 : "=m" (timer) : "m" (expires) ); 51 121 S390_lowcore.system_timer += S390_lowcore.last_update_timer - timer; 52 122 S390_lowcore.last_update_timer = expires; 53 - 54 - /* store expire time for this CPU timer */ 55 - __get_cpu_var(virt_cpu_timer).to_expire = expires; 56 123 } 57 124 58 - void vtime_start_cpu_timer(void) 125 + /* 126 + * Update process times based on virtual cpu times stored by entry.S 127 + * to the lowcore fields user_timer, system_timer & steal_clock. 128 + */ 129 + static void do_account_vtime(struct task_struct *tsk, int hardirq_offset) 59 130 { 60 - struct vtimer_queue *vt_list; 131 + struct thread_info *ti = task_thread_info(tsk); 132 + __u64 timer, clock, user, system, steal; 61 133 62 - vt_list = &__get_cpu_var(virt_cpu_timer); 134 + timer = S390_lowcore.last_update_timer; 135 + clock = S390_lowcore.last_update_clock; 136 + asm volatile (" STPT %0\n" /* Store current cpu timer value */ 137 + " STCK %1" /* Store current tod clock value */ 138 + : "=m" (S390_lowcore.last_update_timer), 139 + "=m" (S390_lowcore.last_update_clock) ); 140 + S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer; 141 + S390_lowcore.steal_timer += S390_lowcore.last_update_clock - clock; 63 142 64 - /* CPU timer interrupt is pending, don't reprogramm it */ 65 - if (vt_list->idle & 1LL<<63) 66 - return; 143 + user = S390_lowcore.user_timer - ti->user_timer; 144 + S390_lowcore.steal_timer -= user; 145 + ti->user_timer = S390_lowcore.user_timer; 146 + account_user_time(tsk, user, user); 67 147 68 - if (!list_empty(&vt_list->list)) 69 - set_vtimer(vt_list->idle); 148 + system = S390_lowcore.system_timer - ti->system_timer; 149 + S390_lowcore.steal_timer -= system; 150 + ti->system_timer = S390_lowcore.system_timer; 151 + account_system_time(tsk, hardirq_offset, system, system); 152 + 153 + steal = S390_lowcore.steal_timer; 154 + if ((s64) steal > 0) { 155 + S390_lowcore.steal_timer = 0; 156 + account_steal_time(steal); 157 + } 70 158 } 71 159 72 - void vtime_stop_cpu_timer(void) 160 + void account_vtime(struct task_struct *prev, struct task_struct *next) 73 161 { 74 - struct vtimer_queue *vt_list; 162 + struct thread_info *ti; 75 163 76 - vt_list = &__get_cpu_var(virt_cpu_timer); 164 + do_account_vtime(prev, 0); 165 + ti = task_thread_info(prev); 166 + ti->user_timer = S390_lowcore.user_timer; 167 + ti->system_timer = S390_lowcore.system_timer; 168 + ti = task_thread_info(next); 169 + S390_lowcore.user_timer = ti->user_timer; 170 + S390_lowcore.system_timer = ti->system_timer; 171 + } 77 172 78 - /* nothing to do */ 79 - if (list_empty(&vt_list->list)) { 80 - vt_list->idle = VTIMER_MAX_SLICE; 81 - goto fire; 173 + void account_process_tick(struct task_struct *tsk, int user_tick) 174 + { 175 + do_account_vtime(tsk, HARDIRQ_OFFSET); 176 + } 177 + 178 + /* 179 + * Update process times based on virtual cpu times stored by entry.S 180 + * to the lowcore fields user_timer, system_timer & steal_clock. 181 + */ 182 + void account_system_vtime(struct task_struct *tsk) 183 + { 184 + struct thread_info *ti = task_thread_info(tsk); 185 + __u64 timer, system; 186 + 187 + timer = S390_lowcore.last_update_timer; 188 + S390_lowcore.last_update_timer = get_vtimer(); 189 + S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer; 190 + 191 + system = S390_lowcore.system_timer - ti->system_timer; 192 + S390_lowcore.steal_timer -= system; 193 + ti->system_timer = S390_lowcore.system_timer; 194 + account_system_time(tsk, 0, system, system); 195 + } 196 + EXPORT_SYMBOL_GPL(account_system_vtime); 197 + 198 + void vtime_start_cpu(void) 199 + { 200 + struct s390_idle_data *idle = &__get_cpu_var(s390_idle); 201 + struct vtimer_queue *vq = &__get_cpu_var(virt_cpu_timer); 202 + __u64 idle_time, expires; 203 + 204 + /* Account time spent with enabled wait psw loaded as idle time. */ 205 + idle_time = S390_lowcore.int_clock - idle->idle_enter; 206 + account_idle_time(idle_time); 207 + S390_lowcore.last_update_clock = S390_lowcore.int_clock; 208 + 209 + /* Account system time spent going idle. */ 210 + S390_lowcore.system_timer += S390_lowcore.last_update_timer - vq->idle; 211 + S390_lowcore.last_update_timer = S390_lowcore.async_enter_timer; 212 + 213 + /* Restart vtime CPU timer */ 214 + if (vq->do_spt) { 215 + /* Program old expire value but first save progress. */ 216 + expires = vq->idle - S390_lowcore.async_enter_timer; 217 + expires += get_vtimer(); 218 + set_vtimer(expires); 219 + } else { 220 + /* Don't account the CPU timer delta while the cpu was idle. */ 221 + vq->elapsed -= vq->idle - S390_lowcore.async_enter_timer; 82 222 } 83 223 84 - /* store the actual expire value */ 85 - asm volatile ("STPT %0" : "=m" (vt_list->idle)); 224 + spin_lock(&idle->lock); 225 + idle->idle_time += idle_time; 226 + idle->idle_enter = 0ULL; 227 + idle->idle_count++; 228 + spin_unlock(&idle->lock); 229 + } 86 230 87 - /* 88 - * If the CPU timer is negative we don't reprogramm 89 - * it because we will get instantly an interrupt. 90 - */ 91 - if (vt_list->idle & 1LL<<63) 92 - return; 231 + void vtime_stop_cpu(void) 232 + { 233 + struct s390_idle_data *idle = &__get_cpu_var(s390_idle); 234 + struct vtimer_queue *vq = &__get_cpu_var(virt_cpu_timer); 235 + psw_t psw; 93 236 94 - vt_list->offset += vt_list->to_expire - vt_list->idle; 237 + /* Wait for external, I/O or machine check interrupt. */ 238 + psw.mask = psw_kernel_bits | PSW_MASK_WAIT | PSW_MASK_IO | PSW_MASK_EXT; 95 239 96 - /* 97 - * We cannot halt the CPU timer, we just write a value that 98 - * nearly never expires (only after 71 years) and re-write 99 - * the stored expire value if we continue the timer 100 - */ 101 - fire: 102 - set_vtimer(VTIMER_MAX_SLICE); 240 + /* Check if the CPU timer needs to be reprogrammed. */ 241 + if (vq->do_spt) { 242 + __u64 vmax = VTIMER_MAX_SLICE; 243 + /* 244 + * The inline assembly is equivalent to 245 + * vq->idle = get_cpu_timer(); 246 + * set_cpu_timer(VTIMER_MAX_SLICE); 247 + * idle->idle_enter = get_clock(); 248 + * __load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT | 249 + * PSW_MASK_IO | PSW_MASK_EXT); 250 + * The difference is that the inline assembly makes sure that 251 + * the last three instruction are stpt, stck and lpsw in that 252 + * order. This is done to increase the precision. 253 + */ 254 + asm volatile( 255 + #ifndef CONFIG_64BIT 256 + " basr 1,0\n" 257 + "0: ahi 1,1f-0b\n" 258 + " st 1,4(%2)\n" 259 + #else /* CONFIG_64BIT */ 260 + " larl 1,1f\n" 261 + " stg 1,8(%2)\n" 262 + #endif /* CONFIG_64BIT */ 263 + " stpt 0(%4)\n" 264 + " spt 0(%5)\n" 265 + " stck 0(%3)\n" 266 + #ifndef CONFIG_64BIT 267 + " lpsw 0(%2)\n" 268 + #else /* CONFIG_64BIT */ 269 + " lpswe 0(%2)\n" 270 + #endif /* CONFIG_64BIT */ 271 + "1:" 272 + : "=m" (idle->idle_enter), "=m" (vq->idle) 273 + : "a" (&psw), "a" (&idle->idle_enter), 274 + "a" (&vq->idle), "a" (&vmax), "m" (vmax), "m" (psw) 275 + : "memory", "cc", "1"); 276 + } else { 277 + /* 278 + * The inline assembly is equivalent to 279 + * vq->idle = get_cpu_timer(); 280 + * idle->idle_enter = get_clock(); 281 + * __load_psw_mask(psw_kernel_bits | PSW_MASK_WAIT | 282 + * PSW_MASK_IO | PSW_MASK_EXT); 283 + * The difference is that the inline assembly makes sure that 284 + * the last three instruction are stpt, stck and lpsw in that 285 + * order. This is done to increase the precision. 286 + */ 287 + asm volatile( 288 + #ifndef CONFIG_64BIT 289 + " basr 1,0\n" 290 + "0: ahi 1,1f-0b\n" 291 + " st 1,4(%2)\n" 292 + #else /* CONFIG_64BIT */ 293 + " larl 1,1f\n" 294 + " stg 1,8(%2)\n" 295 + #endif /* CONFIG_64BIT */ 296 + " stpt 0(%4)\n" 297 + " stck 0(%3)\n" 298 + #ifndef CONFIG_64BIT 299 + " lpsw 0(%2)\n" 300 + #else /* CONFIG_64BIT */ 301 + " lpswe 0(%2)\n" 302 + #endif /* CONFIG_64BIT */ 303 + "1:" 304 + : "=m" (idle->idle_enter), "=m" (vq->idle) 305 + : "a" (&psw), "a" (&idle->idle_enter), 306 + "a" (&vq->idle), "m" (psw) 307 + : "memory", "cc", "1"); 308 + } 103 309 } 104 310 105 311 /* ··· 261 195 */ 262 196 static void do_callbacks(struct list_head *cb_list) 263 197 { 264 - struct vtimer_queue *vt_list; 198 + struct vtimer_queue *vq; 265 199 struct vtimer_list *event, *tmp; 266 - void (*fn)(unsigned long); 267 - unsigned long data; 268 200 269 201 if (list_empty(cb_list)) 270 202 return; 271 203 272 - vt_list = &__get_cpu_var(virt_cpu_timer); 204 + vq = &__get_cpu_var(virt_cpu_timer); 273 205 274 206 list_for_each_entry_safe(event, tmp, cb_list, entry) { 275 - fn = event->function; 276 - data = event->data; 277 - fn(data); 278 - 279 - if (!event->interval) 280 - /* delete one shot timer */ 281 - list_del_init(&event->entry); 282 - else { 283 - /* move interval timer back to list */ 284 - spin_lock(&vt_list->lock); 285 - list_del_init(&event->entry); 286 - list_add_sorted(event, &vt_list->list); 287 - spin_unlock(&vt_list->lock); 207 + list_del_init(&event->entry); 208 + (event->function)(event->data); 209 + if (event->interval) { 210 + /* Recharge interval timer */ 211 + event->expires = event->interval + vq->elapsed; 212 + spin_lock(&vq->lock); 213 + list_add_sorted(event, &vq->list); 214 + spin_unlock(&vq->lock); 288 215 } 289 216 } 290 217 } ··· 287 228 */ 288 229 static void do_cpu_timer_interrupt(__u16 error_code) 289 230 { 290 - __u64 next, delta; 291 - struct vtimer_queue *vt_list; 231 + struct vtimer_queue *vq; 292 232 struct vtimer_list *event, *tmp; 293 - struct list_head *ptr; 294 - /* the callback queue */ 295 - struct list_head cb_list; 233 + struct list_head cb_list; /* the callback queue */ 234 + __u64 elapsed, next; 296 235 297 236 INIT_LIST_HEAD(&cb_list); 298 - vt_list = &__get_cpu_var(virt_cpu_timer); 237 + vq = &__get_cpu_var(virt_cpu_timer); 299 238 300 239 /* walk timer list, fire all expired events */ 301 - spin_lock(&vt_list->lock); 240 + spin_lock(&vq->lock); 302 241 303 - if (vt_list->to_expire < VTIMER_MAX_SLICE) 304 - vt_list->offset += vt_list->to_expire; 305 - 306 - list_for_each_entry_safe(event, tmp, &vt_list->list, entry) { 307 - if (event->expires > vt_list->offset) 308 - /* found first unexpired event, leave */ 309 - break; 310 - 311 - /* re-charge interval timer, we have to add the offset */ 312 - if (event->interval) 313 - event->expires = event->interval + vt_list->offset; 314 - 315 - /* move expired timer to the callback queue */ 316 - list_move_tail(&event->entry, &cb_list); 242 + elapsed = vq->elapsed + (vq->timer - S390_lowcore.async_enter_timer); 243 + BUG_ON((s64) elapsed < 0); 244 + vq->elapsed = 0; 245 + list_for_each_entry_safe(event, tmp, &vq->list, entry) { 246 + if (event->expires < elapsed) 247 + /* move expired timer to the callback queue */ 248 + list_move_tail(&event->entry, &cb_list); 249 + else 250 + event->expires -= elapsed; 317 251 } 318 - spin_unlock(&vt_list->lock); 252 + spin_unlock(&vq->lock); 253 + 254 + vq->do_spt = list_empty(&cb_list); 319 255 do_callbacks(&cb_list); 320 256 321 257 /* next event is first in list */ 322 - spin_lock(&vt_list->lock); 323 - if (!list_empty(&vt_list->list)) { 324 - ptr = vt_list->list.next; 325 - event = list_entry(ptr, struct vtimer_list, entry); 326 - next = event->expires - vt_list->offset; 327 - 328 - /* add the expired time from this interrupt handler 329 - * and the callback functions 330 - */ 331 - asm volatile ("STPT %0" : "=m" (delta)); 332 - delta = 0xffffffffffffffffLL - delta + 1; 333 - vt_list->offset += delta; 334 - next -= delta; 335 - } else { 336 - vt_list->offset = 0; 337 - next = VTIMER_MAX_SLICE; 338 - } 339 - spin_unlock(&vt_list->lock); 340 - set_vtimer(next); 258 + next = VTIMER_MAX_SLICE; 259 + spin_lock(&vq->lock); 260 + if (!list_empty(&vq->list)) { 261 + event = list_first_entry(&vq->list, struct vtimer_list, entry); 262 + next = event->expires; 263 + } else 264 + vq->do_spt = 0; 265 + spin_unlock(&vq->lock); 266 + /* 267 + * To improve precision add the time spent by the 268 + * interrupt handler to the elapsed time. 269 + * Note: CPU timer counts down and we got an interrupt, 270 + * the current content is negative 271 + */ 272 + elapsed = S390_lowcore.async_enter_timer - get_vtimer(); 273 + set_vtimer(next - elapsed); 274 + vq->timer = next - elapsed; 275 + vq->elapsed = elapsed; 341 276 } 342 277 343 278 void init_virt_timer(struct vtimer_list *timer) 344 279 { 345 280 timer->function = NULL; 346 281 INIT_LIST_HEAD(&timer->entry); 347 - spin_lock_init(&timer->lock); 348 282 } 349 283 EXPORT_SYMBOL(init_virt_timer); 350 284 ··· 351 299 */ 352 300 static void internal_add_vtimer(struct vtimer_list *timer) 353 301 { 302 + struct vtimer_queue *vq; 354 303 unsigned long flags; 355 - __u64 done; 356 - struct vtimer_list *event; 357 - struct vtimer_queue *vt_list; 304 + __u64 left, expires; 358 305 359 - vt_list = &per_cpu(virt_cpu_timer, timer->cpu); 360 - spin_lock_irqsave(&vt_list->lock, flags); 306 + vq = &per_cpu(virt_cpu_timer, timer->cpu); 307 + spin_lock_irqsave(&vq->lock, flags); 361 308 362 309 BUG_ON(timer->cpu != smp_processor_id()); 363 310 364 - /* if list is empty we only have to set the timer */ 365 - if (list_empty(&vt_list->list)) { 366 - /* reset the offset, this may happen if the last timer was 367 - * just deleted by mod_virt_timer and the interrupt 368 - * didn't happen until here 369 - */ 370 - vt_list->offset = 0; 371 - goto fire; 311 + if (list_empty(&vq->list)) { 312 + /* First timer on this cpu, just program it. */ 313 + list_add(&timer->entry, &vq->list); 314 + set_vtimer(timer->expires); 315 + vq->timer = timer->expires; 316 + vq->elapsed = 0; 317 + } else { 318 + /* Check progress of old timers. */ 319 + expires = timer->expires; 320 + left = get_vtimer(); 321 + if (likely((s64) expires < (s64) left)) { 322 + /* The new timer expires before the current timer. */ 323 + set_vtimer(expires); 324 + vq->elapsed += vq->timer - left; 325 + vq->timer = expires; 326 + } else { 327 + vq->elapsed += vq->timer - left; 328 + vq->timer = left; 329 + } 330 + /* Insert new timer into per cpu list. */ 331 + timer->expires += vq->elapsed; 332 + list_add_sorted(timer, &vq->list); 372 333 } 373 334 374 - /* save progress */ 375 - asm volatile ("STPT %0" : "=m" (done)); 376 - 377 - /* calculate completed work */ 378 - done = vt_list->to_expire - done + vt_list->offset; 379 - vt_list->offset = 0; 380 - 381 - list_for_each_entry(event, &vt_list->list, entry) 382 - event->expires -= done; 383 - 384 - fire: 385 - list_add_sorted(timer, &vt_list->list); 386 - 387 - /* get first element, which is the next vtimer slice */ 388 - event = list_entry(vt_list->list.next, struct vtimer_list, entry); 389 - 390 - set_vtimer(event->expires); 391 - spin_unlock_irqrestore(&vt_list->lock, flags); 335 + spin_unlock_irqrestore(&vq->lock, flags); 392 336 /* release CPU acquired in prepare_vtimer or mod_virt_timer() */ 393 337 put_cpu(); 394 338 } ··· 429 381 * If we change a pending timer the function must be called on the CPU 430 382 * where the timer is running on, e.g. by smp_call_function_single() 431 383 * 432 - * The original mod_timer adds the timer if it is not pending. For compatibility 433 - * we do the same. The timer will be added on the current CPU as a oneshot timer. 384 + * The original mod_timer adds the timer if it is not pending. For 385 + * compatibility we do the same. The timer will be added on the current 386 + * CPU as a oneshot timer. 434 387 * 435 388 * returns whether it has modified a pending timer (1) or not (0) 436 389 */ 437 390 int mod_virt_timer(struct vtimer_list *timer, __u64 expires) 438 391 { 439 - struct vtimer_queue *vt_list; 392 + struct vtimer_queue *vq; 440 393 unsigned long flags; 441 394 int cpu; 442 395 ··· 453 404 return 1; 454 405 455 406 cpu = get_cpu(); 456 - vt_list = &per_cpu(virt_cpu_timer, cpu); 407 + vq = &per_cpu(virt_cpu_timer, cpu); 457 408 458 409 /* check if we run on the right CPU */ 459 410 BUG_ON(timer->cpu != cpu); 460 411 461 412 /* disable interrupts before test if timer is pending */ 462 - spin_lock_irqsave(&vt_list->lock, flags); 413 + spin_lock_irqsave(&vq->lock, flags); 463 414 464 415 /* if timer isn't pending add it on the current CPU */ 465 416 if (!vtimer_pending(timer)) { 466 - spin_unlock_irqrestore(&vt_list->lock, flags); 417 + spin_unlock_irqrestore(&vq->lock, flags); 467 418 /* we do not activate an interval timer with mod_virt_timer */ 468 419 timer->interval = 0; 469 420 timer->expires = expires; ··· 480 431 timer->interval = expires; 481 432 482 433 /* the timer can't expire anymore so we can release the lock */ 483 - spin_unlock_irqrestore(&vt_list->lock, flags); 434 + spin_unlock_irqrestore(&vq->lock, flags); 484 435 internal_add_vtimer(timer); 485 436 return 1; 486 437 } ··· 494 445 int del_virt_timer(struct vtimer_list *timer) 495 446 { 496 447 unsigned long flags; 497 - struct vtimer_queue *vt_list; 448 + struct vtimer_queue *vq; 498 449 499 450 /* check if timer is pending */ 500 451 if (!vtimer_pending(timer)) 501 452 return 0; 502 453 503 - vt_list = &per_cpu(virt_cpu_timer, timer->cpu); 504 - spin_lock_irqsave(&vt_list->lock, flags); 454 + vq = &per_cpu(virt_cpu_timer, timer->cpu); 455 + spin_lock_irqsave(&vq->lock, flags); 505 456 506 457 /* we don't interrupt a running timer, just let it expire! */ 507 458 list_del_init(&timer->entry); 508 459 509 - /* last timer removed */ 510 - if (list_empty(&vt_list->list)) { 511 - vt_list->to_expire = 0; 512 - vt_list->offset = 0; 513 - } 514 - 515 - spin_unlock_irqrestore(&vt_list->lock, flags); 460 + spin_unlock_irqrestore(&vq->lock, flags); 516 461 return 1; 517 462 } 518 463 EXPORT_SYMBOL(del_virt_timer); ··· 516 473 */ 517 474 void init_cpu_vtimer(void) 518 475 { 519 - struct vtimer_queue *vt_list; 476 + struct vtimer_queue *vq; 520 477 521 478 /* kick the virtual timer */ 522 - S390_lowcore.exit_timer = VTIMER_MAX_SLICE; 523 - S390_lowcore.last_update_timer = VTIMER_MAX_SLICE; 524 - asm volatile ("SPT %0" : : "m" (S390_lowcore.last_update_timer)); 525 479 asm volatile ("STCK %0" : "=m" (S390_lowcore.last_update_clock)); 480 + asm volatile ("STPT %0" : "=m" (S390_lowcore.last_update_timer)); 481 + 482 + /* initialize per cpu vtimer structure */ 483 + vq = &__get_cpu_var(virt_cpu_timer); 484 + INIT_LIST_HEAD(&vq->list); 485 + spin_lock_init(&vq->lock); 526 486 527 487 /* enable cpu timer interrupts */ 528 488 __ctl_set_bit(0,10); 529 - 530 - vt_list = &__get_cpu_var(virt_cpu_timer); 531 - INIT_LIST_HEAD(&vt_list->list); 532 - spin_lock_init(&vt_list->lock); 533 - vt_list->to_expire = 0; 534 - vt_list->offset = 0; 535 - vt_list->idle = 0; 536 - 537 489 } 538 490 539 491 void __init vtime_init(void)
+4 -6
arch/x86/xen/time.c
··· 132 132 *snap = state; 133 133 134 134 /* Add the appropriate number of ticks of stolen time, 135 - including any left-overs from last time. Passing NULL to 136 - account_steal_time accounts the time as stolen. */ 135 + including any left-overs from last time. */ 137 136 stolen = runnable + offline + __get_cpu_var(residual_stolen); 138 137 139 138 if (stolen < 0) ··· 140 141 141 142 ticks = iter_div_u64_rem(stolen, NS_PER_TICK, &stolen); 142 143 __get_cpu_var(residual_stolen) = stolen; 143 - account_steal_time(NULL, ticks); 144 + account_steal_ticks(ticks); 144 145 145 146 /* Add the appropriate number of ticks of blocked time, 146 - including any left-overs from last time. Passing idle to 147 - account_steal_time accounts the time as idle/wait. */ 147 + including any left-overs from last time. */ 148 148 blocked += __get_cpu_var(residual_blocked); 149 149 150 150 if (blocked < 0) ··· 151 153 152 154 ticks = iter_div_u64_rem(blocked, NS_PER_TICK, &blocked); 153 155 __get_cpu_var(residual_blocked) = blocked; 154 - account_steal_time(idle_task(smp_processor_id()), ticks); 156 + account_idle_ticks(ticks); 155 157 } 156 158 157 159 /*
+1 -1
drivers/s390/cio/cio.c
··· 632 632 struct pt_regs *old_regs; 633 633 634 634 old_regs = set_irq_regs(regs); 635 - irq_enter(); 636 635 s390_idle_check(); 636 + irq_enter(); 637 637 if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) 638 638 /* Serve timer interrupts first. */ 639 639 clock_comparator_work();
+3
drivers/s390/s390mach.c
··· 18 18 #include <asm/etr.h> 19 19 #include <asm/lowcore.h> 20 20 #include <asm/cio.h> 21 + #include <asm/cpu.h> 21 22 #include "s390mach.h" 22 23 23 24 static struct semaphore m_sem; ··· 369 368 int umode; 370 369 371 370 lockdep_off(); 371 + 372 + s390_idle_check(); 372 373 373 374 mci = (struct mci *) &S390_lowcore.mcck_interruption_code; 374 375 mcck = &__get_cpu_var(cpu_mcck);
+8 -5
include/linux/kernel_stat.h
··· 79 79 } 80 80 81 81 extern unsigned long long task_delta_exec(struct task_struct *); 82 - extern void account_user_time(struct task_struct *, cputime_t); 83 - extern void account_user_time_scaled(struct task_struct *, cputime_t); 84 - extern void account_system_time(struct task_struct *, int, cputime_t); 85 - extern void account_system_time_scaled(struct task_struct *, cputime_t); 86 - extern void account_steal_time(struct task_struct *, cputime_t); 82 + extern void account_user_time(struct task_struct *, cputime_t, cputime_t); 83 + extern void account_system_time(struct task_struct *, int, cputime_t, cputime_t); 84 + extern void account_steal_time(cputime_t); 85 + extern void account_idle_time(cputime_t); 86 + 87 + extern void account_process_tick(struct task_struct *, int user); 88 + extern void account_steal_ticks(unsigned long ticks); 89 + extern void account_idle_ticks(unsigned long ticks); 87 90 88 91 #endif /* _LINUX_KERNEL_STAT_H */
-1
include/linux/sched.h
··· 284 284 285 285 extern void cpu_init (void); 286 286 extern void trap_init(void); 287 - extern void account_process_tick(struct task_struct *task, int user); 288 287 extern void update_process_times(int user); 289 288 extern void scheduler_tick(void); 290 289
+76 -39
kernel/sched.c
··· 4150 4150 * Account user cpu time to a process. 4151 4151 * @p: the process that the cpu time gets accounted to 4152 4152 * @cputime: the cpu time spent in user space since the last update 4153 + * @cputime_scaled: cputime scaled by cpu frequency 4153 4154 */ 4154 - void account_user_time(struct task_struct *p, cputime_t cputime) 4155 + void account_user_time(struct task_struct *p, cputime_t cputime, 4156 + cputime_t cputime_scaled) 4155 4157 { 4156 4158 struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; 4157 4159 cputime64_t tmp; 4158 4160 4161 + /* Add user time to process. */ 4159 4162 p->utime = cputime_add(p->utime, cputime); 4163 + p->utimescaled = cputime_add(p->utimescaled, cputime_scaled); 4160 4164 account_group_user_time(p, cputime); 4161 4165 4162 4166 /* Add user time to cpustat. */ ··· 4177 4173 * Account guest cpu time to a process. 4178 4174 * @p: the process that the cpu time gets accounted to 4179 4175 * @cputime: the cpu time spent in virtual machine since the last update 4176 + * @cputime_scaled: cputime scaled by cpu frequency 4180 4177 */ 4181 - static void account_guest_time(struct task_struct *p, cputime_t cputime) 4178 + static void account_guest_time(struct task_struct *p, cputime_t cputime, 4179 + cputime_t cputime_scaled) 4182 4180 { 4183 4181 cputime64_t tmp; 4184 4182 struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; 4185 4183 4186 4184 tmp = cputime_to_cputime64(cputime); 4187 4185 4186 + /* Add guest time to process. */ 4188 4187 p->utime = cputime_add(p->utime, cputime); 4188 + p->utimescaled = cputime_add(p->utimescaled, cputime_scaled); 4189 4189 account_group_user_time(p, cputime); 4190 4190 p->gtime = cputime_add(p->gtime, cputime); 4191 4191 4192 + /* Add guest time to cpustat. */ 4192 4193 cpustat->user = cputime64_add(cpustat->user, tmp); 4193 4194 cpustat->guest = cputime64_add(cpustat->guest, tmp); 4194 - } 4195 - 4196 - /* 4197 - * Account scaled user cpu time to a process. 4198 - * @p: the process that the cpu time gets accounted to 4199 - * @cputime: the cpu time spent in user space since the last update 4200 - */ 4201 - void account_user_time_scaled(struct task_struct *p, cputime_t cputime) 4202 - { 4203 - p->utimescaled = cputime_add(p->utimescaled, cputime); 4204 4195 } 4205 4196 4206 4197 /* ··· 4203 4204 * @p: the process that the cpu time gets accounted to 4204 4205 * @hardirq_offset: the offset to subtract from hardirq_count() 4205 4206 * @cputime: the cpu time spent in kernel space since the last update 4207 + * @cputime_scaled: cputime scaled by cpu frequency 4206 4208 */ 4207 4209 void account_system_time(struct task_struct *p, int hardirq_offset, 4208 - cputime_t cputime) 4210 + cputime_t cputime, cputime_t cputime_scaled) 4209 4211 { 4210 4212 struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; 4211 - struct rq *rq = this_rq(); 4212 4213 cputime64_t tmp; 4213 4214 4214 4215 if ((p->flags & PF_VCPU) && (irq_count() - hardirq_offset == 0)) { 4215 - account_guest_time(p, cputime); 4216 + account_guest_time(p, cputime, cputime_scaled); 4216 4217 return; 4217 4218 } 4218 4219 4220 + /* Add system time to process. */ 4219 4221 p->stime = cputime_add(p->stime, cputime); 4222 + p->stimescaled = cputime_add(p->stimescaled, cputime_scaled); 4220 4223 account_group_system_time(p, cputime); 4221 4224 4222 4225 /* Add system time to cpustat. */ ··· 4227 4226 cpustat->irq = cputime64_add(cpustat->irq, tmp); 4228 4227 else if (softirq_count()) 4229 4228 cpustat->softirq = cputime64_add(cpustat->softirq, tmp); 4230 - else if (p != rq->idle) 4231 - cpustat->system = cputime64_add(cpustat->system, tmp); 4232 - else if (atomic_read(&rq->nr_iowait) > 0) 4233 - cpustat->iowait = cputime64_add(cpustat->iowait, tmp); 4234 4229 else 4235 - cpustat->idle = cputime64_add(cpustat->idle, tmp); 4230 + cpustat->system = cputime64_add(cpustat->system, tmp); 4231 + 4236 4232 /* Account for system time used */ 4237 4233 acct_update_integrals(p); 4238 4234 } 4239 4235 4240 4236 /* 4241 - * Account scaled system cpu time to a process. 4242 - * @p: the process that the cpu time gets accounted to 4243 - * @hardirq_offset: the offset to subtract from hardirq_count() 4244 - * @cputime: the cpu time spent in kernel space since the last update 4237 + * Account for involuntary wait time. 4238 + * @steal: the cpu time spent in involuntary wait 4245 4239 */ 4246 - void account_system_time_scaled(struct task_struct *p, cputime_t cputime) 4240 + void account_steal_time(cputime_t cputime) 4247 4241 { 4248 - p->stimescaled = cputime_add(p->stimescaled, cputime); 4242 + struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; 4243 + cputime64_t cputime64 = cputime_to_cputime64(cputime); 4244 + 4245 + cpustat->steal = cputime64_add(cpustat->steal, cputime64); 4249 4246 } 4250 4247 4251 4248 /* 4252 - * Account for involuntary wait time. 4253 - * @p: the process from which the cpu time has been stolen 4254 - * @steal: the cpu time spent in involuntary wait 4249 + * Account for idle time. 4250 + * @cputime: the cpu time spent in idle wait 4255 4251 */ 4256 - void account_steal_time(struct task_struct *p, cputime_t steal) 4252 + void account_idle_time(cputime_t cputime) 4257 4253 { 4258 4254 struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; 4259 - cputime64_t tmp = cputime_to_cputime64(steal); 4255 + cputime64_t cputime64 = cputime_to_cputime64(cputime); 4260 4256 struct rq *rq = this_rq(); 4261 4257 4262 - if (p == rq->idle) { 4263 - p->stime = cputime_add(p->stime, steal); 4264 - if (atomic_read(&rq->nr_iowait) > 0) 4265 - cpustat->iowait = cputime64_add(cpustat->iowait, tmp); 4266 - else 4267 - cpustat->idle = cputime64_add(cpustat->idle, tmp); 4268 - } else 4269 - cpustat->steal = cputime64_add(cpustat->steal, tmp); 4258 + if (atomic_read(&rq->nr_iowait) > 0) 4259 + cpustat->iowait = cputime64_add(cpustat->iowait, cputime64); 4260 + else 4261 + cpustat->idle = cputime64_add(cpustat->idle, cputime64); 4270 4262 } 4263 + 4264 + #ifndef CONFIG_VIRT_CPU_ACCOUNTING 4265 + 4266 + /* 4267 + * Account a single tick of cpu time. 4268 + * @p: the process that the cpu time gets accounted to 4269 + * @user_tick: indicates if the tick is a user or a system tick 4270 + */ 4271 + void account_process_tick(struct task_struct *p, int user_tick) 4272 + { 4273 + cputime_t one_jiffy = jiffies_to_cputime(1); 4274 + cputime_t one_jiffy_scaled = cputime_to_scaled(one_jiffy); 4275 + struct rq *rq = this_rq(); 4276 + 4277 + if (user_tick) 4278 + account_user_time(p, one_jiffy, one_jiffy_scaled); 4279 + else if (p != rq->idle) 4280 + account_system_time(p, HARDIRQ_OFFSET, one_jiffy, 4281 + one_jiffy_scaled); 4282 + else 4283 + account_idle_time(one_jiffy); 4284 + } 4285 + 4286 + /* 4287 + * Account multiple ticks of steal time. 4288 + * @p: the process from which the cpu time has been stolen 4289 + * @ticks: number of stolen ticks 4290 + */ 4291 + void account_steal_ticks(unsigned long ticks) 4292 + { 4293 + account_steal_time(jiffies_to_cputime(ticks)); 4294 + } 4295 + 4296 + /* 4297 + * Account multiple ticks of idle time. 4298 + * @ticks: number of stolen ticks 4299 + */ 4300 + void account_idle_ticks(unsigned long ticks) 4301 + { 4302 + account_idle_time(jiffies_to_cputime(ticks)); 4303 + } 4304 + 4305 + #endif 4271 4306 4272 4307 /* 4273 4308 * Use precise platform statistics if available:
+6 -6
kernel/time/tick-sched.c
··· 419 419 { 420 420 int cpu = smp_processor_id(); 421 421 struct tick_sched *ts = &per_cpu(tick_cpu_sched, cpu); 422 + #ifndef CONFIG_VIRT_CPU_ACCOUNTING 422 423 unsigned long ticks; 424 + #endif 423 425 ktime_t now; 424 426 425 427 local_irq_disable(); ··· 443 441 tick_do_update_jiffies64(now); 444 442 cpumask_clear_cpu(cpu, nohz_cpu_mask); 445 443 444 + #ifndef CONFIG_VIRT_CPU_ACCOUNTING 446 445 /* 447 446 * We stopped the tick in idle. Update process times would miss the 448 447 * time we slept as update_process_times does only a 1 tick ··· 453 450 /* 454 451 * We might be one off. Do not randomly account a huge number of ticks! 455 452 */ 456 - if (ticks && ticks < LONG_MAX) { 457 - add_preempt_count(HARDIRQ_OFFSET); 458 - account_system_time(current, HARDIRQ_OFFSET, 459 - jiffies_to_cputime(ticks)); 460 - sub_preempt_count(HARDIRQ_OFFSET); 461 - } 453 + if (ticks && ticks < LONG_MAX) 454 + account_idle_ticks(ticks); 455 + #endif 462 456 463 457 touch_softlockup_watchdog(); 464 458 /*
-15
kernel/timer.c
··· 1018 1018 } 1019 1019 #endif 1020 1020 1021 - #ifndef CONFIG_VIRT_CPU_ACCOUNTING 1022 - void account_process_tick(struct task_struct *p, int user_tick) 1023 - { 1024 - cputime_t one_jiffy = jiffies_to_cputime(1); 1025 - 1026 - if (user_tick) { 1027 - account_user_time(p, one_jiffy); 1028 - account_user_time_scaled(p, cputime_to_scaled(one_jiffy)); 1029 - } else { 1030 - account_system_time(p, HARDIRQ_OFFSET, one_jiffy); 1031 - account_system_time_scaled(p, cputime_to_scaled(one_jiffy)); 1032 - } 1033 - } 1034 - #endif 1035 - 1036 1021 /* 1037 1022 * Called from the timer interrupt handler to charge one tick to the current 1038 1023 * process. user_tick is 1 if the tick is user time, 0 for system.