qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V17 0/6] mips: Add Loongson-3 machine support
@ 2020-11-06  4:21 Huacai Chen
  2020-11-06  4:21 ` [PATCH V17 1/6] target/mips: Fix PageMask with variable page size Huacai Chen
                   ` (5 more replies)
  0 siblings, 6 replies; 31+ messages in thread
From: Huacai Chen @ 2020-11-06  4:21 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Aleksandar Rikalo, Huacai Chen, qemu-devel, Aleksandar Markovic,
	Huacai Chen, Aurelien Jarno

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.

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.

And human-translated documents (W.I.P) are available here now:
https://github.com/loongson-community/docs/tree/master/English-translation-of-Loongson-manual

Both KVM and TCG are available now!

We now already have a full functional Linux kernel (based on Linux-5.4.x
LTS) here:

https://github.com/chenhuacai/linux

Of course the upstream kernel is also usable (the kvm host side and
guest side have both been upstream in Linux-5.9):

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git

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

   The "-cpu" parameter is optional here and QEMU will use the correct type for TCG/KVM automatically.

V1 -> V2:
1, Add a cover letter;
2, Improve CPU definitions;
3, Remove LS7A-related things (Use GPEX instead);
4, Add a description of how to run QEMU/Loongson-3.

V2 -> V3:
1, Fix all possible checkpatch.pl errors and warnings.

V3 -> V4:
1, Sync code with upstream;
2, Remove merged patches;
3, Fix build failure without CONFIG_KVM;
4, Add Reviewed-by: Aleksandar Markovic <aleksandar.qemu.devel@gmail.com>.

V4 -> V5:
1, Improve coding style;
2, Remove merged patches;
3, Rename machine name from "loongson3" to "loongson3-virt";
4, Rework the "loongson3-virt" machine to drop any ISA things;
5, Rework "hw/mips: Implement the kvm_type() hook in MachineClass";
6, Add Jiaxun Yang as a reviewer of Loongson-3.

V5 -> V6:
1, Fix license preamble;
2, Improve commit messages;
3, Add hw/intc/loongson_liointc.c to MAINTAINERS;
4, Fix all possible checkpatch.pl errors and warnings.

V7 and V8 have only one patch (machine definition) with some minor improvements.

V8 -> V9:
1, Update KVM type definition from kernel;
2, Fix PageMask with variable page size for TCG;
3, Add TCG support (add Loongson-EXT instructions).

V9 -> V10:
1, Split fw_cfg to a separate patch;
2, Split boot parameters definition to a local header;
3, Update MIPS machine documentation;
4, Many other improvements suggested by Philippe Mathieu-Daudé.

V10 -> V11:
1, Fix some typos;
2, Add Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>.

V11 -> V12:
1, Split boot parameter helpers to loongson3_bootp.c;
2, Support both BE and LE host (Loongson guests are always LE).

V12 -> V13:
1, Sync code with upstream;
2, Re-enable KVM support for MIPS in meson;

V13 -> V14:
1, Remove merged patches;
2, Split boot parameter helpers to a separate patch;
3, Many other improvements suggested by Philippe Mathieu-Daudé.

V14 -> V15:
1, Remove merged patches;
2, Fix malta breakage caused by variable page size;
3, Add unaligned access support for Loongson-3's TCG mode;
4, Many other improvements suggested by Philippe Mathieu-Daudé.

V15 -> V16:
1, Remove some unused code;
2, Add Reviewed-by: Richard Henderson <richard.henderson@linaro.org>.

V16 -> V17:
1, Remove merged patches;
2, Rework Loongson LIOINTC;
3, Fix update_pagemask() for MIPS R6; 
4, Add Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>.

Huacai Chen and Jiaxun Yang (6):
 target/mips: Fix PageMask with variable page size
 hw/intc: Rework Loongson LIOINTC
 hw/mips: Implement fw_cfg_arch_key_name()
 hw/mips: Add Loongson-3 boot parameter helpers
 hw/mips: Add Loongson-3 machine support
 docs/system: Update MIPS machine documentation

Signed-off-by: Huacai Chen <chenhc@lemote.com>
---
 default-configs/devices/mips64el-softmmu.mak |   1 +
 docs/system/target-mips.rst                  |  10 +
 hw/intc/loongson_liointc.c                   |  49 +--
 hw/mips/Kconfig                              |  12 +
 hw/mips/fw_cfg.c                             |  35 ++
 hw/mips/fw_cfg.h                             |  19 +
 hw/mips/loongson3_bootp.c                    | 165 +++++++
 hw/mips/loongson3_bootp.h                    | 241 +++++++++++
 hw/mips/loongson3_virt.c                     | 614 +++++++++++++++++++++++++++
 hw/mips/meson.build                          |   3 +-
 include/hw/intc/loongson_liointc.h           |  39 ++
 target/mips/cp0_helper.c                     |  27 +-
 target/mips/cpu.h                            |   1 +
 13 files changed, 1174 insertions(+), 42 deletions(-)
 create mode 100644 hw/mips/fw_cfg.c
 create mode 100644 hw/mips/fw_cfg.h
 create mode 100644 hw/mips/loongson3_bootp.c
 create mode 100644 hw/mips/loongson3_bootp.h
 create mode 100644 hw/mips/loongson3_virt.c
 create mode 100644 include/hw/intc/loongson_liointc.h
--
2.7.0


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

* [PATCH V17 1/6] target/mips: Fix PageMask with variable page size
  2020-11-06  4:21 [PATCH V17 0/6] mips: Add Loongson-3 machine support Huacai Chen
@ 2020-11-06  4:21 ` Huacai Chen
  2020-11-07 12:11   ` Philippe Mathieu-Daudé
  2020-11-08 23:15   ` Philippe Mathieu-Daudé
  2020-11-06  4:21 ` [PATCH V17 2/6] hw/intc: Rework Loongson LIOINTC Huacai Chen
                   ` (4 subsequent siblings)
  5 siblings, 2 replies; 31+ messages in thread
From: Huacai Chen @ 2020-11-06  4:21 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Aleksandar Rikalo, Huacai Chen, qemu-devel, Aleksandar Markovic,
	Huacai Chen, Aurelien Jarno

From: Jiaxun Yang <jiaxun.yang@flygoat.com>

Our current code assumed the target page size is always 4k
when handling PageMask and VPN2, however, variable page size
was just added to mips target and that's no longer true.

Fixes: ee3863b9d414 ("target/mips: Support variable page size")
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Huacai Chen <chenhc@lemote.com>
---
 target/mips/cp0_helper.c | 27 +++++++++++++++++++++------
 target/mips/cpu.h        |  1 +
 2 files changed, 22 insertions(+), 6 deletions(-)

diff --git a/target/mips/cp0_helper.c b/target/mips/cp0_helper.c
index 709cc9a..92bf14f 100644
--- a/target/mips/cp0_helper.c
+++ b/target/mips/cp0_helper.c
@@ -892,13 +892,28 @@ void helper_mtc0_memorymapid(CPUMIPSState *env, target_ulong arg1)
 
 void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask)
 {
-    uint64_t mask = arg1 >> (TARGET_PAGE_BITS + 1);
-    if (!(env->insn_flags & ISA_MIPS32R6) || (arg1 == ~0) ||
-        (mask == 0x0000 || mask == 0x0003 || mask == 0x000F ||
-         mask == 0x003F || mask == 0x00FF || mask == 0x03FF ||
-         mask == 0x0FFF || mask == 0x3FFF || mask == 0xFFFF)) {
-        env->CP0_PageMask = arg1 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
+    unsigned long mask;
+    int maskbits;
+
+    /* Don't care MASKX as we don't support 1KB page */
+    mask = extract32((uint32_t)arg1, CP0PM_MASK, 16);
+    maskbits = find_first_zero_bit(&mask, 32);
+
+    /* Ensure no more set bit after first zero */
+    if (mask >> maskbits) {
+        goto invalid;
+    }
+    /* We don't support VTLB entry smaller than target page */
+    if ((maskbits + 12) < TARGET_PAGE_BITS) {
+        goto invalid;
     }
+    env->CP0_PageMask = mask << CP0PM_MASK;
+
+    return;
+
+invalid:
+    /* When invalid, set to default target page size. */
+    env->CP0_PageMask = (~TARGET_PAGE_MASK >> 12) << CP0PM_MASK;
 }
 
 void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1)
diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index d41579d..23f8c6f 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -619,6 +619,7 @@ struct CPUMIPSState {
  * CP0 Register 5
  */
     int32_t CP0_PageMask;
+#define CP0PM_MASK 13
     int32_t CP0_PageGrain_rw_bitmask;
     int32_t CP0_PageGrain;
 #define CP0PG_RIE 31
-- 
2.7.0



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

* [PATCH V17 2/6] hw/intc: Rework Loongson LIOINTC
  2020-11-06  4:21 [PATCH V17 0/6] mips: Add Loongson-3 machine support Huacai Chen
  2020-11-06  4:21 ` [PATCH V17 1/6] target/mips: Fix PageMask with variable page size Huacai Chen
@ 2020-11-06  4:21 ` Huacai Chen
  2020-11-23 20:52   ` Philippe Mathieu-Daudé
  2020-11-06  4:21 ` [PATCH V17 3/6] hw/mips: Implement fw_cfg_arch_key_name() Huacai Chen
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 31+ messages in thread
From: Huacai Chen @ 2020-11-06  4:21 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Aleksandar Rikalo, Huacai Chen, qemu-devel, Aleksandar Markovic,
	Huacai Chen, Aurelien Jarno

As suggested by Philippe Mathieu-Daudé, rework Loongson's liointc:
1, Move macro definitions to loongson_liointc.h;
2, Remove magic values and use macros instead;
3, Replace dead D() code by trace events.

Suggested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Huacai Chen <chenhc@lemote.com>
---
 hw/intc/loongson_liointc.c         | 49 +++++++++++---------------------------
 include/hw/intc/loongson_liointc.h | 39 ++++++++++++++++++++++++++++++
 2 files changed, 53 insertions(+), 35 deletions(-)
 create mode 100644 include/hw/intc/loongson_liointc.h

diff --git a/hw/intc/loongson_liointc.c b/hw/intc/loongson_liointc.c
index fbbfb57..be29e2f 100644
--- a/hw/intc/loongson_liointc.c
+++ b/hw/intc/loongson_liointc.c
@@ -1,6 +1,7 @@
 /*
  * QEMU Loongson Local I/O interrupt controler.
  *
+ * Copyright (c) 2020 Huacai Chen <chenhc@lemote.com>
  * Copyright (c) 2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
  *
  * This program is free software: you can redistribute it and/or modify
@@ -19,33 +20,11 @@
  */
 
 #include "qemu/osdep.h"
-#include "hw/sysbus.h"
 #include "qemu/module.h"
+#include "qemu/log.h"
 #include "hw/irq.h"
 #include "hw/qdev-properties.h"
-#include "qom/object.h"
-
-#define D(x)
-
-#define NUM_IRQS                32
-
-#define NUM_CORES               4
-#define NUM_IPS                 4
-#define NUM_PARENTS             (NUM_CORES * NUM_IPS)
-#define PARENT_COREx_IPy(x, y)  (NUM_IPS * x + y)
-
-#define R_MAPPER_START          0x0
-#define R_MAPPER_END            0x20
-#define R_ISR                   R_MAPPER_END
-#define R_IEN                   0x24
-#define R_IEN_SET               0x28
-#define R_IEN_CLR               0x2c
-#define R_PERCORE_ISR(x)        (0x40 + 0x8 * x)
-#define R_END                   0x64
-
-#define TYPE_LOONGSON_LIOINTC "loongson.liointc"
-DECLARE_INSTANCE_CHECKER(struct loongson_liointc, LOONGSON_LIOINTC,
-                         TYPE_LOONGSON_LIOINTC)
+#include "hw/intc/loongson_liointc.h"
 
 struct loongson_liointc {
     SysBusDevice parent_obj;
@@ -123,14 +102,13 @@ liointc_read(void *opaque, hwaddr addr, unsigned int size)
         goto out;
     }
 
-    /* Rest is 4 byte */
+    /* Rest are 4 bytes */
     if (size != 4 || (addr % 4)) {
         goto out;
     }
 
-    if (addr >= R_PERCORE_ISR(0) &&
-        addr < R_PERCORE_ISR(NUM_CORES)) {
-        int core = (addr - R_PERCORE_ISR(0)) / 8;
+    if (addr >= R_START && addr < R_END) {
+        int core = (addr - R_START) / R_ISR_SIZE;
         r = p->per_core_isr[core];
         goto out;
     }
@@ -147,7 +125,8 @@ liointc_read(void *opaque, hwaddr addr, unsigned int size)
     }
 
 out:
-    D(qemu_log("%s: size=%d addr=%lx val=%x\n", __func__, size, addr, r));
+    qemu_log_mask(CPU_LOG_INT, "%s: size=%d addr=%lx val=%x\n",
+                  __func__, size, addr, r);
     return r;
 }
 
@@ -158,7 +137,8 @@ liointc_write(void *opaque, hwaddr addr,
     struct loongson_liointc *p = opaque;
     uint32_t value = val64;
 
-    D(qemu_log("%s: size=%d, addr=%lx val=%x\n", __func__, size, addr, value));
+    qemu_log_mask(CPU_LOG_INT, "%s: size=%d, addr=%lx val=%x\n",
+                  __func__, size, addr, value);
 
     /* Mapper is 1 byte */
     if (size == 1 && addr < R_MAPPER_END) {
@@ -166,14 +146,13 @@ liointc_write(void *opaque, hwaddr addr,
         goto out;
     }
 
-    /* Rest is 4 byte */
+    /* Rest are 4 bytes */
     if (size != 4 || (addr % 4)) {
         goto out;
     }
 
-    if (addr >= R_PERCORE_ISR(0) &&
-        addr < R_PERCORE_ISR(NUM_CORES)) {
-        int core = (addr - R_PERCORE_ISR(0)) / 8;
+    if (addr >= R_START && addr < R_END) {
+        int core = (addr - R_START) / R_ISR_SIZE;
         p->per_core_isr[core] = value;
         goto out;
     }
@@ -224,7 +203,7 @@ static void loongson_liointc_init(Object *obj)
     }
 
     memory_region_init_io(&p->mmio, obj, &pic_ops, p,
-                         "loongson.liointc", R_END);
+                         TYPE_LOONGSON_LIOINTC, R_END);
     sysbus_init_mmio(SYS_BUS_DEVICE(obj), &p->mmio);
 }
 
diff --git a/include/hw/intc/loongson_liointc.h b/include/hw/intc/loongson_liointc.h
new file mode 100644
index 0000000..e11f482
--- /dev/null
+++ b/include/hw/intc/loongson_liointc.h
@@ -0,0 +1,39 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (c) 2020 Huacai Chen <chenhc@lemote.com>
+ * Copyright (c) 2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
+ *
+ */
+
+#ifndef LOONSGON_LIOINTC_H
+#define LOONGSON_LIOINTC_H
+
+#include "qemu/units.h"
+#include "hw/sysbus.h"
+#include "qom/object.h"
+
+#define NUM_IRQS                32
+
+#define NUM_CORES               4
+#define NUM_IPS                 4
+#define NUM_PARENTS             (NUM_CORES * NUM_IPS)
+#define PARENT_COREx_IPy(x, y)  (NUM_IPS * x + y)
+
+#define R_MAPPER_START          0x0
+#define R_MAPPER_END            0x20
+#define R_ISR                   R_MAPPER_END
+#define R_IEN                   0x24
+#define R_IEN_SET               0x28
+#define R_IEN_CLR               0x2c
+#define R_ISR_SIZE              0x8
+#define R_START                 0x40
+#define R_END                   0x64
+
+#define TYPE_LOONGSON_LIOINTC "loongson.liointc"
+DECLARE_INSTANCE_CHECKER(struct loongson_liointc, LOONGSON_LIOINTC,
+                         TYPE_LOONGSON_LIOINTC)
+
+#endif /* LOONGSON_LIOINTC_H */
-- 
2.7.0



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

* [PATCH V17 3/6] hw/mips: Implement fw_cfg_arch_key_name()
  2020-11-06  4:21 [PATCH V17 0/6] mips: Add Loongson-3 machine support Huacai Chen
  2020-11-06  4:21 ` [PATCH V17 1/6] target/mips: Fix PageMask with variable page size Huacai Chen
  2020-11-06  4:21 ` [PATCH V17 2/6] hw/intc: Rework Loongson LIOINTC Huacai Chen
@ 2020-11-06  4:21 ` Huacai Chen
  2020-11-06  4:21 ` [PATCH V17 4/6] hw/mips: Add Loongson-3 boot parameter helpers Huacai Chen
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 31+ messages in thread
From: Huacai Chen @ 2020-11-06  4:21 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Aleksandar Rikalo, Huacai Chen, qemu-devel, Aleksandar Markovic,
	Huacai Chen, Aurelien Jarno

Implement fw_cfg_arch_key_name(), which returns the name of a
mips-specific key.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Huacai Chen <chenhc@lemote.com>
Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 hw/mips/fw_cfg.c    | 35 +++++++++++++++++++++++++++++++++++
 hw/mips/fw_cfg.h    | 19 +++++++++++++++++++
 hw/mips/meson.build |  2 +-
 3 files changed, 55 insertions(+), 1 deletion(-)
 create mode 100644 hw/mips/fw_cfg.c
 create mode 100644 hw/mips/fw_cfg.h

diff --git a/hw/mips/fw_cfg.c b/hw/mips/fw_cfg.c
new file mode 100644
index 0000000..67c4a74
--- /dev/null
+++ b/hw/mips/fw_cfg.c
@@ -0,0 +1,35 @@
+/*
+ * QEMU fw_cfg helpers (MIPS specific)
+ *
+ * Copyright (c) 2020 Lemote, Inc.
+ *
+ * Author:
+ *   Huacai Chen (chenhc@lemote.com)
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/mips/fw_cfg.h"
+#include "hw/nvram/fw_cfg.h"
+
+const char *fw_cfg_arch_key_name(uint16_t key)
+{
+    static const struct {
+        uint16_t key;
+        const char *name;
+    } fw_cfg_arch_wellknown_keys[] = {
+        {FW_CFG_MACHINE_VERSION, "machine_version"},
+        {FW_CFG_CPU_FREQ, "cpu_frequency"},
+    };
+
+    for (size_t i = 0; i < ARRAY_SIZE(fw_cfg_arch_wellknown_keys); i++) {
+        if (fw_cfg_arch_wellknown_keys[i].key == key) {
+            return fw_cfg_arch_wellknown_keys[i].name;
+        }
+    }
+    return NULL;
+}
diff --git a/hw/mips/fw_cfg.h b/hw/mips/fw_cfg.h
new file mode 100644
index 0000000..e317d5b
--- /dev/null
+++ b/hw/mips/fw_cfg.h
@@ -0,0 +1,19 @@
+/*
+ * QEMU fw_cfg helpers (MIPS specific)
+ *
+ * Copyright (c) 2020 Huacai Chen
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#ifndef HW_MIPS_FW_CFG_H
+#define HW_MIPS_FW_CFG_H
+
+#include "hw/boards.h"
+#include "hw/nvram/fw_cfg.h"
+
+/* Data for BIOS to identify machine */
+#define FW_CFG_MACHINE_VERSION  (FW_CFG_ARCH_LOCAL + 0)
+#define FW_CFG_CPU_FREQ         (FW_CFG_ARCH_LOCAL + 1)
+
+#endif
diff --git a/hw/mips/meson.build b/hw/mips/meson.build
index bcdf96b..0e9f930 100644
--- a/hw/mips/meson.build
+++ b/hw/mips/meson.build
@@ -1,5 +1,5 @@
 mips_ss = ss.source_set()
-mips_ss.add(files('addr.c', 'mips_int.c'))
+mips_ss.add(files('addr.c', 'mips_int.c', 'fw_cfg.c'))
 mips_ss.add(when: 'CONFIG_FULOONG', if_true: files('fuloong2e.c'))
 mips_ss.add(when: 'CONFIG_JAZZ', if_true: files('jazz.c'))
 mips_ss.add(when: 'CONFIG_MALTA', if_true: files('gt64xxx_pci.c', 'malta.c'))
-- 
2.7.0



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

* [PATCH V17 4/6] hw/mips: Add Loongson-3 boot parameter helpers
  2020-11-06  4:21 [PATCH V17 0/6] mips: Add Loongson-3 machine support Huacai Chen
                   ` (2 preceding siblings ...)
  2020-11-06  4:21 ` [PATCH V17 3/6] hw/mips: Implement fw_cfg_arch_key_name() Huacai Chen
@ 2020-11-06  4:21 ` Huacai Chen
  2020-11-23 22:25   ` Philippe Mathieu-Daudé
  2020-12-13 23:24   ` Philippe Mathieu-Daudé
  2020-11-06  4:21 ` [PATCH V17 5/6] hw/mips: Add Loongson-3 machine support Huacai Chen
  2020-11-06  4:21 ` [PATCH V17 6/6] docs/system: Update MIPS machine documentation Huacai Chen
  5 siblings, 2 replies; 31+ messages in thread
From: Huacai Chen @ 2020-11-06  4:21 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Aleksandar Rikalo, Huacai Chen, qemu-devel, Aleksandar Markovic,
	Huacai Chen, Aurelien Jarno

Preparing to add Loongson-3 machine support, add Loongson-3's LEFI (a
UEFI-like interface for BIOS-Kernel boot parameters) helpers first.

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Huacai Chen <chenhc@lemote.com>
Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 hw/mips/loongson3_bootp.c | 165 +++++++++++++++++++++++++++++++
 hw/mips/loongson3_bootp.h | 241 ++++++++++++++++++++++++++++++++++++++++++++++
 hw/mips/meson.build       |   1 +
 3 files changed, 407 insertions(+)
 create mode 100644 hw/mips/loongson3_bootp.c
 create mode 100644 hw/mips/loongson3_bootp.h

diff --git a/hw/mips/loongson3_bootp.c b/hw/mips/loongson3_bootp.c
new file mode 100644
index 0000000..3a16081
--- /dev/null
+++ b/hw/mips/loongson3_bootp.c
@@ -0,0 +1,165 @@
+/*
+ * LEFI (a UEFI-like interface for BIOS-Kernel boot parameters) helpers
+ *
+ * Copyright (c) 2018-2020 Huacai Chen (chenhc@lemote.com)
+ * Copyright (c) 2018-2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "qemu/cutils.h"
+#include "cpu.h"
+#include "hw/boards.h"
+#include "hw/mips/loongson3_bootp.h"
+
+#define LOONGSON3_CORE_PER_NODE 4
+
+static struct efi_cpuinfo_loongson *init_cpu_info(void *g_cpuinfo, uint64_t cpu_freq)
+{
+    struct efi_cpuinfo_loongson *c = g_cpuinfo;
+
+    stl_le_p(&c->cputype, Loongson_3A);
+    stl_le_p(&c->processor_id, MIPS_CPU(first_cpu)->env.CP0_PRid);
+    if (cpu_freq > UINT_MAX) {
+        stl_le_p(&c->cpu_clock_freq, UINT_MAX);
+    } else {
+        stl_le_p(&c->cpu_clock_freq, cpu_freq);
+    }
+
+    stw_le_p(&c->cpu_startup_core_id, 0);
+    stl_le_p(&c->nr_cpus, current_machine->smp.cpus);
+    stl_le_p(&c->total_node, DIV_ROUND_UP(current_machine->smp.cpus,
+                                          LOONGSON3_CORE_PER_NODE));
+
+    return c;
+}
+
+static struct efi_memory_map_loongson *init_memory_map(void *g_map, uint64_t ram_size)
+{
+    struct efi_memory_map_loongson *emap = g_map;
+
+    stl_le_p(&emap->nr_map, 2);
+    stl_le_p(&emap->mem_freq, 300000000);
+
+    stl_le_p(&emap->map[0].node_id, 0);
+    stl_le_p(&emap->map[0].mem_type, 1);
+    stq_le_p(&emap->map[0].mem_start, 0x0);
+    stl_le_p(&emap->map[0].mem_size, 240);
+
+    stl_le_p(&emap->map[1].node_id, 0);
+    stl_le_p(&emap->map[1].mem_type, 2);
+    stq_le_p(&emap->map[1].mem_start, 0x90000000);
+    stl_le_p(&emap->map[1].mem_size, (ram_size / MiB) - 256);
+
+    return emap;
+}
+
+static struct system_loongson *init_system_loongson(void *g_system)
+{
+    struct system_loongson *s = g_system;
+
+    stl_le_p(&s->ccnuma_smp, 0);
+    stl_le_p(&s->sing_double_channel, 1);
+    stl_le_p(&s->nr_uarts, 1);
+    stl_le_p(&s->uarts[0].iotype, 2);
+    stl_le_p(&s->uarts[0].int_offset, 2);
+    stl_le_p(&s->uarts[0].uartclk, 25000000); /* Random value */
+    stq_le_p(&s->uarts[0].uart_base, virt_memmap[VIRT_UART].base);
+
+    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;
+
+    stl_le_p(&irq_info->node_id, 0);
+    stl_le_p(&irq_info->PIC_type, 0);
+    stw_le_p(&irq_info->dma_mask_bits, 64);
+    stq_le_p(&irq_info->pci_mem_start_addr, virt_memmap[VIRT_PCIE_MMIO].base);
+    stq_le_p(&irq_info->pci_mem_end_addr, virt_memmap[VIRT_PCIE_MMIO].base +
+                                          virt_memmap[VIRT_PCIE_MMIO].size - 1);
+    stq_le_p(&irq_info->pci_io_start_addr, virt_memmap[VIRT_PCIE_PIO].base);
+
+    return irq_info;
+}
+
+static struct interface_info *init_interface_info(void *g_interface)
+{
+    struct interface_info *interface = g_interface;
+
+    stw_le_p(&interface->vers, 0x01);
+    strpadcpy(interface->description, 64, "UEFI_Version_v1.0", '\0');
+
+    return interface;
+}
+
+static struct board_devices *board_devices_info(void *g_board)
+{
+    struct board_devices *bd = g_board;
+
+    strpadcpy(bd->name, 64, "Loongson-3A-VIRT-1w-V1.00-demo", '\0');
+
+    return bd;
+}
+
+static struct loongson_special_attribute *init_special_info(void *g_special)
+{
+    struct loongson_special_attribute *special = g_special;
+
+    strpadcpy(special->special_name, 64, "2018-04-01", '\0');
+
+    return special;
+}
+
+void init_loongson_params(struct loongson_params *lp, void *p,
+                          uint64_t cpu_freq, uint64_t ram_size)
+{
+    stq_le_p(&lp->cpu_offset,
+              (uintptr_t)init_cpu_info(p, cpu_freq) - (uintptr_t)lp);
+    p += ROUND_UP(sizeof(struct efi_cpuinfo_loongson), 64);
+
+    stq_le_p(&lp->memory_offset,
+              (uintptr_t)init_memory_map(p, ram_size) - (uintptr_t)lp);
+    p += ROUND_UP(sizeof(struct efi_memory_map_loongson), 64);
+
+    stq_le_p(&lp->system_offset,
+              (uintptr_t)init_system_loongson(p) - (uintptr_t)lp);
+    p += ROUND_UP(sizeof(struct system_loongson), 64);
+
+    stq_le_p(&lp->irq_offset,
+              (uintptr_t)init_irq_source(p) - (uintptr_t)lp);
+    p += ROUND_UP(sizeof(struct irq_source_routing_table), 64);
+
+    stq_le_p(&lp->interface_offset,
+              (uintptr_t)init_interface_info(p) - (uintptr_t)lp);
+    p += ROUND_UP(sizeof(struct interface_info), 64);
+
+    stq_le_p(&lp->boarddev_table_offset,
+              (uintptr_t)board_devices_info(p) - (uintptr_t)lp);
+    p += ROUND_UP(sizeof(struct board_devices), 64);
+
+    stq_le_p(&lp->special_offset,
+              (uintptr_t)init_special_info(p) - (uintptr_t)lp);
+    p += ROUND_UP(sizeof(struct loongson_special_attribute), 64);
+}
+
+void init_reset_system(struct efi_reset_system_t *reset)
+{
+    stq_le_p(&reset->Shutdown, 0xffffffffbfc000a8);
+    stq_le_p(&reset->ResetCold, 0xffffffffbfc00080);
+    stq_le_p(&reset->ResetWarm, 0xffffffffbfc00080);
+}
diff --git a/hw/mips/loongson3_bootp.h b/hw/mips/loongson3_bootp.h
new file mode 100644
index 0000000..bf4fd8c
--- /dev/null
+++ b/hw/mips/loongson3_bootp.h
@@ -0,0 +1,241 @@
+/*
+ * LEFI (a UEFI-like interface for BIOS-Kernel boot parameters) data structrues
+ * defined at arch/mips/include/asm/mach-loongson64/boot_param.h in Linux kernel
+ *
+ * Copyright (c) 2017-2020 Huacai Chen (chenhc@lemote.com)
+ * Copyright (c) 2017-2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef HW_MIPS_LOONGSON3_BOOTP_H
+#define HW_MIPS_LOONGSON3_BOOTP_H
+
+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];
+} QEMU_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];
+} QEMU_PACKED;
+
+#define MAX_UARTS 64
+struct uart_device {
+    uint32_t iotype;
+    uint32_t uartclk;
+    uint32_t int_offset;
+    uint64_t uart_base;
+} QEMU_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; /* step speed or constant speed */
+    uint32_t fan_percent;/* only for constant speed policy */
+    uint64_t base_addr;  /* base address of device registers */
+} QEMU_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;
+    uint64_t of_dtb_addr; /* NULL if not support */
+} QEMU_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;
+} QEMU_PACKED;
+
+struct interface_info {
+    uint16_t vers;               /* version of the specificition */
+    uint16_t size;
+    uint8_t  flag;
+    char description[64];
+} QEMU_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;
+};
+
+/* Overall MMIO & Memory layout */
+enum {
+    VIRT_LOWMEM,
+    VIRT_PM,
+    VIRT_FW_CFG,
+    VIRT_RTC,
+    VIRT_PCIE_PIO,
+    VIRT_PCIE_ECAM,
+    VIRT_BIOS_ROM,
+    VIRT_UART,
+    VIRT_LIOINTC,
+    VIRT_PCIE_MMIO,
+    VIRT_HIGHMEM
+};
+
+/* Low MEM layout for QEMU kernel loader */
+enum {
+    LOADER_KERNEL,
+    LOADER_INITRD,
+    LOADER_CMDLINE
+};
+
+/* BIOS ROM layout for QEMU kernel loader */
+enum {
+    LOADER_BOOTROM,
+    LOADER_PARAM,
+};
+
+struct MemmapEntry {
+    hwaddr base;
+    hwaddr size;
+};
+
+extern const struct MemmapEntry virt_memmap[];
+void init_loongson_params(struct loongson_params *lp, void *p,
+                          uint64_t cpu_freq, uint64_t ram_size);
+void init_reset_system(struct efi_reset_system_t *reset);
+
+#endif
diff --git a/hw/mips/meson.build b/hw/mips/meson.build
index 0e9f930..9e58c2b 100644
--- a/hw/mips/meson.build
+++ b/hw/mips/meson.build
@@ -1,6 +1,7 @@
 mips_ss = ss.source_set()
 mips_ss.add(files('addr.c', 'mips_int.c', 'fw_cfg.c'))
 mips_ss.add(when: 'CONFIG_FULOONG', if_true: files('fuloong2e.c'))
+mips_ss.add(when: 'CONFIG_LOONGSON3V', if_true: files('loongson3_bootp.c'))
 mips_ss.add(when: 'CONFIG_JAZZ', if_true: files('jazz.c'))
 mips_ss.add(when: 'CONFIG_MALTA', if_true: files('gt64xxx_pci.c', 'malta.c'))
 mips_ss.add(when: 'CONFIG_MIPSSIM', if_true: files('mipssim.c'))
-- 
2.7.0



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

* [PATCH V17 5/6] hw/mips: Add Loongson-3 machine support
  2020-11-06  4:21 [PATCH V17 0/6] mips: Add Loongson-3 machine support Huacai Chen
                   ` (3 preceding siblings ...)
  2020-11-06  4:21 ` [PATCH V17 4/6] hw/mips: Add Loongson-3 boot parameter helpers Huacai Chen
