All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH for-5.1 1/7] configure: Add KVM target support for MIPS64
@ 2020-04-27  9:33 Huacai Chen
  2020-04-27  9:33 ` [PATCH for-5.1 2/7] hw/mips: Implement the kvm_type() hook in MachineClass Huacai Chen
                   ` (6 more replies)
  0 siblings, 7 replies; 30+ messages in thread
From: Huacai Chen @ 2020-04-27  9:33 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, Aleksandar Markovic
  Cc: Huacai Chen, Huacai Chen, qemu-devel, Aurelien Jarno

Preparing for Loongson-3 virtualization, add KVM target support for
MIPS64 in configure script.

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 configure | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/configure b/configure
index 23b5e93..7581e65 100755
--- a/configure
+++ b/configure
@@ -198,7 +198,7 @@ supported_kvm_target() {
         arm:arm | aarch64:aarch64 | \
         i386:i386 | i386:x86_64 | i386:x32 | \
         x86_64:i386 | x86_64:x86_64 | x86_64:x32 | \
-        mips:mips | mipsel:mips | \
+        mips:mips | mipsel:mips | mips64:mips | mips64el:mips | \
         ppc:ppc | ppc64:ppc | ppc:ppc64 | ppc64:ppc64 | ppc64:ppc64le | \
         s390x:s390x)
             return 0
-- 
2.7.0



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH for-5.1 2/7] hw/mips: Implement the kvm_type() hook in MachineClass
  2020-04-27  9:33 [PATCH for-5.1 1/7] configure: Add KVM target support for MIPS64 Huacai Chen
@ 2020-04-27  9:33 ` Huacai Chen
  2020-04-27  9:33 ` [PATCH for-5.1 3/7] hw/mips: Add CPU IRQ3 delivery for KVM Huacai Chen
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 30+ messages in thread
From: Huacai Chen @ 2020-04-27  9:33 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, Aleksandar Markovic
  Cc: Huacai Chen, Huacai Chen, qemu-devel, Aurelien Jarno

MIPS has two types of KVM: TE & VZ, and TE is the default type. Now we
can't create a VZ guest in QEMU because it lacks the kvm_type() hook in
MachineClass. Besides, libvirt uses a null-machine to detect the kvm
capability, so by default it will return "KVM not supported" on a VZ
platform. Thus, null-machine also need the kvm_type() hook.

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 hw/core/Makefile.objs  |  2 +-
 hw/core/null-machine.c |  4 ++++
 hw/mips/Makefile.objs  |  2 +-
 hw/mips/common.c       | 29 +++++++++++++++++++++++++++++
 include/hw/mips/mips.h |  3 +++
 5 files changed, 38 insertions(+), 2 deletions(-)
 create mode 100644 hw/mips/common.c

diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs
index 6215e7c..7cfef1f 100644
--- a/hw/core/Makefile.objs
+++ b/hw/core/Makefile.objs
@@ -16,10 +16,10 @@ common-obj-$(CONFIG_SOFTMMU) += vm-change-state-handler.o
 common-obj-$(CONFIG_SOFTMMU) += qdev-properties-system.o
 common-obj-$(CONFIG_SOFTMMU) += sysbus.o
 common-obj-$(CONFIG_SOFTMMU) += machine.o
-common-obj-$(CONFIG_SOFTMMU) += null-machine.o
 common-obj-$(CONFIG_SOFTMMU) += loader.o
 common-obj-$(CONFIG_SOFTMMU) += machine-hmp-cmds.o
 common-obj-$(CONFIG_SOFTMMU) += numa.o
+obj-$(CONFIG_SOFTMMU) += null-machine.o
 obj-$(CONFIG_SOFTMMU) += machine-qmp-cmds.o
 
 common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o
diff --git a/hw/core/null-machine.c b/hw/core/null-machine.c
index cb47d9d..94a36f9 100644
--- a/hw/core/null-machine.c
+++ b/hw/core/null-machine.c
@@ -17,6 +17,7 @@
 #include "sysemu/sysemu.h"
 #include "exec/address-spaces.h"
 #include "hw/core/cpu.h"
+#include "hw/mips/mips.h"
 
 static void machine_none_init(MachineState *mch)
 {
@@ -50,6 +51,9 @@ static void machine_none_machine_init(MachineClass *mc)
     mc->max_cpus = 1;
     mc->default_ram_size = 0;
     mc->default_ram_id = "ram";
+#ifdef TARGET_MIPS
+    mc->kvm_type = mips_kvm_type;
+#endif
 }
 
 DEFINE_MACHINE("none", machine_none_machine_init)
diff --git a/hw/mips/Makefile.objs b/hw/mips/Makefile.objs
index 525809a..2f7795b 100644
--- a/hw/mips/Makefile.objs
+++ b/hw/mips/Makefile.objs
@@ -1,4 +1,4 @@
-obj-y += addr.o mips_int.o
+obj-y += addr.o common.o mips_int.o
 obj-$(CONFIG_R4K) += mips_r4k.o
 obj-$(CONFIG_MALTA) += gt64xxx_pci.o mips_malta.o
 obj-$(CONFIG_MIPSSIM) += mips_mipssim.o
diff --git a/hw/mips/common.c b/hw/mips/common.c
new file mode 100644
index 0000000..eb0c649
--- /dev/null
+++ b/hw/mips/common.c
@@ -0,0 +1,29 @@
+/*
+ * Common MIPS routines
+ *
+ * Copyright (c) 2020 Huacai Chen (chenhc@lemote.com)
+ * This code is licensed under the GNU GPL v2.
+ */
+
+#include <linux/kvm.h>
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "hw/boards.h"
+#include "hw/mips/mips.h"
+#include "sysemu/kvm_int.h"
+
+int mips_kvm_type(MachineState *machine, const char *vm_type)
+{
+    int r;
+    KVMState *s = KVM_STATE(machine->accelerator);;
+
+    r = kvm_check_extension(s, KVM_CAP_MIPS_VZ);
+    if (r > 0)
+        return KVM_VM_MIPS_VZ;
+
+    r = kvm_check_extension(s, KVM_CAP_MIPS_TE);
+    if (r > 0)
+        return KVM_VM_MIPS_TE;
+
+    return -1;
+}
diff --git a/include/hw/mips/mips.h b/include/hw/mips/mips.h
index 0af4c3d..2ac0580 100644
--- a/include/hw/mips/mips.h
+++ b/include/hw/mips/mips.h
@@ -20,4 +20,7 @@ void rc4030_dma_write(void *dma, uint8_t *buf, int len);
 
 DeviceState *rc4030_init(rc4030_dma **dmas, IOMMUMemoryRegion **dma_mr);
 
+/* common.c */
+int mips_kvm_type(MachineState *machine, const char *vm_type);
+
 #endif
-- 
2.7.0



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH for-5.1 3/7] hw/mips: Add CPU IRQ3 delivery for KVM
  2020-04-27  9:33 [PATCH for-5.1 1/7] configure: Add KVM target support for MIPS64 Huacai Chen
  2020-04-27  9:33 ` [PATCH for-5.1 2/7] hw/mips: Implement the kvm_type() hook in MachineClass Huacai Chen
@ 2020-04-27  9:33 ` Huacai Chen
  2020-04-27  9:57   ` Philippe Mathieu-Daudé
  2020-04-27  9:33 ` [PATCH for-5.1 4/7] target/mips: Add Loongson-3 CPU definition Huacai Chen
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 30+ messages in thread
From: Huacai Chen @ 2020-04-27  9:33 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, Aleksandar Markovic
  Cc: Huacai Chen, Huacai Chen, qemu-devel, Aurelien Jarno

Currently, KVM/MIPS only deliver I/O interrupt via IP2, this patch add
IP2 delivery as well, because Loongson-3 based machine use both IRQ2
(CPU's IP2) and IRQ3 (CPU's IP3).

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 hw/mips/mips_int.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c
index 796730b..5526219 100644
--- a/hw/mips/mips_int.c
+++ b/hw/mips/mips_int.c
@@ -48,16 +48,14 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level)
     if (level) {
         env->CP0_Cause |= 1 << (irq + CP0Ca_IP);
 
-        if (kvm_enabled() && irq == 2) {
+        if (kvm_enabled() && (irq == 2 || irq == 3))
             kvm_mips_set_interrupt(cpu, irq, level);
-        }
 
     } else {
         env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
 
-        if (kvm_enabled() && irq == 2) {
+        if (kvm_enabled() && (irq == 2 || irq == 3))
             kvm_mips_set_interrupt(cpu, irq, level);
-        }
     }
 
     if (env->CP0_Cause & CP0Ca_IP_mask) {
-- 
2.7.0



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH for-5.1 4/7] target/mips: Add Loongson-3 CPU definition
  2020-04-27  9:33 [PATCH for-5.1 1/7] configure: Add KVM target support for MIPS64 Huacai Chen
  2020-04-27  9:33 ` [PATCH for-5.1 2/7] hw/mips: Implement the kvm_type() hook in MachineClass Huacai Chen
  2020-04-27  9:33 ` [PATCH for-5.1 3/7] hw/mips: Add CPU IRQ3 delivery for KVM Huacai Chen
@ 2020-04-27  9:33 ` Huacai Chen
  2020-04-28  6:34   ` Philippe Mathieu-Daudé
  2020-04-27  9:33 ` [PATCH for-5.1 5/7] target/mips: Add more CP0 register for save/restore Huacai Chen
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 30+ messages in thread
From: Huacai Chen @ 2020-04-27  9:33 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, Aleksandar Markovic
  Cc: Huacai Chen, Huacai Chen, qemu-devel, Aurelien Jarno

Loongson-3 CPU family include Loongson-3A R1/R2/R3/R4 and Loongson-3B
R1/R2. Loongson-3A R4 is the newest and its ISA is almost the superset
of all others. To reduce complexity, we just define a "Loongson-3A" CPU
which is corresponding to Loongson-3A R4. Loongson-3A has CONFIG6 and
CONFIG7, so add their bit-fields as well.

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 target/mips/cpu.h                | 28 ++++++++++++++++++++++
 target/mips/internal.h           |  2 ++
 target/mips/mips-defs.h          |  7 ++++--
 target/mips/translate.c          |  2 ++
 target/mips/translate_init.inc.c | 51 ++++++++++++++++++++++++++++++++++++++++
 5 files changed, 88 insertions(+), 2 deletions(-)

diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index 94d01ea..0b3c987 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -940,7 +940,35 @@ struct CPUMIPSState {
 #define CP0C5_UFR          2
 #define CP0C5_NFExists     0
     int32_t CP0_Config6;
+    int32_t CP0_Config6_rw_bitmask;
+#define CP0C6_BPPASS          31
+#define CP0C6_KPOS            24
+#define CP0C6_KE              23
+#define CP0C6_VTLBONLY        22
+#define CP0C6_LASX            21
+#define CP0C6_SSEN            20
+#define CP0C6_DISDRTIME       19
+#define CP0C6_PIXNUEN         18
+#define CP0C6_SCRAND          17
+#define CP0C6_LLEXCEN         16
+#define CP0C6_DISVC           15
+#define CP0C6_VCLRU           14
+#define CP0C6_DCLRU           13
+#define CP0C6_PIXUEN          12
+#define CP0C6_DISBLKLYEN      11
+#define CP0C6_UMEMUALEN       10
+#define CP0C6_SFBEN           8
+#define CP0C6_FLTINT          7
+#define CP0C6_VLTINT          6
+#define CP0C6_DISBTB          5
+#define CP0C6_STPREFCTL       2
+#define CP0C6_INSTPREF        1
+#define CP0C6_DATAPREF        0
     int32_t CP0_Config7;
+    int64_t CP0_Config7_rw_bitmask;
+#define CP0C7_NAPCGEN       2
+#define CP0C7_UNIMUEN       1
+#define CP0C7_VFPUCGEN      0
     uint64_t CP0_LLAddr;
     uint64_t CP0_MAAR[MIPS_MAAR_MAX];
     int32_t CP0_MAARI;
diff --git a/target/mips/internal.h b/target/mips/internal.h
index 1bf274b..7853cb1 100644
--- a/target/mips/internal.h
+++ b/target/mips/internal.h
@@ -36,7 +36,9 @@ struct mips_def_t {
     int32_t CP0_Config5;
     int32_t CP0_Config5_rw_bitmask;
     int32_t CP0_Config6;
+    int32_t CP0_Config6_rw_bitmask;
     int32_t CP0_Config7;
+    int32_t CP0_Config7_rw_bitmask;
     target_ulong CP0_LLAddr_rw_bitmask;
     int CP0_LLAddr_shift;
     int32_t SYNCI_Step;
diff --git a/target/mips/mips-defs.h b/target/mips/mips-defs.h
index a831bb4..c2c96db 100644
--- a/target/mips/mips-defs.h
+++ b/target/mips/mips-defs.h
@@ -51,8 +51,9 @@
  */
 #define INSN_LOONGSON2E   0x0001000000000000ULL
 #define INSN_LOONGSON2F   0x0002000000000000ULL
-#define INSN_VR54XX       0x0004000000000000ULL
-#define INSN_R5900        0x0008000000000000ULL
+#define INSN_LOONGSON3A   0x0004000000000000ULL
+#define INSN_VR54XX       0x0008000000000000ULL
+#define INSN_R5900        0x0010000000000000ULL
 /*
  *   bits 56-63: vendor-specific ASEs
  */
@@ -94,6 +95,8 @@
 /* Wave Computing: "nanoMIPS" */
 #define CPU_NANOMIPS32  (CPU_MIPS32R6 | ISA_NANOMIPS32)
 
+#define CPU_LOONGSON3A  (CPU_MIPS64R2 | INSN_LOONGSON3A)
+
 /*
  * Strictly follow the architecture standard:
  * - Disallow "special" instruction handling for PMON/SPIM.
diff --git a/target/mips/translate.c b/target/mips/translate.c
index 25b595a..2caf4cb 100644
--- a/target/mips/translate.c
+++ b/target/mips/translate.c
@@ -31206,7 +31206,9 @@ void cpu_state_reset(CPUMIPSState *env)
     env->CP0_Config5 = env->cpu_model->CP0_Config5;
     env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
     env->CP0_Config6 = env->cpu_model->CP0_Config6;
+    env->CP0_Config6_rw_bitmask = env->cpu_model->CP0_Config6_rw_bitmask;
     env->CP0_Config7 = env->cpu_model->CP0_Config7;
+    env->CP0_Config7_rw_bitmask = env->cpu_model->CP0_Config7_rw_bitmask;
     env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
                                  << env->cpu_model->CP0_LLAddr_shift;
     env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
diff --git a/target/mips/translate_init.inc.c b/target/mips/translate_init.inc.c
index 6d145a9..a32412d 100644
--- a/target/mips/translate_init.inc.c
+++ b/target/mips/translate_init.inc.c
@@ -802,6 +802,57 @@ const mips_def_t mips_defs[] =
         .mmu_type = MMU_TYPE_R4000,
     },
     {
+        .name = "Loongson-3A",
+        .CP0_PRid = 0x14C000,
+        /* 64KB I-cache and d-cache. 4 way with 32 bit cache line size.  */
+        .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
+                       (MMU_TYPE_R4000 << CP0C0_MT),
+        .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) |
+                       (2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
+                       (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
+                       (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
+        .CP0_Config2 = MIPS_CONFIG2,
+        .CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_MSAP) |
+                       (1 << CP0C3_BP) | (1 << CP0C3_BI) | (1 << CP0C3_ULRI) |
+                       (1 << CP0C3_RXI) | (1 << CP0C3_LPA) | (1 << CP0C3_VInt),
+        .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) | (2 << CP0C4_IE) |
+                       (1 << CP0C4_AE) | (0x1c << CP0C4_KScrExist),
+        .CP0_Config4_rw_bitmask = 0,
+        .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_NFExists) | (1 << 18),
+        .CP0_Config5_rw_bitmask = (1 << CP0C5_K) | (1 << CP0C5_CV) |
+                                  (1 << CP0C5_MSAEn) | (1 << CP0C5_UFE) |
+                                  (1 << CP0C5_FRE) | (1 << CP0C5_SBRI),
+        .CP0_Config6 = (1 << CP0C6_VCLRU) | (1 << CP0C6_DCLRU) | (1 << CP0C6_SFBEN) |
+                       (1 << CP0C6_FLTINT) | (1 << CP0C6_INSTPREF) | (1 << CP0C6_DATAPREF),
+        .CP0_Config6_rw_bitmask = (1 << CP0C6_BPPASS) | (0x3f << CP0C6_KPOS) |
+                                  (1 << CP0C6_KE) | (1 << CP0C6_VTLBONLY) | (1 << CP0C6_LASX) |
+                                  (1 << CP0C6_SSEN) | (1 << CP0C6_DISDRTIME) |
+                                  (1 << CP0C6_PIXNUEN) | (1 << CP0C6_SCRAND) |
+                                  (1 << CP0C6_LLEXCEN) | (1 << CP0C6_DISVC) |
+                                  (1 << CP0C6_VCLRU) | (1 << CP0C6_DCLRU) |
+                                  (1 << CP0C6_PIXUEN) | (1 << CP0C6_DISBLKLYEN) |
+                                  (1 << CP0C6_UMEMUALEN) | (1 << CP0C6_SFBEN) |
+                                  (1 << CP0C6_FLTINT) | (1 << CP0C6_VLTINT) |
+                                  (1 << CP0C6_DISBTB) | (3 << CP0C6_STPREFCTL) |
+                                  (1 << CP0C6_INSTPREF) | (1 << CP0C6_DATAPREF),
+        .CP0_Config7 = 0,
+        .CP0_Config7_rw_bitmask = (1 << CP0C7_NAPCGEN) | (1 << CP0C7_UNIMUEN) | \
+                                  (1 << CP0C7_VFPUCGEN),
+        .CP0_LLAddr_rw_bitmask = 1,
+        .SYNCI_Step = 16,
+        .CCRes = 2,
+        .CP0_Status_rw_bitmask = 0x7DDBFFFF,
+        .CP0_PageGrain_rw_bitmask = (1U << CP0PG_RIE) | (1 << CP0PG_XIE) |
+                    (1 << CP0PG_ELPA) | (1 << CP0PG_IEC),
+        .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x1 << FCR0_REV) | (0x1 << FCR0_F64),
+        .CP1_fcr31 = 0,
+        .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
+        .SEGBITS = 48,
+        .PABITS = 48,
+        .insn_flags = CPU_LOONGSON3A,
+        .mmu_type = MMU_TYPE_R4000,
+    },
+    {
         /* A generic CPU providing MIPS64 DSP R2 ASE features.
            FIXME: Eventually this should be replaced by a real CPU model. */
         .name = "mips64dspr2",
-- 
2.7.0



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH for-5.1 5/7] target/mips: Add more CP0 register for save/restore
  2020-04-27  9:33 [PATCH for-5.1 1/7] configure: Add KVM target support for MIPS64 Huacai Chen
                   ` (2 preceding siblings ...)
  2020-04-27  9:33 ` [PATCH for-5.1 4/7] target/mips: Add Loongson-3 CPU definition Huacai Chen
@ 2020-04-27  9:33 ` Huacai Chen
  2020-04-28 19:10   ` Aleksandar Markovic
  2020-04-27  9:33 ` [PATCH for-5.1 6/7] hw/mips: Add Loongson-3 machine support (with KVM) Huacai Chen
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 30+ messages in thread
From: Huacai Chen @ 2020-04-27  9:33 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, Aleksandar Markovic
  Cc: Huacai Chen, Huacai Chen, qemu-devel, Aurelien Jarno

Add more CP0 register for save/restore, including: EBase, XContext,
PageGrain, PWBase, PWSize, PWField, PWCtl, Config*, KScratch1~KScratch6.

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 target/mips/kvm.c     | 212 ++++++++++++++++++++++++++++++++++++++++++++++++++
 target/mips/machine.c |   2 +
 2 files changed, 214 insertions(+)

diff --git a/target/mips/kvm.c b/target/mips/kvm.c
index de3e26e..96cfa10 100644
--- a/target/mips/kvm.c
+++ b/target/mips/kvm.c
@@ -245,10 +245,16 @@ int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level)
     (KVM_REG_MIPS_CP0 | KVM_REG_SIZE_U64 | (8 * (_R) + (_S)))
 
 #define KVM_REG_MIPS_CP0_INDEX          MIPS_CP0_32(0, 0)
+#define KVM_REG_MIPS_CP0_RANDOM         MIPS_CP0_32(1, 0)
 #define KVM_REG_MIPS_CP0_CONTEXT        MIPS_CP0_64(4, 0)
 #define KVM_REG_MIPS_CP0_USERLOCAL      MIPS_CP0_64(4, 2)
 #define KVM_REG_MIPS_CP0_PAGEMASK       MIPS_CP0_32(5, 0)
+#define KVM_REG_MIPS_CP0_PAGEGRAIN      MIPS_CP0_32(5, 1)
+#define KVM_REG_MIPS_CP0_PWBASE         MIPS_CP0_64(5, 5)
+#define KVM_REG_MIPS_CP0_PWFIELD        MIPS_CP0_64(5, 6)
+#define KVM_REG_MIPS_CP0_PWSIZE         MIPS_CP0_64(5, 7)
 #define KVM_REG_MIPS_CP0_WIRED          MIPS_CP0_32(6, 0)
+#define KVM_REG_MIPS_CP0_PWCTL          MIPS_CP0_32(6, 6)
 #define KVM_REG_MIPS_CP0_HWRENA         MIPS_CP0_32(7, 0)
 #define KVM_REG_MIPS_CP0_BADVADDR       MIPS_CP0_64(8, 0)
 #define KVM_REG_MIPS_CP0_COUNT          MIPS_CP0_32(9, 0)
@@ -258,13 +264,22 @@ int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level)
 #define KVM_REG_MIPS_CP0_CAUSE          MIPS_CP0_32(13, 0)
 #define KVM_REG_MIPS_CP0_EPC            MIPS_CP0_64(14, 0)
 #define KVM_REG_MIPS_CP0_PRID           MIPS_CP0_32(15, 0)
+#define KVM_REG_MIPS_CP0_EBASE          MIPS_CP0_64(15, 1)
 #define KVM_REG_MIPS_CP0_CONFIG         MIPS_CP0_32(16, 0)
 #define KVM_REG_MIPS_CP0_CONFIG1        MIPS_CP0_32(16, 1)
 #define KVM_REG_MIPS_CP0_CONFIG2        MIPS_CP0_32(16, 2)
 #define KVM_REG_MIPS_CP0_CONFIG3        MIPS_CP0_32(16, 3)
 #define KVM_REG_MIPS_CP0_CONFIG4        MIPS_CP0_32(16, 4)
 #define KVM_REG_MIPS_CP0_CONFIG5        MIPS_CP0_32(16, 5)
+#define KVM_REG_MIPS_CP0_CONFIG6        MIPS_CP0_32(16, 6)
+#define KVM_REG_MIPS_CP0_XCONTEXT       MIPS_CP0_64(20, 0)
 #define KVM_REG_MIPS_CP0_ERROREPC       MIPS_CP0_64(30, 0)
+#define KVM_REG_MIPS_CP0_KSCRATCH1      MIPS_CP0_64(31, 2)
+#define KVM_REG_MIPS_CP0_KSCRATCH2      MIPS_CP0_64(31, 3)
+#define KVM_REG_MIPS_CP0_KSCRATCH3      MIPS_CP0_64(31, 4)
+#define KVM_REG_MIPS_CP0_KSCRATCH4      MIPS_CP0_64(31, 5)
+#define KVM_REG_MIPS_CP0_KSCRATCH5      MIPS_CP0_64(31, 6)
+#define KVM_REG_MIPS_CP0_KSCRATCH6      MIPS_CP0_64(31, 7)
 
 static inline int kvm_mips_put_one_reg(CPUState *cs, uint64_t reg_id,
                                        int32_t *addr)
@@ -394,6 +409,29 @@ static inline int kvm_mips_get_one_ureg64(CPUState *cs, uint64_t reg_id,
                                          (1U << CP0C5_UFE) | \
                                          (1U << CP0C5_FRE) | \
                                          (1U << CP0C5_UFR))
+#define KVM_REG_MIPS_CP0_CONFIG6_MASK   ((1U << CP0C6_BPPASS) | \
+                                         (0x3fU << CP0C6_KPOS) | \
+                                         (1U << CP0C6_KE) | \
+                                         (1U << CP0C6_VTLBONLY) | \
+                                         (1U << CP0C6_LASX) | \
+                                         (1U << CP0C6_SSEN) | \
+                                         (1U << CP0C6_DISDRTIME) | \
+                                         (1U << CP0C6_PIXNUEN) | \
+                                         (1U << CP0C6_SCRAND) | \
+                                         (1U << CP0C6_LLEXCEN) | \
+                                         (1U << CP0C6_DISVC) | \
+                                         (1U << CP0C6_VCLRU) | \
+                                         (1U << CP0C6_DCLRU) | \
+                                         (1U << CP0C6_PIXUEN) | \
+                                         (1U << CP0C6_DISBLKLYEN) | \
+                                         (1U << CP0C6_UMEMUALEN) | \
+                                         (1U << CP0C6_SFBEN) | \
+                                         (1U << CP0C6_FLTINT) | \
+                                         (1U << CP0C6_VLTINT) | \
+                                         (1U << CP0C6_DISBTB) | \
+                                         (3U << CP0C6_STPREFCTL) | \
+                                         (1U << CP0C6_INSTPREF) | \
+                                         (1U << CP0C6_DATAPREF))
 
 static inline int kvm_mips_change_one_reg(CPUState *cs, uint64_t reg_id,
                                           int32_t *addr, int32_t mask)
@@ -729,6 +767,11 @@ static int kvm_mips_put_cp0_registers(CPUState *cs, int level)
         DPRINTF("%s: Failed to put CP0_INDEX (%d)\n", __func__, err);
         ret = err;
     }
+    err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_RANDOM, &env->CP0_Random);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_RANDOM (%d)\n", __func__, err);
+        ret = err;
+    }
     err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT,
                                  &env->CP0_Context);
     if (err < 0) {
@@ -747,11 +790,40 @@ static int kvm_mips_put_cp0_registers(CPUState *cs, int level)
         DPRINTF("%s: Failed to put CP0_PAGEMASK (%d)\n", __func__, err);
         ret = err;
     }
+    err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PAGEGRAIN,
+                               &env->CP0_PageGrain);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_PAGEGRAIN (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWBASE,
+                               &env->CP0_PWBase);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_PWBASE (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWFIELD,
+                               &env->CP0_PWField);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_PWField (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWSIZE,
+                               &env->CP0_PWSize);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_PWSIZE (%d)\n", __func__, err);
+        ret = err;
+    }
     err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired);
     if (err < 0) {
         DPRINTF("%s: Failed to put CP0_WIRED (%d)\n", __func__, err);
         ret = err;
     }
+    err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PWCTL, &env->CP0_PWCtl);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_PWCTL (%d)\n", __func__, err);
+        ret = err;
+    }
     err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_HWRENA, &env->CP0_HWREna);
     if (err < 0) {
         DPRINTF("%s: Failed to put CP0_HWRENA (%d)\n", __func__, err);
@@ -799,6 +871,11 @@ static int kvm_mips_put_cp0_registers(CPUState *cs, int level)
         DPRINTF("%s: Failed to put CP0_PRID (%d)\n", __func__, err);
         ret = err;
     }
+    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_EBASE, &env->CP0_EBase);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_EBASE (%d)\n", __func__, err);
+        ret = err;
+    }
     err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG,
                                   &env->CP0_Config0,
                                   KVM_REG_MIPS_CP0_CONFIG_MASK);
@@ -841,12 +918,61 @@ static int kvm_mips_put_cp0_registers(CPUState *cs, int level)
         DPRINTF("%s: Failed to change CP0_CONFIG5 (%d)\n", __func__, err);
         ret = err;
     }
+    err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG6,
+                                  &env->CP0_Config6,
+                                  KVM_REG_MIPS_CP0_CONFIG6_MASK);
+    if (err < 0) {
+        DPRINTF("%s: Failed to change CP0_CONFIG6 (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_XCONTEXT,
+                                 &env->CP0_XContext);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_XCONTEXT (%d)\n", __func__, err);
+        ret = err;
+    }
     err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
                                  &env->CP0_ErrorEPC);
     if (err < 0) {
         DPRINTF("%s: Failed to put CP0_ERROREPC (%d)\n", __func__, err);
         ret = err;
     }
+    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH1,
+                                 &env->CP0_KScratch[0]);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_KSCRATCH1 (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH2,
+                                 &env->CP0_KScratch[1]);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_KSCRATCH2 (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH3,
+                                 &env->CP0_KScratch[2]);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_KSCRATCH3 (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH4,
+                                 &env->CP0_KScratch[3]);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_KSCRATCH4 (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH5,
+                                 &env->CP0_KScratch[4]);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_KSCRATCH5 (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH6,
+                                 &env->CP0_KScratch[5]);
+    if (err < 0) {
+        DPRINTF("%s: Failed to put CP0_KSCRATCH6 (%d)\n", __func__, err);
+        ret = err;
+    }
 
     return ret;
 }
@@ -862,6 +988,11 @@ static int kvm_mips_get_cp0_registers(CPUState *cs)
         DPRINTF("%s: Failed to get CP0_INDEX (%d)\n", __func__, err);
         ret = err;
     }
+    err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_RANDOM, &env->CP0_Random);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_RANDOM (%d)\n", __func__, err);
+        ret = err;
+    }
     err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT,
                                  &env->CP0_Context);
     if (err < 0) {
@@ -880,11 +1011,40 @@ static int kvm_mips_get_cp0_registers(CPUState *cs)
         DPRINTF("%s: Failed to get CP0_PAGEMASK (%d)\n", __func__, err);
         ret = err;
     }
+    err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PAGEGRAIN,
+                               &env->CP0_PageGrain);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_PAGEGRAIN (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWBASE,
+                               &env->CP0_PWBase);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_PWBASE (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWFIELD,
+                               &env->CP0_PWField);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_PWFIELD (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWSIZE,
+                               &env->CP0_PWSize);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_PWSIZE (%d)\n", __func__, err);
+        ret = err;
+    }
     err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired);
     if (err < 0) {
         DPRINTF("%s: Failed to get CP0_WIRED (%d)\n", __func__, err);
         ret = err;
     }
+    err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PWCTL, &env->CP0_PWCtl);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_PWCtl (%d)\n", __func__, err);
+        ret = err;
+    }
     err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_HWRENA, &env->CP0_HWREna);
     if (err < 0) {
         DPRINTF("%s: Failed to get CP0_HWRENA (%d)\n", __func__, err);
@@ -932,6 +1092,11 @@ static int kvm_mips_get_cp0_registers(CPUState *cs)
         DPRINTF("%s: Failed to get CP0_PRID (%d)\n", __func__, err);
         ret = err;
     }
+    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_EBASE, &env->CP0_EBase);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_EBASE (%d)\n", __func__, err);
+        ret = err;
+    }
     err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG, &env->CP0_Config0);
     if (err < 0) {
         DPRINTF("%s: Failed to get CP0_CONFIG (%d)\n", __func__, err);
@@ -962,12 +1127,59 @@ static int kvm_mips_get_cp0_registers(CPUState *cs)
         DPRINTF("%s: Failed to get CP0_CONFIG5 (%d)\n", __func__, err);
         ret = err;
     }
+    err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG6, &env->CP0_Config6);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_CONFIG6 (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_XCONTEXT,
+                                 &env->CP0_XContext);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_XCONTEXT (%d)\n", __func__, err);
+        ret = err;
+    }
     err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
                                  &env->CP0_ErrorEPC);
     if (err < 0) {
         DPRINTF("%s: Failed to get CP0_ERROREPC (%d)\n", __func__, err);
         ret = err;
     }
+    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH1,
+                                 &env->CP0_KScratch[0]);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_KSCRATCH1 (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH2,
+                                 &env->CP0_KScratch[1]);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_KSCRATCH2 (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH3,
+                                 &env->CP0_KScratch[2]);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_KSCRATCH3 (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH4,
+                                 &env->CP0_KScratch[3]);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_KSCRATCH4 (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH5,
+                                 &env->CP0_KScratch[4]);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_KSCRATCH5 (%d)\n", __func__, err);
+        ret = err;
+    }
+    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH6,
+                                 &env->CP0_KScratch[5]);
+    if (err < 0) {
+        DPRINTF("%s: Failed to get CP0_KSCRATCH6 (%d)\n", __func__, err);
+        ret = err;
+    }
 
     return ret;
 }
diff --git a/target/mips/machine.c b/target/mips/machine.c
index 8d5b18b..a84aefc 100644
--- a/target/mips/machine.c
+++ b/target/mips/machine.c
@@ -289,6 +289,8 @@ const VMStateDescription vmstate_mips_cpu = {
         VMSTATE_INT32(env.CP0_Config1, MIPSCPU),
         VMSTATE_INT32(env.CP0_Config2, MIPSCPU),
         VMSTATE_INT32(env.CP0_Config3, MIPSCPU),
+        VMSTATE_INT32(env.CP0_Config4, MIPSCPU),
+        VMSTATE_INT32(env.CP0_Config5, MIPSCPU),
         VMSTATE_INT32(env.CP0_Config6, MIPSCPU),
         VMSTATE_INT32(env.CP0_Config7, MIPSCPU),
         VMSTATE_UINT64(env.CP0_LLAddr, MIPSCPU),
-- 
2.7.0



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH for-5.1 6/7] hw/mips: Add Loongson-3 machine support (with KVM)
  2020-04-27  9:33 [PATCH for-5.1 1/7] configure: Add KVM target support for MIPS64 Huacai Chen
                   ` (3 preceding siblings ...)
  2020-04-27  9:33 ` [PATCH for-5.1 5/7] target/mips: Add more CP0 register for save/restore Huacai Chen
@ 2020-04-27  9:33 ` Huacai Chen
  2020-04-28 19:23   ` Aleksandar Markovic
  2020-04-27  9:33 ` [PATCH for-5.1 7/7] MAINTAINERS: Add myself as Loongson-3 maintainer Huacai Chen
  2020-04-28 19:15 ` [PATCH for-5.1 1/7] configure: Add KVM target support for MIPS64 Aleksandar Markovic
  6 siblings, 1 reply; 30+ messages in thread
From: Huacai Chen @ 2020-04-27  9:33 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, Aleksandar Markovic
  Cc: Huacai Chen, Huacai Chen, qemu-devel, Aurelien Jarno

Add Loongson-3 based machine support, it use i8259 as the interrupt
controler and use GPEX as the pci controller. Currently it can only
work with KVM, but we will add TCG support in future.

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 default-configs/mips64el-softmmu.mak |   1 +
 hw/mips/Kconfig                      |  10 +
 hw/mips/Makefile.objs                |   1 +
 hw/mips/mips_loongson3.c             | 869 +++++++++++++++++++++++++++++++++++
 4 files changed, 881 insertions(+)
 create mode 100644 hw/mips/mips_loongson3.c

diff --git a/default-configs/mips64el-softmmu.mak b/default-configs/mips64el-softmmu.mak
index 8b0c9b1..fc798e4 100644
--- a/default-configs/mips64el-softmmu.mak
+++ b/default-configs/mips64el-softmmu.mak
@@ -3,6 +3,7 @@
 include mips-softmmu-common.mak
 CONFIG_IDE_VIA=y
 CONFIG_FULONG=y
+CONFIG_LOONGSON3=y
 CONFIG_ATI_VGA=y
 CONFIG_RTL8139_PCI=y
 CONFIG_JAZZ=y
diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig
index 2c2adbc..6f16b16 100644
--- a/hw/mips/Kconfig
+++ b/hw/mips/Kconfig
@@ -44,6 +44,16 @@ config JAZZ
 config FULONG
     bool
 
+config LOONGSON3
+    bool
+    select PCKBD
+    select SERIAL
+    select ISA_BUS
+    select PCI_EXPRESS_GENERIC_BRIDGE
+    select VIRTIO_VGA
+    select QXL if SPICE
+    select MSI_NONBROKEN
+
 config MIPS_CPS
     bool
     select PTIMER
diff --git a/hw/mips/Makefile.objs b/hw/mips/Makefile.objs
index 2f7795b..f9bc8f5 100644
--- a/hw/mips/Makefile.objs
+++ b/hw/mips/Makefile.objs
@@ -4,5 +4,6 @@ obj-$(CONFIG_MALTA) += gt64xxx_pci.o mips_malta.o
 obj-$(CONFIG_MIPSSIM) += mips_mipssim.o
 obj-$(CONFIG_JAZZ) += mips_jazz.o
 obj-$(CONFIG_FULONG) += mips_fulong2e.o
+obj-$(CONFIG_LOONGSON3) += mips_loongson3.o
 obj-$(CONFIG_MIPS_CPS) += cps.o
 obj-$(CONFIG_MIPS_BOSTON) += boston.o
