[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [RFC 3/5] i386/kvm: Support event with select&umask format in KVM PM
From: |
Mi, Dapeng |
Subject: |
Re: [RFC 3/5] i386/kvm: Support event with select&umask format in KVM PMU filter |
Date: |
Thu, 18 Jul 2024 13:28:25 +0800 |
User-agent: |
Mozilla Thunderbird |
On 7/10/2024 12:51 PM, Zhao Liu wrote:
> The select&umask is the common way for x86 to identify the PMU event,
> so support this way as the "x86-default" format in kvm-pmu-filter
> object.
>
> Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
> ---
> accel/kvm/kvm-pmu.c | 62 ++++++++++++++++++++++++++++++++++++++++
> include/sysemu/kvm-pmu.h | 13 +++++++++
> qapi/kvm.json | 46 +++++++++++++++++++++++++++--
> target/i386/kvm/kvm.c | 5 ++++
> 4 files changed, 123 insertions(+), 3 deletions(-)
>
> diff --git a/accel/kvm/kvm-pmu.c b/accel/kvm/kvm-pmu.c
> index 483d1bdf4807..51d3fba5a72a 100644
> --- a/accel/kvm/kvm-pmu.c
> +++ b/accel/kvm/kvm-pmu.c
> @@ -17,6 +17,8 @@
> #include "qom/object_interfaces.h"
> #include "sysemu/kvm-pmu.h"
>
> +#define UINT12_MAX (4095)
> +
> static void kvm_pmu_filter_get_event(Object *obj, Visitor *v, const char
> *name,
> void *opaque, Error **errp)
> {
> @@ -38,6 +40,12 @@ static void kvm_pmu_filter_get_event(Object *obj, Visitor
> *v, const char *name,
> str_event->u.raw.code = g_strdup_printf("0x%lx",
> event->u.raw.code);
> break;
> + case KVM_PMU_EVENT_FMT_X86_DEFAULT:
> + str_event->u.x86_default.select =
> + g_strdup_printf("0x%x", event->u.x86_default.select);
> + str_event->u.x86_default.umask =
> + g_strdup_printf("0x%x", event->u.x86_default.umask);
> + break;
> default:
> g_assert_not_reached();
> }
> @@ -83,6 +91,60 @@ static void kvm_pmu_filter_set_event(Object *obj, Visitor
> *v, const char *name,
> goto fail;
> }
> break;
> + case KVM_PMU_EVENT_FMT_X86_DEFAULT: {
> + uint64_t select, umask;
> +
> + ret = qemu_strtou64(str_event->u.x86_default.select, NULL,
> + 0, &select);
> + if (ret < 0) {
> + error_setg(errp,
> + "Invalid %s PMU event (select: %s): %s. "
> + "The select must be a "
> + "12-bit unsigned number string.",
> + KVMPMUEventEncodeFmt_str(str_event->format),
> + str_event->u.x86_default.select,
> + strerror(-ret));
> + g_free(event);
> + goto fail;
> + }
> + if (select > UINT12_MAX) {
> + error_setg(errp,
> + "Invalid %s PMU event (select: %s): "
> + "Numerical result out of range. "
> + "The select must be a "
> + "12-bit unsigned number string.",
> + KVMPMUEventEncodeFmt_str(str_event->format),
> + str_event->u.x86_default.select);
> + g_free(event);
> + goto fail;
> + }
> + event->u.x86_default.select = select;
> +
> + ret = qemu_strtou64(str_event->u.x86_default.umask, NULL,
> + 0, &umask);
> + if (ret < 0) {
> + error_setg(errp,
> + "Invalid %s PMU event (umask: %s): %s. "
> + "The umask must be a uint8 string.",
> + KVMPMUEventEncodeFmt_str(str_event->format),
> + str_event->u.x86_default.umask,
> + strerror(-ret));
> + g_free(event);
> + goto fail;
> + }
> + if (umask > UINT8_MAX) {
umask is extended to 16 bits from Perfmon v6+. Please notice we need to
upgrade this to 16 bits in the future. More details can be found here.
[PATCH V3 00/13] Support Lunar Lake and Arrow Lake core PMU - kan.liang
(kernel.org)
<https://lore.kernel.org/all/20240626143545.480761-1-kan.liang@linux.intel.com/>
> + error_setg(errp,
> + "Invalid %s PMU event (umask: %s): "
> + "Numerical result out of range. "
> + "The umask must be a uint8 string.",
> + KVMPMUEventEncodeFmt_str(str_event->format),
> + str_event->u.x86_default.umask);
> + g_free(event);
> + goto fail;
> + }
> + event->u.x86_default.umask = umask;
> + break;
> + }
> default:
> g_assert_not_reached();
> }
> diff --git a/include/sysemu/kvm-pmu.h b/include/sysemu/kvm-pmu.h
> index 4707759761f1..707f33d604fd 100644
> --- a/include/sysemu/kvm-pmu.h
> +++ b/include/sysemu/kvm-pmu.h
> @@ -26,4 +26,17 @@ struct KVMPMUFilter {
> KVMPMUFilterEventList *events;
> };
>
> +/*
> + * Stolen from Linux kernel (RAW_EVENT at
> tools/testing/selftests/kvm/include/
> + * x86_64/pmu.h).
> + *
> + * Encode an eventsel+umask pair into event-select MSR format. Note, this is
> + * technically AMD's format, as Intel's format only supports 8 bits for the
> + * event selector, i.e. doesn't use bits 24:16 for the selector. But, OR-ing
> + * in '0' is a nop and won't clobber the CMASK.
> + */
> +#define X86_PMU_RAW_EVENT(eventsel, umask) (((eventsel & 0xf00UL) << 24) | \
> + ((eventsel) & 0xff) | \
> + ((umask) & 0xff) << 8)
> +
> #endif /* KVM_PMU_H */
> diff --git a/qapi/kvm.json b/qapi/kvm.json
> index 0619da83c123..0d759884c229 100644
> --- a/qapi/kvm.json
> +++ b/qapi/kvm.json
> @@ -27,11 +27,13 @@
> #
> # @raw: the encoded event code that KVM can directly consume.
> #
> +# @x86-default: standard x86 encoding format with select and umask.
> +#
> # Since 9.1
> ##
> { 'enum': 'KVMPMUEventEncodeFmt',
> 'prefix': 'KVM_PMU_EVENT_FMT',
> - 'data': ['raw'] }
> + 'data': ['raw', 'x86-default'] }
>
> ##
> # @KVMPMURawEvent:
> @@ -46,6 +48,25 @@
> { 'struct': 'KVMPMURawEvent',
> 'data': { 'code': 'uint64' } }
>
> +##
> +# @KVMPMUX86DefalutEvent:
> +#
> +# x86 PMU event encoding with select and umask.
> +# raw_event = ((select & 0xf00UL) << 24) | \
> +# (select) & 0xff) | \
> +# ((umask) & 0xff) << 8)
> +#
> +# @select: x86 PMU event select field, which is a 12-bit unsigned
> +# number.
> +#
> +# @umask: x86 PMU event umask field.
> +#
> +# Since 9.1
> +##
> +{ 'struct': 'KVMPMUX86DefalutEvent',
> + 'data': { 'select': 'uint16',
> + 'umask': 'uint8' } }
> +
> ##
> # @KVMPMUFilterEvent:
> #
> @@ -61,7 +82,8 @@
> 'base': { 'action': 'KVMPMUFilterAction',
> 'format': 'KVMPMUEventEncodeFmt' },
> 'discriminator': 'format',
> - 'data': { 'raw': 'KVMPMURawEvent' } }
> + 'data': { 'raw': 'KVMPMURawEvent',
> + 'x86-default': 'KVMPMUX86DefalutEvent' } }
>
> ##
> # @KVMPMUFilterProperty:
> @@ -89,6 +111,23 @@
> { 'struct': 'KVMPMURawEventVariant',
> 'data': { 'code': 'str' } }
>
> +##
> +# @KVMPMUX86DefalutEventVariant:
> +#
> +# The variant of KVMPMUX86DefalutEvent with the string, rather than
> +# the numeric value.
> +#
> +# @select: x86 PMU event select field. This field is a 12-bit
> +# unsigned number string.
> +#
> +# @umask: x86 PMU event umask field. This field is a uint8 string.
> +#
> +# Since 9.1
> +##
> +{ 'struct': 'KVMPMUX86DefalutEventVariant',
> + 'data': { 'select': 'str',
> + 'umask': 'str' } }
> +
> ##
> # @KVMPMUFilterEventVariant:
> #
> @@ -104,7 +143,8 @@
> 'base': { 'action': 'KVMPMUFilterAction',
> 'format': 'KVMPMUEventEncodeFmt' },
> 'discriminator': 'format',
> - 'data': { 'raw': 'KVMPMURawEventVariant' } }
> + 'data': { 'raw': 'KVMPMURawEventVariant',
> + 'x86-default': 'KVMPMUX86DefalutEventVariant' } }
>
> ##
> # @KVMPMUFilterPropertyVariant:
> diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c
> index e9bf79782316..391531c036a6 100644
> --- a/target/i386/kvm/kvm.c
> +++ b/target/i386/kvm/kvm.c
> @@ -5393,6 +5393,10 @@ kvm_config_pmu_event(KVMPMUFilter *filter,
> case KVM_PMU_EVENT_FMT_RAW:
> code = event->u.raw.code;
> break;
> + case KVM_PMU_EVENT_FMT_X86_DEFAULT:
> + code = X86_PMU_RAW_EVENT(event->u.x86_default.select,
> + event->u.x86_default.umask);
> + break;
> default:
> g_assert_not_reached();
> }
> @@ -6073,6 +6077,7 @@ static void kvm_arch_check_pmu_filter(const Object
> *obj, const char *name,
>
> switch (event->format) {
> case KVM_PMU_EVENT_FMT_RAW:
> + case KVM_PMU_EVENT_FMT_X86_DEFAULT:
> break;
> default:
> error_setg(errp,