2 * drivers/s390/sysinfo.c
4 * Copyright (C) 2001 IBM Deutschland Entwicklung GmbH, IBM Corporation
5 * Author(s): Ulrich Weigand (Ulrich.Weigand@de.ibm.com)
8 #include <linux/kernel.h>
10 #include <linux/proc_fs.h>
11 #include <linux/init.h>
12 #include <asm/ebcdic.h>
14 struct sysinfo_1_1_1
{
16 char manufacturer
[16];
19 char model_capacity
[16];
25 struct sysinfo_1_2_1
{
30 unsigned short cpu_address
;
33 struct sysinfo_1_2_2
{
36 unsigned short acc_offset
;
38 unsigned int secondary_capability
;
39 unsigned int capability
;
40 unsigned short cpus_total
;
41 unsigned short cpus_configured
;
42 unsigned short cpus_standby
;
43 unsigned short cpus_reserved
;
44 unsigned short adjustment
[0];
47 struct sysinfo_1_2_2_extension
{
48 unsigned int alt_capability
;
49 unsigned short alt_adjustment
[0];
52 struct sysinfo_2_2_1
{
56 unsigned short cpu_id
;
57 unsigned short cpu_address
;
60 struct sysinfo_2_2_2
{
62 unsigned short lpar_number
;
64 unsigned char characteristics
;
65 unsigned short cpus_total
;
66 unsigned short cpus_configured
;
67 unsigned short cpus_standby
;
68 unsigned short cpus_reserved
;
72 unsigned short cpus_dedicated
;
73 unsigned short cpus_shared
;
76 #define LPAR_CHAR_DEDICATED (1 << 7)
77 #define LPAR_CHAR_SHARED (1 << 6)
78 #define LPAR_CHAR_LIMITED (1 << 5)
80 struct sysinfo_3_2_2
{
85 unsigned short cpus_total
;
86 unsigned short cpus_configured
;
87 unsigned short cpus_standby
;
88 unsigned short cpus_reserved
;
97 static inline int stsi(void *sysinfo
, int fc
, int sel1
, int sel2
)
99 register int r0
asm("0") = (fc
<< 28) | sel1
;
100 register int r1
asm("1") = sel2
;
108 : "+d" (r0
) : "d" (r1
), "a" (sysinfo
), "K" (-ENOSYS
)
113 static inline int stsi_0(void)
115 int rc
= stsi (NULL
, 0, 0, 0);
116 return rc
== -ENOSYS
? rc
: (((unsigned int) rc
) >> 28);
119 static int stsi_1_1_1(struct sysinfo_1_1_1
*info
, char *page
, int len
)
121 if (stsi(info
, 1, 1, 1) == -ENOSYS
)
124 EBCASC(info
->manufacturer
, sizeof(info
->manufacturer
));
125 EBCASC(info
->type
, sizeof(info
->type
));
126 EBCASC(info
->model
, sizeof(info
->model
));
127 EBCASC(info
->sequence
, sizeof(info
->sequence
));
128 EBCASC(info
->plant
, sizeof(info
->plant
));
129 EBCASC(info
->model_capacity
, sizeof(info
->model_capacity
));
130 len
+= sprintf(page
+ len
, "Manufacturer: %-16.16s\n",
132 len
+= sprintf(page
+ len
, "Type: %-4.4s\n",
134 if (info
->model
[0] != '\0')
136 * Sigh: the model field has been renamed with System z9
137 * to model_capacity and a new model field has been added
138 * after the plant field. To avoid confusing older programs
139 * the "Model:" prints "model_capacity model" or just
140 * "model_capacity" if the model string is empty .
142 len
+= sprintf(page
+ len
,
143 "Model: %-16.16s %-16.16s\n",
144 info
->model_capacity
, info
->model
);
146 len
+= sprintf(page
+ len
, "Model: %-16.16s\n",
147 info
->model_capacity
);
148 len
+= sprintf(page
+ len
, "Sequence Code: %-16.16s\n",
150 len
+= sprintf(page
+ len
, "Plant: %-4.4s\n",
152 len
+= sprintf(page
+ len
, "Model Capacity: %-16.16s\n",
153 info
->model_capacity
);
157 #if 0 /* Currently unused */
158 static int stsi_1_2_1(struct sysinfo_1_2_1
*info
, char *page
, int len
)
160 if (stsi(info
, 1, 2, 1) == -ENOSYS
)
163 len
+= sprintf(page
+ len
, "\n");
164 EBCASC(info
->sequence
, sizeof(info
->sequence
));
165 EBCASC(info
->plant
, sizeof(info
->plant
));
166 len
+= sprintf(page
+ len
, "Sequence Code of CPU: %-16.16s\n",
168 len
+= sprintf(page
+ len
, "Plant of CPU: %-16.16s\n",
174 static int stsi_1_2_2(struct sysinfo_1_2_2
*info
, char *page
, int len
)
176 struct sysinfo_1_2_2_extension
*ext
;
179 if (stsi(info
, 1, 2, 2) == -ENOSYS
)
181 ext
= (struct sysinfo_1_2_2_extension
*)
182 ((unsigned long) info
+ info
->acc_offset
);
184 len
+= sprintf(page
+ len
, "\n");
185 len
+= sprintf(page
+ len
, "CPUs Total: %d\n",
187 len
+= sprintf(page
+ len
, "CPUs Configured: %d\n",
188 info
->cpus_configured
);
189 len
+= sprintf(page
+ len
, "CPUs Standby: %d\n",
191 len
+= sprintf(page
+ len
, "CPUs Reserved: %d\n",
192 info
->cpus_reserved
);
194 if (info
->format
== 1) {
196 * Sigh 2. According to the specification the alternate
197 * capability field is a 32 bit floating point number
198 * if the higher order 8 bits are not zero. Printing
199 * a floating point number in the kernel is a no-no,
200 * always print the number as 32 bit unsigned integer.
201 * The user-space needs to know about the stange
202 * encoding of the alternate cpu capability.
204 len
+= sprintf(page
+ len
, "Capability: %u %u\n",
205 info
->capability
, ext
->alt_capability
);
206 for (i
= 2; i
<= info
->cpus_total
; i
++)
207 len
+= sprintf(page
+ len
,
208 "Adjustment %02d-way: %u %u\n",
209 i
, info
->adjustment
[i
-2],
210 ext
->alt_adjustment
[i
-2]);
213 len
+= sprintf(page
+ len
, "Capability: %u\n",
215 for (i
= 2; i
<= info
->cpus_total
; i
++)
216 len
+= sprintf(page
+ len
,
217 "Adjustment %02d-way: %u\n",
218 i
, info
->adjustment
[i
-2]);
221 if (info
->secondary_capability
!= 0)
222 len
+= sprintf(page
+ len
, "Secondary Capability: %d\n",
223 info
->secondary_capability
);
228 #if 0 /* Currently unused */
229 static int stsi_2_2_1(struct sysinfo_2_2_1
*info
, char *page
, int len
)
231 if (stsi(info
, 2, 2, 1) == -ENOSYS
)
234 len
+= sprintf(page
+ len
, "\n");
235 EBCASC (info
->sequence
, sizeof(info
->sequence
));
236 EBCASC (info
->plant
, sizeof(info
->plant
));
237 len
+= sprintf(page
+ len
, "Sequence Code of logical CPU: %-16.16s\n",
239 len
+= sprintf(page
+ len
, "Plant of logical CPU: %-16.16s\n",
245 static int stsi_2_2_2(struct sysinfo_2_2_2
*info
, char *page
, int len
)
247 if (stsi(info
, 2, 2, 2) == -ENOSYS
)
250 EBCASC (info
->name
, sizeof(info
->name
));
252 len
+= sprintf(page
+ len
, "\n");
253 len
+= sprintf(page
+ len
, "LPAR Number: %d\n",
256 len
+= sprintf(page
+ len
, "LPAR Characteristics: ");
257 if (info
->characteristics
& LPAR_CHAR_DEDICATED
)
258 len
+= sprintf(page
+ len
, "Dedicated ");
259 if (info
->characteristics
& LPAR_CHAR_SHARED
)
260 len
+= sprintf(page
+ len
, "Shared ");
261 if (info
->characteristics
& LPAR_CHAR_LIMITED
)
262 len
+= sprintf(page
+ len
, "Limited ");
263 len
+= sprintf(page
+ len
, "\n");
265 len
+= sprintf(page
+ len
, "LPAR Name: %-8.8s\n",
268 len
+= sprintf(page
+ len
, "LPAR Adjustment: %d\n",
271 len
+= sprintf(page
+ len
, "LPAR CPUs Total: %d\n",
273 len
+= sprintf(page
+ len
, "LPAR CPUs Configured: %d\n",
274 info
->cpus_configured
);
275 len
+= sprintf(page
+ len
, "LPAR CPUs Standby: %d\n",
277 len
+= sprintf(page
+ len
, "LPAR CPUs Reserved: %d\n",
278 info
->cpus_reserved
);
279 len
+= sprintf(page
+ len
, "LPAR CPUs Dedicated: %d\n",
280 info
->cpus_dedicated
);
281 len
+= sprintf(page
+ len
, "LPAR CPUs Shared: %d\n",
286 static int stsi_3_2_2(struct sysinfo_3_2_2
*info
, char *page
, int len
)
290 if (stsi(info
, 3, 2, 2) == -ENOSYS
)
292 for (i
= 0; i
< info
->count
; i
++) {
293 EBCASC (info
->vm
[i
].name
, sizeof(info
->vm
[i
].name
));
294 EBCASC (info
->vm
[i
].cpi
, sizeof(info
->vm
[i
].cpi
));
295 len
+= sprintf(page
+ len
, "\n");
296 len
+= sprintf(page
+ len
, "VM%02d Name: %-8.8s\n",
297 i
, info
->vm
[i
].name
);
298 len
+= sprintf(page
+ len
, "VM%02d Control Program: %-16.16s\n",
301 len
+= sprintf(page
+ len
, "VM%02d Adjustment: %d\n",
304 len
+= sprintf(page
+ len
, "VM%02d CPUs Total: %d\n",
305 i
, info
->vm
[i
].cpus_total
);
306 len
+= sprintf(page
+ len
, "VM%02d CPUs Configured: %d\n",
307 i
, info
->vm
[i
].cpus_configured
);
308 len
+= sprintf(page
+ len
, "VM%02d CPUs Standby: %d\n",
309 i
, info
->vm
[i
].cpus_standby
);
310 len
+= sprintf(page
+ len
, "VM%02d CPUs Reserved: %d\n",
311 i
, info
->vm
[i
].cpus_reserved
);
317 static int proc_read_sysinfo(char *page
, char **start
,
318 off_t off
, int count
,
319 int *eof
, void *data
)
321 unsigned long info
= get_zeroed_page (GFP_KERNEL
);
330 len
= stsi_1_1_1((struct sysinfo_1_1_1
*) info
, page
, len
);
333 len
= stsi_1_2_2((struct sysinfo_1_2_2
*) info
, page
, len
);
336 len
= stsi_2_2_2((struct sysinfo_2_2_2
*) info
, page
, len
);
339 len
= stsi_3_2_2((struct sysinfo_3_2_2
*) info
, page
, len
);
345 static __init
int create_proc_sysinfo(void)
347 create_proc_read_entry("sysinfo", 0444, NULL
,
348 proc_read_sysinfo
, NULL
);
352 __initcall(create_proc_sysinfo
);