@@ -31,6 +31,7 @@ use crate::{
31
31
allocate_pages, free_pages, get_system_page_size, protect_pages, round_to_page_size,
32
32
} ,
33
33
memory_region:: { AccessType , MemoryMapping } ,
34
+ program:: BuiltinFunction ,
34
35
vm:: { get_runtime_environment_key, Config , ContextObject , EbpfVm } ,
35
36
x86:: * ,
36
37
} ;
@@ -705,48 +706,36 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> {
705
706
ebpf:: JSLT_REG => self . emit_conditional_branch_reg ( 0x8c , false , src, dst, target_pc) ,
706
707
ebpf:: JSLE_IMM => self . emit_conditional_branch_imm ( 0x8e , false , insn. imm , dst, target_pc) ,
707
708
ebpf:: JSLE_REG => self . emit_conditional_branch_reg ( 0x8e , false , src, dst, target_pc) ,
708
- ebpf:: CALL_IMM | ebpf:: SYSCALL
709
- if insn. opc == ebpf:: CALL_IMM || self . executable . get_sbpf_version ( ) . static_syscalls ( ) => {
709
+ ebpf:: CALL_IMM => {
710
710
// For JIT, external functions MUST be registered at compile time.
711
-
712
- let mut resolved = false ;
713
- let ( external, internal) = if self . executable . get_sbpf_version ( ) . static_syscalls ( ) {
714
- ( insn. src == 0 , insn. src != 0 )
715
- } else {
716
- ( true , true )
717
- } ;
718
-
719
- if external {
720
- if let Some ( ( _function_name, function) ) = self . executable . get_loader ( ) . get_function_registry ( self . executable . get_sbpf_version ( ) ) . lookup_by_key ( insn. imm as u32 ) {
721
- self . emit_validate_and_profile_instruction_count ( false , Some ( 0 ) ) ;
722
- self . emit_ins ( X86Instruction :: load_immediate ( OperandSize :: S64 , REGISTER_SCRATCH , function as usize as i64 ) ) ;
723
- self . emit_ins ( X86Instruction :: call_immediate ( self . relative_to_anchor ( ANCHOR_EXTERNAL_FUNCTION_CALL , 5 ) ) ) ;
724
- self . emit_undo_profile_instruction_count ( 0 ) ;
725
- resolved = true ;
726
- }
727
- }
728
-
729
- if internal {
730
- if let Some ( ( _function_name, target_pc) ) =
711
+ if let ( false , Some ( ( _, function) ) ) =
712
+ ( self . executable . get_sbpf_version ( ) . static_syscalls ( ) ,
713
+ self . executable . get_loader ( ) . get_function_registry ( self . executable . get_sbpf_version ( ) ) . lookup_by_key ( insn. imm as u32 ) ) {
714
+ // SBPFv1 syscall
715
+ self . emit_syscall_dispatch ( function) ;
716
+ } else if let Some ( ( _function_name, target_pc) ) =
731
717
self . executable
732
718
. get_function_registry ( )
733
719
. lookup_by_key (
734
720
self
735
721
. executable
736
722
. get_sbpf_version ( )
737
723
. calculate_call_imm_target_pc ( self . pc , insn. imm )
738
- )
739
- {
740
- self . emit_internal_call ( Value :: Constant64 ( target_pc as i64 , true ) ) ;
741
- resolved = true ;
742
- }
743
- }
744
-
745
- if !resolved {
724
+ ) {
725
+ // BPF to BPF call
726
+ self . emit_internal_call ( Value :: Constant64 ( target_pc as i64 , true ) ) ;
727
+ } else {
746
728
self . emit_ins ( X86Instruction :: load_immediate ( OperandSize :: S64 , REGISTER_SCRATCH , self . pc as i64 ) ) ;
747
729
self . emit_ins ( X86Instruction :: jump_immediate ( self . relative_to_anchor ( ANCHOR_CALL_UNSUPPORTED_INSTRUCTION , 5 ) ) ) ;
748
730
}
749
731
} ,
732
+ ebpf:: SYSCALL if self . executable . get_sbpf_version ( ) . static_syscalls ( ) => {
733
+ if let Some ( ( _, function) ) = self . executable . get_loader ( ) . get_function_registry ( self . executable . get_sbpf_version ( ) ) . lookup_by_key ( insn. imm as u32 ) {
734
+ self . emit_syscall_dispatch ( function) ;
735
+ } else {
736
+ debug_assert ! ( false , "Invalid syscall should have been detected in the verifier." )
737
+ }
738
+ } ,
750
739
ebpf:: CALL_REG => {
751
740
let target_pc = if self . executable . get_sbpf_version ( ) . callx_uses_src_reg ( ) {
752
741
src
@@ -1144,6 +1133,14 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> {
1144
1133
}
1145
1134
}
1146
1135
1136
+ #[ inline]
1137
+ fn emit_syscall_dispatch ( & mut self , function : BuiltinFunction < C > ) {
1138
+ self . emit_validate_and_profile_instruction_count ( false , Some ( 0 ) ) ;
1139
+ self . emit_ins ( X86Instruction :: load_immediate ( OperandSize :: S64 , REGISTER_SCRATCH , function as usize as i64 ) ) ;
1140
+ self . emit_ins ( X86Instruction :: call_immediate ( self . relative_to_anchor ( ANCHOR_EXTERNAL_FUNCTION_CALL , 5 ) ) ) ;
1141
+ self . emit_undo_profile_instruction_count ( 0 ) ;
1142
+ }
1143
+
1147
1144
#[ inline]
1148
1145
fn emit_address_translation ( & mut self , dst : Option < u8 > , vm_addr : Value , len : u64 , value : Option < Value > ) {
1149
1146
debug_assert_ne ! ( dst. is_some( ) , value. is_some( ) ) ;
@@ -1705,7 +1702,7 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> {
1705
1702
mod tests {
1706
1703
use super :: * ;
1707
1704
use crate :: {
1708
- program:: { BuiltinFunction , BuiltinProgram , FunctionRegistry , SBPFVersion } ,
1705
+ program:: { BuiltinProgram , FunctionRegistry , SBPFVersion } ,
1709
1706
syscalls,
1710
1707
vm:: TestContextObject ,
1711
1708
} ;
@@ -1752,12 +1749,10 @@ mod tests {
1752
1749
1753
1750
fn create_mockup_executable ( config : Config , program : & [ u8 ] ) -> Executable < TestContextObject > {
1754
1751
let sbpf_version = * config. enabled_sbpf_versions . end ( ) ;
1755
- let mut function_registry =
1756
- FunctionRegistry :: < BuiltinFunction < TestContextObject > > :: default ( ) ;
1757
- function_registry
1758
- . register_function_hashed ( * b"gather_bytes" , syscalls:: SyscallGatherBytes :: vm)
1752
+ let mut loader = BuiltinProgram :: new_loader_with_dense_registration ( config) ;
1753
+ loader
1754
+ . register_function ( "gather_bytes" , 1 , syscalls:: SyscallGatherBytes :: vm)
1759
1755
. unwrap ( ) ;
1760
- let loader = BuiltinProgram :: new_loader ( config, function_registry) ;
1761
1756
let mut function_registry = FunctionRegistry :: default ( ) ;
1762
1757
function_registry
1763
1758
. register_function ( 8 , * b"function_foo" , 8 )
@@ -1844,6 +1839,10 @@ mod tests {
1844
1839
opcode = 0x85 ;
1845
1840
( 0x88 , 0x91020CDD )
1846
1841
}
1842
+ 0x95 => {
1843
+ // Put a valid syscall
1844
+ ( 0 , 1 )
1845
+ }
1847
1846
0xD4 | 0xDC => ( 0x88 , 16 ) ,
1848
1847
_ => ( 0x88 , 0xFFFFFFFF ) ,
1849
1848
} ;
0 commit comments