1cff7e81bSJeremy Fitzhardinge /* 2cff7e81bSJeremy Fitzhardinge * copyright (c) 2006 IBM Corporation 3cff7e81bSJeremy Fitzhardinge * Authored by: Mike D. Day <ncmike@us.ibm.com> 4cff7e81bSJeremy Fitzhardinge * 5cff7e81bSJeremy Fitzhardinge * This program is free software; you can redistribute it and/or modify 6cff7e81bSJeremy Fitzhardinge * it under the terms of the GNU General Public License version 2 as 7cff7e81bSJeremy Fitzhardinge * published by the Free Software Foundation. 8cff7e81bSJeremy Fitzhardinge */ 9cff7e81bSJeremy Fitzhardinge 105a0e3ad6STejun Heo #include <linux/slab.h> 11cff7e81bSJeremy Fitzhardinge #include <linux/kernel.h> 12cff7e81bSJeremy Fitzhardinge #include <linux/module.h> 13cff7e81bSJeremy Fitzhardinge #include <linux/kobject.h> 14609b0b8cSIan Campbell #include <linux/err.h> 15cff7e81bSJeremy Fitzhardinge 16cff7e81bSJeremy Fitzhardinge #include <asm/xen/hypervisor.h> 17cff7e81bSJeremy Fitzhardinge #include <asm/xen/hypercall.h> 18cff7e81bSJeremy Fitzhardinge 191ccbf534SJeremy Fitzhardinge #include <xen/xen.h> 20cff7e81bSJeremy Fitzhardinge #include <xen/xenbus.h> 21cff7e81bSJeremy Fitzhardinge #include <xen/interface/xen.h> 22cff7e81bSJeremy Fitzhardinge #include <xen/interface/version.h> 23*5f141548SBoris Ostrovsky #ifdef CONFIG_XEN_HAVE_VPMU 24*5f141548SBoris Ostrovsky #include <xen/interface/xenpmu.h> 25*5f141548SBoris Ostrovsky #endif 26cff7e81bSJeremy Fitzhardinge 27cff7e81bSJeremy Fitzhardinge #define HYPERVISOR_ATTR_RO(_name) \ 28cff7e81bSJeremy Fitzhardinge static struct hyp_sysfs_attr _name##_attr = __ATTR_RO(_name) 29cff7e81bSJeremy Fitzhardinge 30cff7e81bSJeremy Fitzhardinge #define HYPERVISOR_ATTR_RW(_name) \ 31cff7e81bSJeremy Fitzhardinge static struct hyp_sysfs_attr _name##_attr = \ 32cff7e81bSJeremy Fitzhardinge __ATTR(_name, 0644, _name##_show, _name##_store) 33cff7e81bSJeremy Fitzhardinge 34cff7e81bSJeremy Fitzhardinge struct hyp_sysfs_attr { 35cff7e81bSJeremy Fitzhardinge struct attribute attr; 36cff7e81bSJeremy Fitzhardinge ssize_t (*show)(struct hyp_sysfs_attr *, char *); 37cff7e81bSJeremy Fitzhardinge ssize_t (*store)(struct hyp_sysfs_attr *, const char *, size_t); 38cff7e81bSJeremy Fitzhardinge void *hyp_attr_data; 39cff7e81bSJeremy Fitzhardinge }; 40cff7e81bSJeremy Fitzhardinge 41cff7e81bSJeremy Fitzhardinge static ssize_t type_show(struct hyp_sysfs_attr *attr, char *buffer) 42cff7e81bSJeremy Fitzhardinge { 43cff7e81bSJeremy Fitzhardinge return sprintf(buffer, "xen\n"); 44cff7e81bSJeremy Fitzhardinge } 45cff7e81bSJeremy Fitzhardinge 46cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(type); 47cff7e81bSJeremy Fitzhardinge 48cff7e81bSJeremy Fitzhardinge static int __init xen_sysfs_type_init(void) 49cff7e81bSJeremy Fitzhardinge { 50cff7e81bSJeremy Fitzhardinge return sysfs_create_file(hypervisor_kobj, &type_attr.attr); 51cff7e81bSJeremy Fitzhardinge } 52cff7e81bSJeremy Fitzhardinge 53cff7e81bSJeremy Fitzhardinge static void xen_sysfs_type_destroy(void) 54cff7e81bSJeremy Fitzhardinge { 55cff7e81bSJeremy Fitzhardinge sysfs_remove_file(hypervisor_kobj, &type_attr.attr); 56cff7e81bSJeremy Fitzhardinge } 57cff7e81bSJeremy Fitzhardinge 58cff7e81bSJeremy Fitzhardinge /* xen version attributes */ 59cff7e81bSJeremy Fitzhardinge static ssize_t major_show(struct hyp_sysfs_attr *attr, char *buffer) 60cff7e81bSJeremy Fitzhardinge { 61cff7e81bSJeremy Fitzhardinge int version = HYPERVISOR_xen_version(XENVER_version, NULL); 62cff7e81bSJeremy Fitzhardinge if (version) 63cff7e81bSJeremy Fitzhardinge return sprintf(buffer, "%d\n", version >> 16); 64cff7e81bSJeremy Fitzhardinge return -ENODEV; 65cff7e81bSJeremy Fitzhardinge } 66cff7e81bSJeremy Fitzhardinge 67cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(major); 68cff7e81bSJeremy Fitzhardinge 69cff7e81bSJeremy Fitzhardinge static ssize_t minor_show(struct hyp_sysfs_attr *attr, char *buffer) 70cff7e81bSJeremy Fitzhardinge { 71cff7e81bSJeremy Fitzhardinge int version = HYPERVISOR_xen_version(XENVER_version, NULL); 72cff7e81bSJeremy Fitzhardinge if (version) 73cff7e81bSJeremy Fitzhardinge return sprintf(buffer, "%d\n", version & 0xff); 74cff7e81bSJeremy Fitzhardinge return -ENODEV; 75cff7e81bSJeremy Fitzhardinge } 76cff7e81bSJeremy Fitzhardinge 77cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(minor); 78cff7e81bSJeremy Fitzhardinge 79cff7e81bSJeremy Fitzhardinge static ssize_t extra_show(struct hyp_sysfs_attr *attr, char *buffer) 80cff7e81bSJeremy Fitzhardinge { 81cff7e81bSJeremy Fitzhardinge int ret = -ENOMEM; 82cff7e81bSJeremy Fitzhardinge char *extra; 83cff7e81bSJeremy Fitzhardinge 84cff7e81bSJeremy Fitzhardinge extra = kmalloc(XEN_EXTRAVERSION_LEN, GFP_KERNEL); 85cff7e81bSJeremy Fitzhardinge if (extra) { 86cff7e81bSJeremy Fitzhardinge ret = HYPERVISOR_xen_version(XENVER_extraversion, extra); 87cff7e81bSJeremy Fitzhardinge if (!ret) 88cff7e81bSJeremy Fitzhardinge ret = sprintf(buffer, "%s\n", extra); 89cff7e81bSJeremy Fitzhardinge kfree(extra); 90cff7e81bSJeremy Fitzhardinge } 91cff7e81bSJeremy Fitzhardinge 92cff7e81bSJeremy Fitzhardinge return ret; 93cff7e81bSJeremy Fitzhardinge } 94cff7e81bSJeremy Fitzhardinge 95cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(extra); 96cff7e81bSJeremy Fitzhardinge 97cff7e81bSJeremy Fitzhardinge static struct attribute *version_attrs[] = { 98cff7e81bSJeremy Fitzhardinge &major_attr.attr, 99cff7e81bSJeremy Fitzhardinge &minor_attr.attr, 100cff7e81bSJeremy Fitzhardinge &extra_attr.attr, 101cff7e81bSJeremy Fitzhardinge NULL 102cff7e81bSJeremy Fitzhardinge }; 103cff7e81bSJeremy Fitzhardinge 104ead1d014SJan Beulich static const struct attribute_group version_group = { 105cff7e81bSJeremy Fitzhardinge .name = "version", 106cff7e81bSJeremy Fitzhardinge .attrs = version_attrs, 107cff7e81bSJeremy Fitzhardinge }; 108cff7e81bSJeremy Fitzhardinge 109cff7e81bSJeremy Fitzhardinge static int __init xen_sysfs_version_init(void) 110cff7e81bSJeremy Fitzhardinge { 111cff7e81bSJeremy Fitzhardinge return sysfs_create_group(hypervisor_kobj, &version_group); 112cff7e81bSJeremy Fitzhardinge } 113cff7e81bSJeremy Fitzhardinge 114cff7e81bSJeremy Fitzhardinge static void xen_sysfs_version_destroy(void) 115cff7e81bSJeremy Fitzhardinge { 116cff7e81bSJeremy Fitzhardinge sysfs_remove_group(hypervisor_kobj, &version_group); 117cff7e81bSJeremy Fitzhardinge } 118cff7e81bSJeremy Fitzhardinge 119cff7e81bSJeremy Fitzhardinge /* UUID */ 120cff7e81bSJeremy Fitzhardinge 1215c13f806SDaniel De Graaf static ssize_t uuid_show_fallback(struct hyp_sysfs_attr *attr, char *buffer) 122cff7e81bSJeremy Fitzhardinge { 123cff7e81bSJeremy Fitzhardinge char *vm, *val; 124cff7e81bSJeremy Fitzhardinge int ret; 125cff7e81bSJeremy Fitzhardinge extern int xenstored_ready; 126cff7e81bSJeremy Fitzhardinge 127cff7e81bSJeremy Fitzhardinge if (!xenstored_ready) 128cff7e81bSJeremy Fitzhardinge return -EBUSY; 129cff7e81bSJeremy Fitzhardinge 130cff7e81bSJeremy Fitzhardinge vm = xenbus_read(XBT_NIL, "vm", "", NULL); 131cff7e81bSJeremy Fitzhardinge if (IS_ERR(vm)) 132cff7e81bSJeremy Fitzhardinge return PTR_ERR(vm); 133cff7e81bSJeremy Fitzhardinge val = xenbus_read(XBT_NIL, vm, "uuid", NULL); 134cff7e81bSJeremy Fitzhardinge kfree(vm); 135cff7e81bSJeremy Fitzhardinge if (IS_ERR(val)) 136cff7e81bSJeremy Fitzhardinge return PTR_ERR(val); 137cff7e81bSJeremy Fitzhardinge ret = sprintf(buffer, "%s\n", val); 138cff7e81bSJeremy Fitzhardinge kfree(val); 139cff7e81bSJeremy Fitzhardinge return ret; 140cff7e81bSJeremy Fitzhardinge } 141cff7e81bSJeremy Fitzhardinge 1425c13f806SDaniel De Graaf static ssize_t uuid_show(struct hyp_sysfs_attr *attr, char *buffer) 1435c13f806SDaniel De Graaf { 1445c13f806SDaniel De Graaf xen_domain_handle_t uuid; 1455c13f806SDaniel De Graaf int ret; 1465c13f806SDaniel De Graaf ret = HYPERVISOR_xen_version(XENVER_guest_handle, uuid); 1475c13f806SDaniel De Graaf if (ret) 1485c13f806SDaniel De Graaf return uuid_show_fallback(attr, buffer); 1495c13f806SDaniel De Graaf ret = sprintf(buffer, "%pU\n", uuid); 1505c13f806SDaniel De Graaf return ret; 1515c13f806SDaniel De Graaf } 1525c13f806SDaniel De Graaf 153cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(uuid); 154cff7e81bSJeremy Fitzhardinge 155cff7e81bSJeremy Fitzhardinge static int __init xen_sysfs_uuid_init(void) 156cff7e81bSJeremy Fitzhardinge { 157cff7e81bSJeremy Fitzhardinge return sysfs_create_file(hypervisor_kobj, &uuid_attr.attr); 158cff7e81bSJeremy Fitzhardinge } 159cff7e81bSJeremy Fitzhardinge 160cff7e81bSJeremy Fitzhardinge static void xen_sysfs_uuid_destroy(void) 161cff7e81bSJeremy Fitzhardinge { 162cff7e81bSJeremy Fitzhardinge sysfs_remove_file(hypervisor_kobj, &uuid_attr.attr); 163cff7e81bSJeremy Fitzhardinge } 164cff7e81bSJeremy Fitzhardinge 165cff7e81bSJeremy Fitzhardinge /* xen compilation attributes */ 166cff7e81bSJeremy Fitzhardinge 167cff7e81bSJeremy Fitzhardinge static ssize_t compiler_show(struct hyp_sysfs_attr *attr, char *buffer) 168cff7e81bSJeremy Fitzhardinge { 169cff7e81bSJeremy Fitzhardinge int ret = -ENOMEM; 170cff7e81bSJeremy Fitzhardinge struct xen_compile_info *info; 171cff7e81bSJeremy Fitzhardinge 172cff7e81bSJeremy Fitzhardinge info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL); 173cff7e81bSJeremy Fitzhardinge if (info) { 174cff7e81bSJeremy Fitzhardinge ret = HYPERVISOR_xen_version(XENVER_compile_info, info); 175cff7e81bSJeremy Fitzhardinge if (!ret) 176cff7e81bSJeremy Fitzhardinge ret = sprintf(buffer, "%s\n", info->compiler); 177cff7e81bSJeremy Fitzhardinge kfree(info); 178cff7e81bSJeremy Fitzhardinge } 179cff7e81bSJeremy Fitzhardinge 180cff7e81bSJeremy Fitzhardinge return ret; 181cff7e81bSJeremy Fitzhardinge } 182cff7e81bSJeremy Fitzhardinge 183cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(compiler); 184cff7e81bSJeremy Fitzhardinge 185cff7e81bSJeremy Fitzhardinge static ssize_t compiled_by_show(struct hyp_sysfs_attr *attr, char *buffer) 186cff7e81bSJeremy Fitzhardinge { 187cff7e81bSJeremy Fitzhardinge int ret = -ENOMEM; 188cff7e81bSJeremy Fitzhardinge struct xen_compile_info *info; 189cff7e81bSJeremy Fitzhardinge 190cff7e81bSJeremy Fitzhardinge info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL); 191cff7e81bSJeremy Fitzhardinge if (info) { 192cff7e81bSJeremy Fitzhardinge ret = HYPERVISOR_xen_version(XENVER_compile_info, info); 193cff7e81bSJeremy Fitzhardinge if (!ret) 194cff7e81bSJeremy Fitzhardinge ret = sprintf(buffer, "%s\n", info->compile_by); 195cff7e81bSJeremy Fitzhardinge kfree(info); 196cff7e81bSJeremy Fitzhardinge } 197cff7e81bSJeremy Fitzhardinge 198cff7e81bSJeremy Fitzhardinge return ret; 199cff7e81bSJeremy Fitzhardinge } 200cff7e81bSJeremy Fitzhardinge 201cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(compiled_by); 202cff7e81bSJeremy Fitzhardinge 203cff7e81bSJeremy Fitzhardinge static ssize_t compile_date_show(struct hyp_sysfs_attr *attr, char *buffer) 204cff7e81bSJeremy Fitzhardinge { 205cff7e81bSJeremy Fitzhardinge int ret = -ENOMEM; 206cff7e81bSJeremy Fitzhardinge struct xen_compile_info *info; 207cff7e81bSJeremy Fitzhardinge 208cff7e81bSJeremy Fitzhardinge info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL); 209cff7e81bSJeremy Fitzhardinge if (info) { 210cff7e81bSJeremy Fitzhardinge ret = HYPERVISOR_xen_version(XENVER_compile_info, info); 211cff7e81bSJeremy Fitzhardinge if (!ret) 212cff7e81bSJeremy Fitzhardinge ret = sprintf(buffer, "%s\n", info->compile_date); 213cff7e81bSJeremy Fitzhardinge kfree(info); 214cff7e81bSJeremy Fitzhardinge } 215cff7e81bSJeremy Fitzhardinge 216cff7e81bSJeremy Fitzhardinge return ret; 217cff7e81bSJeremy Fitzhardinge } 218cff7e81bSJeremy Fitzhardinge 219cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(compile_date); 220cff7e81bSJeremy Fitzhardinge 221cff7e81bSJeremy Fitzhardinge static struct attribute *xen_compile_attrs[] = { 222cff7e81bSJeremy Fitzhardinge &compiler_attr.attr, 223cff7e81bSJeremy Fitzhardinge &compiled_by_attr.attr, 224cff7e81bSJeremy Fitzhardinge &compile_date_attr.attr, 225cff7e81bSJeremy Fitzhardinge NULL 226cff7e81bSJeremy Fitzhardinge }; 227cff7e81bSJeremy Fitzhardinge 228ead1d014SJan Beulich static const struct attribute_group xen_compilation_group = { 229cff7e81bSJeremy Fitzhardinge .name = "compilation", 230cff7e81bSJeremy Fitzhardinge .attrs = xen_compile_attrs, 231cff7e81bSJeremy Fitzhardinge }; 232cff7e81bSJeremy Fitzhardinge 233887cb456SDaniel Kiper static int __init xen_compilation_init(void) 234cff7e81bSJeremy Fitzhardinge { 235cff7e81bSJeremy Fitzhardinge return sysfs_create_group(hypervisor_kobj, &xen_compilation_group); 236cff7e81bSJeremy Fitzhardinge } 237cff7e81bSJeremy Fitzhardinge 238cff7e81bSJeremy Fitzhardinge static void xen_compilation_destroy(void) 239cff7e81bSJeremy Fitzhardinge { 240cff7e81bSJeremy Fitzhardinge sysfs_remove_group(hypervisor_kobj, &xen_compilation_group); 241cff7e81bSJeremy Fitzhardinge } 242cff7e81bSJeremy Fitzhardinge 243cff7e81bSJeremy Fitzhardinge /* xen properties info */ 244cff7e81bSJeremy Fitzhardinge 245cff7e81bSJeremy Fitzhardinge static ssize_t capabilities_show(struct hyp_sysfs_attr *attr, char *buffer) 246cff7e81bSJeremy Fitzhardinge { 247cff7e81bSJeremy Fitzhardinge int ret = -ENOMEM; 248cff7e81bSJeremy Fitzhardinge char *caps; 249cff7e81bSJeremy Fitzhardinge 250cff7e81bSJeremy Fitzhardinge caps = kmalloc(XEN_CAPABILITIES_INFO_LEN, GFP_KERNEL); 251cff7e81bSJeremy Fitzhardinge if (caps) { 252cff7e81bSJeremy Fitzhardinge ret = HYPERVISOR_xen_version(XENVER_capabilities, caps); 253cff7e81bSJeremy Fitzhardinge if (!ret) 254cff7e81bSJeremy Fitzhardinge ret = sprintf(buffer, "%s\n", caps); 255cff7e81bSJeremy Fitzhardinge kfree(caps); 256cff7e81bSJeremy Fitzhardinge } 257cff7e81bSJeremy Fitzhardinge 258cff7e81bSJeremy Fitzhardinge return ret; 259cff7e81bSJeremy Fitzhardinge } 260cff7e81bSJeremy Fitzhardinge 261cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(capabilities); 262cff7e81bSJeremy Fitzhardinge 263cff7e81bSJeremy Fitzhardinge static ssize_t changeset_show(struct hyp_sysfs_attr *attr, char *buffer) 264cff7e81bSJeremy Fitzhardinge { 265cff7e81bSJeremy Fitzhardinge int ret = -ENOMEM; 266cff7e81bSJeremy Fitzhardinge char *cset; 267cff7e81bSJeremy Fitzhardinge 268cff7e81bSJeremy Fitzhardinge cset = kmalloc(XEN_CHANGESET_INFO_LEN, GFP_KERNEL); 269cff7e81bSJeremy Fitzhardinge if (cset) { 270cff7e81bSJeremy Fitzhardinge ret = HYPERVISOR_xen_version(XENVER_changeset, cset); 271cff7e81bSJeremy Fitzhardinge if (!ret) 272cff7e81bSJeremy Fitzhardinge ret = sprintf(buffer, "%s\n", cset); 273cff7e81bSJeremy Fitzhardinge kfree(cset); 274cff7e81bSJeremy Fitzhardinge } 275cff7e81bSJeremy Fitzhardinge 276cff7e81bSJeremy Fitzhardinge return ret; 277cff7e81bSJeremy Fitzhardinge } 278cff7e81bSJeremy Fitzhardinge 279cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(changeset); 280cff7e81bSJeremy Fitzhardinge 281cff7e81bSJeremy Fitzhardinge static ssize_t virtual_start_show(struct hyp_sysfs_attr *attr, char *buffer) 282cff7e81bSJeremy Fitzhardinge { 283cff7e81bSJeremy Fitzhardinge int ret = -ENOMEM; 284cff7e81bSJeremy Fitzhardinge struct xen_platform_parameters *parms; 285cff7e81bSJeremy Fitzhardinge 286cff7e81bSJeremy Fitzhardinge parms = kmalloc(sizeof(struct xen_platform_parameters), GFP_KERNEL); 287cff7e81bSJeremy Fitzhardinge if (parms) { 288cff7e81bSJeremy Fitzhardinge ret = HYPERVISOR_xen_version(XENVER_platform_parameters, 289cff7e81bSJeremy Fitzhardinge parms); 290cff7e81bSJeremy Fitzhardinge if (!ret) 29137ea0fcbSIan Campbell ret = sprintf(buffer, "%"PRI_xen_ulong"\n", 29237ea0fcbSIan Campbell parms->virt_start); 293cff7e81bSJeremy Fitzhardinge kfree(parms); 294cff7e81bSJeremy Fitzhardinge } 295cff7e81bSJeremy Fitzhardinge 296cff7e81bSJeremy Fitzhardinge return ret; 297cff7e81bSJeremy Fitzhardinge } 298cff7e81bSJeremy Fitzhardinge 299cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(virtual_start); 300cff7e81bSJeremy Fitzhardinge 301cff7e81bSJeremy Fitzhardinge static ssize_t pagesize_show(struct hyp_sysfs_attr *attr, char *buffer) 302cff7e81bSJeremy Fitzhardinge { 303cff7e81bSJeremy Fitzhardinge int ret; 304cff7e81bSJeremy Fitzhardinge 305cff7e81bSJeremy Fitzhardinge ret = HYPERVISOR_xen_version(XENVER_pagesize, NULL); 306cff7e81bSJeremy Fitzhardinge if (ret > 0) 307cff7e81bSJeremy Fitzhardinge ret = sprintf(buffer, "%x\n", ret); 308cff7e81bSJeremy Fitzhardinge 309cff7e81bSJeremy Fitzhardinge return ret; 310cff7e81bSJeremy Fitzhardinge } 311cff7e81bSJeremy Fitzhardinge 312cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(pagesize); 313cff7e81bSJeremy Fitzhardinge 314cff7e81bSJeremy Fitzhardinge static ssize_t xen_feature_show(int index, char *buffer) 315cff7e81bSJeremy Fitzhardinge { 316a649b720SJeremy Fitzhardinge ssize_t ret; 317a649b720SJeremy Fitzhardinge struct xen_feature_info info; 318cff7e81bSJeremy Fitzhardinge 319a649b720SJeremy Fitzhardinge info.submap_idx = index; 320a649b720SJeremy Fitzhardinge ret = HYPERVISOR_xen_version(XENVER_get_features, &info); 321cff7e81bSJeremy Fitzhardinge if (!ret) 322a649b720SJeremy Fitzhardinge ret = sprintf(buffer, "%08x", info.submap); 323cff7e81bSJeremy Fitzhardinge 324cff7e81bSJeremy Fitzhardinge return ret; 325cff7e81bSJeremy Fitzhardinge } 326cff7e81bSJeremy Fitzhardinge 327a649b720SJeremy Fitzhardinge static ssize_t features_show(struct hyp_sysfs_attr *attr, char *buffer) 328cff7e81bSJeremy Fitzhardinge { 329a649b720SJeremy Fitzhardinge ssize_t len; 330a649b720SJeremy Fitzhardinge int i; 331a649b720SJeremy Fitzhardinge 332a649b720SJeremy Fitzhardinge len = 0; 333a649b720SJeremy Fitzhardinge for (i = XENFEAT_NR_SUBMAPS-1; i >= 0; i--) { 334a649b720SJeremy Fitzhardinge int ret = xen_feature_show(i, buffer + len); 335a649b720SJeremy Fitzhardinge if (ret < 0) { 336a649b720SJeremy Fitzhardinge if (len == 0) 337a649b720SJeremy Fitzhardinge len = ret; 338a649b720SJeremy Fitzhardinge break; 339a649b720SJeremy Fitzhardinge } 340a649b720SJeremy Fitzhardinge len += ret; 341a649b720SJeremy Fitzhardinge } 342a649b720SJeremy Fitzhardinge if (len > 0) 343a649b720SJeremy Fitzhardinge buffer[len++] = '\n'; 344a649b720SJeremy Fitzhardinge 345a649b720SJeremy Fitzhardinge return len; 346cff7e81bSJeremy Fitzhardinge } 347cff7e81bSJeremy Fitzhardinge 348a649b720SJeremy Fitzhardinge HYPERVISOR_ATTR_RO(features); 349cff7e81bSJeremy Fitzhardinge 350cff7e81bSJeremy Fitzhardinge static struct attribute *xen_properties_attrs[] = { 351cff7e81bSJeremy Fitzhardinge &capabilities_attr.attr, 352cff7e81bSJeremy Fitzhardinge &changeset_attr.attr, 353cff7e81bSJeremy Fitzhardinge &virtual_start_attr.attr, 354cff7e81bSJeremy Fitzhardinge &pagesize_attr.attr, 355a649b720SJeremy Fitzhardinge &features_attr.attr, 356cff7e81bSJeremy Fitzhardinge NULL 357cff7e81bSJeremy Fitzhardinge }; 358cff7e81bSJeremy Fitzhardinge 359ead1d014SJan Beulich static const struct attribute_group xen_properties_group = { 360cff7e81bSJeremy Fitzhardinge .name = "properties", 361cff7e81bSJeremy Fitzhardinge .attrs = xen_properties_attrs, 362cff7e81bSJeremy Fitzhardinge }; 363cff7e81bSJeremy Fitzhardinge 364cff7e81bSJeremy Fitzhardinge static int __init xen_properties_init(void) 365cff7e81bSJeremy Fitzhardinge { 366cff7e81bSJeremy Fitzhardinge return sysfs_create_group(hypervisor_kobj, &xen_properties_group); 367cff7e81bSJeremy Fitzhardinge } 368cff7e81bSJeremy Fitzhardinge 369cff7e81bSJeremy Fitzhardinge static void xen_properties_destroy(void) 370cff7e81bSJeremy Fitzhardinge { 371cff7e81bSJeremy Fitzhardinge sysfs_remove_group(hypervisor_kobj, &xen_properties_group); 372cff7e81bSJeremy Fitzhardinge } 373cff7e81bSJeremy Fitzhardinge 374*5f141548SBoris Ostrovsky #ifdef CONFIG_XEN_HAVE_VPMU 375*5f141548SBoris Ostrovsky struct pmu_mode { 376*5f141548SBoris Ostrovsky const char *name; 377*5f141548SBoris Ostrovsky uint32_t mode; 378*5f141548SBoris Ostrovsky }; 379*5f141548SBoris Ostrovsky 380*5f141548SBoris Ostrovsky static struct pmu_mode pmu_modes[] = { 381*5f141548SBoris Ostrovsky {"off", XENPMU_MODE_OFF}, 382*5f141548SBoris Ostrovsky {"self", XENPMU_MODE_SELF}, 383*5f141548SBoris Ostrovsky {"hv", XENPMU_MODE_HV}, 384*5f141548SBoris Ostrovsky {"all", XENPMU_MODE_ALL} 385*5f141548SBoris Ostrovsky }; 386*5f141548SBoris Ostrovsky 387*5f141548SBoris Ostrovsky static ssize_t pmu_mode_store(struct hyp_sysfs_attr *attr, 388*5f141548SBoris Ostrovsky const char *buffer, size_t len) 389*5f141548SBoris Ostrovsky { 390*5f141548SBoris Ostrovsky int ret; 391*5f141548SBoris Ostrovsky struct xen_pmu_params xp; 392*5f141548SBoris Ostrovsky int i; 393*5f141548SBoris Ostrovsky 394*5f141548SBoris Ostrovsky for (i = 0; i < ARRAY_SIZE(pmu_modes); i++) { 395*5f141548SBoris Ostrovsky if (strncmp(buffer, pmu_modes[i].name, len - 1) == 0) { 396*5f141548SBoris Ostrovsky xp.val = pmu_modes[i].mode; 397*5f141548SBoris Ostrovsky break; 398*5f141548SBoris Ostrovsky } 399*5f141548SBoris Ostrovsky } 400*5f141548SBoris Ostrovsky 401*5f141548SBoris Ostrovsky if (i == ARRAY_SIZE(pmu_modes)) 402*5f141548SBoris Ostrovsky return -EINVAL; 403*5f141548SBoris Ostrovsky 404*5f141548SBoris Ostrovsky xp.version.maj = XENPMU_VER_MAJ; 405*5f141548SBoris Ostrovsky xp.version.min = XENPMU_VER_MIN; 406*5f141548SBoris Ostrovsky ret = HYPERVISOR_xenpmu_op(XENPMU_mode_set, &xp); 407*5f141548SBoris Ostrovsky if (ret) 408*5f141548SBoris Ostrovsky return ret; 409*5f141548SBoris Ostrovsky 410*5f141548SBoris Ostrovsky return len; 411*5f141548SBoris Ostrovsky } 412*5f141548SBoris Ostrovsky 413*5f141548SBoris Ostrovsky static ssize_t pmu_mode_show(struct hyp_sysfs_attr *attr, char *buffer) 414*5f141548SBoris Ostrovsky { 415*5f141548SBoris Ostrovsky int ret; 416*5f141548SBoris Ostrovsky struct xen_pmu_params xp; 417*5f141548SBoris Ostrovsky int i; 418*5f141548SBoris Ostrovsky uint32_t mode; 419*5f141548SBoris Ostrovsky 420*5f141548SBoris Ostrovsky xp.version.maj = XENPMU_VER_MAJ; 421*5f141548SBoris Ostrovsky xp.version.min = XENPMU_VER_MIN; 422*5f141548SBoris Ostrovsky ret = HYPERVISOR_xenpmu_op(XENPMU_mode_get, &xp); 423*5f141548SBoris Ostrovsky if (ret) 424*5f141548SBoris Ostrovsky return ret; 425*5f141548SBoris Ostrovsky 426*5f141548SBoris Ostrovsky mode = (uint32_t)xp.val; 427*5f141548SBoris Ostrovsky for (i = 0; i < ARRAY_SIZE(pmu_modes); i++) { 428*5f141548SBoris Ostrovsky if (mode == pmu_modes[i].mode) 429*5f141548SBoris Ostrovsky return sprintf(buffer, "%s\n", pmu_modes[i].name); 430*5f141548SBoris Ostrovsky } 431*5f141548SBoris Ostrovsky 432*5f141548SBoris Ostrovsky return -EINVAL; 433*5f141548SBoris Ostrovsky } 434*5f141548SBoris Ostrovsky HYPERVISOR_ATTR_RW(pmu_mode); 435*5f141548SBoris Ostrovsky 436*5f141548SBoris Ostrovsky static ssize_t pmu_features_store(struct hyp_sysfs_attr *attr, 437*5f141548SBoris Ostrovsky const char *buffer, size_t len) 438*5f141548SBoris Ostrovsky { 439*5f141548SBoris Ostrovsky int ret; 440*5f141548SBoris Ostrovsky uint32_t features; 441*5f141548SBoris Ostrovsky struct xen_pmu_params xp; 442*5f141548SBoris Ostrovsky 443*5f141548SBoris Ostrovsky ret = kstrtou32(buffer, 0, &features); 444*5f141548SBoris Ostrovsky if (ret) 445*5f141548SBoris Ostrovsky return ret; 446*5f141548SBoris Ostrovsky 447*5f141548SBoris Ostrovsky xp.val = features; 448*5f141548SBoris Ostrovsky xp.version.maj = XENPMU_VER_MAJ; 449*5f141548SBoris Ostrovsky xp.version.min = XENPMU_VER_MIN; 450*5f141548SBoris Ostrovsky ret = HYPERVISOR_xenpmu_op(XENPMU_feature_set, &xp); 451*5f141548SBoris Ostrovsky if (ret) 452*5f141548SBoris Ostrovsky return ret; 453*5f141548SBoris Ostrovsky 454*5f141548SBoris Ostrovsky return len; 455*5f141548SBoris Ostrovsky } 456*5f141548SBoris Ostrovsky 457*5f141548SBoris Ostrovsky static ssize_t pmu_features_show(struct hyp_sysfs_attr *attr, char *buffer) 458*5f141548SBoris Ostrovsky { 459*5f141548SBoris Ostrovsky int ret; 460*5f141548SBoris Ostrovsky struct xen_pmu_params xp; 461*5f141548SBoris Ostrovsky 462*5f141548SBoris Ostrovsky xp.version.maj = XENPMU_VER_MAJ; 463*5f141548SBoris Ostrovsky xp.version.min = XENPMU_VER_MIN; 464*5f141548SBoris Ostrovsky ret = HYPERVISOR_xenpmu_op(XENPMU_feature_get, &xp); 465*5f141548SBoris Ostrovsky if (ret) 466*5f141548SBoris Ostrovsky return ret; 467*5f141548SBoris Ostrovsky 468*5f141548SBoris Ostrovsky return sprintf(buffer, "0x%x\n", (uint32_t)xp.val); 469*5f141548SBoris Ostrovsky } 470*5f141548SBoris Ostrovsky HYPERVISOR_ATTR_RW(pmu_features); 471*5f141548SBoris Ostrovsky 472*5f141548SBoris Ostrovsky static struct attribute *xen_pmu_attrs[] = { 473*5f141548SBoris Ostrovsky &pmu_mode_attr.attr, 474*5f141548SBoris Ostrovsky &pmu_features_attr.attr, 475*5f141548SBoris Ostrovsky NULL 476*5f141548SBoris Ostrovsky }; 477*5f141548SBoris Ostrovsky 478*5f141548SBoris Ostrovsky static const struct attribute_group xen_pmu_group = { 479*5f141548SBoris Ostrovsky .name = "pmu", 480*5f141548SBoris Ostrovsky .attrs = xen_pmu_attrs, 481*5f141548SBoris Ostrovsky }; 482*5f141548SBoris Ostrovsky 483*5f141548SBoris Ostrovsky static int __init xen_pmu_init(void) 484*5f141548SBoris Ostrovsky { 485*5f141548SBoris Ostrovsky return sysfs_create_group(hypervisor_kobj, &xen_pmu_group); 486*5f141548SBoris Ostrovsky } 487*5f141548SBoris Ostrovsky 488*5f141548SBoris Ostrovsky static void xen_pmu_destroy(void) 489*5f141548SBoris Ostrovsky { 490*5f141548SBoris Ostrovsky sysfs_remove_group(hypervisor_kobj, &xen_pmu_group); 491*5f141548SBoris Ostrovsky } 492*5f141548SBoris Ostrovsky #endif 493*5f141548SBoris Ostrovsky 494cff7e81bSJeremy Fitzhardinge static int __init hyper_sysfs_init(void) 495cff7e81bSJeremy Fitzhardinge { 496cff7e81bSJeremy Fitzhardinge int ret; 497cff7e81bSJeremy Fitzhardinge 498cff7e81bSJeremy Fitzhardinge if (!xen_domain()) 499cff7e81bSJeremy Fitzhardinge return -ENODEV; 500cff7e81bSJeremy Fitzhardinge 501cff7e81bSJeremy Fitzhardinge ret = xen_sysfs_type_init(); 502cff7e81bSJeremy Fitzhardinge if (ret) 503cff7e81bSJeremy Fitzhardinge goto out; 504cff7e81bSJeremy Fitzhardinge ret = xen_sysfs_version_init(); 505cff7e81bSJeremy Fitzhardinge if (ret) 506cff7e81bSJeremy Fitzhardinge goto version_out; 507cff7e81bSJeremy Fitzhardinge ret = xen_compilation_init(); 508cff7e81bSJeremy Fitzhardinge if (ret) 509cff7e81bSJeremy Fitzhardinge goto comp_out; 510cff7e81bSJeremy Fitzhardinge ret = xen_sysfs_uuid_init(); 511cff7e81bSJeremy Fitzhardinge if (ret) 512cff7e81bSJeremy Fitzhardinge goto uuid_out; 513cff7e81bSJeremy Fitzhardinge ret = xen_properties_init(); 514cff7e81bSJeremy Fitzhardinge if (ret) 515cff7e81bSJeremy Fitzhardinge goto prop_out; 516*5f141548SBoris Ostrovsky #ifdef CONFIG_XEN_HAVE_VPMU 517*5f141548SBoris Ostrovsky if (xen_initial_domain()) { 518*5f141548SBoris Ostrovsky ret = xen_pmu_init(); 519*5f141548SBoris Ostrovsky if (ret) { 520*5f141548SBoris Ostrovsky xen_properties_destroy(); 521*5f141548SBoris Ostrovsky goto prop_out; 522*5f141548SBoris Ostrovsky } 523*5f141548SBoris Ostrovsky } 524*5f141548SBoris Ostrovsky #endif 525cff7e81bSJeremy Fitzhardinge goto out; 526cff7e81bSJeremy Fitzhardinge 527cff7e81bSJeremy Fitzhardinge prop_out: 528cff7e81bSJeremy Fitzhardinge xen_sysfs_uuid_destroy(); 529cff7e81bSJeremy Fitzhardinge uuid_out: 530cff7e81bSJeremy Fitzhardinge xen_compilation_destroy(); 531cff7e81bSJeremy Fitzhardinge comp_out: 532cff7e81bSJeremy Fitzhardinge xen_sysfs_version_destroy(); 533cff7e81bSJeremy Fitzhardinge version_out: 534cff7e81bSJeremy Fitzhardinge xen_sysfs_type_destroy(); 535cff7e81bSJeremy Fitzhardinge out: 536cff7e81bSJeremy Fitzhardinge return ret; 537cff7e81bSJeremy Fitzhardinge } 538cff7e81bSJeremy Fitzhardinge 539cff7e81bSJeremy Fitzhardinge static void __exit hyper_sysfs_exit(void) 540cff7e81bSJeremy Fitzhardinge { 541*5f141548SBoris Ostrovsky #ifdef CONFIG_XEN_HAVE_VPMU 542*5f141548SBoris Ostrovsky xen_pmu_destroy(); 543*5f141548SBoris Ostrovsky #endif 544cff7e81bSJeremy Fitzhardinge xen_properties_destroy(); 545cff7e81bSJeremy Fitzhardinge xen_compilation_destroy(); 546cff7e81bSJeremy Fitzhardinge xen_sysfs_uuid_destroy(); 547cff7e81bSJeremy Fitzhardinge xen_sysfs_version_destroy(); 548cff7e81bSJeremy Fitzhardinge xen_sysfs_type_destroy(); 549cff7e81bSJeremy Fitzhardinge 550cff7e81bSJeremy Fitzhardinge } 551cff7e81bSJeremy Fitzhardinge module_init(hyper_sysfs_init); 552cff7e81bSJeremy Fitzhardinge module_exit(hyper_sysfs_exit); 553cff7e81bSJeremy Fitzhardinge 554cff7e81bSJeremy Fitzhardinge static ssize_t hyp_sysfs_show(struct kobject *kobj, 555cff7e81bSJeremy Fitzhardinge struct attribute *attr, 556cff7e81bSJeremy Fitzhardinge char *buffer) 557cff7e81bSJeremy Fitzhardinge { 558cff7e81bSJeremy Fitzhardinge struct hyp_sysfs_attr *hyp_attr; 559cff7e81bSJeremy Fitzhardinge hyp_attr = container_of(attr, struct hyp_sysfs_attr, attr); 560cff7e81bSJeremy Fitzhardinge if (hyp_attr->show) 561cff7e81bSJeremy Fitzhardinge return hyp_attr->show(hyp_attr, buffer); 562cff7e81bSJeremy Fitzhardinge return 0; 563cff7e81bSJeremy Fitzhardinge } 564cff7e81bSJeremy Fitzhardinge 565cff7e81bSJeremy Fitzhardinge static ssize_t hyp_sysfs_store(struct kobject *kobj, 566cff7e81bSJeremy Fitzhardinge struct attribute *attr, 567cff7e81bSJeremy Fitzhardinge const char *buffer, 568cff7e81bSJeremy Fitzhardinge size_t len) 569cff7e81bSJeremy Fitzhardinge { 570cff7e81bSJeremy Fitzhardinge struct hyp_sysfs_attr *hyp_attr; 571cff7e81bSJeremy Fitzhardinge hyp_attr = container_of(attr, struct hyp_sysfs_attr, attr); 572cff7e81bSJeremy Fitzhardinge if (hyp_attr->store) 573cff7e81bSJeremy Fitzhardinge return hyp_attr->store(hyp_attr, buffer, len); 574cff7e81bSJeremy Fitzhardinge return 0; 575cff7e81bSJeremy Fitzhardinge } 576cff7e81bSJeremy Fitzhardinge 57752cf25d0SEmese Revfy static const struct sysfs_ops hyp_sysfs_ops = { 578cff7e81bSJeremy Fitzhardinge .show = hyp_sysfs_show, 579cff7e81bSJeremy Fitzhardinge .store = hyp_sysfs_store, 580cff7e81bSJeremy Fitzhardinge }; 581cff7e81bSJeremy Fitzhardinge 582cff7e81bSJeremy Fitzhardinge static struct kobj_type hyp_sysfs_kobj_type = { 583cff7e81bSJeremy Fitzhardinge .sysfs_ops = &hyp_sysfs_ops, 584cff7e81bSJeremy Fitzhardinge }; 585cff7e81bSJeremy Fitzhardinge 586cff7e81bSJeremy Fitzhardinge static int __init hypervisor_subsys_init(void) 587cff7e81bSJeremy Fitzhardinge { 588cff7e81bSJeremy Fitzhardinge if (!xen_domain()) 589cff7e81bSJeremy Fitzhardinge return -ENODEV; 590cff7e81bSJeremy Fitzhardinge 591cff7e81bSJeremy Fitzhardinge hypervisor_kobj->ktype = &hyp_sysfs_kobj_type; 592cff7e81bSJeremy Fitzhardinge return 0; 593cff7e81bSJeremy Fitzhardinge } 594cff7e81bSJeremy Fitzhardinge device_initcall(hypervisor_subsys_init); 595