@@ -1114,8 +1114,11 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> {
11141114
11151115 match dst {
11161116 Value :: Register ( reg) => {
1117- // Move guest_target_address into REGISTER_MAP[FRAME_PTR_REG]
1118- self . emit_ins ( X86Instruction :: mov ( OperandSize :: S64 , reg, REGISTER_MAP [ FRAME_PTR_REG ] ) ) ;
1117+ // REGISTER_SCRATCH contains self.pc, and we must store it for proper error handling.
1118+ // We can discard the value if callx succeeds, so we are not incrementing the stack pointer (RSP).
1119+ self . emit_ins ( X86Instruction :: store ( OperandSize :: S64 , REGISTER_SCRATCH , RSP , X86IndirectAccess :: OffsetIndexShift ( -24 , RSP , 0 ) ) ) ;
1120+ // Move guest_target_address into REGISTER_SCRATCH
1121+ self . emit_ins ( X86Instruction :: mov ( OperandSize :: S64 , reg, REGISTER_SCRATCH ) ) ;
11191122 self . emit_ins ( X86Instruction :: call_immediate ( self . relative_to_anchor ( ANCHOR_INTERNAL_FUNCTION_CALL_REG , 5 ) ) ) ;
11201123 } ,
11211124 Value :: Constant64 ( target_pc, user_provided) => {
@@ -1477,6 +1480,7 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> {
14771480 // Handler for EbpfError::CallOutsideTextSegment
14781481 self . set_anchor ( ANCHOR_CALL_OUTSIDE_TEXT_SEGMENT ) ;
14791482 self . emit_set_exception_kind ( EbpfError :: CallOutsideTextSegment ) ;
1483+ self . emit_ins ( X86Instruction :: load ( OperandSize :: S64 , RSP , REGISTER_SCRATCH , X86IndirectAccess :: OffsetIndexShift ( -8 , RSP , 0 ) ) ) ;
14801484 self . emit_ins ( X86Instruction :: jump_immediate ( self . relative_to_anchor ( ANCHOR_THROW_EXCEPTION , 5 ) ) ) ;
14811485
14821486 // Handler for EbpfError::DivideByZero
@@ -1556,43 +1560,35 @@ impl<'a, C: ContextObject> JitCompiler<'a, C> {
15561560 self . emit_ins ( X86Instruction :: return_near ( ) ) ;
15571561
15581562 // Routine for emit_internal_call(Value::Register())
1559- // Inputs: Guest current pc in REGISTER_SCRATCH, Guest target address in REGISTER_MAP[FRAME_PTR_REG]
1560- // Outputs: Guest target pc in REGISTER_SCRATCH, Host target address in RIP
1563+ // Inputs: Guest current pc in X86IndirectAccess::OffsetIndexShift(-16, RSP, 0), Guest target address in REGISTER_SCRATCH
1564+ // Outputs: Guest current pc in X86IndirectAccess::OffsetIndexShift(-16, RSP, 0), Guest target pc in REGISTER_SCRATCH, Host target address in RIP
15611565 self . set_anchor ( ANCHOR_INTERNAL_FUNCTION_CALL_REG ) ;
15621566 self . emit_ins ( X86Instruction :: push ( REGISTER_MAP [ 0 ] , None ) ) ;
1563- // REGISTER_SCRATCH contains the current program counter, and we must store it for proper
1564- // error handling. We can discard the value if callx succeeds, so we are not incrementing
1565- // the stack pointer (RSP).
1566- self . emit_ins ( X86Instruction :: store ( OperandSize :: S64 , REGISTER_SCRATCH , RSP , X86IndirectAccess :: OffsetIndexShift ( -8 , RSP , 0 ) ) ) ;
1567- self . emit_ins ( X86Instruction :: mov ( OperandSize :: S64 , REGISTER_MAP [ FRAME_PTR_REG ] , REGISTER_MAP [ 0 ] ) ) ;
15681567 // Calculate offset relative to program_vm_addr
1569- self . emit_ins ( X86Instruction :: load_immediate ( OperandSize :: S64 , REGISTER_MAP [ FRAME_PTR_REG ] , self . program_vm_addr as i64 ) ) ;
1570- self . emit_ins ( X86Instruction :: alu ( OperandSize :: S64 , 0x29 , REGISTER_MAP [ FRAME_PTR_REG ] , REGISTER_MAP [ 0 ] , 0 , None ) ) ; // guest_target_address -= self.program_vm_addr;
1568+ self . emit_ins ( X86Instruction :: load_immediate ( OperandSize :: S64 , REGISTER_MAP [ 0 ] , self . program_vm_addr as i64 ) ) ;
1569+ self . emit_ins ( X86Instruction :: alu ( OperandSize :: S64 , 0x29 , REGISTER_MAP [ 0 ] , REGISTER_SCRATCH , 0 , None ) ) ; // guest_target_address -= self.program_vm_addr;
15711570 // Force alignment of guest_target_address
1572- self . emit_ins ( X86Instruction :: alu ( OperandSize :: S64 , 0x81 , 4 , REGISTER_MAP [ 0 ] , !( INSN_SIZE as i64 - 1 ) , None ) ) ; // guest_target_address &= !(INSN_SIZE - 1);
1571+ self . emit_ins ( X86Instruction :: alu ( OperandSize :: S64 , 0x81 , 4 , REGISTER_SCRATCH , !( INSN_SIZE as i64 - 1 ) , None ) ) ; // guest_target_address &= !(INSN_SIZE - 1);
15731572 // Bound check
15741573 // if(guest_target_address >= number_of_instructions * INSN_SIZE) throw CALL_OUTSIDE_TEXT_SEGMENT;
15751574 let number_of_instructions = self . result . pc_section . len ( ) ;
1576- self . emit_ins ( X86Instruction :: cmp_immediate ( OperandSize :: S64 , REGISTER_MAP [ 0 ] , ( number_of_instructions * INSN_SIZE ) as i64 , None ) ) ; // guest_target_address.cmp(number_of_instructions * INSN_SIZE)
1575+ self . emit_ins ( X86Instruction :: cmp_immediate ( OperandSize :: S64 , REGISTER_SCRATCH , ( number_of_instructions * INSN_SIZE ) as i64 , None ) ) ; // guest_target_address.cmp(number_of_instructions * INSN_SIZE)
15771576 self . emit_ins ( X86Instruction :: conditional_jump_immediate ( 0x83 , self . relative_to_anchor ( ANCHOR_CALL_OUTSIDE_TEXT_SEGMENT , 6 ) ) ) ;
15781577 // First half of self.emit_profile_instruction_count(false, None);
1579- self . emit_ins ( X86Instruction :: alu ( OperandSize :: S64 , 0x29 , REGISTER_SCRATCH , REGISTER_INSTRUCTION_METER , 0 , None ) ) ; // instruction_meter -= guest_current_pc;
1578+ self . emit_ins ( X86Instruction :: alu ( OperandSize :: S64 , 0x2b , REGISTER_INSTRUCTION_METER , RSP , 0 , Some ( X86IndirectAccess :: OffsetIndexShift ( - 8 , RSP , 0 ) ) ) ) ; // instruction_meter -= guest_current_pc;
15801579 self . emit_ins ( X86Instruction :: alu ( OperandSize :: S64 , 0x81 , 5 , REGISTER_INSTRUCTION_METER , 1 , None ) ) ; // instruction_meter -= 1;
1581- // Calculate the target_pc (dst / INSN_SIZE) to update REGISTER_INSTRUCTION_METER
1582- // and as target pc for potential ANCHOR_CALL_UNSUPPORTED_INSTRUCTION
1580+ // Load host target_address from self.result.pc_section
1581+ debug_assert_eq ! ( INSN_SIZE , 8 ) ; // Because the instruction size is also the slot size we do not need to shift the offset
1582+ self . emit_ins ( X86Instruction :: load_immediate ( OperandSize :: S64 , REGISTER_MAP [ 0 ] , self . result . pc_section . as_ptr ( ) as i64 ) ) ; // host_target_address = self.result.pc_section;
1583+ self . emit_ins ( X86Instruction :: alu ( OperandSize :: S64 , 0x01 , REGISTER_SCRATCH , REGISTER_MAP [ 0 ] , 0 , None ) ) ; // host_target_address += guest_target_address;
1584+ self . emit_ins ( X86Instruction :: load ( OperandSize :: S64 , REGISTER_MAP [ 0 ] , REGISTER_MAP [ 0 ] , X86IndirectAccess :: Offset ( 0 ) ) ) ; // host_target_address = self.result.pc_section[host_target_address / 8];
1585+ // Calculate the guest_target_pc (dst / INSN_SIZE) to update REGISTER_INSTRUCTION_METER
1586+ // and as target_pc for potential ANCHOR_CALL_UNSUPPORTED_INSTRUCTION
15831587 let shift_amount = INSN_SIZE . trailing_zeros ( ) ;
15841588 debug_assert_eq ! ( INSN_SIZE , 1 << shift_amount) ;
1585- self . emit_ins ( X86Instruction :: mov ( OperandSize :: S64 , REGISTER_MAP [ 0 ] , REGISTER_SCRATCH ) ) ; // guest_target_pc = guest_target_address;
15861589 self . emit_ins ( X86Instruction :: alu ( OperandSize :: S64 , 0xc1 , 5 , REGISTER_SCRATCH , shift_amount as i64 , None ) ) ; // guest_target_pc /= INSN_SIZE;
15871590 // Second half of self.emit_profile_instruction_count(false, None);
15881591 self . emit_ins ( X86Instruction :: alu ( OperandSize :: S64 , 0x01 , REGISTER_SCRATCH , REGISTER_INSTRUCTION_METER , 0 , None ) ) ; // instruction_meter += guest_target_pc;
1589- // Load host target_address from self.result.pc_section
1590- debug_assert_eq ! ( INSN_SIZE , 8 ) ; // Because the instruction size is also the slot size we do not need to shift the offset
1591- self . emit_ins ( X86Instruction :: load_immediate ( OperandSize :: S64 , REGISTER_MAP [ FRAME_PTR_REG ] , self . result . pc_section . as_ptr ( ) as i64 ) ) ;
1592- self . emit_ins ( X86Instruction :: alu ( OperandSize :: S64 , 0x01 , REGISTER_MAP [ FRAME_PTR_REG ] , REGISTER_MAP [ 0 ] , 0 , None ) ) ; // host_target_address = guest_target_address + self.result.pc_section;
1593- self . emit_ins ( X86Instruction :: load ( OperandSize :: S64 , REGISTER_MAP [ 0 ] , REGISTER_MAP [ 0 ] , X86IndirectAccess :: Offset ( 0 ) ) ) ; // host_target_address = self.result.pc_section[host_target_address / 8];
1594- // Load the frame pointer again since we've clobbered REGISTER_MAP[FRAME_PTR_REG]
1595- self . emit_ins ( X86Instruction :: load ( OperandSize :: S64 , REGISTER_PTR_TO_VM , REGISTER_MAP [ FRAME_PTR_REG ] , stack_pointer_access) ) ;
15961592 // Restore the clobbered REGISTER_MAP[0]
15971593 self . emit_ins ( X86Instruction :: xchg ( OperandSize :: S64 , REGISTER_MAP [ 0 ] , RSP , Some ( X86IndirectAccess :: OffsetIndexShift ( 0 , RSP , 0 ) ) ) ) ; // Swap REGISTER_MAP[0] and host_target_address
15981594 self . emit_ins ( X86Instruction :: return_near ( ) ) ; // Tail call to host_target_address
0 commit comments