commit 8483ca3c99559027a3741af7f56f6b36887f7fd5 Merge: ede847c... 190a24f... Author: Linus Torvalds Date: Wed Oct 25 20:20:03 2006 -0700 Merge branch 'merge' of master.kernel.org:/pub/scm/linux/kernel/git/paulus/powerpc * 'merge' of master.kernel.org:/pub/scm/linux/kernel/git/paulus/powerpc: [POWERPC] Make sure __cpu_preinit_ppc970 gets called on 970GX processors [POWERPC] Fix CHRP platforms with only 8259 [POWERPC] IPIC: Fix spinlock recursion in set_irq_handler [POWERPC] Fix the UCC rx/tx clock of QE [POWERPC] cell: update defconfig [POWERPC] spufs: fix another off-by-one bug in spufs_mbox_read [POWERPC] spufs: fix signal2 file to report signal2 [POWERPC] Fix device_is_compatible() const warning [POWERPC] Cell timebase bug workaround [POWERPC] Support feature fixups in modules [POWERPC] Support feature fixups in vdso's [POWERPC] Support nested cpu feature sections [POWERPC] Consolidate feature fixup code [POWERPC] Fix hang in start_ldr if _end or _edata is unaligned [POWERPC] Fix spelling errors in ucc_fast.c and ucc_slow.c [POWERPC] Don't require execute perms on wrapper when building zImage.initrd [POWERPC] Add 970GX cputable entry [POWERPC] Fix build breakage with CONFIG_PPC32 [POWERPC] Fix compiler warning message on get_property call [POWERPC] Simplify stolen time calculation commit 190a24f5605d95b786c92280bf7a51ebef43f29f Author: Olof Johansson Date: Wed Oct 25 17:32:40 2006 -0500 [POWERPC] Make sure __cpu_preinit_ppc970 gets called on 970GX processors Add check for 970GX for __cpu_preinit_ppc970. Signed-off-by: Olof Johansson Signed-off-by: Paul Mackerras commit f4d4c354bca18210296cc0a8f592c0cdb720bf20 Author: Benjamin Herrenschmidt Date: Wed Oct 25 13:22:27 2006 +1000 [POWERPC] Fix CHRP platforms with only 8259 On CHRP platforms with only a 8259 controller, we should set the default IRQ host to the 8259 driver's one for the IRQ probing fallbacks to work in case the IRQ tree is incorrect (like on Pegasos for example). Without this fix, we get a bunch of WARN_ON's during boot. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras commit f49196a5f53aa62a964b08ffa2c59699a0c8eb53 Author: Scott Wood Date: Mon Oct 23 11:35:22 2006 -0500 [POWERPC] IPIC: Fix spinlock recursion in set_irq_handler This causes ipic_set_irq_type to set the handler directly rather than call set_irq_handler, which causes spinlock recursion because the lock is already held when ipic_set_irq_type is called. I'm also not convinced that ipic_set_irq_type should be changing the handler at all. There seem to be several controllers that don't and several that do. Those that do would break what appears to be a common usage of calling set_irq_chip_and_handler followed by set_irq_type, if a non-standard handler were to be used. OTOH, irq_create_of_mapping() doesn't set the handler, but only calls set_irq_type(). This patch gets things working in the spinlock-debugging-enabled case, but I'm curious as to where the handler setting is ideally supposed to be done. I don't see any documentation on set_irq_type() that clarifies what the semantics are supposed to be. Signed-off-by: Scott Wood Signed-off-by: Paul Mackerras commit f84c39da766b4c8f13872282f58286a57ad05b3e Author: Liu Dave-r63238 Date: Wed Oct 18 16:36:56 2006 +0800 [POWERPC] Fix the UCC rx/tx clock of QE MPC8323EMDS board ethernet interface with RMII uses the CLK16 divisor for the rx and tx clock, but the ucc_set_qe_mux_rxtx() function doesn't handle the CLK16 setting of the CMXUCR3 and CMXUCR4 registers. This fixes it. Signed-off-by: Dave Liu Signed-off-by: Paul Mackerras commit b910ecf6bf221bb06f37e44765307c42b20db205 Author: Arnd Bergmann Date: Tue Oct 24 18:01:43 2006 +0200 [POWERPC] cell: update defconfig =================================================================== Signed-off-by: Paul Mackerras commit 274cef5e9d0e494ad84dbc28513b0bb6e3d847ae Author: Arnd Bergmann Date: Tue Oct 24 18:01:42 2006 +0200 [POWERPC] spufs: fix another off-by-one bug in spufs_mbox_read Currently, spufs_mbox_read transfers more bytes than requested on a read. If you ask for four bytes, you get eight. This fixes it to transfer the largest multiple of four bytes that is less than or equal to the number you asked for. Note: one nasty property of this file in spufs is that you can only read multiples of four bytes in the first place, since there is no way to atomically put back a few bytes into the hardware register. Thus, reading less than four bytes returns -EINVAL. Asking for more than four returns the largest possible multiple of four. Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras commit f6b301b89b7bf0bb872da4f37dc28240413cbae7 Author: Dwayne Grant Mcconnell Date: Tue Oct 24 18:27:30 2006 +0200 [POWERPC] spufs: fix signal2 file to report signal2 This fixes the /signal2 file to actually give signal2 data. Signed-off-by: Dwayne Grant Mcconnell Signed-off-by: Arnd Bergmann Signed-off-by: Paul Mackerras commit e2100efb266c9335925191afe79f81f8d0a5807e Author: Benjamin Herrenschmidt Date: Fri Oct 20 11:49:54 2006 +1000 [POWERPC] Fix device_is_compatible() const warning Fix a const'ification related warning with device_is_compatible() and friends related to get_property() not properly having const on it's input device node argument. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras commit 859deea949c382d9ccb6397fe33df3703ecef45d Author: Benjamin Herrenschmidt Date: Fri Oct 20 14:37:05 2006 +1000 [POWERPC] Cell timebase bug workaround The Cell CPU timebase has an erratum. When reading the entire 64 bits of the timebase with one mftb instruction, there is a handful of cycles window during which one might read a value with the low order 32 bits already reset to 0x00000000 but the high order bits not yet incremeted by one. This fixes it by reading the timebase again until the low order 32 bits is no longer 0. That might introduce occasional latencies if hitting mftb just at the wrong time, but no more than 70ns on a cell blade, and that was considered acceptable. Signed-off-by: Benjamin Herrenschmidt Acked-by: Olof Johansson Signed-off-by: Paul Mackerras commit 21c4ff80cba5e24932f3ef79c8482c0491630b2b Author: Benjamin Herrenschmidt Date: Fri Oct 20 11:47:19 2006 +1000 [POWERPC] Support feature fixups in modules This patch adds support for feature fixups in modules. This involves adding support for R_PPC64_REL64 relocs to the 64 bits module loader. It also modifies modpost.c to ignore the powerpc fixup sections (or it would warn when used in .init.text). Signed-off-by: Benjamin Herrenschmidt Acked-by: Olof Johansson Signed-off-by: Paul Mackerras commit 0909c8c2d547e45ca50e2492b08ec93a37b35237 Author: Benjamin Herrenschmidt Date: Fri Oct 20 11:47:18 2006 +1000 [POWERPC] Support feature fixups in vdso's This patch reworks the feature fixup mecanism so vdso's can be fixed up. The main issue was that the construct: .long label (or .llong on 64 bits) will not work in the case of a shared library like the vdso. It will generate an empty placeholder in the fixup table along with a reloc, which is not something we can deal with in the vdso. The idea here (thanks Alan Modra !) is to instead use something like: 1: .long label - 1b That is, the feature fixup tables no longer contain addresses of bits of code to patch, but offsets of such code from the fixup table entry itself. That is properly resolved by ld when building the .so's. I've modified the fixup mecanism generically to use that method for the rest of the kernel as well. Another trick is that the 32 bits vDSO included in the 64 bits kernel need to have a table in the 64 bits format. However, gas does not support 32 bits code with a statement of the form: .llong label - 1b (Or even just .llong label) That is, it cannot emit the right fixup/relocation for the linker to use to assign a 32 bits address to an .llong field. Thus, in the specific case of the 32 bits vdso built as part of the 64 bits kernel, we are using a modified macro that generates: .long 0xffffffff .llong label - 1b Note that is assumes that the value is negative which is enforced by the .lds (those offsets are always negative as the .text is always before the fixup table and gas doesn't support emiting the reloc the other way around). Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras commit 7aeb732428fc8e2ecae6d432873770c12f04a979 Author: Benjamin Herrenschmidt Date: Fri Oct 20 11:47:16 2006 +1000 [POWERPC] Support nested cpu feature sections This patch adds some macros that can be used with an explicit label in order to nest cpu features. This should be used very careful but is necessary for the upcoming cell TB fixup. Signed-off-by: Benjamin Herrenschmidt Acked-by: Olof Johansson Signed-off-by: Paul Mackerras commit 42c4aaadb737e0e672b3fb86b2c41ff59f0fb8bc Author: Benjamin Herrenschmidt Date: Tue Oct 24 16:42:40 2006 +1000 [POWERPC] Consolidate feature fixup code There are currently two versions of the functions for applying the feature fixups, one for CPU features and one for firmware features. In addition, they are both in assembly and with separate implementations for 32 and 64 bits. identify_cpu() is also implemented in assembly and separately for 32 and 64 bits. This patch replaces them with a pair of C functions. The call sites are slightly moved on ppc64 as well to be called from C instead of from assembly, though it's a very small change, and thus shouldn't cause any problem. Signed-off-by: Benjamin Herrenschmidt Acked-by: Olof Johansson Signed-off-by: Paul Mackerras commit fb20f65a01a97bdf4bb746eecfc24a08561e2648 Author: Olaf Hering Date: Fri Oct 20 15:57:15 2006 +0200 [POWERPC] Fix hang in start_ldr if _end or _edata is unaligned Quick fix for lack of memset(__bss_start, 0, _end-__bss_start) in load_kernel(). If edata is unaligned, the loop will overwrite all memory because r3 and r4 will never be equal. Signed-off-by: Olaf Hering Signed-off-by: Paul Mackerras commit aa7a32cbdac50bb46a75722faa359993dab07c61 Author: Timur Tabi Date: Wed Oct 18 17:27:32 2006 -0500 [POWERPC] Fix spelling errors in ucc_fast.c and ucc_slow.c In ucc_fast.c and ucc_slow.c, "illegal" is twice spelled "illagal". Signed-off-by: Timur Tabi Signed-off-by: Paul Mackerras commit 3688a0f484e980771c078ab90f74a2656c339106 Author: Mark A. Greer Date: Wed Oct 18 14:38:09 2006 -0700 [POWERPC] Don't require execute perms on wrapper when building zImage.initrd Don't require that the wrapper script be executable when building zImage.initrds. This has already been fixed for zImages. Signed-off-by: Mark A. Greer Signed-off-by: Paul Mackerras commit 362ff7b2ac0234152b4a334dd006b77f4fa2ab23 Author: Jake Moilanen Date: Wed Oct 18 10:47:22 2006 -0500 [POWERPC] Add 970GX cputable entry 970GX cputable entry from Steve Winiecki. Signed-off-by: Jake Moilanen arch/powerpc/kernel/cputable.c | 15 +++++++++++++++ arch/powerpc/oprofile/op_model_power4.c | 2 +- include/asm-powerpc/reg.h | 1 + 3 files changed, 17 insertions(+), 1 deletion(-) Signed-off-by: Paul Mackerras commit 7f8c4c50bda13d27afc03679d25aa1fcac8df551 Author: Srinivasa Ds Date: Wed Oct 18 17:34:49 2006 +0530 [POWERPC] Fix build breakage with CONFIG_PPC32 low_cpu_die is called from the CPU hotplug code on 32-bit powermacs, but it is only defined if CONFIG_PM || CONFIG_CPU_FREQ_PMAC. This changes the ifdef so it is defined for CONFIG_HOTPLUG_CPU on 32-bit machines. Signed-off-by: Srinivasa DS Signed-off-by: Paul Mackerras commit c3386e40142e9d0c077460c2a548c4653fecaf15 Author: Zang Roy-r61911 Date: Wed Oct 18 11:18:58 2006 +0800 [POWERPC] Fix compiler warning message on get_property call This fixes the warning message from the return value of function get_property(), by making sure that the variable that receives the value is marked as const. Signed-off-by: Roy Zang -- Signed-off-by: Paul Mackerras commit cbcdb93d4443568f17e93610d240043ec5ac067b Author: Stephen Rothwell Date: Tue Oct 17 23:08:35 2006 +1000 [POWERPC] Simplify stolen time calculation In calculating stolen time, we were trying to actually account for time spent in the hypervisor. We don't really have enough information to do that accurately, so don't try. Instead, we now calculate stolen time as time that the current cpu thread is not actually dispatching instructions. On chips without a PURR, we cannot do this, so stolen time will always be zero. On chips with a PURR, this is merely the difference between the elapsed PURR values and the elapsed TB values. This gives us much more sane vaules from tools such as mpstat, even if they are still a bit strange e.g. 2 busy threads on one cpu will both appear to have 50% user time and 50% stolen time while 1 busy thread on a cpu will look like 100% user on one of them and 100% idle on the other. Signed-off-by: Stephen Rothwell Signed-off-by: Paul Mackerras Index: linux-2.6/arch/powerpc/boot/Makefile =================================================================== --- linux-2.6.orig/arch/powerpc/boot/Makefile +++ linux-2.6/arch/powerpc/boot/Makefile @@ -115,7 +115,7 @@ endif quiet_cmd_wrap = WRAP $@ cmd_wrap =$(wrapper) -c -o $@ -p $2 $(CROSSWRAP) vmlinux quiet_cmd_wrap_initrd = WRAP $@ - cmd_wrap_initrd =$(wrapper) -c -o $@ -p $2 $(CROSSWRAP) \ + cmd_wrap_initrd =$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) \ -i $(obj)/ramdisk.image.gz vmlinux $(obj)/zImage.chrp: vmlinux $(wrapperbits) Index: linux-2.6/arch/powerpc/configs/cell_defconfig =================================================================== --- linux-2.6.orig/arch/powerpc/configs/cell_defconfig +++ linux-2.6/arch/powerpc/configs/cell_defconfig @@ -254,6 +254,7 @@ CONFIG_SYN_COOKIES=y CONFIG_INET_TUNNEL=y CONFIG_INET_XFRM_MODE_TRANSPORT=y CONFIG_INET_XFRM_MODE_TUNNEL=y +# CONFIG_INET_XFRM_MODE_BEET is not set CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set @@ -275,7 +276,9 @@ CONFIG_INET6_XFRM_TUNNEL=m CONFIG_INET6_TUNNEL=m CONFIG_INET6_XFRM_MODE_TRANSPORT=y CONFIG_INET6_XFRM_MODE_TUNNEL=y +# CONFIG_INET6_XFRM_MODE_BEET is not set # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +# CONFIG_IPV6_SIT is not set CONFIG_IPV6_TUNNEL=m # CONFIG_IPV6_SUBTREES is not set # CONFIG_IPV6_MULTIPLE_TABLES is not set @@ -406,6 +409,12 @@ CONFIG_BLK_DEV_INITRD=y # CONFIG_ATA_OVER_ETH is not set # +# Misc devices +# +# CONFIG_SGI_IOC4 is not set +# CONFIG_TIFM_CORE is not set + +# # ATA/ATAPI/MFM/RLL support # CONFIG_IDE=y @@ -738,7 +747,6 @@ CONFIG_GEN_RTC=y # TPM devices # # CONFIG_TCG_TPM is not set -# CONFIG_TELCLOCK is not set # # I2C support @@ -802,6 +810,7 @@ CONFIG_I2C_ALGOBIT=y # # Dallas's 1-wire bus # +# CONFIG_W1 is not set # # Hardware Monitoring support @@ -810,14 +819,9 @@ CONFIG_I2C_ALGOBIT=y # CONFIG_HWMON_VID is not set # -# Misc devices -# - -# # Multimedia devices # # CONFIG_VIDEO_DEV is not set -CONFIG_VIDEO_V4L2=y # # Digital Video Broadcasting Devices @@ -923,6 +927,7 @@ CONFIG_EXT3_FS=y CONFIG_EXT3_FS_XATTR=y # CONFIG_EXT3_FS_POSIX_ACL is not set # CONFIG_EXT3_FS_SECURITY is not set +# CONFIG_EXT4DEV_FS is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set CONFIG_FS_MBCACHE=y @@ -930,6 +935,7 @@ CONFIG_FS_MBCACHE=y # CONFIG_JFS_FS is not set CONFIG_FS_POSIX_ACL=y # CONFIG_XFS_FS is not set +# CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set @@ -1129,6 +1135,7 @@ CONFIG_DEBUG_FS=y # CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_LIST is not set # CONFIG_FORCED_INLINING is not set +# CONFIG_HEADERS_CHECK is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_DEBUG_STACKOVERFLOW is not set # CONFIG_DEBUG_STACK_USAGE is not set Index: linux-2.6/arch/powerpc/kernel/cputable.c =================================================================== --- linux-2.6.orig/arch/powerpc/kernel/cputable.c +++ linux-2.6/arch/powerpc/kernel/cputable.c @@ -18,6 +18,7 @@ #include #include +#include /* for PTRRELOC on ARCH=ppc */ struct cpu_spec* cur_cpu_spec = NULL; EXPORT_SYMBOL(cur_cpu_spec); @@ -73,7 +74,7 @@ extern void __restore_cpu_ppc970(void); #define PPC_FEATURE_SPE_COMP 0 #endif -struct cpu_spec cpu_specs[] = { +static struct cpu_spec cpu_specs[] = { #ifdef CONFIG_PPC64 { /* Power3 */ .pvr_mask = 0xffff0000, @@ -227,6 +228,21 @@ struct cpu_spec cpu_specs[] = { .oprofile_type = PPC_OPROFILE_POWER4, .platform = "ppc970", }, + { /* PPC970GX */ + .pvr_mask = 0xffff0000, + .pvr_value = 0x00450000, + .cpu_name = "PPC970GX", + .cpu_features = CPU_FTRS_PPC970, + .cpu_user_features = COMMON_USER_POWER4 | + PPC_FEATURE_HAS_ALTIVEC_COMP, + .icache_bsize = 128, + .dcache_bsize = 128, + .num_pmcs = 8, + .cpu_setup = __setup_cpu_ppc970, + .oprofile_cpu_type = "ppc64/970", + .oprofile_type = PPC_OPROFILE_POWER4, + .platform = "ppc970", + }, { /* Power5 GR */ .pvr_mask = 0xffff0000, .pvr_value = 0x003a0000, @@ -1152,3 +1168,71 @@ struct cpu_spec cpu_specs[] = { #endif /* !CLASSIC_PPC */ #endif /* CONFIG_PPC32 */ }; + +struct cpu_spec *identify_cpu(unsigned long offset) +{ + struct cpu_spec *s = cpu_specs; + struct cpu_spec **cur = &cur_cpu_spec; + unsigned int pvr = mfspr(SPRN_PVR); + int i; + + s = PTRRELOC(s); + cur = PTRRELOC(cur); + + if (*cur != NULL) + return PTRRELOC(*cur); + + for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++) + if ((pvr & s->pvr_mask) == s->pvr_value) { + *cur = cpu_specs + i; +#ifdef CONFIG_PPC64 + /* ppc64 expects identify_cpu to also call setup_cpu + * for that processor. I will consolidate that at a + * later time, for now, just use our friend #ifdef. + * we also don't need to PTRRELOC the function pointer + * on ppc64 as we are running at 0 in real mode. + */ + if (s->cpu_setup) { + s->cpu_setup(offset, s); + } +#endif /* CONFIG_PPC64 */ + return s; + } + BUG(); + return NULL; +} + +void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end) +{ + struct fixup_entry { + unsigned long mask; + unsigned long value; + long start_off; + long end_off; + } *fcur, *fend; + + fcur = fixup_start; + fend = fixup_end; + + for (; fcur < fend; fcur++) { + unsigned int *pstart, *pend, *p; + + if ((value & fcur->mask) == fcur->value) + continue; + + /* These PTRRELOCs will disappear once the new scheme for + * modules and vdso is implemented + */ + pstart = ((unsigned int *)fcur) + (fcur->start_off / 4); + pend = ((unsigned int *)fcur) + (fcur->end_off / 4); + + for (p = pstart; p < pend; p++) { + *p = 0x60000000u; + asm volatile ("dcbst 0, %0" : : "r" (p)); + } + asm volatile ("sync" : : : "memory"); + for (p = pstart; p < pend; p++) + asm volatile ("icbi 0,%0" : : "r" (p)); + asm volatile ("sync; isync" : : : "memory"); + } +} Index: linux-2.6/arch/powerpc/kernel/head_64.S =================================================================== --- linux-2.6.orig/arch/powerpc/kernel/head_64.S +++ linux-2.6/arch/powerpc/kernel/head_64.S @@ -1580,11 +1580,6 @@ _STATIC(__start_initialization_iSeries) li r0,0 stdu r0,-STACK_FRAME_OVERHEAD(r1) - LOAD_REG_IMMEDIATE(r3,cpu_specs) - LOAD_REG_IMMEDIATE(r4,cur_cpu_spec) - li r5,0 - bl .identify_cpu - LOAD_REG_IMMEDIATE(r2,__toc_start) addi r2,r2,0x4000 addi r2,r2,0x4000 @@ -1646,6 +1641,8 @@ _GLOBAL(__start_initialization_multiplat cmpwi r0,0x3c /* 970FX */ beq 1f cmpwi r0,0x44 /* 970MP */ + beq 1f + cmpwi r0,0x45 /* 970GX */ bne 2f 1: bl .__cpu_preinit_ppc970 2: @@ -1964,13 +1961,6 @@ _STATIC(start_here_multiplatform) addi r2,r2,0x4000 add r2,r2,r26 - LOAD_REG_IMMEDIATE(r3, cpu_specs) - add r3,r3,r26 - LOAD_REG_IMMEDIATE(r4,cur_cpu_spec) - add r4,r4,r26 - mr r5,r26 - bl .identify_cpu - /* Do very early kernel initializations, including initial hash table, * stab and slb setup before we turn on relocation. */ @@ -2000,13 +1990,6 @@ _STATIC(start_here_common) li r0,0 stdu r0,-STACK_FRAME_OVERHEAD(r1) - /* Apply the CPUs-specific fixups (nop out sections not relevant - * to this CPU - */ - li r3,0 - bl .do_cpu_ftr_fixups - bl .do_fw_ftr_fixups - /* ptr to current */ LOAD_REG_IMMEDIATE(r4, init_task) std r4,PACACURRENT(r13) Index: linux-2.6/arch/powerpc/kernel/misc_32.S =================================================================== --- linux-2.6.orig/arch/powerpc/kernel/misc_32.S +++ linux-2.6/arch/powerpc/kernel/misc_32.S @@ -102,80 +102,6 @@ _GLOBAL(reloc_got2) blr /* - * identify_cpu, - * called with r3 = data offset and r4 = CPU number - * doesn't change r3 - */ -_GLOBAL(identify_cpu) - addis r8,r3,cpu_specs@ha - addi r8,r8,cpu_specs@l - mfpvr r7 -1: - lwz r5,CPU_SPEC_PVR_MASK(r8) - and r5,r5,r7 - lwz r6,CPU_SPEC_PVR_VALUE(r8) - cmplw 0,r6,r5 - beq 1f - addi r8,r8,CPU_SPEC_ENTRY_SIZE - b 1b -1: - addis r6,r3,cur_cpu_spec@ha - addi r6,r6,cur_cpu_spec@l - sub r8,r8,r3 - stw r8,0(r6) - blr - -/* - * do_cpu_ftr_fixups - goes through the list of CPU feature fixups - * and writes nop's over sections of code that don't apply for this cpu. - * r3 = data offset (not changed) - */ -_GLOBAL(do_cpu_ftr_fixups) - /* Get CPU 0 features */ - addis r6,r3,cur_cpu_spec@ha - addi r6,r6,cur_cpu_spec@l - lwz r4,0(r6) - add r4,r4,r3 - lwz r4,CPU_SPEC_FEATURES(r4) - - /* Get the fixup table */ - addis r6,r3,__start___ftr_fixup@ha - addi r6,r6,__start___ftr_fixup@l - addis r7,r3,__stop___ftr_fixup@ha - addi r7,r7,__stop___ftr_fixup@l - - /* Do the fixup */ -1: cmplw 0,r6,r7 - bgelr - addi r6,r6,16 - lwz r8,-16(r6) /* mask */ - and r8,r8,r4 - lwz r9,-12(r6) /* value */ - cmplw 0,r8,r9 - beq 1b - lwz r8,-8(r6) /* section begin */ - lwz r9,-4(r6) /* section end */ - subf. r9,r8,r9 - beq 1b - /* write nops over the section of code */ - /* todo: if large section, add a branch at the start of it */ - srwi r9,r9,2 - mtctr r9 - add r8,r8,r3 - lis r0,0x60000000@h /* nop */ -3: stw r0,0(r8) - andi. r10,r4,CPU_FTR_SPLIT_ID_CACHE@l - beq 2f - dcbst 0,r8 /* suboptimal, but simpler */ - sync - icbi 0,r8 -2: addi r8,r8,4 - bdnz 3b - sync /* additional sync needed on g4 */ - isync - b 1b - -/* * call_setup_cpu - call the setup_cpu function for this cpu * r3 = data offset, r24 = cpu number * Index: linux-2.6/arch/powerpc/kernel/misc_64.S =================================================================== --- linux-2.6.orig/arch/powerpc/kernel/misc_64.S +++ linux-2.6/arch/powerpc/kernel/misc_64.S @@ -246,130 +246,6 @@ _GLOBAL(__flush_dcache_icache) isync blr -/* - * identify_cpu and calls setup_cpu - * In: r3 = base of the cpu_specs array - * r4 = address of cur_cpu_spec - * r5 = relocation offset - */ -_GLOBAL(identify_cpu) - mfpvr r7 -1: - lwz r8,CPU_SPEC_PVR_MASK(r3) - and r8,r8,r7 - lwz r9,CPU_SPEC_PVR_VALUE(r3) - cmplw 0,r9,r8 - beq 1f - addi r3,r3,CPU_SPEC_ENTRY_SIZE - b 1b -1: - sub r0,r3,r5 - std r0,0(r4) - ld r4,CPU_SPEC_SETUP(r3) - cmpdi 0,r4,0 - add r4,r4,r5 - beqlr - ld r4,0(r4) - add r4,r4,r5 - mtctr r4 - /* Calling convention for cpu setup is r3=offset, r4=cur_cpu_spec */ - mr r4,r3 - mr r3,r5 - bctr - -/* - * do_cpu_ftr_fixups - goes through the list of CPU feature fixups - * and writes nop's over sections of code that don't apply for this cpu. - * r3 = data offset (not changed) - */ -_GLOBAL(do_cpu_ftr_fixups) - /* Get CPU 0 features */ - LOAD_REG_IMMEDIATE(r6,cur_cpu_spec) - sub r6,r6,r3 - ld r4,0(r6) - sub r4,r4,r3 - ld r4,CPU_SPEC_FEATURES(r4) - /* Get the fixup table */ - LOAD_REG_IMMEDIATE(r6,__start___ftr_fixup) - sub r6,r6,r3 - LOAD_REG_IMMEDIATE(r7,__stop___ftr_fixup) - sub r7,r7,r3 - /* Do the fixup */ -1: cmpld r6,r7 - bgelr - addi r6,r6,32 - ld r8,-32(r6) /* mask */ - and r8,r8,r4 - ld r9,-24(r6) /* value */ - cmpld r8,r9 - beq 1b - ld r8,-16(r6) /* section begin */ - ld r9,-8(r6) /* section end */ - subf. r9,r8,r9 - beq 1b - /* write nops over the section of code */ - /* todo: if large section, add a branch at the start of it */ - srwi r9,r9,2 - mtctr r9 - sub r8,r8,r3 - lis r0,0x60000000@h /* nop */ -3: stw r0,0(r8) - andi. r10,r4,CPU_FTR_SPLIT_ID_CACHE@l - beq 2f - dcbst 0,r8 /* suboptimal, but simpler */ - sync - icbi 0,r8 -2: addi r8,r8,4 - bdnz 3b - sync /* additional sync needed on g4 */ - isync - b 1b - -/* - * do_fw_ftr_fixups - goes through the list of firmware feature fixups - * and writes nop's over sections of code that don't apply for this firmware. - * r3 = data offset (not changed) - */ -_GLOBAL(do_fw_ftr_fixups) - /* Get firmware features */ - LOAD_REG_IMMEDIATE(r6,powerpc_firmware_features) - sub r6,r6,r3 - ld r4,0(r6) - /* Get the fixup table */ - LOAD_REG_IMMEDIATE(r6,__start___fw_ftr_fixup) - sub r6,r6,r3 - LOAD_REG_IMMEDIATE(r7,__stop___fw_ftr_fixup) - sub r7,r7,r3 - /* Do the fixup */ -1: cmpld r6,r7 - bgelr - addi r6,r6,32 - ld r8,-32(r6) /* mask */ - and r8,r8,r4 - ld r9,-24(r6) /* value */ - cmpld r8,r9 - beq 1b - ld r8,-16(r6) /* section begin */ - ld r9,-8(r6) /* section end */ - subf. r9,r8,r9 - beq 1b - /* write nops over the section of code */ - /* todo: if large section, add a branch at the start of it */ - srwi r9,r9,2 - mtctr r9 - sub r8,r8,r3 - lis r0,0x60000000@h /* nop */ -3: stw r0,0(r8) -BEGIN_FTR_SECTION - dcbst 0,r8 /* suboptimal, but simpler */ - sync - icbi 0,r8 -END_FTR_SECTION_IFSET(CPU_FTR_SPLIT_ID_CACHE) - addi r8,r8,4 - bdnz 3b - sync /* additional sync needed on g4 */ - isync - b 1b #if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) /* Index: linux-2.6/arch/powerpc/kernel/module_32.c =================================================================== --- linux-2.6.orig/arch/powerpc/kernel/module_32.c +++ linux-2.6/arch/powerpc/kernel/module_32.c @@ -24,6 +24,8 @@ #include #include +#include "setup.h" + #if 0 #define DEBUGP printk #else @@ -269,33 +271,50 @@ int apply_relocate_add(Elf32_Shdr *sechd return 0; } +static const Elf_Shdr *find_section(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, + const char *name) +{ + char *secstrings; + unsigned int i; + + secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; + for (i = 1; i < hdr->e_shnum; i++) + if (strcmp(secstrings+sechdrs[i].sh_name, name) == 0) + return &sechdrs[i]; + return NULL; +} + int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *me) { - char *secstrings; - unsigned int i; + const Elf_Shdr *sect; me->arch.bug_table = NULL; me->arch.num_bugs = 0; /* Find the __bug_table section, if present */ - secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; - for (i = 1; i < hdr->e_shnum; i++) { - if (strcmp(secstrings+sechdrs[i].sh_name, "__bug_table")) - continue; - me->arch.bug_table = (void *) sechdrs[i].sh_addr; - me->arch.num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry); - break; + sect = find_section(hdr, sechdrs, "__bug_table"); + if (sect != NULL) { + me->arch.bug_table = (void *) sect->sh_addr; + me->arch.num_bugs = sect->sh_size / sizeof(struct bug_entry); } - /* + /* * Strictly speaking this should have a spinlock to protect against * traversals, but since we only traverse on BUG()s, a spinlock * could potentially lead to deadlock and thus be counter-productive. */ list_add(&me->arch.bug_list, &module_bug_list); + /* Apply feature fixups */ + sect = find_section(hdr, sechdrs, "__ftr_fixup"); + if (sect != NULL) + do_feature_fixups(cur_cpu_spec->cpu_features, + (void *)sect->sh_addr, + (void *)sect->sh_addr + sect->sh_size); + return 0; } Index: linux-2.6/arch/powerpc/kernel/module_64.c =================================================================== --- linux-2.6.orig/arch/powerpc/kernel/module_64.c +++ linux-2.6/arch/powerpc/kernel/module_64.c @@ -22,6 +22,9 @@ #include #include #include +#include + +#include "setup.h" /* FIXME: We don't do .init separately. To do this, we'd need to have a separate r2 value in the init and core section, and stub between @@ -400,6 +403,11 @@ int apply_relocate_add(Elf64_Shdr *sechd | (value & 0x03fffffc); break; + case R_PPC64_REL64: + /* 64 bits relative (used by features fixups) */ + *location = value - (unsigned long)location; + break; + default: printk("%s: Unknown ADD relocation: %lu\n", me->name, @@ -413,23 +421,33 @@ int apply_relocate_add(Elf64_Shdr *sechd LIST_HEAD(module_bug_list); -int module_finalize(const Elf_Ehdr *hdr, - const Elf_Shdr *sechdrs, struct module *me) +static const Elf_Shdr *find_section(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, + const char *name) { char *secstrings; unsigned int i; + secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; + for (i = 1; i < hdr->e_shnum; i++) + if (strcmp(secstrings+sechdrs[i].sh_name, name) == 0) + return &sechdrs[i]; + return NULL; +} + +int module_finalize(const Elf_Ehdr *hdr, + const Elf_Shdr *sechdrs, struct module *me) +{ + const Elf_Shdr *sect; + me->arch.bug_table = NULL; me->arch.num_bugs = 0; /* Find the __bug_table section, if present */ - secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; - for (i = 1; i < hdr->e_shnum; i++) { - if (strcmp(secstrings+sechdrs[i].sh_name, "__bug_table")) - continue; - me->arch.bug_table = (void *) sechdrs[i].sh_addr; - me->arch.num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry); - break; + sect = find_section(hdr, sechdrs, "__bug_table"); + if (sect != NULL) { + me->arch.bug_table = (void *) sect->sh_addr; + me->arch.num_bugs = sect->sh_size / sizeof(struct bug_entry); } /* @@ -439,6 +457,19 @@ int module_finalize(const Elf_Ehdr *hdr, */ list_add(&me->arch.bug_list, &module_bug_list); + /* Apply feature fixups */ + sect = find_section(hdr, sechdrs, "__ftr_fixup"); + if (sect != NULL) + do_feature_fixups(cur_cpu_spec->cpu_features, + (void *)sect->sh_addr, + (void *)sect->sh_addr + sect->sh_size); + + sect = find_section(hdr, sechdrs, "__fw_ftr_fixup"); + if (sect != NULL) + do_feature_fixups(powerpc_firmware_features, + (void *)sect->sh_addr, + (void *)sect->sh_addr + sect->sh_size); + return 0; } Index: linux-2.6/arch/powerpc/kernel/prom.c =================================================================== --- linux-2.6.orig/arch/powerpc/kernel/prom.c +++ linux-2.6/arch/powerpc/kernel/prom.c @@ -1014,7 +1014,7 @@ EXPORT_SYMBOL(find_all_nodes); /** Checks if the given "compat" string matches one of the strings in * the device's "compatible" property */ -int device_is_compatible(struct device_node *device, const char *compat) +int device_is_compatible(const struct device_node *device, const char *compat) { const char* cp; int cplen, l; @@ -1491,7 +1491,8 @@ static int __init prom_reconfig_setup(vo __initcall(prom_reconfig_setup); #endif -struct property *of_find_property(struct device_node *np, const char *name, +struct property *of_find_property(const struct device_node *np, + const char *name, int *lenp) { struct property *pp; @@ -1512,7 +1513,8 @@ struct property *of_find_property(struct * Find a property with a given name for a given node * and return the value. */ -const void *get_property(struct device_node *np, const char *name, int *lenp) +const void *get_property(const struct device_node *np, const char *name, + int *lenp) { struct property *pp = of_find_property(np,name,lenp); return pp ? pp->value : NULL; Index: linux-2.6/arch/powerpc/kernel/setup_32.c =================================================================== --- linux-2.6.orig/arch/powerpc/kernel/setup_32.c +++ linux-2.6/arch/powerpc/kernel/setup_32.c @@ -95,6 +95,7 @@ int ucache_bsize; unsigned long __init early_init(unsigned long dt_ptr) { unsigned long offset = reloc_offset(); + struct cpu_spec *spec; /* First zero the BSS -- use memset_io, some platforms don't have * caches on yet */ @@ -104,8 +105,11 @@ unsigned long __init early_init(unsigned * Identify the CPU type and fix up code sections * that depend on which cpu we have. */ - identify_cpu(offset, 0); - do_cpu_ftr_fixups(offset); + spec = identify_cpu(offset); + + do_feature_fixups(spec->cpu_features, + PTRRELOC(&__start___ftr_fixup), + PTRRELOC(&__stop___ftr_fixup)); return KERNELBASE + offset; } Index: linux-2.6/arch/powerpc/kernel/setup_64.c =================================================================== --- linux-2.6.orig/arch/powerpc/kernel/setup_64.c +++ linux-2.6/arch/powerpc/kernel/setup_64.c @@ -175,6 +175,9 @@ void __init setup_paca(int cpu) void __init early_setup(unsigned long dt_ptr) { + /* Identify CPU type */ + identify_cpu(0); + /* Assume we're on cpu 0 for now. Don't write to the paca yet! */ setup_paca(0); @@ -353,6 +356,14 @@ void __init setup_system(void) { DBG(" -> setup_system()\n"); + /* Apply the CPUs-specific and firmware specific fixups to kernel + * text (nop out sections not relevant to this CPU or this firmware) + */ + do_feature_fixups(cur_cpu_spec->cpu_features, + &__start___ftr_fixup, &__stop___ftr_fixup); + do_feature_fixups(powerpc_firmware_features, + &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup); + /* * Unflatten the device-tree passed by prom_init or kexec */ Index: linux-2.6/arch/powerpc/kernel/time.c =================================================================== --- linux-2.6.orig/arch/powerpc/kernel/time.c +++ linux-2.6/arch/powerpc/kernel/time.c @@ -221,11 +221,8 @@ static void account_process_time(struct */ struct cpu_purr_data { int initialized; /* thread is running */ - u64 tb0; /* timebase at origin time */ - u64 purr0; /* PURR at origin time */ u64 tb; /* last TB value read */ u64 purr; /* last PURR value read */ - u64 stolen; /* stolen time so far */ spinlock_t lock; }; @@ -235,10 +232,8 @@ static void snapshot_tb_and_purr(void *d { struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data); - p->tb0 = mftb(); - p->purr0 = mfspr(SPRN_PURR); - p->tb = p->tb0; - p->purr = 0; + p->tb = mftb(); + p->purr = mfspr(SPRN_PURR); wmb(); p->initialized = 1; } @@ -259,37 +254,24 @@ void snapshot_timebases(void) void calculate_steal_time(void) { - u64 tb, purr, t0; + u64 tb, purr; s64 stolen; - struct cpu_purr_data *p0, *pme, *phim; - int cpu; + struct cpu_purr_data *pme; if (!cpu_has_feature(CPU_FTR_PURR)) return; - cpu = smp_processor_id(); - pme = &per_cpu(cpu_purr_data, cpu); + pme = &per_cpu(cpu_purr_data, smp_processor_id()); if (!pme->initialized) return; /* this can happen in early boot */ - p0 = &per_cpu(cpu_purr_data, cpu & ~1); - phim = &per_cpu(cpu_purr_data, cpu ^ 1); - spin_lock(&p0->lock); + spin_lock(&pme->lock); tb = mftb(); - purr = mfspr(SPRN_PURR) - pme->purr0; - if (!phim->initialized || !cpu_online(cpu ^ 1)) { - stolen = (tb - pme->tb) - (purr - pme->purr); - } else { - t0 = pme->tb0; - if (phim->tb0 < t0) - t0 = phim->tb0; - stolen = phim->tb - t0 - phim->purr - purr - p0->stolen; - } - if (stolen > 0) { + purr = mfspr(SPRN_PURR); + stolen = (tb - pme->tb) - (purr - pme->purr); + if (stolen > 0) account_steal_time(current, stolen); - p0->stolen += stolen; - } pme->tb = tb; pme->purr = purr; - spin_unlock(&p0->lock); + spin_unlock(&pme->lock); } /* @@ -298,30 +280,17 @@ void calculate_steal_time(void) */ static void snapshot_purr(void) { - int cpu; - u64 purr; - struct cpu_purr_data *p0, *pme, *phim; + struct cpu_purr_data *pme; unsigned long flags; if (!cpu_has_feature(CPU_FTR_PURR)) return; - cpu = smp_processor_id(); - pme = &per_cpu(cpu_purr_data, cpu); - p0 = &per_cpu(cpu_purr_data, cpu & ~1); - phim = &per_cpu(cpu_purr_data, cpu ^ 1); - spin_lock_irqsave(&p0->lock, flags); - pme->tb = pme->tb0 = mftb(); - purr = mfspr(SPRN_PURR); - if (!phim->initialized) { - pme->purr = 0; - pme->purr0 = purr; - } else { - /* set p->purr and p->purr0 for no change in p0->stolen */ - pme->purr = phim->tb - phim->tb0 - phim->purr - p0->stolen; - pme->purr0 = purr - pme->purr; - } + pme = &per_cpu(cpu_purr_data, smp_processor_id()); + spin_lock_irqsave(&pme->lock, flags); + pme->tb = mftb(); + pme->purr = mfspr(SPRN_PURR); pme->initialized = 1; - spin_unlock_irqrestore(&p0->lock, flags); + spin_unlock_irqrestore(&pme->lock, flags); } #endif /* CONFIG_PPC_SPLPAR */ Index: linux-2.6/arch/powerpc/kernel/vdso.c =================================================================== --- linux-2.6.orig/arch/powerpc/kernel/vdso.c +++ linux-2.6/arch/powerpc/kernel/vdso.c @@ -36,6 +36,8 @@ #include #include +#include "setup.h" + #undef DEBUG #ifdef DEBUG @@ -586,6 +588,43 @@ static __init int vdso_fixup_datapage(st return 0; } + +static __init int vdso_fixup_features(struct lib32_elfinfo *v32, + struct lib64_elfinfo *v64) +{ + void *start32; + unsigned long size32; + +#ifdef CONFIG_PPC64 + void *start64; + unsigned long size64; + + start64 = find_section64(v64->hdr, "__ftr_fixup", &size64); + if (start64) + do_feature_fixups(cur_cpu_spec->cpu_features, + start64, start64 + size64); + + start64 = find_section64(v64->hdr, "__fw_ftr_fixup", &size64); + if (start64) + do_feature_fixups(powerpc_firmware_features, + start64, start64 + size64); +#endif /* CONFIG_PPC64 */ + + start32 = find_section32(v32->hdr, "__ftr_fixup", &size32); + if (start32) + do_feature_fixups(cur_cpu_spec->cpu_features, + start32, start32 + size32); + +#ifdef CONFIG_PPC64 + start32 = find_section32(v32->hdr, "__fw_ftr_fixup", &size32); + if (start32) + do_feature_fixups(powerpc_firmware_features, + start32, start32 + size32); +#endif /* CONFIG_PPC64 */ + + return 0; +} + static __init int vdso_fixup_alt_funcs(struct lib32_elfinfo *v32, struct lib64_elfinfo *v64) { @@ -634,6 +673,9 @@ static __init int vdso_setup(void) if (vdso_fixup_datapage(&v32, &v64)) return -1; + if (vdso_fixup_features(&v32, &v64)) + return -1; + if (vdso_fixup_alt_funcs(&v32, &v64)) return -1; @@ -714,6 +756,7 @@ void __init vdso_init(void) * Setup the syscall map in the vDOS */ vdso_setup_syscall_map(); + /* * Initialize the vDSO images in memory, that is do necessary * fixups of vDSO symbols, locate trampolines, etc... Index: linux-2.6/arch/powerpc/kernel/vdso32/vdso32.lds.S =================================================================== --- linux-2.6.orig/arch/powerpc/kernel/vdso32/vdso32.lds.S +++ linux-2.6/arch/powerpc/kernel/vdso32/vdso32.lds.S @@ -32,6 +32,18 @@ SECTIONS PROVIDE (_etext = .); PROVIDE (etext = .); + . = ALIGN(8); + __ftr_fixup : { + *(__ftr_fixup) + } + +#ifdef CONFIG_PPC64 + . = ALIGN(8); + __fw_ftr_fixup : { + *(__fw_ftr_fixup) + } +#endif + /* Other stuff is appended to the text segment: */ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } .rodata1 : { *(.rodata1) } Index: linux-2.6/arch/powerpc/kernel/vdso64/gettimeofday.S =================================================================== --- linux-2.6.orig/arch/powerpc/kernel/vdso64/gettimeofday.S +++ linux-2.6/arch/powerpc/kernel/vdso64/gettimeofday.S @@ -229,8 +229,10 @@ V_FUNCTION_BEGIN(__do_get_xsec) xor r0,r8,r8 /* create dependency */ add r3,r3,r0 - /* Get TB & offset it */ - mftb r7 + /* Get TB & offset it. We use the MFTB macro which will generate + * workaround code for Cell. + */ + MFTB(r7) ld r9,CFG_TB_ORIG_STAMP(r3) subf r7,r9,r7 Index: linux-2.6/arch/powerpc/kernel/vdso64/vdso64.lds.S =================================================================== --- linux-2.6.orig/arch/powerpc/kernel/vdso64/vdso64.lds.S +++ linux-2.6/arch/powerpc/kernel/vdso64/vdso64.lds.S @@ -31,6 +31,16 @@ SECTIONS PROVIDE (_etext = .); PROVIDE (etext = .); + . = ALIGN(8); + __ftr_fixup : { + *(__ftr_fixup) + } + + . = ALIGN(8); + __fw_ftr_fixup : { + *(__fw_ftr_fixup) + } + /* Other stuff is appended to the text segment: */ .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } .rodata1 : { *(.rodata1) } Index: linux-2.6/arch/powerpc/oprofile/op_model_power4.c =================================================================== --- linux-2.6.orig/arch/powerpc/oprofile/op_model_power4.c +++ linux-2.6/arch/powerpc/oprofile/op_model_power4.c @@ -76,7 +76,7 @@ static inline int mmcra_must_set_sample( { if (__is_processor(PV_POWER4) || __is_processor(PV_POWER4p) || __is_processor(PV_970) || __is_processor(PV_970FX) || - __is_processor(PV_970MP)) + __is_processor(PV_970MP) || __is_processor(PV_970GX)) return 1; return 0; Index: linux-2.6/arch/powerpc/platforms/cell/spufs/file.c =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/file.c +++ linux-2.6/arch/powerpc/platforms/cell/spufs/file.c @@ -385,7 +385,7 @@ static ssize_t spufs_mbox_read(struct fi udata = (void __user *)buf; spu_acquire(ctx); - for (count = 0; count <= len; count += 4, udata++) { + for (count = 0; (count + 4) <= len; count += 4, udata++) { int ret; ret = ctx->ops->mbox_read(ctx, &mbox_data); if (ret == 0) Index: linux-2.6/arch/powerpc/platforms/cell/spufs/hw_ops.c =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/cell/spufs/hw_ops.c +++ linux-2.6/arch/powerpc/platforms/cell/spufs/hw_ops.c @@ -147,7 +147,7 @@ static void spu_hw_signal1_write(struct static u32 spu_hw_signal2_read(struct spu_context *ctx) { - return in_be32(&ctx->spu->problem->signal_notify1); + return in_be32(&ctx->spu->problem->signal_notify2); } static void spu_hw_signal2_write(struct spu_context *ctx, u32 data) Index: linux-2.6/arch/powerpc/platforms/chrp/setup.c =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/chrp/setup.c +++ linux-2.6/arch/powerpc/platforms/chrp/setup.c @@ -478,8 +478,10 @@ static void __init chrp_find_8259(void) " address, polling\n"); i8259_init(pic, chrp_int_ack); - if (ppc_md.get_irq == NULL) + if (ppc_md.get_irq == NULL) { ppc_md.get_irq = i8259_irq; + irq_set_default_host(i8259_get_host()); + } if (chrp_mpic != NULL) { cascade_irq = irq_of_parse_and_map(pic, 0); if (cascade_irq == NO_IRQ) Index: linux-2.6/arch/powerpc/platforms/iseries/setup.c =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/iseries/setup.c +++ linux-2.6/arch/powerpc/platforms/iseries/setup.c @@ -694,6 +694,11 @@ void * __init iSeries_early_setup(void) { unsigned long phys_mem_size; + /* Identify CPU type. This is done again by the common code later + * on but calling this function multiple times is fine. + */ + identify_cpu(0); + powerpc_firmware_features |= FW_FEATURE_ISERIES; powerpc_firmware_features |= FW_FEATURE_LPAR; Index: linux-2.6/arch/powerpc/platforms/powermac/sleep.S =================================================================== --- linux-2.6.orig/arch/powerpc/platforms/powermac/sleep.S +++ linux-2.6/arch/powerpc/platforms/powermac/sleep.S @@ -45,7 +45,8 @@ .section .text .align 5 -#if defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ_PMAC) +#if defined(CONFIG_PM) || defined(CONFIG_CPU_FREQ_PMAC) || \ + (defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32)) /* This gets called by via-pmu.c late during the sleep process. * The PMU was already send the sleep command and will shut us down Index: linux-2.6/arch/powerpc/sysdev/i8259.c =================================================================== --- linux-2.6.orig/arch/powerpc/sysdev/i8259.c +++ linux-2.6/arch/powerpc/sysdev/i8259.c @@ -224,6 +224,11 @@ static struct irq_host_ops i8259_host_op .xlate = i8259_host_xlate, }; +struct irq_host *i8259_get_host(void) +{ + return i8259_host; +} + /** * i8259_init - Initialize the legacy controller * @node: device node of the legacy PIC (can be NULL, but then, it will match Index: linux-2.6/arch/powerpc/sysdev/ipic.c =================================================================== --- linux-2.6.orig/arch/powerpc/sysdev/ipic.c +++ linux-2.6/arch/powerpc/sysdev/ipic.c @@ -473,9 +473,9 @@ static int ipic_set_irq_type(unsigned in desc->status |= flow_type & IRQ_TYPE_SENSE_MASK; if (flow_type & IRQ_TYPE_LEVEL_LOW) { desc->status |= IRQ_LEVEL; - set_irq_handler(virq, handle_level_irq); + desc->handle_irq = handle_level_irq; } else { - set_irq_handler(virq, handle_edge_irq); + desc->handle_irq = handle_edge_irq; } /* only EXT IRQ senses are programmable on ipic Index: linux-2.6/arch/powerpc/sysdev/qe_lib/ucc.c =================================================================== --- linux-2.6.orig/arch/powerpc/sysdev/qe_lib/ucc.c +++ linux-2.6/arch/powerpc/sysdev/qe_lib/ucc.c @@ -207,6 +207,7 @@ int ucc_set_qe_mux_rxtx(int ucc_num, enu case QE_CLK18: source = 8; break; case QE_CLK7: source = 9; break; case QE_CLK8: source = 10; break; + case QE_CLK16: source = 11; break; default: source = -1; break; } break; @@ -222,6 +223,7 @@ int ucc_set_qe_mux_rxtx(int ucc_num, enu case QE_CLK22: source = 8; break; case QE_CLK7: source = 9; break; case QE_CLK8: source = 10; break; + case QE_CLK16: source = 11; break; default: source = -1; break; } break; Index: linux-2.6/arch/powerpc/sysdev/qe_lib/ucc_fast.c =================================================================== --- linux-2.6.orig/arch/powerpc/sysdev/qe_lib/ucc_fast.c +++ linux-2.6/arch/powerpc/sysdev/qe_lib/ucc_fast.c @@ -163,7 +163,7 @@ int ucc_fast_init(struct ucc_fast_info * /* check if the UCC port number is in range. */ if ((uf_info->ucc_num < 0) || (uf_info->ucc_num > UCC_MAX_NUM - 1)) { - uccf_err("ucc_fast_init: Illagal UCC number!"); + uccf_err("ucc_fast_init: Illegal UCC number!"); return -EINVAL; } Index: linux-2.6/arch/powerpc/sysdev/qe_lib/ucc_slow.c =================================================================== --- linux-2.6.orig/arch/powerpc/sysdev/qe_lib/ucc_slow.c +++ linux-2.6/arch/powerpc/sysdev/qe_lib/ucc_slow.c @@ -152,7 +152,7 @@ int ucc_slow_init(struct ucc_slow_info * /* check if the UCC port number is in range. */ if ((us_info->ucc_num < 0) || (us_info->ucc_num > UCC_MAX_NUM - 1)) { - uccs_err("ucc_slow_init: Illagal UCC number!"); + uccs_err("ucc_slow_init: Illegal UCC number!"); return -EINVAL; } Index: linux-2.6/arch/powerpc/sysdev/tsi108_dev.c =================================================================== --- linux-2.6.orig/arch/powerpc/sysdev/tsi108_dev.c +++ linux-2.6/arch/powerpc/sysdev/tsi108_dev.c @@ -49,7 +49,7 @@ phys_addr_t get_csrbase(void) tsi = of_find_node_by_type(NULL, "tsi-bridge"); if (tsi) { unsigned int size; - void *prop = get_property(tsi, "reg", &size); + const void *prop = get_property(tsi, "reg", &size); tsi108_csr_base = of_translate_address(tsi, prop); of_node_put(tsi); }; @@ -80,7 +80,7 @@ static int __init tsi108_eth_of_init(voi hw_info tsi_eth_data; unsigned int *id; unsigned int *phy_id; - void *mac_addr; + const void *mac_addr; phandle *ph; memset(r, 0, sizeof(r)); Index: linux-2.6/arch/ppc/boot/simple/relocate.S =================================================================== --- linux-2.6.orig/arch/ppc/boot/simple/relocate.S +++ linux-2.6/arch/ppc/boot/simple/relocate.S @@ -154,8 +154,8 @@ do_relocate_out: start_ldr: /* Clear all of BSS and set up stack for C calls */ - lis r3,edata@h - ori r3,r3,edata@l + lis r3,__bss_start@h + ori r3,r3,__bss_start@l lis r4,end@h ori r4,r4,end@l subi r3,r3,4 @@ -163,7 +163,7 @@ start_ldr: li r0,0 50: stwu r0,4(r3) cmpw cr0,r3,r4 - bne 50b + blt 50b 90: mr r9,r1 /* Save old stack pointer (in case it matters) */ lis r1,.stack@h ori r1,r1,.stack@l Index: linux-2.6/arch/ppc/kernel/misc.S =================================================================== --- linux-2.6.orig/arch/ppc/kernel/misc.S +++ linux-2.6/arch/ppc/kernel/misc.S @@ -110,80 +110,6 @@ _GLOBAL(reloc_got2) blr /* - * identify_cpu, - * called with r3 = data offset and r4 = CPU number - * doesn't change r3 - */ -_GLOBAL(identify_cpu) - addis r8,r3,cpu_specs@ha - addi r8,r8,cpu_specs@l - mfpvr r7 -1: - lwz r5,CPU_SPEC_PVR_MASK(r8) - and r5,r5,r7 - lwz r6,CPU_SPEC_PVR_VALUE(r8) - cmplw 0,r6,r5 - beq 1f - addi r8,r8,CPU_SPEC_ENTRY_SIZE - b 1b -1: - addis r6,r3,cur_cpu_spec@ha - addi r6,r6,cur_cpu_spec@l - sub r8,r8,r3 - stw r8,0(r6) - blr - -/* - * do_cpu_ftr_fixups - goes through the list of CPU feature fixups - * and writes nop's over sections of code that don't apply for this cpu. - * r3 = data offset (not changed) - */ -_GLOBAL(do_cpu_ftr_fixups) - /* Get CPU 0 features */ - addis r6,r3,cur_cpu_spec@ha - addi r6,r6,cur_cpu_spec@l - lwz r4,0(r6) - add r4,r4,r3 - lwz r4,CPU_SPEC_FEATURES(r4) - - /* Get the fixup table */ - addis r6,r3,__start___ftr_fixup@ha - addi r6,r6,__start___ftr_fixup@l - addis r7,r3,__stop___ftr_fixup@ha - addi r7,r7,__stop___ftr_fixup@l - - /* Do the fixup */ -1: cmplw 0,r6,r7 - bgelr - addi r6,r6,16 - lwz r8,-16(r6) /* mask */ - and r8,r8,r4 - lwz r9,-12(r6) /* value */ - cmplw 0,r8,r9 - beq 1b - lwz r8,-8(r6) /* section begin */ - lwz r9,-4(r6) /* section end */ - subf. r9,r8,r9 - beq 1b - /* write nops over the section of code */ - /* todo: if large section, add a branch at the start of it */ - srwi r9,r9,2 - mtctr r9 - add r8,r8,r3 - lis r0,0x60000000@h /* nop */ -3: stw r0,0(r8) - andi. r10,r4,CPU_FTR_SPLIT_ID_CACHE@l - beq 2f - dcbst 0,r8 /* suboptimal, but simpler */ - sync - icbi 0,r8 -2: addi r8,r8,4 - bdnz 3b - sync /* additional sync needed on g4 */ - isync - b 1b - -/* * call_setup_cpu - call the setup_cpu function for this cpu * r3 = data offset, r24 = cpu number * Index: linux-2.6/arch/ppc/kernel/setup.c =================================================================== --- linux-2.6.orig/arch/ppc/kernel/setup.c +++ linux-2.6/arch/ppc/kernel/setup.c @@ -38,6 +38,7 @@ #include #include #include +#include #define USES_PPC_SYS (defined(CONFIG_85xx) || defined(CONFIG_83xx) || \ defined(CONFIG_MPC10X_BRIDGE) || defined(CONFIG_8260) || \ @@ -53,8 +54,6 @@ extern void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7); -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); extern void ppc6xx_idle(void); @@ -305,6 +304,7 @@ early_init(int r3, int r4, int r5) { unsigned long phys; unsigned long offset = reloc_offset(); + struct cpu_spec *spec; /* Default */ phys = offset + KERNELBASE; @@ -317,8 +317,10 @@ early_init(int r3, int r4, int r5) * Identify the CPU type and fix up code sections * that depend on which cpu we have. */ - identify_cpu(offset, 0); - do_cpu_ftr_fixups(offset); + spec = identify_cpu(offset); + do_feature_fixups(spec->cpu_features, + PTRRELOC(&__start___ftr_fixup), + PTRRELOC(&__stop___ftr_fixup)); return phys; } Index: linux-2.6/include/asm-powerpc/asm-compat.h =================================================================== --- linux-2.6.orig/include/asm-powerpc/asm-compat.h +++ linux-2.6/include/asm-powerpc/asm-compat.h @@ -14,6 +14,58 @@ # define ASM_CONST(x) __ASM_CONST(x) #endif + +/* + * Feature section common macros + * + * Note that the entries now contain offsets between the table entry + * and the code rather than absolute code pointers in order to be + * useable with the vdso shared library. There is also an assumption + * that values will be negative, that is, the fixup table has to be + * located after the code it fixes up. + */ +#ifdef CONFIG_PPC64 +#ifdef __powerpc64__ +/* 64 bits kernel, 64 bits code */ +#define MAKE_FTR_SECTION_ENTRY(msk, val, label, sect) \ +99: \ + .section sect,"a"; \ + .align 3; \ +98: \ + .llong msk; \ + .llong val; \ + .llong label##b-98b; \ + .llong 99b-98b; \ + .previous +#else /* __powerpc64__ */ +/* 64 bits kernel, 32 bits code (ie. vdso32) */ +#define MAKE_FTR_SECTION_ENTRY(msk, val, label, sect) \ +99: \ + .section sect,"a"; \ + .align 3; \ +98: \ + .llong msk; \ + .llong val; \ + .long 0xffffffff; \ + .long label##b-98b; \ + .long 0xffffffff; \ + .long 99b-98b; \ + .previous +#endif /* !__powerpc64__ */ +#else /* CONFIG_PPC64 */ +/* 32 bits kernel, 32 bits code */ +#define MAKE_FTR_SECTION_ENTRY(msk, val, label, sect) \ +99: \ + .section sect,"a"; \ + .align 2; \ +98: \ + .long msk; \ + .long val; \ + .long label##b-98b; \ + .long 99b-98b; \ + .previous +#endif /* !CONFIG_PPC64 */ + #ifdef __powerpc64__ /* operations for longs and pointers */ Index: linux-2.6/include/asm-powerpc/cputable.h =================================================================== --- linux-2.6.orig/include/asm-powerpc/cputable.h +++ linux-2.6/include/asm-powerpc/cputable.h @@ -89,8 +89,11 @@ struct cpu_spec { extern struct cpu_spec *cur_cpu_spec; -extern void identify_cpu(unsigned long offset, unsigned long cpu); -extern void do_cpu_ftr_fixups(unsigned long offset); +extern unsigned int __start___ftr_fixup, __stop___ftr_fixup; + +extern struct cpu_spec *identify_cpu(unsigned long offset); +extern void do_feature_fixups(unsigned long value, void *fixup_start, + void *fixup_end); #endif /* __ASSEMBLY__ */ @@ -144,6 +147,7 @@ extern void do_cpu_ftr_fixups(unsigned l #define CPU_FTR_CI_LARGE_PAGE LONG_ASM_CONST(0x0000100000000000) #define CPU_FTR_PAUSE_ZERO LONG_ASM_CONST(0x0000200000000000) #define CPU_FTR_PURR LONG_ASM_CONST(0x0000400000000000) +#define CPU_FTR_CELL_TB_BUG LONG_ASM_CONST(0x0000800000000000) #ifndef __ASSEMBLY__ @@ -332,7 +336,7 @@ extern void do_cpu_ftr_fixups(unsigned l #define CPU_FTRS_CELL (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \ CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \ - CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE) + CPU_FTR_PAUSE_ZERO | CPU_FTR_CI_LARGE_PAGE | CPU_FTR_CELL_TB_BUG) #define CPU_FTRS_PA6T (CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | \ CPU_FTR_HPTE_TABLE | CPU_FTR_PPCAS_ARCH_V2 | \ CPU_FTR_ALTIVEC_COMP | CPU_FTR_CI_LARGE_PAGE | \ @@ -431,29 +435,12 @@ static inline int cpu_has_feature(unsign #ifdef __ASSEMBLY__ -#define BEGIN_FTR_SECTION 98: - -#ifndef __powerpc64__ +#define BEGIN_FTR_SECTION_NESTED(label) label: +#define BEGIN_FTR_SECTION BEGIN_FTR_SECTION_NESTED(97) +#define END_FTR_SECTION_NESTED(msk, val, label) \ + MAKE_FTR_SECTION_ENTRY(msk, val, label, __ftr_fixup) #define END_FTR_SECTION(msk, val) \ -99: \ - .section __ftr_fixup,"a"; \ - .align 2; \ - .long msk; \ - .long val; \ - .long 98b; \ - .long 99b; \ - .previous -#else /* __powerpc64__ */ -#define END_FTR_SECTION(msk, val) \ -99: \ - .section __ftr_fixup,"a"; \ - .align 3; \ - .llong msk; \ - .llong val; \ - .llong 98b; \ - .llong 99b; \ - .previous -#endif /* __powerpc64__ */ + END_FTR_SECTION_NESTED(msk, val, 97) #define END_FTR_SECTION_IFSET(msk) END_FTR_SECTION((msk), (msk)) #define END_FTR_SECTION_IFCLR(msk) END_FTR_SECTION((msk), 0) Index: linux-2.6/include/asm-powerpc/firmware.h =================================================================== --- linux-2.6.orig/include/asm-powerpc/firmware.h +++ linux-2.6/include/asm-powerpc/firmware.h @@ -96,19 +96,16 @@ extern void machine_check_fwnmi(void); /* This is true if we are using the firmware NMI handler (typically LPAR) */ extern int fwnmi_active; -#else /* __ASSEMBLY__ */ +extern unsigned int __start___fw_ftr_fixup, __stop___fw_ftr_fixup; -#define BEGIN_FW_FTR_SECTION 96: +#else /* __ASSEMBLY__ */ +#define BEGIN_FW_FTR_SECTION_NESTED(label) label: +#define BEGIN_FW_FTR_SECTION BEGIN_FW_FTR_SECTION_NESTED(97) +#define END_FW_FTR_SECTION_NESTED(msk, val, label) \ + MAKE_FTR_SECTION_ENTRY(msk, val, label, __fw_ftr_fixup) #define END_FW_FTR_SECTION(msk, val) \ -97: \ - .section __fw_ftr_fixup,"a"; \ - .align 3; \ - .llong msk; \ - .llong val; \ - .llong 96b; \ - .llong 97b; \ - .previous + END_FW_FTR_SECTION_NESTED(msk, val, 97) #define END_FW_FTR_SECTION_IFSET(msk) END_FW_FTR_SECTION((msk), (msk)) #define END_FW_FTR_SECTION_IFCLR(msk) END_FW_FTR_SECTION((msk), 0) Index: linux-2.6/include/asm-powerpc/i8259.h =================================================================== --- linux-2.6.orig/include/asm-powerpc/i8259.h +++ linux-2.6/include/asm-powerpc/i8259.h @@ -7,6 +7,7 @@ #ifdef CONFIG_PPC_MERGE extern void i8259_init(struct device_node *node, unsigned long intack_addr); extern unsigned int i8259_irq(struct pt_regs *regs); +extern struct irq_host *i8259_get_host(void); #else extern void i8259_init(unsigned long intack_addr, int offset); extern int i8259_irq(struct pt_regs *regs); Index: linux-2.6/include/asm-powerpc/ppc_asm.h =================================================================== --- linux-2.6.orig/include/asm-powerpc/ppc_asm.h +++ linux-2.6/include/asm-powerpc/ppc_asm.h @@ -30,9 +30,9 @@ BEGIN_FTR_SECTION; \ mfspr ra,SPRN_PURR; /* get processor util. reg */ \ END_FTR_SECTION_IFSET(CPU_FTR_PURR); \ BEGIN_FTR_SECTION; \ - mftb ra; /* or get TB if no PURR */ \ + MFTB(ra); /* or get TB if no PURR */ \ END_FTR_SECTION_IFCLR(CPU_FTR_PURR); \ - ld rb,PACA_STARTPURR(r13); \ + ld rb,PACA_STARTPURR(r13); \ std ra,PACA_STARTPURR(r13); \ subf rb,rb,ra; /* subtract start value */ \ ld ra,PACA_USER_TIME(r13); \ @@ -45,9 +45,9 @@ BEGIN_FTR_SECTION; \ mfspr ra,SPRN_PURR; /* get processor util. reg */ \ END_FTR_SECTION_IFSET(CPU_FTR_PURR); \ BEGIN_FTR_SECTION; \ - mftb ra; /* or get TB if no PURR */ \ + MFTB(ra); /* or get TB if no PURR */ \ END_FTR_SECTION_IFCLR(CPU_FTR_PURR); \ - ld rb,PACA_STARTPURR(r13); \ + ld rb,PACA_STARTPURR(r13); \ std ra,PACA_STARTPURR(r13); \ subf rb,rb,ra; /* subtract start value */ \ ld ra,PACA_SYSTEM_TIME(r13); \ @@ -274,6 +274,16 @@ END_FTR_SECTION_IFSET(CPU_FTR_601) #define ISYNC_601 #endif +#ifdef CONFIG_PPC_CELL +#define MFTB(dest) \ +90: mftb dest; \ +BEGIN_FTR_SECTION_NESTED(96); \ + cmpwi dest,0; \ + beq- 90b; \ +END_FTR_SECTION_NESTED(CPU_FTR_CELL_TB_BUG, CPU_FTR_CELL_TB_BUG, 96) +#else +#define MFTB(dest) mftb dest +#endif #ifndef CONFIG_SMP #define TLBSYNC Index: linux-2.6/include/asm-powerpc/prom.h =================================================================== --- linux-2.6.orig/include/asm-powerpc/prom.h +++ linux-2.6/include/asm-powerpc/prom.h @@ -134,7 +134,7 @@ extern struct device_node *of_find_all_n extern struct device_node *of_get_parent(const struct device_node *node); extern struct device_node *of_get_next_child(const struct device_node *node, struct device_node *prev); -extern struct property *of_find_property(struct device_node *np, +extern struct property *of_find_property(const struct device_node *np, const char *name, int *lenp); extern struct device_node *of_node_get(struct device_node *node); @@ -158,10 +158,12 @@ extern void of_detach_node(const struct extern void finish_device_tree(void); extern void unflatten_device_tree(void); extern void early_init_devtree(void *); -extern int device_is_compatible(struct device_node *device, const char *); +extern int device_is_compatible(const struct device_node *device, + const char *); extern int machine_is_compatible(const char *compat); -extern const void *get_property(struct device_node *node, const char *name, - int *lenp); +extern const void *get_property(const struct device_node *node, + const char *name, + int *lenp); extern void print_properties(struct device_node *node); extern int prom_n_addr_cells(struct device_node* np); extern int prom_n_size_cells(struct device_node* np); Index: linux-2.6/include/asm-powerpc/reg.h =================================================================== --- linux-2.6.orig/include/asm-powerpc/reg.h +++ linux-2.6/include/asm-powerpc/reg.h @@ -591,6 +591,7 @@ #define PV_630 0x0040 #define PV_630p 0x0041 #define PV_970MP 0x0044 +#define PV_970GX 0x0045 #define PV_BE 0x0070 #define PV_PA6T 0x0090 @@ -618,10 +619,35 @@ : "=r" (rval)); rval;}) #define mtspr(rn, v) asm volatile("mtspr " __stringify(rn) ",%0" : : "r" (v)) +#ifdef __powerpc64__ +#ifdef CONFIG_PPC_CELL +#define mftb() ({unsigned long rval; \ + asm volatile( \ + "90: mftb %0;\n" \ + "97: cmpwi %0,0;\n" \ + " beq- 90b;\n" \ + "99:\n" \ + ".section __ftr_fixup,\"a\"\n" \ + ".align 3\n" \ + "98:\n" \ + " .llong %1\n" \ + " .llong %1\n" \ + " .llong 97b-98b\n" \ + " .llong 99b-98b\n" \ + ".previous" \ + : "=r" (rval) : "i" (CPU_FTR_CELL_TB_BUG)); rval;}) +#else #define mftb() ({unsigned long rval; \ asm volatile("mftb %0" : "=r" (rval)); rval;}) +#endif /* !CONFIG_PPC_CELL */ + +#else /* __powerpc64__ */ + #define mftbl() ({unsigned long rval; \ asm volatile("mftbl %0" : "=r" (rval)); rval;}) +#define mftbu() ({unsigned long rval; \ + asm volatile("mftbu %0" : "=r" (rval)); rval;}) +#endif /* !__powerpc64__ */ #define mttbl(v) asm volatile("mttbl %0":: "r"(v)) #define mttbu(v) asm volatile("mttbu %0":: "r"(v)) Index: linux-2.6/include/asm-powerpc/time.h =================================================================== --- linux-2.6.orig/include/asm-powerpc/time.h +++ linux-2.6/include/asm-powerpc/time.h @@ -82,30 +82,35 @@ struct div_result { #define __USE_RTC() 0 #endif -/* On ppc64 this gets us the whole timebase; on ppc32 just the lower half */ +#ifdef CONFIG_PPC64 + +/* For compatibility, get_tbl() is defined as get_tb() on ppc64 */ +#define get_tbl get_tb + +#else + static inline unsigned long get_tbl(void) { - unsigned long tbl; - #if defined(CONFIG_403GCX) + unsigned long tbl; asm volatile("mfspr %0, 0x3dd" : "=r" (tbl)); + return tbl; #else - asm volatile("mftb %0" : "=r" (tbl)); + return mftbl(); #endif - return tbl; } static inline unsigned int get_tbu(void) { +#ifdef CONFIG_403GCX unsigned int tbu; - -#if defined(CONFIG_403GCX) asm volatile("mfspr %0, 0x3dc" : "=r" (tbu)); + return tbu; #else - asm volatile("mftbu %0" : "=r" (tbu)); + return mftbu(); #endif - return tbu; } +#endif /* !CONFIG_PPC64 */ static inline unsigned int get_rtcl(void) { @@ -131,7 +136,7 @@ static inline u64 get_tb(void) { return mftb(); } -#else +#else /* CONFIG_PPC64 */ static inline u64 get_tb(void) { unsigned int tbhi, tblo, tbhi2; @@ -144,7 +149,7 @@ static inline u64 get_tb(void) return ((u64)tbhi << 32) | tblo; } -#endif +#endif /* !CONFIG_PPC64 */ static inline void set_tb(unsigned int upper, unsigned int lower) { Index: linux-2.6/include/asm-powerpc/timex.h =================================================================== --- linux-2.6.orig/include/asm-powerpc/timex.h +++ linux-2.6/include/asm-powerpc/timex.h @@ -8,6 +8,7 @@ */ #include +#include #define CLOCK_TICK_RATE 1024000 /* Underlying HZ */ @@ -15,13 +16,11 @@ typedef unsigned long cycles_t; static inline cycles_t get_cycles(void) { - cycles_t ret; - #ifdef __powerpc64__ - - __asm__ __volatile__("mftb %0" : "=r" (ret) : ); - + return mftb(); #else + cycles_t ret; + /* * For the "cycle" counter we use the timebase lower half. * Currently only used on SMP. @@ -30,18 +29,19 @@ static inline cycles_t get_cycles(void) ret = 0; __asm__ __volatile__( - "98: mftb %0\n" + "97: mftb %0\n" "99:\n" ".section __ftr_fixup,\"a\"\n" + ".align 2\n" + "98:\n" " .long %1\n" " .long 0\n" - " .long 98b\n" - " .long 99b\n" + " .long 97b-98b\n" + " .long 99b-98b\n" ".previous" : "=r" (ret) : "i" (CPU_FTR_601)); -#endif - return ret; +#endif } #endif /* __KERNEL__ */ Index: linux-2.6/scripts/mod/modpost.c =================================================================== --- linux-2.6.orig/scripts/mod/modpost.c +++ linux-2.6/scripts/mod/modpost.c @@ -910,6 +910,8 @@ static int init_section_ref_ok(const cha ".fixup", ".smp_locks", ".plt", /* seen on ARCH=um build on x86_64. Harmless */ + "__ftr_fixup", /* powerpc cpu feature fixup */ + "__fw_ftr_fixup", /* powerpc firmware feature fixup */ NULL }; /* Start of section names */