diff options
author | Christophe Leroy <christophe.leroy@c-s.fr> | 2016-05-17 02:33:46 -0400 |
---|---|---|
committer | Scott Wood <oss@buserror.net> | 2016-07-09 02:43:50 -0400 |
commit | c223c90386bc2306510e0ceacd768a0123ff2a2f (patch) | |
tree | 520a7bc88a7e36bbd0615cc5a035337a36729fb8 /arch/powerpc | |
parent | 1afbf61750364864adf6a17818c5bbbea4dea531 (diff) |
powerpc32: provide VIRT_CPU_ACCOUNTING
This patch provides VIRT_CPU_ACCOUTING to PPC32 architecture.
PPC32 doesn't have the PACA structure, so we use the task_info
structure to store the accounting data.
In order to reuse on PPC32 the PPC64 functions, all u64 data has
been replaced by 'unsigned long' so that it is u32 on PPC32 and
u64 on PPC64
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
Signed-off-by: Scott Wood <oss@buserror.net>
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/Kconfig | 1 | ||||
-rw-r--r-- | arch/powerpc/include/asm/accounting.h | 24 | ||||
-rw-r--r-- | arch/powerpc/include/asm/cputime.h | 14 | ||||
-rw-r--r-- | arch/powerpc/include/asm/exception-64s.h | 2 | ||||
-rw-r--r-- | arch/powerpc/include/asm/paca.h | 9 | ||||
-rw-r--r-- | arch/powerpc/include/asm/ppc_asm.h | 24 | ||||
-rw-r--r-- | arch/powerpc/include/asm/reg.h | 1 | ||||
-rw-r--r-- | arch/powerpc/include/asm/thread_info.h | 4 | ||||
-rw-r--r-- | arch/powerpc/kernel/asm-offsets.c | 23 | ||||
-rw-r--r-- | arch/powerpc/kernel/entry_32.S | 17 | ||||
-rw-r--r-- | arch/powerpc/kernel/entry_64.S | 6 | ||||
-rw-r--r-- | arch/powerpc/kernel/exceptions-64e.S | 4 | ||||
-rw-r--r-- | arch/powerpc/kernel/time.c | 81 | ||||
-rw-r--r-- | arch/powerpc/platforms/Kconfig.cputype | 1 | ||||
-rw-r--r-- | arch/powerpc/xmon/xmon.c | 14 |
15 files changed, 158 insertions, 67 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index ee82f9a09a85..394f9dc7be08 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
@@ -165,6 +165,7 @@ config PPC | |||
165 | select ARCH_HAS_UBSAN_SANITIZE_ALL | 165 | select ARCH_HAS_UBSAN_SANITIZE_ALL |
166 | select ARCH_SUPPORTS_DEFERRED_STRUCT_PAGE_INIT | 166 | select ARCH_SUPPORTS_DEFERRED_STRUCT_PAGE_INIT |
167 | select HAVE_LIVEPATCH if HAVE_DYNAMIC_FTRACE_WITH_REGS | 167 | select HAVE_LIVEPATCH if HAVE_DYNAMIC_FTRACE_WITH_REGS |
168 | select HAVE_VIRT_CPU_ACCOUNTING | ||
168 | 169 | ||
169 | config GENERIC_CSUM | 170 | config GENERIC_CSUM |
170 | def_bool CPU_LITTLE_ENDIAN | 171 | def_bool CPU_LITTLE_ENDIAN |
diff --git a/arch/powerpc/include/asm/accounting.h b/arch/powerpc/include/asm/accounting.h new file mode 100644 index 000000000000..c133246df467 --- /dev/null +++ b/arch/powerpc/include/asm/accounting.h | |||
@@ -0,0 +1,24 @@ | |||
1 | /* | ||
2 | * Common time accounting prototypes and such for all ppc machines. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or | ||
5 | * modify it under the terms of the GNU General Public License | ||
6 | * as published by the Free Software Foundation; either version | ||
7 | * 2 of the License, or (at your option) any later version. | ||
8 | */ | ||
9 | |||
10 | #ifndef __POWERPC_ACCOUNTING_H | ||
11 | #define __POWERPC_ACCOUNTING_H | ||
12 | |||
13 | /* Stuff for accurate time accounting */ | ||
14 | struct cpu_accounting_data { | ||
15 | unsigned long user_time; /* accumulated usermode TB ticks */ | ||
16 | unsigned long system_time; /* accumulated system TB ticks */ | ||
17 | unsigned long user_time_scaled; /* accumulated usermode SPURR ticks */ | ||
18 | unsigned long starttime; /* TB value snapshot */ | ||
19 | unsigned long starttime_user; /* TB value on exit to usermode */ | ||
20 | unsigned long startspurr; /* SPURR value snapshot */ | ||
21 | unsigned long utime_sspurr; /* ->user_time when ->startspurr set */ | ||
22 | }; | ||
23 | |||
24 | #endif | ||
diff --git a/arch/powerpc/include/asm/cputime.h b/arch/powerpc/include/asm/cputime.h index e2452550bcb1..2dfd4fc41f3e 100644 --- a/arch/powerpc/include/asm/cputime.h +++ b/arch/powerpc/include/asm/cputime.h | |||
@@ -90,11 +90,10 @@ static inline void setup_cputime_one_jiffy(void) | |||
90 | static inline cputime64_t jiffies64_to_cputime64(const u64 jif) | 90 | static inline cputime64_t jiffies64_to_cputime64(const u64 jif) |
91 | { | 91 | { |
92 | u64 ct; | 92 | u64 ct; |
93 | u64 sec; | 93 | u64 sec = jif; |
94 | 94 | ||
95 | /* have to be a little careful about overflow */ | 95 | /* have to be a little careful about overflow */ |
96 | ct = jif % HZ; | 96 | ct = do_div(sec, HZ); |
97 | sec = jif / HZ; | ||
98 | if (ct) { | 97 | if (ct) { |
99 | ct *= tb_ticks_per_sec; | 98 | ct *= tb_ticks_per_sec; |
100 | do_div(ct, HZ); | 99 | do_div(ct, HZ); |
@@ -230,7 +229,16 @@ static inline cputime_t clock_t_to_cputime(const unsigned long clk) | |||
230 | 229 | ||
231 | #define cputime64_to_clock_t(ct) cputime_to_clock_t((cputime_t)(ct)) | 230 | #define cputime64_to_clock_t(ct) cputime_to_clock_t((cputime_t)(ct)) |
232 | 231 | ||
232 | /* | ||
233 | * PPC64 uses PACA which is task independent for storing accounting data while | ||
234 | * PPC32 uses struct thread_info, therefore at task switch the accounting data | ||
235 | * has to be populated in the new task | ||
236 | */ | ||
237 | #ifdef CONFIG_PPC64 | ||
233 | static inline void arch_vtime_task_switch(struct task_struct *tsk) { } | 238 | static inline void arch_vtime_task_switch(struct task_struct *tsk) { } |
239 | #else | ||
240 | void arch_vtime_task_switch(struct task_struct *tsk); | ||
241 | #endif | ||
234 | 242 | ||
235 | #endif /* __KERNEL__ */ | 243 | #endif /* __KERNEL__ */ |
236 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ | 244 | #endif /* CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ |
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index 93ae809fe5ea..8bc38d179c36 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h | |||
@@ -287,7 +287,7 @@ do_kvm_##n: \ | |||
287 | std r0,GPR0(r1); /* save r0 in stackframe */ \ | 287 | std r0,GPR0(r1); /* save r0 in stackframe */ \ |
288 | std r10,GPR1(r1); /* save r1 in stackframe */ \ | 288 | std r10,GPR1(r1); /* save r1 in stackframe */ \ |
289 | beq 4f; /* if from kernel mode */ \ | 289 | beq 4f; /* if from kernel mode */ \ |
290 | ACCOUNT_CPU_USER_ENTRY(r9, r10); \ | 290 | ACCOUNT_CPU_USER_ENTRY(r13, r9, r10); \ |
291 | SAVE_PPR(area, r9, r10); \ | 291 | SAVE_PPR(area, r9, r10); \ |
292 | 4: EXCEPTION_PROLOG_COMMON_2(area) \ | 292 | 4: EXCEPTION_PROLOG_COMMON_2(area) \ |
293 | EXCEPTION_PROLOG_COMMON_3(n) \ | 293 | EXCEPTION_PROLOG_COMMON_3(n) \ |
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h index 546540b91095..ad171e979ab0 100644 --- a/arch/powerpc/include/asm/paca.h +++ b/arch/powerpc/include/asm/paca.h | |||
@@ -25,6 +25,7 @@ | |||
25 | #ifdef CONFIG_KVM_BOOK3S_64_HANDLER | 25 | #ifdef CONFIG_KVM_BOOK3S_64_HANDLER |
26 | #include <asm/kvm_book3s_asm.h> | 26 | #include <asm/kvm_book3s_asm.h> |
27 | #endif | 27 | #endif |
28 | #include <asm/accounting.h> | ||
28 | 29 | ||
29 | register struct paca_struct *local_paca asm("r13"); | 30 | register struct paca_struct *local_paca asm("r13"); |
30 | 31 | ||
@@ -184,13 +185,7 @@ struct paca_struct { | |||
184 | #endif | 185 | #endif |
185 | 186 | ||
186 | /* Stuff for accurate time accounting */ | 187 | /* Stuff for accurate time accounting */ |
187 | u64 user_time; /* accumulated usermode TB ticks */ | 188 | struct cpu_accounting_data accounting; |
188 | u64 system_time; /* accumulated system TB ticks */ | ||
189 | u64 user_time_scaled; /* accumulated usermode SPURR ticks */ | ||
190 | u64 starttime; /* TB value snapshot */ | ||
191 | u64 starttime_user; /* TB value on exit to usermode */ | ||
192 | u64 startspurr; /* SPURR value snapshot */ | ||
193 | u64 utime_sspurr; /* ->user_time when ->startspurr set */ | ||
194 | u64 stolen_time; /* TB ticks taken by hypervisor */ | 189 | u64 stolen_time; /* TB ticks taken by hypervisor */ |
195 | u64 dtl_ridx; /* read index in dispatch log */ | 190 | u64 dtl_ridx; /* read index in dispatch log */ |
196 | struct dtl_entry *dtl_curr; /* pointer corresponding to dtl_ridx */ | 191 | struct dtl_entry *dtl_curr; /* pointer corresponding to dtl_ridx */ |
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h index 7b591f98edcc..96b06dc93b4c 100644 --- a/arch/powerpc/include/asm/ppc_asm.h +++ b/arch/powerpc/include/asm/ppc_asm.h | |||
@@ -24,27 +24,27 @@ | |||
24 | */ | 24 | */ |
25 | 25 | ||
26 | #ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE | 26 | #ifndef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE |
27 | #define ACCOUNT_CPU_USER_ENTRY(ra, rb) | 27 | #define ACCOUNT_CPU_USER_ENTRY(ptr, ra, rb) |
28 | #define ACCOUNT_CPU_USER_EXIT(ra, rb) | 28 | #define ACCOUNT_CPU_USER_EXIT(ptr, ra, rb) |
29 | #define ACCOUNT_STOLEN_TIME | 29 | #define ACCOUNT_STOLEN_TIME |
30 | #else | 30 | #else |
31 | #define ACCOUNT_CPU_USER_ENTRY(ra, rb) \ | 31 | #define ACCOUNT_CPU_USER_ENTRY(ptr, ra, rb) \ |
32 | MFTB(ra); /* get timebase */ \ | 32 | MFTB(ra); /* get timebase */ \ |
33 | ld rb,PACA_STARTTIME_USER(r13); \ | 33 | PPC_LL rb, ACCOUNT_STARTTIME_USER(ptr); \ |
34 | std ra,PACA_STARTTIME(r13); \ | 34 | PPC_STL ra, ACCOUNT_STARTTIME(ptr); \ |
35 | subf rb,rb,ra; /* subtract start value */ \ | 35 | subf rb,rb,ra; /* subtract start value */ \ |
36 | ld ra,PACA_USER_TIME(r13); \ | 36 | PPC_LL ra, ACCOUNT_USER_TIME(ptr); \ |
37 | add ra,ra,rb; /* add on to user time */ \ | 37 | add ra,ra,rb; /* add on to user time */ \ |
38 | std ra,PACA_USER_TIME(r13); \ | 38 | PPC_STL ra, ACCOUNT_USER_TIME(ptr); \ |
39 | 39 | ||
40 | #define ACCOUNT_CPU_USER_EXIT(ra, rb) \ | 40 | #define ACCOUNT_CPU_USER_EXIT(ptr, ra, rb) \ |
41 | MFTB(ra); /* get timebase */ \ | 41 | MFTB(ra); /* get timebase */ \ |
42 | ld rb,PACA_STARTTIME(r13); \ | 42 | PPC_LL rb, ACCOUNT_STARTTIME(ptr); \ |
43 | std ra,PACA_STARTTIME_USER(r13); \ | 43 | PPC_STL ra, ACCOUNT_STARTTIME_USER(ptr); \ |
44 | subf rb,rb,ra; /* subtract start value */ \ | 44 | subf rb,rb,ra; /* subtract start value */ \ |
45 | ld ra,PACA_SYSTEM_TIME(r13); \ | 45 | PPC_LL ra, ACCOUNT_SYSTEM_TIME(ptr); \ |
46 | add ra,ra,rb; /* add on to system time */ \ | 46 | add ra,ra,rb; /* add on to system time */ \ |
47 | std ra,PACA_SYSTEM_TIME(r13) | 47 | PPC_STL ra, ACCOUNT_SYSTEM_TIME(ptr) |
48 | 48 | ||
49 | #ifdef CONFIG_PPC_SPLPAR | 49 | #ifdef CONFIG_PPC_SPLPAR |
50 | #define ACCOUNT_STOLEN_TIME \ | 50 | #define ACCOUNT_STOLEN_TIME \ |
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h index 320136f5fe28..d383f13b9fac 100644 --- a/arch/powerpc/include/asm/reg.h +++ b/arch/powerpc/include/asm/reg.h | |||
@@ -1294,6 +1294,7 @@ static inline unsigned long mfvtb (void) | |||
1294 | asm volatile("mfspr %0, %1" : "=r" (rval) : \ | 1294 | asm volatile("mfspr %0, %1" : "=r" (rval) : \ |
1295 | "i" (SPRN_TBRU)); rval;}) | 1295 | "i" (SPRN_TBRU)); rval;}) |
1296 | #endif | 1296 | #endif |
1297 | #define mftb() mftbl() | ||
1297 | #endif /* !__powerpc64__ */ | 1298 | #endif /* !__powerpc64__ */ |
1298 | 1299 | ||
1299 | #define mttbl(v) asm volatile("mttbl %0":: "r"(v)) | 1300 | #define mttbl(v) asm volatile("mttbl %0":: "r"(v)) |
diff --git a/arch/powerpc/include/asm/thread_info.h b/arch/powerpc/include/asm/thread_info.h index 8febc3f66d53..b21bb1f72314 100644 --- a/arch/powerpc/include/asm/thread_info.h +++ b/arch/powerpc/include/asm/thread_info.h | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <asm/processor.h> | 33 | #include <asm/processor.h> |
34 | #include <asm/page.h> | 34 | #include <asm/page.h> |
35 | #include <linux/stringify.h> | 35 | #include <linux/stringify.h> |
36 | #include <asm/accounting.h> | ||
36 | 37 | ||
37 | /* | 38 | /* |
38 | * low level task data. | 39 | * low level task data. |
@@ -46,6 +47,9 @@ struct thread_info { | |||
46 | #ifdef CONFIG_LIVEPATCH | 47 | #ifdef CONFIG_LIVEPATCH |
47 | unsigned long *livepatch_sp; | 48 | unsigned long *livepatch_sp; |
48 | #endif | 49 | #endif |
50 | #if defined(CONFIG_VIRT_CPU_ACCOUNTING_NATIVE) && defined(CONFIG_PPC32) | ||
51 | struct cpu_accounting_data accounting; | ||
52 | #endif | ||
49 | /* low level flags - has atomic operations done on it */ | 53 | /* low level flags - has atomic operations done on it */ |
50 | unsigned long flags ____cacheline_aligned_in_smp; | 54 | unsigned long flags ____cacheline_aligned_in_smp; |
51 | }; | 55 | }; |
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 5b99f956e32f..047892869257 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -240,13 +240,28 @@ int main(void) | |||
240 | DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); | 240 | DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); |
241 | DEFINE(PACAKEXECSTATE, offsetof(struct paca_struct, kexec_state)); | 241 | DEFINE(PACAKEXECSTATE, offsetof(struct paca_struct, kexec_state)); |
242 | DEFINE(PACA_DSCR_DEFAULT, offsetof(struct paca_struct, dscr_default)); | 242 | DEFINE(PACA_DSCR_DEFAULT, offsetof(struct paca_struct, dscr_default)); |
243 | DEFINE(PACA_STARTTIME, offsetof(struct paca_struct, starttime)); | 243 | DEFINE(ACCOUNT_STARTTIME, |
244 | DEFINE(PACA_STARTTIME_USER, offsetof(struct paca_struct, starttime_user)); | 244 | offsetof(struct paca_struct, accounting.starttime)); |
245 | DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time)); | 245 | DEFINE(ACCOUNT_STARTTIME_USER, |
246 | DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time)); | 246 | offsetof(struct paca_struct, accounting.starttime_user)); |
247 | DEFINE(ACCOUNT_USER_TIME, | ||
248 | offsetof(struct paca_struct, accounting.user_time)); | ||
249 | DEFINE(ACCOUNT_SYSTEM_TIME, | ||
250 | offsetof(struct paca_struct, accounting.system_time)); | ||
247 | DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save)); | 251 | DEFINE(PACA_TRAP_SAVE, offsetof(struct paca_struct, trap_save)); |
248 | DEFINE(PACA_NAPSTATELOST, offsetof(struct paca_struct, nap_state_lost)); | 252 | DEFINE(PACA_NAPSTATELOST, offsetof(struct paca_struct, nap_state_lost)); |
249 | DEFINE(PACA_SPRG_VDSO, offsetof(struct paca_struct, sprg_vdso)); | 253 | DEFINE(PACA_SPRG_VDSO, offsetof(struct paca_struct, sprg_vdso)); |
254 | #else /* CONFIG_PPC64 */ | ||
255 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE | ||
256 | DEFINE(ACCOUNT_STARTTIME, | ||
257 | offsetof(struct thread_info, accounting.starttime)); | ||
258 | DEFINE(ACCOUNT_STARTTIME_USER, | ||
259 | offsetof(struct thread_info, accounting.starttime_user)); | ||
260 | DEFINE(ACCOUNT_USER_TIME, | ||
261 | offsetof(struct thread_info, accounting.user_time)); | ||
262 | DEFINE(ACCOUNT_SYSTEM_TIME, | ||
263 | offsetof(struct thread_info, accounting.system_time)); | ||
264 | #endif | ||
250 | #endif /* CONFIG_PPC64 */ | 265 | #endif /* CONFIG_PPC64 */ |
251 | 266 | ||
252 | /* RTAS */ | 267 | /* RTAS */ |
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 2405631e91a2..9899032230b4 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S | |||
@@ -175,6 +175,12 @@ transfer_to_handler: | |||
175 | addi r12,r12,-1 | 175 | addi r12,r12,-1 |
176 | stw r12,4(r11) | 176 | stw r12,4(r11) |
177 | #endif | 177 | #endif |
178 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE | ||
179 | CURRENT_THREAD_INFO(r9, r1) | ||
180 | tophys(r9, r9) | ||
181 | ACCOUNT_CPU_USER_ENTRY(r9, r11, r12) | ||
182 | #endif | ||
183 | |||
178 | b 3f | 184 | b 3f |
179 | 185 | ||
180 | 2: /* if from kernel, check interrupted DOZE/NAP mode and | 186 | 2: /* if from kernel, check interrupted DOZE/NAP mode and |
@@ -398,6 +404,13 @@ BEGIN_FTR_SECTION | |||
398 | lwarx r7,0,r1 | 404 | lwarx r7,0,r1 |
399 | END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX) | 405 | END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX) |
400 | stwcx. r0,0,r1 /* to clear the reservation */ | 406 | stwcx. r0,0,r1 /* to clear the reservation */ |
407 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE | ||
408 | andi. r4,r8,MSR_PR | ||
409 | beq 3f | ||
410 | CURRENT_THREAD_INFO(r4, r1) | ||
411 | ACCOUNT_CPU_USER_EXIT(r4, r5, r7) | ||
412 | 3: | ||
413 | #endif | ||
401 | lwz r4,_LINK(r1) | 414 | lwz r4,_LINK(r1) |
402 | lwz r5,_CCR(r1) | 415 | lwz r5,_CCR(r1) |
403 | mtlr r4 | 416 | mtlr r4 |
@@ -769,6 +782,10 @@ restore_user: | |||
769 | andis. r10,r0,DBCR0_IDM@h | 782 | andis. r10,r0,DBCR0_IDM@h |
770 | bnel- load_dbcr0 | 783 | bnel- load_dbcr0 |
771 | #endif | 784 | #endif |
785 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING_NATIVE | ||
786 | CURRENT_THREAD_INFO(r9, r1) | ||
787 | ACCOUNT_CPU_USER_EXIT(r9, r10, r11) | ||
788 | #endif | ||
772 | 789 | ||
773 | b restore | 790 | b restore |
774 | 791 | ||
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 2e0c565754aa..fcb2887f5a33 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
@@ -72,7 +72,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_TM) | |||
72 | std r0,GPR0(r1) | 72 | std r0,GPR0(r1) |
73 | std r10,GPR1(r1) | 73 | std r10,GPR1(r1) |
74 | beq 2f /* if from kernel mode */ | 74 | beq 2f /* if from kernel mode */ |
75 | ACCOUNT_CPU_USER_ENTRY(r10, r11) | 75 | ACCOUNT_CPU_USER_ENTRY(r13, r10, r11) |
76 | 2: std r2,GPR2(r1) | 76 | 2: std r2,GPR2(r1) |
77 | std r3,GPR3(r1) | 77 | std r3,GPR3(r1) |
78 | mfcr r2 | 78 | mfcr r2 |
@@ -246,7 +246,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_STCX_CHECKS_ADDRESS) | |||
246 | ld r4,_LINK(r1) | 246 | ld r4,_LINK(r1) |
247 | 247 | ||
248 | beq- 1f | 248 | beq- 1f |
249 | ACCOUNT_CPU_USER_EXIT(r11, r12) | 249 | ACCOUNT_CPU_USER_EXIT(r13, r11, r12) |
250 | 250 | ||
251 | BEGIN_FTR_SECTION | 251 | BEGIN_FTR_SECTION |
252 | HMT_MEDIUM_LOW | 252 | HMT_MEDIUM_LOW |
@@ -859,7 +859,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) | |||
859 | BEGIN_FTR_SECTION | 859 | BEGIN_FTR_SECTION |
860 | mtspr SPRN_PPR,r2 /* Restore PPR */ | 860 | mtspr SPRN_PPR,r2 /* Restore PPR */ |
861 | END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) | 861 | END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR) |
862 | ACCOUNT_CPU_USER_EXIT(r2, r4) | 862 | ACCOUNT_CPU_USER_EXIT(r13, r2, r4) |
863 | REST_GPR(13, r1) | 863 | REST_GPR(13, r1) |
864 | 1: | 864 | 1: |
865 | mtspr SPRN_SRR1,r3 | 865 | mtspr SPRN_SRR1,r3 |
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S index 2d3b40fd9bac..38a1f96430e1 100644 --- a/arch/powerpc/kernel/exceptions-64e.S +++ b/arch/powerpc/kernel/exceptions-64e.S | |||
@@ -386,7 +386,7 @@ exc_##n##_common: \ | |||
386 | std r10,_NIP(r1); /* save SRR0 to stackframe */ \ | 386 | std r10,_NIP(r1); /* save SRR0 to stackframe */ \ |
387 | std r11,_MSR(r1); /* save SRR1 to stackframe */ \ | 387 | std r11,_MSR(r1); /* save SRR1 to stackframe */ \ |
388 | beq 2f; /* if from kernel mode */ \ | 388 | beq 2f; /* if from kernel mode */ \ |
389 | ACCOUNT_CPU_USER_ENTRY(r10,r11);/* accounting (uses cr0+eq) */ \ | 389 | ACCOUNT_CPU_USER_ENTRY(r13,r10,r11);/* accounting (uses cr0+eq) */ \ |
390 | 2: ld r3,excf+EX_R10(r13); /* get back r10 */ \ | 390 | 2: ld r3,excf+EX_R10(r13); /* get back r10 */ \ |
391 | ld r4,excf+EX_R11(r13); /* get back r11 */ \ | 391 | ld r4,excf+EX_R11(r13); /* get back r11 */ \ |
392 | mfspr r5,scratch; /* get back r13 */ \ | 392 | mfspr r5,scratch; /* get back r13 */ \ |
@@ -1059,7 +1059,7 @@ fast_exception_return: | |||
1059 | andi. r6,r10,MSR_PR | 1059 | andi. r6,r10,MSR_PR |
1060 | REST_2GPRS(6, r1) | 1060 | REST_2GPRS(6, r1) |
1061 | beq 1f | 1061 | beq 1f |
1062 | ACCOUNT_CPU_USER_EXIT(r10, r11) | 1062 | ACCOUNT_CPU_USER_EXIT(r13, r10, r11) |
1063 | ld r0,GPR13(r1) | 1063 | ld r0,GPR13(r1) |
1064 | 1064 | ||
1065 | 1: stdcx. r0,0,r1 /* to clear the reservation */ | 1065 | 1: stdcx. r0,0,r1 /* to clear the reservation */ |
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 6b4d01d1ccf0..4e7759c8ca30 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -167,7 +167,15 @@ DEFINE_PER_CPU(unsigned long, cputime_scaled_last_delta); | |||
167 | 167 | ||
168 | cputime_t cputime_one_jiffy; | 168 | cputime_t cputime_one_jiffy; |
169 | 169 | ||
170 | #ifdef CONFIG_PPC_SPLPAR | ||
170 | void (*dtl_consumer)(struct dtl_entry *, u64); | 171 | void (*dtl_consumer)(struct dtl_entry *, u64); |
172 | #endif | ||
173 | |||
174 | #ifdef CONFIG_PPC64 | ||
175 | #define get_accounting(tsk) (&get_paca()->accounting) | ||
176 | #else | ||
177 | #define get_accounting(tsk) (&task_thread_info(tsk)->accounting) | ||
178 | #endif | ||
171 | 179 | ||
172 | static void calc_cputime_factors(void) | 180 | static void calc_cputime_factors(void) |
173 | { | 181 | { |
@@ -187,7 +195,7 @@ static void calc_cputime_factors(void) | |||
187 | * Read the SPURR on systems that have it, otherwise the PURR, | 195 | * Read the SPURR on systems that have it, otherwise the PURR, |
188 | * or if that doesn't exist return the timebase value passed in. | 196 | * or if that doesn't exist return the timebase value passed in. |
189 | */ | 197 | */ |
190 | static u64 read_spurr(u64 tb) | 198 | static unsigned long read_spurr(unsigned long tb) |
191 | { | 199 | { |
192 | if (cpu_has_feature(CPU_FTR_SPURR)) | 200 | if (cpu_has_feature(CPU_FTR_SPURR)) |
193 | return mfspr(SPRN_SPURR); | 201 | return mfspr(SPRN_SPURR); |
@@ -250,8 +258,8 @@ static u64 scan_dispatch_log(u64 stop_tb) | |||
250 | void accumulate_stolen_time(void) | 258 | void accumulate_stolen_time(void) |
251 | { | 259 | { |
252 | u64 sst, ust; | 260 | u64 sst, ust; |
253 | |||
254 | u8 save_soft_enabled = local_paca->soft_enabled; | 261 | u8 save_soft_enabled = local_paca->soft_enabled; |
262 | struct cpu_accounting_data *acct = &local_paca->accounting; | ||
255 | 263 | ||
256 | /* We are called early in the exception entry, before | 264 | /* We are called early in the exception entry, before |
257 | * soft/hard_enabled are sync'ed to the expected state | 265 | * soft/hard_enabled are sync'ed to the expected state |
@@ -261,10 +269,10 @@ void accumulate_stolen_time(void) | |||
261 | */ | 269 | */ |
262 | local_paca->soft_enabled = 0; | 270 | local_paca->soft_enabled = 0; |
263 | 271 | ||
264 | sst = scan_dispatch_log(local_paca->starttime_user); | 272 | sst = scan_dispatch_log(acct->starttime_user); |
265 | ust = scan_dispatch_log(local_paca->starttime); | 273 | ust = scan_dispatch_log(acct->starttime); |
266 | local_paca->system_time -= sst; | 274 | acct->system_time -= sst; |
267 | local_paca->user_time -= ust; | 275 | acct->user_time -= ust; |
268 | local_paca->stolen_time += ust + sst; | 276 | local_paca->stolen_time += ust + sst; |
269 | 277 | ||
270 | local_paca->soft_enabled = save_soft_enabled; | 278 | local_paca->soft_enabled = save_soft_enabled; |
@@ -276,7 +284,7 @@ static inline u64 calculate_stolen_time(u64 stop_tb) | |||
276 | 284 | ||
277 | if (get_paca()->dtl_ridx != be64_to_cpu(get_lppaca()->dtl_idx)) { | 285 | if (get_paca()->dtl_ridx != be64_to_cpu(get_lppaca()->dtl_idx)) { |
278 | stolen = scan_dispatch_log(stop_tb); | 286 | stolen = scan_dispatch_log(stop_tb); |
279 | get_paca()->system_time -= stolen; | 287 | get_paca()->accounting.system_time -= stolen; |
280 | } | 288 | } |
281 | 289 | ||
282 | stolen += get_paca()->stolen_time; | 290 | stolen += get_paca()->stolen_time; |
@@ -296,27 +304,29 @@ static inline u64 calculate_stolen_time(u64 stop_tb) | |||
296 | * Account time for a transition between system, hard irq | 304 | * Account time for a transition between system, hard irq |
297 | * or soft irq state. | 305 | * or soft irq state. |
298 | */ | 306 | */ |
299 | static u64 vtime_delta(struct task_struct *tsk, | 307 | static unsigned long vtime_delta(struct task_struct *tsk, |
300 | u64 *sys_scaled, u64 *stolen) | 308 | unsigned long *sys_scaled, |
309 | unsigned long *stolen) | ||
301 | { | 310 | { |
302 | u64 now, nowscaled, deltascaled; | 311 | unsigned long now, nowscaled, deltascaled; |
303 | u64 udelta, delta, user_scaled; | 312 | unsigned long udelta, delta, user_scaled; |
313 | struct cpu_accounting_data *acct = get_accounting(tsk); | ||
304 | 314 | ||
305 | WARN_ON_ONCE(!irqs_disabled()); | 315 | WARN_ON_ONCE(!irqs_disabled()); |
306 | 316 | ||
307 | now = mftb(); | 317 | now = mftb(); |
308 | nowscaled = read_spurr(now); | 318 | nowscaled = read_spurr(now); |
309 | get_paca()->system_time += now - get_paca()->starttime; | 319 | acct->system_time += now - acct->starttime; |
310 | get_paca()->starttime = now; | 320 | acct->starttime = now; |
311 | deltascaled = nowscaled - get_paca()->startspurr; | 321 | deltascaled = nowscaled - acct->startspurr; |
312 | get_paca()->startspurr = nowscaled; | 322 | acct->startspurr = nowscaled; |
313 | 323 | ||
314 | *stolen = calculate_stolen_time(now); | 324 | *stolen = calculate_stolen_time(now); |
315 | 325 | ||
316 | delta = get_paca()->system_time; | 326 | delta = acct->system_time; |
317 | get_paca()->system_time = 0; | 327 | acct->system_time = 0; |
318 | udelta = get_paca()->user_time - get_paca()->utime_sspurr; | 328 | udelta = acct->user_time - acct->utime_sspurr; |
319 | get_paca()->utime_sspurr = get_paca()->user_time; | 329 | acct->utime_sspurr = acct->user_time; |
320 | 330 | ||
321 | /* | 331 | /* |
322 | * Because we don't read the SPURR on every kernel entry/exit, | 332 | * Because we don't read the SPURR on every kernel entry/exit, |
@@ -338,14 +348,14 @@ static u64 vtime_delta(struct task_struct *tsk, | |||
338 | *sys_scaled = deltascaled; | 348 | *sys_scaled = deltascaled; |
339 | } | 349 | } |
340 | } | 350 | } |
341 | get_paca()->user_time_scaled += user_scaled; | 351 | acct->user_time_scaled += user_scaled; |
342 | 352 | ||
343 | return delta; | 353 | return delta; |
344 | } | 354 | } |
345 | 355 | ||
346 | void vtime_account_system(struct task_struct *tsk) | 356 | void vtime_account_system(struct task_struct *tsk) |
347 | { | 357 | { |
348 | u64 delta, sys_scaled, stolen; | 358 | unsigned long delta, sys_scaled, stolen; |
349 | 359 | ||
350 | delta = vtime_delta(tsk, &sys_scaled, &stolen); | 360 | delta = vtime_delta(tsk, &sys_scaled, &stolen); |
351 | account_system_time(tsk, 0, delta, sys_scaled); | 361 | account_system_time(tsk, 0, delta, sys_scaled); |
@@ -356,7 +366,7 @@ EXPORT_SYMBOL_GPL(vtime_account_system); | |||
356 | 366 | ||
357 | void vtime_account_idle(struct task_struct *tsk) | 367 | void vtime_account_idle(struct task_struct *tsk) |
358 | { | 368 | { |
359 | u64 delta, sys_scaled, stolen; | 369 | unsigned long delta, sys_scaled, stolen; |
360 | 370 | ||
361 | delta = vtime_delta(tsk, &sys_scaled, &stolen); | 371 | delta = vtime_delta(tsk, &sys_scaled, &stolen); |
362 | account_idle_time(delta + stolen); | 372 | account_idle_time(delta + stolen); |
@@ -374,15 +384,32 @@ void vtime_account_idle(struct task_struct *tsk) | |||
374 | void vtime_account_user(struct task_struct *tsk) | 384 | void vtime_account_user(struct task_struct *tsk) |
375 | { | 385 | { |
376 | cputime_t utime, utimescaled; | 386 | cputime_t utime, utimescaled; |
387 | struct cpu_accounting_data *acct = get_accounting(tsk); | ||
377 | 388 | ||
378 | utime = get_paca()->user_time; | 389 | utime = acct->user_time; |
379 | utimescaled = get_paca()->user_time_scaled; | 390 | utimescaled = acct->user_time_scaled; |
380 | get_paca()->user_time = 0; | 391 | acct->user_time = 0; |
381 | get_paca()->user_time_scaled = 0; | 392 | acct->user_time_scaled = 0; |
382 | get_paca()->utime_sspurr = 0; | 393 | acct->utime_sspurr = 0; |
383 | account_user_time(tsk, utime, utimescaled); | 394 | account_user_time(tsk, utime, utimescaled); |
384 | } | 395 | } |
385 | 396 | ||
397 | #ifdef CONFIG_PPC32 | ||
398 | /* | ||
399 | * Called from the context switch with interrupts disabled, to charge all | ||
400 | * accumulated times to the current process, and to prepare accounting on | ||
401 | * the next process. | ||
402 | */ | ||
403 | void arch_vtime_task_switch(struct task_struct *prev) | ||
404 | { | ||
405 | struct cpu_accounting_data *acct = get_accounting(current); | ||
406 | |||
407 | acct->starttime = get_accounting(prev)->starttime; | ||
408 | acct->system_time = 0; | ||
409 | acct->user_time = 0; | ||
410 | } | ||
411 | #endif /* CONFIG_PPC32 */ | ||
412 | |||
386 | #else /* ! CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ | 413 | #else /* ! CONFIG_VIRT_CPU_ACCOUNTING_NATIVE */ |
387 | #define calc_cputime_factors() | 414 | #define calc_cputime_factors() |
388 | #endif | 415 | #endif |
diff --git a/arch/powerpc/platforms/Kconfig.cputype b/arch/powerpc/platforms/Kconfig.cputype index 77e9b8d591fb..f32edec13fd1 100644 --- a/arch/powerpc/platforms/Kconfig.cputype +++ b/arch/powerpc/platforms/Kconfig.cputype | |||
@@ -1,7 +1,6 @@ | |||
1 | config PPC64 | 1 | config PPC64 |
2 | bool "64-bit kernel" | 2 | bool "64-bit kernel" |
3 | default n | 3 | default n |
4 | select HAVE_VIRT_CPU_ACCOUNTING | ||
5 | select ZLIB_DEFLATE | 4 | select ZLIB_DEFLATE |
6 | help | 5 | help |
7 | This option selects whether a 32-bit or a 64-bit kernel | 6 | This option selects whether a 32-bit or a 64-bit kernel |
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c index c5e155108be5..4f7c29d87ec3 100644 --- a/arch/powerpc/xmon/xmon.c +++ b/arch/powerpc/xmon/xmon.c | |||
@@ -2213,13 +2213,13 @@ static void dump_one_paca(int cpu) | |||
2213 | DUMP(p, subcore_sibling_mask, "x"); | 2213 | DUMP(p, subcore_sibling_mask, "x"); |
2214 | #endif | 2214 | #endif |
2215 | 2215 | ||
2216 | DUMP(p, user_time, "llx"); | 2216 | DUMP(p, accounting.user_time, "llx"); |
2217 | DUMP(p, system_time, "llx"); | 2217 | DUMP(p, accounting.system_time, "llx"); |
2218 | DUMP(p, user_time_scaled, "llx"); | 2218 | DUMP(p, accounting.user_time_scaled, "llx"); |
2219 | DUMP(p, starttime, "llx"); | 2219 | DUMP(p, accounting.starttime, "llx"); |
2220 | DUMP(p, starttime_user, "llx"); | 2220 | DUMP(p, accounting.starttime_user, "llx"); |
2221 | DUMP(p, startspurr, "llx"); | 2221 | DUMP(p, accounting.startspurr, "llx"); |
2222 | DUMP(p, utime_sspurr, "llx"); | 2222 | DUMP(p, accounting.utime_sspurr, "llx"); |
2223 | DUMP(p, stolen_time, "llx"); | 2223 | DUMP(p, stolen_time, "llx"); |
2224 | #undef DUMP | 2224 | #undef DUMP |
2225 | 2225 | ||