@ 2020-11-06  4:21 ` Huacai Chen
  2020-11-23 21:54   ` Philippe Mathieu-Daudé
  2020-11-06  4:21 ` [PATCH V17 6/6] docs/system: Update MIPS machine documentation Huacai Chen
  5 siblings, 1 reply; 31+ messages in thread
From: Huacai Chen @ 2020-11-06  4:21 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Aleksandar Rikalo, Huacai Chen, qemu-devel, Aleksandar Markovic,
	Huacai Chen, Aurelien Jarno

Add Loongson-3 based machine support, it use liointc as the interrupt
controler and use GPEX as the pci controller. Currently it can work with
both TCG and KVM.

As the machine model is not based on any exiting physical hardware, the
name of the machine is "loongson3-virt". It may be superseded in future
by a real machine model. If this happens, then a regular deprecation
procedure shall occur for "loongson3-virt" machine.

We now already have a full functional Linux kernel (based on Linux-5.4.x
LTS) here:

https://github.com/chenhuacai/linux

Of course the upstream kernel is also usable (the kvm host side and
guest side have both been upstream in Linux-5.9):

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git

How to use QEMU/Loongson-3?
1, Download kernel source from the above URL;
2, Build a kernel with arch/mips/configs/loongson3_defconfig;
3, Boot a Loongson-3A4000 host with this kernel (for KVM mode);
4, Build QEMU-master with this patchset;
5, modprobe kvm (only necessary for KVM mode);
6, Use QEMU with TCG:
       qemu-system-mips64el -M loongson3-virt,accel=tcg -cpu Loongson-3A1000 -kernel <path_to_kernel> -append ...
   Use QEMU with KVM:
       qemu-system-mips64el -M loongson3-virt,accel=kvm -cpu Loongson-3A4000 -kernel <path_to_kernel> -append ...

   The "-cpu" parameter is optional here and QEMU will use the correct type for TCG/KVM automatically.

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 default-configs/devices/mips64el-softmmu.mak |   1 +
 hw/mips/Kconfig                              |  12 +
 hw/mips/loongson3_virt.c                     | 614 +++++++++++++++++++++++++++
 hw/mips/meson.build                          |   2 +-
 4 files changed, 628 insertions(+), 1 deletion(-)
 create mode 100644 hw/mips/loongson3_virt.c

diff --git a/default-configs/devices/mips64el-softmmu.mak b/default-configs/devices/mips64el-softmmu.mak
index 9f8a3ef..26c660a 100644
--- a/default-configs/devices/mips64el-softmmu.mak
+++ b/default-configs/devices/mips64el-softmmu.mak
@@ -3,6 +3,7 @@
 include mips-softmmu-common.mak
 CONFIG_IDE_VIA=y
 CONFIG_FULOONG=y
+CONFIG_LOONGSON3V=y
 CONFIG_ATI_VGA=y
 CONFIG_RTL8139_PCI=y
 CONFIG_JAZZ=y
diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig
index 8be7012..ef5cee1 100644
--- a/hw/mips/Kconfig
+++ b/hw/mips/Kconfig
@@ -32,6 +32,18 @@ config FULOONG
     bool
     select PCI_BONITO
 
+config LOONGSON3V
+    bool
+    select PCKBD
+    select SERIAL
+    select GOLDFISH_RTC
+    select LOONGSON_LIOINTC
+    select PCI_DEVICES
+    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/loongson3_virt.c b/hw/mips/loongson3_virt.c
new file mode 100644
index 0000000..c5db2db
--- /dev/null
+++ b/hw/mips/loongson3_virt.c
@@ -0,0 +1,614 @@
+/*
+ * Generic Loongson-3 Platform support
+ *
+ * Copyright (c) 2018-2020 Huacai Chen (chenhc@lemote.com)
+ * Copyright (c) 2018-2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+/*
+ * Generic virtualized 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 "qemu/cutils.h"
+#include "qapi/error.h"
+#include "cpu.h"
+#include "elf.h"
+#include "kvm_mips.h"
+#include "hw/boards.h"
+#include "hw/char/serial.h"
+#include "hw/intc/loongson_liointc.h"
+#include "hw/mips/mips.h"
+#include "hw/mips/cpudevs.h"
+#include "hw/mips/fw_cfg.h"
+#include "hw/mips/loongson3_bootp.h"
+#include "hw/misc/unimp.h"
+#include "hw/intc/i8259.h"
+#include "hw/loader.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/usb.h"
+#include "net/net.h"
+#include "exec/address-spaces.h"
+#include "sysemu/kvm.h"
+#include "sysemu/qtest.h"
+#include "sysemu/reset.h"
+#include "sysemu/runstate.h"
+#include "qemu/log.h"
+#include "qemu/error-report.h"
+
+#define PM_CNTL_MODE          0x10
+
+#define LOONGSON_MAX_VCPUS      16
+
+/*
+ * Loongson-3's virtual machine BIOS can be obtained here:
+ * 1, https://github.com/loongson-community/firmware-nonfree
+ * 2, http://dev.lemote.com:8000/files/firmware/UEFI/KVM/bios_loongson3.bin
+ */
+#define LOONGSON3_BIOSNAME "bios_loongson3.bin"
+
+#define UART_IRQ            0
+#define RTC_IRQ             1
+#define PCIE_IRQ_BASE       2
+
+const struct MemmapEntry virt_memmap[] = {
+    [VIRT_LOWMEM] =      { 0x00000000,    0x10000000 },
+    [VIRT_PM] =          { 0x10080000,         0x100 },
+    [VIRT_FW_CFG] =      { 0x10080100,         0x100 },
+    [VIRT_RTC] =         { 0x10081000,        0x1000 },
+    [VIRT_PCIE_PIO] =    { 0x18000000,       0x80000 },
+    [VIRT_PCIE_ECAM] =   { 0x1a000000,     0x2000000 },
+    [VIRT_BIOS_ROM] =    { 0x1fc00000,      0x200000 },
+    [VIRT_UART] =        { 0x1fe001e0,           0x8 },
+    [VIRT_LIOINTC] =     { 0x3ff01400,          0x64 },
+    [VIRT_PCIE_MMIO] =   { 0x40000000,    0x40000000 },
+    [VIRT_HIGHMEM] =     { 0x80000000,           0x0 }, /* Variable */
+};
+
+static const struct MemmapEntry loader_memmap[] = {
+    [LOADER_KERNEL] =    { 0x00000000,     0x4000000 },
+    [LOADER_INITRD] =    { 0x04000000,           0x0 }, /* Variable */
+    [LOADER_CMDLINE] =   { 0x0ff00000,      0x100000 },
+};
+
+static const struct MemmapEntry loader_rommap[] = {
+    [LOADER_BOOTROM] =   { 0x1fc00000,        0x1000 },
+    [LOADER_PARAM] =     { 0x1fc01000,       0x10000 },
+};
+
+static struct _loaderparams {
+    uint64_t cpu_freq;
+    uint64_t ram_size;
+    const char *kernel_cmdline;
+    const char *kernel_filename;
+    const char *initrd_filename;
+    uint64_t kernel_entry;
+    uint64_t a0, a1, a2;
+} loaderparams;
+
+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,
+};
+
+#define DEF_LOONGSON3_FREQ (800 * 1000 * 1000)
+
+static uint64_t get_cpu_freq_hz(void)
+{
+#ifdef CONFIG_KVM
+    int ret;
+    uint64_t freq;
+    struct kvm_one_reg freq_reg = {
+        .id = KVM_REG_MIPS_COUNT_HZ,
+        .addr = (uintptr_t)(&freq)
+    };
+
+    if (kvm_enabled()) {
+        ret = kvm_vcpu_ioctl(first_cpu, KVM_GET_ONE_REG, &freq_reg);
+        if (ret >= 0) {
+            return freq * 2;
+        }
+    }
+#endif
+    return DEF_LOONGSON3_FREQ;
+}
+
+static void init_boot_param(void)
+{
+    void *p;
+    struct boot_params *bp;
+
+    p = g_malloc0(loader_rommap[LOADER_PARAM].size);
+    bp = p;
+
+    stw_le_p(&bp->efi.smbios.vers, 1);
+    init_reset_system(&(bp->reset_system));
+    p += ROUND_UP(sizeof(struct boot_params), 64);
+    init_loongson_params(&(bp->efi.smbios.lp), p,
+                         loaderparams.cpu_freq, loaderparams.ram_size);
+
+    rom_add_blob_fixed("params_rom", bp,
+                       loader_rommap[LOADER_PARAM].size,
+                       loader_rommap[LOADER_PARAM].base);
+
+    g_free(bp);
+
+    loaderparams.a2 = cpu_mips_phys_to_kseg0(NULL, loader_rommap[LOADER_PARAM].base);
+}
+
+static void init_boot_rom(void)
+{
+    const unsigned int boot_code[] = {
+        0x40086000,   /* mfc0    t0, CP0_STATUS                               */
+        0x240900E4,   /* li      t1, 0xe4         #set kx, sx, ux, erl        */
+        0x01094025,   /* or      t0, t0, t1                                   */
+        0x3C090040,   /* lui     t1, 0x40         #set 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                                                  */
+    };
+
+    rom_add_blob_fixed("boot_rom", boot_code, sizeof(boot_code),
+                        loader_rommap[LOADER_BOOTROM].base);
+}
+
+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;
+    hwaddr cfg_addr = virt_memmap[VIRT_FW_CFG].base;
+
+    fw_cfg = fw_cfg_init_mem_wide(cfg_addr, cfg_addr + 8, 8, 0, NULL);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)current_machine->smp.cpus);
+    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)current_machine->smp.max_cpus);
+    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
+    fw_cfg_add_i32(fw_cfg, FW_CFG_MACHINE_VERSION, 1);
+    fw_cfg_add_i64(fw_cfg, FW_CFG_CPU_FREQ, get_cpu_freq_hz());
+    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
+}
+
+static int set_prom_cmdline(ram_addr_t initrd_offset, long initrd_size)
+{
+    hwaddr cmdline_vaddr;
+    char memenv[32];
+    char highmemenv[32];
+    void *cmdline_buf;
+    unsigned int *parg_env;
+    int ret = 0;
+
+    /* Allocate cmdline_buf for command line. */
+    cmdline_buf = g_malloc0(loader_memmap[LOADER_CMDLINE].size);
+    cmdline_vaddr = cpu_mips_phys_to_kseg0(NULL,
+                                           loader_memmap[LOADER_CMDLINE].base);
+
+    /*
+     * Layout of cmdline_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 *)cmdline_buf;
+
+    ret = (3 + 1) * 4;
+    *parg_env++ = cmdline_vaddr + ret;
+    ret += (1 + snprintf(cmdline_buf + ret, 256 - ret, "g"));
+
+    /* argv1 */
+    *parg_env++ = cmdline_vaddr + ret;
+    if (initrd_size > 0)
+        ret += (1 + snprintf(cmdline_buf + ret, 256 - ret,
+                "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
+                cpu_mips_phys_to_kseg0(NULL, initrd_offset),
+                initrd_size, loaderparams.kernel_cmdline));
+    else
+        ret += (1 + snprintf(cmdline_buf + ret, 256 - ret, "%s",
+                loaderparams.kernel_cmdline));
+
+    /* argv2 */
+    *parg_env++ = cmdline_vaddr + 4 * ret;
+
+    /* env */
+    sprintf(memenv, "%d", 256);
+    sprintf(highmemenv, "%ld", (unsigned long)(loaderparams.ram_size / MiB) - 256);
+
+    rom_add_blob_fixed("cmdline", cmdline_buf,
+                       loader_memmap[LOADER_CMDLINE].size,
+                       loader_memmap[LOADER_CMDLINE].base);
+
+    g_free(cmdline_buf);
+
+    loaderparams.a0 = 2;
+    loaderparams.a1 = cmdline_vaddr;
+
+    return 0;
+}
+
+static uint64_t load_kernel(CPUMIPSState *env)
+{
+    long kernel_size;
+    ram_addr_t initrd_offset;
+    uint64_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 = MAX(loader_memmap[LOADER_INITRD].base,
+                                ROUND_UP(kernel_high, INITRD_PAGE_SIZE));
+
+            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 cmdline. */
+    set_prom_cmdline(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 inline void loongson3_virt_devices_init(MachineState *machine, DeviceState *pic)
+{
+    int i;
+    qemu_irq irq;
+    PCIBus *pci_bus;
+    DeviceState *dev;
+    MemoryRegion *pio_alias;
+    MemoryRegion *mmio_alias, *mmio_reg;
+    MemoryRegion *ecam_alias, *ecam_reg;
+
+    dev = qdev_new(TYPE_GPEX_HOST);
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
+    pci_bus = PCI_HOST_BRIDGE(dev)->bus;
+
+    ecam_alias = g_new0(MemoryRegion, 1);
+    ecam_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
+    memory_region_init_alias(ecam_alias, OBJECT(dev), "pcie-ecam",
+                             ecam_reg, 0, virt_memmap[VIRT_PCIE_ECAM].size);
+    memory_region_add_subregion(get_system_memory(),
+                                virt_memmap[VIRT_PCIE_ECAM].base, ecam_alias);
+
+    mmio_alias = g_new0(MemoryRegion, 1);
+    mmio_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1);
+    memory_region_init_alias(mmio_alias, OBJECT(dev), "pcie-mmio",
+                             mmio_reg, virt_memmap[VIRT_PCIE_MMIO].base,
+                             virt_memmap[VIRT_PCIE_MMIO].size);
+    memory_region_add_subregion(get_system_memory(),
+                                virt_memmap[VIRT_PCIE_MMIO].base, mmio_alias);
+
+    pio_alias = g_new0(MemoryRegion, 1);
+    memory_region_init_alias(pio_alias, OBJECT(dev), "pcie-pio",
+                             get_system_io(), 0, virt_memmap[VIRT_PCIE_PIO].size);
+    memory_region_add_subregion(get_system_memory(),
+                                virt_memmap[VIRT_PCIE_PIO].base, pio_alias);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, virt_memmap[VIRT_PCIE_PIO].base);
+
+    for (i = 0; i < GPEX_NUM_IRQS; i++) {
+        irq = qdev_get_gpio_in(pic, PCIE_IRQ_BASE + i);
+        sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, irq);
+        gpex_set_irq_num(GPEX_HOST(dev), i, PCIE_IRQ_BASE + i);
+    }
+
+    pci_vga_init(pci_bus);
+
+    if (defaults_enabled()) {
+        pci_create_simple(pci_bus, -1, "pci-ohci");
+        usb_create_simple(usb_bus_find(-1), "usb-kbd");
+        usb_create_simple(usb_bus_find(-1), "usb-tablet");
+    }
+
+    for (i = 0; i < nb_nics; i++) {
+        NICInfo *nd = &nd_table[i];
+
+        if (!nd->model) {
+            nd->model = g_strdup("virtio");
+        }
+
+        pci_nic_init_nofail(nd, pci_bus, nd->model, NULL);
+    }
+}
+
+static void mips_loongson3_virt_init(MachineState *machine)
+{
+    int i;
+    long bios_size;
+    MIPSCPU *cpu;
+    Clock *cpuclk;
+    CPUMIPSState *env;
+    DeviceState *liointc;
+    char *filename;
+    const char *kernel_cmdline = machine->kernel_cmdline;
+    const char *kernel_filename = machine->kernel_filename;
+    const char *initrd_filename = machine->initrd_filename;
+    ram_addr_t ram_size = machine->ram_size;
+    MemoryRegion *address_space_mem = get_system_memory();
+    MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *bios = g_new(MemoryRegion, 1);
+    MemoryRegion *iomem = g_new(MemoryRegion, 1);
+
+    /* TODO: TCG will support all CPU types */
+    if (!kvm_enabled()) {
+        if (!machine->cpu_type) {
+            machine->cpu_type = MIPS_CPU_TYPE_NAME("Loongson-3A1000");
+        }
+        if (!strstr(machine->cpu_type, "Loongson-3A1000")) {
+            error_report("Loongson-3/TCG needs cpu type Loongson-3A1000");
+            exit(1);
+        }
+    } else {
+        if (!machine->cpu_type) {
+            machine->cpu_type = MIPS_CPU_TYPE_NAME("Loongson-3A4000");
+        }
+        if (!strstr(machine->cpu_type, "Loongson-3A4000")) {
+            error_report("Loongson-3/KVM needs cpu type Loongson-3A4000");
+            exit(1);
+        }
+    }
+
+    if (ram_size < 512 * MiB) {
+        error_report("Loongson-3 machine needs at least 512MB memory");
+        exit(1);
+    }
+
+    /*
+     * The whole MMIO range among configure registers doesn't generate
+     * exception when accessing invalid memory. Create some unimplememted
+     * devices to emulate this feature.
+     */
+    create_unimplemented_device("mmio fallback 0", 0x10000000, 256 * MiB);
+    create_unimplemented_device("mmio fallback 1", 0x30000000, 256 * MiB);
+
+    liointc = qdev_new("loongson.liointc");
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(liointc), &error_fatal);
+
+    sysbus_mmio_map(SYS_BUS_DEVICE(liointc), 0, virt_memmap[VIRT_LIOINTC].base);
+
+    serial_mm_init(address_space_mem, virt_memmap[VIRT_UART].base, 0,
+                   qdev_get_gpio_in(liointc, UART_IRQ), 115200, serial_hd(0),
+                   DEVICE_NATIVE_ENDIAN);
+
+    sysbus_create_simple("goldfish_rtc", virt_memmap[VIRT_RTC].base,
+                         qdev_get_gpio_in(liointc, RTC_IRQ));
+
+    cpuclk = clock_new(OBJECT(machine), "cpu-refclk");
+    clock_set_hz(cpuclk, DEF_LOONGSON3_FREQ);
+
+    for (i = 0; i < machine->smp.cpus; i++) {
+        int ip;
+
+        /* init CPUs */
+        cpu = mips_cpu_create_with_clock(machine->cpu_type, cpuclk);
+
+        /* Init internal devices */
+        cpu_mips_irq_init_cpu(cpu);
+        cpu_mips_clock_init(cpu);
+        qemu_register_reset(main_cpu_reset, cpu);
+
+        if (i >= 4) {
+            continue; /* Only node-0 can be connected to LIOINTC */
+        }
+
+        for (ip = 0; ip < 4 ; ip++) {
+            int pin = i * 4 + ip;
+            sysbus_connect_irq(SYS_BUS_DEVICE(liointc),
+                               pin, cpu->env.irq[ip + 2]);
+        }
+    }
+    env = &MIPS_CPU(first_cpu)->env;
+
+    /* Allocate RAM/BIOS, 0x00000000~0x10000000 is alias of 0x80000000~0x90000000 */
+    memory_region_init_rom(bios, NULL, "loongson3.bios",
+                           virt_memmap[VIRT_BIOS_ROM].size, &error_fatal);
+    memory_region_init_alias(ram, NULL, "loongson3.lowmem",
+                           machine->ram, 0, virt_memmap[VIRT_LOWMEM].size);
+    memory_region_init_io(iomem, NULL, &loongson3_pm_ops,
+                           NULL, "loongson3_pm", virt_memmap[VIRT_PM].size);
+
+    memory_region_add_subregion(address_space_mem,
+                      virt_memmap[VIRT_LOWMEM].base, ram);
+    memory_region_add_subregion(address_space_mem,
+                      virt_memmap[VIRT_BIOS_ROM].base, bios);
+    memory_region_add_subregion(address_space_mem,
+                      virt_memmap[VIRT_HIGHMEM].base, machine->ram);
+    memory_region_add_subregion(address_space_mem,
+                      virt_memmap[VIRT_PM].base, iomem);
+
+    /*
+     * We do not support flash operation, just loading bios.bin as raw BIOS.
+     * Please use -L to set the BIOS path and -bios to set bios name.
+     */
+
+    if (kernel_filename) {
+        loaderparams.cpu_freq = get_cpu_freq_hz();
+        loaderparams.ram_size = ram_size;
+        loaderparams.kernel_filename = kernel_filename;
+        loaderparams.kernel_cmdline = kernel_cmdline;
+        loaderparams.initrd_filename = initrd_filename;
+        loaderparams.kernel_entry = load_kernel(env);
+
+        init_boot_rom();
+        init_boot_param();
+    } 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,
+                                            virt_memmap[VIRT_BIOS_ROM].base,
+                                            virt_memmap[VIRT_BIOS_ROM].size);
+            g_free(filename);
+        } else {
+            bios_size = -1;
+        }
+
+        if ((bios_size < 0 || bios_size > virt_memmap[VIRT_BIOS_ROM].size) &&
+            !kernel_filename && !qtest_enabled()) {
+            error_report("Could not load MIPS bios '%s'", bios_name);
+            exit(1);
+        }
+
+        fw_conf_init(ram_size);
+    }
+
+    msi_nonbroken = true;
+    loongson3_virt_devices_init(machine, liointc);
+}
+
+static void mips_loongson3_virt_machine_init(MachineClass *mc)
+{
+    mc->desc = "Loongson-3 Virtualization Platform";
+    mc->init = mips_loongson3_virt_init;
+    mc->block_default_type = IF_IDE;
+    mc->max_cpus = LOONGSON_MAX_VCPUS;
+    mc->default_ram_id = "loongson3.highram";
+    mc->default_ram_size = 1600 * MiB;
+    mc->kvm_type = mips_kvm_type;
+    mc->minimum_page_bits = 14;
+}
+
+DEFINE_MACHINE("loongson3-virt", mips_loongson3_virt_machine_init)
diff --git a/hw/mips/meson.build b/hw/mips/meson.build
index 9e58c2b..73a961d 100644
--- a/hw/mips/meson.build
+++ b/hw/mips/meson.build
@@ -1,7 +1,7 @@
 mips_ss = ss.source_set()
 mips_ss.add(files('addr.c', 'mips_int.c', 'fw_cfg.c'))
 mips_ss.add(when: 'CONFIG_FULOONG', if_true: files('fuloong2e.c'))
-mips_ss.add(when: 'CONFIG_LOONGSON3V', if_true: files('loongson3_bootp.c'))
+mips_ss.add(when: 'CONFIG_LOONGSON3V', if_true: files('loongson3_bootp.c', 'loongson3_virt.c'))
 mips_ss.add(when: 'CONFIG_JAZZ', if_true: files('jazz.c'))
 mips_ss.add(when: 'CONFIG_MALTA', if_true: files('gt64xxx_pci.c', 'malta.c'))
 mips_ss.add(when: 'CONFIG_MIPSSIM', if_true: files('mipssim.c'))
-- 
2.7.0



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

* [PATCH V17 6/6] docs/system: Update MIPS machine documentation
  2020-11-06  4:21 [PATCH V17 0/6] mips: Add Loongson-3 machine support Huacai Chen
                   ` (4 preceding siblings ...)
  2020-11-06  4:21 ` [PATCH V17 5/6] hw/mips: Add Loongson-3 machine support Huacai Chen
@ 2020-11-06  4:21 ` Huacai Chen
  2020-11-23 20:52   ` Philippe Mathieu-Daudé
  5 siblings, 1 reply; 31+ messages in thread
From: Huacai Chen @ 2020-11-06  4:21 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Aleksandar Rikalo, Huacai Chen, qemu-devel, Aleksandar Markovic,
	Huacai Chen, Aurelien Jarno

Update MIPS machine documentation to add Loongson-3 based machine description.

Signed-off-by: Huacai Chen <chenhc@lemote.com>
---
 docs/system/target-mips.rst | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/docs/system/target-mips.rst b/docs/system/target-mips.rst
index cd2a931..138441b 100644
--- a/docs/system/target-mips.rst
+++ b/docs/system/target-mips.rst
@@ -84,6 +84,16 @@ The Fuloong 2E emulation supports:
 
 -  RTL8139D as a network card chipset
 
+The Loongson-3 virtual platform emulation supports:
+
+-  Loongson 3A CPU
+
+-  LIOINTC as interrupt controller
+
+-  GPEX and virtio as peripheral devices
+
+-  Both KVM and TCG supported
+
 The mipssim pseudo board emulation provides an environment similar to
 what the proprietary MIPS emulator uses for running Linux. It supports:
 
-- 
2.7.0



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

* Re: [PATCH V17 1/6] target/mips: Fix PageMask with variable page size
  2020-11-06  4:21 ` [PATCH V17 1/6] target/mips: Fix PageMask with variable page size Huacai Chen
@ 2020-11-07 12:11   ` Philippe Mathieu-Daudé
  2020-11-08  1:34     ` Huacai Chen
  2020-11-08 23:15   ` Philippe Mathieu-Daudé
  1 sibling, 1 reply; 31+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-11-07 12:11 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Aleksandar Rikalo, Huacai Chen, qemu-devel, Aleksandar Markovic,
	Huacai Chen, Aurelien Jarno

Hi Huacai,

On 11/6/20 5:21 AM, Huacai Chen wrote:
> From: Jiaxun Yang <jiaxun.yang@flygoat.com>
> 
> Our current code assumed the target page size is always 4k
> when handling PageMask and VPN2, however, variable page size
> was just added to mips target and that's no longer true.
> 
> Fixes: ee3863b9d414 ("target/mips: Support variable page size")
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> ---
>  target/mips/cp0_helper.c | 27 +++++++++++++++++++++------
>  target/mips/cpu.h        |  1 +
>  2 files changed, 22 insertions(+), 6 deletions(-)

Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

> 
> diff --git a/target/mips/cp0_helper.c b/target/mips/cp0_helper.c
> index 709cc9a..92bf14f 100644
> --- a/target/mips/cp0_helper.c
> +++ b/target/mips/cp0_helper.c
> @@ -892,13 +892,28 @@ void helper_mtc0_memorymapid(CPUMIPSState *env, target_ulong arg1)
>  
>  void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask)
>  {
> -    uint64_t mask = arg1 >> (TARGET_PAGE_BITS + 1);
> -    if (!(env->insn_flags & ISA_MIPS32R6) || (arg1 == ~0) ||
> -        (mask == 0x0000 || mask == 0x0003 || mask == 0x000F ||
> -         mask == 0x003F || mask == 0x00FF || mask == 0x03FF ||
> -         mask == 0x0FFF || mask == 0x3FFF || mask == 0xFFFF)) {
> -        env->CP0_PageMask = arg1 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
> +    unsigned long mask;
> +    int maskbits;
> +
> +    /* Don't care MASKX as we don't support 1KB page */
> +    mask = extract32((uint32_t)arg1, CP0PM_MASK, 16);

I'd simply use extract64().

> +    maskbits = find_first_zero_bit(&mask, 32);
> +
> +    /* Ensure no more set bit after first zero */
> +    if (mask >> maskbits) {
> +        goto invalid;
> +    }
> +    /* We don't support VTLB entry smaller than target page */
> +    if ((maskbits + 12) < TARGET_PAGE_BITS) {

I suppose the magic 12 is TARGET_PAGE_BITS_MIN, right?

If you confirm I can do the change when applying (no need to
repost the whole series).

> +        goto invalid;
>      }
> +    env->CP0_PageMask = mask << CP0PM_MASK;
> +
> +    return;
> +
> +invalid:
> +    /* When invalid, set to default target page size. */
> +    env->CP0_PageMask = (~TARGET_PAGE_MASK >> 12) << CP0PM_MASK;

Ditto.

>  }
>  
>  void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1)
> diff --git a/target/mips/cpu.h b/target/mips/cpu.h
> index d41579d..23f8c6f 100644
> --- a/target/mips/cpu.h
> +++ b/target/mips/cpu.h
> @@ -619,6 +619,7 @@ struct CPUMIPSState {
>   * CP0 Register 5
>   */
>      int32_t CP0_PageMask;
> +#define CP0PM_MASK 13
>      int32_t CP0_PageGrain_rw_bitmask;
>      int32_t CP0_PageGrain;
>  #define CP0PG_RIE 31
> 


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

* Re: [PATCH V17 1/6] target/mips: Fix PageMask with variable page size
  2020-11-07 12:11   ` Philippe Mathieu-Daudé
@ 2020-11-08  1:34     ` Huacai Chen
  0 siblings, 0 replies; 31+ messages in thread
From: Huacai Chen @ 2020-11-08  1:34 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Huacai Chen, Aleksandar Rikalo, QEMU Developers, Aurelien Jarno,
	Aleksandar Markovic

Hi, Philippe,

On Sat, Nov 7, 2020 at 8:11 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>
> Hi Huacai,
>
> On 11/6/20 5:21 AM, Huacai Chen wrote:
> > From: Jiaxun Yang <jiaxun.yang@flygoat.com>
> >
> > Our current code assumed the target page size is always 4k
> > when handling PageMask and VPN2, however, variable page size
> > was just added to mips target and that's no longer true.
> >
> > Fixes: ee3863b9d414 ("target/mips: Support variable page size")
> > Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> > Signed-off-by: Huacai Chen <chenhc@lemote.com>
> > ---
> >  target/mips/cp0_helper.c | 27 +++++++++++++++++++++------
> >  target/mips/cpu.h        |  1 +
> >  2 files changed, 22 insertions(+), 6 deletions(-)
>
> Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
>
> >
> > diff --git a/target/mips/cp0_helper.c b/target/mips/cp0_helper.c
> > index 709cc9a..92bf14f 100644
> > --- a/target/mips/cp0_helper.c
> > +++ b/target/mips/cp0_helper.c
> > @@ -892,13 +892,28 @@ void helper_mtc0_memorymapid(CPUMIPSState *env, target_ulong arg1)
> >
> >  void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask)
> >  {
> > -    uint64_t mask = arg1 >> (TARGET_PAGE_BITS + 1);
> > -    if (!(env->insn_flags & ISA_MIPS32R6) || (arg1 == ~0) ||
> > -        (mask == 0x0000 || mask == 0x0003 || mask == 0x000F ||
> > -         mask == 0x003F || mask == 0x00FF || mask == 0x03FF ||
> > -         mask == 0x0FFF || mask == 0x3FFF || mask == 0xFFFF)) {
> > -        env->CP0_PageMask = arg1 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
> > +    unsigned long mask;
> > +    int maskbits;
> > +
> > +    /* Don't care MASKX as we don't support 1KB page */
> > +    mask = extract32((uint32_t)arg1, CP0PM_MASK, 16);
>
> I'd simply use extract64().
>
> > +    maskbits = find_first_zero_bit(&mask, 32);
> > +
> > +    /* Ensure no more set bit after first zero */
> > +    if (mask >> maskbits) {
> > +        goto invalid;
> > +    }
> > +    /* We don't support VTLB entry smaller than target page */
> > +    if ((maskbits + 12) < TARGET_PAGE_BITS) {
>
> I suppose the magic 12 is TARGET_PAGE_BITS_MIN, right?
>
> If you confirm I can do the change when applying (no need to
> repost the whole series).
Yes, 12 is TARGET_PAGE_BITS_MIN.

Huacai
>
> > +        goto invalid;
> >      }
> > +    env->CP0_PageMask = mask << CP0PM_MASK;
> > +
> > +    return;
> > +
> > +invalid:
> > +    /* When invalid, set to default target page size. */
> > +    env->CP0_PageMask = (~TARGET_PAGE_MASK >> 12) << CP0PM_MASK;
>
> Ditto.
>
> >  }
> >
> >  void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1)
> > diff --git a/target/mips/cpu.h b/target/mips/cpu.h
> > index d41579d..23f8c6f 100644
> > --- a/target/mips/cpu.h
> > +++ b/target/mips/cpu.h
> > @@ -619,6 +619,7 @@ struct CPUMIPSState {
> >   * CP0 Register 5
> >   */
> >      int32_t CP0_PageMask;
> > +#define CP0PM_MASK 13
> >      int32_t CP0_PageGrain_rw_bitmask;
> >      int32_t CP0_PageGrain;
> >  #define CP0PG_RIE 31
> >


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

* Re: [PATCH V17 1/6] target/mips: Fix PageMask with variable page size
  2020-11-06  4:21 ` [PATCH V17 1/6] target/mips: Fix PageMask with variable page size Huacai Chen
  2020-11-07 12:11   ` Philippe Mathieu-Daudé
@ 2020-11-08 23:15   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 31+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-11-08 23:15 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Aleksandar Rikalo, Huacai Chen, qemu-devel, Aleksandar Markovic,
	Huacai Chen, Aurelien Jarno

On 11/6/20 5:21 AM, Huacai Chen wrote:
> From: Jiaxun Yang <jiaxun.yang@flygoat.com>
> 
> Our current code assumed the target page size is always 4k
> when handling PageMask and VPN2, however, variable page size
> was just added to mips target and that's no longer true.
> 
> Fixes: ee3863b9d414 ("target/mips: Support variable page size")
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> ---
>  target/mips/cp0_helper.c | 27 +++++++++++++++++++++------
>  target/mips/cpu.h        |  1 +
>  2 files changed, 22 insertions(+), 6 deletions(-)
> 
> diff --git a/target/mips/cp0_helper.c b/target/mips/cp0_helper.c
> index 709cc9a..92bf14f 100644
> --- a/target/mips/cp0_helper.c
> +++ b/target/mips/cp0_helper.c
> @@ -892,13 +892,28 @@ void helper_mtc0_memorymapid(CPUMIPSState *env, target_ulong arg1)
>  
>  void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask)
>  {
> -    uint64_t mask = arg1 >> (TARGET_PAGE_BITS + 1);
> -    if (!(env->insn_flags & ISA_MIPS32R6) || (arg1 == ~0) ||
> -        (mask == 0x0000 || mask == 0x0003 || mask == 0x000F ||
> -         mask == 0x003F || mask == 0x00FF || mask == 0x03FF ||
> -         mask == 0x0FFF || mask == 0x3FFF || mask == 0xFFFF)) {
> -        env->CP0_PageMask = arg1 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
> +    unsigned long mask;
> +    int maskbits;
> +
> +    /* Don't care MASKX as we don't support 1KB page */
> +    mask = extract32((uint32_t)arg1, CP0PM_MASK, 16);
> +    maskbits = find_first_zero_bit(&mask, 32);

Thanks, applied to mips-fixes, using cto32 instead
of find_first_zero_bit.

> +
> +    /* Ensure no more set bit after first zero */
> +    if (mask >> maskbits) {
> +        goto invalid;
> +    }
> +    /* We don't support VTLB entry smaller than target page */
> +    if ((maskbits + 12) < TARGET_PAGE_BITS) {
> +        goto invalid;
>      }
> +    env->CP0_PageMask = mask << CP0PM_MASK;
> +
> +    return;
> +
> +invalid:
> +    /* When invalid, set to default target page size. */
> +    env->CP0_PageMask = (~TARGET_PAGE_MASK >> 12) << CP0PM_MASK;
>  }
>  
>  void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1)
> diff --git a/target/mips/cpu.h b/target/mips/cpu.h
> index d41579d..23f8c6f 100644
> --- a/target/mips/cpu.h
> +++ b/target/mips/cpu.h
> @@ -619,6 +619,7 @@ struct CPUMIPSState {
>   * CP0 Register 5
>   */
>      int32_t CP0_PageMask;
> +#define CP0PM_MASK 13
>      int32_t CP0_PageGrain_rw_bitmask;
>      int32_t CP0_PageGrain;
>  #define CP0PG_RIE 31
> 


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

* Re: [PATCH V17 2/6] hw/intc: Rework Loongson LIOINTC
  2020-11-06  4:21 ` [PATCH V17 2/6] hw/intc: Rework Loongson LIOINTC Huacai Chen
