Author | Tokens | Token Proportion | Commits | Commit Proportion |
---|---|---|---|---|
Jeremy Fitzhardinge | 1803 | 62.71% | 3 | 15.00% |
Boris Ostrovsky | 533 | 18.54% | 1 | 5.00% |
Per Bilse | 289 | 10.05% | 1 | 5.00% |
Juergen Gross | 189 | 6.57% | 3 | 15.00% |
Daniel De Graaf | 31 | 1.08% | 1 | 5.00% |
Paul Gortmaker | 11 | 0.38% | 1 | 5.00% |
Ian Campbell | 6 | 0.21% | 2 | 10.00% |
Jan Beulich | 3 | 0.10% | 1 | 5.00% |
Thomas Gleixner | 2 | 0.07% | 1 | 5.00% |
Linus Torvalds (pre-git) | 2 | 0.07% | 1 | 5.00% |
zhanglianjie | 2 | 0.07% | 1 | 5.00% |
Daniel Kiper | 1 | 0.03% | 1 | 5.00% |
Thomas Weißschuh | 1 | 0.03% | 1 | 5.00% |
Emese Revfy | 1 | 0.03% | 1 | 5.00% |
Linus Torvalds | 1 | 0.03% | 1 | 5.00% |
Total | 2875 | 20 |
// SPDX-License-Identifier: GPL-2.0-only /* * copyright (c) 2006 IBM Corporation * Authored by: Mike D. Day <ncmike@us.ibm.com> */ #include <linux/slab.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/kobject.h> #include <linux/err.h> #include <asm/xen/hypervisor.h> #include <asm/xen/hypercall.h> #include <xen/xen.h> #include <xen/xenbus.h> #include <xen/interface/xen.h> #include <xen/interface/version.h> #ifdef CONFIG_XEN_HAVE_VPMU #include <xen/interface/xenpmu.h> #endif #define HYPERVISOR_ATTR_RO(_name) \ static struct hyp_sysfs_attr _name##_attr = __ATTR_RO(_name) #define HYPERVISOR_ATTR_RW(_name) \ static struct hyp_sysfs_attr _name##_attr = __ATTR_RW(_name) struct hyp_sysfs_attr { struct attribute attr; ssize_t (*show)(struct hyp_sysfs_attr *, char *); ssize_t (*store)(struct hyp_sysfs_attr *, const char *, size_t); union { void *hyp_attr_data; unsigned long hyp_attr_value; }; }; static ssize_t type_show(struct hyp_sysfs_attr *attr, char *buffer) { return sprintf(buffer, "xen\n"); } HYPERVISOR_ATTR_RO(type); static int __init xen_sysfs_type_init(void) { return sysfs_create_file(hypervisor_kobj, &type_attr.attr); } static ssize_t guest_type_show(struct hyp_sysfs_attr *attr, char *buffer) { const char *type; switch (xen_domain_type) { case XEN_NATIVE: /* ARM only. */ type = "Xen"; break; case XEN_PV_DOMAIN: type = "PV"; break; case XEN_HVM_DOMAIN: type = xen_pvh_domain() ? "PVH" : "HVM"; break; default: return -EINVAL; } return sprintf(buffer, "%s\n", type); } HYPERVISOR_ATTR_RO(guest_type); static int __init xen_sysfs_guest_type_init(void) { return sysfs_create_file(hypervisor_kobj, &guest_type_attr.attr); } /* xen version attributes */ static ssize_t major_show(struct hyp_sysfs_attr *attr, char *buffer) { int version = HYPERVISOR_xen_version(XENVER_version, NULL); if (version) return sprintf(buffer, "%d\n", version >> 16); return -ENODEV; } HYPERVISOR_ATTR_RO(major); static ssize_t minor_show(struct hyp_sysfs_attr *attr, char *buffer) { int version = HYPERVISOR_xen_version(XENVER_version, NULL); if (version) return sprintf(buffer, "%d\n", version & 0xff); return -ENODEV; } HYPERVISOR_ATTR_RO(minor); static ssize_t extra_show(struct hyp_sysfs_attr *attr, char *buffer) { int ret = -ENOMEM; char *extra; extra = kmalloc(XEN_EXTRAVERSION_LEN, GFP_KERNEL); if (extra) { ret = HYPERVISOR_xen_version(XENVER_extraversion, extra); if (!ret) ret = sprintf(buffer, "%s\n", extra); kfree(extra); } return ret; } HYPERVISOR_ATTR_RO(extra); static struct attribute *version_attrs[] = { &major_attr.attr, &minor_attr.attr, &extra_attr.attr, NULL }; static const struct attribute_group version_group = { .name = "version", .attrs = version_attrs, }; static int __init xen_sysfs_version_init(void) { return sysfs_create_group(hypervisor_kobj, &version_group); } /* UUID */ static ssize_t uuid_show_fallback(struct hyp_sysfs_attr *attr, char *buffer) { char *vm, *val; int ret; extern int xenstored_ready; if (!xenstored_ready) return -EBUSY; vm = xenbus_read(XBT_NIL, "vm", "", NULL); if (IS_ERR(vm)) return PTR_ERR(vm); val = xenbus_read(XBT_NIL, vm, "uuid", NULL); kfree(vm); if (IS_ERR(val)) return PTR_ERR(val); ret = sprintf(buffer, "%s\n", val); kfree(val); return ret; } static ssize_t uuid_show(struct hyp_sysfs_attr *attr, char *buffer) { xen_domain_handle_t uuid; int ret; ret = HYPERVISOR_xen_version(XENVER_guest_handle, uuid); if (ret) return uuid_show_fallback(attr, buffer); ret = sprintf(buffer, "%pU\n", uuid); return ret; } HYPERVISOR_ATTR_RO(uuid); static int __init xen_sysfs_uuid_init(void) { return sysfs_create_file(hypervisor_kobj, &uuid_attr.attr); } /* xen compilation attributes */ static ssize_t compiler_show(struct hyp_sysfs_attr *attr, char *buffer) { int ret = -ENOMEM; struct xen_compile_info *info; info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL); if (info) { ret = HYPERVISOR_xen_version(XENVER_compile_info, info); if (!ret) ret = sprintf(buffer, "%s\n", info->compiler); kfree(info); } return ret; } HYPERVISOR_ATTR_RO(compiler); static ssize_t compiled_by_show(struct hyp_sysfs_attr *attr, char *buffer) { int ret = -ENOMEM; struct xen_compile_info *info; info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL); if (info) { ret = HYPERVISOR_xen_version(XENVER_compile_info, info); if (!ret) ret = sprintf(buffer, "%s\n", info->compile_by); kfree(info); } return ret; } HYPERVISOR_ATTR_RO(compiled_by); static ssize_t compile_date_show(struct hyp_sysfs_attr *attr, char *buffer) { int ret = -ENOMEM; struct xen_compile_info *info; info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL); if (info) { ret = HYPERVISOR_xen_version(XENVER_compile_info, info); if (!ret) ret = sprintf(buffer, "%s\n", info->compile_date); kfree(info); } return ret; } HYPERVISOR_ATTR_RO(compile_date); static struct attribute *xen_compile_attrs[] = { &compiler_attr.attr, &compiled_by_attr.attr, &compile_date_attr.attr, NULL }; static const struct attribute_group xen_compilation_group = { .name = "compilation", .attrs = xen_compile_attrs, }; static int __init xen_sysfs_compilation_init(void) { return sysfs_create_group(hypervisor_kobj, &xen_compilation_group); } /* xen properties info */ static ssize_t capabilities_show(struct hyp_sysfs_attr *attr, char *buffer) { int ret = -ENOMEM; char *caps; caps = kmalloc(XEN_CAPABILITIES_INFO_LEN, GFP_KERNEL); if (caps) { ret = HYPERVISOR_xen_version(XENVER_capabilities, caps); if (!ret) ret = sprintf(buffer, "%s\n", caps); kfree(caps); } return ret; } HYPERVISOR_ATTR_RO(capabilities); static ssize_t changeset_show(struct hyp_sysfs_attr *attr, char *buffer) { int ret = -ENOMEM; char *cset; cset = kmalloc(XEN_CHANGESET_INFO_LEN, GFP_KERNEL); if (cset) { ret = HYPERVISOR_xen_version(XENVER_changeset, cset); if (!ret) ret = sprintf(buffer, "%s\n", cset); kfree(cset); } return ret; } HYPERVISOR_ATTR_RO(changeset); static ssize_t virtual_start_show(struct hyp_sysfs_attr *attr, char *buffer) { int ret = -ENOMEM; struct xen_platform_parameters *parms; parms = kmalloc(sizeof(struct xen_platform_parameters), GFP_KERNEL); if (parms) { ret = HYPERVISOR_xen_version(XENVER_platform_parameters, parms); if (!ret) ret = sprintf(buffer, "%"PRI_xen_ulong"\n", parms->virt_start); kfree(parms); } return ret; } HYPERVISOR_ATTR_RO(virtual_start); static ssize_t pagesize_show(struct hyp_sysfs_attr *attr, char *buffer) { int ret; ret = HYPERVISOR_xen_version(XENVER_pagesize, NULL); if (ret > 0) ret = sprintf(buffer, "%x\n", ret); return ret; } HYPERVISOR_ATTR_RO(pagesize); static ssize_t xen_feature_show(int index, char *buffer) { ssize_t ret; struct xen_feature_info info; info.submap_idx = index; ret = HYPERVISOR_xen_version(XENVER_get_features, &info); if (!ret) ret = sprintf(buffer, "%08x", info.submap); return ret; } static ssize_t features_show(struct hyp_sysfs_attr *attr, char *buffer) { ssize_t len; int i; len = 0; for (i = XENFEAT_NR_SUBMAPS-1; i >= 0; i--) { int ret = xen_feature_show(i, buffer + len); if (ret < 0) { if (len == 0) len = ret; break; } len += ret; } if (len > 0) buffer[len++] = '\n'; return len; } HYPERVISOR_ATTR_RO(features); static ssize_t buildid_show(struct hyp_sysfs_attr *attr, char *buffer) { ssize_t ret; struct xen_build_id *buildid; ret = HYPERVISOR_xen_version(XENVER_build_id, NULL); if (ret < 0) { if (ret == -EPERM) ret = sprintf(buffer, "<denied>"); return ret; } buildid = kmalloc(sizeof(*buildid) + ret, GFP_KERNEL); if (!buildid) return -ENOMEM; buildid->len = ret; ret = HYPERVISOR_xen_version(XENVER_build_id, buildid); if (ret > 0) ret = sprintf(buffer, "%s", buildid->buf); kfree(buildid); return ret; } HYPERVISOR_ATTR_RO(buildid); static struct attribute *xen_properties_attrs[] = { &capabilities_attr.attr, &changeset_attr.attr, &virtual_start_attr.attr, &pagesize_attr.attr, &features_attr.attr, &buildid_attr.attr, NULL }; static const struct attribute_group xen_properties_group = { .name = "properties", .attrs = xen_properties_attrs, }; static int __init xen_sysfs_properties_init(void) { return sysfs_create_group(hypervisor_kobj, &xen_properties_group); } #define FLAG_UNAME "unknown" #define FLAG_UNAME_FMT FLAG_UNAME "%02u" #define FLAG_UNAME_MAX sizeof(FLAG_UNAME "XX") #define FLAG_COUNT (sizeof(xen_start_flags) * BITS_PER_BYTE) static_assert(sizeof(xen_start_flags) <= sizeof_field(struct hyp_sysfs_attr, hyp_attr_value)); static ssize_t flag_show(struct hyp_sysfs_attr *attr, char *buffer) { char *p = buffer; *p++ = '0' + ((xen_start_flags & attr->hyp_attr_value) != 0); *p++ = '\n'; return p - buffer; } #define FLAG_NODE(flag, node) \ [ilog2(flag)] = { \ .attr = { .name = #node, .mode = 0444 },\ .show = flag_show, \ .hyp_attr_value = flag \ } /* * Add new, known flags here. No other changes are required, but * note that each known flag wastes one entry in flag_unames[]. * The code/complexity machinations to avoid this isn't worth it * for a few entries, but keep it in mind. */ static struct hyp_sysfs_attr flag_attrs[FLAG_COUNT] = { FLAG_NODE(SIF_PRIVILEGED, privileged), FLAG_NODE(SIF_INITDOMAIN, initdomain) }; static struct attribute_group xen_flags_group = { .name = "start_flags", .attrs = (struct attribute *[FLAG_COUNT + 1]){} }; static char flag_unames[FLAG_COUNT][FLAG_UNAME_MAX]; static int __init xen_sysfs_flags_init(void) { for (unsigned fnum = 0; fnum != FLAG_COUNT; fnum++) { if (likely(flag_attrs[fnum].attr.name == NULL)) { sprintf(flag_unames[fnum], FLAG_UNAME_FMT, fnum); flag_attrs[fnum].attr.name = flag_unames[fnum]; flag_attrs[fnum].attr.mode = 0444; flag_attrs[fnum].show = flag_show; flag_attrs[fnum].hyp_attr_value = 1 << fnum; } xen_flags_group.attrs[fnum] = &flag_attrs[fnum].attr; } return sysfs_create_group(hypervisor_kobj, &xen_flags_group); } #ifdef CONFIG_XEN_HAVE_VPMU struct pmu_mode { const char *name; uint32_t mode; }; static struct pmu_mode pmu_modes[] = { {"off", XENPMU_MODE_OFF}, {"self", XENPMU_MODE_SELF}, {"hv", XENPMU_MODE_HV}, {"all", XENPMU_MODE_ALL} }; static ssize_t pmu_mode_store(struct hyp_sysfs_attr *attr, const char *buffer, size_t len) { int ret; struct xen_pmu_params xp; int i; for (i = 0; i < ARRAY_SIZE(pmu_modes); i++) { if (strncmp(buffer, pmu_modes[i].name, len - 1) == 0) { xp.val = pmu_modes[i].mode; break; } } if (i == ARRAY_SIZE(pmu_modes)) return -EINVAL; xp.version.maj = XENPMU_VER_MAJ; xp.version.min = XENPMU_VER_MIN; ret = HYPERVISOR_xenpmu_op(XENPMU_mode_set, &xp); if (ret) return ret; return len; } static ssize_t pmu_mode_show(struct hyp_sysfs_attr *attr, char *buffer) { int ret; struct xen_pmu_params xp; int i; uint32_t mode; xp.version.maj = XENPMU_VER_MAJ; xp.version.min = XENPMU_VER_MIN; ret = HYPERVISOR_xenpmu_op(XENPMU_mode_get, &xp); if (ret) return ret; mode = (uint32_t)xp.val; for (i = 0; i < ARRAY_SIZE(pmu_modes); i++) { if (mode == pmu_modes[i].mode) return sprintf(buffer, "%s\n", pmu_modes[i].name); } return -EINVAL; } HYPERVISOR_ATTR_RW(pmu_mode); static ssize_t pmu_features_store(struct hyp_sysfs_attr *attr, const char *buffer, size_t len) { int ret; uint32_t features; struct xen_pmu_params xp; ret = kstrtou32(buffer, 0, &features); if (ret) return ret; xp.val = features; xp.version.maj = XENPMU_VER_MAJ; xp.version.min = XENPMU_VER_MIN; ret = HYPERVISOR_xenpmu_op(XENPMU_feature_set, &xp); if (ret) return ret; return len; } static ssize_t pmu_features_show(struct hyp_sysfs_attr *attr, char *buffer) { int ret; struct xen_pmu_params xp; xp.version.maj = XENPMU_VER_MAJ; xp.version.min = XENPMU_VER_MIN; ret = HYPERVISOR_xenpmu_op(XENPMU_feature_get, &xp); if (ret) return ret; return sprintf(buffer, "0x%x\n", (uint32_t)xp.val); } HYPERVISOR_ATTR_RW(pmu_features); static struct attribute *xen_pmu_attrs[] = { &pmu_mode_attr.attr, &pmu_features_attr.attr, NULL }; static const struct attribute_group xen_pmu_group = { .name = "pmu", .attrs = xen_pmu_attrs, }; static int __init xen_sysfs_pmu_init(void) { return sysfs_create_group(hypervisor_kobj, &xen_pmu_group); } #endif static int __init hyper_sysfs_init(void) { int ret; if (!xen_domain()) return -ENODEV; ret = xen_sysfs_type_init(); if (ret) goto out; ret = xen_sysfs_guest_type_init(); if (ret) goto guest_type_out; ret = xen_sysfs_version_init(); if (ret) goto version_out; ret = xen_sysfs_compilation_init(); if (ret) goto comp_out; ret = xen_sysfs_uuid_init(); if (ret) goto uuid_out; ret = xen_sysfs_properties_init(); if (ret) goto prop_out; ret = xen_sysfs_flags_init(); if (ret) goto flags_out; #ifdef CONFIG_XEN_HAVE_VPMU if (xen_initial_domain()) { ret = xen_sysfs_pmu_init(); if (ret) { sysfs_remove_group(hypervisor_kobj, &xen_flags_group); goto flags_out; } } #endif goto out; flags_out: sysfs_remove_group(hypervisor_kobj, &xen_properties_group); prop_out: sysfs_remove_file(hypervisor_kobj, &uuid_attr.attr); uuid_out: sysfs_remove_group(hypervisor_kobj, &xen_compilation_group); comp_out: sysfs_remove_group(hypervisor_kobj, &version_group); version_out: sysfs_remove_file(hypervisor_kobj, &guest_type_attr.attr); guest_type_out: sysfs_remove_file(hypervisor_kobj, &type_attr.attr); out: return ret; } device_initcall(hyper_sysfs_init); static ssize_t hyp_sysfs_show(struct kobject *kobj, struct attribute *attr, char *buffer) { struct hyp_sysfs_attr *hyp_attr; hyp_attr = container_of(attr, struct hyp_sysfs_attr, attr); if (hyp_attr->show) return hyp_attr->show(hyp_attr, buffer); return 0; } static ssize_t hyp_sysfs_store(struct kobject *kobj, struct attribute *attr, const char *buffer, size_t len) { struct hyp_sysfs_attr *hyp_attr; hyp_attr = container_of(attr, struct hyp_sysfs_attr, attr); if (hyp_attr->store) return hyp_attr->store(hyp_attr, buffer, len); return 0; } static const struct sysfs_ops hyp_sysfs_ops = { .show = hyp_sysfs_show, .store = hyp_sysfs_store, }; static const struct kobj_type hyp_sysfs_kobj_type = { .sysfs_ops = &hyp_sysfs_ops, }; static int __init hypervisor_subsys_init(void) { if (!xen_domain()) return -ENODEV; hypervisor_kobj->ktype = &hyp_sysfs_kobj_type; return 0; } device_initcall(hypervisor_subsys_init);
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with Cregit http://github.com/cregit/cregit
Version 2.0-RC1