diff options
Diffstat (limited to 'arch/powerpc/kernel/time.c')
| -rw-r--r-- | arch/powerpc/kernel/time.c | 63 |
1 files changed, 16 insertions, 47 deletions
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 5b59bc18dfe7..a1b5e4b16151 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
| @@ -220,11 +220,8 @@ static void account_process_time(struct pt_regs *regs) | |||
| 220 | */ | 220 | */ |
| 221 | struct cpu_purr_data { | 221 | struct cpu_purr_data { |
| 222 | int initialized; /* thread is running */ | 222 | int initialized; /* thread is running */ |
| 223 | u64 tb0; /* timebase at origin time */ | ||
| 224 | u64 purr0; /* PURR at origin time */ | ||
| 225 | u64 tb; /* last TB value read */ | 223 | u64 tb; /* last TB value read */ |
| 226 | u64 purr; /* last PURR value read */ | 224 | u64 purr; /* last PURR value read */ |
| 227 | u64 stolen; /* stolen time so far */ | ||
| 228 | spinlock_t lock; | 225 | spinlock_t lock; |
| 229 | }; | 226 | }; |
| 230 | 227 | ||
| @@ -234,10 +231,8 @@ static void snapshot_tb_and_purr(void *data) | |||
| 234 | { | 231 | { |
| 235 | struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data); | 232 | struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data); |
| 236 | 233 | ||
| 237 | p->tb0 = mftb(); | 234 | p->tb = mftb(); |
| 238 | p->purr0 = mfspr(SPRN_PURR); | 235 | p->purr = mfspr(SPRN_PURR); |
| 239 | p->tb = p->tb0; | ||
| 240 | p->purr = 0; | ||
| 241 | wmb(); | 236 | wmb(); |
| 242 | p->initialized = 1; | 237 | p->initialized = 1; |
| 243 | } | 238 | } |
| @@ -258,37 +253,24 @@ void snapshot_timebases(void) | |||
| 258 | 253 | ||
| 259 | void calculate_steal_time(void) | 254 | void calculate_steal_time(void) |
| 260 | { | 255 | { |
| 261 | u64 tb, purr, t0; | 256 | u64 tb, purr; |
| 262 | s64 stolen; | 257 | s64 stolen; |
| 263 | struct cpu_purr_data *p0, *pme, *phim; | 258 | struct cpu_purr_data *pme; |
| 264 | int cpu; | ||
| 265 | 259 | ||
| 266 | if (!cpu_has_feature(CPU_FTR_PURR)) | 260 | if (!cpu_has_feature(CPU_FTR_PURR)) |
| 267 | return; | 261 | return; |
| 268 | cpu = smp_processor_id(); | 262 | pme = &per_cpu(cpu_purr_data, smp_processor_id()); |
| 269 | pme = &per_cpu(cpu_purr_data, cpu); | ||
| 270 | if (!pme->initialized) | 263 | if (!pme->initialized) |
| 271 | return; /* this can happen in early boot */ | 264 | return; /* this can happen in early boot */ |
| 272 | p0 = &per_cpu(cpu_purr_data, cpu & ~1); | 265 | spin_lock(&pme->lock); |
| 273 | phim = &per_cpu(cpu_purr_data, cpu ^ 1); | ||
| 274 | spin_lock(&p0->lock); | ||
| 275 | tb = mftb(); | 266 | tb = mftb(); |
| 276 | purr = mfspr(SPRN_PURR) - pme->purr0; | 267 | purr = mfspr(SPRN_PURR); |
| 277 | if (!phim->initialized || !cpu_online(cpu ^ 1)) { | 268 | stolen = (tb - pme->tb) - (purr - pme->purr); |
| 278 | stolen = (tb - pme->tb) - (purr - pme->purr); | 269 | if (stolen > 0) |
| 279 | } else { | ||
| 280 | t0 = pme->tb0; | ||
| 281 | if (phim->tb0 < t0) | ||
| 282 | t0 = phim->tb0; | ||
| 283 | stolen = phim->tb - t0 - phim->purr - purr - p0->stolen; | ||
| 284 | } | ||
| 285 | if (stolen > 0) { | ||
| 286 | account_steal_time(current, stolen); | 270 | account_steal_time(current, stolen); |
| 287 | p0->stolen += stolen; | ||
| 288 | } | ||
| 289 | pme->tb = tb; | 271 | pme->tb = tb; |
| 290 | pme->purr = purr; | 272 | pme->purr = purr; |
| 291 | spin_unlock(&p0->lock); | 273 | spin_unlock(&pme->lock); |
| 292 | } | 274 | } |
| 293 | 275 | ||
| 294 | /* | 276 | /* |
| @@ -297,30 +279,17 @@ void calculate_steal_time(void) | |||
| 297 | */ | 279 | */ |
| 298 | static void snapshot_purr(void) | 280 | static void snapshot_purr(void) |
| 299 | { | 281 | { |
| 300 | int cpu; | 282 | struct cpu_purr_data *pme; |
| 301 | u64 purr; | ||
| 302 | struct cpu_purr_data *p0, *pme, *phim; | ||
| 303 | unsigned long flags; | 283 | unsigned long flags; |
| 304 | 284 | ||
| 305 | if (!cpu_has_feature(CPU_FTR_PURR)) | 285 | if (!cpu_has_feature(CPU_FTR_PURR)) |
| 306 | return; | 286 | return; |
| 307 | cpu = smp_processor_id(); | 287 | pme = &per_cpu(cpu_purr_data, smp_processor_id()); |
| 308 | pme = &per_cpu(cpu_purr_data, cpu); | 288 | spin_lock_irqsave(&pme->lock, flags); |
| 309 | p0 = &per_cpu(cpu_purr_data, cpu & ~1); | 289 | pme->tb = mftb(); |
| 310 | phim = &per_cpu(cpu_purr_data, cpu ^ 1); | 290 | pme->purr = mfspr(SPRN_PURR); |
| 311 | spin_lock_irqsave(&p0->lock, flags); | ||
| 312 | pme->tb = pme->tb0 = mftb(); | ||
| 313 | purr = mfspr(SPRN_PURR); | ||
| 314 | if (!phim->initialized) { | ||
| 315 | pme->purr = 0; | ||
| 316 | pme->purr0 = purr; | ||
| 317 | } else { | ||
| 318 | /* set p->purr and p->purr0 for no change in p0->stolen */ | ||
| 319 | pme->purr = phim->tb - phim->tb0 - phim->purr - p0->stolen; | ||
| 320 | pme->purr0 = purr - pme->purr; | ||
| 321 | } | ||
| 322 | pme->initialized = 1; | 291 | pme->initialized = 1; |
| 323 | spin_unlock_irqrestore(&p0->lock, flags); | 292 | spin_unlock_irqrestore(&pme->lock, flags); |
| 324 | } | 293 | } |
| 325 | 294 | ||
| 326 | #endif /* CONFIG_PPC_SPLPAR */ | 295 | #endif /* CONFIG_PPC_SPLPAR */ |