@ 2020-11-23 20:52   ` Philippe Mathieu-Daudé
  2020-11-23 22:24     ` Philippe Mathieu-Daudé
  2020-11-28  6:19     ` Huacai Chen
  0 siblings, 2 replies; 31+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-11-23 20:52 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Aleksandar Rikalo, Huacai Chen, qemu-devel, Aleksandar Markovic,
	Huacai Chen, Aurelien Jarno

On 11/6/20 5:21 AM, Huacai Chen wrote:
> As suggested by Philippe Mathieu-Daudé, rework Loongson's liointc:
> 1, Move macro definitions to loongson_liointc.h;
> 2, Remove magic values and use macros instead;
> 3, Replace dead D() code by trace events.
> 
> Suggested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> ---
>  hw/intc/loongson_liointc.c         | 49 +++++++++++---------------------------
>  include/hw/intc/loongson_liointc.h | 39 ++++++++++++++++++++++++++++++
>  2 files changed, 53 insertions(+), 35 deletions(-)
>  create mode 100644 include/hw/intc/loongson_liointc.h
> 
> diff --git a/hw/intc/loongson_liointc.c b/hw/intc/loongson_liointc.c
> index fbbfb57..be29e2f 100644
> --- a/hw/intc/loongson_liointc.c
> +++ b/hw/intc/loongson_liointc.c
> @@ -1,6 +1,7 @@
>  /*
>   * QEMU Loongson Local I/O interrupt controler.
>   *
> + * Copyright (c) 2020 Huacai Chen <chenhc@lemote.com>
>   * Copyright (c) 2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
>   *
>   * This program is free software: you can redistribute it and/or modify
> @@ -19,33 +20,11 @@
>   */
>  
>  #include "qemu/osdep.h"
> -#include "hw/sysbus.h"
>  #include "qemu/module.h"
> +#include "qemu/log.h"
>  #include "hw/irq.h"
>  #include "hw/qdev-properties.h"
> -#include "qom/object.h"
> -
> -#define D(x)
> -
> -#define NUM_IRQS                32
> -
> -#define NUM_CORES               4
> -#define NUM_IPS                 4
> -#define NUM_PARENTS             (NUM_CORES * NUM_IPS)
> -#define PARENT_COREx_IPy(x, y)  (NUM_IPS * x + y)
> -
> -#define R_MAPPER_START          0x0
> -#define R_MAPPER_END            0x20
> -#define R_ISR                   R_MAPPER_END
> -#define R_IEN                   0x24
> -#define R_IEN_SET               0x28
> -#define R_IEN_CLR               0x2c
> -#define R_PERCORE_ISR(x)        (0x40 + 0x8 * x)
> -#define R_END                   0x64
> -
> -#define TYPE_LOONGSON_LIOINTC "loongson.liointc"
> -DECLARE_INSTANCE_CHECKER(struct loongson_liointc, LOONGSON_LIOINTC,
> -                         TYPE_LOONGSON_LIOINTC)
> +#include "hw/intc/loongson_liointc.h"
>  
>  struct loongson_liointc {
>      SysBusDevice parent_obj;
> @@ -123,14 +102,13 @@ liointc_read(void *opaque, hwaddr addr, unsigned int size)
>          goto out;
>      }
>  
> -    /* Rest is 4 byte */
> +    /* Rest are 4 bytes */
>      if (size != 4 || (addr % 4)) {
>          goto out;
>      }
>  
> -    if (addr >= R_PERCORE_ISR(0) &&
> -        addr < R_PERCORE_ISR(NUM_CORES)) {
> -        int core = (addr - R_PERCORE_ISR(0)) / 8;
> +    if (addr >= R_START && addr < R_END) {
> +        int core = (addr - R_START) / R_ISR_SIZE;
>          r = p->per_core_isr[core];
>          goto out;
>      }
> @@ -147,7 +125,8 @@ liointc_read(void *opaque, hwaddr addr, unsigned int size)
>      }
>  
>  out:
> -    D(qemu_log("%s: size=%d addr=%lx val=%x\n", __func__, size, addr, r));
> +    qemu_log_mask(CPU_LOG_INT, "%s: size=%d addr=%lx val=%x\n",
> +                  __func__, size, addr, r);
>      return r;
>  }
>  
> @@ -158,7 +137,8 @@ liointc_write(void *opaque, hwaddr addr,
>      struct loongson_liointc *p = opaque;
>      uint32_t value = val64;
>  
> -    D(qemu_log("%s: size=%d, addr=%lx val=%x\n", __func__, size, addr, value));
> +    qemu_log_mask(CPU_LOG_INT, "%s: size=%d, addr=%lx val=%x\n",
> +                  __func__, size, addr, value);
>  
>      /* Mapper is 1 byte */
>      if (size == 1 && addr < R_MAPPER_END) {
> @@ -166,14 +146,13 @@ liointc_write(void *opaque, hwaddr addr,
>          goto out;
>      }
>  
> -    /* Rest is 4 byte */
> +    /* Rest are 4 bytes */
>      if (size != 4 || (addr % 4)) {
>          goto out;
>      }
>  
> -    if (addr >= R_PERCORE_ISR(0) &&
> -        addr < R_PERCORE_ISR(NUM_CORES)) {
> -        int core = (addr - R_PERCORE_ISR(0)) / 8;
> +    if (addr >= R_START && addr < R_END) {
> +        int core = (addr - R_START) / R_ISR_SIZE;
>          p->per_core_isr[core] = value;
>          goto out;
>      }
> @@ -224,7 +203,7 @@ static void loongson_liointc_init(Object *obj)
>      }
>  
>      memory_region_init_io(&p->mmio, obj, &pic_ops, p,
> -                         "loongson.liointc", R_END);
> +                         TYPE_LOONGSON_LIOINTC, R_END);
>      sysbus_init_mmio(SYS_BUS_DEVICE(obj), &p->mmio);
>  }
>  
> diff --git a/include/hw/intc/loongson_liointc.h b/include/hw/intc/loongson_liointc.h
> new file mode 100644
> index 0000000..e11f482
> --- /dev/null
> +++ b/include/hw/intc/loongson_liointc.h
> @@ -0,0 +1,39 @@
> +/*
> + * This file is subject to the terms and conditions of the GNU General Public
> + * License.  See the file "COPYING" in the main directory of this archive
> + * for more details.
> + *
> + * Copyright (c) 2020 Huacai Chen <chenhc@lemote.com>
> + * Copyright (c) 2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
> + *
> + */
> +
> +#ifndef LOONSGON_LIOINTC_H
> +#define LOONGSON_LIOINTC_H
> +
> +#include "qemu/units.h"
> +#include "hw/sysbus.h"
> +#include "qom/object.h"
> +
> +#define NUM_IRQS                32
> +
> +#define NUM_CORES               4
> +#define NUM_IPS                 4
> +#define NUM_PARENTS             (NUM_CORES * NUM_IPS)
> +#define PARENT_COREx_IPy(x, y)  (NUM_IPS * x + y)
> +
> +#define R_MAPPER_START          0x0
> +#define R_MAPPER_END            0x20
> +#define R_ISR                   R_MAPPER_END
> +#define R_IEN                   0x24
> +#define R_IEN_SET               0x28
> +#define R_IEN_CLR               0x2c
> +#define R_ISR_SIZE              0x8
> +#define R_START                 0x40
> +#define R_END                   0x64

Can we keep the R_* definitions local in the .c?
(if you agree I can amend that when applying).

Thanks for cleaning!

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

> +
> +#define TYPE_LOONGSON_LIOINTC "loongson.liointc"
> +DECLARE_INSTANCE_CHECKER(struct loongson_liointc, LOONGSON_LIOINTC,
> +                         TYPE_LOONGSON_LIOINTC)
> +
> +#endif /* LOONGSON_LIOINTC_H */
> 


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

* Re: [PATCH V17 6/6] docs/system: Update MIPS machine documentation
  2020-11-06  4:21 ` [PATCH V17 6/6] docs/system: Update MIPS machine documentation Huacai Chen
@ 2020-11-23 20:52   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 31+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-11-23 20:52 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Aleksandar Rikalo, Huacai Chen, qemu-devel, Aleksandar Markovic,
	Huacai Chen, Aurelien Jarno

On 11/6/20 5:21 AM, Huacai Chen wrote:
> Update MIPS machine documentation to add Loongson-3 based machine description.
> 
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> ---
>  docs/system/target-mips.rst | 10 ++++++++++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/docs/system/target-mips.rst b/docs/system/target-mips.rst
> index cd2a931..138441b 100644
> --- a/docs/system/target-mips.rst
> +++ b/docs/system/target-mips.rst
> @@ -84,6 +84,16 @@ The Fuloong 2E emulation supports:
>  
>  -  RTL8139D as a network card chipset
>  
> +The Loongson-3 virtual platform emulation supports:
> +
> +-  Loongson 3A CPU
> +
> +-  LIOINTC as interrupt controller
> +
> +-  GPEX and virtio as peripheral devices
> +
> +-  Both KVM and TCG supported

Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>


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

* Re: [PATCH V17 5/6] hw/mips: Add Loongson-3 machine support
  2020-11-06  4:21 ` [PATCH V17 5/6] hw/mips: Add Loongson-3 machine support Huacai Chen
@ 2020-11-23 21:54   ` Philippe Mathieu-Daudé
  2020-11-28  7:04     ` Huacai Chen
  0 siblings, 1 reply; 31+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-11-23 21:54 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Aleksandar Rikalo, Huacai Chen, qemu-devel, Aleksandar Markovic,
	Huacai Chen, Aurelien Jarno

Hi Huacai,

On 11/6/20 5:21 AM, Huacai Chen wrote:
> Add Loongson-3 based machine support, it use liointc as the interrupt
> controler and use GPEX as the pci controller. Currently it can work with
> both TCG and KVM.
> 
> As the machine model is not based on any exiting physical hardware, the
> name of the machine is "loongson3-virt". It may be superseded in future
> by a real machine model. If this happens, then a regular deprecation
> procedure shall occur for "loongson3-virt" machine.
> 
> We now already have a full functional Linux kernel (based on Linux-5.4.x
> LTS) here:
> 
> https://github.com/chenhuacai/linux
> 
> Of course the upstream kernel is also usable (the kvm host side and
> guest side have both been upstream in Linux-5.9):
> 
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
> 
> How to use QEMU/Loongson-3?
> 1, Download kernel source from the above URL;
> 2, Build a kernel with arch/mips/configs/loongson3_defconfig;
> 3, Boot a Loongson-3A4000 host with this kernel (for KVM mode);
> 4, Build QEMU-master with this patchset;
> 5, modprobe kvm (only necessary for KVM mode);
> 6, Use QEMU with TCG:
>        qemu-system-mips64el -M loongson3-virt,accel=tcg -cpu Loongson-3A1000 -kernel <path_to_kernel> -append ...
>    Use QEMU with KVM:
>        qemu-system-mips64el -M loongson3-virt,accel=kvm -cpu Loongson-3A4000 -kernel <path_to_kernel> -append ...
> 
>    The "-cpu" parameter is optional here and QEMU will use the correct type for TCG/KVM automatically.
> 
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
>  default-configs/devices/mips64el-softmmu.mak |   1 +
>  hw/mips/Kconfig                              |  12 +
>  hw/mips/loongson3_virt.c                     | 614 +++++++++++++++++++++++++++
>  hw/mips/meson.build                          |   2 +-
>  4 files changed, 628 insertions(+), 1 deletion(-)
>  create mode 100644 hw/mips/loongson3_virt.c
> 
> diff --git a/default-configs/devices/mips64el-softmmu.mak b/default-configs/devices/mips64el-softmmu.mak
> index 9f8a3ef..26c660a 100644
> --- a/default-configs/devices/mips64el-softmmu.mak
> +++ b/default-configs/devices/mips64el-softmmu.mak
> @@ -3,6 +3,7 @@
>  include mips-softmmu-common.mak
>  CONFIG_IDE_VIA=y
>  CONFIG_FULOONG=y
> +CONFIG_LOONGSON3V=y
>  CONFIG_ATI_VGA=y
>  CONFIG_RTL8139_PCI=y
>  CONFIG_JAZZ=y
> diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig
> index 8be7012..ef5cee1 100644
> --- a/hw/mips/Kconfig
> +++ b/hw/mips/Kconfig
> @@ -32,6 +32,18 @@ config FULOONG
>      bool
>      select PCI_BONITO
>  
> +config LOONGSON3V
> +    bool
> +    select PCKBD

Is it used? I only see USB.

> +    select SERIAL
> +    select GOLDFISH_RTC
> +    select LOONGSON_LIOINTC
> +    select PCI_DEVICES
> +    select PCI_EXPRESS_GENERIC_BRIDGE
> +    select VIRTIO_VGA
> +    select QXL if SPICE

I don't understand the UI dependencies, as we should
be able to start this machine without UI (just console
for example).

Maybe you want the 'imply' keyword instead?

> +    select MSI_NONBROKEN
> +
>  config MIPS_CPS
>      bool
>      select PTIMER
> diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c
> new file mode 100644
> index 0000000..c5db2db
> --- /dev/null
> +++ b/hw/mips/loongson3_virt.c
> @@ -0,0 +1,614 @@
> +/*
> + * Generic Loongson-3 Platform support
> + *
> + * Copyright (c) 2018-2020 Huacai Chen (chenhc@lemote.com)
> + * Copyright (c) 2018-2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
> + *
> + * This program is free software: you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <https://www.gnu.org/licenses/>.
> + */
> +
> +/*
> + * Generic virtualized 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 "qemu/cutils.h"
> +#include "qapi/error.h"
> +#include "cpu.h"
> +#include "elf.h"
> +#include "kvm_mips.h"
> +#include "hw/boards.h"
> +#include "hw/char/serial.h"
> +#include "hw/intc/loongson_liointc.h"
> +#include "hw/mips/mips.h"
> +#include "hw/mips/cpudevs.h"
> +#include "hw/mips/fw_cfg.h"
> +#include "hw/mips/loongson3_bootp.h"
> +#include "hw/misc/unimp.h"
> +#include "hw/intc/i8259.h"
> +#include "hw/loader.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/usb.h"
> +#include "net/net.h"
> +#include "exec/address-spaces.h"
> +#include "sysemu/kvm.h"
> +#include "sysemu/qtest.h"
> +#include "sysemu/reset.h"
> +#include "sysemu/runstate.h"
> +#include "qemu/log.h"
> +#include "qemu/error-report.h"
> +
> +#define PM_CNTL_MODE          0x10
> +
> +#define LOONGSON_MAX_VCPUS      16
> +
> +/*
> + * Loongson-3's virtual machine BIOS can be obtained here:
> + * 1, https://github.com/loongson-community/firmware-nonfree
> + * 2, http://dev.lemote.com:8000/files/firmware/UEFI/KVM/bios_loongson3.bin
> + */
> +#define LOONGSON3_BIOSNAME "bios_loongson3.bin"
> +
> +#define UART_IRQ            0
> +#define RTC_IRQ             1
> +#define PCIE_IRQ_BASE       2
> +
> +const struct MemmapEntry virt_memmap[] = {
> +    [VIRT_LOWMEM] =      { 0x00000000,    0x10000000 },
> +    [VIRT_PM] =          { 0x10080000,         0x100 },
> +    [VIRT_FW_CFG] =      { 0x10080100,         0x100 },
> +    [VIRT_RTC] =         { 0x10081000,        0x1000 },
> +    [VIRT_PCIE_PIO] =    { 0x18000000,       0x80000 },
> +    [VIRT_PCIE_ECAM] =   { 0x1a000000,     0x2000000 },
> +    [VIRT_BIOS_ROM] =    { 0x1fc00000,      0x200000 },
> +    [VIRT_UART] =        { 0x1fe001e0,           0x8 },
> +    [VIRT_LIOINTC] =     { 0x3ff01400,          0x64 },
> +    [VIRT_PCIE_MMIO] =   { 0x40000000,    0x40000000 },
> +    [VIRT_HIGHMEM] =     { 0x80000000,           0x0 }, /* Variable */
> +};
> +
> +static const struct MemmapEntry loader_memmap[] = {
> +    [LOADER_KERNEL] =    { 0x00000000,     0x4000000 },
> +    [LOADER_INITRD] =    { 0x04000000,           0x0 }, /* Variable */
> +    [LOADER_CMDLINE] =   { 0x0ff00000,      0x100000 },
> +};
> +
> +static const struct MemmapEntry loader_rommap[] = {
> +    [LOADER_BOOTROM] =   { 0x1fc00000,        0x1000 },
> +    [LOADER_PARAM] =     { 0x1fc01000,       0x10000 },
> +};
> +
> +static struct _loaderparams {
> +    uint64_t cpu_freq;
> +    uint64_t ram_size;
> +    const char *kernel_cmdline;
> +    const char *kernel_filename;
> +    const char *initrd_filename;
> +    uint64_t kernel_entry;
> +    uint64_t a0, a1, a2;
> +} loaderparams;
> +
> +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,

Any access size is OK? (from your ASM it is byte accessed).

> +    .endianness = DEVICE_NATIVE_ENDIAN,
> +};
> +
> +#define DEF_LOONGSON3_FREQ (800 * 1000 * 1000)
> +
> +static uint64_t get_cpu_freq_hz(void)
> +{
> +#ifdef CONFIG_KVM
> +    int ret;
> +    uint64_t freq;
> +    struct kvm_one_reg freq_reg = {
> +        .id = KVM_REG_MIPS_COUNT_HZ,
> +        .addr = (uintptr_t)(&freq)
> +    };
> +
> +    if (kvm_enabled()) {
> +        ret = kvm_vcpu_ioctl(first_cpu, KVM_GET_ONE_REG, &freq_reg);
> +        if (ret >= 0) {
> +            return freq * 2;
> +        }
> +    }
> +#endif
> +    return DEF_LOONGSON3_FREQ;
> +}
> +
> +static void init_boot_param(void)
> +{
> +    void *p;
> +    struct boot_params *bp;
> +
> +    p = g_malloc0(loader_rommap[LOADER_PARAM].size);

I'm worried Coverity complains we are leaking this. Maybe keep it
static? [updated, see MachineState comment below]

> +    bp = p;
> +
> +    stw_le_p(&bp->efi.smbios.vers, 1);
> +    init_reset_system(&(bp->reset_system));
> +    p += ROUND_UP(sizeof(struct boot_params), 64);
> +    init_loongson_params(&(bp->efi.smbios.lp), p,
> +                         loaderparams.cpu_freq, loaderparams.ram_size);
> +
> +    rom_add_blob_fixed("params_rom", bp,
> +                       loader_rommap[LOADER_PARAM].size,
> +                       loader_rommap[LOADER_PARAM].base);
> +
> +    g_free(bp);
> +
> +    loaderparams.a2 = cpu_mips_phys_to_kseg0(NULL, loader_rommap[LOADER_PARAM].base);
> +}
> +
> +static void init_boot_rom(void)
> +{
> +    const unsigned int boot_code[] = {
> +        0x40086000,   /* mfc0    t0, CP0_STATUS                               */
> +        0x240900E4,   /* li      t1, 0xe4         #set kx, sx, ux, erl        */
> +        0x01094025,   /* or      t0, t0, t1                                   */
> +        0x3C090040,   /* lui     t1, 0x40         #set 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                                                  */
> +    };
> +
> +    rom_add_blob_fixed("boot_rom", boot_code, sizeof(boot_code),
> +                        loader_rommap[LOADER_BOOTROM].base);
> +}
> +
> +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;
> +    hwaddr cfg_addr = virt_memmap[VIRT_FW_CFG].base;
> +
> +    fw_cfg = fw_cfg_init_mem_wide(cfg_addr, cfg_addr + 8, 8, 0, NULL);
> +    fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)current_machine->smp.cpus);
> +    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)current_machine->smp.max_cpus);
> +    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
> +    fw_cfg_add_i32(fw_cfg, FW_CFG_MACHINE_VERSION, 1);
> +    fw_cfg_add_i64(fw_cfg, FW_CFG_CPU_FREQ, get_cpu_freq_hz());
> +    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
> +}
> +
> +static int set_prom_cmdline(ram_addr_t initrd_offset, long initrd_size)
> +{
> +    hwaddr cmdline_vaddr;
> +    char memenv[32];
> +    char highmemenv[32];
> +    void *cmdline_buf;
> +    unsigned int *parg_env;
> +    int ret = 0;
> +
> +    /* Allocate cmdline_buf for command line. */
> +    cmdline_buf = g_malloc0(loader_memmap[LOADER_CMDLINE].size);
> +    cmdline_vaddr = cpu_mips_phys_to_kseg0(NULL,
> +                                           loader_memmap[LOADER_CMDLINE].base);
> +
> +    /*
> +     * Layout of cmdline_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 *)cmdline_buf;
> +
> +    ret = (3 + 1) * 4;
> +    *parg_env++ = cmdline_vaddr + ret;
> +    ret += (1 + snprintf(cmdline_buf + ret, 256 - ret, "g"));
> +
> +    /* argv1 */
> +    *parg_env++ = cmdline_vaddr + ret;
> +    if (initrd_size > 0)
> +        ret += (1 + snprintf(cmdline_buf + ret, 256 - ret,
> +                "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
> +                cpu_mips_phys_to_kseg0(NULL, initrd_offset),
> +                initrd_size, loaderparams.kernel_cmdline));
> +    else
> +        ret += (1 + snprintf(cmdline_buf + ret, 256 - ret, "%s",
> +                loaderparams.kernel_cmdline));
> +
> +    /* argv2 */
> +    *parg_env++ = cmdline_vaddr + 4 * ret;
> +
> +    /* env */
> +    sprintf(memenv, "%d", 256);

Where is that used? This could be const...

> +    sprintf(highmemenv, "%ld", (unsigned long)(loaderparams.ram_size / MiB) - 256);

Where is that used? Anyhow, if needed, please use g_strdup_printf().

> +
> +    rom_add_blob_fixed("cmdline", cmdline_buf,
> +                       loader_memmap[LOADER_CMDLINE].size,
> +                       loader_memmap[LOADER_CMDLINE].base);
> +
> +    g_free(cmdline_buf);
> +
> +    loaderparams.a0 = 2;
> +    loaderparams.a1 = cmdline_vaddr;
> +
> +    return 0;
> +}
> +
> +static uint64_t load_kernel(CPUMIPSState *env)
> +{
> +    long kernel_size;
> +    ram_addr_t initrd_offset;
> +    uint64_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 = MAX(loader_memmap[LOADER_INITRD].base,
> +                                ROUND_UP(kernel_high, INITRD_PAGE_SIZE));
> +
> +            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 cmdline. */
> +    set_prom_cmdline(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 inline void loongson3_virt_devices_init(MachineState *machine, DeviceState *pic)
> +{
> +    int i;
> +    qemu_irq irq;
> +    PCIBus *pci_bus;
> +    DeviceState *dev;
> +    MemoryRegion *pio_alias;
> +    MemoryRegion *mmio_alias, *mmio_reg;
> +    MemoryRegion *ecam_alias, *ecam_reg;
> +
> +    dev = qdev_new(TYPE_GPEX_HOST);
> +    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
> +    pci_bus = PCI_HOST_BRIDGE(dev)->bus;
> +
> +    ecam_alias = g_new0(MemoryRegion, 1);

Again, Coverity will complain for the memory leaked :(

I think you want to keep all these pointers in an object
extending MachineState. You can check at RaspiMachineState
for an example.

> +    ecam_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
> +    memory_region_init_alias(ecam_alias, OBJECT(dev), "pcie-ecam",
> +                             ecam_reg, 0, virt_memmap[VIRT_PCIE_ECAM].size);
> +    memory_region_add_subregion(get_system_memory(),
> +                                virt_memmap[VIRT_PCIE_ECAM].base, ecam_alias);
> +
> +    mmio_alias = g_new0(MemoryRegion, 1);
> +    mmio_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1);
> +    memory_region_init_alias(mmio_alias, OBJECT(dev), "pcie-mmio",
> +                             mmio_reg, virt_memmap[VIRT_PCIE_MMIO].base,
> +                             virt_memmap[VIRT_PCIE_MMIO].size);
> +    memory_region_add_subregion(get_system_memory(),
> +                                virt_memmap[VIRT_PCIE_MMIO].base, mmio_alias);
> +
> +    pio_alias = g_new0(MemoryRegion, 1);
> +    memory_region_init_alias(pio_alias, OBJECT(dev), "pcie-pio",
> +                             get_system_io(), 0, virt_memmap[VIRT_PCIE_PIO].size);
> +    memory_region_add_subregion(get_system_memory(),
> +                                virt_memmap[VIRT_PCIE_PIO].base, pio_alias);
> +    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, virt_memmap[VIRT_PCIE_PIO].base);
> +
> +    for (i = 0; i < GPEX_NUM_IRQS; i++) {
> +        irq = qdev_get_gpio_in(pic, PCIE_IRQ_BASE + i);
> +        sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, irq);
> +        gpex_set_irq_num(GPEX_HOST(dev), i, PCIE_IRQ_BASE + i);
> +    }

Maybe set here "msi_nonbroken = true;".

> +
> +    pci_vga_init(pci_bus);

Maybe part of defaults_enabled... not sure although.

> +
> +    if (defaults_enabled()) {
> +        pci_create_simple(pci_bus, -1, "pci-ohci");
> +        usb_create_simple(usb_bus_find(-1), "usb-kbd");
> +        usb_create_simple(usb_bus_find(-1), "usb-tablet");
> +    }
> +
> +    for (i = 0; i < nb_nics; i++) {
> +        NICInfo *nd = &nd_table[i];
> +
> +        if (!nd->model) {
> +            nd->model = g_strdup("virtio");
> +        }
> +
> +        pci_nic_init_nofail(nd, pci_bus, nd->model, NULL);
> +    }
> +}
> +
> +static void mips_loongson3_virt_init(MachineState *machine)
> +{
> +    int i;
> +    long bios_size;
> +    MIPSCPU *cpu;
> +    Clock *cpuclk;
> +    CPUMIPSState *env;
> +    DeviceState *liointc;
> +    char *filename;
> +    const char *kernel_cmdline = machine->kernel_cmdline;
> +    const char *kernel_filename = machine->kernel_filename;
> +    const char *initrd_filename = machine->initrd_filename;
> +    ram_addr_t ram_size = machine->ram_size;
> +    MemoryRegion *address_space_mem = get_system_memory();
> +    MemoryRegion *ram = g_new(MemoryRegion, 1);
> +    MemoryRegion *bios = g_new(MemoryRegion, 1);
> +    MemoryRegion *iomem = g_new(MemoryRegion, 1);
> +
> +    /* TODO: TCG will support all CPU types */
> +    if (!kvm_enabled()) {
> +        if (!machine->cpu_type) {
> +            machine->cpu_type = MIPS_CPU_TYPE_NAME("Loongson-3A1000");
> +        }
> +        if (!strstr(machine->cpu_type, "Loongson-3A1000")) {
> +            error_report("Loongson-3/TCG needs cpu type Loongson-3A1000");

Why not accept any 3A family?

> +            exit(1);
> +        }
> +    } else {
> +        if (!machine->cpu_type) {
> +            machine->cpu_type = MIPS_CPU_TYPE_NAME("Loongson-3A4000");
> +        }
> +        if (!strstr(machine->cpu_type, "Loongson-3A4000")) {
> +            error_report("Loongson-3/KVM needs cpu type Loongson-3A4000");
> +            exit(1);
> +        }
> +    }
> +
> +    if (ram_size < 512 * MiB) {
> +        error_report("Loongson-3 machine needs at least 512MB memory");
> +        exit(1);
> +    }
> +
> +    /*
> +     * The whole MMIO range among configure registers doesn't generate
> +     * exception when accessing invalid memory. Create some unimplememted
> +     * devices to emulate this feature.
> +     */
> +    create_unimplemented_device("mmio fallback 0", 0x10000000, 256 * MiB);
> +    create_unimplemented_device("mmio fallback 1", 0x30000000, 256 * MiB);
> +
> +    liointc = qdev_new("loongson.liointc");
> +    sysbus_realize_and_unref(SYS_BUS_DEVICE(liointc), &error_fatal);
> +
> +    sysbus_mmio_map(SYS_BUS_DEVICE(liointc), 0, virt_memmap[VIRT_LIOINTC].base);
> +
> +    serial_mm_init(address_space_mem, virt_memmap[VIRT_UART].base, 0,
> +                   qdev_get_gpio_in(liointc, UART_IRQ), 115200, serial_hd(0),
> +                   DEVICE_NATIVE_ENDIAN);
> +
> +    sysbus_create_simple("goldfish_rtc", virt_memmap[VIRT_RTC].base,
> +                         qdev_get_gpio_in(liointc, RTC_IRQ));
> +
> +    cpuclk = clock_new(OBJECT(machine), "cpu-refclk");
> +    clock_set_hz(cpuclk, DEF_LOONGSON3_FREQ);
> +
> +    for (i = 0; i < machine->smp.cpus; i++) {
> +        int ip;
> +
> +        /* init CPUs */
> +        cpu = mips_cpu_create_with_clock(machine->cpu_type, cpuclk);
> +
> +        /* Init internal devices */
> +        cpu_mips_irq_init_cpu(cpu);
> +        cpu_mips_clock_init(cpu);
> +        qemu_register_reset(main_cpu_reset, cpu);
> +
> +        if (i >= 4) {
> +            continue; /* Only node-0 can be connected to LIOINTC */
> +        }
> +
> +        for (ip = 0; ip < 4 ; ip++) {
> +            int pin = i * 4 + ip;
> +            sysbus_connect_irq(SYS_BUS_DEVICE(liointc),
> +                               pin, cpu->env.irq[ip + 2]);
> +        }
> +    }
> +    env = &MIPS_CPU(first_cpu)->env;
> +
> +    /* Allocate RAM/BIOS, 0x00000000~0x10000000 is alias of 0x80000000~0x90000000 */
> +    memory_region_init_rom(bios, NULL, "loongson3.bios",
> +                           virt_memmap[VIRT_BIOS_ROM].size, &error_fatal);
> +    memory_region_init_alias(ram, NULL, "loongson3.lowmem",
> +                           machine->ram, 0, virt_memmap[VIRT_LOWMEM].size);
> +    memory_region_init_io(iomem, NULL, &loongson3_pm_ops,
> +                           NULL, "loongson3_pm", virt_memmap[VIRT_PM].size);
> +
> +    memory_region_add_subregion(address_space_mem,
> +                      virt_memmap[VIRT_LOWMEM].base, ram);
> +    memory_region_add_subregion(address_space_mem,
> +                      virt_memmap[VIRT_BIOS_ROM].base, bios);
> +    memory_region_add_subregion(address_space_mem,
> +                      virt_memmap[VIRT_HIGHMEM].base, machine->ram);
> +    memory_region_add_subregion(address_space_mem,
> +                      virt_memmap[VIRT_PM].base, iomem);
> +
> +    /*
> +     * We do not support flash operation, just loading bios.bin as raw BIOS.
> +     * Please use -L to set the BIOS path and -bios to set bios name.
> +     */
> +
> +    if (kernel_filename) {
> +        loaderparams.cpu_freq = get_cpu_freq_hz();
> +        loaderparams.ram_size = ram_size;
> +        loaderparams.kernel_filename = kernel_filename;
> +        loaderparams.kernel_cmdline = kernel_cmdline;
> +        loaderparams.initrd_filename = initrd_filename;
> +        loaderparams.kernel_entry = load_kernel(env);
> +
> +        init_boot_rom();
> +        init_boot_param();
> +    } 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,
> +                                            virt_memmap[VIRT_BIOS_ROM].base,
> +                                            virt_memmap[VIRT_BIOS_ROM].size);
> +            g_free(filename);
> +        } else {
> +            bios_size = -1;
> +        }
> +
> +        if ((bios_size < 0 || bios_size > virt_memmap[VIRT_BIOS_ROM].size) &&
> +            !kernel_filename && !qtest_enabled()) {
> +            error_report("Could not load MIPS bios '%s'", bios_name);
> +            exit(1);
> +        }
> +
> +        fw_conf_init(ram_size);
> +    }
> +
> +    msi_nonbroken = true;
> +    loongson3_virt_devices_init(machine, liointc);
> +}
> +
> +static void mips_loongson3_virt_machine_init(MachineClass *mc)
> +{
> +    mc->desc = "Loongson-3 Virtualization Platform";
> +    mc->init = mips_loongson3_virt_init;
> +    mc->block_default_type = IF_IDE;
> +    mc->max_cpus = LOONGSON_MAX_VCPUS;
> +    mc->default_ram_id = "loongson3.highram";
> +    mc->default_ram_size = 1600 * MiB;
> +    mc->kvm_type = mips_kvm_type;
> +    mc->minimum_page_bits = 14;
> +}
> +
> +DEFINE_MACHINE("loongson3-virt", mips_loongson3_virt_machine_init)

There are still some questions, but we are almost there!

I can fix the leak/MachineState problem if you are lost.

For smoke testing, you can have a look at test_pmon_serial_console()
in https://www.mail-archive.com/qemu-devel@nongnu.org/msg752605.html
(forgot the test_pmon_framebuffer_console part).
This should be almost a copy/paste for your machine.

Regards,

Phil.


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

* Re: [PATCH V17 2/6] hw/intc: Rework Loongson LIOINTC
  2020-11-23 20:52   ` Philippe Mathieu-Daudé
