Commit cff7e81b3dd7c25cd2248cd7a04c5764552d5d55

Authored by Jeremy Fitzhardinge
1 parent 6d02c42698

xen: add /sys/hypervisor support

Adds support for Xen info under /sys/hypervisor.  Taken from Novell 2.6.27
backport tree.

Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>

Showing 4 changed files with 490 additions and 1 deletions Side-by-side Diff

... ... @@ -40,4 +40,15 @@
40 40 the compatibilty mount point /proc/xen if it is running on
41 41 a xen platform.
42 42 If in doubt, say yes.
  43 +
  44 +config XEN_SYS_HYPERVISOR
  45 + bool "Create xen entries under /sys/hypervisor"
  46 + depends on XEN && SYSFS
  47 + select SYS_HYPERVISOR
  48 + default y
  49 + help
  50 + Create entries under /sys/hypervisor describing the Xen
  51 + hypervisor environment. When running native or in another
  52 + virtual environment, /sys/hypervisor will still be present,
  53 + but will have no xen contents.
drivers/xen/Makefile
... ... @@ -5,4 +5,5 @@
5 5 obj-$(CONFIG_XEN_XENCOMM) += xencomm.o
6 6 obj-$(CONFIG_XEN_BALLOON) += balloon.o
7 7 obj-$(CONFIG_XENFS) += xenfs/
  8 +obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o
