aboutsummaryrefslogtreecommitdiff
path: root/hw/mips/loongson3_virt.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/mips/loongson3_virt.c')
-rw-r--r--hw/mips/loongson3_virt.c89
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";
}