@ 2020-11-23 22:24     ` Philippe Mathieu-Daudé
  2020-11-28  6:20       ` Huacai Chen
  2020-11-28  6:19     ` Huacai Chen
  1 sibling, 1 reply; 31+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-11-23 22:24 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Aleksandar Rikalo, Huacai Chen, qemu-devel, Aleksandar Markovic,
	Huacai Chen, Aurelien Jarno

On 11/23/20 9:52 PM, Philippe Mathieu-Daudé wrote:
> On 11/6/20 5:21 AM, Huacai Chen wrote:
>> As suggested by Philippe Mathieu-Daudé, rework Loongson's liointc:
>> 1, Move macro definitions to loongson_liointc.h;
>> 2, Remove magic values and use macros instead;
>> 3, Replace dead D() code by trace events.
>>
>> Suggested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
>> Signed-off-by: Huacai Chen <chenhc@lemote.com>
>> ---
>>  hw/intc/loongson_liointc.c         | 49 +++++++++++---------------------------
>>  include/hw/intc/loongson_liointc.h | 39 ++++++++++++++++++++++++++++++
>>  2 files changed, 53 insertions(+), 35 deletions(-)
>>  create mode 100644 include/hw/intc/loongson_liointc.h
>>
>> diff --git a/hw/intc/loongson_liointc.c b/hw/intc/loongson_liointc.c
>> index fbbfb57..be29e2f 100644
>> --- a/hw/intc/loongson_liointc.c
>> +++ b/hw/intc/loongson_liointc.c
>> @@ -1,6 +1,7 @@
>>  /*
>>   * QEMU Loongson Local I/O interrupt controler.
>>   *
>> + * Copyright (c) 2020 Huacai Chen <chenhc@lemote.com>
>>   * Copyright (c) 2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
>>   *
>>   * This program is free software: you can redistribute it and/or modify
>> @@ -19,33 +20,11 @@
>>   */
>>  
>>  #include "qemu/osdep.h"
>> -#include "hw/sysbus.h"
>>  #include "qemu/module.h"
>> +#include "qemu/log.h"
>>  #include "hw/irq.h"
>>  #include "hw/qdev-properties.h"
>> -#include "qom/object.h"
>> -
>> -#define D(x)
>> -
>> -#define NUM_IRQS                32
>> -
>> -#define NUM_CORES               4
>> -#define NUM_IPS                 4
>> -#define NUM_PARENTS             (NUM_CORES * NUM_IPS)
>> -#define PARENT_COREx_IPy(x, y)  (NUM_IPS * x + y)
>> -
>> -#define R_MAPPER_START          0x0
>> -#define R_MAPPER_END            0x20
>> -#define R_ISR                   R_MAPPER_END
>> -#define R_IEN                   0x24
>> -#define R_IEN_SET               0x28
>> -#define R_IEN_CLR               0x2c
>> -#define R_PERCORE_ISR(x)        (0x40 + 0x8 * x)
>> -#define R_END                   0x64
>> -
>> -#define TYPE_LOONGSON_LIOINTC "loongson.liointc"
>> -DECLARE_INSTANCE_CHECKER(struct loongson_liointc, LOONGSON_LIOINTC,
>> -                         TYPE_LOONGSON_LIOINTC)
>> +#include "hw/intc/loongson_liointc.h"
>>  
>>  struct loongson_liointc {
>>      SysBusDevice parent_obj;
>> @@ -123,14 +102,13 @@ liointc_read(void *opaque, hwaddr addr, unsigned int size)
>>          goto out;
>>      }
>>  
>> -    /* Rest is 4 byte */
>> +    /* Rest are 4 bytes */
>>      if (size != 4 || (addr % 4)) {
>>          goto out;
>>      }
>>  
>> -    if (addr >= R_PERCORE_ISR(0) &&
>> -        addr < R_PERCORE_ISR(NUM_CORES)) {
>> -        int core = (addr - R_PERCORE_ISR(0)) / 8;
>> +    if (addr >= R_START && addr < R_END) {
>> +        int core = (addr - R_START) / R_ISR_SIZE;
>>          r = p->per_core_isr[core];
>>          goto out;
>>      }
>> @@ -147,7 +125,8 @@ liointc_read(void *opaque, hwaddr addr, unsigned int size)
>>      }
>>  
>>  out:
>> -    D(qemu_log("%s: size=%d addr=%lx val=%x\n", __func__, size, addr, r));
>> +    qemu_log_mask(CPU_LOG_INT, "%s: size=%d addr=%lx val=%x\n",
>> +                  __func__, size, addr, r);
>>      return r;
>>  }
>>  
>> @@ -158,7 +137,8 @@ liointc_write(void *opaque, hwaddr addr,
>>      struct loongson_liointc *p = opaque;
>>      uint32_t value = val64;
>>  
>> -    D(qemu_log("%s: size=%d, addr=%lx val=%x\n", __func__, size, addr, value));
>> +    qemu_log_mask(CPU_LOG_INT, "%s: size=%d, addr=%lx val=%x\n",
>> +                  __func__, size, addr, value);
>>  
>>      /* Mapper is 1 byte */
>>      if (size == 1 && addr < R_MAPPER_END) {
>> @@ -166,14 +146,13 @@ liointc_write(void *opaque, hwaddr addr,
>>          goto out;
>>      }
>>  
>> -    /* Rest is 4 byte */
>> +    /* Rest are 4 bytes */
>>      if (size != 4 || (addr % 4)) {
>>          goto out;
>>      }
>>  
>> -    if (addr >= R_PERCORE_ISR(0) &&
>> -        addr < R_PERCORE_ISR(NUM_CORES)) {
>> -        int core = (addr - R_PERCORE_ISR(0)) / 8;
>> +    if (addr >= R_START && addr < R_END) {
>> +        int core = (addr - R_START) / R_ISR_SIZE;
>>          p->per_core_isr[core] = value;
>>          goto out;
>>      }
>> @@ -224,7 +203,7 @@ static void loongson_liointc_init(Object *obj)
>>      }
>>  
>>      memory_region_init_io(&p->mmio, obj, &pic_ops, p,
>> -                         "loongson.liointc", R_END);
>> +                         TYPE_LOONGSON_LIOINTC, R_END);
>>      sysbus_init_mmio(SYS_BUS_DEVICE(obj), &p->mmio);
>>  }
>>  
>> diff --git a/include/hw/intc/loongson_liointc.h b/include/hw/intc/loongson_liointc.h
>> new file mode 100644
>> index 0000000..e11f482
>> --- /dev/null
>> +++ b/include/hw/intc/loongson_liointc.h
>> @@ -0,0 +1,39 @@
>> +/*
>> + * This file is subject to the terms and conditions of the GNU General Public
>> + * License.  See the file "COPYING" in the main directory of this archive
>> + * for more details.
>> + *
>> + * Copyright (c) 2020 Huacai Chen <chenhc@lemote.com>
>> + * Copyright (c) 2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
>> + *
>> + */
>> +
>> +#ifndef LOONSGON_LIOINTC_H
>> +#define LOONGSON_LIOINTC_H

Clang is smart:

hw/intc/loongson_liointc.h:11:9: error: 'LOONSGON_LIOINTC_H' is used as
a header guard here, followed by #define of a different macro
[-Werror,-Wheader-guard]
#ifndef LOONSGON_LIOINTC_H
        ^~~~~~~~~~~~~~~~~~
include/hw/intc/loongson_liointc.h:12:9: note: 'LOONGSON_LIOINTC_H' is
defined here; did you mean 'LOONSGON_LIOINTC_H'?
#define LOONGSON_LIOINTC_H
        ^~~~~~~~~~~~~~~~~~
        LOONSGON_LIOINTC_H
1 error generated.

Once fixed:
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>

>> +
>> +#include "qemu/units.h"
>> +#include "hw/sysbus.h"
>> +#include "qom/object.h"
>> +
>> +#define NUM_IRQS                32
>> +
>> +#define NUM_CORES               4
>> +#define NUM_IPS                 4
>> +#define NUM_PARENTS             (NUM_CORES * NUM_IPS)
>> +#define PARENT_COREx_IPy(x, y)  (NUM_IPS * x + y)
>> +
>> +#define R_MAPPER_START          0x0
>> +#define R_MAPPER_END            0x20
>> +#define R_ISR                   R_MAPPER_END
>> +#define R_IEN                   0x24
>> +#define R_IEN_SET               0x28
>> +#define R_IEN_CLR               0x2c
>> +#define R_ISR_SIZE              0x8
>> +#define R_START                 0x40
>> +#define R_END                   0x64
> 
> Can we keep the R_* definitions local in the .c?
> (if you agree I can amend that when applying).
> 
> Thanks for cleaning!
> 
> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> 
>> +
>> +#define TYPE_LOONGSON_LIOINTC "loongson.liointc"
>> +DECLARE_INSTANCE_CHECKER(struct loongson_liointc, LOONGSON_LIOINTC,
>> +                         TYPE_LOONGSON_LIOINTC)
>> +
>> +#endif /* LOONGSON_LIOINTC_H */
>>
> 


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

* Re: [PATCH V17 4/6] hw/mips: Add Loongson-3 boot parameter helpers
  2020-11-06  4:21 ` [PATCH V17 4/6] hw/mips: Add Loongson-3 boot parameter helpers Huacai Chen
@ 2020-11-23 22:25   ` Philippe Mathieu-Daudé
  2020-12-02  1:14     ` Huacai Chen
  2020-12-13 23:24   ` Philippe Mathieu-Daudé
  1 sibling, 1 reply; 31+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-11-23 22:25 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Aleksandar Rikalo, Huacai Chen, qemu-devel, Aleksandar Markovic,
	Huacai Chen, Aurelien Jarno

On 11/6/20 5:21 AM, Huacai Chen wrote:
> Preparing to add Loongson-3 machine support, add Loongson-3's LEFI (a
> UEFI-like interface for BIOS-Kernel boot parameters) helpers first.
> 
> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
>  hw/mips/loongson3_bootp.c | 165 +++++++++++++++++++++++++++++++
>  hw/mips/loongson3_bootp.h | 241 ++++++++++++++++++++++++++++++++++++++++++++++
>  hw/mips/meson.build       |   1 +
>  3 files changed, 407 insertions(+)
>  create mode 100644 hw/mips/loongson3_bootp.c
>  create mode 100644 hw/mips/loongson3_bootp.h
> 
> diff --git a/hw/mips/loongson3_bootp.c b/hw/mips/loongson3_bootp.c
> new file mode 100644
> index 0000000..3a16081
> --- /dev/null
> +++ b/hw/mips/loongson3_bootp.c
> @@ -0,0 +1,165 @@
> +/*
> + * LEFI (a UEFI-like interface for BIOS-Kernel boot parameters) helpers
> + *
> + * Copyright (c) 2018-2020 Huacai Chen (chenhc@lemote.com)
> + * Copyright (c) 2018-2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
> + *
> + * This program is free software: you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <https://www.gnu.org/licenses/>.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/units.h"
> +#include "qemu/cutils.h"
> +#include "cpu.h"
> +#include "hw/boards.h"
> +#include "hw/mips/loongson3_bootp.h"
> +
> +#define LOONGSON3_CORE_PER_NODE 4
> +
> +static struct efi_cpuinfo_loongson *init_cpu_info(void *g_cpuinfo, uint64_t cpu_freq)
> +{
> +    struct efi_cpuinfo_loongson *c = g_cpuinfo;
> +
> +    stl_le_p(&c->cputype, Loongson_3A);
> +    stl_le_p(&c->processor_id, MIPS_CPU(first_cpu)->env.CP0_PRid);

Build failing with Clang:

FAILED: libqemu-mips64el-softmmu.fa.p/hw_mips_loongson3_bootp.c.o
hw/mips/loongson3_bootp.c:35:15: error: taking address of packed member
'processor_id' of class or structure 'efi_cpuinfo_loongson' may result
in an unaligned pointer value [-Werror,-Waddress-of-packed-member]
    stl_le_p(&c->processor_id, MIPS_CPU(first_cpu)->env.CP0_PRid);
              ^~~~~~~~~~~~~~~
1 error generated.

> +    if (cpu_freq > UINT_MAX) {
> +        stl_le_p(&c->cpu_clock_freq, UINT_MAX);
> +    } else {
> +        stl_le_p(&c->cpu_clock_freq, cpu_freq);
> +    }
> +
> +    stw_le_p(&c->cpu_startup_core_id, 0);
> +    stl_le_p(&c->nr_cpus, current_machine->smp.cpus);
> +    stl_le_p(&c->total_node, DIV_ROUND_UP(current_machine->smp.cpus,
> +                                          LOONGSON3_CORE_PER_NODE));
> +
> +    return c;
> +}
> +
> +static struct efi_memory_map_loongson *init_memory_map(void *g_map, uint64_t ram_size)
> +{
> +    struct efi_memory_map_loongson *emap = g_map;
> +
> +    stl_le_p(&emap->nr_map, 2);
> +    stl_le_p(&emap->mem_freq, 300000000);
> +
> +    stl_le_p(&emap->map[0].node_id, 0);
> +    stl_le_p(&emap->map[0].mem_type, 1);
> +    stq_le_p(&emap->map[0].mem_start, 0x0);
> +    stl_le_p(&emap->map[0].mem_size, 240);
> +
> +    stl_le_p(&emap->map[1].node_id, 0);
> +    stl_le_p(&emap->map[1].mem_type, 2);
> +    stq_le_p(&emap->map[1].mem_start, 0x90000000);
> +    stl_le_p(&emap->map[1].mem_size, (ram_size / MiB) - 256);
> +
> +    return emap;
> +}
> +
> +static struct system_loongson *init_system_loongson(void *g_system)
> +{
> +    struct system_loongson *s = g_system;
> +
> +    stl_le_p(&s->ccnuma_smp, 0);
> +    stl_le_p(&s->sing_double_channel, 1);
> +    stl_le_p(&s->nr_uarts, 1);
> +    stl_le_p(&s->uarts[0].iotype, 2);
> +    stl_le_p(&s->uarts[0].int_offset, 2);
> +    stl_le_p(&s->uarts[0].uartclk, 25000000); /* Random value */
> +    stq_le_p(&s->uarts[0].uart_base, virt_memmap[VIRT_UART].base);
> +
> +    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;
> +
> +    stl_le_p(&irq_info->node_id, 0);
> +    stl_le_p(&irq_info->PIC_type, 0);
> +    stw_le_p(&irq_info->dma_mask_bits, 64);
> +    stq_le_p(&irq_info->pci_mem_start_addr, virt_memmap[VIRT_PCIE_MMIO].base);
> +    stq_le_p(&irq_info->pci_mem_end_addr, virt_memmap[VIRT_PCIE_MMIO].base +
> +                                          virt_memmap[VIRT_PCIE_MMIO].size - 1);
> +    stq_le_p(&irq_info->pci_io_start_addr, virt_memmap[VIRT_PCIE_PIO].base);
> +
> +    return irq_info;
> +}
> +
> +static struct interface_info *init_interface_info(void *g_interface)
> +{
> +    struct interface_info *interface = g_interface;
> +
> +    stw_le_p(&interface->vers, 0x01);
> +    strpadcpy(interface->description, 64, "UEFI_Version_v1.0", '\0');
> +
> +    return interface;
> +}
> +
> +static struct board_devices *board_devices_info(void *g_board)
> +{
> +    struct board_devices *bd = g_board;
> +
> +    strpadcpy(bd->name, 64, "Loongson-3A-VIRT-1w-V1.00-demo", '\0');
> +
> +    return bd;
> +}
> +
> +static struct loongson_special_attribute *init_special_info(void *g_special)
> +{
> +    struct loongson_special_attribute *special = g_special;
> +
> +    strpadcpy(special->special_name, 64, "2018-04-01", '\0');
> +
> +    return special;
> +}
> +
> +void init_loongson_params(struct loongson_params *lp, void *p,
> +                          uint64_t cpu_freq, uint64_t ram_size)
> +{
> +    stq_le_p(&lp->cpu_offset,
> +              (uintptr_t)init_cpu_info(p, cpu_freq) - (uintptr_t)lp);
> +    p += ROUND_UP(sizeof(struct efi_cpuinfo_loongson), 64);
> +
> +    stq_le_p(&lp->memory_offset,
> +              (uintptr_t)init_memory_map(p, ram_size) - (uintptr_t)lp);
> +    p += ROUND_UP(sizeof(struct efi_memory_map_loongson), 64);
> +
> +    stq_le_p(&lp->system_offset,
> +              (uintptr_t)init_system_loongson(p) - (uintptr_t)lp);
> +    p += ROUND_UP(sizeof(struct system_loongson), 64);
> +
> +    stq_le_p(&lp->irq_offset,
> +              (uintptr_t)init_irq_source(p) - (uintptr_t)lp);
> +    p += ROUND_UP(sizeof(struct irq_source_routing_table), 64);
> +
> +    stq_le_p(&lp->interface_offset,
> +              (uintptr_t)init_interface_info(p) - (uintptr_t)lp);
> +    p += ROUND_UP(sizeof(struct interface_info), 64);
> +
> +    stq_le_p(&lp->boarddev_table_offset,
> +              (uintptr_t)board_devices_info(p) - (uintptr_t)lp);
> +    p += ROUND_UP(sizeof(struct board_devices), 64);
> +
> +    stq_le_p(&lp->special_offset,
> +              (uintptr_t)init_special_info(p) - (uintptr_t)lp);
> +    p += ROUND_UP(sizeof(struct loongson_special_attribute), 64);
> +}
> +
> +void init_reset_system(struct efi_reset_system_t *reset)
> +{
> +    stq_le_p(&reset->Shutdown, 0xffffffffbfc000a8);
> +    stq_le_p(&reset->ResetCold, 0xffffffffbfc00080);
> +    stq_le_p(&reset->ResetWarm, 0xffffffffbfc00080);
> +}
> diff --git a/hw/mips/loongson3_bootp.h b/hw/mips/loongson3_bootp.h
> new file mode 100644
> index 0000000..bf4fd8c
> --- /dev/null
> +++ b/hw/mips/loongson3_bootp.h
> @@ -0,0 +1,241 @@
> +/*
> + * LEFI (a UEFI-like interface for BIOS-Kernel boot parameters) data structrues
> + * defined at arch/mips/include/asm/mach-loongson64/boot_param.h in Linux kernel
> + *
> + * Copyright (c) 2017-2020 Huacai Chen (chenhc@lemote.com)
> + * Copyright (c) 2017-2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
> + *
> + * This program is free software: you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <https://www.gnu.org/licenses/>.
> + */
> +
> +#ifndef HW_MIPS_LOONGSON3_BOOTP_H
> +#define HW_MIPS_LOONGSON3_BOOTP_H
> +
> +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];
> +} QEMU_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];
> +} QEMU_PACKED;
> +
> +#define MAX_UARTS 64
> +struct uart_device {
> +    uint32_t iotype;
> +    uint32_t uartclk;
> +    uint32_t int_offset;
> +    uint64_t uart_base;
> +} QEMU_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; /* step speed or constant speed */
> +    uint32_t fan_percent;/* only for constant speed policy */
> +    uint64_t base_addr;  /* base address of device registers */
> +} QEMU_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;
> +    uint64_t of_dtb_addr; /* NULL if not support */
> +} QEMU_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;
> +} QEMU_PACKED;
> +
> +struct interface_info {
> +    uint16_t vers;               /* version of the specificition */
> +    uint16_t size;
> +    uint8_t  flag;
> +    char description[64];
> +} QEMU_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;
> +};
> +
> +/* Overall MMIO & Memory layout */
> +enum {
> +    VIRT_LOWMEM,
> +    VIRT_PM,
> +    VIRT_FW_CFG,
> +    VIRT_RTC,
> +    VIRT_PCIE_PIO,
> +    VIRT_PCIE_ECAM,
> +    VIRT_BIOS_ROM,
> +    VIRT_UART,
> +    VIRT_LIOINTC,
> +    VIRT_PCIE_MMIO,
> +    VIRT_HIGHMEM
> +};
> +
> +/* Low MEM layout for QEMU kernel loader */
> +enum {
> +    LOADER_KERNEL,
> +    LOADER_INITRD,
> +    LOADER_CMDLINE
> +};
> +
> +/* BIOS ROM layout for QEMU kernel loader */
> +enum {
> +    LOADER_BOOTROM,
> +    LOADER_PARAM,
> +};
> +
> +struct MemmapEntry {
> +    hwaddr base;
> +    hwaddr size;
> +};
> +
> +extern const struct MemmapEntry virt_memmap[];
> +void init_loongson_params(struct loongson_params *lp, void *p,
> +                          uint64_t cpu_freq, uint64_t ram_size);
> +void init_reset_system(struct efi_reset_system_t *reset);
> +
> +#endif
> diff --git a/hw/mips/meson.build b/hw/mips/meson.build
> index 0e9f930..9e58c2b 100644
> --- a/hw/mips/meson.build
> +++ b/hw/mips/meson.build
> @@ -1,6 +1,7 @@
>  mips_ss = ss.source_set()
>  mips_ss.add(files('addr.c', 'mips_int.c', 'fw_cfg.c'))
>  mips_ss.add(when: 'CONFIG_FULOONG', if_true: files('fuloong2e.c'))
> +mips_ss.add(when: 'CONFIG_LOONGSON3V', if_true: files('loongson3_bootp.c'))
>  mips_ss.add(when: 'CONFIG_JAZZ', if_true: files('jazz.c'))
>  mips_ss.add(when: 'CONFIG_MALTA', if_true: files('gt64xxx_pci.c', 'malta.c'))
>  mips_ss.add(when: 'CONFIG_MIPSSIM', if_true: files('mipssim.c'))
> 


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

* Re: [PATCH V17 2/6] hw/intc: Rework Loongson LIOINTC
  2020-11-23 20:52   ` Philippe Mathieu-Daudé
  2020-11-23 22:24     ` Philippe Mathieu-Daudé
@ 2020-11-28  6:19     ` Huacai Chen
  2020-11-30 10:08       ` Philippe Mathieu-Daudé
  1 sibling, 1 reply; 31+ messages in thread
From: Huacai Chen @ 2020-11-28  6:19 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Huacai Chen, Aleksandar Rikalo, QEMU Developers, Aurelien Jarno,
	Aleksandar Markovic

Hi, Philippe,

On Tue, Nov 24, 2020 at 4:52 AM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>
> On 11/6/20 5:21 AM, Huacai Chen wrote:
> > As suggested by Philippe Mathieu-Daudé, rework Loongson's liointc:
> > 1, Move macro definitions to loongson_liointc.h;
> > 2, Remove magic values and use macros instead;
> > 3, Replace dead D() code by trace events.
> >
> > Suggested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> > Signed-off-by: Huacai Chen <chenhc@lemote.com>
> > ---
> >  hw/intc/loongson_liointc.c         | 49 +++++++++++---------------------------
> >  include/hw/intc/loongson_liointc.h | 39 ++++++++++++++++++++++++++++++
> >  2 files changed, 53 insertions(+), 35 deletions(-)
> >  create mode 100644 include/hw/intc/loongson_liointc.h
> >
> > diff --git a/hw/intc/loongson_liointc.c b/hw/intc/loongson_liointc.c
> > index fbbfb57..be29e2f 100644
> > --- a/hw/intc/loongson_liointc.c
> > +++ b/hw/intc/loongson_liointc.c
> > @@ -1,6 +1,7 @@
> >  /*
> >   * QEMU Loongson Local I/O interrupt controler.
> >   *
> > + * Copyright (c) 2020 Huacai Chen <chenhc@lemote.com>
> >   * Copyright (c) 2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
> >   *
> >   * This program is free software: you can redistribute it and/or modify
> > @@ -19,33 +20,11 @@
> >   */
> >
> >  #include "qemu/osdep.h"
> > -#include "hw/sysbus.h"
> >  #include "qemu/module.h"
> > +#include "qemu/log.h"
> >  #include "hw/irq.h"
> >  #include "hw/qdev-properties.h"
> > -#include "qom/object.h"
> > -
> > -#define D(x)
> > -
> > -#define NUM_IRQS                32
> > -
> > -#define NUM_CORES               4
> > -#define NUM_IPS                 4
> > -#define NUM_PARENTS             (NUM_CORES * NUM_IPS)
> > -#define PARENT_COREx_IPy(x, y)  (NUM_IPS * x + y)
> > -
> > -#define R_MAPPER_START          0x0
> > -#define R_MAPPER_END            0x20
> > -#define R_ISR                   R_MAPPER_END
> > -#define R_IEN                   0x24
> > -#define R_IEN_SET               0x28
> > -#define R_IEN_CLR               0x2c
> > -#define R_PERCORE_ISR(x)        (0x40 + 0x8 * x)
> > -#define R_END                   0x64
> > -
> > -#define TYPE_LOONGSON_LIOINTC "loongson.liointc"
> > -DECLARE_INSTANCE_CHECKER(struct loongson_liointc, LOONGSON_LIOINTC,
> > -                         TYPE_LOONGSON_LIOINTC)
> > +#include "hw/intc/loongson_liointc.h"
> >
> >  struct loongson_liointc {
> >      SysBusDevice parent_obj;
> > @@ -123,14 +102,13 @@ liointc_read(void *opaque, hwaddr addr, unsigned int size)
> >          goto out;
> >      }
> >
> > -    /* Rest is 4 byte */
> > +    /* Rest are 4 bytes */
> >      if (size != 4 || (addr % 4)) {
> >          goto out;
> >      }
> >
> > -    if (addr >= R_PERCORE_ISR(0) &&
> > -        addr < R_PERCORE_ISR(NUM_CORES)) {
> > -        int core = (addr - R_PERCORE_ISR(0)) / 8;
> > +    if (addr >= R_START && addr < R_END) {
> > +        int core = (addr - R_START) / R_ISR_SIZE;
> >          r = p->per_core_isr[core];
> >          goto out;
> >      }
> > @@ -147,7 +125,8 @@ liointc_read(void *opaque, hwaddr addr, unsigned int size)
> >      }
> >
> >  out:
> > -    D(qemu_log("%s: size=%d addr=%lx val=%x\n", __func__, size, addr, r));
> > +    qemu_log_mask(CPU_LOG_INT, "%s: size=%d addr=%lx val=%x\n",
> > +                  __func__, size, addr, r);
> >      return r;
> >  }
> >
> > @@ -158,7 +137,8 @@ liointc_write(void *opaque, hwaddr addr,
> >      struct loongson_liointc *p = opaque;
> >      uint32_t value = val64;
> >
> > -    D(qemu_log("%s: size=%d, addr=%lx val=%x\n", __func__, size, addr, value));
> > +    qemu_log_mask(CPU_LOG_INT, "%s: size=%d, addr=%lx val=%x\n",
> > +                  __func__, size, addr, value);
> >
> >      /* Mapper is 1 byte */
> >      if (size == 1 && addr < R_MAPPER_END) {
> > @@ -166,14 +146,13 @@ liointc_write(void *opaque, hwaddr addr,
> >          goto out;
> >      }
> >
> > -    /* Rest is 4 byte */
> > +    /* Rest are 4 bytes */
> >      if (size != 4 || (addr % 4)) {
> >          goto out;
> >      }
> >
> > -    if (addr >= R_PERCORE_ISR(0) &&
> > -        addr < R_PERCORE_ISR(NUM_CORES)) {
> > -        int core = (addr - R_PERCORE_ISR(0)) / 8;
> > +    if (addr >= R_START && addr < R_END) {
> > +        int core = (addr - R_START) / R_ISR_SIZE;
> >          p->per_core_isr[core] = value;
> >          goto out;
> >      }
> > @@ -224,7 +203,7 @@ static void loongson_liointc_init(Object *obj)
> >      }
> >
> >      memory_region_init_io(&p->mmio, obj, &pic_ops, p,
> > -                         "loongson.liointc", R_END);
> > +                         TYPE_LOONGSON_LIOINTC, R_END);
> >      sysbus_init_mmio(SYS_BUS_DEVICE(obj), &p->mmio);
> >  }
> >
> > diff --git a/include/hw/intc/loongson_liointc.h b/include/hw/intc/loongson_liointc.h
> > new file mode 100644
> > index 0000000..e11f482
> > --- /dev/null
> > +++ b/include/hw/intc/loongson_liointc.h
> > @@ -0,0 +1,39 @@
> > +/*
> > + * This file is subject to the terms and conditions of the GNU General Public
> > + * License.  See the file "COPYING" in the main directory of this archive
> > + * for more details.
> > + *
> > + * Copyright (c) 2020 Huacai Chen <chenhc@lemote.com>
> > + * Copyright (c) 2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
> > + *
> > + */
> > +
> > +#ifndef LOONSGON_LIOINTC_H
> > +#define LOONGSON_LIOINTC_H
> > +
> > +#include "qemu/units.h"
> > +#include "hw/sysbus.h"
> > +#include "qom/object.h"
> > +
> > +#define NUM_IRQS                32
> > +
> > +#define NUM_CORES               4
> > +#define NUM_IPS                 4
> > +#define NUM_PARENTS             (NUM_CORES * NUM_IPS)
> > +#define PARENT_COREx_IPy(x, y)  (NUM_IPS * x + y)
> > +
> > +#define R_MAPPER_START          0x0
> > +#define R_MAPPER_END            0x20
> > +#define R_ISR                   R_MAPPER_END
> > +#define R_IEN                   0x24
> > +#define R_IEN_SET               0x28
> > +#define R_IEN_CLR               0x2c
> > +#define R_ISR_SIZE              0x8
> > +#define R_START                 0x40
> > +#define R_END                   0x64
>
> Can we keep the R_* definitions local in the .c?
> (if you agree I can amend that when applying).
If put them in .c, then .h is to small.., but TYPE_LOONGSON_LIOINTC
should be defined in .h since it will be used in other place.

Huacai
>
> Thanks for cleaning!
>
> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
>
> > +
> > +#define TYPE_LOONGSON_LIOINTC "loongson.liointc"
> > +DECLARE_INSTANCE_CHECKER(struct loongson_liointc, LOONGSON_LIOINTC,
> > +                         TYPE_LOONGSON_LIOINTC)
> > +
> > +#endif /* LOONGSON_LIOINTC_H */
> >


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

* Re: [PATCH V17 2/6] hw/intc: Rework Loongson LIOINTC
  2020-11-23 22:24     ` Philippe Mathieu-Daudé
@ 2020-11-28  6:20       ` Huacai Chen
  0 siblings, 0 replies; 31+ messages in thread
From: Huacai Chen @ 2020-11-28  6:20 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Huacai Chen, Aleksandar Rikalo, QEMU Developers, Aurelien Jarno,
	Aleksandar Markovic

Hi, Philippe,

On Tue, Nov 24, 2020 at 6:24 AM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>
> On 11/23/20 9:52 PM, Philippe Mathieu-Daudé wrote:
> > On 11/6/20 5:21 AM, Huacai Chen wrote:
> >> As suggested by Philippe Mathieu-Daudé, rework Loongson's liointc:
> >> 1, Move macro definitions to loongson_liointc.h;
> >> 2, Remove magic values and use macros instead;
> >> 3, Replace dead D() code by trace events.
> >>
> >> Suggested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> >> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> >> ---
> >>  hw/intc/loongson_liointc.c         | 49 +++++++++++---------------------------
> >>  include/hw/intc/loongson_liointc.h | 39 ++++++++++++++++++++++++++++++
> >>  2 files changed, 53 insertions(+), 35 deletions(-)
> >>  create mode 100644 include/hw/intc/loongson_liointc.h
> >>
> >> diff --git a/hw/intc/loongson_liointc.c b/hw/intc/loongson_liointc.c
> >> index fbbfb57..be29e2f 100644
> >> --- a/hw/intc/loongson_liointc.c
> >> +++ b/hw/intc/loongson_liointc.c
> >> @@ -1,6 +1,7 @@
> >>  /*
> >>   * QEMU Loongson Local I/O interrupt controler.
> >>   *
> >> + * Copyright (c) 2020 Huacai Chen <chenhc@lemote.com>
> >>   * Copyright (c) 2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
> >>   *
> >>   * This program is free software: you can redistribute it and/or modify
> >> @@ -19,33 +20,11 @@
> >>   */
> >>
> >>  #include "qemu/osdep.h"
> >> -#include "hw/sysbus.h"
> >>  #include "qemu/module.h"
> >> +#include "qemu/log.h"
> >>  #include "hw/irq.h"
> >>  #include "hw/qdev-properties.h"
> >> -#include "qom/object.h"
> >> -
> >> -#define D(x)
> >> -
> >> -#define NUM_IRQS                32
> >> -
> >> -#define NUM_CORES               4
> >> -#define NUM_IPS                 4
> >> -#define NUM_PARENTS             (NUM_CORES * NUM_IPS)
> >> -#define PARENT_COREx_IPy(x, y)  (NUM_IPS * x + y)
> >> -
> >> -#define R_MAPPER_START          0x0
> >> -#define R_MAPPER_END            0x20
> >> -#define R_ISR                   R_MAPPER_END
> >> -#define R_IEN                   0x24
> >> -#define R_IEN_SET               0x28
> >> -#define R_IEN_CLR               0x2c
> >> -#define R_PERCORE_ISR(x)        (0x40 + 0x8 * x)
> >> -#define R_END                   0x64
> >> -
> >> -#define TYPE_LOONGSON_LIOINTC "loongson.liointc"
> >> -DECLARE_INSTANCE_CHECKER(struct loongson_liointc, LOONGSON_LIOINTC,
> >> -                         TYPE_LOONGSON_LIOINTC)
> >> +#include "hw/intc/loongson_liointc.h"
> >>
> >>  struct loongson_liointc {
> >>      SysBusDevice parent_obj;
> >> @@ -123,14 +102,13 @@ liointc_read(void *opaque, hwaddr addr, unsigned int size)
> >>          goto out;
> >>      }
> >>
> >> -    /* Rest is 4 byte */
> >> +    /* Rest are 4 bytes */
> >>      if (size != 4 || (addr % 4)) {
> >>          goto out;
> >>      }
> >>
> >> -    if (addr >= R_PERCORE_ISR(0) &&
> >> -        addr < R_PERCORE_ISR(NUM_CORES)) {
> >> -        int core = (addr - R_PERCORE_ISR(0)) / 8;
> >> +    if (addr >= R_START && addr < R_END) {
> >> +        int core = (addr - R_START) / R_ISR_SIZE;
> >>          r = p->per_core_isr[core];
> >>          goto out;
> >>      }
> >> @@ -147,7 +125,8 @@ liointc_read(void *opaque, hwaddr addr, unsigned int size)
> >>      }
> >>
> >>  out:
> >> -    D(qemu_log("%s: size=%d addr=%lx val=%x\n", __func__, size, addr, r));
> >> +    qemu_log_mask(CPU_LOG_INT, "%s: size=%d addr=%lx val=%x\n",
> >> +                  __func__, size, addr, r);
> >>      return r;
> >>  }
> >>
> >> @@ -158,7 +137,8 @@ liointc_write(void *opaque, hwaddr addr,
> >>      struct loongson_liointc *p = opaque;
> >>      uint32_t value = val64;
> >>
> >> -    D(qemu_log("%s: size=%d, addr=%lx val=%x\n", __func__, size, addr, value));
> >> +    qemu_log_mask(CPU_LOG_INT, "%s: size=%d, addr=%lx val=%x\n",
> >> +                  __func__, size, addr, value);
> >>
> >>      /* Mapper is 1 byte */
> >>      if (size == 1 && addr < R_MAPPER_END) {
> >> @@ -166,14 +146,13 @@ liointc_write(void *opaque, hwaddr addr,
> >>          goto out;
> >>      }
> >>
> >> -    /* Rest is 4 byte */
> >> +    /* Rest are 4 bytes */
> >>      if (size != 4 || (addr % 4)) {
> >>          goto out;
> >>      }
> >>
> >> -    if (addr >= R_PERCORE_ISR(0) &&
> >> -        addr < R_PERCORE_ISR(NUM_CORES)) {
> >> -        int core = (addr - R_PERCORE_ISR(0)) / 8;
> >> +    if (addr >= R_START && addr < R_END) {
> >> +        int core = (addr - R_START) / R_ISR_SIZE;
> >>          p->per_core_isr[core] = value;
> >>          goto out;
> >>      }
> >> @@ -224,7 +203,7 @@ static void loongson_liointc_init(Object *obj)
> >>      }
> >>
> >>      memory_region_init_io(&p->mmio, obj, &pic_ops, p,
> >> -                         "loongson.liointc", R_END);
> >> +                         TYPE_LOONGSON_LIOINTC, R_END);
> >>      sysbus_init_mmio(SYS_BUS_DEVICE(obj), &p->mmio);
> >>  }
> >>
> >> diff --git a/include/hw/intc/loongson_liointc.h b/include/hw/intc/loongson_liointc.h
> >> new file mode 100644
> >> index 0000000..e11f482
> >> --- /dev/null
> >> +++ b/include/hw/intc/loongson_liointc.h
> >> @@ -0,0 +1,39 @@
> >> +/*
> >> + * This file is subject to the terms and conditions of the GNU General Public
> >> + * License.  See the file "COPYING" in the main directory of this archive
> >> + * for more details.
> >> + *
> >> + * Copyright (c) 2020 Huacai Chen <chenhc@lemote.com>
> >> + * Copyright (c) 2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
> >> + *
> >> + */
> >> +
> >> +#ifndef LOONSGON_LIOINTC_H
> >> +#define LOONGSON_LIOINTC_H
>
> Clang is smart:
>
> hw/intc/loongson_liointc.h:11:9: error: 'LOONSGON_LIOINTC_H' is used as
> a header guard here, followed by #define of a different macro
> [-Werror,-Wheader-guard]
> #ifndef LOONSGON_LIOINTC_H
>         ^~~~~~~~~~~~~~~~~~
> include/hw/intc/loongson_liointc.h:12:9: note: 'LOONGSON_LIOINTC_H' is
> defined here; did you mean 'LOONSGON_LIOINTC_H'?
> #define LOONGSON_LIOINTC_H
>         ^~~~~~~~~~~~~~~~~~
>         LOONSGON_LIOINTC_H
> 1 error generated.
>
> Once fixed:
> Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
OK, will be fixed in the next version.

>
> >> +
> >> +#include "qemu/units.h"
> >> +#include "hw/sysbus.h"
> >> +#include "qom/object.h"
> >> +
> >> +#define NUM_IRQS                32
> >> +
> >> +#define NUM_CORES               4
> >> +#define NUM_IPS                 4
> >> +#define NUM_PARENTS             (NUM_CORES * NUM_IPS)
> >> +#define PARENT_COREx_IPy(x, y)  (NUM_IPS * x + y)
> >> +
> >> +#define R_MAPPER_START          0x0
> >> +#define R_MAPPER_END            0x20
> >> +#define R_ISR                   R_MAPPER_END
> >> +#define R_IEN                   0x24
> >> +#define R_IEN_SET               0x28
> >> +#define R_IEN_CLR               0x2c
> >> +#define R_ISR_SIZE              0x8
> >> +#define R_START                 0x40
> >> +#define R_END                   0x64
> >
> > Can we keep the R_* definitions local in the .c?
> > (if you agree I can amend that when applying).
> >
> > Thanks for cleaning!
> >
> > Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> >
> >> +
> >> +#define TYPE_LOONGSON_LIOINTC "loongson.liointc"
> >> +DECLARE_INSTANCE_CHECKER(struct loongson_liointc, LOONGSON_LIOINTC,
> >> +                         TYPE_LOONGSON_LIOINTC)
> >> +
> >> +#endif /* LOONGSON_LIOINTC_H */
> >>
> >


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

* Re: [PATCH V17 5/6] hw/mips: Add Loongson-3 machine support
  2020-11-23 21:54   ` Philippe Mathieu-Daudé
