diff options
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r-- | arch/powerpc/kernel/entry_64.S | 18 | ||||
-rw-r--r-- | arch/powerpc/kernel/head_64.S | 28 | ||||
-rw-r--r-- | arch/powerpc/kernel/misc_64.S | 46 | ||||
-rw-r--r-- | arch/powerpc/kernel/pci_64.c | 58 | ||||
-rw-r--r-- | arch/powerpc/kernel/vmlinux.lds.S | 8 |
5 files changed, 121 insertions, 37 deletions
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 2cd872b5283..748e74fcf54 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -27,10 +27,7 @@ #include <asm/ppc_asm.h> #include <asm/asm-offsets.h> #include <asm/cputable.h> - -#ifdef CONFIG_PPC_ISERIES -#define DO_SOFT_DISABLE -#endif +#include <asm/firmware.h> /* * System calls. @@ -91,6 +88,7 @@ system_call_common: ld r11,exception_marker@toc(r2) std r11,-16(r9) /* "regshere" marker */ #ifdef CONFIG_PPC_ISERIES +BEGIN_FW_FTR_SECTION /* Hack for handling interrupts when soft-enabling on iSeries */ cmpdi cr1,r0,0x5555 /* syscall 0x5555 */ andi. r10,r12,MSR_PR /* from kernel */ @@ -98,6 +96,7 @@ system_call_common: beq hardware_interrupt_entry lbz r10,PACAPROCENABLED(r13) std r10,SOFTE(r1) +END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) #endif mfmsr r11 ori r11,r11,MSR_EE @@ -462,6 +461,7 @@ _GLOBAL(ret_from_except_lite) restore: #ifdef CONFIG_PPC_ISERIES +BEGIN_FW_FTR_SECTION ld r5,SOFTE(r1) cmpdi 0,r5,0 beq 4f @@ -480,6 +480,7 @@ restore: b .ret_from_except_lite /* loop back and handle more */ 4: stb r5,PACAPROCENABLED(r13) +END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) #endif ld r3,_MSR(r1) @@ -538,18 +539,23 @@ do_work: lwz r8,TI_PREEMPT(r9) cmpwi cr1,r8,0 #ifdef CONFIG_PPC_ISERIES +BEGIN_FW_FTR_SECTION ld r0,SOFTE(r1) cmpdi r0,0 -#else - andi. r0,r3,MSR_EE +END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) #endif +BEGIN_FW_FTR_SECTION + andi. r0,r3,MSR_EE +END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) crandc eq,cr1*4+eq,eq bne restore /* here we are preempting the current task */ 1: #ifdef CONFIG_PPC_ISERIES +BEGIN_FW_FTR_SECTION li r0,1 stb r0,PACAPROCENABLED(r13) +END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) #endif ori r10,r10,MSR_EE mtmsrd r10,1 /* reenable interrupts */ diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 3065b472b95..645c7f10fb2 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S @@ -33,6 +33,7 @@ #include <asm/hvcall.h> #include <asm/iseries/lpar_map.h> #include <asm/thread_info.h> +#include <asm/firmware.h> #ifdef CONFIG_PPC_ISERIES #define DO_SOFT_DISABLE @@ -365,19 +366,28 @@ label##_iSeries: \ #ifdef DO_SOFT_DISABLE #define DISABLE_INTS \ +BEGIN_FW_FTR_SECTION; \ lbz r10,PACAPROCENABLED(r13); \ li r11,0; \ std r10,SOFTE(r1); \ mfmsr r10; \ stb r11,PACAPROCENABLED(r13); \ ori r10,r10,MSR_EE; \ - mtmsrd r10,1 + mtmsrd r10,1; \ +END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) #define ENABLE_INTS \ +BEGIN_FW_FTR_SECTION; \ lbz r10,PACAPROCENABLED(r13); \ mfmsr r11; \ std r10,SOFTE(r1); \ ori r11,r11,MSR_EE; \ +END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES); \ +BEGIN_FW_FTR_SECTION; \ + ld r12,_MSR(r1); \ + mfmsr r11; \ + rlwimi r11,r12,0,MSR_EE; \ +END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES); \ mtmsrd r11,1 #else /* hard enable/disable interrupts */ @@ -1071,8 +1081,10 @@ _GLOBAL(slb_miss_realmode) ld r3,PACA_EXSLB+EX_R3(r13) lwz r9,PACA_EXSLB+EX_CCR(r13) /* get saved CR */ #ifdef CONFIG_PPC_ISERIES +BEGIN_FW_FTR_SECTION ld r11,PACALPPACAPTR(r13) ld r11,LPPACASRR0(r11) /* get SRR0 value */ +END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) #endif /* CONFIG_PPC_ISERIES */ mtlr r10 @@ -1087,8 +1099,10 @@ _GLOBAL(slb_miss_realmode) .machine pop #ifdef CONFIG_PPC_ISERIES +BEGIN_FW_FTR_SECTION mtspr SPRN_SRR0,r11 mtspr SPRN_SRR1,r12 +END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) #endif /* CONFIG_PPC_ISERIES */ ld r9,PACA_EXSLB+EX_R9(r13) ld r10,PACA_EXSLB+EX_R10(r13) @@ -1301,6 +1315,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB) cmpdi r3,0 /* see if hash_page succeeded */ #ifdef DO_SOFT_DISABLE +BEGIN_FW_FTR_SECTION /* * If we had interrupts soft-enabled at the point where the * DSI/ISI occurred, and an interrupt came in during hash_page, @@ -1321,12 +1336,14 @@ END_FTR_SECTION_IFCLR(CPU_FTR_SLB) ld r3,SOFTE(r1) bl .local_irq_restore b 11f -#else +END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) +#endif +BEGIN_FW_FTR_SECTION beq fast_exception_return /* Return from exception on success */ ble- 12f /* Failure return from hash_page */ /* fall through */ -#endif +END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) /* Here we have a page fault that hash_page can't handle. */ _GLOBAL(handle_page_fault) @@ -1861,7 +1878,9 @@ _GLOBAL(__secondary_start) LOAD_REG_ADDR(r3, .start_secondary_prolog) LOAD_REG_IMMEDIATE(r4, MSR_KERNEL) #ifdef DO_SOFT_DISABLE +BEGIN_FW_FTR_SECTION ori r4,r4,MSR_EE +END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) #endif mtspr SPRN_SRR0,r3 mtspr SPRN_SRR1,r4 @@ -1986,6 +2005,7 @@ _STATIC(start_here_common) */ li r3,0 bl .do_cpu_ftr_fixups + bl .do_fw_ftr_fixups /* ptr to current */ LOAD_REG_IMMEDIATE(r4, init_task) @@ -2000,11 +2020,13 @@ _STATIC(start_here_common) /* Load up the kernel context */ 5: #ifdef DO_SOFT_DISABLE +BEGIN_FW_FTR_SECTION li r5,0 stb r5,PACAPROCENABLED(r13) /* Soft Disabled */ mfmsr r5 ori r5,r5,MSR_EE /* Hard Enabled */ mtmsrd r5 +END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) #endif bl .start_kernel diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index 9c54eccad99..41521b30c3c 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S @@ -325,6 +325,52 @@ _GLOBAL(do_cpu_ftr_fixups) 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) /* * Do an IO access in real mode diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index c1b1e14775e..78d3c0fc8df 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c @@ -30,6 +30,7 @@ #include <asm/byteorder.h> #include <asm/machdep.h> #include <asm/ppc-pci.h> +#include <asm/firmware.h> #ifdef DEBUG #include <asm/udbg.h> @@ -209,7 +210,6 @@ void pcibios_free_controller(struct pci_controller *phb) kfree(phb); } -#ifndef CONFIG_PPC_ISERIES void __devinit pcibios_claim_one_bus(struct pci_bus *b) { struct pci_dev *dev; @@ -238,10 +238,12 @@ static void __init pcibios_claim_of_setup(void) { struct pci_bus *b; + if (firmware_has_feature(FW_FEATURE_ISERIES)) + return; + list_for_each_entry(b, &pci_root_buses, node) pcibios_claim_one_bus(b); } -#endif #ifdef CONFIG_PPC_MULTIPLATFORM static u32 get_int_prop(struct device_node *np, const char *name, u32 def) @@ -554,9 +556,8 @@ static int __init pcibios_init(void) */ ppc_md.phys_mem_access_prot = pci_phys_mem_access_prot; -#ifdef CONFIG_PPC_ISERIES - iSeries_pcibios_init(); -#endif + if (firmware_has_feature(FW_FEATURE_ISERIES)) + iSeries_pcibios_init(); printk(KERN_DEBUG "PCI: Probing PCI hardware\n"); @@ -566,15 +567,15 @@ static int __init pcibios_init(void) pci_bus_add_devices(hose->bus); } -#ifndef CONFIG_PPC_ISERIES - if (pci_probe_only) - pcibios_claim_of_setup(); - else - /* FIXME: `else' will be removed when - pci_assign_unassigned_resources() is able to work - correctly with [partially] allocated PCI tree. */ - pci_assign_unassigned_resources(); -#endif /* !CONFIG_PPC_ISERIES */ + if (!firmware_has_feature(FW_FEATURE_ISERIES)) { + if (pci_probe_only) + pcibios_claim_of_setup(); + else + /* FIXME: `else' will be removed when + pci_assign_unassigned_resources() is able to work + correctly with [partially] allocated PCI tree. */ + pci_assign_unassigned_resources(); + } /* Call machine dependent final fixup */ if (ppc_md.pcibios_fixup) @@ -586,8 +587,9 @@ static int __init pcibios_init(void) printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev)); #ifdef CONFIG_PPC_MULTIPLATFORM - /* map in PCI I/O space */ - phbs_remap_io(); + if (!firmware_has_feature(FW_FEATURE_ISERIES)) + /* map in PCI I/O space */ + phbs_remap_io(); #endif printk(KERN_DEBUG "PCI: Probing PCI hardware done\n"); @@ -637,13 +639,13 @@ int pcibios_enable_device(struct pci_dev *dev, int mask) */ int pci_domain_nr(struct pci_bus *bus) { -#ifdef CONFIG_PPC_ISERIES - return 0; -#else - struct pci_controller *hose = pci_bus_to_host(bus); + if (firmware_has_feature(FW_FEATURE_ISERIES)) + return 0; + else { + struct pci_controller *hose = pci_bus_to_host(bus); - return hose->global_number; -#endif + return hose->global_number; + } } EXPORT_SYMBOL(pci_domain_nr); @@ -651,12 +653,12 @@ EXPORT_SYMBOL(pci_domain_nr); /* Decide whether to display the domain number in /proc */ int pci_proc_domain(struct pci_bus *bus) { -#ifdef CONFIG_PPC_ISERIES - return 0; -#else - struct pci_controller *hose = pci_bus_to_host(bus); - return hose->buid; -#endif + if (firmware_has_feature(FW_FEATURE_ISERIES)) + return 0; + else { + struct pci_controller *hose = pci_bus_to_host(bus); + return hose->buid; + } } /* diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index 02665a02130..cb0e8d46c3e 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S @@ -132,6 +132,14 @@ SECTIONS *(__ftr_fixup) __stop___ftr_fixup = .; } +#ifdef CONFIG_PPC64 + . = ALIGN(8); + __fw_ftr_fixup : { + __start___fw_ftr_fixup = .; + *(__fw_ftr_fixup) + __stop___fw_ftr_fixup = .; + } +#endif . = ALIGN(PAGE_SIZE); .init.ramfs : { |