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 | */ |