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/init.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 /* xen version attributes */
54 static ssize_t
major_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
56 int version
= HYPERVISOR_xen_version(XENVER_version
, NULL
);
58 return sprintf(buffer
, "%d\n", version
>> 16);
62 HYPERVISOR_ATTR_RO(major
);
64 static ssize_t
minor_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
66 int version
= HYPERVISOR_xen_version(XENVER_version
, NULL
);
68 return sprintf(buffer
, "%d\n", version
& 0xff);
72 HYPERVISOR_ATTR_RO(minor
);
74 static ssize_t
extra_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
79 extra
= kmalloc(XEN_EXTRAVERSION_LEN
, GFP_KERNEL
);
81 ret
= HYPERVISOR_xen_version(XENVER_extraversion
, extra
);
83 ret
= sprintf(buffer
, "%s\n", extra
);
90 HYPERVISOR_ATTR_RO(extra
);
92 static struct attribute
*version_attrs
[] = {
99 static const struct attribute_group version_group
= {
101 .attrs
= version_attrs
,
104 static int __init
xen_sysfs_version_init(void)
106 return sysfs_create_group(hypervisor_kobj
, &version_group
);
111 static ssize_t
uuid_show_fallback(struct hyp_sysfs_attr
*attr
, char *buffer
)
115 extern int xenstored_ready
;
117 if (!xenstored_ready
)
120 vm
= xenbus_read(XBT_NIL
, "vm", "", NULL
);
123 val
= xenbus_read(XBT_NIL
, vm
, "uuid", NULL
);
127 ret
= sprintf(buffer
, "%s\n", val
);
132 static ssize_t
uuid_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
134 xen_domain_handle_t uuid
;
136 ret
= HYPERVISOR_xen_version(XENVER_guest_handle
, uuid
);
138 return uuid_show_fallback(attr
, buffer
);
139 ret
= sprintf(buffer
, "%pU\n", uuid
);
143 HYPERVISOR_ATTR_RO(uuid
);
145 static int __init
xen_sysfs_uuid_init(void)
147 return sysfs_create_file(hypervisor_kobj
, &uuid_attr
.attr
);
150 /* xen compilation attributes */
152 static ssize_t
compiler_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
155 struct xen_compile_info
*info
;
157 info
= kmalloc(sizeof(struct xen_compile_info
), GFP_KERNEL
);
159 ret
= HYPERVISOR_xen_version(XENVER_compile_info
, info
);
161 ret
= sprintf(buffer
, "%s\n", info
->compiler
);
168 HYPERVISOR_ATTR_RO(compiler
);
170 static ssize_t
compiled_by_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
173 struct xen_compile_info
*info
;
175 info
= kmalloc(sizeof(struct xen_compile_info
), GFP_KERNEL
);
177 ret
= HYPERVISOR_xen_version(XENVER_compile_info
, info
);
179 ret
= sprintf(buffer
, "%s\n", info
->compile_by
);
186 HYPERVISOR_ATTR_RO(compiled_by
);
188 static ssize_t
compile_date_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
191 struct xen_compile_info
*info
;
193 info
= kmalloc(sizeof(struct xen_compile_info
), GFP_KERNEL
);
195 ret
= HYPERVISOR_xen_version(XENVER_compile_info
, info
);
197 ret
= sprintf(buffer
, "%s\n", info
->compile_date
);
204 HYPERVISOR_ATTR_RO(compile_date
);
206 static struct attribute
*xen_compile_attrs
[] = {
208 &compiled_by_attr
.attr
,
209 &compile_date_attr
.attr
,
213 static const struct attribute_group xen_compilation_group
= {
214 .name
= "compilation",
215 .attrs
= xen_compile_attrs
,
218 static int __init
xen_compilation_init(void)
220 return sysfs_create_group(hypervisor_kobj
, &xen_compilation_group
);
223 /* xen properties info */
225 static ssize_t
capabilities_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
230 caps
= kmalloc(XEN_CAPABILITIES_INFO_LEN
, GFP_KERNEL
);
232 ret
= HYPERVISOR_xen_version(XENVER_capabilities
, caps
);
234 ret
= sprintf(buffer
, "%s\n", caps
);
241 HYPERVISOR_ATTR_RO(capabilities
);
243 static ssize_t
changeset_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
248 cset
= kmalloc(XEN_CHANGESET_INFO_LEN
, GFP_KERNEL
);
250 ret
= HYPERVISOR_xen_version(XENVER_changeset
, cset
);
252 ret
= sprintf(buffer
, "%s\n", cset
);
259 HYPERVISOR_ATTR_RO(changeset
);
261 static ssize_t
virtual_start_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
264 struct xen_platform_parameters
*parms
;
266 parms
= kmalloc(sizeof(struct xen_platform_parameters
), GFP_KERNEL
);
268 ret
= HYPERVISOR_xen_version(XENVER_platform_parameters
,
271 ret
= sprintf(buffer
, "%"PRI_xen_ulong
"\n",
279 HYPERVISOR_ATTR_RO(virtual_start
);
281 static ssize_t
pagesize_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
285 ret
= HYPERVISOR_xen_version(XENVER_pagesize
, NULL
);
287 ret
= sprintf(buffer
, "%x\n", ret
);
292 HYPERVISOR_ATTR_RO(pagesize
);
294 static ssize_t
xen_feature_show(int index
, char *buffer
)
297 struct xen_feature_info info
;
299 info
.submap_idx
= index
;
300 ret
= HYPERVISOR_xen_version(XENVER_get_features
, &info
);
302 ret
= sprintf(buffer
, "%08x", info
.submap
);
307 static ssize_t
features_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
313 for (i
= XENFEAT_NR_SUBMAPS
-1; i
>= 0; i
--) {
314 int ret
= xen_feature_show(i
, buffer
+ len
);
323 buffer
[len
++] = '\n';
328 HYPERVISOR_ATTR_RO(features
);
330 static struct attribute
*xen_properties_attrs
[] = {
331 &capabilities_attr
.attr
,
332 &changeset_attr
.attr
,
333 &virtual_start_attr
.attr
,
339 static const struct attribute_group xen_properties_group
= {
340 .name
= "properties",
341 .attrs
= xen_properties_attrs
,
344 static int __init
xen_properties_init(void)
346 return sysfs_create_group(hypervisor_kobj
, &xen_properties_group
);
349 #ifdef CONFIG_XEN_HAVE_VPMU
355 static struct pmu_mode pmu_modes
[] = {
356 {"off", XENPMU_MODE_OFF
},
357 {"self", XENPMU_MODE_SELF
},
358 {"hv", XENPMU_MODE_HV
},
359 {"all", XENPMU_MODE_ALL
}
362 static ssize_t
pmu_mode_store(struct hyp_sysfs_attr
*attr
,
363 const char *buffer
, size_t len
)
366 struct xen_pmu_params xp
;
369 for (i
= 0; i
< ARRAY_SIZE(pmu_modes
); i
++) {
370 if (strncmp(buffer
, pmu_modes
[i
].name
, len
- 1) == 0) {
371 xp
.val
= pmu_modes
[i
].mode
;
376 if (i
== ARRAY_SIZE(pmu_modes
))
379 xp
.version
.maj
= XENPMU_VER_MAJ
;
380 xp
.version
.min
= XENPMU_VER_MIN
;
381 ret
= HYPERVISOR_xenpmu_op(XENPMU_mode_set
, &xp
);
388 static ssize_t
pmu_mode_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
391 struct xen_pmu_params xp
;
395 xp
.version
.maj
= XENPMU_VER_MAJ
;
396 xp
.version
.min
= XENPMU_VER_MIN
;
397 ret
= HYPERVISOR_xenpmu_op(XENPMU_mode_get
, &xp
);
401 mode
= (uint32_t)xp
.val
;
402 for (i
= 0; i
< ARRAY_SIZE(pmu_modes
); i
++) {
403 if (mode
== pmu_modes
[i
].mode
)
404 return sprintf(buffer
, "%s\n", pmu_modes
[i
].name
);
409 HYPERVISOR_ATTR_RW(pmu_mode
);
411 static ssize_t
pmu_features_store(struct hyp_sysfs_attr
*attr
,
412 const char *buffer
, size_t len
)
416 struct xen_pmu_params xp
;
418 ret
= kstrtou32(buffer
, 0, &features
);
423 xp
.version
.maj
= XENPMU_VER_MAJ
;
424 xp
.version
.min
= XENPMU_VER_MIN
;
425 ret
= HYPERVISOR_xenpmu_op(XENPMU_feature_set
, &xp
);
432 static ssize_t
pmu_features_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
435 struct xen_pmu_params xp
;
437 xp
.version
.maj
= XENPMU_VER_MAJ
;
438 xp
.version
.min
= XENPMU_VER_MIN
;
439 ret
= HYPERVISOR_xenpmu_op(XENPMU_feature_get
, &xp
);
443 return sprintf(buffer
, "0x%x\n", (uint32_t)xp
.val
);
445 HYPERVISOR_ATTR_RW(pmu_features
);
447 static struct attribute
*xen_pmu_attrs
[] = {
449 &pmu_features_attr
.attr
,
453 static const struct attribute_group xen_pmu_group
= {
455 .attrs
= xen_pmu_attrs
,
458 static int __init
xen_pmu_init(void)
460 return sysfs_create_group(hypervisor_kobj
, &xen_pmu_group
);
464 static int __init
hyper_sysfs_init(void)
471 ret
= xen_sysfs_type_init();
474 ret
= xen_sysfs_version_init();
477 ret
= xen_compilation_init();
480 ret
= xen_sysfs_uuid_init();
483 ret
= xen_properties_init();
486 #ifdef CONFIG_XEN_HAVE_VPMU
487 if (xen_initial_domain()) {
488 ret
= xen_pmu_init();
490 sysfs_remove_group(hypervisor_kobj
,
491 &xen_properties_group
);
499 sysfs_remove_file(hypervisor_kobj
, &uuid_attr
.attr
);
501 sysfs_remove_group(hypervisor_kobj
, &xen_compilation_group
);
503 sysfs_remove_group(hypervisor_kobj
, &version_group
);
505 sysfs_remove_file(hypervisor_kobj
, &type_attr
.attr
);
509 device_initcall(hyper_sysfs_init
);
511 static ssize_t
hyp_sysfs_show(struct kobject
*kobj
,
512 struct attribute
*attr
,
515 struct hyp_sysfs_attr
*hyp_attr
;
516 hyp_attr
= container_of(attr
, struct hyp_sysfs_attr
, attr
);
518 return hyp_attr
->show(hyp_attr
, buffer
);
522 static ssize_t
hyp_sysfs_store(struct kobject
*kobj
,
523 struct attribute
*attr
,
527 struct hyp_sysfs_attr
*hyp_attr
;
528 hyp_attr
= container_of(attr
, struct hyp_sysfs_attr
, attr
);
530 return hyp_attr
->store(hyp_attr
, buffer
, len
);
534 static const struct sysfs_ops hyp_sysfs_ops
= {
535 .show
= hyp_sysfs_show
,
536 .store
= hyp_sysfs_store
,
539 static struct kobj_type hyp_sysfs_kobj_type
= {
540 .sysfs_ops
= &hyp_sysfs_ops
,
543 static int __init
hypervisor_subsys_init(void)
548 hypervisor_kobj
->ktype
= &hyp_sysfs_kobj_type
;
551 device_initcall(hypervisor_subsys_init
);