diff options
Diffstat (limited to 'arch/powerpc/kernel/prom_init.c')
-rw-r--r-- | arch/powerpc/kernel/prom_init.c | 120 |
1 files changed, 113 insertions, 7 deletions
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c index a3944540fe0d..1c1b44ec7642 100644 --- a/arch/powerpc/kernel/prom_init.c +++ b/arch/powerpc/kernel/prom_init.c | |||
@@ -168,6 +168,14 @@ static unsigned long __initdata prom_tce_alloc_start; | |||
168 | static unsigned long __initdata prom_tce_alloc_end; | 168 | static unsigned long __initdata prom_tce_alloc_end; |
169 | #endif | 169 | #endif |
170 | 170 | ||
171 | static bool __initdata prom_radix_disable; | ||
172 | |||
173 | struct platform_support { | ||
174 | bool hash_mmu; | ||
175 | bool radix_mmu; | ||
176 | bool radix_gtse; | ||
177 | }; | ||
178 | |||
171 | /* Platforms codes are now obsolete in the kernel. Now only used within this | 179 | /* Platforms codes are now obsolete in the kernel. Now only used within this |
172 | * file and ultimately gone too. Feel free to change them if you need, they | 180 | * file and ultimately gone too. Feel free to change them if you need, they |
173 | * are not shared with anything outside of this file anymore | 181 | * are not shared with anything outside of this file anymore |
@@ -626,6 +634,12 @@ static void __init early_cmdline_parse(void) | |||
626 | prom_memory_limit = ALIGN(prom_memory_limit, 0x1000000); | 634 | prom_memory_limit = ALIGN(prom_memory_limit, 0x1000000); |
627 | #endif | 635 | #endif |
628 | } | 636 | } |
637 | |||
638 | opt = strstr(prom_cmd_line, "disable_radix"); | ||
639 | if (opt) { | ||
640 | prom_debug("Radix disabled from cmdline\n"); | ||
641 | prom_radix_disable = true; | ||
642 | } | ||
629 | } | 643 | } |
630 | 644 | ||
631 | #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) | 645 | #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) |
@@ -695,6 +709,8 @@ struct option_vector5 { | |||
695 | u8 byte22; | 709 | u8 byte22; |
696 | u8 intarch; | 710 | u8 intarch; |
697 | u8 mmu; | 711 | u8 mmu; |
712 | u8 hash_ext; | ||
713 | u8 radix_ext; | ||
698 | } __packed; | 714 | } __packed; |
699 | 715 | ||
700 | struct option_vector6 { | 716 | struct option_vector6 { |
@@ -850,8 +866,9 @@ struct ibm_arch_vec __cacheline_aligned ibm_architecture_vec = { | |||
850 | .reserved3 = 0, | 866 | .reserved3 = 0, |
851 | .subprocessors = 1, | 867 | .subprocessors = 1, |
852 | .intarch = 0, | 868 | .intarch = 0, |
853 | .mmu = OV5_FEAT(OV5_MMU_RADIX_300) | OV5_FEAT(OV5_MMU_HASH_300) | | 869 | .mmu = 0, |
854 | OV5_FEAT(OV5_MMU_PROC_TBL) | OV5_FEAT(OV5_MMU_GTSE), | 870 | .hash_ext = 0, |
871 | .radix_ext = 0, | ||
855 | }, | 872 | }, |
856 | 873 | ||
857 | /* option vector 6: IBM PAPR hints */ | 874 | /* option vector 6: IBM PAPR hints */ |
@@ -990,6 +1007,92 @@ static int __init prom_count_smt_threads(void) | |||
990 | 1007 | ||
991 | } | 1008 | } |
992 | 1009 | ||
1010 | static void __init prom_parse_mmu_model(u8 val, | ||
1011 | struct platform_support *support) | ||
1012 | { | ||
1013 | switch (val) { | ||
1014 | case OV5_FEAT(OV5_MMU_DYNAMIC): | ||
1015 | case OV5_FEAT(OV5_MMU_EITHER): /* Either Available */ | ||
1016 | prom_debug("MMU - either supported\n"); | ||
1017 | support->radix_mmu = !prom_radix_disable; | ||
1018 | support->hash_mmu = true; | ||
1019 | break; | ||
1020 | case OV5_FEAT(OV5_MMU_RADIX): /* Only Radix */ | ||
1021 | prom_debug("MMU - radix only\n"); | ||
1022 | if (prom_radix_disable) { | ||
1023 | /* | ||
1024 | * If we __have__ to do radix, we're better off ignoring | ||
1025 | * the command line rather than not booting. | ||
1026 | */ | ||
1027 | prom_printf("WARNING: Ignoring cmdline option disable_radix\n"); | ||
1028 | } | ||
1029 | support->radix_mmu = true; | ||
1030 | break; | ||
1031 | case OV5_FEAT(OV5_MMU_HASH): | ||
1032 | prom_debug("MMU - hash only\n"); | ||
1033 | support->hash_mmu = true; | ||
1034 | break; | ||
1035 | default: | ||
1036 | prom_debug("Unknown mmu support option: 0x%x\n", val); | ||
1037 | break; | ||
1038 | } | ||
1039 | } | ||
1040 | |||
1041 | static void __init prom_parse_platform_support(u8 index, u8 val, | ||
1042 | struct platform_support *support) | ||
1043 | { | ||
1044 | switch (index) { | ||
1045 | case OV5_INDX(OV5_MMU_SUPPORT): /* MMU Model */ | ||
1046 | prom_parse_mmu_model(val & OV5_FEAT(OV5_MMU_SUPPORT), support); | ||
1047 | break; | ||
1048 | case OV5_INDX(OV5_RADIX_GTSE): /* Radix Extensions */ | ||
1049 | if (val & OV5_FEAT(OV5_RADIX_GTSE)) { | ||
1050 | prom_debug("Radix - GTSE supported\n"); | ||
1051 | support->radix_gtse = true; | ||
1052 | } | ||
1053 | break; | ||
1054 | } | ||
1055 | } | ||
1056 | |||
1057 | static void __init prom_check_platform_support(void) | ||
1058 | { | ||
1059 | struct platform_support supported = { | ||
1060 | .hash_mmu = false, | ||
1061 | .radix_mmu = false, | ||
1062 | .radix_gtse = false | ||
1063 | }; | ||
1064 | int prop_len = prom_getproplen(prom.chosen, | ||
1065 | "ibm,arch-vec-5-platform-support"); | ||
1066 | if (prop_len > 1) { | ||
1067 | int i; | ||
1068 | u8 vec[prop_len]; | ||
1069 | prom_debug("Found ibm,arch-vec-5-platform-support, len: %d\n", | ||
1070 | prop_len); | ||
1071 | prom_getprop(prom.chosen, "ibm,arch-vec-5-platform-support", | ||
1072 | &vec, sizeof(vec)); | ||
1073 | for (i = 0; i < prop_len; i += 2) { | ||
1074 | prom_debug("%d: index = 0x%x val = 0x%x\n", i / 2 | ||
1075 | , vec[i] | ||
1076 | , vec[i + 1]); | ||
1077 | prom_parse_platform_support(vec[i], vec[i + 1], | ||
1078 | &supported); | ||
1079 | } | ||
1080 | } | ||
1081 | |||
1082 | if (supported.radix_mmu && supported.radix_gtse) { | ||
1083 | /* Radix preferred - but we require GTSE for now */ | ||
1084 | prom_debug("Asking for radix with GTSE\n"); | ||
1085 | ibm_architecture_vec.vec5.mmu = OV5_FEAT(OV5_MMU_RADIX); | ||
1086 | ibm_architecture_vec.vec5.radix_ext = OV5_FEAT(OV5_RADIX_GTSE); | ||
1087 | } else if (supported.hash_mmu) { | ||
1088 | /* Default to hash mmu (if we can) */ | ||
1089 | prom_debug("Asking for hash\n"); | ||
1090 | ibm_architecture_vec.vec5.mmu = OV5_FEAT(OV5_MMU_HASH); | ||
1091 | } else { | ||
1092 | /* We're probably on a legacy hypervisor */ | ||
1093 | prom_debug("Assuming legacy hash support\n"); | ||
1094 | } | ||
1095 | } | ||
993 | 1096 | ||
994 | static void __init prom_send_capabilities(void) | 1097 | static void __init prom_send_capabilities(void) |
995 | { | 1098 | { |
@@ -997,6 +1100,9 @@ static void __init prom_send_capabilities(void) | |||
997 | prom_arg_t ret; | 1100 | prom_arg_t ret; |
998 | u32 cores; | 1101 | u32 cores; |
999 | 1102 | ||
1103 | /* Check ibm,arch-vec-5-platform-support and fixup vec5 if required */ | ||
1104 | prom_check_platform_support(); | ||
1105 | |||
1000 | root = call_prom("open", 1, 1, ADDR("/")); | 1106 | root = call_prom("open", 1, 1, ADDR("/")); |
1001 | if (root != 0) { | 1107 | if (root != 0) { |
1002 | /* We need to tell the FW about the number of cores we support. | 1108 | /* We need to tell the FW about the number of cores we support. |
@@ -2993,6 +3099,11 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
2993 | */ | 3099 | */ |
2994 | prom_check_initrd(r3, r4); | 3100 | prom_check_initrd(r3, r4); |
2995 | 3101 | ||
3102 | /* | ||
3103 | * Do early parsing of command line | ||
3104 | */ | ||
3105 | early_cmdline_parse(); | ||
3106 | |||
2996 | #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) | 3107 | #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV) |
2997 | /* | 3108 | /* |
2998 | * On pSeries, inform the firmware about our capabilities | 3109 | * On pSeries, inform the firmware about our capabilities |
@@ -3009,11 +3120,6 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4, | |||
3009 | copy_and_flush(0, kbase, 0x100, 0); | 3120 | copy_and_flush(0, kbase, 0x100, 0); |
3010 | 3121 | ||
3011 | /* | 3122 | /* |
3012 | * Do early parsing of command line | ||
3013 | */ | ||
3014 | early_cmdline_parse(); | ||
3015 | |||
3016 | /* | ||
3017 | * Initialize memory management within prom_init | 3123 | * Initialize memory management within prom_init |
3018 | */ | 3124 | */ |
3019 | prom_init_mem(); | 3125 | prom_init_mem(); |