diff options
-rw-r--r-- | arch/powerpc/kernel/asm-offsets.c | 1 | ||||
-rw-r--r-- | arch/powerpc/kernel/time.c | 32 | ||||
-rw-r--r-- | include/asm-powerpc/paca.h | 3 |
3 files changed, 34 insertions, 2 deletions
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 0ae5d57b9368..2c8e756d19a3 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -141,6 +141,7 @@ int main(void) | |||
141 | DEFINE(PACALPPACAPTR, offsetof(struct paca_struct, lppaca_ptr)); | 141 | DEFINE(PACALPPACAPTR, offsetof(struct paca_struct, lppaca_ptr)); |
142 | DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); | 142 | DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); |
143 | DEFINE(PACA_STARTPURR, offsetof(struct paca_struct, startpurr)); | 143 | DEFINE(PACA_STARTPURR, offsetof(struct paca_struct, startpurr)); |
144 | DEFINE(PACA_STARTSPURR, offsetof(struct paca_struct, startspurr)); | ||
144 | DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time)); | 145 | DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time)); |
145 | DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time)); | 146 | DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time)); |
146 | DEFINE(PACA_SLBSHADOWPTR, offsetof(struct paca_struct, slb_shadow_ptr)); | 147 | DEFINE(PACA_SLBSHADOWPTR, offsetof(struct paca_struct, slb_shadow_ptr)); |
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 863a5d6d9b18..9eb3284deac4 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -212,23 +212,44 @@ static u64 read_purr(void) | |||
212 | } | 212 | } |
213 | 213 | ||
214 | /* | 214 | /* |
215 | * Read the SPURR on systems that have it, otherwise the purr | ||
216 | */ | ||
217 | static u64 read_spurr(u64 purr) | ||
218 | { | ||
219 | if (cpu_has_feature(CPU_FTR_SPURR)) | ||
220 | return mfspr(SPRN_SPURR); | ||
221 | return purr; | ||
222 | } | ||
223 | |||
224 | /* | ||
215 | * Account time for a transition between system, hard irq | 225 | * Account time for a transition between system, hard irq |
216 | * or soft irq state. | 226 | * or soft irq state. |
217 | */ | 227 | */ |
218 | void account_system_vtime(struct task_struct *tsk) | 228 | void account_system_vtime(struct task_struct *tsk) |
219 | { | 229 | { |
220 | u64 now, delta; | 230 | u64 now, nowscaled, delta, deltascaled; |
221 | unsigned long flags; | 231 | unsigned long flags; |
222 | 232 | ||
223 | local_irq_save(flags); | 233 | local_irq_save(flags); |
224 | now = read_purr(); | 234 | now = read_purr(); |
225 | delta = now - get_paca()->startpurr; | 235 | delta = now - get_paca()->startpurr; |
226 | get_paca()->startpurr = now; | 236 | get_paca()->startpurr = now; |
237 | nowscaled = read_spurr(now); | ||
238 | deltascaled = nowscaled - get_paca()->startspurr; | ||
239 | get_paca()->startspurr = nowscaled; | ||
227 | if (!in_interrupt()) { | 240 | if (!in_interrupt()) { |
241 | /* deltascaled includes both user and system time. | ||
242 | * Hence scale it based on the purr ratio to estimate | ||
243 | * the system time */ | ||
244 | deltascaled = deltascaled * get_paca()->system_time / | ||
245 | (get_paca()->system_time + get_paca()->user_time); | ||
228 | delta += get_paca()->system_time; | 246 | delta += get_paca()->system_time; |
229 | get_paca()->system_time = 0; | 247 | get_paca()->system_time = 0; |
230 | } | 248 | } |
231 | account_system_time(tsk, 0, delta); | 249 | account_system_time(tsk, 0, delta); |
250 | get_paca()->purrdelta = delta; | ||
251 | account_system_time_scaled(tsk, deltascaled); | ||
252 | get_paca()->spurrdelta = deltascaled; | ||
232 | local_irq_restore(flags); | 253 | local_irq_restore(flags); |
233 | } | 254 | } |
234 | 255 | ||
@@ -240,11 +261,17 @@ void account_system_vtime(struct task_struct *tsk) | |||
240 | */ | 261 | */ |
241 | void account_process_vtime(struct task_struct *tsk) | 262 | void account_process_vtime(struct task_struct *tsk) |
242 | { | 263 | { |
243 | cputime_t utime; | 264 | cputime_t utime, utimescaled; |
244 | 265 | ||
245 | utime = get_paca()->user_time; | 266 | utime = get_paca()->user_time; |
246 | get_paca()->user_time = 0; | 267 | get_paca()->user_time = 0; |
247 | account_user_time(tsk, utime); | 268 | account_user_time(tsk, utime); |
269 | |||
270 | /* Estimate the scaled utime by scaling the real utime based | ||
271 | * on the last spurr to purr ratio */ | ||
272 | utimescaled = utime * get_paca()->spurrdelta / get_paca()->purrdelta; | ||
273 | get_paca()->spurrdelta = get_paca()->purrdelta = 0; | ||
274 | account_user_time_scaled(tsk, utimescaled); | ||
248 | } | 275 | } |
249 | 276 | ||
250 | static void account_process_time(struct pt_regs *regs) | 277 | static void account_process_time(struct pt_regs *regs) |
@@ -266,6 +293,7 @@ struct cpu_purr_data { | |||
266 | int initialized; /* thread is running */ | 293 | int initialized; /* thread is running */ |
267 | u64 tb; /* last TB value read */ | 294 | u64 tb; /* last TB value read */ |
268 | u64 purr; /* last PURR value read */ | 295 | u64 purr; /* last PURR value read */ |
296 | u64 spurr; /* last SPURR value read */ | ||
269 | }; | 297 | }; |
270 | 298 | ||
271 | /* | 299 | /* |
diff --git a/include/asm-powerpc/paca.h b/include/asm-powerpc/paca.h index fcd7b428ed0b..98c6bd5756b7 100644 --- a/include/asm-powerpc/paca.h +++ b/include/asm-powerpc/paca.h | |||
@@ -114,6 +114,9 @@ struct paca_struct { | |||
114 | u64 user_time; /* accumulated usermode TB ticks */ | 114 | u64 user_time; /* accumulated usermode TB ticks */ |
115 | u64 system_time; /* accumulated system TB ticks */ | 115 | u64 system_time; /* accumulated system TB ticks */ |
116 | u64 startpurr; /* PURR/TB value snapshot */ | 116 | u64 startpurr; /* PURR/TB value snapshot */ |
117 | u64 startspurr; /* SPURR value snapshot */ | ||
118 | u64 purrdelta; /* FIXME: document */ | ||
119 | u64 spurrdelta; /* FIXME: document */ | ||
117 | }; | 120 | }; |
118 | 121 | ||
119 | extern struct paca_struct paca[]; | 122 | extern struct paca_struct paca[]; |