diff options
author | Kumar Gala <galak@kernel.crashing.org> | 2006-02-28 12:25:22 -0500 |
---|---|---|
committer | Kumar Gala <galak@kernel.crashing.org> | 2006-02-28 12:25:22 -0500 |
commit | 9585da3729e7e27bf22818625c10ac6c64ebb609 (patch) | |
tree | 8c8d46f7f2cc933fdf75a6a75cf593a63f7b8717 /arch/powerpc/kernel | |
parent | 8080d5497146d5d27d9e8e78229d1adc7fe280cf (diff) | |
parent | 6749c5507388f3fc3719f57a54b540ee83f6661a (diff) |
Merge branch 'master' of git+ssh://galak@master.kernel.org/pub/scm/linux/kernel/git/galak/powerpc
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r-- | arch/powerpc/kernel/asm-offsets.c | 3 | ||||
-rw-r--r-- | arch/powerpc/kernel/crash.c | 4 | ||||
-rw-r--r-- | arch/powerpc/kernel/entry_64.S | 7 | ||||
-rw-r--r-- | arch/powerpc/kernel/head_32.S | 1 | ||||
-rw-r--r-- | arch/powerpc/kernel/head_64.S | 120 | ||||
-rw-r--r-- | arch/powerpc/kernel/irq.c | 30 | ||||
-rw-r--r-- | arch/powerpc/kernel/lparcfg.c | 6 | ||||
-rw-r--r-- | arch/powerpc/kernel/machine_kexec_64.c | 10 | ||||
-rw-r--r-- | arch/powerpc/kernel/ppc_ksyms.c | 16 | ||||
-rw-r--r-- | arch/powerpc/kernel/process.c | 39 | ||||
-rw-r--r-- | arch/powerpc/kernel/prom.c | 54 | ||||
-rw-r--r-- | arch/powerpc/kernel/prom_init.c | 38 | ||||
-rw-r--r-- | arch/powerpc/kernel/setup_64.c | 4 | ||||
-rw-r--r-- | arch/powerpc/kernel/smp.c | 4 | ||||
-rw-r--r-- | arch/powerpc/kernel/sys_ppc32.c | 4 | ||||
-rw-r--r-- | arch/powerpc/kernel/time.c | 523 | ||||
-rw-r--r-- | arch/powerpc/kernel/vdso64/gettimeofday.S | 4 |
17 files changed, 477 insertions, 390 deletions
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 840aad43a98b..18810ac55bcc 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -137,6 +137,9 @@ int main(void) | |||
137 | DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp)); | 137 | DEFINE(PACAEMERGSP, offsetof(struct paca_struct, emergency_sp)); |
138 | DEFINE(PACALPPACAPTR, offsetof(struct paca_struct, lppaca_ptr)); | 138 | DEFINE(PACALPPACAPTR, offsetof(struct paca_struct, lppaca_ptr)); |
139 | DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); | 139 | DEFINE(PACAHWCPUID, offsetof(struct paca_struct, hw_cpu_id)); |
140 | DEFINE(PACA_STARTPURR, offsetof(struct paca_struct, startpurr)); | ||
141 | DEFINE(PACA_USER_TIME, offsetof(struct paca_struct, user_time)); | ||
142 | DEFINE(PACA_SYSTEM_TIME, offsetof(struct paca_struct, system_time)); | ||
140 | 143 | ||
141 | DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0)); | 144 | DEFINE(LPPACASRR0, offsetof(struct lppaca, saved_srr0)); |
142 | DEFINE(LPPACASRR1, offsetof(struct lppaca, saved_srr1)); | 145 | DEFINE(LPPACASRR1, offsetof(struct lppaca, saved_srr1)); |
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c index 8c21d378f5d2..778f22fd85d2 100644 --- a/arch/powerpc/kernel/crash.c +++ b/arch/powerpc/kernel/crash.c | |||
@@ -134,8 +134,10 @@ static void crash_kexec_prepare_cpus(void) | |||
134 | * the crash CPU will send an IPI and wait for other CPUs to | 134 | * the crash CPU will send an IPI and wait for other CPUs to |
135 | * respond. If not, proceed the kexec boot even though we failed to | 135 | * respond. If not, proceed the kexec boot even though we failed to |
136 | * capture other CPU states. | 136 | * capture other CPU states. |
137 | * Delay of at least 10 seconds. | ||
137 | */ | 138 | */ |
138 | msecs = 1000000; | 139 | printk(KERN_ALERT "Sending IPI to other cpus...\n"); |
140 | msecs = 10000; | ||
139 | while ((atomic_read(&waiting_for_crash_ipi) > 0) && (--msecs > 0)) { | 141 | while ((atomic_read(&waiting_for_crash_ipi) > 0) && (--msecs > 0)) { |
140 | barrier(); | 142 | barrier(); |
141 | mdelay(1); | 143 | mdelay(1); |
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 79a0c910f0d8..8f606c1889fa 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
@@ -61,6 +61,7 @@ system_call_common: | |||
61 | std r12,_MSR(r1) | 61 | std r12,_MSR(r1) |
62 | std r0,GPR0(r1) | 62 | std r0,GPR0(r1) |
63 | std r10,GPR1(r1) | 63 | std r10,GPR1(r1) |
64 | ACCOUNT_CPU_USER_ENTRY(r10, r11) | ||
64 | std r2,GPR2(r1) | 65 | std r2,GPR2(r1) |
65 | std r3,GPR3(r1) | 66 | std r3,GPR3(r1) |
66 | std r4,GPR4(r1) | 67 | std r4,GPR4(r1) |
@@ -168,8 +169,9 @@ syscall_error_cont: | |||
168 | stdcx. r0,0,r1 /* to clear the reservation */ | 169 | stdcx. r0,0,r1 /* to clear the reservation */ |
169 | andi. r6,r8,MSR_PR | 170 | andi. r6,r8,MSR_PR |
170 | ld r4,_LINK(r1) | 171 | ld r4,_LINK(r1) |
171 | beq- 1f /* only restore r13 if */ | 172 | beq- 1f |
172 | 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 */ | ||
173 | 1: ld r2,GPR2(r1) | 175 | 1: ld r2,GPR2(r1) |
174 | li r12,MSR_RI | 176 | li r12,MSR_RI |
175 | andc r11,r10,r12 | 177 | andc r11,r10,r12 |
@@ -536,6 +538,7 @@ restore: | |||
536 | * userspace | 538 | * userspace |
537 | */ | 539 | */ |
538 | beq 1f | 540 | beq 1f |
541 | ACCOUNT_CPU_USER_EXIT(r3, r4) | ||
539 | REST_GPR(13, r1) | 542 | REST_GPR(13, r1) |
540 | 1: | 543 | 1: |
541 | ld r3,_CTR(r1) | 544 | ld r3,_CTR(r1) |
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S index 03b25f9359f8..a0579e859b21 100644 --- a/arch/powerpc/kernel/head_32.S +++ b/arch/powerpc/kernel/head_32.S | |||
@@ -714,6 +714,7 @@ AltiVecUnavailable: | |||
714 | #ifdef CONFIG_ALTIVEC | 714 | #ifdef CONFIG_ALTIVEC |
715 | bne load_up_altivec /* if from user, just load it up */ | 715 | bne load_up_altivec /* if from user, just load it up */ |
716 | #endif /* CONFIG_ALTIVEC */ | 716 | #endif /* CONFIG_ALTIVEC */ |
717 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
717 | EXC_XFER_EE_LITE(0xf20, altivec_unavailable_exception) | 718 | EXC_XFER_EE_LITE(0xf20, altivec_unavailable_exception) |
718 | 719 | ||
719 | PerformanceMonitor: | 720 | PerformanceMonitor: |
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 7ebb73665e9d..be3ae7733577 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
@@ -137,7 +137,7 @@ _GLOBAL(__secondary_hold) | |||
137 | ori r24,r24,MSR_RI | 137 | ori r24,r24,MSR_RI |
138 | mtmsrd r24 /* RI on */ | 138 | mtmsrd r24 /* RI on */ |
139 | 139 | ||
140 | /* Grab our linux cpu number */ | 140 | /* Grab our physical cpu number */ |
141 | mr r24,r3 | 141 | mr r24,r3 |
142 | 142 | ||
143 | /* Tell the master cpu we're here */ | 143 | /* Tell the master cpu we're here */ |
@@ -151,12 +151,7 @@ _GLOBAL(__secondary_hold) | |||
151 | cmpdi 0,r4,1 | 151 | cmpdi 0,r4,1 |
152 | bne 100b | 152 | bne 100b |
153 | 153 | ||
154 | #ifdef CONFIG_HMT | 154 | #if defined(CONFIG_SMP) || defined(CONFIG_KEXEC) |
155 | SET_REG_IMMEDIATE(r4, .hmt_init) | ||
156 | mtctr r4 | ||
157 | bctr | ||
158 | #else | ||
159 | #ifdef CONFIG_SMP | ||
160 | LOAD_REG_IMMEDIATE(r4, .pSeries_secondary_smp_init) | 155 | LOAD_REG_IMMEDIATE(r4, .pSeries_secondary_smp_init) |
161 | mtctr r4 | 156 | mtctr r4 |
162 | mr r3,r24 | 157 | mr r3,r24 |
@@ -164,7 +159,6 @@ _GLOBAL(__secondary_hold) | |||
164 | #else | 159 | #else |
165 | BUG_OPCODE | 160 | BUG_OPCODE |
166 | #endif | 161 | #endif |
167 | #endif | ||
168 | 162 | ||
169 | /* This value is used to mark exception frames on the stack. */ | 163 | /* This value is used to mark exception frames on the stack. */ |
170 | .section ".toc","aw" | 164 | .section ".toc","aw" |
@@ -283,6 +277,7 @@ exception_marker: | |||
283 | std r10,0(r1); /* make stack chain pointer */ \ | 277 | std r10,0(r1); /* make stack chain pointer */ \ |
284 | std r0,GPR0(r1); /* save r0 in stackframe */ \ | 278 | std r0,GPR0(r1); /* save r0 in stackframe */ \ |
285 | std r10,GPR1(r1); /* save r1 in stackframe */ \ | 279 | std r10,GPR1(r1); /* save r1 in stackframe */ \ |
280 | ACCOUNT_CPU_USER_ENTRY(r9, r10); \ | ||
286 | std r2,GPR2(r1); /* save r2 in stackframe */ \ | 281 | std r2,GPR2(r1); /* save r2 in stackframe */ \ |
287 | SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \ | 282 | SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \ |
288 | SAVE_2GPRS(7, r1); /* save r7, r8 in stackframe */ \ | 283 | SAVE_2GPRS(7, r1); /* save r7, r8 in stackframe */ \ |
@@ -319,7 +314,6 @@ exception_marker: | |||
319 | label##_pSeries: \ | 314 | label##_pSeries: \ |
320 | HMT_MEDIUM; \ | 315 | HMT_MEDIUM; \ |
321 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ | 316 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ |
322 | RUNLATCH_ON(r13); \ | ||
323 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) | 317 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) |
324 | 318 | ||
325 | #define STD_EXCEPTION_ISERIES(n, label, area) \ | 319 | #define STD_EXCEPTION_ISERIES(n, label, area) \ |
@@ -327,7 +321,6 @@ label##_pSeries: \ | |||
327 | label##_iSeries: \ | 321 | label##_iSeries: \ |
328 | HMT_MEDIUM; \ | 322 | HMT_MEDIUM; \ |
329 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ | 323 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ |
330 | RUNLATCH_ON(r13); \ | ||
331 | EXCEPTION_PROLOG_ISERIES_1(area); \ | 324 | EXCEPTION_PROLOG_ISERIES_1(area); \ |
332 | EXCEPTION_PROLOG_ISERIES_2; \ | 325 | EXCEPTION_PROLOG_ISERIES_2; \ |
333 | b label##_common | 326 | b label##_common |
@@ -337,7 +330,6 @@ label##_iSeries: \ | |||
337 | label##_iSeries: \ | 330 | label##_iSeries: \ |
338 | HMT_MEDIUM; \ | 331 | HMT_MEDIUM; \ |
339 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ | 332 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ |
340 | RUNLATCH_ON(r13); \ | ||
341 | EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN); \ | 333 | EXCEPTION_PROLOG_ISERIES_1(PACA_EXGEN); \ |
342 | lbz r10,PACAPROCENABLED(r13); \ | 334 | lbz r10,PACAPROCENABLED(r13); \ |
343 | cmpwi 0,r10,0; \ | 335 | cmpwi 0,r10,0; \ |
@@ -390,6 +382,7 @@ label##_common: \ | |||
390 | label##_common: \ | 382 | label##_common: \ |
391 | EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \ | 383 | EXCEPTION_PROLOG_COMMON(trap, PACA_EXGEN); \ |
392 | DISABLE_INTS; \ | 384 | DISABLE_INTS; \ |
385 | bl .ppc64_runlatch_on; \ | ||
393 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | 386 | addi r3,r1,STACK_FRAME_OVERHEAD; \ |
394 | bl hdlr; \ | 387 | bl hdlr; \ |
395 | b .ret_from_except_lite | 388 | b .ret_from_except_lite |
@@ -407,7 +400,6 @@ __start_interrupts: | |||
407 | _machine_check_pSeries: | 400 | _machine_check_pSeries: |
408 | HMT_MEDIUM | 401 | HMT_MEDIUM |
409 | mtspr SPRN_SPRG1,r13 /* save r13 */ | 402 | mtspr SPRN_SPRG1,r13 /* save r13 */ |
410 | RUNLATCH_ON(r13) | ||
411 | EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common) | 403 | EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common) |
412 | 404 | ||
413 | . = 0x300 | 405 | . = 0x300 |
@@ -434,7 +426,6 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB) | |||
434 | data_access_slb_pSeries: | 426 | data_access_slb_pSeries: |
435 | HMT_MEDIUM | 427 | HMT_MEDIUM |
436 | mtspr SPRN_SPRG1,r13 | 428 | mtspr SPRN_SPRG1,r13 |
437 | RUNLATCH_ON(r13) | ||
438 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ | 429 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ |
439 | std r3,PACA_EXSLB+EX_R3(r13) | 430 | std r3,PACA_EXSLB+EX_R3(r13) |
440 | mfspr r3,SPRN_DAR | 431 | mfspr r3,SPRN_DAR |
@@ -460,7 +451,6 @@ data_access_slb_pSeries: | |||
460 | instruction_access_slb_pSeries: | 451 | instruction_access_slb_pSeries: |
461 | HMT_MEDIUM | 452 | HMT_MEDIUM |
462 | mtspr SPRN_SPRG1,r13 | 453 | mtspr SPRN_SPRG1,r13 |
463 | RUNLATCH_ON(r13) | ||
464 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ | 454 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ |
465 | std r3,PACA_EXSLB+EX_R3(r13) | 455 | std r3,PACA_EXSLB+EX_R3(r13) |
466 | mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ | 456 | mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ |
@@ -491,7 +481,6 @@ instruction_access_slb_pSeries: | |||
491 | .globl system_call_pSeries | 481 | .globl system_call_pSeries |
492 | system_call_pSeries: | 482 | system_call_pSeries: |
493 | HMT_MEDIUM | 483 | HMT_MEDIUM |
494 | RUNLATCH_ON(r9) | ||
495 | mr r9,r13 | 484 | mr r9,r13 |
496 | mfmsr r10 | 485 | mfmsr r10 |
497 | mfspr r13,SPRN_SPRG3 | 486 | mfspr r13,SPRN_SPRG3 |
@@ -575,7 +564,6 @@ slb_miss_user_pseries: | |||
575 | system_reset_fwnmi: | 564 | system_reset_fwnmi: |
576 | HMT_MEDIUM | 565 | HMT_MEDIUM |
577 | mtspr SPRN_SPRG1,r13 /* save r13 */ | 566 | mtspr SPRN_SPRG1,r13 /* save r13 */ |
578 | RUNLATCH_ON(r13) | ||
579 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common) | 567 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common) |
580 | 568 | ||
581 | .globl machine_check_fwnmi | 569 | .globl machine_check_fwnmi |
@@ -583,7 +571,6 @@ system_reset_fwnmi: | |||
583 | machine_check_fwnmi: | 571 | machine_check_fwnmi: |
584 | HMT_MEDIUM | 572 | HMT_MEDIUM |
585 | mtspr SPRN_SPRG1,r13 /* save r13 */ | 573 | mtspr SPRN_SPRG1,r13 /* save r13 */ |
586 | RUNLATCH_ON(r13) | ||
587 | EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common) | 574 | EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common) |
588 | 575 | ||
589 | #ifdef CONFIG_PPC_ISERIES | 576 | #ifdef CONFIG_PPC_ISERIES |
@@ -858,6 +845,14 @@ fast_exception_return: | |||
858 | ld r11,_NIP(r1) | 845 | ld r11,_NIP(r1) |
859 | andi. r3,r12,MSR_RI /* check if RI is set */ | 846 | andi. r3,r12,MSR_RI /* check if RI is set */ |
860 | 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 | |||
861 | ld r3,_CCR(r1) | 856 | ld r3,_CCR(r1) |
862 | ld r4,_LINK(r1) | 857 | ld r4,_LINK(r1) |
863 | ld r5,_CTR(r1) | 858 | ld r5,_CTR(r1) |
@@ -894,7 +889,6 @@ unrecov_fer: | |||
894 | .align 7 | 889 | .align 7 |
895 | .globl data_access_common | 890 | .globl data_access_common |
896 | data_access_common: | 891 | data_access_common: |
897 | RUNLATCH_ON(r10) /* It wont fit in the 0x300 handler */ | ||
898 | mfspr r10,SPRN_DAR | 892 | mfspr r10,SPRN_DAR |
899 | std r10,PACA_EXGEN+EX_DAR(r13) | 893 | std r10,PACA_EXGEN+EX_DAR(r13) |
900 | mfspr r10,SPRN_DSISR | 894 | mfspr r10,SPRN_DSISR |
@@ -1042,6 +1036,7 @@ hardware_interrupt_common: | |||
1042 | EXCEPTION_PROLOG_COMMON(0x500, PACA_EXGEN) | 1036 | EXCEPTION_PROLOG_COMMON(0x500, PACA_EXGEN) |
1043 | hardware_interrupt_entry: | 1037 | hardware_interrupt_entry: |
1044 | DISABLE_INTS | 1038 | DISABLE_INTS |
1039 | bl .ppc64_runlatch_on | ||
1045 | addi r3,r1,STACK_FRAME_OVERHEAD | 1040 | addi r3,r1,STACK_FRAME_OVERHEAD |
1046 | bl .do_IRQ | 1041 | bl .do_IRQ |
1047 | b .ret_from_except_lite | 1042 | b .ret_from_except_lite |
@@ -1816,22 +1811,6 @@ _STATIC(start_here_multiplatform) | |||
1816 | ori r6,r6,MSR_RI | 1811 | ori r6,r6,MSR_RI |
1817 | mtmsrd r6 /* RI on */ | 1812 | mtmsrd r6 /* RI on */ |
1818 | 1813 | ||
1819 | #ifdef CONFIG_HMT | ||
1820 | /* Start up the second thread on cpu 0 */ | ||
1821 | mfspr r3,SPRN_PVR | ||
1822 | srwi r3,r3,16 | ||
1823 | cmpwi r3,0x34 /* Pulsar */ | ||
1824 | beq 90f | ||
1825 | cmpwi r3,0x36 /* Icestar */ | ||
1826 | beq 90f | ||
1827 | cmpwi r3,0x37 /* SStar */ | ||
1828 | beq 90f | ||
1829 | b 91f /* HMT not supported */ | ||
1830 | 90: li r3,0 | ||
1831 | bl .hmt_start_secondary | ||
1832 | 91: | ||
1833 | #endif | ||
1834 | |||
1835 | /* The following gets the stack and TOC set up with the regs */ | 1814 | /* The following gets the stack and TOC set up with the regs */ |
1836 | /* pointing to the real addr of the kernel stack. This is */ | 1815 | /* pointing to the real addr of the kernel stack. This is */ |
1837 | /* all done to support the C function call below which sets */ | 1816 | /* all done to support the C function call below which sets */ |
@@ -1945,77 +1924,8 @@ _STATIC(start_here_common) | |||
1945 | 1924 | ||
1946 | bl .start_kernel | 1925 | bl .start_kernel |
1947 | 1926 | ||
1948 | _GLOBAL(hmt_init) | 1927 | /* Not reached */ |
1949 | #ifdef CONFIG_HMT | 1928 | BUG_OPCODE |
1950 | LOAD_REG_IMMEDIATE(r5, hmt_thread_data) | ||
1951 | mfspr r7,SPRN_PVR | ||
1952 | srwi r7,r7,16 | ||
1953 | cmpwi r7,0x34 /* Pulsar */ | ||
1954 | beq 90f | ||
1955 | cmpwi r7,0x36 /* Icestar */ | ||
1956 | beq 91f | ||
1957 | cmpwi r7,0x37 /* SStar */ | ||
1958 | beq 91f | ||
1959 | b 101f | ||
1960 | 90: mfspr r6,SPRN_PIR | ||
1961 | andi. r6,r6,0x1f | ||
1962 | b 92f | ||
1963 | 91: mfspr r6,SPRN_PIR | ||
1964 | andi. r6,r6,0x3ff | ||
1965 | 92: sldi r4,r24,3 | ||
1966 | stwx r6,r5,r4 | ||
1967 | bl .hmt_start_secondary | ||
1968 | b 101f | ||
1969 | |||
1970 | __hmt_secondary_hold: | ||
1971 | LOAD_REG_IMMEDIATE(r5, hmt_thread_data) | ||
1972 | clrldi r5,r5,4 | ||
1973 | li r7,0 | ||
1974 | mfspr r6,SPRN_PIR | ||
1975 | mfspr r8,SPRN_PVR | ||
1976 | srwi r8,r8,16 | ||
1977 | cmpwi r8,0x34 | ||
1978 | bne 93f | ||
1979 | andi. r6,r6,0x1f | ||
1980 | b 103f | ||
1981 | 93: andi. r6,r6,0x3f | ||
1982 | |||
1983 | 103: lwzx r8,r5,r7 | ||
1984 | cmpw r8,r6 | ||
1985 | beq 104f | ||
1986 | addi r7,r7,8 | ||
1987 | b 103b | ||
1988 | |||
1989 | 104: addi r7,r7,4 | ||
1990 | lwzx r9,r5,r7 | ||
1991 | mr r24,r9 | ||
1992 | 101: | ||
1993 | #endif | ||
1994 | mr r3,r24 | ||
1995 | b .pSeries_secondary_smp_init | ||
1996 | |||
1997 | #ifdef CONFIG_HMT | ||
1998 | _GLOBAL(hmt_start_secondary) | ||
1999 | LOAD_REG_IMMEDIATE(r4,__hmt_secondary_hold) | ||
2000 | clrldi r4,r4,4 | ||
2001 | mtspr SPRN_NIADORM, r4 | ||
2002 | mfspr r4, SPRN_MSRDORM | ||
2003 | li r5, -65 | ||
2004 | and r4, r4, r5 | ||
2005 | mtspr SPRN_MSRDORM, r4 | ||
2006 | lis r4,0xffef | ||
2007 | ori r4,r4,0x7403 | ||
2008 | mtspr SPRN_TSC, r4 | ||
2009 | li r4,0x1f4 | ||
2010 | mtspr SPRN_TST, r4 | ||
2011 | mfspr r4, SPRN_HID0 | ||
2012 | ori r4, r4, 0x1 | ||
2013 | mtspr SPRN_HID0, r4 | ||
2014 | mfspr r4, SPRN_CTRLF | ||
2015 | oris r4, r4, 0x40 | ||
2016 | mtspr SPRN_CTRLT, r4 | ||
2017 | blr | ||
2018 | #endif | ||
2019 | 1929 | ||
2020 | /* | 1930 | /* |
2021 | * We put a few things here that have to be page-aligned. | 1931 | * We put a few things here that have to be page-aligned. |
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index edb2b00edbd2..24dc8117b822 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
@@ -369,6 +369,7 @@ unsigned int real_irq_to_virt_slowpath(unsigned int real_irq) | |||
369 | return NO_IRQ; | 369 | return NO_IRQ; |
370 | 370 | ||
371 | } | 371 | } |
372 | #endif /* CONFIG_PPC64 */ | ||
372 | 373 | ||
373 | #ifdef CONFIG_IRQSTACKS | 374 | #ifdef CONFIG_IRQSTACKS |
374 | struct thread_info *softirq_ctx[NR_CPUS]; | 375 | struct thread_info *softirq_ctx[NR_CPUS]; |
@@ -392,10 +393,24 @@ void irq_ctx_init(void) | |||
392 | } | 393 | } |
393 | } | 394 | } |
394 | 395 | ||
396 | static inline void do_softirq_onstack(void) | ||
397 | { | ||
398 | struct thread_info *curtp, *irqtp; | ||
399 | |||
400 | curtp = current_thread_info(); | ||
401 | irqtp = softirq_ctx[smp_processor_id()]; | ||
402 | irqtp->task = curtp->task; | ||
403 | call_do_softirq(irqtp); | ||
404 | irqtp->task = NULL; | ||
405 | } | ||
406 | |||
407 | #else | ||
408 | #define do_softirq_onstack() __do_softirq() | ||
409 | #endif /* CONFIG_IRQSTACKS */ | ||
410 | |||
395 | void do_softirq(void) | 411 | void do_softirq(void) |
396 | { | 412 | { |
397 | unsigned long flags; | 413 | unsigned long flags; |
398 | struct thread_info *curtp, *irqtp; | ||
399 | 414 | ||
400 | if (in_interrupt()) | 415 | if (in_interrupt()) |
401 | return; | 416 | return; |
@@ -403,19 +418,18 @@ void do_softirq(void) | |||
403 | local_irq_save(flags); | 418 | local_irq_save(flags); |
404 | 419 | ||
405 | if (local_softirq_pending()) { | 420 | if (local_softirq_pending()) { |
406 | curtp = current_thread_info(); | 421 | account_system_vtime(current); |
407 | irqtp = softirq_ctx[smp_processor_id()]; | 422 | local_bh_disable(); |
408 | irqtp->task = curtp->task; | 423 | do_softirq_onstack(); |
409 | call_do_softirq(irqtp); | 424 | account_system_vtime(current); |
410 | irqtp->task = NULL; | 425 | __local_bh_enable(); |
411 | } | 426 | } |
412 | 427 | ||
413 | local_irq_restore(flags); | 428 | local_irq_restore(flags); |
414 | } | 429 | } |
415 | EXPORT_SYMBOL(do_softirq); | 430 | EXPORT_SYMBOL(do_softirq); |
416 | 431 | ||
417 | #endif /* CONFIG_IRQSTACKS */ | 432 | #ifdef CONFIG_PPC64 |
418 | |||
419 | static int __init setup_noirqdistrib(char *str) | 433 | static int __init setup_noirqdistrib(char *str) |
420 | { | 434 | { |
421 | distribute_irqs = 0; | 435 | distribute_irqs = 0; |
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index 1ae96a8ed7e2..e789fef4eb8a 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c | |||
@@ -341,7 +341,7 @@ static int lparcfg_data(struct seq_file *m, void *v) | |||
341 | const char *system_id = ""; | 341 | const char *system_id = ""; |
342 | unsigned int *lp_index_ptr, lp_index = 0; | 342 | unsigned int *lp_index_ptr, lp_index = 0; |
343 | struct device_node *rtas_node; | 343 | struct device_node *rtas_node; |
344 | int *lrdrp; | 344 | int *lrdrp = NULL; |
345 | 345 | ||
346 | rootdn = find_path_device("/"); | 346 | rootdn = find_path_device("/"); |
347 | if (rootdn) { | 347 | if (rootdn) { |
@@ -362,7 +362,9 @@ static int lparcfg_data(struct seq_file *m, void *v) | |||
362 | seq_printf(m, "partition_id=%d\n", (int)lp_index); | 362 | seq_printf(m, "partition_id=%d\n", (int)lp_index); |
363 | 363 | ||
364 | rtas_node = find_path_device("/rtas"); | 364 | rtas_node = find_path_device("/rtas"); |
365 | lrdrp = (int *)get_property(rtas_node, "ibm,lrdr-capacity", NULL); | 365 | if (rtas_node) |
366 | lrdrp = (int *)get_property(rtas_node, "ibm,lrdr-capacity", | ||
367 | NULL); | ||
366 | 368 | ||
367 | if (lrdrp == NULL) { | 369 | if (lrdrp == NULL) { |
368 | partition_potential_processors = vdso_data->processorCount; | 370 | partition_potential_processors = vdso_data->processorCount; |
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index d6431440c54f..ee166c586642 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c | |||
@@ -26,8 +26,6 @@ | |||
26 | #include <asm/prom.h> | 26 | #include <asm/prom.h> |
27 | #include <asm/smp.h> | 27 | #include <asm/smp.h> |
28 | 28 | ||
29 | #define HASH_GROUP_SIZE 0x80 /* size of each hash group, asm/mmu.h */ | ||
30 | |||
31 | int default_machine_kexec_prepare(struct kimage *image) | 29 | int default_machine_kexec_prepare(struct kimage *image) |
32 | { | 30 | { |
33 | int i; | 31 | int i; |
@@ -61,7 +59,7 @@ int default_machine_kexec_prepare(struct kimage *image) | |||
61 | */ | 59 | */ |
62 | if (htab_address) { | 60 | if (htab_address) { |
63 | low = __pa(htab_address); | 61 | low = __pa(htab_address); |
64 | high = low + (htab_hash_mask + 1) * HASH_GROUP_SIZE; | 62 | high = low + htab_size_bytes; |
65 | 63 | ||
66 | for (i = 0; i < image->nr_segments; i++) { | 64 | for (i = 0; i < image->nr_segments; i++) { |
67 | begin = image->segment[i].mem; | 65 | begin = image->segment[i].mem; |
@@ -294,7 +292,7 @@ void default_machine_kexec(struct kimage *image) | |||
294 | } | 292 | } |
295 | 293 | ||
296 | /* Values we need to export to the second kernel via the device tree. */ | 294 | /* Values we need to export to the second kernel via the device tree. */ |
297 | static unsigned long htab_base, htab_size, kernel_end; | 295 | static unsigned long htab_base, kernel_end; |
298 | 296 | ||
299 | static struct property htab_base_prop = { | 297 | static struct property htab_base_prop = { |
300 | .name = "linux,htab-base", | 298 | .name = "linux,htab-base", |
@@ -305,7 +303,7 @@ static struct property htab_base_prop = { | |||
305 | static struct property htab_size_prop = { | 303 | static struct property htab_size_prop = { |
306 | .name = "linux,htab-size", | 304 | .name = "linux,htab-size", |
307 | .length = sizeof(unsigned long), | 305 | .length = sizeof(unsigned long), |
308 | .value = (unsigned char *)&htab_size, | 306 | .value = (unsigned char *)&htab_size_bytes, |
309 | }; | 307 | }; |
310 | 308 | ||
311 | static struct property kernel_end_prop = { | 309 | static struct property kernel_end_prop = { |
@@ -331,8 +329,6 @@ static void __init export_htab_values(void) | |||
331 | 329 | ||
332 | htab_base = __pa(htab_address); | 330 | htab_base = __pa(htab_address); |
333 | prom_add_property(node, &htab_base_prop); | 331 | prom_add_property(node, &htab_base_prop); |
334 | |||
335 | htab_size = 1UL << ppc64_pft_size; | ||
336 | prom_add_property(node, &htab_size_prop); | 332 | prom_add_property(node, &htab_size_prop); |
337 | 333 | ||
338 | out: | 334 | out: |
diff --git a/arch/powerpc/kernel/ppc_ksyms.c b/arch/powerpc/kernel/ppc_ksyms.c index b212d3e64b8d..af32922db65b 100644 --- a/arch/powerpc/kernel/ppc_ksyms.c +++ b/arch/powerpc/kernel/ppc_ksyms.c | |||
@@ -78,15 +78,8 @@ EXPORT_SYMBOL(sys_sigreturn); | |||
78 | EXPORT_SYMBOL(strcpy); | 78 | EXPORT_SYMBOL(strcpy); |
79 | EXPORT_SYMBOL(strncpy); | 79 | EXPORT_SYMBOL(strncpy); |
80 | EXPORT_SYMBOL(strcat); | 80 | EXPORT_SYMBOL(strcat); |
81 | EXPORT_SYMBOL(strncat); | ||
82 | EXPORT_SYMBOL(strchr); | ||
83 | EXPORT_SYMBOL(strrchr); | ||
84 | EXPORT_SYMBOL(strpbrk); | ||
85 | EXPORT_SYMBOL(strstr); | ||
86 | EXPORT_SYMBOL(strlen); | 81 | EXPORT_SYMBOL(strlen); |
87 | EXPORT_SYMBOL(strnlen); | ||
88 | EXPORT_SYMBOL(strcmp); | 82 | EXPORT_SYMBOL(strcmp); |
89 | EXPORT_SYMBOL(strncmp); | ||
90 | EXPORT_SYMBOL(strcasecmp); | 83 | EXPORT_SYMBOL(strcasecmp); |
91 | 84 | ||
92 | EXPORT_SYMBOL(csum_partial); | 85 | EXPORT_SYMBOL(csum_partial); |
@@ -184,9 +177,6 @@ EXPORT_SYMBOL(adb_try_handler_change); | |||
184 | EXPORT_SYMBOL(cuda_request); | 177 | EXPORT_SYMBOL(cuda_request); |
185 | EXPORT_SYMBOL(cuda_poll); | 178 | EXPORT_SYMBOL(cuda_poll); |
186 | #endif /* CONFIG_ADB_CUDA */ | 179 | #endif /* CONFIG_ADB_CUDA */ |
187 | #ifdef CONFIG_PPC_PMAC | ||
188 | EXPORT_SYMBOL(sys_ctrler); | ||
189 | #endif | ||
190 | #ifdef CONFIG_VT | 180 | #ifdef CONFIG_VT |
191 | EXPORT_SYMBOL(kd_mksound); | 181 | EXPORT_SYMBOL(kd_mksound); |
192 | #endif | 182 | #endif |
@@ -204,7 +194,6 @@ EXPORT_SYMBOL(__lshrdi3); | |||
204 | EXPORT_SYMBOL(memcpy); | 194 | EXPORT_SYMBOL(memcpy); |
205 | EXPORT_SYMBOL(memset); | 195 | EXPORT_SYMBOL(memset); |
206 | EXPORT_SYMBOL(memmove); | 196 | EXPORT_SYMBOL(memmove); |
207 | EXPORT_SYMBOL(memscan); | ||
208 | EXPORT_SYMBOL(memcmp); | 197 | EXPORT_SYMBOL(memcmp); |
209 | EXPORT_SYMBOL(memchr); | 198 | EXPORT_SYMBOL(memchr); |
210 | 199 | ||
@@ -213,7 +202,6 @@ EXPORT_SYMBOL(screen_info); | |||
213 | #endif | 202 | #endif |
214 | 203 | ||
215 | #ifdef CONFIG_PPC32 | 204 | #ifdef CONFIG_PPC32 |
216 | EXPORT_SYMBOL(__delay); | ||
217 | EXPORT_SYMBOL(timer_interrupt); | 205 | EXPORT_SYMBOL(timer_interrupt); |
218 | EXPORT_SYMBOL(irq_desc); | 206 | EXPORT_SYMBOL(irq_desc); |
219 | EXPORT_SYMBOL(tb_ticks_per_jiffy); | 207 | EXPORT_SYMBOL(tb_ticks_per_jiffy); |
@@ -221,10 +209,6 @@ EXPORT_SYMBOL(console_drivers); | |||
221 | EXPORT_SYMBOL(cacheable_memcpy); | 209 | EXPORT_SYMBOL(cacheable_memcpy); |
222 | #endif | 210 | #endif |
223 | 211 | ||
224 | EXPORT_SYMBOL(__up); | ||
225 | EXPORT_SYMBOL(__down); | ||
226 | EXPORT_SYMBOL(__down_interruptible); | ||
227 | |||
228 | #ifdef CONFIG_8xx | 212 | #ifdef CONFIG_8xx |
229 | EXPORT_SYMBOL(cpm_install_handler); | 213 | EXPORT_SYMBOL(cpm_install_handler); |
230 | EXPORT_SYMBOL(cpm_free_handler); | 214 | EXPORT_SYMBOL(cpm_free_handler); |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 1201880cab40..1770a066c217 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -45,9 +45,9 @@ | |||
45 | #include <asm/mmu.h> | 45 | #include <asm/mmu.h> |
46 | #include <asm/prom.h> | 46 | #include <asm/prom.h> |
47 | #include <asm/machdep.h> | 47 | #include <asm/machdep.h> |
48 | #include <asm/time.h> | ||
48 | #ifdef CONFIG_PPC64 | 49 | #ifdef CONFIG_PPC64 |
49 | #include <asm/firmware.h> | 50 | #include <asm/firmware.h> |
50 | #include <asm/time.h> | ||
51 | #endif | 51 | #endif |
52 | 52 | ||
53 | extern unsigned long _get_SP(void); | 53 | extern unsigned long _get_SP(void); |
@@ -328,6 +328,11 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
328 | #endif | 328 | #endif |
329 | 329 | ||
330 | 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 | |||
331 | last = _switch(old_thread, new_thread); | 336 | last = _switch(old_thread, new_thread); |
332 | 337 | ||
333 | local_irq_restore(flags); | 338 | local_irq_restore(flags); |
@@ -886,3 +891,35 @@ void dump_stack(void) | |||
886 | show_stack(current, NULL); | 891 | show_stack(current, NULL); |
887 | } | 892 | } |
888 | EXPORT_SYMBOL(dump_stack); | 893 | EXPORT_SYMBOL(dump_stack); |
894 | |||
895 | #ifdef CONFIG_PPC64 | ||
896 | void ppc64_runlatch_on(void) | ||
897 | { | ||
898 | unsigned long ctrl; | ||
899 | |||
900 | if (cpu_has_feature(CPU_FTR_CTRL) && !test_thread_flag(TIF_RUNLATCH)) { | ||
901 | HMT_medium(); | ||
902 | |||
903 | ctrl = mfspr(SPRN_CTRLF); | ||
904 | ctrl |= CTRL_RUNLATCH; | ||
905 | mtspr(SPRN_CTRLT, ctrl); | ||
906 | |||
907 | set_thread_flag(TIF_RUNLATCH); | ||
908 | } | ||
909 | } | ||
910 | |||
911 | void ppc64_runlatch_off(void) | ||
912 | { | ||
913 | unsigned long ctrl; | ||
914 | |||
915 | if (cpu_has_feature(CPU_FTR_CTRL) && test_thread_flag(TIF_RUNLATCH)) { | ||
916 | HMT_medium(); | ||
917 | |||
918 | clear_thread_flag(TIF_RUNLATCH); | ||
919 | |||
920 | ctrl = mfspr(SPRN_CTRLF); | ||
921 | ctrl &= ~CTRL_RUNLATCH; | ||
922 | mtspr(SPRN_CTRLT, ctrl); | ||
923 | } | ||
924 | } | ||
925 | #endif | ||
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 82d117c60d7f..d63cd562d9d5 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -816,8 +816,6 @@ void __init unflatten_device_tree(void) | |||
816 | { | 816 | { |
817 | unsigned long start, mem, size; | 817 | unsigned long start, mem, size; |
818 | struct device_node **allnextp = &allnodes; | 818 | struct device_node **allnextp = &allnodes; |
819 | char *p = NULL; | ||
820 | int l = 0; | ||
821 | 819 | ||
822 | DBG(" -> unflatten_device_tree()\n"); | 820 | DBG(" -> unflatten_device_tree()\n"); |
823 | 821 | ||
@@ -853,19 +851,6 @@ void __init unflatten_device_tree(void) | |||
853 | if (of_chosen == NULL) | 851 | if (of_chosen == NULL) |
854 | of_chosen = of_find_node_by_path("/chosen@0"); | 852 | of_chosen = of_find_node_by_path("/chosen@0"); |
855 | 853 | ||
856 | /* Retreive command line */ | ||
857 | if (of_chosen != NULL) { | ||
858 | p = (char *)get_property(of_chosen, "bootargs", &l); | ||
859 | if (p != NULL && l > 0) | ||
860 | strlcpy(cmd_line, p, min(l, COMMAND_LINE_SIZE)); | ||
861 | } | ||
862 | #ifdef CONFIG_CMDLINE | ||
863 | if (l == 0 || (l == 1 && (*p) == 0)) | ||
864 | strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); | ||
865 | #endif /* CONFIG_CMDLINE */ | ||
866 | |||
867 | DBG("Command line is: %s\n", cmd_line); | ||
868 | |||
869 | DBG(" <- unflatten_device_tree()\n"); | 854 | DBG(" <- unflatten_device_tree()\n"); |
870 | } | 855 | } |
871 | 856 | ||
@@ -936,6 +921,8 @@ static int __init early_init_dt_scan_chosen(unsigned long node, | |||
936 | { | 921 | { |
937 | u32 *prop; | 922 | u32 *prop; |
938 | unsigned long *lprop; | 923 | unsigned long *lprop; |
924 | unsigned long l; | ||
925 | char *p; | ||
939 | 926 | ||
940 | DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname); | 927 | DBG("search \"chosen\", depth: %d, uname: %s\n", depth, uname); |
941 | 928 | ||
@@ -1000,6 +987,41 @@ static int __init early_init_dt_scan_chosen(unsigned long node, | |||
1000 | crashk_res.end = crashk_res.start + *lprop - 1; | 987 | crashk_res.end = crashk_res.start + *lprop - 1; |
1001 | #endif | 988 | #endif |
1002 | 989 | ||
990 | /* Retreive command line */ | ||
991 | p = of_get_flat_dt_prop(node, "bootargs", &l); | ||
992 | if (p != NULL && l > 0) | ||
993 | strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE)); | ||
994 | |||
995 | #ifdef CONFIG_CMDLINE | ||
996 | if (l == 0 || (l == 1 && (*p) == 0)) | ||
997 | strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE); | ||
998 | #endif /* CONFIG_CMDLINE */ | ||
999 | |||
1000 | DBG("Command line is: %s\n", cmd_line); | ||
1001 | |||
1002 | if (strstr(cmd_line, "mem=")) { | ||
1003 | char *p, *q; | ||
1004 | unsigned long maxmem = 0; | ||
1005 | |||
1006 | for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) { | ||
1007 | q = p + 4; | ||
1008 | if (p > cmd_line && p[-1] != ' ') | ||
1009 | continue; | ||
1010 | maxmem = simple_strtoul(q, &q, 0); | ||
1011 | if (*q == 'k' || *q == 'K') { | ||
1012 | maxmem <<= 10; | ||
1013 | ++q; | ||
1014 | } else if (*q == 'm' || *q == 'M') { | ||
1015 | maxmem <<= 20; | ||
1016 | ++q; | ||
1017 | } else if (*q == 'g' || *q == 'G') { | ||
1018 | maxmem <<= 30; | ||
1019 | ++q; | ||
1020 | } | ||
1021 | } | ||
1022 | memory_limit = maxmem; | ||
1023 | } | ||
1024 | |||
1003 | /* break now */ | 1025 | /* break now */ |
1004 | return 1; | 1026 | return 1; |
1005 | } | 1027 | } |
@@ -1120,7 +1142,7 @@ static void __init early_reserve_mem(void) | |||
1120 | size_32 = *(reserve_map_32++); | 1142 | size_32 = *(reserve_map_32++); |
1121 | if (size_32 == 0) | 1143 | if (size_32 == 0) |
1122 | break; | 1144 | break; |
1123 | DBG("reserving: %lx -> %lx\n", base_32, size_32); | 1145 | DBG("reserving: %x -> %x\n", base_32, size_32); |
1124 | lmb_reserve(base_32, size_32); | 1146 | lmb_reserve(base_32, size_32); |
1125 | } | 1147 | } |
1126 | return; | 1148 | return; |
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index ec7153f4d47c..d34fe537400e 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
@@ -205,14 +205,6 @@ static cell_t __initdata regbuf[1024]; | |||
205 | 205 | ||
206 | #define MAX_CPU_THREADS 2 | 206 | #define MAX_CPU_THREADS 2 |
207 | 207 | ||
208 | /* TO GO */ | ||
209 | #ifdef CONFIG_HMT | ||
210 | struct { | ||
211 | unsigned int pir; | ||
212 | unsigned int threadid; | ||
213 | } hmt_thread_data[NR_CPUS]; | ||
214 | #endif /* CONFIG_HMT */ | ||
215 | |||
216 | /* | 208 | /* |
217 | * Error results ... some OF calls will return "-1" on error, some | 209 | * Error results ... some OF calls will return "-1" on error, some |
218 | * will return 0, some will return either. To simplify, here are | 210 | * will return 0, some will return either. To simplify, here are |
@@ -1319,10 +1311,6 @@ static void __init prom_hold_cpus(void) | |||
1319 | */ | 1311 | */ |
1320 | *spinloop = 0; | 1312 | *spinloop = 0; |
1321 | 1313 | ||
1322 | #ifdef CONFIG_HMT | ||
1323 | for (i = 0; i < NR_CPUS; i++) | ||
1324 | RELOC(hmt_thread_data)[i].pir = 0xdeadbeef; | ||
1325 | #endif | ||
1326 | /* look for cpus */ | 1314 | /* look for cpus */ |
1327 | for (node = 0; prom_next_node(&node); ) { | 1315 | for (node = 0; prom_next_node(&node); ) { |
1328 | type[0] = 0; | 1316 | type[0] = 0; |
@@ -1389,32 +1377,6 @@ static void __init prom_hold_cpus(void) | |||
1389 | /* Reserve cpu #s for secondary threads. They start later. */ | 1377 | /* Reserve cpu #s for secondary threads. They start later. */ |
1390 | cpuid += cpu_threads; | 1378 | cpuid += cpu_threads; |
1391 | } | 1379 | } |
1392 | #ifdef CONFIG_HMT | ||
1393 | /* Only enable HMT on processors that provide support. */ | ||
1394 | if (__is_processor(PV_PULSAR) || | ||
1395 | __is_processor(PV_ICESTAR) || | ||
1396 | __is_processor(PV_SSTAR)) { | ||
1397 | prom_printf(" starting secondary threads\n"); | ||
1398 | |||
1399 | for (i = 0; i < NR_CPUS; i += 2) { | ||
1400 | if (!cpu_online(i)) | ||
1401 | continue; | ||
1402 | |||
1403 | if (i == 0) { | ||
1404 | unsigned long pir = mfspr(SPRN_PIR); | ||
1405 | if (__is_processor(PV_PULSAR)) { | ||
1406 | RELOC(hmt_thread_data)[i].pir = | ||
1407 | pir & 0x1f; | ||
1408 | } else { | ||
1409 | RELOC(hmt_thread_data)[i].pir = | ||
1410 | pir & 0x3ff; | ||
1411 | } | ||
1412 | } | ||
1413 | } | ||
1414 | } else { | ||
1415 | prom_printf("Processor is not HMT capable\n"); | ||
1416 | } | ||
1417 | #endif | ||
1418 | 1380 | ||
1419 | if (cpuid > NR_CPUS) | 1381 | if (cpuid > NR_CPUS) |
1420 | prom_printf("WARNING: maximum CPUs (" __stringify(NR_CPUS) | 1382 | prom_printf("WARNING: maximum CPUs (" __stringify(NR_CPUS) |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index a717dff695ef..f96c49b03ba0 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -311,8 +311,6 @@ void smp_release_cpus(void) | |||
311 | 311 | ||
312 | DBG(" <- smp_release_cpus()\n"); | 312 | DBG(" <- smp_release_cpus()\n"); |
313 | } | 313 | } |
314 | #else | ||
315 | #define smp_release_cpus() | ||
316 | #endif /* CONFIG_SMP || CONFIG_KEXEC */ | 314 | #endif /* CONFIG_SMP || CONFIG_KEXEC */ |
317 | 315 | ||
318 | /* | 316 | /* |
@@ -473,10 +471,12 @@ void __init setup_system(void) | |||
473 | check_smt_enabled(); | 471 | check_smt_enabled(); |
474 | smp_setup_cpu_maps(); | 472 | smp_setup_cpu_maps(); |
475 | 473 | ||
474 | #ifdef CONFIG_SMP | ||
476 | /* Release secondary cpus out of their spinloops at 0x60 now that | 475 | /* Release secondary cpus out of their spinloops at 0x60 now that |
477 | * we can map physical -> logical CPU ids | 476 | * we can map physical -> logical CPU ids |
478 | */ | 477 | */ |
479 | smp_release_cpus(); | 478 | smp_release_cpus(); |
479 | #endif | ||
480 | 480 | ||
481 | printk("Starting Linux PPC64 %s\n", system_utsname.version); | 481 | printk("Starting Linux PPC64 %s\n", system_utsname.version); |
482 | 482 | ||
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/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c index 475249dc2350..cd75ab2908fa 100644 --- a/arch/powerpc/kernel/sys_ppc32.c +++ b/arch/powerpc/kernel/sys_ppc32.c | |||
@@ -176,7 +176,6 @@ struct timex32 { | |||
176 | }; | 176 | }; |
177 | 177 | ||
178 | extern int do_adjtimex(struct timex *); | 178 | extern int do_adjtimex(struct timex *); |
179 | extern void ppc_adjtimex(void); | ||
180 | 179 | ||
181 | asmlinkage long compat_sys_adjtimex(struct timex32 __user *utp) | 180 | asmlinkage long compat_sys_adjtimex(struct timex32 __user *utp) |
182 | { | 181 | { |
@@ -209,9 +208,6 @@ asmlinkage long compat_sys_adjtimex(struct timex32 __user *utp) | |||
209 | 208 | ||
210 | ret = do_adjtimex(&txc); | 209 | ret = do_adjtimex(&txc); |
211 | 210 | ||
212 | /* adjust the conversion of TB to time of day to track adjtimex */ | ||
213 | ppc_adjtimex(); | ||
214 | |||
215 | if(put_user(txc.modes, &utp->modes) || | 211 | if(put_user(txc.modes, &utp->modes) || |
216 | __put_user(txc.offset, &utp->offset) || | 212 | __put_user(txc.offset, &utp->offset) || |
217 | __put_user(txc.freq, &utp->freq) || | 213 | __put_user(txc.freq, &utp->freq) || |
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 1886045a2fd8..4f20a5f15d49 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -50,6 +50,8 @@ | |||
50 | #include <linux/security.h> | 50 | #include <linux/security.h> |
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> | ||
54 | #include <linux/posix-timers.h> | ||
53 | 55 | ||
54 | #include <asm/io.h> | 56 | #include <asm/io.h> |
55 | #include <asm/processor.h> | 57 | #include <asm/processor.h> |
@@ -97,9 +99,18 @@ unsigned long tb_ticks_per_jiffy; | |||
97 | unsigned long tb_ticks_per_usec = 100; /* sane default */ | 99 | unsigned long tb_ticks_per_usec = 100; /* sane default */ |
98 | EXPORT_SYMBOL(tb_ticks_per_usec); | 100 | EXPORT_SYMBOL(tb_ticks_per_usec); |
99 | unsigned long tb_ticks_per_sec; | 101 | unsigned long tb_ticks_per_sec; |
102 | EXPORT_SYMBOL(tb_ticks_per_sec); /* for cputime_t conversions */ | ||
100 | u64 tb_to_xs; | 103 | u64 tb_to_xs; |
101 | unsigned tb_to_us; | 104 | unsigned tb_to_us; |
102 | unsigned long processor_freq; | 105 | |
106 | #define TICKLEN_SCALE (SHIFT_SCALE - 10) | ||
107 | u64 last_tick_len; /* units are ns / 2^TICKLEN_SCALE */ | ||
108 | u64 ticklen_to_xs; /* 0.64 fraction */ | ||
109 | |||
110 | /* If last_tick_len corresponds to about 1/HZ seconds, then | ||
111 | last_tick_len << TICKLEN_SHIFT will be about 2^63. */ | ||
112 | #define TICKLEN_SHIFT (63 - 30 - TICKLEN_SCALE + SHIFT_HZ) | ||
113 | |||
103 | DEFINE_SPINLOCK(rtc_lock); | 114 | DEFINE_SPINLOCK(rtc_lock); |
104 | EXPORT_SYMBOL_GPL(rtc_lock); | 115 | EXPORT_SYMBOL_GPL(rtc_lock); |
105 | 116 | ||
@@ -113,10 +124,6 @@ extern unsigned long wall_jiffies; | |||
113 | extern struct timezone sys_tz; | 124 | extern struct timezone sys_tz; |
114 | static long timezone_offset; | 125 | static long timezone_offset; |
115 | 126 | ||
116 | void ppc_adjtimex(void); | ||
117 | |||
118 | static unsigned adjusting_time = 0; | ||
119 | |||
120 | unsigned long ppc_proc_freq; | 127 | unsigned long ppc_proc_freq; |
121 | unsigned long ppc_tb_freq; | 128 | unsigned long ppc_tb_freq; |
122 | 129 | ||
@@ -130,6 +137,224 @@ unsigned long tb_last_stamp; | |||
130 | */ | 137 | */ |
131 | DEFINE_PER_CPU(unsigned long, last_jiffy); | 138 | DEFINE_PER_CPU(unsigned long, last_jiffy); |
132 | 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 | |||
133 | void __delay(unsigned long loops) | 358 | void __delay(unsigned long loops) |
134 | { | 359 | { |
135 | unsigned long start; | 360 | unsigned long start; |
@@ -178,8 +403,7 @@ static __inline__ void timer_check_rtc(void) | |||
178 | */ | 403 | */ |
179 | if (ppc_md.set_rtc_time && ntp_synced() && | 404 | if (ppc_md.set_rtc_time && ntp_synced() && |
180 | xtime.tv_sec - last_rtc_update >= 659 && | 405 | xtime.tv_sec - last_rtc_update >= 659 && |
181 | abs((xtime.tv_nsec/1000) - (1000000-1000000/HZ)) < 500000/HZ && | 406 | abs((xtime.tv_nsec/1000) - (1000000-1000000/HZ)) < 500000/HZ) { |
182 | jiffies - wall_jiffies == 1) { | ||
183 | struct rtc_time tm; | 407 | struct rtc_time tm; |
184 | to_tm(xtime.tv_sec + 1 + timezone_offset, &tm); | 408 | to_tm(xtime.tv_sec + 1 + timezone_offset, &tm); |
185 | tm.tm_year -= 1900; | 409 | tm.tm_year -= 1900; |
@@ -226,15 +450,14 @@ void do_gettimeofday(struct timeval *tv) | |||
226 | if (__USE_RTC()) { | 450 | if (__USE_RTC()) { |
227 | /* do this the old way */ | 451 | /* do this the old way */ |
228 | unsigned long flags, seq; | 452 | unsigned long flags, seq; |
229 | unsigned int sec, nsec, usec, lost; | 453 | unsigned int sec, nsec, usec; |
230 | 454 | ||
231 | do { | 455 | do { |
232 | seq = read_seqbegin_irqsave(&xtime_lock, flags); | 456 | seq = read_seqbegin_irqsave(&xtime_lock, flags); |
233 | sec = xtime.tv_sec; | 457 | sec = xtime.tv_sec; |
234 | nsec = xtime.tv_nsec + tb_ticks_since(tb_last_stamp); | 458 | nsec = xtime.tv_nsec + tb_ticks_since(tb_last_stamp); |
235 | lost = jiffies - wall_jiffies; | ||
236 | } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); | 459 | } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); |
237 | usec = nsec / 1000 + lost * (1000000 / HZ); | 460 | usec = nsec / 1000; |
238 | while (usec >= 1000000) { | 461 | while (usec >= 1000000) { |
239 | usec -= 1000000; | 462 | usec -= 1000000; |
240 | ++sec; | 463 | ++sec; |
@@ -248,23 +471,6 @@ void do_gettimeofday(struct timeval *tv) | |||
248 | 471 | ||
249 | EXPORT_SYMBOL(do_gettimeofday); | 472 | EXPORT_SYMBOL(do_gettimeofday); |
250 | 473 | ||
251 | /* Synchronize xtime with do_gettimeofday */ | ||
252 | |||
253 | static inline void timer_sync_xtime(unsigned long cur_tb) | ||
254 | { | ||
255 | #ifdef CONFIG_PPC64 | ||
256 | /* why do we do this? */ | ||
257 | struct timeval my_tv; | ||
258 | |||
259 | __do_gettimeofday(&my_tv, cur_tb); | ||
260 | |||
261 | if (xtime.tv_sec <= my_tv.tv_sec) { | ||
262 | xtime.tv_sec = my_tv.tv_sec; | ||
263 | xtime.tv_nsec = my_tv.tv_usec * 1000; | ||
264 | } | ||
265 | #endif | ||
266 | } | ||
267 | |||
268 | /* | 474 | /* |
269 | * There are two copies of tb_to_xs and stamp_xsec so that no | 475 | * There are two copies of tb_to_xs and stamp_xsec so that no |
270 | * lock is needed to access and use these values in | 476 | * lock is needed to access and use these values in |
@@ -323,15 +529,30 @@ static __inline__ void timer_recalc_offset(u64 cur_tb) | |||
323 | { | 529 | { |
324 | unsigned long offset; | 530 | unsigned long offset; |
325 | u64 new_stamp_xsec; | 531 | u64 new_stamp_xsec; |
532 | u64 tlen, t2x; | ||
326 | 533 | ||
327 | if (__USE_RTC()) | 534 | if (__USE_RTC()) |
328 | return; | 535 | return; |
536 | tlen = current_tick_length(); | ||
329 | offset = cur_tb - do_gtod.varp->tb_orig_stamp; | 537 | offset = cur_tb - do_gtod.varp->tb_orig_stamp; |
330 | if ((offset & 0x80000000u) == 0) | 538 | if (tlen == last_tick_len && offset < 0x80000000u) { |
331 | return; | 539 | /* check that we're still in sync; if not, resync */ |
332 | new_stamp_xsec = do_gtod.varp->stamp_xsec | 540 | struct timeval tv; |
333 | + mulhdu(offset, do_gtod.varp->tb_to_xs); | 541 | __do_gettimeofday(&tv, cur_tb); |
334 | update_gtod(cur_tb, new_stamp_xsec, do_gtod.varp->tb_to_xs); | 542 | if (tv.tv_sec <= xtime.tv_sec && |
543 | (tv.tv_sec < xtime.tv_sec || | ||
544 | tv.tv_usec * 1000 <= xtime.tv_nsec)) | ||
545 | return; | ||
546 | } | ||
547 | if (tlen != last_tick_len) { | ||
548 | t2x = mulhdu(tlen << TICKLEN_SHIFT, ticklen_to_xs); | ||
549 | last_tick_len = tlen; | ||
550 | } else | ||
551 | t2x = do_gtod.varp->tb_to_xs; | ||
552 | new_stamp_xsec = (u64) xtime.tv_nsec * XSEC_PER_SEC; | ||
553 | do_div(new_stamp_xsec, 1000000000); | ||
554 | new_stamp_xsec += (u64) xtime.tv_sec * XSEC_PER_SEC; | ||
555 | update_gtod(cur_tb, new_stamp_xsec, t2x); | ||
335 | } | 556 | } |
336 | 557 | ||
337 | #ifdef CONFIG_SMP | 558 | #ifdef CONFIG_SMP |
@@ -381,6 +602,7 @@ static void iSeries_tb_recal(void) | |||
381 | new_tb_ticks_per_jiffy, sign, tick_diff ); | 602 | new_tb_ticks_per_jiffy, sign, tick_diff ); |
382 | tb_ticks_per_jiffy = new_tb_ticks_per_jiffy; | 603 | tb_ticks_per_jiffy = new_tb_ticks_per_jiffy; |
383 | tb_ticks_per_sec = new_tb_ticks_per_sec; | 604 | tb_ticks_per_sec = new_tb_ticks_per_sec; |
605 | calc_cputime_factors(); | ||
384 | div128_by_32( XSEC_PER_SEC, 0, tb_ticks_per_sec, &divres ); | 606 | div128_by_32( XSEC_PER_SEC, 0, tb_ticks_per_sec, &divres ); |
385 | do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; | 607 | do_gtod.tb_ticks_per_sec = tb_ticks_per_sec; |
386 | tb_to_xs = divres.result_low; | 608 | tb_to_xs = divres.result_low; |
@@ -429,6 +651,7 @@ void timer_interrupt(struct pt_regs * regs) | |||
429 | irq_enter(); | 651 | irq_enter(); |
430 | 652 | ||
431 | profile_tick(CPU_PROFILING, regs); | 653 | profile_tick(CPU_PROFILING, regs); |
654 | calculate_steal_time(); | ||
432 | 655 | ||
433 | #ifdef CONFIG_PPC_ISERIES | 656 | #ifdef CONFIG_PPC_ISERIES |
434 | get_lppaca()->int_dword.fields.decr_int = 0; | 657 | get_lppaca()->int_dword.fields.decr_int = 0; |
@@ -450,7 +673,7 @@ void timer_interrupt(struct pt_regs * regs) | |||
450 | * is the case. | 673 | * is the case. |
451 | */ | 674 | */ |
452 | if (!cpu_is_offline(cpu)) | 675 | if (!cpu_is_offline(cpu)) |
453 | update_process_times(user_mode(regs)); | 676 | account_process_time(regs); |
454 | 677 | ||
455 | /* | 678 | /* |
456 | * No need to check whether cpu is offline here; boot_cpuid | 679 | * No need to check whether cpu is offline here; boot_cpuid |
@@ -462,13 +685,10 @@ void timer_interrupt(struct pt_regs * regs) | |||
462 | write_seqlock(&xtime_lock); | 685 | write_seqlock(&xtime_lock); |
463 | tb_last_jiffy += tb_ticks_per_jiffy; | 686 | tb_last_jiffy += tb_ticks_per_jiffy; |
464 | tb_last_stamp = per_cpu(last_jiffy, cpu); | 687 | tb_last_stamp = per_cpu(last_jiffy, cpu); |
465 | timer_recalc_offset(tb_last_jiffy); | ||
466 | do_timer(regs); | 688 | do_timer(regs); |
467 | timer_sync_xtime(tb_last_jiffy); | 689 | timer_recalc_offset(tb_last_jiffy); |
468 | timer_check_rtc(); | 690 | timer_check_rtc(); |
469 | write_sequnlock(&xtime_lock); | 691 | write_sequnlock(&xtime_lock); |
470 | if (adjusting_time && (time_adjust == 0)) | ||
471 | ppc_adjtimex(); | ||
472 | } | 692 | } |
473 | 693 | ||
474 | next_dec = tb_ticks_per_jiffy - ticks; | 694 | next_dec = tb_ticks_per_jiffy - ticks; |
@@ -492,29 +712,45 @@ void timer_interrupt(struct pt_regs * regs) | |||
492 | 712 | ||
493 | void wakeup_decrementer(void) | 713 | void wakeup_decrementer(void) |
494 | { | 714 | { |
495 | int i; | 715 | unsigned long ticks; |
496 | 716 | ||
497 | set_dec(tb_ticks_per_jiffy); | ||
498 | /* | 717 | /* |
499 | * We don't expect this to be called on a machine with a 601, | 718 | * The timebase gets saved on sleep and restored on wakeup, |
500 | * so using get_tbl is fine. | 719 | * so all we need to do is to reset the decrementer. |
501 | */ | 720 | */ |
502 | tb_last_stamp = tb_last_jiffy = get_tb(); | 721 | ticks = tb_ticks_since(__get_cpu_var(last_jiffy)); |
503 | for_each_cpu(i) | 722 | if (ticks < tb_ticks_per_jiffy) |
504 | per_cpu(last_jiffy, i) = tb_last_stamp; | 723 | ticks = tb_ticks_per_jiffy - ticks; |
724 | else | ||
725 | ticks = 1; | ||
726 | set_dec(ticks); | ||
505 | } | 727 | } |
506 | 728 | ||
507 | #ifdef CONFIG_SMP | 729 | #ifdef CONFIG_SMP |
508 | void __init smp_space_timers(unsigned int max_cpus) | 730 | void __init smp_space_timers(unsigned int max_cpus) |
509 | { | 731 | { |
510 | int i; | 732 | int i; |
733 | unsigned long half = tb_ticks_per_jiffy / 2; | ||
511 | unsigned long offset = tb_ticks_per_jiffy / max_cpus; | 734 | unsigned long offset = tb_ticks_per_jiffy / max_cpus; |
512 | unsigned long previous_tb = per_cpu(last_jiffy, boot_cpuid); | 735 | unsigned long previous_tb = per_cpu(last_jiffy, boot_cpuid); |
513 | 736 | ||
514 | /* make sure tb > per_cpu(last_jiffy, cpu) for all cpus always */ | 737 | /* make sure tb > per_cpu(last_jiffy, cpu) for all cpus always */ |
515 | previous_tb -= tb_ticks_per_jiffy; | 738 | previous_tb -= tb_ticks_per_jiffy; |
739 | /* | ||
740 | * The stolen time calculation for POWER5 shared-processor LPAR | ||
741 | * systems works better if the two threads' timebase interrupts | ||
742 | * are staggered by half a jiffy with respect to each other. | ||
743 | */ | ||
516 | for_each_cpu(i) { | 744 | for_each_cpu(i) { |
517 | if (i != boot_cpuid) { | 745 | if (i == boot_cpuid) |
746 | continue; | ||
747 | if (i == (boot_cpuid ^ 1)) | ||
748 | per_cpu(last_jiffy, i) = | ||
749 | per_cpu(last_jiffy, boot_cpuid) - half; | ||
750 | else if (i & 1) | ||
751 | per_cpu(last_jiffy, i) = | ||
752 | per_cpu(last_jiffy, i ^ 1) + half; | ||
753 | else { | ||
518 | previous_tb += offset; | 754 | previous_tb += offset; |
519 | per_cpu(last_jiffy, i) = previous_tb; | 755 | per_cpu(last_jiffy, i) = previous_tb; |
520 | } | 756 | } |
@@ -541,8 +777,8 @@ int do_settimeofday(struct timespec *tv) | |||
541 | time_t wtm_sec, new_sec = tv->tv_sec; | 777 | time_t wtm_sec, new_sec = tv->tv_sec; |
542 | long wtm_nsec, new_nsec = tv->tv_nsec; | 778 | long wtm_nsec, new_nsec = tv->tv_nsec; |
543 | unsigned long flags; | 779 | unsigned long flags; |
544 | long int tb_delta; | 780 | u64 new_xsec; |
545 | u64 new_xsec, tb_delta_xs; | 781 | unsigned long tb_delta; |
546 | 782 | ||
547 | if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) | 783 | if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC) |
548 | return -EINVAL; | 784 | return -EINVAL; |
@@ -563,9 +799,19 @@ int do_settimeofday(struct timespec *tv) | |||
563 | first_settimeofday = 0; | 799 | first_settimeofday = 0; |
564 | } | 800 | } |
565 | #endif | 801 | #endif |
802 | |||
803 | /* | ||
804 | * Subtract off the number of nanoseconds since the | ||
805 | * beginning of the last tick. | ||
806 | * Note that since we don't increment jiffies_64 anywhere other | ||
807 | * than in do_timer (since we don't have a lost tick problem), | ||
808 | * wall_jiffies will always be the same as jiffies, | ||
809 | * and therefore the (jiffies - wall_jiffies) computation | ||
810 | * has been removed. | ||
811 | */ | ||
566 | tb_delta = tb_ticks_since(tb_last_stamp); | 812 | tb_delta = tb_ticks_since(tb_last_stamp); |
567 | tb_delta += (jiffies - wall_jiffies) * tb_ticks_per_jiffy; | 813 | tb_delta = mulhdu(tb_delta, do_gtod.varp->tb_to_xs); /* in xsec */ |
568 | tb_delta_xs = mulhdu(tb_delta, do_gtod.varp->tb_to_xs); | 814 | new_nsec -= SCALE_XSEC(tb_delta, 1000000000); |
569 | 815 | ||
570 | wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - new_sec); | 816 | wtm_sec = wall_to_monotonic.tv_sec + (xtime.tv_sec - new_sec); |
571 | wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - new_nsec); | 817 | wtm_nsec = wall_to_monotonic.tv_nsec + (xtime.tv_nsec - new_nsec); |
@@ -580,12 +826,12 @@ int do_settimeofday(struct timespec *tv) | |||
580 | 826 | ||
581 | ntp_clear(); | 827 | ntp_clear(); |
582 | 828 | ||
583 | new_xsec = 0; | 829 | new_xsec = xtime.tv_nsec; |
584 | if (new_nsec != 0) { | 830 | if (new_xsec != 0) { |
585 | new_xsec = (u64)new_nsec * XSEC_PER_SEC; | 831 | new_xsec *= XSEC_PER_SEC; |
586 | do_div(new_xsec, NSEC_PER_SEC); | 832 | do_div(new_xsec, NSEC_PER_SEC); |
587 | } | 833 | } |
588 | new_xsec += (u64)new_sec * XSEC_PER_SEC - tb_delta_xs; | 834 | new_xsec += (u64)xtime.tv_sec * XSEC_PER_SEC; |
589 | update_gtod(tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs); | 835 | update_gtod(tb_last_jiffy, new_xsec, do_gtod.varp->tb_to_xs); |
590 | 836 | ||
591 | vdso_data->tz_minuteswest = sys_tz.tz_minuteswest; | 837 | vdso_data->tz_minuteswest = sys_tz.tz_minuteswest; |
@@ -671,7 +917,7 @@ void __init time_init(void) | |||
671 | unsigned long flags; | 917 | unsigned long flags; |
672 | unsigned long tm = 0; | 918 | unsigned long tm = 0; |
673 | struct div_result res; | 919 | struct div_result res; |
674 | u64 scale; | 920 | u64 scale, x; |
675 | unsigned shift; | 921 | unsigned shift; |
676 | 922 | ||
677 | if (ppc_md.time_init != NULL) | 923 | if (ppc_md.time_init != NULL) |
@@ -693,11 +939,37 @@ void __init time_init(void) | |||
693 | } | 939 | } |
694 | 940 | ||
695 | tb_ticks_per_jiffy = ppc_tb_freq / HZ; | 941 | tb_ticks_per_jiffy = ppc_tb_freq / HZ; |
696 | tb_ticks_per_sec = tb_ticks_per_jiffy * HZ; | 942 | tb_ticks_per_sec = ppc_tb_freq; |
697 | tb_ticks_per_usec = ppc_tb_freq / 1000000; | 943 | tb_ticks_per_usec = ppc_tb_freq / 1000000; |
698 | tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000); | 944 | tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000); |
699 | div128_by_32(1024*1024, 0, tb_ticks_per_sec, &res); | 945 | calc_cputime_factors(); |
700 | tb_to_xs = res.result_low; | 946 | |
947 | /* | ||
948 | * Calculate the length of each tick in ns. It will not be | ||
949 | * exactly 1e9/HZ unless ppc_tb_freq is divisible by HZ. | ||
950 | * We compute 1e9 * tb_ticks_per_jiffy / ppc_tb_freq, | ||
951 | * rounded up. | ||
952 | */ | ||
953 | x = (u64) NSEC_PER_SEC * tb_ticks_per_jiffy + ppc_tb_freq - 1; | ||
954 | do_div(x, ppc_tb_freq); | ||
955 | tick_nsec = x; | ||
956 | last_tick_len = x << TICKLEN_SCALE; | ||
957 | |||
958 | /* | ||
959 | * Compute ticklen_to_xs, which is a factor which gets multiplied | ||
960 | * by (last_tick_len << TICKLEN_SHIFT) to get a tb_to_xs value. | ||
961 | * It is computed as: | ||
962 | * ticklen_to_xs = 2^N / (tb_ticks_per_jiffy * 1e9) | ||
963 | * where N = 64 + 20 - TICKLEN_SCALE - TICKLEN_SHIFT | ||
964 | * so as to give the result as a 0.64 fixed-point fraction. | ||
965 | */ | ||
966 | div128_by_32(1ULL << (64 + 20 - TICKLEN_SCALE - TICKLEN_SHIFT), 0, | ||
967 | tb_ticks_per_jiffy, &res); | ||
968 | div128_by_32(res.result_high, res.result_low, NSEC_PER_SEC, &res); | ||
969 | ticklen_to_xs = res.result_low; | ||
970 | |||
971 | /* Compute tb_to_xs from tick_nsec */ | ||
972 | tb_to_xs = mulhdu(last_tick_len << TICKLEN_SHIFT, ticklen_to_xs); | ||
701 | 973 | ||
702 | /* | 974 | /* |
703 | * Compute scale factor for sched_clock. | 975 | * Compute scale factor for sched_clock. |
@@ -724,6 +996,14 @@ void __init time_init(void) | |||
724 | tm = get_boot_time(); | 996 | tm = get_boot_time(); |
725 | 997 | ||
726 | write_seqlock_irqsave(&xtime_lock, flags); | 998 | write_seqlock_irqsave(&xtime_lock, flags); |
999 | |||
1000 | /* If platform provided a timezone (pmac), we correct the time */ | ||
1001 | if (timezone_offset) { | ||
1002 | sys_tz.tz_minuteswest = -timezone_offset / 60; | ||
1003 | sys_tz.tz_dsttime = 0; | ||
1004 | tm -= timezone_offset; | ||
1005 | } | ||
1006 | |||
727 | xtime.tv_sec = tm; | 1007 | xtime.tv_sec = tm; |
728 | xtime.tv_nsec = 0; | 1008 | xtime.tv_nsec = 0; |
729 | do_gtod.varp = &do_gtod.vars[0]; | 1009 | do_gtod.varp = &do_gtod.vars[0]; |
@@ -738,18 +1018,11 @@ void __init time_init(void) | |||
738 | vdso_data->tb_orig_stamp = tb_last_jiffy; | 1018 | vdso_data->tb_orig_stamp = tb_last_jiffy; |
739 | vdso_data->tb_update_count = 0; | 1019 | vdso_data->tb_update_count = 0; |
740 | vdso_data->tb_ticks_per_sec = tb_ticks_per_sec; | 1020 | vdso_data->tb_ticks_per_sec = tb_ticks_per_sec; |
741 | vdso_data->stamp_xsec = xtime.tv_sec * XSEC_PER_SEC; | 1021 | vdso_data->stamp_xsec = (u64) xtime.tv_sec * XSEC_PER_SEC; |
742 | vdso_data->tb_to_xs = tb_to_xs; | 1022 | vdso_data->tb_to_xs = tb_to_xs; |
743 | 1023 | ||
744 | time_freq = 0; | 1024 | time_freq = 0; |
745 | 1025 | ||
746 | /* If platform provided a timezone (pmac), we correct the time */ | ||
747 | if (timezone_offset) { | ||
748 | sys_tz.tz_minuteswest = -timezone_offset / 60; | ||
749 | sys_tz.tz_dsttime = 0; | ||
750 | xtime.tv_sec -= timezone_offset; | ||
751 | } | ||
752 | |||
753 | last_rtc_update = xtime.tv_sec; | 1026 | last_rtc_update = xtime.tv_sec; |
754 | set_normalized_timespec(&wall_to_monotonic, | 1027 | set_normalized_timespec(&wall_to_monotonic, |
755 | -xtime.tv_sec, -xtime.tv_nsec); | 1028 | -xtime.tv_sec, -xtime.tv_nsec); |
@@ -759,126 +1032,6 @@ void __init time_init(void) | |||
759 | set_dec(tb_ticks_per_jiffy); | 1032 | set_dec(tb_ticks_per_jiffy); |
760 | } | 1033 | } |
761 | 1034 | ||
762 | /* | ||
763 | * After adjtimex is called, adjust the conversion of tb ticks | ||
764 | * to microseconds to keep do_gettimeofday synchronized | ||
765 | * with ntpd. | ||
766 | * | ||
767 | * Use the time_adjust, time_freq and time_offset computed by adjtimex to | ||
768 | * adjust the frequency. | ||
769 | */ | ||
770 | |||
771 | /* #define DEBUG_PPC_ADJTIMEX 1 */ | ||
772 | |||
773 | void ppc_adjtimex(void) | ||
774 | { | ||
775 | #ifdef CONFIG_PPC64 | ||
776 | unsigned long den, new_tb_ticks_per_sec, tb_ticks, old_xsec, | ||
777 | new_tb_to_xs, new_xsec, new_stamp_xsec; | ||
778 | unsigned long tb_ticks_per_sec_delta; | ||
779 | long delta_freq, ltemp; | ||
780 | struct div_result divres; | ||
781 | unsigned long flags; | ||
782 | long singleshot_ppm = 0; | ||
783 | |||
784 | /* | ||
785 | * Compute parts per million frequency adjustment to | ||
786 | * accomplish the time adjustment implied by time_offset to be | ||
787 | * applied over the elapsed time indicated by time_constant. | ||
788 | * Use SHIFT_USEC to get it into the same units as | ||
789 | * time_freq. | ||
790 | */ | ||
791 | if ( time_offset < 0 ) { | ||
792 | ltemp = -time_offset; | ||
793 | ltemp <<= SHIFT_USEC - SHIFT_UPDATE; | ||
794 | ltemp >>= SHIFT_KG + time_constant; | ||
795 | ltemp = -ltemp; | ||
796 | } else { | ||
797 | ltemp = time_offset; | ||
798 | ltemp <<= SHIFT_USEC - SHIFT_UPDATE; | ||
799 | ltemp >>= SHIFT_KG + time_constant; | ||
800 | } | ||
801 | |||
802 | /* If there is a single shot time adjustment in progress */ | ||
803 | if ( time_adjust ) { | ||
804 | #ifdef DEBUG_PPC_ADJTIMEX | ||
805 | printk("ppc_adjtimex: "); | ||
806 | if ( adjusting_time == 0 ) | ||
807 | printk("starting "); | ||
808 | printk("single shot time_adjust = %ld\n", time_adjust); | ||
809 | #endif | ||
810 | |||
811 | adjusting_time = 1; | ||
812 | |||
813 | /* | ||
814 | * Compute parts per million frequency adjustment | ||
815 | * to match time_adjust | ||
816 | */ | ||
817 | singleshot_ppm = tickadj * HZ; | ||
818 | /* | ||
819 | * The adjustment should be tickadj*HZ to match the code in | ||
820 | * linux/kernel/timer.c, but experiments show that this is too | ||
821 | * large. 3/4 of tickadj*HZ seems about right | ||
822 | */ | ||
823 | singleshot_ppm -= singleshot_ppm / 4; | ||
824 | /* Use SHIFT_USEC to get it into the same units as time_freq */ | ||
825 | singleshot_ppm <<= SHIFT_USEC; | ||
826 | if ( time_adjust < 0 ) | ||
827 | singleshot_ppm = -singleshot_ppm; | ||
828 | } | ||
829 | else { | ||
830 | #ifdef DEBUG_PPC_ADJTIMEX | ||
831 | if ( adjusting_time ) | ||
832 | printk("ppc_adjtimex: ending single shot time_adjust\n"); | ||
833 | #endif | ||
834 | adjusting_time = 0; | ||
835 | } | ||
836 | |||
837 | /* Add up all of the frequency adjustments */ | ||
838 | delta_freq = time_freq + ltemp + singleshot_ppm; | ||
839 | |||
840 | /* | ||
841 | * Compute a new value for tb_ticks_per_sec based on | ||
842 | * the frequency adjustment | ||
843 | */ | ||
844 | den = 1000000 * (1 << (SHIFT_USEC - 8)); | ||
845 | if ( delta_freq < 0 ) { | ||
846 | tb_ticks_per_sec_delta = ( tb_ticks_per_sec * ( (-delta_freq) >> (SHIFT_USEC - 8))) / den; | ||
847 | new_tb_ticks_per_sec = tb_ticks_per_sec + tb_ticks_per_sec_delta; | ||
848 | } | ||
849 | else { | ||
850 | tb_ticks_per_sec_delta = ( tb_ticks_per_sec * ( delta_freq >> (SHIFT_USEC - 8))) / den; | ||
851 | new_tb_ticks_per_sec = tb_ticks_per_sec - tb_ticks_per_sec_delta; | ||
852 | } | ||
853 | |||
854 | #ifdef DEBUG_PPC_ADJTIMEX | ||
855 | printk("ppc_adjtimex: ltemp = %ld, time_freq = %ld, singleshot_ppm = %ld\n", ltemp, time_freq, singleshot_ppm); | ||
856 | printk("ppc_adjtimex: tb_ticks_per_sec - base = %ld new = %ld\n", tb_ticks_per_sec, new_tb_ticks_per_sec); | ||
857 | #endif | ||
858 | |||
859 | /* | ||
860 | * Compute a new value of tb_to_xs (used to convert tb to | ||
861 | * microseconds) and a new value of stamp_xsec which is the | ||
862 | * time (in 1/2^20 second units) corresponding to | ||
863 | * tb_orig_stamp. This new value of stamp_xsec compensates | ||
864 | * for the change in frequency (implied by the new tb_to_xs) | ||
865 | * which guarantees that the current time remains the same. | ||
866 | */ | ||
867 | write_seqlock_irqsave( &xtime_lock, flags ); | ||
868 | tb_ticks = get_tb() - do_gtod.varp->tb_orig_stamp; | ||
869 | div128_by_32(1024*1024, 0, new_tb_ticks_per_sec, &divres); | ||
870 | new_tb_to_xs = divres.result_low; | ||
871 | new_xsec = mulhdu(tb_ticks, new_tb_to_xs); | ||
872 | |||
873 | old_xsec = mulhdu(tb_ticks, do_gtod.varp->tb_to_xs); | ||
874 | new_stamp_xsec = do_gtod.varp->stamp_xsec + old_xsec - new_xsec; | ||
875 | |||
876 | update_gtod(do_gtod.varp->tb_orig_stamp, new_stamp_xsec, new_tb_to_xs); | ||
877 | |||
878 | write_sequnlock_irqrestore( &xtime_lock, flags ); | ||
879 | #endif /* CONFIG_PPC64 */ | ||
880 | } | ||
881 | |||
882 | 1035 | ||
883 | #define FEBRUARY 2 | 1036 | #define FEBRUARY 2 |
884 | #define STARTOFTIME 1970 | 1037 | #define STARTOFTIME 1970 |
diff --git a/arch/powerpc/kernel/vdso64/gettimeofday.S b/arch/powerpc/kernel/vdso64/gettimeofday.S index ccaeda5136d1..4ee871f1cadb 100644 --- a/arch/powerpc/kernel/vdso64/gettimeofday.S +++ b/arch/powerpc/kernel/vdso64/gettimeofday.S | |||
@@ -225,9 +225,9 @@ V_FUNCTION_BEGIN(__do_get_xsec) | |||
225 | .cfi_startproc | 225 | .cfi_startproc |
226 | /* check for update count & load values */ | 226 | /* check for update count & load values */ |
227 | 1: ld r8,CFG_TB_UPDATE_COUNT(r3) | 227 | 1: ld r8,CFG_TB_UPDATE_COUNT(r3) |
228 | andi. r0,r4,1 /* pending update ? loop */ | 228 | andi. r0,r8,1 /* pending update ? loop */ |
229 | bne- 1b | 229 | bne- 1b |
230 | xor r0,r4,r4 /* create dependency */ | 230 | xor r0,r8,r8 /* create dependency */ |
231 | add r3,r3,r0 | 231 | add r3,r3,r0 |
232 | 232 | ||
233 | /* Get TB & offset it */ | 233 | /* Get TB & offset it */ |