diff options
| -rw-r--r-- | arch/powerpc/kernel/prom_init.c | 111 |
1 files changed, 107 insertions, 4 deletions
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index 7e4d54821a07..00ad7f981a0d 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
| @@ -636,10 +636,95 @@ static void __init early_cmdline_parse(void) | |||
| 636 | 636 | ||
| 637 | #ifdef CONFIG_PPC_PSERIES | 637 | #ifdef CONFIG_PPC_PSERIES |
| 638 | /* | 638 | /* |
| 639 | * To tell the firmware what our capabilities are, we have to pass | 639 | * There are two methods for telling firmware what our capabilities are. |
| 640 | * it a fake 32-bit ELF header containing a couple of PT_NOTE sections | 640 | * Newer machines have an "ibm,client-architecture-support" method on the |
| 641 | * that contain structures that contain the actual values. | 641 | * root node. For older machines, we have to call the "process-elf-header" |
| 642 | * method in the /packages/elf-loader node, passing it a fake 32-bit | ||
| 643 | * ELF header containing a couple of PT_NOTE sections that contain | ||
| 644 | * structures that contain various information. | ||
| 642 | */ | 645 | */ |
| 646 | |||
| 647 | /* | ||
| 648 | * New method - extensible architecture description vector. | ||
| 649 | * | ||
| 650 | * Because the description vector contains a mix of byte and word | ||
| 651 | * values, we declare it as an unsigned char array, and use this | ||
| 652 | * macro to put word values in. | ||
| 653 | */ | ||
| 654 | #define W(x) ((x) >> 24) & 0xff, ((x) >> 16) & 0xff, \ | ||
| 655 | ((x) >> 8) & 0xff, (x) & 0xff | ||
| 656 | |||
| 657 | /* Option vector bits - generic bits in byte 1 */ | ||
| 658 | #define OV_IGNORE 0x80 /* ignore this vector */ | ||
| 659 | #define OV_CESSATION_POLICY 0x40 /* halt if unsupported option present*/ | ||
| 660 | |||
| 661 | /* Option vector 1: processor architectures supported */ | ||
| 662 | #define OV1_PPC_2_00 0x80 /* set if we support PowerPC 2.00 */ | ||
| 663 | #define OV1_PPC_2_01 0x40 /* set if we support PowerPC 2.01 */ | ||
| 664 | #define OV1_PPC_2_02 0x20 /* set if we support PowerPC 2.02 */ | ||
| 665 | #define OV1_PPC_2_03 0x10 /* set if we support PowerPC 2.03 */ | ||
| 666 | #define OV1_PPC_2_04 0x08 /* set if we support PowerPC 2.04 */ | ||
| 667 | #define OV1_PPC_2_05 0x04 /* set if we support PowerPC 2.05 */ | ||
| 668 | |||
| 669 | /* Option vector 2: Open Firmware options supported */ | ||
| 670 | #define OV2_REAL_MODE 0x20 /* set if we want OF in real mode */ | ||
| 671 | |||
| 672 | /* Option vector 3: processor options supported */ | ||
| 673 | #define OV3_FP 0x80 /* floating point */ | ||
| 674 | #define OV3_VMX 0x40 /* VMX/Altivec */ | ||
| 675 | |||
| 676 | /* Option vector 5: PAPR/OF options supported */ | ||
| 677 | #define OV5_LPAR 0x80 /* logical partitioning supported */ | ||
| 678 | #define OV5_SPLPAR 0x40 /* shared-processor LPAR supported */ | ||
| 679 | /* ibm,dynamic-reconfiguration-memory property supported */ | ||
| 680 | #define OV5_DRCONF_MEMORY 0x20 | ||
| 681 | #define OV5_LARGE_PAGES 0x10 /* large pages supported */ | ||
| 682 | |||
| 683 | /* | ||
| 684 | * The architecture vector has an array of PVR mask/value pairs, | ||
| 685 | * followed by # option vectors - 1, followed by the option vectors. | ||
| 686 | */ | ||
| 687 | static unsigned char ibm_architecture_vec[] = { | ||
| 688 | W(0xfffe0000), W(0x003a0000), /* POWER5/POWER5+ */ | ||
| 689 | W(0xfffffffe), W(0x0f000001), /* all 2.04-compliant and earlier */ | ||
| 690 | 5 - 1, /* 5 option vectors */ | ||
| 691 | |||
| 692 | /* option vector 1: processor architectures supported */ | ||
| 693 | 3 - 1, /* length */ | ||
| 694 | 0, /* don't ignore, don't halt */ | ||
| 695 | OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 | | ||
| 696 | OV1_PPC_2_04 | OV1_PPC_2_05, | ||
| 697 | |||
| 698 | /* option vector 2: Open Firmware options supported */ | ||
| 699 | 34 - 1, /* length */ | ||
| 700 | OV2_REAL_MODE, | ||
| 701 | 0, 0, | ||
| 702 | W(0xffffffff), /* real_base */ | ||
| 703 | W(0xffffffff), /* real_size */ | ||
| 704 | W(0xffffffff), /* virt_base */ | ||
| 705 | W(0xffffffff), /* virt_size */ | ||
| 706 | W(0xffffffff), /* load_base */ | ||
| 707 | W(64), /* 128MB min RMA */ | ||
| 708 | W(0xffffffff), /* full client load */ | ||
| 709 | 0, /* min RMA percentage of total RAM */ | ||
| 710 | 48, /* max log_2(hash table size) */ | ||
| 711 | |||
| 712 | /* option vector 3: processor options supported */ | ||
| 713 | 3 - 1, /* length */ | ||
| 714 | 0, /* don't ignore, don't halt */ | ||
| 715 | OV3_FP | OV3_VMX, | ||
| 716 | |||
| 717 | /* option vector 4: IBM PAPR implementation */ | ||
| 718 | 2 - 1, /* length */ | ||
| 719 | 0, /* don't halt */ | ||
| 720 | |||
| 721 | /* option vector 5: PAPR/OF options */ | ||
| 722 | 3 - 1, /* length */ | ||
| 723 | 0, /* don't ignore, don't halt */ | ||
| 724 | OV5_LPAR | OV5_SPLPAR | OV5_LARGE_PAGES, | ||
| 725 | }; | ||
| 726 | |||
| 727 | /* Old method - ELF header with PT_NOTE sections */ | ||
| 643 | static struct fake_elf { | 728 | static struct fake_elf { |
| 644 | Elf32_Ehdr elfhdr; | 729 | Elf32_Ehdr elfhdr; |
| 645 | Elf32_Phdr phdr[2]; | 730 | Elf32_Phdr phdr[2]; |
| @@ -728,8 +813,26 @@ static struct fake_elf { | |||
| 728 | 813 | ||
| 729 | static void __init prom_send_capabilities(void) | 814 | static void __init prom_send_capabilities(void) |
| 730 | { | 815 | { |
| 731 | ihandle elfloader; | 816 | ihandle elfloader, root; |
| 817 | prom_arg_t ret; | ||
| 818 | |||
| 819 | root = call_prom("open", 1, 1, ADDR("/")); | ||
| 820 | if (root != 0) { | ||
| 821 | /* try calling the ibm,client-architecture-support method */ | ||
| 822 | if (call_prom_ret("call-method", 3, 2, &ret, | ||
| 823 | ADDR("ibm,client-architecture-support"), | ||
| 824 | ADDR(ibm_architecture_vec)) == 0) { | ||
| 825 | /* the call exists... */ | ||
| 826 | if (ret) | ||
| 827 | prom_printf("WARNING: ibm,client-architecture" | ||
| 828 | "-support call FAILED!\n"); | ||
| 829 | call_prom("close", 1, 0, root); | ||
| 830 | return; | ||
| 831 | } | ||
| 832 | call_prom("close", 1, 0, root); | ||
| 833 | } | ||
| 732 | 834 | ||
| 835 | /* no ibm,client-architecture-support call, try the old way */ | ||
| 733 | elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader")); | 836 | elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader")); |
| 734 | if (elfloader == 0) { | 837 | if (elfloader == 0) { |
| 735 | prom_printf("couldn't open /packages/elf-loader\n"); | 838 | prom_printf("couldn't open /packages/elf-loader\n"); |
