diff options
Diffstat (limited to 'arch/powerpc/kernel')
36 files changed, 947 insertions, 588 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/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..dfe2fcfb20a0 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", |
@@ -232,6 +221,7 @@ struct cpu_spec cpu_specs[] = { | |||
232 | PPC_FEATURE_HAS_ALTIVEC_COMP, | 221 | PPC_FEATURE_HAS_ALTIVEC_COMP, |
233 | .icache_bsize = 128, | 222 | .icache_bsize = 128, |
234 | .dcache_bsize = 128, | 223 | .dcache_bsize = 128, |
224 | .num_pmcs = 8, | ||
235 | .cpu_setup = __setup_cpu_ppc970, | 225 | .cpu_setup = __setup_cpu_ppc970, |
236 | .oprofile_cpu_type = "ppc64/970", | 226 | .oprofile_cpu_type = "ppc64/970", |
237 | .oprofile_type = PPC_OPROFILE_POWER4, | 227 | .oprofile_type = PPC_OPROFILE_POWER4, |
@@ -246,9 +236,13 @@ struct cpu_spec cpu_specs[] = { | |||
246 | .icache_bsize = 128, | 236 | .icache_bsize = 128, |
247 | .dcache_bsize = 128, | 237 | .dcache_bsize = 128, |
248 | .num_pmcs = 6, | 238 | .num_pmcs = 6, |
249 | .cpu_setup = __setup_cpu_power4, | ||
250 | .oprofile_cpu_type = "ppc64/power5", | 239 | .oprofile_cpu_type = "ppc64/power5", |
251 | .oprofile_type = PPC_OPROFILE_POWER4, | 240 | .oprofile_type = PPC_OPROFILE_POWER4, |
241 | /* SIHV / SIPR bits are implemented on POWER4+ (GQ) | ||
242 | * and above but only works on POWER5 and above | ||
243 | */ | ||
244 | .oprofile_mmcra_sihv = MMCRA_SIHV, | ||
245 | .oprofile_mmcra_sipr = MMCRA_SIPR, | ||
252 | .platform = "power5", | 246 | .platform = "power5", |
253 | }, | 247 | }, |
254 | { /* Power5 GS */ | 248 | { /* Power5 GS */ |
@@ -260,9 +254,10 @@ struct cpu_spec cpu_specs[] = { | |||
260 | .icache_bsize = 128, | 254 | .icache_bsize = 128, |
261 | .dcache_bsize = 128, | 255 | .dcache_bsize = 128, |
262 | .num_pmcs = 6, | 256 | .num_pmcs = 6, |
263 | .cpu_setup = __setup_cpu_power4, | ||
264 | .oprofile_cpu_type = "ppc64/power5+", | 257 | .oprofile_cpu_type = "ppc64/power5+", |
265 | .oprofile_type = PPC_OPROFILE_POWER4, | 258 | .oprofile_type = PPC_OPROFILE_POWER4, |
259 | .oprofile_mmcra_sihv = MMCRA_SIHV, | ||
260 | .oprofile_mmcra_sipr = MMCRA_SIPR, | ||
266 | .platform = "power5+", | 261 | .platform = "power5+", |
267 | }, | 262 | }, |
268 | { /* Power6 */ | 263 | { /* Power6 */ |
@@ -273,10 +268,13 @@ struct cpu_spec cpu_specs[] = { | |||
273 | .cpu_user_features = COMMON_USER_POWER6, | 268 | .cpu_user_features = COMMON_USER_POWER6, |
274 | .icache_bsize = 128, | 269 | .icache_bsize = 128, |
275 | .dcache_bsize = 128, | 270 | .dcache_bsize = 128, |
276 | .num_pmcs = 6, | 271 | .num_pmcs = 8, |
277 | .cpu_setup = __setup_cpu_power4, | ||
278 | .oprofile_cpu_type = "ppc64/power6", | 272 | .oprofile_cpu_type = "ppc64/power6", |
279 | .oprofile_type = PPC_OPROFILE_POWER4, | 273 | .oprofile_type = PPC_OPROFILE_POWER4, |
274 | .oprofile_mmcra_sihv = POWER6_MMCRA_SIHV, | ||
275 | .oprofile_mmcra_sipr = POWER6_MMCRA_SIPR, | ||
276 | .oprofile_mmcra_clear = POWER6_MMCRA_THRM | | ||
277 | POWER6_MMCRA_OTHER, | ||
280 | .platform = "power6", | 278 | .platform = "power6", |
281 | }, | 279 | }, |
282 | { /* Cell Broadband Engine */ | 280 | { /* Cell Broadband Engine */ |
@@ -289,7 +287,6 @@ struct cpu_spec cpu_specs[] = { | |||
289 | PPC_FEATURE_SMT, | 287 | PPC_FEATURE_SMT, |
290 | .icache_bsize = 128, | 288 | .icache_bsize = 128, |
291 | .dcache_bsize = 128, | 289 | .dcache_bsize = 128, |
292 | .cpu_setup = __setup_cpu_be, | ||
293 | .platform = "ppc-cell-be", | 290 | .platform = "ppc-cell-be", |
294 | }, | 291 | }, |
295 | { /* default match */ | 292 | { /* default match */ |
@@ -301,7 +298,6 @@ struct cpu_spec cpu_specs[] = { | |||
301 | .icache_bsize = 128, | 298 | .icache_bsize = 128, |
302 | .dcache_bsize = 128, | 299 | .dcache_bsize = 128, |
303 | .num_pmcs = 6, | 300 | .num_pmcs = 6, |
304 | .cpu_setup = __setup_cpu_power4, | ||
305 | .platform = "power4", | 301 | .platform = "power4", |
306 | } | 302 | } |
307 | #endif /* CONFIG_PPC64 */ | 303 | #endif /* CONFIG_PPC64 */ |
@@ -323,7 +319,7 @@ struct cpu_spec cpu_specs[] = { | |||
323 | .pvr_value = 0x00030000, | 319 | .pvr_value = 0x00030000, |
324 | .cpu_name = "603", | 320 | .cpu_name = "603", |
325 | .cpu_features = CPU_FTRS_603, | 321 | .cpu_features = CPU_FTRS_603, |
326 | .cpu_user_features = COMMON_USER, | 322 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
327 | .icache_bsize = 32, | 323 | .icache_bsize = 32, |
328 | .dcache_bsize = 32, | 324 | .dcache_bsize = 32, |
329 | .cpu_setup = __setup_cpu_603, | 325 | .cpu_setup = __setup_cpu_603, |
@@ -334,7 +330,7 @@ struct cpu_spec cpu_specs[] = { | |||
334 | .pvr_value = 0x00060000, | 330 | .pvr_value = 0x00060000, |
335 | .cpu_name = "603e", | 331 | .cpu_name = "603e", |
336 | .cpu_features = CPU_FTRS_603, | 332 | .cpu_features = CPU_FTRS_603, |
337 | .cpu_user_features = COMMON_USER, | 333 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
338 | .icache_bsize = 32, | 334 | .icache_bsize = 32, |
339 | .dcache_bsize = 32, | 335 | .dcache_bsize = 32, |
340 | .cpu_setup = __setup_cpu_603, | 336 | .cpu_setup = __setup_cpu_603, |
@@ -345,7 +341,7 @@ struct cpu_spec cpu_specs[] = { | |||
345 | .pvr_value = 0x00070000, | 341 | .pvr_value = 0x00070000, |
346 | .cpu_name = "603ev", | 342 | .cpu_name = "603ev", |
347 | .cpu_features = CPU_FTRS_603, | 343 | .cpu_features = CPU_FTRS_603, |
348 | .cpu_user_features = COMMON_USER, | 344 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
349 | .icache_bsize = 32, | 345 | .icache_bsize = 32, |
350 | .dcache_bsize = 32, | 346 | .dcache_bsize = 32, |
351 | .cpu_setup = __setup_cpu_603, | 347 | .cpu_setup = __setup_cpu_603, |
@@ -356,7 +352,7 @@ struct cpu_spec cpu_specs[] = { | |||
356 | .pvr_value = 0x00040000, | 352 | .pvr_value = 0x00040000, |
357 | .cpu_name = "604", | 353 | .cpu_name = "604", |
358 | .cpu_features = CPU_FTRS_604, | 354 | .cpu_features = CPU_FTRS_604, |
359 | .cpu_user_features = COMMON_USER, | 355 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
360 | .icache_bsize = 32, | 356 | .icache_bsize = 32, |
361 | .dcache_bsize = 32, | 357 | .dcache_bsize = 32, |
362 | .num_pmcs = 2, | 358 | .num_pmcs = 2, |
@@ -368,7 +364,7 @@ struct cpu_spec cpu_specs[] = { | |||
368 | .pvr_value = 0x00090000, | 364 | .pvr_value = 0x00090000, |
369 | .cpu_name = "604e", | 365 | .cpu_name = "604e", |
370 | .cpu_features = CPU_FTRS_604, | 366 | .cpu_features = CPU_FTRS_604, |
371 | .cpu_user_features = COMMON_USER, | 367 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
372 | .icache_bsize = 32, | 368 | .icache_bsize = 32, |
373 | .dcache_bsize = 32, | 369 | .dcache_bsize = 32, |
374 | .num_pmcs = 4, | 370 | .num_pmcs = 4, |
@@ -380,7 +376,7 @@ struct cpu_spec cpu_specs[] = { | |||
380 | .pvr_value = 0x00090000, | 376 | .pvr_value = 0x00090000, |
381 | .cpu_name = "604r", | 377 | .cpu_name = "604r", |
382 | .cpu_features = CPU_FTRS_604, | 378 | .cpu_features = CPU_FTRS_604, |
383 | .cpu_user_features = COMMON_USER, | 379 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
384 | .icache_bsize = 32, | 380 | .icache_bsize = 32, |
385 | .dcache_bsize = 32, | 381 | .dcache_bsize = 32, |
386 | .num_pmcs = 4, | 382 | .num_pmcs = 4, |
@@ -392,7 +388,7 @@ struct cpu_spec cpu_specs[] = { | |||
392 | .pvr_value = 0x000a0000, | 388 | .pvr_value = 0x000a0000, |
393 | .cpu_name = "604ev", | 389 | .cpu_name = "604ev", |
394 | .cpu_features = CPU_FTRS_604, | 390 | .cpu_features = CPU_FTRS_604, |
395 | .cpu_user_features = COMMON_USER, | 391 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
396 | .icache_bsize = 32, | 392 | .icache_bsize = 32, |
397 | .dcache_bsize = 32, | 393 | .dcache_bsize = 32, |
398 | .num_pmcs = 4, | 394 | .num_pmcs = 4, |
@@ -404,7 +400,7 @@ struct cpu_spec cpu_specs[] = { | |||
404 | .pvr_value = 0x00084202, | 400 | .pvr_value = 0x00084202, |
405 | .cpu_name = "740/750", | 401 | .cpu_name = "740/750", |
406 | .cpu_features = CPU_FTRS_740_NOTAU, | 402 | .cpu_features = CPU_FTRS_740_NOTAU, |
407 | .cpu_user_features = COMMON_USER, | 403 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
408 | .icache_bsize = 32, | 404 | .icache_bsize = 32, |
409 | .dcache_bsize = 32, | 405 | .dcache_bsize = 32, |
410 | .num_pmcs = 4, | 406 | .num_pmcs = 4, |
@@ -416,7 +412,7 @@ struct cpu_spec cpu_specs[] = { | |||
416 | .pvr_value = 0x00080100, | 412 | .pvr_value = 0x00080100, |
417 | .cpu_name = "750CX", | 413 | .cpu_name = "750CX", |
418 | .cpu_features = CPU_FTRS_750, | 414 | .cpu_features = CPU_FTRS_750, |
419 | .cpu_user_features = COMMON_USER, | 415 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
420 | .icache_bsize = 32, | 416 | .icache_bsize = 32, |
421 | .dcache_bsize = 32, | 417 | .dcache_bsize = 32, |
422 | .num_pmcs = 4, | 418 | .num_pmcs = 4, |
@@ -428,7 +424,7 @@ struct cpu_spec cpu_specs[] = { | |||
428 | .pvr_value = 0x00082200, | 424 | .pvr_value = 0x00082200, |
429 | .cpu_name = "750CX", | 425 | .cpu_name = "750CX", |
430 | .cpu_features = CPU_FTRS_750, | 426 | .cpu_features = CPU_FTRS_750, |
431 | .cpu_user_features = COMMON_USER, | 427 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
432 | .icache_bsize = 32, | 428 | .icache_bsize = 32, |
433 | .dcache_bsize = 32, | 429 | .dcache_bsize = 32, |
434 | .num_pmcs = 4, | 430 | .num_pmcs = 4, |
@@ -440,7 +436,7 @@ struct cpu_spec cpu_specs[] = { | |||
440 | .pvr_value = 0x00082210, | 436 | .pvr_value = 0x00082210, |
441 | .cpu_name = "750CXe", | 437 | .cpu_name = "750CXe", |
442 | .cpu_features = CPU_FTRS_750, | 438 | .cpu_features = CPU_FTRS_750, |
443 | .cpu_user_features = COMMON_USER, | 439 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
444 | .icache_bsize = 32, | 440 | .icache_bsize = 32, |
445 | .dcache_bsize = 32, | 441 | .dcache_bsize = 32, |
446 | .num_pmcs = 4, | 442 | .num_pmcs = 4, |
@@ -452,7 +448,7 @@ struct cpu_spec cpu_specs[] = { | |||
452 | .pvr_value = 0x00083214, | 448 | .pvr_value = 0x00083214, |
453 | .cpu_name = "750CXe", | 449 | .cpu_name = "750CXe", |
454 | .cpu_features = CPU_FTRS_750, | 450 | .cpu_features = CPU_FTRS_750, |
455 | .cpu_user_features = COMMON_USER, | 451 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
456 | .icache_bsize = 32, | 452 | .icache_bsize = 32, |
457 | .dcache_bsize = 32, | 453 | .dcache_bsize = 32, |
458 | .num_pmcs = 4, | 454 | .num_pmcs = 4, |
@@ -464,7 +460,7 @@ struct cpu_spec cpu_specs[] = { | |||
464 | .pvr_value = 0x00083000, | 460 | .pvr_value = 0x00083000, |
465 | .cpu_name = "745/755", | 461 | .cpu_name = "745/755", |
466 | .cpu_features = CPU_FTRS_750, | 462 | .cpu_features = CPU_FTRS_750, |
467 | .cpu_user_features = COMMON_USER, | 463 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
468 | .icache_bsize = 32, | 464 | .icache_bsize = 32, |
469 | .dcache_bsize = 32, | 465 | .dcache_bsize = 32, |
470 | .num_pmcs = 4, | 466 | .num_pmcs = 4, |
@@ -476,7 +472,7 @@ struct cpu_spec cpu_specs[] = { | |||
476 | .pvr_value = 0x70000100, | 472 | .pvr_value = 0x70000100, |
477 | .cpu_name = "750FX", | 473 | .cpu_name = "750FX", |
478 | .cpu_features = CPU_FTRS_750FX1, | 474 | .cpu_features = CPU_FTRS_750FX1, |
479 | .cpu_user_features = COMMON_USER, | 475 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
480 | .icache_bsize = 32, | 476 | .icache_bsize = 32, |
481 | .dcache_bsize = 32, | 477 | .dcache_bsize = 32, |
482 | .num_pmcs = 4, | 478 | .num_pmcs = 4, |
@@ -488,7 +484,7 @@ struct cpu_spec cpu_specs[] = { | |||
488 | .pvr_value = 0x70000200, | 484 | .pvr_value = 0x70000200, |
489 | .cpu_name = "750FX", | 485 | .cpu_name = "750FX", |
490 | .cpu_features = CPU_FTRS_750FX2, | 486 | .cpu_features = CPU_FTRS_750FX2, |
491 | .cpu_user_features = COMMON_USER, | 487 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
492 | .icache_bsize = 32, | 488 | .icache_bsize = 32, |
493 | .dcache_bsize = 32, | 489 | .dcache_bsize = 32, |
494 | .num_pmcs = 4, | 490 | .num_pmcs = 4, |
@@ -500,7 +496,7 @@ struct cpu_spec cpu_specs[] = { | |||
500 | .pvr_value = 0x70000000, | 496 | .pvr_value = 0x70000000, |
501 | .cpu_name = "750FX", | 497 | .cpu_name = "750FX", |
502 | .cpu_features = CPU_FTRS_750FX, | 498 | .cpu_features = CPU_FTRS_750FX, |
503 | .cpu_user_features = COMMON_USER, | 499 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
504 | .icache_bsize = 32, | 500 | .icache_bsize = 32, |
505 | .dcache_bsize = 32, | 501 | .dcache_bsize = 32, |
506 | .num_pmcs = 4, | 502 | .num_pmcs = 4, |
@@ -512,7 +508,7 @@ struct cpu_spec cpu_specs[] = { | |||
512 | .pvr_value = 0x70020000, | 508 | .pvr_value = 0x70020000, |
513 | .cpu_name = "750GX", | 509 | .cpu_name = "750GX", |
514 | .cpu_features = CPU_FTRS_750GX, | 510 | .cpu_features = CPU_FTRS_750GX, |
515 | .cpu_user_features = COMMON_USER, | 511 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
516 | .icache_bsize = 32, | 512 | .icache_bsize = 32, |
517 | .dcache_bsize = 32, | 513 | .dcache_bsize = 32, |
518 | .num_pmcs = 4, | 514 | .num_pmcs = 4, |
@@ -524,7 +520,7 @@ struct cpu_spec cpu_specs[] = { | |||
524 | .pvr_value = 0x00080000, | 520 | .pvr_value = 0x00080000, |
525 | .cpu_name = "740/750", | 521 | .cpu_name = "740/750", |
526 | .cpu_features = CPU_FTRS_740, | 522 | .cpu_features = CPU_FTRS_740, |
527 | .cpu_user_features = COMMON_USER, | 523 | .cpu_user_features = COMMON_USER | PPC_FEATURE_PPC_LE, |
528 | .icache_bsize = 32, | 524 | .icache_bsize = 32, |
529 | .dcache_bsize = 32, | 525 | .dcache_bsize = 32, |
530 | .num_pmcs = 4, | 526 | .num_pmcs = 4, |
@@ -536,7 +532,8 @@ struct cpu_spec cpu_specs[] = { | |||
536 | .pvr_value = 0x000c1101, | 532 | .pvr_value = 0x000c1101, |
537 | .cpu_name = "7400 (1.1)", | 533 | .cpu_name = "7400 (1.1)", |
538 | .cpu_features = CPU_FTRS_7400_NOTAU, | 534 | .cpu_features = CPU_FTRS_7400_NOTAU, |
539 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 535 | .cpu_user_features = COMMON_USER | |
536 | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, | ||
540 | .icache_bsize = 32, | 537 | .icache_bsize = 32, |
541 | .dcache_bsize = 32, | 538 | .dcache_bsize = 32, |
542 | .num_pmcs = 4, | 539 | .num_pmcs = 4, |
@@ -548,7 +545,8 @@ struct cpu_spec cpu_specs[] = { | |||
548 | .pvr_value = 0x000c0000, | 545 | .pvr_value = 0x000c0000, |
549 | .cpu_name = "7400", | 546 | .cpu_name = "7400", |
550 | .cpu_features = CPU_FTRS_7400, | 547 | .cpu_features = CPU_FTRS_7400, |
551 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 548 | .cpu_user_features = COMMON_USER | |
549 | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, | ||
552 | .icache_bsize = 32, | 550 | .icache_bsize = 32, |
553 | .dcache_bsize = 32, | 551 | .dcache_bsize = 32, |
554 | .num_pmcs = 4, | 552 | .num_pmcs = 4, |
@@ -560,7 +558,8 @@ struct cpu_spec cpu_specs[] = { | |||
560 | .pvr_value = 0x800c0000, | 558 | .pvr_value = 0x800c0000, |
561 | .cpu_name = "7410", | 559 | .cpu_name = "7410", |
562 | .cpu_features = CPU_FTRS_7400, | 560 | .cpu_features = CPU_FTRS_7400, |
563 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 561 | .cpu_user_features = COMMON_USER | |
562 | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, | ||
564 | .icache_bsize = 32, | 563 | .icache_bsize = 32, |
565 | .dcache_bsize = 32, | 564 | .dcache_bsize = 32, |
566 | .num_pmcs = 4, | 565 | .num_pmcs = 4, |
@@ -572,7 +571,8 @@ struct cpu_spec cpu_specs[] = { | |||
572 | .pvr_value = 0x80000200, | 571 | .pvr_value = 0x80000200, |
573 | .cpu_name = "7450", | 572 | .cpu_name = "7450", |
574 | .cpu_features = CPU_FTRS_7450_20, | 573 | .cpu_features = CPU_FTRS_7450_20, |
575 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 574 | .cpu_user_features = COMMON_USER | |
575 | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, | ||
576 | .icache_bsize = 32, | 576 | .icache_bsize = 32, |
577 | .dcache_bsize = 32, | 577 | .dcache_bsize = 32, |
578 | .num_pmcs = 6, | 578 | .num_pmcs = 6, |
@@ -586,7 +586,8 @@ struct cpu_spec cpu_specs[] = { | |||
586 | .pvr_value = 0x80000201, | 586 | .pvr_value = 0x80000201, |
587 | .cpu_name = "7450", | 587 | .cpu_name = "7450", |
588 | .cpu_features = CPU_FTRS_7450_21, | 588 | .cpu_features = CPU_FTRS_7450_21, |
589 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 589 | .cpu_user_features = COMMON_USER | |
590 | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, | ||
590 | .icache_bsize = 32, | 591 | .icache_bsize = 32, |
591 | .dcache_bsize = 32, | 592 | .dcache_bsize = 32, |
592 | .num_pmcs = 6, | 593 | .num_pmcs = 6, |
@@ -600,7 +601,8 @@ struct cpu_spec cpu_specs[] = { | |||
600 | .pvr_value = 0x80000000, | 601 | .pvr_value = 0x80000000, |
601 | .cpu_name = "7450", | 602 | .cpu_name = "7450", |
602 | .cpu_features = CPU_FTRS_7450_23, | 603 | .cpu_features = CPU_FTRS_7450_23, |
603 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 604 | .cpu_user_features = COMMON_USER | |
605 | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, | ||
604 | .icache_bsize = 32, | 606 | .icache_bsize = 32, |
605 | .dcache_bsize = 32, | 607 | .dcache_bsize = 32, |
606 | .num_pmcs = 6, | 608 | .num_pmcs = 6, |
@@ -614,7 +616,8 @@ struct cpu_spec cpu_specs[] = { | |||
614 | .pvr_value = 0x80010100, | 616 | .pvr_value = 0x80010100, |
615 | .cpu_name = "7455", | 617 | .cpu_name = "7455", |
616 | .cpu_features = CPU_FTRS_7455_1, | 618 | .cpu_features = CPU_FTRS_7455_1, |
617 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 619 | .cpu_user_features = COMMON_USER | |
620 | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, | ||
618 | .icache_bsize = 32, | 621 | .icache_bsize = 32, |
619 | .dcache_bsize = 32, | 622 | .dcache_bsize = 32, |
620 | .num_pmcs = 6, | 623 | .num_pmcs = 6, |
@@ -628,7 +631,8 @@ struct cpu_spec cpu_specs[] = { | |||
628 | .pvr_value = 0x80010200, | 631 | .pvr_value = 0x80010200, |
629 | .cpu_name = "7455", | 632 | .cpu_name = "7455", |
630 | .cpu_features = CPU_FTRS_7455_20, | 633 | .cpu_features = CPU_FTRS_7455_20, |
631 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 634 | .cpu_user_features = COMMON_USER | |
635 | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, | ||
632 | .icache_bsize = 32, | 636 | .icache_bsize = 32, |
633 | .dcache_bsize = 32, | 637 | .dcache_bsize = 32, |
634 | .num_pmcs = 6, | 638 | .num_pmcs = 6, |
@@ -642,7 +646,8 @@ struct cpu_spec cpu_specs[] = { | |||
642 | .pvr_value = 0x80010000, | 646 | .pvr_value = 0x80010000, |
643 | .cpu_name = "7455", | 647 | .cpu_name = "7455", |
644 | .cpu_features = CPU_FTRS_7455, | 648 | .cpu_features = CPU_FTRS_7455, |
645 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 649 | .cpu_user_features = COMMON_USER | |
650 | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, | ||
646 | .icache_bsize = 32, | 651 | .icache_bsize = 32, |
647 | .dcache_bsize = 32, | 652 | .dcache_bsize = 32, |
648 | .num_pmcs = 6, | 653 | .num_pmcs = 6, |
@@ -656,7 +661,8 @@ struct cpu_spec cpu_specs[] = { | |||
656 | .pvr_value = 0x80020100, | 661 | .pvr_value = 0x80020100, |
657 | .cpu_name = "7447/7457", | 662 | .cpu_name = "7447/7457", |
658 | .cpu_features = CPU_FTRS_7447_10, | 663 | .cpu_features = CPU_FTRS_7447_10, |
659 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 664 | .cpu_user_features = COMMON_USER | |
665 | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, | ||
660 | .icache_bsize = 32, | 666 | .icache_bsize = 32, |
661 | .dcache_bsize = 32, | 667 | .dcache_bsize = 32, |
662 | .num_pmcs = 6, | 668 | .num_pmcs = 6, |
@@ -670,7 +676,8 @@ struct cpu_spec cpu_specs[] = { | |||
670 | .pvr_value = 0x80020101, | 676 | .pvr_value = 0x80020101, |
671 | .cpu_name = "7447/7457", | 677 | .cpu_name = "7447/7457", |
672 | .cpu_features = CPU_FTRS_7447_10, | 678 | .cpu_features = CPU_FTRS_7447_10, |
673 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 679 | .cpu_user_features = COMMON_USER | |
680 | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, | ||
674 | .icache_bsize = 32, | 681 | .icache_bsize = 32, |
675 | .dcache_bsize = 32, | 682 | .dcache_bsize = 32, |
676 | .num_pmcs = 6, | 683 | .num_pmcs = 6, |
@@ -684,7 +691,7 @@ struct cpu_spec cpu_specs[] = { | |||
684 | .pvr_value = 0x80020000, | 691 | .pvr_value = 0x80020000, |
685 | .cpu_name = "7447/7457", | 692 | .cpu_name = "7447/7457", |
686 | .cpu_features = CPU_FTRS_7447, | 693 | .cpu_features = CPU_FTRS_7447, |
687 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 694 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, |
688 | .icache_bsize = 32, | 695 | .icache_bsize = 32, |
689 | .dcache_bsize = 32, | 696 | .dcache_bsize = 32, |
690 | .num_pmcs = 6, | 697 | .num_pmcs = 6, |
@@ -698,7 +705,8 @@ struct cpu_spec cpu_specs[] = { | |||
698 | .pvr_value = 0x80030000, | 705 | .pvr_value = 0x80030000, |
699 | .cpu_name = "7447A", | 706 | .cpu_name = "7447A", |
700 | .cpu_features = CPU_FTRS_7447A, | 707 | .cpu_features = CPU_FTRS_7447A, |
701 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 708 | .cpu_user_features = COMMON_USER | |
709 | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, | ||
702 | .icache_bsize = 32, | 710 | .icache_bsize = 32, |
703 | .dcache_bsize = 32, | 711 | .dcache_bsize = 32, |
704 | .num_pmcs = 6, | 712 | .num_pmcs = 6, |
@@ -712,7 +720,8 @@ struct cpu_spec cpu_specs[] = { | |||
712 | .pvr_value = 0x80040000, | 720 | .pvr_value = 0x80040000, |
713 | .cpu_name = "7448", | 721 | .cpu_name = "7448", |
714 | .cpu_features = CPU_FTRS_7447A, | 722 | .cpu_features = CPU_FTRS_7447A, |
715 | .cpu_user_features = COMMON_USER | PPC_FEATURE_HAS_ALTIVEC_COMP, | 723 | .cpu_user_features = COMMON_USER | |
724 | PPC_FEATURE_HAS_ALTIVEC_COMP | PPC_FEATURE_PPC_LE, | ||
716 | .icache_bsize = 32, | 725 | .icache_bsize = 32, |
717 | .dcache_bsize = 32, | 726 | .dcache_bsize = 32, |
718 | .num_pmcs = 6, | 727 | .num_pmcs = 6, |
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/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..cef8cba8329b 100644 --- a/arch/powerpc/kernel/iommu.c +++ b/arch/powerpc/kernel/iommu.c | |||
@@ -536,11 +536,12 @@ void iommu_unmap_single(struct iommu_table *tbl, dma_addr_t dma_handle, | |||
536 | * to the dma address (mapping) of the first page. | 536 | * to the dma address (mapping) of the first page. |
537 | */ | 537 | */ |
538 | void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, | 538 | void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, |
539 | dma_addr_t *dma_handle, unsigned long mask, gfp_t flag) | 539 | dma_addr_t *dma_handle, unsigned long mask, gfp_t flag, int node) |
540 | { | 540 | { |
541 | void *ret = NULL; | 541 | void *ret = NULL; |
542 | dma_addr_t mapping; | 542 | dma_addr_t mapping; |
543 | unsigned int npages, order; | 543 | unsigned int npages, order; |
544 | struct page *page; | ||
544 | 545 | ||
545 | size = PAGE_ALIGN(size); | 546 | size = PAGE_ALIGN(size); |
546 | npages = size >> PAGE_SHIFT; | 547 | npages = size >> PAGE_SHIFT; |
@@ -560,9 +561,10 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, | |||
560 | return NULL; | 561 | return NULL; |
561 | 562 | ||
562 | /* Alloc enough pages (and possibly more) */ | 563 | /* Alloc enough pages (and possibly more) */ |
563 | ret = (void *)__get_free_pages(flag, order); | 564 | page = alloc_pages_node(node, flag, order); |
564 | if (!ret) | 565 | if (!page) |
565 | return NULL; | 566 | return NULL; |
567 | ret = page_address(page); | ||
566 | memset(ret, 0, size); | 568 | memset(ret, 0, size); |
567 | 569 | ||
568 | /* Set up tces to cover the allocated range */ | 570 | /* Set up tces to cover the allocated range */ |
@@ -570,9 +572,9 @@ void *iommu_alloc_coherent(struct iommu_table *tbl, size_t size, | |||
570 | mask >> PAGE_SHIFT, order); | 572 | mask >> PAGE_SHIFT, order); |
571 | if (mapping == DMA_ERROR_CODE) { | 573 | if (mapping == DMA_ERROR_CODE) { |
572 | free_pages((unsigned long)ret, order); | 574 | free_pages((unsigned long)ret, order); |
573 | ret = NULL; | 575 | return NULL; |
574 | } else | 576 | } |
575 | *dma_handle = mapping; | 577 | *dma_handle = mapping; |
576 | return ret; | 578 | return ret; |
577 | } | 579 | } |
578 | 580 | ||
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_64.c b/arch/powerpc/kernel/pci_64.c index 4c4449be81ce..30a4e6a1368a 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); |
@@ -605,7 +597,7 @@ static int __init pcibios_init(void) | |||
605 | iSeries_pcibios_init(); | 597 | iSeries_pcibios_init(); |
606 | #endif | 598 | #endif |
607 | 599 | ||
608 | printk("PCI: Probing PCI hardware\n"); | 600 | printk(KERN_DEBUG "PCI: Probing PCI hardware\n"); |
609 | 601 | ||
610 | /* Scan all of the recorded PCI controllers. */ | 602 | /* Scan all of the recorded PCI controllers. */ |
611 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { | 603 | list_for_each_entry_safe(hose, tmp, &hose_list, list_node) { |
@@ -630,14 +622,14 @@ static int __init pcibios_init(void) | |||
630 | /* Cache the location of the ISA bridge (if we have one) */ | 622 | /* Cache the location of the ISA bridge (if we have one) */ |
631 | ppc64_isabridge_dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL); | 623 | ppc64_isabridge_dev = pci_get_class(PCI_CLASS_BRIDGE_ISA << 8, NULL); |
632 | if (ppc64_isabridge_dev != NULL) | 624 | if (ppc64_isabridge_dev != NULL) |
633 | printk("ISA bridge at %s\n", pci_name(ppc64_isabridge_dev)); | 625 | printk(KERN_DEBUG "ISA bridge at %s\n", pci_name(ppc64_isabridge_dev)); |
634 | 626 | ||
635 | #ifdef CONFIG_PPC_MULTIPLATFORM | 627 | #ifdef CONFIG_PPC_MULTIPLATFORM |
636 | /* map in PCI I/O space */ | 628 | /* map in PCI I/O space */ |
637 | phbs_remap_io(); | 629 | phbs_remap_io(); |
638 | #endif | 630 | #endif |
639 | 631 | ||
640 | printk("PCI: Probing PCI hardware done\n"); | 632 | printk(KERN_DEBUG "PCI: Probing PCI hardware done\n"); |
641 | 633 | ||
642 | return 0; | 634 | return 0; |
643 | } | 635 | } |
@@ -804,7 +796,7 @@ static pgprot_t __pci_mmap_set_pgprot(struct pci_dev *dev, struct resource *rp, | |||
804 | else | 796 | else |
805 | prot |= _PAGE_GUARDED; | 797 | prot |= _PAGE_GUARDED; |
806 | 798 | ||
807 | printk("PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start, | 799 | printk(KERN_DEBUG "PCI map for %s:%lx, prot: %lx\n", pci_name(dev), rp->start, |
808 | prot); | 800 | prot); |
809 | 801 | ||
810 | return __pgprot(prot); | 802 | return __pgprot(prot); |
@@ -894,8 +886,8 @@ int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma, | |||
894 | return ret; | 886 | return ret; |
895 | } | 887 | } |
896 | 888 | ||
897 | #ifdef CONFIG_PPC_MULTIPLATFORM | 889 | 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) | 890 | struct device_attribute *attr, char *buf) |
899 | { | 891 | { |
900 | struct pci_dev *pdev; | 892 | struct pci_dev *pdev; |
901 | struct device_node *np; | 893 | struct device_node *np; |
@@ -907,13 +899,10 @@ static ssize_t pci_show_devspec(struct device *dev, struct device_attribute *att | |||
907 | return sprintf(buf, "%s", np->full_name); | 899 | return sprintf(buf, "%s", np->full_name); |
908 | } | 900 | } |
909 | static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); | 901 | static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); |
910 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
911 | 902 | ||
912 | void pcibios_add_platform_entries(struct pci_dev *pdev) | 903 | void pcibios_add_platform_entries(struct pci_dev *pdev) |
913 | { | 904 | { |
914 | #ifdef CONFIG_PPC_MULTIPLATFORM | ||
915 | device_create_file(&pdev->dev, &dev_attr_devspec); | 905 | device_create_file(&pdev->dev, &dev_attr_devspec); |
916 | #endif /* CONFIG_PPC_MULTIPLATFORM */ | ||
917 | } | 906 | } |
918 | 907 | ||
919 | #ifdef CONFIG_PPC_MULTIPLATFORM | 908 | #ifdef CONFIG_PPC_MULTIPLATFORM |
@@ -1104,8 +1093,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, | 1093 | pci_process_ISA_OF_ranges(isa_dn, hose->io_base_phys, |
1105 | hose->io_base_virt); | 1094 | hose->io_base_virt); |
1106 | of_node_put(isa_dn); | 1095 | of_node_put(isa_dn); |
1107 | /* Allow all IO */ | ||
1108 | io_page_mask = -1; | ||
1109 | } | 1096 | } |
1110 | } | 1097 | } |
1111 | 1098 | ||
@@ -1212,7 +1199,7 @@ int remap_bus_range(struct pci_bus *bus) | |||
1212 | return 1; | 1199 | return 1; |
1213 | if (start_phys == 0) | 1200 | if (start_phys == 0) |
1214 | return 1; | 1201 | return 1; |
1215 | printk("mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size); | 1202 | printk(KERN_DEBUG "mapping IO %lx -> %lx, size: %lx\n", start_phys, start_virt, size); |
1216 | if (__ioremap_explicit(start_phys, start_virt, size, | 1203 | if (__ioremap_explicit(start_phys, start_virt, size, |
1217 | _PAGE_NO_CACHE | _PAGE_GUARDED)) | 1204 | _PAGE_NO_CACHE | _PAGE_GUARDED)) |
1218 | return 1; | 1205 | return 1; |
@@ -1232,27 +1219,13 @@ static void phbs_remap_io(void) | |||
1232 | static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev) | 1219 | static void __devinit fixup_resource(struct resource *res, struct pci_dev *dev) |
1233 | { | 1220 | { |
1234 | struct pci_controller *hose = pci_bus_to_host(dev->bus); | 1221 | struct pci_controller *hose = pci_bus_to_host(dev->bus); |
1235 | unsigned long start, end, mask, offset; | 1222 | unsigned long offset; |
1236 | 1223 | ||
1237 | if (res->flags & IORESOURCE_IO) { | 1224 | if (res->flags & IORESOURCE_IO) { |
1238 | offset = (unsigned long)hose->io_base_virt - pci_io_base; | 1225 | offset = (unsigned long)hose->io_base_virt - pci_io_base; |
1239 | 1226 | ||
1240 | start = res->start += offset; | 1227 | res->start += offset; |
1241 | end = res->end += offset; | 1228 | 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) { | 1229 | } else if (res->flags & IORESOURCE_MEM) { |
1257 | res->start += hose->pci_mem_offset; | 1230 | res->start += hose->pci_mem_offset; |
1258 | res->end += hose->pci_mem_offset; | 1231 | res->end += hose->pci_mem_offset; |
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..7fb4cca021be 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"); |
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..969f4abcc0be 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 |
@@ -1070,6 +1107,7 @@ static int __init early_init_dt_scan_chosen(unsigned long node, | |||
1070 | iommu_force_on = 1; | 1107 | iommu_force_on = 1; |
1071 | #endif | 1108 | #endif |
1072 | 1109 | ||
1110 | /* mem=x on the command line is the preferred mechanism */ | ||
1073 | lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL); | 1111 | lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL); |
1074 | if (lprop) | 1112 | if (lprop) |
1075 | memory_limit = *lprop; | 1113 | memory_limit = *lprop; |
@@ -1123,17 +1161,6 @@ static int __init early_init_dt_scan_chosen(unsigned long node, | |||
1123 | 1161 | ||
1124 | DBG("Command line is: %s\n", cmd_line); | 1162 | DBG("Command line is: %s\n", cmd_line); |
1125 | 1163 | ||
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 */ | 1164 | /* break now */ |
1138 | return 1; | 1165 | return 1; |
1139 | } | 1166 | } |
@@ -1240,6 +1267,11 @@ static void __init early_reserve_mem(void) | |||
1240 | 1267 | ||
1241 | reserve_map = (u64 *)(((unsigned long)initial_boot_params) + | 1268 | reserve_map = (u64 *)(((unsigned long)initial_boot_params) + |
1242 | initial_boot_params->off_mem_rsvmap); | 1269 | initial_boot_params->off_mem_rsvmap); |
1270 | |||
1271 | /* before we do anything, lets reserve the dt blob */ | ||
1272 | lmb_reserve(__pa((unsigned long)initial_boot_params), | ||
1273 | initial_boot_params->totalsize); | ||
1274 | |||
1243 | #ifdef CONFIG_PPC32 | 1275 | #ifdef CONFIG_PPC32 |
1244 | /* | 1276 | /* |
1245 | * Handle the case where we might be booting from an old kexec | 1277 | * Handle the case where we might be booting from an old kexec |
@@ -1292,18 +1324,26 @@ void __init early_init_devtree(void *params) | |||
1292 | lmb_init(); | 1324 | lmb_init(); |
1293 | of_scan_flat_dt(early_init_dt_scan_root, NULL); | 1325 | of_scan_flat_dt(early_init_dt_scan_root, NULL); |
1294 | of_scan_flat_dt(early_init_dt_scan_memory, NULL); | 1326 | of_scan_flat_dt(early_init_dt_scan_memory, NULL); |
1295 | lmb_enforce_memory_limit(memory_limit); | ||
1296 | lmb_analyze(); | ||
1297 | 1327 | ||
1298 | DBG("Phys. mem: %lx\n", lmb_phys_mem_size()); | 1328 | /* Save command line for /proc/cmdline and then parse parameters */ |
1329 | strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE); | ||
1330 | parse_early_param(); | ||
1299 | 1331 | ||
1300 | /* Reserve LMB regions used by kernel, initrd, dt, etc... */ | 1332 | /* Reserve LMB regions used by kernel, initrd, dt, etc... */ |
1301 | lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START); | 1333 | lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START); |
1302 | #ifdef CONFIG_CRASH_DUMP | 1334 | reserve_kdump_trampoline(); |
1303 | lmb_reserve(0, KDUMP_RESERVE_LIMIT); | 1335 | reserve_crashkernel(); |
1304 | #endif | ||
1305 | early_reserve_mem(); | 1336 | early_reserve_mem(); |
1306 | 1337 | ||
1338 | lmb_enforce_memory_limit(memory_limit); | ||
1339 | lmb_analyze(); | ||
1340 | |||
1341 | DBG("Phys. mem: %lx\n", lmb_phys_mem_size()); | ||
1342 | |||
1343 | /* We may need to relocate the flat tree, do it now. | ||
1344 | * FIXME .. and the initrd too? */ | ||
1345 | move_device_tree(); | ||
1346 | |||
1307 | DBG("Scanning CPUs ...\n"); | 1347 | DBG("Scanning CPUs ...\n"); |
1308 | 1348 | ||
1309 | /* Retreive CPU related informations from the flat tree | 1349 | /* Retreive CPU related informations from the flat tree |
@@ -2053,29 +2093,3 @@ int prom_update_property(struct device_node *np, | |||
2053 | return 0; | 2093 | return 0; |
2054 | } | 2094 | } |
2055 | 2095 | ||
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 | |||
2070 | new = (struct boot_param_header*) | ||
2071 | __va(lmb_alloc(initial_boot_params->totalsize, PAGE_SIZE)); | ||
2072 | |||
2073 | memcpy(new, initial_boot_params, initial_boot_params->totalsize); | ||
2074 | |||
2075 | initial_boot_params = new; | ||
2076 | |||
2077 | DBG("Flat device tree blob moved to %p\n", initial_boot_params); | ||
2078 | |||
2079 | /* XXX should we unreserve the old DT? */ | ||
2080 | } | ||
2081 | #endif /* CONFIG_KEXEC */ | ||
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index f70bd090dacd..57d8a16438a0 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 | ||
@@ -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..13496f319855 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; |
@@ -789,7 +774,7 @@ EXPORT_SYMBOL(rtas_token); | |||
789 | EXPORT_SYMBOL(rtas_call); | 774 | EXPORT_SYMBOL(rtas_call); |
790 | EXPORT_SYMBOL(rtas_data_buf); | 775 | EXPORT_SYMBOL(rtas_data_buf); |
791 | EXPORT_SYMBOL(rtas_data_buf_lock); | 776 | EXPORT_SYMBOL(rtas_data_buf_lock); |
792 | EXPORT_SYMBOL(rtas_extended_busy_delay_time); | 777 | EXPORT_SYMBOL(rtas_busy_delay_time); |
793 | EXPORT_SYMBOL(rtas_get_sensor); | 778 | EXPORT_SYMBOL(rtas_get_sensor); |
794 | EXPORT_SYMBOL(rtas_get_power_level); | 779 | EXPORT_SYMBOL(rtas_get_power_level); |
795 | EXPORT_SYMBOL(rtas_set_power_level); | 780 | 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/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/time.c b/arch/powerpc/kernel/time.c index 24e3ad756de0..528e7f84cb67 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; |
@@ -945,9 +944,9 @@ void __init time_init(void) | |||
945 | } else { | 944 | } else { |
946 | /* Normal PowerPC with timebase register */ | 945 | /* Normal PowerPC with timebase register */ |
947 | ppc_md.calibrate_decr(); | 946 | ppc_md.calibrate_decr(); |
948 | printk(KERN_INFO "time_init: decrementer frequency = %lu.%.6lu MHz\n", | 947 | printk(KERN_DEBUG "time_init: decrementer frequency = %lu.%.6lu MHz\n", |
949 | ppc_tb_freq / 1000000, ppc_tb_freq % 1000000); | 948 | ppc_tb_freq / 1000000, ppc_tb_freq % 1000000); |
950 | printk(KERN_INFO "time_init: processor frequency = %lu.%.6lu MHz\n", | 949 | printk(KERN_DEBUG "time_init: processor frequency = %lu.%.6lu MHz\n", |
951 | ppc_proc_freq / 1000000, ppc_proc_freq % 1000000); | 950 | ppc_proc_freq / 1000000, ppc_proc_freq % 1000000); |
952 | tb_last_stamp = tb_last_jiffy = get_tb(); | 951 | tb_last_stamp = tb_last_jiffy = get_tb(); |
953 | } | 952 | } |
@@ -1010,10 +1009,7 @@ void __init time_init(void) | |||
1010 | tb_to_ns_scale = scale; | 1009 | tb_to_ns_scale = scale; |
1011 | tb_to_ns_shift = shift; | 1010 | tb_to_ns_shift = shift; |
1012 | 1011 | ||
1013 | #ifdef CONFIG_PPC_ISERIES | 1012 | tm = get_boot_time(); |
1014 | if (!piranha_simulator) | ||
1015 | #endif | ||
1016 | tm = get_boot_time(); | ||
1017 | 1013 | ||
1018 | write_seqlock_irqsave(&xtime_lock, flags); | 1014 | write_seqlock_irqsave(&xtime_lock, flags); |
1019 | 1015 | ||
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/vio.c b/arch/powerpc/kernel/vio.c index 971020cf3f7d..e746686d48b8 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)) | ||
64 | printk("Virtual Bus VETH TCE table failed.\n"); | ||
65 | if (!iommu_init_table(&vio_iommu_table)) | ||
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); | ||
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); |