Add @perf_event program type with full attach/detach/count support#18
Open
SiyuanSun0736 wants to merge 2 commits intomultikernel:mainfrom
Open
Add @perf_event program type with full attach/detach/count support#18SiyuanSun0736 wants to merge 2 commits intomultikernel:mainfrom
@perf_event program type with full attach/detach/count support#18SiyuanSun0736 wants to merge 2 commits intomultikernel:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds first-class @perf_event support to KernelScript, enabling eBPF programs to attach to hardware/software performance counters via a perf_event_attr literal and a dedicated attach(handle, attr) workflow with compiler-generated userspace lifecycle helpers.
Changes:
- Introduces
PerfEventprogram type end-to-end (AST/type-checking/IR/codegen) withSEC("perf_event")and*bpf_perf_event_datacontext. - Extends
attach()to support a 2-arg perf-event form, generating userspaceperf_event_open+ attach/enable/disable + read/print helpers. - Adds tests, example, and documentation for perf event programs, counters, and lifecycle semantics.
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_program_ref.ml | Updates stdlib integration expectations for attach() custom validation and error assertion. |
| tests/test_perf_event_attach.ml | Adds unit tests covering perf attach/detach sequencing, pid/cpu validation, defaults, and helper generation. |
| tests/test_ir.ml | Extends IR program type pretty-printing for PerfEvent. |
| tests/dune | Registers new perf-event attach test executable and runtest rule. |
| src/userspace_codegen.ml | Adds perf-event attach detection, conditional headers/types, perf fd lifecycle helpers, and perf attach/detach support. |
| src/type_checker.ml | Adds @perf_event program type recognition and partial signature validation. |
| src/stdlib.ml | Adds perf_counter / perf_event_attr builtins and custom attach() validation for 2-arg/3-arg forms. |
| src/multi_program_analyzer.ml | Adds execution context and discovery logic for PerfEvent programs. |
| src/main.ml | Adds perf_event to init program-type whitelist and project description text. |
| src/ir_generator.ml | Adjusts lowering for non-void function calls used as statements (emit IRCall with discarded return). |
| src/ir_function_system.ml | Adds perf-event entrypoint signature validation at IR validation stage. |
| src/ebpf_c_codegen.ml | Registers perf-event context codegen and emits SEC("perf_event") / perf-event context detection. |
| src/context/perf_event_codegen.ml | New perf-event context codegen module (includes/field access/section name). |
| src/context/dune | Adds perf_event_codegen module to the context library build. |
| src/codegen_common.ml | Maps perf_event_attr IR struct to ks_perf_event_attr in generated C. |
| src/btf_parser.ml | Adds perf-event program template generation and BTF type list updates. |
| src/ast.ml | Adds PerfEvent to program_type and string conversion. |
| examples/perf_branch_miss.ks | New example demonstrating @perf_event attach/detach with perf_event_attr. |
| SPEC.md | Documents perf-event syntax, pid/cpu rules, counters, helper generation, and attach/detach sequences. |
| README.md | Adds perf-event overview, lifecycle example, and counter table. |
| BUILTINS.md | Documents attach(handle, attr) overload and usage example. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
## Language changes
- New `@perf_event` program attribute; context type `*bpf_perf_event_data`
- New `perf_event_attr` struct literal with counter, pid, cpu, period, wakeup,
inherit, exclude_kernel, exclude_user fields
- New `perf_counter` enum: cpu_cycles, instructions, cache_references,
cache_misses, branch_instructions, branch_misses, page_faults,
context_switches, cpu_migrations
- `attach(prog, attr)` two-argument form for perf_event programs
- `detach(prog)` cleans up BPF link, disables and closes perf fd
## Compiler / codegen
- AST: PerfEvent program type, perf_event_attr struct, perf_counter enum
- Type checker: validates @perf_event function signatures and attr fields
- IR generator: recognises PerfEvent program type
- ebpf_c_codegen: emits SEC("perf_event") and bpf_perf_event_data context
- userspace_codegen:
- ks_open_perf_event(): maps perf_counter enum to PERF_TYPE/PERF_COUNT
constants, validates pid/cpu rules, calls perf_event_open(2)
- attach sequence: disabled=1 → IOC_RESET → attach_perf_event → IOC_ENABLE
- detach sequence: IOC_DISABLE → bpf_link__destroy → close(perf_fd)
- ks_read_perf_count(): reads raw 64-bit counter via read()
- ks_print_perf_count(): prints "[perf] <name>: <count>" with PRId64
## Tests
- tests/test_perf_event_attach.ml (6 test cases):
- pid/cpu validation rules enforced
- counting startup ordering (RESET before ENABLE, attach before ENABLE)
- period/wakeup default values when 0
- custom period/wakeup runtime expressions
- ks_read/print_perf_count helpers generated with correct logic
- standard attach branches use libbpf_get_error
## Example
- examples/perf_branch_miss.ks: minimal @perf_event example (branch misses)
- examples/perf_branch_miss/: pre-built reference C output
## Docs
- README.md: @perf_event in program types overview; perf_counter table;
Hardware Performance Counter Programs section with full lifecycle example
- SPEC.md: section 3.1.3 Perf Event Programs — syntax, pid/cpu rules,
perf_counter enum, generated C helpers, attach/detach sequence steps
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds first-class support for
@perf_eventeBPF programs in KernelScript. Users can now attach eBPF logic to hardware and software performance counters (branch misses, CPU cycles, cache misses, etc.) with a clean, safe, single-file workflow — no manualperf_event_open(2)boilerplate required.New language features
@perf_eventprogram attributeperf_event_attrstruct literal — passed directly toattach():perf_counterenum — 9 hardware/software counters:cpu_cycles,instructions,cache_references,cache_misses,branch_instructions,branch_misses,page_faults,context_switches,cpu_migrationsCompiler & codegen changes
ast.mlPerfEventprogram type,perf_event_attrstruct,perf_counterenumtype_checker.ml@perf_eventsignature andperf_event_attrfield typesir_generator.mlPerfEventprogram typeebpf_c_codegen.mlSEC("perf_event")andbpf_perf_event_datacontextcontext/perf_event_codegen.mlstdlib.mlattach/detachbuiltin resolution for perf_event formbtf_parser.mlperf_event_attrBTF type extractionGenerated userspace C functions (emitted when
attach(prog, attr)is used):ks_open_perf_event(ks_perf_event_attr)— mapsperf_counterenum →PERF_TYPE_*/PERF_COUNT_*, validatespid/cpurules, callssyscall(SYS_perf_event_open, ...)ks_read_perf_count(int perf_fd)→int64_t— reads raw counter value viaread()ks_print_perf_count(int perf_fd, const char *name)— prints[perf] <name>: <count>withPRId64Attach sequence (compiler-generated, in order):
attr.disabled = 1— open without startingperf_event_open(2)→perf_fdIOC_RESET— zero the counter before BPF attachmentbpf_program__attach_perf_event(prog, perf_fd)— link BPF programIOC_ENABLE— start countingDetach sequence:
IOC_DISABLE→bpf_link__destroy→close(perf_fd)pid/cpuvalidation (enforced at runtime):pidcpuTests
New file test_perf_event_attach.ml — 6 test cases:
perf_event_codegen_enforces_pid_cpu_rulesIOC_ENABLE/DISABLE, success messagesperf_event_counting_starts_correctlydisabled=1→IOC_RESET→attach_perf_event→IOC_ENABLEorderingperf_event_period_and_wakeup_defaults1000000/1) substituted whenperiod/wakeup= 0perf_event_period_and_wakeup_customperf_read_count_function_generatedks_read_perf_countandks_print_perf_countgenerated correctlystandard_attach_uses_libbpf_error_checkslibbpf_get_errorAll 6 tests pass. perf_branch_miss.ks compiles successfully end-to-end.
Documentation
@perf_eventadded to program types overview; new Hardware Performance Counter Programs section with full lifecycle example andperf_countertablepid/cpurules,perf_counterenum, generated C helpers table, attach/detach sequences, compiler implementation notesTesting checklist
dune build— passesdune build @tests— all OCaml unit tests passtest_all_examples.sh— perf_branch_miss.ks compiles KS→C→binary successfully (remaining failures are pre-existing and unrelated to this PR)