@ 2020-11-28  7:04     ` Huacai Chen
  0 siblings, 0 replies; 31+ messages in thread
From: Huacai Chen @ 2020-11-28  7:04 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Huacai Chen, Aleksandar Rikalo, QEMU Developers, Aurelien Jarno,
	Aleksandar Markovic

Hi, Philippe,

On Tue, Nov 24, 2020 at 5:54 AM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>
> Hi Huacai,
>
> On 11/6/20 5:21 AM, Huacai Chen wrote:
> > Add Loongson-3 based machine support, it use liointc as the interrupt
> > controler and use GPEX as the pci controller. Currently it can work with
> > both TCG and KVM.
> >
> > As the machine model is not based on any exiting physical hardware, the
> > name of the machine is "loongson3-virt". It may be superseded in future
> > by a real machine model. If this happens, then a regular deprecation
> > procedure shall occur for "loongson3-virt" machine.
> >
> > We now already have a full functional Linux kernel (based on Linux-5.4.x
> > LTS) here:
> >
> > https://github.com/chenhuacai/linux
> >
> > Of course the upstream kernel is also usable (the kvm host side and
> > guest side have both been upstream in Linux-5.9):
> >
> > https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
> >
> > How to use QEMU/Loongson-3?
> > 1, Download kernel source from the above URL;
> > 2, Build a kernel with arch/mips/configs/loongson3_defconfig;
> > 3, Boot a Loongson-3A4000 host with this kernel (for KVM mode);
> > 4, Build QEMU-master with this patchset;
> > 5, modprobe kvm (only necessary for KVM mode);
> > 6, Use QEMU with TCG:
> >        qemu-system-mips64el -M loongson3-virt,accel=tcg -cpu Loongson-3A1000 -kernel <path_to_kernel> -append ...
> >    Use QEMU with KVM:
> >        qemu-system-mips64el -M loongson3-virt,accel=kvm -cpu Loongson-3A4000 -kernel <path_to_kernel> -append ...
> >
> >    The "-cpu" parameter is optional here and QEMU will use the correct type for TCG/KVM automatically.
> >
> > Signed-off-by: Huacai Chen <chenhc@lemote.com>
> > Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> > Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> > ---
> >  default-configs/devices/mips64el-softmmu.mak |   1 +
> >  hw/mips/Kconfig                              |  12 +
> >  hw/mips/loongson3_virt.c                     | 614 +++++++++++++++++++++++++++
> >  hw/mips/meson.build                          |   2 +-
> >  4 files changed, 628 insertions(+), 1 deletion(-)
> >  create mode 100644 hw/mips/loongson3_virt.c
> >
> > diff --git a/default-configs/devices/mips64el-softmmu.mak b/default-configs/devices/mips64el-softmmu.mak
> > index 9f8a3ef..26c660a 100644
> > --- a/default-configs/devices/mips64el-softmmu.mak
> > +++ b/default-configs/devices/mips64el-softmmu.mak
> > @@ -3,6 +3,7 @@
> >  include mips-softmmu-common.mak
> >  CONFIG_IDE_VIA=y
> >  CONFIG_FULOONG=y
> > +CONFIG_LOONGSON3V=y
> >  CONFIG_ATI_VGA=y
> >  CONFIG_RTL8139_PCI=y
> >  CONFIG_JAZZ=y
> > diff --git a/hw/mips/Kconfig b/hw/mips/Kconfig
> > index 8be7012..ef5cee1 100644
> > --- a/hw/mips/Kconfig
> > +++ b/hw/mips/Kconfig
> > @@ -32,6 +32,18 @@ config FULOONG
> >      bool
> >      select PCI_BONITO
> >
> > +config LOONGSON3V
> > +    bool
> > +    select PCKBD
>
> Is it used? I only see USB.
OK, PCKBD will be removed.

>
> > +    select SERIAL
> > +    select GOLDFISH_RTC
> > +    select LOONGSON_LIOINTC
> > +    select PCI_DEVICES
> > +    select PCI_EXPRESS_GENERIC_BRIDGE
> > +    select VIRTIO_VGA
> > +    select QXL if SPICE
>
> I don't understand the UI dependencies, as we should
> be able to start this machine without UI (just console
> for example).
>
> Maybe you want the 'imply' keyword instead?
OK, I will use imply instead.

>
> > +    select MSI_NONBROKEN
> > +
> >  config MIPS_CPS
> >      bool
> >      select PTIMER
> > diff --git a/hw/mips/loongson3_virt.c b/hw/mips/loongson3_virt.c
> > new file mode 100644
> > index 0000000..c5db2db
> > --- /dev/null
> > +++ b/hw/mips/loongson3_virt.c
> > @@ -0,0 +1,614 @@
> > +/*
> > + * Generic Loongson-3 Platform support
> > + *
> > + * Copyright (c) 2018-2020 Huacai Chen (chenhc@lemote.com)
> > + * Copyright (c) 2018-2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
> > + *
> > + * This program is free software: you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License as published by
> > + * the Free Software Foundation, either version 2 of the License, or
> > + * (at your option) any later version.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > + * GNU General Public License for more details.
> > + *
> > + * You should have received a copy of the GNU General Public License
> > + * along with this program. If not, see <https://www.gnu.org/licenses/>.
> > + */
> > +
> > +/*
> > + * Generic virtualized 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 "qemu/cutils.h"
> > +#include "qapi/error.h"
> > +#include "cpu.h"
> > +#include "elf.h"
> > +#include "kvm_mips.h"
> > +#include "hw/boards.h"
> > +#include "hw/char/serial.h"
> > +#include "hw/intc/loongson_liointc.h"
> > +#include "hw/mips/mips.h"
> > +#include "hw/mips/cpudevs.h"
> > +#include "hw/mips/fw_cfg.h"
> > +#include "hw/mips/loongson3_bootp.h"
> > +#include "hw/misc/unimp.h"
> > +#include "hw/intc/i8259.h"
> > +#include "hw/loader.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/usb.h"
> > +#include "net/net.h"
> > +#include "exec/address-spaces.h"
> > +#include "sysemu/kvm.h"
> > +#include "sysemu/qtest.h"
> > +#include "sysemu/reset.h"
> > +#include "sysemu/runstate.h"
> > +#include "qemu/log.h"
> > +#include "qemu/error-report.h"
> > +
> > +#define PM_CNTL_MODE          0x10
> > +
> > +#define LOONGSON_MAX_VCPUS      16
> > +
> > +/*
> > + * Loongson-3's virtual machine BIOS can be obtained here:
> > + * 1, https://github.com/loongson-community/firmware-nonfree
> > + * 2, http://dev.lemote.com:8000/files/firmware/UEFI/KVM/bios_loongson3.bin
> > + */
> > +#define LOONGSON3_BIOSNAME "bios_loongson3.bin"
> > +
> > +#define UART_IRQ            0
> > +#define RTC_IRQ             1
> > +#define PCIE_IRQ_BASE       2
> > +
> > +const struct MemmapEntry virt_memmap[] = {
> > +    [VIRT_LOWMEM] =      { 0x00000000,    0x10000000 },
> > +    [VIRT_PM] =          { 0x10080000,         0x100 },
> > +    [VIRT_FW_CFG] =      { 0x10080100,         0x100 },
> > +    [VIRT_RTC] =         { 0x10081000,        0x1000 },
> > +    [VIRT_PCIE_PIO] =    { 0x18000000,       0x80000 },
> > +    [VIRT_PCIE_ECAM] =   { 0x1a000000,     0x2000000 },
> > +    [VIRT_BIOS_ROM] =    { 0x1fc00000,      0x200000 },
> > +    [VIRT_UART] =        { 0x1fe001e0,           0x8 },
> > +    [VIRT_LIOINTC] =     { 0x3ff01400,          0x64 },
> > +    [VIRT_PCIE_MMIO] =   { 0x40000000,    0x40000000 },
> > +    [VIRT_HIGHMEM] =     { 0x80000000,           0x0 }, /* Variable */
> > +};
> > +
> > +static const struct MemmapEntry loader_memmap[] = {
> > +    [LOADER_KERNEL] =    { 0x00000000,     0x4000000 },
> > +    [LOADER_INITRD] =    { 0x04000000,           0x0 }, /* Variable */
> > +    [LOADER_CMDLINE] =   { 0x0ff00000,      0x100000 },
> > +};
> > +
> > +static const struct MemmapEntry loader_rommap[] = {
> > +    [LOADER_BOOTROM] =   { 0x1fc00000,        0x1000 },
> > +    [LOADER_PARAM] =     { 0x1fc01000,       0x10000 },
> > +};
> > +
> > +static struct _loaderparams {
> > +    uint64_t cpu_freq;
> > +    uint64_t ram_size;
> > +    const char *kernel_cmdline;
> > +    const char *kernel_filename;
> > +    const char *initrd_filename;
> > +    uint64_t kernel_entry;
> > +    uint64_t a0, a1, a2;
> > +} loaderparams;
> > +
> > +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,
>
> Any access size is OK? (from your ASM it is byte accessed).
OK, I will limit it to byte access.

>
> > +    .endianness = DEVICE_NATIVE_ENDIAN,
> > +};
> > +
> > +#define DEF_LOONGSON3_FREQ (800 * 1000 * 1000)
> > +
> > +static uint64_t get_cpu_freq_hz(void)
> > +{
> > +#ifdef CONFIG_KVM
> > +    int ret;
> > +    uint64_t freq;
> > +    struct kvm_one_reg freq_reg = {
> > +        .id = KVM_REG_MIPS_COUNT_HZ,
> > +        .addr = (uintptr_t)(&freq)
> > +    };
> > +
> > +    if (kvm_enabled()) {
> > +        ret = kvm_vcpu_ioctl(first_cpu, KVM_GET_ONE_REG, &freq_reg);
> > +        if (ret >= 0) {
> > +            return freq * 2;
> > +        }
> > +    }
> > +#endif
> > +    return DEF_LOONGSON3_FREQ;
> > +}
> > +
> > +static void init_boot_param(void)
> > +{
> > +    void *p;
> > +    struct boot_params *bp;
> > +
> > +    p = g_malloc0(loader_rommap[LOADER_PARAM].size);
>
> I'm worried Coverity complains we are leaking this. Maybe keep it
> static? [updated, see MachineState comment below]
>
> > +    bp = p;
> > +
> > +    stw_le_p(&bp->efi.smbios.vers, 1);
> > +    init_reset_system(&(bp->reset_system));
> > +    p += ROUND_UP(sizeof(struct boot_params), 64);
> > +    init_loongson_params(&(bp->efi.smbios.lp), p,
> > +                         loaderparams.cpu_freq, loaderparams.ram_size);
> > +
> > +    rom_add_blob_fixed("params_rom", bp,
> > +                       loader_rommap[LOADER_PARAM].size,
> > +                       loader_rommap[LOADER_PARAM].base);
> > +
> > +    g_free(bp);
> > +
> > +    loaderparams.a2 = cpu_mips_phys_to_kseg0(NULL, loader_rommap[LOADER_PARAM].base);
> > +}
> > +
> > +static void init_boot_rom(void)
> > +{
> > +    const unsigned int boot_code[] = {
> > +        0x40086000,   /* mfc0    t0, CP0_STATUS                               */
> > +        0x240900E4,   /* li      t1, 0xe4         #set kx, sx, ux, erl        */
> > +        0x01094025,   /* or      t0, t0, t1                                   */
> > +        0x3C090040,   /* lui     t1, 0x40         #set 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                                                  */
> > +    };
> > +
> > +    rom_add_blob_fixed("boot_rom", boot_code, sizeof(boot_code),
> > +                        loader_rommap[LOADER_BOOTROM].base);
> > +}
> > +
> > +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;
> > +    hwaddr cfg_addr = virt_memmap[VIRT_FW_CFG].base;
> > +
> > +    fw_cfg = fw_cfg_init_mem_wide(cfg_addr, cfg_addr + 8, 8, 0, NULL);
> > +    fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)current_machine->smp.cpus);
> > +    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)current_machine->smp.max_cpus);
> > +    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
> > +    fw_cfg_add_i32(fw_cfg, FW_CFG_MACHINE_VERSION, 1);
> > +    fw_cfg_add_i64(fw_cfg, FW_CFG_CPU_FREQ, get_cpu_freq_hz());
> > +    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
> > +}
> > +
> > +static int set_prom_cmdline(ram_addr_t initrd_offset, long initrd_size)
> > +{
> > +    hwaddr cmdline_vaddr;
> > +    char memenv[32];
> > +    char highmemenv[32];
> > +    void *cmdline_buf;
> > +    unsigned int *parg_env;
> > +    int ret = 0;
> > +
> > +    /* Allocate cmdline_buf for command line. */
> > +    cmdline_buf = g_malloc0(loader_memmap[LOADER_CMDLINE].size);
> > +    cmdline_vaddr = cpu_mips_phys_to_kseg0(NULL,
> > +                                           loader_memmap[LOADER_CMDLINE].base);
> > +
> > +    /*
> > +     * Layout of cmdline_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 *)cmdline_buf;
> > +
> > +    ret = (3 + 1) * 4;
> > +    *parg_env++ = cmdline_vaddr + ret;
> > +    ret += (1 + snprintf(cmdline_buf + ret, 256 - ret, "g"));
> > +
> > +    /* argv1 */
> > +    *parg_env++ = cmdline_vaddr + ret;
> > +    if (initrd_size > 0)
> > +        ret += (1 + snprintf(cmdline_buf + ret, 256 - ret,
> > +                "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
> > +                cpu_mips_phys_to_kseg0(NULL, initrd_offset),
> > +                initrd_size, loaderparams.kernel_cmdline));
> > +    else
> > +        ret += (1 + snprintf(cmdline_buf + ret, 256 - ret, "%s",
> > +                loaderparams.kernel_cmdline));
> > +
> > +    /* argv2 */
> > +    *parg_env++ = cmdline_vaddr + 4 * ret;
> > +
> > +    /* env */
> > +    sprintf(memenv, "%d", 256);
>
> Where is that used? This could be const...
>
> > +    sprintf(highmemenv, "%ld", (unsigned long)(loaderparams.ram_size / MiB) - 256);
>
> Where is that used? Anyhow, if needed, please use g_strdup_printf().
OK, they will be removed.

>
> > +
> > +    rom_add_blob_fixed("cmdline", cmdline_buf,
> > +                       loader_memmap[LOADER_CMDLINE].size,
> > +                       loader_memmap[LOADER_CMDLINE].base);
> > +
> > +    g_free(cmdline_buf);
> > +
> > +    loaderparams.a0 = 2;
> > +    loaderparams.a1 = cmdline_vaddr;
> > +
> > +    return 0;
> > +}
> > +
> > +static uint64_t load_kernel(CPUMIPSState *env)
> > +{
> > +    long kernel_size;
> > +    ram_addr_t initrd_offset;
> > +    uint64_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 = MAX(loader_memmap[LOADER_INITRD].base,
> > +                                ROUND_UP(kernel_high, INITRD_PAGE_SIZE));
> > +
> > +            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 cmdline. */
> > +    set_prom_cmdline(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 inline void loongson3_virt_devices_init(MachineState *machine, DeviceState *pic)
> > +{
> > +    int i;
> > +    qemu_irq irq;
> > +    PCIBus *pci_bus;
> > +    DeviceState *dev;
> > +    MemoryRegion *pio_alias;
> > +    MemoryRegion *mmio_alias, *mmio_reg;
> > +    MemoryRegion *ecam_alias, *ecam_reg;
> > +
> > +    dev = qdev_new(TYPE_GPEX_HOST);
> > +    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
> > +    pci_bus = PCI_HOST_BRIDGE(dev)->bus;
> > +
> > +    ecam_alias = g_new0(MemoryRegion, 1);
>
> Again, Coverity will complain for the memory leaked :(
>
> I think you want to keep all these pointers in an object
> extending MachineState. You can check at RaspiMachineState
> for an example.
OK, I will do.

>
> > +    ecam_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 0);
> > +    memory_region_init_alias(ecam_alias, OBJECT(dev), "pcie-ecam",
> > +                             ecam_reg, 0, virt_memmap[VIRT_PCIE_ECAM].size);
> > +    memory_region_add_subregion(get_system_memory(),
> > +                                virt_memmap[VIRT_PCIE_ECAM].base, ecam_alias);
> > +
> > +    mmio_alias = g_new0(MemoryRegion, 1);
> > +    mmio_reg = sysbus_mmio_get_region(SYS_BUS_DEVICE(dev), 1);
> > +    memory_region_init_alias(mmio_alias, OBJECT(dev), "pcie-mmio",
> > +                             mmio_reg, virt_memmap[VIRT_PCIE_MMIO].base,
> > +                             virt_memmap[VIRT_PCIE_MMIO].size);
> > +    memory_region_add_subregion(get_system_memory(),
> > +                                virt_memmap[VIRT_PCIE_MMIO].base, mmio_alias);
> > +
> > +    pio_alias = g_new0(MemoryRegion, 1);
> > +    memory_region_init_alias(pio_alias, OBJECT(dev), "pcie-pio",
> > +                             get_system_io(), 0, virt_memmap[VIRT_PCIE_PIO].size);
> > +    memory_region_add_subregion(get_system_memory(),
> > +                                virt_memmap[VIRT_PCIE_PIO].base, pio_alias);
> > +    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 2, virt_memmap[VIRT_PCIE_PIO].base);
> > +
> > +    for (i = 0; i < GPEX_NUM_IRQS; i++) {
> > +        irq = qdev_get_gpio_in(pic, PCIE_IRQ_BASE + i);
> > +        sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, irq);
> > +        gpex_set_irq_num(GPEX_HOST(dev), i, PCIE_IRQ_BASE + i);
> > +    }
>
> Maybe set here "msi_nonbroken = true;".
OK.

>
> > +
> > +    pci_vga_init(pci_bus);
>
> Maybe part of defaults_enabled... not sure although.
Not needed, other machines also do it like this.

>
> > +
> > +    if (defaults_enabled()) {
> > +        pci_create_simple(pci_bus, -1, "pci-ohci");
> > +        usb_create_simple(usb_bus_find(-1), "usb-kbd");
> > +        usb_create_simple(usb_bus_find(-1), "usb-tablet");
> > +    }
> > +
> > +    for (i = 0; i < nb_nics; i++) {
> > +        NICInfo *nd = &nd_table[i];
> > +
> > +        if (!nd->model) {
> > +            nd->model = g_strdup("virtio");
> > +        }
> > +
> > +        pci_nic_init_nofail(nd, pci_bus, nd->model, NULL);
> > +    }
> > +}
> > +
> > +static void mips_loongson3_virt_init(MachineState *machine)
> > +{
> > +    int i;
> > +    long bios_size;
> > +    MIPSCPU *cpu;
> > +    Clock *cpuclk;
> > +    CPUMIPSState *env;
> > +    DeviceState *liointc;
> > +    char *filename;
> > +    const char *kernel_cmdline = machine->kernel_cmdline;
> > +    const char *kernel_filename = machine->kernel_filename;
> > +    const char *initrd_filename = machine->initrd_filename;
> > +    ram_addr_t ram_size = machine->ram_size;
> > +    MemoryRegion *address_space_mem = get_system_memory();
> > +    MemoryRegion *ram = g_new(MemoryRegion, 1);
> > +    MemoryRegion *bios = g_new(MemoryRegion, 1);
> > +    MemoryRegion *iomem = g_new(MemoryRegion, 1);
> > +
> > +    /* TODO: TCG will support all CPU types */
> > +    if (!kvm_enabled()) {
> > +        if (!machine->cpu_type) {
> > +            machine->cpu_type = MIPS_CPU_TYPE_NAME("Loongson-3A1000");
> > +        }
> > +        if (!strstr(machine->cpu_type, "Loongson-3A1000")) {
> > +            error_report("Loongson-3/TCG needs cpu type Loongson-3A1000");
>
> Why not accept any 3A family?
Because some new instructions hadn't been emulated in qemu.

>
> > +            exit(1);
> > +        }
> > +    } else {
> > +        if (!machine->cpu_type) {
> > +            machine->cpu_type = MIPS_CPU_TYPE_NAME("Loongson-3A4000");
> > +        }
> > +        if (!strstr(machine->cpu_type, "Loongson-3A4000")) {
> > +            error_report("Loongson-3/KVM needs cpu type Loongson-3A4000");
> > +            exit(1);
> > +        }
> > +    }
> > +
> > +    if (ram_size < 512 * MiB) {
> > +        error_report("Loongson-3 machine needs at least 512MB memory");
> > +        exit(1);
> > +    }
> > +
> > +    /*
> > +     * The whole MMIO range among configure registers doesn't generate
> > +     * exception when accessing invalid memory. Create some unimplememted
> > +     * devices to emulate this feature.
> > +     */
> > +    create_unimplemented_device("mmio fallback 0", 0x10000000, 256 * MiB);
> > +    create_unimplemented_device("mmio fallback 1", 0x30000000, 256 * MiB);
> > +
> > +    liointc = qdev_new("loongson.liointc");
> > +    sysbus_realize_and_unref(SYS_BUS_DEVICE(liointc), &error_fatal);
> > +
> > +    sysbus_mmio_map(SYS_BUS_DEVICE(liointc), 0, virt_memmap[VIRT_LIOINTC].base);
> > +
> > +    serial_mm_init(address_space_mem, virt_memmap[VIRT_UART].base, 0,
> > +                   qdev_get_gpio_in(liointc, UART_IRQ), 115200, serial_hd(0),
> > +                   DEVICE_NATIVE_ENDIAN);
> > +
> > +    sysbus_create_simple("goldfish_rtc", virt_memmap[VIRT_RTC].base,
> > +                         qdev_get_gpio_in(liointc, RTC_IRQ));
> > +
> > +    cpuclk = clock_new(OBJECT(machine), "cpu-refclk");
> > +    clock_set_hz(cpuclk, DEF_LOONGSON3_FREQ);
> > +
> > +    for (i = 0; i < machine->smp.cpus; i++) {
> > +        int ip;
> > +
> > +        /* init CPUs */
> > +        cpu = mips_cpu_create_with_clock(machine->cpu_type, cpuclk);
> > +
> > +        /* Init internal devices */
> > +        cpu_mips_irq_init_cpu(cpu);
> > +        cpu_mips_clock_init(cpu);
> > +        qemu_register_reset(main_cpu_reset, cpu);
> > +
> > +        if (i >= 4) {
> > +            continue; /* Only node-0 can be connected to LIOINTC */
> > +        }
> > +
> > +        for (ip = 0; ip < 4 ; ip++) {
> > +            int pin = i * 4 + ip;
> > +            sysbus_connect_irq(SYS_BUS_DEVICE(liointc),
> > +                               pin, cpu->env.irq[ip + 2]);
> > +        }
> > +    }
> > +    env = &MIPS_CPU(first_cpu)->env;
> > +
> > +    /* Allocate RAM/BIOS, 0x00000000~0x10000000 is alias of 0x80000000~0x90000000 */
> > +    memory_region_init_rom(bios, NULL, "loongson3.bios",
> > +                           virt_memmap[VIRT_BIOS_ROM].size, &error_fatal);
> > +    memory_region_init_alias(ram, NULL, "loongson3.lowmem",
> > +                           machine->ram, 0, virt_memmap[VIRT_LOWMEM].size);
> > +    memory_region_init_io(iomem, NULL, &loongson3_pm_ops,
> > +                           NULL, "loongson3_pm", virt_memmap[VIRT_PM].size);
> > +
> > +    memory_region_add_subregion(address_space_mem,
> > +                      virt_memmap[VIRT_LOWMEM].base, ram);
> > +    memory_region_add_subregion(address_space_mem,
> > +                      virt_memmap[VIRT_BIOS_ROM].base, bios);
> > +    memory_region_add_subregion(address_space_mem,
> > +                      virt_memmap[VIRT_HIGHMEM].base, machine->ram);
> > +    memory_region_add_subregion(address_space_mem,
> > +                      virt_memmap[VIRT_PM].base, iomem);
> > +
> > +    /*
> > +     * We do not support flash operation, just loading bios.bin as raw BIOS.
> > +     * Please use -L to set the BIOS path and -bios to set bios name.
> > +     */
> > +
> > +    if (kernel_filename) {
> > +        loaderparams.cpu_freq = get_cpu_freq_hz();
> > +        loaderparams.ram_size = ram_size;
> > +        loaderparams.kernel_filename = kernel_filename;
> > +        loaderparams.kernel_cmdline = kernel_cmdline;
> > +        loaderparams.initrd_filename = initrd_filename;
> > +        loaderparams.kernel_entry = load_kernel(env);
> > +
> > +        init_boot_rom();
> > +        init_boot_param();
> > +    } 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,
> > +                                            virt_memmap[VIRT_BIOS_ROM].base,
> > +                                            virt_memmap[VIRT_BIOS_ROM].size);
> > +            g_free(filename);
> > +        } else {
> > +            bios_size = -1;
> > +        }
> > +
> > +        if ((bios_size < 0 || bios_size > virt_memmap[VIRT_BIOS_ROM].size) &&
> > +            !kernel_filename && !qtest_enabled()) {
> > +            error_report("Could not load MIPS bios '%s'", bios_name);
> > +            exit(1);
> > +        }
> > +
> > +        fw_conf_init(ram_size);
> > +    }
> > +
> > +    msi_nonbroken = true;
> > +    loongson3_virt_devices_init(machine, liointc);
> > +}
> > +
> > +static void mips_loongson3_virt_machine_init(MachineClass *mc)
> > +{
> > +    mc->desc = "Loongson-3 Virtualization Platform";
> > +    mc->init = mips_loongson3_virt_init;
> > +    mc->block_default_type = IF_IDE;
> > +    mc->max_cpus = LOONGSON_MAX_VCPUS;
> > +    mc->default_ram_id = "loongson3.highram";
> > +    mc->default_ram_size = 1600 * MiB;
> > +    mc->kvm_type = mips_kvm_type;
> > +    mc->minimum_page_bits = 14;
> > +}
> > +
> > +DEFINE_MACHINE("loongson3-virt", mips_loongson3_virt_machine_init)
>
> There are still some questions, but we are almost there!
>
> I can fix the leak/MachineState problem if you are lost.
>
> For smoke testing, you can have a look at test_pmon_serial_console()
> in https://www.mail-archive.com/qemu-devel@nongnu.org/msg752605.html
> (forgot the test_pmon_framebuffer_console part).
> This should be almost a copy/paste for your machine.
I will improve these problems in the next version, thanks.

Huacai
>
> Regards,
>
> Phil.


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

* Re: [PATCH V17 2/6] hw/intc: Rework Loongson LIOINTC
  2020-11-28  6:19     ` Huacai Chen
@ 2020-11-30 10:08       ` Philippe Mathieu-Daudé
  2020-12-02  1:16         ` Huacai Chen
  0 siblings, 1 reply; 31+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-11-30 10:08 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Huacai Chen, Aleksandar Rikalo, QEMU Developers, Aurelien Jarno,
	Aleksandar Markovic

On 11/28/20 7:19 AM, Huacai Chen wrote:
> On Tue, Nov 24, 2020 at 4:52 AM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>> On 11/6/20 5:21 AM, Huacai Chen wrote:
>>> As suggested by Philippe Mathieu-Daudé, rework Loongson's liointc:
>>> 1, Move macro definitions to loongson_liointc.h;
>>> 2, Remove magic values and use macros instead;
>>> 3, Replace dead D() code by trace events.
>>>
>>> Suggested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
>>> Signed-off-by: Huacai Chen <chenhc@lemote.com>
>>> ---
>>>  hw/intc/loongson_liointc.c         | 49 +++++++++++---------------------------
>>>  include/hw/intc/loongson_liointc.h | 39 ++++++++++++++++++++++++++++++
>>>  2 files changed, 53 insertions(+), 35 deletions(-)
>>>  create mode 100644 include/hw/intc/loongson_liointc.h
>>>
>>> diff --git a/hw/intc/loongson_liointc.c b/hw/intc/loongson_liointc.c
>>> index fbbfb57..be29e2f 100644
>>> --- a/hw/intc/loongson_liointc.c
>>> +++ b/hw/intc/loongson_liointc.c
>>> @@ -1,6 +1,7 @@
>>>  /*
>>>   * QEMU Loongson Local I/O interrupt controler.
>>>   *
>>> + * Copyright (c) 2020 Huacai Chen <chenhc@lemote.com>
>>>   * Copyright (c) 2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
>>>   *
>>>   * This program is free software: you can redistribute it and/or modify
>>> @@ -19,33 +20,11 @@
>>>   */
>>>
>>>  #include "qemu/osdep.h"
>>> -#include "hw/sysbus.h"
>>>  #include "qemu/module.h"
>>> +#include "qemu/log.h"
>>>  #include "hw/irq.h"
>>>  #include "hw/qdev-properties.h"
>>> -#include "qom/object.h"
>>> -
>>> -#define D(x)
>>> -
>>> -#define NUM_IRQS                32
>>> -
>>> -#define NUM_CORES               4
>>> -#define NUM_IPS                 4
>>> -#define NUM_PARENTS             (NUM_CORES * NUM_IPS)
>>> -#define PARENT_COREx_IPy(x, y)  (NUM_IPS * x + y)
>>> -
>>> -#define R_MAPPER_START          0x0
>>> -#define R_MAPPER_END            0x20
>>> -#define R_ISR                   R_MAPPER_END
>>> -#define R_IEN                   0x24
>>> -#define R_IEN_SET               0x28
>>> -#define R_IEN_CLR               0x2c
>>> -#define R_PERCORE_ISR(x)        (0x40 + 0x8 * x)
>>> -#define R_END                   0x64
>>> -
>>> -#define TYPE_LOONGSON_LIOINTC "loongson.liointc"
>>> -DECLARE_INSTANCE_CHECKER(struct loongson_liointc, LOONGSON_LIOINTC,
>>> -                         TYPE_LOONGSON_LIOINTC)
>>> +#include "hw/intc/loongson_liointc.h"
>>>
>>>  struct loongson_liointc {
>>>      SysBusDevice parent_obj;
>>> @@ -123,14 +102,13 @@ liointc_read(void *opaque, hwaddr addr, unsigned int size)
>>>          goto out;
>>>      }
>>>
>>> -    /* Rest is 4 byte */
>>> +    /* Rest are 4 bytes */
>>>      if (size != 4 || (addr % 4)) {
>>>          goto out;
>>>      }
>>>
>>> -    if (addr >= R_PERCORE_ISR(0) &&
>>> -        addr < R_PERCORE_ISR(NUM_CORES)) {
>>> -        int core = (addr - R_PERCORE_ISR(0)) / 8;
>>> +    if (addr >= R_START && addr < R_END) {
>>> +        int core = (addr - R_START) / R_ISR_SIZE;
>>>          r = p->per_core_isr[core];
>>>          goto out;
>>>      }
>>> @@ -147,7 +125,8 @@ liointc_read(void *opaque, hwaddr addr, unsigned int size)
>>>      }
>>>
>>>  out:
>>> -    D(qemu_log("%s: size=%d addr=%lx val=%x\n", __func__, size, addr, r));
>>> +    qemu_log_mask(CPU_LOG_INT, "%s: size=%d addr=%lx val=%x\n",
>>> +                  __func__, size, addr, r);
>>>      return r;
>>>  }
>>>
>>> @@ -158,7 +137,8 @@ liointc_write(void *opaque, hwaddr addr,
>>>      struct loongson_liointc *p = opaque;
>>>      uint32_t value = val64;
>>>
>>> -    D(qemu_log("%s: size=%d, addr=%lx val=%x\n", __func__, size, addr, value));
>>> +    qemu_log_mask(CPU_LOG_INT, "%s: size=%d, addr=%lx val=%x\n",
>>> +                  __func__, size, addr, value);
>>>
>>>      /* Mapper is 1 byte */
>>>      if (size == 1 && addr < R_MAPPER_END) {
>>> @@ -166,14 +146,13 @@ liointc_write(void *opaque, hwaddr addr,
>>>          goto out;
>>>      }
>>>
>>> -    /* Rest is 4 byte */
>>> +    /* Rest are 4 bytes */
>>>      if (size != 4 || (addr % 4)) {
>>>          goto out;
>>>      }
>>>
>>> -    if (addr >= R_PERCORE_ISR(0) &&
>>> -        addr < R_PERCORE_ISR(NUM_CORES)) {
>>> -        int core = (addr - R_PERCORE_ISR(0)) / 8;
>>> +    if (addr >= R_START && addr < R_END) {
>>> +        int core = (addr - R_START) / R_ISR_SIZE;
>>>          p->per_core_isr[core] = value;
>>>          goto out;
>>>      }
>>> @@ -224,7 +203,7 @@ static void loongson_liointc_init(Object *obj)
>>>      }
>>>
>>>      memory_region_init_io(&p->mmio, obj, &pic_ops, p,
>>> -                         "loongson.liointc", R_END);
>>> +                         TYPE_LOONGSON_LIOINTC, R_END);
>>>      sysbus_init_mmio(SYS_BUS_DEVICE(obj), &p->mmio);
>>>  }
>>>
>>> diff --git a/include/hw/intc/loongson_liointc.h b/include/hw/intc/loongson_liointc.h
>>> new file mode 100644
>>> index 0000000..e11f482
>>> --- /dev/null
>>> +++ b/include/hw/intc/loongson_liointc.h
>>> @@ -0,0 +1,39 @@
>>> +/*
>>> + * This file is subject to the terms and conditions of the GNU General Public
>>> + * License.  See the file "COPYING" in the main directory of this archive
>>> + * for more details.
>>> + *
>>> + * Copyright (c) 2020 Huacai Chen <chenhc@lemote.com>
>>> + * Copyright (c) 2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
>>> + *
>>> + */
>>> +
>>> +#ifndef LOONSGON_LIOINTC_H
>>> +#define LOONGSON_LIOINTC_H
>>> +
>>> +#include "qemu/units.h"
>>> +#include "hw/sysbus.h"
>>> +#include "qom/object.h"
>>> +
>>> +#define NUM_IRQS                32
>>> +
>>> +#define NUM_CORES               4
>>> +#define NUM_IPS                 4
>>> +#define NUM_PARENTS             (NUM_CORES * NUM_IPS)
>>> +#define PARENT_COREx_IPy(x, y)  (NUM_IPS * x + y)
>>> +
>>> +#define R_MAPPER_START          0x0
>>> +#define R_MAPPER_END            0x20
>>> +#define R_ISR                   R_MAPPER_END
>>> +#define R_IEN                   0x24
>>> +#define R_IEN_SET               0x28
>>> +#define R_IEN_CLR               0x2c
>>> +#define R_ISR_SIZE              0x8
>>> +#define R_START                 0x40
>>> +#define R_END                   0x64
>>
>> Can we keep the R_* definitions local in the .c?
>> (if you agree I can amend that when applying).
> If put them in .c, then .h is to small..,

