static void r2d_init(ram_addr_t ram_size, int vga_ram_size, const char *boot_device, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { CPUState *env; struct SH7750State *s; ram_addr_t sdram_addr, sm501_vga_ram_addr; qemu_irq *irq; PCIBus *pci; int i; if (!cpu_model) cpu_model = "SH7751R"; env = cpu_init(cpu_model); if (!env) { fprintf(stderr, "Unable to find CPU definition\n"); exit(1); } /* Allocate memory space */ sdram_addr = qemu_ram_alloc(SDRAM_SIZE); cpu_register_physical_memory(SDRAM_BASE, SDRAM_SIZE, sdram_addr); /* Register peripherals */ s = sh7750_init(env); irq = r2d_fpga_init(0x04000000, sh7750_irl(s)); pci = sh_pci_register_bus(r2d_pci_set_irq, r2d_pci_map_irq, irq, 0, 4); sm501_vga_ram_addr = qemu_ram_alloc(SM501_VRAM_SIZE); sm501_init(0x10000000, sm501_vga_ram_addr, SM501_VRAM_SIZE, serial_hds[2]); /* onboard CF (True IDE mode, Master only). */ mmio_ide_init(0x14001000, 0x1400080c, irq[CF_IDE], 1, drives_table[drive_get_index(IF_IDE, 0, 0)].bdrv, NULL); /* NIC: rtl8139 on-board, and 2 slots. */ pci_nic_init(pci, &nd_table[0], 2 << 3, "rtl8139"); for (i = 1; i < nb_nics; i++) pci_nic_init(pci, &nd_table[i], -1, "ne2k_pci"); /* Todo: register on board registers */ { int kernel_size; /* initialization which should be done by firmware */ stl_phys(SH7750_BCR1, 1<<3); /* cs3 SDRAM */ stw_phys(SH7750_BCR2, 3<<(3*2)); /* cs3 32bit */ kernel_size = load_image(kernel_filename, phys_ram_base); if (kernel_size < 0) { fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename); exit(1); } env->pc = SDRAM_BASE | 0xa0000000; /* Start from P2 area */ } }
static inline void vring_avail_event(VirtQueue *vq, uint16_t val) { hwaddr pa; if (!vq->notification) { return; } pa = vq->vring.used + offsetof(VRingUsed, ring[vq->vring.num]); stw_phys(pa, val); }
static inline void vring_used_flags_unset_bit(VirtQueue *vq, int mask) { hwaddr pa; pa = vq->vring.used + offsetof(VRingUsed, flags); stw_phys(pa, lduw_phys(pa) & ~mask); }
static inline void vring_used_idx_set(VirtQueue *vq, uint16_t val) { hwaddr pa; pa = vq->vring.used + offsetof(VRingUsed, idx); stw_phys(pa, val); }
static inline void vring_used_flags_set_bit(VirtQueue *vq, int mask) { target_phys_addr_t pa; pa = vq->vring.used + offsetof(VRingUsed, flags); stw_phys(pa, lduw_phys(pa) | mask); }
/* * Handle writes to CSRs and any resulting special behavior * * Note: mtohost and mfromhost are not handled here */ inline void csr_write_helper(CPURISCVState *env, target_ulong val_to_write, target_ulong csrno) { #ifdef RISCV_DEBUG_PRINT fprintf(stderr, "Write CSR reg: 0x" TARGET_FMT_lx "\n", csrno); fprintf(stderr, "Write CSR val: 0x" TARGET_FMT_lx "\n", val_to_write); #endif switch (csrno) { case NEW_CSR_FFLAGS: env->csr[NEW_CSR_MSTATUS] |= MSTATUS_FS | MSTATUS64_SD; env->csr[NEW_CSR_FFLAGS] = val_to_write & (FSR_AEXC >> FSR_AEXC_SHIFT); break; case NEW_CSR_FRM: env->csr[NEW_CSR_MSTATUS] |= MSTATUS_FS | MSTATUS64_SD; env->csr[NEW_CSR_FRM] = val_to_write & (FSR_RD >> FSR_RD_SHIFT); break; case NEW_CSR_FCSR: env->csr[NEW_CSR_MSTATUS] |= MSTATUS_FS | MSTATUS64_SD; env->csr[NEW_CSR_FFLAGS] = (val_to_write & FSR_AEXC) >> FSR_AEXC_SHIFT; env->csr[NEW_CSR_FRM] = (val_to_write & FSR_RD) >> FSR_RD_SHIFT; break; case NEW_CSR_MTIME: case NEW_CSR_STIMEW: // this implementation ignores writes to MTIME break; case NEW_CSR_MTIMEH: case NEW_CSR_STIMEHW: // this implementation ignores writes to MTIME break; case NEW_CSR_TIMEW: cpu_riscv_store_timew(env, val_to_write); break; case NEW_CSR_TIMEHW: fprintf(stderr, "CSR_TIMEHW unsupported on RV64I\n"); exit(1); break; case NEW_CSR_CYCLEW: case NEW_CSR_INSTRETW: cpu_riscv_store_instretw(env, val_to_write); break; case NEW_CSR_CYCLEHW: case NEW_CSR_INSTRETHW: fprintf(stderr, "CSR_CYCLEHW/INSTRETHW unsupported on RV64I\n"); exit(1); break; case NEW_CSR_MSTATUS: { target_ulong mstatus = env->csr[NEW_CSR_MSTATUS]; #ifdef RISCV_DEBUG_PRINT target_ulong debug_mstatus = mstatus; #endif if ((val_to_write ^ mstatus) & (MSTATUS_VM | MSTATUS_PRV | MSTATUS_PRV1 | MSTATUS_MPRV)) { #ifdef RISCV_DEBUG_PRINT fprintf(stderr, "flushing TLB\n"); #endif helper_tlb_flush(env); } // no extension support target_ulong mask = MSTATUS_IE | MSTATUS_IE1 | MSTATUS_IE2 | MSTATUS_MPRV | MSTATUS_FS; if (validate_vm(get_field(val_to_write, MSTATUS_VM))) { mask |= MSTATUS_VM; } if (validate_priv(get_field(val_to_write, MSTATUS_PRV))) { mask |= MSTATUS_PRV; } if (validate_priv(get_field(val_to_write, MSTATUS_PRV1))) { mask |= MSTATUS_PRV1; } if (validate_priv(get_field(val_to_write, MSTATUS_PRV2))) { mask |= MSTATUS_PRV2; } mstatus = (mstatus & ~mask) | (val_to_write & mask); int dirty = (mstatus & MSTATUS_FS) == MSTATUS_FS; dirty |= (mstatus & MSTATUS_XS) == MSTATUS_XS; mstatus = set_field(mstatus, MSTATUS64_SD, dirty); env->csr[NEW_CSR_MSTATUS] = mstatus; break; } case NEW_CSR_MIP: { target_ulong mask = MIP_SSIP | MIP_MSIP | MIP_STIP; env->csr[NEW_CSR_MIP] = (env->csr[NEW_CSR_MIP] & ~mask) | (val_to_write & mask); CPUState *cs = CPU(riscv_env_get_cpu(env)); if (env->csr[NEW_CSR_MIP] & MIP_SSIP) { stw_phys(cs->as, 0xFFFFFFFFF0000020, 0x1); } else { stw_phys(cs->as, 0xFFFFFFFFF0000020, 0x0); } if (env->csr[NEW_CSR_MIP] & MIP_STIP) { stw_phys(cs->as, 0xFFFFFFFFF0000040, 0x1); } else { stw_phys(cs->as, 0xFFFFFFFFF0000040, 0x0); } if (env->csr[NEW_CSR_MIP] & MIP_MSIP) { stw_phys(cs->as, 0xFFFFFFFFF0000060, 0x1); } else { stw_phys(cs->as, 0xFFFFFFFFF0000060, 0x0); } break; } case NEW_CSR_MIPI: { CPUState *cs = CPU(riscv_env_get_cpu(env)); env->csr[NEW_CSR_MIP] = set_field(env->csr[NEW_CSR_MIP], MIP_MSIP, val_to_write & 1); if (env->csr[NEW_CSR_MIP] & MIP_MSIP) { stw_phys(cs->as, 0xFFFFFFFFF0000060, 0x1); } else { stw_phys(cs->as, 0xFFFFFFFFF0000060, 0x0); } break; } case NEW_CSR_MIE: { target_ulong mask = MIP_SSIP | MIP_MSIP | MIP_STIP | MIP_MTIP; env->csr[NEW_CSR_MIE] = (env->csr[NEW_CSR_MIE] & ~mask) | (val_to_write & mask); break; } case NEW_CSR_SSTATUS: { target_ulong ms = env->csr[NEW_CSR_MSTATUS]; ms = set_field(ms, MSTATUS_IE, get_field(val_to_write, SSTATUS_IE)); ms = set_field(ms, MSTATUS_IE1, get_field(val_to_write, SSTATUS_PIE)); ms = set_field(ms, MSTATUS_PRV1, get_field(val_to_write, SSTATUS_PS)); ms = set_field(ms, MSTATUS_FS, get_field(val_to_write, SSTATUS_FS)); ms = set_field(ms, MSTATUS_XS, get_field(val_to_write, SSTATUS_XS)); ms = set_field(ms, MSTATUS_MPRV, get_field(val_to_write, SSTATUS_MPRV)); csr_write_helper(env, ms, NEW_CSR_MSTATUS); break; } case NEW_CSR_SIP: { target_ulong mask = MIP_SSIP; env->csr[NEW_CSR_MIP] = (env->csr[NEW_CSR_MIP] & ~mask) | (val_to_write & mask); CPUState *cs = CPU(riscv_env_get_cpu(env)); if (env->csr[NEW_CSR_MIP] & MIP_SSIP) { stw_phys(cs->as, 0xFFFFFFFFF0000020, 0x1); } else { stw_phys(cs->as, 0xFFFFFFFFF0000020, 0x0); } break; } case NEW_CSR_SIE: { target_ulong mask = MIP_SSIP | MIP_STIP | MIP_SXIP; env->csr[NEW_CSR_MIE] = (env->csr[NEW_CSR_MIE] & ~mask) | (val_to_write & mask); break; } case NEW_CSR_SEPC: env->csr[NEW_CSR_SEPC] = val_to_write; break; case NEW_CSR_STVEC: env->csr[NEW_CSR_STVEC] = val_to_write >> 2 << 2; break; case NEW_CSR_SPTBR: env->csr[NEW_CSR_SPTBR] = val_to_write & -(1L << PGSHIFT); break; case NEW_CSR_SSCRATCH: env->csr[NEW_CSR_SSCRATCH] = val_to_write; break; case NEW_CSR_MEPC: env->csr[NEW_CSR_MEPC] = val_to_write; break; case NEW_CSR_MSCRATCH: env->csr[NEW_CSR_MSCRATCH] = val_to_write; break; case NEW_CSR_MCAUSE: env->csr[NEW_CSR_MCAUSE] = val_to_write; break; case NEW_CSR_MBADADDR: env->csr[NEW_CSR_MBADADDR] = val_to_write; break; case NEW_CSR_MTIMECMP: // NOTE: clearing bit in MIP handled in cpu_riscv_store_compare cpu_riscv_store_compare(env, val_to_write); break; case NEW_CSR_MTOHOST: fprintf(stderr, "Write to mtohost should not be handled here\n"); exit(1); break; case NEW_CSR_MFROMHOST: fprintf(stderr, "Write to mfromhost should not be handled here\n"); exit(1); break; } }
void do_smm_enter(X86CPU *cpu) { CPUX86State *env = &cpu->env; CPUState *cs = CPU(cpu); target_ulong sm_state; SegmentCache *dt; int i, offset; qemu_log_mask(CPU_LOG_INT, "SMM: enter\n"); log_cpu_state_mask(CPU_LOG_INT, CPU(cpu), CPU_DUMP_CCOP); env->hflags |= HF_SMM_MASK; cpu_smm_update(env); sm_state = env->smbase + 0x8000; #ifdef TARGET_X86_64 for (i = 0; i < 6; i++) { dt = &env->segs[i]; offset = 0x7e00 + i * 16; stw_phys(cs->as, sm_state + offset, dt->selector); stw_phys(cs->as, sm_state + offset + 2, (dt->flags >> 8) & 0xf0ff); stl_phys(cs->as, sm_state + offset + 4, dt->limit); stq_phys(cs->as, sm_state + offset + 8, dt->base); } stq_phys(cs->as, sm_state + 0x7e68, env->gdt.base); stl_phys(cs->as, sm_state + 0x7e64, env->gdt.limit); stw_phys(cs->as, sm_state + 0x7e70, env->ldt.selector); stq_phys(cs->as, sm_state + 0x7e78, env->ldt.base); stl_phys(cs->as, sm_state + 0x7e74, env->ldt.limit); stw_phys(cs->as, sm_state + 0x7e72, (env->ldt.flags >> 8) & 0xf0ff); stq_phys(cs->as, sm_state + 0x7e88, env->idt.base); stl_phys(cs->as, sm_state + 0x7e84, env->idt.limit); stw_phys(cs->as, sm_state + 0x7e90, env->tr.selector); stq_phys(cs->as, sm_state + 0x7e98, env->tr.base); stl_phys(cs->as, sm_state + 0x7e94, env->tr.limit); stw_phys(cs->as, sm_state + 0x7e92, (env->tr.flags >> 8) & 0xf0ff); stq_phys(cs->as, sm_state + 0x7ed0, env->efer); stq_phys(cs->as, sm_state + 0x7ff8, env->regs[R_EAX]); stq_phys(cs->as, sm_state + 0x7ff0, env->regs[R_ECX]); stq_phys(cs->as, sm_state + 0x7fe8, env->regs[R_EDX]); stq_phys(cs->as, sm_state + 0x7fe0, env->regs[R_EBX]); stq_phys(cs->as, sm_state + 0x7fd8, env->regs[R_ESP]); stq_phys(cs->as, sm_state + 0x7fd0, env->regs[R_EBP]); stq_phys(cs->as, sm_state + 0x7fc8, env->regs[R_ESI]); stq_phys(cs->as, sm_state + 0x7fc0, env->regs[R_EDI]); for (i = 8; i < 16; i++) { stq_phys(cs->as, sm_state + 0x7ff8 - i * 8, env->regs[i]); } stq_phys(cs->as, sm_state + 0x7f78, env->eip); stl_phys(cs->as, sm_state + 0x7f70, cpu_compute_eflags(env)); stl_phys(cs->as, sm_state + 0x7f68, env->dr[6]); stl_phys(cs->as, sm_state + 0x7f60, env->dr[7]); stl_phys(cs->as, sm_state + 0x7f48, env->cr[4]); stl_phys(cs->as, sm_state + 0x7f50, env->cr[3]); stl_phys(cs->as, sm_state + 0x7f58, env->cr[0]); stl_phys(cs->as, sm_state + 0x7efc, SMM_REVISION_ID); stl_phys(cs->as, sm_state + 0x7f00, env->smbase); #else stl_phys(cs->as, sm_state + 0x7ffc, env->cr[0]); stl_phys(cs->as, sm_state + 0x7ff8, env->cr[3]); stl_phys(cs->as, sm_state + 0x7ff4, cpu_compute_eflags(env)); stl_phys(cs->as, sm_state + 0x7ff0, env->eip); stl_phys(cs->as, sm_state + 0x7fec, env->regs[R_EDI]); stl_phys(cs->as, sm_state + 0x7fe8, env->regs[R_ESI]); stl_phys(cs->as, sm_state + 0x7fe4, env->regs[R_EBP]); stl_phys(cs->as, sm_state + 0x7fe0, env->regs[R_ESP]); stl_phys(cs->as, sm_state + 0x7fdc, env->regs[R_EBX]); stl_phys(cs->as, sm_state + 0x7fd8, env->regs[R_EDX]); stl_phys(cs->as, sm_state + 0x7fd4, env->regs[R_ECX]); stl_phys(cs->as, sm_state + 0x7fd0, env->regs[R_EAX]); stl_phys(cs->as, sm_state + 0x7fcc, env->dr[6]); stl_phys(cs->as, sm_state + 0x7fc8, env->dr[7]); stl_phys(cs->as, sm_state + 0x7fc4, env->tr.selector); stl_phys(cs->as, sm_state + 0x7f64, env->tr.base); stl_phys(cs->as, sm_state + 0x7f60, env->tr.limit); stl_phys(cs->as, sm_state + 0x7f5c, (env->tr.flags >> 8) & 0xf0ff); stl_phys(cs->as, sm_state + 0x7fc0, env->ldt.selector); stl_phys(cs->as, sm_state + 0x7f80, env->ldt.base); stl_phys(cs->as, sm_state + 0x7f7c, env->ldt.limit); stl_phys(cs->as, sm_state + 0x7f78, (env->ldt.flags >> 8) & 0xf0ff); stl_phys(cs->as, sm_state + 0x7f74, env->gdt.base); stl_phys(cs->as, sm_state + 0x7f70, env->gdt.limit); stl_phys(cs->as, sm_state + 0x7f58, env->idt.base); stl_phys(cs->as, sm_state + 0x7f54, env->idt.limit); for (i = 0; i < 6; i++) { dt = &env->segs[i]; if (i < 3) { offset = 0x7f84 + i * 12; } else { offset = 0x7f2c + (i - 3) * 12; } stl_phys(cs->as, sm_state + 0x7fa8 + i * 4, dt->selector); stl_phys(cs->as, sm_state + offset + 8, dt->base); stl_phys(cs->as, sm_state + offset + 4, dt->limit); stl_phys(cs->as, sm_state + offset, (dt->flags >> 8) & 0xf0ff); } stl_phys(cs->as, sm_state + 0x7f14, env->cr[4]); stl_phys(cs->as, sm_state + 0x7efc, SMM_REVISION_ID); stl_phys(cs->as, sm_state + 0x7ef8, env->smbase); #endif /* init SMM cpu state */ #ifdef TARGET_X86_64 cpu_load_efer(env, 0); #endif cpu_load_eflags(env, 0, ~(CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C | DF_MASK)); env->eip = 0x00008000; cpu_x86_update_cr0(env, env->cr[0] & ~(CR0_PE_MASK | CR0_EM_MASK | CR0_TS_MASK | CR0_PG_MASK)); cpu_x86_update_cr4(env, 0); env->dr[7] = 0x00000400; cpu_x86_load_seg_cache(env, R_CS, (env->smbase >> 4) & 0xffff, env->smbase, 0xffffffff, DESC_P_MASK | DESC_S_MASK | DESC_W_MASK | DESC_A_MASK); cpu_x86_load_seg_cache(env, R_DS, 0, 0, 0xffffffff, DESC_P_MASK | DESC_S_MASK | DESC_W_MASK | DESC_A_MASK); cpu_x86_load_seg_cache(env, R_ES, 0, 0, 0xffffffff, DESC_P_MASK | DESC_S_MASK | DESC_W_MASK | DESC_A_MASK); cpu_x86_load_seg_cache(env, R_SS, 0, 0, 0xffffffff, DESC_P_MASK | DESC_S_MASK | DESC_W_MASK | DESC_A_MASK); cpu_x86_load_seg_cache(env, R_FS, 0, 0, 0xffffffff, DESC_P_MASK | DESC_S_MASK | DESC_W_MASK | DESC_A_MASK); cpu_x86_load_seg_cache(env, R_GS, 0, 0, 0xffffffff, DESC_P_MASK | DESC_S_MASK | DESC_W_MASK | DESC_A_MASK); }
static void r2d_init(ram_addr_t ram_size, const char *boot_device, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { CPUState *env; struct SH7750State *s; ram_addr_t sdram_addr; qemu_irq *irq; PCIBus *pci; DriveInfo *dinfo; int i; if (!cpu_model) cpu_model = "SH7751R"; env = cpu_init(cpu_model); if (!env) { fprintf(stderr, "Unable to find CPU definition\n"); exit(1); } /* Allocate memory space */ sdram_addr = qemu_ram_alloc(SDRAM_SIZE); cpu_register_physical_memory(SDRAM_BASE, SDRAM_SIZE, sdram_addr); /* Register peripherals */ s = sh7750_init(env); irq = r2d_fpga_init(0x04000000, sh7750_irl(s)); pci = sh_pci_register_bus(r2d_pci_set_irq, r2d_pci_map_irq, irq, 0, 4); sm501_init(0x10000000, SM501_VRAM_SIZE, irq[SM501], serial_hds[2]); /* onboard CF (True IDE mode, Master only). */ if ((dinfo = drive_get(IF_IDE, 0, 0)) != NULL) mmio_ide_init(0x14001000, 0x1400080c, irq[CF_IDE], 1, dinfo, NULL); /* NIC: rtl8139 on-board, and 2 slots. */ for (i = 0; i < nb_nics; i++) pci_nic_init_nofail(&nd_table[i], "rtl8139", i==0 ? "2" : NULL); /* Todo: register on board registers */ if (kernel_filename) { int kernel_size; /* initialization which should be done by firmware */ stl_phys(SH7750_BCR1, 1<<3); /* cs3 SDRAM */ stw_phys(SH7750_BCR2, 3<<(3*2)); /* cs3 32bit */ if (kernel_cmdline) { kernel_size = load_image_targphys(kernel_filename, SDRAM_BASE + LINUX_LOAD_OFFSET, SDRAM_SIZE - LINUX_LOAD_OFFSET); env->pc = (SDRAM_BASE + LINUX_LOAD_OFFSET) | 0xa0000000; pstrcpy_targphys("cmdline", SDRAM_BASE + 0x10100, 256, kernel_cmdline); } else { kernel_size = load_image_targphys(kernel_filename, SDRAM_BASE, SDRAM_SIZE); env->pc = SDRAM_BASE | 0xa0000000; /* Start from P2 area */ } if (kernel_size < 0) { fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename); exit(1); } } }
static void r2d_init(ram_addr_t ram_size, const char *boot_device, const char *kernel_filename, const char *kernel_cmdline, const char *initrd_filename, const char *cpu_model) { CPUState *env; struct SH7750State *s; ram_addr_t sdram_addr; qemu_irq *irq; DriveInfo *dinfo; int i; if (!cpu_model) cpu_model = "SH7751R"; env = cpu_init(cpu_model); if (!env) { fprintf(stderr, "Unable to find CPU definition\n"); exit(1); } /* Allocate memory space */ sdram_addr = qemu_ram_alloc(NULL, "r2d.sdram", SDRAM_SIZE); cpu_register_physical_memory(SDRAM_BASE, SDRAM_SIZE, sdram_addr); /* Register peripherals */ s = sh7750_init(env); irq = r2d_fpga_init(0x04000000, sh7750_irl(s)); sh_pci_register_bus(r2d_pci_set_irq, r2d_pci_map_irq, irq, 0, 4); sm501_init(0x10000000, SM501_VRAM_SIZE, irq[SM501], serial_hds[2]); /* onboard CF (True IDE mode, Master only). */ dinfo = drive_get(IF_IDE, 0, 0); mmio_ide_init(0x14001000, 0x1400080c, irq[CF_IDE], 1, dinfo, NULL); /* onboard flash memory */ dinfo = drive_get(IF_PFLASH, 0, 0); pflash_cfi02_register(0x0, qemu_ram_alloc(NULL, "r2d.flash", FLASH_SIZE), dinfo ? dinfo->bdrv : NULL, (16 * 1024), FLASH_SIZE >> 16, 1, 4, 0x0000, 0x0000, 0x0000, 0x0000, 0x555, 0x2aa, 0); /* NIC: rtl8139 on-board, and 2 slots. */ for (i = 0; i < nb_nics; i++) pci_nic_init_nofail(&nd_table[i], "rtl8139", i==0 ? "2" : NULL); /* USB keyboard */ usbdevice_create("keyboard"); /* Todo: register on board registers */ memset(&boot_params, 0, sizeof(boot_params)); if (kernel_filename) { int kernel_size; kernel_size = load_image_targphys(kernel_filename, SDRAM_BASE + LINUX_LOAD_OFFSET, INITRD_LOAD_OFFSET - LINUX_LOAD_OFFSET); if (kernel_size < 0) { fprintf(stderr, "qemu: could not load kernel '%s'\n", kernel_filename); exit(1); } /* initialization which should be done by firmware */ stl_phys(SH7750_BCR1, 1<<3); /* cs3 SDRAM */ stw_phys(SH7750_BCR2, 3<<(3*2)); /* cs3 32bit */ env->pc = (SDRAM_BASE + LINUX_LOAD_OFFSET) | 0xa0000000; /* Start from P2 area */ } if (initrd_filename) { int initrd_size; initrd_size = load_image_targphys(initrd_filename, SDRAM_BASE + INITRD_LOAD_OFFSET, SDRAM_SIZE - INITRD_LOAD_OFFSET); if (initrd_size < 0) { fprintf(stderr, "qemu: could not load initrd '%s'\n", initrd_filename); exit(1); } /* initialization which should be done by firmware */ boot_params.loader_type = 1; boot_params.initrd_start = INITRD_LOAD_OFFSET; boot_params.initrd_size = initrd_size; } if (kernel_cmdline) { strncpy(boot_params.kernel_cmdline, kernel_cmdline, sizeof(boot_params.kernel_cmdline)); } rom_add_blob_fixed("boot_params", &boot_params, sizeof(boot_params), SDRAM_BASE + BOOT_PARAMS_OFFSET); }
static int virtio_ccw_cb(SubchDev *sch, CCW1 ccw) { int ret; VqInfoBlock info; uint8_t status; VirtioFeatDesc features; void *config; hwaddr indicators; VqConfigBlock vq_config; VirtioCcwDevice *dev = sch->driver_data; bool check_len; int len; hwaddr hw_len; if (!dev) { return -EINVAL; } trace_virtio_ccw_interpret_ccw(sch->cssid, sch->ssid, sch->schid, ccw.cmd_code); check_len = !((ccw.flags & CCW_FLAG_SLI) && !(ccw.flags & CCW_FLAG_DC)); /* Look at the command. */ switch (ccw.cmd_code) { case CCW_CMD_SET_VQ: if (check_len) { if (ccw.count != sizeof(info)) { ret = -EINVAL; break; } } else if (ccw.count < sizeof(info)) { /* Can't execute command. */ ret = -EINVAL; break; } if (!ccw.cda) { ret = -EFAULT; } else { info.queue = ldq_phys(ccw.cda); info.align = ldl_phys(ccw.cda + sizeof(info.queue)); info.index = lduw_phys(ccw.cda + sizeof(info.queue) + sizeof(info.align)); info.num = lduw_phys(ccw.cda + sizeof(info.queue) + sizeof(info.align) + sizeof(info.index)); ret = virtio_ccw_set_vqs(sch, info.queue, info.align, info.index, info.num); sch->curr_status.scsw.count = 0; } break; case CCW_CMD_VDEV_RESET: virtio_reset(dev->vdev); ret = 0; break; case CCW_CMD_READ_FEAT: if (check_len) { if (ccw.count != sizeof(features)) { ret = -EINVAL; break; } } else if (ccw.count < sizeof(features)) { /* Can't execute command. */ ret = -EINVAL; break; } if (!ccw.cda) { ret = -EFAULT; } else { features.index = ldub_phys(ccw.cda + sizeof(features.features)); if (features.index < ARRAY_SIZE(dev->host_features)) { features.features = dev->host_features[features.index]; } else { /* Return zeroes if the guest supports more feature bits. */ features.features = 0; } stl_le_phys(ccw.cda, features.features); sch->curr_status.scsw.count = ccw.count - sizeof(features); ret = 0; } break; case CCW_CMD_WRITE_FEAT: if (check_len) { if (ccw.count != sizeof(features)) { ret = -EINVAL; break; } } else if (ccw.count < sizeof(features)) { /* Can't execute command. */ ret = -EINVAL; break; } if (!ccw.cda) { ret = -EFAULT; } else { features.index = ldub_phys(ccw.cda + sizeof(features.features)); features.features = ldl_le_phys(ccw.cda); if (features.index < ARRAY_SIZE(dev->host_features)) { if (dev->vdev->set_features) { dev->vdev->set_features(dev->vdev, features.features); } dev->vdev->guest_features = features.features; } else { /* * If the guest supports more feature bits, assert that it * passes us zeroes for those we don't support. */ if (features.features) { fprintf(stderr, "Guest bug: features[%i]=%x (expected 0)\n", features.index, features.features); /* XXX: do a unit check here? */ } } sch->curr_status.scsw.count = ccw.count - sizeof(features); ret = 0; } break; case CCW_CMD_READ_CONF: if (check_len) { if (ccw.count > dev->vdev->config_len) { ret = -EINVAL; break; } } len = MIN(ccw.count, dev->vdev->config_len); if (!ccw.cda) { ret = -EFAULT; } else { dev->vdev->get_config(dev->vdev, dev->vdev->config); /* XXX config space endianness */ cpu_physical_memory_write(ccw.cda, dev->vdev->config, len); sch->curr_status.scsw.count = ccw.count - len; ret = 0; } break; case CCW_CMD_WRITE_CONF: if (check_len) { if (ccw.count > dev->vdev->config_len) { ret = -EINVAL; break; } } len = MIN(ccw.count, dev->vdev->config_len); hw_len = len; if (!ccw.cda) { ret = -EFAULT; } else { config = cpu_physical_memory_map(ccw.cda, &hw_len, 0); if (!config) { ret = -EFAULT; } else { len = hw_len; /* XXX config space endianness */ memcpy(dev->vdev->config, config, len); cpu_physical_memory_unmap(config, hw_len, 0, hw_len); if (dev->vdev->set_config) { dev->vdev->set_config(dev->vdev, dev->vdev->config); } sch->curr_status.scsw.count = ccw.count - len; ret = 0; } } break; case CCW_CMD_WRITE_STATUS: if (check_len) { if (ccw.count != sizeof(status)) { ret = -EINVAL; break; } } else if (ccw.count < sizeof(status)) { /* Can't execute command. */ ret = -EINVAL; break; } if (!ccw.cda) { ret = -EFAULT; } else { status = ldub_phys(ccw.cda); virtio_set_status(dev->vdev, status); if (dev->vdev->status == 0) { virtio_reset(dev->vdev); } sch->curr_status.scsw.count = ccw.count - sizeof(status); ret = 0; } break; case CCW_CMD_SET_IND: if (check_len) { if (ccw.count != sizeof(indicators)) { ret = -EINVAL; break; } } else if (ccw.count < sizeof(indicators)) { /* Can't execute command. */ ret = -EINVAL; break; } indicators = ldq_phys(ccw.cda); if (!indicators) { ret = -EFAULT; } else { dev->indicators = indicators; sch->curr_status.scsw.count = ccw.count - sizeof(indicators); ret = 0; } break; case CCW_CMD_SET_CONF_IND: if (check_len) { if (ccw.count != sizeof(indicators)) { ret = -EINVAL; break; } } else if (ccw.count < sizeof(indicators)) { /* Can't execute command. */ ret = -EINVAL; break; } indicators = ldq_phys(ccw.cda); if (!indicators) { ret = -EFAULT; } else { dev->indicators2 = indicators; sch->curr_status.scsw.count = ccw.count - sizeof(indicators); ret = 0; } break; case CCW_CMD_READ_VQ_CONF: if (check_len) { if (ccw.count != sizeof(vq_config)) { ret = -EINVAL; break; } } else if (ccw.count < sizeof(vq_config)) { /* Can't execute command. */ ret = -EINVAL; break; } if (!ccw.cda) { ret = -EFAULT; } else { vq_config.index = lduw_phys(ccw.cda); vq_config.num_max = virtio_queue_get_num(dev->vdev, vq_config.index); stw_phys(ccw.cda + sizeof(vq_config.index), vq_config.num_max); sch->curr_status.scsw.count = ccw.count - sizeof(vq_config); ret = 0; } break; default: ret = -ENOSYS; break; } return ret; }
static inline void vring_used_idx_increment(VirtQueue *vq, uint16_t val) { target_phys_addr_t pa; pa = vq->vring.used + offsetof(VRingUsed, idx); stw_phys(pa, vring_used_idx(vq) + val); }