static int amd_pmu_hw_config(struct perf_event *event) { int ret = x86_pmu_hw_config(event); if (ret) return ret; if (has_branch_stack(event)) return -EOPNOTSUPP; if (event->attr.exclude_host && event->attr.exclude_guest) event->hw.config &= ~(ARCH_PERFMON_EVENTSEL_USR | ARCH_PERFMON_EVENTSEL_OS); else if (event->attr.exclude_host) event->hw.config |= AMD_PERFMON_EVENTSEL_GUESTONLY; else if (event->attr.exclude_guest) event->hw.config |= AMD_PERFMON_EVENTSEL_HOSTONLY; if (event->attr.type != PERF_TYPE_RAW) return 0; event->hw.config |= event->attr.config & AMD64_RAW_EVENT_MASK; return 0; }
static int amd_pmu_hw_config(struct perf_event *event) { int ret = x86_pmu_hw_config(event); if (ret) return ret; if (has_branch_stack(event)) return -EOPNOTSUPP; if (event->attr.exclude_host && event->attr.exclude_guest) /* * When HO == GO == 1 the hardware treats that as GO == HO == 0 * and will count in both modes. We don't want to count in that * case so we emulate no-counting by setting US = OS = 0. */ event->hw.config &= ~(ARCH_PERFMON_EVENTSEL_USR | ARCH_PERFMON_EVENTSEL_OS); else if (event->attr.exclude_host) event->hw.config |= AMD_PERFMON_EVENTSEL_GUESTONLY; else if (event->attr.exclude_guest) event->hw.config |= AMD_PERFMON_EVENTSEL_HOSTONLY; if (event->attr.type != PERF_TYPE_RAW) return 0; event->hw.config |= event->attr.config & AMD64_RAW_EVENT_MASK; return 0; }
static int h_gpci_event_init(struct perf_event *event) { u64 count; u8 length; /* Not our event */ if (event->attr.type != event->pmu->type) return -ENOENT; /* config2 is unused */ if (event->attr.config2) { pr_devel("config2 set when reserved\n"); return -EINVAL; } /* unsupported modes and filters */ if (event->attr.exclude_user || event->attr.exclude_kernel || event->attr.exclude_hv || event->attr.exclude_idle || event->attr.exclude_host || event->attr.exclude_guest) return -EINVAL; /* no branch sampling */ if (has_branch_stack(event)) return -EOPNOTSUPP; length = event_get_length(event); if (length < 1 || length > 8) { pr_devel("length invalid\n"); return -EINVAL; } /* last byte within the buffer? */ if ((event_get_offset(event) + length) > GPCI_MAX_DATA_BYTES) { pr_devel("request outside of buffer: %zu > %zu\n", (size_t)event_get_offset(event) + length, GPCI_MAX_DATA_BYTES); return -EINVAL; } /* check if the request works... */ if (single_gpci_request(event_get_request(event), event_get_starting_index(event), event_get_secondary_index(event), event_get_counter_info_version(event), event_get_offset(event), length, &count)) { pr_devel("gpci hcall failed\n"); return -EINVAL; } return 0; }
static inline bool intel_pmu_needs_lbr_smpl(struct perf_event *event) { /* user explicitly requested branch sampling */ if (has_branch_stack(event)) return true; /* implicit branch sampling to correct PEBS skid */ if (x86_pmu.intel_cap.pebs_trap && event->attr.precise_ip > 1 && x86_pmu.intel_cap.pebs_format < 2) return true; return false; }