Not a problem:

include/hw/ppc/openpic_kvm.h
include/hw/display/ramfb.h
include/hw/input/lasips2.h
include/hw/usb/chipidea.h
include/hw/s390x/ap-bridge.h
include/hw/char/lm32_juart.h
include/hw/isa/vt82c686.h
include/hw/net/lan9118.h
include/hw/intc/imx_gpcv2.h
include/hw/usb/xhci.h

> but TYPE_LOONGSON_LIOINTC
> should be defined in .h since it will be used in other place.
> 
> Huacai
>>
>> Thanks for cleaning!
>>
>> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
>>
>>> +
>>> +#define TYPE_LOONGSON_LIOINTC "loongson.liointc"
>>> +DECLARE_INSTANCE_CHECKER(struct loongson_liointc, LOONGSON_LIOINTC,
>>> +                         TYPE_LOONGSON_LIOINTC)
>>> +
>>> +#endif /* LOONGSON_LIOINTC_H */
>>>
> 


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

* Re: [PATCH V17 4/6] hw/mips: Add Loongson-3 boot parameter helpers
  2020-11-23 22:25   ` Philippe Mathieu-Daudé
@ 2020-12-02  1:14     ` Huacai Chen
  2020-12-02  9:32       ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 31+ messages in thread
From: Huacai Chen @ 2020-12-02  1:14 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé, Jiaxun Yang
  Cc: Huacai Chen, Aleksandar Rikalo, QEMU Developers, Aurelien Jarno,
	Aleksandar Markovic

Hi, Phillippe,

On Tue, Nov 24, 2020 at 6:25 AM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>
> On 11/6/20 5:21 AM, Huacai Chen wrote:
> > Preparing to add Loongson-3 machine support, add Loongson-3's LEFI (a
> > UEFI-like interface for BIOS-Kernel boot parameters) helpers first.
> >
> > Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> > Signed-off-by: Huacai Chen <chenhc@lemote.com>
> > Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> > Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> > ---
> >  hw/mips/loongson3_bootp.c | 165 +++++++++++++++++++++++++++++++
> >  hw/mips/loongson3_bootp.h | 241 ++++++++++++++++++++++++++++++++++++++++++++++
> >  hw/mips/meson.build       |   1 +
> >  3 files changed, 407 insertions(+)
> >  create mode 100644 hw/mips/loongson3_bootp.c
> >  create mode 100644 hw/mips/loongson3_bootp.h
> >
> > diff --git a/hw/mips/loongson3_bootp.c b/hw/mips/loongson3_bootp.c
> > new file mode 100644
> > index 0000000..3a16081
> > --- /dev/null
> > +++ b/hw/mips/loongson3_bootp.c
> > @@ -0,0 +1,165 @@
> > +/*
> > + * LEFI (a UEFI-like interface for BIOS-Kernel boot parameters) helpers
> > + *
> > + * Copyright (c) 2018-2020 Huacai Chen (chenhc@lemote.com)
> > + * Copyright (c) 2018-2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
> > + *
> > + * This program is free software: you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License as published by
> > + * the Free Software Foundation, either version 2 of the License, or
> > + * (at your option) any later version.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > + * GNU General Public License for more details.
> > + *
> > + * You should have received a copy of the GNU General Public License
> > + * along with this program. If not, see <https://www.gnu.org/licenses/>.
> > + */
> > +
> > +#include "qemu/osdep.h"
> > +#include "qemu/units.h"
> > +#include "qemu/cutils.h"
> > +#include "cpu.h"
> > +#include "hw/boards.h"
> > +#include "hw/mips/loongson3_bootp.h"
> > +
> > +#define LOONGSON3_CORE_PER_NODE 4
> > +
> > +static struct efi_cpuinfo_loongson *init_cpu_info(void *g_cpuinfo, uint64_t cpu_freq)
> > +{
> > +    struct efi_cpuinfo_loongson *c = g_cpuinfo;
> > +
> > +    stl_le_p(&c->cputype, Loongson_3A);
> > +    stl_le_p(&c->processor_id, MIPS_CPU(first_cpu)->env.CP0_PRid);
>
> Build failing with Clang:
>
> FAILED: libqemu-mips64el-softmmu.fa.p/hw_mips_loongson3_bootp.c.o
> hw/mips/loongson3_bootp.c:35:15: error: taking address of packed member
> 'processor_id' of class or structure 'efi_cpuinfo_loongson' may result
> in an unaligned pointer value [-Werror,-Waddress-of-packed-member]
>     stl_le_p(&c->processor_id, MIPS_CPU(first_cpu)->env.CP0_PRid);
>               ^~~~~~~~~~~~~~~
> 1 error generated.
We cannot reproduce it on X86/MIPS with clang... And I found that
stl_le_p() will be __builtin_memcpy(), I don't think memcpy() will
cause unaligned access. So, any suggestions?

Huacai
>
> > +    if (cpu_freq > UINT_MAX) {
> > +        stl_le_p(&c->cpu_clock_freq, UINT_MAX);
> > +    } else {
> > +        stl_le_p(&c->cpu_clock_freq, cpu_freq);
> > +    }
> > +
> > +    stw_le_p(&c->cpu_startup_core_id, 0);
> > +    stl_le_p(&c->nr_cpus, current_machine->smp.cpus);
> > +    stl_le_p(&c->total_node, DIV_ROUND_UP(current_machine->smp.cpus,
> > +                                          LOONGSON3_CORE_PER_NODE));
> > +
> > +    return c;
> > +}
> > +
> > +static struct efi_memory_map_loongson *init_memory_map(void *g_map, uint64_t ram_size)
> > +{
> > +    struct efi_memory_map_loongson *emap = g_map;
> > +
> > +    stl_le_p(&emap->nr_map, 2);
> > +    stl_le_p(&emap->mem_freq, 300000000);
> > +
> > +    stl_le_p(&emap->map[0].node_id, 0);
> > +    stl_le_p(&emap->map[0].mem_type, 1);
> > +    stq_le_p(&emap->map[0].mem_start, 0x0);
> > +    stl_le_p(&emap->map[0].mem_size, 240);
> > +
> > +    stl_le_p(&emap->map[1].node_id, 0);
> > +    stl_le_p(&emap->map[1].mem_type, 2);
> > +    stq_le_p(&emap->map[1].mem_start, 0x90000000);
> > +    stl_le_p(&emap->map[1].mem_size, (ram_size / MiB) - 256);
> > +
> > +    return emap;
> > +}
> > +
> > +static struct system_loongson *init_system_loongson(void *g_system)
> > +{
> > +    struct system_loongson *s = g_system;
> > +
> > +    stl_le_p(&s->ccnuma_smp, 0);
> > +    stl_le_p(&s->sing_double_channel, 1);
> > +    stl_le_p(&s->nr_uarts, 1);
> > +    stl_le_p(&s->uarts[0].iotype, 2);
> > +    stl_le_p(&s->uarts[0].int_offset, 2);
> > +    stl_le_p(&s->uarts[0].uartclk, 25000000); /* Random value */
> > +    stq_le_p(&s->uarts[0].uart_base, virt_memmap[VIRT_UART].base);
> > +
> > +    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;
> > +
> > +    stl_le_p(&irq_info->node_id, 0);
> > +    stl_le_p(&irq_info->PIC_type, 0);
> > +    stw_le_p(&irq_info->dma_mask_bits, 64);
> > +    stq_le_p(&irq_info->pci_mem_start_addr, virt_memmap[VIRT_PCIE_MMIO].base);
> > +    stq_le_p(&irq_info->pci_mem_end_addr, virt_memmap[VIRT_PCIE_MMIO].base +
> > +                                          virt_memmap[VIRT_PCIE_MMIO].size - 1);
> > +    stq_le_p(&irq_info->pci_io_start_addr, virt_memmap[VIRT_PCIE_PIO].base);
> > +
> > +    return irq_info;
> > +}
> > +
> > +static struct interface_info *init_interface_info(void *g_interface)
> > +{
> > +    struct interface_info *interface = g_interface;
> > +
> > +    stw_le_p(&interface->vers, 0x01);
> > +    strpadcpy(interface->description, 64, "UEFI_Version_v1.0", '\0');
> > +
> > +    return interface;
> > +}
> > +
> > +static struct board_devices *board_devices_info(void *g_board)
> > +{
> > +    struct board_devices *bd = g_board;
> > +
> > +    strpadcpy(bd->name, 64, "Loongson-3A-VIRT-1w-V1.00-demo", '\0');
> > +
> > +    return bd;
> > +}
> > +
> > +static struct loongson_special_attribute *init_special_info(void *g_special)
> > +{
> > +    struct loongson_special_attribute *special = g_special;
> > +
> > +    strpadcpy(special->special_name, 64, "2018-04-01", '\0');
> > +
> > +    return special;
> > +}
> > +
> > +void init_loongson_params(struct loongson_params *lp, void *p,
> > +                          uint64_t cpu_freq, uint64_t ram_size)
> > +{
> > +    stq_le_p(&lp->cpu_offset,
> > +              (uintptr_t)init_cpu_info(p, cpu_freq) - (uintptr_t)lp);
> > +    p += ROUND_UP(sizeof(struct efi_cpuinfo_loongson), 64);
> > +
> > +    stq_le_p(&lp->memory_offset,
> > +              (uintptr_t)init_memory_map(p, ram_size) - (uintptr_t)lp);
> > +    p += ROUND_UP(sizeof(struct efi_memory_map_loongson), 64);
> > +
> > +    stq_le_p(&lp->system_offset,
> > +              (uintptr_t)init_system_loongson(p) - (uintptr_t)lp);
> > +    p += ROUND_UP(sizeof(struct system_loongson), 64);
> > +
> > +    stq_le_p(&lp->irq_offset,
> > +              (uintptr_t)init_irq_source(p) - (uintptr_t)lp);
> > +    p += ROUND_UP(sizeof(struct irq_source_routing_table), 64);
> > +
> > +    stq_le_p(&lp->interface_offset,
> > +              (uintptr_t)init_interface_info(p) - (uintptr_t)lp);
> > +    p += ROUND_UP(sizeof(struct interface_info), 64);
> > +
> > +    stq_le_p(&lp->boarddev_table_offset,
> > +              (uintptr_t)board_devices_info(p) - (uintptr_t)lp);
> > +    p += ROUND_UP(sizeof(struct board_devices), 64);
> > +
> > +    stq_le_p(&lp->special_offset,
> > +              (uintptr_t)init_special_info(p) - (uintptr_t)lp);
> > +    p += ROUND_UP(sizeof(struct loongson_special_attribute), 64);
> > +}
> > +
> > +void init_reset_system(struct efi_reset_system_t *reset)
> > +{
> > +    stq_le_p(&reset->Shutdown, 0xffffffffbfc000a8);
> > +    stq_le_p(&reset->ResetCold, 0xffffffffbfc00080);
> > +    stq_le_p(&reset->ResetWarm, 0xffffffffbfc00080);
> > +}
> > diff --git a/hw/mips/loongson3_bootp.h b/hw/mips/loongson3_bootp.h
> > new file mode 100644
> > index 0000000..bf4fd8c
> > --- /dev/null
> > +++ b/hw/mips/loongson3_bootp.h
> > @@ -0,0 +1,241 @@
> > +/*
> > + * LEFI (a UEFI-like interface for BIOS-Kernel boot parameters) data structrues
> > + * defined at arch/mips/include/asm/mach-loongson64/boot_param.h in Linux kernel
> > + *
> > + * Copyright (c) 2017-2020 Huacai Chen (chenhc@lemote.com)
> > + * Copyright (c) 2017-2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
> > + *
> > + * This program is free software: you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License as published by
> > + * the Free Software Foundation, either version 2 of the License, or
> > + * (at your option) any later version.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > + * GNU General Public License for more details.
> > + *
> > + * You should have received a copy of the GNU General Public License
> > + * along with this program. If not, see <https://www.gnu.org/licenses/>.
> > + */
> > +
> > +#ifndef HW_MIPS_LOONGSON3_BOOTP_H
> > +#define HW_MIPS_LOONGSON3_BOOTP_H
> > +
> > +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];
> > +} QEMU_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];
> > +} QEMU_PACKED;
> > +
> > +#define MAX_UARTS 64
> > +struct uart_device {
> > +    uint32_t iotype;
> > +    uint32_t uartclk;
> > +    uint32_t int_offset;
> > +    uint64_t uart_base;
> > +} QEMU_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; /* step speed or constant speed */
> > +    uint32_t fan_percent;/* only for constant speed policy */
> > +    uint64_t base_addr;  /* base address of device registers */
> > +} QEMU_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;
> > +    uint64_t of_dtb_addr; /* NULL if not support */
> > +} QEMU_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;
> > +} QEMU_PACKED;
> > +
> > +struct interface_info {
> > +    uint16_t vers;               /* version of the specificition */
> > +    uint16_t size;
> > +    uint8_t  flag;
> > +    char description[64];
> > +} QEMU_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;
> > +};
> > +
> > +/* Overall MMIO & Memory layout */
> > +enum {
> > +    VIRT_LOWMEM,
> > +    VIRT_PM,
> > +    VIRT_FW_CFG,
> > +    VIRT_RTC,
> > +    VIRT_PCIE_PIO,
> > +    VIRT_PCIE_ECAM,
> > +    VIRT_BIOS_ROM,
> > +    VIRT_UART,
> > +    VIRT_LIOINTC,
> > +    VIRT_PCIE_MMIO,
> > +    VIRT_HIGHMEM
> > +};
> > +
> > +/* Low MEM layout for QEMU kernel loader */
> > +enum {
> > +    LOADER_KERNEL,
> > +    LOADER_INITRD,
> > +    LOADER_CMDLINE
> > +};
> > +
> > +/* BIOS ROM layout for QEMU kernel loader */
> > +enum {
> > +    LOADER_BOOTROM,
> > +    LOADER_PARAM,
> > +};
> > +
> > +struct MemmapEntry {
> > +    hwaddr base;
> > +    hwaddr size;
> > +};
> > +
> > +extern const struct MemmapEntry virt_memmap[];
> > +void init_loongson_params(struct loongson_params *lp, void *p,
> > +                          uint64_t cpu_freq, uint64_t ram_size);
> > +void init_reset_system(struct efi_reset_system_t *reset);
> > +
> > +#endif
> > diff --git a/hw/mips/meson.build b/hw/mips/meson.build
> > index 0e9f930..9e58c2b 100644
> > --- a/hw/mips/meson.build
> > +++ b/hw/mips/meson.build
> > @@ -1,6 +1,7 @@
> >  mips_ss = ss.source_set()
> >  mips_ss.add(files('addr.c', 'mips_int.c', 'fw_cfg.c'))
> >  mips_ss.add(when: 'CONFIG_FULOONG', if_true: files('fuloong2e.c'))
> > +mips_ss.add(when: 'CONFIG_LOONGSON3V', if_true: files('loongson3_bootp.c'))
> >  mips_ss.add(when: 'CONFIG_JAZZ', if_true: files('jazz.c'))
> >  mips_ss.add(when: 'CONFIG_MALTA', if_true: files('gt64xxx_pci.c', 'malta.c'))
> >  mips_ss.add(when: 'CONFIG_MIPSSIM', if_true: files('mipssim.c'))
> >


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

* Re: [PATCH V17 2/6] hw/intc: Rework Loongson LIOINTC
  2020-11-30 10:08       ` Philippe Mathieu-Daudé
@ 2020-12-02  1:16         ` Huacai Chen
  0 siblings, 0 replies; 31+ messages in thread
From: Huacai Chen @ 2020-12-02  1:16 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Huacai Chen, Aleksandar Rikalo, QEMU Developers, Aurelien Jarno,
	Aleksandar Markovic

Hi, Phillippe,

On Mon, Nov 30, 2020 at 6:08 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>
> On 11/28/20 7:19 AM, Huacai Chen wrote:
> > On Tue, Nov 24, 2020 at 4:52 AM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
> >> On 11/6/20 5:21 AM, Huacai Chen wrote:
> >>> As suggested by Philippe Mathieu-Daudé, rework Loongson's liointc:
> >>> 1, Move macro definitions to loongson_liointc.h;
> >>> 2, Remove magic values and use macros instead;
> >>> 3, Replace dead D() code by trace events.
> >>>
> >>> Suggested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> >>> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> >>> ---
> >>>  hw/intc/loongson_liointc.c         | 49 +++++++++++---------------------------
> >>>  include/hw/intc/loongson_liointc.h | 39 ++++++++++++++++++++++++++++++
> >>>  2 files changed, 53 insertions(+), 35 deletions(-)
> >>>  create mode 100644 include/hw/intc/loongson_liointc.h
> >>>
> >>> diff --git a/hw/intc/loongson_liointc.c b/hw/intc/loongson_liointc.c
> >>> index fbbfb57..be29e2f 100644
> >>> --- a/hw/intc/loongson_liointc.c
> >>> +++ b/hw/intc/loongson_liointc.c
> >>> @@ -1,6 +1,7 @@
> >>>  /*
> >>>   * QEMU Loongson Local I/O interrupt controler.
> >>>   *
> >>> + * Copyright (c) 2020 Huacai Chen <chenhc@lemote.com>
> >>>   * Copyright (c) 2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
> >>>   *
> >>>   * This program is free software: you can redistribute it and/or modify
> >>> @@ -19,33 +20,11 @@
> >>>   */
> >>>
> >>>  #include "qemu/osdep.h"
> >>> -#include "hw/sysbus.h"
> >>>  #include "qemu/module.h"
> >>> +#include "qemu/log.h"
> >>>  #include "hw/irq.h"
> >>>  #include "hw/qdev-properties.h"
> >>> -#include "qom/object.h"
> >>> -
> >>> -#define D(x)
> >>> -
> >>> -#define NUM_IRQS                32
> >>> -
> >>> -#define NUM_CORES               4
> >>> -#define NUM_IPS                 4
> >>> -#define NUM_PARENTS             (NUM_CORES * NUM_IPS)
> >>> -#define PARENT_COREx_IPy(x, y)  (NUM_IPS * x + y)
> >>> -
> >>> -#define R_MAPPER_START          0x0
> >>> -#define R_MAPPER_END            0x20
> >>> -#define R_ISR                   R_MAPPER_END
> >>> -#define R_IEN                   0x24
> >>> -#define R_IEN_SET               0x28
> >>> -#define R_IEN_CLR               0x2c
> >>> -#define R_PERCORE_ISR(x)        (0x40 + 0x8 * x)
> >>> -#define R_END                   0x64
> >>> -
> >>> -#define TYPE_LOONGSON_LIOINTC "loongson.liointc"
> >>> -DECLARE_INSTANCE_CHECKER(struct loongson_liointc, LOONGSON_LIOINTC,
> >>> -                         TYPE_LOONGSON_LIOINTC)
> >>> +#include "hw/intc/loongson_liointc.h"
> >>>
> >>>  struct loongson_liointc {
> >>>      SysBusDevice parent_obj;
> >>> @@ -123,14 +102,13 @@ liointc_read(void *opaque, hwaddr addr, unsigned int size)
> >>>          goto out;
> >>>      }
> >>>
> >>> -    /* Rest is 4 byte */
> >>> +    /* Rest are 4 bytes */
> >>>      if (size != 4 || (addr % 4)) {
> >>>          goto out;
> >>>      }
> >>>
> >>> -    if (addr >= R_PERCORE_ISR(0) &&
> >>> -        addr < R_PERCORE_ISR(NUM_CORES)) {
> >>> -        int core = (addr - R_PERCORE_ISR(0)) / 8;
> >>> +    if (addr >= R_START && addr < R_END) {
> >>> +        int core = (addr - R_START) / R_ISR_SIZE;
> >>>          r = p->per_core_isr[core];
> >>>          goto out;
> >>>      }
> >>> @@ -147,7 +125,8 @@ liointc_read(void *opaque, hwaddr addr, unsigned int size)
> >>>      }
> >>>
> >>>  out:
> >>> -    D(qemu_log("%s: size=%d addr=%lx val=%x\n", __func__, size, addr, r));
> >>> +    qemu_log_mask(CPU_LOG_INT, "%s: size=%d addr=%lx val=%x\n",
> >>> +                  __func__, size, addr, r);
> >>>      return r;
> >>>  }
> >>>
> >>> @@ -158,7 +137,8 @@ liointc_write(void *opaque, hwaddr addr,
> >>>      struct loongson_liointc *p = opaque;
> >>>      uint32_t value = val64;
> >>>
> >>> -    D(qemu_log("%s: size=%d, addr=%lx val=%x\n", __func__, size, addr, value));
> >>> +    qemu_log_mask(CPU_LOG_INT, "%s: size=%d, addr=%lx val=%x\n",
> >>> +                  __func__, size, addr, value);
> >>>
> >>>      /* Mapper is 1 byte */
> >>>      if (size == 1 && addr < R_MAPPER_END) {
> >>> @@ -166,14 +146,13 @@ liointc_write(void *opaque, hwaddr addr,
> >>>          goto out;
> >>>      }
> >>>
> >>> -    /* Rest is 4 byte */
> >>> +    /* Rest are 4 bytes */
> >>>      if (size != 4 || (addr % 4)) {
> >>>          goto out;
> >>>      }
> >>>
> >>> -    if (addr >= R_PERCORE_ISR(0) &&
> >>> -        addr < R_PERCORE_ISR(NUM_CORES)) {
> >>> -        int core = (addr - R_PERCORE_ISR(0)) / 8;
> >>> +    if (addr >= R_START && addr < R_END) {
> >>> +        int core = (addr - R_START) / R_ISR_SIZE;
> >>>          p->per_core_isr[core] = value;
> >>>          goto out;
> >>>      }
> >>> @@ -224,7 +203,7 @@ static void loongson_liointc_init(Object *obj)
> >>>      }
> >>>
> >>>      memory_region_init_io(&p->mmio, obj, &pic_ops, p,
> >>> -                         "loongson.liointc", R_END);
> >>> +                         TYPE_LOONGSON_LIOINTC, R_END);
> >>>      sysbus_init_mmio(SYS_BUS_DEVICE(obj), &p->mmio);
> >>>  }
> >>>
> >>> diff --git a/include/hw/intc/loongson_liointc.h b/include/hw/intc/loongson_liointc.h
> >>> new file mode 100644
> >>> index 0000000..e11f482
> >>> --- /dev/null
> >>> +++ b/include/hw/intc/loongson_liointc.h
> >>> @@ -0,0 +1,39 @@
> >>> +/*
> >>> + * This file is subject to the terms and conditions of the GNU General Public
> >>> + * License.  See the file "COPYING" in the main directory of this archive
> >>> + * for more details.
> >>> + *
> >>> + * Copyright (c) 2020 Huacai Chen <chenhc@lemote.com>
> >>> + * Copyright (c) 2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
> >>> + *
> >>> + */
> >>> +
> >>> +#ifndef LOONSGON_LIOINTC_H
> >>> +#define LOONGSON_LIOINTC_H
> >>> +
> >>> +#include "qemu/units.h"
> >>> +#include "hw/sysbus.h"
> >>> +#include "qom/object.h"
> >>> +
> >>> +#define NUM_IRQS                32
> >>> +
> >>> +#define NUM_CORES               4
> >>> +#define NUM_IPS                 4
> >>> +#define NUM_PARENTS             (NUM_CORES * NUM_IPS)
> >>> +#define PARENT_COREx_IPy(x, y)  (NUM_IPS * x + y)
> >>> +
> >>> +#define R_MAPPER_START          0x0
> >>> +#define R_MAPPER_END            0x20
> >>> +#define R_ISR                   R_MAPPER_END
> >>> +#define R_IEN                   0x24
> >>> +#define R_IEN_SET               0x28
> >>> +#define R_IEN_CLR               0x2c
> >>> +#define R_ISR_SIZE              0x8
> >>> +#define R_START                 0x40
> >>> +#define R_END                   0x64
> >>
> >> Can we keep the R_* definitions local in the .c?
> >> (if you agree I can amend that when applying).
> > If put them in .c, then .h is to small..,
>
> Not a problem:
>
> include/hw/ppc/openpic_kvm.h
> include/hw/display/ramfb.h
> include/hw/input/lasips2.h
> include/hw/usb/chipidea.h
> include/hw/s390x/ap-bridge.h
> include/hw/char/lm32_juart.h
> include/hw/isa/vt82c686.h
> include/hw/net/lan9118.h
> include/hw/intc/imx_gpcv2.h
> include/hw/usb/xhci.h
OK, I will put all these macros in .c file.

Huacai
>
> > but TYPE_LOONGSON_LIOINTC
> > should be defined in .h since it will be used in other place.
> >
> > Huacai
> >>
> >> Thanks for cleaning!
> >>
> >> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> >>
> >>> +
> >>> +#define TYPE_LOONGSON_LIOINTC "loongson.liointc"
> >>> +DECLARE_INSTANCE_CHECKER(struct loongson_liointc, LOONGSON_LIOINTC,
> >>> +                         TYPE_LOONGSON_LIOINTC)
> >>> +
> >>> +#endif /* LOONGSON_LIOINTC_H */
> >>>
> >


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

* Re: [PATCH V17 4/6] hw/mips: Add Loongson-3 boot parameter helpers
  2020-12-02  1:14     ` Huacai Chen
@ 2020-12-02  9:32       ` Philippe Mathieu-Daudé
  2020-12-11  2:46         ` Huacai Chen
  0 siblings, 1 reply; 31+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-12-02  9:32 UTC (permalink / raw)
  To: Huacai Chen, Jiaxun Yang, Richard Henderson, Peter Maydell
  Cc: Huacai Chen, Aleksandar Rikalo, QEMU Developers, Aurelien Jarno,
	Aleksandar Markovic

On 12/2/20 2:14 AM, Huacai Chen wrote:
> Hi, Phillippe,
> 
> On Tue, Nov 24, 2020 at 6:25 AM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>>
>> On 11/6/20 5:21 AM, Huacai Chen wrote:
>>> Preparing to add Loongson-3 machine support, add Loongson-3's LEFI (a
>>> UEFI-like interface for BIOS-Kernel boot parameters) helpers first.
>>>
>>> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
>>> Signed-off-by: Huacai Chen <chenhc@lemote.com>
>>> Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
>>> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
>>> ---
>>>  hw/mips/loongson3_bootp.c | 165 +++++++++++++++++++++++++++++++
>>>  hw/mips/loongson3_bootp.h | 241 ++++++++++++++++++++++++++++++++++++++++++++++
>>>  hw/mips/meson.build       |   1 +
>>>  3 files changed, 407 insertions(+)
>>>  create mode 100644 hw/mips/loongson3_bootp.c
>>>  create mode 100644 hw/mips/loongson3_bootp.h
>>>
>>> diff --git a/hw/mips/loongson3_bootp.c b/hw/mips/loongson3_bootp.c
>>> new file mode 100644
>>> index 0000000..3a16081
>>> --- /dev/null
>>> +++ b/hw/mips/loongson3_bootp.c
>>> @@ -0,0 +1,165 @@
>>> +/*
>>> + * LEFI (a UEFI-like interface for BIOS-Kernel boot parameters) helpers
>>> + *
>>> + * Copyright (c) 2018-2020 Huacai Chen (chenhc@lemote.com)
>>> + * Copyright (c) 2018-2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
>>> + *
>>> + * This program is free software: you can redistribute it and/or modify
>>> + * it under the terms of the GNU General Public License as published by
>>> + * the Free Software Foundation, either version 2 of the License, or
>>> + * (at your option) any later version.
>>> + *
>>> + * This program is distributed in the hope that it will be useful,
>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>>> + * GNU General Public License for more details.
>>> + *
>>> + * You should have received a copy of the GNU General Public License
>>> + * along with this program. If not, see <https://www.gnu.org/licenses/>.
>>> + */
>>> +
>>> +#include "qemu/osdep.h"
>>> +#include "qemu/units.h"
>>> +#include "qemu/cutils.h"
>>> +#include "cpu.h"
>>> +#include "hw/boards.h"
>>> +#include "hw/mips/loongson3_bootp.h"
>>> +
>>> +#define LOONGSON3_CORE_PER_NODE 4
>>> +
>>> +static struct efi_cpuinfo_loongson *init_cpu_info(void *g_cpuinfo, uint64_t cpu_freq)
>>> +{
>>> +    struct efi_cpuinfo_loongson *c = g_cpuinfo;
>>> +
>>> +    stl_le_p(&c->cputype, Loongson_3A);
>>> +    stl_le_p(&c->processor_id, MIPS_CPU(first_cpu)->env.CP0_PRid);
>>
>> Build failing with Clang:
>>
>> FAILED: libqemu-mips64el-softmmu.fa.p/hw_mips_loongson3_bootp.c.o
>> hw/mips/loongson3_bootp.c:35:15: error: taking address of packed member
>> 'processor_id' of class or structure 'efi_cpuinfo_loongson' may result
>> in an unaligned pointer value [-Werror,-Waddress-of-packed-member]
>>     stl_le_p(&c->processor_id, MIPS_CPU(first_cpu)->env.CP0_PRid);
>>               ^~~~~~~~~~~~~~~
>> 1 error generated.
> We cannot reproduce it on X86/MIPS with clang...

You can reproduce running the Clang job on Gitlab-CI:

https://wiki.qemu.org/Testing/CI/GitLabCI

> And I found that
> stl_le_p() will be __builtin_memcpy(), I don't think memcpy() will
> cause unaligned access. So, any suggestions?

I'll defer this question to Richard/Peter who have deeper understanding.

> 
> Huacai


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

* Re: [PATCH V17 4/6] hw/mips: Add Loongson-3 boot parameter helpers
  2020-12-02  9:32       ` Philippe Mathieu-Daudé
@ 2020-12-11  2:46         ` Huacai Chen
  2020-12-11 11:32           ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 31+ messages in thread
From: Huacai Chen @ 2020-12-11  2:46 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Peter Maydell, Aleksandar Rikalo, Huacai Chen, Richard Henderson,
	QEMU Developers, Aleksandar Markovic, Aurelien Jarno

Hi, Rechard and Peter,

On Wed, Dec 2, 2020 at 5:32 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>
> On 12/2/20 2:14 AM, Huacai Chen wrote:
> > Hi, Phillippe,
> >
> > On Tue, Nov 24, 2020 at 6:25 AM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
> >>
> >> On 11/6/20 5:21 AM, Huacai Chen wrote:
> >>> Preparing to add Loongson-3 machine support, add Loongson-3's LEFI (a
> >>> UEFI-like interface for BIOS-Kernel boot parameters) helpers first.
> >>>
> >>> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> >>> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> >>> Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> >>> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> >>> ---
> >>>  hw/mips/loongson3_bootp.c | 165 +++++++++++++++++++++++++++++++
> >>>  hw/mips/loongson3_bootp.h | 241 ++++++++++++++++++++++++++++++++++++++++++++++
> >>>  hw/mips/meson.build       |   1 +
> >>>  3 files changed, 407 insertions(+)
> >>>  create mode 100644 hw/mips/loongson3_bootp.c
> >>>  create mode 100644 hw/mips/loongson3_bootp.h
> >>>
> >>> diff --git a/hw/mips/loongson3_bootp.c b/hw/mips/loongson3_bootp.c
> >>> new file mode 100644
> >>> index 0000000..3a16081
> >>> --- /dev/null
> >>> +++ b/hw/mips/loongson3_bootp.c
> >>> @@ -0,0 +1,165 @@
> >>> +/*
> >>> + * LEFI (a UEFI-like interface for BIOS-Kernel boot parameters) helpers
> >>> + *
> >>> + * Copyright (c) 2018-2020 Huacai Chen (chenhc@lemote.com)
> >>> + * Copyright (c) 2018-2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
> >>> + *
> >>> + * This program is free software: you can redistribute it and/or modify
> >>> + * it under the terms of the GNU General Public License as published by
> >>> + * the Free Software Foundation, either version 2 of the License, or
> >>> + * (at your option) any later version.
> >>> + *
> >>> + * This program is distributed in the hope that it will be useful,
> >>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> >>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> >>> + * GNU General Public License for more details.
> >>> + *
> >>> + * You should have received a copy of the GNU General Public License
> >>> + * along with this program. If not, see <https://www.gnu.org/licenses/>.
> >>> + */
> >>> +
> >>> +#include "qemu/osdep.h"
> >>> +#include "qemu/units.h"
> >>> +#include "qemu/cutils.h"
> >>> +#include "cpu.h"
> >>> +#include "hw/boards.h"
> >>> +#include "hw/mips/loongson3_bootp.h"
> >>> +
> >>> +#define LOONGSON3_CORE_PER_NODE 4
> >>> +
> >>> +static struct efi_cpuinfo_loongson *init_cpu_info(void *g_cpuinfo, uint64_t cpu_freq)
> >>> +{
> >>> +    struct efi_cpuinfo_loongson *c = g_cpuinfo;
> >>> +
> >>> +    stl_le_p(&c->cputype, Loongson_3A);
> >>> +    stl_le_p(&c->processor_id, MIPS_CPU(first_cpu)->env.CP0_PRid);
> >>
> >> Build failing with Clang:
> >>
> >> FAILED: libqemu-mips64el-softmmu.fa.p/hw_mips_loongson3_bootp.c.o
> >> hw/mips/loongson3_bootp.c:35:15: error: taking address of packed member
> >> 'processor_id' of class or structure 'efi_cpuinfo_loongson' may result
> >> in an unaligned pointer value [-Werror,-Waddress-of-packed-member]
> >>     stl_le_p(&c->processor_id, MIPS_CPU(first_cpu)->env.CP0_PRid);
> >>               ^~~~~~~~~~~~~~~
> >> 1 error generated.
> > We cannot reproduce it on X86/MIPS with clang...
>
> You can reproduce running the Clang job on Gitlab-CI:
>
> https://wiki.qemu.org/Testing/CI/GitLabCI
>
> > And I found that
> > stl_le_p() will be __builtin_memcpy(), I don't think memcpy() will
> > cause unaligned access. So, any suggestions?
>
> I'll defer this question to Richard/Peter who have deeper understanding.
Any sugguestions? Other patches are updated, except this one.

Huacai
>
> >
> > Huacai


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

* Re: [PATCH V17 4/6] hw/mips: Add Loongson-3 boot parameter helpers
  2020-12-11  2:46         ` Huacai Chen
