Skip to content

Commit

Permalink
xen: Expose the PMU to the guests
Browse files Browse the repository at this point in the history
Add parameter vpmu to xl domain configuration syntax
to enable the access to PMU registers by disabling
the PMU traps(currently only for ARM).

The current status is that the PMU registers are not
virtualized and the physical registers are directly
accessible when this parameter is enabled. There is no
interrupt support and Xen will not save/restore the
register values on context switches.

According to Arm Arm, section D7.1:
"The Performance Monitors Extension is common
to AArch64 operation and AArch32 operation."
That means we have an ensurance that if PMU is
present in one exception state, it must also be
present in the other.

Please note that this feature is experimental.

Signed-off-by: Michal Orzel <michal.orzel@arm.com>
Signed-off-by: Julien Grall <julien@xen.org>
Reviewed-by: Bertrand Marquis <bertrand.marquis@arm.com>
Acked-by: Anthony PERARD <anthony.perard@citrix.com>
Acked-by: Ian Jackson <iwj@xenproject.org>
  • Loading branch information
orzelmichal authored and ijackson-citrix committed Oct 13, 2021
1 parent c8c6cd9 commit dbb9481
Show file tree
Hide file tree
Showing 15 changed files with 83 additions and 8 deletions.
14 changes: 11 additions & 3 deletions SUPPORT.md
Original file line number Diff line number Diff line change
Expand Up @@ -671,11 +671,19 @@ such as KVM, Hyper-V, Bromium, and so on as guests.

### vPMU

Virtual Performance Management Unit for HVM guests
Virtual Performance Management Unit

Status, x86: Supported, Not security supported
Status, x86 HVM: Supported, Not security supported
Status, ARM: Experimental

On ARM, support for accessing PMU registers from the guests.
There is no interrupt support and Xen will not save/restore
the register values on context switches.

Disabled by default.
On ARM, enable with guest parameter.
On x86, enable with hypervisor command line option.

Disabled by default (enable with hypervisor command line option).
This feature is not security supported: see https://xenbits.xen.org/xsa/advisory-163.html

### Argo: Inter-domain message delivery by hypercall
Expand Down
17 changes: 17 additions & 0 deletions docs/man/xl.cfg.5.pod.in
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,23 @@ default.
B<NOTE>: Acceptable values are platform specific. For Intel Processor
Trace, this value must be a power of 2 between 4k and 16M.

=item B<vpmu=BOOLEAN>

Currently ARM only.

Specifies whether to enable the access to PMU registers by disabling
the PMU traps.

The PMU registers are not virtualized and the physical registers are directly
accessible when this parameter is enabled. There is no interrupt support and
Xen will not save/restore the register values on context switches.

vPMU, by design and purpose, exposes system level performance
information to the guest. Only to be used by sufficiently privileged
domains. This feature is currently in experimental state.

If this option is not specified then it will default to B<false>.

=back

=head2 Devices
Expand Down
6 changes: 6 additions & 0 deletions tools/golang/xenlight/helpers.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions tools/golang/xenlight/types.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions tools/include/libxl.h
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,12 @@
*/
#define LIBXL_HAVE_PHYSINFO_CAP_VPMU 1

/*
* LIBXL_HAVE_VPMU indicates that libxl_domain_build_info has a vpmu parameter,
* which allows to enable the access to PMU registers.
*/
#define LIBXL_HAVE_VPMU 1

