diff options
author | David Woodhouse <dwmw2@infradead.org> | 2006-12-01 04:56:43 -0500 |
---|---|---|
committer | David Woodhouse <dwmw2@infradead.org> | 2006-12-01 04:56:43 -0500 |
commit | bd3c97a7c718bfb9f1e4f31c16c383a5c6f815eb (patch) | |
tree | 3f56594e813c6f35cbacbdb3e137ba5bfd0b3069 /arch/powerpc/kernel | |
parent | 6c33cafc794d07c9254c160789120a0e98c088c9 (diff) | |
parent | 0215ffb08ce99e2bb59eca114a99499a4d06e704 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'arch/powerpc/kernel')
-rw-r--r-- | arch/powerpc/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/powerpc/kernel/btext.c | 2 | ||||
-rw-r--r-- | arch/powerpc/kernel/cputable.c | 86 | ||||
-rw-r--r-- | arch/powerpc/kernel/head_64.S | 48 | ||||
-rw-r--r-- | arch/powerpc/kernel/iommu.c | 77 | ||||
-rw-r--r-- | arch/powerpc/kernel/misc_32.S | 74 | ||||
-rw-r--r-- | arch/powerpc/kernel/misc_64.S | 124 | ||||
-rw-r--r-- | arch/powerpc/kernel/module_32.c | 39 | ||||
-rw-r--r-- | arch/powerpc/kernel/module_64.c | 49 | ||||
-rw-r--r-- | arch/powerpc/kernel/perfmon_fsl_booke.c | 221 | ||||
-rw-r--r-- | arch/powerpc/kernel/pmc.c | 2 | ||||
-rw-r--r-- | arch/powerpc/kernel/prom.c | 8 | ||||
-rw-r--r-- | arch/powerpc/kernel/rtas_flash.c | 47 | ||||
-rw-r--r-- | arch/powerpc/kernel/setup_32.c | 8 | ||||
-rw-r--r-- | arch/powerpc/kernel/setup_64.c | 11 | ||||
-rw-r--r-- | arch/powerpc/kernel/time.c | 105 | ||||
-rw-r--r-- | arch/powerpc/kernel/traps.c | 18 | ||||
-rw-r--r-- | arch/powerpc/kernel/vdso.c | 43 | ||||
-rw-r--r-- | arch/powerpc/kernel/vdso32/vdso32.lds.S | 12 | ||||
-rw-r--r-- | arch/powerpc/kernel/vdso64/gettimeofday.S | 6 | ||||
-rw-r--r-- | arch/powerpc/kernel/vdso64/vdso64.lds.S | 10 | ||||
-rw-r--r-- | arch/powerpc/kernel/vio.c | 4 | ||||
-rw-r--r-- | arch/powerpc/kernel/vmlinux.lds.S | 8 |
23 files changed, 375 insertions, 628 deletions
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 8b133afbdc20..7af23c43fd4b 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile | |||
@@ -38,7 +38,6 @@ obj-$(CONFIG_6xx) += idle_6xx.o l2cr_6xx.o cpu_setup_6xx.o | |||
38 | obj-$(CONFIG_TAU) += tau_6xx.o | 38 | obj-$(CONFIG_TAU) += tau_6xx.o |
39 | obj32-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_32.o | 39 | obj32-$(CONFIG_SOFTWARE_SUSPEND) += swsusp_32.o |
40 | obj32-$(CONFIG_MODULES) += module_32.o | 40 | obj32-$(CONFIG_MODULES) += module_32.o |
41 | obj-$(CONFIG_E500) += perfmon_fsl_booke.o | ||
42 | 41 | ||
43 | ifeq ($(CONFIG_PPC_MERGE),y) | 42 | ifeq ($(CONFIG_PPC_MERGE),y) |
44 | 43 | ||
diff --git a/arch/powerpc/kernel/btext.c b/arch/powerpc/kernel/btext.c index 995fcef156fd..93f21aaf7c8e 100644 --- a/arch/powerpc/kernel/btext.c +++ b/arch/powerpc/kernel/btext.c | |||
@@ -182,7 +182,7 @@ int btext_initialize(struct device_node *np) | |||
182 | prop = get_property(np, "linux,bootx-linebytes", NULL); | 182 | prop = get_property(np, "linux,bootx-linebytes", NULL); |
183 | if (prop == NULL) | 183 | if (prop == NULL) |
184 | prop = get_property(np, "linebytes", NULL); | 184 | prop = get_property(np, "linebytes", NULL); |
185 | if (prop) | 185 | if (prop && *prop != 0xffffffffu) |
186 | pitch = *prop; | 186 | pitch = *prop; |
187 | if (pitch == 1) | 187 | if (pitch == 1) |
188 | pitch = 0x1000; | 188 | pitch = 0x1000; |
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 95382f994404..bfd499ee3753 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
@@ -18,6 +18,7 @@ | |||
18 | 18 | ||
19 | #include <asm/oprofile_impl.h> | 19 | #include <asm/oprofile_impl.h> |
20 | #include <asm/cputable.h> | 20 | #include <asm/cputable.h> |
21 | #include <asm/prom.h> /* for PTRRELOC on ARCH=ppc */ | ||
21 | 22 | ||
22 | struct cpu_spec* cur_cpu_spec = NULL; | 23 | struct cpu_spec* cur_cpu_spec = NULL; |
23 | EXPORT_SYMBOL(cur_cpu_spec); | 24 | EXPORT_SYMBOL(cur_cpu_spec); |
@@ -73,7 +74,7 @@ extern void __restore_cpu_ppc970(void); | |||
73 | #define PPC_FEATURE_SPE_COMP 0 | 74 | #define PPC_FEATURE_SPE_COMP 0 |
74 | #endif | 75 | #endif |
75 | 76 | ||
76 | struct cpu_spec cpu_specs[] = { | 77 | static struct cpu_spec cpu_specs[] = { |
77 | #ifdef CONFIG_PPC64 | 78 | #ifdef CONFIG_PPC64 |
78 | { /* Power3 */ | 79 | { /* Power3 */ |
79 | .pvr_mask = 0xffff0000, | 80 | .pvr_mask = 0xffff0000, |
@@ -227,6 +228,21 @@ struct cpu_spec cpu_specs[] = { | |||
227 | .oprofile_type = PPC_OPROFILE_POWER4, | 228 | .oprofile_type = PPC_OPROFILE_POWER4, |
228 | .platform = "ppc970", | 229 | .platform = "ppc970", |
229 | }, | 230 | }, |
231 | { /* PPC970GX */ | ||
232 | .pvr_mask = 0xffff0000, | ||
233 | .pvr_value = 0x00450000, | ||
234 | .cpu_name = "PPC970GX", | ||
235 | .cpu_features = CPU_FTRS_PPC970, | ||
236 | .cpu_user_features = COMMON_USER_POWER4 | | ||
237 | PPC_FEATURE_HAS_ALTIVEC_COMP, | ||
238 | .icache_bsize = 128, | ||
239 | .dcache_bsize = 128, | ||
240 | .num_pmcs = 8, | ||
241 | .cpu_setup = __setup_cpu_ppc970, | ||
242 | .oprofile_cpu_type = "ppc64/970", | ||
243 | .oprofile_type = PPC_OPROFILE_POWER4, | ||
244 | .platform = "ppc970", | ||
245 | }, | ||
230 | { /* Power5 GR */ | 246 | { /* Power5 GR */ |
231 | .pvr_mask = 0xffff0000, | 247 | .pvr_mask = 0xffff0000, |
232 | .pvr_value = 0x003a0000, | 248 | .pvr_value = 0x003a0000, |
@@ -1152,3 +1168,71 @@ struct cpu_spec cpu_specs[] = { | |||
1152 | #endif /* !CLASSIC_PPC */ | 1168 | #endif /* !CLASSIC_PPC */ |
1153 | #endif /* CONFIG_PPC32 */ | 1169 | #endif /* CONFIG_PPC32 */ |
1154 | }; | 1170 | }; |
1171 | |||
1172 | struct cpu_spec *identify_cpu(unsigned long offset) | ||
1173 | { | ||
1174 | struct cpu_spec *s = cpu_specs; | ||
1175 | struct cpu_spec **cur = &cur_cpu_spec; | ||
1176 | unsigned int pvr = mfspr(SPRN_PVR); | ||
1177 | int i; | ||
1178 | |||
1179 | s = PTRRELOC(s); | ||
1180 | cur = PTRRELOC(cur); | ||
1181 | |||
1182 | if (*cur != NULL) | ||
1183 | return PTRRELOC(*cur); | ||
1184 | |||
1185 | for (i = 0; i < ARRAY_SIZE(cpu_specs); i++,s++) | ||
1186 | if ((pvr & s->pvr_mask) == s->pvr_value) { | ||
1187 | *cur = cpu_specs + i; | ||
1188 | #ifdef CONFIG_PPC64 | ||
1189 | /* ppc64 expects identify_cpu to also call setup_cpu | ||
1190 | * for that processor. I will consolidate that at a | ||
1191 | * later time, for now, just use our friend #ifdef. | ||
1192 | * we also don't need to PTRRELOC the function pointer | ||
1193 | * on ppc64 as we are running at 0 in real mode. | ||
1194 | */ | ||
1195 | if (s->cpu_setup) { | ||
1196 | s->cpu_setup(offset, s); | ||
1197 | } | ||
1198 | #endif /* CONFIG_PPC64 */ | ||
1199 | return s; | ||
1200 | } | ||
1201 | BUG(); | ||
1202 | return NULL; | ||
1203 | } | ||
1204 | |||
1205 | void do_feature_fixups(unsigned long value, void *fixup_start, void *fixup_end) | ||
1206 | { | ||
1207 | struct fixup_entry { | ||
1208 | unsigned long mask; | ||
1209 | unsigned long value; | ||
1210 | long start_off; | ||
1211 | long end_off; | ||
1212 | } *fcur, *fend; | ||
1213 | |||
1214 | fcur = fixup_start; | ||
1215 | fend = fixup_end; | ||
1216 | |||
1217 | for (; fcur < fend; fcur++) { | ||
1218 | unsigned int *pstart, *pend, *p; | ||
1219 | |||
1220 | if ((value & fcur->mask) == fcur->value) | ||
1221 | continue; | ||
1222 | |||
1223 | /* These PTRRELOCs will disappear once the new scheme for | ||
1224 | * modules and vdso is implemented | ||
1225 | */ | ||
1226 | pstart = ((unsigned int *)fcur) + (fcur->start_off / 4); | ||
1227 | pend = ((unsigned int *)fcur) + (fcur->end_off / 4); | ||
1228 | |||
1229 | for (p = pstart; p < pend; p++) { | ||
1230 | *p = 0x60000000u; | ||
1231 | asm volatile ("dcbst 0, %0" : : "r" (p)); | ||
1232 | } | ||
1233 | asm volatile ("sync" : : : "memory"); | ||
1234 | for (p = pstart; p < pend; p++) | ||
1235 | asm volatile ("icbi 0,%0" : : "r" (p)); | ||
1236 | asm volatile ("sync; isync" : : : "memory"); | ||
1237 | } | ||
1238 | } | ||
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index 645c7f10fb28..e720729f3e55 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
@@ -487,7 +487,7 @@ BEGIN_FTR_SECTION | |||
487 | rlwimi r13,r12,16,0x20 | 487 | rlwimi r13,r12,16,0x20 |
488 | mfcr r12 | 488 | mfcr r12 |
489 | cmpwi r13,0x2c | 489 | cmpwi r13,0x2c |
490 | beq .do_stab_bolted_pSeries | 490 | beq do_stab_bolted_pSeries |
491 | mtcrf 0x80,r12 | 491 | mtcrf 0x80,r12 |
492 | mfspr r12,SPRN_SPRG2 | 492 | mfspr r12,SPRN_SPRG2 |
493 | END_FTR_SECTION_IFCLR(CPU_FTR_SLB) | 493 | END_FTR_SECTION_IFCLR(CPU_FTR_SLB) |
@@ -600,7 +600,7 @@ system_call_pSeries: | |||
600 | STD_EXCEPTION_PSERIES(., performance_monitor) | 600 | STD_EXCEPTION_PSERIES(., performance_monitor) |
601 | 601 | ||
602 | .align 7 | 602 | .align 7 |
603 | _GLOBAL(do_stab_bolted_pSeries) | 603 | do_stab_bolted_pSeries: |
604 | mtcrf 0x80,r12 | 604 | mtcrf 0x80,r12 |
605 | mfspr r12,SPRN_SPRG2 | 605 | mfspr r12,SPRN_SPRG2 |
606 | EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted) | 606 | EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted) |
@@ -1046,7 +1046,7 @@ slb_miss_fault: | |||
1046 | li r5,0 | 1046 | li r5,0 |
1047 | std r4,_DAR(r1) | 1047 | std r4,_DAR(r1) |
1048 | std r5,_DSISR(r1) | 1048 | std r5,_DSISR(r1) |
1049 | b .handle_page_fault | 1049 | b handle_page_fault |
1050 | 1050 | ||
1051 | unrecov_user_slb: | 1051 | unrecov_user_slb: |
1052 | EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN) | 1052 | EXCEPTION_PROLOG_COMMON(0x4200, PACA_EXGEN) |
@@ -1174,12 +1174,13 @@ program_check_common: | |||
1174 | .globl fp_unavailable_common | 1174 | .globl fp_unavailable_common |
1175 | fp_unavailable_common: | 1175 | fp_unavailable_common: |
1176 | EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN) | 1176 | EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN) |
1177 | bne .load_up_fpu /* if from user, just load it up */ | 1177 | bne 1f /* if from user, just load it up */ |
1178 | bl .save_nvgprs | 1178 | bl .save_nvgprs |
1179 | addi r3,r1,STACK_FRAME_OVERHEAD | 1179 | addi r3,r1,STACK_FRAME_OVERHEAD |
1180 | ENABLE_INTS | 1180 | ENABLE_INTS |
1181 | bl .kernel_fp_unavailable_exception | 1181 | bl .kernel_fp_unavailable_exception |
1182 | BUG_OPCODE | 1182 | BUG_OPCODE |
1183 | 1: b .load_up_fpu | ||
1183 | 1184 | ||
1184 | .align 7 | 1185 | .align 7 |
1185 | .globl altivec_unavailable_common | 1186 | .globl altivec_unavailable_common |
@@ -1279,10 +1280,10 @@ _GLOBAL(do_hash_page) | |||
1279 | std r4,_DSISR(r1) | 1280 | std r4,_DSISR(r1) |
1280 | 1281 | ||
1281 | andis. r0,r4,0xa450 /* weird error? */ | 1282 | andis. r0,r4,0xa450 /* weird error? */ |
1282 | bne- .handle_page_fault /* if not, try to insert a HPTE */ | 1283 | bne- handle_page_fault /* if not, try to insert a HPTE */ |
1283 | BEGIN_FTR_SECTION | 1284 | BEGIN_FTR_SECTION |
1284 | andis. r0,r4,0x0020 /* Is it a segment table fault? */ | 1285 | andis. r0,r4,0x0020 /* Is it a segment table fault? */ |
1285 | bne- .do_ste_alloc /* If so handle it */ | 1286 | bne- do_ste_alloc /* If so handle it */ |
1286 | END_FTR_SECTION_IFCLR(CPU_FTR_SLB) | 1287 | END_FTR_SECTION_IFCLR(CPU_FTR_SLB) |
1287 | 1288 | ||
1288 | /* | 1289 | /* |
@@ -1324,7 +1325,7 @@ BEGIN_FW_FTR_SECTION | |||
1324 | * because ret_from_except_lite will check for and handle pending | 1325 | * because ret_from_except_lite will check for and handle pending |
1325 | * interrupts if necessary. | 1326 | * interrupts if necessary. |
1326 | */ | 1327 | */ |
1327 | beq .ret_from_except_lite | 1328 | beq 13f |
1328 | /* For a hash failure, we don't bother re-enabling interrupts */ | 1329 | /* For a hash failure, we don't bother re-enabling interrupts */ |
1329 | ble- 12f | 1330 | ble- 12f |
1330 | 1331 | ||
@@ -1346,14 +1347,14 @@ BEGIN_FW_FTR_SECTION | |||
1346 | END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) | 1347 | END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES) |
1347 | 1348 | ||
1348 | /* Here we have a page fault that hash_page can't handle. */ | 1349 | /* Here we have a page fault that hash_page can't handle. */ |
1349 | _GLOBAL(handle_page_fault) | 1350 | handle_page_fault: |
1350 | ENABLE_INTS | 1351 | ENABLE_INTS |
1351 | 11: ld r4,_DAR(r1) | 1352 | 11: ld r4,_DAR(r1) |
1352 | ld r5,_DSISR(r1) | 1353 | ld r5,_DSISR(r1) |
1353 | addi r3,r1,STACK_FRAME_OVERHEAD | 1354 | addi r3,r1,STACK_FRAME_OVERHEAD |
1354 | bl .do_page_fault | 1355 | bl .do_page_fault |
1355 | cmpdi r3,0 | 1356 | cmpdi r3,0 |
1356 | beq+ .ret_from_except_lite | 1357 | beq+ 13f |
1357 | bl .save_nvgprs | 1358 | bl .save_nvgprs |
1358 | mr r5,r3 | 1359 | mr r5,r3 |
1359 | addi r3,r1,STACK_FRAME_OVERHEAD | 1360 | addi r3,r1,STACK_FRAME_OVERHEAD |
@@ -1370,12 +1371,14 @@ _GLOBAL(handle_page_fault) | |||
1370 | bl .low_hash_fault | 1371 | bl .low_hash_fault |
1371 | b .ret_from_except | 1372 | b .ret_from_except |
1372 | 1373 | ||
1374 | 13: b .ret_from_except_lite | ||
1375 | |||
1373 | /* here we have a segment miss */ | 1376 | /* here we have a segment miss */ |
1374 | _GLOBAL(do_ste_alloc) | 1377 | do_ste_alloc: |
1375 | bl .ste_allocate /* try to insert stab entry */ | 1378 | bl .ste_allocate /* try to insert stab entry */ |
1376 | cmpdi r3,0 | 1379 | cmpdi r3,0 |
1377 | beq+ fast_exception_return | 1380 | bne- handle_page_fault |
1378 | b .handle_page_fault | 1381 | b fast_exception_return |
1379 | 1382 | ||
1380 | /* | 1383 | /* |
1381 | * r13 points to the PACA, r9 contains the saved CR, | 1384 | * r13 points to the PACA, r9 contains the saved CR, |
@@ -1580,11 +1583,6 @@ _STATIC(__start_initialization_iSeries) | |||
1580 | li r0,0 | 1583 | li r0,0 |
1581 | stdu r0,-STACK_FRAME_OVERHEAD(r1) | 1584 | stdu r0,-STACK_FRAME_OVERHEAD(r1) |
1582 | 1585 | ||
1583 | LOAD_REG_IMMEDIATE(r3,cpu_specs) | ||
1584 | LOAD_REG_IMMEDIATE(r4,cur_cpu_spec) | ||
1585 | li r5,0 | ||
1586 | bl .identify_cpu | ||
1587 | |||
1588 | LOAD_REG_IMMEDIATE(r2,__toc_start) | 1586 | LOAD_REG_IMMEDIATE(r2,__toc_start) |
1589 | addi r2,r2,0x4000 | 1587 | addi r2,r2,0x4000 |
1590 | addi r2,r2,0x4000 | 1588 | addi r2,r2,0x4000 |
@@ -1646,6 +1644,8 @@ _GLOBAL(__start_initialization_multiplatform) | |||
1646 | cmpwi r0,0x3c /* 970FX */ | 1644 | cmpwi r0,0x3c /* 970FX */ |
1647 | beq 1f | 1645 | beq 1f |
1648 | cmpwi r0,0x44 /* 970MP */ | 1646 | cmpwi r0,0x44 /* 970MP */ |
1647 | beq 1f | ||
1648 | cmpwi r0,0x45 /* 970GX */ | ||
1649 | bne 2f | 1649 | bne 2f |
1650 | 1: bl .__cpu_preinit_ppc970 | 1650 | 1: bl .__cpu_preinit_ppc970 |
1651 | 2: | 1651 | 2: |
@@ -1964,13 +1964,6 @@ _STATIC(start_here_multiplatform) | |||
1964 | addi r2,r2,0x4000 | 1964 | addi r2,r2,0x4000 |
1965 | add r2,r2,r26 | 1965 | add r2,r2,r26 |
1966 | 1966 | ||
1967 | LOAD_REG_IMMEDIATE(r3, cpu_specs) | ||
1968 | add r3,r3,r26 | ||
1969 | LOAD_REG_IMMEDIATE(r4,cur_cpu_spec) | ||
1970 | add r4,r4,r26 | ||
1971 | mr r5,r26 | ||
1972 | bl .identify_cpu | ||
1973 | |||
1974 | /* Do very early kernel initializations, including initial hash table, | 1967 | /* Do very early kernel initializations, including initial hash table, |
1975 | * stab and slb setup before we turn on relocation. */ | 1968 | * stab and slb setup before we turn on relocation. */ |
1976 | 1969 | ||
@@ -2000,13 +1993,6 @@ _STATIC(start_here_common) | |||
2000 | li r0,0 | 1993 | li r0,0 |
2001 | stdu r0,-STACK_FRAME_OVERHEAD(r1) | 1994 | stdu r0,-STACK_FRAME_OVERHEAD(r1) |
2002 | 1995 | ||
2003 | /* Apply the CPUs-specific fixups (nop out sections not relevant | ||
2004 | * to this CPU | ||
2005 | */ | ||
2006 | li r3,0 | ||
2007 | bl .do_cpu_ftr_fixups | ||
2008 | bl .do_fw_ftr_fixups | ||
2009 | |||
2010 | /* ptr to current */ | 1996 | /* ptr to current */ |
2011 | LOAD_REG_IMMEDIATE(r4, init_task) | 1997 | LOAD_REG_IMMEDIATE(r4, init_task) |
2012 | std r4,PACACURRENT(r13) | 1998 | std r4,PACACURRENT(r13) |
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index f88a2a675d90..ba6b7256084b 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c | |||
@@ -47,6 +47,17 @@ static int novmerge = 0; | |||
47 | static int novmerge = 1; | 47 | static int novmerge = 1; |
48 | #endif | 48 | #endif |
49 | 49 | ||
50 | static inline unsigned long iommu_num_pages(unsigned long vaddr, | ||
51 | unsigned long slen) | ||
52 | { | ||
53 | unsigned long npages; | ||
54 | |||
55 | npages = IOMMU_PAGE_ALIGN(vaddr + slen) - (vaddr & IOMMU_PAGE_MASK); | ||
56 | npages >>= IOMMU_PAGE_SHIFT; | ||
57 | |||
58 | return npages; | ||
59 | } | ||
60 | |||
50 | static int __init setup_iommu(char *str) | 61 | static int __init setup_iommu(char *str) |
51 | { | 62 | { |
52 | if (!strcmp(str, "novmerge")) | 63 | if (!strcmp(str, "novmerge")) |
@@ -178,10 +189,10 @@ static dma_addr_t iommu_alloc(struct iommu_table *tbl, void *page, | |||
178 | } | 189 | } |
179 | 190 | ||
180 | entry += tbl->it_offset; /* Offset into real TCE table */ | 191 | entry += tbl->it_offset; /* Offset into real TCE table */ |
181 | ret = entry << PAGE_SHIFT; /* Set the return dma address */ | 192 | ret = entry << IOMMU_PAGE_SHIFT; /* Set the return dma address */ |
182 | 193 | ||
183 | /* Put the TCEs in the HW table */ | 194 | /* Put the TCEs in the HW table */ |
184 | ppc_md.tce_build(tbl, entry, npages, (unsigned long)page & PAGE_MASK, | 195 | ppc_md.tce_build(tbl, entry, npages, (unsigned long)page & IOMMU_PAGE_MASK, |
185 | direction); | 196 | direction); |
186 | 197 | ||
187 | 198 | ||
@@ -203,7 +214,7 @@ static void __iommu_free(struct iommu_table *tbl, dma_addr_t dma_addr, | |||
203 | unsigned long entry, free_entry; | 214 | unsigned long entry, free_entry; |
204 | unsigned long i; | 215 | unsigned long i; |
205 | 216 | ||
206 | entry = dma_addr >> PAGE_SHIFT; | 217 | entry = dma_addr >> IOMMU_PAGE_SHIFT; |
207 | free_entry = entry - tbl->it_offset; | 218 | free_entry = entry - tbl->it_offset; |
208 | 219 | ||
209 | if (((free_entry + npages) > tbl->it_size) || | 220 | if (((free_entry + npages) > tbl->it_size) || |
@@ -270,7 +281,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, | |||
270 | /* Init first segment length for backout at failure */ | 281 | /* Init first segment length for backout at failure */ |
271 | outs->dma_length = 0; | 282 | outs->dma_length = 0; |
272 | 283 | ||
273 | DBG("mapping %d elements:\n", nelems); | 284 | DBG("sg mapping %d elements:\n", nelems); |
274 | 285 | ||
275 | spin_lock_irqsave(&(tbl->it_lock), flags); | 286 | spin_lock_irqsave(&(tbl->it_lock), flags); |
276 | 287 | ||
@@ -285,9 +296,8 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, | |||
285 | } | 296 | } |
286 | /* Allocate iommu entries for that segment */ | 297 | /* Allocate iommu entries for that segment */ |
287 | vaddr = (unsigned long)page_address(s->page) + s->offset; | 298 | vaddr = (unsigned long)page_address(s->page) + s->offset; |
288 | npages = PAGE_ALIGN(vaddr + slen) - (vaddr & PAGE_MASK); | 299 | npages = iommu_num_pages(vaddr, slen); |
289 | npages >>= PAGE_SHIFT; | 300 | entry = iommu_range_alloc(tbl, npages, &handle, mask >> IOMMU_PAGE_SHIFT, 0); |
290 | entry = iommu_range_alloc(tbl, npages, &handle, mask >> PAGE_SHIFT, 0); | ||
291 | 301 | ||
292 | DBG(" - vaddr: %lx, size: %lx\n", vaddr, slen); | 302 | DBG(" - vaddr: %lx, size: %lx\n", vaddr, slen); |
293 | 303 | ||
@@ -301,14 +311,14 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, | |||
301 | 311 | ||
302 | /* Convert entry to a dma_addr_t */ | 312 | /* Convert entry to a dma_addr_t */ |
303 | entry += tbl->it_offset; | 313 | entry += tbl->it_offset; |
304 | dma_addr = entry << PAGE_SHIFT; | 314 | dma_addr = entry << IOMMU_PAGE_SHIFT; |
305 | dma_addr |= s->offset; | 315 | dma_addr |= (s->offset & ~IOMMU_PAGE_MASK); |
306 | 316 | ||
307 | DBG(" - %lx pages, entry: %lx, dma_addr: %lx\n", | 317 | DBG(" - %lu pages, entry: %lx, dma_addr: %lx\n", |
308 | npages, entry, dma_addr); | 318 | npages, entry, dma_addr); |
309 | 319 | ||
310 | /* Insert into HW table */ | 320 | /* Insert into HW table */ |
311 | ppc_md.tce_build(tbl, entry, npages, vaddr & PAGE_MASK, direction); | 321 | ppc_md.tce_build(tbl, entry, npages, vaddr & IOMMU_PAGE_MASK, direction); |
312 | 322 | ||
313 | /* If we are in an open segment, try merging */ | 323 | /* If we are in an open segment, try merging */ |
314 | if (segstart != s) { | 324 | if (segstart != s) { |
@@ -323,7 +333,7 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, | |||
323 | DBG(" can't merge, new segment.\n"); | 333 | DBG(" can't merge, new segment.\n"); |
324 | } else { | 334 | } else { |
325 | outs->dma_length += s->length; | 335 | outs->dma_length += s->length; |
326 | DBG(" merged, new len: %lx\n", outs->dma_length); | 336 | DBG(" merged, new len: %ux\n", outs->dma_length); |
327 | } | 337 | } |
328 | } | 338 | } |
329 | 339 | ||
@@ -367,9 +377,8 @@ int iommu_map_sg(struct device *dev, struct iommu_table *tbl, | |||
367 | if (s->dma_length != 0) { | 377 | if (s->dma_length != 0) { |
368 | unsigned long vaddr, npages; | 378 | unsigned long vaddr, npages; |
369 | 379 | ||
370 | vaddr = s->dma_address & PAGE_MASK; | 380 | vaddr = s->dma_address & IOMMU_PAGE_MASK; |
371 | npages = (PAGE_ALIGN(s->dma_address + s->dma_length) - vaddr) | 381 | npages = iommu_num_pages(s->dma_address, s->dma_length); |
372 | >> PAGE_SHIFT; | ||
373 | __iommu_free(tbl, vaddr, npages); | 382 | __iommu_free(tbl, vaddr, npages); |
374 | s->dma_address = DMA_ERROR_CODE; | 383 | s->dma_address = DMA_ERROR_CODE; |
375 | s->dma_length = 0; | 384 | s->dma_length = 0; |
@@ -398,8 +407,7 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist, | |||
398 | 407 | ||
399 | if (sglist->dma_length == 0) | 408 | if (sglist->dma_length == 0) |
400 | break; | 409 | break; |
401 | npages = (PAGE_ALIGN(dma_handle + sglist->dma_length) | 410 | npages = iommu_num_pages(dma_handle,sglist->dma_length); |
402 | - (dma_handle & PAGE_MASK)) >> PAGE_SHIFT; | ||
403 | __iommu_free(tbl, dma_handle, npages); | 411 | __iommu_free(tbl, dma_handle, npages); |
404 | sglist++; | 412 | sglist++; |
405 | } | 413 | } |
@@ -532,12 +540,11 @@ dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, | |||
532 | BUG_ON(direction == DMA_NONE); | 540 | BUG_ON(direction == DMA_NONE); |
533 | 541 | ||
534 | uaddr = (unsigned long)vaddr; | 542 | uaddr = (unsigned long)vaddr; |
535 | npages = PAGE_ALIGN(uaddr + size) - (uaddr & PAGE_MASK); | 543 | npages = iommu_num_pages(uaddr, size); |
536 | npages >>= PAGE_SHIFT; | ||
537 | 544 | ||
538 | if (tbl) { | 545 | if (tbl) { |
539 | dma_handle = iommu_alloc(tbl, vaddr, npages, direction, | 546 | dma_handle = iommu_alloc(tbl, vaddr, npages, direction, |
540 | mask >> PAGE_SHIFT, 0); | 547 | mask >> IOMMU_PAGE_SHIFT, 0); |
541 | if (dma_handle == DMA_ERROR_CODE) { | 548 | if (dma_handle == DMA_ERROR_CODE) { |
542 | if (printk_ratelimit()) { | 549 | if (printk_ratelimit()) { |
543 | printk(KERN_INFO "iommu_alloc failed, " | 550 | printk(KERN_INFO "iommu_alloc failed, " |
@@ -545,7 +552,7 @@ dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, | |||
545 | tbl, vaddr, npages); | 552 | tbl, vaddr, npages); |
546 | } | 553 | } |
547 | } else | 554 | } else |
548 | dma_handle |= (uaddr & ~PAGE_MASK); | 555 | dma_handle |= (uaddr & ~IOMMU_PAGE_MASK); |
549 | } | 556 | } |
550 | 557 | ||
551 | return dma_handle; | 558 | return dma_handle; |
@@ -554,11 +561,14 @@ dma_addr_t iommu_map_single(struct iommu_table *tbl, void *vaddr, | |||
554 | void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle, | 561 | void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle, |
555 | size_t size, enum dma_data_direction direction) | 562 | size_t size, enum dma_data_direction direction) |
556 | { | 563 | { |
564 | unsigned int npages; | ||
565 | |||
557 | BUG_ON(direction == DMA_NONE); | 566 | BUG_ON(direction == DMA_NONE); |
558 | 567 | ||
559 | if (tbl) | 568 | if (tbl) { |
560 | iommu_free(tbl, dma_handle, (PAGE_ALIGN(dma_handle + size) - | 569 | npages = iommu_num_pages(dma_handle, size); |
561 | (dma_handle & PAGE_MASK)) >> PAGE_SHIFT); | 570 | iommu_free(tbl, dma_handle, npages); |
571 | } | ||
562 | } | 572 | } |
563 | 573 | ||
564 | /* Allocates a contiguous real buffer and creates mappings over it. | 574 | /* Allocates a contiguous real buffer and creates mappings over it. |
@@ -570,11 +580,11 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, | |||
570 | { | 580 | { |
571 | void *ret = NULL; | 581 | void *ret = NULL; |
572 | dma_addr_t mapping; | 582 | dma_addr_t mapping; |
573 | unsigned int npages, order; | 583 | unsigned int order; |
584 | unsigned int nio_pages, io_order; | ||
574 | struct page *page; | 585 | struct page *page; |
575 | 586 | ||
576 | size = PAGE_ALIGN(size); | 587 | size = PAGE_ALIGN(size); |
577 | npages = size >> PAGE_SHIFT; | ||
578 | order = get_order(size); | 588 | order = get_order(size); |
579 | 589 | ||
580 | /* | 590 | /* |
@@ -598,8 +608,10 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, | |||
598 | memset(ret, 0, size); | 608 | memset(ret, 0, size); |
599 | 609 | ||
600 | /* Set up tces to cover the allocated range */ | 610 | /* Set up tces to cover the allocated range */ |
601 | mapping = iommu_alloc(tbl, ret, npages, DMA_BIDIRECTIONAL, | 611 | nio_pages = size >> IOMMU_PAGE_SHIFT; |
602 | mask >> PAGE_SHIFT, order); | 612 | io_order = get_iommu_order(size); |
613 | mapping = iommu_alloc(tbl, ret, nio_pages, DMA_BIDIRECTIONAL, | ||
614 | mask >> IOMMU_PAGE_SHIFT, io_order); | ||
603 | if (mapping == DMA_ERROR_CODE) { | 615 | if (mapping == DMA_ERROR_CODE) { |
604 | free_pages((unsigned long)ret, order); | 616 | free_pages((unsigned long)ret, order); |
605 | return NULL; | 617 | return NULL; |
@@ -611,12 +623,13 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, | |||
611 | void iommu_free_coherent(struct iommu_table *tbl, size_t size, | 623 | void iommu_free_coherent(struct iommu_table *tbl, size_t size, |
612 | void *vaddr, dma_addr_t dma_handle) | 624 | void *vaddr, dma_addr_t dma_handle) |
613 | { | 625 | { |
614 | unsigned int npages; | ||
615 | |||
616 | if (tbl) { | 626 | if (tbl) { |
627 | unsigned int nio_pages; | ||
628 | |||
629 | size = PAGE_ALIGN(size); | ||
630 | nio_pages = size >> IOMMU_PAGE_SHIFT; | ||
631 | iommu_free(tbl, dma_handle, nio_pages); | ||
617 | size = PAGE_ALIGN(size); | 632 | size = PAGE_ALIGN(size); |
618 | npages = size >> PAGE_SHIFT; | ||
619 | iommu_free(tbl, dma_handle, npages); | ||
620 | free_pages((unsigned long)vaddr, get_order(size)); | 633 | free_pages((unsigned long)vaddr, get_order(size)); |
621 | } | 634 | } |
622 | } | 635 | } |
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index 88fd73fdf048..412bea3cf813 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S | |||
@@ -102,80 +102,6 @@ _GLOBAL(reloc_got2) | |||
102 | blr | 102 | blr |
103 | 103 | ||
104 | /* | 104 | /* |
105 | * identify_cpu, | ||
106 | * called with r3 = data offset and r4 = CPU number | ||
107 | * doesn't change r3 | ||
108 | */ | ||
109 | _GLOBAL(identify_cpu) | ||
110 | addis r8,r3,cpu_specs@ha | ||
111 | addi r8,r8,cpu_specs@l | ||
112 | mfpvr r7 | ||
113 | 1: | ||
114 | lwz r5,CPU_SPEC_PVR_MASK(r8) | ||
115 | and r5,r5,r7 | ||
116 | lwz r6,CPU_SPEC_PVR_VALUE(r8) | ||
117 | cmplw 0,r6,r5 | ||
118 | beq 1f | ||
119 | addi r8,r8,CPU_SPEC_ENTRY_SIZE | ||
120 | b 1b | ||
121 | 1: | ||
122 | addis r6,r3,cur_cpu_spec@ha | ||
123 | addi r6,r6,cur_cpu_spec@l | ||
124 | sub r8,r8,r3 | ||
125 | stw r8,0(r6) | ||
126 | blr | ||
127 | |||
128 | /* | ||
129 | * do_cpu_ftr_fixups - goes through the list of CPU feature fixups | ||
130 | * and writes nop's over sections of code that don't apply for this cpu. | ||
131 | * r3 = data offset (not changed) | ||
132 | */ | ||
133 | _GLOBAL(do_cpu_ftr_fixups) | ||
134 | /* Get CPU 0 features */ | ||
135 | addis r6,r3,cur_cpu_spec@ha | ||
136 | addi r6,r6,cur_cpu_spec@l | ||
137 | lwz r4,0(r6) | ||
138 | add r4,r4,r3 | ||
139 | lwz r4,CPU_SPEC_FEATURES(r4) | ||
140 | |||
141 | /* Get the fixup table */ | ||
142 | addis r6,r3,__start___ftr_fixup@ha | ||
143 | addi r6,r6,__start___ftr_fixup@l | ||
144 | addis r7,r3,__stop___ftr_fixup@ha | ||
145 | addi r7,r7,__stop___ftr_fixup@l | ||
146 | |||
147 | /* Do the fixup */ | ||
148 | 1: cmplw 0,r6,r7 | ||
149 | bgelr | ||
150 | addi r6,r6,16 | ||
151 | lwz r8,-16(r6) /* mask */ | ||
152 | and r8,r8,r4 | ||
153 | lwz r9,-12(r6) /* value */ | ||
154 | cmplw 0,r8,r9 | ||
155 | beq 1b | ||
156 | lwz r8,-8(r6) /* section begin */ | ||
157 | lwz r9,-4(r6) /* section end */ | ||
158 | subf. r9,r8,r9 | ||
159 | beq 1b | ||
160 | /* write nops over the section of code */ | ||
161 | /* todo: if large section, add a branch at the start of it */ | ||
162 | srwi r9,r9,2 | ||
163 | mtctr r9 | ||
164 | add r8,r8,r3 | ||
165 | lis r0,0x60000000@h /* nop */ | ||
166 | 3: stw r0,0(r8) | ||
167 | andi. r10,r4,CPU_FTR_SPLIT_ID_CACHE@l | ||
168 | beq 2f | ||
169 | dcbst 0,r8 /* suboptimal, but simpler */ | ||
170 | sync | ||
171 | icbi 0,r8 | ||
172 | 2: addi r8,r8,4 | ||
173 | bdnz 3b | ||
174 | sync /* additional sync needed on g4 */ | ||
175 | isync | ||
176 | b 1b | ||
177 | |||
178 | /* | ||
179 | * call_setup_cpu - call the setup_cpu function for this cpu | 105 | * call_setup_cpu - call the setup_cpu function for this cpu |
180 | * r3 = data offset, r24 = cpu number | 106 | * r3 = data offset, r24 = cpu number |
181 | * | 107 | * |
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index c70e20708a1f..21fd2c662a99 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S | |||
@@ -246,130 +246,6 @@ _GLOBAL(__flush_dcache_icache) | |||
246 | isync | 246 | isync |
247 | blr | 247 | blr |
248 | 248 | ||
249 | /* | ||
250 | * identify_cpu and calls setup_cpu | ||
251 | * In: r3 = base of the cpu_specs array | ||
252 | * r4 = address of cur_cpu_spec | ||
253 | * r5 = relocation offset | ||
254 | */ | ||
255 | _GLOBAL(identify_cpu) | ||
256 | mfpvr r7 | ||
257 | 1: | ||
258 | lwz r8,CPU_SPEC_PVR_MASK(r3) | ||
259 | and r8,r8,r7 | ||
260 | lwz r9,CPU_SPEC_PVR_VALUE(r3) | ||
261 | cmplw 0,r9,r8 | ||
262 | beq 1f | ||
263 | addi r3,r3,CPU_SPEC_ENTRY_SIZE | ||
264 | b 1b | ||
265 | 1: | ||
266 | sub r0,r3,r5 | ||
267 | std r0,0(r4) | ||
268 | ld r4,CPU_SPEC_SETUP(r3) | ||
269 | cmpdi 0,r4,0 | ||
270 | add r4,r4,r5 | ||
271 | beqlr | ||
272 | ld r4,0(r4) | ||
273 | add r4,r4,r5 | ||
274 | mtctr r4 | ||
275 | /* Calling convention for cpu setup is r3=offset, r4=cur_cpu_spec */ | ||
276 | mr r4,r3 | ||
277 | mr r3,r5 | ||
278 | bctr | ||
279 | |||
280 | /* | ||
281 | * do_cpu_ftr_fixups - goes through the list of CPU feature fixups | ||
282 | * and writes nop's over sections of code that don't apply for this cpu. | ||
283 | * r3 = data offset (not changed) | ||
284 | */ | ||
285 | _GLOBAL(do_cpu_ftr_fixups) | ||
286 | /* Get CPU 0 features */ | ||
287 | LOAD_REG_IMMEDIATE(r6,cur_cpu_spec) | ||
288 | sub r6,r6,r3 | ||
289 | ld r4,0(r6) | ||
290 | sub r4,r4,r3 | ||
291 | ld r4,CPU_SPEC_FEATURES(r4) | ||
292 | /* Get the fixup table */ | ||
293 | LOAD_REG_IMMEDIATE(r6,__start___ftr_fixup) | ||
294 | sub r6,r6,r3 | ||
295 | LOAD_REG_IMMEDIATE(r7,__stop___ftr_fixup) | ||
296 | sub r7,r7,r3 | ||
297 | /* Do the fixup */ | ||
298 | 1: cmpld r6,r7 | ||
299 | bgelr | ||
300 | addi r6,r6,32 | ||
301 | ld r8,-32(r6) /* mask */ | ||
302 | and r8,r8,r4 | ||
303 | ld r9,-24(r6) /* value */ | ||
304 | cmpld r8,r9 | ||
305 | beq 1b | ||
306 | ld r8,-16(r6) /* section begin */ | ||
307 | ld r9,-8(r6) /* section end */ | ||
308 | subf. r9,r8,r9 | ||
309 | beq 1b | ||
310 | /* write nops over the section of code */ | ||
311 | /* todo: if large section, add a branch at the start of it */ | ||
312 | srwi r9,r9,2 | ||
313 | mtctr r9 | ||
314 | sub r8,r8,r3 | ||
315 | lis r0,0x60000000@h /* nop */ | ||
316 | 3: stw r0,0(r8) | ||
317 | andi. r10,r4,CPU_FTR_SPLIT_ID_CACHE@l | ||
318 | beq 2f | ||
319 | dcbst 0,r8 /* suboptimal, but simpler */ | ||
320 | sync | ||
321 | icbi 0,r8 | ||
322 | 2: addi r8,r8,4 | ||
323 | bdnz 3b | ||
324 | sync /* additional sync needed on g4 */ | ||
325 | isync | ||
326 | b 1b | ||
327 | |||
328 | /* | ||
329 | * do_fw_ftr_fixups - goes through the list of firmware feature fixups | ||
330 | * and writes nop's over sections of code that don't apply for this firmware. | ||
331 | * r3 = data offset (not changed) | ||
332 | */ | ||
333 | _GLOBAL(do_fw_ftr_fixups) | ||
334 | /* Get firmware features */ | ||
335 | LOAD_REG_IMMEDIATE(r6,powerpc_firmware_features) | ||
336 | sub r6,r6,r3 | ||
337 | ld r4,0(r6) | ||
338 | /* Get the fixup table */ | ||
339 | LOAD_REG_IMMEDIATE(r6,__start___fw_ftr_fixup) | ||
340 | sub r6,r6,r3 | ||
341 | LOAD_REG_IMMEDIATE(r7,__stop___fw_ftr_fixup) | ||
342 | sub r7,r7,r3 | ||
343 | /* Do the fixup */ | ||
344 | 1: cmpld r6,r7 | ||
345 | bgelr | ||
346 | addi r6,r6,32 | ||
347 | ld r8,-32(r6) /* mask */ | ||
348 | and r8,r8,r4 | ||
349 | ld r9,-24(r6) /* value */ | ||
350 | cmpld r8,r9 | ||
351 | beq 1b | ||
352 | ld r8,-16(r6) /* section begin */ | ||
353 | ld r9,-8(r6) /* section end */ | ||
354 | subf. r9,r8,r9 | ||
355 | beq 1b | ||
356 | /* write nops over the section of code */ | ||
357 | /* todo: if large section, add a branch at the start of it */ | ||
358 | srwi r9,r9,2 | ||
359 | mtctr r9 | ||
360 | sub r8,r8,r3 | ||
361 | lis r0,0x60000000@h /* nop */ | ||
362 | 3: stw r0,0(r8) | ||
363 | BEGIN_FTR_SECTION | ||
364 | dcbst 0,r8 /* suboptimal, but simpler */ | ||
365 | sync | ||
366 | icbi 0,r8 | ||
367 | END_FTR_SECTION_IFSET(CPU_FTR_SPLIT_ID_CACHE) | ||
368 | addi r8,r8,4 | ||
369 | bdnz 3b | ||
370 | sync /* additional sync needed on g4 */ | ||
371 | isync | ||
372 | b 1b | ||
373 | 249 | ||
374 | #if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) | 250 | #if defined(CONFIG_PPC_PMAC) || defined(CONFIG_PPC_MAPLE) |
375 | /* | 251 | /* |
diff --git a/arch/powerpc/kernel/module_32.c b/arch/powerpc/kernel/module_32.c index 92f4e5f64f02..e2c3c6a85f33 100644 --- a/arch/powerpc/kernel/module_32.c +++ b/arch/powerpc/kernel/module_32.c | |||
@@ -24,6 +24,8 @@ | |||
24 | #include <linux/kernel.h> | 24 | #include <linux/kernel.h> |
25 | #include <linux/cache.h> | 25 | #include <linux/cache.h> |
26 | 26 | ||
27 | #include "setup.h" | ||
28 | |||
27 | #if 0 | 29 | #if 0 |
28 | #define DEBUGP printk | 30 | #define DEBUGP printk |
29 | #else | 31 | #else |
@@ -269,33 +271,50 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, | |||
269 | return 0; | 271 | return 0; |
270 | } | 272 | } |
271 | 273 | ||
274 | static const Elf_Shdr *find_section(const Elf_Ehdr *hdr, | ||
275 | const Elf_Shdr *sechdrs, | ||
276 | const char *name) | ||
277 | { | ||
278 | char *secstrings; | ||
279 | unsigned int i; | ||
280 | |||
281 | secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; | ||
282 | for (i = 1; i < hdr->e_shnum; i++) | ||
283 | if (strcmp(secstrings+sechdrs[i].sh_name, name) == 0) | ||
284 | return &sechdrs[i]; | ||
285 | return NULL; | ||
286 | } | ||
287 | |||
272 | int module_finalize(const Elf_Ehdr *hdr, | 288 | int module_finalize(const Elf_Ehdr *hdr, |
273 | const Elf_Shdr *sechdrs, | 289 | const Elf_Shdr *sechdrs, |
274 | struct module *me) | 290 | struct module *me) |
275 | { | 291 | { |
276 | char *secstrings; | 292 | const Elf_Shdr *sect; |
277 | unsigned int i; | ||
278 | 293 | ||
279 | me->arch.bug_table = NULL; | 294 | me->arch.bug_table = NULL; |
280 | me->arch.num_bugs = 0; | 295 | me->arch.num_bugs = 0; |
281 | 296 | ||
282 | /* Find the __bug_table section, if present */ | 297 | /* Find the __bug_table section, if present */ |
283 | secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; | 298 | sect = find_section(hdr, sechdrs, "__bug_table"); |
284 | for (i = 1; i < hdr->e_shnum; i++) { | 299 | if (sect != NULL) { |
285 | if (strcmp(secstrings+sechdrs[i].sh_name, "__bug_table")) | 300 | me->arch.bug_table = (void *) sect->sh_addr; |
286 | continue; | 301 | me->arch.num_bugs = sect->sh_size / sizeof(struct bug_entry); |
287 | me->arch.bug_table = (void *) sechdrs[i].sh_addr; | ||
288 | me->arch.num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry); | ||
289 | break; | ||
290 | } | 302 | } |
291 | 303 | ||
292 | /* | 304 | /* |
293 | * Strictly speaking this should have a spinlock to protect against | 305 | * Strictly speaking this should have a spinlock to protect against |
294 | * traversals, but since we only traverse on BUG()s, a spinlock | 306 | * traversals, but since we only traverse on BUG()s, a spinlock |
295 | * could potentially lead to deadlock and thus be counter-productive. | 307 | * could potentially lead to deadlock and thus be counter-productive. |
296 | */ | 308 | */ |
297 | list_add(&me->arch.bug_list, &module_bug_list); | 309 | list_add(&me->arch.bug_list, &module_bug_list); |
298 | 310 | ||
311 | /* Apply feature fixups */ | ||
312 | sect = find_section(hdr, sechdrs, "__ftr_fixup"); | ||
313 | if (sect != NULL) | ||
314 | do_feature_fixups(cur_cpu_spec->cpu_features, | ||
315 | (void *)sect->sh_addr, | ||
316 | (void *)sect->sh_addr + sect->sh_size); | ||
317 | |||
299 | return 0; | 318 | return 0; |
300 | } | 319 | } |
301 | 320 | ||
diff --git a/arch/powerpc/kernel/module_64.c b/arch/powerpc/kernel/module_64.c index ba34001fca8e..8dd1f0aae5d6 100644 --- a/arch/powerpc/kernel/module_64.c +++ b/arch/powerpc/kernel/module_64.c | |||
@@ -22,6 +22,9 @@ | |||
22 | #include <linux/vmalloc.h> | 22 | #include <linux/vmalloc.h> |
23 | #include <asm/module.h> | 23 | #include <asm/module.h> |
24 | #include <asm/uaccess.h> | 24 | #include <asm/uaccess.h> |
25 | #include <asm/firmware.h> | ||
26 | |||
27 | #include "setup.h" | ||
25 | 28 | ||
26 | /* FIXME: We don't do .init separately. To do this, we'd need to have | 29 | /* FIXME: We don't do .init separately. To do this, we'd need to have |
27 | a separate r2 value in the init and core section, and stub between | 30 | a separate r2 value in the init and core section, and stub between |
@@ -400,6 +403,11 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, | |||
400 | | (value & 0x03fffffc); | 403 | | (value & 0x03fffffc); |
401 | break; | 404 | break; |
402 | 405 | ||
406 | case R_PPC64_REL64: | ||
407 | /* 64 bits relative (used by features fixups) */ | ||
408 | *location = value - (unsigned long)location; | ||
409 | break; | ||
410 | |||
403 | default: | 411 | default: |
404 | printk("%s: Unknown ADD relocation: %lu\n", | 412 | printk("%s: Unknown ADD relocation: %lu\n", |
405 | me->name, | 413 | me->name, |
@@ -413,23 +421,33 @@ int apply_relocate_add(Elf64_Shdr *sechdrs, | |||
413 | 421 | ||
414 | LIST_HEAD(module_bug_list); | 422 | LIST_HEAD(module_bug_list); |
415 | 423 | ||
416 | int module_finalize(const Elf_Ehdr *hdr, | 424 | static const Elf_Shdr *find_section(const Elf_Ehdr *hdr, |
417 | const Elf_Shdr *sechdrs, struct module *me) | 425 | const Elf_Shdr *sechdrs, |
426 | const char *name) | ||
418 | { | 427 | { |
419 | char *secstrings; | 428 | char *secstrings; |
420 | unsigned int i; | 429 | unsigned int i; |
421 | 430 | ||
431 | secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; | ||
432 | for (i = 1; i < hdr->e_shnum; i++) | ||
433 | if (strcmp(secstrings+sechdrs[i].sh_name, name) == 0) | ||
434 | return &sechdrs[i]; | ||
435 | return NULL; | ||
436 | } | ||
437 | |||
438 | int module_finalize(const Elf_Ehdr *hdr, | ||
439 | const Elf_Shdr *sechdrs, struct module *me) | ||
440 | { | ||
441 | const Elf_Shdr *sect; | ||
442 | |||
422 | me->arch.bug_table = NULL; | 443 | me->arch.bug_table = NULL; |
423 | me->arch.num_bugs = 0; | 444 | me->arch.num_bugs = 0; |
424 | 445 | ||
425 | /* Find the __bug_table section, if present */ | 446 | /* Find the __bug_table section, if present */ |
426 | secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; | 447 | sect = find_section(hdr, sechdrs, "__bug_table"); |
427 | for (i = 1; i < hdr->e_shnum; i++) { | 448 | if (sect != NULL) { |
428 | if (strcmp(secstrings+sechdrs[i].sh_name, "__bug_table")) | 449 | me->arch.bug_table = (void *) sect->sh_addr; |
429 | continue; | 450 | me->arch.num_bugs = sect->sh_size / sizeof(struct bug_entry); |
430 | me->arch.bug_table = (void *) sechdrs[i].sh_addr; | ||
431 | me->arch.num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry); | ||
432 | break; | ||
433 | } | 451 | } |
434 | 452 | ||
435 | /* | 453 | /* |
@@ -439,6 +457,19 @@ int module_finalize(const Elf_Ehdr *hdr, | |||
439 | */ | 457 | */ |
440 | list_add(&me->arch.bug_list, &module_bug_list); | 458 | list_add(&me->arch.bug_list, &module_bug_list); |
441 | 459 | ||
460 | /* Apply feature fixups */ | ||
461 | sect = find_section(hdr, sechdrs, "__ftr_fixup"); | ||
462 | if (sect != NULL) | ||
463 | do_feature_fixups(cur_cpu_spec->cpu_features, | ||
464 | (void *)sect->sh_addr, | ||
465 | (void *)sect->sh_addr + sect->sh_size); | ||
466 | |||
467 | sect = find_section(hdr, sechdrs, "__fw_ftr_fixup"); | ||
468 | if (sect != NULL) | ||
469 | do_feature_fixups(powerpc_firmware_features, | ||
470 | (void *)sect->sh_addr, | ||
471 | (void *)sect->sh_addr + sect->sh_size); | ||
472 | |||
442 | return 0; | 473 | return 0; |
443 | } | 474 | } |
444 | 475 | ||
diff --git a/arch/powerpc/kernel/perfmon_fsl_booke.c b/arch/powerpc/kernel/perfmon_fsl_booke.c deleted file mode 100644 index e0dcf2b41fbe..000000000000 --- a/arch/powerpc/kernel/perfmon_fsl_booke.c +++ /dev/null | |||
@@ -1,221 +0,0 @@ | |||
1 | /* arch/powerpc/kernel/perfmon_fsl_booke.c | ||
2 | * Freescale Book-E Performance Monitor code | ||
3 | * | ||
4 | * Author: Andy Fleming | ||
5 | * Copyright (c) 2004 Freescale Semiconductor, Inc | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version | ||
10 | * 2 of the License, or (at your option) any later version. | ||
11 | */ | ||
12 | |||
13 | #include <linux/errno.h> | ||
14 | #include <linux/sched.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/mm.h> | ||
17 | #include <linux/stddef.h> | ||
18 | #include <linux/unistd.h> | ||
19 | #include <linux/ptrace.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/user.h> | ||
22 | #include <linux/a.out.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/module.h> | ||
26 | #include <linux/prctl.h> | ||
27 | |||
28 | #include <asm/pgtable.h> | ||
29 | #include <asm/uaccess.h> | ||
30 | #include <asm/system.h> | ||
31 | #include <asm/io.h> | ||
32 | #include <asm/reg.h> | ||
33 | #include <asm/xmon.h> | ||
34 | #include <asm/pmc.h> | ||
35 | |||
36 | static inline u32 get_pmlca(int ctr); | ||
37 | static inline void set_pmlca(int ctr, u32 pmlca); | ||
38 | |||
39 | static inline u32 get_pmlca(int ctr) | ||
40 | { | ||
41 | u32 pmlca; | ||
42 | |||
43 | switch (ctr) { | ||
44 | case 0: | ||
45 | pmlca = mfpmr(PMRN_PMLCA0); | ||
46 | break; | ||
47 | case 1: | ||
48 | pmlca = mfpmr(PMRN_PMLCA1); | ||
49 | break; | ||
50 | case 2: | ||
51 | pmlca = mfpmr(PMRN_PMLCA2); | ||
52 | break; | ||
53 | case 3: | ||
54 | pmlca = mfpmr(PMRN_PMLCA3); | ||
55 | break; | ||
56 | default: | ||
57 | panic("Bad ctr number\n"); | ||
58 | } | ||
59 | |||
60 | return pmlca; | ||
61 | } | ||
62 | |||
63 | static inline void set_pmlca(int ctr, u32 pmlca) | ||
64 | { | ||
65 | switch (ctr) { | ||
66 | case 0: | ||
67 | mtpmr(PMRN_PMLCA0, pmlca); | ||
68 | break; | ||
69 | case 1: | ||
70 | mtpmr(PMRN_PMLCA1, pmlca); | ||
71 | break; | ||
72 | case 2: | ||
73 | mtpmr(PMRN_PMLCA2, pmlca); | ||
74 | break; | ||
75 | case 3: | ||
76 | mtpmr(PMRN_PMLCA3, pmlca); | ||
77 | break; | ||
78 | default: | ||
79 | panic("Bad ctr number\n"); | ||
80 | } | ||
81 | } | ||
82 | |||
83 | void init_pmc_stop(int ctr) | ||
84 | { | ||
85 | u32 pmlca = (PMLCA_FC | PMLCA_FCS | PMLCA_FCU | | ||
86 | PMLCA_FCM1 | PMLCA_FCM0); | ||
87 | u32 pmlcb = 0; | ||
88 | |||
89 | switch (ctr) { | ||
90 | case 0: | ||
91 | mtpmr(PMRN_PMLCA0, pmlca); | ||
92 | mtpmr(PMRN_PMLCB0, pmlcb); | ||
93 | break; | ||
94 | case 1: | ||
95 | mtpmr(PMRN_PMLCA1, pmlca); | ||
96 | mtpmr(PMRN_PMLCB1, pmlcb); | ||
97 | break; | ||
98 | case 2: | ||
99 | mtpmr(PMRN_PMLCA2, pmlca); | ||
100 | mtpmr(PMRN_PMLCB2, pmlcb); | ||
101 | break; | ||
102 | case 3: | ||
103 | mtpmr(PMRN_PMLCA3, pmlca); | ||
104 | mtpmr(PMRN_PMLCB3, pmlcb); | ||
105 | break; | ||
106 | default: | ||
107 | panic("Bad ctr number!\n"); | ||
108 | } | ||
109 | } | ||
110 | |||
111 | void set_pmc_event(int ctr, int event) | ||
112 | { | ||
113 | u32 pmlca; | ||
114 | |||
115 | pmlca = get_pmlca(ctr); | ||
116 | |||
117 | pmlca = (pmlca & ~PMLCA_EVENT_MASK) | | ||
118 | ((event << PMLCA_EVENT_SHIFT) & | ||
119 | PMLCA_EVENT_MASK); | ||
120 | |||
121 | set_pmlca(ctr, pmlca); | ||
122 | } | ||
123 | |||
124 | void set_pmc_user_kernel(int ctr, int user, int kernel) | ||
125 | { | ||
126 | u32 pmlca; | ||
127 | |||
128 | pmlca = get_pmlca(ctr); | ||
129 | |||
130 | if(user) | ||
131 | pmlca &= ~PMLCA_FCU; | ||
132 | else | ||
133 | pmlca |= PMLCA_FCU; | ||
134 | |||
135 | if(kernel) | ||
136 | pmlca &= ~PMLCA_FCS; | ||
137 | else | ||
138 | pmlca |= PMLCA_FCS; | ||
139 | |||
140 | set_pmlca(ctr, pmlca); | ||
141 | } | ||
142 | |||
143 | void set_pmc_marked(int ctr, int mark0, int mark1) | ||
144 | { | ||
145 | u32 pmlca = get_pmlca(ctr); | ||
146 | |||
147 | if(mark0) | ||
148 | pmlca &= ~PMLCA_FCM0; | ||
149 | else | ||
150 | pmlca |= PMLCA_FCM0; | ||
151 | |||
152 | if(mark1) | ||
153 | pmlca &= ~PMLCA_FCM1; | ||
154 | else | ||
155 | pmlca |= PMLCA_FCM1; | ||
156 | |||
157 | set_pmlca(ctr, pmlca); | ||
158 | } | ||
159 | |||
160 | void pmc_start_ctr(int ctr, int enable) | ||
161 | { | ||
162 | u32 pmlca = get_pmlca(ctr); | ||
163 | |||
164 | pmlca &= ~PMLCA_FC; | ||
165 | |||
166 | if (enable) | ||
167 | pmlca |= PMLCA_CE; | ||
168 | else | ||
169 | pmlca &= ~PMLCA_CE; | ||
170 | |||
171 | set_pmlca(ctr, pmlca); | ||
172 | } | ||
173 | |||
174 | void pmc_start_ctrs(int enable) | ||
175 | { | ||
176 | u32 pmgc0 = mfpmr(PMRN_PMGC0); | ||
177 | |||
178 | pmgc0 &= ~PMGC0_FAC; | ||
179 | pmgc0 |= PMGC0_FCECE; | ||
180 | |||
181 | if (enable) | ||
182 | pmgc0 |= PMGC0_PMIE; | ||
183 | else | ||
184 | pmgc0 &= ~PMGC0_PMIE; | ||
185 | |||
186 | mtpmr(PMRN_PMGC0, pmgc0); | ||
187 | } | ||
188 | |||
189 | void pmc_stop_ctrs(void) | ||
190 | { | ||
191 | u32 pmgc0 = mfpmr(PMRN_PMGC0); | ||
192 | |||
193 | pmgc0 |= PMGC0_FAC; | ||
194 | |||
195 | pmgc0 &= ~(PMGC0_PMIE | PMGC0_FCECE); | ||
196 | |||
197 | mtpmr(PMRN_PMGC0, pmgc0); | ||
198 | } | ||
199 | |||
200 | void dump_pmcs(void) | ||
201 | { | ||
202 | printk("pmgc0: %x\n", mfpmr(PMRN_PMGC0)); | ||
203 | printk("pmc\t\tpmlca\t\tpmlcb\n"); | ||
204 | printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC0), | ||
205 | mfpmr(PMRN_PMLCA0), mfpmr(PMRN_PMLCB0)); | ||
206 | printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC1), | ||
207 | mfpmr(PMRN_PMLCA1), mfpmr(PMRN_PMLCB1)); | ||
208 | printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC2), | ||
209 | mfpmr(PMRN_PMLCA2), mfpmr(PMRN_PMLCB2)); | ||
210 | printk("%8x\t%8x\t%8x\n", mfpmr(PMRN_PMC3), | ||
211 | mfpmr(PMRN_PMLCA3), mfpmr(PMRN_PMLCB3)); | ||
212 | } | ||
213 | |||
214 | EXPORT_SYMBOL(init_pmc_stop); | ||
215 | EXPORT_SYMBOL(set_pmc_event); | ||
216 | EXPORT_SYMBOL(set_pmc_user_kernel); | ||
217 | EXPORT_SYMBOL(set_pmc_marked); | ||
218 | EXPORT_SYMBOL(pmc_start_ctr); | ||
219 | EXPORT_SYMBOL(pmc_start_ctrs); | ||
220 | EXPORT_SYMBOL(pmc_stop_ctrs); | ||
221 | EXPORT_SYMBOL(dump_pmcs); | ||
diff --git a/arch/powerpc/kernel/pmc.c b/arch/powerpc/kernel/pmc.c index a0a2efadeabf..3d8f6f44641e 100644 --- a/arch/powerpc/kernel/pmc.c +++ b/arch/powerpc/kernel/pmc.c | |||
@@ -71,7 +71,7 @@ int reserve_pmc_hardware(perf_irq_t new_perf_irq) | |||
71 | } | 71 | } |
72 | 72 | ||
73 | pmc_owner_caller = __builtin_return_address(0); | 73 | pmc_owner_caller = __builtin_return_address(0); |
74 | perf_irq = new_perf_irq ? : dummy_perf; | 74 | perf_irq = new_perf_irq ? new_perf_irq : dummy_perf; |
75 | 75 | ||
76 | out: | 76 | out: |
77 | spin_unlock(&pmc_owner_lock); | 77 | spin_unlock(&pmc_owner_lock); |
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 865b9648d0d5..bdb412d4b748 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -1014,7 +1014,7 @@ EXPORT_SYMBOL(find_all_nodes); | |||
1014 | /** Checks if the given "compat" string matches one of the strings in | 1014 | /** Checks if the given "compat" string matches one of the strings in |
1015 | * the device's "compatible" property | 1015 | * the device's "compatible" property |
1016 | */ | 1016 | */ |
1017 | int device_is_compatible(struct device_node *device, const char *compat) | 1017 | int device_is_compatible(const struct device_node *device, const char *compat) |
1018 | { | 1018 | { |
1019 | const char* cp; | 1019 | const char* cp; |
1020 | int cplen, l; | 1020 | int cplen, l; |
@@ -1491,7 +1491,8 @@ static int __init prom_reconfig_setup(void) | |||
1491 | __initcall(prom_reconfig_setup); | 1491 | __initcall(prom_reconfig_setup); |
1492 | #endif | 1492 | #endif |
1493 | 1493 | ||
1494 | struct property *of_find_property(struct device_node *np, const char *name, | 1494 | struct property *of_find_property(const struct device_node *np, |
1495 | const char *name, | ||
1495 | int *lenp) | 1496 | int *lenp) |
1496 | { | 1497 | { |
1497 | struct property *pp; | 1498 | struct property *pp; |
@@ -1512,7 +1513,8 @@ struct property *of_find_property(struct device_node *np, const char *name, | |||
1512 | * Find a property with a given name for a given node | 1513 | * Find a property with a given name for a given node |
1513 | * and return the value. | 1514 | * and return the value. |
1514 | */ | 1515 | */ |
1515 | const void *get_property(struct device_node *np, const char *name, int *lenp) | 1516 | const void *get_property(const struct device_node *np, const char *name, |
1517 | int *lenp) | ||
1516 | { | 1518 | { |
1517 | struct property *pp = of_find_property(np,name,lenp); | 1519 | struct property *pp = of_find_property(np,name,lenp); |
1518 | return pp ? pp->value : NULL; | 1520 | return pp ? pp->value : NULL; |
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index 1442b63a75da..6f6fc977cb39 100644 --- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c | |||
@@ -72,6 +72,10 @@ | |||
72 | #define VALIDATE_BUF_SIZE 4096 | 72 | #define VALIDATE_BUF_SIZE 4096 |
73 | #define RTAS_MSG_MAXLEN 64 | 73 | #define RTAS_MSG_MAXLEN 64 |
74 | 74 | ||
75 | /* Quirk - RTAS requires 4k list length and block size */ | ||
76 | #define RTAS_BLKLIST_LENGTH 4096 | ||
77 | #define RTAS_BLK_SIZE 4096 | ||
78 | |||
75 | struct flash_block { | 79 | struct flash_block { |
76 | char *data; | 80 | char *data; |
77 | unsigned long length; | 81 | unsigned long length; |
@@ -83,7 +87,7 @@ struct flash_block { | |||
83 | * into a version/length and translate the pointers | 87 | * into a version/length and translate the pointers |
84 | * to absolute. | 88 | * to absolute. |
85 | */ | 89 | */ |
86 | #define FLASH_BLOCKS_PER_NODE ((PAGE_SIZE - 16) / sizeof(struct flash_block)) | 90 | #define FLASH_BLOCKS_PER_NODE ((RTAS_BLKLIST_LENGTH - 16) / sizeof(struct flash_block)) |
87 | struct flash_block_list { | 91 | struct flash_block_list { |
88 | unsigned long num_blocks; | 92 | unsigned long num_blocks; |
89 | struct flash_block_list *next; | 93 | struct flash_block_list *next; |
@@ -96,6 +100,9 @@ struct flash_block_list_header { /* just the header of flash_block_list */ | |||
96 | 100 | ||
97 | static struct flash_block_list_header rtas_firmware_flash_list = {0, NULL}; | 101 | static struct flash_block_list_header rtas_firmware_flash_list = {0, NULL}; |
98 | 102 | ||
103 | /* Use slab cache to guarantee 4k alignment */ | ||
104 | static kmem_cache_t *flash_block_cache = NULL; | ||
105 | |||
99 | #define FLASH_BLOCK_LIST_VERSION (1UL) | 106 | #define FLASH_BLOCK_LIST_VERSION (1UL) |
100 | 107 | ||
101 | /* Local copy of the flash block list. | 108 | /* Local copy of the flash block list. |
@@ -153,7 +160,7 @@ static int flash_list_valid(struct flash_block_list *flist) | |||
153 | return FLASH_IMG_NULL_DATA; | 160 | return FLASH_IMG_NULL_DATA; |
154 | } | 161 | } |
155 | block_size = f->blocks[i].length; | 162 | block_size = f->blocks[i].length; |
156 | if (block_size <= 0 || block_size > PAGE_SIZE) { | 163 | if (block_size <= 0 || block_size > RTAS_BLK_SIZE) { |
157 | return FLASH_IMG_BAD_LEN; | 164 | return FLASH_IMG_BAD_LEN; |
158 | } | 165 | } |
159 | image_size += block_size; | 166 | image_size += block_size; |
@@ -177,9 +184,9 @@ static void free_flash_list(struct flash_block_list *f) | |||
177 | 184 | ||
178 | while (f) { | 185 | while (f) { |
179 | for (i = 0; i < f->num_blocks; i++) | 186 | for (i = 0; i < f->num_blocks; i++) |
180 | free_page((unsigned long)(f->blocks[i].data)); | 187 | kmem_cache_free(flash_block_cache, f->blocks[i].data); |
181 | next = f->next; | 188 | next = f->next; |
182 | free_page((unsigned long)f); | 189 | kmem_cache_free(flash_block_cache, f); |
183 | f = next; | 190 | f = next; |
184 | } | 191 | } |
185 | } | 192 | } |
@@ -278,6 +285,12 @@ static ssize_t rtas_flash_read(struct file *file, char __user *buf, | |||
278 | return msglen; | 285 | return msglen; |
279 | } | 286 | } |
280 | 287 | ||
288 | /* constructor for flash_block_cache */ | ||
289 | void rtas_block_ctor(void *ptr, kmem_cache_t *cache, unsigned long flags) | ||
290 | { | ||
291 | memset(ptr, 0, RTAS_BLK_SIZE); | ||
292 | } | ||
293 | |||
281 | /* We could be much more efficient here. But to keep this function | 294 | /* We could be much more efficient here. But to keep this function |
282 | * simple we allocate a page to the block list no matter how small the | 295 | * simple we allocate a page to the block list no matter how small the |
283 | * count is. If the system is low on memory it will be just as well | 296 | * count is. If the system is low on memory it will be just as well |
@@ -302,7 +315,7 @@ static ssize_t rtas_flash_write(struct file *file, const char __user *buffer, | |||
302 | * proc file | 315 | * proc file |
303 | */ | 316 | */ |
304 | if (uf->flist == NULL) { | 317 | if (uf->flist == NULL) { |
305 | uf->flist = (struct flash_block_list *) get_zeroed_page(GFP_KERNEL); | 318 | uf->flist = kmem_cache_alloc(flash_block_cache, GFP_KERNEL); |
306 | if (!uf->flist) | 319 | if (!uf->flist) |
307 | return -ENOMEM; | 320 | return -ENOMEM; |
308 | } | 321 | } |
@@ -313,21 +326,21 @@ static ssize_t rtas_flash_write(struct file *file, const char __user *buffer, | |||
313 | next_free = fl->num_blocks; | 326 | next_free = fl->num_blocks; |
314 | if (next_free == FLASH_BLOCKS_PER_NODE) { | 327 | if (next_free == FLASH_BLOCKS_PER_NODE) { |
315 | /* Need to allocate another block_list */ | 328 | /* Need to allocate another block_list */ |
316 | fl->next = (struct flash_block_list *)get_zeroed_page(GFP_KERNEL); | 329 | fl->next = kmem_cache_alloc(flash_block_cache, GFP_KERNEL); |
317 | if (!fl->next) | 330 | if (!fl->next) |
318 | return -ENOMEM; | 331 | return -ENOMEM; |
319 | fl = fl->next; | 332 | fl = fl->next; |
320 | next_free = 0; | 333 | next_free = 0; |
321 | } | 334 | } |
322 | 335 | ||
323 | if (count > PAGE_SIZE) | 336 | if (count > RTAS_BLK_SIZE) |
324 | count = PAGE_SIZE; | 337 | count = RTAS_BLK_SIZE; |
325 | p = (char *)get_zeroed_page(GFP_KERNEL); | 338 | p = kmem_cache_alloc(flash_block_cache, GFP_KERNEL); |
326 | if (!p) | 339 | if (!p) |
327 | return -ENOMEM; | 340 | return -ENOMEM; |
328 | 341 | ||
329 | if(copy_from_user(p, buffer, count)) { | 342 | if(copy_from_user(p, buffer, count)) { |
330 | free_page((unsigned long)p); | 343 | kmem_cache_free(flash_block_cache, p); |
331 | return -EFAULT; | 344 | return -EFAULT; |
332 | } | 345 | } |
333 | fl->blocks[next_free].data = p; | 346 | fl->blocks[next_free].data = p; |
@@ -791,6 +804,16 @@ int __init rtas_flash_init(void) | |||
791 | goto cleanup; | 804 | goto cleanup; |
792 | 805 | ||
793 | rtas_flash_term_hook = rtas_flash_firmware; | 806 | rtas_flash_term_hook = rtas_flash_firmware; |
807 | |||
808 | flash_block_cache = kmem_cache_create("rtas_flash_cache", | ||
809 | RTAS_BLK_SIZE, RTAS_BLK_SIZE, 0, | ||
810 | rtas_block_ctor, NULL); | ||
811 | if (!flash_block_cache) { | ||
812 | printk(KERN_ERR "%s: failed to create block cache\n", | ||
813 | __FUNCTION__); | ||
814 | rc = -ENOMEM; | ||
815 | goto cleanup; | ||
816 | } | ||
794 | return 0; | 817 | return 0; |
795 | 818 | ||
796 | cleanup: | 819 | cleanup: |
@@ -805,6 +828,10 @@ cleanup: | |||
805 | void __exit rtas_flash_cleanup(void) | 828 | void __exit rtas_flash_cleanup(void) |
806 | { | 829 | { |
807 | rtas_flash_term_hook = NULL; | 830 | rtas_flash_term_hook = NULL; |
831 | |||
832 | if (flash_block_cache) | ||
833 | kmem_cache_destroy(flash_block_cache); | ||
834 | |||
808 | remove_flash_pde(firmware_flash_pde); | 835 | remove_flash_pde(firmware_flash_pde); |
809 | remove_flash_pde(firmware_update_pde); | 836 | remove_flash_pde(firmware_update_pde); |
810 | remove_flash_pde(validate_pde); | 837 | remove_flash_pde(validate_pde); |
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 191d0ab09222..a4c2964a3ca6 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c | |||
@@ -91,6 +91,7 @@ int ucache_bsize; | |||
91 | unsigned long __init early_init(unsigned long dt_ptr) | 91 | unsigned long __init early_init(unsigned long dt_ptr) |
92 | { | 92 | { |
93 | unsigned long offset = reloc_offset(); | 93 | unsigned long offset = reloc_offset(); |
94 | struct cpu_spec *spec; | ||
94 | 95 | ||
95 | /* First zero the BSS -- use memset_io, some platforms don't have | 96 | /* First zero the BSS -- use memset_io, some platforms don't have |
96 | * caches on yet */ | 97 | * caches on yet */ |
@@ -100,8 +101,11 @@ unsigned long __init early_init(unsigned long dt_ptr) | |||
100 | * Identify the CPU type and fix up code sections | 101 | * Identify the CPU type and fix up code sections |
101 | * that depend on which cpu we have. | 102 | * that depend on which cpu we have. |
102 | */ | 103 | */ |
103 | identify_cpu(offset, 0); | 104 | spec = identify_cpu(offset); |
104 | do_cpu_ftr_fixups(offset); | 105 | |
106 | do_feature_fixups(spec->cpu_features, | ||
107 | PTRRELOC(&__start___ftr_fixup), | ||
108 | PTRRELOC(&__stop___ftr_fixup)); | ||
105 | 109 | ||
106 | return KERNELBASE + offset; | 110 | return KERNELBASE + offset; |
107 | } | 111 | } |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 4b2e32eab9dc..16278968dab6 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -170,6 +170,9 @@ void __init setup_paca(int cpu) | |||
170 | 170 | ||
171 | void __init early_setup(unsigned long dt_ptr) | 171 | void __init early_setup(unsigned long dt_ptr) |
172 | { | 172 | { |
173 | /* Identify CPU type */ | ||
174 | identify_cpu(0); | ||
175 | |||
173 | /* Assume we're on cpu 0 for now. Don't write to the paca yet! */ | 176 | /* Assume we're on cpu 0 for now. Don't write to the paca yet! */ |
174 | setup_paca(0); | 177 | setup_paca(0); |
175 | 178 | ||
@@ -348,6 +351,14 @@ void __init setup_system(void) | |||
348 | { | 351 | { |
349 | DBG(" -> setup_system()\n"); | 352 | DBG(" -> setup_system()\n"); |
350 | 353 | ||
354 | /* Apply the CPUs-specific and firmware specific fixups to kernel | ||
355 | * text (nop out sections not relevant to this CPU or this firmware) | ||
356 | */ | ||
357 | do_feature_fixups(cur_cpu_spec->cpu_features, | ||
358 | &__start___ftr_fixup, &__stop___ftr_fixup); | ||
359 | do_feature_fixups(powerpc_firmware_features, | ||
360 | &__start___fw_ftr_fixup, &__stop___fw_ftr_fixup); | ||
361 | |||
351 | /* | 362 | /* |
352 | * Unflatten the device-tree passed by prom_init or kexec | 363 | * Unflatten the device-tree passed by prom_init or kexec |
353 | */ | 364 | */ |
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 5b59bc18dfe7..46a24de36fec 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -220,11 +220,8 @@ static void account_process_time(struct pt_regs *regs) | |||
220 | */ | 220 | */ |
221 | struct cpu_purr_data { | 221 | struct cpu_purr_data { |
222 | int initialized; /* thread is running */ | 222 | int initialized; /* thread is running */ |
223 | u64 tb0; /* timebase at origin time */ | ||
224 | u64 purr0; /* PURR at origin time */ | ||
225 | u64 tb; /* last TB value read */ | 223 | u64 tb; /* last TB value read */ |
226 | u64 purr; /* last PURR value read */ | 224 | u64 purr; /* last PURR value read */ |
227 | u64 stolen; /* stolen time so far */ | ||
228 | spinlock_t lock; | 225 | spinlock_t lock; |
229 | }; | 226 | }; |
230 | 227 | ||
@@ -234,10 +231,8 @@ static void snapshot_tb_and_purr(void *data) | |||
234 | { | 231 | { |
235 | struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data); | 232 | struct cpu_purr_data *p = &__get_cpu_var(cpu_purr_data); |
236 | 233 | ||
237 | p->tb0 = mftb(); | 234 | p->tb = mftb(); |
238 | p->purr0 = mfspr(SPRN_PURR); | 235 | p->purr = mfspr(SPRN_PURR); |
239 | p->tb = p->tb0; | ||
240 | p->purr = 0; | ||
241 | wmb(); | 236 | wmb(); |
242 | p->initialized = 1; | 237 | p->initialized = 1; |
243 | } | 238 | } |
@@ -258,37 +253,24 @@ void snapshot_timebases(void) | |||
258 | 253 | ||
259 | void calculate_steal_time(void) | 254 | void calculate_steal_time(void) |
260 | { | 255 | { |
261 | u64 tb, purr, t0; | 256 | u64 tb, purr; |
262 | s64 stolen; | 257 | s64 stolen; |
263 | struct cpu_purr_data *p0, *pme, *phim; | 258 | struct cpu_purr_data *pme; |
264 | int cpu; | ||
265 | 259 | ||
266 | if (!cpu_has_feature(CPU_FTR_PURR)) | 260 | if (!cpu_has_feature(CPU_FTR_PURR)) |
267 | return; | 261 | return; |
268 | cpu = smp_processor_id(); | 262 | pme = &per_cpu(cpu_purr_data, smp_processor_id()); |
269 | pme = &per_cpu(cpu_purr_data, cpu); | ||
270 | if (!pme->initialized) | 263 | if (!pme->initialized) |
271 | return; /* this can happen in early boot */ | 264 | return; /* this can happen in early boot */ |
272 | p0 = &per_cpu(cpu_purr_data, cpu & ~1); | 265 | spin_lock(&pme->lock); |
273 | phim = &per_cpu(cpu_purr_data, cpu ^ 1); | ||
274 | spin_lock(&p0->lock); | ||
275 | tb = mftb(); | 266 | tb = mftb(); |
276 | purr = mfspr(SPRN_PURR) - pme->purr0; | 267 | purr = mfspr(SPRN_PURR); |
277 | if (!phim->initialized || !cpu_online(cpu ^ 1)) { | 268 | stolen = (tb - pme->tb) - (purr - pme->purr); |
278 | stolen = (tb - pme->tb) - (purr - pme->purr); | 269 | if (stolen > 0) |
279 | } else { | ||
280 | t0 = pme->tb0; | ||
281 | if (phim->tb0 < t0) | ||
282 | t0 = phim->tb0; | ||
283 | stolen = phim->tb - t0 - phim->purr - purr - p0->stolen; | ||
284 | } | ||
285 | if (stolen > 0) { | ||
286 | account_steal_time(current, stolen); | 270 | account_steal_time(current, stolen); |
287 | p0->stolen += stolen; | ||
288 | } | ||
289 | pme->tb = tb; | 271 | pme->tb = tb; |
290 | pme->purr = purr; | 272 | pme->purr = purr; |
291 | spin_unlock(&p0->lock); | 273 | spin_unlock(&pme->lock); |
292 | } | 274 | } |
293 | 275 | ||
294 | /* | 276 | /* |
@@ -297,30 +279,17 @@ void calculate_steal_time(void) | |||
297 | */ | 279 | */ |
298 | static void snapshot_purr(void) | 280 | static void snapshot_purr(void) |
299 | { | 281 | { |
300 | int cpu; | 282 | struct cpu_purr_data *pme; |
301 | u64 purr; | ||
302 | struct cpu_purr_data *p0, *pme, *phim; | ||
303 | unsigned long flags; | 283 | unsigned long flags; |
304 | 284 | ||
305 | if (!cpu_has_feature(CPU_FTR_PURR)) | 285 | if (!cpu_has_feature(CPU_FTR_PURR)) |
306 | return; | 286 | return; |
307 | cpu = smp_processor_id(); | 287 | pme = &per_cpu(cpu_purr_data, smp_processor_id()); |
308 | pme = &per_cpu(cpu_purr_data, cpu); | 288 | spin_lock_irqsave(&pme->lock, flags); |
309 | p0 = &per_cpu(cpu_purr_data, cpu & ~1); | 289 | pme->tb = mftb(); |
310 | phim = &per_cpu(cpu_purr_data, cpu ^ 1); | 290 | pme->purr = mfspr(SPRN_PURR); |
311 | spin_lock_irqsave(&p0->lock, flags); | ||
312 | pme->tb = pme->tb0 = mftb(); | ||
313 | purr = mfspr(SPRN_PURR); | ||
314 | if (!phim->initialized) { | ||
315 | pme->purr = 0; | ||
316 | pme->purr0 = purr; | ||
317 | } else { | ||
318 | /* set p->purr and p->purr0 for no change in p0->stolen */ | ||
319 | pme->purr = phim->tb - phim->tb0 - phim->purr - p0->stolen; | ||
320 | pme->purr0 = purr - pme->purr; | ||
321 | } | ||
322 | pme->initialized = 1; | 291 | pme->initialized = 1; |
323 | spin_unlock_irqrestore(&p0->lock, flags); | 292 | spin_unlock_irqrestore(&pme->lock, flags); |
324 | } | 293 | } |
325 | 294 | ||
326 | #endif /* CONFIG_PPC_SPLPAR */ | 295 | #endif /* CONFIG_PPC_SPLPAR */ |
@@ -1045,48 +1014,6 @@ void __init time_init(void) | |||
1045 | set_dec(tb_ticks_per_jiffy); | 1014 | set_dec(tb_ticks_per_jiffy); |
1046 | } | 1015 | } |
1047 | 1016 | ||
1048 | #ifdef CONFIG_RTC_CLASS | ||
1049 | static int set_rtc_class_time(struct rtc_time *tm) | ||
1050 | { | ||
1051 | int err; | ||
1052 | struct class_device *class_dev = | ||
1053 | rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); | ||
1054 | |||
1055 | if (class_dev == NULL) | ||
1056 | return -ENODEV; | ||
1057 | |||
1058 | err = rtc_set_time(class_dev, tm); | ||
1059 | |||
1060 | rtc_class_close(class_dev); | ||
1061 | |||
1062 | return 0; | ||
1063 | } | ||
1064 | |||
1065 | static void get_rtc_class_time(struct rtc_time *tm) | ||
1066 | { | ||
1067 | int err; | ||
1068 | struct class_device *class_dev = | ||
1069 | rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); | ||
1070 | |||
1071 | if (class_dev == NULL) | ||
1072 | return; | ||
1073 | |||
1074 | err = rtc_read_time(class_dev, tm); | ||
1075 | |||
1076 | rtc_class_close(class_dev); | ||
1077 | |||
1078 | return; | ||
1079 | } | ||
1080 | |||
1081 | int __init rtc_class_hookup(void) | ||
1082 | { | ||
1083 | ppc_md.get_rtc_time = get_rtc_class_time; | ||
1084 | ppc_md.set_rtc_time = set_rtc_class_time; | ||
1085 | |||
1086 | return 0; | ||
1087 | } | ||
1088 | #endif /* CONFIG_RTC_CLASS */ | ||
1089 | |||
1090 | 1017 | ||
1091 | #define FEBRUARY 2 | 1018 | #define FEBRUARY 2 |
1092 | #define STARTOFTIME 1970 | 1019 | #define STARTOFTIME 1970 |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 5ed4c2ceb5ca..c66b4771ef44 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -843,7 +843,7 @@ void __kprobes program_check_exception(struct pt_regs *regs) | |||
843 | 843 | ||
844 | void alignment_exception(struct pt_regs *regs) | 844 | void alignment_exception(struct pt_regs *regs) |
845 | { | 845 | { |
846 | int fixed = 0; | 846 | int sig, code, fixed = 0; |
847 | 847 | ||
848 | /* we don't implement logging of alignment exceptions */ | 848 | /* we don't implement logging of alignment exceptions */ |
849 | if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS)) | 849 | if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS)) |
@@ -857,14 +857,16 @@ void alignment_exception(struct pt_regs *regs) | |||
857 | 857 | ||
858 | /* Operand address was bad */ | 858 | /* Operand address was bad */ |
859 | if (fixed == -EFAULT) { | 859 | if (fixed == -EFAULT) { |
860 | if (user_mode(regs)) | 860 | sig = SIGSEGV; |
861 | _exception(SIGSEGV, regs, SEGV_ACCERR, regs->dar); | 861 | code = SEGV_ACCERR; |
862 | else | 862 | } else { |
863 | /* Search exception table */ | 863 | sig = SIGBUS; |
864 | bad_page_fault(regs, regs->dar, SIGSEGV); | 864 | code = BUS_ADRALN; |
865 | return; | ||
866 | } | 865 | } |
867 | _exception(SIGBUS, regs, BUS_ADRALN, regs->dar); | 866 | if (user_mode(regs)) |
867 | _exception(sig, regs, code, regs->dar); | ||
868 | else | ||
869 | bad_page_fault(regs, regs->dar, sig); | ||
868 | } | 870 | } |
869 | 871 | ||
870 | void StackOverflow(struct pt_regs *regs) | 872 | void StackOverflow(struct pt_regs *regs) |
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index 1a7e19cdab39..c913ad5cad29 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c | |||
@@ -36,6 +36,8 @@ | |||
36 | #include <asm/vdso.h> | 36 | #include <asm/vdso.h> |
37 | #include <asm/vdso_datapage.h> | 37 | #include <asm/vdso_datapage.h> |
38 | 38 | ||
39 | #include "setup.h" | ||
40 | |||
39 | #undef DEBUG | 41 | #undef DEBUG |
40 | 42 | ||
41 | #ifdef DEBUG | 43 | #ifdef DEBUG |
@@ -586,6 +588,43 @@ static __init int vdso_fixup_datapage(struct lib32_elfinfo *v32, | |||
586 | return 0; | 588 | return 0; |
587 | } | 589 | } |
588 | 590 | ||
591 | |||
592 | static __init int vdso_fixup_features(struct lib32_elfinfo *v32, | ||
593 | struct lib64_elfinfo *v64) | ||
594 | { | ||
595 | void *start32; | ||
596 | unsigned long size32; | ||
597 | |||
598 | #ifdef CONFIG_PPC64 | ||
599 | void *start64; | ||
600 | unsigned long size64; | ||
601 | |||
602 | start64 = find_section64(v64->hdr, "__ftr_fixup", &size64); | ||
603 | if (start64) | ||
604 | do_feature_fixups(cur_cpu_spec->cpu_features, | ||
605 | start64, start64 + size64); | ||
606 | |||
607 | start64 = find_section64(v64->hdr, "__fw_ftr_fixup", &size64); | ||
608 | if (start64) | ||
609 | do_feature_fixups(powerpc_firmware_features, | ||
610 | start64, start64 + size64); | ||
611 | #endif /* CONFIG_PPC64 */ | ||
612 | |||
613 | start32 = find_section32(v32->hdr, "__ftr_fixup", &size32); | ||
614 | if (start32) | ||
615 | do_feature_fixups(cur_cpu_spec->cpu_features, | ||
616 | start32, start32 + size32); | ||
617 | |||
618 | #ifdef CONFIG_PPC64 | ||
619 | start32 = find_section32(v32->hdr, "__fw_ftr_fixup", &size32); | ||
620 | if (start32) | ||
621 | do_feature_fixups(powerpc_firmware_features, | ||
622 | start32, start32 + size32); | ||
623 | #endif /* CONFIG_PPC64 */ | ||
624 | |||
625 | return 0; | ||
626 | } | ||
627 | |||
589 | static __init int vdso_fixup_alt_funcs(struct lib32_elfinfo *v32, | 628 | static __init int vdso_fixup_alt_funcs(struct lib32_elfinfo *v32, |
590 | struct lib64_elfinfo *v64) | 629 | struct lib64_elfinfo *v64) |
591 | { | 630 | { |
@@ -634,6 +673,9 @@ static __init int vdso_setup(void) | |||
634 | if (vdso_fixup_datapage(&v32, &v64)) | 673 | if (vdso_fixup_datapage(&v32, &v64)) |
635 | return -1; | 674 | return -1; |
636 | 675 | ||
676 | if (vdso_fixup_features(&v32, &v64)) | ||
677 | return -1; | ||
678 | |||
637 | if (vdso_fixup_alt_funcs(&v32, &v64)) | 679 | if (vdso_fixup_alt_funcs(&v32, &v64)) |
638 | return -1; | 680 | return -1; |
639 | 681 | ||
@@ -714,6 +756,7 @@ void __init vdso_init(void) | |||
714 | * Setup the syscall map in the vDOS | 756 | * Setup the syscall map in the vDOS |
715 | */ | 757 | */ |
716 | vdso_setup_syscall_map(); | 758 | vdso_setup_syscall_map(); |
759 | |||
717 | /* | 760 | /* |
718 | * Initialize the vDSO images in memory, that is do necessary | 761 | * Initialize the vDSO images in memory, that is do necessary |
719 | * fixups of vDSO symbols, locate trampolines, etc... | 762 | * fixups of vDSO symbols, locate trampolines, etc... |
diff --git a/arch/powerpc/kernel/vdso32/vdso32.lds.S b/arch/powerpc/kernel/vdso32/vdso32.lds.S index 6187af2d54c3..26e138c4ce17 100644 --- a/arch/powerpc/kernel/vdso32/vdso32.lds.S +++ b/arch/powerpc/kernel/vdso32/vdso32.lds.S | |||
@@ -32,6 +32,18 @@ SECTIONS | |||
32 | PROVIDE (_etext = .); | 32 | PROVIDE (_etext = .); |
33 | PROVIDE (etext = .); | 33 | PROVIDE (etext = .); |
34 | 34 | ||
35 | . = ALIGN(8); | ||
36 | __ftr_fixup : { | ||
37 | *(__ftr_fixup) | ||
38 | } | ||
39 | |||
40 | #ifdef CONFIG_PPC64 | ||
41 | . = ALIGN(8); | ||
42 | __fw_ftr_fixup : { | ||
43 | *(__fw_ftr_fixup) | ||
44 | } | ||
45 | #endif | ||
46 | |||
35 | /* Other stuff is appended to the text segment: */ | 47 | /* Other stuff is appended to the text segment: */ |
36 | .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } | 48 | .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } |
37 | .rodata1 : { *(.rodata1) } | 49 | .rodata1 : { *(.rodata1) } |
diff --git a/arch/powerpc/kernel/vdso64/gettimeofday.S b/arch/powerpc/kernel/vdso64/gettimeofday.S index 56e76ff5498f..40ffd9b6cef7 100644 --- a/arch/powerpc/kernel/vdso64/gettimeofday.S +++ b/arch/powerpc/kernel/vdso64/gettimeofday.S | |||
@@ -229,8 +229,10 @@ V_FUNCTION_BEGIN(__do_get_xsec) | |||
229 | xor r0,r8,r8 /* create dependency */ | 229 | xor r0,r8,r8 /* create dependency */ |
230 | add r3,r3,r0 | 230 | add r3,r3,r0 |
231 | 231 | ||
232 | /* Get TB & offset it */ | 232 | /* Get TB & offset it. We use the MFTB macro which will generate |
233 | mftb r7 | 233 | * workaround code for Cell. |
234 | */ | ||
235 | MFTB(r7) | ||
234 | ld r9,CFG_TB_ORIG_STAMP(r3) | 236 | ld r9,CFG_TB_ORIG_STAMP(r3) |
235 | subf r7,r9,r7 | 237 | subf r7,r9,r7 |
236 | 238 | ||
diff --git a/arch/powerpc/kernel/vdso64/vdso64.lds.S b/arch/powerpc/kernel/vdso64/vdso64.lds.S index 4a2b6dc0960c..2d70f35d50b5 100644 --- a/arch/powerpc/kernel/vdso64/vdso64.lds.S +++ b/arch/powerpc/kernel/vdso64/vdso64.lds.S | |||
@@ -31,6 +31,16 @@ SECTIONS | |||
31 | PROVIDE (_etext = .); | 31 | PROVIDE (_etext = .); |
32 | PROVIDE (etext = .); | 32 | PROVIDE (etext = .); |
33 | 33 | ||
34 | . = ALIGN(8); | ||
35 | __ftr_fixup : { | ||
36 | *(__ftr_fixup) | ||
37 | } | ||
38 | |||
39 | . = ALIGN(8); | ||
40 | __fw_ftr_fixup : { | ||
41 | *(__fw_ftr_fixup) | ||
42 | } | ||
43 | |||
34 | /* Other stuff is appended to the text segment: */ | 44 | /* Other stuff is appended to the text segment: */ |
35 | .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } | 45 | .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } |
36 | .rodata1 : { *(.rodata1) } | 46 | .rodata1 : { *(.rodata1) } |
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index cb87e71eec66..ed007878d1bf 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c | |||
@@ -92,9 +92,9 @@ static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) | |||
92 | &tbl->it_index, &offset, &size); | 92 | &tbl->it_index, &offset, &size); |
93 | 93 | ||
94 | /* TCE table size - measured in tce entries */ | 94 | /* TCE table size - measured in tce entries */ |
95 | tbl->it_size = size >> PAGE_SHIFT; | 95 | tbl->it_size = size >> IOMMU_PAGE_SHIFT; |
96 | /* offset for VIO should always be 0 */ | 96 | /* offset for VIO should always be 0 */ |
97 | tbl->it_offset = offset >> PAGE_SHIFT; | 97 | tbl->it_offset = offset >> IOMMU_PAGE_SHIFT; |
98 | tbl->it_busno = 0; | 98 | tbl->it_busno = 0; |
99 | tbl->it_type = TCE_VB; | 99 | tbl->it_type = TCE_VB; |
100 | 100 | ||
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index cb0e8d46c3e8..e8342d867536 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S | |||
@@ -108,13 +108,7 @@ SECTIONS | |||
108 | 108 | ||
109 | .initcall.init : { | 109 | .initcall.init : { |
110 | __initcall_start = .; | 110 | __initcall_start = .; |
111 | *(.initcall1.init) | 111 | INITCALLS |
112 | *(.initcall2.init) | ||
113 | *(.initcall3.init) | ||
114 | *(.initcall4.init) | ||
115 | *(.initcall5.init) | ||
116 | *(.initcall6.init) | ||
117 | *(.initcall7.init) | ||
118 | __initcall_end = .; | 112 | __initcall_end = .; |
119 | } | 113 | } |
120 | 114 | ||