cpu.c (4058B)
1 /* CPUState: per-thread guest register/trap/memory-base record. Lifted blocks 2 * and runtime helpers access it through explicit helper calls; the host address 3 * is exposed to the JIT linker by emu_runtime_extern_resolver. */ 4 5 #include <string.h> 6 7 #include "emu/emu.h" 8 9 /* ---- Guest-AS shape (set by executable loader) ---- 10 * The CPU owns no memory storage. It only holds a borrowed pointer to the 11 * process address space; sparse VM translation lives in image.c. */ 12 13 struct EmuCPUState { 14 Compiler* c; 15 KitArchKind arch; 16 EmuThread* thread; 17 u64 pc; 18 EmuTrapReason trap; 19 int exit_code; 20 21 EmuAddrSpace* addr_space; 22 void* arch_state; 23 size_t arch_state_size; 24 size_t arch_state_align; 25 }; 26 27 EmuCPUState* emu_cpu_new_with_arch_state(Compiler* c, KitArchKind arch, 28 u64 initial_pc, size_t arch_state_size, 29 size_t arch_state_align) { 30 Heap* h; 31 EmuCPUState* s; 32 if (!c) return NULL; 33 h = c->ctx->heap; 34 s = (EmuCPUState*)h->alloc(h, sizeof(*s), _Alignof(EmuCPUState)); 35 if (!s) return NULL; 36 memset(s, 0, sizeof(*s)); 37 s->c = c; 38 s->arch = arch; 39 s->pc = initial_pc; 40 s->trap = EMU_TRAP_NONE; 41 s->arch_state_size = arch_state_size; 42 s->arch_state_align = arch_state_align ? arch_state_align : _Alignof(u64); 43 if (arch_state_size) { 44 s->arch_state = h->alloc(h, arch_state_size, s->arch_state_align); 45 if (!s->arch_state) { 46 h->free(h, s, sizeof(*s)); 47 return NULL; 48 } 49 memset(s->arch_state, 0, arch_state_size); 50 } 51 return s; 52 } 53 54 void emu_cpu_free(EmuCPUState* s) { 55 Heap* h; 56 if (!s) return; 57 h = s->c->ctx->heap; 58 if (s->arch_state) h->free(h, s->arch_state, s->arch_state_size); 59 h->free(h, s, sizeof(*s)); 60 } 61 62 void* emu_cpu_arch_state(EmuCPUState* s) { return s ? s->arch_state : NULL; } 63 64 void emu_cpu_set_thread(EmuCPUState* s, EmuThread* thread) { 65 if (s) s->thread = thread; 66 } 67 68 EmuThread* emu_cpu_thread(const EmuCPUState* s) { return s ? s->thread : NULL; } 69 70 u64 emu_cpu_pc(const EmuCPUState* s) { return s ? s->pc : 0; } 71 72 void emu_cpu_set_pc(EmuCPUState* s, u64 pc) { 73 if (s) s->pc = pc; 74 } 75 76 EmuTrapReason emu_cpu_trap_reason(const EmuCPUState* s) { 77 return s ? s->trap : EMU_TRAP_NONE; 78 } 79 80 int emu_cpu_exit_code(const EmuCPUState* s) { return s ? s->exit_code : 0; } 81 82 /* ---- Guest-memory window plumbing ---- */ 83 84 void emu_cpu_attach_addr_space(EmuCPUState* s, EmuAddrSpace* as) { 85 if (!s) return; 86 s->addr_space = as; 87 } 88 89 u8* emu_cpu_va_to_host_perm(EmuCPUState* s, u64 va, u64 nbytes, u8 need_perms) { 90 if (!s || !s->addr_space) return NULL; 91 return emu_addr_space_ptr(s->addr_space, va, nbytes, need_perms); 92 } 93 94 u64 emu_cpu_brk_cur(const EmuCPUState* s) { 95 return s && s->addr_space ? s->addr_space->brk_cur : 0; 96 } 97 u64 emu_cpu_brk_max(const EmuCPUState* s) { 98 return s && s->addr_space ? s->addr_space->brk_max : 0; 99 } 100 void emu_cpu_set_brk_cur(EmuCPUState* s, u64 v) { 101 if (s && s->addr_space) s->addr_space->brk_cur = v; 102 } 103 104 void emu_cpu_trap_exit(EmuCPUState* s, int code) { 105 if (!s) return; 106 s->trap = EMU_TRAP_EXIT; 107 s->exit_code = code; 108 } 109 void emu_cpu_trap_fault(EmuCPUState* s) { 110 if (!s) return; 111 s->trap = EMU_TRAP_FAULT; 112 } 113 void emu_cpu_clear_trap(EmuCPUState* s) { 114 if (!s) return; 115 s->trap = EMU_TRAP_NONE; 116 s->exit_code = 0; 117 } 118 119 EmuCPUState* emu_thread_cpu(EmuThread* t) { return t ? t->cpu : NULL; } 120 121 KitCgTypeId emu_thread_type(Compiler* c) { 122 return kit_cg_type_ptr( 123 (KitCompiler*)c, 124 kit_cg_builtin_types((KitCompiler*)c).id[KIT_CG_BUILTIN_VOID], 0); 125 } 126 127 KitCgTypeId emu_block_fn_type(Compiler* c) { 128 KitCgBuiltinTypes bi; 129 KitCgFuncParam param; 130 KitCgFuncResult result; 131 KitCgFuncSig sig; 132 bi = kit_cg_builtin_types((KitCompiler*)c); 133 memset(¶m, 0, sizeof(param)); 134 param.type = emu_thread_type(c); 135 memset(&sig, 0, sizeof(sig)); 136 memset(&result, 0, sizeof(result)); 137 result.type = bi.id[KIT_CG_BUILTIN_I64]; 138 sig.result = result; 139 sig.params = ¶m; 140 sig.nparams = 1; 141 sig.call_conv = KIT_CG_CC_TARGET_C; 142 return kit_cg_type_func((KitCompiler*)c, sig); 143 }