perf tools fixes for v6.0: 1st batch
- 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. Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> -----BEGIN PGP SIGNATURE----- iHUEABYKAB0WIQR2GiIUctdOfX2qHhGyPKLppCJ+JwUCYv/jZAAKCRCyPKLppCJ+ J5ZWAP9P7qMcKppgzYqnHU7TX2tJoT7WbYpaf2lp0TkIpynKdAD9E+9FjbAnQznN 90DIIH/BljChgiUTkMxHaAl789XL1gU= =UXWB -----END PGP SIGNATURE----- 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()
This commit is contained in:
commit
16b3d851c0
|
@ -74,6 +74,7 @@ struct kvm_s390_io_adapter_req {
|
|||
#define KVM_S390_VM_CRYPTO 2
|
||||
#define KVM_S390_VM_CPU_MODEL 3
|
||||
#define KVM_S390_VM_MIGRATION 4
|
||||
#define KVM_S390_VM_CPU_TOPOLOGY 5
|
||||
|
||||
/* kvm attributes for mem_ctrl */
|
||||
#define KVM_S390_VM_MEM_ENABLE_CMMA 0
|
||||
|
|
|
@ -219,7 +219,7 @@
|
|||
#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_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_IBRS_ENHANCED ( 7*32+30) /* Enhanced IBRS */
|
||||
#define X86_FEATURE_MSR_IA32_FEAT_CTL ( 7*32+31) /* "" MSR IA32_FEAT_CTL configured */
|
||||
|
@ -303,7 +303,7 @@
|
|||
#define X86_FEATURE_RETHUNK (11*32+14) /* "" Use REturn THUNK */
|
||||
#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_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 */
|
||||
#define X86_FEATURE_AVX_VNNI (12*32+ 4) /* AVX VNNI instructions */
|
||||
|
@ -354,6 +354,7 @@
|
|||
#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_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_SVME_ADDR_CHK (15*32+28) /* "" SVME addr check */
|
||||
|
||||
|
@ -457,5 +458,6 @@
|
|||
#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_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 */
|
||||
|
|
|
@ -235,6 +235,12 @@
|
|||
#define PERF_CAP_PT_IDX 16
|
||||
|
||||
#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 RTIT_CTL_TRACEEN BIT(0)
|
||||
|
@ -392,6 +398,7 @@
|
|||
#define MSR_TURBO_ACTIVATION_RATIO 0x0000064C
|
||||
|
||||
#define MSR_PLATFORM_ENERGY_STATUS 0x0000064D
|
||||
#define MSR_SECONDARY_TURBO_RATIO_LIMIT 0x00000650
|
||||
|
||||
#define MSR_PKG_WEIGHTED_CORE_C0_RES 0x00000658
|
||||
#define MSR_PKG_ANY_CORE_C0_RES 0x00000659
|
||||
|
@ -1022,6 +1029,7 @@
|
|||
#define MSR_IA32_VMX_TRUE_EXIT_CTLS 0x0000048f
|
||||
#define MSR_IA32_VMX_TRUE_ENTRY_CTLS 0x00000490
|
||||
#define MSR_IA32_VMX_VMFUNC 0x00000491
|
||||
#define MSR_IA32_VMX_PROCBASED_CTLS3 0x00000492
|
||||
|
||||
/* VMX_BASIC bits and bitmasks */
|
||||
#define VMX_BASIC_VMCS_SIZE_SHIFT 32
|
||||
|
|
|
@ -306,7 +306,8 @@ struct kvm_pit_state {
|
|||
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_channel_state channels[3];
|
||||
|
@ -325,6 +326,7 @@ struct kvm_reinject_control {
|
|||
#define KVM_VCPUEVENT_VALID_SHADOW 0x00000004
|
||||
#define KVM_VCPUEVENT_VALID_SMM 0x00000008
|
||||
#define KVM_VCPUEVENT_VALID_PAYLOAD 0x00000010
|
||||
#define KVM_VCPUEVENT_VALID_TRIPLE_FAULT 0x00000020
|
||||
|
||||
/* Interrupt shadow states */
|
||||
#define KVM_X86_SHADOW_INT_MOV_SS 0x01
|
||||
|
@ -359,7 +361,10 @@ struct kvm_vcpu_events {
|
|||
__u8 smm_inside_nmi;
|
||||
__u8 latched_init;
|
||||
} smi;
|
||||
__u8 reserved[27];
|
||||
struct {
|
||||
__u8 pending;
|
||||
} triple_fault;
|
||||
__u8 reserved[26];
|
||||
__u8 exception_has_payload;
|
||||
__u64 exception_payload;
|
||||
};
|
||||
|
@ -434,6 +439,7 @@ struct kvm_sync_regs {
|
|||
#define KVM_X86_QUIRK_OUT_7E_INC_RIP (1 << 3)
|
||||
#define KVM_X86_QUIRK_MISC_ENABLE_NO_MWAIT (1 << 4)
|
||||
#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_SVM 1
|
||||
|
|
|
@ -91,6 +91,7 @@
|
|||
#define EXIT_REASON_UMWAIT 67
|
||||
#define EXIT_REASON_TPAUSE 68
|
||||
#define EXIT_REASON_BUS_LOCK 74
|
||||
#define EXIT_REASON_NOTIFY 75
|
||||
|
||||
#define VMX_EXIT_REASONS \
|
||||
{ EXIT_REASON_EXCEPTION_NMI, "EXCEPTION_NMI" }, \
|
||||
|
@ -153,7 +154,8 @@
|
|||
{ EXIT_REASON_XRSTORS, "XRSTORS" }, \
|
||||
{ EXIT_REASON_UMWAIT, "UMWAIT" }, \
|
||||
{ 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 \
|
||||
{ VMX_EXIT_REASONS_FAILED_VMENTRY, "FAILED_VMENTRY" }
|
||||
|
|
|
@ -751,14 +751,27 @@ typedef struct drm_i915_irq_wait {
|
|||
|
||||
/* Must be kept compact -- no holes and well documented */
|
||||
|
||||
typedef struct drm_i915_getparam {
|
||||
/**
|
||||
* struct drm_i915_getparam - Driver parameter query structure.
|
||||
*/
|
||||
struct drm_i915_getparam {
|
||||
/** @param: Driver parameter to query. */
|
||||
__s32 param;
|
||||
/*
|
||||
|
||||
/**
|
||||
* @value: Address of memory where queried value should be put.
|
||||
*
|
||||
* WARNING: Using pointers instead of fixed-size u64 means we need to write
|
||||
* compat32 code. Don't repeat this mistake.
|
||||
*/
|
||||
int __user *value;
|
||||
} drm_i915_getparam_t;
|
||||
};
|
||||
|
||||
/**
|
||||
* typedef drm_i915_getparam_t - Driver parameter query structure.
|
||||
* See struct drm_i915_getparam.
|
||||
*/
|
||||
typedef struct drm_i915_getparam drm_i915_getparam_t;
|
||||
|
||||
/* Ioctl to set kernel params:
|
||||
*/
|
||||
|
@ -1239,76 +1252,119 @@ struct drm_i915_gem_exec_object2 {
|
|||
__u64 rsvd2;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_i915_gem_exec_fence - An input or output fence for the execbuf
|
||||
* ioctl.
|
||||
*
|
||||
* The request will wait for input fence to signal before submission.
|
||||
*
|
||||
* The returned output fence will be signaled after the completion of the
|
||||
* request.
|
||||
*/
|
||||
struct drm_i915_gem_exec_fence {
|
||||
/**
|
||||
* User's handle for a drm_syncobj to wait on or signal.
|
||||
*/
|
||||
/** @handle: User's handle for a drm_syncobj to wait on or signal. */
|
||||
__u32 handle;
|
||||
|
||||
/**
|
||||
* @flags: Supported flags are:
|
||||
*
|
||||
* I915_EXEC_FENCE_WAIT:
|
||||
* Wait for the input fence before request submission.
|
||||
*
|
||||
* I915_EXEC_FENCE_SIGNAL:
|
||||
* Return request completion fence as output
|
||||
*/
|
||||
__u32 flags;
|
||||
#define I915_EXEC_FENCE_WAIT (1<<0)
|
||||
#define I915_EXEC_FENCE_SIGNAL (1<<1)
|
||||
#define __I915_EXEC_FENCE_UNKNOWN_FLAGS (-(I915_EXEC_FENCE_SIGNAL << 1))
|
||||
__u32 flags;
|
||||
};
|
||||
|
||||
/*
|
||||
* See drm_i915_gem_execbuffer_ext_timeline_fences.
|
||||
*/
|
||||
#define DRM_I915_GEM_EXECBUFFER_EXT_TIMELINE_FENCES 0
|
||||
|
||||
/*
|
||||
/**
|
||||
* struct drm_i915_gem_execbuffer_ext_timeline_fences - Timeline fences
|
||||
* for execbuf ioctl.
|
||||
*
|
||||
* This structure describes an array of drm_syncobj and associated points for
|
||||
* timeline variants of drm_syncobj. It is invalid to append this structure to
|
||||
* the execbuf if I915_EXEC_FENCE_ARRAY is set.
|
||||
*/
|
||||
struct drm_i915_gem_execbuffer_ext_timeline_fences {
|
||||
#define DRM_I915_GEM_EXECBUFFER_EXT_TIMELINE_FENCES 0
|
||||
/** @base: Extension link. See struct i915_user_extension. */
|
||||
struct i915_user_extension base;
|
||||
|
||||
/**
|
||||
* Number of element in the handles_ptr & value_ptr arrays.
|
||||
* @fence_count: Number of elements in the @handles_ptr & @value_ptr
|
||||
* arrays.
|
||||
*/
|
||||
__u64 fence_count;
|
||||
|
||||
/**
|
||||
* Pointer to an array of struct drm_i915_gem_exec_fence of length
|
||||
* fence_count.
|
||||
* @handles_ptr: Pointer to an array of struct drm_i915_gem_exec_fence
|
||||
* of length @fence_count.
|
||||
*/
|
||||
__u64 handles_ptr;
|
||||
|
||||
/**
|
||||
* Pointer to an array of u64 values of length fence_count. Values
|
||||
* must be 0 for a binary drm_syncobj. A Value of 0 for a timeline
|
||||
* drm_syncobj is invalid as it turns a drm_syncobj into a binary one.
|
||||
* @values_ptr: Pointer to an array of u64 values of length
|
||||
* @fence_count.
|
||||
* Values must be 0 for a binary drm_syncobj. A Value of 0 for a
|
||||
* timeline drm_syncobj is invalid as it turns a drm_syncobj into a
|
||||
* binary one.
|
||||
*/
|
||||
__u64 values_ptr;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_i915_gem_execbuffer2 - Structure for DRM_I915_GEM_EXECBUFFER2
|
||||
* ioctl.
|
||||
*/
|
||||
struct drm_i915_gem_execbuffer2 {
|
||||
/**
|
||||
* List of gem_exec_object2 structs
|
||||
*/
|
||||
/** @buffers_ptr: Pointer to a list of gem_exec_object2 structs */
|
||||
__u64 buffers_ptr;
|
||||
|
||||
/** @buffer_count: Number of elements in @buffers_ptr array */
|
||||
__u32 buffer_count;
|
||||
|
||||
/** Offset in the batchbuffer to start execution from. */
|
||||
__u32 batch_start_offset;
|
||||
/** Bytes used in batchbuffer from batch_start_offset */
|
||||
__u32 batch_len;
|
||||
__u32 DR1;
|
||||
__u32 DR4;
|
||||
__u32 num_cliprects;
|
||||
/**
|
||||
* This is a struct drm_clip_rect *cliprects if I915_EXEC_FENCE_ARRAY
|
||||
* & I915_EXEC_USE_EXTENSIONS are not set.
|
||||
* @batch_start_offset: Offset in the batchbuffer to start execution
|
||||
* from.
|
||||
*/
|
||||
__u32 batch_start_offset;
|
||||
|
||||
/**
|
||||
* @batch_len: Length in bytes of the batch buffer, starting from the
|
||||
* @batch_start_offset. If 0, length is assumed to be the batch buffer
|
||||
* object size.
|
||||
*/
|
||||
__u32 batch_len;
|
||||
|
||||
/** @DR1: deprecated */
|
||||
__u32 DR1;
|
||||
|
||||
/** @DR4: deprecated */
|
||||
__u32 DR4;
|
||||
|
||||
/** @num_cliprects: See @cliprects_ptr */
|
||||
__u32 num_cliprects;
|
||||
|
||||
/**
|
||||
* @cliprects_ptr: Kernel clipping was a DRI1 misfeature.
|
||||
*
|
||||
* It is invalid to use this field if I915_EXEC_FENCE_ARRAY or
|
||||
* I915_EXEC_USE_EXTENSIONS flags are not set.
|
||||
*
|
||||
* If I915_EXEC_FENCE_ARRAY is set, then this is a pointer to an array
|
||||
* of struct drm_i915_gem_exec_fence and num_cliprects is the length
|
||||
* of the array.
|
||||
* of &drm_i915_gem_exec_fence and @num_cliprects is the length of the
|
||||
* array.
|
||||
*
|
||||
* If I915_EXEC_USE_EXTENSIONS is set, then this is a pointer to a
|
||||
* single struct i915_user_extension and num_cliprects is 0.
|
||||
* single &i915_user_extension and num_cliprects is 0.
|
||||
*/
|
||||
__u64 cliprects_ptr;
|
||||
|
||||
/** @flags: Execbuf flags */
|
||||
__u64 flags;
|
||||
#define I915_EXEC_RING_MASK (0x3f)
|
||||
#define I915_EXEC_DEFAULT (0<<0)
|
||||
#define I915_EXEC_RENDER (1<<0)
|
||||
|
@ -1326,10 +1382,6 @@ struct drm_i915_gem_execbuffer2 {
|
|||
#define I915_EXEC_CONSTANTS_REL_GENERAL (0<<6) /* default */
|
||||
#define I915_EXEC_CONSTANTS_ABSOLUTE (1<<6)
|
||||
#define I915_EXEC_CONSTANTS_REL_SURFACE (2<<6) /* gen4/5 only */
|
||||
__u64 flags;
|
||||
__u64 rsvd1; /* now used for context info */
|
||||
__u64 rsvd2;
|
||||
};
|
||||
|
||||
/** Resets the SO write offset registers for transform feedback on gen7. */
|
||||
#define I915_EXEC_GEN7_SOL_RESET (1<<8)
|
||||
|
@ -1432,9 +1484,23 @@ struct drm_i915_gem_execbuffer2 {
|
|||
* drm_i915_gem_execbuffer_ext enum.
|
||||
*/
|
||||
#define I915_EXEC_USE_EXTENSIONS (1 << 21)
|
||||
|
||||
#define __I915_EXEC_UNKNOWN_FLAGS (-(I915_EXEC_USE_EXTENSIONS << 1))
|
||||
|
||||
/** @rsvd1: Context id */
|
||||
__u64 rsvd1;
|
||||
|
||||
/**
|
||||
* @rsvd2: in and out sync_file file descriptors.
|
||||
*
|
||||
* When I915_EXEC_FENCE_IN or I915_EXEC_FENCE_SUBMIT flag is set, the
|
||||
* lower 32 bits of this field will have the in sync_file fd (input).
|
||||
*
|
||||
* When I915_EXEC_FENCE_OUT flag is set, the upper 32 bits of this
|
||||
* field will have the out sync_file fd (output).
|
||||
*/
|
||||
__u64 rsvd2;
|
||||
};
|
||||
|
||||
#define I915_EXEC_CONTEXT_ID_MASK (0xffffffff)
|
||||
#define i915_execbuffer2_set_context_id(eb2, context) \
|
||||
(eb2).rsvd1 = context & I915_EXEC_CONTEXT_ID_MASK
|
||||
|
@ -1814,19 +1880,58 @@ struct drm_i915_gem_context_create {
|
|||
__u32 pad;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_i915_gem_context_create_ext - Structure for creating contexts.
|
||||
*/
|
||||
struct drm_i915_gem_context_create_ext {
|
||||
__u32 ctx_id; /* output: id of new context*/
|
||||
/** @ctx_id: Id of the created context (output) */
|
||||
__u32 ctx_id;
|
||||
|
||||
/**
|
||||
* @flags: Supported flags are:
|
||||
*
|
||||
* I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS:
|
||||
*
|
||||
* Extensions may be appended to this structure and driver must check
|
||||
* for those. See @extensions.
|
||||
*
|
||||
* I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE
|
||||
*
|
||||
* Created context will have single timeline.
|
||||
*/
|
||||
__u32 flags;
|
||||
#define I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS (1u << 0)
|
||||
#define I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE (1u << 1)
|
||||
#define I915_CONTEXT_CREATE_FLAGS_UNKNOWN \
|
||||
(-(I915_CONTEXT_CREATE_FLAGS_SINGLE_TIMELINE << 1))
|
||||
|
||||
/**
|
||||
* @extensions: Zero-terminated chain of extensions.
|
||||
*
|
||||
* I915_CONTEXT_CREATE_EXT_SETPARAM:
|
||||
* Context parameter to set or query during context creation.
|
||||
* See struct drm_i915_gem_context_create_ext_setparam.
|
||||
*
|
||||
* I915_CONTEXT_CREATE_EXT_CLONE:
|
||||
* This extension has been removed. On the off chance someone somewhere
|
||||
* has attempted to use it, never re-use this extension number.
|
||||
*/
|
||||
__u64 extensions;
|
||||
#define I915_CONTEXT_CREATE_EXT_SETPARAM 0
|
||||
#define I915_CONTEXT_CREATE_EXT_CLONE 1
|
||||
};
|
||||
|
||||
/**
|
||||
* struct drm_i915_gem_context_param - Context parameter to set or query.
|
||||
*/
|
||||
struct drm_i915_gem_context_param {
|
||||
/** @ctx_id: Context id */
|
||||
__u32 ctx_id;
|
||||
|
||||
/** @size: Size of the parameter @value */
|
||||
__u32 size;
|
||||
|
||||
/** @param: Parameter to set or query */
|
||||
__u64 param;
|
||||
#define I915_CONTEXT_PARAM_BAN_PERIOD 0x1
|
||||
/* I915_CONTEXT_PARAM_NO_ZEROMAP has been removed. On the off chance
|
||||
|
@ -1973,6 +2078,7 @@ struct drm_i915_gem_context_param {
|
|||
#define I915_CONTEXT_PARAM_PROTECTED_CONTENT 0xd
|
||||
/* Must be kept compact -- no holes and well documented */
|
||||
|
||||
/** @value: Context parameter value to be set or queried */
|
||||
__u64 value;
|
||||
};
|
||||
|
||||
|
@ -2371,23 +2477,29 @@ struct i915_context_param_engines {
|
|||
struct i915_engine_class_instance engines[N__]; \
|
||||
} __attribute__((packed)) name__
|
||||
|
||||
/**
|
||||
* struct drm_i915_gem_context_create_ext_setparam - Context parameter
|
||||
* to set or query during context creation.
|
||||
*/
|
||||
struct drm_i915_gem_context_create_ext_setparam {
|
||||
#define I915_CONTEXT_CREATE_EXT_SETPARAM 0
|
||||
/** @base: Extension link. See struct i915_user_extension. */
|
||||
struct i915_user_extension base;
|
||||
|
||||
/**
|
||||
* @param: Context parameter to set or query.
|
||||
* See struct drm_i915_gem_context_param.
|
||||
*/
|
||||
struct drm_i915_gem_context_param param;
|
||||
};
|
||||
|
||||
/* This API has been removed. On the off chance someone somewhere has
|
||||
* attempted to use it, never re-use this extension number.
|
||||
*/
|
||||
#define I915_CONTEXT_CREATE_EXT_CLONE 1
|
||||
|
||||
struct drm_i915_gem_context_destroy {
|
||||
__u32 ctx_id;
|
||||
__u32 pad;
|
||||
};
|
||||
|
||||
/*
|
||||
/**
|
||||
* struct drm_i915_gem_vm_control - Structure to create or destroy VM.
|
||||
*
|
||||
* DRM_I915_GEM_VM_CREATE -
|
||||
*
|
||||
* Create a new virtual memory address space (ppGTT) for use within a context
|
||||
|
@ -2397,20 +2509,23 @@ struct drm_i915_gem_context_destroy {
|
|||
* The id of new VM (bound to the fd) for use with I915_CONTEXT_PARAM_VM is
|
||||
* returned in the outparam @id.
|
||||
*
|
||||
* No flags are defined, with all bits reserved and must be zero.
|
||||
*
|
||||
* An extension chain maybe provided, starting with @extensions, and terminated
|
||||
* by the @next_extension being 0. Currently, no extensions are defined.
|
||||
*
|
||||
* DRM_I915_GEM_VM_DESTROY -
|
||||
*
|
||||
* Destroys a previously created VM id, specified in @id.
|
||||
* Destroys a previously created VM id, specified in @vm_id.
|
||||
*
|
||||
* No extensions or flags are allowed currently, and so must be zero.
|
||||
*/
|
||||
struct drm_i915_gem_vm_control {
|
||||
/** @extensions: Zero-terminated chain of extensions. */
|
||||
__u64 extensions;
|
||||
|
||||
/** @flags: reserved for future usage, currently MBZ */
|
||||
__u32 flags;
|
||||
|
||||
/** @vm_id: Id of the VM created or to be destroyed */
|
||||
__u32 vm_id;
|
||||
};
|
||||
|
||||
|
@ -3207,36 +3322,6 @@ struct drm_i915_gem_memory_class_instance {
|
|||
* struct drm_i915_memory_region_info - Describes one region as known to the
|
||||
* driver.
|
||||
*
|
||||
* Note that we reserve some stuff here for potential future work. As an example
|
||||
* we might want expose the capabilities for a given region, which could include
|
||||
* things like if the region is CPU mappable/accessible, what are the supported
|
||||
* mapping types etc.
|
||||
*
|
||||
* Note that to extend struct drm_i915_memory_region_info and struct
|
||||
* drm_i915_query_memory_regions in the future the plan is to do the following:
|
||||
*
|
||||
* .. code-block:: C
|
||||
*
|
||||
* struct drm_i915_memory_region_info {
|
||||
* struct drm_i915_gem_memory_class_instance region;
|
||||
* union {
|
||||
* __u32 rsvd0;
|
||||
* __u32 new_thing1;
|
||||
* };
|
||||
* ...
|
||||
* union {
|
||||
* __u64 rsvd1[8];
|
||||
* struct {
|
||||
* __u64 new_thing2;
|
||||
* __u64 new_thing3;
|
||||
* ...
|
||||
* };
|
||||
* };
|
||||
* };
|
||||
*
|
||||
* With this things should remain source compatible between versions for
|
||||
* userspace, even as we add new fields.
|
||||
*
|
||||
* Note this is using both struct drm_i915_query_item and struct drm_i915_query.
|
||||
* For this new query we are adding the new query id DRM_I915_QUERY_MEMORY_REGIONS
|
||||
* at &drm_i915_query_item.query_id.
|
||||
|
@ -3248,14 +3333,81 @@ struct drm_i915_memory_region_info {
|
|||
/** @rsvd0: MBZ */
|
||||
__u32 rsvd0;
|
||||
|
||||
/** @probed_size: Memory probed by the driver (-1 = unknown) */
|
||||
/**
|
||||
* @probed_size: Memory probed by the driver
|
||||
*
|
||||
* Note that it should not be possible to ever encounter a zero value
|
||||
* here, also note that no current region type will ever return -1 here.
|
||||
* Although for future region types, this might be a possibility. The
|
||||
* same applies to the other size fields.
|
||||
*/
|
||||
__u64 probed_size;
|
||||
|
||||
/** @unallocated_size: Estimate of memory remaining (-1 = unknown) */
|
||||
/**
|
||||
* @unallocated_size: Estimate of memory remaining
|
||||
*
|
||||
* Requires CAP_PERFMON or CAP_SYS_ADMIN to get reliable accounting.
|
||||
* Without this (or if this is an older kernel) the value here will
|
||||
* always equal the @probed_size. Note this is only currently tracked
|
||||
* for I915_MEMORY_CLASS_DEVICE regions (for other types the value here
|
||||
* will always equal the @probed_size).
|
||||
*/
|
||||
__u64 unallocated_size;
|
||||
|
||||
/** @rsvd1: MBZ */
|
||||
__u64 rsvd1[8];
|
||||
union {
|
||||
/** @rsvd1: MBZ */
|
||||
__u64 rsvd1[8];
|
||||
struct {
|
||||
/**
|
||||
* @probed_cpu_visible_size: Memory probed by the driver
|
||||
* that is CPU accessible.
|
||||
*
|
||||
* This will be always be <= @probed_size, and the
|
||||
* remainder (if there is any) will not be CPU
|
||||
* accessible.
|
||||
*
|
||||
* On systems without small BAR, the @probed_size will
|
||||
* always equal the @probed_cpu_visible_size, since all
|
||||
* of it will be CPU accessible.
|
||||
*
|
||||
* Note this is only tracked for
|
||||
* I915_MEMORY_CLASS_DEVICE regions (for other types the
|
||||
* value here will always equal the @probed_size).
|
||||
*
|
||||
* Note that if the value returned here is zero, then
|
||||
* this must be an old kernel which lacks the relevant
|
||||
* small-bar uAPI support (including
|
||||
* I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS), but on
|
||||
* such systems we should never actually end up with a
|
||||
* small BAR configuration, assuming we are able to load
|
||||
* the kernel module. Hence it should be safe to treat
|
||||
* this the same as when @probed_cpu_visible_size ==
|
||||
* @probed_size.
|
||||
*/
|
||||
__u64 probed_cpu_visible_size;
|
||||
|
||||
/**
|
||||
* @unallocated_cpu_visible_size: Estimate of CPU
|
||||
* visible memory remaining.
|
||||
*
|
||||
* Note this is only tracked for
|
||||
* I915_MEMORY_CLASS_DEVICE regions (for other types the
|
||||
* value here will always equal the
|
||||
* @probed_cpu_visible_size).
|
||||
*
|
||||
* Requires CAP_PERFMON or CAP_SYS_ADMIN to get reliable
|
||||
* accounting. Without this the value here will always
|
||||
* equal the @probed_cpu_visible_size. Note this is only
|
||||
* currently tracked for I915_MEMORY_CLASS_DEVICE
|
||||
* regions (for other types the value here will also
|
||||
* always equal the @probed_cpu_visible_size).
|
||||
*
|
||||
* If this is an older kernel the value here will be
|
||||
* zero, see also @probed_cpu_visible_size.
|
||||
*/
|
||||
__u64 unallocated_cpu_visible_size;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -3329,11 +3481,11 @@ struct drm_i915_query_memory_regions {
|
|||
* struct drm_i915_gem_create_ext - Existing gem_create behaviour, with added
|
||||
* extension support using struct i915_user_extension.
|
||||
*
|
||||
* Note that in the future we want to have our buffer flags here, at least for
|
||||
* the stuff that is immutable. Previously we would have two ioctls, one to
|
||||
* create the object with gem_create, and another to apply various parameters,
|
||||
* however this creates some ambiguity for the params which are considered
|
||||
* immutable. Also in general we're phasing out the various SET/GET ioctls.
|
||||
* Note that new buffer flags should be added here, at least for the stuff that
|
||||
* is immutable. Previously we would have two ioctls, one to create the object
|
||||
* with gem_create, and another to apply various parameters, however this
|
||||
* creates some ambiguity for the params which are considered immutable. Also in
|
||||
* general we're phasing out the various SET/GET ioctls.
|
||||
*/
|
||||
struct drm_i915_gem_create_ext {
|
||||
/**
|
||||
|
@ -3341,7 +3493,6 @@ struct drm_i915_gem_create_ext {
|
|||
*
|
||||
* The (page-aligned) allocated size for the object will be returned.
|
||||
*
|
||||
*
|
||||
* DG2 64K min page size implications:
|
||||
*
|
||||
* On discrete platforms, starting from DG2, we have to contend with GTT
|
||||
|
@ -3353,7 +3504,9 @@ struct drm_i915_gem_create_ext {
|
|||
*
|
||||
* Note that the returned size here will always reflect any required
|
||||
* rounding up done by the kernel, i.e 4K will now become 64K on devices
|
||||
* such as DG2.
|
||||
* such as DG2. The kernel will always select the largest minimum
|
||||
* page-size for the set of possible placements as the value to use when
|
||||
* rounding up the @size.
|
||||
*
|
||||
* Special DG2 GTT address alignment requirement:
|
||||
*
|
||||
|
@ -3377,14 +3530,58 @@ struct drm_i915_gem_create_ext {
|
|||
* is deemed to be a good compromise.
|
||||
*/
|
||||
__u64 size;
|
||||
|
||||
/**
|
||||
* @handle: Returned handle for the object.
|
||||
*
|
||||
* Object handles are nonzero.
|
||||
*/
|
||||
__u32 handle;
|
||||
/** @flags: MBZ */
|
||||
|
||||
/**
|
||||
* @flags: Optional flags.
|
||||
*
|
||||
* Supported values:
|
||||
*
|
||||
* I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS - Signal to the kernel that
|
||||
* the object will need to be accessed via the CPU.
|
||||
*
|
||||
* Only valid when placing objects in I915_MEMORY_CLASS_DEVICE, and only
|
||||
* strictly required on configurations where some subset of the device
|
||||
* memory is directly visible/mappable through the CPU (which we also
|
||||
* call small BAR), like on some DG2+ systems. Note that this is quite
|
||||
* undesirable, but due to various factors like the client CPU, BIOS etc
|
||||
* it's something we can expect to see in the wild. See
|
||||
* &drm_i915_memory_region_info.probed_cpu_visible_size for how to
|
||||
* determine if this system applies.
|
||||
*
|
||||
* Note that one of the placements MUST be I915_MEMORY_CLASS_SYSTEM, to
|
||||
* ensure the kernel can always spill the allocation to system memory,
|
||||
* if the object can't be allocated in the mappable part of
|
||||
* I915_MEMORY_CLASS_DEVICE.
|
||||
*
|
||||
* Also note that since the kernel only supports flat-CCS on objects
|
||||
* that can *only* be placed in I915_MEMORY_CLASS_DEVICE, we therefore
|
||||
* don't support I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS together with
|
||||
* flat-CCS.
|
||||
*
|
||||
* Without this hint, the kernel will assume that non-mappable
|
||||
* I915_MEMORY_CLASS_DEVICE is preferred for this object. Note that the
|
||||
* kernel can still migrate the object to the mappable part, as a last
|
||||
* resort, if userspace ever CPU faults this object, but this might be
|
||||
* expensive, and so ideally should be avoided.
|
||||
*
|
||||
* On older kernels which lack the relevant small-bar uAPI support (see
|
||||
* also &drm_i915_memory_region_info.probed_cpu_visible_size),
|
||||
* usage of the flag will result in an error, but it should NEVER be
|
||||
* possible to end up with a small BAR configuration, assuming we can
|
||||
* also successfully load the i915 kernel module. In such cases the
|
||||
* entire I915_MEMORY_CLASS_DEVICE region will be CPU accessible, and as
|
||||
* such there are zero restrictions on where the object can be placed.
|
||||
*/
|
||||
#define I915_GEM_CREATE_EXT_FLAG_NEEDS_CPU_ACCESS (1 << 0)
|
||||
__u32 flags;
|
||||
|
||||
/**
|
||||
* @extensions: The chain of extensions to apply to this object.
|
||||
*
|
||||
|
@ -3443,6 +3640,22 @@ struct drm_i915_gem_create_ext {
|
|||
* At which point we get the object handle in &drm_i915_gem_create_ext.handle,
|
||||
* along with the final object size in &drm_i915_gem_create_ext.size, which
|
||||
* should account for any rounding up, if required.
|
||||
*
|
||||
* Note that userspace has no means of knowing the current backing region
|
||||
* for objects where @num_regions is larger than one. The kernel will only
|
||||
* ensure that the priority order of the @regions array is honoured, either
|
||||
* when initially placing the object, or when moving memory around due to
|
||||
* memory pressure
|
||||
*
|
||||
* On Flat-CCS capable HW, compression is supported for the objects residing
|
||||
* in I915_MEMORY_CLASS_DEVICE. When such objects (compressed) have other
|
||||
* memory class in @regions and migrated (by i915, due to memory
|
||||
* constraints) to the non I915_MEMORY_CLASS_DEVICE region, then i915 needs to
|
||||
* decompress the content. But i915 doesn't have the required information to
|
||||
* decompress the userspace compressed objects.
|
||||
*
|
||||
* So i915 supports Flat-CCS, on the objects which can reside only on
|
||||
* I915_MEMORY_CLASS_DEVICE regions.
|
||||
*/
|
||||
struct drm_i915_gem_create_ext_memory_regions {
|
||||
/** @base: Extension link. See struct i915_user_extension. */
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
#define FSCRYPT_MODE_AES_128_CBC 5
|
||||
#define FSCRYPT_MODE_AES_128_CTS 6
|
||||
#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.
|
||||
|
|
|
@ -270,6 +270,8 @@ struct kvm_xen_exit {
|
|||
#define KVM_EXIT_X86_BUS_LOCK 33
|
||||
#define KVM_EXIT_XEN 34
|
||||
#define KVM_EXIT_RISCV_SBI 35
|
||||
#define KVM_EXIT_RISCV_CSR 36
|
||||
#define KVM_EXIT_NOTIFY 37
|
||||
|
||||
/* For KVM_EXIT_INTERNAL_ERROR */
|
||||
/* Emulate instruction failed. */
|
||||
|
@ -496,6 +498,18 @@ struct kvm_run {
|
|||
unsigned long args[6];
|
||||
unsigned long ret[2];
|
||||
} 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. */
|
||||
char padding[256];
|
||||
};
|
||||
|
@ -1157,6 +1171,12 @@ struct kvm_ppc_resize_hpt {
|
|||
#define KVM_CAP_VM_TSC_CONTROL 214
|
||||
#define KVM_CAP_SYSTEM_EVENT_DATA 215
|
||||
#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
|
||||
|
||||
|
@ -1660,6 +1680,55 @@ struct kvm_s390_pv_unp {
|
|||
__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 {
|
||||
KVM_PV_ENABLE,
|
||||
KVM_PV_DISABLE,
|
||||
|
@ -1668,6 +1737,8 @@ enum pv_cmd_id {
|
|||
KVM_PV_VERIFY,
|
||||
KVM_PV_PREP_RESET,
|
||||
KVM_PV_UNSHARE_ALL,
|
||||
KVM_PV_INFO,
|
||||
KVM_PV_DUMP,
|
||||
};
|
||||
|
||||
struct kvm_pv_cmd {
|
||||
|
@ -2119,4 +2190,41 @@ struct kvm_stats_desc {
|
|||
/* Available with KVM_CAP_XSAVE2 */
|
||||
#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 */
|
||||
|
|
|
@ -301,6 +301,7 @@ enum {
|
|||
* { u64 time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED
|
||||
* { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
|
||||
* { u64 id; } && PERF_FORMAT_ID
|
||||
* { u64 lost; } && PERF_FORMAT_LOST
|
||||
* } && !PERF_FORMAT_GROUP
|
||||
*
|
||||
* { u64 nr;
|
||||
|
@ -308,6 +309,7 @@ enum {
|
|||
* { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
|
||||
* { u64 value;
|
||||
* { u64 id; } && PERF_FORMAT_ID
|
||||
* { u64 lost; } && PERF_FORMAT_LOST
|
||||
* } cntr[nr];
|
||||
* } && PERF_FORMAT_GROUP
|
||||
* };
|
||||
|
@ -317,8 +319,9 @@ enum perf_event_read_format {
|
|||
PERF_FORMAT_TOTAL_TIME_RUNNING = 1U << 1,
|
||||
PERF_FORMAT_ID = 1U << 2,
|
||||
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 */
|
||||
|
|
|
@ -171,4 +171,13 @@
|
|||
#define VHOST_VDPA_SET_GROUP_ASID _IOW(VHOST_VIRTIO, 0x7C, \
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
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 = {
|
||||
.cpu = -1
|
||||
|
|
|
@ -305,6 +305,9 @@ int perf_evsel__read_size(struct perf_evsel *evsel)
|
|||
if (read_format & PERF_FORMAT_ID)
|
||||
entry += sizeof(u64);
|
||||
|
||||
if (read_format & PERF_FORMAT_LOST)
|
||||
entry += sizeof(u64);
|
||||
|
||||
if (read_format & PERF_FORMAT_GROUP) {
|
||||
nr = evsel->nr_members;
|
||||
size += sizeof(u64);
|
||||
|
@ -314,24 +317,98 @@ int perf_evsel__read_size(struct perf_evsel *evsel)
|
|||
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,
|
||||
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;
|
||||
struct perf_counts_values buf;
|
||||
|
||||
memset(count, 0, sizeof(*count));
|
||||
|
||||
if (fd == NULL || *fd < 0)
|
||||
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) &&
|
||||
!(read_format & (PERF_FORMAT_ID | PERF_FORMAT_LOST)) &&
|
||||
!perf_mmap__read_self(MMAP(evsel, cpu_map_idx, thread), count))
|
||||
return 0;
|
||||
|
||||
if (readn(*fd, count->values, size) <= 0)
|
||||
if (readn(*fd, buf.values, size) <= 0)
|
||||
return -errno;
|
||||
|
||||
perf_evsel__adjust_values(evsel, buf.values, count);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 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 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);
|
||||
|
||||
#define perf_cpu_map__for_each_cpu(cpu, idx, cpus) \
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <linux/types.h>
|
||||
#include <linux/limits.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <sys/types.h> /* pid_t */
|
||||
|
||||
#define event_contains(obj, mem) ((obj).header.size > offsetof(typeof(obj), mem))
|
||||
|
@ -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_event_header header;
|
||||
|
@ -85,6 +86,7 @@ struct perf_record_read {
|
|||
__u64 time_enabled;
|
||||
__u64 time_running;
|
||||
__u64 id;
|
||||
__u64 lost;
|
||||
};
|
||||
|
||||
struct perf_record_throttle {
|
||||
|
@ -153,22 +155,60 @@ enum {
|
|||
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 {
|
||||
__u16 nr;
|
||||
__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;
|
||||
unsigned long mask[];
|
||||
/* Bitmap data. */
|
||||
__u32 mask[];
|
||||
};
|
||||
|
||||
struct perf_record_cpu_map_data {
|
||||
__u16 type;
|
||||
char data[];
|
||||
/* 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;
|
||||
/* Constant 8. */
|
||||
__u16 long_size;
|
||||
/* Legacy padding. */
|
||||
char __pad[4];
|
||||
/* Bitmap data. */
|
||||
__u64 mask[];
|
||||
};
|
||||
|
||||
/*
|
||||
* '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;
|
||||
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_event_header header;
|
||||
struct perf_record_cpu_map_data data;
|
||||
|
|
|
@ -18,8 +18,10 @@ struct perf_counts_values {
|
|||
uint64_t val;
|
||||
uint64_t ena;
|
||||
uint64_t run;
|
||||
uint64_t id;
|
||||
uint64_t lost;
|
||||
};
|
||||
uint64_t values[3];
|
||||
uint64_t values[5];
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <perf/cpumap.h>
|
||||
#include <perf/threadmap.h>
|
||||
#include <perf/evsel.h>
|
||||
#include <internal/evsel.h>
|
||||
#include <internal/tests.h>
|
||||
#include "tests.h"
|
||||
|
||||
|
@ -189,6 +192,163 @@ static int test_stat_user_read(int event)
|
|||
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)
|
||||
{
|
||||
__T_START;
|
||||
|
@ -200,6 +360,7 @@ int test_evsel(int argc, char **argv)
|
|||
test_stat_thread_enable();
|
||||
test_stat_user_read(PERF_COUNT_HW_INSTRUCTIONS);
|
||||
test_stat_user_read(PERF_COUNT_HW_CPU_CYCLES);
|
||||
test_stat_read_format();
|
||||
|
||||
__T_END;
|
||||
return tests_failed == 0 ? 0 : -1;
|
||||
|
|
|
@ -17,21 +17,23 @@ static int process_event_mask(struct perf_tool *tool __maybe_unused,
|
|||
struct machine *machine __maybe_unused)
|
||||
{
|
||||
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_cpu_map *map;
|
||||
int i;
|
||||
unsigned int long_size;
|
||||
|
||||
data = &map_event->data;
|
||||
|
||||
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++) {
|
||||
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);
|
||||
|
@ -51,7 +53,6 @@ static int process_event_cpus(struct perf_tool *tool __maybe_unused,
|
|||
struct machine *machine __maybe_unused)
|
||||
{
|
||||
struct perf_record_cpu_map *map_event = &event->cpu_map;
|
||||
struct cpu_map_entries *cpus;
|
||||
struct perf_record_cpu_map_data *data;
|
||||
struct perf_cpu_map *map;
|
||||
|
||||
|
@ -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);
|
||||
|
||||
cpus = (struct cpu_map_entries *)data->data;
|
||||
|
||||
TEST_ASSERT_VAL("wrong nr", cpus->nr == 2);
|
||||
TEST_ASSERT_VAL("wrong cpu", cpus->cpu[0] == 1);
|
||||
TEST_ASSERT_VAL("wrong cpu", cpus->cpu[1] == 256);
|
||||
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 cpu", data->cpus_data.cpu[1] == 256);
|
||||
|
||||
map = cpu_map__new_data(data);
|
||||
TEST_ASSERT_VAL("wrong nr", perf_cpu_map__nr(map) == 2);
|
||||
|
|
|
@ -86,10 +86,15 @@ static bool samples_same(const struct perf_sample *s1,
|
|||
COMP(read.time_running);
|
||||
/* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */
|
||||
if (read_format & PERF_FORMAT_GROUP) {
|
||||
for (i = 0; i < s1->read.group.nr; i++)
|
||||
MCOMP(read.group.values[i]);
|
||||
for (i = 0; i < s1->read.group.nr; i++) {
|
||||
/* FIXME: check values without LOST */
|
||||
if (read_format & PERF_FORMAT_LOST)
|
||||
MCOMP(read.group.values[i]);
|
||||
}
|
||||
} else {
|
||||
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)
|
|||
.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;
|
||||
size_t i, sz, bufsz;
|
||||
int err, ret = -1;
|
||||
|
@ -286,6 +291,7 @@ static int do_test(u64 sample_type, u64 sample_regs, u64 read_format)
|
|||
} else {
|
||||
sample.read.one.value = 0x08789faeb786aa87ULL;
|
||||
sample.read.one.id = 99;
|
||||
sample.read.one.lost = 1;
|
||||
}
|
||||
|
||||
sz = perf_event__sample_event_size(&sample, sample_type, read_format);
|
||||
|
@ -370,7 +376,7 @@ out_free:
|
|||
*/
|
||||
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_regs;
|
||||
size_t i;
|
||||
|
|
|
@ -14,6 +14,8 @@ struct file;
|
|||
struct pid;
|
||||
struct cred;
|
||||
struct socket;
|
||||
struct sock;
|
||||
struct sk_buff;
|
||||
|
||||
#define __sockaddr_check_size(size) \
|
||||
BUILD_BUG_ON(((size) > sizeof(struct __kernel_sockaddr_storage)))
|
||||
|
@ -69,6 +71,9 @@ struct msghdr {
|
|||
unsigned int msg_flags; /* flags on received message */
|
||||
__kernel_size_t msg_controllen; /* ancillary data buffer length */
|
||||
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 {
|
||||
|
@ -416,10 +421,9 @@ extern int recvmsg_copy_msghdr(struct msghdr *msg,
|
|||
struct user_msghdr __user *umsg, unsigned flags,
|
||||
struct sockaddr __user **uaddr,
|
||||
struct iovec **iov);
|
||||
extern int __copy_msghdr_from_user(struct msghdr *kmsg,
|
||||
struct user_msghdr __user *umsg,
|
||||
struct sockaddr __user **save_addr,
|
||||
struct iovec __user **uiov, size_t *nsegs);
|
||||
extern int __copy_msghdr(struct msghdr *kmsg,
|
||||
struct user_msghdr *umsg,
|
||||
struct sockaddr __user **save_addr);
|
||||
|
||||
/* helpers which do the actual work for syscalls */
|
||||
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,
|
||||
unsigned int flags, struct sockaddr __user *addr,
|
||||
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,
|
||||
struct sockaddr __user *upeer_sockaddr,
|
||||
int __user *upeer_addrlen, int flags);
|
||||
|
|
|
@ -22,54 +22,102 @@ static int max_node_num;
|
|||
*/
|
||||
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;
|
||||
|
||||
map = perf_cpu_map__empty_new(cpus->nr);
|
||||
map = perf_cpu_map__empty_new(data->cpus_data.nr);
|
||||
if (map) {
|
||||
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,
|
||||
* and we need to use (int) -1 to initialize map[i],
|
||||
* otherwise it would become 65535.
|
||||
*/
|
||||
if (cpus->cpu[i] == (u16) -1)
|
||||
if (data->cpus_data.cpu[i] == (u16) -1)
|
||||
map->map[i].cpu = -1;
|
||||
else
|
||||
map->map[i].cpu = (int) cpus->cpu[i];
|
||||
map->map[i].cpu = (int) data->cpus_data.cpu[i];
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
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(nr);
|
||||
if (map) {
|
||||
int cpu, i = 0;
|
||||
map = perf_cpu_map__empty_new(weight);
|
||||
if (!map)
|
||||
return NULL;
|
||||
|
||||
for_each_set_bit(cpu, mask->mask, nbits)
|
||||
map->map[i++].cpu = cpu;
|
||||
for (int i = 0, j = 0; i < mask_nr; i++) {
|
||||
int cpus_per_i = (i * data->mask32_data.long_size * BITS_PER_BYTE);
|
||||
int cpu;
|
||||
|
||||
perf_record_cpu_map_data__read_one_mask(data, i, local_copy);
|
||||
for_each_set_bit(cpu, local_copy, 64)
|
||||
map->map[j++].cpu = cpu + cpus_per_i;
|
||||
}
|
||||
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)
|
||||
return cpu_map__from_entries((struct cpu_map_entries *)data->data);
|
||||
return cpu_map__from_entries(data);
|
||||
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)
|
||||
|
|
|
@ -37,9 +37,11 @@ struct cpu_aggr_map {
|
|||
|
||||
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 *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_mask(struct perf_cpu_map *map, char *buf, size_t size);
|
||||
size_t cpu_map__fprintf(struct perf_cpu_map *map, FILE *fp);
|
||||
|
|
|
@ -65,7 +65,8 @@ struct stack_dump {
|
|||
|
||||
struct sample_read_value {
|
||||
u64 value;
|
||||
u64 id;
|
||||
u64 id; /* only if PERF_FORMAT_ID */
|
||||
u64 lost; /* only if PERF_FORMAT_LOST */
|
||||
};
|
||||
|
||||
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 {
|
||||
u64 nr;
|
||||
u64 ips[];
|
||||
|
@ -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,
|
||||
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);
|
||||
|
||||
int perf_event_paranoid(void);
|
||||
|
|
|
@ -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,
|
||||
u64 val, u64 ena, u64 run)
|
||||
u64 val, u64 ena, u64 run, u64 lost)
|
||||
{
|
||||
struct perf_counts_values *count;
|
||||
|
||||
|
@ -1550,6 +1550,7 @@ static void evsel__set_count(struct evsel *counter, int cpu_map_idx, int thread,
|
|||
count->val = val;
|
||||
count->ena = ena;
|
||||
count->run = run;
|
||||
count->lost = lost;
|
||||
|
||||
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
|
|||
{
|
||||
u64 read_format = leader->core.attr.read_format;
|
||||
struct sample_read_value *v;
|
||||
u64 nr, ena = 0, run = 0, i;
|
||||
u64 nr, ena = 0, run = 0, lost = 0;
|
||||
|
||||
nr = *data++;
|
||||
|
||||
|
@ -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)
|
||||
run = *data++;
|
||||
|
||||
v = (struct sample_read_value *) data;
|
||||
|
||||
evsel__set_count(leader, cpu_map_idx, thread, v[0].value, ena, run);
|
||||
|
||||
for (i = 1; i < nr; i++) {
|
||||
v = (void *)data;
|
||||
sample_read_group__for_each(v, nr, read_format) {
|
||||
struct evsel *counter;
|
||||
|
||||
counter = evlist__id2evsel(leader->evlist, v[i].id);
|
||||
counter = evlist__id2evsel(leader->evlist, v->id);
|
||||
if (!counter)
|
||||
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;
|
||||
|
@ -2475,8 +2476,8 @@ int evsel__parse_sample(struct evsel *evsel, union perf_event *event,
|
|||
|
||||
if (data->read.group.nr > max_group_nr)
|
||||
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);
|
||||
data->read.group.values =
|
||||
(struct sample_read_value *)array;
|
||||
|
@ -2485,6 +2486,12 @@ int evsel__parse_sample(struct evsel *evsel, union perf_event *event,
|
|||
OVERFLOW_CHECK_u64(array);
|
||||
data->read.one.id = *array;
|
||||
array++;
|
||||
|
||||
if (read_format & PERF_FORMAT_LOST) {
|
||||
OVERFLOW_CHECK_u64(array);
|
||||
data->read.one.lost = *array;
|
||||
array++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -642,15 +642,19 @@ exit:
|
|||
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;
|
||||
|
||||
t = PyTuple_New(2);
|
||||
t = PyTuple_New(3);
|
||||
if (!t)
|
||||
Py_FatalError("couldn't create Python tuple");
|
||||
PyTuple_SetItem(t, 0, PyLong_FromUnsignedLongLong(value->id));
|
||||
PyTuple_SetItem(t, 1, PyLong_FromUnsignedLongLong(value->value));
|
||||
if (read_format & PERF_FORMAT_LOST)
|
||||
PyTuple_SetItem(t, 2, PyLong_FromUnsignedLongLong(value->lost));
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
|
@ -681,12 +685,17 @@ static void set_sample_read_in_dict(PyObject *dict_sample,
|
|||
Py_FatalError("couldn't create Python list");
|
||||
|
||||
if (read_format & PERF_FORMAT_GROUP) {
|
||||
for (i = 0; i < sample->read.group.nr; i++) {
|
||||
PyObject *t = get_sample_value_as_tuple(&sample->read.group.values[i]);
|
||||
struct sample_read_value *v = sample->read.group.values;
|
||||
|
||||
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);
|
||||
i++;
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
pydict_set_item_string_decref(dict_sample, "values", values);
|
||||
|
|
|
@ -916,30 +916,30 @@ static void perf_event__cpu_map_swap(union perf_event *event,
|
|||
bool sample_id_all __maybe_unused)
|
||||
{
|
||||
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);
|
||||
|
||||
switch (data->type) {
|
||||
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++)
|
||||
cpus->cpu[i] = bswap_16(cpus->cpu[i]);
|
||||
for (unsigned i = 0; i < data->cpus_data.nr; i++)
|
||||
data->cpus_data.cpu[i] = bswap_16(data->cpus_data.cpu[i]);
|
||||
break;
|
||||
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) {
|
||||
case 4: mem_bswap_32(&mask->mask, mask->nr); break;
|
||||
case 8: mem_bswap_64(&mask->mask, mask->nr); break;
|
||||
switch (data->mask32_data.long_size) {
|
||||
case 4:
|
||||
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:
|
||||
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)
|
|||
sample->read.time_running);
|
||||
|
||||
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);
|
||||
|
||||
for (i = 0; i < sample->read.group.nr; i++) {
|
||||
struct sample_read_value *value;
|
||||
|
||||
value = &sample->read.group.values[i];
|
||||
sample_read_group__for_each(value, sample->read.group.nr, read_format) {
|
||||
printf("..... id %016" PRIx64
|
||||
", value %016" PRIx64 "\n",
|
||||
", value %016" PRIx64,
|
||||
value->id, value->value);
|
||||
if (read_format & PERF_FORMAT_LOST)
|
||||
printf(", lost %" PRIu64, value->lost);
|
||||
printf("\n");
|
||||
}
|
||||
} else
|
||||
printf("..... id %016" PRIx64 ", value %016" PRIx64 "\n",
|
||||
} else {
|
||||
printf("..... id %016" PRIx64 ", value %016" PRIx64,
|
||||
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,
|
||||
|
@ -1411,6 +1415,9 @@ static void dump_read(struct evsel *evsel, union perf_event *event)
|
|||
|
||||
if (read_format & PERF_FORMAT_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,
|
||||
|
@ -1479,14 +1486,14 @@ static int deliver_sample_group(struct evlist *evlist,
|
|||
struct perf_tool *tool,
|
||||
union perf_event *event,
|
||||
struct perf_sample *sample,
|
||||
struct machine *machine)
|
||||
struct machine *machine,
|
||||
u64 read_format)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
u64 i;
|
||||
struct sample_read_value *v = sample->read.group.values;
|
||||
|
||||
for (i = 0; i < sample->read.group.nr; i++) {
|
||||
ret = deliver_sample_value(evlist, tool, event, sample,
|
||||
&sample->read.group.values[i],
|
||||
sample_read_group__for_each(v, sample->read.group.nr, read_format) {
|
||||
ret = deliver_sample_value(evlist, tool, event, sample, v,
|
||||
machine);
|
||||
if (ret)
|
||||
break;
|
||||
|
@ -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. */
|
||||
if (read_format & PERF_FORMAT_GROUP)
|
||||
return deliver_sample_group(evlist, tool, event, sample,
|
||||
machine);
|
||||
machine, read_format);
|
||||
else
|
||||
return deliver_sample_value(evlist, tool, event, sample,
|
||||
&sample->read.one, machine);
|
||||
|
|
|
@ -1184,52 +1184,48 @@ int perf_event__synthesize_thread_map2(struct perf_tool *tool,
|
|||
return err;
|
||||
}
|
||||
|
||||
static void synthesize_cpus(struct cpu_map_entries *cpus,
|
||||
struct perf_cpu_map *map)
|
||||
static void synthesize_cpus(struct perf_record_cpu_map_data *data,
|
||||
const struct perf_cpu_map *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++)
|
||||
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,
|
||||
struct perf_cpu_map *map, int max)
|
||||
static void synthesize_mask(struct perf_record_cpu_map_data *data,
|
||||
const struct perf_cpu_map *map, int max)
|
||||
{
|
||||
int i;
|
||||
int idx;
|
||||
struct perf_cpu cpu;
|
||||
|
||||
mask->nr = BITS_TO_LONGS(max);
|
||||
mask->long_size = sizeof(long);
|
||||
/* 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;
|
||||
|
||||
for (i = 0; i < perf_cpu_map__nr(map); i++)
|
||||
set_bit(perf_cpu_map__cpu(map, i).cpu, mask->mask);
|
||||
perf_cpu_map__for_each_cpu(cpu, idx, map) {
|
||||
int bit_word = cpu.cpu / 32;
|
||||
__u32 bit_mask = 1U << (cpu.cpu & 31);
|
||||
|
||||
data->mask32_data.mask[bit_word] |= bit_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);
|
||||
}
|
||||
|
||||
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 = 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);
|
||||
*max = perf_cpu_map__max(map).cpu;
|
||||
return sizeof(struct perf_record_mask_cpu_map32) + BITS_TO_U32(*max) * sizeof(__u32);
|
||||
}
|
||||
|
||||
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;
|
||||
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
|
|||
*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));
|
||||
return zalloc(*size);
|
||||
}
|
||||
|
||||
void cpu_map_data__synthesize(struct perf_record_cpu_map_data *data, struct perf_cpu_map *map,
|
||||
u16 type, int max)
|
||||
static void cpu_map_data__synthesize(struct perf_record_cpu_map_data *data,
|
||||
const struct perf_cpu_map *map,
|
||||
u16 type, int max)
|
||||
{
|
||||
data->type = type;
|
||||
|
||||
switch (type) {
|
||||
case PERF_CPU_MAP__CPUS:
|
||||
synthesize_cpus((struct cpu_map_entries *) data->data, map);
|
||||
synthesize_cpus(data, map);
|
||||
break;
|
||||
case PERF_CPU_MAP__MASK:
|
||||
synthesize_mask((struct perf_record_record_cpu_map *)data->data, map, max);
|
||||
synthesize_mask(data, map, max);
|
||||
default:
|
||||
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;
|
||||
int max;
|
||||
u16 type;
|
||||
|
@ -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,
|
||||
struct perf_cpu_map *map,
|
||||
const struct perf_cpu_map *map,
|
||||
perf_event__handler_t process,
|
||||
struct machine *machine)
|
||||
{
|
||||
|
@ -1432,11 +1429,12 @@ size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
|
|||
result += sizeof(u64);
|
||||
/* PERF_FORMAT_ID is forced for PERF_SAMPLE_READ */
|
||||
if (read_format & PERF_FORMAT_GROUP) {
|
||||
sz = sample->read.group.nr *
|
||||
sizeof(struct sample_read_value);
|
||||
result += sz;
|
||||
sz = sample_read_value_size(read_format);
|
||||
result += sz * sample->read.group.nr;
|
||||
} else {
|
||||
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,
|
|||
*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,
|
||||
const struct perf_sample *sample)
|
||||
{
|
||||
|
@ -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 */
|
||||
if (read_format & PERF_FORMAT_GROUP) {
|
||||
sz = sample->read.group.nr *
|
||||
sizeof(struct sample_read_value);
|
||||
memcpy(array, sample->read.group.values, sz);
|
||||
array = (void *)array + sz;
|
||||
array = copy_read_group_values(array, read_format,
|
||||
sample);
|
||||
} else {
|
||||
*array = sample->read.one.id;
|
||||
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
|
|||
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_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_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);
|
||||
|
|
Loading…
Reference in New Issue