@ 2020-12-11 11:32           ` Philippe Mathieu-Daudé
  2020-12-13 22:17             ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 31+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-12-11 11:32 UTC (permalink / raw)
  To: Huacai Chen, Eric Blake, Richard Henderson, Marc-André Lureau
  Cc: Peter Maydell, Aleksandar Rikalo, Huacai Chen, David Hildenbrand,
	QEMU Developers, Aleksandar Markovic, Alex Bennée,
	Aurelien Jarno

On 12/11/20 3:46 AM, Huacai Chen wrote:
> Hi, Rechard and Peter,
> 
> On Wed, Dec 2, 2020 at 5:32 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>>
>> On 12/2/20 2:14 AM, Huacai Chen wrote:
>>> Hi, Phillippe,
>>>
>>> On Tue, Nov 24, 2020 at 6:25 AM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>>>>
>>>> On 11/6/20 5:21 AM, Huacai Chen wrote:
>>>>> Preparing to add Loongson-3 machine support, add Loongson-3's LEFI (a
>>>>> UEFI-like interface for BIOS-Kernel boot parameters) helpers first.
>>>>>
>>>>> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
>>>>> Signed-off-by: Huacai Chen <chenhc@lemote.com>
>>>>> Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
>>>>> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
>>>>> ---
>>>>>  hw/mips/loongson3_bootp.c | 165 +++++++++++++++++++++++++++++++
>>>>>  hw/mips/loongson3_bootp.h | 241 ++++++++++++++++++++++++++++++++++++++++++++++
>>>>>  hw/mips/meson.build       |   1 +
>>>>>  3 files changed, 407 insertions(+)
>>>>>  create mode 100644 hw/mips/loongson3_bootp.c
>>>>>  create mode 100644 hw/mips/loongson3_bootp.h
>>>>>
>>>>> diff --git a/hw/mips/loongson3_bootp.c b/hw/mips/loongson3_bootp.c
>>>>> new file mode 100644
>>>>> index 0000000..3a16081
>>>>> --- /dev/null
>>>>> +++ b/hw/mips/loongson3_bootp.c
>>>>> @@ -0,0 +1,165 @@
>>>>> +/*
>>>>> + * LEFI (a UEFI-like interface for BIOS-Kernel boot parameters) helpers
>>>>> + *
>>>>> + * Copyright (c) 2018-2020 Huacai Chen (chenhc@lemote.com)
>>>>> + * Copyright (c) 2018-2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
>>>>> + *
>>>>> + * This program is free software: you can redistribute it and/or modify
>>>>> + * it under the terms of the GNU General Public License as published by
>>>>> + * the Free Software Foundation, either version 2 of the License, or
>>>>> + * (at your option) any later version.
>>>>> + *
>>>>> + * This program is distributed in the hope that it will be useful,
>>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>>>>> + * GNU General Public License for more details.
>>>>> + *
>>>>> + * You should have received a copy of the GNU General Public License
>>>>> + * along with this program. If not, see <https://www.gnu.org/licenses/>.
>>>>> + */
>>>>> +
>>>>> +#include "qemu/osdep.h"
>>>>> +#include "qemu/units.h"
>>>>> +#include "qemu/cutils.h"
>>>>> +#include "cpu.h"
>>>>> +#include "hw/boards.h"
>>>>> +#include "hw/mips/loongson3_bootp.h"
>>>>> +
>>>>> +#define LOONGSON3_CORE_PER_NODE 4
>>>>> +
>>>>> +static struct efi_cpuinfo_loongson *init_cpu_info(void *g_cpuinfo, uint64_t cpu_freq)
>>>>> +{
>>>>> +    struct efi_cpuinfo_loongson *c = g_cpuinfo;
>>>>> +
>>>>> +    stl_le_p(&c->cputype, Loongson_3A);
>>>>> +    stl_le_p(&c->processor_id, MIPS_CPU(first_cpu)->env.CP0_PRid);
>>>>
>>>> Build failing with Clang:
>>>>
>>>> FAILED: libqemu-mips64el-softmmu.fa.p/hw_mips_loongson3_bootp.c.o
>>>> hw/mips/loongson3_bootp.c:35:15: error: taking address of packed member
>>>> 'processor_id' of class or structure 'efi_cpuinfo_loongson' may result
>>>> in an unaligned pointer value [-Werror,-Waddress-of-packed-member]
>>>>     stl_le_p(&c->processor_id, MIPS_CPU(first_cpu)->env.CP0_PRid);
>>>>               ^~~~~~~~~~~~~~~
>>>> 1 error generated.
>>> We cannot reproduce it on X86/MIPS with clang...
>>
>> You can reproduce running the Clang job on Gitlab-CI:
>>
>> https://wiki.qemu.org/Testing/CI/GitLabCI
>>
>>> And I found that
>>> stl_le_p() will be __builtin_memcpy(), I don't think memcpy() will
>>> cause unaligned access. So, any suggestions?

My understanding is the compiler is complaining for the argument
passed to the caller, with no knowledge of the callee implementation.

Which makes me wonder if these functions are really inlined...

Do we need to use QEMU_ALWAYS_INLINE for these LDST helpers?

I see Richard used it in commit 80d9d1c6785 ("cputlb: Split out
load/store_memop").

>>
>> I'll defer this question to Richard/Peter who have deeper understanding.
> Any sugguestions? Other patches are updated, except this one.

Searching on the list, I see Marc-André resolved that by
using a copy on the stack:
https://www.mail-archive.com/qemu-devel@nongnu.org/msg614482.html

> 
> Huacai
>>
>>>
>>> Huacai
> 


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

* Re: [PATCH V17 4/6] hw/mips: Add Loongson-3 boot parameter helpers
  2020-12-11 11:32           ` Philippe Mathieu-Daudé
@ 2020-12-13 22:17             ` Philippe Mathieu-Daudé
  2020-12-13 23:09               ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 31+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-12-13 22:17 UTC (permalink / raw)
  To: Huacai Chen, Eric Blake, Richard Henderson, Marc-André Lureau
  Cc: Peter Maydell, Aleksandar Rikalo, David Hildenbrand,
	QEMU Developers, Aleksandar Markovic, Huacai Chen,
	Alex Bennée, Aurelien Jarno

On 12/11/20 12:32 PM, Philippe Mathieu-Daudé wrote:
> On 12/11/20 3:46 AM, Huacai Chen wrote:
>> Hi, Rechard and Peter,
>>
>> On Wed, Dec 2, 2020 at 5:32 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>>>
>>> On 12/2/20 2:14 AM, Huacai Chen wrote:
>>>> Hi, Phillippe,
>>>>
>>>> On Tue, Nov 24, 2020 at 6:25 AM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>>>>>
>>>>> On 11/6/20 5:21 AM, Huacai Chen wrote:
>>>>>> Preparing to add Loongson-3 machine support, add Loongson-3's LEFI (a
>>>>>> UEFI-like interface for BIOS-Kernel boot parameters) helpers first.
>>>>>>
>>>>>> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
>>>>>> Signed-off-by: Huacai Chen <chenhc@lemote.com>
>>>>>> Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
>>>>>> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
>>>>>> ---
>>>>>>  hw/mips/loongson3_bootp.c | 165 +++++++++++++++++++++++++++++++
>>>>>>  hw/mips/loongson3_bootp.h | 241 ++++++++++++++++++++++++++++++++++++++++++++++
>>>>>>  hw/mips/meson.build       |   1 +
>>>>>>  3 files changed, 407 insertions(+)
>>>>>>  create mode 100644 hw/mips/loongson3_bootp.c
>>>>>>  create mode 100644 hw/mips/loongson3_bootp.h
>>>>>>
>>>>>> diff --git a/hw/mips/loongson3_bootp.c b/hw/mips/loongson3_bootp.c
>>>>>> new file mode 100644
>>>>>> index 0000000..3a16081
>>>>>> --- /dev/null
>>>>>> +++ b/hw/mips/loongson3_bootp.c
>>>>>> @@ -0,0 +1,165 @@
>>>>>> +/*
>>>>>> + * LEFI (a UEFI-like interface for BIOS-Kernel boot parameters) helpers
>>>>>> + *
>>>>>> + * Copyright (c) 2018-2020 Huacai Chen (chenhc@lemote.com)
>>>>>> + * Copyright (c) 2018-2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
>>>>>> + *
>>>>>> + * This program is free software: you can redistribute it and/or modify
>>>>>> + * it under the terms of the GNU General Public License as published by
>>>>>> + * the Free Software Foundation, either version 2 of the License, or
>>>>>> + * (at your option) any later version.
>>>>>> + *
>>>>>> + * This program is distributed in the hope that it will be useful,
>>>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>>>>>> + * GNU General Public License for more details.
>>>>>> + *
>>>>>> + * You should have received a copy of the GNU General Public License
>>>>>> + * along with this program. If not, see <https://www.gnu.org/licenses/>.
>>>>>> + */
>>>>>> +
>>>>>> +#include "qemu/osdep.h"
>>>>>> +#include "qemu/units.h"
>>>>>> +#include "qemu/cutils.h"
>>>>>> +#include "cpu.h"
>>>>>> +#include "hw/boards.h"
>>>>>> +#include "hw/mips/loongson3_bootp.h"
>>>>>> +
>>>>>> +#define LOONGSON3_CORE_PER_NODE 4
>>>>>> +
>>>>>> +static struct efi_cpuinfo_loongson *init_cpu_info(void *g_cpuinfo, uint64_t cpu_freq)
>>>>>> +{
>>>>>> +    struct efi_cpuinfo_loongson *c = g_cpuinfo;
>>>>>> +
>>>>>> +    stl_le_p(&c->cputype, Loongson_3A);
>>>>>> +    stl_le_p(&c->processor_id, MIPS_CPU(first_cpu)->env.CP0_PRid);
>>>>>
>>>>> Build failing with Clang:
>>>>>
>>>>> FAILED: libqemu-mips64el-softmmu.fa.p/hw_mips_loongson3_bootp.c.o
>>>>> hw/mips/loongson3_bootp.c:35:15: error: taking address of packed member
>>>>> 'processor_id' of class or structure 'efi_cpuinfo_loongson' may result
>>>>> in an unaligned pointer value [-Werror,-Waddress-of-packed-member]
>>>>>     stl_le_p(&c->processor_id, MIPS_CPU(first_cpu)->env.CP0_PRid);
>>>>>               ^~~~~~~~~~~~~~~
>>>>> 1 error generated.
>>>> We cannot reproduce it on X86/MIPS with clang...
>>>
>>> You can reproduce running the Clang job on Gitlab-CI:
>>>
>>> https://wiki.qemu.org/Testing/CI/GitLabCI
>>>
>>>> And I found that
>>>> stl_le_p() will be __builtin_memcpy(), I don't think memcpy() will
>>>> cause unaligned access. So, any suggestions?
> 
> My understanding is the compiler is complaining for the argument
> passed to the caller, with no knowledge of the callee implementation.
> 
> Which makes me wonder if these functions are really inlined...
> 
> Do we need to use QEMU_ALWAYS_INLINE for these LDST helpers?

No, this doesn't work neither.

> 
> I see Richard used it in commit 80d9d1c6785 ("cputlb: Split out
> load/store_memop").
> 
>>>
>>> I'll defer this question to Richard/Peter who have deeper understanding.
>> Any sugguestions? Other patches are updated, except this one.
> 
> Searching on the list, I see Marc-André resolved that by
> using a copy on the stack:
> https://www.mail-archive.com/qemu-devel@nongnu.org/msg614482.html
> 
>>
>> Huacai
>>>
>>>>
>>>> Huacai
>>
> 


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

* Re: [PATCH V17 4/6] hw/mips: Add Loongson-3 boot parameter helpers
  2020-12-13 22:17             ` Philippe Mathieu-Daudé
@ 2020-12-13 23:09               ` Philippe Mathieu-Daudé
  2020-12-14  2:37                 ` Huacai Chen
  0 siblings, 1 reply; 31+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-12-13 23:09 UTC (permalink / raw)
  To: Huacai Chen, Eric Blake, Richard Henderson, Marc-André Lureau
  Cc: Huacai Chen, Aleksandar Rikalo, Peter Maydell, David Hildenbrand,
	QEMU Developers, Aleksandar Markovic, Alex Bennée,
	Aurelien Jarno

