Annotation of cf/mips64_jit.c, revision 1.1.1.13

1.1       root        1: /*
1.1.1.9   root        2:  * Cisco router simulation platform.
1.1       root        3:  * Copyright (c) 2005,2006 Christophe Fillot ([email protected])
                      4:  *
                      5:  * MIPS64 JIT compiler.
                      6:  */
                      7: 
                      8: #include <stdio.h>
                      9: #include <stdlib.h>
                     10: #include <unistd.h>
                     11: #include <string.h>
                     12: #include <sys/types.h>
                     13: #include <sys/stat.h>
                     14: #include <sys/mman.h>
                     15: #include <signal.h>
                     16: #include <fcntl.h>
                     17: #include <assert.h>
                     18: 
1.1.1.10  root       19: #include "sbox.h"
1.1       root       20: #include "cpu.h"
                     21: #include "device.h"
1.1.1.13! root       22: #include "tcb.h"
1.1.1.4   root       23: #include "mips64.h"
1.1.1.9   root       24: #include "mips64_cp0.h"
1.1       root       25: #include "mips64_exec.h"
1.1.1.9   root       26: #include "mips64_jit.h"
1.1       root       27: #include "insn_lookup.h"
1.1.1.9   root       28: #include "memory.h"
1.1       root       29: #include "ptask.h"
                     30: 
1.1.1.9   root       31: #include MIPS64_ARCH_INC_FILE
                     32: 
1.1.1.13! root       33: #define DEBUG_JIT_SHARED  0
        !            34: 
1.1       root       35: #if DEBUG_BLOCK_TIMESTAMP
                     36: static volatile m_uint64_t jit_jiffies = 0;
                     37: #endif
                     38: 
                     39: /* MIPS jump instructions for block scan */
1.1.1.9   root       40: struct mips64_insn_jump mips64_insn_jumps[] = {
1.1       root       41:    { "b"       , 0xffff0000, 0x10000000, 16, 1 },
                     42:    { "bal"     , 0xffff0000, 0x04110000, 16, 1 },
                     43:    { "beq"     , 0xfc000000, 0x10000000, 16, 1 },
                     44:    { "beql"    , 0xfc000000, 0x50000000, 16, 1 },
                     45:    { "bgez"    , 0xfc1f0000, 0x04010000, 16, 1 },
                     46:    { "bgezl"   , 0xfc1f0000, 0x04030000, 16, 1 },
                     47:    { "bgezal"  , 0xfc1f0000, 0x04110000, 16, 1 },
                     48:    { "bgezall" , 0xfc1f0000, 0x04130000, 16, 1 },
                     49:    { "bgtz"    , 0xfc1f0000, 0x1c000000, 16, 1 },
                     50:    { "bgtzl"   , 0xfc1f0000, 0x5c000000, 16, 1 },
                     51:    { "blez"    , 0xfc1f0000, 0x18000000, 16, 1 },
                     52:    { "blezl"   , 0xfc1f0000, 0x58000000, 16, 1 },
                     53:    { "bltz"    , 0xfc1f0000, 0x04000000, 16, 1 },
                     54:    { "bltzl"   , 0xfc1f0000, 0x04020000, 16, 1 },
                     55:    { "bltzal"  , 0xfc1f0000, 0x04100000, 16, 1 },
                     56:    { "bltzall" , 0xfc1f0000, 0x04120000, 16, 1 },
                     57:    { "bne"     , 0xfc000000, 0x14000000, 16, 1 },
                     58:    { "bnel"    , 0xfc000000, 0x54000000, 16, 1 },
                     59:    { "j"       , 0xfc000000, 0x08000000, 26, 0 },
                     60:    { NULL      , 0x00000000, 0x00000000,  0, 0 },
                     61: };
                     62: 
                     63: /* Instruction Lookup Table */
                     64: static insn_lookup_t *ilt = NULL;
                     65: 
                     66: static void *mips64_jit_get_insn(int index)
                     67: {
                     68:    return(&mips64_insn_tags[index]);
                     69: }
                     70: 
