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/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) \
  22static struct hyp_sysfs_attr  _name##_attr = __ATTR_RO(_name)
  23
  24#define HYPERVISOR_ATTR_RW(_name) \
  25static struct hyp_sysfs_attr _name##_attr = \
  26        __ATTR(_name, 0644, _name##_show, _name##_store)
  27
  28struct 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
  35static ssize_t type_show(struct hyp_sysfs_attr *attr, char *buffer)
  36{
  37        return sprintf(buffer, "xen\n");
  38}
  39
  40HYPERVISOR_ATTR_RO(type);
  41
  42static int __init xen_sysfs_type_init(void)
  43{
  44        return sysfs_create_file(hypervisor_kobj, &type_attr.attr);
  45}
  46
  47static void xen_sysfs_type_destroy(void)
  48{
  49        sysfs_remove_file(hypervisor_kobj, &type_attr.attr);
  50}
  51
  52/* xen version attributes */
  53static 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
  61HYPERVISOR_ATTR_RO(major);
  62
  63static 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
  71HYPERVISOR_ATTR_RO(minor);
  72
  73static 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
  89HYPERVISOR_ATTR_RO(extra);
  90
  91static struct attribute *version_attrs[] = {
  92        &major_attr.attr,
  93        &minor_attr.attr,
  94        &extra_attr.attr,
  95        NULL
  96};
  97
  98static struct attribute_group version_group = {
  99        .name = "version",
 100        .attrs = version_attrs,
 101};
 102
 103static int __init xen_sysfs_version_init(void)
 104{
 105        return sysfs_create_group(hypervisor_kobj, &version_group);
 106}
 107
 108static void xen_sysfs_version_destroy(void)
 109{
 110        sysfs_remove_group(hypervisor_kobj, &version_group);
 111}
 112
 113/* UUID */
 114
 115static 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
 136HYPERVISOR_ATTR_RO(uuid);
 137
 138static int __init xen_sysfs_uuid_init(void)
 139{
 140        return sysfs_create_file(hypervisor_kobj, &uuid_attr.attr);
 141}
 142
 143static void xen_sysfs_uuid_destroy(void)
 144{
 145        sysfs_remove_file(hypervisor_kobj, &uuid_attr.attr);
 146}
 147
 148/* xen compilation attributes */
 149
 150static 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
 166HYPERVISOR_ATTR_RO(compiler);
 167
 168static 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
 184HYPERVISOR_ATTR_RO(compiled_by);
 185
 186static 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
 202HYPERVISOR_ATTR_RO(compile_date);
 203
 204static struct attribute *xen_compile_attrs[] = {
 205        &compiler_attr.attr,
 206        &compiled_by_attr.attr,
 207        &compile_date_attr.attr,
 208        NULL
 209};
 210
 211static struct attribute_group xen_compilation_group = {
 212        .name = "compilation",
 213        .attrs = xen_compile_attrs,
 214};
 215
 216int __init static xen_compilation_init(void)
 217{
 218        return sysfs_create_group(hypervisor_kobj, &xen_compilation_group);
 219}
 220
 221static void xen_compilation_destroy(void)
 222{
 223        sysfs_remove_group(hypervisor_kobj, &xen_compilation_group);
 224}
 225
 226/* xen properties info */
 227
 228static 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
 244HYPERVISOR_ATTR_RO(capabilities);
 245
 246static 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
 262HYPERVISOR_ATTR_RO(changeset);
 263
 264static 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
 281HYPERVISOR_ATTR_RO(virtual_start);
 282
 283static 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
 294HYPERVISOR_ATTR_RO(pagesize);
 295
 296static ssize_t xen_feature_show(int index, char *buffer)
 297{
 298        ssize_t ret;
 299        struct xen_feature_info info;
 300
 301        info.submap_idx = index;
 302        ret = HYPERVISOR_xen_version(XENVER_get_features, &info);
 303        if (!ret)
 304                ret = sprintf(buffer, "%08x", info.submap);
 305
 306        return ret;
 307}
 308
 309static ssize_t features_show(struct hyp_sysfs_attr *attr, char *buffer)
 310{
 311        ssize_t len;
 312        int i;
 313
 314        len = 0;
 315        for (i = XENFEAT_NR_SUBMAPS-1; i >= 0; i--) {
 316                int ret = xen_feature_show(i, buffer + len);
 317                if (ret < 0) {
 318                        if (len == 0)
 319                                len = ret;
 320                        break;
 321                }
 322                len += ret;
 323        }
 324        if (len > 0)
 325                buffer[len++] = '\n';
 326
 327        return len;
 328}
 329
 330HYPERVISOR_ATTR_RO(features);
 331
 332static struct attribute *xen_properties_attrs[] = {
 333        &capabilities_attr.attr,
 334        &changeset_attr.attr,
 335        &virtual_start_attr.attr,
 336        &pagesize_attr.attr,
 337        &features_attr.attr,
 338        NULL
 339};
 340
 341static struct attribute_group xen_properties_group = {
 342        .name = "properties",
 343        .attrs = xen_properties_attrs,
 344};
 345
 346static int __init xen_properties_init(void)
 347{
 348        return sysfs_create_group(hypervisor_kobj, &xen_properties_group);
 349}
 350
 351static void xen_properties_destroy(void)
 352{
 353        sysfs_remove_group(hypervisor_kobj, &xen_properties_group);
 354}
 355
 356static int __init hyper_sysfs_init(void)
 357{
 358        int ret;
 359
 360        if (!xen_domain())
 361                return -ENODEV;
 362
 363        ret = xen_sysfs_type_init();
 364        if (ret)
 365                goto out;
 366        ret = xen_sysfs_version_init();
 367        if (ret)
 368                goto version_out;
 369        ret = xen_compilation_init();
 370        if (ret)
 371                goto comp_out;
 372        ret = xen_sysfs_uuid_init();
 373        if (ret)
 374                goto uuid_out;
 375        ret = xen_properties_init();
 376        if (ret)
 377                goto prop_out;
 378
 379        goto out;
 380
 381prop_out:
 382        xen_sysfs_uuid_destroy();
 383uuid_out:
 384        xen_compilation_destroy();
 385comp_out:
 386        xen_sysfs_version_destroy();
 387version_out:
 388        xen_sysfs_type_destroy();
 389out:
 390        return ret;
 391}
 392
 393static void __exit hyper_sysfs_exit(void)
 394{
 395        xen_properties_destroy();
 396        xen_compilation_destroy();
 397        xen_sysfs_uuid_destroy();
 398        xen_sysfs_version_destroy();
 399        xen_sysfs_type_destroy();
 400
 401}
 402module_init(hyper_sysfs_init);
 403module_exit(hyper_sysfs_exit);
 404
 405static ssize_t hyp_sysfs_show(struct kobject *kobj,
 406                              struct attribute *attr,
 407                              char *buffer)
 408{
 409        struct hyp_sysfs_attr *hyp_attr;
 410        hyp_attr = container_of(attr, struct hyp_sysfs_attr, attr);
 411        if (hyp_attr->show)
 412                return hyp_attr->show(hyp_attr, buffer);
 413        return 0;
 414}
 415
 416static ssize_t hyp_sysfs_store(struct kobject *kobj,
 417                               struct attribute *attr,
 418                               const char *buffer,
 419                               size_t len)
 420{
 421        struct hyp_sysfs_attr *hyp_attr;
 422        hyp_attr = container_of(attr, struct hyp_sysfs_attr, attr);
 423        if (hyp_attr->store)
 424                return hyp_attr->store(hyp_attr, buffer, len);
 425        return 0;
 426}
 427
 428static struct sysfs_ops hyp_sysfs_ops = {
 429        .show = hyp_sysfs_show,
 430        .store = hyp_sysfs_store,
 431};
 432
 433static struct kobj_type hyp_sysfs_kobj_type = {
 434        .sysfs_ops = &hyp_sysfs_ops,
 435};
 436
 437static int __init hypervisor_subsys_init(void)
 438{
 439        if (!xen_domain())
 440                return -ENODEV;
 441
 442        hypervisor_kobj->ktype = &hyp_sysfs_kobj_type;
 443        return 0;
 444}
 445device_initcall(hypervisor_subsys_init);
 446
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.