Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xen: add /sys/hypervisor support

Adds support for Xen info under /sys/hypervisor. Taken from Novell 2.6.27
backport tree.

Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>

+489
+10
drivers/xen/Kconfig
··· 41 41 a xen platform. 42 42 If in doubt, say yes. 43 43 44 + config XEN_SYS_HYPERVISOR 45 + bool "Create xen entries under /sys/hypervisor" 46 + depends on XEN && SYSFS 47 + select SYS_HYPERVISOR 48 + default y 49 + help 50 + Create entries under /sys/hypervisor describing the Xen 51 + hypervisor environment. When running native or in another 52 + virtual environment, /sys/hypervisor will still be present, 53 + but will have no xen contents.
+1
drivers/xen/Makefile
··· 5 5 obj-$(CONFIG_XEN_XENCOMM) += xencomm.o 6 6 obj-$(CONFIG_XEN_BALLOON) += balloon.o 7 7 obj-$(CONFIG_XENFS) += xenfs/ 8 + obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o
+475
drivers/xen/sys-hypervisor.c
··· 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) \ 22 + static struct hyp_sysfs_attr _name##_attr = __ATTR_RO(_name) 23 + 24 + #define HYPERVISOR_ATTR_RW(_name) \ 25 + static struct hyp_sysfs_attr _name##_attr = \ 26 + __ATTR(_name, 0644, _name##_show, _name##_store) 27 + 28 + struct 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 + 35 + static ssize_t type_show(struct hyp_sysfs_attr *attr, char *buffer) 36 + { 37 + return sprintf(buffer, "xen\n"); 38 + } 39 + 40 + HYPERVISOR_ATTR_RO(type); 41 + 42 + static int __init xen_sysfs_type_init(void) 43 + { 44 + return sysfs_create_file(hypervisor_kobj, &type_attr.attr); 45 + } 46 + 47 + static void xen_sysfs_type_destroy(void) 48 + { 49 + sysfs_remove_file(hypervisor_kobj, &type_attr.attr); 50 + } 51 + 52 + /* xen version attributes */ 53 + static 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 + 61 + HYPERVISOR_ATTR_RO(major); 62 + 63 + static 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 + 71 + HYPERVISOR_ATTR_RO(minor); 72 + 73 + static 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 + 89 + HYPERVISOR_ATTR_RO(extra); 90 + 91 + static struct attribute *version_attrs[] = { 92 + &major_attr.attr, 93 + &minor_attr.attr, 94 + &extra_attr.attr, 95 + NULL 96 + }; 97 + 98 + static struct attribute_group version_group = { 99 + .name = "version", 100 + .attrs = version_attrs, 101 + }; 102 + 103 + static int __init xen_sysfs_version_init(void) 104 + { 105 + return sysfs_create_group(hypervisor_kobj, &version_group); 106 + } 107 + 108 + static void xen_sysfs_version_destroy(void) 109 + { 110 + sysfs_remove_group(hypervisor_kobj, &version_group); 111 + } 112 + 113 + /* UUID */ 114 + 115 + static 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 + 136 + HYPERVISOR_ATTR_RO(uuid); 137 + 138 + static int __init xen_sysfs_uuid_init(void) 139 + { 140 + return sysfs_create_file(hypervisor_kobj, &uuid_attr.attr); 141 + } 142 + 143 + static void xen_sysfs_uuid_destroy(void) 144 + { 145 + sysfs_remove_file(hypervisor_kobj, &uuid_attr.attr); 146 + } 147 + 148 + /* xen compilation attributes */ 149 + 150 + static 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 + 166 + HYPERVISOR_ATTR_RO(compiler); 167 + 168 + static 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 + 184 + HYPERVISOR_ATTR_RO(compiled_by); 185 + 186 + static 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 + 202 + HYPERVISOR_ATTR_RO(compile_date); 203 + 204 + static struct attribute *xen_compile_attrs[] = { 205 + &compiler_attr.attr, 206 + &compiled_by_attr.attr, 207 + &compile_date_attr.attr, 208 + NULL 209 + }; 210 + 211 + static struct attribute_group xen_compilation_group = { 212 + .name = "compilation", 213 + .attrs = xen_compile_attrs, 214 + }; 215 + 216 + int __init static xen_compilation_init(void) 217 + { 218 + return sysfs_create_group(hypervisor_kobj, &xen_compilation_group); 219 + } 220 + 221 + static void xen_compilation_destroy(void) 222 + { 223 + sysfs_remove_group(hypervisor_kobj, &xen_compilation_group); 224 + } 225 + 226 + /* xen properties info */ 227 + 228 + static 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 + 244 + HYPERVISOR_ATTR_RO(capabilities); 245 + 246 + static 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 + 262 + HYPERVISOR_ATTR_RO(changeset); 263 + 264 + static 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 + 281 + HYPERVISOR_ATTR_RO(virtual_start); 282 + 283 + static 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 + 294 + HYPERVISOR_ATTR_RO(pagesize); 295 + 296 + /* eventually there will be several more features to export */ 297 + static ssize_t xen_feature_show(int index, char *buffer) 298 + { 299 + int ret = -ENOMEM; 300 + struct xen_feature_info *info; 301 + 302 + info = kmalloc(sizeof(struct xen_feature_info), GFP_KERNEL); 303 + if (info) { 304 + info->submap_idx = index; 305 + ret = HYPERVISOR_xen_version(XENVER_get_features, info); 306 + if (!ret) 307 + ret = sprintf(buffer, "%d\n", info->submap); 308 + kfree(info); 309 + } 310 + 311 + return ret; 312 + } 313 + 314 + static ssize_t writable_pt_show(struct hyp_sysfs_attr *attr, char *buffer) 315 + { 316 + return xen_feature_show(XENFEAT_writable_page_tables, buffer); 317 + } 318 + 319 + HYPERVISOR_ATTR_RO(writable_pt); 320 + 321 + static struct attribute *xen_properties_attrs[] = { 322 + &capabilities_attr.attr, 323 + &changeset_attr.attr, 324 + &virtual_start_attr.attr, 325 + &pagesize_attr.attr, 326 + &writable_pt_attr.attr, 327 + NULL 328 + }; 329 + 330 + static struct attribute_group xen_properties_group = { 331 + .name = "properties", 332 + .attrs = xen_properties_attrs, 333 + }; 334 + 335 + static int __init xen_properties_init(void) 336 + { 337 + return sysfs_create_group(hypervisor_kobj, &xen_properties_group); 338 + } 339 + 340 + static void xen_properties_destroy(void) 341 + { 342 + sysfs_remove_group(hypervisor_kobj, &xen_properties_group); 343 + } 344 + 345 + #ifdef CONFIG_KEXEC 346 + 347 + extern size_t vmcoreinfo_size_xen; 348 + extern unsigned long paddr_vmcoreinfo_xen; 349 + 350 + static ssize_t vmcoreinfo_show(struct hyp_sysfs_attr *attr, char *page) 351 + { 352 + return sprintf(page, "%lx %zx\n", 353 + paddr_vmcoreinfo_xen, vmcoreinfo_size_xen); 354 + } 355 + 356 + HYPERVISOR_ATTR_RO(vmcoreinfo); 357 + 358 + static int __init xen_sysfs_vmcoreinfo_init(void) 359 + { 360 + return sysfs_create_file(hypervisor_kobj, 361 + &vmcoreinfo_attr.attr); 362 + } 363 + 364 + static void xen_sysfs_vmcoreinfo_destroy(void) 365 + { 366 + sysfs_remove_file(hypervisor_kobj, &vmcoreinfo_attr.attr); 367 + } 368 + 369 + #endif 370 + 371 + static int __init hyper_sysfs_init(void) 372 + { 373 + int ret; 374 + 375 + if (!xen_domain()) 376 + return -ENODEV; 377 + 378 + ret = xen_sysfs_type_init(); 379 + if (ret) 380 + goto out; 381 + ret = xen_sysfs_version_init(); 382 + if (ret) 383 + goto version_out; 384 + ret = xen_compilation_init(); 385 + if (ret) 386 + goto comp_out; 387 + ret = xen_sysfs_uuid_init(); 388 + if (ret) 389 + goto uuid_out; 390 + ret = xen_properties_init(); 391 + if (ret) 392 + goto prop_out; 393 + #ifdef CONFIG_KEXEC 394 + if (vmcoreinfo_size_xen != 0) { 395 + ret = xen_sysfs_vmcoreinfo_init(); 396 + if (ret) 397 + goto vmcoreinfo_out; 398 + } 399 + #endif 400 + 401 + goto out; 402 + 403 + #ifdef CONFIG_KEXEC 404 + vmcoreinfo_out: 405 + #endif 406 + xen_properties_destroy(); 407 + prop_out: 408 + xen_sysfs_uuid_destroy(); 409 + uuid_out: 410 + xen_compilation_destroy(); 411 + comp_out: 412 + xen_sysfs_version_destroy(); 413 + version_out: 414 + xen_sysfs_type_destroy(); 415 + out: 416 + return ret; 417 + } 418 + 419 + static void __exit hyper_sysfs_exit(void) 420 + { 421 + #ifdef CONFIG_KEXEC 422 + if (vmcoreinfo_size_xen != 0) 423 + xen_sysfs_vmcoreinfo_destroy(); 424 + #endif 425 + xen_properties_destroy(); 426 + xen_compilation_destroy(); 427 + xen_sysfs_uuid_destroy(); 428 + xen_sysfs_version_destroy(); 429 + xen_sysfs_type_destroy(); 430 + 431 + } 432 + module_init(hyper_sysfs_init); 433 + module_exit(hyper_sysfs_exit); 434 + 435 + static ssize_t hyp_sysfs_show(struct kobject *kobj, 436 + struct attribute *attr, 437 + char *buffer) 438 + { 439 + struct hyp_sysfs_attr *hyp_attr; 440 + hyp_attr = container_of(attr, struct hyp_sysfs_attr, attr); 441 + if (hyp_attr->show) 442 + return hyp_attr->show(hyp_attr, buffer); 443 + return 0; 444 + } 445 + 446 + static ssize_t hyp_sysfs_store(struct kobject *kobj, 447 + struct attribute *attr, 448 + const char *buffer, 449 + size_t len) 450 + { 451 + struct hyp_sysfs_attr *hyp_attr; 452 + hyp_attr = container_of(attr, struct hyp_sysfs_attr, attr); 453 + if (hyp_attr->store) 454 + return hyp_attr->store(hyp_attr, buffer, len); 455 + return 0; 456 + } 457 + 458 + static struct sysfs_ops hyp_sysfs_ops = { 459 + .show = hyp_sysfs_show, 460 + .store = hyp_sysfs_store, 461 + }; 462 + 463 + static struct kobj_type hyp_sysfs_kobj_type = { 464 + .sysfs_ops = &hyp_sysfs_ops, 465 + }; 466 + 467 + static int __init hypervisor_subsys_init(void) 468 + { 469 + if (!xen_domain()) 470 + return -ENODEV; 471 + 472 + hypervisor_kobj->ktype = &hyp_sysfs_kobj_type; 473 + return 0; 474 + } 475 + device_initcall(hypervisor_subsys_init);
+3
include/xen/interface/version.h
··· 57 57 /* Declares the features reported by XENVER_get_features. */ 58 58 #include "features.h" 59 59 60 + /* arg == NULL; returns host memory page size. */ 61 + #define XENVER_pagesize 7 62 + 60 63 #endif /* __XEN_PUBLIC_VERSION_H__ */