diff --git a/hw/mips/mips_loongson3.c b/hw/mips/mips_loongson3.c
new file mode 100644
index 0000000..a45c9ec
--- /dev/null
+++ b/hw/mips/mips_loongson3.c
@@ -0,0 +1,869 @@
+/*
+ * Generic Loongson-3 Platform support
+ *
+ * Copyright (c) 2015-2020 Huacai Chen (chenhc@lemote.com)
+ * This code is licensed under the GNU GPL v2.
+ *
+ * Contributions are licensed under the terms of the GNU GPL,
+ * version 2 or (at your option) any later version.
+ */
+
+/*
+ * Generic PC Platform based on Loongson-3 CPU (MIPS64R2 with extensions,
+ * 800~2000MHz)
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qemu/units.h"
+#include "qapi/error.h"
+#include "cpu.h"
+#include "elf.h"
+#include "hw/boards.h"
+#include "hw/block/flash.h"
+#include "hw/char/serial.h"
+#include "hw/mips/mips.h"
+#include "hw/mips/cpudevs.h"
+#include "hw/intc/i8259.h"
+#include "hw/loader.h"
+#include "hw/ide.h"
+#include "hw/isa/superio.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_host.h"
+#include "hw/pci-host/gpex.h"
+#include "hw/rtc/mc146818rtc.h"
+#include "net/net.h"
+#include "exec/address-spaces.h"
+#include "sysemu/qtest.h"
+#include "sysemu/reset.h"
+#include "sysemu/runstate.h"
+#include "qemu/log.h"
+#include "qemu/error-report.h"
+
+#define INITRD_OFFSET		0x04000000
+#define BOOTPARAM_ADDR		0x8ff00000
+#define BOOTPARAM_PHYADDR	0x0ff00000
+#define CFG_ADDR 		0x0f100000
+#define FW_CONF_ADDR		0x0fff0000
+#define PM_MMIO_ADDR		0x10080000
+#define PM_MMIO_SIZE		0x100
+#define PM_CNTL_MODE		0x10
+
+#define PHYS_TO_VIRT(x) ((x) | ~(target_ulong)0x7fffffff)
+
+/* Loongson-3 has a 2MB flash rom */
+#define BIOS_SIZE               (2 * MiB)
+#define LOONGSON_MAX_VCPUS      16
+
+#define LOONGSON3_BIOSNAME "bios_loongson3.bin"
+
+#define PCIE_IRQ_BASE	   3
+
+#define VIRT_PCI_IO_BASE    0x18000000ul
+#define VIRT_PCI_IO_SIZE    0x000c0000ul
+#define VIRT_PCI_MEM_BASE   0x40000000ul
+#define VIRT_PCI_MEM_SIZE   0x40000000ul
+#define VIRT_PCI_ECAM_BASE  0x1a000000ul
+#define VIRT_PCI_ECAM_SIZE  0x02000000ul
+
+#define align(x) (((x) + 63) & ~63)
+
+struct efi_memory_map_loongson {
+    uint16_t vers;               /* version of efi_memory_map */
+    uint32_t nr_map;             /* number of memory_maps */
+    uint32_t mem_freq;           /* memory frequence */
+    struct mem_map{
+        uint32_t node_id;        /* node_id which memory attached to */
+        uint32_t mem_type;       /* system memory, pci memory, pci io, etc. */
+        uint64_t mem_start;      /* memory map start address */
+        uint32_t mem_size;       /* each memory_map size, not the total size */
+    } map[128];
+} __attribute__((packed));
+
+enum loongson_cpu_type {
+    Legacy_2E = 0x0,
+    Legacy_2F = 0x1,
+    Legacy_3A = 0x2,
+    Legacy_3B = 0x3,
+    Legacy_1A = 0x4,
+    Legacy_1B = 0x5,
+    Legacy_2G = 0x6,
+    Legacy_2H = 0x7,
+    Loongson_1A = 0x100,
+    Loongson_1B = 0x101,
+    Loongson_2E = 0x200,
+    Loongson_2F = 0x201,
+    Loongson_2G = 0x202,
+    Loongson_2H = 0x203,
+    Loongson_3A = 0x300,
+    Loongson_3B = 0x301
+};
+
+/*
+ * Capability and feature descriptor structure for MIPS CPU
+ */
+struct efi_cpuinfo_loongson {
+    uint16_t vers;               /* version of efi_cpuinfo_loongson */
+    uint32_t processor_id;       /* PRID, e.g. 6305, 6306 */
+    uint32_t cputype;            /* Loongson_3A/3B, etc. */
+    uint32_t total_node;         /* num of total numa nodes */
+    uint16_t cpu_startup_core_id;   /* Boot core id */
+    uint16_t reserved_cores_mask;
+    uint32_t cpu_clock_freq;     /* cpu_clock */
+    uint32_t nr_cpus;
+    char cpuname[64];
+} __attribute__((packed));
+
+#define MAX_UARTS 64
+struct uart_device {
+    uint32_t iotype; /* see include/linux/serial_core.h */
+    uint32_t uartclk;
+    uint32_t int_offset;
+    uint64_t uart_base;
+} __attribute__((packed));
+
+#define MAX_SENSORS 64
+#define SENSOR_TEMPER  0x00000001
+#define SENSOR_VOLTAGE 0x00000002
+#define SENSOR_FAN     0x00000004
+struct sensor_device {
+    char name[32];  /* a formal name */
+    char label[64]; /* a flexible description */
+    uint32_t type;       /* SENSOR_* */
+    uint32_t id;         /* instance id of a sensor-class */
+    uint32_t fan_policy; /* see arch/mips/include/asm/mach-loongson/loongson_hwmon.h */
+    uint32_t fan_percent;/* only for constant speed policy */
+    uint64_t base_addr;  /* base address of device registers */
+} __attribute__((packed));
+
+struct system_loongson {
+    uint16_t vers;               /* version of system_loongson */
+    uint32_t ccnuma_smp;         /* 0: no numa; 1: has numa */
+    uint32_t sing_double_channel;/* 1: single; 2: double */
+    uint32_t nr_uarts;
+    struct uart_device uarts[MAX_UARTS];
+    uint32_t nr_sensors;
+    struct sensor_device sensors[MAX_SENSORS];
+    char has_ec;
+    char ec_name[32];
+    uint64_t ec_base_addr;
+    char has_tcm;
+    char tcm_name[32];
+    uint64_t tcm_base_addr;
+    uint64_t workarounds; /* see workarounds.h */
+    uint64_t of_dtb_addr; /* NULL if not support */
+} __attribute__((packed));
+
+struct irq_source_routing_table {
+    uint16_t vers;
+    uint16_t size;
+    uint16_t rtr_bus;
+    uint16_t rtr_devfn;
+    uint32_t vendor;
+    uint32_t device;
+    uint32_t PIC_type;           /* conform use HT or PCI to route to CPU-PIC */
+    uint64_t ht_int_bit;         /* 3A: 1<<24; 3B: 1<<16 */
+    uint64_t ht_enable;          /* irqs used in this PIC */
+    uint32_t node_id;            /* node id: 0x0-0; 0x1-1; 0x10-2; 0x11-3 */
+    uint64_t pci_mem_start_addr;
+    uint64_t pci_mem_end_addr;
+    uint64_t pci_io_start_addr;
+    uint64_t pci_io_end_addr;
+    uint64_t pci_config_addr;
+    uint16_t dma_mask_bits;
+    uint16_t dma_noncoherent;
+} __attribute__((packed));
+
+struct interface_info {
+    uint16_t vers;               /* version of the specificition */
+    uint16_t size;
+    uint8_t  flag;
+    char description[64];
+} __attribute__((packed));
+
+#define MAX_RESOURCE_NUMBER 128
+struct resource_loongson {
+    uint64_t start;              /* resource start address */
+    uint64_t end;                /* resource end address */
+    char name[64];
+    uint32_t flags;
+};
+
+struct archdev_data {};          /* arch specific additions */
+
+struct board_devices {
+    char name[64];               /* hold the device name */
+    uint32_t num_resources;      /* number of device_resource */
+    /* for each device's resource */
+    struct resource_loongson resource[MAX_RESOURCE_NUMBER];
+    /* arch specific additions */
+    struct archdev_data archdata;
+};
+
+struct loongson_special_attribute {
+    uint16_t vers;               /* version of this special */
+    char special_name[64];       /* special_atribute_name */
+    uint32_t loongson_special_type; /* type of special device */
+    /* for each device's resource */
+    struct resource_loongson resource[MAX_RESOURCE_NUMBER];
+};
+
+struct loongson_params {
+    uint64_t memory_offset;      /* efi_memory_map_loongson struct offset */
+    uint64_t cpu_offset;         /* efi_cpuinfo_loongson struct offset */
+    uint64_t system_offset;      /* system_loongson struct offset */
+    uint64_t irq_offset;         /* irq_source_routing_table struct offset */
+    uint64_t interface_offset;   /* interface_info struct offset */
+    uint64_t special_offset;     /* loongson_special_attribute struct offset */
+    uint64_t boarddev_table_offset;  /* board_devices offset */
+};
+
+struct smbios_tables {
+    uint16_t vers;               /* version of smbios */
+    uint64_t vga_bios;           /* vga_bios address */
+    struct loongson_params lp;
+};
+
+struct efi_reset_system_t {
+    uint64_t ResetCold;
+    uint64_t ResetWarm;
+    uint64_t ResetType;
+    uint64_t Shutdown;
+    uint64_t DoSuspend; /* NULL if not support */
+};
+
+struct efi_loongson {
+    uint64_t mps;                /* MPS table */
+    uint64_t acpi;               /* ACPI table (IA64 ext 0.71) */
+    uint64_t acpi20;             /* ACPI table (ACPI 2.0) */
+    struct smbios_tables smbios; /* SM BIOS table */
+    uint64_t sal_systab;         /* SAL system table */
+    uint64_t boot_info;          /* boot info table */
+};
+
+struct boot_params {
+    struct efi_loongson efi;
+    struct efi_reset_system_t reset_system;
+};
+
+static struct _fw_config {
+    unsigned long ram_size;
+    unsigned int mem_freq;
+    unsigned int nr_cpus;
+    unsigned int cpu_clock_freq;
+} fw_config;
+
+static struct _loaderparams {
+    unsigned long ram_size;
+    const char *kernel_cmdline;
+    const char *kernel_filename;
+    const char *initrd_filename;
+    int64_t kernel_entry;
+    unsigned long a0, a1, a2;
+} loaderparams;
+
+static void *boot_params_p;
+static void *boot_params_buf;
+
+static unsigned int bios_boot_code[] = {
+    0x40086000,   /* mfc0    t0, CP0_STATUS                                        */
+    0x240900E2,   /* li      t1, 0x00e2       #{cu3,cu2,cu1,cu0,status_fr}<={0111} */
+    0x01094025,   /* or      t0, t0, t1                                            */
+    0x40886000,   /* mtc0    t0, CP0_STATUS                                        */
+    0x00000000,
+    0x40086000,   /* mfc0    t0, CP0_STATUS                                        */
+    0x3C090040,   /* lui     t1, 0x40         #bev                                 */
+    0x01094025,   /* or      t0, t0, t1                                            */
+    0x40886000,   /* mtc0    t0, CP0_STATUS                                        */
+    0x00000000,
+    0x40806800,   /* mtc0    zero, CP0_CAUSE                                       */
+    0x00000000,
+    0x400A7801,   /* mfc0    t2, $15, 1                                            */
+    0x314A00FF,   /* andi    t2, 0x0ff                                             */
+    0x3C089000,   /* dli     t0, 0x900000003ff01000                                */
+    0x00084438,
+    0x35083FF0,
+    0x00084438,
+    0x35081000,
+    0x314B0003,   /* andi    t3, t2, 0x3      #local cpuid                         */
+    0x000B5A00,   /* sll     t3, 8                                                 */
+    0x010B4025,   /* or      t0, t0, t3                                            */
+    0x314C000C,   /* andi    t4, t2, 0xc      #node id                             */
+    0x000C62BC,   /* dsll    t4, 42                                                */
+    0x010C4025,   /* or      t0, t0, t4                                            */
+                  /* waitforinit:                                                  */
+    0xDD020020,   /* ld      v0, FN_OFF(t0)   #FN_OFF 0x020                        */
+    0x1040FFFE,   /* beqz    v0, waitforinit                                       */
+    0x00000000,   /* nop                                                           */
+    0xDD1D0028,   /* ld      sp, SP_OFF(t0)   #FN_OFF 0x028                        */
+    0xDD1C0030,   /* ld      gp, GP_OFF(t0)   #FN_OFF 0x030                        */
+    0xDD050038,   /* ld      a1, A1_OFF(t0)   #FN_OFF 0x038                        */
+    0x00400008,   /* jr      v0               #byebye                              */
+    0x00000000,   /* nop                                                           */
+    0x1000FFFF,   /* 1:  b   1b                                                    */
+    0x00000000,   /* nop                                                           */
+
+                  /* Reset                                                         */
+    0x3C0C9000,   /* dli     t0, 0x9000000010080010                                */
+    0x358C0000,
+    0x000C6438,
+    0x358C1008,
+    0x000C6438,
+    0x358C0010,
+    0x240D0000,   /* li      t1, 0x00                                              */
+    0xA18D0000,   /* sb      t1, (t0)                                              */
+    0x1000FFFF,   /* 1:  b   1b                                                    */
+    0x00000000,   /* nop                                                           */
+
+                  /* Shutdown                                                      */
+    0x3C0C9000,   /* dli     t0, 0x9000000010080010                                */
+    0x358C0000,
+    0x000C6438,
+    0x358C1008,
+    0x000C6438,
+    0x358C0010,
+    0x240D00FF,   /* li      t1, 0xff                                              */
+    0xA18D0000,   /* sb      t1, (t0)                                              */
+    0x1000FFFF,   /* 1:  b   1b                                                    */
+    0x00000000    /* nop                                                           */
+};
+
+static uint64_t loongson3_pm_read(void *opaque, hwaddr addr, unsigned size)
+{
+    return 0;
+}
+
+static void loongson3_pm_write(void *opaque, hwaddr addr, uint64_t val,unsigned size)
+{
+    if (addr != PM_CNTL_MODE)
+        return;
+
+    switch (val) {
+    case 0x00:
+        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
+        return;
+    case 0xff:
+        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
+        return;
+    default:
+        return;
+    }
+}
+
+static const MemoryRegionOps loongson3_pm_ops = {
+    .read  = loongson3_pm_read,
+    .write = loongson3_pm_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static struct efi_memory_map_loongson *init_memory_map(void *g_map)
+{
+    struct efi_memory_map_loongson *emap = g_map;
+
+    emap->nr_map = 2;
+    emap->mem_freq = 300000000;
+
+    emap->map[0].node_id = 0;
+    emap->map[0].mem_type = 1;
+    emap->map[0].mem_start = 0x0;
+    emap->map[0].mem_size = (loaderparams.ram_size > 0x10000000
+                            ? 256 : (loaderparams.ram_size >> 20)) - 16;
+
+    emap->map[1].node_id = 0;
+    emap->map[1].mem_type = 2;
+    emap->map[1].mem_start = 0x90000000;
+    emap->map[1].mem_size = (loaderparams.ram_size > 0x10000000
+                            ? (loaderparams.ram_size >> 20) - 256 : 0);
+
+    return emap;
+}
+
+static int get_host_cpu_freq(void)
+{
+    int fd = 0, freq = 0;
+    char buf[1024], *buf_p;
+
+    if ((fd = open("/proc/cpuinfo", O_RDONLY)) == -1) {
+        fprintf(stderr, "Failed to open /proc/cpuinfo!\n");
+        return 0;
+    }
+
+    if (read(fd, buf, 1024) < 0) {
+        close(fd);
+        fprintf(stderr, "Failed to read /proc/cpuinfo!\n");
+        return 0;
+    }
+    close(fd);
+
+    buf_p = strstr(buf, "model name");
+    while (*buf_p != '@') buf_p++;
+
+    buf_p += 2;
+    memcpy(buf, buf_p, 12);
+    buf_p = buf;
+    while ((*buf_p >= '0') && (*buf_p <= '9')) buf_p++;
+    *buf_p = '\0';
+
+    freq = atoi(buf);
+
+    return freq * 1000 * 1000;
+}
+
+static struct efi_cpuinfo_loongson *init_cpu_info(void *g_cpuinfo_loongson)
+{
+    struct efi_cpuinfo_loongson *c = g_cpuinfo_loongson;
+
+    c->cputype  = Loongson_3A;
+    c->processor_id = 0x14C000;
+    c->cpu_clock_freq = get_host_cpu_freq();
+    if (!c->cpu_clock_freq)
+        c->cpu_clock_freq = 400000000;
+
+    c->cpu_startup_core_id = 0;
+    c->nr_cpus = current_machine->smp.cpus;
+    c->total_node = (current_machine->smp.cpus + 3) / 4;
+
+    return c;
+}
+
+static struct system_loongson *init_system_loongson(void *g_system)
+{
+    struct system_loongson *s = g_system;
+
+    s->ccnuma_smp = 0;
+    s->sing_double_channel = 1;
+    s->nr_uarts = 1;
+    s->uarts[0].iotype = 2;
+    s->uarts[0].int_offset = 2;
+    s->uarts[0].uartclk = 25000000;
+    s->uarts[0].uart_base = 0x1fe001e0;
+
+    return s;
+}
+
+static struct irq_source_routing_table *init_irq_source(void *g_irq_source)
+{
+    struct irq_source_routing_table *irq_info = g_irq_source;
+
+    irq_info->node_id = 0;
+    irq_info->PIC_type = 0;
+    irq_info->dma_mask_bits = 64;
+    irq_info->pci_mem_start_addr = VIRT_PCI_MEM_BASE;
+    irq_info->pci_mem_end_addr   = VIRT_PCI_MEM_BASE + VIRT_PCI_MEM_SIZE - 1;
+    irq_info->pci_io_start_addr  = VIRT_PCI_IO_BASE;
+
+    return irq_info;
+}
+
+static struct interface_info *init_interface_info(void *g_interface)
+{
+    struct interface_info *interface = g_interface;
+
+    interface->vers = 0x01;
+    strcpy(interface->description, "UEFI_Version_v1.0");
+
+    return interface;
+}
+
+static struct board_devices *board_devices_info(void *g_board)
+{
+    struct board_devices *bd = g_board;
+
+    strcpy(bd->name, "Loongson-3A-VIRT-1w-V1.00-demo");
+
+    return bd;
+}
+
+static struct loongson_special_attribute *init_special_info(void *g_special)
+{
+    struct loongson_special_attribute *special = g_special;
+
+    strcpy(special->special_name, "2015-04-17");
+
+    return special;
+}
+
+static void init_loongson_params(struct loongson_params *lp)
+{
+    void *p = boot_params_p;
+
+    lp->memory_offset = (unsigned long long)init_memory_map(p)
+                        - (unsigned long long)lp;
+    p += align(sizeof(struct efi_memory_map_loongson));
+
+    lp->cpu_offset = (unsigned long long)init_cpu_info(p)
+                     - (unsigned long long)lp;
+    p += align(sizeof(struct efi_cpuinfo_loongson));
+
+    lp->system_offset = (unsigned long long)init_system_loongson(p)
+                        - (unsigned long long)lp;
+    p += align(sizeof(struct system_loongson));
+
+    lp->irq_offset = (unsigned long long)init_irq_source(p)
+                     - (unsigned long long)lp;
+    p += align(sizeof(struct irq_source_routing_table));
+
+    lp->interface_offset = (unsigned long long)init_interface_info(p)
+                           - (unsigned long long)lp;
+    p += align(sizeof(struct interface_info));
+
+    lp->boarddev_table_offset = (unsigned long long)board_devices_info(p)
+                                - (unsigned long long)lp;
+    p+= align(sizeof(struct board_devices));
+
+    lp->special_offset = (unsigned long long)init_special_info(p)
+                         - (unsigned long long)lp;
+    p+= align(sizeof(struct loongson_special_attribute));
+
+    boot_params_p = p;
+}
+
+static void init_smbios(struct smbios_tables *smbios)
+{
+    smbios->vers = 1;
+    init_loongson_params(&(smbios->lp));
+}
+
+static void init_efi(struct efi_loongson *efi)
+{
+    init_smbios(&(efi->smbios));
+}
+
+static void init_reset_system(struct efi_reset_system_t *reset)
+{
+    reset->Shutdown = 0xffffffffbfc000b0;
+    reset->ResetCold = 0xffffffffbfc00088;
+    reset->ResetWarm = 0xffffffffbfc00088;
+}
+
+static int init_boot_param(struct boot_params *bp)
+{
+    init_efi(&(bp->efi));
+    init_reset_system(&(bp->reset_system));
+
+    return 0;
+}
+
+static void fw_cfg_boot_set(void *opaque, const char *boot_device,
+                            Error **errp)
+{
+    fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
+}
+
+static void fw_conf_init(unsigned long ram_size)
+{
+    FWCfgState *fw_cfg;
+
+    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);
+    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
+
+    fw_config.ram_size = ram_size;
+    fw_config.mem_freq = 300000000;
+    fw_config.nr_cpus = current_machine->smp.cpus;
+    fw_config.cpu_clock_freq = get_host_cpu_freq();
+}
+
+static int set_prom_bootparam(ram_addr_t initrd_offset, long initrd_size)
+{
+    long params_size;
+    char memenv[32];
+    char highmemenv[32];
+    void *params_buf;
+    unsigned int *parg_env;
+    int ret = 0;
+
+    /* Allocate params_buf for command line. */
+    params_size = 0x100000;
+    params_buf = g_malloc0(params_size);
+
+    /*
+     * Layout of params_buf looks like this:
+     * argv[0], argv[1], 0, env[0], env[1], ... env[i], 0,
+     * argv[0]'s data, argv[1]'s data, env[0]'data, ..., env[i]'s data, 0
+     */
+    parg_env = (void *)params_buf;
+
+    ret = (3 + 1) * 4;
+    *parg_env++ = (BOOTPARAM_ADDR + ret);
+    ret += (1 + snprintf(params_buf + ret, 256 - ret, "g"));
+
+    /* argv1 */
+    *parg_env++ = BOOTPARAM_ADDR + ret;
+    if (initrd_size > 0)
+        ret += (1 + snprintf(params_buf + ret, 256 - ret,
+                "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
+                PHYS_TO_VIRT((uint32_t)initrd_offset),
+                initrd_size, loaderparams.kernel_cmdline));
+    else
+        ret += (1 + snprintf(params_buf+ret, 256 - ret, "%s",
+                loaderparams.kernel_cmdline));
+
+    /* argv2 */
+    *parg_env++ = BOOTPARAM_ADDR + 4*ret;
+
+    /* env */
+    sprintf(memenv, "%ld", loaderparams.ram_size > 0x10000000
+            ? 256 : (loaderparams.ram_size >> 20));
+    sprintf(highmemenv, "%ld", loaderparams.ram_size > 0x10000000
+            ? (loaderparams.ram_size >> 20) - 256 : 0);
+
+    setenv("memsize", memenv, 1);
+    setenv("highmemsize", highmemenv, 1);
+
+    ret = ((ret + 32) & ~31);
+
+    boot_params_buf = (void *)(params_buf + ret);
+    boot_params_p = boot_params_buf + align(sizeof(struct boot_params));
+
+    init_boot_param(boot_params_buf);
+
+    rom_add_blob_fixed("params", params_buf, params_size,
+                       BOOTPARAM_PHYADDR);
+    loaderparams.a0 = 2;
+    loaderparams.a1 = 0xffffffff80000000ULL + BOOTPARAM_PHYADDR;
+    loaderparams.a2 = 0xffffffff80000000ULL + BOOTPARAM_PHYADDR + ret;
+
+    return 0;
+}
+
+static int64_t load_kernel(CPUMIPSState *env)
+{
+    long kernel_size;
+    ram_addr_t initrd_offset;
+    int64_t kernel_entry, kernel_low, kernel_high, initrd_size;
+
+    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);
+    if (kernel_size < 0) {
+        error_report("could not load kernel '%s': %s",
+                     loaderparams.kernel_filename,
+                     load_elf_strerror(kernel_size));
+        exit(1);
+    }
+
+    /* load initrd */
+    initrd_size = 0;
+    initrd_offset = 0;
+    if (loaderparams.initrd_filename) {
+        initrd_size = get_image_size(loaderparams.initrd_filename);
+        if (initrd_size > 0) {
+            initrd_offset = (kernel_high + ~INITRD_PAGE_MASK) &
+                            INITRD_PAGE_MASK;
+            initrd_offset = MAX(initrd_offset, INITRD_OFFSET);
+
+            if (initrd_offset + initrd_size > ram_size) {
+                error_report("memory too small for initial ram disk '%s'",
+                             loaderparams.initrd_filename);
+                exit(1);
+            }
+
+            initrd_size = load_image_targphys(loaderparams.initrd_filename,
+                                              initrd_offset,
+                                              ram_size - initrd_offset);
+        }
+
+        if (initrd_size == (target_ulong) -1) {
+            error_report("could not load initial ram disk '%s'",
+                         loaderparams.initrd_filename);
+            exit(1);
+        }
+    }
+
+    /* Setup prom parameters. */
+    set_prom_bootparam(initrd_offset, initrd_size);
+
+    return kernel_entry;
+}
+
+static void main_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 loongson3_isa_init(qemu_irq intc)
+{
+    qemu_irq *i8259;
+    ISABus *isa_bus;
+
+    isa_bus = isa_bus_new(NULL, get_system_memory(), get_system_io(), &error_abort);
+
+    /* Interrupt controller */
+    /* The 8259 -> IP3  */
+    i8259 = i8259_init(isa_bus, intc);
+    isa_bus_irqs(isa_bus, i8259);
+    /* init other devices */
+    isa_create_simple(isa_bus, "i8042");
+    mc146818_rtc_init(isa_bus, 2000, NULL);
+}
+
+static inline void loongson3_pcie_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_create(NULL, TYPE_GPEX_HOST);
+
+    qdev_init_nofail(dev);
+    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_PCI_ECAM_SIZE);
+    memory_region_add_subregion(get_system_memory(), VIRT_PCI_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_PCI_MEM_BASE, VIRT_PCI_MEM_SIZE);
+    memory_region_add_subregion(get_system_memory(), VIRT_PCI_MEM_BASE, mmio_alias);
+
+    pio_alias = g_new0(MemoryRegion, 1);
+    memory_region_init_alias(pio_alias, OBJECT(dev), "pcie-pio",
+                             get_system_io(), 0, VIRT_PCI_IO_SIZE);
+    memory_region_add_subregion(get_system_memory(), VIRT_PCI_IO_BASE, pio_alias);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, VIRT_PCI_IO_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);
+
+    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_init(MachineState *machine)
+{
+    int i;
+    long bios_size;
+    MIPSCPU *cpu;
+    CPUMIPSState *env;
+    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);
+
+    if (ram_size < 256 * 0x100000) {
+        error_report("Loongson-3 need at least 256MB memory");
+        exit(1);
+    }
+
+    for (i = 0; i < machine->smp.cpus; i++) {
+        /* init CPUs */
+        cpu = MIPS_CPU(cpu_create(machine->cpu_type));
+
+        /* Init internal devices */
+        cpu_mips_irq_init_cpu(cpu);
+        cpu_mips_clock_init(cpu);
+        qemu_register_reset(main_cpu_reset, cpu);
+    }
+    env = &MIPS_CPU(first_cpu)->env;
+
+    /* Allocate RAM/BIOS, 0x00000000~0x10000000 is alias of 0x80000000~0x90000000 */
+    memory_region_init_rom(bios, NULL, "loongson3.bios", BIOS_SIZE, &error_fatal);
+    memory_region_init_alias(ram, NULL, "loongson3.lowram", machine->ram, 0, 256 * 0x100000);
+    memory_region_init_io(iomem, NULL, &loongson3_pm_ops, NULL, "loongson3_pm", PM_MMIO_SIZE);
+
+    memory_region_add_subregion(address_space_mem, 0x00000000LL, ram);
+    memory_region_add_subregion(address_space_mem, 0x1fc00000LL, bios);
+    memory_region_add_subregion(address_space_mem, 0x80000000LL, machine->ram);
+    memory_region_add_subregion(address_space_mem, PM_MMIO_ADDR, iomem);
+
+    /*
+     * We do not support flash operation, just loading pmon.bin as raw BIOS.
+     * Please use -L to set the BIOS path and -bios to set bios name.
+     */
+
+    if (kernel_filename) {
+        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);
+        rom_add_blob_fixed("bios", bios_boot_code, sizeof(bios_boot_code), 0x1fc00000LL);
+    } else {
+        if (bios_name == NULL) {
+                bios_name = LOONGSON3_BIOSNAME;
+        }
+        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+        if (filename) {
+            bios_size = load_image_targphys(filename, 0x1fc00000LL,
+                                            BIOS_SIZE);
+            g_free(filename);
+        } else {
+            bios_size = -1;
+        }
+
+        if ((bios_size < 0 || bios_size > BIOS_SIZE) &&
+            !kernel_filename && !qtest_enabled()) {
+            error_report("Could not load MIPS bios '%s'", bios_name);
+            exit(1);
+        }
+
+        fw_conf_init(ram_size);
+        rom_add_blob_fixed("fw_conf", (void*)&fw_config, sizeof(fw_config), FW_CONF_ADDR);
+    }
+
+    msi_nonbroken = true;
+    loongson3_isa_init(env->irq[3]);
+    loongson3_pcie_init(machine, isa_pic);
+
+    if (serial_hd(0))
+        serial_mm_init(address_space_mem, 0x1fe001e0, 0, env->irq[2], 115200, serial_hd(0), DEVICE_NATIVE_ENDIAN);
+}
+
+static void mips_loongson3_machine_init(MachineClass *mc)
+{
+    mc->desc = "Generic Loongson-3 Platform";
+    mc->init = mips_loongson3_init;
+    mc->block_default_type = IF_IDE;
+    mc->max_cpus = LOONGSON_MAX_VCPUS;
+    mc->default_cpu_type = MIPS_CPU_TYPE_NAME("Loongson-3A");
+    mc->default_ram_id = "loongson3.highram";
+    mc->default_ram_size = 784 * MiB;
+    mc->kvm_type = mips_kvm_type;
+    mc->minimum_page_bits = 14;
+}
+
+DEFINE_MACHINE("loongson3", mips_loongson3_machine_init)
-- 
2.7.0



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* [PATCH for-5.1 7/7] MAINTAINERS: Add myself as Loongson-3 maintainer
  2020-04-27  9:33 [PATCH for-5.1 1/7] configure: Add KVM target support for MIPS64 Huacai Chen
                   ` (4 preceding siblings ...)
  2020-04-27  9:33 ` [PATCH for-5.1 6/7] hw/mips: Add Loongson-3 machine support (with KVM) Huacai Chen
@ 2020-04-27  9:33 ` Huacai Chen
  2020-04-28  6:18   ` Philippe Mathieu-Daudé
  2020-04-28 19:15 ` [PATCH for-5.1 1/7] configure: Add KVM target support for MIPS64 Aleksandar Markovic
  6 siblings, 1 reply; 30+ messages in thread
From: Huacai Chen @ 2020-04-27  9:33 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, Aleksandar Markovic
  Cc: Huacai Chen, Huacai Chen, qemu-devel, Aurelien Jarno

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 MAINTAINERS | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index aa9a057..efe840b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1080,6 +1080,12 @@ F: hw/isa/vt82c686.c
 F: hw/pci-host/bonito.c
 F: include/hw/isa/vt82c686.h
 
+Loongson-3
+M: Huacai Chen <chenhc@lemote.com>
+S: Maintained
+F: hw/mips/mips_loongson3.c
+F: hw/pci-host/ls7a.c
+
 Boston
 M: Paul Burton <pburton@wavecomp.com>
 R: Aleksandar Rikalo <aleksandar.rikalo@rt-rk.com>
-- 
2.7.0



^ permalink raw reply related	[flat|nested] 30+ messages in thread

* Re: [PATCH for-5.1 3/7] hw/mips: Add CPU IRQ3 delivery for KVM
  2020-04-27  9:33 ` [PATCH for-5.1 3/7] hw/mips: Add CPU IRQ3 delivery for KVM Huacai Chen
@ 2020-04-27  9:57   ` Philippe Mathieu-Daudé
  2020-04-28  8:28     ` chen huacai
  0 siblings, 1 reply; 30+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-04-27  9:57 UTC (permalink / raw)
  To: Huacai Chen, Aleksandar Markovic
  Cc: Huacai Chen, Huacai Chen, qemu-devel, Aurelien Jarno

On 4/27/20 11:33 AM, Huacai Chen wrote:
> Currently, KVM/MIPS only deliver I/O interrupt via IP2, this patch add
> IP2 delivery as well, because Loongson-3 based machine use both IRQ2
> (CPU's IP2) and IRQ3 (CPU's IP3).
> 
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
>  hw/mips/mips_int.c | 6 ++----
>  1 file changed, 2 insertions(+), 4 deletions(-)
> 
> diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c
> index 796730b..5526219 100644
> --- a/hw/mips/mips_int.c
> +++ b/hw/mips/mips_int.c
> @@ -48,16 +48,14 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level)
>      if (level) {
>          env->CP0_Cause |= 1 << (irq + CP0Ca_IP);
>  
> -        if (kvm_enabled() && irq == 2) {
> +        if (kvm_enabled() && (irq == 2 || irq == 3))

Shouldn't we check env->CP0_Config6 (or Config7) has the required
feature first?

>              kvm_mips_set_interrupt(cpu, irq, level);
> -        }
>  
>      } else {
>          env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
>  
> -        if (kvm_enabled() && irq == 2) {
> +        if (kvm_enabled() && (irq == 2 || irq == 3))
>              kvm_mips_set_interrupt(cpu, irq, level);
> -        }
>      }
>  
>      if (env->CP0_Cause & CP0Ca_IP_mask) {
> 


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH for-5.1 7/7] MAINTAINERS: Add myself as Loongson-3 maintainer
  2020-04-27  9:33 ` [PATCH for-5.1 7/7] MAINTAINERS: Add myself as Loongson-3 maintainer Huacai Chen
@ 2020-04-28  6:18   ` Philippe Mathieu-Daudé
  2020-04-28  8:31     ` chen huacai
  0 siblings, 1 reply; 30+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-04-28  6:18 UTC (permalink / raw)
  To: Huacai Chen, Aleksandar Markovic
  Cc: Huacai Chen, Huacai Chen, qemu-devel, Aurelien Jarno

Hi Huacai,

On 4/27/20 11:33 AM, Huacai Chen wrote:
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
>  MAINTAINERS | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index aa9a057..efe840b 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -1080,6 +1080,12 @@ F: hw/isa/vt82c686.c
>  F: hw/pci-host/bonito.c
>  F: include/hw/isa/vt82c686.h
>  
> +Loongson-3
> +M: Huacai Chen <chenhc@lemote.com>
> +S: Maintained
> +F: hw/mips/mips_loongson3.c
> +F: hw/pci-host/ls7a.c

I still haven't received the series cover, so I'm not sure if you
intended to include the LS7A bridge chip here, but if so it seems you
forgot to include it.

> +
>  Boston
>  M: Paul Burton <pburton@wavecomp.com>
>  R: Aleksandar Rikalo <aleksandar.rikalo@rt-rk.com>
> 


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH for-5.1 4/7] target/mips: Add Loongson-3 CPU definition
  2020-04-27  9:33 ` [PATCH for-5.1 4/7] target/mips: Add Loongson-3 CPU definition Huacai Chen
@ 2020-04-28  6:34   ` Philippe Mathieu-Daudé
  2020-04-28  8:34     ` chen huacai
  0 siblings, 1 reply; 30+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-04-28  6:34 UTC (permalink / raw)
  To: Huacai Chen, Aleksandar Markovic
  Cc: Huacai Chen, Huacai Chen, qemu-devel, Aurelien Jarno

Hi Huacai,

On 4/27/20 11:33 AM, Huacai Chen wrote:
> Loongson-3 CPU family include Loongson-3A R1/R2/R3/R4 and Loongson-3B
> R1/R2. Loongson-3A R4 is the newest and its ISA is almost the superset
> of all others. To reduce complexity, we just define a "Loongson-3A" CPU
> which is corresponding to Loongson-3A R4. Loongson-3A has CONFIG6 and
> CONFIG7, so add their bit-fields as well.

Is there a public datasheet for R4? (If possible in English).

