sys-hypervisor.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. /*
  2. * copyright (c) 2006 IBM Corporation
  3. * Authored by: Mike D. Day <ncmike@us.ibm.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. */
  9. #include <linux/kernel.h>
  10. #include <linux/module.h>
  11. #include <linux/kobject.h>
  12. #include <asm/xen/hypervisor.h>
  13. #include <asm/xen/hypercall.h>
  14. #include <xen/xen.h>
  15. #include <xen/xenbus.h>
  16. #include <xen/interface/xen.h>
  17. #include <xen/interface/version.h>
  18. #define HYPERVISOR_ATTR_RO(_name) \
  19. static struct hyp_sysfs_attr _name##_attr = __ATTR_RO(_name)
  20. #define HYPERVISOR_ATTR_RW(_name) \
  21. static struct hyp_sysfs_attr _name##_attr = \
  22. __ATTR(_name, 0644, _name##_show, _name##_store)
  23. struct hyp_sysfs_attr {
  24. struct attribute attr;
  25. ssize_t (*show)(struct hyp_sysfs_attr *, char *);
  26. ssize_t (*store)(struct hyp_sysfs_attr *, const char *, size_t);
  27. void *hyp_attr_data;
  28. };
  29. static ssize_t type_show(struct hyp_sysfs_attr *attr, char *buffer)
  30. {
  31. return sprintf(buffer, "xen\n");
  32. }
  33. HYPERVISOR_ATTR_RO(type);
  34. static int __init xen_sysfs_type_init(void)
  35. {
  36. return sysfs_create_file(hypervisor_kobj, &type_attr.attr);
  37. }
  38. static void xen_sysfs_type_destroy(void)
  39. {
  40. sysfs_remove_file(hypervisor_kobj, &type_attr.attr);
  41. }
  42. /* xen version attributes */
  43. static ssize_t major_show(struct hyp_sysfs_attr *attr, char *buffer)
  44. {
  45. int version = HYPERVISOR_xen_version(XENVER_version, NULL);
  46. if (version)
  47. return sprintf(buffer, "%d\n", version >> 16);
  48. return -ENODEV;
  49. }
  50. HYPERVISOR_ATTR_RO(major);
  51. static ssize_t minor_show(struct hyp_sysfs_attr *attr, char *buffer)
  52. {
  53. int version = HYPERVISOR_xen_version(XENVER_version, NULL);
  54. if (version)
  55. return sprintf(buffer, "%d\n", version & 0xff);
  56. return -ENODEV;
  57. }
  58. HYPERVISOR_ATTR_RO(minor);
  59. static ssize_t extra_show(struct hyp_sysfs_attr *attr, char *buffer)
  60. {
  61. int ret = -ENOMEM;
  62. char *extra;
  63. extra = kmalloc(XEN_EXTRAVERSION_LEN, GFP_KERNEL);
  64. if (extra) {
  65. ret = HYPERVISOR_xen_version(XENVER_extraversion, extra);
  66. if (!ret)
  67. ret = sprintf(buffer, "%s\n", extra);
  68. kfree(extra);
  69. }
  70. return ret;
  71. }
  72. HYPERVISOR_ATTR_RO(extra);
  73. static struct attribute *version_attrs[] = {
  74. &major_attr.attr,
  75. &minor_attr.attr,
  76. &extra_attr.attr,
  77. NULL
  78. };
  79. static struct attribute_group version_group = {
  80. .name = "version",
  81. .attrs = version_attrs,
  82. };
  83. static int __init xen_sysfs_version_init(void)
  84. {
  85. return sysfs_create_group(hypervisor_kobj, &version_group);
  86. }
  87. static void xen_sysfs_version_destroy(void)
  88. {
  89. sysfs_remove_group(hypervisor_kobj, &version_group);
  90. }
  91. /* UUID */
  92. static ssize_t uuid_show(struct hyp_sysfs_attr *attr, char *buffer)
  93. {
  94. char *vm, *val;
  95. int ret;
  96. extern int xenstored_ready;
  97. if (!xenstored_ready)
  98. return -EBUSY;
  99. vm = xenbus_read(XBT_NIL, "vm", "", NULL);
  100. if (IS_ERR(vm))
  101. return PTR_ERR(vm);
  102. val = xenbus_read(XBT_NIL, vm, "uuid", NULL);
  103. kfree(vm);
  104. if (IS_ERR(val))
  105. return PTR_ERR(val);
  106. ret = sprintf(buffer, "%s\n", val);
  107. kfree(val);
  108. return ret;
  109. }
  110. HYPERVISOR_ATTR_RO(uuid);
  111. static int __init xen_sysfs_uuid_init(void)
  112. {
  113. return sysfs_create_file(hypervisor_kobj, &uuid_attr.attr);
  114. }
  115. static void xen_sysfs_uuid_destroy(void)
  116. {
  117. sysfs_remove_file(hypervisor_kobj, &uuid_attr.attr);
  118. }
  119. /* xen compilation attributes */
  120. static ssize_t compiler_show(struct hyp_sysfs_attr *attr, char *buffer)
  121. {
  122. int ret = -ENOMEM;
  123. struct xen_compile_info *info;
  124. info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL);
  125. if (info) {
  126. ret = HYPERVISOR_xen_version(XENVER_compile_info, info);
  127. if (!ret)
  128. ret = sprintf(buffer, "%s\n", info->compiler);
  129. kfree(info);
  130. }
  131. return ret;
  132. }
  133. HYPERVISOR_ATTR_RO(compiler);
  134. static ssize_t compiled_by_show(struct hyp_sysfs_attr *attr, char *buffer)
  135. {
  136. int ret = -ENOMEM;
  137. struct xen_compile_info *info;
  138. info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL);
  139. if (info) {
  140. ret = HYPERVISOR_xen_version(XENVER_compile_info, info);
  141. if (!ret)
  142. ret = sprintf(buffer, "%s\n", info->compile_by);
  143. kfree(info);
  144. }
  145. return ret;
  146. }
  147. HYPERVISOR_ATTR_RO(compiled_by);
  148. static ssize_t compile_date_show(struct hyp_sysfs_attr *attr, char *buffer)
  149. {
  150. int ret = -ENOMEM;
  151. struct xen_compile_info *info;
  152. info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL);
  153. if (info) {
  154. ret = HYPERVISOR_xen_version(XENVER_compile_info, info);
  155. if (!ret)
  156. ret = sprintf(buffer, "%s\n", info->compile_date);
  157. kfree(info);
  158. }
  159. return ret;
  160. }
  161. HYPERVISOR_ATTR_RO(compile_date);
  162. static struct attribute *xen_compile_attrs[] = {
  163. &compiler_attr.attr,
  164. &compiled_by_attr.attr,
  165. &compile_date_attr.attr,
  166. NULL
  167. };
  168. static struct attribute_group xen_compilation_group = {
  169. .name = "compilation",
  170. .attrs = xen_compile_attrs,
  171. };
  172. int __init static xen_compilation_init(void)
  173. {
  174. return sysfs_create_group(hypervisor_kobj, &xen_compilation_group);
  175. }
  176. static void xen_compilation_destroy(void)
  177. {
  178. sysfs_remove_group(hypervisor_kobj, &xen_compilation_group);
  179. }
  180. /* xen properties info */
  181. static ssize_t capabilities_show(struct hyp_sysfs_attr *attr, char *buffer)
  182. {
  183. int ret = -ENOMEM;
  184. char *caps;
  185. caps = kmalloc(XEN_CAPABILITIES_INFO_LEN, GFP_KERNEL);
  186. if (caps) {
  187. ret = HYPERVISOR_xen_version(XENVER_capabilities, caps);
  188. if (!ret)
  189. ret = sprintf(buffer, "%s\n", caps);
  190. kfree(caps);
  191. }
  192. return ret;
  193. }
  194. HYPERVISOR_ATTR_RO(capabilities);
  195. static ssize_t changeset_show(struct hyp_sysfs_attr *attr, char *buffer)
  196. {
  197. int ret = -ENOMEM;
  198. char *cset;
  199. cset = kmalloc(XEN_CHANGESET_INFO_LEN, GFP_KERNEL);
  200. if (cset) {
  201. ret = HYPERVISOR_xen_version(XENVER_changeset, cset);
  202. if (!ret)
  203. ret = sprintf(buffer, "%s\n", cset);
  204. kfree(cset);
  205. }
  206. return ret;
  207. }
  208. HYPERVISOR_ATTR_RO(changeset);
  209. static ssize_t virtual_start_show(struct hyp_sysfs_attr *attr, char *buffer)
  210. {
  211. int ret = -ENOMEM;
  212. struct xen_platform_parameters *parms;
  213. parms = kmalloc(sizeof(struct xen_platform_parameters), GFP_KERNEL);
  214. if (parms) {
  215. ret = HYPERVISOR_xen_version(XENVER_platform_parameters,
  216. parms);
  217. if (!ret)
  218. ret = sprintf(buffer, "%lx\n", parms->virt_start);
  219. kfree(parms);
  220. }
  221. return ret;
  222. }
  223. HYPERVISOR_ATTR_RO(virtual_start);
  224. static ssize_t pagesize_show(struct hyp_sysfs_attr *attr, char *buffer)
  225. {
  226. int ret;
  227. ret = HYPERVISOR_xen_version(XENVER_pagesize, NULL);
  228. if (ret > 0)
  229. ret = sprintf(buffer, "%x\n", ret);
  230. return ret;
  231. }
  232. HYPERVISOR_ATTR_RO(pagesize);
  233. static ssize_t xen_feature_show(int index, char *buffer)
  234. {
  235. ssize_t ret;
  236. struct xen_feature_info info;
  237. info.submap_idx = index;
  238. ret = HYPERVISOR_xen_version(XENVER_get_features, &info);
  239. if (!ret)
  240. ret = sprintf(buffer, "%08x", info.submap);
  241. return ret;
  242. }
  243. static ssize_t features_show(struct hyp_sysfs_attr *attr, char *buffer)
  244. {
  245. ssize_t len;
  246. int i;
  247. len = 0;
  248. for (i = XENFEAT_NR_SUBMAPS-1; i >= 0; i--) {
  249. int ret = xen_feature_show(i, buffer + len);
  250. if (ret < 0) {
  251. if (len == 0)
  252. len = ret;
  253. break;
  254. }
  255. len += ret;
  256. }
  257. if (len > 0)
  258. buffer[len++] = '\n';
  259. return len;
  260. }
  261. HYPERVISOR_ATTR_RO(features);
  262. static struct attribute *xen_properties_attrs[] = {
  263. &capabilities_attr.attr,
  264. &changeset_attr.attr,
  265. &virtual_start_attr.attr,
  266. &pagesize_attr.attr,
  267. &features_attr.attr,
  268. NULL
  269. };
  270. static struct attribute_group xen_properties_group = {
  271. .name = "properties",
  272. .attrs = xen_properties_attrs,
  273. };
  274. static int __init xen_properties_init(void)
  275. {
  276. return sysfs_create_group(hypervisor_kobj, &xen_properties_group);
  277. }
  278. static void xen_properties_destroy(void)
  279. {
  280. sysfs_remove_group(hypervisor_kobj, &xen_properties_group);
  281. }
  282. static int __init hyper_sysfs_init(void)
  283. {
  284. int ret;
  285. if (!xen_domain())
  286. return -ENODEV;
  287. ret = xen_sysfs_type_init();
  288. if (ret)
  289. goto out;
  290. ret = xen_sysfs_version_init();
  291. if (ret)
  292. goto version_out;
  293. ret = xen_compilation_init();
  294. if (ret)
  295. goto comp_out;
  296. ret = xen_sysfs_uuid_init();
  297. if (ret)
  298. goto uuid_out;
  299. ret = xen_properties_init();
  300. if (ret)
  301. goto prop_out;
  302. goto out;
  303. prop_out:
  304. xen_sysfs_uuid_destroy();
  305. uuid_out:
  306. xen_compilation_destroy();
  307. comp_out:
  308. xen_sysfs_version_destroy();
  309. version_out:
  310. xen_sysfs_type_destroy();
  311. out:
  312. return ret;
  313. }
  314. static void __exit hyper_sysfs_exit(void)
  315. {
  316. xen_properties_destroy();
  317. xen_compilation_destroy();
  318. xen_sysfs_uuid_destroy();
  319. xen_sysfs_version_destroy();
  320. xen_sysfs_type_destroy();
  321. }
  322. module_init(hyper_sysfs_init);
  323. module_exit(hyper_sysfs_exit);
  324. static ssize_t hyp_sysfs_show(struct kobject *kobj,
  325. struct attribute *attr,
  326. char *buffer)
  327. {
  328. struct hyp_sysfs_attr *hyp_attr;
  329. hyp_attr = container_of(attr, struct hyp_sysfs_attr, attr);
  330. if (hyp_attr->show)
  331. return hyp_attr->show(hyp_attr, buffer);
  332. return 0;
  333. }
  334. static ssize_t hyp_sysfs_store(struct kobject *kobj,
  335. struct attribute *attr,
  336. const char *buffer,
  337. size_t len)
  338. {
  339. struct hyp_sysfs_attr *hyp_attr;
  340. hyp_attr = container_of(attr, struct hyp_sysfs_attr, attr);
  341. if (hyp_attr->store)
  342. return hyp_attr->store(hyp_attr, buffer, len);
  343. return 0;
  344. }
  345. static struct sysfs_ops hyp_sysfs_ops = {
  346. .show = hyp_sysfs_show,
  347. .store = hyp_sysfs_store,
  348. };
  349. static struct kobj_type hyp_sysfs_kobj_type = {
  350. .sysfs_ops = &hyp_sysfs_ops,
  351. };
  352. static int __init hypervisor_subsys_init(void)
  353. {
  354. if (!xen_domain())
  355. return -ENODEV;
  356. hypervisor_kobj->ktype = &hyp_sysfs_kobj_type;
  357. return 0;
  358. }
  359. device_initcall(hypervisor_subsys_init);