1.1.1.9   root       71: static int mips64_jit_chk_lo(struct mips64_insn_tag *tag,int value)
1.1       root       72: {
                     73:    return((value & tag->mask) == (tag->value & 0xFFFF));
                     74: }
                     75: 
1.1.1.9   root       76: static int mips64_jit_chk_hi(struct mips64_insn_tag *tag,int value)
1.1       root       77: {
                     78:    return((value & (tag->mask >> 16)) == (tag->value >> 16));
                     79: }
                     80: 
                     81: /* Initialize instruction lookup table */
                     82: void mips64_jit_create_ilt(void)
                     83: {
                     84:    int i,count;
                     85: 
                     86:    for(i=0,count=0;mips64_insn_tags[i].emit;i++)
                     87:       count++;
                     88: 
1.1.1.10  root       89:    ilt = ilt_create("mips64j",count,
1.1       root       90:                     (ilt_get_insn_cbk_t)mips64_jit_get_insn,
                     91:                     (ilt_check_cbk_t)mips64_jit_chk_lo,
                     92:                     (ilt_check_cbk_t)mips64_jit_chk_hi);
                     93: }
                     94: 
1.1.1.4   root       95: /* Initialize the JIT structure */
                     96: int mips64_jit_init(cpu_mips_t *cpu)
1.1.1.2   root       97: {
1.1.1.13! root       98:    if (tsg_bind_cpu(cpu->gen) == -1)
1.1.1.4   root       99:       return(-1);
1.1.1.2   root      100:    
1.1.1.13! root      101:    return(cpu_jit_init(cpu->gen,
        !           102:                        MIPS_JIT_VIRT_HASH_SIZE,
        !           103:                        MIPS_JIT_PHYS_HASH_SIZE));
1.1.1.2   root      104: }
                    105: 
1.1.1.4   root      106: /* Flush the JIT */
                    107: u_int mips64_jit_flush(cpu_mips_t *cpu,u_int threshold)
1.1.1.2   root      108: {
1.1.1.13! root      109:    /* TO FIX / ENHANCE */
        !           110:    return(tsg_remove_single_desc(cpu->gen));
1.1.1.4   root      111: }
                    112: 
                    113: /* Shutdown the JIT */
                    114: void mips64_jit_shutdown(cpu_mips_t *cpu)
1.1.1.2   root      115: {
1.1.1.13! root      116:    cpu_jit_shutdown(cpu->gen);
1.1.1.2   root      117: }
                    118: 
1.1       root      119: /* Find the JIT code emitter for the specified MIPS instruction */
1.1.1.9   root      120: static struct mips64_insn_tag *insn_tag_find(mips_insn_t ins)
1.1       root      121: {
1.1.1.9   root      122:    struct mips64_insn_tag *tag = NULL;
1.1       root      123:    int index;
                    124: 
                    125:    index = ilt_lookup(ilt,ins);
                    126:    tag = mips64_jit_get_insn(index);
                    127:    return tag;
                    128: }
                    129: 
                    130: /* Check if the specified MIPS instruction is a jump */
1.1.1.9   root      131: static struct mips64_insn_jump *insn_jump_find(mips_insn_t ins)
1.1       root      132: {
1.1.1.9   root      133:    struct mips64_insn_jump *jump = NULL;
1.1       root      134:    int i;
                    135: 
                    136:    for(i=0;mips64_insn_jumps[i].name;i++)
                    137:       if ((ins & mips64_insn_jumps[i].mask) == mips64_insn_jumps[i].value) {
                    138:          jump = &mips64_insn_jumps[i];
                    139:          break;
                    140:       }
                    141: 
                    142:    return(jump);
                    143: }
                    144: 
                    145: /* Fetch a MIPS instruction */
1.1.1.13! root      146: static forced_inline mips_insn_t insn_fetch(cpu_tc_t *tc)
1.1       root      147: {
1.1.1.13! root      148:    return(vmtoh32(((mips_insn_t *)tc->target_code)[tc->trans_pos]));
1.1       root      149: }
                    150: 
                    151: /* Emit a breakpoint if necessary */
