static void load_kernel (CPUState *env) { int64_t entry, kernel_low, kernel_high; long kernel_size, initrd_size; ram_addr_t initrd_offset; kernel_size = load_elf(loaderparams.kernel_filename, VIRT_TO_PHYS_ADDEND, (uint64_t *)&entry, (uint64_t *)&kernel_low, (uint64_t *)&kernel_high); if (kernel_size >= 0) { if ((entry & ~0x7fffffffULL) == 0x80000000) entry = (int32_t)entry; env->active_tc.PC = entry; } else { fprintf(stderr, "qemu: could not load kernel '%s'\n", loaderparams.kernel_filename); exit(1); } /* load initrd */ initrd_size = 0; initrd_offset = 0; if (loaderparams.initrd_filename) { initrd_size = get_image_size (loaderparams.initrd_filename); if (initrd_size > 0) { initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK; if (initrd_offset + initrd_size > ram_size) { fprintf(stderr, "qemu: memory too small for initial ram disk '%s'\n", loaderparams.initrd_filename); exit(1); } initrd_size = load_image(loaderparams.initrd_filename, phys_ram_base + initrd_offset); } if (initrd_size == (target_ulong) -1) { fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", loaderparams.initrd_filename); exit(1); } } /* Store command line. */ if (initrd_size > 0) { int ret; ret = sprintf((char *)(phys_ram_base + (16 << 20) - 256), "rd_start=0x" TARGET_FMT_lx " rd_size=%li ", PHYS_TO_VIRT((uint32_t)initrd_offset), initrd_size); strcpy ((char *)(phys_ram_base + (16 << 20) - 256 + ret), loaderparams.kernel_cmdline); } else { strcpy ((char *)(phys_ram_base + (16 << 20) - 256), loaderparams.kernel_cmdline); } *(int32_t *)(phys_ram_base + (16 << 20) - 260) = tswap32 (0x12345678); *(int32_t *)(phys_ram_base + (16 << 20) - 264) = tswap32 (ram_size); }
long do_execve(char* arg1, char ** arg2, char ** arg3) { long ret; char **argv = arg2; char **envp = arg3; int argc; int envc; /* XXX: don't let the %s stay in here */ DPRINTF("execve(%s, %p, %p)\n", arg1, arg2, arg3); for(argc = 0; argv[argc]; argc++); for(envc = 0; envp[envc]; envc++); argv = (char**)malloc(sizeof(char*)*argc); envp = (char**)malloc(sizeof(char*)*envc); for(; argc >= 0; argc--) argv[argc] = (char*)tswap32((uint32_t)(arg2)[argc]); for(; envc >= 0; envc--) envp[envc] = (char*)tswap32((uint32_t)(arg3)[envc]); ret = get_errno(execve(arg1, argv, envp)); free(argv); free(envp); return ret; }
/* Load new Frame Descriptors from DMA */ static void pxa2xx_descriptor_load(PXA2xxLCDState *s) { PXAFrameDescriptor desc; target_phys_addr_t descptr; int i; for (i = 0; i < PXA_LCDDMA_CHANS; i ++) { s->dma_ch[i].source = 0; if (!s->dma_ch[i].up) continue; if (s->dma_ch[i].branch & FBR_BRA) { descptr = s->dma_ch[i].branch & FBR_SRCADDR; if (s->dma_ch[i].branch & FBR_BINT) pxa2xx_dma_bs_set(s, i); s->dma_ch[i].branch &= ~FBR_BRA; } else descptr = s->dma_ch[i].descriptor; if (!(descptr >= PXA2XX_SDRAM_BASE && descptr + sizeof(desc) <= PXA2XX_SDRAM_BASE + ram_size)) continue; cpu_physical_memory_read(descptr, (void *)&desc, sizeof(desc)); s->dma_ch[i].descriptor = tswap32(desc.fdaddr); s->dma_ch[i].source = tswap32(desc.fsaddr); s->dma_ch[i].id = tswap32(desc.fidr); s->dma_ch[i].command = tswap32(desc.ldcmd); } }
/* * try and convert sysctl return data for the target. * XXX doesn't handle CTLTYPE_OPAQUE and CTLTYPE_STRUCT. */ static int sysctl_oldcvt(void *holdp, size_t holdlen, uint32_t kind) { switch (kind & CTLTYPE) { case CTLTYPE_INT: case CTLTYPE_UINT: *(uint32_t *)holdp = tswap32(*(uint32_t *)holdp); break; #ifdef TARGET_ABI32 case CTLTYPE_LONG: case CTLTYPE_ULONG: *(uint32_t *)holdp = tswap32(*(long *)holdp); break; #else case CTLTYPE_LONG: *(uint64_t *)holdp = tswap64(*(long *)holdp); case CTLTYPE_ULONG: *(uint64_t *)holdp = tswap64(*(unsigned long *)holdp); break; #endif #ifdef CTLTYPE_U64 case CTLTYPE_S64: case CTLTYPE_U64: #else case CTLTYPE_QUAD: #endif *(uint64_t *)holdp = tswap64(*(uint64_t *)holdp); break; case CTLTYPE_STRING: break; default: /* XXX unhandled */ return -1; } return 0; }
void exynos4210_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info) { int n; uint32_t smpboot[] = { 0xe59f3034, /* ldr r3, External gic_cpu_if */ 0xe59f2034, /* ldr r2, Internal gic_cpu_if */ 0xe59f0034, /* ldr r0, startaddr */ 0xe3a01001, /* mov r1, #1 */ 0xe5821000, /* str r1, [r2] */ 0xe5831000, /* str r1, [r3] */ 0xe3a010ff, /* mov r1, #0xff */ 0xe5821004, /* str r1, [r2, #4] */ 0xe5831004, /* str r1, [r3, #4] */ 0xf57ff04f, /* dsb */ 0xe320f003, /* wfi */ 0xe5901000, /* ldr r1, [r0] */ 0xe1110001, /* tst r1, r1 */ 0x0afffffb, /* beq <wfi> */ 0xe12fff11, /* bx r1 */ EXYNOS4210_EXT_GIC_CPU_BASE_ADDR, 0, /* gic_cpu_if: base address of Internal GIC CPU interface */ 0 /* bootreg: Boot register address is held here */ }; smpboot[ARRAY_SIZE(smpboot) - 1] = info->smp_bootreg_addr; smpboot[ARRAY_SIZE(smpboot) - 2] = info->gic_cpu_if_addr; for (n = 0; n < ARRAY_SIZE(smpboot); n++) { smpboot[n] = tswap32(smpboot[n]); } rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot), info->smp_loader_start); }
static void hb_write_board_setup(ARMCPU *cpu, const struct arm_boot_info *info) { int n; uint32_t board_setup_blob[] = { /* MVBAR_ADDR */ /* Default unimplemented and unused vectors to spin. Makes it * easier to debug (as opposed to the CPU running away). */ 0xeafffffe, /* notused1: b notused */ 0xeafffffe, /* notused2: b notused */ 0xe1b0f00e, /* smc: movs pc, lr - exception return */ 0xeafffffe, /* prefetch_abort: b prefetch_abort */ 0xeafffffe, /* data_abort: b data_abort */ 0xeafffffe, /* notused3: b notused3 */ 0xeafffffe, /* irq: b irq */ 0xeafffffe, /* fiq: b fiq */ #define BOARD_SETUP_ADDR (MVBAR_ADDR + 8 * sizeof(uint32_t)) 0xe3000000 + ARMV7_IMM16(MVBAR_ADDR), /* movw r0, MVBAR_ADDR */ 0xee0c0f30, /* mcr p15, 0, r0, c12, c0, 1 - set MVBAR */ 0xee110f11, /* mrc p15, 0, r0, c1 , c1, 0 - get SCR */ 0xe3810001, /* orr r0, #1 - set NS */ 0xee010f11, /* mcr p15, 0, r0, c1 , c1, 0 - set SCR */ 0xe1600070, /* smc - go to monitor mode to flush NS change */ 0xe12fff1e, /* bx lr - return to caller */ }; for (n = 0; n < ARRAY_SIZE(board_setup_blob); n++) { board_setup_blob[n] = tswap32(board_setup_blob[n]); } rom_add_blob_fixed("board-setup", board_setup_blob, sizeof(board_setup_blob), MVBAR_ADDR); }
/* XXX this needs to be emulated on non-FreeBSD hosts... */ static abi_long do_freebsd_sysctl(abi_ulong namep, int32_t namelen, abi_ulong oldp, abi_ulong oldlenp, abi_ulong newp, abi_ulong newlen) { abi_long ret; void *hnamep, *holdp, *hnewp = NULL; size_t holdlen; abi_ulong oldlen = 0; int32_t *snamep = g_malloc(sizeof(int32_t) * namelen), *p, *q, i; uint32_t kind = 0; if (oldlenp) get_user_ual(oldlen, oldlenp); if (!(hnamep = lock_user(VERIFY_READ, namep, namelen, 1))) return -TARGET_EFAULT; if (newp && !(hnewp = lock_user(VERIFY_READ, newp, newlen, 1))) return -TARGET_EFAULT; if (!(holdp = lock_user(VERIFY_WRITE, oldp, oldlen, 0))) return -TARGET_EFAULT; holdlen = oldlen; for (p = hnamep, q = snamep, i = 0; i < namelen; p++, i++) *q++ = tswap32(*p); oidfmt(snamep, namelen, NULL, &kind); /* XXX swap hnewp */ ret = get_errno(sysctl(snamep, namelen, holdp, &holdlen, hnewp, newlen)); if (!ret) sysctl_oldcvt(holdp, holdlen, kind); put_user_ual(holdlen, oldlenp); unlock_user(hnamep, namep, 0); unlock_user(holdp, oldp, holdlen); if (hnewp) unlock_user(hnewp, newp, 0); g_free(snamep); return ret; }
static void main_cpu_reset(void *opaque) { PowerPCCPU *cpu = opaque; CPUPPCState *env = &cpu->env; struct boot_info *bi = env->load_info; cpu_reset(CPU(cpu)); /* Linux Kernel Parameters (passing device tree): * r3: pointer to the fdt * r4: 0 * r5: 0 * r6: epapr magic * r7: size of IMA in bytes * r8: 0 * r9: 0 */ env->gpr[1] = (16<<20) - 8; /* Provide a device-tree. */ env->gpr[3] = bi->fdt; env->nip = bi->bootstrap_pc; /* Create a mapping for the kernel. */ mmubooke_create_initial_mapping(env, 0, 0); env->gpr[6] = tswap32(EPAPR_MAGIC); env->gpr[7] = bi->ima_size; }
static uint64_t eth_read(void *opaque, hwaddr addr, unsigned int size) { struct xlx_ethlite *s = opaque; uint32_t r = 0; addr >>= 2; switch (addr) { case R_TX_GIE0: case R_TX_LEN0: case R_TX_LEN1: case R_TX_CTRL1: case R_TX_CTRL0: case R_RX_CTRL1: case R_RX_CTRL0: r = s->regs[addr]; D(qemu_log("%s " TARGET_FMT_plx "=%x\n", __func__, addr * 4, r)); break; default: r = tswap32(s->regs[addr]); break; } return r; }
static void hb_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info) { int n; uint32_t smpboot[] = { 0xee100fb0, /* mrc p15, 0, r0, c0, c0, 5 - read current core id */ 0xe210000f, /* ands r0, r0, #0x0f */ 0xe3a03040, /* mov r3, #0x40 - jump address is 0x40 + 0x10 * core id */ 0xe0830200, /* add r0, r3, r0, lsl #4 */ 0xe59f2024, /* ldr r2, privbase */ 0xe3a01001, /* mov r1, #1 */ 0xe5821100, /* str r1, [r2, #256] - set GICC_CTLR.Enable */ 0xe3a010ff, /* mov r1, #0xff */ 0xe5821104, /* str r1, [r2, #260] - set GICC_PMR.Priority to 0xff */ 0xf57ff04f, /* dsb */ 0xe320f003, /* wfi */ 0xe5901000, /* ldr r1, [r0] */ 0xe1110001, /* tst r1, r1 */ 0x0afffffb, /* beq <wfi> */ 0xe12fff11, /* bx r1 */ MPCORE_PERIPHBASE /* privbase: MPCore peripheral base address. */ }; for (n = 0; n < ARRAY_SIZE(smpboot); n++) { smpboot[n] = tswap32(smpboot[n]); } rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot), SMP_BOOT_ADDR); }
/* ------------------------------------------------------------ thread type syscall handling */ long do_thread_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, uint32_t arg8) { extern uint32_t cthread_set_self(uint32_t); extern uint32_t processor_facilities_used(); long ret = 0; arg1 = tswap32(arg1); arg2 = tswap32(arg2); arg3 = tswap32(arg3); arg4 = tswap32(arg4); arg5 = tswap32(arg5); arg6 = tswap32(arg6); arg7 = tswap32(arg7); arg8 = tswap32(arg8); DPRINTF("thread syscall %d : " , num); switch(num) { #ifdef TARGET_I386 case 0x3: #endif case 0x7FF1: /* cthread_set_self */ DPRINTF("cthread_set_self(0x%x)\n", (unsigned int)arg1); ret = cthread_set_self(arg1); #ifdef TARGET_I386 /* we need to update the LDT with the address of the thread */ write_dt((void *)(((CPUX86State *) cpu_env)->ldt.base + (4 * sizeof(uint64_t))), arg1, 1, DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | (3 << DESC_DPL_SHIFT) | (0x2 << DESC_TYPE_SHIFT)); /* New i386 convention, %gs should be set to our this LDT entry */ cpu_x86_load_seg(cpu_env, R_GS, 0x27); /* Old i386 convention, the kernel returns the selector for the cthread (pre-10.4.8?)*/ ret = 0x27; #endif break; case 0x7FF2: /* Called the super-fast pthread_self handler by the apple guys */ DPRINTF("pthread_self()\n"); ret = (uint32_t)pthread_self(); break; case 0x7FF3: DPRINTF("processor_facilities_used()\n"); #ifdef __i386__ qerror("processor_facilities_used: not implemented!\n"); #else ret = (uint32_t)processor_facilities_used(); #endif break; default: gemu_log("qemu: Unsupported thread syscall: %d(0x%x)\n", num, num); gdb_handlesig (cpu_env, SIGTRAP); exit(0); break; } return ret; }
static void eth_write(void *opaque, hwaddr addr, uint64_t val64, unsigned int size) { struct xlx_ethlite *s = opaque; unsigned int base = 0; uint32_t value = val64; addr >>= 2; switch (addr) { case R_TX_CTRL0: case R_TX_CTRL1: if (addr == R_TX_CTRL1) base = 0x800 / 4; D(qemu_log("%s addr=" TARGET_FMT_plx " val=%x\n", __func__, addr * 4, value)); if ((value & (CTRL_P | CTRL_S)) == CTRL_S) { qemu_send_packet(qemu_get_queue(s->nic), (void *) &s->regs[base], s->regs[base + R_TX_LEN0]); D(qemu_log("eth_tx %d\n", s->regs[base + R_TX_LEN0])); if (s->regs[base + R_TX_CTRL0] & CTRL_I) eth_pulse_irq(s); } else if ((value & (CTRL_P | CTRL_S)) == (CTRL_P | CTRL_S)) { memcpy(&s->conf.macaddr.a[0], &s->regs[base], 6); if (s->regs[base + R_TX_CTRL0] & CTRL_I) eth_pulse_irq(s); } /* We are fast and get ready pretty much immediately so we actually never flip the S nor P bits to one. */ s->regs[addr] = value & ~(CTRL_P | CTRL_S); break; /* Keep these native. */ case R_RX_CTRL0: case R_RX_CTRL1: if (!(value & CTRL_S)) { qemu_flush_queued_packets(qemu_get_queue(s->nic)); } /* fall through */ case R_TX_LEN0: case R_TX_LEN1: case R_TX_GIE0: D(qemu_log("%s addr=" TARGET_FMT_plx " val=%x\n", __func__, addr * 4, value)); s->regs[addr] = value; break; default: s->regs[addr] = tswap32(value); break; } }
static void zynq_write_secondary_boot(ARMCPU *cpu, const struct arm_boot_info *info) { int n; for (n = 0; n < ARRAY_SIZE(zynq_smpboot); n++) { zynq_smpboot[n] = tswap32(zynq_smpboot[n]); } rom_add_blob_fixed("smpboot", zynq_smpboot, sizeof(zynq_smpboot), SMP_BOOT_ADDR); }
static inline void swap_mach_msg_header(mach_msg_header_t *hdr) { hdr->msgh_bits = tswap32(hdr->msgh_bits); hdr->msgh_size = tswap32(hdr->msgh_size); hdr->msgh_remote_port = tswap32(hdr->msgh_remote_port); hdr->msgh_local_port = tswap32(hdr->msgh_local_port); hdr->msgh_reserved = tswap32(hdr->msgh_reserved); hdr->msgh_id = tswap32(hdr->msgh_id); }
static void zynq_write_board_setup(ARMCPU *cpu, const struct arm_boot_info *info) { int n; uint32_t board_setup_blob[] = { 0xe3a004f8, /* mov r0, #0xf8000000 */ SLCR_WRITE(SLCR_UNLOCK_OFFSET, SLCR_XILINX_UNLOCK_KEY), SLCR_WRITE(SLCR_ARM_PLL_OFFSET, 0x00014008), SLCR_WRITE(SLCR_LOCK_OFFSET, SLCR_XILINX_LOCK_KEY), 0xe12fff1e, /* bx lr */ }; for (n = 0; n < ARRAY_SIZE(board_setup_blob); n++) { board_setup_blob[n] = tswap32(board_setup_blob[n]); } rom_add_blob_fixed("board-setup", board_setup_blob, sizeof(board_setup_blob), BOARD_SETUP_ADDR); }
int do_sigaltstack(const struct sigaltstack *ss, struct sigaltstack *oss) { /* XXX: test errors */ if(oss) { oss->ss_sp = tswap32(target_sigaltstack_used.ss_sp); oss->ss_size = tswap32(target_sigaltstack_used.ss_size); oss->ss_flags = tswap32(target_sigaltstack_used.ss_flags); } if(ss) { target_sigaltstack_used.ss_sp = tswap32(ss->ss_sp); target_sigaltstack_used.ss_size = tswap32(ss->ss_size); target_sigaltstack_used.ss_flags = tswap32(ss->ss_flags); } return 0; }
static void hb_write_secondary(CPUARMState *env, const struct arm_boot_info *info) { int n; uint32_t smpboot[] = { 0xee100fb0, /* mrc p15, 0, r0, c0, c0, 5 - read current core id */ 0xe210000f, /* ands r0, r0, #0x0f */ 0xe3a03040, /* mov r3, #0x40 - jump address is 0x40 + 0x10 * core id */ 0xe0830200, /* add r0, r3, r0, lsl #4 */ 0xe59f2018, /* ldr r2, privbase */ 0xe3a01001, /* mov r1, #1 */ 0xe5821100, /* str r1, [r2, #256] */ 0xe320f003, /* wfi */ 0xe5901000, /* ldr r1, [r0] */ 0xe1110001, /* tst r1, r1 */ 0x0afffffb, /* beq <wfi> */ 0xe12fff11, /* bx r1 */ GIC_BASE_ADDR /* privbase: gic address. */ }; for (n = 0; n < ARRAY_SIZE(smpboot); n++) { smpboot[n] = tswap32(smpboot[n]); } rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot), SMP_BOOT_ADDR); }
static void qtest_process_command(CharDriverState *chr, gchar **words) { const gchar *command; g_assert(words); command = words[0]; if (qtest_log_fp) { qemu_timeval tv; int i; qtest_get_time(&tv); fprintf(qtest_log_fp, "[R +" FMT_timeval "]", (long) tv.tv_sec, (long) tv.tv_usec); for (i = 0; words[i]; i++) { fprintf(qtest_log_fp, " %s", words[i]); } fprintf(qtest_log_fp, "\n"); } g_assert(command); if (strcmp(words[0], "irq_intercept_out") == 0 || strcmp(words[0], "irq_intercept_in") == 0) { DeviceState *dev; g_assert(words[1]); dev = DEVICE(object_resolve_path(words[1], NULL)); if (!dev) { qtest_send_prefix(chr); qtest_send(chr, "FAIL Unknown device\n"); return; } if (irq_intercept_dev) { qtest_send_prefix(chr); if (irq_intercept_dev != dev) { qtest_send(chr, "FAIL IRQ intercept already enabled\n"); } else { qtest_send(chr, "OK\n"); } return; } if (words[0][14] == 'o') { qemu_irq_intercept_out(&dev->gpio_out, qtest_irq_handler, dev->num_gpio_out); } else { qemu_irq_intercept_in(dev->gpio_in, qtest_irq_handler, dev->num_gpio_in); } irq_intercept_dev = dev; qtest_send_prefix(chr); qtest_send(chr, "OK\n"); } else if (strcmp(words[0], "outb") == 0 || strcmp(words[0], "outw") == 0 || strcmp(words[0], "outl") == 0) { uint16_t addr; uint32_t value; g_assert(words[1] && words[2]); addr = strtoul(words[1], NULL, 0); value = strtoul(words[2], NULL, 0); if (words[0][3] == 'b') { cpu_outb(addr, value); } else if (words[0][3] == 'w') { cpu_outw(addr, value); } else if (words[0][3] == 'l') { cpu_outl(addr, value); } qtest_send_prefix(chr); qtest_send(chr, "OK\n"); } else if (strcmp(words[0], "inb") == 0 || strcmp(words[0], "inw") == 0 || strcmp(words[0], "inl") == 0) { uint16_t addr; uint32_t value = -1U; g_assert(words[1]); addr = strtoul(words[1], NULL, 0); if (words[0][2] == 'b') { value = cpu_inb(addr); } else if (words[0][2] == 'w') { value = cpu_inw(addr); } else if (words[0][2] == 'l') { value = cpu_inl(addr); } qtest_send_prefix(chr); qtest_send(chr, "OK 0x%04x\n", value); } else if (strcmp(words[0], "writeb") == 0 || strcmp(words[0], "writew") == 0 || strcmp(words[0], "writel") == 0 || strcmp(words[0], "writeq") == 0) { uint64_t addr; uint64_t value; g_assert(words[1] && words[2]); addr = strtoull(words[1], NULL, 0); value = strtoull(words[2], NULL, 0); if (words[0][5] == 'b') { uint8_t data = value; cpu_physical_memory_write(addr, &data, 1); } else if (words[0][5] == 'w') { uint16_t data = value; tswap16s(&data); cpu_physical_memory_write(addr, &data, 2); } else if (words[0][5] == 'l') { uint32_t data = value; tswap32s(&data); cpu_physical_memory_write(addr, &data, 4); } else if (words[0][5] == 'q') { uint64_t data = value; tswap64s(&data); cpu_physical_memory_write(addr, &data, 8); } qtest_send_prefix(chr); qtest_send(chr, "OK\n"); } else if (strcmp(words[0], "readb") == 0 || strcmp(words[0], "readw") == 0 || strcmp(words[0], "readl") == 0 || strcmp(words[0], "readq") == 0) { uint64_t addr; uint64_t value = UINT64_C(-1); g_assert(words[1]); addr = strtoull(words[1], NULL, 0); if (words[0][4] == 'b') { uint8_t data; cpu_physical_memory_read(addr, &data, 1); value = data; } else if (words[0][4] == 'w') { uint16_t data; cpu_physical_memory_read(addr, &data, 2); value = tswap16(data); } else if (words[0][4] == 'l') { uint32_t data; cpu_physical_memory_read(addr, &data, 4); value = tswap32(data); } else if (words[0][4] == 'q') { cpu_physical_memory_read(addr, &value, 8); tswap64s(&value); } qtest_send_prefix(chr); qtest_send(chr, "OK 0x%016" PRIx64 "\n", value); } else if (strcmp(words[0], "read") == 0) { uint64_t addr, len, i; uint8_t *data; g_assert(words[1] && words[2]); addr = strtoull(words[1], NULL, 0); len = strtoull(words[2], NULL, 0); data = g_malloc(len); cpu_physical_memory_read(addr, data, len); qtest_send_prefix(chr); qtest_send(chr, "OK 0x"); for (i = 0; i < len; i++) { qtest_send(chr, "%02x", data[i]); } qtest_send(chr, "\n"); g_free(data); } else if (strcmp(words[0], "write") == 0) { uint64_t addr, len, i; uint8_t *data; size_t data_len; g_assert(words[1] && words[2] && words[3]); addr = strtoull(words[1], NULL, 0); len = strtoull(words[2], NULL, 0); data_len = strlen(words[3]); if (data_len < 3) { qtest_send(chr, "ERR invalid argument size\n"); return; } data = g_malloc(len); for (i = 0; i < len; i++) { if ((i * 2 + 4) <= data_len) { data[i] = hex2nib(words[3][i * 2 + 2]) << 4; data[i] |= hex2nib(words[3][i * 2 + 3]); } else { data[i] = 0; } } cpu_physical_memory_write(addr, data, len); g_free(data); qtest_send_prefix(chr); qtest_send(chr, "OK\n"); } else if (qtest_enabled() && strcmp(words[0], "clock_step") == 0) { int64_t ns; if (words[1]) { ns = strtoll(words[1], NULL, 0); } else { ns = qemu_clock_deadline_ns_all(QEMU_CLOCK_VIRTUAL); } qtest_clock_warp(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + ns); qtest_send_prefix(chr); qtest_send(chr, "OK %"PRIi64"\n", (int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); } else if (qtest_enabled() && strcmp(words[0], "clock_set") == 0) { int64_t ns; g_assert(words[1]); ns = strtoll(words[1], NULL, 0); qtest_clock_warp(ns); qtest_send_prefix(chr); qtest_send(chr, "OK %"PRIi64"\n", (int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); } else { qtest_send_prefix(chr); qtest_send(chr, "FAIL Unknown command `%s'\n", words[0]); } }
/* Interpret pseudo code in tb. */ tcg_target_ulong tcg_qemu_tb_exec(CPUArchState *env, uint8_t *tb_ptr) { long tcg_temps[CPU_TEMP_BUF_NLONGS]; uintptr_t sp_value = (uintptr_t)(tcg_temps + CPU_TEMP_BUF_NLONGS); tcg_target_ulong next_tb = 0; tci_reg[TCG_AREG0] = (tcg_target_ulong)env; tci_reg[TCG_REG_CALL_STACK] = sp_value; assert(tb_ptr); for (;;) { TCGOpcode opc = tb_ptr[0]; #if !defined(NDEBUG) uint8_t op_size = tb_ptr[1]; uint8_t *old_code_ptr = tb_ptr; #endif tcg_target_ulong t0; tcg_target_ulong t1; tcg_target_ulong t2; tcg_target_ulong label; TCGCond condition; target_ulong taddr; #ifndef CONFIG_SOFTMMU tcg_target_ulong host_addr; #endif uint8_t tmp8; uint16_t tmp16; uint32_t tmp32; uint64_t tmp64; #if TCG_TARGET_REG_BITS == 32 uint64_t v64; #endif #if defined(GETPC) tci_tb_ptr = (uintptr_t)tb_ptr; #endif /* Skip opcode and size entry. */ tb_ptr += 2; switch (opc) { case INDEX_op_end: case INDEX_op_nop: break; case INDEX_op_nop1: case INDEX_op_nop2: case INDEX_op_nop3: case INDEX_op_nopn: case INDEX_op_discard: TODO(); break; case INDEX_op_set_label: TODO(); break; case INDEX_op_call: t0 = tci_read_ri(&tb_ptr); #if TCG_TARGET_REG_BITS == 32 tmp64 = ((helper_function)t0)(tci_read_reg(TCG_REG_R0), tci_read_reg(TCG_REG_R1), tci_read_reg(TCG_REG_R2), tci_read_reg(TCG_REG_R3), tci_read_reg(TCG_REG_R5), tci_read_reg(TCG_REG_R6), tci_read_reg(TCG_REG_R7), tci_read_reg(TCG_REG_R8), tci_read_reg(TCG_REG_R9), tci_read_reg(TCG_REG_R10)); tci_write_reg(TCG_REG_R0, tmp64); tci_write_reg(TCG_REG_R1, tmp64 >> 32); #else tmp64 = ((helper_function)t0)(tci_read_reg(TCG_REG_R0), tci_read_reg(TCG_REG_R1), tci_read_reg(TCG_REG_R2), tci_read_reg(TCG_REG_R3), tci_read_reg(TCG_REG_R5)); tci_write_reg(TCG_REG_R0, tmp64); #endif break; case INDEX_op_br: label = tci_read_label(&tb_ptr); assert(tb_ptr == old_code_ptr + op_size); tb_ptr = (uint8_t *)label; continue; case INDEX_op_setcond_i32: t0 = *tb_ptr++; t1 = tci_read_r32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); condition = *tb_ptr++; tci_write_reg32(t0, tci_compare32(t1, t2, condition)); break; #if TCG_TARGET_REG_BITS == 32 case INDEX_op_setcond2_i32: t0 = *tb_ptr++; tmp64 = tci_read_r64(&tb_ptr); v64 = tci_read_ri64(&tb_ptr); condition = *tb_ptr++; tci_write_reg32(t0, tci_compare64(tmp64, v64, condition)); break; #elif TCG_TARGET_REG_BITS == 64 case INDEX_op_setcond_i64: t0 = *tb_ptr++; t1 = tci_read_r64(&tb_ptr); t2 = tci_read_ri64(&tb_ptr); condition = *tb_ptr++; tci_write_reg64(t0, tci_compare64(t1, t2, condition)); break; #endif case INDEX_op_mov_i32: t0 = *tb_ptr++; t1 = tci_read_r32(&tb_ptr); tci_write_reg32(t0, t1); break; case INDEX_op_movi_i32: t0 = *tb_ptr++; t1 = tci_read_i32(&tb_ptr); tci_write_reg32(t0, t1); break; /* Load/store operations (32 bit). */ case INDEX_op_ld8u_i32: t0 = *tb_ptr++; t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); tci_write_reg8(t0, *(uint8_t *)(t1 + t2)); break; case INDEX_op_ld8s_i32: case INDEX_op_ld16u_i32: TODO(); break; case INDEX_op_ld16s_i32: TODO(); break; case INDEX_op_ld_i32: t0 = *tb_ptr++; t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); tci_write_reg32(t0, *(uint32_t *)(t1 + t2)); break; case INDEX_op_st8_i32: t0 = tci_read_r8(&tb_ptr); t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); *(uint8_t *)(t1 + t2) = t0; break; case INDEX_op_st16_i32: t0 = tci_read_r16(&tb_ptr); t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); *(uint16_t *)(t1 + t2) = t0; break; case INDEX_op_st_i32: t0 = tci_read_r32(&tb_ptr); t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); assert(t1 != sp_value || (int32_t)t2 < 0); *(uint32_t *)(t1 + t2) = t0; break; /* Arithmetic operations (32 bit). */ case INDEX_op_add_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, t1 + t2); break; case INDEX_op_sub_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, t1 - t2); break; case INDEX_op_mul_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, t1 * t2); break; #if TCG_TARGET_HAS_div_i32 case INDEX_op_div_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, (int32_t)t1 / (int32_t)t2); break; case INDEX_op_divu_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, t1 / t2); break; case INDEX_op_rem_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, (int32_t)t1 % (int32_t)t2); break; case INDEX_op_remu_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, t1 % t2); break; #elif TCG_TARGET_HAS_div2_i32 case INDEX_op_div2_i32: case INDEX_op_divu2_i32: TODO(); break; #endif case INDEX_op_and_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, t1 & t2); break; case INDEX_op_or_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, t1 | t2); break; case INDEX_op_xor_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, t1 ^ t2); break; /* Shift/rotate operations (32 bit). */ case INDEX_op_shl_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, t1 << t2); break; case INDEX_op_shr_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, t1 >> t2); break; case INDEX_op_sar_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, ((int32_t)t1 >> t2)); break; #if TCG_TARGET_HAS_rot_i32 case INDEX_op_rotl_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, rol32(t1, t2)); break; case INDEX_op_rotr_i32: t0 = *tb_ptr++; t1 = tci_read_ri32(&tb_ptr); t2 = tci_read_ri32(&tb_ptr); tci_write_reg32(t0, ror32(t1, t2)); break; #endif #if TCG_TARGET_HAS_deposit_i32 case INDEX_op_deposit_i32: t0 = *tb_ptr++; t1 = tci_read_r32(&tb_ptr); t2 = tci_read_r32(&tb_ptr); tmp16 = *tb_ptr++; tmp8 = *tb_ptr++; tmp32 = (((1 << tmp8) - 1) << tmp16); tci_write_reg32(t0, (t1 & ~tmp32) | ((t2 << tmp16) & tmp32)); break; #endif case INDEX_op_brcond_i32: t0 = tci_read_r32(&tb_ptr); t1 = tci_read_ri32(&tb_ptr); condition = *tb_ptr++; label = tci_read_label(&tb_ptr); if (tci_compare32(t0, t1, condition)) { assert(tb_ptr == old_code_ptr + op_size); tb_ptr = (uint8_t *)label; continue; } break; #if TCG_TARGET_REG_BITS == 32 case INDEX_op_add2_i32: t0 = *tb_ptr++; t1 = *tb_ptr++; tmp64 = tci_read_r64(&tb_ptr); tmp64 += tci_read_r64(&tb_ptr); tci_write_reg64(t1, t0, tmp64); break; case INDEX_op_sub2_i32: t0 = *tb_ptr++; t1 = *tb_ptr++; tmp64 = tci_read_r64(&tb_ptr); tmp64 -= tci_read_r64(&tb_ptr); tci_write_reg64(t1, t0, tmp64); break; case INDEX_op_brcond2_i32: tmp64 = tci_read_r64(&tb_ptr); v64 = tci_read_ri64(&tb_ptr); condition = *tb_ptr++; label = tci_read_label(&tb_ptr); if (tci_compare64(tmp64, v64, condition)) { assert(tb_ptr == old_code_ptr + op_size); tb_ptr = (uint8_t *)label; continue; } break; case INDEX_op_mulu2_i32: t0 = *tb_ptr++; t1 = *tb_ptr++; t2 = tci_read_r32(&tb_ptr); tmp64 = tci_read_r32(&tb_ptr); tci_write_reg64(t1, t0, t2 * tmp64); break; #endif /* TCG_TARGET_REG_BITS == 32 */ #if TCG_TARGET_HAS_ext8s_i32 case INDEX_op_ext8s_i32: t0 = *tb_ptr++; t1 = tci_read_r8s(&tb_ptr); tci_write_reg32(t0, t1); break; #endif #if TCG_TARGET_HAS_ext16s_i32 case INDEX_op_ext16s_i32: t0 = *tb_ptr++; t1 = tci_read_r16s(&tb_ptr); tci_write_reg32(t0, t1); break; #endif #if TCG_TARGET_HAS_ext8u_i32 case INDEX_op_ext8u_i32: t0 = *tb_ptr++; t1 = tci_read_r8(&tb_ptr); tci_write_reg32(t0, t1); break; #endif #if TCG_TARGET_HAS_ext16u_i32 case INDEX_op_ext16u_i32: t0 = *tb_ptr++; t1 = tci_read_r16(&tb_ptr); tci_write_reg32(t0, t1); break; #endif #if TCG_TARGET_HAS_bswap16_i32 case INDEX_op_bswap16_i32: t0 = *tb_ptr++; t1 = tci_read_r16(&tb_ptr); tci_write_reg32(t0, bswap16(t1)); break; #endif #if TCG_TARGET_HAS_bswap32_i32 case INDEX_op_bswap32_i32: t0 = *tb_ptr++; t1 = tci_read_r32(&tb_ptr); tci_write_reg32(t0, bswap32(t1)); break; #endif #if TCG_TARGET_HAS_not_i32 case INDEX_op_not_i32: t0 = *tb_ptr++; t1 = tci_read_r32(&tb_ptr); tci_write_reg32(t0, ~t1); break; #endif #if TCG_TARGET_HAS_neg_i32 case INDEX_op_neg_i32: t0 = *tb_ptr++; t1 = tci_read_r32(&tb_ptr); tci_write_reg32(t0, -t1); break; #endif #if TCG_TARGET_REG_BITS == 64 case INDEX_op_mov_i64: t0 = *tb_ptr++; t1 = tci_read_r64(&tb_ptr); tci_write_reg64(t0, t1); break; case INDEX_op_movi_i64: t0 = *tb_ptr++; t1 = tci_read_i64(&tb_ptr); tci_write_reg64(t0, t1); break; /* Load/store operations (64 bit). */ case INDEX_op_ld8u_i64: t0 = *tb_ptr++; t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); tci_write_reg8(t0, *(uint8_t *)(t1 + t2)); break; case INDEX_op_ld8s_i64: case INDEX_op_ld16u_i64: case INDEX_op_ld16s_i64: TODO(); break; case INDEX_op_ld32u_i64: t0 = *tb_ptr++; t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); tci_write_reg32(t0, *(uint32_t *)(t1 + t2)); break; case INDEX_op_ld32s_i64: t0 = *tb_ptr++; t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); tci_write_reg32s(t0, *(int32_t *)(t1 + t2)); break; case INDEX_op_ld_i64: t0 = *tb_ptr++; t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); tci_write_reg64(t0, *(uint64_t *)(t1 + t2)); break; case INDEX_op_st8_i64: t0 = tci_read_r8(&tb_ptr); t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); *(uint8_t *)(t1 + t2) = t0; break; case INDEX_op_st16_i64: t0 = tci_read_r16(&tb_ptr); t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); *(uint16_t *)(t1 + t2) = t0; break; case INDEX_op_st32_i64: t0 = tci_read_r32(&tb_ptr); t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); *(uint32_t *)(t1 + t2) = t0; break; case INDEX_op_st_i64: t0 = tci_read_r64(&tb_ptr); t1 = tci_read_r(&tb_ptr); t2 = tci_read_s32(&tb_ptr); assert(t1 != sp_value || (int32_t)t2 < 0); *(uint64_t *)(t1 + t2) = t0; break; /* Arithmetic operations (64 bit). */ case INDEX_op_add_i64: t0 = *tb_ptr++; t1 = tci_read_ri64(&tb_ptr); t2 = tci_read_ri64(&tb_ptr); tci_write_reg64(t0, t1 + t2); break; case INDEX_op_sub_i64: t0 = *tb_ptr++; t1 = tci_read_ri64(&tb_ptr); t2 = tci_read_ri64(&tb_ptr); tci_write_reg64(t0, t1 - t2); break; case INDEX_op_mul_i64: t0 = *tb_ptr++; t1 = tci_read_ri64(&tb_ptr); t2 = tci_read_ri64(&tb_ptr); tci_write_reg64(t0, t1 * t2); break; #if TCG_TARGET_HAS_div_i64 case INDEX_op_div_i64: case INDEX_op_divu_i64: case INDEX_op_rem_i64: case INDEX_op_remu_i64: TODO(); break; #elif TCG_TARGET_HAS_div2_i64 case INDEX_op_div2_i64: case INDEX_op_divu2_i64: TODO(); break; #endif case INDEX_op_and_i64: t0 = *tb_ptr++; t1 = tci_read_ri64(&tb_ptr); t2 = tci_read_ri64(&tb_ptr); tci_write_reg64(t0, t1 & t2); break; case INDEX_op_or_i64: t0 = *tb_ptr++; t1 = tci_read_ri64(&tb_ptr); t2 = tci_read_ri64(&tb_ptr); tci_write_reg64(t0, t1 | t2); break; case INDEX_op_xor_i64: t0 = *tb_ptr++; t1 = tci_read_ri64(&tb_ptr); t2 = tci_read_ri64(&tb_ptr); tci_write_reg64(t0, t1 ^ t2); break; /* Shift/rotate operations (64 bit). */ case INDEX_op_shl_i64: t0 = *tb_ptr++; t1 = tci_read_ri64(&tb_ptr); t2 = tci_read_ri64(&tb_ptr); tci_write_reg64(t0, t1 << t2); break; case INDEX_op_shr_i64: t0 = *tb_ptr++; t1 = tci_read_ri64(&tb_ptr); t2 = tci_read_ri64(&tb_ptr); tci_write_reg64(t0, t1 >> t2); break; case INDEX_op_sar_i64: t0 = *tb_ptr++; t1 = tci_read_ri64(&tb_ptr); t2 = tci_read_ri64(&tb_ptr); tci_write_reg64(t0, ((int64_t)t1 >> t2)); break; #if TCG_TARGET_HAS_rot_i64 case INDEX_op_rotl_i64: t0 = *tb_ptr++; t1 = tci_read_ri64(&tb_ptr); t2 = tci_read_ri64(&tb_ptr); tci_write_reg64(t0, rol64(t1, t2)); break; case INDEX_op_rotr_i64: t0 = *tb_ptr++; t1 = tci_read_ri64(&tb_ptr); t2 = tci_read_ri64(&tb_ptr); tci_write_reg64(t0, ror64(t1, t2)); break; #endif #if TCG_TARGET_HAS_deposit_i64 case INDEX_op_deposit_i64: t0 = *tb_ptr++; t1 = tci_read_r64(&tb_ptr); t2 = tci_read_r64(&tb_ptr); tmp16 = *tb_ptr++; tmp8 = *tb_ptr++; tmp64 = (((1ULL << tmp8) - 1) << tmp16); tci_write_reg64(t0, (t1 & ~tmp64) | ((t2 << tmp16) & tmp64)); break; #endif case INDEX_op_brcond_i64: t0 = tci_read_r64(&tb_ptr); t1 = tci_read_ri64(&tb_ptr); condition = *tb_ptr++; label = tci_read_label(&tb_ptr); if (tci_compare64(t0, t1, condition)) { assert(tb_ptr == old_code_ptr + op_size); tb_ptr = (uint8_t *)label; continue; } break; #if TCG_TARGET_HAS_ext8u_i64 case INDEX_op_ext8u_i64: t0 = *tb_ptr++; t1 = tci_read_r8(&tb_ptr); tci_write_reg64(t0, t1); break; #endif #if TCG_TARGET_HAS_ext8s_i64 case INDEX_op_ext8s_i64: t0 = *tb_ptr++; t1 = tci_read_r8s(&tb_ptr); tci_write_reg64(t0, t1); break; #endif #if TCG_TARGET_HAS_ext16s_i64 case INDEX_op_ext16s_i64: t0 = *tb_ptr++; t1 = tci_read_r16s(&tb_ptr); tci_write_reg64(t0, t1); break; #endif #if TCG_TARGET_HAS_ext16u_i64 case INDEX_op_ext16u_i64: t0 = *tb_ptr++; t1 = tci_read_r16(&tb_ptr); tci_write_reg64(t0, t1); break; #endif #if TCG_TARGET_HAS_ext32s_i64 case INDEX_op_ext32s_i64: t0 = *tb_ptr++; t1 = tci_read_r32s(&tb_ptr); tci_write_reg64(t0, t1); break; #endif #if TCG_TARGET_HAS_ext32u_i64 case INDEX_op_ext32u_i64: t0 = *tb_ptr++; t1 = tci_read_r32(&tb_ptr); tci_write_reg64(t0, t1); break; #endif #if TCG_TARGET_HAS_bswap16_i64 case INDEX_op_bswap16_i64: TODO(); t0 = *tb_ptr++; t1 = tci_read_r16(&tb_ptr); tci_write_reg64(t0, bswap16(t1)); break; #endif #if TCG_TARGET_HAS_bswap32_i64 case INDEX_op_bswap32_i64: t0 = *tb_ptr++; t1 = tci_read_r32(&tb_ptr); tci_write_reg64(t0, bswap32(t1)); break; #endif #if TCG_TARGET_HAS_bswap64_i64 case INDEX_op_bswap64_i64: t0 = *tb_ptr++; t1 = tci_read_r64(&tb_ptr); tci_write_reg64(t0, bswap64(t1)); break; #endif #if TCG_TARGET_HAS_not_i64 case INDEX_op_not_i64: t0 = *tb_ptr++; t1 = tci_read_r64(&tb_ptr); tci_write_reg64(t0, ~t1); break; #endif #if TCG_TARGET_HAS_neg_i64 case INDEX_op_neg_i64: t0 = *tb_ptr++; t1 = tci_read_r64(&tb_ptr); tci_write_reg64(t0, -t1); break; #endif #endif /* TCG_TARGET_REG_BITS == 64 */ /* QEMU specific operations. */ #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS case INDEX_op_debug_insn_start: TODO(); break; #else case INDEX_op_debug_insn_start: TODO(); break; #endif case INDEX_op_exit_tb: next_tb = *(uint64_t *)tb_ptr; goto exit; break; case INDEX_op_goto_tb: t0 = tci_read_i32(&tb_ptr); assert(tb_ptr == old_code_ptr + op_size); tb_ptr += (int32_t)t0; continue; case INDEX_op_qemu_ld8u: t0 = *tb_ptr++; taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU tmp8 = helper_ldb_mmu(env, taddr, tci_read_i(&tb_ptr)); #else host_addr = (tcg_target_ulong)taddr; tmp8 = *(uint8_t *)(host_addr + GUEST_BASE); #endif tci_write_reg8(t0, tmp8); break; case INDEX_op_qemu_ld8s: t0 = *tb_ptr++; taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU tmp8 = helper_ldb_mmu(env, taddr, tci_read_i(&tb_ptr)); #else host_addr = (tcg_target_ulong)taddr; tmp8 = *(uint8_t *)(host_addr + GUEST_BASE); #endif tci_write_reg8s(t0, tmp8); break; case INDEX_op_qemu_ld16u: t0 = *tb_ptr++; taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU tmp16 = helper_ldw_mmu(env, taddr, tci_read_i(&tb_ptr)); #else host_addr = (tcg_target_ulong)taddr; tmp16 = tswap16(*(uint16_t *)(host_addr + GUEST_BASE)); #endif tci_write_reg16(t0, tmp16); break; case INDEX_op_qemu_ld16s: t0 = *tb_ptr++; taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU tmp16 = helper_ldw_mmu(env, taddr, tci_read_i(&tb_ptr)); #else host_addr = (tcg_target_ulong)taddr; tmp16 = tswap16(*(uint16_t *)(host_addr + GUEST_BASE)); #endif tci_write_reg16s(t0, tmp16); break; #if TCG_TARGET_REG_BITS == 64 case INDEX_op_qemu_ld32u: t0 = *tb_ptr++; taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU tmp32 = helper_ldl_mmu(env, taddr, tci_read_i(&tb_ptr)); #else host_addr = (tcg_target_ulong)taddr; tmp32 = tswap32(*(uint32_t *)(host_addr + GUEST_BASE)); #endif tci_write_reg32(t0, tmp32); break; case INDEX_op_qemu_ld32s: t0 = *tb_ptr++; taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU tmp32 = helper_ldl_mmu(env, taddr, tci_read_i(&tb_ptr)); #else host_addr = (tcg_target_ulong)taddr; tmp32 = tswap32(*(uint32_t *)(host_addr + GUEST_BASE)); #endif tci_write_reg32s(t0, tmp32); break; #endif /* TCG_TARGET_REG_BITS == 64 */ case INDEX_op_qemu_ld32: t0 = *tb_ptr++; taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU tmp32 = helper_ldl_mmu(env, taddr, tci_read_i(&tb_ptr)); #else host_addr = (tcg_target_ulong)taddr; tmp32 = tswap32(*(uint32_t *)(host_addr + GUEST_BASE)); #endif tci_write_reg32(t0, tmp32); break; case INDEX_op_qemu_ld64: t0 = *tb_ptr++; #if TCG_TARGET_REG_BITS == 32 t1 = *tb_ptr++; #endif taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU tmp64 = helper_ldq_mmu(env, taddr, tci_read_i(&tb_ptr)); #else host_addr = (tcg_target_ulong)taddr; tmp64 = tswap64(*(uint64_t *)(host_addr + GUEST_BASE)); #endif tci_write_reg(t0, tmp64); #if TCG_TARGET_REG_BITS == 32 tci_write_reg(t1, tmp64 >> 32); #endif break; case INDEX_op_qemu_st8: t0 = tci_read_r8(&tb_ptr); taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU t2 = tci_read_i(&tb_ptr); helper_stb_mmu(env, taddr, t0, t2); #else host_addr = (tcg_target_ulong)taddr; *(uint8_t *)(host_addr + GUEST_BASE) = t0; #endif break; case INDEX_op_qemu_st16: t0 = tci_read_r16(&tb_ptr); taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU t2 = tci_read_i(&tb_ptr); helper_stw_mmu(env, taddr, t0, t2); #else host_addr = (tcg_target_ulong)taddr; *(uint16_t *)(host_addr + GUEST_BASE) = tswap16(t0); #endif break; case INDEX_op_qemu_st32: t0 = tci_read_r32(&tb_ptr); taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU t2 = tci_read_i(&tb_ptr); helper_stl_mmu(env, taddr, t0, t2); #else host_addr = (tcg_target_ulong)taddr; *(uint32_t *)(host_addr + GUEST_BASE) = tswap32(t0); #endif break; case INDEX_op_qemu_st64: tmp64 = tci_read_r64(&tb_ptr); taddr = tci_read_ulong(&tb_ptr); #ifdef CONFIG_SOFTMMU t2 = tci_read_i(&tb_ptr); helper_stq_mmu(env, taddr, tmp64, t2); #else host_addr = (tcg_target_ulong)taddr; *(uint64_t *)(host_addr + GUEST_BASE) = tswap64(tmp64); #endif break; default: TODO(); break; } assert(tb_ptr == old_code_ptr + op_size); } exit: return next_tb; }
void do_m68k_simcall(CPUM68KState *env, int nr) { uint32_t *args; args = (uint32_t *)(env->aregs[7] + 4); switch (nr) { case SYS_EXIT: exit(ARG(0)); case SYS_READ: check_err(env, read(ARG(0), (void *)ARG(1), ARG(2))); break; case SYS_WRITE: check_err(env, write(ARG(0), (void *)ARG(1), ARG(2))); break; case SYS_OPEN: check_err(env, open((char *)ARG(0), translate_openflags(ARG(1)), ARG(2))); break; case SYS_CLOSE: { /* Ignore attempts to close stdin/out/err. */ int fd = ARG(0); if (fd > 2) check_err(env, close(fd)); else check_err(env, 0); break; } case SYS_BRK: { int32_t ret; ret = do_brk((void *)ARG(0)); if (ret == -ENOMEM) ret = -1; check_err(env, ret); } break; case SYS_FSTAT: { struct stat s; int rc; struct m86k_sim_stat *p; rc = check_err(env, fstat(ARG(0), &s)); if (rc == 0) { p = (struct m86k_sim_stat *)ARG(1); p->sim_st_dev = tswap16(s.st_dev); p->sim_st_ino = tswap16(s.st_ino); p->sim_st_mode = tswap32(s.st_mode); p->sim_st_nlink = tswap16(s.st_nlink); p->sim_st_uid = tswap16(s.st_uid); p->sim_st_gid = tswap16(s.st_gid); p->sim_st_rdev = tswap16(s.st_rdev); p->sim_st_size = tswap32(s.st_size); p->sim_st_atime = tswap32(s.st_atime); p->sim_st_mtime = tswap32(s.st_mtime); p->sim_st_ctime = tswap32(s.st_ctime); p->sim_st_blksize = tswap32(s.st_blksize); p->sim_st_blocks = tswap32(s.st_blocks); } } break; case SYS_ISATTY: check_err(env, isatty(ARG(0))); break; case SYS_LSEEK: check_err(env, lseek(ARG(0), (int32_t)ARG(1), ARG(2))); break; default: cpu_abort(env, "Unsupported m68k sim syscall %d\n", nr); } }
long do_mach_syscall(void *cpu_env, int num, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, uint32_t arg5, uint32_t arg6, uint32_t arg7, uint32_t arg8) { extern uint32_t mach_reply_port(); long ret = 0; arg1 = tswap32(arg1); arg2 = tswap32(arg2); arg3 = tswap32(arg3); arg4 = tswap32(arg4); arg5 = tswap32(arg5); arg6 = tswap32(arg6); arg7 = tswap32(arg7); arg8 = tswap32(arg8); DPRINTF("mach syscall %d : " , num); switch(num) { /* see xnu/osfmk/mach/syscall_sw.h */ case -26: DPRINTF("mach_reply_port()\n"); ret = mach_reply_port(); break; case -27: DPRINTF("mach_thread_self()\n"); ret = mach_thread_self(); break; case -28: DPRINTF("mach_task_self()\n"); ret = mach_task_self(); break; case -29: DPRINTF("mach_host_self()\n"); ret = mach_host_self(); break; case -31: DPRINTF("mach_msg_trap(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", arg1, arg2, arg3, arg4, arg5, arg6, arg7); ret = target_mach_msg_trap((mach_msg_header_t *)arg1, arg2, arg3, arg4, arg5, arg6, arg7); break; /* may need more translation if target arch is different from host */ #if (defined(TARGET_I386) && defined(__i386__)) || (defined(TARGET_PPC) && defined(__ppc__)) case -33: DPRINTF("semaphore_signal_trap(0x%x)\n", arg1); ret = semaphore_signal_trap(arg1); break; case -34: DPRINTF("semaphore_signal_all_trap(0x%x)\n", arg1); ret = semaphore_signal_all_trap(arg1); break; case -35: DPRINTF("semaphore_signal_thread_trap(0x%x)\n", arg1, arg2); ret = semaphore_signal_thread_trap(arg1,arg2); break; #endif case -36: DPRINTF("semaphore_wait_trap(0x%x)\n", arg1); extern int semaphore_wait_trap(int); // XXX: is there any header for that? ret = semaphore_wait_trap(arg1); break; /* may need more translation if target arch is different from host */ #if (defined(TARGET_I386) && defined(__i386__)) || (defined(TARGET_PPC) && defined(__ppc__)) case -37: DPRINTF("semaphore_wait_signal_trap(0x%x, 0x%x)\n", arg1, arg2); ret = semaphore_wait_signal_trap(arg1,arg2); break; #endif case -43: DPRINTF("map_fd(0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", arg1, arg2, arg3, arg4, arg5); ret = map_fd(arg1, arg2, (void*)arg3, arg4, arg5); tswap32s((uint32_t*)arg3); break; /* may need more translation if target arch is different from host */ #if (defined(TARGET_I386) && defined(__i386__)) || (defined(TARGET_PPC) && defined(__ppc__)) case -61: DPRINTF("syscall_thread_switch(0x%x, 0x%x, 0x%x)\n", arg1, arg2, arg3); ret = syscall_thread_switch(arg1, arg2, arg3); // just a hint to the scheduler; can drop? break; #endif case -89: DPRINTF("mach_timebase_info(0x%x)\n", arg1); struct mach_timebase_info info; ret = mach_timebase_info(&info); if(!is_error(ret)) { struct mach_timebase_info *outInfo = (void*)arg1; outInfo->numer = tswap32(info.numer); outInfo->denom = tswap32(info.denom); } break; case -90: DPRINTF("mach_wait_until()\n"); extern int mach_wait_until(uint64_t); // XXX: is there any header for that? ret = mach_wait_until(((uint64_t)arg2<<32) | (uint64_t)arg1); break; case -91: DPRINTF("mk_timer_create()\n"); extern int mk_timer_create(); // XXX: is there any header for that? ret = mk_timer_create(); break; case -92: DPRINTF("mk_timer_destroy()\n"); extern int mk_timer_destroy(int); // XXX: is there any header for that? ret = mk_timer_destroy(arg1); break; case -93: DPRINTF("mk_timer_create()\n"); extern int mk_timer_arm(int, uint64_t); // XXX: is there any header for that? ret = mk_timer_arm(arg1, ((uint64_t)arg3<<32) | (uint64_t)arg2); break; case -94: DPRINTF("mk_timer_cancel()\n"); extern int mk_timer_cancel(int, uint64_t *); // XXX: is there any header for that? ret = mk_timer_cancel(arg1, (uint64_t *)arg2); if((!is_error(ret)) && arg2) tswap64s((uint64_t *)arg2); break; default: gemu_log("qemu: Unsupported mach syscall: %d(0x%x)\n", num, num); gdb_handlesig (cpu_env, SIGTRAP); exit(0); break; } return ret; }
static void lx_init(const LxBoardDesc *board, MachineState *machine) { #ifdef TARGET_WORDS_BIGENDIAN int be = 1; #else int be = 0; #endif MemoryRegion *system_memory = get_system_memory(); XtensaCPU *cpu = NULL; CPUXtensaState *env = NULL; MemoryRegion *ram, *rom, *system_io; DriveInfo *dinfo; pflash_t *flash = NULL; QemuOpts *machine_opts = qemu_get_machine_opts(); const char *cpu_model = machine->cpu_model; const char *kernel_filename = qemu_opt_get(machine_opts, "kernel"); const char *kernel_cmdline = qemu_opt_get(machine_opts, "append"); const char *dtb_filename = qemu_opt_get(machine_opts, "dtb"); const char *initrd_filename = qemu_opt_get(machine_opts, "initrd"); int n; if (!cpu_model) { cpu_model = XTENSA_DEFAULT_CPU_MODEL; } for (n = 0; n < smp_cpus; n++) { cpu = cpu_xtensa_init(cpu_model); if (cpu == NULL) { error_report("unable to find CPU definition '%s'", cpu_model); exit(EXIT_FAILURE); } env = &cpu->env; env->sregs[PRID] = n; qemu_register_reset(lx60_reset, cpu); /* Need MMU initialized prior to ELF loading, * so that ELF gets loaded into virtual addresses */ cpu_reset(CPU(cpu)); } ram = g_malloc(sizeof(*ram)); memory_region_init_ram(ram, NULL, "lx60.dram", machine->ram_size, &error_fatal); vmstate_register_ram_global(ram); memory_region_add_subregion(system_memory, 0, ram); system_io = g_malloc(sizeof(*system_io)); memory_region_init_io(system_io, NULL, &lx60_io_ops, NULL, "lx60.io", 224 * 1024 * 1024); memory_region_add_subregion(system_memory, 0xf0000000, system_io); lx60_fpga_init(system_io, 0x0d020000); if (nd_table[0].used) { lx60_net_init(system_io, 0x0d030000, 0x0d030400, 0x0d800000, xtensa_get_extint(env, 1), nd_table); } if (!serial_hds[0]) { serial_hds[0] = qemu_chr_new("serial0", "null", NULL); } serial_mm_init(system_io, 0x0d050020, 2, xtensa_get_extint(env, 0), 115200, serial_hds[0], DEVICE_NATIVE_ENDIAN); dinfo = drive_get(IF_PFLASH, 0, 0); if (dinfo) { flash = xtfpga_flash_init(system_io, board, dinfo, be); } /* Use presence of kernel file name as 'boot from SRAM' switch. */ if (kernel_filename) { uint32_t entry_point = env->pc; size_t bp_size = 3 * get_tag_size(0); /* first/last and memory tags */ uint32_t tagptr = 0xfe000000 + board->sram_size; uint32_t cur_tagptr; BpMemInfo memory_location = { .type = tswap32(MEMORY_TYPE_CONVENTIONAL), .start = tswap32(0), .end = tswap32(machine->ram_size), }; uint32_t lowmem_end = machine->ram_size < 0x08000000 ? machine->ram_size : 0x08000000; uint32_t cur_lowmem = QEMU_ALIGN_UP(lowmem_end / 2, 4096); rom = g_malloc(sizeof(*rom)); memory_region_init_ram(rom, NULL, "lx60.sram", board->sram_size, &error_fatal); vmstate_register_ram_global(rom); memory_region_add_subregion(system_memory, 0xfe000000, rom); if (kernel_cmdline) { bp_size += get_tag_size(strlen(kernel_cmdline) + 1); } if (dtb_filename) { bp_size += get_tag_size(sizeof(uint32_t)); } if (initrd_filename) { bp_size += get_tag_size(sizeof(BpMemInfo)); } /* Put kernel bootparameters to the end of that SRAM */ tagptr = (tagptr - bp_size) & ~0xff; cur_tagptr = put_tag(tagptr, BP_TAG_FIRST, 0, NULL); cur_tagptr = put_tag(cur_tagptr, BP_TAG_MEMORY, sizeof(memory_location), &memory_location); if (kernel_cmdline) { cur_tagptr = put_tag(cur_tagptr, BP_TAG_COMMAND_LINE, strlen(kernel_cmdline) + 1, kernel_cmdline); } if (dtb_filename) { int fdt_size; void *fdt = load_device_tree(dtb_filename, &fdt_size); uint32_t dtb_addr = tswap32(cur_lowmem); if (!fdt) { error_report("could not load DTB '%s'", dtb_filename); exit(EXIT_FAILURE); } cpu_physical_memory_write(cur_lowmem, fdt, fdt_size); cur_tagptr = put_tag(cur_tagptr, BP_TAG_FDT, sizeof(dtb_addr), &dtb_addr); cur_lowmem = QEMU_ALIGN_UP(cur_lowmem + fdt_size, 4096); } if (initrd_filename) { BpMemInfo initrd_location = { 0 }; int initrd_size = load_ramdisk(initrd_filename, cur_lowmem, lowmem_end - cur_lowmem); if (initrd_size < 0) { initrd_size = load_image_targphys(initrd_filename, cur_lowmem, lowmem_end - cur_lowmem); } if (initrd_size < 0) { error_report("could not load initrd '%s'", initrd_filename); exit(EXIT_FAILURE); } initrd_location.start = tswap32(cur_lowmem); initrd_location.end = tswap32(cur_lowmem + initrd_size); cur_tagptr = put_tag(cur_tagptr, BP_TAG_INITRD, sizeof(initrd_location), &initrd_location); cur_lowmem = QEMU_ALIGN_UP(cur_lowmem + initrd_size, 4096); } cur_tagptr = put_tag(cur_tagptr, BP_TAG_LAST, 0, NULL); env->regs[2] = tagptr; uint64_t elf_entry; uint64_t elf_lowaddr; int success = load_elf(kernel_filename, translate_phys_addr, cpu, &elf_entry, &elf_lowaddr, NULL, be, EM_XTENSA, 0, 0); if (success > 0) { entry_point = elf_entry; } else { hwaddr ep; int is_linux; success = load_uimage(kernel_filename, &ep, NULL, &is_linux, translate_phys_addr, cpu); if (success > 0 && is_linux) { entry_point = ep; } else { error_report("could not load kernel '%s'", kernel_filename); exit(EXIT_FAILURE); } } if (entry_point != env->pc) { static const uint8_t jx_a0[] = { #ifdef TARGET_WORDS_BIGENDIAN 0x0a, 0, 0, #else 0xa0, 0, 0, #endif }; env->regs[0] = entry_point; cpu_physical_memory_write(env->pc, jx_a0, sizeof(jx_a0)); } } else { if (flash) { MemoryRegion *flash_mr = pflash_cfi01_get_memory(flash); MemoryRegion *flash_io = g_malloc(sizeof(*flash_io)); memory_region_init_alias(flash_io, NULL, "lx60.flash", flash_mr, board->flash_boot_base, board->flash_size - board->flash_boot_base < 0x02000000 ? board->flash_size - board->flash_boot_base : 0x02000000); memory_region_add_subregion(system_memory, 0xfe000000, flash_io); } } }
static void xtfpga_init(const XtfpgaBoardDesc *board, MachineState *machine) { #ifdef TARGET_WORDS_BIGENDIAN int be = 1; #else int be = 0; #endif MemoryRegion *system_memory = get_system_memory(); XtensaCPU *cpu = NULL; CPUXtensaState *env = NULL; MemoryRegion *system_io; DriveInfo *dinfo; pflash_t *flash = NULL; QemuOpts *machine_opts = qemu_get_machine_opts(); const char *kernel_filename = qemu_opt_get(machine_opts, "kernel"); const char *kernel_cmdline = qemu_opt_get(machine_opts, "append"); const char *dtb_filename = qemu_opt_get(machine_opts, "dtb"); const char *initrd_filename = qemu_opt_get(machine_opts, "initrd"); const unsigned system_io_size = 224 * 1024 * 1024; int n; for (n = 0; n < smp_cpus; n++) { cpu = XTENSA_CPU(cpu_create(machine->cpu_type)); env = &cpu->env; env->sregs[PRID] = n; qemu_register_reset(xtfpga_reset, cpu); /* Need MMU initialized prior to ELF loading, * so that ELF gets loaded into virtual addresses */ cpu_reset(CPU(cpu)); } if (env) { XtensaMemory sysram = env->config->sysram; sysram.location[0].size = machine->ram_size; xtensa_create_memory_regions(&env->config->instrom, "xtensa.instrom", system_memory); xtensa_create_memory_regions(&env->config->instram, "xtensa.instram", system_memory); xtensa_create_memory_regions(&env->config->datarom, "xtensa.datarom", system_memory); xtensa_create_memory_regions(&env->config->dataram, "xtensa.dataram", system_memory); xtensa_create_memory_regions(&sysram, "xtensa.sysram", system_memory); } system_io = g_malloc(sizeof(*system_io)); memory_region_init_io(system_io, NULL, &xtfpga_io_ops, NULL, "xtfpga.io", system_io_size); memory_region_add_subregion(system_memory, board->io[0], system_io); if (board->io[1]) { MemoryRegion *io = g_malloc(sizeof(*io)); memory_region_init_alias(io, NULL, "xtfpga.io.cached", system_io, 0, system_io_size); memory_region_add_subregion(system_memory, board->io[1], io); } xtfpga_fpga_init(system_io, 0x0d020000); if (nd_table[0].used) { xtfpga_net_init(system_io, 0x0d030000, 0x0d030400, 0x0d800000, xtensa_get_extint(env, 1), nd_table); } if (!serial_hds[0]) { serial_hds[0] = qemu_chr_new("serial0", "null"); } serial_mm_init(system_io, 0x0d050020, 2, xtensa_get_extint(env, 0), 115200, serial_hds[0], DEVICE_NATIVE_ENDIAN); dinfo = drive_get(IF_PFLASH, 0, 0); if (dinfo) { flash = xtfpga_flash_init(system_io, board, dinfo, be); } /* Use presence of kernel file name as 'boot from SRAM' switch. */ if (kernel_filename) { uint32_t entry_point = env->pc; size_t bp_size = 3 * get_tag_size(0); /* first/last and memory tags */ uint32_t tagptr = env->config->sysrom.location[0].addr + board->sram_size; uint32_t cur_tagptr; BpMemInfo memory_location = { .type = tswap32(MEMORY_TYPE_CONVENTIONAL), .start = tswap32(env->config->sysram.location[0].addr), .end = tswap32(env->config->sysram.location[0].addr + machine->ram_size), }; uint32_t lowmem_end = machine->ram_size < 0x08000000 ? machine->ram_size : 0x08000000; uint32_t cur_lowmem = QEMU_ALIGN_UP(lowmem_end / 2, 4096); lowmem_end += env->config->sysram.location[0].addr; cur_lowmem += env->config->sysram.location[0].addr; xtensa_create_memory_regions(&env->config->sysrom, "xtensa.sysrom", system_memory); if (kernel_cmdline) { bp_size += get_tag_size(strlen(kernel_cmdline) + 1); } if (dtb_filename) { bp_size += get_tag_size(sizeof(uint32_t)); } if (initrd_filename) { bp_size += get_tag_size(sizeof(BpMemInfo)); } /* Put kernel bootparameters to the end of that SRAM */ tagptr = (tagptr - bp_size) & ~0xff; cur_tagptr = put_tag(tagptr, BP_TAG_FIRST, 0, NULL); cur_tagptr = put_tag(cur_tagptr, BP_TAG_MEMORY, sizeof(memory_location), &memory_location); if (kernel_cmdline) { cur_tagptr = put_tag(cur_tagptr, BP_TAG_COMMAND_LINE, strlen(kernel_cmdline) + 1, kernel_cmdline); } #ifdef CONFIG_FDT if (dtb_filename) { int fdt_size; void *fdt = load_device_tree(dtb_filename, &fdt_size); uint32_t dtb_addr = tswap32(cur_lowmem); if (!fdt) { error_report("could not load DTB '%s'", dtb_filename); exit(EXIT_FAILURE); } cpu_physical_memory_write(cur_lowmem, fdt, fdt_size); cur_tagptr = put_tag(cur_tagptr, BP_TAG_FDT, sizeof(dtb_addr), &dtb_addr); cur_lowmem = QEMU_ALIGN_UP(cur_lowmem + fdt_size, 4096); } #else if (dtb_filename) { error_report("could not load DTB '%s': " "FDT support is not configured in QEMU", dtb_filename); exit(EXIT_FAILURE); } #endif if (initrd_filename) { BpMemInfo initrd_location = { 0 }; int initrd_size = load_ramdisk(initrd_filename, cur_lowmem, lowmem_end - cur_lowmem); if (initrd_size < 0) { initrd_size = load_image_targphys(initrd_filename, cur_lowmem, lowmem_end - cur_lowmem); } if (initrd_size < 0) { error_report("could not load initrd '%s'", initrd_filename); exit(EXIT_FAILURE); } initrd_location.start = tswap32(cur_lowmem); initrd_location.end = tswap32(cur_lowmem + initrd_size); cur_tagptr = put_tag(cur_tagptr, BP_TAG_INITRD, sizeof(initrd_location), &initrd_location); cur_lowmem = QEMU_ALIGN_UP(cur_lowmem + initrd_size, 4096); } cur_tagptr = put_tag(cur_tagptr, BP_TAG_LAST, 0, NULL); env->regs[2] = tagptr; uint64_t elf_entry; uint64_t elf_lowaddr; int success = load_elf(kernel_filename, translate_phys_addr, cpu, &elf_entry, &elf_lowaddr, NULL, be, EM_XTENSA, 0, 0); if (success > 0) { entry_point = elf_entry; } else { hwaddr ep; int is_linux; success = load_uimage(kernel_filename, &ep, NULL, &is_linux, translate_phys_addr, cpu); if (success > 0 && is_linux) { entry_point = ep; } else { error_report("could not load kernel '%s'", kernel_filename); exit(EXIT_FAILURE); } } if (entry_point != env->pc) { uint8_t boot[] = { #ifdef TARGET_WORDS_BIGENDIAN 0x60, 0x00, 0x08, /* j 1f */ 0x00, /* .literal_position */ 0x00, 0x00, 0x00, 0x00, /* .literal entry_pc */ 0x00, 0x00, 0x00, 0x00, /* .literal entry_a2 */ /* 1: */ 0x10, 0xff, 0xfe, /* l32r a0, entry_pc */ 0x12, 0xff, 0xfe, /* l32r a2, entry_a2 */ 0x0a, 0x00, 0x00, /* jx a0 */ #else 0x06, 0x02, 0x00, /* j 1f */ 0x00, /* .literal_position */ 0x00, 0x00, 0x00, 0x00, /* .literal entry_pc */ 0x00, 0x00, 0x00, 0x00, /* .literal entry_a2 */ /* 1: */ 0x01, 0xfe, 0xff, /* l32r a0, entry_pc */ 0x21, 0xfe, 0xff, /* l32r a2, entry_a2 */ 0xa0, 0x00, 0x00, /* jx a0 */ #endif }; uint32_t entry_pc = tswap32(entry_point); uint32_t entry_a2 = tswap32(tagptr); memcpy(boot + 4, &entry_pc, sizeof(entry_pc)); memcpy(boot + 8, &entry_a2, sizeof(entry_a2)); cpu_physical_memory_write(env->pc, boot, sizeof(boot)); } } else { if (flash) { MemoryRegion *flash_mr = pflash_cfi01_get_memory(flash); MemoryRegion *flash_io = g_malloc(sizeof(*flash_io)); uint32_t size = env->config->sysrom.location[0].size; if (board->flash->size - board->flash->boot_base < size) { size = board->flash->size - board->flash->boot_base; } memory_region_init_alias(flash_io, NULL, "xtfpga.flash", flash_mr, board->flash->boot_base, size); memory_region_add_subregion(system_memory, env->config->sysrom.location[0].addr, flash_io); } else { xtensa_create_memory_regions(&env->config->sysrom, "xtensa.sysrom", system_memory); } } }
/* now we can define the main conversion functions */ const argtype *thunk_convert(void *dst, const void *src, const argtype *type_ptr, int to_host) { int type; type = *type_ptr++; switch(type) { case TYPE_CHAR: *(uint8_t *)dst = *(uint8_t *)src; break; case TYPE_SHORT: *(uint16_t *)dst = tswap16(*(uint16_t *)src); break; case TYPE_INT: *(uint32_t *)dst = tswap32(*(uint32_t *)src); break; case TYPE_LONGLONG: case TYPE_ULONGLONG: *(uint64_t *)dst = tswap64(*(uint64_t *)src); break; #if HOST_LONG_BITS == 32 && TARGET_ABI_BITS == 32 case TYPE_LONG: case TYPE_ULONG: case TYPE_PTRVOID: *(uint32_t *)dst = tswap32(*(uint32_t *)src); break; #elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 32 case TYPE_LONG: case TYPE_ULONG: case TYPE_PTRVOID: if (to_host) { if (type == TYPE_LONG) { /* sign extension */ *(uint64_t *)dst = (int32_t)tswap32(*(uint32_t *)src); } else { *(uint64_t *)dst = tswap32(*(uint32_t *)src); } } else { *(uint32_t *)dst = tswap32(*(uint64_t *)src & 0xffffffff); } break; #elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 64 case TYPE_LONG: case TYPE_ULONG: case TYPE_PTRVOID: *(uint64_t *)dst = tswap64(*(uint64_t *)src); break; #elif HOST_LONG_BITS == 32 && TARGET_ABI_BITS == 64 case TYPE_LONG: case TYPE_ULONG: case TYPE_PTRVOID: if (to_host) { *(uint32_t *)dst = tswap64(*(uint64_t *)src); } else { if (type == TYPE_LONG) { /* sign extension */ *(uint64_t *)dst = tswap64(*(int32_t *)src); } else { *(uint64_t *)dst = tswap64(*(uint32_t *)src); } } break; #else #warning unsupported conversion #endif case TYPE_ARRAY: { int array_length, i, dst_size, src_size; const uint8_t *s; uint8_t *d; array_length = *type_ptr++; dst_size = thunk_type_size(type_ptr, to_host); src_size = thunk_type_size(type_ptr, 1 - to_host); d = dst; s = src; for(i = 0;i < array_length; i++) { thunk_convert(d, s, type_ptr, to_host); d += dst_size; s += src_size; } type_ptr = thunk_type_next(type_ptr); } break; case TYPE_STRUCT: { int i; const StructEntry *se; const uint8_t *s; uint8_t *d; const argtype *field_types; const int *dst_offsets, *src_offsets; se = struct_entries + *type_ptr++; if (se->convert[0] != NULL) { /* specific conversion is needed */ (*se->convert[to_host])(dst, src); } else { /* standard struct conversion */ field_types = se->field_types; dst_offsets = se->field_offsets[to_host]; src_offsets = se->field_offsets[1 - to_host]; d = dst; s = src; for(i = 0;i < se->nb_fields; i++) { field_types = thunk_convert(d + dst_offsets[i], s + src_offsets[i], field_types, to_host); } } } break; default: fprintf(stderr, "Invalid type 0x%x\n", type); break; } return type_ptr; }
static void eth_write(void *opaque, hwaddr addr, uint64_t val64, unsigned int size) { struct xlx_ethlite *s = opaque; unsigned int base = 0; uint32_t value = val64; addr >>= 2; switch (addr) { case R_TX_CTRL0: case R_TX_CTRL1: if (addr == R_TX_CTRL1) base = 0x800 / 4; D(qemu_log("%s addr=" TARGET_FMT_plx " val=%x\n", __func__, addr * 4, value)); if ((value & (CTRL_P | CTRL_S)) == CTRL_S) { qemu_send_packet(qemu_get_queue(s->nic), (void *) &s->regs[base], s->regs[base + R_TX_LEN0]); D(qemu_log("eth_tx %d\n", s->regs[base + R_TX_LEN0])); if (s->regs[base + R_TX_CTRL0] & CTRL_I) eth_pulse_irq(s); } else if ((value & (CTRL_P | CTRL_S)) == (CTRL_P | CTRL_S)) { memcpy(&s->conf.macaddr.a[0], &s->regs[base], 6); if (s->regs[base + R_TX_CTRL0] & CTRL_I) eth_pulse_irq(s); } /* We are fast and get ready pretty much immediately so we actually never flip the S nor P bits to one. */ s->regs[addr] = value & ~(CTRL_P | CTRL_S); break; /* Keep these native. */ case R_RX_CTRL0: case R_RX_CTRL1: if (!(value & CTRL_S)) { qemu_flush_queued_packets(qemu_get_queue(s->nic)); } case R_TX_LEN0: case R_TX_LEN1: case R_TX_GIE0: D(qemu_log("%s addr=" TARGET_FMT_plx " val=%x\n", __func__, addr * 4, value)); s->regs[addr] = value; break; case R_MDIOCTRL: if (((unsigned int)value & R_MDIOCTRL_MDIOSTS_MASK) != 0) { struct TEMAC *t = &s->TEMAC; unsigned int op = s->regs[R_MDIOADDR] & R_MDIOADDR_OP_MASK; unsigned int phyaddr = (s->regs[R_MDIOADDR] & R_MDIOADDR_PHYADR_MASK) >> R_MDIOADDR_PHYADR_SHIFT; unsigned int regaddr = s->regs[R_MDIOADDR] & R_MDIOADDR_REGADR_MASK; if (op) { /* read PHY registers */ s->regs[R_MDIORD] = mdio_read_req( &t->mdio_bus, phyaddr, regaddr); } else { /* write PHY registers */ mdio_write_req(&t->mdio_bus, phyaddr, regaddr, s->regs[R_MDIOWR]); } } s->regs[addr] = value; default: s->regs[addr] = tswap32(value); break; } }
static int64_t load_kernel(void) { int64_t entry, kernel_high; long kernel_size, initrd_size, params_size; ram_addr_t initrd_offset; uint32_t *params_buf; int big_endian; #ifdef TARGET_WORDS_BIGENDIAN big_endian = 1; #else big_endian = 0; #endif kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL, (uint64_t *)&entry, NULL, (uint64_t *)&kernel_high, big_endian, ELF_MACHINE, 1); if (kernel_size >= 0) { if ((entry & ~0x7fffffffULL) == 0x80000000) entry = (int32_t)entry; } else { fprintf(stderr, "qemu: could not load kernel '%s'\n", loaderparams.kernel_filename); exit(1); } /* load initrd */ initrd_size = 0; initrd_offset = 0; if (loaderparams.initrd_filename) { initrd_size = get_image_size (loaderparams.initrd_filename); if (initrd_size > 0) { initrd_offset = (kernel_high + ~TARGET_PAGE_MASK) & TARGET_PAGE_MASK; if (initrd_offset + initrd_size > ram_size) { fprintf(stderr, "qemu: memory too small for initial ram disk '%s'\n", loaderparams.initrd_filename); exit(1); } initrd_size = load_image_targphys(loaderparams.initrd_filename, initrd_offset, ram_size - initrd_offset); } if (initrd_size == (target_ulong) -1) { fprintf(stderr, "qemu: could not load initial ram disk '%s'\n", loaderparams.initrd_filename); exit(1); } } /* Store command line. */ params_size = 264; params_buf = qemu_malloc(params_size); params_buf[0] = tswap32(ram_size); params_buf[1] = tswap32(0x12345678); if (initrd_size > 0) { snprintf((char *)params_buf + 8, 256, "rd_start=0x%" PRIx64 " rd_size=%li %s", cpu_mips_phys_to_kseg0(NULL, initrd_offset), initrd_size, loaderparams.kernel_cmdline); } else { snprintf((char *)params_buf + 8, 256, "%s", loaderparams.kernel_cmdline); } rom_add_blob_fixed("params", params_buf, params_size, (16 << 20) - 264); return entry; }