> 
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
>  target/mips/cpu.h                | 28 ++++++++++++++++++++++
>  target/mips/internal.h           |  2 ++
>  target/mips/mips-defs.h          |  7 ++++--
>  target/mips/translate.c          |  2 ++
>  target/mips/translate_init.inc.c | 51 ++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 88 insertions(+), 2 deletions(-)
> 
> diff --git a/target/mips/cpu.h b/target/mips/cpu.h
> index 94d01ea..0b3c987 100644
> --- a/target/mips/cpu.h
> +++ b/target/mips/cpu.h
> @@ -940,7 +940,35 @@ struct CPUMIPSState {
>  #define CP0C5_UFR          2
>  #define CP0C5_NFExists     0
>      int32_t CP0_Config6;
> +    int32_t CP0_Config6_rw_bitmask;
> +#define CP0C6_BPPASS          31
> +#define CP0C6_KPOS            24
> +#define CP0C6_KE              23
> +#define CP0C6_VTLBONLY        22
> +#define CP0C6_LASX            21
> +#define CP0C6_SSEN            20
> +#define CP0C6_DISDRTIME       19
> +#define CP0C6_PIXNUEN         18
> +#define CP0C6_SCRAND          17
> +#define CP0C6_LLEXCEN         16
> +#define CP0C6_DISVC           15
> +#define CP0C6_VCLRU           14
> +#define CP0C6_DCLRU           13
> +#define CP0C6_PIXUEN          12
> +#define CP0C6_DISBLKLYEN      11
> +#define CP0C6_UMEMUALEN       10
> +#define CP0C6_SFBEN           8
> +#define CP0C6_FLTINT          7
> +#define CP0C6_VLTINT          6
> +#define CP0C6_DISBTB          5
> +#define CP0C6_STPREFCTL       2
> +#define CP0C6_INSTPREF        1
> +#define CP0C6_DATAPREF        0
>      int32_t CP0_Config7;
> +    int64_t CP0_Config7_rw_bitmask;
> +#define CP0C7_NAPCGEN       2
> +#define CP0C7_UNIMUEN       1
> +#define CP0C7_VFPUCGEN      0
>      uint64_t CP0_LLAddr;
>      uint64_t CP0_MAAR[MIPS_MAAR_MAX];
>      int32_t CP0_MAARI;
> diff --git a/target/mips/internal.h b/target/mips/internal.h
> index 1bf274b..7853cb1 100644
> --- a/target/mips/internal.h
> +++ b/target/mips/internal.h
> @@ -36,7 +36,9 @@ struct mips_def_t {
>      int32_t CP0_Config5;
>      int32_t CP0_Config5_rw_bitmask;
>      int32_t CP0_Config6;
> +    int32_t CP0_Config6_rw_bitmask;
>      int32_t CP0_Config7;
> +    int32_t CP0_Config7_rw_bitmask;
>      target_ulong CP0_LLAddr_rw_bitmask;
>      int CP0_LLAddr_shift;
>      int32_t SYNCI_Step;
> diff --git a/target/mips/mips-defs.h b/target/mips/mips-defs.h
> index a831bb4..c2c96db 100644
> --- a/target/mips/mips-defs.h
> +++ b/target/mips/mips-defs.h
> @@ -51,8 +51,9 @@
>   */
>  #define INSN_LOONGSON2E   0x0001000000000000ULL
>  #define INSN_LOONGSON2F   0x0002000000000000ULL
> -#define INSN_VR54XX       0x0004000000000000ULL
> -#define INSN_R5900        0x0008000000000000ULL
> +#define INSN_LOONGSON3A   0x0004000000000000ULL
> +#define INSN_VR54XX       0x0008000000000000ULL
> +#define INSN_R5900        0x0010000000000000ULL
>  /*
>   *   bits 56-63: vendor-specific ASEs
>   */
> @@ -94,6 +95,8 @@
>  /* Wave Computing: "nanoMIPS" */
>  #define CPU_NANOMIPS32  (CPU_MIPS32R6 | ISA_NANOMIPS32)
>  
> +#define CPU_LOONGSON3A  (CPU_MIPS64R2 | INSN_LOONGSON3A)
> +
>  /*
>   * Strictly follow the architecture standard:
>   * - Disallow "special" instruction handling for PMON/SPIM.
> diff --git a/target/mips/translate.c b/target/mips/translate.c
> index 25b595a..2caf4cb 100644
> --- a/target/mips/translate.c
> +++ b/target/mips/translate.c
> @@ -31206,7 +31206,9 @@ void cpu_state_reset(CPUMIPSState *env)
>      env->CP0_Config5 = env->cpu_model->CP0_Config5;
>      env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
>      env->CP0_Config6 = env->cpu_model->CP0_Config6;
> +    env->CP0_Config6_rw_bitmask = env->cpu_model->CP0_Config6_rw_bitmask;
>      env->CP0_Config7 = env->cpu_model->CP0_Config7;
> +    env->CP0_Config7_rw_bitmask = env->cpu_model->CP0_Config7_rw_bitmask;
>      env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
>                                   << env->cpu_model->CP0_LLAddr_shift;
>      env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
> diff --git a/target/mips/translate_init.inc.c b/target/mips/translate_init.inc.c
> index 6d145a9..a32412d 100644
> --- a/target/mips/translate_init.inc.c
> +++ b/target/mips/translate_init.inc.c
> @@ -802,6 +802,57 @@ const mips_def_t mips_defs[] =
>          .mmu_type = MMU_TYPE_R4000,
>      },
>      {
> +        .name = "Loongson-3A",
> +        .CP0_PRid = 0x14C000,
> +        /* 64KB I-cache and d-cache. 4 way with 32 bit cache line size.  */
> +        .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
> +                       (MMU_TYPE_R4000 << CP0C0_MT),
> +        .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) |
> +                       (2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
> +                       (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
> +                       (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
> +        .CP0_Config2 = MIPS_CONFIG2,
> +        .CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_MSAP) |
> +                       (1 << CP0C3_BP) | (1 << CP0C3_BI) | (1 << CP0C3_ULRI) |
> +                       (1 << CP0C3_RXI) | (1 << CP0C3_LPA) | (1 << CP0C3_VInt),
> +        .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) | (2 << CP0C4_IE) |
> +                       (1 << CP0C4_AE) | (0x1c << CP0C4_KScrExist),
> +        .CP0_Config4_rw_bitmask = 0,
> +        .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_NFExists) | (1 << 18),
> +        .CP0_Config5_rw_bitmask = (1 << CP0C5_K) | (1 << CP0C5_CV) |
> +                                  (1 << CP0C5_MSAEn) | (1 << CP0C5_UFE) |
> +                                  (1 << CP0C5_FRE) | (1 << CP0C5_SBRI),
> +        .CP0_Config6 = (1 << CP0C6_VCLRU) | (1 << CP0C6_DCLRU) | (1 << CP0C6_SFBEN) |
> +                       (1 << CP0C6_FLTINT) | (1 << CP0C6_INSTPREF) | (1 << CP0C6_DATAPREF),
> +        .CP0_Config6_rw_bitmask = (1 << CP0C6_BPPASS) | (0x3f << CP0C6_KPOS) |
> +                                  (1 << CP0C6_KE) | (1 << CP0C6_VTLBONLY) | (1 << CP0C6_LASX) |
> +                                  (1 << CP0C6_SSEN) | (1 << CP0C6_DISDRTIME) |
> +                                  (1 << CP0C6_PIXNUEN) | (1 << CP0C6_SCRAND) |
> +                                  (1 << CP0C6_LLEXCEN) | (1 << CP0C6_DISVC) |
> +                                  (1 << CP0C6_VCLRU) | (1 << CP0C6_DCLRU) |
> +                                  (1 << CP0C6_PIXUEN) | (1 << CP0C6_DISBLKLYEN) |
> +                                  (1 << CP0C6_UMEMUALEN) | (1 << CP0C6_SFBEN) |
> +                                  (1 << CP0C6_FLTINT) | (1 << CP0C6_VLTINT) |
> +                                  (1 << CP0C6_DISBTB) | (3 << CP0C6_STPREFCTL) |
> +                                  (1 << CP0C6_INSTPREF) | (1 << CP0C6_DATAPREF),
> +        .CP0_Config7 = 0,
> +        .CP0_Config7_rw_bitmask = (1 << CP0C7_NAPCGEN) | (1 << CP0C7_UNIMUEN) | \
> +                                  (1 << CP0C7_VFPUCGEN),
> +        .CP0_LLAddr_rw_bitmask = 1,
> +        .SYNCI_Step = 16,
> +        .CCRes = 2,
> +        .CP0_Status_rw_bitmask = 0x7DDBFFFF,
> +        .CP0_PageGrain_rw_bitmask = (1U << CP0PG_RIE) | (1 << CP0PG_XIE) |
> +                    (1 << CP0PG_ELPA) | (1 << CP0PG_IEC),
> +        .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x1 << FCR0_REV) | (0x1 << FCR0_F64),
> +        .CP1_fcr31 = 0,
> +        .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
> +        .SEGBITS = 48,
> +        .PABITS = 48,
> +        .insn_flags = CPU_LOONGSON3A,
> +        .mmu_type = MMU_TYPE_R4000,
> +    },
> +    {
>          /* A generic CPU providing MIPS64 DSP R2 ASE features.
>             FIXME: Eventually this should be replaced by a real CPU model. */
>          .name = "mips64dspr2",
> 


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH for-5.1 3/7] hw/mips: Add CPU IRQ3 delivery for KVM
  2020-04-27  9:57   ` Philippe Mathieu-Daudé
@ 2020-04-28  8:28     ` chen huacai
  2020-04-28 18:58       ` Aleksandar Markovic
  0 siblings, 1 reply; 30+ messages in thread
From: chen huacai @ 2020-04-28  8:28 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Huacai Chen, Huacai Chen, Aleksandar Markovic, qemu-level,
	Aurelien Jarno

Hi, Philippe,

On Mon, Apr 27, 2020 at 5:57 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>
> On 4/27/20 11:33 AM, Huacai Chen wrote:
> > Currently, KVM/MIPS only deliver I/O interrupt via IP2, this patch add
> > IP2 delivery as well, because Loongson-3 based machine use both IRQ2
> > (CPU's IP2) and IRQ3 (CPU's IP3).
> >
> > Signed-off-by: Huacai Chen <chenhc@lemote.com>
> > Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> > ---
> >  hw/mips/mips_int.c | 6 ++----
> >  1 file changed, 2 insertions(+), 4 deletions(-)
> >
> > diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c
> > index 796730b..5526219 100644
> > --- a/hw/mips/mips_int.c
> > +++ b/hw/mips/mips_int.c
> > @@ -48,16 +48,14 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level)
> >      if (level) {
> >          env->CP0_Cause |= 1 << (irq + CP0Ca_IP);
> >
> > -        if (kvm_enabled() && irq == 2) {
> > +        if (kvm_enabled() && (irq == 2 || irq == 3))
>
> Shouldn't we check env->CP0_Config6 (or Config7) has the required
> feature first?
I'm sorry that I can't understand IRQ delivery has something to do
with Config6/Config7, to identify Loongson-3?

>
> >              kvm_mips_set_interrupt(cpu, irq, level);
> > -        }
> >
> >      } else {
> >          env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
> >
> > -        if (kvm_enabled() && irq == 2) {
> > +        if (kvm_enabled() && (irq == 2 || irq == 3))
> >              kvm_mips_set_interrupt(cpu, irq, level);
> > -        }
> >      }
> >
> >      if (env->CP0_Cause & CP0Ca_IP_mask) {
> >



-- 
Huacai Chen


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH for-5.1 7/7] MAINTAINERS: Add myself as Loongson-3 maintainer
  2020-04-28  6:18   ` Philippe Mathieu-Daudé
@ 2020-04-28  8:31     ` chen huacai
  0 siblings, 0 replies; 30+ messages in thread
From: chen huacai @ 2020-04-28  8:31 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Huacai Chen, Huacai Chen, Aleksandar Markovic, qemu-level,
	Aurelien Jarno

Hi, Philippe,

On Tue, Apr 28, 2020 at 2:18 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>
> Hi Huacai,
>
> On 4/27/20 11:33 AM, Huacai Chen wrote:
> > Signed-off-by: Huacai Chen <chenhc@lemote.com>
> > Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> > ---
> >  MAINTAINERS | 6 ++++++
> >  1 file changed, 6 insertions(+)
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index aa9a057..efe840b 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -1080,6 +1080,12 @@ F: hw/isa/vt82c686.c
> >  F: hw/pci-host/bonito.c
> >  F: include/hw/isa/vt82c686.h
> >
> > +Loongson-3
> > +M: Huacai Chen <chenhc@lemote.com>
> > +S: Maintained
> > +F: hw/mips/mips_loongson3.c
> > +F: hw/pci-host/ls7a.c
>
> I still haven't received the series cover, so I'm not sure if you
> intended to include the LS7A bridge chip here, but if so it seems you
> forgot to include it.
I'm sorry that I've rework the qemu patchset together with Jiaxun
Yang. Now we have dropped LS7A bridge and use GPEX instead. This patch
should also be updated but I forgot.

>
> > +
> >  Boston
> >  M: Paul Burton <pburton@wavecomp.com>
> >  R: Aleksandar Rikalo <aleksandar.rikalo@rt-rk.com>
> >



-- 
Huacai Chen


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH for-5.1 4/7] target/mips: Add Loongson-3 CPU definition
  2020-04-28  6:34   ` Philippe Mathieu-Daudé
@ 2020-04-28  8:34     ` chen huacai
  2020-04-28 18:37       ` Aleksandar Markovic
  0 siblings, 1 reply; 30+ messages in thread
From: chen huacai @ 2020-04-28  8:34 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Huacai Chen, Huacai Chen, Aleksandar Markovic, qemu-level,
	Aurelien Jarno

Hi, Philippe,

On Tue, Apr 28, 2020 at 2:34 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>
> Hi Huacai,
>
> On 4/27/20 11:33 AM, Huacai Chen wrote:
> > Loongson-3 CPU family include Loongson-3A R1/R2/R3/R4 and Loongson-3B
> > R1/R2. Loongson-3A R4 is the newest and its ISA is almost the superset
> > of all others. To reduce complexity, we just define a "Loongson-3A" CPU
> > which is corresponding to Loongson-3A R4. Loongson-3A has CONFIG6 and
> > CONFIG7, so add their bit-fields as well.
>
> Is there a public datasheet for R4? (If possible in English).
I'm sorry that we only have Chinese datasheet in www.loongson.cn.

>
> >
> > Signed-off-by: Huacai Chen <chenhc@lemote.com>
> > Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> > ---
> >  target/mips/cpu.h                | 28 ++++++++++++++++++++++
> >  target/mips/internal.h           |  2 ++
> >  target/mips/mips-defs.h          |  7 ++++--
> >  target/mips/translate.c          |  2 ++
> >  target/mips/translate_init.inc.c | 51 ++++++++++++++++++++++++++++++++++++++++
> >  5 files changed, 88 insertions(+), 2 deletions(-)
> >
> > diff --git a/target/mips/cpu.h b/target/mips/cpu.h
> > index 94d01ea..0b3c987 100644
> > --- a/target/mips/cpu.h
> > +++ b/target/mips/cpu.h
> > @@ -940,7 +940,35 @@ struct CPUMIPSState {
> >  #define CP0C5_UFR          2
> >  #define CP0C5_NFExists     0
> >      int32_t CP0_Config6;
> > +    int32_t CP0_Config6_rw_bitmask;
> > +#define CP0C6_BPPASS          31
> > +#define CP0C6_KPOS            24
> > +#define CP0C6_KE              23
> > +#define CP0C6_VTLBONLY        22
> > +#define CP0C6_LASX            21
> > +#define CP0C6_SSEN            20
> > +#define CP0C6_DISDRTIME       19
> > +#define CP0C6_PIXNUEN         18
> > +#define CP0C6_SCRAND          17
> > +#define CP0C6_LLEXCEN         16
> > +#define CP0C6_DISVC           15
> > +#define CP0C6_VCLRU           14
> > +#define CP0C6_DCLRU           13
> > +#define CP0C6_PIXUEN          12
> > +#define CP0C6_DISBLKLYEN      11
> > +#define CP0C6_UMEMUALEN       10
> > +#define CP0C6_SFBEN           8
> > +#define CP0C6_FLTINT          7
> > +#define CP0C6_VLTINT          6
> > +#define CP0C6_DISBTB          5
> > +#define CP0C6_STPREFCTL       2
> > +#define CP0C6_INSTPREF        1
> > +#define CP0C6_DATAPREF        0
> >      int32_t CP0_Config7;
> > +    int64_t CP0_Config7_rw_bitmask;
> > +#define CP0C7_NAPCGEN       2
> > +#define CP0C7_UNIMUEN       1
> > +#define CP0C7_VFPUCGEN      0
> >      uint64_t CP0_LLAddr;
> >      uint64_t CP0_MAAR[MIPS_MAAR_MAX];
> >      int32_t CP0_MAARI;
> > diff --git a/target/mips/internal.h b/target/mips/internal.h
> > index 1bf274b..7853cb1 100644
> > --- a/target/mips/internal.h
> > +++ b/target/mips/internal.h
> > @@ -36,7 +36,9 @@ struct mips_def_t {
> >      int32_t CP0_Config5;
> >      int32_t CP0_Config5_rw_bitmask;
> >      int32_t CP0_Config6;
> > +    int32_t CP0_Config6_rw_bitmask;
> >      int32_t CP0_Config7;
> > +    int32_t CP0_Config7_rw_bitmask;
> >      target_ulong CP0_LLAddr_rw_bitmask;
> >      int CP0_LLAddr_shift;
> >      int32_t SYNCI_Step;
> > diff --git a/target/mips/mips-defs.h b/target/mips/mips-defs.h
> > index a831bb4..c2c96db 100644
> > --- a/target/mips/mips-defs.h
> > +++ b/target/mips/mips-defs.h
> > @@ -51,8 +51,9 @@
> >   */
> >  #define INSN_LOONGSON2E   0x0001000000000000ULL
> >  #define INSN_LOONGSON2F   0x0002000000000000ULL
> > -#define INSN_VR54XX       0x0004000000000000ULL
> > -#define INSN_R5900        0x0008000000000000ULL
> > +#define INSN_LOONGSON3A   0x0004000000000000ULL
> > +#define INSN_VR54XX       0x0008000000000000ULL
> > +#define INSN_R5900        0x0010000000000000ULL
> >  /*
> >   *   bits 56-63: vendor-specific ASEs
> >   */
> > @@ -94,6 +95,8 @@
> >  /* Wave Computing: "nanoMIPS" */
> >  #define CPU_NANOMIPS32  (CPU_MIPS32R6 | ISA_NANOMIPS32)
> >
> > +#define CPU_LOONGSON3A  (CPU_MIPS64R2 | INSN_LOONGSON3A)
> > +
> >  /*
> >   * Strictly follow the architecture standard:
> >   * - Disallow "special" instruction handling for PMON/SPIM.
> > diff --git a/target/mips/translate.c b/target/mips/translate.c
> > index 25b595a..2caf4cb 100644
> > --- a/target/mips/translate.c
> > +++ b/target/mips/translate.c
> > @@ -31206,7 +31206,9 @@ void cpu_state_reset(CPUMIPSState *env)
> >      env->CP0_Config5 = env->cpu_model->CP0_Config5;
> >      env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
> >      env->CP0_Config6 = env->cpu_model->CP0_Config6;
> > +    env->CP0_Config6_rw_bitmask = env->cpu_model->CP0_Config6_rw_bitmask;
> >      env->CP0_Config7 = env->cpu_model->CP0_Config7;
> > +    env->CP0_Config7_rw_bitmask = env->cpu_model->CP0_Config7_rw_bitmask;
> >      env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
> >                                   << env->cpu_model->CP0_LLAddr_shift;
> >      env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
> > diff --git a/target/mips/translate_init.inc.c b/target/mips/translate_init.inc.c
> > index 6d145a9..a32412d 100644
> > --- a/target/mips/translate_init.inc.c
> > +++ b/target/mips/translate_init.inc.c
> > @@ -802,6 +802,57 @@ const mips_def_t mips_defs[] =
> >          .mmu_type = MMU_TYPE_R4000,
> >      },
> >      {
> > +        .name = "Loongson-3A",
> > +        .CP0_PRid = 0x14C000,
> > +        /* 64KB I-cache and d-cache. 4 way with 32 bit cache line size.  */
> > +        .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
> > +                       (MMU_TYPE_R4000 << CP0C0_MT),
> > +        .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) |
> > +                       (2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
> > +                       (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
> > +                       (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
> > +        .CP0_Config2 = MIPS_CONFIG2,
> > +        .CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_MSAP) |
> > +                       (1 << CP0C3_BP) | (1 << CP0C3_BI) | (1 << CP0C3_ULRI) |
> > +                       (1 << CP0C3_RXI) | (1 << CP0C3_LPA) | (1 << CP0C3_VInt),
> > +        .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) | (2 << CP0C4_IE) |
> > +                       (1 << CP0C4_AE) | (0x1c << CP0C4_KScrExist),
> > +        .CP0_Config4_rw_bitmask = 0,
> > +        .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_NFExists) | (1 << 18),
> > +        .CP0_Config5_rw_bitmask = (1 << CP0C5_K) | (1 << CP0C5_CV) |
> > +                                  (1 << CP0C5_MSAEn) | (1 << CP0C5_UFE) |
> > +                                  (1 << CP0C5_FRE) | (1 << CP0C5_SBRI),
> > +        .CP0_Config6 = (1 << CP0C6_VCLRU) | (1 << CP0C6_DCLRU) | (1 << CP0C6_SFBEN) |
> > +                       (1 << CP0C6_FLTINT) | (1 << CP0C6_INSTPREF) | (1 << CP0C6_DATAPREF),
> > +        .CP0_Config6_rw_bitmask = (1 << CP0C6_BPPASS) | (0x3f << CP0C6_KPOS) |
> > +                                  (1 << CP0C6_KE) | (1 << CP0C6_VTLBONLY) | (1 << CP0C6_LASX) |
> > +                                  (1 << CP0C6_SSEN) | (1 << CP0C6_DISDRTIME) |
> > +                                  (1 << CP0C6_PIXNUEN) | (1 << CP0C6_SCRAND) |
> > +                                  (1 << CP0C6_LLEXCEN) | (1 << CP0C6_DISVC) |
> > +                                  (1 << CP0C6_VCLRU) | (1 << CP0C6_DCLRU) |
> > +                                  (1 << CP0C6_PIXUEN) | (1 << CP0C6_DISBLKLYEN) |
> > +                                  (1 << CP0C6_UMEMUALEN) | (1 << CP0C6_SFBEN) |
> > +                                  (1 << CP0C6_FLTINT) | (1 << CP0C6_VLTINT) |
> > +                                  (1 << CP0C6_DISBTB) | (3 << CP0C6_STPREFCTL) |
> > +                                  (1 << CP0C6_INSTPREF) | (1 << CP0C6_DATAPREF),
> > +        .CP0_Config7 = 0,
> > +        .CP0_Config7_rw_bitmask = (1 << CP0C7_NAPCGEN) | (1 << CP0C7_UNIMUEN) | \
> > +                                  (1 << CP0C7_VFPUCGEN),
> > +        .CP0_LLAddr_rw_bitmask = 1,
> > +        .SYNCI_Step = 16,
> > +        .CCRes = 2,
> > +        .CP0_Status_rw_bitmask = 0x7DDBFFFF,
> > +        .CP0_PageGrain_rw_bitmask = (1U << CP0PG_RIE) | (1 << CP0PG_XIE) |
> > +                    (1 << CP0PG_ELPA) | (1 << CP0PG_IEC),
> > +        .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x1 << FCR0_REV) | (0x1 << FCR0_F64),
> > +        .CP1_fcr31 = 0,
> > +        .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
> > +        .SEGBITS = 48,
> > +        .PABITS = 48,
> > +        .insn_flags = CPU_LOONGSON3A,
> > +        .mmu_type = MMU_TYPE_R4000,
> > +    },
> > +    {
> >          /* A generic CPU providing MIPS64 DSP R2 ASE features.
> >             FIXME: Eventually this should be replaced by a real CPU model. */
> >          .name = "mips64dspr2",
> >



-- 
Huacai Chen


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH for-5.1 4/7] target/mips: Add Loongson-3 CPU definition
  2020-04-28  8:34     ` chen huacai
@ 2020-04-28 18:37       ` Aleksandar Markovic
  2020-04-29  3:51         ` Huacai Chen
  0 siblings, 1 reply; 30+ messages in thread
From: Aleksandar Markovic @ 2020-04-28 18:37 UTC (permalink / raw)
  To: chen huacai
  Cc: Huacai Chen, Huacai Chen, Philippe Mathieu-Daudé,
	Aurelien Jarno, qemu-level

Huacai,

Can you please do machine translation of the document?

It can be done via translate.google.com (it accepts pdf files, but
does not have download feature, and workaround is to "print to pdf"...

Thanks in advance!
Aleksandar

уто, 28. апр 2020. у 10:26 chen huacai <zltjiangshi@gmail.com> је написао/ла:
>
> Hi, Philippe,
>
> On Tue, Apr 28, 2020 at 2:34 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
> >
> > Hi Huacai,
> >
> > On 4/27/20 11:33 AM, Huacai Chen wrote:
> > > Loongson-3 CPU family include Loongson-3A R1/R2/R3/R4 and Loongson-3B
> > > R1/R2. Loongson-3A R4 is the newest and its ISA is almost the superset
> > > of all others. To reduce complexity, we just define a "Loongson-3A" CPU
> > > which is corresponding to Loongson-3A R4. Loongson-3A has CONFIG6 and
> > > CONFIG7, so add their bit-fields as well.
> >
> > Is there a public datasheet for R4? (If possible in English).
> I'm sorry that we only have Chinese datasheet in www.loongson.cn.
>
> >
> > >
> > > Signed-off-by: Huacai Chen <chenhc@lemote.com>
> > > Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> > > ---
> > >  target/mips/cpu.h                | 28 ++++++++++++++++++++++
> > >  target/mips/internal.h           |  2 ++
> > >  target/mips/mips-defs.h          |  7 ++++--
> > >  target/mips/translate.c          |  2 ++
> > >  target/mips/translate_init.inc.c | 51 ++++++++++++++++++++++++++++++++++++++++
> > >  5 files changed, 88 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/target/mips/cpu.h b/target/mips/cpu.h
> > > index 94d01ea..0b3c987 100644
> > > --- a/target/mips/cpu.h
> > > +++ b/target/mips/cpu.h
> > > @@ -940,7 +940,35 @@ struct CPUMIPSState {
> > >  #define CP0C5_UFR          2
> > >  #define CP0C5_NFExists     0
> > >      int32_t CP0_Config6;
> > > +    int32_t CP0_Config6_rw_bitmask;
> > > +#define CP0C6_BPPASS          31
> > > +#define CP0C6_KPOS            24
> > > +#define CP0C6_KE              23
> > > +#define CP0C6_VTLBONLY        22
> > > +#define CP0C6_LASX            21
> > > +#define CP0C6_SSEN            20
> > > +#define CP0C6_DISDRTIME       19
> > > +#define CP0C6_PIXNUEN         18
> > > +#define CP0C6_SCRAND          17
> > > +#define CP0C6_LLEXCEN         16
> > > +#define CP0C6_DISVC           15
> > > +#define CP0C6_VCLRU           14
> > > +#define CP0C6_DCLRU           13
> > > +#define CP0C6_PIXUEN          12
> > > +#define CP0C6_DISBLKLYEN      11
> > > +#define CP0C6_UMEMUALEN       10
> > > +#define CP0C6_SFBEN           8
> > > +#define CP0C6_FLTINT          7
> > > +#define CP0C6_VLTINT          6
> > > +#define CP0C6_DISBTB          5
> > > +#define CP0C6_STPREFCTL       2
> > > +#define CP0C6_INSTPREF        1
> > > +#define CP0C6_DATAPREF        0
> > >      int32_t CP0_Config7;
> > > +    int64_t CP0_Config7_rw_bitmask;
> > > +#define CP0C7_NAPCGEN       2
> > > +#define CP0C7_UNIMUEN       1
> > > +#define CP0C7_VFPUCGEN      0
> > >      uint64_t CP0_LLAddr;
> > >      uint64_t CP0_MAAR[MIPS_MAAR_MAX];
> > >      int32_t CP0_MAARI;
> > > diff --git a/target/mips/internal.h b/target/mips/internal.h
> > > index 1bf274b..7853cb1 100644
> > > --- a/target/mips/internal.h
> > > +++ b/target/mips/internal.h
> > > @@ -36,7 +36,9 @@ struct mips_def_t {
> > >      int32_t CP0_Config5;
> > >      int32_t CP0_Config5_rw_bitmask;
> > >      int32_t CP0_Config6;
> > > +    int32_t CP0_Config6_rw_bitmask;
> > >      int32_t CP0_Config7;
> > > +    int32_t CP0_Config7_rw_bitmask;
> > >      target_ulong CP0_LLAddr_rw_bitmask;
> > >      int CP0_LLAddr_shift;
> > >      int32_t SYNCI_Step;
> > > diff --git a/target/mips/mips-defs.h b/target/mips/mips-defs.h
> > > index a831bb4..c2c96db 100644
> > > --- a/target/mips/mips-defs.h
> > > +++ b/target/mips/mips-defs.h
> > > @@ -51,8 +51,9 @@
> > >   */
> > >  #define INSN_LOONGSON2E   0x0001000000000000ULL
> > >  #define INSN_LOONGSON2F   0x0002000000000000ULL
> > > -#define INSN_VR54XX       0x0004000000000000ULL
> > > -#define INSN_R5900        0x0008000000000000ULL
> > > +#define INSN_LOONGSON3A   0x0004000000000000ULL
> > > +#define INSN_VR54XX       0x0008000000000000ULL
> > > +#define INSN_R5900        0x0010000000000000ULL
> > >  /*
> > >   *   bits 56-63: vendor-specific ASEs
> > >   */
> > > @@ -94,6 +95,8 @@
> > >  /* Wave Computing: "nanoMIPS" */
> > >  #define CPU_NANOMIPS32  (CPU_MIPS32R6 | ISA_NANOMIPS32)
> > >
> > > +#define CPU_LOONGSON3A  (CPU_MIPS64R2 | INSN_LOONGSON3A)
> > > +
> > >  /*
> > >   * Strictly follow the architecture standard:
> > >   * - Disallow "special" instruction handling for PMON/SPIM.
> > > diff --git a/target/mips/translate.c b/target/mips/translate.c
> > > index 25b595a..2caf4cb 100644
> > > --- a/target/mips/translate.c
> > > +++ b/target/mips/translate.c
> > > @@ -31206,7 +31206,9 @@ void cpu_state_reset(CPUMIPSState *env)
> > >      env->CP0_Config5 = env->cpu_model->CP0_Config5;
> > >      env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
> > >      env->CP0_Config6 = env->cpu_model->CP0_Config6;
> > > +    env->CP0_Config6_rw_bitmask = env->cpu_model->CP0_Config6_rw_bitmask;
> > >      env->CP0_Config7 = env->cpu_model->CP0_Config7;
> > > +    env->CP0_Config7_rw_bitmask = env->cpu_model->CP0_Config7_rw_bitmask;
> > >      env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
> > >                                   << env->cpu_model->CP0_LLAddr_shift;
> > >      env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
> > > diff --git a/target/mips/translate_init.inc.c b/target/mips/translate_init.inc.c
> > > index 6d145a9..a32412d 100644
> > > --- a/target/mips/translate_init.inc.c
> > > +++ b/target/mips/translate_init.inc.c
> > > @@ -802,6 +802,57 @@ const mips_def_t mips_defs[] =
> > >          .mmu_type = MMU_TYPE_R4000,
> > >      },
> > >      {
> > > +        .name = "Loongson-3A",
> > > +        .CP0_PRid = 0x14C000,
> > > +        /* 64KB I-cache and d-cache. 4 way with 32 bit cache line size.  */
> > > +        .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
> > > +                       (MMU_TYPE_R4000 << CP0C0_MT),
> > > +        .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) |
> > > +                       (2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
> > > +                       (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
> > > +                       (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
> > > +        .CP0_Config2 = MIPS_CONFIG2,
> > > +        .CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_MSAP) |
> > > +                       (1 << CP0C3_BP) | (1 << CP0C3_BI) | (1 << CP0C3_ULRI) |
> > > +                       (1 << CP0C3_RXI) | (1 << CP0C3_LPA) | (1 << CP0C3_VInt),
> > > +        .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) | (2 << CP0C4_IE) |
> > > +                       (1 << CP0C4_AE) | (0x1c << CP0C4_KScrExist),
> > > +        .CP0_Config4_rw_bitmask = 0,
> > > +        .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_NFExists) | (1 << 18),
> > > +        .CP0_Config5_rw_bitmask = (1 << CP0C5_K) | (1 << CP0C5_CV) |
> > > +                                  (1 << CP0C5_MSAEn) | (1 << CP0C5_UFE) |
> > > +                                  (1 << CP0C5_FRE) | (1 << CP0C5_SBRI),
> > > +        .CP0_Config6 = (1 << CP0C6_VCLRU) | (1 << CP0C6_DCLRU) | (1 << CP0C6_SFBEN) |
> > > +                       (1 << CP0C6_FLTINT) | (1 << CP0C6_INSTPREF) | (1 << CP0C6_DATAPREF),
> > > +        .CP0_Config6_rw_bitmask = (1 << CP0C6_BPPASS) | (0x3f << CP0C6_KPOS) |
> > > +                                  (1 << CP0C6_KE) | (1 << CP0C6_VTLBONLY) | (1 << CP0C6_LASX) |
> > > +                                  (1 << CP0C6_SSEN) | (1 << CP0C6_DISDRTIME) |
> > > +                                  (1 << CP0C6_PIXNUEN) | (1 << CP0C6_SCRAND) |
> > > +                                  (1 << CP0C6_LLEXCEN) | (1 << CP0C6_DISVC) |
> > > +                                  (1 << CP0C6_VCLRU) | (1 << CP0C6_DCLRU) |
> > > +                                  (1 << CP0C6_PIXUEN) | (1 << CP0C6_DISBLKLYEN) |
> > > +                                  (1 << CP0C6_UMEMUALEN) | (1 << CP0C6_SFBEN) |
> > > +                                  (1 << CP0C6_FLTINT) | (1 << CP0C6_VLTINT) |
> > > +                                  (1 << CP0C6_DISBTB) | (3 << CP0C6_STPREFCTL) |
> > > +                                  (1 << CP0C6_INSTPREF) | (1 << CP0C6_DATAPREF),
> > > +        .CP0_Config7 = 0,
> > > +        .CP0_Config7_rw_bitmask = (1 << CP0C7_NAPCGEN) | (1 << CP0C7_UNIMUEN) | \
> > > +                                  (1 << CP0C7_VFPUCGEN),
> > > +        .CP0_LLAddr_rw_bitmask = 1,
> > > +        .SYNCI_Step = 16,
> > > +        .CCRes = 2,
> > > +        .CP0_Status_rw_bitmask = 0x7DDBFFFF,
> > > +        .CP0_PageGrain_rw_bitmask = (1U << CP0PG_RIE) | (1 << CP0PG_XIE) |
> > > +                    (1 << CP0PG_ELPA) | (1 << CP0PG_IEC),
> > > +        .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x1 << FCR0_REV) | (0x1 << FCR0_F64),
> > > +        .CP1_fcr31 = 0,
> > > +        .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
> > > +        .SEGBITS = 48,
> > > +        .PABITS = 48,
> > > +        .insn_flags = CPU_LOONGSON3A,
> > > +        .mmu_type = MMU_TYPE_R4000,
> > > +    },
> > > +    {
> > >          /* A generic CPU providing MIPS64 DSP R2 ASE features.
> > >             FIXME: Eventually this should be replaced by a real CPU model. */
> > >          .name = "mips64dspr2",
> > >
>
>
>
> --
> Huacai Chen


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH for-5.1 3/7] hw/mips: Add CPU IRQ3 delivery for KVM
  2020-04-28  8:28     ` chen huacai
@ 2020-04-28 18:58       ` Aleksandar Markovic
  2020-04-29  1:52         ` Huacai Chen
  0 siblings, 1 reply; 30+ messages in thread
From: Aleksandar Markovic @ 2020-04-28 18:58 UTC (permalink / raw)
  To: chen huacai
  Cc: Huacai Chen, Huacai Chen, Philippe Mathieu-Daudé,
	Aurelien Jarno, qemu-level