1.1.1.4   root      152: #if BREAKPOINT_ENABLE
1.1.1.13! root      153: static void insn_emit_breakpoint(cpu_mips_t *cpu,cpu_tc_t *tc)
1.1       root      154: {
                    155:    m_uint64_t pc;
                    156:    int i;
                    157: 
1.1.1.13! root      158:    pc = tc->vaddr + ((tc->trans_pos-1) << 2);
1.1       root      159: 
                    160:    for(i=0;i<MIPS64_MAX_BREAKPOINTS;i++)
                    161:       if (pc == cpu->breakpoints[i]) {
1.1.1.13! root      162:          mips64_emit_breakpoint(tc);
1.1       root      163:          break;
                    164:       }
                    165: }
1.1.1.4   root      166: #endif /* BREAKPOINT_ENABLE */
1.1       root      167: 
1.1.1.10  root      168: /* Check if an instruction is in a delay slot or not */
1.1.1.13! root      169: int mips64_jit_is_delay_slot(cpu_tc_t *tc,m_uint64_t pc)
1.1.1.10  root      170: {   
                    171:    struct mips64_insn_tag *tag;
                    172:    m_uint32_t offset,insn;
                    173: 
1.1.1.13! root      174:    offset = (pc - tc->vaddr) >> 2;
1.1.1.10  root      175: 
                    176:    if (!offset)
                    177:       return(FALSE);
                    178: 
                    179:    /* Fetch the previous instruction to determine if it is a jump */
1.1.1.13! root      180:    insn = vmtoh32(((m_uint32_t *)tc->target_code)[offset-1]);
1.1.1.10  root      181:    tag = insn_tag_find(insn);
                    182:    assert(tag != NULL);
                    183:    return(!tag->delay_slot);
                    184: }
                    185: 
1.1       root      186: /* Fetch a MIPS instruction and emit corresponding translated code */
1.1.1.9   root      187: struct mips64_insn_tag *mips64_jit_fetch_and_emit(cpu_mips_t *cpu,
1.1.1.13! root      188:                                                   cpu_tc_t *tc,
1.1.1.9   root      189:                                                   int delay_slot)
1.1       root      190: {
1.1.1.9   root      191:    struct mips64_insn_tag *tag;
1.1       root      192:    mips_insn_t code;
                    193: 
1.1.1.13! root      194:    code = insn_fetch(tc);
1.1       root      195:    tag = insn_tag_find(code);
                    196:    assert(tag);
1.1.1.9   root      197: 
                    198:    /* Branch-delay slot is in another page: slow exec */
1.1.1.13! root      199:    if ((tc->trans_pos == (MIPS_INSN_PER_PAGE-1)) && !tag->delay_slot) {
        !           200:       tc->jit_insn_ptr[tc->trans_pos] = tc->jit_ptr;
1.1.1.9   root      201: 
1.1.1.13! root      202:       mips64_set_pc(tc,tc->vaddr + (tc->trans_pos << 2));
        !           203:       mips64_emit_single_step(tc,code); 
        !           204:       mips64_jit_tcb_push_epilog(tc);
        !           205:       tc->trans_pos++;
1.1.1.9   root      206:       return tag;
                    207:    }
                    208: 
1.1       root      209:    if (delay_slot && !tag->delay_slot) {
1.1.1.13! root      210:       mips64_emit_invalid_delay_slot(tc);
1.1       root      211:       return NULL;
                    212:    }
                    213: 
1.1.1.9   root      214:    if (!delay_slot)
1.1.1.13! root      215:       tc->jit_insn_ptr[tc->trans_pos] = tc->jit_ptr;
1.1       root      216: 
                    217:    if (delay_slot != 2)
1.1.1.13! root      218:       tc->trans_pos++;
1.1       root      219: 
1.1.1.8   root      220: #if DEBUG_INSN_PERF_CNT
1.1.1.13! root      221:    mips64_inc_perf_counter(tc);
1.1.1.4   root      222: #endif
1.1       root      223: 
1.1.1.4   root      224:    if (!delay_slot) {
                    225:       /* Check for IRQs + Increment count register before jumps */
                    226:       if (!tag->delay_slot) {
1.1.1.13! root      227:          mips64_inc_cp0_count_reg(tc);
        !           228:          mips64_check_pending_irq(tc);
1.1.1.4   root      229:       }
                    230:    }
1.1       root      231: 
1.1.1.3   root      232: #if BREAKPOINT_ENABLE
                    233:    if (cpu->breakpoints_enabled)
1.1.1.13! root      234:       insn_emit_breakpoint(cpu,tc);
1.1.1.3   root      235: #endif
                    236: 
1.1.1.13! root      237:    tag->emit(cpu,tc,code);
1.1       root      238:    return tag;
                    239: }
                    240: 
                    241: /* Add end of JIT block */
