Commit 16b3d851 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'perf-tools-fixes-for-v6.0-2022-08-19' of...

Merge tag 'perf-tools-fixes-for-v6.0-2022-08-19' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux

Pull perf tools fixes from Arnaldo Carvalho de Melo:

 - Fix alignment for cpu map masks in event encoding.

 - Support reading PERF_FORMAT_LOST, perf tool counterpart for a feature
   that was added in this merge window.

 - Sync perf tools copies of kernel headers: socket, msr-index, fscrypt,
   cpufeatures, i915_drm, kvm, vhost, perf_event.

* tag 'perf-tools-fixes-for-v6.0-2022-08-19' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux:
  perf tools: Support reading PERF_FORMAT_LOST
  libperf: Add a test case for read formats
  libperf: Handle read format in perf_evsel__read()
  tools headers UAPI: Sync linux/perf_event.h with the kernel sources
  tools headers UAPI: Sync x86's asm/kvm.h with the kernel sources
  tools headers UAPI: Sync KVM's vmx.h header with the kernel sources
  tools include UAPI: Sync linux/vhost.h with the kernel sources
  tools headers kvm s390: Sync headers with the kernel sources
  tools headers UAPI: Sync linux/kvm.h with the kernel sources
  tools headers UAPI: Sync drm/i915_drm.h with the kernel sources
  tools headers cpufeatures: Sync with the kernel sources
  tools headers UAPI: Sync linux/fscrypt.h with the kernel sources
  tools arch x86: Sync the msr-index.h copy with the kernel sources
  perf beauty: Update copy of linux/socket.h with the kernel sources
  perf cpumap: Fix alignment for masks in event encoding
  perf cpumap: Compute mask size in constant time
  perf cpumap: Synthetic events and const/static
  perf cpumap: Const map for max()
