diff options
Diffstat (limited to 'arch/powerpc/kernel/time.c')
| -rw-r--r-- | arch/powerpc/kernel/time.c | 64 | 
1 files changed, 44 insertions, 20 deletions
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index be171ee73bf..eaa9d0e6abc 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -291,13 +291,12 @@ static inline u64 calculate_stolen_time(u64 stop_tb)   * Account time for a transition between system, hard irq   * or soft irq state.   */ -void account_system_vtime(struct task_struct *tsk) +static u64 vtime_delta(struct task_struct *tsk, +			u64 *sys_scaled, u64 *stolen)  { -	u64 now, nowscaled, delta, deltascaled; -	unsigned long flags; -	u64 stolen, udelta, sys_scaled, user_scaled; +	u64 now, nowscaled, deltascaled; +	u64 udelta, delta, user_scaled; -	local_irq_save(flags);  	now = mftb();  	nowscaled = read_spurr(now);  	get_paca()->system_time += now - get_paca()->starttime; @@ -305,7 +304,7 @@ void account_system_vtime(struct task_struct *tsk)  	deltascaled = nowscaled - get_paca()->startspurr;  	get_paca()->startspurr = nowscaled; -	stolen = calculate_stolen_time(now); +	*stolen = calculate_stolen_time(now);  	delta = get_paca()->system_time;  	get_paca()->system_time = 0; @@ -322,35 +321,45 @@ void account_system_vtime(struct task_struct *tsk)  	 * the user ticks get saved up in paca->user_time_scaled to be  	 * used by account_process_tick.  	 */ -	sys_scaled = delta; +	*sys_scaled = delta;  	user_scaled = udelta;  	if (deltascaled != delta + udelta) {  		if (udelta) { -			sys_scaled = deltascaled * delta / (delta + udelta); -			user_scaled = deltascaled - sys_scaled; +			*sys_scaled = deltascaled * delta / (delta + udelta); +			user_scaled = deltascaled - *sys_scaled;  		} else { -			sys_scaled = deltascaled; +			*sys_scaled = deltascaled;  		}  	}  	get_paca()->user_time_scaled += user_scaled; -	if (in_interrupt() || idle_task(smp_processor_id()) != tsk) { -		account_system_time(tsk, 0, delta, sys_scaled); -		if (stolen) -			account_steal_time(stolen); -	} else { -		account_idle_time(delta + stolen); -	} -	local_irq_restore(flags); +	return delta; +} + +void vtime_account_system(struct task_struct *tsk) +{ +	u64 delta, sys_scaled, stolen; + +	delta = vtime_delta(tsk, &sys_scaled, &stolen); +	account_system_time(tsk, 0, delta, sys_scaled); +	if (stolen) +		account_steal_time(stolen); +} + +void vtime_account_idle(struct task_struct *tsk) +{ +	u64 delta, sys_scaled, stolen; + +	delta = vtime_delta(tsk, &sys_scaled, &stolen); +	account_idle_time(delta + stolen);  } -EXPORT_SYMBOL_GPL(account_system_vtime);  /*   * Transfer the user and system times accumulated in the paca   * by the exception entry and exit code to the generic process   * user and system time records.   * Must be called with interrupts disabled. - * Assumes that account_system_vtime() has been called recently + * Assumes that vtime_account() has been called recently   * (i.e. since the last entry from usermode) so that   * get_paca()->user_time_scaled is up to date.   */ @@ -366,6 +375,12 @@ void account_process_tick(struct task_struct *tsk, int user_tick)  	account_user_time(tsk, utime, utimescaled);  } +void vtime_task_switch(struct task_struct *prev) +{ +	vtime_account(prev); +	account_process_tick(prev, 0); +} +  #else /* ! CONFIG_VIRT_CPU_ACCOUNTING */  #define calc_cputime_factors()  #endif @@ -535,6 +550,15 @@ void timer_interrupt(struct pt_regs * regs)  	trace_timer_interrupt_exit(regs);  } +/* + * Hypervisor decrementer interrupts shouldn't occur but are sometimes + * left pending on exit from a KVM guest.  We don't need to do anything + * to clear them, as they are edge-triggered. + */ +void hdec_interrupt(struct pt_regs *regs) +{ +} +  #ifdef CONFIG_SUSPEND  static void generic_suspend_disable_irqs(void)  {  |