4242#include "decode.h"
4343#include "io.h"
4444#include "jit.h"
45+ #include "log.h"
4546#include "riscv.h"
4647#include "riscv_private.h"
4748#include "utils.h"
@@ -593,24 +594,30 @@ static void update_branch_imm(struct jit_state *state,
593594 assert ((imm & 3 ) == 0 );
594595 uint32_t insn ;
595596 imm >>= 2 ;
597+ rv_log_debug ("JIT: Patching branch at offset=%u, imm=%d" , offset , imm * 4 );
598+ /* Read instruction while in execute mode (MAP_JIT requirement) */
596599 memcpy (& insn , state -> buf + offset , sizeof (uint32_t ));
597600 if ((insn & 0xfe000000U ) == 0x54000000U /* Conditional branch immediate. */
598601 || (insn & 0x7e000000U ) ==
599602 0x34000000U ) { /* Compare and branch immediate. */
600603 assert ((imm >> 19 ) == INT64_C (-1 ) || (imm >> 19 ) == 0 );
604+ insn &= ~(0x7ffffU << 5 ); /* Clear old offset bits */
601605 insn |= (imm & 0x7ffff ) << 5 ;
602606 } else if ((insn & 0x7c000000U ) == 0x14000000U ) {
603607 /* Unconditional branch immediate. */
604608 assert ((imm >> 26 ) == INT64_C (-1 ) || (imm >> 26 ) == 0 );
609+ insn &= ~0x03ffffffU ; /* Clear old offset bits */
605610 insn |= (imm & 0x03ffffffU ) << 0 ;
606611 } else {
607612 assert (false);
608613 insn = BAD_OPCODE ;
609614 }
610615#if defined(__APPLE__ ) && defined(__aarch64__ )
616+ /* Switch to write mode only for writing */
611617 pthread_jit_write_protect_np (false);
612618#endif
613619 memcpy (state -> buf + offset , & insn , sizeof (uint32_t ));
620+ sys_icache_invalidate (state -> buf + offset , sizeof (uint32_t ));
614621#if defined(__APPLE__ ) && defined(__aarch64__ )
615622 pthread_jit_write_protect_np (true);
616623#endif
@@ -2164,9 +2171,12 @@ void clear_hot(block_t *block)
21642171
21652172static void code_cache_flush (struct jit_state * state , riscv_t * rv )
21662173{
2174+ rv_log_info ("JIT: Flushing code cache (n_blocks=%d, n_jumps=%d, offset=%u)" ,
2175+ state -> n_blocks , state -> n_jumps , state -> offset );
21672176 should_flush = false;
21682177 state -> offset = state -> org_size ;
21692178 state -> n_blocks = 0 ;
2179+ state -> n_jumps = 0 ; /* Reset jump count when flushing */
21702180 set_reset (& state -> set );
21712181 clear_cache_hot (rv -> block_cache , (clear_func_t ) clear_hot );
21722182#if RV32_HAS (T2C )
@@ -2196,6 +2206,7 @@ static void translate(struct jit_state *state, riscv_t *rv, block_t *block)
21962206
21972207static void resolve_jumps (struct jit_state * state )
21982208{
2209+ rv_log_debug ("JIT: Resolving %d jumps" , state -> n_jumps );
21992210 for (int i = 0 ; i < state -> n_jumps ; i ++ ) {
22002211 struct jump jump = state -> jumps [i ];
22012212 int target_loc ;
@@ -2218,6 +2229,10 @@ static void resolve_jumps(struct jit_state *state)
22182229 (if (jump .target_satp == state -> offset_map [i ].satp ), )
22192230 {
22202231 target_loc = state -> offset_map [i ].offset ;
2232+ rv_log_debug (
2233+ "JIT: Jump %d resolved to block pc=0x%08x, "
2234+ "offset=%d" ,
2235+ i , jump .target_pc , target_loc );
22212236 break ;
22222237 }
22232238 }
@@ -2229,6 +2244,7 @@ static void resolve_jumps(struct jit_state *state)
22292244
22302245 uint8_t * offset_ptr = & state -> buf [jump .offset_loc ];
22312246 memcpy (offset_ptr , & rel , sizeof (uint32_t ));
2247+ sys_icache_invalidate (offset_ptr , sizeof (uint32_t ));
22322248#elif defined(__aarch64__)
22332249 int32_t rel = target_loc - jump .offset_loc ;
22342250 update_branch_imm (state , jump .offset_loc , rel );
@@ -2308,23 +2324,35 @@ void jit_translate(riscv_t *rv, block_t *block)
23082324 ) {
23092325 block -> offset = state -> offset_map [i ].offset ;
23102326 block -> hot = true;
2327+ rv_log_debug ("JIT: Cache hit for block pc=0x%08x, offset=%u" ,
2328+ block -> pc_start , block -> offset );
23112329 return ;
23122330 }
23132331 }
23142332 assert (NULL );
23152333 __UNREACHABLE ;
23162334 }
2335+ rv_log_debug ("JIT: Starting translation for block pc=0x%08x" ,
2336+ block -> pc_start );
23172337restart :
23182338 memset (state -> jumps , 0 , MAX_JUMPS * sizeof (struct jump ));
23192339 state -> n_jumps = 0 ;
23202340 block -> offset = state -> offset ;
23212341 translate_chained_block (state , rv , block );
23222342 if (unlikely (should_flush )) {
2343+ /* Mark block as not translated since translation was incomplete */
2344+ block -> hot = false;
2345+ /* Don't reset offset - it will be set correctly on restart */
2346+ rv_log_debug ("JIT: Translation triggered flush for block pc=0x%08x" ,
2347+ block -> pc_start );
23232348 code_cache_flush (state , rv );
23242349 goto restart ;
23252350 }
23262351 resolve_jumps (state );
23272352 block -> hot = true;
2353+ rv_log_debug (
2354+ "JIT: Translation completed for block pc=0x%08x, offset=%u, size=%u" ,
2355+ block -> pc_start , block -> offset , state -> offset - block -> offset );
23282356}
23292357
23302358struct jit_state * jit_state_init (size_t size )
@@ -2336,10 +2364,12 @@ struct jit_state *jit_state_init(size_t size)
23362364
23372365 state -> offset = 0 ;
23382366 state -> size = size ;
2339- #if defined(TSAN_ENABLED ) && defined( __x86_64__ )
2367+ #if defined(TSAN_ENABLED )
23402368 /* ThreadSanitizer compatibility: Allocate JIT code buffer at a fixed
23412369 * address above the main memory region to avoid conflicts.
2342- *
2370+ */
2371+ #if defined(__x86_64__ )
2372+ /* x86_64 memory layout:
23432373 * Main memory: 0x7d0000000000 - 0x7d0100000000 (4GB for FULL4G)
23442374 * JIT buffer: 0x7d1000000000 + size
23452375 *
@@ -2348,7 +2378,32 @@ struct jit_state *jit_state_init(size_t size)
23482378 */
23492379 void * jit_addr = (void * ) 0x7d1000000000UL ;
23502380 state -> buf = mmap (jit_addr , size , PROT_READ | PROT_WRITE | PROT_EXEC ,
2351- MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED , -1 , 0 );
2381+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED
2382+ #if defined(__APPLE__ )
2383+ | MAP_JIT
2384+ #endif
2385+ ,
2386+ -1 , 0 );
2387+ #elif defined(__aarch64__ )
2388+ /* ARM64 memory layout (macOS/Apple Silicon):
2389+ * Main memory: 0x150000000000 - 0x150100000000 (4GB for FULL4G)
2390+ * JIT buffer: 0x151000000000 + size
2391+ *
2392+ * Apple Silicon requires MAP_JIT for executable memory. The fixed
2393+ * address is chosen to avoid TSAN's shadow memory and typical process
2394+ * allocations. Requires ASLR disabled via: setarch $(uname -m) -R
2395+ */
2396+ void * jit_addr = (void * ) 0x151000000000UL ;
2397+ state -> buf = mmap (jit_addr , size , PROT_READ | PROT_WRITE | PROT_EXEC ,
2398+ MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED
2399+ #if defined(__APPLE__ )
2400+ | MAP_JIT
2401+ #endif
2402+ ,
2403+ -1 , 0 );
2404+ #else
2405+ #error "TSAN is only supported on x86_64 and aarch64"
2406+ #endif
23522407 if (state -> buf == MAP_FAILED ) {
23532408 free (state );
23542409 return NULL ;
0 commit comments