loongson3_virt has KVM SMP support in kenrel.
This patch adds TCG SMP support by enable IPI controller
for machine.

Also add definition about IRQs to enhance readability.

Note that TCG SMP can only support up to 4 CPUs as we
didn't implement multi-node support.

Signed-off-by: Jiaxun Yang <jiaxun.y...@flygoat.com>
---
 hw/mips/loongson3_bootp.h |  1 +
 hw/mips/loongson3_virt.c  | 41 ++++++++++++++++++++++++++++++++-------
 hw/mips/Kconfig           |  1 +
 3 files changed, 36 insertions(+), 7 deletions(-)

diff --git a/hw/mips/loongson3_bootp.h b/hw/mips/loongson3_bootp.h
index 09f8480abf..4756aa44f6 100644
--- a/hw/mips/loongson3_bootp.h
+++ b/hw/mips/loongson3_bootp.h
@@ -210,6 +210,7 @@ enum {
     VIRT_PCIE_ECAM,
     VIRT_BIOS_ROM,
     VIRT_UART,
+    VIRT_IPIS,
     VIRT_LIOINTC,
     VIRT_PCIE_MMIO,
     VIRT_HIGHMEM
diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c
index d4a82fa536..0765addb7f 100644
--- a/hw/mips/loongson3_virt.c
+++ b/hw/mips/loongson3_virt.c
@@ -35,6 +35,7 @@
 #include "hw/boards.h"
 #include "hw/char/serial.h"
 #include "hw/intc/loongson_liointc.h"
+#include "hw/intc/loongson_ipi.h"
 #include "hw/mips/mips.h"
 #include "hw/mips/cpudevs.h"
 #include "hw/mips/fw_cfg.h"
@@ -59,7 +60,11 @@
 
 #define PM_CNTL_MODE          0x10
 
-#define LOONGSON_MAX_VCPUS      16
+#define VCPU_PER_NODE         4
+#define TCG_MAX_NODES         1
+#define KVM_MAX_NODES         4
+#define TCG_MAX_VCPUS         (TCG_MAX_NODES  * VCPU_PER_NODE)
+#define KVM_MAX_VCPUS         (KVM_MAX_NODES  * VCPU_PER_NODE)
 
 /*
  * Loongson-3's virtual machine BIOS can be obtained here:
@@ -68,9 +73,16 @@
  */
 #define LOONGSON3_BIOSNAME "bios_loongson3.bin"
 
+/* IRQ allocation of CPU IP */
+#define LIOINTC_IP_START    2
+#define LIOINTC_IP_END      5
+#define IPI_IP              6
+
+/* IRQ allcation of LIOINTC */
 #define UART_IRQ            0
 #define RTC_IRQ             1
 #define PCIE_IRQ_BASE       2
+#define IPI_REG_SPACE       0x100
 
 const struct MemmapEntry virt_memmap[] = {
     [VIRT_LOWMEM] =      { 0x00000000,    0x10000000 },
@@ -81,6 +93,7 @@ const struct MemmapEntry virt_memmap[] = {
     [VIRT_PCIE_ECAM] =   { 0x1a000000,     0x2000000 },
     [VIRT_BIOS_ROM] =    { 0x1fc00000,      0x200000 },
     [VIRT_UART] =        { 0x1fe001e0,           0x8 },
+    [VIRT_IPIS] =        { 0x3ff01000,         0x400 },
     [VIRT_LIOINTC] =     { 0x3ff01400,          0x64 },
     [VIRT_PCIE_MMIO] =   { 0x40000000,    0x40000000 },
     [VIRT_HIGHMEM] =     { 0x80000000,           0x0 }, /* Variable */
@@ -495,6 +508,10 @@ static void mips_loongson3_virt_init(MachineState *machine)
             error_report("Loongson-3/TCG needs cpu type Loongson-3A1000");
             exit(1);
         }
+        if (machine->smp.cpus > TCG_MAX_VCPUS) {
+            error_report("Loongson-3/TCG supports up to %d CPUs", 
TCG_MAX_VCPUS);
+            exit(1);
+        }
     } else {
         if (!machine->cpu_type) {
             machine->cpu_type = MIPS_CPU_TYPE_NAME("Loongson-3A4000");
@@ -544,14 +561,24 @@ static void mips_loongson3_virt_init(MachineState 
*machine)
         cpu_mips_clock_init(cpu);
         qemu_register_reset(main_cpu_reset, cpu);
 
-        if (i >= 4) {
-            continue; /* Only node-0 can be connected to LIOINTC */
+        if (i >= VCPU_PER_NODE) {
+            continue; /* Only node-0 can be connected to LIOINTC and IPI */
+        }
+
+        if (!kvm_enabled()) {
+            /* IPI is handled by kernel for KVM */
+            DeviceState *ipi;
+            ipi = qdev_new(TYPE_LOONGSON_IPI);
+            sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), &error_fatal);
+            sysbus_mmio_map(SYS_BUS_DEVICE(ipi), 0,
+                            virt_memmap[VIRT_IPIS].base + IPI_REG_SPACE * i);
+            sysbus_connect_irq(SYS_BUS_DEVICE(ipi), 0, cpu->env.irq[IPI_IP]);
         }
 
-        for (ip = 0; ip < 4 ; ip++) {
-            int pin = i * 4 + ip;
+        for (ip = LIOINTC_IP_START; ip <= LIOINTC_IP_END ; ip++) {
+            int pin = i * 4 + (ip - LIOINTC_IP_START);
             sysbus_connect_irq(SYS_BUS_DEVICE(liointc),
-                               pin, cpu->env.irq[ip + 2]);
+                               pin, cpu->env.irq[ip]);
         }
     }
     env = &MIPS_CPU(first_cpu)->env;
@@ -619,7 +646,7 @@ static void loongson3v_machine_class_init(ObjectClass *oc, 
void *data)
     mc->desc = "Loongson-3 Virtualization Platform";
     mc->init = mips_loongson3_virt_init;
     mc->block_default_type = IF_IDE;
-    mc->max_cpus = LOONGSON_MAX_VCPUS;
+    mc->max_cpus = KVM_MAX_VCPUS;
     mc->default_ram_id = "loongson3.highram";
     mc->default_ram_size = 1600 * MiB;
     mc->kvm_type = mips_kvm_type;
diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig
index aadd436bf4..4fb0cc49e8 100644
--- a/hw/mips/Kconfig
+++ b/hw/mips/Kconfig
@@ -39,6 +39,7 @@ config LOONGSON3V
     select SERIAL
     select GOLDFISH_RTC
     select LOONGSON_LIOINTC
+    select LOONGSON_IPI if TCG
     select PCI_DEVICES
     select PCI_EXPRESS_GENERIC_BRIDGE
     select MSI_NONBROKEN
-- 
2.30.0


Reply via email to