1.1.1.13! root      242: static void mips64_jit_tcb_add_end(cpu_tc_t *tc)
1.1       root      243: {
1.1.1.13! root      244:    mips64_set_pc(tc,tc->vaddr+(tc->trans_pos<<2));
        !           245:    mips64_jit_tcb_push_epilog(tc);
1.1       root      246: }
                    247: 
                    248: /* Record a patch to apply in a compiled block */
1.1.1.13! root      249: int mips64_jit_tcb_record_patch(cpu_mips_t *cpu,cpu_tc_t *tc,
        !           250:                                 u_char *jit_ptr,m_uint64_t vaddr)
1.1       root      251: {
1.1.1.13! root      252:    struct insn_patch *patch;
        !           253:    
        !           254:    patch = tc_record_patch(cpu->gen,tc,jit_ptr,vaddr);
        !           255:    return((patch != NULL) ? 0 : -1);
1.1       root      256: }
                    257: 
                    258: /* Apply all patches */
1.1.1.13! root      259: static int mips64_jit_tcb_apply_patches(cpu_mips_t *cpu,cpu_tc_t *tc)
1.1       root      260: {
1.1.1.13! root      261:    tc_apply_patches(tc,mips64_jit_tcb_set_patch);
1.1       root      262:    return(0);
                    263: }
                    264: 
                    265: /* Adjust the JIT buffer if its size is not sufficient */
1.1.1.13! root      266: static int mips64_jit_tcb_adjust_buffer(cpu_mips_t *cpu,cpu_tc_t *tc)
1.1       root      267: {
1.1.1.13! root      268:    return(tc_adjust_jit_buffer(cpu->gen,tc,mips64_jit_tcb_set_jump));
1.1       root      269: }
                    270: 
1.1.1.13! root      271: /* Produce translated code for a page. If this fails, use non-compiled mode */
        !           272: static cpu_tc_t *mips64_jit_tcb_translate(cpu_mips_t *cpu,cpu_tb_t *tb)
1.1       root      273: {
1.1.1.13! root      274:    struct mips64_insn_tag *tag;
        !           275:    cpu_tc_t *tc;
        !           276:    
        !           277:    /* The page is not shared, we have to compile it */
        !           278:    tc = tc_alloc(cpu->gen,tb->vaddr,tb->exec_state);
        !           279:    
        !           280:    if (tc == NULL)
        !           281:       return NULL;
        !           282:    
        !           283:    tc->target_code = tb->target_code;
        !           284:    tc->trans_pos   = 0;
        !           285:    
        !           286:    /* Emit native code for each instruction */
        !           287:    while(tc->trans_pos < MIPS_INSN_PER_PAGE)
        !           288:    {
        !           289:       if (unlikely(!(tag = mips64_jit_fetch_and_emit(cpu,tc,0)))) {
        !           290:          cpu_log(cpu->gen,"JIT",
        !           291:                  "unable to fetch instruction (VA=0x%8.8llx,exec_state=%u).\n",
        !           292:                  tb->vaddr,tb->exec_state);
1.1.1.4   root      293:          return NULL;
1.1       root      294:       }
                    295: 
1.1.1.13! root      296: #if DEBUG_BLOCK_COMPILE
        !           297:       cpu_log(cpu->gen,"JIT","Page 0x%8.8llx: emitted tag 0x%8.8x/0x%8.8x\n",
        !           298:              tb->vaddr,tag->mask,tag->value);
        !           299: #endif
1.1.1.4   root      300: 
1.1.1.13! root      301:       if (mips64_jit_tcb_adjust_buffer(cpu,tc) == -1)
        !           302:          return NULL;
1.1.1.4   root      303:    }
                    304: 
1.1.1.13! root      305:    mips64_jit_tcb_add_end(tc);
        !           306:    mips64_jit_tcb_apply_patches(cpu,tc);
        !           307:    tc_free_patches(tc);
        !           308:    tc->target_code = NULL;
        !           309:    return tc;
1.1       root      310: }
                    311: 
