at v2.6.16 347 lines 8.9 kB view raw
1/* 2 * drivers/s390/sysinfo.c 3 * 4 * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation 5 * Author(s): Ulrich Weigand (Ulrich.Weigand@de.ibm.com) 6 */ 7 8#include <linux/config.h> 9#include <linux/kernel.h> 10#include <linux/mm.h> 11#include <linux/proc_fs.h> 12#include <linux/init.h> 13#include <asm/ebcdic.h> 14 15struct sysinfo_1_1_1 16{ 17 char reserved_0[32]; 18 char manufacturer[16]; 19 char type[4]; 20 char reserved_1[12]; 21 char model[16]; 22 char sequence[16]; 23 char plant[4]; 24}; 25 26struct sysinfo_1_2_1 27{ 28 char reserved_0[80]; 29 char sequence[16]; 30 char plant[4]; 31 char reserved_1[2]; 32 unsigned short cpu_address; 33}; 34 35struct sysinfo_1_2_2 36{ 37 char reserved_0[32]; 38 unsigned int capability; 39 unsigned short cpus_total; 40 unsigned short cpus_configured; 41 unsigned short cpus_standby; 42 unsigned short cpus_reserved; 43 unsigned short adjustment[0]; 44}; 45 46struct sysinfo_2_2_1 47{ 48 char reserved_0[80]; 49 char sequence[16]; 50 char plant[4]; 51 unsigned short cpu_id; 52 unsigned short cpu_address; 53}; 54 55struct sysinfo_2_2_2 56{ 57 char reserved_0[32]; 58 unsigned short lpar_number; 59 char reserved_1; 60 unsigned char characteristics; 61 #define LPAR_CHAR_DEDICATED (1 << 7) 62 #define LPAR_CHAR_SHARED (1 << 6) 63 #define LPAR_CHAR_LIMITED (1 << 5) 64 unsigned short cpus_total; 65 unsigned short cpus_configured; 66 unsigned short cpus_standby; 67 unsigned short cpus_reserved; 68 char name[8]; 69 unsigned int caf; 70 char reserved_2[16]; 71 unsigned short cpus_dedicated; 72 unsigned short cpus_shared; 73}; 74 75struct sysinfo_3_2_2 76{ 77 char reserved_0[31]; 78 unsigned char count; 79 struct 80 { 81 char reserved_0[4]; 82 unsigned short cpus_total; 83 unsigned short cpus_configured; 84 unsigned short cpus_standby; 85 unsigned short cpus_reserved; 86 char name[8]; 87 unsigned int caf; 88 char cpi[16]; 89 char reserved_1[24]; 90 91 } vm[8]; 92}; 93 94union s390_sysinfo 95{ 96 struct sysinfo_1_1_1 sysinfo_1_1_1; 97 struct sysinfo_1_2_1 sysinfo_1_2_1; 98 struct sysinfo_1_2_2 sysinfo_1_2_2; 99 struct sysinfo_2_2_1 sysinfo_2_2_1; 100 struct sysinfo_2_2_2 sysinfo_2_2_2; 101 struct sysinfo_3_2_2 sysinfo_3_2_2; 102}; 103 104static inline int stsi (void *sysinfo, 105 int fc, int sel1, int sel2) 106{ 107 int cc, retv; 108 109#ifndef CONFIG_64BIT 110 __asm__ __volatile__ ( "lr\t0,%2\n" 111 "\tlr\t1,%3\n" 112 "\tstsi\t0(%4)\n" 113 "0:\tipm\t%0\n" 114 "\tsrl\t%0,28\n" 115 "1:lr\t%1,0\n" 116 ".section .fixup,\"ax\"\n" 117 "2:\tlhi\t%0,3\n" 118 "\tbras\t1,3f\n" 119 "\t.long 1b\n" 120 "3:\tl\t1,0(1)\n" 121 "\tbr\t1\n" 122 ".previous\n" 123 ".section __ex_table,\"a\"\n" 124 "\t.align 4\n" 125 "\t.long 0b,2b\n" 126 ".previous\n" 127 : "=d" (cc), "=d" (retv) 128 : "d" ((fc << 28) | sel1), "d" (sel2), "a" (sysinfo) 129 : "cc", "memory", "0", "1" ); 130#else 131 __asm__ __volatile__ ( "lr\t0,%2\n" 132 "lr\t1,%3\n" 133 "\tstsi\t0(%4)\n" 134 "0:\tipm\t%0\n" 135 "\tsrl\t%0,28\n" 136 "1:lr\t%1,0\n" 137 ".section .fixup,\"ax\"\n" 138 "2:\tlhi\t%0,3\n" 139 "\tjg\t1b\n" 140 ".previous\n" 141 ".section __ex_table,\"a\"\n" 142 "\t.align 8\n" 143 "\t.quad 0b,2b\n" 144 ".previous\n" 145 : "=d" (cc), "=d" (retv) 146 : "d" ((fc << 28) | sel1), "d" (sel2), "a" (sysinfo) 147 : "cc", "memory", "0", "1" ); 148#endif 149 150 return cc? -1 : retv; 151} 152 153static inline int stsi_0 (void) 154{ 155 int rc = stsi (NULL, 0, 0, 0); 156 return rc == -1 ? rc : (((unsigned int)rc) >> 28); 157} 158 159static inline int stsi_1_1_1 (struct sysinfo_1_1_1 *info) 160{ 161 int rc = stsi (info, 1, 1, 1); 162 if (rc != -1) 163 { 164 EBCASC (info->manufacturer, sizeof(info->manufacturer)); 165 EBCASC (info->type, sizeof(info->type)); 166 EBCASC (info->model, sizeof(info->model)); 167 EBCASC (info->sequence, sizeof(info->sequence)); 168 EBCASC (info->plant, sizeof(info->plant)); 169 } 170 return rc == -1 ? rc : 0; 171} 172 173static inline int stsi_1_2_1 (struct sysinfo_1_2_1 *info) 174{ 175 int rc = stsi (info, 1, 2, 1); 176 if (rc != -1) 177 { 178 EBCASC (info->sequence, sizeof(info->sequence)); 179 EBCASC (info->plant, sizeof(info->plant)); 180 } 181 return rc == -1 ? rc : 0; 182} 183 184static inline int stsi_1_2_2 (struct sysinfo_1_2_2 *info) 185{ 186 int rc = stsi (info, 1, 2, 2); 187 return rc == -1 ? rc : 0; 188} 189 190static inline int stsi_2_2_1 (struct sysinfo_2_2_1 *info) 191{ 192 int rc = stsi (info, 2, 2, 1); 193 if (rc != -1) 194 { 195 EBCASC (info->sequence, sizeof(info->sequence)); 196 EBCASC (info->plant, sizeof(info->plant)); 197 } 198 return rc == -1 ? rc : 0; 199} 200 201static inline int stsi_2_2_2 (struct sysinfo_2_2_2 *info) 202{ 203 int rc = stsi (info, 2, 2, 2); 204 if (rc != -1) 205 { 206 EBCASC (info->name, sizeof(info->name)); 207 } 208 return rc == -1 ? rc : 0; 209} 210 211static inline int stsi_3_2_2 (struct sysinfo_3_2_2 *info) 212{ 213 int rc = stsi (info, 3, 2, 2); 214 if (rc != -1) 215 { 216 int i; 217 for (i = 0; i < info->count; i++) 218 { 219 EBCASC (info->vm[i].name, sizeof(info->vm[i].name)); 220 EBCASC (info->vm[i].cpi, sizeof(info->vm[i].cpi)); 221 } 222 } 223 return rc == -1 ? rc : 0; 224} 225 226 227static int proc_read_sysinfo(char *page, char **start, 228 off_t off, int count, 229 int *eof, void *data) 230{ 231 unsigned long info_page = get_zeroed_page (GFP_KERNEL); 232 union s390_sysinfo *info = (union s390_sysinfo *) info_page; 233 int len = 0; 234 int level; 235 int i; 236 237 if (!info) 238 return 0; 239 240 level = stsi_0 (); 241 242 if (level >= 1 && stsi_1_1_1 (&info->sysinfo_1_1_1) == 0) 243 { 244 len += sprintf (page+len, "Manufacturer: %-16.16s\n", 245 info->sysinfo_1_1_1.manufacturer); 246 len += sprintf (page+len, "Type: %-4.4s\n", 247 info->sysinfo_1_1_1.type); 248 len += sprintf (page+len, "Model: %-16.16s\n", 249 info->sysinfo_1_1_1.model); 250 len += sprintf (page+len, "Sequence Code: %-16.16s\n", 251 info->sysinfo_1_1_1.sequence); 252 len += sprintf (page+len, "Plant: %-4.4s\n", 253 info->sysinfo_1_1_1.plant); 254 } 255 256 if (level >= 1 && stsi_1_2_2 (&info->sysinfo_1_2_2) == 0) 257 { 258 len += sprintf (page+len, "\n"); 259 len += sprintf (page+len, "CPUs Total: %d\n", 260 info->sysinfo_1_2_2.cpus_total); 261 len += sprintf (page+len, "CPUs Configured: %d\n", 262 info->sysinfo_1_2_2.cpus_configured); 263 len += sprintf (page+len, "CPUs Standby: %d\n", 264 info->sysinfo_1_2_2.cpus_standby); 265 len += sprintf (page+len, "CPUs Reserved: %d\n", 266 info->sysinfo_1_2_2.cpus_reserved); 267 268 len += sprintf (page+len, "Capability: %d\n", 269 info->sysinfo_1_2_2.capability); 270 271 for (i = 2; i <= info->sysinfo_1_2_2.cpus_total; i++) 272 len += sprintf (page+len, "Adjustment %02d-way: %d\n", 273 i, info->sysinfo_1_2_2.adjustment[i-2]); 274 } 275 276 if (level >= 2 && stsi_2_2_2 (&info->sysinfo_2_2_2) == 0) 277 { 278 len += sprintf (page+len, "\n"); 279 len += sprintf (page+len, "LPAR Number: %d\n", 280 info->sysinfo_2_2_2.lpar_number); 281 282 len += sprintf (page+len, "LPAR Characteristics: "); 283 if (info->sysinfo_2_2_2.characteristics & LPAR_CHAR_DEDICATED) 284 len += sprintf (page+len, "Dedicated "); 285 if (info->sysinfo_2_2_2.characteristics & LPAR_CHAR_SHARED) 286 len += sprintf (page+len, "Shared "); 287 if (info->sysinfo_2_2_2.characteristics & LPAR_CHAR_LIMITED) 288 len += sprintf (page+len, "Limited "); 289 len += sprintf (page+len, "\n"); 290 291 len += sprintf (page+len, "LPAR Name: %-8.8s\n", 292 info->sysinfo_2_2_2.name); 293 294 len += sprintf (page+len, "LPAR Adjustment: %d\n", 295 info->sysinfo_2_2_2.caf); 296 297 len += sprintf (page+len, "LPAR CPUs Total: %d\n", 298 info->sysinfo_2_2_2.cpus_total); 299 len += sprintf (page+len, "LPAR CPUs Configured: %d\n", 300 info->sysinfo_2_2_2.cpus_configured); 301 len += sprintf (page+len, "LPAR CPUs Standby: %d\n", 302 info->sysinfo_2_2_2.cpus_standby); 303 len += sprintf (page+len, "LPAR CPUs Reserved: %d\n", 304 info->sysinfo_2_2_2.cpus_reserved); 305 len += sprintf (page+len, "LPAR CPUs Dedicated: %d\n", 306 info->sysinfo_2_2_2.cpus_dedicated); 307 len += sprintf (page+len, "LPAR CPUs Shared: %d\n", 308 info->sysinfo_2_2_2.cpus_shared); 309 } 310 311 if (level >= 3 && stsi_3_2_2 (&info->sysinfo_3_2_2) == 0) 312 { 313 for (i = 0; i < info->sysinfo_3_2_2.count; i++) 314 { 315 len += sprintf (page+len, "\n"); 316 len += sprintf (page+len, "VM%02d Name: %-8.8s\n", 317 i, info->sysinfo_3_2_2.vm[i].name); 318 len += sprintf (page+len, "VM%02d Control Program: %-16.16s\n", 319 i, info->sysinfo_3_2_2.vm[i].cpi); 320 321 len += sprintf (page+len, "VM%02d Adjustment: %d\n", 322 i, info->sysinfo_3_2_2.vm[i].caf); 323 324 len += sprintf (page+len, "VM%02d CPUs Total: %d\n", 325 i, info->sysinfo_3_2_2.vm[i].cpus_total); 326 len += sprintf (page+len, "VM%02d CPUs Configured: %d\n", 327 i, info->sysinfo_3_2_2.vm[i].cpus_configured); 328 len += sprintf (page+len, "VM%02d CPUs Standby: %d\n", 329 i, info->sysinfo_3_2_2.vm[i].cpus_standby); 330 len += sprintf (page+len, "VM%02d CPUs Reserved: %d\n", 331 i, info->sysinfo_3_2_2.vm[i].cpus_reserved); 332 } 333 } 334 335 free_page (info_page); 336 return len; 337} 338 339static __init int create_proc_sysinfo(void) 340{ 341 create_proc_read_entry ("sysinfo", 0444, NULL, 342 proc_read_sysinfo, NULL); 343 return 0; 344} 345 346__initcall(create_proc_sysinfo); 347