kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

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(&param, 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 = &param;
    140   sig.nparams = 1;
    141   sig.call_conv = KIT_CG_CC_TARGET_C;
    142   return kit_cg_type_func((KitCompiler*)c, sig);
    143 }