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> 1246894f17SPaul Gortmaker #include <linux/init.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> 235f141548SBoris Ostrovsky #ifdef CONFIG_XEN_HAVE_VPMU 245f141548SBoris Ostrovsky #include <xen/interface/xenpmu.h> 255f141548SBoris 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 534a4c29c9SJuergen Gross static ssize_t guest_type_show(struct hyp_sysfs_attr *attr, char *buffer) 544a4c29c9SJuergen Gross { 554a4c29c9SJuergen Gross const char *type; 564a4c29c9SJuergen Gross 574a4c29c9SJuergen Gross switch (xen_domain_type) { 584a4c29c9SJuergen Gross case XEN_NATIVE: 594a4c29c9SJuergen Gross /* ARM only. */ 604a4c29c9SJuergen Gross type = "Xen"; 614a4c29c9SJuergen Gross break; 624a4c29c9SJuergen Gross case XEN_PV_DOMAIN: 634a4c29c9SJuergen Gross type = "PV"; 644a4c29c9SJuergen Gross break; 654a4c29c9SJuergen Gross case XEN_HVM_DOMAIN: 664a4c29c9SJuergen Gross type = xen_pvh_domain() ? "PVH" : "HVM"; 674a4c29c9SJuergen Gross break; 684a4c29c9SJuergen Gross default: 694a4c29c9SJuergen Gross return -EINVAL; 704a4c29c9SJuergen Gross } 714a4c29c9SJuergen Gross 724a4c29c9SJuergen Gross return sprintf(buffer, "%s\n", type); 734a4c29c9SJuergen Gross } 744a4c29c9SJuergen Gross 754a4c29c9SJuergen Gross HYPERVISOR_ATTR_RO(guest_type); 764a4c29c9SJuergen Gross 774a4c29c9SJuergen Gross static int __init xen_sysfs_guest_type_init(void) 784a4c29c9SJuergen Gross { 794a4c29c9SJuergen Gross return sysfs_create_file(hypervisor_kobj, &guest_type_attr.attr); 804a4c29c9SJuergen Gross } 814a4c29c9SJuergen Gross 82cff7e81bSJeremy Fitzhardinge /* xen version attributes */ 83cff7e81bSJeremy Fitzhardinge static ssize_t major_show(struct hyp_sysfs_attr *attr, char *buffer) 84cff7e81bSJeremy Fitzhardinge { 85cff7e81bSJeremy Fitzhardinge int version = HYPERVISOR_xen_version(XENVER_version, NULL); 86cff7e81bSJeremy Fitzhardinge if (version) 87cff7e81bSJeremy Fitzhardinge return sprintf(buffer, "%d\n", version >> 16); 88cff7e81bSJeremy Fitzhardinge return -ENODEV; 89cff7e81bSJeremy Fitzhardinge } 90cff7e81bSJeremy Fitzhardinge 91cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(major); 92cff7e81bSJeremy Fitzhardinge 93cff7e81bSJeremy Fitzhardinge static ssize_t minor_show(struct hyp_sysfs_attr *attr, char *buffer) 94cff7e81bSJeremy Fitzhardinge { 95cff7e81bSJeremy Fitzhardinge int version = HYPERVISOR_xen_version(XENVER_version, NULL); 96cff7e81bSJeremy Fitzhardinge if (version) 97cff7e81bSJeremy Fitzhardinge return sprintf(buffer, "%d\n", version & 0xff); 98cff7e81bSJeremy Fitzhardinge return -ENODEV; 99cff7e81bSJeremy Fitzhardinge } 100cff7e81bSJeremy Fitzhardinge 101cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(minor); 102cff7e81bSJeremy Fitzhardinge 103cff7e81bSJeremy Fitzhardinge static ssize_t extra_show(struct hyp_sysfs_attr *attr, char *buffer) 104cff7e81bSJeremy Fitzhardinge { 105cff7e81bSJeremy Fitzhardinge int ret = -ENOMEM; 106cff7e81bSJeremy Fitzhardinge char *extra; 107cff7e81bSJeremy Fitzhardinge 108cff7e81bSJeremy Fitzhardinge extra = kmalloc(XEN_EXTRAVERSION_LEN, GFP_KERNEL); 109cff7e81bSJeremy Fitzhardinge if (extra) { 110cff7e81bSJeremy Fitzhardinge ret = HYPERVISOR_xen_version(XENVER_extraversion, extra); 111cff7e81bSJeremy Fitzhardinge if (!ret) 112cff7e81bSJeremy Fitzhardinge ret = sprintf(buffer, "%s\n", extra); 113cff7e81bSJeremy Fitzhardinge kfree(extra); 114cff7e81bSJeremy Fitzhardinge } 115cff7e81bSJeremy Fitzhardinge 116cff7e81bSJeremy Fitzhardinge return ret; 117cff7e81bSJeremy Fitzhardinge } 118cff7e81bSJeremy Fitzhardinge 119cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(extra); 120cff7e81bSJeremy Fitzhardinge 121cff7e81bSJeremy Fitzhardinge static struct attribute *version_attrs[] = { 122cff7e81bSJeremy Fitzhardinge &major_attr.attr, 123cff7e81bSJeremy Fitzhardinge &minor_attr.attr, 124cff7e81bSJeremy Fitzhardinge &extra_attr.attr, 125cff7e81bSJeremy Fitzhardinge NULL 126cff7e81bSJeremy Fitzhardinge }; 127cff7e81bSJeremy Fitzhardinge 128ead1d014SJan Beulich static const struct attribute_group version_group = { 129cff7e81bSJeremy Fitzhardinge .name = "version", 130cff7e81bSJeremy Fitzhardinge .attrs = version_attrs, 131cff7e81bSJeremy Fitzhardinge }; 132cff7e81bSJeremy Fitzhardinge 133cff7e81bSJeremy Fitzhardinge static int __init xen_sysfs_version_init(void) 134cff7e81bSJeremy Fitzhardinge { 135cff7e81bSJeremy Fitzhardinge return sysfs_create_group(hypervisor_kobj, &version_group); 136cff7e81bSJeremy Fitzhardinge } 137cff7e81bSJeremy Fitzhardinge 138cff7e81bSJeremy Fitzhardinge /* UUID */ 139cff7e81bSJeremy Fitzhardinge 1405c13f806SDaniel De Graaf static ssize_t uuid_show_fallback(struct hyp_sysfs_attr *attr, char *buffer) 141cff7e81bSJeremy Fitzhardinge { 142cff7e81bSJeremy Fitzhardinge char *vm, *val; 143cff7e81bSJeremy Fitzhardinge int ret; 144cff7e81bSJeremy Fitzhardinge extern int xenstored_ready; 145cff7e81bSJeremy Fitzhardinge 146cff7e81bSJeremy Fitzhardinge if (!xenstored_ready) 147cff7e81bSJeremy Fitzhardinge return -EBUSY; 148cff7e81bSJeremy Fitzhardinge 149cff7e81bSJeremy Fitzhardinge vm = xenbus_read(XBT_NIL, "vm", "", NULL); 150cff7e81bSJeremy Fitzhardinge if (IS_ERR(vm)) 151cff7e81bSJeremy Fitzhardinge return PTR_ERR(vm); 152cff7e81bSJeremy Fitzhardinge val = xenbus_read(XBT_NIL, vm, "uuid", NULL); 153cff7e81bSJeremy Fitzhardinge kfree(vm); 154cff7e81bSJeremy Fitzhardinge if (IS_ERR(val)) 155cff7e81bSJeremy Fitzhardinge return PTR_ERR(val); 156cff7e81bSJeremy Fitzhardinge ret = sprintf(buffer, "%s\n", val); 157cff7e81bSJeremy Fitzhardinge kfree(val); 158cff7e81bSJeremy Fitzhardinge return ret; 159cff7e81bSJeremy Fitzhardinge } 160cff7e81bSJeremy Fitzhardinge 1615c13f806SDaniel De Graaf static ssize_t uuid_show(struct hyp_sysfs_attr *attr, char *buffer) 1625c13f806SDaniel De Graaf { 1635c13f806SDaniel De Graaf xen_domain_handle_t uuid; 1645c13f806SDaniel De Graaf int ret; 1655c13f806SDaniel De Graaf ret = HYPERVISOR_xen_version(XENVER_guest_handle, uuid); 1665c13f806SDaniel De Graaf if (ret) 1675c13f806SDaniel De Graaf return uuid_show_fallback(attr, buffer); 1685c13f806SDaniel De Graaf ret = sprintf(buffer, "%pU\n", uuid); 1695c13f806SDaniel De Graaf return ret; 1705c13f806SDaniel De Graaf } 1715c13f806SDaniel De Graaf 172cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(uuid); 173cff7e81bSJeremy Fitzhardinge 174cff7e81bSJeremy Fitzhardinge static int __init xen_sysfs_uuid_init(void) 175cff7e81bSJeremy Fitzhardinge { 176cff7e81bSJeremy Fitzhardinge return sysfs_create_file(hypervisor_kobj, &uuid_attr.attr); 177cff7e81bSJeremy Fitzhardinge } 178cff7e81bSJeremy Fitzhardinge 179cff7e81bSJeremy Fitzhardinge /* xen compilation attributes */ 180cff7e81bSJeremy Fitzhardinge 181cff7e81bSJeremy Fitzhardinge static ssize_t compiler_show(struct hyp_sysfs_attr *attr, char *buffer) 182cff7e81bSJeremy Fitzhardinge { 183cff7e81bSJeremy Fitzhardinge int ret = -ENOMEM; 184cff7e81bSJeremy Fitzhardinge struct xen_compile_info *info; 185cff7e81bSJeremy Fitzhardinge 186cff7e81bSJeremy Fitzhardinge info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL); 187cff7e81bSJeremy Fitzhardinge if (info) { 188cff7e81bSJeremy Fitzhardinge ret = HYPERVISOR_xen_version(XENVER_compile_info, info); 189cff7e81bSJeremy Fitzhardinge if (!ret) 190cff7e81bSJeremy Fitzhardinge ret = sprintf(buffer, "%s\n", info->compiler); 191cff7e81bSJeremy Fitzhardinge kfree(info); 192cff7e81bSJeremy Fitzhardinge } 193cff7e81bSJeremy Fitzhardinge 194cff7e81bSJeremy Fitzhardinge return ret; 195cff7e81bSJeremy Fitzhardinge } 196cff7e81bSJeremy Fitzhardinge 197cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(compiler); 198cff7e81bSJeremy Fitzhardinge 199cff7e81bSJeremy Fitzhardinge static ssize_t compiled_by_show(struct hyp_sysfs_attr *attr, char *buffer) 200cff7e81bSJeremy Fitzhardinge { 201cff7e81bSJeremy Fitzhardinge int ret = -ENOMEM; 202cff7e81bSJeremy Fitzhardinge struct xen_compile_info *info; 203cff7e81bSJeremy Fitzhardinge 204cff7e81bSJeremy Fitzhardinge info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL); 205cff7e81bSJeremy Fitzhardinge if (info) { 206cff7e81bSJeremy Fitzhardinge ret = HYPERVISOR_xen_version(XENVER_compile_info, info); 207cff7e81bSJeremy Fitzhardinge if (!ret) 208cff7e81bSJeremy Fitzhardinge ret = sprintf(buffer, "%s\n", info->compile_by); 209cff7e81bSJeremy Fitzhardinge kfree(info); 210cff7e81bSJeremy Fitzhardinge } 211cff7e81bSJeremy Fitzhardinge 212cff7e81bSJeremy Fitzhardinge return ret; 213cff7e81bSJeremy Fitzhardinge } 214cff7e81bSJeremy Fitzhardinge 215cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(compiled_by); 216cff7e81bSJeremy Fitzhardinge 217cff7e81bSJeremy Fitzhardinge static ssize_t compile_date_show(struct hyp_sysfs_attr *attr, char *buffer) 218cff7e81bSJeremy Fitzhardinge { 219cff7e81bSJeremy Fitzhardinge int ret = -ENOMEM; 220cff7e81bSJeremy Fitzhardinge struct xen_compile_info *info; 221cff7e81bSJeremy Fitzhardinge 222cff7e81bSJeremy Fitzhardinge info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL); 223cff7e81bSJeremy Fitzhardinge if (info) { 224cff7e81bSJeremy Fitzhardinge ret = HYPERVISOR_xen_version(XENVER_compile_info, info); 225cff7e81bSJeremy Fitzhardinge if (!ret) 226cff7e81bSJeremy Fitzhardinge ret = sprintf(buffer, "%s\n", info->compile_date); 227cff7e81bSJeremy Fitzhardinge kfree(info); 228cff7e81bSJeremy Fitzhardinge } 229cff7e81bSJeremy Fitzhardinge 230cff7e81bSJeremy Fitzhardinge return ret; 231cff7e81bSJeremy Fitzhardinge } 232cff7e81bSJeremy Fitzhardinge 233cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(compile_date); 234cff7e81bSJeremy Fitzhardinge 235cff7e81bSJeremy Fitzhardinge static struct attribute *xen_compile_attrs[] = { 236cff7e81bSJeremy Fitzhardinge &compiler_attr.attr, 237cff7e81bSJeremy Fitzhardinge &compiled_by_attr.attr, 238cff7e81bSJeremy Fitzhardinge &compile_date_attr.attr, 239cff7e81bSJeremy Fitzhardinge NULL 240cff7e81bSJeremy Fitzhardinge }; 241cff7e81bSJeremy Fitzhardinge 242ead1d014SJan Beulich static const struct attribute_group xen_compilation_group = { 243cff7e81bSJeremy Fitzhardinge .name = "compilation", 244cff7e81bSJeremy Fitzhardinge .attrs = xen_compile_attrs, 245cff7e81bSJeremy Fitzhardinge }; 246cff7e81bSJeremy Fitzhardinge 2475b00b504SJuergen Gross static int __init xen_sysfs_compilation_init(void) 248cff7e81bSJeremy Fitzhardinge { 249cff7e81bSJeremy Fitzhardinge return sysfs_create_group(hypervisor_kobj, &xen_compilation_group); 250cff7e81bSJeremy Fitzhardinge } 251cff7e81bSJeremy Fitzhardinge 252cff7e81bSJeremy Fitzhardinge /* xen properties info */ 253cff7e81bSJeremy Fitzhardinge 254cff7e81bSJeremy Fitzhardinge static ssize_t capabilities_show(struct hyp_sysfs_attr *attr, char *buffer) 255cff7e81bSJeremy Fitzhardinge { 256cff7e81bSJeremy Fitzhardinge int ret = -ENOMEM; 257cff7e81bSJeremy Fitzhardinge char *caps; 258cff7e81bSJeremy Fitzhardinge 259cff7e81bSJeremy Fitzhardinge caps = kmalloc(XEN_CAPABILITIES_INFO_LEN, GFP_KERNEL); 260cff7e81bSJeremy Fitzhardinge if (caps) { 261cff7e81bSJeremy Fitzhardinge ret = HYPERVISOR_xen_version(XENVER_capabilities, caps); 262cff7e81bSJeremy Fitzhardinge if (!ret) 263cff7e81bSJeremy Fitzhardinge ret = sprintf(buffer, "%s\n", caps); 264cff7e81bSJeremy Fitzhardinge kfree(caps); 265cff7e81bSJeremy Fitzhardinge } 266cff7e81bSJeremy Fitzhardinge 267cff7e81bSJeremy Fitzhardinge return ret; 268cff7e81bSJeremy Fitzhardinge } 269cff7e81bSJeremy Fitzhardinge 270cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(capabilities); 271cff7e81bSJeremy Fitzhardinge 272cff7e81bSJeremy Fitzhardinge static ssize_t changeset_show(struct hyp_sysfs_attr *attr, char *buffer) 273cff7e81bSJeremy Fitzhardinge { 274cff7e81bSJeremy Fitzhardinge int ret = -ENOMEM; 275cff7e81bSJeremy Fitzhardinge char *cset; 276cff7e81bSJeremy Fitzhardinge 277cff7e81bSJeremy Fitzhardinge cset = kmalloc(XEN_CHANGESET_INFO_LEN, GFP_KERNEL); 278cff7e81bSJeremy Fitzhardinge if (cset) { 279cff7e81bSJeremy Fitzhardinge ret = HYPERVISOR_xen_version(XENVER_changeset, cset); 280cff7e81bSJeremy Fitzhardinge if (!ret) 281cff7e81bSJeremy Fitzhardinge ret = sprintf(buffer, "%s\n", cset); 282cff7e81bSJeremy Fitzhardinge kfree(cset); 283cff7e81bSJeremy Fitzhardinge } 284cff7e81bSJeremy Fitzhardinge 285cff7e81bSJeremy Fitzhardinge return ret; 286cff7e81bSJeremy Fitzhardinge } 287cff7e81bSJeremy Fitzhardinge 288cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(changeset); 289cff7e81bSJeremy Fitzhardinge 290cff7e81bSJeremy Fitzhardinge static ssize_t virtual_start_show(struct hyp_sysfs_attr *attr, char *buffer) 291cff7e81bSJeremy Fitzhardinge { 292cff7e81bSJeremy Fitzhardinge int ret = -ENOMEM; 293cff7e81bSJeremy Fitzhardinge struct xen_platform_parameters *parms; 294cff7e81bSJeremy Fitzhardinge 295cff7e81bSJeremy Fitzhardinge parms = kmalloc(sizeof(struct xen_platform_parameters), GFP_KERNEL); 296cff7e81bSJeremy Fitzhardinge if (parms) { 297cff7e81bSJeremy Fitzhardinge ret = HYPERVISOR_xen_version(XENVER_platform_parameters, 298cff7e81bSJeremy Fitzhardinge parms); 299cff7e81bSJeremy Fitzhardinge if (!ret) 30037ea0fcbSIan Campbell ret = sprintf(buffer, "%"PRI_xen_ulong"\n", 30137ea0fcbSIan Campbell parms->virt_start); 302cff7e81bSJeremy Fitzhardinge kfree(parms); 303cff7e81bSJeremy Fitzhardinge } 304cff7e81bSJeremy Fitzhardinge 305cff7e81bSJeremy Fitzhardinge return ret; 306cff7e81bSJeremy Fitzhardinge } 307cff7e81bSJeremy Fitzhardinge 308cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(virtual_start); 309cff7e81bSJeremy Fitzhardinge 310cff7e81bSJeremy Fitzhardinge static ssize_t pagesize_show(struct hyp_sysfs_attr *attr, char *buffer) 311cff7e81bSJeremy Fitzhardinge { 312cff7e81bSJeremy Fitzhardinge int ret; 313cff7e81bSJeremy Fitzhardinge 314cff7e81bSJeremy Fitzhardinge ret = HYPERVISOR_xen_version(XENVER_pagesize, NULL); 315cff7e81bSJeremy Fitzhardinge if (ret > 0) 316cff7e81bSJeremy Fitzhardinge ret = sprintf(buffer, "%x\n", ret); 317cff7e81bSJeremy Fitzhardinge 318cff7e81bSJeremy Fitzhardinge return ret; 319cff7e81bSJeremy Fitzhardinge } 320cff7e81bSJeremy Fitzhardinge 321cff7e81bSJeremy Fitzhardinge HYPERVISOR_ATTR_RO(pagesize); 322cff7e81bSJeremy Fitzhardinge 323cff7e81bSJeremy Fitzhardinge static ssize_t xen_feature_show(int index, char *buffer) 324cff7e81bSJeremy Fitzhardinge { 325a649b720SJeremy Fitzhardinge ssize_t ret; 326a649b720SJeremy Fitzhardinge struct xen_feature_info info; 327cff7e81bSJeremy Fitzhardinge 328a649b720SJeremy Fitzhardinge info.submap_idx = index; 329a649b720SJeremy Fitzhardinge ret = HYPERVISOR_xen_version(XENVER_get_features, &info); 330cff7e81bSJeremy Fitzhardinge if (!ret) 331a649b720SJeremy Fitzhardinge ret = sprintf(buffer, "%08x", info.submap); 332cff7e81bSJeremy Fitzhardinge 333cff7e81bSJeremy Fitzhardinge return ret; 334cff7e81bSJeremy Fitzhardinge } 335cff7e81bSJeremy Fitzhardinge 336a649b720SJeremy Fitzhardinge static ssize_t features_show(struct hyp_sysfs_attr *attr, char *buffer) 337cff7e81bSJeremy Fitzhardinge { 338a649b720SJeremy Fitzhardinge ssize_t len; 339a649b720SJeremy Fitzhardinge int i; 340a649b720SJeremy Fitzhardinge 341a649b720SJeremy Fitzhardinge len = 0; 342a649b720SJeremy Fitzhardinge for (i = XENFEAT_NR_SUBMAPS-1; i >= 0; i--) { 343a649b720SJeremy Fitzhardinge int ret = xen_feature_show(i, buffer + len); 344a649b720SJeremy Fitzhardinge if (ret < 0) { 345a649b720SJeremy Fitzhardinge if (len == 0) 346a649b720SJeremy Fitzhardinge len = ret; 347a649b720SJeremy Fitzhardinge break; 348a649b720SJeremy Fitzhardinge } 349a649b720SJeremy Fitzhardinge len += ret; 350a649b720SJeremy Fitzhardinge } 351a649b720SJeremy Fitzhardinge if (len > 0) 352a649b720SJeremy Fitzhardinge buffer[len++] = '\n'; 353a649b720SJeremy Fitzhardinge 354a649b720SJeremy Fitzhardinge return len; 355cff7e81bSJeremy Fitzhardinge } 356cff7e81bSJeremy Fitzhardinge 357a649b720SJeremy Fitzhardinge HYPERVISOR_ATTR_RO(features); 358cff7e81bSJeremy Fitzhardinge 359*84b76257SJuergen Gross static ssize_t buildid_show(struct hyp_sysfs_attr *attr, char *buffer) 360*84b76257SJuergen Gross { 361*84b76257SJuergen Gross ssize_t ret; 362*84b76257SJuergen Gross struct xen_build_id *buildid; 363*84b76257SJuergen Gross 364*84b76257SJuergen Gross ret = HYPERVISOR_xen_version(XENVER_build_id, NULL); 365*84b76257SJuergen Gross if (ret < 0) { 366*84b76257SJuergen Gross if (ret == -EPERM) 367*84b76257SJuergen Gross ret = sprintf(buffer, "<denied>"); 368*84b76257SJuergen Gross return ret; 369*84b76257SJuergen Gross } 370*84b76257SJuergen Gross 371*84b76257SJuergen Gross buildid = kmalloc(sizeof(*buildid) + ret, GFP_KERNEL); 372*84b76257SJuergen Gross if (!buildid) 373*84b76257SJuergen Gross return -ENOMEM; 374*84b76257SJuergen Gross 375*84b76257SJuergen Gross buildid->len = ret; 376*84b76257SJuergen Gross ret = HYPERVISOR_xen_version(XENVER_build_id, buildid); 377*84b76257SJuergen Gross if (ret > 0) 378*84b76257SJuergen Gross ret = sprintf(buffer, "%s", buildid->buf); 379*84b76257SJuergen Gross kfree(buildid); 380*84b76257SJuergen Gross 381*84b76257SJuergen Gross return ret; 382*84b76257SJuergen Gross } 383*84b76257SJuergen Gross 384*84b76257SJuergen Gross HYPERVISOR_ATTR_RO(buildid); 385*84b76257SJuergen Gross 386cff7e81bSJeremy Fitzhardinge static struct attribute *xen_properties_attrs[] = { 387cff7e81bSJeremy Fitzhardinge &capabilities_attr.attr, 388cff7e81bSJeremy Fitzhardinge &changeset_attr.attr, 389cff7e81bSJeremy Fitzhardinge &virtual_start_attr.attr, 390cff7e81bSJeremy Fitzhardinge &pagesize_attr.attr, 391a649b720SJeremy Fitzhardinge &features_attr.attr, 392*84b76257SJuergen Gross &buildid_attr.attr, 393cff7e81bSJeremy Fitzhardinge NULL 394cff7e81bSJeremy Fitzhardinge }; 395cff7e81bSJeremy Fitzhardinge 396ead1d014SJan Beulich static const struct attribute_group xen_properties_group = { 397cff7e81bSJeremy Fitzhardinge .name = "properties", 398cff7e81bSJeremy Fitzhardinge .attrs = xen_properties_attrs, 399cff7e81bSJeremy Fitzhardinge }; 400cff7e81bSJeremy Fitzhardinge 4015b00b504SJuergen Gross static int __init xen_sysfs_properties_init(void) 402cff7e81bSJeremy Fitzhardinge { 403cff7e81bSJeremy Fitzhardinge return sysfs_create_group(hypervisor_kobj, &xen_properties_group); 404cff7e81bSJeremy Fitzhardinge } 405cff7e81bSJeremy Fitzhardinge 4065f141548SBoris Ostrovsky #ifdef CONFIG_XEN_HAVE_VPMU 4075f141548SBoris Ostrovsky struct pmu_mode { 4085f141548SBoris Ostrovsky const char *name; 4095f141548SBoris Ostrovsky uint32_t mode; 4105f141548SBoris Ostrovsky }; 4115f141548SBoris Ostrovsky 4125f141548SBoris Ostrovsky static struct pmu_mode pmu_modes[] = { 4135f141548SBoris Ostrovsky {"off", XENPMU_MODE_OFF}, 4145f141548SBoris Ostrovsky {"self", XENPMU_MODE_SELF}, 4155f141548SBoris Ostrovsky {"hv", XENPMU_MODE_HV}, 4165f141548SBoris Ostrovsky {"all", XENPMU_MODE_ALL} 4175f141548SBoris Ostrovsky }; 4185f141548SBoris Ostrovsky 4195f141548SBoris Ostrovsky static ssize_t pmu_mode_store(struct hyp_sysfs_attr *attr, 4205f141548SBoris Ostrovsky const char *buffer, size_t len) 4215f141548SBoris Ostrovsky { 4225f141548SBoris Ostrovsky int ret; 4235f141548SBoris Ostrovsky struct xen_pmu_params xp; 4245f141548SBoris Ostrovsky int i; 4255f141548SBoris Ostrovsky 4265f141548SBoris Ostrovsky for (i = 0; i < ARRAY_SIZE(pmu_modes); i++) { 4275f141548SBoris Ostrovsky if (strncmp(buffer, pmu_modes[i].name, len - 1) == 0) { 4285f141548SBoris Ostrovsky xp.val = pmu_modes[i].mode; 4295f141548SBoris Ostrovsky break; 4305f141548SBoris Ostrovsky } 4315f141548SBoris Ostrovsky } 4325f141548SBoris Ostrovsky 4335f141548SBoris Ostrovsky if (i == ARRAY_SIZE(pmu_modes)) 4345f141548SBoris Ostrovsky return -EINVAL; 4355f141548SBoris Ostrovsky 4365f141548SBoris Ostrovsky xp.version.maj = XENPMU_VER_MAJ; 4375f141548SBoris Ostrovsky xp.version.min = XENPMU_VER_MIN; 4385f141548SBoris Ostrovsky ret = HYPERVISOR_xenpmu_op(XENPMU_mode_set, &xp); 4395f141548SBoris Ostrovsky if (ret) 4405f141548SBoris Ostrovsky return ret; 4415f141548SBoris Ostrovsky 4425f141548SBoris Ostrovsky return len; 4435f141548SBoris Ostrovsky } 4445f141548SBoris Ostrovsky 4455f141548SBoris Ostrovsky static ssize_t pmu_mode_show(struct hyp_sysfs_attr *attr, char *buffer) 4465f141548SBoris Ostrovsky { 4475f141548SBoris Ostrovsky int ret; 4485f141548SBoris Ostrovsky struct xen_pmu_params xp; 4495f141548SBoris Ostrovsky int i; 4505f141548SBoris Ostrovsky uint32_t mode; 4515f141548SBoris Ostrovsky 4525f141548SBoris Ostrovsky xp.version.maj = XENPMU_VER_MAJ; 4535f141548SBoris Ostrovsky xp.version.min = XENPMU_VER_MIN; 4545f141548SBoris Ostrovsky ret = HYPERVISOR_xenpmu_op(XENPMU_mode_get, &xp); 4555f141548SBoris Ostrovsky if (ret) 4565f141548SBoris Ostrovsky return ret; 4575f141548SBoris Ostrovsky 4585f141548SBoris Ostrovsky mode = (uint32_t)xp.val; 4595f141548SBoris Ostrovsky for (i = 0; i < ARRAY_SIZE(pmu_modes); i++) { 4605f141548SBoris Ostrovsky if (mode == pmu_modes[i].mode) 4615f141548SBoris Ostrovsky return sprintf(buffer, "%s\n", pmu_modes[i].name); 4625f141548SBoris Ostrovsky } 4635f141548SBoris Ostrovsky 4645f141548SBoris Ostrovsky return -EINVAL; 4655f141548SBoris Ostrovsky } 4665f141548SBoris Ostrovsky HYPERVISOR_ATTR_RW(pmu_mode); 4675f141548SBoris Ostrovsky 4685f141548SBoris Ostrovsky static ssize_t pmu_features_store(struct hyp_sysfs_attr *attr, 4695f141548SBoris Ostrovsky const char *buffer, size_t len) 4705f141548SBoris Ostrovsky { 4715f141548SBoris Ostrovsky int ret; 4725f141548SBoris Ostrovsky uint32_t features; 4735f141548SBoris Ostrovsky struct xen_pmu_params xp; 4745f141548SBoris Ostrovsky 4755f141548SBoris Ostrovsky ret = kstrtou32(buffer, 0, &features); 4765f141548SBoris Ostrovsky if (ret) 4775f141548SBoris Ostrovsky return ret; 4785f141548SBoris Ostrovsky 4795f141548SBoris Ostrovsky xp.val = features; 4805f141548SBoris Ostrovsky xp.version.maj = XENPMU_VER_MAJ; 4815f141548SBoris Ostrovsky xp.version.min = XENPMU_VER_MIN; 4825f141548SBoris Ostrovsky ret = HYPERVISOR_xenpmu_op(XENPMU_feature_set, &xp); 4835f141548SBoris Ostrovsky if (ret) 4845f141548SBoris Ostrovsky return ret; 4855f141548SBoris Ostrovsky 4865f141548SBoris Ostrovsky return len; 4875f141548SBoris Ostrovsky } 4885f141548SBoris Ostrovsky 4895f141548SBoris Ostrovsky static ssize_t pmu_features_show(struct hyp_sysfs_attr *attr, char *buffer) 4905f141548SBoris Ostrovsky { 4915f141548SBoris Ostrovsky int ret; 4925f141548SBoris Ostrovsky struct xen_pmu_params xp; 4935f141548SBoris Ostrovsky 4945f141548SBoris Ostrovsky xp.version.maj = XENPMU_VER_MAJ; 4955f141548SBoris Ostrovsky xp.version.min = XENPMU_VER_MIN; 4965f141548SBoris Ostrovsky ret = HYPERVISOR_xenpmu_op(XENPMU_feature_get, &xp); 4975f141548SBoris Ostrovsky if (ret) 4985f141548SBoris Ostrovsky return ret; 4995f141548SBoris Ostrovsky 5005f141548SBoris Ostrovsky return sprintf(buffer, "0x%x\n", (uint32_t)xp.val); 5015f141548SBoris Ostrovsky } 5025f141548SBoris Ostrovsky HYPERVISOR_ATTR_RW(pmu_features); 5035f141548SBoris Ostrovsky 5045f141548SBoris Ostrovsky static struct attribute *xen_pmu_attrs[] = { 5055f141548SBoris Ostrovsky &pmu_mode_attr.attr, 5065f141548SBoris Ostrovsky &pmu_features_attr.attr, 5075f141548SBoris Ostrovsky NULL 5085f141548SBoris Ostrovsky }; 5095f141548SBoris Ostrovsky 5105f141548SBoris Ostrovsky static const struct attribute_group xen_pmu_group = { 5115f141548SBoris Ostrovsky .name = "pmu", 5125f141548SBoris Ostrovsky .attrs = xen_pmu_attrs, 5135f141548SBoris Ostrovsky }; 5145f141548SBoris Ostrovsky 5155b00b504SJuergen Gross static int __init xen_sysfs_pmu_init(void) 5165f141548SBoris Ostrovsky { 5175f141548SBoris Ostrovsky return sysfs_create_group(hypervisor_kobj, &xen_pmu_group); 5185f141548SBoris Ostrovsky } 5195f141548SBoris Ostrovsky #endif 5205f141548SBoris Ostrovsky 521cff7e81bSJeremy Fitzhardinge static int __init hyper_sysfs_init(void) 522cff7e81bSJeremy Fitzhardinge { 523cff7e81bSJeremy Fitzhardinge int ret; 524cff7e81bSJeremy Fitzhardinge 525cff7e81bSJeremy Fitzhardinge if (!xen_domain()) 526cff7e81bSJeremy Fitzhardinge return -ENODEV; 527cff7e81bSJeremy Fitzhardinge 528cff7e81bSJeremy Fitzhardinge ret = xen_sysfs_type_init(); 529cff7e81bSJeremy Fitzhardinge if (ret) 530cff7e81bSJeremy Fitzhardinge goto out; 5314a4c29c9SJuergen Gross ret = xen_sysfs_guest_type_init(); 5324a4c29c9SJuergen Gross if (ret) 5334a4c29c9SJuergen Gross goto guest_type_out; 534cff7e81bSJeremy Fitzhardinge ret = xen_sysfs_version_init(); 535cff7e81bSJeremy Fitzhardinge if (ret) 536cff7e81bSJeremy Fitzhardinge goto version_out; 5375b00b504SJuergen Gross ret = xen_sysfs_compilation_init(); 538cff7e81bSJeremy Fitzhardinge if (ret) 539cff7e81bSJeremy Fitzhardinge goto comp_out; 540cff7e81bSJeremy Fitzhardinge ret = xen_sysfs_uuid_init(); 541cff7e81bSJeremy Fitzhardinge if (ret) 542cff7e81bSJeremy Fitzhardinge goto uuid_out; 5435b00b504SJuergen Gross ret = xen_sysfs_properties_init(); 544cff7e81bSJeremy Fitzhardinge if (ret) 545cff7e81bSJeremy Fitzhardinge goto prop_out; 5465f141548SBoris Ostrovsky #ifdef CONFIG_XEN_HAVE_VPMU 5475f141548SBoris Ostrovsky if (xen_initial_domain()) { 5485b00b504SJuergen Gross ret = xen_sysfs_pmu_init(); 5495f141548SBoris Ostrovsky if (ret) { 55046894f17SPaul Gortmaker sysfs_remove_group(hypervisor_kobj, 55146894f17SPaul Gortmaker &xen_properties_group); 5525f141548SBoris Ostrovsky goto prop_out; 5535f141548SBoris Ostrovsky } 5545f141548SBoris Ostrovsky } 5555f141548SBoris Ostrovsky #endif 556cff7e81bSJeremy Fitzhardinge goto out; 557cff7e81bSJeremy Fitzhardinge 558cff7e81bSJeremy Fitzhardinge prop_out: 55946894f17SPaul Gortmaker sysfs_remove_file(hypervisor_kobj, &uuid_attr.attr); 560cff7e81bSJeremy Fitzhardinge uuid_out: 56146894f17SPaul Gortmaker sysfs_remove_group(hypervisor_kobj, &xen_compilation_group); 562cff7e81bSJeremy Fitzhardinge comp_out: 56346894f17SPaul Gortmaker sysfs_remove_group(hypervisor_kobj, &version_group); 564cff7e81bSJeremy Fitzhardinge version_out: 5654a4c29c9SJuergen Gross sysfs_remove_file(hypervisor_kobj, &guest_type_attr.attr); 5664a4c29c9SJuergen Gross guest_type_out: 56746894f17SPaul Gortmaker sysfs_remove_file(hypervisor_kobj, &type_attr.attr); 568cff7e81bSJeremy Fitzhardinge out: 569cff7e81bSJeremy Fitzhardinge return ret; 570cff7e81bSJeremy Fitzhardinge } 57146894f17SPaul Gortmaker device_initcall(hyper_sysfs_init); 572cff7e81bSJeremy Fitzhardinge 573cff7e81bSJeremy Fitzhardinge static ssize_t hyp_sysfs_show(struct kobject *kobj, 574cff7e81bSJeremy Fitzhardinge struct attribute *attr, 575cff7e81bSJeremy Fitzhardinge char *buffer) 576cff7e81bSJeremy Fitzhardinge { 577cff7e81bSJeremy Fitzhardinge struct hyp_sysfs_attr *hyp_attr; 578cff7e81bSJeremy Fitzhardinge hyp_attr = container_of(attr, struct hyp_sysfs_attr, attr); 579cff7e81bSJeremy Fitzhardinge if (hyp_attr->show) 580cff7e81bSJeremy Fitzhardinge return hyp_attr->show(hyp_attr, buffer); 581cff7e81bSJeremy Fitzhardinge return 0; 582cff7e81bSJeremy Fitzhardinge } 583cff7e81bSJeremy Fitzhardinge 584cff7e81bSJeremy Fitzhardinge static ssize_t hyp_sysfs_store(struct kobject *kobj, 585cff7e81bSJeremy Fitzhardinge struct attribute *attr, 586cff7e81bSJeremy Fitzhardinge const char *buffer, 587cff7e81bSJeremy Fitzhardinge size_t len) 588cff7e81bSJeremy Fitzhardinge { 589cff7e81bSJeremy Fitzhardinge struct hyp_sysfs_attr *hyp_attr; 590cff7e81bSJeremy Fitzhardinge hyp_attr = container_of(attr, struct hyp_sysfs_attr, attr); 591cff7e81bSJeremy Fitzhardinge if (hyp_attr->store) 592cff7e81bSJeremy Fitzhardinge return hyp_attr->store(hyp_attr, buffer, len); 593cff7e81bSJeremy Fitzhardinge return 0; 594cff7e81bSJeremy Fitzhardinge } 595cff7e81bSJeremy Fitzhardinge 59652cf25d0SEmese Revfy static const struct sysfs_ops hyp_sysfs_ops = { 597cff7e81bSJeremy Fitzhardinge .show = hyp_sysfs_show, 598cff7e81bSJeremy Fitzhardinge .store = hyp_sysfs_store, 599cff7e81bSJeremy Fitzhardinge }; 600cff7e81bSJeremy Fitzhardinge 601cff7e81bSJeremy Fitzhardinge static struct kobj_type hyp_sysfs_kobj_type = { 602cff7e81bSJeremy Fitzhardinge .sysfs_ops = &hyp_sysfs_ops, 603cff7e81bSJeremy Fitzhardinge }; 604cff7e81bSJeremy Fitzhardinge 605cff7e81bSJeremy Fitzhardinge static int __init hypervisor_subsys_init(void) 606cff7e81bSJeremy Fitzhardinge { 607cff7e81bSJeremy Fitzhardinge if (!xen_domain()) 608cff7e81bSJeremy Fitzhardinge return -ENODEV; 609cff7e81bSJeremy Fitzhardinge 610cff7e81bSJeremy Fitzhardinge hypervisor_kobj->ktype = &hyp_sysfs_kobj_type; 611cff7e81bSJeremy Fitzhardinge return 0; 612cff7e81bSJeremy Fitzhardinge } 613cff7e81bSJeremy Fitzhardinge device_initcall(hypervisor_subsys_init); 614