sysinfo.c 8.7 KB

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