/*
* libxl ABI compatibility
*
Expand Down
10 changes: 10 additions & 0 deletions tools/libs/light/libxl_create.c
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ int libxl__domain_build_info_setdefault(libxl__gc *gc,
}

libxl_defbool_setdefault(&b_info->device_model_stubdomain, false);
libxl_defbool_setdefault(&b_info->vpmu, false);

if (libxl_defbool_val(b_info->device_model_stubdomain) &&
!b_info->device_model_ssidref)
Expand Down Expand Up @@ -622,6 +623,9 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_config *d_config,
create.flags |= XEN_DOMCTL_CDF_nested_virt;
}

if (libxl_defbool_val(b_info->vpmu))
create.flags |= XEN_DOMCTL_CDF_vpmu;

assert(info->passthrough != LIBXL_PASSTHROUGH_DEFAULT);
LOG(DETAIL, "passthrough: %s",
libxl_passthrough_to_string(info->passthrough));
Expand Down Expand Up @@ -1199,6 +1203,12 @@ int libxl__domain_config_setdefault(libxl__gc *gc,
goto error_out;
}

if (libxl_defbool_val(d_config->b_info.vpmu) && !physinfo.cap_vpmu) {
ret = ERROR_INVAL;
LOGD(ERROR, domid, "vPMU not supported on this platform");
goto error_out;
}

ret = 0;
error_out:
return ret;
Expand Down
2 changes: 2 additions & 0 deletions tools/libs/light/libxl_types.idl
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,8 @@ libxl_domain_build_info = Struct("domain_build_info",[
# Use zero value to disable this feature.
("vmtrace_buf_kb", integer),

("vpmu", libxl_defbool),

], dir=DIR_IN,
copy_deprecated_fn="libxl__domain_build_info_copy_deprecated",
)
Expand Down
1 change: 1 addition & 0 deletions tools/ocaml/libs/xc/xenctrl.ml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ type domain_create_flag =
| CDF_IOMMU
| CDF_NESTED_VIRT
| CDF_VPCI
| CDF_VPMU

type domain_create_iommu_opts =
| IOMMU_NO_SHAREPT
Expand Down
1 change: 1 addition & 0 deletions tools/ocaml/libs/xc/xenctrl.mli
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ type domain_create_flag =
| CDF_IOMMU
| CDF_NESTED_VIRT
| CDF_VPCI
| CDF_VPMU

type domain_create_iommu_opts =
| IOMMU_NO_SHAREPT
Expand Down
2 changes: 2 additions & 0 deletions tools/xl/xl_parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -2750,6 +2750,8 @@ void parse_config_data(const char *config_source,
"If it fixes an issue you are having please report to "
"xen-devel@lists.xenproject.org.\n");

xlu_cfg_get_defbool(config, "vpmu", &b_info->vpmu, 0);

xlu_cfg_destroy(config);
}

Expand Down
13 changes: 10 additions & 3 deletions xen/arch/arm/domain.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,8 @@ static void ctxt_switch_to(struct vcpu *n)
* timer. The interrupt needs to be injected into the guest. */
WRITE_SYSREG(n->arch.cntkctl, CNTKCTL_EL1);
virt_timer_restore(n);

WRITE_SYSREG(n->arch.mdcr_el2, MDCR_EL2);
}

/* Update per-VCPU guest runstate shared memory area (if registered). */
Expand Down Expand Up @@ -586,6 +588,10 @@ int arch_vcpu_create(struct vcpu *v)

v->arch.hcr_el2 = get_default_hcr_flags();

v->arch.mdcr_el2 = HDCR_TDRA | HDCR_TDOSA | HDCR_TDA;
if ( !(v->domain->options & XEN_DOMCTL_CDF_vpmu) )
v->arch.mdcr_el2 |= HDCR_TPM | HDCR_TPMCR;

if ( (rc = vcpu_vgic_init(v)) != 0 )
goto fail;