1.1.1.4   root      312: /* Compile a MIPS instruction page */
1.1.1.13! root      313: static cpu_tb_t *
        !           314: mips64_jit_tcb_compile(cpu_mips_t *cpu,m_uint64_t vaddr,m_uint32_t exec_state)
        !           315: {
        !           316:    cpu_tb_t *tb;
        !           317:    cpu_tc_t *tc;
1.1.1.4   root      318:    m_uint64_t page_addr;
1.1.1.13! root      319:    mips_insn_t *mips_code;
        !           320:    m_uint32_t phys_page;
1.1.1.4   root      321: 
1.1.1.13! root      322:    page_addr = vaddr & MIPS_MIN_PAGE_MASK;
1.1       root      323: 
1.1.1.13! root      324:    /* 
        !           325:     * Get the mips code address from the host point of view.
        !           326:     * If there is an error (TLB,...), we return directly to the main loop.
        !           327:     */
        !           328:    mips_code = cpu->mem_op_ifetch(cpu,page_addr);
1.1       root      329: 
1.1.1.13! root      330:    if (unlikely(cpu->translate(cpu,page_addr,&phys_page)))
        !           331:       return NULL;
1.1       root      332: 
1.1.1.13! root      333:    /* Create a new translation block */
        !           334:    if (!(tb = tb_alloc(cpu->gen,page_addr,exec_state)))
        !           335:       return NULL;
        !           336:       
        !           337:    tb->vaddr       = page_addr;
        !           338:    tb->exec_state  = exec_state;
        !           339:    tb->phys_page   = phys_page;
        !           340:    tb->phys_hash   = mips64_jit_get_phys_hash(phys_page);   
        !           341:    tb->virt_hash   = mips64_jit_get_virt_hash(page_addr);
        !           342:    tb->target_code = mips_code;
        !           343:    tb->checksum    = tsg_checksum_page(tb->target_code,VM_PAGE_SIZE);
        !           344: 
        !           345:    /* Check if we can share this page with another virtual CPU */
        !           346:    if (tc_find_shared(cpu->gen,tb) == TSG_LOOKUP_SHARED) {
        !           347: #if DEBUG_JIT_SHARED
        !           348:       cpu_log(cpu->gen,"JIT","Page 0x%8.8llx is shared (ref_count=%u)\n",
        !           349:               tb->vaddr,tb->tc->ref_count);
1.1       root      350: #endif
1.1.1.13! root      351:       return tb;
1.1       root      352:    }
                    353: 
1.1.1.13! root      354:    /* The page is not shared, we have to compile it */
        !           355:    tc = mips64_jit_tcb_translate(cpu,tb);
1.1.1.2   root      356:    
1.1.1.13! root      357:    if (tc != NULL) {
        !           358:       tc->target_code = tb->target_code;
        !           359:       tc->trans_pos   = 0;
        !           360:  
        !           361:       tb_enable(cpu->gen,tb);
        !           362:       tc_register(cpu->gen,tb,tc);
        !           363:    } else {
        !           364:       tb->flags |= TB_FLAG_NOJIT;
        !           365:       tb_enable(cpu->gen,tb);
        !           366:    }
        !           367:    
        !           368:    return tb;
1.1       root      369: }
                    370: 
                    371: /* Run a compiled MIPS instruction block */
