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