уто, 28. апр 2020. у 10:21 chen huacai <zltjiangshi@gmail.com> је написао/ла:
>
> Hi, Philippe,
>
> On Mon, Apr 27, 2020 at 5:57 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
> >
> > On 4/27/20 11:33 AM, Huacai Chen wrote:
> > > Currently, KVM/MIPS only deliver I/O interrupt via IP2, this patch add
> > > IP2 delivery as well, because Loongson-3 based machine use both IRQ2
> > > (CPU's IP2) and IRQ3 (CPU's IP3).
> > >
> > > Signed-off-by: Huacai Chen <chenhc@lemote.com>
> > > Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> > > ---
> > >  hw/mips/mips_int.c | 6 ++----
> > >  1 file changed, 2 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c
> > > index 796730b..5526219 100644
> > > --- a/hw/mips/mips_int.c
> > > +++ b/hw/mips/mips_int.c
> > > @@ -48,16 +48,14 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level)
> > >      if (level) {
> > >          env->CP0_Cause |= 1 << (irq + CP0Ca_IP);
> > >
> > > -        if (kvm_enabled() && irq == 2) {
> > > +        if (kvm_enabled() && (irq == 2 || irq == 3))
> >
> > Shouldn't we check env->CP0_Config6 (or Config7) has the required
> > feature first?
> I'm sorry that I can't understand IRQ delivery has something to do
> with Config6/Config7, to identify Loongson-3?
>

Obviously, yes.

Thanks,
Aleksandar


> >
> > >              kvm_mips_set_interrupt(cpu, irq, level);
> > > -        }
> > >
> > >      } else {
> > >          env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
> > >
> > > -        if (kvm_enabled() && irq == 2) {
> > > +        if (kvm_enabled() && (irq == 2 || irq == 3))
> > >              kvm_mips_set_interrupt(cpu, irq, level);
> > > -        }
> > >      }
> > >
> > >      if (env->CP0_Cause & CP0Ca_IP_mask) {
> > >
>
>
>
> --
> Huacai Chen


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH for-5.1 5/7] target/mips: Add more CP0 register for save/restore
  2020-04-27  9:33 ` [PATCH for-5.1 5/7] target/mips: Add more CP0 register for save/restore Huacai Chen
@ 2020-04-28 19:10   ` Aleksandar Markovic
  2020-04-29  1:11     ` Huacai Chen
  0 siblings, 1 reply; 30+ messages in thread
From: Aleksandar Markovic @ 2020-04-28 19:10 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Huacai Chen, Huacai Chen, Philippe Mathieu-Daudé,
	Aurelien Jarno, QEMU Developers

пон, 27. апр 2020. у 11:36 Huacai Chen <zltjiangshi@gmail.com> је написао/ла:
>
> Add more CP0 register for save/restore, including: EBase, XContext,
> PageGrain, PWBase, PWSize, PWField, PWCtl, Config*, KScratch1~KScratch6.
>
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
>  target/mips/kvm.c     | 212 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  target/mips/machine.c |   2 +
>  2 files changed, 214 insertions(+)
>
> diff --git a/target/mips/kvm.c b/target/mips/kvm.c
> index de3e26e..96cfa10 100644
> --- a/target/mips/kvm.c
> +++ b/target/mips/kvm.c
> @@ -245,10 +245,16 @@ int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level)
>      (KVM_REG_MIPS_CP0 | KVM_REG_SIZE_U64 | (8 * (_R) + (_S)))
>
>  #define KVM_REG_MIPS_CP0_INDEX          MIPS_CP0_32(0, 0)
> +#define KVM_REG_MIPS_CP0_RANDOM         MIPS_CP0_32(1, 0)
>  #define KVM_REG_MIPS_CP0_CONTEXT        MIPS_CP0_64(4, 0)
>  #define KVM_REG_MIPS_CP0_USERLOCAL      MIPS_CP0_64(4, 2)
>  #define KVM_REG_MIPS_CP0_PAGEMASK       MIPS_CP0_32(5, 0)
> +#define KVM_REG_MIPS_CP0_PAGEGRAIN      MIPS_CP0_32(5, 1)
> +#define KVM_REG_MIPS_CP0_PWBASE         MIPS_CP0_64(5, 5)
> +#define KVM_REG_MIPS_CP0_PWFIELD        MIPS_CP0_64(5, 6)
> +#define KVM_REG_MIPS_CP0_PWSIZE         MIPS_CP0_64(5, 7)
>  #define KVM_REG_MIPS_CP0_WIRED          MIPS_CP0_32(6, 0)
> +#define KVM_REG_MIPS_CP0_PWCTL          MIPS_CP0_32(6, 6)
>  #define KVM_REG_MIPS_CP0_HWRENA         MIPS_CP0_32(7, 0)
>  #define KVM_REG_MIPS_CP0_BADVADDR       MIPS_CP0_64(8, 0)
>  #define KVM_REG_MIPS_CP0_COUNT          MIPS_CP0_32(9, 0)
> @@ -258,13 +264,22 @@ int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level)
>  #define KVM_REG_MIPS_CP0_CAUSE          MIPS_CP0_32(13, 0)
>  #define KVM_REG_MIPS_CP0_EPC            MIPS_CP0_64(14, 0)
>  #define KVM_REG_MIPS_CP0_PRID           MIPS_CP0_32(15, 0)
> +#define KVM_REG_MIPS_CP0_EBASE          MIPS_CP0_64(15, 1)
>  #define KVM_REG_MIPS_CP0_CONFIG         MIPS_CP0_32(16, 0)
>  #define KVM_REG_MIPS_CP0_CONFIG1        MIPS_CP0_32(16, 1)
>  #define KVM_REG_MIPS_CP0_CONFIG2        MIPS_CP0_32(16, 2)
>  #define KVM_REG_MIPS_CP0_CONFIG3        MIPS_CP0_32(16, 3)
>  #define KVM_REG_MIPS_CP0_CONFIG4        MIPS_CP0_32(16, 4)
>  #define KVM_REG_MIPS_CP0_CONFIG5        MIPS_CP0_32(16, 5)
> +#define KVM_REG_MIPS_CP0_CONFIG6        MIPS_CP0_32(16, 6)
> +#define KVM_REG_MIPS_CP0_XCONTEXT       MIPS_CP0_64(20, 0)
>  #define KVM_REG_MIPS_CP0_ERROREPC       MIPS_CP0_64(30, 0)
> +#define KVM_REG_MIPS_CP0_KSCRATCH1      MIPS_CP0_64(31, 2)
> +#define KVM_REG_MIPS_CP0_KSCRATCH2      MIPS_CP0_64(31, 3)
> +#define KVM_REG_MIPS_CP0_KSCRATCH3      MIPS_CP0_64(31, 4)
> +#define KVM_REG_MIPS_CP0_KSCRATCH4      MIPS_CP0_64(31, 5)
> +#define KVM_REG_MIPS_CP0_KSCRATCH5      MIPS_CP0_64(31, 6)
> +#define KVM_REG_MIPS_CP0_KSCRATCH6      MIPS_CP0_64(31, 7)
>
>  static inline int kvm_mips_put_one_reg(CPUState *cs, uint64_t reg_id,
>                                         int32_t *addr)
> @@ -394,6 +409,29 @@ static inline int kvm_mips_get_one_ureg64(CPUState *cs, uint64_t reg_id,
>                                           (1U << CP0C5_UFE) | \
>                                           (1U << CP0C5_FRE) | \
>                                           (1U << CP0C5_UFR))
> +#define KVM_REG_MIPS_CP0_CONFIG6_MASK   ((1U << CP0C6_BPPASS) | \
> +                                         (0x3fU << CP0C6_KPOS) | \
> +                                         (1U << CP0C6_KE) | \
> +                                         (1U << CP0C6_VTLBONLY) | \
> +                                         (1U << CP0C6_LASX) | \
> +                                         (1U << CP0C6_SSEN) | \
> +                                         (1U << CP0C6_DISDRTIME) | \
> +                                         (1U << CP0C6_PIXNUEN) | \
> +                                         (1U << CP0C6_SCRAND) | \
> +                                         (1U << CP0C6_LLEXCEN) | \
> +                                         (1U << CP0C6_DISVC) | \
> +                                         (1U << CP0C6_VCLRU) | \
> +                                         (1U << CP0C6_DCLRU) | \
> +                                         (1U << CP0C6_PIXUEN) | \
> +                                         (1U << CP0C6_DISBLKLYEN) | \
> +                                         (1U << CP0C6_UMEMUALEN) | \
> +                                         (1U << CP0C6_SFBEN) | \
> +                                         (1U << CP0C6_FLTINT) | \
> +                                         (1U << CP0C6_VLTINT) | \
> +                                         (1U << CP0C6_DISBTB) | \
> +                                         (3U << CP0C6_STPREFCTL) | \
> +                                         (1U << CP0C6_INSTPREF) | \
> +                                         (1U << CP0C6_DATAPREF))
>
>  static inline int kvm_mips_change_one_reg(CPUState *cs, uint64_t reg_id,
>                                            int32_t *addr, int32_t mask)
> @@ -729,6 +767,11 @@ static int kvm_mips_put_cp0_registers(CPUState *cs, int level)
>          DPRINTF("%s: Failed to put CP0_INDEX (%d)\n", __func__, err);
>          ret = err;
>      }
> +    err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_RANDOM, &env->CP0_Random);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to put CP0_RANDOM (%d)\n", __func__, err);
> +        ret = err;
> +    }
>      err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT,
>                                   &env->CP0_Context);
>      if (err < 0) {
> @@ -747,11 +790,40 @@ static int kvm_mips_put_cp0_registers(CPUState *cs, int level)
>          DPRINTF("%s: Failed to put CP0_PAGEMASK (%d)\n", __func__, err);
>          ret = err;
>      }
> +    err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PAGEGRAIN,
> +                               &env->CP0_PageGrain);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to put CP0_PAGEGRAIN (%d)\n", __func__, err);
> +        ret = err;
> +    }
> +    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWBASE,
> +                               &env->CP0_PWBase);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to put CP0_PWBASE (%d)\n", __func__, err);
> +        ret = err;
> +    }
> +    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWFIELD,
> +                               &env->CP0_PWField);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to put CP0_PWField (%d)\n", __func__, err);
> +        ret = err;
> +    }
> +    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWSIZE,
> +                               &env->CP0_PWSize);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to put CP0_PWSIZE (%d)\n", __func__, err);
> +        ret = err;
> +    }
>      err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired);
>      if (err < 0) {
>          DPRINTF("%s: Failed to put CP0_WIRED (%d)\n", __func__, err);
>          ret = err;
>      }
> +    err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PWCTL, &env->CP0_PWCtl);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to put CP0_PWCTL (%d)\n", __func__, err);
> +        ret = err;
> +    }
>      err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_HWRENA, &env->CP0_HWREna);
>      if (err < 0) {
>          DPRINTF("%s: Failed to put CP0_HWRENA (%d)\n", __func__, err);
> @@ -799,6 +871,11 @@ static int kvm_mips_put_cp0_registers(CPUState *cs, int level)
>          DPRINTF("%s: Failed to put CP0_PRID (%d)\n", __func__, err);
>          ret = err;
>      }
> +    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_EBASE, &env->CP0_EBase);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to put CP0_EBASE (%d)\n", __func__, err);
> +        ret = err;
> +    }
>      err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG,
>                                    &env->CP0_Config0,
>                                    KVM_REG_MIPS_CP0_CONFIG_MASK);
> @@ -841,12 +918,61 @@ static int kvm_mips_put_cp0_registers(CPUState *cs, int level)
>          DPRINTF("%s: Failed to change CP0_CONFIG5 (%d)\n", __func__, err);
>          ret = err;
>      }
> +    err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG6,
> +                                  &env->CP0_Config6,
> +                                  KVM_REG_MIPS_CP0_CONFIG6_MASK);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to change CP0_CONFIG6 (%d)\n", __func__, err);
> +        ret = err;
> +    }
> +    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_XCONTEXT,
> +                                 &env->CP0_XContext);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to put CP0_XCONTEXT (%d)\n", __func__, err);
> +        ret = err;
> +    }
>      err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
>                                   &env->CP0_ErrorEPC);
>      if (err < 0) {
>          DPRINTF("%s: Failed to put CP0_ERROREPC (%d)\n", __func__, err);
>          ret = err;
>      }
> +    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH1,
> +                                 &env->CP0_KScratch[0]);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to put CP0_KSCRATCH1 (%d)\n", __func__, err);
> +        ret = err;
> +    }
> +    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH2,
> +                                 &env->CP0_KScratch[1]);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to put CP0_KSCRATCH2 (%d)\n", __func__, err);
> +        ret = err;
> +    }
> +    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH3,
> +                                 &env->CP0_KScratch[2]);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to put CP0_KSCRATCH3 (%d)\n", __func__, err);
> +        ret = err;
> +    }
> +    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH4,
> +                                 &env->CP0_KScratch[3]);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to put CP0_KSCRATCH4 (%d)\n", __func__, err);
> +        ret = err;
> +    }
> +    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH5,
> +                                 &env->CP0_KScratch[4]);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to put CP0_KSCRATCH5 (%d)\n", __func__, err);
> +        ret = err;
> +    }
> +    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH6,
> +                                 &env->CP0_KScratch[5]);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to put CP0_KSCRATCH6 (%d)\n", __func__, err);
> +        ret = err;
> +    }
>
>      return ret;
>  }
> @@ -862,6 +988,11 @@ static int kvm_mips_get_cp0_registers(CPUState *cs)
>          DPRINTF("%s: Failed to get CP0_INDEX (%d)\n", __func__, err);
>          ret = err;
>      }
> +    err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_RANDOM, &env->CP0_Random);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to get CP0_RANDOM (%d)\n", __func__, err);
> +        ret = err;
> +    }
>      err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT,
>                                   &env->CP0_Context);
>      if (err < 0) {
> @@ -880,11 +1011,40 @@ static int kvm_mips_get_cp0_registers(CPUState *cs)
>          DPRINTF("%s: Failed to get CP0_PAGEMASK (%d)\n", __func__, err);
>          ret = err;
>      }
> +    err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PAGEGRAIN,
> +                               &env->CP0_PageGrain);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to get CP0_PAGEGRAIN (%d)\n", __func__, err);
> +        ret = err;
> +    }
> +    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWBASE,
> +                               &env->CP0_PWBase);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to get CP0_PWBASE (%d)\n", __func__, err);
> +        ret = err;
> +    }
> +    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWFIELD,
> +                               &env->CP0_PWField);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to get CP0_PWFIELD (%d)\n", __func__, err);
> +        ret = err;
> +    }
> +    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWSIZE,
> +                               &env->CP0_PWSize);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to get CP0_PWSIZE (%d)\n", __func__, err);
> +        ret = err;
> +    }
>      err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired);
>      if (err < 0) {
>          DPRINTF("%s: Failed to get CP0_WIRED (%d)\n", __func__, err);
>          ret = err;
>      }
> +    err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PWCTL, &env->CP0_PWCtl);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to get CP0_PWCtl (%d)\n", __func__, err);
> +        ret = err;
> +    }
>      err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_HWRENA, &env->CP0_HWREna);
>      if (err < 0) {
>          DPRINTF("%s: Failed to get CP0_HWRENA (%d)\n", __func__, err);
> @@ -932,6 +1092,11 @@ static int kvm_mips_get_cp0_registers(CPUState *cs)
>          DPRINTF("%s: Failed to get CP0_PRID (%d)\n", __func__, err);
>          ret = err;
>      }
> +    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_EBASE, &env->CP0_EBase);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to get CP0_EBASE (%d)\n", __func__, err);
> +        ret = err;
> +    }
>      err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG, &env->CP0_Config0);
>      if (err < 0) {
>          DPRINTF("%s: Failed to get CP0_CONFIG (%d)\n", __func__, err);
> @@ -962,12 +1127,59 @@ static int kvm_mips_get_cp0_registers(CPUState *cs)
>          DPRINTF("%s: Failed to get CP0_CONFIG5 (%d)\n", __func__, err);
>          ret = err;
>      }
> +    err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG6, &env->CP0_Config6);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to get CP0_CONFIG6 (%d)\n", __func__, err);
> +        ret = err;
> +    }
> +    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_XCONTEXT,
> +                                 &env->CP0_XContext);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to get CP0_XCONTEXT (%d)\n", __func__, err);
> +        ret = err;
> +    }
>      err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
>                                   &env->CP0_ErrorEPC);
>      if (err < 0) {
>          DPRINTF("%s: Failed to get CP0_ERROREPC (%d)\n", __func__, err);
>          ret = err;
>      }
> +    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH1,
> +                                 &env->CP0_KScratch[0]);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to get CP0_KSCRATCH1 (%d)\n", __func__, err);
> +        ret = err;
> +    }
> +    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH2,
> +                                 &env->CP0_KScratch[1]);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to get CP0_KSCRATCH2 (%d)\n", __func__, err);
> +        ret = err;
> +    }
> +    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH3,
> +                                 &env->CP0_KScratch[2]);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to get CP0_KSCRATCH3 (%d)\n", __func__, err);
> +        ret = err;
> +    }
> +    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH4,
> +                                 &env->CP0_KScratch[3]);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to get CP0_KSCRATCH4 (%d)\n", __func__, err);
> +        ret = err;
> +    }
> +    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH5,
> +                                 &env->CP0_KScratch[4]);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to get CP0_KSCRATCH5 (%d)\n", __func__, err);
> +        ret = err;
> +    }
> +    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH6,
> +                                 &env->CP0_KScratch[5]);
> +    if (err < 0) {
> +        DPRINTF("%s: Failed to get CP0_KSCRATCH6 (%d)\n", __func__, err);
> +        ret = err;
> +    }
>
>      return ret;
>  }
> diff --git a/target/mips/machine.c b/target/mips/machine.c
> index 8d5b18b..a84aefc 100644
> --- a/target/mips/machine.c
> +++ b/target/mips/machine.c
> @@ -289,6 +289,8 @@ const VMStateDescription vmstate_mips_cpu = {
>          VMSTATE_INT32(env.CP0_Config1, MIPSCPU),
>          VMSTATE_INT32(env.CP0_Config2, MIPSCPU),
>          VMSTATE_INT32(env.CP0_Config3, MIPSCPU),
> +        VMSTATE_INT32(env.CP0_Config4, MIPSCPU),
> +        VMSTATE_INT32(env.CP0_Config5, MIPSCPU),
>          VMSTATE_INT32(env.CP0_Config6, MIPSCPU),
>          VMSTATE_INT32(env.CP0_Config7, MIPSCPU),
>          VMSTATE_UINT64(env.CP0_LLAddr, MIPSCPU),
> --
> 2.7.0
>

Huacai,

You need to bump two fields in VMStateDescription any time you add new fields.

This means two instances of "19" should be changed to "20" here:

const VMStateDescription vmstate_mips_cpu = {
.name = "cpu",
.version_id = 19,
.minimum_version_id = 19,
.post_load = cpu_post_load,
.fields = (VMStateField[]) {

Thanks,
Aleksandar


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH for-5.1 1/7] configure: Add KVM target support for MIPS64
  2020-04-27  9:33 [PATCH for-5.1 1/7] configure: Add KVM target support for MIPS64 Huacai Chen
                   ` (5 preceding siblings ...)
  2020-04-27  9:33 ` [PATCH for-5.1 7/7] MAINTAINERS: Add myself as Loongson-3 maintainer Huacai Chen
@ 2020-04-28 19:15 ` Aleksandar Markovic
  6 siblings, 0 replies; 30+ messages in thread
From: Aleksandar Markovic @ 2020-04-28 19:15 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Huacai Chen, Huacai Chen, Philippe Mathieu-Daudé,
	Aurelien Jarno, QEMU Developers

пон, 27. апр 2020. у 11:33 Huacai Chen <zltjiangshi@gmail.com> је написао/ла:
>
> Preparing for Loongson-3 virtualization, add KVM target support for
> MIPS64 in configure script.
>
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---

Huacai, hi.

I am really glad this series arrived, and salute your work.

But it looks no cover letter arrived, and here and there there are
some omission.

The english machine translation of all relevant docs would be good too.

Please send v2, a little bit more complete.

Sincerely,
Aleksandar

>  configure | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/configure b/configure
> index 23b5e93..7581e65 100755
> --- a/configure
> +++ b/configure
> @@ -198,7 +198,7 @@ supported_kvm_target() {
>          arm:arm | aarch64:aarch64 | \
>          i386:i386 | i386:x86_64 | i386:x32 | \
>          x86_64:i386 | x86_64:x86_64 | x86_64:x32 | \
> -        mips:mips | mipsel:mips | \
> +        mips:mips | mipsel:mips | mips64:mips | mips64el:mips | \
>          ppc:ppc | ppc64:ppc | ppc:ppc64 | ppc64:ppc64 | ppc64:ppc64le | \
>          s390x:s390x)
>              return 0
> --
> 2.7.0
>


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH for-5.1 6/7] hw/mips: Add Loongson-3 machine support (with KVM)
  2020-04-27  9:33 ` [PATCH for-5.1 6/7] hw/mips: Add Loongson-3 machine support (with KVM) Huacai Chen
@ 2020-04-28 19:23   ` Aleksandar Markovic
  2020-04-29  1:13     ` Huacai Chen
  0 siblings, 1 reply; 30+ messages in thread
From: Aleksandar Markovic @ 2020-04-28 19:23 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Huacai Chen, Huacai Chen, Philippe Mathieu-Daudé,
	Aurelien Jarno, QEMU Developers

Hi. Huacei.

Please expand commit message with the description of the machine
internal organization (several paragraphs).

Also, please include command line for starting the machine. More than
one example is better than only one.

Specifically, can you explicitly say what is your KVM setup, so that
anyone could repro it?

Good health to people from China!

Yours,
Aleksandar

пон, 27. апр 2020. у 11:36 Huacai Chen <zltjiangshi@gmail.com> је написао/ла:
>
> Add Loongson-3 based machine support, it use i8259 as the interrupt
> controler and use GPEX as the pci controller. Currently it can only
> work with KVM, but we will add TCG support in future.
>
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
>  default-configs/mips64el-softmmu.mak |   1 +
>  hw/mips/Kconfig                      |  10 +
>  hw/mips/Makefile.objs                |   1 +
>  hw/mips/mips_loongson3.c             | 869 +++++++++++++++++++++++++++++++++++
>  4 files changed, 881 insertions(+)
>  create mode 100644 hw/mips/mips_loongson3.c
>
> diff --git a/default-configs/mips64el-softmmu.mak b/default-configs/mips64el-softmmu.mak
> index 8b0c9b1..fc798e4 100644
> --- a/default-configs/mips64el-softmmu.mak
> +++ b/default-configs/mips64el-softmmu.mak
> @@ -3,6 +3,7 @@
>  include mips-softmmu-common.mak
>  CONFIG_IDE_VIA=y
>  CONFIG_FULONG=y
> +CONFIG_LOONGSON3=y
>  CONFIG_ATI_VGA=y
>  CONFIG_RTL8139_PCI=y
>  CONFIG_JAZZ=y
> diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig
> index 2c2adbc..6f16b16 100644
> --- a/hw/mips/Kconfig
> +++ b/hw/mips/Kconfig
> @@ -44,6 +44,16 @@ config JAZZ
>  config FULONG
>      bool
>
> +config LOONGSON3
> +    bool
> +    select PCKBD
> +    select SERIAL
> +    select ISA_BUS
> +    select PCI_EXPRESS_GENERIC_BRIDGE
> +    select VIRTIO_VGA
> +    select QXL if SPICE
> +    select MSI_NONBROKEN
> +
>  config MIPS_CPS
>      bool
>      select PTIMER
> diff --git a/hw/mips/Makefile.objs b/hw/mips/Makefile.objs
> index 2f7795b..f9bc8f5 100644
> --- a/hw/mips/Makefile.objs
> +++ b/hw/mips/Makefile.objs
> @@ -4,5 +4,6 @@ obj-$(CONFIG_MALTA) += gt64xxx_pci.o mips_malta.o
>  obj-$(CONFIG_MIPSSIM) += mips_mipssim.o
>  obj-$(CONFIG_JAZZ) += mips_jazz.o
>  obj-$(CONFIG_FULONG) += mips_fulong2e.o
> +obj-$(CONFIG_LOONGSON3) += mips_loongson3.o
>  obj-$(CONFIG_MIPS_CPS) += cps.o
>  obj-$(CONFIG_MIPS_BOSTON) += boston.o
> diff --git a/hw/mips/mips_loongson3.c b/hw/mips/mips_loongson3.c
> new file mode 100644
> index 0000000..a45c9ec
> --- /dev/null
> +++ b/hw/mips/mips_loongson3.c
> @@ -0,0 +1,869 @@
> +/*
> + * Generic Loongson-3 Platform support
> + *
> + * Copyright (c) 2015-2020 Huacai Chen (chenhc@lemote.com)
> + * This code is licensed under the GNU GPL v2.
> + *
> + * Contributions are licensed under the terms of the GNU GPL,
> + * version 2 or (at your option) any later version.
> + */
> +
> +/*
> + * Generic PC Platform based on Loongson-3 CPU (MIPS64R2 with extensions,
> + * 800~2000MHz)
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu-common.h"
> +#include "qemu/units.h"
> +#include "qapi/error.h"
> +#include "cpu.h"
> +#include "elf.h"
> +#include "hw/boards.h"
> +#include "hw/block/flash.h"
> +#include "hw/char/serial.h"
> +#include "hw/mips/mips.h"
> +#include "hw/mips/cpudevs.h"
> +#include "hw/intc/i8259.h"
> +#include "hw/loader.h"
> +#include "hw/ide.h"
> +#include "hw/isa/superio.h"
> +#include "hw/pci/msi.h"
> +#include "hw/pci/pci.h"
> +#include "hw/pci/pci_host.h"
> +#include "hw/pci-host/gpex.h"
> +#include "hw/rtc/mc146818rtc.h"
> +#include "net/net.h"
> +#include "exec/address-spaces.h"
> +#include "sysemu/qtest.h"
> +#include "sysemu/reset.h"
> +#include "sysemu/runstate.h"
> +#include "qemu/log.h"
> +#include "qemu/error-report.h"
> +
> +#define INITRD_OFFSET          0x04000000
> +#define BOOTPARAM_ADDR         0x8ff00000
> +#define BOOTPARAM_PHYADDR      0x0ff00000
> +#define CFG_ADDR               0x0f100000
> +#define FW_CONF_ADDR           0x0fff0000
> +#define PM_MMIO_ADDR           0x10080000
> +#define PM_MMIO_SIZE           0x100
> +#define PM_CNTL_MODE           0x10
> +
> +#define PHYS_TO_VIRT(x) ((x) | ~(target_ulong)0x7fffffff)
> +
> +/* Loongson-3 has a 2MB flash rom */
> +#define BIOS_SIZE               (2 * MiB)
> +#define LOONGSON_MAX_VCPUS      16
> +
> +#define LOONGSON3_BIOSNAME "bios_loongson3.bin"
> +
> +#define PCIE_IRQ_BASE     3
> +
> +#define VIRT_PCI_IO_BASE    0x18000000ul
> +#define VIRT_PCI_IO_SIZE    0x000c0000ul
> +#define VIRT_PCI_MEM_BASE   0x40000000ul
> +#define VIRT_PCI_MEM_SIZE   0x40000000ul
> +#define VIRT_PCI_ECAM_BASE  0x1a000000ul
> +#define VIRT_PCI_ECAM_SIZE  0x02000000ul
> +
> +#define align(x) (((x) + 63) & ~63)
> +
> +struct efi_memory_map_loongson {
> +    uint16_t vers;               /* version of efi_memory_map */
> +    uint32_t nr_map;             /* number of memory_maps */
> +    uint32_t mem_freq;           /* memory frequence */
> +    struct mem_map{
> +        uint32_t node_id;        /* node_id which memory attached to */
> +        uint32_t mem_type;       /* system memory, pci memory, pci io, etc. */
> +        uint64_t mem_start;      /* memory map start address */
> +        uint32_t mem_size;       /* each memory_map size, not the total size */
> +    } map[128];
> +} __attribute__((packed));
> +
> +enum loongson_cpu_type {
> +    Legacy_2E = 0x0,
> +    Legacy_2F = 0x1,
> +    Legacy_3A = 0x2,
> +    Legacy_3B = 0x3,
> +    Legacy_1A = 0x4,
> +    Legacy_1B = 0x5,
> +    Legacy_2G = 0x6,
> +    Legacy_2H = 0x7,
> +    Loongson_1A = 0x100,
> +    Loongson_1B = 0x101,
> +    Loongson_2E = 0x200,
> +    Loongson_2F = 0x201,
> +    Loongson_2G = 0x202,
> +    Loongson_2H = 0x203,
> +    Loongson_3A = 0x300,
> +    Loongson_3B = 0x301
> +};
> +
> +/*
> + * Capability and feature descriptor structure for MIPS CPU
> + */
> +struct efi_cpuinfo_loongson {
> +    uint16_t vers;               /* version of efi_cpuinfo_loongson */
> +    uint32_t processor_id;       /* PRID, e.g. 6305, 6306 */
> +    uint32_t cputype;            /* Loongson_3A/3B, etc. */
> +    uint32_t total_node;         /* num of total numa nodes */
> +    uint16_t cpu_startup_core_id;   /* Boot core id */
> +    uint16_t reserved_cores_mask;
> +    uint32_t cpu_clock_freq;     /* cpu_clock */
> +    uint32_t nr_cpus;
> +    char cpuname[64];
> +} __attribute__((packed));
> +
> +#define MAX_UARTS 64
> +struct uart_device {
> +    uint32_t iotype; /* see include/linux/serial_core.h */
> +    uint32_t uartclk;
> +    uint32_t int_offset;
> +    uint64_t uart_base;
> +} __attribute__((packed));
> +
> +#define MAX_SENSORS 64
> +#define SENSOR_TEMPER  0x00000001
> +#define SENSOR_VOLTAGE 0x00000002
> +#define SENSOR_FAN     0x00000004
> +struct sensor_device {
> +    char name[32];  /* a formal name */
> +    char label[64]; /* a flexible description */
> +    uint32_t type;       /* SENSOR_* */
> +    uint32_t id;         /* instance id of a sensor-class */
> +    uint32_t fan_policy; /* see arch/mips/include/asm/mach-loongson/loongson_hwmon.h */
> +    uint32_t fan_percent;/* only for constant speed policy */
> +    uint64_t base_addr;  /* base address of device registers */
> +} __attribute__((packed));
> +
> +struct system_loongson {
> +    uint16_t vers;               /* version of system_loongson */
> +    uint32_t ccnuma_smp;         /* 0: no numa; 1: has numa */
> +    uint32_t sing_double_channel;/* 1: single; 2: double */
> +    uint32_t nr_uarts;
> +    struct uart_device uarts[MAX_UARTS];
> +    uint32_t nr_sensors;
> +    struct sensor_device sensors[MAX_SENSORS];
> +    char has_ec;
> +    char ec_name[32];
> +    uint64_t ec_base_addr;
> +    char has_tcm;
> +    char tcm_name[32];
> +    uint64_t tcm_base_addr;
> +    uint64_t workarounds; /* see workarounds.h */
> +    uint64_t of_dtb_addr; /* NULL if not support */
> +} __attribute__((packed));
> +
> +struct irq_source_routing_table {
> +    uint16_t vers;
> +    uint16_t size;
> +    uint16_t rtr_bus;
> +    uint16_t rtr_devfn;
> +    uint32_t vendor;
> +    uint32_t device;
> +    uint32_t PIC_type;           /* conform use HT or PCI to route to CPU-PIC */
> +    uint64_t ht_int_bit;         /* 3A: 1<<24; 3B: 1<<16 */
> +    uint64_t ht_enable;          /* irqs used in this PIC */
> +    uint32_t node_id;            /* node id: 0x0-0; 0x1-1; 0x10-2; 0x11-3 */
> +    uint64_t pci_mem_start_addr;
> +    uint64_t pci_mem_end_addr;
> +    uint64_t pci_io_start_addr;
> +    uint64_t pci_io_end_addr;
> +    uint64_t pci_config_addr;
> +    uint16_t dma_mask_bits;
> +    uint16_t dma_noncoherent;
> +} __attribute__((packed));
> +
> +struct interface_info {
> +    uint16_t vers;               /* version of the specificition */
> +    uint16_t size;
> +    uint8_t  flag;
> +    char description[64];
> +} __attribute__((packed));
> +
> +#define MAX_RESOURCE_NUMBER 128
> +struct resource_loongson {
> +    uint64_t start;              /* resource start address */
> +    uint64_t end;                /* resource end address */
> +    char name[64];
> +    uint32_t flags;
> +};
> +
> +struct archdev_data {};          /* arch specific additions */
> +
> +struct board_devices {
> +    char name[64];               /* hold the device name */
> +    uint32_t num_resources;      /* number of device_resource */
> +    /* for each device's resource */
> +    struct resource_loongson resource[MAX_RESOURCE_NUMBER];
> +    /* arch specific additions */
> +    struct archdev_data archdata;
> +};
> +
> +struct loongson_special_attribute {
> +    uint16_t vers;               /* version of this special */
> +    char special_name[64];       /* special_atribute_name */
> +    uint32_t loongson_special_type; /* type of special device */
> +    /* for each device's resource */
> +    struct resource_loongson resource[MAX_RESOURCE_NUMBER];
> +};
> +
> +struct loongson_params {
> +    uint64_t memory_offset;      /* efi_memory_map_loongson struct offset */
> +    uint64_t cpu_offset;         /* efi_cpuinfo_loongson struct offset */
> +    uint64_t system_offset;      /* system_loongson struct offset */
> +    uint64_t irq_offset;         /* irq_source_routing_table struct offset */
> +    uint64_t interface_offset;   /* interface_info struct offset */
> +    uint64_t special_offset;     /* loongson_special_attribute struct offset */
> +    uint64_t boarddev_table_offset;  /* board_devices offset */
> +};
> +
> +struct smbios_tables {
> +    uint16_t vers;               /* version of smbios */
> +    uint64_t vga_bios;           /* vga_bios address */
> +    struct loongson_params lp;
> +};
> +
> +struct efi_reset_system_t {
> +    uint64_t ResetCold;
> +    uint64_t ResetWarm;
> +    uint64_t ResetType;
> +    uint64_t Shutdown;
> +    uint64_t DoSuspend; /* NULL if not support */
> +};
> +
> +struct efi_loongson {
> +    uint64_t mps;                /* MPS table */
> +    uint64_t acpi;               /* ACPI table (IA64 ext 0.71) */
> +    uint64_t acpi20;             /* ACPI table (ACPI 2.0) */
> +    struct smbios_tables smbios; /* SM BIOS table */
> +    uint64_t sal_systab;         /* SAL system table */
> +    uint64_t boot_info;          /* boot info table */
> +};
> +
> +struct boot_params {
> +    struct efi_loongson efi;
> +    struct efi_reset_system_t reset_system;
> +};
> +
> +static struct _fw_config {
> +    unsigned long ram_size;
> +    unsigned int mem_freq;
> +    unsigned int nr_cpus;
> +    unsigned int cpu_clock_freq;
> +} fw_config;
> +
> +static struct _loaderparams {
> +    unsigned long ram_size;
> +    const char *kernel_cmdline;
> +    const char *kernel_filename;
> +    const char *initrd_filename;
> +    int64_t kernel_entry;
> +    unsigned long a0, a1, a2;
> +} loaderparams;
> +
> +static void *boot_params_p;
> +static void *boot_params_buf;
> +
> +static unsigned int bios_boot_code[] = {
> +    0x40086000,   /* mfc0    t0, CP0_STATUS                                        */
> +    0x240900E2,   /* li      t1, 0x00e2       #{cu3,cu2,cu1,cu0,status_fr}<={0111} */
> +    0x01094025,   /* or      t0, t0, t1                                            */
> +    0x40886000,   /* mtc0    t0, CP0_STATUS                                        */
> +    0x00000000,
> +    0x40086000,   /* mfc0    t0, CP0_STATUS                                        */
> +    0x3C090040,   /* lui     t1, 0x40         #bev                                 */
> +    0x01094025,   /* or      t0, t0, t1                                            */
> +    0x40886000,   /* mtc0    t0, CP0_STATUS                                        */
> +    0x00000000,
> +    0x40806800,   /* mtc0    zero, CP0_CAUSE                                       */
> +    0x00000000,
> +    0x400A7801,   /* mfc0    t2, $15, 1                                            */
> +    0x314A00FF,   /* andi    t2, 0x0ff                                             */
> +    0x3C089000,   /* dli     t0, 0x900000003ff01000                                */
> +    0x00084438,
> +    0x35083FF0,
> +    0x00084438,
> +    0x35081000,
> +    0x314B0003,   /* andi    t3, t2, 0x3      #local cpuid                         */
> +    0x000B5A00,   /* sll     t3, 8                                                 */
> +    0x010B4025,   /* or      t0, t0, t3                                            */
> +    0x314C000C,   /* andi    t4, t2, 0xc      #node id                             */
> +    0x000C62BC,   /* dsll    t4, 42                                                */
> +    0x010C4025,   /* or      t0, t0, t4                                            */
> +                  /* waitforinit:                                                  */
> +    0xDD020020,   /* ld      v0, FN_OFF(t0)   #FN_OFF 0x020                        */
> +    0x1040FFFE,   /* beqz    v0, waitforinit                                       */
> +    0x00000000,   /* nop                                                           */
> +    0xDD1D0028,   /* ld      sp, SP_OFF(t0)   #FN_OFF 0x028                        */
> +    0xDD1C0030,   /* ld      gp, GP_OFF(t0)   #FN_OFF 0x030                        */
> +    0xDD050038,   /* ld      a1, A1_OFF(t0)   #FN_OFF 0x038                        */
> +    0x00400008,   /* jr      v0               #byebye                              */
> +    0x00000000,   /* nop                                                           */
> +    0x1000FFFF,   /* 1:  b   1b                                                    */
> +    0x00000000,   /* nop                                                           */
> +
> +                  /* Reset                                                         */
> +    0x3C0C9000,   /* dli     t0, 0x9000000010080010                                */
> +    0x358C0000,
> +    0x000C6438,
> +    0x358C1008,
> +    0x000C6438,
> +    0x358C0010,
> +    0x240D0000,   /* li      t1, 0x00                                              */
> +    0xA18D0000,   /* sb      t1, (t0)                                              */
> +    0x1000FFFF,   /* 1:  b   1b                                                    */
> +    0x00000000,   /* nop                                                           */
> +
> +                  /* Shutdown                                                      */
> +    0x3C0C9000,   /* dli     t0, 0x9000000010080010                                */
> +    0x358C0000,
> +    0x000C6438,
> +    0x358C1008,
> +    0x000C6438,
> +    0x358C0010,
> +    0x240D00FF,   /* li      t1, 0xff                                              */
> +    0xA18D0000,   /* sb      t1, (t0)                                              */
> +    0x1000FFFF,   /* 1:  b   1b                                                    */
> +    0x00000000    /* nop                                                           */
> +};
> +
> +static uint64_t loongson3_pm_read(void *opaque, hwaddr addr, unsigned size)
> +{
> +    return 0;
> +}
> +
> +static void loongson3_pm_write(void *opaque, hwaddr addr, uint64_t val,unsigned size)
> +{
> +    if (addr != PM_CNTL_MODE)
> +        return;
> +
> +    switch (val) {
> +    case 0x00:
> +        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
> +        return;
> +    case 0xff:
> +        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
> +        return;
> +    default:
> +        return;
> +    }
> +}
> +
> +static const MemoryRegionOps loongson3_pm_ops = {
> +    .read  = loongson3_pm_read,
> +    .write = loongson3_pm_write,
> +    .endianness = DEVICE_NATIVE_ENDIAN,
> +};
> +
> +static struct efi_memory_map_loongson *init_memory_map(void *g_map)
> +{
> +    struct efi_memory_map_loongson *emap = g_map;
> +
> +    emap->nr_map = 2;
> +    emap->mem_freq = 300000000;
> +
> +    emap->map[0].node_id = 0;
> +    emap->map[0].mem_type = 1;
> +    emap->map[0].mem_start = 0x0;
> +    emap->map[0].mem_size = (loaderparams.ram_size > 0x10000000
> +                            ? 256 : (loaderparams.ram_size >> 20)) - 16;
> +
> +    emap->map[1].node_id = 0;
> +    emap->map[1].mem_type = 2;
> +    emap->map[1].mem_start = 0x90000000;
> +    emap->map[1].mem_size = (loaderparams.ram_size > 0x10000000
> +                            ? (loaderparams.ram_size >> 20) - 256 : 0);
> +
> +    return emap;
> +}
> +
> +static int get_host_cpu_freq(void)
> +{
> +    int fd = 0, freq = 0;
> +    char buf[1024], *buf_p;
> +
> +    if ((fd = open("/proc/cpuinfo", O_RDONLY)) == -1) {
> +        fprintf(stderr, "Failed to open /proc/cpuinfo!\n");
> +        return 0;
> +    }
> +
> +    if (read(fd, buf, 1024) < 0) {
> +        close(fd);
> +        fprintf(stderr, "Failed to read /proc/cpuinfo!\n");
> +        return 0;
> +    }
> +    close(fd);
> +
> +    buf_p = strstr(buf, "model name");
> +    while (*buf_p != '@') buf_p++;
> +
> +    buf_p += 2;
> +    memcpy(buf, buf_p, 12);
> +    buf_p = buf;
> +    while ((*buf_p >= '0') && (*buf_p <= '9')) buf_p++;
> +    *buf_p = '\0';
> +
> +    freq = atoi(buf);
> +
> +    return freq * 1000 * 1000;
> +}
> +
> +static struct efi_cpuinfo_loongson *init_cpu_info(void *g_cpuinfo_loongson)
> +{
> +    struct efi_cpuinfo_loongson *c = g_cpuinfo_loongson;
> +
> +    c->cputype  = Loongson_3A;
> +    c->processor_id = 0x14C000;
> +    c->cpu_clock_freq = get_host_cpu_freq();
> +    if (!c->cpu_clock_freq)
> +        c->cpu_clock_freq = 400000000;
> +
> +    c->cpu_startup_core_id = 0;
> +    c->nr_cpus = current_machine->smp.cpus;
> +    c->total_node = (current_machine->smp.cpus + 3) / 4;
> +
> +    return c;
> +}
> +
> +static struct system_loongson *init_system_loongson(void *g_system)
> +{
> +    struct system_loongson *s = g_system;
> +
> +    s->ccnuma_smp = 0;
> +    s->sing_double_channel = 1;
> +    s->nr_uarts = 1;
> +    s->uarts[0].iotype = 2;
> +    s->uarts[0].int_offset = 2;
> +    s->uarts[0].uartclk = 25000000;
> +    s->uarts[0].uart_base = 0x1fe001e0;
> +
> +    return s;
> +}
> +
> +static struct irq_source_routing_table *init_irq_source(void *g_irq_source)
> +{
> +    struct irq_source_routing_table *irq_info = g_irq_source;
> +
> +    irq_info->node_id = 0;
> +    irq_info->PIC_type = 0;
> +    irq_info->dma_mask_bits = 64;
> +    irq_info->pci_mem_start_addr = VIRT_PCI_MEM_BASE;
> +    irq_info->pci_mem_end_addr   = VIRT_PCI_MEM_BASE + VIRT_PCI_MEM_SIZE - 1;
> +    irq_info->pci_io_start_addr  = VIRT_PCI_IO_BASE;
> +
> +    return irq_info;
> +}
> +
> +static struct interface_info *init_interface_info(void *g_interface)
> +{
> +    struct interface_info *interface = g_interface;
> +
> +    interface->vers = 0x01;
> +    strcpy(interface->description, "UEFI_Version_v1.0");
> +
> +    return interface;
> +}
> +
> +static struct board_devices *board_devices_info(void *g_board)
> +{
> +    struct board_devices *bd = g_board;
> +
> +    strcpy(bd->name, "Loongson-3A-VIRT-1w-V1.00-demo");
> +
> +    return bd;
> +}
> +
> +static struct loongson_special_attribute *init_special_info(void *g_special)
> +{
> +    struct loongson_special_attribute *special = g_special;
> +
> +    strcpy(special->special_name, "2015-04-17");
> +
> +    return special;
> +}
> +
> +static void init_loongson_params(struct loongson_params *lp)
> +{
> +    void *p = boot_params_p;
> +
> +    lp->memory_offset = (unsigned long long)init_memory_map(p)
> +                        - (unsigned long long)lp;
> +    p += align(sizeof(struct efi_memory_map_loongson));
> +
> +    lp->cpu_offset = (unsigned long long)init_cpu_info(p)
> +                     - (unsigned long long)lp;
> +    p += align(sizeof(struct efi_cpuinfo_loongson));
> +
> +    lp->system_offset = (unsigned long long)init_system_loongson(p)
> +                        - (unsigned long long)lp;
> +    p += align(sizeof(struct system_loongson));
> +
> +    lp->irq_offset = (unsigned long long)init_irq_source(p)
> +                     - (unsigned long long)lp;
> +    p += align(sizeof(struct irq_source_routing_table));
> +
> +    lp->interface_offset = (unsigned long long)init_interface_info(p)
> +                           - (unsigned long long)lp;
> +    p += align(sizeof(struct interface_info));
> +
> +    lp->boarddev_table_offset = (unsigned long long)board_devices_info(p)
> +                                - (unsigned long long)lp;
> +    p+= align(sizeof(struct board_devices));
> +
> +    lp->special_offset = (unsigned long long)init_special_info(p)
> +                         - (unsigned long long)lp;
> +    p+= align(sizeof(struct loongson_special_attribute));
> +
> +    boot_params_p = p;
> +}
> +
> +static void init_smbios(struct smbios_tables *smbios)
> +{
> +    smbios->vers = 1;
> +    init_loongson_params(&(smbios->lp));
> +}
> +
> +static void init_efi(struct efi_loongson *efi)
> +{
> +    init_smbios(&(efi->smbios));
> +}
> +
> +static void init_reset_system(struct efi_reset_system_t *reset)
> +{
> +    reset->Shutdown = 0xffffffffbfc000b0;
> +    reset->ResetCold = 0xffffffffbfc00088;
> +    reset->ResetWarm = 0xffffffffbfc00088;
> +}
> +
> +static int init_boot_param(struct boot_params *bp)
> +{
> +    init_efi(&(bp->efi));
> +    init_reset_system(&(bp->reset_system));
> +
> +    return 0;
> +}
> +
> +static void fw_cfg_boot_set(void *opaque, const char *boot_device,
> +                            Error **errp)
> +{
> +    fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
> +}
> +
> +static void fw_conf_init(unsigned long ram_size)
> +{
> +    FWCfgState *fw_cfg;
> +
> +    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);
> +    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
> +
> +    fw_config.ram_size = ram_size;
> +    fw_config.mem_freq = 300000000;
> +    fw_config.nr_cpus = current_machine->smp.cpus;
> +    fw_config.cpu_clock_freq = get_host_cpu_freq();
> +}
> +
> +static int set_prom_bootparam(ram_addr_t initrd_offset, long initrd_size)
> +{
> +    long params_size;
> +    char memenv[32];
> +    char highmemenv[32];
> +    void *params_buf;
> +    unsigned int *parg_env;
> +    int ret = 0;
> +
> +    /* Allocate params_buf for command line. */
> +    params_size = 0x100000;
> +    params_buf = g_malloc0(params_size);
> +
> +    /*
> +     * Layout of params_buf looks like this:
> +     * argv[0], argv[1], 0, env[0], env[1], ... env[i], 0,
> +     * argv[0]'s data, argv[1]'s data, env[0]'data, ..., env[i]'s data, 0
> +     */
> +    parg_env = (void *)params_buf;
> +
> +    ret = (3 + 1) * 4;
> +    *parg_env++ = (BOOTPARAM_ADDR + ret);
> +    ret += (1 + snprintf(params_buf + ret, 256 - ret, "g"));
> +
> +    /* argv1 */
> +    *parg_env++ = BOOTPARAM_ADDR + ret;
> +    if (initrd_size > 0)
> +        ret += (1 + snprintf(params_buf + ret, 256 - ret,
> +                "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
> +                PHYS_TO_VIRT((uint32_t)initrd_offset),
> +                initrd_size, loaderparams.kernel_cmdline));
> +    else
> +        ret += (1 + snprintf(params_buf+ret, 256 - ret, "%s",
> +                loaderparams.kernel_cmdline));
> +
> +    /* argv2 */
> +    *parg_env++ = BOOTPARAM_ADDR + 4*ret;
> +
> +    /* env */
> +    sprintf(memenv, "%ld", loaderparams.ram_size > 0x10000000
> +            ? 256 : (loaderparams.ram_size >> 20));
> +    sprintf(highmemenv, "%ld", loaderparams.ram_size > 0x10000000
> +            ? (loaderparams.ram_size >> 20) - 256 : 0);
> +
> +    setenv("memsize", memenv, 1);
> +    setenv("highmemsize", highmemenv, 1);
> +
> +    ret = ((ret + 32) & ~31);
> +
> +    boot_params_buf = (void *)(params_buf + ret);
> +    boot_params_p = boot_params_buf + align(sizeof(struct boot_params));
> +
> +    init_boot_param(boot_params_buf);
> +
> +    rom_add_blob_fixed("params", params_buf, params_size,
> +                       BOOTPARAM_PHYADDR);
> +    loaderparams.a0 = 2;
> +    loaderparams.a1 = 0xffffffff80000000ULL + BOOTPARAM_PHYADDR;
> +    loaderparams.a2 = 0xffffffff80000000ULL + BOOTPARAM_PHYADDR + ret;
> +
> +    return 0;
> +}
> +
> +static int64_t load_kernel(CPUMIPSState *env)
> +{
> +    long kernel_size;
> +    ram_addr_t initrd_offset;
> +    int64_t kernel_entry, kernel_low, kernel_high, initrd_size;
> +
> +    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);
> +    if (kernel_size < 0) {
> +        error_report("could not load kernel '%s': %s",
> +                     loaderparams.kernel_filename,
> +                     load_elf_strerror(kernel_size));
> +        exit(1);
> +    }
> +
> +    /* load initrd */
> +    initrd_size = 0;
> +    initrd_offset = 0;
> +    if (loaderparams.initrd_filename) {
> +        initrd_size = get_image_size(loaderparams.initrd_filename);
> +        if (initrd_size > 0) {
> +            initrd_offset = (kernel_high + ~INITRD_PAGE_MASK) &
> +                            INITRD_PAGE_MASK;
> +            initrd_offset = MAX(initrd_offset, INITRD_OFFSET);
> +
> +            if (initrd_offset + initrd_size > ram_size) {
> +                error_report("memory too small for initial ram disk '%s'",
> +                             loaderparams.initrd_filename);
> +                exit(1);
> +            }
> +
> +            initrd_size = load_image_targphys(loaderparams.initrd_filename,
> +                                              initrd_offset,
> +                                              ram_size - initrd_offset);
> +        }
> +
> +        if (initrd_size == (target_ulong) -1) {
> +            error_report("could not load initial ram disk '%s'",
> +                         loaderparams.initrd_filename);
> +            exit(1);
> +        }
> +    }
> +
> +    /* Setup prom parameters. */
> +    set_prom_bootparam(initrd_offset, initrd_size);
> +
> +    return kernel_entry;
> +}
> +
> +static void main_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 loongson3_isa_init(qemu_irq intc)
> +{
> +    qemu_irq *i8259;
> +    ISABus *isa_bus;
> +
> +    isa_bus = isa_bus_new(NULL, get_system_memory(), get_system_io(), &error_abort);
> +
> +    /* Interrupt controller */
> +    /* The 8259 -> IP3  */
> +    i8259 = i8259_init(isa_bus, intc);
> +    isa_bus_irqs(isa_bus, i8259);
> +    /* init other devices */
> +    isa_create_simple(isa_bus, "i8042");
> +    mc146818_rtc_init(isa_bus, 2000, NULL);
> +}
> +
> +static inline void loongson3_pcie_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_create(NULL, TYPE_GPEX_HOST);
> +
> +    qdev_init_nofail(dev);
> +    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_PCI_ECAM_SIZE);
> +    memory_region_add_subregion(get_system_memory(), VIRT_PCI_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_PCI_MEM_BASE, VIRT_PCI_MEM_SIZE);
> +    memory_region_add_subregion(get_system_memory(), VIRT_PCI_MEM_BASE, mmio_alias);
> +
> +    pio_alias = g_new0(MemoryRegion, 1);
> +    memory_region_init_alias(pio_alias, OBJECT(dev), "pcie-pio",
> +                             get_system_io(), 0, VIRT_PCI_IO_SIZE);
> +    memory_region_add_subregion(get_system_memory(), VIRT_PCI_IO_BASE, pio_alias);
> +    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, VIRT_PCI_IO_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);
> +
> +    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_init(MachineState *machine)
> +{
> +    int i;
> +    long bios_size;
> +    MIPSCPU *cpu;
> +    CPUMIPSState *env;
> +    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);
> +
> +    if (ram_size < 256 * 0x100000) {
> +        error_report("Loongson-3 need at least 256MB memory");
> +        exit(1);
> +    }
> +
> +    for (i = 0; i < machine->smp.cpus; i++) {
> +        /* init CPUs */
> +        cpu = MIPS_CPU(cpu_create(machine->cpu_type));
> +
> +        /* Init internal devices */
> +        cpu_mips_irq_init_cpu(cpu);
> +        cpu_mips_clock_init(cpu);
> +        qemu_register_reset(main_cpu_reset, cpu);
> +    }
> +    env = &MIPS_CPU(first_cpu)->env;
> +
> +    /* Allocate RAM/BIOS, 0x00000000~0x10000000 is alias of 0x80000000~0x90000000 */
> +    memory_region_init_rom(bios, NULL, "loongson3.bios", BIOS_SIZE, &error_fatal);
> +    memory_region_init_alias(ram, NULL, "loongson3.lowram", machine->ram, 0, 256 * 0x100000);
> +    memory_region_init_io(iomem, NULL, &loongson3_pm_ops, NULL, "loongson3_pm", PM_MMIO_SIZE);
> +
> +    memory_region_add_subregion(address_space_mem, 0x00000000LL, ram);
> +    memory_region_add_subregion(address_space_mem, 0x1fc00000LL, bios);
> +    memory_region_add_subregion(address_space_mem, 0x80000000LL, machine->ram);
> +    memory_region_add_subregion(address_space_mem, PM_MMIO_ADDR, iomem);
> +
> +    /*
> +     * We do not support flash operation, just loading pmon.bin as raw BIOS.
> +     * Please use -L to set the BIOS path and -bios to set bios name.
> +     */
> +
> +    if (kernel_filename) {
> +        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);
> +        rom_add_blob_fixed("bios", bios_boot_code, sizeof(bios_boot_code), 0x1fc00000LL);
> +    } else {
> +        if (bios_name == NULL) {
> +                bios_name = LOONGSON3_BIOSNAME;
> +        }
> +        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
> +        if (filename) {
> +            bios_size = load_image_targphys(filename, 0x1fc00000LL,
> +                                            BIOS_SIZE);
> +            g_free(filename);
> +        } else {
> +            bios_size = -1;
> +        }
> +
> +        if ((bios_size < 0 || bios_size > BIOS_SIZE) &&
> +            !kernel_filename && !qtest_enabled()) {
> +            error_report("Could not load MIPS bios '%s'", bios_name);
> +            exit(1);
> +        }
> +
> +        fw_conf_init(ram_size);
> +        rom_add_blob_fixed("fw_conf", (void*)&fw_config, sizeof(fw_config), FW_CONF_ADDR);
> +    }
> +
> +    msi_nonbroken = true;
> +    loongson3_isa_init(env->irq[3]);
> +    loongson3_pcie_init(machine, isa_pic);
> +
> +    if (serial_hd(0))
> +        serial_mm_init(address_space_mem, 0x1fe001e0, 0, env->irq[2], 115200, serial_hd(0), DEVICE_NATIVE_ENDIAN);
> +}
> +
> +static void mips_loongson3_machine_init(MachineClass *mc)
> +{
> +    mc->desc = "Generic Loongson-3 Platform";
> +    mc->init = mips_loongson3_init;
> +    mc->block_default_type = IF_IDE;
> +    mc->max_cpus = LOONGSON_MAX_VCPUS;
> +    mc->default_cpu_type = MIPS_CPU_TYPE_NAME("Loongson-3A");
> +    mc->default_ram_id = "loongson3.highram";
> +    mc->default_ram_size = 784 * MiB;
> +    mc->kvm_type = mips_kvm_type;
> +    mc->minimum_page_bits = 14;
> +}
> +
> +DEFINE_MACHINE("loongson3", mips_loongson3_machine_init)
> --
> 2.7.0
>


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH for-5.1 5/7] target/mips: Add more CP0 register for save/restore
  2020-04-28 19:10   ` Aleksandar Markovic
