aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/prom_init.c
diff options
context:
space:
mode:
authorMichael Ellerman <mpe@ellerman.id.au>2016-11-18 07:15:42 -0500
committerMichael Ellerman <mpe@ellerman.id.au>2016-11-30 07:19:59 -0500
commit76ffb5785047b3924da20969eb3f658b363c20f0 (patch)
tree73fa1528e64b0145725dc00e4b75f300bb8f7689 /arch/powerpc/kernel/prom_init.c
parentd03d1d65b5570ab6fba462a09c2b3274dca80ba9 (diff)
powerpc/prom: Switch to using structs for ibm_architecture_vec
Now that we've defined structures to describe each of the client architecture vectors, we can use those to construct the value we pass to firmware. This avoids the tricks we previously played with the W() macro, allows us to properly endian annotate fields, and should help to avoid bugs introduced by failing to have the correct number of zero pad bytes between fields. It also means we can avoid hard coding IBM_ARCH_VEC_NRCORES_OFFSET in order to update the max_cpus value and instead just set it. Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc/kernel/prom_init.c')
-rw-r--r--arch/powerpc/kernel/prom_init.c274
1 files changed, 154 insertions, 120 deletions
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index e41c0b6637ab..ec47a939cbdd 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -635,13 +635,7 @@ static void __init early_cmdline_parse(void)
635 * 635 *
636 * See prom.h for the definition of the bits specified in the 636 * See prom.h for the definition of the bits specified in the
637 * architecture vector. 637 * architecture vector.
638 *
639 * Because the description vector contains a mix of byte and word
640 * values, we declare it as an unsigned char array, and use this
641 * macro to put word values in.
642 */ 638 */
643#define W(x) ((x) >> 24) & 0xff, ((x) >> 16) & 0xff, \
644 ((x) >> 8) & 0xff, (x) & 0xff
645 639
646/* Firmware expects the value to be n - 1, where n is the # of vectors */ 640/* Firmware expects the value to be n - 1, where n is the # of vectors */
647#define NUM_VECTORS(n) ((n) - 1) 641#define NUM_VECTORS(n) ((n) - 1)
@@ -652,94 +646,6 @@ static void __init early_cmdline_parse(void)
652 */ 646 */
653#define VECTOR_LENGTH(n) (1 + (n) - 2) 647#define VECTOR_LENGTH(n) (1 + (n) - 2)
654 648
655unsigned char ibm_architecture_vec[] = {
656 W(0xfffe0000), W(0x003a0000), /* POWER5/POWER5+ */
657 W(0xffff0000), W(0x003e0000), /* POWER6 */
658 W(0xffff0000), W(0x003f0000), /* POWER7 */
659 W(0xffff0000), W(0x004b0000), /* POWER8E */
660 W(0xffff0000), W(0x004c0000), /* POWER8NVL */
661 W(0xffff0000), W(0x004d0000), /* POWER8 */
662 W(0xffffffff), W(0x0f000004), /* all 2.07-compliant */
663 W(0xffffffff), W(0x0f000003), /* all 2.06-compliant */
664 W(0xffffffff), W(0x0f000002), /* all 2.05-compliant */
665 W(0xfffffffe), W(0x0f000001), /* all 2.04-compliant and earlier */
666 NUM_VECTORS(6), /* 6 option vectors */
667
668 /* option vector 1: processor architectures supported */
669 VECTOR_LENGTH(2), /* length */
670 0, /* don't ignore, don't halt */
671 OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
672 OV1_PPC_2_04 | OV1_PPC_2_05 | OV1_PPC_2_06 | OV1_PPC_2_07,
673
674 /* option vector 2: Open Firmware options supported */
675 VECTOR_LENGTH(33), /* length */
676 OV2_REAL_MODE,
677 0, 0,
678 W(0xffffffff), /* real_base */
679 W(0xffffffff), /* real_size */
680 W(0xffffffff), /* virt_base */
681 W(0xffffffff), /* virt_size */
682 W(0xffffffff), /* load_base */
683 W(256), /* 256MB min RMA */
684 W(0xffffffff), /* full client load */
685 0, /* min RMA percentage of total RAM */
686 48, /* max log_2(hash table size) */
687
688 /* option vector 3: processor options supported */
689 VECTOR_LENGTH(2), /* length */
690 0, /* don't ignore, don't halt */
691 OV3_FP | OV3_VMX | OV3_DFP,
692
693 /* option vector 4: IBM PAPR implementation */
694 VECTOR_LENGTH(2), /* length */
695 0, /* don't halt */
696 OV4_MIN_ENT_CAP, /* minimum VP entitled capacity */
697
698 /* option vector 5: PAPR/OF options */
699 VECTOR_LENGTH(21), /* length */
700 0, /* don't ignore, don't halt */
701 OV5_FEAT(OV5_LPAR) | OV5_FEAT(OV5_SPLPAR) | OV5_FEAT(OV5_LARGE_PAGES) |
702 OV5_FEAT(OV5_DRCONF_MEMORY) | OV5_FEAT(OV5_DONATE_DEDICATE_CPU) |
703#ifdef CONFIG_PCI_MSI
704 /* PCIe/MSI support. Without MSI full PCIe is not supported */
705 OV5_FEAT(OV5_MSI),
706#else
707 0,
708#endif
709 0,
710#ifdef CONFIG_PPC_SMLPAR
711 OV5_FEAT(OV5_CMO) | OV5_FEAT(OV5_XCMO),
712#else
713 0,
714#endif
715 OV5_FEAT(OV5_TYPE1_AFFINITY) | OV5_FEAT(OV5_PRRN),
716 0,
717 0,
718 0,
719 /* WARNING: The offset of the "number of cores" field below
720 * must match by the macro below. Update the definition if
721 * the structure layout changes.
722 */
723#define IBM_ARCH_VEC_NRCORES_OFFSET 133
724 W(NR_CPUS), /* number of cores supported */
725 0,
726 0,
727 0,
728 0,
729 OV5_FEAT(OV5_PFO_HW_RNG) | OV5_FEAT(OV5_PFO_HW_ENCR) |
730 OV5_FEAT(OV5_PFO_HW_842), /* Byte 17 */
731 0, /* Byte 18 */
732 0, /* Byte 19 */
733 0, /* Byte 20 */
734 OV5_FEAT(OV5_SUB_PROCESSORS), /* Byte 21 */
735
736 /* option vector 6: IBM PAPR hints */
737 VECTOR_LENGTH(3), /* length */
738 0,
739 0,
740 OV6_LINUX,
741};
742
743struct option_vector1 { 649struct option_vector1 {
744 u8 byte1; 650 u8 byte1;
745 u8 arch_versions; 651 u8 arch_versions;
@@ -793,6 +699,154 @@ struct option_vector6 {
793 u8 os_name; 699 u8 os_name;
794} __packed; 700} __packed;
795 701
702struct ibm_arch_vec {
703 struct { u32 mask, val; } pvrs[10];
704
705 u8 num_vectors;
706
707 u8 vec1_len;
708 struct option_vector1 vec1;
709
710 u8 vec2_len;
711 struct option_vector2 vec2;
712
713 u8 vec3_len;
714 struct option_vector3 vec3;
715
716 u8 vec4_len;
717 struct option_vector4 vec4;
718
719 u8 vec5_len;
720 struct option_vector5 vec5;
721
722 u8 vec6_len;
723 struct option_vector6 vec6;
724} __packed;
725
726struct ibm_arch_vec __cacheline_aligned ibm_architecture_vec = {
727 .pvrs = {
728 {
729 .mask = cpu_to_be32(0xfffe0000), /* POWER5/POWER5+ */
730 .val = cpu_to_be32(0x003a0000),
731 },
732 {
733 .mask = cpu_to_be32(0xffff0000), /* POWER6 */
734 .val = cpu_to_be32(0x003e0000),
735 },
736 {
737 .mask = cpu_to_be32(0xffff0000), /* POWER7 */
738 .val = cpu_to_be32(0x003f0000),
739 },
740 {
741 .mask = cpu_to_be32(0xffff0000), /* POWER8E */
742 .val = cpu_to_be32(0x004b0000),
743 },
744 {
745 .mask = cpu_to_be32(0xffff0000), /* POWER8NVL */
746 .val = cpu_to_be32(0x004c0000),
747 },
748 {
749 .mask = cpu_to_be32(0xffff0000), /* POWER8 */
750 .val = cpu_to_be32(0x004d0000),
751 },
752 {
753 .mask = cpu_to_be32(0xffffffff), /* all 2.07-compliant */
754 .val = cpu_to_be32(0x0f000004),
755 },
756 {
757 .mask = cpu_to_be32(0xffffffff), /* all 2.06-compliant */
758 .val = cpu_to_be32(0x0f000003),
759 },
760 {
761 .mask = cpu_to_be32(0xffffffff), /* all 2.05-compliant */
762 .val = cpu_to_be32(0x0f000002),
763 },
764 {
765 .mask = cpu_to_be32(0xfffffffe), /* all 2.04-compliant and earlier */
766 .val = cpu_to_be32(0x0f000001),
767 },
768 },
769
770 .num_vectors = NUM_VECTORS(6),
771
772 .vec1_len = VECTOR_LENGTH(sizeof(struct option_vector1)),
773 .vec1 = {
774 .byte1 = 0,
775 .arch_versions = OV1_PPC_2_00 | OV1_PPC_2_01 | OV1_PPC_2_02 | OV1_PPC_2_03 |
776 OV1_PPC_2_04 | OV1_PPC_2_05 | OV1_PPC_2_06 | OV1_PPC_2_07,
777 },
778
779 .vec2_len = VECTOR_LENGTH(sizeof(struct option_vector2)),
780 /* option vector 2: Open Firmware options supported */
781 .vec2 = {
782 .byte1 = OV2_REAL_MODE,
783 .reserved = 0,
784 .real_base = cpu_to_be32(0xffffffff),
785 .real_size = cpu_to_be32(0xffffffff),
786 .virt_base = cpu_to_be32(0xffffffff),
787 .virt_size = cpu_to_be32(0xffffffff),
788 .load_base = cpu_to_be32(0xffffffff),
789 .min_rma = cpu_to_be32(256), /* 256MB min RMA */
790 .min_load = cpu_to_be32(0xffffffff), /* full client load */
791 .min_rma_percent = 0, /* min RMA percentage of total RAM */
792 .max_pft_size = 48, /* max log_2(hash table size) */
793 },
794
795 .vec3_len = VECTOR_LENGTH(sizeof(struct option_vector3)),
796 /* option vector 3: processor options supported */
797 .vec3 = {
798 .byte1 = 0, /* don't ignore, don't halt */
799 .byte2 = OV3_FP | OV3_VMX | OV3_DFP,
800 },
801
802 .vec4_len = VECTOR_LENGTH(sizeof(struct option_vector4)),
803 /* option vector 4: IBM PAPR implementation */
804 .vec4 = {
805 .byte1 = 0, /* don't halt */
806 .min_vp_cap = OV4_MIN_ENT_CAP, /* minimum VP entitled capacity */
807 },
808
809 .vec5_len = VECTOR_LENGTH(sizeof(struct option_vector5)),
810 /* option vector 5: PAPR/OF options */
811 .vec5 = {
812 .byte1 = 0, /* don't ignore, don't halt */
813 .byte2 = OV5_FEAT(OV5_LPAR) | OV5_FEAT(OV5_SPLPAR) | OV5_FEAT(OV5_LARGE_PAGES) |
814 OV5_FEAT(OV5_DRCONF_MEMORY) | OV5_FEAT(OV5_DONATE_DEDICATE_CPU) |
815#ifdef CONFIG_PCI_MSI
816 /* PCIe/MSI support. Without MSI full PCIe is not supported */
817 OV5_FEAT(OV5_MSI),
818#else
819 0,
820#endif
821 .byte3 = 0,
822 .cmo =
823#ifdef CONFIG_PPC_SMLPAR
824 OV5_FEAT(OV5_CMO) | OV5_FEAT(OV5_XCMO),
825#else
826 0,
827#endif
828 .associativity = OV5_FEAT(OV5_TYPE1_AFFINITY) | OV5_FEAT(OV5_PRRN),
829 .bin_opts = 0,
830 .micro_checkpoint = 0,
831 .reserved0 = 0,
832 .max_cpus = cpu_to_be32(NR_CPUS), /* number of cores supported */
833 .papr_level = 0,
834 .reserved1 = 0,
835 .platform_facilities = OV5_FEAT(OV5_PFO_HW_RNG) | OV5_FEAT(OV5_PFO_HW_ENCR) | OV5_FEAT(OV5_PFO_HW_842),
836 .reserved2 = 0,
837 .reserved3 = 0,
838 .subprocessors = 1,
839 },
840
841 /* option vector 6: IBM PAPR hints */
842 .vec6_len = VECTOR_LENGTH(sizeof(struct option_vector6)),
843 .vec6 = {
844 .reserved = 0,
845 .secondary_pteg = 0,
846 .os_name = OV6_LINUX,
847 },
848};
849
796/* Old method - ELF header with PT_NOTE sections only works on BE */ 850/* Old method - ELF header with PT_NOTE sections only works on BE */
797#ifdef __BIG_ENDIAN__ 851#ifdef __BIG_ENDIAN__
798static struct fake_elf { 852static struct fake_elf {
@@ -926,7 +980,6 @@ static void __init prom_send_capabilities(void)
926 ihandle root; 980 ihandle root;
927 prom_arg_t ret; 981 prom_arg_t ret;
928 u32 cores; 982 u32 cores;
929 unsigned char *ptcores;
930 983
931 root = call_prom("open", 1, 1, ADDR("/")); 984 root = call_prom("open", 1, 1, ADDR("/"));
932 if (root != 0) { 985 if (root != 0) {
@@ -937,37 +990,18 @@ static void __init prom_send_capabilities(void)
937 * divide NR_CPUS. 990 * divide NR_CPUS.
938 */ 991 */
939 992
940 /* The core value may start at an odd address. If such a word 993 cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads());
941 * access is made at a cache line boundary, this leads to an 994 prom_printf("Max number of cores passed to firmware: %lu (NR_CPUS = %lu)\n",
942 * exception which may not be handled at this time. 995 cores, NR_CPUS);
943 * Forcing a per byte access to avoid exception. 996
944 */ 997 ibm_architecture_vec.vec5.max_cpus = cpu_to_be32(cores);
945 ptcores = &ibm_architecture_vec[IBM_ARCH_VEC_NRCORES_OFFSET];
946 cores = 0;
947 cores |= ptcores[0] << 24;
948 cores |= ptcores[1] << 16;
949 cores |= ptcores[2] << 8;
950 cores |= ptcores[3];
951 if (cores != NR_CPUS) {
952 prom_printf("WARNING ! "
953 "ibm_architecture_vec structure inconsistent: %lu!\n",
954 cores);
955 } else {
956 cores = DIV_ROUND_UP(NR_CPUS, prom_count_smt_threads());
957 prom_printf("Max number of cores passed to firmware: %lu (NR_CPUS = %lu)\n",
958 cores, NR_CPUS);
959 ptcores[0] = (cores >> 24) & 0xff;
960 ptcores[1] = (cores >> 16) & 0xff;
961 ptcores[2] = (cores >> 8) & 0xff;
962 ptcores[3] = cores & 0xff;
963 }
964 998
965 /* try calling the ibm,client-architecture-support method */ 999 /* try calling the ibm,client-architecture-support method */
966 prom_printf("Calling ibm,client-architecture-support..."); 1000 prom_printf("Calling ibm,client-architecture-support...");
967 if (call_prom_ret("call-method", 3, 2, &ret, 1001 if (call_prom_ret("call-method", 3, 2, &ret,
968 ADDR("ibm,client-architecture-support"), 1002 ADDR("ibm,client-architecture-support"),
969 root, 1003 root,
970 ADDR(ibm_architecture_vec)) == 0) { 1004 ADDR(&ibm_architecture_vec)) == 0) {
971 /* the call exists... */ 1005 /* the call exists... */
972 if (ret) 1006 if (ret)
973 prom_printf("\nWARNING: ibm,client-architecture" 1007 prom_printf("\nWARNING: ibm,client-architecture"