• Aaron Lewis's avatar
    KVM: x86/pmu: Introduce masked events to the pmu event filter · 14329b82
    Aaron Lewis authored
    When building a list of filter events, it can sometimes be a challenge
    to fit all the events needed to adequately restrict the guest into the
    limited space available in the pmu event filter.  This stems from the
    fact that the pmu event filter requires each event (i.e. event select +
    unit mask) be listed, when the intention might be to restrict the
    event select all together, regardless of it's unit mask.  Instead of
    increasing the number of filter events in the pmu event filter, add a
    new encoding that is able to do a more generalized match on the unit mask.
    
    Introduce masked events as another encoding the pmu event filter
    understands.  Masked events has the fields: mask, match, and exclude.
    When filtering based on these events, the mask is applied to the guest's
    unit mask to see if it matches the match value (i.e. umask & mask ==
    match).  The exclude bit can then be used to exclude events from that
    match.  E.g. for a given event select, if it's easier to say which unit
    mask values shouldn't be filtered, a masked event can be set up to match
    all possible unit mask values, then another masked event can be set up to
    match the unit mask values that shouldn't be filtered.
    
    Userspace can query to see if this feature exists by looking for the
    capability, KVM_CAP_PMU_EVENT_MASKED_EVENTS.
    
    This feature is enabled by setting the flags field in the pmu event
    filter to KVM_PMU_EVENT_FLAG_MASKED_EVENTS.
    
    Events can be encoded by using KVM_PMU_ENCODE_MASKED_ENTRY().
    
    It is an error to have a bit set outside the valid bits for a masked
    event, and calls to KVM_SET_PMU_EVENT_FILTER will return -EINVAL in
    such cases, including the high bits of the event select (35:32) if
    called on Intel.
    
    With these updates the filter matching code has been updated to match on
    a common event.  Masked events were flexible enough to handle both event
    types, so they were used as the common event.  This changes how guest
    events get filtered because regardless of the type of event used in the
    uAPI, they will be converted to masked events.  Because of this there
    could be a slight performance hit because instead of matching the filter
    event with a lookup on event select + unit mask, it does a lookup on event
    select then walks the unit masks to find the match.  This shouldn't be a
    big problem because I would expect the set of common event selects to be
    small, and if they aren't the set can likely be reduced by using masked
    events to generalize the unit mask.  Using one type of event when
    filtering guest events allows for a common code path to be used.
    Signed-off-by: default avatarAaron Lewis <aaronlewis@google.com>
    Link: https://lore.kernel.org/r/20221220161236.555143-5-aaronlewis@google.comSigned-off-by: default avatarSean Christopherson <seanjc@google.com>
    14329b82
x86.c 359 KB