@ 2020-04-29  1:11     ` Huacai Chen
  0 siblings, 0 replies; 30+ messages in thread
From: Huacai Chen @ 2020-04-29  1:11 UTC (permalink / raw)
  To: Aleksandar Markovic
  Cc: Huacai Chen, Philippe Mathieu-Daudé,
	Aurelien Jarno, QEMU Developers

Hi, Aleksandar,

On Wed, Apr 29, 2020 at 3:10 AM Aleksandar Markovic
<aleksandar.qemu.devel@gmail.com> wrote:
>
> пон, 27. апр 2020. у 11:36 Huacai Chen <zltjiangshi@gmail.com> је написао/ла:
> >
> > Add more CP0 register for save/restore, including: EBase, XContext,
> > PageGrain, PWBase, PWSize, PWField, PWCtl, Config*, KScratch1~KScratch6.
> >
> > Signed-off-by: Huacai Chen <chenhc@lemote.com>
> > Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> > ---
> >  target/mips/kvm.c     | 212 ++++++++++++++++++++++++++++++++++++++++++++++++++
> >  target/mips/machine.c |   2 +
> >  2 files changed, 214 insertions(+)
> >
> > diff --git a/target/mips/kvm.c b/target/mips/kvm.c
> > index de3e26e..96cfa10 100644
> > --- a/target/mips/kvm.c
> > +++ b/target/mips/kvm.c
> > @@ -245,10 +245,16 @@ int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level)
> >      (KVM_REG_MIPS_CP0 | KVM_REG_SIZE_U64 | (8 * (_R) + (_S)))
> >
> >  #define KVM_REG_MIPS_CP0_INDEX          MIPS_CP0_32(0, 0)
> > +#define KVM_REG_MIPS_CP0_RANDOM         MIPS_CP0_32(1, 0)
> >  #define KVM_REG_MIPS_CP0_CONTEXT        MIPS_CP0_64(4, 0)
> >  #define KVM_REG_MIPS_CP0_USERLOCAL      MIPS_CP0_64(4, 2)
> >  #define KVM_REG_MIPS_CP0_PAGEMASK       MIPS_CP0_32(5, 0)
> > +#define KVM_REG_MIPS_CP0_PAGEGRAIN      MIPS_CP0_32(5, 1)
> > +#define KVM_REG_MIPS_CP0_PWBASE         MIPS_CP0_64(5, 5)
> > +#define KVM_REG_MIPS_CP0_PWFIELD        MIPS_CP0_64(5, 6)
> > +#define KVM_REG_MIPS_CP0_PWSIZE         MIPS_CP0_64(5, 7)
> >  #define KVM_REG_MIPS_CP0_WIRED          MIPS_CP0_32(6, 0)
> > +#define KVM_REG_MIPS_CP0_PWCTL          MIPS_CP0_32(6, 6)
> >  #define KVM_REG_MIPS_CP0_HWRENA         MIPS_CP0_32(7, 0)
> >  #define KVM_REG_MIPS_CP0_BADVADDR       MIPS_CP0_64(8, 0)
> >  #define KVM_REG_MIPS_CP0_COUNT          MIPS_CP0_32(9, 0)
> > @@ -258,13 +264,22 @@ int kvm_mips_set_ipi_interrupt(MIPSCPU *cpu, int irq, int level)
> >  #define KVM_REG_MIPS_CP0_CAUSE          MIPS_CP0_32(13, 0)
> >  #define KVM_REG_MIPS_CP0_EPC            MIPS_CP0_64(14, 0)
> >  #define KVM_REG_MIPS_CP0_PRID           MIPS_CP0_32(15, 0)
> > +#define KVM_REG_MIPS_CP0_EBASE          MIPS_CP0_64(15, 1)
> >  #define KVM_REG_MIPS_CP0_CONFIG         MIPS_CP0_32(16, 0)
> >  #define KVM_REG_MIPS_CP0_CONFIG1        MIPS_CP0_32(16, 1)
> >  #define KVM_REG_MIPS_CP0_CONFIG2        MIPS_CP0_32(16, 2)
> >  #define KVM_REG_MIPS_CP0_CONFIG3        MIPS_CP0_32(16, 3)
> >  #define KVM_REG_MIPS_CP0_CONFIG4        MIPS_CP0_32(16, 4)
> >  #define KVM_REG_MIPS_CP0_CONFIG5        MIPS_CP0_32(16, 5)
> > +#define KVM_REG_MIPS_CP0_CONFIG6        MIPS_CP0_32(16, 6)
> > +#define KVM_REG_MIPS_CP0_XCONTEXT       MIPS_CP0_64(20, 0)
> >  #define KVM_REG_MIPS_CP0_ERROREPC       MIPS_CP0_64(30, 0)
> > +#define KVM_REG_MIPS_CP0_KSCRATCH1      MIPS_CP0_64(31, 2)
> > +#define KVM_REG_MIPS_CP0_KSCRATCH2      MIPS_CP0_64(31, 3)
> > +#define KVM_REG_MIPS_CP0_KSCRATCH3      MIPS_CP0_64(31, 4)
> > +#define KVM_REG_MIPS_CP0_KSCRATCH4      MIPS_CP0_64(31, 5)
> > +#define KVM_REG_MIPS_CP0_KSCRATCH5      MIPS_CP0_64(31, 6)
> > +#define KVM_REG_MIPS_CP0_KSCRATCH6      MIPS_CP0_64(31, 7)
> >
> >  static inline int kvm_mips_put_one_reg(CPUState *cs, uint64_t reg_id,
> >                                         int32_t *addr)
> > @@ -394,6 +409,29 @@ static inline int kvm_mips_get_one_ureg64(CPUState *cs, uint64_t reg_id,
> >                                           (1U << CP0C5_UFE) | \
> >                                           (1U << CP0C5_FRE) | \
> >                                           (1U << CP0C5_UFR))
> > +#define KVM_REG_MIPS_CP0_CONFIG6_MASK   ((1U << CP0C6_BPPASS) | \
> > +                                         (0x3fU << CP0C6_KPOS) | \
> > +                                         (1U << CP0C6_KE) | \
> > +                                         (1U << CP0C6_VTLBONLY) | \
> > +                                         (1U << CP0C6_LASX) | \
> > +                                         (1U << CP0C6_SSEN) | \
> > +                                         (1U << CP0C6_DISDRTIME) | \
> > +                                         (1U << CP0C6_PIXNUEN) | \
> > +                                         (1U << CP0C6_SCRAND) | \
> > +                                         (1U << CP0C6_LLEXCEN) | \
> > +                                         (1U << CP0C6_DISVC) | \
> > +                                         (1U << CP0C6_VCLRU) | \
> > +                                         (1U << CP0C6_DCLRU) | \
> > +                                         (1U << CP0C6_PIXUEN) | \
> > +                                         (1U << CP0C6_DISBLKLYEN) | \
> > +                                         (1U << CP0C6_UMEMUALEN) | \
> > +                                         (1U << CP0C6_SFBEN) | \
> > +                                         (1U << CP0C6_FLTINT) | \
> > +                                         (1U << CP0C6_VLTINT) | \
> > +                                         (1U << CP0C6_DISBTB) | \
> > +                                         (3U << CP0C6_STPREFCTL) | \
> > +                                         (1U << CP0C6_INSTPREF) | \
> > +                                         (1U << CP0C6_DATAPREF))
> >
> >  static inline int kvm_mips_change_one_reg(CPUState *cs, uint64_t reg_id,
> >                                            int32_t *addr, int32_t mask)
> > @@ -729,6 +767,11 @@ static int kvm_mips_put_cp0_registers(CPUState *cs, int level)
> >          DPRINTF("%s: Failed to put CP0_INDEX (%d)\n", __func__, err);
> >          ret = err;
> >      }
> > +    err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_RANDOM, &env->CP0_Random);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to put CP0_RANDOM (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> >      err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT,
> >                                   &env->CP0_Context);
> >      if (err < 0) {
> > @@ -747,11 +790,40 @@ static int kvm_mips_put_cp0_registers(CPUState *cs, int level)
> >          DPRINTF("%s: Failed to put CP0_PAGEMASK (%d)\n", __func__, err);
> >          ret = err;
> >      }
> > +    err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PAGEGRAIN,
> > +                               &env->CP0_PageGrain);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to put CP0_PAGEGRAIN (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> > +    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWBASE,
> > +                               &env->CP0_PWBase);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to put CP0_PWBASE (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> > +    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWFIELD,
> > +                               &env->CP0_PWField);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to put CP0_PWField (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> > +    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_PWSIZE,
> > +                               &env->CP0_PWSize);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to put CP0_PWSIZE (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> >      err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired);
> >      if (err < 0) {
> >          DPRINTF("%s: Failed to put CP0_WIRED (%d)\n", __func__, err);
> >          ret = err;
> >      }
> > +    err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_PWCTL, &env->CP0_PWCtl);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to put CP0_PWCTL (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> >      err = kvm_mips_put_one_reg(cs, KVM_REG_MIPS_CP0_HWRENA, &env->CP0_HWREna);
> >      if (err < 0) {
> >          DPRINTF("%s: Failed to put CP0_HWRENA (%d)\n", __func__, err);
> > @@ -799,6 +871,11 @@ static int kvm_mips_put_cp0_registers(CPUState *cs, int level)
> >          DPRINTF("%s: Failed to put CP0_PRID (%d)\n", __func__, err);
> >          ret = err;
> >      }
> > +    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_EBASE, &env->CP0_EBase);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to put CP0_EBASE (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> >      err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG,
> >                                    &env->CP0_Config0,
> >                                    KVM_REG_MIPS_CP0_CONFIG_MASK);
> > @@ -841,12 +918,61 @@ static int kvm_mips_put_cp0_registers(CPUState *cs, int level)
> >          DPRINTF("%s: Failed to change CP0_CONFIG5 (%d)\n", __func__, err);
> >          ret = err;
> >      }
> > +    err = kvm_mips_change_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG6,
> > +                                  &env->CP0_Config6,
> > +                                  KVM_REG_MIPS_CP0_CONFIG6_MASK);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to change CP0_CONFIG6 (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> > +    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_XCONTEXT,
> > +                                 &env->CP0_XContext);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to put CP0_XCONTEXT (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> >      err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
> >                                   &env->CP0_ErrorEPC);
> >      if (err < 0) {
> >          DPRINTF("%s: Failed to put CP0_ERROREPC (%d)\n", __func__, err);
> >          ret = err;
> >      }
> > +    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH1,
> > +                                 &env->CP0_KScratch[0]);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to put CP0_KSCRATCH1 (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> > +    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH2,
> > +                                 &env->CP0_KScratch[1]);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to put CP0_KSCRATCH2 (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> > +    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH3,
> > +                                 &env->CP0_KScratch[2]);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to put CP0_KSCRATCH3 (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> > +    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH4,
> > +                                 &env->CP0_KScratch[3]);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to put CP0_KSCRATCH4 (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> > +    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH5,
> > +                                 &env->CP0_KScratch[4]);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to put CP0_KSCRATCH5 (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> > +    err = kvm_mips_put_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH6,
> > +                                 &env->CP0_KScratch[5]);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to put CP0_KSCRATCH6 (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> >
> >      return ret;
> >  }
> > @@ -862,6 +988,11 @@ static int kvm_mips_get_cp0_registers(CPUState *cs)
> >          DPRINTF("%s: Failed to get CP0_INDEX (%d)\n", __func__, err);
> >          ret = err;
> >      }
> > +    err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_RANDOM, &env->CP0_Random);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to get CP0_RANDOM (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> >      err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_CONTEXT,
> >                                   &env->CP0_Context);
> >      if (err < 0) {
> > @@ -880,11 +1011,40 @@ static int kvm_mips_get_cp0_registers(CPUState *cs)
> >          DPRINTF("%s: Failed to get CP0_PAGEMASK (%d)\n", __func__, err);
> >          ret = err;
> >      }
> > +    err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PAGEGRAIN,
> > +                               &env->CP0_PageGrain);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to get CP0_PAGEGRAIN (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> > +    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWBASE,
> > +                               &env->CP0_PWBase);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to get CP0_PWBASE (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> > +    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWFIELD,
> > +                               &env->CP0_PWField);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to get CP0_PWFIELD (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> > +    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_PWSIZE,
> > +                               &env->CP0_PWSize);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to get CP0_PWSIZE (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> >      err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_WIRED, &env->CP0_Wired);
> >      if (err < 0) {
> >          DPRINTF("%s: Failed to get CP0_WIRED (%d)\n", __func__, err);
> >          ret = err;
> >      }
> > +    err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_PWCTL, &env->CP0_PWCtl);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to get CP0_PWCtl (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> >      err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_HWRENA, &env->CP0_HWREna);
> >      if (err < 0) {
> >          DPRINTF("%s: Failed to get CP0_HWRENA (%d)\n", __func__, err);
> > @@ -932,6 +1092,11 @@ static int kvm_mips_get_cp0_registers(CPUState *cs)
> >          DPRINTF("%s: Failed to get CP0_PRID (%d)\n", __func__, err);
> >          ret = err;
> >      }
> > +    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_EBASE, &env->CP0_EBase);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to get CP0_EBASE (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> >      err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG, &env->CP0_Config0);
> >      if (err < 0) {
> >          DPRINTF("%s: Failed to get CP0_CONFIG (%d)\n", __func__, err);
> > @@ -962,12 +1127,59 @@ static int kvm_mips_get_cp0_registers(CPUState *cs)
> >          DPRINTF("%s: Failed to get CP0_CONFIG5 (%d)\n", __func__, err);
> >          ret = err;
> >      }
> > +    err = kvm_mips_get_one_reg(cs, KVM_REG_MIPS_CP0_CONFIG6, &env->CP0_Config6);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to get CP0_CONFIG6 (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> > +    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_XCONTEXT,
> > +                                 &env->CP0_XContext);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to get CP0_XCONTEXT (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> >      err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_ERROREPC,
> >                                   &env->CP0_ErrorEPC);
> >      if (err < 0) {
> >          DPRINTF("%s: Failed to get CP0_ERROREPC (%d)\n", __func__, err);
> >          ret = err;
> >      }
> > +    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH1,
> > +                                 &env->CP0_KScratch[0]);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to get CP0_KSCRATCH1 (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> > +    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH2,
> > +                                 &env->CP0_KScratch[1]);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to get CP0_KSCRATCH2 (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> > +    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH3,
> > +                                 &env->CP0_KScratch[2]);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to get CP0_KSCRATCH3 (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> > +    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH4,
> > +                                 &env->CP0_KScratch[3]);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to get CP0_KSCRATCH4 (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> > +    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH5,
> > +                                 &env->CP0_KScratch[4]);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to get CP0_KSCRATCH5 (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> > +    err = kvm_mips_get_one_ulreg(cs, KVM_REG_MIPS_CP0_KSCRATCH6,
> > +                                 &env->CP0_KScratch[5]);
> > +    if (err < 0) {
> > +        DPRINTF("%s: Failed to get CP0_KSCRATCH6 (%d)\n", __func__, err);
> > +        ret = err;
> > +    }
> >
> >      return ret;
> >  }
> > diff --git a/target/mips/machine.c b/target/mips/machine.c
> > index 8d5b18b..a84aefc 100644
> > --- a/target/mips/machine.c
> > +++ b/target/mips/machine.c
> > @@ -289,6 +289,8 @@ const VMStateDescription vmstate_mips_cpu = {
> >          VMSTATE_INT32(env.CP0_Config1, MIPSCPU),
> >          VMSTATE_INT32(env.CP0_Config2, MIPSCPU),
> >          VMSTATE_INT32(env.CP0_Config3, MIPSCPU),
> > +        VMSTATE_INT32(env.CP0_Config4, MIPSCPU),
> > +        VMSTATE_INT32(env.CP0_Config5, MIPSCPU),
> >          VMSTATE_INT32(env.CP0_Config6, MIPSCPU),
> >          VMSTATE_INT32(env.CP0_Config7, MIPSCPU),
> >          VMSTATE_UINT64(env.CP0_LLAddr, MIPSCPU),
> > --
> > 2.7.0
> >
>
> Huacai,
>
> You need to bump two fields in VMStateDescription any time you add new fields.
>
> This means two instances of "19" should be changed to "20" here:
>
> const VMStateDescription vmstate_mips_cpu = {
> .name = "cpu",
> .version_id = 19,
> .minimum_version_id = 19,
> .post_load = cpu_post_load,
> .fields = (VMStateField[]) {
>
OK, this will be fixed in V2.

> Thanks,
> Aleksandar


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH for-5.1 6/7] hw/mips: Add Loongson-3 machine support (with KVM)
  2020-04-28 19:23   ` Aleksandar Markovic
