aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel/vtime.c
diff options
context:
space:
mode:
authorMartin Schwidefsky <schwidefsky@de.ibm.com>2015-01-14 11:52:10 -0500
committerMartin Schwidefsky <schwidefsky@de.ibm.com>2015-01-22 06:16:01 -0500
commit10ad34bc76dfbc49bda327a13012f6754c0c72e0 (patch)
tree4d76fb6882da2eb3e77b53c4fe64f6367ffbd79d /arch/s390/kernel/vtime.c
parent1f6b83e5e4d3aed46eac1d219322fba9c7341cd8 (diff)
s390: add SMT support
The multi-threading facility is introduced with the z13 processor family. This patch adds code to detect the multi-threading facility. With the facility enabled each core will surface multiple hardware threads to the system. Each hardware threads looks like a normal CPU to the operating system with all its registers and properties. The SCLP interface reports the SMT topology indirectly via the maximum thread id. Each reported CPU in the result of a read-scp-information is a core representing a number of hardware threads. To reflect the reduced CPU capacity if two hardware threads run on a single core the MT utilization counter set is used to normalize the raw cputime obtained by the CPU timer deltas. This scaled cputime is reported via the taskstats interface. The normal /proc/stat numbers are based on the raw cputime and are not affected by the normalization. Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Diffstat (limited to 'arch/s390/kernel/vtime.c')
-rw-r--r--arch/s390/kernel/vtime.c58
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
19static void virt_timer_expire(void); 21static void virt_timer_expire(void);
20 22
@@ -23,6 +25,10 @@ static DEFINE_SPINLOCK(virt_timer_lock);
23static atomic64_t virt_timer_current; 25static atomic64_t virt_timer_current;
24static atomic64_t virt_timer_elapsed; 26static atomic64_t virt_timer_elapsed;
25 27
28static DEFINE_PER_CPU(u64, mt_cycles[32]);
29static DEFINE_PER_CPU(u64, mt_scaling_mult) = { 1 };
30static DEFINE_PER_CPU(u64, mt_scaling_div) = { 1 };
31
26static inline u64 get_vtimer(void) 32static 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)
126void vtime_account_irq_enter(struct task_struct *tsk) 168void 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}