qemu-devel
[Top][All Lists]
Advanced

[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,



reply via email to

[Prev in Thread] Current Thread [Next in Thread]