1use crate::memio::EbpfPtr;
6use crate::visitor::{BpfVisitor, ProgramCounter, Register, Source};
7use crate::{
8 BPF_STACK_SIZE, BpfValue, DataWidth, EbpfInstruction, EbpfProgramContext, FromBpfValue,
9 GENERAL_REGISTER_COUNT, HelperSet, Packet, VerifierErrorKind,
10};
11use byteorder::{BigEndian, ByteOrder, LittleEndian};
12use std::mem::MaybeUninit;
13use std::sync::atomic::{AtomicU32, AtomicU64, Ordering};
14use zerocopy::IntoBytes;
15
16pub fn execute<C: EbpfProgramContext>(
17 code: &[EbpfInstruction],
18 helpers: &HelperSet<C>,
19 run_context: &mut C::RunContext<'_>,
20 arguments: &[BpfValue],
21) -> u64 {
22 assert!(arguments.len() < 5);
23 let mut context = ComputationContext {
24 code,
25 helpers,
26 registers: Default::default(),
27 stack: [MaybeUninit::uninit(); BPF_STACK_SIZE / std::mem::size_of::<BpfValue>()],
28 pc: 0,
29 result: None,
30 };
31 for (i, v) in arguments.iter().enumerate() {
32 context.set_reg((i as u8) + 1, *v);
34 }
35
36 context.registers[10] =
38 BpfValue::from((context.stack.as_mut_ptr() as u64) + (BPF_STACK_SIZE as u64));
39
40 loop {
41 if let Some(result) = context.result {
42 return result;
43 }
44 let Ok(()) = context.visit(run_context, code[context.pc]);
46 context.next();
47 }
48}
49
50impl BpfValue {
51 #[inline(always)]
52 pub fn add(&self, offset: u64) -> Self {
53 Self::from(self.as_u64().overflowing_add(offset).0)
54 }
55}
56
57struct ComputationContext<'a, C: EbpfProgramContext> {
59 code: &'a [EbpfInstruction],
61 helpers: &'a HelperSet<C>,
63 registers: [BpfValue; GENERAL_REGISTER_COUNT as usize + 1],
65 stack: [MaybeUninit<BpfValue>; BPF_STACK_SIZE / std::mem::size_of::<BpfValue>()],
67 pc: ProgramCounter,
69 result: Option<u64>,
71}
72
73struct InterpreterError(!);
76
77impl From<VerifierErrorKind> for InterpreterError {
78 #[inline(always)]
79 fn from(error: VerifierErrorKind) -> Self {
80 unreachable!("Invalid code passed to eBPF interpreter: {:?}", error)
81 }
82}
83
84impl<C: EbpfProgramContext> ComputationContext<'_, C> {
85 #[inline(always)]
86 fn reg(&mut self, index: Register) -> BpfValue {
87 self.registers[index as usize]
88 }
89
90 #[inline(always)]
91 fn set_reg(&mut self, index: Register, value: BpfValue) {
92 self.registers[index as usize] = value;
93 }
94
95 #[inline(always)]
96 fn next(&mut self) {
97 self.advance_pc(1)
98 }
99
100 #[inline(always)]
102 fn advance_pc(&mut self, offset: i16) {
103 let mut pc = self.pc as i64;
104 pc += offset as i64;
105 self.pc = pc as usize;
106 }
107
108 #[inline(always)]
109 fn store_memory(
110 &mut self,
111 addr: BpfValue,
112 value: BpfValue,
113 instruction_offset: u64,
114 width: DataWidth,
115 ) {
116 let addr = addr.add(instruction_offset);
117 match width {
118 DataWidth::U8 => {
119 unsafe { EbpfPtr::new(addr.as_ptr::<u8>()).store_relaxed(value.as_u8()) }
121 }
122 DataWidth::U16 => {
123 unsafe { EbpfPtr::new(addr.as_ptr::<u16>()).store_relaxed(value.as_u16()) }
125 }
126 DataWidth::U32 => {
127 unsafe { EbpfPtr::new(addr.as_ptr::<u32>()).store_relaxed(value.as_u32()) }
129 }
130 DataWidth::U64 => {
131 unsafe { EbpfPtr::new(addr.as_ptr::<u64>()).store_relaxed(value.as_u64()) }
133 }
134 }
135 }
136
137 #[inline(always)]
138 fn load_memory(&self, addr: BpfValue, instruction_offset: u64, width: DataWidth) -> BpfValue {
139 let addr = addr.add(instruction_offset);
140 match width {
141 DataWidth::U8 => {
142 BpfValue::from(unsafe { EbpfPtr::new(addr.as_ptr::<u8>()).load_relaxed() })
144 }
145 DataWidth::U16 => {
146 BpfValue::from(unsafe { EbpfPtr::new(addr.as_ptr::<u16>()).load_relaxed() })
148 }
149 DataWidth::U32 => {
150 BpfValue::from(unsafe { EbpfPtr::new(addr.as_ptr::<u32>()).load_relaxed() })
152 }
153 DataWidth::U64 => {
154 BpfValue::from(unsafe { EbpfPtr::new(addr.as_ptr::<u64>()).load_relaxed() })
156 }
157 }
158 }
159
160 #[inline(always)]
161 fn compute_source(&mut self, src: Source) -> BpfValue {
162 match src {
163 Source::Reg(reg) => self.reg(reg),
164 Source::Value(v) => v.into(),
165 }
166 }
167
168 #[inline(always)]
169 fn alu(
170 &mut self,
171 dst: Register,
172 src: Source,
173 op: impl Fn(u64, u64) -> u64,
174 ) -> Result<(), InterpreterError> {
175 let op1 = self.reg(dst).as_u64();
176 let op2 = self.compute_source(src).as_u64();
177 let result = op(op1, op2);
178 self.set_reg(dst, result.into());
179 Ok(())
180 }
181
182 #[inline(always)]
183 fn atomic_operation(
184 &mut self,
185 fetch: bool,
186 dst: Register,
187 offset: i16,
188 src: Register,
189 op: impl Fn(&mut Self, &AtomicU32, u32) -> u32,
190 ) -> Result<(), InterpreterError> {
191 let addr = self.reg(dst).add(offset as u64);
192 #[allow(
197 clippy::undocumented_unsafe_blocks,
198 reason = "Force documented unsafe blocks in Starnix"
199 )]
200 let atomic = unsafe { &*addr.as_ptr::<AtomicU32>() };
201 let value = self.reg(src).as_u32();
202 let old_value = op(self, atomic, value);
203 if fetch {
204 self.set_reg(src, old_value.into());
205 }
206 Ok(())
207 }
208
209 #[inline(always)]
210 fn atomic_operation64(
211 &mut self,
212 fetch: bool,
213 dst: Register,
214 offset: i16,
215 src: Register,
216 op: impl Fn(&mut Self, &AtomicU64, u64) -> u64,
217 ) -> Result<(), InterpreterError> {
218 let addr = self.reg(dst).add(offset as u64);
219 #[allow(
224 clippy::undocumented_unsafe_blocks,
225 reason = "Force documented unsafe blocks in Starnix"
226 )]
227 let atomic = unsafe { &*addr.as_ptr::<AtomicU64>() };
228 let value = self.reg(src).as_u64();
229 let old_value = op(self, atomic, value);
230 if fetch {
231 self.set_reg(src, old_value.into());
232 }
233 Ok(())
234 }
235
236 #[inline(always)]
237 fn endianness<BO: ByteOrder>(
238 &mut self,
239 dst: Register,
240 width: DataWidth,
241 ) -> Result<(), InterpreterError> {
242 let value = self.reg(dst);
243 let new_value = match width {
244 DataWidth::U16 => BO::read_u16((value.as_u64() as u16).as_bytes()) as u64,
245 DataWidth::U32 => BO::read_u32((value.as_u64() as u32).as_bytes()) as u64,
246 DataWidth::U64 => BO::read_u64(value.as_u64().as_bytes()),
247 _ => {
248 panic!("Unexpected bit width for endianness operation");
249 }
250 };
251 self.set_reg(dst, new_value.into());
252 Ok(())
253 }
254
255 #[inline(always)]
256 fn conditional_jump(
257 &mut self,
258 dst: Register,
259 src: Source,
260 offset: i16,
261 op: impl Fn(u64, u64) -> bool,
262 ) -> Result<(), InterpreterError> {
263 let op1 = self.reg(dst).as_u64();
264 let op2 = self.compute_source(src.clone()).as_u64();
265 if op(op1, op2) {
266 self.advance_pc(offset);
267 }
268 Ok(())
269 }
270}
271
272impl<C: EbpfProgramContext> BpfVisitor for ComputationContext<'_, C> {
273 type Context<'a> = C::RunContext<'a>;
274 type Error = InterpreterError;
275
276 #[inline(always)]
277 fn add<'a>(
278 &mut self,
279 _context: &mut Self::Context<'a>,
280 dst: Register,
281 src: Source,
282 ) -> Result<(), InterpreterError> {
283 self.alu(dst, src, |x, y| alu32(x, y, |x, y| x.overflowing_add(y).0))
284 }
285 #[inline(always)]
286 fn add64<'a>(
287 &mut self,
288 _context: &mut Self::Context<'a>,
289 dst: Register,
290 src: Source,
291 ) -> Result<(), InterpreterError> {
292 self.alu(dst, src, |x, y| x.overflowing_add(y).0)
293 }
294 #[inline(always)]
295 fn and<'a>(
296 &mut self,
297 _context: &mut Self::Context<'a>,
298 dst: Register,
299 src: Source,
300 ) -> Result<(), InterpreterError> {
301 self.alu(dst, src, |x, y| alu32(x, y, |x, y| x & y))
302 }
303 #[inline(always)]
304 fn and64<'a>(
305 &mut self,
306 _context: &mut Self::Context<'a>,
307 dst: Register,
308 src: Source,
309 ) -> Result<(), InterpreterError> {
310 self.alu(dst, src, |x, y| x & y)
311 }
312 #[inline(always)]
313 fn arsh<'a>(
314 &mut self,
315 _context: &mut Self::Context<'a>,
316 dst: Register,
317 src: Source,
318 ) -> Result<(), InterpreterError> {
319 self.alu(dst, src, |x, y| {
320 alu32(x, y, |x, y| {
321 let x = x as i32;
322 x.overflowing_shr(y).0 as u32
323 })
324 })
325 }
326 #[inline(always)]
327 fn arsh64<'a>(
328 &mut self,
329 _context: &mut Self::Context<'a>,
330 dst: Register,
331 src: Source,
332 ) -> Result<(), InterpreterError> {
333 self.alu(dst, src, |x, y| {
334 let x = x as i64;
335 let y = y as u32;
338 x.overflowing_shr(y).0 as u64
339 })
340 }
341 #[inline(always)]
342 fn div<'a>(
343 &mut self,
344 _context: &mut Self::Context<'a>,
345 dst: Register,
346 src: Source,
347 ) -> Result<(), InterpreterError> {
348 self.alu(dst, src, |x, y| alu32(x, y, |x, y| if y == 0 { 0 } else { x / y }))
349 }
350 #[inline(always)]
351 fn div64<'a>(
352 &mut self,
353 _context: &mut Self::Context<'a>,
354 dst: Register,
355 src: Source,
356 ) -> Result<(), InterpreterError> {
357 self.alu(dst, src, |x, y| if y == 0 { 0 } else { x / y })
358 }
359 #[inline(always)]
360 fn lsh<'a>(
361 &mut self,
362 _context: &mut Self::Context<'a>,
363 dst: Register,
364 src: Source,
365 ) -> Result<(), InterpreterError> {
366 self.alu(dst, src, |x, y| alu32(x, y, |x, y| x.overflowing_shl(y).0))
367 }
368 #[inline(always)]
369 fn lsh64<'a>(
370 &mut self,
371 _context: &mut Self::Context<'a>,
372 dst: Register,
373 src: Source,
374 ) -> Result<(), InterpreterError> {
375 self.alu(dst, src, |x, y| {
376 let y = y as u32;
379 x.overflowing_shl(y).0
380 })
381 }
382 #[inline(always)]
383 fn r#mod<'a>(
384 &mut self,
385 _context: &mut Self::Context<'a>,
386 dst: Register,
387 src: Source,
388 ) -> Result<(), InterpreterError> {
389 self.alu(dst, src, |x, y| alu32(x, y, |x, y| if y == 0 { x } else { x % y }))
390 }
391 #[inline(always)]
392 fn mod64<'a>(
393 &mut self,
394 _context: &mut Self::Context<'a>,
395 dst: Register,
396 src: Source,
397 ) -> Result<(), InterpreterError> {
398 self.alu(dst, src, |x, y| if y == 0 { x } else { x % y })
399 }
400 #[inline(always)]
401 fn mov<'a>(
402 &mut self,
403 _context: &mut Self::Context<'a>,
404 dst: Register,
405 src: Source,
406 ) -> Result<(), InterpreterError> {
407 self.alu(dst, src, |x, y| alu32(x, y, |_x, y| y))
408 }
409 #[inline(always)]
410 fn mov64<'a>(
411 &mut self,
412 _context: &mut Self::Context<'a>,
413 dst: Register,
414 src: Source,
415 ) -> Result<(), InterpreterError> {
416 self.alu(dst, src, |_x, y| y)
417 }
418 #[inline(always)]
419 fn mul<'a>(
420 &mut self,
421 _context: &mut Self::Context<'a>,
422 dst: Register,
423 src: Source,
424 ) -> Result<(), InterpreterError> {
425 self.alu(dst, src, |x, y| alu32(x, y, |x, y| x.overflowing_mul(y).0))
426 }
427 #[inline(always)]
428 fn mul64<'a>(
429 &mut self,
430 _context: &mut Self::Context<'a>,
431 dst: Register,
432 src: Source,
433 ) -> Result<(), InterpreterError> {
434 self.alu(dst, src, |x, y| x.overflowing_mul(y).0)
435 }
436 #[inline(always)]
437 fn or<'a>(
438 &mut self,
439 _context: &mut Self::Context<'a>,
440 dst: Register,
441 src: Source,
442 ) -> Result<(), InterpreterError> {
443 self.alu(dst, src, |x, y| alu32(x, y, |x, y| x | y))
444 }
445 #[inline(always)]
446 fn or64<'a>(
447 &mut self,
448 _context: &mut Self::Context<'a>,
449 dst: Register,
450 src: Source,
451 ) -> Result<(), InterpreterError> {
452 self.alu(dst, src, |x, y| x | y)
453 }
454 #[inline(always)]
455 fn rsh<'a>(
456 &mut self,
457 _context: &mut Self::Context<'a>,
458 dst: Register,
459 src: Source,
460 ) -> Result<(), InterpreterError> {
461 self.alu(dst, src, |x, y| alu32(x, y, |x, y| x.overflowing_shr(y).0))
462 }
463 #[inline(always)]
464 fn rsh64<'a>(
465 &mut self,
466 _context: &mut Self::Context<'a>,
467 dst: Register,
468 src: Source,
469 ) -> Result<(), InterpreterError> {
470 self.alu(dst, src, |x, y| {
471 let y = y as u32;
474 x.overflowing_shr(y).0
475 })
476 }
477 #[inline(always)]
478 fn sub<'a>(
479 &mut self,
480 _context: &mut Self::Context<'a>,
481 dst: Register,
482 src: Source,
483 ) -> Result<(), InterpreterError> {
484 self.alu(dst, src, |x, y| alu32(x, y, |x, y| x.overflowing_sub(y).0))
485 }
486 #[inline(always)]
487 fn sub64<'a>(
488 &mut self,
489 _context: &mut Self::Context<'a>,
490 dst: Register,
491 src: Source,
492 ) -> Result<(), InterpreterError> {
493 self.alu(dst, src, |x, y| x.overflowing_sub(y).0)
494 }
495 #[inline(always)]
496 fn xor<'a>(
497 &mut self,
498 _context: &mut Self::Context<'a>,
499 dst: Register,
500 src: Source,
501 ) -> Result<(), InterpreterError> {
502 self.alu(dst, src, |x, y| alu32(x, y, |x, y| x ^ y))
503 }
504 #[inline(always)]
505 fn xor64<'a>(
506 &mut self,
507 _context: &mut Self::Context<'a>,
508 dst: Register,
509 src: Source,
510 ) -> Result<(), InterpreterError> {
511 self.alu(dst, src, |x, y| x ^ y)
512 }
513
514 #[inline(always)]
515 fn neg<'a>(
516 &mut self,
517 _context: &mut Self::Context<'a>,
518 dst: Register,
519 ) -> Result<(), InterpreterError> {
520 self.alu(dst, Source::Value(0), |x, y| {
521 alu32(x, y, |x, _y| (x as i32).overflowing_neg().0 as u32)
522 })
523 }
524 #[inline(always)]
525 fn neg64<'a>(
526 &mut self,
527 _context: &mut Self::Context<'a>,
528 dst: Register,
529 ) -> Result<(), InterpreterError> {
530 self.alu(dst, Source::Value(0), |x, _y| (x as i64).overflowing_neg().0 as u64)
531 }
532
533 #[inline(always)]
534 fn be<'a>(
535 &mut self,
536 _context: &mut Self::Context<'a>,
537 dst: Register,
538 width: DataWidth,
539 ) -> Result<(), InterpreterError> {
540 self.endianness::<BigEndian>(dst, width)
541 }
542
543 #[inline(always)]
544 fn le<'a>(
545 &mut self,
546 _context: &mut Self::Context<'a>,
547 dst: Register,
548 width: DataWidth,
549 ) -> Result<(), InterpreterError> {
550 self.endianness::<LittleEndian>(dst, width)
551 }
552
553 #[inline(always)]
554 fn call_external<'a>(
555 &mut self,
556 context: &mut Self::Context<'a>,
557 index: u32,
558 ) -> Result<(), InterpreterError> {
559 let helper = &self.helpers.get_by_index(index).unwrap();
560 let result =
561 helper.0(context, self.reg(1), self.reg(2), self.reg(3), self.reg(4), self.reg(5));
562 self.set_reg(0, result);
563 Ok(())
564 }
565
566 #[inline(always)]
567 fn exit<'a>(&mut self, _context: &mut Self::Context<'a>) -> Result<(), InterpreterError> {
568 self.result = Some(self.reg(0).as_u64());
569 Ok(())
570 }
571
572 #[inline(always)]
573 fn jump<'a>(
574 &mut self,
575 _context: &mut Self::Context<'a>,
576 offset: i16,
577 ) -> Result<(), InterpreterError> {
578 self.advance_pc(offset);
579 Ok(())
580 }
581
582 #[inline(always)]
583 fn jeq<'a>(
584 &mut self,
585 _context: &mut Self::Context<'a>,
586 dst: Register,
587 src: Source,
588 offset: i16,
589 ) -> Result<(), InterpreterError> {
590 self.conditional_jump(dst, src, offset, |x, y| comp32(x, y, |x, y| x == y))
591 }
592 #[inline(always)]
593 fn jeq64<'a>(
594 &mut self,
595 _context: &mut Self::Context<'a>,
596 dst: Register,
597 src: Source,
598 offset: i16,
599 ) -> Result<(), InterpreterError> {
600 self.conditional_jump(dst, src, offset, |x, y| x == y)
601 }
602 #[inline(always)]
603 fn jne<'a>(
604 &mut self,
605 _context: &mut Self::Context<'a>,
606 dst: Register,
607 src: Source,
608 offset: i16,
609 ) -> Result<(), InterpreterError> {
610 self.conditional_jump(dst, src, offset, |x, y| comp32(x, y, |x, y| x != y))
611 }
612 #[inline(always)]
613 fn jne64<'a>(
614 &mut self,
615 _context: &mut Self::Context<'a>,
616 dst: Register,
617 src: Source,
618 offset: i16,
619 ) -> Result<(), InterpreterError> {
620 self.conditional_jump(dst, src, offset, |x, y| x != y)
621 }
622 #[inline(always)]
623 fn jge<'a>(
624 &mut self,
625 _context: &mut Self::Context<'a>,
626 dst: Register,
627 src: Source,
628 offset: i16,
629 ) -> Result<(), InterpreterError> {
630 self.conditional_jump(dst, src, offset, |x, y| comp32(x, y, |x, y| x >= y))
631 }
632 #[inline(always)]
633 fn jge64<'a>(
634 &mut self,
635 _context: &mut Self::Context<'a>,
636 dst: Register,
637 src: Source,
638 offset: i16,
639 ) -> Result<(), InterpreterError> {
640 self.conditional_jump(dst, src, offset, |x, y| x >= y)
641 }
642 #[inline(always)]
643 fn jgt<'a>(
644 &mut self,
645 _context: &mut Self::Context<'a>,
646 dst: Register,
647 src: Source,
648 offset: i16,
649 ) -> Result<(), InterpreterError> {
650 self.conditional_jump(dst, src, offset, |x, y| comp32(x, y, |x, y| x > y))
651 }
652 #[inline(always)]
653 fn jgt64<'a>(
654 &mut self,
655 _context: &mut Self::Context<'a>,
656 dst: Register,
657 src: Source,
658 offset: i16,
659 ) -> Result<(), InterpreterError> {
660 self.conditional_jump(dst, src, offset, |x, y| x > y)
661 }
662 #[inline(always)]
663 fn jle<'a>(
664 &mut self,
665 _context: &mut Self::Context<'a>,
666 dst: Register,
667 src: Source,
668 offset: i16,
669 ) -> Result<(), InterpreterError> {
670 self.conditional_jump(dst, src, offset, |x, y| comp32(x, y, |x, y| x <= y))
671 }
672 #[inline(always)]
673 fn jle64<'a>(
674 &mut self,
675 _context: &mut Self::Context<'a>,
676 dst: Register,
677 src: Source,
678 offset: i16,
679 ) -> Result<(), InterpreterError> {
680 self.conditional_jump(dst, src, offset, |x, y| x <= y)
681 }
682 #[inline(always)]
683 fn jlt<'a>(
684 &mut self,
685 _context: &mut Self::Context<'a>,
686 dst: Register,
687 src: Source,
688 offset: i16,
689 ) -> Result<(), InterpreterError> {
690 self.conditional_jump(dst, src, offset, |x, y| comp32(x, y, |x, y| x < y))
691 }
692 #[inline(always)]
693 fn jlt64<'a>(
694 &mut self,
695 _context: &mut Self::Context<'a>,
696 dst: Register,
697 src: Source,
698 offset: i16,
699 ) -> Result<(), InterpreterError> {
700 self.conditional_jump(dst, src, offset, |x, y| x < y)
701 }
702 #[inline(always)]
703 fn jsge<'a>(
704 &mut self,
705 _context: &mut Self::Context<'a>,
706 dst: Register,
707 src: Source,
708 offset: i16,
709 ) -> Result<(), InterpreterError> {
710 self.conditional_jump(dst, src, offset, |x, y| scomp32(x, y, |x, y| x >= y))
711 }
712 #[inline(always)]
713 fn jsge64<'a>(
714 &mut self,
715 _context: &mut Self::Context<'a>,
716 dst: Register,
717 src: Source,
718 offset: i16,
719 ) -> Result<(), InterpreterError> {
720 self.conditional_jump(dst, src, offset, |x, y| scomp64(x, y, |x, y| x >= y))
721 }
722 #[inline(always)]
723 fn jsgt<'a>(
724 &mut self,
725 _context: &mut Self::Context<'a>,
726 dst: Register,
727 src: Source,
728 offset: i16,
729 ) -> Result<(), InterpreterError> {
730 self.conditional_jump(dst, src, offset, |x, y| scomp32(x, y, |x, y| x > y))
731 }
732 #[inline(always)]
733 fn jsgt64<'a>(
734 &mut self,
735 _context: &mut Self::Context<'a>,
736 dst: Register,
737 src: Source,
738 offset: i16,
739 ) -> Result<(), InterpreterError> {
740 self.conditional_jump(dst, src, offset, |x, y| scomp64(x, y, |x, y| x > y))
741 }
742 #[inline(always)]
743 fn jsle<'a>(
744 &mut self,
745 _context: &mut Self::Context<'a>,
746 dst: Register,
747 src: Source,
748 offset: i16,
749 ) -> Result<(), InterpreterError> {
750 self.conditional_jump(dst, src, offset, |x, y| scomp32(x, y, |x, y| x <= y))
751 }
752 #[inline(always)]
753 fn jsle64<'a>(
754 &mut self,
755 _context: &mut Self::Context<'a>,
756 dst: Register,
757 src: Source,
758 offset: i16,
759 ) -> Result<(), InterpreterError> {
760 self.conditional_jump(dst, src, offset, |x, y| scomp64(x, y, |x, y| x <= y))
761 }
762 #[inline(always)]
763 fn jslt<'a>(
764 &mut self,
765 _context: &mut Self::Context<'a>,
766 dst: Register,
767 src: Source,
768 offset: i16,
769 ) -> Result<(), InterpreterError> {
770 self.conditional_jump(dst, src, offset, |x, y| scomp32(x, y, |x, y| x < y))
771 }
772 #[inline(always)]
773 fn jslt64<'a>(
774 &mut self,
775 _context: &mut Self::Context<'a>,
776 dst: Register,
777 src: Source,
778 offset: i16,
779 ) -> Result<(), InterpreterError> {
780 self.conditional_jump(dst, src, offset, |x, y| scomp64(x, y, |x, y| x < y))
781 }
782 #[inline(always)]
783 fn jset<'a>(
784 &mut self,
785 _context: &mut Self::Context<'a>,
786 dst: Register,
787 src: Source,
788 offset: i16,
789 ) -> Result<(), InterpreterError> {
790 self.conditional_jump(dst, src, offset, |x, y| comp32(x, y, |x, y| x & y != 0))
791 }
792 #[inline(always)]
793 fn jset64<'a>(
794 &mut self,
795 _context: &mut Self::Context<'a>,
796 dst: Register,
797 src: Source,
798 offset: i16,
799 ) -> Result<(), InterpreterError> {
800 self.conditional_jump(dst, src, offset, |x, y| x & y != 0)
801 }
802
803 #[inline(always)]
804 fn atomic_add<'a>(
805 &mut self,
806 _context: &mut Self::Context<'a>,
807 fetch: bool,
808 dst: Register,
809 offset: i16,
810 src: Register,
811 ) -> Result<(), InterpreterError> {
812 self.atomic_operation(fetch, dst, offset, src, |_, a, v| a.fetch_add(v, Ordering::SeqCst))
813 }
814
815 #[inline(always)]
816 fn atomic_add64<'a>(
817 &mut self,
818 _context: &mut Self::Context<'a>,
819 fetch: bool,
820 dst: Register,
821 offset: i16,
822 src: Register,
823 ) -> Result<(), InterpreterError> {
824 self.atomic_operation64(fetch, dst, offset, src, |_, a, v| a.fetch_add(v, Ordering::SeqCst))
825 }
826
827 #[inline(always)]
828 fn atomic_and<'a>(
829 &mut self,
830 _context: &mut Self::Context<'a>,
831 fetch: bool,
832 dst: Register,
833 offset: i16,
834 src: Register,
835 ) -> Result<(), InterpreterError> {
836 self.atomic_operation(fetch, dst, offset, src, |_, a, v| a.fetch_and(v, Ordering::SeqCst))
837 }
838
839 #[inline(always)]
840 fn atomic_and64<'a>(
841 &mut self,
842 _context: &mut Self::Context<'a>,
843 fetch: bool,
844 dst: Register,
845 offset: i16,
846 src: Register,
847 ) -> Result<(), InterpreterError> {
848 self.atomic_operation64(fetch, dst, offset, src, |_, a, v| a.fetch_and(v, Ordering::SeqCst))
849 }
850
851 #[inline(always)]
852 fn atomic_or<'a>(
853 &mut self,
854 _context: &mut Self::Context<'a>,
855 fetch: bool,
856 dst: Register,
857 offset: i16,
858 src: Register,
859 ) -> Result<(), InterpreterError> {
860 self.atomic_operation(fetch, dst, offset, src, |_, a, v| a.fetch_or(v, Ordering::SeqCst))
861 }
862
863 #[inline(always)]
864 fn atomic_or64<'a>(
865 &mut self,
866 _context: &mut Self::Context<'a>,
867 fetch: bool,
868 dst: Register,
869 offset: i16,
870 src: Register,
871 ) -> Result<(), InterpreterError> {
872 self.atomic_operation64(fetch, dst, offset, src, |_, a, v| a.fetch_or(v, Ordering::SeqCst))
873 }
874
875 #[inline(always)]
876 fn atomic_xor<'a>(
877 &mut self,
878 _context: &mut Self::Context<'a>,
879 fetch: bool,
880 dst: Register,
881 offset: i16,
882 src: Register,
883 ) -> Result<(), InterpreterError> {
884 self.atomic_operation(fetch, dst, offset, src, |_, a, v| a.fetch_xor(v, Ordering::SeqCst))
885 }
886
887 #[inline(always)]
888 fn atomic_xor64<'a>(
889 &mut self,
890 _context: &mut Self::Context<'a>,
891 fetch: bool,
892 dst: Register,
893 offset: i16,
894 src: Register,
895 ) -> Result<(), InterpreterError> {
896 self.atomic_operation64(fetch, dst, offset, src, |_, a, v| a.fetch_xor(v, Ordering::SeqCst))
897 }
898
899 #[inline(always)]
900 fn atomic_xchg<'a>(
901 &mut self,
902 _context: &mut Self::Context<'a>,
903 fetch: bool,
904 dst: Register,
905 offset: i16,
906 src: Register,
907 ) -> Result<(), InterpreterError> {
908 self.atomic_operation(fetch, dst, offset, src, |_, a, v| a.swap(v, Ordering::SeqCst))
909 }
910
911 #[inline(always)]
912 fn atomic_xchg64<'a>(
913 &mut self,
914 _context: &mut Self::Context<'a>,
915 fetch: bool,
916 dst: Register,
917 offset: i16,
918 src: Register,
919 ) -> Result<(), InterpreterError> {
920 self.atomic_operation64(fetch, dst, offset, src, |_, a, v| a.swap(v, Ordering::SeqCst))
921 }
922
923 #[inline(always)]
924 fn atomic_cmpxchg<'a>(
925 &mut self,
926 _context: &mut Self::Context<'a>,
927 dst: Register,
928 offset: i16,
929 src: Register,
930 ) -> Result<(), InterpreterError> {
931 self.atomic_operation(false, dst, offset, src, |this, a, v| {
932 let r0 = this.reg(0).as_u32();
933 let r0 = match a.compare_exchange(r0, v, Ordering::SeqCst, Ordering::SeqCst) {
934 Ok(v) | Err(v) => v,
935 };
936 this.set_reg(0, r0.into());
937 0
938 })
939 }
940
941 #[inline(always)]
942 fn atomic_cmpxchg64<'a>(
943 &mut self,
944 _context: &mut Self::Context<'a>,
945 dst: Register,
946 offset: i16,
947 src: Register,
948 ) -> Result<(), InterpreterError> {
949 self.atomic_operation64(false, dst, offset, src, |this, a, v| {
950 let r0 = this.reg(0).as_u64();
951 let r0 = match a.compare_exchange(r0, v, Ordering::SeqCst, Ordering::SeqCst) {
952 Ok(v) | Err(v) => v,
953 };
954 this.set_reg(0, r0.into());
955 0
956 })
957 }
958
959 #[inline(always)]
960 fn load<'a>(
961 &mut self,
962 _context: &mut Self::Context<'a>,
963 dst: Register,
964 offset: i16,
965 src: Register,
966 width: DataWidth,
967 ) -> Result<(), InterpreterError> {
968 let addr = self.reg(src);
969 let loaded = self.load_memory(addr, offset as u64, width);
970 self.set_reg(dst, loaded);
971 Ok(())
972 }
973
974 #[inline(always)]
975 fn load64<'a>(
976 &mut self,
977 _context: &mut Self::Context<'a>,
978 dst: Register,
979 _src: u8,
980 lower: u32,
981 ) -> Result<(), InterpreterError> {
982 let value = (lower as u64) | (((self.code[self.pc + 1].imm() as u32) as u64) << 32);
983 self.set_reg(dst, value.into());
984 self.advance_pc(1);
985 Ok(())
986 }
987
988 #[inline(always)]
989 fn load_from_packet<'a>(
990 &mut self,
991 context: &mut Self::Context<'a>,
992 dst_reg: Register,
993 src_reg: Register,
994 offset: i32,
995 register_offset: Option<Register>,
996 width: DataWidth,
997 ) -> Result<(), InterpreterError> {
998 let Some(offset) =
999 register_offset.map(|r| self.reg(r).as_i32()).unwrap_or(0).checked_add(offset as i32)
1000 else {
1001 self.result = Some(0);
1003 return Ok(());
1004 };
1005 let src_reg = self.reg(src_reg);
1006 let packet = unsafe { C::Packet::from_bpf_value(context, src_reg) };
1008 if let Some(value) = packet.load(offset, width) {
1009 self.set_reg(dst_reg, value.into());
1010 } else {
1011 self.result = Some(0);
1012 }
1013 Ok(())
1014 }
1015
1016 #[inline(always)]
1017 fn store<'a>(
1018 &mut self,
1019 _context: &mut Self::Context<'a>,
1020 dst: Register,
1021 offset: i16,
1022 src: Source,
1023 width: DataWidth,
1024 ) -> Result<(), InterpreterError> {
1025 let src = self.compute_source(src);
1026 let dst = self.reg(dst);
1027 self.store_memory(dst, src, offset as u64, width);
1028 Ok(())
1029 }
1030}
1031
1032#[inline(always)]
1033fn alu32(x: u64, y: u64, op: impl FnOnce(u32, u32) -> u32) -> u64 {
1034 op(x as u32, y as u32) as u64
1035}
1036
1037#[inline(always)]
1038fn comp32(x: u64, y: u64, op: impl FnOnce(u32, u32) -> bool) -> bool {
1039 op(x as u32, y as u32)
1040}
1041
1042#[inline(always)]
1043fn scomp64(x: u64, y: u64, op: impl FnOnce(i64, i64) -> bool) -> bool {
1044 op(x as i64, y as i64)
1045}
1046
1047#[inline(always)]
1048fn scomp32(x: u64, y: u64, op: impl FnOnce(i32, i32) -> bool) -> bool {
1049 op(x as i32, y as i32)
1050}