/* * The CPU number, cstate number and pstate number are based * on 96boards Hikey with octa CA53 CPUs. * * Every CPU have three idle states for cstate: * WFI, CPU_OFF, CLUSTER_OFF * * Every CPU have 5 operating points: * 208MHz, 432MHz, 729MHz, 960MHz, 1200MHz * * This code is based on these assumption and other platforms * need to adjust these definitions.
*/ #define MAX_CPU 8 #define MAX_PSTATE_ENTRIES 5 #define MAX_CSTATE_ENTRIES 3
/* * my_map structure is used to record cstate and pstate index and * timestamp (Idx, Ts), when new event incoming we need to update * combination for new state index and timestamp (Idx`, Ts`). * * Based on (Idx, Ts) and (Idx`, Ts`) we can calculate the time * interval for the previous state: Duration(Idx) = Ts` - Ts. * * Every CPU has one below array for recording state index and * timestamp, and record for cstate and pstate saperately: * * +--------------------------+ * | cstate timestamp | * +--------------------------+ * | cstate index | * +--------------------------+ * | pstate timestamp | * +--------------------------+ * | pstate index | * +--------------------------+
*/ #define MAP_OFF_CSTATE_TIME 0 #define MAP_OFF_CSTATE_IDX 1 #define MAP_OFF_PSTATE_TIME 2 #define MAP_OFF_PSTATE_IDX 3 #define MAP_OFF_NUM 4
/* cstate_duration records duration time for every idle state per CPU */ struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__type(key, u32);
__type(value, u64);
__uint(max_entries, MAX_CPU * MAX_CSTATE_ENTRIES);
} cstate_duration SEC(".maps");
/* pstate_duration records duration time for every operating point per CPU */ struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__type(key, u32);
__type(value, u64);
__uint(max_entries, MAX_CPU * MAX_PSTATE_ENTRIES);
} pstate_duration SEC(".maps");
/* * The trace events for cpu_idle and cpu_frequency are taken from: * /sys/kernel/tracing/events/power/cpu_idle/format * /sys/kernel/tracing/events/power/cpu_frequency/format * * These two events have same format, so define one common structure.
*/ struct cpu_args {
u64 pad;
u32 state;
u32 cpu_id;
};
/* * When state doesn't equal to (u32)-1, the cpu will enter * one idle state; for this case we need to record interval * for the pstate. * * OPP2 * +---------------------+ * OPP1 | | * ---------+ | * | Idle state * +--------------- * * |<- pstate duration ->| * ^ ^ * pts cur_ts
*/ if (ctx->state != (u32)-1) {
/* record pstate after have first cpu_frequency event */ if (!*pts) return 0;
delta = cur_ts - *pts;
pstate_idx = find_cpu_pstate_idx(*pstate); if (pstate_idx >= MAX_PSTATE_ENTRIES) return 0;
key = cpu * MAX_PSTATE_ENTRIES + pstate_idx;
val = bpf_map_lookup_elem(&pstate_duration, &key); if (val)
__sync_fetch_and_add((long *)val, delta);
/* * When state equal to (u32)-1, the cpu just exits from one * specific idle state; for this case we need to record * interval for the pstate. * * OPP2 * -----------+ * | OPP1 * | +----------- * | Idle state | * +---------------------+ * * |<- cstate duration ->| * ^ ^ * cts cur_ts
*/
} else {
key = cpu * MAX_CSTATE_ENTRIES + prev_state;
val = bpf_map_lookup_elem(&cstate_duration, &key); if (val)
__sync_fetch_and_add((long *)val, delta);
}
/* Update timestamp for pstate as new start time */ if (*pts)
*pts = cur_ts;
/* When CPU is in idle, bail out to skip pstate statistics */ if (*cstate != (u32)(-1)) return 0;
/* * The cpu changes to another different OPP (in below diagram * change frequency from OPP3 to OPP1), need recording interval * for previous frequency OPP3 and update timestamp as start * time for new frequency OPP1. * * OPP3 * +---------------------+ * OPP2 | | * ---------+ | * | OPP1 * +--------------- * * |<- pstate duration ->| * ^ ^ * pts cur_ts
*/
pstate_idx = find_cpu_pstate_idx(*pstate); if (pstate_idx >= MAX_PSTATE_ENTRIES) return 0;
key = cpu * MAX_PSTATE_ENTRIES + pstate_idx;
val = bpf_map_lookup_elem(&pstate_duration, &key); if (val)
__sync_fetch_and_add((long *)val, delta);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.