diff options
Diffstat (limited to 'arch/powerpc/kernel')
28 files changed, 675 insertions, 91 deletions
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index c9a660e4c2db..882889b15926 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
| @@ -136,6 +136,9 @@ int main(void) | |||
| 136 | DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp)); | 136 | DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp)); |
| 137 | DEFINE(PACALPPACAPTR, offsetof(struct paca_struct, lppaca_ptr)); | 137 | DEFINE(PACALPPACAPTR, offsetof(struct paca_struct, lppaca_ptr)); |
| 138 | DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); | 138 | DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); |
| 139 | DEFINE(PACA_STARTPURR, offsetof(struct paca_struct, startpurr)); | ||
| 140 | DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time)); | ||
| 141 | DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time)); | ||
| 139 | 142 | ||
| 140 | DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0)); | 143 | DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0)); |
| 141 | DEFINE(LPPACASRR1, offsetof(struct lppaca, saved_srr1)); | 144 | DEFINE(LPPACASRR1, offsetof(struct lppaca, saved_srr1)); |
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index e4e81374cb9a..39e348a3ade2 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
| @@ -894,7 +894,7 @@ struct cpu_spec cpu_specs[] = { | |||
| 894 | .platform = "ppc405", | 894 | .platform = "ppc405", |
| 895 | }, | 895 | }, |
| 896 | { /* Xilinx Virtex-II Pro */ | 896 | { /* Xilinx Virtex-II Pro */ |
| 897 | .pvr_mask = 0xffff0000, | 897 | .pvr_mask = 0xfffff000, |
| 898 | .pvr_value = 0x20010000, | 898 | .pvr_value = 0x20010000, |
| 899 | .cpu_name = "Virtex-II Pro", | 899 | .cpu_name = "Virtex-II Pro", |
| 900 | .cpu_features = CPU_FTRS_40X, | 900 | .cpu_features = CPU_FTRS_40X, |
| @@ -904,6 +904,16 @@ struct cpu_spec cpu_specs[] = { | |||
| 904 | .dcache_bsize = 32, | 904 | .dcache_bsize = 32, |
| 905 | .platform = "ppc405", | 905 | .platform = "ppc405", |
| 906 | }, | 906 | }, |
| 907 | { /* Xilinx Virtex-4 FX */ | ||
| 908 | .pvr_mask = 0xfffff000, | ||
| 909 | .pvr_value = 0x20011000, | ||
| 910 | .cpu_name = "Virtex-4 FX", | ||
| 911 | .cpu_features = CPU_FTRS_40X, | ||
| 912 | .cpu_user_features = PPC_FEATURE_32 | | ||
| 913 | PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC, | ||
| 914 | .icache_bsize = 32, | ||
| 915 | .dcache_bsize = 32, | ||
| 916 | }, | ||
| 907 | { /* 405EP */ | 917 | { /* 405EP */ |
| 908 | .pvr_mask = 0xffff0000, | 918 | .pvr_mask = 0xffff0000, |
| 909 | .pvr_value = 0x51210000, | 919 | .pvr_value = 0x51210000, |
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 24be0cf86d7f..1060155d84c3 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
| @@ -1,6 +1,4 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * arch/ppc64/kernel/entry.S | ||
| 3 | * | ||
| 4 | * PowerPC version | 2 | * PowerPC version |
| 5 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | 3 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) |
| 6 | * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP | 4 | * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP |
| @@ -63,6 +61,7 @@ system_call_common: | |||
| 63 | std r12,_MSR(r1) | 61 | std r12,_MSR(r1) |
| 64 | std r0,GPR0(r1) | 62 | std r0,GPR0(r1) |
| 65 | std r10,GPR1(r1) | 63 | std r10,GPR1(r1) |
| 64 | ACCOUNT_CPU_USER_ENTRY(r10, r11) | ||
| 66 | std r2,GPR2(r1) | 65 | std r2,GPR2(r1) |
| 67 | std r3,GPR3(r1) | 66 | std r3,GPR3(r1) |
| 68 | std r4,GPR4(r1) | 67 | std r4,GPR4(r1) |
| @@ -170,8 +169,9 @@ syscall_error_cont: | |||
| 170 | stdcx. r0,0,r1 /* to clear the reservation */ | 169 | stdcx. r0,0,r1 /* to clear the reservation */ |
| 171 | andi. r6,r8,MSR_PR | 170 | andi. r6,r8,MSR_PR |
| 172 | ld r4,_LINK(r1) | 171 | ld r4,_LINK(r1) |
| 173 | beq- 1f /* only restore r13 if */ | 172 | beq- 1f |
| 174 | ld r13,GPR13(r1) /* returning to usermode */ | 173 | ACCOUNT_CPU_USER_EXIT(r11, r12) |
| 174 | ld r13,GPR13(r1) /* only restore r13 if returning to usermode */ | ||
| 175 | 1: ld r2,GPR2(r1) | 175 | 1: ld r2,GPR2(r1) |
| 176 | li r12,MSR_RI | 176 | li r12,MSR_RI |
| 177 | andc r11,r10,r12 | 177 | andc r11,r10,r12 |
| @@ -322,7 +322,7 @@ _GLOBAL(ret_from_fork) | |||
| 322 | * the fork code also. | 322 | * the fork code also. |
| 323 | * | 323 | * |
| 324 | * The code which creates the new task context is in 'copy_thread' | 324 | * The code which creates the new task context is in 'copy_thread' |
| 325 | * in arch/ppc64/kernel/process.c | 325 | * in arch/powerpc/kernel/process.c |
| 326 | */ | 326 | */ |
| 327 | .align 7 | 327 | .align 7 |
| 328 | _GLOBAL(_switch) | 328 | _GLOBAL(_switch) |
| @@ -486,6 +486,7 @@ restore: | |||
| 486 | * userspace | 486 | * userspace |
| 487 | */ | 487 | */ |
| 488 | beq 1f | 488 | beq 1f |
| 489 | ACCOUNT_CPU_USER_EXIT(r3, r4) | ||
| 489 | REST_GPR(13, r1) | 490 | REST_GPR(13, r1) |
| 490 | 1: | 491 | 1: |
| 491 | ld r3,_CTR(r1) | 492 | ld r3,_CTR(r1) |
diff --git a/arch/powerpc/kernel/firmware.c b/arch/powerpc/kernel/firmware.c index 65eae752a527..4d37a3cb80f6 100644 --- a/arch/powerpc/kernel/firmware.c +++ b/arch/powerpc/kernel/firmware.c | |||
| @@ -18,28 +18,3 @@ | |||
| 18 | #include <asm/firmware.h> | 18 | #include <asm/firmware.h> |
| 19 | 19 | ||
| 20 | unsigned long ppc64_firmware_features; | 20 | unsigned long ppc64_firmware_features; |
| 21 | |||
| 22 | #ifdef CONFIG_PPC_PSERIES | ||
| 23 | firmware_feature_t firmware_features_table[FIRMWARE_MAX_FEATURES] = { | ||
| 24 | {FW_FEATURE_PFT, "hcall-pft"}, | ||
| 25 | {FW_FEATURE_TCE, "hcall-tce"}, | ||
| 26 | {FW_FEATURE_SPRG0, "hcall-sprg0"}, | ||
| 27 | {FW_FEATURE_DABR, "hcall-dabr"}, | ||
| 28 | {FW_FEATURE_COPY, "hcall-copy"}, | ||
| 29 | {FW_FEATURE_ASR, "hcall-asr"}, | ||
| 30 | {FW_FEATURE_DEBUG, "hcall-debug"}, | ||
| 31 | {FW_FEATURE_PERF, "hcall-perf"}, | ||
| 32 | {FW_FEATURE_DUMP, "hcall-dump"}, | ||
| 33 | {FW_FEATURE_INTERRUPT, "hcall-interrupt"}, | ||
| 34 | {FW_FEATURE_MIGRATE, "hcall-migrate"}, | ||
| 35 | {FW_FEATURE_PERFMON, "hcall-perfmon"}, | ||
| 36 | {FW_FEATURE_CRQ, "hcall-crq"}, | ||
| 37 | {FW_FEATURE_VIO, "hcall-vio"}, | ||
| 38 | {FW_FEATURE_RDMA, "hcall-rdma"}, | ||
| 39 | {FW_FEATURE_LLAN, "hcall-lLAN"}, | ||
| 40 | {FW_FEATURE_BULK, "hcall-bulk"}, | ||
| 41 | {FW_FEATURE_XDABR, "hcall-xdabr"}, | ||
| 42 | {FW_FEATURE_MULTITCE, "hcall-multi-tce"}, | ||
| 43 | {FW_FEATURE_SPLPAR, "hcall-splpar"}, | ||
| 44 | }; | ||
| 45 | #endif | ||
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S index 8b49679fad54..47c7fa148c9a 100644 --- a/arch/powerpc/kernel/head_44x.S +++ b/arch/powerpc/kernel/head_44x.S | |||
| @@ -1,6 +1,4 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * arch/ppc/kernel/head_44x.S | ||
| 3 | * | ||
| 4 | * Kernel execution entry point code. | 2 | * Kernel execution entry point code. |
| 5 | * | 3 | * |
| 6 | * Copyright (c) 1995-1996 Gary Thomas <gdt@linuxppc.org> | 4 | * Copyright (c) 1995-1996 Gary Thomas <gdt@linuxppc.org> |
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 9b65029dd2a3..35084f3a841b 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
| @@ -1,6 +1,4 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * arch/ppc64/kernel/head.S | ||
| 3 | * | ||
| 4 | * PowerPC version | 2 | * PowerPC version |
| 5 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | 3 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) |
| 6 | * | 4 | * |
| @@ -279,6 +277,7 @@ exception_marker: | |||
| 279 | std r10,0(r1); /* make stack chain pointer */ \ | 277 | std r10,0(r1); /* make stack chain pointer */ \ |
| 280 | std r0,GPR0(r1); /* save r0 in stackframe */ \ | 278 | std r0,GPR0(r1); /* save r0 in stackframe */ \ |
| 281 | std r10,GPR1(r1); /* save r1 in stackframe */ \ | 279 | std r10,GPR1(r1); /* save r1 in stackframe */ \ |
| 280 | ACCOUNT_CPU_USER_ENTRY(r9, r10); \ | ||
| 282 | std r2,GPR2(r1); /* save r2 in stackframe */ \ | 281 | std r2,GPR2(r1); /* save r2 in stackframe */ \ |
| 283 | SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \ | 282 | SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \ |
| 284 | SAVE_2GPRS(7, r1); /* save r7, r8 in stackframe */ \ | 283 | SAVE_2GPRS(7, r1); /* save r7, r8 in stackframe */ \ |
| @@ -846,6 +845,14 @@ fast_exception_return: | |||
| 846 | ld r11,_NIP(r1) | 845 | ld r11,_NIP(r1) |
| 847 | andi. r3,r12,MSR_RI /* check if RI is set */ | 846 | andi. r3,r12,MSR_RI /* check if RI is set */ |
| 848 | beq- unrecov_fer | 847 | beq- unrecov_fer |
| 848 | |||
| 849 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
| 850 | andi. r3,r12,MSR_PR | ||
| 851 | beq 2f | ||
| 852 | ACCOUNT_CPU_USER_EXIT(r3, r4) | ||
| 853 | 2: | ||
| 854 | #endif | ||
| 855 | |||
| 849 | ld r3,_CCR(r1) | 856 | ld r3,_CCR(r1) |
| 850 | ld r4,_LINK(r1) | 857 | ld r4,_LINK(r1) |
| 851 | ld r5,_CTR(r1) | 858 | ld r5,_CTR(r1) |
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index bc6d1ac55235..28941f5ce673 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S | |||
| @@ -1,6 +1,4 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * arch/ppc/kernel/except_8xx.S | ||
| 3 | * | ||
| 4 | * PowerPC version | 2 | * PowerPC version |
| 5 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | 3 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) |
| 6 | * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP | 4 | * Rewritten by Cort Dougan (cort@cs.nmt.edu) for PReP |
diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/head_booke.h new file mode 100644 index 000000000000..8536e7676160 --- /dev/null +++ b/arch/powerpc/kernel/head_booke.h | |||
| @@ -0,0 +1,363 @@ | |||
| 1 | #ifndef __HEAD_BOOKE_H__ | ||
| 2 | #define __HEAD_BOOKE_H__ | ||
| 3 | |||
| 4 | /* | ||
| 5 | * Macros used for common Book-e exception handling | ||
| 6 | */ | ||
| 7 | |||
| 8 | #define SET_IVOR(vector_number, vector_label) \ | ||
| 9 | li r26,vector_label@l; \ | ||
| 10 | mtspr SPRN_IVOR##vector_number,r26; \ | ||
| 11 | sync | ||
| 12 | |||
| 13 | #define NORMAL_EXCEPTION_PROLOG \ | ||
| 14 | mtspr SPRN_SPRG0,r10; /* save two registers to work with */\ | ||
| 15 | mtspr SPRN_SPRG1,r11; \ | ||
| 16 | mtspr SPRN_SPRG4W,r1; \ | ||
| 17 | mfcr r10; /* save CR in r10 for now */\ | ||
| 18 | mfspr r11,SPRN_SRR1; /* check whether user or kernel */\ | ||
| 19 | andi. r11,r11,MSR_PR; \ | ||
| 20 | beq 1f; \ | ||
| 21 | mfspr r1,SPRN_SPRG3; /* if from user, start at top of */\ | ||
| 22 | lwz r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack */\ | ||
| 23 | addi r1,r1,THREAD_SIZE; \ | ||
| 24 | 1: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\ | ||
| 25 | mr r11,r1; \ | ||
| 26 | stw r10,_CCR(r11); /* save various registers */\ | ||
| 27 | stw r12,GPR12(r11); \ | ||
| 28 | stw r9,GPR9(r11); \ | ||
| 29 | mfspr r10,SPRN_SPRG0; \ | ||
| 30 | stw r10,GPR10(r11); \ | ||
| 31 | mfspr r12,SPRN_SPRG1; \ | ||
| 32 | stw r12,GPR11(r11); \ | ||
| 33 | mflr r10; \ | ||
| 34 | stw r10,_LINK(r11); \ | ||
| 35 | mfspr r10,SPRN_SPRG4R; \ | ||
| 36 | mfspr r12,SPRN_SRR0; \ | ||
| 37 | stw r10,GPR1(r11); \ | ||
| 38 | mfspr r9,SPRN_SRR1; \ | ||
| 39 | stw r10,0(r11); \ | ||
| 40 | rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\ | ||
| 41 | stw r0,GPR0(r11); \ | ||
| 42 | SAVE_4GPRS(3, r11); \ | ||
| 43 | SAVE_2GPRS(7, r11) | ||
| 44 | |||
| 45 | /* To handle the additional exception priority levels on 40x and Book-E | ||
| 46 | * processors we allocate a 4k stack per additional priority level. The various | ||
| 47 | * head_xxx.S files allocate space (exception_stack_top) for each priority's | ||
| 48 | * stack times the number of CPUs | ||
| 49 | * | ||
| 50 | * On 40x critical is the only additional level | ||
| 51 | * On 44x/e500 we have critical and machine check | ||
| 52 | * On e200 we have critical and debug (machine check occurs via critical) | ||
| 53 | * | ||
| 54 | * Additionally we reserve a SPRG for each priority level so we can free up a | ||
| 55 | * GPR to use as the base for indirect access to the exception stacks. This | ||
| 56 | * is necessary since the MMU is always on, for Book-E parts, and the stacks | ||
| 57 | * are offset from KERNELBASE. | ||
| 58 | * | ||
| 59 | */ | ||
| 60 | #define BOOKE_EXCEPTION_STACK_SIZE (8192) | ||
| 61 | |||
| 62 | /* CRIT_SPRG only used in critical exception handling */ | ||
| 63 | #define CRIT_SPRG SPRN_SPRG2 | ||
| 64 | /* MCHECK_SPRG only used in machine check exception handling */ | ||
| 65 | #define MCHECK_SPRG SPRN_SPRG6W | ||
| 66 | |||
| 67 | #define MCHECK_STACK_TOP (exception_stack_top - 4096) | ||
| 68 | #define CRIT_STACK_TOP (exception_stack_top) | ||
| 69 | |||
| 70 | /* only on e200 for now */ | ||
| 71 | #define DEBUG_STACK_TOP (exception_stack_top - 4096) | ||
| 72 | #define DEBUG_SPRG SPRN_SPRG6W | ||
| 73 | |||
| 74 | #ifdef CONFIG_SMP | ||
| 75 | #define BOOKE_LOAD_EXC_LEVEL_STACK(level) \ | ||
| 76 | mfspr r8,SPRN_PIR; \ | ||
| 77 | mulli r8,r8,BOOKE_EXCEPTION_STACK_SIZE; \ | ||
| 78 | neg r8,r8; \ | ||
| 79 | addis r8,r8,level##_STACK_TOP@ha; \ | ||
| 80 | addi r8,r8,level##_STACK_TOP@l | ||
| 81 | #else | ||
| 82 | #define BOOKE_LOAD_EXC_LEVEL_STACK(level) \ | ||
| 83 | lis r8,level##_STACK_TOP@h; \ | ||
| 84 | ori r8,r8,level##_STACK_TOP@l | ||
| 85 | #endif | ||
| 86 | |||
| 87 | /* | ||
| 88 | * Exception prolog for critical/machine check exceptions. This is a | ||
| 89 | * little different from the normal exception prolog above since a | ||
| 90 | * critical/machine check exception can potentially occur at any point | ||
| 91 | * during normal exception processing. Thus we cannot use the same SPRG | ||
| 92 | * registers as the normal prolog above. Instead we use a portion of the | ||
| 93 | * critical/machine check exception stack at low physical addresses. | ||
| 94 | */ | ||
| 95 | #define EXC_LEVEL_EXCEPTION_PROLOG(exc_level, exc_level_srr0, exc_level_srr1) \ | ||
| 96 | mtspr exc_level##_SPRG,r8; \ | ||
| 97 | BOOKE_LOAD_EXC_LEVEL_STACK(exc_level);/* r8 points to the exc_level stack*/ \ | ||
| 98 | stw r10,GPR10-INT_FRAME_SIZE(r8); \ | ||
| 99 | stw r11,GPR11-INT_FRAME_SIZE(r8); \ | ||
| 100 | mfcr r10; /* save CR in r10 for now */\ | ||
| 101 | mfspr r11,exc_level_srr1; /* check whether user or kernel */\ | ||
| 102 | andi. r11,r11,MSR_PR; \ | ||
| 103 | mr r11,r8; \ | ||
| 104 | mfspr r8,exc_level##_SPRG; \ | ||
| 105 | beq 1f; \ | ||
| 106 | /* COMING FROM USER MODE */ \ | ||
| 107 | mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\ | ||
| 108 | lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\ | ||
| 109 | addi r11,r11,THREAD_SIZE; \ | ||
| 110 | 1: subi r11,r11,INT_FRAME_SIZE; /* Allocate an exception frame */\ | ||
| 111 | stw r10,_CCR(r11); /* save various registers */\ | ||
| 112 | stw r12,GPR12(r11); \ | ||
| 113 | stw r9,GPR9(r11); \ | ||
| 114 | mflr r10; \ | ||
| 115 | stw r10,_LINK(r11); \ | ||
| 116 | mfspr r12,SPRN_DEAR; /* save DEAR and ESR in the frame */\ | ||
| 117 | stw r12,_DEAR(r11); /* since they may have had stuff */\ | ||
| 118 | mfspr r9,SPRN_ESR; /* in them at the point where the */\ | ||
| 119 | stw r9,_ESR(r11); /* exception was taken */\ | ||
| 120 | mfspr r12,exc_level_srr0; \ | ||
| 121 | stw r1,GPR1(r11); \ | ||
| 122 | mfspr r9,exc_level_srr1; \ | ||
| 123 | stw r1,0(r11); \ | ||
| 124 | mr r1,r11; \ | ||
| 125 | rlwinm r9,r9,0,14,12; /* clear MSR_WE (necessary?) */\ | ||
| 126 | stw r0,GPR0(r11); \ | ||
| 127 | SAVE_4GPRS(3, r11); \ | ||
| 128 | SAVE_2GPRS(7, r11) | ||
| 129 | |||
| 130 | #define CRITICAL_EXCEPTION_PROLOG \ | ||
| 131 | EXC_LEVEL_EXCEPTION_PROLOG(CRIT, SPRN_CSRR0, SPRN_CSRR1) | ||
| 132 | #define DEBUG_EXCEPTION_PROLOG \ | ||
| 133 | EXC_LEVEL_EXCEPTION_PROLOG(DEBUG, SPRN_DSRR0, SPRN_DSRR1) | ||
| 134 | #define MCHECK_EXCEPTION_PROLOG \ | ||
| 135 | EXC_LEVEL_EXCEPTION_PROLOG(MCHECK, SPRN_MCSRR0, SPRN_MCSRR1) | ||
| 136 | |||
| 137 | /* | ||
| 138 | * Exception vectors. | ||
| 139 | */ | ||
| 140 | #define START_EXCEPTION(label) \ | ||
| 141 | .align 5; \ | ||
| 142 | label: | ||
| 143 | |||
| 144 | #define FINISH_EXCEPTION(func) \ | ||
| 145 | bl transfer_to_handler_full; \ | ||
| 146 | .long func; \ | ||
| 147 | .long ret_from_except_full | ||
| 148 | |||
| 149 | #define EXCEPTION(n, label, hdlr, xfer) \ | ||
| 150 | START_EXCEPTION(label); \ | ||
| 151 | NORMAL_EXCEPTION_PROLOG; \ | ||
| 152 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
| 153 | xfer(n, hdlr) | ||
| 154 | |||
| 155 | #define CRITICAL_EXCEPTION(n, label, hdlr) \ | ||
| 156 | START_EXCEPTION(label); \ | ||
| 157 | CRITICAL_EXCEPTION_PROLOG; \ | ||
| 158 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
| 159 | EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \ | ||
| 160 | NOCOPY, crit_transfer_to_handler, \ | ||
| 161 | ret_from_crit_exc) | ||
| 162 | |||
| 163 | #define MCHECK_EXCEPTION(n, label, hdlr) \ | ||
| 164 | START_EXCEPTION(label); \ | ||
| 165 | MCHECK_EXCEPTION_PROLOG; \ | ||
| 166 | mfspr r5,SPRN_ESR; \ | ||
| 167 | stw r5,_ESR(r11); \ | ||
| 168 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
| 169 | EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \ | ||
| 170 | NOCOPY, mcheck_transfer_to_handler, \ | ||
| 171 | ret_from_mcheck_exc) | ||
| 172 | |||
| 173 | #define EXC_XFER_TEMPLATE(hdlr, trap, msr, copyee, tfer, ret) \ | ||
| 174 | li r10,trap; \ | ||
| 175 | stw r10,_TRAP(r11); \ | ||
| 176 | lis r10,msr@h; \ | ||
| 177 | ori r10,r10,msr@l; \ | ||
| 178 | copyee(r10, r9); \ | ||
| 179 | bl tfer; \ | ||
| 180 | .long hdlr; \ | ||
| 181 | .long ret | ||
| 182 | |||
| 183 | #define COPY_EE(d, s) rlwimi d,s,0,16,16 | ||
| 184 | #define NOCOPY(d, s) | ||
| 185 | |||
| 186 | #define EXC_XFER_STD(n, hdlr) \ | ||
| 187 | EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, NOCOPY, transfer_to_handler_full, \ | ||
| 188 | ret_from_except_full) | ||
| 189 | |||
| 190 | #define EXC_XFER_LITE(n, hdlr) \ | ||
| 191 | EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, NOCOPY, transfer_to_handler, \ | ||
| 192 | ret_from_except) | ||
| 193 | |||
| 194 | #define EXC_XFER_EE(n, hdlr) \ | ||
| 195 | EXC_XFER_TEMPLATE(hdlr, n, MSR_KERNEL, COPY_EE, transfer_to_handler_full, \ | ||
| 196 | ret_from_except_full) | ||
| 197 | |||
| 198 | #define EXC_XFER_EE_LITE(n, hdlr) \ | ||
| 199 | EXC_XFER_TEMPLATE(hdlr, n+1, MSR_KERNEL, COPY_EE, transfer_to_handler, \ | ||
| 200 | ret_from_except) | ||
| 201 | |||
| 202 | /* Check for a single step debug exception while in an exception | ||
| 203 | * handler before state has been saved. This is to catch the case | ||
| 204 | * where an instruction that we are trying to single step causes | ||
| 205 | * an exception (eg ITLB/DTLB miss) and thus the first instruction of | ||
| 206 | * the exception handler generates a single step debug exception. | ||
| 207 | * | ||
| 208 | * If we get a debug trap on the first instruction of an exception handler, | ||
| 209 | * we reset the MSR_DE in the _exception handler's_ MSR (the debug trap is | ||
| 210 | * a critical exception, so we are using SPRN_CSRR1 to manipulate the MSR). | ||
| 211 | * The exception handler was handling a non-critical interrupt, so it will | ||
| 212 | * save (and later restore) the MSR via SPRN_CSRR1, which will still have | ||
| 213 | * the MSR_DE bit set. | ||
| 214 | */ | ||
| 215 | #ifdef CONFIG_E200 | ||
| 216 | #define DEBUG_EXCEPTION \ | ||
| 217 | START_EXCEPTION(Debug); \ | ||
| 218 | DEBUG_EXCEPTION_PROLOG; \ | ||
| 219 | \ | ||
| 220 | /* \ | ||
| 221 | * If there is a single step or branch-taken exception in an \ | ||
| 222 | * exception entry sequence, it was probably meant to apply to \ | ||
| 223 | * the code where the exception occurred (since exception entry \ | ||
| 224 | * doesn't turn off DE automatically). We simulate the effect \ | ||
| 225 | * of turning off DE on entry to an exception handler by turning \ | ||
| 226 | * off DE in the CSRR1 value and clearing the debug status. \ | ||
| 227 | */ \ | ||
| 228 | mfspr r10,SPRN_DBSR; /* check single-step/branch taken */ \ | ||
| 229 | andis. r10,r10,DBSR_IC@h; \ | ||
| 230 | beq+ 2f; \ | ||
| 231 | \ | ||
| 232 | lis r10,KERNELBASE@h; /* check if exception in vectors */ \ | ||
| 233 | ori r10,r10,KERNELBASE@l; \ | ||
| 234 | cmplw r12,r10; \ | ||
| 235 | blt+ 2f; /* addr below exception vectors */ \ | ||
| 236 | \ | ||
| 237 | lis r10,Debug@h; \ | ||
| 238 | ori r10,r10,Debug@l; \ | ||
| 239 | cmplw r12,r10; \ | ||
| 240 | bgt+ 2f; /* addr above exception vectors */ \ | ||
| 241 | \ | ||
| 242 | /* here it looks like we got an inappropriate debug exception. */ \ | ||
| 243 | 1: rlwinm r9,r9,0,~MSR_DE; /* clear DE in the CDRR1 value */ \ | ||
| 244 | lis r10,DBSR_IC@h; /* clear the IC event */ \ | ||
| 245 | mtspr SPRN_DBSR,r10; \ | ||
| 246 | /* restore state and get out */ \ | ||
| 247 | lwz r10,_CCR(r11); \ | ||
| 248 | lwz r0,GPR0(r11); \ | ||
| 249 | lwz r1,GPR1(r11); \ | ||
| 250 | mtcrf 0x80,r10; \ | ||
| 251 | mtspr SPRN_DSRR0,r12; \ | ||
| 252 | mtspr SPRN_DSRR1,r9; \ | ||
| 253 | lwz r9,GPR9(r11); \ | ||
| 254 | lwz r12,GPR12(r11); \ | ||
| 255 | mtspr DEBUG_SPRG,r8; \ | ||
| 256 | BOOKE_LOAD_EXC_LEVEL_STACK(DEBUG); /* r8 points to the debug stack */ \ | ||
| 257 | lwz r10,GPR10-INT_FRAME_SIZE(r8); \ | ||
| 258 | lwz r11,GPR11-INT_FRAME_SIZE(r8); \ | ||
| 259 | mfspr r8,DEBUG_SPRG; \ | ||
| 260 | \ | ||
| 261 | RFDI; \ | ||
| 262 | b .; \ | ||
| 263 | \ | ||
| 264 | /* continue normal handling for a critical exception... */ \ | ||
| 265 | 2: mfspr r4,SPRN_DBSR; \ | ||
| 266 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
| 267 | EXC_XFER_TEMPLATE(DebugException, 0x2002, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, debug_transfer_to_handler, ret_from_debug_exc) | ||
| 268 | #else | ||
| 269 | #define DEBUG_EXCEPTION \ | ||
| 270 | START_EXCEPTION(Debug); \ | ||
| 271 | CRITICAL_EXCEPTION_PROLOG; \ | ||
| 272 | \ | ||
| 273 | /* \ | ||
| 274 | * If there is a single step or branch-taken exception in an \ | ||
| 275 | * exception entry sequence, it was probably meant to apply to \ | ||
| 276 | * the code where the exception occurred (since exception entry \ | ||
| 277 | * doesn't turn off DE automatically). We simulate the effect \ | ||
| 278 | * of turning off DE on entry to an exception handler by turning \ | ||
| 279 | * off DE in the CSRR1 value and clearing the debug status. \ | ||
| 280 | */ \ | ||
| 281 | mfspr r10,SPRN_DBSR; /* check single-step/branch taken */ \ | ||
| 282 | andis. r10,r10,DBSR_IC@h; \ | ||
| 283 | beq+ 2f; \ | ||
| 284 | \ | ||
| 285 | lis r10,KERNELBASE@h; /* check if exception in vectors */ \ | ||
| 286 | ori r10,r10,KERNELBASE@l; \ | ||
| 287 | cmplw r12,r10; \ | ||
| 288 | blt+ 2f; /* addr below exception vectors */ \ | ||
| 289 | \ | ||
| 290 | lis r10,Debug@h; \ | ||
| 291 | ori r10,r10,Debug@l; \ | ||
| 292 | cmplw r12,r10; \ | ||
| 293 | bgt+ 2f; /* addr above exception vectors */ \ | ||
| 294 | \ | ||
| 295 | /* here it looks like we got an inappropriate debug exception. */ \ | ||
| 296 | 1: rlwinm r9,r9,0,~MSR_DE; /* clear DE in the CSRR1 value */ \ | ||
| 297 | lis r10,DBSR_IC@h; /* clear the IC event */ \ | ||
| 298 | mtspr SPRN_DBSR,r10; \ | ||
| 299 | /* restore state and get out */ \ | ||
| 300 | lwz r10,_CCR(r11); \ | ||
| 301 | lwz r0,GPR0(r11); \ | ||
| 302 | lwz r1,GPR1(r11); \ | ||
| 303 | mtcrf 0x80,r10; \ | ||
| 304 | mtspr SPRN_CSRR0,r12; \ | ||
| 305 | mtspr SPRN_CSRR1,r9; \ | ||
| 306 | lwz r9,GPR9(r11); \ | ||
| 307 | lwz r12,GPR12(r11); \ | ||
| 308 | mtspr CRIT_SPRG,r8; \ | ||
| 309 | BOOKE_LOAD_EXC_LEVEL_STACK(CRIT); /* r8 points to the debug stack */ \ | ||
| 310 | lwz r10,GPR10-INT_FRAME_SIZE(r8); \ | ||
| 311 | lwz r11,GPR11-INT_FRAME_SIZE(r8); \ | ||
| 312 | mfspr r8,CRIT_SPRG; \ | ||
| 313 | \ | ||
| 314 | rfci; \ | ||
| 315 | b .; \ | ||
| 316 | \ | ||
| 317 | /* continue normal handling for a critical exception... */ \ | ||
| 318 | 2: mfspr r4,SPRN_DBSR; \ | ||
| 319 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
| 320 | EXC_XFER_TEMPLATE(DebugException, 0x2002, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), NOCOPY, crit_transfer_to_handler, ret_from_crit_exc) | ||
| 321 | #endif | ||
| 322 | |||
| 323 | #define INSTRUCTION_STORAGE_EXCEPTION \ | ||
| 324 | START_EXCEPTION(InstructionStorage) \ | ||
| 325 | NORMAL_EXCEPTION_PROLOG; \ | ||
| 326 | mfspr r5,SPRN_ESR; /* Grab the ESR and save it */ \ | ||
| 327 | stw r5,_ESR(r11); \ | ||
| 328 | mr r4,r12; /* Pass SRR0 as arg2 */ \ | ||
| 329 | li r5,0; /* Pass zero as arg3 */ \ | ||
| 330 | EXC_XFER_EE_LITE(0x0400, handle_page_fault) | ||
| 331 | |||
| 332 | #define ALIGNMENT_EXCEPTION \ | ||
| 333 | START_EXCEPTION(Alignment) \ | ||
| 334 | NORMAL_EXCEPTION_PROLOG; \ | ||
| 335 | mfspr r4,SPRN_DEAR; /* Grab the DEAR and save it */ \ | ||
| 336 | stw r4,_DEAR(r11); \ | ||
| 337 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
| 338 | EXC_XFER_EE(0x0600, alignment_exception) | ||
| 339 | |||
| 340 | #define PROGRAM_EXCEPTION \ | ||
| 341 | START_EXCEPTION(Program) \ | ||
| 342 | NORMAL_EXCEPTION_PROLOG; \ | ||
| 343 | mfspr r4,SPRN_ESR; /* Grab the ESR and save it */ \ | ||
| 344 | stw r4,_ESR(r11); \ | ||
| 345 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
| 346 | EXC_XFER_STD(0x0700, program_check_exception) | ||
| 347 | |||
| 348 | #define DECREMENTER_EXCEPTION \ | ||
| 349 | START_EXCEPTION(Decrementer) \ | ||
| 350 | NORMAL_EXCEPTION_PROLOG; \ | ||
| 351 | lis r0,TSR_DIS@h; /* Setup the DEC interrupt mask */ \ | ||
| 352 | mtspr SPRN_TSR,r0; /* Clear the DEC interrupt */ \ | ||
| 353 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
| 354 | EXC_XFER_LITE(0x0900, timer_interrupt) | ||
| 355 | |||
| 356 | #define FP_UNAVAILABLE_EXCEPTION \ | ||
| 357 | START_EXCEPTION(FloatingPointUnavailable) \ | ||
| 358 | NORMAL_EXCEPTION_PROLOG; \ | ||
| 359 | bne load_up_fpu; /* if from user, just load it up */ \ | ||
| 360 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
| 361 | EXC_XFER_EE_LITE(0x800, kernel_fp_unavailable_exception) | ||
| 362 | |||
| 363 | #endif /* __HEAD_BOOKE_H__ */ | ||
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index 8d60fa99fc4b..dd86bbed7627 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S | |||
| @@ -1,6 +1,4 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * arch/ppc/kernel/head_fsl_booke.S | ||
| 3 | * | ||
| 4 | * Kernel execution entry point code. | 2 | * Kernel execution entry point code. |
| 5 | * | 3 | * |
| 6 | * Copyright (c) 1995-1996 Gary Thomas <gdt@linuxppc.org> | 4 | * Copyright (c) 1995-1996 Gary Thomas <gdt@linuxppc.org> |
| @@ -316,6 +314,7 @@ skpinv: addi r6,r6,1 /* Increment */ | |||
| 316 | */ | 314 | */ |
| 317 | lis r2,DBCR0_IDM@h | 315 | lis r2,DBCR0_IDM@h |
| 318 | mtspr SPRN_DBCR0,r2 | 316 | mtspr SPRN_DBCR0,r2 |
| 317 | isync | ||
| 319 | /* clear any residual debug events */ | 318 | /* clear any residual debug events */ |
| 320 | li r2,-1 | 319 | li r2,-1 |
| 321 | mtspr SPRN_DBSR,r2 | 320 | mtspr SPRN_DBSR,r2 |
| @@ -1002,12 +1001,15 @@ _GLOBAL(giveup_fpu) | |||
| 1002 | _GLOBAL(abort) | 1001 | _GLOBAL(abort) |
| 1003 | li r13,0 | 1002 | li r13,0 |
| 1004 | mtspr SPRN_DBCR0,r13 /* disable all debug events */ | 1003 | mtspr SPRN_DBCR0,r13 /* disable all debug events */ |
| 1004 | isync | ||
| 1005 | mfmsr r13 | 1005 | mfmsr r13 |
| 1006 | ori r13,r13,MSR_DE@l /* Enable Debug Events */ | 1006 | ori r13,r13,MSR_DE@l /* Enable Debug Events */ |
| 1007 | mtmsr r13 | 1007 | mtmsr r13 |
| 1008 | isync | ||
| 1008 | mfspr r13,SPRN_DBCR0 | 1009 | mfspr r13,SPRN_DBCR0 |
| 1009 | lis r13,(DBCR0_IDM|DBCR0_RST_CHIP)@h | 1010 | lis r13,(DBCR0_IDM|DBCR0_RST_CHIP)@h |
| 1010 | mtspr SPRN_DBCR0,r13 | 1011 | mtspr SPRN_DBCR0,r13 |
| 1012 | isync | ||
| 1011 | 1013 | ||
| 1012 | _GLOBAL(set_context) | 1014 | _GLOBAL(set_context) |
| 1013 | 1015 | ||
diff --git a/arch/powerpc/kernel/iomap.c b/arch/powerpc/kernel/iomap.c index 6160c8dbb7c5..fd8214caedee 100644 --- a/arch/powerpc/kernel/iomap.c +++ b/arch/powerpc/kernel/iomap.c | |||
| @@ -1,6 +1,4 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * arch/ppc64/kernel/iomap.c | ||
| 3 | * | ||
| 4 | * ppc64 "iomap" interface implementation. | 2 | * ppc64 "iomap" interface implementation. |
| 5 | * | 3 | * |
| 6 | * (C) Copyright 2004 Linus Torvalds | 4 | * (C) Copyright 2004 Linus Torvalds |
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 946f3219fd29..d9a7fdef59b9 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c | |||
| @@ -1,5 +1,4 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * arch/ppc64/kernel/iommu.c | ||
| 3 | * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation | 2 | * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation |
| 4 | * | 3 | * |
| 5 | * Rewrite, cleanup, new allocation schemes, virtual merging: | 4 | * Rewrite, cleanup, new allocation schemes, virtual merging: |
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index d1fffce86df9..771a59cbd213 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
| @@ -1,6 +1,4 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * arch/ppc/kernel/irq.c | ||
| 3 | * | ||
| 4 | * Derived from arch/i386/kernel/irq.c | 2 | * Derived from arch/i386/kernel/irq.c |
| 5 | * Copyright (C) 1992 Linus Torvalds | 3 | * Copyright (C) 1992 Linus Torvalds |
| 6 | * Adapted from arch/i386 by Gary Thomas | 4 | * Adapted from arch/i386 by Gary Thomas |
| @@ -137,9 +135,8 @@ skip: | |||
| 137 | #ifdef CONFIG_TAU_INT | 135 | #ifdef CONFIG_TAU_INT |
| 138 | if (tau_initialized){ | 136 | if (tau_initialized){ |
| 139 | seq_puts(p, "TAU: "); | 137 | seq_puts(p, "TAU: "); |
| 140 | for (j = 0; j < NR_CPUS; j++) | 138 | for_each_online_cpu(j) |
| 141 | if (cpu_online(j)) | 139 | seq_printf(p, "%10u ", tau_interrupts(j)); |
| 142 | seq_printf(p, "%10u ", tau_interrupts(j)); | ||
| 143 | seq_puts(p, " PowerPC Thermal Assist (cpu temp)\n"); | 140 | seq_puts(p, " PowerPC Thermal Assist (cpu temp)\n"); |
| 144 | } | 141 | } |
| 145 | #endif | 142 | #endif |
| @@ -371,6 +368,7 @@ unsigned int real_irq_to_virt_slowpath(unsigned int real_irq) | |||
| 371 | return NO_IRQ; | 368 | return NO_IRQ; |
| 372 | 369 | ||
| 373 | } | 370 | } |
| 371 | #endif /* CONFIG_PPC64 */ | ||
| 374 | 372 | ||
| 375 | #ifdef CONFIG_IRQSTACKS | 373 | #ifdef CONFIG_IRQSTACKS |
| 376 | struct thread_info *softirq_ctx[NR_CPUS]; | 374 | struct thread_info *softirq_ctx[NR_CPUS]; |
| @@ -394,10 +392,24 @@ void irq_ctx_init(void) | |||
| 394 | } | 392 | } |
| 395 | } | 393 | } |
| 396 | 394 | ||
| 395 | static inline void do_softirq_onstack(void) | ||
| 396 | { | ||
| 397 | struct thread_info *curtp, *irqtp; | ||
| 398 | |||
| 399 | curtp = current_thread_info(); | ||
| 400 | irqtp = softirq_ctx[smp_processor_id()]; | ||
| 401 | irqtp->task = curtp->task; | ||
| 402 | call_do_softirq(irqtp); | ||
| 403 | irqtp->task = NULL; | ||
| 404 | } | ||
| 405 | |||
| 406 | #else | ||
| 407 | #define do_softirq_onstack() __do_softirq() | ||
| 408 | #endif /* CONFIG_IRQSTACKS */ | ||
| 409 | |||
| 397 | void do_softirq(void) | 410 | void do_softirq(void) |
| 398 | { | 411 | { |
| 399 | unsigned long flags; | 412 | unsigned long flags; |
| 400 | struct thread_info *curtp, *irqtp; | ||
| 401 | 413 | ||
| 402 | if (in_interrupt()) | 414 | if (in_interrupt()) |
| 403 | return; | 415 | return; |
| @@ -405,19 +417,18 @@ void do_softirq(void) | |||
| 405 | local_irq_save(flags); | 417 | local_irq_save(flags); |
| 406 | 418 | ||
| 407 | if (local_softirq_pending()) { | 419 | if (local_softirq_pending()) { |
| 408 | curtp = current_thread_info(); | 420 | account_system_vtime(current); |
| 409 | irqtp = softirq_ctx[smp_processor_id()]; | 421 | local_bh_disable(); |
| 410 | irqtp->task = curtp->task; | 422 | do_softirq_onstack(); |
| 411 | call_do_softirq(irqtp); | 423 | account_system_vtime(current); |
| 412 | irqtp->task = NULL; | 424 | __local_bh_enable(); |
| 413 | } | 425 | } |
| 414 | 426 | ||
| 415 | local_irq_restore(flags); | 427 | local_irq_restore(flags); |
| 416 | } | 428 | } |
| 417 | EXPORT_SYMBOL(do_softirq); | 429 | EXPORT_SYMBOL(do_softirq); |
| 418 | 430 | ||
| 419 | #endif /* CONFIG_IRQSTACKS */ | 431 | #ifdef CONFIG_PPC64 |
| 420 | |||
| 421 | static int __init setup_noirqdistrib(char *str) | 432 | static int __init setup_noirqdistrib(char *str) |
| 422 | { | 433 | { |
| 423 | distribute_irqs = 0; | 434 | distribute_irqs = 0; |
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index cfab48566db1..cb1fe5878e8b 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c | |||
| @@ -1,6 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Kernel Probes (KProbes) | 2 | * Kernel Probes (KProbes) |
| 3 | * arch/ppc64/kernel/kprobes.c | ||
| 4 | * | 3 | * |
| 5 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
| 6 | * it under the terms of the GNU General Public License as published by | 5 | * it under the terms of the GNU General Public License as published by |
| @@ -82,9 +81,9 @@ void __kprobes arch_disarm_kprobe(struct kprobe *p) | |||
| 82 | 81 | ||
| 83 | void __kprobes arch_remove_kprobe(struct kprobe *p) | 82 | void __kprobes arch_remove_kprobe(struct kprobe *p) |
| 84 | { | 83 | { |
| 85 | down(&kprobe_mutex); | 84 | mutex_lock(&kprobe_mutex); |
| 86 | free_insn_slot(p->ainsn.insn); | 85 | free_insn_slot(p->ainsn.insn); |
| 87 | up(&kprobe_mutex); | 86 | mutex_unlock(&kprobe_mutex); |
| 88 | } | 87 | } |
| 89 | 88 | ||
| 90 | static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) | 89 | static inline void prepare_singlestep(struct kprobe *p, struct pt_regs *regs) |
diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c index 22d83d4d1af5..9feeeef5a875 100644 --- a/arch/powerpc/kernel/of_device.c +++ b/arch/powerpc/kernel/of_device.c | |||
| @@ -147,15 +147,12 @@ postcore_initcall(of_bus_driver_init); | |||
| 147 | 147 | ||
| 148 | int of_register_driver(struct of_platform_driver *drv) | 148 | int of_register_driver(struct of_platform_driver *drv) |
| 149 | { | 149 | { |
| 150 | int count = 0; | ||
| 151 | |||
| 152 | /* initialize common driver fields */ | 150 | /* initialize common driver fields */ |
| 153 | drv->driver.name = drv->name; | 151 | drv->driver.name = drv->name; |
| 154 | drv->driver.bus = &of_platform_bus_type; | 152 | drv->driver.bus = &of_platform_bus_type; |
| 155 | 153 | ||
| 156 | /* register with core */ | 154 | /* register with core */ |
| 157 | count = driver_register(&drv->driver); | 155 | return driver_register(&drv->driver); |
| 158 | return count ? count : 1; | ||
| 159 | } | 156 | } |
| 160 | 157 | ||
| 161 | void of_unregister_driver(struct of_platform_driver *drv) | 158 | void of_unregister_driver(struct of_platform_driver *drv) |
diff --git a/arch/powerpc/kernel/pci_iommu.c b/arch/powerpc/kernel/pci_iommu.c index bdf15dbbf4f0..c336f3e31cff 100644 --- a/arch/powerpc/kernel/pci_iommu.c +++ b/arch/powerpc/kernel/pci_iommu.c | |||
| @@ -1,5 +1,4 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * arch/ppc64/kernel/pci_iommu.c | ||
| 3 | * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation | 2 | * Copyright (C) 2001 Mike Corrigan & Dave Engebretsen, IBM Corporation |
| 4 | * | 3 | * |
| 5 | * Rewrite, cleanup, new allocation schemes: | 4 | * Rewrite, cleanup, new allocation schemes: |
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index 63ecbec05202..dfa5398ab3c8 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c | |||
| @@ -57,7 +57,6 @@ extern void machine_check_exception(struct pt_regs *regs); | |||
| 57 | extern void alignment_exception(struct pt_regs *regs); | 57 | extern void alignment_exception(struct pt_regs *regs); |
| 58 | extern void program_check_exception(struct pt_regs *regs); | 58 | extern void program_check_exception(struct pt_regs *regs); |
| 59 | extern void single_step_exception(struct pt_regs *regs); | 59 | extern void single_step_exception(struct pt_regs *regs); |
| 60 | extern int pmac_newworld; | ||
| 61 | extern int sys_sigreturn(struct pt_regs *regs); | 60 | extern int sys_sigreturn(struct pt_regs *regs); |
| 62 | 61 | ||
| 63 | EXPORT_SYMBOL(clear_pages); | 62 | EXPORT_SYMBOL(clear_pages); |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index c225cf154bfe..1770a066c217 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
| @@ -1,6 +1,4 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * arch/ppc/kernel/process.c | ||
| 3 | * | ||
| 4 | * Derived from "arch/i386/kernel/process.c" | 2 | * Derived from "arch/i386/kernel/process.c" |
| 5 | * Copyright (C) 1995 Linus Torvalds | 3 | * Copyright (C) 1995 Linus Torvalds |
| 6 | * | 4 | * |
| @@ -47,9 +45,9 @@ | |||
| 47 | #include <asm/mmu.h> | 45 | #include <asm/mmu.h> |
| 48 | #include <asm/prom.h> | 46 | #include <asm/prom.h> |
| 49 | #include <asm/machdep.h> | 47 | #include <asm/machdep.h> |
| 48 | #include <asm/time.h> | ||
| 50 | #ifdef CONFIG_PPC64 | 49 | #ifdef CONFIG_PPC64 |
| 51 | #include <asm/firmware.h> | 50 | #include <asm/firmware.h> |
| 52 | #include <asm/time.h> | ||
| 53 | #endif | 51 | #endif |
| 54 | 52 | ||
| 55 | extern unsigned long _get_SP(void); | 53 | extern unsigned long _get_SP(void); |
| @@ -330,6 +328,11 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
| 330 | #endif | 328 | #endif |
| 331 | 329 | ||
| 332 | local_irq_save(flags); | 330 | local_irq_save(flags); |
| 331 | |||
| 332 | account_system_vtime(current); | ||
| 333 | account_process_vtime(current); | ||
| 334 | calculate_steal_time(); | ||
| 335 | |||
| 333 | last = _switch(old_thread, new_thread); | 336 | last = _switch(old_thread, new_thread); |
| 334 | 337 | ||
| 335 | local_irq_restore(flags); | 338 | local_irq_restore(flags); |
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 6dbd21726770..d63cd562d9d5 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
| @@ -829,10 +829,6 @@ void __init unflatten_device_tree(void) | |||
| 829 | 829 | ||
| 830 | /* Allocate memory for the expanded device tree */ | 830 | /* Allocate memory for the expanded device tree */ |
| 831 | mem = lmb_alloc(size + 4, __alignof__(struct device_node)); | 831 | mem = lmb_alloc(size + 4, __alignof__(struct device_node)); |
| 832 | if (!mem) { | ||
| 833 | DBG("Couldn't allocate memory with lmb_alloc()!\n"); | ||
| 834 | panic("Couldn't allocate memory with lmb_alloc()!\n"); | ||
| 835 | } | ||
| 836 | mem = (unsigned long) __va(mem); | 832 | mem = (unsigned long) __va(mem); |
| 837 | 833 | ||
| 838 | ((u32 *)mem)[size / 4] = 0xdeadbeef; | 834 | ((u32 *)mem)[size / 4] = 0xdeadbeef; |
diff --git a/arch/powerpc/kernel/ptrace-common.h b/arch/powerpc/kernel/ptrace-common.h index 5ccbdbe0d5c9..c42a860c8d25 100644 --- a/arch/powerpc/kernel/ptrace-common.h +++ b/arch/powerpc/kernel/ptrace-common.h | |||
| @@ -1,6 +1,4 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * linux/arch/ppc64/kernel/ptrace-common.h | ||
| 3 | * | ||
| 4 | * Copyright (c) 2002 Stephen Rothwell, IBM Coproration | 2 | * Copyright (c) 2002 Stephen Rothwell, IBM Coproration |
| 5 | * Extracted from ptrace.c and ptrace32.c | 3 | * Extracted from ptrace.c and ptrace32.c |
| 6 | * | 4 | * |
diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c index 7a95b8a28354..1f03fb28cc0a 100644 --- a/arch/powerpc/kernel/rtas-proc.c +++ b/arch/powerpc/kernel/rtas-proc.c | |||
| @@ -1,5 +1,4 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * arch/ppc64/kernel/rtas-proc.c | ||
| 3 | * Copyright (C) 2000 Tilmann Bitterberg | 2 | * Copyright (C) 2000 Tilmann Bitterberg |
| 4 | * (tilmann@bitterberg.de) | 3 | * (tilmann@bitterberg.de) |
| 5 | * | 4 | * |
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index 7442775ef2a1..57b539a03fa9 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c | |||
| @@ -1,6 +1,4 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * arch/ppc64/kernel/rtas_pci.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2001 Dave Engebretsen, IBM Corporation | 2 | * Copyright (C) 2001 Dave Engebretsen, IBM Corporation |
| 5 | * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM | 3 | * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM |
| 6 | * | 4 | * |
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index be12041c0fc5..c1d62bf11f29 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c | |||
| @@ -162,9 +162,8 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
| 162 | #if defined(CONFIG_SMP) && defined(CONFIG_PPC32) | 162 | #if defined(CONFIG_SMP) && defined(CONFIG_PPC32) |
| 163 | unsigned long bogosum = 0; | 163 | unsigned long bogosum = 0; |
| 164 | int i; | 164 | int i; |
| 165 | for (i = 0; i < NR_CPUS; ++i) | 165 | for_each_online_cpu(i) |
| 166 | if (cpu_online(i)) | 166 | bogosum += loops_per_jiffy; |
| 167 | bogosum += loops_per_jiffy; | ||
| 168 | seq_printf(m, "total bogomips\t: %lu.%02lu\n", | 167 | seq_printf(m, "total bogomips\t: %lu.%02lu\n", |
| 169 | bogosum/(500000/HZ), bogosum/(5000/HZ) % 100); | 168 | bogosum/(500000/HZ), bogosum/(5000/HZ) % 100); |
| 170 | #endif /* CONFIG_SMP && CONFIG_PPC32 */ | 169 | #endif /* CONFIG_SMP && CONFIG_PPC32 */ |
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index db72a92943bf..dc2770df25b3 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c | |||
| @@ -272,9 +272,8 @@ int __init ppc_init(void) | |||
| 272 | if ( ppc_md.progress ) ppc_md.progress(" ", 0xffff); | 272 | if ( ppc_md.progress ) ppc_md.progress(" ", 0xffff); |
| 273 | 273 | ||
| 274 | /* register CPU devices */ | 274 | /* register CPU devices */ |
| 275 | for (i = 0; i < NR_CPUS; i++) | 275 | for_each_cpu(i) |
| 276 | if (cpu_possible(i)) | 276 | register_cpu(&cpu_devices[i], i, NULL); |
| 277 | register_cpu(&cpu_devices[i], i, NULL); | ||
| 278 | 277 | ||
| 279 | /* call platform init */ | 278 | /* call platform init */ |
| 280 | if (ppc_md.init != NULL) { | 279 | if (ppc_md.init != NULL) { |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index f96c49b03ba0..2f3fdad35594 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
| @@ -497,8 +497,6 @@ void __init setup_system(void) | |||
| 497 | #endif | 497 | #endif |
| 498 | printk("-----------------------------------------------------\n"); | 498 | printk("-----------------------------------------------------\n"); |
| 499 | 499 | ||
| 500 | mm_init_ppc64(); | ||
| 501 | |||
| 502 | DBG(" <- setup_system()\n"); | 500 | DBG(" <- setup_system()\n"); |
| 503 | } | 501 | } |
| 504 | 502 | ||
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index 4324f8a8ba24..47f910380a6a 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c | |||
| @@ -1,6 +1,4 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * linux/arch/ppc64/kernel/signal.c | ||
| 3 | * | ||
| 4 | * PowerPC version | 2 | * PowerPC version |
| 5 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) | 3 | * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) |
| 6 | * | 4 | * |
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 13595a64f013..805eaedbc308 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
| @@ -541,7 +541,7 @@ int __devinit start_secondary(void *unused) | |||
| 541 | smp_ops->take_timebase(); | 541 | smp_ops->take_timebase(); |
| 542 | 542 | ||
| 543 | if (system_state > SYSTEM_BOOTING) | 543 | if (system_state > SYSTEM_BOOTING) |
| 544 | per_cpu(last_jiffy, cpu) = get_tb(); | 544 | snapshot_timebase(); |
| 545 | 545 | ||
| 546 | spin_lock(&call_lock); | 546 | spin_lock(&call_lock); |
| 547 | cpu_set(cpu, cpu_online_map); | 547 | cpu_set(cpu, cpu_online_map); |
| @@ -573,6 +573,8 @@ void __init smp_cpus_done(unsigned int max_cpus) | |||
| 573 | 573 | ||
| 574 | set_cpus_allowed(current, old_mask); | 574 | set_cpus_allowed(current, old_mask); |
| 575 | 575 | ||
| 576 | snapshot_timebases(); | ||
| 577 | |||
| 576 | dump_numa_cpu_topology(); | 578 | dump_numa_cpu_topology(); |
| 577 | } | 579 | } |
| 578 | 580 | ||
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 86f7e3d154d8..4a27218a086c 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
| @@ -51,6 +51,7 @@ | |||
| 51 | #include <linux/percpu.h> | 51 | #include <linux/percpu.h> |
| 52 | #include <linux/rtc.h> | 52 | #include <linux/rtc.h> |
| 53 | #include <linux/jiffies.h> | 53 | #include <linux/jiffies.h> |
| 54 | #include <linux/posix-timers.h> | ||
| 54 | 55 | ||
| 55 | #include <asm/io.h> | 56 | #include <asm/io.h> |
| 56 | #include <asm/processor.h> | 57 | #include <asm/processor.h> |
| @@ -98,6 +99,7 @@ unsigned long tb_ticks_per_jiffy; | |||
| 98 | unsigned long tb_ticks_per_usec = 100; /* sane default */ | 99 | unsigned long tb_ticks_per_usec = 100; /* sane default */ |
| 99 | EXPORT_SYMBOL(tb_ticks_per_usec); | 100 | EXPORT_SYMBOL(tb_ticks_per_usec); |
| 100 | unsigned long tb_ticks_per_sec; | 101 | unsigned long tb_ticks_per_sec; |
| 102 | EXPORT_SYMBOL(tb_ticks_per_sec); /* for cputime_t conversions */ | ||
| 101 | u64 tb_to_xs; | 103 | u64 tb_to_xs; |
| 102 | unsigned tb_to_us; | 104 | unsigned tb_to_us; |
| 103 | 105 | ||
| @@ -135,6 +137,224 @@ unsigned long tb_last_stamp; | |||
| 135 | */ | 137 | */ |
| 136 | DEFINE_PER_CPU(unsigned long, last_jiffy); | 138 | DEFINE_PER_CPU(unsigned long, last_jiffy); |
| 137 | 139 | ||
| 140 | #ifdef CONFIG_VIRT_CPU_ACCOUNTING | ||
| 141 | /* | ||
| 142 | * Factors for converting from cputime_t (timebase ticks) to | ||
| 143 | * jiffies, milliseconds, seconds, and clock_t (1/USER_HZ seconds). | ||
| 144 | * These are all stored as 0.64 fixed-point binary fractions. | ||
| 145 | */ | ||
| 146 | u64 __cputime_jiffies_factor; | ||
| 147 | EXPORT_SYMBOL(__cputime_jiffies_factor); | ||
| 148 | u64 __cputime_msec_factor; | ||
| 149 | EXPORT_SYMBOL(__cputime_msec_factor); | ||
| 150 | u64 __cputime_sec_factor; | ||
| 151 | EXPORT_SYMBOL(__cputime_sec_factor); | ||
| 152 | u64 __cputime_clockt_factor; | ||
| 153 | EXPORT_SYMBOL(__cputime_clockt_factor); | ||
| 154 | |||
| 155 | static void calc_cputime_factors(void) | ||
| 156 | { | ||
| 157 | struct div_result res; | ||
| 158 | |||
| 159 | div128_by_32(HZ, 0, tb_ticks_per_sec, &res); | ||
| 160 | __cputime_jiffies_factor = res.result_low; | ||
| 161 | div128_by_32(1000, 0, tb_ticks_per_sec, &res); | ||
| 162 | __cputime_msec_factor = res.result_low; | ||
| 163 | div128_by_32(1, 0, tb_ticks_per_sec, &res); | ||
| 164 | __cputime_sec_factor = res.result_low; | ||
| 165 | div128_by_32(USER_HZ, 0, tb_ticks_per_sec, &res); | ||
| 166 | __cputime_clockt_factor = res.result_low; | ||
| 167 | } | ||
| 168 | |||
| 169 | /* | ||
| 170 | * Read the PURR on systems that have it, otherwise the timebase. | ||
| 171 | */ | ||
| 172 | static u64 read_purr(void) | ||
| 173 | { | ||
| 174 | if (cpu_has_feature(CPU_FTR_PURR)) | ||
| 175 | return mfspr(SPRN_PURR); | ||
| 176 | return mftb(); | ||
| 177 | } | ||
| 178 | |||
| 179 | /* | ||
| 180 | * Account time for a transition between system, hard irq | ||
| 181 | * or soft irq state. | ||
| 182 | */ | ||
| 183 | void account_system_vtime(struct task_struct *tsk) | ||
| 184 | { | ||
| 185 | u64 now, delta; | ||
| 186 | unsigned long flags; | ||
| 187 | |||
| 188 | local_irq_save(flags); | ||
| 189 | now = read_purr(); | ||
| 190 | delta = now - get_paca()->startpurr; | ||
| 191 | get_paca()->startpurr = now; | ||
| 192 | if (!in_interrupt()) { | ||
| 193 | delta += get_paca()->system_time; | ||
| 194 | get_paca()->system_time = 0; | ||
| 195 | } | ||
| 196 | account_system_time(tsk, 0, delta); | ||
| 197 | local_irq_restore(flags); | ||
| 198 | } | ||
| 199 | |||
| 200 | /* | ||
| 201 | * Transfer the user and system times accumulated in the paca | ||
| 202 | * by the exception entry and exit code to the generic process | ||
| 203 | * user and system time records. | ||
| 204 | * Must be called with interrupts disabled. | ||
| 205 | */ | ||
| 206 | void account_process_vtime(struct task_struct *tsk) | ||
| 207 | { | ||
| 208 | cputime_t utime; | ||
| 209 | |||
| 210 | utime = get_paca()->user_time; | ||
| 211 | get_paca()->user_time = 0; | ||
| 212 | account_user_time(tsk, utime); | ||
| 213 | } | ||
| 214 | |||
| 215 | static void account_process_time(struct pt_regs *regs) | ||
| 216 | { | ||
| 217 | int cpu = smp_processor_id(); | ||
| 218 | |||
| 219 | account_process_vtime(current); | ||
| 220 | run_local_timers(); | ||
| 221 | if (rcu_pending(cpu)) | ||
| 222 | rcu_check_callbacks(cpu, user_mode(regs)); | ||
| 223 | scheduler_tick(); | ||
| 224 | run_posix_cpu_timers(current); | ||
| 225 | } | ||
| 226 | |||
| 227 | #ifdef CONFIG_PPC_SPLPAR | ||
| 228 | /* | ||
| 229 | * Stuff for accounting stolen time. | ||
| 230 | */ | ||
| 231 | struct cpu_purr_data { | ||
| 232 | int initialized; /* thread is running */ | ||
| 233 | u64 tb0; /* timebase at origin time */ | ||
| 234 | u64 purr0; /* PURR at origin time */ | ||
| 235 | u64 tb; /* last TB value read */ | ||
| 236 | u64 purr; /* last PURR value read */ | ||
| 237 | u64 stolen; /* stolen time so far */ | ||
| 238 | spinlock_t lock; | ||
| 239 | }; | ||
| 240 | |||
| 241 | static DEFINE_PER_CPU(struct cpu_purr_data, cpu_purr_data); | ||
| 242 | |||
| 243 | static void snapshot_tb_and_purr(void *data) | ||
| 244 | { | ||
| 245 | struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data); | ||
| 246 | |||
| 247 | p->tb0 = mftb(); | ||
| 248 | p->purr0 = mfspr(SPRN_PURR); | ||
| 249 | p->tb = p->tb0; | ||
| 250 | p->purr = 0; | ||
| 251 | wmb(); | ||
| 252 | p->initialized = 1; | ||
| 253 | } | ||
| 254 | |||
| 255 | /* | ||
| 256 | * Called during boot when all cpus have come up. | ||
| 257 | */ | ||
| 258 | void snapshot_timebases(void) | ||
| 259 | { | ||
| 260 | int cpu; | ||
| 261 | |||
| 262 | if (!cpu_has_feature(CPU_FTR_PURR)) | ||
| 263 | return; | ||
| 264 | for_each_cpu(cpu) | ||
| 265 | spin_lock_init(&per_cpu(cpu_purr_data, cpu).lock); | ||
| 266 | on_each_cpu(snapshot_tb_and_purr, NULL, 0, 1); | ||
| 267 | } | ||
| 268 | |||
| 269 | void calculate_steal_time(void) | ||
| 270 | { | ||
| 271 | u64 tb, purr, t0; | ||
| 272 | s64 stolen; | ||
| 273 | struct cpu_purr_data *p0, *pme, *phim; | ||
| 274 | int cpu; | ||
| 275 | |||
| 276 | if (!cpu_has_feature(CPU_FTR_PURR)) | ||
| 277 | return; | ||
| 278 | cpu = smp_processor_id(); | ||
| 279 | pme = &per_cpu(cpu_purr_data, cpu); | ||
| 280 | if (!pme->initialized) | ||
| 281 | return; /* this can happen in early boot */ | ||
| 282 | p0 = &per_cpu(cpu_purr_data, cpu & ~1); | ||
| 283 | phim = &per_cpu(cpu_purr_data, cpu ^ 1); | ||
| 284 | spin_lock(&p0->lock); | ||
| 285 | tb = mftb(); | ||
| 286 | purr = mfspr(SPRN_PURR) - pme->purr0; | ||
| 287 | if (!phim->initialized || !cpu_online(cpu ^ 1)) { | ||
| 288 | stolen = (tb - pme->tb) - (purr - pme->purr); | ||
| 289 | } else { | ||
| 290 | t0 = pme->tb0; | ||
| 291 | if (phim->tb0 < t0) | ||
| 292 | t0 = phim->tb0; | ||
| 293 | stolen = phim->tb - t0 - phim->purr - purr - p0->stolen; | ||
| 294 | } | ||
| 295 | if (stolen > 0) { | ||
| 296 | account_steal_time(current, stolen); | ||
| 297 | p0->stolen += stolen; | ||
| 298 | } | ||
| 299 | pme->tb = tb; | ||
| 300 | pme->purr = purr; | ||
| 301 | spin_unlock(&p0->lock); | ||
| 302 | } | ||
| 303 | |||
| 304 | /* | ||
| 305 | * Must be called before the cpu is added to the online map when | ||
| 306 | * a cpu is being brought up at runtime. | ||
| 307 | */ | ||
| 308 | static void snapshot_purr(void) | ||
| 309 | { | ||
| 310 | int cpu; | ||
| 311 | u64 purr; | ||
| 312 | struct cpu_purr_data *p0, *pme, *phim; | ||
| 313 | unsigned long flags; | ||
| 314 | |||
| 315 | if (!cpu_has_feature(CPU_FTR_PURR)) | ||
| 316 | return; | ||
| 317 | cpu = smp_processor_id(); | ||
| 318 | pme = &per_cpu(cpu_purr_data, cpu); | ||
| 319 | p0 = &per_cpu(cpu_purr_data, cpu & ~1); | ||
| 320 | phim = &per_cpu(cpu_purr_data, cpu ^ 1); | ||
| 321 | spin_lock_irqsave(&p0->lock, flags); | ||
| 322 | pme->tb = pme->tb0 = mftb(); | ||
| 323 | purr = mfspr(SPRN_PURR); | ||
| 324 | if (!phim->initialized) { | ||
| 325 | pme->purr = 0; | ||
| 326 | pme->purr0 = purr; | ||
| 327 | } else { | ||
| 328 | /* set p->purr and p->purr0 for no change in p0->stolen */ | ||
| 329 | pme->purr = phim->tb - phim->tb0 - phim->purr - p0->stolen; | ||
| 330 | pme->purr0 = purr - pme->purr; | ||
| 331 | } | ||
| 332 | pme->initialized = 1; | ||
| 333 | spin_unlock_irqrestore(&p0->lock, flags); | ||
| 334 | } | ||
| 335 | |||
| 336 | #endif /* CONFIG_PPC_SPLPAR */ | ||
| 337 | |||
| 338 | #else /* ! CONFIG_VIRT_CPU_ACCOUNTING */ | ||
| 339 | #define calc_cputime_factors() | ||
| 340 | #define account_process_time(regs) update_process_times(user_mode(regs)) | ||
| 341 | #define calculate_steal_time() do { } while (0) | ||
| 342 | #endif | ||
| 343 | |||
| 344 | #if !(defined(CONFIG_VIRT_CPU_ACCOUNTING) && defined(CONFIG_PPC_SPLPAR)) | ||
| 345 | #define snapshot_purr() do { } while (0) | ||
| 346 | #endif | ||
| 347 | |||
| 348 | /* | ||
| 349 | * Called when a cpu comes up after the system has finished booting, | ||
| 350 | * i.e. as a result of a hotplug cpu action. | ||
| 351 | */ | ||
| 352 | void snapshot_timebase(void) | ||
| 353 | { | ||
| 354 | __get_cpu_var(last_jiffy) = get_tb(); | ||
| 355 | snapshot_purr(); | ||
| 356 | } | ||
| 357 | |||
| 138 | void __delay(unsigned long loops) | 358 | void __delay(unsigned long loops) |
| 139 | { | 359 | { |
| 140 | unsigned long start; | 360 | unsigned long start; |
| @@ -392,6 +612,7 @@ static void iSeries_tb_recal(void) | |||
| 392 | new_tb_ticks_per_jiffy, sign, tick_diff ); | 612 | new_tb_ticks_per_jiffy, sign, tick_diff ); |
| 393 | tb_ticks_per_jiffy = new_tb_ticks_per_jiffy; | 613 | tb_ticks_per_jiffy = new_tb_ticks_per_jiffy; |
| 394 | tb_ticks_per_sec = new_tb_ticks_per_sec; | 614 | tb_ticks_per_sec = new_tb_ticks_per_sec; |
| 615 | calc_cputime_factors(); | ||
| 395 | div128_by_32( XSEC_PER_SEC, 0, tb_ticks_per_sec, &divres ); | 616 | div128_by_32( XSEC_PER_SEC, 0, tb_ticks_per_sec, &divres ); |
| 396 | do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; | 617 | do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; |
| 397 | tb_to_xs = divres.result_low; | 618 | tb_to_xs = divres.result_low; |
| @@ -440,6 +661,7 @@ void timer_interrupt(struct pt_regs * regs) | |||
| 440 | irq_enter(); | 661 | irq_enter(); |
| 441 | 662 | ||
| 442 | profile_tick(CPU_PROFILING, regs); | 663 | profile_tick(CPU_PROFILING, regs); |
| 664 | calculate_steal_time(); | ||
| 443 | 665 | ||
| 444 | #ifdef CONFIG_PPC_ISERIES | 666 | #ifdef CONFIG_PPC_ISERIES |
| 445 | get_lppaca()->int_dword.fields.decr_int = 0; | 667 | get_lppaca()->int_dword.fields.decr_int = 0; |
| @@ -461,7 +683,7 @@ void timer_interrupt(struct pt_regs * regs) | |||
| 461 | * is the case. | 683 | * is the case. |
| 462 | */ | 684 | */ |
| 463 | if (!cpu_is_offline(cpu)) | 685 | if (!cpu_is_offline(cpu)) |
| 464 | update_process_times(user_mode(regs)); | 686 | account_process_time(regs); |
| 465 | 687 | ||
| 466 | /* | 688 | /* |
| 467 | * No need to check whether cpu is offline here; boot_cpuid | 689 | * No need to check whether cpu is offline here; boot_cpuid |
| @@ -518,13 +740,27 @@ void wakeup_decrementer(void) | |||
| 518 | void __init smp_space_timers(unsigned int max_cpus) | 740 | void __init smp_space_timers(unsigned int max_cpus) |
| 519 | { | 741 | { |
| 520 | int i; | 742 | int i; |
| 743 | unsigned long half = tb_ticks_per_jiffy / 2; | ||
| 521 | unsigned long offset = tb_ticks_per_jiffy / max_cpus; | 744 | unsigned long offset = tb_ticks_per_jiffy / max_cpus; |
| 522 | unsigned long previous_tb = per_cpu(last_jiffy, boot_cpuid); | 745 | unsigned long previous_tb = per_cpu(last_jiffy, boot_cpuid); |
| 523 | 746 | ||
| 524 | /* make sure tb > per_cpu(last_jiffy, cpu) for all cpus always */ | 747 | /* make sure tb > per_cpu(last_jiffy, cpu) for all cpus always */ |
| 525 | previous_tb -= tb_ticks_per_jiffy; | 748 | previous_tb -= tb_ticks_per_jiffy; |
| 749 | /* | ||
| 750 | * The stolen time calculation for POWER5 shared-processor LPAR | ||
| 751 | * systems works better if the two threads' timebase interrupts | ||
| 752 | * are staggered by half a jiffy with respect to each other. | ||
| 753 | */ | ||
| 526 | for_each_cpu(i) { | 754 | for_each_cpu(i) { |
| 527 | if (i != boot_cpuid) { | 755 | if (i == boot_cpuid) |
| 756 | continue; | ||
| 757 | if (i == (boot_cpuid ^ 1)) | ||
| 758 | per_cpu(last_jiffy, i) = | ||
| 759 | per_cpu(last_jiffy, boot_cpuid) - half; | ||
| 760 | else if (i & 1) | ||
| 761 | per_cpu(last_jiffy, i) = | ||
| 762 | per_cpu(last_jiffy, i ^ 1) + half; | ||
| 763 | else { | ||
| 528 | previous_tb += offset; | 764 | previous_tb += offset; |
| 529 | per_cpu(last_jiffy, i) = previous_tb; | 765 | per_cpu(last_jiffy, i) = previous_tb; |
| 530 | } | 766 | } |
| @@ -720,6 +956,7 @@ void __init time_init(void) | |||
| 720 | tb_ticks_per_sec = ppc_tb_freq; | 956 | tb_ticks_per_sec = ppc_tb_freq; |
| 721 | tb_ticks_per_usec = ppc_tb_freq / 1000000; | 957 | tb_ticks_per_usec = ppc_tb_freq / 1000000; |
| 722 | tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000); | 958 | tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000); |
| 959 | calc_cputime_factors(); | ||
| 723 | 960 | ||
| 724 | /* | 961 | /* |
| 725 | * Calculate the length of each tick in ns. It will not be | 962 | * Calculate the length of each tick in ns. It will not be |
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index 04f7df39ffbb..ec8370368423 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c | |||
| @@ -1,6 +1,4 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * linux/arch/ppc64/kernel/vdso.c | ||
| 3 | * | ||
| 4 | * Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp. | 2 | * Copyright (C) 2004 Benjamin Herrenschmidt, IBM Corp. |
| 5 | * <benh@kernel.crashing.org> | 3 | * <benh@kernel.crashing.org> |
| 6 | * | 4 | * |