On 12/13/20 11:17 PM, Philippe Mathieu-Daudé wrote:
> On 12/11/20 12:32 PM, Philippe Mathieu-Daudé wrote:
>> On 12/11/20 3:46 AM, Huacai Chen wrote:
>>> Hi, Rechard and Peter,
>>>
>>> On Wed, Dec 2, 2020 at 5:32 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>>>>
>>>> On 12/2/20 2:14 AM, Huacai Chen wrote:
>>>>> Hi, Phillippe,
>>>>>
>>>>> On Tue, Nov 24, 2020 at 6:25 AM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>>>>>>
>>>>>> On 11/6/20 5:21 AM, Huacai Chen wrote:
>>>>>>> Preparing to add Loongson-3 machine support, add Loongson-3's LEFI (a
>>>>>>> UEFI-like interface for BIOS-Kernel boot parameters) helpers first.
>>>>>>>
>>>>>>> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
>>>>>>> Signed-off-by: Huacai Chen <chenhc@lemote.com>
>>>>>>> Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
>>>>>>> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
>>>>>>> ---
>>>>>>>  hw/mips/loongson3_bootp.c | 165 +++++++++++++++++++++++++++++++
>>>>>>>  hw/mips/loongson3_bootp.h | 241 ++++++++++++++++++++++++++++++++++++++++++++++
>>>>>>>  hw/mips/meson.build       |   1 +
>>>>>>>  3 files changed, 407 insertions(+)
>>>>>>>  create mode 100644 hw/mips/loongson3_bootp.c
>>>>>>>  create mode 100644 hw/mips/loongson3_bootp.h
>>>>>>>
>>>>>>> diff --git a/hw/mips/loongson3_bootp.c b/hw/mips/loongson3_bootp.c
>>>>>>> new file mode 100644
>>>>>>> index 0000000..3a16081
>>>>>>> --- /dev/null
>>>>>>> +++ b/hw/mips/loongson3_bootp.c
>>>>>>> @@ -0,0 +1,165 @@
>>>>>>> +/*
>>>>>>> + * LEFI (a UEFI-like interface for BIOS-Kernel boot parameters) helpers
>>>>>>> + *
>>>>>>> + * Copyright (c) 2018-2020 Huacai Chen (chenhc@lemote.com)
>>>>>>> + * Copyright (c) 2018-2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
>>>>>>> + *
>>>>>>> + * This program is free software: you can redistribute it and/or modify
>>>>>>> + * it under the terms of the GNU General Public License as published by
>>>>>>> + * the Free Software Foundation, either version 2 of the License, or
>>>>>>> + * (at your option) any later version.
>>>>>>> + *
>>>>>>> + * This program is distributed in the hope that it will be useful,
>>>>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>>>>>>> + * GNU General Public License for more details.
>>>>>>> + *
>>>>>>> + * You should have received a copy of the GNU General Public License
>>>>>>> + * along with this program. If not, see <https://www.gnu.org/licenses/>.
>>>>>>> + */
>>>>>>> +
>>>>>>> +#include "qemu/osdep.h"
>>>>>>> +#include "qemu/units.h"
>>>>>>> +#include "qemu/cutils.h"
>>>>>>> +#include "cpu.h"
>>>>>>> +#include "hw/boards.h"
>>>>>>> +#include "hw/mips/loongson3_bootp.h"
>>>>>>> +
>>>>>>> +#define LOONGSON3_CORE_PER_NODE 4
>>>>>>> +
>>>>>>> +static struct efi_cpuinfo_loongson *init_cpu_info(void *g_cpuinfo, uint64_t cpu_freq)
>>>>>>> +{
>>>>>>> +    struct efi_cpuinfo_loongson *c = g_cpuinfo;
>>>>>>> +
>>>>>>> +    stl_le_p(&c->cputype, Loongson_3A);
>>>>>>> +    stl_le_p(&c->processor_id, MIPS_CPU(first_cpu)->env.CP0_PRid);
>>>>>>
>>>>>> Build failing with Clang:
>>>>>>
>>>>>> FAILED: libqemu-mips64el-softmmu.fa.p/hw_mips_loongson3_bootp.c.o
>>>>>> hw/mips/loongson3_bootp.c:35:15: error: taking address of packed member
>>>>>> 'processor_id' of class or structure 'efi_cpuinfo_loongson' may result
>>>>>> in an unaligned pointer value [-Werror,-Waddress-of-packed-member]
>>>>>>     stl_le_p(&c->processor_id, MIPS_CPU(first_cpu)->env.CP0_PRid);
>>>>>>               ^~~~~~~~~~~~~~~
>>>>>> 1 error generated.
>>>>> We cannot reproduce it on X86/MIPS with clang...
>>>>
>>>> You can reproduce running the Clang job on Gitlab-CI:
>>>>
>>>> https://wiki.qemu.org/Testing/CI/GitLabCI
>>>>
>>>>> And I found that
>>>>> stl_le_p() will be __builtin_memcpy(), I don't think memcpy() will
>>>>> cause unaligned access. So, any suggestions?
>>
>> My understanding is the compiler is complaining for the argument
>> passed to the caller, with no knowledge of the callee implementation.
>>
>> Which makes me wonder if these functions are really inlined...
>>
>> Do we need to use QEMU_ALWAYS_INLINE for these LDST helpers?
> 
> No, this doesn't work neither.

Well, this works:

-- >8 --
@@ -32,7 +32,7 @@ static struct efi_cpuinfo_loongson *init_cpu_info(void
*g_cpuinfo, uint64_t cpu_
     struct efi_cpuinfo_loongson *c = g_cpuinfo;

     stl_le_p(&c->cputype, Loongson_3A);
-    stl_le_p(&c->processor_id, MIPS_CPU(first_cpu)->env.CP0_PRid);
+    c->processor_id = cpu_to_le32(MIPS_CPU(first_cpu)->env.CP0_PRid);
     if (cpu_freq > UINT_MAX) {
         stl_le_p(&c->cpu_clock_freq, UINT_MAX);
     } else {
---

> 
>>
>> I see Richard used it in commit 80d9d1c6785 ("cputlb: Split out
>> load/store_memop").
>>
>>>>
>>>> I'll defer this question to Richard/Peter who have deeper understanding.
>>> Any sugguestions? Other patches are updated, except this one.
>>
>> Searching on the list, I see Marc-André resolved that by
>> using a copy on the stack:
>> https://www.mail-archive.com/qemu-devel@nongnu.org/msg614482.html
>>
>>>
>>> Huacai
>>>>
>>>>>
>>>>> Huacai
>>>
>>
> 


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

* Re: [PATCH V17 4/6] hw/mips: Add Loongson-3 boot parameter helpers
  2020-11-06  4:21 ` [PATCH V17 4/6] hw/mips: Add Loongson-3 boot parameter helpers Huacai Chen
  2020-11-23 22:25   ` Philippe Mathieu-Daudé
@ 2020-12-13 23:24   ` Philippe Mathieu-Daudé
  1 sibling, 0 replies; 31+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-12-13 23:24 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Aleksandar Rikalo, Huacai Chen, qemu-devel, Aleksandar Markovic,
	Huacai Chen, Aurelien Jarno

On 11/6/20 5:21 AM, Huacai Chen wrote:
> Preparing to add Loongson-3 machine support, add Loongson-3's LEFI (a
> UEFI-like interface for BIOS-Kernel boot parameters) helpers first.
> 
> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> ---
>  hw/mips/loongson3_bootp.c | 165 +++++++++++++++++++++++++++++++
>  hw/mips/loongson3_bootp.h | 241 ++++++++++++++++++++++++++++++++++++++++++++++
>  hw/mips/meson.build       |   1 +
>  3 files changed, 407 insertions(+)
>  create mode 100644 hw/mips/loongson3_bootp.c
>  create mode 100644 hw/mips/loongson3_bootp.h
> 
> diff --git a/hw/mips/loongson3_bootp.c b/hw/mips/loongson3_bootp.c
> new file mode 100644
> index 0000000..3a16081
> --- /dev/null
> +++ b/hw/mips/loongson3_bootp.c
> @@ -0,0 +1,165 @@
> +/*
> + * LEFI (a UEFI-like interface for BIOS-Kernel boot parameters) helpers
> + *
> + * Copyright (c) 2018-2020 Huacai Chen (chenhc@lemote.com)
> + * Copyright (c) 2018-2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
> + *
> + * This program is free software: you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation, either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program. If not, see <https://www.gnu.org/licenses/>.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/units.h"
> +#include "qemu/cutils.h"
> +#include "cpu.h"
> +#include "hw/boards.h"
> +#include "hw/mips/loongson3_bootp.h"
> +
> +#define LOONGSON3_CORE_PER_NODE 4
> +
> +static struct efi_cpuinfo_loongson *init_cpu_info(void *g_cpuinfo, uint64_t cpu_freq)
> +{
> +    struct efi_cpuinfo_loongson *c = g_cpuinfo;
> +
> +    stl_le_p(&c->cputype, Loongson_3A);
> +    stl_le_p(&c->processor_id, MIPS_CPU(first_cpu)->env.CP0_PRid);
> +    if (cpu_freq > UINT_MAX) {
> +        stl_le_p(&c->cpu_clock_freq, UINT_MAX);
> +    } else {
> +        stl_le_p(&c->cpu_clock_freq, cpu_freq);
> +    }
> +
> +    stw_le_p(&c->cpu_startup_core_id, 0);
> +    stl_le_p(&c->nr_cpus, current_machine->smp.cpus);
> +    stl_le_p(&c->total_node, DIV_ROUND_UP(current_machine->smp.cpus,
> +                                          LOONGSON3_CORE_PER_NODE));
> +
> +    return c;
> +}
> +
> +static struct efi_memory_map_loongson *init_memory_map(void *g_map, uint64_t ram_size)
> +{
> +    struct efi_memory_map_loongson *emap = g_map;
> +
> +    stl_le_p(&emap->nr_map, 2);
> +    stl_le_p(&emap->mem_freq, 300000000);
> +
> +    stl_le_p(&emap->map[0].node_id, 0);
> +    stl_le_p(&emap->map[0].mem_type, 1);
> +    stq_le_p(&emap->map[0].mem_start, 0x0);
> +    stl_le_p(&emap->map[0].mem_size, 240);
> +
> +    stl_le_p(&emap->map[1].node_id, 0);
> +    stl_le_p(&emap->map[1].mem_type, 2);
> +    stq_le_p(&emap->map[1].mem_start, 0x90000000);
> +    stl_le_p(&emap->map[1].mem_size, (ram_size / MiB) - 256);
> +
> +    return emap;
> +}
> +
> +static struct system_loongson *init_system_loongson(void *g_system)
> +{
> +    struct system_loongson *s = g_system;
> +
> +    stl_le_p(&s->ccnuma_smp, 0);
> +    stl_le_p(&s->sing_double_channel, 1);
> +    stl_le_p(&s->nr_uarts, 1);
> +    stl_le_p(&s->uarts[0].iotype, 2);
> +    stl_le_p(&s->uarts[0].int_offset, 2);
> +    stl_le_p(&s->uarts[0].uartclk, 25000000); /* Random value */
> +    stq_le_p(&s->uarts[0].uart_base, virt_memmap[VIRT_UART].base);
> +
> +    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;
> +
> +    stl_le_p(&irq_info->node_id, 0);
> +    stl_le_p(&irq_info->PIC_type, 0);
> +    stw_le_p(&irq_info->dma_mask_bits, 64);
> +    stq_le_p(&irq_info->pci_mem_start_addr, virt_memmap[VIRT_PCIE_MMIO].base);
> +    stq_le_p(&irq_info->pci_mem_end_addr, virt_memmap[VIRT_PCIE_MMIO].base +
> +                                          virt_memmap[VIRT_PCIE_MMIO].size - 1);
> +    stq_le_p(&irq_info->pci_io_start_addr, virt_memmap[VIRT_PCIE_PIO].base);
> +
> +    return irq_info;
> +}
> +
> +static struct interface_info *init_interface_info(void *g_interface)
> +{
> +    struct interface_info *interface = g_interface;
> +
> +    stw_le_p(&interface->vers, 0x01);
> +    strpadcpy(interface->description, 64, "UEFI_Version_v1.0", '\0');
> +
> +    return interface;
> +}
> +
> +static struct board_devices *board_devices_info(void *g_board)
> +{
> +    struct board_devices *bd = g_board;
> +
> +    strpadcpy(bd->name, 64, "Loongson-3A-VIRT-1w-V1.00-demo", '\0');
> +
> +    return bd;
> +}
> +
> +static struct loongson_special_attribute *init_special_info(void *g_special)
> +{
> +    struct loongson_special_attribute *special = g_special;
> +
> +    strpadcpy(special->special_name, 64, "2018-04-01", '\0');
> +
> +    return special;
> +}
> +
> +void init_loongson_params(struct loongson_params *lp, void *p,
> +                          uint64_t cpu_freq, uint64_t ram_size)
> +{
> +    stq_le_p(&lp->cpu_offset,
> +              (uintptr_t)init_cpu_info(p, cpu_freq) - (uintptr_t)lp);

Since I've been trying to debug your patch, I stumbled around this
code. Why init_cpu_info() returns 'p'? To make code shorter here?
This makes it very hard to review. Don't we have this:

  cpu_offset = base_offset + sizeof(struct efi_cpuinfo_loongson);

> +    p += ROUND_UP(sizeof(struct efi_cpuinfo_loongson), 64);

What about this simpler (IMHO) code (untested):

  void init_loongson_params(void *p, size_t base_ofs,
                            uint64_t cpu_freq, uint64_t ram_size)
  {
      struct loongson_params *lp = (struct loongson_params *lp)
                                   ((char *)p + base_ofs);
      size_t sz;

      init_cpu_info(p, cpu_freq); // init_cpu_info() returns 'void'.
      sz = sizeof(struct efi_cpuinfo_loongson);
      lp->cpu_offset = cpu_to_le64(base_ofs + sz);
      p += ROUND_UP(sz, 64);

> +
> +    stq_le_p(&lp->memory_offset,
> +              (uintptr_t)init_memory_map(p, ram_size) - (uintptr_t)lp);
> +    p += ROUND_UP(sizeof(struct efi_memory_map_loongson), 64);

      init_memory_map(p, ram_size);
      sz = sizeof(struct efi_memory_map_loongson);
      lp->memory_offset = cpu_to_le64(base_ofs + sz);
      p += ROUND_UP(sz, 64);

> +
> +    stq_le_p(&lp->system_offset,
> +              (uintptr_t)init_system_loongson(p) - (uintptr_t)lp);
> +    p += ROUND_UP(sizeof(struct system_loongson), 64);

      etc...

> +
> +    stq_le_p(&lp->irq_offset,
> +              (uintptr_t)init_irq_source(p) - (uintptr_t)lp);
> +    p += ROUND_UP(sizeof(struct irq_source_routing_table), 64);
> +
> +    stq_le_p(&lp->interface_offset,
> +              (uintptr_t)init_interface_info(p) - (uintptr_t)lp);
> +    p += ROUND_UP(sizeof(struct interface_info), 64);
> +
> +    stq_le_p(&lp->boarddev_table_offset,
> +              (uintptr_t)board_devices_info(p) - (uintptr_t)lp);
> +    p += ROUND_UP(sizeof(struct board_devices), 64);
> +
> +    stq_le_p(&lp->special_offset,
> +              (uintptr_t)init_special_info(p) - (uintptr_t)lp);
> +    p += ROUND_UP(sizeof(struct loongson_special_attribute), 64);
> +}
> +
> +void init_reset_system(struct efi_reset_system_t *reset)
> +{
> +    stq_le_p(&reset->Shutdown, 0xffffffffbfc000a8);
> +    stq_le_p(&reset->ResetCold, 0xffffffffbfc00080);
> +    stq_le_p(&reset->ResetWarm, 0xffffffffbfc00080);
> +}


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

* Re: [PATCH V17 4/6] hw/mips: Add Loongson-3 boot parameter helpers
  2020-12-13 23:09               ` Philippe Mathieu-Daudé
@ 2020-12-14  2:37                 ` Huacai Chen
  2020-12-14 13:49                   ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 31+ messages in thread
From: Huacai Chen @ 2020-12-14  2:37 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Peter Maydell, Aleksandar Rikalo, David Hildenbrand,
	Alex Bennée, Richard Henderson, QEMU Developers,
	Aleksandar Markovic, Marc-André Lureau, Huacai Chen,
	Aurelien Jarno

Hi, Philippe,

On Mon, Dec 14, 2020 at 7:09 AM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>
> On 12/13/20 11:17 PM, Philippe Mathieu-Daudé wrote:
> > On 12/11/20 12:32 PM, Philippe Mathieu-Daudé wrote:
> >> On 12/11/20 3:46 AM, Huacai Chen wrote:
> >>> Hi, Rechard and Peter,
> >>>
> >>> On Wed, Dec 2, 2020 at 5:32 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
> >>>>
> >>>> On 12/2/20 2:14 AM, Huacai Chen wrote:
> >>>>> Hi, Phillippe,
> >>>>>
> >>>>> On Tue, Nov 24, 2020 at 6:25 AM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
> >>>>>>
> >>>>>> On 11/6/20 5:21 AM, Huacai Chen wrote:
> >>>>>>> Preparing to add Loongson-3 machine support, add Loongson-3's LEFI (a
> >>>>>>> UEFI-like interface for BIOS-Kernel boot parameters) helpers first.
> >>>>>>>
> >>>>>>> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> >>>>>>> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> >>>>>>> Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> >>>>>>> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> >>>>>>> ---
> >>>>>>>  hw/mips/loongson3_bootp.c | 165 +++++++++++++++++++++++++++++++
> >>>>>>>  hw/mips/loongson3_bootp.h | 241 ++++++++++++++++++++++++++++++++++++++++++++++
> >>>>>>>  hw/mips/meson.build       |   1 +
> >>>>>>>  3 files changed, 407 insertions(+)
> >>>>>>>  create mode 100644 hw/mips/loongson3_bootp.c
> >>>>>>>  create mode 100644 hw/mips/loongson3_bootp.h
> >>>>>>>
> >>>>>>> diff --git a/hw/mips/loongson3_bootp.c b/hw/mips/loongson3_bootp.c
> >>>>>>> new file mode 100644
> >>>>>>> index 0000000..3a16081
> >>>>>>> --- /dev/null
> >>>>>>> +++ b/hw/mips/loongson3_bootp.c
> >>>>>>> @@ -0,0 +1,165 @@
> >>>>>>> +/*
> >>>>>>> + * LEFI (a UEFI-like interface for BIOS-Kernel boot parameters) helpers
> >>>>>>> + *
> >>>>>>> + * Copyright (c) 2018-2020 Huacai Chen (chenhc@lemote.com)
> >>>>>>> + * Copyright (c) 2018-2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
> >>>>>>> + *
> >>>>>>> + * This program is free software: you can redistribute it and/or modify
> >>>>>>> + * it under the terms of the GNU General Public License as published by
> >>>>>>> + * the Free Software Foundation, either version 2 of the License, or
> >>>>>>> + * (at your option) any later version.
> >>>>>>> + *
> >>>>>>> + * This program is distributed in the hope that it will be useful,
> >>>>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> >>>>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> >>>>>>> + * GNU General Public License for more details.
> >>>>>>> + *
> >>>>>>> + * You should have received a copy of the GNU General Public License
> >>>>>>> + * along with this program. If not, see <https://www.gnu.org/licenses/>.
> >>>>>>> + */
> >>>>>>> +
> >>>>>>> +#include "qemu/osdep.h"
> >>>>>>> +#include "qemu/units.h"
> >>>>>>> +#include "qemu/cutils.h"
> >>>>>>> +#include "cpu.h"
> >>>>>>> +#include "hw/boards.h"
> >>>>>>> +#include "hw/mips/loongson3_bootp.h"
> >>>>>>> +
> >>>>>>> +#define LOONGSON3_CORE_PER_NODE 4
> >>>>>>> +
> >>>>>>> +static struct efi_cpuinfo_loongson *init_cpu_info(void *g_cpuinfo, uint64_t cpu_freq)
> >>>>>>> +{
> >>>>>>> +    struct efi_cpuinfo_loongson *c = g_cpuinfo;
> >>>>>>> +
> >>>>>>> +    stl_le_p(&c->cputype, Loongson_3A);
> >>>>>>> +    stl_le_p(&c->processor_id, MIPS_CPU(first_cpu)->env.CP0_PRid);
> >>>>>>
> >>>>>> Build failing with Clang:
> >>>>>>
> >>>>>> FAILED: libqemu-mips64el-softmmu.fa.p/hw_mips_loongson3_bootp.c.o
> >>>>>> hw/mips/loongson3_bootp.c:35:15: error: taking address of packed member
> >>>>>> 'processor_id' of class or structure 'efi_cpuinfo_loongson' may result
> >>>>>> in an unaligned pointer value [-Werror,-Waddress-of-packed-member]
> >>>>>>     stl_le_p(&c->processor_id, MIPS_CPU(first_cpu)->env.CP0_PRid);
> >>>>>>               ^~~~~~~~~~~~~~~
> >>>>>> 1 error generated.
> >>>>> We cannot reproduce it on X86/MIPS with clang...
> >>>>
> >>>> You can reproduce running the Clang job on Gitlab-CI:
> >>>>
> >>>> https://wiki.qemu.org/Testing/CI/GitLabCI
> >>>>
> >>>>> And I found that
> >>>>> stl_le_p() will be __builtin_memcpy(), I don't think memcpy() will
> >>>>> cause unaligned access. So, any suggestions?
> >>
> >> My understanding is the compiler is complaining for the argument
> >> passed to the caller, with no knowledge of the callee implementation.
> >>
> >> Which makes me wonder if these functions are really inlined...
> >>
> >> Do we need to use QEMU_ALWAYS_INLINE for these LDST helpers?
> >
> > No, this doesn't work neither.
>
> Well, this works:
>
> -- >8 --
> @@ -32,7 +32,7 @@ static struct efi_cpuinfo_loongson *init_cpu_info(void
> *g_cpuinfo, uint64_t cpu_
>      struct efi_cpuinfo_loongson *c = g_cpuinfo;
>
>      stl_le_p(&c->cputype, Loongson_3A);
> -    stl_le_p(&c->processor_id, MIPS_CPU(first_cpu)->env.CP0_PRid);
> +    c->processor_id = cpu_to_le32(MIPS_CPU(first_cpu)->env.CP0_PRid);
>      if (cpu_freq > UINT_MAX) {
>          stl_le_p(&c->cpu_clock_freq, UINT_MAX);
>      } else {

This seems not allowed. In include/qemu/bswap.h it says:
 * Do an in-place conversion of the value pointed to by @v from the
 * native endianness of the host CPU to the specified format.
 *
 * Both X_to_cpu() and cpu_to_X() perform the same operation; you
 * should use whichever one is better documenting of the function your
 * code is performing.
 *
 * Do not use these functions for conversion of values which are in guest
 * memory, since the data may not be sufficiently aligned for the host CPU's
 * load and store instructions. Instead you should use the ld*_p() and
 * st*_p() functions, which perform loads and stores of data of any
 * required size and endianness and handle possible misalignment.

And there is a very strange problem, nearly all 32bit members are
after a 16bit vers member, why only processor_id is special? Compiler
bug?

Huacai
> ---
>
> >
> >>
> >> I see Richard used it in commit 80d9d1c6785 ("cputlb: Split out
> >> load/store_memop").
> >>
> >>>>
> >>>> I'll defer this question to Richard/Peter who have deeper understanding.
> >>> Any sugguestions? Other patches are updated, except this one.
> >>
> >> Searching on the list, I see Marc-André resolved that by
> >> using a copy on the stack:
> >> https://www.mail-archive.com/qemu-devel@nongnu.org/msg614482.html
> >>
> >>>
> >>> Huacai
> >>>>
> >>>>>
> >>>>> Huacai
> >>>
> >>
> >


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

* Re: [PATCH V17 4/6] hw/mips: Add Loongson-3 boot parameter helpers
  2020-12-14  2:37                 ` Huacai Chen
@ 2020-12-14 13:49                   ` Philippe Mathieu-Daudé
  2020-12-15  5:34                     ` Huacai Chen
  0 siblings, 1 reply; 31+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-12-14 13:49 UTC (permalink / raw)
  To: Huacai Chen, Eric Blake
  Cc: Peter Maydell, Aleksandar Rikalo, David Hildenbrand,
	Richard Henderson, QEMU Developers, Aleksandar Markovic,
	Marc-André Lureau, Huacai Chen, Alex Bennée,
	Aurelien Jarno

On 12/14/20 3:37 AM, Huacai Chen wrote:
> Hi, Philippe,
> 
> On Mon, Dec 14, 2020 at 7:09 AM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>>
>> On 12/13/20 11:17 PM, Philippe Mathieu-Daudé wrote:
>>> On 12/11/20 12:32 PM, Philippe Mathieu-Daudé wrote:
>>>> On 12/11/20 3:46 AM, Huacai Chen wrote:
>>>>> Hi, Rechard and Peter,
>>>>>
>>>>> On Wed, Dec 2, 2020 at 5:32 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>>>>>>
>>>>>> On 12/2/20 2:14 AM, Huacai Chen wrote:
>>>>>>> Hi, Phillippe,
>>>>>>>
>>>>>>> On Tue, Nov 24, 2020 at 6:25 AM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>>>>>>>>
>>>>>>>> On 11/6/20 5:21 AM, Huacai Chen wrote:
>>>>>>>>> Preparing to add Loongson-3 machine support, add Loongson-3's LEFI (a
>>>>>>>>> UEFI-like interface for BIOS-Kernel boot parameters) helpers first.
>>>>>>>>>
>>>>>>>>> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
>>>>>>>>> Signed-off-by: Huacai Chen <chenhc@lemote.com>
>>>>>>>>> Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
>>>>>>>>> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
>>>>>>>>> ---
>>>>>>>>>  hw/mips/loongson3_bootp.c | 165 +++++++++++++++++++++++++++++++
>>>>>>>>>  hw/mips/loongson3_bootp.h | 241 ++++++++++++++++++++++++++++++++++++++++++++++
>>>>>>>>>  hw/mips/meson.build       |   1 +
>>>>>>>>>  3 files changed, 407 insertions(+)
>>>>>>>>>  create mode 100644 hw/mips/loongson3_bootp.c
>>>>>>>>>  create mode 100644 hw/mips/loongson3_bootp.h
>>>>>>>>>
>>>>>>>>> diff --git a/hw/mips/loongson3_bootp.c b/hw/mips/loongson3_bootp.c
>>>>>>>>> new file mode 100644
>>>>>>>>> index 0000000..3a16081
>>>>>>>>> --- /dev/null
>>>>>>>>> +++ b/hw/mips/loongson3_bootp.c
>>>>>>>>> @@ -0,0 +1,165 @@
>>>>>>>>> +/*
>>>>>>>>> + * LEFI (a UEFI-like interface for BIOS-Kernel boot parameters) helpers
>>>>>>>>> + *
>>>>>>>>> + * Copyright (c) 2018-2020 Huacai Chen (chenhc@lemote.com)
>>>>>>>>> + * Copyright (c) 2018-2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
>>>>>>>>> + *
>>>>>>>>> + * This program is free software: you can redistribute it and/or modify
>>>>>>>>> + * it under the terms of the GNU General Public License as published by
>>>>>>>>> + * the Free Software Foundation, either version 2 of the License, or
>>>>>>>>> + * (at your option) any later version.
>>>>>>>>> + *
>>>>>>>>> + * This program is distributed in the hope that it will be useful,
>>>>>>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
>>>>>>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
>>>>>>>>> + * GNU General Public License for more details.
>>>>>>>>> + *
>>>>>>>>> + * You should have received a copy of the GNU General Public License
>>>>>>>>> + * along with this program. If not, see <https://www.gnu.org/licenses/>.
>>>>>>>>> + */
>>>>>>>>> +
>>>>>>>>> +#include "qemu/osdep.h"
>>>>>>>>> +#include "qemu/units.h"
>>>>>>>>> +#include "qemu/cutils.h"
>>>>>>>>> +#include "cpu.h"
>>>>>>>>> +#include "hw/boards.h"
>>>>>>>>> +#include "hw/mips/loongson3_bootp.h"
>>>>>>>>> +
>>>>>>>>> +#define LOONGSON3_CORE_PER_NODE 4
>>>>>>>>> +
>>>>>>>>> +static struct efi_cpuinfo_loongson *init_cpu_info(void *g_cpuinfo, uint64_t cpu_freq)
>>>>>>>>> +{
>>>>>>>>> +    struct efi_cpuinfo_loongson *c = g_cpuinfo;
>>>>>>>>> +
>>>>>>>>> +    stl_le_p(&c->cputype, Loongson_3A);
>>>>>>>>> +    stl_le_p(&c->processor_id, MIPS_CPU(first_cpu)->env.CP0_PRid);
>>>>>>>>
>>>>>>>> Build failing with Clang:
>>>>>>>>
>>>>>>>> FAILED: libqemu-mips64el-softmmu.fa.p/hw_mips_loongson3_bootp.c.o
>>>>>>>> hw/mips/loongson3_bootp.c:35:15: error: taking address of packed member
>>>>>>>> 'processor_id' of class or structure 'efi_cpuinfo_loongson' may result
>>>>>>>> in an unaligned pointer value [-Werror,-Waddress-of-packed-member]
>>>>>>>>     stl_le_p(&c->processor_id, MIPS_CPU(first_cpu)->env.CP0_PRid);
>>>>>>>>               ^~~~~~~~~~~~~~~
>>>>>>>> 1 error generated.
>>>>>>> We cannot reproduce it on X86/MIPS with clang...
>>>>>>
>>>>>> You can reproduce running the Clang job on Gitlab-CI:
>>>>>>
>>>>>> https://wiki.qemu.org/Testing/CI/GitLabCI
>>>>>>
>>>>>>> And I found that
>>>>>>> stl_le_p() will be __builtin_memcpy(), I don't think memcpy() will
>>>>>>> cause unaligned access. So, any suggestions?
>>>>
>>>> My understanding is the compiler is complaining for the argument
>>>> passed to the caller, with no knowledge of the callee implementation.
>>>>
>>>> Which makes me wonder if these functions are really inlined...
>>>>
>>>> Do we need to use QEMU_ALWAYS_INLINE for these LDST helpers?
>>>
>>> No, this doesn't work neither.
>>
>> Well, this works:
>>
>> -- >8 --
>> @@ -32,7 +32,7 @@ static struct efi_cpuinfo_loongson *init_cpu_info(void
>> *g_cpuinfo, uint64_t cpu_
>>      struct efi_cpuinfo_loongson *c = g_cpuinfo;
>>
>>      stl_le_p(&c->cputype, Loongson_3A);
>> -    stl_le_p(&c->processor_id, MIPS_CPU(first_cpu)->env.CP0_PRid);
>> +    c->processor_id = cpu_to_le32(MIPS_CPU(first_cpu)->env.CP0_PRid);
>>      if (cpu_freq > UINT_MAX) {
>>          stl_le_p(&c->cpu_clock_freq, UINT_MAX);
>>      } else {
> 
> This seems not allowed. In include/qemu/bswap.h it says:
>  * Do an in-place conversion of the value pointed to by @v from the
>  * native endianness of the host CPU to the specified format.
>  *
>  * Both X_to_cpu() and cpu_to_X() perform the same operation; you
>  * should use whichever one is better documenting of the function your
>  * code is performing.
>  *
>  * Do not use these functions for conversion of values which are in guest
>  * memory, since the data may not be sufficiently aligned for the host CPU's
>  * load and store instructions. Instead you should use the ld*_p() and
>  * st*_p() functions, which perform loads and stores of data of any
>  * required size and endianness and handle possible misalignment.
> 
> And there is a very strange problem, nearly all 32bit members are
> after a 16bit vers member, why only processor_id is special? Compiler
> bug?

This is what I wonder since some time but I don't have the knowledge
to confirm.

Indeed I commented the "stl_le_p(&c->processor_id, ...);" line,
and there is no error for the following 32-bit values, which are
similarly unlikely 32-bit aligned.

FWIW I am using Fedora release 32 (Thirty Two), and 'cc -v':

 clang version 10.0.1 (Fedora 10.0.1-3.fc32)
 Target: x86_64-unknown-linux-gnu
 clang -cc1 version 10.0.1 based upon LLVM 10.0.1 default target
x86_64-unknown-linux-gnu

> 
> Huacai
>> ---
>>
>>>
>>>>
>>>> I see Richard used it in commit 80d9d1c6785 ("cputlb: Split out
>>>> load/store_memop").
>>>>
>>>>>>
>>>>>> I'll defer this question to Richard/Peter who have deeper understanding.
>>>>> Any sugguestions? Other patches are updated, except this one.
>>>>
>>>> Searching on the list, I see Marc-André resolved that by
>>>> using a copy on the stack:
>>>> https://www.mail-archive.com/qemu-devel@nongnu.org/msg614482.html


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

* Re: [PATCH V17 4/6] hw/mips: Add Loongson-3 boot parameter helpers
  2020-12-14 13:49                   ` Philippe Mathieu-Daudé
@ 2020-12-15  5:34                     ` Huacai Chen
  2020-12-15 10:21                       ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 31+ messages in thread
From: Huacai Chen @ 2020-12-15  5:34 UTC (permalink / raw)
  To: Philippe Mathieu-Daudé
  Cc: Peter Maydell, Aleksandar Rikalo, David Hildenbrand,
	Richard Henderson, QEMU Developers, Aleksandar Markovic,
	Marc-André Lureau, Huacai Chen, Alex Bennée,
	Aurelien Jarno

Hi, Philippe,

On Mon, Dec 14, 2020 at 9:49 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
>
> On 12/14/20 3:37 AM, Huacai Chen wrote:
> > Hi, Philippe,
> >
> > On Mon, Dec 14, 2020 at 7:09 AM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
> >>
> >> On 12/13/20 11:17 PM, Philippe Mathieu-Daudé wrote:
> >>> On 12/11/20 12:32 PM, Philippe Mathieu-Daudé wrote:
> >>>> On 12/11/20 3:46 AM, Huacai Chen wrote:
> >>>>> Hi, Rechard and Peter,
> >>>>>
> >>>>> On Wed, Dec 2, 2020 at 5:32 PM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
> >>>>>>
> >>>>>> On 12/2/20 2:14 AM, Huacai Chen wrote:
> >>>>>>> Hi, Phillippe,
> >>>>>>>
> >>>>>>> On Tue, Nov 24, 2020 at 6:25 AM Philippe Mathieu-Daudé <f4bug@amsat.org> wrote:
> >>>>>>>>
> >>>>>>>> On 11/6/20 5:21 AM, Huacai Chen wrote:
> >>>>>>>>> Preparing to add Loongson-3 machine support, add Loongson-3's LEFI (a
> >>>>>>>>> UEFI-like interface for BIOS-Kernel boot parameters) helpers first.
> >>>>>>>>>
> >>>>>>>>> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> >>>>>>>>> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> >>>>>>>>> Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> >>>>>>>>> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> >>>>>>>>> ---
> >>>>>>>>>  hw/mips/loongson3_bootp.c | 165 +++++++++++++++++++++++++++++++
> >>>>>>>>>  hw/mips/loongson3_bootp.h | 241 ++++++++++++++++++++++++++++++++++++++++++++++
> >>>>>>>>>  hw/mips/meson.build       |   1 +
> >>>>>>>>>  3 files changed, 407 insertions(+)
> >>>>>>>>>  create mode 100644 hw/mips/loongson3_bootp.c
> >>>>>>>>>  create mode 100644 hw/mips/loongson3_bootp.h
> >>>>>>>>>
> >>>>>>>>> diff --git a/hw/mips/loongson3_bootp.c b/hw/mips/loongson3_bootp.c
> >>>>>>>>> new file mode 100644
> >>>>>>>>> index 0000000..3a16081
> >>>>>>>>> --- /dev/null
> >>>>>>>>> +++ b/hw/mips/loongson3_bootp.c
> >>>>>>>>> @@ -0,0 +1,165 @@
> >>>>>>>>> +/*
> >>>>>>>>> + * LEFI (a UEFI-like interface for BIOS-Kernel boot parameters) helpers
> >>>>>>>>> + *
> >>>>>>>>> + * Copyright (c) 2018-2020 Huacai Chen (chenhc@lemote.com)
> >>>>>>>>> + * Copyright (c) 2018-2020 Jiaxun Yang <jiaxun.yang@flygoat.com>
> >>>>>>>>> + *
> >>>>>>>>> + * This program is free software: you can redistribute it and/or modify
> >>>>>>>>> + * it under the terms of the GNU General Public License as published by
> >>>>>>>>> + * the Free Software Foundation, either version 2 of the License, or
> >>>>>>>>> + * (at your option) any later version.
> >>>>>>>>> + *
> >>>>>>>>> + * This program is distributed in the hope that it will be useful,
> >>>>>>>>> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> >>>>>>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> >>>>>>>>> + * GNU General Public License for more details.
> >>>>>>>>> + *
> >>>>>>>>> + * You should have received a copy of the GNU General Public License
> >>>>>>>>> + * along with this program. If not, see <https://www.gnu.org/licenses/>.
> >>>>>>>>> + */
> >>>>>>>>> +
> >>>>>>>>> +#include "qemu/osdep.h"
> >>>>>>>>> +#include "qemu/units.h"
> >>>>>>>>> +#include "qemu/cutils.h"
> >>>>>>>>> +#include "cpu.h"
> >>>>>>>>> +#include "hw/boards.h"
> >>>>>>>>> +#include "hw/mips/loongson3_bootp.h"
> >>>>>>>>> +
> >>>>>>>>> +#define LOONGSON3_CORE_PER_NODE 4
> >>>>>>>>> +
> >>>>>>>>> +static struct efi_cpuinfo_loongson *init_cpu_info(void *g_cpuinfo, uint64_t cpu_freq)
> >>>>>>>>> +{
> >>>>>>>>> +    struct efi_cpuinfo_loongson *c = g_cpuinfo;
> >>>>>>>>> +
> >>>>>>>>> +    stl_le_p(&c->cputype, Loongson_3A);
> >>>>>>>>> +    stl_le_p(&c->processor_id, MIPS_CPU(first_cpu)->env.CP0_PRid);
> >>>>>>>>
> >>>>>>>> Build failing with Clang:
> >>>>>>>>
> >>>>>>>> FAILED: libqemu-mips64el-softmmu.fa.p/hw_mips_loongson3_bootp.c.o
> >>>>>>>> hw/mips/loongson3_bootp.c:35:15: error: taking address of packed member
> >>>>>>>> 'processor_id' of class or structure 'efi_cpuinfo_loongson' may result
> >>>>>>>> in an unaligned pointer value [-Werror,-Waddress-of-packed-member]
> >>>>>>>>     stl_le_p(&c->processor_id, MIPS_CPU(first_cpu)->env.CP0_PRid);
> >>>>>>>>               ^~~~~~~~~~~~~~~
> >>>>>>>> 1 error generated.
> >>>>>>> We cannot reproduce it on X86/MIPS with clang...
> >>>>>>
> >>>>>> You can reproduce running the Clang job on Gitlab-CI:
> >>>>>>
> >>>>>> https://wiki.qemu.org/Testing/CI/GitLabCI
> >>>>>>
> >>>>>>> And I found that
> >>>>>>> stl_le_p() will be __builtin_memcpy(), I don't think memcpy() will
> >>>>>>> cause unaligned access. So, any suggestions?
> >>>>
> >>>> My understanding is the compiler is complaining for the argument
> >>>> passed to the caller, with no knowledge of the callee implementation.
> >>>>
> >>>> Which makes me wonder if these functions are really inlined...
> >>>>
> >>>> Do we need to use QEMU_ALWAYS_INLINE for these LDST helpers?
> >>>
> >>> No, this doesn't work neither.
> >>
> >> Well, this works:
> >>
> >> -- >8 --
> >> @@ -32,7 +32,7 @@ static struct efi_cpuinfo_loongson *init_cpu_info(void
> >> *g_cpuinfo, uint64_t cpu_
> >>      struct efi_cpuinfo_loongson *c = g_cpuinfo;
> >>
> >>      stl_le_p(&c->cputype, Loongson_3A);
> >> -    stl_le_p(&c->processor_id, MIPS_CPU(first_cpu)->env.CP0_PRid);
> >> +    c->processor_id = cpu_to_le32(MIPS_CPU(first_cpu)->env.CP0_PRid);
> >>      if (cpu_freq > UINT_MAX) {
> >>          stl_le_p(&c->cpu_clock_freq, UINT_MAX);
> >>      } else {
> >
> > This seems not allowed. In include/qemu/bswap.h it says:
> >  * Do an in-place conversion of the value pointed to by @v from the
> >  * native endianness of the host CPU to the specified format.
> >  *
> >  * Both X_to_cpu() and cpu_to_X() perform the same operation; you
> >  * should use whichever one is better documenting of the function your
> >  * code is performing.
> >  *
> >  * Do not use these functions for conversion of values which are in guest
> >  * memory, since the data may not be sufficiently aligned for the host CPU's
> >  * load and store instructions. Instead you should use the ld*_p() and
> >  * st*_p() functions, which perform loads and stores of data of any
> >  * required size and endianness and handle possible misalignment.
> >
> > And there is a very strange problem, nearly all 32bit members are
> > after a 16bit vers member, why only processor_id is special? Compiler
> > bug?
>
> This is what I wonder since some time but I don't have the knowledge
> to confirm.
>
> Indeed I commented the "stl_le_p(&c->processor_id, ...);" line,
> and there is no error for the following 32-bit values, which are
> similarly unlikely 32-bit aligned.
>
> FWIW I am using Fedora release 32 (Thirty Two), and 'cc -v':
>
>  clang version 10.0.1 (Fedora 10.0.1-3.fc32)
>  Target: x86_64-unknown-linux-gnu
>  clang -cc1 version 10.0.1 based upon LLVM 10.0.1 default target
> x86_64-unknown-linux-gnu
>
Since cpu_to_le32() "solve" the problem here, I want to use
cpu_to_lexx() for all members, do you agree?

Huacai

> >
> > Huacai
> >> ---
> >>
> >>>
> >>>>
> >>>> I see Richard used it in commit 80d9d1c6785 ("cputlb: Split out
> >>>> load/store_memop").
> >>>>
> >>>>>>
> >>>>>> I'll defer this question to Richard/Peter who have deeper understanding.
> >>>>> Any sugguestions? Other patches are updated, except this one.
> >>>>
> >>>> Searching on the list, I see Marc-André resolved that by
> >>>> using a copy on the stack:
> >>>> https://www.mail-archive.com/qemu-devel@nongnu.org/msg614482.html


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

* Re: [PATCH V17 4/6] hw/mips: Add Loongson-3 boot parameter helpers
  2020-12-15  5:34                     ` Huacai Chen
@ 2020-12-15 10:21                       ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 31+ messages in thread
From: Philippe Mathieu-Daudé @ 2020-12-15 10:21 UTC (permalink / raw)
  To: Huacai Chen
  Cc: Peter Maydell, Aleksandar Rikalo, David Hildenbrand,
	Richard Henderson, QEMU Developers, Aleksandar Markovic,
	Marc-André Lureau, Huacai Chen, Alex Bennée,
	Aurelien Jarno

[-- Attachment #1: Type: text/plain, Size: 8216 bytes --]

Le mar. 15 déc. 2020 06:34, Huacai Chen <chenhuacai@gmail.com> a écrit :

> Hi, Philippe,
>
> On Mon, Dec 14, 2020 at 9:49 PM Philippe Mathieu-Daudé <f4bug@amsat.org>
> wrote:
> >
> > On 12/14/20 3:37 AM, Huacai Chen wrote:
> > > Hi, Philippe,
> > >
> > > On Mon, Dec 14, 2020 at 7:09 AM Philippe Mathieu-Daudé <
> f4bug@amsat.org> wrote:
> > >>
> > >> On 12/13/20 11:17 PM, Philippe Mathieu-Daudé wrote:
> > >>> On 12/11/20 12:32 PM, Philippe Mathieu-Daudé wrote:
> > >>>> On 12/11/20 3:46 AM, Huacai Chen wrote:
> > >>>>> Hi, Rechard and Peter,
> > >>>>>
> > >>>>> On Wed, Dec 2, 2020 at 5:32 PM Philippe Mathieu-Daudé <
> f4bug@amsat.org> wrote:
> > >>>>>>
> > >>>>>> On 12/2/20 2:14 AM, Huacai Chen wrote:
> > >>>>>>> Hi, Phillippe,
> > >>>>>>>
> > >>>>>>> On Tue, Nov 24, 2020 at 6:25 AM Philippe Mathieu-Daudé <
> f4bug@amsat.org> wrote:
> > >>>>>>>>
> > >>>>>>>> On 11/6/20 5:21 AM, Huacai Chen wrote:
> > >>>>>>>>> Preparing to add Loongson-3 machine support, add Loongson-3's
> LEFI (a
> > >>>>>>>>> UEFI-like interface for BIOS-Kernel boot parameters) helpers
> first.
> > >>>>>>>>>
> > >>>>>>>>> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
> > >>>>>>>>> Signed-off-by: Huacai Chen <chenhc@lemote.com>
> > >>>>>>>>> Co-developed-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> > >>>>>>>>> Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
> > >>>>>>>>> ---
> > >>>>>>>>>  hw/mips/loongson3_bootp.c | 165
> +++++++++++++++++++++++++++++++
> > >>>>>>>>>  hw/mips/loongson3_bootp.h | 241
> ++++++++++++++++++++++++++++++++++++++++++++++
> > >>>>>>>>>  hw/mips/meson.build       |   1 +
> > >>>>>>>>>  3 files changed, 407 insertions(+)
> > >>>>>>>>>  create mode 100644 hw/mips/loongson3_bootp.c
> > >>>>>>>>>  create mode 100644 hw/mips/loongson3_bootp.h
> > >>>>>>>>>
> > >>>>>>>>> diff --git a/hw/mips/loongson3_bootp.c
> b/hw/mips/loongson3_bootp.c
> > >>>>>>>>> new file mode 100644
> > >>>>>>>>> index 0000000..3a16081
> > >>>>>>>>> --- /dev/null
> > >>>>>>>>> +++ b/hw/mips/loongson3_bootp.c
> > >>>>>>>>> @@ -0,0 +1,165 @@
> > >>>>>>>>> +/*
> > >>>>>>>>> + * LEFI (a UEFI-like interface for BIOS-Kernel boot
> parameters) helpers
> > >>>>>>>>> + *
> > >>>>>>>>> + * Copyright (c) 2018-2020 Huacai Chen (chenhc@lemote.com)
> > >>>>>>>>> + * Copyright (c) 2018-2020 Jiaxun Yang <
> jiaxun.yang@flygoat.com>
> > >>>>>>>>> + *
> > >>>>>>>>> + * This program is free software: you can redistribute it
> and/or modify
> > >>>>>>>>> + * it under the terms of the GNU General Public License as
> published by
> > >>>>>>>>> + * the Free Software Foundation, either version 2 of the
> License, or
> > >>>>>>>>> + * (at your option) any later version.
> > >>>>>>>>> + *
> > >>>>>>>>> + * This program is distributed in the hope that it will be
> useful,
> > >>>>>>>>> + * but WITHOUT ANY WARRANTY; without even the implied
> warranty of
> > >>>>>>>>> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
> the
> > >>>>>>>>> + * GNU General Public License for more details.
> > >>>>>>>>> + *
> > >>>>>>>>> + * You should have received a copy of the GNU General Public
> License
> > >>>>>>>>> + * along with this program. If not, see <
> https://www.gnu.org/licenses/>.
> > >>>>>>>>> + */
> > >>>>>>>>> +
> > >>>>>>>>> +#include "qemu/osdep.h"
> > >>>>>>>>> +#include "qemu/units.h"
> > >>>>>>>>> +#include "qemu/cutils.h"
> > >>>>>>>>> +#include "cpu.h"
> > >>>>>>>>> +#include "hw/boards.h"
> > >>>>>>>>> +#include "hw/mips/loongson3_bootp.h"
> > >>>>>>>>> +
> > >>>>>>>>> +#define LOONGSON3_CORE_PER_NODE 4
> > >>>>>>>>> +
> > >>>>>>>>> +static struct efi_cpuinfo_loongson *init_cpu_info(void
> *g_cpuinfo, uint64_t cpu_freq)
> > >>>>>>>>> +{
> > >>>>>>>>> +    struct efi_cpuinfo_loongson *c = g_cpuinfo;
> > >>>>>>>>> +
> > >>>>>>>>> +    stl_le_p(&c->cputype, Loongson_3A);
> > >>>>>>>>> +    stl_le_p(&c->processor_id,
> MIPS_CPU(first_cpu)->env.CP0_PRid);
> > >>>>>>>>
> > >>>>>>>> Build failing with Clang:
> > >>>>>>>>
> > >>>>>>>> FAILED:
> libqemu-mips64el-softmmu.fa.p/hw_mips_loongson3_bootp.c.o
> > >>>>>>>> hw/mips/loongson3_bootp.c:35:15: error: taking address of
> packed member
> > >>>>>>>> 'processor_id' of class or structure 'efi_cpuinfo_loongson' may
> result
> > >>>>>>>> in an unaligned pointer value
> [-Werror,-Waddress-of-packed-member]
> > >>>>>>>>     stl_le_p(&c->processor_id,
> MIPS_CPU(first_cpu)->env.CP0_PRid);
> > >>>>>>>>               ^~~~~~~~~~~~~~~
> > >>>>>>>> 1 error generated.
> > >>>>>>> We cannot reproduce it on X86/MIPS with clang...
> > >>>>>>
> > >>>>>> You can reproduce running the Clang job on Gitlab-CI:
> > >>>>>>
> > >>>>>> https://wiki.qemu.org/Testing/CI/GitLabCI
> > >>>>>>
> > >>>>>>> And I found that
> > >>>>>>> stl_le_p() will be __builtin_memcpy(), I don't think memcpy()
> will
> > >>>>>>> cause unaligned access. So, any suggestions?
> > >>>>
> > >>>> My understanding is the compiler is complaining for the argument
> > >>>> passed to the caller, with no knowledge of the callee
> implementation.
> > >>>>
> > >>>> Which makes me wonder if these functions are really inlined...
> > >>>>
> > >>>> Do we need to use QEMU_ALWAYS_INLINE for these LDST helpers?
> > >>>
> > >>> No, this doesn't work neither.
> > >>
> > >> Well, this works:
> > >>
> > >> -- >8 --
> > >> @@ -32,7 +32,7 @@ static struct efi_cpuinfo_loongson
> *init_cpu_info(void
> > >> *g_cpuinfo, uint64_t cpu_
> > >>      struct efi_cpuinfo_loongson *c = g_cpuinfo;
> > >>
> > >>      stl_le_p(&c->cputype, Loongson_3A);
> > >> -    stl_le_p(&c->processor_id, MIPS_CPU(first_cpu)->env.CP0_PRid);
> > >> +    c->processor_id = cpu_to_le32(MIPS_CPU(first_cpu)->env.CP0_PRid);
> > >>      if (cpu_freq > UINT_MAX) {
> > >>          stl_le_p(&c->cpu_clock_freq, UINT_MAX);
> > >>      } else {
> > >
> > > This seems not allowed. In include/qemu/bswap.h it says:
> > >  * Do an in-place conversion of the value pointed to by @v from the
> > >  * native endianness of the host CPU to the specified format.
> > >  *
> > >  * Both X_to_cpu() and cpu_to_X() perform the same operation; you
> > >  * should use whichever one is better documenting of the function your
> > >  * code is performing.
> > >  *
> > >  * Do not use these functions for conversion of values which are in
> guest
> > >  * memory, since the data may not be sufficiently aligned for the host
> CPU's
> > >  * load and store instructions. Instead you should use the ld*_p() and
> > >  * st*_p() functions, which perform loads and stores of data of any
> > >  * required size and endianness and handle possible misalignment.
> > >
> > > And there is a very strange problem, nearly all 32bit members are
> > > after a 16bit vers member, why only processor_id is special? Compiler
> > > bug?
> >
> > This is what I wonder since some time but I don't have the knowledge
> > to confirm.
> >
> > Indeed I commented the "stl_le_p(&c->processor_id, ...);" line,
> > and there is no error for the following 32-bit values, which are
> > similarly unlikely 32-bit aligned.
> >
> > FWIW I am using Fedora release 32 (Thirty Two), and 'cc -v':
> >
> >  clang version 10.0.1 (Fedora 10.0.1-3.fc32)
> >  Target: x86_64-unknown-linux-gnu
> >  clang -cc1 version 10.0.1 based upon LLVM 10.0.1 default target
> > x86_64-unknown-linux-gnu
> >
> Since cpu_to_le32() "solve" the problem here, I want to use
> cpu_to_lexx() for all members, do you agree?
>

Fine by me. We can switch back to the recommended ldst helpers later, when
someone figure out the problem.


> Huacai
>
> > >
> > > Huacai
> > >> ---
> > >>
> > >>>
> > >>>>
> > >>>> I see Richard used it in commit 80d9d1c6785 ("cputlb: Split out
> > >>>> load/store_memop").
> > >>>>
> > >>>>>>
> > >>>>>> I'll defer this question to Richard/Peter who have deeper
> understanding.
> > >>>>> Any sugguestions? Other patches are updated, except this one.
> > >>>>
> > >>>> Searching on the list, I see Marc-André resolved that by
> > >>>> using a copy on the stack:
> > >>>> https://www.mail-archive.com/qemu-devel@nongnu.org/msg614482.html
>

[-- Attachment #2: Type: text/html, Size: 13413 bytes --]

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

end of thread, other threads:[~2020-12-15 10:22 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-11-06  4:21 [PATCH V17 0/6] mips: Add Loongson-3 machine support Huacai Chen
2020-11-06  4:21 ` [PATCH V17 1/6] target/mips: Fix PageMask with variable page size Huacai Chen
2020-11-07 12:11   ` Philippe Mathieu-Daudé
2020-11-08  1:34     ` Huacai Chen
2020-11-08 23:15   ` Philippe Mathieu-Daudé
2020-11-06  4:21 ` [PATCH V17 2/6] hw/intc: Rework Loongson LIOINTC Huacai Chen
2020-11-23 20:52   ` Philippe Mathieu-Daudé
2020-11-23 22:24     ` Philippe Mathieu-Daudé
2020-11-28  6:20       ` Huacai Chen
2020-11-28  6:19     ` Huacai Chen
2020-11-30 10:08       ` Philippe Mathieu-Daudé
2020-12-02  1:16         ` Huacai Chen
2020-11-06  4:21 ` [PATCH V17 3/6] hw/mips: Implement fw_cfg_arch_key_name() Huacai Chen
2020-11-06  4:21 ` [PATCH V17 4/6] hw/mips: Add Loongson-3 boot parameter helpers Huacai Chen
2020-11-23 22:25   ` Philippe Mathieu-Daudé
2020-12-02  1:14     ` Huacai Chen
2020-12-02  9:32       ` Philippe Mathieu-Daudé
2020-12-11  2:46         ` Huacai Chen
2020-12-11 11:32           ` Philippe Mathieu-Daudé
2020-12-13 22:17             ` Philippe Mathieu-Daudé
2020-12-13 23:09               ` Philippe Mathieu-Daudé
2020-12-14  2:37                 ` Huacai Chen
2020-12-14 13:49                   ` Philippe Mathieu-Daudé
2020-12-15  5:34                     ` Huacai Chen
2020-12-15 10:21                       ` Philippe Mathieu-Daudé
2020-12-13 23:24   ` Philippe Mathieu-Daudé
2020-11-06  4:21 ` [PATCH V17 5/6] hw/mips: Add Loongson-3 machine support Huacai Chen
2020-11-23 21:54   ` Philippe Mathieu-Daudé
2020-11-28  7:04     ` Huacai Chen
2020-11-06  4:21 ` [PATCH V17 6/6] docs/system: Update MIPS machine documentation Huacai Chen
2020-11-23 20:52   ` Philippe Mathieu-Daudé

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).