drivers/xen/sys-hypervisor.c
  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 +
  10 +#include <linux/kernel.h>
  11 +#include <linux/module.h>
  12 +#include <linux/kobject.h>
  13 +
  14 +#include <asm/xen/hypervisor.h>
  15 +#include <asm/xen/hypercall.h>
  16 +
  17 +#include <xen/xenbus.h>
  18 +#include <xen/interface/xen.h>
  19 +#include <xen/interface/version.h>
  20 +
  21 +#define HYPERVISOR_ATTR_RO(_name) \
  22 +static struct hyp_sysfs_attr _name##_attr = __ATTR_RO(_name)
  23 +
  24 +#define HYPERVISOR_ATTR_RW(_name) \
  25 +static struct hyp_sysfs_attr _name##_attr = \
  26 + __ATTR(_name, 0644, _name##_show, _name##_store)
  27 +
  28 +struct hyp_sysfs_attr {
  29 + struct attribute attr;
  30 + ssize_t (*show)(struct hyp_sysfs_attr *, char *);
  31 + ssize_t (*store)(struct hyp_sysfs_attr *, const char *, size_t);
  32 + void *hyp_attr_data;
  33 +};
  34 +
  35 +static ssize_t type_show(struct hyp_sysfs_attr *attr, char *buffer)
  36 +{
  37 + return sprintf(buffer, "xen\n");
  38 +}
  39 +
  40 +HYPERVISOR_ATTR_RO(type);
  41 +
  42 +static int __init xen_sysfs_type_init(void)
  43 +{
  44 + return sysfs_create_file(hypervisor_kobj, &type_attr.attr);
  45 +}
  46 +
  47 +static void xen_sysfs_type_destroy(void)
  48 +{
  49 + sysfs_remove_file(hypervisor_kobj, &type_attr.attr);
  50 +}
  51 +
  52 +/* xen version attributes */
  53 +static ssize_t major_show(struct hyp_sysfs_attr *attr, char *buffer)
  54 +{
  55 + int version = HYPERVISOR_xen_version(XENVER_version, NULL);
  56 + if (version)
  57 + return sprintf(buffer, "%d\n", version >> 16);
  58 + return -ENODEV;
  59 +}
  60 +
  61 +HYPERVISOR_ATTR_RO(major);
  62 +
  63 +static ssize_t minor_show(struct hyp_sysfs_attr *attr, char *buffer)
  64 +{
  65 + int version = HYPERVISOR_xen_version(XENVER_version, NULL);
  66 + if (version)
  67 + return sprintf(buffer, "%d\n", version & 0xff);
  68 + return -ENODEV;
  69 +}
  70 +
  71 +HYPERVISOR_ATTR_RO(minor);
  72 +
  73 +static ssize_t extra_show(struct hyp_sysfs_attr *attr, char *buffer)
  74 +{
  75 + int ret = -ENOMEM;
  76 + char *extra;
  77 +
  78 + extra = kmalloc(XEN_EXTRAVERSION_LEN, GFP_KERNEL);
  79 + if (extra) {
  80 + ret = HYPERVISOR_xen_version(XENVER_extraversion, extra);
  81 + if (!ret)
  82 + ret = sprintf(buffer, "%s\n", extra);
  83 + kfree(extra);
  84 + }
  85 +
  86 + return ret;
  87 +}
  88 +
  89 +HYPERVISOR_ATTR_RO(extra);
  90 +
  91 +static struct attribute *version_attrs[] = {
  92 + &major_attr.attr,
  93 + &minor_attr.attr,
  94 + &extra_attr.attr,
  95 + NULL
  96 +};
  97 +
  98 +static struct attribute_group version_group = {
  99 + .name = "version",
  100 + .attrs = version_attrs,
  101 +};
  102 +
  103 +static int __init xen_sysfs_version_init(void)
  104 +{
  105 + return sysfs_create_group(hypervisor_kobj, &version_group);
  106 +}
  107 +
  108 +static void xen_sysfs_version_destroy(void)
  109 +{
  110 + sysfs_remove_group(hypervisor_kobj, &version_group);
  111 +}
  112 +
  113 +/* UUID */
  114 +
  115 +static ssize_t uuid_show(struct hyp_sysfs_attr *attr, char *buffer)
  116 +{
  117 + char *vm, *val;
  118 + int ret;
  119 + extern int xenstored_ready;
  120 +
  121 + if (!xenstored_ready)
  122 + return -EBUSY;
  123 +
  124 + vm = xenbus_read(XBT_NIL, "vm", "", NULL);
  125 + if (IS_ERR(vm))
  126 + return PTR_ERR(vm);
  127 + val = xenbus_read(XBT_NIL, vm, "uuid", NULL);
  128 + kfree(vm);
  129 + if (IS_ERR(val))
  130 + return PTR_ERR(val);
  131 + ret = sprintf(buffer, "%s\n", val);
  132 + kfree(val);
  133 + return ret;
  134 +}
  135 +
  136 +HYPERVISOR_ATTR_RO(uuid);
  137 +
  138 +static int __init xen_sysfs_uuid_init(void)
  139 +{
  140 + return sysfs_create_file(hypervisor_kobj, &uuid_attr.attr);
  141 +}
  142 +
  143 +static void xen_sysfs_uuid_destroy(void)
  144 +{
  145 + sysfs_remove_file(hypervisor_kobj, &uuid_attr.attr);
  146 +}
  147 +
  148 +/* xen compilation attributes */
  149 +
  150 +static ssize_t compiler_show(struct hyp_sysfs_attr *attr, char *buffer)
  151 +{
  152 + int ret = -ENOMEM;
  153 + struct xen_compile_info *info;
  154 +
  155 + info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL);
  156 + if (info) {
  157 + ret = HYPERVISOR_xen_version(XENVER_compile_info, info);
  158 + if (!ret)
  159 + ret = sprintf(buffer, "%s\n", info->compiler);
  160 + kfree(info);
  161 + }
  162 +
  163 + return ret;
  164 +}
  165 +
  166 +HYPERVISOR_ATTR_RO(compiler);
  167 +
  168 +static ssize_t compiled_by_show(struct hyp_sysfs_attr *attr, char *buffer)
  169 +{
  170 + int ret = -ENOMEM;
  171 + struct xen_compile_info *info;
  172 +
  173 + info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL);
  174 + if (info) {
  175 + ret = HYPERVISOR_xen_version(XENVER_compile_info, info);
  176 + if (!ret)
  177 + ret = sprintf(buffer, "%s\n", info->compile_by);
  178 + kfree(info);
  179 + }
  180 +
  181 + return ret;
  182 +}
  183 +
  184 +HYPERVISOR_ATTR_RO(compiled_by);
  185 +
  186 +static ssize_t compile_date_show(struct hyp_sysfs_attr *attr, char *buffer)
  187 +{
  188 + int ret = -ENOMEM;
  189 + struct xen_compile_info *info;
  190 +
  191 + info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL);
  192 + if (info) {
  193 + ret = HYPERVISOR_xen_version(XENVER_compile_info, info);
  194 + if (!ret)
  195 + ret = sprintf(buffer, "%s\n", info->compile_date);
  196 + kfree(info);
  197 + }
  198 +
  199 + return ret;
  200 +}
  201 +
  202 +HYPERVISOR_ATTR_RO(compile_date);
  203 +
  204 +static struct attribute *xen_compile_attrs[] = {
  205 + &compiler_attr.attr,
  206 + &compiled_by_attr.attr,
  207 + &compile_date_attr.attr,
  208 + NULL
  209 +};
  210 +
  211 +static struct attribute_group xen_compilation_group = {
  212 + .name = "compilation",
  213 + .attrs = xen_compile_attrs,
  214 +};
  215 +
  216 +int __init static xen_compilation_init(void)
  217 +{
  218 + return sysfs_create_group(hypervisor_kobj, &xen_compilation_group);
  219 +}
  220 +
  221 +static void xen_compilation_destroy(void)
  222 +{
  223 + sysfs_remove_group(hypervisor_kobj, &xen_compilation_group);
  224 +}
  225 +
  226 +/* xen properties info */
  227 +
  228 +static ssize_t capabilities_show(struct hyp_sysfs_attr *attr, char *buffer)
  229 +{
  230 + int ret = -ENOMEM;
  231 + char *caps;
  232 +
  233 + caps = kmalloc(XEN_CAPABILITIES_INFO_LEN, GFP_KERNEL);
  234 + if (caps) {
  235 + ret = HYPERVISOR_xen_version(XENVER_capabilities, caps);
  236 + if (!ret)
  237 + ret = sprintf(buffer, "%s\n", caps);
  238 + kfree(caps);
  239 + }
  240 +
  241 + return ret;
  242 +}
  243 +
  244 +HYPERVISOR_ATTR_RO(capabilities);
  245 +
  246 +static ssize_t changeset_show(struct hyp_sysfs_attr *attr, char *buffer)
  247 +{
  248 + int ret = -ENOMEM;
  249 + char *cset;
  250 +
  251 + cset = kmalloc(XEN_CHANGESET_INFO_LEN, GFP_KERNEL);
  252 + if (cset) {
  253 + ret = HYPERVISOR_xen_version(XENVER_changeset, cset);
  254 + if (!ret)
  255 + ret = sprintf(buffer, "%s\n", cset);
  256 + kfree(cset);
  257 + }
  258 +
  259 + return ret;
  260 +}
  261 +
  262 +HYPERVISOR_ATTR_RO(changeset);
  263 +
  264 +static ssize_t virtual_start_show(struct hyp_sysfs_attr *attr, char *buffer)
  265 +{
  266 + int ret = -ENOMEM;
  267 + struct xen_platform_parameters *parms;
  268 +
  269 + parms = kmalloc(sizeof(struct xen_platform_parameters), GFP_KERNEL);
  270 + if (parms) {
  271 + ret = HYPERVISOR_xen_version(XENVER_platform_parameters,
  272 + parms);
  273 + if (!ret)
  274 + ret = sprintf(buffer, "%lx\n", parms->virt_start);
  275 + kfree(parms);
  276 + }
  277 +
  278 + return ret;
  279 +}
  280 +
  281 +HYPERVISOR_ATTR_RO(virtual_start);
  282 +
  283 +static ssize_t pagesize_show(struct hyp_sysfs_attr *attr, char *buffer)
  284 +{
  285 + int ret;
  286 +
  287 + ret = HYPERVISOR_xen_version(XENVER_pagesize, NULL);
  288 + if (ret > 0)
  289 + ret = sprintf(buffer, "%x\n", ret);
  290 +
  291 + return ret;
  292 +}
  293 +
  294 +HYPERVISOR_ATTR_RO(pagesize);
  295 +
  296 +/* eventually there will be several more features to export */
  297 +static ssize_t xen_feature_show(int index, char *buffer)
  298 +{
  299 + int ret = -ENOMEM;
  300 + struct xen_feature_info *info;
  301 +
  302 + info = kmalloc(sizeof(struct xen_feature_info), GFP_KERNEL);
  303 + if (info) {
  304 + info->submap_idx = index;
  305 + ret = HYPERVISOR_xen_version(XENVER_get_features, info);
  306 + if (!ret)
  307 + ret = sprintf(buffer, "%d\n", info->submap);
  308 + kfree(info);
  309 + }
  310 +
  311 + return ret;
  312 +}
  313 +
  314 +static ssize_t writable_pt_show(struct hyp_sysfs_attr *attr, char *buffer)
  315 +{
  316 + return xen_feature_show(XENFEAT_writable_page_tables, buffer);
  317 +}
  318 +
  319 +HYPERVISOR_ATTR_RO(writable_pt);
  320 +
  321 +static struct attribute *xen_properties_attrs[] = {
  322 + &capabilities_attr.attr,
  323 + &changeset_attr.attr,
  324 + &virtual_start_attr.attr,
  325 + &pagesize_attr.attr,
  326 + &writable_pt_attr.attr,
  327 + NULL
  328 +};
  329 +
  330 +static struct attribute_group xen_properties_group = {
  331 + .name = "properties",
  332 + .attrs = xen_properties_attrs,
  333 +};
  334 +
  335 +static int __init xen_properties_init(void)
  336 +{
  337 + return sysfs_create_group(hypervisor_kobj, &xen_properties_group);
  338 +}
  339 +
  340 +static void xen_properties_destroy(void)
  341 +{
  342 + sysfs_remove_group(hypervisor_kobj, &xen_properties_group);
  343 +}
  344 +
  345 +#ifdef CONFIG_KEXEC
  346 +
  347 +extern size_t vmcoreinfo_size_xen;
  348 +extern unsigned long paddr_vmcoreinfo_xen;
  349 +
  350 +static ssize_t vmcoreinfo_show(struct hyp_sysfs_attr *attr, char *page)
  351 +{
  352 + return sprintf(page, "%lx %zx\n",
  353 + paddr_vmcoreinfo_xen, vmcoreinfo_size_xen);
  354 +}
  355 +
  356 +HYPERVISOR_ATTR_RO(vmcoreinfo);
  357 +
  358 +static int __init xen_sysfs_vmcoreinfo_init(void)
  359 +{
  360 + return sysfs_create_file(hypervisor_kobj,
  361 + &vmcoreinfo_attr.attr);
  362 +}
  363 +
  364 +static void xen_sysfs_vmcoreinfo_destroy(void)
  365 +{
  366 + sysfs_remove_file(hypervisor_kobj, &vmcoreinfo_attr.attr);
  367 +}
  368 +
  369 +#endif
  370 +
  371 +static int __init hyper_sysfs_init(void)
  372 +{
  373 + int ret;
  374 +
  375 + if (!xen_domain())
  376 + return -ENODEV;
  377 +
  378 + ret = xen_sysfs_type_init();
  379 + if (ret)
  380 + goto out;
  381 + ret = xen_sysfs_version_init();
  382 + if (ret)
  383 + goto version_out;
  384 + ret = xen_compilation_init();
  385 + if (ret)
  386 + goto comp_out;
  387 + ret = xen_sysfs_uuid_init();
  388 + if (ret)
  389 + goto uuid_out;
  390 + ret = xen_properties_init();
  391 + if (ret)
  392 + goto prop_out;
  393 +#ifdef CONFIG_KEXEC
  394 + if (vmcoreinfo_size_xen != 0) {
  395 + ret = xen_sysfs_vmcoreinfo_init();
  396 + if (ret)
  397 + goto vmcoreinfo_out;
  398 + }
  399 +#endif
  400 +
  401 + goto out;
  402 +
  403 +#ifdef CONFIG_KEXEC
  404 +vmcoreinfo_out:
  405 +#endif
  406 + xen_properties_destroy();
  407 +prop_out:
  408 + xen_sysfs_uuid_destroy();
  409 +uuid_out:
  410 + xen_compilation_destroy();
  411 +comp_out:
  412 + xen_sysfs_version_destroy();
  413 +version_out:
  414 + xen_sysfs_type_destroy();
  415 +out:
  416 + return ret;
  417 +}
  418 +
  419 +static void __exit hyper_sysfs_exit(void)
  420 +{
  421 +#ifdef CONFIG_KEXEC
  422 + if (vmcoreinfo_size_xen != 0)
  423 + xen_sysfs_vmcoreinfo_destroy();
  424 +#endif
  425 + xen_properties_destroy();
  426 + xen_compilation_destroy();
  427 + xen_sysfs_uuid_destroy();
  428 + xen_sysfs_version_destroy();
  429 + xen_sysfs_type_destroy();
  430 +
  431 +}
  432 +module_init(hyper_sysfs_init);
  433 +module_exit(hyper_sysfs_exit);
  434 +
  435 +static ssize_t hyp_sysfs_show(struct kobject *kobj,
  436 + struct attribute *attr,
  437 + char *buffer)
  438 +{
  439 + struct hyp_sysfs_attr *hyp_attr;
  440 + hyp_attr = container_of(attr, struct hyp_sysfs_attr, attr);
  441 + if (hyp_attr->show)
  442 + return hyp_attr->show(hyp_attr, buffer);
  443 + return 0;
  444 +}
  445 +
  446 +static ssize_t hyp_sysfs_store(struct kobject *kobj,
  447 + struct attribute *attr,
  448 + const char *buffer,
  449 + size_t len)
  450 +{
  451 + struct hyp_sysfs_attr *hyp_attr;
  452 + hyp_attr = container_of(attr, struct hyp_sysfs_attr, attr);
  453 + if (hyp_attr->store)
  454 + return hyp_attr->store(hyp_attr, buffer, len);
  455 + return 0;
  456 +}
  457 +
  458 +static struct sysfs_ops hyp_sysfs_ops = {
  459 + .show = hyp_sysfs_show,
  460 + .store = hyp_sysfs_store,
  461 +};
  462 +
  463 +static struct kobj_type hyp_sysfs_kobj_type = {
  464 + .sysfs_ops = &hyp_sysfs_ops,
  465 +};
  466 +
  467 +static int __init hypervisor_subsys_init(void)
  468 +{
  469 + if (!xen_domain())
  470 + return -ENODEV;
  471 +
  472 + hypervisor_kobj->ktype = &hyp_sysfs_kobj_type;
  473 + return 0;
  474 +}
  475 +device_initcall(hypervisor_subsys_init);
include/xen/interface/version.h
... ... @@ -57,5 +57,8 @@
57 57 /* Declares the features reported by XENVER_get_features. */
58 58 #include "features.h"
59 59  
  60 +/* arg == NULL; returns host memory page size. */
  61 +#define XENVER_pagesize 7
  62 +
60 63 #endif /* __XEN_PUBLIC_VERSION_H__ */