diff options
Diffstat (limited to 'arch/powerpc/kernel')
44 files changed, 2254 insertions, 860 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 9619285f64e8..569f79ccd310 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
| @@ -33,10 +33,10 @@ obj-y := cputable.o ptrace.o syscalls.o \ | |||
| 33 | obj-y += vdso32/ | 33 | obj-y += vdso32/ |
| 34 | obj-$(CONFIG_PPC64) += setup_64.o sys_ppc32.o \ | 34 | obj-$(CONFIG_PPC64) += setup_64.o sys_ppc32.o \ |
| 35 | signal_64.o ptrace32.o \ | 35 | signal_64.o ptrace32.o \ |
| 36 | paca.o cpu_setup_ppc970.o \ | 36 | paca.o nvram_64.o firmware.o |
| 37 | cpu_setup_pa6t.o \ | 37 | obj-$(CONFIG_PPC_BOOK3S_64) += cpu_setup_ppc970.o cpu_setup_pa6t.o |
| 38 | firmware.o nvram_64.o | ||
| 39 | obj64-$(CONFIG_RELOCATABLE) += reloc_64.o | 38 | obj64-$(CONFIG_RELOCATABLE) += reloc_64.o |
| 39 | obj-$(CONFIG_PPC_BOOK3E_64) += exceptions-64e.o | ||
| 40 | obj-$(CONFIG_PPC64) += vdso64/ | 40 | obj-$(CONFIG_PPC64) += vdso64/ |
| 41 | obj-$(CONFIG_ALTIVEC) += vecemu.o | 41 | obj-$(CONFIG_ALTIVEC) += vecemu.o |
| 42 | obj-$(CONFIG_PPC_970_NAP) += idle_power4.o | 42 | obj-$(CONFIG_PPC_970_NAP) += idle_power4.o |
| @@ -63,8 +63,8 @@ obj-$(CONFIG_MODULES) += module.o module_$(CONFIG_WORD_SIZE).o | |||
| 63 | obj-$(CONFIG_44x) += cpu_setup_44x.o | 63 | obj-$(CONFIG_44x) += cpu_setup_44x.o |
| 64 | obj-$(CONFIG_FSL_BOOKE) += cpu_setup_fsl_booke.o dbell.o | 64 | obj-$(CONFIG_FSL_BOOKE) += cpu_setup_fsl_booke.o dbell.o |
| 65 | 65 | ||
| 66 | extra-$(CONFIG_PPC_STD_MMU) := head_32.o | 66 | extra-y := head_$(CONFIG_WORD_SIZE).o |
| 67 | extra-$(CONFIG_PPC64) := head_64.o | 67 | extra-$(CONFIG_PPC_BOOK3E_32) := head_new_booke.o |
| 68 | extra-$(CONFIG_40x) := head_40x.o | 68 | extra-$(CONFIG_40x) := head_40x.o |
| 69 | extra-$(CONFIG_44x) := head_44x.o | 69 | extra-$(CONFIG_44x) := head_44x.o |
| 70 | extra-$(CONFIG_FSL_BOOKE) := head_fsl_booke.o | 70 | extra-$(CONFIG_FSL_BOOKE) := head_fsl_booke.o |
| @@ -88,7 +88,7 @@ obj-$(CONFIG_SWIOTLB) += dma-swiotlb.o | |||
| 88 | 88 | ||
| 89 | pci64-$(CONFIG_PPC64) += pci_dn.o isa-bridge.o | 89 | pci64-$(CONFIG_PPC64) += pci_dn.o isa-bridge.o |
| 90 | obj-$(CONFIG_PCI) += pci_$(CONFIG_WORD_SIZE).o $(pci64-y) \ | 90 | obj-$(CONFIG_PCI) += pci_$(CONFIG_WORD_SIZE).o $(pci64-y) \ |
| 91 | pci-common.o | 91 | pci-common.o pci_of_scan.o |
| 92 | obj-$(CONFIG_PCI_MSI) += msi.o | 92 | obj-$(CONFIG_PCI_MSI) += msi.o |
| 93 | obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o \ | 93 | obj-$(CONFIG_KEXEC) += machine_kexec.o crash.o \ |
| 94 | machine_kexec_$(CONFIG_WORD_SIZE).o | 94 | machine_kexec_$(CONFIG_WORD_SIZE).o |
| @@ -115,6 +115,13 @@ ifneq ($(CONFIG_XMON)$(CONFIG_KEXEC),) | |||
| 115 | obj-y += ppc_save_regs.o | 115 | obj-y += ppc_save_regs.o |
| 116 | endif | 116 | endif |
| 117 | 117 | ||
| 118 | # Disable GCOV in odd or sensitive code | ||
| 119 | GCOV_PROFILE_prom_init.o := n | ||
| 120 | GCOV_PROFILE_ftrace.o := n | ||
| 121 | GCOV_PROFILE_machine_kexec_64.o := n | ||
| 122 | GCOV_PROFILE_machine_kexec_32.o := n | ||
| 123 | GCOV_PROFILE_kprobes.o := n | ||
| 124 | |||
| 118 | extra-$(CONFIG_PPC_FPU) += fpu.o | 125 | extra-$(CONFIG_PPC_FPU) += fpu.o |
| 119 | extra-$(CONFIG_ALTIVEC) += vector.o | 126 | extra-$(CONFIG_ALTIVEC) += vector.o |
| 120 | extra-$(CONFIG_PPC64) += entry_64.o | 127 | extra-$(CONFIG_PPC64) += entry_64.o |
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 197b15646eeb..f0df285f0f87 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
| @@ -52,9 +52,11 @@ | |||
| 52 | #include <linux/kvm_host.h> | 52 | #include <linux/kvm_host.h> |
| 53 | #endif | 53 | #endif |
| 54 | 54 | ||
| 55 | #ifdef CONFIG_PPC32 | ||
| 55 | #if defined(CONFIG_BOOKE) || defined(CONFIG_40x) | 56 | #if defined(CONFIG_BOOKE) || defined(CONFIG_40x) |
| 56 | #include "head_booke.h" | 57 | #include "head_booke.h" |
| 57 | #endif | 58 | #endif |
| 59 | #endif | ||
| 58 | 60 | ||
| 59 | #if defined(CONFIG_FSL_BOOKE) | 61 | #if defined(CONFIG_FSL_BOOKE) |
| 60 | #include "../mm/mmu_decl.h" | 62 | #include "../mm/mmu_decl.h" |
| @@ -140,6 +142,20 @@ int main(void) | |||
| 140 | context.high_slices_psize)); | 142 | context.high_slices_psize)); |
| 141 | DEFINE(MMUPSIZEDEFSIZE, sizeof(struct mmu_psize_def)); | 143 | DEFINE(MMUPSIZEDEFSIZE, sizeof(struct mmu_psize_def)); |
| 142 | #endif /* CONFIG_PPC_MM_SLICES */ | 144 | #endif /* CONFIG_PPC_MM_SLICES */ |
| 145 | |||
| 146 | #ifdef CONFIG_PPC_BOOK3E | ||
| 147 | DEFINE(PACAPGD, offsetof(struct paca_struct, pgd)); | ||
| 148 | DEFINE(PACA_KERNELPGD, offsetof(struct paca_struct, kernel_pgd)); | ||
| 149 | DEFINE(PACA_EXGEN, offsetof(struct paca_struct, exgen)); | ||
| 150 | DEFINE(PACA_EXTLB, offsetof(struct paca_struct, extlb)); | ||
| 151 | DEFINE(PACA_EXMC, offsetof(struct paca_struct, exmc)); | ||
| 152 | DEFINE(PACA_EXCRIT, offsetof(struct paca_struct, excrit)); | ||
| 153 | DEFINE(PACA_EXDBG, offsetof(struct paca_struct, exdbg)); | ||
| 154 | DEFINE(PACA_MC_STACK, offsetof(struct paca_struct, mc_kstack)); | ||
| 155 | DEFINE(PACA_CRIT_STACK, offsetof(struct paca_struct, crit_kstack)); | ||
| 156 | DEFINE(PACA_DBG_STACK, offsetof(struct paca_struct, dbg_kstack)); | ||
| 157 | #endif /* CONFIG_PPC_BOOK3E */ | ||
| 158 | |||
| 143 | #ifdef CONFIG_PPC_STD_MMU_64 | 159 | #ifdef CONFIG_PPC_STD_MMU_64 |
| 144 | DEFINE(PACASTABREAL, offsetof(struct paca_struct, stab_real)); | 160 | DEFINE(PACASTABREAL, offsetof(struct paca_struct, stab_real)); |
| 145 | DEFINE(PACASTABVIRT, offsetof(struct paca_struct, stab_addr)); | 161 | DEFINE(PACASTABVIRT, offsetof(struct paca_struct, stab_addr)); |
| @@ -262,6 +278,7 @@ int main(void) | |||
| 262 | DEFINE(_SRR1, STACK_FRAME_OVERHEAD+sizeof(struct pt_regs)+8); | 278 | DEFINE(_SRR1, STACK_FRAME_OVERHEAD+sizeof(struct pt_regs)+8); |
| 263 | #endif /* CONFIG_PPC64 */ | 279 | #endif /* CONFIG_PPC64 */ |
| 264 | 280 | ||
| 281 | #if defined(CONFIG_PPC32) | ||
| 265 | #if defined(CONFIG_BOOKE) || defined(CONFIG_40x) | 282 | #if defined(CONFIG_BOOKE) || defined(CONFIG_40x) |
| 266 | DEFINE(EXC_LVL_SIZE, STACK_EXC_LVL_FRAME_SIZE); | 283 | DEFINE(EXC_LVL_SIZE, STACK_EXC_LVL_FRAME_SIZE); |
| 267 | DEFINE(MAS0, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas0)); | 284 | DEFINE(MAS0, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, mas0)); |
| @@ -280,7 +297,7 @@ int main(void) | |||
| 280 | DEFINE(_DSRR1, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, dsrr1)); | 297 | DEFINE(_DSRR1, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, dsrr1)); |
| 281 | DEFINE(SAVED_KSP_LIMIT, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, saved_ksp_limit)); | 298 | DEFINE(SAVED_KSP_LIMIT, STACK_INT_FRAME_SIZE+offsetof(struct exception_regs, saved_ksp_limit)); |
| 282 | #endif | 299 | #endif |
| 283 | 300 | #endif | |
| 284 | DEFINE(CLONE_VM, CLONE_VM); | 301 | DEFINE(CLONE_VM, CLONE_VM); |
| 285 | DEFINE(CLONE_UNTRACED, CLONE_UNTRACED); | 302 | DEFINE(CLONE_UNTRACED, CLONE_UNTRACED); |
| 286 | 303 | ||
diff --git a/arch/powerpc/kernel/cpu_setup_6xx.S b/arch/powerpc/kernel/cpu_setup_6xx.S index 1e9949e68856..55cba4a8a959 100644 --- a/arch/powerpc/kernel/cpu_setup_6xx.S +++ b/arch/powerpc/kernel/cpu_setup_6xx.S | |||
| @@ -21,7 +21,7 @@ _GLOBAL(__setup_cpu_603) | |||
| 21 | mflr r4 | 21 | mflr r4 |
| 22 | BEGIN_MMU_FTR_SECTION | 22 | BEGIN_MMU_FTR_SECTION |
| 23 | li r10,0 | 23 | li r10,0 |
| 24 | mtspr SPRN_SPRG4,r10 /* init SW LRU tracking */ | 24 | mtspr SPRN_SPRG_603_LRU,r10 /* init SW LRU tracking */ |
| 25 | END_MMU_FTR_SECTION_IFSET(MMU_FTR_NEED_DTLB_SW_LRU) | 25 | END_MMU_FTR_SECTION_IFSET(MMU_FTR_NEED_DTLB_SW_LRU) |
| 26 | BEGIN_FTR_SECTION | 26 | BEGIN_FTR_SECTION |
| 27 | bl __init_fpu_registers | 27 | bl __init_fpu_registers |
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 4a24a2fc4574..0b9c9135922e 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
| @@ -89,11 +89,15 @@ extern void __restore_cpu_power7(void); | |||
| 89 | #define COMMON_USER_PA6T (COMMON_USER_PPC64 | PPC_FEATURE_PA6T |\ | 89 | #define COMMON_USER_PA6T (COMMON_USER_PPC64 | PPC_FEATURE_PA6T |\ |
| 90 | PPC_FEATURE_TRUE_LE | \ | 90 | PPC_FEATURE_TRUE_LE | \ |
| 91 | PPC_FEATURE_HAS_ALTIVEC_COMP) | 91 | PPC_FEATURE_HAS_ALTIVEC_COMP) |
| 92 | #ifdef CONFIG_PPC_BOOK3E_64 | ||
| 93 | #define COMMON_USER_BOOKE (COMMON_USER_PPC64 | PPC_FEATURE_BOOKE) | ||
| 94 | #else | ||
| 92 | #define COMMON_USER_BOOKE (PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \ | 95 | #define COMMON_USER_BOOKE (PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \ |
| 93 | PPC_FEATURE_BOOKE) | 96 | PPC_FEATURE_BOOKE) |
| 97 | #endif | ||
| 94 | 98 | ||
| 95 | static struct cpu_spec __initdata cpu_specs[] = { | 99 | static struct cpu_spec __initdata cpu_specs[] = { |
| 96 | #ifdef CONFIG_PPC64 | 100 | #ifdef CONFIG_PPC_BOOK3S_64 |
| 97 | { /* Power3 */ | 101 | { /* Power3 */ |
| 98 | .pvr_mask = 0xffff0000, | 102 | .pvr_mask = 0xffff0000, |
| 99 | .pvr_value = 0x00400000, | 103 | .pvr_value = 0x00400000, |
| @@ -508,7 +512,8 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
| 508 | .machine_check = machine_check_generic, | 512 | .machine_check = machine_check_generic, |
| 509 | .platform = "power4", | 513 | .platform = "power4", |
| 510 | } | 514 | } |
| 511 | #endif /* CONFIG_PPC64 */ | 515 | #endif /* CONFIG_PPC_BOOK3S_64 */ |
| 516 | |||
| 512 | #ifdef CONFIG_PPC32 | 517 | #ifdef CONFIG_PPC32 |
| 513 | #if CLASSIC_PPC | 518 | #if CLASSIC_PPC |
| 514 | { /* 601 */ | 519 | { /* 601 */ |
| @@ -1630,7 +1635,7 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
| 1630 | .platform = "ppc440", | 1635 | .platform = "ppc440", |
| 1631 | }, | 1636 | }, |
| 1632 | { /* 460EX */ | 1637 | { /* 460EX */ |
| 1633 | .pvr_mask = 0xffff0002, | 1638 | .pvr_mask = 0xffff0006, |
| 1634 | .pvr_value = 0x13020002, | 1639 | .pvr_value = 0x13020002, |
| 1635 | .cpu_name = "460EX", | 1640 | .cpu_name = "460EX", |
| 1636 | .cpu_features = CPU_FTRS_440x6, | 1641 | .cpu_features = CPU_FTRS_440x6, |
| @@ -1642,8 +1647,21 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
| 1642 | .machine_check = machine_check_440A, | 1647 | .machine_check = machine_check_440A, |
| 1643 | .platform = "ppc440", | 1648 | .platform = "ppc440", |
| 1644 | }, | 1649 | }, |
| 1650 | { /* 460EX Rev B */ | ||
| 1651 | .pvr_mask = 0xffff0007, | ||
| 1652 | .pvr_value = 0x13020004, | ||
| 1653 | .cpu_name = "460EX Rev. B", | ||
| 1654 | .cpu_features = CPU_FTRS_440x6, | ||
| 1655 | .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, | ||
| 1656 | .mmu_features = MMU_FTR_TYPE_44x, | ||
| 1657 | .icache_bsize = 32, | ||
| 1658 | .dcache_bsize = 32, | ||
| 1659 | .cpu_setup = __setup_cpu_460ex, | ||
| 1660 | .machine_check = machine_check_440A, | ||
| 1661 | .platform = "ppc440", | ||
| 1662 | }, | ||
| 1645 | { /* 460GT */ | 1663 | { /* 460GT */ |
| 1646 | .pvr_mask = 0xffff0002, | 1664 | .pvr_mask = 0xffff0006, |
| 1647 | .pvr_value = 0x13020000, | 1665 | .pvr_value = 0x13020000, |
| 1648 | .cpu_name = "460GT", | 1666 | .cpu_name = "460GT", |
| 1649 | .cpu_features = CPU_FTRS_440x6, | 1667 | .cpu_features = CPU_FTRS_440x6, |
| @@ -1655,6 +1673,19 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
| 1655 | .machine_check = machine_check_440A, | 1673 | .machine_check = machine_check_440A, |
| 1656 | .platform = "ppc440", | 1674 | .platform = "ppc440", |
| 1657 | }, | 1675 | }, |
| 1676 | { /* 460GT Rev B */ | ||
| 1677 | .pvr_mask = 0xffff0007, | ||
| 1678 | .pvr_value = 0x13020005, | ||
| 1679 | .cpu_name = "460GT Rev. B", | ||
| 1680 | .cpu_features = CPU_FTRS_440x6, | ||
| 1681 | .cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU, | ||
| 1682 | .mmu_features = MMU_FTR_TYPE_44x, | ||
| 1683 | .icache_bsize = 32, | ||
| 1684 | .dcache_bsize = 32, | ||
| 1685 | .cpu_setup = __setup_cpu_460gt, | ||
| 1686 | .machine_check = machine_check_440A, | ||
| 1687 | .platform = "ppc440", | ||
| 1688 | }, | ||
| 1658 | { /* 460SX */ | 1689 | { /* 460SX */ |
| 1659 | .pvr_mask = 0xffffff00, | 1690 | .pvr_mask = 0xffffff00, |
| 1660 | .pvr_value = 0x13541800, | 1691 | .pvr_value = 0x13541800, |
| @@ -1797,6 +1828,29 @@ static struct cpu_spec __initdata cpu_specs[] = { | |||
| 1797 | } | 1828 | } |
| 1798 | #endif /* CONFIG_E500 */ | 1829 | #endif /* CONFIG_E500 */ |
| 1799 | #endif /* CONFIG_PPC32 */ | 1830 | #endif /* CONFIG_PPC32 */ |
| 1831 | |||
| 1832 | #ifdef CONFIG_PPC_BOOK3E_64 | ||
| 1833 | { /* This is a default entry to get going, to be replaced by | ||
| 1834 | * a real one at some stage | ||
| 1835 | */ | ||
| 1836 | #define CPU_FTRS_BASE_BOOK3E (CPU_FTR_USE_TB | \ | ||
| 1837 | CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_SMT | \ | ||
| 1838 | CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE) | ||
| 1839 | .pvr_mask = 0x00000000, | ||
| 1840 | .pvr_value = 0x00000000, | ||
| 1841 | .cpu_name = "Book3E", | ||
| 1842 | .cpu_features = CPU_FTRS_BASE_BOOK3E, | ||
| 1843 | .cpu_user_features = COMMON_USER_PPC64, | ||
| 1844 | .mmu_features = MMU_FTR_TYPE_3E | MMU_FTR_USE_TLBILX | | ||
| 1845 | MMU_FTR_USE_TLBIVAX_BCAST | | ||
| 1846 | MMU_FTR_LOCK_BCAST_INVAL, | ||
| 1847 | .icache_bsize = 64, | ||
| 1848 | .dcache_bsize = 64, | ||
| 1849 | .num_pmcs = 0, | ||
| 1850 | .machine_check = machine_check_generic, | ||
| 1851 | .platform = "power6", | ||
| 1852 | }, | ||
| 1853 | #endif | ||
| 1800 | }; | 1854 | }; |
| 1801 | 1855 | ||
| 1802 | static struct cpu_spec the_cpu_spec; | 1856 | static struct cpu_spec the_cpu_spec; |
diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c index 2983adac8cc3..87ddb3fb948c 100644 --- a/arch/powerpc/kernel/dma-iommu.c +++ b/arch/powerpc/kernel/dma-iommu.c | |||
| @@ -89,7 +89,7 @@ static int dma_iommu_dma_supported(struct device *dev, u64 mask) | |||
| 89 | return 1; | 89 | return 1; |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | struct dma_mapping_ops dma_iommu_ops = { | 92 | struct dma_map_ops dma_iommu_ops = { |
| 93 | .alloc_coherent = dma_iommu_alloc_coherent, | 93 | .alloc_coherent = dma_iommu_alloc_coherent, |
| 94 | .free_coherent = dma_iommu_free_coherent, | 94 | .free_coherent = dma_iommu_free_coherent, |
| 95 | .map_sg = dma_iommu_map_sg, | 95 | .map_sg = dma_iommu_map_sg, |
diff --git a/arch/powerpc/kernel/dma-swiotlb.c b/arch/powerpc/kernel/dma-swiotlb.c index e8a57de85bcf..e96cbbd9b449 100644 --- a/arch/powerpc/kernel/dma-swiotlb.c +++ b/arch/powerpc/kernel/dma-swiotlb.c | |||
| @@ -25,33 +25,13 @@ int swiotlb __read_mostly; | |||
| 25 | unsigned int ppc_swiotlb_enable; | 25 | unsigned int ppc_swiotlb_enable; |
| 26 | 26 | ||
| 27 | /* | 27 | /* |
| 28 | * Determine if an address is reachable by a pci device, or if we must bounce. | ||
| 29 | */ | ||
| 30 | static int | ||
| 31 | swiotlb_pci_addr_needs_map(struct device *hwdev, dma_addr_t addr, size_t size) | ||
| 32 | { | ||
| 33 | dma_addr_t max; | ||
| 34 | struct pci_controller *hose; | ||
| 35 | struct pci_dev *pdev = to_pci_dev(hwdev); | ||
| 36 | |||
| 37 | hose = pci_bus_to_host(pdev->bus); | ||
| 38 | max = hose->dma_window_base_cur + hose->dma_window_size; | ||
| 39 | |||
| 40 | /* check that we're within mapped pci window space */ | ||
| 41 | if ((addr + size > max) | (addr < hose->dma_window_base_cur)) | ||
| 42 | return 1; | ||
| 43 | |||
| 44 | return 0; | ||
| 45 | } | ||
| 46 | |||
| 47 | /* | ||
| 48 | * At the moment, all platforms that use this code only require | 28 | * At the moment, all platforms that use this code only require |
| 49 | * swiotlb to be used if we're operating on HIGHMEM. Since | 29 | * swiotlb to be used if we're operating on HIGHMEM. Since |
| 50 | * we don't ever call anything other than map_sg, unmap_sg, | 30 | * we don't ever call anything other than map_sg, unmap_sg, |
| 51 | * map_page, and unmap_page on highmem, use normal dma_ops | 31 | * map_page, and unmap_page on highmem, use normal dma_ops |
| 52 | * for everything else. | 32 | * for everything else. |
| 53 | */ | 33 | */ |
| 54 | struct dma_mapping_ops swiotlb_dma_ops = { | 34 | struct dma_map_ops swiotlb_dma_ops = { |
| 55 | .alloc_coherent = dma_direct_alloc_coherent, | 35 | .alloc_coherent = dma_direct_alloc_coherent, |
| 56 | .free_coherent = dma_direct_free_coherent, | 36 | .free_coherent = dma_direct_free_coherent, |
| 57 | .map_sg = swiotlb_map_sg_attrs, | 37 | .map_sg = swiotlb_map_sg_attrs, |
| @@ -62,33 +42,34 @@ struct dma_mapping_ops swiotlb_dma_ops = { | |||
| 62 | .sync_single_range_for_cpu = swiotlb_sync_single_range_for_cpu, | 42 | .sync_single_range_for_cpu = swiotlb_sync_single_range_for_cpu, |
| 63 | .sync_single_range_for_device = swiotlb_sync_single_range_for_device, | 43 | .sync_single_range_for_device = swiotlb_sync_single_range_for_device, |
| 64 | .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu, | 44 | .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu, |
| 65 | .sync_sg_for_device = swiotlb_sync_sg_for_device | 45 | .sync_sg_for_device = swiotlb_sync_sg_for_device, |
| 46 | .mapping_error = swiotlb_dma_mapping_error, | ||
| 66 | }; | 47 | }; |
| 67 | 48 | ||
| 68 | struct dma_mapping_ops swiotlb_pci_dma_ops = { | 49 | void pci_dma_dev_setup_swiotlb(struct pci_dev *pdev) |
| 69 | .alloc_coherent = dma_direct_alloc_coherent, | 50 | { |
| 70 | .free_coherent = dma_direct_free_coherent, | 51 | struct pci_controller *hose; |
| 71 | .map_sg = swiotlb_map_sg_attrs, | 52 | struct dev_archdata *sd; |
| 72 | .unmap_sg = swiotlb_unmap_sg_attrs, | 53 | |
| 73 | .dma_supported = swiotlb_dma_supported, | 54 | hose = pci_bus_to_host(pdev->bus); |
| 74 | .map_page = swiotlb_map_page, | 55 | sd = &pdev->dev.archdata; |
| 75 | .unmap_page = swiotlb_unmap_page, | 56 | sd->max_direct_dma_addr = |
| 76 | .addr_needs_map = swiotlb_pci_addr_needs_map, | 57 | hose->dma_window_base_cur + hose->dma_window_size; |
| 77 | .sync_single_range_for_cpu = swiotlb_sync_single_range_for_cpu, | 58 | } |
| 78 | .sync_single_range_for_device = swiotlb_sync_single_range_for_device, | ||
| 79 | .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu, | ||
| 80 | .sync_sg_for_device = swiotlb_sync_sg_for_device | ||
| 81 | }; | ||
| 82 | 59 | ||
| 83 | static int ppc_swiotlb_bus_notify(struct notifier_block *nb, | 60 | static int ppc_swiotlb_bus_notify(struct notifier_block *nb, |
| 84 | unsigned long action, void *data) | 61 | unsigned long action, void *data) |
| 85 | { | 62 | { |
| 86 | struct device *dev = data; | 63 | struct device *dev = data; |
| 64 | struct dev_archdata *sd; | ||
| 87 | 65 | ||
| 88 | /* We are only intereted in device addition */ | 66 | /* We are only intereted in device addition */ |
| 89 | if (action != BUS_NOTIFY_ADD_DEVICE) | 67 | if (action != BUS_NOTIFY_ADD_DEVICE) |
| 90 | return 0; | 68 | return 0; |
| 91 | 69 | ||
| 70 | sd = &dev->archdata; | ||
| 71 | sd->max_direct_dma_addr = 0; | ||
| 72 | |||
| 92 | /* May need to bounce if the device can't address all of DRAM */ | 73 | /* May need to bounce if the device can't address all of DRAM */ |
| 93 | if (dma_get_mask(dev) < lmb_end_of_DRAM()) | 74 | if (dma_get_mask(dev) < lmb_end_of_DRAM()) |
| 94 | set_dma_ops(dev, &swiotlb_dma_ops); | 75 | set_dma_ops(dev, &swiotlb_dma_ops); |
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c index ccf129d47d84..21b784d7e7d0 100644 --- a/arch/powerpc/kernel/dma.c +++ b/arch/powerpc/kernel/dma.c | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | #include <linux/device.h> | 8 | #include <linux/device.h> |
| 9 | #include <linux/dma-mapping.h> | 9 | #include <linux/dma-mapping.h> |
| 10 | #include <linux/dma-debug.h> | ||
| 10 | #include <linux/lmb.h> | 11 | #include <linux/lmb.h> |
| 11 | #include <asm/bug.h> | 12 | #include <asm/bug.h> |
| 12 | #include <asm/abs_addr.h> | 13 | #include <asm/abs_addr.h> |
| @@ -140,7 +141,7 @@ static inline void dma_direct_sync_single_range(struct device *dev, | |||
| 140 | } | 141 | } |
| 141 | #endif | 142 | #endif |
| 142 | 143 | ||
| 143 | struct dma_mapping_ops dma_direct_ops = { | 144 | struct dma_map_ops dma_direct_ops = { |
| 144 | .alloc_coherent = dma_direct_alloc_coherent, | 145 | .alloc_coherent = dma_direct_alloc_coherent, |
| 145 | .free_coherent = dma_direct_free_coherent, | 146 | .free_coherent = dma_direct_free_coherent, |
| 146 | .map_sg = dma_direct_map_sg, | 147 | .map_sg = dma_direct_map_sg, |
| @@ -156,3 +157,13 @@ struct dma_mapping_ops dma_direct_ops = { | |||
| 156 | #endif | 157 | #endif |
| 157 | }; | 158 | }; |
| 158 | EXPORT_SYMBOL(dma_direct_ops); | 159 | EXPORT_SYMBOL(dma_direct_ops); |
| 160 | |||
| 161 | #define PREALLOC_DMA_DEBUG_ENTRIES (1 << 16) | ||
| 162 | |||
| 163 | static int __init dma_init(void) | ||
| 164 | { | ||
| 165 | dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); | ||
| 166 | |||
| 167 | return 0; | ||
| 168 | } | ||
| 169 | fs_initcall(dma_init); | ||
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 3cadba60a4b6..1175a8539e6c 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S | |||
| @@ -88,7 +88,7 @@ crit_transfer_to_handler: | |||
| 88 | mfspr r0,SPRN_SRR1 | 88 | mfspr r0,SPRN_SRR1 |
| 89 | stw r0,_SRR1(r11) | 89 | stw r0,_SRR1(r11) |
| 90 | 90 | ||
| 91 | mfspr r8,SPRN_SPRG3 | 91 | mfspr r8,SPRN_SPRG_THREAD |
| 92 | lwz r0,KSP_LIMIT(r8) | 92 | lwz r0,KSP_LIMIT(r8) |
| 93 | stw r0,SAVED_KSP_LIMIT(r11) | 93 | stw r0,SAVED_KSP_LIMIT(r11) |
| 94 | rlwimi r0,r1,0,0,(31-THREAD_SHIFT) | 94 | rlwimi r0,r1,0,0,(31-THREAD_SHIFT) |
| @@ -108,7 +108,7 @@ crit_transfer_to_handler: | |||
| 108 | mfspr r0,SPRN_SRR1 | 108 | mfspr r0,SPRN_SRR1 |
| 109 | stw r0,crit_srr1@l(0) | 109 | stw r0,crit_srr1@l(0) |
| 110 | 110 | ||
| 111 | mfspr r8,SPRN_SPRG3 | 111 | mfspr r8,SPRN_SPRG_THREAD |
| 112 | lwz r0,KSP_LIMIT(r8) | 112 | lwz r0,KSP_LIMIT(r8) |
| 113 | stw r0,saved_ksp_limit@l(0) | 113 | stw r0,saved_ksp_limit@l(0) |
| 114 | rlwimi r0,r1,0,0,(31-THREAD_SHIFT) | 114 | rlwimi r0,r1,0,0,(31-THREAD_SHIFT) |
| @@ -138,7 +138,7 @@ transfer_to_handler: | |||
| 138 | mfspr r2,SPRN_XER | 138 | mfspr r2,SPRN_XER |
| 139 | stw r12,_CTR(r11) | 139 | stw r12,_CTR(r11) |
| 140 | stw r2,_XER(r11) | 140 | stw r2,_XER(r11) |
| 141 | mfspr r12,SPRN_SPRG3 | 141 | mfspr r12,SPRN_SPRG_THREAD |
| 142 | addi r2,r12,-THREAD | 142 | addi r2,r12,-THREAD |
| 143 | tovirt(r2,r2) /* set r2 to current */ | 143 | tovirt(r2,r2) /* set r2 to current */ |
| 144 | beq 2f /* if from user, fix up THREAD.regs */ | 144 | beq 2f /* if from user, fix up THREAD.regs */ |
| @@ -680,7 +680,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_SPE) | |||
| 680 | 680 | ||
| 681 | tophys(r0,r4) | 681 | tophys(r0,r4) |
| 682 | CLR_TOP32(r0) | 682 | CLR_TOP32(r0) |
| 683 | mtspr SPRN_SPRG3,r0 /* Update current THREAD phys addr */ | 683 | mtspr SPRN_SPRG_THREAD,r0 /* Update current THREAD phys addr */ |
| 684 | lwz r1,KSP(r4) /* Load new stack pointer */ | 684 | lwz r1,KSP(r4) /* Load new stack pointer */ |
| 685 | 685 | ||
| 686 | /* save the old current 'last' for return value */ | 686 | /* save the old current 'last' for return value */ |
| @@ -1057,7 +1057,7 @@ exc_exit_restart_end: | |||
| 1057 | #ifdef CONFIG_40x | 1057 | #ifdef CONFIG_40x |
| 1058 | .globl ret_from_crit_exc | 1058 | .globl ret_from_crit_exc |
| 1059 | ret_from_crit_exc: | 1059 | ret_from_crit_exc: |
| 1060 | mfspr r9,SPRN_SPRG3 | 1060 | mfspr r9,SPRN_SPRG_THREAD |
| 1061 | lis r10,saved_ksp_limit@ha; | 1061 | lis r10,saved_ksp_limit@ha; |
| 1062 | lwz r10,saved_ksp_limit@l(r10); | 1062 | lwz r10,saved_ksp_limit@l(r10); |
| 1063 | tovirt(r9,r9); | 1063 | tovirt(r9,r9); |
| @@ -1074,7 +1074,7 @@ ret_from_crit_exc: | |||
| 1074 | #ifdef CONFIG_BOOKE | 1074 | #ifdef CONFIG_BOOKE |
| 1075 | .globl ret_from_crit_exc | 1075 | .globl ret_from_crit_exc |
| 1076 | ret_from_crit_exc: | 1076 | ret_from_crit_exc: |
| 1077 | mfspr r9,SPRN_SPRG3 | 1077 | mfspr r9,SPRN_SPRG_THREAD |
| 1078 | lwz r10,SAVED_KSP_LIMIT(r1) | 1078 | lwz r10,SAVED_KSP_LIMIT(r1) |
| 1079 | stw r10,KSP_LIMIT(r9) | 1079 | stw r10,KSP_LIMIT(r9) |
| 1080 | RESTORE_xSRR(SRR0,SRR1); | 1080 | RESTORE_xSRR(SRR0,SRR1); |
| @@ -1083,7 +1083,7 @@ ret_from_crit_exc: | |||
| 1083 | 1083 | ||
| 1084 | .globl ret_from_debug_exc | 1084 | .globl ret_from_debug_exc |
| 1085 | ret_from_debug_exc: | 1085 | ret_from_debug_exc: |
| 1086 | mfspr r9,SPRN_SPRG3 | 1086 | mfspr r9,SPRN_SPRG_THREAD |
| 1087 | lwz r10,SAVED_KSP_LIMIT(r1) | 1087 | lwz r10,SAVED_KSP_LIMIT(r1) |
| 1088 | stw r10,KSP_LIMIT(r9) | 1088 | stw r10,KSP_LIMIT(r9) |
| 1089 | lwz r9,THREAD_INFO-THREAD(r9) | 1089 | lwz r9,THREAD_INFO-THREAD(r9) |
| @@ -1097,7 +1097,7 @@ ret_from_debug_exc: | |||
| 1097 | 1097 | ||
| 1098 | .globl ret_from_mcheck_exc | 1098 | .globl ret_from_mcheck_exc |
| 1099 | ret_from_mcheck_exc: | 1099 | ret_from_mcheck_exc: |
| 1100 | mfspr r9,SPRN_SPRG3 | 1100 | mfspr r9,SPRN_SPRG_THREAD |
| 1101 | lwz r10,SAVED_KSP_LIMIT(r1) | 1101 | lwz r10,SAVED_KSP_LIMIT(r1) |
| 1102 | stw r10,KSP_LIMIT(r9) | 1102 | stw r10,KSP_LIMIT(r9) |
| 1103 | RESTORE_xSRR(SRR0,SRR1); | 1103 | RESTORE_xSRR(SRR0,SRR1); |
| @@ -1255,7 +1255,7 @@ _GLOBAL(enter_rtas) | |||
| 1255 | MTMSRD(r0) /* don't get trashed */ | 1255 | MTMSRD(r0) /* don't get trashed */ |
| 1256 | li r9,MSR_KERNEL & ~(MSR_IR|MSR_DR) | 1256 | li r9,MSR_KERNEL & ~(MSR_IR|MSR_DR) |
| 1257 | mtlr r6 | 1257 | mtlr r6 |
| 1258 | mtspr SPRN_SPRG2,r7 | 1258 | mtspr SPRN_SPRG_RTAS,r7 |
| 1259 | mtspr SPRN_SRR0,r8 | 1259 | mtspr SPRN_SRR0,r8 |
| 1260 | mtspr SPRN_SRR1,r9 | 1260 | mtspr SPRN_SRR1,r9 |
| 1261 | RFI | 1261 | RFI |
| @@ -1265,7 +1265,7 @@ _GLOBAL(enter_rtas) | |||
| 1265 | FIX_SRR1(r9,r0) | 1265 | FIX_SRR1(r9,r0) |
| 1266 | addi r1,r1,INT_FRAME_SIZE | 1266 | addi r1,r1,INT_FRAME_SIZE |
| 1267 | li r0,0 | 1267 | li r0,0 |
| 1268 | mtspr SPRN_SPRG2,r0 | 1268 | mtspr SPRN_SPRG_RTAS,r0 |
| 1269 | mtspr SPRN_SRR0,r8 | 1269 | mtspr SPRN_SRR0,r8 |
| 1270 | mtspr SPRN_SRR1,r9 | 1270 | mtspr SPRN_SRR1,r9 |
| 1271 | RFI /* return to caller */ | 1271 | RFI /* return to caller */ |
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 43e073477c34..66bcda34a6bb 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
| @@ -120,9 +120,15 @@ BEGIN_FW_FTR_SECTION | |||
| 120 | 2: | 120 | 2: |
| 121 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) | 121 | END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES) |
| 122 | #endif /* CONFIG_PPC_ISERIES */ | 122 | #endif /* CONFIG_PPC_ISERIES */ |
| 123 | |||
| 124 | /* Hard enable interrupts */ | ||
| 125 | #ifdef CONFIG_PPC_BOOK3E | ||
| 126 | wrteei 1 | ||
| 127 | #else | ||
| 123 | mfmsr r11 | 128 | mfmsr r11 |
| 124 | ori r11,r11,MSR_EE | 129 | ori r11,r11,MSR_EE |
| 125 | mtmsrd r11,1 | 130 | mtmsrd r11,1 |
| 131 | #endif /* CONFIG_PPC_BOOK3E */ | ||
| 126 | 132 | ||
| 127 | #ifdef SHOW_SYSCALLS | 133 | #ifdef SHOW_SYSCALLS |
| 128 | bl .do_show_syscall | 134 | bl .do_show_syscall |
| @@ -168,15 +174,25 @@ syscall_exit: | |||
| 168 | #endif | 174 | #endif |
| 169 | clrrdi r12,r1,THREAD_SHIFT | 175 | clrrdi r12,r1,THREAD_SHIFT |
| 170 | 176 | ||
| 171 | /* disable interrupts so current_thread_info()->flags can't change, | ||
| 172 | and so that we don't get interrupted after loading SRR0/1. */ | ||
| 173 | ld r8,_MSR(r1) | 177 | ld r8,_MSR(r1) |
| 178 | #ifdef CONFIG_PPC_BOOK3S | ||
| 179 | /* No MSR:RI on BookE */ | ||
| 174 | andi. r10,r8,MSR_RI | 180 | andi. r10,r8,MSR_RI |
| 175 | beq- unrecov_restore | 181 | beq- unrecov_restore |
| 182 | #endif | ||
| 183 | |||
| 184 | /* Disable interrupts so current_thread_info()->flags can't change, | ||
| 185 | * and so that we don't get interrupted after loading SRR0/1. | ||
| 186 | */ | ||
| 187 | #ifdef CONFIG_PPC_BOOK3E | ||
| 188 | wrteei 0 | ||
| 189 | #else | ||
| 176 | mfmsr r10 | 190 | mfmsr r10 |
| 177 | rldicl r10,r10,48,1 | 191 | rldicl r10,r10,48,1 |
| 178 | rotldi r10,r10,16 | 192 | rotldi r10,r10,16 |
| 179 | mtmsrd r10,1 | 193 | mtmsrd r10,1 |
| 194 | #endif /* CONFIG_PPC_BOOK3E */ | ||
| 195 | |||
| 180 | ld r9,TI_FLAGS(r12) | 196 | ld r9,TI_FLAGS(r12) |
| 181 | li r11,-_LAST_ERRNO | 197 | li r11,-_LAST_ERRNO |
| 182 | andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_USER_WORK_MASK|_TIF_PERSYSCALL_MASK) | 198 | andi. r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP|_TIF_USER_WORK_MASK|_TIF_PERSYSCALL_MASK) |
| @@ -194,9 +210,13 @@ syscall_error_cont: | |||
| 194 | * userspace and we take an exception after restoring r13, | 210 | * userspace and we take an exception after restoring r13, |
| 195 | * we end up corrupting the userspace r13 value. | 211 | * we end up corrupting the userspace r13 value. |
| 196 | */ | 212 | */ |
| 213 | #ifdef CONFIG_PPC_BOOK3S | ||
| 214 | /* No MSR:RI on BookE */ | ||
| 197 | li r12,MSR_RI | 215 | li r12,MSR_RI |
| 198 | andc r11,r10,r12 | 216 | andc r11,r10,r12 |
| 199 | mtmsrd r11,1 /* clear MSR.RI */ | 217 | mtmsrd r11,1 /* clear MSR.RI */ |
| 218 | #endif /* CONFIG_PPC_BOOK3S */ | ||
| 219 | |||
| 200 | beq- 1f | 220 | beq- 1f |
| 201 | ACCOUNT_CPU_USER_EXIT(r11, r12) | 221 | ACCOUNT_CPU_USER_EXIT(r11, r12) |
| 202 | ld r13,GPR13(r1) /* only restore r13 if returning to usermode */ | 222 | ld r13,GPR13(r1) /* only restore r13 if returning to usermode */ |
| @@ -206,7 +226,7 @@ syscall_error_cont: | |||
| 206 | mtcr r5 | 226 | mtcr r5 |
| 207 | mtspr SPRN_SRR0,r7 | 227 | mtspr SPRN_SRR0,r7 |
| 208 | mtspr SPRN_SRR1,r8 | 228 | mtspr SPRN_SRR1,r8 |
| 209 | rfid | 229 | RFI |
| 210 | b . /* prevent speculative execution */ | 230 | b . /* prevent speculative execution */ |
| 211 | 231 | ||
| 212 | syscall_error: | 232 | syscall_error: |
| @@ -276,9 +296,13 @@ syscall_exit_work: | |||
| 276 | beq .ret_from_except_lite | 296 | beq .ret_from_except_lite |
| 277 | 297 | ||
| 278 | /* Re-enable interrupts */ | 298 | /* Re-enable interrupts */ |
| 299 | #ifdef CONFIG_PPC_BOOK3E | ||
| 300 | wrteei 1 | ||
| 301 | #else | ||
| 279 | mfmsr r10 | 302 | mfmsr r10 |
| 280 | ori r10,r10,MSR_EE | 303 | ori r10,r10,MSR_EE |
| 281 | mtmsrd r10,1 | 304 | mtmsrd r10,1 |
| 305 | #endif /* CONFIG_PPC_BOOK3E */ | ||
| 282 | 306 | ||
| 283 | bl .save_nvgprs | 307 | bl .save_nvgprs |
| 284 | addi r3,r1,STACK_FRAME_OVERHEAD | 308 | addi r3,r1,STACK_FRAME_OVERHEAD |
| @@ -380,7 +404,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | |||
| 380 | and. r0,r0,r22 | 404 | and. r0,r0,r22 |
| 381 | beq+ 1f | 405 | beq+ 1f |
| 382 | andc r22,r22,r0 | 406 | andc r22,r22,r0 |
| 383 | mtmsrd r22 | 407 | MTMSRD(r22) |
| 384 | isync | 408 | isync |
| 385 | 1: std r20,_NIP(r1) | 409 | 1: std r20,_NIP(r1) |
| 386 | mfcr r23 | 410 | mfcr r23 |
| @@ -399,6 +423,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | |||
| 399 | std r6,PACACURRENT(r13) /* Set new 'current' */ | 423 | std r6,PACACURRENT(r13) /* Set new 'current' */ |
| 400 | 424 | ||
| 401 | ld r8,KSP(r4) /* new stack pointer */ | 425 | ld r8,KSP(r4) /* new stack pointer */ |
| 426 | #ifdef CONFIG_PPC_BOOK3S | ||
| 402 | BEGIN_FTR_SECTION | 427 | BEGIN_FTR_SECTION |
| 403 | BEGIN_FTR_SECTION_NESTED(95) | 428 | BEGIN_FTR_SECTION_NESTED(95) |
| 404 | clrrdi r6,r8,28 /* get its ESID */ | 429 | clrrdi r6,r8,28 /* get its ESID */ |
| @@ -445,8 +470,9 @@ END_FTR_SECTION_IFSET(CPU_FTR_1T_SEGMENT) | |||
| 445 | slbie r6 /* Workaround POWER5 < DD2.1 issue */ | 470 | slbie r6 /* Workaround POWER5 < DD2.1 issue */ |
| 446 | slbmte r7,r0 | 471 | slbmte r7,r0 |
| 447 | isync | 472 | isync |
| 448 | |||
| 449 | 2: | 473 | 2: |
| 474 | #endif /* !CONFIG_PPC_BOOK3S */ | ||
| 475 | |||
| 450 | clrrdi r7,r8,THREAD_SHIFT /* base of new stack */ | 476 | clrrdi r7,r8,THREAD_SHIFT /* base of new stack */ |
| 451 | /* Note: this uses SWITCH_FRAME_SIZE rather than INT_FRAME_SIZE | 477 | /* Note: this uses SWITCH_FRAME_SIZE rather than INT_FRAME_SIZE |
| 452 | because we don't need to leave the 288-byte ABI gap at the | 478 | because we don't need to leave the 288-byte ABI gap at the |
| @@ -490,10 +516,14 @@ _GLOBAL(ret_from_except_lite) | |||
| 490 | * can't change between when we test it and when we return | 516 | * can't change between when we test it and when we return |
| 491 | * from the interrupt. | 517 | * from the interrupt. |
| 492 | */ | 518 | */ |
| 519 | #ifdef CONFIG_PPC_BOOK3E | ||
| 520 | wrteei 0 | ||
| 521 | #else | ||
| 493 | mfmsr r10 /* Get current interrupt state */ | 522 | mfmsr r10 /* Get current interrupt state */ |
| 494 | rldicl r9,r10,48,1 /* clear MSR_EE */ | 523 | rldicl r9,r10,48,1 /* clear MSR_EE */ |
| 495 | rotldi r9,r9,16 | 524 | rotldi r9,r9,16 |
| 496 | mtmsrd r9,1 /* Update machine state */ | 525 | mtmsrd r9,1 /* Update machine state */ |
| 526 | #endif /* CONFIG_PPC_BOOK3E */ | ||
| 497 | 527 | ||
| 498 | #ifdef CONFIG_PREEMPT | 528 | #ifdef CONFIG_PREEMPT |
| 499 | clrrdi r9,r1,THREAD_SHIFT /* current_thread_info() */ | 529 | clrrdi r9,r1,THREAD_SHIFT /* current_thread_info() */ |
| @@ -540,6 +570,9 @@ ALT_FW_FTR_SECTION_END_IFCLR(FW_FEATURE_ISERIES) | |||
| 540 | rldicl r4,r3,49,63 /* r0 = (r3 >> 15) & 1 */ | 570 | rldicl r4,r3,49,63 /* r0 = (r3 >> 15) & 1 */ |
| 541 | stb r4,PACAHARDIRQEN(r13) | 571 | stb r4,PACAHARDIRQEN(r13) |
| 542 | 572 | ||
| 573 | #ifdef CONFIG_PPC_BOOK3E | ||
| 574 | b .exception_return_book3e | ||
| 575 | #else | ||
| 543 | ld r4,_CTR(r1) | 576 | ld r4,_CTR(r1) |
| 544 | ld r0,_LINK(r1) | 577 | ld r0,_LINK(r1) |
| 545 | mtctr r4 | 578 | mtctr r4 |
| @@ -588,6 +621,8 @@ ALT_FW_FTR_SECTION_END_IFCLR(FW_FEATURE_ISERIES) | |||
| 588 | rfid | 621 | rfid |
| 589 | b . /* prevent speculative execution */ | 622 | b . /* prevent speculative execution */ |
| 590 | 623 | ||
| 624 | #endif /* CONFIG_PPC_BOOK3E */ | ||
| 625 | |||
| 591 | iseries_check_pending_irqs: | 626 | iseries_check_pending_irqs: |
| 592 | #ifdef CONFIG_PPC_ISERIES | 627 | #ifdef CONFIG_PPC_ISERIES |
| 593 | ld r5,SOFTE(r1) | 628 | ld r5,SOFTE(r1) |
| @@ -638,6 +673,11 @@ do_work: | |||
| 638 | li r0,1 | 673 | li r0,1 |
| 639 | stb r0,PACASOFTIRQEN(r13) | 674 | stb r0,PACASOFTIRQEN(r13) |
| 640 | stb r0,PACAHARDIRQEN(r13) | 675 | stb r0,PACAHARDIRQEN(r13) |
| 676 | #ifdef CONFIG_PPC_BOOK3E | ||
| 677 | wrteei 1 | ||
| 678 | bl .preempt_schedule | ||
| 679 | wrteei 0 | ||
| 680 | #else | ||
| 641 | ori r10,r10,MSR_EE | 681 | ori r10,r10,MSR_EE |
| 642 | mtmsrd r10,1 /* reenable interrupts */ | 682 | mtmsrd r10,1 /* reenable interrupts */ |
| 643 | bl .preempt_schedule | 683 | bl .preempt_schedule |
| @@ -646,6 +686,7 @@ do_work: | |||
| 646 | rldicl r10,r10,48,1 /* disable interrupts again */ | 686 | rldicl r10,r10,48,1 /* disable interrupts again */ |
| 647 | rotldi r10,r10,16 | 687 | rotldi r10,r10,16 |
| 648 | mtmsrd r10,1 | 688 | mtmsrd r10,1 |
| 689 | #endif /* CONFIG_PPC_BOOK3E */ | ||
| 649 | ld r4,TI_FLAGS(r9) | 690 | ld r4,TI_FLAGS(r9) |
| 650 | andi. r0,r4,_TIF_NEED_RESCHED | 691 | andi. r0,r4,_TIF_NEED_RESCHED |
| 651 | bne 1b | 692 | bne 1b |
| @@ -654,8 +695,12 @@ do_work: | |||
| 654 | user_work: | 695 | user_work: |
| 655 | #endif | 696 | #endif |
| 656 | /* Enable interrupts */ | 697 | /* Enable interrupts */ |
| 698 | #ifdef CONFIG_PPC_BOOK3E | ||
| 699 | wrteei 1 | ||
| 700 | #else | ||
| 657 | ori r10,r10,MSR_EE | 701 | ori r10,r10,MSR_EE |
| 658 | mtmsrd r10,1 | 702 | mtmsrd r10,1 |
| 703 | #endif /* CONFIG_PPC_BOOK3E */ | ||
| 659 | 704 | ||
| 660 | andi. r0,r4,_TIF_NEED_RESCHED | 705 | andi. r0,r4,_TIF_NEED_RESCHED |
| 661 | beq 1f | 706 | beq 1f |
| @@ -762,7 +807,7 @@ _GLOBAL(enter_rtas) | |||
| 762 | 807 | ||
| 763 | _STATIC(rtas_return_loc) | 808 | _STATIC(rtas_return_loc) |
| 764 | /* relocation is off at this point */ | 809 | /* relocation is off at this point */ |
| 765 | mfspr r4,SPRN_SPRG3 /* Get PACA */ | 810 | mfspr r4,SPRN_SPRG_PACA /* Get PACA */ |
| 766 | clrldi r4,r4,2 /* convert to realmode address */ | 811 | clrldi r4,r4,2 /* convert to realmode address */ |
| 767 | 812 | ||
| 768 | bcl 20,31,$+4 | 813 | bcl 20,31,$+4 |
| @@ -793,7 +838,7 @@ _STATIC(rtas_restore_regs) | |||
| 793 | REST_8GPRS(14, r1) /* Restore the non-volatiles */ | 838 | REST_8GPRS(14, r1) /* Restore the non-volatiles */ |
| 794 | REST_10GPRS(22, r1) /* ditto */ | 839 | REST_10GPRS(22, r1) /* ditto */ |
| 795 | 840 | ||
| 796 | mfspr r13,SPRN_SPRG3 | 841 | mfspr r13,SPRN_SPRG_PACA |
| 797 | 842 | ||
| 798 | ld r4,_CCR(r1) | 843 | ld r4,_CCR(r1) |
| 799 | mtcr r4 | 844 | mtcr r4 |
| @@ -823,33 +868,24 @@ _GLOBAL(enter_prom) | |||
| 823 | * of all registers that it saves. We therefore save those registers | 868 | * of all registers that it saves. We therefore save those registers |
| 824 | * PROM might touch to the stack. (r0, r3-r13 are caller saved) | 869 | * PROM might touch to the stack. (r0, r3-r13 are caller saved) |
| 825 | */ | 870 | */ |
| 826 | SAVE_8GPRS(2, r1) | 871 | SAVE_GPR(2, r1) |
| 827 | SAVE_GPR(13, r1) | 872 | SAVE_GPR(13, r1) |
| 828 | SAVE_8GPRS(14, r1) | 873 | SAVE_8GPRS(14, r1) |
| 829 | SAVE_10GPRS(22, r1) | 874 | SAVE_10GPRS(22, r1) |
| 830 | mfcr r4 | 875 | mfcr r10 |
| 831 | std r4,_CCR(r1) | ||
| 832 | mfctr r5 | ||
| 833 | std r5,_CTR(r1) | ||
| 834 | mfspr r6,SPRN_XER | ||
| 835 | std r6,_XER(r1) | ||
| 836 | mfdar r7 | ||
| 837 | std r7,_DAR(r1) | ||
| 838 | mfdsisr r8 | ||
| 839 | std r8,_DSISR(r1) | ||
| 840 | mfsrr0 r9 | ||
| 841 | std r9,_SRR0(r1) | ||
| 842 | mfsrr1 r10 | ||
| 843 | std r10,_SRR1(r1) | ||
| 844 | mfmsr r11 | 876 | mfmsr r11 |
| 877 | std r10,_CCR(r1) | ||
| 845 | std r11,_MSR(r1) | 878 | std r11,_MSR(r1) |
| 846 | 879 | ||
| 847 | /* Get the PROM entrypoint */ | 880 | /* Get the PROM entrypoint */ |
| 848 | ld r0,GPR4(r1) | 881 | mtlr r4 |
| 849 | mtlr r0 | ||
| 850 | 882 | ||
| 851 | /* Switch MSR to 32 bits mode | 883 | /* Switch MSR to 32 bits mode |
| 852 | */ | 884 | */ |
| 885 | #ifdef CONFIG_PPC_BOOK3E | ||
| 886 | rlwinm r11,r11,0,1,31 | ||
| 887 | mtmsr r11 | ||
| 888 | #else /* CONFIG_PPC_BOOK3E */ | ||
| 853 | mfmsr r11 | 889 | mfmsr r11 |
| 854 | li r12,1 | 890 | li r12,1 |
| 855 | rldicr r12,r12,MSR_SF_LG,(63-MSR_SF_LG) | 891 | rldicr r12,r12,MSR_SF_LG,(63-MSR_SF_LG) |
| @@ -858,10 +894,10 @@ _GLOBAL(enter_prom) | |||
| 858 | rldicr r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG) | 894 | rldicr r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG) |
| 859 | andc r11,r11,r12 | 895 | andc r11,r11,r12 |
| 860 | mtmsrd r11 | 896 | mtmsrd r11 |
| 897 | #endif /* CONFIG_PPC_BOOK3E */ | ||
| 861 | isync | 898 | isync |
| 862 | 899 | ||
| 863 | /* Restore arguments & enter PROM here... */ | 900 | /* Enter PROM here... */ |
| 864 | ld r3,GPR3(r1) | ||
| 865 | blrl | 901 | blrl |
| 866 | 902 | ||
| 867 | /* Just make sure that r1 top 32 bits didn't get | 903 | /* Just make sure that r1 top 32 bits didn't get |
| @@ -871,7 +907,7 @@ _GLOBAL(enter_prom) | |||
| 871 | 907 | ||
| 872 | /* Restore the MSR (back to 64 bits) */ | 908 | /* Restore the MSR (back to 64 bits) */ |
| 873 | ld r0,_MSR(r1) | 909 | ld r0,_MSR(r1) |
| 874 | mtmsrd r0 | 910 | MTMSRD(r0) |
| 875 | isync | 911 | isync |
| 876 | 912 | ||
| 877 | /* Restore other registers */ | 913 | /* Restore other registers */ |
| @@ -881,18 +917,6 @@ _GLOBAL(enter_prom) | |||
| 881 | REST_10GPRS(22, r1) | 917 | REST_10GPRS(22, r1) |
| 882 | ld r4,_CCR(r1) | 918 | ld r4,_CCR(r1) |
| 883 | mtcr r4 | 919 | mtcr r4 |
| 884 | ld r5,_CTR(r1) | ||
| 885 | mtctr r5 | ||
| 886 | ld r6,_XER(r1) | ||
| 887 | mtspr SPRN_XER,r6 | ||
| 888 | ld r7,_DAR(r1) | ||
| 889 | mtdar r7 | ||
| 890 | ld r8,_DSISR(r1) | ||
| 891 | mtdsisr r8 | ||
| 892 | ld r9,_SRR0(r1) | ||
| 893 | mtsrr0 r9 | ||
| 894 | ld r10,_SRR1(r1) | ||
| 895 | mtsrr1 r10 | ||
| 896 | 920 | ||
| 897 | addi r1,r1,PROM_FRAME_SIZE | 921 | addi r1,r1,PROM_FRAME_SIZE |
| 898 | ld r0,16(r1) | 922 | ld r0,16(r1) |
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S new file mode 100644 index 000000000000..9048f96237f6 --- /dev/null +++ b/arch/powerpc/kernel/exceptions-64e.S | |||
| @@ -0,0 +1,1001 @@ | |||
| 1 | /* | ||
| 2 | * Boot code and exception vectors for Book3E processors | ||
| 3 | * | ||
| 4 | * Copyright (C) 2007 Ben. Herrenschmidt (benh@kernel.crashing.org), IBM Corp. | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the License, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/threads.h> | ||
| 13 | #include <asm/reg.h> | ||
| 14 | #include <asm/page.h> | ||
| 15 | #include <asm/ppc_asm.h> | ||
| 16 | #include <asm/asm-offsets.h> | ||
| 17 | #include <asm/cputable.h> | ||
| 18 | #include <asm/setup.h> | ||
| 19 | #include <asm/thread_info.h> | ||
| 20 | #include <asm/reg.h> | ||
| 21 | #include <asm/exception-64e.h> | ||
| 22 | #include <asm/bug.h> | ||
| 23 | #include <asm/irqflags.h> | ||
| 24 | #include <asm/ptrace.h> | ||
| 25 | #include <asm/ppc-opcode.h> | ||
| 26 | #include <asm/mmu.h> | ||
| 27 | |||
| 28 | /* XXX This will ultimately add space for a special exception save | ||
| 29 | * structure used to save things like SRR0/SRR1, SPRGs, MAS, etc... | ||
| 30 | * when taking special interrupts. For now we don't support that, | ||
| 31 | * special interrupts from within a non-standard level will probably | ||
| 32 | * blow you up | ||
| 33 | */ | ||
| 34 | #define SPECIAL_EXC_FRAME_SIZE INT_FRAME_SIZE | ||
| 35 | |||
| 36 | /* Exception prolog code for all exceptions */ | ||
| 37 | #define EXCEPTION_PROLOG(n, type, addition) \ | ||
| 38 | mtspr SPRN_SPRG_##type##_SCRATCH,r13; /* get spare registers */ \ | ||
| 39 | mfspr r13,SPRN_SPRG_PACA; /* get PACA */ \ | ||
| 40 | std r10,PACA_EX##type+EX_R10(r13); \ | ||
| 41 | std r11,PACA_EX##type+EX_R11(r13); \ | ||
| 42 | mfcr r10; /* save CR */ \ | ||
| 43 | addition; /* additional code for that exc. */ \ | ||
| 44 | std r1,PACA_EX##type+EX_R1(r13); /* save old r1 in the PACA */ \ | ||
| 45 | stw r10,PACA_EX##type+EX_CR(r13); /* save old CR in the PACA */ \ | ||
| 46 | mfspr r11,SPRN_##type##_SRR1;/* what are we coming from */ \ | ||
| 47 | type##_SET_KSTACK; /* get special stack if necessary */\ | ||
| 48 | andi. r10,r11,MSR_PR; /* save stack pointer */ \ | ||
| 49 | beq 1f; /* branch around if supervisor */ \ | ||
| 50 | ld r1,PACAKSAVE(r13); /* get kernel stack coming from usr */\ | ||
| 51 | 1: cmpdi cr1,r1,0; /* check if SP makes sense */ \ | ||
| 52 | bge- cr1,exc_##n##_bad_stack;/* bad stack (TODO: out of line) */ \ | ||
| 53 | mfspr r10,SPRN_##type##_SRR0; /* read SRR0 before touching stack */ | ||
| 54 | |||
| 55 | /* Exception type-specific macros */ | ||
| 56 | #define GEN_SET_KSTACK \ | ||
| 57 | subi r1,r1,INT_FRAME_SIZE; /* alloc frame on kernel stack */ | ||
| 58 | #define SPRN_GEN_SRR0 SPRN_SRR0 | ||
| 59 | #define SPRN_GEN_SRR1 SPRN_SRR1 | ||
| 60 | |||
| 61 | #define CRIT_SET_KSTACK \ | ||
| 62 | ld r1,PACA_CRIT_STACK(r13); \ | ||
| 63 | subi r1,r1,SPECIAL_EXC_FRAME_SIZE; | ||
| 64 | #define SPRN_CRIT_SRR0 SPRN_CSRR0 | ||
| 65 | #define SPRN_CRIT_SRR1 SPRN_CSRR1 | ||
| 66 | |||
| 67 | #define DBG_SET_KSTACK \ | ||
| 68 | ld r1,PACA_DBG_STACK(r13); \ | ||
| 69 | subi r1,r1,SPECIAL_EXC_FRAME_SIZE; | ||
| 70 | #define SPRN_DBG_SRR0 SPRN_DSRR0 | ||
| 71 | #define SPRN_DBG_SRR1 SPRN_DSRR1 | ||
| 72 | |||
| 73 | #define MC_SET_KSTACK \ | ||
| 74 | ld r1,PACA_MC_STACK(r13); \ | ||
| 75 | subi r1,r1,SPECIAL_EXC_FRAME_SIZE; | ||
| 76 | #define SPRN_MC_SRR0 SPRN_MCSRR0 | ||
| 77 | #define SPRN_MC_SRR1 SPRN_MCSRR1 | ||
| 78 | |||
| 79 | #define NORMAL_EXCEPTION_PROLOG(n, addition) \ | ||
| 80 | EXCEPTION_PROLOG(n, GEN, addition##_GEN) | ||
| 81 | |||
| 82 | #define CRIT_EXCEPTION_PROLOG(n, addition) \ | ||
| 83 | EXCEPTION_PROLOG(n, CRIT, addition##_CRIT) | ||
| 84 | |||
| 85 | #define DBG_EXCEPTION_PROLOG(n, addition) \ | ||
| 86 | EXCEPTION_PROLOG(n, DBG, addition##_DBG) | ||
| 87 | |||
| 88 | #define MC_EXCEPTION_PROLOG(n, addition) \ | ||
| 89 | EXCEPTION_PROLOG(n, MC, addition##_MC) | ||
| 90 | |||
| 91 | |||
| 92 | /* Variants of the "addition" argument for the prolog | ||
| 93 | */ | ||
| 94 | #define PROLOG_ADDITION_NONE_GEN | ||
| 95 | #define PROLOG_ADDITION_NONE_CRIT | ||
| 96 | #define PROLOG_ADDITION_NONE_DBG | ||
| 97 | #define PROLOG_ADDITION_NONE_MC | ||
| 98 | |||
| 99 | #define PROLOG_ADDITION_MASKABLE_GEN \ | ||
| 100 | lbz r11,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */ \ | ||
| 101 | cmpwi cr0,r11,0; /* yes -> go out of line */ \ | ||
| 102 | beq masked_interrupt_book3e; | ||
| 103 | |||
| 104 | #define PROLOG_ADDITION_2REGS_GEN \ | ||
| 105 | std r14,PACA_EXGEN+EX_R14(r13); \ | ||
| 106 | std r15,PACA_EXGEN+EX_R15(r13) | ||
| 107 | |||
| 108 | #define PROLOG_ADDITION_1REG_GEN \ | ||
| 109 | std r14,PACA_EXGEN+EX_R14(r13); | ||
| 110 | |||
| 111 | #define PROLOG_ADDITION_2REGS_CRIT \ | ||
| 112 | std r14,PACA_EXCRIT+EX_R14(r13); \ | ||
| 113 | std r15,PACA_EXCRIT+EX_R15(r13) | ||
| 114 | |||
| 115 | #define PROLOG_ADDITION_2REGS_DBG \ | ||
| 116 | std r14,PACA_EXDBG+EX_R14(r13); \ | ||
| 117 | std r15,PACA_EXDBG+EX_R15(r13) | ||
| 118 | |||
| 119 | #define PROLOG_ADDITION_2REGS_MC \ | ||
| 120 | std r14,PACA_EXMC+EX_R14(r13); \ | ||
| 121 | std r15,PACA_EXMC+EX_R15(r13) | ||
| 122 | |||
| 123 | /* Core exception code for all exceptions except TLB misses. | ||
| 124 | * XXX: Needs to make SPRN_SPRG_GEN depend on exception type | ||
| 125 | */ | ||
| 126 | #define EXCEPTION_COMMON(n, excf, ints) \ | ||
| 127 | std r0,GPR0(r1); /* save r0 in stackframe */ \ | ||
| 128 | std r2,GPR2(r1); /* save r2 in stackframe */ \ | ||
| 129 | SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \ | ||
| 130 | SAVE_2GPRS(7, r1); /* save r7, r8 in stackframe */ \ | ||
| 131 | std r9,GPR9(r1); /* save r9 in stackframe */ \ | ||
| 132 | std r10,_NIP(r1); /* save SRR0 to stackframe */ \ | ||
| 133 | std r11,_MSR(r1); /* save SRR1 to stackframe */ \ | ||
| 134 | ACCOUNT_CPU_USER_ENTRY(r10,r11);/* accounting (uses cr0+eq) */ \ | ||
| 135 | ld r3,excf+EX_R10(r13); /* get back r10 */ \ | ||
| 136 | ld r4,excf+EX_R11(r13); /* get back r11 */ \ | ||
| 137 | mfspr r5,SPRN_SPRG_GEN_SCRATCH;/* get back r13 */ \ | ||
| 138 | std r12,GPR12(r1); /* save r12 in stackframe */ \ | ||
| 139 | ld r2,PACATOC(r13); /* get kernel TOC into r2 */ \ | ||
| 140 | mflr r6; /* save LR in stackframe */ \ | ||
| 141 | mfctr r7; /* save CTR in stackframe */ \ | ||
| 142 | mfspr r8,SPRN_XER; /* save XER in stackframe */ \ | ||
| 143 | ld r9,excf+EX_R1(r13); /* load orig r1 back from PACA */ \ | ||
| 144 | lwz r10,excf+EX_CR(r13); /* load orig CR back from PACA */ \ | ||
| 145 | lbz r11,PACASOFTIRQEN(r13); /* get current IRQ softe */ \ | ||
| 146 | ld r12,exception_marker@toc(r2); \ | ||
| 147 | li r0,0; \ | ||
| 148 | std r3,GPR10(r1); /* save r10 to stackframe */ \ | ||
| 149 | std r4,GPR11(r1); /* save r11 to stackframe */ \ | ||
| 150 | std r5,GPR13(r1); /* save it to stackframe */ \ | ||
| 151 | std r6,_LINK(r1); \ | ||
| 152 | std r7,_CTR(r1); \ | ||
| 153 | std r8,_XER(r1); \ | ||
| 154 | li r3,(n)+1; /* indicate partial regs in trap */ \ | ||
| 155 | std r9,0(r1); /* store stack frame back link */ \ | ||
| 156 | std r10,_CCR(r1); /* store orig CR in stackframe */ \ | ||
| 157 | std r9,GPR1(r1); /* store stack frame back link */ \ | ||
| 158 | std r11,SOFTE(r1); /* and save it to stackframe */ \ | ||
| 159 | std r12,STACK_FRAME_OVERHEAD-16(r1); /* mark the frame */ \ | ||
| 160 | std r3,_TRAP(r1); /* set trap number */ \ | ||
| 161 | std r0,RESULT(r1); /* clear regs->result */ \ | ||
| 162 | ints; | ||
| 163 | |||
| 164 | /* Variants for the "ints" argument */ | ||
| 165 | #define INTS_KEEP | ||
| 166 | #define INTS_DISABLE_SOFT \ | ||
| 167 | stb r0,PACASOFTIRQEN(r13); /* mark interrupts soft-disabled */ \ | ||
| 168 | TRACE_DISABLE_INTS; | ||
| 169 | #define INTS_DISABLE_HARD \ | ||
| 170 | stb r0,PACAHARDIRQEN(r13); /* and hard disabled */ | ||
| 171 | #define INTS_DISABLE_ALL \ | ||
| 172 | INTS_DISABLE_SOFT \ | ||
| 173 | INTS_DISABLE_HARD | ||
| 174 | |||
| 175 | /* This is called by exceptions that used INTS_KEEP (that is did not clear | ||
| 176 | * neither soft nor hard IRQ indicators in the PACA. This will restore MSR:EE | ||
| 177 | * to it's previous value | ||
| 178 | * | ||
| 179 | * XXX In the long run, we may want to open-code it in order to separate the | ||
| 180 | * load from the wrtee, thus limiting the latency caused by the dependency | ||
| 181 | * but at this point, I'll favor code clarity until we have a near to final | ||
| 182 | * implementation | ||
| 183 | */ | ||
| 184 | #define INTS_RESTORE_HARD \ | ||
| 185 | ld r11,_MSR(r1); \ | ||
| 186 | wrtee r11; | ||
| 187 | |||
| 188 | /* XXX FIXME: Restore r14/r15 when necessary */ | ||
| 189 | #define BAD_STACK_TRAMPOLINE(n) \ | ||
| 190 | exc_##n##_bad_stack: \ | ||
| 191 | li r1,(n); /* get exception number */ \ | ||
| 192 | sth r1,PACA_TRAP_SAVE(r13); /* store trap */ \ | ||
| 193 | b bad_stack_book3e; /* bad stack error */ | ||
| 194 | |||
| 195 | #define EXCEPTION_STUB(loc, label) \ | ||
| 196 | . = interrupt_base_book3e + loc; \ | ||
| 197 | nop; /* To make debug interrupts happy */ \ | ||
| 198 | b exc_##label##_book3e; | ||
| 199 | |||
| 200 | #define ACK_NONE(r) | ||
| 201 | #define ACK_DEC(r) \ | ||
| 202 | lis r,TSR_DIS@h; \ | ||
| 203 | mtspr SPRN_TSR,r | ||
| 204 | #define ACK_FIT(r) \ | ||
| 205 | lis r,TSR_FIS@h; \ | ||
| 206 | mtspr SPRN_TSR,r | ||
| 207 | |||
| 208 | #define MASKABLE_EXCEPTION(trapnum, label, hdlr, ack) \ | ||
| 209 | START_EXCEPTION(label); \ | ||
| 210 | NORMAL_EXCEPTION_PROLOG(trapnum, PROLOG_ADDITION_MASKABLE) \ | ||
| 211 | EXCEPTION_COMMON(trapnum, PACA_EXGEN, INTS_DISABLE_ALL) \ | ||
| 212 | ack(r8); \ | ||
| 213 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | ||
| 214 | bl hdlr; \ | ||
| 215 | b .ret_from_except_lite; | ||
| 216 | |||
| 217 | /* This value is used to mark exception frames on the stack. */ | ||
| 218 | .section ".toc","aw" | ||
| 219 | exception_marker: | ||
| 220 | .tc ID_EXC_MARKER[TC],STACK_FRAME_REGS_MARKER | ||
| 221 | |||
| 222 | |||
| 223 | /* | ||
| 224 | * And here we have the exception vectors ! | ||
| 225 | */ | ||
| 226 | |||
| 227 | .text | ||
| 228 | .balign 0x1000 | ||
| 229 | .globl interrupt_base_book3e | ||
| 230 | interrupt_base_book3e: /* fake trap */ | ||
| 231 | /* Note: If real debug exceptions are supported by the HW, the vector | ||
| 232 | * below will have to be patched up to point to an appropriate handler | ||
| 233 | */ | ||
| 234 | EXCEPTION_STUB(0x000, machine_check) /* 0x0200 */ | ||
| 235 | EXCEPTION_STUB(0x020, critical_input) /* 0x0580 */ | ||
| 236 | EXCEPTION_STUB(0x040, debug_crit) /* 0x0d00 */ | ||
| 237 | EXCEPTION_STUB(0x060, data_storage) /* 0x0300 */ | ||
| 238 | EXCEPTION_STUB(0x080, instruction_storage) /* 0x0400 */ | ||
| 239 | EXCEPTION_STUB(0x0a0, external_input) /* 0x0500 */ | ||
| 240 | EXCEPTION_STUB(0x0c0, alignment) /* 0x0600 */ | ||
| 241 | EXCEPTION_STUB(0x0e0, program) /* 0x0700 */ | ||
| 242 | EXCEPTION_STUB(0x100, fp_unavailable) /* 0x0800 */ | ||
| 243 | EXCEPTION_STUB(0x120, system_call) /* 0x0c00 */ | ||
| 244 | EXCEPTION_STUB(0x140, ap_unavailable) /* 0x0f20 */ | ||
| 245 | EXCEPTION_STUB(0x160, decrementer) /* 0x0900 */ | ||
| 246 | EXCEPTION_STUB(0x180, fixed_interval) /* 0x0980 */ | ||
| 247 | EXCEPTION_STUB(0x1a0, watchdog) /* 0x09f0 */ | ||
| 248 | EXCEPTION_STUB(0x1c0, data_tlb_miss) | ||
| 249 | EXCEPTION_STUB(0x1e0, instruction_tlb_miss) | ||
| 250 | |||
| 251 | #if 0 | ||
| 252 | EXCEPTION_STUB(0x280, processor_doorbell) | ||
| 253 | EXCEPTION_STUB(0x220, processor_doorbell_crit) | ||
| 254 | #endif | ||
| 255 | .globl interrupt_end_book3e | ||
| 256 | interrupt_end_book3e: | ||
| 257 | |||
| 258 | /* Critical Input Interrupt */ | ||
| 259 | START_EXCEPTION(critical_input); | ||
| 260 | CRIT_EXCEPTION_PROLOG(0x100, PROLOG_ADDITION_NONE) | ||
| 261 | // EXCEPTION_COMMON(0x100, PACA_EXCRIT, INTS_DISABLE_ALL) | ||
| 262 | // bl special_reg_save_crit | ||
| 263 | // addi r3,r1,STACK_FRAME_OVERHEAD | ||
| 264 | // bl .critical_exception | ||
| 265 | // b ret_from_crit_except | ||
| 266 | b . | ||
| 267 | |||
| 268 | /* Machine Check Interrupt */ | ||
| 269 | START_EXCEPTION(machine_check); | ||
| 270 | CRIT_EXCEPTION_PROLOG(0x200, PROLOG_ADDITION_NONE) | ||
| 271 | // EXCEPTION_COMMON(0x200, PACA_EXMC, INTS_DISABLE_ALL) | ||
| 272 | // bl special_reg_save_mc | ||
| 273 | // addi r3,r1,STACK_FRAME_OVERHEAD | ||
| 274 | // bl .machine_check_exception | ||
| 275 | // b ret_from_mc_except | ||
| 276 | b . | ||
| 277 | |||
| 278 | /* Data Storage Interrupt */ | ||
| 279 | START_EXCEPTION(data_storage) | ||
| 280 | NORMAL_EXCEPTION_PROLOG(0x300, PROLOG_ADDITION_2REGS) | ||
| 281 | mfspr r14,SPRN_DEAR | ||
| 282 | mfspr r15,SPRN_ESR | ||
| 283 | EXCEPTION_COMMON(0x300, PACA_EXGEN, INTS_KEEP) | ||
| 284 | b storage_fault_common | ||
| 285 | |||
| 286 | /* Instruction Storage Interrupt */ | ||
| 287 | START_EXCEPTION(instruction_storage); | ||
| 288 | NORMAL_EXCEPTION_PROLOG(0x400, PROLOG_ADDITION_2REGS) | ||
| 289 | li r15,0 | ||
| 290 | mr r14,r10 | ||
| 291 | EXCEPTION_COMMON(0x400, PACA_EXGEN, INTS_KEEP) | ||
| 292 | b storage_fault_common | ||
| 293 | |||
| 294 | /* External Input Interrupt */ | ||
| 295 | MASKABLE_EXCEPTION(0x500, external_input, .do_IRQ, ACK_NONE) | ||
| 296 | |||
| 297 | /* Alignment */ | ||
| 298 | START_EXCEPTION(alignment); | ||
| 299 | NORMAL_EXCEPTION_PROLOG(0x600, PROLOG_ADDITION_2REGS) | ||
| 300 | mfspr r14,SPRN_DEAR | ||
| 301 | mfspr r15,SPRN_ESR | ||
| 302 | EXCEPTION_COMMON(0x600, PACA_EXGEN, INTS_KEEP) | ||
| 303 | b alignment_more /* no room, go out of line */ | ||
| 304 | |||
| 305 | /* Program Interrupt */ | ||
| 306 | START_EXCEPTION(program); | ||
| 307 | NORMAL_EXCEPTION_PROLOG(0x700, PROLOG_ADDITION_1REG) | ||
| 308 | mfspr r14,SPRN_ESR | ||
| 309 | EXCEPTION_COMMON(0x700, PACA_EXGEN, INTS_DISABLE_SOFT) | ||
| 310 | std r14,_DSISR(r1) | ||
| 311 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
| 312 | ld r14,PACA_EXGEN+EX_R14(r13) | ||
| 313 | bl .save_nvgprs | ||
| 314 | INTS_RESTORE_HARD | ||
| 315 | bl .program_check_exception | ||
| 316 | b .ret_from_except | ||
| 317 | |||
| 318 | /* Floating Point Unavailable Interrupt */ | ||
| 319 | START_EXCEPTION(fp_unavailable); | ||
| 320 | NORMAL_EXCEPTION_PROLOG(0x800, PROLOG_ADDITION_NONE) | ||
| 321 | /* we can probably do a shorter exception entry for that one... */ | ||
| 322 | EXCEPTION_COMMON(0x800, PACA_EXGEN, INTS_KEEP) | ||
| 323 | bne 1f /* if from user, just load it up */ | ||
| 324 | bl .save_nvgprs | ||
| 325 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
| 326 | INTS_RESTORE_HARD | ||
| 327 | bl .kernel_fp_unavailable_exception | ||
| 328 | BUG_OPCODE | ||
| 329 | 1: ld r12,_MSR(r1) | ||
| 330 | bl .load_up_fpu | ||
| 331 | b fast_exception_return | ||
| 332 | |||
| 333 | /* Decrementer Interrupt */ | ||
| 334 | MASKABLE_EXCEPTION(0x900, decrementer, .timer_interrupt, ACK_DEC) | ||
| 335 | |||
| 336 | /* Fixed Interval Timer Interrupt */ | ||
| 337 | MASKABLE_EXCEPTION(0x980, fixed_interval, .unknown_exception, ACK_FIT) | ||
| 338 | |||
| 339 | /* Watchdog Timer Interrupt */ | ||
| 340 | START_EXCEPTION(watchdog); | ||
| 341 | CRIT_EXCEPTION_PROLOG(0x9f0, PROLOG_ADDITION_NONE) | ||
| 342 | // EXCEPTION_COMMON(0x9f0, PACA_EXCRIT, INTS_DISABLE_ALL) | ||
| 343 | // bl special_reg_save_crit | ||
| 344 | // addi r3,r1,STACK_FRAME_OVERHEAD | ||
| 345 | // bl .unknown_exception | ||
| 346 | // b ret_from_crit_except | ||
| 347 | b . | ||
| 348 | |||
| 349 | /* System Call Interrupt */ | ||
| 350 | START_EXCEPTION(system_call) | ||
| 351 | mr r9,r13 /* keep a copy of userland r13 */ | ||
| 352 | mfspr r11,SPRN_SRR0 /* get return address */ | ||
| 353 | mfspr r12,SPRN_SRR1 /* get previous MSR */ | ||
| 354 | mfspr r13,SPRN_SPRG_PACA /* get our PACA */ | ||
| 355 | b system_call_common | ||
| 356 | |||
| 357 | /* Auxillary Processor Unavailable Interrupt */ | ||
| 358 | START_EXCEPTION(ap_unavailable); | ||
| 359 | NORMAL_EXCEPTION_PROLOG(0xf20, PROLOG_ADDITION_NONE) | ||
| 360 | EXCEPTION_COMMON(0xf20, PACA_EXGEN, INTS_KEEP) | ||
| 361 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
| 362 | bl .save_nvgprs | ||
| 363 | INTS_RESTORE_HARD | ||
| 364 | bl .unknown_exception | ||
| 365 | b .ret_from_except | ||
| 366 | |||
| 367 | /* Debug exception as a critical interrupt*/ | ||
| 368 | START_EXCEPTION(debug_crit); | ||
| 369 | CRIT_EXCEPTION_PROLOG(0xd00, PROLOG_ADDITION_2REGS) | ||
| 370 | |||
| 371 | /* | ||
| 372 | * If there is a single step or branch-taken exception in an | ||
| 373 | * exception entry sequence, it was probably meant to apply to | ||
| 374 | * the code where the exception occurred (since exception entry | ||
| 375 | * doesn't turn off DE automatically). We simulate the effect | ||
| 376 | * of turning off DE on entry to an exception handler by turning | ||
| 377 | * off DE in the CSRR1 value and clearing the debug status. | ||
| 378 | */ | ||
| 379 | |||
| 380 | mfspr r14,SPRN_DBSR /* check single-step/branch taken */ | ||
| 381 | andis. r15,r14,DBSR_IC@h | ||
| 382 | beq+ 1f | ||
| 383 | |||
| 384 | LOAD_REG_IMMEDIATE(r14,interrupt_base_book3e) | ||
| 385 | LOAD_REG_IMMEDIATE(r15,interrupt_end_book3e) | ||
| 386 | cmpld cr0,r10,r14 | ||
| 387 | cmpld cr1,r10,r15 | ||
| 388 | blt+ cr0,1f | ||
| 389 | bge+ cr1,1f | ||
| 390 | |||
| 391 | /* here it looks like we got an inappropriate debug exception. */ | ||
| 392 | lis r14,DBSR_IC@h /* clear the IC event */ | ||
| 393 | rlwinm r11,r11,0,~MSR_DE /* clear DE in the CSRR1 value */ | ||
| 394 | mtspr SPRN_DBSR,r14 | ||
| 395 | mtspr SPRN_CSRR1,r11 | ||
| 396 | lwz r10,PACA_EXCRIT+EX_CR(r13) /* restore registers */ | ||
| 397 | ld r1,PACA_EXCRIT+EX_R1(r13) | ||
| 398 | ld r14,PACA_EXCRIT+EX_R14(r13) | ||
| 399 | ld r15,PACA_EXCRIT+EX_R15(r13) | ||
| 400 | mtcr r10 | ||
| 401 | ld r10,PACA_EXCRIT+EX_R10(r13) /* restore registers */ | ||
| 402 | ld r11,PACA_EXCRIT+EX_R11(r13) | ||
| 403 | mfspr r13,SPRN_SPRG_CRIT_SCRATCH | ||
| 404 | rfci | ||
| 405 | |||
| 406 | /* Normal debug exception */ | ||
| 407 | /* XXX We only handle coming from userspace for now since we can't | ||
| 408 | * quite save properly an interrupted kernel state yet | ||
| 409 | */ | ||
| 410 | 1: andi. r14,r11,MSR_PR; /* check for userspace again */ | ||
| 411 | beq kernel_dbg_exc; /* if from kernel mode */ | ||
| 412 | |||
| 413 | /* Now we mash up things to make it look like we are coming on a | ||
| 414 | * normal exception | ||
| 415 | */ | ||
| 416 | mfspr r15,SPRN_SPRG_CRIT_SCRATCH | ||
| 417 | mtspr SPRN_SPRG_GEN_SCRATCH,r15 | ||
| 418 | mfspr r14,SPRN_DBSR | ||
| 419 | EXCEPTION_COMMON(0xd00, PACA_EXCRIT, INTS_DISABLE_ALL) | ||
| 420 | std r14,_DSISR(r1) | ||
| 421 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
| 422 | mr r4,r14 | ||
| 423 | ld r14,PACA_EXCRIT+EX_R14(r13) | ||
| 424 | ld r15,PACA_EXCRIT+EX_R15(r13) | ||
| 425 | bl .save_nvgprs | ||
| 426 | bl .DebugException | ||
| 427 | b .ret_from_except | ||
| 428 | |||
| 429 | kernel_dbg_exc: | ||
| 430 | b . /* NYI */ | ||
| 431 | |||
| 432 | |||
| 433 | /* | ||
| 434 | * An interrupt came in while soft-disabled; clear EE in SRR1, | ||
| 435 | * clear paca->hard_enabled and return. | ||
| 436 | */ | ||
| 437 | masked_interrupt_book3e: | ||
| 438 | mtcr r10 | ||
| 439 | stb r11,PACAHARDIRQEN(r13) | ||
| 440 | mfspr r10,SPRN_SRR1 | ||
| 441 | rldicl r11,r10,48,1 /* clear MSR_EE */ | ||
| 442 | rotldi r10,r11,16 | ||
| 443 | mtspr SPRN_SRR1,r10 | ||
| 444 | ld r10,PACA_EXGEN+EX_R10(r13); /* restore registers */ | ||
| 445 | ld r11,PACA_EXGEN+EX_R11(r13); | ||
| 446 | mfspr r13,SPRN_SPRG_GEN_SCRATCH; | ||
| 447 | rfi | ||
| 448 | b . | ||
| 449 | |||
| 450 | /* | ||
| 451 | * This is called from 0x300 and 0x400 handlers after the prologs with | ||
| 452 | * r14 and r15 containing the fault address and error code, with the | ||
| 453 | * original values stashed away in the PACA | ||
| 454 | */ | ||
| 455 | storage_fault_common: | ||
| 456 | std r14,_DAR(r1) | ||
| 457 | std r15,_DSISR(r1) | ||
| 458 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
| 459 | mr r4,r14 | ||
| 460 | mr r5,r15 | ||
| 461 | ld r14,PACA_EXGEN+EX_R14(r13) | ||
| 462 | ld r15,PACA_EXGEN+EX_R15(r13) | ||
| 463 | INTS_RESTORE_HARD | ||
| 464 | bl .do_page_fault | ||
| 465 | cmpdi r3,0 | ||
| 466 | bne- 1f | ||
| 467 | b .ret_from_except_lite | ||
| 468 | 1: bl .save_nvgprs | ||
| 469 | mr r5,r3 | ||
| 470 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
| 471 | ld r4,_DAR(r1) | ||
| 472 | bl .bad_page_fault | ||
| 473 | b .ret_from_except | ||
| 474 | |||
| 475 | /* | ||
| 476 | * Alignment exception doesn't fit entirely in the 0x100 bytes so it | ||
| 477 | * continues here. | ||
| 478 | */ | ||
| 479 | alignment_more: | ||
| 480 | std r14,_DAR(r1) | ||
| 481 | std r15,_DSISR(r1) | ||
| 482 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
| 483 | ld r14,PACA_EXGEN+EX_R14(r13) | ||
| 484 | ld r15,PACA_EXGEN+EX_R15(r13) | ||
| 485 | bl .save_nvgprs | ||
| 486 | INTS_RESTORE_HARD | ||
| 487 | bl .alignment_exception | ||
| 488 | b .ret_from_except | ||
| 489 | |||
| 490 | /* | ||
| 491 | * We branch here from entry_64.S for the last stage of the exception | ||
| 492 | * return code path. MSR:EE is expected to be off at that point | ||
| 493 | */ | ||
| 494 | _GLOBAL(exception_return_book3e) | ||
| 495 | b 1f | ||
| 496 | |||
| 497 | /* This is the return from load_up_fpu fast path which could do with | ||
| 498 | * less GPR restores in fact, but for now we have a single return path | ||
| 499 | */ | ||
| 500 | .globl fast_exception_return | ||
| 501 | fast_exception_return: | ||
| 502 | wrteei 0 | ||
| 503 | 1: mr r0,r13 | ||
| 504 | ld r10,_MSR(r1) | ||
| 505 | REST_4GPRS(2, r1) | ||
| 506 | andi. r6,r10,MSR_PR | ||
| 507 | REST_2GPRS(6, r1) | ||
| 508 | beq 1f | ||
| 509 | ACCOUNT_CPU_USER_EXIT(r10, r11) | ||
| 510 | ld r0,GPR13(r1) | ||
| 511 | |||
| 512 | 1: stdcx. r0,0,r1 /* to clear the reservation */ | ||
| 513 | |||
| 514 | ld r8,_CCR(r1) | ||
| 515 | ld r9,_LINK(r1) | ||
| 516 | ld r10,_CTR(r1) | ||
| 517 | ld r11,_XER(r1) | ||
| 518 | mtcr r8 | ||
| 519 | mtlr r9 | ||
| 520 | mtctr r10 | ||
| 521 | mtxer r11 | ||
| 522 | REST_2GPRS(8, r1) | ||
| 523 | ld r10,GPR10(r1) | ||
| 524 | ld r11,GPR11(r1) | ||
| 525 | ld r12,GPR12(r1) | ||
| 526 | mtspr SPRN_SPRG_GEN_SCRATCH,r0 | ||
| 527 | |||
| 528 | std r10,PACA_EXGEN+EX_R10(r13); | ||
| 529 | std r11,PACA_EXGEN+EX_R11(r13); | ||
| 530 | ld r10,_NIP(r1) | ||
| 531 | ld r11,_MSR(r1) | ||
| 532 | ld r0,GPR0(r1) | ||
| 533 | ld r1,GPR1(r1) | ||
| 534 | mtspr SPRN_SRR0,r10 | ||
| 535 | mtspr SPRN_SRR1,r11 | ||
| 536 | ld r10,PACA_EXGEN+EX_R10(r13) | ||
| 537 | ld r11,PACA_EXGEN+EX_R11(r13) | ||
| 538 | mfspr r13,SPRN_SPRG_GEN_SCRATCH | ||
| 539 | rfi | ||
| 540 | |||
| 541 | /* | ||
| 542 | * Trampolines used when spotting a bad kernel stack pointer in | ||
| 543 | * the exception entry code. | ||
| 544 | * | ||
| 545 | * TODO: move some bits like SRR0 read to trampoline, pass PACA | ||
| 546 | * index around, etc... to handle crit & mcheck | ||
| 547 | */ | ||
| 548 | BAD_STACK_TRAMPOLINE(0x000) | ||
| 549 | BAD_STACK_TRAMPOLINE(0x100) | ||
| 550 | BAD_STACK_TRAMPOLINE(0x200) | ||
| 551 | BAD_STACK_TRAMPOLINE(0x300) | ||
| 552 | BAD_STACK_TRAMPOLINE(0x400) | ||
| 553 | BAD_STACK_TRAMPOLINE(0x500) | ||
| 554 | BAD_STACK_TRAMPOLINE(0x600) | ||
| 555 | BAD_STACK_TRAMPOLINE(0x700) | ||
| 556 | BAD_STACK_TRAMPOLINE(0x800) | ||
| 557 | BAD_STACK_TRAMPOLINE(0x900) | ||
| 558 | BAD_STACK_TRAMPOLINE(0x980) | ||
| 559 | BAD_STACK_TRAMPOLINE(0x9f0) | ||
| 560 | BAD_STACK_TRAMPOLINE(0xa00) | ||
| 561 | BAD_STACK_TRAMPOLINE(0xb00) | ||
| 562 | BAD_STACK_TRAMPOLINE(0xc00) | ||
| 563 | BAD_STACK_TRAMPOLINE(0xd00) | ||
| 564 | BAD_STACK_TRAMPOLINE(0xe00) | ||
| 565 | BAD_STACK_TRAMPOLINE(0xf00) | ||
| 566 | BAD_STACK_TRAMPOLINE(0xf20) | ||
| 567 | |||
| 568 | .globl bad_stack_book3e | ||
| 569 | bad_stack_book3e: | ||
| 570 | /* XXX: Needs to make SPRN_SPRG_GEN depend on exception type */ | ||
| 571 | mfspr r10,SPRN_SRR0; /* read SRR0 before touching stack */ | ||
| 572 | ld r1,PACAEMERGSP(r13) | ||
| 573 | subi r1,r1,64+INT_FRAME_SIZE | ||
| 574 | std r10,_NIP(r1) | ||
| 575 | std r11,_MSR(r1) | ||
| 576 | ld r10,PACA_EXGEN+EX_R1(r13) /* FIXME for crit & mcheck */ | ||
| 577 | lwz r11,PACA_EXGEN+EX_CR(r13) /* FIXME for crit & mcheck */ | ||
| 578 | std r10,GPR1(r1) | ||
| 579 | std r11,_CCR(r1) | ||
| 580 | mfspr r10,SPRN_DEAR | ||
| 581 | mfspr r11,SPRN_ESR | ||
| 582 | std r10,_DAR(r1) | ||
| 583 | std r11,_DSISR(r1) | ||
| 584 | std r0,GPR0(r1); /* save r0 in stackframe */ \ | ||
| 585 | std r2,GPR2(r1); /* save r2 in stackframe */ \ | ||
| 586 | SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \ | ||
| 587 | SAVE_2GPRS(7, r1); /* save r7, r8 in stackframe */ \ | ||
| 588 | std r9,GPR9(r1); /* save r9 in stackframe */ \ | ||
| 589 | ld r3,PACA_EXGEN+EX_R10(r13);/* get back r10 */ \ | ||
| 590 | ld r4,PACA_EXGEN+EX_R11(r13);/* get back r11 */ \ | ||
| 591 | mfspr r5,SPRN_SPRG_GEN_SCRATCH;/* get back r13 XXX can be wrong */ \ | ||
| 592 | std r3,GPR10(r1); /* save r10 to stackframe */ \ | ||
| 593 | std r4,GPR11(r1); /* save r11 to stackframe */ \ | ||
| 594 | std r12,GPR12(r1); /* save r12 in stackframe */ \ | ||
| 595 | std r5,GPR13(r1); /* save it to stackframe */ \ | ||
| 596 | mflr r10 | ||
| 597 | mfctr r11 | ||
| 598 | mfxer r12 | ||
| 599 | std r10,_LINK(r1) | ||
| 600 | std r11,_CTR(r1) | ||
| 601 | std r12,_XER(r1) | ||
| 602 | SAVE_10GPRS(14,r1) | ||
| 603 | SAVE_8GPRS(24,r1) | ||
| 604 | lhz r12,PACA_TRAP_SAVE(r13) | ||
| 605 | std r12,_TRAP(r1) | ||
| 606 | addi r11,r1,INT_FRAME_SIZE | ||
| 607 | std r11,0(r1) | ||
| 608 | li r12,0 | ||
| 609 | std r12,0(r11) | ||
| 610 | ld r2,PACATOC(r13) | ||
| 611 | 1: addi r3,r1,STACK_FRAME_OVERHEAD | ||
| 612 | bl .kernel_bad_stack | ||
| 613 | b 1b | ||
| 614 | |||
| 615 | /* | ||
| 616 | * Setup the initial TLB for a core. This current implementation | ||
| 617 | * assume that whatever we are running off will not conflict with | ||
| 618 | * the new mapping at PAGE_OFFSET. | ||
| 619 | */ | ||
| 620 | _GLOBAL(initial_tlb_book3e) | ||
| 621 | |||
| 622 | /* Look for the first TLB with IPROT set */ | ||
| 623 | mfspr r4,SPRN_TLB0CFG | ||
| 624 | andi. r3,r4,TLBnCFG_IPROT | ||
| 625 | lis r3,MAS0_TLBSEL(0)@h | ||
| 626 | bne found_iprot | ||
| 627 | |||
| 628 | mfspr r4,SPRN_TLB1CFG | ||
| 629 | andi. r3,r4,TLBnCFG_IPROT | ||
| 630 | lis r3,MAS0_TLBSEL(1)@h | ||
| 631 | bne found_iprot | ||
| 632 | |||
| 633 | mfspr r4,SPRN_TLB2CFG | ||
| 634 | andi. r3,r4,TLBnCFG_IPROT | ||
| 635 | lis r3,MAS0_TLBSEL(2)@h | ||
| 636 | bne found_iprot | ||
| 637 | |||
| 638 | lis r3,MAS0_TLBSEL(3)@h | ||
| 639 | mfspr r4,SPRN_TLB3CFG | ||
| 640 | /* fall through */ | ||
| 641 | |||
| 642 | found_iprot: | ||
| 643 | andi. r5,r4,TLBnCFG_HES | ||
| 644 | bne have_hes | ||
| 645 | |||
| 646 | mflr r8 /* save LR */ | ||
| 647 | /* 1. Find the index of the entry we're executing in | ||
| 648 | * | ||
| 649 | * r3 = MAS0_TLBSEL (for the iprot array) | ||
| 650 | * r4 = SPRN_TLBnCFG | ||
| 651 | */ | ||
| 652 | bl invstr /* Find our address */ | ||
| 653 | invstr: mflr r6 /* Make it accessible */ | ||
| 654 | mfmsr r7 | ||
| 655 | rlwinm r5,r7,27,31,31 /* extract MSR[IS] */ | ||
| 656 | mfspr r7,SPRN_PID | ||
| 657 | slwi r7,r7,16 | ||
| 658 | or r7,r7,r5 | ||
| 659 | mtspr SPRN_MAS6,r7 | ||
| 660 | tlbsx 0,r6 /* search MSR[IS], SPID=PID */ | ||
| 661 | |||
| 662 | mfspr r3,SPRN_MAS0 | ||
| 663 | rlwinm r5,r3,16,20,31 /* Extract MAS0(Entry) */ | ||
| 664 | |||
| 665 | mfspr r7,SPRN_MAS1 /* Insure IPROT set */ | ||
| 666 | oris r7,r7,MAS1_IPROT@h | ||
| 667 | mtspr SPRN_MAS1,r7 | ||
| 668 | tlbwe | ||
| 669 | |||
| 670 | /* 2. Invalidate all entries except the entry we're executing in | ||
| 671 | * | ||
| 672 | * r3 = MAS0 w/TLBSEL & ESEL for the entry we are running in | ||
| 673 | * r4 = SPRN_TLBnCFG | ||
| 674 | * r5 = ESEL of entry we are running in | ||
| 675 | */ | ||
| 676 | andi. r4,r4,TLBnCFG_N_ENTRY /* Extract # entries */ | ||
| 677 | li r6,0 /* Set Entry counter to 0 */ | ||
| 678 | 1: mr r7,r3 /* Set MAS0(TLBSEL) */ | ||
| 679 | rlwimi r7,r6,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r6) */ | ||
| 680 | mtspr SPRN_MAS0,r7 | ||
| 681 | tlbre | ||
| 682 | mfspr r7,SPRN_MAS1 | ||
| 683 | rlwinm r7,r7,0,2,31 /* Clear MAS1 Valid and IPROT */ | ||
| 684 | cmpw r5,r6 | ||
| 685 | beq skpinv /* Dont update the current execution TLB */ | ||
| 686 | mtspr SPRN_MAS1,r7 | ||
| 687 | tlbwe | ||
| 688 | isync | ||
| 689 | skpinv: addi r6,r6,1 /* Increment */ | ||
| 690 | cmpw r6,r4 /* Are we done? */ | ||
| 691 | bne 1b /* If not, repeat */ | ||
| 692 | |||
| 693 | /* Invalidate all TLBs */ | ||
| 694 | PPC_TLBILX_ALL(0,0) | ||
| 695 | sync | ||
| 696 | isync | ||
| 697 | |||
| 698 | /* 3. Setup a temp mapping and jump to it | ||
| 699 | * | ||
| 700 | * r3 = MAS0 w/TLBSEL & ESEL for the entry we are running in | ||
| 701 | * r5 = ESEL of entry we are running in | ||
| 702 | */ | ||
| 703 | andi. r7,r5,0x1 /* Find an entry not used and is non-zero */ | ||
| 704 | addi r7,r7,0x1 | ||
| 705 | mr r4,r3 /* Set MAS0(TLBSEL) = 1 */ | ||
| 706 | mtspr SPRN_MAS0,r4 | ||
| 707 | tlbre | ||
| 708 | |||
| 709 | rlwimi r4,r7,16,4,15 /* Setup MAS0 = TLBSEL | ESEL(r7) */ | ||
| 710 | mtspr SPRN_MAS0,r4 | ||
| 711 | |||
| 712 | mfspr r7,SPRN_MAS1 | ||
| 713 | xori r6,r7,MAS1_TS /* Setup TMP mapping in the other Address space */ | ||
| 714 | mtspr SPRN_MAS1,r6 | ||
| 715 | |||
| 716 | tlbwe | ||
| 717 | |||
| 718 | mfmsr r6 | ||
| 719 | xori r6,r6,MSR_IS | ||
| 720 | mtspr SPRN_SRR1,r6 | ||
| 721 | bl 1f /* Find our address */ | ||
| 722 | 1: mflr r6 | ||
| 723 | addi r6,r6,(2f - 1b) | ||
| 724 | mtspr SPRN_SRR0,r6 | ||
| 725 | rfi | ||
| 726 | 2: | ||
| 727 | |||
| 728 | /* 4. Clear out PIDs & Search info | ||
| 729 | * | ||
| 730 | * r3 = MAS0 w/TLBSEL & ESEL for the entry we started in | ||
| 731 | * r4 = MAS0 w/TLBSEL & ESEL for the temp mapping | ||
| 732 | * r5 = MAS3 | ||
| 733 | */ | ||
| 734 | li r6,0 | ||
| 735 | mtspr SPRN_MAS6,r6 | ||
| 736 | mtspr SPRN_PID,r6 | ||
| 737 | |||
| 738 | /* 5. Invalidate mapping we started in | ||
| 739 | * | ||
| 740 | * r3 = MAS0 w/TLBSEL & ESEL for the entry we started in | ||
| 741 | * r4 = MAS0 w/TLBSEL & ESEL for the temp mapping | ||
| 742 | * r5 = MAS3 | ||
| 743 | */ | ||
| 744 | mtspr SPRN_MAS0,r3 | ||
| 745 | tlbre | ||
| 746 | mfspr r6,SPRN_MAS1 | ||
| 747 | rlwinm r6,r6,0,2,0 /* clear IPROT */ | ||
| 748 | mtspr SPRN_MAS1,r6 | ||
| 749 | tlbwe | ||
| 750 | |||
| 751 | /* Invalidate TLB1 */ | ||
| 752 | PPC_TLBILX_ALL(0,0) | ||
| 753 | sync | ||
| 754 | isync | ||
| 755 | |||
| 756 | /* The mapping only needs to be cache-coherent on SMP */ | ||
| 757 | #ifdef CONFIG_SMP | ||
| 758 | #define M_IF_SMP MAS2_M | ||
| 759 | #else | ||
| 760 | #define M_IF_SMP 0 | ||
| 761 | #endif | ||
| 762 | |||
| 763 | /* 6. Setup KERNELBASE mapping in TLB[0] | ||
| 764 | * | ||
| 765 | * r3 = MAS0 w/TLBSEL & ESEL for the entry we started in | ||
| 766 | * r4 = MAS0 w/TLBSEL & ESEL for the temp mapping | ||
| 767 | * r5 = MAS3 | ||
| 768 | */ | ||
| 769 | rlwinm r3,r3,0,16,3 /* clear ESEL */ | ||
| 770 | mtspr SPRN_MAS0,r3 | ||
| 771 | lis r6,(MAS1_VALID|MAS1_IPROT)@h | ||
| 772 | ori r6,r6,(MAS1_TSIZE(BOOK3E_PAGESZ_1GB))@l | ||
| 773 | mtspr SPRN_MAS1,r6 | ||
| 774 | |||
| 775 | LOAD_REG_IMMEDIATE(r6, PAGE_OFFSET | M_IF_SMP) | ||
| 776 | mtspr SPRN_MAS2,r6 | ||
| 777 | |||
| 778 | rlwinm r5,r5,0,0,25 | ||
| 779 | ori r5,r5,MAS3_SR | MAS3_SW | MAS3_SX | ||
| 780 | mtspr SPRN_MAS3,r5 | ||
| 781 | li r5,-1 | ||
| 782 | rlwinm r5,r5,0,0,25 | ||
| 783 | |||
| 784 | tlbwe | ||
| 785 | |||
| 786 | /* 7. Jump to KERNELBASE mapping | ||
| 787 | * | ||
| 788 | * r4 = MAS0 w/TLBSEL & ESEL for the temp mapping | ||
| 789 | */ | ||
| 790 | /* Now we branch the new virtual address mapped by this entry */ | ||
| 791 | LOAD_REG_IMMEDIATE(r6,2f) | ||
| 792 | lis r7,MSR_KERNEL@h | ||
| 793 | ori r7,r7,MSR_KERNEL@l | ||
| 794 | mtspr SPRN_SRR0,r6 | ||
| 795 | mtspr SPRN_SRR1,r7 | ||
| 796 | rfi /* start execution out of TLB1[0] entry */ | ||
| 797 | 2: | ||
| 798 | |||
| 799 | /* 8. Clear out the temp mapping | ||
| 800 | * | ||
| 801 | * r4 = MAS0 w/TLBSEL & ESEL for the entry we are running in | ||
| 802 | */ | ||
| 803 | mtspr SPRN_MAS0,r4 | ||
| 804 | tlbre | ||
| 805 | mfspr r5,SPRN_MAS1 | ||
| 806 | rlwinm r5,r5,0,2,0 /* clear IPROT */ | ||
| 807 | mtspr SPRN_MAS1,r5 | ||
| 808 | tlbwe | ||
| 809 | |||
| 810 | /* Invalidate TLB1 */ | ||
| 811 | PPC_TLBILX_ALL(0,0) | ||
| 812 | sync | ||
| 813 | isync | ||
| 814 | |||
| 815 | /* We translate LR and return */ | ||
| 816 | tovirt(r8,r8) | ||
| 817 | mtlr r8 | ||
| 818 | blr | ||
| 819 | |||
| 820 | have_hes: | ||
| 821 | /* Setup MAS 0,1,2,3 and 7 for tlbwe of a 1G entry that maps the | ||
| 822 | * kernel linear mapping. We also set MAS8 once for all here though | ||
| 823 | * that will have to be made dependent on whether we are running under | ||
| 824 | * a hypervisor I suppose. | ||
| 825 | */ | ||
| 826 | ori r3,r3,MAS0_HES | MAS0_WQ_ALLWAYS | ||
| 827 | mtspr SPRN_MAS0,r3 | ||
| 828 | lis r3,(MAS1_VALID | MAS1_IPROT)@h | ||
| 829 | ori r3,r3,BOOK3E_PAGESZ_1GB << MAS1_TSIZE_SHIFT | ||
| 830 | mtspr SPRN_MAS1,r3 | ||
| 831 | LOAD_REG_IMMEDIATE(r3, PAGE_OFFSET | MAS2_M) | ||
| 832 | mtspr SPRN_MAS2,r3 | ||
| 833 | li r3,MAS3_SR | MAS3_SW | MAS3_SX | ||
| 834 | mtspr SPRN_MAS7_MAS3,r3 | ||
| 835 | li r3,0 | ||
| 836 | mtspr SPRN_MAS8,r3 | ||
| 837 | |||
| 838 | /* Write the TLB entry */ | ||
| 839 | tlbwe | ||
| 840 | |||
| 841 | /* Now we branch the new virtual address mapped by this entry */ | ||
| 842 | LOAD_REG_IMMEDIATE(r3,1f) | ||
| 843 | mtctr r3 | ||
| 844 | bctr | ||
| 845 | |||
| 846 | 1: /* We are now running at PAGE_OFFSET, clean the TLB of everything | ||
| 847 | * else (XXX we should scan for bolted crap from the firmware too) | ||
| 848 | */ | ||
| 849 | PPC_TLBILX(0,0,0) | ||
| 850 | sync | ||
| 851 | isync | ||
| 852 | |||
| 853 | /* We translate LR and return */ | ||
| 854 | mflr r3 | ||
| 855 | tovirt(r3,r3) | ||
| 856 | mtlr r3 | ||
| 857 | blr | ||
| 858 | |||
| 859 | /* | ||
| 860 | * Main entry (boot CPU, thread 0) | ||
| 861 | * | ||
| 862 | * We enter here from head_64.S, possibly after the prom_init trampoline | ||
| 863 | * with r3 and r4 already saved to r31 and 30 respectively and in 64 bits | ||
| 864 | * mode. Anything else is as it was left by the bootloader | ||
| 865 | * | ||
| 866 | * Initial requirements of this port: | ||
| 867 | * | ||
| 868 | * - Kernel loaded at 0 physical | ||
| 869 | * - A good lump of memory mapped 0:0 by UTLB entry 0 | ||
| 870 | * - MSR:IS & MSR:DS set to 0 | ||
| 871 | * | ||
| 872 | * Note that some of the above requirements will be relaxed in the future | ||
| 873 | * as the kernel becomes smarter at dealing with different initial conditions | ||
| 874 | * but for now you have to be careful | ||
| 875 | */ | ||
| 876 | _GLOBAL(start_initialization_book3e) | ||
| 877 | mflr r28 | ||
| 878 | |||
| 879 | /* First, we need to setup some initial TLBs to map the kernel | ||
| 880 | * text, data and bss at PAGE_OFFSET. We don't have a real mode | ||
| 881 | * and always use AS 0, so we just set it up to match our link | ||
| 882 | * address and never use 0 based addresses. | ||
| 883 | */ | ||
| 884 | bl .initial_tlb_book3e | ||
| 885 | |||
| 886 | /* Init global core bits */ | ||
| 887 | bl .init_core_book3e | ||
| 888 | |||
| 889 | /* Init per-thread bits */ | ||
| 890 | bl .init_thread_book3e | ||
| 891 | |||
| 892 | /* Return to common init code */ | ||
| 893 | tovirt(r28,r28) | ||
| 894 | mtlr r28 | ||
| 895 | blr | ||
| 896 | |||
| 897 | |||
| 898 | /* | ||
| 899 | * Secondary core/processor entry | ||
| 900 | * | ||
| 901 | * This is entered for thread 0 of a secondary core, all other threads | ||
| 902 | * are expected to be stopped. It's similar to start_initialization_book3e | ||
| 903 | * except that it's generally entered from the holding loop in head_64.S | ||
| 904 | * after CPUs have been gathered by Open Firmware. | ||
| 905 | * | ||
| 906 | * We assume we are in 32 bits mode running with whatever TLB entry was | ||
| 907 | * set for us by the firmware or POR engine. | ||
| 908 | */ | ||
| 909 | _GLOBAL(book3e_secondary_core_init_tlb_set) | ||
| 910 | li r4,1 | ||
| 911 | b .generic_secondary_smp_init | ||
| 912 | |||
| 913 | _GLOBAL(book3e_secondary_core_init) | ||
| 914 | mflr r28 | ||
| 915 | |||
| 916 | /* Do we need to setup initial TLB entry ? */ | ||
| 917 | cmplwi r4,0 | ||
| 918 | bne 2f | ||
| 919 | |||
| 920 | /* Setup TLB for this core */ | ||
| 921 | bl .initial_tlb_book3e | ||
| 922 | |||
| 923 | /* We can return from the above running at a different | ||
| 924 | * address, so recalculate r2 (TOC) | ||
| 925 | */ | ||
| 926 | bl .relative_toc | ||
| 927 | |||
| 928 | /* Init global core bits */ | ||
| 929 | 2: bl .init_core_book3e | ||
| 930 | |||
| 931 | /* Init per-thread bits */ | ||
| 932 | 3: bl .init_thread_book3e | ||
| 933 | |||
| 934 | /* Return to common init code at proper virtual address. | ||
| 935 | * | ||
| 936 | * Due to various previous assumptions, we know we entered this | ||
| 937 | * function at either the final PAGE_OFFSET mapping or using a | ||
| 938 | * 1:1 mapping at 0, so we don't bother doing a complicated check | ||
| 939 | * here, we just ensure the return address has the right top bits. | ||
| 940 | * | ||
| 941 | * Note that if we ever want to be smarter about where we can be | ||
| 942 | * started from, we have to be careful that by the time we reach | ||
| 943 | * the code below we may already be running at a different location | ||
| 944 | * than the one we were called from since initial_tlb_book3e can | ||
| 945 | * have moved us already. | ||
| 946 | */ | ||
| 947 | cmpdi cr0,r28,0 | ||
| 948 | blt 1f | ||
| 949 | lis r3,PAGE_OFFSET@highest | ||
| 950 | sldi r3,r3,32 | ||
| 951 | or r28,r28,r3 | ||
| 952 | 1: mtlr r28 | ||
| 953 | blr | ||
| 954 | |||
| 955 | _GLOBAL(book3e_secondary_thread_init) | ||
| 956 | mflr r28 | ||
| 957 | b 3b | ||
| 958 | |||
| 959 | _STATIC(init_core_book3e) | ||
| 960 | /* Establish the interrupt vector base */ | ||
| 961 | LOAD_REG_IMMEDIATE(r3, interrupt_base_book3e) | ||
| 962 | mtspr SPRN_IVPR,r3 | ||
| 963 | sync | ||
| 964 | blr | ||
| 965 | |||
| 966 | _STATIC(init_thread_book3e) | ||
| 967 | lis r3,(SPRN_EPCR_ICM | SPRN_EPCR_GICM)@h | ||
| 968 | mtspr SPRN_EPCR,r3 | ||
| 969 | |||
| 970 | /* Make sure interrupts are off */ | ||
| 971 | wrteei 0 | ||
| 972 | |||
| 973 | /* disable all timers and clear out status */ | ||
| 974 | li r3,0 | ||
| 975 | mtspr SPRN_TCR,r3 | ||
| 976 | mfspr r3,SPRN_TSR | ||
| 977 | mtspr SPRN_TSR,r3 | ||
| 978 | |||
| 979 | blr | ||
| 980 | |||
| 981 | _GLOBAL(__setup_base_ivors) | ||
| 982 | SET_IVOR(0, 0x020) /* Critical Input */ | ||
| 983 | SET_IVOR(1, 0x000) /* Machine Check */ | ||
| 984 | SET_IVOR(2, 0x060) /* Data Storage */ | ||
| 985 | SET_IVOR(3, 0x080) /* Instruction Storage */ | ||
| 986 | SET_IVOR(4, 0x0a0) /* External Input */ | ||
| 987 | SET_IVOR(5, 0x0c0) /* Alignment */ | ||
| 988 | SET_IVOR(6, 0x0e0) /* Program */ | ||
| 989 | SET_IVOR(7, 0x100) /* FP Unavailable */ | ||
| 990 | SET_IVOR(8, 0x120) /* System Call */ | ||
| 991 | SET_IVOR(9, 0x140) /* Auxiliary Processor Unavailable */ | ||
| 992 | SET_IVOR(10, 0x160) /* Decrementer */ | ||
| 993 | SET_IVOR(11, 0x180) /* Fixed Interval Timer */ | ||
| 994 | SET_IVOR(12, 0x1a0) /* Watchdog Timer */ | ||
| 995 | SET_IVOR(13, 0x1c0) /* Data TLB Error */ | ||
| 996 | SET_IVOR(14, 0x1e0) /* Instruction TLB Error */ | ||
| 997 | SET_IVOR(15, 0x040) /* Debug */ | ||
| 998 | |||
| 999 | sync | ||
| 1000 | |||
| 1001 | blr | ||
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index 8ac85e08ffae..1808876edcc9 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
| @@ -12,6 +12,8 @@ | |||
| 12 | * | 12 | * |
| 13 | */ | 13 | */ |
| 14 | 14 | ||
| 15 | #include <asm/exception-64s.h> | ||
| 16 | |||
| 15 | /* | 17 | /* |
| 16 | * We layout physical memory as follows: | 18 | * We layout physical memory as follows: |
| 17 | * 0x0000 - 0x00ff : Secondary processor spin code | 19 | * 0x0000 - 0x00ff : Secondary processor spin code |
| @@ -22,18 +24,6 @@ | |||
| 22 | * 0x8000 - : Early init and support code | 24 | * 0x8000 - : Early init and support code |
| 23 | */ | 25 | */ |
| 24 | 26 | ||
| 25 | |||
| 26 | /* | ||
| 27 | * SPRG Usage | ||
| 28 | * | ||
| 29 | * Register Definition | ||
| 30 | * | ||
| 31 | * SPRG0 reserved for hypervisor | ||
| 32 | * SPRG1 temp - used to save gpr | ||
| 33 | * SPRG2 temp - used to save gpr | ||
| 34 | * SPRG3 virt addr of paca | ||
| 35 | */ | ||
| 36 | |||
| 37 | /* | 27 | /* |
| 38 | * This is the start of the interrupt handlers for pSeries | 28 | * This is the start of the interrupt handlers for pSeries |
| 39 | * This code runs with relocation off. | 29 | * This code runs with relocation off. |
| @@ -51,34 +41,44 @@ __start_interrupts: | |||
| 51 | . = 0x200 | 41 | . = 0x200 |
| 52 | _machine_check_pSeries: | 42 | _machine_check_pSeries: |
| 53 | HMT_MEDIUM | 43 | HMT_MEDIUM |
| 54 | mtspr SPRN_SPRG1,r13 /* save r13 */ | 44 | mtspr SPRN_SPRG_SCRATCH0,r13 /* save r13 */ |
| 55 | EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common) | 45 | EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common) |
| 56 | 46 | ||
| 57 | . = 0x300 | 47 | . = 0x300 |
| 58 | .globl data_access_pSeries | 48 | .globl data_access_pSeries |
| 59 | data_access_pSeries: | 49 | data_access_pSeries: |
| 60 | HMT_MEDIUM | 50 | HMT_MEDIUM |
| 61 | mtspr SPRN_SPRG1,r13 | 51 | mtspr SPRN_SPRG_SCRATCH0,r13 |
| 62 | BEGIN_FTR_SECTION | 52 | BEGIN_FTR_SECTION |
| 63 | mtspr SPRN_SPRG2,r12 | 53 | mfspr r13,SPRN_SPRG_PACA |
| 64 | mfspr r13,SPRN_DAR | 54 | std r9,PACA_EXSLB+EX_R9(r13) |
| 65 | mfspr r12,SPRN_DSISR | 55 | std r10,PACA_EXSLB+EX_R10(r13) |
| 66 | srdi r13,r13,60 | 56 | mfspr r10,SPRN_DAR |
| 67 | rlwimi r13,r12,16,0x20 | 57 | mfspr r9,SPRN_DSISR |
| 68 | mfcr r12 | 58 | srdi r10,r10,60 |
| 69 | cmpwi r13,0x2c | 59 | rlwimi r10,r9,16,0x20 |
| 60 | mfcr r9 | ||
| 61 | cmpwi r10,0x2c | ||
| 70 | beq do_stab_bolted_pSeries | 62 | beq do_stab_bolted_pSeries |
| 71 | mtcrf 0x80,r12 | 63 | ld r10,PACA_EXSLB+EX_R10(r13) |
| 72 | mfspr r12,SPRN_SPRG2 | 64 | std r11,PACA_EXGEN+EX_R11(r13) |
| 73 | END_FTR_SECTION_IFCLR(CPU_FTR_SLB) | 65 | ld r11,PACA_EXSLB+EX_R9(r13) |
| 66 | std r12,PACA_EXGEN+EX_R12(r13) | ||
| 67 | mfspr r12,SPRN_SPRG_SCRATCH0 | ||
| 68 | std r10,PACA_EXGEN+EX_R10(r13) | ||
| 69 | std r11,PACA_EXGEN+EX_R9(r13) | ||
| 70 | std r12,PACA_EXGEN+EX_R13(r13) | ||
| 71 | EXCEPTION_PROLOG_PSERIES_1(data_access_common) | ||
| 72 | FTR_SECTION_ELSE | ||
| 74 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common) | 73 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, data_access_common) |
| 74 | ALT_FTR_SECTION_END_IFCLR(CPU_FTR_SLB) | ||
| 75 | 75 | ||
| 76 | . = 0x380 | 76 | . = 0x380 |
| 77 | .globl data_access_slb_pSeries | 77 | .globl data_access_slb_pSeries |
| 78 | data_access_slb_pSeries: | 78 | data_access_slb_pSeries: |
| 79 | HMT_MEDIUM | 79 | HMT_MEDIUM |
| 80 | mtspr SPRN_SPRG1,r13 | 80 | mtspr SPRN_SPRG_SCRATCH0,r13 |
| 81 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ | 81 | mfspr r13,SPRN_SPRG_PACA /* get paca address into r13 */ |
| 82 | std r3,PACA_EXSLB+EX_R3(r13) | 82 | std r3,PACA_EXSLB+EX_R3(r13) |
| 83 | mfspr r3,SPRN_DAR | 83 | mfspr r3,SPRN_DAR |
| 84 | std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ | 84 | std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ |
| @@ -91,7 +91,7 @@ data_access_slb_pSeries: | |||
| 91 | std r10,PACA_EXSLB+EX_R10(r13) | 91 | std r10,PACA_EXSLB+EX_R10(r13) |
| 92 | std r11,PACA_EXSLB+EX_R11(r13) | 92 | std r11,PACA_EXSLB+EX_R11(r13) |
| 93 | std r12,PACA_EXSLB+EX_R12(r13) | 93 | std r12,PACA_EXSLB+EX_R12(r13) |
| 94 | mfspr r10,SPRN_SPRG1 | 94 | mfspr r10,SPRN_SPRG_SCRATCH0 |
| 95 | std r10,PACA_EXSLB+EX_R13(r13) | 95 | std r10,PACA_EXSLB+EX_R13(r13) |
| 96 | mfspr r12,SPRN_SRR1 /* and SRR1 */ | 96 | mfspr r12,SPRN_SRR1 /* and SRR1 */ |
| 97 | #ifndef CONFIG_RELOCATABLE | 97 | #ifndef CONFIG_RELOCATABLE |
| @@ -115,8 +115,8 @@ data_access_slb_pSeries: | |||
| 115 | .globl instruction_access_slb_pSeries | 115 | .globl instruction_access_slb_pSeries |
| 116 | instruction_access_slb_pSeries: | 116 | instruction_access_slb_pSeries: |
| 117 | HMT_MEDIUM | 117 | HMT_MEDIUM |
| 118 | mtspr SPRN_SPRG1,r13 | 118 | mtspr SPRN_SPRG_SCRATCH0,r13 |
| 119 | mfspr r13,SPRN_SPRG3 /* get paca address into r13 */ | 119 | mfspr r13,SPRN_SPRG_PACA /* get paca address into r13 */ |
| 120 | std r3,PACA_EXSLB+EX_R3(r13) | 120 | std r3,PACA_EXSLB+EX_R3(r13) |
| 121 | mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ | 121 | mfspr r3,SPRN_SRR0 /* SRR0 is faulting address */ |
| 122 | std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ | 122 | std r9,PACA_EXSLB+EX_R9(r13) /* save r9 - r12 */ |
| @@ -129,7 +129,7 @@ instruction_access_slb_pSeries: | |||
| 129 | std r10,PACA_EXSLB+EX_R10(r13) | 129 | std r10,PACA_EXSLB+EX_R10(r13) |
| 130 | std r11,PACA_EXSLB+EX_R11(r13) | 130 | std r11,PACA_EXSLB+EX_R11(r13) |
| 131 | std r12,PACA_EXSLB+EX_R12(r13) | 131 | std r12,PACA_EXSLB+EX_R12(r13) |
| 132 | mfspr r10,SPRN_SPRG1 | 132 | mfspr r10,SPRN_SPRG_SCRATCH0 |
| 133 | std r10,PACA_EXSLB+EX_R13(r13) | 133 | std r10,PACA_EXSLB+EX_R13(r13) |
| 134 | mfspr r12,SPRN_SRR1 /* and SRR1 */ | 134 | mfspr r12,SPRN_SRR1 /* and SRR1 */ |
| 135 | #ifndef CONFIG_RELOCATABLE | 135 | #ifndef CONFIG_RELOCATABLE |
| @@ -159,7 +159,7 @@ BEGIN_FTR_SECTION | |||
| 159 | beq- 1f | 159 | beq- 1f |
| 160 | END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) | 160 | END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE) |
| 161 | mr r9,r13 | 161 | mr r9,r13 |
| 162 | mfspr r13,SPRN_SPRG3 | 162 | mfspr r13,SPRN_SPRG_PACA |
| 163 | mfspr r11,SPRN_SRR0 | 163 | mfspr r11,SPRN_SRR0 |
| 164 | ld r12,PACAKBASE(r13) | 164 | ld r12,PACAKBASE(r13) |
| 165 | ld r10,PACAKMSR(r13) | 165 | ld r10,PACAKMSR(r13) |
| @@ -228,15 +228,17 @@ masked_interrupt: | |||
| 228 | rotldi r10,r10,16 | 228 | rotldi r10,r10,16 |
| 229 | mtspr SPRN_SRR1,r10 | 229 | mtspr SPRN_SRR1,r10 |
| 230 | ld r10,PACA_EXGEN+EX_R10(r13) | 230 | ld r10,PACA_EXGEN+EX_R10(r13) |
| 231 | mfspr r13,SPRN_SPRG1 | 231 | mfspr r13,SPRN_SPRG_SCRATCH0 |
| 232 | rfid | 232 | rfid |
| 233 | b . | 233 | b . |
| 234 | 234 | ||
| 235 | .align 7 | 235 | .align 7 |
| 236 | do_stab_bolted_pSeries: | 236 | do_stab_bolted_pSeries: |
| 237 | mtcrf 0x80,r12 | 237 | std r11,PACA_EXSLB+EX_R11(r13) |
| 238 | mfspr r12,SPRN_SPRG2 | 238 | std r12,PACA_EXSLB+EX_R12(r13) |
| 239 | EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted) | 239 | mfspr r10,SPRN_SPRG_SCRATCH0 |
| 240 | std r10,PACA_EXSLB+EX_R13(r13) | ||
| 241 | EXCEPTION_PROLOG_PSERIES_1(.do_stab_bolted) | ||
| 240 | 242 | ||
| 241 | #ifdef CONFIG_PPC_PSERIES | 243 | #ifdef CONFIG_PPC_PSERIES |
| 242 | /* | 244 | /* |
| @@ -246,14 +248,14 @@ do_stab_bolted_pSeries: | |||
| 246 | .align 7 | 248 | .align 7 |
| 247 | system_reset_fwnmi: | 249 | system_reset_fwnmi: |
| 248 | HMT_MEDIUM | 250 | HMT_MEDIUM |
| 249 | mtspr SPRN_SPRG1,r13 /* save r13 */ | 251 | mtspr SPRN_SPRG_SCRATCH0,r13 /* save r13 */ |
| 250 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common) | 252 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common) |
| 251 | 253 | ||
| 252 | .globl machine_check_fwnmi | 254 | .globl machine_check_fwnmi |
| 253 | .align 7 | 255 | .align 7 |
| 254 | machine_check_fwnmi: | 256 | machine_check_fwnmi: |
| 255 | HMT_MEDIUM | 257 | HMT_MEDIUM |
| 256 | mtspr SPRN_SPRG1,r13 /* save r13 */ | 258 | mtspr SPRN_SPRG_SCRATCH0,r13 /* save r13 */ |
| 257 | EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common) | 259 | EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common) |
| 258 | 260 | ||
| 259 | #endif /* CONFIG_PPC_PSERIES */ | 261 | #endif /* CONFIG_PPC_PSERIES */ |
| @@ -268,7 +270,7 @@ slb_miss_user_pseries: | |||
| 268 | std r10,PACA_EXGEN+EX_R10(r13) | 270 | std r10,PACA_EXGEN+EX_R10(r13) |
| 269 | std r11,PACA_EXGEN+EX_R11(r13) | 271 | std r11,PACA_EXGEN+EX_R11(r13) |
| 270 | std r12,PACA_EXGEN+EX_R12(r13) | 272 | std r12,PACA_EXGEN+EX_R12(r13) |
| 271 | mfspr r10,SPRG1 | 273 | mfspr r10,SPRG_SCRATCH0 |
| 272 | ld r11,PACA_EXSLB+EX_R9(r13) | 274 | ld r11,PACA_EXSLB+EX_R9(r13) |
| 273 | ld r12,PACA_EXSLB+EX_R3(r13) | 275 | ld r12,PACA_EXSLB+EX_R3(r13) |
| 274 | std r10,PACA_EXGEN+EX_R13(r13) | 276 | std r10,PACA_EXGEN+EX_R13(r13) |
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S index 2436df33c6f4..fc8f5b14019c 100644 --- a/arch/powerpc/kernel/fpu.S +++ b/arch/powerpc/kernel/fpu.S | |||
| @@ -91,7 +91,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX) | |||
| 91 | #endif /* CONFIG_SMP */ | 91 | #endif /* CONFIG_SMP */ |
| 92 | /* enable use of FP after return */ | 92 | /* enable use of FP after return */ |
| 93 | #ifdef CONFIG_PPC32 | 93 | #ifdef CONFIG_PPC32 |
| 94 | mfspr r5,SPRN_SPRG3 /* current task's THREAD (phys) */ | 94 | mfspr r5,SPRN_SPRG_THREAD /* current task's THREAD (phys) */ |
| 95 | lwz r4,THREAD_FPEXC_MODE(r5) | 95 | lwz r4,THREAD_FPEXC_MODE(r5) |
| 96 | ori r9,r9,MSR_FP /* enable FP for current */ | 96 | ori r9,r9,MSR_FP /* enable FP for current */ |
| 97 | or r9,r9,r4 | 97 | or r9,r9,r4 |
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S index fc2132942754..829c3fe7c5a2 100644 --- a/arch/powerpc/kernel/head_32.S +++ b/arch/powerpc/kernel/head_32.S | |||
| @@ -244,8 +244,8 @@ __secondary_hold_acknowledge: | |||
| 244 | * task's thread_struct. | 244 | * task's thread_struct. |
| 245 | */ | 245 | */ |
| 246 | #define EXCEPTION_PROLOG \ | 246 | #define EXCEPTION_PROLOG \ |
| 247 | mtspr SPRN_SPRG0,r10; \ | 247 | mtspr SPRN_SPRG_SCRATCH0,r10; \ |
| 248 | mtspr SPRN_SPRG1,r11; \ | 248 | mtspr SPRN_SPRG_SCRATCH1,r11; \ |
| 249 | mfcr r10; \ | 249 | mfcr r10; \ |
| 250 | EXCEPTION_PROLOG_1; \ | 250 | EXCEPTION_PROLOG_1; \ |
| 251 | EXCEPTION_PROLOG_2 | 251 | EXCEPTION_PROLOG_2 |
| @@ -255,7 +255,7 @@ __secondary_hold_acknowledge: | |||
| 255 | andi. r11,r11,MSR_PR; \ | 255 | andi. r11,r11,MSR_PR; \ |
| 256 | tophys(r11,r1); /* use tophys(r1) if kernel */ \ | 256 | tophys(r11,r1); /* use tophys(r1) if kernel */ \ |
| 257 | beq 1f; \ | 257 | beq 1f; \ |
| 258 | mfspr r11,SPRN_SPRG3; \ | 258 | mfspr r11,SPRN_SPRG_THREAD; \ |
| 259 | lwz r11,THREAD_INFO-THREAD(r11); \ | 259 | lwz r11,THREAD_INFO-THREAD(r11); \ |
| 260 | addi r11,r11,THREAD_SIZE; \ | 260 | addi r11,r11,THREAD_SIZE; \ |
| 261 | tophys(r11,r11); \ | 261 | tophys(r11,r11); \ |
| @@ -267,9 +267,9 @@ __secondary_hold_acknowledge: | |||
| 267 | stw r10,_CCR(r11); /* save registers */ \ | 267 | stw r10,_CCR(r11); /* save registers */ \ |
| 268 | stw r12,GPR12(r11); \ | 268 | stw r12,GPR12(r11); \ |
| 269 | stw r9,GPR9(r11); \ | 269 | stw r9,GPR9(r11); \ |
| 270 | mfspr r10,SPRN_SPRG0; \ | 270 | mfspr r10,SPRN_SPRG_SCRATCH0; \ |
| 271 | stw r10,GPR10(r11); \ | 271 | stw r10,GPR10(r11); \ |
| 272 | mfspr r12,SPRN_SPRG1; \ | 272 | mfspr r12,SPRN_SPRG_SCRATCH1; \ |
| 273 | stw r12,GPR11(r11); \ | 273 | stw r12,GPR11(r11); \ |
| 274 | mflr r10; \ | 274 | mflr r10; \ |
| 275 | stw r10,_LINK(r11); \ | 275 | stw r10,_LINK(r11); \ |
| @@ -355,11 +355,11 @@ i##n: \ | |||
| 355 | * -- paulus. | 355 | * -- paulus. |
| 356 | */ | 356 | */ |
| 357 | . = 0x200 | 357 | . = 0x200 |
| 358 | mtspr SPRN_SPRG0,r10 | 358 | mtspr SPRN_SPRG_SCRATCH0,r10 |
| 359 | mtspr SPRN_SPRG1,r11 | 359 | mtspr SPRN_SPRG_SCRATCH1,r11 |
| 360 | mfcr r10 | 360 | mfcr r10 |
| 361 | #ifdef CONFIG_PPC_CHRP | 361 | #ifdef CONFIG_PPC_CHRP |
| 362 | mfspr r11,SPRN_SPRG2 | 362 | mfspr r11,SPRN_SPRG_RTAS |
| 363 | cmpwi 0,r11,0 | 363 | cmpwi 0,r11,0 |
| 364 | bne 7f | 364 | bne 7f |
| 365 | #endif /* CONFIG_PPC_CHRP */ | 365 | #endif /* CONFIG_PPC_CHRP */ |
| @@ -367,7 +367,7 @@ i##n: \ | |||
| 367 | 7: EXCEPTION_PROLOG_2 | 367 | 7: EXCEPTION_PROLOG_2 |
| 368 | addi r3,r1,STACK_FRAME_OVERHEAD | 368 | addi r3,r1,STACK_FRAME_OVERHEAD |
| 369 | #ifdef CONFIG_PPC_CHRP | 369 | #ifdef CONFIG_PPC_CHRP |
| 370 | mfspr r4,SPRN_SPRG2 | 370 | mfspr r4,SPRN_SPRG_RTAS |
| 371 | cmpwi cr1,r4,0 | 371 | cmpwi cr1,r4,0 |
| 372 | bne cr1,1f | 372 | bne cr1,1f |
| 373 | #endif | 373 | #endif |
| @@ -485,7 +485,7 @@ InstructionTLBMiss: | |||
| 485 | mfspr r3,SPRN_IMISS | 485 | mfspr r3,SPRN_IMISS |
| 486 | lis r1,PAGE_OFFSET@h /* check if kernel address */ | 486 | lis r1,PAGE_OFFSET@h /* check if kernel address */ |
| 487 | cmplw 0,r1,r3 | 487 | cmplw 0,r1,r3 |
| 488 | mfspr r2,SPRN_SPRG3 | 488 | mfspr r2,SPRN_SPRG_THREAD |
| 489 | li r1,_PAGE_USER|_PAGE_PRESENT /* low addresses tested as user */ | 489 | li r1,_PAGE_USER|_PAGE_PRESENT /* low addresses tested as user */ |
| 490 | lwz r2,PGDIR(r2) | 490 | lwz r2,PGDIR(r2) |
| 491 | bge- 112f | 491 | bge- 112f |
| @@ -559,7 +559,7 @@ DataLoadTLBMiss: | |||
| 559 | mfspr r3,SPRN_DMISS | 559 | mfspr r3,SPRN_DMISS |
| 560 | lis r1,PAGE_OFFSET@h /* check if kernel address */ | 560 | lis r1,PAGE_OFFSET@h /* check if kernel address */ |
| 561 | cmplw 0,r1,r3 | 561 | cmplw 0,r1,r3 |
| 562 | mfspr r2,SPRN_SPRG3 | 562 | mfspr r2,SPRN_SPRG_THREAD |
| 563 | li r1,_PAGE_USER|_PAGE_PRESENT /* low addresses tested as user */ | 563 | li r1,_PAGE_USER|_PAGE_PRESENT /* low addresses tested as user */ |
| 564 | lwz r2,PGDIR(r2) | 564 | lwz r2,PGDIR(r2) |
| 565 | bge- 112f | 565 | bge- 112f |
| @@ -598,12 +598,12 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) | |||
| 598 | mtcrf 0x80,r2 | 598 | mtcrf 0x80,r2 |
| 599 | BEGIN_MMU_FTR_SECTION | 599 | BEGIN_MMU_FTR_SECTION |
| 600 | li r0,1 | 600 | li r0,1 |
| 601 | mfspr r1,SPRN_SPRG4 | 601 | mfspr r1,SPRN_SPRG_603_LRU |
| 602 | rlwinm r2,r3,20,27,31 /* Get Address bits 15:19 */ | 602 | rlwinm r2,r3,20,27,31 /* Get Address bits 15:19 */ |
| 603 | slw r0,r0,r2 | 603 | slw r0,r0,r2 |
| 604 | xor r1,r0,r1 | 604 | xor r1,r0,r1 |
| 605 | srw r0,r1,r2 | 605 | srw r0,r1,r2 |
| 606 | mtspr SPRN_SPRG4,r1 | 606 | mtspr SPRN_SPRG_603_LRU,r1 |
| 607 | mfspr r2,SPRN_SRR1 | 607 | mfspr r2,SPRN_SRR1 |
| 608 | rlwimi r2,r0,31-14,14,14 | 608 | rlwimi r2,r0,31-14,14,14 |
| 609 | mtspr SPRN_SRR1,r2 | 609 | mtspr SPRN_SRR1,r2 |
| @@ -643,7 +643,7 @@ DataStoreTLBMiss: | |||
| 643 | mfspr r3,SPRN_DMISS | 643 | mfspr r3,SPRN_DMISS |
| 644 | lis r1,PAGE_OFFSET@h /* check if kernel address */ | 644 | lis r1,PAGE_OFFSET@h /* check if kernel address */ |
| 645 | cmplw 0,r1,r3 | 645 | cmplw 0,r1,r3 |
| 646 | mfspr r2,SPRN_SPRG3 | 646 | mfspr r2,SPRN_SPRG_THREAD |
| 647 | li r1,_PAGE_RW|_PAGE_USER|_PAGE_PRESENT /* access flags */ | 647 | li r1,_PAGE_RW|_PAGE_USER|_PAGE_PRESENT /* access flags */ |
| 648 | lwz r2,PGDIR(r2) | 648 | lwz r2,PGDIR(r2) |
| 649 | bge- 112f | 649 | bge- 112f |
| @@ -678,12 +678,12 @@ END_FTR_SECTION_IFCLR(CPU_FTR_NEED_COHERENT) | |||
| 678 | mtcrf 0x80,r2 | 678 | mtcrf 0x80,r2 |
| 679 | BEGIN_MMU_FTR_SECTION | 679 | BEGIN_MMU_FTR_SECTION |
| 680 | li r0,1 | 680 | li r0,1 |
| 681 | mfspr r1,SPRN_SPRG4 | 681 | mfspr r1,SPRN_SPRG_603_LRU |
| 682 | rlwinm r2,r3,20,27,31 /* Get Address bits 15:19 */ | 682 | rlwinm r2,r3,20,27,31 /* Get Address bits 15:19 */ |
| 683 | slw r0,r0,r2 | 683 | slw r0,r0,r2 |
| 684 | xor r1,r0,r1 | 684 | xor r1,r0,r1 |
| 685 | srw r0,r1,r2 | 685 | srw r0,r1,r2 |
| 686 | mtspr SPRN_SPRG4,r1 | 686 | mtspr SPRN_SPRG_603_LRU,r1 |
| 687 | mfspr r2,SPRN_SRR1 | 687 | mfspr r2,SPRN_SRR1 |
| 688 | rlwimi r2,r0,31-14,14,14 | 688 | rlwimi r2,r0,31-14,14,14 |
| 689 | mtspr SPRN_SRR1,r2 | 689 | mtspr SPRN_SRR1,r2 |
| @@ -864,9 +864,9 @@ __secondary_start: | |||
| 864 | tophys(r4,r2) | 864 | tophys(r4,r2) |
| 865 | addi r4,r4,THREAD /* phys address of our thread_struct */ | 865 | addi r4,r4,THREAD /* phys address of our thread_struct */ |
| 866 | CLR_TOP32(r4) | 866 | CLR_TOP32(r4) |
| 867 | mtspr SPRN_SPRG3,r4 | 867 | mtspr SPRN_SPRG_THREAD,r4 |
| 868 | li r3,0 | 868 | li r3,0 |
| 869 | mtspr SPRN_SPRG2,r3 /* 0 => not in RTAS */ | 869 | mtspr SPRN_SPRG_RTAS,r3 /* 0 => not in RTAS */ |
| 870 | 870 | ||
| 871 | /* enable MMU and jump to start_secondary */ | 871 | /* enable MMU and jump to start_secondary */ |
| 872 | li r4,MSR_KERNEL | 872 | li r4,MSR_KERNEL |
| @@ -947,9 +947,9 @@ start_here: | |||
| 947 | tophys(r4,r2) | 947 | tophys(r4,r2) |
| 948 | addi r4,r4,THREAD /* init task's THREAD */ | 948 | addi r4,r4,THREAD /* init task's THREAD */ |
| 949 | CLR_TOP32(r4) | 949 | CLR_TOP32(r4) |
| 950 | mtspr SPRN_SPRG3,r4 | 950 | mtspr SPRN_SPRG_THREAD,r4 |
| 951 | li r3,0 | 951 | li r3,0 |
| 952 | mtspr SPRN_SPRG2,r3 /* 0 => not in RTAS */ | 952 | mtspr SPRN_SPRG_RTAS,r3 /* 0 => not in RTAS */ |
| 953 | 953 | ||
| 954 | /* stack */ | 954 | /* stack */ |
| 955 | lis r1,init_thread_union@ha | 955 | lis r1,init_thread_union@ha |
diff --git a/arch/powerpc/kernel/head_40x.S b/arch/powerpc/kernel/head_40x.S index 0c96911d4299..a90625f9b485 100644 --- a/arch/powerpc/kernel/head_40x.S +++ b/arch/powerpc/kernel/head_40x.S | |||
| @@ -103,21 +103,21 @@ _ENTRY(saved_ksp_limit) | |||
| 103 | 103 | ||
| 104 | /* | 104 | /* |
| 105 | * Exception vector entry code. This code runs with address translation | 105 | * Exception vector entry code. This code runs with address translation |
| 106 | * turned off (i.e. using physical addresses). We assume SPRG3 has the | 106 | * turned off (i.e. using physical addresses). We assume SPRG_THREAD has |
| 107 | * physical address of the current task thread_struct. | 107 | * the physical address of the current task thread_struct. |
| 108 | * Note that we have to have decremented r1 before we write to any fields | 108 | * Note that we have to have decremented r1 before we write to any fields |
| 109 | * of the exception frame, since a critical interrupt could occur at any | 109 | * of the exception frame, since a critical interrupt could occur at any |
| 110 | * time, and it will write to the area immediately below the current r1. | 110 | * time, and it will write to the area immediately below the current r1. |
| 111 | */ | 111 | */ |
| 112 | #define NORMAL_EXCEPTION_PROLOG \ | 112 | #define NORMAL_EXCEPTION_PROLOG \ |
| 113 | mtspr SPRN_SPRG0,r10; /* save two registers to work with */\ | 113 | mtspr SPRN_SPRG_SCRATCH0,r10; /* save two registers to work with */\ |
| 114 | mtspr SPRN_SPRG1,r11; \ | 114 | mtspr SPRN_SPRG_SCRATCH1,r11; \ |
| 115 | mtspr SPRN_SPRG2,r1; \ | 115 | mtspr SPRN_SPRG_SCRATCH2,r1; \ |
| 116 | mfcr r10; /* save CR in r10 for now */\ | 116 | mfcr r10; /* save CR in r10 for now */\ |
| 117 | mfspr r11,SPRN_SRR1; /* check whether user or kernel */\ | 117 | mfspr r11,SPRN_SRR1; /* check whether user or kernel */\ |
| 118 | andi. r11,r11,MSR_PR; \ | 118 | andi. r11,r11,MSR_PR; \ |
| 119 | beq 1f; \ | 119 | beq 1f; \ |
| 120 | mfspr r1,SPRN_SPRG3; /* if from user, start at top of */\ | 120 | mfspr r1,SPRN_SPRG_THREAD; /* if from user, start at top of */\ |
| 121 | lwz r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack */\ | 121 | lwz r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack */\ |
| 122 | addi r1,r1,THREAD_SIZE; \ | 122 | addi r1,r1,THREAD_SIZE; \ |
| 123 | 1: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\ | 123 | 1: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\ |
| @@ -125,13 +125,13 @@ _ENTRY(saved_ksp_limit) | |||
| 125 | stw r10,_CCR(r11); /* save various registers */\ | 125 | stw r10,_CCR(r11); /* save various registers */\ |
| 126 | stw r12,GPR12(r11); \ | 126 | stw r12,GPR12(r11); \ |
| 127 | stw r9,GPR9(r11); \ | 127 | stw r9,GPR9(r11); \ |
| 128 | mfspr r10,SPRN_SPRG0; \ | 128 | mfspr r10,SPRN_SPRG_SCRATCH0; \ |
| 129 | stw r10,GPR10(r11); \ | 129 | stw r10,GPR10(r11); \ |
| 130 | mfspr r12,SPRN_SPRG1; \ | 130 | mfspr r12,SPRN_SPRG_SCRATCH1; \ |
| 131 | stw r12,GPR11(r11); \ | 131 | stw r12,GPR11(r11); \ |
| 132 | mflr r10; \ | 132 | mflr r10; \ |
| 133 | stw r10,_LINK(r11); \ | 133 | stw r10,_LINK(r11); \ |
| 134 | mfspr r10,SPRN_SPRG2; \ | 134 | mfspr r10,SPRN_SPRG_SCRATCH2; \ |
| 135 | mfspr r12,SPRN_SRR0; \ | 135 | mfspr r12,SPRN_SRR0; \ |
| 136 | stw r10,GPR1(r11); \ | 136 | stw r10,GPR1(r11); \ |
| 137 | mfspr r9,SPRN_SRR1; \ | 137 | mfspr r9,SPRN_SRR1; \ |
| @@ -160,7 +160,7 @@ _ENTRY(saved_ksp_limit) | |||
| 160 | lwz r11,critirq_ctx@l(r11); \ | 160 | lwz r11,critirq_ctx@l(r11); \ |
| 161 | beq 1f; \ | 161 | beq 1f; \ |
| 162 | /* COMING FROM USER MODE */ \ | 162 | /* COMING FROM USER MODE */ \ |
| 163 | mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\ | 163 | mfspr r11,SPRN_SPRG_THREAD; /* if from user, start at top of */\ |
| 164 | lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\ | 164 | lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\ |
| 165 | 1: addi r11,r11,THREAD_SIZE-INT_FRAME_SIZE; /* Alloc an excpt frm */\ | 165 | 1: addi r11,r11,THREAD_SIZE-INT_FRAME_SIZE; /* Alloc an excpt frm */\ |
| 166 | tophys(r11,r11); \ | 166 | tophys(r11,r11); \ |
| @@ -265,8 +265,8 @@ label: | |||
| 265 | * and exit. Otherwise, we call heavywight functions to do the work. | 265 | * and exit. Otherwise, we call heavywight functions to do the work. |
| 266 | */ | 266 | */ |
| 267 | START_EXCEPTION(0x0300, DataStorage) | 267 | START_EXCEPTION(0x0300, DataStorage) |
| 268 | mtspr SPRN_SPRG0, r10 /* Save some working registers */ | 268 | mtspr SPRN_SPRG_SCRATCH0, r10 /* Save some working registers */ |
| 269 | mtspr SPRN_SPRG1, r11 | 269 | mtspr SPRN_SPRG_SCRATCH1, r11 |
| 270 | #ifdef CONFIG_403GCX | 270 | #ifdef CONFIG_403GCX |
| 271 | stw r12, 0(r0) | 271 | stw r12, 0(r0) |
| 272 | stw r9, 4(r0) | 272 | stw r9, 4(r0) |
| @@ -275,12 +275,12 @@ label: | |||
| 275 | stw r11, 8(r0) | 275 | stw r11, 8(r0) |
| 276 | stw r12, 12(r0) | 276 | stw r12, 12(r0) |
| 277 | #else | 277 | #else |
| 278 | mtspr SPRN_SPRG4, r12 | 278 | mtspr SPRN_SPRG_SCRATCH3, r12 |
| 279 | mtspr SPRN_SPRG5, r9 | 279 | mtspr SPRN_SPRG_SCRATCH4, r9 |
| 280 | mfcr r11 | 280 | mfcr r11 |
| 281 | mfspr r12, SPRN_PID | 281 | mfspr r12, SPRN_PID |
| 282 | mtspr SPRN_SPRG7, r11 | 282 | mtspr SPRN_SPRG_SCRATCH6, r11 |
| 283 | mtspr SPRN_SPRG6, r12 | 283 | mtspr SPRN_SPRG_SCRATCH5, r12 |
| 284 | #endif | 284 | #endif |
| 285 | 285 | ||
| 286 | /* First, check if it was a zone fault (which means a user | 286 | /* First, check if it was a zone fault (which means a user |
| @@ -308,7 +308,7 @@ label: | |||
| 308 | /* Get the PGD for the current thread. | 308 | /* Get the PGD for the current thread. |
| 309 | */ | 309 | */ |
| 310 | 3: | 310 | 3: |
| 311 | mfspr r11,SPRN_SPRG3 | 311 | mfspr r11,SPRN_SPRG_THREAD |
| 312 | lwz r11,PGDIR(r11) | 312 | lwz r11,PGDIR(r11) |
| 313 | 4: | 313 | 4: |
| 314 | tophys(r11, r11) | 314 | tophys(r11, r11) |
| @@ -355,15 +355,15 @@ label: | |||
| 355 | lwz r9, 4(r0) | 355 | lwz r9, 4(r0) |
| 356 | lwz r12, 0(r0) | 356 | lwz r12, 0(r0) |
| 357 | #else | 357 | #else |
| 358 | mfspr r12, SPRN_SPRG6 | 358 | mfspr r12, SPRN_SPRG_SCRATCH5 |
| 359 | mfspr r11, SPRN_SPRG7 | 359 | mfspr r11, SPRN_SPRG_SCRATCH6 |
| 360 | mtspr SPRN_PID, r12 | 360 | mtspr SPRN_PID, r12 |
| 361 | mtcr r11 | 361 | mtcr r11 |
| 362 | mfspr r9, SPRN_SPRG5 | 362 | mfspr r9, SPRN_SPRG_SCRATCH4 |
| 363 | mfspr r12, SPRN_SPRG4 | 363 | mfspr r12, SPRN_SPRG_SCRATCH3 |
| 364 | #endif | 364 | #endif |
| 365 | mfspr r11, SPRN_SPRG1 | 365 | mfspr r11, SPRN_SPRG_SCRATCH1 |
| 366 | mfspr r10, SPRN_SPRG0 | 366 | mfspr r10, SPRN_SPRG_SCRATCH0 |
| 367 | PPC405_ERR77_SYNC | 367 | PPC405_ERR77_SYNC |
| 368 | rfi /* Should sync shadow TLBs */ | 368 | rfi /* Should sync shadow TLBs */ |
| 369 | b . /* prevent prefetch past rfi */ | 369 | b . /* prevent prefetch past rfi */ |
| @@ -380,15 +380,15 @@ label: | |||
| 380 | lwz r9, 4(r0) | 380 | lwz r9, 4(r0) |
| 381 | lwz r12, 0(r0) | 381 | lwz r12, 0(r0) |
| 382 | #else | 382 | #else |
| 383 | mfspr r12, SPRN_SPRG6 | 383 | mfspr r12, SPRN_SPRG_SCRATCH5 |
| 384 | mfspr r11, SPRN_SPRG7 | 384 | mfspr r11, SPRN_SPRG_SCRATCH6 |
| 385 | mtspr SPRN_PID, r12 | 385 | mtspr SPRN_PID, r12 |
| 386 | mtcr r11 | 386 | mtcr r11 |
| 387 | mfspr r9, SPRN_SPRG5 | 387 | mfspr r9, SPRN_SPRG_SCRATCH4 |
| 388 | mfspr r12, SPRN_SPRG4 | 388 | mfspr r12, SPRN_SPRG_SCRATCH3 |
| 389 | #endif | 389 | #endif |
| 390 | mfspr r11, SPRN_SPRG1 | 390 | mfspr r11, SPRN_SPRG_SCRATCH1 |
| 391 | mfspr r10, SPRN_SPRG0 | 391 | mfspr r10, SPRN_SPRG_SCRATCH0 |
| 392 | b DataAccess | 392 | b DataAccess |
| 393 | 393 | ||
| 394 | /* | 394 | /* |
| @@ -466,8 +466,8 @@ label: | |||
| 466 | * load TLB entries from the page table if they exist. | 466 | * load TLB entries from the page table if they exist. |
| 467 | */ | 467 | */ |
| 468 | START_EXCEPTION(0x1100, DTLBMiss) | 468 | START_EXCEPTION(0x1100, DTLBMiss) |
| 469 | mtspr SPRN_SPRG0, r10 /* Save some working registers */ | 469 | mtspr SPRN_SPRG_SCRATCH0, r10 /* Save some working registers */ |
| 470 | mtspr SPRN_SPRG1, r11 | 470 | mtspr SPRN_SPRG_SCRATCH1, r11 |
| 471 | #ifdef CONFIG_403GCX | 471 | #ifdef CONFIG_403GCX |
| 472 | stw r12, 0(r0) | 472 | stw r12, 0(r0) |
| 473 | stw r9, 4(r0) | 473 | stw r9, 4(r0) |
| @@ -476,12 +476,12 @@ label: | |||
| 476 | stw r11, 8(r0) | 476 | stw r11, 8(r0) |
| 477 | stw r12, 12(r0) | 477 | stw r12, 12(r0) |
| 478 | #else | 478 | #else |
| 479 | mtspr SPRN_SPRG4, r12 | 479 | mtspr SPRN_SPRG_SCRATCH3, r12 |
| 480 | mtspr SPRN_SPRG5, r9 | 480 | mtspr SPRN_SPRG_SCRATCH4, r9 |
| 481 | mfcr r11 | 481 | mfcr r11 |
| 482 | mfspr r12, SPRN_PID | 482 | mfspr r12, SPRN_PID |
| 483 | mtspr SPRN_SPRG7, r11 | 483 | mtspr SPRN_SPRG_SCRATCH6, r11 |
| 484 | mtspr SPRN_SPRG6, r12 | 484 | mtspr SPRN_SPRG_SCRATCH5, r12 |
| 485 | #endif | 485 | #endif |
| 486 | mfspr r10, SPRN_DEAR /* Get faulting address */ | 486 | mfspr r10, SPRN_DEAR /* Get faulting address */ |
| 487 | 487 | ||
| @@ -500,7 +500,7 @@ label: | |||
| 500 | /* Get the PGD for the current thread. | 500 | /* Get the PGD for the current thread. |
| 501 | */ | 501 | */ |
| 502 | 3: | 502 | 3: |
| 503 | mfspr r11,SPRN_SPRG3 | 503 | mfspr r11,SPRN_SPRG_THREAD |
| 504 | lwz r11,PGDIR(r11) | 504 | lwz r11,PGDIR(r11) |
| 505 | 4: | 505 | 4: |
| 506 | tophys(r11, r11) | 506 | tophys(r11, r11) |
| @@ -550,15 +550,15 @@ label: | |||
| 550 | lwz r9, 4(r0) | 550 | lwz r9, 4(r0) |
| 551 | lwz r12, 0(r0) | 551 | lwz r12, 0(r0) |
| 552 | #else | 552 | #else |
| 553 | mfspr r12, SPRN_SPRG6 | 553 | mfspr r12, SPRN_SPRG_SCRATCH5 |
| 554 | mfspr r11, SPRN_SPRG7 | 554 | mfspr r11, SPRN_SPRG_SCRATCH6 |
| 555 | mtspr SPRN_PID, r12 | 555 | mtspr SPRN_PID, r12 |
| 556 | mtcr r11 | 556 | mtcr r11 |
| 557 | mfspr r9, SPRN_SPRG5 | 557 | mfspr r9, SPRN_SPRG_SCRATCH4 |
| 558 | mfspr r12, SPRN_SPRG4 | 558 | mfspr r12, SPRN_SPRG_SCRATCH3 |
| 559 | #endif | 559 | #endif |
| 560 | mfspr r11, SPRN_SPRG1 | 560 | mfspr r11, SPRN_SPRG_SCRATCH1 |
| 561 | mfspr r10, SPRN_SPRG0 | 561 | mfspr r10, SPRN_SPRG_SCRATCH0 |
| 562 | b DataAccess | 562 | b DataAccess |
| 563 | 563 | ||
| 564 | /* 0x1200 - Instruction TLB Miss Exception | 564 | /* 0x1200 - Instruction TLB Miss Exception |
| @@ -566,8 +566,8 @@ label: | |||
| 566 | * registers and bailout to a different point. | 566 | * registers and bailout to a different point. |
| 567 | */ | 567 | */ |
| 568 | START_EXCEPTION(0x1200, ITLBMiss) | 568 | START_EXCEPTION(0x1200, ITLBMiss) |
| 569 | mtspr SPRN_SPRG0, r10 /* Save some working registers */ | 569 | mtspr SPRN_SPRG_SCRATCH0, r10 /* Save some working registers */ |
| 570 | mtspr SPRN_SPRG1, r11 | 570 | mtspr SPRN_SPRG_SCRATCH1, r11 |
| 571 | #ifdef CONFIG_403GCX | 571 | #ifdef CONFIG_403GCX |
| 572 | stw r12, 0(r0) | 572 | stw r12, 0(r0) |
| 573 | stw r9, 4(r0) | 573 | stw r9, 4(r0) |
| @@ -576,12 +576,12 @@ label: | |||
| 576 | stw r11, 8(r0) | 576 | stw r11, 8(r0) |
| 577 | stw r12, 12(r0) | 577 | stw r12, 12(r0) |
| 578 | #else | 578 | #else |
| 579 | mtspr SPRN_SPRG4, r12 | 579 | mtspr SPRN_SPRG_SCRATCH3, r12 |
| 580 | mtspr SPRN_SPRG5, r9 | 580 | mtspr SPRN_SPRG_SCRATCH4, r9 |
| 581 | mfcr r11 | 581 | mfcr r11 |
| 582 | mfspr r12, SPRN_PID | 582 | mfspr r12, SPRN_PID |
| 583 | mtspr SPRN_SPRG7, r11 | 583 | mtspr SPRN_SPRG_SCRATCH6, r11 |
| 584 | mtspr SPRN_SPRG6, r12 | 584 | mtspr SPRN_SPRG_SCRATCH5, r12 |
| 585 | #endif | 585 | #endif |
| 586 | mfspr r10, SPRN_SRR0 /* Get faulting address */ | 586 | mfspr r10, SPRN_SRR0 /* Get faulting address */ |
| 587 | 587 | ||
| @@ -600,7 +600,7 @@ label: | |||
| 600 | /* Get the PGD for the current thread. | 600 | /* Get the PGD for the current thread. |
| 601 | */ | 601 | */ |
| 602 | 3: | 602 | 3: |
| 603 | mfspr r11,SPRN_SPRG3 | 603 | mfspr r11,SPRN_SPRG_THREAD |
| 604 | lwz r11,PGDIR(r11) | 604 | lwz r11,PGDIR(r11) |
| 605 | 4: | 605 | 4: |
| 606 | tophys(r11, r11) | 606 | tophys(r11, r11) |
| @@ -650,15 +650,15 @@ label: | |||
| 650 | lwz r9, 4(r0) | 650 | lwz r9, 4(r0) |
| 651 | lwz r12, 0(r0) | 651 | lwz r12, 0(r0) |
| 652 | #else | 652 | #else |
| 653 | mfspr r12, SPRN_SPRG6 | 653 | mfspr r12, SPRN_SPRG_SCRATCH5 |
| 654 | mfspr r11, SPRN_SPRG7 | 654 | mfspr r11, SPRN_SPRG_SCRATCH6 |
| 655 | mtspr SPRN_PID, r12 | 655 | mtspr SPRN_PID, r12 |
| 656 | mtcr r11 | 656 | mtcr r11 |
| 657 | mfspr r9, SPRN_SPRG5 | 657 | mfspr r9, SPRN_SPRG_SCRATCH4 |
| 658 | mfspr r12, SPRN_SPRG4 | 658 | mfspr r12, SPRN_SPRG_SCRATCH3 |
| 659 | #endif | 659 | #endif |
| 660 | mfspr r11, SPRN_SPRG1 | 660 | mfspr r11, SPRN_SPRG_SCRATCH1 |
| 661 | mfspr r10, SPRN_SPRG0 | 661 | mfspr r10, SPRN_SPRG_SCRATCH0 |
| 662 | b InstructionAccess | 662 | b InstructionAccess |
| 663 | 663 | ||
| 664 | EXCEPTION(0x1300, Trap_13, unknown_exception, EXC_XFER_EE) | 664 | EXCEPTION(0x1300, Trap_13, unknown_exception, EXC_XFER_EE) |
| @@ -803,15 +803,15 @@ finish_tlb_load: | |||
| 803 | lwz r9, 4(r0) | 803 | lwz r9, 4(r0) |
| 804 | lwz r12, 0(r0) | 804 | lwz r12, 0(r0) |
| 805 | #else | 805 | #else |
| 806 | mfspr r12, SPRN_SPRG6 | 806 | mfspr r12, SPRN_SPRG_SCRATCH5 |
| 807 | mfspr r11, SPRN_SPRG7 | 807 | mfspr r11, SPRN_SPRG_SCRATCH6 |
| 808 | mtspr SPRN_PID, r12 | 808 | mtspr SPRN_PID, r12 |
| 809 | mtcr r11 | 809 | mtcr r11 |
| 810 | mfspr r9, SPRN_SPRG5 | 810 | mfspr r9, SPRN_SPRG_SCRATCH4 |
| 811 | mfspr r12, SPRN_SPRG4 | 811 | mfspr r12, SPRN_SPRG_SCRATCH3 |
| 812 | #endif | 812 | #endif |
| 813 | mfspr r11, SPRN_SPRG1 | 813 | mfspr r11, SPRN_SPRG_SCRATCH1 |
| 814 | mfspr r10, SPRN_SPRG0 | 814 | mfspr r10, SPRN_SPRG_SCRATCH0 |
| 815 | PPC405_ERR77_SYNC | 815 | PPC405_ERR77_SYNC |
| 816 | rfi /* Should sync shadow TLBs */ | 816 | rfi /* Should sync shadow TLBs */ |
| 817 | b . /* prevent prefetch past rfi */ | 817 | b . /* prevent prefetch past rfi */ |
| @@ -835,7 +835,7 @@ start_here: | |||
| 835 | /* ptr to phys current thread */ | 835 | /* ptr to phys current thread */ |
| 836 | tophys(r4,r2) | 836 | tophys(r4,r2) |
| 837 | addi r4,r4,THREAD /* init task's THREAD */ | 837 | addi r4,r4,THREAD /* init task's THREAD */ |
| 838 | mtspr SPRN_SPRG3,r4 | 838 | mtspr SPRN_SPRG_THREAD,r4 |
| 839 | 839 | ||
| 840 | /* stack */ | 840 | /* stack */ |
| 841 | lis r1,init_thread_union@ha | 841 | lis r1,init_thread_union@ha |
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S index 18d8a1677c4d..711368b993f2 100644 --- a/arch/powerpc/kernel/head_44x.S +++ b/arch/powerpc/kernel/head_44x.S | |||
| @@ -239,7 +239,7 @@ skpinv: addi r4,r4,1 /* Increment */ | |||
| 239 | 239 | ||
| 240 | /* ptr to current thread */ | 240 | /* ptr to current thread */ |
| 241 | addi r4,r2,THREAD /* init task's THREAD */ | 241 | addi r4,r2,THREAD /* init task's THREAD */ |
| 242 | mtspr SPRN_SPRG3,r4 | 242 | mtspr SPRN_SPRG_THREAD,r4 |
| 243 | 243 | ||
| 244 | /* stack */ | 244 | /* stack */ |
| 245 | lis r1,init_thread_union@h | 245 | lis r1,init_thread_union@h |
| @@ -350,12 +350,12 @@ interrupt_base: | |||
| 350 | 350 | ||
| 351 | /* Data TLB Error Interrupt */ | 351 | /* Data TLB Error Interrupt */ |
| 352 | START_EXCEPTION(DataTLBError) | 352 | START_EXCEPTION(DataTLBError) |
| 353 | mtspr SPRN_SPRG0, r10 /* Save some working registers */ | 353 | mtspr SPRN_SPRG_WSCRATCH0, r10 /* Save some working registers */ |
| 354 | mtspr SPRN_SPRG1, r11 | 354 | mtspr SPRN_SPRG_WSCRATCH1, r11 |
| 355 | mtspr SPRN_SPRG4W, r12 | 355 | mtspr SPRN_SPRG_WSCRATCH2, r12 |
| 356 | mtspr SPRN_SPRG5W, r13 | 356 | mtspr SPRN_SPRG_WSCRATCH3, r13 |
| 357 | mfcr r11 | 357 | mfcr r11 |
| 358 | mtspr SPRN_SPRG7W, r11 | 358 | mtspr SPRN_SPRG_WSCRATCH4, r11 |
| 359 | mfspr r10, SPRN_DEAR /* Get faulting address */ | 359 | mfspr r10, SPRN_DEAR /* Get faulting address */ |
| 360 | 360 | ||
| 361 | /* If we are faulting a kernel address, we have to use the | 361 | /* If we are faulting a kernel address, we have to use the |
| @@ -374,7 +374,7 @@ interrupt_base: | |||
| 374 | 374 | ||
| 375 | /* Get the PGD for the current thread */ | 375 | /* Get the PGD for the current thread */ |
| 376 | 3: | 376 | 3: |
| 377 | mfspr r11,SPRN_SPRG3 | 377 | mfspr r11,SPRN_SPRG_THREAD |
| 378 | lwz r11,PGDIR(r11) | 378 | lwz r11,PGDIR(r11) |
| 379 | 379 | ||
| 380 | /* Load PID into MMUCR TID */ | 380 | /* Load PID into MMUCR TID */ |
| @@ -446,12 +446,12 @@ tlb_44x_patch_hwater_D: | |||
| 446 | /* The bailout. Restore registers to pre-exception conditions | 446 | /* The bailout. Restore registers to pre-exception conditions |
| 447 | * and call the heavyweights to help us out. | 447 | * and call the heavyweights to help us out. |
| 448 | */ | 448 | */ |
| 449 | mfspr r11, SPRN_SPRG7R | 449 | mfspr r11, SPRN_SPRG_RSCRATCH4 |
| 450 | mtcr r11 | 450 | mtcr r11 |
| 451 | mfspr r13, SPRN_SPRG5R | 451 | mfspr r13, SPRN_SPRG_RSCRATCH3 |
| 452 | mfspr r12, SPRN_SPRG4R | 452 | mfspr r12, SPRN_SPRG_RSCRATCH2 |
| 453 | mfspr r11, SPRN_SPRG1 | 453 | mfspr r11, SPRN_SPRG_RSCRATCH1 |
| 454 | mfspr r10, SPRN_SPRG0 | 454 | mfspr r10, SPRN_SPRG_RSCRATCH0 |
| 455 | b DataStorage | 455 | b DataStorage |
| 456 | 456 | ||
| 457 | /* Instruction TLB Error Interrupt */ | 457 | /* Instruction TLB Error Interrupt */ |
| @@ -461,12 +461,12 @@ tlb_44x_patch_hwater_D: | |||
| 461 | * to a different point. | 461 | * to a different point. |
| 462 | */ | 462 | */ |
| 463 | START_EXCEPTION(InstructionTLBError) | 463 | START_EXCEPTION(InstructionTLBError) |
| 464 | mtspr SPRN_SPRG0, r10 /* Save some working registers */ | 464 | mtspr SPRN_SPRG_WSCRATCH0, r10 /* Save some working registers */ |
| 465 | mtspr SPRN_SPRG1, r11 | 465 | mtspr SPRN_SPRG_WSCRATCH1, r11 |
| 466 | mtspr SPRN_SPRG4W, r12 | 466 | mtspr SPRN_SPRG_WSCRATCH2, r12 |
| 467 | mtspr SPRN_SPRG5W, r13 | 467 | mtspr SPRN_SPRG_WSCRATCH3, r13 |
| 468 | mfcr r11 | 468 | mfcr r11 |
| 469 | mtspr SPRN_SPRG7W, r11 | 469 | mtspr SPRN_SPRG_WSCRATCH4, r11 |
| 470 | mfspr r10, SPRN_SRR0 /* Get faulting address */ | 470 | mfspr r10, SPRN_SRR0 /* Get faulting address */ |
| 471 | 471 | ||
| 472 | /* If we are faulting a kernel address, we have to use the | 472 | /* If we are faulting a kernel address, we have to use the |
| @@ -485,7 +485,7 @@ tlb_44x_patch_hwater_D: | |||
| 485 | 485 | ||
| 486 | /* Get the PGD for the current thread */ | 486 | /* Get the PGD for the current thread */ |
| 487 | 3: | 487 | 3: |
| 488 | mfspr r11,SPRN_SPRG3 | 488 | mfspr r11,SPRN_SPRG_THREAD |
| 489 | lwz r11,PGDIR(r11) | 489 | lwz r11,PGDIR(r11) |
| 490 | 490 | ||
| 491 | /* Load PID into MMUCR TID */ | 491 | /* Load PID into MMUCR TID */ |
| @@ -497,7 +497,7 @@ tlb_44x_patch_hwater_D: | |||
| 497 | mtspr SPRN_MMUCR,r12 | 497 | mtspr SPRN_MMUCR,r12 |
| 498 | 498 | ||
| 499 | /* Make up the required permissions */ | 499 | /* Make up the required permissions */ |
| 500 | li r13,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_HWEXEC | 500 | li r13,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC |
| 501 | 501 | ||
| 502 | /* Compute pgdir/pmd offset */ | 502 | /* Compute pgdir/pmd offset */ |
| 503 | rlwinm r12, r10, PPC44x_PGD_OFF_SHIFT, PPC44x_PGD_OFF_MASK_BIT, 29 | 503 | rlwinm r12, r10, PPC44x_PGD_OFF_SHIFT, PPC44x_PGD_OFF_MASK_BIT, 29 |
| @@ -542,12 +542,12 @@ tlb_44x_patch_hwater_I: | |||
| 542 | /* The bailout. Restore registers to pre-exception conditions | 542 | /* The bailout. Restore registers to pre-exception conditions |
| 543 | * and call the heavyweights to help us out. | 543 | * and call the heavyweights to help us out. |
| 544 | */ | 544 | */ |
| 545 | mfspr r11, SPRN_SPRG7R | 545 | mfspr r11, SPRN_SPRG_RSCRATCH4 |
| 546 | mtcr r11 | 546 | mtcr r11 |
| 547 | mfspr r13, SPRN_SPRG5R | 547 | mfspr r13, SPRN_SPRG_RSCRATCH3 |
| 548 | mfspr r12, SPRN_SPRG4R | 548 | mfspr r12, SPRN_SPRG_RSCRATCH2 |
| 549 | mfspr r11, SPRN_SPRG1 | 549 | mfspr r11, SPRN_SPRG_RSCRATCH1 |
| 550 | mfspr r10, SPRN_SPRG0 | 550 | mfspr r10, SPRN_SPRG_RSCRATCH0 |
| 551 | b InstructionStorage | 551 | b InstructionStorage |
| 552 | 552 | ||
| 553 | /* Debug Interrupt */ | 553 | /* Debug Interrupt */ |
| @@ -593,12 +593,12 @@ finish_tlb_load: | |||
| 593 | 593 | ||
| 594 | /* Done...restore registers and get out of here. | 594 | /* Done...restore registers and get out of here. |
| 595 | */ | 595 | */ |
| 596 | mfspr r11, SPRN_SPRG7R | 596 | mfspr r11, SPRN_SPRG_RSCRATCH4 |
| 597 | mtcr r11 | 597 | mtcr r11 |
| 598 | mfspr r13, SPRN_SPRG5R | 598 | mfspr r13, SPRN_SPRG_RSCRATCH3 |
| 599 | mfspr r12, SPRN_SPRG4R | 599 | mfspr r12, SPRN_SPRG_RSCRATCH2 |
| 600 | mfspr r11, SPRN_SPRG1 | 600 | mfspr r11, SPRN_SPRG_RSCRATCH1 |
| 601 | mfspr r10, SPRN_SPRG0 | 601 | mfspr r10, SPRN_SPRG_RSCRATCH0 |
| 602 | rfi /* Force context change */ | 602 | rfi /* Force context change */ |
| 603 | 603 | ||
| 604 | /* | 604 | /* |
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 012505ebd9f9..c38afdb45d7b 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
| @@ -36,7 +36,6 @@ | |||
| 36 | #include <asm/thread_info.h> | 36 | #include <asm/thread_info.h> |
| 37 | #include <asm/firmware.h> | 37 | #include <asm/firmware.h> |
| 38 | #include <asm/page_64.h> | 38 | #include <asm/page_64.h> |
| 39 | #include <asm/exception.h> | ||
| 40 | #include <asm/irqflags.h> | 39 | #include <asm/irqflags.h> |
| 41 | 40 | ||
| 42 | /* The physical memory is layed out such that the secondary processor | 41 | /* The physical memory is layed out such that the secondary processor |
| @@ -122,10 +121,11 @@ __run_at_load: | |||
| 122 | */ | 121 | */ |
| 123 | .globl __secondary_hold | 122 | .globl __secondary_hold |
| 124 | __secondary_hold: | 123 | __secondary_hold: |
| 124 | #ifndef CONFIG_PPC_BOOK3E | ||
| 125 | mfmsr r24 | 125 | mfmsr r24 |
| 126 | ori r24,r24,MSR_RI | 126 | ori r24,r24,MSR_RI |
| 127 | mtmsrd r24 /* RI on */ | 127 | mtmsrd r24 /* RI on */ |
| 128 | 128 | #endif | |
| 129 | /* Grab our physical cpu number */ | 129 | /* Grab our physical cpu number */ |
| 130 | mr r24,r3 | 130 | mr r24,r3 |
| 131 | 131 | ||
| @@ -144,6 +144,7 @@ __secondary_hold: | |||
| 144 | ld r4,0(r4) /* deref function descriptor */ | 144 | ld r4,0(r4) /* deref function descriptor */ |
| 145 | mtctr r4 | 145 | mtctr r4 |
| 146 | mr r3,r24 | 146 | mr r3,r24 |
| 147 | li r4,0 | ||
| 147 | bctr | 148 | bctr |
| 148 | #else | 149 | #else |
| 149 | BUG_OPCODE | 150 | BUG_OPCODE |
| @@ -164,21 +165,49 @@ exception_marker: | |||
| 164 | #include "exceptions-64s.S" | 165 | #include "exceptions-64s.S" |
| 165 | #endif | 166 | #endif |
| 166 | 167 | ||
| 168 | _GLOBAL(generic_secondary_thread_init) | ||
| 169 | mr r24,r3 | ||
| 170 | |||
| 171 | /* turn on 64-bit mode */ | ||
| 172 | bl .enable_64b_mode | ||
| 173 | |||
| 174 | /* get a valid TOC pointer, wherever we're mapped at */ | ||
| 175 | bl .relative_toc | ||
| 176 | |||
| 177 | #ifdef CONFIG_PPC_BOOK3E | ||
| 178 | /* Book3E initialization */ | ||
| 179 | mr r3,r24 | ||
| 180 | bl .book3e_secondary_thread_init | ||
| 181 | #endif | ||
| 182 | b generic_secondary_common_init | ||
| 167 | 183 | ||
| 168 | /* | 184 | /* |
| 169 | * On pSeries and most other platforms, secondary processors spin | 185 | * On pSeries and most other platforms, secondary processors spin |
| 170 | * in the following code. | 186 | * in the following code. |
| 171 | * At entry, r3 = this processor's number (physical cpu id) | 187 | * At entry, r3 = this processor's number (physical cpu id) |
| 188 | * | ||
| 189 | * On Book3E, r4 = 1 to indicate that the initial TLB entry for | ||
| 190 | * this core already exists (setup via some other mechanism such | ||
| 191 | * as SCOM before entry). | ||
| 172 | */ | 192 | */ |
| 173 | _GLOBAL(generic_secondary_smp_init) | 193 | _GLOBAL(generic_secondary_smp_init) |
| 174 | mr r24,r3 | 194 | mr r24,r3 |
| 175 | 195 | mr r25,r4 | |
| 196 | |||
| 176 | /* turn on 64-bit mode */ | 197 | /* turn on 64-bit mode */ |
| 177 | bl .enable_64b_mode | 198 | bl .enable_64b_mode |
| 178 | 199 | ||
| 179 | /* get the TOC pointer (real address) */ | 200 | /* get a valid TOC pointer, wherever we're mapped at */ |
| 180 | bl .relative_toc | 201 | bl .relative_toc |
| 181 | 202 | ||
| 203 | #ifdef CONFIG_PPC_BOOK3E | ||
| 204 | /* Book3E initialization */ | ||
| 205 | mr r3,r24 | ||
| 206 | mr r4,r25 | ||
| 207 | bl .book3e_secondary_core_init | ||
| 208 | #endif | ||
| 209 | |||
| 210 | generic_secondary_common_init: | ||
| 182 | /* Set up a paca value for this processor. Since we have the | 211 | /* Set up a paca value for this processor. Since we have the |
| 183 | * physical cpu id in r24, we need to search the pacas to find | 212 | * physical cpu id in r24, we need to search the pacas to find |
| 184 | * which logical id maps to our physical one. | 213 | * which logical id maps to our physical one. |
| @@ -196,7 +225,12 @@ _GLOBAL(generic_secondary_smp_init) | |||
| 196 | mr r3,r24 /* not found, copy phys to r3 */ | 225 | mr r3,r24 /* not found, copy phys to r3 */ |
| 197 | b .kexec_wait /* next kernel might do better */ | 226 | b .kexec_wait /* next kernel might do better */ |
| 198 | 227 | ||
| 199 | 2: mtspr SPRN_SPRG3,r13 /* Save vaddr of paca in SPRG3 */ | 228 | 2: mtspr SPRN_SPRG_PACA,r13 /* Save vaddr of paca in an SPRG */ |
| 229 | #ifdef CONFIG_PPC_BOOK3E | ||
| 230 | addi r12,r13,PACA_EXTLB /* and TLB exc frame in another */ | ||
| 231 | mtspr SPRN_SPRG_TLB_EXFRAME,r12 | ||
| 232 | #endif | ||
| 233 | |||
| 200 | /* From now on, r24 is expected to be logical cpuid */ | 234 | /* From now on, r24 is expected to be logical cpuid */ |
| 201 | mr r24,r5 | 235 | mr r24,r5 |
| 202 | 3: HMT_LOW | 236 | 3: HMT_LOW |
| @@ -232,6 +266,7 @@ _GLOBAL(generic_secondary_smp_init) | |||
| 232 | * Turn the MMU off. | 266 | * Turn the MMU off. |
| 233 | * Assumes we're mapped EA == RA if the MMU is on. | 267 | * Assumes we're mapped EA == RA if the MMU is on. |
| 234 | */ | 268 | */ |
| 269 | #ifdef CONFIG_PPC_BOOK3S | ||
| 235 | _STATIC(__mmu_off) | 270 | _STATIC(__mmu_off) |
| 236 | mfmsr r3 | 271 | mfmsr r3 |
| 237 | andi. r0,r3,MSR_IR|MSR_DR | 272 | andi. r0,r3,MSR_IR|MSR_DR |
| @@ -243,6 +278,7 @@ _STATIC(__mmu_off) | |||
| 243 | sync | 278 | sync |
| 244 | rfid | 279 | rfid |
| 245 | b . /* prevent speculative execution */ | 280 | b . /* prevent speculative execution */ |
| 281 | #endif | ||
| 246 | 282 | ||
| 247 | 283 | ||
| 248 | /* | 284 | /* |
| @@ -280,6 +316,10 @@ _GLOBAL(__start_initialization_multiplatform) | |||
| 280 | mr r31,r3 | 316 | mr r31,r3 |
| 281 | mr r30,r4 | 317 | mr r30,r4 |
| 282 | 318 | ||
| 319 | #ifdef CONFIG_PPC_BOOK3E | ||
| 320 | bl .start_initialization_book3e | ||
| 321 | b .__after_prom_start | ||
| 322 | #else | ||
| 283 | /* Setup some critical 970 SPRs before switching MMU off */ | 323 | /* Setup some critical 970 SPRs before switching MMU off */ |
| 284 | mfspr r0,SPRN_PVR | 324 | mfspr r0,SPRN_PVR |
| 285 | srwi r0,r0,16 | 325 | srwi r0,r0,16 |
| @@ -297,6 +337,7 @@ _GLOBAL(__start_initialization_multiplatform) | |||
| 297 | /* Switch off MMU if not already off */ | 337 | /* Switch off MMU if not already off */ |
| 298 | bl .__mmu_off | 338 | bl .__mmu_off |
| 299 | b .__after_prom_start | 339 | b .__after_prom_start |
| 340 | #endif /* CONFIG_PPC_BOOK3E */ | ||
| 300 | 341 | ||
| 301 | _INIT_STATIC(__boot_from_prom) | 342 | _INIT_STATIC(__boot_from_prom) |
| 302 | #ifdef CONFIG_PPC_OF_BOOT_TRAMPOLINE | 343 | #ifdef CONFIG_PPC_OF_BOOT_TRAMPOLINE |
| @@ -359,10 +400,16 @@ _STATIC(__after_prom_start) | |||
| 359 | * Note: This process overwrites the OF exception vectors. | 400 | * Note: This process overwrites the OF exception vectors. |
| 360 | */ | 401 | */ |
| 361 | li r3,0 /* target addr */ | 402 | li r3,0 /* target addr */ |
| 403 | #ifdef CONFIG_PPC_BOOK3E | ||
| 404 | tovirt(r3,r3) /* on booke, we already run at PAGE_OFFSET */ | ||
| 405 | #endif | ||
| 362 | mr. r4,r26 /* In some cases the loader may */ | 406 | mr. r4,r26 /* In some cases the loader may */ |
| 363 | beq 9f /* have already put us at zero */ | 407 | beq 9f /* have already put us at zero */ |
| 364 | li r6,0x100 /* Start offset, the first 0x100 */ | 408 | li r6,0x100 /* Start offset, the first 0x100 */ |
| 365 | /* bytes were copied earlier. */ | 409 | /* bytes were copied earlier. */ |
| 410 | #ifdef CONFIG_PPC_BOOK3E | ||
| 411 | tovirt(r6,r6) /* on booke, we already run at PAGE_OFFSET */ | ||
| 412 | #endif | ||
| 366 | 413 | ||
| 367 | #ifdef CONFIG_CRASH_DUMP | 414 | #ifdef CONFIG_CRASH_DUMP |
| 368 | /* | 415 | /* |
| @@ -485,7 +532,7 @@ _GLOBAL(pmac_secondary_start) | |||
| 485 | LOAD_REG_ADDR(r4,paca) /* Get base vaddr of paca array */ | 532 | LOAD_REG_ADDR(r4,paca) /* Get base vaddr of paca array */ |
| 486 | mulli r13,r24,PACA_SIZE /* Calculate vaddr of right paca */ | 533 | mulli r13,r24,PACA_SIZE /* Calculate vaddr of right paca */ |
| 487 | add r13,r13,r4 /* for this processor. */ | 534 | add r13,r13,r4 /* for this processor. */ |
| 488 | mtspr SPRN_SPRG3,r13 /* Save vaddr of paca in SPRG3 */ | 535 | mtspr SPRN_SPRG_PACA,r13 /* Save vaddr of paca in an SPRG*/ |
| 489 | 536 | ||
| 490 | /* Create a temp kernel stack for use before relocation is on. */ | 537 | /* Create a temp kernel stack for use before relocation is on. */ |
| 491 | ld r1,PACAEMERGSP(r13) | 538 | ld r1,PACAEMERGSP(r13) |
| @@ -503,11 +550,14 @@ _GLOBAL(pmac_secondary_start) | |||
| 503 | * 1. Processor number | 550 | * 1. Processor number |
| 504 | * 2. Segment table pointer (virtual address) | 551 | * 2. Segment table pointer (virtual address) |
| 505 | * On entry the following are set: | 552 | * On entry the following are set: |
| 506 | * r1 = stack pointer. vaddr for iSeries, raddr (temp stack) for pSeries | 553 | * r1 = stack pointer. vaddr for iSeries, raddr (temp stack) for pSeries |
| 507 | * r24 = cpu# (in Linux terms) | 554 | * r24 = cpu# (in Linux terms) |
| 508 | * r13 = paca virtual address | 555 | * r13 = paca virtual address |
| 509 | * SPRG3 = paca virtual address | 556 | * SPRG_PACA = paca virtual address |
| 510 | */ | 557 | */ |
| 558 | .section ".text"; | ||
| 559 | .align 2 ; | ||
| 560 | |||
| 511 | .globl __secondary_start | 561 | .globl __secondary_start |
| 512 | __secondary_start: | 562 | __secondary_start: |
| 513 | /* Set thread priority to MEDIUM */ | 563 | /* Set thread priority to MEDIUM */ |
| @@ -544,7 +594,7 @@ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) | |||
| 544 | 594 | ||
| 545 | mtspr SPRN_SRR0,r3 | 595 | mtspr SPRN_SRR0,r3 |
| 546 | mtspr SPRN_SRR1,r4 | 596 | mtspr SPRN_SRR1,r4 |
| 547 | rfid | 597 | RFI |
| 548 | b . /* prevent speculative execution */ | 598 | b . /* prevent speculative execution */ |
| 549 | 599 | ||
| 550 | /* | 600 | /* |
| @@ -565,11 +615,16 @@ _GLOBAL(start_secondary_prolog) | |||
| 565 | */ | 615 | */ |
| 566 | _GLOBAL(enable_64b_mode) | 616 | _GLOBAL(enable_64b_mode) |
| 567 | mfmsr r11 /* grab the current MSR */ | 617 | mfmsr r11 /* grab the current MSR */ |
| 618 | #ifdef CONFIG_PPC_BOOK3E | ||
| 619 | oris r11,r11,0x8000 /* CM bit set, we'll set ICM later */ | ||
| 620 | mtmsr r11 | ||
| 621 | #else /* CONFIG_PPC_BOOK3E */ | ||
| 568 | li r12,(MSR_SF | MSR_ISF)@highest | 622 | li r12,(MSR_SF | MSR_ISF)@highest |
| 569 | sldi r12,r12,48 | 623 | sldi r12,r12,48 |
| 570 | or r11,r11,r12 | 624 | or r11,r11,r12 |
| 571 | mtmsrd r11 | 625 | mtmsrd r11 |
| 572 | isync | 626 | isync |
| 627 | #endif | ||
| 573 | blr | 628 | blr |
| 574 | 629 | ||
| 575 | /* | 630 | /* |
| @@ -613,9 +668,11 @@ _INIT_STATIC(start_here_multiplatform) | |||
| 613 | bdnz 3b | 668 | bdnz 3b |
| 614 | 4: | 669 | 4: |
| 615 | 670 | ||
| 671 | #ifndef CONFIG_PPC_BOOK3E | ||
| 616 | mfmsr r6 | 672 | mfmsr r6 |
| 617 | ori r6,r6,MSR_RI | 673 | ori r6,r6,MSR_RI |
| 618 | mtmsrd r6 /* RI on */ | 674 | mtmsrd r6 /* RI on */ |
| 675 | #endif | ||
| 619 | 676 | ||
| 620 | #ifdef CONFIG_RELOCATABLE | 677 | #ifdef CONFIG_RELOCATABLE |
| 621 | /* Save the physical address we're running at in kernstart_addr */ | 678 | /* Save the physical address we're running at in kernstart_addr */ |
| @@ -642,13 +699,13 @@ _INIT_STATIC(start_here_multiplatform) | |||
| 642 | 699 | ||
| 643 | /* Restore parameters passed from prom_init/kexec */ | 700 | /* Restore parameters passed from prom_init/kexec */ |
| 644 | mr r3,r31 | 701 | mr r3,r31 |
| 645 | bl .early_setup /* also sets r13 and SPRG3 */ | 702 | bl .early_setup /* also sets r13 and SPRG_PACA */ |
| 646 | 703 | ||
| 647 | LOAD_REG_ADDR(r3, .start_here_common) | 704 | LOAD_REG_ADDR(r3, .start_here_common) |
| 648 | ld r4,PACAKMSR(r13) | 705 | ld r4,PACAKMSR(r13) |
| 649 | mtspr SPRN_SRR0,r3 | 706 | mtspr SPRN_SRR0,r3 |
| 650 | mtspr SPRN_SRR1,r4 | 707 | mtspr SPRN_SRR1,r4 |
| 651 | rfid | 708 | RFI |
| 652 | b . /* prevent speculative execution */ | 709 | b . /* prevent speculative execution */ |
| 653 | 710 | ||
| 654 | /* This is where all platforms converge execution */ | 711 | /* This is where all platforms converge execution */ |
diff --git a/arch/powerpc/kernel/head_8xx.S b/arch/powerpc/kernel/head_8xx.S index 52ff8c53b93c..6ded19d01891 100644 --- a/arch/powerpc/kernel/head_8xx.S +++ b/arch/powerpc/kernel/head_8xx.S | |||
| @@ -110,8 +110,8 @@ turn_on_mmu: | |||
| 110 | * task's thread_struct. | 110 | * task's thread_struct. |
| 111 | */ | 111 | */ |
| 112 | #define EXCEPTION_PROLOG \ | 112 | #define EXCEPTION_PROLOG \ |
| 113 | mtspr SPRN_SPRG0,r10; \ | 113 | mtspr SPRN_SPRG_SCRATCH0,r10; \ |
| 114 | mtspr SPRN_SPRG1,r11; \ | 114 | mtspr SPRN_SPRG_SCRATCH1,r11; \ |
| 115 | mfcr r10; \ | 115 | mfcr r10; \ |
| 116 | EXCEPTION_PROLOG_1; \ | 116 | EXCEPTION_PROLOG_1; \ |
| 117 | EXCEPTION_PROLOG_2 | 117 | EXCEPTION_PROLOG_2 |
| @@ -121,7 +121,7 @@ turn_on_mmu: | |||
| 121 | andi. r11,r11,MSR_PR; \ | 121 | andi. r11,r11,MSR_PR; \ |
| 122 | tophys(r11,r1); /* use tophys(r1) if kernel */ \ | 122 | tophys(r11,r1); /* use tophys(r1) if kernel */ \ |
| 123 | beq 1f; \ | 123 | beq 1f; \ |
| 124 | mfspr r11,SPRN_SPRG3; \ | 124 | mfspr r11,SPRN_SPRG_THREAD; \ |
| 125 | lwz r11,THREAD_INFO-THREAD(r11); \ | 125 | lwz r11,THREAD_INFO-THREAD(r11); \ |
| 126 | addi r11,r11,THREAD_SIZE; \ | 126 | addi r11,r11,THREAD_SIZE; \ |
| 127 | tophys(r11,r11); \ | 127 | tophys(r11,r11); \ |
| @@ -133,9 +133,9 @@ turn_on_mmu: | |||
| 133 | stw r10,_CCR(r11); /* save registers */ \ | 133 | stw r10,_CCR(r11); /* save registers */ \ |
| 134 | stw r12,GPR12(r11); \ | 134 | stw r12,GPR12(r11); \ |
| 135 | stw r9,GPR9(r11); \ | 135 | stw r9,GPR9(r11); \ |
| 136 | mfspr r10,SPRN_SPRG0; \ | 136 | mfspr r10,SPRN_SPRG_SCRATCH0; \ |
| 137 | stw r10,GPR10(r11); \ | 137 | stw r10,GPR10(r11); \ |
| 138 | mfspr r12,SPRN_SPRG1; \ | 138 | mfspr r12,SPRN_SPRG_SCRATCH1; \ |
| 139 | stw r12,GPR11(r11); \ | 139 | stw r12,GPR11(r11); \ |
| 140 | mflr r10; \ | 140 | mflr r10; \ |
| 141 | stw r10,_LINK(r11); \ | 141 | stw r10,_LINK(r11); \ |
| @@ -603,8 +603,9 @@ start_here: | |||
| 603 | /* ptr to phys current thread */ | 603 | /* ptr to phys current thread */ |
| 604 | tophys(r4,r2) | 604 | tophys(r4,r2) |
| 605 | addi r4,r4,THREAD /* init task's THREAD */ | 605 | addi r4,r4,THREAD /* init task's THREAD */ |
| 606 | mtspr SPRN_SPRG3,r4 | 606 | mtspr SPRN_SPRG_THREAD,r4 |
| 607 | li r3,0 | 607 | li r3,0 |
| 608 | /* XXX What is that for ? SPRG2 appears otherwise unused on 8xx */ | ||
| 608 | mtspr SPRN_SPRG2,r3 /* 0 => r1 has kernel sp */ | 609 | mtspr SPRN_SPRG2,r3 /* 0 => r1 has kernel sp */ |
| 609 | 610 | ||
| 610 | /* stack */ | 611 | /* stack */ |
diff --git a/arch/powerpc/kernel/head_booke.h b/arch/powerpc/kernel/head_booke.h index 5f9febc8d143..50504ae39cb7 100644 --- a/arch/powerpc/kernel/head_booke.h +++ b/arch/powerpc/kernel/head_booke.h | |||
| @@ -20,14 +20,14 @@ | |||
| 20 | #endif | 20 | #endif |
| 21 | 21 | ||
| 22 | #define NORMAL_EXCEPTION_PROLOG \ | 22 | #define NORMAL_EXCEPTION_PROLOG \ |
| 23 | mtspr SPRN_SPRG0,r10; /* save two registers to work with */\ | 23 | mtspr SPRN_SPRG_WSCRATCH0,r10;/* save two registers to work with */\ |
| 24 | mtspr SPRN_SPRG1,r11; \ | 24 | mtspr SPRN_SPRG_WSCRATCH1,r11; \ |
| 25 | mtspr SPRN_SPRG4W,r1; \ | 25 | mtspr SPRN_SPRG_WSCRATCH2,r1; \ |
| 26 | mfcr r10; /* save CR in r10 for now */\ | 26 | mfcr r10; /* save CR in r10 for now */\ |
| 27 | mfspr r11,SPRN_SRR1; /* check whether user or kernel */\ | 27 | mfspr r11,SPRN_SRR1; /* check whether user or kernel */\ |
| 28 | andi. r11,r11,MSR_PR; \ | 28 | andi. r11,r11,MSR_PR; \ |
| 29 | beq 1f; \ | 29 | beq 1f; \ |
| 30 | mfspr r1,SPRN_SPRG3; /* if from user, start at top of */\ | 30 | mfspr r1,SPRN_SPRG_THREAD; /* if from user, start at top of */\ |
| 31 | lwz r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack */\ | 31 | lwz r1,THREAD_INFO-THREAD(r1); /* this thread's kernel stack */\ |
| 32 | ALLOC_STACK_FRAME(r1, THREAD_SIZE); \ | 32 | ALLOC_STACK_FRAME(r1, THREAD_SIZE); \ |
| 33 | 1: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\ | 33 | 1: subi r1,r1,INT_FRAME_SIZE; /* Allocate an exception frame */\ |
| @@ -35,13 +35,13 @@ | |||
| 35 | stw r10,_CCR(r11); /* save various registers */\ | 35 | stw r10,_CCR(r11); /* save various registers */\ |
| 36 | stw r12,GPR12(r11); \ | 36 | stw r12,GPR12(r11); \ |
| 37 | stw r9,GPR9(r11); \ | 37 | stw r9,GPR9(r11); \ |
| 38 | mfspr r10,SPRN_SPRG0; \ | 38 | mfspr r10,SPRN_SPRG_RSCRATCH0; \ |
| 39 | stw r10,GPR10(r11); \ | 39 | stw r10,GPR10(r11); \ |
| 40 | mfspr r12,SPRN_SPRG1; \ | 40 | mfspr r12,SPRN_SPRG_RSCRATCH1; \ |
| 41 | stw r12,GPR11(r11); \ | 41 | stw r12,GPR11(r11); \ |
| 42 | mflr r10; \ | 42 | mflr r10; \ |
| 43 | stw r10,_LINK(r11); \ | 43 | stw r10,_LINK(r11); \ |
| 44 | mfspr r10,SPRN_SPRG4R; \ | 44 | mfspr r10,SPRN_SPRG_RSCRATCH2; \ |
| 45 | mfspr r12,SPRN_SRR0; \ | 45 | mfspr r12,SPRN_SRR0; \ |
| 46 | stw r10,GPR1(r11); \ | 46 | stw r10,GPR1(r11); \ |
| 47 | mfspr r9,SPRN_SRR1; \ | 47 | mfspr r9,SPRN_SRR1; \ |
| @@ -69,21 +69,11 @@ | |||
| 69 | * providing configurations that micro-optimize space usage. | 69 | * providing configurations that micro-optimize space usage. |
| 70 | */ | 70 | */ |
| 71 | 71 | ||
| 72 | /* CRIT_SPRG only used in critical exception handling */ | 72 | #define MC_STACK_BASE mcheckirq_ctx |
| 73 | #define CRIT_SPRG SPRN_SPRG2 | ||
| 74 | /* MCHECK_SPRG only used in machine check exception handling */ | ||
| 75 | #define MCHECK_SPRG SPRN_SPRG6W | ||
| 76 | |||
| 77 | #define MCHECK_STACK_BASE mcheckirq_ctx | ||
| 78 | #define CRIT_STACK_BASE critirq_ctx | 73 | #define CRIT_STACK_BASE critirq_ctx |
| 79 | 74 | ||
| 80 | /* only on e500mc/e200 */ | 75 | /* only on e500mc/e200 */ |
| 81 | #define DEBUG_STACK_BASE dbgirq_ctx | 76 | #define DBG_STACK_BASE dbgirq_ctx |
| 82 | #ifdef CONFIG_E200 | ||
| 83 | #define DEBUG_SPRG SPRN_SPRG6W | ||
| 84 | #else | ||
| 85 | #define DEBUG_SPRG SPRN_SPRG9 | ||
| 86 | #endif | ||
| 87 | 77 | ||
| 88 | #define EXC_LVL_FRAME_OVERHEAD (THREAD_SIZE - INT_FRAME_SIZE - EXC_LVL_SIZE) | 78 | #define EXC_LVL_FRAME_OVERHEAD (THREAD_SIZE - INT_FRAME_SIZE - EXC_LVL_SIZE) |
| 89 | 79 | ||
| @@ -110,7 +100,7 @@ | |||
| 110 | * critical/machine check exception stack at low physical addresses. | 100 | * critical/machine check exception stack at low physical addresses. |
| 111 | */ | 101 | */ |
| 112 | #define EXC_LEVEL_EXCEPTION_PROLOG(exc_level, exc_level_srr0, exc_level_srr1) \ | 102 | #define EXC_LEVEL_EXCEPTION_PROLOG(exc_level, exc_level_srr0, exc_level_srr1) \ |
| 113 | mtspr exc_level##_SPRG,r8; \ | 103 | mtspr SPRN_SPRG_WSCRATCH_##exc_level,r8; \ |
| 114 | BOOKE_LOAD_EXC_LEVEL_STACK(exc_level);/* r8 points to the exc_level stack*/ \ | 104 | BOOKE_LOAD_EXC_LEVEL_STACK(exc_level);/* r8 points to the exc_level stack*/ \ |
| 115 | stw r9,GPR9(r8); /* save various registers */\ | 105 | stw r9,GPR9(r8); /* save various registers */\ |
| 116 | mfcr r9; /* save CR in r9 for now */\ | 106 | mfcr r9; /* save CR in r9 for now */\ |
| @@ -119,7 +109,7 @@ | |||
| 119 | stw r9,_CCR(r8); /* save CR on stack */\ | 109 | stw r9,_CCR(r8); /* save CR on stack */\ |
| 120 | mfspr r10,exc_level_srr1; /* check whether user or kernel */\ | 110 | mfspr r10,exc_level_srr1; /* check whether user or kernel */\ |
| 121 | andi. r10,r10,MSR_PR; \ | 111 | andi. r10,r10,MSR_PR; \ |
| 122 | mfspr r11,SPRN_SPRG3; /* if from user, start at top of */\ | 112 | mfspr r11,SPRN_SPRG_THREAD; /* if from user, start at top of */\ |
| 123 | lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\ | 113 | lwz r11,THREAD_INFO-THREAD(r11); /* this thread's kernel stack */\ |
| 124 | addi r11,r11,EXC_LVL_FRAME_OVERHEAD; /* allocate stack frame */\ | 114 | addi r11,r11,EXC_LVL_FRAME_OVERHEAD; /* allocate stack frame */\ |
| 125 | beq 1f; \ | 115 | beq 1f; \ |
| @@ -140,7 +130,7 @@ | |||
| 140 | lwz r9,TI_TASK-EXC_LVL_FRAME_OVERHEAD(r11); \ | 130 | lwz r9,TI_TASK-EXC_LVL_FRAME_OVERHEAD(r11); \ |
| 141 | stw r9,TI_TASK-EXC_LVL_FRAME_OVERHEAD(r8); \ | 131 | stw r9,TI_TASK-EXC_LVL_FRAME_OVERHEAD(r8); \ |
| 142 | mr r11,r8; \ | 132 | mr r11,r8; \ |
| 143 | 2: mfspr r8,exc_level##_SPRG; \ | 133 | 2: mfspr r8,SPRN_SPRG_RSCRATCH_##exc_level; \ |
| 144 | stw r12,GPR12(r11); /* save various registers */\ | 134 | stw r12,GPR12(r11); /* save various registers */\ |
| 145 | mflr r10; \ | 135 | mflr r10; \ |
| 146 | stw r10,_LINK(r11); \ | 136 | stw r10,_LINK(r11); \ |
| @@ -161,9 +151,9 @@ | |||
| 161 | #define CRITICAL_EXCEPTION_PROLOG \ | 151 | #define CRITICAL_EXCEPTION_PROLOG \ |
| 162 | EXC_LEVEL_EXCEPTION_PROLOG(CRIT, SPRN_CSRR0, SPRN_CSRR1) | 152 | EXC_LEVEL_EXCEPTION_PROLOG(CRIT, SPRN_CSRR0, SPRN_CSRR1) |
| 163 | #define DEBUG_EXCEPTION_PROLOG \ | 153 | #define DEBUG_EXCEPTION_PROLOG \ |
| 164 | EXC_LEVEL_EXCEPTION_PROLOG(DEBUG, SPRN_DSRR0, SPRN_DSRR1) | 154 | EXC_LEVEL_EXCEPTION_PROLOG(DBG, SPRN_DSRR0, SPRN_DSRR1) |
| 165 | #define MCHECK_EXCEPTION_PROLOG \ | 155 | #define MCHECK_EXCEPTION_PROLOG \ |
| 166 | EXC_LEVEL_EXCEPTION_PROLOG(MCHECK, SPRN_MCSRR0, SPRN_MCSRR1) | 156 | EXC_LEVEL_EXCEPTION_PROLOG(MC, SPRN_MCSRR0, SPRN_MCSRR1) |
| 167 | 157 | ||
| 168 | /* | 158 | /* |
| 169 | * Exception vectors. | 159 | * Exception vectors. |
| @@ -282,13 +272,13 @@ label: | |||
| 282 | mtspr SPRN_DSRR1,r9; \ | 272 | mtspr SPRN_DSRR1,r9; \ |
| 283 | lwz r9,GPR9(r11); \ | 273 | lwz r9,GPR9(r11); \ |
| 284 | lwz r12,GPR12(r11); \ | 274 | lwz r12,GPR12(r11); \ |
| 285 | mtspr DEBUG_SPRG,r8; \ | 275 | mtspr SPRN_SPRG_WSCRATCH_DBG,r8; \ |
| 286 | BOOKE_LOAD_EXC_LEVEL_STACK(DEBUG); /* r8 points to the debug stack */ \ | 276 | BOOKE_LOAD_EXC_LEVEL_STACK(DBG); /* r8 points to the debug stack */ \ |
| 287 | lwz r10,GPR10(r8); \ | 277 | lwz r10,GPR10(r8); \ |
| 288 | lwz r11,GPR11(r8); \ | 278 | lwz r11,GPR11(r8); \ |
| 289 | mfspr r8,DEBUG_SPRG; \ | 279 | mfspr r8,SPRN_SPRG_RSCRATCH_DBG; \ |
| 290 | \ | 280 | \ |
| 291 | PPC_RFDI; \ | 281 | PPC_RFDI; \ |
| 292 | b .; \ | 282 | b .; \ |
| 293 | \ | 283 | \ |
| 294 | /* continue normal handling for a debug exception... */ \ | 284 | /* continue normal handling for a debug exception... */ \ |
| @@ -335,11 +325,11 @@ label: | |||
| 335 | mtspr SPRN_CSRR1,r9; \ | 325 | mtspr SPRN_CSRR1,r9; \ |
| 336 | lwz r9,GPR9(r11); \ | 326 | lwz r9,GPR9(r11); \ |
| 337 | lwz r12,GPR12(r11); \ | 327 | lwz r12,GPR12(r11); \ |
| 338 | mtspr CRIT_SPRG,r8; \ | 328 | mtspr SPRN_SPRG_WSCRATCH_CRIT,r8; \ |
| 339 | BOOKE_LOAD_EXC_LEVEL_STACK(CRIT); /* r8 points to the debug stack */ \ | 329 | BOOKE_LOAD_EXC_LEVEL_STACK(CRIT); /* r8 points to the debug stack */ \ |
| 340 | lwz r10,GPR10(r8); \ | 330 | lwz r10,GPR10(r8); \ |
| 341 | lwz r11,GPR11(r8); \ | 331 | lwz r11,GPR11(r8); \ |
| 342 | mfspr r8,CRIT_SPRG; \ | 332 | mfspr r8,SPRN_SPRG_RSCRATCH_CRIT; \ |
| 343 | \ | 333 | \ |
| 344 | rfci; \ | 334 | rfci; \ |
| 345 | b .; \ | 335 | b .; \ |
diff --git a/arch/powerpc/kernel/head_fsl_booke.S b/arch/powerpc/kernel/head_fsl_booke.S index 5bdcc06d294c..975788ca05d2 100644 --- a/arch/powerpc/kernel/head_fsl_booke.S +++ b/arch/powerpc/kernel/head_fsl_booke.S | |||
| @@ -361,7 +361,7 @@ skpinv: addi r6,r6,1 /* Increment */ | |||
| 361 | 361 | ||
| 362 | /* ptr to current thread */ | 362 | /* ptr to current thread */ |
| 363 | addi r4,r2,THREAD /* init task's THREAD */ | 363 | addi r4,r2,THREAD /* init task's THREAD */ |
| 364 | mtspr SPRN_SPRG3,r4 | 364 | mtspr SPRN_SPRG_THREAD,r4 |
| 365 | 365 | ||
| 366 | /* stack */ | 366 | /* stack */ |
| 367 | lis r1,init_thread_union@h | 367 | lis r1,init_thread_union@h |
| @@ -532,12 +532,12 @@ interrupt_base: | |||
| 532 | 532 | ||
| 533 | /* Data TLB Error Interrupt */ | 533 | /* Data TLB Error Interrupt */ |
| 534 | START_EXCEPTION(DataTLBError) | 534 | START_EXCEPTION(DataTLBError) |
| 535 | mtspr SPRN_SPRG0, r10 /* Save some working registers */ | 535 | mtspr SPRN_SPRG_WSCRATCH0, r10 /* Save some working registers */ |
| 536 | mtspr SPRN_SPRG1, r11 | 536 | mtspr SPRN_SPRG_WSCRATCH1, r11 |
| 537 | mtspr SPRN_SPRG4W, r12 | 537 | mtspr SPRN_SPRG_WSCRATCH2, r12 |
| 538 | mtspr SPRN_SPRG5W, r13 | 538 | mtspr SPRN_SPRG_WSCRATCH3, r13 |
| 539 | mfcr r11 | 539 | mfcr r11 |
| 540 | mtspr SPRN_SPRG7W, r11 | 540 | mtspr SPRN_SPRG_WSCRATCH4, r11 |
| 541 | mfspr r10, SPRN_DEAR /* Get faulting address */ | 541 | mfspr r10, SPRN_DEAR /* Get faulting address */ |
| 542 | 542 | ||
| 543 | /* If we are faulting a kernel address, we have to use the | 543 | /* If we are faulting a kernel address, we have to use the |
| @@ -557,7 +557,7 @@ interrupt_base: | |||
| 557 | 557 | ||
| 558 | /* Get the PGD for the current thread */ | 558 | /* Get the PGD for the current thread */ |
| 559 | 3: | 559 | 3: |
| 560 | mfspr r11,SPRN_SPRG3 | 560 | mfspr r11,SPRN_SPRG_THREAD |
| 561 | lwz r11,PGDIR(r11) | 561 | lwz r11,PGDIR(r11) |
| 562 | 562 | ||
| 563 | 4: | 563 | 4: |
| @@ -575,7 +575,12 @@ interrupt_base: | |||
| 575 | * place or can we save a couple of instructions here ? | 575 | * place or can we save a couple of instructions here ? |
| 576 | */ | 576 | */ |
| 577 | mfspr r12,SPRN_ESR | 577 | mfspr r12,SPRN_ESR |
| 578 | #ifdef CONFIG_PTE_64BIT | ||
| 579 | li r13,_PAGE_PRESENT | ||
| 580 | oris r13,r13,_PAGE_ACCESSED@h | ||
| 581 | #else | ||
| 578 | li r13,_PAGE_PRESENT|_PAGE_ACCESSED | 582 | li r13,_PAGE_PRESENT|_PAGE_ACCESSED |
| 583 | #endif | ||
| 579 | rlwimi r13,r12,11,29,29 | 584 | rlwimi r13,r12,11,29,29 |
| 580 | 585 | ||
| 581 | FIND_PTE | 586 | FIND_PTE |
| @@ -598,12 +603,12 @@ interrupt_base: | |||
| 598 | /* The bailout. Restore registers to pre-exception conditions | 603 | /* The bailout. Restore registers to pre-exception conditions |
| 599 | * and call the heavyweights to help us out. | 604 | * and call the heavyweights to help us out. |
| 600 | */ | 605 | */ |
| 601 | mfspr r11, SPRN_SPRG7R | 606 | mfspr r11, SPRN_SPRG_RSCRATCH4 |
| 602 | mtcr r11 | 607 | mtcr r11 |
| 603 | mfspr r13, SPRN_SPRG5R | 608 | mfspr r13, SPRN_SPRG_RSCRATCH3 |
| 604 | mfspr r12, SPRN_SPRG4R | 609 | mfspr r12, SPRN_SPRG_RSCRATCH2 |
| 605 | mfspr r11, SPRN_SPRG1 | 610 | mfspr r11, SPRN_SPRG_RSCRATCH1 |
| 606 | mfspr r10, SPRN_SPRG0 | 611 | mfspr r10, SPRN_SPRG_RSCRATCH0 |
| 607 | b DataStorage | 612 | b DataStorage |
| 608 | 613 | ||
| 609 | /* Instruction TLB Error Interrupt */ | 614 | /* Instruction TLB Error Interrupt */ |
| @@ -613,12 +618,12 @@ interrupt_base: | |||
| 613 | * to a different point. | 618 | * to a different point. |
| 614 | */ | 619 | */ |
| 615 | START_EXCEPTION(InstructionTLBError) | 620 | START_EXCEPTION(InstructionTLBError) |
| 616 | mtspr SPRN_SPRG0, r10 /* Save some working registers */ | 621 | mtspr SPRN_SPRG_WSCRATCH0, r10 /* Save some working registers */ |
| 617 | mtspr SPRN_SPRG1, r11 | 622 | mtspr SPRN_SPRG_WSCRATCH1, r11 |
| 618 | mtspr SPRN_SPRG4W, r12 | 623 | mtspr SPRN_SPRG_WSCRATCH2, r12 |
| 619 | mtspr SPRN_SPRG5W, r13 | 624 | mtspr SPRN_SPRG_WSCRATCH3, r13 |
| 620 | mfcr r11 | 625 | mfcr r11 |
| 621 | mtspr SPRN_SPRG7W, r11 | 626 | mtspr SPRN_SPRG_WSCRATCH4, r11 |
| 622 | mfspr r10, SPRN_SRR0 /* Get faulting address */ | 627 | mfspr r10, SPRN_SRR0 /* Get faulting address */ |
| 623 | 628 | ||
| 624 | /* If we are faulting a kernel address, we have to use the | 629 | /* If we are faulting a kernel address, we have to use the |
| @@ -638,12 +643,17 @@ interrupt_base: | |||
| 638 | 643 | ||
| 639 | /* Get the PGD for the current thread */ | 644 | /* Get the PGD for the current thread */ |
| 640 | 3: | 645 | 3: |
| 641 | mfspr r11,SPRN_SPRG3 | 646 | mfspr r11,SPRN_SPRG_THREAD |
| 642 | lwz r11,PGDIR(r11) | 647 | lwz r11,PGDIR(r11) |
| 643 | 648 | ||
| 644 | 4: | 649 | 4: |
| 645 | /* Make up the required permissions */ | 650 | /* Make up the required permissions */ |
| 646 | li r13,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_HWEXEC | 651 | #ifdef CONFIG_PTE_64BIT |
| 652 | li r13,_PAGE_PRESENT | _PAGE_EXEC | ||
| 653 | oris r13,r13,_PAGE_ACCESSED@h | ||
| 654 | #else | ||
| 655 | li r13,_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_EXEC | ||
| 656 | #endif | ||
| 647 | 657 | ||
| 648 | FIND_PTE | 658 | FIND_PTE |
| 649 | andc. r13,r13,r11 /* Check permission */ | 659 | andc. r13,r13,r11 /* Check permission */ |
| @@ -666,12 +676,12 @@ interrupt_base: | |||
| 666 | /* The bailout. Restore registers to pre-exception conditions | 676 | /* The bailout. Restore registers to pre-exception conditions |
| 667 | * and call the heavyweights to help us out. | 677 | * and call the heavyweights to help us out. |
| 668 | */ | 678 | */ |
| 669 | mfspr r11, SPRN_SPRG7R | 679 | mfspr r11, SPRN_SPRG_RSCRATCH4 |
| 670 | mtcr r11 | 680 | mtcr r11 |
| 671 | mfspr r13, SPRN_SPRG5R | 681 | mfspr r13, SPRN_SPRG_RSCRATCH3 |
| 672 | mfspr r12, SPRN_SPRG4R | 682 | mfspr r12, SPRN_SPRG_RSCRATCH2 |
| 673 | mfspr r11, SPRN_SPRG1 | 683 | mfspr r11, SPRN_SPRG_RSCRATCH1 |
| 674 | mfspr r10, SPRN_SPRG0 | 684 | mfspr r10, SPRN_SPRG_RSCRATCH0 |
| 675 | b InstructionStorage | 685 | b InstructionStorage |
| 676 | 686 | ||
| 677 | #ifdef CONFIG_SPE | 687 | #ifdef CONFIG_SPE |
| @@ -733,7 +743,7 @@ finish_tlb_load: | |||
| 733 | 743 | ||
| 734 | mfspr r12, SPRN_MAS2 | 744 | mfspr r12, SPRN_MAS2 |
| 735 | #ifdef CONFIG_PTE_64BIT | 745 | #ifdef CONFIG_PTE_64BIT |
| 736 | rlwimi r12, r11, 26, 24, 31 /* extract ...WIMGE from pte */ | 746 | rlwimi r12, r11, 32-19, 27, 31 /* extract WIMGE from pte */ |
| 737 | #else | 747 | #else |
| 738 | rlwimi r12, r11, 26, 27, 31 /* extract WIMGE from pte */ | 748 | rlwimi r12, r11, 26, 27, 31 /* extract WIMGE from pte */ |
| 739 | #endif | 749 | #endif |
| @@ -742,23 +752,27 @@ finish_tlb_load: | |||
| 742 | #endif | 752 | #endif |
| 743 | mtspr SPRN_MAS2, r12 | 753 | mtspr SPRN_MAS2, r12 |
| 744 | 754 | ||
| 745 | li r10, (_PAGE_HWEXEC | _PAGE_PRESENT) | ||
| 746 | rlwimi r10, r11, 31, 29, 29 /* extract _PAGE_DIRTY into SW */ | ||
| 747 | and r12, r11, r10 | ||
| 748 | andi. r10, r11, _PAGE_USER /* Test for _PAGE_USER */ | ||
| 749 | slwi r10, r12, 1 | ||
| 750 | or r10, r10, r12 | ||
| 751 | iseleq r12, r12, r10 | ||
| 752 | |||
| 753 | #ifdef CONFIG_PTE_64BIT | 755 | #ifdef CONFIG_PTE_64BIT |
| 754 | rlwimi r12, r13, 24, 0, 7 /* grab RPN[32:39] */ | 756 | rlwinm r12, r11, 32-2, 26, 31 /* Move in perm bits */ |
| 755 | rlwimi r12, r11, 24, 8, 19 /* grab RPN[40:51] */ | 757 | andi. r10, r11, _PAGE_DIRTY |
| 758 | bne 1f | ||
| 759 | li r10, MAS3_SW | MAS3_UW | ||
| 760 | andc r12, r12, r10 | ||
| 761 | 1: rlwimi r12, r13, 20, 0, 11 /* grab RPN[32:43] */ | ||
| 762 | rlwimi r12, r11, 20, 12, 19 /* grab RPN[44:51] */ | ||
| 756 | mtspr SPRN_MAS3, r12 | 763 | mtspr SPRN_MAS3, r12 |
| 757 | BEGIN_MMU_FTR_SECTION | 764 | BEGIN_MMU_FTR_SECTION |
| 758 | srwi r10, r13, 8 /* grab RPN[8:31] */ | 765 | srwi r10, r13, 12 /* grab RPN[12:31] */ |
| 759 | mtspr SPRN_MAS7, r10 | 766 | mtspr SPRN_MAS7, r10 |
| 760 | END_MMU_FTR_SECTION_IFSET(MMU_FTR_BIG_PHYS) | 767 | END_MMU_FTR_SECTION_IFSET(MMU_FTR_BIG_PHYS) |
| 761 | #else | 768 | #else |
| 769 | li r10, (_PAGE_EXEC | _PAGE_PRESENT) | ||
| 770 | rlwimi r10, r11, 31, 29, 29 /* extract _PAGE_DIRTY into SW */ | ||
| 771 | and r12, r11, r10 | ||
| 772 | andi. r10, r11, _PAGE_USER /* Test for _PAGE_USER */ | ||
| 773 | slwi r10, r12, 1 | ||
| 774 | or r10, r10, r12 | ||
| 775 | iseleq r12, r12, r10 | ||
| 762 | rlwimi r11, r12, 0, 20, 31 /* Extract RPN from PTE and merge with perms */ | 776 | rlwimi r11, r12, 0, 20, 31 /* Extract RPN from PTE and merge with perms */ |
| 763 | mtspr SPRN_MAS3, r11 | 777 | mtspr SPRN_MAS3, r11 |
| 764 | #endif | 778 | #endif |
| @@ -790,12 +804,12 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_BIG_PHYS) | |||
| 790 | tlbwe | 804 | tlbwe |
| 791 | 805 | ||
| 792 | /* Done...restore registers and get out of here. */ | 806 | /* Done...restore registers and get out of here. */ |
| 793 | mfspr r11, SPRN_SPRG7R | 807 | mfspr r11, SPRN_SPRG_RSCRATCH4 |
| 794 | mtcr r11 | 808 | mtcr r11 |
| 795 | mfspr r13, SPRN_SPRG5R | 809 | mfspr r13, SPRN_SPRG_RSCRATCH3 |
| 796 | mfspr r12, SPRN_SPRG4R | 810 | mfspr r12, SPRN_SPRG_RSCRATCH2 |
| 797 | mfspr r11, SPRN_SPRG1 | 811 | mfspr r11, SPRN_SPRG_RSCRATCH1 |
| 798 | mfspr r10, SPRN_SPRG0 | 812 | mfspr r10, SPRN_SPRG_RSCRATCH0 |
| 799 | rfi /* Force context change */ | 813 | rfi /* Force context change */ |
| 800 | 814 | ||
| 801 | #ifdef CONFIG_SPE | 815 | #ifdef CONFIG_SPE |
| @@ -839,7 +853,7 @@ load_up_spe: | |||
| 839 | #endif /* !CONFIG_SMP */ | 853 | #endif /* !CONFIG_SMP */ |
| 840 | /* enable use of SPE after return */ | 854 | /* enable use of SPE after return */ |
| 841 | oris r9,r9,MSR_SPE@h | 855 | oris r9,r9,MSR_SPE@h |
| 842 | mfspr r5,SPRN_SPRG3 /* current task's THREAD (phys) */ | 856 | mfspr r5,SPRN_SPRG_THREAD /* current task's THREAD (phys) */ |
| 843 | li r4,1 | 857 | li r4,1 |
| 844 | li r10,THREAD_ACC | 858 | li r10,THREAD_ACC |
| 845 | stw r4,THREAD_USED_SPE(r5) | 859 | stw r4,THREAD_USED_SPE(r5) |
| @@ -1118,7 +1132,7 @@ __secondary_start: | |||
| 1118 | 1132 | ||
| 1119 | /* ptr to current thread */ | 1133 | /* ptr to current thread */ |
| 1120 | addi r4,r2,THREAD /* address of our thread_struct */ | 1134 | addi r4,r2,THREAD /* address of our thread_struct */ |
| 1121 | mtspr SPRN_SPRG3,r4 | 1135 | mtspr SPRN_SPRG_THREAD,r4 |
| 1122 | 1136 | ||
| 1123 | /* Setup the defaults for TLB entries */ | 1137 | /* Setup the defaults for TLB entries */ |
| 1124 | li r4,(MAS4_TSIZED(BOOK3E_PAGESZ_4K))@l | 1138 | li r4,(MAS4_TSIZED(BOOK3E_PAGESZ_4K))@l |
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c index 6e3f62493659..a4c8b38b0ba1 100644 --- a/arch/powerpc/kernel/ibmebus.c +++ b/arch/powerpc/kernel/ibmebus.c | |||
| @@ -127,7 +127,7 @@ static int ibmebus_dma_supported(struct device *dev, u64 mask) | |||
| 127 | return 1; | 127 | return 1; |
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | static struct dma_mapping_ops ibmebus_dma_ops = { | 130 | static struct dma_map_ops ibmebus_dma_ops = { |
| 131 | .alloc_coherent = ibmebus_alloc_coherent, | 131 | .alloc_coherent = ibmebus_alloc_coherent, |
| 132 | .free_coherent = ibmebus_free_coherent, | 132 | .free_coherent = ibmebus_free_coherent, |
| 133 | .map_sg = ibmebus_map_sg, | 133 | .map_sg = ibmebus_map_sg, |
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index 2419cc706ff1..ed0ac4e4b8d8 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #include <asm/prom.h> | 35 | #include <asm/prom.h> |
| 36 | #include <asm/vdso_datapage.h> | 36 | #include <asm/vdso_datapage.h> |
| 37 | #include <asm/vio.h> | 37 | #include <asm/vio.h> |
| 38 | #include <asm/mmu.h> | ||
| 38 | 39 | ||
| 39 | #define MODULE_VERS "1.8" | 40 | #define MODULE_VERS "1.8" |
| 40 | #define MODULE_NAME "lparcfg" | 41 | #define MODULE_NAME "lparcfg" |
| @@ -537,6 +538,8 @@ static int pseries_lparcfg_data(struct seq_file *m, void *v) | |||
| 537 | 538 | ||
| 538 | seq_printf(m, "shared_processor_mode=%d\n", lppaca[0].shared_proc); | 539 | seq_printf(m, "shared_processor_mode=%d\n", lppaca[0].shared_proc); |
| 539 | 540 | ||
| 541 | seq_printf(m, "slb_size=%d\n", mmu_slb_size); | ||
| 542 | |||
| 540 | return 0; | 543 | return 0; |
| 541 | } | 544 | } |
| 542 | 545 | ||
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 15f28e0de78d..da9c0c4c10f3 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S | |||
| @@ -342,10 +342,17 @@ END_FTR_SECTION_IFSET(CPU_FTR_COHERENT_ICACHE) | |||
| 342 | addi r3,r3,L1_CACHE_BYTES | 342 | addi r3,r3,L1_CACHE_BYTES |
| 343 | bdnz 1b | 343 | bdnz 1b |
| 344 | sync /* wait for dcbst's to get to ram */ | 344 | sync /* wait for dcbst's to get to ram */ |
| 345 | #ifndef CONFIG_44x | ||
| 345 | mtctr r4 | 346 | mtctr r4 |
| 346 | 2: icbi 0,r6 | 347 | 2: icbi 0,r6 |
| 347 | addi r6,r6,L1_CACHE_BYTES | 348 | addi r6,r6,L1_CACHE_BYTES |
| 348 | bdnz 2b | 349 | bdnz 2b |
| 350 | #else | ||
| 351 | /* Flash invalidate on 44x because we are passed kmapped addresses and | ||
| 352 | this doesn't work for userspace pages due to the virtually tagged | ||
| 353 | icache. Sigh. */ | ||
| 354 | iccci 0, r0 | ||
| 355 | #endif | ||
| 349 | sync /* additional sync needed on g4 */ | 356 | sync /* additional sync needed on g4 */ |
| 350 | isync | 357 | isync |
| 351 | blr | 358 | blr |
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c index 87df428e3588..1a4fc0d11a03 100644 --- a/arch/powerpc/kernel/of_platform.c +++ b/arch/powerpc/kernel/of_platform.c | |||
| @@ -276,7 +276,7 @@ static int __devinit of_pci_phb_probe(struct of_device *dev, | |||
| 276 | #endif /* CONFIG_EEH */ | 276 | #endif /* CONFIG_EEH */ |
| 277 | 277 | ||
| 278 | /* Scan the bus */ | 278 | /* Scan the bus */ |
| 279 | scan_phb(phb); | 279 | pcibios_scan_phb(phb, dev->node); |
| 280 | if (phb->bus == NULL) | 280 | if (phb->bus == NULL) |
| 281 | return -ENXIO; | 281 | return -ENXIO; |
| 282 | 282 | ||
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c index e9962c7f8a09..d16b1ea55d44 100644 --- a/arch/powerpc/kernel/paca.c +++ b/arch/powerpc/kernel/paca.c | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <asm/lppaca.h> | 13 | #include <asm/lppaca.h> |
| 14 | #include <asm/paca.h> | 14 | #include <asm/paca.h> |
| 15 | #include <asm/sections.h> | 15 | #include <asm/sections.h> |
| 16 | #include <asm/pgtable.h> | ||
| 16 | 17 | ||
| 17 | /* This symbol is provided by the linker - let it fill in the paca | 18 | /* This symbol is provided by the linker - let it fill in the paca |
| 18 | * field correctly */ | 19 | * field correctly */ |
| @@ -87,6 +88,8 @@ void __init initialise_pacas(void) | |||
| 87 | 88 | ||
| 88 | #ifdef CONFIG_PPC_BOOK3S | 89 | #ifdef CONFIG_PPC_BOOK3S |
| 89 | new_paca->lppaca_ptr = &lppaca[cpu]; | 90 | new_paca->lppaca_ptr = &lppaca[cpu]; |
| 91 | #else | ||
| 92 | new_paca->kernel_pgd = swapper_pg_dir; | ||
| 90 | #endif | 93 | #endif |
| 91 | new_paca->lock_token = 0x8000; | 94 | new_paca->lock_token = 0x8000; |
| 92 | new_paca->paca_index = cpu; | 95 | new_paca->paca_index = cpu; |
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c index 5a56e97c5ac0..e9f4840096b3 100644 --- a/arch/powerpc/kernel/pci-common.c +++ b/arch/powerpc/kernel/pci-common.c | |||
| @@ -50,14 +50,14 @@ resource_size_t isa_mem_base; | |||
| 50 | unsigned int ppc_pci_flags = 0; | 50 | unsigned int ppc_pci_flags = 0; |
| 51 | 51 | ||
| 52 | 52 | ||
| 53 | static struct dma_mapping_ops *pci_dma_ops = &dma_direct_ops; | 53 | static struct dma_map_ops *pci_dma_ops = &dma_direct_ops; |
| 54 | 54 | ||
| 55 | void set_pci_dma_ops(struct dma_mapping_ops *dma_ops) | 55 | void set_pci_dma_ops(struct dma_map_ops *dma_ops) |
| 56 | { | 56 | { |
| 57 | pci_dma_ops = dma_ops; | 57 | pci_dma_ops = dma_ops; |
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | struct dma_mapping_ops *get_pci_dma_ops(void) | 60 | struct dma_map_ops *get_pci_dma_ops(void) |
| 61 | { | 61 | { |
| 62 | return pci_dma_ops; | 62 | return pci_dma_ops; |
| 63 | } | 63 | } |
| @@ -176,8 +176,6 @@ int pci_domain_nr(struct pci_bus *bus) | |||
| 176 | } | 176 | } |
| 177 | EXPORT_SYMBOL(pci_domain_nr); | 177 | EXPORT_SYMBOL(pci_domain_nr); |
| 178 | 178 | ||
| 179 | #ifdef CONFIG_PPC_OF | ||
| 180 | |||
| 181 | /* This routine is meant to be used early during boot, when the | 179 | /* This routine is meant to be used early during boot, when the |
| 182 | * PCI bus numbers have not yet been assigned, and you need to | 180 | * PCI bus numbers have not yet been assigned, and you need to |
| 183 | * issue PCI config cycles to an OF device. | 181 | * issue PCI config cycles to an OF device. |
| @@ -210,17 +208,11 @@ static ssize_t pci_show_devspec(struct device *dev, | |||
| 210 | return sprintf(buf, "%s", np->full_name); | 208 | return sprintf(buf, "%s", np->full_name); |
| 211 | } | 209 | } |
| 212 | static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); | 210 | static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); |
| 213 | #endif /* CONFIG_PPC_OF */ | ||
| 214 | 211 | ||
| 215 | /* Add sysfs properties */ | 212 | /* Add sysfs properties */ |
| 216 | int pcibios_add_platform_entries(struct pci_dev *pdev) | 213 | int pcibios_add_platform_entries(struct pci_dev *pdev) |
| 217 | { | 214 | { |
| 218 | #ifdef CONFIG_PPC_OF | ||
| 219 | return device_create_file(&pdev->dev, &dev_attr_devspec); | 215 | return device_create_file(&pdev->dev, &dev_attr_devspec); |
| 220 | #else | ||
| 221 | return 0; | ||
| 222 | #endif /* CONFIG_PPC_OF */ | ||
| 223 | |||
| 224 | } | 216 | } |
| 225 | 217 | ||
| 226 | char __devinit *pcibios_setup(char *str) | 218 | char __devinit *pcibios_setup(char *str) |
| @@ -1626,3 +1618,122 @@ void __devinit pcibios_setup_phb_resources(struct pci_controller *hose) | |||
| 1626 | 1618 | ||
| 1627 | } | 1619 | } |
| 1628 | 1620 | ||
| 1621 | /* | ||
| 1622 | * Null PCI config access functions, for the case when we can't | ||
| 1623 | * find a hose. | ||
| 1624 | */ | ||
| 1625 | #define NULL_PCI_OP(rw, size, type) \ | ||
| 1626 | static int \ | ||
| 1627 | null_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \ | ||
| 1628 | { \ | ||
| 1629 | return PCIBIOS_DEVICE_NOT_FOUND; \ | ||
| 1630 | } | ||
| 1631 | |||
| 1632 | static int | ||
| 1633 | null_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | ||
| 1634 | int len, u32 *val) | ||
| 1635 | { | ||
| 1636 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 1637 | } | ||
| 1638 | |||
| 1639 | static int | ||
| 1640 | null_write_config(struct pci_bus *bus, unsigned int devfn, int offset, | ||
| 1641 | int len, u32 val) | ||
| 1642 | { | ||
| 1643 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 1644 | } | ||
| 1645 | |||
| 1646 | static struct pci_ops null_pci_ops = | ||
| 1647 | { | ||
| 1648 | .read = null_read_config, | ||
| 1649 | .write = null_write_config, | ||
| 1650 | }; | ||
| 1651 | |||
| 1652 | /* | ||
| 1653 | * These functions are used early on before PCI scanning is done | ||
| 1654 | * and all of the pci_dev and pci_bus structures have been created. | ||
| 1655 | */ | ||
| 1656 | static struct pci_bus * | ||
| 1657 | fake_pci_bus(struct pci_controller *hose, int busnr) | ||
| 1658 | { | ||
| 1659 | static struct pci_bus bus; | ||
| 1660 | |||
| 1661 | if (hose == 0) { | ||
| 1662 | printk(KERN_ERR "Can't find hose for PCI bus %d!\n", busnr); | ||
| 1663 | } | ||
| 1664 | bus.number = busnr; | ||
| 1665 | bus.sysdata = hose; | ||
| 1666 | bus.ops = hose? hose->ops: &null_pci_ops; | ||
| 1667 | return &bus; | ||
| 1668 | } | ||
| 1669 | |||
| 1670 | #define EARLY_PCI_OP(rw, size, type) \ | ||
| 1671 | int early_##rw##_config_##size(struct pci_controller *hose, int bus, \ | ||
| 1672 | int devfn, int offset, type value) \ | ||
| 1673 | { \ | ||
| 1674 | return pci_bus_##rw##_config_##size(fake_pci_bus(hose, bus), \ | ||
| 1675 | devfn, offset, value); \ | ||
| 1676 | } | ||
| 1677 | |||
| 1678 | EARLY_PCI_OP(read, byte, u8 *) | ||
| 1679 | EARLY_PCI_OP(read, word, u16 *) | ||
| 1680 | EARLY_PCI_OP(read, dword, u32 *) | ||
| 1681 | EARLY_PCI_OP(write, byte, u8) | ||
| 1682 | EARLY_PCI_OP(write, word, u16) | ||
| 1683 | EARLY_PCI_OP(write, dword, u32) | ||
| 1684 | |||
| 1685 | extern int pci_bus_find_capability (struct pci_bus *bus, unsigned int devfn, int cap); | ||
| 1686 | int early_find_capability(struct pci_controller *hose, int bus, int devfn, | ||
| 1687 | int cap) | ||
| 1688 | { | ||
| 1689 | return pci_bus_find_capability(fake_pci_bus(hose, bus), devfn, cap); | ||
| 1690 | } | ||
| 1691 | |||
| 1692 | /** | ||
| 1693 | * pci_scan_phb - Given a pci_controller, setup and scan the PCI bus | ||
| 1694 | * @hose: Pointer to the PCI host controller instance structure | ||
| 1695 | * @sysdata: value to use for sysdata pointer. ppc32 and ppc64 differ here | ||
| 1696 | * | ||
| 1697 | * Note: the 'data' pointer is a temporary measure. As 32 and 64 bit | ||
| 1698 | * pci code gets merged, this parameter should become unnecessary because | ||
| 1699 | * both will use the same value. | ||
| 1700 | */ | ||
| 1701 | void __devinit pcibios_scan_phb(struct pci_controller *hose, void *sysdata) | ||
| 1702 | { | ||
| 1703 | struct pci_bus *bus; | ||
| 1704 | struct device_node *node = hose->dn; | ||
| 1705 | int mode; | ||
| 1706 | |||
| 1707 | pr_debug("PCI: Scanning PHB %s\n", | ||
| 1708 | node ? node->full_name : "<NO NAME>"); | ||
| 1709 | |||
| 1710 | /* Create an empty bus for the toplevel */ | ||
| 1711 | bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, | ||
| 1712 | sysdata); | ||
| 1713 | if (bus == NULL) { | ||
| 1714 | pr_err("Failed to create bus for PCI domain %04x\n", | ||
| 1715 | hose->global_number); | ||
| 1716 | return; | ||
| 1717 | } | ||
| 1718 | bus->secondary = hose->first_busno; | ||
| 1719 | hose->bus = bus; | ||
| 1720 | |||
| 1721 | /* Get some IO space for the new PHB */ | ||
| 1722 | pcibios_setup_phb_io_space(hose); | ||
| 1723 | |||
| 1724 | /* Wire up PHB bus resources */ | ||
| 1725 | pcibios_setup_phb_resources(hose); | ||
| 1726 | |||
| 1727 | /* Get probe mode and perform scan */ | ||
| 1728 | mode = PCI_PROBE_NORMAL; | ||
| 1729 | if (node && ppc_md.pci_probe_mode) | ||
| 1730 | mode = ppc_md.pci_probe_mode(bus); | ||
| 1731 | pr_debug(" probe mode: %d\n", mode); | ||
| 1732 | if (mode == PCI_PROBE_DEVTREE) { | ||
| 1733 | bus->subordinate = hose->last_busno; | ||
| 1734 | of_scan_bus(node, bus); | ||
| 1735 | } | ||
| 1736 | |||
| 1737 | if (mode == PCI_PROBE_NORMAL) | ||
| 1738 | hose->last_busno = bus->subordinate = pci_scan_child_bus(bus); | ||
| 1739 | } | ||
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index 3ae1c666ff92..c13668cf36d9 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c | |||
| @@ -34,9 +34,7 @@ int pcibios_assign_bus_offset = 1; | |||
| 34 | void pcibios_make_OF_bus_map(void); | 34 | void pcibios_make_OF_bus_map(void); |
| 35 | 35 | ||
| 36 | static void fixup_cpc710_pci64(struct pci_dev* dev); | 36 | static void fixup_cpc710_pci64(struct pci_dev* dev); |
| 37 | #ifdef CONFIG_PPC_OF | ||
| 38 | static u8* pci_to_OF_bus_map; | 37 | static u8* pci_to_OF_bus_map; |
| 39 | #endif | ||
| 40 | 38 | ||
| 41 | /* By default, we don't re-assign bus numbers. We do this only on | 39 | /* By default, we don't re-assign bus numbers. We do this only on |
| 42 | * some pmacs | 40 | * some pmacs |
| @@ -83,7 +81,6 @@ fixup_cpc710_pci64(struct pci_dev* dev) | |||
| 83 | } | 81 | } |
| 84 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CPC710_PCI64, fixup_cpc710_pci64); | 82 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_IBM_CPC710_PCI64, fixup_cpc710_pci64); |
| 85 | 83 | ||
| 86 | #ifdef CONFIG_PPC_OF | ||
| 87 | /* | 84 | /* |
| 88 | * Functions below are used on OpenFirmware machines. | 85 | * Functions below are used on OpenFirmware machines. |
| 89 | */ | 86 | */ |
| @@ -357,42 +354,15 @@ pci_create_OF_bus_map(void) | |||
| 357 | } | 354 | } |
| 358 | } | 355 | } |
| 359 | 356 | ||
| 360 | #else /* CONFIG_PPC_OF */ | 357 | void __devinit pcibios_setup_phb_io_space(struct pci_controller *hose) |
| 361 | void pcibios_make_OF_bus_map(void) | ||
| 362 | { | 358 | { |
| 363 | } | ||
| 364 | #endif /* CONFIG_PPC_OF */ | ||
| 365 | |||
| 366 | static void __devinit pcibios_scan_phb(struct pci_controller *hose) | ||
| 367 | { | ||
| 368 | struct pci_bus *bus; | ||
| 369 | struct device_node *node = hose->dn; | ||
| 370 | unsigned long io_offset; | 359 | unsigned long io_offset; |
| 371 | struct resource *res = &hose->io_resource; | 360 | struct resource *res = &hose->io_resource; |
| 372 | 361 | ||
| 373 | pr_debug("PCI: Scanning PHB %s\n", | ||
| 374 | node ? node->full_name : "<NO NAME>"); | ||
| 375 | |||
| 376 | /* Create an empty bus for the toplevel */ | ||
| 377 | bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, hose); | ||
| 378 | if (bus == NULL) { | ||
| 379 | printk(KERN_ERR "Failed to create bus for PCI domain %04x\n", | ||
| 380 | hose->global_number); | ||
| 381 | return; | ||
| 382 | } | ||
| 383 | bus->secondary = hose->first_busno; | ||
| 384 | hose->bus = bus; | ||
| 385 | |||
| 386 | /* Fixup IO space offset */ | 362 | /* Fixup IO space offset */ |
| 387 | io_offset = (unsigned long)hose->io_base_virt - isa_io_base; | 363 | io_offset = (unsigned long)hose->io_base_virt - isa_io_base; |
| 388 | res->start = (res->start + io_offset) & 0xffffffffu; | 364 | res->start = (res->start + io_offset) & 0xffffffffu; |
| 389 | res->end = (res->end + io_offset) & 0xffffffffu; | 365 | res->end = (res->end + io_offset) & 0xffffffffu; |
| 390 | |||
| 391 | /* Wire up PHB bus resources */ | ||
| 392 | pcibios_setup_phb_resources(hose); | ||
| 393 | |||
| 394 | /* Scan children */ | ||
| 395 | hose->last_busno = bus->subordinate = pci_scan_child_bus(bus); | ||
| 396 | } | 366 | } |
| 397 | 367 | ||
| 398 | static int __init pcibios_init(void) | 368 | static int __init pcibios_init(void) |
| @@ -410,7 +380,7 @@ static int __init pcibios_init(void) | |||
| 410 | if (pci_assign_all_buses) | 380 | if (pci_assign_all_buses) |
| 411 | hose->first_busno = next_busno; | 381 | hose->first_busno = next_busno; |
| 412 | hose->last_busno = 0xff; | 382 | hose->last_busno = 0xff; |
| 413 | pcibios_scan_phb(hose); | 383 | pcibios_scan_phb(hose, hose); |
| 414 | pci_bus_add_devices(hose->bus); | 384 | pci_bus_add_devices(hose->bus); |
| 415 | if (pci_assign_all_buses || next_busno <= hose->last_busno) | 385 | if (pci_assign_all_buses || next_busno <= hose->last_busno) |
| 416 | next_busno = hose->last_busno + pcibios_assign_bus_offset; | 386 | next_busno = hose->last_busno + pcibios_assign_bus_offset; |
| @@ -478,75 +448,4 @@ long sys_pciconfig_iobase(long which, unsigned long bus, unsigned long devfn) | |||
| 478 | return result; | 448 | return result; |
| 479 | } | 449 | } |
| 480 | 450 | ||
| 481 | /* | ||
| 482 | * Null PCI config access functions, for the case when we can't | ||
| 483 | * find a hose. | ||
| 484 | */ | ||
| 485 | #define NULL_PCI_OP(rw, size, type) \ | ||
| 486 | static int \ | ||
| 487 | null_##rw##_config_##size(struct pci_dev *dev, int offset, type val) \ | ||
| 488 | { \ | ||
| 489 | return PCIBIOS_DEVICE_NOT_FOUND; \ | ||
| 490 | } | ||
| 491 | 451 | ||
| 492 | static int | ||
| 493 | null_read_config(struct pci_bus *bus, unsigned int devfn, int offset, | ||
| 494 | int len, u32 *val) | ||
| 495 | { | ||
| 496 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 497 | } | ||
| 498 | |||
| 499 | static int | ||
| 500 | null_write_config(struct pci_bus *bus, unsigned int devfn, int offset, | ||
| 501 | int len, u32 val) | ||
| 502 | { | ||
| 503 | return PCIBIOS_DEVICE_NOT_FOUND; | ||
| 504 | } | ||
| 505 | |||
| 506 | static struct pci_ops null_pci_ops = | ||
| 507 | { | ||
| 508 | .read = null_read_config, | ||
| 509 | .write = null_write_config, | ||
| 510 | }; | ||
| 511 | |||
| 512 | /* | ||
| 513 | * These functions are used early on before PCI scanning is done | ||
| 514 | * and all of the pci_dev and pci_bus structures have been created. | ||
| 515 | */ | ||
| 516 | static struct pci_bus * | ||
| 517 | fake_pci_bus(struct pci_controller *hose, int busnr) | ||
| 518 | { | ||
| 519 | static struct pci_bus bus; | ||
| 520 | |||
| 521 | if (hose == 0) { | ||
| 522 | hose = pci_bus_to_hose(busnr); | ||
| 523 | if (hose == 0) | ||
| 524 | printk(KERN_ERR "Can't find hose for PCI bus %d!\n", busnr); | ||
| 525 | } | ||
| 526 | bus.number = busnr; | ||
| 527 | bus.sysdata = hose; | ||
| 528 | bus.ops = hose? hose->ops: &null_pci_ops; | ||
| 529 | return &bus; | ||
| 530 | } | ||
| 531 | |||
| 532 | #define EARLY_PCI_OP(rw, size, type) \ | ||
| 533 | int early_##rw##_config_##size(struct pci_controller *hose, int bus, \ | ||
| 534 | int devfn, int offset, type value) \ | ||
| 535 | { \ | ||
| 536 | return pci_bus_##rw##_config_##size(fake_pci_bus(hose, bus), \ | ||
| 537 | devfn, offset, value); \ | ||
| 538 | } | ||
| 539 | |||
| 540 | EARLY_PCI_OP(read, byte, u8 *) | ||
| 541 | EARLY_PCI_OP(read, word, u16 *) | ||
| 542 | EARLY_PCI_OP(read, dword, u32 *) | ||
| 543 | EARLY_PCI_OP(write, byte, u8) | ||
| 544 | EARLY_PCI_OP(write, word, u16) | ||
| 545 | EARLY_PCI_OP(write, dword, u32) | ||
| 546 | |||
| 547 | extern int pci_bus_find_capability (struct pci_bus *bus, unsigned int devfn, int cap); | ||
| 548 | int early_find_capability(struct pci_controller *hose, int bus, int devfn, | ||
| 549 | int cap) | ||
| 550 | { | ||
| 551 | return pci_bus_find_capability(fake_pci_bus(hose, bus), devfn, cap); | ||
| 552 | } | ||
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 9e8902fa14c7..ba949a2c93ac 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c | |||
| @@ -43,334 +43,6 @@ unsigned long pci_probe_only = 1; | |||
| 43 | unsigned long pci_io_base = ISA_IO_BASE; | 43 | unsigned long pci_io_base = ISA_IO_BASE; |
| 44 | EXPORT_SYMBOL(pci_io_base); | 44 | EXPORT_SYMBOL(pci_io_base); |
| 45 | 45 | ||
| 46 | static u32 get_int_prop(struct device_node *np, const char *name, u32 def) | ||
| 47 | { | ||
| 48 | const u32 *prop; | ||
| 49 | int len; | ||
| 50 | |||
| 51 | prop = of_get_property(np, name, &len); | ||
| 52 | if (prop && len >= 4) | ||
| 53 | return *prop; | ||
| 54 | return def; | ||
| 55 | } | ||
| 56 | |||
| 57 | static unsigned int pci_parse_of_flags(u32 addr0, int bridge) | ||
| 58 | { | ||
| 59 | unsigned int flags = 0; | ||
| 60 | |||
| 61 | if (addr0 & 0x02000000) { | ||
| 62 | flags = IORESOURCE_MEM | PCI_BASE_ADDRESS_SPACE_MEMORY; | ||
| 63 | flags |= (addr0 >> 22) & PCI_BASE_ADDRESS_MEM_TYPE_64; | ||
| 64 | flags |= (addr0 >> 28) & PCI_BASE_ADDRESS_MEM_TYPE_1M; | ||
| 65 | if (addr0 & 0x40000000) | ||
| 66 | flags |= IORESOURCE_PREFETCH | ||
| 67 | | PCI_BASE_ADDRESS_MEM_PREFETCH; | ||
| 68 | /* Note: We don't know whether the ROM has been left enabled | ||
| 69 | * by the firmware or not. We mark it as disabled (ie, we do | ||
| 70 | * not set the IORESOURCE_ROM_ENABLE flag) for now rather than | ||
| 71 | * do a config space read, it will be force-enabled if needed | ||
| 72 | */ | ||
| 73 | if (!bridge && (addr0 & 0xff) == 0x30) | ||
| 74 | flags |= IORESOURCE_READONLY; | ||
| 75 | } else if (addr0 & 0x01000000) | ||
| 76 | flags = IORESOURCE_IO | PCI_BASE_ADDRESS_SPACE_IO; | ||
| 77 | if (flags) | ||
| 78 | flags |= IORESOURCE_SIZEALIGN; | ||
| 79 | return flags; | ||
| 80 | } | ||
| 81 | |||
| 82 | |||
| 83 | static void pci_parse_of_addrs(struct device_node *node, struct pci_dev *dev) | ||
| 84 | { | ||
| 85 | u64 base, size; | ||
| 86 | unsigned int flags; | ||
| 87 | struct resource *res; | ||
| 88 | const u32 *addrs; | ||
| 89 | u32 i; | ||
| 90 | int proplen; | ||
| 91 | |||
| 92 | addrs = of_get_property(node, "assigned-addresses", &proplen); | ||
| 93 | if (!addrs) | ||
| 94 | return; | ||
| 95 | pr_debug(" parse addresses (%d bytes) @ %p\n", proplen, addrs); | ||
| 96 | for (; proplen >= 20; proplen -= 20, addrs += 5) { | ||
| 97 | flags = pci_parse_of_flags(addrs[0], 0); | ||
| 98 | if (!flags) | ||
| 99 | continue; | ||
| 100 | base = of_read_number(&addrs[1], 2); | ||
| 101 | size = of_read_number(&addrs[3], 2); | ||
| 102 | if (!size) | ||
| 103 | continue; | ||
| 104 | i = addrs[0] & 0xff; | ||
| 105 | pr_debug(" base: %llx, size: %llx, i: %x\n", | ||
| 106 | (unsigned long long)base, | ||
| 107 | (unsigned long long)size, i); | ||
| 108 | |||
| 109 | if (PCI_BASE_ADDRESS_0 <= i && i <= PCI_BASE_ADDRESS_5) { | ||
| 110 | res = &dev->resource[(i - PCI_BASE_ADDRESS_0) >> 2]; | ||
| 111 | } else if (i == dev->rom_base_reg) { | ||
| 112 | res = &dev->resource[PCI_ROM_RESOURCE]; | ||
| 113 | flags |= IORESOURCE_READONLY | IORESOURCE_CACHEABLE; | ||
| 114 | } else { | ||
| 115 | printk(KERN_ERR "PCI: bad cfg reg num 0x%x\n", i); | ||
| 116 | continue; | ||
| 117 | } | ||
| 118 | res->start = base; | ||
| 119 | res->end = base + size - 1; | ||
| 120 | res->flags = flags; | ||
| 121 | res->name = pci_name(dev); | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | struct pci_dev *of_create_pci_dev(struct device_node *node, | ||
| 126 | struct pci_bus *bus, int devfn) | ||
| 127 | { | ||
| 128 | struct pci_dev *dev; | ||
| 129 | const char *type; | ||
| 130 | |||
| 131 | dev = alloc_pci_dev(); | ||
| 132 | if (!dev) | ||
| 133 | return NULL; | ||
| 134 | type = of_get_property(node, "device_type", NULL); | ||
| 135 | if (type == NULL) | ||
| 136 | type = ""; | ||
| 137 | |||
| 138 | pr_debug(" create device, devfn: %x, type: %s\n", devfn, type); | ||
| 139 | |||
| 140 | dev->bus = bus; | ||
| 141 | dev->sysdata = node; | ||
| 142 | dev->dev.parent = bus->bridge; | ||
| 143 | dev->dev.bus = &pci_bus_type; | ||
| 144 | dev->devfn = devfn; | ||
| 145 | dev->multifunction = 0; /* maybe a lie? */ | ||
| 146 | |||
| 147 | dev->vendor = get_int_prop(node, "vendor-id", 0xffff); | ||
| 148 | dev->device = get_int_prop(node, "device-id", 0xffff); | ||
| 149 | dev->subsystem_vendor = get_int_prop(node, "subsystem-vendor-id", 0); | ||
| 150 | dev->subsystem_device = get_int_prop(node, "subsystem-id", 0); | ||
| 151 | |||
| 152 | dev->cfg_size = pci_cfg_space_size(dev); | ||
| 153 | |||
| 154 | dev_set_name(&dev->dev, "%04x:%02x:%02x.%d", pci_domain_nr(bus), | ||
| 155 | dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn)); | ||
| 156 | dev->class = get_int_prop(node, "class-code", 0); | ||
| 157 | dev->revision = get_int_prop(node, "revision-id", 0); | ||
| 158 | |||
| 159 | pr_debug(" class: 0x%x\n", dev->class); | ||
| 160 | pr_debug(" revision: 0x%x\n", dev->revision); | ||
| 161 | |||
| 162 | dev->current_state = 4; /* unknown power state */ | ||
| 163 | dev->error_state = pci_channel_io_normal; | ||
| 164 | dev->dma_mask = 0xffffffff; | ||
| 165 | |||
| 166 | if (!strcmp(type, "pci") || !strcmp(type, "pciex")) { | ||
| 167 | /* a PCI-PCI bridge */ | ||
| 168 | dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; | ||
| 169 | dev->rom_base_reg = PCI_ROM_ADDRESS1; | ||
| 170 | } else if (!strcmp(type, "cardbus")) { | ||
| 171 | dev->hdr_type = PCI_HEADER_TYPE_CARDBUS; | ||
| 172 | } else { | ||
| 173 | dev->hdr_type = PCI_HEADER_TYPE_NORMAL; | ||
| 174 | dev->rom_base_reg = PCI_ROM_ADDRESS; | ||
| 175 | /* Maybe do a default OF mapping here */ | ||
| 176 | dev->irq = NO_IRQ; | ||
| 177 | } | ||
| 178 | |||
| 179 | pci_parse_of_addrs(node, dev); | ||
| 180 | |||
| 181 | pr_debug(" adding to system ...\n"); | ||
| 182 | |||
| 183 | pci_device_add(dev, bus); | ||
| 184 | |||
| 185 | return dev; | ||
| 186 | } | ||
| 187 | EXPORT_SYMBOL(of_create_pci_dev); | ||
| 188 | |||
| 189 | static void __devinit __of_scan_bus(struct device_node *node, | ||
| 190 | struct pci_bus *bus, int rescan_existing) | ||
| 191 | { | ||
| 192 | struct device_node *child; | ||
| 193 | const u32 *reg; | ||
| 194 | int reglen, devfn; | ||
| 195 | struct pci_dev *dev; | ||
| 196 | |||
| 197 | pr_debug("of_scan_bus(%s) bus no %d... \n", | ||
| 198 | node->full_name, bus->number); | ||
| 199 | |||
| 200 | /* Scan direct children */ | ||
| 201 | for_each_child_of_node(node, child) { | ||
| 202 | pr_debug(" * %s\n", child->full_name); | ||
| 203 | reg = of_get_property(child, "reg", ®len); | ||
| 204 | if (reg == NULL || reglen < 20) | ||
| 205 | continue; | ||
| 206 | devfn = (reg[0] >> 8) & 0xff; | ||
| 207 | |||
| 208 | /* create a new pci_dev for this device */ | ||
| 209 | dev = of_create_pci_dev(child, bus, devfn); | ||
| 210 | if (!dev) | ||
| 211 | continue; | ||
| 212 | pr_debug(" dev header type: %x\n", dev->hdr_type); | ||
| 213 | } | ||
| 214 | |||
| 215 | /* Apply all fixups necessary. We don't fixup the bus "self" | ||
| 216 | * for an existing bridge that is being rescanned | ||
| 217 | */ | ||
| 218 | if (!rescan_existing) | ||
| 219 | pcibios_setup_bus_self(bus); | ||
| 220 | pcibios_setup_bus_devices(bus); | ||
| 221 | |||
| 222 | /* Now scan child busses */ | ||
| 223 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
| 224 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || | ||
| 225 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { | ||
| 226 | struct device_node *child = pci_device_to_OF_node(dev); | ||
| 227 | if (dev) | ||
| 228 | of_scan_pci_bridge(child, dev); | ||
| 229 | } | ||
| 230 | } | ||
| 231 | } | ||
| 232 | |||
| 233 | void __devinit of_scan_bus(struct device_node *node, | ||
| 234 | struct pci_bus *bus) | ||
| 235 | { | ||
| 236 | __of_scan_bus(node, bus, 0); | ||
| 237 | } | ||
| 238 | EXPORT_SYMBOL_GPL(of_scan_bus); | ||
| 239 | |||
| 240 | void __devinit of_rescan_bus(struct device_node *node, | ||
| 241 | struct pci_bus *bus) | ||
| 242 | { | ||
| 243 | __of_scan_bus(node, bus, 1); | ||
| 244 | } | ||
| 245 | EXPORT_SYMBOL_GPL(of_rescan_bus); | ||
| 246 | |||
| 247 | void __devinit of_scan_pci_bridge(struct device_node *node, | ||
| 248 | struct pci_dev *dev) | ||
| 249 | { | ||
| 250 | struct pci_bus *bus; | ||
| 251 | const u32 *busrange, *ranges; | ||
| 252 | int len, i, mode; | ||
| 253 | struct resource *res; | ||
| 254 | unsigned int flags; | ||
| 255 | u64 size; | ||
| 256 | |||
| 257 | pr_debug("of_scan_pci_bridge(%s)\n", node->full_name); | ||
| 258 | |||
| 259 | /* parse bus-range property */ | ||
| 260 | busrange = of_get_property(node, "bus-range", &len); | ||
| 261 | if (busrange == NULL || len != 8) { | ||
| 262 | printk(KERN_DEBUG "Can't get bus-range for PCI-PCI bridge %s\n", | ||
| 263 | node->full_name); | ||
| 264 | return; | ||
| 265 | } | ||
| 266 | ranges = of_get_property(node, "ranges", &len); | ||
| 267 | if (ranges == NULL) { | ||
| 268 | printk(KERN_DEBUG "Can't get ranges for PCI-PCI bridge %s\n", | ||
| 269 | node->full_name); | ||
| 270 | return; | ||
| 271 | } | ||
| 272 | |||
| 273 | bus = pci_add_new_bus(dev->bus, dev, busrange[0]); | ||
| 274 | if (!bus) { | ||
| 275 | printk(KERN_ERR "Failed to create pci bus for %s\n", | ||
| 276 | node->full_name); | ||
| 277 | return; | ||
| 278 | } | ||
| 279 | |||
| 280 | bus->primary = dev->bus->number; | ||
| 281 | bus->subordinate = busrange[1]; | ||
| 282 | bus->bridge_ctl = 0; | ||
| 283 | bus->sysdata = node; | ||
| 284 | |||
| 285 | /* parse ranges property */ | ||
| 286 | /* PCI #address-cells == 3 and #size-cells == 2 always */ | ||
| 287 | res = &dev->resource[PCI_BRIDGE_RESOURCES]; | ||
| 288 | for (i = 0; i < PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES; ++i) { | ||
| 289 | res->flags = 0; | ||
| 290 | bus->resource[i] = res; | ||
| 291 | ++res; | ||
| 292 | } | ||
| 293 | i = 1; | ||
| 294 | for (; len >= 32; len -= 32, ranges += 8) { | ||
| 295 | flags = pci_parse_of_flags(ranges[0], 1); | ||
| 296 | size = of_read_number(&ranges[6], 2); | ||
| 297 | if (flags == 0 || size == 0) | ||
| 298 | continue; | ||
| 299 | if (flags & IORESOURCE_IO) { | ||
| 300 | res = bus->resource[0]; | ||
| 301 | if (res->flags) { | ||
| 302 | printk(KERN_ERR "PCI: ignoring extra I/O range" | ||
| 303 | " for bridge %s\n", node->full_name); | ||
| 304 | continue; | ||
| 305 | } | ||
| 306 | } else { | ||
| 307 | if (i >= PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES) { | ||
| 308 | printk(KERN_ERR "PCI: too many memory ranges" | ||
| 309 | " for bridge %s\n", node->full_name); | ||
| 310 | continue; | ||
| 311 | } | ||
| 312 | res = bus->resource[i]; | ||
| 313 | ++i; | ||
| 314 | } | ||
| 315 | res->start = of_read_number(&ranges[1], 2); | ||
| 316 | res->end = res->start + size - 1; | ||
| 317 | res->flags = flags; | ||
| 318 | } | ||
| 319 | sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus), | ||
| 320 | bus->number); | ||
| 321 | pr_debug(" bus name: %s\n", bus->name); | ||
| 322 | |||
| 323 | mode = PCI_PROBE_NORMAL; | ||
| 324 | if (ppc_md.pci_probe_mode) | ||
| 325 | mode = ppc_md.pci_probe_mode(bus); | ||
| 326 | pr_debug(" probe mode: %d\n", mode); | ||
| 327 | |||
| 328 | if (mode == PCI_PROBE_DEVTREE) | ||
| 329 | of_scan_bus(node, bus); | ||
| 330 | else if (mode == PCI_PROBE_NORMAL) | ||
| 331 | pci_scan_child_bus(bus); | ||
| 332 | } | ||
| 333 | EXPORT_SYMBOL(of_scan_pci_bridge); | ||
| 334 | |||
| 335 | void __devinit scan_phb(struct pci_controller *hose) | ||
| 336 | { | ||
| 337 | struct pci_bus *bus; | ||
| 338 | struct device_node *node = hose->dn; | ||
| 339 | int mode; | ||
| 340 | |||
| 341 | pr_debug("PCI: Scanning PHB %s\n", | ||
| 342 | node ? node->full_name : "<NO NAME>"); | ||
| 343 | |||
| 344 | /* Create an empty bus for the toplevel */ | ||
| 345 | bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, node); | ||
| 346 | if (bus == NULL) { | ||
| 347 | printk(KERN_ERR "Failed to create bus for PCI domain %04x\n", | ||
| 348 | hose->global_number); | ||
| 349 | return; | ||
| 350 | } | ||
| 351 | bus->secondary = hose->first_busno; | ||
| 352 | hose->bus = bus; | ||
| 353 | |||
| 354 | /* Get some IO space for the new PHB */ | ||
| 355 | pcibios_map_io_space(bus); | ||
| 356 | |||
| 357 | /* Wire up PHB bus resources */ | ||
| 358 | pcibios_setup_phb_resources(hose); | ||
| 359 | |||
| 360 | /* Get probe mode and perform scan */ | ||
| 361 | mode = PCI_PROBE_NORMAL; | ||
| 362 | if (node && ppc_md.pci_probe_mode) | ||
| 363 | mode = ppc_md.pci_probe_mode(bus); | ||
| 364 | pr_debug(" probe mode: %d\n", mode); | ||
| 365 | if (mode == PCI_PROBE_DEVTREE) { | ||
| 366 | bus->subordinate = hose->last_busno; | ||
| 367 | of_scan_bus(node, bus); | ||
| 368 | } | ||
| 369 | |||
| 370 | if (mode == PCI_PROBE_NORMAL) | ||
| 371 | hose->last_busno = bus->subordinate = pci_scan_child_bus(bus); | ||
| 372 | } | ||
| 373 | |||
| 374 | static int __init pcibios_init(void) | 46 | static int __init pcibios_init(void) |
| 375 | { | 47 | { |
| 376 | struct pci_controller *hose, *tmp; | 48 | struct pci_controller *hose, *tmp; |
| @@ -392,7 +64,7 @@ static int __init pcibios_init(void) | |||
| 392 | 64 | ||
| 393 | /* Scan all of the recorded PCI controllers. */ | 65 | /* Scan all of the recorded PCI controllers. */ |
| 394 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { | 66 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { |
| 395 | scan_phb(hose); | 67 | pcibios_scan_phb(hose, hose->dn); |
| 396 | pci_bus_add_devices(hose->bus); | 68 | pci_bus_add_devices(hose->bus); |
| 397 | } | 69 | } |
| 398 | 70 | ||
| @@ -526,6 +198,11 @@ int __devinit pcibios_map_io_space(struct pci_bus *bus) | |||
| 526 | } | 198 | } |
| 527 | EXPORT_SYMBOL_GPL(pcibios_map_io_space); | 199 | EXPORT_SYMBOL_GPL(pcibios_map_io_space); |
| 528 | 200 | ||
| 201 | void __devinit pcibios_setup_phb_io_space(struct pci_controller *hose) | ||
| 202 | { | ||
| 203 | pcibios_map_io_space(hose->bus); | ||
| 204 | } | ||
| 205 | |||
| 529 | #define IOBASE_BRIDGE_NUMBER 0 | 206 | #define IOBASE_BRIDGE_NUMBER 0 |
| 530 | #define IOBASE_MEMORY 1 | 207 | #define IOBASE_MEMORY 1 |
| 531 | #define IOBASE_IO 2 | 208 | #define IOBASE_IO 2 |
diff --git a/arch/powerpc/kernel/pci_of_scan.c b/arch/powerpc/kernel/pci_of_scan.c new file mode 100644 index 000000000000..72c31bcb7aa4 --- /dev/null +++ b/arch/powerpc/kernel/pci_of_scan.c | |||
| @@ -0,0 +1,358 @@ | |||
| 1 | /* | ||
| 2 | * Helper routines to scan the device tree for PCI devices and busses | ||
| 3 | * | ||
| 4 | * Migrated out of PowerPC architecture pci_64.c file by Grant Likely | ||
| 5 | * <grant.likely@secretlab.ca> so that these routines are available for | ||
| 6 | * 32 bit also. | ||
| 7 | * | ||
| 8 | * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM | ||
| 9 | * Rework, based on alpha PCI code. | ||
| 10 | * Copyright (c) 2009 Secret Lab Technologies Ltd. | ||
| 11 | * | ||
| 12 | * This program is free software; you can redistribute it and/or | ||
| 13 | * modify it under the terms of the GNU General Public License | ||
| 14 | * version 2 as published by the Free Software Foundation. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/pci.h> | ||
| 18 | #include <asm/pci-bridge.h> | ||
| 19 | #include <asm/prom.h> | ||
| 20 | |||
| 21 | /** | ||
| 22 | * get_int_prop - Decode a u32 from a device tree property | ||
| 23 | */ | ||
| 24 | static u32 get_int_prop(struct device_node *np, const char *name, u32 def) | ||
| 25 | { | ||
| 26 | const u32 *prop; | ||
| 27 | int len; | ||
| 28 | |||
| 29 | prop = of_get_property(np, name, &len); | ||
| 30 | if (prop && len >= 4) | ||
| 31 | return *prop; | ||
| 32 | return def; | ||
| 33 | } | ||
| 34 | |||
| 35 | /** | ||
| 36 | * pci_parse_of_flags - Parse the flags cell of a device tree PCI address | ||
| 37 | * @addr0: value of 1st cell of a device tree PCI address. | ||
| 38 | * @bridge: Set this flag if the address is from a bridge 'ranges' property | ||
| 39 | */ | ||
| 40 | unsigned int pci_parse_of_flags(u32 addr0, int bridge) | ||
| 41 | { | ||
| 42 | unsigned int flags = 0; | ||
| 43 | |||
| 44 | if (addr0 & 0x02000000) { | ||
| 45 | flags = IORESOURCE_MEM | PCI_BASE_ADDRESS_SPACE_MEMORY; | ||
| 46 | flags |= (addr0 >> 22) & PCI_BASE_ADDRESS_MEM_TYPE_64; | ||
| 47 | flags |= (addr0 >> 28) & PCI_BASE_ADDRESS_MEM_TYPE_1M; | ||
| 48 | if (addr0 & 0x40000000) | ||
| 49 | flags |= IORESOURCE_PREFETCH | ||
| 50 | | PCI_BASE_ADDRESS_MEM_PREFETCH; | ||
| 51 | /* Note: We don't know whether the ROM has been left enabled | ||
| 52 | * by the firmware or not. We mark it as disabled (ie, we do | ||
| 53 | * not set the IORESOURCE_ROM_ENABLE flag) for now rather than | ||
| 54 | * do a config space read, it will be force-enabled if needed | ||
| 55 | */ | ||
| 56 | if (!bridge && (addr0 & 0xff) == 0x30) | ||
| 57 | flags |= IORESOURCE_READONLY; | ||
| 58 | } else if (addr0 & 0x01000000) | ||
| 59 | flags = IORESOURCE_IO | PCI_BASE_ADDRESS_SPACE_IO; | ||
| 60 | if (flags) | ||
| 61 | flags |= IORESOURCE_SIZEALIGN; | ||
| 62 | return flags; | ||
| 63 | } | ||
| 64 | |||
| 65 | /** | ||
| 66 | * of_pci_parse_addrs - Parse PCI addresses assigned in the device tree node | ||
| 67 | * @node: device tree node for the PCI device | ||
| 68 | * @dev: pci_dev structure for the device | ||
| 69 | * | ||
| 70 | * This function parses the 'assigned-addresses' property of a PCI devices' | ||
| 71 | * device tree node and writes them into the associated pci_dev structure. | ||
| 72 | */ | ||
| 73 | static void of_pci_parse_addrs(struct device_node *node, struct pci_dev *dev) | ||
| 74 | { | ||
| 75 | u64 base, size; | ||
| 76 | unsigned int flags; | ||
| 77 | struct resource *res; | ||
| 78 | const u32 *addrs; | ||
| 79 | u32 i; | ||
| 80 | int proplen; | ||
| 81 | |||
| 82 | addrs = of_get_property(node, "assigned-addresses", &proplen); | ||
| 83 | if (!addrs) | ||
| 84 | return; | ||
| 85 | pr_debug(" parse addresses (%d bytes) @ %p\n", proplen, addrs); | ||
| 86 | for (; proplen >= 20; proplen -= 20, addrs += 5) { | ||
| 87 | flags = pci_parse_of_flags(addrs[0], 0); | ||
| 88 | if (!flags) | ||
| 89 | continue; | ||
| 90 | base = of_read_number(&addrs[1], 2); | ||
| 91 | size = of_read_number(&addrs[3], 2); | ||
| 92 | if (!size) | ||
| 93 | continue; | ||
| 94 | i = addrs[0] & 0xff; | ||
| 95 | pr_debug(" base: %llx, size: %llx, i: %x\n", | ||
| 96 | (unsigned long long)base, | ||
| 97 | (unsigned long long)size, i); | ||
| 98 | |||
| 99 | if (PCI_BASE_ADDRESS_0 <= i && i <= PCI_BASE_ADDRESS_5) { | ||
| 100 | res = &dev->resource[(i - PCI_BASE_ADDRESS_0) >> 2]; | ||
| 101 | } else if (i == dev->rom_base_reg) { | ||
| 102 | res = &dev->resource[PCI_ROM_RESOURCE]; | ||
| 103 | flags |= IORESOURCE_READONLY | IORESOURCE_CACHEABLE; | ||
| 104 | } else { | ||
| 105 | printk(KERN_ERR "PCI: bad cfg reg num 0x%x\n", i); | ||
| 106 | continue; | ||
| 107 | } | ||
| 108 | res->start = base; | ||
| 109 | res->end = base + size - 1; | ||
| 110 | res->flags = flags; | ||
| 111 | res->name = pci_name(dev); | ||
| 112 | } | ||
| 113 | } | ||
| 114 | |||
| 115 | /** | ||
| 116 | * of_create_pci_dev - Given a device tree node on a pci bus, create a pci_dev | ||
| 117 | * @node: device tree node pointer | ||
| 118 | * @bus: bus the device is sitting on | ||
| 119 | * @devfn: PCI function number, extracted from device tree by caller. | ||
| 120 | */ | ||
| 121 | struct pci_dev *of_create_pci_dev(struct device_node *node, | ||
| 122 | struct pci_bus *bus, int devfn) | ||
| 123 | { | ||
| 124 | struct pci_dev *dev; | ||
| 125 | const char *type; | ||
| 126 | |||
| 127 | dev = alloc_pci_dev(); | ||
| 128 | if (!dev) | ||
| 129 | return NULL; | ||
| 130 | type = of_get_property(node, "device_type", NULL); | ||
| 131 | if (type == NULL) | ||
| 132 | type = ""; | ||
| 133 | |||
| 134 | pr_debug(" create device, devfn: %x, type: %s\n", devfn, type); | ||
| 135 | |||
| 136 | dev->bus = bus; | ||
| 137 | dev->sysdata = node; | ||
| 138 | dev->dev.parent = bus->bridge; | ||
| 139 | dev->dev.bus = &pci_bus_type; | ||
| 140 | dev->devfn = devfn; | ||
| 141 | dev->multifunction = 0; /* maybe a lie? */ | ||
| 142 | |||
| 143 | dev->vendor = get_int_prop(node, "vendor-id", 0xffff); | ||
| 144 | dev->device = get_int_prop(node, "device-id", 0xffff); | ||
| 145 | dev->subsystem_vendor = get_int_prop(node, "subsystem-vendor-id", 0); | ||
| 146 | dev->subsystem_device = get_int_prop(node, "subsystem-id", 0); | ||
| 147 | |||
| 148 | dev->cfg_size = pci_cfg_space_size(dev); | ||
| 149 | |||
| 150 | dev_set_name(&dev->dev, "%04x:%02x:%02x.%d", pci_domain_nr(bus), | ||
| 151 | dev->bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn)); | ||
| 152 | dev->class = get_int_prop(node, "class-code", 0); | ||
| 153 | dev->revision = get_int_prop(node, "revision-id", 0); | ||
| 154 | |||
| 155 | pr_debug(" class: 0x%x\n", dev->class); | ||
| 156 | pr_debug(" revision: 0x%x\n", dev->revision); | ||
| 157 | |||
| 158 | dev->current_state = 4; /* unknown power state */ | ||
| 159 | dev->error_state = pci_channel_io_normal; | ||
| 160 | dev->dma_mask = 0xffffffff; | ||
| 161 | |||
| 162 | if (!strcmp(type, "pci") || !strcmp(type, "pciex")) { | ||
| 163 | /* a PCI-PCI bridge */ | ||
| 164 | dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; | ||
| 165 | dev->rom_base_reg = PCI_ROM_ADDRESS1; | ||
| 166 | } else if (!strcmp(type, "cardbus")) { | ||
| 167 | dev->hdr_type = PCI_HEADER_TYPE_CARDBUS; | ||
| 168 | } else { | ||
| 169 | dev->hdr_type = PCI_HEADER_TYPE_NORMAL; | ||
| 170 | dev->rom_base_reg = PCI_ROM_ADDRESS; | ||
| 171 | /* Maybe do a default OF mapping here */ | ||
| 172 | dev->irq = NO_IRQ; | ||
| 173 | } | ||
| 174 | |||
| 175 | of_pci_parse_addrs(node, dev); | ||
| 176 | |||
| 177 | pr_debug(" adding to system ...\n"); | ||
| 178 | |||
| 179 | pci_device_add(dev, bus); | ||
| 180 | |||
| 181 | return dev; | ||
| 182 | } | ||
| 183 | EXPORT_SYMBOL(of_create_pci_dev); | ||
| 184 | |||
| 185 | /** | ||
| 186 | * of_scan_pci_bridge - Set up a PCI bridge and scan for child nodes | ||
| 187 | * @node: device tree node of bridge | ||
| 188 | * @dev: pci_dev structure for the bridge | ||
| 189 | * | ||
| 190 | * of_scan_bus() calls this routine for each PCI bridge that it finds, and | ||
| 191 | * this routine in turn call of_scan_bus() recusively to scan for more child | ||
| 192 | * devices. | ||
| 193 | */ | ||
| 194 | void __devinit of_scan_pci_bridge(struct device_node *node, | ||
| 195 | struct pci_dev *dev) | ||
| 196 | { | ||
| 197 | struct pci_bus *bus; | ||
| 198 | const u32 *busrange, *ranges; | ||
| 199 | int len, i, mode; | ||
| 200 | struct resource *res; | ||
| 201 | unsigned int flags; | ||
| 202 | u64 size; | ||
| 203 | |||
| 204 | pr_debug("of_scan_pci_bridge(%s)\n", node->full_name); | ||
| 205 | |||
| 206 | /* parse bus-range property */ | ||
| 207 | busrange = of_get_property(node, "bus-range", &len); | ||
| 208 | if (busrange == NULL || len != 8) { | ||
| 209 | printk(KERN_DEBUG "Can't get bus-range for PCI-PCI bridge %s\n", | ||
| 210 | node->full_name); | ||
| 211 | return; | ||
| 212 | } | ||
| 213 | ranges = of_get_property(node, "ranges", &len); | ||
| 214 | if (ranges == NULL) { | ||
| 215 | printk(KERN_DEBUG "Can't get ranges for PCI-PCI bridge %s\n", | ||
| 216 | node->full_name); | ||
| 217 | return; | ||
| 218 | } | ||
| 219 | |||
| 220 | bus = pci_add_new_bus(dev->bus, dev, busrange[0]); | ||
| 221 | if (!bus) { | ||
| 222 | printk(KERN_ERR "Failed to create pci bus for %s\n", | ||
| 223 | node->full_name); | ||
| 224 | return; | ||
| 225 | } | ||
| 226 | |||
| 227 | bus->primary = dev->bus->number; | ||
| 228 | bus->subordinate = busrange[1]; | ||
| 229 | bus->bridge_ctl = 0; | ||
| 230 | bus->sysdata = node; | ||
| 231 | |||
| 232 | /* parse ranges property */ | ||
| 233 | /* PCI #address-cells == 3 and #size-cells == 2 always */ | ||
| 234 | res = &dev->resource[PCI_BRIDGE_RESOURCES]; | ||
| 235 | for (i = 0; i < PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES; ++i) { | ||
| 236 | res->flags = 0; | ||
| 237 | bus->resource[i] = res; | ||
| 238 | ++res; | ||
| 239 | } | ||
| 240 | i = 1; | ||
| 241 | for (; len >= 32; len -= 32, ranges += 8) { | ||
| 242 | flags = pci_parse_of_flags(ranges[0], 1); | ||
| 243 | size = of_read_number(&ranges[6], 2); | ||
| 244 | if (flags == 0 || size == 0) | ||
| 245 | continue; | ||
| 246 | if (flags & IORESOURCE_IO) { | ||
| 247 | res = bus->resource[0]; | ||
| 248 | if (res->flags) { | ||
| 249 | printk(KERN_ERR "PCI: ignoring extra I/O range" | ||
| 250 | " for bridge %s\n", node->full_name); | ||
| 251 | continue; | ||
| 252 | } | ||
| 253 | } else { | ||
| 254 | if (i >= PCI_NUM_RESOURCES - PCI_BRIDGE_RESOURCES) { | ||
| 255 | printk(KERN_ERR "PCI: too many memory ranges" | ||
| 256 | " for bridge %s\n", node->full_name); | ||
| 257 | continue; | ||
| 258 | } | ||
| 259 | res = bus->resource[i]; | ||
| 260 | ++i; | ||
| 261 | } | ||
| 262 | res->start = of_read_number(&ranges[1], 2); | ||
| 263 | res->end = res->start + size - 1; | ||
| 264 | res->flags = flags; | ||
| 265 | } | ||
| 266 | sprintf(bus->name, "PCI Bus %04x:%02x", pci_domain_nr(bus), | ||
| 267 | bus->number); | ||
| 268 | pr_debug(" bus name: %s\n", bus->name); | ||
| 269 | |||
| 270 | mode = PCI_PROBE_NORMAL; | ||
| 271 | if (ppc_md.pci_probe_mode) | ||
| 272 | mode = ppc_md.pci_probe_mode(bus); | ||
| 273 | pr_debug(" probe mode: %d\n", mode); | ||
| 274 | |||
| 275 | if (mode == PCI_PROBE_DEVTREE) | ||
| 276 | of_scan_bus(node, bus); | ||
| 277 | else if (mode == PCI_PROBE_NORMAL) | ||
| 278 | pci_scan_child_bus(bus); | ||
| 279 | } | ||
| 280 | EXPORT_SYMBOL(of_scan_pci_bridge); | ||
| 281 | |||
| 282 | /** | ||
| 283 | * __of_scan_bus - given a PCI bus node, setup bus and scan for child devices | ||
| 284 | * @node: device tree node for the PCI bus | ||
| 285 | * @bus: pci_bus structure for the PCI bus | ||
| 286 | * @rescan_existing: Flag indicating bus has already been set up | ||
| 287 | */ | ||
| 288 | static void __devinit __of_scan_bus(struct device_node *node, | ||
| 289 | struct pci_bus *bus, int rescan_existing) | ||
| 290 | { | ||
| 291 | struct device_node *child; | ||
| 292 | const u32 *reg; | ||
| 293 | int reglen, devfn; | ||
| 294 | struct pci_dev *dev; | ||
| 295 | |||
| 296 | pr_debug("of_scan_bus(%s) bus no %d... \n", | ||
| 297 | node->full_name, bus->number); | ||
| 298 | |||
| 299 | /* Scan direct children */ | ||
| 300 | for_each_child_of_node(node, child) { | ||
| 301 | pr_debug(" * %s\n", child->full_name); | ||
| 302 | reg = of_get_property(child, "reg", ®len); | ||
| 303 | if (reg == NULL || reglen < 20) | ||
| 304 | continue; | ||
| 305 | devfn = (reg[0] >> 8) & 0xff; | ||
| 306 | |||
| 307 | /* create a new pci_dev for this device */ | ||
| 308 | dev = of_create_pci_dev(child, bus, devfn); | ||
| 309 | if (!dev) | ||
| 310 | continue; | ||
| 311 | pr_debug(" dev header type: %x\n", dev->hdr_type); | ||
| 312 | } | ||
| 313 | |||
| 314 | /* Apply all fixups necessary. We don't fixup the bus "self" | ||
| 315 | * for an existing bridge that is being rescanned | ||
| 316 | */ | ||
| 317 | if (!rescan_existing) | ||
| 318 | pcibios_setup_bus_self(bus); | ||
| 319 | pcibios_setup_bus_devices(bus); | ||
| 320 | |||
| 321 | /* Now scan child busses */ | ||
| 322 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
| 323 | if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE || | ||
| 324 | dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) { | ||
| 325 | struct device_node *child = pci_device_to_OF_node(dev); | ||
| 326 | if (dev) | ||
| 327 | of_scan_pci_bridge(child, dev); | ||
| 328 | } | ||
| 329 | } | ||
| 330 | } | ||
| 331 | |||
| 332 | /** | ||
| 333 | * of_scan_bus - given a PCI bus node, setup bus and scan for child devices | ||
| 334 | * @node: device tree node for the PCI bus | ||
| 335 | * @bus: pci_bus structure for the PCI bus | ||
| 336 | */ | ||
| 337 | void __devinit of_scan_bus(struct device_node *node, | ||
| 338 | struct pci_bus *bus) | ||
| 339 | { | ||
| 340 | __of_scan_bus(node, bus, 0); | ||
| 341 | } | ||
| 342 | EXPORT_SYMBOL_GPL(of_scan_bus); | ||
| 343 | |||
| 344 | /** | ||
| 345 | * of_rescan_bus - given a PCI bus node, scan for child devices | ||
| 346 | * @node: device tree node for the PCI bus | ||
| 347 | * @bus: pci_bus structure for the PCI bus | ||
| 348 | * | ||
| 349 | * Same as of_scan_bus, but for a pci_bus structure that has already been | ||
| 350 | * setup. | ||
| 351 | */ | ||
| 352 | void __devinit of_rescan_bus(struct device_node *node, | ||
| 353 | struct pci_bus *bus) | ||
| 354 | { | ||
| 355 | __of_scan_bus(node, bus, 1); | ||
| 356 | } | ||
| 357 | EXPORT_SYMBOL_GPL(of_rescan_bus); | ||
| 358 | |||
diff --git a/arch/powerpc/kernel/perf_counter.c b/arch/powerpc/kernel/perf_counter.c index 70e1f57f7dd8..7ceefaf3a7f5 100644 --- a/arch/powerpc/kernel/perf_counter.c +++ b/arch/powerpc/kernel/perf_counter.c | |||
| @@ -32,6 +32,9 @@ struct cpu_hw_counters { | |||
| 32 | unsigned long mmcr[3]; | 32 | unsigned long mmcr[3]; |
| 33 | struct perf_counter *limited_counter[MAX_LIMITED_HWCOUNTERS]; | 33 | struct perf_counter *limited_counter[MAX_LIMITED_HWCOUNTERS]; |
| 34 | u8 limited_hwidx[MAX_LIMITED_HWCOUNTERS]; | 34 | u8 limited_hwidx[MAX_LIMITED_HWCOUNTERS]; |
| 35 | u64 alternatives[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES]; | ||
| 36 | unsigned long amasks[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES]; | ||
| 37 | unsigned long avalues[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES]; | ||
| 35 | }; | 38 | }; |
| 36 | DEFINE_PER_CPU(struct cpu_hw_counters, cpu_hw_counters); | 39 | DEFINE_PER_CPU(struct cpu_hw_counters, cpu_hw_counters); |
| 37 | 40 | ||
| @@ -62,7 +65,6 @@ static inline unsigned long perf_ip_adjust(struct pt_regs *regs) | |||
| 62 | { | 65 | { |
| 63 | return 0; | 66 | return 0; |
| 64 | } | 67 | } |
| 65 | static inline void perf_set_pmu_inuse(int inuse) { } | ||
| 66 | static inline void perf_get_data_addr(struct pt_regs *regs, u64 *addrp) { } | 68 | static inline void perf_get_data_addr(struct pt_regs *regs, u64 *addrp) { } |
| 67 | static inline u32 perf_get_misc_flags(struct pt_regs *regs) | 69 | static inline u32 perf_get_misc_flags(struct pt_regs *regs) |
| 68 | { | 70 | { |
| @@ -93,11 +95,6 @@ static inline unsigned long perf_ip_adjust(struct pt_regs *regs) | |||
| 93 | return 0; | 95 | return 0; |
| 94 | } | 96 | } |
| 95 | 97 | ||
| 96 | static inline void perf_set_pmu_inuse(int inuse) | ||
| 97 | { | ||
| 98 | get_lppaca()->pmcregs_in_use = inuse; | ||
| 99 | } | ||
| 100 | |||
| 101 | /* | 98 | /* |
| 102 | * The user wants a data address recorded. | 99 | * The user wants a data address recorded. |
| 103 | * If we're not doing instruction sampling, give them the SDAR | 100 | * If we're not doing instruction sampling, give them the SDAR |
| @@ -245,13 +242,11 @@ static void write_pmc(int idx, unsigned long val) | |||
| 245 | * and see if any combination of alternative codes is feasible. | 242 | * and see if any combination of alternative codes is feasible. |
| 246 | * The feasible set is returned in event[]. | 243 | * The feasible set is returned in event[]. |
| 247 | */ | 244 | */ |
| 248 | static int power_check_constraints(u64 event[], unsigned int cflags[], | 245 | static int power_check_constraints(struct cpu_hw_counters *cpuhw, |
| 246 | u64 event[], unsigned int cflags[], | ||
| 249 | int n_ev) | 247 | int n_ev) |
| 250 | { | 248 | { |
| 251 | unsigned long mask, value, nv; | 249 | unsigned long mask, value, nv; |
| 252 | u64 alternatives[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES]; | ||
| 253 | unsigned long amasks[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES]; | ||
| 254 | unsigned long avalues[MAX_HWCOUNTERS][MAX_EVENT_ALTERNATIVES]; | ||
| 255 | unsigned long smasks[MAX_HWCOUNTERS], svalues[MAX_HWCOUNTERS]; | 250 | unsigned long smasks[MAX_HWCOUNTERS], svalues[MAX_HWCOUNTERS]; |
| 256 | int n_alt[MAX_HWCOUNTERS], choice[MAX_HWCOUNTERS]; | 251 | int n_alt[MAX_HWCOUNTERS], choice[MAX_HWCOUNTERS]; |
| 257 | int i, j; | 252 | int i, j; |
| @@ -266,21 +261,23 @@ static int power_check_constraints(u64 event[], unsigned int cflags[], | |||
| 266 | if ((cflags[i] & PPMU_LIMITED_PMC_REQD) | 261 | if ((cflags[i] & PPMU_LIMITED_PMC_REQD) |
| 267 | && !ppmu->limited_pmc_event(event[i])) { | 262 | && !ppmu->limited_pmc_event(event[i])) { |
| 268 | ppmu->get_alternatives(event[i], cflags[i], | 263 | ppmu->get_alternatives(event[i], cflags[i], |
| 269 | alternatives[i]); | 264 | cpuhw->alternatives[i]); |
| 270 | event[i] = alternatives[i][0]; | 265 | event[i] = cpuhw->alternatives[i][0]; |
| 271 | } | 266 | } |
| 272 | if (ppmu->get_constraint(event[i], &amasks[i][0], | 267 | if (ppmu->get_constraint(event[i], &cpuhw->amasks[i][0], |
| 273 | &avalues[i][0])) | 268 | &cpuhw->avalues[i][0])) |
| 274 | return -1; | 269 | return -1; |
| 275 | } | 270 | } |
| 276 | value = mask = 0; | 271 | value = mask = 0; |
| 277 | for (i = 0; i < n_ev; ++i) { | 272 | for (i = 0; i < n_ev; ++i) { |
| 278 | nv = (value | avalues[i][0]) + (value & avalues[i][0] & addf); | 273 | nv = (value | cpuhw->avalues[i][0]) + |
| 274 | (value & cpuhw->avalues[i][0] & addf); | ||
| 279 | if ((((nv + tadd) ^ value) & mask) != 0 || | 275 | if ((((nv + tadd) ^ value) & mask) != 0 || |
| 280 | (((nv + tadd) ^ avalues[i][0]) & amasks[i][0]) != 0) | 276 | (((nv + tadd) ^ cpuhw->avalues[i][0]) & |
| 277 | cpuhw->amasks[i][0]) != 0) | ||
| 281 | break; | 278 | break; |
| 282 | value = nv; | 279 | value = nv; |
| 283 | mask |= amasks[i][0]; | 280 | mask |= cpuhw->amasks[i][0]; |
| 284 | } | 281 | } |
| 285 | if (i == n_ev) | 282 | if (i == n_ev) |
| 286 | return 0; /* all OK */ | 283 | return 0; /* all OK */ |
| @@ -291,10 +288,11 @@ static int power_check_constraints(u64 event[], unsigned int cflags[], | |||
| 291 | for (i = 0; i < n_ev; ++i) { | 288 | for (i = 0; i < n_ev; ++i) { |
| 292 | choice[i] = 0; | 289 | choice[i] = 0; |
| 293 | n_alt[i] = ppmu->get_alternatives(event[i], cflags[i], | 290 | n_alt[i] = ppmu->get_alternatives(event[i], cflags[i], |
| 294 | alternatives[i]); | 291 | cpuhw->alternatives[i]); |
| 295 | for (j = 1; j < n_alt[i]; ++j) | 292 | for (j = 1; j < n_alt[i]; ++j) |
| 296 | ppmu->get_constraint(alternatives[i][j], | 293 | ppmu->get_constraint(cpuhw->alternatives[i][j], |
| 297 | &amasks[i][j], &avalues[i][j]); | 294 | &cpuhw->amasks[i][j], |
| 295 | &cpuhw->avalues[i][j]); | ||
| 298 | } | 296 | } |
| 299 | 297 | ||
| 300 | /* enumerate all possibilities and see if any will work */ | 298 | /* enumerate all possibilities and see if any will work */ |
| @@ -313,11 +311,11 @@ static int power_check_constraints(u64 event[], unsigned int cflags[], | |||
| 313 | * where k > j, will satisfy the constraints. | 311 | * where k > j, will satisfy the constraints. |
| 314 | */ | 312 | */ |
| 315 | while (++j < n_alt[i]) { | 313 | while (++j < n_alt[i]) { |
| 316 | nv = (value | avalues[i][j]) + | 314 | nv = (value | cpuhw->avalues[i][j]) + |
| 317 | (value & avalues[i][j] & addf); | 315 | (value & cpuhw->avalues[i][j] & addf); |
| 318 | if ((((nv + tadd) ^ value) & mask) == 0 && | 316 | if ((((nv + tadd) ^ value) & mask) == 0 && |
| 319 | (((nv + tadd) ^ avalues[i][j]) | 317 | (((nv + tadd) ^ cpuhw->avalues[i][j]) |
| 320 | & amasks[i][j]) == 0) | 318 | & cpuhw->amasks[i][j]) == 0) |
| 321 | break; | 319 | break; |
| 322 | } | 320 | } |
| 323 | if (j >= n_alt[i]) { | 321 | if (j >= n_alt[i]) { |
| @@ -339,7 +337,7 @@ static int power_check_constraints(u64 event[], unsigned int cflags[], | |||
| 339 | svalues[i] = value; | 337 | svalues[i] = value; |
| 340 | smasks[i] = mask; | 338 | smasks[i] = mask; |
| 341 | value = nv; | 339 | value = nv; |
| 342 | mask |= amasks[i][j]; | 340 | mask |= cpuhw->amasks[i][j]; |
| 343 | ++i; | 341 | ++i; |
| 344 | j = -1; | 342 | j = -1; |
| 345 | } | 343 | } |
| @@ -347,7 +345,7 @@ static int power_check_constraints(u64 event[], unsigned int cflags[], | |||
| 347 | 345 | ||
| 348 | /* OK, we have a feasible combination, tell the caller the solution */ | 346 | /* OK, we have a feasible combination, tell the caller the solution */ |
| 349 | for (i = 0; i < n_ev; ++i) | 347 | for (i = 0; i < n_ev; ++i) |
| 350 | event[i] = alternatives[i][choice[i]]; | 348 | event[i] = cpuhw->alternatives[i][choice[i]]; |
| 351 | return 0; | 349 | return 0; |
| 352 | } | 350 | } |
| 353 | 351 | ||
| @@ -531,8 +529,7 @@ void hw_perf_disable(void) | |||
| 531 | * Check if we ever enabled the PMU on this cpu. | 529 | * Check if we ever enabled the PMU on this cpu. |
| 532 | */ | 530 | */ |
| 533 | if (!cpuhw->pmcs_enabled) { | 531 | if (!cpuhw->pmcs_enabled) { |
| 534 | if (ppc_md.enable_pmcs) | 532 | ppc_enable_pmcs(); |
| 535 | ppc_md.enable_pmcs(); | ||
| 536 | cpuhw->pmcs_enabled = 1; | 533 | cpuhw->pmcs_enabled = 1; |
| 537 | } | 534 | } |
| 538 | 535 | ||
| @@ -594,7 +591,7 @@ void hw_perf_enable(void) | |||
| 594 | mtspr(SPRN_MMCRA, cpuhw->mmcr[2] & ~MMCRA_SAMPLE_ENABLE); | 591 | mtspr(SPRN_MMCRA, cpuhw->mmcr[2] & ~MMCRA_SAMPLE_ENABLE); |
| 595 | mtspr(SPRN_MMCR1, cpuhw->mmcr[1]); | 592 | mtspr(SPRN_MMCR1, cpuhw->mmcr[1]); |
| 596 | if (cpuhw->n_counters == 0) | 593 | if (cpuhw->n_counters == 0) |
| 597 | perf_set_pmu_inuse(0); | 594 | ppc_set_pmu_inuse(0); |
| 598 | goto out_enable; | 595 | goto out_enable; |
| 599 | } | 596 | } |
| 600 | 597 | ||
| @@ -627,7 +624,7 @@ void hw_perf_enable(void) | |||
| 627 | * bit set and set the hardware counters to their initial values. | 624 | * bit set and set the hardware counters to their initial values. |
| 628 | * Then unfreeze the counters. | 625 | * Then unfreeze the counters. |
| 629 | */ | 626 | */ |
| 630 | perf_set_pmu_inuse(1); | 627 | ppc_set_pmu_inuse(1); |
| 631 | mtspr(SPRN_MMCRA, cpuhw->mmcr[2] & ~MMCRA_SAMPLE_ENABLE); | 628 | mtspr(SPRN_MMCRA, cpuhw->mmcr[2] & ~MMCRA_SAMPLE_ENABLE); |
| 632 | mtspr(SPRN_MMCR1, cpuhw->mmcr[1]); | 629 | mtspr(SPRN_MMCR1, cpuhw->mmcr[1]); |
| 633 | mtspr(SPRN_MMCR0, (cpuhw->mmcr[0] & ~(MMCR0_PMC1CE | MMCR0_PMCjCE)) | 630 | mtspr(SPRN_MMCR0, (cpuhw->mmcr[0] & ~(MMCR0_PMC1CE | MMCR0_PMCjCE)) |
| @@ -752,7 +749,7 @@ int hw_perf_group_sched_in(struct perf_counter *group_leader, | |||
| 752 | return -EAGAIN; | 749 | return -EAGAIN; |
| 753 | if (check_excludes(cpuhw->counter, cpuhw->flags, n0, n)) | 750 | if (check_excludes(cpuhw->counter, cpuhw->flags, n0, n)) |
| 754 | return -EAGAIN; | 751 | return -EAGAIN; |
| 755 | i = power_check_constraints(cpuhw->events, cpuhw->flags, n + n0); | 752 | i = power_check_constraints(cpuhw, cpuhw->events, cpuhw->flags, n + n0); |
| 756 | if (i < 0) | 753 | if (i < 0) |
| 757 | return -EAGAIN; | 754 | return -EAGAIN; |
| 758 | cpuhw->n_counters = n0 + n; | 755 | cpuhw->n_counters = n0 + n; |
| @@ -807,7 +804,7 @@ static int power_pmu_enable(struct perf_counter *counter) | |||
| 807 | cpuhw->flags[n0] = counter->hw.counter_base; | 804 | cpuhw->flags[n0] = counter->hw.counter_base; |
| 808 | if (check_excludes(cpuhw->counter, cpuhw->flags, n0, 1)) | 805 | if (check_excludes(cpuhw->counter, cpuhw->flags, n0, 1)) |
| 809 | goto out; | 806 | goto out; |
| 810 | if (power_check_constraints(cpuhw->events, cpuhw->flags, n0 + 1)) | 807 | if (power_check_constraints(cpuhw, cpuhw->events, cpuhw->flags, n0 + 1)) |
| 811 | goto out; | 808 | goto out; |
| 812 | 809 | ||
| 813 | counter->hw.config = cpuhw->events[n0]; | 810 | counter->hw.config = cpuhw->events[n0]; |
| @@ -1012,6 +1009,7 @@ const struct pmu *hw_perf_counter_init(struct perf_counter *counter) | |||
| 1012 | unsigned int cflags[MAX_HWCOUNTERS]; | 1009 | unsigned int cflags[MAX_HWCOUNTERS]; |
| 1013 | int n; | 1010 | int n; |
| 1014 | int err; | 1011 | int err; |
| 1012 | struct cpu_hw_counters *cpuhw; | ||
| 1015 | 1013 | ||
| 1016 | if (!ppmu) | 1014 | if (!ppmu) |
| 1017 | return ERR_PTR(-ENXIO); | 1015 | return ERR_PTR(-ENXIO); |
| @@ -1090,7 +1088,11 @@ const struct pmu *hw_perf_counter_init(struct perf_counter *counter) | |||
| 1090 | cflags[n] = flags; | 1088 | cflags[n] = flags; |
| 1091 | if (check_excludes(ctrs, cflags, n, 1)) | 1089 | if (check_excludes(ctrs, cflags, n, 1)) |
| 1092 | return ERR_PTR(-EINVAL); | 1090 | return ERR_PTR(-EINVAL); |
| 1093 | if (power_check_constraints(events, cflags, n + 1)) | 1091 | |
| 1092 | cpuhw = &get_cpu_var(cpu_hw_counters); | ||
| 1093 | err = power_check_constraints(cpuhw, events, cflags, n + 1); | ||
| 1094 | put_cpu_var(cpu_hw_counters); | ||
| 1095 | if (err) | ||
| 1094 | return ERR_PTR(-EINVAL); | 1096 | return ERR_PTR(-EINVAL); |
| 1095 | 1097 | ||
| 1096 | counter->hw.config = events[n]; | 1098 | counter->hw.config = events[n]; |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 892a9f2e6d76..0a3216433051 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
| @@ -284,14 +284,13 @@ int set_dabr(unsigned long dabr) | |||
| 284 | return ppc_md.set_dabr(dabr); | 284 | return ppc_md.set_dabr(dabr); |
| 285 | 285 | ||
| 286 | /* XXX should we have a CPU_FTR_HAS_DABR ? */ | 286 | /* XXX should we have a CPU_FTR_HAS_DABR ? */ |
| 287 | #if defined(CONFIG_PPC64) || defined(CONFIG_6xx) | ||
| 288 | mtspr(SPRN_DABR, dabr); | ||
| 289 | #endif | ||
| 290 | |||
| 291 | #if defined(CONFIG_BOOKE) | 287 | #if defined(CONFIG_BOOKE) |
| 292 | mtspr(SPRN_DAC1, dabr); | 288 | mtspr(SPRN_DAC1, dabr); |
| 289 | #elif defined(CONFIG_PPC_BOOK3S) | ||
| 290 | mtspr(SPRN_DABR, dabr); | ||
| 293 | #endif | 291 | #endif |
| 294 | 292 | ||
| 293 | |||
| 295 | return 0; | 294 | return 0; |
| 296 | } | 295 | } |
| 297 | 296 | ||
| @@ -372,15 +371,16 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
| 372 | 371 | ||
| 373 | #endif /* CONFIG_SMP */ | 372 | #endif /* CONFIG_SMP */ |
| 374 | 373 | ||
| 375 | if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) | ||
| 376 | set_dabr(new->thread.dabr); | ||
| 377 | |||
| 378 | #if defined(CONFIG_BOOKE) | 374 | #if defined(CONFIG_BOOKE) |
| 379 | /* If new thread DAC (HW breakpoint) is the same then leave it */ | 375 | /* If new thread DAC (HW breakpoint) is the same then leave it */ |
| 380 | if (new->thread.dabr) | 376 | if (new->thread.dabr) |
| 381 | set_dabr(new->thread.dabr); | 377 | set_dabr(new->thread.dabr); |
| 378 | #else | ||
| 379 | if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) | ||
| 380 | set_dabr(new->thread.dabr); | ||
| 382 | #endif | 381 | #endif |
| 383 | 382 | ||
| 383 | |||
| 384 | new_thread = &new->thread; | 384 | new_thread = &new->thread; |
| 385 | old_thread = ¤t->thread; | 385 | old_thread = ¤t->thread; |
| 386 | 386 | ||
| @@ -664,6 +664,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
| 664 | sp_vsid |= SLB_VSID_KERNEL | llp; | 664 | sp_vsid |= SLB_VSID_KERNEL | llp; |
| 665 | p->thread.ksp_vsid = sp_vsid; | 665 | p->thread.ksp_vsid = sp_vsid; |
| 666 | } | 666 | } |
| 667 | #endif /* CONFIG_PPC_STD_MMU_64 */ | ||
| 667 | 668 | ||
| 668 | /* | 669 | /* |
| 669 | * The PPC64 ABI makes use of a TOC to contain function | 670 | * The PPC64 ABI makes use of a TOC to contain function |
| @@ -671,6 +672,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
| 671 | * to the TOC entry. The first entry is a pointer to the actual | 672 | * to the TOC entry. The first entry is a pointer to the actual |
| 672 | * function. | 673 | * function. |
| 673 | */ | 674 | */ |
| 675 | #ifdef CONFIG_PPC64 | ||
| 674 | kregs->nip = *((unsigned long *)ret_from_fork); | 676 | kregs->nip = *((unsigned long *)ret_from_fork); |
| 675 | #else | 677 | #else |
| 676 | kregs->nip = (unsigned long)ret_from_fork; | 678 | kregs->nip = (unsigned long)ret_from_fork; |
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index a538824616fd..864334b337a3 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
| @@ -190,6 +190,8 @@ static int __initdata of_platform; | |||
| 190 | 190 | ||
| 191 | static char __initdata prom_cmd_line[COMMAND_LINE_SIZE]; | 191 | static char __initdata prom_cmd_line[COMMAND_LINE_SIZE]; |
| 192 | 192 | ||
| 193 | static unsigned long __initdata prom_memory_limit; | ||
| 194 | |||
| 193 | static unsigned long __initdata alloc_top; | 195 | static unsigned long __initdata alloc_top; |
| 194 | static unsigned long __initdata alloc_top_high; | 196 | static unsigned long __initdata alloc_top_high; |
| 195 | static unsigned long __initdata alloc_bottom; | 197 | static unsigned long __initdata alloc_bottom; |
| @@ -484,6 +486,67 @@ static int __init prom_setprop(phandle node, const char *nodename, | |||
| 484 | return call_prom("interpret", 1, 1, (u32)(unsigned long) cmd); | 486 | return call_prom("interpret", 1, 1, (u32)(unsigned long) cmd); |
| 485 | } | 487 | } |
| 486 | 488 | ||
| 489 | /* We can't use the standard versions because of RELOC headaches. */ | ||
| 490 | #define isxdigit(c) (('0' <= (c) && (c) <= '9') \ | ||
| 491 | || ('a' <= (c) && (c) <= 'f') \ | ||
| 492 | || ('A' <= (c) && (c) <= 'F')) | ||
| 493 | |||
| 494 | #define isdigit(c) ('0' <= (c) && (c) <= '9') | ||
| 495 | #define islower(c) ('a' <= (c) && (c) <= 'z') | ||
| 496 | #define toupper(c) (islower(c) ? ((c) - 'a' + 'A') : (c)) | ||
| 497 | |||
| 498 | unsigned long prom_strtoul(const char *cp, const char **endp) | ||
| 499 | { | ||
| 500 | unsigned long result = 0, base = 10, value; | ||
| 501 | |||
| 502 | if (*cp == '0') { | ||
| 503 | base = 8; | ||
| 504 | cp++; | ||
| 505 | if (toupper(*cp) == 'X') { | ||
| 506 | cp++; | ||
| 507 | base = 16; | ||
| 508 | } | ||
| 509 | } | ||
| 510 | |||
| 511 | while (isxdigit(*cp) && | ||
| 512 | (value = isdigit(*cp) ? *cp - '0' : toupper(*cp) - 'A' + 10) < base) { | ||
| 513 | result = result * base + value; | ||
| 514 | cp++; | ||
| 515 | } | ||
| 516 | |||
| 517 | if (endp) | ||
| 518 | *endp = cp; | ||
| 519 | |||
| 520 | return result; | ||
| 521 | } | ||
| 522 | |||
| 523 | unsigned long prom_memparse(const char *ptr, const char **retptr) | ||
| 524 | { | ||
| 525 | unsigned long ret = prom_strtoul(ptr, retptr); | ||
| 526 | int shift = 0; | ||
| 527 | |||
| 528 | /* | ||
| 529 | * We can't use a switch here because GCC *may* generate a | ||
| 530 | * jump table which won't work, because we're not running at | ||
| 531 | * the address we're linked at. | ||
| 532 | */ | ||
| 533 | if ('G' == **retptr || 'g' == **retptr) | ||
| 534 | shift = 30; | ||
| 535 | |||
| 536 | if ('M' == **retptr || 'm' == **retptr) | ||
| 537 | shift = 20; | ||
| 538 | |||
| 539 | if ('K' == **retptr || 'k' == **retptr) | ||
| 540 | shift = 10; | ||
| 541 | |||
| 542 | if (shift) { | ||
| 543 | ret <<= shift; | ||
| 544 | (*retptr)++; | ||
| 545 | } | ||
| 546 | |||
| 547 | return ret; | ||
| 548 | } | ||
| 549 | |||
| 487 | /* | 550 | /* |
| 488 | * Early parsing of the command line passed to the kernel, used for | 551 | * Early parsing of the command line passed to the kernel, used for |
| 489 | * "mem=x" and the options that affect the iommu | 552 | * "mem=x" and the options that affect the iommu |
| @@ -491,9 +554,8 @@ static int __init prom_setprop(phandle node, const char *nodename, | |||
| 491 | static void __init early_cmdline_parse(void) | 554 | static void __init early_cmdline_parse(void) |
| 492 | { | 555 | { |
| 493 | struct prom_t *_prom = &RELOC(prom); | 556 | struct prom_t *_prom = &RELOC(prom); |
| 494 | #ifdef CONFIG_PPC64 | ||
| 495 | const char *opt; | 557 | const char *opt; |
| 496 | #endif | 558 | |
| 497 | char *p; | 559 | char *p; |
| 498 | int l = 0; | 560 | int l = 0; |
| 499 | 561 | ||
| @@ -521,6 +583,15 @@ static void __init early_cmdline_parse(void) | |||
| 521 | RELOC(prom_iommu_force_on) = 1; | 583 | RELOC(prom_iommu_force_on) = 1; |
| 522 | } | 584 | } |
| 523 | #endif | 585 | #endif |
| 586 | opt = strstr(RELOC(prom_cmd_line), RELOC("mem=")); | ||
| 587 | if (opt) { | ||
| 588 | opt += 4; | ||
| 589 | RELOC(prom_memory_limit) = prom_memparse(opt, (const char **)&opt); | ||
| 590 | #ifdef CONFIG_PPC64 | ||
| 591 | /* Align to 16 MB == size of ppc64 large page */ | ||
| 592 | RELOC(prom_memory_limit) = ALIGN(RELOC(prom_memory_limit), 0x1000000); | ||
| 593 | #endif | ||
| 594 | } | ||
| 524 | } | 595 | } |
| 525 | 596 | ||
| 526 | #ifdef CONFIG_PPC_PSERIES | 597 | #ifdef CONFIG_PPC_PSERIES |
| @@ -1027,6 +1098,29 @@ static void __init prom_init_mem(void) | |||
| 1027 | } | 1098 | } |
| 1028 | 1099 | ||
| 1029 | /* | 1100 | /* |
| 1101 | * If prom_memory_limit is set we reduce the upper limits *except* for | ||
| 1102 | * alloc_top_high. This must be the real top of RAM so we can put | ||
| 1103 | * TCE's up there. | ||
| 1104 | */ | ||
| 1105 | |||
| 1106 | RELOC(alloc_top_high) = RELOC(ram_top); | ||
| 1107 | |||
| 1108 | if (RELOC(prom_memory_limit)) { | ||
| 1109 | if (RELOC(prom_memory_limit) <= RELOC(alloc_bottom)) { | ||
| 1110 | prom_printf("Ignoring mem=%x <= alloc_bottom.\n", | ||
| 1111 | RELOC(prom_memory_limit)); | ||
| 1112 | RELOC(prom_memory_limit) = 0; | ||
| 1113 | } else if (RELOC(prom_memory_limit) >= RELOC(ram_top)) { | ||
| 1114 | prom_printf("Ignoring mem=%x >= ram_top.\n", | ||
| 1115 | RELOC(prom_memory_limit)); | ||
| 1116 | RELOC(prom_memory_limit) = 0; | ||
| 1117 | } else { | ||
| 1118 | RELOC(ram_top) = RELOC(prom_memory_limit); | ||
| 1119 | RELOC(rmo_top) = min(RELOC(rmo_top), RELOC(prom_memory_limit)); | ||
| 1120 | } | ||
| 1121 | } | ||
| 1122 | |||
| 1123 | /* | ||
| 1030 | * Setup our top alloc point, that is top of RMO or top of | 1124 | * Setup our top alloc point, that is top of RMO or top of |
| 1031 | * segment 0 when running non-LPAR. | 1125 | * segment 0 when running non-LPAR. |
| 1032 | * Some RS64 machines have buggy firmware where claims up at | 1126 | * Some RS64 machines have buggy firmware where claims up at |
| @@ -1041,6 +1135,7 @@ static void __init prom_init_mem(void) | |||
| 1041 | RELOC(alloc_top_high) = RELOC(ram_top); | 1135 | RELOC(alloc_top_high) = RELOC(ram_top); |
| 1042 | 1136 | ||
| 1043 | prom_printf("memory layout at init:\n"); | 1137 | prom_printf("memory layout at init:\n"); |
| 1138 | prom_printf(" memory_limit : %x (16 MB aligned)\n", RELOC(prom_memory_limit)); | ||
| 1044 | prom_printf(" alloc_bottom : %x\n", RELOC(alloc_bottom)); | 1139 | prom_printf(" alloc_bottom : %x\n", RELOC(alloc_bottom)); |
| 1045 | prom_printf(" alloc_top : %x\n", RELOC(alloc_top)); | 1140 | prom_printf(" alloc_top : %x\n", RELOC(alloc_top)); |
| 1046 | prom_printf(" alloc_top_hi : %x\n", RELOC(alloc_top_high)); | 1141 | prom_printf(" alloc_top_hi : %x\n", RELOC(alloc_top_high)); |
| @@ -1259,10 +1354,6 @@ static void __init prom_initialize_tce_table(void) | |||
| 1259 | * | 1354 | * |
| 1260 | * -- Cort | 1355 | * -- Cort |
| 1261 | */ | 1356 | */ |
| 1262 | extern char __secondary_hold; | ||
| 1263 | extern unsigned long __secondary_hold_spinloop; | ||
| 1264 | extern unsigned long __secondary_hold_acknowledge; | ||
| 1265 | |||
| 1266 | /* | 1357 | /* |
| 1267 | * We want to reference the copy of __secondary_hold_* in the | 1358 | * We want to reference the copy of __secondary_hold_* in the |
| 1268 | * 0 - 0x100 address range | 1359 | * 0 - 0x100 address range |
| @@ -2399,6 +2490,10 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
| 2399 | /* | 2490 | /* |
| 2400 | * Fill in some infos for use by the kernel later on | 2491 | * Fill in some infos for use by the kernel later on |
| 2401 | */ | 2492 | */ |
| 2493 | if (RELOC(prom_memory_limit)) | ||
| 2494 | prom_setprop(_prom->chosen, "/chosen", "linux,memory-limit", | ||
| 2495 | &RELOC(prom_memory_limit), | ||
| 2496 | sizeof(prom_memory_limit)); | ||
| 2402 | #ifdef CONFIG_PPC64 | 2497 | #ifdef CONFIG_PPC64 |
| 2403 | if (RELOC(prom_iommu_off)) | 2498 | if (RELOC(prom_iommu_off)) |
| 2404 | prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off", | 2499 | prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off", |
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index c434823b8c83..bf90361bb70f 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | #include <asm/smp.h> | 39 | #include <asm/smp.h> |
| 40 | #include <asm/atomic.h> | 40 | #include <asm/atomic.h> |
| 41 | #include <asm/time.h> | 41 | #include <asm/time.h> |
| 42 | #include <asm/mmu.h> | ||
| 42 | 43 | ||
| 43 | struct rtas_t rtas = { | 44 | struct rtas_t rtas = { |
| 44 | .lock = __RAW_SPIN_LOCK_UNLOCKED | 45 | .lock = __RAW_SPIN_LOCK_UNLOCKED |
| @@ -713,6 +714,7 @@ static void rtas_percpu_suspend_me(void *info) | |||
| 713 | { | 714 | { |
| 714 | long rc = H_SUCCESS; | 715 | long rc = H_SUCCESS; |
| 715 | unsigned long msr_save; | 716 | unsigned long msr_save; |
| 717 | u16 slb_size = mmu_slb_size; | ||
| 716 | int cpu; | 718 | int cpu; |
| 717 | struct rtas_suspend_me_data *data = | 719 | struct rtas_suspend_me_data *data = |
| 718 | (struct rtas_suspend_me_data *)info; | 720 | (struct rtas_suspend_me_data *)info; |
| @@ -735,13 +737,16 @@ static void rtas_percpu_suspend_me(void *info) | |||
| 735 | /* All other cpus are in H_JOIN, this cpu does | 737 | /* All other cpus are in H_JOIN, this cpu does |
| 736 | * the suspend. | 738 | * the suspend. |
| 737 | */ | 739 | */ |
| 740 | slb_set_size(SLB_MIN_SIZE); | ||
| 738 | printk(KERN_DEBUG "calling ibm,suspend-me on cpu %i\n", | 741 | printk(KERN_DEBUG "calling ibm,suspend-me on cpu %i\n", |
| 739 | smp_processor_id()); | 742 | smp_processor_id()); |
| 740 | data->error = rtas_call(data->token, 0, 1, NULL); | 743 | data->error = rtas_call(data->token, 0, 1, NULL); |
| 741 | 744 | ||
| 742 | if (data->error) | 745 | if (data->error) { |
| 743 | printk(KERN_DEBUG "ibm,suspend-me returned %d\n", | 746 | printk(KERN_DEBUG "ibm,suspend-me returned %d\n", |
| 744 | data->error); | 747 | data->error); |
| 748 | slb_set_size(slb_size); | ||
| 749 | } | ||
| 745 | } else { | 750 | } else { |
| 746 | printk(KERN_ERR "H_JOIN on cpu %i failed with rc = %ld\n", | 751 | printk(KERN_ERR "H_JOIN on cpu %i failed with rc = %ld\n", |
| 747 | smp_processor_id(), rc); | 752 | smp_processor_id(), rc); |
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index e1e3059cf34b..53bcf3d792db 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c | |||
| @@ -210,6 +210,14 @@ void nvram_write_byte(unsigned char val, int addr) | |||
| 210 | } | 210 | } |
| 211 | EXPORT_SYMBOL(nvram_write_byte); | 211 | EXPORT_SYMBOL(nvram_write_byte); |
| 212 | 212 | ||
| 213 | ssize_t nvram_get_size(void) | ||
| 214 | { | ||
| 215 | if (ppc_md.nvram_size) | ||
| 216 | return ppc_md.nvram_size(); | ||
| 217 | return -1; | ||
| 218 | } | ||
| 219 | EXPORT_SYMBOL(nvram_get_size); | ||
| 220 | |||
| 213 | void nvram_sync(void) | 221 | void nvram_sync(void) |
| 214 | { | 222 | { |
| 215 | if (ppc_md.nvram_sync) | 223 | if (ppc_md.nvram_sync) |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index aa6e4500635f..797ea95aae2e 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
| @@ -63,6 +63,7 @@ | |||
| 63 | #include <asm/udbg.h> | 63 | #include <asm/udbg.h> |
| 64 | #include <asm/kexec.h> | 64 | #include <asm/kexec.h> |
| 65 | #include <asm/swiotlb.h> | 65 | #include <asm/swiotlb.h> |
| 66 | #include <asm/mmu_context.h> | ||
| 66 | 67 | ||
| 67 | #include "setup.h" | 68 | #include "setup.h" |
| 68 | 69 | ||
| @@ -143,11 +144,14 @@ early_param("smt-enabled", early_smt_enabled); | |||
| 143 | #define check_smt_enabled() | 144 | #define check_smt_enabled() |
| 144 | #endif /* CONFIG_SMP */ | 145 | #endif /* CONFIG_SMP */ |
| 145 | 146 | ||
| 146 | /* Put the paca pointer into r13 and SPRG3 */ | 147 | /* Put the paca pointer into r13 and SPRG_PACA */ |
| 147 | void __init setup_paca(int cpu) | 148 | void __init setup_paca(int cpu) |
| 148 | { | 149 | { |
| 149 | local_paca = &paca[cpu]; | 150 | local_paca = &paca[cpu]; |
| 150 | mtspr(SPRN_SPRG3, local_paca); | 151 | mtspr(SPRN_SPRG_PACA, local_paca); |
| 152 | #ifdef CONFIG_PPC_BOOK3E | ||
| 153 | mtspr(SPRN_SPRG_TLB_EXFRAME, local_paca->extlb); | ||
| 154 | #endif | ||
| 151 | } | 155 | } |
| 152 | 156 | ||
| 153 | /* | 157 | /* |
| @@ -231,9 +235,6 @@ void early_setup_secondary(void) | |||
| 231 | #endif /* CONFIG_SMP */ | 235 | #endif /* CONFIG_SMP */ |
| 232 | 236 | ||
| 233 | #if defined(CONFIG_SMP) || defined(CONFIG_KEXEC) | 237 | #if defined(CONFIG_SMP) || defined(CONFIG_KEXEC) |
| 234 | extern unsigned long __secondary_hold_spinloop; | ||
| 235 | extern void generic_secondary_smp_init(void); | ||
| 236 | |||
| 237 | void smp_release_cpus(void) | 238 | void smp_release_cpus(void) |
| 238 | { | 239 | { |
| 239 | unsigned long *ptr; | 240 | unsigned long *ptr; |
| @@ -454,6 +455,24 @@ static void __init irqstack_early_init(void) | |||
| 454 | #define irqstack_early_init() | 455 | #define irqstack_early_init() |
| 455 | #endif | 456 | #endif |
| 456 | 457 | ||
| 458 | #ifdef CONFIG_PPC_BOOK3E | ||
| 459 | static void __init exc_lvl_early_init(void) | ||
| 460 | { | ||
| 461 | unsigned int i; | ||
| 462 | |||
| 463 | for_each_possible_cpu(i) { | ||
| 464 | critirq_ctx[i] = (struct thread_info *) | ||
| 465 | __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE)); | ||
| 466 | dbgirq_ctx[i] = (struct thread_info *) | ||
| 467 | __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE)); | ||
| 468 | mcheckirq_ctx[i] = (struct thread_info *) | ||
| 469 | __va(lmb_alloc(THREAD_SIZE, THREAD_SIZE)); | ||
| 470 | } | ||
| 471 | } | ||
| 472 | #else | ||
| 473 | #define exc_lvl_early_init() | ||
| 474 | #endif | ||
| 475 | |||
| 457 | /* | 476 | /* |
| 458 | * Stack space used when we detect a bad kernel stack pointer, and | 477 | * Stack space used when we detect a bad kernel stack pointer, and |
| 459 | * early in SMP boots before relocation is enabled. | 478 | * early in SMP boots before relocation is enabled. |
| @@ -513,6 +532,7 @@ void __init setup_arch(char **cmdline_p) | |||
| 513 | init_mm.brk = klimit; | 532 | init_mm.brk = klimit; |
| 514 | 533 | ||
| 515 | irqstack_early_init(); | 534 | irqstack_early_init(); |
| 535 | exc_lvl_early_init(); | ||
| 516 | emergency_stack_init(); | 536 | emergency_stack_init(); |
| 517 | 537 | ||
| 518 | #ifdef CONFIG_PPC_STD_MMU_64 | 538 | #ifdef CONFIG_PPC_STD_MMU_64 |
| @@ -535,6 +555,10 @@ void __init setup_arch(char **cmdline_p) | |||
| 535 | #endif | 555 | #endif |
| 536 | 556 | ||
| 537 | paging_init(); | 557 | paging_init(); |
| 558 | |||
| 559 | /* Initialize the MMU context management stuff */ | ||
| 560 | mmu_context_init(); | ||
| 561 | |||
| 538 | ppc64_boot_msg(0x15, "Setup Done"); | 562 | ppc64_boot_msg(0x15, "Setup Done"); |
| 539 | } | 563 | } |
| 540 | 564 | ||
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 0b47de07302d..d387b3937ccc 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
| @@ -269,7 +269,10 @@ void __init smp_prepare_cpus(unsigned int max_cpus) | |||
| 269 | cpu_callin_map[boot_cpuid] = 1; | 269 | cpu_callin_map[boot_cpuid] = 1; |
| 270 | 270 | ||
| 271 | if (smp_ops) | 271 | if (smp_ops) |
| 272 | max_cpus = smp_ops->probe(); | 272 | if (smp_ops->probe) |
| 273 | max_cpus = smp_ops->probe(); | ||
| 274 | else | ||
| 275 | max_cpus = NR_CPUS; | ||
| 273 | else | 276 | else |
| 274 | max_cpus = 1; | 277 | max_cpus = 1; |
| 275 | 278 | ||
| @@ -412,9 +415,8 @@ int __cpuinit __cpu_up(unsigned int cpu) | |||
| 412 | * CPUs can take much longer to come up in the | 415 | * CPUs can take much longer to come up in the |
| 413 | * hotplug case. Wait five seconds. | 416 | * hotplug case. Wait five seconds. |
| 414 | */ | 417 | */ |
| 415 | for (c = 25; c && !cpu_callin_map[cpu]; c--) { | 418 | for (c = 5000; c && !cpu_callin_map[cpu]; c--) |
| 416 | msleep(200); | 419 | msleep(1); |
| 417 | } | ||
| 418 | #endif | 420 | #endif |
| 419 | 421 | ||
| 420 | if (!cpu_callin_map[cpu]) { | 422 | if (!cpu_callin_map[cpu]) { |
| @@ -494,7 +496,8 @@ int __devinit start_secondary(void *unused) | |||
| 494 | preempt_disable(); | 496 | preempt_disable(); |
| 495 | cpu_callin_map[cpu] = 1; | 497 | cpu_callin_map[cpu] = 1; |
| 496 | 498 | ||
| 497 | smp_ops->setup_cpu(cpu); | 499 | if (smp_ops->setup_cpu) |
| 500 | smp_ops->setup_cpu(cpu); | ||
| 498 | if (smp_ops->take_timebase) | 501 | if (smp_ops->take_timebase) |
| 499 | smp_ops->take_timebase(); | 502 | smp_ops->take_timebase(); |
| 500 | 503 | ||
| @@ -557,7 +560,7 @@ void __init smp_cpus_done(unsigned int max_cpus) | |||
| 557 | old_mask = current->cpus_allowed; | 560 | old_mask = current->cpus_allowed; |
| 558 | set_cpus_allowed(current, cpumask_of_cpu(boot_cpuid)); | 561 | set_cpus_allowed(current, cpumask_of_cpu(boot_cpuid)); |
| 559 | 562 | ||
| 560 | if (smp_ops) | 563 | if (smp_ops && smp_ops->setup_cpu) |
| 561 | smp_ops->setup_cpu(boot_cpuid); | 564 | smp_ops->setup_cpu(boot_cpuid); |
| 562 | 565 | ||
| 563 | set_cpus_allowed(current, old_mask); | 566 | set_cpus_allowed(current, old_mask); |
diff --git a/arch/powerpc/kernel/sys_ppc32.c b/arch/powerpc/kernel/sys_ppc32.c index bb1cfcfdbbbb..1cc5e9e5da96 100644 --- a/arch/powerpc/kernel/sys_ppc32.c +++ b/arch/powerpc/kernel/sys_ppc32.c | |||
| @@ -343,6 +343,18 @@ off_t ppc32_lseek(unsigned int fd, u32 offset, unsigned int origin) | |||
| 343 | return sys_lseek(fd, (int)offset, origin); | 343 | return sys_lseek(fd, (int)offset, origin); |
| 344 | } | 344 | } |
| 345 | 345 | ||
| 346 | long compat_sys_truncate(const char __user * path, u32 length) | ||
| 347 | { | ||
| 348 | /* sign extend length */ | ||
| 349 | return sys_truncate(path, (int)length); | ||
| 350 | } | ||
| 351 | |||
| 352 | long compat_sys_ftruncate(int fd, u32 length) | ||
| 353 | { | ||
| 354 | /* sign extend length */ | ||
| 355 | return sys_ftruncate(fd, (int)length); | ||
| 356 | } | ||
| 357 | |||
| 346 | /* Note: it is necessary to treat bufsiz as an unsigned int, | 358 | /* Note: it is necessary to treat bufsiz as an unsigned int, |
| 347 | * with the corresponding cast to a signed int to insure that the | 359 | * with the corresponding cast to a signed int to insure that the |
| 348 | * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) | 360 | * proper conversion (sign extension) between the register representation of a signed int (msr in 32-bit mode) |
diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c index f41aec85aa49..956ab33fd73f 100644 --- a/arch/powerpc/kernel/sysfs.c +++ b/arch/powerpc/kernel/sysfs.c | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include <asm/prom.h> | 17 | #include <asm/prom.h> |
| 18 | #include <asm/machdep.h> | 18 | #include <asm/machdep.h> |
| 19 | #include <asm/smp.h> | 19 | #include <asm/smp.h> |
| 20 | #include <asm/pmc.h> | ||
| 20 | 21 | ||
| 21 | #include "cacheinfo.h" | 22 | #include "cacheinfo.h" |
| 22 | 23 | ||
| @@ -123,6 +124,8 @@ static DEFINE_PER_CPU(char, pmcs_enabled); | |||
| 123 | 124 | ||
| 124 | void ppc_enable_pmcs(void) | 125 | void ppc_enable_pmcs(void) |
| 125 | { | 126 | { |
| 127 | ppc_set_pmu_inuse(1); | ||
| 128 | |||
| 126 | /* Only need to enable them once */ | 129 | /* Only need to enable them once */ |
| 127 | if (__get_cpu_var(pmcs_enabled)) | 130 | if (__get_cpu_var(pmcs_enabled)) |
| 128 | return; | 131 | return; |
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index eae4511ceeac..a180b4f9a4f6 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
| @@ -479,7 +479,8 @@ static int __init iSeries_tb_recal(void) | |||
| 479 | unsigned long tb_ticks = tb - iSeries_recal_tb; | 479 | unsigned long tb_ticks = tb - iSeries_recal_tb; |
| 480 | unsigned long titan_usec = (titan - iSeries_recal_titan) >> 12; | 480 | unsigned long titan_usec = (titan - iSeries_recal_titan) >> 12; |
| 481 | unsigned long new_tb_ticks_per_sec = (tb_ticks * USEC_PER_SEC)/titan_usec; | 481 | unsigned long new_tb_ticks_per_sec = (tb_ticks * USEC_PER_SEC)/titan_usec; |
| 482 | unsigned long new_tb_ticks_per_jiffy = (new_tb_ticks_per_sec+(HZ/2))/HZ; | 482 | unsigned long new_tb_ticks_per_jiffy = |
| 483 | DIV_ROUND_CLOSEST(new_tb_ticks_per_sec, HZ); | ||
| 483 | long tick_diff = new_tb_ticks_per_jiffy - tb_ticks_per_jiffy; | 484 | long tick_diff = new_tb_ticks_per_jiffy - tb_ticks_per_jiffy; |
| 484 | char sign = '+'; | 485 | char sign = '+'; |
| 485 | /* make sure tb_ticks_per_sec and tb_ticks_per_jiffy are consistent */ | 486 | /* make sure tb_ticks_per_sec and tb_ticks_per_jiffy are consistent */ |
| @@ -726,6 +727,18 @@ static int __init get_freq(char *name, int cells, unsigned long *val) | |||
| 726 | return found; | 727 | return found; |
| 727 | } | 728 | } |
| 728 | 729 | ||
| 730 | /* should become __cpuinit when secondary_cpu_time_init also is */ | ||
| 731 | void start_cpu_decrementer(void) | ||
| 732 | { | ||
| 733 | #if defined(CONFIG_BOOKE) || defined(CONFIG_40x) | ||
| 734 | /* Clear any pending timer interrupts */ | ||
| 735 | mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS); | ||
| 736 | |||
| 737 | /* Enable decrementer interrupt */ | ||
| 738 | mtspr(SPRN_TCR, TCR_DIE); | ||
| 739 | #endif /* defined(CONFIG_BOOKE) || defined(CONFIG_40x) */ | ||
| 740 | } | ||
| 741 | |||
| 729 | void __init generic_calibrate_decr(void) | 742 | void __init generic_calibrate_decr(void) |
| 730 | { | 743 | { |
| 731 | ppc_tb_freq = DEFAULT_TB_FREQ; /* hardcoded default */ | 744 | ppc_tb_freq = DEFAULT_TB_FREQ; /* hardcoded default */ |
| @@ -745,14 +758,6 @@ void __init generic_calibrate_decr(void) | |||
| 745 | printk(KERN_ERR "WARNING: Estimating processor frequency " | 758 | printk(KERN_ERR "WARNING: Estimating processor frequency " |
| 746 | "(not found)\n"); | 759 | "(not found)\n"); |
| 747 | } | 760 | } |
| 748 | |||
| 749 | #if defined(CONFIG_BOOKE) || defined(CONFIG_40x) | ||
| 750 | /* Clear any pending timer interrupts */ | ||
| 751 | mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS); | ||
| 752 | |||
| 753 | /* Enable decrementer interrupt */ | ||
| 754 | mtspr(SPRN_TCR, TCR_DIE); | ||
| 755 | #endif | ||
| 756 | } | 761 | } |
| 757 | 762 | ||
| 758 | int update_persistent_clock(struct timespec now) | 763 | int update_persistent_clock(struct timespec now) |
| @@ -913,6 +918,11 @@ static void __init init_decrementer_clockevent(void) | |||
| 913 | 918 | ||
| 914 | void secondary_cpu_time_init(void) | 919 | void secondary_cpu_time_init(void) |
| 915 | { | 920 | { |
| 921 | /* Start the decrementer on CPUs that have manual control | ||
| 922 | * such as BookE | ||
| 923 | */ | ||
| 924 | start_cpu_decrementer(); | ||
| 925 | |||
| 916 | /* FIME: Should make unrelatred change to move snapshot_timebase | 926 | /* FIME: Should make unrelatred change to move snapshot_timebase |
| 917 | * call here ! */ | 927 | * call here ! */ |
| 918 | register_decrementer_clockevent(smp_processor_id()); | 928 | register_decrementer_clockevent(smp_processor_id()); |
| @@ -1016,6 +1026,11 @@ void __init time_init(void) | |||
| 1016 | 1026 | ||
| 1017 | write_sequnlock_irqrestore(&xtime_lock, flags); | 1027 | write_sequnlock_irqrestore(&xtime_lock, flags); |
| 1018 | 1028 | ||
| 1029 | /* Start the decrementer on CPUs that have manual control | ||
| 1030 | * such as BookE | ||
| 1031 | */ | ||
| 1032 | start_cpu_decrementer(); | ||
| 1033 | |||
| 1019 | /* Register the clocksource, if we're not running on iSeries */ | 1034 | /* Register the clocksource, if we're not running on iSeries */ |
| 1020 | if (!firmware_has_feature(FW_FEATURE_ISERIES)) | 1035 | if (!firmware_has_feature(FW_FEATURE_ISERIES)) |
| 1021 | clocksource_init(); | 1036 | clocksource_init(); |
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index ad06d5c75b15..a0abce251d0a 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c | |||
| @@ -203,7 +203,12 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp) | |||
| 203 | } else { | 203 | } else { |
| 204 | vdso_pagelist = vdso64_pagelist; | 204 | vdso_pagelist = vdso64_pagelist; |
| 205 | vdso_pages = vdso64_pages; | 205 | vdso_pages = vdso64_pages; |
| 206 | vdso_base = VDSO64_MBASE; | 206 | /* |
| 207 | * On 64bit we don't have a preferred map address. This | ||
| 208 | * allows get_unmapped_area to find an area near other mmaps | ||
| 209 | * and most likely share a SLB entry. | ||
| 210 | */ | ||
| 211 | vdso_base = 0; | ||
| 207 | } | 212 | } |
| 208 | #else | 213 | #else |
| 209 | vdso_pagelist = vdso32_pagelist; | 214 | vdso_pagelist = vdso32_pagelist; |
diff --git a/arch/powerpc/kernel/vdso32/Makefile b/arch/powerpc/kernel/vdso32/Makefile index c3d57bd01a88..b54b81688132 100644 --- a/arch/powerpc/kernel/vdso32/Makefile +++ b/arch/powerpc/kernel/vdso32/Makefile | |||
| @@ -12,6 +12,7 @@ endif | |||
| 12 | targets := $(obj-vdso32) vdso32.so vdso32.so.dbg | 12 | targets := $(obj-vdso32) vdso32.so vdso32.so.dbg |
| 13 | obj-vdso32 := $(addprefix $(obj)/, $(obj-vdso32)) | 13 | obj-vdso32 := $(addprefix $(obj)/, $(obj-vdso32)) |
| 14 | 14 | ||
| 15 | GCOV_PROFILE := n | ||
| 15 | 16 | ||
| 16 | EXTRA_CFLAGS := -shared -fno-common -fno-builtin | 17 | EXTRA_CFLAGS := -shared -fno-common -fno-builtin |
| 17 | EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso32.so.1 \ | 18 | EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso32.so.1 \ |
diff --git a/arch/powerpc/kernel/vdso64/Makefile b/arch/powerpc/kernel/vdso64/Makefile index fa7f1b8f3e50..dd0c8e936775 100644 --- a/arch/powerpc/kernel/vdso64/Makefile +++ b/arch/powerpc/kernel/vdso64/Makefile | |||
| @@ -7,6 +7,8 @@ obj-vdso64 = sigtramp.o gettimeofday.o datapage.o cacheflush.o note.o | |||
| 7 | targets := $(obj-vdso64) vdso64.so vdso64.so.dbg | 7 | targets := $(obj-vdso64) vdso64.so vdso64.so.dbg |
| 8 | obj-vdso64 := $(addprefix $(obj)/, $(obj-vdso64)) | 8 | obj-vdso64 := $(addprefix $(obj)/, $(obj-vdso64)) |
| 9 | 9 | ||
| 10 | GCOV_PROFILE := n | ||
| 11 | |||
| 10 | EXTRA_CFLAGS := -shared -fno-common -fno-builtin | 12 | EXTRA_CFLAGS := -shared -fno-common -fno-builtin |
| 11 | EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso64.so.1 \ | 13 | EXTRA_CFLAGS += -nostdlib -Wl,-soname=linux-vdso64.so.1 \ |
| 12 | $(call ld-option, -Wl$(comma)--hash-style=sysv) | 14 | $(call ld-option, -Wl$(comma)--hash-style=sysv) |
diff --git a/arch/powerpc/kernel/vector.S b/arch/powerpc/kernel/vector.S index ea4d64644d02..67b6916f0e94 100644 --- a/arch/powerpc/kernel/vector.S +++ b/arch/powerpc/kernel/vector.S | |||
| @@ -65,7 +65,7 @@ _GLOBAL(load_up_altivec) | |||
| 65 | 1: | 65 | 1: |
| 66 | /* enable use of VMX after return */ | 66 | /* enable use of VMX after return */ |
| 67 | #ifdef CONFIG_PPC32 | 67 | #ifdef CONFIG_PPC32 |
| 68 | mfspr r5,SPRN_SPRG3 /* current task's THREAD (phys) */ | 68 | mfspr r5,SPRN_SPRG_THREAD /* current task's THREAD (phys) */ |
| 69 | oris r9,r9,MSR_VEC@h | 69 | oris r9,r9,MSR_VEC@h |
| 70 | #else | 70 | #else |
| 71 | ld r4,PACACURRENT(r13) | 71 | ld r4,PACACURRENT(r13) |
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 819e59f6f7c7..bc7b41edbdfc 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c | |||
| @@ -601,7 +601,7 @@ static void vio_dma_iommu_unmap_sg(struct device *dev, | |||
| 601 | vio_cmo_dealloc(viodev, alloc_size); | 601 | vio_cmo_dealloc(viodev, alloc_size); |
| 602 | } | 602 | } |
| 603 | 603 | ||
| 604 | struct dma_mapping_ops vio_dma_mapping_ops = { | 604 | struct dma_map_ops vio_dma_mapping_ops = { |
| 605 | .alloc_coherent = vio_dma_iommu_alloc_coherent, | 605 | .alloc_coherent = vio_dma_iommu_alloc_coherent, |
| 606 | .free_coherent = vio_dma_iommu_free_coherent, | 606 | .free_coherent = vio_dma_iommu_free_coherent, |
| 607 | .map_sg = vio_dma_iommu_map_sg, | 607 | .map_sg = vio_dma_iommu_map_sg, |
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index 244e3658983c..58da4070723d 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S | |||
| @@ -239,10 +239,6 @@ SECTIONS | |||
| 239 | } | 239 | } |
| 240 | #endif | 240 | #endif |
| 241 | 241 | ||
| 242 | . = ALIGN(PAGE_SIZE); | ||
| 243 | _edata = .; | ||
| 244 | PROVIDE32 (edata = .); | ||
| 245 | |||
| 246 | /* The initial task and kernel stack */ | 242 | /* The initial task and kernel stack */ |
| 247 | #ifdef CONFIG_PPC32 | 243 | #ifdef CONFIG_PPC32 |
| 248 | . = ALIGN(8192); | 244 | . = ALIGN(8192); |
| @@ -276,6 +272,10 @@ SECTIONS | |||
| 276 | __nosave_end = .; | 272 | __nosave_end = .; |
| 277 | } | 273 | } |
| 278 | 274 | ||
| 275 | . = ALIGN(PAGE_SIZE); | ||
| 276 | _edata = .; | ||
| 277 | PROVIDE32 (edata = .); | ||
| 278 | |||
| 279 | /* | 279 | /* |
| 280 | * And finally the bss | 280 | * And finally the bss |
| 281 | */ | 281 | */ |
