From 578558a46308043bf216823eeb93b6df5a219bf2 Mon Sep 17 00:00:00 2001 From: wuying39 <921169248@qq.com> Date: Mon, 29 Sep 2025 15:44:46 +0800 Subject: [PATCH] src/libkperf: Add PMU sampling support for go pprof --- src/internal/goexperiment/exp_libkperf_off.go | 8 + src/internal/goexperiment/exp_libkperf_on.go | 8 + src/internal/goexperiment/flags.go | 3 + src/libkperf/core_event.go | 196 +++++++++++++ src/libkperf/perf_defs.go | 271 ++++++++++++++++++ src/libkperf/perror.go | 33 +++ src/libkperf/pfm.go | 180 ++++++++++++ 7 files changed, 699 insertions(+) create mode 100644 src/internal/goexperiment/exp_libkperf_off.go create mode 100644 src/internal/goexperiment/exp_libkperf_on.go create mode 100644 src/libkperf/core_event.go create mode 100644 src/libkperf/perf_defs.go create mode 100644 src/libkperf/perror.go create mode 100644 src/libkperf/pfm.go diff --git a/src/internal/goexperiment/exp_libkperf_off.go b/src/internal/goexperiment/exp_libkperf_off.go new file mode 100644 index 00000000..3af8fd8f --- /dev/null +++ b/src/internal/goexperiment/exp_libkperf_off.go @@ -0,0 +1,8 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build !goexperiment.libkperf + +package goexperiment + +const Libkperf = false +const LibkperfInt = 0 diff --git a/src/internal/goexperiment/exp_libkperf_on.go b/src/internal/goexperiment/exp_libkperf_on.go new file mode 100644 index 00000000..416aae98 --- /dev/null +++ b/src/internal/goexperiment/exp_libkperf_on.go @@ -0,0 +1,8 @@ +// Code generated by mkconsts.go. DO NOT EDIT. + +//go:build goexperiment.libkperf + +package goexperiment + +const Libkperf = true +const LibkperfInt = 1 diff --git a/src/internal/goexperiment/flags.go b/src/internal/goexperiment/flags.go index ac85fc80..c20dbb82 100644 --- a/src/internal/goexperiment/flags.go +++ b/src/internal/goexperiment/flags.go @@ -131,4 +131,7 @@ type Flags struct { // Kunpeng malloc prefetch optimization. PrefetchMalloc bool + + // Kunpeng libkperf collection for go pprof + Libkperf bool } diff --git a/src/libkperf/core_event.go b/src/libkperf/core_event.go new file mode 100644 index 00000000..93e50874 --- /dev/null +++ b/src/libkperf/core_event.go @@ -0,0 +1,196 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +//go:build goexperiment.libkperf + +package libkperf + +import ( + "os" + "strings" + "strconv" + "path/filepath" +) + +var coreEventList []string +var pmuDevice string + +const sysDevicePath = "/sys/bus/event_source/devices/" +const midrEl1Path = "/sys/devices/system/cpu/cpu0/regs/identification/midr_el1"; + +type chipType int +const ( + UndefinedType chipType = iota // 0 + HipA // 1 + HipB // 2 + HipC // 3 + HipF // 4 + HipE // 5 + HipG // 6 +) + +var chipMap = map[string]chipType{ + "0x00000000481fd010": HipA, + "0x00000000480fd020": HipB, + "0x00000000480fd030": HipC, + "0x00000000480fd220": HipF, + "0x00000000480fd450": HipE, + "0x00000000480fd060": HipG, +} + +// GetCpuType reads the midr_el1 file and looks up the CPU type in the map +// Returns the corresponding type number, or -1 with an error if not found +func GetCpuType() chipType { + data, err := os.ReadFile(midrEl1Path) + if err != nil { + return UndefinedType + } + midr := strings.TrimSpace(string(data)) + if val, ok := chipMap[midr]; ok { + return val + } else { + return UndefinedType + } +} + +func getPmuDevicePath() string { + if pmuDevice != "" { + return pmuDevice + } + + entries, err := os.ReadDir(sysDevicePath) + if err != nil { + return "" + } + + for _, entry := range entries { + name := entry.Name() + if name == "." || name == ".." || name == "cpu" { + continue + } + + armPmuPath := filepath.Join(sysDevicePath, name, "cpus") + if _, err := os.Stat(armPmuPath); err == nil { + pmuDevice = filepath.Join(sysDevicePath, name) + break + } + } + + return pmuDevice +} + +func queryCoreEvent() []string { + if len(coreEventList) > 0 { + return coreEventList + } + + for evt := range coreEventMap { + coreEventList = append(coreEventList, evt) + } + + pmuDevPath := getPmuDevicePath() + if pmuDevPath == "" { + return coreEventList + } + + eventsPath := filepath.Join(pmuDevPath, "events") + entries, err := os.ReadDir(eventsPath) + if err != nil { + return coreEventList + } + + for _, entry := range entries { + if entry.Type().IsRegular() { + coreEventList = append(coreEventList, entry.Name()) + } + } + + return coreEventList +} + +func containsCoreEvent(events []string, name string) bool { + for _, e := range events { + if e == name { + return true + } + } + return false +} + +func getKernelCoreEventConfig(name string) int64 { + pmuDevicePath := getPmuDevicePath() + if pmuDevicePath == "" { + return -1 + } + + eventPath := filepath.Join(pmuDevicePath, "events", name) + realPath := getRealPath(eventPath) + if !isValidPath(realPath) { + return -1 + } + + data, err := os.ReadFile(realPath) + if err != nil { + return -1 + } + + configStr := strings.TrimSpace(string(data)) + idx := strings.Index(configStr, "=") + if idx == -1 { + return -1 + } + + subStr := configStr[idx+1:] + val, err := strconv.ParseInt(subStr, 0, 64) + if err != nil { + return -1 + } + return val +} + +func isValidPath(path string) bool { + _, err := os.Stat(path) + return err == nil +} + +func getRealPath(path string) string { + real, err := filepath.EvalSymlinks(path) + if err != nil { + return "" + } + return real +} + +func getKernelCoreEventType() int64 { + pmuDevicePath := getPmuDevicePath() + if pmuDevicePath == "" { + return -1 + } + + eventPath := filepath.Join(pmuDevicePath, "type") + realPath := getRealPath(eventPath) + if !isValidPath(realPath) { + return -1 + } + + data, err := os.ReadFile(realPath) + if err != nil { + return -1 + } + + typeStr := strings.TrimSpace(string(data)) + val, err := strconv.ParseInt(typeStr, 0, 64) + if err != nil { + return -1 + } + return val +} + +func getCoreEvent(evtName string) (evtConfig, evtType int64) { + coreEvt, ok := coreEventMap[evtName] + if ok { + return coreEvt.Config, coreEvt.Type + } + + return getKernelCoreEventConfig(evtName), getKernelCoreEventType() +} diff --git a/src/libkperf/perf_defs.go b/src/libkperf/perf_defs.go new file mode 100644 index 00000000..84fe9aa8 --- /dev/null +++ b/src/libkperf/perf_defs.go @@ -0,0 +1,271 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +//go:build goexperiment.libkperf + +package libkperf + +const ( + // Syscall number for perf_event_open on ARM64 linux kernel + SYS_PERF_EVENT_OPEN = 241 + // IOCTL command: disable the selected perf event + PERF_EVENT_IOC_DISABLE = 0x2401 + // IOCTL command: enable the selected perf event + PERF_EVENT_IOC_ENABLE = 0x2400 + // IOCTL command: reset the selected perf event's counters/buffers + PERF_EVENT_IOC_RESET = 0x2403 +) + +// The page size setting for ring buffer mmap +const ( + DEFAULT_SAMPLE_PAGES = 128 + BRBE_SAMPLE_PAGES = 1024 +) + +// PMU collection params for go pprof +type PmuAttr struct { + Period uint64 + Duration int64 + EvtList []string + EnableBrbe bool + EvtFilter string +} + +// The definition of a perf event +type PerfEventAttr struct { + Type uint32 + Size uint32 + Config uint64 + Sample uint64 + Sample_type uint64 + Read_format uint64 + Bits uint64 + Wakeup uint32 + Bp_type uint32 + Ext1 uint64 + Ext2 uint64 + Branch_sample_type uint64 + Sample_regs_user uint64 + Sample_stack_user uint32 + Clockid int32 + Sample_regs_intr uint64 + Aux_watermark uint32 + Sample_max_stack uint16 + _ uint16 + Aux_sample_size uint32 + _ uint32 + Sig_data uint64 +} + +// The definition of the PMU sampling header +type PerfEventHeader struct { + Type uint32 + Misc uint16 + Size uint16 +} + +// The definition of the BRBE data +type PerfBranchEntry struct { + FromAddr uint64 + ToAddr uint64 + Flags uint64 +} + +// The definition of the page that can be mapped via mmap +type PerfEventMmapPage struct { + Version uint32 + Compat_version uint32 + Lock uint32 + Index uint32 + Offset int64 + Time_enabled uint64 + Time_running uint64 + Capabilities uint64 + Pmc_width uint16 + Time_shift uint16 + Time_mult uint32 + Time_offset uint64 + Time_zero uint64 + Size uint32 + _ uint32 + Time_cycles uint64 + Time_mask uint64 + _ [928]uint8 + Data_head uint64 + Data_tail uint64 + Data_offset uint64 + Data_size uint64 + Aux_head uint64 + Aux_tail uint64 + Aux_offset uint64 + Aux_size uint64 +} + +// The sampling data for statistics +type Sample struct { + IP uint64 + PID, TID uint32 + Time uint64 + ID uint64 + Period uint64 + Branches []PerfBranchEntry + Callchain []uint64 + EvtName string +} + +// Set PerfEventAttr.Bits +const ( + PERF_ATTR_DISABLED = 1 << 0 + PERF_ATTR_INHERIT = 1 << 1 + PERF_ATTR_PINNED = 1 << 2 + PERF_ATTR_EXCLUSIVE = 1 << 3 + PERF_ATTR_EXCLUDE_USER = 1 << 4 + PERF_ATTR_EXCLUDE_KERNEL = 1 << 5 + PERF_ATTR_EXCLUDE_HV = 1 << 6 + PERF_ATTR_EXCLUDE_IDLE = 1 << 7 + PERF_ATTR_MMAP = 1 << 8 + PERF_ATTR_COMM = 1 << 9 + PERF_ATTR_FREQ = 1 << 10 + PERF_ATTR_INHERIT_STAT = 1 << 11 + PERF_ATTR_ENABLE_ON_EXEC = 1 << 12 + PERF_ATTR_TASK = 1 << 13 + PERF_ATTR_WATERMARK = 1 << 14 + PERF_ATTR_PRECISE_IP_MASK = 0x3 << 15 + PERF_ATTR_MMAP_DATA = 1 << 17 + PERF_ATTR_SAMPLE_ID_ALL = 1 << 18 + PERF_ATTR_EXCLUDE_HOST = 1 << 19 + PERF_ATTR_EXCLUDE_GUEST = 1 << 20 + PERF_ATTR_EXCLUDE_CALLCHAIN_KERNAL = 1 << 21 + PERF_ATTR_EXCLUDE_CALLCHAIN_USER = 1 << 22 + PERF_ATTR_MMAP2 = 1 << 23 + PERF_ATTR_COMM_EXEC = 1 << 24 + PERF_ATTR_USE_CLOCKID = 1 << 25 + PERF_ATTR_CONTEXT_SWITCH = 1 << 26 + PERF_ATTR_WRITE_BACKWARD = 1 << 27 + PERF_ATTR_NAMESPACES = 1 << 28 + PERF_ATTR_KSYMBOL = 1 << 29 + PERF_ATTR_BPF_EVENT = 1 << 30 + PERF_ATTR_AUX_OUTPUT = 1 << 31 + PERF_ATTR_CGROUP = 1 << 32 + PERF_ATTR_TEXT_POKE = 1 << 33 + PERF_ATTR_BUILD_ID = 1 << 34 + PERF_ATTR_INHERIT_THREAD = 1 << 35 + PERF_ATTR_REMOVE_ONEXEC = 1 << 36 + PERF_ATTR_SIGTRAP = 1 << 37 +) + +// Set PerfEventAttr.Sample_type +const ( + PERF_SAMPLE_IP = 1 << 0 + PERF_SAMPLE_TID = 1 << 1 + PERF_SAMPLE_TIME = 1 << 2 + PERF_SAMPLE_ADDR = 1 << 3 + PERF_SAMPLE_READ = 1 << 4 + PERF_SAMPLE_CALLCHAIN = 1 << 5 + PERF_SAMPLE_ID = 1 << 6 + PERF_SAMPLE_CPU = 1 << 7 + PERF_SAMPLE_PERIOD = 1 << 8 + PERF_SAMPLE_STREAM_ID = 1 << 9 + PERF_SAMPLE_RAW = 1 << 10 + PERF_SAMPLE_BRANCH_STACK = 1 << 11 + PERF_SAMPLE_REGS_USER = 1 << 12 + PERF_SAMPLE_STACK_USER = 1 << 13 + PERF_SAMPLE_WEIGHT = 1 << 14 + PERF_SAMPLE_DATA_SRC = 1 << 15 + PERF_SAMPLE_IDENTIFIER = 1 << 16 + PERF_SAMPLE_TRANSACTION = 1 << 17 + PERF_SAMPLE_REGS_INTR = 1 << 18 + PERF_SAMPLE_PHYS_ADDR = 1 << 19 + PERF_SAMPLE_AUX = 1 << 20 + PERF_SAMPLE_CGROUP = 1 << 21 + PERF_SAMPLE_DATA_PAGE_SIZE = 1 << 22 + PERF_SAMPLE_CODE_PAGE_SIZE = 1 << 23 + PERF_SAMPLE_WEIGHT_STRUCT = 1 << 24 + PERF_SAMPLE_MAX = 1 << 25 +) + +// Set PerfEventAttr.Branch_sample_type +const( + PERF_SAMPLE_BRANCH_USER_SHIFT = 0x0 + PERF_SAMPLE_BRANCH_KERNEL_SHIFT = 0x1 + PERF_SAMPLE_BRANCH_HV_SHIFT = 0x2 + PERF_SAMPLE_BRANCH_ANY_SHIFT = 0x3 + PERF_SAMPLE_BRANCH_ANY_CALL_SHIFT = 0x4 + PERF_SAMPLE_BRANCH_ANY_RETURN_SHIFT = 0x5 + PERF_SAMPLE_BRANCH_IND_CALL_SHIFT = 0x6 + PERF_SAMPLE_BRANCH_ABORT_TX_SHIFT = 0x7 + PERF_SAMPLE_BRANCH_IN_TX_SHIFT = 0x8 + PERF_SAMPLE_BRANCH_NO_TX_SHIFT = 0x9 + PERF_SAMPLE_BRANCH_COND_SHIFT = 0xa + PERF_SAMPLE_BRANCH_CALL_STACK_SHIFT = 0xb + PERF_SAMPLE_BRANCH_IND_JUMP_SHIFT = 0xc + PERF_SAMPLE_BRANCH_CALL_SHIFT = 0xd + PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT = 0xe + PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT = 0xf + PERF_SAMPLE_BRANCH_TYPE_SAVE_SHIFT = 0x10 + PERF_SAMPLE_BRANCH_HW_INDEX_SHIFT = 0x11 + PERF_SAMPLE_BRANCH_PRIV_SAVE_SHIFT = 0x12 + PERF_SAMPLE_BRANCH_COUNTERS = 0x80000 + PERF_SAMPLE_BRANCH_MAX_SHIFT = 0x14 + PERF_SAMPLE_BRANCH_USER = 0x1 + PERF_SAMPLE_BRANCH_KERNEL = 0x2 + PERF_SAMPLE_BRANCH_HV = 0x4 + PERF_SAMPLE_BRANCH_ANY = 0x8 + PERF_SAMPLE_BRANCH_ANY_CALL = 0x10 + PERF_SAMPLE_BRANCH_ANY_RETURN = 0x20 + PERF_SAMPLE_BRANCH_IND_CALL = 0x40 + PERF_SAMPLE_BRANCH_ABORT_TX = 0x80 + PERF_SAMPLE_BRANCH_IN_TX = 0x100 + PERF_SAMPLE_BRANCH_NO_TX = 0x200 + PERF_SAMPLE_BRANCH_COND = 0x400 + PERF_SAMPLE_BRANCH_CALL_STACK = 0x800 + PERF_SAMPLE_BRANCH_IND_JUMP = 0x1000 + PERF_SAMPLE_BRANCH_CALL = 0x2000 + PERF_SAMPLE_BRANCH_NO_FLAGS = 0x4000 + PERF_SAMPLE_BRANCH_NO_CYCLES = 0x8000 + PERF_SAMPLE_BRANCH_TYPE_SAVE = 0x10000 + PERF_SAMPLE_BRANCH_HW_INDEX = 0x20000 + PERF_SAMPLE_BRANCH_PRIV_SAVE = 0x40000 + PERF_SAMPLE_BRANCH_MAX = 0x100000 +) + +// The types of perf record +const ( + PERF_RECORD_MMAP = 0x1 + PERF_RECORD_LOST = 0x2 + PERF_RECORD_COMM = 0x3 + PERF_RECORD_EXIT = 0x4 + PERF_RECORD_THROTTLE = 0x5 + PERF_RECORD_UNTHROTTLE = 0x6 + PERF_RECORD_FORK = 0x7 + PERF_RECORD_READ = 0x8 + PERF_RECORD_SAMPLE = 0x9 + PERF_RECORD_MMAP2 = 0xa + PERF_RECORD_AUX = 0xb + PERF_RECORD_ITRACE_START = 0xc + PERF_RECORD_LOST_SAMPLES = 0xd + PERF_RECORD_SWITCH = 0xe + PERF_RECORD_SWITCH_CPU_WIDE = 0xf + PERF_RECORD_NAMESPACES = 0x10 + PERF_RECORD_KSYMBOL = 0x11 + PERF_RECORD_BPF_EVENT = 0x12 + PERF_RECORD_CGROUP = 0x13 + PERF_RECORD_TEXT_POKE = 0x14 + PERF_RECORD_AUX_OUTPUT_HW_ID = 0x15 + PERF_RECORD_MAX = 0x16 + PERF_RECORD_KSYMBOL_TYPE_UNKNOWN = 0x0 + PERF_RECORD_KSYMBOL_TYPE_BPF = 0x1 + PERF_RECORD_KSYMBOL_TYPE_OOL = 0x2 + PERF_RECORD_KSYMBOL_TYPE_MAX = 0x3 +) + +// Invalid ip list +const( + PERF_CONTEXT_HV = -0x20 + PERF_CONTEXT_KERNEL = -0x80 + PERF_CONTEXT_USER = -0x200 + PERF_CONTEXT_GUEST = -0x800 + PERF_CONTEXT_GUEST_KERNEL = -0x880 + PERF_CONTEXT_GUEST_USER = -0xa00 + PERF_CONTEXT_MAX = -0xfff +) diff --git a/src/libkperf/perror.go b/src/libkperf/perror.go new file mode 100644 index 00000000..553c05ba --- /dev/null +++ b/src/libkperf/perror.go @@ -0,0 +1,33 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +//go:build goexperiment.libkperf + +package libkperf + +import ( + "fmt" + "syscall" +) + +// Return error info of perf_event_open syscall +func errnoErr(e syscall.Errno) error { + switch e { + case syscall.EPERM, syscall.EACCES: + return fmt.Errorf("No permission") + case syscall.EBUSY: + return fmt.Errorf("Pmu device is busy") + case syscall.EINVAL: + return fmt.Errorf("Invalid event for pmu device") + case syscall.ESRCH: + return fmt.Errorf("No such process") + case syscall.EMFILE: + return fmt.Errorf("To many open files") + case syscall.ENOENT: + return fmt.Errorf("Invalid event") + case syscall.ENOTSUP: + return fmt.Errorf("Operation not supported") + default: + return fmt.Errorf("Unknown error: %v", e) + } +} diff --git a/src/libkperf/pfm.go b/src/libkperf/pfm.go new file mode 100644 index 00000000..0ba1e514 --- /dev/null +++ b/src/libkperf/pfm.go @@ -0,0 +1,180 @@ +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. +//go:build goexperiment.libkperf + +package libkperf + +// Set PerfEventAttr Hardware Config +const ( + PERF_COUNT_HW_CPU_CYCLES = 0x0 + PERF_COUNT_HW_INSTRUCTIONS = 0x1 + PERF_COUNT_HW_CACHE_REFERENCES = 0x2 + PERF_COUNT_HW_CACHE_MISSES = 0x3 + PERF_COUNT_HW_BRANCH_INSTRUCTIONS = 0x4 + PERF_COUNT_HW_BRANCH_MISSES = 0x5 + PERF_COUNT_HW_BUS_CYCLES = 0x6 + PERF_COUNT_HW_STALLED_CYCLES_FRONTEND = 0x7 + PERF_COUNT_HW_STALLED_CYCLES_BACKEND = 0x8 + PERF_COUNT_HW_REF_CPU_CYCLES = 0x9 + PERF_COUNT_HW_MAX = 0xa + PERF_COUNT_HW_CACHE_L1D = 0x0 + PERF_COUNT_HW_CACHE_L1I = 0x1 + PERF_COUNT_HW_CACHE_LL = 0x2 + PERF_COUNT_HW_CACHE_DTLB = 0x3 + PERF_COUNT_HW_CACHE_ITLB = 0x4 + PERF_COUNT_HW_CACHE_BPU = 0x5 + PERF_COUNT_HW_CACHE_NODE = 0x6 + PERF_COUNT_HW_CACHE_MAX = 0x7 + PERF_COUNT_HW_CACHE_OP_READ = 0x0 + PERF_COUNT_HW_CACHE_OP_WRITE = 0x1 + PERF_COUNT_HW_CACHE_OP_PREFETCH = 0x2 + PERF_COUNT_HW_CACHE_OP_MAX = 0x3 + PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0x0 + PERF_COUNT_HW_CACHE_RESULT_MISS = 0x1 + PERF_COUNT_HW_CACHE_RESULT_MAX = 0x2 +) + +// Set PerfEventAttr Software Config +const ( + PERF_COUNT_SW_CPU_CLOCK = 0x0 + PERF_COUNT_SW_TASK_CLOCK = 0x1 + PERF_COUNT_SW_PAGE_FAULTS = 0x2 + PERF_COUNT_SW_CONTEXT_SWITCHES = 0x3 + PERF_COUNT_SW_CPU_MIGRATIONS = 0x4 + PERF_COUNT_SW_PAGE_FAULTS_MIN = 0x5 + PERF_COUNT_SW_PAGE_FAULTS_MAJ = 0x6 + PERF_COUNT_SW_ALIGNMENT_FAULTS = 0x7 + PERF_COUNT_SW_EMULATION_FAULTS = 0x8 + PERF_COUNT_SW_DUMMY = 0x9 + PERF_COUNT_SW_BPF_OUTPUT = 0xa + PERF_COUNT_SW_MAX = 0xc +) + +// Set PerfEventAttr.Type +const ( + PERF_TYPE_HARDWARE = 0x0 + PERF_TYPE_SOFTWARE = 0x1 + PERF_TYPE_TRACEPOINT = 0x2 + PERF_TYPE_HW_CACHE = 0x3 + PERF_TYPE_RAW = 0x4 + PERF_TYPE_BREAKPOINT = 0x5 + PERF_TYPE_MAX = 0x6 +) + +// Hardware event names +const BRANCH_MISSES = "branch-misses"; +const BUS_CYCLES = "bus-cycles"; +const CACHE_MISSES = "cache-misses"; +const REF_CYCLES = "ref-cycles"; +const BRANCHES = "branches"; +const BRANCH_INSTRUCTIONS = "branch-instructions"; +const CACHE_REFERENCES = "cache-references"; +const CPU_CYCLES = "cpu-cycles"; +const CYCLES = "cycles"; +const INSTRUCTIONS = "instructions"; +const STALLED_CYCLES_BACKEND = "stalled-cycles-backend"; +const STALLED_CYCLES_FRONTEND = "stalled-cycles-frontend"; + +// Hardware cache event names +const L1_DCACHE_LOAD_MISSES = "L1-dcache-load-misses"; +const L1_DCACHE_LOADS = "L1-dcache-loads"; +const L1_DCACHE_STORE_MISSES = "L1-dcache-store-misses"; +const L1_DCACHE_STORES = "L1-dcache-stores"; +const IDLE_CYCLES_BACKEND = "idle-cycles-backend"; +const L1_ICACHE_LOAD_MISSES = "L1-icache-load-misses"; +const IDLE_CYCLES_FRONTEND = "idle-cycles-frontend"; +const L1_ICACHE_LOADS = "L1-icache-loads"; +const LLC_LOAD_MISSES = "LLC-load-misses"; +const LLC_LOADS = "LLC-loads"; +const LLC_STORE_MISSES = "LLC-store-misses"; +const LLC_STORES = "LLC-stores"; +const BRANCH_LOAD_MISSES = "branch-load-misses"; +const BRANCH_LOADS = "branch-loads"; +const DTLB_LOAD_MISSES = "dTLB-load-misses"; +const DTLB_LOADS = "dTLB-loads"; +const DTLB_STORE_MISSES = "dTLB-store-misses"; +const DTLB_STORES = "dTLB-stores"; +const ITLB_LOAD_MISSES = "iTLB-load-misses"; +const ITLB_LOADS = "iTLB-loads"; +const NODE_LOAD_MISSES = "node-load-misses"; +const NODE_LOADS = "node-loads"; +const NODE_STORE_MISSES = "node-store-misses"; +const NODE_STORES = "node-stores"; + +// Software event name +const ALIGNMENT_FAULTS = "alignment-faults"; +const BPF_OUTPUT = "bpf-output"; +const CONTEXT_SWITCHES = "context-switches"; +const CS = "cs"; +const CPU_CLOCK = "cpu-clock"; +const CPU_MIGRATIONS = "cpu-migrations"; +const MIGRATIONS = "migrations"; +const DUMMY = "dummy"; +const EMULATION_FAULTS = "emulation-faults"; +const MAJOR_FAULTS = "major-faults"; +const MINOR_FAULTS = "minor-faults"; +const PAGE_FAULTS = "page-faults"; +const FAULTS = "faults"; +const TASK_CLOCK = "task-clock"; + +type perfEventDesc struct { + Type int64 + Config int64 +} + +var coreEventMap = map[string]perfEventDesc{ + // Hardware events + BRANCH_INSTRUCTIONS: {Type: PERF_TYPE_HARDWARE, Config: PERF_COUNT_HW_BRANCH_INSTRUCTIONS}, + BRANCH_MISSES: {Type: PERF_TYPE_HARDWARE, Config: PERF_COUNT_HW_BRANCH_MISSES}, + BRANCHES: {Type: PERF_TYPE_HARDWARE, Config: PERF_COUNT_HW_BRANCH_INSTRUCTIONS}, + BUS_CYCLES: {Type: PERF_TYPE_HARDWARE, Config: PERF_COUNT_HW_BUS_CYCLES}, + CACHE_MISSES: {Type: PERF_TYPE_HARDWARE, Config: PERF_COUNT_HW_CACHE_MISSES}, + CACHE_REFERENCES: {Type: PERF_TYPE_HARDWARE, Config: PERF_COUNT_HW_CACHE_REFERENCES}, + CPU_CYCLES: {Type: PERF_TYPE_HARDWARE, Config: PERF_COUNT_HW_CPU_CYCLES}, + CYCLES: {Type: PERF_TYPE_HARDWARE, Config: PERF_COUNT_HW_CPU_CYCLES}, + IDLE_CYCLES_BACKEND: {Type: PERF_TYPE_HARDWARE, Config: PERF_COUNT_HW_STALLED_CYCLES_BACKEND}, + IDLE_CYCLES_FRONTEND: {Type: PERF_TYPE_HARDWARE, Config: PERF_COUNT_HW_STALLED_CYCLES_FRONTEND}, + INSTRUCTIONS: {Type: PERF_TYPE_HARDWARE, Config: PERF_COUNT_HW_INSTRUCTIONS}, + REF_CYCLES: {Type: PERF_TYPE_HARDWARE, Config: PERF_COUNT_HW_REF_CPU_CYCLES}, + STALLED_CYCLES_BACKEND: {Type: PERF_TYPE_HARDWARE, Config: PERF_COUNT_HW_STALLED_CYCLES_BACKEND}, + STALLED_CYCLES_FRONTEND: {Type: PERF_TYPE_HARDWARE, Config: PERF_COUNT_HW_STALLED_CYCLES_FRONTEND}, + // Software events + ALIGNMENT_FAULTS: {Type: PERF_TYPE_SOFTWARE, Config: PERF_COUNT_SW_ALIGNMENT_FAULTS}, + BPF_OUTPUT: {Type: PERF_TYPE_SOFTWARE, Config: PERF_COUNT_SW_BPF_OUTPUT}, + CONTEXT_SWITCHES: {Type: PERF_TYPE_SOFTWARE, Config: PERF_COUNT_SW_CONTEXT_SWITCHES}, + CPU_CLOCK: {Type: PERF_TYPE_SOFTWARE, Config: PERF_COUNT_SW_CPU_CLOCK}, + CPU_MIGRATIONS: {Type: PERF_TYPE_SOFTWARE, Config: PERF_COUNT_SW_CPU_MIGRATIONS}, + CS: {Type: PERF_TYPE_SOFTWARE, Config: PERF_COUNT_SW_CONTEXT_SWITCHES}, + DUMMY: {Type: PERF_TYPE_SOFTWARE, Config: PERF_COUNT_SW_DUMMY}, + EMULATION_FAULTS: {Type: PERF_TYPE_SOFTWARE, Config: PERF_COUNT_SW_EMULATION_FAULTS}, + FAULTS: {Type: PERF_TYPE_SOFTWARE, Config: PERF_COUNT_SW_PAGE_FAULTS}, + MAJOR_FAULTS: {Type: PERF_TYPE_SOFTWARE, Config: PERF_COUNT_SW_PAGE_FAULTS_MAJ}, + MIGRATIONS: {Type: PERF_TYPE_SOFTWARE, Config: PERF_COUNT_SW_CPU_MIGRATIONS}, + MINOR_FAULTS: {Type: PERF_TYPE_SOFTWARE, Config: PERF_COUNT_SW_PAGE_FAULTS_MIN}, + PAGE_FAULTS: {Type: PERF_TYPE_SOFTWARE, Config: PERF_COUNT_SW_PAGE_FAULTS}, + TASK_CLOCK: {Type: PERF_TYPE_SOFTWARE, Config: PERF_COUNT_SW_TASK_CLOCK}, + // Hardware cache events + BRANCH_LOAD_MISSES: {Type: PERF_TYPE_HW_CACHE, Config: 0x10005}, + BRANCH_LOADS: {Type: PERF_TYPE_HW_CACHE, Config: 0x5}, + DTLB_LOAD_MISSES: {Type: PERF_TYPE_HW_CACHE, Config: 0x10003}, + DTLB_LOADS: {Type: PERF_TYPE_HW_CACHE, Config: 0x3}, + DTLB_STORE_MISSES: {Type: PERF_TYPE_HW_CACHE, Config: 0x10103}, + DTLB_STORES: {Type: PERF_TYPE_HW_CACHE, Config: 0x103}, + ITLB_LOAD_MISSES: {Type: PERF_TYPE_HW_CACHE, Config: 0x10004}, + ITLB_LOADS: {Type: PERF_TYPE_HW_CACHE, Config: 0x4}, + L1_DCACHE_LOAD_MISSES: {Type: PERF_TYPE_HW_CACHE, Config: 0x10000}, + L1_DCACHE_LOADS: {Type: PERF_TYPE_HW_CACHE, Config: 0x0}, + L1_DCACHE_STORE_MISSES: {Type: PERF_TYPE_HW_CACHE, Config: 0x10100}, + L1_DCACHE_STORES: {Type: PERF_TYPE_HW_CACHE, Config: 0x100}, + L1_ICACHE_LOAD_MISSES: {Type: PERF_TYPE_HW_CACHE, Config: 0x10001}, + L1_ICACHE_LOADS: {Type: PERF_TYPE_HW_CACHE, Config: 0x1}, + LLC_LOAD_MISSES: {Type: PERF_TYPE_HW_CACHE, Config: 0x10002}, + LLC_LOADS: {Type: PERF_TYPE_HW_CACHE, Config: 0x2}, + LLC_STORE_MISSES: {Type: PERF_TYPE_HW_CACHE, Config: 0x10102}, + LLC_STORES: {Type: PERF_TYPE_HW_CACHE, Config: 0x102}, + NODE_LOAD_MISSES: {Type: PERF_TYPE_HW_CACHE, Config: 0x10006}, + NODE_LOADS: {Type: PERF_TYPE_HW_CACHE, Config: 0x6}, + NODE_STORE_MISSES: {Type: PERF_TYPE_HW_CACHE, Config: 0x10106}, + NODE_STORES: {Type: PERF_TYPE_HW_CACHE, Config: 0x106}, +} -- Gitee