/* CPUClass::reset() */ static void mips_cpu_reset(CPUState *s) { MIPSCPU *cpu = MIPS_CPU(s); MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(cpu); CPUMIPSState *env = &cpu->env; mcc->parent_reset(s); memset(env, 0, offsetof(CPUMIPSState, end_reset_fields)); cpu_state_reset(env); #ifndef CONFIG_USER_ONLY if (kvm_enabled()) { kvm_mips_reset_vcpu(cpu); } #endif }
/* CPUClass::reset() */ static void mips_cpu_reset(CPUState *s) { MIPSCPU *cpu = MIPS_CPU(s); MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(cpu); CPUMIPSState *env = &cpu->env; if (qemu_loglevel_mask(CPU_LOG_RESET)) { qemu_log("CPU Reset (CPU %d)\n", s->cpu_index); log_cpu_state(env, 0); } mcc->parent_reset(s); memset(env, 0, offsetof(CPUMIPSState, breakpoints)); tlb_flush(env, 1); cpu_state_reset(env); }
static void mips_cpu_realizefn(DeviceState *dev, Error **errp) { CPUState *cs = CPU(dev); MIPSCPU *cpu = MIPS_CPU(dev); MIPSCPUClass *mcc = MIPS_CPU_GET_CLASS(dev); Error *local_err = NULL; cpu_exec_realizefn(cs, &local_err); if (local_err != NULL) { error_propagate(errp, local_err); return; } cpu_mips_realize_env(&cpu->env); cpu_reset(cs); qemu_init_vcpu(cs); mcc->parent_realize(dev, errp); }
static bool mips_cpu_has_work(CPUState *cs) { MIPSCPU *cpu = MIPS_CPU(cs); CPUMIPSState *env = &cpu->env; bool has_work = false; /* Prior to MIPS Release 6 it is implementation dependent if non-enabled interrupts wake-up the CPU, however most of the implementations only check for interrupts that can be taken. */ if ((cs->interrupt_request & CPU_INTERRUPT_HARD) && cpu_mips_hw_interrupts_pending(env)) { if (cpu_mips_hw_interrupts_enabled(env) || (env->insn_flags & ISA_MIPS32R6)) { has_work = true; } } /* MIPS-MT has the ability to halt the CPU. */ if (env->CP0_Config3 & (1 << CP0C3_MT)) { /* The QEMU model will issue an _WAKE request whenever the CPUs should be woken up. */ if (cs->interrupt_request & CPU_INTERRUPT_WAKE) { has_work = true; } if (!mips_vpe_active(env)) { has_work = false; } } /* MIPS Release 6 has the ability to halt the CPU. */ if (env->CP0_Config5 & (1 << CP0C5_VP)) { if (cs->interrupt_request & CPU_INTERRUPT_WAKE) { has_work = true; } if (!mips_vp_active(env)) { has_work = false; } } return has_work; }
static void mips_cps_realize(DeviceState *dev, Error **errp) { MIPSCPSState *s = MIPS_CPS(dev); CPUMIPSState *env; MIPSCPU *cpu; int i; Error *err = NULL; target_ulong gcr_base; bool itu_present = false; bool saar_present = false; for (i = 0; i < s->num_vp; i++) { cpu = MIPS_CPU(cpu_create(s->cpu_type)); /* Init internal devices */ cpu_mips_irq_init_cpu(cpu); cpu_mips_clock_init(cpu); env = &cpu->env; if (cpu_mips_itu_supported(env)) { itu_present = true; /* Attach ITC Tag to the VP */ env->itc_tag = mips_itu_get_tag_region(&s->itu); env->itu = &s->itu; } qemu_register_reset(main_cpu_reset, cpu); } cpu = MIPS_CPU(first_cpu); env = &cpu->env; saar_present = (bool)env->saarp; /* Inter-Thread Communication Unit */ if (itu_present) { object_initialize(&s->itu, sizeof(s->itu), TYPE_MIPS_ITU); qdev_set_parent_bus(DEVICE(&s->itu), sysbus_get_default()); object_property_set_int(OBJECT(&s->itu), 16, "num-fifo", &err); object_property_set_int(OBJECT(&s->itu), 16, "num-semaphores", &err); object_property_set_bool(OBJECT(&s->itu), saar_present, "saar-present", &err); if (saar_present) { qdev_prop_set_ptr(DEVICE(&s->itu), "saar", (void *)&env->CP0_SAAR); } object_property_set_bool(OBJECT(&s->itu), true, "realized", &err); if (err != NULL) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->container, 0, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->itu), 0)); } /* Cluster Power Controller */ object_initialize(&s->cpc, sizeof(s->cpc), TYPE_MIPS_CPC); qdev_set_parent_bus(DEVICE(&s->cpc), sysbus_get_default()); object_property_set_int(OBJECT(&s->cpc), s->num_vp, "num-vp", &err); object_property_set_int(OBJECT(&s->cpc), 1, "vp-start-running", &err); object_property_set_bool(OBJECT(&s->cpc), true, "realized", &err); if (err != NULL) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->container, 0, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->cpc), 0)); /* Global Interrupt Controller */ object_initialize(&s->gic, sizeof(s->gic), TYPE_MIPS_GIC); qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default()); object_property_set_int(OBJECT(&s->gic), s->num_vp, "num-vp", &err); object_property_set_int(OBJECT(&s->gic), 128, "num-irq", &err); object_property_set_bool(OBJECT(&s->gic), true, "realized", &err); if (err != NULL) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->container, 0, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gic), 0)); /* Global Configuration Registers */ gcr_base = env->CP0_CMGCRBase << 4; object_initialize(&s->gcr, sizeof(s->gcr), TYPE_MIPS_GCR); qdev_set_parent_bus(DEVICE(&s->gcr), sysbus_get_default()); object_property_set_int(OBJECT(&s->gcr), s->num_vp, "num-vp", &err); object_property_set_int(OBJECT(&s->gcr), 0x800, "gcr-rev", &err); object_property_set_int(OBJECT(&s->gcr), gcr_base, "gcr-base", &err); object_property_set_link(OBJECT(&s->gcr), OBJECT(&s->gic.mr), "gic", &err); object_property_set_link(OBJECT(&s->gcr), OBJECT(&s->cpc.mr), "cpc", &err); object_property_set_bool(OBJECT(&s->gcr), true, "realized", &err); if (err != NULL) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->container, gcr_base, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gcr), 0)); }
static void mips_jazz_init(MachineState *machine, enum jazz_model_e jazz_model) { MemoryRegion *address_space = get_system_memory(); char *filename; int bios_size, n; MIPSCPU *cpu; CPUClass *cc; CPUMIPSState *env; qemu_irq *i8259; rc4030_dma *dmas; IOMMUMemoryRegion *rc4030_dma_mr; MemoryRegion *isa_mem = g_new(MemoryRegion, 1); MemoryRegion *isa_io = g_new(MemoryRegion, 1); MemoryRegion *rtc = g_new(MemoryRegion, 1); MemoryRegion *i8042 = g_new(MemoryRegion, 1); MemoryRegion *dma_dummy = g_new(MemoryRegion, 1); NICInfo *nd; DeviceState *dev, *rc4030; SysBusDevice *sysbus; ISABus *isa_bus; ISADevice *pit; DriveInfo *fds[MAX_FD]; qemu_irq esp_reset, dma_enable; MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *bios = g_new(MemoryRegion, 1); MemoryRegion *bios2 = g_new(MemoryRegion, 1); /* init CPUs */ cpu = MIPS_CPU(cpu_create(machine->cpu_type)); env = &cpu->env; qemu_register_reset(main_cpu_reset, cpu); /* Chipset returns 0 in invalid reads and do not raise data exceptions. * However, we can't simply add a global memory region to catch * everything, as memory core directly call unassigned_mem_read/write * on some invalid accesses, which call do_unassigned_access on the * CPU, which raise an exception. * Handle that case by hijacking the do_unassigned_access method on * the CPU, and do not raise exceptions for data access. */ cc = CPU_GET_CLASS(cpu); real_do_unassigned_access = cc->do_unassigned_access; cc->do_unassigned_access = mips_jazz_do_unassigned_access; /* allocate RAM */ memory_region_allocate_system_memory(ram, NULL, "mips_jazz.ram", machine->ram_size); memory_region_add_subregion(address_space, 0, ram); memory_region_init_ram(bios, NULL, "mips_jazz.bios", MAGNUM_BIOS_SIZE, &error_fatal); memory_region_set_readonly(bios, true); memory_region_init_alias(bios2, NULL, "mips_jazz.bios", bios, 0, MAGNUM_BIOS_SIZE); memory_region_add_subregion(address_space, 0x1fc00000LL, bios); memory_region_add_subregion(address_space, 0xfff00000LL, bios2); /* load the BIOS image. */ if (bios_name == NULL) bios_name = BIOS_FILENAME; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (filename) { bios_size = load_image_targphys(filename, 0xfff00000LL, MAGNUM_BIOS_SIZE); g_free(filename); } else { bios_size = -1; } if ((bios_size < 0 || bios_size > MAGNUM_BIOS_SIZE) && !qtest_enabled()) { error_report("Could not load MIPS bios '%s'", bios_name); exit(1); } /* Init CPU internal devices */ cpu_mips_irq_init_cpu(cpu); cpu_mips_clock_init(cpu); /* Chipset */ rc4030 = rc4030_init(&dmas, &rc4030_dma_mr); sysbus = SYS_BUS_DEVICE(rc4030); sysbus_connect_irq(sysbus, 0, env->irq[6]); sysbus_connect_irq(sysbus, 1, env->irq[3]); memory_region_add_subregion(address_space, 0x80000000, sysbus_mmio_get_region(sysbus, 0)); memory_region_add_subregion(address_space, 0xf0000000, sysbus_mmio_get_region(sysbus, 1)); memory_region_init_io(dma_dummy, NULL, &dma_dummy_ops, NULL, "dummy_dma", 0x1000); memory_region_add_subregion(address_space, 0x8000d000, dma_dummy); /* ISA bus: IO space at 0x90000000, mem space at 0x91000000 */ memory_region_init(isa_io, NULL, "isa-io", 0x00010000); memory_region_init(isa_mem, NULL, "isa-mem", 0x01000000); memory_region_add_subregion(address_space, 0x90000000, isa_io); memory_region_add_subregion(address_space, 0x91000000, isa_mem); isa_bus = isa_bus_new(NULL, isa_mem, isa_io, &error_abort); /* ISA devices */ i8259 = i8259_init(isa_bus, env->irq[4]); isa_bus_irqs(isa_bus, i8259); DMA_init(isa_bus, 0); pit = pit_init(isa_bus, 0x40, 0, NULL); pcspk_init(isa_bus, pit); /* Video card */ switch (jazz_model) { case JAZZ_MAGNUM: dev = qdev_create(NULL, "sysbus-g364"); qdev_init_nofail(dev); sysbus = SYS_BUS_DEVICE(dev); sysbus_mmio_map(sysbus, 0, 0x60080000); sysbus_mmio_map(sysbus, 1, 0x40000000); sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in(rc4030, 3)); { /* Simple ROM, so user doesn't have to provide one */ MemoryRegion *rom_mr = g_new(MemoryRegion, 1); memory_region_init_ram(rom_mr, NULL, "g364fb.rom", 0x80000, &error_fatal); memory_region_set_readonly(rom_mr, true); uint8_t *rom = memory_region_get_ram_ptr(rom_mr); memory_region_add_subregion(address_space, 0x60000000, rom_mr); rom[0] = 0x10; /* Mips G364 */ } break; case JAZZ_PICA61: isa_vga_mm_init(0x40000000, 0x60000000, 0, get_system_memory()); break; default: break; } /* Network controller */ for (n = 0; n < nb_nics; n++) { nd = &nd_table[n]; if (!nd->model) nd->model = g_strdup("dp83932"); if (strcmp(nd->model, "dp83932") == 0) { qemu_check_nic_model(nd, "dp83932"); dev = qdev_create(NULL, "dp8393x"); qdev_set_nic_properties(dev, nd); qdev_prop_set_uint8(dev, "it_shift", 2); qdev_prop_set_ptr(dev, "dma_mr", rc4030_dma_mr); qdev_init_nofail(dev); sysbus = SYS_BUS_DEVICE(dev); sysbus_mmio_map(sysbus, 0, 0x80001000); sysbus_mmio_map(sysbus, 1, 0x8000b000); sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in(rc4030, 4)); break; } else if (is_help_option(nd->model)) { fprintf(stderr, "qemu: Supported NICs: dp83932\n"); exit(1); } else { fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model); exit(1); } } /* SCSI adapter */ esp_init(0x80002000, 0, rc4030_dma_read, rc4030_dma_write, dmas[0], qdev_get_gpio_in(rc4030, 5), &esp_reset, &dma_enable); /* Floppy */ for (n = 0; n < MAX_FD; n++) { fds[n] = drive_get(IF_FLOPPY, 0, n); } /* FIXME: we should enable DMA with a custom IsaDma device */ fdctrl_init_sysbus(qdev_get_gpio_in(rc4030, 1), -1, 0x80003000, fds); /* Real time clock */ rtc_init(isa_bus, 1980, NULL); memory_region_init_io(rtc, NULL, &rtc_ops, NULL, "rtc", 0x1000); memory_region_add_subregion(address_space, 0x80004000, rtc); /* Keyboard (i8042) */ i8042_mm_init(qdev_get_gpio_in(rc4030, 6), qdev_get_gpio_in(rc4030, 7), i8042, 0x1000, 0x1); memory_region_add_subregion(address_space, 0x80005000, i8042); /* Serial ports */ if (serial_hds[0]) { serial_mm_init(address_space, 0x80006000, 0, qdev_get_gpio_in(rc4030, 8), 8000000/16, serial_hds[0], DEVICE_NATIVE_ENDIAN); } if (serial_hds[1]) { serial_mm_init(address_space, 0x80007000, 0, qdev_get_gpio_in(rc4030, 9), 8000000/16, serial_hds[1], DEVICE_NATIVE_ENDIAN); } /* Parallel port */ if (parallel_hds[0]) parallel_mm_init(address_space, 0x80008000, 0, qdev_get_gpio_in(rc4030, 0), parallel_hds[0]); /* FIXME: missing Jazz sound at 0x8000c000, rc4030[2] */ /* NVRAM */ dev = qdev_create(NULL, "ds1225y"); qdev_init_nofail(dev); sysbus = SYS_BUS_DEVICE(dev); sysbus_mmio_map(sysbus, 0, 0x80009000); /* LED indicator */ sysbus_create_simple("jazz-led", 0x8000f000, NULL); }
static void mips_r4k_init(MachineState *machine) { ram_addr_t ram_size = machine->ram_size; const char *kernel_filename = machine->kernel_filename; const char *kernel_cmdline = machine->kernel_cmdline; const char *initrd_filename = machine->initrd_filename; char *filename; MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *bios; MemoryRegion *iomem = g_new(MemoryRegion, 1); MemoryRegion *isa_io = g_new(MemoryRegion, 1); MemoryRegion *isa_mem = g_new(MemoryRegion, 1); int bios_size; MIPSCPU *cpu; CPUMIPSState *env; ResetData *reset_info; int i; qemu_irq *i8259; ISABus *isa_bus; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; DriveInfo *dinfo; int be; /* init CPUs */ cpu = MIPS_CPU(cpu_create(machine->cpu_type)); env = &cpu->env; reset_info = g_malloc0(sizeof(ResetData)); reset_info->cpu = cpu; reset_info->vector = env->active_tc.PC; qemu_register_reset(main_cpu_reset, reset_info); /* allocate RAM */ if (ram_size > (256 << 20)) { error_report("Too much memory for this machine: %dMB, maximum 256MB", ((unsigned int)ram_size / (1 << 20))); exit(1); } memory_region_allocate_system_memory(ram, NULL, "mips_r4k.ram", ram_size); memory_region_add_subregion(address_space_mem, 0, ram); memory_region_init_io(iomem, NULL, &mips_qemu_ops, NULL, "mips-qemu", 0x10000); memory_region_add_subregion(address_space_mem, 0x1fbf0000, iomem); /* Try to load a BIOS image. If this fails, we continue regardless, but initialize the hardware ourselves. When a kernel gets preloaded we also initialize the hardware, since the BIOS wasn't run. */ if (bios_name == NULL) bios_name = BIOS_FILENAME; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (filename) { bios_size = get_image_size(filename); } else { bios_size = -1; } #ifdef TARGET_WORDS_BIGENDIAN be = 1; #else be = 0; #endif if ((bios_size > 0) && (bios_size <= BIOS_SIZE)) { bios = g_new(MemoryRegion, 1); memory_region_init_ram(bios, NULL, "mips_r4k.bios", BIOS_SIZE, &error_fatal); memory_region_set_readonly(bios, true); memory_region_add_subregion(get_system_memory(), 0x1fc00000, bios); load_image_targphys(filename, 0x1fc00000, BIOS_SIZE); } else if ((dinfo = drive_get(IF_PFLASH, 0, 0)) != NULL) { uint32_t mips_rom = 0x00400000; if (!pflash_cfi01_register(0x1fc00000, NULL, "mips_r4k.bios", mips_rom, blk_by_legacy_dinfo(dinfo), sector_len, mips_rom / sector_len, 4, 0, 0, 0, 0, be)) { fprintf(stderr, "qemu: Error registering flash memory.\n"); } } else if (!qtest_enabled()) { /* not fatal */ warn_report("could not load MIPS bios '%s'", bios_name); } g_free(filename); if (kernel_filename) { loaderparams.ram_size = ram_size; loaderparams.kernel_filename = kernel_filename; loaderparams.kernel_cmdline = kernel_cmdline; loaderparams.initrd_filename = initrd_filename; reset_info->vector = load_kernel(); } /* Init CPU internal devices */ cpu_mips_irq_init_cpu(cpu); cpu_mips_clock_init(cpu); /* ISA bus: IO space at 0x14000000, mem space at 0x10000000 */ memory_region_init_alias(isa_io, NULL, "isa-io", get_system_io(), 0, 0x00010000); memory_region_init(isa_mem, NULL, "isa-mem", 0x01000000); memory_region_add_subregion(get_system_memory(), 0x14000000, isa_io); memory_region_add_subregion(get_system_memory(), 0x10000000, isa_mem); isa_bus = isa_bus_new(NULL, isa_mem, get_system_io(), &error_abort); /* The PIC is attached to the MIPS CPU INT0 pin */ i8259 = i8259_init(isa_bus, env->irq[2]); isa_bus_irqs(isa_bus, i8259); mc146818_rtc_init(isa_bus, 2000, NULL); pit = i8254_pit_init(isa_bus, 0x40, 0, NULL); serial_hds_isa_init(isa_bus, 0, MAX_SERIAL_PORTS); isa_vga_init(isa_bus); if (nd_table[0].used) isa_ne2000_init(isa_bus, 0x300, 9, &nd_table[0]); ide_drive_get(hd, ARRAY_SIZE(hd)); for(i = 0; i < MAX_IDE_BUS; i++) isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i], ide_irq[i], hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]); isa_create_simple(isa_bus, TYPE_I8042); }
int mips_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) { MIPSCPU *cpu = MIPS_CPU(cs); CPUMIPSState *env = &cpu->env; target_ulong tmp; tmp = ldtul_p(mem_buf); if (n < 32) { env->active_tc.gpr[n] = tmp; return sizeof(target_ulong); } if (env->CP0_Config1 & (1 << CP0C1_FP) && n >= 38 && n < 73) { if (n < 70) { if (env->CP0_Status & (1 << CP0St_FR)) { env->active_fpu.fpr[n - 38].d = tmp; } else { env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX] = tmp; } } switch (n) { case 70: env->active_fpu.fcr31 = tmp & 0xFF83FFFF; /* set rounding mode */ RESTORE_ROUNDING_MODE; break; case 71: env->active_fpu.fcr0 = tmp; break; } return sizeof(target_ulong); } switch (n) { case 32: env->CP0_Status = tmp; break; case 33: env->active_tc.LO[0] = tmp; break; case 34: env->active_tc.HI[0] = tmp; break; case 35: env->CP0_BadVAddr = tmp; break; case 36: env->CP0_Cause = tmp; break; case 37: env->active_tc.PC = tmp & ~(target_ulong)1; if (tmp & 1) { env->hflags |= MIPS_HFLAG_M16; } else { env->hflags &= ~(MIPS_HFLAG_M16); } break; case 72: /* fp, ignored */ break; default: if (n > 89) { return 0; } /* Other registers are readonly. Ignore writes. */ break; } return sizeof(target_ulong); }