diff options
Diffstat (limited to 'arch/ppc/kernel')
27 files changed, 254 insertions, 133 deletions
diff --git a/arch/ppc/kernel/Makefile b/arch/ppc/kernel/Makefile index b1457a8a9c0f..1fb92f16acd6 100644 --- a/arch/ppc/kernel/Makefile +++ b/arch/ppc/kernel/Makefile @@ -15,8 +15,9 @@ extra-y += vmlinux.lds obj-y := entry.o traps.o irq.o idle.o time.o misc.o \ process.o signal.o ptrace.o align.o \ semaphore.o syscalls.o setup.o \ - cputable.o ppc_htab.o perfmon.o + cputable.o ppc_htab.o obj-$(CONFIG_6xx) += l2cr.o cpu_setup_6xx.o +obj-$(CONFIG_E500) += perfmon.o obj-$(CONFIG_SOFTWARE_SUSPEND) += swsusp.o obj-$(CONFIG_POWER4) += cpu_setup_power4.o obj-$(CONFIG_MODULES) += module.o ppc_ksyms.o diff --git a/arch/ppc/kernel/cpu_setup_6xx.S b/arch/ppc/kernel/cpu_setup_6xx.S index 468721d9ebd2..ba396438ede3 100644 --- a/arch/ppc/kernel/cpu_setup_6xx.S +++ b/arch/ppc/kernel/cpu_setup_6xx.S @@ -12,10 +12,9 @@ #include <linux/config.h> #include <asm/processor.h> #include <asm/page.h> -#include <asm/ppc_asm.h> #include <asm/cputable.h> #include <asm/ppc_asm.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> #include <asm/cache.h> _GLOBAL(__setup_cpu_601) @@ -249,8 +248,11 @@ END_FTR_SECTION_IFSET(CPU_FTR_NO_DPM) sync isync - /* Enable L2 HW prefetch + /* Enable L2 HW prefetch, if L2 is enabled */ + mfspr r3,SPRN_L2CR + andis. r3,r3,L2CR_L2E@h + beqlr mfspr r3,SPRN_MSSCR0 ori r3,r3,3 sync @@ -324,6 +326,7 @@ _GLOBAL(__save_cpu_setup) cmplwi cr4,r3,0x8002 /* 7457 */ cmplwi cr5,r3,0x8003 /* 7447A */ cmplwi cr6,r3,0x7000 /* 750FX */ + cmplwi cr7,r3,0x8004 /* 7448 */ /* cr1 is 7400 || 7410 */ cror 4*cr1+eq,4*cr1+eq,4*cr2+eq /* cr0 is 74xx */ @@ -331,6 +334,7 @@ _GLOBAL(__save_cpu_setup) cror 4*cr0+eq,4*cr0+eq,4*cr4+eq cror 4*cr0+eq,4*cr0+eq,4*cr1+eq cror 4*cr0+eq,4*cr0+eq,4*cr5+eq + cror 4*cr0+eq,4*cr0+eq,4*cr7+eq bne 1f /* Backup 74xx specific regs */ mfspr r4,SPRN_MSSCR0 @@ -393,6 +397,7 @@ _GLOBAL(__restore_cpu_setup) cmplwi cr4,r3,0x8002 /* 7457 */ cmplwi cr5,r3,0x8003 /* 7447A */ cmplwi cr6,r3,0x7000 /* 750FX */ + cmplwi cr7,r3,0x8004 /* 7448 */ /* cr1 is 7400 || 7410 */ cror 4*cr1+eq,4*cr1+eq,4*cr2+eq /* cr0 is 74xx */ @@ -400,6 +405,7 @@ _GLOBAL(__restore_cpu_setup) cror 4*cr0+eq,4*cr0+eq,4*cr4+eq cror 4*cr0+eq,4*cr0+eq,4*cr1+eq cror 4*cr0+eq,4*cr0+eq,4*cr5+eq + cror 4*cr0+eq,4*cr0+eq,4*cr7+eq bne 2f /* Restore 74xx specific regs */ lwz r4,CS_MSSCR0(r5) diff --git a/arch/ppc/kernel/cpu_setup_power4.S b/arch/ppc/kernel/cpu_setup_power4.S index f2ea1a990f17..7e4fbb653724 100644 --- a/arch/ppc/kernel/cpu_setup_power4.S +++ b/arch/ppc/kernel/cpu_setup_power4.S @@ -14,8 +14,7 @@ #include <asm/page.h> #include <asm/ppc_asm.h> #include <asm/cputable.h> -#include <asm/ppc_asm.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> #include <asm/cache.h> _GLOBAL(__970_cpu_preinit) diff --git a/arch/ppc/kernel/cputable.c b/arch/ppc/kernel/cputable.c index 8a3d74f2531e..546e1ea4cafa 100644 --- a/arch/ppc/kernel/cputable.c +++ b/arch/ppc/kernel/cputable.c @@ -198,10 +198,10 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 4, .cpu_setup = __setup_cpu_750 }, - { /* 745/755 */ - .pvr_mask = 0xfffff000, - .pvr_value = 0x00083000, - .cpu_name = "745/755", + { /* 750CX (80100 and 8010x?) */ + .pvr_mask = 0xfffffff0, + .pvr_value = 0x00080100, + .cpu_name = "750CX", .cpu_features = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | @@ -210,11 +210,11 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, .num_pmcs = 4, - .cpu_setup = __setup_cpu_750 + .cpu_setup = __setup_cpu_750cx }, - { /* 750CX (80100 and 8010x?) */ + { /* 750CX (82201 and 82202) */ .pvr_mask = 0xfffffff0, - .pvr_value = 0x00080100, + .pvr_value = 0x00082200, .cpu_name = "750CX", .cpu_features = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | @@ -226,10 +226,10 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 4, .cpu_setup = __setup_cpu_750cx }, - { /* 750CX (82201 and 82202) */ + { /* 750CXe (82214) */ .pvr_mask = 0xfffffff0, - .pvr_value = 0x00082200, - .cpu_name = "750CX", + .pvr_value = 0x00082210, + .cpu_name = "750CXe", .cpu_features = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | @@ -240,9 +240,9 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 4, .cpu_setup = __setup_cpu_750cx }, - { /* 750CXe (82214) */ - .pvr_mask = 0xfffffff0, - .pvr_value = 0x00082210, + { /* 750CXe "Gekko" (83214) */ + .pvr_mask = 0xffffffff, + .pvr_value = 0x00083214, .cpu_name = "750CXe", .cpu_features = CPU_FTR_COMMON | CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | @@ -254,6 +254,20 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 4, .cpu_setup = __setup_cpu_750cx }, + { /* 745/755 */ + .pvr_mask = 0xfffff000, + .pvr_value = 0x00083000, + .cpu_name = "745/755", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_MAYBE_CAN_DOZE | + CPU_FTR_USE_TB | CPU_FTR_L2CR | CPU_FTR_TAU | + CPU_FTR_HPTE_TABLE | CPU_FTR_MAYBE_CAN_NAP, + .cpu_user_features = COMMON_PPC, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 4, + .cpu_setup = __setup_cpu_750 + }, { /* 750FX rev 1.x */ .pvr_mask = 0xffffff00, .pvr_value = 0x70000100, @@ -536,6 +550,22 @@ struct cpu_spec cpu_specs[] = { .num_pmcs = 6, .cpu_setup = __setup_cpu_745x }, + { /* 7448 */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x80040000, + .cpu_name = "7448", + .cpu_features = CPU_FTR_COMMON | + CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | + CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_L2CR | + CPU_FTR_ALTIVEC_COMP | CPU_FTR_HPTE_TABLE | + CPU_FTR_SPEC7450 | CPU_FTR_NAP_DISABLE_L2_PR | + CPU_FTR_HAS_HIGH_BATS | CPU_FTR_NEED_COHERENT, + .cpu_user_features = COMMON_PPC | PPC_FEATURE_ALTIVEC_COMP, + .icache_bsize = 32, + .dcache_bsize = 32, + .num_pmcs = 6, + .cpu_setup = __setup_cpu_745x + }, { /* 82xx (8240, 8245, 8260 are all 603e cores) */ .pvr_mask = 0x7fff0000, .pvr_value = 0x00810000, @@ -922,6 +952,26 @@ struct cpu_spec cpu_specs[] = { .icache_bsize = 32, .dcache_bsize = 32, }, + { /* 440GX Rev. F */ + .pvr_mask = 0xf0000fff, + .pvr_value = 0x50000894, + .cpu_name = "440GX Rev. F", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .icache_bsize = 32, + .dcache_bsize = 32, + }, + { /* 440SP Rev. A */ + .pvr_mask = 0xff000fff, + .pvr_value = 0x53000891, + .cpu_name = "440SP Rev. A", + .cpu_features = CPU_FTR_SPLIT_ID_CACHE | + CPU_FTR_USE_TB, + .cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU, + .icache_bsize = 32, + .dcache_bsize = 32, + }, #endif /* CONFIG_44x */ #ifdef CONFIG_FSL_BOOKE { /* e200z5 */ diff --git a/arch/ppc/kernel/dma-mapping.c b/arch/ppc/kernel/dma-mapping.c index e0c631cf96b0..b566d982806c 100644 --- a/arch/ppc/kernel/dma-mapping.c +++ b/arch/ppc/kernel/dma-mapping.c @@ -393,7 +393,7 @@ EXPORT_SYMBOL(__dma_sync); * __dma_sync_page() implementation for systems using highmem. * In this case, each page of a buffer must be kmapped/kunmapped * in order to have a virtual address for __dma_sync(). This must - * not sleep so kmap_atmomic()/kunmap_atomic() are used. + * not sleep so kmap_atomic()/kunmap_atomic() are used. * * Note: yes, it is possible and correct to have a buffer extend * beyond the first page. diff --git a/arch/ppc/kernel/entry.S b/arch/ppc/kernel/entry.S index cb83045e2edf..03d4886869f3 100644 --- a/arch/ppc/kernel/entry.S +++ b/arch/ppc/kernel/entry.S @@ -29,7 +29,7 @@ #include <asm/cputable.h> #include <asm/thread_info.h> #include <asm/ppc_asm.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> #include <asm/unistd.h> #undef SHOW_SYSCALLS diff --git a/arch/ppc/kernel/find_name.c b/arch/ppc/kernel/find_name.c deleted file mode 100644 index 3c0fa8e0c077..000000000000 --- a/arch/ppc/kernel/find_name.c +++ /dev/null @@ -1,48 +0,0 @@ -#include <stdio.h> -#include <asm/page.h> -#include <sys/mman.h> -#include <strings.h> -/* - * Finds a given address in the System.map and prints it out - * with its neighbors. -- Cort - */ - -int main(int argc, char **argv) -{ - unsigned long addr, cmp, i; - FILE *f; - char s[256], last[256]; - - if ( argc < 2 ) - { - fprintf(stderr, "Usage: %s <address>\n", argv[0]); - return -1; - } - - for ( i = 1 ; argv[i] ; i++ ) - { - sscanf( argv[i], "%0lx", &addr ); - /* adjust if addr is relative to kernelbase */ - if ( addr < PAGE_OFFSET ) - addr += PAGE_OFFSET; - - if ( (f = fopen( "System.map", "r" )) == NULL ) - { - perror("fopen()\n"); - exit(-1); - } - - while ( !feof(f) ) - { - fgets(s, 255 , f); - sscanf( s, "%0lx", &cmp ); - if ( addr < cmp ) - break; - strcpy( last, s); - } - - printf( "%s%s", last, s ); - } - fclose(f); - return 0; -} diff --git a/arch/ppc/kernel/fpu.S b/arch/ppc/kernel/fpu.S index 6189b26f640f..665d7d34304c 100644 --- a/arch/ppc/kernel/fpu.S +++ b/arch/ppc/kernel/fpu.S @@ -18,7 +18,7 @@ #include <asm/cache.h> #include <asm/thread_info.h> #include <asm/ppc_asm.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> /* * This task wants to use the FPU now. diff --git a/arch/ppc/kernel/head.S b/arch/ppc/kernel/head.S index a931d773715f..1960fb8c259c 100644 --- a/arch/ppc/kernel/head.S +++ b/arch/ppc/kernel/head.S @@ -31,7 +31,7 @@ #include <asm/cache.h> #include <asm/thread_info.h> #include <asm/ppc_asm.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> #ifdef CONFIG_APUS #include <asm/amigappc.h> @@ -1023,23 +1023,21 @@ __secondary_start_gemini: andc r4,r4,r3 mtspr SPRN_HID0,r4 sync - bl gemini_prom_init b __secondary_start #endif /* CONFIG_GEMINI */ - .globl __secondary_start_psurge -__secondary_start_psurge: - li r24,1 /* cpu # */ - b __secondary_start_psurge99 - .globl __secondary_start_psurge2 -__secondary_start_psurge2: - li r24,2 /* cpu # */ - b __secondary_start_psurge99 - .globl __secondary_start_psurge3 -__secondary_start_psurge3: - li r24,3 /* cpu # */ - b __secondary_start_psurge99 -__secondary_start_psurge99: - /* we come in here with IR=0 and DR=1, and DBAT 0 + + .globl __secondary_start_pmac_0 +__secondary_start_pmac_0: + /* NB the entries for cpus 0, 1, 2 must each occupy 8 bytes. */ + li r24,0 + b 1f + li r24,1 + b 1f + li r24,2 + b 1f + li r24,3 +1: + /* on powersurge, we come in here with IR=0 and DR=1, and DBAT 0 set to map the 0xf0000000 - 0xffffffff region */ mfmsr r0 rlwinm r0,r0,0,28,26 /* clear DR (0x10) */ diff --git a/arch/ppc/kernel/head_44x.S b/arch/ppc/kernel/head_44x.S index 69ff3a9961e8..599245b0407e 100644 --- a/arch/ppc/kernel/head_44x.S +++ b/arch/ppc/kernel/head_44x.S @@ -40,7 +40,7 @@ #include <asm/cputable.h> #include <asm/thread_info.h> #include <asm/ppc_asm.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> #include "head_booke.h" @@ -462,7 +462,11 @@ interrupt_base: /* Watchdog Timer Interrupt */ /* TODO: Add watchdog support */ +#ifdef CONFIG_BOOKE_WDT + CRITICAL_EXCEPTION(0x1020, WatchdogTimer, WatchdogException) +#else CRITICAL_EXCEPTION(0x1020, WatchdogTimer, UnknownException) +#endif /* Data TLB Error Interrupt */ START_EXCEPTION(DataTLBError) diff --git a/arch/ppc/kernel/head_4xx.S b/arch/ppc/kernel/head_4xx.S index 23fb51819ba5..8562b807b37c 100644 --- a/arch/ppc/kernel/head_4xx.S +++ b/arch/ppc/kernel/head_4xx.S @@ -40,7 +40,7 @@ #include <asm/cputable.h> #include <asm/thread_info.h> #include <asm/ppc_asm.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> /* As with the other PowerPC ports, it is expected that when code * execution begins here, the following registers contain valid, yet @@ -448,9 +448,12 @@ label: /* 0x1020 - Watchdog Timer (WDT) Exception */ - +#ifdef CONFIG_BOOKE_WDT + CRITICAL_EXCEPTION(0x1020, WDTException, WatchdogException) +#else CRITICAL_EXCEPTION(0x1020, WDTException, UnknownException) #endif +#endif /* 0x1100 - Data TLB Miss Exception * As the name implies, translation is not in the MMU, so search the diff --git a/arch/ppc/kernel/head_8xx.S b/arch/ppc/kernel/head_8xx.S index eb18cadb3755..cb1a3a54a026 100644 --- a/arch/ppc/kernel/head_8xx.S +++ b/arch/ppc/kernel/head_8xx.S @@ -30,7 +30,7 @@ #include <asm/cputable.h> #include <asm/thread_info.h> #include <asm/ppc_asm.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> /* Macro to make the code more readable. */ #ifdef CONFIG_8xx_CPU6 diff --git a/arch/ppc/kernel/head_fsl_booke.S b/arch/ppc/kernel/head_fsl_booke.S index eb804b7a3cb2..8e52e8408316 100644 --- a/arch/ppc/kernel/head_fsl_booke.S +++ b/arch/ppc/kernel/head_fsl_booke.S @@ -41,7 +41,7 @@ #include <asm/cputable.h> #include <asm/thread_info.h> #include <asm/ppc_asm.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> #include "head_booke.h" /* As with the other PowerPC ports, it is expected that when code @@ -564,8 +564,11 @@ interrupt_base: EXCEPTION(0x3100, FixedIntervalTimer, UnknownException, EXC_XFER_EE) /* Watchdog Timer Interrupt */ - /* TODO: Add watchdog support */ +#ifdef CONFIG_BOOKE_WDT + CRITICAL_EXCEPTION(0x3200, WatchdogTimer, WatchdogException) +#else CRITICAL_EXCEPTION(0x3200, WatchdogTimer, UnknownException) +#endif /* Data TLB Error Interrupt */ START_EXCEPTION(DataTLBError) diff --git a/arch/ppc/kernel/idle.c b/arch/ppc/kernel/idle.c index 53547b6de45b..fba29c876b62 100644 --- a/arch/ppc/kernel/idle.c +++ b/arch/ppc/kernel/idle.c @@ -22,6 +22,7 @@ #include <linux/ptrace.h> #include <linux/slab.h> #include <linux/sysctl.h> +#include <linux/cpu.h> #include <asm/pgtable.h> #include <asm/uaccess.h> @@ -35,6 +36,7 @@ void default_idle(void) { void (*powersave)(void); + int cpu = smp_processor_id(); powersave = ppc_md.power_save; @@ -44,7 +46,7 @@ void default_idle(void) #ifdef CONFIG_SMP else { set_thread_flag(TIF_POLLING_NRFLAG); - while (!need_resched()) + while (!need_resched() && !cpu_is_offline(cpu)) barrier(); clear_thread_flag(TIF_POLLING_NRFLAG); } @@ -52,6 +54,8 @@ void default_idle(void) } if (need_resched()) schedule(); + if (cpu_is_offline(cpu) && system_state == SYSTEM_RUNNING) + cpu_die(); } /* diff --git a/arch/ppc/kernel/idle_6xx.S b/arch/ppc/kernel/idle_6xx.S index 25d009c75f7b..1a2194cf6828 100644 --- a/arch/ppc/kernel/idle_6xx.S +++ b/arch/ppc/kernel/idle_6xx.S @@ -20,7 +20,7 @@ #include <asm/cputable.h> #include <asm/thread_info.h> #include <asm/ppc_asm.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> #undef DEBUG diff --git a/arch/ppc/kernel/idle_power4.S b/arch/ppc/kernel/idle_power4.S index 73a58ff03900..cc0d535365cd 100644 --- a/arch/ppc/kernel/idle_power4.S +++ b/arch/ppc/kernel/idle_power4.S @@ -20,7 +20,7 @@ #include <asm/cputable.h> #include <asm/thread_info.h> #include <asm/ppc_asm.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> #undef DEBUG diff --git a/arch/ppc/kernel/l2cr.S b/arch/ppc/kernel/l2cr.S index c39441048266..861115249b35 100644 --- a/arch/ppc/kernel/l2cr.S +++ b/arch/ppc/kernel/l2cr.S @@ -156,6 +156,26 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) The bit moved on the 7450..... ****/ +BEGIN_FTR_SECTION + /* Disable L2 prefetch on some 745x and try to ensure + * L2 prefetch engines are idle. As explained by errata + * text, we can't be sure they are, we just hope very hard + * that well be enough (sic !). At least I noticed Apple + * doesn't even bother doing the dcbf's here... + */ + mfspr r4,SPRN_MSSCR0 + rlwinm r4,r4,0,0,29 + sync + mtspr SPRN_MSSCR0,r4 + sync + isync + lis r4,KERNELBASE@h + dcbf 0,r4 + dcbf 0,r4 + dcbf 0,r4 + dcbf 0,r4 +END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450) + /* TODO: use HW flush assist when available */ lis r4,0x0002 @@ -230,7 +250,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450) oris r3,r3,0x8000 mtspr SPRN_L2CR,r3 sync - + + /* Enable L2 HW prefetch on 744x/745x */ +BEGIN_FTR_SECTION + mfspr r3,SPRN_MSSCR0 + ori r3,r3,3 + sync + mtspr SPRN_MSSCR0,r3 + sync + isync +END_FTR_SECTION_IFSET(CPU_FTR_SPEC7450) 4: /* Restore HID0[DPM] to whatever it was before */ diff --git a/arch/ppc/kernel/misc.S b/arch/ppc/kernel/misc.S index ce71b4a01585..90d917d2e856 100644 --- a/arch/ppc/kernel/misc.S +++ b/arch/ppc/kernel/misc.S @@ -23,7 +23,7 @@ #include <asm/mmu.h> #include <asm/ppc_asm.h> #include <asm/thread_info.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> .text diff --git a/arch/ppc/kernel/pci.c b/arch/ppc/kernel/pci.c index 7b3586a3bf30..854e45beb387 100644 --- a/arch/ppc/kernel/pci.c +++ b/arch/ppc/kernel/pci.c @@ -80,7 +80,6 @@ fixup_broken_pcnet32(struct pci_dev* dev) if ((dev->class>>8 == PCI_CLASS_NETWORK_ETHERNET)) { dev->vendor = PCI_VENDOR_ID_AMD; pci_write_config_word(dev, PCI_VENDOR_ID, PCI_VENDOR_ID_AMD); - pci_name_device(dev); } } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32); diff --git a/arch/ppc/kernel/ppc_ksyms.c b/arch/ppc/kernel/ppc_ksyms.c index e7d40cc6c1b6..88f6bb7b6964 100644 --- a/arch/ppc/kernel/ppc_ksyms.c +++ b/arch/ppc/kernel/ppc_ksyms.c @@ -51,9 +51,6 @@ #include <asm/commproc.h> #endif -/* Tell string.h we don't want memcpy etc. as cpp defines */ -#define EXPORT_SYMTAB_STROPS - extern void transfer_to_handler(void); extern void do_IRQ(struct pt_regs *regs); extern void MachineCheckException(struct pt_regs *regs); @@ -263,6 +260,7 @@ EXPORT_SYMBOL(__ashrdi3); EXPORT_SYMBOL(__ashldi3); EXPORT_SYMBOL(__lshrdi3); EXPORT_SYMBOL(memcpy); +EXPORT_SYMBOL(cacheable_memcpy); EXPORT_SYMBOL(memset); EXPORT_SYMBOL(memmove); EXPORT_SYMBOL(memscan); diff --git a/arch/ppc/kernel/setup.c b/arch/ppc/kernel/setup.c index 929e5d1cc7fe..545cfd0fab59 100644 --- a/arch/ppc/kernel/setup.c +++ b/arch/ppc/kernel/setup.c @@ -41,7 +41,11 @@ #include <asm/xmon.h> #include <asm/ocp.h> -#if defined(CONFIG_85xx) || defined(CONFIG_83xx) || defined(CONFIG_MPC10X_BRIDGE) +#define USES_PPC_SYS (defined(CONFIG_85xx) || defined(CONFIG_83xx) || \ + defined(CONFIG_MPC10X_BRIDGE) || defined(CONFIG_8260) || \ + defined(CONFIG_PPC_MPC52xx)) + +#if USES_PPC_SYS #include <asm/ppc_sys.h> #endif @@ -241,7 +245,7 @@ int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "bogomips\t: %lu.%02lu\n", lpj / (500000/HZ), (lpj / (5000/HZ)) % 100); -#if defined(CONFIG_85xx) || defined(CONFIG_83xx) || defined(CONFIG_MPC10X_BRIDGE) +#if USES_PPC_SYS if (cur_ppc_sys_spec->ppc_sys_name) seq_printf(m, "chipset\t\t: %s\n", cur_ppc_sys_spec->ppc_sys_name); @@ -615,6 +619,26 @@ machine_init(unsigned long r3, unsigned long r4, unsigned long r5, if (ppc_md.progress) ppc_md.progress("id mach(): done", 0x200); } +#ifdef CONFIG_BOOKE_WDT +/* Checks wdt=x and wdt_period=xx command-line option */ +int __init early_parse_wdt(char *p) +{ + if (p && strncmp(p, "0", 1) != 0) + booke_wdt_enabled = 1; + + return 0; +} +early_param("wdt", early_parse_wdt); + +int __init early_parse_wdt_period (char *p) +{ + if (p) + booke_wdt_period = simple_strtoul(p, NULL, 0); + + return 0; +} +early_param("wdt_period", early_parse_wdt_period); +#endif /* CONFIG_BOOKE_WDT */ /* Checks "l2cr=xxxx" command-line option */ int __init ppc_setup_l2cr(char *str) diff --git a/arch/ppc/kernel/signal.c b/arch/ppc/kernel/signal.c index 8aaeb6f4e750..2244bf91e593 100644 --- a/arch/ppc/kernel/signal.c +++ b/arch/ppc/kernel/signal.c @@ -759,13 +759,12 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs) else handle_signal(signr, &ka, &info, oldset, regs, newsp); - if (!(ka.sa.sa_flags & SA_NODEFER)) { - spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked,¤t->blocked,&ka.sa.sa_mask); + spin_lock_irq(¤t->sighand->siglock); + sigorsets(¤t->blocked,¤t->blocked,&ka.sa.sa_mask); + if (!(ka.sa.sa_flags & SA_NODEFER)) sigaddset(¤t->blocked, signr); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - } + recalc_sigpending(); + spin_unlock_irq(¤t->sighand->siglock); return 1; } diff --git a/arch/ppc/kernel/smp.c b/arch/ppc/kernel/smp.c index e70b587b9e51..726fe7ce1747 100644 --- a/arch/ppc/kernel/smp.c +++ b/arch/ppc/kernel/smp.c @@ -45,6 +45,7 @@ cpumask_t cpu_online_map; cpumask_t cpu_possible_map; int smp_hw_index[NR_CPUS]; struct thread_info *secondary_ti; +static struct task_struct *idle_tasks[NR_CPUS]; EXPORT_SYMBOL(cpu_online_map); EXPORT_SYMBOL(cpu_possible_map); @@ -286,7 +287,8 @@ static void __devinit smp_store_cpu_info(int id) void __init smp_prepare_cpus(unsigned int max_cpus) { - int num_cpus, i; + int num_cpus, i, cpu; + struct task_struct *p; /* Fixup boot cpu */ smp_store_cpu_info(smp_processor_id()); @@ -308,6 +310,17 @@ void __init smp_prepare_cpus(unsigned int max_cpus) if (smp_ops->space_timers) smp_ops->space_timers(num_cpus); + + for_each_cpu(cpu) { + if (cpu == smp_processor_id()) + continue; + /* create a process for the processor */ + p = fork_idle(cpu); + if (IS_ERR(p)) + panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p)); + p->thread_info->cpu = cpu; + idle_tasks[cpu] = p; + } } void __devinit smp_prepare_boot_cpu(void) @@ -334,12 +347,17 @@ int __devinit start_secondary(void *unused) set_dec(tb_ticks_per_jiffy); cpu_callin_map[cpu] = 1; - printk("CPU %i done callin...\n", cpu); + printk("CPU %d done callin...\n", cpu); smp_ops->setup_cpu(cpu); - printk("CPU %i done setup...\n", cpu); - local_irq_enable(); + printk("CPU %d done setup...\n", cpu); smp_ops->take_timebase(); - printk("CPU %i done timebase take...\n", cpu); + printk("CPU %d done timebase take...\n", cpu); + + spin_lock(&call_lock); + cpu_set(cpu, cpu_online_map); + spin_unlock(&call_lock); + + local_irq_enable(); cpu_idle(); return 0; @@ -347,17 +365,11 @@ int __devinit start_secondary(void *unused) int __cpu_up(unsigned int cpu) { - struct task_struct *p; char buf[32]; int c; - /* create a process for the processor */ - /* only regs.msr is actually used, and 0 is OK for it */ - p = fork_idle(cpu); - if (IS_ERR(p)) - panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p)); - secondary_ti = p->thread_info; - p->thread_info->cpu = cpu; + secondary_ti = idle_tasks[cpu]->thread_info; + mb(); /* * There was a cache flush loop here to flush the cache @@ -389,7 +401,11 @@ int __cpu_up(unsigned int cpu) printk("Processor %d found.\n", cpu); smp_ops->give_timebase(); - cpu_set(cpu, cpu_online_map); + + /* Wait until cpu puts itself in the online map */ + while (!cpu_online(cpu)) + cpu_relax(); + return 0; } diff --git a/arch/ppc/kernel/swsusp.S b/arch/ppc/kernel/swsusp.S index 55148bb88d39..69773cc1a85f 100644 --- a/arch/ppc/kernel/swsusp.S +++ b/arch/ppc/kernel/swsusp.S @@ -5,7 +5,7 @@ #include <asm/cputable.h> #include <asm/thread_info.h> #include <asm/ppc_asm.h> -#include <asm/offsets.h> +#include <asm/asm-offsets.h> /* diff --git a/arch/ppc/kernel/syscalls.c b/arch/ppc/kernel/syscalls.c index 124313ce3c09..127f040de9de 100644 --- a/arch/ppc/kernel/syscalls.c +++ b/arch/ppc/kernel/syscalls.c @@ -41,10 +41,6 @@ #include <asm/ipc.h> #include <asm/semaphore.h> -void -check_bugs(void) -{ -} /* * sys_ipc() is the de-multiplexer for the SysV IPC calls.. diff --git a/arch/ppc/kernel/time.c b/arch/ppc/kernel/time.c index bf4ddca5e853..a3c5281a5d2d 100644 --- a/arch/ppc/kernel/time.c +++ b/arch/ppc/kernel/time.c @@ -169,7 +169,7 @@ void timer_interrupt(struct pt_regs * regs) * We should have an rtc call that only sets the minutes and * seconds like on Intel to avoid problems with non UTC clocks. */ - if ( ppc_md.set_rtc_time && (time_status & STA_UNSYNC) == 0 && + if ( ppc_md.set_rtc_time && ntp_synced() && xtime.tv_sec - last_rtc_update >= 659 && abs((xtime.tv_nsec / 1000) - (1000000-1000000/HZ)) < 500000/HZ && jiffies - wall_jiffies == 1) { @@ -271,10 +271,7 @@ int do_settimeofday(struct timespec *tv) */ last_rtc_update = new_sec - 658; - time_adjust = 0; /* stop active adjtime() */ - time_status |= STA_UNSYNC; - time_maxerror = NTP_PHASE_LIMIT; - time_esterror = NTP_PHASE_LIMIT; + ntp_clear(); write_sequnlock_irqrestore(&xtime_lock, flags); clock_was_set(); return 0; diff --git a/arch/ppc/kernel/traps.c b/arch/ppc/kernel/traps.c index 9e6ae5696650..961ede87be72 100644 --- a/arch/ppc/kernel/traps.c +++ b/arch/ppc/kernel/traps.c @@ -118,6 +118,28 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) info.si_code = code; info.si_addr = (void __user *) addr; force_sig_info(signr, &info, current); + + /* + * Init gets no signals that it doesn't have a handler for. + * That's all very well, but if it has caused a synchronous + * exception and we ignore the resulting signal, it will just + * generate the same exception over and over again and we get + * nowhere. Better to kill it and let the kernel panic. + */ + if (current->pid == 1) { + __sighandler_t handler; + + spin_lock_irq(¤t->sighand->siglock); + handler = current->sighand->action[signr-1].sa.sa_handler; + spin_unlock_irq(¤t->sighand->siglock); + if (handler == SIG_DFL) { + /* init has generated a synchronous exception + and it doesn't have a handler for the signal */ + printk(KERN_CRIT "init has generated signal %d " + "but has no handler for it\n", signr); + do_exit(signr); + } + } } /* @@ -849,10 +871,12 @@ void AltivecAssistException(struct pt_regs *regs) } #endif /* CONFIG_ALTIVEC */ +#ifdef CONFIG_E500 void PerformanceMonitorException(struct pt_regs *regs) { perf_irq(regs); } +#endif #ifdef CONFIG_FSL_BOOKE void CacheLockingException(struct pt_regs *regs, unsigned long address, @@ -904,6 +928,25 @@ void SPEFloatingPointException(struct pt_regs *regs) } #endif +#ifdef CONFIG_BOOKE_WDT +/* + * Default handler for a Watchdog exception, + * spins until a reboot occurs + */ +void __attribute__ ((weak)) WatchdogHandler(struct pt_regs *regs) +{ + /* Generic WatchdogHandler, implement your own */ + mtspr(SPRN_TCR, mfspr(SPRN_TCR)&(~TCR_WIE)); + return; +} + +void WatchdogException(struct pt_regs *regs) +{ + printk (KERN_EMERG "PowerPC Book-E Watchdog Exception\n"); + WatchdogHandler(regs); +} +#endif + void __init trap_init(void) { } |