aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc64/kernel/prom.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2005-11-06 19:06:55 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-11-06 19:56:47 -0500
commit3c726f8dee6f55e96475574e9f645327e461884c (patch)
treef67c381e8f57959aa4a94bda4c68e24253cd8171 /arch/ppc64/kernel/prom.c
parentf912696ab330bf539231d1f8032320f2a08b850f (diff)
[PATCH] ppc64: support 64k pages
Adds a new CONFIG_PPC_64K_PAGES which, when enabled, changes the kernel base page size to 64K. The resulting kernel still boots on any hardware. On current machines with 4K pages support only, the kernel will maintain 16 "subpages" for each 64K page transparently. Note that while real 64K capable HW has been tested, the current patch will not enable it yet as such hardware is not released yet, and I'm still verifying with the firmware architects the proper to get the information from the newer hypervisors. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/ppc64/kernel/prom.c')
-rw-r--r--arch/ppc64/kernel/prom.c94
1 files changed, 33 insertions, 61 deletions
diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
index 97bfceb5353b..dece31e58bc4 100644
--- a/arch/ppc64/kernel/prom.c
+++ b/arch/ppc64/kernel/prom.c
@@ -635,10 +635,10 @@ static inline char *find_flat_dt_string(u32 offset)
635 * used to extract the memory informations at boot before we can 635 * used to extract the memory informations at boot before we can
636 * unflatten the tree 636 * unflatten the tree
637 */ 637 */
638static int __init scan_flat_dt(int (*it)(unsigned long node, 638int __init of_scan_flat_dt(int (*it)(unsigned long node,
639 const char *uname, int depth, 639 const char *uname, int depth,
640 void *data), 640 void *data),
641 void *data) 641 void *data)
642{ 642{
643 unsigned long p = ((unsigned long)initial_boot_params) + 643 unsigned long p = ((unsigned long)initial_boot_params) +
644 initial_boot_params->off_dt_struct; 644 initial_boot_params->off_dt_struct;
@@ -695,8 +695,8 @@ static int __init scan_flat_dt(int (*it)(unsigned long node,
695 * This function can be used within scan_flattened_dt callback to get 695 * This function can be used within scan_flattened_dt callback to get
696 * access to properties 696 * access to properties
697 */ 697 */
698static void* __init get_flat_dt_prop(unsigned long node, const char *name, 698void* __init of_get_flat_dt_prop(unsigned long node, const char *name,
699 unsigned long *size) 699 unsigned long *size)
700{ 700{
701 unsigned long p = node; 701 unsigned long p = node;
702 702
@@ -996,7 +996,7 @@ void __init unflatten_device_tree(void)
996static int __init early_init_dt_scan_cpus(unsigned long node, 996static int __init early_init_dt_scan_cpus(unsigned long node,
997 const char *uname, int depth, void *data) 997 const char *uname, int depth, void *data)
998{ 998{
999 char *type = get_flat_dt_prop(node, "device_type", NULL); 999 char *type = of_get_flat_dt_prop(node, "device_type", NULL);
1000 u32 *prop; 1000 u32 *prop;
1001 unsigned long size; 1001 unsigned long size;
1002 1002
@@ -1004,17 +1004,6 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
1004 if (type == NULL || strcmp(type, "cpu") != 0) 1004 if (type == NULL || strcmp(type, "cpu") != 0)
1005 return 0; 1005 return 0;
1006 1006
1007 /* On LPAR, look for the first ibm,pft-size property for the hash table size
1008 */
1009 if (systemcfg->platform == PLATFORM_PSERIES_LPAR && ppc64_pft_size == 0) {
1010 u32 *pft_size;
1011 pft_size = (u32 *)get_flat_dt_prop(node, "ibm,pft-size", NULL);
1012 if (pft_size != NULL) {
1013 /* pft_size[0] is the NUMA CEC cookie */
1014 ppc64_pft_size = pft_size[1];
1015 }
1016 }
1017
1018 if (initial_boot_params && initial_boot_params->version >= 2) { 1007 if (initial_boot_params && initial_boot_params->version >= 2) {
1019 /* version 2 of the kexec param format adds the phys cpuid 1008 /* version 2 of the kexec param format adds the phys cpuid
1020 * of booted proc. 1009 * of booted proc.
@@ -1023,8 +1012,9 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
1023 boot_cpuid = 0; 1012 boot_cpuid = 0;
1024 } else { 1013 } else {
1025 /* Check if it's the boot-cpu, set it's hw index in paca now */ 1014 /* Check if it's the boot-cpu, set it's hw index in paca now */
1026 if (get_flat_dt_prop(node, "linux,boot-cpu", NULL) != NULL) { 1015 if (of_get_flat_dt_prop(node, "linux,boot-cpu", NULL)
1027 u32 *prop = get_flat_dt_prop(node, "reg", NULL); 1016 != NULL) {
1017 u32 *prop = of_get_flat_dt_prop(node, "reg", NULL);
1028 set_hard_smp_processor_id(0, prop == NULL ? 0 : *prop); 1018 set_hard_smp_processor_id(0, prop == NULL ? 0 : *prop);
1029 boot_cpuid_phys = get_hard_smp_processor_id(0); 1019 boot_cpuid_phys = get_hard_smp_processor_id(0);
1030 } 1020 }
@@ -1032,14 +1022,14 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
1032 1022
1033#ifdef CONFIG_ALTIVEC 1023#ifdef CONFIG_ALTIVEC
1034 /* Check if we have a VMX and eventually update CPU features */ 1024 /* Check if we have a VMX and eventually update CPU features */
1035 prop = (u32 *)get_flat_dt_prop(node, "ibm,vmx", NULL); 1025 prop = (u32 *)of_get_flat_dt_prop(node, "ibm,vmx", NULL);
1036 if (prop && (*prop) > 0) { 1026 if (prop && (*prop) > 0) {
1037 cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; 1027 cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC;
1038 cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; 1028 cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC;
1039 } 1029 }
1040 1030
1041 /* Same goes for Apple's "altivec" property */ 1031 /* Same goes for Apple's "altivec" property */
1042 prop = (u32 *)get_flat_dt_prop(node, "altivec", NULL); 1032 prop = (u32 *)of_get_flat_dt_prop(node, "altivec", NULL);
1043 if (prop) { 1033 if (prop) {
1044 cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC; 1034 cur_cpu_spec->cpu_features |= CPU_FTR_ALTIVEC;
1045 cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC; 1035 cur_cpu_spec->cpu_user_features |= PPC_FEATURE_HAS_ALTIVEC;
@@ -1051,7 +1041,7 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
1051 * this by looking at the size of the ibm,ppc-interrupt-server#s 1041 * this by looking at the size of the ibm,ppc-interrupt-server#s
1052 * property 1042 * property
1053 */ 1043 */
1054 prop = (u32 *)get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s", 1044 prop = (u32 *)of_get_flat_dt_prop(node, "ibm,ppc-interrupt-server#s",
1055 &size); 1045 &size);
1056 cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT; 1046 cur_cpu_spec->cpu_features &= ~CPU_FTR_SMT;
1057 if (prop && ((size / sizeof(u32)) > 1)) 1047 if (prop && ((size / sizeof(u32)) > 1))
@@ -1072,26 +1062,26 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
1072 return 0; 1062 return 0;
1073 1063
1074 /* get platform type */ 1064 /* get platform type */
1075 prop = (u32 *)get_flat_dt_prop(node, "linux,platform", NULL); 1065 prop = (u32 *)of_get_flat_dt_prop(node, "linux,platform", NULL);
1076 if (prop == NULL) 1066 if (prop == NULL)
1077 return 0; 1067 return 0;
1078 systemcfg->platform = *prop; 1068 systemcfg->platform = *prop;
1079 1069
1080 /* check if iommu is forced on or off */ 1070 /* check if iommu is forced on or off */
1081 if (get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL) 1071 if (of_get_flat_dt_prop(node, "linux,iommu-off", NULL) != NULL)
1082 iommu_is_off = 1; 1072 iommu_is_off = 1;
1083 if (get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL) 1073 if (of_get_flat_dt_prop(node, "linux,iommu-force-on", NULL) != NULL)
1084 iommu_force_on = 1; 1074 iommu_force_on = 1;
1085 1075
1086 prop64 = (u64*)get_flat_dt_prop(node, "linux,memory-limit", NULL); 1076 prop64 = (u64*)of_get_flat_dt_prop(node, "linux,memory-limit", NULL);
1087 if (prop64) 1077 if (prop64)
1088 memory_limit = *prop64; 1078 memory_limit = *prop64;
1089 1079
1090 prop64 = (u64*)get_flat_dt_prop(node, "linux,tce-alloc-start", NULL); 1080 prop64 = (u64*)of_get_flat_dt_prop(node, "linux,tce-alloc-start",NULL);
1091 if (prop64) 1081 if (prop64)
1092 tce_alloc_start = *prop64; 1082 tce_alloc_start = *prop64;
1093 1083
1094 prop64 = (u64*)get_flat_dt_prop(node, "linux,tce-alloc-end", NULL); 1084 prop64 = (u64*)of_get_flat_dt_prop(node, "linux,tce-alloc-end", NULL);
1095 if (prop64) 1085 if (prop64)
1096 tce_alloc_end = *prop64; 1086 tce_alloc_end = *prop64;
1097 1087
@@ -1102,9 +1092,12 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
1102 { 1092 {
1103 u64 *basep, *entryp; 1093 u64 *basep, *entryp;
1104 1094
1105 basep = (u64*)get_flat_dt_prop(node, "linux,rtas-base", NULL); 1095 basep = (u64*)of_get_flat_dt_prop(node,
1106 entryp = (u64*)get_flat_dt_prop(node, "linux,rtas-entry", NULL); 1096 "linux,rtas-base", NULL);
1107 prop = (u32*)get_flat_dt_prop(node, "linux,rtas-size", NULL); 1097 entryp = (u64*)of_get_flat_dt_prop(node,
1098 "linux,rtas-entry", NULL);
1099 prop = (u32*)of_get_flat_dt_prop(node,
1100 "linux,rtas-size", NULL);
1108 if (basep && entryp && prop) { 1101 if (basep && entryp && prop) {
1109 rtas.base = *basep; 1102 rtas.base = *basep;
1110 rtas.entry = *entryp; 1103 rtas.entry = *entryp;
@@ -1125,11 +1118,11 @@ static int __init early_init_dt_scan_root(unsigned long node,
1125 if (depth != 0) 1118 if (depth != 0)
1126 return 0; 1119 return 0;
1127 1120
1128 prop = (u32 *)get_flat_dt_prop(node, "#size-cells", NULL); 1121 prop = (u32 *)of_get_flat_dt_prop(node, "#size-cells", NULL);
1129 dt_root_size_cells = (prop == NULL) ? 1 : *prop; 1122 dt_root_size_cells = (prop == NULL) ? 1 : *prop;
1130 DBG("dt_root_size_cells = %x\n", dt_root_size_cells); 1123 DBG("dt_root_size_cells = %x\n", dt_root_size_cells);
1131 1124
1132 prop = (u32 *)get_flat_dt_prop(node, "#address-cells", NULL); 1125 prop = (u32 *)of_get_flat_dt_prop(node, "#address-cells", NULL);
1133 dt_root_addr_cells = (prop == NULL) ? 2 : *prop; 1126 dt_root_addr_cells = (prop == NULL) ? 2 : *prop;
1134 DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells); 1127 DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells);
1135 1128
@@ -1161,7 +1154,7 @@ static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp)
1161static int __init early_init_dt_scan_memory(unsigned long node, 1154static int __init early_init_dt_scan_memory(unsigned long node,
1162 const char *uname, int depth, void *data) 1155 const char *uname, int depth, void *data)
1163{ 1156{
1164 char *type = get_flat_dt_prop(node, "device_type", NULL); 1157 char *type = of_get_flat_dt_prop(node, "device_type", NULL);
1165 cell_t *reg, *endp; 1158 cell_t *reg, *endp;
1166 unsigned long l; 1159 unsigned long l;
1167 1160
@@ -1169,7 +1162,7 @@ static int __init early_init_dt_scan_memory(unsigned long node,
1169 if (type == NULL || strcmp(type, "memory") != 0) 1162 if (type == NULL || strcmp(type, "memory") != 0)
1170 return 0; 1163 return 0;
1171 1164
1172 reg = (cell_t *)get_flat_dt_prop(node, "reg", &l); 1165 reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l);
1173 if (reg == NULL) 1166 if (reg == NULL)
1174 return 0; 1167 return 0;
1175 1168
@@ -1225,19 +1218,16 @@ void __init early_init_devtree(void *params)
1225 /* Setup flat device-tree pointer */ 1218 /* Setup flat device-tree pointer */
1226 initial_boot_params = params; 1219 initial_boot_params = params;
1227 1220
1228 /* By default, hash size is not set */
1229 ppc64_pft_size = 0;
1230
1231 /* Retreive various informations from the /chosen node of the 1221 /* Retreive various informations from the /chosen node of the
1232 * device-tree, including the platform type, initrd location and 1222 * device-tree, including the platform type, initrd location and
1233 * size, TCE reserve, and more ... 1223 * size, TCE reserve, and more ...
1234 */ 1224 */
1235 scan_flat_dt(early_init_dt_scan_chosen, NULL); 1225 of_scan_flat_dt(early_init_dt_scan_chosen, NULL);
1236 1226
1237 /* Scan memory nodes and rebuild LMBs */ 1227 /* Scan memory nodes and rebuild LMBs */
1238 lmb_init(); 1228 lmb_init();
1239 scan_flat_dt(early_init_dt_scan_root, NULL); 1229 of_scan_flat_dt(early_init_dt_scan_root, NULL);
1240 scan_flat_dt(early_init_dt_scan_memory, NULL); 1230 of_scan_flat_dt(early_init_dt_scan_memory, NULL);
1241 lmb_enforce_memory_limit(memory_limit); 1231 lmb_enforce_memory_limit(memory_limit);
1242 lmb_analyze(); 1232 lmb_analyze();
1243 systemcfg->physicalMemorySize = lmb_phys_mem_size(); 1233 systemcfg->physicalMemorySize = lmb_phys_mem_size();
@@ -1253,26 +1243,8 @@ void __init early_init_devtree(void *params)
1253 /* Retreive hash table size from flattened tree plus other 1243 /* Retreive hash table size from flattened tree plus other
1254 * CPU related informations (altivec support, boot CPU ID, ...) 1244 * CPU related informations (altivec support, boot CPU ID, ...)
1255 */ 1245 */
1256 scan_flat_dt(early_init_dt_scan_cpus, NULL); 1246 of_scan_flat_dt(early_init_dt_scan_cpus, NULL);
1257
1258 /* If hash size wasn't obtained above, we calculate it now based on
1259 * the total RAM size
1260 */
1261 if (ppc64_pft_size == 0) {
1262 unsigned long rnd_mem_size, pteg_count;
1263
1264 /* round mem_size up to next power of 2 */
1265 rnd_mem_size = 1UL << __ilog2(systemcfg->physicalMemorySize);
1266 if (rnd_mem_size < systemcfg->physicalMemorySize)
1267 rnd_mem_size <<= 1;
1268
1269 /* # pages / 2 */
1270 pteg_count = max(rnd_mem_size >> (12 + 1), 1UL << 11);
1271
1272 ppc64_pft_size = __ilog2(pteg_count << 7);
1273 }
1274 1247
1275 DBG("Hash pftSize: %x\n", (int)ppc64_pft_size);
1276 DBG(" <- early_init_devtree()\n"); 1248 DBG(" <- early_init_devtree()\n");
1277} 1249}
1278 1250