@ 2020-04-29  1:13     ` Huacai Chen
  0 siblings, 0 replies; 30+ messages in thread
From: Huacai Chen @ 2020-04-29  1:13 UTC (permalink / raw)
  To: Aleksandar Markovic
  Cc: Huacai Chen, Philippe Mathieu-Daudé,
	Aurelien Jarno, QEMU Developers

Hi, Aleksandr,

On Wed, Apr 29, 2020 at 3:23 AM Aleksandar Markovic
<aleksandar.qemu.devel@gmail.com> wrote:
>
> Hi. Huacei.
>
> Please expand commit message with the description of the machine
> internal organization (several paragraphs).
>
> Also, please include command line for starting the machine. More than
> one example is better than only one.
>
> Specifically, can you explicitly say what is your KVM setup, so that
> anyone could repro it?
>
> Good health to people from China!
>
Thank you very much, I will improve that in V2.

> Yours,
> Aleksandar
>
> пон, 27. апр 2020. у 11:36 Huacai Chen <zltjiangshi@gmail.com> је написао/ла:
> >
> > Add Loongson-3 based machine support, it use i8259 as the interrupt
> > controler and use GPEX as the pci controller. Currently it can only
> > work with KVM, but we will add TCG support in future.
> >
> > Signed-off-by: Huacai Chen <chenhc@lemote.com>
> > Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> > ---
> >  default-configs/mips64el-softmmu.mak |   1 +
> >  hw/mips/Kconfig                      |  10 +
> >  hw/mips/Makefile.objs                |   1 +
> >  hw/mips/mips_loongson3.c             | 869 +++++++++++++++++++++++++++++++++++
> >  4 files changed, 881 insertions(+)
> >  create mode 100644 hw/mips/mips_loongson3.c
> >
> > diff --git a/default-configs/mips64el-softmmu.mak b/default-configs/mips64el-softmmu.mak
> > index 8b0c9b1..fc798e4 100644
> > --- a/default-configs/mips64el-softmmu.mak
> > +++ b/default-configs/mips64el-softmmu.mak
> > @@ -3,6 +3,7 @@
> >  include mips-softmmu-common.mak
> >  CONFIG_IDE_VIA=y
> >  CONFIG_FULONG=y
> > +CONFIG_LOONGSON3=y
> >  CONFIG_ATI_VGA=y
> >  CONFIG_RTL8139_PCI=y
> >  CONFIG_JAZZ=y
> > diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig
> > index 2c2adbc..6f16b16 100644
> > --- a/hw/mips/Kconfig
> > +++ b/hw/mips/Kconfig
> > @@ -44,6 +44,16 @@ config JAZZ
> >  config FULONG
> >      bool
> >
> > +config LOONGSON3
> > +    bool
> > +    select PCKBD
> > +    select SERIAL
> > +    select ISA_BUS
> > +    select PCI_EXPRESS_GENERIC_BRIDGE
> > +    select VIRTIO_VGA
> > +    select QXL if SPICE
> > +    select MSI_NONBROKEN
> > +
> >  config MIPS_CPS
> >      bool
> >      select PTIMER
> > diff --git a/hw/mips/Makefile.objs b/hw/mips/Makefile.objs
> > index 2f7795b..f9bc8f5 100644
> > --- a/hw/mips/Makefile.objs
> > +++ b/hw/mips/Makefile.objs
> > @@ -4,5 +4,6 @@ obj-$(CONFIG_MALTA) += gt64xxx_pci.o mips_malta.o
> >  obj-$(CONFIG_MIPSSIM) += mips_mipssim.o
> >  obj-$(CONFIG_JAZZ) += mips_jazz.o
> >  obj-$(CONFIG_FULONG) += mips_fulong2e.o
> > +obj-$(CONFIG_LOONGSON3) += mips_loongson3.o
> >  obj-$(CONFIG_MIPS_CPS) += cps.o
> >  obj-$(CONFIG_MIPS_BOSTON) += boston.o
> > diff --git a/hw/mips/mips_loongson3.c b/hw/mips/mips_loongson3.c
> > new file mode 100644
> > index 0000000..a45c9ec
> > --- /dev/null
> > +++ b/hw/mips/mips_loongson3.c
> > @@ -0,0 +1,869 @@
> > +/*
> > + * Generic Loongson-3 Platform support
> > + *
> > + * Copyright (c) 2015-2020 Huacai Chen (chenhc@lemote.com)
> > + * This code is licensed under the GNU GPL v2.
> > + *
> > + * Contributions are licensed under the terms of the GNU GPL,
> > + * version 2 or (at your option) any later version.
> > + */
> > +
> > +/*
> > + * Generic PC Platform based on Loongson-3 CPU (MIPS64R2 with extensions,
> > + * 800~2000MHz)
> > + */
> > +
> > +#include "qemu/osdep.h"
> > +#include "qemu-common.h"
> > +#include "qemu/units.h"
> > +#include "qapi/error.h"
> > +#include "cpu.h"
> > +#include "elf.h"
> > +#include "hw/boards.h"
> > +#include "hw/block/flash.h"
> > +#include "hw/char/serial.h"
> > +#include "hw/mips/mips.h"
> > +#include "hw/mips/cpudevs.h"
> > +#include "hw/intc/i8259.h"
> > +#include "hw/loader.h"
> > +#include "hw/ide.h"
> > +#include "hw/isa/superio.h"
> > +#include "hw/pci/msi.h"
> > +#include "hw/pci/pci.h"
> > +#include "hw/pci/pci_host.h"
> > +#include "hw/pci-host/gpex.h"
> > +#include "hw/rtc/mc146818rtc.h"
> > +#include "net/net.h"
> > +#include "exec/address-spaces.h"
> > +#include "sysemu/qtest.h"
> > +#include "sysemu/reset.h"
> > +#include "sysemu/runstate.h"
> > +#include "qemu/log.h"
> > +#include "qemu/error-report.h"
> > +
> > +#define INITRD_OFFSET          0x04000000
> > +#define BOOTPARAM_ADDR         0x8ff00000
> > +#define BOOTPARAM_PHYADDR      0x0ff00000
> > +#define CFG_ADDR               0x0f100000
> > +#define FW_CONF_ADDR           0x0fff0000
> > +#define PM_MMIO_ADDR           0x10080000
> > +#define PM_MMIO_SIZE           0x100
> > +#define PM_CNTL_MODE           0x10
> > +
> > +#define PHYS_TO_VIRT(x) ((x) | ~(target_ulong)0x7fffffff)
> > +
> > +/* Loongson-3 has a 2MB flash rom */
> > +#define BIOS_SIZE               (2 * MiB)
> > +#define LOONGSON_MAX_VCPUS      16
> > +
> > +#define LOONGSON3_BIOSNAME "bios_loongson3.bin"
> > +
> > +#define PCIE_IRQ_BASE     3
> > +
> > +#define VIRT_PCI_IO_BASE    0x18000000ul
> > +#define VIRT_PCI_IO_SIZE    0x000c0000ul
> > +#define VIRT_PCI_MEM_BASE   0x40000000ul
> > +#define VIRT_PCI_MEM_SIZE   0x40000000ul
> > +#define VIRT_PCI_ECAM_BASE  0x1a000000ul
> > +#define VIRT_PCI_ECAM_SIZE  0x02000000ul
> > +
> > +#define align(x) (((x) + 63) & ~63)
> > +
> > +struct efi_memory_map_loongson {
> > +    uint16_t vers;               /* version of efi_memory_map */
> > +    uint32_t nr_map;             /* number of memory_maps */
> > +    uint32_t mem_freq;           /* memory frequence */
> > +    struct mem_map{
> > +        uint32_t node_id;        /* node_id which memory attached to */
> > +        uint32_t mem_type;       /* system memory, pci memory, pci io, etc. */
> > +        uint64_t mem_start;      /* memory map start address */
> > +        uint32_t mem_size;       /* each memory_map size, not the total size */
> > +    } map[128];
> > +} __attribute__((packed));
> > +
> > +enum loongson_cpu_type {
> > +    Legacy_2E = 0x0,
> > +    Legacy_2F = 0x1,
> > +    Legacy_3A = 0x2,
> > +    Legacy_3B = 0x3,
> > +    Legacy_1A = 0x4,
> > +    Legacy_1B = 0x5,
> > +    Legacy_2G = 0x6,
> > +    Legacy_2H = 0x7,
> > +    Loongson_1A = 0x100,
> > +    Loongson_1B = 0x101,
> > +    Loongson_2E = 0x200,
> > +    Loongson_2F = 0x201,
> > +    Loongson_2G = 0x202,
> > +    Loongson_2H = 0x203,
> > +    Loongson_3A = 0x300,
> > +    Loongson_3B = 0x301
> > +};
> > +
> > +/*
> > + * Capability and feature descriptor structure for MIPS CPU
> > + */
> > +struct efi_cpuinfo_loongson {
> > +    uint16_t vers;               /* version of efi_cpuinfo_loongson */
> > +    uint32_t processor_id;       /* PRID, e.g. 6305, 6306 */
> > +    uint32_t cputype;            /* Loongson_3A/3B, etc. */
> > +    uint32_t total_node;         /* num of total numa nodes */
> > +    uint16_t cpu_startup_core_id;   /* Boot core id */
> > +    uint16_t reserved_cores_mask;
> > +    uint32_t cpu_clock_freq;     /* cpu_clock */
> > +    uint32_t nr_cpus;
> > +    char cpuname[64];
> > +} __attribute__((packed));
> > +
> > +#define MAX_UARTS 64
> > +struct uart_device {
> > +    uint32_t iotype; /* see include/linux/serial_core.h */
> > +    uint32_t uartclk;
> > +    uint32_t int_offset;
> > +    uint64_t uart_base;
> > +} __attribute__((packed));
> > +
> > +#define MAX_SENSORS 64
> > +#define SENSOR_TEMPER  0x00000001
> > +#define SENSOR_VOLTAGE 0x00000002
> > +#define SENSOR_FAN     0x00000004
> > +struct sensor_device {
> > +    char name[32];  /* a formal name */
> > +    char label[64]; /* a flexible description */
> > +    uint32_t type;       /* SENSOR_* */
> > +    uint32_t id;         /* instance id of a sensor-class */
> > +    uint32_t fan_policy; /* see arch/mips/include/asm/mach-loongson/loongson_hwmon.h */
> > +    uint32_t fan_percent;/* only for constant speed policy */
> > +    uint64_t base_addr;  /* base address of device registers */
> > +} __attribute__((packed));
> > +
> > +struct system_loongson {
> > +    uint16_t vers;               /* version of system_loongson */
> > +    uint32_t ccnuma_smp;         /* 0: no numa; 1: has numa */
> > +    uint32_t sing_double_channel;/* 1: single; 2: double */
> > +    uint32_t nr_uarts;
> > +    struct uart_device uarts[MAX_UARTS];
> > +    uint32_t nr_sensors;
> > +    struct sensor_device sensors[MAX_SENSORS];
> > +    char has_ec;
> > +    char ec_name[32];
> > +    uint64_t ec_base_addr;
> > +    char has_tcm;
> > +    char tcm_name[32];
> > +    uint64_t tcm_base_addr;
> > +    uint64_t workarounds; /* see workarounds.h */
> > +    uint64_t of_dtb_addr; /* NULL if not support */
> > +} __attribute__((packed));
> > +
> > +struct irq_source_routing_table {
> > +    uint16_t vers;
> > +    uint16_t size;
> > +    uint16_t rtr_bus;
> > +    uint16_t rtr_devfn;
> > +    uint32_t vendor;
> > +    uint32_t device;
> > +    uint32_t PIC_type;           /* conform use HT or PCI to route to CPU-PIC */
> > +    uint64_t ht_int_bit;         /* 3A: 1<<24; 3B: 1<<16 */
> > +    uint64_t ht_enable;          /* irqs used in this PIC */
> > +    uint32_t node_id;            /* node id: 0x0-0; 0x1-1; 0x10-2; 0x11-3 */
> > +    uint64_t pci_mem_start_addr;
> > +    uint64_t pci_mem_end_addr;
> > +    uint64_t pci_io_start_addr;
> > +    uint64_t pci_io_end_addr;
> > +    uint64_t pci_config_addr;
> > +    uint16_t dma_mask_bits;
> > +    uint16_t dma_noncoherent;
> > +} __attribute__((packed));
> > +
> > +struct interface_info {
> > +    uint16_t vers;               /* version of the specificition */
> > +    uint16_t size;
> > +    uint8_t  flag;
> > +    char description[64];
> > +} __attribute__((packed));
> > +
> > +#define MAX_RESOURCE_NUMBER 128
> > +struct resource_loongson {
> > +    uint64_t start;              /* resource start address */
> > +    uint64_t end;                /* resource end address */
> > +    char name[64];
> > +    uint32_t flags;
> > +};
> > +
> > +struct archdev_data {};          /* arch specific additions */
> > +
> > +struct board_devices {
> > +    char name[64];               /* hold the device name */
> > +    uint32_t num_resources;      /* number of device_resource */
> > +    /* for each device's resource */
> > +    struct resource_loongson resource[MAX_RESOURCE_NUMBER];
> > +    /* arch specific additions */
> > +    struct archdev_data archdata;
> > +};
> > +
> > +struct loongson_special_attribute {
> > +    uint16_t vers;               /* version of this special */
> > +    char special_name[64];       /* special_atribute_name */
> > +    uint32_t loongson_special_type; /* type of special device */
> > +    /* for each device's resource */
> > +    struct resource_loongson resource[MAX_RESOURCE_NUMBER];
> > +};
> > +
> > +struct loongson_params {
> > +    uint64_t memory_offset;      /* efi_memory_map_loongson struct offset */
> > +    uint64_t cpu_offset;         /* efi_cpuinfo_loongson struct offset */
> > +    uint64_t system_offset;      /* system_loongson struct offset */
> > +    uint64_t irq_offset;         /* irq_source_routing_table struct offset */
> > +    uint64_t interface_offset;   /* interface_info struct offset */
> > +    uint64_t special_offset;     /* loongson_special_attribute struct offset */
> > +    uint64_t boarddev_table_offset;  /* board_devices offset */
> > +};
> > +
> > +struct smbios_tables {
> > +    uint16_t vers;               /* version of smbios */
> > +    uint64_t vga_bios;           /* vga_bios address */
> > +    struct loongson_params lp;
> > +};
> > +
> > +struct efi_reset_system_t {
> > +    uint64_t ResetCold;
> > +    uint64_t ResetWarm;
> > +    uint64_t ResetType;
> > +    uint64_t Shutdown;
> > +    uint64_t DoSuspend; /* NULL if not support */
> > +};
> > +
> > +struct efi_loongson {
> > +    uint64_t mps;                /* MPS table */
> > +    uint64_t acpi;               /* ACPI table (IA64 ext 0.71) */
> > +    uint64_t acpi20;             /* ACPI table (ACPI 2.0) */
> > +    struct smbios_tables smbios; /* SM BIOS table */
> > +    uint64_t sal_systab;         /* SAL system table */
> > +    uint64_t boot_info;          /* boot info table */
> > +};
> > +
> > +struct boot_params {
> > +    struct efi_loongson efi;
> > +    struct efi_reset_system_t reset_system;
> > +};
> > +
> > +static struct _fw_config {
> > +    unsigned long ram_size;
> > +    unsigned int mem_freq;
> > +    unsigned int nr_cpus;
> > +    unsigned int cpu_clock_freq;
> > +} fw_config;
> > +
> > +static struct _loaderparams {
> > +    unsigned long ram_size;
> > +    const char *kernel_cmdline;
> > +    const char *kernel_filename;
> > +    const char *initrd_filename;
> > +    int64_t kernel_entry;
> > +    unsigned long a0, a1, a2;
> > +} loaderparams;
> > +
> > +static void *boot_params_p;
> > +static void *boot_params_buf;
> > +
> > +static unsigned int bios_boot_code[] = {
> > +    0x40086000,   /* mfc0    t0, CP0_STATUS                                        */
> > +    0x240900E2,   /* li      t1, 0x00e2       #{cu3,cu2,cu1,cu0,status_fr}<={0111} */
> > +    0x01094025,   /* or      t0, t0, t1                                            */
> > +    0x40886000,   /* mtc0    t0, CP0_STATUS                                        */
> > +    0x00000000,
> > +    0x40086000,   /* mfc0    t0, CP0_STATUS                                        */
> > +    0x3C090040,   /* lui     t1, 0x40         #bev                                 */
> > +    0x01094025,   /* or      t0, t0, t1                                            */
> > +    0x40886000,   /* mtc0    t0, CP0_STATUS                                        */
> > +    0x00000000,
> > +    0x40806800,   /* mtc0    zero, CP0_CAUSE                                       */
> > +    0x00000000,
> > +    0x400A7801,   /* mfc0    t2, $15, 1                                            */
> > +    0x314A00FF,   /* andi    t2, 0x0ff                                             */
> > +    0x3C089000,   /* dli     t0, 0x900000003ff01000                                */
> > +    0x00084438,
> > +    0x35083FF0,
> > +    0x00084438,
> > +    0x35081000,
> > +    0x314B0003,   /* andi    t3, t2, 0x3      #local cpuid                         */
> > +    0x000B5A00,   /* sll     t3, 8                                                 */
> > +    0x010B4025,   /* or      t0, t0, t3                                            */
> > +    0x314C000C,   /* andi    t4, t2, 0xc      #node id                             */
> > +    0x000C62BC,   /* dsll    t4, 42                                                */
> > +    0x010C4025,   /* or      t0, t0, t4                                            */
> > +                  /* waitforinit:                                                  */
> > +    0xDD020020,   /* ld      v0, FN_OFF(t0)   #FN_OFF 0x020                        */
> > +    0x1040FFFE,   /* beqz    v0, waitforinit                                       */
> > +    0x00000000,   /* nop                                                           */
> > +    0xDD1D0028,   /* ld      sp, SP_OFF(t0)   #FN_OFF 0x028                        */
> > +    0xDD1C0030,   /* ld      gp, GP_OFF(t0)   #FN_OFF 0x030                        */
> > +    0xDD050038,   /* ld      a1, A1_OFF(t0)   #FN_OFF 0x038                        */
> > +    0x00400008,   /* jr      v0               #byebye                              */
> > +    0x00000000,   /* nop                                                           */
> > +    0x1000FFFF,   /* 1:  b   1b                                                    */
> > +    0x00000000,   /* nop                                                           */
> > +
> > +                  /* Reset                                                         */
> > +    0x3C0C9000,   /* dli     t0, 0x9000000010080010                                */
> > +    0x358C0000,
> > +    0x000C6438,
> > +    0x358C1008,
> > +    0x000C6438,
> > +    0x358C0010,
> > +    0x240D0000,   /* li      t1, 0x00                                              */
> > +    0xA18D0000,   /* sb      t1, (t0)                                              */
> > +    0x1000FFFF,   /* 1:  b   1b                                                    */
> > +    0x00000000,   /* nop                                                           */
> > +
> > +                  /* Shutdown                                                      */
> > +    0x3C0C9000,   /* dli     t0, 0x9000000010080010                                */
> > +    0x358C0000,
> > +    0x000C6438,
> > +    0x358C1008,
> > +    0x000C6438,
> > +    0x358C0010,
> > +    0x240D00FF,   /* li      t1, 0xff                                              */
> > +    0xA18D0000,   /* sb      t1, (t0)                                              */
> > +    0x1000FFFF,   /* 1:  b   1b                                                    */
> > +    0x00000000    /* nop                                                           */
> > +};
> > +
> > +static uint64_t loongson3_pm_read(void *opaque, hwaddr addr, unsigned size)
> > +{
> > +    return 0;
> > +}
> > +
> > +static void loongson3_pm_write(void *opaque, hwaddr addr, uint64_t val,unsigned size)
> > +{
> > +    if (addr != PM_CNTL_MODE)
> > +        return;
> > +
> > +    switch (val) {
> > +    case 0x00:
> > +        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
> > +        return;
> > +    case 0xff:
> > +        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
> > +        return;
> > +    default:
> > +        return;
> > +    }
> > +}
> > +
> > +static const MemoryRegionOps loongson3_pm_ops = {
> > +    .read  = loongson3_pm_read,
> > +    .write = loongson3_pm_write,
> > +    .endianness = DEVICE_NATIVE_ENDIAN,
> > +};
> > +
> > +static struct efi_memory_map_loongson *init_memory_map(void *g_map)
> > +{
> > +    struct efi_memory_map_loongson *emap = g_map;
> > +
> > +    emap->nr_map = 2;
> > +    emap->mem_freq = 300000000;
> > +
> > +    emap->map[0].node_id = 0;
> > +    emap->map[0].mem_type = 1;
> > +    emap->map[0].mem_start = 0x0;
> > +    emap->map[0].mem_size = (loaderparams.ram_size > 0x10000000
> > +                            ? 256 : (loaderparams.ram_size >> 20)) - 16;
> > +
> > +    emap->map[1].node_id = 0;
> > +    emap->map[1].mem_type = 2;
> > +    emap->map[1].mem_start = 0x90000000;
> > +    emap->map[1].mem_size = (loaderparams.ram_size > 0x10000000
> > +                            ? (loaderparams.ram_size >> 20) - 256 : 0);
> > +
> > +    return emap;
> > +}
> > +
> > +static int get_host_cpu_freq(void)
> > +{
> > +    int fd = 0, freq = 0;
> > +    char buf[1024], *buf_p;
> > +
> > +    if ((fd = open("/proc/cpuinfo", O_RDONLY)) == -1) {
> > +        fprintf(stderr, "Failed to open /proc/cpuinfo!\n");
> > +        return 0;
> > +    }
> > +
> > +    if (read(fd, buf, 1024) < 0) {
> > +        close(fd);
> > +        fprintf(stderr, "Failed to read /proc/cpuinfo!\n");
> > +        return 0;
> > +    }
> > +    close(fd);
> > +
> > +    buf_p = strstr(buf, "model name");
> > +    while (*buf_p != '@') buf_p++;
> > +
> > +    buf_p += 2;
> > +    memcpy(buf, buf_p, 12);
> > +    buf_p = buf;
> > +    while ((*buf_p >= '0') && (*buf_p <= '9')) buf_p++;
> > +    *buf_p = '\0';
> > +
> > +    freq = atoi(buf);
> > +
> > +    return freq * 1000 * 1000;
> > +}
> > +
> > +static struct efi_cpuinfo_loongson *init_cpu_info(void *g_cpuinfo_loongson)
> > +{
> > +    struct efi_cpuinfo_loongson *c = g_cpuinfo_loongson;
> > +
> > +    c->cputype  = Loongson_3A;
> > +    c->processor_id = 0x14C000;
> > +    c->cpu_clock_freq = get_host_cpu_freq();
> > +    if (!c->cpu_clock_freq)
> > +        c->cpu_clock_freq = 400000000;
> > +
> > +    c->cpu_startup_core_id = 0;
> > +    c->nr_cpus = current_machine->smp.cpus;
> > +    c->total_node = (current_machine->smp.cpus + 3) / 4;
> > +
> > +    return c;
> > +}
> > +
> > +static struct system_loongson *init_system_loongson(void *g_system)
> > +{
> > +    struct system_loongson *s = g_system;
> > +
> > +    s->ccnuma_smp = 0;
> > +    s->sing_double_channel = 1;
> > +    s->nr_uarts = 1;
> > +    s->uarts[0].iotype = 2;
> > +    s->uarts[0].int_offset = 2;
> > +    s->uarts[0].uartclk = 25000000;
> > +    s->uarts[0].uart_base = 0x1fe001e0;
> > +
> > +    return s;
> > +}
> > +
> > +static struct irq_source_routing_table *init_irq_source(void *g_irq_source)
> > +{
> > +    struct irq_source_routing_table *irq_info = g_irq_source;
> > +
> > +    irq_info->node_id = 0;
> > +    irq_info->PIC_type = 0;
> > +    irq_info->dma_mask_bits = 64;
> > +    irq_info->pci_mem_start_addr = VIRT_PCI_MEM_BASE;
> > +    irq_info->pci_mem_end_addr   = VIRT_PCI_MEM_BASE + VIRT_PCI_MEM_SIZE - 1;
> > +    irq_info->pci_io_start_addr  = VIRT_PCI_IO_BASE;
> > +
> > +    return irq_info;
> > +}
> > +
> > +static struct interface_info *init_interface_info(void *g_interface)
> > +{
> > +    struct interface_info *interface = g_interface;
> > +
> > +    interface->vers = 0x01;
> > +    strcpy(interface->description, "UEFI_Version_v1.0");
> > +
> > +    return interface;
> > +}
> > +
> > +static struct board_devices *board_devices_info(void *g_board)
> > +{
> > +    struct board_devices *bd = g_board;
> > +
> > +    strcpy(bd->name, "Loongson-3A-VIRT-1w-V1.00-demo");
> > +
> > +    return bd;
> > +}
> > +
> > +static struct loongson_special_attribute *init_special_info(void *g_special)
> > +{
> > +    struct loongson_special_attribute *special = g_special;
> > +
> > +    strcpy(special->special_name, "2015-04-17");
> > +
> > +    return special;
> > +}
> > +
> > +static void init_loongson_params(struct loongson_params *lp)
> > +{
> > +    void *p = boot_params_p;
> > +
> > +    lp->memory_offset = (unsigned long long)init_memory_map(p)
> > +                        - (unsigned long long)lp;
> > +    p += align(sizeof(struct efi_memory_map_loongson));
> > +
> > +    lp->cpu_offset = (unsigned long long)init_cpu_info(p)
> > +                     - (unsigned long long)lp;
> > +    p += align(sizeof(struct efi_cpuinfo_loongson));
> > +
> > +    lp->system_offset = (unsigned long long)init_system_loongson(p)
> > +                        - (unsigned long long)lp;
> > +    p += align(sizeof(struct system_loongson));
> > +
> > +    lp->irq_offset = (unsigned long long)init_irq_source(p)
> > +                     - (unsigned long long)lp;
> > +    p += align(sizeof(struct irq_source_routing_table));
> > +
> > +    lp->interface_offset = (unsigned long long)init_interface_info(p)
> > +                           - (unsigned long long)lp;
> > +    p += align(sizeof(struct interface_info));
> > +
> > +    lp->boarddev_table_offset = (unsigned long long)board_devices_info(p)
> > +                                - (unsigned long long)lp;
> > +    p+= align(sizeof(struct board_devices));
> > +
> > +    lp->special_offset = (unsigned long long)init_special_info(p)
> > +                         - (unsigned long long)lp;
> > +    p+= align(sizeof(struct loongson_special_attribute));
> > +
> > +    boot_params_p = p;
> > +}
> > +
> > +static void init_smbios(struct smbios_tables *smbios)
> > +{
> > +    smbios->vers = 1;
> > +    init_loongson_params(&(smbios->lp));
> > +}
> > +
> > +static void init_efi(struct efi_loongson *efi)
> > +{
> > +    init_smbios(&(efi->smbios));
> > +}
> > +
> > +static void init_reset_system(struct efi_reset_system_t *reset)
> > +{
> > +    reset->Shutdown = 0xffffffffbfc000b0;
> > +    reset->ResetCold = 0xffffffffbfc00088;
> > +    reset->ResetWarm = 0xffffffffbfc00088;
> > +}
> > +
> > +static int init_boot_param(struct boot_params *bp)
> > +{
> > +    init_efi(&(bp->efi));
> > +    init_reset_system(&(bp->reset_system));
> > +
> > +    return 0;
> > +}
> > +
> > +static void fw_cfg_boot_set(void *opaque, const char *boot_device,
> > +                            Error **errp)
> > +{
> > +    fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
> > +}
> > +
> > +static void fw_conf_init(unsigned long ram_size)
> > +{
> > +    FWCfgState *fw_cfg;
> > +
> > +    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);
> > +    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
> > +
> > +    fw_config.ram_size = ram_size;
> > +    fw_config.mem_freq = 300000000;
> > +    fw_config.nr_cpus = current_machine->smp.cpus;
> > +    fw_config.cpu_clock_freq = get_host_cpu_freq();
> > +}
> > +
> > +static int set_prom_bootparam(ram_addr_t initrd_offset, long initrd_size)
> > +{
> > +    long params_size;
> > +    char memenv[32];
> > +    char highmemenv[32];
> > +    void *params_buf;
> > +    unsigned int *parg_env;
> > +    int ret = 0;
> > +
> > +    /* Allocate params_buf for command line. */
> > +    params_size = 0x100000;
> > +    params_buf = g_malloc0(params_size);
> > +
> > +    /*
> > +     * Layout of params_buf looks like this:
> > +     * argv[0], argv[1], 0, env[0], env[1], ... env[i], 0,
> > +     * argv[0]'s data, argv[1]'s data, env[0]'data, ..., env[i]'s data, 0
> > +     */
> > +    parg_env = (void *)params_buf;
> > +
> > +    ret = (3 + 1) * 4;
> > +    *parg_env++ = (BOOTPARAM_ADDR + ret);
> > +    ret += (1 + snprintf(params_buf + ret, 256 - ret, "g"));
> > +
> > +    /* argv1 */
> > +    *parg_env++ = BOOTPARAM_ADDR + ret;
> > +    if (initrd_size > 0)
> > +        ret += (1 + snprintf(params_buf + ret, 256 - ret,
> > +                "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
> > +                PHYS_TO_VIRT((uint32_t)initrd_offset),
> > +                initrd_size, loaderparams.kernel_cmdline));
> > +    else
> > +        ret += (1 + snprintf(params_buf+ret, 256 - ret, "%s",
> > +                loaderparams.kernel_cmdline));
> > +
> > +    /* argv2 */
> > +    *parg_env++ = BOOTPARAM_ADDR + 4*ret;
> > +
> > +    /* env */
> > +    sprintf(memenv, "%ld", loaderparams.ram_size > 0x10000000
> > +            ? 256 : (loaderparams.ram_size >> 20));
> > +    sprintf(highmemenv, "%ld", loaderparams.ram_size > 0x10000000
> > +            ? (loaderparams.ram_size >> 20) - 256 : 0);
> > +
> > +    setenv("memsize", memenv, 1);
> > +    setenv("highmemsize", highmemenv, 1);
> > +
> > +    ret = ((ret + 32) & ~31);
> > +
> > +    boot_params_buf = (void *)(params_buf + ret);
> > +    boot_params_p = boot_params_buf + align(sizeof(struct boot_params));
> > +
> > +    init_boot_param(boot_params_buf);
> > +
> > +    rom_add_blob_fixed("params", params_buf, params_size,
> > +                       BOOTPARAM_PHYADDR);
> > +    loaderparams.a0 = 2;
> > +    loaderparams.a1 = 0xffffffff80000000ULL + BOOTPARAM_PHYADDR;
> > +    loaderparams.a2 = 0xffffffff80000000ULL + BOOTPARAM_PHYADDR + ret;
> > +
> > +    return 0;
> > +}
> > +
> > +static int64_t load_kernel(CPUMIPSState *env)
> > +{
> > +    long kernel_size;
> > +    ram_addr_t initrd_offset;
> > +    int64_t kernel_entry, kernel_low, kernel_high, initrd_size;
> > +
> > +    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);
> > +    if (kernel_size < 0) {
> > +        error_report("could not load kernel '%s': %s",
> > +                     loaderparams.kernel_filename,
> > +                     load_elf_strerror(kernel_size));
> > +        exit(1);
> > +    }
> > +
> > +    /* load initrd */
> > +    initrd_size = 0;
> > +    initrd_offset = 0;
> > +    if (loaderparams.initrd_filename) {
> > +        initrd_size = get_image_size(loaderparams.initrd_filename);
> > +        if (initrd_size > 0) {
> > +            initrd_offset = (kernel_high + ~INITRD_PAGE_MASK) &
> > +                            INITRD_PAGE_MASK;
> > +            initrd_offset = MAX(initrd_offset, INITRD_OFFSET);
> > +
> > +            if (initrd_offset + initrd_size > ram_size) {
> > +                error_report("memory too small for initial ram disk '%s'",
> > +                             loaderparams.initrd_filename);
> > +                exit(1);
> > +            }
> > +
> > +            initrd_size = load_image_targphys(loaderparams.initrd_filename,
> > +                                              initrd_offset,
> > +                                              ram_size - initrd_offset);
> > +        }
> > +
> > +        if (initrd_size == (target_ulong) -1) {
> > +            error_report("could not load initial ram disk '%s'",
> > +                         loaderparams.initrd_filename);
> > +            exit(1);
> > +        }
> > +    }
> > +
> > +    /* Setup prom parameters. */
> > +    set_prom_bootparam(initrd_offset, initrd_size);
> > +
> > +    return kernel_entry;
> > +}
> > +
> > +static void main_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 loongson3_isa_init(qemu_irq intc)
> > +{
> > +    qemu_irq *i8259;
> > +    ISABus *isa_bus;
> > +
> > +    isa_bus = isa_bus_new(NULL, get_system_memory(), get_system_io(), &error_abort);
> > +
> > +    /* Interrupt controller */
> > +    /* The 8259 -> IP3  */
> > +    i8259 = i8259_init(isa_bus, intc);
> > +    isa_bus_irqs(isa_bus, i8259);
> > +    /* init other devices */
> > +    isa_create_simple(isa_bus, "i8042");
> > +    mc146818_rtc_init(isa_bus, 2000, NULL);
> > +}
> > +
> > +static inline void loongson3_pcie_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_create(NULL, TYPE_GPEX_HOST);
> > +
> > +    qdev_init_nofail(dev);
> > +    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_PCI_ECAM_SIZE);
> > +    memory_region_add_subregion(get_system_memory(), VIRT_PCI_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_PCI_MEM_BASE, VIRT_PCI_MEM_SIZE);
> > +    memory_region_add_subregion(get_system_memory(), VIRT_PCI_MEM_BASE, mmio_alias);
> > +
> > +    pio_alias = g_new0(MemoryRegion, 1);
> > +    memory_region_init_alias(pio_alias, OBJECT(dev), "pcie-pio",
> > +                             get_system_io(), 0, VIRT_PCI_IO_SIZE);
> > +    memory_region_add_subregion(get_system_memory(), VIRT_PCI_IO_BASE, pio_alias);
> > +    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, VIRT_PCI_IO_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);
> > +
> > +    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_init(MachineState *machine)
> > +{
> > +    int i;
> > +    long bios_size;
> > +    MIPSCPU *cpu;
> > +    CPUMIPSState *env;
> > +    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);
> > +
> > +    if (ram_size < 256 * 0x100000) {
> > +        error_report("Loongson-3 need at least 256MB memory");
> > +        exit(1);
> > +    }
> > +
> > +    for (i = 0; i < machine->smp.cpus; i++) {
> > +        /* init CPUs */
> > +        cpu = MIPS_CPU(cpu_create(machine->cpu_type));
> > +
> > +        /* Init internal devices */
> > +        cpu_mips_irq_init_cpu(cpu);
> > +        cpu_mips_clock_init(cpu);
> > +        qemu_register_reset(main_cpu_reset, cpu);
> > +    }
> > +    env = &MIPS_CPU(first_cpu)->env;
> > +
> > +    /* Allocate RAM/BIOS, 0x00000000~0x10000000 is alias of 0x80000000~0x90000000 */
> > +    memory_region_init_rom(bios, NULL, "loongson3.bios", BIOS_SIZE, &error_fatal);
> > +    memory_region_init_alias(ram, NULL, "loongson3.lowram", machine->ram, 0, 256 * 0x100000);
> > +    memory_region_init_io(iomem, NULL, &loongson3_pm_ops, NULL, "loongson3_pm", PM_MMIO_SIZE);
> > +
> > +    memory_region_add_subregion(address_space_mem, 0x00000000LL, ram);
> > +    memory_region_add_subregion(address_space_mem, 0x1fc00000LL, bios);
> > +    memory_region_add_subregion(address_space_mem, 0x80000000LL, machine->ram);
> > +    memory_region_add_subregion(address_space_mem, PM_MMIO_ADDR, iomem);
> > +
> > +    /*
> > +     * We do not support flash operation, just loading pmon.bin as raw BIOS.
> > +     * Please use -L to set the BIOS path and -bios to set bios name.
> > +     */
> > +
> > +    if (kernel_filename) {
> > +        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);
> > +        rom_add_blob_fixed("bios", bios_boot_code, sizeof(bios_boot_code), 0x1fc00000LL);
> > +    } else {
> > +        if (bios_name == NULL) {
> > +                bios_name = LOONGSON3_BIOSNAME;
> > +        }
> > +        filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
> > +        if (filename) {
> > +            bios_size = load_image_targphys(filename, 0x1fc00000LL,
> > +                                            BIOS_SIZE);
> > +            g_free(filename);
> > +        } else {
> > +            bios_size = -1;
> > +        }
> > +
> > +        if ((bios_size < 0 || bios_size > BIOS_SIZE) &&
> > +            !kernel_filename && !qtest_enabled()) {
> > +            error_report("Could not load MIPS bios '%s'", bios_name);
> > +            exit(1);
> > +        }
> > +
> > +        fw_conf_init(ram_size);
> > +        rom_add_blob_fixed("fw_conf", (void*)&fw_config, sizeof(fw_config), FW_CONF_ADDR);
> > +    }
> > +
> > +    msi_nonbroken = true;
> > +    loongson3_isa_init(env->irq[3]);
> > +    loongson3_pcie_init(machine, isa_pic);
> > +
> > +    if (serial_hd(0))
> > +        serial_mm_init(address_space_mem, 0x1fe001e0, 0, env->irq[2], 115200, serial_hd(0), DEVICE_NATIVE_ENDIAN);
> > +}
> > +
> > +static void mips_loongson3_machine_init(MachineClass *mc)
> > +{
> > +    mc->desc = "Generic Loongson-3 Platform";
> > +    mc->init = mips_loongson3_init;
> > +    mc->block_default_type = IF_IDE;
> > +    mc->max_cpus = LOONGSON_MAX_VCPUS;
> > +    mc->default_cpu_type = MIPS_CPU_TYPE_NAME("Loongson-3A");
> > +    mc->default_ram_id = "loongson3.highram";
> > +    mc->default_ram_size = 784 * MiB;
> > +    mc->kvm_type = mips_kvm_type;
> > +    mc->minimum_page_bits = 14;
> > +}
> > +
> > +DEFINE_MACHINE("loongson3", mips_loongson3_machine_init)
> > --
> > 2.7.0
> >


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH for-5.1 3/7] hw/mips: Add CPU IRQ3 delivery for KVM
  2020-04-28 18:58       ` Aleksandar Markovic
@ 2020-04-29  1:52         ` Huacai Chen
  2020-04-29  9:17           ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 30+ messages in thread
From: Huacai Chen @ 2020-04-29  1:52 UTC (permalink / raw)
  To: Aleksandar Markovic
  Cc: chen huacai, Philippe Mathieu-Daudé, Aurelien Jarno, qemu-level

Hi, Philippe and Aleksandar,

I'm not refusing to change my patch, but I have two questions:
1, Why we should identify Loongson-3 to deliver IP3? It seems that
deliver all IPs (IP2~IP7) unconditionally is harmless as well.
2, How to identify Loongson-3 by Config6/Config7? Loongson-3 is not
the only processor which has Config6/Config7.

Huacai

On Wed, Apr 29, 2020 at 2:58 AM Aleksandar Markovic
<aleksandar.qemu.devel@gmail.com> wrote:
>
> уто, 28. апр 2020. у 10:21 chen huacai <zltjiangshi@gmail.com> је написао/ла:
> >
> > Hi, Philippe,
> >
> > On Mon, Apr 27, 2020 at 5:57 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
> > >
> > > On 4/27/20 11:33 AM, Huacai Chen wrote:
> > > > Currently, KVM/MIPS only deliver I/O interrupt via IP2, this patch add
> > > > IP2 delivery as well, because Loongson-3 based machine use both IRQ2
> > > > (CPU's IP2) and IRQ3 (CPU's IP3).
> > > >
> > > > Signed-off-by: Huacai Chen <chenhc@lemote.com>
> > > > Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> > > > ---
> > > >  hw/mips/mips_int.c | 6 ++----
> > > >  1 file changed, 2 insertions(+), 4 deletions(-)
> > > >
> > > > diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c
> > > > index 796730b..5526219 100644
> > > > --- a/hw/mips/mips_int.c
> > > > +++ b/hw/mips/mips_int.c
> > > > @@ -48,16 +48,14 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level)
> > > >      if (level) {
> > > >          env->CP0_Cause |= 1 << (irq + CP0Ca_IP);
> > > >
> > > > -        if (kvm_enabled() && irq == 2) {
> > > > +        if (kvm_enabled() && (irq == 2 || irq == 3))
> > >
> > > Shouldn't we check env->CP0_Config6 (or Config7) has the required
> > > feature first?
> > I'm sorry that I can't understand IRQ delivery has something to do
> > with Config6/Config7, to identify Loongson-3?
> >
>
> Obviously, yes.
>
> Thanks,
> Aleksandar
>
>
> > >
> > > >              kvm_mips_set_interrupt(cpu, irq, level);
> > > > -        }
> > > >
> > > >      } else {
> > > >          env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
> > > >
> > > > -        if (kvm_enabled() && irq == 2) {
> > > > +        if (kvm_enabled() && (irq == 2 || irq == 3))
> > > >              kvm_mips_set_interrupt(cpu, irq, level);
> > > > -        }
> > > >      }
> > > >
> > > >      if (env->CP0_Cause & CP0Ca_IP_mask) {
> > > >
> >
> >
> >
> > --
> > Huacai Chen


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH for-5.1 4/7] target/mips: Add Loongson-3 CPU definition
  2020-04-28 18:37       ` Aleksandar Markovic
@ 2020-04-29  3:51         ` Huacai Chen
  2020-04-29  8:09           ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 30+ messages in thread
From: Huacai Chen @ 2020-04-29  3:51 UTC (permalink / raw)
  To: Aleksandar Markovic
  Cc: chen huacai, Philippe Mathieu-Daudé, Aurelien Jarno, qemu-level

Hi, Aleksandar,

I've tried translate.google.com, and documents are available here:
Loongson-3A R1 (Loongson-3A1000)
User Manual Part 1:
http://ftp.godson.ac.cn/lemote/3A1000_p1.pdf
http://ftp.godson.ac.cn/lemote/Loongson3A1000_processor_user_manual_P1.pdf
(Chinese Version)
User Manual Part 2:
http://ftp.godson.ac.cn/lemote/3A1000_p2.pdf
http://ftp.godson.ac.cn/lemote/Loongson3A1000_processor_user_manual_P2.pdf
(Chinese Version)

Loongson-3A R2 (Loongson-3A2000)
User Manual Part 1:
http://ftp.godson.ac.cn/lemote/3A2000_p1.pdf
http://ftp.godson.ac.cn/lemote/Loongson3A2000_user1.pdf (Chinese Version)
User Manual Part 2:
http://ftp.godson.ac.cn/lemote/3A2000_p2.pdf
http://ftp.godson.ac.cn/lemote/Loongson3A2000_user2.pdf (Chinese Version)

Loongson-3A R3 (Loongson-3A3000)
User Manual Part 1:
http://ftp.godson.ac.cn/lemote/3A3000_p1.pdf
http://ftp.godson.ac.cn/lemote/Loongson3A3000_3B3000usermanual1.pdf
(Chinese Version)
User Manual Part 2:
http://ftp.godson.ac.cn/lemote/3A3000_p2.pdf
http://ftp.godson.ac.cn/lemote/Loongson3A3000_3B3000usermanual2.pdf
(Chinese Version)

Loongson-3A R4 (Loongson-3A4000)
User Manual Part 1:
http://ftp.godson.ac.cn/lemote/3A4000_p1.pdf
http://ftp.godson.ac.cn/lemote/3A4000user.pdf (Chinese Version)
User Manual Part 2:
I'm sorry that it is unavailable now.

On Wed, Apr 29, 2020 at 2:37 AM Aleksandar Markovic
<aleksandar.qemu.devel@gmail.com> wrote:
>
> Huacai,
>
> Can you please do machine translation of the document?
>
> It can be done via translate.google.com (it accepts pdf files, but
> does not have download feature, and workaround is to "print to pdf"...
>
> Thanks in advance!
> Aleksandar
>
> уто, 28. апр 2020. у 10:26 chen huacai <zltjiangshi@gmail.com> је написао/ла:
> >
> > Hi, Philippe,
> >
> > On Tue, Apr 28, 2020 at 2:34 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
> > >
> > > Hi Huacai,
> > >
> > > On 4/27/20 11:33 AM, Huacai Chen wrote:
> > > > Loongson-3 CPU family include Loongson-3A R1/R2/R3/R4 and Loongson-3B
> > > > R1/R2. Loongson-3A R4 is the newest and its ISA is almost the superset
> > > > of all others. To reduce complexity, we just define a "Loongson-3A" CPU
> > > > which is corresponding to Loongson-3A R4. Loongson-3A has CONFIG6 and
> > > > CONFIG7, so add their bit-fields as well.
> > >
> > > Is there a public datasheet for R4? (If possible in English).
> > I'm sorry that we only have Chinese datasheet in www.loongson.cn.
> >
> > >
> > > >
> > > > Signed-off-by: Huacai Chen <chenhc@lemote.com>
> > > > Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> > > > ---
> > > >  target/mips/cpu.h                | 28 ++++++++++++++++++++++
> > > >  target/mips/internal.h           |  2 ++
> > > >  target/mips/mips-defs.h          |  7 ++++--
> > > >  target/mips/translate.c          |  2 ++
> > > >  target/mips/translate_init.inc.c | 51 ++++++++++++++++++++++++++++++++++++++++
> > > >  5 files changed, 88 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/target/mips/cpu.h b/target/mips/cpu.h
> > > > index 94d01ea..0b3c987 100644
> > > > --- a/target/mips/cpu.h
> > > > +++ b/target/mips/cpu.h
> > > > @@ -940,7 +940,35 @@ struct CPUMIPSState {
> > > >  #define CP0C5_UFR          2
> > > >  #define CP0C5_NFExists     0
> > > >      int32_t CP0_Config6;
> > > > +    int32_t CP0_Config6_rw_bitmask;
> > > > +#define CP0C6_BPPASS          31
> > > > +#define CP0C6_KPOS            24
> > > > +#define CP0C6_KE              23
> > > > +#define CP0C6_VTLBONLY        22
> > > > +#define CP0C6_LASX            21
> > > > +#define CP0C6_SSEN            20
> > > > +#define CP0C6_DISDRTIME       19
> > > > +#define CP0C6_PIXNUEN         18
> > > > +#define CP0C6_SCRAND          17
> > > > +#define CP0C6_LLEXCEN         16
> > > > +#define CP0C6_DISVC           15
> > > > +#define CP0C6_VCLRU           14
> > > > +#define CP0C6_DCLRU           13
> > > > +#define CP0C6_PIXUEN          12
> > > > +#define CP0C6_DISBLKLYEN      11
> > > > +#define CP0C6_UMEMUALEN       10
> > > > +#define CP0C6_SFBEN           8
> > > > +#define CP0C6_FLTINT          7
> > > > +#define CP0C6_VLTINT          6
> > > > +#define CP0C6_DISBTB          5
> > > > +#define CP0C6_STPREFCTL       2
> > > > +#define CP0C6_INSTPREF        1
> > > > +#define CP0C6_DATAPREF        0
> > > >      int32_t CP0_Config7;
> > > > +    int64_t CP0_Config7_rw_bitmask;
> > > > +#define CP0C7_NAPCGEN       2
> > > > +#define CP0C7_UNIMUEN       1
> > > > +#define CP0C7_VFPUCGEN      0
> > > >      uint64_t CP0_LLAddr;
> > > >      uint64_t CP0_MAAR[MIPS_MAAR_MAX];
> > > >      int32_t CP0_MAARI;
> > > > diff --git a/target/mips/internal.h b/target/mips/internal.h
> > > > index 1bf274b..7853cb1 100644
> > > > --- a/target/mips/internal.h
> > > > +++ b/target/mips/internal.h
> > > > @@ -36,7 +36,9 @@ struct mips_def_t {
> > > >      int32_t CP0_Config5;
> > > >      int32_t CP0_Config5_rw_bitmask;
> > > >      int32_t CP0_Config6;
> > > > +    int32_t CP0_Config6_rw_bitmask;
> > > >      int32_t CP0_Config7;
> > > > +    int32_t CP0_Config7_rw_bitmask;
> > > >      target_ulong CP0_LLAddr_rw_bitmask;
> > > >      int CP0_LLAddr_shift;
> > > >      int32_t SYNCI_Step;
> > > > diff --git a/target/mips/mips-defs.h b/target/mips/mips-defs.h
> > > > index a831bb4..c2c96db 100644
> > > > --- a/target/mips/mips-defs.h
> > > > +++ b/target/mips/mips-defs.h
> > > > @@ -51,8 +51,9 @@
> > > >   */
> > > >  #define INSN_LOONGSON2E   0x0001000000000000ULL
> > > >  #define INSN_LOONGSON2F   0x0002000000000000ULL
> > > > -#define INSN_VR54XX       0x0004000000000000ULL
> > > > -#define INSN_R5900        0x0008000000000000ULL
> > > > +#define INSN_LOONGSON3A   0x0004000000000000ULL
> > > > +#define INSN_VR54XX       0x0008000000000000ULL
> > > > +#define INSN_R5900        0x0010000000000000ULL
> > > >  /*
> > > >   *   bits 56-63: vendor-specific ASEs
> > > >   */
> > > > @@ -94,6 +95,8 @@
> > > >  /* Wave Computing: "nanoMIPS" */
> > > >  #define CPU_NANOMIPS32  (CPU_MIPS32R6 | ISA_NANOMIPS32)
> > > >
> > > > +#define CPU_LOONGSON3A  (CPU_MIPS64R2 | INSN_LOONGSON3A)
> > > > +
> > > >  /*
> > > >   * Strictly follow the architecture standard:
> > > >   * - Disallow "special" instruction handling for PMON/SPIM.
> > > > diff --git a/target/mips/translate.c b/target/mips/translate.c
> > > > index 25b595a..2caf4cb 100644
> > > > --- a/target/mips/translate.c
> > > > +++ b/target/mips/translate.c
> > > > @@ -31206,7 +31206,9 @@ void cpu_state_reset(CPUMIPSState *env)
> > > >      env->CP0_Config5 = env->cpu_model->CP0_Config5;
> > > >      env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
> > > >      env->CP0_Config6 = env->cpu_model->CP0_Config6;
> > > > +    env->CP0_Config6_rw_bitmask = env->cpu_model->CP0_Config6_rw_bitmask;
> > > >      env->CP0_Config7 = env->cpu_model->CP0_Config7;
> > > > +    env->CP0_Config7_rw_bitmask = env->cpu_model->CP0_Config7_rw_bitmask;
> > > >      env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
> > > >                                   << env->cpu_model->CP0_LLAddr_shift;
> > > >      env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
> > > > diff --git a/target/mips/translate_init.inc.c b/target/mips/translate_init.inc.c
> > > > index 6d145a9..a32412d 100644
> > > > --- a/target/mips/translate_init.inc.c
> > > > +++ b/target/mips/translate_init.inc.c
> > > > @@ -802,6 +802,57 @@ const mips_def_t mips_defs[] =
> > > >          .mmu_type = MMU_TYPE_R4000,
> > > >      },
> > > >      {
> > > > +        .name = "Loongson-3A",
> > > > +        .CP0_PRid = 0x14C000,
> > > > +        /* 64KB I-cache and d-cache. 4 way with 32 bit cache line size.  */
> > > > +        .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
> > > > +                       (MMU_TYPE_R4000 << CP0C0_MT),
> > > > +        .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) |
> > > > +                       (2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
> > > > +                       (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
> > > > +                       (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
> > > > +        .CP0_Config2 = MIPS_CONFIG2,
> > > > +        .CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_MSAP) |
> > > > +                       (1 << CP0C3_BP) | (1 << CP0C3_BI) | (1 << CP0C3_ULRI) |
> > > > +                       (1 << CP0C3_RXI) | (1 << CP0C3_LPA) | (1 << CP0C3_VInt),
> > > > +        .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) | (2 << CP0C4_IE) |
> > > > +                       (1 << CP0C4_AE) | (0x1c << CP0C4_KScrExist),
> > > > +        .CP0_Config4_rw_bitmask = 0,
> > > > +        .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_NFExists) | (1 << 18),
> > > > +        .CP0_Config5_rw_bitmask = (1 << CP0C5_K) | (1 << CP0C5_CV) |
> > > > +                                  (1 << CP0C5_MSAEn) | (1 << CP0C5_UFE) |
> > > > +                                  (1 << CP0C5_FRE) | (1 << CP0C5_SBRI),
> > > > +        .CP0_Config6 = (1 << CP0C6_VCLRU) | (1 << CP0C6_DCLRU) | (1 << CP0C6_SFBEN) |
> > > > +                       (1 << CP0C6_FLTINT) | (1 << CP0C6_INSTPREF) | (1 << CP0C6_DATAPREF),
> > > > +        .CP0_Config6_rw_bitmask = (1 << CP0C6_BPPASS) | (0x3f << CP0C6_KPOS) |
> > > > +                                  (1 << CP0C6_KE) | (1 << CP0C6_VTLBONLY) | (1 << CP0C6_LASX) |
> > > > +                                  (1 << CP0C6_SSEN) | (1 << CP0C6_DISDRTIME) |
> > > > +                                  (1 << CP0C6_PIXNUEN) | (1 << CP0C6_SCRAND) |
> > > > +                                  (1 << CP0C6_LLEXCEN) | (1 << CP0C6_DISVC) |
> > > > +                                  (1 << CP0C6_VCLRU) | (1 << CP0C6_DCLRU) |
> > > > +                                  (1 << CP0C6_PIXUEN) | (1 << CP0C6_DISBLKLYEN) |
> > > > +                                  (1 << CP0C6_UMEMUALEN) | (1 << CP0C6_SFBEN) |
> > > > +                                  (1 << CP0C6_FLTINT) | (1 << CP0C6_VLTINT) |
> > > > +                                  (1 << CP0C6_DISBTB) | (3 << CP0C6_STPREFCTL) |
> > > > +                                  (1 << CP0C6_INSTPREF) | (1 << CP0C6_DATAPREF),
> > > > +        .CP0_Config7 = 0,
> > > > +        .CP0_Config7_rw_bitmask = (1 << CP0C7_NAPCGEN) | (1 << CP0C7_UNIMUEN) | \
> > > > +                                  (1 << CP0C7_VFPUCGEN),
> > > > +        .CP0_LLAddr_rw_bitmask = 1,
> > > > +        .SYNCI_Step = 16,
> > > > +        .CCRes = 2,
> > > > +        .CP0_Status_rw_bitmask = 0x7DDBFFFF,
> > > > +        .CP0_PageGrain_rw_bitmask = (1U << CP0PG_RIE) | (1 << CP0PG_XIE) |
> > > > +                    (1 << CP0PG_ELPA) | (1 << CP0PG_IEC),
> > > > +        .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x1 << FCR0_REV) | (0x1 << FCR0_F64),
> > > > +        .CP1_fcr31 = 0,
> > > > +        .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
> > > > +        .SEGBITS = 48,
> > > > +        .PABITS = 48,
> > > > +        .insn_flags = CPU_LOONGSON3A,
> > > > +        .mmu_type = MMU_TYPE_R4000,
> > > > +    },
> > > > +    {
> > > >          /* A generic CPU providing MIPS64 DSP R2 ASE features.
> > > >             FIXME: Eventually this should be replaced by a real CPU model. */
> > > >          .name = "mips64dspr2",
> > > >
> >
> >
> >
> > --
> > Huacai Chen


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH for-5.1 4/7] target/mips: Add Loongson-3 CPU definition
  2020-04-29  3:51         ` Huacai Chen