1.1.1.9   root      372: static forced_inline 
1.1.1.13! root      373: void mips64_jit_tcb_run(cpu_mips_t *cpu,cpu_tb_t *tb)
1.1       root      374: {
                    375: #if DEBUG_SYM_TREE
                    376:    struct symbol *sym = NULL;
                    377:    int mark = FALSE;
                    378: #endif
                    379: 
                    380:    if (unlikely(cpu->pc & 0x03)) {
1.1.1.9   root      381:       fprintf(stderr,"mips64_jit_tcb_run: Invalid PC 0x%llx.\n",cpu->pc);
                    382:       mips64_dump_regs(cpu->gen);
                    383:       mips64_tlb_dump(cpu->gen);
                    384:       cpu_stop(cpu->gen);
1.1.1.4   root      385:       return;
1.1       root      386:    }
                    387: 
                    388: #if DEBUG_SYM_TREE
1.1.1.4   root      389:    if (cpu->sym_trace && cpu->sym_tree)
1.1       root      390:    {
1.1.1.4   root      391:       if ((sym = mips64_sym_lookup(cpu,cpu->pc)) != NULL) {
1.1.1.9   root      392:          cpu_log(cpu,"mips64_jit_tcb_run(start)",
1.1.1.4   root      393:                  "%s (PC=0x%llx) RA = 0x%llx\na0=0x%llx, "
1.1       root      394:                  "a1=0x%llx, a2=0x%llx, a3=0x%llx\n",
                    395:                  sym->name, cpu->pc, cpu->gpr[MIPS_GPR_RA],
                    396:                  cpu->gpr[MIPS_GPR_A0], cpu->gpr[MIPS_GPR_A1],
                    397:                  cpu->gpr[MIPS_GPR_A2], cpu->gpr[MIPS_GPR_A3]);
                    398:          mark = TRUE;
                    399:       }
                    400:    }
                    401: #endif
                    402: 
                    403:    /* Execute JIT compiled code */
1.1.1.13! root      404:    mips64_jit_tcb_exec(cpu,tb);
1.1       root      405: 
                    406: #if DEBUG_SYM_TREE
                    407:    if (mark) {
1.1.1.9   root      408:       cpu_log(cpu,"mips64_jit_tcb_run(end)","%s, v0 = 0x%llx\n",
1.1       root      409:               sym->name,cpu->gpr[MIPS_GPR_V0]);
                    410:    }
                    411: #endif
                    412: }
                    413: 
