diff options
Diffstat (limited to 'arch/s390/kernel/vtime.c')
-rw-r--r-- | arch/s390/kernel/vtime.c | 58 |
1 files changed, 54 insertions, 4 deletions
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index e34122e539a1..e53d3595a7c8 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c | |||
@@ -15,6 +15,8 @@ | |||
15 | #include <asm/cputime.h> | 15 | #include <asm/cputime.h> |
16 | #include <asm/vtimer.h> | 16 | #include <asm/vtimer.h> |
17 | #include <asm/vtime.h> | 17 | #include <asm/vtime.h> |
18 | #include <asm/cpu_mf.h> | ||
19 | #include <asm/smp.h> | ||
18 | 20 | ||
19 | static void virt_timer_expire(void); | 21 | static void virt_timer_expire(void); |
20 | 22 | ||
@@ -23,6 +25,10 @@ static DEFINE_SPINLOCK(virt_timer_lock); | |||
23 | static atomic64_t virt_timer_current; | 25 | static atomic64_t virt_timer_current; |
24 | static atomic64_t virt_timer_elapsed; | 26 | static atomic64_t virt_timer_elapsed; |
25 | 27 | ||
28 | static DEFINE_PER_CPU(u64, mt_cycles[32]); | ||
29 | static DEFINE_PER_CPU(u64, mt_scaling_mult) = { 1 }; | ||
30 | static DEFINE_PER_CPU(u64, mt_scaling_div) = { 1 }; | ||
31 | |||
26 | static inline u64 get_vtimer(void) | 32 | static inline u64 get_vtimer(void) |
27 | { | 33 | { |
28 | u64 timer; | 34 | u64 timer; |
@@ -61,6 +67,8 @@ static int do_account_vtime(struct task_struct *tsk, int hardirq_offset) | |||
61 | { | 67 | { |
62 | struct thread_info *ti = task_thread_info(tsk); | 68 | struct thread_info *ti = task_thread_info(tsk); |
63 | u64 timer, clock, user, system, steal; | 69 | u64 timer, clock, user, system, steal; |
70 | u64 user_scaled, system_scaled; | ||
71 | int i; | ||
64 | 72 | ||
65 | timer = S390_lowcore.last_update_timer; | 73 | timer = S390_lowcore.last_update_timer; |
66 | clock = S390_lowcore.last_update_clock; | 74 | clock = S390_lowcore.last_update_clock; |
@@ -76,15 +84,49 @@ static int do_account_vtime(struct task_struct *tsk, int hardirq_offset) | |||
76 | S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer; | 84 | S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer; |
77 | S390_lowcore.steal_timer += S390_lowcore.last_update_clock - clock; | 85 | S390_lowcore.steal_timer += S390_lowcore.last_update_clock - clock; |
78 | 86 | ||
87 | /* Do MT utilization calculation */ | ||
88 | if (smp_cpu_mtid) { | ||
89 | u64 cycles_new[32], *cycles_old; | ||
90 | u64 delta, mult, div; | ||
91 | |||
92 | cycles_old = this_cpu_ptr(mt_cycles); | ||
93 | if (stcctm5(smp_cpu_mtid + 1, cycles_new) < 2) { | ||
94 | mult = div = 0; | ||
95 | for (i = 0; i <= smp_cpu_mtid; i++) { | ||
96 | delta = cycles_new[i] - cycles_old[i]; | ||
97 | mult += delta; | ||
98 | div += (i + 1) * delta; | ||
99 | } | ||
100 | if (mult > 0) { | ||
101 | /* Update scaling factor */ | ||
102 | __this_cpu_write(mt_scaling_mult, mult); | ||
103 | __this_cpu_write(mt_scaling_div, div); | ||
104 | memcpy(cycles_old, cycles_new, | ||
105 | sizeof(u64) * (smp_cpu_mtid + 1)); | ||
106 | } | ||
107 | } | ||
108 | } | ||
109 | |||
79 | user = S390_lowcore.user_timer - ti->user_timer; | 110 | user = S390_lowcore.user_timer - ti->user_timer; |
80 | S390_lowcore.steal_timer -= user; | 111 | S390_lowcore.steal_timer -= user; |
81 | ti->user_timer = S390_lowcore.user_timer; | 112 | ti->user_timer = S390_lowcore.user_timer; |
82 | account_user_time(tsk, user, user); | ||
83 | 113 | ||
84 | system = S390_lowcore.system_timer - ti->system_timer; | 114 | system = S390_lowcore.system_timer - ti->system_timer; |
85 | S390_lowcore.steal_timer -= system; | 115 | S390_lowcore.steal_timer -= system; |
86 | ti->system_timer = S390_lowcore.system_timer; | 116 | ti->system_timer = S390_lowcore.system_timer; |
87 | account_system_time(tsk, hardirq_offset, system, system); | 117 | |
118 | user_scaled = user; | ||
119 | system_scaled = system; | ||
120 | /* Do MT utilization scaling */ | ||
121 | if (smp_cpu_mtid) { | ||
122 | u64 mult = __this_cpu_read(mt_scaling_mult); | ||
123 | u64 div = __this_cpu_read(mt_scaling_div); | ||
124 | |||
125 | user_scaled = (user_scaled * mult) / div; | ||
126 | system_scaled = (system_scaled * mult) / div; | ||
127 | } | ||
128 | account_user_time(tsk, user, user_scaled); | ||
129 | account_system_time(tsk, hardirq_offset, system, system_scaled); | ||
88 | 130 | ||
89 | steal = S390_lowcore.steal_timer; | 131 | steal = S390_lowcore.steal_timer; |
90 | if ((s64) steal > 0) { | 132 | if ((s64) steal > 0) { |
@@ -126,7 +168,7 @@ void vtime_account_user(struct task_struct *tsk) | |||
126 | void vtime_account_irq_enter(struct task_struct *tsk) | 168 | void vtime_account_irq_enter(struct task_struct *tsk) |
127 | { | 169 | { |
128 | struct thread_info *ti = task_thread_info(tsk); | 170 | struct thread_info *ti = task_thread_info(tsk); |
129 | u64 timer, system; | 171 | u64 timer, system, system_scaled; |
130 | 172 | ||
131 | timer = S390_lowcore.last_update_timer; | 173 | timer = S390_lowcore.last_update_timer; |
132 | S390_lowcore.last_update_timer = get_vtimer(); | 174 | S390_lowcore.last_update_timer = get_vtimer(); |
@@ -135,7 +177,15 @@ void vtime_account_irq_enter(struct task_struct *tsk) | |||
135 | system = S390_lowcore.system_timer - ti->system_timer; | 177 | system = S390_lowcore.system_timer - ti->system_timer; |
136 | S390_lowcore.steal_timer -= system; | 178 | S390_lowcore.steal_timer -= system; |
137 | ti->system_timer = S390_lowcore.system_timer; | 179 | ti->system_timer = S390_lowcore.system_timer; |
138 | account_system_time(tsk, 0, system, system); | 180 | system_scaled = system; |
181 | /* Do MT utilization scaling */ | ||
182 | if (smp_cpu_mtid) { | ||
183 | u64 mult = __this_cpu_read(mt_scaling_mult); | ||
184 | u64 div = __this_cpu_read(mt_scaling_div); | ||
185 | |||
186 | system_scaled = (system_scaled * mult) / div; | ||
187 | } | ||
188 | account_system_time(tsk, 0, system, system_scaled); | ||
139 | 189 | ||
140 | virt_timer_forward(system); | 190 | virt_timer_forward(system); |
141 | } | 191 | } |