Expand Down Expand Up @@ -621,10 +627,11 @@ void vcpu_switch_to_aarch64_mode(struct vcpu *v)
int arch_sanitise_domain_config(struct xen_domctl_createdomain *config)
{
unsigned int max_vcpus;
unsigned int flags_required = (XEN_DOMCTL_CDF_hvm | XEN_DOMCTL_CDF_hap);
unsigned int flags_optional = (XEN_DOMCTL_CDF_iommu | XEN_DOMCTL_CDF_vpci |
XEN_DOMCTL_CDF_vpmu);

/* HVM and HAP must be set. IOMMU and VPCI may or may not be */
if ( (config->flags & ~XEN_DOMCTL_CDF_iommu & ~XEN_DOMCTL_CDF_vpci) !=
(XEN_DOMCTL_CDF_hvm | XEN_DOMCTL_CDF_hap) )
if ( (config->flags & ~flags_optional) != flags_required )
{
dprintk(XENLOG_INFO, "Unsupported configuration %#x\n",
config->flags);
Expand Down
3 changes: 3 additions & 0 deletions xen/arch/arm/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -999,6 +999,9 @@ void __init start_xen(unsigned long boot_phys_offset,
printk("Brought up %ld CPUs\n", (long)num_online_cpus());
/* TODO: smp_cpus_done(); */

/* This should be done in a vpmu driver but we do not have one yet. */
vpmu_is_available = cpu_has_pmu;

/*
* The IOMMU subsystem must be initialized before P2M as we need
* to gather requirements regarding the maximum IPA bits supported by
Expand Down
10 changes: 9 additions & 1 deletion xen/common/domain.c
Original file line number Diff line number Diff line change
Expand Up @@ -480,12 +480,14 @@ static int sanitise_domain_config(struct xen_domctl_createdomain *config)
bool hvm = config->flags & XEN_DOMCTL_CDF_hvm;
bool hap = config->flags & XEN_DOMCTL_CDF_hap;
bool iommu = config->flags & XEN_DOMCTL_CDF_iommu;
bool vpmu = config->flags & XEN_DOMCTL_CDF_vpmu;

if ( config->flags &
~(XEN_DOMCTL_CDF_hvm | XEN_DOMCTL_CDF_hap |
XEN_DOMCTL_CDF_s3_integrity | XEN_DOMCTL_CDF_oos_off |
XEN_DOMCTL_CDF_xs_domain | XEN_DOMCTL_CDF_iommu |
XEN_DOMCTL_CDF_nested_virt | XEN_DOMCTL_CDF_vpci) )
XEN_DOMCTL_CDF_nested_virt | XEN_DOMCTL_CDF_vpci |
XEN_DOMCTL_CDF_vpmu) )
{
dprintk(XENLOG_INFO, "Unknown CDF flags %#x\n", config->flags);
return -EINVAL;
Expand Down Expand Up @@ -534,6 +536,12 @@ static int sanitise_domain_config(struct xen_domctl_createdomain *config)
return -EINVAL;
}

if ( vpmu && !vpmu_is_available )
{
dprintk(XENLOG_INFO, "vpmu requested but cannot be enabled this way\n");
return -EINVAL;
}

return arch_sanitise_domain_config(config);
}

Expand Down
1 change: 1 addition & 0 deletions xen/include/asm-arm/domain.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ struct arch_vcpu

/* HYP configuration */
register_t hcr_el2;
register_t mdcr_el2;

uint32_t teecr, teehbr; /* ThumbEE, 32-bit guests only */
#ifdef CONFIG_ARM_32
Expand Down
4 changes: 3 additions & 1 deletion xen/include/public/domctl.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,11 @@ struct xen_domctl_createdomain {
#define _XEN_DOMCTL_CDF_nested_virt 6
#define XEN_DOMCTL_CDF_nested_virt (1U << _XEN_DOMCTL_CDF_nested_virt)
#define XEN_DOMCTL_CDF_vpci (1U << 7)
/* Should we expose the vPMU to the guest? */
#define XEN_DOMCTL_CDF_vpmu (1U << 8)

/* Max XEN_DOMCTL_CDF_* constant. Used for ABI checking. */
#define XEN_DOMCTL_CDF_MAX XEN_DOMCTL_CDF_vpci
#define XEN_DOMCTL_CDF_MAX XEN_DOMCTL_CDF_vpmu

uint32_t flags;

Expand Down

0 comments on commit dbb9481

Please sign in to comment.