1.1.1.9   root      414: /* Execute compiled MIPS code */
                    415: void *mips64_jit_run_cpu(cpu_gen_t *gen)
                    416: {    
                    417:    cpu_mips_t *cpu = CPU_MIPS64(gen);
1.1.1.4   root      418:    pthread_t timer_irq_thread;
1.1.1.13! root      419:    cpu_tb_t *tb;
        !           420:    m_uint32_t hv,hp;
        !           421:    m_uint32_t phys_page;
1.1.1.4   root      422:    int timer_irq_check = 0;
1.1       root      423: 
1.1.1.4   root      424:    if (pthread_create(&timer_irq_thread,NULL,
                    425:                       (void *)mips64_timer_irq_run,cpu)) 
                    426:    {
1.1.1.7   root      427:       fprintf(stderr,
                    428:               "VM '%s': unable to create Timer IRQ thread for CPU%u.\n",
1.1.1.9   root      429:               cpu->vm->name,gen->id);
                    430:       cpu_stop(cpu->gen);
1.1.1.4   root      431:       return NULL;
                    432:    }
                    433: 
1.1.1.9   root      434:    gen->cpu_thread_running = TRUE;
1.1.1.11  root      435:    cpu_exec_loop_set(gen);
                    436:    
1.1.1.4   root      437:  start_cpu:   
1.1.1.9   root      438:    gen->idle_count = 0;
1.1.1.6   root      439: 
1.1       root      440:    for(;;) {
1.1.1.13! root      441:       if (unlikely(gen->state != CPU_STATE_RUNNING)) {
        !           442:          /* 
        !           443:           * We are paused/halted, so free the TCB/TCD in order to allow
        !           444:           * reallocation of exec pages for other vCPUs.
        !           445:           */
        !           446:          cpu_jit_tcb_flush_all(cpu->gen);
1.1       root      447:          break;
1.1.1.13! root      448:       }
        !           449:       
1.1.1.8   root      450: #if DEBUG_BLOCK_PERF_CNT
                    451:       cpu->perf_counter++;
                    452: #endif
1.1.1.4   root      453:       /* Handle virtual idle loop */
                    454:       if (unlikely(cpu->pc == cpu->idle_pc)) {
1.1.1.9   root      455:          if (++gen->idle_count == gen->idle_max) {
                    456:             cpu_idle_loop(gen);
                    457:             gen->idle_count = 0;
1.1.1.4   root      458:          }
                    459:       }
                    460: 
                    461:       /* Handle the virtual CPU clock */
                    462:       if (++timer_irq_check == cpu->timer_irq_check_itv) {
                    463:          timer_irq_check = 0;
                    464: 
                    465:          if (cpu->timer_irq_pending && !cpu->irq_disable) {
                    466:             mips64_trigger_timer_irq(cpu);
                    467:             mips64_trigger_irq(cpu);
                    468:             cpu->timer_irq_pending--;
                    469:          }
                    470:       }
1.1       root      471: 
1.1.1.13! root      472:       /* Get the JIT block corresponding to PC register */
        !           473:       hv = mips64_jit_get_virt_hash(cpu->pc);
        !           474:       tb = gen->tb_virt_hash[hv];
1.1.1.4   root      475: 
1.1.1.13! root      476:       if (unlikely(!tb) || unlikely(!mips64_jit_tcb_match(cpu,tb))) 
        !           477:       {
        !           478:          /* slow lookup: try to find the page by physical address */
        !           479:          cpu->translate(cpu,cpu->pc,&phys_page);
        !           480:          hp = mips64_jit_get_phys_hash(phys_page);
        !           481: 
        !           482:          for(tb=gen->tb_phys_hash[hp];tb;tb=tb->phys_next)
        !           483:             if (mips64_jit_tcb_match(cpu,tb))
        !           484:                goto tb_found;
        !           485: 
        !           486:          /* the TB doesn't exist, compile the page */
        !           487:          tb = mips64_jit_tcb_compile(cpu,cpu->pc,cpu->exec_state);
1.1.1.5   root      488: 
1.1.1.13! root      489:          if (unlikely(!tb)) {
1.1.1.4   root      490:             fprintf(stderr,
                    491:                     "VM '%s': unable to compile block for CPU%u PC=0x%llx\n",
1.1.1.9   root      492:                     cpu->vm->name,gen->id,cpu->pc);
                    493:             cpu_stop(gen);
1.1.1.4   root      494:             break;
1.1       root      495:          }
1.1.1.2   root      496: 
1.1.1.13! root      497:         tb_found:
        !           498:          /* update the virtual hash table */
        !           499:          gen->tb_virt_hash[hv] = tb;
1.1       root      500:       }
                    501: 
                    502: #if DEBUG_BLOCK_TIMESTAMP
1.1.1.13! root      503:       tb->tm_last_use = jit_jiffies++;
1.1       root      504: #endif
1.1.1.13! root      505:       tb->acc_count++;
        !           506:  
        !           507:       cpu->current_tb = tb;
        !           508: 
        !           509:       if (unlikely(tb->flags & TB_FLAG_NOTRANS))
        !           510:          mips64_exec_page(cpu);
        !           511:       else
        !           512:          mips64_jit_tcb_run(cpu,tb);
1.1       root      513:    }
                    514: 
1.1.1.4   root      515:    /* Check regularly if the CPU has been restarted */
1.1.1.9   root      516:    while(gen->cpu_thread_running) {
                    517:       gen->seq_state++;
1.1.1.4   root      518: 
1.1.1.9   root      519:       switch(gen->state) {
                    520:          case CPU_STATE_RUNNING:
1.1.1.13! root      521:             printf("VM %s: starting CPU!\n",cpu->vm->name);
1.1.1.4   root      522:             goto start_cpu;
                    523: 
1.1.1.9   root      524:          case CPU_STATE_HALTED:
                    525:             gen->cpu_thread_running = FALSE;
1.1.1.4   root      526:             pthread_join(timer_irq_thread,NULL);
1.1.1.12  root      527:             return NULL;
1.1.1.4   root      528:       }
1.1       root      529:       
1.1.1.4   root      530:       /* CPU is paused */
1.1       root      531:       usleep(200000);
1.1.1.4   root      532:    }
1.1       root      533: 
                    534:    return NULL;
                    535: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.