@ 2020-04-29  8:09           ` Philippe Mathieu-Daudé
  2020-04-29  8:27             ` Huacai Chen
  0 siblings, 1 reply; 30+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-04-29  8:09 UTC (permalink / raw)
  To: Huacai Chen, Aleksandar Markovic; +Cc: chen huacai, qemu-level, Aurelien Jarno

On 4/29/20 5:51 AM, Huacai Chen wrote:
> Hi, Aleksandar,
> 
> I've tried translate.google.com, and documents are available here:
> Loongson-3A R1 (Loongson-3A1000)
> User Manual Part 1:
> http://ftp.godson.ac.cn/lemote/3A1000_p1.pdf
> http://ftp.godson.ac.cn/lemote/Loongson3A1000_processor_user_manual_P1.pdf
> (Chinese Version)
> User Manual Part 2:
> http://ftp.godson.ac.cn/lemote/3A1000_p2.pdf
> http://ftp.godson.ac.cn/lemote/Loongson3A1000_processor_user_manual_P2.pdf
> (Chinese Version)
> 
> Loongson-3A R2 (Loongson-3A2000)
> User Manual Part 1:
> http://ftp.godson.ac.cn/lemote/3A2000_p1.pdf
> http://ftp.godson.ac.cn/lemote/Loongson3A2000_user1.pdf (Chinese Version)
> User Manual Part 2:
> http://ftp.godson.ac.cn/lemote/3A2000_p2.pdf
> http://ftp.godson.ac.cn/lemote/Loongson3A2000_user2.pdf (Chinese Version)
> 
> Loongson-3A R3 (Loongson-3A3000)
> User Manual Part 1:
> http://ftp.godson.ac.cn/lemote/3A3000_p1.pdf
> http://ftp.godson.ac.cn/lemote/Loongson3A3000_3B3000usermanual1.pdf
> (Chinese Version)
> User Manual Part 2:
> http://ftp.godson.ac.cn/lemote/3A3000_p2.pdf
> http://ftp.godson.ac.cn/lemote/Loongson3A3000_3B3000usermanual2.pdf
> (Chinese Version)
> 
> Loongson-3A R4 (Loongson-3A4000)
> User Manual Part 1:
> http://ftp.godson.ac.cn/lemote/3A4000_p1.pdf
> http://ftp.godson.ac.cn/lemote/3A4000user.pdf (Chinese Version)
> User Manual Part 2:
> I'm sorry that it is unavailable now.

Thanks for the translations!

Since we can only review Loongson-3A R3, are there specific features 
from R4 you need that are not available in R3?

> 
> On Wed, Apr 29, 2020 at 2:37 AM Aleksandar Markovic
> <aleksandar.qemu.devel@gmail.com> wrote:
>>
>> Huacai,
>>
>> Can you please do machine translation of the document?
>>
>> It can be done via translate.google.com (it accepts pdf files, but
>> does not have download feature, and workaround is to "print to pdf"...
>>
>> Thanks in advance!
>> Aleksandar
>>
>> уто, 28. апр 2020. у 10:26 chen huacai <zltjiangshi@gmail.com> је написао/ла:
>>>
>>> Hi, Philippe,
>>>
>>> On Tue, Apr 28, 2020 at 2:34 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>>>>
>>>> Hi Huacai,
>>>>
>>>> On 4/27/20 11:33 AM, Huacai Chen wrote:
>>>>> Loongson-3 CPU family include Loongson-3A R1/R2/R3/R4 and Loongson-3B
>>>>> R1/R2. Loongson-3A R4 is the newest and its ISA is almost the superset
>>>>> of all others. To reduce complexity, we just define a "Loongson-3A" CPU
>>>>> which is corresponding to Loongson-3A R4. Loongson-3A has CONFIG6 and
>>>>> CONFIG7, so add their bit-fields as well.
>>>>
>>>> Is there a public datasheet for R4? (If possible in English).
>>> I'm sorry that we only have Chinese datasheet in www.loongson.cn.
>>>
>>>>
>>>>>
>>>>> Signed-off-by: Huacai Chen <chenhc@lemote.com>
>>>>> Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
>>>>> ---
>>>>>   target/mips/cpu.h                | 28 ++++++++++++++++++++++
>>>>>   target/mips/internal.h           |  2 ++
>>>>>   target/mips/mips-defs.h          |  7 ++++--
>>>>>   target/mips/translate.c          |  2 ++
>>>>>   target/mips/translate_init.inc.c | 51 ++++++++++++++++++++++++++++++++++++++++
>>>>>   5 files changed, 88 insertions(+), 2 deletions(-)
>>>>>
>>>>> diff --git a/target/mips/cpu.h b/target/mips/cpu.h
>>>>> index 94d01ea..0b3c987 100644
>>>>> --- a/target/mips/cpu.h
>>>>> +++ b/target/mips/cpu.h
>>>>> @@ -940,7 +940,35 @@ struct CPUMIPSState {
>>>>>   #define CP0C5_UFR          2
>>>>>   #define CP0C5_NFExists     0
>>>>>       int32_t CP0_Config6;
>>>>> +    int32_t CP0_Config6_rw_bitmask;
>>>>> +#define CP0C6_BPPASS          31
>>>>> +#define CP0C6_KPOS            24
>>>>> +#define CP0C6_KE              23
>>>>> +#define CP0C6_VTLBONLY        22
>>>>> +#define CP0C6_LASX            21
>>>>> +#define CP0C6_SSEN            20
>>>>> +#define CP0C6_DISDRTIME       19
>>>>> +#define CP0C6_PIXNUEN         18
>>>>> +#define CP0C6_SCRAND          17
>>>>> +#define CP0C6_LLEXCEN         16
>>>>> +#define CP0C6_DISVC           15
>>>>> +#define CP0C6_VCLRU           14
>>>>> +#define CP0C6_DCLRU           13
>>>>> +#define CP0C6_PIXUEN          12
>>>>> +#define CP0C6_DISBLKLYEN      11
>>>>> +#define CP0C6_UMEMUALEN       10
>>>>> +#define CP0C6_SFBEN           8
>>>>> +#define CP0C6_FLTINT          7
>>>>> +#define CP0C6_VLTINT          6
>>>>> +#define CP0C6_DISBTB          5
>>>>> +#define CP0C6_STPREFCTL       2
>>>>> +#define CP0C6_INSTPREF        1
>>>>> +#define CP0C6_DATAPREF        0
>>>>>       int32_t CP0_Config7;
>>>>> +    int64_t CP0_Config7_rw_bitmask;
>>>>> +#define CP0C7_NAPCGEN       2
>>>>> +#define CP0C7_UNIMUEN       1
>>>>> +#define CP0C7_VFPUCGEN      0
>>>>>       uint64_t CP0_LLAddr;
>>>>>       uint64_t CP0_MAAR[MIPS_MAAR_MAX];
>>>>>       int32_t CP0_MAARI;
>>>>> diff --git a/target/mips/internal.h b/target/mips/internal.h
>>>>> index 1bf274b..7853cb1 100644
>>>>> --- a/target/mips/internal.h
>>>>> +++ b/target/mips/internal.h
>>>>> @@ -36,7 +36,9 @@ struct mips_def_t {
>>>>>       int32_t CP0_Config5;
>>>>>       int32_t CP0_Config5_rw_bitmask;
>>>>>       int32_t CP0_Config6;
>>>>> +    int32_t CP0_Config6_rw_bitmask;
>>>>>       int32_t CP0_Config7;
>>>>> +    int32_t CP0_Config7_rw_bitmask;
>>>>>       target_ulong CP0_LLAddr_rw_bitmask;
>>>>>       int CP0_LLAddr_shift;
>>>>>       int32_t SYNCI_Step;
>>>>> diff --git a/target/mips/mips-defs.h b/target/mips/mips-defs.h
>>>>> index a831bb4..c2c96db 100644
>>>>> --- a/target/mips/mips-defs.h
>>>>> +++ b/target/mips/mips-defs.h
>>>>> @@ -51,8 +51,9 @@
>>>>>    */
>>>>>   #define INSN_LOONGSON2E   0x0001000000000000ULL
>>>>>   #define INSN_LOONGSON2F   0x0002000000000000ULL
>>>>> -#define INSN_VR54XX       0x0004000000000000ULL
>>>>> -#define INSN_R5900        0x0008000000000000ULL
>>>>> +#define INSN_LOONGSON3A   0x0004000000000000ULL
>>>>> +#define INSN_VR54XX       0x0008000000000000ULL
>>>>> +#define INSN_R5900        0x0010000000000000ULL
>>>>>   /*
>>>>>    *   bits 56-63: vendor-specific ASEs
>>>>>    */
>>>>> @@ -94,6 +95,8 @@
>>>>>   /* Wave Computing: "nanoMIPS" */
>>>>>   #define CPU_NANOMIPS32  (CPU_MIPS32R6 | ISA_NANOMIPS32)
>>>>>
>>>>> +#define CPU_LOONGSON3A  (CPU_MIPS64R2 | INSN_LOONGSON3A)
>>>>> +
>>>>>   /*
>>>>>    * Strictly follow the architecture standard:
>>>>>    * - Disallow "special" instruction handling for PMON/SPIM.
>>>>> diff --git a/target/mips/translate.c b/target/mips/translate.c
>>>>> index 25b595a..2caf4cb 100644
>>>>> --- a/target/mips/translate.c
>>>>> +++ b/target/mips/translate.c
>>>>> @@ -31206,7 +31206,9 @@ void cpu_state_reset(CPUMIPSState *env)
>>>>>       env->CP0_Config5 = env->cpu_model->CP0_Config5;
>>>>>       env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
>>>>>       env->CP0_Config6 = env->cpu_model->CP0_Config6;
>>>>> +    env->CP0_Config6_rw_bitmask = env->cpu_model->CP0_Config6_rw_bitmask;
>>>>>       env->CP0_Config7 = env->cpu_model->CP0_Config7;
>>>>> +    env->CP0_Config7_rw_bitmask = env->cpu_model->CP0_Config7_rw_bitmask;
>>>>>       env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
>>>>>                                    << env->cpu_model->CP0_LLAddr_shift;
>>>>>       env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
>>>>> diff --git a/target/mips/translate_init.inc.c b/target/mips/translate_init.inc.c
>>>>> index 6d145a9..a32412d 100644
>>>>> --- a/target/mips/translate_init.inc.c
>>>>> +++ b/target/mips/translate_init.inc.c
>>>>> @@ -802,6 +802,57 @@ const mips_def_t mips_defs[] =
>>>>>           .mmu_type = MMU_TYPE_R4000,
>>>>>       },
>>>>>       {
>>>>> +        .name = "Loongson-3A",
>>>>> +        .CP0_PRid = 0x14C000,
>>>>> +        /* 64KB I-cache and d-cache. 4 way with 32 bit cache line size.  */
>>>>> +        .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
>>>>> +                       (MMU_TYPE_R4000 << CP0C0_MT),
>>>>> +        .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) |
>>>>> +                       (2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
>>>>> +                       (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
>>>>> +                       (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
>>>>> +        .CP0_Config2 = MIPS_CONFIG2,
>>>>> +        .CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_MSAP) |
>>>>> +                       (1 << CP0C3_BP) | (1 << CP0C3_BI) | (1 << CP0C3_ULRI) |
>>>>> +                       (1 << CP0C3_RXI) | (1 << CP0C3_LPA) | (1 << CP0C3_VInt),
>>>>> +        .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) | (2 << CP0C4_IE) |
>>>>> +                       (1 << CP0C4_AE) | (0x1c << CP0C4_KScrExist),
>>>>> +        .CP0_Config4_rw_bitmask = 0,
>>>>> +        .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_NFExists) | (1 << 18),
>>>>> +        .CP0_Config5_rw_bitmask = (1 << CP0C5_K) | (1 << CP0C5_CV) |
>>>>> +                                  (1 << CP0C5_MSAEn) | (1 << CP0C5_UFE) |
>>>>> +                                  (1 << CP0C5_FRE) | (1 << CP0C5_SBRI),
>>>>> +        .CP0_Config6 = (1 << CP0C6_VCLRU) | (1 << CP0C6_DCLRU) | (1 << CP0C6_SFBEN) |
>>>>> +                       (1 << CP0C6_FLTINT) | (1 << CP0C6_INSTPREF) | (1 << CP0C6_DATAPREF),
>>>>> +        .CP0_Config6_rw_bitmask = (1 << CP0C6_BPPASS) | (0x3f << CP0C6_KPOS) |
>>>>> +                                  (1 << CP0C6_KE) | (1 << CP0C6_VTLBONLY) | (1 << CP0C6_LASX) |
>>>>> +                                  (1 << CP0C6_SSEN) | (1 << CP0C6_DISDRTIME) |
>>>>> +                                  (1 << CP0C6_PIXNUEN) | (1 << CP0C6_SCRAND) |
>>>>> +                                  (1 << CP0C6_LLEXCEN) | (1 << CP0C6_DISVC) |
>>>>> +                                  (1 << CP0C6_VCLRU) | (1 << CP0C6_DCLRU) |
>>>>> +                                  (1 << CP0C6_PIXUEN) | (1 << CP0C6_DISBLKLYEN) |
>>>>> +                                  (1 << CP0C6_UMEMUALEN) | (1 << CP0C6_SFBEN) |
>>>>> +                                  (1 << CP0C6_FLTINT) | (1 << CP0C6_VLTINT) |
>>>>> +                                  (1 << CP0C6_DISBTB) | (3 << CP0C6_STPREFCTL) |
>>>>> +                                  (1 << CP0C6_INSTPREF) | (1 << CP0C6_DATAPREF),
>>>>> +        .CP0_Config7 = 0,
>>>>> +        .CP0_Config7_rw_bitmask = (1 << CP0C7_NAPCGEN) | (1 << CP0C7_UNIMUEN) | \
>>>>> +                                  (1 << CP0C7_VFPUCGEN),
>>>>> +        .CP0_LLAddr_rw_bitmask = 1,
>>>>> +        .SYNCI_Step = 16,
>>>>> +        .CCRes = 2,
>>>>> +        .CP0_Status_rw_bitmask = 0x7DDBFFFF,
>>>>> +        .CP0_PageGrain_rw_bitmask = (1U << CP0PG_RIE) | (1 << CP0PG_XIE) |
>>>>> +                    (1 << CP0PG_ELPA) | (1 << CP0PG_IEC),
>>>>> +        .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x1 << FCR0_REV) | (0x1 << FCR0_F64),
>>>>> +        .CP1_fcr31 = 0,
>>>>> +        .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
>>>>> +        .SEGBITS = 48,
>>>>> +        .PABITS = 48,
>>>>> +        .insn_flags = CPU_LOONGSON3A,
>>>>> +        .mmu_type = MMU_TYPE_R4000,
>>>>> +    },
>>>>> +    {
>>>>>           /* A generic CPU providing MIPS64 DSP R2 ASE features.
>>>>>              FIXME: Eventually this should be replaced by a real CPU model. */
>>>>>           .name = "mips64dspr2",
>>>>>
>>>
>>>
>>>
>>> --
>>> Huacai Chen
> 


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH for-5.1 4/7] target/mips: Add Loongson-3 CPU definition
  2020-04-29  8:09           ` Philippe Mathieu-Daudé
@ 2020-04-29  8:27             ` Huacai Chen
  2020-04-29  8:58               ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 30+ messages in thread
From: Huacai Chen @ 2020-04-29  8:27 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: chen huacai, Aleksandar Markovic, qemu-level, Aurelien Jarno

Hi, Philippe,

The major differences of R3 and R4 are:
1, R4 has complete MIPS VZ ASE (while R3 is incomplete), so very
usable for KVM host;
2, R4 has MSA ASE while R3 hasn't;
3, R4 has cpucfg, rdcsr and wrcsr instructions (similar to cpuid,
rdmsr and wrmsr in X86).

On Wed, Apr 29, 2020 at 4:09 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>
> On 4/29/20 5:51 AM, Huacai Chen wrote:
> > Hi, Aleksandar,
> >
> > I've tried translate.google.com, and documents are available here:
> > Loongson-3A R1 (Loongson-3A1000)
> > User Manual Part 1:
> > http://ftp.godson.ac.cn/lemote/3A1000_p1.pdf
> > http://ftp.godson.ac.cn/lemote/Loongson3A1000_processor_user_manual_P1.pdf
> > (Chinese Version)
> > User Manual Part 2:
> > http://ftp.godson.ac.cn/lemote/3A1000_p2.pdf
> > http://ftp.godson.ac.cn/lemote/Loongson3A1000_processor_user_manual_P2.pdf
> > (Chinese Version)
> >
> > Loongson-3A R2 (Loongson-3A2000)
> > User Manual Part 1:
> > http://ftp.godson.ac.cn/lemote/3A2000_p1.pdf
> > http://ftp.godson.ac.cn/lemote/Loongson3A2000_user1.pdf (Chinese Version)
> > User Manual Part 2:
> > http://ftp.godson.ac.cn/lemote/3A2000_p2.pdf
> > http://ftp.godson.ac.cn/lemote/Loongson3A2000_user2.pdf (Chinese Version)
> >
> > Loongson-3A R3 (Loongson-3A3000)
> > User Manual Part 1:
> > http://ftp.godson.ac.cn/lemote/3A3000_p1.pdf
> > http://ftp.godson.ac.cn/lemote/Loongson3A3000_3B3000usermanual1.pdf
> > (Chinese Version)
> > User Manual Part 2:
> > http://ftp.godson.ac.cn/lemote/3A3000_p2.pdf
> > http://ftp.godson.ac.cn/lemote/Loongson3A3000_3B3000usermanual2.pdf
> > (Chinese Version)
> >
> > Loongson-3A R4 (Loongson-3A4000)
> > User Manual Part 1:
> > http://ftp.godson.ac.cn/lemote/3A4000_p1.pdf
> > http://ftp.godson.ac.cn/lemote/3A4000user.pdf (Chinese Version)
> > User Manual Part 2:
> > I'm sorry that it is unavailable now.
>
> Thanks for the translations!
>
> Since we can only review Loongson-3A R3, are there specific features
> from R4 you need that are not available in R3?
>
> >
> > On Wed, Apr 29, 2020 at 2:37 AM Aleksandar Markovic
> > <aleksandar.qemu.devel@gmail.com> wrote:
> >>
> >> Huacai,
> >>
> >> Can you please do machine translation of the document?
> >>
> >> It can be done via translate.google.com (it accepts pdf files, but
> >> does not have download feature, and workaround is to "print to pdf"...
> >>
> >> Thanks in advance!
> >> Aleksandar
> >>
> >> уто, 28. апр 2020. у 10:26 chen huacai <zltjiangshi@gmail.com> је написао/ла:
> >>>
> >>> Hi, Philippe,
> >>>
> >>> On Tue, Apr 28, 2020 at 2:34 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
> >>>>
> >>>> Hi Huacai,
> >>>>
> >>>> On 4/27/20 11:33 AM, Huacai Chen wrote:
> >>>>> Loongson-3 CPU family include Loongson-3A R1/R2/R3/R4 and Loongson-3B
> >>>>> R1/R2. Loongson-3A R4 is the newest and its ISA is almost the superset
> >>>>> of all others. To reduce complexity, we just define a "Loongson-3A" CPU
> >>>>> which is corresponding to Loongson-3A R4. Loongson-3A has CONFIG6 and
> >>>>> CONFIG7, so add their bit-fields as well.
> >>>>
> >>>> Is there a public datasheet for R4? (If possible in English).
> >>> I'm sorry that we only have Chinese datasheet in www.loongson.cn.
> >>>
> >>>>
> >>>>>
> >>>>> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> >>>>> Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> >>>>> ---
> >>>>>   target/mips/cpu.h                | 28 ++++++++++++++++++++++
> >>>>>   target/mips/internal.h           |  2 ++
> >>>>>   target/mips/mips-defs.h          |  7 ++++--
> >>>>>   target/mips/translate.c          |  2 ++
> >>>>>   target/mips/translate_init.inc.c | 51 ++++++++++++++++++++++++++++++++++++++++
> >>>>>   5 files changed, 88 insertions(+), 2 deletions(-)
> >>>>>
> >>>>> diff --git a/target/mips/cpu.h b/target/mips/cpu.h
> >>>>> index 94d01ea..0b3c987 100644
> >>>>> --- a/target/mips/cpu.h
> >>>>> +++ b/target/mips/cpu.h
> >>>>> @@ -940,7 +940,35 @@ struct CPUMIPSState {
> >>>>>   #define CP0C5_UFR          2
> >>>>>   #define CP0C5_NFExists     0
> >>>>>       int32_t CP0_Config6;
> >>>>> +    int32_t CP0_Config6_rw_bitmask;
> >>>>> +#define CP0C6_BPPASS          31
> >>>>> +#define CP0C6_KPOS            24
> >>>>> +#define CP0C6_KE              23
> >>>>> +#define CP0C6_VTLBONLY        22
> >>>>> +#define CP0C6_LASX            21
> >>>>> +#define CP0C6_SSEN            20
> >>>>> +#define CP0C6_DISDRTIME       19
> >>>>> +#define CP0C6_PIXNUEN         18
> >>>>> +#define CP0C6_SCRAND          17
> >>>>> +#define CP0C6_LLEXCEN         16
> >>>>> +#define CP0C6_DISVC           15
> >>>>> +#define CP0C6_VCLRU           14
> >>>>> +#define CP0C6_DCLRU           13
> >>>>> +#define CP0C6_PIXUEN          12
> >>>>> +#define CP0C6_DISBLKLYEN      11
> >>>>> +#define CP0C6_UMEMUALEN       10
> >>>>> +#define CP0C6_SFBEN           8
> >>>>> +#define CP0C6_FLTINT          7
> >>>>> +#define CP0C6_VLTINT          6
> >>>>> +#define CP0C6_DISBTB          5
> >>>>> +#define CP0C6_STPREFCTL       2
> >>>>> +#define CP0C6_INSTPREF        1
> >>>>> +#define CP0C6_DATAPREF        0
> >>>>>       int32_t CP0_Config7;
> >>>>> +    int64_t CP0_Config7_rw_bitmask;
> >>>>> +#define CP0C7_NAPCGEN       2
> >>>>> +#define CP0C7_UNIMUEN       1
> >>>>> +#define CP0C7_VFPUCGEN      0
> >>>>>       uint64_t CP0_LLAddr;
> >>>>>       uint64_t CP0_MAAR[MIPS_MAAR_MAX];
> >>>>>       int32_t CP0_MAARI;
> >>>>> diff --git a/target/mips/internal.h b/target/mips/internal.h
> >>>>> index 1bf274b..7853cb1 100644
> >>>>> --- a/target/mips/internal.h
> >>>>> +++ b/target/mips/internal.h
> >>>>> @@ -36,7 +36,9 @@ struct mips_def_t {
> >>>>>       int32_t CP0_Config5;
> >>>>>       int32_t CP0_Config5_rw_bitmask;
> >>>>>       int32_t CP0_Config6;
> >>>>> +    int32_t CP0_Config6_rw_bitmask;
> >>>>>       int32_t CP0_Config7;
> >>>>> +    int32_t CP0_Config7_rw_bitmask;
> >>>>>       target_ulong CP0_LLAddr_rw_bitmask;
> >>>>>       int CP0_LLAddr_shift;
> >>>>>       int32_t SYNCI_Step;
> >>>>> diff --git a/target/mips/mips-defs.h b/target/mips/mips-defs.h
> >>>>> index a831bb4..c2c96db 100644
> >>>>> --- a/target/mips/mips-defs.h
> >>>>> +++ b/target/mips/mips-defs.h
> >>>>> @@ -51,8 +51,9 @@
> >>>>>    */
> >>>>>   #define INSN_LOONGSON2E   0x0001000000000000ULL
> >>>>>   #define INSN_LOONGSON2F   0x0002000000000000ULL
> >>>>> -#define INSN_VR54XX       0x0004000000000000ULL
> >>>>> -#define INSN_R5900        0x0008000000000000ULL
> >>>>> +#define INSN_LOONGSON3A   0x0004000000000000ULL
> >>>>> +#define INSN_VR54XX       0x0008000000000000ULL
> >>>>> +#define INSN_R5900        0x0010000000000000ULL
> >>>>>   /*
> >>>>>    *   bits 56-63: vendor-specific ASEs
> >>>>>    */
> >>>>> @@ -94,6 +95,8 @@
> >>>>>   /* Wave Computing: "nanoMIPS" */
> >>>>>   #define CPU_NANOMIPS32  (CPU_MIPS32R6 | ISA_NANOMIPS32)
> >>>>>
> >>>>> +#define CPU_LOONGSON3A  (CPU_MIPS64R2 | INSN_LOONGSON3A)
> >>>>> +
> >>>>>   /*
> >>>>>    * Strictly follow the architecture standard:
> >>>>>    * - Disallow "special" instruction handling for PMON/SPIM.
> >>>>> diff --git a/target/mips/translate.c b/target/mips/translate.c
> >>>>> index 25b595a..2caf4cb 100644
> >>>>> --- a/target/mips/translate.c
> >>>>> +++ b/target/mips/translate.c
> >>>>> @@ -31206,7 +31206,9 @@ void cpu_state_reset(CPUMIPSState *env)
> >>>>>       env->CP0_Config5 = env->cpu_model->CP0_Config5;
> >>>>>       env->CP0_Config5_rw_bitmask = env->cpu_model->CP0_Config5_rw_bitmask;
> >>>>>       env->CP0_Config6 = env->cpu_model->CP0_Config6;
> >>>>> +    env->CP0_Config6_rw_bitmask = env->cpu_model->CP0_Config6_rw_bitmask;
> >>>>>       env->CP0_Config7 = env->cpu_model->CP0_Config7;
> >>>>> +    env->CP0_Config7_rw_bitmask = env->cpu_model->CP0_Config7_rw_bitmask;
> >>>>>       env->CP0_LLAddr_rw_bitmask = env->cpu_model->CP0_LLAddr_rw_bitmask
> >>>>>                                    << env->cpu_model->CP0_LLAddr_shift;
> >>>>>       env->CP0_LLAddr_shift = env->cpu_model->CP0_LLAddr_shift;
> >>>>> diff --git a/target/mips/translate_init.inc.c b/target/mips/translate_init.inc.c
> >>>>> index 6d145a9..a32412d 100644
> >>>>> --- a/target/mips/translate_init.inc.c
> >>>>> +++ b/target/mips/translate_init.inc.c
> >>>>> @@ -802,6 +802,57 @@ const mips_def_t mips_defs[] =
> >>>>>           .mmu_type = MMU_TYPE_R4000,
> >>>>>       },
> >>>>>       {
> >>>>> +        .name = "Loongson-3A",
> >>>>> +        .CP0_PRid = 0x14C000,
> >>>>> +        /* 64KB I-cache and d-cache. 4 way with 32 bit cache line size.  */
> >>>>> +        .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
> >>>>> +                       (MMU_TYPE_R4000 << CP0C0_MT),
> >>>>> +        .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) |
> >>>>> +                       (2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
> >>>>> +                       (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
> >>>>> +                       (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
> >>>>> +        .CP0_Config2 = MIPS_CONFIG2,
> >>>>> +        .CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_MSAP) |
> >>>>> +                       (1 << CP0C3_BP) | (1 << CP0C3_BI) | (1 << CP0C3_ULRI) |
> >>>>> +                       (1 << CP0C3_RXI) | (1 << CP0C3_LPA) | (1 << CP0C3_VInt),
> >>>>> +        .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) | (2 << CP0C4_IE) |
> >>>>> +                       (1 << CP0C4_AE) | (0x1c << CP0C4_KScrExist),
> >>>>> +        .CP0_Config4_rw_bitmask = 0,
> >>>>> +        .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_NFExists) | (1 << 18),
> >>>>> +        .CP0_Config5_rw_bitmask = (1 << CP0C5_K) | (1 << CP0C5_CV) |
> >>>>> +                                  (1 << CP0C5_MSAEn) | (1 << CP0C5_UFE) |
> >>>>> +                                  (1 << CP0C5_FRE) | (1 << CP0C5_SBRI),
> >>>>> +        .CP0_Config6 = (1 << CP0C6_VCLRU) | (1 << CP0C6_DCLRU) | (1 << CP0C6_SFBEN) |
> >>>>> +                       (1 << CP0C6_FLTINT) | (1 << CP0C6_INSTPREF) | (1 << CP0C6_DATAPREF),
> >>>>> +        .CP0_Config6_rw_bitmask = (1 << CP0C6_BPPASS) | (0x3f << CP0C6_KPOS) |
> >>>>> +                                  (1 << CP0C6_KE) | (1 << CP0C6_VTLBONLY) | (1 << CP0C6_LASX) |
> >>>>> +                                  (1 << CP0C6_SSEN) | (1 << CP0C6_DISDRTIME) |
> >>>>> +                                  (1 << CP0C6_PIXNUEN) | (1 << CP0C6_SCRAND) |
> >>>>> +                                  (1 << CP0C6_LLEXCEN) | (1 << CP0C6_DISVC) |
> >>>>> +                                  (1 << CP0C6_VCLRU) | (1 << CP0C6_DCLRU) |
> >>>>> +                                  (1 << CP0C6_PIXUEN) | (1 << CP0C6_DISBLKLYEN) |
> >>>>> +                                  (1 << CP0C6_UMEMUALEN) | (1 << CP0C6_SFBEN) |
> >>>>> +                                  (1 << CP0C6_FLTINT) | (1 << CP0C6_VLTINT) |
> >>>>> +                                  (1 << CP0C6_DISBTB) | (3 << CP0C6_STPREFCTL) |
> >>>>> +                                  (1 << CP0C6_INSTPREF) | (1 << CP0C6_DATAPREF),
> >>>>> +        .CP0_Config7 = 0,
> >>>>> +        .CP0_Config7_rw_bitmask = (1 << CP0C7_NAPCGEN) | (1 << CP0C7_UNIMUEN) | \
> >>>>> +                                  (1 << CP0C7_VFPUCGEN),
> >>>>> +        .CP0_LLAddr_rw_bitmask = 1,
> >>>>> +        .SYNCI_Step = 16,
> >>>>> +        .CCRes = 2,
> >>>>> +        .CP0_Status_rw_bitmask = 0x7DDBFFFF,
> >>>>> +        .CP0_PageGrain_rw_bitmask = (1U << CP0PG_RIE) | (1 << CP0PG_XIE) |
> >>>>> +                    (1 << CP0PG_ELPA) | (1 << CP0PG_IEC),
> >>>>> +        .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x1 << FCR0_REV) | (0x1 << FCR0_F64),
> >>>>> +        .CP1_fcr31 = 0,
> >>>>> +        .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
> >>>>> +        .SEGBITS = 48,
> >>>>> +        .PABITS = 48,
> >>>>> +        .insn_flags = CPU_LOONGSON3A,
> >>>>> +        .mmu_type = MMU_TYPE_R4000,
> >>>>> +    },
> >>>>> +    {
> >>>>>           /* A generic CPU providing MIPS64 DSP R2 ASE features.
> >>>>>              FIXME: Eventually this should be replaced by a real CPU model. */
> >>>>>           .name = "mips64dspr2",
> >>>>>
> >>>
> >>>
> >>>
> >>> --
> >>> Huacai Chen
> >


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH for-5.1 4/7] target/mips: Add Loongson-3 CPU definition
  2020-04-29  8:27             ` Huacai Chen
@ 2020-04-29  8:58               ` Philippe Mathieu-Daudé
  2020-04-29  9:25                 ` Huacai Chen
  0 siblings, 1 reply; 30+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-04-29  8:58 UTC (permalink / raw)
  To: Huacai Chen; +Cc: chen huacai, Aleksandar Markovic, qemu-level, Aurelien Jarno

On 4/29/20 10:27 AM, Huacai Chen wrote:
> Hi, Philippe,
> 
> The major differences of R3 and R4 are:
> 1, R4 has complete MIPS VZ ASE (while R3 is incomplete), so very
> usable for KVM host;

So you need to set CP0C3_VZ.

> 2, R4 has MSA ASE while R3 hasn't;

So you need to set CP0C5_MSAEn.

> 3, R4 has cpucfg, rdcsr and wrcsr instructions (similar to cpuid,
> rdmsr and wrmsr in X86).

OK, these are not implemented.

[...]

>>>>>>> diff --git a/target/mips/translate_init.inc.c b/target/mips/translate_init.inc.c
>>>>>>> index 6d145a9..a32412d 100644
>>>>>>> --- a/target/mips/translate_init.inc.c
>>>>>>> +++ b/target/mips/translate_init.inc.c
>>>>>>> @@ -802,6 +802,57 @@ const mips_def_t mips_defs[] =
>>>>>>>            .mmu_type = MMU_TYPE_R4000,
>>>>>>>        },
>>>>>>>        {
>>>>>>> +        .name = "Loongson-3A",
>>>>>>> +        .CP0_PRid = 0x14C000,
>>>>>>> +        /* 64KB I-cache and d-cache. 4 way with 32 bit cache line size.  */
>>>>>>> +        .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
>>>>>>> +                       (MMU_TYPE_R4000 << CP0C0_MT),
>>>>>>> +        .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) |
>>>>>>> +                       (2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
>>>>>>> +                       (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
>>>>>>> +                       (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
>>>>>>> +        .CP0_Config2 = MIPS_CONFIG2,
>>>>>>> +        .CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_MSAP) |
>>>>>>> +                       (1 << CP0C3_BP) | (1 << CP0C3_BI) | (1 << CP0C3_ULRI) |
>>>>>>> +                       (1 << CP0C3_RXI) | (1 << CP0C3_LPA) | (1 << CP0C3_VInt),
>>>>>>> +        .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) | (2 << CP0C4_IE) |
>>>>>>> +                       (1 << CP0C4_AE) | (0x1c << CP0C4_KScrExist),
>>>>>>> +        .CP0_Config4_rw_bitmask = 0,
>>>>>>> +        .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_NFExists) | (1 << 18),
>>>>>>> +        .CP0_Config5_rw_bitmask = (1 << CP0C5_K) | (1 << CP0C5_CV) |
>>>>>>> +                                  (1 << CP0C5_MSAEn) | (1 << CP0C5_UFE) |
>>>>>>> +                                  (1 << CP0C5_FRE) | (1 << CP0C5_SBRI),
>>>>>>> +        .CP0_Config6 = (1 << CP0C6_VCLRU) | (1 << CP0C6_DCLRU) | (1 << CP0C6_SFBEN) |
>>>>>>> +                       (1 << CP0C6_FLTINT) | (1 << CP0C6_INSTPREF) | (1 << CP0C6_DATAPREF),
>>>>>>> +        .CP0_Config6_rw_bitmask = (1 << CP0C6_BPPASS) | (0x3f << CP0C6_KPOS) |
>>>>>>> +                                  (1 << CP0C6_KE) | (1 << CP0C6_VTLBONLY) | (1 << CP0C6_LASX) |
>>>>>>> +                                  (1 << CP0C6_SSEN) | (1 << CP0C6_DISDRTIME) |
>>>>>>> +                                  (1 << CP0C6_PIXNUEN) | (1 << CP0C6_SCRAND) |
>>>>>>> +                                  (1 << CP0C6_LLEXCEN) | (1 << CP0C6_DISVC) |
>>>>>>> +                                  (1 << CP0C6_VCLRU) | (1 << CP0C6_DCLRU) |
>>>>>>> +                                  (1 << CP0C6_PIXUEN) | (1 << CP0C6_DISBLKLYEN) |
>>>>>>> +                                  (1 << CP0C6_UMEMUALEN) | (1 << CP0C6_SFBEN) |
>>>>>>> +                                  (1 << CP0C6_FLTINT) | (1 << CP0C6_VLTINT) |
>>>>>>> +                                  (1 << CP0C6_DISBTB) | (3 << CP0C6_STPREFCTL) |
>>>>>>> +                                  (1 << CP0C6_INSTPREF) | (1 << CP0C6_DATAPREF),
>>>>>>> +        .CP0_Config7 = 0,
>>>>>>> +        .CP0_Config7_rw_bitmask = (1 << CP0C7_NAPCGEN) | (1 << CP0C7_UNIMUEN) | \
>>>>>>> +                                  (1 << CP0C7_VFPUCGEN),
>>>>>>> +        .CP0_LLAddr_rw_bitmask = 1,
>>>>>>> +        .SYNCI_Step = 16,
>>>>>>> +        .CCRes = 2,
>>>>>>> +        .CP0_Status_rw_bitmask = 0x7DDBFFFF,
>>>>>>> +        .CP0_PageGrain_rw_bitmask = (1U << CP0PG_RIE) | (1 << CP0PG_XIE) |
>>>>>>> +                    (1 << CP0PG_ELPA) | (1 << CP0PG_IEC),
>>>>>>> +        .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x1 << FCR0_REV) | (0x1 << FCR0_F64),
>>>>>>> +        .CP1_fcr31 = 0,
>>>>>>> +        .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
>>>>>>> +        .SEGBITS = 48,
>>>>>>> +        .PABITS = 48,
>>>>>>> +        .insn_flags = CPU_LOONGSON3A,
>>>>>>> +        .mmu_type = MMU_TYPE_R4000,
>>>>>>> +    },
>>>>>>> +    {
>>>>>>>            /* A generic CPU providing MIPS64 DSP R2 ASE features.
>>>>>>>               FIXME: Eventually this should be replaced by a real CPU model. */
>>>>>>>            .name = "mips64dspr2",
>>>>>>>
>>>>>
>>>>>
>>>>>
>>>>> --
>>>>> Huacai Chen
>>>
> 


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH for-5.1 3/7] hw/mips: Add CPU IRQ3 delivery for KVM
  2020-04-29  1:52         ` Huacai Chen
