1 /* 2 * Copyright IBM Corp. 2001, 2009 3 * Author(s): Ulrich Weigand <Ulrich.Weigand@de.ibm.com>, 4 * Martin Schwidefsky <schwidefsky@de.ibm.com>, 5 */ 6 7 #include <linux/kernel.h> 8 #include <linux/mm.h> 9 #include <linux/proc_fs.h> 10 #include <linux/seq_file.h> 11 #include <linux/init.h> 12 #include <linux/delay.h> 13 #include <linux/module.h> 14 #include <linux/slab.h> 15 #include <asm/ebcdic.h> 16 #include <asm/sysinfo.h> 17 #include <asm/cpcmd.h> 18 #include <asm/topology.h> 19 20 /* Sigh, math-emu. Don't ask. */ 21 #include <asm/sfp-util.h> 22 #include <math-emu/soft-fp.h> 23 #include <math-emu/single.h> 24 25 static inline int stsi_0(void) 26 { 27 int rc = stsi(NULL, 0, 0, 0); 28 29 return rc == -ENOSYS ? rc : (((unsigned int) rc) >> 28); 30 } 31 32 static void stsi_1_1_1(struct seq_file *m, struct sysinfo_1_1_1 *info) 33 { 34 int i; 35 36 if (stsi(info, 1, 1, 1) == -ENOSYS) 37 return; 38 EBCASC(info->manufacturer, sizeof(info->manufacturer)); 39 EBCASC(info->type, sizeof(info->type)); 40 EBCASC(info->model, sizeof(info->model)); 41 EBCASC(info->sequence, sizeof(info->sequence)); 42 EBCASC(info->plant, sizeof(info->plant)); 43 EBCASC(info->model_capacity, sizeof(info->model_capacity)); 44 EBCASC(info->model_perm_cap, sizeof(info->model_perm_cap)); 45 EBCASC(info->model_temp_cap, sizeof(info->model_temp_cap)); 46 seq_printf(m, "Manufacturer: %-16.16s\n", info->manufacturer); 47 seq_printf(m, "Type: %-4.4s\n", info->type); 48 /* 49 * Sigh: the model field has been renamed with System z9 50 * to model_capacity and a new model field has been added 51 * after the plant field. To avoid confusing older programs 52 * the "Model:" prints "model_capacity model" or just 53 * "model_capacity" if the model string is empty . 54 */ 55 seq_printf(m, "Model: %-16.16s", info->model_capacity); 56 if (info->model[0] != '\0') 57 seq_printf(m, " %-16.16s", info->model); 58 seq_putc(m, '\n'); 59 seq_printf(m, "Sequence Code: %-16.16s\n", info->sequence); 60 seq_printf(m, "Plant: %-4.4s\n", info->plant); 61 seq_printf(m, "Model Capacity: %-16.16s %08u\n", 62 info->model_capacity, info->model_cap_rating); 63 if (info->model_perm_cap_rating) 64 seq_printf(m, "Model Perm. Capacity: %-16.16s %08u\n", 65 info->model_perm_cap, 66 info->model_perm_cap_rating); 67 if (info->model_temp_cap_rating) 68 seq_printf(m, "Model Temp. Capacity: %-16.16s %08u\n", 69 info->model_temp_cap, 70 info->model_temp_cap_rating); 71 if (info->ncr) 72 seq_printf(m, "Nominal Cap. Rating: %08u\n", info->ncr); 73 if (info->npr) 74 seq_printf(m, "Nominal Perm. Rating: %08u\n", info->npr); 75 if (info->ntr) 76 seq_printf(m, "Nominal Temp. Rating: %08u\n", info->ntr); 77 if (info->cai) { 78 seq_printf(m, "Capacity Adj. Ind.: %d\n", info->cai); 79 seq_printf(m, "Capacity Ch. Reason: %d\n", info->ccr); 80 seq_printf(m, "Capacity Transient: %d\n", info->t); 81 } 82 if (info->p) { 83 for (i = 1; i <= ARRAY_SIZE(info->typepct); i++) { 84 seq_printf(m, "Type %d Percentage: %d\n", 85 i, info->typepct[i - 1]); 86 } 87 } 88 } 89 90 static void stsi_15_1_x(struct seq_file *m, struct sysinfo_15_1_x *info) 91 { 92 static int max_mnest; 93 int i, rc; 94 95 seq_putc(m, '\n'); 96 if (!MACHINE_HAS_TOPOLOGY) 97 return; 98 if (max_mnest) { 99 stsi(info, 15, 1, max_mnest); 100 } else { 101 for (max_mnest = 6; max_mnest > 1; max_mnest--) { 102 rc = stsi(info, 15, 1, max_mnest); 103 if (rc != -ENOSYS) 104 break; 105 } 106 } 107 seq_printf(m, "CPU Topology HW: "); 108 for (i = 0; i < TOPOLOGY_NR_MAG; i++) 109 seq_printf(m, " %d", info->mag[i]); 110 seq_putc(m, '\n'); 111 #ifdef CONFIG_SCHED_MC 112 store_topology(info); 113 seq_printf(m, "CPU Topology SW: "); 114 for (i = 0; i < TOPOLOGY_NR_MAG; i++) 115 seq_printf(m, " %d", info->mag[i]); 116 seq_putc(m, '\n'); 117 #endif 118 } 119 120 static void stsi_1_2_2(struct seq_file *m, struct sysinfo_1_2_2 *info) 121 { 122 struct sysinfo_1_2_2_extension *ext; 123 int i; 124 125 if (stsi(info, 1, 2, 2) == -ENOSYS) 126 return; 127 ext = (struct sysinfo_1_2_2_extension *) 128 ((unsigned long) info + info->acc_offset); 129 seq_printf(m, "CPUs Total: %d\n", info->cpus_total); 130 seq_printf(m, "CPUs Configured: %d\n", info->cpus_configured); 131 seq_printf(m, "CPUs Standby: %d\n", info->cpus_standby); 132 seq_printf(m, "CPUs Reserved: %d\n", info->cpus_reserved); 133 /* 134 * Sigh 2. According to the specification the alternate 135 * capability field is a 32 bit floating point number 136 * if the higher order 8 bits are not zero. Printing 137 * a floating point number in the kernel is a no-no, 138 * always print the number as 32 bit unsigned integer. 139 * The user-space needs to know about the strange 140 * encoding of the alternate cpu capability. 141 */ 142 seq_printf(m, "Capability: %u", info->capability); 143 if (info->format == 1) 144 seq_printf(m, " %u", ext->alt_capability); 145 seq_putc(m, '\n'); 146 if (info->nominal_cap) 147 seq_printf(m, "Nominal Capability: %d\n", info->nominal_cap); 148 if (info->secondary_cap) 149 seq_printf(m, "Secondary Capability: %d\n", info->secondary_cap); 150 for (i = 2; i <= info->cpus_total; i++) { 151 seq_printf(m, "Adjustment %02d-way: %u", 152 i, info->adjustment[i-2]); 153 if (info->format == 1) 154 seq_printf(m, " %u", ext->alt_adjustment[i-2]); 155 seq_putc(m, '\n'); 156 } 157 } 158 159 static void stsi_2_2_2(struct seq_file *m, struct sysinfo_2_2_2 *info) 160 { 161 if (stsi(info, 2, 2, 2) == -ENOSYS) 162 return; 163 EBCASC(info->name, sizeof(info->name)); 164 seq_putc(m, '\n'); 165 seq_printf(m, "LPAR Number: %d\n", info->lpar_number); 166 seq_printf(m, "LPAR Characteristics: "); 167 if (info->characteristics & LPAR_CHAR_DEDICATED) 168 seq_printf(m, "Dedicated "); 169 if (info->characteristics & LPAR_CHAR_SHARED) 170 seq_printf(m, "Shared "); 171 if (info->characteristics & LPAR_CHAR_LIMITED) 172 seq_printf(m, "Limited "); 173 seq_putc(m, '\n'); 174 seq_printf(m, "LPAR Name: %-8.8s\n", info->name); 175 seq_printf(m, "LPAR Adjustment: %d\n", info->caf); 176 seq_printf(m, "LPAR CPUs Total: %d\n", info->cpus_total); 177 seq_printf(m, "LPAR CPUs Configured: %d\n", info->cpus_configured); 178 seq_printf(m, "LPAR CPUs Standby: %d\n", info->cpus_standby); 179 seq_printf(m, "LPAR CPUs Reserved: %d\n", info->cpus_reserved); 180 seq_printf(m, "LPAR CPUs Dedicated: %d\n", info->cpus_dedicated); 181 seq_printf(m, "LPAR CPUs Shared: %d\n", info->cpus_shared); 182 } 183 184 static void stsi_3_2_2(struct seq_file *m, struct sysinfo_3_2_2 *info) 185 { 186 int i; 187 188 if (stsi(info, 3, 2, 2) == -ENOSYS) 189 return; 190 for (i = 0; i < info->count; i++) { 191 EBCASC(info->vm[i].name, sizeof(info->vm[i].name)); 192 EBCASC(info->vm[i].cpi, sizeof(info->vm[i].cpi)); 193 seq_putc(m, '\n'); 194 seq_printf(m, "VM%02d Name: %-8.8s\n", i, info->vm[i].name); 195 seq_printf(m, "VM%02d Control Program: %-16.16s\n", i, info->vm[i].cpi); 196 seq_printf(m, "VM%02d Adjustment: %d\n", i, info->vm[i].caf); 197 seq_printf(m, "VM%02d CPUs Total: %d\n", i, info->vm[i].cpus_total); 198 seq_printf(m, "VM%02d CPUs Configured: %d\n", i, info->vm[i].cpus_configured); 199 seq_printf(m, "VM%02d CPUs Standby: %d\n", i, info->vm[i].cpus_standby); 200 seq_printf(m, "VM%02d CPUs Reserved: %d\n", i, info->vm[i].cpus_reserved); 201 } 202 } 203 204 static int sysinfo_show(struct seq_file *m, void *v) 205 { 206 void *info = (void *)get_zeroed_page(GFP_KERNEL); 207 int level; 208 209 if (!info) 210 return 0; 211 level = stsi_0(); 212 if (level >= 1) 213 stsi_1_1_1(m, info); 214 if (level >= 1) 215 stsi_15_1_x(m, info); 216 if (level >= 1) 217 stsi_1_2_2(m, info); 218 if (level >= 2) 219 stsi_2_2_2(m, info); 220 if (level >= 3) 221 stsi_3_2_2(m, info); 222 free_page((unsigned long)info); 223 return 0; 224 } 225 226 static int sysinfo_open(struct inode *inode, struct file *file) 227 { 228 return single_open(file, sysinfo_show, NULL); 229 } 230 231 static const struct file_operations sysinfo_fops = { 232 .open = sysinfo_open, 233 .read = seq_read, 234 .llseek = seq_lseek, 235 .release = single_release, 236 }; 237 238 static int __init sysinfo_create_proc(void) 239 { 240 proc_create("sysinfo", 0444, NULL, &sysinfo_fops); 241 return 0; 242 } 243 device_initcall(sysinfo_create_proc); 244 245 /* 246 * Service levels interface. 247 */ 248 249 static DECLARE_RWSEM(service_level_sem); 250 static LIST_HEAD(service_level_list); 251 252 int register_service_level(struct service_level *slr) 253 { 254 struct service_level *ptr; 255 256 down_write(&service_level_sem); 257 list_for_each_entry(ptr, &service_level_list, list) 258 if (ptr == slr) { 259 up_write(&service_level_sem); 260 return -EEXIST; 261 } 262 list_add_tail(&slr->list, &service_level_list); 263 up_write(&service_level_sem); 264 return 0; 265 } 266 EXPORT_SYMBOL(register_service_level); 267 268 int unregister_service_level(struct service_level *slr) 269 { 270 struct service_level *ptr, *next; 271 int rc = -ENOENT; 272 273 down_write(&service_level_sem); 274 list_for_each_entry_safe(ptr, next, &service_level_list, list) { 275 if (ptr != slr) 276 continue; 277 list_del(&ptr->list); 278 rc = 0; 279 break; 280 } 281 up_write(&service_level_sem); 282 return rc; 283 } 284 EXPORT_SYMBOL(unregister_service_level); 285 286 static void *service_level_start(struct seq_file *m, loff_t *pos) 287 { 288 down_read(&service_level_sem); 289 return seq_list_start(&service_level_list, *pos); 290 } 291 292 static void *service_level_next(struct seq_file *m, void *p, loff_t *pos) 293 { 294 return seq_list_next(p, &service_level_list, pos); 295 } 296 297 static void service_level_stop(struct seq_file *m, void *p) 298 { 299 up_read(&service_level_sem); 300 } 301 302 static int service_level_show(struct seq_file *m, void *p) 303 { 304 struct service_level *slr; 305 306 slr = list_entry(p, struct service_level, list); 307 slr->seq_print(m, slr); 308 return 0; 309 } 310 311 static const struct seq_operations service_level_seq_ops = { 312 .start = service_level_start, 313 .next = service_level_next, 314 .stop = service_level_stop, 315 .show = service_level_show 316 }; 317 318 static int service_level_open(struct inode *inode, struct file *file) 319 { 320 return seq_open(file, &service_level_seq_ops); 321 } 322 323 static const struct file_operations service_level_ops = { 324 .open = service_level_open, 325 .read = seq_read, 326 .llseek = seq_lseek, 327 .release = seq_release 328 }; 329 330 static void service_level_vm_print(struct seq_file *m, 331 struct service_level *slr) 332 { 333 char *query_buffer, *str; 334 335 query_buffer = kmalloc(1024, GFP_KERNEL | GFP_DMA); 336 if (!query_buffer) 337 return; 338 cpcmd("QUERY CPLEVEL", query_buffer, 1024, NULL); 339 str = strchr(query_buffer, '\n'); 340 if (str) 341 *str = 0; 342 seq_printf(m, "VM: %s\n", query_buffer); 343 kfree(query_buffer); 344 } 345 346 static struct service_level service_level_vm = { 347 .seq_print = service_level_vm_print 348 }; 349 350 static __init int create_proc_service_level(void) 351 { 352 proc_create("service_levels", 0, NULL, &service_level_ops); 353 if (MACHINE_IS_VM) 354 register_service_level(&service_level_vm); 355 return 0; 356 } 357 subsys_initcall(create_proc_service_level); 358 359 /* 360 * CPU capability might have changed. Therefore recalculate loops_per_jiffy. 361 */ 362 void s390_adjust_jiffies(void) 363 { 364 struct sysinfo_1_2_2 *info; 365 const unsigned int fmil = 0x4b189680; /* 1e7 as 32-bit float. */ 366 FP_DECL_S(SA); FP_DECL_S(SB); FP_DECL_S(SR); 367 FP_DECL_EX; 368 unsigned int capability; 369 370 info = (void *) get_zeroed_page(GFP_KERNEL); 371 if (!info) 372 return; 373 374 if (stsi(info, 1, 2, 2) != -ENOSYS) { 375 /* 376 * Major sigh. The cpu capability encoding is "special". 377 * If the first 9 bits of info->capability are 0 then it 378 * is a 32 bit unsigned integer in the range 0 .. 2^23. 379 * If the first 9 bits are != 0 then it is a 32 bit float. 380 * In addition a lower value indicates a proportionally 381 * higher cpu capacity. Bogomips are the other way round. 382 * To get to a halfway suitable number we divide 1e7 383 * by the cpu capability number. Yes, that means a floating 384 * point division .. math-emu here we come :-) 385 */ 386 FP_UNPACK_SP(SA, &fmil); 387 if ((info->capability >> 23) == 0) 388 FP_FROM_INT_S(SB, (long) info->capability, 64, long); 389 else 390 FP_UNPACK_SP(SB, &info->capability); 391 FP_DIV_S(SR, SA, SB); 392 FP_TO_INT_S(capability, SR, 32, 0); 393 } else 394 /* 395 * Really old machine without stsi block for basic 396 * cpu information. Report 42.0 bogomips. 397 */ 398 capability = 42; 399 loops_per_jiffy = capability * (500000/HZ); 400 free_page((unsigned long) info); 401 } 402 403 /* 404 * calibrate the delay loop 405 */ 406 void __cpuinit calibrate_delay(void) 407 { 408 s390_adjust_jiffies(); 409 /* Print the good old Bogomips line .. */ 410 printk(KERN_DEBUG "Calibrating delay loop (skipped)... " 411 "%lu.%02lu BogoMIPS preset\n", loops_per_jiffy/(500000/HZ), 412 (loops_per_jiffy/(5000/HZ)) % 100); 413 } 414