/* DMA transfer operation */ void physmem_dma_transfer(vm_instance_t *vm,m_uint64_t src,m_uint64_t dst, size_t len) { m_uint64_t dummy; u_char *sptr,*dptr; size_t clen,sl,dl; while(len > 0) { sptr = physmem_get_hptr(vm,src,0,MTS_READ,&dummy); dptr = physmem_get_hptr(vm,dst,0,MTS_WRITE,&dummy); if (!sptr || !dptr) { vm_log(vm,"DMA","unable to transfer from 0x%llx to 0x%llx\n",src,dst); return; } sl = VM_PAGE_SIZE - (src & VM_PAGE_IMASK); dl = VM_PAGE_SIZE - (dst & VM_PAGE_IMASK); clen = m_min(sl,dl); clen = m_min(clen,len); memcpy(dptr,sptr,clen); src += clen; dst += clen; len -= clen; } }
/* Copy a memory block to VM physical RAM from real host */ void physmem_copy_to_vm(vm_instance_t *vm,void *real_buffer, m_uint64_t paddr,size_t len) { m_uint64_t dummy; m_uint32_t r; u_char *ptr; while(len > 0) { r = m_min(VM_PAGE_SIZE - (paddr & VM_PAGE_IMASK), len); ptr = physmem_get_hptr(vm,paddr,0,MTS_WRITE,&dummy); if (likely(ptr != NULL)) { memcpy(ptr,real_buffer,r); } else { r = m_min(len,4); switch(r) { case 4: physmem_copy_u32_to_vm(vm,paddr, htovm32(*(m_uint32_t *)real_buffer)); break; case 2: physmem_copy_u16_to_vm(vm,paddr, htovm16(*(m_uint16_t *)real_buffer)); break; case 1: physmem_copy_u8_to_vm(vm,paddr,*(m_uint8_t *)real_buffer); break; } } real_buffer += r; paddr += r; len -= r; } }
/* Copy a 16-bit word to the VM physical RAM from real host */ void physmem_copy_u8_to_vm(vm_instance_t *vm,m_uint64_t paddr,m_uint8_t val) { m_uint64_t tmp = val; m_uint8_t *ptr; if ((ptr = physmem_get_hptr(vm,paddr,1,MTS_WRITE,&tmp)) != NULL) *ptr = val; }
/* Copy a 16-bit word to the VM physical RAM from real host */ void physmem_copy_u16_to_vm(vm_instance_t *vm,m_uint64_t paddr,m_uint16_t val) { m_uint64_t tmp = val; m_uint16_t *ptr; if ((ptr = physmem_get_hptr(vm,paddr,2,MTS_WRITE,&tmp)) != NULL) *ptr = htovm16(val); }
/* Copy a byte from the VM physical RAM to real host */ m_uint8_t physmem_copy_u8_from_vm(vm_instance_t *vm,m_uint64_t paddr) { m_uint64_t tmp = 0; m_uint8_t *ptr; if ((ptr = physmem_get_hptr(vm,paddr,1,MTS_READ,&tmp)) != NULL) return(*ptr); return(tmp); }
/* * MIPS64 fetch->decode->dispatch main loop */ void *mips_cpu_fdd (cpu_mips_t * cpu) { mips_insn_t insn = 0; int res; cpu->cpu_thread_running = TRUE; current_cpu = cpu; mips_init_host_alarm (); start_cpu: for (;;) { if (unlikely (cpu->state != CPU_STATE_RUNNING)) break; if (unlikely ((cpu->pause_request) & CPU_INTERRUPT_EXIT)) { cpu->state = CPU_STATE_PAUSING; break; } /* Reset "zero register" (for safety) */ cpu->gpr[0] = 0; /* Check IRQ */ if (unlikely (cpu->irq_pending)) { mips_trigger_irq (cpu); continue; } /* Fetch the instruction */ res = mips_fetch_instruction (cpu, cpu->pc, &insn); if (cpu->vm->trace_address == cpu->pc) { /* Trace address. */ printf ("*** %08x: %08x ", cpu->pc, insn); print_insn_mips (cpu->pc, insn, stdout); printf ("\n"); dumpregs (cpu); } if (unlikely (res == 1)) { /*exception when fetching instruction */ printf ("%08x: exception when fetching instruction\n", cpu->pc); if (cpu->pc == 0) exit(-1); continue; } if (unlikely ((cpu->vm->mipsy_debug_mode) && ((cpu_hit_breakpoint (cpu->vm, cpu->pc) == SUCCESS) || (cpu->vm->gdb_interact_sock == -1) || (cpu->vm->mipsy_break_nexti == MIPS_BREAKANYCPU)))) { if (mips_debug (cpu->vm, 1)) { continue; } } if (cpu->vm->debug_level > 2 || (cpu->vm->debug_level > 1 && (cpu->cp0.reg[MIPS_CP0_STATUS] & MIPS_CP0_STATUS_UM) && ! (cpu->cp0.reg[MIPS_CP0_STATUS] & MIPS_CP0_STATUS_EXL))) { /* Print instructions in user mode. */ printf ("%08x: %08x ", cpu->pc, insn); print_insn_mips (cpu->pc, insn, stdout); printf ("\n"); fflush (stdout); #if 0 m_uint32_t dummy; unsigned char *p = physmem_get_hptr (cpu->vm, 0x00010000, 0, MTS_READ, &dummy); if (p) { unsigned nbytes; for (nbytes=0x40; nbytes>0; p+=16, nbytes-=16) { printf ("%08x: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", (unsigned) p, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]); } } #endif } res = mips_exec_single_instruction (cpu, insn); /* Normal flow ? */ if (likely (!res)) cpu->pc += sizeof (mips_insn_t); } while (cpu->cpu_thread_running) { switch (cpu->state) { case CPU_STATE_RUNNING: cpu->state = CPU_STATE_RUNNING; goto start_cpu; case CPU_STATE_HALTED: cpu->cpu_thread_running = FALSE; break; case CPU_STATE_RESTARTING: cpu->state = CPU_STATE_RESTARTING; /*Just waiting for cpu restart. */ break; case CPU_STATE_PAUSING: /*main loop must wait for me. heihei :) */ mips_main_loop_wait (cpu, 0); cpu->state = CPU_STATE_RUNNING; cpu->pause_request &= ~CPU_INTERRUPT_EXIT; /*start cpu again */ goto start_cpu; } } return NULL; }