@ 2020-04-29  9:17           ` Philippe Mathieu-Daudé
  2020-04-29 10:13             ` Huacai Chen
  0 siblings, 1 reply; 30+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-04-29  9:17 UTC (permalink / raw)
  To: Huacai Chen, Aleksandar Markovic; +Cc: chen huacai, qemu-level, Aurelien Jarno

On 4/29/20 3:52 AM, Huacai Chen wrote:
> Hi, Philippe and Aleksandar,
> 
> I'm not refusing to change my patch, but I have two questions:
> 1, Why we should identify Loongson-3 to deliver IP3? It seems that
> deliver all IPs (IP2~IP7) unconditionally is harmless as well.
> 2, How to identify Loongson-3 by Config6/Config7? Loongson-3 is not
> the only processor which has Config6/Config7.
Please don't top-post on technical lists, it makes the conversation
harder to follow.

This code is modelling the device, not KVM.

Commit b1bd8b28cca is not very verbose. I wonder why not delivering all 
IRQs to kvm_mips_set_interrupt, that would make this patch simpler.

I think the problem in QEMU MIPS IRQ delivery is one implementation is 
in cpu_mips_irq_request() while another one (vectored IRQ) in 
cpu_mips_hw_interrupts_pending (see 138afb024bb) and KVM is also in the 
middle.

And I see you selected CP0C3_VInt in the R4 definition... so what is 
delivered here?

> 
> Huacai
> 
> On Wed, Apr 29, 2020 at 2:58 AM Aleksandar Markovic
> <aleksandar.qemu.devel@gmail.com> wrote:
>>
>> уто, 28. апр 2020. у 10:21 chen huacai <zltjiangshi@gmail.com> је написао/ла:
>>>
>>> Hi, Philippe,
>>>
>>> On Mon, Apr 27, 2020 at 5:57 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>>>>
>>>> On 4/27/20 11:33 AM, Huacai Chen wrote:
>>>>> Currently, KVM/MIPS only deliver I/O interrupt via IP2, this patch add
>>>>> IP2 delivery as well, because Loongson-3 based machine use both IRQ2

"IP3 delivery as well"?

>>>>> (CPU's IP2) and IRQ3 (CPU's IP3).
>>>>>
>>>>> Signed-off-by: Huacai Chen <chenhc@lemote.com>
>>>>> Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
>>>>> ---
>>>>>   hw/mips/mips_int.c | 6 ++----
>>>>>   1 file changed, 2 insertions(+), 4 deletions(-)
>>>>>
>>>>> diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c
>>>>> index 796730b..5526219 100644
>>>>> --- a/hw/mips/mips_int.c
>>>>> +++ b/hw/mips/mips_int.c
>>>>> @@ -48,16 +48,14 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level)
>>>>>       if (level) {
>>>>>           env->CP0_Cause |= 1 << (irq + CP0Ca_IP);
>>>>>
>>>>> -        if (kvm_enabled() && irq == 2) {
>>>>> +        if (kvm_enabled() && (irq == 2 || irq == 3))
>>>>
>>>> Shouldn't we check env->CP0_Config6 (or Config7) has the required
>>>> feature first?
>>> I'm sorry that I can't understand IRQ delivery has something to do
>>> with Config6/Config7, to identify Loongson-3?
>>>
>>
>> Obviously, yes.
>>
>> Thanks,
>> Aleksandar
>>
>>
>>>>
>>>>>               kvm_mips_set_interrupt(cpu, irq, level);
>>>>> -        }
>>>>>
>>>>>       } else {
>>>>>           env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
>>>>>
>>>>> -        if (kvm_enabled() && irq == 2) {
>>>>> +        if (kvm_enabled() && (irq == 2 || irq == 3))
>>>>>               kvm_mips_set_interrupt(cpu, irq, level);
>>>>> -        }
>>>>>       }
>>>>>
>>>>>       if (env->CP0_Cause & CP0Ca_IP_mask) {
>>>>>
>>>
>>>
>>>
>>> --
>>> Huacai Chen
> 


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH for-5.1 4/7] target/mips: Add Loongson-3 CPU definition
  2020-04-29  8:58               ` Philippe Mathieu-Daudé
@ 2020-04-29  9:25                 ` Huacai Chen
  2020-04-29  9:30                   ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 30+ messages in thread
From: Huacai Chen @ 2020-04-29  9:25 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: chen huacai, Aleksandar Markovic, qemu-level, Aurelien Jarno

Hi, Philippe,

I think that this CPU definition is for Guest, not for Host (Maybe I'm wrong?).

On Wed, Apr 29, 2020 at 4:58 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>
> On 4/29/20 10:27 AM, Huacai Chen wrote:
> > Hi, Philippe,
> >
> > The major differences of R3 and R4 are:
> > 1, R4 has complete MIPS VZ ASE (while R3 is incomplete), so very
> > usable for KVM host;
>
> So you need to set CP0C3_VZ.
If the definition is for Guest, I think CP0C3_VZ should not be set in
CP0_Config3, because only the Host can see VZ ASE.

>
> > 2, R4 has MSA ASE while R3 hasn't;
>
> So you need to set CP0C5_MSAEn.
I have already set CP0C5_MSAEn CP0_Config5_rw_bitmask, but I don't
think it should be set in CP0_Config5 because MSA is disabled by
default.

>
> > 3, R4 has cpucfg, rdcsr and wrcsr instructions (similar to cpuid,
> > rdmsr and wrmsr in X86).
>
> OK, these are not implemented.
>
> [...]
>
> >>>>>>> diff --git a/target/mips/translate_init.inc.c b/target/mips/translate_init.inc.c
> >>>>>>> index 6d145a9..a32412d 100644
> >>>>>>> --- a/target/mips/translate_init.inc.c
> >>>>>>> +++ b/target/mips/translate_init.inc.c
> >>>>>>> @@ -802,6 +802,57 @@ const mips_def_t mips_defs[] =
> >>>>>>>            .mmu_type = MMU_TYPE_R4000,
> >>>>>>>        },
> >>>>>>>        {
> >>>>>>> +        .name = "Loongson-3A",
> >>>>>>> +        .CP0_PRid = 0x14C000,
> >>>>>>> +        /* 64KB I-cache and d-cache. 4 way with 32 bit cache line size.  */
> >>>>>>> +        .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
> >>>>>>> +                       (MMU_TYPE_R4000 << CP0C0_MT),
> >>>>>>> +        .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) |
> >>>>>>> +                       (2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
> >>>>>>> +                       (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
> >>>>>>> +                       (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
> >>>>>>> +        .CP0_Config2 = MIPS_CONFIG2,
> >>>>>>> +        .CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_MSAP) |
> >>>>>>> +                       (1 << CP0C3_BP) | (1 << CP0C3_BI) | (1 << CP0C3_ULRI) |
> >>>>>>> +                       (1 << CP0C3_RXI) | (1 << CP0C3_LPA) | (1 << CP0C3_VInt),
> >>>>>>> +        .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) | (2 << CP0C4_IE) |
> >>>>>>> +                       (1 << CP0C4_AE) | (0x1c << CP0C4_KScrExist),
> >>>>>>> +        .CP0_Config4_rw_bitmask = 0,
> >>>>>>> +        .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_NFExists) | (1 << 18),
> >>>>>>> +        .CP0_Config5_rw_bitmask = (1 << CP0C5_K) | (1 << CP0C5_CV) |
> >>>>>>> +                                  (1 << CP0C5_MSAEn) | (1 << CP0C5_UFE) |
> >>>>>>> +                                  (1 << CP0C5_FRE) | (1 << CP0C5_SBRI),
> >>>>>>> +        .CP0_Config6 = (1 << CP0C6_VCLRU) | (1 << CP0C6_DCLRU) | (1 << CP0C6_SFBEN) |
> >>>>>>> +                       (1 << CP0C6_FLTINT) | (1 << CP0C6_INSTPREF) | (1 << CP0C6_DATAPREF),
> >>>>>>> +        .CP0_Config6_rw_bitmask = (1 << CP0C6_BPPASS) | (0x3f << CP0C6_KPOS) |
> >>>>>>> +                                  (1 << CP0C6_KE) | (1 << CP0C6_VTLBONLY) | (1 << CP0C6_LASX) |
> >>>>>>> +                                  (1 << CP0C6_SSEN) | (1 << CP0C6_DISDRTIME) |
> >>>>>>> +                                  (1 << CP0C6_PIXNUEN) | (1 << CP0C6_SCRAND) |
> >>>>>>> +                                  (1 << CP0C6_LLEXCEN) | (1 << CP0C6_DISVC) |
> >>>>>>> +                                  (1 << CP0C6_VCLRU) | (1 << CP0C6_DCLRU) |
> >>>>>>> +                                  (1 << CP0C6_PIXUEN) | (1 << CP0C6_DISBLKLYEN) |
> >>>>>>> +                                  (1 << CP0C6_UMEMUALEN) | (1 << CP0C6_SFBEN) |
> >>>>>>> +                                  (1 << CP0C6_FLTINT) | (1 << CP0C6_VLTINT) |
> >>>>>>> +                                  (1 << CP0C6_DISBTB) | (3 << CP0C6_STPREFCTL) |
> >>>>>>> +                                  (1 << CP0C6_INSTPREF) | (1 << CP0C6_DATAPREF),
> >>>>>>> +        .CP0_Config7 = 0,
> >>>>>>> +        .CP0_Config7_rw_bitmask = (1 << CP0C7_NAPCGEN) | (1 << CP0C7_UNIMUEN) | \
> >>>>>>> +                                  (1 << CP0C7_VFPUCGEN),
> >>>>>>> +        .CP0_LLAddr_rw_bitmask = 1,
> >>>>>>> +        .SYNCI_Step = 16,
> >>>>>>> +        .CCRes = 2,
> >>>>>>> +        .CP0_Status_rw_bitmask = 0x7DDBFFFF,
> >>>>>>> +        .CP0_PageGrain_rw_bitmask = (1U << CP0PG_RIE) | (1 << CP0PG_XIE) |
> >>>>>>> +                    (1 << CP0PG_ELPA) | (1 << CP0PG_IEC),
> >>>>>>> +        .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x1 << FCR0_REV) | (0x1 << FCR0_F64),
> >>>>>>> +        .CP1_fcr31 = 0,
> >>>>>>> +        .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
> >>>>>>> +        .SEGBITS = 48,
> >>>>>>> +        .PABITS = 48,
> >>>>>>> +        .insn_flags = CPU_LOONGSON3A,
> >>>>>>> +        .mmu_type = MMU_TYPE_R4000,
> >>>>>>> +    },
> >>>>>>> +    {
> >>>>>>>            /* A generic CPU providing MIPS64 DSP R2 ASE features.
> >>>>>>>               FIXME: Eventually this should be replaced by a real CPU model. */
> >>>>>>>            .name = "mips64dspr2",
> >>>>>>>
> >>>>>
> >>>>>
> >>>>>
> >>>>> --
> >>>>> Huacai Chen
> >>>
> >


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH for-5.1 4/7] target/mips: Add Loongson-3 CPU definition
  2020-04-29  9:25                 ` Huacai Chen
@ 2020-04-29  9:30                   ` Philippe Mathieu-Daudé
  2020-04-29  9:54                     ` Huacai Chen
  0 siblings, 1 reply; 30+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-04-29  9:30 UTC (permalink / raw)
  To: Huacai Chen; +Cc: chen huacai, Aleksandar Markovic, qemu-level, Aurelien Jarno

On 4/29/20 11:25 AM, Huacai Chen wrote:
> Hi, Philippe,
> 
> I think that this CPU definition is for Guest, not for Host (Maybe I'm wrong?).

OK, it was not obvious to me (I haven't received the cover letter of 
this series).
The code you modified is used by both host emulation and guest 
virtualization.

If you want to only add a guest cpu type, you should name it 
"Loongson-3A virtualized" and can restrict with:

   if (kvm_enabled()) {
     add_guest_cpu();
   }

But cleaner is to add the host cpu regardless, and in cpu_state_reset() 
restrict when virtualized:

   if (kvm_enabled()) {
     /* disable host features on guest */
     env->CP0_Config3 &= ~CP0C3_VZ;
     ...
   }

> 
> On Wed, Apr 29, 2020 at 4:58 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>>
>> On 4/29/20 10:27 AM, Huacai Chen wrote:
>>> Hi, Philippe,
>>>
>>> The major differences of R3 and R4 are:
>>> 1, R4 has complete MIPS VZ ASE (while R3 is incomplete), so very
>>> usable for KVM host;
>>
>> So you need to set CP0C3_VZ.
> If the definition is for Guest, I think CP0C3_VZ should not be set in
> CP0_Config3, because only the Host can see VZ ASE.
> 
>>
>>> 2, R4 has MSA ASE while R3 hasn't;
>>
>> So you need to set CP0C5_MSAEn.
> I have already set CP0C5_MSAEn CP0_Config5_rw_bitmask, but I don't
> think it should be set in CP0_Config5 because MSA is disabled by
> default.
> 
>>
>>> 3, R4 has cpucfg, rdcsr and wrcsr instructions (similar to cpuid,
>>> rdmsr and wrmsr in X86).
>>
>> OK, these are not implemented.

I was looking at TCG emulation, now I understand why you don't mind 
about them there.

>>
>> [...]
>>
>>>>>>>>> diff --git a/target/mips/translate_init.inc.c b/target/mips/translate_init.inc.c
>>>>>>>>> index 6d145a9..a32412d 100644
>>>>>>>>> --- a/target/mips/translate_init.inc.c
>>>>>>>>> +++ b/target/mips/translate_init.inc.c
>>>>>>>>> @@ -802,6 +802,57 @@ const mips_def_t mips_defs[] =
>>>>>>>>>             .mmu_type = MMU_TYPE_R4000,
>>>>>>>>>         },
>>>>>>>>>         {
>>>>>>>>> +        .name = "Loongson-3A",
>>>>>>>>> +        .CP0_PRid = 0x14C000,
>>>>>>>>> +        /* 64KB I-cache and d-cache. 4 way with 32 bit cache line size.  */
>>>>>>>>> +        .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
>>>>>>>>> +                       (MMU_TYPE_R4000 << CP0C0_MT),
>>>>>>>>> +        .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) |
>>>>>>>>> +                       (2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
>>>>>>>>> +                       (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
>>>>>>>>> +                       (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
>>>>>>>>> +        .CP0_Config2 = MIPS_CONFIG2,
>>>>>>>>> +        .CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_MSAP) |
>>>>>>>>> +                       (1 << CP0C3_BP) | (1 << CP0C3_BI) | (1 << CP0C3_ULRI) |
>>>>>>>>> +                       (1 << CP0C3_RXI) | (1 << CP0C3_LPA) | (1 << CP0C3_VInt),
>>>>>>>>> +        .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) | (2 << CP0C4_IE) |
>>>>>>>>> +                       (1 << CP0C4_AE) | (0x1c << CP0C4_KScrExist),
>>>>>>>>> +        .CP0_Config4_rw_bitmask = 0,
>>>>>>>>> +        .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_NFExists) | (1 << 18),
>>>>>>>>> +        .CP0_Config5_rw_bitmask = (1 << CP0C5_K) | (1 << CP0C5_CV) |
>>>>>>>>> +                                  (1 << CP0C5_MSAEn) | (1 << CP0C5_UFE) |
>>>>>>>>> +                                  (1 << CP0C5_FRE) | (1 << CP0C5_SBRI),
>>>>>>>>> +        .CP0_Config6 = (1 << CP0C6_VCLRU) | (1 << CP0C6_DCLRU) | (1 << CP0C6_SFBEN) |
>>>>>>>>> +                       (1 << CP0C6_FLTINT) | (1 << CP0C6_INSTPREF) | (1 << CP0C6_DATAPREF),
>>>>>>>>> +        .CP0_Config6_rw_bitmask = (1 << CP0C6_BPPASS) | (0x3f << CP0C6_KPOS) |
>>>>>>>>> +                                  (1 << CP0C6_KE) | (1 << CP0C6_VTLBONLY) | (1 << CP0C6_LASX) |
>>>>>>>>> +                                  (1 << CP0C6_SSEN) | (1 << CP0C6_DISDRTIME) |
>>>>>>>>> +                                  (1 << CP0C6_PIXNUEN) | (1 << CP0C6_SCRAND) |
>>>>>>>>> +                                  (1 << CP0C6_LLEXCEN) | (1 << CP0C6_DISVC) |
>>>>>>>>> +                                  (1 << CP0C6_VCLRU) | (1 << CP0C6_DCLRU) |
>>>>>>>>> +                                  (1 << CP0C6_PIXUEN) | (1 << CP0C6_DISBLKLYEN) |
>>>>>>>>> +                                  (1 << CP0C6_UMEMUALEN) | (1 << CP0C6_SFBEN) |
>>>>>>>>> +                                  (1 << CP0C6_FLTINT) | (1 << CP0C6_VLTINT) |
>>>>>>>>> +                                  (1 << CP0C6_DISBTB) | (3 << CP0C6_STPREFCTL) |
>>>>>>>>> +                                  (1 << CP0C6_INSTPREF) | (1 << CP0C6_DATAPREF),
>>>>>>>>> +        .CP0_Config7 = 0,
>>>>>>>>> +        .CP0_Config7_rw_bitmask = (1 << CP0C7_NAPCGEN) | (1 << CP0C7_UNIMUEN) | \
>>>>>>>>> +                                  (1 << CP0C7_VFPUCGEN),
>>>>>>>>> +        .CP0_LLAddr_rw_bitmask = 1,
>>>>>>>>> +        .SYNCI_Step = 16,
>>>>>>>>> +        .CCRes = 2,
>>>>>>>>> +        .CP0_Status_rw_bitmask = 0x7DDBFFFF,
>>>>>>>>> +        .CP0_PageGrain_rw_bitmask = (1U << CP0PG_RIE) | (1 << CP0PG_XIE) |
>>>>>>>>> +                    (1 << CP0PG_ELPA) | (1 << CP0PG_IEC),
>>>>>>>>> +        .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x1 << FCR0_REV) | (0x1 << FCR0_F64),
>>>>>>>>> +        .CP1_fcr31 = 0,
>>>>>>>>> +        .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
>>>>>>>>> +        .SEGBITS = 48,
>>>>>>>>> +        .PABITS = 48,
>>>>>>>>> +        .insn_flags = CPU_LOONGSON3A,
>>>>>>>>> +        .mmu_type = MMU_TYPE_R4000,
>>>>>>>>> +    },
>>>>>>>>> +    {
>>>>>>>>>             /* A generic CPU providing MIPS64 DSP R2 ASE features.
>>>>>>>>>                FIXME: Eventually this should be replaced by a real CPU model. */
>>>>>>>>>             .name = "mips64dspr2",
>>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>> Huacai Chen
>>>>>
>>>
> 


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH for-5.1 4/7] target/mips: Add Loongson-3 CPU definition
  2020-04-29  9:30                   ` Philippe Mathieu-Daudé
@ 2020-04-29  9:54                     ` Huacai Chen
  0 siblings, 0 replies; 30+ messages in thread
From: Huacai Chen @ 2020-04-29  9:54 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: chen huacai, Aleksandar Markovic, qemu-level, Aurelien Jarno

Hi, Philippe,

On Wed, Apr 29, 2020 at 5:30 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>
> On 4/29/20 11:25 AM, Huacai Chen wrote:
> > Hi, Philippe,
> >
> > I think that this CPU definition is for Guest, not for Host (Maybe I'm wrong?).
>
> OK, it was not obvious to me (I haven't received the cover letter of
> this series).
> The code you modified is used by both host emulation and guest
> virtualization.
I'm very sorry that I hadn't send a cover letter...
Now I preparing the V2 series and I think put the cover letter of V2
here could make life easier...
----
Loongson-3 CPU family include Loongson-3A R1/R2/R3/R4 and Loongson-3B
R1/R2. Loongson-3A R1 is the oldest and its ISA is the smallest, while
Loongson-3A R4 is the newest and its ISA is almost the superset of all
others. To reduce complexity, in QEMU we just define two CPU types:

1, "Loongson-3A1000" CPU which is corresponding to Loongson-3A R1. It is
   suitable for TCG because Loongson-3A R1 has fewest ASE.
2, "Loongson-3A4000" CPU which is corresponding to Loongson-3A R4. It is
   suitable for KVM because Loongson-3A R4 has the VZ ASE.

Loongson-3 lacks English documents. I've tried to translated them with
translate.google.com, and the machine translated documents (together
with their original Chinese versions) are available here.

......

We are preparing to add QEMU's Loongson-3 support. MIPS VZ extension is
fully supported in Loongson-3A R4+, so we at first add QEMU/KVM support
in this series. And the next series will add QEMU/TCG support (it will
emulate Loongson-3A R1).

We already have a full functional Linux kernel (based on Linux-5.4.x LTS
but not upstream yet) here:

https://github.com/chenhuacai/linux

How to use QEMU/Loongson-3?
1, Download kernel source from the above URL;
2, Build a kernel with arch/mips/configs/loongson3_{def,hpc}config;
3, Boot the a Loongson-3A4000 host with this kernel;
4, Build QEMU-5.0.0 with this patchset;
5, modprobe kvm;
6, Use QEMU with TCG (available in future):
       qemu-system-mips64el -M loongson3,accel=tcg -cpu
Loongson-3A1000 -kernel <path_to_kernel> -append ...
   Use QEMU with KVM (available at present):
       qemu-system-mips64el -M loongson3,accel=kvm -cpu
Loongson-3A4000 -kernel <path_to_kernel> -append ...

   The "-cpu" parameter can be omitted here and QEMU will use the
correct type for TCG/KVM automatically.
----
>
> If you want to only add a guest cpu type, you should name it
> "Loongson-3A virtualized" and can restrict with:
>
>    if (kvm_enabled()) {
>      add_guest_cpu();
>    }
>
> But cleaner is to add the host cpu regardless, and in cpu_state_reset()
> restrict when virtualized:
>
>    if (kvm_enabled()) {
>      /* disable host features on guest */
>      env->CP0_Config3 &= ~CP0C3_VZ;
>      ...
>    }
>
> >
> > On Wed, Apr 29, 2020 at 4:58 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
> >>
> >> On 4/29/20 10:27 AM, Huacai Chen wrote:
> >>> Hi, Philippe,
> >>>
> >>> The major differences of R3 and R4 are:
> >>> 1, R4 has complete MIPS VZ ASE (while R3 is incomplete), so very
> >>> usable for KVM host;
> >>
> >> So you need to set CP0C3_VZ.
> > If the definition is for Guest, I think CP0C3_VZ should not be set in
> > CP0_Config3, because only the Host can see VZ ASE.
> >
> >>
> >>> 2, R4 has MSA ASE while R3 hasn't;
> >>
> >> So you need to set CP0C5_MSAEn.
> > I have already set CP0C5_MSAEn CP0_Config5_rw_bitmask, but I don't
> > think it should be set in CP0_Config5 because MSA is disabled by
> > default.
> >
> >>
> >>> 3, R4 has cpucfg, rdcsr and wrcsr instructions (similar to cpuid,
> >>> rdmsr and wrmsr in X86).
> >>
> >> OK, these are not implemented.
>
> I was looking at TCG emulation, now I understand why you don't mind
> about them there.
Assume that you have read my cover letter now. So TCG only need to
consider Loongson-3A1000 and KVM only need to consider Loongson-3A4000
(in V2 I will define two types of CPU).

>
> >>
> >> [...]
> >>
> >>>>>>>>> diff --git a/target/mips/translate_init.inc.c b/target/mips/translate_init.inc.c
> >>>>>>>>> index 6d145a9..a32412d 100644
> >>>>>>>>> --- a/target/mips/translate_init.inc.c
> >>>>>>>>> +++ b/target/mips/translate_init.inc.c
> >>>>>>>>> @@ -802,6 +802,57 @@ const mips_def_t mips_defs[] =
> >>>>>>>>>             .mmu_type = MMU_TYPE_R4000,
> >>>>>>>>>         },
> >>>>>>>>>         {
> >>>>>>>>> +        .name = "Loongson-3A",
> >>>>>>>>> +        .CP0_PRid = 0x14C000,
> >>>>>>>>> +        /* 64KB I-cache and d-cache. 4 way with 32 bit cache line size.  */
> >>>>>>>>> +        .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) | (0x2 << CP0C0_AT) |
> >>>>>>>>> +                       (MMU_TYPE_R4000 << CP0C0_MT),
> >>>>>>>>> +        .CP0_Config1 = MIPS_CONFIG1 | (1 << CP0C1_FP) | (63 << CP0C1_MMU) |
> >>>>>>>>> +                       (2 << CP0C1_IS) | (4 << CP0C1_IL) | (3 << CP0C1_IA) |
> >>>>>>>>> +                       (2 << CP0C1_DS) | (4 << CP0C1_DL) | (3 << CP0C1_DA) |
> >>>>>>>>> +                       (1 << CP0C1_PC) | (1 << CP0C1_WR) | (1 << CP0C1_EP),
> >>>>>>>>> +        .CP0_Config2 = MIPS_CONFIG2,
> >>>>>>>>> +        .CP0_Config3 = MIPS_CONFIG3 | (1U << CP0C3_M) | (1 << CP0C3_MSAP) |
> >>>>>>>>> +                       (1 << CP0C3_BP) | (1 << CP0C3_BI) | (1 << CP0C3_ULRI) |
> >>>>>>>>> +                       (1 << CP0C3_RXI) | (1 << CP0C3_LPA) | (1 << CP0C3_VInt),
> >>>>>>>>> +        .CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) | (2 << CP0C4_IE) |
> >>>>>>>>> +                       (1 << CP0C4_AE) | (0x1c << CP0C4_KScrExist),
> >>>>>>>>> +        .CP0_Config4_rw_bitmask = 0,
> >>>>>>>>> +        .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_NFExists) | (1 << 18),
> >>>>>>>>> +        .CP0_Config5_rw_bitmask = (1 << CP0C5_K) | (1 << CP0C5_CV) |
> >>>>>>>>> +                                  (1 << CP0C5_MSAEn) | (1 << CP0C5_UFE) |
> >>>>>>>>> +                                  (1 << CP0C5_FRE) | (1 << CP0C5_SBRI),
> >>>>>>>>> +        .CP0_Config6 = (1 << CP0C6_VCLRU) | (1 << CP0C6_DCLRU) | (1 << CP0C6_SFBEN) |
> >>>>>>>>> +                       (1 << CP0C6_FLTINT) | (1 << CP0C6_INSTPREF) | (1 << CP0C6_DATAPREF),
> >>>>>>>>> +        .CP0_Config6_rw_bitmask = (1 << CP0C6_BPPASS) | (0x3f << CP0C6_KPOS) |
> >>>>>>>>> +                                  (1 << CP0C6_KE) | (1 << CP0C6_VTLBONLY) | (1 << CP0C6_LASX) |
> >>>>>>>>> +                                  (1 << CP0C6_SSEN) | (1 << CP0C6_DISDRTIME) |
> >>>>>>>>> +                                  (1 << CP0C6_PIXNUEN) | (1 << CP0C6_SCRAND) |
> >>>>>>>>> +                                  (1 << CP0C6_LLEXCEN) | (1 << CP0C6_DISVC) |
> >>>>>>>>> +                                  (1 << CP0C6_VCLRU) | (1 << CP0C6_DCLRU) |
> >>>>>>>>> +                                  (1 << CP0C6_PIXUEN) | (1 << CP0C6_DISBLKLYEN) |
> >>>>>>>>> +                                  (1 << CP0C6_UMEMUALEN) | (1 << CP0C6_SFBEN) |
> >>>>>>>>> +                                  (1 << CP0C6_FLTINT) | (1 << CP0C6_VLTINT) |
> >>>>>>>>> +                                  (1 << CP0C6_DISBTB) | (3 << CP0C6_STPREFCTL) |
> >>>>>>>>> +                                  (1 << CP0C6_INSTPREF) | (1 << CP0C6_DATAPREF),
> >>>>>>>>> +        .CP0_Config7 = 0,
> >>>>>>>>> +        .CP0_Config7_rw_bitmask = (1 << CP0C7_NAPCGEN) | (1 << CP0C7_UNIMUEN) | \
> >>>>>>>>> +                                  (1 << CP0C7_VFPUCGEN),
> >>>>>>>>> +        .CP0_LLAddr_rw_bitmask = 1,
> >>>>>>>>> +        .SYNCI_Step = 16,
> >>>>>>>>> +        .CCRes = 2,
> >>>>>>>>> +        .CP0_Status_rw_bitmask = 0x7DDBFFFF,
> >>>>>>>>> +        .CP0_PageGrain_rw_bitmask = (1U << CP0PG_RIE) | (1 << CP0PG_XIE) |
> >>>>>>>>> +                    (1 << CP0PG_ELPA) | (1 << CP0PG_IEC),
> >>>>>>>>> +        .CP1_fcr0 = (0x5 << FCR0_PRID) | (0x1 << FCR0_REV) | (0x1 << FCR0_F64),
> >>>>>>>>> +        .CP1_fcr31 = 0,
> >>>>>>>>> +        .CP1_fcr31_rw_bitmask = 0xFF83FFFF,
> >>>>>>>>> +        .SEGBITS = 48,
> >>>>>>>>> +        .PABITS = 48,
> >>>>>>>>> +        .insn_flags = CPU_LOONGSON3A,
> >>>>>>>>> +        .mmu_type = MMU_TYPE_R4000,
> >>>>>>>>> +    },
> >>>>>>>>> +    {
> >>>>>>>>>             /* A generic CPU providing MIPS64 DSP R2 ASE features.
> >>>>>>>>>                FIXME: Eventually this should be replaced by a real CPU model. */
> >>>>>>>>>             .name = "mips64dspr2",
> >>>>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>>
> >>>>>>> --
> >>>>>>> Huacai Chen
> >>>>>
> >>>
> >


^ permalink raw reply	[flat|nested] 30+ messages in thread

* Re: [PATCH for-5.1 3/7] hw/mips: Add CPU IRQ3 delivery for KVM
  2020-04-29  9:17           ` Philippe Mathieu-Daudé
@ 2020-04-29 10:13             ` Huacai Chen
  0 siblings, 0 replies; 30+ messages in thread
From: Huacai Chen @ 2020-04-29 10:13 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: chen huacai, Aleksandar Markovic, qemu-level, Aurelien Jarno

Hi, Philippe,

On Wed, Apr 29, 2020 at 5:18 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>
> On 4/29/20 3:52 AM, Huacai Chen wrote:
> > Hi, Philippe and Aleksandar,
> >
> > I'm not refusing to change my patch, but I have two questions:
> > 1, Why we should identify Loongson-3 to deliver IP3? It seems that
> > deliver all IPs (IP2~IP7) unconditionally is harmless as well.
> > 2, How to identify Loongson-3 by Config6/Config7? Loongson-3 is not
> > the only processor which has Config6/Config7.
> Please don't top-post on technical lists, it makes the conversation
> harder to follow.
>
> This code is modelling the device, not KVM.
>
> Commit b1bd8b28cca is not very verbose. I wonder why not delivering all
> IRQs to kvm_mips_set_interrupt, that would make this patch simpler.
>
> I think the problem in QEMU MIPS IRQ delivery is one implementation is
> in cpu_mips_irq_request() while another one (vectored IRQ) in
> cpu_mips_hw_interrupts_pending (see 138afb024bb) and KVM is also in the
> middle.
I think the previous code only deliver IP2 is because KVM/MIPS only
use IP2 for external interrupts, but now I have changed KVM/MIPS as
well, please see:
https://patchwork.kernel.org/patch/11507591/

>
> And I see you selected CP0C3_VInt in the R4 definition... so what is
> delivered here?
CP0C3_VInt just indicates the capability, kernel of Loongson-3 doesn't use VINT.

>
> >
> > Huacai
> >
> > On Wed, Apr 29, 2020 at 2:58 AM Aleksandar Markovic
> > <aleksandar.qemu.devel@gmail.com> wrote:
> >>
> >> уто, 28. апр 2020. у 10:21 chen huacai <zltjiangshi@gmail.com> је написао/ла:
> >>>
> >>> Hi, Philippe,
> >>>
> >>> On Mon, Apr 27, 2020 at 5:57 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
> >>>>
> >>>> On 4/27/20 11:33 AM, Huacai Chen wrote:
> >>>>> Currently, KVM/MIPS only deliver I/O interrupt via IP2, this patch add
> >>>>> IP2 delivery as well, because Loongson-3 based machine use both IRQ2
>
> "IP3 delivery as well"?
Sorry, this is my fault.

>
> >>>>> (CPU's IP2) and IRQ3 (CPU's IP3).
> >>>>>
> >>>>> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> >>>>> Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> >>>>> ---
> >>>>>   hw/mips/mips_int.c | 6 ++----
> >>>>>   1 file changed, 2 insertions(+), 4 deletions(-)
> >>>>>
> >>>>> diff --git a/hw/mips/mips_int.c b/hw/mips/mips_int.c
> >>>>> index 796730b..5526219 100644
> >>>>> --- a/hw/mips/mips_int.c
> >>>>> +++ b/hw/mips/mips_int.c
> >>>>> @@ -48,16 +48,14 @@ static void cpu_mips_irq_request(void *opaque, int irq, int level)
> >>>>>       if (level) {
> >>>>>           env->CP0_Cause |= 1 << (irq + CP0Ca_IP);
> >>>>>
> >>>>> -        if (kvm_enabled() && irq == 2) {
> >>>>> +        if (kvm_enabled() && (irq == 2 || irq == 3))
> >>>>
> >>>> Shouldn't we check env->CP0_Config6 (or Config7) has the required
> >>>> feature first?
> >>> I'm sorry that I can't understand IRQ delivery has something to do
> >>> with Config6/Config7, to identify Loongson-3?
> >>>
> >>
> >> Obviously, yes.
> >>
> >> Thanks,
> >> Aleksandar
> >>
> >>
> >>>>
> >>>>>               kvm_mips_set_interrupt(cpu, irq, level);
> >>>>> -        }
> >>>>>
> >>>>>       } else {
> >>>>>           env->CP0_Cause &= ~(1 << (irq + CP0Ca_IP));
> >>>>>
> >>>>> -        if (kvm_enabled() && irq == 2) {
> >>>>> +        if (kvm_enabled() && (irq == 2 || irq == 3))
> >>>>>               kvm_mips_set_interrupt(cpu, irq, level);
> >>>>> -        }
> >>>>>       }
> >>>>>
> >>>>>       if (env->CP0_Cause & CP0Ca_IP_mask) {
> >>>>>
> >>>
> >>>
> >>>
> >>> --
> >>> Huacai Chen
> >


^ permalink raw reply	[flat|nested] 30+ messages in thread

end of thread, other threads:[~2020-04-29 10:06 UTC | newest]

Thread overview: 30+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-04-27  9:33 [PATCH for-5.1 1/7] configure: Add KVM target support for MIPS64 Huacai Chen
2020-04-27  9:33 ` [PATCH for-5.1 2/7] hw/mips: Implement the kvm_type() hook in MachineClass Huacai Chen
2020-04-27  9:33 ` [PATCH for-5.1 3/7] hw/mips: Add CPU IRQ3 delivery for KVM Huacai Chen
2020-04-27  9:57   ` Philippe Mathieu-Daudé
2020-04-28  8:28     ` chen huacai
2020-04-28 18:58       ` Aleksandar Markovic
2020-04-29  1:52         ` Huacai Chen
2020-04-29  9:17           ` Philippe Mathieu-Daudé
2020-04-29 10:13             ` Huacai Chen
2020-04-27  9:33 ` [PATCH for-5.1 4/7] target/mips: Add Loongson-3 CPU definition Huacai Chen
2020-04-28  6:34   ` Philippe Mathieu-Daudé
2020-04-28  8:34     ` chen huacai
2020-04-28 18:37       ` Aleksandar Markovic
2020-04-29  3:51         ` Huacai Chen
2020-04-29  8:09           ` Philippe Mathieu-Daudé
2020-04-29  8:27             ` Huacai Chen
2020-04-29  8:58               ` Philippe Mathieu-Daudé
2020-04-29  9:25                 ` Huacai Chen
2020-04-29  9:30                   ` Philippe Mathieu-Daudé
2020-04-29  9:54                     ` Huacai Chen
2020-04-27  9:33 ` [PATCH for-5.1 5/7] target/mips: Add more CP0 register for save/restore Huacai Chen
2020-04-28 19:10   ` Aleksandar Markovic
2020-04-29  1:11     ` Huacai Chen
2020-04-27  9:33 ` [PATCH for-5.1 6/7] hw/mips: Add Loongson-3 machine support (with KVM) Huacai Chen
2020-04-28 19:23   ` Aleksandar Markovic
2020-04-29  1:13     ` Huacai Chen
2020-04-27  9:33 ` [PATCH for-5.1 7/7] MAINTAINERS: Add myself as Loongson-3 maintainer Huacai Chen
2020-04-28  6:18   ` Philippe Mathieu-Daudé
2020-04-28  8:31     ` chen huacai
2020-04-28 19:15 ` [PATCH for-5.1 1/7] configure: Add KVM target support for MIPS64 Aleksandar Markovic

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.