|
@@ -90,14 +90,41 @@ static void update_mt_scaling(void)
|
|
|
__this_cpu_write(mt_scaling_jiffies, jiffies_64);
|
|
|
}
|
|
|
|
|
|
+static inline u64 update_tsk_timer(unsigned long *tsk_vtime, u64 new)
|
|
|
+{
|
|
|
+ u64 delta;
|
|
|
+
|
|
|
+ delta = new - *tsk_vtime;
|
|
|
+ *tsk_vtime = new;
|
|
|
+ return delta;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+static inline u64 scale_vtime(u64 vtime)
|
|
|
+{
|
|
|
+ u64 mult = __this_cpu_read(mt_scaling_mult);
|
|
|
+ u64 div = __this_cpu_read(mt_scaling_div);
|
|
|
+
|
|
|
+ if (smp_cpu_mtid)
|
|
|
+ return vtime * mult / div;
|
|
|
+ return vtime;
|
|
|
+}
|
|
|
+
|
|
|
+static void account_system_index_scaled(struct task_struct *p,
|
|
|
+ cputime_t cputime, cputime_t scaled,
|
|
|
+ enum cpu_usage_stat index)
|
|
|
+{
|
|
|
+ p->stimescaled += scaled;
|
|
|
+ account_system_index_time(p, cputime, index);
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Update process times based on virtual cpu times stored by entry.S
|
|
|
* to the lowcore fields user_timer, system_timer & steal_clock.
|
|
|
*/
|
|
|
static int do_account_vtime(struct task_struct *tsk)
|
|
|
{
|
|
|
- u64 timer, clock, user, system, steal;
|
|
|
- u64 user_scaled, system_scaled;
|
|
|
+ u64 timer, clock, user, guest, system, hardirq, softirq, steal;
|
|
|
|
|
|
timer = S390_lowcore.last_update_timer;
|
|
|
clock = S390_lowcore.last_update_clock;
|
|
@@ -110,36 +137,53 @@ static int do_account_vtime(struct task_struct *tsk)
|
|
|
#endif
|
|
|
: "=m" (S390_lowcore.last_update_timer),
|
|
|
"=m" (S390_lowcore.last_update_clock));
|
|
|
- S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer;
|
|
|
- S390_lowcore.steal_timer += S390_lowcore.last_update_clock - clock;
|
|
|
+ clock = S390_lowcore.last_update_clock - clock;
|
|
|
+ timer -= S390_lowcore.last_update_timer;
|
|
|
+
|
|
|
+ if (hardirq_count())
|
|
|
+ S390_lowcore.hardirq_timer += timer;
|
|
|
+ else
|
|
|
+ S390_lowcore.system_timer += timer;
|
|
|
|
|
|
/* Update MT utilization calculation */
|
|
|
if (smp_cpu_mtid &&
|
|
|
time_after64(jiffies_64, this_cpu_read(mt_scaling_jiffies)))
|
|
|
update_mt_scaling();
|
|
|
|
|
|
- user = S390_lowcore.user_timer - tsk->thread.user_timer;
|
|
|
- S390_lowcore.steal_timer -= user;
|
|
|
- tsk->thread.user_timer = S390_lowcore.user_timer;
|
|
|
-
|
|
|
- system = S390_lowcore.system_timer - tsk->thread.system_timer;
|
|
|
- S390_lowcore.steal_timer -= system;
|
|
|
- tsk->thread.system_timer = S390_lowcore.system_timer;
|
|
|
-
|
|
|
- user_scaled = user;
|
|
|
- system_scaled = system;
|
|
|
- /* Do MT utilization scaling */
|
|
|
- if (smp_cpu_mtid) {
|
|
|
- u64 mult = __this_cpu_read(mt_scaling_mult);
|
|
|
- u64 div = __this_cpu_read(mt_scaling_div);
|
|
|
+ /* Calculate cputime delta */
|
|
|
+ user = update_tsk_timer(&tsk->thread.user_timer,
|
|
|
+ READ_ONCE(S390_lowcore.user_timer));
|
|
|
+ guest = update_tsk_timer(&tsk->thread.guest_timer,
|
|
|
+ READ_ONCE(S390_lowcore.guest_timer));
|
|
|
+ system = update_tsk_timer(&tsk->thread.system_timer,
|
|
|
+ READ_ONCE(S390_lowcore.system_timer));
|
|
|
+ hardirq = update_tsk_timer(&tsk->thread.hardirq_timer,
|
|
|
+ READ_ONCE(S390_lowcore.hardirq_timer));
|
|
|
+ softirq = update_tsk_timer(&tsk->thread.softirq_timer,
|
|
|
+ READ_ONCE(S390_lowcore.softirq_timer));
|
|
|
+ S390_lowcore.steal_timer +=
|
|
|
+ clock - user - guest - system - hardirq - softirq;
|
|
|
+
|
|
|
+ /* Push account value */
|
|
|
+ if (user) {
|
|
|
+ account_user_time(tsk, user);
|
|
|
+ tsk->utimescaled += scale_vtime(user);
|
|
|
+ }
|
|
|
|
|
|
- user_scaled = (user_scaled * mult) / div;
|
|
|
- system_scaled = (system_scaled * mult) / div;
|
|
|
+ if (guest) {
|
|
|
+ account_guest_time(tsk, guest);
|
|
|
+ tsk->utimescaled += scale_vtime(guest);
|
|
|
}
|
|
|
- account_user_time(tsk, user);
|
|
|
- tsk->utimescaled += user_scaled;
|
|
|
- account_system_time(tsk, 0, system);
|
|
|
- tsk->stimescaled += system_scaled;
|
|
|
+
|
|
|
+ if (system)
|
|
|
+ account_system_index_scaled(tsk, system, scale_vtime(system),
|
|
|
+ CPUTIME_SYSTEM);
|
|
|
+ if (hardirq)
|
|
|
+ account_system_index_scaled(tsk, hardirq, scale_vtime(hardirq),
|
|
|
+ CPUTIME_IRQ);
|
|
|
+ if (softirq)
|
|
|
+ account_system_index_scaled(tsk, softirq, scale_vtime(softirq),
|
|
|
+ CPUTIME_SOFTIRQ);
|
|
|
|
|
|
steal = S390_lowcore.steal_timer;
|
|
|
if ((s64) steal > 0) {
|
|
@@ -147,16 +191,22 @@ static int do_account_vtime(struct task_struct *tsk)
|
|
|
account_steal_time(steal);
|
|
|
}
|
|
|
|
|
|
- return virt_timer_forward(user + system);
|
|
|
+ return virt_timer_forward(user + guest + system + hardirq + softirq);
|
|
|
}
|
|
|
|
|
|
void vtime_task_switch(struct task_struct *prev)
|
|
|
{
|
|
|
do_account_vtime(prev);
|
|
|
prev->thread.user_timer = S390_lowcore.user_timer;
|
|
|
+ prev->thread.guest_timer = S390_lowcore.guest_timer;
|
|
|
prev->thread.system_timer = S390_lowcore.system_timer;
|
|
|
+ prev->thread.hardirq_timer = S390_lowcore.hardirq_timer;
|
|
|
+ prev->thread.softirq_timer = S390_lowcore.softirq_timer;
|
|
|
S390_lowcore.user_timer = current->thread.user_timer;
|
|
|
+ S390_lowcore.guest_timer = current->thread.guest_timer;
|
|
|
S390_lowcore.system_timer = current->thread.system_timer;
|
|
|
+ S390_lowcore.hardirq_timer = current->thread.hardirq_timer;
|
|
|
+ S390_lowcore.softirq_timer = current->thread.softirq_timer;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -176,32 +226,22 @@ void vtime_account_user(struct task_struct *tsk)
|
|
|
*/
|
|
|
void vtime_account_irq_enter(struct task_struct *tsk)
|
|
|
{
|
|
|
- u64 timer, system, system_scaled;
|
|
|
+ u64 timer;
|
|
|
|
|
|
timer = S390_lowcore.last_update_timer;
|
|
|
S390_lowcore.last_update_timer = get_vtimer();
|
|
|
- S390_lowcore.system_timer += timer - S390_lowcore.last_update_timer;
|
|
|
-
|
|
|
- /* Update MT utilization calculation */
|
|
|
- if (smp_cpu_mtid &&
|
|
|
- time_after64(jiffies_64, this_cpu_read(mt_scaling_jiffies)))
|
|
|
- update_mt_scaling();
|
|
|
-
|
|
|
- system = S390_lowcore.system_timer - tsk->thread.system_timer;
|
|
|
- S390_lowcore.steal_timer -= system;
|
|
|
- tsk->thread.system_timer = S390_lowcore.system_timer;
|
|
|
- system_scaled = system;
|
|
|
- /* Do MT utilization scaling */
|
|
|
- if (smp_cpu_mtid) {
|
|
|
- u64 mult = __this_cpu_read(mt_scaling_mult);
|
|
|
- u64 div = __this_cpu_read(mt_scaling_div);
|
|
|
-
|
|
|
- system_scaled = (system_scaled * mult) / div;
|
|
|
- }
|
|
|
- account_system_time(tsk, 0, system);
|
|
|
- tsk->stimescaled += system_scaled;
|
|
|
-
|
|
|
- virt_timer_forward(system);
|
|
|
+ timer -= S390_lowcore.last_update_timer;
|
|
|
+
|
|
|
+ if ((tsk->flags & PF_VCPU) && (irq_count() == 0))
|
|
|
+ S390_lowcore.guest_timer += timer;
|
|
|
+ else if (hardirq_count())
|
|
|
+ S390_lowcore.hardirq_timer += timer;
|
|
|
+ else if (in_serving_softirq())
|
|
|
+ S390_lowcore.softirq_timer += timer;
|
|
|
+ else
|
|
|
+ S390_lowcore.system_timer += timer;
|
|
|
+
|
|
|
+ virt_timer_forward(timer);
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(vtime_account_irq_enter);
|
|
|
|