Skip to content

Commit bdf5e4f

Browse files
committed
Add BUILTINS.md for builtin function reference.
Signed-off-by: Cong Wang <cwang@multikernel.io>
1 parent 2d43949 commit bdf5e4f

File tree

2 files changed

+398
-0
lines changed

2 files changed

+398
-0
lines changed

BUILTINS.md

Lines changed: 396 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,396 @@
1+
# KernelScript Builtin Functions Reference
2+
3+
This document provides a comprehensive reference for all builtin functions available in KernelScript. These functions are context-aware and translate differently depending on the execution environment (eBPF, userspace, or kernel module).
4+
5+
## Overview
6+
7+
KernelScript builtin functions provide essential functionality across different execution contexts:
8+
- **eBPF Context**: Functions available within eBPF programs running in kernel space
9+
- **Userspace Context**: Functions available in userspace programs that manage eBPF programs
10+
- **Kernel Module Context**: Functions available when compiling to kernel modules
11+
12+
## Builtin Functions by Category
13+
14+
### 1. Input/Output Functions
15+
16+
#### `print(...)`
17+
**Signature:** `print(...) -> u32`
18+
**Variadic:** Yes (accepts any number of arguments)
19+
**Context:** All contexts
20+
21+
**Description:** Print formatted output to the appropriate output stream based on context.
22+
23+
**Context-specific implementations:**
24+
- **eBPF:** Uses `bpf_printk` to write to kernel trace log (limited to format string + 3 arguments)
25+
- **Userspace:** Uses `printf` to write to console/stdout
26+
- **Kernel Module:** Uses `printk` to write to kernel log
27+
28+
**Parameters:**
29+
- Variable number of arguments of any type
30+
- First argument typically used as format string in userspace/kernel contexts
31+
32+
**Return Value:**
33+
- Returns `0` on success (like standard printf family)
34+
- Returns error code on failure
35+
36+
**Examples:**
37+
```kernelscript
38+
print("Hello, world!")
39+
print("Value:", 42)
40+
print("Multiple values:", x, y, z)
41+
```
42+
43+
**Notes:**
44+
- In eBPF context, limited to 4 total arguments due to `bpf_printk` restrictions
45+
- Automatically handles type conversion for different contexts
46+
47+
---
48+
49+
### 2. Program Lifecycle Management
50+
51+
#### `load(function)`
52+
**Signature:** `load(function) -> ProgramHandle`
53+
**Variadic:** No
54+
**Context:** Userspace only
55+
56+
**Description:** Load an eBPF program function and return a handle for subsequent operations.
57+
58+
**Parameters:**
59+
- `function`: Any function with eBPF attributes (`@xdp`, `@kprobe`, `@tracepoint`, etc.)
60+
61+
**Return Value:**
62+
- Returns a `ProgramHandle` that can be used with `attach()` and `detach()`
63+
- Handle represents the loaded eBPF program file descriptor
64+
65+
**Examples:**
66+
```kernelscript
67+
@xdp
68+
fn my_xdp_program(ctx: *xdp_md) -> xdp_action {
69+
return XDP_PASS
70+
}
71+
72+
fn main() -> i32 {
73+
var prog = load(my_xdp_program)
74+
// Use prog with attach()
75+
return 0
76+
}
77+
```
78+
79+
**Context-specific implementations:**
80+
- **eBPF:** Not available
81+
- **Userspace:** Uses `bpf_prog_load` system call
82+
- **Kernel Module:** Not available
83+
84+
---
85+
86+
#### `attach(handle, target, flags)`
87+
**Signature:** `attach(handle: ProgramHandle, target: str(128), flags: u32) -> u32`
88+
**Variadic:** No
89+
**Context:** Userspace only
90+
91+
**Description:** Attach a loaded eBPF program to a target interface or attachment point.
92+
93+
**Parameters:**
94+
- `handle`: Program handle returned from `load()`
95+
- `target`: Target interface name (e.g., "eth0", "lo") or attachment point
96+
- `flags`: Attachment flags (context-dependent)
97+
98+
**Return Value:**
99+
- Returns `0` on success
100+
- Returns error code on failure
101+
102+
**Examples:**
103+
```kernelscript
104+
var prog = load(my_xdp_program)
105+
var result = attach(prog, "eth0", 0)
106+
if (result != 0) {
107+
print("Failed to attach program")
108+
}
109+
```
110+
111+
**Context-specific implementations:**
112+
- **eBPF:** Not available
113+
- **Userspace:** Uses `bpf_prog_attach` system call
114+
- **Kernel Module:** Not available
115+
116+
---
117+
118+
#### `detach(handle)`
119+
**Signature:** `detach(handle: ProgramHandle) -> void`
120+
**Variadic:** No
121+
**Context:** Userspace only
122+
123+
**Description:** Detach a loaded eBPF program from its current attachment point.
124+
125+
**Parameters:**
126+
- `handle`: Program handle returned from `load()`
127+
128+
**Return Value:**
129+
- No return value (void)
130+
131+
**Examples:**
132+
```kernelscript
133+
var prog = load(my_xdp_program)
134+
attach(prog, "eth0", 0)
135+
// ... program runs ...
136+
detach(prog) // Clean up
137+
```
138+
139+
**Context-specific implementations:**
140+
- **eBPF:** Not available
141+
- **Userspace:** Uses `detach_bpf_program_by_fd` function
142+
- **Kernel Module:** Not available
143+
144+
---
145+
146+
### 3. Struct Operations (struct_ops)
147+
148+
#### `register(impl_instance)`
149+
**Signature:** `register(impl_instance) -> u32`
150+
**Variadic:** No
151+
**Context:** Userspace only
152+
153+
**Description:** Register an implementation block instance with the kernel for struct_ops programs.
154+
155+
**Parameters:**
156+
- `impl_instance`: Instance of a struct with `@struct_ops` attribute
157+
158+
**Return Value:**
159+
- Returns `0` on success
160+
- Returns error code on failure
161+
162+
**Validation:**
163+
- Only accepts impl block instances with `@struct_ops` attribute
164+
- Validates that the struct_ops type is known to the kernel
165+
- Must be used with properly attributed implementation blocks
166+
167+
**Examples:**
168+
```kernelscript
169+
@struct_ops("tcp_congestion_ops")
170+
impl TcpCongestion {
171+
// Implementation methods here
172+
}
173+
174+
fn main() -> i32 {
175+
var tcp_impl = TcpCongestion {}
176+
var result = register(tcp_impl)
177+
return result
178+
}
179+
```
180+
181+
**Context-specific implementations:**
182+
- **eBPF:** Not available
183+
- **Userspace:** Uses `IRStructOpsRegister` instruction
184+
- **Kernel Module:** Not available
185+
186+
---
187+
188+
### 4. Testing and Development
189+
190+
#### `test(program, test_data)`
191+
**Signature:** `test(program, test_data) -> u32`
192+
**Variadic:** No
193+
**Context:** Userspace only (from `@test` functions only)
194+
195+
**Description:** Execute an eBPF program with test data and return the program's return value.
196+
197+
**Parameters:**
198+
- `program`: eBPF program to test
199+
- `test_data`: Test input data for the program
200+
201+
**Return Value:**
202+
- Returns the program's return value
203+
- Can be used to verify program behavior in tests
204+
205+
**Restrictions:**
206+
- Can only be called from functions with the `@test` attribute
207+
- Used for unit testing eBPF programs
208+
209+
**Examples:**
210+
```kernelscript
211+
@test
212+
fn test_my_program() -> i32 {
213+
var result = test(my_xdp_program, test_packet_data)
214+
// Assert result == expected_value
215+
return result
216+
}
217+
```
218+
219+
**Context-specific implementations:**
220+
- **eBPF:** Not available
221+
- **Userspace:** Uses `bpf_prog_test_run` system call
222+
- **Kernel Module:** Not available
223+
224+
---
225+
226+
### 5. Event Processing
227+
228+
#### `dispatch(...)`
229+
**Signature:** `dispatch(ringbuf1, ringbuf2, ...) -> i32`
230+
**Variadic:** Yes (accepts multiple ring buffer arguments)
231+
**Context:** Userspace only
232+
233+
**Description:** Poll multiple ring buffers for events and dispatch them to their registered callbacks.
234+
235+
**Parameters:**
236+
- Variable number of ring buffer arguments (RingbufRef or Ringbuf types)
237+
- Each ring buffer should have associated event callbacks
238+
239+
**Return Value:**
240+
- Returns `0` on success
241+
- Returns error code on failure
242+
243+
**Validation:**
244+
- All arguments must be ring buffer types
245+
- Requires at least one ring buffer argument
246+
247+
**Examples:**
248+
```kernelscript
249+
var rb1: ringbuf<u32>(1024)
250+
var rb2: ringbuf<u64>(2048)
251+
252+
fn main() -> i32 {
253+
// Poll both ring buffers for events
254+
var result = dispatch(rb1, rb2)
255+
return result
256+
}
257+
```
258+
259+
**Context-specific implementations:**
260+
- **eBPF:** Not available
261+
- **Userspace:** Uses `ring_buffer__poll` from libbpf
262+
- **Kernel Module:** Not available
263+
264+
---
265+
266+
### 6. Process Management
267+
268+
#### `daemon()`
269+
**Signature:** `daemon() -> void`
270+
**Variadic:** No
271+
**Context:** Userspace only
272+
273+
**Description:** Become a daemon process by detaching from the terminal and running in the background.
274+
275+
**Parameters:**
276+
- No parameters
277+
278+
**Return Value:**
279+
- Never returns in practice (process becomes daemon)
280+
- Type system requires void return type
281+
282+
**Examples:**
283+
```kernelscript
284+
fn main() -> i32 {
285+
print("Starting daemon...")
286+
daemon() // Process detaches from terminal
287+
// Code here runs as daemon
288+
return 0
289+
}
290+
```
291+
292+
**Context-specific implementations:**
293+
- **eBPF:** Not available
294+
- **Userspace:** Uses `daemon_builtin` custom implementation
295+
- **Kernel Module:** Not available
296+
297+
---
298+
299+
#### `exec(python_script)`
300+
**Signature:** `exec(python_script: str(256)) -> void`
301+
**Variadic:** No
302+
**Context:** Userspace only
303+
304+
**Description:** Replace the current process with a Python script, inheriting all eBPF maps and file descriptors.
305+
306+
**Parameters:**
307+
- `python_script`: Path to Python script file (must have .py extension)
308+
309+
**Return Value:**
310+
- Never returns (replaces current process)
311+
- Type system requires void return type
312+
313+
**Validation:**
314+
- Script path must be a string
315+
- File suffix validation occurs during code generation
316+
- Python script inherits eBPF program state
317+
318+
**Examples:**
319+
```kernelscript
320+
fn main() -> i32 {
321+
// Set up eBPF programs and maps
322+
var prog = load(my_program)
323+
attach(prog, "eth0", 0)
324+
325+
// Hand off to Python for advanced processing
326+
exec("advanced_analysis.py") // Never returns
327+
}
328+
```
329+
330+
**Context-specific implementations:**
331+
- **eBPF:** Not available
332+
- **Userspace:** Uses `exec_builtin` custom implementation
333+
- **Kernel Module:** Not available
334+
335+
---
336+
337+
## Context Availability Summary
338+
339+
| Function | eBPF | Userspace | Kernel Module | Notes |
340+
|----------|------|-----------|---------------|-------|
341+
| `print()` |||| Different output destinations |
342+
| `load()` |||| Program management only |
343+
| `attach()` |||| Program management only |
344+
| `detach()` |||| Program management only |
345+
| `register()` |||| struct_ops registration |
346+
| `test()` |||| Testing framework only |
347+
| `dispatch()` |||| Event processing only |
348+
| `daemon()` |||| Process management only |
349+
| `exec()` |||| Process replacement only |
350+
351+
## Related Concepts
352+
353+
### Helper Functions vs. Builtin Functions
354+
355+
- **Builtin Functions**: Defined by KernelScript, context-aware, part of the language
356+
- **Helper Functions**: User-defined functions with `@helper` attribute, compiled as eBPF helpers
357+
- **Kernel Functions (kfuncs)**: External kernel functions declared with `extern` or `@kfunc`
358+
359+
### External Functions
360+
361+
KernelScript also supports external kernel functions that can be declared and called:
362+
363+
```kernelscript
364+
// External eBPF helper functions
365+
extern bpf_ktime_get_ns() -> u64
366+
extern bpf_trace_printk(fmt: *u8, fmt_size: u32) -> i32
367+
extern bpf_get_current_pid_tgid() -> u64
368+
369+
// Usage in eBPF programs
370+
@xdp
371+
fn my_program(ctx: *xdp_md) -> xdp_action {
372+
var timestamp = bpf_ktime_get_ns()
373+
return XDP_PASS
374+
}
375+
```
376+
377+
### Error Handling
378+
379+
Most builtin functions return error codes where appropriate:
380+
- `0`: Success
381+
- Non-zero: Error (specific meaning depends on function)
382+
383+
Always check return values for functions that can fail:
384+
385+
```kernelscript
386+
var result = attach(prog, "eth0", 0)
387+
if (result != 0) {
388+
print("Failed to attach program, error:", result)
389+
return result
390+
}
391+
```
392+
393+
## See Also
394+
395+
- **SPEC.md**: Language specification and features
396+
- **examples/**: Example programs demonstrating builtin function usage

0 commit comments

Comments
 (0)