2 * copyright (c) 2006 IBM Corporation
3 * Authored by: Mike D. Day <ncmike@us.ibm.com>
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.
10 #include <linux/slab.h>
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/kobject.h>
14 #include <linux/err.h>
16 #include <asm/xen/hypervisor.h>
17 #include <asm/xen/hypercall.h>
20 #include <xen/xenbus.h>
21 #include <xen/interface/xen.h>
22 #include <xen/interface/version.h>
23 #ifdef CONFIG_XEN_HAVE_VPMU
24 #include <xen/interface/xenpmu.h>
27 #define HYPERVISOR_ATTR_RO(_name) \
28 static struct hyp_sysfs_attr _name##_attr = __ATTR_RO(_name)
30 #define HYPERVISOR_ATTR_RW(_name) \
31 static struct hyp_sysfs_attr _name##_attr = \
32 __ATTR(_name, 0644, _name##_show, _name##_store)
34 struct hyp_sysfs_attr
{
35 struct attribute attr
;
36 ssize_t (*show
)(struct hyp_sysfs_attr
*, char *);
37 ssize_t (*store
)(struct hyp_sysfs_attr
*, const char *, size_t);
41 static ssize_t
type_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
43 return sprintf(buffer
, "xen\n");
46 HYPERVISOR_ATTR_RO(type
);
48 static int __init
xen_sysfs_type_init(void)
50 return sysfs_create_file(hypervisor_kobj
, &type_attr
.attr
);
53 static void xen_sysfs_type_destroy(void)
55 sysfs_remove_file(hypervisor_kobj
, &type_attr
.attr
);
58 /* xen version attributes */
59 static ssize_t
major_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
61 int version
= HYPERVISOR_xen_version(XENVER_version
, NULL
);
63 return sprintf(buffer
, "%d\n", version
>> 16);
67 HYPERVISOR_ATTR_RO(major
);
69 static ssize_t
minor_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
71 int version
= HYPERVISOR_xen_version(XENVER_version
, NULL
);
73 return sprintf(buffer
, "%d\n", version
& 0xff);
77 HYPERVISOR_ATTR_RO(minor
);
79 static ssize_t
extra_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
84 extra
= kmalloc(XEN_EXTRAVERSION_LEN
, GFP_KERNEL
);
86 ret
= HYPERVISOR_xen_version(XENVER_extraversion
, extra
);
88 ret
= sprintf(buffer
, "%s\n", extra
);
95 HYPERVISOR_ATTR_RO(extra
);
97 static struct attribute
*version_attrs
[] = {
104 static const struct attribute_group version_group
= {
106 .attrs
= version_attrs
,
109 static int __init
xen_sysfs_version_init(void)
111 return sysfs_create_group(hypervisor_kobj
, &version_group
);
114 static void xen_sysfs_version_destroy(void)
116 sysfs_remove_group(hypervisor_kobj
, &version_group
);
121 static ssize_t
uuid_show_fallback(struct hyp_sysfs_attr
*attr
, char *buffer
)
125 extern int xenstored_ready
;
127 if (!xenstored_ready
)
130 vm
= xenbus_read(XBT_NIL
, "vm", "", NULL
);
133 val
= xenbus_read(XBT_NIL
, vm
, "uuid", NULL
);
137 ret
= sprintf(buffer
, "%s\n", val
);
142 static ssize_t
uuid_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
144 xen_domain_handle_t uuid
;
146 ret
= HYPERVISOR_xen_version(XENVER_guest_handle
, uuid
);
148 return uuid_show_fallback(attr
, buffer
);
149 ret
= sprintf(buffer
, "%pU\n", uuid
);
153 HYPERVISOR_ATTR_RO(uuid
);
155 static int __init
xen_sysfs_uuid_init(void)
157 return sysfs_create_file(hypervisor_kobj
, &uuid_attr
.attr
);
160 static void xen_sysfs_uuid_destroy(void)
162 sysfs_remove_file(hypervisor_kobj
, &uuid_attr
.attr
);
165 /* xen compilation attributes */
167 static ssize_t
compiler_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
170 struct xen_compile_info
*info
;
172 info
= kmalloc(sizeof(struct xen_compile_info
), GFP_KERNEL
);
174 ret
= HYPERVISOR_xen_version(XENVER_compile_info
, info
);
176 ret
= sprintf(buffer
, "%s\n", info
->compiler
);
183 HYPERVISOR_ATTR_RO(compiler
);
185 static ssize_t
compiled_by_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
188 struct xen_compile_info
*info
;
190 info
= kmalloc(sizeof(struct xen_compile_info
), GFP_KERNEL
);
192 ret
= HYPERVISOR_xen_version(XENVER_compile_info
, info
);
194 ret
= sprintf(buffer
, "%s\n", info
->compile_by
);
201 HYPERVISOR_ATTR_RO(compiled_by
);
203 static ssize_t
compile_date_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
206 struct xen_compile_info
*info
;
208 info
= kmalloc(sizeof(struct xen_compile_info
), GFP_KERNEL
);
210 ret
= HYPERVISOR_xen_version(XENVER_compile_info
, info
);
212 ret
= sprintf(buffer
, "%s\n", info
->compile_date
);
219 HYPERVISOR_ATTR_RO(compile_date
);
221 static struct attribute
*xen_compile_attrs
[] = {
223 &compiled_by_attr
.attr
,
224 &compile_date_attr
.attr
,
228 static const struct attribute_group xen_compilation_group
= {
229 .name
= "compilation",
230 .attrs
= xen_compile_attrs
,
233 static int __init
xen_compilation_init(void)
235 return sysfs_create_group(hypervisor_kobj
, &xen_compilation_group
);
238 static void xen_compilation_destroy(void)
240 sysfs_remove_group(hypervisor_kobj
, &xen_compilation_group
);
243 /* xen properties info */
245 static ssize_t
capabilities_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
250 caps
= kmalloc(XEN_CAPABILITIES_INFO_LEN
, GFP_KERNEL
);
252 ret
= HYPERVISOR_xen_version(XENVER_capabilities
, caps
);
254 ret
= sprintf(buffer
, "%s\n", caps
);
261 HYPERVISOR_ATTR_RO(capabilities
);
263 static ssize_t
changeset_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
268 cset
= kmalloc(XEN_CHANGESET_INFO_LEN
, GFP_KERNEL
);
270 ret
= HYPERVISOR_xen_version(XENVER_changeset
, cset
);
272 ret
= sprintf(buffer
, "%s\n", cset
);
279 HYPERVISOR_ATTR_RO(changeset
);
281 static ssize_t
virtual_start_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
284 struct xen_platform_parameters
*parms
;
286 parms
= kmalloc(sizeof(struct xen_platform_parameters
), GFP_KERNEL
);
288 ret
= HYPERVISOR_xen_version(XENVER_platform_parameters
,
291 ret
= sprintf(buffer
, "%"PRI_xen_ulong
"\n",
299 HYPERVISOR_ATTR_RO(virtual_start
);
301 static ssize_t
pagesize_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
305 ret
= HYPERVISOR_xen_version(XENVER_pagesize
, NULL
);
307 ret
= sprintf(buffer
, "%x\n", ret
);
312 HYPERVISOR_ATTR_RO(pagesize
);
314 static ssize_t
xen_feature_show(int index
, char *buffer
)
317 struct xen_feature_info info
;
319 info
.submap_idx
= index
;
320 ret
= HYPERVISOR_xen_version(XENVER_get_features
, &info
);
322 ret
= sprintf(buffer
, "%08x", info
.submap
);
327 static ssize_t
features_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
333 for (i
= XENFEAT_NR_SUBMAPS
-1; i
>= 0; i
--) {
334 int ret
= xen_feature_show(i
, buffer
+ len
);
343 buffer
[len
++] = '\n';
348 HYPERVISOR_ATTR_RO(features
);
350 static struct attribute
*xen_properties_attrs
[] = {
351 &capabilities_attr
.attr
,
352 &changeset_attr
.attr
,
353 &virtual_start_attr
.attr
,
359 static const struct attribute_group xen_properties_group
= {
360 .name
= "properties",
361 .attrs
= xen_properties_attrs
,
364 static int __init
xen_properties_init(void)
366 return sysfs_create_group(hypervisor_kobj
, &xen_properties_group
);
369 static void xen_properties_destroy(void)
371 sysfs_remove_group(hypervisor_kobj
, &xen_properties_group
);
374 #ifdef CONFIG_XEN_HAVE_VPMU
380 static struct pmu_mode pmu_modes
[] = {
381 {"off", XENPMU_MODE_OFF
},
382 {"self", XENPMU_MODE_SELF
},
383 {"hv", XENPMU_MODE_HV
},
384 {"all", XENPMU_MODE_ALL
}
387 static ssize_t
pmu_mode_store(struct hyp_sysfs_attr
*attr
,
388 const char *buffer
, size_t len
)
391 struct xen_pmu_params xp
;
394 for (i
= 0; i
< ARRAY_SIZE(pmu_modes
); i
++) {
395 if (strncmp(buffer
, pmu_modes
[i
].name
, len
- 1) == 0) {
396 xp
.val
= pmu_modes
[i
].mode
;
401 if (i
== ARRAY_SIZE(pmu_modes
))
404 xp
.version
.maj
= XENPMU_VER_MAJ
;
405 xp
.version
.min
= XENPMU_VER_MIN
;
406 ret
= HYPERVISOR_xenpmu_op(XENPMU_mode_set
, &xp
);
413 static ssize_t
pmu_mode_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
416 struct xen_pmu_params xp
;
420 xp
.version
.maj
= XENPMU_VER_MAJ
;
421 xp
.version
.min
= XENPMU_VER_MIN
;
422 ret
= HYPERVISOR_xenpmu_op(XENPMU_mode_get
, &xp
);
426 mode
= (uint32_t)xp
.val
;
427 for (i
= 0; i
< ARRAY_SIZE(pmu_modes
); i
++) {
428 if (mode
== pmu_modes
[i
].mode
)
429 return sprintf(buffer
, "%s\n", pmu_modes
[i
].name
);
434 HYPERVISOR_ATTR_RW(pmu_mode
);
436 static ssize_t
pmu_features_store(struct hyp_sysfs_attr
*attr
,
437 const char *buffer
, size_t len
)
441 struct xen_pmu_params xp
;
443 ret
= kstrtou32(buffer
, 0, &features
);
448 xp
.version
.maj
= XENPMU_VER_MAJ
;
449 xp
.version
.min
= XENPMU_VER_MIN
;
450 ret
= HYPERVISOR_xenpmu_op(XENPMU_feature_set
, &xp
);
457 static ssize_t
pmu_features_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
460 struct xen_pmu_params xp
;
462 xp
.version
.maj
= XENPMU_VER_MAJ
;
463 xp
.version
.min
= XENPMU_VER_MIN
;
464 ret
= HYPERVISOR_xenpmu_op(XENPMU_feature_get
, &xp
);
468 return sprintf(buffer
, "0x%x\n", (uint32_t)xp
.val
);
470 HYPERVISOR_ATTR_RW(pmu_features
);
472 static struct attribute
*xen_pmu_attrs
[] = {
474 &pmu_features_attr
.attr
,
478 static const struct attribute_group xen_pmu_group
= {
480 .attrs
= xen_pmu_attrs
,
483 static int __init
xen_pmu_init(void)
485 return sysfs_create_group(hypervisor_kobj
, &xen_pmu_group
);
488 static void xen_pmu_destroy(void)
490 sysfs_remove_group(hypervisor_kobj
, &xen_pmu_group
);
494 static int __init
hyper_sysfs_init(void)
501 ret
= xen_sysfs_type_init();
504 ret
= xen_sysfs_version_init();
507 ret
= xen_compilation_init();
510 ret
= xen_sysfs_uuid_init();
513 ret
= xen_properties_init();
516 #ifdef CONFIG_XEN_HAVE_VPMU
517 if (xen_initial_domain()) {
518 ret
= xen_pmu_init();
520 xen_properties_destroy();
528 xen_sysfs_uuid_destroy();
530 xen_compilation_destroy();
532 xen_sysfs_version_destroy();
534 xen_sysfs_type_destroy();
539 static void __exit
hyper_sysfs_exit(void)
541 #ifdef CONFIG_XEN_HAVE_VPMU
544 xen_properties_destroy();
545 xen_compilation_destroy();
546 xen_sysfs_uuid_destroy();
547 xen_sysfs_version_destroy();
548 xen_sysfs_type_destroy();
551 module_init(hyper_sysfs_init
);
552 module_exit(hyper_sysfs_exit
);
554 static ssize_t
hyp_sysfs_show(struct kobject
*kobj
,
555 struct attribute
*attr
,
558 struct hyp_sysfs_attr
*hyp_attr
;
559 hyp_attr
= container_of(attr
, struct hyp_sysfs_attr
, attr
);
561 return hyp_attr
->show(hyp_attr
, buffer
);
565 static ssize_t
hyp_sysfs_store(struct kobject
*kobj
,
566 struct attribute
*attr
,
570 struct hyp_sysfs_attr
*hyp_attr
;
571 hyp_attr
= container_of(attr
, struct hyp_sysfs_attr
, attr
);
573 return hyp_attr
->store(hyp_attr
, buffer
, len
);
577 static const struct sysfs_ops hyp_sysfs_ops
= {
578 .show
= hyp_sysfs_show
,
579 .store
= hyp_sysfs_store
,
582 static struct kobj_type hyp_sysfs_kobj_type
= {
583 .sysfs_ops
= &hyp_sysfs_ops
,
586 static int __init
hypervisor_subsys_init(void)
591 hypervisor_kobj
->ktype
= &hyp_sysfs_kobj_type
;
594 device_initcall(hypervisor_subsys_init
);