diff options
author | Len Brown <len.brown@intel.com> | 2006-01-27 17:18:29 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2006-01-27 17:18:29 -0500 |
commit | 292dd876ee765c478b27c93cc51e93a558ed58bf (patch) | |
tree | 5b740e93253295baee2a9c414a6c66d03d44a9ef /arch/ppc/kernel | |
parent | d4ec6c7cc9a15a7a529719bc3b84f46812f9842e (diff) | |
parent | 9fdb62af92c741addbea15545f214a6e89460865 (diff) |
Pull release into acpica branch
Diffstat (limited to 'arch/ppc/kernel')
-rw-r--r-- | arch/ppc/kernel/Makefile | 5 | ||||
-rw-r--r-- | arch/ppc/kernel/asm-offsets.c | 2 | ||||
-rw-r--r-- | arch/ppc/kernel/entry.S | 167 | ||||
-rw-r--r-- | arch/ppc/kernel/head_8xx.S | 77 | ||||
-rw-r--r-- | arch/ppc/kernel/machine_kexec.c | 6 | ||||
-rw-r--r-- | arch/ppc/kernel/misc.S | 78 | ||||
-rw-r--r-- | arch/ppc/kernel/pci.c | 289 | ||||
-rw-r--r-- | arch/ppc/kernel/ppc_htab.c | 1 | ||||
-rw-r--r-- | arch/ppc/kernel/ppc_ksyms.c | 15 | ||||
-rw-r--r-- | arch/ppc/kernel/process.c | 851 | ||||
-rw-r--r-- | arch/ppc/kernel/setup.c | 35 | ||||
-rw-r--r-- | arch/ppc/kernel/smp.c | 4 | ||||
-rw-r--r-- | arch/ppc/kernel/traps.c | 13 |
13 files changed, 230 insertions, 1313 deletions
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index 0bb23fce4293..e399bbb969a4 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -9,16 +9,13 @@ extra-$(CONFIG_44x) := head_44x.o extra-$(CONFIG_FSL_BOOKE) := head_fsl_booke.o extra-$(CONFIG_8xx) := head_8xx.o extra-$(CONFIG_6xx) += idle_6xx.o -extra-$(CONFIG_POWER4) += idle_power4.o extra-y += vmlinux.lds obj-y := entry.o traps.o idle.o time.o misc.o \ - process.o \ setup.o \ ppc_htab.o obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o -obj-$(CONFIG_POWER4) += cpu_setup_power4.o obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-mapping.o obj-$(CONFIG_PCI) += pci.o @@ -43,11 +40,9 @@ obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_NOT_COHERENT_CACHE) += dma-mapping.o -obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_KGDB) += ppc-stub.o obj-$(CONFIG_TAU) += temp.o ifndef CONFIG_E200 obj-$(CONFIG_FSL_BOOKE) += perfmon_fsl_booke.o endif -obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o endif diff --git a/arch/ppc/kernel/asm-offsets.c b/arch/ppc/kernel/asm-offsets.c index fe0e767fb94e..7964bf660e92 100644 --- a/arch/ppc/kernel/asm-offsets.c +++ b/arch/ppc/kernel/asm-offsets.c @@ -131,7 +131,7 @@ main(void) DEFINE(CPU_SPEC_FEATURES, offsetof(struct cpu_spec, cpu_features)); DEFINE(CPU_SPEC_SETUP, offsetof(struct cpu_spec, cpu_setup)); - DEFINE(TI_SC_NOERR, offsetof(struct thread_info, syscall_noerror)); + DEFINE(TI_SIGFRAME, offsetof(struct thread_info, nvgprs_frame)); DEFINE(TI_TASK, offsetof(struct thread_info, task)); DEFINE(TI_EXECDOMAIN, offsetof(struct thread_info, exec_domain)); DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S index f044edbb454f..a48b950722a1 100644 --- a/arch/ppc/kernel/entry.S +++ b/arch/ppc/kernel/entry.S @@ -200,8 +200,6 @@ _GLOBAL(DoSyscall) bl do_show_syscall #endif /* SHOW_SYSCALLS */ rlwinm r10,r1,0,0,18 /* current_thread_info() */ - li r11,0 - stb r11,TI_SC_NOERR(r10) lwz r11,TI_FLAGS(r10) andi. r11,r11,_TIF_SYSCALL_T_OR_A bne- syscall_dotrace @@ -222,25 +220,21 @@ ret_from_syscall: bl do_show_syscall_exit #endif mr r6,r3 - li r11,-_LAST_ERRNO - cmplw 0,r3,r11 rlwinm r12,r1,0,0,18 /* current_thread_info() */ - blt+ 30f - lbz r11,TI_SC_NOERR(r12) - cmpwi r11,0 - bne 30f - neg r3,r3 - lwz r10,_CCR(r1) /* Set SO bit in CR */ - oris r10,r10,0x1000 - stw r10,_CCR(r1) - /* disable interrupts so current_thread_info()->flags can't change */ -30: LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */ + LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */ SYNC MTMSRD(r10) lwz r9,TI_FLAGS(r12) - andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED) + li r8,-_LAST_ERRNO + andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL) bne- syscall_exit_work + cmplw 0,r3,r8 + blt+ syscall_exit_cont + lwz r11,_CCR(r1) /* Load CR */ + neg r3,r3 + oris r11,r11,0x1000 /* Set SO bit in CR */ + stw r11,_CCR(r1) syscall_exit_cont: #if defined(CONFIG_4xx) || defined(CONFIG_BOOKE) /* If the process has its own DBCR0 value, load it up. The single @@ -292,46 +286,113 @@ syscall_dotrace: b syscall_dotrace_cont syscall_exit_work: - stw r6,RESULT(r1) /* Save result */ + andi. r0,r9,_TIF_RESTOREALL + bne- 2f + cmplw 0,r3,r8 + blt+ 1f + andi. r0,r9,_TIF_NOERROR + bne- 1f + lwz r11,_CCR(r1) /* Load CR */ + neg r3,r3 + oris r11,r11,0x1000 /* Set SO bit in CR */ + stw r11,_CCR(r1) + +1: stw r6,RESULT(r1) /* Save result */ stw r3,GPR3(r1) /* Update return value */ - andi. r0,r9,_TIF_SYSCALL_T_OR_A - beq 5f - ori r10,r10,MSR_EE - SYNC - MTMSRD(r10) /* re-enable interrupts */ +2: andi. r0,r9,(_TIF_PERSYSCALL_MASK) + beq 4f + + /* Clear per-syscall TIF flags if any are set, but _leave_ + _TIF_SAVE_NVGPRS set in r9 since we haven't dealt with that + yet. */ + + li r11,_TIF_PERSYSCALL_MASK + addi r12,r12,TI_FLAGS +3: lwarx r8,0,r12 + andc r8,r8,r11 +#ifdef CONFIG_IBM405_ERR77 + dcbt 0,r12 +#endif + stwcx. r8,0,r12 + bne- 3b + subi r12,r12,TI_FLAGS + +4: /* Anything which requires enabling interrupts? */ + andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_SAVE_NVGPRS) + beq 7f + + /* Save NVGPRS if they're not saved already */ lwz r4,TRAP(r1) andi. r4,r4,1 - beq 4f + beq 5f SAVE_NVGPRS(r1) li r4,0xc00 stw r4,TRAP(r1) -4: + + /* Re-enable interrupts */ +5: ori r10,r10,MSR_EE + SYNC + MTMSRD(r10) + + andi. r0,r9,_TIF_SAVE_NVGPRS + bne save_user_nvgprs + +save_user_nvgprs_cont: + andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP) + beq 7f + addi r3,r1,STACK_FRAME_OVERHEAD bl do_syscall_trace_leave REST_NVGPRS(r1) -2: - lwz r3,GPR3(r1) + +6: lwz r3,GPR3(r1) LOAD_MSR_KERNEL(r10,MSR_KERNEL) /* doesn't include MSR_EE */ SYNC MTMSRD(r10) /* disable interrupts again */ rlwinm r12,r1,0,0,18 /* current_thread_info() */ lwz r9,TI_FLAGS(r12) -5: +7: andi. r0,r9,_TIF_NEED_RESCHED - bne 1f + bne 8f lwz r5,_MSR(r1) andi. r5,r5,MSR_PR - beq syscall_exit_cont + beq ret_from_except andi. r0,r9,_TIF_SIGPENDING - beq syscall_exit_cont + beq ret_from_except b do_user_signal -1: +8: ori r10,r10,MSR_EE SYNC MTMSRD(r10) /* re-enable interrupts */ bl schedule - b 2b + b 6b + +save_user_nvgprs: + lwz r8,TI_SIGFRAME(r12) + +.macro savewords start, end + 1: stw \start,4*(\start)(r8) + .section __ex_table,"a" + .align 2 + .long 1b,save_user_nvgprs_fault + .previous + .if \end - \start + savewords "(\start+1)",\end + .endif +.endm + savewords 14,31 + b save_user_nvgprs_cont + + +save_user_nvgprs_fault: + li r3,11 /* SIGSEGV */ + lwz r4,TI_TASK(r12) + bl force_sigsegv + rlwinm r12,r1,0,0,18 /* current_thread_info() */ + lwz r9,TI_FLAGS(r12) + b save_user_nvgprs_cont + #ifdef SHOW_SYSCALLS do_show_syscall: #ifdef SHOW_SYSCALLS_TASK @@ -401,28 +462,10 @@ show_syscalls_task: #endif /* SHOW_SYSCALLS */ /* - * The sigsuspend and rt_sigsuspend system calls can call do_signal - * and thus put the process into the stopped state where we might - * want to examine its user state with ptrace. Therefore we need - * to save all the nonvolatile registers (r13 - r31) before calling - * the C code. + * The fork/clone functions need to copy the full register set into + * the child process. Therefore we need to save all the nonvolatile + * registers (r13 - r31) before calling the C code. */ - .globl ppc_sigsuspend -ppc_sigsuspend: - SAVE_NVGPRS(r1) - lwz r0,TRAP(r1) - rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */ - stw r0,TRAP(r1) /* register set saved */ - b sys_sigsuspend - - .globl ppc_rt_sigsuspend -ppc_rt_sigsuspend: - SAVE_NVGPRS(r1) - lwz r0,TRAP(r1) - rlwinm r0,r0,0,0,30 - stw r0,TRAP(r1) - b sys_rt_sigsuspend - .globl ppc_fork ppc_fork: SAVE_NVGPRS(r1) @@ -447,14 +490,6 @@ ppc_clone: stw r0,TRAP(r1) /* register set saved */ b sys_clone - .globl ppc_swapcontext -ppc_swapcontext: - SAVE_NVGPRS(r1) - lwz r0,TRAP(r1) - rlwinm r0,r0,0,0,30 /* clear LSB to indicate full */ - stw r0,TRAP(r1) /* register set saved */ - b sys_swapcontext - /* * Top-level page fault handling. * This is in assembler because if do_page_fault tells us that @@ -626,16 +661,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_601) .long ret_from_except #endif - .globl sigreturn_exit -sigreturn_exit: - subi r1,r3,STACK_FRAME_OVERHEAD - rlwinm r12,r1,0,0,18 /* current_thread_info() */ - lwz r9,TI_FLAGS(r12) - andi. r0,r9,_TIF_SYSCALL_T_OR_A - beq+ ret_from_except_full - bl do_syscall_trace_leave - /* fall through */ - .globl ret_from_except_full ret_from_except_full: REST_NVGPRS(r1) @@ -658,7 +683,7 @@ user_exc_return: /* r10 contains MSR_KERNEL here */ /* Check current_thread_info()->flags */ rlwinm r9,r1,0,0,18 lwz r9,TI_FLAGS(r9) - andi. r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED) + andi. r0,r9,(_TIF_SIGPENDING|_TIF_NEED_RESCHED|_TIF_RESTOREALL) bne do_work restore_user: diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S index de0978742221..3e6ca7f5843f 100644 --- a/arch/ppc/kernel/head_8xx.S +++ b/arch/ppc/kernel/head_8xx.S @@ -375,6 +375,8 @@ DataStoreTLBMiss: lis r11, swapper_pg_dir@h ori r11, r11, swapper_pg_dir@l rlwimi r10, r11, 0, 2, 19 + stw r12, 16(r0) + b LoadLargeDTLB 3: lwz r11, 0(r10) /* Get the level 1 entry */ rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */ @@ -430,6 +432,81 @@ DataStoreTLBMiss: InstructionTLBError: b InstructionAccess +LoadLargeDTLB: + li r12, 0 + lwz r11, 0(r10) /* Get the level 1 entry */ + rlwinm. r10, r11,0,0,19 /* Extract page descriptor page address */ + beq 3f /* If zero, don't try to find a pte */ + + /* We have a pte table, so load fetch the pte from the table. + */ + ori r11, r11, 1 /* Set valid bit in physical L2 page */ + DO_8xx_CPU6(0x3b80, r3) + mtspr SPRN_MD_TWC, r11 /* Load pte table base address */ + mfspr r10, SPRN_MD_TWC /* ....and get the pte address */ + lwz r10, 0(r10) /* Get the pte */ + + /* Insert the Guarded flag into the TWC from the Linux PTE. + * It is bit 27 of both the Linux PTE and the TWC (at least + * I got that right :-). It will be better when we can put + * this into the Linux pgd/pmd and load it in the operation + * above. + */ + rlwimi r11, r10, 0, 27, 27 + + rlwimi r12, r10, 0, 0, 9 /* extract phys. addr */ + mfspr r3, SPRN_MD_EPN + rlwinm r3, r3, 0, 0, 9 /* extract virtual address */ + tophys(r3, r3) + cmpw r3, r12 /* only use 8M page if it is a direct + kernel mapping */ + bne 1f + ori r11, r11, MD_PS8MEG + li r12, 1 + b 2f +1: + li r12, 0 /* can't use 8MB TLB, so zero r12. */ +2: + DO_8xx_CPU6(0x3b80, r3) + mtspr SPRN_MD_TWC, r11 + + /* The Linux PTE won't go exactly into the MMU TLB. + * Software indicator bits 21, 22 and 28 must be clear. + * Software indicator bits 24, 25, 26, and 27 must be + * set. All other Linux PTE bits control the behavior + * of the MMU. + */ +3: li r11, 0x00f0 + rlwimi r10, r11, 0, 24, 28 /* Set 24-27, clear 28 */ + cmpwi r12, 1 + bne 4f + ori r10, r10, 0x8 + + mfspr r12, SPRN_MD_EPN + lis r3, 0xff80 /* 10-19 must be clear for 8MB TLB */ + ori r3, r3, 0x0fff + and r12, r3, r12 + DO_8xx_CPU6(0x3780, r3) + mtspr SPRN_MD_EPN, r12 + + lis r3, 0xff80 /* 10-19 must be clear for 8MB TLB */ + ori r3, r3, 0x0fff + and r10, r3, r10 +4: + DO_8xx_CPU6(0x3d80, r3) + mtspr SPRN_MD_RPN, r10 /* Update TLB entry */ + + mfspr r10, SPRN_M_TW /* Restore registers */ + lwz r11, 0(r0) + mtcr r11 + lwz r11, 4(r0) + + lwz r12, 16(r0) +#ifdef CONFIG_8xx_CPU6 + lwz r3, 8(r0) +#endif + rfi + /* This is the data TLB error on the MPC8xx. This could be due to * many reasons, including a dirty update to a pte. We can catch that * one here, but anything else is an error. First, we track down the diff --git a/arch/ppc/kernel/machine_kexec.c b/arch/ppc/kernel/machine_kexec.c index a882b0dbe8de..84d65a87191e 100644 --- a/arch/ppc/kernel/machine_kexec.c +++ b/arch/ppc/kernel/machine_kexec.c @@ -28,12 +28,6 @@ typedef NORET_TYPE void (*relocate_new_kernel_t)( const extern unsigned char relocate_new_kernel[]; const extern unsigned int relocate_new_kernel_size; -/* - * Provide a dummy crash_notes definition while crash dump arrives to ppc. - * This prevents breakage of crash_notes attribute in kernel/ksysfs.c. - */ -note_buf_t crash_notes[NR_CPUS]; - void machine_shutdown(void) { if (ppc_md.machine_shutdown) diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index 5e61124581d0..c3427eed8345 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S @@ -204,78 +204,6 @@ _GLOBAL(call_setup_cpu) mtctr r5 bctr -#if defined(CONFIG_CPU_FREQ_PMAC) && defined(CONFIG_6xx) - -/* This gets called by via-pmu.c to switch the PLL selection - * on 750fx CPU. This function should really be moved to some - * other place (as most of the cpufreq code in via-pmu - */ -_GLOBAL(low_choose_750fx_pll) - /* Clear MSR:EE */ - mfmsr r7 - rlwinm r0,r7,0,17,15 - mtmsr r0 - - /* If switching to PLL1, disable HID0:BTIC */ - cmplwi cr0,r3,0 - beq 1f - mfspr r5,SPRN_HID0 - rlwinm r5,r5,0,27,25 - sync - mtspr SPRN_HID0,r5 - isync - sync - -1: - /* Calc new HID1 value */ - mfspr r4,SPRN_HID1 /* Build a HID1:PS bit from parameter */ - rlwinm r5,r3,16,15,15 /* Clear out HID1:PS from value read */ - rlwinm r4,r4,0,16,14 /* Could have I used rlwimi here ? */ - or r4,r4,r5 - mtspr SPRN_HID1,r4 - - /* Store new HID1 image */ - rlwinm r6,r1,0,0,18 - lwz r6,TI_CPU(r6) - slwi r6,r6,2 - addis r6,r6,nap_save_hid1@ha - stw r4,nap_save_hid1@l(r6) - - /* If switching to PLL0, enable HID0:BTIC */ - cmplwi cr0,r3,0 - bne 1f - mfspr r5,SPRN_HID0 - ori r5,r5,HID0_BTIC - sync - mtspr SPRN_HID0,r5 - isync - sync - -1: - /* Return */ - mtmsr r7 - blr - -_GLOBAL(low_choose_7447a_dfs) - /* Clear MSR:EE */ - mfmsr r7 - rlwinm r0,r7,0,17,15 - mtmsr r0 - - /* Calc new HID1 value */ - mfspr r4,SPRN_HID1 - insrwi r4,r3,1,9 /* insert parameter into bit 9 */ - sync - mtspr SPRN_HID1,r4 - sync - isync - - /* Return */ - mtmsr r7 - blr - -#endif /* CONFIG_CPU_FREQ_PMAC && CONFIG_6xx */ - /* * complement mask on the msr then "or" some values on. * _nmask_and_or_msr(nmask, value_to_or) @@ -1197,7 +1125,7 @@ _GLOBAL(sys_call_table) .long sys_ssetmask .long sys_setreuid /* 70 */ .long sys_setregid - .long ppc_sigsuspend + .long sys_sigsuspend .long sys_sigpending .long sys_sethostname .long sys_setrlimit /* 75 */ @@ -1303,7 +1231,7 @@ _GLOBAL(sys_call_table) .long sys_rt_sigpending /* 175 */ .long sys_rt_sigtimedwait .long sys_rt_sigqueueinfo - .long ppc_rt_sigsuspend + .long sys_rt_sigsuspend .long sys_pread64 .long sys_pwrite64 /* 180 */ .long sys_chown @@ -1374,7 +1302,7 @@ _GLOBAL(sys_call_table) .long sys_clock_gettime .long sys_clock_getres .long sys_clock_nanosleep - .long ppc_swapcontext + .long sys_swapcontext .long sys_tgkill /* 250 */ .long sys_utimes .long sys_statfs64 diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c index f7fae5f153b2..04d04c5bfdd0 100644 --- a/arch/ppc/kernel/pci.c +++ b/arch/ppc/kernel/pci.c @@ -1,5 +1,5 @@ /* - * Common pmac/prep/chrp pci routines. -- Cort + * Common prep/chrp pci routines. -- Cort */ #include <linux/config.h> @@ -50,8 +50,7 @@ static void fixup_cpc710_pci64(struct pci_dev* dev); static u8* pci_to_OF_bus_map; #endif -/* By default, we don't re-assign bus numbers. We do this only on - * some pmacs +/* By default, we don't re-assign bus numbers. */ int pci_assign_all_buses; @@ -503,7 +502,7 @@ pcibios_allocate_resources(int pass) u16 command; struct resource *r; - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + for_each_pci_dev(dev) { pci_read_config_word(dev, PCI_COMMAND, &command); for (idx = 0; idx < 6; idx++) { r = &dev->resource[idx]; @@ -540,7 +539,7 @@ pcibios_assign_resources(void) int idx; struct resource *r; - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + for_each_pci_dev(dev) { int class = dev->class >> 8; /* Don't touch classless devices and host bridges */ @@ -780,17 +779,6 @@ pci_busdev_to_OF_node(struct pci_bus *bus, int devfn) return NULL; /* Fixup bus number according to what OF think it is. */ -#ifdef CONFIG_PPC_PMAC - /* The G5 need a special case here. Basically, we don't remap all - * busses on it so we don't create the pci-OF-map. However, we do - * remap the AGP bus and so have to deal with it. A future better - * fix has to be done by making the remapping per-host and always - * filling the pci_to_OF map. --BenH - */ - if (_machine == _MACH_Pmac && busnr >= 0xf0) - busnr -= 0xf0; - else -#endif if (pci_to_OF_bus_map) busnr = pci_to_OF_bus_map[busnr]; if (busnr == 0xff) @@ -815,8 +803,7 @@ EXPORT_SYMBOL(pci_device_to_OF_node); * to set pci_assign_all_buses to 1 and still use RTAS for PCI * config cycles. */ -struct pci_controller* -pci_find_hose_for_OF_device(struct device_node* node) +struct pci_controller* pci_find_hose_for_OF_device(struct device_node* node) { if (!have_of) return NULL; @@ -868,14 +855,15 @@ pci_device_from_OF_node(struct device_node* node, u8* bus, u8* devfn) */ if (!pci_to_OF_bus_map) return 0; - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - if (pci_to_OF_bus_map[dev->bus->number] != *bus) - continue; - if (dev->devfn != *devfn) - continue; - *bus = dev->bus->number; - return 0; - } + + for_each_pci_dev(dev) + if (pci_to_OF_bus_map[dev->bus->number] == *bus && + dev->devfn == *devfn) { + *bus = dev->bus->number; + pci_dev_put(dev); + return 0; + } + return -ENODEV; } EXPORT_SYMBOL(pci_device_from_OF_node); @@ -942,7 +930,7 @@ pci_process_bridge_OF_ranges(struct pci_controller *hose, while (ranges && (rlen -= np * sizeof(unsigned int)) >= 0) { res = NULL; size = ranges[na+4]; - switch (ranges[0] >> 24) { + switch ((ranges[0] >> 24) & 0x3) { case 1: /* I/O space */ if (ranges[2] != 0) break; @@ -956,6 +944,8 @@ pci_process_bridge_OF_ranges(struct pci_controller *hose, res = &hose->io_resource; res->flags = IORESOURCE_IO; res->start = ranges[2]; + DBG("PCI: IO 0x%lx -> 0x%lx\n", + res->start, res->start + size - 1); break; case 2: /* memory space */ memno = 0; @@ -973,7 +963,11 @@ pci_process_bridge_OF_ranges(struct pci_controller *hose, if (memno < 3) { res = &hose->mem_resources[memno]; res->flags = IORESOURCE_MEM; + if(ranges[0] & 0x40000000) + res->flags |= IORESOURCE_PREFETCH; res->start = ranges[na+2]; + DBG("PCI: MEM[%d] 0x%lx -> 0x%lx\n", memno, + res->start, res->start + size - 1); } break; } @@ -1034,216 +1028,6 @@ void pcibios_add_platform_entries(struct pci_dev *pdev) } -#ifdef CONFIG_PPC_PMAC -/* - * This set of routines checks for PCI<->PCI bridges that have closed - * IO resources and have child devices. It tries to re-open an IO - * window on them. - * - * This is a _temporary_ fix to workaround a problem with Apple's OF - * closing IO windows on P2P bridges when the OF drivers of cards - * below this bridge don't claim any IO range (typically ATI or - * Adaptec). - * - * A more complete fix would be to use drivers/pci/setup-bus.c, which - * involves a working pcibios_fixup_pbus_ranges(), some more care about - * ordering when creating the host bus resources, and maybe a few more - * minor tweaks - */ - -/* Initialize bridges with base/limit values we have collected */ -static void __init -do_update_p2p_io_resource(struct pci_bus *bus, int enable_vga) -{ - struct pci_dev *bridge = bus->self; - struct pci_controller* hose = (struct pci_controller *)bridge->sysdata; - u32 l; - u16 w; - struct resource res; - - if (bus->resource[0] == NULL) - return; - res = *(bus->resource[0]); - - DBG("Remapping Bus %d, bridge: %s\n", bus->number, pci_name(bridge)); - res.start -= ((unsigned long) hose->io_base_virt - isa_io_base); - res.end -= ((unsigned long) hose->io_base_virt - isa_io_base); - DBG(" IO window: %08lx-%08lx\n", res.start, res.end); - - /* Set up the top and bottom of the PCI I/O segment for this bus. */ - pci_read_config_dword(bridge, PCI_IO_BASE, &l); - l &= 0xffff000f; - l |= (res.start >> 8) & 0x00f0; - l |= res.end & 0xf000; - pci_write_config_dword(bridge, PCI_IO_BASE, l); - - if ((l & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) { - l = (res.start >> 16) | (res.end & 0xffff0000); - pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, l); - } - - pci_read_config_word(bridge, PCI_COMMAND, &w); - w |= PCI_COMMAND_IO; - pci_write_config_word(bridge, PCI_COMMAND, w); - -#if 0 /* Enabling this causes XFree 4.2.0 to hang during PCI probe */ - if (enable_vga) { - pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, &w); - w |= PCI_BRIDGE_CTL_VGA; - pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, w); - } -#endif -} - -/* This function is pretty basic and actually quite broken for the - * general case, it's enough for us right now though. It's supposed - * to tell us if we need to open an IO range at all or not and what - * size. - */ -static int __init -check_for_io_childs(struct pci_bus *bus, struct resource* res, int *found_vga) -{ - struct pci_dev *dev; - int i; - int rc = 0; - -#define push_end(res, size) do { unsigned long __sz = (size) ; \ - res->end = ((res->end + __sz) / (__sz + 1)) * (__sz + 1) + __sz; \ - } while (0) - - list_for_each_entry(dev, &bus->devices, bus_list) { - u16 class = dev->class >> 8; - - if (class == PCI_CLASS_DISPLAY_VGA || - class == PCI_CLASS_NOT_DEFINED_VGA) - *found_vga = 1; - if (class >> 8 == PCI_BASE_CLASS_BRIDGE && dev->subordinate) - rc |= check_for_io_childs(dev->subordinate, res, found_vga); - if (class == PCI_CLASS_BRIDGE_CARDBUS) - push_end(res, 0xfff); - - for (i=0; i<PCI_NUM_RESOURCES; i++) { - struct resource *r; - unsigned long r_size; - - if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI - && i >= PCI_BRIDGE_RESOURCES) - continue; - r = &dev->resource[i]; - r_size = r->end - r->start; - if (r_size < 0xfff) - r_size = 0xfff; - if (r->flags & IORESOURCE_IO && (r_size) != 0) { - rc = 1; - push_end(res, r_size); - } - } - } - - return rc; -} - -/* Here we scan all P2P bridges of a given level that have a closed - * IO window. Note that the test for the presence of a VGA card should - * be improved to take into account already configured P2P bridges, - * currently, we don't see them and might end up configuring 2 bridges - * with VGA pass through enabled - */ -static void __init -do_fixup_p2p_level(struct pci_bus *bus) -{ - struct pci_bus *b; - int i, parent_io; - int has_vga = 0; - - for (parent_io=0; parent_io<4; parent_io++) - if (bus->resource[parent_io] - && bus->resource[parent_io]->flags & IORESOURCE_IO) - break; - if (parent_io >= 4) - return; - - list_for_each_entry(b, &bus->children, node) { - struct pci_dev *d = b->self; - struct pci_controller* hose = (struct pci_controller *)d->sysdata; - struct resource *res = b->resource[0]; - struct resource tmp_res; - unsigned long max; - int found_vga = 0; - - memset(&tmp_res, 0, sizeof(tmp_res)); - tmp_res.start = bus->resource[parent_io]->start; - - /* We don't let low addresses go through that closed P2P bridge, well, - * that may not be necessary but I feel safer that way - */ - if (tmp_res.start == 0) - tmp_res.start = 0x1000; - - if (!list_empty(&b->devices) && res && res->flags == 0 && - res != bus->resource[parent_io] && - (d->class >> 8) == PCI_CLASS_BRIDGE_PCI && - check_for_io_childs(b, &tmp_res, &found_vga)) { - u8 io_base_lo; - - printk(KERN_INFO "Fixing up IO bus %s\n", b->name); - - if (found_vga) { - if (has_vga) { - printk(KERN_WARNING "Skipping VGA, already active" - " on bus segment\n"); - found_vga = 0; - } else - has_vga = 1; - } - pci_read_config_byte(d, PCI_IO_BASE, &io_base_lo); - - if ((io_base_lo & PCI_IO_RANGE_TYPE_MASK) == PCI_IO_RANGE_TYPE_32) - max = ((unsigned long) hose->io_base_virt - - isa_io_base) + 0xffffffff; - else - max = ((unsigned long) hose->io_base_virt - - isa_io_base) + 0xffff; - - *res = tmp_res; - res->flags = IORESOURCE_IO; - res->name = b->name; - - /* Find a resource in the parent where we can allocate */ - for (i = 0 ; i < 4; i++) { - struct resource *r = bus->resource[i]; - if (!r) - continue; - if ((r->flags & IORESOURCE_IO) == 0) - continue; - DBG("Trying to allocate from %08lx, size %08lx from parent" - " res %d: %08lx -> %08lx\n", - res->start, res->end, i, r->start, r->end); - - if (allocate_resource(r, res, res->end + 1, res->start, max, - res->end + 1, NULL, NULL) < 0) { - DBG("Failed !\n"); - continue; - } - do_update_p2p_io_resource(b, found_vga); - break; - } - } - do_fixup_p2p_level(b); - } -} - -static void -pcibios_fixup_p2p_bridges(void) -{ - struct pci_bus *b; - - list_for_each_entry(b, &pci_root_buses, node) - do_fixup_p2p_level(b); -} - -#endif /* CONFIG_PPC_PMAC */ - static int __init pcibios_init(void) { @@ -1284,9 +1068,6 @@ pcibios_init(void) pcibios_allocate_bus_resources(&pci_root_buses); pcibios_allocate_resources(0); pcibios_allocate_resources(1); -#ifdef CONFIG_PPC_PMAC - pcibios_fixup_p2p_bridges(); -#endif /* CONFIG_PPC_PMAC */ pcibios_assign_resources(); /* Call machine dependent post-init code */ @@ -1716,17 +1497,6 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn) struct pci_controller* hose; long result = -EOPNOTSUPP; - /* Argh ! Please forgive me for that hack, but that's the - * simplest way to get existing XFree to not lockup on some - * G5 machines... So when something asks for bus 0 io base - * (bus 0 is HT root), we return the AGP one instead. - */ -#ifdef CONFIG_PPC_PMAC - if (_machine == _MACH_Pmac && machine_is_compatible("MacRISC4")) - if (bus == 0) - bus = 0xf0; -#endif /* CONFIG_PPC_PMAC */ - hose = pci_bus_to_hose(bus); if (!hose) return -ENODEV; @@ -1806,6 +1576,23 @@ void pci_iounmap(struct pci_dev *dev, void __iomem *addr) EXPORT_SYMBOL(pci_iomap); EXPORT_SYMBOL(pci_iounmap); +unsigned long pci_address_to_pio(phys_addr_t address) +{ + struct pci_controller* hose = hose_head; + + for (; hose; hose = hose->next) { + unsigned int size = hose->io_resource.end - + hose->io_resource.start + 1; + if (address >= hose->io_base_phys && + address < (hose->io_base_phys + size)) { + unsigned long base = + (unsigned long)hose->io_base_virt - _IO_BASE; + return base + (address - hose->io_base_phys); + } + } + return (unsigned int)-1; +} +EXPORT_SYMBOL(pci_address_to_pio); /* * Null PCI config access functions, for the case when we can't diff --git a/arch/ppc/kernel/ppc_htab.c b/arch/ppc/kernel/ppc_htab.c index ca810025993f..2f5c7650274f 100644 --- a/arch/ppc/kernel/ppc_htab.c +++ b/arch/ppc/kernel/ppc_htab.c @@ -16,6 +16,7 @@ #include <linux/proc_fs.h> #include <linux/stat.h> #include <linux/sysctl.h> +#include <linux/capability.h> #include <linux/ctype.h> #include <linux/threads.h> #include <linux/smp_lock.h> diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index bb6a5c6a64be..3a6e4bcb3c53 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c @@ -34,7 +34,6 @@ #include <asm/system.h> #include <asm/pci-bridge.h> #include <asm/irq.h> -#include <asm/pmac_feature.h> #include <asm/dma.h> #include <asm/machdep.h> #include <asm/hw_irq.h> @@ -58,7 +57,6 @@ extern void machine_check_exception(struct pt_regs *regs); extern void alignment_exception(struct pt_regs *regs); extern void program_check_exception(struct pt_regs *regs); extern void single_step_exception(struct pt_regs *regs); -extern int pmac_newworld; extern int sys_sigreturn(struct pt_regs *regs); long long __ashrdi3(long long, int); @@ -82,10 +80,6 @@ EXPORT_SYMBOL(ppc_n_lost_interrupts); EXPORT_SYMBOL(ISA_DMA_THRESHOLD); EXPORT_SYMBOL(DMA_MODE_READ); EXPORT_SYMBOL(DMA_MODE_WRITE); -#if defined(CONFIG_PPC_PREP) -EXPORT_SYMBOL(_prep_type); -EXPORT_SYMBOL(ucSystemType); -#endif #if !defined(__INLINE_BITOPS) EXPORT_SYMBOL(set_bit); @@ -217,10 +211,6 @@ EXPORT_SYMBOL(adb_try_handler_change); EXPORT_SYMBOL(cuda_request); EXPORT_SYMBOL(cuda_poll); #endif /* CONFIG_ADB_CUDA */ -#ifdef CONFIG_PPC_PMAC -EXPORT_SYMBOL(sys_ctrler); -EXPORT_SYMBOL(pmac_newworld); -#endif #ifdef CONFIG_PPC_OF EXPORT_SYMBOL(find_devices); EXPORT_SYMBOL(find_type_devices); @@ -245,9 +235,6 @@ EXPORT_SYMBOL(of_node_put); #if defined(CONFIG_BOOTX_TEXT) EXPORT_SYMBOL(btext_update_display); #endif -#if defined(CONFIG_SCSI) && defined(CONFIG_PPC_PMAC) -EXPORT_SYMBOL(note_scsi_host); -#endif #ifdef CONFIG_VT EXPORT_SYMBOL(kd_mksound); #endif @@ -274,7 +261,6 @@ EXPORT_SYMBOL(__delay); EXPORT_SYMBOL(timer_interrupt); EXPORT_SYMBOL(irq_desc); EXPORT_SYMBOL(tb_ticks_per_jiffy); -EXPORT_SYMBOL(get_wchan); EXPORT_SYMBOL(console_drivers); #ifdef CONFIG_XMON EXPORT_SYMBOL(xmon); @@ -311,7 +297,6 @@ EXPORT_SYMBOL(__res); EXPORT_SYMBOL(next_mmu_context); EXPORT_SYMBOL(set_context); -EXPORT_SYMBOL_GPL(__handle_mm_fault); /* For MOL */ EXPORT_SYMBOL(disarm_decr); #ifdef CONFIG_PPC_STD_MMU extern long mol_trampoline; diff --git a/arch/ppc/kernel/process.c b/arch/ppc/kernel/process.c deleted file mode 100644 index 25cbdc8d2941..000000000000 --- a/arch/ppc/kernel/process.c +++ /dev/null @@ -1,851 +0,0 @@ -/* - * arch/ppc/kernel/process.c - * - * Derived from "arch/i386/kernel/process.c" - * Copyright (C) 1995 Linus Torvalds - * - * Updated and modified by Cort Dougan (cort@cs.nmt.edu) and - * Paul Mackerras (paulus@cs.anu.edu.au) - * - * PowerPC version - * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - */ - -#include <linux/config.h> -#include <linux/errno.h> -#include <linux/sched.h> -#include <linux/kernel.h> -#include <linux/mm.h> -#include <linux/smp.h> -#include <linux/smp_lock.h> -#include <linux/stddef.h> -#include <linux/unistd.h> -#include <linux/ptrace.h> -#include <linux/slab.h> -#include <linux/user.h> -#include <linux/elf.h> -#include <linux/init.h> -#include <linux/prctl.h> -#include <linux/init_task.h> -#include <linux/module.h> -#include <linux/kallsyms.h> -#include <linux/mqueue.h> -#include <linux/hardirq.h> - -#include <asm/pgtable.h> -#include <asm/uaccess.h> -#include <asm/system.h> -#include <asm/io.h> -#include <asm/processor.h> -#include <asm/mmu.h> -#include <asm/prom.h> - -extern unsigned long _get_SP(void); - -struct task_struct *last_task_used_math = NULL; -struct task_struct *last_task_used_altivec = NULL; -struct task_struct *last_task_used_spe = NULL; - -static struct fs_struct init_fs = INIT_FS; -static struct files_struct init_files = INIT_FILES; -static struct signal_struct init_signals = INIT_SIGNALS(init_signals); -static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); -struct mm_struct init_mm = INIT_MM(init_mm); -EXPORT_SYMBOL(init_mm); - -/* this is 8kB-aligned so we can get to the thread_info struct - at the base of it from the stack pointer with 1 integer instruction. */ -union thread_union init_thread_union - __attribute__((__section__(".data.init_task"))) = -{ INIT_THREAD_INFO(init_task) }; - -/* initial task structure */ -struct task_struct init_task = INIT_TASK(init_task); -EXPORT_SYMBOL(init_task); - -/* only used to get secondary processor up */ -struct task_struct *current_set[NR_CPUS] = {&init_task, }; - -#undef SHOW_TASK_SWITCHES -#undef CHECK_STACK - -#if defined(CHECK_STACK) -unsigned long -kernel_stack_top(struct task_struct *tsk) -{ - return ((unsigned long)tsk) + sizeof(union task_union); -} - -unsigned long -task_top(struct task_struct *tsk) -{ - return ((unsigned long)tsk) + sizeof(struct thread_info); -} - -/* check to make sure the kernel stack is healthy */ -int check_stack(struct task_struct *tsk) -{ - unsigned long stack_top = kernel_stack_top(tsk); - unsigned long tsk_top = task_top(tsk); - int ret = 0; - -#if 0 - /* check thread magic */ - if ( tsk->thread.magic != THREAD_MAGIC ) - { - ret |= 1; - printk("thread.magic bad: %08x\n", tsk->thread.magic); - } -#endif - - if ( !tsk ) - printk("check_stack(): tsk bad tsk %p\n",tsk); - - /* check if stored ksp is bad */ - if ( (tsk->thread.ksp > stack_top) || (tsk->thread.ksp < tsk_top) ) - { - printk("stack out of bounds: %s/%d\n" - " tsk_top %08lx ksp %08lx stack_top %08lx\n", - tsk->comm,tsk->pid, - tsk_top, tsk->thread.ksp, stack_top); - ret |= 2; - } - - /* check if stack ptr RIGHT NOW is bad */ - if ( (tsk == current) && ((_get_SP() > stack_top ) || (_get_SP() < tsk_top)) ) - { - printk("current stack ptr out of bounds: %s/%d\n" - " tsk_top %08lx sp %08lx stack_top %08lx\n", - current->comm,current->pid, - tsk_top, _get_SP(), stack_top); - ret |= 4; - } - -#if 0 - /* check amount of free stack */ - for ( i = (unsigned long *)task_top(tsk) ; i < kernel_stack_top(tsk) ; i++ ) - { - if ( !i ) - printk("check_stack(): i = %p\n", i); - if ( *i != 0 ) - { - /* only notify if it's less than 900 bytes */ - if ( (i - (unsigned long *)task_top(tsk)) < 900 ) - printk("%d bytes free on stack\n", - i - task_top(tsk)); - break; - } - } -#endif - - if (ret) - { - panic("bad kernel stack"); - } - return(ret); -} -#endif /* defined(CHECK_STACK) */ - -/* - * Make sure the floating-point register state in the - * the thread_struct is up to date for task tsk. - */ -void flush_fp_to_thread(struct task_struct *tsk) -{ - if (tsk->thread.regs) { - /* - * We need to disable preemption here because if we didn't, - * another process could get scheduled after the regs->msr - * test but before we have finished saving the FP registers - * to the thread_struct. That process could take over the - * FPU, and then when we get scheduled again we would store - * bogus values for the remaining FP registers. - */ - preempt_disable(); - if (tsk->thread.regs->msr & MSR_FP) { -#ifdef CONFIG_SMP - /* - * This should only ever be called for current or - * for a stopped child process. Since we save away - * the FP register state on context switch on SMP, - * there is something wrong if a stopped child appears - * to still have its FP state in the CPU registers. - */ - BUG_ON(tsk != current); -#endif - giveup_fpu(current); - } - preempt_enable(); - } -} - -void enable_kernel_fp(void) -{ - WARN_ON(preemptible()); - -#ifdef CONFIG_SMP - if (current->thread.regs && (current->thread.regs->msr & MSR_FP)) - giveup_fpu(current); - else - giveup_fpu(NULL); /* just enables FP for kernel */ -#else - giveup_fpu(last_task_used_math); -#endif /* CONFIG_SMP */ -} -EXPORT_SYMBOL(enable_kernel_fp); - -int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs) -{ - preempt_disable(); - if (tsk->thread.regs && (tsk->thread.regs->msr & MSR_FP)) - giveup_fpu(tsk); - preempt_enable(); - memcpy(fpregs, &tsk->thread.fpr[0], sizeof(*fpregs)); - return 1; -} - -#ifdef CONFIG_ALTIVEC -void enable_kernel_altivec(void) -{ - WARN_ON(preemptible()); - -#ifdef CONFIG_SMP - if (current->thread.regs && (current->thread.regs->msr & MSR_VEC)) - giveup_altivec(current); - else - giveup_altivec(NULL); /* just enable AltiVec for kernel - force */ -#else - giveup_altivec(last_task_used_altivec); -#endif /* __SMP __ */ -} -EXPORT_SYMBOL(enable_kernel_altivec); - -/* - * Make sure the VMX/Altivec register state in the - * the thread_struct is up to date for task tsk. - */ -void flush_altivec_to_thread(struct task_struct *tsk) -{ - if (tsk->thread.regs) { - preempt_disable(); - if (tsk->thread.regs->msr & MSR_VEC) { -#ifdef CONFIG_SMP - BUG_ON(tsk != current); -#endif - giveup_altivec(current); - } - preempt_enable(); - } -} - -int dump_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs) -{ - if (regs->msr & MSR_VEC) - giveup_altivec(current); - memcpy(vrregs, ¤t->thread.vr[0], sizeof(*vrregs)); - return 1; -} -#endif /* CONFIG_ALTIVEC */ - -#ifdef CONFIG_SPE -void -enable_kernel_spe(void) -{ - WARN_ON(preemptible()); - -#ifdef CONFIG_SMP - if (current->thread.regs && (current->thread.regs->msr & MSR_SPE)) - giveup_spe(current); - else - giveup_spe(NULL); /* just enable SPE for kernel - force */ -#else - giveup_spe(last_task_used_spe); -#endif /* __SMP __ */ -} -EXPORT_SYMBOL(enable_kernel_spe); - -void flush_spe_to_thread(struct task_struct *tsk) -{ - if (tsk->thread.regs) { - preempt_disable(); - if (tsk->thread.regs->msr & MSR_SPE) { -#ifdef CONFIG_SMP - BUG_ON(tsk != current); -#endif - giveup_spe(current); - } - preempt_enable(); - } -} - -int dump_spe(struct pt_regs *regs, elf_vrregset_t *evrregs) -{ - if (regs->msr & MSR_SPE) - giveup_spe(current); - /* We copy u32 evr[32] + u64 acc + u32 spefscr -> 35 */ - memcpy(evrregs, ¤t->thread.evr[0], sizeof(u32) * 35); - return 1; -} -#endif /* CONFIG_SPE */ - -struct task_struct *__switch_to(struct task_struct *prev, - struct task_struct *new) -{ - struct thread_struct *new_thread, *old_thread; - unsigned long s; - struct task_struct *last; - - local_irq_save(s); -#ifdef CHECK_STACK - check_stack(prev); - check_stack(new); -#endif - -#ifdef CONFIG_SMP - /* avoid complexity of lazy save/restore of fpu - * by just saving it every time we switch out if - * this task used the fpu during the last quantum. - * - * If it tries to use the fpu again, it'll trap and - * reload its fp regs. So we don't have to do a restore - * every switch, just a save. - * -- Cort - */ - if (prev->thread.regs && (prev->thread.regs->msr & MSR_FP)) - giveup_fpu(prev); -#ifdef CONFIG_ALTIVEC - /* - * If the previous thread used altivec in the last quantum - * (thus changing altivec regs) then save them. - * We used to check the VRSAVE register but not all apps - * set it, so we don't rely on it now (and in fact we need - * to save & restore VSCR even if VRSAVE == 0). -- paulus - * - * On SMP we always save/restore altivec regs just to avoid the - * complexity of changing processors. - * -- Cort - */ - if ((prev->thread.regs && (prev->thread.regs->msr & MSR_VEC))) - giveup_altivec(prev); -#endif /* CONFIG_ALTIVEC */ -#ifdef CONFIG_SPE - /* - * If the previous thread used spe in the last quantum - * (thus changing spe regs) then save them. - * - * On SMP we always save/restore spe regs just to avoid the - * complexity of changing processors. - */ - if ((prev->thread.regs && (prev->thread.regs->msr & MSR_SPE))) - giveup_spe(prev); -#endif /* CONFIG_SPE */ -#endif /* CONFIG_SMP */ - -#ifdef CONFIG_ALTIVEC - /* Avoid the trap. On smp this this never happens since - * we don't set last_task_used_altivec -- Cort - */ - if (new->thread.regs && last_task_used_altivec == new) - new->thread.regs->msr |= MSR_VEC; -#endif -#ifdef CONFIG_SPE - /* Avoid the trap. On smp this this never happens since - * we don't set last_task_used_spe - */ - if (new->thread.regs && last_task_used_spe == new) - new->thread.regs->msr |= MSR_SPE; -#endif /* CONFIG_SPE */ - new_thread = &new->thread; - old_thread = ¤t->thread; - last = _switch(old_thread, new_thread); - local_irq_restore(s); - return last; -} - -void show_regs(struct pt_regs * regs) -{ - int i, trap; - - printk("NIP: %08lX LR: %08lX SP: %08lX REGS: %p TRAP: %04lx %s\n", - regs->nip, regs->link, regs->gpr[1], regs, regs->trap, - print_tainted()); - printk("MSR: %08lx EE: %01x PR: %01x FP: %01x ME: %01x IR/DR: %01x%01x\n", - regs->msr, regs->msr&MSR_EE ? 1 : 0, regs->msr&MSR_PR ? 1 : 0, - regs->msr & MSR_FP ? 1 : 0,regs->msr&MSR_ME ? 1 : 0, - regs->msr&MSR_IR ? 1 : 0, - regs->msr&MSR_DR ? 1 : 0); - trap = TRAP(regs); - if (trap == 0x300 || trap == 0x600) - printk("DAR: %08lX, DSISR: %08lX\n", regs->dar, regs->dsisr); - printk("TASK = %p[%d] '%s' THREAD: %p\n", - current, current->pid, current->comm, current->thread_info); - printk("Last syscall: %ld ", current->thread.last_syscall); - -#ifdef CONFIG_SMP - printk(" CPU: %d", smp_processor_id()); -#endif /* CONFIG_SMP */ - - for (i = 0; i < 32; i++) { - long r; - if ((i % 8) == 0) - printk("\n" KERN_INFO "GPR%02d: ", i); - if (__get_user(r, ®s->gpr[i])) - break; - printk("%08lX ", r); - if (i == 12 && !FULL_REGS(regs)) - break; - } - printk("\n"); -#ifdef CONFIG_KALLSYMS - /* - * Lookup NIP late so we have the best change of getting the - * above info out without failing - */ - printk("NIP [%08lx] ", regs->nip); - print_symbol("%s\n", regs->nip); - printk("LR [%08lx] ", regs->link); - print_symbol("%s\n", regs->link); -#endif - show_stack(current, (unsigned long *) regs->gpr[1]); -} - -void exit_thread(void) -{ - preempt_disable(); - if (last_task_used_math == current) - last_task_used_math = NULL; - if (last_task_used_altivec == current) - last_task_used_altivec = NULL; -#ifdef CONFIG_SPE - if (last_task_used_spe == current) - last_task_used_spe = NULL; -#endif - preempt_enable(); -} - -void flush_thread(void) -{ - preempt_disable(); - if (last_task_used_math == current) - last_task_used_math = NULL; - if (last_task_used_altivec == current) - last_task_used_altivec = NULL; -#ifdef CONFIG_SPE - if (last_task_used_spe == current) - last_task_used_spe = NULL; -#endif - preempt_enable(); -} - -void -release_thread(struct task_struct *t) -{ -} - -/* - * This gets called before we allocate a new thread and copy - * the current task into it. - */ -void prepare_to_copy(struct task_struct *tsk) -{ - struct pt_regs *regs = tsk->thread.regs; - - if (regs == NULL) - return; - preempt_disable(); - if (regs->msr & MSR_FP) - giveup_fpu(current); -#ifdef CONFIG_ALTIVEC - if (regs->msr & MSR_VEC) - giveup_altivec(current); -#endif /* CONFIG_ALTIVEC */ -#ifdef CONFIG_SPE - if (regs->msr & MSR_SPE) - giveup_spe(current); -#endif /* CONFIG_SPE */ - preempt_enable(); -} - -/* - * Copy a thread.. - */ -int -copy_thread(int nr, unsigned long clone_flags, unsigned long usp, - unsigned long unused, - struct task_struct *p, struct pt_regs *regs) -{ - struct pt_regs *childregs, *kregs; - extern void ret_from_fork(void); - unsigned long sp = (unsigned long)p->thread_info + THREAD_SIZE; - unsigned long childframe; - - CHECK_FULL_REGS(regs); - /* Copy registers */ - sp -= sizeof(struct pt_regs); - childregs = (struct pt_regs *) sp; - *childregs = *regs; - if ((childregs->msr & MSR_PR) == 0) { - /* for kernel thread, set `current' and stackptr in new task */ - childregs->gpr[1] = sp + sizeof(struct pt_regs); - childregs->gpr[2] = (unsigned long) p; - p->thread.regs = NULL; /* no user register state */ - } else { - childregs->gpr[1] = usp; - p->thread.regs = childregs; - if (clone_flags & CLONE_SETTLS) - childregs->gpr[2] = childregs->gpr[6]; - } - childregs->gpr[3] = 0; /* Result from fork() */ - sp -= STACK_FRAME_OVERHEAD; - childframe = sp; - - /* - * The way this works is that at some point in the future - * some task will call _switch to switch to the new task. - * That will pop off the stack frame created below and start - * the new task running at ret_from_fork. The new task will - * do some house keeping and then return from the fork or clone - * system call, using the stack frame created above. - */ - sp -= sizeof(struct pt_regs); - kregs = (struct pt_regs *) sp; - sp -= STACK_FRAME_OVERHEAD; - p->thread.ksp = sp; - kregs->nip = (unsigned long)ret_from_fork; - - p->thread.last_syscall = -1; - - return 0; -} - -/* - * Set up a thread for executing a new program - */ -void start_thread(struct pt_regs *regs, unsigned long nip, unsigned long sp) -{ - set_fs(USER_DS); - memset(regs->gpr, 0, sizeof(regs->gpr)); - regs->ctr = 0; - regs->link = 0; - regs->xer = 0; - regs->ccr = 0; - regs->mq = 0; - regs->nip = nip; - regs->gpr[1] = sp; - regs->msr = MSR_USER; - preempt_disable(); - if (last_task_used_math == current) - last_task_used_math = NULL; - if (last_task_used_altivec == current) - last_task_used_altivec = NULL; -#ifdef CONFIG_SPE - if (last_task_used_spe == current) - last_task_used_spe = NULL; -#endif - preempt_enable(); - memset(current->thread.fpr, 0, sizeof(current->thread.fpr)); - current->thread.fpscr.val = 0; -#ifdef CONFIG_ALTIVEC - memset(current->thread.vr, 0, sizeof(current->thread.vr)); - memset(¤t->thread.vscr, 0, sizeof(current->thread.vscr)); - current->thread.vrsave = 0; - current->thread.used_vr = 0; -#endif /* CONFIG_ALTIVEC */ -#ifdef CONFIG_SPE - memset(current->thread.evr, 0, sizeof(current->thread.evr)); - current->thread.acc = 0; - current->thread.spefscr = 0; - current->thread.used_spe = 0; -#endif /* CONFIG_SPE */ -} - -#define PR_FP_ALL_EXCEPT (PR_FP_EXC_DIV | PR_FP_EXC_OVF | PR_FP_EXC_UND \ - | PR_FP_EXC_RES | PR_FP_EXC_INV) - -int set_fpexc_mode(struct task_struct *tsk, unsigned int val) -{ - struct pt_regs *regs = tsk->thread.regs; - - /* This is a bit hairy. If we are an SPE enabled processor - * (have embedded fp) we store the IEEE exception enable flags in - * fpexc_mode. fpexc_mode is also used for setting FP exception - * mode (asyn, precise, disabled) for 'Classic' FP. */ - if (val & PR_FP_EXC_SW_ENABLE) { -#ifdef CONFIG_SPE - tsk->thread.fpexc_mode = val & - (PR_FP_EXC_SW_ENABLE | PR_FP_ALL_EXCEPT); -#else - return -EINVAL; -#endif - } else { - /* on a CONFIG_SPE this does not hurt us. The bits that - * __pack_fe01 use do not overlap with bits used for - * PR_FP_EXC_SW_ENABLE. Additionally, the MSR[FE0,FE1] bits - * on CONFIG_SPE implementations are reserved so writing to - * them does not change anything */ - if (val > PR_FP_EXC_PRECISE) - return -EINVAL; - tsk->thread.fpexc_mode = __pack_fe01(val); - if (regs != NULL && (regs->msr & MSR_FP) != 0) - regs->msr = (regs->msr & ~(MSR_FE0|MSR_FE1)) - | tsk->thread.fpexc_mode; - } - return 0; -} - -int get_fpexc_mode(struct task_struct *tsk, unsigned long adr) -{ - unsigned int val; - - if (tsk->thread.fpexc_mode & PR_FP_EXC_SW_ENABLE) -#ifdef CONFIG_SPE - val = tsk->thread.fpexc_mode; -#else - return -EINVAL; -#endif - else - val = __unpack_fe01(tsk->thread.fpexc_mode); - return put_user(val, (unsigned int __user *) adr); -} - -int sys_clone(unsigned long clone_flags, unsigned long usp, - int __user *parent_tidp, void __user *child_threadptr, - int __user *child_tidp, int p6, - struct pt_regs *regs) -{ - CHECK_FULL_REGS(regs); - if (usp == 0) - usp = regs->gpr[1]; /* stack pointer for child */ - return do_fork(clone_flags, usp, regs, 0, parent_tidp, child_tidp); -} - -int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3, - unsigned long p4, unsigned long p5, unsigned long p6, - struct pt_regs *regs) -{ - CHECK_FULL_REGS(regs); - return do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL); -} - -int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3, - unsigned long p4, unsigned long p5, unsigned long p6, - struct pt_regs *regs) -{ - CHECK_FULL_REGS(regs); - return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], - regs, 0, NULL, NULL); -} - -int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, - unsigned long a3, unsigned long a4, unsigned long a5, - struct pt_regs *regs) -{ - int error; - char * filename; - - filename = getname((char __user *) a0); - error = PTR_ERR(filename); - if (IS_ERR(filename)) - goto out; - preempt_disable(); - if (regs->msr & MSR_FP) - giveup_fpu(current); -#ifdef CONFIG_ALTIVEC - if (regs->msr & MSR_VEC) - giveup_altivec(current); -#endif /* CONFIG_ALTIVEC */ -#ifdef CONFIG_SPE - if (regs->msr & MSR_SPE) - giveup_spe(current); -#endif /* CONFIG_SPE */ - preempt_enable(); - error = do_execve(filename, (char __user *__user *) a1, - (char __user *__user *) a2, regs); - if (error == 0) { - task_lock(current); - current->ptrace &= ~PT_DTRACE; - task_unlock(current); - } - putname(filename); -out: - return error; -} - -void dump_stack(void) -{ - show_stack(current, NULL); -} - -EXPORT_SYMBOL(dump_stack); - -void show_stack(struct task_struct *tsk, unsigned long *stack) -{ - unsigned long sp, stack_top, prev_sp, ret; - int count = 0; - unsigned long next_exc = 0; - struct pt_regs *regs; - extern char ret_from_except, ret_from_except_full, ret_from_syscall; - - sp = (unsigned long) stack; - if (tsk == NULL) - tsk = current; - if (sp == 0) { - if (tsk == current) - asm("mr %0,1" : "=r" (sp)); - else - sp = tsk->thread.ksp; - } - - prev_sp = (unsigned long) (tsk->thread_info + 1); - stack_top = (unsigned long) tsk->thread_info + THREAD_SIZE; - while (count < 16 && sp > prev_sp && sp < stack_top && (sp & 3) == 0) { - if (count == 0) { - printk("Call trace:"); -#ifdef CONFIG_KALLSYMS - printk("\n"); -#endif - } else { - if (next_exc) { - ret = next_exc; - next_exc = 0; - } else - ret = *(unsigned long *)(sp + 4); - printk(" [%08lx] ", ret); -#ifdef CONFIG_KALLSYMS - print_symbol("%s", ret); - printk("\n"); -#endif - if (ret == (unsigned long) &ret_from_except - || ret == (unsigned long) &ret_from_except_full - || ret == (unsigned long) &ret_from_syscall) { - /* sp + 16 points to an exception frame */ - regs = (struct pt_regs *) (sp + 16); - if (sp + 16 + sizeof(*regs) <= stack_top) - next_exc = regs->nip; - } - } - ++count; - sp = *(unsigned long *)sp; - } -#ifndef CONFIG_KALLSYMS - if (count > 0) - printk("\n"); -#endif -} - -#if 0 -/* - * Low level print for debugging - Cort - */ -int __init ll_printk(const char *fmt, ...) -{ - va_list args; - char buf[256]; - int i; - - va_start(args, fmt); - i=vsprintf(buf,fmt,args); - ll_puts(buf); - va_end(args); - return i; -} - -int lines = 24, cols = 80; -int orig_x = 0, orig_y = 0; - -void puthex(unsigned long val) -{ - unsigned char buf[10]; - int i; - for (i = 7; i >= 0; i--) - { - buf[i] = "0123456789ABCDEF"[val & 0x0F]; - val >>= 4; - } - buf[8] = '\0'; - prom_print(buf); -} - -void __init ll_puts(const char *s) -{ - int x,y; - char *vidmem = (char *)/*(_ISA_MEM_BASE + 0xB8000) */0xD00B8000; - char c; - extern int mem_init_done; - - if ( mem_init_done ) /* assume this means we can printk */ - { - printk(s); - return; - } - -#if 0 - if ( have_of ) - { - prom_print(s); - return; - } -#endif - - /* - * can't ll_puts on chrp without openfirmware yet. - * vidmem just needs to be setup for it. - * -- Cort - */ - if ( _machine != _MACH_prep ) - return; - x = orig_x; - y = orig_y; - - while ( ( c = *s++ ) != '\0' ) { - if ( c == '\n' ) { - x = 0; - if ( ++y >= lines ) { - /*scroll();*/ - /*y--;*/ - y = 0; - } - } else { - vidmem [ ( x + cols * y ) * 2 ] = c; - if ( ++x >= cols ) { - x = 0; - if ( ++y >= lines ) { - /*scroll();*/ - /*y--;*/ - y = 0; - } - } - } - } - - orig_x = x; - orig_y = y; -} -#endif - -unsigned long get_wchan(struct task_struct *p) -{ - unsigned long ip, sp; - unsigned long stack_page = (unsigned long) p->thread_info; - int count = 0; - if (!p || p == current || p->state == TASK_RUNNING) - return 0; - sp = p->thread.ksp; - do { - sp = *(unsigned long *)sp; - if (sp < stack_page || sp >= stack_page + 8188) - return 0; - if (count > 0) { - ip = *(unsigned long *)(sp + 4); - if (!in_sched_functions(ip)) - return ip; - } - } while (count++ < 16); - return 0; -} diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index 0eb0b7085e6a..c08ab432e958 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -1,5 +1,5 @@ /* - * Common prep/pmac/chrp boot and setup code. + * Common prep/chrp boot and setup code. */ #include <linux/config.h> @@ -35,7 +35,6 @@ #include <asm/machdep.h> #include <asm/uaccess.h> #include <asm/system.h> -#include <asm/pmac_feature.h> #include <asm/sections.h> #include <asm/nvram.h> #include <asm/xmon.h> @@ -55,7 +54,6 @@ extern void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7); -extern void bootx_init(unsigned long r4, unsigned long phys); extern void identify_cpu(unsigned long offset, unsigned long cpu); extern void do_cpu_ftr_fixups(unsigned long offset); extern void reloc_got2(unsigned long offset); @@ -80,8 +78,6 @@ EXPORT_SYMBOL(_machine); extern void prep_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7); -extern void pmac_init(unsigned long r3, unsigned long r4, - unsigned long r5, unsigned long r6, unsigned long r7); extern void chrp_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7); @@ -324,20 +320,15 @@ early_init(int r3, int r4, int r5) identify_cpu(offset, 0); do_cpu_ftr_fixups(offset); -#if defined(CONFIG_PPC_MULTIPLATFORM) +#if defined(CONFIG_PPC_OF) reloc_got2(offset); - /* If we came here from BootX, clear the screen, - * set up some pointers and return. */ - if ((r3 == 0x426f6f58) && (r5 == 0)) - bootx_init(r4, phys); - /* * don't do anything on prep * for now, don't use bootinfo because it breaks yaboot 0.5 * and assume that if we didn't find a magic number, we have OF */ - else if (*(unsigned long *)(0) != 0xdeadc0de) + if (*(unsigned long *)(0) != 0xdeadc0de) phys = prom_init(r3, r4, (prom_entry)r5); reloc_got2(-offset); @@ -424,6 +415,7 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, } #endif +#ifdef CONFIG_PPC_OF have_of = 1; /* prom_init has already been called from __start */ @@ -495,19 +487,17 @@ platform_init(unsigned long r3, unsigned long r4, unsigned long r5, #endif /* CONFIG_ADB */ switch (_machine) { -#ifdef CONFIG_PPC_PMAC - case _MACH_Pmac: - pmac_init(r3, r4, r5, r6, r7); - break; -#endif #ifdef CONFIG_PPC_CHRP case _MACH_chrp: chrp_init(r3, r4, r5, r6, r7); break; #endif } +#endif /* CONFIG_PPC_OF */ } +#endif /* CONFIG_PPC_MULTIPLATFORM */ +#ifdef CONFIG_PPC_OF #ifdef CONFIG_SERIAL_CORE_CONSOLE extern char *of_stdout_device; @@ -564,7 +554,7 @@ static int __init set_preferred_console(void) } console_initcall(set_preferred_console); #endif /* CONFIG_SERIAL_CORE_CONSOLE */ -#endif /* CONFIG_PPC_MULTIPLATFORM */ +#endif /* CONFIG_PPC_OF */ struct bi_record *find_bootinfo(void) { @@ -744,13 +734,8 @@ void __init setup_arch(char **cmdline_p) /* so udelay does something sensible, assume <= 1000 bogomips */ loops_per_jiffy = 500000000 / HZ; -#ifdef CONFIG_PPC_MULTIPLATFORM - /* This could be called "early setup arch", it must be done - * now because xmon need it - */ - if (_machine == _MACH_Pmac) - pmac_feature_init(); /* New cool way */ -#endif + if (ppc_md.init_early) + ppc_md.init_early(); #ifdef CONFIG_XMON xmon_init(1); diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c index becbfa397556..e55cdda6149a 100644 --- a/arch/ppc/kernel/smp.c +++ b/arch/ppc/kernel/smp.c @@ -318,7 +318,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) p = fork_idle(cpu); if (IS_ERR(p)) panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p)); - p->thread_info->cpu = cpu; + task_thread_info(p)->cpu = cpu; idle_tasks[cpu] = p; } } @@ -369,7 +369,7 @@ int __cpu_up(unsigned int cpu) char buf[32]; int c; - secondary_ti = idle_tasks[cpu]->thread_info; + secondary_ti = task_thread_info(idle_tasks[cpu]); mb(); /* diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index 9dbc4d28fa28..6d0a1838d94c 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -38,9 +38,6 @@ #include <asm/io.h> #include <asm/reg.h> #include <asm/xmon.h> -#ifdef CONFIG_PMAC_BACKLIGHT -#include <asm/backlight.h> -#endif #include <asm/pmc.h> #ifdef CONFIG_XMON @@ -85,12 +82,6 @@ int die(const char * str, struct pt_regs * fp, long err) int nl = 0; console_verbose(); spin_lock_irq(&die_lock); -#ifdef CONFIG_PMAC_BACKLIGHT - if (_machine == _MACH_Pmac) { - set_backlight_enable(1); - set_backlight_level(BACKLIGHT_MAX); - } -#endif printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter); #ifdef CONFIG_PREEMPT printk("PREEMPT "); @@ -159,7 +150,7 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) */ static inline int check_io_access(struct pt_regs *regs) { -#if defined CONFIG_PPC_PMAC || defined CONFIG_8xx +#if defined CONFIG_8xx unsigned long msr = regs->msr; const struct exception_table_entry *entry; unsigned int *nip = (unsigned int *)regs->nip; @@ -196,7 +187,7 @@ static inline int check_io_access(struct pt_regs *regs) return 1; } } -#endif /* CONFIG_PPC_PMAC */ +#endif /* CONFIG_8xx */ return 0; } |