diff options
Diffstat (limited to 'arch/powerpc/kernel')
49 files changed, 1193 insertions, 960 deletions
diff --git a/arch/powerpc/kernel/align.c b/arch/powerpc/kernel/align.c index faaec9c6f78f..4734b5de599d 100644 --- a/arch/powerpc/kernel/align.c +++ b/arch/powerpc/kernel/align.c | |||
@@ -35,17 +35,19 @@ struct aligninfo { | |||
35 | 35 | ||
36 | #define INVALID { 0, 0 } | 36 | #define INVALID { 0, 0 } |
37 | 37 | ||
38 | #define LD 1 /* load */ | 38 | /* Bits in the flags field */ |
39 | #define ST 2 /* store */ | 39 | #define LD 0 /* load */ |
40 | #define SE 4 /* sign-extend value */ | 40 | #define ST 1 /* store */ |
41 | #define F 8 /* to/from fp regs */ | 41 | #define SE 2 /* sign-extend value */ |
42 | #define U 0x10 /* update index register */ | 42 | #define F 4 /* to/from fp regs */ |
43 | #define M 0x20 /* multiple load/store */ | 43 | #define U 8 /* update index register */ |
44 | #define SW 0x40 /* byte swap int or ... */ | 44 | #define M 0x10 /* multiple load/store */ |
45 | #define S 0x40 /* ... single-precision fp */ | 45 | #define SW 0x20 /* byte swap */ |
46 | #define SX 0x40 /* byte count in XER */ | 46 | #define S 0x40 /* single-precision fp or... */ |
47 | #define SX 0x40 /* ... byte count in XER */ | ||
47 | #define HARD 0x80 /* string, stwcx. */ | 48 | #define HARD 0x80 /* string, stwcx. */ |
48 | 49 | ||
50 | /* DSISR bits reported for a DCBZ instruction: */ | ||
49 | #define DCBZ 0x5f /* 8xx/82xx dcbz faults when cache not enabled */ | 51 | #define DCBZ 0x5f /* 8xx/82xx dcbz faults when cache not enabled */ |
50 | 52 | ||
51 | #define SWAP(a, b) (t = (a), (a) = (b), (b) = t) | 53 | #define SWAP(a, b) (t = (a), (a) = (b), (b) = t) |
@@ -256,12 +258,16 @@ static int emulate_dcbz(struct pt_regs *regs, unsigned char __user *addr) | |||
256 | #define REG_BYTE(rp, i) *((u8 *)(rp) + (i)) | 258 | #define REG_BYTE(rp, i) *((u8 *)(rp) + (i)) |
257 | #endif | 259 | #endif |
258 | 260 | ||
261 | #define SWIZ_PTR(p) ((unsigned char __user *)((p) ^ swiz)) | ||
262 | |||
259 | static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr, | 263 | static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr, |
260 | unsigned int reg, unsigned int nb, | 264 | unsigned int reg, unsigned int nb, |
261 | unsigned int flags, unsigned int instr) | 265 | unsigned int flags, unsigned int instr, |
266 | unsigned long swiz) | ||
262 | { | 267 | { |
263 | unsigned long *rptr; | 268 | unsigned long *rptr; |
264 | unsigned int nb0, i; | 269 | unsigned int nb0, i, bswiz; |
270 | unsigned long p; | ||
265 | 271 | ||
266 | /* | 272 | /* |
267 | * We do not try to emulate 8 bytes multiple as they aren't really | 273 | * We do not try to emulate 8 bytes multiple as they aren't really |
@@ -280,9 +286,12 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr, | |||
280 | if (nb == 0) | 286 | if (nb == 0) |
281 | return 1; | 287 | return 1; |
282 | } else { | 288 | } else { |
283 | if (__get_user(instr, | 289 | unsigned long pc = regs->nip ^ (swiz & 4); |
284 | (unsigned int __user *)regs->nip)) | 290 | |
291 | if (__get_user(instr, (unsigned int __user *)pc)) | ||
285 | return -EFAULT; | 292 | return -EFAULT; |
293 | if (swiz == 0 && (flags & SW)) | ||
294 | instr = cpu_to_le32(instr); | ||
286 | nb = (instr >> 11) & 0x1f; | 295 | nb = (instr >> 11) & 0x1f; |
287 | if (nb == 0) | 296 | if (nb == 0) |
288 | nb = 32; | 297 | nb = 32; |
@@ -300,7 +309,10 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr, | |||
300 | return -EFAULT; /* bad address */ | 309 | return -EFAULT; /* bad address */ |
301 | 310 | ||
302 | rptr = ®s->gpr[reg]; | 311 | rptr = ®s->gpr[reg]; |
303 | if (flags & LD) { | 312 | p = (unsigned long) addr; |
313 | bswiz = (flags & SW)? 3: 0; | ||
314 | |||
315 | if (!(flags & ST)) { | ||
304 | /* | 316 | /* |
305 | * This zeroes the top 4 bytes of the affected registers | 317 | * This zeroes the top 4 bytes of the affected registers |
306 | * in 64-bit mode, and also zeroes out any remaining | 318 | * in 64-bit mode, and also zeroes out any remaining |
@@ -311,26 +323,28 @@ static int emulate_multiple(struct pt_regs *regs, unsigned char __user *addr, | |||
311 | memset(®s->gpr[0], 0, | 323 | memset(®s->gpr[0], 0, |
312 | ((nb0 + 3) / 4) * sizeof(unsigned long)); | 324 | ((nb0 + 3) / 4) * sizeof(unsigned long)); |
313 | 325 | ||
314 | for (i = 0; i < nb; ++i) | 326 | for (i = 0; i < nb; ++i, ++p) |
315 | if (__get_user(REG_BYTE(rptr, i), addr + i)) | 327 | if (__get_user(REG_BYTE(rptr, i ^ bswiz), SWIZ_PTR(p))) |
316 | return -EFAULT; | 328 | return -EFAULT; |
317 | if (nb0 > 0) { | 329 | if (nb0 > 0) { |
318 | rptr = ®s->gpr[0]; | 330 | rptr = ®s->gpr[0]; |
319 | addr += nb; | 331 | addr += nb; |
320 | for (i = 0; i < nb0; ++i) | 332 | for (i = 0; i < nb0; ++i, ++p) |
321 | if (__get_user(REG_BYTE(rptr, i), addr + i)) | 333 | if (__get_user(REG_BYTE(rptr, i ^ bswiz), |
334 | SWIZ_PTR(p))) | ||
322 | return -EFAULT; | 335 | return -EFAULT; |
323 | } | 336 | } |
324 | 337 | ||
325 | } else { | 338 | } else { |
326 | for (i = 0; i < nb; ++i) | 339 | for (i = 0; i < nb; ++i, ++p) |
327 | if (__put_user(REG_BYTE(rptr, i), addr + i)) | 340 | if (__put_user(REG_BYTE(rptr, i ^ bswiz), SWIZ_PTR(p))) |
328 | return -EFAULT; | 341 | return -EFAULT; |
329 | if (nb0 > 0) { | 342 | if (nb0 > 0) { |
330 | rptr = ®s->gpr[0]; | 343 | rptr = ®s->gpr[0]; |
331 | addr += nb; | 344 | addr += nb; |
332 | for (i = 0; i < nb0; ++i) | 345 | for (i = 0; i < nb0; ++i, ++p) |
333 | if (__put_user(REG_BYTE(rptr, i), addr + i)) | 346 | if (__put_user(REG_BYTE(rptr, i ^ bswiz), |
347 | SWIZ_PTR(p))) | ||
334 | return -EFAULT; | 348 | return -EFAULT; |
335 | } | 349 | } |
336 | } | 350 | } |
@@ -352,7 +366,7 @@ int fix_alignment(struct pt_regs *regs) | |||
352 | unsigned int reg, areg; | 366 | unsigned int reg, areg; |
353 | unsigned int dsisr; | 367 | unsigned int dsisr; |
354 | unsigned char __user *addr; | 368 | unsigned char __user *addr; |
355 | unsigned char __user *p; | 369 | unsigned long p, swiz; |
356 | int ret, t; | 370 | int ret, t; |
357 | union { | 371 | union { |
358 | u64 ll; | 372 | u64 ll; |
@@ -380,11 +394,15 @@ int fix_alignment(struct pt_regs *regs) | |||
380 | * let's make one up from the instruction | 394 | * let's make one up from the instruction |
381 | */ | 395 | */ |
382 | if (cpu_has_feature(CPU_FTR_NODSISRALIGN)) { | 396 | if (cpu_has_feature(CPU_FTR_NODSISRALIGN)) { |
383 | unsigned int real_instr; | 397 | unsigned long pc = regs->nip; |
384 | if (unlikely(__get_user(real_instr, | 398 | |
385 | (unsigned int __user *)regs->nip))) | 399 | if (cpu_has_feature(CPU_FTR_PPC_LE) && (regs->msr & MSR_LE)) |
400 | pc ^= 4; | ||
401 | if (unlikely(__get_user(instr, (unsigned int __user *)pc))) | ||
386 | return -EFAULT; | 402 | return -EFAULT; |
387 | dsisr = make_dsisr(real_instr); | 403 | if (cpu_has_feature(CPU_FTR_REAL_LE) && (regs->msr & MSR_LE)) |
404 | instr = cpu_to_le32(instr); | ||
405 | dsisr = make_dsisr(instr); | ||
388 | } | 406 | } |
389 | 407 | ||
390 | /* extract the operation and registers from the dsisr */ | 408 | /* extract the operation and registers from the dsisr */ |
@@ -397,6 +415,24 @@ int fix_alignment(struct pt_regs *regs) | |||
397 | nb = aligninfo[instr].len; | 415 | nb = aligninfo[instr].len; |
398 | flags = aligninfo[instr].flags; | 416 | flags = aligninfo[instr].flags; |
399 | 417 | ||
418 | /* Byteswap little endian loads and stores */ | ||
419 | swiz = 0; | ||
420 | if (regs->msr & MSR_LE) { | ||
421 | flags ^= SW; | ||
422 | /* | ||
423 | * So-called "PowerPC little endian" mode works by | ||
424 | * swizzling addresses rather than by actually doing | ||
425 | * any byte-swapping. To emulate this, we XOR each | ||
426 | * byte address with 7. We also byte-swap, because | ||
427 | * the processor's address swizzling depends on the | ||
428 | * operand size (it xors the address with 7 for bytes, | ||
429 | * 6 for halfwords, 4 for words, 0 for doublewords) but | ||
430 | * we will xor with 7 and load/store each byte separately. | ||
431 | */ | ||
432 | if (cpu_has_feature(CPU_FTR_PPC_LE)) | ||
433 | swiz = 7; | ||
434 | } | ||
435 | |||
400 | /* DAR has the operand effective address */ | 436 | /* DAR has the operand effective address */ |
401 | addr = (unsigned char __user *)regs->dar; | 437 | addr = (unsigned char __user *)regs->dar; |
402 | 438 | ||
@@ -412,7 +448,8 @@ int fix_alignment(struct pt_regs *regs) | |||
412 | * function | 448 | * function |
413 | */ | 449 | */ |
414 | if (flags & M) | 450 | if (flags & M) |
415 | return emulate_multiple(regs, addr, reg, nb, flags, instr); | 451 | return emulate_multiple(regs, addr, reg, nb, |
452 | flags, instr, swiz); | ||
416 | 453 | ||
417 | /* Verify the address of the operand */ | 454 | /* Verify the address of the operand */ |
418 | if (unlikely(user_mode(regs) && | 455 | if (unlikely(user_mode(regs) && |
@@ -431,51 +468,71 @@ int fix_alignment(struct pt_regs *regs) | |||
431 | /* If we are loading, get the data from user space, else | 468 | /* If we are loading, get the data from user space, else |
432 | * get it from register values | 469 | * get it from register values |
433 | */ | 470 | */ |
434 | if (flags & LD) { | 471 | if (!(flags & ST)) { |
435 | data.ll = 0; | 472 | data.ll = 0; |
436 | ret = 0; | 473 | ret = 0; |
437 | p = addr; | 474 | p = (unsigned long) addr; |
438 | switch (nb) { | 475 | switch (nb) { |
439 | case 8: | 476 | case 8: |
440 | ret |= __get_user(data.v[0], p++); | 477 | ret |= __get_user(data.v[0], SWIZ_PTR(p++)); |
441 | ret |= __get_user(data.v[1], p++); | 478 | ret |= __get_user(data.v[1], SWIZ_PTR(p++)); |
442 | ret |= __get_user(data.v[2], p++); | 479 | ret |= __get_user(data.v[2], SWIZ_PTR(p++)); |
443 | ret |= __get_user(data.v[3], p++); | 480 | ret |= __get_user(data.v[3], SWIZ_PTR(p++)); |
444 | case 4: | 481 | case 4: |
445 | ret |= __get_user(data.v[4], p++); | 482 | ret |= __get_user(data.v[4], SWIZ_PTR(p++)); |
446 | ret |= __get_user(data.v[5], p++); | 483 | ret |= __get_user(data.v[5], SWIZ_PTR(p++)); |
447 | case 2: | 484 | case 2: |
448 | ret |= __get_user(data.v[6], p++); | 485 | ret |= __get_user(data.v[6], SWIZ_PTR(p++)); |
449 | ret |= __get_user(data.v[7], p++); | 486 | ret |= __get_user(data.v[7], SWIZ_PTR(p++)); |
450 | if (unlikely(ret)) | 487 | if (unlikely(ret)) |
451 | return -EFAULT; | 488 | return -EFAULT; |
452 | } | 489 | } |
453 | } else if (flags & F) | 490 | } else if (flags & F) { |
454 | data.dd = current->thread.fpr[reg]; | 491 | data.dd = current->thread.fpr[reg]; |
455 | else | 492 | if (flags & S) { |
493 | /* Single-precision FP store requires conversion... */ | ||
494 | #ifdef CONFIG_PPC_FPU | ||
495 | preempt_disable(); | ||
496 | enable_kernel_fp(); | ||
497 | cvt_df(&data.dd, (float *)&data.v[4], ¤t->thread); | ||
498 | preempt_enable(); | ||
499 | #else | ||
500 | return 0; | ||
501 | #endif | ||
502 | } | ||
503 | } else | ||
456 | data.ll = regs->gpr[reg]; | 504 | data.ll = regs->gpr[reg]; |
457 | 505 | ||
458 | /* Perform other misc operations like sign extension, byteswap, | 506 | if (flags & SW) { |
507 | switch (nb) { | ||
508 | case 8: | ||
509 | SWAP(data.v[0], data.v[7]); | ||
510 | SWAP(data.v[1], data.v[6]); | ||
511 | SWAP(data.v[2], data.v[5]); | ||
512 | SWAP(data.v[3], data.v[4]); | ||
513 | break; | ||
514 | case 4: | ||
515 | SWAP(data.v[4], data.v[7]); | ||
516 | SWAP(data.v[5], data.v[6]); | ||
517 | break; | ||
518 | case 2: | ||
519 | SWAP(data.v[6], data.v[7]); | ||
520 | break; | ||
521 | } | ||
522 | } | ||
523 | |||
524 | /* Perform other misc operations like sign extension | ||
459 | * or floating point single precision conversion | 525 | * or floating point single precision conversion |
460 | */ | 526 | */ |
461 | switch (flags & ~U) { | 527 | switch (flags & ~(U|SW)) { |
462 | case LD+SE: /* sign extend */ | 528 | case LD+SE: /* sign extend */ |
463 | if ( nb == 2 ) | 529 | if ( nb == 2 ) |
464 | data.ll = data.x16.low16; | 530 | data.ll = data.x16.low16; |
465 | else /* nb must be 4 */ | 531 | else /* nb must be 4 */ |
466 | data.ll = data.x32.low32; | 532 | data.ll = data.x32.low32; |
467 | break; | 533 | break; |
468 | case LD+S: /* byte-swap */ | ||
469 | case ST+S: | ||
470 | if (nb == 2) { | ||
471 | SWAP(data.v[6], data.v[7]); | ||
472 | } else { | ||
473 | SWAP(data.v[4], data.v[7]); | ||
474 | SWAP(data.v[5], data.v[6]); | ||
475 | } | ||
476 | break; | ||
477 | 534 | ||
478 | /* Single-precision FP load and store require conversions... */ | 535 | /* Single-precision FP load requires conversion... */ |
479 | case LD+F+S: | 536 | case LD+F+S: |
480 | #ifdef CONFIG_PPC_FPU | 537 | #ifdef CONFIG_PPC_FPU |
481 | preempt_disable(); | 538 | preempt_disable(); |
@@ -486,34 +543,24 @@ int fix_alignment(struct pt_regs *regs) | |||
486 | return 0; | 543 | return 0; |
487 | #endif | 544 | #endif |
488 | break; | 545 | break; |
489 | case ST+F+S: | ||
490 | #ifdef CONFIG_PPC_FPU | ||
491 | preempt_disable(); | ||
492 | enable_kernel_fp(); | ||
493 | cvt_df(&data.dd, (float *)&data.v[4], ¤t->thread); | ||
494 | preempt_enable(); | ||
495 | #else | ||
496 | return 0; | ||
497 | #endif | ||
498 | break; | ||
499 | } | 546 | } |
500 | 547 | ||
501 | /* Store result to memory or update registers */ | 548 | /* Store result to memory or update registers */ |
502 | if (flags & ST) { | 549 | if (flags & ST) { |
503 | ret = 0; | 550 | ret = 0; |
504 | p = addr; | 551 | p = (unsigned long) addr; |
505 | switch (nb) { | 552 | switch (nb) { |
506 | case 8: | 553 | case 8: |
507 | ret |= __put_user(data.v[0], p++); | 554 | ret |= __put_user(data.v[0], SWIZ_PTR(p++)); |
508 | ret |= __put_user(data.v[1], p++); | 555 | ret |= __put_user(data.v[1], SWIZ_PTR(p++)); |
509 | ret |= __put_user(data.v[2], p++); | 556 | ret |= __put_user(data.v[2], SWIZ_PTR(p++)); |
510 | ret |= __put_user(data.v[3], p++); | 557 | ret |= __put_user(data.v[3], SWIZ_PTR(p++)); |
511 | case 4: | 558 | case 4: |
512 | ret |= __put_user(data.v[4], p++); | 559 | ret |= __put_user(data.v[4], SWIZ_PTR(p++)); |
513 | ret |= __put_user(data.v[5], p++); | 560 | ret |= __put_user(data.v[5], SWIZ_PTR(p++)); |
514 | case 2: | 561 | case 2: |
515 | ret |= __put_user(data.v[6], p++); | 562 | ret |= __put_user(data.v[6], SWIZ_PTR(p++)); |
516 | ret |= __put_user(data.v[7], p++); | 563 | ret |= __put_user(data.v[7], SWIZ_PTR(p++)); |
517 | } | 564 | } |
518 | if (unlikely(ret)) | 565 | if (unlikely(ret)) |
519 | return -EFAULT; | 566 | return -EFAULT; |
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index 8f85c5e8a55a..ff2940548929 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c | |||
@@ -122,9 +122,8 @@ int main(void) | |||
122 | DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); | 122 | DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache)); |
123 | DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); | 123 | DEFINE(PACASLBCACHEPTR, offsetof(struct paca_struct, slb_cache_ptr)); |
124 | DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); | 124 | DEFINE(PACACONTEXTID, offsetof(struct paca_struct, context.id)); |
125 | #ifdef CONFIG_PPC_64K_PAGES | 125 | DEFINE(PACACONTEXTSLLP, offsetof(struct paca_struct, context.sllp)); |
126 | DEFINE(PACAPGDIR, offsetof(struct paca_struct, pgdir)); | 126 | DEFINE(PACAVMALLOCSLLP, offsetof(struct paca_struct, vmalloc_sllp)); |
127 | #endif | ||
128 | #ifdef CONFIG_HUGETLB_PAGE | 127 | #ifdef CONFIG_HUGETLB_PAGE |
129 | DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas)); | 128 | DEFINE(PACALOWHTLBAREAS, offsetof(struct paca_struct, context.low_htlb_areas)); |
130 | DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas)); | 129 | DEFINE(PACAHIGHHTLBAREAS, offsetof(struct paca_struct, context.high_htlb_areas)); |
diff --git a/arch/powerpc/kernel/cpu_setup_6xx.S b/arch/powerpc/kernel/cpu_setup_6xx.S index 55ed7716636f..365381fcb27c 100644 --- a/arch/powerpc/kernel/cpu_setup_6xx.S +++ b/arch/powerpc/kernel/cpu_setup_6xx.S | |||
@@ -210,9 +210,11 @@ setup_745x_specifics: | |||
210 | * the firmware. If any, we disable NAP capability as | 210 | * the firmware. If any, we disable NAP capability as |
211 | * it's known to be bogus on rev 2.1 and earlier | 211 | * it's known to be bogus on rev 2.1 and earlier |
212 | */ | 212 | */ |
213 | BEGIN_FTR_SECTION | ||
213 | mfspr r11,SPRN_L3CR | 214 | mfspr r11,SPRN_L3CR |
214 | andis. r11,r11,L3CR_L3E@h | 215 | andis. r11,r11,L3CR_L3E@h |
215 | beq 1f | 216 | beq 1f |
217 | END_FTR_SECTION_IFSET(CPU_FTR_L3CR) | ||
216 | lwz r6,CPU_SPEC_FEATURES(r5) | 218 | lwz r6,CPU_SPEC_FEATURES(r5) |
217 | andi. r0,r6,CPU_FTR_L3_DISABLE_NAP | 219 | andi. r0,r6,CPU_FTR_L3_DISABLE_NAP |
218 | beq 1f | 220 | beq 1f |
diff --git a/arch/powerpc/kernel/cpu_setup_power4.S b/arch/powerpc/kernel/cpu_setup_power4.S index b61d86e7ceb6..271418308d53 100644 --- a/arch/powerpc/kernel/cpu_setup_power4.S +++ b/arch/powerpc/kernel/cpu_setup_power4.S | |||
@@ -73,23 +73,6 @@ _GLOBAL(__970_cpu_preinit) | |||
73 | isync | 73 | isync |
74 | blr | 74 | blr |
75 | 75 | ||
76 | _GLOBAL(__setup_cpu_power4) | ||
77 | blr | ||
78 | |||
79 | _GLOBAL(__setup_cpu_be) | ||
80 | /* Set large page sizes LP=0: 16MB, LP=1: 64KB */ | ||
81 | addi r3, 0, 0 | ||
82 | ori r3, r3, HID6_LB | ||
83 | sldi r3, r3, 32 | ||
84 | nor r3, r3, r3 | ||
85 | mfspr r4, SPRN_HID6 | ||
86 | and r4, r4, r3 | ||
87 | addi r3, 0, 0x02000 | ||
88 | sldi r3, r3, 32 | ||
89 | or r4, r4, r3 | ||
90 | mtspr SPRN_HID6, r4 | ||
91 | blr | ||
92 | |||
93 | _GLOBAL(__setup_cpu_ppc970) | 76 | _GLOBAL(__setup_cpu_ppc970) |
94 | mfspr r0,SPRN_HID0 | 77 | mfspr r0,SPRN_HID0 |
95 | li r11,5 /* clear DOZE and SLEEP */ | 78 | li r11,5 /* clear DOZE and SLEEP */ |
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c index 3f7182db9ed5..1c114880dc05 100644 --- a/arch/powerpc/kernel/cputable.c +++ b/arch/powerpc/kernel/cputable.c | |||
@@ -30,11 +30,7 @@ EXPORT_SYMBOL(cur_cpu_spec); | |||
30 | * part of the cputable though. That has to be fixed for both ppc32 | 30 | * part of the cputable though. That has to be fixed for both ppc32 |
31 | * and ppc64 | 31 | * and ppc64 |
32 | */ | 32 | */ |
33 | #ifdef CONFIG_PPC64 | 33 | #ifdef CONFIG_PPC32 |
34 | extern void __setup_cpu_power3(unsigned long offset, struct cpu_spec* spec); | ||
35 | extern void __setup_cpu_power4(unsigned long offset, struct cpu_spec* spec); | ||
36 | extern void __setup_cpu_be(unsigned long offset, struct cpu_spec* spec); | ||
37 | #else | ||
38 | extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec); | 34 | extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec); |
39 | extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec); | 35 | extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec); |
40 | extern void __setup_cpu_750(unsigned long offset, struct cpu_spec* spec); | 36 | extern void __setup_cpu_750(unsigned long offset, struct cpu_spec* spec); |
@@ -58,7 +54,8 @@ extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); | |||
58 | #define COMMON_USER_POWER5_PLUS (COMMON_USER_PPC64 | PPC_FEATURE_POWER5_PLUS|\ | 54 | #define COMMON_USER_POWER5_PLUS (COMMON_USER_PPC64 | PPC_FEATURE_POWER5_PLUS|\ |
59 | PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP) | 55 | PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP) |
60 | #define COMMON_USER_POWER6 (COMMON_USER_PPC64 | PPC_FEATURE_ARCH_2_05 |\ | 56 | #define COMMON_USER_POWER6 (COMMON_USER_PPC64 | PPC_FEATURE_ARCH_2_05 |\ |
61 | PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP) | 57 | PPC_FEATURE_SMT | PPC_FEATURE_ICACHE_SNOOP | \ |
58 | PPC_FEATURE_TRUE_LE) | ||
62 | #define COMMON_USER_BOOKE (PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \ | 59 | #define COMMON_USER_BOOKE (PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU | \ |
63 | PPC_FEATURE_BOOKE) | 60 | PPC_FEATURE_BOOKE) |
64 | 61 | ||
@@ -78,11 +75,10 @@ struct cpu_spec cpu_specs[] = { | |||
78 | .pvr_value = 0x00400000, | 75 | .pvr_value = 0x00400000, |
79 | .cpu_name = "POWER3 (630)", | 76 | .cpu_name = "POWER3 (630)", |
80 | .cpu_features = CPU_FTRS_POWER3, | 77 | .cpu_features = CPU_FTRS_POWER3, |
81 | .cpu_user_features = COMMON_USER_PPC64, | 78 | .cpu_user_features = COMMON_USER_PPC64|PPC_FEATURE_PPC_LE, |
82 | .icache_bsize = 128, | 79 | .icache_bsize = 128, |
83 | .dcache_bsize = 128, | 80 | .dcache_bsize = 128, |
84 | .num_pmcs = 8, | 81 | .num_pmcs = 8, |
85 | .cpu_setup = __setup_cpu_power3, | ||
86 | .oprofile_cpu_type = "ppc64/power3", | 82 | .oprofile_cpu_type = "ppc64/power3", |
87 | .oprofile_type = PPC_OPROFILE_RS64, | 83 | .oprofile_type = PPC_OPROFILE_RS64, |
88 | .platform = "power3", | 84 | .platform = "power3", |
@@ -92,11 +88,10 @@ struct cpu_spec cpu_specs[] = { | |||
92 | .pvr_value = 0x00410000, | 88 | .pvr_value = 0x00410000, |
93 | .cpu_name = "POWER3 (630+)", | 89 | .cpu_name = "POWER3 (630+)", |
94 | .cpu_features = CPU_FTRS_POWER3, | 90 | .cpu_features = CPU_FTRS_POWER3, |
95 | .cpu_user_features = COMMON_USER_PPC64, | 91 | .cpu_user_features = COMMON_USER_PPC64|PPC_FEATURE_PPC_LE, |
96 | .icache_bsize = 128, | 92 | .icache_bsize = 128, |
97 | .dcache_bsize = 128, | 93 | .dcache_bsize = 128, |
98 | .num_pmcs = 8, | 94 | .num_pmcs = 8, |
99 | .cpu_setup = __setup_cpu_power3, | ||
100 | .oprofile_cpu_type = "ppc64/power3", | 95 | .oprofile_cpu_type = "ppc64/power3", |
101 | .oprofile_type = PPC_OPROFILE_RS64, | 96 | .oprofile_type = PPC_OPROFILE_RS64, |
102 | .platform = "power3", | 97 | .platform = "power3", |
@@ -110,7 +105,6 @@ struct cpu_spec cpu_specs[] = { | |||
110 | .icache_bsize = 128, | 105 | .icache_bsize = 128, |
111 | .dcache_bsize = 128, | 106 | .dcache_bsize = 128, |
112 | .num_pmcs = 8, | 107 | .num_pmcs = 8, |
113 | .cpu_setup = __setup_cpu_power3, | ||
114 | .oprofile_cpu_type = "ppc64/rs64", | 108 | .oprofile_cpu_type = "ppc64/rs64", |
115 | .oprofile_type = PPC_OPROFILE_RS64, | 109 | .oprofile_type = PPC_OPROFILE_RS64, |
116 | .platform = "rs64", | 110 | .platform = "rs64", |
@@ -124,7 +118,6 @@ struct cpu_spec cpu_specs[] = { | |||
124 | .icache_bsize = 128, | 118 | .icache_bsize = 128, |
125 | .dcache_bsize = 128, | 119 | .dcache_bsize = 128, |
126 | .num_pmcs = 8, | 120 | .num_pmcs = 8, |
127 | .cpu_setup = __setup_cpu_power3, | ||
128 | .oprofile_cpu_type = "ppc64/rs64", | 121 | .oprofile_cpu_type = "ppc64/rs64", |
129 | .oprofile_type = PPC_OPROFILE_RS64, | 122 | .oprofile_type = PPC_OPROFILE_RS64, |
130 | .platform = "rs64", | 123 | .platform = "rs64", |
@@ -138,7 +131,6 @@ struct cpu_spec cpu_specs[] = { | |||
138 | .icache_bsize = 128, | 131 | .icache_bsize = 128, |
139 | .dcache_bsize = 128, | 132 | .dcache_bsize = 128, |
140 | .num_pmcs = 8, | 133 | .num_pmcs = 8, |
141 | .cpu_setup = __setup_cpu_power3, | ||
142 | .oprofile_cpu_type = "ppc64/rs64", | 134 | .oprofile_cpu_type = "ppc64/rs64", |
143 | .oprofile_type = PPC_OPROFILE_RS64, | 135 | .oprofile_type = PPC_OPROFILE_RS64, |
144 | .platform = "rs64", | 136 | .platform = "rs64", |
@@ -152,7 +144,6 @@ struct cpu_spec cpu_specs[] = { | |||
152 | .icache_bsize = 128, | 144 | .icache_bsize = 128, |
153 | .dcache_bsize = 128, | 145 | .dcache_bsize = 128, |
154 | .num_pmcs = 8, | 146 | .num_pmcs = 8, |
155 | .cpu_setup = __setup_cpu_power3, | ||
156 | .oprofile_cpu_type = "ppc64/rs64", | 147 | .oprofile_cpu_type = "ppc64/rs64", |
157 | .oprofile_type = PPC_OPROFILE_RS64, | 148 | .oprofile_type = PPC_OPROFILE_RS64, |
158 | .platform = "rs64", | 149 | .platform = "rs64", |
@@ -166,7 +157,6 @@ struct cpu_spec cpu_specs[] = { | |||
166 | .icache_bsize = 128, | 157 | .icache_bsize = 128, |
167 | .dcache_bsize = 128, | 158 | .dcache_bsize = 128, |
168 | .num_pmcs = 8, | 159 | .num_pmcs = 8, |
169 | .cpu_setup = __setup_cpu_power4, | ||
170 | .oprofile_cpu_type = "ppc64/power4", | 160 | .oprofile_cpu_type = "ppc64/power4", |
171 | .oprofile_type = PPC_OPROFILE_POWER4, | 161 | .oprofile_type = PPC_OPROFILE_POWER4, |
172 | .platform = "power4", | 162 | .platform = "power4", |
@@ -180,7 +170,6 @@ struct cpu_spec cpu_specs[] = { | |||
180 | .icache_bsize = 128, | 170 | .icache_bsize = 128, |
181 | .dcache_bsize = 128, | 171 | .dcache_bsize = 128, |
182 | .num_pmcs = 8, | 172 | .num_pmcs = 8, |
183 | .cpu_setup = __setup_cpu_power4, | ||
184 | .oprofile_cpu_type = "ppc64/power4", | 173 | .oprofile_cpu_type = "ppc64/power4", |
185 | .oprofile_type = PPC_OPROFILE_POWER4, | 174 | .oprofile_type = PPC_OPROFILE_POWER4, |
186 | .platform = "power4", | 175 | .platform = "power4", |
@@ -200,17 +189,11 @@ struct cpu_spec cpu_specs[] = { | |||
200 | .oprofile_type = PPC_OPROFILE_POWER4, | 189 | .oprofile_type = PPC_OPROFILE_POWER4, |
201 | .platform = "ppc970", | 190 | .platform = "ppc970", |
202 | }, | 191 | }, |
203 | #endif /* CONFIG_PPC64 */ | ||
204 | #if defined(CONFIG_PPC64) || defined(CONFIG_POWER4) | ||
205 | { /* PPC970FX */ | 192 | { /* PPC970FX */ |
206 | .pvr_mask = 0xffff0000, | 193 | .pvr_mask = 0xffff0000, |
207 | .pvr_value = 0x003c0000, | 194 | .pvr_value = 0x003c0000, |
208 | .cpu_name = "PPC970FX", | 195 | .cpu_name = "PPC970FX", |
209 | #ifdef CONFIG_PPC32 | ||
210 | .cpu_features = CPU_FTRS_970_32, | ||
211 | #else | ||
212 | .cpu_features = CPU_FTRS_PPC970, | 196 | .cpu_features = CPU_FTRS_PPC970, |
213 | #endif | ||
214 | .cpu_user_features = COMMON_USER_POWER4 | | 197 | .cpu_user_features = COMMON_USER_POWER4 | |
215 | PPC_FEATURE_HAS_ALTIVEC_COMP, | 198 | PPC_FEATURE_HAS_ALTIVEC_COMP, |
216 | .icache_bsize = 128, | 199 | .icache_bsize = 128, |
@@ -221,8 +204,6 @@ struct cpu_spec cpu_specs[] = { | |||
221 | .oprofile_type = PPC_OPROFILE_POWER4, | 204 | .oprofile_type = PPC_OPROFILE_POWER4, |
222 | .platform = "ppc970", | 205 | .platform = "ppc970", |
223 | }, | 206 | }, |
224 | #endif /* defined(CONFIG_PPC64) || defined(CONFIG_POWER4) */ | ||
225 | #ifdef CONFIG_PPC64 | ||
226 | { /* PPC970MP */ | 207 | { /* PPC970MP */ |
227 | .pvr_mask = 0xffff0000, | 208 | .pvr_mask = 0xffff0000, |
228 | .pvr_value = 0x00440000, | 209 | .pvr_value = 0x00440000, |
@@ -232,6 +213,7 @@ struct cpu_spec cpu_specs[] = { | |||
232 | PPC_FEATURE_HAS_ALTIVEC_COMP, | 213 | PPC_FEATURE_HAS_ALTIVEC_COMP, |
233 | .icache_bsize = 128, | 214 | .icache_bsize = 128, |
234 | .dcache_bsize = 128, | 215 | .dcache_bsize = 128, |
216 | .num_pmcs = 8, | ||
235 | .cpu_setup = __setup_cpu_ppc970, | 217 | .cpu_setup = __setup_cpu_ppc970, |
236 | .oprofile_cpu_type = "ppc64/970", | 218 | .oprofile_cpu_type = "ppc64/970", |
237 | .oprofile_type = PPC_OPROFILE_POWER4, | 219 | .oprofile_type = PPC_OPROFILE_POWER4, |
@@ -246,9 +228,13 @@ struct cpu_spec cpu_specs[] = { | |||
246 | .icache_bsize = 128, | 228 | .icache_bsize = 128, |
247 | .dcache_bsize = 128, | 229 | .dcache_bsize = 128, |
248 | .num_pmcs = 6, | 230 | .num_pmcs = 6, |
249 | .cpu_setup = __setup_cpu_power4, | ||
250 | .oprofile_cpu_type = "ppc64/power5", | 231 | .oprofile_cpu_type = "ppc64/power5", |
251 | .oprofile_type = PPC_OPROFILE_POWER4, | 232 | .oprofile_type = PPC_OPROFILE_POWER4, |
233 | /* SIHV / SIPR bits are implemented on POWER4+ (GQ) | ||
234 | * and above but only works on POWER5 and above | ||
235 | */ | ||
236 | .oprofile_mmcra_sihv = MMCRA_SIHV, | ||
237 | .oprofile_mmcra_sipr = MMCRA_SIPR, | ||
252 | .platform = "power5", | 238 | .platform = "power5", |
253 | }, | 239 | }, |
254 | { /* Power5 GS */ | 240 | { /* Power5 GS */ |
@@ -260,9 +246,10 @@ struct cpu_spec cpu_specs[] = { | |||
260 | .icache_bsize = 128, | 246 | .icache_bsize = 128, |
261 | .dcache_bsize = 128, | 247 | .dcache_bsize = 128, |
262 | .num_pmcs = 6, | 248 | .num_pmcs = 6, |
263 | .cpu_setup = __setup_cpu_power4, | ||
264 | .oprofile_cpu_type = "ppc64/power5+", | 249 | .oprofile_cpu_type = "ppc64/power5+", |
265 | .oprofile_type = PPC_OPROFILE_POWER4, | 250 | .oprofile_type = PPC_OPROFILE_POWER4, |
251 | .oprofile_mmcra_sihv = MMCRA_SIHV, | ||
252 | .oprofile_mmcra_sipr = MMCRA_SIPR, | ||
266 | .platform = "power5+", | 253 | .platform = "power5+", |
267 | }, | 254 | }, |
268 | { /* Power6 */ | 255 | { /* Power6 */ |
@@ -273,10 +260,13 @@ struct cpu_spec cpu_specs[] = { | |||
273 | .cpu_user_features = COMMON_USER_POWER6, | 260 | .cpu_user_features = COMMON_USER_POWER6, |
274 | .icache_bsize = 128, | 261 | .icache_bsize = 128, |
275 | .dcache_bsize = 128, | 262 | .dcache_bsize = 128, |
276 | .num_pmcs = 6, | 263 | .num_pmcs = 8, |
277 | .cpu_setup = __setup_cpu_power4, | ||
278 | .oprofile_cpu_type = "ppc64/power6", | 264 | .oprofile_cpu_type = "ppc64/power6", |
279 | .oprofile_type = PPC_OPROFILE_POWER4, | 265 | .oprofile_type = PPC_OPROFILE_POWER4, |
266 | .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV, | ||
267 | .oprofile_mmcra_sipr = POWER6_MMCRA_SIPR, | ||
268 | .oprofile_mmcra_clear = POWER6_MMCRA_THRM | | ||
269 | POWER6_MMCRA_OTHER, | ||
280 | .platform = "power6", | 270 | .platform = "power6", |
281 | }, | 271 | }, |
282 | { /* Cell Broadband Engine */ | 272 | { /* Cell Broadband Engine */ |
@@ -289,7 +279,6 @@ struct cpu_spec cpu_specs[] = { | |||
289 | PPC_FEATURE_SMT, | 279 | PPC_FEATURE_SMT, |
290 | .icache_bsize = 128, | 280 | .icache_bsize = 128, |
291 | .dcache_bsize = 128, | 281 | .dcache_bsize = 128, |
292 | .cpu_setup = __setup_cpu_be, | ||
293 | .platform = "ppc-cell-be", | 282 | .platform = "ppc-cell-be", |
294 | }, | 283 | }, |
295 | { /* default match */ | 284 | { /* default match */ |
@@ -301,7 +290,6 @@ struct cpu_spec cpu_specs[] = { | |||
301 | .icache_bsize = 128, | 290 | .icache_bsize = 128, |
302 | .dcache_bsize = 128, | 291 | .dcache_bsize = 128, |
303 | .num_pmcs = 6, | 292 | .num_pmcs = 6, |
304 | .cpu_setup = __setup_cpu_power4, | ||
305 | .platform = "power4", | 293 | .platform = "power4", |
306 | } | 294 | } |
307 | #endif /* CONFIG_PPC64 */ | 295 | #endif /* CONFIG_PPC64 */ |
@@ -323,7 +311,7 @@ struct cpu_spec cpu_specs[] = { | |||
323 | .pvr_value = 0x00030000, | 311 | .pvr_value = 0x00030000, |
324 | .cpu_name = "603", | 312 | .cpu_name = "603", |
325 | .cpu_features = CPU_FTRS_603, | 313 | .cpu_features = CPU_FTRS_603, |
326 | .cpu_user_features = COMMON_USER, | 314 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
327 | .icache_bsize = 32, | 315 | .icache_bsize = 32, |
328 | .dcache_bsize = 32, | 316 | .dcache_bsize = 32, |
329 | .cpu_setup = __setup_cpu_603, | 317 | .cpu_setup = __setup_cpu_603, |
@@ -334,7 +322,7 @@ struct cpu_spec cpu_specs[] = { | |||
334 | .pvr_value = 0x00060000, | 322 | .pvr_value = 0x00060000, |
335 | .cpu_name = "603e", | 323 | .cpu_name = "603e", |
336 | .cpu_features = CPU_FTRS_603, | 324 | .cpu_features = CPU_FTRS_603, |
337 | .cpu_user_features = COMMON_USER, | 325 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
338 | .icache_bsize = 32, | 326 | .icache_bsize = 32, |
339 | .dcache_bsize = 32, | 327 | .dcache_bsize = 32, |
340 | .cpu_setup = __setup_cpu_603, | 328 | .cpu_setup = __setup_cpu_603, |
@@ -345,7 +333,7 @@ struct cpu_spec cpu_specs[] = { | |||
345 | .pvr_value = 0x00070000, | 333 | .pvr_value = 0x00070000, |
346 | .cpu_name = "603ev", | 334 | .cpu_name = "603ev", |
347 | .cpu_features = CPU_FTRS_603, | 335 | .cpu_features = CPU_FTRS_603, |
348 | .cpu_user_features = COMMON_USER, | 336 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
349 | .icache_bsize = 32, | 337 | .icache_bsize = 32, |
350 | .dcache_bsize = 32, | 338 | .dcache_bsize = 32, |
351 | .cpu_setup = __setup_cpu_603, | 339 | .cpu_setup = __setup_cpu_603, |
@@ -356,7 +344,7 @@ struct cpu_spec cpu_specs[] = { | |||
356 | .pvr_value = 0x00040000, | 344 | .pvr_value = 0x00040000, |
357 | .cpu_name = "604", | 345 | .cpu_name = "604", |
358 | .cpu_features = CPU_FTRS_604, | 346 | .cpu_features = CPU_FTRS_604, |
359 | .cpu_user_features = COMMON_USER, | 347 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
360 | .icache_bsize = 32, | 348 | .icache_bsize = 32, |
361 | .dcache_bsize = 32, | 349 | .dcache_bsize = 32, |
362 | .num_pmcs = 2, | 350 | .num_pmcs = 2, |
@@ -368,7 +356,7 @@ struct cpu_spec cpu_specs[] = { | |||
368 | .pvr_value = 0x00090000, | 356 | .pvr_value = 0x00090000, |
369 | .cpu_name = "604e", | 357 | .cpu_name = "604e", |
370 | .cpu_features = CPU_FTRS_604, | 358 | .cpu_features = CPU_FTRS_604, |
371 | .cpu_user_features = COMMON_USER, | 359 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
372 | .icache_bsize = 32, | 360 | .icache_bsize = 32, |
373 | .dcache_bsize = 32, | 361 | .dcache_bsize = 32, |
374 | .num_pmcs = 4, | 362 | .num_pmcs = 4, |
@@ -380,7 +368,7 @@ struct cpu_spec cpu_specs[] = { | |||
380 | .pvr_value = 0x00090000, | 368 | .pvr_value = 0x00090000, |
381 | .cpu_name = "604r", | 369 | .cpu_name = "604r", |
382 | .cpu_features = CPU_FTRS_604, | 370 | .cpu_features = CPU_FTRS_604, |
383 | .cpu_user_features = COMMON_USER, | 371 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
384 | .icache_bsize = 32, | 372 | .icache_bsize = 32, |
385 | .dcache_bsize = 32, | 373 | .dcache_bsize = 32, |
386 | .num_pmcs = 4, | 374 | .num_pmcs = 4, |
@@ -392,7 +380,7 @@ struct cpu_spec cpu_specs[] = { | |||
392 | .pvr_value = 0x000a0000, | 380 | .pvr_value = 0x000a0000, |
393 | .cpu_name = "604ev", | 381 | .cpu_name = "604ev", |
394 | .cpu_features = CPU_FTRS_604, | 382 | .cpu_features = CPU_FTRS_604, |
395 | .cpu_user_features = COMMON_USER, | 383 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
396 | .icache_bsize = 32, | 384 | .icache_bsize = 32, |
397 | .dcache_bsize = 32, | 385 | .dcache_bsize = 32, |
398 | .num_pmcs = 4, | 386 | .num_pmcs = 4, |
@@ -404,7 +392,7 @@ struct cpu_spec cpu_specs[] = { | |||
404 | .pvr_value = 0x00084202, | 392 | .pvr_value = 0x00084202, |
405 | .cpu_name = "740/750", | 393 | .cpu_name = "740/750", |
406 | .cpu_features = CPU_FTRS_740_NOTAU, | 394 | .cpu_features = CPU_FTRS_740_NOTAU, |
407 | .cpu_user_features = COMMON_USER, | 395 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
408 | .icache_bsize = 32, | 396 | .icache_bsize = 32, |
409 | .dcache_bsize = 32, | 397 | .dcache_bsize = 32, |
410 | .num_pmcs = 4, | 398 | .num_pmcs = 4, |
@@ -416,7 +404,7 @@ struct cpu_spec cpu_specs[] = { | |||
416 | .pvr_value = 0x00080100, | 404 | .pvr_value = 0x00080100, |
417 | .cpu_name = "750CX", | 405 | .cpu_name = "750CX", |
418 | .cpu_features = CPU_FTRS_750, | 406 | .cpu_features = CPU_FTRS_750, |
419 | .cpu_user_features = COMMON_USER, | 407 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
420 | .icache_bsize = 32, | 408 | .icache_bsize = 32, |
421 | .dcache_bsize = 32, | 409 | .dcache_bsize = 32, |
422 | .num_pmcs = 4, | 410 | .num_pmcs = 4, |
@@ -428,7 +416,7 @@ struct cpu_spec cpu_specs[] = { | |||
428 | .pvr_value = 0x00082200, | 416 | .pvr_value = 0x00082200, |
429 | .cpu_name = "750CX", | 417 | .cpu_name = "750CX", |
430 | .cpu_features = CPU_FTRS_750, | 418 | .cpu_features = CPU_FTRS_750, |
431 | .cpu_user_features = COMMON_USER, | 419 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
432 | .icache_bsize = 32, | 420 | .icache_bsize = 32, |
433 | .dcache_bsize = 32, | 421 | .dcache_bsize = 32, |
434 | .num_pmcs = 4, | 422 | .num_pmcs = 4, |
@@ -440,7 +428,7 @@ struct cpu_spec cpu_specs[] = { | |||
440 | .pvr_value = 0x00082210, | 428 | .pvr_value = 0x00082210, |
441 | .cpu_name = "750CXe", | 429 | .cpu_name = "750CXe", |
442 | .cpu_features = CPU_FTRS_750, | 430 | .cpu_features = CPU_FTRS_750, |
443 | .cpu_user_features = COMMON_USER, | 431 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
444 | .icache_bsize = 32, | 432 | .icache_bsize = 32, |
445 | .dcache_bsize = 32, | 433 | .dcache_bsize = 32, |
446 | .num_pmcs = 4, | 434 | .num_pmcs = 4, |
@@ -452,7 +440,7 @@ struct cpu_spec cpu_specs[] = { | |||
452 | .pvr_value = 0x00083214, | 440 | .pvr_value = 0x00083214, |
453 | .cpu_name = "750CXe", | 441 | .cpu_name = "750CXe", |
454 | .cpu_features = CPU_FTRS_750, | 442 | .cpu_features = CPU_FTRS_750, |
455 | .cpu_user_features = COMMON_USER, | 443 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
456 | .icache_bsize = 32, | 444 | .icache_bsize = 32, |
457 | .dcache_bsize = 32, | 445 | .dcache_bsize = 32, |
458 | .num_pmcs = 4, | 446 | .num_pmcs = 4, |
@@ -464,7 +452,7 @@ struct cpu_spec cpu_specs[] = { | |||
464 | .pvr_value = 0x00083000, | 452 | .pvr_value = 0x00083000, |
465 | .cpu_name = "745/755", | 453 | .cpu_name = "745/755", |
466 | .cpu_features = CPU_FTRS_750, | 454 | .cpu_features = CPU_FTRS_750, |
467 | .cpu_user_features = COMMON_USER, | 455 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
468 | .icache_bsize = 32, | 456 | .icache_bsize = 32, |
469 | .dcache_bsize = 32, | 457 | .dcache_bsize = 32, |
470 | .num_pmcs = 4, | 458 | .num_pmcs = 4, |
@@ -476,7 +464,7 @@ struct cpu_spec cpu_specs[] = { | |||
476 | .pvr_value = 0x70000100, | 464 | .pvr_value = 0x70000100, |
477 | .cpu_name = "750FX", | 465 | .cpu_name = "750FX", |
478 | .cpu_features = CPU_FTRS_750FX1, | 466 | .cpu_features = CPU_FTRS_750FX1, |
479 | .cpu_user_features = COMMON_USER, | 467 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
480 | .icache_bsize = 32, | 468 | .icache_bsize = 32, |
481 | .dcache_bsize = 32, | 469 | .dcache_bsize = 32, |
482 | .num_pmcs = 4, | 470 | .num_pmcs = 4, |
@@ -488,7 +476,7 @@ struct cpu_spec cpu_specs[] = { | |||
488 | .pvr_value = 0x70000200, | 476 | .pvr_value = 0x70000200, |
489 | .cpu_name = "750FX", | 477 | .cpu_name = "750FX", |
490 | .cpu_features = CPU_FTRS_750FX2, | 478 | .cpu_features = CPU_FTRS_750FX2, |
491 | .cpu_user_features = COMMON_USER, | 479 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
492 | .icache_bsize = 32, | 480 | .icache_bsize = 32, |
493 | .dcache_bsize = 32, | 481 | .dcache_bsize = 32, |
494 | .num_pmcs = 4, | 482 | .num_pmcs = 4, |
@@ -500,7 +488,7 @@ struct cpu_spec cpu_specs[] = { | |||
500 | .pvr_value = 0x70000000, | 488 | .pvr_value = 0x70000000, |
501 | .cpu_name = "750FX", | 489 | .cpu_name = "750FX", |
502 | .cpu_features = CPU_FTRS_750FX, | 490 | .cpu_features = CPU_FTRS_750FX, |
503 | .cpu_user_features = COMMON_USER, | 491 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
504 | .icache_bsize = 32, | 492 | .icache_bsize = 32, |
505 | .dcache_bsize = 32, | 493 | .dcache_bsize = 32, |
506 | .num_pmcs = 4, | 494 | .num_pmcs = 4, |
@@ -512,7 +500,7 @@ struct cpu_spec cpu_specs[] = { | |||
512 | .pvr_value = 0x70020000, | 500 | .pvr_value = 0x70020000, |
513 | .cpu_name = "750GX", | 501 | .cpu_name = "750GX", |
514 | .cpu_features = CPU_FTRS_750GX, | 502 | .cpu_features = CPU_FTRS_750GX, |
515 | .cpu_user_features = COMMON_USER, | 503 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
516 | .icache_bsize = 32, | 504 | .icache_bsize = 32, |
517 | .dcache_bsize = 32, | 505 | .dcache_bsize = 32, |
518 | .num_pmcs = 4, | 506 | .num_pmcs = 4, |
@@ -524,7 +512,7 @@ struct cpu_spec cpu_specs[] = { | |||
524 | .pvr_value = 0x00080000, | 512 | .pvr_value = 0x00080000, |
525 | .cpu_name = "740/750", | 513 | .cpu_name = "740/750", |
526 | .cpu_features = CPU_FTRS_740, | 514 | .cpu_features = CPU_FTRS_740, |
527 | .cpu_user_features = COMMON_USER, | 515 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
528 | .icache_bsize = 32, | 516 | .icache_bsize = 32, |
529 | .dcache_bsize = 32, | 517 | .dcache_bsize = 32, |
530 | .num_pmcs = 4, | 518 | .num_pmcs = 4, |
@@ -536,7 +524,8 @@ struct cpu_spec cpu_specs[] = { | |||
536 | .pvr_value = 0x000c1101, | 524 | .pvr_value = 0x000c1101, |
537 | .cpu_name = "7400 (1.1)", | 525 | .cpu_name = "7400 (1.1)", |
538 | .cpu_features = CPU_FTRS_7400_NOTAU, | 526 | .cpu_features = CPU_FTRS_7400_NOTAU, |
539 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 527 | .cpu_user_features = COMMON_USER | |
528 | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, | ||
540 | .icache_bsize = 32, | 529 | .icache_bsize = 32, |
541 | .dcache_bsize = 32, | 530 | .dcache_bsize = 32, |
542 | .num_pmcs = 4, | 531 | .num_pmcs = 4, |
@@ -548,7 +537,8 @@ struct cpu_spec cpu_specs[] = { | |||
548 | .pvr_value = 0x000c0000, | 537 | .pvr_value = 0x000c0000, |
549 | .cpu_name = "7400", | 538 | .cpu_name = "7400", |
550 | .cpu_features = CPU_FTRS_7400, | 539 | .cpu_features = CPU_FTRS_7400, |
551 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 540 | .cpu_user_features = COMMON_USER | |
541 | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, | ||
552 | .icache_bsize = 32, | 542 | .icache_bsize = 32, |
553 | .dcache_bsize = 32, | 543 | .dcache_bsize = 32, |
554 | .num_pmcs = 4, | 544 | .num_pmcs = 4, |
@@ -560,7 +550,8 @@ struct cpu_spec cpu_specs[] = { | |||
560 | .pvr_value = 0x800c0000, | 550 | .pvr_value = 0x800c0000, |
561 | .cpu_name = "7410", | 551 | .cpu_name = "7410", |
562 | .cpu_features = CPU_FTRS_7400, | 552 | .cpu_features = CPU_FTRS_7400, |
563 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 553 | .cpu_user_features = COMMON_USER | |
554 | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, | ||
564 | .icache_bsize = 32, | 555 | .icache_bsize = 32, |
565 | .dcache_bsize = 32, | 556 | .dcache_bsize = 32, |
566 | .num_pmcs = 4, | 557 | .num_pmcs = 4, |
@@ -572,7 +563,8 @@ struct cpu_spec cpu_specs[] = { | |||
572 | .pvr_value = 0x80000200, | 563 | .pvr_value = 0x80000200, |
573 | .cpu_name = "7450", | 564 | .cpu_name = "7450", |
574 | .cpu_features = CPU_FTRS_7450_20, | 565 | .cpu_features = CPU_FTRS_7450_20, |
575 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 566 | .cpu_user_features = COMMON_USER | |
567 | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, | ||
576 | .icache_bsize = 32, | 568 | .icache_bsize = 32, |
577 | .dcache_bsize = 32, | 569 | .dcache_bsize = 32, |
578 | .num_pmcs = 6, | 570 | .num_pmcs = 6, |
@@ -586,7 +578,8 @@ struct cpu_spec cpu_specs[] = { | |||
586 | .pvr_value = 0x80000201, | 578 | .pvr_value = 0x80000201, |
587 | .cpu_name = "7450", | 579 | .cpu_name = "7450", |
588 | .cpu_features = CPU_FTRS_7450_21, | 580 | .cpu_features = CPU_FTRS_7450_21, |
589 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 581 | .cpu_user_features = COMMON_USER | |
582 | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, | ||
590 | .icache_bsize = 32, | 583 | .icache_bsize = 32, |
591 | .dcache_bsize = 32, | 584 | .dcache_bsize = 32, |
592 | .num_pmcs = 6, | 585 | .num_pmcs = 6, |
@@ -600,7 +593,8 @@ struct cpu_spec cpu_specs[] = { | |||
600 | .pvr_value = 0x80000000, | 593 | .pvr_value = 0x80000000, |
601 | .cpu_name = "7450", | 594 | .cpu_name = "7450", |
602 | .cpu_features = CPU_FTRS_7450_23, | 595 | .cpu_features = CPU_FTRS_7450_23, |
603 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 596 | .cpu_user_features = COMMON_USER | |
597 | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, | ||
604 | .icache_bsize = 32, | 598 | .icache_bsize = 32, |
605 | .dcache_bsize = 32, | 599 | .dcache_bsize = 32, |
606 | .num_pmcs = 6, | 600 | .num_pmcs = 6, |
@@ -614,7 +608,8 @@ struct cpu_spec cpu_specs[] = { | |||
614 | .pvr_value = 0x80010100, | 608 | .pvr_value = 0x80010100, |
615 | .cpu_name = "7455", | 609 | .cpu_name = "7455", |
616 | .cpu_features = CPU_FTRS_7455_1, | 610 | .cpu_features = CPU_FTRS_7455_1, |
617 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 611 | .cpu_user_features = COMMON_USER | |
612 | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, | ||
618 | .icache_bsize = 32, | 613 | .icache_bsize = 32, |
619 | .dcache_bsize = 32, | 614 | .dcache_bsize = 32, |
620 | .num_pmcs = 6, | 615 | .num_pmcs = 6, |
@@ -628,7 +623,8 @@ struct cpu_spec cpu_specs[] = { | |||
628 | .pvr_value = 0x80010200, | 623 | .pvr_value = 0x80010200, |
629 | .cpu_name = "7455", | 624 | .cpu_name = "7455", |
630 | .cpu_features = CPU_FTRS_7455_20, | 625 | .cpu_features = CPU_FTRS_7455_20, |
631 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 626 | .cpu_user_features = COMMON_USER | |
627 | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, | ||
632 | .icache_bsize = 32, | 628 | .icache_bsize = 32, |
633 | .dcache_bsize = 32, | 629 | .dcache_bsize = 32, |
634 | .num_pmcs = 6, | 630 | .num_pmcs = 6, |
@@ -642,7 +638,8 @@ struct cpu_spec cpu_specs[] = { | |||
642 | .pvr_value = 0x80010000, | 638 | .pvr_value = 0x80010000, |
643 | .cpu_name = "7455", | 639 | .cpu_name = "7455", |
644 | .cpu_features = CPU_FTRS_7455, | 640 | .cpu_features = CPU_FTRS_7455, |
645 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 641 | .cpu_user_features = COMMON_USER | |
642 | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, | ||
646 | .icache_bsize = 32, | 643 | .icache_bsize = 32, |
647 | .dcache_bsize = 32, | 644 | .dcache_bsize = 32, |
648 | .num_pmcs = 6, | 645 | .num_pmcs = 6, |
@@ -656,7 +653,8 @@ struct cpu_spec cpu_specs[] = { | |||
656 | .pvr_value = 0x80020100, | 653 | .pvr_value = 0x80020100, |
657 | .cpu_name = "7447/7457", | 654 | .cpu_name = "7447/7457", |
658 | .cpu_features = CPU_FTRS_7447_10, | 655 | .cpu_features = CPU_FTRS_7447_10, |
659 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 656 | .cpu_user_features = COMMON_USER | |
657 | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, | ||
660 | .icache_bsize = 32, | 658 | .icache_bsize = 32, |
661 | .dcache_bsize = 32, | 659 | .dcache_bsize = 32, |
662 | .num_pmcs = 6, | 660 | .num_pmcs = 6, |
@@ -670,7 +668,8 @@ struct cpu_spec cpu_specs[] = { | |||
670 | .pvr_value = 0x80020101, | 668 | .pvr_value = 0x80020101, |
671 | .cpu_name = "7447/7457", | 669 | .cpu_name = "7447/7457", |
672 | .cpu_features = CPU_FTRS_7447_10, | 670 | .cpu_features = CPU_FTRS_7447_10, |
673 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 671 | .cpu_user_features = COMMON_USER | |
672 | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, | ||
674 | .icache_bsize = 32, | 673 | .icache_bsize = 32, |
675 | .dcache_bsize = 32, | 674 | .dcache_bsize = 32, |
676 | .num_pmcs = 6, | 675 | .num_pmcs = 6, |
@@ -684,7 +683,7 @@ struct cpu_spec cpu_specs[] = { | |||
684 | .pvr_value = 0x80020000, | 683 | .pvr_value = 0x80020000, |
685 | .cpu_name = "7447/7457", | 684 | .cpu_name = "7447/7457", |
686 | .cpu_features = CPU_FTRS_7447, | 685 | .cpu_features = CPU_FTRS_7447, |
687 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 686 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, |
688 | .icache_bsize = 32, | 687 | .icache_bsize = 32, |
689 | .dcache_bsize = 32, | 688 | .dcache_bsize = 32, |
690 | .num_pmcs = 6, | 689 | .num_pmcs = 6, |
@@ -698,7 +697,8 @@ struct cpu_spec cpu_specs[] = { | |||
698 | .pvr_value = 0x80030000, | 697 | .pvr_value = 0x80030000, |
699 | .cpu_name = "7447A", | 698 | .cpu_name = "7447A", |
700 | .cpu_features = CPU_FTRS_7447A, | 699 | .cpu_features = CPU_FTRS_7447A, |
701 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 700 | .cpu_user_features = COMMON_USER | |
701 | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, | ||
702 | .icache_bsize = 32, | 702 | .icache_bsize = 32, |
703 | .dcache_bsize = 32, | 703 | .dcache_bsize = 32, |
704 | .num_pmcs = 6, | 704 | .num_pmcs = 6, |
@@ -712,7 +712,8 @@ struct cpu_spec cpu_specs[] = { | |||
712 | .pvr_value = 0x80040000, | 712 | .pvr_value = 0x80040000, |
713 | .cpu_name = "7448", | 713 | .cpu_name = "7448", |
714 | .cpu_features = CPU_FTRS_7447A, | 714 | .cpu_features = CPU_FTRS_7447A, |
715 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 715 | .cpu_user_features = COMMON_USER | |
716 | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, | ||
716 | .icache_bsize = 32, | 717 | .icache_bsize = 32, |
717 | .dcache_bsize = 32, | 718 | .dcache_bsize = 32, |
718 | .num_pmcs = 6, | 719 | .num_pmcs = 6, |
@@ -721,6 +722,18 @@ struct cpu_spec cpu_specs[] = { | |||
721 | .oprofile_type = PPC_OPROFILE_G4, | 722 | .oprofile_type = PPC_OPROFILE_G4, |
722 | .platform = "ppc7450", | 723 | .platform = "ppc7450", |
723 | }, | 724 | }, |
725 | { /* 8641 */ | ||
726 | .pvr_mask = 0xffffffff, | ||
727 | .pvr_value = 0x80040010, | ||
728 | .cpu_name = "8641", | ||
729 | .cpu_features = CPU_FTRS_7447A, | ||
730 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | ||
731 | .icache_bsize = 32, | ||
732 | .dcache_bsize = 32, | ||
733 | .num_pmcs = 6, | ||
734 | .cpu_setup = __setup_cpu_745x | ||
735 | }, | ||
736 | |||
724 | { /* 82xx (8240, 8245, 8260 are all 603e cores) */ | 737 | { /* 82xx (8240, 8245, 8260 are all 603e cores) */ |
725 | .pvr_mask = 0x7fff0000, | 738 | .pvr_mask = 0x7fff0000, |
726 | .pvr_value = 0x00810000, | 739 | .pvr_value = 0x00810000, |
diff --git a/arch/powerpc/kernel/crash.c b/arch/powerpc/kernel/crash.c index 778f22fd85d2..dbcb85994f46 100644 --- a/arch/powerpc/kernel/crash.c +++ b/arch/powerpc/kernel/crash.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/elf.h> | 22 | #include <linux/elf.h> |
23 | #include <linux/elfcore.h> | 23 | #include <linux/elfcore.h> |
24 | #include <linux/init.h> | 24 | #include <linux/init.h> |
25 | #include <linux/irq.h> | ||
25 | #include <linux/types.h> | 26 | #include <linux/types.h> |
26 | 27 | ||
27 | #include <asm/processor.h> | 28 | #include <asm/processor.h> |
@@ -174,6 +175,8 @@ static void crash_kexec_prepare_cpus(void) | |||
174 | 175 | ||
175 | void default_machine_crash_shutdown(struct pt_regs *regs) | 176 | void default_machine_crash_shutdown(struct pt_regs *regs) |
176 | { | 177 | { |
178 | unsigned int irq; | ||
179 | |||
177 | /* | 180 | /* |
178 | * This function is only called after the system | 181 | * This function is only called after the system |
179 | * has paniced or is otherwise in a critical state. | 182 | * has paniced or is otherwise in a critical state. |
@@ -186,6 +189,16 @@ void default_machine_crash_shutdown(struct pt_regs *regs) | |||
186 | */ | 189 | */ |
187 | local_irq_disable(); | 190 | local_irq_disable(); |
188 | 191 | ||
192 | for_each_irq(irq) { | ||
193 | struct irq_desc *desc = irq_descp(irq); | ||
194 | |||
195 | if (desc->status & IRQ_INPROGRESS) | ||
196 | desc->handler->end(irq); | ||
197 | |||
198 | if (!(desc->status & IRQ_DISABLED)) | ||
199 | desc->handler->disable(irq); | ||
200 | } | ||
201 | |||
189 | if (ppc_md.kexec_cpu_down) | 202 | if (ppc_md.kexec_cpu_down) |
190 | ppc_md.kexec_cpu_down(1, 0); | 203 | ppc_md.kexec_cpu_down(1, 0); |
191 | 204 | ||
diff --git a/arch/powerpc/kernel/crash_dump.c b/arch/powerpc/kernel/crash_dump.c index 764d07329716..371973be8d71 100644 --- a/arch/powerpc/kernel/crash_dump.c +++ b/arch/powerpc/kernel/crash_dump.c | |||
@@ -25,6 +25,11 @@ | |||
25 | #define DBG(fmt...) | 25 | #define DBG(fmt...) |
26 | #endif | 26 | #endif |
27 | 27 | ||
28 | void reserve_kdump_trampoline(void) | ||
29 | { | ||
30 | lmb_reserve(0, KDUMP_RESERVE_LIMIT); | ||
31 | } | ||
32 | |||
28 | static void __init create_trampoline(unsigned long addr) | 33 | static void __init create_trampoline(unsigned long addr) |
29 | { | 34 | { |
30 | /* The maximum range of a single instruction branch, is the current | 35 | /* The maximum range of a single instruction branch, is the current |
@@ -39,11 +44,11 @@ static void __init create_trampoline(unsigned long addr) | |||
39 | create_branch(addr + 4, addr + PHYSICAL_START, 0); | 44 | create_branch(addr + 4, addr + PHYSICAL_START, 0); |
40 | } | 45 | } |
41 | 46 | ||
42 | void __init kdump_setup(void) | 47 | void __init setup_kdump_trampoline(void) |
43 | { | 48 | { |
44 | unsigned long i; | 49 | unsigned long i; |
45 | 50 | ||
46 | DBG(" -> kdump_setup()\n"); | 51 | DBG(" -> setup_kdump_trampoline()\n"); |
47 | 52 | ||
48 | for (i = KDUMP_TRAMPOLINE_START; i < KDUMP_TRAMPOLINE_END; i += 8) { | 53 | for (i = KDUMP_TRAMPOLINE_START; i < KDUMP_TRAMPOLINE_END; i += 8) { |
49 | create_trampoline(i); | 54 | create_trampoline(i); |
@@ -52,7 +57,7 @@ void __init kdump_setup(void) | |||
52 | create_trampoline(__pa(system_reset_fwnmi) - PHYSICAL_START); | 57 | create_trampoline(__pa(system_reset_fwnmi) - PHYSICAL_START); |
53 | create_trampoline(__pa(machine_check_fwnmi) - PHYSICAL_START); | 58 | create_trampoline(__pa(machine_check_fwnmi) - PHYSICAL_START); |
54 | 59 | ||
55 | DBG(" <- kdump_setup()\n"); | 60 | DBG(" <- setup_kdump_trampoline()\n"); |
56 | } | 61 | } |
57 | 62 | ||
58 | #ifdef CONFIG_PROC_VMCORE | 63 | #ifdef CONFIG_PROC_VMCORE |
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 19ad5c6b1818..221062c960c9 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
@@ -57,6 +57,7 @@ system_call_common: | |||
57 | beq- 1f | 57 | beq- 1f |
58 | ld r1,PACAKSAVE(r13) | 58 | ld r1,PACAKSAVE(r13) |
59 | 1: std r10,0(r1) | 59 | 1: std r10,0(r1) |
60 | crclr so | ||
60 | std r11,_NIP(r1) | 61 | std r11,_NIP(r1) |
61 | std r12,_MSR(r1) | 62 | std r12,_MSR(r1) |
62 | std r0,GPR0(r1) | 63 | std r0,GPR0(r1) |
@@ -75,7 +76,6 @@ system_call_common: | |||
75 | std r11,GPR11(r1) | 76 | std r11,GPR11(r1) |
76 | std r11,GPR12(r1) | 77 | std r11,GPR12(r1) |
77 | std r9,GPR13(r1) | 78 | std r9,GPR13(r1) |
78 | crclr so | ||
79 | mfcr r9 | 79 | mfcr r9 |
80 | mflr r10 | 80 | mflr r10 |
81 | li r11,0xc01 | 81 | li r11,0xc01 |
diff --git a/arch/powerpc/kernel/fpu.S b/arch/powerpc/kernel/fpu.S index 340730fb8c91..01f71200c603 100644 --- a/arch/powerpc/kernel/fpu.S +++ b/arch/powerpc/kernel/fpu.S | |||
@@ -72,7 +72,7 @@ _GLOBAL(load_up_fpu) | |||
72 | std r12,_MSR(r1) | 72 | std r12,_MSR(r1) |
73 | #endif | 73 | #endif |
74 | lfd fr0,THREAD_FPSCR(r5) | 74 | lfd fr0,THREAD_FPSCR(r5) |
75 | mtfsf 0xff,fr0 | 75 | MTFSF_L(fr0) |
76 | REST_32FPRS(0, r5) | 76 | REST_32FPRS(0, r5) |
77 | #ifndef CONFIG_SMP | 77 | #ifndef CONFIG_SMP |
78 | subi r4,r5,THREAD | 78 | subi r4,r5,THREAD |
@@ -127,7 +127,7 @@ _GLOBAL(giveup_fpu) | |||
127 | 127 | ||
128 | _GLOBAL(cvt_fd) | 128 | _GLOBAL(cvt_fd) |
129 | lfd 0,THREAD_FPSCR(r5) /* load up fpscr value */ | 129 | lfd 0,THREAD_FPSCR(r5) /* load up fpscr value */ |
130 | mtfsf 0xff,0 | 130 | MTFSF_L(0) |
131 | lfs 0,0(r3) | 131 | lfs 0,0(r3) |
132 | stfd 0,0(r4) | 132 | stfd 0,0(r4) |
133 | mffs 0 | 133 | mffs 0 |
@@ -136,7 +136,7 @@ _GLOBAL(cvt_fd) | |||
136 | 136 | ||
137 | _GLOBAL(cvt_df) | 137 | _GLOBAL(cvt_df) |
138 | lfd 0,THREAD_FPSCR(r5) /* load up fpscr value */ | 138 | lfd 0,THREAD_FPSCR(r5) /* load up fpscr value */ |
139 | mtfsf 0xff,0 | 139 | MTFSF_L(0) |
140 | lfd 0,0(r3) | 140 | lfd 0,0(r3) |
141 | stfs 0,0(r4) | 141 | stfs 0,0(r4) |
142 | mffs 0 | 142 | mffs 0 |
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S index a0579e859b21..b25b25902d15 100644 --- a/arch/powerpc/kernel/head_32.S +++ b/arch/powerpc/kernel/head_32.S | |||
@@ -973,6 +973,13 @@ __secondary_start_gemini: | |||
973 | b __secondary_start | 973 | b __secondary_start |
974 | #endif /* CONFIG_GEMINI */ | 974 | #endif /* CONFIG_GEMINI */ |
975 | 975 | ||
976 | .globl __secondary_start_mpc86xx | ||
977 | __secondary_start_mpc86xx: | ||
978 | mfspr r3, SPRN_PIR | ||
979 | stw r3, __secondary_hold_acknowledge@l(0) | ||
980 | mr r24, r3 /* cpu # */ | ||
981 | b __secondary_start | ||
982 | |||
976 | .globl __secondary_start_pmac_0 | 983 | .globl __secondary_start_pmac_0 |
977 | __secondary_start_pmac_0: | 984 | __secondary_start_pmac_0: |
978 | /* NB the entries for cpus 0, 1, 2 must each occupy 8 bytes. */ | 985 | /* NB the entries for cpus 0, 1, 2 must each occupy 8 bytes. */ |
@@ -1088,7 +1095,12 @@ load_up_mmu: | |||
1088 | LOAD_BAT(1,r3,r4,r5) | 1095 | LOAD_BAT(1,r3,r4,r5) |
1089 | LOAD_BAT(2,r3,r4,r5) | 1096 | LOAD_BAT(2,r3,r4,r5) |
1090 | LOAD_BAT(3,r3,r4,r5) | 1097 | LOAD_BAT(3,r3,r4,r5) |
1091 | 1098 | BEGIN_FTR_SECTION | |
1099 | LOAD_BAT(4,r3,r4,r5) | ||
1100 | LOAD_BAT(5,r3,r4,r5) | ||
1101 | LOAD_BAT(6,r3,r4,r5) | ||
1102 | LOAD_BAT(7,r3,r4,r5) | ||
1103 | END_FTR_SECTION_IFSET(CPU_FTR_HAS_HIGH_BATS) | ||
1092 | blr | 1104 | blr |
1093 | 1105 | ||
1094 | /* | 1106 | /* |
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S index b7d140430a41..831acbdf2592 100644 --- a/arch/powerpc/kernel/head_64.S +++ b/arch/powerpc/kernel/head_64.S | |||
@@ -316,6 +316,21 @@ label##_pSeries: \ | |||
316 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ | 316 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ |
317 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) | 317 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) |
318 | 318 | ||
319 | #define HSTD_EXCEPTION_PSERIES(n, label) \ | ||
320 | . = n; \ | ||
321 | .globl label##_pSeries; \ | ||
322 | label##_pSeries: \ | ||
323 | HMT_MEDIUM; \ | ||
324 | mtspr SPRN_SPRG1,r20; /* save r20 */ \ | ||
325 | mfspr r20,SPRN_HSRR0; /* copy HSRR0 to SRR0 */ \ | ||
326 | mtspr SPRN_SRR0,r20; \ | ||
327 | mfspr r20,SPRN_HSRR1; /* copy HSRR0 to SRR0 */ \ | ||
328 | mtspr SPRN_SRR1,r20; \ | ||
329 | mfspr r20,SPRN_SPRG1; /* restore r20 */ \ | ||
330 | mtspr SPRN_SPRG1,r13; /* save r13 */ \ | ||
331 | EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, label##_common) | ||
332 | |||
333 | |||
319 | #define STD_EXCEPTION_ISERIES(n, label, area) \ | 334 | #define STD_EXCEPTION_ISERIES(n, label, area) \ |
320 | .globl label##_iSeries; \ | 335 | .globl label##_iSeries; \ |
321 | label##_iSeries: \ | 336 | label##_iSeries: \ |
@@ -544,8 +559,17 @@ system_call_pSeries: | |||
544 | 559 | ||
545 | STD_EXCEPTION_PSERIES(0xf20, altivec_unavailable) | 560 | STD_EXCEPTION_PSERIES(0xf20, altivec_unavailable) |
546 | 561 | ||
562 | #ifdef CONFIG_CBE_RAS | ||
563 | HSTD_EXCEPTION_PSERIES(0x1200, cbe_system_error) | ||
564 | #endif /* CONFIG_CBE_RAS */ | ||
547 | STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint) | 565 | STD_EXCEPTION_PSERIES(0x1300, instruction_breakpoint) |
566 | #ifdef CONFIG_CBE_RAS | ||
567 | HSTD_EXCEPTION_PSERIES(0x1600, cbe_maintenance) | ||
568 | #endif /* CONFIG_CBE_RAS */ | ||
548 | STD_EXCEPTION_PSERIES(0x1700, altivec_assist) | 569 | STD_EXCEPTION_PSERIES(0x1700, altivec_assist) |
570 | #ifdef CONFIG_CBE_RAS | ||
571 | HSTD_EXCEPTION_PSERIES(0x1800, cbe_thermal) | ||
572 | #endif /* CONFIG_CBE_RAS */ | ||
549 | 573 | ||
550 | . = 0x3000 | 574 | . = 0x3000 |
551 | 575 | ||
@@ -827,6 +851,11 @@ machine_check_common: | |||
827 | #else | 851 | #else |
828 | STD_EXCEPTION_COMMON(0x1700, altivec_assist, .unknown_exception) | 852 | STD_EXCEPTION_COMMON(0x1700, altivec_assist, .unknown_exception) |
829 | #endif | 853 | #endif |
854 | #ifdef CONFIG_CBE_RAS | ||
855 | STD_EXCEPTION_COMMON(0x1200, cbe_system_error, .cbe_system_error_exception) | ||
856 | STD_EXCEPTION_COMMON(0x1600, cbe_maintenance, .cbe_maintenance_exception) | ||
857 | STD_EXCEPTION_COMMON(0x1800, cbe_thermal, .cbe_thermal_exception) | ||
858 | #endif /* CONFIG_CBE_RAS */ | ||
830 | 859 | ||
831 | /* | 860 | /* |
832 | * Here we have detected that the kernel stack pointer is bad. | 861 | * Here we have detected that the kernel stack pointer is bad. |
diff --git a/arch/powerpc/kernel/iomap.c b/arch/powerpc/kernel/iomap.c index fd8214caedee..a13a93dfc655 100644 --- a/arch/powerpc/kernel/iomap.c +++ b/arch/powerpc/kernel/iomap.c | |||
@@ -106,8 +106,6 @@ EXPORT_SYMBOL(iowrite32_rep); | |||
106 | 106 | ||
107 | void __iomem *ioport_map(unsigned long port, unsigned int len) | 107 | void __iomem *ioport_map(unsigned long port, unsigned int len) |
108 | { | 108 | { |
109 | if (!_IO_IS_VALID(port)) | ||
110 | return NULL; | ||
111 | return (void __iomem *) (port+pci_io_base); | 109 | return (void __iomem *) (port+pci_io_base); |
112 | } | 110 | } |
113 | 111 | ||
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c index 4eba60a32890..7cb77c20fc5d 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c | |||
@@ -418,10 +418,11 @@ void iommu_unmap_sg(struct iommu_table *tbl, struct scatterlist *sglist, | |||
418 | * Build a iommu_table structure. This contains a bit map which | 418 | * Build a iommu_table structure. This contains a bit map which |
419 | * is used to manage allocation of the tce space. | 419 | * is used to manage allocation of the tce space. |
420 | */ | 420 | */ |
421 | struct iommu_table *iommu_init_table(struct iommu_table *tbl) | 421 | struct iommu_table *iommu_init_table(struct iommu_table *tbl, int nid) |
422 | { | 422 | { |
423 | unsigned long sz; | 423 | unsigned long sz; |
424 | static int welcomed = 0; | 424 | static int welcomed = 0; |
425 | struct page *page; | ||
425 | 426 | ||
426 | /* Set aside 1/4 of the table for large allocations. */ | 427 | /* Set aside 1/4 of the table for large allocations. */ |
427 | tbl->it_halfpoint = tbl->it_size * 3 / 4; | 428 | tbl->it_halfpoint = tbl->it_size * 3 / 4; |
@@ -429,10 +430,10 @@ struct iommu_table *iommu_init_table(struct iommu_table *tbl) | |||
429 | /* number of bytes needed for the bitmap */ | 430 | /* number of bytes needed for the bitmap */ |
430 | sz = (tbl->it_size + 7) >> 3; | 431 | sz = (tbl->it_size + 7) >> 3; |
431 | 432 | ||
432 | tbl->it_map = (unsigned long *)__get_free_pages(GFP_ATOMIC, get_order(sz)); | 433 | page = alloc_pages_node(nid, GFP_ATOMIC, get_order(sz)); |
433 | if (!tbl->it_map) | 434 | if (!page) |
434 | panic("iommu_init_table: Can't allocate %ld bytes\n", sz); | 435 | panic("iommu_init_table: Can't allocate %ld bytes\n", sz); |
435 | 436 | tbl->it_map = page_address(page); | |
436 | memset(tbl->it_map, 0, sz); | 437 | memset(tbl->it_map, 0, sz); |
437 | 438 | ||
438 | tbl->it_hint = 0; | 439 | tbl->it_hint = 0; |
@@ -536,11 +537,12 @@ void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle, | |||
536 | * to the dma address (mapping) of the first page. | 537 | * to the dma address (mapping) of the first page. |
537 | */ | 538 | */ |
538 | void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, | 539 | void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, |
539 | dma_addr_t *dma_handle, unsigned long mask, gfp_t flag) | 540 | dma_addr_t *dma_handle, unsigned long mask, gfp_t flag, int node) |
540 | { | 541 | { |
541 | void *ret = NULL; | 542 | void *ret = NULL; |
542 | dma_addr_t mapping; | 543 | dma_addr_t mapping; |
543 | unsigned int npages, order; | 544 | unsigned int npages, order; |
545 | struct page *page; | ||
544 | 546 | ||
545 | size = PAGE_ALIGN(size); | 547 | size = PAGE_ALIGN(size); |
546 | npages = size >> PAGE_SHIFT; | 548 | npages = size >> PAGE_SHIFT; |
@@ -560,9 +562,10 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, | |||
560 | return NULL; | 562 | return NULL; |
561 | 563 | ||
562 | /* Alloc enough pages (and possibly more) */ | 564 | /* Alloc enough pages (and possibly more) */ |
563 | ret = (void *)__get_free_pages(flag, order); | 565 | page = alloc_pages_node(node, flag, order); |
564 | if (!ret) | 566 | if (!page) |
565 | return NULL; | 567 | return NULL; |
568 | ret = page_address(page); | ||
566 | memset(ret, 0, size); | 569 | memset(ret, 0, size); |
567 | 570 | ||
568 | /* Set up tces to cover the allocated range */ | 571 | /* Set up tces to cover the allocated range */ |
@@ -570,9 +573,9 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, | |||
570 | mask >> PAGE_SHIFT, order); | 573 | mask >> PAGE_SHIFT, order); |
571 | if (mapping == DMA_ERROR_CODE) { | 574 | if (mapping == DMA_ERROR_CODE) { |
572 | free_pages((unsigned long)ret, order); | 575 | free_pages((unsigned long)ret, order); |
573 | ret = NULL; | 576 | return NULL; |
574 | } else | 577 | } |
575 | *dma_handle = mapping; | 578 | *dma_handle = mapping; |
576 | return ret; | 579 | return ret; |
577 | } | 580 | } |
578 | 581 | ||
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 57d560c68897..bfcec4cc70a7 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
@@ -47,6 +47,7 @@ | |||
47 | #include <linux/cpumask.h> | 47 | #include <linux/cpumask.h> |
48 | #include <linux/profile.h> | 48 | #include <linux/profile.h> |
49 | #include <linux/bitops.h> | 49 | #include <linux/bitops.h> |
50 | #include <linux/pci.h> | ||
50 | 51 | ||
51 | #include <asm/uaccess.h> | 52 | #include <asm/uaccess.h> |
52 | #include <asm/system.h> | 53 | #include <asm/system.h> |
@@ -436,6 +437,30 @@ void do_softirq(void) | |||
436 | } | 437 | } |
437 | EXPORT_SYMBOL(do_softirq); | 438 | EXPORT_SYMBOL(do_softirq); |
438 | 439 | ||
440 | #ifdef CONFIG_PCI_MSI | ||
441 | int pci_enable_msi(struct pci_dev * pdev) | ||
442 | { | ||
443 | if (ppc_md.enable_msi) | ||
444 | return ppc_md.enable_msi(pdev); | ||
445 | else | ||
446 | return -1; | ||
447 | } | ||
448 | |||
449 | void pci_disable_msi(struct pci_dev * pdev) | ||
450 | { | ||
451 | if (ppc_md.disable_msi) | ||
452 | ppc_md.disable_msi(pdev); | ||
453 | } | ||
454 | |||
455 | void pci_scan_msi_device(struct pci_dev *dev) {} | ||
456 | int pci_enable_msix(struct pci_dev* dev, struct msix_entry *entries, int nvec) {return -1;} | ||
457 | void pci_disable_msix(struct pci_dev *dev) {} | ||
458 | void msi_remove_pci_irq_vectors(struct pci_dev *dev) {} | ||
459 | void disable_msi_mode(struct pci_dev *dev, int pos, int type) {} | ||
460 | void pci_no_msi(void) {} | ||
461 | |||
462 | #endif | ||
463 | |||
439 | #ifdef CONFIG_PPC64 | 464 | #ifdef CONFIG_PPC64 |
440 | static int __init setup_noirqdistrib(char *str) | 465 | static int __init setup_noirqdistrib(char *str) |
441 | { | 466 | { |
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index 2cbde865d4f5..c02deaab26c7 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c | |||
@@ -521,10 +521,10 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf, | |||
521 | 521 | ||
522 | current_weight = (resource >> 5 * 8) & 0xFF; | 522 | current_weight = (resource >> 5 * 8) & 0xFF; |
523 | 523 | ||
524 | pr_debug("%s: current_entitled = %lu, current_weight = %lu\n", | 524 | pr_debug("%s: current_entitled = %lu, current_weight = %u\n", |
525 | __FUNCTION__, current_entitled, current_weight); | 525 | __FUNCTION__, current_entitled, current_weight); |
526 | 526 | ||
527 | pr_debug("%s: new_entitled = %lu, new_weight = %lu\n", | 527 | pr_debug("%s: new_entitled = %lu, new_weight = %u\n", |
528 | __FUNCTION__, *new_entitled_ptr, *new_weight_ptr); | 528 | __FUNCTION__, *new_entitled_ptr, *new_weight_ptr); |
529 | 529 | ||
530 | retval = plpar_hcall_norets(H_SET_PPP, *new_entitled_ptr, | 530 | retval = plpar_hcall_norets(H_SET_PPP, *new_entitled_ptr, |
diff --git a/arch/powerpc/kernel/machine_kexec_64.c b/arch/powerpc/kernel/machine_kexec_64.c index ee166c586642..a8fa04ef27cd 100644 --- a/arch/powerpc/kernel/machine_kexec_64.c +++ b/arch/powerpc/kernel/machine_kexec_64.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <asm/machdep.h> | 21 | #include <asm/machdep.h> |
22 | #include <asm/cacheflush.h> | 22 | #include <asm/cacheflush.h> |
23 | #include <asm/paca.h> | 23 | #include <asm/paca.h> |
24 | #include <asm/lmb.h> | ||
24 | #include <asm/mmu.h> | 25 | #include <asm/mmu.h> |
25 | #include <asm/sections.h> /* _end */ | 26 | #include <asm/sections.h> /* _end */ |
26 | #include <asm/prom.h> | 27 | #include <asm/prom.h> |
@@ -335,7 +336,105 @@ static void __init export_htab_values(void) | |||
335 | of_node_put(node); | 336 | of_node_put(node); |
336 | } | 337 | } |
337 | 338 | ||
339 | static struct property crashk_base_prop = { | ||
340 | .name = "linux,crashkernel-base", | ||
341 | .length = sizeof(unsigned long), | ||
342 | .value = (unsigned char *)&crashk_res.start, | ||
343 | }; | ||
344 | |||
345 | static unsigned long crashk_size; | ||
346 | |||
347 | static struct property crashk_size_prop = { | ||
348 | .name = "linux,crashkernel-size", | ||
349 | .length = sizeof(unsigned long), | ||
350 | .value = (unsigned char *)&crashk_size, | ||
351 | }; | ||
352 | |||
353 | static void __init export_crashk_values(void) | ||
354 | { | ||
355 | struct device_node *node; | ||
356 | struct property *prop; | ||
357 | |||
358 | node = of_find_node_by_path("/chosen"); | ||
359 | if (!node) | ||
360 | return; | ||
361 | |||
362 | /* There might be existing crash kernel properties, but we can't | ||
363 | * be sure what's in them, so remove them. */ | ||
364 | prop = of_find_property(node, "linux,crashkernel-base", NULL); | ||
365 | if (prop) | ||
366 | prom_remove_property(node, prop); | ||
367 | |||
368 | prop = of_find_property(node, "linux,crashkernel-size", NULL); | ||
369 | if (prop) | ||
370 | prom_remove_property(node, prop); | ||
371 | |||
372 | if (crashk_res.start != 0) { | ||
373 | prom_add_property(node, &crashk_base_prop); | ||
374 | crashk_size = crashk_res.end - crashk_res.start + 1; | ||
375 | prom_add_property(node, &crashk_size_prop); | ||
376 | } | ||
377 | |||
378 | of_node_put(node); | ||
379 | } | ||
380 | |||
338 | void __init kexec_setup(void) | 381 | void __init kexec_setup(void) |
339 | { | 382 | { |
340 | export_htab_values(); | 383 | export_htab_values(); |
384 | export_crashk_values(); | ||
385 | } | ||
386 | |||
387 | static int __init early_parse_crashk(char *p) | ||
388 | { | ||
389 | unsigned long size; | ||
390 | |||
391 | if (!p) | ||
392 | return 1; | ||
393 | |||
394 | size = memparse(p, &p); | ||
395 | |||
396 | if (*p == '@') | ||
397 | crashk_res.start = memparse(p + 1, &p); | ||
398 | else | ||
399 | crashk_res.start = KDUMP_KERNELBASE; | ||
400 | |||
401 | crashk_res.end = crashk_res.start + size - 1; | ||
402 | |||
403 | return 0; | ||
404 | } | ||
405 | early_param("crashkernel", early_parse_crashk); | ||
406 | |||
407 | void __init reserve_crashkernel(void) | ||
408 | { | ||
409 | unsigned long size; | ||
410 | |||
411 | if (crashk_res.start == 0) | ||
412 | return; | ||
413 | |||
414 | /* We might have got these values via the command line or the | ||
415 | * device tree, either way sanitise them now. */ | ||
416 | |||
417 | size = crashk_res.end - crashk_res.start + 1; | ||
418 | |||
419 | if (crashk_res.start != KDUMP_KERNELBASE) | ||
420 | printk("Crash kernel location must be 0x%x\n", | ||
421 | KDUMP_KERNELBASE); | ||
422 | |||
423 | crashk_res.start = KDUMP_KERNELBASE; | ||
424 | size = PAGE_ALIGN(size); | ||
425 | crashk_res.end = crashk_res.start + size - 1; | ||
426 | |||
427 | /* Crash kernel trumps memory limit */ | ||
428 | if (memory_limit && memory_limit <= crashk_res.end) { | ||
429 | memory_limit = crashk_res.end + 1; | ||
430 | printk("Adjusted memory limit for crashkernel, now 0x%lx\n", | ||
431 | memory_limit); | ||
432 | } | ||
433 | |||
434 | lmb_reserve(crashk_res.start, size); | ||
435 | } | ||
436 | |||
437 | int overlaps_crashkernel(unsigned long start, unsigned long size) | ||
438 | { | ||
439 | return (start + size) > crashk_res.start && start <= crashk_res.end; | ||
341 | } | 440 | } |
diff --git a/arch/powerpc/kernel/misc_32.S b/arch/powerpc/kernel/misc_32.S index be982023409e..01d3916c4cb1 100644 --- a/arch/powerpc/kernel/misc_32.S +++ b/arch/powerpc/kernel/misc_32.S | |||
@@ -216,7 +216,7 @@ _GLOBAL(call_setup_cpu) | |||
216 | lwz r4,0(r4) | 216 | lwz r4,0(r4) |
217 | add r4,r4,r3 | 217 | add r4,r4,r3 |
218 | lwz r5,CPU_SPEC_SETUP(r4) | 218 | lwz r5,CPU_SPEC_SETUP(r4) |
219 | cmpi 0,r5,0 | 219 | cmpwi 0,r5,0 |
220 | add r5,r5,r3 | 220 | add r5,r5,r3 |
221 | beqlr | 221 | beqlr |
222 | mtctr r5 | 222 | mtctr r5 |
diff --git a/arch/powerpc/kernel/misc_64.S b/arch/powerpc/kernel/misc_64.S index 2778cce058e2..e8883d42c43c 100644 --- a/arch/powerpc/kernel/misc_64.S +++ b/arch/powerpc/kernel/misc_64.S | |||
@@ -482,7 +482,9 @@ _GLOBAL(identify_cpu) | |||
482 | sub r0,r3,r5 | 482 | sub r0,r3,r5 |
483 | std r0,0(r4) | 483 | std r0,0(r4) |
484 | ld r4,CPU_SPEC_SETUP(r3) | 484 | ld r4,CPU_SPEC_SETUP(r3) |
485 | cmpdi 0,r4,0 | ||
485 | add r4,r4,r5 | 486 | add r4,r4,r5 |
487 | beqlr | ||
486 | ld r4,0(r4) | 488 | ld r4,0(r4) |
487 | add r4,r4,r5 | 489 | add r4,r4,r5 |
488 | mtctr r4 | 490 | mtctr r4 |
@@ -768,9 +770,6 @@ _GLOBAL(giveup_altivec) | |||
768 | 770 | ||
769 | #endif /* CONFIG_ALTIVEC */ | 771 | #endif /* CONFIG_ALTIVEC */ |
770 | 772 | ||
771 | _GLOBAL(__setup_cpu_power3) | ||
772 | blr | ||
773 | |||
774 | _GLOBAL(execve) | 773 | _GLOBAL(execve) |
775 | li r0,__NR_execve | 774 | li r0,__NR_execve |
776 | sc | 775 | sc |
diff --git a/arch/powerpc/kernel/nvram_64.c b/arch/powerpc/kernel/nvram_64.c index ada50aa5b600..6960f090991e 100644 --- a/arch/powerpc/kernel/nvram_64.c +++ b/arch/powerpc/kernel/nvram_64.c | |||
@@ -204,7 +204,7 @@ static void nvram_print_partitions(char * label) | |||
204 | printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n"); | 204 | printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n"); |
205 | list_for_each(p, &nvram_part->partition) { | 205 | list_for_each(p, &nvram_part->partition) { |
206 | tmp_part = list_entry(p, struct nvram_partition, partition); | 206 | tmp_part = list_entry(p, struct nvram_partition, partition); |
207 | printk(KERN_WARNING "%d \t%02x\t%02x\t%d\t%s\n", | 207 | printk(KERN_WARNING "%4d \t%02x\t%02x\t%d\t%s\n", |
208 | tmp_part->index, tmp_part->header.signature, | 208 | tmp_part->index, tmp_part->header.signature, |
209 | tmp_part->header.checksum, tmp_part->header.length, | 209 | tmp_part->header.checksum, tmp_part->header.length, |
210 | tmp_part->header.name); | 210 | tmp_part->header.name); |
diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c index b129d2e4b759..c858eb4bef17 100644 --- a/arch/powerpc/kernel/pci_32.c +++ b/arch/powerpc/kernel/pci_32.c | |||
@@ -1113,9 +1113,10 @@ check_for_io_childs(struct pci_bus *bus, struct resource* res, int *found_vga) | |||
1113 | int i; | 1113 | int i; |
1114 | int rc = 0; | 1114 | int rc = 0; |
1115 | 1115 | ||
1116 | #define push_end(res, size) do { unsigned long __sz = (size) ; \ | 1116 | #define push_end(res, mask) do { \ |
1117 | res->end = ((res->end + __sz) / (__sz + 1)) * (__sz + 1) + __sz; \ | 1117 | BUG_ON((mask+1) & mask); \ |
1118 | } while (0) | 1118 | res->end = (res->end + mask) | mask; \ |
1119 | } while (0) | ||
1119 | 1120 | ||
1120 | list_for_each_entry(dev, &bus->devices, bus_list) { | 1121 | list_for_each_entry(dev, &bus->devices, bus_list) { |
1121 | u16 class = dev->class >> 8; | 1122 | u16 class = dev->class >> 8; |
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c index 4c4449be81ce..5ad87c426bed 100644 --- a/arch/powerpc/kernel/pci_64.c +++ b/arch/powerpc/kernel/pci_64.c | |||
@@ -42,14 +42,6 @@ | |||
42 | unsigned long pci_probe_only = 1; | 42 | unsigned long pci_probe_only = 1; |
43 | int pci_assign_all_buses = 0; | 43 | int pci_assign_all_buses = 0; |
44 | 44 | ||
45 | /* | ||
46 | * legal IO pages under MAX_ISA_PORT. This is to ensure we don't touch | ||
47 | * devices we don't have access to. | ||
48 | */ | ||
49 | unsigned long io_page_mask; | ||
50 | |||
51 | EXPORT_SYMBOL(io_page_mask); | ||
52 | |||
53 | #ifdef CONFIG_PPC_MULTIPLATFORM | 45 | #ifdef CONFIG_PPC_MULTIPLATFORM |
54 | static void fixup_resource(struct resource *res, struct pci_dev *dev); | 46 | static void fixup_resource(struct resource *res, struct pci_dev *dev); |
55 | static void do_bus_setup(struct pci_bus *bus); | 47 | static void do_bus_setup(struct pci_bus *bus); |
@@ -235,8 +227,10 @@ struct pci_controller * pcibios_alloc_controller(struct device_node *dev) | |||
235 | pci_setup_pci_controller(phb); | 227 | pci_setup_pci_controller(phb); |
236 | phb->arch_data = dev; | 228 | phb->arch_data = dev; |
237 | phb->is_dynamic = mem_init_done; | 229 | phb->is_dynamic = mem_init_done; |
238 | if (dev) | 230 | if (dev) { |
231 | PHB_SET_NODE(phb, of_node_to_nid(dev)); | ||
239 | add_linux_pci_domain(dev, phb); | 232 | add_linux_pci_domain(dev, phb); |
233 | } | ||
240 | return phb; | 234 | return phb; |
241 | } | 235 | } |
242 | 236 | ||
@@ -396,7 +390,7 @@ struct pci_dev *of_create_pci_dev(struct device_node *node, | |||
396 | 390 | ||
397 | dev->current_state = 4; /* unknown power state */ | 391 | dev->current_state = 4; /* unknown power state */ |
398 | 392 | ||
399 | if (!strcmp(type, "pci")) { | 393 | if (!strcmp(type, "pci") || !strcmp(type, "pciex")) { |
400 | /* a PCI-PCI bridge */ | 394 | /* a PCI-PCI bridge */ |
401 | dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; | 395 | dev->hdr_type = PCI_HEADER_TYPE_BRIDGE; |
402 | dev->rom_base_reg = PCI_ROM_ADDRESS1; | 396 | dev->rom_base_reg = PCI_ROM_ADDRESS1; |
@@ -605,7 +599,7 @@ static int __init pcibios_init(void) | |||
605 | iSeries_pcibios_init(); | 599 | iSeries_pcibios_init(); |
606 | #endif | 600 | #endif |
607 | 601 | ||
608 | printk("PCI: Probing PCI hardware\n"); | 602 | printk(KERN_DEBUG "PCI: Probing PCI hardware\n"); |
609 | 603 | ||
610 | /* Scan all of the recorded PCI controllers. */ | 604 | /* Scan all of the recorded PCI controllers. */ |
611 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { | 605 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { |
@@ -630,14 +624,14 @@ static int __init pcibios_init(void) | |||
630 | /* Cache the location of the ISA bridge (if we have one) */ | 624 | /* Cache the location of the ISA bridge (if we have one) */ |
631 | ppc64_isabridge_dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL); | 625 | ppc64_isabridge_dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL); |
632 | if (ppc64_isabridge_dev != NULL) | 626 | if (ppc64_isabridge_dev != NULL) |
633 | printk("ISA bridge at %s\n", pci_name(ppc64_isabridge_dev)); | 627 | printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev)); |
634 | 628 | ||
635 | #ifdef CONFIG_PPC_MULTIPLATFORM | 629 | #ifdef CONFIG_PPC_MULTIPLATFORM |
636 | /* map in PCI I/O space */ | 630 | /* map in PCI I/O space */ |
637 | phbs_remap_io(); | 631 | phbs_remap_io(); |
638 | #endif | 632 | #endif |
639 | 633 | ||
640 | printk("PCI: Probing PCI hardware done\n"); | 634 | printk(KERN_DEBUG "PCI: Probing PCI hardware done\n"); |
641 | 635 | ||
642 | return 0; | 636 | return 0; |
643 | } | 637 | } |
@@ -804,7 +798,7 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, | |||
804 | else | 798 | else |
805 | prot |= _PAGE_GUARDED; | 799 | prot |= _PAGE_GUARDED; |
806 | 800 | ||
807 | printk("PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start, | 801 | printk(KERN_DEBUG "PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start, |
808 | prot); | 802 | prot); |
809 | 803 | ||
810 | return __pgprot(prot); | 804 | return __pgprot(prot); |
@@ -894,8 +888,8 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, | |||
894 | return ret; | 888 | return ret; |
895 | } | 889 | } |
896 | 890 | ||
897 | #ifdef CONFIG_PPC_MULTIPLATFORM | 891 | static ssize_t pci_show_devspec(struct device *dev, |
898 | static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *attr, char *buf) | 892 | struct device_attribute *attr, char *buf) |
899 | { | 893 | { |
900 | struct pci_dev *pdev; | 894 | struct pci_dev *pdev; |
901 | struct device_node *np; | 895 | struct device_node *np; |
@@ -907,13 +901,10 @@ static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *att | |||
907 | return sprintf(buf, "%s", np->full_name); | 901 | return sprintf(buf, "%s", np->full_name); |
908 | } | 902 | } |
909 | static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); | 903 | static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); |
910 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
911 | 904 | ||
912 | void pcibios_add_platform_entries(struct pci_dev *pdev) | 905 | void pcibios_add_platform_entries(struct pci_dev *pdev) |
913 | { | 906 | { |
914 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
915 | device_create_file(&pdev->dev, &dev_attr_devspec); | 907 | device_create_file(&pdev->dev, &dev_attr_devspec); |
916 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
917 | } | 908 | } |
918 | 909 | ||
919 | #ifdef CONFIG_PPC_MULTIPLATFORM | 910 | #ifdef CONFIG_PPC_MULTIPLATFORM |
@@ -1104,8 +1095,6 @@ void __init pci_setup_phb_io(struct pci_controller *hose, int primary) | |||
1104 | pci_process_ISA_OF_ranges(isa_dn, hose->io_base_phys, | 1095 | pci_process_ISA_OF_ranges(isa_dn, hose->io_base_phys, |
1105 | hose->io_base_virt); | 1096 | hose->io_base_virt); |
1106 | of_node_put(isa_dn); | 1097 | of_node_put(isa_dn); |
1107 | /* Allow all IO */ | ||
1108 | io_page_mask = -1; | ||
1109 | } | 1098 | } |
1110 | } | 1099 | } |
1111 | 1100 | ||
@@ -1212,7 +1201,7 @@ int remap_bus_range(struct pci_bus *bus) | |||
1212 | return 1; | 1201 | return 1; |
1213 | if (start_phys == 0) | 1202 | if (start_phys == 0) |
1214 | return 1; | 1203 | return 1; |
1215 | printk("mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size); | 1204 | printk(KERN_DEBUG "mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size); |
1216 | if (__ioremap_explicit(start_phys, start_virt, size, | 1205 | if (__ioremap_explicit(start_phys, start_virt, size, |
1217 | _PAGE_NO_CACHE | _PAGE_GUARDED)) | 1206 | _PAGE_NO_CACHE | _PAGE_GUARDED)) |
1218 | return 1; | 1207 | return 1; |
@@ -1232,27 +1221,13 @@ static void phbs_remap_io(void) | |||
1232 | static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev) | 1221 | static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev) |
1233 | { | 1222 | { |
1234 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | 1223 | struct pci_controller *hose = pci_bus_to_host(dev->bus); |
1235 | unsigned long start, end, mask, offset; | 1224 | unsigned long offset; |
1236 | 1225 | ||
1237 | if (res->flags & IORESOURCE_IO) { | 1226 | if (res->flags & IORESOURCE_IO) { |
1238 | offset = (unsigned long)hose->io_base_virt - pci_io_base; | 1227 | offset = (unsigned long)hose->io_base_virt - pci_io_base; |
1239 | 1228 | ||
1240 | start = res->start += offset; | 1229 | res->start += offset; |
1241 | end = res->end += offset; | 1230 | res->end += offset; |
1242 | |||
1243 | /* Need to allow IO access to pages that are in the | ||
1244 | ISA range */ | ||
1245 | if (start < MAX_ISA_PORT) { | ||
1246 | if (end > MAX_ISA_PORT) | ||
1247 | end = MAX_ISA_PORT; | ||
1248 | |||
1249 | start >>= PAGE_SHIFT; | ||
1250 | end >>= PAGE_SHIFT; | ||
1251 | |||
1252 | /* get the range of pages for the map */ | ||
1253 | mask = ((1 << (end+1)) - 1) ^ ((1 << start) - 1); | ||
1254 | io_page_mask |= mask; | ||
1255 | } | ||
1256 | } else if (res->flags & IORESOURCE_MEM) { | 1231 | } else if (res->flags & IORESOURCE_MEM) { |
1257 | res->start += hose->pci_mem_offset; | 1232 | res->start += hose->pci_mem_offset; |
1258 | res->end += hose->pci_mem_offset; | 1233 | res->end += hose->pci_mem_offset; |
@@ -1442,3 +1417,12 @@ long sys_pciconfig_iobase(long which, unsigned long in_bus, | |||
1442 | 1417 | ||
1443 | return -EOPNOTSUPP; | 1418 | return -EOPNOTSUPP; |
1444 | } | 1419 | } |
1420 | |||
1421 | #ifdef CONFIG_NUMA | ||
1422 | int pcibus_to_node(struct pci_bus *bus) | ||
1423 | { | ||
1424 | struct pci_controller *phb = pci_bus_to_host(bus); | ||
1425 | return phb->node; | ||
1426 | } | ||
1427 | EXPORT_SYMBOL(pcibus_to_node); | ||
1428 | #endif | ||
diff --git a/arch/powerpc/kernel/pci_direct_iommu.c b/arch/powerpc/kernel/pci_direct_iommu.c index e1a32f802c0b..72ce082ce738 100644 --- a/arch/powerpc/kernel/pci_direct_iommu.c +++ b/arch/powerpc/kernel/pci_direct_iommu.c | |||
@@ -82,13 +82,17 @@ static int pci_direct_dma_supported(struct device *dev, u64 mask) | |||
82 | return mask < 0x100000000ull; | 82 | return mask < 0x100000000ull; |
83 | } | 83 | } |
84 | 84 | ||
85 | static struct dma_mapping_ops pci_direct_ops = { | ||
86 | .alloc_coherent = pci_direct_alloc_coherent, | ||
87 | .free_coherent = pci_direct_free_coherent, | ||
88 | .map_single = pci_direct_map_single, | ||
89 | .unmap_single = pci_direct_unmap_single, | ||
90 | .map_sg = pci_direct_map_sg, | ||
91 | .unmap_sg = pci_direct_unmap_sg, | ||
92 | .dma_supported = pci_direct_dma_supported, | ||
93 | }; | ||
94 | |||
85 | void __init pci_direct_iommu_init(void) | 95 | void __init pci_direct_iommu_init(void) |
86 | { | 96 | { |
87 | pci_dma_ops.alloc_coherent = pci_direct_alloc_coherent; | 97 | pci_dma_ops = pci_direct_ops; |
88 | pci_dma_ops.free_coherent = pci_direct_free_coherent; | ||
89 | pci_dma_ops.map_single = pci_direct_map_single; | ||
90 | pci_dma_ops.unmap_single = pci_direct_unmap_single; | ||
91 | pci_dma_ops.map_sg = pci_direct_map_sg; | ||
92 | pci_dma_ops.unmap_sg = pci_direct_unmap_sg; | ||
93 | pci_dma_ops.dma_supported = pci_direct_dma_supported; | ||
94 | } | 98 | } |
diff --git a/arch/powerpc/kernel/pci_dn.c b/arch/powerpc/kernel/pci_dn.c index 12c4c9e9bbc7..1c18953514c3 100644 --- a/arch/powerpc/kernel/pci_dn.c +++ b/arch/powerpc/kernel/pci_dn.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <asm/pci-bridge.h> | 31 | #include <asm/pci-bridge.h> |
32 | #include <asm/pSeries_reconfig.h> | 32 | #include <asm/pSeries_reconfig.h> |
33 | #include <asm/ppc-pci.h> | 33 | #include <asm/ppc-pci.h> |
34 | #include <asm/firmware.h> | ||
34 | 35 | ||
35 | /* | 36 | /* |
36 | * Traverse_func that inits the PCI fields of the device node. | 37 | * Traverse_func that inits the PCI fields of the device node. |
@@ -59,6 +60,11 @@ static void * __devinit update_dn_pci_info(struct device_node *dn, void *data) | |||
59 | pdn->busno = (regs[0] >> 16) & 0xff; | 60 | pdn->busno = (regs[0] >> 16) & 0xff; |
60 | pdn->devfn = (regs[0] >> 8) & 0xff; | 61 | pdn->devfn = (regs[0] >> 8) & 0xff; |
61 | } | 62 | } |
63 | if (firmware_has_feature(FW_FEATURE_ISERIES)) { | ||
64 | u32 *busp = (u32 *)get_property(dn, "linux,subbus", NULL); | ||
65 | if (busp) | ||
66 | pdn->bussubno = *busp; | ||
67 | } | ||
62 | 68 | ||
63 | pdn->pci_ext_config_space = (type && *type == 1); | 69 | pdn->pci_ext_config_space = (type && *type == 1); |
64 | return NULL; | 70 | return NULL; |
diff --git a/arch/powerpc/kernel/pci_iommu.c b/arch/powerpc/kernel/pci_iommu.c index c1d95e14bbed..0688b2534acb 100644 --- a/arch/powerpc/kernel/pci_iommu.c +++ b/arch/powerpc/kernel/pci_iommu.c | |||
@@ -44,16 +44,16 @@ | |||
44 | */ | 44 | */ |
45 | #define PCI_GET_DN(dev) ((struct device_node *)((dev)->sysdata)) | 45 | #define PCI_GET_DN(dev) ((struct device_node *)((dev)->sysdata)) |
46 | 46 | ||
47 | static inline struct iommu_table *devnode_table(struct device *dev) | 47 | static inline struct iommu_table *device_to_table(struct device *hwdev) |
48 | { | 48 | { |
49 | struct pci_dev *pdev; | 49 | struct pci_dev *pdev; |
50 | 50 | ||
51 | if (!dev) { | 51 | if (!hwdev) { |
52 | pdev = ppc64_isabridge_dev; | 52 | pdev = ppc64_isabridge_dev; |
53 | if (!pdev) | 53 | if (!pdev) |
54 | return NULL; | 54 | return NULL; |
55 | } else | 55 | } else |
56 | pdev = to_pci_dev(dev); | 56 | pdev = to_pci_dev(hwdev); |
57 | 57 | ||
58 | return PCI_DN(PCI_GET_DN(pdev))->iommu_table; | 58 | return PCI_DN(PCI_GET_DN(pdev))->iommu_table; |
59 | } | 59 | } |
@@ -85,14 +85,15 @@ static inline unsigned long device_to_mask(struct device *hwdev) | |||
85 | static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size, | 85 | static void *pci_iommu_alloc_coherent(struct device *hwdev, size_t size, |
86 | dma_addr_t *dma_handle, gfp_t flag) | 86 | dma_addr_t *dma_handle, gfp_t flag) |
87 | { | 87 | { |
88 | return iommu_alloc_coherent(devnode_table(hwdev), size, dma_handle, | 88 | return iommu_alloc_coherent(device_to_table(hwdev), size, dma_handle, |
89 | device_to_mask(hwdev), flag); | 89 | device_to_mask(hwdev), flag, |
90 | pcibus_to_node(to_pci_dev(hwdev)->bus)); | ||
90 | } | 91 | } |
91 | 92 | ||
92 | static void pci_iommu_free_coherent(struct device *hwdev, size_t size, | 93 | static void pci_iommu_free_coherent(struct device *hwdev, size_t size, |
93 | void *vaddr, dma_addr_t dma_handle) | 94 | void *vaddr, dma_addr_t dma_handle) |
94 | { | 95 | { |
95 | iommu_free_coherent(devnode_table(hwdev), size, vaddr, dma_handle); | 96 | iommu_free_coherent(device_to_table(hwdev), size, vaddr, dma_handle); |
96 | } | 97 | } |
97 | 98 | ||
98 | /* Creates TCEs for a user provided buffer. The user buffer must be | 99 | /* Creates TCEs for a user provided buffer. The user buffer must be |
@@ -104,7 +105,7 @@ static void pci_iommu_free_coherent(struct device *hwdev, size_t size, | |||
104 | static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr, | 105 | static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr, |
105 | size_t size, enum dma_data_direction direction) | 106 | size_t size, enum dma_data_direction direction) |
106 | { | 107 | { |
107 | return iommu_map_single(devnode_table(hwdev), vaddr, size, | 108 | return iommu_map_single(device_to_table(hwdev), vaddr, size, |
108 | device_to_mask(hwdev), direction); | 109 | device_to_mask(hwdev), direction); |
109 | } | 110 | } |
110 | 111 | ||
@@ -112,27 +113,27 @@ static dma_addr_t pci_iommu_map_single(struct device *hwdev, void *vaddr, | |||
112 | static void pci_iommu_unmap_single(struct device *hwdev, dma_addr_t dma_handle, | 113 | static void pci_iommu_unmap_single(struct device *hwdev, dma_addr_t dma_handle, |
113 | size_t size, enum dma_data_direction direction) | 114 | size_t size, enum dma_data_direction direction) |
114 | { | 115 | { |
115 | iommu_unmap_single(devnode_table(hwdev), dma_handle, size, direction); | 116 | iommu_unmap_single(device_to_table(hwdev), dma_handle, size, direction); |
116 | } | 117 | } |
117 | 118 | ||
118 | 119 | ||
119 | static int pci_iommu_map_sg(struct device *pdev, struct scatterlist *sglist, | 120 | static int pci_iommu_map_sg(struct device *pdev, struct scatterlist *sglist, |
120 | int nelems, enum dma_data_direction direction) | 121 | int nelems, enum dma_data_direction direction) |
121 | { | 122 | { |
122 | return iommu_map_sg(pdev, devnode_table(pdev), sglist, | 123 | return iommu_map_sg(pdev, device_to_table(pdev), sglist, |
123 | nelems, device_to_mask(pdev), direction); | 124 | nelems, device_to_mask(pdev), direction); |
124 | } | 125 | } |
125 | 126 | ||
126 | static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist, | 127 | static void pci_iommu_unmap_sg(struct device *pdev, struct scatterlist *sglist, |
127 | int nelems, enum dma_data_direction direction) | 128 | int nelems, enum dma_data_direction direction) |
128 | { | 129 | { |
129 | iommu_unmap_sg(devnode_table(pdev), sglist, nelems, direction); | 130 | iommu_unmap_sg(device_to_table(pdev), sglist, nelems, direction); |
130 | } | 131 | } |
131 | 132 | ||
132 | /* We support DMA to/from any memory page via the iommu */ | 133 | /* We support DMA to/from any memory page via the iommu */ |
133 | static int pci_iommu_dma_supported(struct device *dev, u64 mask) | 134 | static int pci_iommu_dma_supported(struct device *dev, u64 mask) |
134 | { | 135 | { |
135 | struct iommu_table *tbl = devnode_table(dev); | 136 | struct iommu_table *tbl = device_to_table(dev); |
136 | 137 | ||
137 | if (!tbl || tbl->it_offset > mask) { | 138 | if (!tbl || tbl->it_offset > mask) { |
138 | printk(KERN_INFO "Warning: IOMMU table offset too big for device mask\n"); | 139 | printk(KERN_INFO "Warning: IOMMU table offset too big for device mask\n"); |
@@ -147,13 +148,17 @@ static int pci_iommu_dma_supported(struct device *dev, u64 mask) | |||
147 | return 1; | 148 | return 1; |
148 | } | 149 | } |
149 | 150 | ||
151 | struct dma_mapping_ops pci_iommu_ops = { | ||
152 | .alloc_coherent = pci_iommu_alloc_coherent, | ||
153 | .free_coherent = pci_iommu_free_coherent, | ||
154 | .map_single = pci_iommu_map_single, | ||
155 | .unmap_single = pci_iommu_unmap_single, | ||
156 | .map_sg = pci_iommu_map_sg, | ||
157 | .unmap_sg = pci_iommu_unmap_sg, | ||
158 | .dma_supported = pci_iommu_dma_supported, | ||
159 | }; | ||
160 | |||
150 | void pci_iommu_init(void) | 161 | void pci_iommu_init(void) |
151 | { | 162 | { |
152 | pci_dma_ops.alloc_coherent = pci_iommu_alloc_coherent; | 163 | pci_dma_ops = pci_iommu_ops; |
153 | pci_dma_ops.free_coherent = pci_iommu_free_coherent; | ||
154 | pci_dma_ops.map_single = pci_iommu_map_single; | ||
155 | pci_dma_ops.unmap_single = pci_iommu_unmap_single; | ||
156 | pci_dma_ops.map_sg = pci_iommu_map_sg; | ||
157 | pci_dma_ops.unmap_sg = pci_iommu_unmap_sg; | ||
158 | pci_dma_ops.dma_supported = pci_iommu_dma_supported; | ||
159 | } | 164 | } |
diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c index 3c2cf661f6d9..2b87f82df135 100644 --- a/arch/powerpc/kernel/proc_ppc64.c +++ b/arch/powerpc/kernel/proc_ppc64.c | |||
@@ -52,7 +52,7 @@ static int __init proc_ppc64_create(void) | |||
52 | if (!root) | 52 | if (!root) |
53 | return 1; | 53 | return 1; |
54 | 54 | ||
55 | if (!machine_is(pseries) && !machine_is(cell)) | 55 | if (!of_find_node_by_path("/rtas")) |
56 | return 0; | 56 | return 0; |
57 | 57 | ||
58 | if (!proc_mkdir("rtas", root)) | 58 | if (!proc_mkdir("rtas", root)) |
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 2dd47d2dd998..e4732459c485 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -708,6 +708,61 @@ int get_fpexc_mode(struct task_struct *tsk, unsigned long adr) | |||
708 | return put_user(val, (unsigned int __user *) adr); | 708 | return put_user(val, (unsigned int __user *) adr); |
709 | } | 709 | } |
710 | 710 | ||
711 | int set_endian(struct task_struct *tsk, unsigned int val) | ||
712 | { | ||
713 | struct pt_regs *regs = tsk->thread.regs; | ||
714 | |||
715 | if ((val == PR_ENDIAN_LITTLE && !cpu_has_feature(CPU_FTR_REAL_LE)) || | ||
716 | (val == PR_ENDIAN_PPC_LITTLE && !cpu_has_feature(CPU_FTR_PPC_LE))) | ||
717 | return -EINVAL; | ||
718 | |||
719 | if (regs == NULL) | ||
720 | return -EINVAL; | ||
721 | |||
722 | if (val == PR_ENDIAN_BIG) | ||
723 | regs->msr &= ~MSR_LE; | ||
724 | else if (val == PR_ENDIAN_LITTLE || val == PR_ENDIAN_PPC_LITTLE) | ||
725 | regs->msr |= MSR_LE; | ||
726 | else | ||
727 | return -EINVAL; | ||
728 | |||
729 | return 0; | ||
730 | } | ||
731 | |||
732 | int get_endian(struct task_struct *tsk, unsigned long adr) | ||
733 | { | ||
734 | struct pt_regs *regs = tsk->thread.regs; | ||
735 | unsigned int val; | ||
736 | |||
737 | if (!cpu_has_feature(CPU_FTR_PPC_LE) && | ||
738 | !cpu_has_feature(CPU_FTR_REAL_LE)) | ||
739 | return -EINVAL; | ||
740 | |||
741 | if (regs == NULL) | ||
742 | return -EINVAL; | ||
743 | |||
744 | if (regs->msr & MSR_LE) { | ||
745 | if (cpu_has_feature(CPU_FTR_REAL_LE)) | ||
746 | val = PR_ENDIAN_LITTLE; | ||
747 | else | ||
748 | val = PR_ENDIAN_PPC_LITTLE; | ||
749 | } else | ||
750 | val = PR_ENDIAN_BIG; | ||
751 | |||
752 | return put_user(val, (unsigned int __user *)adr); | ||
753 | } | ||
754 | |||
755 | int set_unalign_ctl(struct task_struct *tsk, unsigned int val) | ||
756 | { | ||
757 | tsk->thread.align_ctl = val; | ||
758 | return 0; | ||
759 | } | ||
760 | |||
761 | int get_unalign_ctl(struct task_struct *tsk, unsigned long adr) | ||
762 | { | ||
763 | return put_user(tsk->thread.align_ctl, (unsigned int __user *)adr); | ||
764 | } | ||
765 | |||
711 | #define TRUNC_PTR(x) ((typeof(x))(((unsigned long)(x)) & 0xffffffff)) | 766 | #define TRUNC_PTR(x) ((typeof(x))(((unsigned long)(x)) & 0xffffffff)) |
712 | 767 | ||
713 | int sys_clone(unsigned long clone_flags, unsigned long usp, | 768 | int sys_clone(unsigned long clone_flags, unsigned long usp, |
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 9a07f97f0712..483455c5bb02 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <asm/machdep.h> | 50 | #include <asm/machdep.h> |
51 | #include <asm/pSeries_reconfig.h> | 51 | #include <asm/pSeries_reconfig.h> |
52 | #include <asm/pci-bridge.h> | 52 | #include <asm/pci-bridge.h> |
53 | #include <asm/kexec.h> | ||
53 | 54 | ||
54 | #ifdef DEBUG | 55 | #ifdef DEBUG |
55 | #define DBG(fmt...) printk(KERN_ERR fmt) | 56 | #define DBG(fmt...) printk(KERN_ERR fmt) |
@@ -836,6 +837,42 @@ static unsigned long __init unflatten_dt_node(unsigned long mem, | |||
836 | return mem; | 837 | return mem; |
837 | } | 838 | } |
838 | 839 | ||
840 | static int __init early_parse_mem(char *p) | ||
841 | { | ||
842 | if (!p) | ||
843 | return 1; | ||
844 | |||
845 | memory_limit = PAGE_ALIGN(memparse(p, &p)); | ||
846 | DBG("memory limit = 0x%lx\n", memory_limit); | ||
847 | |||
848 | return 0; | ||
849 | } | ||
850 | early_param("mem", early_parse_mem); | ||
851 | |||
852 | /* | ||
853 | * The device tree may be allocated below our memory limit, or inside the | ||
854 | * crash kernel region for kdump. If so, move it out now. | ||
855 | */ | ||
856 | static void move_device_tree(void) | ||
857 | { | ||
858 | unsigned long start, size; | ||
859 | void *p; | ||
860 | |||
861 | DBG("-> move_device_tree\n"); | ||
862 | |||
863 | start = __pa(initial_boot_params); | ||
864 | size = initial_boot_params->totalsize; | ||
865 | |||
866 | if ((memory_limit && (start + size) > memory_limit) || | ||
867 | overlaps_crashkernel(start, size)) { | ||
868 | p = __va(lmb_alloc_base(size, PAGE_SIZE, lmb.rmo_size)); | ||
869 | memcpy(p, initial_boot_params, size); | ||
870 | initial_boot_params = (struct boot_param_header *)p; | ||
871 | DBG("Moved device tree to 0x%p\n", p); | ||
872 | } | ||
873 | |||
874 | DBG("<- move_device_tree\n"); | ||
875 | } | ||
839 | 876 | ||
840 | /** | 877 | /** |
841 | * unflattens the device-tree passed by the firmware, creating the | 878 | * unflattens the device-tree passed by the firmware, creating the |
@@ -911,7 +948,10 @@ static struct ibm_pa_feature { | |||
911 | {CPU_FTR_CTRL, 0, 0, 3, 0}, | 948 | {CPU_FTR_CTRL, 0, 0, 3, 0}, |
912 | {CPU_FTR_NOEXECUTE, 0, 0, 6, 0}, | 949 | {CPU_FTR_NOEXECUTE, 0, 0, 6, 0}, |
913 | {CPU_FTR_NODSISRALIGN, 0, 1, 1, 1}, | 950 | {CPU_FTR_NODSISRALIGN, 0, 1, 1, 1}, |
951 | #if 0 | ||
952 | /* put this back once we know how to test if firmware does 64k IO */ | ||
914 | {CPU_FTR_CI_LARGE_PAGE, 0, 1, 2, 0}, | 953 | {CPU_FTR_CI_LARGE_PAGE, 0, 1, 2, 0}, |
954 | #endif | ||
915 | }; | 955 | }; |
916 | 956 | ||
917 | static void __init check_cpu_pa_features(unsigned long node) | 957 | static void __init check_cpu_pa_features(unsigned long node) |
@@ -1070,6 +1110,7 @@ static int __init early_init_dt_scan_chosen(unsigned long node, | |||
1070 | iommu_force_on = 1; | 1110 | iommu_force_on = 1; |
1071 | #endif | 1111 | #endif |
1072 | 1112 | ||
1113 | /* mem=x on the command line is the preferred mechanism */ | ||
1073 | lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL); | 1114 | lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL); |
1074 | if (lprop) | 1115 | if (lprop) |
1075 | memory_limit = *lprop; | 1116 | memory_limit = *lprop; |
@@ -1123,17 +1164,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node, | |||
1123 | 1164 | ||
1124 | DBG("Command line is: %s\n", cmd_line); | 1165 | DBG("Command line is: %s\n", cmd_line); |
1125 | 1166 | ||
1126 | if (strstr(cmd_line, "mem=")) { | ||
1127 | char *p, *q; | ||
1128 | |||
1129 | for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) { | ||
1130 | q = p + 4; | ||
1131 | if (p > cmd_line && p[-1] != ' ') | ||
1132 | continue; | ||
1133 | memory_limit = memparse(q, &q); | ||
1134 | } | ||
1135 | } | ||
1136 | |||
1137 | /* break now */ | 1167 | /* break now */ |
1138 | return 1; | 1168 | return 1; |
1139 | } | 1169 | } |
@@ -1237,9 +1267,17 @@ static void __init early_reserve_mem(void) | |||
1237 | { | 1267 | { |
1238 | u64 base, size; | 1268 | u64 base, size; |
1239 | u64 *reserve_map; | 1269 | u64 *reserve_map; |
1270 | unsigned long self_base; | ||
1271 | unsigned long self_size; | ||
1240 | 1272 | ||
1241 | reserve_map = (u64 *)(((unsigned long)initial_boot_params) + | 1273 | reserve_map = (u64 *)(((unsigned long)initial_boot_params) + |
1242 | initial_boot_params->off_mem_rsvmap); | 1274 | initial_boot_params->off_mem_rsvmap); |
1275 | |||
1276 | /* before we do anything, lets reserve the dt blob */ | ||
1277 | self_base = __pa((unsigned long)initial_boot_params); | ||
1278 | self_size = initial_boot_params->totalsize; | ||
1279 | lmb_reserve(self_base, self_size); | ||
1280 | |||
1243 | #ifdef CONFIG_PPC32 | 1281 | #ifdef CONFIG_PPC32 |
1244 | /* | 1282 | /* |
1245 | * Handle the case where we might be booting from an old kexec | 1283 | * Handle the case where we might be booting from an old kexec |
@@ -1254,6 +1292,9 @@ static void __init early_reserve_mem(void) | |||
1254 | size_32 = *(reserve_map_32++); | 1292 | size_32 = *(reserve_map_32++); |
1255 | if (size_32 == 0) | 1293 | if (size_32 == 0) |
1256 | break; | 1294 | break; |
1295 | /* skip if the reservation is for the blob */ | ||
1296 | if (base_32 == self_base && size_32 == self_size) | ||
1297 | continue; | ||
1257 | DBG("reserving: %x -> %x\n", base_32, size_32); | 1298 | DBG("reserving: %x -> %x\n", base_32, size_32); |
1258 | lmb_reserve(base_32, size_32); | 1299 | lmb_reserve(base_32, size_32); |
1259 | } | 1300 | } |
@@ -1265,6 +1306,9 @@ static void __init early_reserve_mem(void) | |||
1265 | size = *(reserve_map++); | 1306 | size = *(reserve_map++); |
1266 | if (size == 0) | 1307 | if (size == 0) |
1267 | break; | 1308 | break; |
1309 | /* skip if the reservation is for the blob */ | ||
1310 | if (base == self_base && size == self_size) | ||
1311 | continue; | ||
1268 | DBG("reserving: %llx -> %llx\n", base, size); | 1312 | DBG("reserving: %llx -> %llx\n", base, size); |
1269 | lmb_reserve(base, size); | 1313 | lmb_reserve(base, size); |
1270 | } | 1314 | } |
@@ -1292,18 +1336,26 @@ void __init early_init_devtree(void *params) | |||
1292 | lmb_init(); | 1336 | lmb_init(); |
1293 | of_scan_flat_dt(early_init_dt_scan_root, NULL); | 1337 | of_scan_flat_dt(early_init_dt_scan_root, NULL); |
1294 | of_scan_flat_dt(early_init_dt_scan_memory, NULL); | 1338 | of_scan_flat_dt(early_init_dt_scan_memory, NULL); |
1295 | lmb_enforce_memory_limit(memory_limit); | ||
1296 | lmb_analyze(); | ||
1297 | 1339 | ||
1298 | DBG("Phys. mem: %lx\n", lmb_phys_mem_size()); | 1340 | /* Save command line for /proc/cmdline and then parse parameters */ |
1341 | strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); | ||
1342 | parse_early_param(); | ||
1299 | 1343 | ||
1300 | /* Reserve LMB regions used by kernel, initrd, dt, etc... */ | 1344 | /* Reserve LMB regions used by kernel, initrd, dt, etc... */ |
1301 | lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START); | 1345 | lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START); |
1302 | #ifdef CONFIG_CRASH_DUMP | 1346 | reserve_kdump_trampoline(); |
1303 | lmb_reserve(0, KDUMP_RESERVE_LIMIT); | 1347 | reserve_crashkernel(); |
1304 | #endif | ||
1305 | early_reserve_mem(); | 1348 | early_reserve_mem(); |
1306 | 1349 | ||
1350 | lmb_enforce_memory_limit(memory_limit); | ||
1351 | lmb_analyze(); | ||
1352 | |||
1353 | DBG("Phys. mem: %lx\n", lmb_phys_mem_size()); | ||
1354 | |||
1355 | /* We may need to relocate the flat tree, do it now. | ||
1356 | * FIXME .. and the initrd too? */ | ||
1357 | move_device_tree(); | ||
1358 | |||
1307 | DBG("Scanning CPUs ...\n"); | 1359 | DBG("Scanning CPUs ...\n"); |
1308 | 1360 | ||
1309 | /* Retreive CPU related informations from the flat tree | 1361 | /* Retreive CPU related informations from the flat tree |
@@ -2053,29 +2105,46 @@ int prom_update_property(struct device_node *np, | |||
2053 | return 0; | 2105 | return 0; |
2054 | } | 2106 | } |
2055 | 2107 | ||
2056 | #ifdef CONFIG_KEXEC | ||
2057 | /* We may have allocated the flat device tree inside the crash kernel region | ||
2058 | * in prom_init. If so we need to move it out into regular memory. */ | ||
2059 | void kdump_move_device_tree(void) | ||
2060 | { | ||
2061 | unsigned long start, end; | ||
2062 | struct boot_param_header *new; | ||
2063 | |||
2064 | start = __pa((unsigned long)initial_boot_params); | ||
2065 | end = start + initial_boot_params->totalsize; | ||
2066 | |||
2067 | if (end < crashk_res.start || start > crashk_res.end) | ||
2068 | return; | ||
2069 | 2108 | ||
2070 | new = (struct boot_param_header*) | 2109 | /* Find the device node for a given logical cpu number, also returns the cpu |
2071 | __va(lmb_alloc(initial_boot_params->totalsize, PAGE_SIZE)); | 2110 | * local thread number (index in ibm,interrupt-server#s) if relevant and |
2072 | 2111 | * asked for (non NULL) | |
2073 | memcpy(new, initial_boot_params, initial_boot_params->totalsize); | 2112 | */ |
2113 | struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) | ||
2114 | { | ||
2115 | int hardid; | ||
2116 | struct device_node *np; | ||
2074 | 2117 | ||
2075 | initial_boot_params = new; | 2118 | hardid = get_hard_smp_processor_id(cpu); |
2076 | 2119 | ||
2077 | DBG("Flat device tree blob moved to %p\n", initial_boot_params); | 2120 | for_each_node_by_type(np, "cpu") { |
2121 | u32 *intserv; | ||
2122 | unsigned int plen, t; | ||
2078 | 2123 | ||
2079 | /* XXX should we unreserve the old DT? */ | 2124 | /* Check for ibm,ppc-interrupt-server#s. If it doesn't exist |
2125 | * fallback to "reg" property and assume no threads | ||
2126 | */ | ||
2127 | intserv = (u32 *)get_property(np, "ibm,ppc-interrupt-server#s", | ||
2128 | &plen); | ||
2129 | if (intserv == NULL) { | ||
2130 | u32 *reg = (u32 *)get_property(np, "reg", NULL); | ||
2131 | if (reg == NULL) | ||
2132 | continue; | ||
2133 | if (*reg == hardid) { | ||
2134 | if (thread) | ||
2135 | *thread = 0; | ||
2136 | return np; | ||
2137 | } | ||
2138 | } else { | ||
2139 | plen /= sizeof(u32); | ||
2140 | for (t = 0; t < plen; t++) { | ||
2141 | if (hardid == intserv[t]) { | ||
2142 | if (thread) | ||
2143 | *thread = t; | ||
2144 | return np; | ||
2145 | } | ||
2146 | } | ||
2147 | } | ||
2148 | } | ||
2149 | return NULL; | ||
2080 | } | 2150 | } |
2081 | #endif /* CONFIG_KEXEC */ | ||
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index f70bd090dacd..8c28eb0cbdac 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
@@ -194,19 +194,12 @@ static int __initdata of_platform; | |||
194 | 194 | ||
195 | static char __initdata prom_cmd_line[COMMAND_LINE_SIZE]; | 195 | static char __initdata prom_cmd_line[COMMAND_LINE_SIZE]; |
196 | 196 | ||
197 | static unsigned long __initdata prom_memory_limit; | ||
198 | |||
199 | static unsigned long __initdata alloc_top; | 197 | static unsigned long __initdata alloc_top; |
200 | static unsigned long __initdata alloc_top_high; | 198 | static unsigned long __initdata alloc_top_high; |
201 | static unsigned long __initdata alloc_bottom; | 199 | static unsigned long __initdata alloc_bottom; |
202 | static unsigned long __initdata rmo_top; | 200 | static unsigned long __initdata rmo_top; |
203 | static unsigned long __initdata ram_top; | 201 | static unsigned long __initdata ram_top; |
204 | 202 | ||
205 | #ifdef CONFIG_KEXEC | ||
206 | static unsigned long __initdata prom_crashk_base; | ||
207 | static unsigned long __initdata prom_crashk_size; | ||
208 | #endif | ||
209 | |||
210 | static struct mem_map_entry __initdata mem_reserve_map[MEM_RESERVE_MAP_SIZE]; | 203 | static struct mem_map_entry __initdata mem_reserve_map[MEM_RESERVE_MAP_SIZE]; |
211 | static int __initdata mem_reserve_cnt; | 204 | static int __initdata mem_reserve_cnt; |
212 | 205 | ||
@@ -574,7 +567,7 @@ static void __init early_cmdline_parse(void) | |||
574 | if ((long)_prom->chosen > 0) | 567 | if ((long)_prom->chosen > 0) |
575 | l = prom_getprop(_prom->chosen, "bootargs", p, COMMAND_LINE_SIZE-1); | 568 | l = prom_getprop(_prom->chosen, "bootargs", p, COMMAND_LINE_SIZE-1); |
576 | #ifdef CONFIG_CMDLINE | 569 | #ifdef CONFIG_CMDLINE |
577 | if (l == 0) /* dbl check */ | 570 | if (l <= 0 || p[0] == '\0') /* dbl check */ |
578 | strlcpy(RELOC(prom_cmd_line), | 571 | strlcpy(RELOC(prom_cmd_line), |
579 | RELOC(CONFIG_CMDLINE), sizeof(prom_cmd_line)); | 572 | RELOC(CONFIG_CMDLINE), sizeof(prom_cmd_line)); |
580 | #endif /* CONFIG_CMDLINE */ | 573 | #endif /* CONFIG_CMDLINE */ |
@@ -593,45 +586,6 @@ static void __init early_cmdline_parse(void) | |||
593 | RELOC(iommu_force_on) = 1; | 586 | RELOC(iommu_force_on) = 1; |
594 | } | 587 | } |
595 | #endif | 588 | #endif |
596 | |||
597 | opt = strstr(RELOC(prom_cmd_line), RELOC("mem=")); | ||
598 | if (opt) { | ||
599 | opt += 4; | ||
600 | RELOC(prom_memory_limit) = prom_memparse(opt, (const char **)&opt); | ||
601 | #ifdef CONFIG_PPC64 | ||
602 | /* Align to 16 MB == size of ppc64 large page */ | ||
603 | RELOC(prom_memory_limit) = ALIGN(RELOC(prom_memory_limit), 0x1000000); | ||
604 | #endif | ||
605 | } | ||
606 | |||
607 | #ifdef CONFIG_KEXEC | ||
608 | /* | ||
609 | * crashkernel=size@addr specifies the location to reserve for | ||
610 | * crash kernel. | ||
611 | */ | ||
612 | opt = strstr(RELOC(prom_cmd_line), RELOC("crashkernel=")); | ||
613 | if (opt) { | ||
614 | opt += 12; | ||
615 | RELOC(prom_crashk_size) = | ||
616 | prom_memparse(opt, (const char **)&opt); | ||
617 | |||
618 | if (ALIGN(RELOC(prom_crashk_size), 0x1000000) != | ||
619 | RELOC(prom_crashk_size)) { | ||
620 | prom_printf("Warning: crashkernel size is not " | ||
621 | "aligned to 16MB\n"); | ||
622 | } | ||
623 | |||
624 | /* | ||
625 | * At present, the crash kernel always run at 32MB. | ||
626 | * Just ignore whatever user passed. | ||
627 | */ | ||
628 | RELOC(prom_crashk_base) = 0x2000000; | ||
629 | if (*opt == '@') { | ||
630 | prom_printf("Warning: PPC64 kdump kernel always runs " | ||
631 | "at 32 MB\n"); | ||
632 | } | ||
633 | } | ||
634 | #endif | ||
635 | } | 589 | } |
636 | 590 | ||
637 | #ifdef CONFIG_PPC_PSERIES | 591 | #ifdef CONFIG_PPC_PSERIES |
@@ -1116,29 +1070,6 @@ static void __init prom_init_mem(void) | |||
1116 | } | 1070 | } |
1117 | 1071 | ||
1118 | /* | 1072 | /* |
1119 | * If prom_memory_limit is set we reduce the upper limits *except* for | ||
1120 | * alloc_top_high. This must be the real top of RAM so we can put | ||
1121 | * TCE's up there. | ||
1122 | */ | ||
1123 | |||
1124 | RELOC(alloc_top_high) = RELOC(ram_top); | ||
1125 | |||
1126 | if (RELOC(prom_memory_limit)) { | ||
1127 | if (RELOC(prom_memory_limit) <= RELOC(alloc_bottom)) { | ||
1128 | prom_printf("Ignoring mem=%x <= alloc_bottom.\n", | ||
1129 | RELOC(prom_memory_limit)); | ||
1130 | RELOC(prom_memory_limit) = 0; | ||
1131 | } else if (RELOC(prom_memory_limit) >= RELOC(ram_top)) { | ||
1132 | prom_printf("Ignoring mem=%x >= ram_top.\n", | ||
1133 | RELOC(prom_memory_limit)); | ||
1134 | RELOC(prom_memory_limit) = 0; | ||
1135 | } else { | ||
1136 | RELOC(ram_top) = RELOC(prom_memory_limit); | ||
1137 | RELOC(rmo_top) = min(RELOC(rmo_top), RELOC(prom_memory_limit)); | ||
1138 | } | ||
1139 | } | ||
1140 | |||
1141 | /* | ||
1142 | * Setup our top alloc point, that is top of RMO or top of | 1073 | * Setup our top alloc point, that is top of RMO or top of |
1143 | * segment 0 when running non-LPAR. | 1074 | * segment 0 when running non-LPAR. |
1144 | * Some RS64 machines have buggy firmware where claims up at | 1075 | * Some RS64 machines have buggy firmware where claims up at |
@@ -1150,20 +1081,14 @@ static void __init prom_init_mem(void) | |||
1150 | RELOC(rmo_top) = RELOC(ram_top); | 1081 | RELOC(rmo_top) = RELOC(ram_top); |
1151 | RELOC(rmo_top) = min(0x30000000ul, RELOC(rmo_top)); | 1082 | RELOC(rmo_top) = min(0x30000000ul, RELOC(rmo_top)); |
1152 | RELOC(alloc_top) = RELOC(rmo_top); | 1083 | RELOC(alloc_top) = RELOC(rmo_top); |
1084 | RELOC(alloc_top_high) = RELOC(ram_top); | ||
1153 | 1085 | ||
1154 | prom_printf("memory layout at init:\n"); | 1086 | prom_printf("memory layout at init:\n"); |
1155 | prom_printf(" memory_limit : %x (16 MB aligned)\n", RELOC(prom_memory_limit)); | ||
1156 | prom_printf(" alloc_bottom : %x\n", RELOC(alloc_bottom)); | 1087 | prom_printf(" alloc_bottom : %x\n", RELOC(alloc_bottom)); |
1157 | prom_printf(" alloc_top : %x\n", RELOC(alloc_top)); | 1088 | prom_printf(" alloc_top : %x\n", RELOC(alloc_top)); |
1158 | prom_printf(" alloc_top_hi : %x\n", RELOC(alloc_top_high)); | 1089 | prom_printf(" alloc_top_hi : %x\n", RELOC(alloc_top_high)); |
1159 | prom_printf(" rmo_top : %x\n", RELOC(rmo_top)); | 1090 | prom_printf(" rmo_top : %x\n", RELOC(rmo_top)); |
1160 | prom_printf(" ram_top : %x\n", RELOC(ram_top)); | 1091 | prom_printf(" ram_top : %x\n", RELOC(ram_top)); |
1161 | #ifdef CONFIG_KEXEC | ||
1162 | if (RELOC(prom_crashk_base)) { | ||
1163 | prom_printf(" crashk_base : %x\n", RELOC(prom_crashk_base)); | ||
1164 | prom_printf(" crashk_size : %x\n", RELOC(prom_crashk_size)); | ||
1165 | } | ||
1166 | #endif | ||
1167 | } | 1092 | } |
1168 | 1093 | ||
1169 | 1094 | ||
@@ -1349,16 +1274,10 @@ static void __init prom_initialize_tce_table(void) | |||
1349 | 1274 | ||
1350 | reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom); | 1275 | reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom); |
1351 | 1276 | ||
1352 | if (RELOC(prom_memory_limit)) { | 1277 | /* These are only really needed if there is a memory limit in |
1353 | /* | 1278 | * effect, but we don't know so export them always. */ |
1354 | * We align the start to a 16MB boundary so we can map | 1279 | RELOC(prom_tce_alloc_start) = local_alloc_bottom; |
1355 | * the TCE area using large pages if possible. | 1280 | RELOC(prom_tce_alloc_end) = local_alloc_top; |
1356 | * The end should be the top of RAM so no need to align it. | ||
1357 | */ | ||
1358 | RELOC(prom_tce_alloc_start) = _ALIGN_DOWN(local_alloc_bottom, | ||
1359 | 0x1000000); | ||
1360 | RELOC(prom_tce_alloc_end) = local_alloc_top; | ||
1361 | } | ||
1362 | 1281 | ||
1363 | /* Flag the first invalid entry */ | 1282 | /* Flag the first invalid entry */ |
1364 | prom_debug("ending prom_initialize_tce_table\n"); | 1283 | prom_debug("ending prom_initialize_tce_table\n"); |
@@ -2041,11 +1960,7 @@ static void __init flatten_device_tree(void) | |||
2041 | /* Version 16 is not backward compatible */ | 1960 | /* Version 16 is not backward compatible */ |
2042 | hdr->last_comp_version = 0x10; | 1961 | hdr->last_comp_version = 0x10; |
2043 | 1962 | ||
2044 | /* Reserve the whole thing and copy the reserve map in, we | 1963 | /* Copy the reserve map in */ |
2045 | * also bump mem_reserve_cnt to cause further reservations to | ||
2046 | * fail since it's too late. | ||
2047 | */ | ||
2048 | reserve_mem(RELOC(dt_header_start), hdr->totalsize); | ||
2049 | memcpy(rsvmap, RELOC(mem_reserve_map), sizeof(mem_reserve_map)); | 1964 | memcpy(rsvmap, RELOC(mem_reserve_map), sizeof(mem_reserve_map)); |
2050 | 1965 | ||
2051 | #ifdef DEBUG_PROM | 1966 | #ifdef DEBUG_PROM |
@@ -2058,6 +1973,9 @@ static void __init flatten_device_tree(void) | |||
2058 | RELOC(mem_reserve_map)[i].size); | 1973 | RELOC(mem_reserve_map)[i].size); |
2059 | } | 1974 | } |
2060 | #endif | 1975 | #endif |
1976 | /* Bump mem_reserve_cnt to cause further reservations to fail | ||
1977 | * since it's too late. | ||
1978 | */ | ||
2061 | RELOC(mem_reserve_cnt) = MEM_RESERVE_MAP_SIZE; | 1979 | RELOC(mem_reserve_cnt) = MEM_RESERVE_MAP_SIZE; |
2062 | 1980 | ||
2063 | prom_printf("Device tree strings 0x%x -> 0x%x\n", | 1981 | prom_printf("Device tree strings 0x%x -> 0x%x\n", |
@@ -2280,10 +2198,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
2280 | */ | 2198 | */ |
2281 | prom_init_mem(); | 2199 | prom_init_mem(); |
2282 | 2200 | ||
2283 | #ifdef CONFIG_KEXEC | ||
2284 | if (RELOC(prom_crashk_base)) | ||
2285 | reserve_mem(RELOC(prom_crashk_base), RELOC(prom_crashk_size)); | ||
2286 | #endif | ||
2287 | /* | 2201 | /* |
2288 | * Determine which cpu is actually running right _now_ | 2202 | * Determine which cpu is actually running right _now_ |
2289 | */ | 2203 | */ |
@@ -2317,10 +2231,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
2317 | /* | 2231 | /* |
2318 | * Fill in some infos for use by the kernel later on | 2232 | * Fill in some infos for use by the kernel later on |
2319 | */ | 2233 | */ |
2320 | if (RELOC(prom_memory_limit)) | ||
2321 | prom_setprop(_prom->chosen, "/chosen", "linux,memory-limit", | ||
2322 | &RELOC(prom_memory_limit), | ||
2323 | sizeof(prom_memory_limit)); | ||
2324 | #ifdef CONFIG_PPC64 | 2234 | #ifdef CONFIG_PPC64 |
2325 | if (RELOC(ppc64_iommu_off)) | 2235 | if (RELOC(ppc64_iommu_off)) |
2326 | prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off", | 2236 | prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off", |
@@ -2340,16 +2250,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
2340 | } | 2250 | } |
2341 | #endif | 2251 | #endif |
2342 | 2252 | ||
2343 | #ifdef CONFIG_KEXEC | ||
2344 | if (RELOC(prom_crashk_base)) { | ||
2345 | prom_setprop(_prom->chosen, "/chosen", "linux,crashkernel-base", | ||
2346 | PTRRELOC(&prom_crashk_base), | ||
2347 | sizeof(RELOC(prom_crashk_base))); | ||
2348 | prom_setprop(_prom->chosen, "/chosen", "linux,crashkernel-size", | ||
2349 | PTRRELOC(&prom_crashk_size), | ||
2350 | sizeof(RELOC(prom_crashk_size))); | ||
2351 | } | ||
2352 | #endif | ||
2353 | /* | 2253 | /* |
2354 | * Fixup any known bugs in the device-tree | 2254 | * Fixup any known bugs in the device-tree |
2355 | */ | 2255 | */ |
diff --git a/arch/powerpc/kernel/prom_parse.c b/arch/powerpc/kernel/prom_parse.c index 3934c227549b..45df420383cc 100644 --- a/arch/powerpc/kernel/prom_parse.c +++ b/arch/powerpc/kernel/prom_parse.c | |||
@@ -548,3 +548,28 @@ int of_pci_address_to_resource(struct device_node *dev, int bar, | |||
548 | return __of_address_to_resource(dev, addrp, size, flags, r); | 548 | return __of_address_to_resource(dev, addrp, size, flags, r); |
549 | } | 549 | } |
550 | EXPORT_SYMBOL_GPL(of_pci_address_to_resource); | 550 | EXPORT_SYMBOL_GPL(of_pci_address_to_resource); |
551 | |||
552 | void of_parse_dma_window(struct device_node *dn, unsigned char *dma_window_prop, | ||
553 | unsigned long *busno, unsigned long *phys, unsigned long *size) | ||
554 | { | ||
555 | u32 *dma_window, cells; | ||
556 | unsigned char *prop; | ||
557 | |||
558 | dma_window = (u32 *)dma_window_prop; | ||
559 | |||
560 | /* busno is always one cell */ | ||
561 | *busno = *(dma_window++); | ||
562 | |||
563 | prop = get_property(dn, "ibm,#dma-address-cells", NULL); | ||
564 | if (!prop) | ||
565 | prop = get_property(dn, "#address-cells", NULL); | ||
566 | |||
567 | cells = prop ? *(u32 *)prop : prom_n_addr_cells(dn); | ||
568 | *phys = of_read_addr(dma_window, cells); | ||
569 | |||
570 | dma_window += cells; | ||
571 | |||
572 | prop = get_property(dn, "ibm,#dma-size-cells", NULL); | ||
573 | cells = prop ? *(u32 *)prop : prom_n_size_cells(dn); | ||
574 | *size = of_read_addr(dma_window, cells); | ||
575 | } | ||
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 4a677d1bd4ef..5563e2e7d89c 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
@@ -404,7 +404,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
404 | ret = ptrace_detach(child, data); | 404 | ret = ptrace_detach(child, data); |
405 | break; | 405 | break; |
406 | 406 | ||
407 | #ifdef CONFIG_PPC64 | ||
408 | case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ | 407 | case PPC_PTRACE_GETREGS: { /* Get GPRs 0 - 31. */ |
409 | int i; | 408 | int i; |
410 | unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; | 409 | unsigned long *reg = &((unsigned long *)child->thread.regs)[0]; |
@@ -468,7 +467,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
468 | } | 467 | } |
469 | break; | 468 | break; |
470 | } | 469 | } |
471 | #endif /* CONFIG_PPC64 */ | ||
472 | 470 | ||
473 | #ifdef CONFIG_ALTIVEC | 471 | #ifdef CONFIG_ALTIVEC |
474 | case PTRACE_GETVRREGS: | 472 | case PTRACE_GETVRREGS: |
diff --git a/arch/powerpc/kernel/rtas-rtc.c b/arch/powerpc/kernel/rtas-rtc.c index 34d073fb6091..77578c093dda 100644 --- a/arch/powerpc/kernel/rtas-rtc.c +++ b/arch/powerpc/kernel/rtas-rtc.c | |||
@@ -14,19 +14,20 @@ | |||
14 | unsigned long __init rtas_get_boot_time(void) | 14 | unsigned long __init rtas_get_boot_time(void) |
15 | { | 15 | { |
16 | int ret[8]; | 16 | int ret[8]; |
17 | int error, wait_time; | 17 | int error; |
18 | unsigned int wait_time; | ||
18 | u64 max_wait_tb; | 19 | u64 max_wait_tb; |
19 | 20 | ||
20 | max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; | 21 | max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; |
21 | do { | 22 | do { |
22 | error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); | 23 | error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); |
23 | if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { | 24 | |
24 | wait_time = rtas_extended_busy_delay_time(error); | 25 | wait_time = rtas_busy_delay_time(error); |
26 | if (wait_time) { | ||
25 | /* This is boot time so we spin. */ | 27 | /* This is boot time so we spin. */ |
26 | udelay(wait_time*1000); | 28 | udelay(wait_time*1000); |
27 | error = RTAS_CLOCK_BUSY; | ||
28 | } | 29 | } |
29 | } while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb)); | 30 | } while (wait_time && (get_tb() < max_wait_tb)); |
30 | 31 | ||
31 | if (error != 0 && printk_ratelimit()) { | 32 | if (error != 0 && printk_ratelimit()) { |
32 | printk(KERN_WARNING "error: reading the clock failed (%d)\n", | 33 | printk(KERN_WARNING "error: reading the clock failed (%d)\n", |
@@ -44,24 +45,25 @@ unsigned long __init rtas_get_boot_time(void) | |||
44 | void rtas_get_rtc_time(struct rtc_time *rtc_tm) | 45 | void rtas_get_rtc_time(struct rtc_time *rtc_tm) |
45 | { | 46 | { |
46 | int ret[8]; | 47 | int ret[8]; |
47 | int error, wait_time; | 48 | int error; |
49 | unsigned int wait_time; | ||
48 | u64 max_wait_tb; | 50 | u64 max_wait_tb; |
49 | 51 | ||
50 | max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; | 52 | max_wait_tb = get_tb() + tb_ticks_per_usec * 1000 * MAX_RTC_WAIT; |
51 | do { | 53 | do { |
52 | error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); | 54 | error = rtas_call(rtas_token("get-time-of-day"), 0, 8, ret); |
53 | if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { | 55 | |
56 | wait_time = rtas_busy_delay_time(error); | ||
57 | if (wait_time) { | ||
54 | if (in_interrupt() && printk_ratelimit()) { | 58 | if (in_interrupt() && printk_ratelimit()) { |
55 | memset(rtc_tm, 0, sizeof(struct rtc_time)); | 59 | memset(rtc_tm, 0, sizeof(struct rtc_time)); |
56 | printk(KERN_WARNING "error: reading clock" | 60 | printk(KERN_WARNING "error: reading clock" |
57 | " would delay interrupt\n"); | 61 | " would delay interrupt\n"); |
58 | return; /* delay not allowed */ | 62 | return; /* delay not allowed */ |
59 | } | 63 | } |
60 | wait_time = rtas_extended_busy_delay_time(error); | ||
61 | msleep(wait_time); | 64 | msleep(wait_time); |
62 | error = RTAS_CLOCK_BUSY; | ||
63 | } | 65 | } |
64 | } while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb)); | 66 | } while (wait_time && (get_tb() < max_wait_tb)); |
65 | 67 | ||
66 | if (error != 0 && printk_ratelimit()) { | 68 | if (error != 0 && printk_ratelimit()) { |
67 | printk(KERN_WARNING "error: reading the clock failed (%d)\n", | 69 | printk(KERN_WARNING "error: reading the clock failed (%d)\n", |
@@ -88,14 +90,14 @@ int rtas_set_rtc_time(struct rtc_time *tm) | |||
88 | tm->tm_year + 1900, tm->tm_mon + 1, | 90 | tm->tm_year + 1900, tm->tm_mon + 1, |
89 | tm->tm_mday, tm->tm_hour, tm->tm_min, | 91 | tm->tm_mday, tm->tm_hour, tm->tm_min, |
90 | tm->tm_sec, 0); | 92 | tm->tm_sec, 0); |
91 | if (error == RTAS_CLOCK_BUSY || rtas_is_extended_busy(error)) { | 93 | |
94 | wait_time = rtas_busy_delay_time(error); | ||
95 | if (wait_time) { | ||
92 | if (in_interrupt()) | 96 | if (in_interrupt()) |
93 | return 1; /* probably decrementer */ | 97 | return 1; /* probably decrementer */ |
94 | wait_time = rtas_extended_busy_delay_time(error); | ||
95 | msleep(wait_time); | 98 | msleep(wait_time); |
96 | error = RTAS_CLOCK_BUSY; | ||
97 | } | 99 | } |
98 | } while (error == RTAS_CLOCK_BUSY && (get_tb() < max_wait_tb)); | 100 | } while (wait_time && (get_tb() < max_wait_tb)); |
99 | 101 | ||
100 | if (error != 0 && printk_ratelimit()) | 102 | if (error != 0 && printk_ratelimit()) |
101 | printk(KERN_WARNING "error: setting the clock failed (%d)\n", | 103 | printk(KERN_WARNING "error: setting the clock failed (%d)\n", |
diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c index 0112318213ab..17dc79198515 100644 --- a/arch/powerpc/kernel/rtas.c +++ b/arch/powerpc/kernel/rtas.c | |||
@@ -370,24 +370,36 @@ int rtas_call(int token, int nargs, int nret, int *outputs, ...) | |||
370 | return ret; | 370 | return ret; |
371 | } | 371 | } |
372 | 372 | ||
373 | /* Given an RTAS status code of 990n compute the hinted delay of 10^n | 373 | /* For RTAS_BUSY (-2), delay for 1 millisecond. For an extended busy status |
374 | * (last digit) milliseconds. For now we bound at n=5 (100 sec). | 374 | * code of 990n, perform the hinted delay of 10^n (last digit) milliseconds. |
375 | */ | 375 | */ |
376 | unsigned int rtas_extended_busy_delay_time(int status) | 376 | unsigned int rtas_busy_delay_time(int status) |
377 | { | 377 | { |
378 | int order = status - 9900; | 378 | int order; |
379 | unsigned long ms; | 379 | unsigned int ms = 0; |
380 | |||
381 | if (status == RTAS_BUSY) { | ||
382 | ms = 1; | ||
383 | } else if (status >= 9900 && status <= 9905) { | ||
384 | order = status - 9900; | ||
385 | for (ms = 1; order > 0; order--) | ||
386 | ms *= 10; | ||
387 | } | ||
380 | 388 | ||
381 | if (order < 0) | 389 | return ms; |
382 | order = 0; /* RTC depends on this for -2 clock busy */ | 390 | } |
383 | else if (order > 5) | ||
384 | order = 5; /* bound */ | ||
385 | 391 | ||
386 | /* Use microseconds for reasonable accuracy */ | 392 | /* For an RTAS busy status code, perform the hinted delay. */ |
387 | for (ms = 1; order > 0; order--) | 393 | unsigned int rtas_busy_delay(int status) |
388 | ms *= 10; | 394 | { |
395 | unsigned int ms; | ||
389 | 396 | ||
390 | return ms; | 397 | might_sleep(); |
398 | ms = rtas_busy_delay_time(status); | ||
399 | if (ms) | ||
400 | msleep(ms); | ||
401 | |||
402 | return ms; | ||
391 | } | 403 | } |
392 | 404 | ||
393 | int rtas_error_rc(int rtas_rc) | 405 | int rtas_error_rc(int rtas_rc) |
@@ -438,22 +450,14 @@ int rtas_get_power_level(int powerdomain, int *level) | |||
438 | int rtas_set_power_level(int powerdomain, int level, int *setlevel) | 450 | int rtas_set_power_level(int powerdomain, int level, int *setlevel) |
439 | { | 451 | { |
440 | int token = rtas_token("set-power-level"); | 452 | int token = rtas_token("set-power-level"); |
441 | unsigned int wait_time; | ||
442 | int rc; | 453 | int rc; |
443 | 454 | ||
444 | if (token == RTAS_UNKNOWN_SERVICE) | 455 | if (token == RTAS_UNKNOWN_SERVICE) |
445 | return -ENOENT; | 456 | return -ENOENT; |
446 | 457 | ||
447 | while (1) { | 458 | do { |
448 | rc = rtas_call(token, 2, 2, setlevel, powerdomain, level); | 459 | rc = rtas_call(token, 2, 2, setlevel, powerdomain, level); |
449 | if (rc == RTAS_BUSY) | 460 | } while (rtas_busy_delay(rc)); |
450 | udelay(1); | ||
451 | else if (rtas_is_extended_busy(rc)) { | ||
452 | wait_time = rtas_extended_busy_delay_time(rc); | ||
453 | udelay(wait_time * 1000); | ||
454 | } else | ||
455 | break; | ||
456 | } | ||
457 | 461 | ||
458 | if (rc < 0) | 462 | if (rc < 0) |
459 | return rtas_error_rc(rc); | 463 | return rtas_error_rc(rc); |
@@ -463,22 +467,14 @@ int rtas_set_power_level(int powerdomain, int level, int *setlevel) | |||
463 | int rtas_get_sensor(int sensor, int index, int *state) | 467 | int rtas_get_sensor(int sensor, int index, int *state) |
464 | { | 468 | { |
465 | int token = rtas_token("get-sensor-state"); | 469 | int token = rtas_token("get-sensor-state"); |
466 | unsigned int wait_time; | ||
467 | int rc; | 470 | int rc; |
468 | 471 | ||
469 | if (token == RTAS_UNKNOWN_SERVICE) | 472 | if (token == RTAS_UNKNOWN_SERVICE) |
470 | return -ENOENT; | 473 | return -ENOENT; |
471 | 474 | ||
472 | while (1) { | 475 | do { |
473 | rc = rtas_call(token, 2, 2, state, sensor, index); | 476 | rc = rtas_call(token, 2, 2, state, sensor, index); |
474 | if (rc == RTAS_BUSY) | 477 | } while (rtas_busy_delay(rc)); |
475 | udelay(1); | ||
476 | else if (rtas_is_extended_busy(rc)) { | ||
477 | wait_time = rtas_extended_busy_delay_time(rc); | ||
478 | udelay(wait_time * 1000); | ||
479 | } else | ||
480 | break; | ||
481 | } | ||
482 | 478 | ||
483 | if (rc < 0) | 479 | if (rc < 0) |
484 | return rtas_error_rc(rc); | 480 | return rtas_error_rc(rc); |
@@ -488,23 +484,14 @@ int rtas_get_sensor(int sensor, int index, int *state) | |||
488 | int rtas_set_indicator(int indicator, int index, int new_value) | 484 | int rtas_set_indicator(int indicator, int index, int new_value) |
489 | { | 485 | { |
490 | int token = rtas_token("set-indicator"); | 486 | int token = rtas_token("set-indicator"); |
491 | unsigned int wait_time; | ||
492 | int rc; | 487 | int rc; |
493 | 488 | ||
494 | if (token == RTAS_UNKNOWN_SERVICE) | 489 | if (token == RTAS_UNKNOWN_SERVICE) |
495 | return -ENOENT; | 490 | return -ENOENT; |
496 | 491 | ||
497 | while (1) { | 492 | do { |
498 | rc = rtas_call(token, 3, 1, NULL, indicator, index, new_value); | 493 | rc = rtas_call(token, 3, 1, NULL, indicator, index, new_value); |
499 | if (rc == RTAS_BUSY) | 494 | } while (rtas_busy_delay(rc)); |
500 | udelay(1); | ||
501 | else if (rtas_is_extended_busy(rc)) { | ||
502 | wait_time = rtas_extended_busy_delay_time(rc); | ||
503 | udelay(wait_time * 1000); | ||
504 | } | ||
505 | else | ||
506 | break; | ||
507 | } | ||
508 | 495 | ||
509 | if (rc < 0) | 496 | if (rc < 0) |
510 | return rtas_error_rc(rc); | 497 | return rtas_error_rc(rc); |
@@ -555,13 +542,11 @@ void rtas_os_term(char *str) | |||
555 | do { | 542 | do { |
556 | status = rtas_call(rtas_token("ibm,os-term"), 1, 1, NULL, | 543 | status = rtas_call(rtas_token("ibm,os-term"), 1, 1, NULL, |
557 | __pa(rtas_os_term_buf)); | 544 | __pa(rtas_os_term_buf)); |
545 | } while (rtas_busy_delay(status)); | ||
558 | 546 | ||
559 | if (status == RTAS_BUSY) | 547 | if (status != 0) |
560 | udelay(1); | 548 | printk(KERN_EMERG "ibm,os-term call failed %d\n", |
561 | else if (status != 0) | ||
562 | printk(KERN_EMERG "ibm,os-term call failed %d\n", | ||
563 | status); | 549 | status); |
564 | } while (status == RTAS_BUSY); | ||
565 | } | 550 | } |
566 | 551 | ||
567 | static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE; | 552 | static int ibm_suspend_me_token = RTAS_UNKNOWN_SERVICE; |
@@ -608,9 +593,31 @@ out: | |||
608 | static int rtas_ibm_suspend_me(struct rtas_args *args) | 593 | static int rtas_ibm_suspend_me(struct rtas_args *args) |
609 | { | 594 | { |
610 | int i; | 595 | int i; |
596 | long state; | ||
597 | long rc; | ||
598 | unsigned long dummy; | ||
611 | 599 | ||
612 | struct rtas_suspend_me_data data; | 600 | struct rtas_suspend_me_data data; |
613 | 601 | ||
602 | /* Make sure the state is valid */ | ||
603 | rc = plpar_hcall(H_VASI_STATE, | ||
604 | ((u64)args->args[0] << 32) | args->args[1], | ||
605 | 0, 0, 0, | ||
606 | &state, &dummy, &dummy); | ||
607 | |||
608 | if (rc) { | ||
609 | printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned %ld\n",rc); | ||
610 | return rc; | ||
611 | } else if (state == H_VASI_ENABLED) { | ||
612 | args->args[args->nargs] = RTAS_NOT_SUSPENDABLE; | ||
613 | return 0; | ||
614 | } else if (state != H_VASI_SUSPENDING) { | ||
615 | printk(KERN_ERR "rtas_ibm_suspend_me: vasi_state returned state %ld\n", | ||
616 | state); | ||
617 | args->args[args->nargs] = -1; | ||
618 | return 0; | ||
619 | } | ||
620 | |||
614 | data.waiting = 1; | 621 | data.waiting = 1; |
615 | data.args = args; | 622 | data.args = args; |
616 | 623 | ||
@@ -789,7 +796,8 @@ EXPORT_SYMBOL(rtas_token); | |||
789 | EXPORT_SYMBOL(rtas_call); | 796 | EXPORT_SYMBOL(rtas_call); |
790 | EXPORT_SYMBOL(rtas_data_buf); | 797 | EXPORT_SYMBOL(rtas_data_buf); |
791 | EXPORT_SYMBOL(rtas_data_buf_lock); | 798 | EXPORT_SYMBOL(rtas_data_buf_lock); |
792 | EXPORT_SYMBOL(rtas_extended_busy_delay_time); | 799 | EXPORT_SYMBOL(rtas_busy_delay_time); |
800 | EXPORT_SYMBOL(rtas_busy_delay); | ||
793 | EXPORT_SYMBOL(rtas_get_sensor); | 801 | EXPORT_SYMBOL(rtas_get_sensor); |
794 | EXPORT_SYMBOL(rtas_get_power_level); | 802 | EXPORT_SYMBOL(rtas_get_power_level); |
795 | EXPORT_SYMBOL(rtas_set_power_level); | 803 | EXPORT_SYMBOL(rtas_set_power_level); |
diff --git a/arch/powerpc/kernel/rtas_flash.c b/arch/powerpc/kernel/rtas_flash.c index aaf384c3f04a..1442b63a75da 100644 --- a/arch/powerpc/kernel/rtas_flash.c +++ b/arch/powerpc/kernel/rtas_flash.c | |||
@@ -365,20 +365,12 @@ static int rtas_excl_release(struct inode *inode, struct file *file) | |||
365 | 365 | ||
366 | static void manage_flash(struct rtas_manage_flash_t *args_buf) | 366 | static void manage_flash(struct rtas_manage_flash_t *args_buf) |
367 | { | 367 | { |
368 | unsigned int wait_time; | ||
369 | s32 rc; | 368 | s32 rc; |
370 | 369 | ||
371 | while (1) { | 370 | do { |
372 | rc = rtas_call(rtas_token("ibm,manage-flash-image"), 1, | 371 | rc = rtas_call(rtas_token("ibm,manage-flash-image"), 1, |
373 | 1, NULL, args_buf->op); | 372 | 1, NULL, args_buf->op); |
374 | if (rc == RTAS_RC_BUSY) | 373 | } while (rtas_busy_delay(rc)); |
375 | udelay(1); | ||
376 | else if (rtas_is_extended_busy(rc)) { | ||
377 | wait_time = rtas_extended_busy_delay_time(rc); | ||
378 | udelay(wait_time * 1000); | ||
379 | } else | ||
380 | break; | ||
381 | } | ||
382 | 374 | ||
383 | args_buf->status = rc; | 375 | args_buf->status = rc; |
384 | } | 376 | } |
@@ -451,27 +443,18 @@ static ssize_t manage_flash_write(struct file *file, const char __user *buf, | |||
451 | static void validate_flash(struct rtas_validate_flash_t *args_buf) | 443 | static void validate_flash(struct rtas_validate_flash_t *args_buf) |
452 | { | 444 | { |
453 | int token = rtas_token("ibm,validate-flash-image"); | 445 | int token = rtas_token("ibm,validate-flash-image"); |
454 | unsigned int wait_time; | ||
455 | int update_results; | 446 | int update_results; |
456 | s32 rc; | 447 | s32 rc; |
457 | 448 | ||
458 | rc = 0; | 449 | rc = 0; |
459 | while(1) { | 450 | do { |
460 | spin_lock(&rtas_data_buf_lock); | 451 | spin_lock(&rtas_data_buf_lock); |
461 | memcpy(rtas_data_buf, args_buf->buf, VALIDATE_BUF_SIZE); | 452 | memcpy(rtas_data_buf, args_buf->buf, VALIDATE_BUF_SIZE); |
462 | rc = rtas_call(token, 2, 2, &update_results, | 453 | rc = rtas_call(token, 2, 2, &update_results, |
463 | (u32) __pa(rtas_data_buf), args_buf->buf_size); | 454 | (u32) __pa(rtas_data_buf), args_buf->buf_size); |
464 | memcpy(args_buf->buf, rtas_data_buf, VALIDATE_BUF_SIZE); | 455 | memcpy(args_buf->buf, rtas_data_buf, VALIDATE_BUF_SIZE); |
465 | spin_unlock(&rtas_data_buf_lock); | 456 | spin_unlock(&rtas_data_buf_lock); |
466 | 457 | } while (rtas_busy_delay(rc)); | |
467 | if (rc == RTAS_RC_BUSY) | ||
468 | udelay(1); | ||
469 | else if (rtas_is_extended_busy(rc)) { | ||
470 | wait_time = rtas_extended_busy_delay_time(rc); | ||
471 | udelay(wait_time * 1000); | ||
472 | } else | ||
473 | break; | ||
474 | } | ||
475 | 458 | ||
476 | args_buf->status = rc; | 459 | args_buf->status = rc; |
477 | args_buf->update_results = update_results; | 460 | args_buf->update_results = update_results; |
diff --git a/arch/powerpc/kernel/rtas_pci.c b/arch/powerpc/kernel/rtas_pci.c index 57b539a03fa9..6eb7e49b394a 100644 --- a/arch/powerpc/kernel/rtas_pci.c +++ b/arch/powerpc/kernel/rtas_pci.c | |||
@@ -313,7 +313,9 @@ unsigned long __init find_and_init_phbs(void) | |||
313 | for (node = of_get_next_child(root, NULL); | 313 | for (node = of_get_next_child(root, NULL); |
314 | node != NULL; | 314 | node != NULL; |
315 | node = of_get_next_child(root, node)) { | 315 | node = of_get_next_child(root, node)) { |
316 | if (node->type == NULL || strcmp(node->type, "pci") != 0) | 316 | |
317 | if (node->type == NULL || (strcmp(node->type, "pci") != 0 && | ||
318 | strcmp(node->type, "pciex") != 0)) | ||
317 | continue; | 319 | continue; |
318 | 320 | ||
319 | phb = pcibios_alloc_controller(node); | 321 | phb = pcibios_alloc_controller(node); |
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c index 684ab1d49c65..bd328123af75 100644 --- a/arch/powerpc/kernel/setup-common.c +++ b/arch/powerpc/kernel/setup-common.c | |||
@@ -443,6 +443,7 @@ void __init smp_setup_cpu_maps(void) | |||
443 | } | 443 | } |
444 | #endif /* CONFIG_SMP */ | 444 | #endif /* CONFIG_SMP */ |
445 | 445 | ||
446 | int __initdata do_early_xmon; | ||
446 | #ifdef CONFIG_XMON | 447 | #ifdef CONFIG_XMON |
447 | static int __init early_xmon(char *p) | 448 | static int __init early_xmon(char *p) |
448 | { | 449 | { |
@@ -456,7 +457,7 @@ static int __init early_xmon(char *p) | |||
456 | return 0; | 457 | return 0; |
457 | } | 458 | } |
458 | xmon_init(1); | 459 | xmon_init(1); |
459 | debugger(NULL); | 460 | do_early_xmon = 1; |
460 | 461 | ||
461 | return 0; | 462 | return 0; |
462 | } | 463 | } |
@@ -524,3 +525,20 @@ int check_legacy_ioport(unsigned long base_port) | |||
524 | return ppc_md.check_legacy_ioport(base_port); | 525 | return ppc_md.check_legacy_ioport(base_port); |
525 | } | 526 | } |
526 | EXPORT_SYMBOL(check_legacy_ioport); | 527 | EXPORT_SYMBOL(check_legacy_ioport); |
528 | |||
529 | static int ppc_panic_event(struct notifier_block *this, | ||
530 | unsigned long event, void *ptr) | ||
531 | { | ||
532 | ppc_md.panic(ptr); /* May not return */ | ||
533 | return NOTIFY_DONE; | ||
534 | } | ||
535 | |||
536 | static struct notifier_block ppc_panic_block = { | ||
537 | .notifier_call = ppc_panic_event, | ||
538 | .priority = INT_MIN /* may not return; must be done last */ | ||
539 | }; | ||
540 | |||
541 | void __init setup_panic(void) | ||
542 | { | ||
543 | atomic_notifier_chain_register(&panic_notifier_list, &ppc_panic_block); | ||
544 | } | ||
diff --git a/arch/powerpc/kernel/setup.h b/arch/powerpc/kernel/setup.h index 2ebba755272e..4c67ad7fae08 100644 --- a/arch/powerpc/kernel/setup.h +++ b/arch/powerpc/kernel/setup.h | |||
@@ -2,5 +2,8 @@ | |||
2 | #define _POWERPC_KERNEL_SETUP_H | 2 | #define _POWERPC_KERNEL_SETUP_H |
3 | 3 | ||
4 | void check_for_initrd(void); | 4 | void check_for_initrd(void); |
5 | void do_init_bootmem(void); | ||
6 | void setup_panic(void); | ||
7 | extern int do_early_xmon; | ||
5 | 8 | ||
6 | #endif /* _POWERPC_KERNEL_SETUP_H */ | 9 | #endif /* _POWERPC_KERNEL_SETUP_H */ |
diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index 69ac25701344..e5a44812441a 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c | |||
@@ -131,12 +131,6 @@ void __init machine_init(unsigned long dt_ptr, unsigned long phys) | |||
131 | /* Do some early initialization based on the flat device tree */ | 131 | /* Do some early initialization based on the flat device tree */ |
132 | early_init_devtree(__va(dt_ptr)); | 132 | early_init_devtree(__va(dt_ptr)); |
133 | 133 | ||
134 | /* Check default command line */ | ||
135 | #ifdef CONFIG_CMDLINE | ||
136 | if (cmd_line[0] == 0) | ||
137 | strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line)); | ||
138 | #endif /* CONFIG_CMDLINE */ | ||
139 | |||
140 | probe_machine(); | 134 | probe_machine(); |
141 | 135 | ||
142 | #ifdef CONFIG_6xx | 136 | #ifdef CONFIG_6xx |
@@ -235,7 +229,7 @@ arch_initcall(ppc_init); | |||
235 | /* Warning, IO base is not yet inited */ | 229 | /* Warning, IO base is not yet inited */ |
236 | void __init setup_arch(char **cmdline_p) | 230 | void __init setup_arch(char **cmdline_p) |
237 | { | 231 | { |
238 | extern void do_init_bootmem(void); | 232 | *cmdline_p = cmd_line; |
239 | 233 | ||
240 | /* so udelay does something sensible, assume <= 1000 bogomips */ | 234 | /* so udelay does something sensible, assume <= 1000 bogomips */ |
241 | loops_per_jiffy = 500000000 / HZ; | 235 | loops_per_jiffy = 500000000 / HZ; |
@@ -285,16 +279,16 @@ void __init setup_arch(char **cmdline_p) | |||
285 | /* reboot on panic */ | 279 | /* reboot on panic */ |
286 | panic_timeout = 180; | 280 | panic_timeout = 180; |
287 | 281 | ||
282 | if (ppc_md.panic) | ||
283 | setup_panic(); | ||
284 | |||
288 | init_mm.start_code = PAGE_OFFSET; | 285 | init_mm.start_code = PAGE_OFFSET; |
289 | init_mm.end_code = (unsigned long) _etext; | 286 | init_mm.end_code = (unsigned long) _etext; |
290 | init_mm.end_data = (unsigned long) _edata; | 287 | init_mm.end_data = (unsigned long) _edata; |
291 | init_mm.brk = klimit; | 288 | init_mm.brk = klimit; |
292 | 289 | ||
293 | /* Save unparsed command line copy for /proc/cmdline */ | 290 | if (do_early_xmon) |
294 | strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); | 291 | debugger(NULL); |
295 | *cmdline_p = cmd_line; | ||
296 | |||
297 | parse_early_param(); | ||
298 | 292 | ||
299 | /* set up the bootmem stuff with available memory */ | 293 | /* set up the bootmem stuff with available memory */ |
300 | do_init_bootmem(); | 294 | do_init_bootmem(); |
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c index 4467c49903b6..78f3a5fd43f6 100644 --- a/arch/powerpc/kernel/setup_64.c +++ b/arch/powerpc/kernel/setup_64.c | |||
@@ -100,12 +100,6 @@ unsigned long SYSRQ_KEY; | |||
100 | #endif /* CONFIG_MAGIC_SYSRQ */ | 100 | #endif /* CONFIG_MAGIC_SYSRQ */ |
101 | 101 | ||
102 | 102 | ||
103 | static int ppc64_panic_event(struct notifier_block *, unsigned long, void *); | ||
104 | static struct notifier_block ppc64_panic_block = { | ||
105 | .notifier_call = ppc64_panic_event, | ||
106 | .priority = INT_MIN /* may not return; must be done last */ | ||
107 | }; | ||
108 | |||
109 | #ifdef CONFIG_SMP | 103 | #ifdef CONFIG_SMP |
110 | 104 | ||
111 | static int smt_enabled_cmdline; | 105 | static int smt_enabled_cmdline; |
@@ -199,9 +193,7 @@ void __init early_setup(unsigned long dt_ptr) | |||
199 | /* Probe the machine type */ | 193 | /* Probe the machine type */ |
200 | probe_machine(); | 194 | probe_machine(); |
201 | 195 | ||
202 | #ifdef CONFIG_CRASH_DUMP | 196 | setup_kdump_trampoline(); |
203 | kdump_setup(); | ||
204 | #endif | ||
205 | 197 | ||
206 | DBG("Found, Initializing memory management...\n"); | 198 | DBG("Found, Initializing memory management...\n"); |
207 | 199 | ||
@@ -353,9 +345,6 @@ void __init setup_system(void) | |||
353 | { | 345 | { |
354 | DBG(" -> setup_system()\n"); | 346 | DBG(" -> setup_system()\n"); |
355 | 347 | ||
356 | #ifdef CONFIG_KEXEC | ||
357 | kdump_move_device_tree(); | ||
358 | #endif | ||
359 | /* | 348 | /* |
360 | * Unflatten the device-tree passed by prom_init or kexec | 349 | * Unflatten the device-tree passed by prom_init or kexec |
361 | */ | 350 | */ |
@@ -420,10 +409,8 @@ void __init setup_system(void) | |||
420 | */ | 409 | */ |
421 | register_early_udbg_console(); | 410 | register_early_udbg_console(); |
422 | 411 | ||
423 | /* Save unparsed command line copy for /proc/cmdline */ | 412 | if (do_early_xmon) |
424 | strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); | 413 | debugger(NULL); |
425 | |||
426 | parse_early_param(); | ||
427 | 414 | ||
428 | check_smt_enabled(); | 415 | check_smt_enabled(); |
429 | smp_setup_cpu_maps(); | 416 | smp_setup_cpu_maps(); |
@@ -456,13 +443,6 @@ void __init setup_system(void) | |||
456 | DBG(" <- setup_system()\n"); | 443 | DBG(" <- setup_system()\n"); |
457 | } | 444 | } |
458 | 445 | ||
459 | static int ppc64_panic_event(struct notifier_block *this, | ||
460 | unsigned long event, void *ptr) | ||
461 | { | ||
462 | ppc_md.panic((char *)ptr); /* May not return */ | ||
463 | return NOTIFY_DONE; | ||
464 | } | ||
465 | |||
466 | #ifdef CONFIG_IRQSTACKS | 446 | #ifdef CONFIG_IRQSTACKS |
467 | static void __init irqstack_early_init(void) | 447 | static void __init irqstack_early_init(void) |
468 | { | 448 | { |
@@ -517,8 +497,6 @@ static void __init emergency_stack_init(void) | |||
517 | */ | 497 | */ |
518 | void __init setup_arch(char **cmdline_p) | 498 | void __init setup_arch(char **cmdline_p) |
519 | { | 499 | { |
520 | extern void do_init_bootmem(void); | ||
521 | |||
522 | ppc64_boot_msg(0x12, "Setup Arch"); | 500 | ppc64_boot_msg(0x12, "Setup Arch"); |
523 | 501 | ||
524 | *cmdline_p = cmd_line; | 502 | *cmdline_p = cmd_line; |
@@ -535,8 +513,7 @@ void __init setup_arch(char **cmdline_p) | |||
535 | panic_timeout = 180; | 513 | panic_timeout = 180; |
536 | 514 | ||
537 | if (ppc_md.panic) | 515 | if (ppc_md.panic) |
538 | atomic_notifier_chain_register(&panic_notifier_list, | 516 | setup_panic(); |
539 | &ppc64_panic_block); | ||
540 | 517 | ||
541 | init_mm.start_code = PAGE_OFFSET; | 518 | init_mm.start_code = PAGE_OFFSET; |
542 | init_mm.end_code = (unsigned long) _etext; | 519 | init_mm.end_code = (unsigned long) _etext; |
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 8fdeca2d4597..d73b25e22fca 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
@@ -419,9 +419,7 @@ static long restore_user_regs(struct pt_regs *regs, | |||
419 | { | 419 | { |
420 | long err; | 420 | long err; |
421 | unsigned int save_r2 = 0; | 421 | unsigned int save_r2 = 0; |
422 | #if defined(CONFIG_ALTIVEC) || defined(CONFIG_SPE) | ||
423 | unsigned long msr; | 422 | unsigned long msr; |
424 | #endif | ||
425 | 423 | ||
426 | /* | 424 | /* |
427 | * restore general registers but not including MSR or SOFTE. Also | 425 | * restore general registers but not including MSR or SOFTE. Also |
@@ -430,11 +428,16 @@ static long restore_user_regs(struct pt_regs *regs, | |||
430 | if (!sig) | 428 | if (!sig) |
431 | save_r2 = (unsigned int)regs->gpr[2]; | 429 | save_r2 = (unsigned int)regs->gpr[2]; |
432 | err = restore_general_regs(regs, sr); | 430 | err = restore_general_regs(regs, sr); |
431 | err |= __get_user(msr, &sr->mc_gregs[PT_MSR]); | ||
433 | if (!sig) | 432 | if (!sig) |
434 | regs->gpr[2] = (unsigned long) save_r2; | 433 | regs->gpr[2] = (unsigned long) save_r2; |
435 | if (err) | 434 | if (err) |
436 | return 1; | 435 | return 1; |
437 | 436 | ||
437 | /* if doing signal return, restore the previous little-endian mode */ | ||
438 | if (sig) | ||
439 | regs->msr = (regs->msr & ~MSR_LE) | (msr & MSR_LE); | ||
440 | |||
438 | /* | 441 | /* |
439 | * Do this before updating the thread state in | 442 | * Do this before updating the thread state in |
440 | * current->thread.fpr/vr/evr. That way, if we get preempted | 443 | * current->thread.fpr/vr/evr. That way, if we get preempted |
@@ -455,7 +458,7 @@ static long restore_user_regs(struct pt_regs *regs, | |||
455 | /* force the process to reload the altivec registers from | 458 | /* force the process to reload the altivec registers from |
456 | current->thread when it next does altivec instructions */ | 459 | current->thread when it next does altivec instructions */ |
457 | regs->msr &= ~MSR_VEC; | 460 | regs->msr &= ~MSR_VEC; |
458 | if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_VEC) != 0) { | 461 | if (msr & MSR_VEC) { |
459 | /* restore altivec registers from the stack */ | 462 | /* restore altivec registers from the stack */ |
460 | if (__copy_from_user(current->thread.vr, &sr->mc_vregs, | 463 | if (__copy_from_user(current->thread.vr, &sr->mc_vregs, |
461 | sizeof(sr->mc_vregs))) | 464 | sizeof(sr->mc_vregs))) |
@@ -472,7 +475,7 @@ static long restore_user_regs(struct pt_regs *regs, | |||
472 | /* force the process to reload the spe registers from | 475 | /* force the process to reload the spe registers from |
473 | current->thread when it next does spe instructions */ | 476 | current->thread when it next does spe instructions */ |
474 | regs->msr &= ~MSR_SPE; | 477 | regs->msr &= ~MSR_SPE; |
475 | if (!__get_user(msr, &sr->mc_gregs[PT_MSR]) && (msr & MSR_SPE) != 0) { | 478 | if (msr & MSR_SPE) { |
476 | /* restore spe registers from the stack */ | 479 | /* restore spe registers from the stack */ |
477 | if (__copy_from_user(current->thread.evr, &sr->mc_vregs, | 480 | if (__copy_from_user(current->thread.evr, &sr->mc_vregs, |
478 | ELF_NEVRREG * sizeof(u32))) | 481 | ELF_NEVRREG * sizeof(u32))) |
@@ -757,10 +760,10 @@ static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka, | |||
757 | 760 | ||
758 | /* Save user registers on the stack */ | 761 | /* Save user registers on the stack */ |
759 | frame = &rt_sf->uc.uc_mcontext; | 762 | frame = &rt_sf->uc.uc_mcontext; |
760 | if (vdso32_rt_sigtramp && current->thread.vdso_base) { | 763 | if (vdso32_rt_sigtramp && current->mm->context.vdso_base) { |
761 | if (save_user_regs(regs, frame, 0)) | 764 | if (save_user_regs(regs, frame, 0)) |
762 | goto badframe; | 765 | goto badframe; |
763 | regs->link = current->thread.vdso_base + vdso32_rt_sigtramp; | 766 | regs->link = current->mm->context.vdso_base + vdso32_rt_sigtramp; |
764 | } else { | 767 | } else { |
765 | if (save_user_regs(regs, frame, __NR_rt_sigreturn)) | 768 | if (save_user_regs(regs, frame, __NR_rt_sigreturn)) |
766 | goto badframe; | 769 | goto badframe; |
@@ -777,6 +780,8 @@ static int handle_rt_signal(unsigned long sig, struct k_sigaction *ka, | |||
777 | regs->gpr[5] = (unsigned long) &rt_sf->uc; | 780 | regs->gpr[5] = (unsigned long) &rt_sf->uc; |
778 | regs->gpr[6] = (unsigned long) rt_sf; | 781 | regs->gpr[6] = (unsigned long) rt_sf; |
779 | regs->nip = (unsigned long) ka->sa.sa_handler; | 782 | regs->nip = (unsigned long) ka->sa.sa_handler; |
783 | /* enter the signal handler in big-endian mode */ | ||
784 | regs->msr &= ~MSR_LE; | ||
780 | regs->trap = 0; | 785 | regs->trap = 0; |
781 | return 1; | 786 | return 1; |
782 | 787 | ||
@@ -1038,10 +1043,10 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka, | |||
1038 | || __put_user(sig, &sc->signal)) | 1043 | || __put_user(sig, &sc->signal)) |
1039 | goto badframe; | 1044 | goto badframe; |
1040 | 1045 | ||
1041 | if (vdso32_sigtramp && current->thread.vdso_base) { | 1046 | if (vdso32_sigtramp && current->mm->context.vdso_base) { |
1042 | if (save_user_regs(regs, &frame->mctx, 0)) | 1047 | if (save_user_regs(regs, &frame->mctx, 0)) |
1043 | goto badframe; | 1048 | goto badframe; |
1044 | regs->link = current->thread.vdso_base + vdso32_sigtramp; | 1049 | regs->link = current->mm->context.vdso_base + vdso32_sigtramp; |
1045 | } else { | 1050 | } else { |
1046 | if (save_user_regs(regs, &frame->mctx, __NR_sigreturn)) | 1051 | if (save_user_regs(regs, &frame->mctx, __NR_sigreturn)) |
1047 | goto badframe; | 1052 | goto badframe; |
@@ -1056,6 +1061,8 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka, | |||
1056 | regs->gpr[3] = sig; | 1061 | regs->gpr[3] = sig; |
1057 | regs->gpr[4] = (unsigned long) sc; | 1062 | regs->gpr[4] = (unsigned long) sc; |
1058 | regs->nip = (unsigned long) ka->sa.sa_handler; | 1063 | regs->nip = (unsigned long) ka->sa.sa_handler; |
1064 | /* enter the signal handler in big-endian mode */ | ||
1065 | regs->msr &= ~MSR_LE; | ||
1059 | regs->trap = 0; | 1066 | regs->trap = 0; |
1060 | 1067 | ||
1061 | return 1; | 1068 | return 1; |
diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c index c2db642f4cdd..6e75d7ab6d4d 100644 --- a/arch/powerpc/kernel/signal_64.c +++ b/arch/powerpc/kernel/signal_64.c | |||
@@ -141,9 +141,7 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, | |||
141 | unsigned long err = 0; | 141 | unsigned long err = 0; |
142 | unsigned long save_r13 = 0; | 142 | unsigned long save_r13 = 0; |
143 | elf_greg_t *gregs = (elf_greg_t *)regs; | 143 | elf_greg_t *gregs = (elf_greg_t *)regs; |
144 | #ifdef CONFIG_ALTIVEC | ||
145 | unsigned long msr; | 144 | unsigned long msr; |
146 | #endif | ||
147 | int i; | 145 | int i; |
148 | 146 | ||
149 | /* If this is not a signal return, we preserve the TLS in r13 */ | 147 | /* If this is not a signal return, we preserve the TLS in r13 */ |
@@ -154,7 +152,12 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, | |||
154 | err |= __copy_from_user(regs, &sc->gp_regs, | 152 | err |= __copy_from_user(regs, &sc->gp_regs, |
155 | PT_MSR*sizeof(unsigned long)); | 153 | PT_MSR*sizeof(unsigned long)); |
156 | 154 | ||
157 | /* skip MSR and SOFTE */ | 155 | /* get MSR separately, transfer the LE bit if doing signal return */ |
156 | err |= __get_user(msr, &sc->gp_regs[PT_MSR]); | ||
157 | if (sig) | ||
158 | regs->msr = (regs->msr & ~MSR_LE) | (msr & MSR_LE); | ||
159 | |||
160 | /* skip SOFTE */ | ||
158 | for (i = PT_MSR+1; i <= PT_RESULT; i++) { | 161 | for (i = PT_MSR+1; i <= PT_RESULT; i++) { |
159 | if (i == PT_SOFTE) | 162 | if (i == PT_SOFTE) |
160 | continue; | 163 | continue; |
@@ -179,7 +182,6 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, | |||
179 | 182 | ||
180 | #ifdef CONFIG_ALTIVEC | 183 | #ifdef CONFIG_ALTIVEC |
181 | err |= __get_user(v_regs, &sc->v_regs); | 184 | err |= __get_user(v_regs, &sc->v_regs); |
182 | err |= __get_user(msr, &sc->gp_regs[PT_MSR]); | ||
183 | if (err) | 185 | if (err) |
184 | return err; | 186 | return err; |
185 | if (v_regs && !access_ok(VERIFY_READ, v_regs, 34 * sizeof(vector128))) | 187 | if (v_regs && !access_ok(VERIFY_READ, v_regs, 34 * sizeof(vector128))) |
@@ -396,8 +398,8 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, | |||
396 | current->thread.fpscr.val = 0; | 398 | current->thread.fpscr.val = 0; |
397 | 399 | ||
398 | /* Set up to return from userspace. */ | 400 | /* Set up to return from userspace. */ |
399 | if (vdso64_rt_sigtramp && current->thread.vdso_base) { | 401 | if (vdso64_rt_sigtramp && current->mm->context.vdso_base) { |
400 | regs->link = current->thread.vdso_base + vdso64_rt_sigtramp; | 402 | regs->link = current->mm->context.vdso_base + vdso64_rt_sigtramp; |
401 | } else { | 403 | } else { |
402 | err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]); | 404 | err |= setup_trampoline(__NR_rt_sigreturn, &frame->tramp[0]); |
403 | if (err) | 405 | if (err) |
@@ -412,6 +414,8 @@ static int setup_rt_frame(int signr, struct k_sigaction *ka, siginfo_t *info, | |||
412 | 414 | ||
413 | /* Set up "regs" so we "return" to the signal handler. */ | 415 | /* Set up "regs" so we "return" to the signal handler. */ |
414 | err |= get_user(regs->nip, &funct_desc_ptr->entry); | 416 | err |= get_user(regs->nip, &funct_desc_ptr->entry); |
417 | /* enter the signal handler in big-endian mode */ | ||
418 | regs->msr &= ~MSR_LE; | ||
415 | regs->gpr[1] = newsp; | 419 | regs->gpr[1] = newsp; |
416 | err |= get_user(regs->gpr[2], &funct_desc_ptr->toc); | 420 | err |= get_user(regs->gpr[2], &funct_desc_ptr->toc); |
417 | regs->gpr[3] = signr; | 421 | regs->gpr[3] = signr; |
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c index 530f7dba0bd2..c5d179d4f818 100644 --- a/arch/powerpc/kernel/smp.c +++ b/arch/powerpc/kernel/smp.c | |||
@@ -492,7 +492,7 @@ int __devinit __cpu_up(unsigned int cpu) | |||
492 | * -- Cort | 492 | * -- Cort |
493 | */ | 493 | */ |
494 | if (system_state < SYSTEM_RUNNING) | 494 | if (system_state < SYSTEM_RUNNING) |
495 | for (c = 5000; c && !cpu_callin_map[cpu]; c--) | 495 | for (c = 50000; c && !cpu_callin_map[cpu]; c--) |
496 | udelay(100); | 496 | udelay(100); |
497 | #ifdef CONFIG_HOTPLUG_CPU | 497 | #ifdef CONFIG_HOTPLUG_CPU |
498 | else | 498 | else |
diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S index 26ed1f5ef16e..ee75ccf1a802 100644 --- a/arch/powerpc/kernel/systbl.S +++ b/arch/powerpc/kernel/systbl.S | |||
@@ -32,6 +32,10 @@ | |||
32 | #define SYS32ONLY(func) .long sys_##func | 32 | #define SYS32ONLY(func) .long sys_##func |
33 | #define SYSX(f, f3264, f32) .long f32 | 33 | #define SYSX(f, f3264, f32) .long f32 |
34 | #endif | 34 | #endif |
35 | #define SYSCALL_SPU(func) SYSCALL(func) | ||
36 | #define COMPAT_SYS_SPU(func) COMPAT_SYS(func) | ||
37 | #define PPC_SYS_SPU(func) PPC_SYS(func) | ||
38 | #define SYSX_SPU(f, f3264, f32) SYSX(f, f3264, f32) | ||
35 | 39 | ||
36 | #ifdef CONFIG_PPC64 | 40 | #ifdef CONFIG_PPC64 |
37 | #define sys_sigpending sys_ni_syscall | 41 | #define sys_sigpending sys_ni_syscall |
@@ -39,309 +43,4 @@ | |||
39 | #endif | 43 | #endif |
40 | 44 | ||
41 | _GLOBAL(sys_call_table) | 45 | _GLOBAL(sys_call_table) |
42 | SYSCALL(restart_syscall) | 46 | #include <asm/systbl.h> |
43 | SYSCALL(exit) | ||
44 | PPC_SYS(fork) | ||
45 | SYSCALL(read) | ||
46 | SYSCALL(write) | ||
47 | COMPAT_SYS(open) | ||
48 | SYSCALL(close) | ||
49 | COMPAT_SYS(waitpid) | ||
50 | COMPAT_SYS(creat) | ||
51 | SYSCALL(link) | ||
52 | SYSCALL(unlink) | ||
53 | COMPAT_SYS(execve) | ||
54 | SYSCALL(chdir) | ||
55 | COMPAT_SYS(time) | ||
56 | SYSCALL(mknod) | ||
57 | SYSCALL(chmod) | ||
58 | SYSCALL(lchown) | ||
59 | SYSCALL(ni_syscall) | ||
60 | OLDSYS(stat) | ||
61 | SYSX(sys_lseek,ppc32_lseek,sys_lseek) | ||
62 | SYSCALL(getpid) | ||
63 | COMPAT_SYS(mount) | ||
64 | SYSX(sys_ni_syscall,sys_oldumount,sys_oldumount) | ||
65 | SYSCALL(setuid) | ||
66 | SYSCALL(getuid) | ||
67 | COMPAT_SYS(stime) | ||
68 | COMPAT_SYS(ptrace) | ||
69 | SYSCALL(alarm) | ||
70 | OLDSYS(fstat) | ||
71 | COMPAT_SYS(pause) | ||
72 | COMPAT_SYS(utime) | ||
73 | SYSCALL(ni_syscall) | ||
74 | SYSCALL(ni_syscall) | ||
75 | COMPAT_SYS(access) | ||
76 | COMPAT_SYS(nice) | ||
77 | SYSCALL(ni_syscall) | ||
78 | SYSCALL(sync) | ||
79 | COMPAT_SYS(kill) | ||
80 | SYSCALL(rename) | ||
81 | COMPAT_SYS(mkdir) | ||
82 | SYSCALL(rmdir) | ||
83 | SYSCALL(dup) | ||
84 | SYSCALL(pipe) | ||
85 | COMPAT_SYS(times) | ||
86 | SYSCALL(ni_syscall) | ||
87 | SYSCALL(brk) | ||
88 | SYSCALL(setgid) | ||
89 | SYSCALL(getgid) | ||
90 | SYSCALL(signal) | ||
91 | SYSCALL(geteuid) | ||
92 | SYSCALL(getegid) | ||
93 | SYSCALL(acct) | ||
94 | SYSCALL(umount) | ||
95 | SYSCALL(ni_syscall) | ||
96 | COMPAT_SYS(ioctl) | ||
97 | COMPAT_SYS(fcntl) | ||
98 | SYSCALL(ni_syscall) | ||
99 | COMPAT_SYS(setpgid) | ||
100 | SYSCALL(ni_syscall) | ||
101 | SYSX(sys_ni_syscall,sys_olduname, sys_olduname) | ||
102 | COMPAT_SYS(umask) | ||
103 | SYSCALL(chroot) | ||
104 | SYSCALL(ustat) | ||
105 | SYSCALL(dup2) | ||
106 | SYSCALL(getppid) | ||
107 | SYSCALL(getpgrp) | ||
108 | SYSCALL(setsid) | ||
109 | SYS32ONLY(sigaction) | ||
110 | SYSCALL(sgetmask) | ||
111 | COMPAT_SYS(ssetmask) | ||
112 | SYSCALL(setreuid) | ||
113 | SYSCALL(setregid) | ||
114 | SYS32ONLY(sigsuspend) | ||
115 | COMPAT_SYS(sigpending) | ||
116 | COMPAT_SYS(sethostname) | ||
117 | COMPAT_SYS(setrlimit) | ||
118 | COMPAT_SYS(old_getrlimit) | ||
119 | COMPAT_SYS(getrusage) | ||
120 | COMPAT_SYS(gettimeofday) | ||
121 | COMPAT_SYS(settimeofday) | ||
122 | COMPAT_SYS(getgroups) | ||
123 | COMPAT_SYS(setgroups) | ||
124 | SYSX(sys_ni_syscall,sys_ni_syscall,ppc_select) | ||
125 | SYSCALL(symlink) | ||
126 | OLDSYS(lstat) | ||
127 | COMPAT_SYS(readlink) | ||
128 | SYSCALL(uselib) | ||
129 | SYSCALL(swapon) | ||
130 | SYSCALL(reboot) | ||
131 | SYSX(sys_ni_syscall,old32_readdir,old_readdir) | ||
132 | SYSCALL(mmap) | ||
133 | SYSCALL(munmap) | ||
134 | SYSCALL(truncate) | ||
135 | SYSCALL(ftruncate) | ||
136 | SYSCALL(fchmod) | ||
137 | SYSCALL(fchown) | ||
138 | COMPAT_SYS(getpriority) | ||
139 | COMPAT_SYS(setpriority) | ||
140 | SYSCALL(ni_syscall) | ||
141 | COMPAT_SYS(statfs) | ||
142 | COMPAT_SYS(fstatfs) | ||
143 | SYSCALL(ni_syscall) | ||
144 | COMPAT_SYS(socketcall) | ||
145 | COMPAT_SYS(syslog) | ||
146 | COMPAT_SYS(setitimer) | ||
147 | COMPAT_SYS(getitimer) | ||
148 | COMPAT_SYS(newstat) | ||
149 | COMPAT_SYS(newlstat) | ||
150 | COMPAT_SYS(newfstat) | ||
151 | SYSX(sys_ni_syscall,sys_uname,sys_uname) | ||
152 | SYSCALL(ni_syscall) | ||
153 | SYSCALL(vhangup) | ||
154 | SYSCALL(ni_syscall) | ||
155 | SYSCALL(ni_syscall) | ||
156 | COMPAT_SYS(wait4) | ||
157 | SYSCALL(swapoff) | ||
158 | COMPAT_SYS(sysinfo) | ||
159 | COMPAT_SYS(ipc) | ||
160 | SYSCALL(fsync) | ||
161 | SYS32ONLY(sigreturn) | ||
162 | PPC_SYS(clone) | ||
163 | COMPAT_SYS(setdomainname) | ||
164 | PPC_SYS(newuname) | ||
165 | SYSCALL(ni_syscall) | ||
166 | COMPAT_SYS(adjtimex) | ||
167 | SYSCALL(mprotect) | ||
168 | SYSX(sys_ni_syscall,compat_sys_sigprocmask,sys_sigprocmask) | ||
169 | SYSCALL(ni_syscall) | ||
170 | SYSCALL(init_module) | ||
171 | SYSCALL(delete_module) | ||
172 | SYSCALL(ni_syscall) | ||
173 | SYSCALL(quotactl) | ||
174 | COMPAT_SYS(getpgid) | ||
175 | SYSCALL(fchdir) | ||
176 | SYSCALL(bdflush) | ||
177 | COMPAT_SYS(sysfs) | ||
178 | SYSX(ppc64_personality,ppc64_personality,sys_personality) | ||
179 | SYSCALL(ni_syscall) | ||
180 | SYSCALL(setfsuid) | ||
181 | SYSCALL(setfsgid) | ||
182 | SYSCALL(llseek) | ||
183 | COMPAT_SYS(getdents) | ||
184 | SYSX(sys_select,ppc32_select,ppc_select) | ||
185 | SYSCALL(flock) | ||
186 | SYSCALL(msync) | ||
187 | COMPAT_SYS(readv) | ||
188 | COMPAT_SYS(writev) | ||
189 | COMPAT_SYS(getsid) | ||
190 | SYSCALL(fdatasync) | ||
191 | COMPAT_SYS(sysctl) | ||
192 | SYSCALL(mlock) | ||
193 | SYSCALL(munlock) | ||
194 | SYSCALL(mlockall) | ||
195 | SYSCALL(munlockall) | ||
196 | COMPAT_SYS(sched_setparam) | ||
197 | COMPAT_SYS(sched_getparam) | ||
198 | COMPAT_SYS(sched_setscheduler) | ||
199 | COMPAT_SYS(sched_getscheduler) | ||
200 | SYSCALL(sched_yield) | ||
201 | COMPAT_SYS(sched_get_priority_max) | ||
202 | COMPAT_SYS(sched_get_priority_min) | ||
203 | COMPAT_SYS(sched_rr_get_interval) | ||
204 | COMPAT_SYS(nanosleep) | ||
205 | SYSCALL(mremap) | ||
206 | SYSCALL(setresuid) | ||
207 | SYSCALL(getresuid) | ||
208 | SYSCALL(ni_syscall) | ||
209 | SYSCALL(poll) | ||
210 | COMPAT_SYS(nfsservctl) | ||
211 | SYSCALL(setresgid) | ||
212 | SYSCALL(getresgid) | ||
213 | COMPAT_SYS(prctl) | ||
214 | COMPAT_SYS(rt_sigreturn) | ||
215 | COMPAT_SYS(rt_sigaction) | ||
216 | COMPAT_SYS(rt_sigprocmask) | ||
217 | COMPAT_SYS(rt_sigpending) | ||
218 | COMPAT_SYS(rt_sigtimedwait) | ||
219 | COMPAT_SYS(rt_sigqueueinfo) | ||
220 | COMPAT_SYS(rt_sigsuspend) | ||
221 | COMPAT_SYS(pread64) | ||
222 | COMPAT_SYS(pwrite64) | ||
223 | SYSCALL(chown) | ||
224 | SYSCALL(getcwd) | ||
225 | SYSCALL(capget) | ||
226 | SYSCALL(capset) | ||
227 | COMPAT_SYS(sigaltstack) | ||
228 | SYSX(sys_sendfile64,compat_sys_sendfile,sys_sendfile) | ||
229 | SYSCALL(ni_syscall) | ||
230 | SYSCALL(ni_syscall) | ||
231 | PPC_SYS(vfork) | ||
232 | COMPAT_SYS(getrlimit) | ||
233 | COMPAT_SYS(readahead) | ||
234 | SYS32ONLY(mmap2) | ||
235 | SYS32ONLY(truncate64) | ||
236 | SYS32ONLY(ftruncate64) | ||
237 | SYSX(sys_ni_syscall,sys_stat64,sys_stat64) | ||
238 | SYSX(sys_ni_syscall,sys_lstat64,sys_lstat64) | ||
239 | SYSX(sys_ni_syscall,sys_fstat64,sys_fstat64) | ||
240 | SYSCALL(pciconfig_read) | ||
241 | SYSCALL(pciconfig_write) | ||
242 | SYSCALL(pciconfig_iobase) | ||
243 | SYSCALL(ni_syscall) | ||
244 | SYSCALL(getdents64) | ||
245 | SYSCALL(pivot_root) | ||
246 | SYSX(sys_ni_syscall,compat_sys_fcntl64,sys_fcntl64) | ||
247 | SYSCALL(madvise) | ||
248 | SYSCALL(mincore) | ||
249 | SYSCALL(gettid) | ||
250 | SYSCALL(tkill) | ||
251 | SYSCALL(setxattr) | ||
252 | SYSCALL(lsetxattr) | ||
253 | SYSCALL(fsetxattr) | ||
254 | SYSCALL(getxattr) | ||
255 | SYSCALL(lgetxattr) | ||
256 | SYSCALL(fgetxattr) | ||
257 | SYSCALL(listxattr) | ||
258 | SYSCALL(llistxattr) | ||
259 | SYSCALL(flistxattr) | ||
260 | SYSCALL(removexattr) | ||
261 | SYSCALL(lremovexattr) | ||
262 | SYSCALL(fremovexattr) | ||
263 | COMPAT_SYS(futex) | ||
264 | COMPAT_SYS(sched_setaffinity) | ||
265 | COMPAT_SYS(sched_getaffinity) | ||
266 | SYSCALL(ni_syscall) | ||
267 | SYSCALL(ni_syscall) | ||
268 | SYS32ONLY(sendfile64) | ||
269 | COMPAT_SYS(io_setup) | ||
270 | SYSCALL(io_destroy) | ||
271 | COMPAT_SYS(io_getevents) | ||
272 | COMPAT_SYS(io_submit) | ||
273 | SYSCALL(io_cancel) | ||
274 | SYSCALL(set_tid_address) | ||
275 | SYSX(sys_fadvise64,ppc32_fadvise64,sys_fadvise64) | ||
276 | SYSCALL(exit_group) | ||
277 | SYSX(sys_lookup_dcookie,ppc32_lookup_dcookie,sys_lookup_dcookie) | ||
278 | SYSCALL(epoll_create) | ||
279 | SYSCALL(epoll_ctl) | ||
280 | SYSCALL(epoll_wait) | ||
281 | SYSCALL(remap_file_pages) | ||
282 | SYSX(sys_timer_create,compat_sys_timer_create,sys_timer_create) | ||
283 | COMPAT_SYS(timer_settime) | ||
284 | COMPAT_SYS(timer_gettime) | ||
285 | SYSCALL(timer_getoverrun) | ||
286 | SYSCALL(timer_delete) | ||
287 | COMPAT_SYS(clock_settime) | ||
288 | COMPAT_SYS(clock_gettime) | ||
289 | COMPAT_SYS(clock_getres) | ||
290 | COMPAT_SYS(clock_nanosleep) | ||
291 | SYSX(ppc64_swapcontext,ppc32_swapcontext,ppc_swapcontext) | ||
292 | COMPAT_SYS(tgkill) | ||
293 | COMPAT_SYS(utimes) | ||
294 | COMPAT_SYS(statfs64) | ||
295 | COMPAT_SYS(fstatfs64) | ||
296 | SYSX(sys_ni_syscall, ppc_fadvise64_64, ppc_fadvise64_64) | ||
297 | PPC_SYS(rtas) | ||
298 | OLDSYS(debug_setcontext) | ||
299 | SYSCALL(ni_syscall) | ||
300 | SYSCALL(ni_syscall) | ||
301 | COMPAT_SYS(mbind) | ||
302 | COMPAT_SYS(get_mempolicy) | ||
303 | COMPAT_SYS(set_mempolicy) | ||
304 | COMPAT_SYS(mq_open) | ||
305 | SYSCALL(mq_unlink) | ||
306 | COMPAT_SYS(mq_timedsend) | ||
307 | COMPAT_SYS(mq_timedreceive) | ||
308 | COMPAT_SYS(mq_notify) | ||
309 | COMPAT_SYS(mq_getsetattr) | ||
310 | COMPAT_SYS(kexec_load) | ||
311 | COMPAT_SYS(add_key) | ||
312 | COMPAT_SYS(request_key) | ||
313 | COMPAT_SYS(keyctl) | ||
314 | COMPAT_SYS(waitid) | ||
315 | COMPAT_SYS(ioprio_set) | ||
316 | COMPAT_SYS(ioprio_get) | ||
317 | SYSCALL(inotify_init) | ||
318 | SYSCALL(inotify_add_watch) | ||
319 | SYSCALL(inotify_rm_watch) | ||
320 | SYSCALL(spu_run) | ||
321 | SYSCALL(spu_create) | ||
322 | COMPAT_SYS(pselect6) | ||
323 | COMPAT_SYS(ppoll) | ||
324 | SYSCALL(unshare) | ||
325 | SYSCALL(splice) | ||
326 | SYSCALL(tee) | ||
327 | SYSCALL(vmsplice) | ||
328 | COMPAT_SYS(openat) | ||
329 | SYSCALL(mkdirat) | ||
330 | SYSCALL(mknodat) | ||
331 | SYSCALL(fchownat) | ||
332 | COMPAT_SYS(futimesat) | ||
333 | SYSX(sys_newfstatat, sys_fstatat64, sys_fstatat64) | ||
334 | SYSCALL(unlinkat) | ||
335 | SYSCALL(renameat) | ||
336 | SYSCALL(linkat) | ||
337 | SYSCALL(symlinkat) | ||
338 | SYSCALL(readlinkat) | ||
339 | SYSCALL(fchmodat) | ||
340 | SYSCALL(faccessat) | ||
341 | COMPAT_SYS(get_robust_list) | ||
342 | COMPAT_SYS(set_robust_list) | ||
343 | |||
344 | /* | ||
345 | * please add new calls to arch/powerpc/platforms/cell/spu_callbacks.c | ||
346 | * as well when appropriate. | ||
347 | */ | ||
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 24e3ad756de0..d20907561f46 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -76,7 +76,6 @@ | |||
76 | 76 | ||
77 | /* keep track of when we need to update the rtc */ | 77 | /* keep track of when we need to update the rtc */ |
78 | time_t last_rtc_update; | 78 | time_t last_rtc_update; |
79 | extern int piranha_simulator; | ||
80 | #ifdef CONFIG_PPC_ISERIES | 79 | #ifdef CONFIG_PPC_ISERIES |
81 | unsigned long iSeries_recal_titan = 0; | 80 | unsigned long iSeries_recal_titan = 0; |
82 | unsigned long iSeries_recal_tb = 0; | 81 | unsigned long iSeries_recal_tb = 0; |
@@ -858,42 +857,50 @@ int do_settimeofday(struct timespec *tv) | |||
858 | 857 | ||
859 | EXPORT_SYMBOL(do_settimeofday); | 858 | EXPORT_SYMBOL(do_settimeofday); |
860 | 859 | ||
861 | void __init generic_calibrate_decr(void) | 860 | static int __init get_freq(char *name, int cells, unsigned long *val) |
862 | { | 861 | { |
863 | struct device_node *cpu; | 862 | struct device_node *cpu; |
864 | unsigned int *fp; | 863 | unsigned int *fp; |
865 | int node_found; | 864 | int found = 0; |
866 | 865 | ||
867 | /* | 866 | /* The cpu node should have timebase and clock frequency properties */ |
868 | * The cpu node should have a timebase-frequency property | ||
869 | * to tell us the rate at which the decrementer counts. | ||
870 | */ | ||
871 | cpu = of_find_node_by_type(NULL, "cpu"); | 867 | cpu = of_find_node_by_type(NULL, "cpu"); |
872 | 868 | ||
873 | ppc_tb_freq = DEFAULT_TB_FREQ; /* hardcoded default */ | ||
874 | node_found = 0; | ||
875 | if (cpu) { | 869 | if (cpu) { |
876 | fp = (unsigned int *)get_property(cpu, "timebase-frequency", | 870 | fp = (unsigned int *)get_property(cpu, name, NULL); |
877 | NULL); | ||
878 | if (fp) { | 871 | if (fp) { |
879 | node_found = 1; | 872 | found = 1; |
880 | ppc_tb_freq = *fp; | 873 | *val = 0; |
874 | while (cells--) | ||
875 | *val = (*val << 32) | *fp++; | ||
881 | } | 876 | } |
877 | |||
878 | of_node_put(cpu); | ||
882 | } | 879 | } |
883 | if (!node_found) | 880 | |
881 | return found; | ||
882 | } | ||
883 | |||
884 | void __init generic_calibrate_decr(void) | ||
885 | { | ||
886 | ppc_tb_freq = DEFAULT_TB_FREQ; /* hardcoded default */ | ||
887 | |||
888 | if (!get_freq("ibm,extended-timebase-frequency", 2, &ppc_tb_freq) && | ||
889 | !get_freq("timebase-frequency", 1, &ppc_tb_freq)) { | ||
890 | |||
884 | printk(KERN_ERR "WARNING: Estimating decrementer frequency " | 891 | printk(KERN_ERR "WARNING: Estimating decrementer frequency " |
885 | "(not found)\n"); | 892 | "(not found)\n"); |
893 | } | ||
886 | 894 | ||
887 | ppc_proc_freq = DEFAULT_PROC_FREQ; | 895 | ppc_proc_freq = DEFAULT_PROC_FREQ; /* hardcoded default */ |
888 | node_found = 0; | 896 | |
889 | if (cpu) { | 897 | if (!get_freq("ibm,extended-clock-frequency", 2, &ppc_proc_freq) && |
890 | fp = (unsigned int *)get_property(cpu, "clock-frequency", | 898 | !get_freq("clock-frequency", 1, &ppc_proc_freq)) { |
891 | NULL); | 899 | |
892 | if (fp) { | 900 | printk(KERN_ERR "WARNING: Estimating processor frequency " |
893 | node_found = 1; | 901 | "(not found)\n"); |
894 | ppc_proc_freq = *fp; | ||
895 | } | ||
896 | } | 902 | } |
903 | |||
897 | #ifdef CONFIG_BOOKE | 904 | #ifdef CONFIG_BOOKE |
898 | /* Set the time base to zero */ | 905 | /* Set the time base to zero */ |
899 | mtspr(SPRN_TBWL, 0); | 906 | mtspr(SPRN_TBWL, 0); |
@@ -905,11 +912,6 @@ void __init generic_calibrate_decr(void) | |||
905 | /* Enable decrementer interrupt */ | 912 | /* Enable decrementer interrupt */ |
906 | mtspr(SPRN_TCR, TCR_DIE); | 913 | mtspr(SPRN_TCR, TCR_DIE); |
907 | #endif | 914 | #endif |
908 | if (!node_found) | ||
909 | printk(KERN_ERR "WARNING: Estimating processor frequency " | ||
910 | "(not found)\n"); | ||
911 | |||
912 | of_node_put(cpu); | ||
913 | } | 915 | } |
914 | 916 | ||
915 | unsigned long get_boot_time(void) | 917 | unsigned long get_boot_time(void) |
@@ -945,9 +947,9 @@ void __init time_init(void) | |||
945 | } else { | 947 | } else { |
946 | /* Normal PowerPC with timebase register */ | 948 | /* Normal PowerPC with timebase register */ |
947 | ppc_md.calibrate_decr(); | 949 | ppc_md.calibrate_decr(); |
948 | printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n", | 950 | printk(KERN_DEBUG "time_init: decrementer frequency = %lu.%.6lu MHz\n", |
949 | ppc_tb_freq / 1000000, ppc_tb_freq % 1000000); | 951 | ppc_tb_freq / 1000000, ppc_tb_freq % 1000000); |
950 | printk(KERN_INFO "time_init: processor frequency = %lu.%.6lu MHz\n", | 952 | printk(KERN_DEBUG "time_init: processor frequency = %lu.%.6lu MHz\n", |
951 | ppc_proc_freq / 1000000, ppc_proc_freq % 1000000); | 953 | ppc_proc_freq / 1000000, ppc_proc_freq % 1000000); |
952 | tb_last_stamp = tb_last_jiffy = get_tb(); | 954 | tb_last_stamp = tb_last_jiffy = get_tb(); |
953 | } | 955 | } |
@@ -1010,10 +1012,7 @@ void __init time_init(void) | |||
1010 | tb_to_ns_scale = scale; | 1012 | tb_to_ns_scale = scale; |
1011 | tb_to_ns_shift = shift; | 1013 | tb_to_ns_shift = shift; |
1012 | 1014 | ||
1013 | #ifdef CONFIG_PPC_ISERIES | 1015 | tm = get_boot_time(); |
1014 | if (!piranha_simulator) | ||
1015 | #endif | ||
1016 | tm = get_boot_time(); | ||
1017 | 1016 | ||
1018 | write_seqlock_irqsave(&xtime_lock, flags); | 1017 | write_seqlock_irqsave(&xtime_lock, flags); |
1019 | 1018 | ||
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 064a52564692..91a6e04d9741 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -658,7 +658,7 @@ static int emulate_instruction(struct pt_regs *regs) | |||
658 | u32 instword; | 658 | u32 instword; |
659 | u32 rd; | 659 | u32 rd; |
660 | 660 | ||
661 | if (!user_mode(regs)) | 661 | if (!user_mode(regs) || (regs->msr & MSR_LE)) |
662 | return -EINVAL; | 662 | return -EINVAL; |
663 | CHECK_FULL_REGS(regs); | 663 | CHECK_FULL_REGS(regs); |
664 | 664 | ||
@@ -805,9 +805,11 @@ void __kprobes program_check_exception(struct pt_regs *regs) | |||
805 | 805 | ||
806 | void alignment_exception(struct pt_regs *regs) | 806 | void alignment_exception(struct pt_regs *regs) |
807 | { | 807 | { |
808 | int fixed; | 808 | int fixed = 0; |
809 | 809 | ||
810 | fixed = fix_alignment(regs); | 810 | /* we don't implement logging of alignment exceptions */ |
811 | if (!(current->thread.align_ctl & PR_UNALIGN_SIGBUS)) | ||
812 | fixed = fix_alignment(regs); | ||
811 | 813 | ||
812 | if (fixed == 1) { | 814 | if (fixed == 1) { |
813 | regs->nip += 4; /* skip over emulated instruction */ | 815 | regs->nip += 4; /* skip over emulated instruction */ |
diff --git a/arch/powerpc/kernel/udbg.c b/arch/powerpc/kernel/udbg.c index 3774e80094f5..67d9fd9ae2b5 100644 --- a/arch/powerpc/kernel/udbg.c +++ b/arch/powerpc/kernel/udbg.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/types.h> | 14 | #include <linux/types.h> |
15 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
16 | #include <linux/console.h> | 16 | #include <linux/console.h> |
17 | #include <linux/init.h> | ||
17 | #include <asm/processor.h> | 18 | #include <asm/processor.h> |
18 | #include <asm/udbg.h> | 19 | #include <asm/udbg.h> |
19 | 20 | ||
@@ -141,12 +142,14 @@ static int early_console_initialized; | |||
141 | 142 | ||
142 | void __init disable_early_printk(void) | 143 | void __init disable_early_printk(void) |
143 | { | 144 | { |
144 | #if 1 | ||
145 | if (!early_console_initialized) | 145 | if (!early_console_initialized) |
146 | return; | 146 | return; |
147 | if (strstr(saved_command_line, "udbg-immortal")) { | ||
148 | printk(KERN_INFO "early console immortal !\n"); | ||
149 | return; | ||
150 | } | ||
147 | unregister_console(&udbg_console); | 151 | unregister_console(&udbg_console); |
148 | early_console_initialized = 0; | 152 | early_console_initialized = 0; |
149 | #endif | ||
150 | } | 153 | } |
151 | 154 | ||
152 | /* called by setup_system */ | 155 | /* called by setup_system */ |
diff --git a/arch/powerpc/kernel/vdso.c b/arch/powerpc/kernel/vdso.c index 573afb68d69e..bc3e15be3087 100644 --- a/arch/powerpc/kernel/vdso.c +++ b/arch/powerpc/kernel/vdso.c | |||
@@ -223,6 +223,7 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, | |||
223 | struct vm_area_struct *vma; | 223 | struct vm_area_struct *vma; |
224 | unsigned long vdso_pages; | 224 | unsigned long vdso_pages; |
225 | unsigned long vdso_base; | 225 | unsigned long vdso_base; |
226 | int rc; | ||
226 | 227 | ||
227 | #ifdef CONFIG_PPC64 | 228 | #ifdef CONFIG_PPC64 |
228 | if (test_thread_flag(TIF_32BIT)) { | 229 | if (test_thread_flag(TIF_32BIT)) { |
@@ -237,20 +238,13 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, | |||
237 | vdso_base = VDSO32_MBASE; | 238 | vdso_base = VDSO32_MBASE; |
238 | #endif | 239 | #endif |
239 | 240 | ||
240 | current->thread.vdso_base = 0; | 241 | current->mm->context.vdso_base = 0; |
241 | 242 | ||
242 | /* vDSO has a problem and was disabled, just don't "enable" it for the | 243 | /* vDSO has a problem and was disabled, just don't "enable" it for the |
243 | * process | 244 | * process |
244 | */ | 245 | */ |
245 | if (vdso_pages == 0) | 246 | if (vdso_pages == 0) |
246 | return 0; | 247 | return 0; |
247 | |||
248 | vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL); | ||
249 | if (vma == NULL) | ||
250 | return -ENOMEM; | ||
251 | |||
252 | memset(vma, 0, sizeof(*vma)); | ||
253 | |||
254 | /* Add a page to the vdso size for the data page */ | 248 | /* Add a page to the vdso size for the data page */ |
255 | vdso_pages ++; | 249 | vdso_pages ++; |
256 | 250 | ||
@@ -259,17 +253,23 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, | |||
259 | * at vdso_base which is the "natural" base for it, but we might fail | 253 | * at vdso_base which is the "natural" base for it, but we might fail |
260 | * and end up putting it elsewhere. | 254 | * and end up putting it elsewhere. |
261 | */ | 255 | */ |
256 | down_write(&mm->mmap_sem); | ||
262 | vdso_base = get_unmapped_area(NULL, vdso_base, | 257 | vdso_base = get_unmapped_area(NULL, vdso_base, |
263 | vdso_pages << PAGE_SHIFT, 0, 0); | 258 | vdso_pages << PAGE_SHIFT, 0, 0); |
264 | if (vdso_base & ~PAGE_MASK) { | 259 | if (IS_ERR_VALUE(vdso_base)) { |
265 | kmem_cache_free(vm_area_cachep, vma); | 260 | rc = vdso_base; |
266 | return (int)vdso_base; | 261 | goto fail_mmapsem; |
267 | } | 262 | } |
268 | 263 | ||
269 | current->thread.vdso_base = vdso_base; | ||
270 | 264 | ||
265 | /* Allocate a VMA structure and fill it up */ | ||
266 | vma = kmem_cache_zalloc(vm_area_cachep, SLAB_KERNEL); | ||
267 | if (vma == NULL) { | ||
268 | rc = -ENOMEM; | ||
269 | goto fail_mmapsem; | ||
270 | } | ||
271 | vma->vm_mm = mm; | 271 | vma->vm_mm = mm; |
272 | vma->vm_start = current->thread.vdso_base; | 272 | vma->vm_start = vdso_base; |
273 | vma->vm_end = vma->vm_start + (vdso_pages << PAGE_SHIFT); | 273 | vma->vm_end = vma->vm_start + (vdso_pages << PAGE_SHIFT); |
274 | 274 | ||
275 | /* | 275 | /* |
@@ -282,23 +282,38 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, | |||
282 | * It's fine to use that for setting breakpoints in the vDSO code | 282 | * It's fine to use that for setting breakpoints in the vDSO code |
283 | * pages though | 283 | * pages though |
284 | */ | 284 | */ |
285 | vma->vm_flags = VM_READ | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC; | 285 | vma->vm_flags = VM_READ|VM_EXEC|VM_MAYREAD|VM_MAYWRITE|VM_MAYEXEC; |
286 | vma->vm_flags |= mm->def_flags; | 286 | vma->vm_flags |= mm->def_flags; |
287 | vma->vm_page_prot = protection_map[vma->vm_flags & 0x7]; | 287 | vma->vm_page_prot = protection_map[vma->vm_flags & 0x7]; |
288 | vma->vm_ops = &vdso_vmops; | 288 | vma->vm_ops = &vdso_vmops; |
289 | 289 | ||
290 | down_write(&mm->mmap_sem); | 290 | /* Insert new VMA */ |
291 | if (insert_vm_struct(mm, vma)) { | 291 | rc = insert_vm_struct(mm, vma); |
292 | up_write(&mm->mmap_sem); | 292 | if (rc) |
293 | kmem_cache_free(vm_area_cachep, vma); | 293 | goto fail_vma; |
294 | return -ENOMEM; | 294 | |
295 | } | 295 | /* Put vDSO base into mm struct and account for memory usage */ |
296 | current->mm->context.vdso_base = vdso_base; | ||
296 | mm->total_vm += (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; | 297 | mm->total_vm += (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; |
297 | up_write(&mm->mmap_sem); | 298 | up_write(&mm->mmap_sem); |
298 | |||
299 | return 0; | 299 | return 0; |
300 | |||
301 | fail_vma: | ||
302 | kmem_cache_free(vm_area_cachep, vma); | ||
303 | fail_mmapsem: | ||
304 | up_write(&mm->mmap_sem); | ||
305 | return rc; | ||
306 | } | ||
307 | |||
308 | const char *arch_vma_name(struct vm_area_struct *vma) | ||
309 | { | ||
310 | if (vma->vm_mm && vma->vm_start == vma->vm_mm->context.vdso_base) | ||
311 | return "[vdso]"; | ||
312 | return NULL; | ||
300 | } | 313 | } |
301 | 314 | ||
315 | |||
316 | |||
302 | static void * __init find_section32(Elf32_Ehdr *ehdr, const char *secname, | 317 | static void * __init find_section32(Elf32_Ehdr *ehdr, const char *secname, |
303 | unsigned long *size) | 318 | unsigned long *size) |
304 | { | 319 | { |
diff --git a/arch/powerpc/kernel/vector.S b/arch/powerpc/kernel/vector.S index 66b3d03c5fa5..9416b4ab92ec 100644 --- a/arch/powerpc/kernel/vector.S +++ b/arch/powerpc/kernel/vector.S | |||
@@ -53,12 +53,12 @@ fpenable: | |||
53 | stfd fr31,8(r1) | 53 | stfd fr31,8(r1) |
54 | LDCONST(fr1, fpzero) | 54 | LDCONST(fr1, fpzero) |
55 | mffs fr31 | 55 | mffs fr31 |
56 | mtfsf 0xff,fr1 | 56 | MTFSF_L(fr1) |
57 | blr | 57 | blr |
58 | 58 | ||
59 | fpdisable: | 59 | fpdisable: |
60 | mtlr r12 | 60 | mtlr r12 |
61 | mtfsf 0xff,fr31 | 61 | MTFSF_L(fr31) |
62 | lfd fr31,8(r1) | 62 | lfd fr31,8(r1) |
63 | lfd fr1,16(r1) | 63 | lfd fr1,16(r1) |
64 | lfd fr0,24(r1) | 64 | lfd fr0,24(r1) |
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c index 971020cf3f7d..cdf5867838a6 100644 --- a/arch/powerpc/kernel/vio.c +++ b/arch/powerpc/kernel/vio.c | |||
@@ -13,27 +13,116 @@ | |||
13 | * 2 of the License, or (at your option) any later version. | 13 | * 2 of the License, or (at your option) any later version. |
14 | */ | 14 | */ |
15 | 15 | ||
16 | #include <linux/types.h> | ||
17 | #include <linux/device.h> | ||
16 | #include <linux/init.h> | 18 | #include <linux/init.h> |
17 | #include <linux/console.h> | 19 | #include <linux/console.h> |
18 | #include <linux/module.h> | 20 | #include <linux/module.h> |
19 | #include <linux/mm.h> | 21 | #include <linux/mm.h> |
20 | #include <linux/dma-mapping.h> | 22 | #include <linux/dma-mapping.h> |
23 | #include <linux/kobject.h> | ||
24 | |||
21 | #include <asm/iommu.h> | 25 | #include <asm/iommu.h> |
22 | #include <asm/dma.h> | 26 | #include <asm/dma.h> |
23 | #include <asm/vio.h> | 27 | #include <asm/vio.h> |
24 | #include <asm/prom.h> | 28 | #include <asm/prom.h> |
25 | 29 | #include <asm/firmware.h> | |
26 | static const struct vio_device_id *vio_match_device( | 30 | #include <asm/tce.h> |
27 | const struct vio_device_id *, const struct vio_dev *); | 31 | #include <asm/abs_addr.h> |
28 | 32 | #include <asm/page.h> | |
29 | struct vio_dev vio_bus_device = { /* fake "parent" device */ | 33 | #include <asm/hvcall.h> |
34 | #include <asm/iseries/vio.h> | ||
35 | #include <asm/iseries/hv_types.h> | ||
36 | #include <asm/iseries/hv_lp_config.h> | ||
37 | #include <asm/iseries/hv_call_xm.h> | ||
38 | #include <asm/iseries/iommu.h> | ||
39 | |||
40 | extern struct subsystem devices_subsys; /* needed for vio_find_name() */ | ||
41 | |||
42 | static struct vio_dev vio_bus_device = { /* fake "parent" device */ | ||
30 | .name = vio_bus_device.dev.bus_id, | 43 | .name = vio_bus_device.dev.bus_id, |
31 | .type = "", | 44 | .type = "", |
32 | .dev.bus_id = "vio", | 45 | .dev.bus_id = "vio", |
33 | .dev.bus = &vio_bus_type, | 46 | .dev.bus = &vio_bus_type, |
34 | }; | 47 | }; |
35 | 48 | ||
36 | static struct vio_bus_ops vio_bus_ops; | 49 | #ifdef CONFIG_PPC_ISERIES |
50 | struct device *iSeries_vio_dev = &vio_bus_device.dev; | ||
51 | EXPORT_SYMBOL(iSeries_vio_dev); | ||
52 | |||
53 | static struct iommu_table veth_iommu_table; | ||
54 | static struct iommu_table vio_iommu_table; | ||
55 | |||
56 | static void __init iommu_vio_init(void) | ||
57 | { | ||
58 | iommu_table_getparms_iSeries(255, 0, 0xff, &veth_iommu_table); | ||
59 | veth_iommu_table.it_size /= 2; | ||
60 | vio_iommu_table = veth_iommu_table; | ||
61 | vio_iommu_table.it_offset += veth_iommu_table.it_size; | ||
62 | |||
63 | if (!iommu_init_table(&veth_iommu_table, -1)) | ||
64 | printk("Virtual Bus VETH TCE table failed.\n"); | ||
65 | if (!iommu_init_table(&vio_iommu_table, -1)) | ||
66 | printk("Virtual Bus VIO TCE table failed.\n"); | ||
67 | } | ||
68 | #endif | ||
69 | |||
70 | static struct iommu_table *vio_build_iommu_table(struct vio_dev *dev) | ||
71 | { | ||
72 | #ifdef CONFIG_PPC_ISERIES | ||
73 | if (firmware_has_feature(FW_FEATURE_ISERIES)) { | ||
74 | if (strcmp(dev->type, "network") == 0) | ||
75 | return &veth_iommu_table; | ||
76 | return &vio_iommu_table; | ||
77 | } else | ||
78 | #endif | ||
79 | { | ||
80 | unsigned char *dma_window; | ||
81 | struct iommu_table *tbl; | ||
82 | unsigned long offset, size; | ||
83 | |||
84 | dma_window = get_property(dev->dev.platform_data, | ||
85 | "ibm,my-dma-window", NULL); | ||
86 | if (!dma_window) | ||
87 | return NULL; | ||
88 | |||
89 | tbl = kmalloc(sizeof(*tbl), GFP_KERNEL); | ||
90 | |||
91 | of_parse_dma_window(dev->dev.platform_data, dma_window, | ||
92 | &tbl->it_index, &offset, &size); | ||
93 | |||
94 | /* TCE table size - measured in tce entries */ | ||
95 | tbl->it_size = size >> PAGE_SHIFT; | ||
96 | /* offset for VIO should always be 0 */ | ||
97 | tbl->it_offset = offset >> PAGE_SHIFT; | ||
98 | tbl->it_busno = 0; | ||
99 | tbl->it_type = TCE_VB; | ||
100 | |||
101 | return iommu_init_table(tbl, -1); | ||
102 | } | ||
103 | } | ||
104 | |||
105 | /** | ||
106 | * vio_match_device: - Tell if a VIO device has a matching | ||
107 | * VIO device id structure. | ||
108 | * @ids: array of VIO device id structures to search in | ||
109 | * @dev: the VIO device structure to match against | ||
110 | * | ||
111 | * Used by a driver to check whether a VIO device present in the | ||
112 | * system is in its list of supported devices. Returns the matching | ||
113 | * vio_device_id structure or NULL if there is no match. | ||
114 | */ | ||
115 | static const struct vio_device_id *vio_match_device( | ||
116 | const struct vio_device_id *ids, const struct vio_dev *dev) | ||
117 | { | ||
118 | while (ids->type[0] != '\0') { | ||
119 | if ((strncmp(dev->type, ids->type, strlen(ids->type)) == 0) && | ||
120 | device_is_compatible(dev->dev.platform_data, ids->compat)) | ||
121 | return ids; | ||
122 | ids++; | ||
123 | } | ||
124 | return NULL; | ||
125 | } | ||
37 | 126 | ||
38 | /* | 127 | /* |
39 | * Convert from struct device to struct vio_dev and pass to driver. | 128 | * Convert from struct device to struct vio_dev and pass to driver. |
@@ -106,35 +195,110 @@ void vio_unregister_driver(struct vio_driver *viodrv) | |||
106 | } | 195 | } |
107 | EXPORT_SYMBOL(vio_unregister_driver); | 196 | EXPORT_SYMBOL(vio_unregister_driver); |
108 | 197 | ||
198 | /* vio_dev refcount hit 0 */ | ||
199 | static void __devinit vio_dev_release(struct device *dev) | ||
200 | { | ||
201 | if (dev->platform_data) { | ||
202 | /* XXX free TCE table */ | ||
203 | of_node_put(dev->platform_data); | ||
204 | } | ||
205 | kfree(to_vio_dev(dev)); | ||
206 | } | ||
207 | |||
109 | /** | 208 | /** |
110 | * vio_match_device: - Tell if a VIO device has a matching | 209 | * vio_register_device_node: - Register a new vio device. |
111 | * VIO device id structure. | 210 | * @of_node: The OF node for this device. |
112 | * @ids: array of VIO device id structures to search in | ||
113 | * @dev: the VIO device structure to match against | ||
114 | * | 211 | * |
115 | * Used by a driver to check whether a VIO device present in the | 212 | * Creates and initializes a vio_dev structure from the data in |
116 | * system is in its list of supported devices. Returns the matching | 213 | * of_node (dev.platform_data) and adds it to the list of virtual devices. |
117 | * vio_device_id structure or NULL if there is no match. | 214 | * Returns a pointer to the created vio_dev or NULL if node has |
215 | * NULL device_type or compatible fields. | ||
118 | */ | 216 | */ |
119 | static const struct vio_device_id *vio_match_device( | 217 | struct vio_dev * __devinit vio_register_device_node(struct device_node *of_node) |
120 | const struct vio_device_id *ids, const struct vio_dev *dev) | ||
121 | { | 218 | { |
122 | while (ids->type[0] != '\0') { | 219 | struct vio_dev *viodev; |
123 | if (vio_bus_ops.match(ids, dev)) | 220 | unsigned int *unit_address; |
124 | return ids; | 221 | unsigned int *irq_p; |
125 | ids++; | 222 | |
223 | /* we need the 'device_type' property, in order to match with drivers */ | ||
224 | if (of_node->type == NULL) { | ||
225 | printk(KERN_WARNING "%s: node %s missing 'device_type'\n", | ||
226 | __FUNCTION__, | ||
227 | of_node->name ? of_node->name : "<unknown>"); | ||
228 | return NULL; | ||
126 | } | 229 | } |
127 | return NULL; | 230 | |
231 | unit_address = (unsigned int *)get_property(of_node, "reg", NULL); | ||
232 | if (unit_address == NULL) { | ||
233 | printk(KERN_WARNING "%s: node %s missing 'reg'\n", | ||
234 | __FUNCTION__, | ||
235 | of_node->name ? of_node->name : "<unknown>"); | ||
236 | return NULL; | ||
237 | } | ||
238 | |||
239 | /* allocate a vio_dev for this node */ | ||
240 | viodev = kzalloc(sizeof(struct vio_dev), GFP_KERNEL); | ||
241 | if (viodev == NULL) | ||
242 | return NULL; | ||
243 | |||
244 | viodev->dev.platform_data = of_node_get(of_node); | ||
245 | |||
246 | viodev->irq = NO_IRQ; | ||
247 | irq_p = (unsigned int *)get_property(of_node, "interrupts", NULL); | ||
248 | if (irq_p) { | ||
249 | int virq = virt_irq_create_mapping(*irq_p); | ||
250 | if (virq == NO_IRQ) { | ||
251 | printk(KERN_ERR "Unable to allocate interrupt " | ||
252 | "number for %s\n", of_node->full_name); | ||
253 | } else | ||
254 | viodev->irq = irq_offset_up(virq); | ||
255 | } | ||
256 | |||
257 | snprintf(viodev->dev.bus_id, BUS_ID_SIZE, "%x", *unit_address); | ||
258 | viodev->name = of_node->name; | ||
259 | viodev->type = of_node->type; | ||
260 | viodev->unit_address = *unit_address; | ||
261 | if (firmware_has_feature(FW_FEATURE_ISERIES)) { | ||
262 | unit_address = (unsigned int *)get_property(of_node, | ||
263 | "linux,unit_address", NULL); | ||
264 | if (unit_address != NULL) | ||
265 | viodev->unit_address = *unit_address; | ||
266 | } | ||
267 | viodev->iommu_table = vio_build_iommu_table(viodev); | ||
268 | |||
269 | /* init generic 'struct device' fields: */ | ||
270 | viodev->dev.parent = &vio_bus_device.dev; | ||
271 | viodev->dev.bus = &vio_bus_type; | ||
272 | viodev->dev.release = vio_dev_release; | ||
273 | |||
274 | /* register with generic device framework */ | ||
275 | if (device_register(&viodev->dev)) { | ||
276 | printk(KERN_ERR "%s: failed to register device %s\n", | ||
277 | __FUNCTION__, viodev->dev.bus_id); | ||
278 | /* XXX free TCE table */ | ||
279 | kfree(viodev); | ||
280 | return NULL; | ||
281 | } | ||
282 | |||
283 | return viodev; | ||
128 | } | 284 | } |
285 | EXPORT_SYMBOL(vio_register_device_node); | ||
129 | 286 | ||
130 | /** | 287 | /** |
131 | * vio_bus_init: - Initialize the virtual IO bus | 288 | * vio_bus_init: - Initialize the virtual IO bus |
132 | */ | 289 | */ |
133 | int __init vio_bus_init(struct vio_bus_ops *ops) | 290 | static int __init vio_bus_init(void) |
134 | { | 291 | { |
135 | int err; | 292 | int err; |
293 | struct device_node *node_vroot; | ||
136 | 294 | ||
137 | vio_bus_ops = *ops; | 295 | #ifdef CONFIG_PPC_ISERIES |
296 | if (firmware_has_feature(FW_FEATURE_ISERIES)) { | ||
297 | iommu_vio_init(); | ||
298 | vio_bus_device.iommu_table = &vio_iommu_table; | ||
299 | iSeries_vio_dev = &vio_bus_device.dev; | ||
300 | } | ||
301 | #endif | ||
138 | 302 | ||
139 | err = bus_register(&vio_bus_type); | 303 | err = bus_register(&vio_bus_type); |
140 | if (err) { | 304 | if (err) { |
@@ -153,47 +317,48 @@ int __init vio_bus_init(struct vio_bus_ops *ops) | |||
153 | return err; | 317 | return err; |
154 | } | 318 | } |
155 | 319 | ||
156 | return 0; | 320 | node_vroot = find_devices("vdevice"); |
157 | } | 321 | if (node_vroot) { |
322 | struct device_node *of_node; | ||
323 | |||
324 | /* | ||
325 | * Create struct vio_devices for each virtual device in | ||
326 | * the device tree. Drivers will associate with them later. | ||
327 | */ | ||
328 | for (of_node = node_vroot->child; of_node != NULL; | ||
329 | of_node = of_node->sibling) { | ||
330 | printk(KERN_DEBUG "%s: processing %p\n", | ||
331 | __FUNCTION__, of_node); | ||
332 | vio_register_device_node(of_node); | ||
333 | } | ||
334 | } | ||
158 | 335 | ||
159 | /* vio_dev refcount hit 0 */ | 336 | return 0; |
160 | static void __devinit vio_dev_release(struct device *dev) | ||
161 | { | ||
162 | if (vio_bus_ops.release_device) | ||
163 | vio_bus_ops.release_device(dev); | ||
164 | kfree(to_vio_dev(dev)); | ||
165 | } | 337 | } |
338 | __initcall(vio_bus_init); | ||
166 | 339 | ||
167 | static ssize_t viodev_show_name(struct device *dev, | 340 | static ssize_t name_show(struct device *dev, |
168 | struct device_attribute *attr, char *buf) | 341 | struct device_attribute *attr, char *buf) |
169 | { | 342 | { |
170 | return sprintf(buf, "%s\n", to_vio_dev(dev)->name); | 343 | return sprintf(buf, "%s\n", to_vio_dev(dev)->name); |
171 | } | 344 | } |
172 | DEVICE_ATTR(name, S_IRUSR | S_IRGRP | S_IROTH, viodev_show_name, NULL); | ||
173 | 345 | ||
174 | struct vio_dev * __devinit vio_register_device(struct vio_dev *viodev) | 346 | static ssize_t devspec_show(struct device *dev, |
347 | struct device_attribute *attr, char *buf) | ||
175 | { | 348 | { |
176 | /* init generic 'struct device' fields: */ | 349 | struct device_node *of_node = dev->platform_data; |
177 | viodev->dev.parent = &vio_bus_device.dev; | ||
178 | viodev->dev.bus = &vio_bus_type; | ||
179 | viodev->dev.release = vio_dev_release; | ||
180 | |||
181 | /* register with generic device framework */ | ||
182 | if (device_register(&viodev->dev)) { | ||
183 | printk(KERN_ERR "%s: failed to register device %s\n", | ||
184 | __FUNCTION__, viodev->dev.bus_id); | ||
185 | return NULL; | ||
186 | } | ||
187 | device_create_file(&viodev->dev, &dev_attr_name); | ||
188 | 350 | ||
189 | return viodev; | 351 | return sprintf(buf, "%s\n", of_node ? of_node->full_name : "none"); |
190 | } | 352 | } |
191 | 353 | ||
354 | static struct device_attribute vio_dev_attrs[] = { | ||
355 | __ATTR_RO(name), | ||
356 | __ATTR_RO(devspec), | ||
357 | __ATTR_NULL | ||
358 | }; | ||
359 | |||
192 | void __devinit vio_unregister_device(struct vio_dev *viodev) | 360 | void __devinit vio_unregister_device(struct vio_dev *viodev) |
193 | { | 361 | { |
194 | if (vio_bus_ops.unregister_device) | ||
195 | vio_bus_ops.unregister_device(viodev); | ||
196 | device_remove_file(&viodev->dev, &dev_attr_name); | ||
197 | device_unregister(&viodev->dev); | 362 | device_unregister(&viodev->dev); |
198 | } | 363 | } |
199 | EXPORT_SYMBOL(vio_unregister_device); | 364 | EXPORT_SYMBOL(vio_unregister_device); |
@@ -229,7 +394,7 @@ static void *vio_alloc_coherent(struct device *dev, size_t size, | |||
229 | dma_addr_t *dma_handle, gfp_t flag) | 394 | dma_addr_t *dma_handle, gfp_t flag) |
230 | { | 395 | { |
231 | return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size, | 396 | return iommu_alloc_coherent(to_vio_dev(dev)->iommu_table, size, |
232 | dma_handle, ~0ul, flag); | 397 | dma_handle, ~0ul, flag, -1); |
233 | } | 398 | } |
234 | 399 | ||
235 | static void vio_free_coherent(struct device *dev, size_t size, | 400 | static void vio_free_coherent(struct device *dev, size_t size, |
@@ -267,22 +432,23 @@ static int vio_hotplug(struct device *dev, char **envp, int num_envp, | |||
267 | char *buffer, int buffer_size) | 432 | char *buffer, int buffer_size) |
268 | { | 433 | { |
269 | const struct vio_dev *vio_dev = to_vio_dev(dev); | 434 | const struct vio_dev *vio_dev = to_vio_dev(dev); |
435 | struct device_node *dn = dev->platform_data; | ||
270 | char *cp; | 436 | char *cp; |
271 | int length; | 437 | int length; |
272 | 438 | ||
273 | if (!num_envp) | 439 | if (!num_envp) |
274 | return -ENOMEM; | 440 | return -ENOMEM; |
275 | 441 | ||
276 | if (!vio_dev->dev.platform_data) | 442 | if (!dn) |
277 | return -ENODEV; | 443 | return -ENODEV; |
278 | cp = (char *)get_property(vio_dev->dev.platform_data, "compatible", &length); | 444 | cp = (char *)get_property(dn, "compatible", &length); |
279 | if (!cp) | 445 | if (!cp) |
280 | return -ENODEV; | 446 | return -ENODEV; |
281 | 447 | ||
282 | envp[0] = buffer; | 448 | envp[0] = buffer; |
283 | length = scnprintf(buffer, buffer_size, "MODALIAS=vio:T%sS%s", | 449 | length = scnprintf(buffer, buffer_size, "MODALIAS=vio:T%sS%s", |
284 | vio_dev->type, cp); | 450 | vio_dev->type, cp); |
285 | if (buffer_size - length <= 0) | 451 | if ((buffer_size - length) <= 0) |
286 | return -ENOMEM; | 452 | return -ENOMEM; |
287 | envp[1] = NULL; | 453 | envp[1] = NULL; |
288 | return 0; | 454 | return 0; |
@@ -290,9 +456,81 @@ static int vio_hotplug(struct device *dev, char **envp, int num_envp, | |||
290 | 456 | ||
291 | struct bus_type vio_bus_type = { | 457 | struct bus_type vio_bus_type = { |
292 | .name = "vio", | 458 | .name = "vio", |
459 | .dev_attrs = vio_dev_attrs, | ||
293 | .uevent = vio_hotplug, | 460 | .uevent = vio_hotplug, |
294 | .match = vio_bus_match, | 461 | .match = vio_bus_match, |
295 | .probe = vio_bus_probe, | 462 | .probe = vio_bus_probe, |
296 | .remove = vio_bus_remove, | 463 | .remove = vio_bus_remove, |
297 | .shutdown = vio_bus_shutdown, | 464 | .shutdown = vio_bus_shutdown, |
298 | }; | 465 | }; |
466 | |||
467 | /** | ||
468 | * vio_get_attribute: - get attribute for virtual device | ||
469 | * @vdev: The vio device to get property. | ||
470 | * @which: The property/attribute to be extracted. | ||
471 | * @length: Pointer to length of returned data size (unused if NULL). | ||
472 | * | ||
473 | * Calls prom.c's get_property() to return the value of the | ||
474 | * attribute specified by @which | ||
475 | */ | ||
476 | const void *vio_get_attribute(struct vio_dev *vdev, char *which, int *length) | ||
477 | { | ||
478 | return get_property(vdev->dev.platform_data, which, length); | ||
479 | } | ||
480 | EXPORT_SYMBOL(vio_get_attribute); | ||
481 | |||
482 | #ifdef CONFIG_PPC_PSERIES | ||
483 | /* vio_find_name() - internal because only vio.c knows how we formatted the | ||
484 | * kobject name | ||
485 | * XXX once vio_bus_type.devices is actually used as a kset in | ||
486 | * drivers/base/bus.c, this function should be removed in favor of | ||
487 | * "device_find(kobj_name, &vio_bus_type)" | ||
488 | */ | ||
489 | static struct vio_dev *vio_find_name(const char *kobj_name) | ||
490 | { | ||
491 | struct kobject *found; | ||
492 | |||
493 | found = kset_find_obj(&devices_subsys.kset, kobj_name); | ||
494 | if (!found) | ||
495 | return NULL; | ||
496 | |||
497 | return to_vio_dev(container_of(found, struct device, kobj)); | ||
498 | } | ||
499 | |||
500 | /** | ||
501 | * vio_find_node - find an already-registered vio_dev | ||
502 | * @vnode: device_node of the virtual device we're looking for | ||
503 | */ | ||
504 | struct vio_dev *vio_find_node(struct device_node *vnode) | ||
505 | { | ||
506 | uint32_t *unit_address; | ||
507 | char kobj_name[BUS_ID_SIZE]; | ||
508 | |||
509 | /* construct the kobject name from the device node */ | ||
510 | unit_address = (uint32_t *)get_property(vnode, "reg", NULL); | ||
511 | if (!unit_address) | ||
512 | return NULL; | ||
513 | snprintf(kobj_name, BUS_ID_SIZE, "%x", *unit_address); | ||
514 | |||
515 | return vio_find_name(kobj_name); | ||
516 | } | ||
517 | EXPORT_SYMBOL(vio_find_node); | ||
518 | |||
519 | int vio_enable_interrupts(struct vio_dev *dev) | ||
520 | { | ||
521 | int rc = h_vio_signal(dev->unit_address, VIO_IRQ_ENABLE); | ||
522 | if (rc != H_SUCCESS) | ||
523 | printk(KERN_ERR "vio: Error 0x%x enabling interrupts\n", rc); | ||
524 | return rc; | ||
525 | } | ||
526 | EXPORT_SYMBOL(vio_enable_interrupts); | ||
527 | |||
528 | int vio_disable_interrupts(struct vio_dev *dev) | ||
529 | { | ||
530 | int rc = h_vio_signal(dev->unit_address, VIO_IRQ_DISABLE); | ||
531 | if (rc != H_SUCCESS) | ||
532 | printk(KERN_ERR "vio: Error 0x%x disabling interrupts\n", rc); | ||
533 | return rc; | ||
534 | } | ||
535 | EXPORT_SYMBOL(vio_disable_interrupts); | ||
536 | #endif /* CONFIG_PPC_PSERIES */ | ||
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index fe79c2584cb0..8b25953dc4f0 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S | |||
@@ -93,6 +93,11 @@ SECTIONS | |||
93 | __ptov_table_begin = .; | 93 | __ptov_table_begin = .; |
94 | *(.ptov_fixup); | 94 | *(.ptov_fixup); |
95 | __ptov_table_end = .; | 95 | __ptov_table_end = .; |
96 | #ifdef CONFIG_PPC_ISERIES | ||
97 | __dt_strings_start = .; | ||
98 | *(.dt_strings); | ||
99 | __dt_strings_end = .; | ||
100 | #endif | ||
96 | } | 101 | } |
97 | 102 | ||
98 | . = ALIGN(16); | 103 | . = ALIGN(16); |