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