parents cc1807b9 f52679b7
...@@ -74,6 +74,7 @@ struct kvm_s390_io_adapter_req { ...@@ -74,6 +74,7 @@ struct kvm_s390_io_adapter_req {
#define KVM_S390_VM_CRYPTO 2 #define KVM_S390_VM_CRYPTO 2
#define KVM_S390_VM_CPU_MODEL 3 #define KVM_S390_VM_CPU_MODEL 3
#define KVM_S390_VM_MIGRATION 4 #define KVM_S390_VM_MIGRATION 4
#define KVM_S390_VM_CPU_TOPOLOGY 5
/* kvm attributes for mem_ctrl */ /* kvm attributes for mem_ctrl */
#define KVM_S390_VM_MEM_ENABLE_CMMA 0 #define KVM_S390_VM_MEM_ENABLE_CMMA 0
......
...@@ -219,7 +219,7 @@ ...@@ -219,7 +219,7 @@
#define X86_FEATURE_IBRS ( 7*32+25) /* Indirect Branch Restricted Speculation */ #define X86_FEATURE_IBRS ( 7*32+25) /* Indirect Branch Restricted Speculation */
#define X86_FEATURE_IBPB ( 7*32+26) /* Indirect Branch Prediction Barrier */ #define X86_FEATURE_IBPB ( 7*32+26) /* Indirect Branch Prediction Barrier */
#define X86_FEATURE_STIBP ( 7*32+27) /* Single Thread Indirect Branch Predictors */ #define X86_FEATURE_STIBP ( 7*32+27) /* Single Thread Indirect Branch Predictors */
#define X86_FEATURE_ZEN ( 7*32+28) /* "" CPU is AMD family 0x17 or above (Zen) */ #define X86_FEATURE_ZEN (7*32+28) /* "" CPU based on Zen microarchitecture */
#define X86_FEATURE_L1TF_PTEINV ( 7*32+29) /* "" L1TF workaround PTE inversion */ #define X86_FEATURE_L1TF_PTEINV ( 7*32+29) /* "" L1TF workaround PTE inversion */
#define X86_FEATURE_IBRS_ENHANCED ( 7*32+30) /* Enhanced IBRS */ #define X86_FEATURE_IBRS_ENHANCED ( 7*32+30) /* Enhanced IBRS */
#define X86_FEATURE_MSR_IA32_FEAT_CTL ( 7*32+31) /* "" MSR IA32_FEAT_CTL configured */ #define X86_FEATURE_MSR_IA32_FEAT_CTL ( 7*32+31) /* "" MSR IA32_FEAT_CTL configured */
...@@ -303,7 +303,7 @@ ...@@ -303,7 +303,7 @@
#define X86_FEATURE_RETHUNK (11*32+14) /* "" Use REturn THUNK */ #define X86_FEATURE_RETHUNK (11*32+14) /* "" Use REturn THUNK */
#define X86_FEATURE_UNRET (11*32+15) /* "" AMD BTB untrain return */ #define X86_FEATURE_UNRET (11*32+15) /* "" AMD BTB untrain return */
#define X86_FEATURE_USE_IBPB_FW (11*32+16) /* "" Use IBPB during runtime firmware calls */ #define X86_FEATURE_USE_IBPB_FW (11*32+16) /* "" Use IBPB during runtime firmware calls */
#define X86_FEATURE_RSB_VMEXIT_LITE (11*32+17) /* "" Fill RSB on VM-Exit when EIBRS is enabled */ #define X86_FEATURE_RSB_VMEXIT_LITE (11*32+17) /* "" Fill RSB on VM exit when EIBRS is enabled */
/* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */ /* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */
#define X86_FEATURE_AVX_VNNI (12*32+ 4) /* AVX VNNI instructions */ #define X86_FEATURE_AVX_VNNI (12*32+ 4) /* AVX VNNI instructions */
...@@ -354,6 +354,7 @@ ...@@ -354,6 +354,7 @@
#define X86_FEATURE_AVIC (15*32+13) /* Virtual Interrupt Controller */ #define X86_FEATURE_AVIC (15*32+13) /* Virtual Interrupt Controller */
#define X86_FEATURE_V_VMSAVE_VMLOAD (15*32+15) /* Virtual VMSAVE VMLOAD */ #define X86_FEATURE_V_VMSAVE_VMLOAD (15*32+15) /* Virtual VMSAVE VMLOAD */
#define X86_FEATURE_VGIF (15*32+16) /* Virtual GIF */ #define X86_FEATURE_VGIF (15*32+16) /* Virtual GIF */
#define X86_FEATURE_X2AVIC (15*32+18) /* Virtual x2apic */
#define X86_FEATURE_V_SPEC_CTRL (15*32+20) /* Virtual SPEC_CTRL */ #define X86_FEATURE_V_SPEC_CTRL (15*32+20) /* Virtual SPEC_CTRL */
#define X86_FEATURE_SVME_ADDR_CHK (15*32+28) /* "" SVME addr check */ #define X86_FEATURE_SVME_ADDR_CHK (15*32+28) /* "" SVME addr check */
...@@ -457,5 +458,6 @@ ...@@ -457,5 +458,6 @@
#define X86_BUG_SRBDS X86_BUG(24) /* CPU may leak RNG bits if not mitigated */ #define X86_BUG_SRBDS X86_BUG(24) /* CPU may leak RNG bits if not mitigated */
#define X86_BUG_MMIO_STALE_DATA X86_BUG(25) /* CPU is affected by Processor MMIO Stale Data vulnerabilities */ #define X86_BUG_MMIO_STALE_DATA X86_BUG(25) /* CPU is affected by Processor MMIO Stale Data vulnerabilities */
#define X86_BUG_RETBLEED X86_BUG(26) /* CPU is affected by RETBleed */ #define X86_BUG_RETBLEED X86_BUG(26) /* CPU is affected by RETBleed */
#define X86_BUG_EIBRS_PBRSB X86_BUG(27) /* EIBRS is vulnerable to Post Barrier RSB Predictions */
#endif /* _ASM_X86_CPUFEATURES_H */ #endif /* _ASM_X86_CPUFEATURES_H */
...@@ -235,6 +235,12 @@ ...@@ -235,6 +235,12 @@
#define PERF_CAP_PT_IDX 16 #define PERF_CAP_PT_IDX 16
#define MSR_PEBS_LD_LAT_THRESHOLD 0x000003f6 #define MSR_PEBS_LD_LAT_THRESHOLD 0x000003f6
#define PERF_CAP_PEBS_TRAP BIT_ULL(6)
#define PERF_CAP_ARCH_REG BIT_ULL(7)
#define PERF_CAP_PEBS_FORMAT 0xf00
#define PERF_CAP_PEBS_BASELINE BIT_ULL(14)
#define PERF_CAP_PEBS_MASK (PERF_CAP_PEBS_TRAP | PERF_CAP_ARCH_REG | \
PERF_CAP_PEBS_FORMAT | PERF_CAP_PEBS_BASELINE)
#define MSR_IA32_RTIT_CTL 0x00000570 #define MSR_IA32_RTIT_CTL 0x00000570
#define RTIT_CTL_TRACEEN BIT(0) #define RTIT_CTL_TRACEEN BIT(0)
...@@ -392,6 +398,7 @@ ...@@ -392,6 +398,7 @@
#define MSR_TURBO_ACTIVATION_RATIO 0x0000064C #define MSR_TURBO_ACTIVATION_RATIO 0x0000064C
#define MSR_PLATFORM_ENERGY_STATUS 0x0000064D #define MSR_PLATFORM_ENERGY_STATUS 0x0000064D
#define MSR_SECONDARY_TURBO_RATIO_LIMIT 0x00000650
#define MSR_PKG_WEIGHTED_CORE_C0_RES 0x00000658 #define MSR_PKG_WEIGHTED_CORE_C0_RES 0x00000658
#define MSR_PKG_ANY_CORE_C0_RES 0x00000659 #define MSR_PKG_ANY_CORE_C0_RES 0x00000659
...@@ -1022,6 +1029,7 @@ ...@@ -1022,6 +1029,7 @@
#define MSR_IA32_VMX_TRUE_EXIT_CTLS 0x0000048f #define MSR_IA32_VMX_TRUE_EXIT_CTLS 0x0000048f
#define MSR_IA32_VMX_TRUE_ENTRY_CTLS 0x00000490 #define MSR_IA32_VMX_TRUE_ENTRY_CTLS 0x00000490
#define MSR_IA32_VMX_VMFUNC 0x00000491 #define MSR_IA32_VMX_VMFUNC 0x00000491
#define MSR_IA32_VMX_PROCBASED_CTLS3 0x00000492
/* VMX_BASIC bits and bitmasks */ /* VMX_BASIC bits and bitmasks */
#define VMX_BASIC_VMCS_SIZE_SHIFT 32 #define VMX_BASIC_VMCS_SIZE_SHIFT 32
......
...@@ -306,7 +306,8 @@ struct kvm_pit_state { ...@@ -306,7 +306,8 @@ struct kvm_pit_state {
struct kvm_pit_channel_state channels[3]; struct kvm_pit_channel_state channels[3];
}; };
#define KVM_PIT_FLAGS_HPET_LEGACY 0x00000001 #define KVM_PIT_FLAGS_HPET_LEGACY 0x00000001
#define KVM_PIT_FLAGS_SPEAKER_DATA_ON 0x00000002
struct kvm_pit_state2 { struct kvm_pit_state2 {
struct kvm_pit_channel_state channels[3]; struct kvm_pit_channel_state channels[3];
...@@ -325,6 +326,7 @@ struct kvm_reinject_control { ...@@ -325,6 +326,7 @@ struct kvm_reinject_control {
#define KVM_VCPUEVENT_VALID_SHADOW 0x00000004 #define KVM_VCPUEVENT_VALID_SHADOW 0x00000004
#define KVM_VCPUEVENT_VALID_SMM 0x00000008 #define KVM_VCPUEVENT_VALID_SMM 0x00000008
#define KVM_VCPUEVENT_VALID_PAYLOAD 0x00000010 #define KVM_VCPUEVENT_VALID_PAYLOAD 0x00000010
#define KVM_VCPUEVENT_VALID_TRIPLE_FAULT 0x00000020
/* Interrupt shadow states */ /* Interrupt shadow states */
#define KVM_X86_SHADOW_INT_MOV_SS 0x01 #define KVM_X86_SHADOW_INT_MOV_SS 0x01
...@@ -359,7 +361,10 @@ struct kvm_vcpu_events { ...@@ -359,7 +361,10 @@ struct kvm_vcpu_events {
__u8 smm_inside_nmi; __u8 smm_inside_nmi;
__u8 latched_init; __u8 latched_init;
} smi; } smi;
__u8 reserved[27]; struct {
__u8 pending;
} triple_fault;
__u8 reserved[26];
__u8 exception_has_payload; __u8 exception_has_payload;
__u64 exception_payload; __u64 exception_payload;
}; };
...@@ -434,6 +439,7 @@ struct kvm_sync_regs { ...@@ -434,6 +439,7 @@ struct kvm_sync_regs {
#define KVM_X86_QUIRK_OUT_7E_INC_RIP (1 << 3) #define KVM_X86_QUIRK_OUT_7E_INC_RIP (1 << 3)
#define KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT (1 << 4) #define KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT (1 << 4)
#define KVM_X86_QUIRK_FIX_HYPERCALL_INSN (1 << 5) #define KVM_X86_QUIRK_FIX_HYPERCALL_INSN (1 << 5)
#define KVM_X86_QUIRK_MWAIT_NEVER_UD_FAULTS (1 << 6)
#define KVM_STATE_NESTED_FORMAT_VMX 0 #define KVM_STATE_NESTED_FORMAT_VMX 0
#define KVM_STATE_NESTED_FORMAT_SVM 1 #define KVM_STATE_NESTED_FORMAT_SVM 1
......
...@@ -91,6 +91,7 @@ ...@@ -91,6 +91,7 @@
#define EXIT_REASON_UMWAIT 67 #define EXIT_REASON_UMWAIT 67
#define EXIT_REASON_TPAUSE 68 #define EXIT_REASON_TPAUSE 68
#define EXIT_REASON_BUS_LOCK 74 #define EXIT_REASON_BUS_LOCK 74
#define EXIT_REASON_NOTIFY 75
#define VMX_EXIT_REASONS \ #define VMX_EXIT_REASONS \
{ EXIT_REASON_EXCEPTION_NMI, "EXCEPTION_NMI" }, \ { EXIT_REASON_EXCEPTION_NMI, "EXCEPTION_NMI" }, \
...@@ -153,7 +154,8 @@ ...@@ -153,7 +154,8 @@
{ EXIT_REASON_XRSTORS, "XRSTORS" }, \ { EXIT_REASON_XRSTORS, "XRSTORS" }, \
{ EXIT_REASON_UMWAIT, "UMWAIT" }, \ { EXIT_REASON_UMWAIT, "UMWAIT" }, \
{ EXIT_REASON_TPAUSE, "TPAUSE" }, \ { EXIT_REASON_TPAUSE, "TPAUSE" }, \
{ EXIT_REASON_BUS_LOCK, "BUS_LOCK" } { EXIT_REASON_BUS_LOCK, "BUS_LOCK" }, \
{ EXIT_REASON_NOTIFY, "NOTIFY" }
#define VMX_EXIT_REASON_FLAGS \ #define VMX_EXIT_REASON_FLAGS \
{ VMX_EXIT_REASONS_FAILED_VMENTRY, "FAILED_VMENTRY" } { VMX_EXIT_REASONS_FAILED_VMENTRY, "FAILED_VMENTRY" }
......
This diff is collapsed.
...@@ -27,7 +27,8 @@ ...@@ -27,7 +27,8 @@
#define FSCRYPT_MODE_AES_128_CBC 5 #define FSCRYPT_MODE_AES_128_CBC 5
#define FSCRYPT_MODE_AES_128_CTS 6 #define FSCRYPT_MODE_AES_128_CTS 6
#define FSCRYPT_MODE_ADIANTUM 9 #define FSCRYPT_MODE_ADIANTUM 9
/* If adding a mode number > 9, update FSCRYPT_MODE_MAX in fscrypt_private.h */ #define FSCRYPT_MODE_AES_256_HCTR2 10
/* If adding a mode number > 10, update FSCRYPT_MODE_MAX in fscrypt_private.h */
/* /*
* Legacy policy version; ad-hoc KDF and no key verification. * Legacy policy version; ad-hoc KDF and no key verification.
......
...@@ -270,6 +270,8 @@ struct kvm_xen_exit { ...@@ -270,6 +270,8 @@ struct kvm_xen_exit {
#define KVM_EXIT_X86_BUS_LOCK 33 #define KVM_EXIT_X86_BUS_LOCK 33
#define KVM_EXIT_XEN 34 #define KVM_EXIT_XEN 34
#define KVM_EXIT_RISCV_SBI 35 #define KVM_EXIT_RISCV_SBI 35
#define KVM_EXIT_RISCV_CSR 36
#define KVM_EXIT_NOTIFY 37
/* For KVM_EXIT_INTERNAL_ERROR */ /* For KVM_EXIT_INTERNAL_ERROR */
/* Emulate instruction failed. */ /* Emulate instruction failed. */
...@@ -496,6 +498,18 @@ struct kvm_run { ...@@ -496,6 +498,18 @@ struct kvm_run {
unsigned long args[6]; unsigned long args[6];
unsigned long ret[2]; unsigned long ret[2];
} riscv_sbi; } riscv_sbi;
/* KVM_EXIT_RISCV_CSR */
struct {
unsigned long csr_num;
unsigned long new_value;
unsigned long write_mask;
unsigned long ret_value;
} riscv_csr;
/* KVM_EXIT_NOTIFY */
struct {
#define KVM_NOTIFY_CONTEXT_INVALID (1 << 0)
__u32 flags;
} notify;
/* Fix the size of the union. */ /* Fix the size of the union. */
char padding[256]; char padding[256];
}; };
...@@ -1157,6 +1171,12 @@ struct kvm_ppc_resize_hpt { ...@@ -1157,6 +1171,12 @@ struct kvm_ppc_resize_hpt {
#define KVM_CAP_VM_TSC_CONTROL 214 #define KVM_CAP_VM_TSC_CONTROL 214
#define KVM_CAP_SYSTEM_EVENT_DATA 215 #define KVM_CAP_SYSTEM_EVENT_DATA 215
#define KVM_CAP_ARM_SYSTEM_SUSPEND 216 #define KVM_CAP_ARM_SYSTEM_SUSPEND 216
#define KVM_CAP_S390_PROTECTED_DUMP 217
#define KVM_CAP_X86_TRIPLE_FAULT_EVENT 218
#define KVM_CAP_X86_NOTIFY_VMEXIT 219
#define KVM_CAP_VM_DISABLE_NX_HUGE_PAGES 220
#define KVM_CAP_S390_ZPCI_OP 221
#define KVM_CAP_S390_CPU_TOPOLOGY 222
#ifdef KVM_CAP_IRQ_ROUTING #ifdef KVM_CAP_IRQ_ROUTING
...@@ -1660,6 +1680,55 @@ struct kvm_s390_pv_unp { ...@@ -1660,6 +1680,55 @@ struct kvm_s390_pv_unp {
__u64 tweak; __u64 tweak;
}; };
enum pv_cmd_dmp_id {
KVM_PV_DUMP_INIT,
KVM_PV_DUMP_CONFIG_STOR_STATE,
KVM_PV_DUMP_COMPLETE,
KVM_PV_DUMP_CPU,
};
struct kvm_s390_pv_dmp {
__u64 subcmd;
__u64 buff_addr;
__u64 buff_len;
__u64 gaddr; /* For dump storage state */
__u64 reserved[4];
};
enum pv_cmd_info_id {
KVM_PV_INFO_VM,
KVM_PV_INFO_DUMP,
};
struct kvm_s390_pv_info_dump {
__u64 dump_cpu_buffer_len;
__u64 dump_config_mem_buffer_per_1m;
__u64 dump_config_finalize_len;
};
struct kvm_s390_pv_info_vm {
__u64 inst_calls_list[4];
__u64 max_cpus;
__u64 max_guests;
__u64 max_guest_addr;
__u64 feature_indication;
};
struct kvm_s390_pv_info_header {
__u32 id;
__u32 len_max;
__u32 len_written;
__u32 reserved;
};
struct kvm_s390_pv_info {
struct kvm_s390_pv_info_header header;
union {
struct kvm_s390_pv_info_dump dump;
struct kvm_s390_pv_info_vm vm;
};
};
enum pv_cmd_id { enum pv_cmd_id {
KVM_PV_ENABLE, KVM_PV_ENABLE,
KVM_PV_DISABLE, KVM_PV_DISABLE,
...@@ -1668,6 +1737,8 @@ enum pv_cmd_id { ...@@ -1668,6 +1737,8 @@ enum pv_cmd_id {
KVM_PV_VERIFY, KVM_PV_VERIFY,
KVM_PV_PREP_RESET, KVM_PV_PREP_RESET,
KVM_PV_UNSHARE_ALL, KVM_PV_UNSHARE_ALL,
KVM_PV_INFO,
KVM_PV_DUMP,
}; };
struct kvm_pv_cmd { struct kvm_pv_cmd {
...@@ -2119,4 +2190,41 @@ struct kvm_stats_desc { ...@@ -2119,4 +2190,41 @@ struct kvm_stats_desc {
/* Available with KVM_CAP_XSAVE2 */ /* Available with KVM_CAP_XSAVE2 */
#define KVM_GET_XSAVE2 _IOR(KVMIO, 0xcf, struct kvm_xsave) #define KVM_GET_XSAVE2 _IOR(KVMIO, 0xcf, struct kvm_xsave)
/* Available with KVM_CAP_S390_PROTECTED_DUMP */
#define KVM_S390_PV_CPU_COMMAND _IOWR(KVMIO, 0xd0, struct kvm_pv_cmd)
/* Available with KVM_CAP_X86_NOTIFY_VMEXIT */
#define KVM_X86_NOTIFY_VMEXIT_ENABLED (1ULL << 0)
#define KVM_X86_NOTIFY_VMEXIT_USER (1ULL << 1)
/* Available with KVM_CAP_S390_ZPCI_OP */
#define KVM_S390_ZPCI_OP _IOW(KVMIO, 0xd1, struct kvm_s390_zpci_op)
struct kvm_s390_zpci_op {
/* in */
__u32 fh; /* target device */
__u8 op; /* operation to perform */
__u8 pad[3];
union {
/* for KVM_S390_ZPCIOP_REG_AEN */
struct {
__u64 ibv; /* Guest addr of interrupt bit vector */
__u64 sb; /* Guest addr of summary bit */
__u32 flags;
__u32 noi; /* Number of interrupts */
__u8 isc; /* Guest interrupt subclass */
__u8 sbo; /* Offset of guest summary bit vector */
__u16 pad;
} reg_aen;
__u64 reserved[8];
} u;
};
/* types for kvm_s390_zpci_op->op */
#define KVM_S390_ZPCIOP_REG_AEN 0
#define KVM_S390_ZPCIOP_DEREG_AEN 1
/* flags for kvm_s390_zpci_op->u.reg_aen.flags */
#define KVM_S390_ZPCIOP_REGAEN_HOST (1 << 0)
#endif /* __LINUX_KVM_H */ #endif /* __LINUX_KVM_H */
...@@ -301,6 +301,7 @@ enum { ...@@ -301,6 +301,7 @@ enum {
* { u64 time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED * { u64 time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED
* { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING * { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
* { u64 id; } && PERF_FORMAT_ID * { u64 id; } && PERF_FORMAT_ID
* { u64 lost; } && PERF_FORMAT_LOST
* } && !PERF_FORMAT_GROUP * } && !PERF_FORMAT_GROUP
* *
* { u64 nr; * { u64 nr;
...@@ -308,6 +309,7 @@ enum { ...@@ -308,6 +309,7 @@ enum {
* { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING * { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
* { u64 value; * { u64 value;
* { u64 id; } && PERF_FORMAT_ID * { u64 id; } && PERF_FORMAT_ID
* { u64 lost; } && PERF_FORMAT_LOST
* } cntr[nr]; * } cntr[nr];
* } && PERF_FORMAT_GROUP * } && PERF_FORMAT_GROUP
* }; * };
...@@ -317,8 +319,9 @@ enum perf_event_read_format { ...@@ -317,8 +319,9 @@ enum perf_event_read_format {
PERF_FORMAT_TOTAL_TIME_RUNNING = 1U << 1, PERF_FORMAT_TOTAL_TIME_RUNNING = 1U << 1,
PERF_FORMAT_ID = 1U << 2, PERF_FORMAT_ID = 1U << 2,
PERF_FORMAT_GROUP = 1U << 3, PERF_FORMAT_GROUP = 1U << 3,
PERF_FORMAT_LOST = 1U << 4,
PERF_FORMAT_MAX = 1U << 4, /* non-ABI */ PERF_FORMAT_MAX = 1U << 5, /* non-ABI */
}; };
#define PERF_ATTR_SIZE_VER0 64 /* sizeof first published struct */ #define PERF_ATTR_SIZE_VER0 64 /* sizeof first published struct */
......
...@@ -171,4 +171,13 @@ ...@@ -171,4 +171,13 @@
#define VHOST_VDPA_SET_GROUP_ASID _IOW(VHOST_VIRTIO, 0x7C, \ #define VHOST_VDPA_SET_GROUP_ASID _IOW(VHOST_VIRTIO, 0x7C, \
struct vhost_vring_state) struct vhost_vring_state)
/* Suspend a device so it does not process virtqueue requests anymore
*
* After the return of ioctl the device must preserve all the necessary state
* (the virtqueue vring base plus the possible device specific states) that is
* required for restoring in the future. The device must not change its
* configuration after that point.
*/
#define VHOST_VDPA_SUSPEND _IO(VHOST_VIRTIO, 0x7D)
#endif #endif
...@@ -309,7 +309,7 @@ bool perf_cpu_map__has(const struct perf_cpu_map *cpus, struct perf_cpu cpu) ...@@ -309,7 +309,7 @@ bool perf_cpu_map__has(const struct perf_cpu_map *cpus, struct perf_cpu cpu)
return perf_cpu_map__idx(cpus, cpu) != -1; return perf_cpu_map__idx(cpus, cpu) != -1;
} }
struct perf_cpu perf_cpu_map__max(struct perf_cpu_map *map) struct perf_cpu perf_cpu_map__max(const struct perf_cpu_map *map)
{ {
struct perf_cpu result = { struct perf_cpu result = {
.cpu = -1 .cpu = -1
......
...@@ -305,6 +305,9 @@ int perf_evsel__read_size(struct perf_evsel *evsel) ...@@ -305,6 +305,9 @@ int perf_evsel__read_size(struct perf_evsel *evsel)
if (read_format & PERF_FORMAT_ID) if (read_format & PERF_FORMAT_ID)
entry += sizeof(u64); entry += sizeof(u64);
if (read_format & PERF_FORMAT_LOST)
entry += sizeof(u64);
if (read_format & PERF_FORMAT_GROUP) { if (read_format & PERF_FORMAT_GROUP) {
nr = evsel->nr_members; nr = evsel->nr_members;
size += sizeof(u64); size += sizeof(u64);
...@@ -314,24 +317,98 @@ int perf_evsel__read_size(struct perf_evsel *evsel) ...@@ -314,24 +317,98 @@ int perf_evsel__read_size(struct perf_evsel *evsel)
return size; return size;
} }
/* This only reads values for the leader */
static int perf_evsel__read_group(struct perf_evsel *evsel, int cpu_map_idx,
int thread, struct perf_counts_values *count)
{
size_t size = perf_evsel__read_size(evsel);
int *fd = FD(evsel, cpu_map_idx, thread);
u64 read_format = evsel->attr.read_format;
u64 *data;
int idx = 1;
if (fd == NULL || *fd < 0)
return -EINVAL;
data = calloc(1, size);
if (data == NULL)
return -ENOMEM;
if (readn(*fd, data, size) <= 0) {
free(data);
return -errno;
}
/*
* This reads only the leader event intentionally since we don't have
* perf counts values for sibling events.
*/
if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
count->ena = data[idx++];
if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
count->run = data[idx++];
/* value is always available */
count->val = data[idx++];
if (read_format & PERF_FORMAT_ID)
count->id = data[idx++];
if (read_format & PERF_FORMAT_LOST)
count->lost = data[idx++];
free(data);
return 0;
}
/*
* The perf read format is very flexible. It needs to set the proper
* values according to the read format.
*/
static void perf_evsel__adjust_values(struct perf_evsel *evsel, u64 *buf,
struct perf_counts_values *count)
{
u64 read_format = evsel->attr.read_format;
int n = 0;
count->val = buf[n++];
if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
count->ena = buf[n++];
if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
count->run = buf[n++];
if (read_format & PERF_FORMAT_ID)
count->id = buf[n++];
if (read_format & PERF_FORMAT_LOST)
count->lost = buf[n++];
}
int perf_evsel__read(struct perf_evsel *evsel, int cpu_map_idx, int thread, int perf_evsel__read(struct perf_evsel *evsel, int cpu_map_idx, int thread,
struct perf_counts_values *count) struct perf_counts_values *count)
{ {
size_t size = perf_evsel__read_size(evsel); size_t size = perf_evsel__read_size(evsel);
int *fd = FD(evsel, cpu_map_idx, thread); int *fd = FD(evsel, cpu_map_idx, thread);
u64 read_format = evsel->attr.read_format;
struct perf_counts_values buf;
memset(count, 0, sizeof(*count)); memset(count, 0, sizeof(*count));
if (fd == NULL || *fd < 0) if (fd == NULL || *fd < 0)
return -EINVAL; return -EINVAL;
if (read_format & PERF_FORMAT_GROUP)
return perf_evsel__read_group(evsel, cpu_map_idx, thread, count);
if (MMAP(evsel, cpu_map_idx, thread) && if (MMAP(evsel, cpu_map_idx, thread) &&
!(read_format & (PERF_FORMAT_ID | PERF_FORMAT_LOST)) &&
!perf_mmap__read_self(MMAP(evsel, cpu_map_idx, thread), count)) !perf_mmap__read_self(MMAP(evsel, cpu_map_idx, thread), count))
return 0; return 0;
if (readn(*fd, count->values, size) <= 0) if (readn(*fd, buf.values, size) <= 0)
return -errno; return -errno;
perf_evsel__adjust_values(evsel, buf.values, count);
return 0; return 0;
} }
......
...@@ -23,7 +23,7 @@ LIBPERF_API void perf_cpu_map__put(struct perf_cpu_map *map); ...@@ -23,7 +23,7 @@ LIBPERF_API void perf_cpu_map__put(struct perf_cpu_map *map);
LIBPERF_API struct perf_cpu perf_cpu_map__cpu(const struct perf_cpu_map *cpus, int idx); LIBPERF_API struct perf_cpu perf_cpu_map__cpu(const struct perf_cpu_map *cpus, int idx);
LIBPERF_API int perf_cpu_map__nr(const struct perf_cpu_map *cpus); LIBPERF_API int perf_cpu_map__nr(const struct perf_cpu_map *cpus);
LIBPERF_API bool perf_cpu_map__empty(const struct perf_cpu_map *map); LIBPERF_API bool perf_cpu_map__empty(const struct perf_cpu_map *map);
LIBPERF_API struct perf_cpu perf_cpu_map__max(struct perf_cpu_map *map); LIBPERF_API struct perf_cpu perf_cpu_map__max(const struct perf_cpu_map *map);
LIBPERF_API bool perf_cpu_map__has(const struct perf_cpu_map *map, struct perf_cpu cpu); LIBPERF_API bool perf_cpu_map__has(const struct perf_cpu_map *map, struct perf_cpu cpu);
#define perf_cpu_map__for_each_cpu(cpu, idx, cpus) \ #define perf_cpu_map__for_each_cpu(cpu, idx, cpus) \
......
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/limits.h> #include <linux/limits.h>
#include <linux/bpf.h> #include <linux/bpf.h>
#include <linux/compiler.h>
#include <sys/types.h> /* pid_t */ #include <sys/types.h> /* pid_t */
#define event_contains(obj, mem) ((obj).header.size > offsetof(typeof(obj), mem)) #define event_contains(obj, mem) ((obj).header.size > offsetof(typeof(obj), mem))
...@@ -76,7 +77,7 @@ struct perf_record_lost_samples { ...@@ -76,7 +77,7 @@ struct perf_record_lost_samples {
}; };
/* /*
* PERF_FORMAT_ENABLED | PERF_FORMAT_RUNNING | PERF_FORMAT_ID * PERF_FORMAT_ENABLED | PERF_FORMAT_RUNNING | PERF_FORMAT_ID | PERF_FORMAT_LOST
*/ */
struct perf_record_read { struct perf_record_read {
struct perf_event_header header; struct perf_event_header header;
...@@ -85,6 +86,7 @@ struct perf_record_read { ...@@ -85,6 +86,7 @@ struct perf_record_read {
__u64 time_enabled; __u64 time_enabled;
__u64 time_running; __u64 time_running;
__u64 id; __u64 id;
__u64 lost;
}; };
struct perf_record_throttle { struct perf_record_throttle {
...@@ -153,22 +155,60 @@ enum { ...@@ -153,22 +155,60 @@ enum {
PERF_CPU_MAP__MASK = 1, PERF_CPU_MAP__MASK = 1,
}; };
/*
* Array encoding of a perf_cpu_map where nr is the number of entries in cpu[]
* and each entry is a value for a CPU in the map.
*/
struct cpu_map_entries { struct cpu_map_entries {
__u16 nr; __u16 nr;
__u16 cpu[]; __u16 cpu[];
}; };
struct perf_record_record_cpu_map { /* Bitmap encoding of a perf_cpu_map where bitmap entries are 32-bit. */
struct perf_record_mask_cpu_map32 {
/* Number of mask values. */
__u16 nr;
/* Constant 4. */
__u16 long_size;
/* Bitmap data. */
__u32 mask[];
};
/* Bitmap encoding of a perf_cpu_map where bitmap entries are 64-bit. */
struct perf_record_mask_cpu_map64 {
/* Number of mask values. */
__u16 nr; __u16 nr;
/* Constant 8. */
__u16 long_size; __u16 long_size;
unsigned long mask[]; /* Legacy padding. */
char __pad[4];
/* Bitmap data. */
__u64 mask[];
}; };
struct perf_record_cpu_map_data { /*
* 'struct perf_record_cpu_map_data' is packed as unfortunately an earlier
* version had unaligned data and we wish to retain file format compatibility.
* -irogers
*/
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpacked"
#pragma GCC diagnostic ignored "-Wattributes"
struct __packed perf_record_cpu_map_data {
__u16 type; __u16 type;
char data[]; union {
/* Used when type == PERF_CPU_MAP__CPUS. */
struct cpu_map_entries cpus_data;
/* Used when type == PERF_CPU_MAP__MASK and long_size == 4. */
struct perf_record_mask_cpu_map32 mask32_data;
/* Used when type == PERF_CPU_MAP__MASK and long_size == 8. */
struct perf_record_mask_cpu_map64 mask64_data;
};
}; };
#pragma GCC diagnostic pop
struct perf_record_cpu_map { struct perf_record_cpu_map {
struct perf_event_header header; struct perf_event_header header;
struct perf_record_cpu_map_data data; struct perf_record_cpu_map_data data;
......
...@@ -18,8 +18,10 @@ struct perf_counts_values { ...@@ -18,8 +18,10 @@ struct perf_counts_values {
uint64_t val; uint64_t val;
uint64_t ena; uint64_t ena;
uint64_t run; uint64_t run;
uint64_t id;
uint64_t lost;
}; };
uint64_t values[3]; uint64_t values[5];
}; };
}; };
......
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
#include <stdarg.h> #include <stdarg.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include <linux/perf_event.h> #include <linux/perf_event.h>
#include <linux/kernel.h>
#include <perf/cpumap.h> #include <perf/cpumap.h>
#include <perf/threadmap.h> #include <perf/threadmap.h>
#include <perf/evsel.h> #include <perf/evsel.h>
#include <internal/evsel.h>
#include <internal/tests.h> #include <internal/tests.h>
#include "tests.h" #include "tests.h"
...@@ -189,6 +192,163 @@ static int test_stat_user_read(int event) ...@@ -189,6 +192,163 @@ static int test_stat_user_read(int event)
return 0; return 0;
} }
static int test_stat_read_format_single(struct perf_event_attr *attr, struct perf_thread_map *threads)
{
struct perf_evsel *evsel;
struct perf_counts_values counts;
volatile int count = 0x100000;
int err;
evsel = perf_evsel__new(attr);
__T("failed to create evsel", evsel);
/* skip old kernels that don't support the format */
err = perf_evsel__open(evsel, NULL, threads);
if (err < 0)
return 0;
while (count--) ;
memset(&counts, -1, sizeof(counts));
perf_evsel__read(evsel, 0, 0, &counts);
__T("failed to read value", counts.val);
if (attr->read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
__T("failed to read TOTAL_TIME_ENABLED", counts.ena);
if (attr->read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
__T("failed to read TOTAL_TIME_RUNNING", counts.run);
if (attr->read_format & PERF_FORMAT_ID)
__T("failed to read ID", counts.id);
if (attr->read_format & PERF_FORMAT_LOST)
__T("failed to read LOST", counts.lost == 0);
perf_evsel__close(evsel);
perf_evsel__delete(evsel);
return 0;
}
static int test_stat_read_format_group(struct perf_event_attr *attr, struct perf_thread_map *threads)
{
struct perf_evsel *leader, *member;
struct perf_counts_values counts;
volatile int count = 0x100000;
int err;
attr->read_format |= PERF_FORMAT_GROUP;
leader = perf_evsel__new(attr);
__T("failed to create leader", leader);
attr->read_format &= ~PERF_FORMAT_GROUP;
member = perf_evsel__new(attr);
__T("failed to create member", member);
member->leader = leader;
leader->nr_members = 2;
/* skip old kernels that don't support the format */
err = perf_evsel__open(leader, NULL, threads);
if (err < 0)
return 0;
err = perf_evsel__open(member, NULL, threads);
if (err < 0)
return 0;
while (count--) ;
memset(&counts, -1, sizeof(counts));
perf_evsel__read(leader, 0, 0, &counts);
__T("failed to read leader value", counts.val);
if (attr->read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
__T("failed to read leader TOTAL_TIME_ENABLED", counts.ena);
if (attr->read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
__T("failed to read leader TOTAL_TIME_RUNNING", counts.run);
if (attr->read_format & PERF_FORMAT_ID)
__T("failed to read leader ID", counts.id);
if (attr->read_format & PERF_FORMAT_LOST)
__T("failed to read leader LOST", counts.lost == 0);
memset(&counts, -1, sizeof(counts));
perf_evsel__read(member, 0, 0, &counts);
__T("failed to read member value", counts.val);
if (attr->read_format & PERF_FORMAT_TOTAL_TIME_ENABLED)
__T("failed to read member TOTAL_TIME_ENABLED", counts.ena);
if (attr->read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
__T("failed to read member TOTAL_TIME_RUNNING", counts.run);
if (attr->read_format & PERF_FORMAT_ID)
__T("failed to read member ID", counts.id);
if (attr->read_format & PERF_FORMAT_LOST)
__T("failed to read member LOST", counts.lost == 0);
perf_evsel__close(member);
perf_evsel__close(leader);
perf_evsel__delete(member);
perf_evsel__delete(leader);
return 0;
}
static int test_stat_read_format(void)
{
struct perf_thread_map *threads;
struct perf_event_attr attr = {
.type = PERF_TYPE_SOFTWARE,
.config = PERF_COUNT_SW_TASK_CLOCK,
};
int err, i;
#define FMT(_fmt) PERF_FORMAT_ ## _fmt
#define FMT_TIME (FMT(TOTAL_TIME_ENABLED) | FMT(TOTAL_TIME_RUNNING))
uint64_t test_formats [] = {
0,
FMT_TIME,
FMT(ID),
FMT(LOST),
FMT_TIME | FMT(ID),
FMT_TIME | FMT(LOST),
FMT_TIME | FMT(ID) | FMT(LOST),
FMT(ID) | FMT(LOST),
};
#undef FMT
#undef FMT_TIME
threads = perf_thread_map__new_dummy();
__T("failed to create threads", threads);
perf_thread_map__set_pid(threads, 0, 0);
for (i = 0; i < (int)ARRAY_SIZE(test_formats); i++) {
attr.read_format = test_formats[i];
__T_VERBOSE("testing single read with read_format: %lx\n",
(unsigned long)test_formats[i]);
err = test_stat_read_format_single(&attr, threads);
__T("failed to read single format", err == 0);
}
perf_thread_map__put(threads);
threads = perf_thread_map__new_array(2, NULL);
__T("failed to create threads", threads);
perf_thread_map__set_pid(threads, 0, 0);
perf_thread_map__set_pid(threads, 1, 0);
for (i = 0; i < (int)ARRAY_SIZE(test_formats); i++) {
attr.read_format = test_formats[i];
__T_VERBOSE("testing group read with read_format: %lx\n",
(unsigned long)test_formats[i]);
err = test_stat_read_format_group(&attr, threads);
__T("failed to read group format", err == 0);
}
perf_thread_map__put(threads);
return 0;
}
int test_evsel(int argc, char **argv) int test_evsel(int argc, char **argv)
{ {
__T_START; __T_START;
...@@ -200,6 +360,7 @@ int test_evsel(int argc, char **argv) ...@@ -200,6 +360,7 @@ int test_evsel(int argc, char **argv)
test_stat_thread_enable(); test_stat_thread_enable();
test_stat_user_read(PERF_COUNT_HW_INSTRUCTIONS); test_stat_user_read(PERF_COUNT_HW_INSTRUCTIONS);
test_stat_user_read(PERF_COUNT_HW_CPU_CYCLES); test_stat_user_read(PERF_COUNT_HW_CPU_CYCLES);
test_stat_read_format();
__T_END; __T_END;
return tests_failed == 0 ? 0 : -1; return tests_failed == 0 ? 0 : -1;
......
...@@ -17,21 +17,23 @@ static int process_event_mask(struct perf_tool *tool __maybe_unused, ...@@ -17,21 +17,23 @@ static int process_event_mask(struct perf_tool *tool __maybe_unused,
struct machine *machine __maybe_unused) struct machine *machine __maybe_unused)
{ {
struct perf_record_cpu_map *map_event = &event->cpu_map; struct perf_record_cpu_map *map_event = &event->cpu_map;
struct perf_record_record_cpu_map *mask;
struct perf_record_cpu_map_data *data; struct perf_record_cpu_map_data *data;
struct perf_cpu_map *map; struct perf_cpu_map *map;
int i; int i;
unsigned int long_size;
data = &map_event->data; data = &map_event->data;
TEST_ASSERT_VAL("wrong type", data->type == PERF_CPU_MAP__MASK); TEST_ASSERT_VAL("wrong type", data->type == PERF_CPU_MAP__MASK);
mask = (struct perf_record_record_cpu_map *)data->data; long_size = data->mask32_data.long_size;
TEST_ASSERT_VAL("wrong nr", mask->nr == 1); TEST_ASSERT_VAL("wrong long_size", long_size == 4 || long_size == 8);
TEST_ASSERT_VAL("wrong nr", data->mask32_data.nr == 1);
for (i = 0; i < 20; i++) { for (i = 0; i < 20; i++) {
TEST_ASSERT_VAL("wrong cpu", test_bit(i, mask->mask)); TEST_ASSERT_VAL("wrong cpu", perf_record_cpu_map_data__test_bit(i, data));
} }
map = cpu_map__new_data(data); map = cpu_map__new_data(data);
...@@ -51,7 +53,6 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused, ...@@ -51,7 +53,6 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused,
struct machine *machine __maybe_unused) struct machine *machine __maybe_unused)
{ {
struct perf_record_cpu_map *map_event = &event->cpu_map; struct perf_record_cpu_map *map_event = &event->cpu_map;
struct cpu_map_entries *cpus;
struct perf_record_cpu_map_data *data; struct perf_record_cpu_map_data *data;
struct perf_cpu_map *map; struct perf_cpu_map *map;
...@@ -59,11 +60,9 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused, ...@@ -59,11 +60,9 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused,
TEST_ASSERT_VAL("wrong type", data->type == PERF_CPU_MAP__CPUS); TEST_ASSERT_VAL("wrong type", data->type == PERF_CPU_MAP__CPUS);
cpus = (struct cpu_map_entries *)data->data; TEST_ASSERT_VAL("wrong nr", data->cpus_data.nr == 2);
TEST_ASSERT_VAL("wrong cpu", data->cpus_data.cpu[0] == 1);
TEST_ASSERT_VAL("wrong nr", cpus->nr == 2); TEST_ASSERT_VAL("wrong cpu", data->cpus_data.cpu[1] == 256);
TEST_ASSERT_VAL("wrong cpu", cpus->cpu[0] == 1);
TEST_ASSERT_VAL("wrong cpu", cpus->cpu[1] == 256);
map = cpu_map__new_data(data); map = cpu_map__new_data(data);
TEST_ASSERT_VAL("wrong nr", perf_cpu_map__nr(map) == 2); TEST_ASSERT_VAL("wrong nr", perf_cpu_map__nr(map) == 2);
......
...@@ -86,10 +86,15 @@ static bool samples_same(const struct perf_sample *s1, ...@@ -86,10 +86,15 @@ static bool samples_same(const struct perf_sample *s1,
COMP(read.time_running); COMP(read.time_running);
/* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */ /* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */
if (read_format & PERF_FORMAT_GROUP) { if (read_format & PERF_FORMAT_GROUP) {
for (i = 0; i < s1->read.group.nr; i++) for (i = 0; i < s1->read.group.nr; i++) {
MCOMP(read.group.values[i]); /* FIXME: check values without LOST */
if (read_format & PERF_FORMAT_LOST)
MCOMP(read.group.values[i]);
}
} else { } else {
COMP(read.one.id); COMP(read.one.id);
if (read_format & PERF_FORMAT_LOST)
COMP(read.one.lost);
} }
} }
...@@ -263,7 +268,7 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format) ...@@ -263,7 +268,7 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format)
.data = (void *)aux_data, .data = (void *)aux_data,
}, },
}; };
struct sample_read_value values[] = {{1, 5}, {9, 3}, {2, 7}, {6, 4},}; struct sample_read_value values[] = {{1, 5, 0}, {9, 3, 0}, {2, 7, 0}, {6, 4, 1},};
struct perf_sample sample_out, sample_out_endian; struct perf_sample sample_out, sample_out_endian;
size_t i, sz, bufsz; size_t i, sz, bufsz;
int err, ret = -1; int err, ret = -1;
...@@ -286,6 +291,7 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format) ...@@ -286,6 +291,7 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format)
} else { } else {
sample.read.one.value = 0x08789faeb786aa87ULL; sample.read.one.value = 0x08789faeb786aa87ULL;
sample.read.one.id = 99; sample.read.one.id = 99;
sample.read.one.lost = 1;
} }
sz = perf_event__sample_event_size(&sample, sample_type, read_format); sz = perf_event__sample_event_size(&sample, sample_type, read_format);
...@@ -370,7 +376,7 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format) ...@@ -370,7 +376,7 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format)
*/ */
static int test__sample_parsing(struct test_suite *test __maybe_unused, int subtest __maybe_unused) static int test__sample_parsing(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
{ {
const u64 rf[] = {4, 5, 6, 7, 12, 13, 14, 15}; const u64 rf[] = {4, 5, 6, 7, 12, 13, 14, 15, 20, 21, 22, 28, 29, 30, 31};
u64 sample_type; u64 sample_type;
u64 sample_regs; u64 sample_regs;
size_t i; size_t i;
......
...@@ -14,6 +14,8 @@ struct file; ...@@ -14,6 +14,8 @@ struct file;
struct pid; struct pid;
struct cred; struct cred;
struct socket; struct socket;
struct sock;
struct sk_buff;
#define __sockaddr_check_size(size) \ #define __sockaddr_check_size(size) \
BUILD_BUG_ON(((size) > sizeof(struct __kernel_sockaddr_storage))) BUILD_BUG_ON(((size) > sizeof(struct __kernel_sockaddr_storage)))
...@@ -69,6 +71,9 @@ struct msghdr { ...@@ -69,6 +71,9 @@ struct msghdr {
unsigned int msg_flags; /* flags on received message */ unsigned int msg_flags; /* flags on received message */
__kernel_size_t msg_controllen; /* ancillary data buffer length */ __kernel_size_t msg_controllen; /* ancillary data buffer length */
struct kiocb *msg_iocb; /* ptr to iocb for async requests */ struct kiocb *msg_iocb; /* ptr to iocb for async requests */
struct ubuf_info *msg_ubuf;
int (*sg_from_iter)(struct sock *sk, struct sk_buff *skb,
struct iov_iter *from, size_t length);
}; };
struct user_msghdr { struct user_msghdr {
...@@ -416,10 +421,9 @@ extern int recvmsg_copy_msghdr(struct msghdr *msg, ...@@ -416,10 +421,9 @@ extern int recvmsg_copy_msghdr(struct msghdr *msg,
struct user_msghdr __user *umsg, unsigned flags, struct user_msghdr __user *umsg, unsigned flags,
struct sockaddr __user **uaddr, struct sockaddr __user **uaddr,
struct iovec **iov); struct iovec **iov);
extern int __copy_msghdr_from_user(struct msghdr *kmsg, extern int __copy_msghdr(struct msghdr *kmsg,
struct user_msghdr __user *umsg, struct user_msghdr *umsg,
struct sockaddr __user **save_addr, struct sockaddr __user **save_addr);
struct iovec __user **uiov, size_t *nsegs);
/* helpers which do the actual work for syscalls */ /* helpers which do the actual work for syscalls */
extern int __sys_recvfrom(int fd, void __user *ubuf, size_t size, extern int __sys_recvfrom(int fd, void __user *ubuf, size_t size,
...@@ -428,10 +432,6 @@ extern int __sys_recvfrom(int fd, void __user *ubuf, size_t size, ...@@ -428,10 +432,6 @@ extern int __sys_recvfrom(int fd, void __user *ubuf, size_t size,
extern int __sys_sendto(int fd, void __user *buff, size_t len, extern int __sys_sendto(int fd, void __user *buff, size_t len,
unsigned int flags, struct sockaddr __user *addr, unsigned int flags, struct sockaddr __user *addr,
int addr_len); int addr_len);
extern int __sys_accept4_file(struct file *file, unsigned file_flags,
struct sockaddr __user *upeer_sockaddr,
int __user *upeer_addrlen, int flags,
unsigned long nofile);
extern struct file *do_accept(struct file *file, unsigned file_flags, extern struct file *do_accept(struct file *file, unsigned file_flags,
struct sockaddr __user *upeer_sockaddr, struct sockaddr __user *upeer_sockaddr,
int __user *upeer_addrlen, int flags); int __user *upeer_addrlen, int flags);
......
...@@ -22,54 +22,102 @@ static int max_node_num; ...@@ -22,54 +22,102 @@ static int max_node_num;
*/ */
static int *cpunode_map; static int *cpunode_map;
static struct perf_cpu_map *cpu_map__from_entries(struct cpu_map_entries *cpus) bool perf_record_cpu_map_data__test_bit(int i,
const struct perf_record_cpu_map_data *data)
{
int bit_word32 = i / 32;
__u32 bit_mask32 = 1U << (i & 31);
int bit_word64 = i / 64;
__u64 bit_mask64 = ((__u64)1) << (i & 63);
return (data->mask32_data.long_size == 4)
? (bit_word32 < data->mask32_data.nr) &&
(data->mask32_data.mask[bit_word32] & bit_mask32) != 0
: (bit_word64 < data->mask64_data.nr) &&
(data->mask64_data.mask[bit_word64] & bit_mask64) != 0;
}
/* Read ith mask value from data into the given 64-bit sized bitmap */
static void perf_record_cpu_map_data__read_one_mask(const struct perf_record_cpu_map_data *data,
int i, unsigned long *bitmap)
{
#if __SIZEOF_LONG__ == 8
if (data->mask32_data.long_size == 4)
bitmap[0] = data->mask32_data.mask[i];
else
bitmap[0] = data->mask64_data.mask[i];
#else
if (data->mask32_data.long_size == 4) {
bitmap[0] = data->mask32_data.mask[i];
bitmap[1] = 0;
} else {
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
bitmap[0] = (unsigned long)(data->mask64_data.mask[i] >> 32);
bitmap[1] = (unsigned long)data->mask64_data.mask[i];
#else
bitmap[0] = (unsigned long)data->mask64_data.mask[i];
bitmap[1] = (unsigned long)(data->mask64_data.mask[i] >> 32);
#endif
}
#endif
}
static struct perf_cpu_map *cpu_map__from_entries(const struct perf_record_cpu_map_data *data)
{ {
struct perf_cpu_map *map; struct perf_cpu_map *map;
map = perf_cpu_map__empty_new(cpus->nr); map = perf_cpu_map__empty_new(data->cpus_data.nr);
if (map) { if (map) {
unsigned i; unsigned i;
for (i = 0; i < cpus->nr; i++) { for (i = 0; i < data->cpus_data.nr; i++) {
/* /*
* Special treatment for -1, which is not real cpu number, * Special treatment for -1, which is not real cpu number,
* and we need to use (int) -1 to initialize map[i], * and we need to use (int) -1 to initialize map[i],
* otherwise it would become 65535. * otherwise it would become 65535.
*/ */
if (cpus->cpu[i] == (u16) -1) if (data->cpus_data.cpu[i] == (u16) -1)
map->map[i].cpu = -1; map->map[i].cpu = -1;
else else
map->map[i].cpu = (int) cpus->cpu[i]; map->map[i].cpu = (int) data->cpus_data.cpu[i];
} }
} }
return map; return map;
} }
static struct perf_cpu_map *cpu_map__from_mask(struct perf_record_record_cpu_map *mask) static struct perf_cpu_map *cpu_map__from_mask(const struct perf_record_cpu_map_data *data)
{ {
DECLARE_BITMAP(local_copy, 64);
int weight = 0, mask_nr = data->mask32_data.nr;
struct perf_cpu_map *map; struct perf_cpu_map *map;
int nr, nbits = mask->nr * mask->long_size * BITS_PER_BYTE;
nr = bitmap_weight(mask->mask, nbits); for (int i = 0; i < mask_nr; i++) {
perf_record_cpu_map_data__read_one_mask(data, i, local_copy);
weight += bitmap_weight(local_copy, 64);
}
map = perf_cpu_map__empty_new(weight);
if (!map)
return NULL;
map = perf_cpu_map__empty_new(nr); for (int i = 0, j = 0; i < mask_nr; i++) {
if (map) { int cpus_per_i = (i * data->mask32_data.long_size * BITS_PER_BYTE);
int cpu, i = 0; int cpu;
for_each_set_bit(cpu, mask->mask, nbits) perf_record_cpu_map_data__read_one_mask(data, i, local_copy);
map->map[i++].cpu = cpu; for_each_set_bit(cpu, local_copy, 64)
map->map[j++].cpu = cpu + cpus_per_i;
} }
return map; return map;
} }
struct perf_cpu_map *cpu_map__new_data(struct perf_record_cpu_map_data *data) struct perf_cpu_map *cpu_map__new_data(const struct perf_record_cpu_map_data *data)
{ {
if (data->type == PERF_CPU_MAP__CPUS) if (data->type == PERF_CPU_MAP__CPUS)
return cpu_map__from_entries((struct cpu_map_entries *)data->data); return cpu_map__from_entries(data);
else else
return cpu_map__from_mask((struct perf_record_record_cpu_map *)data->data); return cpu_map__from_mask(data);
} }
size_t cpu_map__fprintf(struct perf_cpu_map *map, FILE *fp) size_t cpu_map__fprintf(struct perf_cpu_map *map, FILE *fp)
......
...@@ -37,9 +37,11 @@ struct cpu_aggr_map { ...@@ -37,9 +37,11 @@ struct cpu_aggr_map {
struct perf_record_cpu_map_data; struct perf_record_cpu_map_data;
bool perf_record_cpu_map_data__test_bit(int i, const struct perf_record_cpu_map_data *data);
struct perf_cpu_map *perf_cpu_map__empty_new(int nr); struct perf_cpu_map *perf_cpu_map__empty_new(int nr);
struct perf_cpu_map *cpu_map__new_data(struct perf_record_cpu_map_data *data); struct perf_cpu_map *cpu_map__new_data(const struct perf_record_cpu_map_data *data);
size_t cpu_map__snprint(struct perf_cpu_map *map, char *buf, size_t size); size_t cpu_map__snprint(struct perf_cpu_map *map, char *buf, size_t size);
size_t cpu_map__snprint_mask(struct perf_cpu_map *map, char *buf, size_t size); size_t cpu_map__snprint_mask(struct perf_cpu_map *map, char *buf, size_t size);
size_t cpu_map__fprintf(struct perf_cpu_map *map, FILE *fp); size_t cpu_map__fprintf(struct perf_cpu_map *map, FILE *fp);
......
...@@ -65,7 +65,8 @@ struct stack_dump { ...@@ -65,7 +65,8 @@ struct stack_dump {
struct sample_read_value { struct sample_read_value {
u64 value; u64 value;
u64 id; u64 id; /* only if PERF_FORMAT_ID */
u64 lost; /* only if PERF_FORMAT_LOST */
}; };
struct sample_read { struct sample_read {
...@@ -80,6 +81,24 @@ struct sample_read { ...@@ -80,6 +81,24 @@ struct sample_read {
}; };
}; };
static inline size_t sample_read_value_size(u64 read_format)
{
/* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */
if (read_format & PERF_FORMAT_LOST)
return sizeof(struct sample_read_value);
else
return offsetof(struct sample_read_value, lost);
}
static inline struct sample_read_value *
next_sample_read_value(struct sample_read_value *v, u64 read_format)
{
return (void *)v + sample_read_value_size(read_format);
}
#define sample_read_group__for_each(v, nr, rf) \
for (int __i = 0; __i < (int)nr; v = next_sample_read_value(v, rf), __i++)
struct ip_callchain { struct ip_callchain {
u64 nr; u64 nr;
u64 ips[]; u64 ips[];
...@@ -463,10 +482,6 @@ size_t perf_event__fprintf(union perf_event *event, struct machine *machine, FIL ...@@ -463,10 +482,6 @@ size_t perf_event__fprintf(union perf_event *event, struct machine *machine, FIL
int kallsyms__get_function_start(const char *kallsyms_filename, int kallsyms__get_function_start(const char *kallsyms_filename,
const char *symbol_name, u64 *addr); const char *symbol_name, u64 *addr);
void *cpu_map_data__alloc(struct perf_cpu_map *map, size_t *size, u16 *type, int *max);
void cpu_map_data__synthesize(struct perf_record_cpu_map_data *data, struct perf_cpu_map *map,
u16 type, int max);
void event_attr_init(struct perf_event_attr *attr); void event_attr_init(struct perf_event_attr *attr);
int perf_event_paranoid(void); int perf_event_paranoid(void);
......
...@@ -1541,7 +1541,7 @@ static int evsel__read_one(struct evsel *evsel, int cpu_map_idx, int thread) ...@@ -1541,7 +1541,7 @@ static int evsel__read_one(struct evsel *evsel, int cpu_map_idx, int thread)
} }
static void evsel__set_count(struct evsel *counter, int cpu_map_idx, int thread, static void evsel__set_count(struct evsel *counter, int cpu_map_idx, int thread,
u64 val, u64 ena, u64 run) u64 val, u64 ena, u64 run, u64 lost)
{ {
struct perf_counts_values *count; struct perf_counts_values *count;
...@@ -1550,6 +1550,7 @@ static void evsel__set_count(struct evsel *counter, int cpu_map_idx, int thread, ...@@ -1550,6 +1550,7 @@ static void evsel__set_count(struct evsel *counter, int cpu_map_idx, int thread,
count->val = val; count->val = val;
count->ena = ena; count->ena = ena;
count->run = run; count->run = run;
count->lost = lost;
perf_counts__set_loaded(counter->counts, cpu_map_idx, thread, true); perf_counts__set_loaded(counter->counts, cpu_map_idx, thread, true);
} }
...@@ -1558,7 +1559,7 @@ static int evsel__process_group_data(struct evsel *leader, int cpu_map_idx, int ...@@ -1558,7 +1559,7 @@ static int evsel__process_group_data(struct evsel *leader, int cpu_map_idx, int
{ {
u64 read_format = leader->core.attr.read_format; u64 read_format = leader->core.attr.read_format;
struct sample_read_value *v; struct sample_read_value *v;
u64 nr, ena = 0, run = 0, i; u64 nr, ena = 0, run = 0, lost = 0;
nr = *data++; nr = *data++;
...@@ -1571,18 +1572,18 @@ static int evsel__process_group_data(struct evsel *leader, int cpu_map_idx, int ...@@ -1571,18 +1572,18 @@ static int evsel__process_group_data(struct evsel *leader, int cpu_map_idx, int
if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING)
run = *data++; run = *data++;
v = (struct sample_read_value *) data; v = (void *)data;
sample_read_group__for_each(v, nr, read_format) {
evsel__set_count(leader, cpu_map_idx, thread, v[0].value, ena, run);
for (i = 1; i < nr; i++) {
struct evsel *counter; struct evsel *counter;
counter = evlist__id2evsel(leader->evlist, v[i].id); counter = evlist__id2evsel(leader->evlist, v->id);
if (!counter) if (!counter)
return -EINVAL; return -EINVAL;
evsel__set_count(counter, cpu_map_idx, thread, v[i].value, ena, run); if (read_format & PERF_FORMAT_LOST)
lost = v->lost;
evsel__set_count(counter, cpu_map_idx, thread, v->value, ena, run, lost);
} }
return 0; return 0;
...@@ -2475,8 +2476,8 @@ int evsel__parse_sample(struct evsel *evsel, union perf_event *event, ...@@ -2475,8 +2476,8 @@ int evsel__parse_sample(struct evsel *evsel, union perf_event *event,
if (data->read.group.nr > max_group_nr) if (data->read.group.nr > max_group_nr)
return -EFAULT; return -EFAULT;
sz = data->read.group.nr *
sizeof(struct sample_read_value); sz = data->read.group.nr * sample_read_value_size(read_format);
OVERFLOW_CHECK(array, sz, max_size); OVERFLOW_CHECK(array, sz, max_size);
data->read.group.values = data->read.group.values =
(struct sample_read_value *)array; (struct sample_read_value *)array;
...@@ -2485,6 +2486,12 @@ int evsel__parse_sample(struct evsel *evsel, union perf_event *event, ...@@ -2485,6 +2486,12 @@ int evsel__parse_sample(struct evsel *evsel, union perf_event *event,
OVERFLOW_CHECK_u64(array); OVERFLOW_CHECK_u64(array);
data->read.one.id = *array; data->read.one.id = *array;
array++; array++;
if (read_format & PERF_FORMAT_LOST) {
OVERFLOW_CHECK_u64(array);
data->read.one.lost = *array;
array++;
}
} }
} }
......
...@@ -642,15 +642,19 @@ static PyObject *python_process_brstacksym(struct perf_sample *sample, ...@@ -642,15 +642,19 @@ static PyObject *python_process_brstacksym(struct perf_sample *sample,
return pylist; return pylist;
} }
static PyObject *get_sample_value_as_tuple(struct sample_read_value *value) static PyObject *get_sample_value_as_tuple(struct sample_read_value *value,
u64 read_format)
{ {
PyObject *t; PyObject *t;
t = PyTuple_New(2); t = PyTuple_New(3);
if (!t) if (!t)
Py_FatalError("couldn't create Python tuple"); Py_FatalError("couldn't create Python tuple");
PyTuple_SetItem(t, 0, PyLong_FromUnsignedLongLong(value->id)); PyTuple_SetItem(t, 0, PyLong_FromUnsignedLongLong(value->id));
PyTuple_SetItem(t, 1, PyLong_FromUnsignedLongLong(value->value)); PyTuple_SetItem(t, 1, PyLong_FromUnsignedLongLong(value->value));
if (read_format & PERF_FORMAT_LOST)
PyTuple_SetItem(t, 2, PyLong_FromUnsignedLongLong(value->lost));
return t; return t;
} }
...@@ -681,12 +685,17 @@ static void set_sample_read_in_dict(PyObject *dict_sample, ...@@ -681,12 +685,17 @@ static void set_sample_read_in_dict(PyObject *dict_sample,
Py_FatalError("couldn't create Python list"); Py_FatalError("couldn't create Python list");
if (read_format & PERF_FORMAT_GROUP) { if (read_format & PERF_FORMAT_GROUP) {
for (i = 0; i < sample->read.group.nr; i++) { struct sample_read_value *v = sample->read.group.values;
PyObject *t = get_sample_value_as_tuple(&sample->read.group.values[i]);
i = 0;
sample_read_group__for_each(v, sample->read.group.nr, read_format) {
PyObject *t = get_sample_value_as_tuple(v, read_format);
PyList_SET_ITEM(values, i, t); PyList_SET_ITEM(values, i, t);
i++;
} }
} else { } else {
PyObject *t = get_sample_value_as_tuple(&sample->read.one); PyObject *t = get_sample_value_as_tuple(&sample->read.one,
read_format);
PyList_SET_ITEM(values, 0, t); PyList_SET_ITEM(values, 0, t);
} }
pydict_set_item_string_decref(dict_sample, "values", values); pydict_set_item_string_decref(dict_sample, "values", values);
......
...@@ -916,30 +916,30 @@ static void perf_event__cpu_map_swap(union perf_event *event, ...@@ -916,30 +916,30 @@ static void perf_event__cpu_map_swap(union perf_event *event,
bool sample_id_all __maybe_unused) bool sample_id_all __maybe_unused)
{ {
struct perf_record_cpu_map_data *data = &event->cpu_map.data; struct perf_record_cpu_map_data *data = &event->cpu_map.data;
struct cpu_map_entries *cpus;
struct perf_record_record_cpu_map *mask;
unsigned i;
data->type = bswap_16(data->type); data->type = bswap_16(data->type);
switch (data->type) { switch (data->type) {
case PERF_CPU_MAP__CPUS: case PERF_CPU_MAP__CPUS:
cpus = (struct cpu_map_entries *)data->data; data->cpus_data.nr = bswap_16(data->cpus_data.nr);
cpus->nr = bswap_16(cpus->nr);
for (i = 0; i < cpus->nr; i++) for (unsigned i = 0; i < data->cpus_data.nr; i++)
cpus->cpu[i] = bswap_16(cpus->cpu[i]); data->cpus_data.cpu[i] = bswap_16(data->cpus_data.cpu[i]);
break; break;
case PERF_CPU_MAP__MASK: case PERF_CPU_MAP__MASK:
mask = (struct perf_record_record_cpu_map *)data->data; data->mask32_data.long_size = bswap_16(data->mask32_data.long_size);
mask->nr = bswap_16(mask->nr);
mask->long_size = bswap_16(mask->long_size);
switch (mask->long_size) { switch (data->mask32_data.long_size) {
case 4: mem_bswap_32(&mask->mask, mask->nr); break; case 4:
case 8: mem_bswap_64(&mask->mask, mask->nr); break; data->mask32_data.nr = bswap_16(data->mask32_data.nr);
for (unsigned i = 0; i < data->mask32_data.nr; i++)
data->mask32_data.mask[i] = bswap_32(data->mask32_data.mask[i]);
break;
case 8:
data->mask64_data.nr = bswap_16(data->mask64_data.nr);
for (unsigned i = 0; i < data->mask64_data.nr; i++)
data->mask64_data.mask[i] = bswap_64(data->mask64_data.mask[i]);
break;
default: default:
pr_err("cpu_map swap: unsupported long size\n"); pr_err("cpu_map swap: unsupported long size\n");
} }
...@@ -1283,21 +1283,25 @@ static void sample_read__printf(struct perf_sample *sample, u64 read_format) ...@@ -1283,21 +1283,25 @@ static void sample_read__printf(struct perf_sample *sample, u64 read_format)
sample->read.time_running); sample->read.time_running);
if (read_format & PERF_FORMAT_GROUP) { if (read_format & PERF_FORMAT_GROUP) {
u64 i; struct sample_read_value *value = sample->read.group.values;
printf(".... group nr %" PRIu64 "\n", sample->read.group.nr); printf(".... group nr %" PRIu64 "\n", sample->read.group.nr);
for (i = 0; i < sample->read.group.nr; i++) { sample_read_group__for_each(value, sample->read.group.nr, read_format) {
struct sample_read_value *value;
value = &sample->read.group.values[i];
printf("..... id %016" PRIx64 printf("..... id %016" PRIx64
", value %016" PRIx64 "\n", ", value %016" PRIx64,
value->id, value->value); value->id, value->value);
if (read_format & PERF_FORMAT_LOST)
printf(", lost %" PRIu64, value->lost);
printf("\n");
} }
} else } else {
printf("..... id %016" PRIx64 ", value %016" PRIx64 "\n", printf("..... id %016" PRIx64 ", value %016" PRIx64,
sample->read.one.id, sample->read.one.value); sample->read.one.id, sample->read.one.value);
if (read_format & PERF_FORMAT_LOST)
printf(", lost %" PRIu64, sample->read.one.lost);
printf("\n");
}
} }
static void dump_event(struct evlist *evlist, union perf_event *event, static void dump_event(struct evlist *evlist, union perf_event *event,
...@@ -1411,6 +1415,9 @@ static void dump_read(struct evsel *evsel, union perf_event *event) ...@@ -1411,6 +1415,9 @@ static void dump_read(struct evsel *evsel, union perf_event *event)
if (read_format & PERF_FORMAT_ID) if (read_format & PERF_FORMAT_ID)
printf("... id : %" PRI_lu64 "\n", read_event->id); printf("... id : %" PRI_lu64 "\n", read_event->id);
if (read_format & PERF_FORMAT_LOST)
printf("... lost : %" PRI_lu64 "\n", read_event->lost);
} }
static struct machine *machines__find_for_cpumode(struct machines *machines, static struct machine *machines__find_for_cpumode(struct machines *machines,
...@@ -1479,14 +1486,14 @@ static int deliver_sample_group(struct evlist *evlist, ...@@ -1479,14 +1486,14 @@ static int deliver_sample_group(struct evlist *evlist,
struct perf_tool *tool, struct perf_tool *tool,
union perf_event *event, union perf_event *event,
struct perf_sample *sample, struct perf_sample *sample,
struct machine *machine) struct machine *machine,
u64 read_format)
{ {
int ret = -EINVAL; int ret = -EINVAL;
u64 i; struct sample_read_value *v = sample->read.group.values;
for (i = 0; i < sample->read.group.nr; i++) { sample_read_group__for_each(v, sample->read.group.nr, read_format) {
ret = deliver_sample_value(evlist, tool, event, sample, ret = deliver_sample_value(evlist, tool, event, sample, v,
&sample->read.group.values[i],
machine); machine);
if (ret) if (ret)
break; break;
...@@ -1510,7 +1517,7 @@ static int evlist__deliver_sample(struct evlist *evlist, struct perf_tool *tool, ...@@ -1510,7 +1517,7 @@ static int evlist__deliver_sample(struct evlist *evlist, struct perf_tool *tool,
/* For PERF_SAMPLE_READ we have either single or group mode. */ /* For PERF_SAMPLE_READ we have either single or group mode. */
if (read_format & PERF_FORMAT_GROUP) if (read_format & PERF_FORMAT_GROUP)
return deliver_sample_group(evlist, tool, event, sample, return deliver_sample_group(evlist, tool, event, sample,
machine); machine, read_format);
else else
return deliver_sample_value(evlist, tool, event, sample, return deliver_sample_value(evlist, tool, event, sample,
&sample->read.one, machine); &sample->read.one, machine);
......
...@@ -1184,52 +1184,48 @@ int perf_event__synthesize_thread_map2(struct perf_tool *tool, ...@@ -1184,52 +1184,48 @@ int perf_event__synthesize_thread_map2(struct perf_tool *tool,
return err; return err;
} }
static void synthesize_cpus(struct cpu_map_entries *cpus, static void synthesize_cpus(struct perf_record_cpu_map_data *data,
struct perf_cpu_map *map) const struct perf_cpu_map *map)
{ {
int i, map_nr = perf_cpu_map__nr(map); int i, map_nr = perf_cpu_map__nr(map);
cpus->nr = map_nr; data->cpus_data.nr = map_nr;
for (i = 0; i < map_nr; i++) for (i = 0; i < map_nr; i++)
cpus->cpu[i] = perf_cpu_map__cpu(map, i).cpu; data->cpus_data.cpu[i] = perf_cpu_map__cpu(map, i).cpu;
} }
static void synthesize_mask(struct perf_record_record_cpu_map *mask, static void synthesize_mask(struct perf_record_cpu_map_data *data,
struct perf_cpu_map *map, int max) const struct perf_cpu_map *map, int max)
{ {
int i; int idx;
struct perf_cpu cpu;
/* Due to padding, the 4bytes per entry mask variant is always smaller. */
data->mask32_data.nr = BITS_TO_U32(max);
data->mask32_data.long_size = 4;
mask->nr = BITS_TO_LONGS(max); perf_cpu_map__for_each_cpu(cpu, idx, map) {
mask->long_size = sizeof(long); int bit_word = cpu.cpu / 32;
__u32 bit_mask = 1U << (cpu.cpu & 31);
for (i = 0; i < perf_cpu_map__nr(map); i++) data->mask32_data.mask[bit_word] |= bit_mask;
set_bit(perf_cpu_map__cpu(map, i).cpu, mask->mask); }
} }
static size_t cpus_size(struct perf_cpu_map *map) static size_t cpus_size(const struct perf_cpu_map *map)
{ {
return sizeof(struct cpu_map_entries) + perf_cpu_map__nr(map) * sizeof(u16); return sizeof(struct cpu_map_entries) + perf_cpu_map__nr(map) * sizeof(u16);
} }
static size_t mask_size(struct perf_cpu_map *map, int *max) static size_t mask_size(const struct perf_cpu_map *map, int *max)
{ {
int i; *max = perf_cpu_map__max(map).cpu;
return sizeof(struct perf_record_mask_cpu_map32) + BITS_TO_U32(*max) * sizeof(__u32);
*max = 0;
for (i = 0; i < perf_cpu_map__nr(map); i++) {
/* bit position of the cpu is + 1 */
int bit = perf_cpu_map__cpu(map, i).cpu + 1;
if (bit > *max)
*max = bit;
}
return sizeof(struct perf_record_record_cpu_map) + BITS_TO_LONGS(*max) * sizeof(long);
} }
void *cpu_map_data__alloc(struct perf_cpu_map *map, size_t *size, u16 *type, int *max) static void *cpu_map_data__alloc(const struct perf_cpu_map *map, size_t *size,
u16 *type, int *max)
{ {
size_t size_cpus, size_mask; size_t size_cpus, size_mask;
bool is_dummy = perf_cpu_map__empty(map); bool is_dummy = perf_cpu_map__empty(map);
...@@ -1258,30 +1254,31 @@ void *cpu_map_data__alloc(struct perf_cpu_map *map, size_t *size, u16 *type, int ...@@ -1258,30 +1254,31 @@ void *cpu_map_data__alloc(struct perf_cpu_map *map, size_t *size, u16 *type, int
*type = PERF_CPU_MAP__MASK; *type = PERF_CPU_MAP__MASK;
} }
*size += sizeof(struct perf_record_cpu_map_data); *size += sizeof(__u16); /* For perf_record_cpu_map_data.type. */
*size = PERF_ALIGN(*size, sizeof(u64)); *size = PERF_ALIGN(*size, sizeof(u64));
return zalloc(*size); return zalloc(*size);
} }
void cpu_map_data__synthesize(struct perf_record_cpu_map_data *data, struct perf_cpu_map *map, static void cpu_map_data__synthesize(struct perf_record_cpu_map_data *data,
u16 type, int max) const struct perf_cpu_map *map,
u16 type, int max)
{ {
data->type = type; data->type = type;
switch (type) { switch (type) {
case PERF_CPU_MAP__CPUS: case PERF_CPU_MAP__CPUS:
synthesize_cpus((struct cpu_map_entries *) data->data, map); synthesize_cpus(data, map);
break; break;
case PERF_CPU_MAP__MASK: case PERF_CPU_MAP__MASK:
synthesize_mask((struct perf_record_record_cpu_map *)data->data, map, max); synthesize_mask(data, map, max);
default: default:
break; break;
} }
} }
static struct perf_record_cpu_map *cpu_map_event__new(struct perf_cpu_map *map) static struct perf_record_cpu_map *cpu_map_event__new(const struct perf_cpu_map *map)
{ {
size_t size = sizeof(struct perf_record_cpu_map); size_t size = sizeof(struct perf_event_header);
struct perf_record_cpu_map *event; struct perf_record_cpu_map *event;
int max; int max;
u16 type; u16 type;
...@@ -1299,7 +1296,7 @@ static struct perf_record_cpu_map *cpu_map_event__new(struct perf_cpu_map *map) ...@@ -1299,7 +1296,7 @@ static struct perf_record_cpu_map *cpu_map_event__new(struct perf_cpu_map *map)
} }
int perf_event__synthesize_cpu_map(struct perf_tool *tool, int perf_event__synthesize_cpu_map(struct perf_tool *tool,
struct perf_cpu_map *map, const struct perf_cpu_map *map,
perf_event__handler_t process, perf_event__handler_t process,
struct machine *machine) struct machine *machine)
{ {
...@@ -1432,11 +1429,12 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type, ...@@ -1432,11 +1429,12 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
result += sizeof(u64); result += sizeof(u64);
/* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */ /* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */
if (read_format & PERF_FORMAT_GROUP) { if (read_format & PERF_FORMAT_GROUP) {
sz = sample->read.group.nr * sz = sample_read_value_size(read_format);
sizeof(struct sample_read_value); result += sz * sample->read.group.nr;
result += sz;
} else { } else {
result += sizeof(u64); result += sizeof(u64);
if (read_format & PERF_FORMAT_LOST)
result += sizeof(u64);
} }
} }
...@@ -1521,6 +1519,20 @@ void __weak arch_perf_synthesize_sample_weight(const struct perf_sample *data, ...@@ -1521,6 +1519,20 @@ void __weak arch_perf_synthesize_sample_weight(const struct perf_sample *data,
*array = data->weight; *array = data->weight;
} }
static __u64 *copy_read_group_values(__u64 *array, __u64 read_format,
const struct perf_sample *sample)
{
size_t sz = sample_read_value_size(read_format);
struct sample_read_value *v = sample->read.group.values;
sample_read_group__for_each(v, sample->read.group.nr, read_format) {
/* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */
memcpy(array, v, sz);
array = (void *)array + sz;
}
return array;
}
int perf_event__synthesize_sample(union perf_event *event, u64 type, u64 read_format, int perf_event__synthesize_sample(union perf_event *event, u64 type, u64 read_format,
const struct perf_sample *sample) const struct perf_sample *sample)
{ {
...@@ -1602,13 +1614,16 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, u64 read_fo ...@@ -1602,13 +1614,16 @@ int perf_event__synthesize_sample(union perf_event *event, u64 type, u64 read_fo
/* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */ /* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */
if (read_format & PERF_FORMAT_GROUP) { if (read_format & PERF_FORMAT_GROUP) {
sz = sample->read.group.nr * array = copy_read_group_values(array, read_format,
sizeof(struct sample_read_value); sample);
memcpy(array, sample->read.group.values, sz);
array = (void *)array + sz;
} else { } else {
*array = sample->read.one.id; *array = sample->read.one.id;
array++; array++;
if (read_format & PERF_FORMAT_LOST) {
*array = sample->read.one.lost;
array++;
}
} }
} }
......
...@@ -46,7 +46,7 @@ typedef int (*perf_event__handler_t)(struct perf_tool *tool, union perf_event *e ...@@ -46,7 +46,7 @@ typedef int (*perf_event__handler_t)(struct perf_tool *tool, union perf_event *e
int perf_event__synthesize_attrs(struct perf_tool *tool, struct evlist *evlist, perf_event__handler_t process); int perf_event__synthesize_attrs(struct perf_tool *tool, struct evlist *evlist, perf_event__handler_t process);
int perf_event__synthesize_attr(struct perf_tool *tool, struct perf_event_attr *attr, u32 ids, u64 *id, perf_event__handler_t process); int perf_event__synthesize_attr(struct perf_tool *tool, struct perf_event_attr *attr, u32 ids, u64 *id, perf_event__handler_t process);
int perf_event__synthesize_build_id(struct perf_tool *tool, struct dso *pos, u16 misc, perf_event__handler_t process, struct machine *machine); int perf_event__synthesize_build_id(struct perf_tool *tool, struct dso *pos, u16 misc, perf_event__handler_t process, struct machine *machine);
int perf_event__synthesize_cpu_map(struct perf_tool *tool, struct perf_cpu_map *cpus, perf_event__handler_t process, struct machine *machine); int perf_event__synthesize_cpu_map(struct perf_tool *tool, const struct perf_cpu_map *cpus, perf_event__handler_t process, struct machine *machine);
int perf_event__synthesize_event_update_cpus(struct perf_tool *tool, struct evsel *evsel, perf_event__handler_t process); int perf_event__synthesize_event_update_cpus(struct perf_tool *tool, struct evsel *evsel, perf_event__handler_t process);
int perf_event__synthesize_event_update_name(struct perf_tool *tool, struct evsel *evsel, perf_event__handler_t process); int perf_event__synthesize_event_update_name(struct perf_tool *tool, struct evsel *evsel, perf_event__handler_t process);
int perf_event__synthesize_event_update_scale(struct perf_tool *tool, struct evsel *evsel, perf_event__handler_t process); int perf_event__synthesize_event_update_scale(struct perf_tool *tool, struct evsel *evsel, perf_event__handler_t process);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment