Hi, Philippe, On Wed, Nov 4, 2020 at 4:23 AM Philippe Mathieu-Daudé <f4...@amsat.org> wrote: > > Hi Huacai, > > On 10/30/20 11:25 AM, Huacai Chen wrote: > > Add Loongson-3 based machine support, it use liointc as the interrupt > > controler and use GPEX as the pci controller. Currently it can work with > > both TCG and KVM. > > > > As the machine model is not based on any exiting physical hardware, the > > name of the machine is "loongson3-virt". It may be superseded in future > > by a real machine model. If this happens, then a regular deprecation > > procedure shall occur for "loongson3-virt" machine. > > > > We now already have a full functional Linux kernel (based on Linux-5.4.x > > LTS, the kvm host side and guest side have both been upstream for Linux- > > 5.9, but Linux-5.9 has not been released yet) here: > > > > https://github.com/chenhuacai/linux > > > > Of course the upstream kernel is also usable (though it is "unstable" > > now): > > > > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git > > > > How to use QEMU/Loongson-3? > > 1, Download kernel source from the above URL; > > 2, Build a kernel with arch/mips/configs/loongson3_defconfig; > > 3, Boot a Loongson-3A4000 host with this kernel (for KVM mode); > > 4, Build QEMU-master with this patchset; > > 5, modprobe kvm (only necessary for KVM mode); > > 6, Use QEMU with TCG: > > qemu-system-mips64el -M loongson3-virt,accel=tcg -cpu > > Loongson-3A1000 -kernel <path_to_kernel> -append ... > > Use QEMU with KVM: > > qemu-system-mips64el -M loongson3-virt,accel=kvm -cpu > > Loongson-3A4000 -kernel <path_to_kernel> -append ... > > > > The "-cpu" parameter is optional here and QEMU will use the correct type > > for TCG/KVM automatically. > > > > Signed-off-by: Huacai Chen <che...@lemote.com> > > Co-developed-by: Jiaxun Yang <jiaxun.y...@flygoat.com> > > Signed-off-by: Jiaxun Yang <jiaxun.y...@flygoat.com> > > --- > > default-configs/devices/mips64el-softmmu.mak | 1 + > > hw/mips/Kconfig | 12 + > > hw/mips/loongson3_virt.c | 620 > > +++++++++++++++++++++++++++ > > hw/mips/meson.build | 2 +- > > 4 files changed, 634 insertions(+), 1 deletion(-) > > create mode 100644 hw/mips/loongson3_virt.c > ... > > +static inline void loongson3_virt_devices_init(MachineState *machine, > > DeviceState *pic) > > +{ > > + int i; > > + qemu_irq irq; > > + PCIBus *pci_bus; > > + DeviceState *dev; > > + MemoryRegion *pio_alias; > > + MemoryRegion *mmio_alias, *mmio_reg; > > + MemoryRegion *ecam_alias, *ecam_reg; > > + > > + dev = qdev_new(TYPE_GPEX_HOST); > > + sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal); > > + pci_bus = PCI_HOST_BRIDGE(dev)->bus; > > + > > + ecam_alias = g_new0(MemoryRegion, 1); > > + ecam_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0); > > + memory_region_init_alias(ecam_alias, OBJECT(dev), "pcie-ecam", > > + ecam_reg, 0, > > virt_memmap[VIRT_PCIE_ECAM].size); > > + memory_region_add_subregion(get_system_memory(), > > + virt_memmap[VIRT_PCIE_ECAM].base, > > ecam_alias); > > + > > + mmio_alias = g_new0(MemoryRegion, 1); > > + mmio_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1); > > + memory_region_init_alias(mmio_alias, OBJECT(dev), "pcie-mmio", > > + mmio_reg, virt_memmap[VIRT_PCIE_MMIO].base, > > + virt_memmap[VIRT_PCIE_MMIO].size); > > + memory_region_add_subregion(get_system_memory(), > > + virt_memmap[VIRT_PCIE_MMIO].base, > > mmio_alias); > > + > > + pio_alias = g_new0(MemoryRegion, 1); > > + memory_region_init_alias(pio_alias, OBJECT(dev), "pcie-pio", > > + get_system_io(), 0, > > virt_memmap[VIRT_PCIE_PIO].size); > > + memory_region_add_subregion(get_system_memory(), > > + virt_memmap[VIRT_PCIE_PIO].base, > > pio_alias); > > + sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, > > virt_memmap[VIRT_PCIE_PIO].base); > > + > > + for (i = 0; i < GPEX_NUM_IRQS; 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); > > + } > > + > > + pci_vga_init(pci_bus); > > + > > + if (defaults_enabled()) { > > + pci_create_simple(pci_bus, -1, "pci-ohci"); > > + usb_create_simple(usb_bus_find(-1), "usb-kbd"); > > + usb_create_simple(usb_bus_find(-1), "usb-tablet"); > > + } > > + > > + for (i = 0; i < nb_nics; i++) { > > + NICInfo *nd = &nd_table[i]; > > + > > + if (!nd->model) { > > + nd->model = g_strdup("virtio"); > > + } > > + > > + pci_nic_init_nofail(nd, pci_bus, nd->model, NULL); > > + } > > +} > > + > > +static void mips_loongson3_virt_init(MachineState *machine) > > +{ > > + int i; > > + long bios_size; > > + MIPSCPU *cpu; > > + Clock *cpuclk; > > + CPUMIPSState *env; > > + DeviceState *liointc; > > + char *filename; > > + const char *kernel_cmdline = machine->kernel_cmdline; > > + const char *kernel_filename = machine->kernel_filename; > > + const char *initrd_filename = machine->initrd_filename; > > + ram_addr_t ram_size = machine->ram_size; > > + MemoryRegion *address_space_mem = get_system_memory(); > > + MemoryRegion *ram = g_new(MemoryRegion, 1); > > + MemoryRegion *bios = g_new(MemoryRegion, 1); > > + MemoryRegion *iomem = g_new(MemoryRegion, 1); > > + > > + /* TODO: TCG will support all CPU types */ > > + if (!kvm_enabled()) { > > + if (!machine->cpu_type) { > > + machine->cpu_type = MIPS_CPU_TYPE_NAME("Loongson-3A1000"); > > + } > > + if (!strstr(machine->cpu_type, "Loongson-3A1000")) { > > + error_report("Loongson-3/TCG needs cpu type Loongson-3A1000"); > > + exit(1); > > + } > > + } else { > > + if (!machine->cpu_type) { > > + machine->cpu_type = MIPS_CPU_TYPE_NAME("Loongson-3A4000"); > > + } > > + if (!strstr(machine->cpu_type, "Loongson-3A4000")) { > > + error_report("Loongson-3/KVM needs cpu type Loongson-3A4000"); > > + exit(1); > > + } > > + } > > + > > + if (ram_size < 512 * MiB) { > > + error_report("Loongson-3 machine needs at least 512MB memory"); > > + exit(1); > > + } > > + > > + /* > > + * The whole MMIO range among configure registers doesn't generate > > + * exception when accessing invalid memory. Create some unimplememted > > + * devices to emulate this feature. > > + */ > > + create_unimplemented_device("mmio fallback 0", 0x10000000, 256 * MiB); > > + create_unimplemented_device("mmio fallback 1", 0x30000000, 256 * MiB); > > + > > + liointc = qdev_new("loongson.liointc"); > > Please use TYPE_name when creating QOM (here TYPE_LOONGSON_LIOINTC). > Similarly loongson3_virt_devices_init(). (no need to respin yet). OK, thanks.
Huacai > > > + sysbus_realize_and_unref(SYS_BUS_DEVICE(liointc), &error_fatal); > > + > > + sysbus_mmio_map(SYS_BUS_DEVICE(liointc), 0, > > virt_memmap[VIRT_LIOINTC].base); > > + > > + 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); > > + > > + sysbus_create_simple("goldfish_rtc", virt_memmap[VIRT_RTC].base, > > + qdev_get_gpio_in(liointc, RTC_IRQ)); > > + > > + cpuclk = clock_new(OBJECT(machine), "cpu-refclk"); > > + clock_set_hz(cpuclk, DEF_LOONGSON3_FREQ); > > + > > + for (i = 0; i < machine->smp.cpus; i++) { > > + int ip; > > + > > + /* init CPUs */ > > + cpu = mips_cpu_create_with_clock(machine->cpu_type, cpuclk); > > + > > + /* Init internal devices */ > > + cpu_mips_irq_init_cpu(cpu); > > + cpu_mips_clock_init(cpu); > > + qemu_register_reset(main_cpu_reset, cpu); > > + > > + if (i >= 4) { > > + continue; /* Only node-0 can be connected to LIOINTC */ > > + } > > + > > + for (ip = 0; ip < 4 ; ip++) { > > + int pin = i * 4 + ip; > > + sysbus_connect_irq(SYS_BUS_DEVICE(liointc), > > + pin, cpu->env.irq[ip + 2]); > > + } > > + } > > + env = &MIPS_CPU(first_cpu)->env; > ...