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 static ssize_t
guest_type_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
57 switch (xen_domain_type
) {
66 type
= xen_pvh_domain() ? "PVH" : "HVM";
72 return sprintf(buffer
, "%s\n", type
);
75 HYPERVISOR_ATTR_RO(guest_type
);
77 static int __init
xen_sysfs_guest_type_init(void)
79 return sysfs_create_file(hypervisor_kobj
, &guest_type_attr
.attr
);
82 /* xen version attributes */
83 static ssize_t
major_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
85 int version
= HYPERVISOR_xen_version(XENVER_version
, NULL
);
87 return sprintf(buffer
, "%d\n", version
>> 16);
91 HYPERVISOR_ATTR_RO(major
);
93 static ssize_t
minor_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
95 int version
= HYPERVISOR_xen_version(XENVER_version
, NULL
);
97 return sprintf(buffer
, "%d\n", version
& 0xff);
101 HYPERVISOR_ATTR_RO(minor
);
103 static ssize_t
extra_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
108 extra
= kmalloc(XEN_EXTRAVERSION_LEN
, GFP_KERNEL
);
110 ret
= HYPERVISOR_xen_version(XENVER_extraversion
, extra
);
112 ret
= sprintf(buffer
, "%s\n", extra
);
119 HYPERVISOR_ATTR_RO(extra
);
121 static struct attribute
*version_attrs
[] = {
128 static const struct attribute_group version_group
= {
130 .attrs
= version_attrs
,
133 static int __init
xen_sysfs_version_init(void)
135 return sysfs_create_group(hypervisor_kobj
, &version_group
);
140 static ssize_t
uuid_show_fallback(struct hyp_sysfs_attr
*attr
, char *buffer
)
144 extern int xenstored_ready
;
146 if (!xenstored_ready
)
149 vm
= xenbus_read(XBT_NIL
, "vm", "", NULL
);
152 val
= xenbus_read(XBT_NIL
, vm
, "uuid", NULL
);
156 ret
= sprintf(buffer
, "%s\n", val
);
161 static ssize_t
uuid_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
163 xen_domain_handle_t uuid
;
165 ret
= HYPERVISOR_xen_version(XENVER_guest_handle
, uuid
);
167 return uuid_show_fallback(attr
, buffer
);
168 ret
= sprintf(buffer
, "%pU\n", uuid
);
172 HYPERVISOR_ATTR_RO(uuid
);
174 static int __init
xen_sysfs_uuid_init(void)
176 return sysfs_create_file(hypervisor_kobj
, &uuid_attr
.attr
);
179 /* xen compilation attributes */
181 static ssize_t
compiler_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
184 struct xen_compile_info
*info
;
186 info
= kmalloc(sizeof(struct xen_compile_info
), GFP_KERNEL
);
188 ret
= HYPERVISOR_xen_version(XENVER_compile_info
, info
);
190 ret
= sprintf(buffer
, "%s\n", info
->compiler
);
197 HYPERVISOR_ATTR_RO(compiler
);
199 static ssize_t
compiled_by_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
202 struct xen_compile_info
*info
;
204 info
= kmalloc(sizeof(struct xen_compile_info
), GFP_KERNEL
);
206 ret
= HYPERVISOR_xen_version(XENVER_compile_info
, info
);
208 ret
= sprintf(buffer
, "%s\n", info
->compile_by
);
215 HYPERVISOR_ATTR_RO(compiled_by
);
217 static ssize_t
compile_date_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
220 struct xen_compile_info
*info
;
222 info
= kmalloc(sizeof(struct xen_compile_info
), GFP_KERNEL
);
224 ret
= HYPERVISOR_xen_version(XENVER_compile_info
, info
);
226 ret
= sprintf(buffer
, "%s\n", info
->compile_date
);
233 HYPERVISOR_ATTR_RO(compile_date
);
235 static struct attribute
*xen_compile_attrs
[] = {
237 &compiled_by_attr
.attr
,
238 &compile_date_attr
.attr
,
242 static const struct attribute_group xen_compilation_group
= {
243 .name
= "compilation",
244 .attrs
= xen_compile_attrs
,
247 static int __init
xen_sysfs_compilation_init(void)
249 return sysfs_create_group(hypervisor_kobj
, &xen_compilation_group
);
252 /* xen properties info */
254 static ssize_t
capabilities_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
259 caps
= kmalloc(XEN_CAPABILITIES_INFO_LEN
, GFP_KERNEL
);
261 ret
= HYPERVISOR_xen_version(XENVER_capabilities
, caps
);
263 ret
= sprintf(buffer
, "%s\n", caps
);
270 HYPERVISOR_ATTR_RO(capabilities
);
272 static ssize_t
changeset_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
277 cset
= kmalloc(XEN_CHANGESET_INFO_LEN
, GFP_KERNEL
);
279 ret
= HYPERVISOR_xen_version(XENVER_changeset
, cset
);
281 ret
= sprintf(buffer
, "%s\n", cset
);
288 HYPERVISOR_ATTR_RO(changeset
);
290 static ssize_t
virtual_start_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
293 struct xen_platform_parameters
*parms
;
295 parms
= kmalloc(sizeof(struct xen_platform_parameters
), GFP_KERNEL
);
297 ret
= HYPERVISOR_xen_version(XENVER_platform_parameters
,
300 ret
= sprintf(buffer
, "%"PRI_xen_ulong
"\n",
308 HYPERVISOR_ATTR_RO(virtual_start
);
310 static ssize_t
pagesize_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
314 ret
= HYPERVISOR_xen_version(XENVER_pagesize
, NULL
);
316 ret
= sprintf(buffer
, "%x\n", ret
);
321 HYPERVISOR_ATTR_RO(pagesize
);
323 static ssize_t
xen_feature_show(int index
, char *buffer
)
326 struct xen_feature_info info
;
328 info
.submap_idx
= index
;
329 ret
= HYPERVISOR_xen_version(XENVER_get_features
, &info
);
331 ret
= sprintf(buffer
, "%08x", info
.submap
);
336 static ssize_t
features_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
342 for (i
= XENFEAT_NR_SUBMAPS
-1; i
>= 0; i
--) {
343 int ret
= xen_feature_show(i
, buffer
+ len
);
352 buffer
[len
++] = '\n';
357 HYPERVISOR_ATTR_RO(features
);
359 static ssize_t
buildid_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
362 struct xen_build_id
*buildid
;
364 ret
= HYPERVISOR_xen_version(XENVER_build_id
, NULL
);
367 ret
= sprintf(buffer
, "<denied>");
371 buildid
= kmalloc(sizeof(*buildid
) + ret
, GFP_KERNEL
);
376 ret
= HYPERVISOR_xen_version(XENVER_build_id
, buildid
);
378 ret
= sprintf(buffer
, "%s", buildid
->buf
);
384 HYPERVISOR_ATTR_RO(buildid
);
386 static struct attribute
*xen_properties_attrs
[] = {
387 &capabilities_attr
.attr
,
388 &changeset_attr
.attr
,
389 &virtual_start_attr
.attr
,
396 static const struct attribute_group xen_properties_group
= {
397 .name
= "properties",
398 .attrs
= xen_properties_attrs
,
401 static int __init
xen_sysfs_properties_init(void)
403 return sysfs_create_group(hypervisor_kobj
, &xen_properties_group
);
406 #ifdef CONFIG_XEN_HAVE_VPMU
412 static struct pmu_mode pmu_modes
[] = {
413 {"off", XENPMU_MODE_OFF
},
414 {"self", XENPMU_MODE_SELF
},
415 {"hv", XENPMU_MODE_HV
},
416 {"all", XENPMU_MODE_ALL
}
419 static ssize_t
pmu_mode_store(struct hyp_sysfs_attr
*attr
,
420 const char *buffer
, size_t len
)
423 struct xen_pmu_params xp
;
426 for (i
= 0; i
< ARRAY_SIZE(pmu_modes
); i
++) {
427 if (strncmp(buffer
, pmu_modes
[i
].name
, len
- 1) == 0) {
428 xp
.val
= pmu_modes
[i
].mode
;
433 if (i
== ARRAY_SIZE(pmu_modes
))
436 xp
.version
.maj
= XENPMU_VER_MAJ
;
437 xp
.version
.min
= XENPMU_VER_MIN
;
438 ret
= HYPERVISOR_xenpmu_op(XENPMU_mode_set
, &xp
);
445 static ssize_t
pmu_mode_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
448 struct xen_pmu_params xp
;
452 xp
.version
.maj
= XENPMU_VER_MAJ
;
453 xp
.version
.min
= XENPMU_VER_MIN
;
454 ret
= HYPERVISOR_xenpmu_op(XENPMU_mode_get
, &xp
);
458 mode
= (uint32_t)xp
.val
;
459 for (i
= 0; i
< ARRAY_SIZE(pmu_modes
); i
++) {
460 if (mode
== pmu_modes
[i
].mode
)
461 return sprintf(buffer
, "%s\n", pmu_modes
[i
].name
);
466 HYPERVISOR_ATTR_RW(pmu_mode
);
468 static ssize_t
pmu_features_store(struct hyp_sysfs_attr
*attr
,
469 const char *buffer
, size_t len
)
473 struct xen_pmu_params xp
;
475 ret
= kstrtou32(buffer
, 0, &features
);
480 xp
.version
.maj
= XENPMU_VER_MAJ
;
481 xp
.version
.min
= XENPMU_VER_MIN
;
482 ret
= HYPERVISOR_xenpmu_op(XENPMU_feature_set
, &xp
);
489 static ssize_t
pmu_features_show(struct hyp_sysfs_attr
*attr
, char *buffer
)
492 struct xen_pmu_params xp
;
494 xp
.version
.maj
= XENPMU_VER_MAJ
;
495 xp
.version
.min
= XENPMU_VER_MIN
;
496 ret
= HYPERVISOR_xenpmu_op(XENPMU_feature_get
, &xp
);
500 return sprintf(buffer
, "0x%x\n", (uint32_t)xp
.val
);
502 HYPERVISOR_ATTR_RW(pmu_features
);
504 static struct attribute
*xen_pmu_attrs
[] = {
506 &pmu_features_attr
.attr
,
510 static const struct attribute_group xen_pmu_group
= {
512 .attrs
= xen_pmu_attrs
,
515 static int __init
xen_sysfs_pmu_init(void)
517 return sysfs_create_group(hypervisor_kobj
, &xen_pmu_group
);
521 static int __init
hyper_sysfs_init(void)
528 ret
= xen_sysfs_type_init();
531 ret
= xen_sysfs_guest_type_init();
534 ret
= xen_sysfs_version_init();
537 ret
= xen_sysfs_compilation_init();
540 ret
= xen_sysfs_uuid_init();
543 ret
= xen_sysfs_properties_init();
546 #ifdef CONFIG_XEN_HAVE_VPMU
547 if (xen_initial_domain()) {
548 ret
= xen_sysfs_pmu_init();
550 sysfs_remove_group(hypervisor_kobj
,
551 &xen_properties_group
);
559 sysfs_remove_file(hypervisor_kobj
, &uuid_attr
.attr
);
561 sysfs_remove_group(hypervisor_kobj
, &xen_compilation_group
);
563 sysfs_remove_group(hypervisor_kobj
, &version_group
);
565 sysfs_remove_file(hypervisor_kobj
, &guest_type_attr
.attr
);
567 sysfs_remove_file(hypervisor_kobj
, &type_attr
.attr
);
571 device_initcall(hyper_sysfs_init
);
573 static ssize_t
hyp_sysfs_show(struct kobject
*kobj
,
574 struct attribute
*attr
,
577 struct hyp_sysfs_attr
*hyp_attr
;
578 hyp_attr
= container_of(attr
, struct hyp_sysfs_attr
, attr
);
580 return hyp_attr
->show(hyp_attr
, buffer
);
584 static ssize_t
hyp_sysfs_store(struct kobject
*kobj
,
585 struct attribute
*attr
,
589 struct hyp_sysfs_attr
*hyp_attr
;
590 hyp_attr
= container_of(attr
, struct hyp_sysfs_attr
, attr
);
592 return hyp_attr
->store(hyp_attr
, buffer
, len
);
596 static const struct sysfs_ops hyp_sysfs_ops
= {
597 .show
= hyp_sysfs_show
,
598 .store
= hyp_sysfs_store
,
601 static struct kobj_type hyp_sysfs_kobj_type
= {
602 .sysfs_ops
= &hyp_sysfs_ops
,
605 static int __init
hypervisor_subsys_init(void)
610 hypervisor_kobj
->ktype
= &hyp_sysfs_kobj_type
;
613 device_initcall(hypervisor_subsys_init
);