diff options
Diffstat (limited to 'hw/mips/loongson3_virt.c')
-rw-r--r-- | hw/mips/loongson3_virt.c | 89 |
1 files changed, 49 insertions, 40 deletions
diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c index 4ad36f0..de6fbcc 100644 --- a/hw/mips/loongson3_virt.c +++ b/hw/mips/loongson3_virt.c @@ -29,7 +29,7 @@ #include "qemu/datadir.h" #include "qapi/error.h" #include "elf.h" -#include "hw/char/serial.h" +#include "hw/char/serial-mm.h" #include "hw/intc/loongson_liointc.h" #include "hw/mips/mips.h" #include "hw/mips/fw_cfg.h" @@ -45,10 +45,10 @@ #include "hw/pci-host/gpex.h" #include "hw/usb.h" #include "net/net.h" -#include "sysemu/kvm.h" -#include "sysemu/qtest.h" -#include "sysemu/reset.h" -#include "sysemu/runstate.h" +#include "system/kvm.h" +#include "system/qtest.h" +#include "system/reset.h" +#include "system/runstate.h" #include "qemu/error-report.h" #define PM_CNTL_MODE 0x10 @@ -97,6 +97,7 @@ struct LoongsonMachineState { MemoryRegion *pio_alias; MemoryRegion *mmio_alias; MemoryRegion *ecam_alias; + MemoryRegion *core_iocsr[LOONGSON_MAX_VCPUS]; }; typedef struct LoongsonMachineState LoongsonMachineState; @@ -143,7 +144,7 @@ static void loongson3_pm_write(void *opaque, hwaddr addr, static const MemoryRegionOps loongson3_pm_ops = { .read = loongson3_pm_read, .write = loongson3_pm_write, - .endianness = DEVICE_NATIVE_ENDIAN, + .endianness = DEVICE_LITTLE_ENDIAN, .valid = { .min_access_size = 1, .max_access_size = 1 @@ -152,7 +153,7 @@ static const MemoryRegionOps loongson3_pm_ops = { #define DEF_LOONGSON3_FREQ (800 * 1000 * 1000) -static uint64_t get_cpu_freq_hz(void) +static uint64_t get_cpu_freq_hz(const MIPSCPU *cpu) { #ifdef CONFIG_KVM int ret; @@ -163,7 +164,7 @@ static uint64_t get_cpu_freq_hz(void) }; if (kvm_enabled()) { - ret = kvm_vcpu_ioctl(first_cpu, KVM_GET_ONE_REG, &freq_reg); + ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_ONE_REG, &freq_reg); if (ret >= 0) { return freq * 2; } @@ -172,7 +173,7 @@ static uint64_t get_cpu_freq_hz(void) return DEF_LOONGSON3_FREQ; } -static void init_boot_param(void) +static void init_boot_param(unsigned cpu_count, uint32_t processor_id) { static void *p; struct boot_params *bp; @@ -183,7 +184,7 @@ static void init_boot_param(void) bp->efi.smbios.vers = cpu_to_le16(1); init_reset_system(&(bp->reset_system)); p += ROUND_UP(sizeof(struct boot_params), 64); - init_loongson_params(&(bp->efi.smbios.lp), p, + init_loongson_params(&(bp->efi.smbios.lp), p, cpu_count, processor_id, loaderparams.cpu_freq, loaderparams.ram_size); rom_add_blob_fixed("params_rom", bp, @@ -279,7 +280,7 @@ static void fw_cfg_boot_set(void *opaque, const char *boot_device, fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]); } -static void fw_conf_init(unsigned long ram_size) +static void fw_conf_init(void) { static const uint8_t suspend[6] = {128, 0, 0, 129, 128, 128}; FWCfgState *fw_cfg; @@ -288,9 +289,9 @@ static void fw_conf_init(unsigned long ram_size) fw_cfg = fw_cfg_init_mem_wide(cfg_addr, cfg_addr + 8, 8, 0, NULL); fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)current_machine->smp.cpus); fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)current_machine->smp.max_cpus); - fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); + fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, loaderparams.ram_size); fw_cfg_add_i32(fw_cfg, FW_CFG_MACHINE_VERSION, 1); - fw_cfg_add_i64(fw_cfg, FW_CFG_CPU_FREQ, get_cpu_freq_hz()); + fw_cfg_add_i64(fw_cfg, FW_CFG_CPU_FREQ, loaderparams.cpu_freq); fw_cfg_add_file(fw_cfg, "etc/system-states", g_memdup2(suspend, sizeof(suspend)), sizeof(suspend)); @@ -355,9 +356,9 @@ static uint64_t load_kernel(CPUMIPSState *env) kernel_size = load_elf(loaderparams.kernel_filename, NULL, cpu_mips_kseg0_to_phys, NULL, - (uint64_t *)&kernel_entry, - (uint64_t *)&kernel_low, (uint64_t *)&kernel_high, - NULL, 0, EM_MIPS, 1, 0); + &kernel_entry, + &kernel_low, &kernel_high, + NULL, ELFDATA2LSB, EM_MIPS, 1, 0); if (kernel_size < 0) { error_report("could not load kernel '%s': %s", loaderparams.kernel_filename, @@ -398,25 +399,33 @@ static uint64_t load_kernel(CPUMIPSState *env) return kernel_entry; } -static void main_cpu_reset(void *opaque) +static void generic_cpu_reset(void *opaque) { MIPSCPU *cpu = opaque; CPUMIPSState *env = &cpu->env; cpu_reset(CPU(cpu)); - /* Loongson-3 reset stuff */ if (loaderparams.kernel_filename) { - if (cpu == MIPS_CPU(first_cpu)) { - env->active_tc.gpr[4] = loaderparams.a0; - env->active_tc.gpr[5] = loaderparams.a1; - env->active_tc.gpr[6] = loaderparams.a2; - env->active_tc.PC = loaderparams.kernel_entry; - } env->CP0_Status &= ~((1 << CP0St_BEV) | (1 << CP0St_ERL)); } } +static void main_cpu_reset(void *opaque) +{ + generic_cpu_reset(opaque); + + if (loaderparams.kernel_filename) { + MIPSCPU *cpu = opaque; + CPUMIPSState *env = &cpu->env; + + env->active_tc.gpr[4] = loaderparams.a0; + env->active_tc.gpr[5] = loaderparams.a1; + env->active_tc.gpr[6] = loaderparams.a2; + env->active_tc.PC = loaderparams.kernel_entry; + } +} + static inline void loongson3_virt_devices_init(MachineState *machine, DeviceState *pic) { @@ -457,7 +466,7 @@ static inline void loongson3_virt_devices_init(MachineState *machine, virt_memmap[VIRT_PCIE_PIO].base, s->pio_alias); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, virt_memmap[VIRT_PCIE_PIO].base); - for (i = 0; i < GPEX_NUM_IRQS; i++) { + for (i = 0; i < PCI_NUM_PINS; i++) { irq = qdev_get_gpio_in(pic, PCIE_IRQ_BASE + i); sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, irq); gpex_set_irq_num(GPEX_HOST(dev), i, PCIE_IRQ_BASE + i); @@ -483,9 +492,8 @@ static void mips_loongson3_virt_init(MachineState *machine) { int i; long bios_size; - MIPSCPU *cpu; + MIPSCPU *cpu = NULL; Clock *cpuclk; - CPUMIPSState *env; DeviceState *liointc; DeviceState *ipi = NULL; char *filename; @@ -493,6 +501,7 @@ static void mips_loongson3_virt_init(MachineState *machine) const char *kernel_filename = machine->kernel_filename; const char *initrd_filename = machine->initrd_filename; ram_addr_t ram_size = machine->ram_size; + LoongsonMachineState *s = LOONGSON_MACHINE(machine); MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *bios = g_new(MemoryRegion, 1); @@ -551,7 +560,7 @@ static void mips_loongson3_virt_init(MachineState *machine) serial_mm_init(address_space_mem, virt_memmap[VIRT_UART].base, 0, qdev_get_gpio_in(liointc, UART_IRQ), 115200, serial_hd(0), - DEVICE_NATIVE_ENDIAN); + DEVICE_LITTLE_ENDIAN); sysbus_create_simple("goldfish_rtc", virt_memmap[VIRT_RTC].base, qdev_get_gpio_in(liointc, RTC_IRQ)); @@ -559,20 +568,20 @@ static void mips_loongson3_virt_init(MachineState *machine) cpuclk = clock_new(OBJECT(machine), "cpu-refclk"); clock_set_hz(cpuclk, DEF_LOONGSON3_FREQ); - for (i = 0; i < machine->smp.cpus; i++) { + for (i = machine->smp.cpus - 1; i >= 0; --i) { int node = i / LOONGSON3_CORE_PER_NODE; int core = i % LOONGSON3_CORE_PER_NODE; int ip; /* init CPUs */ - cpu = mips_cpu_create_with_clock(machine->cpu_type, cpuclk); + cpu = mips_cpu_create_with_clock(machine->cpu_type, cpuclk, false); /* Init internal devices */ cpu_mips_irq_init_cpu(cpu); cpu_mips_clock_init(cpu); - qemu_register_reset(main_cpu_reset, cpu); + qemu_register_reset(i ? generic_cpu_reset : main_cpu_reset, cpu); - if (ipi) { + if (!kvm_enabled()) { hwaddr base = ((hwaddr)node << 44) + virt_memmap[VIRT_IPI].base; base += core * 0x100; qdev_connect_gpio_out(ipi, i, cpu->env.irq[6]); @@ -586,6 +595,7 @@ static void mips_loongson3_virt_init(MachineState *machine) iocsr, 0, UINT32_MAX); memory_region_add_subregion(&MIPS_CPU(cpu)->env.iocsr.mr, 0, core_iocsr); + s->core_iocsr[i] = core_iocsr; } if (node > 0) { @@ -598,7 +608,7 @@ static void mips_loongson3_virt_init(MachineState *machine) pin, cpu->env.irq[ip + 2]); } } - env = &MIPS_CPU(first_cpu)->env; + assert(cpu); /* This variable points to the first created cpu. */ /* Allocate RAM/BIOS, 0x00000000~0x10000000 is alias of 0x80000000~0x90000000 */ memory_region_init_rom(bios, NULL, "loongson3.bios", @@ -623,16 +633,16 @@ static void mips_loongson3_virt_init(MachineState *machine) * Please use -L to set the BIOS path and -bios to set bios name. */ + loaderparams.cpu_freq = get_cpu_freq_hz(cpu); + loaderparams.ram_size = ram_size; if (kernel_filename) { - loaderparams.cpu_freq = get_cpu_freq_hz(); - loaderparams.ram_size = ram_size; loaderparams.kernel_filename = kernel_filename; loaderparams.kernel_cmdline = kernel_cmdline; loaderparams.initrd_filename = initrd_filename; - loaderparams.kernel_entry = load_kernel(env); + loaderparams.kernel_entry = load_kernel(&cpu->env); init_boot_rom(); - init_boot_param(); + init_boot_param(machine->smp.cpus, cpu->env.CP0_PRid); } else { filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, machine->firmware ?: LOONGSON3_BIOSNAME); @@ -651,13 +661,13 @@ static void mips_loongson3_virt_init(MachineState *machine) exit(1); } - fw_conf_init(ram_size); + fw_conf_init(); } loongson3_virt_devices_init(machine, liointc); } -static void loongson3v_machine_class_init(ObjectClass *oc, void *data) +static void loongson3v_machine_class_init(ObjectClass *oc, const void *data) { MachineClass *mc = MACHINE_CLASS(oc); @@ -667,7 +677,6 @@ static void loongson3v_machine_class_init(ObjectClass *oc, void *data) mc->max_cpus = LOONGSON_MAX_VCPUS; mc->default_ram_id = "loongson3.highram"; mc->default_ram_size = 1600 * MiB; - mc->minimum_page_bits = 14; mc->default_nic = "virtio-net-pci"; } |