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

xen/PMU: Sysfs interface for setting Xen PMU mode

Set Xen's PMU mode via /sys/hypervisor/pmu/pmu_mode. Add XENPMU hypercall.

Signed-off-by: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Signed-off-by: David Vrabel <david.vrabel@citrix.com>

authored by

Boris Ostrovsky and committed by
David Vrabel
5f141548 a11f4f0a

+228 -1
+23
Documentation/ABI/testing/sysfs-hypervisor-pmu
··· 1 + What: /sys/hypervisor/pmu/pmu_mode 2 + Date: August 2015 3 + KernelVersion: 4.3 4 + Contact: Boris Ostrovsky <boris.ostrovsky@oracle.com> 5 + Description: 6 + Describes mode that Xen's performance-monitoring unit (PMU) 7 + uses. Accepted values are 8 + "off" -- PMU is disabled 9 + "self" -- The guest can profile itself 10 + "hv" -- The guest can profile itself and, if it is 11 + privileged (e.g. dom0), the hypervisor 12 + "all" -- The guest can profile itself, the hypervisor 13 + and all other guests. Only available to 14 + privileged guests. 15 + 16 + What: /sys/hypervisor/pmu/pmu_features 17 + Date: August 2015 18 + KernelVersion: 4.3 19 + Contact: Boris Ostrovsky <boris.ostrovsky@oracle.com> 20 + Description: 21 + Describes Xen PMU features (as an integer). A set bit indicates 22 + that the corresponding feature is enabled. See 23 + include/xen/interface/xenpmu.h for available features
+6
arch/x86/include/asm/xen/hypercall.h
··· 465 465 return _hypercall1(int, tmem_op, op); 466 466 } 467 467 468 + static inline int 469 + HYPERVISOR_xenpmu_op(unsigned int op, void *arg) 470 + { 471 + return _hypercall2(int, xenpmu_op, op, arg); 472 + } 473 + 468 474 static inline void 469 475 MULTI_fpu_taskswitch(struct multicall_entry *mcl, int set) 470 476 {
+1
arch/x86/xen/Kconfig
··· 7 7 depends on PARAVIRT 8 8 select PARAVIRT_CLOCK 9 9 select XEN_HAVE_PVMMU 10 + select XEN_HAVE_VPMU 10 11 depends on X86_64 || (X86_32 && X86_PAE) 11 12 depends on X86_TSC 12 13 help
+3
drivers/xen/Kconfig
··· 288 288 Exports hypervisor symbols (along with their types and addresses) via 289 289 /proc/xen/xensyms file, similar to /proc/kallsyms 290 290 291 + config XEN_HAVE_VPMU 292 + bool 293 + 291 294 endmenu
+135 -1
drivers/xen/sys-hypervisor.c
··· 20 20 #include <xen/xenbus.h> 21 21 #include <xen/interface/xen.h> 22 22 #include <xen/interface/version.h> 23 + #ifdef CONFIG_XEN_HAVE_VPMU 24 + #include <xen/interface/xenpmu.h> 25 + #endif 23 26 24 27 #define HYPERVISOR_ATTR_RO(_name) \ 25 28 static struct hyp_sysfs_attr _name##_attr = __ATTR_RO(_name) ··· 371 368 sysfs_remove_group(hypervisor_kobj, &xen_properties_group); 372 369 } 373 370 371 + #ifdef CONFIG_XEN_HAVE_VPMU 372 + struct pmu_mode { 373 + const char *name; 374 + uint32_t mode; 375 + }; 376 + 377 + static struct pmu_mode pmu_modes[] = { 378 + {"off", XENPMU_MODE_OFF}, 379 + {"self", XENPMU_MODE_SELF}, 380 + {"hv", XENPMU_MODE_HV}, 381 + {"all", XENPMU_MODE_ALL} 382 + }; 383 + 384 + static ssize_t pmu_mode_store(struct hyp_sysfs_attr *attr, 385 + const char *buffer, size_t len) 386 + { 387 + int ret; 388 + struct xen_pmu_params xp; 389 + int i; 390 + 391 + for (i = 0; i < ARRAY_SIZE(pmu_modes); i++) { 392 + if (strncmp(buffer, pmu_modes[i].name, len - 1) == 0) { 393 + xp.val = pmu_modes[i].mode; 394 + break; 395 + } 396 + } 397 + 398 + if (i == ARRAY_SIZE(pmu_modes)) 399 + return -EINVAL; 400 + 401 + xp.version.maj = XENPMU_VER_MAJ; 402 + xp.version.min = XENPMU_VER_MIN; 403 + ret = HYPERVISOR_xenpmu_op(XENPMU_mode_set, &xp); 404 + if (ret) 405 + return ret; 406 + 407 + return len; 408 + } 409 + 410 + static ssize_t pmu_mode_show(struct hyp_sysfs_attr *attr, char *buffer) 411 + { 412 + int ret; 413 + struct xen_pmu_params xp; 414 + int i; 415 + uint32_t mode; 416 + 417 + xp.version.maj = XENPMU_VER_MAJ; 418 + xp.version.min = XENPMU_VER_MIN; 419 + ret = HYPERVISOR_xenpmu_op(XENPMU_mode_get, &xp); 420 + if (ret) 421 + return ret; 422 + 423 + mode = (uint32_t)xp.val; 424 + for (i = 0; i < ARRAY_SIZE(pmu_modes); i++) { 425 + if (mode == pmu_modes[i].mode) 426 + return sprintf(buffer, "%s\n", pmu_modes[i].name); 427 + } 428 + 429 + return -EINVAL; 430 + } 431 + HYPERVISOR_ATTR_RW(pmu_mode); 432 + 433 + static ssize_t pmu_features_store(struct hyp_sysfs_attr *attr, 434 + const char *buffer, size_t len) 435 + { 436 + int ret; 437 + uint32_t features; 438 + struct xen_pmu_params xp; 439 + 440 + ret = kstrtou32(buffer, 0, &features); 441 + if (ret) 442 + return ret; 443 + 444 + xp.val = features; 445 + xp.version.maj = XENPMU_VER_MAJ; 446 + xp.version.min = XENPMU_VER_MIN; 447 + ret = HYPERVISOR_xenpmu_op(XENPMU_feature_set, &xp); 448 + if (ret) 449 + return ret; 450 + 451 + return len; 452 + } 453 + 454 + static ssize_t pmu_features_show(struct hyp_sysfs_attr *attr, char *buffer) 455 + { 456 + int ret; 457 + struct xen_pmu_params xp; 458 + 459 + xp.version.maj = XENPMU_VER_MAJ; 460 + xp.version.min = XENPMU_VER_MIN; 461 + ret = HYPERVISOR_xenpmu_op(XENPMU_feature_get, &xp); 462 + if (ret) 463 + return ret; 464 + 465 + return sprintf(buffer, "0x%x\n", (uint32_t)xp.val); 466 + } 467 + HYPERVISOR_ATTR_RW(pmu_features); 468 + 469 + static struct attribute *xen_pmu_attrs[] = { 470 + &pmu_mode_attr.attr, 471 + &pmu_features_attr.attr, 472 + NULL 473 + }; 474 + 475 + static const struct attribute_group xen_pmu_group = { 476 + .name = "pmu", 477 + .attrs = xen_pmu_attrs, 478 + }; 479 + 480 + static int __init xen_pmu_init(void) 481 + { 482 + return sysfs_create_group(hypervisor_kobj, &xen_pmu_group); 483 + } 484 + 485 + static void xen_pmu_destroy(void) 486 + { 487 + sysfs_remove_group(hypervisor_kobj, &xen_pmu_group); 488 + } 489 + #endif 490 + 374 491 static int __init hyper_sysfs_init(void) 375 492 { 376 493 int ret; ··· 513 390 ret = xen_properties_init(); 514 391 if (ret) 515 392 goto prop_out; 516 - 393 + #ifdef CONFIG_XEN_HAVE_VPMU 394 + if (xen_initial_domain()) { 395 + ret = xen_pmu_init(); 396 + if (ret) { 397 + xen_properties_destroy(); 398 + goto prop_out; 399 + } 400 + } 401 + #endif 517 402 goto out; 518 403 519 404 prop_out: ··· 538 407 539 408 static void __exit hyper_sysfs_exit(void) 540 409 { 410 + #ifdef CONFIG_XEN_HAVE_VPMU 411 + xen_pmu_destroy(); 412 + #endif 541 413 xen_properties_destroy(); 542 414 xen_compilation_destroy(); 543 415 xen_sysfs_uuid_destroy();
+1
include/xen/interface/xen.h
··· 80 80 #define __HYPERVISOR_kexec_op 37 81 81 #define __HYPERVISOR_tmem_op 38 82 82 #define __HYPERVISOR_xc_reserved_op 39 /* reserved for XenClient */ 83 + #define __HYPERVISOR_xenpmu_op 40 83 84 84 85 /* Architecture-specific hypercall definitions. */ 85 86 #define __HYPERVISOR_arch_0 48
+59
include/xen/interface/xenpmu.h
··· 1 + #ifndef __XEN_PUBLIC_XENPMU_H__ 2 + #define __XEN_PUBLIC_XENPMU_H__ 3 + 4 + #include "xen.h" 5 + 6 + #define XENPMU_VER_MAJ 0 7 + #define XENPMU_VER_MIN 1 8 + 9 + /* 10 + * ` enum neg_errnoval 11 + * ` HYPERVISOR_xenpmu_op(enum xenpmu_op cmd, struct xenpmu_params *args); 12 + * 13 + * @cmd == XENPMU_* (PMU operation) 14 + * @args == struct xenpmu_params 15 + */ 16 + /* ` enum xenpmu_op { */ 17 + #define XENPMU_mode_get 0 /* Also used for getting PMU version */ 18 + #define XENPMU_mode_set 1 19 + #define XENPMU_feature_get 2 20 + #define XENPMU_feature_set 3 21 + #define XENPMU_init 4 22 + #define XENPMU_finish 5 23 + 24 + /* ` } */ 25 + 26 + /* Parameters structure for HYPERVISOR_xenpmu_op call */ 27 + struct xen_pmu_params { 28 + /* IN/OUT parameters */ 29 + struct { 30 + uint32_t maj; 31 + uint32_t min; 32 + } version; 33 + uint64_t val; 34 + 35 + /* IN parameters */ 36 + uint32_t vcpu; 37 + uint32_t pad; 38 + }; 39 + 40 + /* PMU modes: 41 + * - XENPMU_MODE_OFF: No PMU virtualization 42 + * - XENPMU_MODE_SELF: Guests can profile themselves 43 + * - XENPMU_MODE_HV: Guests can profile themselves, dom0 profiles 44 + * itself and Xen 45 + * - XENPMU_MODE_ALL: Only dom0 has access to VPMU and it profiles 46 + * everyone: itself, the hypervisor and the guests. 47 + */ 48 + #define XENPMU_MODE_OFF 0 49 + #define XENPMU_MODE_SELF (1<<0) 50 + #define XENPMU_MODE_HV (1<<1) 51 + #define XENPMU_MODE_ALL (1<<2) 52 + 53 + /* 54 + * PMU features: 55 + * - XENPMU_FEATURE_INTEL_BTS: Intel BTS support (ignored on AMD) 56 + */ 57 + #define XENPMU_FEATURE_INTEL_BTS 1 58 + 59 + #endif /* __XEN_PUBLIC_XENPMU_H__ */