[RFC PATCH v4 27/30] hw/loongarch: Add LoongArch smbios support

2022-01-08 Thread Xiaojuan Yang
Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 hw/loongarch/Kconfig |  1 +
 hw/loongarch/loongson3.c | 40 
 include/hw/loongarch/loongarch.h |  1 +
 3 files changed, 42 insertions(+)

diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
index 06bfb82b1d..6e24e112b3 100644
--- a/hw/loongarch/Kconfig
+++ b/hw/loongarch/Kconfig
@@ -14,6 +14,7 @@ config LOONGSON3_LS7A
 select LOONGARCH_EXTIOI
 select LS7A_RTC
 select FW_CFG_LOONGARCH
+select SMBIOS
 
 config FW_CFG_LOONGARCH
 bool
diff --git a/hw/loongarch/loongson3.c b/hw/loongarch/loongson3.c
index 546ef6f4f1..8856225a99 100644
--- a/hw/loongarch/loongson3.c
+++ b/hw/loongarch/loongson3.c
@@ -27,6 +27,7 @@
 #include "hw/pci-host/ls7a.h"
 #include "hw/misc/unimp.h"
 #include "hw/loongarch/fw_cfg.h"
+#include "hw/firmware/smbios.h"
 
 #define LOONGSON3_BIOSNAME "loongarch_bios.bin"
 
@@ -100,6 +101,42 @@ static void fw_cfg_add_kernel_info(FWCfgState *fw_cfg)
 fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, (const char *)cmdline_buf);
 }
 
+static void loongarch_build_smbios(LoongArchMachineState *lams)
+{
+MachineState *ms = MACHINE(lams);
+MachineClass *mc = MACHINE_GET_CLASS(lams);
+uint8_t *smbios_tables, *smbios_anchor;
+size_t smbios_tables_len, smbios_anchor_len;
+const char *product = "QEMU Virtual Machine";
+
+if (!lams->fw_cfg) {
+return;
+}
+
+product = "Loongson-3A5000-7A1000-TCG";
+
+smbios_set_defaults("QEMU", product, mc->name, false,
+true, SMBIOS_ENTRY_POINT_TYPE_64);
+
+smbios_get_tables(ms, NULL, 0, _tables, _tables_len,
+  _anchor, _anchor_len, _fatal);
+
+if (smbios_anchor) {
+fw_cfg_add_file(lams->fw_cfg, "etc/smbios/smbios-tables",
+smbios_tables, smbios_tables_len);
+fw_cfg_add_file(lams->fw_cfg, "etc/smbios/smbios-anchor",
+smbios_anchor, smbios_anchor_len);
+}
+}
+
+static
+void loongarch_machine_done(Notifier *notifier, void *data)
+{
+LoongArchMachineState *lams = container_of(notifier,
+LoongArchMachineState, machine_done);
+loongarch_build_smbios(lams);
+}
+
 static void loongarch_cpu_reset(void *opaque)
 {
 LoongArchCPU *cpu = opaque;
@@ -417,6 +454,9 @@ static void loongarch_init(MachineState *machine)
 memory_region_set_readonly(>bios, true);
 memory_region_add_subregion(get_system_memory(), LA_BIOS_BASE, 
>bios);
 
+lams->machine_done.notify = loongarch_machine_done;
+qemu_add_machine_init_done_notifier(>machine_done);
+
 /* Initialize the IO interrupt subsystem */
 loongarch_irq_init(lams);
 }
diff --git a/include/hw/loongarch/loongarch.h b/include/hw/loongarch/loongarch.h
index 9ffcf8429f..9080864804 100644
--- a/include/hw/loongarch/loongarch.h
+++ b/include/hw/loongarch/loongarch.h
@@ -54,6 +54,7 @@ typedef struct LoongArchMachineState {
 MemoryRegion bios;
 
 /* State for other subsystems/APIs: */
+Notifier machine_done;
 FWCfgState  *fw_cfg;
 } LoongArchMachineState;
 
-- 
2.27.0




[RFC PATCH v4 14/30] hw/pci-host: Add ls7a1000 PCIe Host bridge support for Loongson3 Platform

2022-01-08 Thread Xiaojuan Yang
This is a model of the PCIe Host Bridge found on a Loongson-5000
processor. It includes a interrupt controller, some interface for
pci and nonpci devices. Mainly emulate part of it that is not
exactly the same as the host and only use part devices for
tcg mode. It support for MSI and MSIX interrupt sources.

For more detailed info about ls7a1000 you can see the doc at
https://github.com/loongson/LoongArch-Documentation/releases/latest/
download/Loongson-7A1000-usermanual-2.00-EN.pdf

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 hw/pci-host/Kconfig|   4 +
 hw/pci-host/ls7a.c | 178 +
 hw/pci-host/meson.build|   1 +
 include/hw/pci-host/ls7a.h |  52 +++
 include/hw/pci/pci_ids.h   |   3 +
 5 files changed, 238 insertions(+)
 create mode 100644 hw/pci-host/ls7a.c
 create mode 100644 include/hw/pci-host/ls7a.h

diff --git a/hw/pci-host/Kconfig b/hw/pci-host/Kconfig
index 2b5f7d58cc..b02a9d1454 100644
--- a/hw/pci-host/Kconfig
+++ b/hw/pci-host/Kconfig
@@ -77,3 +77,7 @@ config MV64361
 bool
 select PCI
 select I8259
+
+config PCI_EXPRESS_7A
+bool
+select PCI_EXPRESS
diff --git a/hw/pci-host/ls7a.c b/hw/pci-host/ls7a.c
new file mode 100644
index 00..eb16b669bb
--- /dev/null
+++ b/hw/pci-host/ls7a.c
@@ -0,0 +1,178 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU Loongson 7A1000 North Bridge Emulation
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+
+#include "hw/pci/pci.h"
+#include "hw/pci/pcie_host.h"
+#include "hw/qdev-properties.h"
+#include "qapi/error.h"
+#include "hw/irq.h"
+#include "hw/pci/pci_bridge.h"
+#include "hw/pci/pci_bus.h"
+#include "sysemu/reset.h"
+#include "hw/pci-host/ls7a.h"
+#include "migration/vmstate.h"
+
+static const VMStateDescription vmstate_ls7a_pcie = {
+.name = "LS7A_PCI_DEVICE",
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_PCI_DEVICE(parent_obj, LS7APCIState),
+VMSTATE_END_OF_LIST()
+}
+};
+
+static void pci_ls7a_config_write(void *opaque, hwaddr addr,
+  uint64_t val, unsigned size)
+{
+pci_data_write(opaque, addr, val, size);
+}
+
+static uint64_t pci_ls7a_config_read(void *opaque,
+ hwaddr addr, unsigned size)
+{
+uint64_t val;
+
+val = pci_data_read(opaque, addr, size);
+
+return val;
+}
+
+static const MemoryRegionOps pci_ls7a_config_ops = {
+.read = pci_ls7a_config_read,
+.write = pci_ls7a_config_write,
+.valid = {
+.min_access_size = 1,
+.max_access_size = 4,
+},
+.impl = {
+.min_access_size = 1,
+.max_access_size = 4,
+},
+.endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void ls7a_pciehost_realize(DeviceState *dev, Error **errp)
+{
+PCIHostState *pci = PCI_HOST_BRIDGE(dev);
+LS7APCIEHost *s = LS7A_HOST_DEVICE(dev);
+SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
+PCIExpressHost *pex = PCIE_HOST_BRIDGE(dev);
+
+pcie_host_mmcfg_init(pex, LS_PCIECFG_SIZE);
+sysbus_init_mmio(sbd, >mmio);
+
+/* Add ls7a pci-io/pci-mmio */
+memory_region_init(>pci_io, OBJECT(s), "io", LS7A_PCI_IO_SIZE);
+memory_region_init(>pci_mmio, OBJECT(s), "ls7a_mmio", UINT64_MAX);
+sysbus_init_mmio(sbd, >pci_io);
+sysbus_init_mmio(sbd, >pci_mmio);
+
+pci->bus = pci_register_root_bus(dev, "pcie.0", NULL, NULL, s,
+ >pci_mmio, >pci_io,
+ PCI_DEVFN(1, 0), 128, TYPE_PCIE_BUS);
+
+memory_region_init_io(>pci_conf, OBJECT(dev),
+  _ls7a_config_ops, pci->bus,
+  "ls7a_pci_conf", HT1LO_PCICFG_SIZE);
+sysbus_init_mmio(sbd, >pci_conf);
+
+qdev_realize(DEVICE(>pci_dev), BUS(pci->bus), _fatal);
+}
+
+static void ls7a_reset(DeviceState *qdev)
+{
+PCIDevice *d = PCI_DEVICE(qdev);
+
+/* pci status */
+d->config[0x6] = 0x01;
+/* base class code */
+d->config[0xb] = 0x06;
+/* header type */
+d->config[0xe] = 0x80;
+/* capabilities pointer */
+d->config[0x34] = 0x40;
+/* link status and control register 0 */
+d->config[0x44] = 0x20;
+}
+
+static void ls7a_pcie_class_init(ObjectClass *klass, void *data)
+{
+DeviceClass *dc = DEVICE_CLASS(klass);
+PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
+dc->desc = "LS7A1000 PCIE Host bridge";
+dc->vmsd = _ls7a_pcie;
+k->vendor_id = PCI_VENDOR_ID_LOONGSON;
+k->device_id = PCI_DEVICE_ID_LOONGSON_HOST;
+k->revision = 0x0;
+k->class_id = PCI_CLASS_BR

[RFC PATCH v4 05/30] target/loongarch: Add constant timer support

2022-01-08 Thread Xiaojuan Yang
Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 target/loongarch/constant_timer.c | 63 +++
 target/loongarch/cpu.c|  9 +
 target/loongarch/cpu.h| 10 +
 target/loongarch/meson.build  |  1 +
 4 files changed, 83 insertions(+)
 create mode 100644 target/loongarch/constant_timer.c

diff --git a/target/loongarch/constant_timer.c 
b/target/loongarch/constant_timer.c
new file mode 100644
index 00..e7d0f5ffe7
--- /dev/null
+++ b/target/loongarch/constant_timer.c
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch constant timer support
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "hw/loongarch/loongarch.h"
+#include "qemu/timer.h"
+#include "cpu.h"
+
+#define TIMER_PERIOD10 /* 10 ns period for 100 Mhz frequency */
+#define CONSTANT_TIMER_TICK_MASK0xfffcUL
+#define CONSTANT_TIMER_ENABLE   0x1UL
+
+/* LoongArch timer */
+uint64_t cpu_loongarch_get_constant_timer_counter(LoongArchCPU *cpu)
+{
+return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / TIMER_PERIOD;
+}
+
+uint64_t cpu_loongarch_get_constant_timer_ticks(LoongArchCPU *cpu)
+{
+uint64_t now, expire;
+
+now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+expire = timer_expire_time_ns(>timer);
+
+return (expire - now) / TIMER_PERIOD;
+}
+
+void cpu_loongarch_store_constant_timer_config(LoongArchCPU *cpu,
+   uint64_t value)
+{
+CPULoongArchState *env = >env;
+uint64_t now, next;
+
+env->CSR_TCFG = value;
+if (value & CONSTANT_TIMER_ENABLE) {
+now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+next = now + (value & CONSTANT_TIMER_TICK_MASK) * TIMER_PERIOD;
+timer_mod(>timer, next);
+}
+}
+
+void loongarch_constant_timer_cb(void *opaque)
+{
+LoongArchCPU *cpu  = opaque;
+CPULoongArchState *env = >env;
+uint64_t now, next;
+
+if (FIELD_EX64(env->CSR_TCFG, CSR_TCFG, PERIODIC)) {
+now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+next = now + (env->CSR_TCFG & CONSTANT_TIMER_TICK_MASK) * TIMER_PERIOD;
+timer_mod(>timer, next);
+} else {
+env->CSR_TCFG = FIELD_DP64(env->CSR_TCFG, CSR_TCFG, EN, 0);
+}
+
+env->CSR_ESTAT |= 1 << IRQ_TIMER;
+cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
+}
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 690eeea2e6..823951 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -235,12 +235,21 @@ static void loongarch_cpu_realizefn(DeviceState *dev, 
Error **errp)
 LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(dev);
 Error *local_err = NULL;
 
+#ifndef CONFIG_USER_ONLY
+LoongArchCPU *cpu = LOONGARCH_CPU(dev);
+#endif
+
 cpu_exec_realizefn(cs, _err);
 if (local_err != NULL) {
 error_propagate(errp, local_err);
 return;
 }
 
+#ifndef CONFIG_USER_ONLY
+timer_init_ns(>timer, QEMU_CLOCK_VIRTUAL,
+  _constant_timer_cb, cpu);
+#endif
+
 cpu_reset(cs);
 qemu_init_vcpu(cs);
 
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index cf7fc46f72..ef84584678 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -12,6 +12,7 @@
 #include "fpu/softfloat-types.h"
 #include "hw/registerfields.h"
 #include "cpu-csr.h"
+#include "qemu/timer.h"
 
 #define TCG_GUEST_DEFAULT_MO (0)
 
@@ -148,6 +149,9 @@ FIELD(CPUCFG20, L3IU_SIZE, 24, 7)
 extern const char * const regnames[32];
 extern const char * const fregnames[32];
 
+#define N_IRQS  14
+#define IRQ_TIMER   11
+
 typedef struct CPULoongArchState CPULoongArchState;
 struct CPULoongArchState {
 uint64_t gpr[32];
@@ -242,6 +246,7 @@ struct LoongArchCPU {
 
 CPUNegativeOffsetState neg;
 CPULoongArchState env;
+QEMUTimer timer; /* Internal timer */
 };
 
 #define TYPE_LOONGARCH_CPU "loongarch-cpu"
@@ -306,4 +311,9 @@ enum {
 #define LOONGARCH_CPU_TYPE_NAME(model) model LOONGARCH_CPU_TYPE_SUFFIX
 #define CPU_RESOLVING_TYPE TYPE_LOONGARCH_CPU
 
+void loongarch_constant_timer_cb(void *opaque);
+uint64_t cpu_loongarch_get_constant_timer_counter(LoongArchCPU *cpu);
+uint64_t cpu_loongarch_get_constant_timer_ticks(LoongArchCPU *cpu);
+void cpu_loongarch_store_constant_timer_config(LoongArchCPU *cpu,
+   uint64_t value);
 #endif /* LOONGARCH_CPU_H */
diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
index 103f36ee15..6168e910a0 100644
--- a/target/loongarch/meson.build
+++ b/target/loongarch/meson.build
@@ -17,6 +17,7 @@ loongarch_tcg_ss.add(zlib)
 loongarch_softmmu_ss = ss.source_set()
 loongarch_softmmu_ss.add(files(
   'machine.c',
+  'constant_timer.c',
 ))
 
 loongarch_ss.add_all(when: 'CONFIG_TCG', if_true: [loongarch_tcg_ss])
-- 
2.27.0




[RFC PATCH v4 12/30] target/loongarch: Add timer related instructions support.

2022-01-08 Thread Xiaojuan Yang
This includes:
-RDTIME{L/H}.W
-RDTIME.D

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 target/loongarch/helper.h |  1 +
 target/loongarch/insn_trans/trans_extra.c.inc | 32 +++
 target/loongarch/op_helper.c  |  6 
 target/loongarch/translate.c  |  2 ++
 4 files changed, 41 insertions(+)

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index c916f2650b..035bd141ed 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -116,4 +116,5 @@ DEF_HELPER_4(lddir, tl, env, tl, tl, i32)
 DEF_HELPER_4(ldpte, void, env, tl, tl, i32)
 DEF_HELPER_1(ertn, void, env)
 DEF_HELPER_1(idle, void, env)
+DEF_HELPER_1(rdtime_d, i64, env)
 #endif /* !CONFIG_USER_ONLY */
diff --git a/target/loongarch/insn_trans/trans_extra.c.inc 
b/target/loongarch/insn_trans/trans_extra.c.inc
index 2ce95d3382..8d3425ba61 100644
--- a/target/loongarch/insn_trans/trans_extra.c.inc
+++ b/target/loongarch/insn_trans/trans_extra.c.inc
@@ -33,22 +33,54 @@ static bool trans_asrtgt_d(DisasContext *ctx, arg_asrtgt_d 
* a)
 return true;
 }
 
+#ifndef CONFIG_USER_ONLY
+static bool gen_rdtime(DisasContext *ctx, arg_rr *a,
+   bool word, bool high)
+{
+TCGv dst1 = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv dst2 = gpr_dst(ctx, a->rj, EXT_NONE);
+
+if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
+gen_io_start();
+}
+gen_helper_rdtime_d(dst1, cpu_env);
+if (word) {
+tcg_gen_sextract_tl(dst1, dst1, high ? 32 : 0, 32);
+}
+tcg_gen_ld_i64(dst2, cpu_env, offsetof(CPULoongArchState, CSR_TID));
+
+return true;
+}
+#endif
+
 static bool trans_rdtimel_w(DisasContext *ctx, arg_rdtimel_w *a)
 {
+#ifdef CONFIG_USER_ONLY
 tcg_gen_movi_tl(cpu_gpr[a->rd], 0);
 return true;
+#else
+return gen_rdtime(ctx, a, 1, 0);
+#endif
 }
 
 static bool trans_rdtimeh_w(DisasContext *ctx, arg_rdtimeh_w *a)
 {
+#ifdef CONFIG_USER_ONLY
 tcg_gen_movi_tl(cpu_gpr[a->rd], 0);
 return true;
+#else
+return gen_rdtime(ctx, a, 1, 1);
+#endif
 }
 
 static bool trans_rdtime_d(DisasContext *ctx, arg_rdtime_d *a)
 {
+#ifdef CONFIG_USER_ONLY
 tcg_gen_movi_tl(cpu_gpr[a->rd], 0);
 return true;
+#else
+return gen_rdtime(ctx, a, 0, 0);
+#endif
 }
 
 static bool trans_cpucfg(DisasContext *ctx, arg_cpucfg *a)
diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c
index 6f9742054a..1d8b501ab9 100644
--- a/target/loongarch/op_helper.c
+++ b/target/loongarch/op_helper.c
@@ -133,4 +133,10 @@ void helper_idle(CPULoongArchState *env)
  */
 do_raise_exception(env, EXCP_HLT, 0);
 }
+
+uint64_t helper_rdtime_d(CPULoongArchState *env)
+{
+ LoongArchCPU *cpu = LOONGARCH_CPU(env_cpu(env));
+ return cpu_loongarch_get_constant_timer_counter(cpu);
+}
 #endif /* !CONFIG_USER_ONLY */
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index ddb97661fa..53a5ef3aa9 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -25,6 +25,8 @@ static TCGv cpu_lladdr, cpu_llval;
 TCGv_i32 cpu_fcsr0;
 TCGv_i64 cpu_fpr[32];
 
+#include "exec/gen-icount.h"
+
 #define DISAS_STOP   DISAS_TARGET_0
 #define DISAS_EXIT   DISAS_TARGET_1
 
-- 
2.27.0




[RFC PATCH v4 22/30] Enable common virtio pci support for LoongArch

2022-01-08 Thread Xiaojuan Yang
Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 softmmu/qdev-monitor.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c
index 01f3834db5..49491d74a1 100644
--- a/softmmu/qdev-monitor.c
+++ b/softmmu/qdev-monitor.c
@@ -60,7 +60,8 @@ typedef struct QDevAlias
   QEMU_ARCH_HPPA | QEMU_ARCH_I386 | \
   QEMU_ARCH_MIPS | QEMU_ARCH_PPC |  \
   QEMU_ARCH_RISCV | QEMU_ARCH_SH4 | \
-  QEMU_ARCH_SPARC | QEMU_ARCH_XTENSA)
+  QEMU_ARCH_SPARC | QEMU_ARCH_XTENSA | \
+  QEMU_ARCH_LOONGARCH)
 #define QEMU_ARCH_VIRTIO_CCW (QEMU_ARCH_S390X)
 #define QEMU_ARCH_VIRTIO_MMIO (QEMU_ARCH_M68K)
 
-- 
2.27.0




[RFC PATCH v4 01/30] target/loongarch: Update README

2022-01-08 Thread Xiaojuan Yang
Mainly introduce how to run the softmmu

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 target/loongarch/README | 25 +
 1 file changed, 25 insertions(+)

diff --git a/target/loongarch/README b/target/loongarch/README
index d5780c5918..337ba55f33 100644
--- a/target/loongarch/README
+++ b/target/loongarch/README
@@ -72,6 +72,31 @@
   ./qemu-loongarch64  /opt/clfs/usr/bin/pwd
   ...
 
+- Softmmu emulation
+
+  Add support softmmu emulation support in the following series patches.
+  Mainly emulate a virt 3A5000 board and ls7a bridge that is not exactly
+  the same as the host. Kernel code and uefi code is on the github.
+  All required binaries can get from github for test.
+
+  1.Download kernel and the cross-tools.(vmlinux)
+
+  https://github.com/loongson/linux/tree/loongarch-next
+  
https://github.com/loongson/build-tools/releases/latest/download/loongarch64-clfs-20211202-cross-tools.tar.xz
+
+  2.Download uefi code.(loongarch_bios.bin)
+
+  https://github.com/loongson/edk2/tree/LoongArch
+  https://github.com/loongson/edk2-platforms
+
+  3.Download the clfs-system and make a ramdisk with busybox.(ramdisk)
+
+  4.Run with command,eg:
+
+   ./build/qemu-system-loongarch64 -m 4G -smp 4 --cpu Loongson-3A5000 
--machine loongson3-ls7a -kernel ./vmlinux -initrd ./ramdisk  -append 
"root=/dev/ram console=ttyS0,115200 rdinit=/sbin/init loglevel=8" -monitor 
tcp::4000,server,nowait -nographic
+
+The vmlinux, ramdisk and uefi binary loongarch_bios.bin can get from :
+git clone https://github.com/yangxiaojuan-loongson/qemu-binary
 
 - Note.
   We can get the latest LoongArch documents or LoongArch tools at 
https://github.com/loongson/
-- 
2.27.0




[RFC PATCH v4 23/30] hw/loongarch: Add some devices support for 3A5000.

2022-01-08 Thread Xiaojuan Yang
1.Add uart,virtio-net,vga and usb for 3A5000.
2.Add irq set and map for the pci host. Non pci device
use irq 0-16, pci device use 16-64.
3.Add some unimplented device to emulate guest unused
memory space.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 hw/loongarch/Kconfig   |  7 
 hw/loongarch/loongson3.c   | 70 ++
 hw/pci-host/ls7a.c | 42 ++-
 include/hw/pci-host/ls7a.h |  5 +++
 4 files changed, 123 insertions(+), 1 deletion(-)

diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
index 468e3acc74..e607c84d21 100644
--- a/hw/loongarch/Kconfig
+++ b/hw/loongarch/Kconfig
@@ -1,5 +1,12 @@
 config LOONGSON3_LS7A
 bool
+imply VGA_PCI
+imply VIRTIO_VGA
+imply PCI_DEVICES
+select ISA_BUS
+select SERIAL
+select SERIAL_ISA
+select VIRTIO_PCI
 select PCI_EXPRESS_7A
 select LOONGARCH_IPI
 select LOONGARCH_PCH_PIC
diff --git a/hw/loongarch/loongson3.c b/hw/loongarch/loongson3.c
index cc7ee02003..85a4be0c7b 100644
--- a/hw/loongarch/loongson3.c
+++ b/hw/loongarch/loongson3.c
@@ -10,16 +10,20 @@
 #include "qemu/datadir.h"
 #include "qapi/error.h"
 #include "hw/boards.h"
+#include "hw/char/serial.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/qtest.h"
 #include "sysemu/runstate.h"
 #include "sysemu/reset.h"
+#include "hw/irq.h"
+#include "net/net.h"
 #include "hw/loongarch/loongarch.h"
 #include "hw/intc/loongarch_ipi.h"
 #include "hw/intc/loongarch_extioi.h"
 #include "hw/intc/loongarch_pch_pic.h"
 #include "hw/intc/loongarch_pch_msi.h"
 #include "hw/pci-host/ls7a.h"
+#include "hw/misc/unimp.h"
 
 static void loongarch_cpu_reset(void *opaque)
 {
@@ -97,6 +101,70 @@ static void loongarch_cpu_set_irq(void *opaque, int irq, 
int level)
 }
 }
 
+static void loongarch_devices_init(DeviceState *pch_pic)
+{
+DeviceState *pciehost;
+SysBusDevice *d;
+PCIBus *pci_bus;
+MemoryRegion *pio_alias;
+int i;
+
+pciehost = qdev_new(TYPE_LS7A_HOST_DEVICE);
+d = SYS_BUS_DEVICE(pciehost);
+sysbus_realize_and_unref(d, _fatal);
+pci_bus = PCI_HOST_BRIDGE(pciehost)->bus;
+
+/* Map pcie ecam space */
+memory_region_add_subregion(get_system_memory(), LS_PCIECFG_BASE,
+sysbus_mmio_get_region(d, 0));
+
+/* Map PCI IO port space. */
+pio_alias = g_new0(MemoryRegion, 1);
+memory_region_init_alias(pio_alias, OBJECT(pciehost), "ls7a-pci-io",
+ sysbus_mmio_get_region(d, 1),
+ LS7A_PCI_IO_OFFSET, LS7A_PCI_IO_SIZE);
+memory_region_add_subregion(get_system_memory(), LS7A_PCI_IO_BASE,
+pio_alias);
+
+/* Map PCI mem space */
+memory_region_add_subregion(get_system_memory(), 0,
+sysbus_mmio_get_region(d, 2));
+
+/* Map PCI conf space */
+memory_region_add_subregion(get_system_memory(), HT1LO_PCICFG_BASE,
+sysbus_mmio_get_region(d, 3));
+
+/* Connect 48 pci irqs to pch_pic */
+for (i = 0; i < LS7A_PCI_IRQS; i++) {
+qdev_connect_gpio_out(pciehost, i,
+  qdev_get_gpio_in(pch_pic, i + LS7A_DEVICE_IRQS));
+}
+
+serial_mm_init(get_system_memory(), LS7A_UART_BASE, 0,
+   qdev_get_gpio_in(pch_pic, LS7A_UART_IRQ - 
PCH_PIC_IRQ_OFFSET),
+   115200, serial_hd(0), DEVICE_LITTLE_ENDIAN);
+
+/* Network init */
+for (i = 0; i < nb_nics; i++) {
+NICInfo *nd = _table[i];
+
+if (!nd->model) {
+nd->model = g_strdup("virtio");
+}
+
+pci_nic_init_nofail(nd, pci_bus, nd->model, NULL);
+}
+
+/* VGA setup */
+pci_vga_init(pci_bus);
+
+/*
+ * There are some invalid guest memory access.
+ * Create some unimplemented devices to emulate this.
+ */
+create_unimplemented_device("pci-dma-cfg", 0x1001041c, 0x4);
+}
+
 static void loongarch_irq_init(LoongArchMachineState *lams)
 {
 MachineState *ms = MACHINE(lams);
@@ -173,6 +241,8 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
 sysbus_connect_irq(d, i,
qdev_get_gpio_in(extioi, i + PCH_MSI_IRQ_START));
 }
+
+loongarch_devices_init(pch_pic);
 }
 
 static void loongarch_init(MachineState *machine)
diff --git a/hw/pci-host/ls7a.c b/hw/pci-host/ls7a.c
index eb16b669bb..c1e08e2356 100644
--- a/hw/pci-host/ls7a.c
+++ b/hw/pci-host/ls7a.c
@@ -28,6 +28,41 @@ static const VMStateDescription vmstate_ls7a_pcie = {
 }
 };
 
+static PCIINTxRoute ls7a_route_intx_pin_to_irq(void *opaque, int pin)
+{
+PCIINTxRoute route;
+
+route.irq = pin;
+route.mode = PCI_INTX_ENABLED;
+return route;
+}
+
+sta

[RFC PATCH v4 19/30] hw/intc: Add LoongArch ls7a msi interrupt controller support(PCH-MSI)

2022-01-08 Thread Xiaojuan Yang
This patch realize PCH-MSI interrupt controller.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 hw/intc/Kconfig |  5 ++
 hw/intc/loongarch_pch_msi.c | 75 +
 hw/intc/meson.build |  1 +
 hw/intc/trace-events|  3 ++
 hw/loongarch/Kconfig|  1 +
 include/hw/intc/loongarch_pch_msi.h | 21 
 6 files changed, 106 insertions(+)
 create mode 100644 hw/intc/loongarch_pch_msi.c
 create mode 100644 include/hw/intc/loongarch_pch_msi.h

diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
index 928db92bb4..727a3bb3e6 100644
--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -85,3 +85,8 @@ config LOONGARCH_IPI
 config LOONGARCH_PCH_PIC
 bool
 select UNIMP
+
+config LOONGARCH_PCH_MSI
+select MSI_NONBROKEN
+bool
+select UNIMP
diff --git a/hw/intc/loongarch_pch_msi.c b/hw/intc/loongarch_pch_msi.c
new file mode 100644
index 00..57a894f3e5
--- /dev/null
+++ b/hw/intc/loongarch_pch_msi.c
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU Loongson 7A1000 msi interrupt controller.
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "hw/intc/loongarch_pch_msi.h"
+#include "hw/intc/loongarch_pch_pic.h"
+#include "hw/pci/msi.h"
+#include "hw/misc/unimp.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+
+static uint64_t loongarch_msi_mem_read(void *opaque, hwaddr addr, unsigned 
size)
+{
+return 0;
+}
+
+static void loongarch_msi_mem_write(void *opaque, hwaddr addr,
+uint64_t val, unsigned size)
+{
+LoongArchPCHMSI *s = LOONGARCH_PCH_MSI(opaque);
+int irq_num = val & 0xff;
+
+trace_loongarch_msi_set_irq(irq_num);
+qemu_set_irq(s->pch_msi_irq[irq_num - PCH_PIC_IRQ_NUM], 1);
+}
+
+static const MemoryRegionOps loongarch_pch_msi_ops = {
+.read  = loongarch_msi_mem_read,
+.write = loongarch_msi_mem_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void pch_msi_irq_handler(void *opaque, int irq, int level)
+{
+LoongArchPCHMSI *s = LOONGARCH_PCH_MSI(opaque);
+
+qemu_set_irq(s->pch_msi_irq[irq], level);
+}
+
+static void loongarch_pch_msi_init(Object *obj)
+{
+LoongArchPCHMSI *s = LOONGARCH_PCH_MSI(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+int i;
+
+memory_region_init_io(>msi_mmio, obj, _pch_msi_ops,
+  s, TYPE_LOONGARCH_PCH_MSI, 0x8);
+sysbus_init_mmio(sbd, >msi_mmio);
+msi_nonbroken = true;
+
+for (i = 0; i < PCH_MSI_IRQ_NUM; i++) {
+sysbus_init_irq(sbd, >pch_msi_irq[i]);
+}
+qdev_init_gpio_in(DEVICE(obj), pch_msi_irq_handler, PCH_MSI_IRQ_NUM);
+}
+
+static const TypeInfo loongarch_pch_msi_info = {
+.name  = TYPE_LOONGARCH_PCH_MSI,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(LoongArchPCHMSI),
+.instance_init = loongarch_pch_msi_init,
+};
+
+static void loongarch_pch_msi_register_types(void)
+{
+type_register_static(_pch_msi_info);
+}
+
+type_init(loongarch_pch_msi_register_types)
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
index cf08816547..c679223420 100644
--- a/hw/intc/meson.build
+++ b/hw/intc/meson.build
@@ -62,3 +62,4 @@ specific_ss.add(when: 'CONFIG_GOLDFISH_PIC', if_true: 
files('goldfish_pic.c'))
 specific_ss.add(when: 'CONFIG_M68K_IRQC', if_true: files('m68k_irqc.c'))
 specific_ss.add(when: 'CONFIG_LOONGARCH_IPI', if_true: 
files('loongarch_ipi.c'))
 specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_PIC', if_true: 
files('loongarch_pch_pic.c'))
+specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_MSI', if_true: 
files('loongarch_pch_msi.c'))
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index ec42cfd3d5..6d2d041766 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -257,3 +257,6 @@ loongarch_pch_pic_readw(unsigned size, uint32_t addr, 
unsigned long val) "size:
 loongarch_pch_pic_writew(unsigned size, uint32_t addr, unsigned long val) 
"size: %u addr: 0x%"PRIx32 "val: 0x%" PRIx64
 loongarch_pch_pic_readb(unsigned size, uint32_t addr, unsigned long val) 
"size: %u addr: 0x%"PRIx32 "val: 0x%" PRIx64
 loongarch_pch_pic_writeb(unsigned size, uint32_t addr, unsigned long val) 
"size: %u addr: 0x%"PRIx32 "val: 0x%" PRIx64
+
+# loongarch_pch_msi.c
+loongarch_msi_set_irq(int irq_num) "set msi irq %d"
diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
index c2b8046b94..cd38d03a19 100644
--- a/hw/loongarch/Kconfig
+++ b/hw/loongarch/Kconfig
@@ -3,3 +3,4 @@ config LOONGSON3_LS7A
 select PCI_EXPRESS_7A
 select LOONGARCH_IPI
 select LOONGARCH_PCH_PIC
+select LOONGARCH_PCH_MSI
diff --git a/include/hw/intc/loongarch_pch_msi.h 
b/include/

[RFC PATCH v4 28/30] hw/loongarch: Add LoongArch acpi support

2022-01-08 Thread Xiaojuan Yang
Add a simple acpi model for LoongArch cpu
More complex functions will be added later

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 hw/acpi/Kconfig  |   4 +
 hw/acpi/ls7a.c   | 374 ++
 hw/acpi/meson.build  |   1 +
 hw/loongarch/Kconfig |   2 +
 hw/loongarch/acpi-build.c| 636 +++
 hw/loongarch/loongson3.c |  62 ++-
 hw/loongarch/meson.build |   1 +
 include/hw/acpi/ls7a.h   |  53 +++
 include/hw/loongarch/loongarch.h |   6 +
 include/hw/pci-host/ls7a.h   |   5 +
 10 files changed, 1142 insertions(+), 2 deletions(-)
 create mode 100644 hw/acpi/ls7a.c
 create mode 100644 hw/loongarch/acpi-build.c
 create mode 100644 include/hw/acpi/ls7a.h

diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig
index 622b0b50b7..30f887d479 100644
--- a/hw/acpi/Kconfig
+++ b/hw/acpi/Kconfig
@@ -11,6 +11,10 @@ config ACPI_X86
 select ACPI_PIIX4
 select ACPI_PCIHP
 
+config ACPI_LOONGARCH
+bool
+select ACPI
+
 config ACPI_X86_ICH
 bool
 select ACPI_X86
diff --git a/hw/acpi/ls7a.c b/hw/acpi/ls7a.c
new file mode 100644
index 00..cc658422dd
--- /dev/null
+++ b/hw/acpi/ls7a.c
@@ -0,0 +1,374 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch ACPI implementation
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "sysemu/sysemu.h"
+#include "hw/hw.h"
+#include "hw/irq.h"
+#include "sysemu/reset.h"
+#include "sysemu/runstate.h"
+#include "hw/acpi/acpi.h"
+#include "hw/acpi/ls7a.h"
+#include "hw/nvram/fw_cfg.h"
+#include "qemu/config-file.h"
+#include "qapi/opts-visitor.h"
+#include "qapi/qapi-events-run-state.h"
+#include "qapi/error.h"
+#include "hw/pci-host/ls7a.h"
+#include "hw/mem/pc-dimm.h"
+#include "hw/mem/nvdimm.h"
+#include "migration/vmstate.h"
+
+static void ls7a_pm_update_sci_fn(ACPIREGS *regs)
+{
+LS7APMState *pm = container_of(regs, LS7APMState, acpi_regs);
+acpi_update_sci(>acpi_regs, pm->irq);
+}
+
+static uint64_t ls7a_gpe_readb(void *opaque, hwaddr addr, unsigned width)
+{
+LS7APMState *pm = opaque;
+return acpi_gpe_ioport_readb(>acpi_regs, addr);
+}
+
+static void ls7a_gpe_writeb(void *opaque, hwaddr addr, uint64_t val,
+unsigned width)
+{
+LS7APMState *pm = opaque;
+acpi_gpe_ioport_writeb(>acpi_regs, addr, val);
+acpi_update_sci(>acpi_regs, pm->irq);
+}
+
+static const MemoryRegionOps ls7a_gpe_ops = {
+.read = ls7a_gpe_readb,
+.write = ls7a_gpe_writeb,
+.valid.min_access_size = 1,
+.valid.max_access_size = 8,
+.impl.min_access_size = 1,
+.impl.max_access_size = 1,
+.endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+#define VMSTATE_GPE_ARRAY(_field, _state)\
+ {   \
+ .name   = (stringify(_field)),  \
+ .version_id = 0,\
+ .num= ACPI_GPE0_LEN,\
+ .info   = _info_uint8,  \
+ .size   = sizeof(uint8_t),  \
+ .flags  = VMS_ARRAY | VMS_POINTER,  \
+ .offset = vmstate_offset_pointer(_state, _field, uint8_t),  \
+ }
+
+static uint64_t ls7a_reset_readw(void *opaque, hwaddr addr, unsigned width)
+{
+return 0;
+}
+
+static void ls7a_reset_writew(void *opaque, hwaddr addr, uint64_t val,
+  unsigned width)
+{
+if (val & 1) {
+qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
+return;
+}
+}
+
+static const MemoryRegionOps ls7a_reset_ops = {
+.read = ls7a_reset_readw,
+.write = ls7a_reset_writew,
+.valid.min_access_size = 4,
+.valid.max_access_size = 4,
+.endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+const VMStateDescription vmstate_ls7a_pm = {
+.name = "ls7a_pm",
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT16(acpi_regs.pm1.evt.sts, LS7APMState),
+VMSTATE_UINT16(acpi_regs.pm1.evt.en, LS7APMState),
+VMSTATE_UINT16(acpi_regs.pm1.cnt.cnt, LS7APMState),
+VMSTATE_TIMER_PTR(acpi_regs.tmr.timer, LS7APMState),
+VMSTATE_INT64(acpi_regs.tmr.overflow_time, LS7APMState),
+VMSTATE_GPE_ARRAY(acpi_regs.gpe.sts, LS7APMState),
+VMSTATE_GPE_ARRAY(acpi_regs.gpe.en, LS7APMState),
+VMSTATE_END_OF_LIST()
+},
+};
+
+static inline int64_t acpi_pm_tmr_get_clock(void)
+{
+return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), PM_TIMER_FREQUENCY,
+NANOSECONDS_PER_SECOND);
+

[PATCH v1 02/43] target/loongarch: Add core definition

2022-04-15 Thread Xiaojuan Yang
From: Song Gao 

This patch adds target state header, target definitions
and initialization routines.

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 target/loongarch/cpu-param.h |  18 ++
 target/loongarch/cpu.c   | 324 +++
 target/loongarch/cpu.h   | 243 ++
 target/loongarch/internals.h |  21 +++
 4 files changed, 606 insertions(+)
 create mode 100644 target/loongarch/cpu-param.h
 create mode 100644 target/loongarch/cpu.c
 create mode 100644 target/loongarch/cpu.h
 create mode 100644 target/loongarch/internals.h

diff --git a/target/loongarch/cpu-param.h b/target/loongarch/cpu-param.h
new file mode 100644
index 00..9a769b67e0
--- /dev/null
+++ b/target/loongarch/cpu-param.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch CPU parameters for QEMU.
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef LOONGARCH_CPU_PARAM_H
+#define LOONGARCH_CPU_PARAM_H
+
+#define TARGET_LONG_BITS 64
+#define TARGET_PHYS_ADDR_SPACE_BITS 48
+#define TARGET_VIRT_ADDR_SPACE_BITS 48
+
+#define TARGET_PAGE_BITS 14
+#define NB_MMU_MODES 4
+
+#endif
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
new file mode 100644
index 00..f4cde31600
--- /dev/null
+++ b/target/loongarch/cpu.c
@@ -0,0 +1,324 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch CPU
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/qemu-print.h"
+#include "qapi/error.h"
+#include "qemu/module.h"
+#include "sysemu/qtest.h"
+#include "exec/exec-all.h"
+#include "qapi/qapi-commands-machine-target.h"
+#include "cpu.h"
+#include "internals.h"
+#include "fpu/softfloat-helpers.h"
+
+const char * const regnames[32] = {
+"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+};
+
+const char * const fregnames[32] = {
+"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
+};
+
+static const char * const excp_names[] = {
+[EXCCODE_INT] = "Interrupt",
+[EXCCODE_PIL] = "Page invalid exception for load",
+[EXCCODE_PIS] = "Page invalid exception for store",
+[EXCCODE_PIF] = "Page invalid exception for fetch",
+[EXCCODE_PME] = "Page modified exception",
+[EXCCODE_PNR] = "Page Not Readable exception",
+[EXCCODE_PNX] = "Page Not Executable exception",
+[EXCCODE_PPI] = "Page Privilege error",
+[EXCCODE_ADEF] = "Address error for instruction fetch",
+[EXCCODE_ADEM] = "Address error for Memory access",
+[EXCCODE_SYS] = "Syscall",
+[EXCCODE_BRK] = "Break",
+[EXCCODE_INE] = "Instruction Non-Existent",
+[EXCCODE_IPE] = "Instruction privilege error",
+[EXCCODE_FPE] = "Floating Point Exception",
+[EXCCODE_DBP] = "Debug breakpoint",
+};
+
+const char *loongarch_exception_name(int32_t exception)
+{
+assert(excp_names[exception]);
+return excp_names[exception];
+}
+
+void QEMU_NORETURN do_raise_exception(CPULoongArchState *env,
+  uint32_t exception,
+  uintptr_t pc)
+{
+CPUState *cs = env_cpu(env);
+
+qemu_log_mask(CPU_LOG_INT, "%s: %d (%s)\n",
+  __func__,
+  exception,
+  loongarch_exception_name(exception));
+cs->exception_index = exception;
+
+cpu_loop_exit_restore(cs, pc);
+}
+
+static void loongarch_cpu_set_pc(CPUState *cs, vaddr value)
+{
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+CPULoongArchState *env = >env;
+
+env->pc = value;
+}
+
+#ifdef CONFIG_TCG
+stat

[PATCH v1 08/43] target/loongarch: Add fixed point atomic instruction translation

2022-04-15 Thread Xiaojuan Yang
From: Song Gao 

This includes:
- LL.{W/D}, SC.{W/D}
- AM{SWAP/ADD/AND/OR/XOR/MAX/MIN}[_DB].{W/D}
- AM{MAX/MIN}[_DB].{WU/DU}

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 .../loongarch/insn_trans/trans_atomic.c.inc   | 114 ++
 .../loongarch/insn_trans/trans_memory.c.inc   |   2 +-
 target/loongarch/insns.decode |  44 +++
 target/loongarch/translate.c  |   1 +
 4 files changed, 160 insertions(+), 1 deletion(-)
 create mode 100644 target/loongarch/insn_trans/trans_atomic.c.inc

diff --git a/target/loongarch/insn_trans/trans_atomic.c.inc 
b/target/loongarch/insn_trans/trans_atomic.c.inc
new file mode 100644
index 00..1e5bd1afe2
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_atomic.c.inc
@@ -0,0 +1,114 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static bool gen_ll(DisasContext *ctx, arg_rr_i *a,
+   void (*func)(TCGv, TCGv, int))
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv t0 = tcg_temp_new();
+
+tcg_gen_addi_tl(t0, src1, a->imm);
+func(dest, t0, ctx->mem_idx);
+tcg_gen_st_tl(t0, cpu_env, offsetof(CPULoongArchState, lladdr));
+tcg_gen_st_tl(dest, cpu_env, offsetof(CPULoongArchState, llval));
+gen_set_gpr(a->rd, dest, EXT_NONE);
+tcg_temp_free(t0);
+
+return true;
+}
+
+static bool gen_sc(DisasContext *ctx, arg_rr_i *a, MemOp mop)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rd, EXT_NONE);
+TCGv t0 = tcg_temp_new();
+TCGv val = tcg_temp_new();
+
+TCGLabel *l1 = gen_new_label();
+TCGLabel *done = gen_new_label();
+
+tcg_gen_addi_tl(t0, src1, a->imm);
+tcg_gen_brcond_tl(TCG_COND_EQ, t0, cpu_lladdr, l1);
+tcg_gen_movi_tl(dest, 0);
+tcg_gen_br(done);
+
+gen_set_label(l1);
+tcg_gen_mov_tl(val, src2);
+/* generate cmpxchg */
+tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval,
+  val, ctx->mem_idx, mop);
+tcg_gen_setcond_tl(TCG_COND_EQ, dest, t0, cpu_llval);
+gen_set_label(done);
+gen_set_gpr(a->rd, dest, EXT_NONE);
+tcg_temp_free(t0);
+tcg_temp_free(val);
+
+return true;
+}
+
+static bool gen_am(DisasContext *ctx, arg_rrr *a,
+   void (*func)(TCGv, TCGv, TCGv, TCGArg, MemOp),
+   MemOp mop)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv val = gpr_src(ctx, a->rk, EXT_NONE);
+
+if (a->rd != 0 && (a->rj == a->rd || a->rk == a->rd)) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "Warning: source register overlaps destination register"
+  "in atomic insn at pc=0x" TARGET_FMT_lx "\n",
+  ctx->base.pc_next - 4);
+return false;
+}
+
+func(dest, addr, val, ctx->mem_idx, mop);
+gen_set_gpr(a->rd, dest, EXT_NONE);
+
+return true;
+}
+
+TRANS(ll_w, gen_ll, tcg_gen_qemu_ld32s)
+TRANS(sc_w, gen_sc, MO_TESL)
+TRANS(ll_d, gen_ll, tcg_gen_qemu_ld64)
+TRANS(sc_d, gen_sc, MO_TEUQ)
+TRANS(amswap_w, gen_am, tcg_gen_atomic_xchg_tl, MO_TESL)
+TRANS(amswap_d, gen_am, tcg_gen_atomic_xchg_tl, MO_TEUQ)
+TRANS(amadd_w, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TESL)
+TRANS(amadd_d, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TEUQ)
+TRANS(amand_w, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TESL)
+TRANS(amand_d, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TEUQ)
+TRANS(amor_w, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TESL)
+TRANS(amor_d, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TEUQ)
+TRANS(amxor_w, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TESL)
+TRANS(amxor_d, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TEUQ)
+TRANS(ammax_w, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TESL)
+TRANS(ammax_d, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TEUQ)
+TRANS(ammin_w, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TESL)
+TRANS(ammin_d, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TEUQ)
+TRANS(ammax_wu, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TESL)
+TRANS(ammax_du, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TEUQ)
+TRANS(ammin_wu, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TESL)
+TRANS(ammin_du, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TEUQ)
+TRANS(amswap_db_w, gen_am, tcg_gen_atomic_xchg_tl, MO_TESL)
+TRANS(amswap_db_d, gen_am, tcg_gen_atomic_xchg_tl, MO_TEUQ)
+TRANS(amadd_db_w, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TESL)
+TRANS(amadd_db_d, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TEUQ)
+TRANS(amand_db_w, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TESL)
+TRANS(amand_db_d, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TEUQ)
+TRANS(amor_db_w, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TESL)
+TRANS(amor_db_d, gen_am, tcg_gen_atomic_fetch_or

[PATCH v1 27/43] target/loongarch: Add TLB instruction support

2022-04-15 Thread Xiaojuan Yang
This includes:
- TLBSRCH
- TLBRD
- TLBWR
- TLBFILL
- TLBCLR
- TLBFLUSH
- INVTLB

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 target/loongarch/disas.c  |  18 +
 target/loongarch/helper.h |  13 +
 .../insn_trans/trans_privileged.c.inc | 101 +
 target/loongarch/insns.decode |  11 +
 target/loongarch/tlb_helper.c | 358 ++
 5 files changed, 501 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 9cc39e7817..4ade829637 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -217,6 +217,17 @@ static void output_rr_csr(DisasContext *ctx, arg_rr_csr *a,
 output(ctx, mnemonic, "r%d, r%d, %d", a->rd, a->rj, a->csr);
 }
 
+static void output_empty(DisasContext *ctx, arg_empty *a,
+ const char *mnemonic)
+{
+output(ctx, mnemonic, "");
+}
+
+static void output_i_rr(DisasContext *ctx, arg_i_rr *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "%d, r%d, r%d", a->imm, a->rj, a->rk);
+}
+
 #define INSN(insn, type)\
 static bool trans_##insn(DisasContext *ctx, arg_##type * a) \
 {   \
@@ -537,6 +548,13 @@ INSN(iocsrwr_b,rr)
 INSN(iocsrwr_h,rr)
 INSN(iocsrwr_w,rr)
 INSN(iocsrwr_d,rr)
+INSN(tlbsrch,  empty)
+INSN(tlbrd,empty)
+INSN(tlbwr,empty)
+INSN(tlbfill,  empty)
+INSN(tlbclr,   empty)
+INSN(tlbflush, empty)
+INSN(invtlb,   i_rr)
 
 #define output_fcmp(C, PREFIX, SUFFIX) 
\
 {  
\
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index e99a714bb4..63ae687749 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -103,3 +103,16 @@ DEF_HELPER_2(csrwr_ticlr, i64, env, tl)
 DEF_HELPER_3(csr_update, void, env, tl, i64)
 DEF_HELPER_3(iocsr_read, i64, env, tl, i32)
 DEF_HELPER_4(iocsr_write, void, env, tl, tl, i32)
+
+/* TLB helper */
+DEF_HELPER_1(tlbwr, void, env)
+DEF_HELPER_1(tlbfill, void, env)
+DEF_HELPER_1(tlbsrch, void, env)
+DEF_HELPER_1(tlbrd, void, env)
+DEF_HELPER_1(tlbclr, void, env)
+DEF_HELPER_1(tlbflush, void, env)
+DEF_HELPER_1(invtlb_all, void, env)
+DEF_HELPER_2(invtlb_all_g, void, env, i32)
+DEF_HELPER_2(invtlb_all_asid, void, env, tl)
+DEF_HELPER_3(invtlb_page_asid, void, env, tl, tl)
+DEF_HELPER_3(invtlb_page_asid_or_g, void, env, tl, tl)
diff --git a/target/loongarch/insn_trans/trans_privileged.c.inc 
b/target/loongarch/insn_trans/trans_privileged.c.inc
index 6b8b79cd1c..67adcecf73 100644
--- a/target/loongarch/insn_trans/trans_privileged.c.inc
+++ b/target/loongarch/insn_trans/trans_privileged.c.inc
@@ -271,3 +271,104 @@ static bool trans_iocsrwr_d(DisasContext *ctx, 
arg_iocsrwr_d *a)
 gen_helper_iocsr_write(cpu_env, addr, val, tcg_constant_i32(8));
 return true;
 }
+
+static void check_mmu_idx(DisasContext *ctx)
+{
+if (ctx->mem_idx != MMU_DA_IDX) {
+gen_disas_exit(ctx);
+}
+}
+
+static bool trans_tlbsrch(DisasContext *ctx, arg_tlbsrch *a)
+{
+if (check_plv(ctx)) {
+return false;
+}
+gen_helper_tlbsrch(cpu_env);
+return true;
+}
+
+static bool trans_tlbrd(DisasContext *ctx, arg_tlbrd *a)
+{
+if (check_plv(ctx)) {
+return false;
+}
+gen_helper_tlbrd(cpu_env);
+return true;
+}
+
+static bool trans_tlbwr(DisasContext *ctx, arg_tlbwr *a)
+{
+if (check_plv(ctx)) {
+return false;
+}
+gen_helper_tlbwr(cpu_env);
+check_mmu_idx(ctx);
+return true;
+}
+
+static bool trans_tlbfill(DisasContext *ctx, arg_tlbfill *a)
+{
+if (check_plv(ctx)) {
+return false;
+}
+gen_helper_tlbfill(cpu_env);
+check_mmu_idx(ctx);
+return true;
+}
+
+static bool trans_tlbclr(DisasContext *ctx, arg_tlbclr *a)
+{
+if (check_plv(ctx)) {
+return false;
+}
+gen_helper_tlbclr(cpu_env);
+check_mmu_idx(ctx);
+return true;
+}
+
+static bool trans_tlbflush(DisasContext *ctx, arg_tlbflush *a)
+{
+if (check_plv(ctx)) {
+return false;
+}
+gen_helper_tlbflush(cpu_env);
+check_mmu_idx(ctx);
+return true;
+}
+
+static bool trans_invtlb(DisasContext *ctx, arg_invtlb *a)
+{
+TCGv rj = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv rk = gpr_src(ctx, a->rk, EXT_NONE);
+
+if (check_plv(ctx)) {
+return false;
+}
+
+switch (a->imm) {
+case 0:
+case 1:
+gen_helper_invtlb_all(cpu_env);
+break;
+case 2:
+gen_helper_invtlb_all_g(cpu_env, tcg_constant_i32(1));
+break;
+case 3:
+gen_helper_invtlb_all_g(cpu_env, tcg_constant_i32(0));
+break;
+case 4:
+gen_helper_invtlb_all_asid(cpu_env, rj);
+break;
+case 5:
+gen_helper_in

[PATCH v1 03/43] target/loongarch: Add main translation routines

2022-04-15 Thread Xiaojuan Yang
From: Song Gao 

This patch adds main translation routines and
basic functions for translation.

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 target/loongarch/helper.h|   6 ++
 target/loongarch/op_helper.c |  21 +
 target/loongarch/translate.c | 159 +++
 target/loongarch/translate.h |  26 ++
 4 files changed, 212 insertions(+)
 create mode 100644 target/loongarch/helper.h
 create mode 100644 target/loongarch/op_helper.c
 create mode 100644 target/loongarch/translate.c
 create mode 100644 target/loongarch/translate.h

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
new file mode 100644
index 00..eb771c0628
--- /dev/null
+++ b/target/loongarch/helper.h
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+DEF_HELPER_2(raise_exception, noreturn, env, i32)
diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c
new file mode 100644
index 00..903810951e
--- /dev/null
+++ b/target/loongarch/op_helper.c
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch emulation helpers for QEMU.
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/main-loop.h"
+#include "cpu.h"
+#include "qemu/host-utils.h"
+#include "exec/helper-proto.h"
+#include "exec/exec-all.h"
+#include "exec/cpu_ldst.h"
+#include "internals.h"
+
+/* Exceptions helpers */
+void helper_raise_exception(CPULoongArchState *env, uint32_t exception)
+{
+do_raise_exception(env, exception, GETPC());
+}
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
new file mode 100644
index 00..8fa50d56cb
--- /dev/null
+++ b/target/loongarch/translate.c
@@ -0,0 +1,159 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch emulation for QEMU - main translation routines.
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "tcg/tcg-op.h"
+#include "exec/translator.h"
+#include "exec/helper-proto.h"
+#include "exec/helper-gen.h"
+
+#include "exec/translator.h"
+#include "exec/log.h"
+#include "qemu/qemu-print.h"
+#include "translate.h"
+#include "internals.h"
+
+/* Global register indices */
+TCGv cpu_gpr[32], cpu_pc;
+static TCGv cpu_lladdr, cpu_llval;
+TCGv_i32 cpu_fcsr0;
+TCGv_i64 cpu_fpr[32];
+
+#define DISAS_STOP   DISAS_TARGET_0
+
+void generate_exception(DisasContext *ctx, int excp)
+{
+tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
+gen_helper_raise_exception(cpu_env, tcg_constant_i32(excp));
+ctx->base.is_jmp = DISAS_NORETURN;
+}
+
+static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
+{
+if (translator_use_goto_tb(>base, dest)) {
+tcg_gen_goto_tb(n);
+tcg_gen_movi_tl(cpu_pc, dest);
+tcg_gen_exit_tb(ctx->base.tb, n);
+} else {
+tcg_gen_movi_tl(cpu_pc, dest);
+tcg_gen_lookup_and_goto_ptr();
+}
+}
+
+static void loongarch_tr_init_disas_context(DisasContextBase *dcbase,
+CPUState *cs)
+{
+int64_t bound;
+DisasContext *ctx = container_of(dcbase, DisasContext, base);
+
+ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
+ctx->mem_idx = ctx->base.tb->flags;
+
+/* Bound the number of insns to execute to those left on the page.  */
+bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4;
+ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
+}
+
+static void loongarch_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
+{
+}
+
+static void loongarch_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
+{
+DisasContext *ctx = container_of(dcbase, DisasContext, base);
+
+tcg_gen_insn_start(ctx->base.pc_next);
+}
+
+static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
+{
+CPULoongArchState *env = cs->env_ptr;
+DisasContext *ctx = container_of(dcbase, DisasContext, base);
+
+ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
+
+if (!decode(ctx, ctx->opcode)) {
+qemu_log_mask(LOG_UNIMP, "Error: unknown opcode. 0x%lx: 0x%x\n",
+  ctx->base.pc_next, ctx->opcode);
+generate_exception(ctx, EXCCODE_INE);
+}
+
+ctx->base.pc_next += 4;
+}
+
+static void loongarch_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
+{
+DisasContext *ctx = container_of(dcbase, DisasContext, base);
+
+switch (ctx->base.is_jmp) {
+case DISAS_STOP:
+tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
+tcg_gen_lookup_and_goto_ptr

[PATCH v1 16/43] target/loongarch: Add disassembler

2022-04-15 Thread Xiaojuan Yang
From: Song Gao 

This patch adds support for disassembling via option '-d in_asm'.

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 include/disas/dis-asm.h  |   2 +
 meson.build  |   1 +
 target/loongarch/disas.c | 610 +++
 3 files changed, 613 insertions(+)
 create mode 100644 target/loongarch/disas.c

diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h
index fadf6a65ef..a285063917 100644
--- a/include/disas/dis-asm.h
+++ b/include/disas/dis-asm.h
@@ -253,6 +253,7 @@ enum bfd_architecture
 #define bfd_mach_rx0x75
 #define bfd_mach_rx_v2 0x76
 #define bfd_mach_rx_v3 0x77
+  bfd_arch_loongarch,
   bfd_arch_last
   };
 #define bfd_mach_s390_31 31
@@ -462,6 +463,7 @@ int print_insn_riscv64  (bfd_vma, 
disassemble_info*);
 int print_insn_riscv128 (bfd_vma, disassemble_info*);
 int print_insn_rx(bfd_vma, disassemble_info *);
 int print_insn_hexagon(bfd_vma, disassemble_info *);
+int print_insn_loongarch(bfd_vma, disassemble_info *);
 
 #ifdef CONFIG_CAPSTONE
 bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size);
diff --git a/meson.build b/meson.build
index 861de93c4f..c0ac5639fa 100644
--- a/meson.build
+++ b/meson.build
@@ -2088,6 +2088,7 @@ disassemblers = {
   'sh4' : ['CONFIG_SH4_DIS'],
   'sparc' : ['CONFIG_SPARC_DIS'],
   'xtensa' : ['CONFIG_XTENSA_DIS'],
+  'loongarch' : ['CONFIG_LOONGARCH_DIS'],
 }
 if link_language == 'cpp'
   disassemblers += {
diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
new file mode 100644
index 00..9454ebb8e9
--- /dev/null
+++ b/target/loongarch/disas.c
@@ -0,0 +1,610 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch Disassembler
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited.
+ */
+
+#include "qemu/osdep.h"
+#include "disas/dis-asm.h"
+#include "qemu/bitops.h"
+
+typedef struct {
+disassemble_info *info;
+uint64_t pc;
+uint32_t insn;
+} DisasContext;
+
+static inline int plus_1(DisasContext *ctx, int x)
+{
+return x + 1;
+}
+
+static inline int shl_2(DisasContext *ctx, int x)
+{
+return x << 2;
+}
+
+#define output(C, INSN, FMT, ...)   \
+{   \
+(C)->info->fprintf_func((C)->info->stream, "%08x   %-9s\t" FMT, \
+(C)->insn, INSN, ##__VA_ARGS__);\
+}
+
+#include "decode-insns.c.inc"
+
+int print_insn_loongarch(bfd_vma memaddr, struct disassemble_info *info)
+{
+bfd_byte buffer[4];
+uint32_t insn;
+int status;
+
+status = (*info->read_memory_func)(memaddr, buffer, 4, info);
+if (status != 0) {
+(*info->memory_error_func)(status, memaddr, info);
+return -1;
+}
+insn = bfd_getl32(buffer);
+DisasContext ctx = {
+.info = info,
+.pc = memaddr,
+.insn = insn
+};
+
+if (!decode(, insn)) {
+output(, "illegal", "");
+}
+return 4;
+}
+
+static void output_r_i(DisasContext *ctx, arg_r_i *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "r%d, %d", a->rd, a->imm);
+}
+
+static void output_rrr(DisasContext *ctx, arg_rrr *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "r%d, r%d, r%d", a->rd, a->rj, a->rk);
+}
+
+static void output_rr_i(DisasContext *ctx, arg_rr_i *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "r%d, r%d, %d", a->rd, a->rj, a->imm);
+}
+
+static void output_rrr_sa(DisasContext *ctx, arg_rrr_sa *a,
+  const char *mnemonic)
+{
+output(ctx, mnemonic, "r%d, r%d, r%d, %d", a->rd, a->rj, a->rk, a->sa);
+}
+
+static void output_rr(DisasContext *ctx, arg_rr *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "r%d, r%d", a->rd, a->rj);
+}
+
+static void output_rr_ms_ls(DisasContext *ctx, arg_rr_ms_ls *a,
+  const char *mnemonic)
+{
+output(ctx, mnemonic, "r%d, r%d, %d, %d", a->rd, a->rj, a->ms, a->ls);
+}
+
+static void output_hint_r_i(DisasContext *ctx, arg_hint_r_i *a,
+const char *mnemonic)
+{
+output(ctx, mnemonic, "%d, r%d, %d", a->hint, a->rj, a->imm);
+}
+
+static void output_i(DisasContext *ctx, arg_i *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "%d", a->imm);
+}
+
+static void output_rr_jk(DisasContext *ctx, arg_rr_jk *a,
+ const char *mnemonic)
+{
+output(ctx, mnemonic, "r%d, r%d", a->rj, a->rk);
+}
+
+static void output_ff(DisasContext *ctx, arg_ff *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "f%d, f%d", a->fd, a->fj);
+}
+
+static void output_fff(DisasCont

[PATCH v1 12/43] target/loongarch: Add floating point conversion instruction translation

2022-04-15 Thread Xiaojuan Yang
From: Song Gao 

This includes:
- FCVT.S.D, FCVT.D.S
- FFINT.{S/D}.{W/L}, FTINT.{W/L}.{S/D}
- FTINT{RM/RP/RZ/RNE}.{W/L}.{S/D}
- FRINT.{S/D}

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 target/loongarch/fpu_helper.c| 393 +++
 target/loongarch/helper.h|  29 ++
 target/loongarch/insn_trans/trans_fcnv.c.inc |  33 ++
 target/loongarch/insns.decode|  32 ++
 target/loongarch/translate.c |   1 +
 5 files changed, 488 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_fcnv.c.inc

diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c
index 2ad707007a..d69a1dd80e 100644
--- a/target/loongarch/fpu_helper.c
+++ b/target/loongarch/fpu_helper.c
@@ -461,3 +461,396 @@ uint64_t helper_fcmp_s_d(CPULoongArchState *env, uint64_t 
fj,
 FloatRelation cmp = float64_compare(fj, fk, >fp_status);
 return fcmp_common(env, cmp, flags);
 }
+
+/* floating point conversion */
+uint64_t helper_fcvt_s_d(CPULoongArchState *env, uint64_t fj)
+{
+uint64_t fd;
+
+fd = nanbox_s(float64_to_float32(fj, >fp_status));
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_fcvt_d_s(CPULoongArchState *env, uint64_t fj)
+{
+uint64_t fd;
+
+fd = float32_to_float64((uint32_t)fj, >fp_status);
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_ffint_s_w(CPULoongArchState *env, uint64_t fj)
+{
+uint64_t fd;
+
+fd = nanbox_s(int32_to_float32((int32_t)fj, >fp_status));
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_ffint_s_l(CPULoongArchState *env, uint64_t fj)
+{
+uint64_t fd;
+
+fd = nanbox_s(int64_to_float32(fj, >fp_status));
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_ffint_d_w(CPULoongArchState *env, uint64_t fj)
+{
+uint64_t fd;
+
+fd = int32_to_float64((int32_t)fj, >fp_status);
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_ffint_d_l(CPULoongArchState *env, uint64_t fj)
+{
+uint64_t fd;
+
+fd = int64_to_float64(fj, >fp_status);
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_frint_s(CPULoongArchState *env, uint64_t fj)
+{
+uint64_t fd;
+
+fd = (uint64_t)(float32_round_to_int((uint32_t)fj, >fp_status));
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_frint_d(CPULoongArchState *env, uint64_t fj)
+{
+uint64_t fd;
+
+fd = float64_round_to_int(fj, >fp_status);
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_ftintrm_l_d(CPULoongArchState *env, uint64_t fj)
+{
+uint64_t fd;
+FloatRoundMode old_mode = get_float_rounding_mode(>fp_status);
+
+set_float_rounding_mode(float_round_down, >fp_status);
+fd = float64_to_int64(fj, >fp_status);
+set_float_rounding_mode(old_mode, >fp_status);
+
+if (get_float_exception_flags(>fp_status) &
+(float_flag_invalid | float_flag_overflow)) {
+fd = FLOAT_TO_INT64_OVERFLOW;
+}
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_ftintrm_l_s(CPULoongArchState *env, uint64_t fj)
+{
+uint64_t fd;
+FloatRoundMode old_mode = get_float_rounding_mode(>fp_status);
+
+set_float_rounding_mode(float_round_down, >fp_status);
+fd = float32_to_int64((uint32_t)fj, >fp_status);
+set_float_rounding_mode(old_mode, >fp_status);
+
+if (get_float_exception_flags(>fp_status) &
+(float_flag_invalid | float_flag_overflow)) {
+fd = FLOAT_TO_INT64_OVERFLOW;
+}
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_ftintrm_w_d(CPULoongArchState *env, uint64_t fj)
+{
+uint64_t fd;
+FloatRoundMode old_mode = get_float_rounding_mode(>fp_status);
+
+set_float_rounding_mode(float_round_down, >fp_status);
+fd = (uint64_t)float64_to_int32(fj, >fp_status);
+set_float_rounding_mode(old_mode, >fp_status);
+
+if (get_float_exception_flags(>fp_status) &
+(float_flag_invalid | float_flag_overflow)) {
+fd = FLOAT_TO_INT32_OVERFLOW;
+}
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_ftintrm_w_s(CPULoongArchState *env, uint64_t fj)
+{
+uint64_t fd;
+FloatRoundMode old_mode = get_float_rounding_mode(>fp_status);
+
+set_float_rounding_mode(float_round_down, >fp_status);
+fd = (uint64_t)float32_to_int32((uint32_t)fj, >fp_status);
+set_float_rounding_mode(old_mode, >fp_status);
+
+if (get_float_exception_flags(>fp_status) &
+(float_flag_invalid | float_flag_overflow)) {
+fd = FLOAT_TO_INT32_OVERFLOW;
+}
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_ftintrp_l_d(CPULoongArchState *env, uint64_t fj)
+{
+uint64_t fd;
+FloatRoundMode old_mode = get_float_rounding_mode(>fp_stat

[PATCH v1 14/43] target/loongarch: Add floating point load/store instruction translation

2022-04-15 Thread Xiaojuan Yang
From: Song Gao 

This includes:
- FLD.{S/D}, FST.{S/D}
- FLDX.{S/D}, FSTX.{S/D}
- FLD{GT/LE}.{S/D}, FST{GT/LE}.{S/D}

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 .../loongarch/insn_trans/trans_fmemory.c.inc  | 153 ++
 target/loongarch/insns.decode |  24 +++
 target/loongarch/translate.c  |   1 +
 3 files changed, 178 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_fmemory.c.inc

diff --git a/target/loongarch/insn_trans/trans_fmemory.c.inc 
b/target/loongarch/insn_trans/trans_fmemory.c.inc
new file mode 100644
index 00..74ee98f63a
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_fmemory.c.inc
@@ -0,0 +1,153 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static void maybe_nanbox_load(TCGv freg, MemOp mop)
+{
+if ((mop & MO_SIZE) == MO_32) {
+gen_nanbox_s(freg, freg);
+}
+}
+
+static bool gen_fload_i(DisasContext *ctx, arg_fr_i *a, MemOp mop)
+{
+TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv temp = NULL;
+
+if (a->imm) {
+temp = tcg_temp_new();
+tcg_gen_addi_tl(temp, addr, a->imm);
+addr = temp;
+}
+
+tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+maybe_nanbox_load(cpu_fpr[a->fd], mop);
+
+if (temp) {
+tcg_temp_free(temp);
+}
+
+return true;
+}
+
+static bool gen_fstore_i(DisasContext *ctx, arg_fr_i *a, MemOp mop)
+{
+TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv temp = NULL;
+
+if (a->imm) {
+temp = tcg_temp_new();
+tcg_gen_addi_tl(temp, addr, a->imm);
+addr = temp;
+}
+
+tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+
+if (temp) {
+tcg_temp_free(temp);
+}
+return true;
+}
+
+static bool gen_floadx(DisasContext *ctx, arg_frr *a, MemOp mop)
+{
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+TCGv addr = tcg_temp_new();
+
+tcg_gen_add_tl(addr, src1, src2);
+tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+maybe_nanbox_load(cpu_fpr[a->fd], mop);
+tcg_temp_free(addr);
+
+return true;
+}
+
+static bool gen_fstorex(DisasContext *ctx, arg_frr *a, MemOp mop)
+{
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+TCGv addr = tcg_temp_new();
+
+tcg_gen_add_tl(addr, src1, src2);
+tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+tcg_temp_free(addr);
+
+return true;
+}
+
+static bool gen_fload_gt(DisasContext *ctx, arg_frr *a, MemOp mop)
+{
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+TCGv addr = tcg_temp_new();
+
+gen_helper_asrtgt_d(cpu_env, src1, src2);
+tcg_gen_add_tl(addr, src1, src2);
+tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+maybe_nanbox_load(cpu_fpr[a->fd], mop);
+tcg_temp_free(addr);
+
+return true;
+}
+
+static bool gen_fstore_gt(DisasContext *ctx, arg_frr *a, MemOp mop)
+{
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+TCGv addr = tcg_temp_new();
+
+gen_helper_asrtgt_d(cpu_env, src1, src2);
+tcg_gen_add_tl(addr, src1, src2);
+tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+tcg_temp_free(addr);
+
+return true;
+}
+
+static bool gen_fload_le(DisasContext *ctx, arg_frr *a, MemOp mop)
+{
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+TCGv addr = tcg_temp_new();
+
+gen_helper_asrtle_d(cpu_env, src1, src2);
+tcg_gen_add_tl(addr, src1, src2);
+tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+maybe_nanbox_load(cpu_fpr[a->fd], mop);
+tcg_temp_free(addr);
+
+return true;
+}
+
+static bool gen_fstore_le(DisasContext *ctx, arg_frr *a, MemOp mop)
+{
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+TCGv addr = tcg_temp_new();
+
+gen_helper_asrtle_d(cpu_env, src1, src2);
+tcg_gen_add_tl(addr, src1, src2);
+tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+tcg_temp_free(addr);
+
+return true;
+}
+
+TRANS(fld_s, gen_fload_i, MO_TEUL)
+TRANS(fst_s, gen_fstore_i, MO_TEUL)
+TRANS(fld_d, gen_fload_i, MO_TEUQ)
+TRANS(fst_d, gen_fstore_i, MO_TEUQ)
+TRANS(fldx_s, gen_floadx, MO_TEUL)
+TRANS(fldx_d, gen_floadx, MO_TEUQ)
+TRANS(fstx_s, gen_fstorex, MO_TEUL)
+TRANS(fstx_d, gen_fstorex, MO_TEUQ)
+TRANS(fldgt_s, gen_fload_gt, MO_TEUL)
+TRANS(fldgt_d, gen_fload_gt, MO_TEUQ)
+TRANS(fldle_s, gen_fload_le, MO_TEUL)
+TRANS(fldle_d, gen_fload_le, MO_TEUQ)
+TRANS(fstgt_s, gen_fstore_gt, MO_TEUL)
+TRANS(fstgt_d, gen_fstore_gt, 

[PATCH v1 38/43] hw/loongarch: Add some devices support for 3A5000.

2022-04-15 Thread Xiaojuan Yang
1.Add uart,virtio-net,vga and usb for 3A5000.
2.Add irq set and map for the pci host. Non pci device
use irq 0-16, pci device use 16-64.
3.Add some unimplented device to emulate guest unused
memory space.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 hw/loongarch/Kconfig   |  7 
 hw/loongarch/loongson3.c   | 77 ++
 include/hw/pci-host/ls7a.h |  8 
 3 files changed, 92 insertions(+)

diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
index f779087416..8552ff4bee 100644
--- a/hw/loongarch/Kconfig
+++ b/hw/loongarch/Kconfig
@@ -2,6 +2,13 @@ config LOONGARCH_VIRT
 bool
 select PCI
 select PCI_EXPRESS_GENERIC_BRIDGE
+imply VGA_PCI
+imply VIRTIO_VGA
+imply PCI_DEVICES
+select ISA_BUS
+select SERIAL
+select SERIAL_ISA
+select VIRTIO_PCI
 select LOONGARCH_IPI
 select LOONGARCH_PCH_PIC
 select LOONGARCH_PCH_MSI
diff --git a/hw/loongarch/loongson3.c b/hw/loongarch/loongson3.c
index 16f0d9e7df..057208811c 100644
--- a/hw/loongarch/loongson3.c
+++ b/hw/loongarch/loongson3.c
@@ -10,20 +10,95 @@
 #include "qemu/datadir.h"
 #include "qapi/error.h"
 #include "hw/boards.h"
+#include "hw/char/serial.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/qtest.h"
 #include "sysemu/runstate.h"
 #include "sysemu/reset.h"
 #include "sysemu/rtc.h"
+#include "hw/irq.h"
+#include "net/net.h"
 #include "hw/loongarch/loongarch.h"
 #include "hw/intc/loongarch_ipi.h"
 #include "hw/intc/loongarch_extioi.h"
 #include "hw/intc/loongarch_pch_pic.h"
 #include "hw/intc/loongarch_pch_msi.h"
 #include "hw/pci-host/ls7a.h"
+#include "hw/pci-host/gpex.h"
+#include "hw/misc/unimp.h"
 
 #include "target/loongarch/cpu.h"
 
+static void loongarch_devices_init(DeviceState *pch_pic)
+{
+DeviceState *gpex_dev;
+SysBusDevice *d;
+PCIBus *pci_bus;
+MemoryRegion *ecam_alias, *ecam_reg, *pio_alias, *pio_reg;
+MemoryRegion *mmio_alias, *mmio_reg;
+int i;
+
+gpex_dev = qdev_new(TYPE_GPEX_HOST);
+d = SYS_BUS_DEVICE(gpex_dev);
+sysbus_realize_and_unref(d, _fatal);
+pci_bus = PCI_HOST_BRIDGE(gpex_dev)->bus;
+
+/* Map only part size_ecam bytes of ECAM space */
+ecam_alias = g_new0(MemoryRegion, 1);
+ecam_reg = sysbus_mmio_get_region(d, 0);
+memory_region_init_alias(ecam_alias, OBJECT(gpex_dev), "pcie-ecam",
+ ecam_reg, 0, LS_PCIECFG_SIZE);
+memory_region_add_subregion(get_system_memory(), LS_PCIECFG_BASE,
+ecam_alias);
+
+/* Map PCI mem space */
+mmio_alias = g_new0(MemoryRegion, 1);
+mmio_reg = sysbus_mmio_get_region(d, 1);
+memory_region_init_alias(mmio_alias, OBJECT(gpex_dev), "pcie-mmio",
+ mmio_reg, LS7A_PCI_MEM_BASE, LS7A_PCI_MEM_SIZE);
+memory_region_add_subregion(get_system_memory(), LS7A_PCI_MEM_BASE,
+mmio_alias);
+
+/* Map PCI IO port space. */
+pio_alias = g_new0(MemoryRegion, 1);
+pio_reg = sysbus_mmio_get_region(d, 2);
+memory_region_init_alias(pio_alias, OBJECT(gpex_dev), "pcie-io", pio_reg,
+ LS7A_PCI_IO_OFFSET, LS7A_PCI_IO_SIZE);
+memory_region_add_subregion(get_system_memory(), LS7A_PCI_IO_BASE,
+pio_alias);
+
+for (i = 0; i < GPEX_NUM_IRQS; i++) {
+sysbus_connect_irq(d, i,
+   qdev_get_gpio_in(pch_pic, 16 + i));
+gpex_set_irq_num(GPEX_HOST(gpex_dev), i, 16 + i);
+}
+
+serial_mm_init(get_system_memory(), LS7A_UART_BASE, 0,
+   qdev_get_gpio_in(pch_pic,
+LS7A_UART_IRQ - PCH_PIC_IRQ_OFFSET),
+   115200, serial_hd(0), DEVICE_LITTLE_ENDIAN);
+
+/* Network init */
+for (i = 0; i < nb_nics; i++) {
+NICInfo *nd = _table[i];
+
+if (!nd->model) {
+nd->model = g_strdup("virtio");
+}
+
+pci_nic_init_nofail(nd, pci_bus, nd->model, NULL);
+}
+
+/* VGA setup */
+pci_vga_init(pci_bus);
+
+/*
+ * There are some invalid guest memory access.
+ * Create some unimplemented devices to emulate this.
+ */
+create_unimplemented_device("pci-dma-cfg", 0x1001041c, 0x4);
+}
+
 static void loongarch_irq_init(LoongArchMachineState *lams)
 {
 MachineState *ms = MACHINE(lams);
@@ -121,6 +196,8 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
 sysbus_connect_irq(d, i,
qdev_get_gpio_in(extioi, i + PCH_MSI_IRQ_START));
 }
+
+loongarch_devices_init(pch_pic);
 }
 
 static void loongarch_init(MachineState *machine)
diff --git a/include/hw/pci-host/ls7a.

[PATCH v1 28/43] target/loongarch: Add other core instructions support

2022-04-15 Thread Xiaojuan Yang
This includes:
-CACOP
-LDDIR
-LDPTE
-ERTN
-DBCL
-IDLE

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 target/loongarch/disas.c  | 17 
 target/loongarch/helper.h |  5 +
 .../insn_trans/trans_privileged.c.inc | 65 +
 target/loongarch/insns.decode | 11 +++
 target/loongarch/internals.h  |  5 +
 target/loongarch/op_helper.c  | 36 +++
 target/loongarch/tlb_helper.c | 93 +++
 7 files changed, 232 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 4ade829637..4ce00012a8 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -228,6 +228,17 @@ static void output_i_rr(DisasContext *ctx, arg_i_rr *a, 
const char *mnemonic)
 output(ctx, mnemonic, "%d, r%d, r%d", a->imm, a->rj, a->rk);
 }
 
+static void output_cop_r_i(DisasContext *ctx, arg_cop_r_i *a,
+   const char *mnemonic)
+{
+output(ctx, mnemonic, "%d, r%d, %d", a->cop, a->rj, a->imm);
+}
+
+static void output_j_i(DisasContext *ctx, arg_j_i *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "r%d, %d", a->rj, a->imm);
+}
+
 #define INSN(insn, type)\
 static bool trans_##insn(DisasContext *ctx, arg_##type * a) \
 {   \
@@ -555,6 +566,12 @@ INSN(tlbfill,  empty)
 INSN(tlbclr,   empty)
 INSN(tlbflush, empty)
 INSN(invtlb,   i_rr)
+INSN(cacop,cop_r_i)
+INSN(lddir,rr_i)
+INSN(ldpte,j_i)
+INSN(ertn, empty)
+INSN(idle, i)
+INSN(dbcl, i)
 
 #define output_fcmp(C, PREFIX, SUFFIX) 
\
 {  
\
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 63ae687749..ad1a43d162 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -116,3 +116,8 @@ DEF_HELPER_2(invtlb_all_g, void, env, i32)
 DEF_HELPER_2(invtlb_all_asid, void, env, tl)
 DEF_HELPER_3(invtlb_page_asid, void, env, tl, tl)
 DEF_HELPER_3(invtlb_page_asid_or_g, void, env, tl, tl)
+
+DEF_HELPER_4(lddir, tl, env, tl, tl, i32)
+DEF_HELPER_4(ldpte, void, env, tl, tl, i32)
+DEF_HELPER_1(ertn, void, env)
+DEF_HELPER_1(idle, void, env)
diff --git a/target/loongarch/insn_trans/trans_privileged.c.inc 
b/target/loongarch/insn_trans/trans_privileged.c.inc
index 67adcecf73..9f46f93fd6 100644
--- a/target/loongarch/insn_trans/trans_privileged.c.inc
+++ b/target/loongarch/insn_trans/trans_privileged.c.inc
@@ -372,3 +372,68 @@ static bool trans_invtlb(DisasContext *ctx, arg_invtlb *a)
 ctx->base.is_jmp = DISAS_STOP;
 return true;
 }
+
+static bool trans_cacop(DisasContext *ctx, arg_cacop *a)
+{
+/* Treat the cacop as a nop */
+if (check_plv(ctx)) {
+return false;
+}
+return true;
+}
+
+static bool trans_ldpte(DisasContext *ctx, arg_ldpte *a)
+{
+TCGv_i32 mem_idx = tcg_constant_i32(ctx->mem_idx);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+if (check_plv(ctx)) {
+return false;
+}
+gen_helper_ldpte(cpu_env, src1, tcg_constant_tl(a->imm), mem_idx);
+return true;
+}
+
+static bool trans_lddir(DisasContext *ctx, arg_lddir *a)
+{
+TCGv_i32 mem_idx = tcg_constant_i32(ctx->mem_idx);
+TCGv src = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+
+if (check_plv(ctx)) {
+return false;
+}
+gen_helper_lddir(dest, cpu_env, src, tcg_constant_tl(a->imm), mem_idx);
+return true;
+}
+
+static bool trans_ertn(DisasContext *ctx, arg_ertn *a)
+{
+if (check_plv(ctx)) {
+return false;
+}
+gen_helper_ertn(cpu_env);
+ctx->base.is_jmp = DISAS_EXIT;
+return true;
+}
+
+static bool trans_dbcl(DisasContext *ctx, arg_dbcl *a)
+{
+if (check_plv(ctx)) {
+return false;
+}
+generate_exception(ctx, EXCCODE_DBP);
+return true;
+}
+
+static bool trans_idle(DisasContext *ctx, arg_idle *a)
+{
+if (check_plv(ctx)) {
+return false;
+}
+
+tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next + 4);
+gen_helper_idle(cpu_env);
+ctx->base.is_jmp = DISAS_NORETURN;
+return true;
+}
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index f8ed11d83e..ebd3d505fb 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -49,6 +49,8 @@
 _csr   rd rj csr
 
 _rr imm rj rk
+_r_i  cop rj imm
+_i  rj imm
 
 #
 # Formats
@@ -60,6 +62,7 @@
 @r_i20   ... imm:s20 rd:5_i
 @rr_ui5     . imm:5 rj:5 rd:5_i
 @rr_ui6   imm:6 rj:5 rd:5_i
+@rr_ui8  ..   imm:8 rj:5 rd:5_i
 @rr_i12   

[PATCH v1 22/43] target/loongarch: Add MMU support for LoongArch CPU.

2022-04-15 Thread Xiaojuan Yang
Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
---
 target/loongarch/cpu-param.h  |   2 +-
 target/loongarch/cpu.c|  24 +++
 target/loongarch/cpu.h|  51 ++
 target/loongarch/internals.h  |   9 +
 target/loongarch/machine.c|  17 ++
 target/loongarch/meson.build  |   1 +
 target/loongarch/tlb_helper.c | 315 ++
 7 files changed, 418 insertions(+), 1 deletion(-)
 create mode 100644 target/loongarch/tlb_helper.c

diff --git a/target/loongarch/cpu-param.h b/target/loongarch/cpu-param.h
index 9a769b67e0..414d8fff46 100644
--- a/target/loongarch/cpu-param.h
+++ b/target/loongarch/cpu-param.h
@@ -13,6 +13,6 @@
 #define TARGET_VIRT_ADDR_SPACE_BITS 48
 
 #define TARGET_PAGE_BITS 14
-#define NB_MMU_MODES 4
+#define NB_MMU_MODES 5
 
 #endif
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 6cf95013ab..2581e60e49 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -298,6 +298,21 @@ void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int 
flags)
 }
 }
 
+qemu_fprintf(f, "CRMD=%016" PRIx64 "\n", env->CSR_CRMD);
+qemu_fprintf(f, "PRMD=%016" PRIx64 "\n", env->CSR_PRMD);
+qemu_fprintf(f, "EUEN=%016" PRIx64 "\n", env->CSR_EUEN);
+qemu_fprintf(f, "ESTAT=%016" PRIx64 "\n", env->CSR_ESTAT);
+qemu_fprintf(f, "ERA=%016" PRIx64 "\n", env->CSR_ERA);
+qemu_fprintf(f, "BADV=%016" PRIx64 "\n", env->CSR_BADV);
+qemu_fprintf(f, "BADI=%016" PRIx64 "\n", env->CSR_BADI);
+qemu_fprintf(f, "EENTRY=%016" PRIx64 "\n", env->CSR_EENTRY);
+qemu_fprintf(f, "PRCFG1=%016" PRIx64 ", PRCFG2=%016" PRIx64 ","
+ " PRCFG3=%016" PRIx64 "\n",
+ env->CSR_PRCFG1, env->CSR_PRCFG3, env->CSR_PRCFG3);
+qemu_fprintf(f, "TLBRENTRY=%016" PRIx64 "\n", env->CSR_TLBRENTRY);
+qemu_fprintf(f, "TLBRBADV=%016" PRIx64 "\n", env->CSR_TLBRBADV);
+qemu_fprintf(f, "TLBRERA=%016" PRIx64 "\n", env->CSR_TLBRERA);
+
 /* fpr */
 if (flags & CPU_DUMP_FPU) {
 for (i = 0; i < 32; i++) {
@@ -315,9 +330,17 @@ void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int 
flags)
 static struct TCGCPUOps loongarch_tcg_ops = {
 .initialize = loongarch_translate_init,
 .synchronize_from_tb = loongarch_cpu_synchronize_from_tb,
+
+.tlb_fill = loongarch_cpu_tlb_fill,
 };
 #endif /* CONFIG_TCG */
 
+#include "hw/core/sysemu-cpu-ops.h"
+
+static const struct SysemuCPUOps loongarch_sysemu_ops = {
+.get_phys_page_debug = loongarch_cpu_get_phys_page_debug,
+};
+
 static void loongarch_cpu_class_init(ObjectClass *c, void *data)
 {
 LoongArchCPUClass *lacc = LOONGARCH_CPU_CLASS(c);
@@ -332,6 +355,7 @@ static void loongarch_cpu_class_init(ObjectClass *c, void 
*data)
 cc->dump_state = loongarch_cpu_dump_state;
 cc->set_pc = loongarch_cpu_set_pc;
 dc->vmsd = _loongarch_cpu;
+cc->sysemu_ops = _sysemu_ops;
 cc->disas_set_info = loongarch_cpu_disas_set_info;
 #ifdef CONFIG_TCG
 cc->tcg_ops = _tcg_ops;
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 74303b2c97..a1b88f81eb 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -184,6 +184,26 @@ FIELD(CSR_CRMD, WE, 9, 1)
 extern const char * const regnames[32];
 extern const char * const fregnames[32];
 
+#define LOONGARCH_STLB 2048 /* 2048 STLB */
+#define LOONGARCH_MTLB 64   /* 64 MTLB */
+#define LOONGARCH_TLB_MAX  (LOONGARCH_STLB + LOONGARCH_MTLB)
+
+/*
+ * define the ASID PS E VPPN field of TLB
+ */
+FIELD(TLB_MISC, E, 0, 1)
+FIELD(TLB_MISC, ASID, 1, 10)
+FIELD(TLB_MISC, VPPN, 13, 35)
+FIELD(TLB_MISC, PS, 48, 6)
+
+struct LoongArchTLB {
+uint64_t tlb_misc;
+/* Fields corresponding to CSR_TLBELO0/1 */
+uint64_t tlb_entry0;
+uint64_t tlb_entry1;
+};
+typedef struct LoongArchTLB LoongArchTLB;
+
 typedef struct CPUArchState {
 uint64_t gpr[32];
 uint64_t pc;
@@ -257,6 +277,8 @@ typedef struct CPUArchState {
 uint64_t CSR_DBG;
 uint64_t CSR_DERA;
 uint64_t CSR_DSAVE;
+
+LoongArchTLB  tlb[LOONGARCH_TLB_MAX];
 } CPULoongArchState;
 
 /**
@@ -295,6 +317,35 @@ struct LoongArchCPUClass {
 DeviceReset parent_reset;
 };
 
+/*
+ * LoongArch CPUs has 4 privilege levels.
+ * 0 for kernel mode, 3 for user mode.
+ * Define an extra index for DA(direct addressing) mode.
+ */
+#define MMU_KERNEL_IDX   0
+#define MMU_USER_IDX 3
+#define MMU_DA_IDX   4
+
+static inline int cpu_mmu_index(CPULoongArchState *env, bool ifetch)
+{
+uint8_t pg = FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PG);
+
+if (!pg) {
+return MMU_DA_IDX;
+}
+ret

[PATCH v1 00/43] Add LoongArch softmmu support

2022-04-15 Thread Xiaojuan Yang
Hi All,

As this series only supports running binary files in ELF format, and does not 
depend on
BIOS and kernel file. so this series are changed from RFC to patch v1.

The manual:
  - https://github.com/loongson/LoongArch-Documentation/releases/tag/2022.03.17

Old series:
  - https://patchew.org/QEMU/20220328125749.2918087-1-yangxiaoj...@loongson.cn/
  - https://patchew.org/QEMU/20220106094200.1801206-1-gaos...@loongson.cn/

Thanks.
Xiaojuan

Song Gao (18):
  target/loongarch: Add README
  target/loongarch: Add core definition
  target/loongarch: Add main translation routines
  target/loongarch: Add fixed point arithmetic instruction translation
  target/loongarch: Add fixed point shift instruction translation
  target/loongarch: Add fixed point bit instruction translation
  target/loongarch: Add fixed point load/store instruction translation
  target/loongarch: Add fixed point atomic instruction translation
  target/loongarch: Add fixed point extra instruction translation
  target/loongarch: Add floating point arithmetic instruction
translation
  target/loongarch: Add floating point comparison instruction
translation
  target/loongarch: Add floating point conversion instruction
translation
  target/loongarch: Add floating point move instruction translation
  target/loongarch: Add floating point load/store instruction
translation
  target/loongarch: Add branch instruction translation
  target/loongarch: Add disassembler
  target/loongarch: Add target build suport
  target/loongarch: 'make check-tcg' support

Xiaojuan Yang (25):
  target/loongarch: Add system emulation introduction
  target/loongarch: Add CSRs definition
  target/loongarch: Add basic vmstate description of CPU.
  target/loongarch: Implement qmp_query_cpu_definitions()
  target/loongarch: Add MMU support for LoongArch CPU.
  target/loongarch: Add LoongArch interrupt and exception handle
  target/loongarch: Add constant timer support
  target/loongarch: Add LoongArch CSR instruction
  target/loongarch: Add LoongArch IOCSR instruction
  target/loongarch: Add TLB instruction support
  target/loongarch: Add other core instructions support
  target/loongarch: Add timer related instructions support.
  target/loongarch: Add gdb support.
  hw/loongarch: Add support loongson3 virt machine type.
  hw/loongarch: Add LoongArch ipi interrupt support(IPI)
  hw/intc: Add LoongArch ls7a interrupt controller support(PCH-PIC)
  hw/intc: Add LoongArch ls7a msi interrupt controller support(PCH-MSI)
  hw/intc: Add LoongArch extioi interrupt controller(EIOINTC)
  hw/loongarch: Add irq hierarchy for the system
  Enable common virtio pci support for LoongArch
  hw/loongarch: Add some devices support for 3A5000.
  hw/loongarch: Add LoongArch ls7a rtc device support
  hw/loongarch: Add LoongArch boot code and load elf function.
  hw/loongarch: Add LoongArch ls7a acpi device support
  tests/tcg/loongarch64: Add hello/memory test in loongarch64 system

 MAINTAINERS   |  26 +
 .../devices/loongarch64-softmmu/default.mak   |   3 +
 configs/targets/loongarch64-softmmu.mak   |   4 +
 docs/system/loongarch/loongson3.rst   |  41 +
 gdb-xml/loongarch-base64.xml  |  44 +
 gdb-xml/loongarch-fpu64.xml   |  57 ++
 hw/Kconfig|   1 +
 hw/acpi/Kconfig   |   4 +
 hw/acpi/ls7a.c| 374 
 hw/acpi/meson.build   |   1 +
 hw/intc/Kconfig   |  15 +
 hw/intc/loongarch_extioi.c| 373 
 hw/intc/loongarch_ipi.c   | 145 +++
 hw/intc/loongarch_pch_msi.c   |  75 ++
 hw/intc/loongarch_pch_pic.c   | 488 ++
 hw/intc/meson.build   |   4 +
 hw/intc/trace-events  |  27 +
 hw/loongarch/Kconfig  |  18 +
 hw/loongarch/loongson3.c  | 354 +++
 hw/loongarch/meson.build  |   4 +
 hw/meson.build|   1 +
 hw/rtc/Kconfig|   3 +
 hw/rtc/ls7a_rtc.c | 323 +++
 hw/rtc/meson.build|   1 +
 include/disas/dis-asm.h   |   2 +
 include/exec/poison.h |   2 +
 include/hw/acpi/ls7a.h|  53 ++
 include/hw/intc/loongarch_extioi.h|  68 ++
 include/hw/intc/loongarch_ipi.h   |  46 +
 include/hw/intc/loongarch_pch_msi.h   |  20 +
 include/hw/intc/loongarch_pch_pic.h   |  80 ++
 include/hw/loongarch/loongarch.h  |  61 ++
 include/hw/pci-host/ls7a.h|  48 +
 include/sysemu/arch_init.h|   1 +
 meson.build   |   1 +
 qapi/machine-target.json  |   6 +-
 qapi

[PATCH v1 06/43] target/loongarch: Add fixed point bit instruction translation

2022-04-15 Thread Xiaojuan Yang
From: Song Gao 

This includes:
- EXT.W.{B/H}
- CL{O/Z}.{W/D}, CT{O/Z}.{W/D}
- BYTEPICK.{W/D}
- REVB.{2H/4H/2W/D}
- REVH.{2W/D}
- BITREV.{4B/8B}, BITREV.{W/D}
- BSTRINS.{W/D}, BSTRPICK.{W/D}
- MASKEQZ, MASKNEZ

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 target/loongarch/helper.h   |   4 +
 target/loongarch/insn_trans/trans_bit.c.inc | 212 
 target/loongarch/insns.decode   |  39 
 target/loongarch/op_helper.c|  21 ++
 target/loongarch/translate.c|   1 +
 5 files changed, 277 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_bit.c.inc

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index eb771c0628..04e0245d5e 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -4,3 +4,7 @@
  */
 
 DEF_HELPER_2(raise_exception, noreturn, env, i32)
+
+DEF_HELPER_FLAGS_1(bitrev_w, TCG_CALL_NO_RWG_SE, tl, tl)
+DEF_HELPER_FLAGS_1(bitrev_d, TCG_CALL_NO_RWG_SE, tl, tl)
+DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl)
diff --git a/target/loongarch/insn_trans/trans_bit.c.inc 
b/target/loongarch/insn_trans/trans_bit.c.inc
new file mode 100644
index 00..9337714ec4
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_bit.c.inc
@@ -0,0 +1,212 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static bool gen_rr(DisasContext *ctx, arg_rr *a,
+   DisasExtend src_ext, DisasExtend dst_ext,
+   void (*func)(TCGv, TCGv))
+{
+TCGv dest = gpr_dst(ctx, a->rd, dst_ext);
+TCGv src1 = gpr_src(ctx, a->rj, src_ext);
+
+func(dest, src1);
+gen_set_gpr(a->rd, dest, dst_ext);
+
+return true;
+}
+
+static void gen_bytepick_w(TCGv dest, TCGv src1, TCGv src2, target_long sa)
+{
+tcg_gen_concat_tl_i64(dest, src1, src2);
+tcg_gen_sextract_i64(dest, dest, (32 - sa * 8), 32);
+}
+
+static void gen_bytepick_d(TCGv dest, TCGv src1, TCGv src2, target_long sa)
+{
+tcg_gen_extract2_i64(dest, src1, src2, (64 - sa * 8));
+}
+
+static void gen_bstrins(TCGv dest, TCGv src1,
+unsigned int ls, unsigned int len)
+{
+tcg_gen_deposit_tl(dest, dest, src1, ls, len);
+}
+
+static bool gen_rr_ms_ls(DisasContext *ctx, arg_rr_ms_ls *a,
+ DisasExtend src_ext, DisasExtend dst_ext,
+ void (*func)(TCGv, TCGv, unsigned int, unsigned int))
+{
+TCGv dest = gpr_dst(ctx, a->rd, dst_ext);
+TCGv src1 = gpr_src(ctx, a->rj, src_ext);
+
+if (a->ls > a->ms) {
+return false;
+}
+
+func(dest, src1, a->ls, a->ms - a->ls + 1);
+gen_set_gpr(a->rd, dest, dst_ext);
+
+return true;
+}
+
+static void gen_clz_w(TCGv dest, TCGv src1)
+{
+tcg_gen_clzi_tl(dest, src1, TARGET_LONG_BITS);
+tcg_gen_subi_tl(dest, dest, TARGET_LONG_BITS - 32);
+}
+
+static void gen_clo_w(TCGv dest, TCGv src1)
+{
+tcg_gen_not_tl(dest, src1);
+tcg_gen_ext32u_tl(dest, dest);
+gen_clz_w(dest, dest);
+}
+
+static void gen_ctz_w(TCGv dest, TCGv src1)
+{
+tcg_gen_ori_tl(dest, src1, (target_ulong)MAKE_64BIT_MASK(32, 32));
+tcg_gen_ctzi_tl(dest, dest, TARGET_LONG_BITS);
+}
+
+static void gen_cto_w(TCGv dest, TCGv src1)
+{
+tcg_gen_not_tl(dest, src1);
+gen_ctz_w(dest, dest);
+}
+
+static void gen_clz_d(TCGv dest, TCGv src1)
+{
+tcg_gen_clzi_i64(dest, src1, TARGET_LONG_BITS);
+}
+
+static void gen_clo_d(TCGv dest, TCGv src1)
+{
+tcg_gen_not_tl(dest, src1);
+gen_clz_d(dest, dest);
+}
+
+static void gen_ctz_d(TCGv dest, TCGv src1)
+{
+tcg_gen_ctzi_tl(dest, src1, TARGET_LONG_BITS);
+}
+
+static void gen_cto_d(TCGv dest, TCGv src1)
+{
+tcg_gen_not_tl(dest, src1);
+gen_ctz_d(dest, dest);
+}
+
+static void gen_revb_2w(TCGv dest, TCGv src1)
+{
+tcg_gen_bswap64_i64(dest, src1);
+tcg_gen_rotri_i64(dest, dest, 32);
+}
+
+static void gen_revb_2h(TCGv dest, TCGv src1)
+{
+TCGv mask = tcg_constant_tl(0x00FF00FF);
+TCGv t0 = tcg_temp_new();
+TCGv t1 = tcg_temp_new();
+
+tcg_gen_shri_tl(t0, src1, 8);
+tcg_gen_and_tl(t0, t0, mask);
+tcg_gen_and_tl(t1, src1, mask);
+tcg_gen_shli_tl(t1, t1, 8);
+tcg_gen_or_tl(dest, t0, t1);
+
+tcg_temp_free(t0);
+tcg_temp_free(t1);
+}
+
+static void gen_revb_4h(TCGv dest, TCGv src1)
+{
+TCGv mask = tcg_constant_tl(0x00FF00FF00FF00FFULL);
+TCGv t0 = tcg_temp_new();
+TCGv t1 = tcg_temp_new();
+
+tcg_gen_shri_tl(t0, src1, 8);
+tcg_gen_and_tl(t0, t0, mask);
+tcg_gen_and_tl(t1, src1, mask);
+tcg_gen_shli_tl(t1, t1, 8);
+tcg_gen_or_tl(dest, t0, t1);
+
+tcg_temp_free(t0);
+tcg_temp_free(t1);
+}
+
+static void gen_revh_2w(TCGv dest, TCGv src1)
+{
+TCGv_i64 t0 = tcg_temp_new_i64();
+TCGv_i64 t1 = tcg_temp_new_i64();
+TCGv_i64 mask = tcg_constant_i64(0xull);

[PATCH v1 36/43] hw/loongarch: Add irq hierarchy for the system

2022-04-15 Thread Xiaojuan Yang
This patch add the irq hierarchy for the virt board.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 hw/loongarch/loongson3.c | 106 +++
 1 file changed, 106 insertions(+)

diff --git a/hw/loongarch/loongson3.c b/hw/loongarch/loongson3.c
index 345226dfe9..16f0d9e7df 100644
--- a/hw/loongarch/loongson3.c
+++ b/hw/loongarch/loongson3.c
@@ -16,9 +16,113 @@
 #include "sysemu/reset.h"
 #include "sysemu/rtc.h"
 #include "hw/loongarch/loongarch.h"
+#include "hw/intc/loongarch_ipi.h"
+#include "hw/intc/loongarch_extioi.h"
+#include "hw/intc/loongarch_pch_pic.h"
+#include "hw/intc/loongarch_pch_msi.h"
+#include "hw/pci-host/ls7a.h"
 
 #include "target/loongarch/cpu.h"
 
+static void loongarch_irq_init(LoongArchMachineState *lams)
+{
+MachineState *ms = MACHINE(lams);
+DeviceState *pch_pic, *pch_msi, *cpudev;
+DeviceState *ipi, *extioi;
+SysBusDevice *d;
+LoongArchCPU *lacpu;
+CPULoongArchState *env;
+CPUState *cpu_state;
+
+int cpu, pin, i;
+unsigned long ipi_addr;
+
+ipi = qdev_new(TYPE_LOONGARCH_IPI);
+sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), _fatal);
+
+extioi = qdev_new(TYPE_LOONGARCH_EXTIOI);
+sysbus_realize_and_unref(SYS_BUS_DEVICE(extioi), _fatal);
+
+/*
+ * The connection of interrupts:
+ *   +-++-+ +---+
+ *   | IPI |--> | CPUINTC | <-- | Timer |
+ *   +-++-+ +---+
+ *  ^
+ *  |
+ *+-+
+ *| EIOINTC |
+ *+-+
+ * ^   ^
+ * |   |
+ *  +-+ +-+
+ *  | PCH-PIC | | PCH-MSI |
+ *  +-+ +-+
+ *^  ^  ^
+ *|  |  |
+ * ++ +-+ +-+
+ * | UARTs  | | Devices | | Devices |
+ * ++ +-+ +-+
+ */
+for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
+cpu_state = qemu_get_cpu(cpu);
+cpudev = DEVICE(cpu_state);
+lacpu = LOONGARCH_CPU(cpu_state);
+env = &(lacpu->env);
+
+/* connect ipi irq to cpu irq */
+qdev_connect_gpio_out(ipi, cpu, qdev_get_gpio_in(cpudev, IRQ_IPI));
+/* ipi memory region */
+ipi_addr = SMP_IPI_MAILBOX + cpu * 0x100;
+memory_region_add_subregion(>system_iocsr, ipi_addr,
+sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi),
+cpu));
+/* extioi memory region */
+memory_region_add_subregion(>system_iocsr, APIC_BASE,
+sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi),
+cpu));
+}
+
+/*
+ * connect ext irq to the cpu irq
+ * cpu_pin[9:2] <= intc_pin[7:0]
+ */
+for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
+cpudev = DEVICE(qemu_get_cpu(cpu));
+for (pin = 0; pin < LS3A_INTC_IP; pin++) {
+qdev_connect_gpio_out(extioi, (cpu * 8 + pin),
+  qdev_get_gpio_in(cpudev, pin + 2));
+}
+}
+
+pch_pic = qdev_new(TYPE_LOONGARCH_PCH_PIC);
+d = SYS_BUS_DEVICE(pch_pic);
+sysbus_realize_and_unref(d, _fatal);
+memory_region_add_subregion(get_system_memory(), LS7A_IOAPIC_REG_BASE,
+sysbus_mmio_get_region(d, 0));
+memory_region_add_subregion(get_system_memory(),
+LS7A_IOAPIC_REG_BASE + PCH_PIC_ROUTE_ENTRY_OFFSET,
+sysbus_mmio_get_region(d, 1));
+memory_region_add_subregion(get_system_memory(),
+LS7A_IOAPIC_REG_BASE + PCH_PIC_INT_STATUS_LO,
+sysbus_mmio_get_region(d, 2));
+
+/* Connect 64 pch_pic irqs to extioi */
+for (int i = 0; i < PCH_PIC_IRQ_NUM; i++) {
+sysbus_connect_irq(d, i, qdev_get_gpio_in(extioi, i));
+}
+
+pch_msi = qdev_new(TYPE_LOONGARCH_PCH_MSI);
+d = SYS_BUS_DEVICE(pch_msi);
+sysbus_realize_and_unref(d, _fatal);
+sysbus_mmio_map(d, 0, LS7A_PCH_MSI_ADDR_LOW);
+for (i = 0; i < PCH_MSI_IRQ_NUM; i++) {
+/* Connect 192 pch_msi irqs to extioi */
+sysbus_connect_irq(d, i,
+   qdev_get_gpio_in(extioi, i + PCH_MSI_IRQ_START));
+}
+}
+
 static void loongarch_init(MachineState *machine)
 {
 const char *cpu_model = machine->cpu_type;
@@ -59,6 +163,8 @@ static void loongarch_init(MachineState *machine)
  get_system_io(), 0, LOONGARCH_ISA_IO_SIZE);
 memory_region_add_subregion(address_space_mem, LOONGARCH_ISA_IO_BASE,
 >isa_io);
+/* Initialize the IO interrupt subsystem */
+loongarch_irq_init(lams);
 }
 
 static void loongarch_class_init(ObjectClass *oc, void *data)
-- 
2.31.1




[PATCH v1 33/43] hw/intc: Add LoongArch ls7a interrupt controller support(PCH-PIC)

2022-04-15 Thread Xiaojuan Yang
This patch realize the PCH-PIC interrupt controller.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 MAINTAINERS |   1 +
 hw/intc/Kconfig |   4 +
 hw/intc/loongarch_pch_pic.c | 488 
 hw/intc/meson.build |   1 +
 hw/intc/trace-events|   9 +
 hw/loongarch/Kconfig|   1 +
 include/hw/intc/loongarch_pch_pic.h |  80 +
 include/hw/pci-host/ls7a.h  |  30 ++
 8 files changed, 614 insertions(+)
 create mode 100644 hw/intc/loongarch_pch_pic.c
 create mode 100644 include/hw/intc/loongarch_pch_pic.h
 create mode 100644 include/hw/pci-host/ls7a.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 3f5aaeeeba..fadb90a9d5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1136,6 +1136,7 @@ F: hw/loongarch/
 F: include/hw/loongarch/loongarch.h
 F: include/hw/intc/loongarch_*.h
 F: hw/intc/loongarch_*.c
+F: include/hw/pci-host/ls7a.h
 
 M68K Machines
 -
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
index 6c7e82da64..1fbba2e728 100644
--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -87,3 +87,7 @@ config M68K_IRQC
 
 config LOONGARCH_IPI
 bool
+
+config LOONGARCH_PCH_PIC
+bool
+select UNIMP
diff --git a/hw/intc/loongarch_pch_pic.c b/hw/intc/loongarch_pch_pic.c
new file mode 100644
index 00..3865015974
--- /dev/null
+++ b/hw/intc/loongarch_pch_pic.c
@@ -0,0 +1,488 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU Loongson 7A1000 I/O interrupt controller.
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/loongarch/loongarch.h"
+#include "hw/irq.h"
+#include "hw/intc/loongarch_pch_pic.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+
+static void pch_pic_update_irq(LoongArchPCHPIC *s, uint32_t mask,
+   int level, int hi)
+{
+uint32_t val, irq;
+
+if (level == 1) {
+if (hi) {
+val = mask & s->intirr_hi & (~s->int_mask_hi);
+irq = find_first_bit((unsigned long *), 32);
+if (irq != 32) {
+s->intisr_hi |= 1ULL << irq;
+qemu_set_irq(s->parent_irq[s->htmsi_vector[irq + 32]], 1);
+}
+} else {
+val = mask & s->intirr_lo & (~s->int_mask_lo);
+irq = find_first_bit((unsigned long *), 32);
+if (irq != 32) {
+s->intisr_lo |= 1ULL << irq;
+qemu_set_irq(s->parent_irq[s->htmsi_vector[irq]], 1);
+}
+}
+} else {
+if (hi) {
+val = mask & s->intisr_hi;
+irq = find_first_bit((unsigned long *), 32);
+if (irq != 32) {
+s->intisr_hi &= ~(0x1ULL << irq);
+qemu_set_irq(s->parent_irq[s->htmsi_vector[irq + 32]], 0);
+}
+} else {
+val = mask & s->intisr_lo;
+irq = find_first_bit((unsigned long *), 32);
+if (irq != 32) {
+s->intisr_lo &= ~(0x1ULL << irq);
+qemu_set_irq(s->parent_irq[s->htmsi_vector[irq]], 0);
+}
+}
+}
+}
+
+static void pch_pic_irq_handler(void *opaque, int irq, int level)
+{
+LoongArchPCHPIC *s = LOONGARCH_PCH_PIC(opaque);
+int hi = 0;
+uint32_t mask;
+
+assert(irq < PCH_PIC_IRQ_NUM);
+trace_loongarch_pch_pic_irq_handler(irq, level);
+
+hi = (irq >= 32) ? 1 : 0;
+if (hi) {
+irq = irq - 32;
+}
+
+mask = 1ULL << irq;
+
+if (hi) {
+if (s->intedge_hi & mask) {
+/* Edge triggered */
+if (level) {
+if ((s->last_intirr_hi & mask) == 0) {
+s->intirr_hi |= mask;
+}
+s->last_intirr_hi |= mask;
+} else {
+s->last_intirr_hi &= ~mask;
+}
+} else {
+/* Level triggered */
+if (level) {
+s->intirr_hi |= mask;
+s->last_intirr_hi |= mask;
+} else {
+s->intirr_hi &= ~mask;
+s->last_intirr_hi &= ~mask;
+}
+}
+} else {
+if (s->intedge_lo & mask) {
+/* Edge triggered */
+if (level) {
+if ((s->last_intirr_lo & mask) == 0) {
+s->intirr_lo |= mask;
+}
+s->last_intirr_lo |= mask;
+} else {
+s->last_intirr_lo &= ~mask;
+}
+} else {
+/* Level triggered */
+if (level) {
+s->intirr_lo |= mask;
+s->l

[PATCH v1 30/43] target/loongarch: Add gdb support.

2022-04-15 Thread Xiaojuan Yang
Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 MAINTAINERS |   2 +
 configs/targets/loongarch64-softmmu.mak |   1 +
 gdb-xml/loongarch-base64.xml|  44 ++
 gdb-xml/loongarch-fpu64.xml |  57 +
 target/loongarch/cpu.c  |   7 ++
 target/loongarch/gdbstub.c  | 107 
 target/loongarch/internals.h|  11 +++
 target/loongarch/meson.build|   1 +
 8 files changed, 230 insertions(+)
 create mode 100644 configs/targets/loongarch64-softmmu.mak
 create mode 100644 gdb-xml/loongarch-base64.xml
 create mode 100644 gdb-xml/loongarch-fpu64.xml
 create mode 100644 target/loongarch/gdbstub.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 51724ad6f6..92de08b19d 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1129,6 +1129,8 @@ M: Xiaojuan Yang 
 M: Song Gao 
 S: Maintained
 F: docs/system/loongarch/loongson3.rst
+F: configs/targets/loongarch64-softmmu.mak
+F: gdb-xml/loongarch*.xml
 
 M68K Machines
 -
diff --git a/configs/targets/loongarch64-softmmu.mak 
b/configs/targets/loongarch64-softmmu.mak
new file mode 100644
index 00..f33fa1590b
--- /dev/null
+++ b/configs/targets/loongarch64-softmmu.mak
@@ -0,0 +1 @@
+TARGET_XML_FILES= gdb-xml/loongarch-base64.xml gdb-xml/loongarch-fpu64.xml
diff --git a/gdb-xml/loongarch-base64.xml b/gdb-xml/loongarch-base64.xml
new file mode 100644
index 00..4962bdbd28
--- /dev/null
+++ b/gdb-xml/loongarch-base64.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+
diff --git a/gdb-xml/loongarch-fpu64.xml b/gdb-xml/loongarch-fpu64.xml
new file mode 100644
index 00..e52cf89fbc
--- /dev/null
+++ b/gdb-xml/loongarch-fpu64.xml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+  
+
+
+  
+
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index ac8d9e7d2a..47b159dba6 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -620,6 +620,13 @@ static void loongarch_cpu_class_init(ObjectClass *c, void 
*data)
 dc->vmsd = _loongarch_cpu;
 cc->sysemu_ops = _sysemu_ops;
 cc->disas_set_info = loongarch_cpu_disas_set_info;
+cc->gdb_read_register = loongarch_cpu_gdb_read_register;
+cc->gdb_write_register = loongarch_cpu_gdb_write_register;
+cc->disas_set_info = loongarch_cpu_disas_set_info;
+cc->gdb_num_core_regs = 34;
+cc->gdb_core_xml_file = "loongarch-base64.xml";
+cc->gdb_stop_before_watchpoint = true;
+
 #ifdef CONFIG_TCG
 cc->tcg_ops = _tcg_ops;
 #endif
diff --git a/target/loongarch/gdbstub.c b/target/loongarch/gdbstub.c
new file mode 100644
index 00..2bcaf9c811
--- /dev/null
+++ b/target/loongarch/gdbstub.c
@@ -0,0 +1,107 @@
+/*
+ * LOONGARCH gdb server stub
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "cpu.h"
+#include "internals.h"
+#include "exec/gdbstub.h"
+#include "exec/helper-proto.h"
+
+int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+{
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+CPULoongArchState *env = >env;
+
+if (0 <= n && n < 32) {
+return gdb_get_regl(mem_buf, env->gpr[n]);
+} else if (n == 32) {
+return gdb_get_regl(mem_buf, env->pc);
+} else if (n == 33) {
+return gdb_get_regl(mem_buf, env->badaddr);
+}
+return 0;
+}
+
+int loongarch_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+CPULoongArchState *env = >env;
+target_ulong tmp = ldtul_p(mem_buf);
+int length = 0;
+
+if (0 <= n && n < 32) {
+env->gpr[n] = tmp;
+length = sizeof(target_ulong);
+} else if (n == 32) {
+env->pc = tmp;
+length = sizeof(target_ulong);
+}
+return length;
+}
+
+static int loongarch_gdb_get_fpu(CPULoongArchState *env,
+ GByteArray *mem_buf, int n)
+{
+if (0 <= n && n < 32) {
+return gdb_get_reg64(mem_buf, env->fpr[n]);
+} else if (32 <= n && n < 40) {
+return gdb_get_reg8(mem_buf, env->cf[n - 32]);
+} else if (n == 40) {
+return gdb_get_reg32(mem_buf, env->fcsr0);
+}
+return 0;
+}
+
+static int loongarch_gdb_set_fpu(CPULoongArchState *env,
+ uint8_t *mem_buf, int n)
+{
+int length = 0;
+
+if (0 <= n && n < 32) {
+env->fpr[n] = ldq_p(mem_buf);

[PATCH v1 15/43] target/loongarch: Add branch instruction translation

2022-04-15 Thread Xiaojuan Yang
From: Song Gao 

This includes:
- BEQ, BNE, BLT[U], BGE[U]
- BEQZ, BNEZ
- B
- BL
- JIRL
- BCEQZ, BCNEZ

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 .../loongarch/insn_trans/trans_branch.c.inc   | 83 +++
 target/loongarch/insns.decode | 28 +++
 target/loongarch/translate.c  |  1 +
 3 files changed, 112 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_branch.c.inc

diff --git a/target/loongarch/insn_trans/trans_branch.c.inc 
b/target/loongarch/insn_trans/trans_branch.c.inc
new file mode 100644
index 00..65dbdff41e
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_branch.c.inc
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static bool trans_b(DisasContext *ctx, arg_b *a)
+{
+gen_goto_tb(ctx, 0, ctx->base.pc_next + a->offs);
+ctx->base.is_jmp = DISAS_NORETURN;
+return true;
+}
+
+static bool trans_bl(DisasContext *ctx, arg_bl *a)
+{
+tcg_gen_movi_tl(cpu_gpr[1], ctx->base.pc_next + 4);
+gen_goto_tb(ctx, 0, ctx->base.pc_next + a->offs);
+ctx->base.is_jmp = DISAS_NORETURN;
+return true;
+}
+
+static bool trans_jirl(DisasContext *ctx, arg_jirl *a)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+tcg_gen_addi_tl(cpu_pc, src1, a->offs);
+tcg_gen_movi_tl(dest, ctx->base.pc_next + 4);
+gen_set_gpr(a->rd, dest, EXT_NONE);
+tcg_gen_lookup_and_goto_ptr();
+ctx->base.is_jmp = DISAS_NORETURN;
+return true;
+}
+
+static void gen_bc(DisasContext *ctx, TCGv src1, TCGv src2,
+   target_long offs, TCGCond cond)
+{
+TCGLabel *l = gen_new_label();
+tcg_gen_brcond_tl(cond, src1, src2, l);
+gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
+gen_set_label(l);
+gen_goto_tb(ctx, 0, ctx->base.pc_next + offs);
+ctx->base.is_jmp = DISAS_NORETURN;
+}
+
+static bool gen_rr_bc(DisasContext *ctx, arg_rr_offs *a, TCGCond cond)
+{
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rd, EXT_NONE);
+
+gen_bc(ctx, src1, src2, a->offs, cond);
+return true;
+}
+
+static bool gen_rz_bc(DisasContext *ctx, arg_r_offs *a, TCGCond cond)
+{
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = tcg_constant_tl(0);
+
+gen_bc(ctx, src1, src2, a->offs, cond);
+return true;
+}
+
+static bool gen_cz_bc(DisasContext *ctx, arg_c_offs *a, TCGCond cond)
+{
+TCGv src1 = tcg_temp_new();
+TCGv src2 = tcg_constant_tl(0);
+
+tcg_gen_ld8u_tl(src1, cpu_env,
+offsetof(CPULoongArchState, cf[a->cj]));
+gen_bc(ctx, src1, src2, a->offs, cond);
+return true;
+}
+
+TRANS(beq, gen_rr_bc, TCG_COND_EQ)
+TRANS(bne, gen_rr_bc, TCG_COND_NE)
+TRANS(blt, gen_rr_bc, TCG_COND_LT)
+TRANS(bge, gen_rr_bc, TCG_COND_GE)
+TRANS(bltu, gen_rr_bc, TCG_COND_LTU)
+TRANS(bgeu, gen_rr_bc, TCG_COND_GEU)
+TRANS(beqz, gen_rz_bc, TCG_COND_EQ)
+TRANS(bnez, gen_rz_bc, TCG_COND_NE)
+TRANS(bceqz, gen_cz_bc, TCG_COND_EQ)
+TRANS(bcnez, gen_cz_bc, TCG_COND_NE)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 8f286e7233..9b293dfdf9 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -10,6 +10,9 @@
 #
 %i14s2 10:s14   !function=shl_2
 %sa2p1 15:2 !function=plus_1
+%offs210:s5 10:16   !function=shl_2
+%offs1610:s16   !function=shl_2
+%offs260:s10 10:16  !function=shl_2
 
 #
 # Argument sets
@@ -38,6 +41,10 @@
rd cj
   fd rj rk
 _i fd rj imm
+_offs   rj offs
+_offs   cj offs
+ offs
+_offs  rj rd offs
 
 #
 # Formats
@@ -74,6 +81,10 @@
 @rc  . . .. cj:3 rd:5
 @frr     . rk:5 rj:5 fd:5
 @fr_i12  .. imm:s12 rj:5 fd:5_i
+@r_offs21  ..  rj:5 ._offs  
offs=%offs21
+@c_offs21   ..  .. cj:3 ._offs  
offs=%offs21
+@offs26 .. ..
offs=%offs26
+@rr_offs16  ..  rj:5 rd:5_offs 
offs=%offs16
 
 #
 # Fixed point arithmetic operation instruction
@@ -409,3 +420,20 @@ fstgt_s 0011 1111 01100 . . .
@frr
 fstgt_d 0011 1111 01101 . . .@frr
 fstle_s 0011 1111 01110 . . .@frr
 fstle_d 0011 1111 0 . . .@frr
+
+#
+# Branch instructions
+#
+beqz0100 00  . . @r_offs21
+bnez0100 01  . . @r_offs21
+bceqz   0100 10  00 ... .@c_offs21
+bcnez   0100 10  01 ... .@c_offs21
+j

[PATCH v1 41/43] hw/loongarch: Add LoongArch ls7a acpi device support

2022-04-15 Thread Xiaojuan Yang
Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 MAINTAINERS|   2 +
 hw/acpi/Kconfig|   4 +
 hw/acpi/ls7a.c | 374 +
 hw/acpi/meson.build|   1 +
 hw/loongarch/Kconfig   |   2 +
 hw/loongarch/loongson3.c   |  19 +-
 include/hw/acpi/ls7a.h |  53 ++
 include/hw/pci-host/ls7a.h |   6 +
 8 files changed, 458 insertions(+), 3 deletions(-)
 create mode 100644 hw/acpi/ls7a.c
 create mode 100644 include/hw/acpi/ls7a.h

diff --git a/MAINTAINERS b/MAINTAINERS
index b78ad3785f..adfbad2473 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1138,6 +1138,8 @@ F: include/hw/intc/loongarch_*.h
 F: hw/intc/loongarch_*.c
 F: include/hw/pci-host/ls7a.h
 F: hw/rtc/ls7a_rtc.c
+F: include/hw/acpi/ls7a.h
+F: hw/acpi/ls7a.c
 
 M68K Machines
 -
diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig
index 19caebde6c..ff9ceb2259 100644
--- a/hw/acpi/Kconfig
+++ b/hw/acpi/Kconfig
@@ -12,6 +12,10 @@ config ACPI_X86
 select ACPI_PCIHP
 select ACPI_ERST
 
+config ACPI_LOONGARCH
+bool
+select ACPI
+
 config ACPI_X86_ICH
 bool
 select ACPI_X86
diff --git a/hw/acpi/ls7a.c b/hw/acpi/ls7a.c
new file mode 100644
index 00..cc658422dd
--- /dev/null
+++ b/hw/acpi/ls7a.c
@@ -0,0 +1,374 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch ACPI implementation
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "sysemu/sysemu.h"
+#include "hw/hw.h"
+#include "hw/irq.h"
+#include "sysemu/reset.h"
+#include "sysemu/runstate.h"
+#include "hw/acpi/acpi.h"
+#include "hw/acpi/ls7a.h"
+#include "hw/nvram/fw_cfg.h"
+#include "qemu/config-file.h"
+#include "qapi/opts-visitor.h"
+#include "qapi/qapi-events-run-state.h"
+#include "qapi/error.h"
+#include "hw/pci-host/ls7a.h"
+#include "hw/mem/pc-dimm.h"
+#include "hw/mem/nvdimm.h"
+#include "migration/vmstate.h"
+
+static void ls7a_pm_update_sci_fn(ACPIREGS *regs)
+{
+LS7APMState *pm = container_of(regs, LS7APMState, acpi_regs);
+acpi_update_sci(>acpi_regs, pm->irq);
+}
+
+static uint64_t ls7a_gpe_readb(void *opaque, hwaddr addr, unsigned width)
+{
+LS7APMState *pm = opaque;
+return acpi_gpe_ioport_readb(>acpi_regs, addr);
+}
+
+static void ls7a_gpe_writeb(void *opaque, hwaddr addr, uint64_t val,
+unsigned width)
+{
+LS7APMState *pm = opaque;
+acpi_gpe_ioport_writeb(>acpi_regs, addr, val);
+acpi_update_sci(>acpi_regs, pm->irq);
+}
+
+static const MemoryRegionOps ls7a_gpe_ops = {
+.read = ls7a_gpe_readb,
+.write = ls7a_gpe_writeb,
+.valid.min_access_size = 1,
+.valid.max_access_size = 8,
+.impl.min_access_size = 1,
+.impl.max_access_size = 1,
+.endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+#define VMSTATE_GPE_ARRAY(_field, _state)\
+ {   \
+ .name   = (stringify(_field)),  \
+ .version_id = 0,\
+ .num= ACPI_GPE0_LEN,\
+ .info   = _info_uint8,  \
+ .size   = sizeof(uint8_t),  \
+ .flags  = VMS_ARRAY | VMS_POINTER,  \
+ .offset = vmstate_offset_pointer(_state, _field, uint8_t),  \
+ }
+
+static uint64_t ls7a_reset_readw(void *opaque, hwaddr addr, unsigned width)
+{
+return 0;
+}
+
+static void ls7a_reset_writew(void *opaque, hwaddr addr, uint64_t val,
+  unsigned width)
+{
+if (val & 1) {
+qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
+return;
+}
+}
+
+static const MemoryRegionOps ls7a_reset_ops = {
+.read = ls7a_reset_readw,
+.write = ls7a_reset_writew,
+.valid.min_access_size = 4,
+.valid.max_access_size = 4,
+.endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+const VMStateDescription vmstate_ls7a_pm = {
+.name = "ls7a_pm",
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT16(acpi_regs.pm1.evt.sts, LS7APMState),
+VMSTATE_UINT16(acpi_regs.pm1.evt.en, LS7APMState),
+VMSTATE_UINT16(acpi_regs.pm1.cnt.cnt, LS7APMState),
+VMSTATE_TIMER_PTR(acpi_regs.tmr.timer, LS7APMState),
+VMSTATE_INT64(acpi_regs.tmr.overflow_time, LS7APMState),
+VMSTATE_GPE_ARRAY(acpi_regs.gpe.sts, LS7APMState),
+VMSTATE_GPE_ARRAY(acpi_regs.gpe.en, LS7APMState),
+VMSTATE_END_OF_LIST()
+},
+};
+
+static inline int64_t acpi_pm_tmr_get_clock(void)
+{
+return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), PM_TIMER_FREQUENCY,
+  

[PATCH v1 01/43] target/loongarch: Add README

2022-04-15 Thread Xiaojuan Yang
From: Song Gao 

This patch gives an introduction to the LoongArch target.

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 MAINTAINERS |  6 ++
 target/loongarch/README | 10 ++
 2 files changed, 16 insertions(+)
 create mode 100644 target/loongarch/README

diff --git a/MAINTAINERS b/MAINTAINERS
index 4ad2451e03..94255cb04e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -213,6 +213,12 @@ S: Maintained
 F: target/hppa/
 F: disas/hppa.c
 
+LoongArch TCG CPUs
+M: Song Gao 
+M: Xiaojuan Yang 
+S: Maintained
+F: target/loongarch/
+
 M68K TCG CPUs
 M: Laurent Vivier 
 S: Maintained
diff --git a/target/loongarch/README b/target/loongarch/README
new file mode 100644
index 00..de141c1a58
--- /dev/null
+++ b/target/loongarch/README
@@ -0,0 +1,10 @@
+- Introduction
+
+  LoongArch is the general processor architecture of Loongson.
+
+  The following versions of the LoongArch core are supported
+core: 3A5000
+
https://github.com/loongson/LoongArch-Documentation/releases/download/2021.08.17/LoongArch-Vol1-v1.00-EN.pdf
+
+  We can get the latest loongarch documents at 
https://github.com/loongson/LoongArch-Documentation/tags.
+
-- 
2.31.1




[PATCH v1 19/43] target/loongarch: Add CSRs definition

2022-04-15 Thread Xiaojuan Yang
Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
---
 target/loongarch/cpu-csr.h | 201 +
 target/loongarch/cpu.c |  36 +++
 target/loongarch/cpu.h |  65 
 3 files changed, 302 insertions(+)
 create mode 100644 target/loongarch/cpu-csr.h

diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
new file mode 100644
index 00..5c89605d1a
--- /dev/null
+++ b/target/loongarch/cpu-csr.h
@@ -0,0 +1,201 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch CSRs
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef LOONGARCH_CPU_CSR_H
+#define LOONGARCH_CPU_CSR_H
+
+/* Base on kernal definitions: arch/loongarch/include/asm/loongarch.h */
+
+/* Basic CSRs */
+#define LOONGARCH_CSR_CRMD   0x0 /* Current mode info */
+
+#define LOONGARCH_CSR_PRMD   0x1 /* Prev-exception mode info */
+FIELD(CSR_PRMD, PPLV, 0, 2)
+FIELD(CSR_PRMD, PIE, 2, 1)
+FIELD(CSR_PRMD, PWE, 3, 1)
+
+#define LOONGARCH_CSR_EUEN   0x2 /* Extended unit enable */
+FIELD(CSR_EUEN, FPE, 0, 1)
+FIELD(CSR_EUEN, SXE, 1, 1)
+FIELD(CSR_EUEN, ASXE, 2, 1)
+FIELD(CSR_EUEN, BTE, 3, 1)
+
+#define LOONGARCH_CSR_MISC   0x3 /* Misc config */
+
+#define LOONGARCH_CSR_ECFG   0x4 /* Exception config */
+FIELD(CSR_ECFG, LIE, 0, 13)
+FIELD(CSR_ECFG, VS, 16, 3)
+
+#define LOONGARCH_CSR_ESTAT  0x5 /* Exception status */
+FIELD(CSR_ESTAT, IS, 0, 13)
+FIELD(CSR_ESTAT, ECODE, 16, 6)
+FIELD(CSR_ESTAT, ESUBCODE, 22, 9)
+
+#define LOONGARCH_CSR_ERA0x6 /* Exception return address */
+
+#define LOONGARCH_CSR_BADV   0x7 /* Bad virtual address */
+
+#define LOONGARCH_CSR_BADI   0x8 /* Bad instruction */
+
+#define LOONGARCH_CSR_EENTRY 0xc /* Exception entry address */
+
+/* TLB related CSRs */
+#define LOONGARCH_CSR_TLBIDX 0x10 /* TLB Index, EHINV, PageSize, NP */
+FIELD(CSR_TLBIDX, INDEX, 0, 12)
+FIELD(CSR_TLBIDX, PS, 24, 6)
+FIELD(CSR_TLBIDX, NE, 31, 1)
+
+#define LOONGARCH_CSR_TLBEHI 0x11 /* TLB EntryHi */
+FIELD(CSR_TLBEHI, VPPN, 13, 35)
+
+#define LOONGARCH_CSR_TLBELO00x12 /* TLB EntryLo0 */
+#define LOONGARCH_CSR_TLBELO10x13 /* TLB EntryLo1 */
+FIELD(TLBENTRY, V, 0, 1)
+FIELD(TLBENTRY, D, 1, 1)
+FIELD(TLBENTRY, PLV, 2, 2)
+FIELD(TLBENTRY, MAT, 4, 2)
+FIELD(TLBENTRY, G, 6, 1)
+FIELD(TLBENTRY, PPN, 12, 36)
+FIELD(TLBENTRY, NR, 61, 1)
+FIELD(TLBENTRY, NX, 62, 1)
+FIELD(TLBENTRY, RPLV, 63, 1)
+
+#define LOONGARCH_CSR_ASID   0x18 /* Address space identifier */
+FIELD(CSR_ASID, ASID, 0, 10)
+FIELD(CSR_ASID, ASIDBITS, 16, 8)
+
+/* Page table base address when badv[47] = 0 */
+#define LOONGARCH_CSR_PGDL   0x19
+/* Page table base address when badv[47] = 1 */
+#define LOONGARCH_CSR_PGDH   0x1a
+
+#define LOONGARCH_CSR_PGD0x1b /* Page table base address */
+
+/* Page walk controller's low addr */
+#define LOONGARCH_CSR_PWCL   0x1c
+FIELD(CSR_PWCL, PTBASE, 0, 5)
+FIELD(CSR_PWCL, PTWIDTH, 5, 5)
+FIELD(CSR_PWCL, DIR1_BASE, 10, 5)
+FIELD(CSR_PWCL, DIR1_WIDTH, 15, 5)
+FIELD(CSR_PWCL, DIR2_BASE, 20, 5)
+FIELD(CSR_PWCL, DIR2_WIDTH, 25, 5)
+FIELD(CSR_PWCL, PTEWIDTH, 30, 2)
+
+/* Page walk controller's high addr */
+#define LOONGARCH_CSR_PWCH   0x1d
+FIELD(CSR_PWCH, DIR3_BASE, 0, 6)
+FIELD(CSR_PWCH, DIR3_WIDTH, 6, 6)
+FIELD(CSR_PWCH, DIR4_BASE, 12, 6)
+FIELD(CSR_PWCH, DIR4_WIDTH, 18, 6)
+
+#define LOONGARCH_CSR_STLBPS 0x1e /* Stlb page size */
+FIELD(CSR_STLBPS, PS, 0, 5)
+
+#define LOONGARCH_CSR_RVACFG 0x1f /* Reduced virtual address config */
+FIELD(CSR_RVACFG, RBITS, 0, 4)
+
+/* Config CSRs */
+#define LOONGARCH_CSR_CPUID  0x20 /* CPU core id */
+
+#define LOONGARCH_CSR_PRCFG1 0x21 /* Config1 */
+FIELD(CSR_PRCFG1, SAVE_NUM, 0, 4)
+FIELD(CSR_PRCFG1, TIMER_BITS, 4, 8)
+FIELD(CSR_PRCFG1, VSMAX, 12, 3)
+
+#define LOONGARCH_CSR_PRCFG2 0x22 /* Config2 */
+
+#define LOONGARCH_CSR_PRCFG3 0x23 /* Config3 */
+FIELD(CSR_PRCFG3, TLB_TYPE, 0, 4)
+FIELD(CSR_PRCFG3, MTLB_ENTRY, 4, 8)
+FIELD(CSR_PRCFG3, STLB_WAYS, 12, 8)
+FIELD(CSR_PRCFG3, STLB_SETS, 20, 8)
+
+/*
+ * Save registers count can read from PRCFG1.SAVE_NUM
+ * The Min count is 1. Max count is 15.
+ */
+#define LOONGARCH_CSR_SAVE(N)(0x30 + N)
+
+/* Timer CSRs */
+#define LOONGARCH_CSR_TID0x40 /* Timer ID */
+
+#define LOONGARCH_CSR_TCFG   0x41 /* Timer config */
+FIELD(CSR_TCFG, EN, 0, 1)
+FIELD(CSR_TCFG, PERIODIC, 1, 1)
+FIELD(CSR_TCFG, INIT_VAL, 2, 46)
+
+#define LOONGARCH_CSR_TVAL   0x42 /* Timer ticks remain */
+
+#define LOONGARCH_CSR_CNTC   0x43 /* Timer offset */
+
+#define LOONGARCH_CSR_TICLR  0x44 /* Timer interrupt clear */
+
+/* LLBCTL CSRs */
+#define LOONGARCH_CSR_LLBCTL 0x60 /* LLBit control */
+FIELD(CSR_LLBCTL, ROLLB, 0, 1)
+FIELD(CSR_LLBCTL, WCLLB, 1, 1)
+FIELD(CSR_LLBCTL, KLO, 2, 1

[PATCH v1 31/43] hw/loongarch: Add support loongson3 virt machine type.

2022-04-15 Thread Xiaojuan Yang
Emulate a 3A5000 board use the new loongarch instruction.
3A5000 belongs to the Loongson3 series processors.
The board consists of a 3A5000 cpu model and the virt
bridge. The host 3A5000 board is really complicated and
contains many functions.Now for the tcg softmmu mode
only part functions are emulated.

More detailed info you can see
https://github.com/loongson/LoongArch-Documentation

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 MAINTAINERS   |  3 +
 .../devices/loongarch64-softmmu/default.mak   |  3 +
 configs/targets/loongarch64-softmmu.mak   |  3 +
 hw/Kconfig|  1 +
 hw/loongarch/Kconfig  |  4 +
 hw/loongarch/loongson3.c  | 90 +++
 hw/loongarch/meson.build  |  4 +
 hw/meson.build|  1 +
 include/exec/poison.h |  2 +
 include/hw/loongarch/loongarch.h  | 51 +++
 include/sysemu/arch_init.h|  1 +
 qapi/machine.json |  2 +-
 target/Kconfig|  1 +
 target/loongarch/Kconfig  |  2 +
 target/loongarch/cpu.c| 54 +++
 target/loongarch/cpu.h|  3 +
 16 files changed, 224 insertions(+), 1 deletion(-)
 create mode 100644 configs/devices/loongarch64-softmmu/default.mak
 create mode 100644 hw/loongarch/Kconfig
 create mode 100644 hw/loongarch/loongson3.c
 create mode 100644 hw/loongarch/meson.build
 create mode 100644 include/hw/loongarch/loongarch.h
 create mode 100644 target/loongarch/Kconfig

diff --git a/MAINTAINERS b/MAINTAINERS
index 92de08b19d..cbba09d0f4 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1130,7 +1130,10 @@ M: Song Gao 
 S: Maintained
 F: docs/system/loongarch/loongson3.rst
 F: configs/targets/loongarch64-softmmu.mak
+F: configs/devices/loongarch64-softmmu/default.mak
 F: gdb-xml/loongarch*.xml
+F: hw/loongarch/
+F: include/hw/loongarch/loongarch.h
 
 M68K Machines
 -
diff --git a/configs/devices/loongarch64-softmmu/default.mak 
b/configs/devices/loongarch64-softmmu/default.mak
new file mode 100644
index 00..928bc117ef
--- /dev/null
+++ b/configs/devices/loongarch64-softmmu/default.mak
@@ -0,0 +1,3 @@
+# Default configuration for loongarch64-softmmu
+
+CONFIG_LOONGARCH_VIRT=y
diff --git a/configs/targets/loongarch64-softmmu.mak 
b/configs/targets/loongarch64-softmmu.mak
index f33fa1590b..7bc06c850c 100644
--- a/configs/targets/loongarch64-softmmu.mak
+++ b/configs/targets/loongarch64-softmmu.mak
@@ -1 +1,4 @@
+TARGET_ARCH=loongarch64
+TARGET_BASE_ARCH=loongarch
+TARGET_SUPPORTS_MTTCG=y
 TARGET_XML_FILES= gdb-xml/loongarch-base64.xml gdb-xml/loongarch-fpu64.xml
diff --git a/hw/Kconfig b/hw/Kconfig
index ad20cce0a9..f71b2155ed 100644
--- a/hw/Kconfig
+++ b/hw/Kconfig
@@ -49,6 +49,7 @@ source avr/Kconfig
 source cris/Kconfig
 source hppa/Kconfig
 source i386/Kconfig
+source loongarch/Kconfig
 source m68k/Kconfig
 source microblaze/Kconfig
 source mips/Kconfig
diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
new file mode 100644
index 00..13e8501897
--- /dev/null
+++ b/hw/loongarch/Kconfig
@@ -0,0 +1,4 @@
+config LOONGARCH_VIRT
+bool
+select PCI
+select PCI_EXPRESS_GENERIC_BRIDGE
diff --git a/hw/loongarch/loongson3.c b/hw/loongarch/loongson3.c
new file mode 100644
index 00..345226dfe9
--- /dev/null
+++ b/hw/loongarch/loongson3.c
@@ -0,0 +1,90 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU loongson 3a5000 develop board emulation
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "qemu/units.h"
+#include "qemu/datadir.h"
+#include "qapi/error.h"
+#include "hw/boards.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/qtest.h"
+#include "sysemu/runstate.h"
+#include "sysemu/reset.h"
+#include "sysemu/rtc.h"
+#include "hw/loongarch/loongarch.h"
+
+#include "target/loongarch/cpu.h"
+
+static void loongarch_init(MachineState *machine)
+{
+const char *cpu_model = machine->cpu_type;
+ram_addr_t offset = 0;
+ram_addr_t ram_size = machine->ram_size;
+uint64_t highram_size = 0;
+MemoryRegion *address_space_mem = get_system_memory();
+LoongArchMachineState *lams = LOONGARCH_MACHINE(machine);
+int i;
+
+if (!cpu_model) {
+cpu_model = LOONGARCH_CPU_TYPE_NAME("Loongson-3A5000");
+}
+
+if (!strstr(cpu_model, "Loongson-3A5000")) {
+error_report("LoongArch/TCG needs cpu type Loongson-3A5000");
+exit(1);
+}
+
+/* Init CPUs */
+for (i = 0; i < machine->smp.cpus; i++) {
+cpu_create(machine->cpu_type);
+}
+
+/* Ad

[PATCH v1 09/43] target/loongarch: Add fixed point extra instruction translation

2022-04-15 Thread Xiaojuan Yang
From: Song Gao 

This includes:
- CRC[C].W.{B/H/W/D}.W
- SYSCALL
- BREAK
- ASRT{LE/GT}.D
- RDTIME{L/H}.W, RDTIME.D
- CPUCFG

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 target/loongarch/helper.h |  4 ++
 target/loongarch/insn_trans/trans_extra.c.inc | 68 +++
 target/loongarch/insns.decode | 19 ++
 target/loongarch/op_helper.c  | 30 +++-
 target/loongarch/translate.c  |  1 +
 5 files changed, 120 insertions(+), 2 deletions(-)
 create mode 100644 target/loongarch/insn_trans/trans_extra.c.inc

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 100622bfc2..638c2efc51 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -11,3 +11,7 @@ DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl)
 
 DEF_HELPER_FLAGS_3(asrtle_d, TCG_CALL_NO_WG, void, env, tl, tl)
 DEF_HELPER_FLAGS_3(asrtgt_d, TCG_CALL_NO_WG, void, env, tl, tl)
+
+DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl)
+DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl)
+DEF_HELPER_FLAGS_2(cpucfg, TCG_CALL_NO_RWG_SE, tl, env, tl)
diff --git a/target/loongarch/insn_trans/trans_extra.c.inc 
b/target/loongarch/insn_trans/trans_extra.c.inc
new file mode 100644
index 00..549f75a867
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_extra.c.inc
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static bool trans_break(DisasContext *ctx, arg_break *a)
+{
+generate_exception(ctx, EXCCODE_BRK);
+return true;
+}
+
+static bool trans_syscall(DisasContext *ctx, arg_syscall *a)
+{
+generate_exception(ctx, EXCCODE_SYS);
+return true;
+}
+
+static bool trans_asrtle_d(DisasContext *ctx, arg_asrtle_d * a)
+{
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+
+gen_helper_asrtle_d(cpu_env, src1, src2);
+return true;
+}
+
+static bool trans_asrtgt_d(DisasContext *ctx, arg_asrtgt_d * a)
+{
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+
+gen_helper_asrtgt_d(cpu_env, src1, src2);
+return true;
+}
+
+static bool trans_cpucfg(DisasContext *ctx, arg_cpucfg *a)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+gen_helper_cpucfg(dest, cpu_env, src1);
+gen_set_gpr(a->rd, dest, EXT_NONE);
+
+return true;
+}
+
+static bool gen_crc(DisasContext *ctx, arg_rrr *a,
+void (*func)(TCGv, TCGv, TCGv, TCGv),
+TCGv tsz)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_SIGN);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+
+func(dest, src2, src1, tsz);
+gen_set_gpr(a->rd, dest, EXT_SIGN);
+
+return true;
+}
+
+TRANS(crc_w_b_w, gen_crc, gen_helper_crc32, tcg_constant_tl(1))
+TRANS(crc_w_h_w, gen_crc, gen_helper_crc32, tcg_constant_tl(2))
+TRANS(crc_w_w_w, gen_crc, gen_helper_crc32, tcg_constant_tl(4))
+TRANS(crc_w_d_w, gen_crc, gen_helper_crc32, tcg_constant_tl(8))
+TRANS(crcc_w_b_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(1))
+TRANS(crcc_w_h_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(2))
+TRANS(crcc_w_w_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(4))
+TRANS(crcc_w_d_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(8))
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 8d247aa68c..98774dbddb 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -17,6 +17,7 @@
 imm
 _i  rd imm
rd rj
+_jkrj rk
   rd rj rk
 _i rd rj imm
 _r_i hint rj imm
@@ -28,6 +29,7 @@
 #
 @i15     . imm:15
 @rr     . . rj:5 rd:5
+@rr_jk  . rk:5 rj:5 ._jk
 @rrr     . rk:5 rj:5 rd:5
 @r_i20   ... imm:s20 rd:5_i
 @rr_ui5     . imm:5 rj:5 rd:5_i
@@ -237,3 +239,20 @@ ammax_db_wu 0011 1111 0 . . .
@rrr
 ammax_db_du 0011 1111 1 . . .@rrr
 ammin_db_wu 0011 1111 00010 . . .@rrr
 ammin_db_du 0011 1111 00011 . . .@rrr
+
+#
+# Fixed point extra instruction
+#
+crc_w_b_w    0010 01000 . . .@rrr
+crc_w_h_w    0010 01001 . . .@rrr
+crc_w_w_w    0010 01010 . . .@rrr
+crc_w_d_w    0010 01011 . . .@rrr
+crcc_w_b_w   0010 01100 . . .@rrr
+crcc_w_h_w   0010 01101 . . .@rrr
+crcc_w_w_w   0010 01110 . . .@rrr
+cr

[PATCH v1 20/43] target/loongarch: Add basic vmstate description of CPU.

2022-04-15 Thread Xiaojuan Yang
Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
---
 target/loongarch/cpu.c   |  1 +
 target/loongarch/internals.h |  2 +
 target/loongarch/machine.c   | 85 
 target/loongarch/meson.build |  6 +++
 4 files changed, 94 insertions(+)
 create mode 100644 target/loongarch/machine.c

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index fac67ab34a..436ced1549 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -331,6 +331,7 @@ static void loongarch_cpu_class_init(ObjectClass *c, void 
*data)
 cc->class_by_name = loongarch_cpu_class_by_name;
 cc->dump_state = loongarch_cpu_dump_state;
 cc->set_pc = loongarch_cpu_set_pc;
+dc->vmsd = _loongarch_cpu;
 cc->disas_set_info = loongarch_cpu_disas_set_info;
 #ifdef CONFIG_TCG
 cc->tcg_ops = _tcg_ops;
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index 774a87ec80..8b5588bf03 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -25,4 +25,6 @@ const char *loongarch_exception_name(int32_t exception);
 
 void restore_fp_status(CPULoongArchState *env);
 
+extern const VMStateDescription vmstate_loongarch_cpu;
+
 #endif
diff --git a/target/loongarch/machine.c b/target/loongarch/machine.c
new file mode 100644
index 00..d738c9c6f0
--- /dev/null
+++ b/target/loongarch/machine.c
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch Machine State
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "migration/cpu.h"
+
+/* LoongArch CPU state */
+
+const VMStateDescription vmstate_loongarch_cpu = {
+.name = "cpu",
+.version_id = 0,
+.minimum_version_id = 0,
+.fields = (VMStateField[]) {
+
+VMSTATE_UINTTL_ARRAY(env.gpr, LoongArchCPU, 32),
+VMSTATE_UINTTL(env.pc, LoongArchCPU),
+VMSTATE_UINT64_ARRAY(env.fpr, LoongArchCPU, 32),
+VMSTATE_UINT32(env.fcsr0, LoongArchCPU),
+
+/* Remaining CSRs */
+VMSTATE_UINT64(env.CSR_CRMD, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_PRMD, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_EUEN, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_MISC, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_ECFG, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_ESTAT, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_ERA, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_BADV, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_BADI, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_EENTRY, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBIDX, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBEHI, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBELO0, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBELO1, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_ASID, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_PGDL, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_PGDH, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_PGD, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_PWCL, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_PWCH, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_STLBPS, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_RVACFG, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_CPUID, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_PRCFG1, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_PRCFG2, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_PRCFG3, LoongArchCPU),
+VMSTATE_UINT64_ARRAY(env.CSR_SAVE, LoongArchCPU, 16),
+VMSTATE_UINT64(env.CSR_TID, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TCFG, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TVAL, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_CNTC, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TICLR, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_LLBCTL, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_IMPCTL1, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_IMPCTL2, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBRENTRY, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBRBADV, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBRERA, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBRSAVE, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBRELO0, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBRELO1, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBREHI, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBRPRMD, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_MERRCTL, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_MERRINFO1, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_MERRINFO2, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_MERRENTRY, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_MERRERA, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_MERRSAVE, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_CTAG, LoongArchCPU),
+VMSTATE_UINT64_ARRAY(env.CSR_DMW, LoongArchCPU, 4),
+
+/* Debug

[PATCH v1 25/43] target/loongarch: Add LoongArch CSR instruction

2022-04-15 Thread Xiaojuan Yang
This includes:
- CSRRD
- CSRWR
- CSRXCHG

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 target/loongarch/cpu-csr.h|   2 +
 target/loongarch/csr_helper.c | 186 ++
 target/loongarch/disas.c  |  15 ++
 target/loongarch/helper.h |   9 +
 .../insn_trans/trans_privileged.c.inc | 177 +
 target/loongarch/insns.decode |  13 ++
 target/loongarch/meson.build  |   1 +
 target/loongarch/translate.c  |   5 +
 8 files changed, 408 insertions(+)
 create mode 100644 target/loongarch/csr_helper.c
 create mode 100644 target/loongarch/insn_trans/trans_privileged.c.inc

diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
index 5c89605d1a..7a96ec7b6a 100644
--- a/target/loongarch/cpu-csr.h
+++ b/target/loongarch/cpu-csr.h
@@ -198,4 +198,6 @@ FIELD(CSR_DBG, ECODE, 16, 6)
 #define LOONGARCH_CSR_DERA   0x501 /* Debug era */
 #define LOONGARCH_CSR_DSAVE  0x502 /* Debug save */
 
+int cpu_csr_offset(unsigned csr_num);
+
 #endif /* LOONGARCH_CPU_CSR_H */
diff --git a/target/loongarch/csr_helper.c b/target/loongarch/csr_helper.c
new file mode 100644
index 00..0884e85cb0
--- /dev/null
+++ b/target/loongarch/csr_helper.c
@@ -0,0 +1,186 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch emulation helpers for CSRs
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/main-loop.h"
+#include "cpu.h"
+#include "internals.h"
+#include "qemu/host-utils.h"
+#include "exec/helper-proto.h"
+#include "exec/exec-all.h"
+#include "exec/cpu_ldst.h"
+#include "hw/irq.h"
+#include "cpu-csr.h"
+#include "hw/loongarch/loongarch.h"
+#include "tcg/tcg-ldst.h"
+
+#define CSR_OFF(X)  \
+   [LOONGARCH_CSR_##X] = offsetof(CPULoongArchState, CSR_##X)
+#define CSR_OFF_ARRAY(X, N)  \
+   [LOONGARCH_CSR_##X(N)] = offsetof(CPULoongArchState, CSR_##X[N])
+
+static const uint64_t csr_offsets[] = {
+ CSR_OFF(CRMD),
+ CSR_OFF(PRMD),
+ CSR_OFF(EUEN),
+ CSR_OFF(MISC),
+ CSR_OFF(ECFG),
+ CSR_OFF(ESTAT),
+ CSR_OFF(ERA),
+ CSR_OFF(BADV),
+ CSR_OFF(BADI),
+ CSR_OFF(EENTRY),
+ CSR_OFF(TLBIDX),
+ CSR_OFF(TLBEHI),
+ CSR_OFF(TLBELO0),
+ CSR_OFF(TLBELO1),
+ CSR_OFF(ASID),
+ CSR_OFF(PGDL),
+ CSR_OFF(PGDH),
+ CSR_OFF(PGD),
+ CSR_OFF(PWCL),
+ CSR_OFF(PWCH),
+ CSR_OFF(STLBPS),
+ CSR_OFF(RVACFG),
+ [LOONGARCH_CSR_CPUID] = offsetof(CPUState, cpu_index)
+ - offsetof(ArchCPU, env),
+ CSR_OFF(PRCFG1),
+ CSR_OFF(PRCFG2),
+ CSR_OFF(PRCFG3),
+ CSR_OFF_ARRAY(SAVE, 0),
+ CSR_OFF_ARRAY(SAVE, 1),
+ CSR_OFF_ARRAY(SAVE, 2),
+ CSR_OFF_ARRAY(SAVE, 3),
+ CSR_OFF_ARRAY(SAVE, 4),
+ CSR_OFF_ARRAY(SAVE, 5),
+ CSR_OFF_ARRAY(SAVE, 6),
+ CSR_OFF_ARRAY(SAVE, 7),
+ CSR_OFF_ARRAY(SAVE, 8),
+ CSR_OFF_ARRAY(SAVE, 9),
+ CSR_OFF_ARRAY(SAVE, 10),
+ CSR_OFF_ARRAY(SAVE, 11),
+ CSR_OFF_ARRAY(SAVE, 12),
+ CSR_OFF_ARRAY(SAVE, 13),
+ CSR_OFF_ARRAY(SAVE, 14),
+ CSR_OFF_ARRAY(SAVE, 15),
+ CSR_OFF(TID),
+ CSR_OFF(TCFG),
+ CSR_OFF(TVAL),
+ CSR_OFF(CNTC),
+ CSR_OFF(TICLR),
+ CSR_OFF(LLBCTL),
+ CSR_OFF(IMPCTL1),
+ CSR_OFF(IMPCTL2),
+ CSR_OFF(TLBRENTRY),
+ CSR_OFF(TLBRBADV),
+ CSR_OFF(TLBRERA),
+ CSR_OFF(TLBRSAVE),
+ CSR_OFF(TLBRELO0),
+ CSR_OFF(TLBRELO1),
+ CSR_OFF(TLBREHI),
+ CSR_OFF(TLBRPRMD),
+ CSR_OFF(MERRCTL),
+ CSR_OFF(MERRINFO1),
+ CSR_OFF(MERRINFO2),
+ CSR_OFF(MERRENTRY),
+ CSR_OFF(MERRERA),
+ CSR_OFF(MERRSAVE),
+ CSR_OFF(CTAG),
+ CSR_OFF_ARRAY(DMW, 0),
+ CSR_OFF_ARRAY(DMW, 1),
+ CSR_OFF_ARRAY(DMW, 2),
+ CSR_OFF_ARRAY(DMW, 3),
+ CSR_OFF(DBG),
+ CSR_OFF(DERA),
+ CSR_OFF(DSAVE),
+};
+
+int cpu_csr_offset(unsigned csr_num)
+{
+if (csr_num < ARRAY_SIZE(csr_offsets)) {
+return csr_offsets[csr_num];
+}
+return 0;
+}
+
+target_ulong helper_csrrd_pgd(CPULoongArchState *env)
+{
+int64_t v;
+
+if (env->CSR_TLBRERA & 0x1) {
+v = env->CSR_TLBRBADV;
+} else {
+v = env->CSR_BADV;
+}
+
+if ((v >> 63) & 0x1) {
+v = env->CSR_PGDH;
+} else {
+v = env->CSR_PGDL;
+}
+
+return v;
+}
+
+target_ulong helper_csrrd_tval(CPULoongArchState *env)
+{
+LoongArchCPU *cpu = LOONGARCH_CPU(env_cpu(env));
+
+return cpu_loongarch_get_constant_timer_ticks(cpu);
+}
+
+target_ulong helper_csrwr_estat(CPULoongArchState *env, target_ulong val)
+{
+int64_t old_v = env->CSR_ESTAT;
+
+/* Only IS[1:0] can be written */
+env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, IS, val 

[PATCH v1 13/43] target/loongarch: Add floating point move instruction translation

2022-04-15 Thread Xiaojuan Yang
From: Song Gao 

This includes:
- FMOV.{S/D}
- FSEL
- MOVGR2FR.{W/D}, MOVGR2FRH.W
- MOVFR2GR.{S/D}, MOVFRH2GR.S
- MOVGR2FCSR, MOVFCSR2GR
- MOVFR2CF, MOVCF2FR
- MOVGR2CF, MOVCF2GR

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 target/loongarch/fpu_helper.c|   6 +
 target/loongarch/helper.h|   2 +
 target/loongarch/insn_trans/trans_fmov.c.inc | 157 +++
 target/loongarch/insns.decode|  37 +
 target/loongarch/translate.c |   1 +
 5 files changed, 203 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_fmov.c.inc

diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c
index d69a1dd80e..1baf012ef7 100644
--- a/target/loongarch/fpu_helper.c
+++ b/target/loongarch/fpu_helper.c
@@ -854,3 +854,9 @@ uint64_t helper_ftint_w_d(CPULoongArchState *env, uint64_t 
fj)
 update_fcsr0(env, GETPC());
 return fd;
 }
+
+void helper_set_rounding_mode(CPULoongArchState *env, uint32_t fcsr0)
+{
+set_float_rounding_mode(ieee_rm[(fcsr0 >> FCSR0_RM) & 0x3],
+>fp_status);
+}
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 1e8749433a..da1a2bced7 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -90,3 +90,5 @@ DEF_HELPER_2(ftint_w_s, i64, env, i64)
 DEF_HELPER_2(ftint_w_d, i64, env, i64)
 DEF_HELPER_2(frint_s, i64, env, i64)
 DEF_HELPER_2(frint_d, i64, env, i64)
+
+DEF_HELPER_FLAGS_2(set_rounding_mode, TCG_CALL_NO_RWG, void, env, i32)
diff --git a/target/loongarch/insn_trans/trans_fmov.c.inc 
b/target/loongarch/insn_trans/trans_fmov.c.inc
new file mode 100644
index 00..24753d4568
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_fmov.c.inc
@@ -0,0 +1,157 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static const uint32_t fcsr_mask[4] = {
+UINT32_MAX, FCSR0_M1, FCSR0_M2, FCSR0_M3
+};
+
+static bool trans_fsel(DisasContext *ctx, arg_fsel *a)
+{
+TCGv zero = tcg_constant_tl(0);
+TCGv cond = tcg_temp_new();
+
+tcg_gen_ld8u_tl(cond, cpu_env, offsetof(CPULoongArchState, cf[a->ca]));
+tcg_gen_movcond_tl(TCG_COND_EQ, cpu_fpr[a->fd], cond, zero,
+   cpu_fpr[a->fj], cpu_fpr[a->fk]);
+tcg_temp_free(cond);
+
+return true;
+}
+
+static bool gen_f2f(DisasContext *ctx, arg_ff *a,
+void (*func)(TCGv, TCGv), bool nanbox)
+{
+TCGv dest = cpu_fpr[a->fd];
+TCGv src = cpu_fpr[a->fj];
+
+func(dest, src);
+if (nanbox) {
+gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]);
+}
+
+return true;
+}
+
+static bool gen_r2f(DisasContext *ctx, arg_fr *a,
+void (*func)(TCGv, TCGv))
+{
+TCGv src = gpr_src(ctx, a->rj, EXT_NONE);
+
+func(cpu_fpr[a->fd], src);
+return true;
+}
+
+static bool gen_f2r(DisasContext *ctx, arg_rf *a,
+void (*func)(TCGv, TCGv))
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+
+func(dest, cpu_fpr[a->fj]);
+gen_set_gpr(a->rd, dest, EXT_NONE);
+
+return true;
+}
+
+static bool trans_movgr2fcsr(DisasContext *ctx, arg_movgr2fcsr *a)
+{
+uint32_t mask = fcsr_mask[a->fcsrd];
+TCGv Rj = gpr_src(ctx, a->rj, EXT_NONE);
+
+if (mask == UINT32_MAX) {
+tcg_gen_extrl_i64_i32(cpu_fcsr0, Rj);
+} else {
+TCGv_i32 temp = tcg_temp_new_i32();
+
+tcg_gen_extrl_i64_i32(temp, Rj);
+tcg_gen_andi_i32(temp, temp, mask);
+tcg_gen_andi_i32(cpu_fcsr0, cpu_fcsr0, ~mask);
+tcg_gen_or_i32(cpu_fcsr0, cpu_fcsr0, temp);
+tcg_temp_free_i32(temp);
+
+/*
+ * Install the new rounding mode to fpu_status, if changed.
+ * Note that FCSR3 is exactly the rounding mode field.
+ */
+if (mask != FCSR0_M3) {
+return true;
+}
+}
+gen_helper_set_rounding_mode(cpu_env, cpu_fcsr0);
+
+return true;
+}
+
+static bool trans_movfcsr2gr(DisasContext *ctx, arg_movfcsr2gr *a)
+{
+TCGv_i32 temp = tcg_temp_new_i32();
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+
+tcg_gen_andi_i32(temp, cpu_fcsr0, fcsr_mask[a->fcsrs]);
+tcg_gen_ext_i32_i64(dest, temp);
+gen_set_gpr(a->rd, dest, EXT_NONE);
+tcg_temp_free_i32(temp);
+
+return true;
+}
+
+static void gen_movgr2fr_w(TCGv dest, TCGv src)
+{
+tcg_gen_deposit_i64(dest, dest, src, 0, 32);
+}
+
+static void gen_movgr2frh_w(TCGv dest, TCGv src)
+{
+tcg_gen_deposit_i64(dest, dest, src, 32, 32);
+}
+
+static void gen_movfrh2gr_s(TCGv dest, TCGv src)
+{
+tcg_gen_sextract_tl(dest, src, 32, 32);
+}
+
+static bool trans_movfr2cf(DisasContext *ctx, arg_movfr2cf *a)
+{
+TCGv t0 = tcg_temp_new();
+
+tcg_gen_andi_tl(t0, cpu_fpr[a->fj], 0x1);
+tcg_gen_st8_tl(t0, cpu_env, offsetof(CPULoongArchState, cf[a->c

[PATCH v1 35/43] hw/intc: Add LoongArch extioi interrupt controller(EIOINTC)

2022-04-15 Thread Xiaojuan Yang
This patch realize the EIOINTC interrupt controller.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 hw/intc/Kconfig|   3 +
 hw/intc/loongarch_extioi.c | 373 +
 hw/intc/meson.build|   1 +
 hw/intc/trace-events   |  11 +
 hw/loongarch/Kconfig   |   1 +
 include/hw/intc/loongarch_extioi.h |  68 ++
 6 files changed, 457 insertions(+)
 create mode 100644 hw/intc/loongarch_extioi.c
 create mode 100644 include/hw/intc/loongarch_extioi.h

diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
index 71c04c328e..28bd1f185d 100644
--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -96,3 +96,6 @@ config LOONGARCH_PCH_MSI
 select MSI_NONBROKEN
 bool
 select UNIMP
+
+config LOONGARCH_EXTIOI
+bool
diff --git a/hw/intc/loongarch_extioi.c b/hw/intc/loongarch_extioi.c
new file mode 100644
index 00..67be990672
--- /dev/null
+++ b/hw/intc/loongarch_extioi.c
@@ -0,0 +1,373 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Loongson 3A5000 ext interrupt controller emulation
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/module.h"
+#include "qemu/log.h"
+#include "hw/irq.h"
+#include "hw/sysbus.h"
+#include "hw/loongarch/loongarch.h"
+#include "hw/qdev-properties.h"
+#include "exec/address-spaces.h"
+#include "hw/intc/loongarch_extioi.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+
+static void extioi_update_irq(LoongArchExtIOI *s, int irq_num, int level)
+{
+uint8_t ipnum, cpu;
+
+/*
+ * Routing in group of 32 interrupts.
+ * The default value of csr[0x420][49]
+ * is 0 and nobody will change it,
+ * so 'ipmap' use bitmap function.
+ */
+ipnum = s->ipmap[irq_num / 32] & 0xf;
+ipnum = find_first_bit((unsigned long *), 4);
+ipnum = (ipnum == 4) ? 0 : ipnum;
+
+cpu = s->coremap[irq_num] & 0xf;
+cpu = find_first_bit((unsigned long *), 4);
+cpu = (cpu == 4) ? 0 : cpu;
+
+/* qemu_set_irq needs integer variable, so level is 'int' */
+if (level) {
+if (test_bit(irq_num, (unsigned long *)s->enable) == false) {
+return;
+}
+bitmap_set((unsigned long *)s->coreisr[cpu], irq_num, 1);
+qemu_set_irq(s->parent_irq[cpu][ipnum], level);
+} else {
+bitmap_clear((unsigned long *)s->coreisr[cpu], irq_num, 1);
+qemu_set_irq(s->parent_irq[cpu][ipnum], level);
+}
+}
+
+static void extioi_setirq(void *opaque, int irq, int level)
+{
+LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
+trace_loongarch_extioi_setirq(irq, level);
+extioi_update_irq(s, irq, level);
+}
+
+static uint64_t extioi_nodetype_readw(void *opaque, hwaddr addr, unsigned size)
+{
+LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
+unsigned long offset = addr & 0x;
+uint32_t index, ret = 0;
+
+switch (offset) {
+case EXTIOI_NODETYPE_START ... EXTIOI_NODETYPE_END - 1:
+index = (offset - EXTIOI_NODETYPE_START) >> 2;
+ret = s->nodetype[index];
+break;
+default:
+break;
+}
+
+trace_loongarch_extioi_nodetype_readw((uint32_t)addr, ret);
+return ret;
+}
+
+static void extioi_nodetype_writew(void *opaque, hwaddr addr,
+   uint64_t val, unsigned size)
+{
+LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
+int index;
+uint32_t offset;
+trace_loongarch_extioi_nodetype_writew(size, (uint32_t)addr, val);
+
+offset = addr & 0x;
+
+switch (offset) {
+case EXTIOI_NODETYPE_START ... EXTIOI_NODETYPE_END - 1:
+index = (offset - EXTIOI_NODETYPE_START) >> 2;
+s->nodetype[index] = val;
+break;
+default:
+break;
+}
+}
+
+static uint64_t extioi_ipmap_enable_read(void *opaque, hwaddr addr,
+ unsigned size)
+{
+LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
+uint8_t ret = 0;
+
+switch (addr) {
+case EXTIOI_IPMAP_START ... EXTIOI_IPMAP_END - 1:
+ret = s->ipmap[addr];
+break;
+case EXTIOI_ENABLE_START ... EXTIOI_ENABLE_END - 1:
+addr -= EXTIOI_ENABLE_START;
+ret = s->enable[addr];
+break;
+default:
+break;
+}
+
+trace_loongarch_extioi_ipmap_enable_read((uint8_t)addr, ret);
+return ret;
+}
+
+static void extioi_ipmap_enable_write(void *opaque, hwaddr addr,
+  uint64_t value, unsigned size)
+{
+LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
+uint8_t old_data, val = value & 0xff;
+int i, level;
+trace_loongarch_extioi_ipmap_enable_write(size, (uint8_t)addr, val);
+
+switch (addr) {
+case EXTIOI_IPMAP_START ... EXTIOI_IPMAP_END - 1:
+

[PATCH v1 34/43] hw/intc: Add LoongArch ls7a msi interrupt controller support(PCH-MSI)

2022-04-15 Thread Xiaojuan Yang
This patch realize PCH-MSI interrupt controller.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 hw/intc/Kconfig |  5 ++
 hw/intc/loongarch_pch_msi.c | 75 +
 hw/intc/meson.build |  1 +
 hw/intc/trace-events|  3 ++
 hw/loongarch/Kconfig|  1 +
 include/hw/intc/loongarch_pch_msi.h | 20 
 6 files changed, 105 insertions(+)
 create mode 100644 hw/intc/loongarch_pch_msi.c
 create mode 100644 include/hw/intc/loongarch_pch_msi.h

diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
index 1fbba2e728..71c04c328e 100644
--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -91,3 +91,8 @@ config LOONGARCH_IPI
 config LOONGARCH_PCH_PIC
 bool
 select UNIMP
+
+config LOONGARCH_PCH_MSI
+select MSI_NONBROKEN
+bool
+select UNIMP
diff --git a/hw/intc/loongarch_pch_msi.c b/hw/intc/loongarch_pch_msi.c
new file mode 100644
index 00..57a894f3e5
--- /dev/null
+++ b/hw/intc/loongarch_pch_msi.c
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU Loongson 7A1000 msi interrupt controller.
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "hw/intc/loongarch_pch_msi.h"
+#include "hw/intc/loongarch_pch_pic.h"
+#include "hw/pci/msi.h"
+#include "hw/misc/unimp.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+
+static uint64_t loongarch_msi_mem_read(void *opaque, hwaddr addr, unsigned 
size)
+{
+return 0;
+}
+
+static void loongarch_msi_mem_write(void *opaque, hwaddr addr,
+uint64_t val, unsigned size)
+{
+LoongArchPCHMSI *s = LOONGARCH_PCH_MSI(opaque);
+int irq_num = val & 0xff;
+
+trace_loongarch_msi_set_irq(irq_num);
+qemu_set_irq(s->pch_msi_irq[irq_num - PCH_PIC_IRQ_NUM], 1);
+}
+
+static const MemoryRegionOps loongarch_pch_msi_ops = {
+.read  = loongarch_msi_mem_read,
+.write = loongarch_msi_mem_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void pch_msi_irq_handler(void *opaque, int irq, int level)
+{
+LoongArchPCHMSI *s = LOONGARCH_PCH_MSI(opaque);
+
+qemu_set_irq(s->pch_msi_irq[irq], level);
+}
+
+static void loongarch_pch_msi_init(Object *obj)
+{
+LoongArchPCHMSI *s = LOONGARCH_PCH_MSI(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+int i;
+
+memory_region_init_io(>msi_mmio, obj, _pch_msi_ops,
+  s, TYPE_LOONGARCH_PCH_MSI, 0x8);
+sysbus_init_mmio(sbd, >msi_mmio);
+msi_nonbroken = true;
+
+for (i = 0; i < PCH_MSI_IRQ_NUM; i++) {
+sysbus_init_irq(sbd, >pch_msi_irq[i]);
+}
+qdev_init_gpio_in(DEVICE(obj), pch_msi_irq_handler, PCH_MSI_IRQ_NUM);
+}
+
+static const TypeInfo loongarch_pch_msi_info = {
+.name  = TYPE_LOONGARCH_PCH_MSI,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(LoongArchPCHMSI),
+.instance_init = loongarch_pch_msi_init,
+};
+
+static void loongarch_pch_msi_register_types(void)
+{
+type_register_static(_pch_msi_info);
+}
+
+type_init(loongarch_pch_msi_register_types)
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
index 960ce81a92..77a30cec33 100644
--- a/hw/intc/meson.build
+++ b/hw/intc/meson.build
@@ -64,3 +64,4 @@ specific_ss.add(when: 'CONFIG_GOLDFISH_PIC', if_true: 
files('goldfish_pic.c'))
 specific_ss.add(when: 'CONFIG_M68K_IRQC', if_true: files('m68k_irqc.c'))
 specific_ss.add(when: 'CONFIG_LOONGARCH_IPI', if_true: 
files('loongarch_ipi.c'))
 specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_PIC', if_true: 
files('loongarch_pch_pic.c'))
+specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_MSI', if_true: 
files('loongarch_pch_msi.c'))
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index 830669b547..aeee1e03de 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -288,3 +288,6 @@ loongarch_pch_pic_high_readw(unsigned size, uint32_t addr, 
unsigned long val) "s
 loongarch_pch_pic_high_writew(unsigned size, uint32_t addr, unsigned long val) 
"size: %u addr: 0x%"PRIx32 "val: 0x%" PRIx64
 loongarch_pch_pic_readb(unsigned size, uint32_t addr, unsigned long val) 
"size: %u addr: 0x%"PRIx32 "val: 0x%" PRIx64
 loongarch_pch_pic_writeb(unsigned size, uint32_t addr, unsigned long val) 
"size: %u addr: 0x%"PRIx32 "val: 0x%" PRIx64
+
+# loongarch_pch_msi.c
+loongarch_msi_set_irq(int irq_num) "set msi irq %d"
diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
index 2df45f7e8f..d814fc6103 100644
--- a/hw/loongarch/Kconfig
+++ b/hw/loongarch/Kconfig
@@ -4,3 +4,4 @@ config LOONGARCH_VIRT
 select PCI_EXPRESS_GENERIC_BRIDGE
 select LOONGARCH_IPI
 select LOONGARCH_PCH_PIC
+select LOONGARCH_PCH_MSI
diff --git a/include/hw/intc/loongarch_p

[PATCH v1 26/43] target/loongarch: Add LoongArch IOCSR instruction

2022-04-15 Thread Xiaojuan Yang
This includes:
- IOCSR{RD/WR}.{B/H/W/D}

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 target/loongarch/cpu.h|   3 +
 target/loongarch/disas.c  |   8 +
 target/loongarch/helper.h |   2 +
 .../insn_trans/trans_privileged.c.inc |  96 
 target/loongarch/insns.decode |   9 ++
 target/loongarch/iocsr_helper.c   | 139 ++
 target/loongarch/meson.build  |   1 +
 7 files changed, 258 insertions(+)
 create mode 100644 target/loongarch/iocsr_helper.c

diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index e907fe3c51..e097ca03ee 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -284,6 +284,9 @@ typedef struct CPUArchState {
 uint64_t CSR_DSAVE;
 
 LoongArchTLB  tlb[LOONGARCH_TLB_MAX];
+
+AddressSpace address_space_iocsr;
+MemoryRegion system_iocsr;
 } CPULoongArchState;
 
 /**
diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index db0e0c73fe..9cc39e7817 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -529,6 +529,14 @@ INSN(bgeu, rr_offs)
 INSN(csrrd,r_csr)
 INSN(csrwr,r_csr)
 INSN(csrxchg,  rr_csr)
+INSN(iocsrrd_b,rr)
+INSN(iocsrrd_h,rr)
+INSN(iocsrrd_w,rr)
+INSN(iocsrrd_d,rr)
+INSN(iocsrwr_b,rr)
+INSN(iocsrwr_h,rr)
+INSN(iocsrwr_w,rr)
+INSN(iocsrwr_d,rr)
 
 #define output_fcmp(C, PREFIX, SUFFIX) 
\
 {  
\
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index bd2cb3a9c5..e99a714bb4 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -101,3 +101,5 @@ DEF_HELPER_2(csrwr_asid, i64, env, tl)
 DEF_HELPER_2(csrwr_tcfg, i64, env, tl)
 DEF_HELPER_2(csrwr_ticlr, i64, env, tl)
 DEF_HELPER_3(csr_update, void, env, tl, i64)
+DEF_HELPER_3(iocsr_read, i64, env, tl, i32)
+DEF_HELPER_4(iocsr_write, void, env, tl, tl, i32)
diff --git a/target/loongarch/insn_trans/trans_privileged.c.inc 
b/target/loongarch/insn_trans/trans_privileged.c.inc
index ba111779c2..6b8b79cd1c 100644
--- a/target/loongarch/insn_trans/trans_privileged.c.inc
+++ b/target/loongarch/insn_trans/trans_privileged.c.inc
@@ -175,3 +175,99 @@ static bool trans_csrxchg(DisasContext *ctx, arg_csrxchg 
*a)
 
 return true;
 }
+
+static bool trans_iocsrrd_b(DisasContext *ctx, arg_iocsrrd_b *a)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+if (check_plv(ctx)) {
+return false;
+}
+gen_helper_iocsr_read(dest, cpu_env, src1, tcg_constant_i32(1));
+return true;
+}
+
+static bool trans_iocsrrd_h(DisasContext *ctx, arg_iocsrrd_h *a)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+if (check_plv(ctx)) {
+return false;
+}
+gen_helper_iocsr_read(dest, cpu_env, src1, tcg_constant_i32(2));
+return true;
+}
+
+static bool trans_iocsrrd_w(DisasContext *ctx, arg_iocsrrd_w *a)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+if (check_plv(ctx)) {
+return false;
+}
+gen_helper_iocsr_read(dest, cpu_env, src1, tcg_constant_i32(4));
+return true;
+}
+
+static bool trans_iocsrrd_d(DisasContext *ctx, arg_iocsrrd_d *a)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+if (check_plv(ctx)) {
+return false;
+}
+gen_helper_iocsr_read(dest, cpu_env, src1, tcg_constant_i32(8));
+return true;
+}
+
+static bool trans_iocsrwr_b(DisasContext *ctx, arg_iocsrwr_b *a)
+{
+TCGv val = gpr_src(ctx, a->rd, EXT_NONE);
+TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+
+if (check_plv(ctx)) {
+return false;
+}
+gen_helper_iocsr_write(cpu_env, addr, val, tcg_constant_i32(1));
+return true;
+}
+
+static bool trans_iocsrwr_h(DisasContext *ctx, arg_iocsrwr_h *a)
+{
+TCGv val = gpr_src(ctx, a->rd, EXT_NONE);
+TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+
+if (check_plv(ctx)) {
+return false;
+}
+gen_helper_iocsr_write(cpu_env, addr, val, tcg_constant_i32(2));
+return true;
+}
+
+static bool trans_iocsrwr_w(DisasContext *ctx, arg_iocsrwr_w *a)
+{
+TCGv val = gpr_src(ctx, a->rd, EXT_NONE);
+TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+
+if (check_plv(ctx)) {
+return false;
+}
+gen_helper_iocsr_write(cpu_env, addr, val, tcg_constant_i32(4));
+return true;
+}
+
+static bool trans_iocsrwr_d(DisasContext *ctx, arg_iocsrwr_d *a)
+{
+TCGv val = gpr_src(ctx, a->rd, EXT_NONE);
+TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+
+if (check_plv(ctx)) {
+return false;
+}
+gen_helper_iocsr_write(cpu_env, addr, val,

[PATCH v1 29/43] target/loongarch: Add timer related instructions support.

2022-04-15 Thread Xiaojuan Yang
This includes:
-RDTIME{L/H}.W
-RDTIME.D

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 target/loongarch/disas.c  |  3 ++
 target/loongarch/helper.h |  2 ++
 target/loongarch/insn_trans/trans_extra.c.inc | 33 +++
 target/loongarch/insns.decode |  3 ++
 target/loongarch/op_helper.c  | 11 +++
 target/loongarch/translate.c  |  2 ++
 6 files changed, 54 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 4ce00012a8..a2a27eee33 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -266,6 +266,9 @@ INSN(bitrev_w, rr)
 INSN(bitrev_d, rr)
 INSN(ext_w_h,  rr)
 INSN(ext_w_b,  rr)
+INSN(rdtimel_w,rr)
+INSN(rdtimeh_w,rr)
+INSN(rdtime_d, rr)
 INSN(cpucfg,   rr)
 INSN(asrtle_d, rr_jk)
 INSN(asrtgt_d, rr_jk)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index ad1a43d162..ce50e99dfc 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -93,6 +93,8 @@ DEF_HELPER_2(frint_d, i64, env, i64)
 
 DEF_HELPER_FLAGS_2(set_rounding_mode, TCG_CALL_NO_RWG, void, env, i32)
 
+DEF_HELPER_1(rdtime_d, i64, env)
+
 /* CSRs helper */
 DEF_HELPER_1(csrrd_pgd, i64, env)
 DEF_HELPER_1(csrrd_tval, i64, env)
diff --git a/target/loongarch/insn_trans/trans_extra.c.inc 
b/target/loongarch/insn_trans/trans_extra.c.inc
index 549f75a867..ad713cd61e 100644
--- a/target/loongarch/insn_trans/trans_extra.c.inc
+++ b/target/loongarch/insn_trans/trans_extra.c.inc
@@ -33,6 +33,39 @@ static bool trans_asrtgt_d(DisasContext *ctx, arg_asrtgt_d * 
a)
 return true;
 }
 
+static bool gen_rdtime(DisasContext *ctx, arg_rr *a,
+   bool word, bool high)
+{
+TCGv dst1 = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv dst2 = gpr_dst(ctx, a->rj, EXT_NONE);
+
+if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
+gen_io_start();
+}
+gen_helper_rdtime_d(dst1, cpu_env);
+if (word) {
+tcg_gen_sextract_tl(dst1, dst1, high ? 32 : 0, 32);
+}
+tcg_gen_ld_i64(dst2, cpu_env, offsetof(CPULoongArchState, CSR_TID));
+
+return true;
+}
+
+static bool trans_rdtimel_w(DisasContext *ctx, arg_rdtimel_w *a)
+{
+return gen_rdtime(ctx, a, 1, 0);
+}
+
+static bool trans_rdtimeh_w(DisasContext *ctx, arg_rdtimeh_w *a)
+{
+return gen_rdtime(ctx, a, 1, 1);
+}
+
+static bool trans_rdtime_d(DisasContext *ctx, arg_rdtime_d *a)
+{
+return gen_rdtime(ctx, a, 0, 0);
+}
+
 static bool trans_cpucfg(DisasContext *ctx, arg_cpucfg *a)
 {
 TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index ebd3d505fb..3fdc6e148c 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -309,6 +309,9 @@ break    0010 10100 ...  
@i15
 syscall  0010 10110 ...  @i15
 asrtle_d  00010 . . 0@rr_jk
 asrtgt_d  00011 . . 0@rr_jk
+rdtimel_w     0 11000 . .@rr
+rdtimeh_w     0 11001 . .@rr
+rdtime_d  0 11010 . .@rr
 cpucfg    0 11011 . .@rr
 
 #
diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c
index 2243fcfa44..57482c743a 100644
--- a/target/loongarch/op_helper.c
+++ b/target/loongarch/op_helper.c
@@ -84,6 +84,17 @@ target_ulong helper_cpucfg(CPULoongArchState *env, 
target_ulong rj)
 return rj > 21 ? 0 : env->cpucfg[rj];
 }
 
+uint64_t helper_rdtime_d(CPULoongArchState *env)
+{
+LoongArchCPU *cpu = LOONGARCH_CPU(env_cpu(env));
+
+if ((env->CSR_MISC >> 7) & 0x1) {
+do_raise_exception(env, EXCCODE_IPE, GETPC());
+}
+
+return cpu_loongarch_get_constant_timer_counter(cpu);
+}
+
 void helper_ertn(CPULoongArchState *env)
 {
 uint64_t csr_pplv, csr_pie;
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index c1cac2f006..9ce003980d 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -25,6 +25,8 @@ static TCGv cpu_lladdr, cpu_llval;
 TCGv_i32 cpu_fcsr0;
 TCGv_i64 cpu_fpr[32];
 
+#include "exec/gen-icount.h"
+
 #define DISAS_STOP   DISAS_TARGET_0
 #define DISAS_EXIT   DISAS_TARGET_1
 
-- 
2.31.1




[PATCH v1 24/43] target/loongarch: Add constant timer support

2022-04-15 Thread Xiaojuan Yang
Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 target/loongarch/constant_timer.c | 65 +++
 target/loongarch/cpu.c|  2 +
 target/loongarch/cpu.h|  4 ++
 target/loongarch/internals.h  |  6 +++
 target/loongarch/meson.build  |  1 +
 5 files changed, 78 insertions(+)
 create mode 100644 target/loongarch/constant_timer.c

diff --git a/target/loongarch/constant_timer.c 
b/target/loongarch/constant_timer.c
new file mode 100644
index 00..2286e15aa1
--- /dev/null
+++ b/target/loongarch/constant_timer.c
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch constant timer support
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "hw/loongarch/loongarch.h"
+#include "qemu/timer.h"
+#include "cpu.h"
+#include "internals.h"
+#include "cpu-csr.h"
+
+#define TIMER_PERIOD10 /* 10 ns period for 100 MHz frequency */
+#define CONSTANT_TIMER_TICK_MASK0xfffcUL
+#define CONSTANT_TIMER_ENABLE   0x1UL
+
+uint64_t cpu_loongarch_get_constant_timer_counter(LoongArchCPU *cpu)
+{
+return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / TIMER_PERIOD;
+}
+
+uint64_t cpu_loongarch_get_constant_timer_ticks(LoongArchCPU *cpu)
+{
+uint64_t now, expire;
+
+now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+expire = timer_expire_time_ns(>timer);
+
+return (expire - now) / TIMER_PERIOD;
+}
+
+void cpu_loongarch_store_constant_timer_config(LoongArchCPU *cpu,
+   uint64_t value)
+{
+CPULoongArchState *env = >env;
+uint64_t now, next;
+
+env->CSR_TCFG = value;
+if (value & CONSTANT_TIMER_ENABLE) {
+now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+next = now + (value & CONSTANT_TIMER_TICK_MASK) * TIMER_PERIOD;
+timer_mod(>timer, next);
+} else {
+timer_del(>timer);
+}
+}
+
+void loongarch_constant_timer_cb(void *opaque)
+{
+LoongArchCPU *cpu  = opaque;
+CPULoongArchState *env = >env;
+uint64_t now, next;
+
+if (FIELD_EX64(env->CSR_TCFG, CSR_TCFG, PERIODIC)) {
+now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+next = now + (env->CSR_TCFG & CONSTANT_TIMER_TICK_MASK) * TIMER_PERIOD;
+timer_mod(>timer, next);
+} else {
+env->CSR_TCFG = FIELD_DP64(env->CSR_TCFG, CSR_TCFG, EN, 0);
+}
+
+loongarch_cpu_set_irq(opaque, IRQ_TIMER, 1);
+}
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 65d2c48201..ac8d9e7d2a 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -521,6 +521,8 @@ static void loongarch_cpu_init(Object *obj)
 
 cpu_set_cpustate_pointers(cpu);
 qdev_init_gpio_in(DEVICE(cpu), loongarch_cpu_set_irq, N_IRQS);
+timer_init_ns(>timer, QEMU_CLOCK_VIRTUAL,
+  _constant_timer_cb, cpu);
 }
 
 static ObjectClass *loongarch_cpu_class_by_name(const char *cpu_model)
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index ea50b26eba..e907fe3c51 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -11,6 +11,7 @@
 #include "exec/cpu-defs.h"
 #include "fpu/softfloat-types.h"
 #include "hw/registerfields.h"
+#include "qemu/timer.h"
 
 #define TCG_GUEST_DEFAULT_MO (0)
 
@@ -185,6 +186,8 @@ extern const char * const regnames[32];
 extern const char * const fregnames[32];
 
 #define N_IRQS  13
+#define IRQ_TIMER   11
+#define IRQ_IPI 12
 
 #define LOONGARCH_STLB 2048 /* 2048 STLB */
 #define LOONGARCH_MTLB 64   /* 64 MTLB */
@@ -296,6 +299,7 @@ struct ArchCPU {
 
 CPUNegativeOffsetState neg;
 CPULoongArchState env;
+QEMUTimer timer;
 };
 
 #define TYPE_LOONGARCH_CPU "loongarch-cpu"
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index 3d64926db7..5ae8199a13 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -32,6 +32,12 @@ extern const VMStateDescription vmstate_loongarch_cpu;
 
 void loongarch_cpu_set_irq(void *opaque, int irq, int level);
 
+void loongarch_constant_timer_cb(void *opaque);
+uint64_t cpu_loongarch_get_constant_timer_counter(LoongArchCPU *cpu);
+uint64_t cpu_loongarch_get_constant_timer_ticks(LoongArchCPU *cpu);
+void cpu_loongarch_store_constant_timer_config(LoongArchCPU *cpu,
+   uint64_t value);
+
 bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
 MMUAccessType access_type, int mmu_idx,
 bool probe, uintptr_t retaddr);
diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
index 435cc75999..04e15ba1e3 100644
--- a/target/loongarch/meson.build
+++ b/target/loongarch/meson.build
@@ -18,6 +18,7 @@ loongarch_softmmu_ss = ss.s

[PATCH v1 37/43] Enable common virtio pci support for LoongArch

2022-04-15 Thread Xiaojuan Yang
Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
---
 softmmu/qdev-monitor.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c
index 12fe60c467..bb5897fc76 100644
--- a/softmmu/qdev-monitor.c
+++ b/softmmu/qdev-monitor.c
@@ -60,7 +60,8 @@ typedef struct QDevAlias
   QEMU_ARCH_HPPA | QEMU_ARCH_I386 | \
   QEMU_ARCH_MIPS | QEMU_ARCH_PPC |  \
   QEMU_ARCH_RISCV | QEMU_ARCH_SH4 | \
-  QEMU_ARCH_SPARC | QEMU_ARCH_XTENSA)
+  QEMU_ARCH_SPARC | QEMU_ARCH_XTENSA | \
+  QEMU_ARCH_LOONGARCH)
 #define QEMU_ARCH_VIRTIO_CCW (QEMU_ARCH_S390X)
 #define QEMU_ARCH_VIRTIO_MMIO (QEMU_ARCH_M68K)
 
-- 
2.31.1




[PATCH v1 32/43] hw/loongarch: Add LoongArch ipi interrupt support(IPI)

2022-04-15 Thread Xiaojuan Yang
This patch realize the IPI interrupt controller.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 MAINTAINERS  |   2 +
 hw/intc/Kconfig  |   3 +
 hw/intc/loongarch_ipi.c  | 145 +++
 hw/intc/meson.build  |   1 +
 hw/intc/trace-events |   4 +
 hw/loongarch/Kconfig |   1 +
 include/hw/intc/loongarch_ipi.h  |  46 ++
 include/hw/loongarch/loongarch.h |   2 +
 8 files changed, 204 insertions(+)
 create mode 100644 hw/intc/loongarch_ipi.c
 create mode 100644 include/hw/intc/loongarch_ipi.h

diff --git a/MAINTAINERS b/MAINTAINERS
index cbba09d0f4..3f5aaeeeba 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1134,6 +1134,8 @@ F: configs/devices/loongarch64-softmmu/default.mak
 F: gdb-xml/loongarch*.xml
 F: hw/loongarch/
 F: include/hw/loongarch/loongarch.h
+F: include/hw/intc/loongarch_*.h
+F: hw/intc/loongarch_*.c
 
 M68K Machines
 -
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
index a7cf301eab..6c7e82da64 100644
--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -84,3 +84,6 @@ config GOLDFISH_PIC
 
 config M68K_IRQC
 bool
+
+config LOONGARCH_IPI
+bool
diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c
new file mode 100644
index 00..82070f8d14
--- /dev/null
+++ b/hw/intc/loongarch_ipi.c
@@ -0,0 +1,145 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch ipi interrupt support
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/intc/loongarch_ipi.h"
+#include "hw/irq.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "exec/address-spaces.h"
+#include "hw/loongarch/loongarch.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+
+static uint64_t loongarch_ipi_readl(void *opaque, hwaddr addr, unsigned size)
+{
+LoongArchMachineState *lams = LOONGARCH_MACHINE(qdev_get_machine());
+IPICore *s = lams->ipi_core;
+uint64_t ret = 0;
+int index = 0;
+
+addr &= 0xff;
+switch (addr) {
+case CORE_STATUS_OFF:
+ret = s->status;
+break;
+case CORE_EN_OFF:
+ret = s->en;
+break;
+case CORE_SET_OFF:
+ret = 0;
+break;
+case CORE_CLEAR_OFF:
+ret = 0;
+break;
+case CORE_BUF_20 ... CORE_BUF_38 + 4:
+index = (addr - CORE_BUF_20) >> 2;
+ret = s->buf[index];
+break;
+default:
+qemu_log_mask(LOG_UNIMP, "invalid read: %x", (uint32_t)addr);
+break;
+}
+
+trace_loongarch_ipi_read(size, (uint64_t)addr, ret);
+return ret;
+}
+
+static void loongarch_ipi_writel(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
+{
+LoongArchMachineState *lams = LOONGARCH_MACHINE(qdev_get_machine());
+IPICore *s = lams->ipi_core;
+int index = 0;
+
+addr &= 0xff;
+trace_loongarch_ipi_write(size, (uint64_t)addr, val);
+switch (addr) {
+case CORE_STATUS_OFF:
+qemu_log_mask(LOG_GUEST_ERROR, "can not be written");
+break;
+case CORE_EN_OFF:
+s->en = val;
+break;
+case CORE_SET_OFF:
+s->status |= val;
+if (s->status != 0 && (s->status & s->en) != 0) {
+qemu_irq_raise(s->irq);
+}
+break;
+case CORE_CLEAR_OFF:
+s->status &= ~val;
+if (s->status == 0 && s->en != 0) {
+qemu_irq_lower(s->irq);
+}
+break;
+case CORE_BUF_20 ... CORE_BUF_38 + 4:
+index = (addr - CORE_BUF_20) >> 2;
+s->buf[index] = val;
+break;
+default:
+qemu_log_mask(LOG_UNIMP, "invalid write: %x", (uint32_t)addr);
+break;
+}
+}
+
+static const MemoryRegionOps loongarch_ipi_ops = {
+.read = loongarch_ipi_readl,
+.write = loongarch_ipi_writel,
+.impl.min_access_size = 4,
+.impl.max_access_size = 4,
+.valid.min_access_size = 4,
+.valid.max_access_size = 8,
+.endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void loongarch_ipi_init(Object *obj)
+{
+LoongArchIPI *s = LOONGARCH_IPI(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+int cpu;
+LoongArchMachineState *lams = LOONGARCH_MACHINE(qdev_get_machine());
+
+for (cpu = 0; cpu < MAX_IPI_CORE_NUM; cpu++) {
+memory_region_init_io(>ipi_mmio[cpu], obj, _ipi_ops,
+  >ipi_core[cpu], "loongarch_ipi", 0x100);
+sysbus_init_mmio(sbd, >ipi_mmio[cpu]);
+qdev_init_gpio_out(DEVICE(obj), >ipi_core[cpu].irq, 1);
+}
+}
+
+static const VMStateDescription vmstate_loongarch_ipi = {
+.name = TYPE_LOONGARCH_IPI,
+.version_id = 0,
+.minimum_version_id

[PATCH v1 05/43] target/loongarch: Add fixed point shift instruction translation

2022-04-15 Thread Xiaojuan Yang
From: Song Gao 

This includes:
- SLL.W, SRL.W, SRA.W, ROTR.W
- SLLI.W, SRLI.W, SRAI.W, ROTRI.W
- SLL.D, SRL.D, SRA.D, ROTR.D
- SLLI.D, SRLI.D, SRAI.D, ROTRI.D

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 target/loongarch/insn_trans/trans_shift.c.inc | 106 ++
 target/loongarch/insns.decode |  22 
 target/loongarch/translate.c  |   1 +
 3 files changed, 129 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_shift.c.inc

diff --git a/target/loongarch/insn_trans/trans_shift.c.inc 
b/target/loongarch/insn_trans/trans_shift.c.inc
new file mode 100644
index 00..5260af2337
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_shift.c.inc
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static void gen_sll_w(TCGv dest, TCGv src1, TCGv src2)
+{
+TCGv t0 = tcg_temp_new();
+tcg_gen_andi_tl(t0, src2, 0x1f);
+tcg_gen_shl_tl(dest, src1, t0);
+tcg_temp_free(t0);
+}
+
+static void gen_srl_w(TCGv dest, TCGv src1, TCGv src2)
+{
+TCGv t0 = tcg_temp_new();
+tcg_gen_andi_tl(t0, src2, 0x1f);
+tcg_gen_shr_tl(dest, src1, t0);
+tcg_temp_free(t0);
+}
+
+static void gen_sra_w(TCGv dest, TCGv src1, TCGv src2)
+{
+TCGv t0 = tcg_temp_new();
+tcg_gen_andi_tl(t0, src2, 0x1f);
+tcg_gen_sar_tl(dest, src1, t0);
+tcg_temp_free(t0);
+}
+
+static void gen_sll_d(TCGv dest, TCGv src1, TCGv src2)
+{
+TCGv t0 = tcg_temp_new();
+tcg_gen_andi_tl(t0, src2, 0x3f);
+tcg_gen_shl_tl(dest, src1, t0);
+tcg_temp_free(t0);
+}
+
+static void gen_srl_d(TCGv dest, TCGv src1, TCGv src2)
+{
+TCGv t0 = tcg_temp_new();
+tcg_gen_andi_tl(t0, src2, 0x3f);
+tcg_gen_shr_tl(dest, src1, t0);
+tcg_temp_free(t0);
+}
+
+static void gen_sra_d(TCGv dest, TCGv src1, TCGv src2)
+{
+TCGv t0 = tcg_temp_new();
+tcg_gen_andi_tl(t0, src2, 0x3f);
+tcg_gen_sar_tl(dest, src1, t0);
+tcg_temp_free(t0);
+}
+
+static void gen_rotr_w(TCGv dest, TCGv src1, TCGv src2)
+{
+TCGv_i32 t1 = tcg_temp_new_i32();
+TCGv_i32 t2 = tcg_temp_new_i32();
+TCGv t0 = tcg_temp_new();
+
+tcg_gen_andi_tl(t0, src2, 0x1f);
+
+tcg_gen_trunc_tl_i32(t1, src1);
+tcg_gen_trunc_tl_i32(t2, t0);
+
+tcg_gen_rotr_i32(t1, t1, t2);
+tcg_gen_ext_i32_tl(dest, t1);
+
+tcg_temp_free_i32(t1);
+tcg_temp_free_i32(t2);
+tcg_temp_free(t0);
+}
+
+static void gen_rotr_d(TCGv dest, TCGv src1, TCGv src2)
+{
+TCGv t0 = tcg_temp_new();
+tcg_gen_andi_tl(t0, src2, 0x3f);
+tcg_gen_rotr_tl(dest, src1, t0);
+tcg_temp_free(t0);
+}
+
+static bool trans_srai_w(DisasContext *ctx, arg_srai_w *a)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_ZERO);
+
+tcg_gen_sextract_tl(dest, src1, a->imm, 32 - a->imm);
+gen_set_gpr(a->rd, dest, EXT_NONE);
+
+return true;
+}
+
+TRANS(sll_w, gen_rrr, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_sll_w)
+TRANS(srl_w, gen_rrr, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_srl_w)
+TRANS(sra_w, gen_rrr, EXT_SIGN, EXT_NONE, EXT_SIGN, gen_sra_w)
+TRANS(sll_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_sll_d)
+TRANS(srl_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_srl_d)
+TRANS(sra_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_sra_d)
+TRANS(rotr_w, gen_rrr, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_rotr_w)
+TRANS(rotr_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_rotr_d)
+TRANS(slli_w, gen_rri_c, EXT_NONE, EXT_SIGN, tcg_gen_shli_tl)
+TRANS(slli_d, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_shli_tl)
+TRANS(srli_w, gen_rri_c, EXT_ZERO, EXT_SIGN, tcg_gen_shri_tl)
+TRANS(srli_d, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_shri_tl)
+TRANS(srai_d, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_sari_tl)
+TRANS(rotri_w, gen_rri_v, EXT_NONE, EXT_NONE, gen_rotr_w)
+TRANS(rotri_d, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_rotri_tl)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 8579c11984..673aee4be5 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -23,6 +23,8 @@
 #
 @rrr     . rk:5 rj:5 rd:5
 @r_i20   ... imm:s20 rd:5_i
+@rr_ui5     . imm:5 rj:5 rd:5_i
+@rr_ui6   imm:6 rj:5 rd:5_i
 @rr_i12  .. imm:s12 rj:5 rd:5_i
 @rr_ui12  .. imm:12 rj:5 rd:5_i
 @rr_i16  .. imm:s16 rj:5 rd:5_i
@@ -77,3 +79,23 @@ addu16i_d   0001 00  . . 
@rr_i16
 andi 001101  . . @rr_ui12
 ori  001110  . . @rr_ui12
 xori 00  . . @rr_ui12
+
+#
+# Fixed point shift operation instruction
+#
+sll_w    0001 01110 . . .@rrr
+srl_w

[PATCH v1 04/43] target/loongarch: Add fixed point arithmetic instruction translation

2022-04-15 Thread Xiaojuan Yang
From: Song Gao 

This includes:
- ADD.{W/D}, SUB.{W/D}
- ADDI.{W/D}, ADDU16ID
- ALSL.{W[U]/D}
- LU12I.W, LU32I.D LU52I.D
- SLT[U], SLT[U]I
- PCADDI, PCADDU12I, PCADDU18I, PCALAU12I
- AND, OR, NOR, XOR, ANDN, ORN
- MUL.{W/D}, MULH.{W[U]/D[U]}
- MULW.D.W[U]
- DIV.{W[U]/D[U]}, MOD.{W[U]/D[U]}
- ANDI, ORI, XORI

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 target/loongarch/insn_trans/trans_arith.c.inc | 304 ++
 target/loongarch/insns.decode |  79 +
 target/loongarch/translate.c  |  83 +
 target/loongarch/translate.h  |  19 ++
 4 files changed, 485 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_arith.c.inc
 create mode 100644 target/loongarch/insns.decode

diff --git a/target/loongarch/insn_trans/trans_arith.c.inc 
b/target/loongarch/insn_trans/trans_arith.c.inc
new file mode 100644
index 00..8e45eadbc8
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_arith.c.inc
@@ -0,0 +1,304 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static bool gen_rrr(DisasContext *ctx, arg_rrr *a,
+DisasExtend src1_ext, DisasExtend src2_ext,
+DisasExtend dst_ext, void (*func)(TCGv, TCGv, TCGv))
+{
+TCGv dest = gpr_dst(ctx, a->rd, dst_ext);
+TCGv src1 = gpr_src(ctx, a->rj, src1_ext);
+TCGv src2 = gpr_src(ctx, a->rk, src2_ext);
+
+func(dest, src1, src2);
+gen_set_gpr(a->rd, dest, dst_ext);
+
+return true;
+}
+
+static bool gen_rri_v(DisasContext *ctx, arg_rr_i *a,
+  DisasExtend src_ext, DisasExtend dst_ext,
+  void (*func)(TCGv, TCGv, TCGv))
+{
+TCGv dest = gpr_dst(ctx, a->rd, dst_ext);
+TCGv src1 = gpr_src(ctx, a->rj, src_ext);
+TCGv src2 = tcg_constant_tl(a->imm);
+
+func(dest, src1, src2);
+gen_set_gpr(a->rd, dest, dst_ext);
+
+return true;
+}
+
+static bool gen_rri_c(DisasContext *ctx, arg_rr_i *a,
+  DisasExtend src_ext, DisasExtend dst_ext,
+  void (*func)(TCGv, TCGv, target_long))
+{
+TCGv dest = gpr_dst(ctx, a->rd, dst_ext);
+TCGv src1 = gpr_src(ctx, a->rj, src_ext);
+
+func(dest, src1, a->imm);
+gen_set_gpr(a->rd, dest, dst_ext);
+
+return true;
+}
+
+static bool gen_rrr_sa(DisasContext *ctx, arg_rrr_sa *a,
+   DisasExtend src_ext, DisasExtend dst_ext,
+   void (*func)(TCGv, TCGv, TCGv, target_long))
+{
+TCGv dest = gpr_dst(ctx, a->rd, dst_ext);
+TCGv src1 = gpr_src(ctx, a->rj, src_ext);
+TCGv src2 = gpr_src(ctx, a->rk, src_ext);
+
+func(dest, src1, src2, a->sa);
+gen_set_gpr(a->rd, dest, dst_ext);
+
+return true;
+}
+
+static bool trans_lu12i_w(DisasContext *ctx, arg_lu12i_w *a)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+
+tcg_gen_movi_tl(dest, a->imm << 12);
+gen_set_gpr(a->rd, dest, EXT_NONE);
+
+return true;
+}
+
+static bool gen_pc(DisasContext *ctx, arg_r_i *a,
+   target_ulong (*func)(target_ulong, int))
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+target_ulong addr = func(ctx->base.pc_next, a->imm);
+
+tcg_gen_movi_tl(dest, addr);
+gen_set_gpr(a->rd, dest, EXT_NONE);
+
+return true;
+}
+
+static void gen_slt(TCGv dest, TCGv src1, TCGv src2)
+{
+tcg_gen_setcond_tl(TCG_COND_LT, dest, src1, src2);
+}
+
+static void gen_sltu(TCGv dest, TCGv src1, TCGv src2)
+{
+tcg_gen_setcond_tl(TCG_COND_LTU, dest, src1, src2);
+}
+
+static void gen_mulh_w(TCGv dest, TCGv src1, TCGv src2)
+{
+tcg_gen_mul_i64(dest, src1, src2);
+tcg_gen_sari_i64(dest, dest, 32);
+}
+
+static void gen_mulh_d(TCGv dest, TCGv src1, TCGv src2)
+{
+TCGv discard = tcg_temp_new();
+tcg_gen_muls2_tl(discard, dest, src1, src2);
+tcg_temp_free(discard);
+}
+
+static void gen_mulh_du(TCGv dest, TCGv src1, TCGv src2)
+{
+TCGv discard = tcg_temp_new();
+tcg_gen_mulu2_tl(discard, dest, src1, src2);
+tcg_temp_free(discard);
+}
+
+static void prep_divisor_d(TCGv ret, TCGv src1, TCGv src2)
+{
+TCGv t0 = tcg_temp_new();
+TCGv t1 = tcg_temp_new();
+TCGv zero = tcg_constant_tl(0);
+
+/*
+ * If min / -1, set the divisor to 1.
+ * This avoids potential host overflow trap and produces min.
+ * If x / 0, set the divisor to 1.
+ * This avoids potential host overflow trap;
+ * the required result is undefined.
+ */
+tcg_gen_setcondi_tl(TCG_COND_EQ, ret, src1, INT64_MIN);
+tcg_gen_setcondi_tl(TCG_COND_EQ, t0, src2, -1);
+tcg_gen_setcondi_tl(TCG_COND_EQ, t1, src2, 0);
+tcg_gen_and_tl(ret, ret, t0);
+tcg_gen_or_tl(ret, ret, t1);
+tcg_gen_movcond_tl(TCG_COND_NE, ret, ret, zero, ret, src2);
+
+tcg_temp_free(t0);
+tcg_temp_free(t1);
+}
+
+static void prep_divisor

[PATCH v1 23/43] target/loongarch: Add LoongArch interrupt and exception handle

2022-04-15 Thread Xiaojuan Yang
Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 target/loongarch/cpu.c   | 261 +++
 target/loongarch/cpu.h   |   2 +
 target/loongarch/internals.h |   2 +
 3 files changed, 265 insertions(+)

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 2581e60e49..65d2c48201 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -80,6 +80,246 @@ static void loongarch_cpu_set_pc(CPUState *cs, vaddr value)
 env->pc = value;
 }
 
+void loongarch_cpu_set_irq(void *opaque, int irq, int level)
+{
+LoongArchCPU *cpu = opaque;
+CPULoongArchState *env = >env;
+CPUState *cs = CPU(cpu);
+
+if (irq < 0 || irq >= N_IRQS) {
+return;
+}
+
+if (level) {
+env->CSR_ESTAT |= 1 << irq;
+} else {
+env->CSR_ESTAT &= ~(1 << irq);
+}
+
+if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) {
+cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+} else {
+cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+}
+}
+
+static inline bool cpu_loongarch_hw_interrupts_enabled(CPULoongArchState *env)
+{
+bool ret = 0;
+
+ret = (FIELD_EX64(env->CSR_CRMD, CSR_CRMD, IE) &&
+  !(FIELD_EX64(env->CSR_DBG, CSR_DBG, DST)));
+
+return ret;
+}
+
+/* Check if there is pending and not masked out interrupt */
+static inline bool cpu_loongarch_hw_interrupts_pending(CPULoongArchState *env)
+{
+uint32_t pending;
+uint32_t status;
+bool r;
+
+pending = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS);
+status  = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, LIE);
+
+r = (pending & status) != 0;
+return r;
+}
+
+static inline unsigned int get_vint_size(CPULoongArchState *env)
+{
+uint64_t vs = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, VS);
+uint64_t size = 0;
+
+if (vs == 0) {
+return 0;
+}
+
+if (vs < 8) {
+size = 1 << (vs + 2);
+}
+
+if (vs > 8) {
+qemu_log("%s: unexpected value", __func__);
+assert(0);
+}
+
+return size;
+}
+
+static void loongarch_cpu_do_interrupt(CPUState *cs)
+{
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+CPULoongArchState *env = >env;
+bool update_badinstr = 1;
+int cause = -1;
+const char *name;
+bool tlbfill = FIELD_EX64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR);
+
+if (cs->exception_index != EXCCODE_INT) {
+if (cs->exception_index < 0 ||
+cs->exception_index > ARRAY_SIZE(excp_names)) {
+name = "unknown";
+} else {
+name = excp_names[cs->exception_index];
+}
+
+qemu_log_mask(CPU_LOG_INT,
+ "%s enter: pc " TARGET_FMT_lx " ERA " TARGET_FMT_lx
+ " TLBRERA " TARGET_FMT_lx " %s exception\n", __func__,
+ env->pc, env->CSR_ERA, env->CSR_TLBRERA, name);
+}
+if (cs->exception_index == EXCCODE_INT &&
+   (FIELD_EX64(env->CSR_DBG, CSR_DBG, DST))) {
+env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, DEI, 1);
+goto set_DERA;
+}
+
+switch (cs->exception_index) {
+case EXCCODE_DBP:
+env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, DCL, 1);
+env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, ECODE, 0xC);
+goto set_DERA;
+set_DERA:
+env->CSR_DERA = env->pc;
+env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, DST, 1);
+env->pc = env->CSR_EENTRY + 0x480;
+break;
+case EXCCODE_INT:
+case EXCCODE_PIF:
+cause = cs->exception_index;
+update_badinstr = 0;
+break;
+case EXCCODE_ADEM:
+case EXCCODE_SYS:
+case EXCCODE_BRK:
+case EXCCODE_PIL:
+case EXCCODE_PIS:
+case EXCCODE_PME:
+case EXCCODE_PNR:
+case EXCCODE_PNX:
+case EXCCODE_PPI:
+case EXCCODE_INE:
+case EXCCODE_IPE:
+case EXCCODE_FPE:
+cause = cs->exception_index;
+break;
+default:
+qemu_log("Error: exception(%d) '%s' has not been supported\n",
+ cs->exception_index, excp_names[cs->exception_index]);
+abort();
+}
+
+if (update_badinstr) {
+env->CSR_BADI = cpu_ldl_code(env, env->pc);
+}
+
+/* Save PLV and IE */
+if (tlbfill) {
+env->CSR_TLBRPRMD = FIELD_DP64(env->CSR_TLBRPRMD, CSR_TLBRPRMD, PPLV,
+   FIELD_EX64(env->CSR_CRMD,
+   CSR_CRMD, PLV));
+env->CSR_TLBRPRMD = FIELD_DP64(env->CSR_TLBRPRMD, CSR_TLBRPRMD, PIE,
+   FIELD_EX64(env->CSR_CRMD, CSR_CRMD, 
IE));
+/* set the DA mode */
+env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, DA, 1);
+   

[PATCH v1 39/43] hw/loongarch: Add LoongArch ls7a rtc device support

2022-04-15 Thread Xiaojuan Yang
This patch add ls7a rtc device support.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 MAINTAINERS|   1 +
 hw/loongarch/Kconfig   |   1 +
 hw/loongarch/loongson3.c   |   4 +
 hw/rtc/Kconfig |   3 +
 hw/rtc/ls7a_rtc.c  | 323 +
 hw/rtc/meson.build |   1 +
 include/hw/pci-host/ls7a.h |   4 +
 7 files changed, 337 insertions(+)
 create mode 100644 hw/rtc/ls7a_rtc.c

diff --git a/MAINTAINERS b/MAINTAINERS
index fadb90a9d5..b78ad3785f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1137,6 +1137,7 @@ F: include/hw/loongarch/loongarch.h
 F: include/hw/intc/loongarch_*.h
 F: hw/intc/loongarch_*.c
 F: include/hw/pci-host/ls7a.h
+F: hw/rtc/ls7a_rtc.c
 
 M68K Machines
 -
diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
index 8552ff4bee..35b6680772 100644
--- a/hw/loongarch/Kconfig
+++ b/hw/loongarch/Kconfig
@@ -13,3 +13,4 @@ config LOONGARCH_VIRT
 select LOONGARCH_PCH_PIC
 select LOONGARCH_PCH_MSI
 select LOONGARCH_EXTIOI
+select LS7A_RTC
diff --git a/hw/loongarch/loongson3.c b/hw/loongarch/loongson3.c
index 057208811c..e30fcf8104 100644
--- a/hw/loongarch/loongson3.c
+++ b/hw/loongarch/loongson3.c
@@ -97,6 +97,10 @@ static void loongarch_devices_init(DeviceState *pch_pic)
  * Create some unimplemented devices to emulate this.
  */
 create_unimplemented_device("pci-dma-cfg", 0x1001041c, 0x4);
+
+sysbus_create_simple("ls7a_rtc", LS7A_RTC_REG_BASE,
+ qdev_get_gpio_in(pch_pic,
+ LS7A_RTC_IRQ - PCH_PIC_IRQ_OFFSET));
 }
 
 static void loongarch_irq_init(LoongArchMachineState *lams)
diff --git a/hw/rtc/Kconfig b/hw/rtc/Kconfig
index 730c272bc5..d0d8dda084 100644
--- a/hw/rtc/Kconfig
+++ b/hw/rtc/Kconfig
@@ -27,3 +27,6 @@ config SUN4V_RTC
 
 config GOLDFISH_RTC
 bool
+
+config LS7A_RTC
+bool
diff --git a/hw/rtc/ls7a_rtc.c b/hw/rtc/ls7a_rtc.c
new file mode 100644
index 00..d4f30c0319
--- /dev/null
+++ b/hw/rtc/ls7a_rtc.c
@@ -0,0 +1,323 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Loongarch LS7A Real Time Clock emulation
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "include/hw/register.h"
+#include "qemu/timer.h"
+#include "sysemu/sysemu.h"
+#include "qemu/cutils.h"
+#include "qemu/log.h"
+#include "migration/vmstate.h"
+#include "hw/misc/unimp.h"
+#include "sysemu/rtc.h"
+
+#define SYS_TOYTRIM0x20
+#define SYS_TOYWRITE0  0x24
+#define SYS_TOYWRITE1  0x28
+#define SYS_TOYREAD0   0x2C
+#define SYS_TOYREAD1   0x30
+#define SYS_TOYMATCH0  0x34
+#define SYS_TOYMATCH1  0x38
+#define SYS_TOYMATCH2  0x3C
+#define SYS_RTCCTRL0x40
+#define SYS_RTCTRIM0x60
+#define SYS_RTCWRTIE0  0x64
+#define SYS_RTCREAD0   0x68
+#define SYS_RTCMATCH0  0x6C
+#define SYS_RTCMATCH1  0x70
+#define SYS_RTCMATCH2  0x74
+
+/*
+ * Shift bits and filed mask
+ */
+#define TOY_MON_MASK   0x3f
+#define TOY_DAY_MASK   0x1f
+#define TOY_HOUR_MASK  0x1f
+#define TOY_MIN_MASK   0x3f
+#define TOY_SEC_MASK   0x3f
+#define TOY_MSEC_MASK  0xf
+
+#define TOY_MON_SHIFT  26
+#define TOY_DAY_SHIFT  21
+#define TOY_HOUR_SHIFT 16
+#define TOY_MIN_SHIFT  10
+#define TOY_SEC_SHIFT  4
+#define TOY_MSEC_SHIFT 0
+
+#define TOY_MATCH_YEAR_MASK  0x3f
+#define TOY_MATCH_MON_MASK   0xf
+#define TOY_MATCH_DAY_MASK   0x1f
+#define TOY_MATCH_HOUR_MASK  0x1f
+#define TOY_MATCH_MIN_MASK   0x3f
+#define TOY_MATCH_SEC_MASK   0x3f
+
+#define TOY_MATCH_YEAR_SHIFT 26
+#define TOY_MATCH_MON_SHIFT  22
+#define TOY_MATCH_DAY_SHIFT  17
+#define TOY_MATCH_HOUR_SHIFT 12
+#define TOY_MATCH_MIN_SHIFT  6
+#define TOY_MATCH_SEC_SHIFT  0
+
+#define TOY_ENABLE_BIT (1U << 11)
+
+#define TYPE_LS7A_RTC "ls7a_rtc"
+OBJECT_DECLARE_SIMPLE_TYPE(LS7ARtcState, LS7A_RTC)
+
+struct LS7ARtcState {
+SysBusDevice parent_obj;
+
+MemoryRegion iomem;
+QEMUTimer *timer;
+/*
+ * Needed to preserve the tick_count across migration, even if the
+ * absolute value of the rtc_clock is different on the source and
+ * destination.
+ */
+int64_t offset;
+int64_t data;
+int64_t save_alarm_offset;
+int tidx;
+uint32_t toymatch[3];
+uint32_t toytrim;
+uint32_t cntrctl;
+uint32_t rtctrim;
+uint32_t rtccount;
+uint32_t rtcmatch[3];
+qemu_irq toy_irq;
+};
+
+enum {
+TOYEN = 1UL << 11,
+RTCEN = 1UL << 13,
+};
+
+static uint64_t ls7a_rtc_read(void *opaque, hwaddr addr, unsigned size)
+{
+LS7ARtcState *s = LS7A_RTC(opaque);
+struct tm tm;
+unsigned int val;
+
+val = 0;
+
+switch (addr) {
+case SYS_TOYREAD0:
+qemu_get_timeda

[PATCH v1 43/43] target/loongarch: 'make check-tcg' support

2022-04-15 Thread Xiaojuan Yang
From: Song Gao 

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
Acked-by: Alex Bennée 
Reviewed-by: Philippe Mathieu-Daudé 
---
 tests/tcg/configure.sh | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh
index 84f928f7f8..90634f6d2f 100755
--- a/tests/tcg/configure.sh
+++ b/tests/tcg/configure.sh
@@ -51,6 +51,7 @@ fi
 : ${cross_cc_cflags_armeb="-mbig-endian"}
 : ${cross_cc_hexagon="hexagon-unknown-linux-musl-clang"}
 : ${cross_cc_cflags_hexagon="-mv67 -O2 -static"}
+: ${cross_cc_loongarch64="loongarch64-unknown-linux-gnu-gcc"}
 : ${cross_cc_hppa="hppa-linux-gnu-gcc"}
 : ${cross_cc_i386="i686-linux-gnu-gcc"}
 : ${cross_cc_cflags_i386="-m32"}
-- 
2.31.1




[PATCH v1 40/43] hw/loongarch: Add LoongArch boot code and load elf function.

2022-04-15 Thread Xiaojuan Yang
Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 hw/loongarch/loongson3.c | 68 +++-
 include/hw/loongarch/loongarch.h |  8 
 2 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/hw/loongarch/loongson3.c b/hw/loongarch/loongson3.c
index e30fcf8104..8806a5be96 100644
--- a/hw/loongarch/loongson3.c
+++ b/hw/loongarch/loongson3.c
@@ -18,6 +18,8 @@
 #include "sysemu/rtc.h"
 #include "hw/irq.h"
 #include "net/net.h"
+#include "hw/loader.h"
+#include "elf.h"
 #include "hw/loongarch/loongarch.h"
 #include "hw/intc/loongarch_ipi.h"
 #include "hw/intc/loongarch_extioi.h"
@@ -29,6 +31,49 @@
 
 #include "target/loongarch/cpu.h"
 
+static void ls3a5k_aui_boot(uint64_t start_addr)
+{
+unsigned int ls3a5k_aui_boot_code[] = {
+0x1864, /* pcaddi  $r4, 0x3*/
+0x28c00084, /* ld.d$r4, $r4, 0 */
+0x4c80, /* jirl$r0, $r4, 0 */
+start_addr, /* elf pc address  */
+};
+int bios_size = sizeof(ls3a5k_aui_boot_code);
+
+rom_add_blob_fixed("bios", ls3a5k_aui_boot_code, bios_size, LA_BIOS_BASE);
+}
+
+static struct _loaderparams {
+unsigned long ram_size;
+const char *kernel_filename;
+} loaderparams;
+
+static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr)
+{
+return addr & 0x1fffll;
+}
+
+static int64_t load_kernel_info(void)
+{
+int64_t kernel_entry, kernel_low, kernel_high;
+long kernel_size;
+
+kernel_size = load_elf(loaderparams.kernel_filename, NULL,
+   cpu_loongarch_virt_to_phys, NULL,
+   (uint64_t *)_entry, (uint64_t *)_low,
+   (uint64_t *)_high, NULL, 0,
+   EM_LOONGARCH, 1, 0);
+
+if (kernel_size < 0) {
+error_report("could not load kernel '%s': %s",
+ loaderparams.kernel_filename,
+ load_elf_strerror(kernel_size));
+exit(1);
+}
+return kernel_entry;
+}
+
 static void loongarch_devices_init(DeviceState *pch_pic)
 {
 DeviceState *gpex_dev;
@@ -207,12 +252,14 @@ static void loongarch_irq_init(LoongArchMachineState 
*lams)
 static void loongarch_init(MachineState *machine)
 {
 const char *cpu_model = machine->cpu_type;
+const char *kernel_filename = machine->kernel_filename;
 ram_addr_t offset = 0;
 ram_addr_t ram_size = machine->ram_size;
 uint64_t highram_size = 0;
 MemoryRegion *address_space_mem = get_system_memory();
 LoongArchMachineState *lams = LOONGARCH_MACHINE(machine);
 int i;
+int64_t kernel_addr = 0;
 
 if (!cpu_model) {
 cpu_model = LOONGARCH_CPU_TYPE_NAME("Loongson-3A5000");
@@ -228,22 +275,39 @@ static void loongarch_init(MachineState *machine)
 cpu_create(machine->cpu_type);
 }
 
+if (ram_size < 1 * GiB) {
+error_report("ram_size must be greater than 1G.");
+exit(1);
+}
+
 /* Add memory region */
 memory_region_init_alias(>lowmem, NULL, "loongarch.lowram",
  machine->ram, 0, 256 * MiB);
 memory_region_add_subregion(address_space_mem, offset, >lowmem);
 offset += 256 * MiB;
-
 highram_size = ram_size - 256 * MiB;
 memory_region_init_alias(>highmem, NULL, "loongarch.highmem",
  machine->ram, offset, highram_size);
 memory_region_add_subregion(address_space_mem, 0x9000, >highmem);
-
 /* Add isa io region */
 memory_region_init_alias(>isa_io, NULL, "isa-io",
  get_system_io(), 0, LOONGARCH_ISA_IO_SIZE);
 memory_region_add_subregion(address_space_mem, LOONGARCH_ISA_IO_BASE,
 >isa_io);
+if (kernel_filename) {
+loaderparams.ram_size = ram_size;
+loaderparams.kernel_filename = kernel_filename;
+kernel_addr = load_kernel_info();
+}
+/* load aui boot code */
+if (!machine->firmware) {
+ls3a5k_aui_boot(kernel_addr);
+}
+memory_region_init_ram(>bios, NULL, "loongarch.bios",
+   LA_BIOS_SIZE, _fatal);
+memory_region_set_readonly(>bios, true);
+memory_region_add_subregion(get_system_memory(), LA_BIOS_BASE, 
>bios);
+
 /* Initialize the IO interrupt subsystem */
 loongarch_irq_init(lams);
 }
diff --git a/include/hw/loongarch/loongarch.h b/include/hw/loongarch/loongarch.h
index a659be2a7f..718543e62f 100644
--- a/include/hw/loongarch/loongarch.h
+++ b/include/hw/loongarch/loongarch.h
@@ -39,6 +39,10 @@
 #define LOONGARCH_ISA_IO_SIZE   0x0004000
 
 struct LoongArchMachineState {
+#define FW_CFG_ADDR 0x1e02
+#define LA_BIOS_BASE0x1c00
+#define LA_BIOS_SIZE(4 * 1024 * 1024)
+
   

[PATCH v1 11/43] target/loongarch: Add floating point comparison instruction translation

2022-04-15 Thread Xiaojuan Yang
From: Song Gao 

This includes:
- FCMP.cond.{S/D}

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 target/loongarch/fpu_helper.c| 60 
 target/loongarch/helper.h|  9 +++
 target/loongarch/insn_trans/trans_fcmp.c.inc | 56 ++
 target/loongarch/insns.decode|  8 +++
 target/loongarch/internals.h |  5 ++
 target/loongarch/translate.c |  1 +
 6 files changed, 139 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_fcmp.c.inc

diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c
index e875638e1d..2ad707007a 100644
--- a/target/loongarch/fpu_helper.c
+++ b/target/loongarch/fpu_helper.c
@@ -401,3 +401,63 @@ uint64_t helper_fmuladd_d(CPULoongArchState *env, uint64_t 
fj,
 update_fcsr0(env, GETPC());
 return fd;
 }
+
+static uint64_t fcmp_common(CPULoongArchState *env, FloatRelation cmp,
+uint32_t flags)
+{
+bool ret;
+
+switch (cmp) {
+case float_relation_less:
+ret = (flags & FCMP_LT);
+break;
+case float_relation_equal:
+ret = (flags & FCMP_EQ);
+break;
+case float_relation_greater:
+ret = (flags & FCMP_GT);
+break;
+case float_relation_unordered:
+ret = (flags & FCMP_UN);
+break;
+default:
+g_assert_not_reached();
+}
+update_fcsr0(env, GETPC());
+
+return ret;
+}
+
+/* fcmp_cXXX_s */
+uint64_t helper_fcmp_c_s(CPULoongArchState *env, uint64_t fj,
+ uint64_t fk, uint32_t flags)
+{
+FloatRelation cmp = float32_compare_quiet((uint32_t)fj,
+  (uint32_t)fk, >fp_status);
+return fcmp_common(env, cmp, flags);
+}
+
+/* fcmp_sXXX_s */
+uint64_t helper_fcmp_s_s(CPULoongArchState *env, uint64_t fj,
+ uint64_t fk, uint32_t flags)
+{
+FloatRelation cmp = float32_compare((uint32_t)fj,
+(uint32_t)fk, >fp_status);
+return fcmp_common(env, cmp, flags);
+}
+
+/* fcmp_cXXX_d */
+uint64_t helper_fcmp_c_d(CPULoongArchState *env, uint64_t fj,
+ uint64_t fk, uint32_t flags)
+{
+FloatRelation cmp = float64_compare_quiet(fj, fk, >fp_status);
+return fcmp_common(env, cmp, flags);
+}
+
+/* fcmp_sXXX_d */
+uint64_t helper_fcmp_s_d(CPULoongArchState *env, uint64_t fj,
+ uint64_t fk, uint32_t flags)
+{
+FloatRelation cmp = float64_compare(fj, fk, >fp_status);
+return fcmp_common(env, cmp, flags);
+}
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 840bad9b2f..25a891bf8b 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -52,3 +52,12 @@ DEF_HELPER_FLAGS_2(frecip_d, TCG_CALL_NO_WG, i64, env, i64)
 
 DEF_HELPER_FLAGS_2(fclass_s, TCG_CALL_NO_RWG_SE, i64, env, i64)
 DEF_HELPER_FLAGS_2(fclass_d, TCG_CALL_NO_RWG_SE, i64, env, i64)
+
+/* fcmp.cXXX.s */
+DEF_HELPER_4(fcmp_c_s, i64, env, i64, i64, i32)
+/* fcmp.sXXX.s */
+DEF_HELPER_4(fcmp_s_s, i64, env, i64, i64, i32)
+/* fcmp.cXXX.d */
+DEF_HELPER_4(fcmp_c_d, i64, env, i64, i64, i32)
+/* fcmp.sXXX.d */
+DEF_HELPER_4(fcmp_s_d, i64, env, i64, i64, i32)
diff --git a/target/loongarch/insn_trans/trans_fcmp.c.inc 
b/target/loongarch/insn_trans/trans_fcmp.c.inc
new file mode 100644
index 00..93a6a2230f
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_fcmp.c.inc
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+/* bit0(signaling/quiet) bit1(lt) bit2(eq) bit3(un) bit4(neq) */
+static uint32_t get_fcmp_flags(int cond)
+{
+uint32_t flags = 0;
+
+if (cond & 0x1) {
+flags |= FCMP_LT;
+}
+if (cond & 0x2) {
+flags |= FCMP_EQ;
+}
+if (cond & 0x4) {
+flags |= FCMP_UN;
+}
+if (cond & 0x8) {
+flags |= FCMP_GT | FCMP_LT;
+}
+return flags;
+}
+
+static bool trans_fcmp_cond_s(DisasContext *ctx, arg_fcmp_cond_s *a)
+{
+TCGv var = tcg_temp_new();
+uint32_t flags;
+void (*fn)(TCGv, TCGv_env, TCGv, TCGv, TCGv_i32);
+
+fn = (a->fcond & 1 ? gen_helper_fcmp_s_s : gen_helper_fcmp_c_s);
+flags = get_fcmp_flags(a->fcond >> 1);
+
+fn(var, cpu_env, cpu_fpr[a->fj], cpu_fpr[a->fk], tcg_constant_i32(flags));
+
+tcg_gen_st8_tl(var, cpu_env, offsetof(CPULoongArchState, cf[a->cd]));
+tcg_temp_free(var);
+return true;
+}
+
+static bool trans_fcmp_cond_d(DisasContext *ctx, arg_fcmp_cond_d *a)
+{
+TCGv var = tcg_temp_new();
+uint32_t flags;
+void (*fn)(TCGv, TCGv_env, TCGv, TCGv, TCGv_i32);
+fn = (a->fcond & 1 ? gen_helper_fcmp_s_d : gen_helper_fcmp_c_d);
+flags = get_fcmp_flags(a->fcond >> 1);
+
+fn(var, cpu_env, cpu_fpr[a->fj]

[PATCH v1 17/43] target/loongarch: Add target build suport

2022-04-15 Thread Xiaojuan Yang
From: Song Gao 

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 target/loongarch/meson.build | 19 +++
 target/meson.build   |  1 +
 2 files changed, 20 insertions(+)
 create mode 100644 target/loongarch/meson.build

diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
new file mode 100644
index 00..bcb076e55f
--- /dev/null
+++ b/target/loongarch/meson.build
@@ -0,0 +1,19 @@
+gen = decodetree.process('insns.decode')
+
+loongarch_ss = ss.source_set()
+loongarch_ss.add(files(
+  'cpu.c',
+  'disas.c',
+))
+loongarch_tcg_ss = ss.source_set()
+loongarch_tcg_ss.add(gen)
+loongarch_tcg_ss.add(files(
+  'fpu_helper.c',
+  'op_helper.c',
+  'translate.c',
+))
+loongarch_tcg_ss.add(zlib)
+
+loongarch_ss.add_all(when: 'CONFIG_TCG', if_true: [loongarch_tcg_ss])
+
+target_arch += {'loongarch': loongarch_ss}
diff --git a/target/meson.build b/target/meson.build
index 2f6940255e..a53a60486f 100644
--- a/target/meson.build
+++ b/target/meson.build
@@ -5,6 +5,7 @@ subdir('cris')
 subdir('hexagon')
 subdir('hppa')
 subdir('i386')
+subdir('loongarch')
 subdir('m68k')
 subdir('microblaze')
 subdir('mips')
-- 
2.31.1




[PATCH v1 10/43] target/loongarch: Add floating point arithmetic instruction translation

2022-04-15 Thread Xiaojuan Yang
From: Song Gao 

This includes:
- F{ADD/SUB/MUL/DIV}.{S/D}
- F{MADD/MSUB/NMADD/NMSUB}.{S/D}
- F{MAX/MIN}.{S/D}
- F{MAXA/MINA}.{S/D}
- F{ABS/NEG}.{S/D}
- F{SQRT/RECIP/RSQRT}.{S/D}
- F{SCALEB/LOGB/COPYSIGN}.{S/D}
- FCLASS.{S/D}

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 target/loongarch/cpu.c|   1 +
 target/loongarch/fpu_helper.c | 403 ++
 target/loongarch/helper.h |  37 ++
 .../loongarch/insn_trans/trans_farith.c.inc   | 105 +
 target/loongarch/insns.decode |  52 +++
 target/loongarch/internals.h  |   2 +
 target/loongarch/translate.c  |  11 +
 7 files changed, 611 insertions(+)
 create mode 100644 target/loongarch/fpu_helper.c
 create mode 100644 target/loongarch/insn_trans/trans_farith.c.inc

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index f4cde31600..629d3a9130 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -196,6 +196,7 @@ static void loongarch_cpu_reset(DeviceState *dev)
 env->fcsr0_mask = FCSR0_M1 | FCSR0_M2 | FCSR0_M3;
 env->fcsr0 = 0x0;
 
+restore_fp_status(env);
 cs->exception_index = -1;
 }
 
diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c
new file mode 100644
index 00..e875638e1d
--- /dev/null
+++ b/target/loongarch/fpu_helper.c
@@ -0,0 +1,403 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch float point emulation helpers for QEMU
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "exec/helper-proto.h"
+#include "exec/exec-all.h"
+#include "exec/cpu_ldst.h"
+#include "fpu/softfloat.h"
+#include "internals.h"
+
+#define FLOAT_TO_INT32_OVERFLOW 0x7fff
+#define FLOAT_TO_INT64_OVERFLOW 0x7fffULL
+
+static inline uint64_t nanbox_s(float32 fp)
+{
+return fp | MAKE_64BIT_MASK(32, 32);
+}
+
+/* Convert loongarch rounding mode in fcsr0 to IEEE library */
+static const FloatRoundMode ieee_rm[4] = {
+float_round_nearest_even,
+float_round_to_zero,
+float_round_up,
+float_round_down
+};
+
+void restore_fp_status(CPULoongArchState *env)
+{
+set_float_rounding_mode(ieee_rm[(env->fcsr0 >> FCSR0_RM) & 0x3],
+>fp_status);
+set_flush_to_zero(0, >fp_status);
+}
+
+static int ieee_ex_to_loongarch(int xcpt)
+{
+int ret = 0;
+if (xcpt & float_flag_invalid) {
+ret |= FP_INVALID;
+}
+if (xcpt & float_flag_overflow) {
+ret |= FP_OVERFLOW;
+}
+if (xcpt & float_flag_underflow) {
+ret |= FP_UNDERFLOW;
+}
+if (xcpt & float_flag_divbyzero) {
+ret |= FP_DIV0;
+}
+if (xcpt & float_flag_inexact) {
+ret |= FP_INEXACT;
+}
+return ret;
+}
+
+static void update_fcsr0_mask(CPULoongArchState *env, uintptr_t pc, int mask)
+{
+int flags = get_float_exception_flags(>fp_status);
+
+set_float_exception_flags(0, >fp_status);
+
+flags &= ~mask;
+
+if (!flags) {
+SET_FP_CAUSE(env->fcsr0, flags);
+return;
+} else {
+flags = ieee_ex_to_loongarch(flags);
+SET_FP_CAUSE(env->fcsr0, flags);
+}
+
+if (GET_FP_ENABLES(env->fcsr0) & flags) {
+do_raise_exception(env, EXCCODE_FPE, pc);
+} else {
+UPDATE_FP_FLAGS(env->fcsr0, flags);
+}
+}
+
+static void update_fcsr0(CPULoongArchState *env, uintptr_t pc)
+{
+update_fcsr0_mask(env, pc, 0);
+}
+
+uint64_t helper_fadd_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+uint64_t fd;
+
+fd = nanbox_s(float32_add((uint32_t)fj, (uint32_t)fk, >fp_status));
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_fadd_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+uint64_t fd;
+
+fd = float64_add(fj, fk, >fp_status);
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_fsub_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+uint64_t fd;
+
+fd = nanbox_s(float32_sub((uint32_t)fj, (uint32_t)fk, >fp_status));
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_fsub_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+uint64_t fd;
+
+fd = float64_sub(fj, fk, >fp_status);
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_fmul_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+uint64_t fd;
+
+fd = nanbox_s(float32_mul((uint32_t)fj, (uint32_t)fk, >fp_status));
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_fmul_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+uint64_t fd;
+
+fd = float64_mul(fj, fk, >fp_status);
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uin

[PATCH v1 42/43] tests/tcg/loongarch64: Add hello/memory test in loongarch64 system

2022-04-15 Thread Xiaojuan Yang
- We write a very minimal softmmu harness.
- This is a very simple smoke test with no need to run a full Linux/kernel.
- The Makefile.softmmu-target record the rule to run.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 MAINTAINERS   |  1 +
 tests/tcg/loongarch64/Makefile.softmmu-target | 33 +++
 tests/tcg/loongarch64/system/boot.S   | 56 
 tests/tcg/loongarch64/system/kernel.ld| 30 +++
 tests/tcg/loongarch64/system/regdef.h | 86 +++
 5 files changed, 206 insertions(+)
 create mode 100644 tests/tcg/loongarch64/Makefile.softmmu-target
 create mode 100644 tests/tcg/loongarch64/system/boot.S
 create mode 100644 tests/tcg/loongarch64/system/kernel.ld
 create mode 100644 tests/tcg/loongarch64/system/regdef.h

diff --git a/MAINTAINERS b/MAINTAINERS
index adfbad2473..961aaa58e0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -218,6 +218,7 @@ M: Song Gao 
 M: Xiaojuan Yang 
 S: Maintained
 F: target/loongarch/
+F: tests/tcg/loongarch64/
 
 M68K TCG CPUs
 M: Laurent Vivier 
diff --git a/tests/tcg/loongarch64/Makefile.softmmu-target 
b/tests/tcg/loongarch64/Makefile.softmmu-target
new file mode 100644
index 00..908f3a8c0f
--- /dev/null
+++ b/tests/tcg/loongarch64/Makefile.softmmu-target
@@ -0,0 +1,33 @@
+#
+# Loongarch64 system tests
+#
+
+LOONGARCH64_SYSTEM_SRC=$(SRC_PATH)/tests/tcg/loongarch64/system
+VPATH+=$(LOONGARCH64_SYSTEM_SRC)
+
+# These objects provide the basic boot code and helper functions for all tests
+CRT_OBJS=boot.o
+
+LOONGARCH64_TEST_SRCS=$(wildcard $(LOONGARCH64_SYSTEM_SRC)/*.c)
+LOONGARCH64_TESTS = $(patsubst $(LOONGARCH64_SYSTEM_SRC)/%.c, %, 
$(LOONGARCH64_TEST_SRCS))
+
+CRT_PATH=$(LOONGARCH64_SYSTEM_SRC)
+LINK_SCRIPT=$(LOONGARCH64_SYSTEM_SRC)/kernel.ld
+LDFLAGS=-Wl,-T$(LINK_SCRIPT)
+TESTS+=$(LOONGARCH64_TESTS) $(MULTIARCH_TESTS)
+CFLAGS+=-nostdlib -g -O1 -march=loongarch64 -mabi=lp64d $(MINILIB_INC)
+LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc
+
+# building head blobs
+.PRECIOUS: $(CRT_OBJS)
+
+%.o: $(CRT_PATH)/%.S
+   $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -x assembler-with-cpp -c $< -o $@
+
+# Build and link the tests
+%: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
+   $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS)
+
+memory: CFLAGS+=-DCHECK_UNALIGNED=0
+# Running
+QEMU_OPTS+=-serial chardev:output -kernel
diff --git a/tests/tcg/loongarch64/system/boot.S 
b/tests/tcg/loongarch64/system/boot.S
new file mode 100644
index 00..aec116a327
--- /dev/null
+++ b/tests/tcg/loongarch64/system/boot.S
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Minimal LoongArch system boot code.
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "regdef.h"
+
+   .global _start
+   .align 16
+_start:
+   la.local t0, stack_end
+   move sp, t0
+   bl main
+
+   .type _start 2
+   .size _start, .-_start
+
+   .global _exit
+   .align 16
+_exit:
+2:  /* QEMU ACPI poweroff */
+   li.w  t0, 0x3c00
+   li.w  t1, 0x100d0014
+   st.w  t0, t1, 0
+   idle  0
+   bl2b
+
+   .type _exit 2
+   .size _exit, .-_exit
+
+   .global __sys_outc
+__sys_outc:
+   li.d t1, 100
+loop:
+   lu12i.w t2, 0x1fe00
+   ori t0, t2, 0x1e5
+   ld.bu   t0, t0, 0
+   andit0, t0, 0x20
+   ext.w.b t0, t0
+   bnezt0, in
+   addi.w  t1, t1, -1
+   bnezt1, loop
+in:
+   ext.w.b a0, a0
+   lu12i.w t0, 0x1fe00
+   ori t0, t0, 0x1e0
+   st.ba0, t0, 0
+   jirl$r0, ra, 0
+
+   .data
+   .align 4
+stack:
+   .space  65536
+stack_end:
diff --git a/tests/tcg/loongarch64/system/kernel.ld 
b/tests/tcg/loongarch64/system/kernel.ld
new file mode 100644
index 00..f1a7c0168c
--- /dev/null
+++ b/tests/tcg/loongarch64/system/kernel.ld
@@ -0,0 +1,30 @@
+ENTRY(_start)
+
+SECTIONS
+{
+/* Linux kernel legacy start address.  */
+. = 0x9020;
+_text = .;
+.text : {
+*(.text)
+}
+.rodata : {
+*(.rodata)
+}
+_etext = .;
+
+. = ALIGN(8192);
+_data = .;
+.got : {
+*(.got)
+}
+.data : {
+   *(.sdata)
+*(.data)
+}
+_edata = .;
+.bss : {
+*(.bss)
+}
+_end = .;
+}
diff --git a/tests/tcg/loongarch64/system/regdef.h 
b/tests/tcg/loongarch64/system/regdef.h
new file mode 100644
index 00..faa09b2377
--- /dev/null
+++ b/tests/tcg/loongarch64/system/regdef.h
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+#ifndef _ASM_REGDEF_H
+#define _ASM_REGDEF_H
+
+#define zero$r0 /* wired zero */
+#define ra  $r1 /* return address */
+#define tp  $r2
+#define sp  $r3 /* stack pointer */
+#define v0  $r4 /* return value - caller saved */
+#define v1 

[PATCH v1 18/43] target/loongarch: Add system emulation introduction

2022-04-15 Thread Xiaojuan Yang
Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 MAINTAINERS |  8 +
 docs/system/loongarch/loongson3.rst | 41 ++
 target/loongarch/README | 54 +
 3 files changed, 103 insertions(+)
 create mode 100644 docs/system/loongarch/loongson3.rst

diff --git a/MAINTAINERS b/MAINTAINERS
index 94255cb04e..51724ad6f6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1122,6 +1122,14 @@ F: hw/net/*i82596*
 F: include/hw/net/lasi_82596.h
 F: pc-bios/hppa-firmware.img
 
+LoongArch Machines
+--
+Virt
+M: Xiaojuan Yang 
+M: Song Gao 
+S: Maintained
+F: docs/system/loongarch/loongson3.rst
+
 M68K Machines
 -
 an5206
diff --git a/docs/system/loongarch/loongson3.rst 
b/docs/system/loongarch/loongson3.rst
new file mode 100644
index 00..fa3acd01c0
--- /dev/null
+++ b/docs/system/loongarch/loongson3.rst
@@ -0,0 +1,41 @@
+:orphan:
+
+==
+loongson3 virt generic platform (``virt``)
+==
+
+The ``virt`` machine use gpex host bridge, and there are some
+emulated devices on virt board, such as loongson7a RTC device,
+IOAPIC device, ACPI device and so on.
+
+Supported devices
+-
+
+The ``virt`` machine supports:
+- Gpex host bridge
+- Ls7a RTC device
+- Ls7a IOAPIC device
+- Ls7a ACPI device
+- Fw_cfg device
+- PCI/PCIe devices
+- Memory device
+- CPU device. Type: Loongson-3A5000.
+
+CPU and machine Type
+
+
+The ``qemu-system-loongarch64`` provides emulation for virt
+machine. You can specify the machine type ``virt`` and
+cpu type ``Loongson-3A5000``.
+
+Boot options
+
+
+Now the ``virt`` machine can run test program in ELF format and the
+method of compiling is in target/loongarch/README.
+
+.. code-block:: bash
+
+  $ qemu-system-loongarch64 -machine virt -m 4G -cpu Loongson-3A5000 \
+  -smp 1 -kernel hello -monitor none -display none \
+  -chardev file,path=hello.out,id=output -serial chardev:output
diff --git a/target/loongarch/README b/target/loongarch/README
index de141c1a58..4dcd0f1682 100644
--- a/target/loongarch/README
+++ b/target/loongarch/README
@@ -8,3 +8,57 @@
 
   We can get the latest loongarch documents at 
https://github.com/loongson/LoongArch-Documentation/tags.
 
+
+- System emulation
+
+  Mainly emulate a virt 3A5000 board and ls7a bridge that is not exactly the 
same as the host.
+  3A5000 support multiple interrupt cascading while here we just emulate the 
extioi interrupt
+  cascading. LS7A1000 host bridge support multiple devices, such as sata, 
gmac, uart, rtc
+  and so on. But we just realize the rtc. Others use the qemu common devices. 
It does not affect
+  the general use. We also introduced the emulation of devices at 
docs/system/loongarch/loongson3.rst.
+
+  This version only supports running binary files in ELF format, and does not 
depend on BIOS and kernel file.
+  You can compile the test program with 'make & make check-tcg' and run the 
test case with the following command:
+
+  1. Install LoongArch cross-tools on X86 machines.
+
+Download cross-tools.
+
+  wget 
https://github.com/loongson/build-tools/releases/latest/download/loongarch64-clfs-20211202-cross-tools.tar.xz
+
+  tar -vxf loongarch64-clfs-20211202-cross-tools.tar.xz -C /opt
+
+Config cross-tools env.
+
+  . setenv.sh
+
+  setenv.sh:
+
+  #!/bin/sh
+  set -x
+  CC_PREFIX=/opt/cross-tools
+
+  export PATH=$CC_PREFIX/bin:$PATH
+  export LD_LIBRARY_PATH=$CC_PREFIX/lib:$LD_LIBRARY_PATH
+  export 
LD_LIBRARY_PATH=$CC_PREFIX/loongarch64-unknown-linux-gnu/lib/:$LD_LIBRARY_PATH
+  set +x
+
+  2. Test tests/tcg/multiarch.
+
+./configure --disable-rdma --disable-pvrdma --prefix=/usr  \
+--target-list="loongarch64-softmmu"  \
+--disable-libiscsi --disable-libnfs --disable-libpmem \
+--disable-glusterfs --enable-libusb --enable-usb-redir \
+--disable-opengl --disable-xen --enable-spice --disable-werror \
+--enable-debug --disable-capstone --disable-kvm --enable-profiler
+
+cd  build/
+
+make && make check-tcg
+
+or
+
+./build/qemu-system-loongarch64 -machine virt -m 4G -cpu Loongson-3A5000 
-smp 1 -kernel build/tests/tcg/loongarch64-softmmu/hello -monitor none -display 
none -chardev file,path=hello.out,id=output -serial chardev:output
+
+- Note.
+  We can get the latest LoongArch documents or LoongArch tools at 
https://github.com/loongson/
-- 
2.31.1




[PATCH v1 21/43] target/loongarch: Implement qmp_query_cpu_definitions()

2022-04-15 Thread Xiaojuan Yang
Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
---
 qapi/machine-target.json |  6 --
 target/loongarch/cpu.c   | 26 ++
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/qapi/machine-target.json b/qapi/machine-target.json
index f5ec4bc172..682dc86b42 100644
--- a/qapi/machine-target.json
+++ b/qapi/machine-target.json
@@ -324,7 +324,8 @@
'TARGET_ARM',
'TARGET_I386',
'TARGET_S390X',
-   'TARGET_MIPS' ] } }
+   'TARGET_MIPS',
+   'TARGET_LOONGARCH64' ] } }
 
 ##
 # @query-cpu-definitions:
@@ -340,4 +341,5 @@
'TARGET_ARM',
'TARGET_I386',
'TARGET_S390X',
-   'TARGET_MIPS' ] } }
+   'TARGET_MIPS',
+   'TARGET_LOONGARCH64' ] } }
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 436ced1549..6cf95013ab 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -360,3 +360,29 @@ static const TypeInfo loongarch_cpu_type_infos[] = {
 };
 
 DEFINE_TYPES(loongarch_cpu_type_infos)
+
+static void loongarch_cpu_add_definition(gpointer data, gpointer user_data)
+{
+ObjectClass *oc = data;
+CpuDefinitionInfoList **cpu_list = user_data;
+CpuDefinitionInfo *info = g_new0(CpuDefinitionInfo, 1);
+const char *typename = object_class_get_name(oc);
+
+info->name = g_strndup(typename,
+   strlen(typename) - strlen("-" TYPE_LOONGARCH_CPU));
+info->q_typename = g_strdup(typename);
+
+QAPI_LIST_PREPEND(*cpu_list, info);
+}
+
+CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
+{
+CpuDefinitionInfoList *cpu_list = NULL;
+GSList *list;
+
+list = object_class_get_list(TYPE_LOONGARCH_CPU, false);
+g_slist_foreach(list, loongarch_cpu_add_definition, _list);
+g_slist_free(list);
+
+return cpu_list;
+}
-- 
2.31.1




[PATCH v1 07/43] target/loongarch: Add fixed point load/store instruction translation

2022-04-15 Thread Xiaojuan Yang
From: Song Gao 

This includes:
- LD.{B[U]/H[U]/W[U]/D}, ST.{B/H/W/D}
- LDX.{B[U]/H[U]/W[U]/D}, STX.{B/H/W/D}
- LDPTR.{W/D}, STPTR.{W/D}
- PRELD
- LD{GT/LE}.{B/H/W/D}, ST{GT/LE}.{B/H/W/D}
- DBAR, IBAR

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 target/loongarch/helper.h |   3 +
 .../loongarch/insn_trans/trans_memory.c.inc   | 229 ++
 target/loongarch/insns.decode |  55 +
 target/loongarch/op_helper.c  |  15 ++
 target/loongarch/translate.c  |   6 +
 5 files changed, 308 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_memory.c.inc

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 04e0245d5e..100622bfc2 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -8,3 +8,6 @@ DEF_HELPER_2(raise_exception, noreturn, env, i32)
 DEF_HELPER_FLAGS_1(bitrev_w, TCG_CALL_NO_RWG_SE, tl, tl)
 DEF_HELPER_FLAGS_1(bitrev_d, TCG_CALL_NO_RWG_SE, tl, tl)
 DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl)
+
+DEF_HELPER_FLAGS_3(asrtle_d, TCG_CALL_NO_WG, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(asrtgt_d, TCG_CALL_NO_WG, void, env, tl, tl)
diff --git a/target/loongarch/insn_trans/trans_memory.c.inc 
b/target/loongarch/insn_trans/trans_memory.c.inc
new file mode 100644
index 00..10914acf52
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_memory.c.inc
@@ -0,0 +1,229 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static bool gen_load(DisasContext *ctx, arg_rr_i *a, MemOp mop)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv temp = NULL;
+
+if (a->imm) {
+temp = tcg_temp_new();
+tcg_gen_addi_tl(temp, addr, a->imm);
+addr = temp;
+}
+
+tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
+gen_set_gpr(a->rd, dest, EXT_NONE);
+
+if (temp) {
+tcg_temp_free(temp);
+}
+
+return true;
+}
+
+static bool gen_store(DisasContext *ctx, arg_rr_i *a, MemOp mop)
+{
+TCGv data = gpr_src(ctx, a->rd, EXT_NONE);
+TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv temp = NULL;
+
+if (a->imm) {
+temp = tcg_temp_new();
+tcg_gen_addi_tl(temp, addr, a->imm);
+addr = temp;
+}
+
+tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, mop);
+
+if (temp) {
+tcg_temp_free(temp);
+}
+
+return true;
+}
+
+static bool gen_loadx(DisasContext *ctx, arg_rrr *a, MemOp mop)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+TCGv addr = tcg_temp_new();
+
+tcg_gen_add_tl(addr, src1, src2);
+tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
+gen_set_gpr(a->rd, dest, EXT_NONE);
+tcg_temp_free(addr);
+
+return true;
+}
+
+static bool gen_storex(DisasContext *ctx, arg_rrr *a, MemOp mop)
+{
+TCGv data = gpr_src(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+TCGv addr = tcg_temp_new();
+
+tcg_gen_add_tl(addr, src1, src2);
+tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, mop);
+tcg_temp_free(addr);
+
+return true;
+}
+
+static bool gen_load_gt(DisasContext *ctx, arg_rrr *a, MemOp mop)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+
+gen_helper_asrtgt_d(cpu_env, src1, src2);
+tcg_gen_qemu_ld_tl(dest, src1, ctx->mem_idx, mop);
+gen_set_gpr(a->rd, dest, EXT_NONE);
+
+return true;
+}
+
+static bool gen_load_le(DisasContext *ctx, arg_rrr *a, MemOp mop)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+
+gen_helper_asrtle_d(cpu_env, src1, src2);
+tcg_gen_qemu_ld_tl(dest, src1, ctx->mem_idx, mop);
+gen_set_gpr(a->rd, dest, EXT_NONE);
+
+return true;
+}
+
+static bool gen_store_gt(DisasContext *ctx, arg_rrr *a, MemOp mop)
+{
+TCGv data = gpr_src(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+
+gen_helper_asrtgt_d(cpu_env, src1, src2);
+tcg_gen_qemu_st_tl(data, src1, ctx->mem_idx, mop);
+
+return true;
+}
+
+static bool gen_store_le(DisasContext *ctx, arg_rrr *a, MemOp mop)
+{
+TCGv data = gpr_src(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+
+gen_helper_asrtle_d(cpu_env, src1, src2);
+tcg_gen_qemu_st_tl(data, src1, ctx->mem_idx, mop);
+
+return true;
+}
+
+static bool trans_preld(DisasContext *ctx, a

[PATCH 1/1] LoongArch: step down as general arch maintainer

2023-10-12 Thread Xiaojuan Yang
I haven't really been working on LoongArch for some time now,
so let's remove myself from this entry.

Signed-off-by: Xiaojuan Yang 
---
 MAINTAINERS | 2 --
 1 file changed, 2 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index c3cc12dc29..5c386f1f37 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -248,7 +248,6 @@ F: disas/hppa.c
 
 LoongArch TCG CPUs
 M: Song Gao 
-M: Xiaojuan Yang 
 S: Maintained
 F: target/loongarch/
 F: tests/tcg/loongarch64/
@@ -1182,7 +1181,6 @@ F: pc-bios/hppa-firmware.img
 LoongArch Machines
 --
 Virt
-M: Xiaojuan Yang 
 M: Song Gao 
 S: Maintained
 F: docs/system/loongarch/virt.rst
-- 
2.39.1




[PATCH v2 35/43] hw/loongarch: Add irq hierarchy for the system

2022-04-25 Thread Xiaojuan Yang
This patch add the irq hierarchy for the virt board.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
---
 hw/loongarch/loongson3.c | 116 +++
 1 file changed, 116 insertions(+)

diff --git a/hw/loongarch/loongson3.c b/hw/loongarch/loongson3.c
index a80ce8d383..4906f9926b 100644
--- a/hw/loongarch/loongson3.c
+++ b/hw/loongarch/loongson3.c
@@ -16,8 +16,122 @@
 #include "sysemu/rtc.h"
 #include "hw/loongarch/virt.h"
 #include "exec/address-spaces.h"
+#include "hw/intc/loongarch_ipi.h"
+#include "hw/intc/loongarch_extioi.h"
+#include "hw/intc/loongarch_pch_pic.h"
+#include "hw/intc/loongarch_pch_msi.h"
+#include "hw/pci-host/ls7a.h"
+
 #include "target/loongarch/cpu.h"
 
+static void loongarch_irq_init(LoongArchMachineState *lams)
+{
+MachineState *ms = MACHINE(lams);
+DeviceState *pch_pic, *pch_msi, *cpudev;
+DeviceState *ipi, *extioi;
+SysBusDevice *d;
+LoongArchCPU *lacpu;
+CPULoongArchState *env;
+CPUState *cpu_state;
+
+int cpu, pin, i;
+unsigned long ipi_addr;
+
+ipi = qdev_new(TYPE_LOONGARCH_IPI);
+sysbus_realize_and_unref(SYS_BUS_DEVICE(ipi), _fatal);
+
+extioi = qdev_new(TYPE_LOONGARCH_EXTIOI);
+sysbus_realize_and_unref(SYS_BUS_DEVICE(extioi), _fatal);
+
+/*
+ * The connection of interrupts:
+ *   +-++-+ +---+
+ *   | IPI |--> | CPUINTC | <-- | Timer |
+ *   +-++-+ +---+
+ *  ^
+ *  |
+ *+-+
+ *| EIOINTC |
+ *+-+
+ * ^   ^
+ * |   |
+ *  +-+ +-+
+ *  | PCH-PIC | | PCH-MSI |
+ *  +-+ +-+
+ *^  ^  ^
+ *|  |  |
+ * ++ +-+ +-+
+ * | UARTs  | | Devices | | Devices |
+ * ++ +-+ +-+
+ */
+for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
+cpu_state = qemu_get_cpu(cpu);
+cpudev = DEVICE(cpu_state);
+lacpu = LOONGARCH_CPU(cpu_state);
+env = &(lacpu->env);
+
+/* connect ipi irq to cpu irq */
+qdev_connect_gpio_out(ipi, cpu, qdev_get_gpio_in(cpudev, IRQ_IPI));
+/* IPI iocsr memory region */
+memory_region_add_subregion(>system_iocsr, SMP_IPI_MAILBOX,
+sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi),
+cpu * 2));
+/* IPI system memory region */
+ipi_addr = IPI_SYSTEM_MEM + cpu * 0x100;
+memory_region_add_subregion(get_system_memory(), ipi_addr,
+sysbus_mmio_get_region(SYS_BUS_DEVICE(ipi),
+cpu * 2 + 1));
+/* extioi iocsr memory region */
+memory_region_add_subregion(>system_iocsr, APIC_BASE,
+sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi),
+cpu));
+}
+
+/* extioi memory region */
+memory_region_add_subregion(get_system_memory(), EXTIOI_SYSTEM_MEM,
+sysbus_mmio_get_region(SYS_BUS_DEVICE(extioi),
+cpu));
+
+/*
+ * connect ext irq to the cpu irq
+ * cpu_pin[9:2] <= intc_pin[7:0]
+ */
+for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
+cpudev = DEVICE(qemu_get_cpu(cpu));
+for (pin = 0; pin < LS3A_INTC_IP; pin++) {
+qdev_connect_gpio_out(extioi, (cpu * 8 + pin),
+  qdev_get_gpio_in(cpudev, pin + 2));
+}
+}
+
+pch_pic = qdev_new(TYPE_LOONGARCH_PCH_PIC);
+d = SYS_BUS_DEVICE(pch_pic);
+sysbus_realize_and_unref(d, _fatal);
+memory_region_add_subregion(get_system_memory(), LS7A_IOAPIC_REG_BASE,
+sysbus_mmio_get_region(d, 0));
+memory_region_add_subregion(get_system_memory(),
+LS7A_IOAPIC_REG_BASE + PCH_PIC_ROUTE_ENTRY_OFFSET,
+sysbus_mmio_get_region(d, 1));
+memory_region_add_subregion(get_system_memory(),
+LS7A_IOAPIC_REG_BASE + PCH_PIC_INT_STATUS_LO,
+sysbus_mmio_get_region(d, 2));
+
+/* Connect 64 pch_pic irqs to extioi */
+for (int i = 0; i < PCH_PIC_IRQ_NUM; i++) {
+sysbus_connect_irq(d, i, qdev_get_gpio_in(extioi, i));
+}
+
+pch_msi = qdev_new(TYPE_LOONGARCH_PCH_MSI);
+d = SYS_BUS_DEVICE(pch_msi);
+sysbus_realize_and_unref(d, _fatal);
+sysbus_mmio_map(d, 0, LS7A_PCH_MSI_ADDR_LOW);
+for (i = 0; i < PCH_MSI_IRQ_NUM; i++) {
+/* Connect 192 pch_msi irqs to extioi */
+sysbus_connect_irq(d, i,
+ 

[PATCH v2 40/43] hw/loongarch: Add LoongArch ls7a acpi device support

2022-04-25 Thread Xiaojuan Yang
Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 MAINTAINERS|   2 +
 hw/acpi/Kconfig|   4 +
 hw/acpi/ls7a.c | 374 +
 hw/acpi/meson.build|   1 +
 hw/loongarch/Kconfig   |   2 +
 hw/loongarch/loongson3.c   |  19 +-
 include/hw/acpi/ls7a.h |  53 ++
 include/hw/pci-host/ls7a.h |   6 +
 8 files changed, 458 insertions(+), 3 deletions(-)
 create mode 100644 hw/acpi/ls7a.c
 create mode 100644 include/hw/acpi/ls7a.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 7969004b91..18d06bb859 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1138,6 +1138,8 @@ F: include/hw/intc/loongarch_*.h
 F: hw/intc/loongarch_*.c
 F: include/hw/pci-host/ls7a.h
 F: hw/rtc/ls7a_rtc.c
+F: include/hw/acpi/ls7a.h
+F: hw/acpi/ls7a.c
 
 M68K Machines
 -
diff --git a/hw/acpi/Kconfig b/hw/acpi/Kconfig
index 19caebde6c..ff9ceb2259 100644
--- a/hw/acpi/Kconfig
+++ b/hw/acpi/Kconfig
@@ -12,6 +12,10 @@ config ACPI_X86
 select ACPI_PCIHP
 select ACPI_ERST
 
+config ACPI_LOONGARCH
+bool
+select ACPI
+
 config ACPI_X86_ICH
 bool
 select ACPI_X86
diff --git a/hw/acpi/ls7a.c b/hw/acpi/ls7a.c
new file mode 100644
index 00..cc658422dd
--- /dev/null
+++ b/hw/acpi/ls7a.c
@@ -0,0 +1,374 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch ACPI implementation
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "sysemu/sysemu.h"
+#include "hw/hw.h"
+#include "hw/irq.h"
+#include "sysemu/reset.h"
+#include "sysemu/runstate.h"
+#include "hw/acpi/acpi.h"
+#include "hw/acpi/ls7a.h"
+#include "hw/nvram/fw_cfg.h"
+#include "qemu/config-file.h"
+#include "qapi/opts-visitor.h"
+#include "qapi/qapi-events-run-state.h"
+#include "qapi/error.h"
+#include "hw/pci-host/ls7a.h"
+#include "hw/mem/pc-dimm.h"
+#include "hw/mem/nvdimm.h"
+#include "migration/vmstate.h"
+
+static void ls7a_pm_update_sci_fn(ACPIREGS *regs)
+{
+LS7APMState *pm = container_of(regs, LS7APMState, acpi_regs);
+acpi_update_sci(>acpi_regs, pm->irq);
+}
+
+static uint64_t ls7a_gpe_readb(void *opaque, hwaddr addr, unsigned width)
+{
+LS7APMState *pm = opaque;
+return acpi_gpe_ioport_readb(>acpi_regs, addr);
+}
+
+static void ls7a_gpe_writeb(void *opaque, hwaddr addr, uint64_t val,
+unsigned width)
+{
+LS7APMState *pm = opaque;
+acpi_gpe_ioport_writeb(>acpi_regs, addr, val);
+acpi_update_sci(>acpi_regs, pm->irq);
+}
+
+static const MemoryRegionOps ls7a_gpe_ops = {
+.read = ls7a_gpe_readb,
+.write = ls7a_gpe_writeb,
+.valid.min_access_size = 1,
+.valid.max_access_size = 8,
+.impl.min_access_size = 1,
+.impl.max_access_size = 1,
+.endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+#define VMSTATE_GPE_ARRAY(_field, _state)\
+ {   \
+ .name   = (stringify(_field)),  \
+ .version_id = 0,\
+ .num= ACPI_GPE0_LEN,\
+ .info   = _info_uint8,  \
+ .size   = sizeof(uint8_t),  \
+ .flags  = VMS_ARRAY | VMS_POINTER,  \
+ .offset = vmstate_offset_pointer(_state, _field, uint8_t),  \
+ }
+
+static uint64_t ls7a_reset_readw(void *opaque, hwaddr addr, unsigned width)
+{
+return 0;
+}
+
+static void ls7a_reset_writew(void *opaque, hwaddr addr, uint64_t val,
+  unsigned width)
+{
+if (val & 1) {
+qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
+return;
+}
+}
+
+static const MemoryRegionOps ls7a_reset_ops = {
+.read = ls7a_reset_readw,
+.write = ls7a_reset_writew,
+.valid.min_access_size = 4,
+.valid.max_access_size = 4,
+.endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+const VMStateDescription vmstate_ls7a_pm = {
+.name = "ls7a_pm",
+.version_id = 1,
+.minimum_version_id = 1,
+.fields = (VMStateField[]) {
+VMSTATE_UINT16(acpi_regs.pm1.evt.sts, LS7APMState),
+VMSTATE_UINT16(acpi_regs.pm1.evt.en, LS7APMState),
+VMSTATE_UINT16(acpi_regs.pm1.cnt.cnt, LS7APMState),
+VMSTATE_TIMER_PTR(acpi_regs.tmr.timer, LS7APMState),
+VMSTATE_INT64(acpi_regs.tmr.overflow_time, LS7APMState),
+VMSTATE_GPE_ARRAY(acpi_regs.gpe.sts, LS7APMState),
+VMSTATE_GPE_ARRAY(acpi_regs.gpe.en, LS7APMState),
+VMSTATE_END_OF_LIST()
+},
+};
+
+static inline int64_t acpi_pm_tmr_get_clock(void)
+{
+return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL), PM_TIMER_FREQUENCY,
+  

[PATCH v2 22/43] target/loongarch: Add MMU support for LoongArch CPU.

2022-04-25 Thread Xiaojuan Yang
Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
---
 target/loongarch/cpu-param.h  |   2 +-
 target/loongarch/cpu.c|  24 +++
 target/loongarch/cpu.h|  51 ++
 target/loongarch/internals.h  |   9 +
 target/loongarch/machine.c|  17 ++
 target/loongarch/meson.build  |   1 +
 target/loongarch/tlb_helper.c | 315 ++
 7 files changed, 418 insertions(+), 1 deletion(-)
 create mode 100644 target/loongarch/tlb_helper.c

diff --git a/target/loongarch/cpu-param.h b/target/loongarch/cpu-param.h
index 9a769b67e0..414d8fff46 100644
--- a/target/loongarch/cpu-param.h
+++ b/target/loongarch/cpu-param.h
@@ -13,6 +13,6 @@
 #define TARGET_VIRT_ADDR_SPACE_BITS 48
 
 #define TARGET_PAGE_BITS 14
-#define NB_MMU_MODES 4
+#define NB_MMU_MODES 5
 
 #endif
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 176e277197..8a6bc24630 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -298,6 +298,21 @@ void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int 
flags)
 }
 }
 
+qemu_fprintf(f, "CRMD=%016" PRIx64 "\n", env->CSR_CRMD);
+qemu_fprintf(f, "PRMD=%016" PRIx64 "\n", env->CSR_PRMD);
+qemu_fprintf(f, "EUEN=%016" PRIx64 "\n", env->CSR_EUEN);
+qemu_fprintf(f, "ESTAT=%016" PRIx64 "\n", env->CSR_ESTAT);
+qemu_fprintf(f, "ERA=%016" PRIx64 "\n", env->CSR_ERA);
+qemu_fprintf(f, "BADV=%016" PRIx64 "\n", env->CSR_BADV);
+qemu_fprintf(f, "BADI=%016" PRIx64 "\n", env->CSR_BADI);
+qemu_fprintf(f, "EENTRY=%016" PRIx64 "\n", env->CSR_EENTRY);
+qemu_fprintf(f, "PRCFG1=%016" PRIx64 ", PRCFG2=%016" PRIx64 ","
+ " PRCFG3=%016" PRIx64 "\n",
+ env->CSR_PRCFG1, env->CSR_PRCFG3, env->CSR_PRCFG3);
+qemu_fprintf(f, "TLBRENTRY=%016" PRIx64 "\n", env->CSR_TLBRENTRY);
+qemu_fprintf(f, "TLBRBADV=%016" PRIx64 "\n", env->CSR_TLBRBADV);
+qemu_fprintf(f, "TLBRERA=%016" PRIx64 "\n", env->CSR_TLBRERA);
+
 /* fpr */
 if (flags & CPU_DUMP_FPU) {
 for (i = 0; i < 32; i++) {
@@ -315,9 +330,17 @@ void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int 
flags)
 static struct TCGCPUOps loongarch_tcg_ops = {
 .initialize = loongarch_translate_init,
 .synchronize_from_tb = loongarch_cpu_synchronize_from_tb,
+
+.tlb_fill = loongarch_cpu_tlb_fill,
 };
 #endif /* CONFIG_TCG */
 
+#include "hw/core/sysemu-cpu-ops.h"
+
+static const struct SysemuCPUOps loongarch_sysemu_ops = {
+.get_phys_page_debug = loongarch_cpu_get_phys_page_debug,
+};
+
 static void loongarch_cpu_class_init(ObjectClass *c, void *data)
 {
 LoongArchCPUClass *lacc = LOONGARCH_CPU_CLASS(c);
@@ -332,6 +355,7 @@ static void loongarch_cpu_class_init(ObjectClass *c, void 
*data)
 cc->dump_state = loongarch_cpu_dump_state;
 cc->set_pc = loongarch_cpu_set_pc;
 dc->vmsd = _loongarch_cpu;
+cc->sysemu_ops = _sysemu_ops;
 cc->disas_set_info = loongarch_cpu_disas_set_info;
 #ifdef CONFIG_TCG
 cc->tcg_ops = _tcg_ops;
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 74303b2c97..a1b88f81eb 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -184,6 +184,26 @@ FIELD(CSR_CRMD, WE, 9, 1)
 extern const char * const regnames[32];
 extern const char * const fregnames[32];
 
+#define LOONGARCH_STLB 2048 /* 2048 STLB */
+#define LOONGARCH_MTLB 64   /* 64 MTLB */
+#define LOONGARCH_TLB_MAX  (LOONGARCH_STLB + LOONGARCH_MTLB)
+
+/*
+ * define the ASID PS E VPPN field of TLB
+ */
+FIELD(TLB_MISC, E, 0, 1)
+FIELD(TLB_MISC, ASID, 1, 10)
+FIELD(TLB_MISC, VPPN, 13, 35)
+FIELD(TLB_MISC, PS, 48, 6)
+
+struct LoongArchTLB {
+uint64_t tlb_misc;
+/* Fields corresponding to CSR_TLBELO0/1 */
+uint64_t tlb_entry0;
+uint64_t tlb_entry1;
+};
+typedef struct LoongArchTLB LoongArchTLB;
+
 typedef struct CPUArchState {
 uint64_t gpr[32];
 uint64_t pc;
@@ -257,6 +277,8 @@ typedef struct CPUArchState {
 uint64_t CSR_DBG;
 uint64_t CSR_DERA;
 uint64_t CSR_DSAVE;
+
+LoongArchTLB  tlb[LOONGARCH_TLB_MAX];
 } CPULoongArchState;
 
 /**
@@ -295,6 +317,35 @@ struct LoongArchCPUClass {
 DeviceReset parent_reset;
 };
 
+/*
+ * LoongArch CPUs has 4 privilege levels.
+ * 0 for kernel mode, 3 for user mode.
+ * Define an extra index for DA(direct addressing) mode.
+ */
+#define MMU_KERNEL_IDX   0
+#define MMU_USER_IDX 3
+#define MMU_DA_IDX   4
+
+static inline int cpu_mmu_index(CPULoongArchState *env, bool ifetch)
+{
+uint8_t pg = FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PG);
+
+if (!pg) {
+return MMU_DA_IDX;
+}
+ret

[PATCH v2 08/43] target/loongarch: Add fixed point atomic instruction translation

2022-04-25 Thread Xiaojuan Yang
From: Song Gao 

This includes:
- LL.{W/D}, SC.{W/D}
- AM{SWAP/ADD/AND/OR/XOR/MAX/MIN}[_DB].{W/D}
- AM{MAX/MIN}[_DB].{WU/DU}

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 .../loongarch/insn_trans/trans_atomic.c.inc   | 113 ++
 .../loongarch/insn_trans/trans_memory.c.inc   |   2 +-
 target/loongarch/insns.decode |  44 +++
 target/loongarch/translate.c  |   1 +
 4 files changed, 159 insertions(+), 1 deletion(-)
 create mode 100644 target/loongarch/insn_trans/trans_atomic.c.inc

diff --git a/target/loongarch/insn_trans/trans_atomic.c.inc 
b/target/loongarch/insn_trans/trans_atomic.c.inc
new file mode 100644
index 00..6763c1c301
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_atomic.c.inc
@@ -0,0 +1,113 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static bool gen_ll(DisasContext *ctx, arg_rr_i *a, MemOp mop)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv t0 = tcg_temp_new();
+
+tcg_gen_addi_tl(t0, src1, a->imm);
+tcg_gen_qemu_ld_i64(dest, t0, ctx->mem_idx, mop);
+tcg_gen_st_tl(t0, cpu_env, offsetof(CPULoongArchState, lladdr));
+tcg_gen_st_tl(dest, cpu_env, offsetof(CPULoongArchState, llval));
+gen_set_gpr(a->rd, dest, EXT_NONE);
+tcg_temp_free(t0);
+
+return true;
+}
+
+static bool gen_sc(DisasContext *ctx, arg_rr_i *a, MemOp mop)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rd, EXT_NONE);
+TCGv t0 = tcg_temp_new();
+TCGv val = tcg_temp_new();
+
+TCGLabel *l1 = gen_new_label();
+TCGLabel *done = gen_new_label();
+
+tcg_gen_addi_tl(t0, src1, a->imm);
+tcg_gen_brcond_tl(TCG_COND_EQ, t0, cpu_lladdr, l1);
+tcg_gen_movi_tl(dest, 0);
+tcg_gen_br(done);
+
+gen_set_label(l1);
+tcg_gen_mov_tl(val, src2);
+/* generate cmpxchg */
+tcg_gen_atomic_cmpxchg_tl(t0, cpu_lladdr, cpu_llval,
+  val, ctx->mem_idx, mop);
+tcg_gen_setcond_tl(TCG_COND_EQ, dest, t0, cpu_llval);
+gen_set_label(done);
+gen_set_gpr(a->rd, dest, EXT_NONE);
+tcg_temp_free(t0);
+tcg_temp_free(val);
+
+return true;
+}
+
+static bool gen_am(DisasContext *ctx, arg_rrr *a,
+   void (*func)(TCGv, TCGv, TCGv, TCGArg, MemOp),
+   MemOp mop)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv val = gpr_src(ctx, a->rk, EXT_NONE);
+
+if (a->rd != 0 && (a->rj == a->rd || a->rk == a->rd)) {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "Warning: source register overlaps destination register"
+  "in atomic insn at pc=0x" TARGET_FMT_lx "\n",
+  ctx->base.pc_next - 4);
+return false;
+}
+
+func(dest, addr, val, ctx->mem_idx, mop);
+gen_set_gpr(a->rd, dest, EXT_NONE);
+
+return true;
+}
+
+TRANS(ll_w, gen_ll, MO_TESL)
+TRANS(sc_w, gen_sc, MO_TESL)
+TRANS(ll_d, gen_ll, MO_TEUQ)
+TRANS(sc_d, gen_sc, MO_TEUQ)
+TRANS(amswap_w, gen_am, tcg_gen_atomic_xchg_tl, MO_TESL)
+TRANS(amswap_d, gen_am, tcg_gen_atomic_xchg_tl, MO_TEUQ)
+TRANS(amadd_w, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TESL)
+TRANS(amadd_d, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TEUQ)
+TRANS(amand_w, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TESL)
+TRANS(amand_d, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TEUQ)
+TRANS(amor_w, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TESL)
+TRANS(amor_d, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TEUQ)
+TRANS(amxor_w, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TESL)
+TRANS(amxor_d, gen_am, tcg_gen_atomic_fetch_xor_tl, MO_TEUQ)
+TRANS(ammax_w, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TESL)
+TRANS(ammax_d, gen_am, tcg_gen_atomic_fetch_smax_tl, MO_TEUQ)
+TRANS(ammin_w, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TESL)
+TRANS(ammin_d, gen_am, tcg_gen_atomic_fetch_smin_tl, MO_TEUQ)
+TRANS(ammax_wu, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TESL)
+TRANS(ammax_du, gen_am, tcg_gen_atomic_fetch_umax_tl, MO_TEUQ)
+TRANS(ammin_wu, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TESL)
+TRANS(ammin_du, gen_am, tcg_gen_atomic_fetch_umin_tl, MO_TEUQ)
+TRANS(amswap_db_w, gen_am, tcg_gen_atomic_xchg_tl, MO_TESL)
+TRANS(amswap_db_d, gen_am, tcg_gen_atomic_xchg_tl, MO_TEUQ)
+TRANS(amadd_db_w, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TESL)
+TRANS(amadd_db_d, gen_am, tcg_gen_atomic_fetch_add_tl, MO_TEUQ)
+TRANS(amand_db_w, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TESL)
+TRANS(amand_db_d, gen_am, tcg_gen_atomic_fetch_and_tl, MO_TEUQ)
+TRANS(amor_db_w, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TESL)
+TRANS(amor_db_d, gen_am, tcg_gen_atomic_fetch_or_tl, MO_TEUQ)
+TRANS(amxor_db_w, gen_am, tcg_g

[PATCH v2 06/43] target/loongarch: Add fixed point bit instruction translation

2022-04-25 Thread Xiaojuan Yang
From: Song Gao 

This includes:
- EXT.W.{B/H}
- CL{O/Z}.{W/D}, CT{O/Z}.{W/D}
- BYTEPICK.{W/D}
- REVB.{2H/4H/2W/D}
- REVH.{2W/D}
- BITREV.{4B/8B}, BITREV.{W/D}
- BSTRINS.{W/D}, BSTRPICK.{W/D}
- MASKEQZ, MASKNEZ

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 target/loongarch/helper.h   |   4 +
 target/loongarch/insn_trans/trans_bit.c.inc | 212 
 target/loongarch/insns.decode   |  39 
 target/loongarch/op_helper.c|  21 ++
 target/loongarch/translate.c|   1 +
 5 files changed, 277 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_bit.c.inc

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index eb771c0628..04e0245d5e 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -4,3 +4,7 @@
  */
 
 DEF_HELPER_2(raise_exception, noreturn, env, i32)
+
+DEF_HELPER_FLAGS_1(bitrev_w, TCG_CALL_NO_RWG_SE, tl, tl)
+DEF_HELPER_FLAGS_1(bitrev_d, TCG_CALL_NO_RWG_SE, tl, tl)
+DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl)
diff --git a/target/loongarch/insn_trans/trans_bit.c.inc 
b/target/loongarch/insn_trans/trans_bit.c.inc
new file mode 100644
index 00..9337714ec4
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_bit.c.inc
@@ -0,0 +1,212 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static bool gen_rr(DisasContext *ctx, arg_rr *a,
+   DisasExtend src_ext, DisasExtend dst_ext,
+   void (*func)(TCGv, TCGv))
+{
+TCGv dest = gpr_dst(ctx, a->rd, dst_ext);
+TCGv src1 = gpr_src(ctx, a->rj, src_ext);
+
+func(dest, src1);
+gen_set_gpr(a->rd, dest, dst_ext);
+
+return true;
+}
+
+static void gen_bytepick_w(TCGv dest, TCGv src1, TCGv src2, target_long sa)
+{
+tcg_gen_concat_tl_i64(dest, src1, src2);
+tcg_gen_sextract_i64(dest, dest, (32 - sa * 8), 32);
+}
+
+static void gen_bytepick_d(TCGv dest, TCGv src1, TCGv src2, target_long sa)
+{
+tcg_gen_extract2_i64(dest, src1, src2, (64 - sa * 8));
+}
+
+static void gen_bstrins(TCGv dest, TCGv src1,
+unsigned int ls, unsigned int len)
+{
+tcg_gen_deposit_tl(dest, dest, src1, ls, len);
+}
+
+static bool gen_rr_ms_ls(DisasContext *ctx, arg_rr_ms_ls *a,
+ DisasExtend src_ext, DisasExtend dst_ext,
+ void (*func)(TCGv, TCGv, unsigned int, unsigned int))
+{
+TCGv dest = gpr_dst(ctx, a->rd, dst_ext);
+TCGv src1 = gpr_src(ctx, a->rj, src_ext);
+
+if (a->ls > a->ms) {
+return false;
+}
+
+func(dest, src1, a->ls, a->ms - a->ls + 1);
+gen_set_gpr(a->rd, dest, dst_ext);
+
+return true;
+}
+
+static void gen_clz_w(TCGv dest, TCGv src1)
+{
+tcg_gen_clzi_tl(dest, src1, TARGET_LONG_BITS);
+tcg_gen_subi_tl(dest, dest, TARGET_LONG_BITS - 32);
+}
+
+static void gen_clo_w(TCGv dest, TCGv src1)
+{
+tcg_gen_not_tl(dest, src1);
+tcg_gen_ext32u_tl(dest, dest);
+gen_clz_w(dest, dest);
+}
+
+static void gen_ctz_w(TCGv dest, TCGv src1)
+{
+tcg_gen_ori_tl(dest, src1, (target_ulong)MAKE_64BIT_MASK(32, 32));
+tcg_gen_ctzi_tl(dest, dest, TARGET_LONG_BITS);
+}
+
+static void gen_cto_w(TCGv dest, TCGv src1)
+{
+tcg_gen_not_tl(dest, src1);
+gen_ctz_w(dest, dest);
+}
+
+static void gen_clz_d(TCGv dest, TCGv src1)
+{
+tcg_gen_clzi_i64(dest, src1, TARGET_LONG_BITS);
+}
+
+static void gen_clo_d(TCGv dest, TCGv src1)
+{
+tcg_gen_not_tl(dest, src1);
+gen_clz_d(dest, dest);
+}
+
+static void gen_ctz_d(TCGv dest, TCGv src1)
+{
+tcg_gen_ctzi_tl(dest, src1, TARGET_LONG_BITS);
+}
+
+static void gen_cto_d(TCGv dest, TCGv src1)
+{
+tcg_gen_not_tl(dest, src1);
+gen_ctz_d(dest, dest);
+}
+
+static void gen_revb_2w(TCGv dest, TCGv src1)
+{
+tcg_gen_bswap64_i64(dest, src1);
+tcg_gen_rotri_i64(dest, dest, 32);
+}
+
+static void gen_revb_2h(TCGv dest, TCGv src1)
+{
+TCGv mask = tcg_constant_tl(0x00FF00FF);
+TCGv t0 = tcg_temp_new();
+TCGv t1 = tcg_temp_new();
+
+tcg_gen_shri_tl(t0, src1, 8);
+tcg_gen_and_tl(t0, t0, mask);
+tcg_gen_and_tl(t1, src1, mask);
+tcg_gen_shli_tl(t1, t1, 8);
+tcg_gen_or_tl(dest, t0, t1);
+
+tcg_temp_free(t0);
+tcg_temp_free(t1);
+}
+
+static void gen_revb_4h(TCGv dest, TCGv src1)
+{
+TCGv mask = tcg_constant_tl(0x00FF00FF00FF00FFULL);
+TCGv t0 = tcg_temp_new();
+TCGv t1 = tcg_temp_new();
+
+tcg_gen_shri_tl(t0, src1, 8);
+tcg_gen_and_tl(t0, t0, mask);
+tcg_gen_and_tl(t1, src1, mask);
+tcg_gen_shli_tl(t1, t1, 8);
+tcg_gen_or_tl(dest, t0, t1);
+
+tcg_temp_free(t0);
+tcg_temp_free(t1);
+}
+
+static void gen_revh_2w(TCGv dest, TCGv src1)
+{
+TCGv_i64 t0 = tcg_temp_new_i64();
+TCGv_i64 t1 = tcg_temp_new_i64();
+TCGv_i64 mask = tcg_constant_i64(0xull);

[PATCH v2 07/43] target/loongarch: Add fixed point load/store instruction translation

2022-04-25 Thread Xiaojuan Yang
From: Song Gao 

This includes:
- LD.{B[U]/H[U]/W[U]/D}, ST.{B/H/W/D}
- LDX.{B[U]/H[U]/W[U]/D}, STX.{B/H/W/D}
- LDPTR.{W/D}, STPTR.{W/D}
- PRELD
- LD{GT/LE}.{B/H/W/D}, ST{GT/LE}.{B/H/W/D}
- DBAR, IBAR

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 target/loongarch/helper.h |   3 +
 .../loongarch/insn_trans/trans_memory.c.inc   | 229 ++
 target/loongarch/insns.decode |  55 +
 target/loongarch/op_helper.c  |  15 ++
 target/loongarch/translate.c  |   6 +
 5 files changed, 308 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_memory.c.inc

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 04e0245d5e..100622bfc2 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -8,3 +8,6 @@ DEF_HELPER_2(raise_exception, noreturn, env, i32)
 DEF_HELPER_FLAGS_1(bitrev_w, TCG_CALL_NO_RWG_SE, tl, tl)
 DEF_HELPER_FLAGS_1(bitrev_d, TCG_CALL_NO_RWG_SE, tl, tl)
 DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl)
+
+DEF_HELPER_FLAGS_3(asrtle_d, TCG_CALL_NO_WG, void, env, tl, tl)
+DEF_HELPER_FLAGS_3(asrtgt_d, TCG_CALL_NO_WG, void, env, tl, tl)
diff --git a/target/loongarch/insn_trans/trans_memory.c.inc 
b/target/loongarch/insn_trans/trans_memory.c.inc
new file mode 100644
index 00..10914acf52
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_memory.c.inc
@@ -0,0 +1,229 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static bool gen_load(DisasContext *ctx, arg_rr_i *a, MemOp mop)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv temp = NULL;
+
+if (a->imm) {
+temp = tcg_temp_new();
+tcg_gen_addi_tl(temp, addr, a->imm);
+addr = temp;
+}
+
+tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
+gen_set_gpr(a->rd, dest, EXT_NONE);
+
+if (temp) {
+tcg_temp_free(temp);
+}
+
+return true;
+}
+
+static bool gen_store(DisasContext *ctx, arg_rr_i *a, MemOp mop)
+{
+TCGv data = gpr_src(ctx, a->rd, EXT_NONE);
+TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv temp = NULL;
+
+if (a->imm) {
+temp = tcg_temp_new();
+tcg_gen_addi_tl(temp, addr, a->imm);
+addr = temp;
+}
+
+tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, mop);
+
+if (temp) {
+tcg_temp_free(temp);
+}
+
+return true;
+}
+
+static bool gen_loadx(DisasContext *ctx, arg_rrr *a, MemOp mop)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+TCGv addr = tcg_temp_new();
+
+tcg_gen_add_tl(addr, src1, src2);
+tcg_gen_qemu_ld_tl(dest, addr, ctx->mem_idx, mop);
+gen_set_gpr(a->rd, dest, EXT_NONE);
+tcg_temp_free(addr);
+
+return true;
+}
+
+static bool gen_storex(DisasContext *ctx, arg_rrr *a, MemOp mop)
+{
+TCGv data = gpr_src(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+TCGv addr = tcg_temp_new();
+
+tcg_gen_add_tl(addr, src1, src2);
+tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, mop);
+tcg_temp_free(addr);
+
+return true;
+}
+
+static bool gen_load_gt(DisasContext *ctx, arg_rrr *a, MemOp mop)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+
+gen_helper_asrtgt_d(cpu_env, src1, src2);
+tcg_gen_qemu_ld_tl(dest, src1, ctx->mem_idx, mop);
+gen_set_gpr(a->rd, dest, EXT_NONE);
+
+return true;
+}
+
+static bool gen_load_le(DisasContext *ctx, arg_rrr *a, MemOp mop)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+
+gen_helper_asrtle_d(cpu_env, src1, src2);
+tcg_gen_qemu_ld_tl(dest, src1, ctx->mem_idx, mop);
+gen_set_gpr(a->rd, dest, EXT_NONE);
+
+return true;
+}
+
+static bool gen_store_gt(DisasContext *ctx, arg_rrr *a, MemOp mop)
+{
+TCGv data = gpr_src(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+
+gen_helper_asrtgt_d(cpu_env, src1, src2);
+tcg_gen_qemu_st_tl(data, src1, ctx->mem_idx, mop);
+
+return true;
+}
+
+static bool gen_store_le(DisasContext *ctx, arg_rrr *a, MemOp mop)
+{
+TCGv data = gpr_src(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+
+gen_helper_asrtle_d(cpu_env, src1, src2);
+tcg_gen_qemu_st_tl(data, src1, ctx->mem_idx, mop);
+
+return true;
+}
+
+static bool trans_preld(DisasContext *ctx, a

[PATCH v2 23/43] target/loongarch: Add LoongArch interrupt and exception handle

2022-04-25 Thread Xiaojuan Yang
Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 target/loongarch/cpu.c   | 229 +++
 target/loongarch/cpu.h   |   2 +
 target/loongarch/internals.h |   2 +
 3 files changed, 233 insertions(+)

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 8a6bc24630..f7c102dfc5 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -80,6 +80,214 @@ static void loongarch_cpu_set_pc(CPUState *cs, vaddr value)
 env->pc = value;
 }
 
+void loongarch_cpu_set_irq(void *opaque, int irq, int level)
+{
+LoongArchCPU *cpu = opaque;
+CPULoongArchState *env = >env;
+CPUState *cs = CPU(cpu);
+
+if (irq < 0 || irq >= N_IRQS) {
+return;
+}
+
+env->CSR_ESTAT = deposit64(env->CSR_ESTAT, irq, 1, level != 0);
+
+if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) {
+cpu_interrupt(cs, CPU_INTERRUPT_HARD);
+} else {
+cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
+}
+}
+
+static inline bool cpu_loongarch_hw_interrupts_enabled(CPULoongArchState *env)
+{
+bool ret = 0;
+
+ret = (FIELD_EX64(env->CSR_CRMD, CSR_CRMD, IE) &&
+  !(FIELD_EX64(env->CSR_DBG, CSR_DBG, DST)));
+
+return ret;
+}
+
+/* Check if there is pending and not masked out interrupt */
+static inline bool cpu_loongarch_hw_interrupts_pending(CPULoongArchState *env)
+{
+uint32_t pending;
+uint32_t status;
+bool r;
+
+pending = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS);
+status  = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, LIE);
+
+r = (pending & status) != 0;
+return r;
+}
+
+static void loongarch_cpu_do_interrupt(CPUState *cs)
+{
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+CPULoongArchState *env = >env;
+bool update_badinstr = 1;
+int cause = -1;
+const char *name;
+bool tlbfill = FIELD_EX64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR);
+uint32_t vec_size = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, VS);
+
+if (cs->exception_index != EXCCODE_INT) {
+if (cs->exception_index < 0 ||
+cs->exception_index > ARRAY_SIZE(excp_names)) {
+name = "unknown";
+} else {
+name = excp_names[cs->exception_index];
+}
+
+qemu_log_mask(CPU_LOG_INT,
+ "%s enter: pc " TARGET_FMT_lx " ERA " TARGET_FMT_lx
+ " TLBRERA " TARGET_FMT_lx " %s exception\n", __func__,
+ env->pc, env->CSR_ERA, env->CSR_TLBRERA, name);
+}
+
+switch (cs->exception_index) {
+case EXCCODE_DBP:
+env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, DCL, 1);
+env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, ECODE, 0xC);
+goto set_DERA;
+set_DERA:
+env->CSR_DERA = env->pc;
+env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, DST, 1);
+env->pc = env->CSR_EENTRY + 0x480;
+break;
+case EXCCODE_INT:
+if (FIELD_EX64(env->CSR_DBG, CSR_DBG, DST)) {
+env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, DEI, 1);
+goto set_DERA;
+}
+QEMU_FALLTHROUGH;
+case EXCCODE_PIF:
+cause = cs->exception_index;
+update_badinstr = 0;
+break;
+case EXCCODE_ADEM:
+case EXCCODE_SYS:
+case EXCCODE_BRK:
+case EXCCODE_PIL:
+case EXCCODE_PIS:
+case EXCCODE_PME:
+case EXCCODE_PNR:
+case EXCCODE_PNX:
+case EXCCODE_PPI:
+case EXCCODE_INE:
+case EXCCODE_IPE:
+case EXCCODE_FPE:
+cause = cs->exception_index;
+break;
+default:
+qemu_log("Error: exception(%d) '%s' has not been supported\n",
+ cs->exception_index, excp_names[cs->exception_index]);
+abort();
+}
+
+if (update_badinstr) {
+env->CSR_BADI = cpu_ldl_code(env, env->pc);
+}
+
+/* Save PLV and IE */
+if (tlbfill) {
+env->CSR_TLBRPRMD = FIELD_DP64(env->CSR_TLBRPRMD, CSR_TLBRPRMD, PPLV,
+   FIELD_EX64(env->CSR_CRMD,
+   CSR_CRMD, PLV));
+env->CSR_TLBRPRMD = FIELD_DP64(env->CSR_TLBRPRMD, CSR_TLBRPRMD, PIE,
+   FIELD_EX64(env->CSR_CRMD, CSR_CRMD, 
IE));
+/* set the DA mode */
+env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, DA, 1);
+env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PG, 0);
+env->CSR_TLBRERA = FIELD_DP64(env->CSR_TLBRERA, CSR_TLBRERA,
+  PC, (env->pc >> 2));
+} else {
+env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, ECODE, cause);
+env->CSR_PRMD = FIELD_DP64(env->CSR_PRMD, CSR_PRMD, PPLV,
+   FIELD_EX64(env->CSR_CRM

[PATCH v2 26/43] target/loongarch: Add LoongArch IOCSR instruction

2022-04-25 Thread Xiaojuan Yang
This includes:
- IOCSR{RD/WR}.{B/H/W/D}

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 target/loongarch/cpu.c|  52 ++
 target/loongarch/cpu.h|  25 +++
 target/loongarch/disas.c  |   8 +
 target/loongarch/helper.h |   8 +
 .../insn_trans/trans_privileged.c.inc |  35 
 target/loongarch/insns.decode |   9 +
 target/loongarch/iocsr_helper.c   | 174 ++
 target/loongarch/meson.build  |   1 +
 8 files changed, 312 insertions(+)
 create mode 100644 target/loongarch/iocsr_helper.c

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 6d6216a846..3167323821 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -17,6 +17,8 @@
 #include "internals.h"
 #include "fpu/softfloat-helpers.h"
 #include "cpu-csr.h"
+#include "sysemu/reset.h"
+#include "hw/loader.h"
 
 const char * const regnames[32] = {
 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
@@ -483,14 +485,64 @@ static void loongarch_cpu_realizefn(DeviceState *dev, 
Error **errp)
 lacc->parent_realize(dev, errp);
 }
 
+static void loongarch_qemu_write(void *opaque, hwaddr addr,
+ uint64_t val, unsigned size)
+{
+}
+
+static uint64_t loongarch_qemu_read(void *opaque, hwaddr addr, unsigned size)
+{
+switch (addr) {
+case FEATURE_REG:
+return 1UL << IOCSRF_MSI | 1UL << IOCSRF_EXTIOI |
+   1UL << IOCSRF_CSRIPI;
+case VENDOR_REG:
+return 0x6e6f73676e6f6f4c; /* "Loongson" */
+case CPUNAME_REG:
+return 0x303030354133; /* "3A5000" */
+case MISC_FUNC_REG:
+return 1UL << IOCSRM_EXTIOI_EN;
+}
+return 0;
+}
+
+static const MemoryRegionOps loongarch_qemu_ops = {
+.read = loongarch_qemu_read,
+.write = loongarch_qemu_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+.valid = {
+.min_access_size = 4,
+.max_access_size = 8,
+},
+.impl = {
+.min_access_size = 8,
+.max_access_size = 8,
+},
+};
+
+static void do_cpu_reset(void *opaque)
+{
+LoongArchCPU *cpu = opaque;
+
+cpu_reset(CPU(cpu));
+}
+
 static void loongarch_cpu_init(Object *obj)
 {
 LoongArchCPU *cpu = LOONGARCH_CPU(obj);
+CPULoongArchState *env = >env;
 
 cpu_set_cpustate_pointers(cpu);
 qdev_init_gpio_in(DEVICE(cpu), loongarch_cpu_set_irq, N_IRQS);
 timer_init_ns(>timer, QEMU_CLOCK_VIRTUAL,
   _constant_timer_cb, cpu);
+memory_region_init_io(>system_iocsr, OBJECT(cpu), NULL,
+  env, "iocsr", UINT64_MAX);
+address_space_init(>address_space_iocsr, >system_iocsr, "IOCSR");
+qemu_register_reset(do_cpu_reset, cpu);
+memory_region_init_io(>iocsr_mem, OBJECT(cpu), _qemu_ops,
+  NULL, "iocsr_misc", 0x428);
+memory_region_add_subregion(>system_iocsr, 0, >iocsr_mem);
 }
 
 static ObjectClass *loongarch_cpu_class_by_name(const char *cpu_model)
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index e907fe3c51..734f90168e 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -12,6 +12,27 @@
 #include "fpu/softfloat-types.h"
 #include "hw/registerfields.h"
 #include "qemu/timer.h"
+#include "exec/memory.h"
+#include "hw/sysbus.h"
+
+#define IOCSRF_TEMP 0
+#define IOCSRF_NODECNT  1
+#define IOCSRF_MSI  2
+#define IOCSRF_EXTIOI   3
+#define IOCSRF_CSRIPI   4
+#define IOCSRF_FREQCSR  5
+#define IOCSRF_FREQSCALE6
+#define IOCSRF_DVFSV1   7
+#define IOCSRF_GMOD 9
+#define IOCSRF_VM   11
+
+#define FEATURE_REG 0x8
+#define VENDOR_REG  0x10
+#define CPUNAME_REG 0x20
+#define MISC_FUNC_REG   0x420
+#define IOCSRM_EXTIOI_EN48
+
+#define IOCSR_MEM_SIZE  0x428
 
 #define TCG_GUEST_DEFAULT_MO (0)
 
@@ -284,6 +305,10 @@ typedef struct CPUArchState {
 uint64_t CSR_DSAVE;
 
 LoongArchTLB  tlb[LOONGARCH_TLB_MAX];
+
+AddressSpace address_space_iocsr;
+MemoryRegion system_iocsr;
+MemoryRegion iocsr_mem;
 } CPULoongArchState;
 
 /**
diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index c76b82dfdf..fcc06abc6b 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -609,6 +609,14 @@ INSN(bgeu, rr_offs)
 INSN(csrrd,r_csr)
 INSN(csrwr,r_csr)
 INSN(csrxchg,  rr_csr)
+INSN(iocsrrd_b,rr)
+INSN(iocsrrd_h,rr)
+INSN(iocsrrd_w,rr)
+INSN(iocsrrd_d,rr)
+INSN(iocsrwr_b,rr)
+INSN(iocsrwr_h,rr)
+INSN(iocsrwr_w,rr)
+INSN(iocsrwr

[PATCH v2 34/43] hw/intc: Add LoongArch extioi interrupt controller(EIOINTC)

2022-04-25 Thread Xiaojuan Yang
This patch realize the EIOINTC interrupt controller.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 hw/intc/Kconfig|   3 +
 hw/intc/loongarch_extioi.c | 483 +
 hw/intc/meson.build|   1 +
 hw/intc/trace-events   |   9 +
 hw/loongarch/Kconfig   |   1 +
 include/hw/intc/loongarch_extioi.h |  60 
 6 files changed, 557 insertions(+)
 create mode 100644 hw/intc/loongarch_extioi.c
 create mode 100644 include/hw/intc/loongarch_extioi.h

diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
index 71c04c328e..28bd1f185d 100644
--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -96,3 +96,6 @@ config LOONGARCH_PCH_MSI
 select MSI_NONBROKEN
 bool
 select UNIMP
+
+config LOONGARCH_EXTIOI
+bool
diff --git a/hw/intc/loongarch_extioi.c b/hw/intc/loongarch_extioi.c
new file mode 100644
index 00..1d9317c5bd
--- /dev/null
+++ b/hw/intc/loongarch_extioi.c
@@ -0,0 +1,483 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Loongson 3A5000 ext interrupt controller emulation
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/module.h"
+#include "qemu/log.h"
+#include "hw/irq.h"
+#include "hw/sysbus.h"
+#include "hw/loongarch/virt.h"
+#include "hw/qdev-properties.h"
+#include "exec/address-spaces.h"
+#include "hw/intc/loongarch_extioi.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+
+static void extioi_update_irq(LoongArchExtIOI *s, int irq_num, int level)
+{
+uint64_t ipnum, cpu;
+
+/*
+ * Routing in group of 32 interrupts.
+ * The default value of csr[0x420][49]
+ * is 0 and nobody will change it,
+ * so 'ipmap' use bitmap function.
+ */
+ipnum = ldub_p((void *)>ipmap + (irq_num / 32)) & 0xf;
+ipnum = find_first_bit(, 4);
+ipnum = (ipnum == 4) ? 0 : ipnum;
+
+cpu = ldub_p((void *)s->coremap + irq_num) & 0xf;
+cpu = find_first_bit(, 4);
+cpu = (cpu == 4) ? 0 : cpu;
+
+if (level) {
+if (test_bit(irq_num, (unsigned long *)s->enable) == false) {
+return;
+}
+bitmap_set((unsigned long *)s->coreisr[cpu], irq_num, 1);
+qemu_set_irq(s->parent_irq[cpu][ipnum], level);
+} else {
+bitmap_clear((unsigned long *)s->coreisr[cpu], irq_num, 1);
+qemu_set_irq(s->parent_irq[cpu][ipnum], level);
+}
+}
+
+static void extioi_setirq(void *opaque, int irq, int level)
+{
+LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
+trace_loongarch_extioi_setirq(irq, level);
+extioi_update_irq(s, irq, level);
+}
+
+static uint32_t extioi_readb(void *opaque, hwaddr addr)
+{
+LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
+unsigned long offset, reg_count;
+uint8_t ret = 0;
+int cpu;
+
+offset = addr & 0x;
+switch (offset) {
+case EXTIOI_ENABLE_START ... EXTIOI_ENABLE_END - 1:
+ret = ldub_p((void *)s->enable + (offset - EXTIOI_ENABLE_START));
+break;
+case EXTIOI_BOUNCE_START ... EXTIOI_BOUNCE_END - 1:
+ret = ldub_p((void *)s->bounce + (offset - EXTIOI_BOUNCE_START));
+break;
+case EXTIOI_COREISR_START ... EXTIOI_COREISR_END - 1:
+reg_count = ((offset - EXTIOI_COREISR_START) & 0x1f);
+cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3;
+ret = ldub_p((void *)s->coreisr[cpu] + reg_count);
+break;
+case EXTIOI_IPMAP_START ... EXTIOI_IPMAP_END - 1:
+ret = ldub_p((void *)>ipmap + (offset - EXTIOI_IPMAP_START));
+break;
+case EXTIOI_COREMAP_START ... EXTIOI_COREMAP_END - 1:
+ret = ldub_p((void *)s->coremap + (offset - EXTIOI_COREMAP_START));
+break;
+case EXTIOI_NODETYPE_START ... EXTIOI_NODETYPE_END - 1:
+ret = ldub_p((void *)s->nodetype + (offset - EXTIOI_NODETYPE_START));
+break;
+default:
+break;
+}
+trace_loongarch_extioi_readb((uint32_t)addr, ret);
+return ret;
+}
+
+static uint32_t extioi_readw(void *opaque, hwaddr addr)
+{
+LoongArchExtIOI *s = LOONGARCH_EXTIOI(opaque);
+unsigned long offset, reg_count;
+uint32_t ret = 0;
+int cpu;
+
+offset = addr & 0x;
+switch (offset) {
+case EXTIOI_ENABLE_START ... EXTIOI_ENABLE_END - 1:
+ret = ldl_p((void *)s->enable + (offset - EXTIOI_ENABLE_START));
+break;
+case EXTIOI_BOUNCE_START ... EXTIOI_BOUNCE_END - 1:
+ret = ldl_p((void *)s->bounce + (offset - EXTIOI_BOUNCE_START));
+break;
+case EXTIOI_COREISR_START ... EXTIOI_COREISR_END - 1:
+reg_count = ((offset - EXTIOI_COREISR_START) & 0x1f);
+cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3;
+ret = ldl_p((void *)s->coreisr[cpu] + reg_count);
+bre

[PATCH v2 13/43] target/loongarch: Add floating point move instruction translation

2022-04-25 Thread Xiaojuan Yang
From: Song Gao 

This includes:
- FMOV.{S/D}
- FSEL
- MOVGR2FR.{W/D}, MOVGR2FRH.W
- MOVFR2GR.{S/D}, MOVFRH2GR.S
- MOVGR2FCSR, MOVFCSR2GR
- MOVFR2CF, MOVCF2FR
- MOVGR2CF, MOVCF2GR

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 target/loongarch/fpu_helper.c|   6 +
 target/loongarch/helper.h|   2 +
 target/loongarch/insn_trans/trans_fmov.c.inc | 157 +++
 target/loongarch/insns.decode|  37 +
 target/loongarch/translate.c |   1 +
 5 files changed, 203 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_fmov.c.inc

diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c
index d69a1dd80e..1baf012ef7 100644
--- a/target/loongarch/fpu_helper.c
+++ b/target/loongarch/fpu_helper.c
@@ -854,3 +854,9 @@ uint64_t helper_ftint_w_d(CPULoongArchState *env, uint64_t 
fj)
 update_fcsr0(env, GETPC());
 return fd;
 }
+
+void helper_set_rounding_mode(CPULoongArchState *env, uint32_t fcsr0)
+{
+set_float_rounding_mode(ieee_rm[(fcsr0 >> FCSR0_RM) & 0x3],
+>fp_status);
+}
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 1e8749433a..da1a2bced7 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -90,3 +90,5 @@ DEF_HELPER_2(ftint_w_s, i64, env, i64)
 DEF_HELPER_2(ftint_w_d, i64, env, i64)
 DEF_HELPER_2(frint_s, i64, env, i64)
 DEF_HELPER_2(frint_d, i64, env, i64)
+
+DEF_HELPER_FLAGS_2(set_rounding_mode, TCG_CALL_NO_RWG, void, env, i32)
diff --git a/target/loongarch/insn_trans/trans_fmov.c.inc 
b/target/loongarch/insn_trans/trans_fmov.c.inc
new file mode 100644
index 00..24753d4568
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_fmov.c.inc
@@ -0,0 +1,157 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static const uint32_t fcsr_mask[4] = {
+UINT32_MAX, FCSR0_M1, FCSR0_M2, FCSR0_M3
+};
+
+static bool trans_fsel(DisasContext *ctx, arg_fsel *a)
+{
+TCGv zero = tcg_constant_tl(0);
+TCGv cond = tcg_temp_new();
+
+tcg_gen_ld8u_tl(cond, cpu_env, offsetof(CPULoongArchState, cf[a->ca]));
+tcg_gen_movcond_tl(TCG_COND_EQ, cpu_fpr[a->fd], cond, zero,
+   cpu_fpr[a->fj], cpu_fpr[a->fk]);
+tcg_temp_free(cond);
+
+return true;
+}
+
+static bool gen_f2f(DisasContext *ctx, arg_ff *a,
+void (*func)(TCGv, TCGv), bool nanbox)
+{
+TCGv dest = cpu_fpr[a->fd];
+TCGv src = cpu_fpr[a->fj];
+
+func(dest, src);
+if (nanbox) {
+gen_nanbox_s(cpu_fpr[a->fd], cpu_fpr[a->fd]);
+}
+
+return true;
+}
+
+static bool gen_r2f(DisasContext *ctx, arg_fr *a,
+void (*func)(TCGv, TCGv))
+{
+TCGv src = gpr_src(ctx, a->rj, EXT_NONE);
+
+func(cpu_fpr[a->fd], src);
+return true;
+}
+
+static bool gen_f2r(DisasContext *ctx, arg_rf *a,
+void (*func)(TCGv, TCGv))
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+
+func(dest, cpu_fpr[a->fj]);
+gen_set_gpr(a->rd, dest, EXT_NONE);
+
+return true;
+}
+
+static bool trans_movgr2fcsr(DisasContext *ctx, arg_movgr2fcsr *a)
+{
+uint32_t mask = fcsr_mask[a->fcsrd];
+TCGv Rj = gpr_src(ctx, a->rj, EXT_NONE);
+
+if (mask == UINT32_MAX) {
+tcg_gen_extrl_i64_i32(cpu_fcsr0, Rj);
+} else {
+TCGv_i32 temp = tcg_temp_new_i32();
+
+tcg_gen_extrl_i64_i32(temp, Rj);
+tcg_gen_andi_i32(temp, temp, mask);
+tcg_gen_andi_i32(cpu_fcsr0, cpu_fcsr0, ~mask);
+tcg_gen_or_i32(cpu_fcsr0, cpu_fcsr0, temp);
+tcg_temp_free_i32(temp);
+
+/*
+ * Install the new rounding mode to fpu_status, if changed.
+ * Note that FCSR3 is exactly the rounding mode field.
+ */
+if (mask != FCSR0_M3) {
+return true;
+}
+}
+gen_helper_set_rounding_mode(cpu_env, cpu_fcsr0);
+
+return true;
+}
+
+static bool trans_movfcsr2gr(DisasContext *ctx, arg_movfcsr2gr *a)
+{
+TCGv_i32 temp = tcg_temp_new_i32();
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+
+tcg_gen_andi_i32(temp, cpu_fcsr0, fcsr_mask[a->fcsrs]);
+tcg_gen_ext_i32_i64(dest, temp);
+gen_set_gpr(a->rd, dest, EXT_NONE);
+tcg_temp_free_i32(temp);
+
+return true;
+}
+
+static void gen_movgr2fr_w(TCGv dest, TCGv src)
+{
+tcg_gen_deposit_i64(dest, dest, src, 0, 32);
+}
+
+static void gen_movgr2frh_w(TCGv dest, TCGv src)
+{
+tcg_gen_deposit_i64(dest, dest, src, 32, 32);
+}
+
+static void gen_movfrh2gr_s(TCGv dest, TCGv src)
+{
+tcg_gen_sextract_tl(dest, src, 32, 32);
+}
+
+static bool trans_movfr2cf(DisasContext *ctx, arg_movfr2cf *a)
+{
+TCGv t0 = tcg_temp_new();
+
+tcg_gen_andi_tl(t0, cpu_fpr[a->fj], 0x1);
+tcg_gen_st8_tl(t0, cpu_env, offsetof(CPULoongArchState, cf[a->c

[PATCH v2 27/43] target/loongarch: Add TLB instruction support

2022-04-25 Thread Xiaojuan Yang
This includes:
- TLBSRCH
- TLBRD
- TLBWR
- TLBFILL
- TLBCLR
- TLBFLUSH
- INVTLB

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
---
 target/loongarch/disas.c  |  18 +
 target/loongarch/helper.h |  13 +
 .../insn_trans/trans_privileged.c.inc | 102 +
 target/loongarch/insns.decode |  11 +
 target/loongarch/tlb_helper.c | 355 ++
 5 files changed, 499 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index fcc06abc6b..8e9a6443b7 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -297,6 +297,17 @@ static void output_rr_csr(DisasContext *ctx, arg_rr_csr *a,
a->rd, a->rj, a->csr, csr_names[a->csr]);
 }
 
+static void output_empty(DisasContext *ctx, arg_empty *a,
+ const char *mnemonic)
+{
+output(ctx, mnemonic, "");
+}
+
+static void output_i_rr(DisasContext *ctx, arg_i_rr *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "%d, r%d, r%d", a->imm, a->rj, a->rk);
+}
+
 #define INSN(insn, type)\
 static bool trans_##insn(DisasContext *ctx, arg_##type * a) \
 {   \
@@ -617,6 +628,13 @@ INSN(iocsrwr_b,rr)
 INSN(iocsrwr_h,rr)
 INSN(iocsrwr_w,rr)
 INSN(iocsrwr_d,rr)
+INSN(tlbsrch,  empty)
+INSN(tlbrd,empty)
+INSN(tlbwr,empty)
+INSN(tlbfill,  empty)
+INSN(tlbclr,   empty)
+INSN(tlbflush, empty)
+INSN(invtlb,   i_rr)
 
 #define output_fcmp(C, PREFIX, SUFFIX) 
\
 {  
\
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 4664a02dcf..b092ca75fe 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -108,3 +108,16 @@ DEF_HELPER_3(iocsrwr_b, void, env, tl, tl)
 DEF_HELPER_3(iocsrwr_h, void, env, tl, tl)
 DEF_HELPER_3(iocsrwr_w, void, env, tl, tl)
 DEF_HELPER_3(iocsrwr_d, void, env, tl, tl)
+
+/* TLB helper */
+DEF_HELPER_1(tlbwr, void, env)
+DEF_HELPER_1(tlbfill, void, env)
+DEF_HELPER_1(tlbsrch, void, env)
+DEF_HELPER_1(tlbrd, void, env)
+DEF_HELPER_1(tlbclr, void, env)
+DEF_HELPER_1(tlbflush, void, env)
+DEF_HELPER_1(invtlb_all, void, env)
+DEF_HELPER_2(invtlb_all_g, void, env, i32)
+DEF_HELPER_2(invtlb_all_asid, void, env, tl)
+DEF_HELPER_3(invtlb_page_asid, void, env, tl, tl)
+DEF_HELPER_3(invtlb_page_asid_or_g, void, env, tl, tl)
diff --git a/target/loongarch/insn_trans/trans_privileged.c.inc 
b/target/loongarch/insn_trans/trans_privileged.c.inc
index 8a1c5b8511..0363d1fda4 100644
--- a/target/loongarch/insn_trans/trans_privileged.c.inc
+++ b/target/loongarch/insn_trans/trans_privileged.c.inc
@@ -291,3 +291,105 @@ TRANS(iocsrwr_b, gen_iocsrwr, gen_helper_iocsrwr_b)
 TRANS(iocsrwr_h, gen_iocsrwr, gen_helper_iocsrwr_h)
 TRANS(iocsrwr_w, gen_iocsrwr, gen_helper_iocsrwr_w)
 TRANS(iocsrwr_d, gen_iocsrwr, gen_helper_iocsrwr_d)
+
+static void check_mmu_idx(DisasContext *ctx)
+{
+if (ctx->mem_idx != MMU_DA_IDX) {
+tcg_gen_exit_tb(NULL, 0);
+ctx->base.is_jmp = DISAS_NORETURN;
+}
+}
+
+static bool trans_tlbsrch(DisasContext *ctx, arg_tlbsrch *a)
+{
+if (check_plv(ctx)) {
+return false;
+}
+gen_helper_tlbsrch(cpu_env);
+return true;
+}
+
+static bool trans_tlbrd(DisasContext *ctx, arg_tlbrd *a)
+{
+if (check_plv(ctx)) {
+return false;
+}
+gen_helper_tlbrd(cpu_env);
+return true;
+}
+
+static bool trans_tlbwr(DisasContext *ctx, arg_tlbwr *a)
+{
+if (check_plv(ctx)) {
+return false;
+}
+gen_helper_tlbwr(cpu_env);
+check_mmu_idx(ctx);
+return true;
+}
+
+static bool trans_tlbfill(DisasContext *ctx, arg_tlbfill *a)
+{
+if (check_plv(ctx)) {
+return false;
+}
+gen_helper_tlbfill(cpu_env);
+check_mmu_idx(ctx);
+return true;
+}
+
+static bool trans_tlbclr(DisasContext *ctx, arg_tlbclr *a)
+{
+if (check_plv(ctx)) {
+return false;
+}
+gen_helper_tlbclr(cpu_env);
+check_mmu_idx(ctx);
+return true;
+}
+
+static bool trans_tlbflush(DisasContext *ctx, arg_tlbflush *a)
+{
+if (check_plv(ctx)) {
+return false;
+}
+gen_helper_tlbflush(cpu_env);
+check_mmu_idx(ctx);
+return true;
+}
+
+static bool trans_invtlb(DisasContext *ctx, arg_invtlb *a)
+{
+TCGv rj = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv rk = gpr_src(ctx, a->rk, EXT_NONE);
+
+if (check_plv(ctx)) {
+return false;
+}
+
+switch (a->imm) {
+case 0:
+case 1:
+gen_helper_invtlb_all(cpu_env);
+break;
+case 2:
+gen_helper_invtlb_all_g(cpu_env, tcg_constant_i32(1));
+break;
+case 3:
+gen_helper_invtlb_all_g(cpu_env, tcg_constant_i32(0));
+break;
+   

[PATCH v2 33/43] hw/intc: Add LoongArch ls7a msi interrupt controller support(PCH-MSI)

2022-04-25 Thread Xiaojuan Yang
This patch realize PCH-MSI interrupt controller.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
---
 hw/intc/Kconfig |  5 ++
 hw/intc/loongarch_pch_msi.c | 75 +
 hw/intc/meson.build |  1 +
 hw/intc/trace-events|  3 ++
 hw/loongarch/Kconfig|  1 +
 include/hw/intc/loongarch_pch_msi.h | 20 
 6 files changed, 105 insertions(+)
 create mode 100644 hw/intc/loongarch_pch_msi.c
 create mode 100644 include/hw/intc/loongarch_pch_msi.h

diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
index 1fbba2e728..71c04c328e 100644
--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -91,3 +91,8 @@ config LOONGARCH_IPI
 config LOONGARCH_PCH_PIC
 bool
 select UNIMP
+
+config LOONGARCH_PCH_MSI
+select MSI_NONBROKEN
+bool
+select UNIMP
diff --git a/hw/intc/loongarch_pch_msi.c b/hw/intc/loongarch_pch_msi.c
new file mode 100644
index 00..57a894f3e5
--- /dev/null
+++ b/hw/intc/loongarch_pch_msi.c
@@ -0,0 +1,75 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU Loongson 7A1000 msi interrupt controller.
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "hw/intc/loongarch_pch_msi.h"
+#include "hw/intc/loongarch_pch_pic.h"
+#include "hw/pci/msi.h"
+#include "hw/misc/unimp.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+
+static uint64_t loongarch_msi_mem_read(void *opaque, hwaddr addr, unsigned 
size)
+{
+return 0;
+}
+
+static void loongarch_msi_mem_write(void *opaque, hwaddr addr,
+uint64_t val, unsigned size)
+{
+LoongArchPCHMSI *s = LOONGARCH_PCH_MSI(opaque);
+int irq_num = val & 0xff;
+
+trace_loongarch_msi_set_irq(irq_num);
+qemu_set_irq(s->pch_msi_irq[irq_num - PCH_PIC_IRQ_NUM], 1);
+}
+
+static const MemoryRegionOps loongarch_pch_msi_ops = {
+.read  = loongarch_msi_mem_read,
+.write = loongarch_msi_mem_write,
+.endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void pch_msi_irq_handler(void *opaque, int irq, int level)
+{
+LoongArchPCHMSI *s = LOONGARCH_PCH_MSI(opaque);
+
+qemu_set_irq(s->pch_msi_irq[irq], level);
+}
+
+static void loongarch_pch_msi_init(Object *obj)
+{
+LoongArchPCHMSI *s = LOONGARCH_PCH_MSI(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+int i;
+
+memory_region_init_io(>msi_mmio, obj, _pch_msi_ops,
+  s, TYPE_LOONGARCH_PCH_MSI, 0x8);
+sysbus_init_mmio(sbd, >msi_mmio);
+msi_nonbroken = true;
+
+for (i = 0; i < PCH_MSI_IRQ_NUM; i++) {
+sysbus_init_irq(sbd, >pch_msi_irq[i]);
+}
+qdev_init_gpio_in(DEVICE(obj), pch_msi_irq_handler, PCH_MSI_IRQ_NUM);
+}
+
+static const TypeInfo loongarch_pch_msi_info = {
+.name  = TYPE_LOONGARCH_PCH_MSI,
+.parent= TYPE_SYS_BUS_DEVICE,
+.instance_size = sizeof(LoongArchPCHMSI),
+.instance_init = loongarch_pch_msi_init,
+};
+
+static void loongarch_pch_msi_register_types(void)
+{
+type_register_static(_pch_msi_info);
+}
+
+type_init(loongarch_pch_msi_register_types)
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
index 960ce81a92..77a30cec33 100644
--- a/hw/intc/meson.build
+++ b/hw/intc/meson.build
@@ -64,3 +64,4 @@ specific_ss.add(when: 'CONFIG_GOLDFISH_PIC', if_true: 
files('goldfish_pic.c'))
 specific_ss.add(when: 'CONFIG_M68K_IRQC', if_true: files('m68k_irqc.c'))
 specific_ss.add(when: 'CONFIG_LOONGARCH_IPI', if_true: 
files('loongarch_ipi.c'))
 specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_PIC', if_true: 
files('loongarch_pch_pic.c'))
+specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_MSI', if_true: 
files('loongarch_pch_msi.c'))
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index 1f343676ee..8bcc1b6992 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -300,3 +300,6 @@ loongarch_pch_pic_high_readw(unsigned size, uint32_t addr, 
unsigned long val) "s
 loongarch_pch_pic_high_writew(unsigned size, uint32_t addr, unsigned long val) 
"size: %u addr: 0x%"PRIx32 "val: 0x%" PRIx64
 loongarch_pch_pic_readb(unsigned size, uint32_t addr, unsigned long val) 
"size: %u addr: 0x%"PRIx32 "val: 0x%" PRIx64
 loongarch_pch_pic_writeb(unsigned size, uint32_t addr, unsigned long val) 
"size: %u addr: 0x%"PRIx32 "val: 0x%" PRIx64
+
+# loongarch_pch_msi.c
+loongarch_msi_set_irq(int irq_num) "set msi irq %d"
diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
index 2df45f7e8f..d814fc6103 100644
--- a/hw/loongarch/Kconfig
+++ b/hw/loongarch/Kconfig
@@ -4,3 +4,4 @@ config LOONGARCH_VIRT
 select PCI_EXPRESS_GENERIC_BRIDGE
 select LOONGARCH_IPI
 select LOONGARCH_PCH_PIC
+select LOONGARCH_PCH_MSI
diff --git a/i

[PATCH v2 21/43] target/loongarch: Implement qmp_query_cpu_definitions()

2022-04-25 Thread Xiaojuan Yang
Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
---
 qapi/machine-target.json |  6 --
 target/loongarch/cpu.c   | 26 ++
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/qapi/machine-target.json b/qapi/machine-target.json
index f5ec4bc172..682dc86b42 100644
--- a/qapi/machine-target.json
+++ b/qapi/machine-target.json
@@ -324,7 +324,8 @@
'TARGET_ARM',
'TARGET_I386',
'TARGET_S390X',
-   'TARGET_MIPS' ] } }
+   'TARGET_MIPS',
+   'TARGET_LOONGARCH64' ] } }
 
 ##
 # @query-cpu-definitions:
@@ -340,4 +341,5 @@
'TARGET_ARM',
'TARGET_I386',
'TARGET_S390X',
-   'TARGET_MIPS' ] } }
+   'TARGET_MIPS',
+   'TARGET_LOONGARCH64' ] } }
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index ef16779fc9..176e277197 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -360,3 +360,29 @@ static const TypeInfo loongarch_cpu_type_infos[] = {
 };
 
 DEFINE_TYPES(loongarch_cpu_type_infos)
+
+static void loongarch_cpu_add_definition(gpointer data, gpointer user_data)
+{
+ObjectClass *oc = data;
+CpuDefinitionInfoList **cpu_list = user_data;
+CpuDefinitionInfo *info = g_new0(CpuDefinitionInfo, 1);
+const char *typename = object_class_get_name(oc);
+
+info->name = g_strndup(typename,
+   strlen(typename) - strlen("-" TYPE_LOONGARCH_CPU));
+info->q_typename = g_strdup(typename);
+
+QAPI_LIST_PREPEND(*cpu_list, info);
+}
+
+CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
+{
+CpuDefinitionInfoList *cpu_list = NULL;
+GSList *list;
+
+list = object_class_get_list(TYPE_LOONGARCH_CPU, false);
+g_slist_foreach(list, loongarch_cpu_add_definition, _list);
+g_slist_free(list);
+
+return cpu_list;
+}
-- 
2.31.1




[PATCH v2 43/43] target/loongarch: 'make check-tcg' support

2022-04-25 Thread Xiaojuan Yang
From: Song Gao 

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
Acked-by: Alex Bennée 
Reviewed-by: Philippe Mathieu-Daudé 
---
 tests/tcg/configure.sh | 1 +
 1 file changed, 1 insertion(+)

diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh
index 691d90abac..331044c65d 100755
--- a/tests/tcg/configure.sh
+++ b/tests/tcg/configure.sh
@@ -51,6 +51,7 @@ fi
 : ${cross_cc_cflags_armeb="-mbig-endian"}
 : ${cross_cc_hexagon="hexagon-unknown-linux-musl-clang"}
 : ${cross_cc_cflags_hexagon="-mv67 -O2 -static"}
+: ${cross_cc_loongarch64="loongarch64-unknown-linux-gnu-gcc"}
 : ${cross_cc_hppa="hppa-linux-gnu-gcc"}
 : ${cross_cc_i386="i686-linux-gnu-gcc"}
 : ${cross_cc_cflags_i386="-m32"}
-- 
2.31.1




[PATCH v2 38/43] hw/loongarch: Add LoongArch ls7a rtc device support

2022-04-25 Thread Xiaojuan Yang
This patch add ls7a rtc device support.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 MAINTAINERS|   1 +
 hw/loongarch/Kconfig   |   1 +
 hw/loongarch/loongson3.c   |   4 +
 hw/rtc/Kconfig |   3 +
 hw/rtc/ls7a_rtc.c  | 322 +
 hw/rtc/meson.build |   1 +
 include/hw/pci-host/ls7a.h |   4 +
 7 files changed, 336 insertions(+)
 create mode 100644 hw/rtc/ls7a_rtc.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 1b724a7d35..7969004b91 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1137,6 +1137,7 @@ F: include/hw/loongarch/virt.h
 F: include/hw/intc/loongarch_*.h
 F: hw/intc/loongarch_*.c
 F: include/hw/pci-host/ls7a.h
+F: hw/rtc/ls7a_rtc.c
 
 M68K Machines
 -
diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
index 8552ff4bee..35b6680772 100644
--- a/hw/loongarch/Kconfig
+++ b/hw/loongarch/Kconfig
@@ -13,3 +13,4 @@ config LOONGARCH_VIRT
 select LOONGARCH_PCH_PIC
 select LOONGARCH_PCH_MSI
 select LOONGARCH_EXTIOI
+select LS7A_RTC
diff --git a/hw/loongarch/loongson3.c b/hw/loongarch/loongson3.c
index 92c353263e..2b87b193c7 100644
--- a/hw/loongarch/loongson3.c
+++ b/hw/loongarch/loongson3.c
@@ -97,6 +97,10 @@ static void loongarch_devices_init(DeviceState *pch_pic)
  * Create some unimplemented devices to emulate this.
  */
 create_unimplemented_device("pci-dma-cfg", 0x1001041c, 0x4);
+
+sysbus_create_simple("ls7a_rtc", LS7A_RTC_REG_BASE,
+ qdev_get_gpio_in(pch_pic,
+ LS7A_RTC_IRQ - PCH_PIC_IRQ_OFFSET));
 }
 
 static void loongarch_irq_init(LoongArchMachineState *lams)
diff --git a/hw/rtc/Kconfig b/hw/rtc/Kconfig
index 730c272bc5..d0d8dda084 100644
--- a/hw/rtc/Kconfig
+++ b/hw/rtc/Kconfig
@@ -27,3 +27,6 @@ config SUN4V_RTC
 
 config GOLDFISH_RTC
 bool
+
+config LS7A_RTC
+bool
diff --git a/hw/rtc/ls7a_rtc.c b/hw/rtc/ls7a_rtc.c
new file mode 100644
index 00..dd40478409
--- /dev/null
+++ b/hw/rtc/ls7a_rtc.c
@@ -0,0 +1,322 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Loongarch LS7A Real Time Clock emulation
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "include/hw/register.h"
+#include "qemu/timer.h"
+#include "sysemu/sysemu.h"
+#include "qemu/cutils.h"
+#include "qemu/log.h"
+#include "migration/vmstate.h"
+#include "hw/misc/unimp.h"
+#include "sysemu/rtc.h"
+
+#define SYS_TOYTRIM0x20
+#define SYS_TOYWRITE0  0x24
+#define SYS_TOYWRITE1  0x28
+#define SYS_TOYREAD0   0x2C
+#define SYS_TOYREAD1   0x30
+#define SYS_TOYMATCH0  0x34
+#define SYS_TOYMATCH1  0x38
+#define SYS_TOYMATCH2  0x3C
+#define SYS_RTCCTRL0x40
+#define SYS_RTCTRIM0x60
+#define SYS_RTCWRTIE0  0x64
+#define SYS_RTCREAD0   0x68
+#define SYS_RTCMATCH0  0x6C
+#define SYS_RTCMATCH1  0x70
+#define SYS_RTCMATCH2  0x74
+
+/*
+ * Shift bits and filed mask
+ */
+#define TOY_MON_MASK   0x3f
+#define TOY_DAY_MASK   0x1f
+#define TOY_HOUR_MASK  0x1f
+#define TOY_MIN_MASK   0x3f
+#define TOY_SEC_MASK   0x3f
+#define TOY_MSEC_MASK  0xf
+
+#define TOY_MON_SHIFT  26
+#define TOY_DAY_SHIFT  21
+#define TOY_HOUR_SHIFT 16
+#define TOY_MIN_SHIFT  10
+#define TOY_SEC_SHIFT  4
+#define TOY_MSEC_SHIFT 0
+
+#define TOY_MATCH_YEAR_MASK  0x3f
+#define TOY_MATCH_MON_MASK   0xf
+#define TOY_MATCH_DAY_MASK   0x1f
+#define TOY_MATCH_HOUR_MASK  0x1f
+#define TOY_MATCH_MIN_MASK   0x3f
+#define TOY_MATCH_SEC_MASK   0x3f
+
+#define TOY_MATCH_YEAR_SHIFT 26
+#define TOY_MATCH_MON_SHIFT  22
+#define TOY_MATCH_DAY_SHIFT  17
+#define TOY_MATCH_HOUR_SHIFT 12
+#define TOY_MATCH_MIN_SHIFT  6
+#define TOY_MATCH_SEC_SHIFT  0
+
+#define TOY_ENABLE_BIT (1U << 11)
+
+#define TYPE_LS7A_RTC "ls7a_rtc"
+OBJECT_DECLARE_SIMPLE_TYPE(LS7ARtcState, LS7A_RTC)
+
+struct LS7ARtcState {
+SysBusDevice parent_obj;
+
+MemoryRegion iomem;
+QEMUTimer *timer;
+/*
+ * Needed to preserve the tick_count across migration, even if the
+ * absolute value of the rtc_clock is different on the source and
+ * destination.
+ */
+int64_t offset;
+int64_t data;
+int64_t save_alarm_offset;
+int tidx;
+uint32_t toymatch[3];
+uint32_t toytrim;
+uint32_t cntrctl;
+uint32_t rtctrim;
+uint32_t rtccount;
+uint32_t rtcmatch[3];
+qemu_irq toy_irq;
+};
+
+enum {
+TOYEN = 1UL << 11,
+RTCEN = 1UL << 13,
+};
+
+static uint64_t ls7a_rtc_read(void *opaque, hwaddr addr, unsigned size)
+{
+LS7ARtcState *s = LS7A_RTC(opaque);
+struct tm tm;
+unsigned int val;
+
+val = 0;
+
+switch (addr) {
+case SYS_TOYREAD0:
+qemu_get_timedate(, s->offset);
+val = (((tm.tm_mo

[PATCH v2 01/43] target/loongarch: Add README

2022-04-25 Thread Xiaojuan Yang
From: Song Gao 

This patch gives an introduction to the LoongArch target.

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 MAINTAINERS |  6 ++
 target/loongarch/README | 10 ++
 2 files changed, 16 insertions(+)
 create mode 100644 target/loongarch/README

diff --git a/MAINTAINERS b/MAINTAINERS
index 294c88ace9..5b5377d353 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -213,6 +213,12 @@ S: Maintained
 F: target/hppa/
 F: disas/hppa.c
 
+LoongArch TCG CPUs
+M: Song Gao 
+M: Xiaojuan Yang 
+S: Maintained
+F: target/loongarch/
+
 M68K TCG CPUs
 M: Laurent Vivier 
 S: Maintained
diff --git a/target/loongarch/README b/target/loongarch/README
new file mode 100644
index 00..de141c1a58
--- /dev/null
+++ b/target/loongarch/README
@@ -0,0 +1,10 @@
+- Introduction
+
+  LoongArch is the general processor architecture of Loongson.
+
+  The following versions of the LoongArch core are supported
+core: 3A5000
+
https://github.com/loongson/LoongArch-Documentation/releases/download/2021.08.17/LoongArch-Vol1-v1.00-EN.pdf
+
+  We can get the latest loongarch documents at 
https://github.com/loongson/LoongArch-Documentation/tags.
+
-- 
2.31.1




[PATCH v2 11/43] target/loongarch: Add floating point comparison instruction translation

2022-04-25 Thread Xiaojuan Yang
From: Song Gao 

This includes:
- FCMP.cond.{S/D}

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 target/loongarch/fpu_helper.c| 60 
 target/loongarch/helper.h|  9 +++
 target/loongarch/insn_trans/trans_fcmp.c.inc | 56 ++
 target/loongarch/insns.decode|  8 +++
 target/loongarch/internals.h |  5 ++
 target/loongarch/translate.c |  1 +
 6 files changed, 139 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_fcmp.c.inc

diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c
index e875638e1d..2ad707007a 100644
--- a/target/loongarch/fpu_helper.c
+++ b/target/loongarch/fpu_helper.c
@@ -401,3 +401,63 @@ uint64_t helper_fmuladd_d(CPULoongArchState *env, uint64_t 
fj,
 update_fcsr0(env, GETPC());
 return fd;
 }
+
+static uint64_t fcmp_common(CPULoongArchState *env, FloatRelation cmp,
+uint32_t flags)
+{
+bool ret;
+
+switch (cmp) {
+case float_relation_less:
+ret = (flags & FCMP_LT);
+break;
+case float_relation_equal:
+ret = (flags & FCMP_EQ);
+break;
+case float_relation_greater:
+ret = (flags & FCMP_GT);
+break;
+case float_relation_unordered:
+ret = (flags & FCMP_UN);
+break;
+default:
+g_assert_not_reached();
+}
+update_fcsr0(env, GETPC());
+
+return ret;
+}
+
+/* fcmp_cXXX_s */
+uint64_t helper_fcmp_c_s(CPULoongArchState *env, uint64_t fj,
+ uint64_t fk, uint32_t flags)
+{
+FloatRelation cmp = float32_compare_quiet((uint32_t)fj,
+  (uint32_t)fk, >fp_status);
+return fcmp_common(env, cmp, flags);
+}
+
+/* fcmp_sXXX_s */
+uint64_t helper_fcmp_s_s(CPULoongArchState *env, uint64_t fj,
+ uint64_t fk, uint32_t flags)
+{
+FloatRelation cmp = float32_compare((uint32_t)fj,
+(uint32_t)fk, >fp_status);
+return fcmp_common(env, cmp, flags);
+}
+
+/* fcmp_cXXX_d */
+uint64_t helper_fcmp_c_d(CPULoongArchState *env, uint64_t fj,
+ uint64_t fk, uint32_t flags)
+{
+FloatRelation cmp = float64_compare_quiet(fj, fk, >fp_status);
+return fcmp_common(env, cmp, flags);
+}
+
+/* fcmp_sXXX_d */
+uint64_t helper_fcmp_s_d(CPULoongArchState *env, uint64_t fj,
+ uint64_t fk, uint32_t flags)
+{
+FloatRelation cmp = float64_compare(fj, fk, >fp_status);
+return fcmp_common(env, cmp, flags);
+}
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 840bad9b2f..25a891bf8b 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -52,3 +52,12 @@ DEF_HELPER_FLAGS_2(frecip_d, TCG_CALL_NO_WG, i64, env, i64)
 
 DEF_HELPER_FLAGS_2(fclass_s, TCG_CALL_NO_RWG_SE, i64, env, i64)
 DEF_HELPER_FLAGS_2(fclass_d, TCG_CALL_NO_RWG_SE, i64, env, i64)
+
+/* fcmp.cXXX.s */
+DEF_HELPER_4(fcmp_c_s, i64, env, i64, i64, i32)
+/* fcmp.sXXX.s */
+DEF_HELPER_4(fcmp_s_s, i64, env, i64, i64, i32)
+/* fcmp.cXXX.d */
+DEF_HELPER_4(fcmp_c_d, i64, env, i64, i64, i32)
+/* fcmp.sXXX.d */
+DEF_HELPER_4(fcmp_s_d, i64, env, i64, i64, i32)
diff --git a/target/loongarch/insn_trans/trans_fcmp.c.inc 
b/target/loongarch/insn_trans/trans_fcmp.c.inc
new file mode 100644
index 00..93a6a2230f
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_fcmp.c.inc
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+/* bit0(signaling/quiet) bit1(lt) bit2(eq) bit3(un) bit4(neq) */
+static uint32_t get_fcmp_flags(int cond)
+{
+uint32_t flags = 0;
+
+if (cond & 0x1) {
+flags |= FCMP_LT;
+}
+if (cond & 0x2) {
+flags |= FCMP_EQ;
+}
+if (cond & 0x4) {
+flags |= FCMP_UN;
+}
+if (cond & 0x8) {
+flags |= FCMP_GT | FCMP_LT;
+}
+return flags;
+}
+
+static bool trans_fcmp_cond_s(DisasContext *ctx, arg_fcmp_cond_s *a)
+{
+TCGv var = tcg_temp_new();
+uint32_t flags;
+void (*fn)(TCGv, TCGv_env, TCGv, TCGv, TCGv_i32);
+
+fn = (a->fcond & 1 ? gen_helper_fcmp_s_s : gen_helper_fcmp_c_s);
+flags = get_fcmp_flags(a->fcond >> 1);
+
+fn(var, cpu_env, cpu_fpr[a->fj], cpu_fpr[a->fk], tcg_constant_i32(flags));
+
+tcg_gen_st8_tl(var, cpu_env, offsetof(CPULoongArchState, cf[a->cd]));
+tcg_temp_free(var);
+return true;
+}
+
+static bool trans_fcmp_cond_d(DisasContext *ctx, arg_fcmp_cond_d *a)
+{
+TCGv var = tcg_temp_new();
+uint32_t flags;
+void (*fn)(TCGv, TCGv_env, TCGv, TCGv, TCGv_i32);
+fn = (a->fcond & 1 ? gen_helper_fcmp_s_d : gen_helper_fcmp_c_d);
+flags = get_fcmp_flags(a->fcond >> 1);
+
+fn(var, cpu_env, cpu_fpr[a->fj]

[PATCH v2 00/43] Add LoongArch softmmu support

2022-04-25 Thread Xiaojuan Yang
Hi All,

As this series only supports running binary files in ELF format, and does not 
depend on
BIOS and kernel file. so this series are changed from RFC to patch v1. 


The manual:
  - https://github.com/loongson/LoongArch-Documentation/releases/tag/2022.03.17

Old series:
  - https://patchew.org/QEMU/20220328125749.2918087-1-yangxiaoj...@loongson.cn/
  - https://patchew.org/QEMU/20220106094200.1801206-1-gaos...@loongson.cn/

Thanks.
Xiaojuan

-

v2:
  - Improvents to CSR/IOCSR instructions translation.
  - Fixed extioi device emulation. It is represented by only one memory region.
  - Fixed IPI device emulation. The registers are represented with uint64_t.
  - Use do_cpu_reset() and cpu_set_pc() to specify the load address. 


v1: https://patchew.org/QEMU/20220415094058.3584233-1-yangxiaoj...@loongson.cn/


Song Gao (18):
  target/loongarch: Add README
  target/loongarch: Add core definition
  target/loongarch: Add main translation routines
  target/loongarch: Add fixed point arithmetic instruction translation
  target/loongarch: Add fixed point shift instruction translation
  target/loongarch: Add fixed point bit instruction translation
  target/loongarch: Add fixed point load/store instruction translation
  target/loongarch: Add fixed point atomic instruction translation
  target/loongarch: Add fixed point extra instruction translation
  target/loongarch: Add floating point arithmetic instruction
translation
  target/loongarch: Add floating point comparison instruction
translation
  target/loongarch: Add floating point conversion instruction
translation
  target/loongarch: Add floating point move instruction translation
  target/loongarch: Add floating point load/store instruction
translation
  target/loongarch: Add branch instruction translation
  target/loongarch: Add disassembler
  target/loongarch: Add target build suport
  target/loongarch: 'make check-tcg' support

Xiaojuan Yang (25):
  target/loongarch: Add system emulation introduction
  target/loongarch: Add CSRs definition
  target/loongarch: Add basic vmstate description of CPU.
  target/loongarch: Implement qmp_query_cpu_definitions()
  target/loongarch: Add MMU support for LoongArch CPU.
  target/loongarch: Add LoongArch interrupt and exception handle
  target/loongarch: Add constant timer support
  target/loongarch: Add LoongArch CSR instruction
  target/loongarch: Add LoongArch IOCSR instruction
  target/loongarch: Add TLB instruction support
  target/loongarch: Add other core instructions support
  target/loongarch: Add timer related instructions support.
  hw/loongarch: Add support loongson3 virt machine type.
  hw/loongarch: Add LoongArch ipi interrupt support(IPI)
  hw/intc: Add LoongArch ls7a interrupt controller support(PCH-PIC)
  hw/intc: Add LoongArch ls7a msi interrupt controller support(PCH-MSI)
  hw/intc: Add LoongArch extioi interrupt controller(EIOINTC)
  hw/loongarch: Add irq hierarchy for the system
  Enable common virtio pci support for LoongArch
  hw/loongarch: Add some devices support for 3A5000.
  hw/loongarch: Add LoongArch ls7a rtc device support
  hw/loongarch: Add LoongArch load elf function.
  hw/loongarch: Add LoongArch ls7a acpi device support
  target/loongarch: Add gdb support.
  tests/tcg/loongarch64: Add hello/memory test in loongarch64 system

 MAINTAINERS   |  26 +
 .../devices/loongarch64-softmmu/default.mak   |   3 +
 configs/targets/loongarch64-softmmu.mak   |   4 +
 docs/system/loongarch/loongson3.rst   |  41 +
 gdb-xml/loongarch-base64.xml  |  44 +
 gdb-xml/loongarch-fpu64.xml   |  57 ++
 hw/Kconfig|   1 +
 hw/acpi/Kconfig   |   4 +
 hw/acpi/ls7a.c| 374 
 hw/acpi/meson.build   |   1 +
 hw/intc/Kconfig   |  15 +
 hw/intc/loongarch_extioi.c| 483 ++
 hw/intc/loongarch_ipi.c   | 166 
 hw/intc/loongarch_pch_msi.c   |  75 ++
 hw/intc/loongarch_pch_pic.c   | 434 +
 hw/intc/meson.build   |   4 +
 hw/intc/trace-events  |  25 +
 hw/loongarch/Kconfig  |  18 +
 hw/loongarch/loongson3.c  | 349 +++
 hw/loongarch/meson.build  |   4 +
 hw/meson.build|   1 +
 hw/rtc/Kconfig|   3 +
 hw/rtc/ls7a_rtc.c | 322 +++
 hw/rtc/meson.build|   1 +
 include/disas/dis-asm.h   |   2 +
 include/exec/poison.h |   2 +
 include/hw/acpi/ls7a.h|  53 ++
 include/hw/intc/loongarch_extioi.h|  60 ++
 include/hw/intc/loongarch_ipi.h   |  50 +
 include/hw/intc

[PATCH v2 14/43] target/loongarch: Add floating point load/store instruction translation

2022-04-25 Thread Xiaojuan Yang
From: Song Gao 

This includes:
- FLD.{S/D}, FST.{S/D}
- FLDX.{S/D}, FSTX.{S/D}
- FLD{GT/LE}.{S/D}, FST{GT/LE}.{S/D}

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 .../loongarch/insn_trans/trans_fmemory.c.inc  | 153 ++
 target/loongarch/insns.decode |  24 +++
 target/loongarch/translate.c  |   1 +
 3 files changed, 178 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_fmemory.c.inc

diff --git a/target/loongarch/insn_trans/trans_fmemory.c.inc 
b/target/loongarch/insn_trans/trans_fmemory.c.inc
new file mode 100644
index 00..74ee98f63a
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_fmemory.c.inc
@@ -0,0 +1,153 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static void maybe_nanbox_load(TCGv freg, MemOp mop)
+{
+if ((mop & MO_SIZE) == MO_32) {
+gen_nanbox_s(freg, freg);
+}
+}
+
+static bool gen_fload_i(DisasContext *ctx, arg_fr_i *a, MemOp mop)
+{
+TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv temp = NULL;
+
+if (a->imm) {
+temp = tcg_temp_new();
+tcg_gen_addi_tl(temp, addr, a->imm);
+addr = temp;
+}
+
+tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+maybe_nanbox_load(cpu_fpr[a->fd], mop);
+
+if (temp) {
+tcg_temp_free(temp);
+}
+
+return true;
+}
+
+static bool gen_fstore_i(DisasContext *ctx, arg_fr_i *a, MemOp mop)
+{
+TCGv addr = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv temp = NULL;
+
+if (a->imm) {
+temp = tcg_temp_new();
+tcg_gen_addi_tl(temp, addr, a->imm);
+addr = temp;
+}
+
+tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+
+if (temp) {
+tcg_temp_free(temp);
+}
+return true;
+}
+
+static bool gen_floadx(DisasContext *ctx, arg_frr *a, MemOp mop)
+{
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+TCGv addr = tcg_temp_new();
+
+tcg_gen_add_tl(addr, src1, src2);
+tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+maybe_nanbox_load(cpu_fpr[a->fd], mop);
+tcg_temp_free(addr);
+
+return true;
+}
+
+static bool gen_fstorex(DisasContext *ctx, arg_frr *a, MemOp mop)
+{
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+TCGv addr = tcg_temp_new();
+
+tcg_gen_add_tl(addr, src1, src2);
+tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+tcg_temp_free(addr);
+
+return true;
+}
+
+static bool gen_fload_gt(DisasContext *ctx, arg_frr *a, MemOp mop)
+{
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+TCGv addr = tcg_temp_new();
+
+gen_helper_asrtgt_d(cpu_env, src1, src2);
+tcg_gen_add_tl(addr, src1, src2);
+tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+maybe_nanbox_load(cpu_fpr[a->fd], mop);
+tcg_temp_free(addr);
+
+return true;
+}
+
+static bool gen_fstore_gt(DisasContext *ctx, arg_frr *a, MemOp mop)
+{
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+TCGv addr = tcg_temp_new();
+
+gen_helper_asrtgt_d(cpu_env, src1, src2);
+tcg_gen_add_tl(addr, src1, src2);
+tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+tcg_temp_free(addr);
+
+return true;
+}
+
+static bool gen_fload_le(DisasContext *ctx, arg_frr *a, MemOp mop)
+{
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+TCGv addr = tcg_temp_new();
+
+gen_helper_asrtle_d(cpu_env, src1, src2);
+tcg_gen_add_tl(addr, src1, src2);
+tcg_gen_qemu_ld_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+maybe_nanbox_load(cpu_fpr[a->fd], mop);
+tcg_temp_free(addr);
+
+return true;
+}
+
+static bool gen_fstore_le(DisasContext *ctx, arg_frr *a, MemOp mop)
+{
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+TCGv addr = tcg_temp_new();
+
+gen_helper_asrtle_d(cpu_env, src1, src2);
+tcg_gen_add_tl(addr, src1, src2);
+tcg_gen_qemu_st_tl(cpu_fpr[a->fd], addr, ctx->mem_idx, mop);
+tcg_temp_free(addr);
+
+return true;
+}
+
+TRANS(fld_s, gen_fload_i, MO_TEUL)
+TRANS(fst_s, gen_fstore_i, MO_TEUL)
+TRANS(fld_d, gen_fload_i, MO_TEUQ)
+TRANS(fst_d, gen_fstore_i, MO_TEUQ)
+TRANS(fldx_s, gen_floadx, MO_TEUL)
+TRANS(fldx_d, gen_floadx, MO_TEUQ)
+TRANS(fstx_s, gen_fstorex, MO_TEUL)
+TRANS(fstx_d, gen_fstorex, MO_TEUQ)
+TRANS(fldgt_s, gen_fload_gt, MO_TEUL)
+TRANS(fldgt_d, gen_fload_gt, MO_TEUQ)
+TRANS(fldle_s, gen_fload_le, MO_TEUL)
+TRANS(fldle_d, gen_fload_le, MO_TEUQ)
+TRANS(fstgt_s, gen_fstore_gt, MO_TEUL)
+TRANS(fstgt_d, gen_fstore_gt, 

[PATCH v2 15/43] target/loongarch: Add branch instruction translation

2022-04-25 Thread Xiaojuan Yang
From: Song Gao 

This includes:
- BEQ, BNE, BLT[U], BGE[U]
- BEQZ, BNEZ
- B
- BL
- JIRL
- BCEQZ, BCNEZ

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 .../loongarch/insn_trans/trans_branch.c.inc   | 83 +++
 target/loongarch/insns.decode | 28 +++
 target/loongarch/translate.c  |  1 +
 3 files changed, 112 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_branch.c.inc

diff --git a/target/loongarch/insn_trans/trans_branch.c.inc 
b/target/loongarch/insn_trans/trans_branch.c.inc
new file mode 100644
index 00..65dbdff41e
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_branch.c.inc
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static bool trans_b(DisasContext *ctx, arg_b *a)
+{
+gen_goto_tb(ctx, 0, ctx->base.pc_next + a->offs);
+ctx->base.is_jmp = DISAS_NORETURN;
+return true;
+}
+
+static bool trans_bl(DisasContext *ctx, arg_bl *a)
+{
+tcg_gen_movi_tl(cpu_gpr[1], ctx->base.pc_next + 4);
+gen_goto_tb(ctx, 0, ctx->base.pc_next + a->offs);
+ctx->base.is_jmp = DISAS_NORETURN;
+return true;
+}
+
+static bool trans_jirl(DisasContext *ctx, arg_jirl *a)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+tcg_gen_addi_tl(cpu_pc, src1, a->offs);
+tcg_gen_movi_tl(dest, ctx->base.pc_next + 4);
+gen_set_gpr(a->rd, dest, EXT_NONE);
+tcg_gen_lookup_and_goto_ptr();
+ctx->base.is_jmp = DISAS_NORETURN;
+return true;
+}
+
+static void gen_bc(DisasContext *ctx, TCGv src1, TCGv src2,
+   target_long offs, TCGCond cond)
+{
+TCGLabel *l = gen_new_label();
+tcg_gen_brcond_tl(cond, src1, src2, l);
+gen_goto_tb(ctx, 1, ctx->base.pc_next + 4);
+gen_set_label(l);
+gen_goto_tb(ctx, 0, ctx->base.pc_next + offs);
+ctx->base.is_jmp = DISAS_NORETURN;
+}
+
+static bool gen_rr_bc(DisasContext *ctx, arg_rr_offs *a, TCGCond cond)
+{
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rd, EXT_NONE);
+
+gen_bc(ctx, src1, src2, a->offs, cond);
+return true;
+}
+
+static bool gen_rz_bc(DisasContext *ctx, arg_r_offs *a, TCGCond cond)
+{
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = tcg_constant_tl(0);
+
+gen_bc(ctx, src1, src2, a->offs, cond);
+return true;
+}
+
+static bool gen_cz_bc(DisasContext *ctx, arg_c_offs *a, TCGCond cond)
+{
+TCGv src1 = tcg_temp_new();
+TCGv src2 = tcg_constant_tl(0);
+
+tcg_gen_ld8u_tl(src1, cpu_env,
+offsetof(CPULoongArchState, cf[a->cj]));
+gen_bc(ctx, src1, src2, a->offs, cond);
+return true;
+}
+
+TRANS(beq, gen_rr_bc, TCG_COND_EQ)
+TRANS(bne, gen_rr_bc, TCG_COND_NE)
+TRANS(blt, gen_rr_bc, TCG_COND_LT)
+TRANS(bge, gen_rr_bc, TCG_COND_GE)
+TRANS(bltu, gen_rr_bc, TCG_COND_LTU)
+TRANS(bgeu, gen_rr_bc, TCG_COND_GEU)
+TRANS(beqz, gen_rz_bc, TCG_COND_EQ)
+TRANS(bnez, gen_rz_bc, TCG_COND_NE)
+TRANS(bceqz, gen_cz_bc, TCG_COND_EQ)
+TRANS(bcnez, gen_cz_bc, TCG_COND_NE)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 8f286e7233..9b293dfdf9 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -10,6 +10,9 @@
 #
 %i14s2 10:s14   !function=shl_2
 %sa2p1 15:2 !function=plus_1
+%offs210:s5 10:16   !function=shl_2
+%offs1610:s16   !function=shl_2
+%offs260:s10 10:16  !function=shl_2
 
 #
 # Argument sets
@@ -38,6 +41,10 @@
rd cj
   fd rj rk
 _i fd rj imm
+_offs   rj offs
+_offs   cj offs
+ offs
+_offs  rj rd offs
 
 #
 # Formats
@@ -74,6 +81,10 @@
 @rc  . . .. cj:3 rd:5
 @frr     . rk:5 rj:5 fd:5
 @fr_i12  .. imm:s12 rj:5 fd:5_i
+@r_offs21  ..  rj:5 ._offs  
offs=%offs21
+@c_offs21   ..  .. cj:3 ._offs  
offs=%offs21
+@offs26 .. ..
offs=%offs26
+@rr_offs16  ..  rj:5 rd:5_offs 
offs=%offs16
 
 #
 # Fixed point arithmetic operation instruction
@@ -409,3 +420,20 @@ fstgt_s 0011 1111 01100 . . .
@frr
 fstgt_d 0011 1111 01101 . . .@frr
 fstle_s 0011 1111 01110 . . .@frr
 fstle_d 0011 1111 0 . . .@frr
+
+#
+# Branch instructions
+#
+beqz0100 00  . . @r_offs21
+bnez0100 01  . . @r_offs21
+bceqz   0100 10  00 ... .@c_offs21
+bcnez   0100 10  01 ... .@c_offs21
+j

[PATCH v2 17/43] target/loongarch: Add target build suport

2022-04-25 Thread Xiaojuan Yang
From: Song Gao 

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 target/loongarch/meson.build | 19 +++
 target/meson.build   |  1 +
 2 files changed, 20 insertions(+)
 create mode 100644 target/loongarch/meson.build

diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
new file mode 100644
index 00..bcb076e55f
--- /dev/null
+++ b/target/loongarch/meson.build
@@ -0,0 +1,19 @@
+gen = decodetree.process('insns.decode')
+
+loongarch_ss = ss.source_set()
+loongarch_ss.add(files(
+  'cpu.c',
+  'disas.c',
+))
+loongarch_tcg_ss = ss.source_set()
+loongarch_tcg_ss.add(gen)
+loongarch_tcg_ss.add(files(
+  'fpu_helper.c',
+  'op_helper.c',
+  'translate.c',
+))
+loongarch_tcg_ss.add(zlib)
+
+loongarch_ss.add_all(when: 'CONFIG_TCG', if_true: [loongarch_tcg_ss])
+
+target_arch += {'loongarch': loongarch_ss}
diff --git a/target/meson.build b/target/meson.build
index 2f6940255e..a53a60486f 100644
--- a/target/meson.build
+++ b/target/meson.build
@@ -5,6 +5,7 @@ subdir('cris')
 subdir('hexagon')
 subdir('hppa')
 subdir('i386')
+subdir('loongarch')
 subdir('m68k')
 subdir('microblaze')
 subdir('mips')
-- 
2.31.1




[PATCH v2 20/43] target/loongarch: Add basic vmstate description of CPU.

2022-04-25 Thread Xiaojuan Yang
Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
---
 target/loongarch/cpu.c   |  1 +
 target/loongarch/internals.h |  2 +
 target/loongarch/machine.c   | 86 
 target/loongarch/meson.build |  6 +++
 4 files changed, 95 insertions(+)
 create mode 100644 target/loongarch/machine.c

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index f14724b78b..ef16779fc9 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -331,6 +331,7 @@ static void loongarch_cpu_class_init(ObjectClass *c, void 
*data)
 cc->class_by_name = loongarch_cpu_class_by_name;
 cc->dump_state = loongarch_cpu_dump_state;
 cc->set_pc = loongarch_cpu_set_pc;
+dc->vmsd = _loongarch_cpu;
 cc->disas_set_info = loongarch_cpu_disas_set_info;
 #ifdef CONFIG_TCG
 cc->tcg_ops = _tcg_ops;
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index 1a3b39e0be..39960dee27 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -25,4 +25,6 @@ const char *loongarch_exception_name(int32_t exception);
 
 void restore_fp_status(CPULoongArchState *env);
 
+extern const VMStateDescription vmstate_loongarch_cpu;
+
 #endif
diff --git a/target/loongarch/machine.c b/target/loongarch/machine.c
new file mode 100644
index 00..72c8602c9c
--- /dev/null
+++ b/target/loongarch/machine.c
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch Machine State
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "migration/cpu.h"
+
+/* LoongArch CPU state */
+
+const VMStateDescription vmstate_loongarch_cpu = {
+.name = "cpu",
+.version_id = 0,
+.minimum_version_id = 0,
+.fields = (VMStateField[]) {
+
+VMSTATE_UINTTL_ARRAY(env.gpr, LoongArchCPU, 32),
+VMSTATE_UINTTL(env.pc, LoongArchCPU),
+VMSTATE_UINT64_ARRAY(env.fpr, LoongArchCPU, 32),
+VMSTATE_UINT32(env.fcsr0, LoongArchCPU),
+VMSTATE_BOOL_ARRAY(env.cf, LoongArchCPU, 8),
+
+/* Remaining CSRs */
+VMSTATE_UINT64(env.CSR_CRMD, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_PRMD, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_EUEN, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_MISC, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_ECFG, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_ESTAT, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_ERA, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_BADV, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_BADI, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_EENTRY, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBIDX, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBEHI, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBELO0, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBELO1, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_ASID, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_PGDL, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_PGDH, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_PGD, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_PWCL, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_PWCH, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_STLBPS, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_RVACFG, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_CPUID, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_PRCFG1, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_PRCFG2, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_PRCFG3, LoongArchCPU),
+VMSTATE_UINT64_ARRAY(env.CSR_SAVE, LoongArchCPU, 16),
+VMSTATE_UINT64(env.CSR_TID, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TCFG, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TVAL, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_CNTC, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TICLR, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_LLBCTL, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_IMPCTL1, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_IMPCTL2, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBRENTRY, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBRBADV, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBRERA, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBRSAVE, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBRELO0, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBRELO1, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBREHI, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_TLBRPRMD, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_MERRCTL, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_MERRINFO1, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_MERRINFO2, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_MERRENTRY, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_MERRERA, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_MERRSAVE, LoongArchCPU),
+VMSTATE_UINT64(env.CSR_CTAG, LoongArchCPU),
+VMSTATE_UINT64_ARR

[PATCH v2 12/43] target/loongarch: Add floating point conversion instruction translation

2022-04-25 Thread Xiaojuan Yang
From: Song Gao 

This includes:
- FCVT.S.D, FCVT.D.S
- FFINT.{S/D}.{W/L}, FTINT.{W/L}.{S/D}
- FTINT{RM/RP/RZ/RNE}.{W/L}.{S/D}
- FRINT.{S/D}

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 target/loongarch/fpu_helper.c| 393 +++
 target/loongarch/helper.h|  29 ++
 target/loongarch/insn_trans/trans_fcnv.c.inc |  33 ++
 target/loongarch/insns.decode|  32 ++
 target/loongarch/translate.c |   1 +
 5 files changed, 488 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_fcnv.c.inc

diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c
index 2ad707007a..d69a1dd80e 100644
--- a/target/loongarch/fpu_helper.c
+++ b/target/loongarch/fpu_helper.c
@@ -461,3 +461,396 @@ uint64_t helper_fcmp_s_d(CPULoongArchState *env, uint64_t 
fj,
 FloatRelation cmp = float64_compare(fj, fk, >fp_status);
 return fcmp_common(env, cmp, flags);
 }
+
+/* floating point conversion */
+uint64_t helper_fcvt_s_d(CPULoongArchState *env, uint64_t fj)
+{
+uint64_t fd;
+
+fd = nanbox_s(float64_to_float32(fj, >fp_status));
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_fcvt_d_s(CPULoongArchState *env, uint64_t fj)
+{
+uint64_t fd;
+
+fd = float32_to_float64((uint32_t)fj, >fp_status);
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_ffint_s_w(CPULoongArchState *env, uint64_t fj)
+{
+uint64_t fd;
+
+fd = nanbox_s(int32_to_float32((int32_t)fj, >fp_status));
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_ffint_s_l(CPULoongArchState *env, uint64_t fj)
+{
+uint64_t fd;
+
+fd = nanbox_s(int64_to_float32(fj, >fp_status));
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_ffint_d_w(CPULoongArchState *env, uint64_t fj)
+{
+uint64_t fd;
+
+fd = int32_to_float64((int32_t)fj, >fp_status);
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_ffint_d_l(CPULoongArchState *env, uint64_t fj)
+{
+uint64_t fd;
+
+fd = int64_to_float64(fj, >fp_status);
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_frint_s(CPULoongArchState *env, uint64_t fj)
+{
+uint64_t fd;
+
+fd = (uint64_t)(float32_round_to_int((uint32_t)fj, >fp_status));
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_frint_d(CPULoongArchState *env, uint64_t fj)
+{
+uint64_t fd;
+
+fd = float64_round_to_int(fj, >fp_status);
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_ftintrm_l_d(CPULoongArchState *env, uint64_t fj)
+{
+uint64_t fd;
+FloatRoundMode old_mode = get_float_rounding_mode(>fp_status);
+
+set_float_rounding_mode(float_round_down, >fp_status);
+fd = float64_to_int64(fj, >fp_status);
+set_float_rounding_mode(old_mode, >fp_status);
+
+if (get_float_exception_flags(>fp_status) &
+(float_flag_invalid | float_flag_overflow)) {
+fd = FLOAT_TO_INT64_OVERFLOW;
+}
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_ftintrm_l_s(CPULoongArchState *env, uint64_t fj)
+{
+uint64_t fd;
+FloatRoundMode old_mode = get_float_rounding_mode(>fp_status);
+
+set_float_rounding_mode(float_round_down, >fp_status);
+fd = float32_to_int64((uint32_t)fj, >fp_status);
+set_float_rounding_mode(old_mode, >fp_status);
+
+if (get_float_exception_flags(>fp_status) &
+(float_flag_invalid | float_flag_overflow)) {
+fd = FLOAT_TO_INT64_OVERFLOW;
+}
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_ftintrm_w_d(CPULoongArchState *env, uint64_t fj)
+{
+uint64_t fd;
+FloatRoundMode old_mode = get_float_rounding_mode(>fp_status);
+
+set_float_rounding_mode(float_round_down, >fp_status);
+fd = (uint64_t)float64_to_int32(fj, >fp_status);
+set_float_rounding_mode(old_mode, >fp_status);
+
+if (get_float_exception_flags(>fp_status) &
+(float_flag_invalid | float_flag_overflow)) {
+fd = FLOAT_TO_INT32_OVERFLOW;
+}
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_ftintrm_w_s(CPULoongArchState *env, uint64_t fj)
+{
+uint64_t fd;
+FloatRoundMode old_mode = get_float_rounding_mode(>fp_status);
+
+set_float_rounding_mode(float_round_down, >fp_status);
+fd = (uint64_t)float32_to_int32((uint32_t)fj, >fp_status);
+set_float_rounding_mode(old_mode, >fp_status);
+
+if (get_float_exception_flags(>fp_status) &
+(float_flag_invalid | float_flag_overflow)) {
+fd = FLOAT_TO_INT32_OVERFLOW;
+}
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_ftintrp_l_d(CPULoongArchState *env, uint64_t fj)
+{
+uint64_t fd;
+FloatRoundMode old_mode = get_float_rounding_mode(>fp_stat

[PATCH v2 18/43] target/loongarch: Add system emulation introduction

2022-04-25 Thread Xiaojuan Yang
Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
---
 MAINTAINERS |  8 +
 docs/system/loongarch/loongson3.rst | 41 ++
 target/loongarch/README | 54 +
 3 files changed, 103 insertions(+)
 create mode 100644 docs/system/loongarch/loongson3.rst

diff --git a/MAINTAINERS b/MAINTAINERS
index 5b5377d353..6361c24b3a 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1123,6 +1123,14 @@ F: hw/net/*i82596*
 F: include/hw/net/lasi_82596.h
 F: pc-bios/hppa-firmware.img
 
+LoongArch Machines
+--
+Virt
+M: Xiaojuan Yang 
+M: Song Gao 
+S: Maintained
+F: docs/system/loongarch/loongson3.rst
+
 M68K Machines
 -
 an5206
diff --git a/docs/system/loongarch/loongson3.rst 
b/docs/system/loongarch/loongson3.rst
new file mode 100644
index 00..fa3acd01c0
--- /dev/null
+++ b/docs/system/loongarch/loongson3.rst
@@ -0,0 +1,41 @@
+:orphan:
+
+==
+loongson3 virt generic platform (``virt``)
+==
+
+The ``virt`` machine use gpex host bridge, and there are some
+emulated devices on virt board, such as loongson7a RTC device,
+IOAPIC device, ACPI device and so on.
+
+Supported devices
+-
+
+The ``virt`` machine supports:
+- Gpex host bridge
+- Ls7a RTC device
+- Ls7a IOAPIC device
+- Ls7a ACPI device
+- Fw_cfg device
+- PCI/PCIe devices
+- Memory device
+- CPU device. Type: Loongson-3A5000.
+
+CPU and machine Type
+
+
+The ``qemu-system-loongarch64`` provides emulation for virt
+machine. You can specify the machine type ``virt`` and
+cpu type ``Loongson-3A5000``.
+
+Boot options
+
+
+Now the ``virt`` machine can run test program in ELF format and the
+method of compiling is in target/loongarch/README.
+
+.. code-block:: bash
+
+  $ qemu-system-loongarch64 -machine virt -m 4G -cpu Loongson-3A5000 \
+  -smp 1 -kernel hello -monitor none -display none \
+  -chardev file,path=hello.out,id=output -serial chardev:output
diff --git a/target/loongarch/README b/target/loongarch/README
index de141c1a58..4dcd0f1682 100644
--- a/target/loongarch/README
+++ b/target/loongarch/README
@@ -8,3 +8,57 @@
 
   We can get the latest loongarch documents at 
https://github.com/loongson/LoongArch-Documentation/tags.
 
+
+- System emulation
+
+  Mainly emulate a virt 3A5000 board and ls7a bridge that is not exactly the 
same as the host.
+  3A5000 support multiple interrupt cascading while here we just emulate the 
extioi interrupt
+  cascading. LS7A1000 host bridge support multiple devices, such as sata, 
gmac, uart, rtc
+  and so on. But we just realize the rtc. Others use the qemu common devices. 
It does not affect
+  the general use. We also introduced the emulation of devices at 
docs/system/loongarch/loongson3.rst.
+
+  This version only supports running binary files in ELF format, and does not 
depend on BIOS and kernel file.
+  You can compile the test program with 'make & make check-tcg' and run the 
test case with the following command:
+
+  1. Install LoongArch cross-tools on X86 machines.
+
+Download cross-tools.
+
+  wget 
https://github.com/loongson/build-tools/releases/latest/download/loongarch64-clfs-20211202-cross-tools.tar.xz
+
+  tar -vxf loongarch64-clfs-20211202-cross-tools.tar.xz -C /opt
+
+Config cross-tools env.
+
+  . setenv.sh
+
+  setenv.sh:
+
+  #!/bin/sh
+  set -x
+  CC_PREFIX=/opt/cross-tools
+
+  export PATH=$CC_PREFIX/bin:$PATH
+  export LD_LIBRARY_PATH=$CC_PREFIX/lib:$LD_LIBRARY_PATH
+  export 
LD_LIBRARY_PATH=$CC_PREFIX/loongarch64-unknown-linux-gnu/lib/:$LD_LIBRARY_PATH
+  set +x
+
+  2. Test tests/tcg/multiarch.
+
+./configure --disable-rdma --disable-pvrdma --prefix=/usr  \
+--target-list="loongarch64-softmmu"  \
+--disable-libiscsi --disable-libnfs --disable-libpmem \
+--disable-glusterfs --enable-libusb --enable-usb-redir \
+--disable-opengl --disable-xen --enable-spice --disable-werror \
+--enable-debug --disable-capstone --disable-kvm --enable-profiler
+
+cd  build/
+
+make && make check-tcg
+
+or
+
+./build/qemu-system-loongarch64 -machine virt -m 4G -cpu Loongson-3A5000 
-smp 1 -kernel build/tests/tcg/loongarch64-softmmu/hello -monitor none -display 
none -chardev file,path=hello.out,id=output -serial chardev:output
+
+- Note.
+  We can get the latest LoongArch documents or LoongArch tools at 
https://github.com/loongson/
-- 
2.31.1




[PATCH v2 42/43] tests/tcg/loongarch64: Add hello/memory test in loongarch64 system

2022-04-25 Thread Xiaojuan Yang
- We write a very minimal softmmu harness.
- This is a very simple smoke test with no need to run a full Linux/kernel.
- The Makefile.softmmu-target record the rule to run.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
---
 MAINTAINERS   |  1 +
 tests/tcg/loongarch64/Makefile.softmmu-target | 33 +++
 tests/tcg/loongarch64/system/boot.S   | 56 
 tests/tcg/loongarch64/system/kernel.ld| 30 +++
 tests/tcg/loongarch64/system/regdef.h | 86 +++
 5 files changed, 206 insertions(+)
 create mode 100644 tests/tcg/loongarch64/Makefile.softmmu-target
 create mode 100644 tests/tcg/loongarch64/system/boot.S
 create mode 100644 tests/tcg/loongarch64/system/kernel.ld
 create mode 100644 tests/tcg/loongarch64/system/regdef.h

diff --git a/MAINTAINERS b/MAINTAINERS
index e123f3026c..31a8c26e71 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -218,6 +218,7 @@ M: Song Gao 
 M: Xiaojuan Yang 
 S: Maintained
 F: target/loongarch/
+F: tests/tcg/loongarch64/
 
 M68K TCG CPUs
 M: Laurent Vivier 
diff --git a/tests/tcg/loongarch64/Makefile.softmmu-target 
b/tests/tcg/loongarch64/Makefile.softmmu-target
new file mode 100644
index 00..908f3a8c0f
--- /dev/null
+++ b/tests/tcg/loongarch64/Makefile.softmmu-target
@@ -0,0 +1,33 @@
+#
+# Loongarch64 system tests
+#
+
+LOONGARCH64_SYSTEM_SRC=$(SRC_PATH)/tests/tcg/loongarch64/system
+VPATH+=$(LOONGARCH64_SYSTEM_SRC)
+
+# These objects provide the basic boot code and helper functions for all tests
+CRT_OBJS=boot.o
+
+LOONGARCH64_TEST_SRCS=$(wildcard $(LOONGARCH64_SYSTEM_SRC)/*.c)
+LOONGARCH64_TESTS = $(patsubst $(LOONGARCH64_SYSTEM_SRC)/%.c, %, 
$(LOONGARCH64_TEST_SRCS))
+
+CRT_PATH=$(LOONGARCH64_SYSTEM_SRC)
+LINK_SCRIPT=$(LOONGARCH64_SYSTEM_SRC)/kernel.ld
+LDFLAGS=-Wl,-T$(LINK_SCRIPT)
+TESTS+=$(LOONGARCH64_TESTS) $(MULTIARCH_TESTS)
+CFLAGS+=-nostdlib -g -O1 -march=loongarch64 -mabi=lp64d $(MINILIB_INC)
+LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc
+
+# building head blobs
+.PRECIOUS: $(CRT_OBJS)
+
+%.o: $(CRT_PATH)/%.S
+   $(CC) $(CFLAGS) $(EXTRA_CFLAGS) -x assembler-with-cpp -c $< -o $@
+
+# Build and link the tests
+%: %.c $(LINK_SCRIPT) $(CRT_OBJS) $(MINILIB_OBJS)
+   $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS)
+
+memory: CFLAGS+=-DCHECK_UNALIGNED=0
+# Running
+QEMU_OPTS+=-serial chardev:output -kernel
diff --git a/tests/tcg/loongarch64/system/boot.S 
b/tests/tcg/loongarch64/system/boot.S
new file mode 100644
index 00..aec116a327
--- /dev/null
+++ b/tests/tcg/loongarch64/system/boot.S
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Minimal LoongArch system boot code.
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "regdef.h"
+
+   .global _start
+   .align 16
+_start:
+   la.local t0, stack_end
+   move sp, t0
+   bl main
+
+   .type _start 2
+   .size _start, .-_start
+
+   .global _exit
+   .align 16
+_exit:
+2:  /* QEMU ACPI poweroff */
+   li.w  t0, 0x3c00
+   li.w  t1, 0x100d0014
+   st.w  t0, t1, 0
+   idle  0
+   bl2b
+
+   .type _exit 2
+   .size _exit, .-_exit
+
+   .global __sys_outc
+__sys_outc:
+   li.d t1, 100
+loop:
+   lu12i.w t2, 0x1fe00
+   ori t0, t2, 0x1e5
+   ld.bu   t0, t0, 0
+   andit0, t0, 0x20
+   ext.w.b t0, t0
+   bnezt0, in
+   addi.w  t1, t1, -1
+   bnezt1, loop
+in:
+   ext.w.b a0, a0
+   lu12i.w t0, 0x1fe00
+   ori t0, t0, 0x1e0
+   st.ba0, t0, 0
+   jirl$r0, ra, 0
+
+   .data
+   .align 4
+stack:
+   .space  65536
+stack_end:
diff --git a/tests/tcg/loongarch64/system/kernel.ld 
b/tests/tcg/loongarch64/system/kernel.ld
new file mode 100644
index 00..f1a7c0168c
--- /dev/null
+++ b/tests/tcg/loongarch64/system/kernel.ld
@@ -0,0 +1,30 @@
+ENTRY(_start)
+
+SECTIONS
+{
+/* Linux kernel legacy start address.  */
+. = 0x9020;
+_text = .;
+.text : {
+*(.text)
+}
+.rodata : {
+*(.rodata)
+}
+_etext = .;
+
+. = ALIGN(8192);
+_data = .;
+.got : {
+*(.got)
+}
+.data : {
+   *(.sdata)
+*(.data)
+}
+_edata = .;
+.bss : {
+*(.bss)
+}
+_end = .;
+}
diff --git a/tests/tcg/loongarch64/system/regdef.h 
b/tests/tcg/loongarch64/system/regdef.h
new file mode 100644
index 00..faa09b2377
--- /dev/null
+++ b/tests/tcg/loongarch64/system/regdef.h
@@ -0,0 +1,86 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+#ifndef _ASM_REGDEF_H
+#define _ASM_REGDEF_H
+
+#define zero$r0 /* wired zero */
+#define ra  $r1 /* return address */
+#define tp  $r2
+#define sp  $r3 /* stack pointer */
+#define v0  $r4 /* return valu

[PATCH v2 29/43] target/loongarch: Add timer related instructions support.

2022-04-25 Thread Xiaojuan Yang
This includes:
-RDTIME{L/H}.W
-RDTIME.D

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 target/loongarch/disas.c  |  3 ++
 target/loongarch/helper.h |  2 ++
 target/loongarch/insn_trans/trans_extra.c.inc | 33 +++
 target/loongarch/insns.decode |  3 ++
 target/loongarch/op_helper.c  | 13 
 target/loongarch/translate.c  |  2 ++
 6 files changed, 56 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index ce71105ee3..5f43b2aabf 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -346,6 +346,9 @@ INSN(bitrev_w, rr)
 INSN(bitrev_d, rr)
 INSN(ext_w_h,  rr)
 INSN(ext_w_b,  rr)
+INSN(rdtimel_w,rr)
+INSN(rdtimeh_w,rr)
+INSN(rdtime_d, rr)
 INSN(cpucfg,   rr)
 INSN(asrtle_d, rr_jk)
 INSN(asrtgt_d, rr_jk)
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 626fc32e1e..85c11a60d4 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -93,6 +93,8 @@ DEF_HELPER_2(frint_d, i64, env, i64)
 
 DEF_HELPER_FLAGS_2(set_rounding_mode, TCG_CALL_NO_RWG, void, env, i32)
 
+DEF_HELPER_1(rdtime_d, i64, env)
+
 /* CSRs helper */
 DEF_HELPER_1(csrrd_pgd, i64, env)
 DEF_HELPER_1(csrrd_tval, i64, env)
diff --git a/target/loongarch/insn_trans/trans_extra.c.inc 
b/target/loongarch/insn_trans/trans_extra.c.inc
index 549f75a867..ad713cd61e 100644
--- a/target/loongarch/insn_trans/trans_extra.c.inc
+++ b/target/loongarch/insn_trans/trans_extra.c.inc
@@ -33,6 +33,39 @@ static bool trans_asrtgt_d(DisasContext *ctx, arg_asrtgt_d * 
a)
 return true;
 }
 
+static bool gen_rdtime(DisasContext *ctx, arg_rr *a,
+   bool word, bool high)
+{
+TCGv dst1 = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv dst2 = gpr_dst(ctx, a->rj, EXT_NONE);
+
+if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
+gen_io_start();
+}
+gen_helper_rdtime_d(dst1, cpu_env);
+if (word) {
+tcg_gen_sextract_tl(dst1, dst1, high ? 32 : 0, 32);
+}
+tcg_gen_ld_i64(dst2, cpu_env, offsetof(CPULoongArchState, CSR_TID));
+
+return true;
+}
+
+static bool trans_rdtimel_w(DisasContext *ctx, arg_rdtimel_w *a)
+{
+return gen_rdtime(ctx, a, 1, 0);
+}
+
+static bool trans_rdtimeh_w(DisasContext *ctx, arg_rdtimeh_w *a)
+{
+return gen_rdtime(ctx, a, 1, 1);
+}
+
+static bool trans_rdtime_d(DisasContext *ctx, arg_rdtime_d *a)
+{
+return gen_rdtime(ctx, a, 0, 0);
+}
+
 static bool trans_cpucfg(DisasContext *ctx, arg_cpucfg *a)
 {
 TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index ebd3d505fb..3fdc6e148c 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -309,6 +309,9 @@ break    0010 10100 ...  
@i15
 syscall  0010 10110 ...  @i15
 asrtle_d  00010 . . 0@rr_jk
 asrtgt_d  00011 . . 0@rr_jk
+rdtimel_w     0 11000 . .@rr
+rdtimeh_w     0 11001 . .@rr
+rdtime_d  0 11010 . .@rr
 cpucfg    0 11011 . .@rr
 
 #
diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c
index 2243fcfa44..626e0b56ac 100644
--- a/target/loongarch/op_helper.c
+++ b/target/loongarch/op_helper.c
@@ -84,6 +84,19 @@ target_ulong helper_cpucfg(CPULoongArchState *env, 
target_ulong rj)
 return rj > 21 ? 0 : env->cpucfg[rj];
 }
 
+uint64_t helper_rdtime_d(CPULoongArchState *env)
+{
+uint64_t plv;
+LoongArchCPU *cpu = LOONGARCH_CPU(env_cpu(env));
+
+plv = FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV);
+if (extract64(env->CSR_MISC, R_CSR_MISC_DRDTL_SHIFT + plv, 1)) {
+do_raise_exception(env, EXCCODE_IPE, GETPC());
+}
+
+return cpu_loongarch_get_constant_timer_counter(cpu);
+}
+
 void helper_ertn(CPULoongArchState *env)
 {
 uint64_t csr_pplv, csr_pie;
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
index 82694f487f..c1f72ee153 100644
--- a/target/loongarch/translate.c
+++ b/target/loongarch/translate.c
@@ -25,6 +25,8 @@ static TCGv cpu_lladdr, cpu_llval;
 TCGv_i32 cpu_fcsr0;
 TCGv_i64 cpu_fpr[32];
 
+#include "exec/gen-icount.h"
+
 #define DISAS_STOPDISAS_TARGET_0
 #define DISAS_EXITDISAS_TARGET_1
 #define DISAS_EXIT_UPDATE DISAS_TARGET_2
-- 
2.31.1




[PATCH v2 36/43] Enable common virtio pci support for LoongArch

2022-04-25 Thread Xiaojuan Yang
Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
---
 softmmu/qdev-monitor.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c
index 12fe60c467..bb5897fc76 100644
--- a/softmmu/qdev-monitor.c
+++ b/softmmu/qdev-monitor.c
@@ -60,7 +60,8 @@ typedef struct QDevAlias
   QEMU_ARCH_HPPA | QEMU_ARCH_I386 | \
   QEMU_ARCH_MIPS | QEMU_ARCH_PPC |  \
   QEMU_ARCH_RISCV | QEMU_ARCH_SH4 | \
-  QEMU_ARCH_SPARC | QEMU_ARCH_XTENSA)
+  QEMU_ARCH_SPARC | QEMU_ARCH_XTENSA | \
+  QEMU_ARCH_LOONGARCH)
 #define QEMU_ARCH_VIRTIO_CCW (QEMU_ARCH_S390X)
 #define QEMU_ARCH_VIRTIO_MMIO (QEMU_ARCH_M68K)
 
-- 
2.31.1




[PATCH v2 02/43] target/loongarch: Add core definition

2022-04-25 Thread Xiaojuan Yang
From: Song Gao 

This patch adds target state header, target definitions
and initialization routines.

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
Reviewed-by: Philippe Mathieu-Daudé 
---
 target/loongarch/cpu-param.h |  18 ++
 target/loongarch/cpu.c   | 324 +++
 target/loongarch/cpu.h   | 243 ++
 target/loongarch/internals.h |  21 +++
 4 files changed, 606 insertions(+)
 create mode 100644 target/loongarch/cpu-param.h
 create mode 100644 target/loongarch/cpu.c
 create mode 100644 target/loongarch/cpu.h
 create mode 100644 target/loongarch/internals.h

diff --git a/target/loongarch/cpu-param.h b/target/loongarch/cpu-param.h
new file mode 100644
index 00..9a769b67e0
--- /dev/null
+++ b/target/loongarch/cpu-param.h
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch CPU parameters for QEMU.
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef LOONGARCH_CPU_PARAM_H
+#define LOONGARCH_CPU_PARAM_H
+
+#define TARGET_LONG_BITS 64
+#define TARGET_PHYS_ADDR_SPACE_BITS 48
+#define TARGET_VIRT_ADDR_SPACE_BITS 48
+
+#define TARGET_PAGE_BITS 14
+#define NB_MMU_MODES 4
+
+#endif
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
new file mode 100644
index 00..2d5b28b822
--- /dev/null
+++ b/target/loongarch/cpu.c
@@ -0,0 +1,324 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch CPU
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/qemu-print.h"
+#include "qapi/error.h"
+#include "qemu/module.h"
+#include "sysemu/qtest.h"
+#include "exec/exec-all.h"
+#include "qapi/qapi-commands-machine-target.h"
+#include "cpu.h"
+#include "internals.h"
+#include "fpu/softfloat-helpers.h"
+
+const char * const regnames[32] = {
+"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
+"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
+"r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
+"r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
+};
+
+const char * const fregnames[32] = {
+"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
+"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
+"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
+"f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
+};
+
+static const char * const excp_names[] = {
+[EXCCODE_INT] = "Interrupt",
+[EXCCODE_PIL] = "Page invalid exception for load",
+[EXCCODE_PIS] = "Page invalid exception for store",
+[EXCCODE_PIF] = "Page invalid exception for fetch",
+[EXCCODE_PME] = "Page modified exception",
+[EXCCODE_PNR] = "Page Not Readable exception",
+[EXCCODE_PNX] = "Page Not Executable exception",
+[EXCCODE_PPI] = "Page Privilege error",
+[EXCCODE_ADEF] = "Address error for instruction fetch",
+[EXCCODE_ADEM] = "Address error for Memory access",
+[EXCCODE_SYS] = "Syscall",
+[EXCCODE_BRK] = "Break",
+[EXCCODE_INE] = "Instruction Non-Existent",
+[EXCCODE_IPE] = "Instruction privilege error",
+[EXCCODE_FPE] = "Floating Point Exception",
+[EXCCODE_DBP] = "Debug breakpoint",
+};
+
+const char *loongarch_exception_name(int32_t exception)
+{
+assert(excp_names[exception]);
+return excp_names[exception];
+}
+
+void G_NORETURN do_raise_exception(CPULoongArchState *env,
+   uint32_t exception,
+   uintptr_t pc)
+{
+CPUState *cs = env_cpu(env);
+
+qemu_log_mask(CPU_LOG_INT, "%s: %d (%s)\n",
+  __func__,
+  exception,
+  loongarch_exception_name(exception));
+cs->exception_index = exception;
+
+cpu_loop_exit_restore(cs, pc);
+}
+
+static void loongarch_cpu_set_pc(CPUState *cs, vaddr value)
+{
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+CPULoongArchState *env = >env;
+
+env->pc = value;
+}
+
+#ifdef CONFIG_TCG
+static void loong

[PATCH v2 03/43] target/loongarch: Add main translation routines

2022-04-25 Thread Xiaojuan Yang
From: Song Gao 

This patch adds main translation routines and
basic functions for translation.

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 target/loongarch/helper.h|   6 ++
 target/loongarch/op_helper.c |  21 +
 target/loongarch/translate.c | 160 +++
 target/loongarch/translate.h |  26 ++
 4 files changed, 213 insertions(+)
 create mode 100644 target/loongarch/helper.h
 create mode 100644 target/loongarch/op_helper.c
 create mode 100644 target/loongarch/translate.c
 create mode 100644 target/loongarch/translate.h

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
new file mode 100644
index 00..eb771c0628
--- /dev/null
+++ b/target/loongarch/helper.h
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+DEF_HELPER_2(raise_exception, noreturn, env, i32)
diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c
new file mode 100644
index 00..903810951e
--- /dev/null
+++ b/target/loongarch/op_helper.c
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch emulation helpers for QEMU.
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/main-loop.h"
+#include "cpu.h"
+#include "qemu/host-utils.h"
+#include "exec/helper-proto.h"
+#include "exec/exec-all.h"
+#include "exec/cpu_ldst.h"
+#include "internals.h"
+
+/* Exceptions helpers */
+void helper_raise_exception(CPULoongArchState *env, uint32_t exception)
+{
+do_raise_exception(env, exception, GETPC());
+}
diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
new file mode 100644
index 00..8a62623cd1
--- /dev/null
+++ b/target/loongarch/translate.c
@@ -0,0 +1,160 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch emulation for QEMU - main translation routines.
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "tcg/tcg-op.h"
+#include "exec/translator.h"
+#include "exec/helper-proto.h"
+#include "exec/helper-gen.h"
+
+#include "exec/translator.h"
+#include "exec/log.h"
+#include "qemu/qemu-print.h"
+#include "translate.h"
+#include "internals.h"
+
+/* Global register indices */
+TCGv cpu_gpr[32], cpu_pc;
+static TCGv cpu_lladdr, cpu_llval;
+TCGv_i32 cpu_fcsr0;
+TCGv_i64 cpu_fpr[32];
+
+#define DISAS_STOP   DISAS_TARGET_0
+
+void generate_exception(DisasContext *ctx, int excp)
+{
+tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
+gen_helper_raise_exception(cpu_env, tcg_constant_i32(excp));
+ctx->base.is_jmp = DISAS_NORETURN;
+}
+
+static inline void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
+{
+if (translator_use_goto_tb(>base, dest)) {
+tcg_gen_goto_tb(n);
+tcg_gen_movi_tl(cpu_pc, dest);
+tcg_gen_exit_tb(ctx->base.tb, n);
+} else {
+tcg_gen_movi_tl(cpu_pc, dest);
+tcg_gen_lookup_and_goto_ptr();
+}
+}
+
+static void loongarch_tr_init_disas_context(DisasContextBase *dcbase,
+CPUState *cs)
+{
+int64_t bound;
+DisasContext *ctx = container_of(dcbase, DisasContext, base);
+
+ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
+ctx->mem_idx = ctx->base.tb->flags;
+
+/* Bound the number of insns to execute to those left on the page.  */
+bound = -(ctx->base.pc_first | TARGET_PAGE_MASK) / 4;
+ctx->base.max_insns = MIN(ctx->base.max_insns, bound);
+}
+
+static void loongarch_tr_tb_start(DisasContextBase *dcbase, CPUState *cs)
+{
+}
+
+static void loongarch_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
+{
+DisasContext *ctx = container_of(dcbase, DisasContext, base);
+
+tcg_gen_insn_start(ctx->base.pc_next);
+}
+
+static void loongarch_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
+{
+CPULoongArchState *env = cs->env_ptr;
+DisasContext *ctx = container_of(dcbase, DisasContext, base);
+
+ctx->opcode = cpu_ldl_code(env, ctx->base.pc_next);
+
+if (!decode(ctx, ctx->opcode)) {
+qemu_log_mask(LOG_UNIMP, "Error: unknown opcode. 0x%lx: 0x%x\n",
+  ctx->base.pc_next, ctx->opcode);
+generate_exception(ctx, EXCCODE_INE);
+}
+
+ctx->base.pc_next += 4;
+}
+
+static void loongarch_tr_tb_stop(DisasContextBase *dcbase, CPUState *cs)
+{
+DisasContext *ctx = container_of(dcbase, DisasContext, base);
+
+switch (ctx->base.is_jmp) {
+case DISAS_STOP:
+tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
+tcg_gen_lookup_and_goto_ptr

[PATCH v2 10/43] target/loongarch: Add floating point arithmetic instruction translation

2022-04-25 Thread Xiaojuan Yang
From: Song Gao 

This includes:
- F{ADD/SUB/MUL/DIV}.{S/D}
- F{MADD/MSUB/NMADD/NMSUB}.{S/D}
- F{MAX/MIN}.{S/D}
- F{MAXA/MINA}.{S/D}
- F{ABS/NEG}.{S/D}
- F{SQRT/RECIP/RSQRT}.{S/D}
- F{SCALEB/LOGB/COPYSIGN}.{S/D}
- FCLASS.{S/D}

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 target/loongarch/cpu.c|   1 +
 target/loongarch/fpu_helper.c | 403 ++
 target/loongarch/helper.h |  37 ++
 .../loongarch/insn_trans/trans_farith.c.inc   | 105 +
 target/loongarch/insns.decode |  52 +++
 target/loongarch/internals.h  |   2 +
 target/loongarch/translate.c  |  11 +
 7 files changed, 611 insertions(+)
 create mode 100644 target/loongarch/fpu_helper.c
 create mode 100644 target/loongarch/insn_trans/trans_farith.c.inc

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 2d5b28b822..d2fc26cff9 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -196,6 +196,7 @@ static void loongarch_cpu_reset(DeviceState *dev)
 env->fcsr0_mask = FCSR0_M1 | FCSR0_M2 | FCSR0_M3;
 env->fcsr0 = 0x0;
 
+restore_fp_status(env);
 cs->exception_index = -1;
 }
 
diff --git a/target/loongarch/fpu_helper.c b/target/loongarch/fpu_helper.c
new file mode 100644
index 00..e875638e1d
--- /dev/null
+++ b/target/loongarch/fpu_helper.c
@@ -0,0 +1,403 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch float point emulation helpers for QEMU
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "exec/helper-proto.h"
+#include "exec/exec-all.h"
+#include "exec/cpu_ldst.h"
+#include "fpu/softfloat.h"
+#include "internals.h"
+
+#define FLOAT_TO_INT32_OVERFLOW 0x7fff
+#define FLOAT_TO_INT64_OVERFLOW 0x7fffULL
+
+static inline uint64_t nanbox_s(float32 fp)
+{
+return fp | MAKE_64BIT_MASK(32, 32);
+}
+
+/* Convert loongarch rounding mode in fcsr0 to IEEE library */
+static const FloatRoundMode ieee_rm[4] = {
+float_round_nearest_even,
+float_round_to_zero,
+float_round_up,
+float_round_down
+};
+
+void restore_fp_status(CPULoongArchState *env)
+{
+set_float_rounding_mode(ieee_rm[(env->fcsr0 >> FCSR0_RM) & 0x3],
+>fp_status);
+set_flush_to_zero(0, >fp_status);
+}
+
+static int ieee_ex_to_loongarch(int xcpt)
+{
+int ret = 0;
+if (xcpt & float_flag_invalid) {
+ret |= FP_INVALID;
+}
+if (xcpt & float_flag_overflow) {
+ret |= FP_OVERFLOW;
+}
+if (xcpt & float_flag_underflow) {
+ret |= FP_UNDERFLOW;
+}
+if (xcpt & float_flag_divbyzero) {
+ret |= FP_DIV0;
+}
+if (xcpt & float_flag_inexact) {
+ret |= FP_INEXACT;
+}
+return ret;
+}
+
+static void update_fcsr0_mask(CPULoongArchState *env, uintptr_t pc, int mask)
+{
+int flags = get_float_exception_flags(>fp_status);
+
+set_float_exception_flags(0, >fp_status);
+
+flags &= ~mask;
+
+if (!flags) {
+SET_FP_CAUSE(env->fcsr0, flags);
+return;
+} else {
+flags = ieee_ex_to_loongarch(flags);
+SET_FP_CAUSE(env->fcsr0, flags);
+}
+
+if (GET_FP_ENABLES(env->fcsr0) & flags) {
+do_raise_exception(env, EXCCODE_FPE, pc);
+} else {
+UPDATE_FP_FLAGS(env->fcsr0, flags);
+}
+}
+
+static void update_fcsr0(CPULoongArchState *env, uintptr_t pc)
+{
+update_fcsr0_mask(env, pc, 0);
+}
+
+uint64_t helper_fadd_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+uint64_t fd;
+
+fd = nanbox_s(float32_add((uint32_t)fj, (uint32_t)fk, >fp_status));
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_fadd_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+uint64_t fd;
+
+fd = float64_add(fj, fk, >fp_status);
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_fsub_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+uint64_t fd;
+
+fd = nanbox_s(float32_sub((uint32_t)fj, (uint32_t)fk, >fp_status));
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_fsub_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+uint64_t fd;
+
+fd = float64_sub(fj, fk, >fp_status);
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_fmul_s(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+uint64_t fd;
+
+fd = nanbox_s(float32_mul((uint32_t)fj, (uint32_t)fk, >fp_status));
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uint64_t helper_fmul_d(CPULoongArchState *env, uint64_t fj, uint64_t fk)
+{
+uint64_t fd;
+
+fd = float64_mul(fj, fk, >fp_status);
+update_fcsr0(env, GETPC());
+return fd;
+}
+
+uin

[PATCH v2 00/43] Add LoongArch softmmu support

2022-04-25 Thread Xiaojuan Yang
Hi All,

As this series only supports running binary files in ELF format, and does not 
depend on
BIOS and kernel file. so this series are changed from RFC to patch v1. 


The manual:
  - https://github.com/loongson/LoongArch-Documentation/releases/tag/2022.03.17

Old series:
  - https://patchew.org/QEMU/20220328125749.2918087-1-yangxiaoj...@loongson.cn/
  - https://patchew.org/QEMU/20220106094200.1801206-1-gaos...@loongson.cn/

Thanks.
Xiaojuan

-

v2:
  - Improvents to CSR/IOCSR instructions translation.
  - Fixed extioi device emulation. It is represented by only one memory region.
  - Fixed IPI device emulation. The registers are represented with uint64_t.
  - Use do_cpu_reset() and cpu_set_pc() to specify the load address. 


v1: https://patchew.org/QEMU/20220415094058.3584233-1-yangxiaoj...@loongson.cn/


Song Gao (18):
  target/loongarch: Add README
  target/loongarch: Add core definition
  target/loongarch: Add main translation routines
  target/loongarch: Add fixed point arithmetic instruction translation
  target/loongarch: Add fixed point shift instruction translation
  target/loongarch: Add fixed point bit instruction translation
  target/loongarch: Add fixed point load/store instruction translation
  target/loongarch: Add fixed point atomic instruction translation
  target/loongarch: Add fixed point extra instruction translation
  target/loongarch: Add floating point arithmetic instruction
translation
  target/loongarch: Add floating point comparison instruction
translation
  target/loongarch: Add floating point conversion instruction
translation
  target/loongarch: Add floating point move instruction translation
  target/loongarch: Add floating point load/store instruction
translation
  target/loongarch: Add branch instruction translation
  target/loongarch: Add disassembler
  target/loongarch: Add target build suport
  target/loongarch: 'make check-tcg' support

Xiaojuan Yang (25):
  target/loongarch: Add system emulation introduction
  target/loongarch: Add CSRs definition
  target/loongarch: Add basic vmstate description of CPU.
  target/loongarch: Implement qmp_query_cpu_definitions()
  target/loongarch: Add MMU support for LoongArch CPU.
  target/loongarch: Add LoongArch interrupt and exception handle
  target/loongarch: Add constant timer support
  target/loongarch: Add LoongArch CSR instruction
  target/loongarch: Add LoongArch IOCSR instruction
  target/loongarch: Add TLB instruction support
  target/loongarch: Add other core instructions support
  target/loongarch: Add timer related instructions support.
  hw/loongarch: Add support loongson3 virt machine type.
  hw/loongarch: Add LoongArch ipi interrupt support(IPI)
  hw/intc: Add LoongArch ls7a interrupt controller support(PCH-PIC)
  hw/intc: Add LoongArch ls7a msi interrupt controller support(PCH-MSI)
  hw/intc: Add LoongArch extioi interrupt controller(EIOINTC)
  hw/loongarch: Add irq hierarchy for the system
  Enable common virtio pci support for LoongArch
  hw/loongarch: Add some devices support for 3A5000.
  hw/loongarch: Add LoongArch ls7a rtc device support
  hw/loongarch: Add LoongArch load elf function.
  hw/loongarch: Add LoongArch ls7a acpi device support
  target/loongarch: Add gdb support.
  tests/tcg/loongarch64: Add hello/memory test in loongarch64 system

 MAINTAINERS   |  26 +
 .../devices/loongarch64-softmmu/default.mak   |   3 +
 configs/targets/loongarch64-softmmu.mak   |   4 +
 docs/system/loongarch/loongson3.rst   |  41 +
 gdb-xml/loongarch-base64.xml  |  44 +
 gdb-xml/loongarch-fpu64.xml   |  57 ++
 hw/Kconfig|   1 +
 hw/acpi/Kconfig   |   4 +
 hw/acpi/ls7a.c| 374 
 hw/acpi/meson.build   |   1 +
 hw/intc/Kconfig   |  15 +
 hw/intc/loongarch_extioi.c| 483 ++
 hw/intc/loongarch_ipi.c   | 166 
 hw/intc/loongarch_pch_msi.c   |  75 ++
 hw/intc/loongarch_pch_pic.c   | 434 +
 hw/intc/meson.build   |   4 +
 hw/intc/trace-events  |  25 +
 hw/loongarch/Kconfig  |  18 +
 hw/loongarch/loongson3.c  | 349 +++
 hw/loongarch/meson.build  |   4 +
 hw/meson.build|   1 +
 hw/rtc/Kconfig|   3 +
 hw/rtc/ls7a_rtc.c | 322 +++
 hw/rtc/meson.build|   1 +
 include/disas/dis-asm.h   |   2 +
 include/exec/poison.h |   2 +
 include/hw/acpi/ls7a.h|  53 ++
 include/hw/intc/loongarch_extioi.h|  60 ++
 include/hw/intc/loongarch_ipi.h   |  50 +
 include/hw/intc

[PATCH v2 39/43] hw/loongarch: Add LoongArch load elf function.

2022-04-25 Thread Xiaojuan Yang
Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 hw/loongarch/loongson3.c| 54 +++--
 include/hw/loongarch/virt.h |  9 +++
 target/loongarch/cpu.c  |  4 +++
 target/loongarch/cpu.h  |  2 ++
 4 files changed, 67 insertions(+), 2 deletions(-)

diff --git a/hw/loongarch/loongson3.c b/hw/loongarch/loongson3.c
index 2b87b193c7..67c130de63 100644
--- a/hw/loongarch/loongson3.c
+++ b/hw/loongarch/loongson3.c
@@ -19,6 +19,8 @@
 #include "exec/address-spaces.h"
 #include "hw/irq.h"
 #include "net/net.h"
+#include "hw/loader.h"
+#include "elf.h"
 #include "hw/intc/loongarch_ipi.h"
 #include "hw/intc/loongarch_extioi.h"
 #include "hw/intc/loongarch_pch_pic.h"
@@ -29,6 +31,36 @@
 
 #include "target/loongarch/cpu.h"
 
+static struct _loaderparams {
+unsigned long ram_size;
+const char *kernel_filename;
+} loaderparams;
+
+static uint64_t cpu_loongarch_virt_to_phys(void *opaque, uint64_t addr)
+{
+return addr & 0x1fffll;
+}
+
+static int64_t load_kernel_info(void)
+{
+int64_t kernel_entry, kernel_low, kernel_high;
+long kernel_size;
+
+kernel_size = load_elf(loaderparams.kernel_filename, NULL,
+   cpu_loongarch_virt_to_phys, NULL,
+   (uint64_t *)_entry, (uint64_t *)_low,
+   (uint64_t *)_high, NULL, 0,
+   EM_LOONGARCH, 1, 0);
+
+if (kernel_size < 0) {
+error_report("could not load kernel '%s': %s",
+ loaderparams.kernel_filename,
+ load_elf_strerror(kernel_size));
+exit(1);
+}
+return kernel_entry;
+}
+
 static void loongarch_devices_init(DeviceState *pch_pic)
 {
 DeviceState *gpex_dev;
@@ -216,12 +248,15 @@ static void loongarch_irq_init(LoongArchMachineState 
*lams)
 static void loongarch_init(MachineState *machine)
 {
 const char *cpu_model = machine->cpu_type;
+const char *kernel_filename = machine->kernel_filename;
 ram_addr_t offset = 0;
 ram_addr_t ram_size = machine->ram_size;
 uint64_t highram_size = 0;
 MemoryRegion *address_space_mem = get_system_memory();
 LoongArchMachineState *lams = LOONGARCH_MACHINE(machine);
+LoongArchCPU *lacpu;
 int i;
+int64_t kernel_addr = 0;
 
 if (!cpu_model) {
 cpu_model = LOONGARCH_CPU_TYPE_NAME("Loongson-3A5000");
@@ -237,22 +272,37 @@ static void loongarch_init(MachineState *machine)
 cpu_create(machine->cpu_type);
 }
 
+if (ram_size < 1 * GiB) {
+error_report("ram_size must be greater than 1G.");
+exit(1);
+}
+
 /* Add memory region */
 memory_region_init_alias(>lowmem, NULL, "loongarch.lowram",
  machine->ram, 0, 256 * MiB);
 memory_region_add_subregion(address_space_mem, offset, >lowmem);
 offset += 256 * MiB;
-
 highram_size = ram_size - 256 * MiB;
 memory_region_init_alias(>highmem, NULL, "loongarch.highmem",
  machine->ram, offset, highram_size);
 memory_region_add_subregion(address_space_mem, 0x9000, >highmem);
-
 /* Add isa io region */
 memory_region_init_alias(>isa_io, NULL, "isa-io",
  get_system_io(), 0, LOONGARCH_ISA_IO_SIZE);
 memory_region_add_subregion(address_space_mem, LOONGARCH_ISA_IO_BASE,
 >isa_io);
+if (kernel_filename) {
+loaderparams.ram_size = ram_size;
+loaderparams.kernel_filename = kernel_filename;
+kernel_addr = load_kernel_info();
+if (!machine->firmware) {
+for (i = 0; i < machine->smp.cpus; i++) {
+lacpu = LOONGARCH_CPU(qemu_get_cpu(i));
+lacpu->env.load_elf = true;
+lacpu->env.elf_address = kernel_addr;
+}
+}
+}
 /* Initialize the IO interrupt subsystem */
 loongarch_irq_init(lams);
 }
diff --git a/include/hw/loongarch/virt.h b/include/hw/loongarch/virt.h
index 09a816191c..35e6bc5055 100644
--- a/include/hw/loongarch/virt.h
+++ b/include/hw/loongarch/virt.h
@@ -12,12 +12,17 @@
 #include "hw/boards.h"
 #include "qemu/queue.h"
 #include "hw/intc/loongarch_ipi.h"
+#include "qemu/units.h"
 
 #define LOONGARCH_MAX_VCPUS 4
 
 #define LOONGARCH_ISA_IO_BASE   0x1800UL
 #define LOONGARCH_ISA_IO_SIZE   0x0004000
 
+#define FW_CFG_ADDR 0x1e02
+#define LA_BIOS_BASE0x1c00
+#define LA_BIOS_SIZE(4 * MiB)
+
 struct LoongArchMachineState {
 /*< private >*/
 MachineState parent_obj;
@@ -26,6 +31,10 @@ struct LoongArchMachineState {
 MemoryRegion lowmem;
 MemoryRegion highmem;
 MemoryRegion isa_io;
+MemoryRe

[PATCH v2 19/43] target/loongarch: Add CSRs definition

2022-04-25 Thread Xiaojuan Yang
Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
---
 target/loongarch/cpu-csr.h | 208 +
 target/loongarch/cpu.c |  36 +++
 target/loongarch/cpu.h |  65 
 3 files changed, 309 insertions(+)
 create mode 100644 target/loongarch/cpu-csr.h

diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
new file mode 100644
index 00..4c8ce7fed5
--- /dev/null
+++ b/target/loongarch/cpu-csr.h
@@ -0,0 +1,208 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch CSRs
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#ifndef LOONGARCH_CPU_CSR_H
+#define LOONGARCH_CPU_CSR_H
+
+#include "hw/registerfields.h"
+
+/* Base on kernal definitions: arch/loongarch/include/asm/loongarch.h */
+
+/* Basic CSRs */
+#define LOONGARCH_CSR_CRMD   0x0 /* Current mode info */
+
+#define LOONGARCH_CSR_PRMD   0x1 /* Prev-exception mode info */
+FIELD(CSR_PRMD, PPLV, 0, 2)
+FIELD(CSR_PRMD, PIE, 2, 1)
+FIELD(CSR_PRMD, PWE, 3, 1)
+
+#define LOONGARCH_CSR_EUEN   0x2 /* Extended unit enable */
+FIELD(CSR_EUEN, FPE, 0, 1)
+FIELD(CSR_EUEN, SXE, 1, 1)
+FIELD(CSR_EUEN, ASXE, 2, 1)
+FIELD(CSR_EUEN, BTE, 3, 1)
+
+#define LOONGARCH_CSR_MISC   0x3 /* Misc config */
+FIELD(CSR_MISC, VA32, 0, 4)
+FIELD(CSR_MISC, DRDTL, 4, 4)
+FIELD(CSR_MISC, RPCNTL, 8, 4)
+FIELD(CSR_MISC, ALCL, 12, 4)
+FIELD(CSR_MISC, DWPL, 16, 3)
+
+#define LOONGARCH_CSR_ECFG   0x4 /* Exception config */
+FIELD(CSR_ECFG, LIE, 0, 13)
+FIELD(CSR_ECFG, VS, 16, 3)
+
+#define LOONGARCH_CSR_ESTAT  0x5 /* Exception status */
+FIELD(CSR_ESTAT, IS, 0, 13)
+FIELD(CSR_ESTAT, ECODE, 16, 6)
+FIELD(CSR_ESTAT, ESUBCODE, 22, 9)
+
+#define LOONGARCH_CSR_ERA0x6 /* Exception return address */
+
+#define LOONGARCH_CSR_BADV   0x7 /* Bad virtual address */
+
+#define LOONGARCH_CSR_BADI   0x8 /* Bad instruction */
+
+#define LOONGARCH_CSR_EENTRY 0xc /* Exception entry address */
+
+/* TLB related CSRs */
+#define LOONGARCH_CSR_TLBIDX 0x10 /* TLB Index, EHINV, PageSize, NP */
+FIELD(CSR_TLBIDX, INDEX, 0, 12)
+FIELD(CSR_TLBIDX, PS, 24, 6)
+FIELD(CSR_TLBIDX, NE, 31, 1)
+
+#define LOONGARCH_CSR_TLBEHI 0x11 /* TLB EntryHi */
+FIELD(CSR_TLBEHI, VPPN, 13, 35)
+
+#define LOONGARCH_CSR_TLBELO00x12 /* TLB EntryLo0 */
+#define LOONGARCH_CSR_TLBELO10x13 /* TLB EntryLo1 */
+FIELD(TLBENTRY, V, 0, 1)
+FIELD(TLBENTRY, D, 1, 1)
+FIELD(TLBENTRY, PLV, 2, 2)
+FIELD(TLBENTRY, MAT, 4, 2)
+FIELD(TLBENTRY, G, 6, 1)
+FIELD(TLBENTRY, PPN, 12, 36)
+FIELD(TLBENTRY, NR, 61, 1)
+FIELD(TLBENTRY, NX, 62, 1)
+FIELD(TLBENTRY, RPLV, 63, 1)
+
+#define LOONGARCH_CSR_ASID   0x18 /* Address space identifier */
+FIELD(CSR_ASID, ASID, 0, 10)
+FIELD(CSR_ASID, ASIDBITS, 16, 8)
+
+/* Page table base address when badv[47] = 0 */
+#define LOONGARCH_CSR_PGDL   0x19
+/* Page table base address when badv[47] = 1 */
+#define LOONGARCH_CSR_PGDH   0x1a
+
+#define LOONGARCH_CSR_PGD0x1b /* Page table base address */
+
+/* Page walk controller's low addr */
+#define LOONGARCH_CSR_PWCL   0x1c
+FIELD(CSR_PWCL, PTBASE, 0, 5)
+FIELD(CSR_PWCL, PTWIDTH, 5, 5)
+FIELD(CSR_PWCL, DIR1_BASE, 10, 5)
+FIELD(CSR_PWCL, DIR1_WIDTH, 15, 5)
+FIELD(CSR_PWCL, DIR2_BASE, 20, 5)
+FIELD(CSR_PWCL, DIR2_WIDTH, 25, 5)
+FIELD(CSR_PWCL, PTEWIDTH, 30, 2)
+
+/* Page walk controller's high addr */
+#define LOONGARCH_CSR_PWCH   0x1d
+FIELD(CSR_PWCH, DIR3_BASE, 0, 6)
+FIELD(CSR_PWCH, DIR3_WIDTH, 6, 6)
+FIELD(CSR_PWCH, DIR4_BASE, 12, 6)
+FIELD(CSR_PWCH, DIR4_WIDTH, 18, 6)
+
+#define LOONGARCH_CSR_STLBPS 0x1e /* Stlb page size */
+FIELD(CSR_STLBPS, PS, 0, 5)
+
+#define LOONGARCH_CSR_RVACFG 0x1f /* Reduced virtual address config */
+FIELD(CSR_RVACFG, RBITS, 0, 4)
+
+/* Config CSRs */
+#define LOONGARCH_CSR_CPUID  0x20 /* CPU core id */
+
+#define LOONGARCH_CSR_PRCFG1 0x21 /* Config1 */
+FIELD(CSR_PRCFG1, SAVE_NUM, 0, 4)
+FIELD(CSR_PRCFG1, TIMER_BITS, 4, 8)
+FIELD(CSR_PRCFG1, VSMAX, 12, 3)
+
+#define LOONGARCH_CSR_PRCFG2 0x22 /* Config2 */
+
+#define LOONGARCH_CSR_PRCFG3 0x23 /* Config3 */
+FIELD(CSR_PRCFG3, TLB_TYPE, 0, 4)
+FIELD(CSR_PRCFG3, MTLB_ENTRY, 4, 8)
+FIELD(CSR_PRCFG3, STLB_WAYS, 12, 8)
+FIELD(CSR_PRCFG3, STLB_SETS, 20, 8)
+
+/*
+ * Save registers count can read from PRCFG1.SAVE_NUM
+ * The Min count is 1. Max count is 15.
+ */
+#define LOONGARCH_CSR_SAVE(N)(0x30 + N)
+
+/* Timer CSRs */
+#define LOONGARCH_CSR_TID0x40 /* Timer ID */
+
+#define LOONGARCH_CSR_TCFG   0x41 /* Timer config */
+FIELD(CSR_TCFG, EN, 0, 1)
+FIELD(CSR_TCFG, PERIODIC, 1, 1)
+FIELD(CSR_TCFG, INIT_VAL, 2, 46)
+
+#define LOONGARCH_CSR_TVAL   0x42 /* Timer ticks remain */
+
+#define LOONGARCH_CSR_CNTC   0x43 /* Timer offset */
+
+#define LOONGARCH_CSR_TICLR  0x44 /* Timer inter

[PATCH v2 41/43] target/loongarch: Add gdb support.

2022-04-25 Thread Xiaojuan Yang
Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 MAINTAINERS |  1 +
 configs/targets/loongarch64-softmmu.mak |  1 +
 gdb-xml/loongarch-base64.xml| 44 ++
 gdb-xml/loongarch-fpu64.xml | 57 +
 target/loongarch/cpu.c  |  9 +++
 target/loongarch/gdbstub.c  | 81 +
 target/loongarch/internals.h|  4 ++
 target/loongarch/meson.build|  1 +
 8 files changed, 198 insertions(+)
 create mode 100644 gdb-xml/loongarch-base64.xml
 create mode 100644 gdb-xml/loongarch-fpu64.xml
 create mode 100644 target/loongarch/gdbstub.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 18d06bb859..e123f3026c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1140,6 +1140,7 @@ F: include/hw/pci-host/ls7a.h
 F: hw/rtc/ls7a_rtc.c
 F: include/hw/acpi/ls7a.h
 F: hw/acpi/ls7a.c
+F: gdb-xml/loongarch*.xml
 
 M68K Machines
 -
diff --git a/configs/targets/loongarch64-softmmu.mak 
b/configs/targets/loongarch64-softmmu.mak
index 666154022f..7bc06c850c 100644
--- a/configs/targets/loongarch64-softmmu.mak
+++ b/configs/targets/loongarch64-softmmu.mak
@@ -1,3 +1,4 @@
 TARGET_ARCH=loongarch64
 TARGET_BASE_ARCH=loongarch
 TARGET_SUPPORTS_MTTCG=y
+TARGET_XML_FILES= gdb-xml/loongarch-base64.xml gdb-xml/loongarch-fpu64.xml
diff --git a/gdb-xml/loongarch-base64.xml b/gdb-xml/loongarch-base64.xml
new file mode 100644
index 00..4962bdbd28
--- /dev/null
+++ b/gdb-xml/loongarch-base64.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+
diff --git a/gdb-xml/loongarch-fpu64.xml b/gdb-xml/loongarch-fpu64.xml
new file mode 100644
index 00..e52cf89fbc
--- /dev/null
+++ b/gdb-xml/loongarch-fpu64.xml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+  
+
+
+  
+
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+  
+
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 4937c1ba85..561e8a2a91 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -481,6 +481,8 @@ static void loongarch_cpu_realizefn(DeviceState *dev, Error 
**errp)
 return;
 }
 
+loongarch_cpu_register_gdb_regs_for_features(cs);
+
 cpu_reset(cs);
 qemu_init_vcpu(cs);
 
@@ -646,6 +648,13 @@ static void loongarch_cpu_class_init(ObjectClass *c, void 
*data)
 dc->vmsd = _loongarch_cpu;
 cc->sysemu_ops = _sysemu_ops;
 cc->disas_set_info = loongarch_cpu_disas_set_info;
+cc->gdb_read_register = loongarch_cpu_gdb_read_register;
+cc->gdb_write_register = loongarch_cpu_gdb_write_register;
+cc->disas_set_info = loongarch_cpu_disas_set_info;
+cc->gdb_num_core_regs = 34;
+cc->gdb_core_xml_file = "loongarch-base64.xml";
+cc->gdb_stop_before_watchpoint = true;
+
 #ifdef CONFIG_TCG
 cc->tcg_ops = _tcg_ops;
 #endif
diff --git a/target/loongarch/gdbstub.c b/target/loongarch/gdbstub.c
new file mode 100644
index 00..0c48834201
--- /dev/null
+++ b/target/loongarch/gdbstub.c
@@ -0,0 +1,81 @@
+/*
+ * LOONGARCH gdb server stub
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "internals.h"
+#include "exec/gdbstub.h"
+
+int loongarch_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
+{
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+CPULoongArchState *env = >env;
+
+if (0 <= n && n < 32) {
+return gdb_get_regl(mem_buf, env->gpr[n]);
+} else if (n == 32) {
+return gdb_get_regl(mem_buf, env->pc);
+} else if (n == 33) {
+return gdb_get_regl(mem_buf, env->badaddr);
+}
+return 0;
+}
+
+int loongarch_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+CPULoongArchState *env = >env;
+target_ulong tmp = ldtul_p(mem_buf);
+int length = 0;
+
+if (0 <= n && n < 32) {
+env->gpr[n] = tmp;
+length = sizeof(target_ulong);
+} else if (n == 32) {
+env->pc = tmp;
+length = sizeof(target_ulong);
+}
+return length;
+}
+
+static int loongarch_gdb_get_fpu(CPULoongArchState *env,
+ GByteArray *mem_buf, int n)
+{
+if (0 <= n && n < 32) {
+return gdb_get_reg64(mem_buf, env->fpr[n]);
+} else if (32 <= n && n < 40) {
+return gdb_get_reg8(mem_buf, env->cf[n - 32]);
+} else if (n == 40) {
+return gdb_get_reg32(mem_buf, env->fcsr0);
+}
+return 0;
+}
+
+static int loongarch_gdb_set_fpu(CPULoongArchState *env,
+ 

[PATCH v2 32/43] hw/intc: Add LoongArch ls7a interrupt controller support(PCH-PIC)

2022-04-25 Thread Xiaojuan Yang
This patch realize the PCH-PIC interrupt controller.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 MAINTAINERS |   1 +
 hw/intc/Kconfig |   4 +
 hw/intc/loongarch_pch_pic.c | 434 
 hw/intc/meson.build |   1 +
 hw/intc/trace-events|   9 +
 hw/loongarch/Kconfig|   1 +
 include/hw/intc/loongarch_pch_pic.h |  69 +
 include/hw/pci-host/ls7a.h  |  30 ++
 8 files changed, 549 insertions(+)
 create mode 100644 hw/intc/loongarch_pch_pic.c
 create mode 100644 include/hw/intc/loongarch_pch_pic.h
 create mode 100644 include/hw/pci-host/ls7a.h

diff --git a/MAINTAINERS b/MAINTAINERS
index c9ba2cc858..1b724a7d35 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1136,6 +1136,7 @@ F: hw/loongarch/
 F: include/hw/loongarch/virt.h
 F: include/hw/intc/loongarch_*.h
 F: hw/intc/loongarch_*.c
+F: include/hw/pci-host/ls7a.h
 
 M68K Machines
 -
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
index 6c7e82da64..1fbba2e728 100644
--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -87,3 +87,7 @@ config M68K_IRQC
 
 config LOONGARCH_IPI
 bool
+
+config LOONGARCH_PCH_PIC
+bool
+select UNIMP
diff --git a/hw/intc/loongarch_pch_pic.c b/hw/intc/loongarch_pch_pic.c
new file mode 100644
index 00..6f8ce55bea
--- /dev/null
+++ b/hw/intc/loongarch_pch_pic.c
@@ -0,0 +1,434 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU Loongson 7A1000 I/O interrupt controller.
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/loongarch/virt.h"
+#include "hw/irq.h"
+#include "hw/intc/loongarch_pch_pic.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+
+static void pch_pic_update_irq(LoongArchPCHPIC *s, uint64_t mask, int level)
+{
+uint64_t val;
+int irq;
+
+if (level) {
+val = mask & s->intirr & ~s->int_mask;
+if (val) {
+irq = find_first_bit(, 64);
+s->intisr |= 0x1ULL << irq;
+qemu_set_irq(s->parent_irq[s->htmsi_vector[irq]], 1);
+}
+} else {
+val = mask & s->intisr;
+if (val) {
+irq = find_first_bit(, 64);
+s->intisr &= ~(0x1ULL << irq);
+qemu_set_irq(s->parent_irq[s->htmsi_vector[irq]], 0);
+}
+}
+}
+
+static void pch_pic_irq_handler(void *opaque, int irq, int level)
+{
+LoongArchPCHPIC *s = LOONGARCH_PCH_PIC(opaque);
+uint64_t mask = 1ULL << irq;
+
+assert(irq < PCH_PIC_IRQ_NUM);
+trace_loongarch_pch_pic_irq_handler(irq, level);
+
+if (s->intedge & mask) {
+/* Edge triggered */
+if (level) {
+if ((s->last_intirr & mask) == 0) {
+s->intirr |= mask;
+}
+s->last_intirr |= mask;
+} else {
+s->last_intirr &= ~mask;
+}
+} else {
+/* Level triggered */
+if (level) {
+s->intirr |= mask;
+s->last_intirr |= mask;
+} else {
+s->intirr &= ~mask;
+s->last_intirr &= ~mask;
+}
+}
+pch_pic_update_irq(s, mask, level);
+}
+
+static uint64_t loongarch_pch_pic_low_readw(void *opaque, hwaddr addr,
+unsigned size)
+{
+LoongArchPCHPIC *s = LOONGARCH_PCH_PIC(opaque);
+uint64_t val = 0;
+uint32_t offset = addr & 0xfff;
+
+switch (offset) {
+case PCH_PIC_INT_ID_LO:
+val = PCH_PIC_INT_ID_VAL;
+break;
+case PCH_PIC_INT_ID_HI:
+val = PCH_PIC_INT_ID_NUM;
+break;
+case PCH_PIC_INT_MASK_LO:
+val = (uint32_t)s->int_mask;
+break;
+case PCH_PIC_INT_MASK_HI:
+val = s->int_mask >> 32;
+break;
+case PCH_PIC_INT_EDGE_LO:
+val = (uint32_t)s->intedge;
+break;
+case PCH_PIC_INT_EDGE_HI:
+val = s->intedge >> 32;
+break;
+case PCH_PIC_HTMSI_EN_LO:
+val = (uint32_t)s->htmsi_en;
+break;
+case PCH_PIC_HTMSI_EN_HI:
+val = s->htmsi_en >> 32;
+break;
+case PCH_PIC_AUTO_CTRL0_LO:
+case PCH_PIC_AUTO_CTRL0_HI:
+case PCH_PIC_AUTO_CTRL1_LO:
+case PCH_PIC_AUTO_CTRL1_HI:
+break;
+default:
+break;
+}
+
+trace_loongarch_pch_pic_low_readw(size, (uint32_t)addr, val);
+return val;
+}
+
+static uint64_t get_writew_val(uint64_t value, uint32_t target, bool hi)
+{
+uint64_t mask = 0x;
+uint64_t data = target;
+
+return hi ? (value & ~mask) | (data << 32) : (value & mask) | data;
+}
+
+static void loongarch_pch_pic_low_writew(void *opaque, hwaddr addr,
+ 

[PATCH v2 37/43] hw/loongarch: Add some devices support for 3A5000.

2022-04-25 Thread Xiaojuan Yang
1.Add uart,virtio-net,vga and usb for 3A5000.
2.Add irq set and map for the pci host. Non pci device
use irq 0-16, pci device use 16-64.
3.Add some unimplented device to emulate guest unused
memory space.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 hw/loongarch/Kconfig   |  7 
 hw/loongarch/loongson3.c   | 77 ++
 include/hw/pci-host/ls7a.h |  8 
 3 files changed, 92 insertions(+)

diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
index f779087416..8552ff4bee 100644
--- a/hw/loongarch/Kconfig
+++ b/hw/loongarch/Kconfig
@@ -2,6 +2,13 @@ config LOONGARCH_VIRT
 bool
 select PCI
 select PCI_EXPRESS_GENERIC_BRIDGE
+imply VGA_PCI
+imply VIRTIO_VGA
+imply PCI_DEVICES
+select ISA_BUS
+select SERIAL
+select SERIAL_ISA
+select VIRTIO_PCI
 select LOONGARCH_IPI
 select LOONGARCH_PCH_PIC
 select LOONGARCH_PCH_MSI
diff --git a/hw/loongarch/loongson3.c b/hw/loongarch/loongson3.c
index 4906f9926b..92c353263e 100644
--- a/hw/loongarch/loongson3.c
+++ b/hw/loongarch/loongson3.c
@@ -9,6 +9,7 @@
 #include "qemu/datadir.h"
 #include "qapi/error.h"
 #include "hw/boards.h"
+#include "hw/char/serial.h"
 #include "sysemu/sysemu.h"
 #include "sysemu/qtest.h"
 #include "sysemu/runstate.h"
@@ -16,14 +17,88 @@
 #include "sysemu/rtc.h"
 #include "hw/loongarch/virt.h"
 #include "exec/address-spaces.h"
+#include "hw/irq.h"
+#include "net/net.h"
 #include "hw/intc/loongarch_ipi.h"
 #include "hw/intc/loongarch_extioi.h"
 #include "hw/intc/loongarch_pch_pic.h"
 #include "hw/intc/loongarch_pch_msi.h"
 #include "hw/pci-host/ls7a.h"
+#include "hw/pci-host/gpex.h"
+#include "hw/misc/unimp.h"
 
 #include "target/loongarch/cpu.h"
 
+static void loongarch_devices_init(DeviceState *pch_pic)
+{
+DeviceState *gpex_dev;
+SysBusDevice *d;
+PCIBus *pci_bus;
+MemoryRegion *ecam_alias, *ecam_reg, *pio_alias, *pio_reg;
+MemoryRegion *mmio_alias, *mmio_reg;
+int i;
+
+gpex_dev = qdev_new(TYPE_GPEX_HOST);
+d = SYS_BUS_DEVICE(gpex_dev);
+sysbus_realize_and_unref(d, _fatal);
+pci_bus = PCI_HOST_BRIDGE(gpex_dev)->bus;
+
+/* Map only part size_ecam bytes of ECAM space */
+ecam_alias = g_new0(MemoryRegion, 1);
+ecam_reg = sysbus_mmio_get_region(d, 0);
+memory_region_init_alias(ecam_alias, OBJECT(gpex_dev), "pcie-ecam",
+ ecam_reg, 0, LS_PCIECFG_SIZE);
+memory_region_add_subregion(get_system_memory(), LS_PCIECFG_BASE,
+ecam_alias);
+
+/* Map PCI mem space */
+mmio_alias = g_new0(MemoryRegion, 1);
+mmio_reg = sysbus_mmio_get_region(d, 1);
+memory_region_init_alias(mmio_alias, OBJECT(gpex_dev), "pcie-mmio",
+ mmio_reg, LS7A_PCI_MEM_BASE, LS7A_PCI_MEM_SIZE);
+memory_region_add_subregion(get_system_memory(), LS7A_PCI_MEM_BASE,
+mmio_alias);
+
+/* Map PCI IO port space. */
+pio_alias = g_new0(MemoryRegion, 1);
+pio_reg = sysbus_mmio_get_region(d, 2);
+memory_region_init_alias(pio_alias, OBJECT(gpex_dev), "pcie-io", pio_reg,
+ LS7A_PCI_IO_OFFSET, LS7A_PCI_IO_SIZE);
+memory_region_add_subregion(get_system_memory(), LS7A_PCI_IO_BASE,
+pio_alias);
+
+for (i = 0; i < GPEX_NUM_IRQS; i++) {
+sysbus_connect_irq(d, i,
+   qdev_get_gpio_in(pch_pic, 16 + i));
+gpex_set_irq_num(GPEX_HOST(gpex_dev), i, 16 + i);
+}
+
+serial_mm_init(get_system_memory(), LS7A_UART_BASE, 0,
+   qdev_get_gpio_in(pch_pic,
+LS7A_UART_IRQ - PCH_PIC_IRQ_OFFSET),
+   115200, serial_hd(0), DEVICE_LITTLE_ENDIAN);
+
+/* Network init */
+for (i = 0; i < nb_nics; i++) {
+NICInfo *nd = _table[i];
+
+if (!nd->model) {
+nd->model = g_strdup("virtio");
+}
+
+pci_nic_init_nofail(nd, pci_bus, nd->model, NULL);
+}
+
+/* VGA setup */
+pci_vga_init(pci_bus);
+
+/*
+ * There are some invalid guest memory access.
+ * Create some unimplemented devices to emulate this.
+ */
+create_unimplemented_device("pci-dma-cfg", 0x1001041c, 0x4);
+}
+
 static void loongarch_irq_init(LoongArchMachineState *lams)
 {
 MachineState *ms = MACHINE(lams);
@@ -130,6 +205,8 @@ static void loongarch_irq_init(LoongArchMachineState *lams)
 sysbus_connect_irq(d, i,
qdev_get_gpio_in(extioi, i + PCH_MSI_IRQ_START));
 }
+
+loongarch_devices_init(pch_pic);
 }
 
 static void loongarch_init(MachineState *machine)
diff --git a/include/h

[PATCH v2 04/43] target/loongarch: Add fixed point arithmetic instruction translation

2022-04-25 Thread Xiaojuan Yang
From: Song Gao 

This includes:
- ADD.{W/D}, SUB.{W/D}
- ADDI.{W/D}, ADDU16ID
- ALSL.{W[U]/D}
- LU12I.W, LU32I.D LU52I.D
- SLT[U], SLT[U]I
- PCADDI, PCADDU12I, PCADDU18I, PCALAU12I
- AND, OR, NOR, XOR, ANDN, ORN
- MUL.{W/D}, MULH.{W[U]/D[U]}
- MULW.D.W[U]
- DIV.{W[U]/D[U]}, MOD.{W[U]/D[U]}
- ANDI, ORI, XORI

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 target/loongarch/insn_trans/trans_arith.c.inc | 304 ++
 target/loongarch/insns.decode |  79 +
 target/loongarch/translate.c  |  83 +
 target/loongarch/translate.h  |  19 ++
 4 files changed, 485 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_arith.c.inc
 create mode 100644 target/loongarch/insns.decode

diff --git a/target/loongarch/insn_trans/trans_arith.c.inc 
b/target/loongarch/insn_trans/trans_arith.c.inc
new file mode 100644
index 00..8e45eadbc8
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_arith.c.inc
@@ -0,0 +1,304 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static bool gen_rrr(DisasContext *ctx, arg_rrr *a,
+DisasExtend src1_ext, DisasExtend src2_ext,
+DisasExtend dst_ext, void (*func)(TCGv, TCGv, TCGv))
+{
+TCGv dest = gpr_dst(ctx, a->rd, dst_ext);
+TCGv src1 = gpr_src(ctx, a->rj, src1_ext);
+TCGv src2 = gpr_src(ctx, a->rk, src2_ext);
+
+func(dest, src1, src2);
+gen_set_gpr(a->rd, dest, dst_ext);
+
+return true;
+}
+
+static bool gen_rri_v(DisasContext *ctx, arg_rr_i *a,
+  DisasExtend src_ext, DisasExtend dst_ext,
+  void (*func)(TCGv, TCGv, TCGv))
+{
+TCGv dest = gpr_dst(ctx, a->rd, dst_ext);
+TCGv src1 = gpr_src(ctx, a->rj, src_ext);
+TCGv src2 = tcg_constant_tl(a->imm);
+
+func(dest, src1, src2);
+gen_set_gpr(a->rd, dest, dst_ext);
+
+return true;
+}
+
+static bool gen_rri_c(DisasContext *ctx, arg_rr_i *a,
+  DisasExtend src_ext, DisasExtend dst_ext,
+  void (*func)(TCGv, TCGv, target_long))
+{
+TCGv dest = gpr_dst(ctx, a->rd, dst_ext);
+TCGv src1 = gpr_src(ctx, a->rj, src_ext);
+
+func(dest, src1, a->imm);
+gen_set_gpr(a->rd, dest, dst_ext);
+
+return true;
+}
+
+static bool gen_rrr_sa(DisasContext *ctx, arg_rrr_sa *a,
+   DisasExtend src_ext, DisasExtend dst_ext,
+   void (*func)(TCGv, TCGv, TCGv, target_long))
+{
+TCGv dest = gpr_dst(ctx, a->rd, dst_ext);
+TCGv src1 = gpr_src(ctx, a->rj, src_ext);
+TCGv src2 = gpr_src(ctx, a->rk, src_ext);
+
+func(dest, src1, src2, a->sa);
+gen_set_gpr(a->rd, dest, dst_ext);
+
+return true;
+}
+
+static bool trans_lu12i_w(DisasContext *ctx, arg_lu12i_w *a)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+
+tcg_gen_movi_tl(dest, a->imm << 12);
+gen_set_gpr(a->rd, dest, EXT_NONE);
+
+return true;
+}
+
+static bool gen_pc(DisasContext *ctx, arg_r_i *a,
+   target_ulong (*func)(target_ulong, int))
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+target_ulong addr = func(ctx->base.pc_next, a->imm);
+
+tcg_gen_movi_tl(dest, addr);
+gen_set_gpr(a->rd, dest, EXT_NONE);
+
+return true;
+}
+
+static void gen_slt(TCGv dest, TCGv src1, TCGv src2)
+{
+tcg_gen_setcond_tl(TCG_COND_LT, dest, src1, src2);
+}
+
+static void gen_sltu(TCGv dest, TCGv src1, TCGv src2)
+{
+tcg_gen_setcond_tl(TCG_COND_LTU, dest, src1, src2);
+}
+
+static void gen_mulh_w(TCGv dest, TCGv src1, TCGv src2)
+{
+tcg_gen_mul_i64(dest, src1, src2);
+tcg_gen_sari_i64(dest, dest, 32);
+}
+
+static void gen_mulh_d(TCGv dest, TCGv src1, TCGv src2)
+{
+TCGv discard = tcg_temp_new();
+tcg_gen_muls2_tl(discard, dest, src1, src2);
+tcg_temp_free(discard);
+}
+
+static void gen_mulh_du(TCGv dest, TCGv src1, TCGv src2)
+{
+TCGv discard = tcg_temp_new();
+tcg_gen_mulu2_tl(discard, dest, src1, src2);
+tcg_temp_free(discard);
+}
+
+static void prep_divisor_d(TCGv ret, TCGv src1, TCGv src2)
+{
+TCGv t0 = tcg_temp_new();
+TCGv t1 = tcg_temp_new();
+TCGv zero = tcg_constant_tl(0);
+
+/*
+ * If min / -1, set the divisor to 1.
+ * This avoids potential host overflow trap and produces min.
+ * If x / 0, set the divisor to 1.
+ * This avoids potential host overflow trap;
+ * the required result is undefined.
+ */
+tcg_gen_setcondi_tl(TCG_COND_EQ, ret, src1, INT64_MIN);
+tcg_gen_setcondi_tl(TCG_COND_EQ, t0, src2, -1);
+tcg_gen_setcondi_tl(TCG_COND_EQ, t1, src2, 0);
+tcg_gen_and_tl(ret, ret, t0);
+tcg_gen_or_tl(ret, ret, t1);
+tcg_gen_movcond_tl(TCG_COND_NE, ret, ret, zero, ret, src2);
+
+tcg_temp_free(t0);
+tcg_temp_free(t1);
+}
+
+static void prep_divisor

[PATCH v2 05/43] target/loongarch: Add fixed point shift instruction translation

2022-04-25 Thread Xiaojuan Yang
From: Song Gao 

This includes:
- SLL.W, SRL.W, SRA.W, ROTR.W
- SLLI.W, SRLI.W, SRAI.W, ROTRI.W
- SLL.D, SRL.D, SRA.D, ROTR.D
- SLLI.D, SRLI.D, SRAI.D, ROTRI.D

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 target/loongarch/insn_trans/trans_shift.c.inc | 106 ++
 target/loongarch/insns.decode |  22 
 target/loongarch/translate.c  |   1 +
 3 files changed, 129 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_shift.c.inc

diff --git a/target/loongarch/insn_trans/trans_shift.c.inc 
b/target/loongarch/insn_trans/trans_shift.c.inc
new file mode 100644
index 00..5260af2337
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_shift.c.inc
@@ -0,0 +1,106 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static void gen_sll_w(TCGv dest, TCGv src1, TCGv src2)
+{
+TCGv t0 = tcg_temp_new();
+tcg_gen_andi_tl(t0, src2, 0x1f);
+tcg_gen_shl_tl(dest, src1, t0);
+tcg_temp_free(t0);
+}
+
+static void gen_srl_w(TCGv dest, TCGv src1, TCGv src2)
+{
+TCGv t0 = tcg_temp_new();
+tcg_gen_andi_tl(t0, src2, 0x1f);
+tcg_gen_shr_tl(dest, src1, t0);
+tcg_temp_free(t0);
+}
+
+static void gen_sra_w(TCGv dest, TCGv src1, TCGv src2)
+{
+TCGv t0 = tcg_temp_new();
+tcg_gen_andi_tl(t0, src2, 0x1f);
+tcg_gen_sar_tl(dest, src1, t0);
+tcg_temp_free(t0);
+}
+
+static void gen_sll_d(TCGv dest, TCGv src1, TCGv src2)
+{
+TCGv t0 = tcg_temp_new();
+tcg_gen_andi_tl(t0, src2, 0x3f);
+tcg_gen_shl_tl(dest, src1, t0);
+tcg_temp_free(t0);
+}
+
+static void gen_srl_d(TCGv dest, TCGv src1, TCGv src2)
+{
+TCGv t0 = tcg_temp_new();
+tcg_gen_andi_tl(t0, src2, 0x3f);
+tcg_gen_shr_tl(dest, src1, t0);
+tcg_temp_free(t0);
+}
+
+static void gen_sra_d(TCGv dest, TCGv src1, TCGv src2)
+{
+TCGv t0 = tcg_temp_new();
+tcg_gen_andi_tl(t0, src2, 0x3f);
+tcg_gen_sar_tl(dest, src1, t0);
+tcg_temp_free(t0);
+}
+
+static void gen_rotr_w(TCGv dest, TCGv src1, TCGv src2)
+{
+TCGv_i32 t1 = tcg_temp_new_i32();
+TCGv_i32 t2 = tcg_temp_new_i32();
+TCGv t0 = tcg_temp_new();
+
+tcg_gen_andi_tl(t0, src2, 0x1f);
+
+tcg_gen_trunc_tl_i32(t1, src1);
+tcg_gen_trunc_tl_i32(t2, t0);
+
+tcg_gen_rotr_i32(t1, t1, t2);
+tcg_gen_ext_i32_tl(dest, t1);
+
+tcg_temp_free_i32(t1);
+tcg_temp_free_i32(t2);
+tcg_temp_free(t0);
+}
+
+static void gen_rotr_d(TCGv dest, TCGv src1, TCGv src2)
+{
+TCGv t0 = tcg_temp_new();
+tcg_gen_andi_tl(t0, src2, 0x3f);
+tcg_gen_rotr_tl(dest, src1, t0);
+tcg_temp_free(t0);
+}
+
+static bool trans_srai_w(DisasContext *ctx, arg_srai_w *a)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_ZERO);
+
+tcg_gen_sextract_tl(dest, src1, a->imm, 32 - a->imm);
+gen_set_gpr(a->rd, dest, EXT_NONE);
+
+return true;
+}
+
+TRANS(sll_w, gen_rrr, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_sll_w)
+TRANS(srl_w, gen_rrr, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_srl_w)
+TRANS(sra_w, gen_rrr, EXT_SIGN, EXT_NONE, EXT_SIGN, gen_sra_w)
+TRANS(sll_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_sll_d)
+TRANS(srl_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_srl_d)
+TRANS(sra_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_sra_d)
+TRANS(rotr_w, gen_rrr, EXT_ZERO, EXT_NONE, EXT_SIGN, gen_rotr_w)
+TRANS(rotr_d, gen_rrr, EXT_NONE, EXT_NONE, EXT_NONE, gen_rotr_d)
+TRANS(slli_w, gen_rri_c, EXT_NONE, EXT_SIGN, tcg_gen_shli_tl)
+TRANS(slli_d, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_shli_tl)
+TRANS(srli_w, gen_rri_c, EXT_ZERO, EXT_SIGN, tcg_gen_shri_tl)
+TRANS(srli_d, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_shri_tl)
+TRANS(srai_d, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_sari_tl)
+TRANS(rotri_w, gen_rri_v, EXT_NONE, EXT_NONE, gen_rotr_w)
+TRANS(rotri_d, gen_rri_c, EXT_NONE, EXT_NONE, tcg_gen_rotri_tl)
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 8579c11984..673aee4be5 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -23,6 +23,8 @@
 #
 @rrr     . rk:5 rj:5 rd:5
 @r_i20   ... imm:s20 rd:5_i
+@rr_ui5     . imm:5 rj:5 rd:5_i
+@rr_ui6   imm:6 rj:5 rd:5_i
 @rr_i12  .. imm:s12 rj:5 rd:5_i
 @rr_ui12  .. imm:12 rj:5 rd:5_i
 @rr_i16  .. imm:s16 rj:5 rd:5_i
@@ -77,3 +79,23 @@ addu16i_d   0001 00  . . 
@rr_i16
 andi 001101  . . @rr_ui12
 ori  001110  . . @rr_ui12
 xori 00  . . @rr_ui12
+
+#
+# Fixed point shift operation instruction
+#
+sll_w    0001 01110 . . .@rrr
+srl_w

[PATCH v2 16/43] target/loongarch: Add disassembler

2022-04-25 Thread Xiaojuan Yang
From: Song Gao 

This patch adds support for disassembling via option '-d in_asm'.

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 include/disas/dis-asm.h  |   2 +
 meson.build  |   1 +
 target/loongarch/disas.c | 610 +++
 3 files changed, 613 insertions(+)
 create mode 100644 target/loongarch/disas.c

diff --git a/include/disas/dis-asm.h b/include/disas/dis-asm.h
index fadf6a65ef..a285063917 100644
--- a/include/disas/dis-asm.h
+++ b/include/disas/dis-asm.h
@@ -253,6 +253,7 @@ enum bfd_architecture
 #define bfd_mach_rx0x75
 #define bfd_mach_rx_v2 0x76
 #define bfd_mach_rx_v3 0x77
+  bfd_arch_loongarch,
   bfd_arch_last
   };
 #define bfd_mach_s390_31 31
@@ -462,6 +463,7 @@ int print_insn_riscv64  (bfd_vma, 
disassemble_info*);
 int print_insn_riscv128 (bfd_vma, disassemble_info*);
 int print_insn_rx(bfd_vma, disassemble_info *);
 int print_insn_hexagon(bfd_vma, disassemble_info *);
+int print_insn_loongarch(bfd_vma, disassemble_info *);
 
 #ifdef CONFIG_CAPSTONE
 bool cap_disas_target(disassemble_info *info, uint64_t pc, size_t size);
diff --git a/meson.build b/meson.build
index d083c6b7bf..8325b5a38b 100644
--- a/meson.build
+++ b/meson.build
@@ -2076,6 +2076,7 @@ disassemblers = {
   'sh4' : ['CONFIG_SH4_DIS'],
   'sparc' : ['CONFIG_SPARC_DIS'],
   'xtensa' : ['CONFIG_XTENSA_DIS'],
+  'loongarch' : ['CONFIG_LOONGARCH_DIS'],
 }
 if link_language == 'cpp'
   disassemblers += {
diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
new file mode 100644
index 00..9454ebb8e9
--- /dev/null
+++ b/target/loongarch/disas.c
@@ -0,0 +1,610 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch Disassembler
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited.
+ */
+
+#include "qemu/osdep.h"
+#include "disas/dis-asm.h"
+#include "qemu/bitops.h"
+
+typedef struct {
+disassemble_info *info;
+uint64_t pc;
+uint32_t insn;
+} DisasContext;
+
+static inline int plus_1(DisasContext *ctx, int x)
+{
+return x + 1;
+}
+
+static inline int shl_2(DisasContext *ctx, int x)
+{
+return x << 2;
+}
+
+#define output(C, INSN, FMT, ...)   \
+{   \
+(C)->info->fprintf_func((C)->info->stream, "%08x   %-9s\t" FMT, \
+(C)->insn, INSN, ##__VA_ARGS__);\
+}
+
+#include "decode-insns.c.inc"
+
+int print_insn_loongarch(bfd_vma memaddr, struct disassemble_info *info)
+{
+bfd_byte buffer[4];
+uint32_t insn;
+int status;
+
+status = (*info->read_memory_func)(memaddr, buffer, 4, info);
+if (status != 0) {
+(*info->memory_error_func)(status, memaddr, info);
+return -1;
+}
+insn = bfd_getl32(buffer);
+DisasContext ctx = {
+.info = info,
+.pc = memaddr,
+.insn = insn
+};
+
+if (!decode(, insn)) {
+output(, "illegal", "");
+}
+return 4;
+}
+
+static void output_r_i(DisasContext *ctx, arg_r_i *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "r%d, %d", a->rd, a->imm);
+}
+
+static void output_rrr(DisasContext *ctx, arg_rrr *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "r%d, r%d, r%d", a->rd, a->rj, a->rk);
+}
+
+static void output_rr_i(DisasContext *ctx, arg_rr_i *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "r%d, r%d, %d", a->rd, a->rj, a->imm);
+}
+
+static void output_rrr_sa(DisasContext *ctx, arg_rrr_sa *a,
+  const char *mnemonic)
+{
+output(ctx, mnemonic, "r%d, r%d, r%d, %d", a->rd, a->rj, a->rk, a->sa);
+}
+
+static void output_rr(DisasContext *ctx, arg_rr *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "r%d, r%d", a->rd, a->rj);
+}
+
+static void output_rr_ms_ls(DisasContext *ctx, arg_rr_ms_ls *a,
+  const char *mnemonic)
+{
+output(ctx, mnemonic, "r%d, r%d, %d, %d", a->rd, a->rj, a->ms, a->ls);
+}
+
+static void output_hint_r_i(DisasContext *ctx, arg_hint_r_i *a,
+const char *mnemonic)
+{
+output(ctx, mnemonic, "%d, r%d, %d", a->hint, a->rj, a->imm);
+}
+
+static void output_i(DisasContext *ctx, arg_i *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "%d", a->imm);
+}
+
+static void output_rr_jk(DisasContext *ctx, arg_rr_jk *a,
+ const char *mnemonic)
+{
+output(ctx, mnemonic, "r%d, r%d", a->rj, a->rk);
+}
+
+static void output_ff(DisasContext *ctx, arg_ff *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "f%d, f%d", a->fd, a->fj);
+}
+
+static void output_fff(DisasCont

[PATCH v2 09/43] target/loongarch: Add fixed point extra instruction translation

2022-04-25 Thread Xiaojuan Yang
From: Song Gao 

This includes:
- CRC[C].W.{B/H/W/D}.W
- SYSCALL
- BREAK
- ASRT{LE/GT}.D
- RDTIME{L/H}.W, RDTIME.D
- CPUCFG

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 target/loongarch/helper.h |  4 ++
 target/loongarch/insn_trans/trans_extra.c.inc | 68 +++
 target/loongarch/insns.decode | 19 ++
 target/loongarch/op_helper.c  | 26 +++
 target/loongarch/translate.c  |  1 +
 5 files changed, 118 insertions(+)
 create mode 100644 target/loongarch/insn_trans/trans_extra.c.inc

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 100622bfc2..638c2efc51 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -11,3 +11,7 @@ DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl)
 
 DEF_HELPER_FLAGS_3(asrtle_d, TCG_CALL_NO_WG, void, env, tl, tl)
 DEF_HELPER_FLAGS_3(asrtgt_d, TCG_CALL_NO_WG, void, env, tl, tl)
+
+DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl)
+DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, tl, tl, tl, tl)
+DEF_HELPER_FLAGS_2(cpucfg, TCG_CALL_NO_RWG_SE, tl, env, tl)
diff --git a/target/loongarch/insn_trans/trans_extra.c.inc 
b/target/loongarch/insn_trans/trans_extra.c.inc
new file mode 100644
index 00..549f75a867
--- /dev/null
+++ b/target/loongarch/insn_trans/trans_extra.c.inc
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+static bool trans_break(DisasContext *ctx, arg_break *a)
+{
+generate_exception(ctx, EXCCODE_BRK);
+return true;
+}
+
+static bool trans_syscall(DisasContext *ctx, arg_syscall *a)
+{
+generate_exception(ctx, EXCCODE_SYS);
+return true;
+}
+
+static bool trans_asrtle_d(DisasContext *ctx, arg_asrtle_d * a)
+{
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+
+gen_helper_asrtle_d(cpu_env, src1, src2);
+return true;
+}
+
+static bool trans_asrtgt_d(DisasContext *ctx, arg_asrtgt_d * a)
+{
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+
+gen_helper_asrtgt_d(cpu_env, src1, src2);
+return true;
+}
+
+static bool trans_cpucfg(DisasContext *ctx, arg_cpucfg *a)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+gen_helper_cpucfg(dest, cpu_env, src1);
+gen_set_gpr(a->rd, dest, EXT_NONE);
+
+return true;
+}
+
+static bool gen_crc(DisasContext *ctx, arg_rrr *a,
+void (*func)(TCGv, TCGv, TCGv, TCGv),
+TCGv tsz)
+{
+TCGv dest = gpr_dst(ctx, a->rd, EXT_SIGN);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv src2 = gpr_src(ctx, a->rk, EXT_NONE);
+
+func(dest, src2, src1, tsz);
+gen_set_gpr(a->rd, dest, EXT_SIGN);
+
+return true;
+}
+
+TRANS(crc_w_b_w, gen_crc, gen_helper_crc32, tcg_constant_tl(1))
+TRANS(crc_w_h_w, gen_crc, gen_helper_crc32, tcg_constant_tl(2))
+TRANS(crc_w_w_w, gen_crc, gen_helper_crc32, tcg_constant_tl(4))
+TRANS(crc_w_d_w, gen_crc, gen_helper_crc32, tcg_constant_tl(8))
+TRANS(crcc_w_b_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(1))
+TRANS(crcc_w_h_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(2))
+TRANS(crcc_w_w_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(4))
+TRANS(crcc_w_d_w, gen_crc, gen_helper_crc32c, tcg_constant_tl(8))
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index 8d247aa68c..98774dbddb 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -17,6 +17,7 @@
 imm
 _i  rd imm
rd rj
+_jkrj rk
   rd rj rk
 _i rd rj imm
 _r_i hint rj imm
@@ -28,6 +29,7 @@
 #
 @i15     . imm:15
 @rr     . . rj:5 rd:5
+@rr_jk  . rk:5 rj:5 ._jk
 @rrr     . rk:5 rj:5 rd:5
 @r_i20   ... imm:s20 rd:5_i
 @rr_ui5     . imm:5 rj:5 rd:5_i
@@ -237,3 +239,20 @@ ammax_db_wu 0011 1111 0 . . .
@rrr
 ammax_db_du 0011 1111 1 . . .@rrr
 ammin_db_wu 0011 1111 00010 . . .@rrr
 ammin_db_du 0011 1111 00011 . . .@rrr
+
+#
+# Fixed point extra instruction
+#
+crc_w_b_w    0010 01000 . . .@rrr
+crc_w_h_w    0010 01001 . . .@rrr
+crc_w_w_w    0010 01010 . . .@rrr
+crc_w_d_w    0010 01011 . . .@rrr
+crcc_w_b_w   0010 01100 . . .@rrr
+crcc_w_h_w   0010 01101 . . .@rrr
+crcc_w_w_w   0010 01110 . . .@rrr
+cr

[PATCH v2 28/43] target/loongarch: Add other core instructions support

2022-04-25 Thread Xiaojuan Yang
This includes:
-CACOP
-LDDIR
-LDPTE
-ERTN
-DBCL
-IDLE

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
---
 target/loongarch/disas.c  | 17 
 target/loongarch/helper.h |  5 +
 .../insn_trans/trans_privileged.c.inc | 65 +
 target/loongarch/insns.decode | 11 +++
 target/loongarch/internals.h  |  5 +
 target/loongarch/op_helper.c  | 36 +++
 target/loongarch/tlb_helper.c | 93 +++
 7 files changed, 232 insertions(+)

diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 8e9a6443b7..ce71105ee3 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -308,6 +308,17 @@ static void output_i_rr(DisasContext *ctx, arg_i_rr *a, 
const char *mnemonic)
 output(ctx, mnemonic, "%d, r%d, r%d", a->imm, a->rj, a->rk);
 }
 
+static void output_cop_r_i(DisasContext *ctx, arg_cop_r_i *a,
+   const char *mnemonic)
+{
+output(ctx, mnemonic, "%d, r%d, %d", a->cop, a->rj, a->imm);
+}
+
+static void output_j_i(DisasContext *ctx, arg_j_i *a, const char *mnemonic)
+{
+output(ctx, mnemonic, "r%d, %d", a->rj, a->imm);
+}
+
 #define INSN(insn, type)\
 static bool trans_##insn(DisasContext *ctx, arg_##type * a) \
 {   \
@@ -635,6 +646,12 @@ INSN(tlbfill,  empty)
 INSN(tlbclr,   empty)
 INSN(tlbflush, empty)
 INSN(invtlb,   i_rr)
+INSN(cacop,cop_r_i)
+INSN(lddir,rr_i)
+INSN(ldpte,j_i)
+INSN(ertn, empty)
+INSN(idle, i)
+INSN(dbcl, i)
 
 #define output_fcmp(C, PREFIX, SUFFIX) 
\
 {  
\
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index b092ca75fe..626fc32e1e 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -121,3 +121,8 @@ DEF_HELPER_2(invtlb_all_g, void, env, i32)
 DEF_HELPER_2(invtlb_all_asid, void, env, tl)
 DEF_HELPER_3(invtlb_page_asid, void, env, tl, tl)
 DEF_HELPER_3(invtlb_page_asid_or_g, void, env, tl, tl)
+
+DEF_HELPER_4(lddir, tl, env, tl, tl, i32)
+DEF_HELPER_4(ldpte, void, env, tl, tl, i32)
+DEF_HELPER_1(ertn, void, env)
+DEF_HELPER_1(idle, void, env)
diff --git a/target/loongarch/insn_trans/trans_privileged.c.inc 
b/target/loongarch/insn_trans/trans_privileged.c.inc
index 0363d1fda4..afadd68e2b 100644
--- a/target/loongarch/insn_trans/trans_privileged.c.inc
+++ b/target/loongarch/insn_trans/trans_privileged.c.inc
@@ -393,3 +393,68 @@ static bool trans_invtlb(DisasContext *ctx, arg_invtlb *a)
 ctx->base.is_jmp = DISAS_STOP;
 return true;
 }
+
+static bool trans_cacop(DisasContext *ctx, arg_cacop *a)
+{
+/* Treat the cacop as a nop */
+if (check_plv(ctx)) {
+return false;
+}
+return true;
+}
+
+static bool trans_ldpte(DisasContext *ctx, arg_ldpte *a)
+{
+TCGv_i32 mem_idx = tcg_constant_i32(ctx->mem_idx);
+TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
+
+if (check_plv(ctx)) {
+return false;
+}
+gen_helper_ldpte(cpu_env, src1, tcg_constant_tl(a->imm), mem_idx);
+return true;
+}
+
+static bool trans_lddir(DisasContext *ctx, arg_lddir *a)
+{
+TCGv_i32 mem_idx = tcg_constant_i32(ctx->mem_idx);
+TCGv src = gpr_src(ctx, a->rj, EXT_NONE);
+TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
+
+if (check_plv(ctx)) {
+return false;
+}
+gen_helper_lddir(dest, cpu_env, src, tcg_constant_tl(a->imm), mem_idx);
+return true;
+}
+
+static bool trans_ertn(DisasContext *ctx, arg_ertn *a)
+{
+if (check_plv(ctx)) {
+return false;
+}
+gen_helper_ertn(cpu_env);
+ctx->base.is_jmp = DISAS_EXIT;
+return true;
+}
+
+static bool trans_dbcl(DisasContext *ctx, arg_dbcl *a)
+{
+if (check_plv(ctx)) {
+return false;
+}
+generate_exception(ctx, EXCCODE_DBP);
+return true;
+}
+
+static bool trans_idle(DisasContext *ctx, arg_idle *a)
+{
+if (check_plv(ctx)) {
+return false;
+}
+
+tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next + 4);
+gen_helper_idle(cpu_env);
+ctx->base.is_jmp = DISAS_NORETURN;
+return true;
+}
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index f8ed11d83e..ebd3d505fb 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -49,6 +49,8 @@
 _csr   rd rj csr
 
 _rr imm rj rk
+_r_i  cop rj imm
+_i  rj imm
 
 #
 # Formats
@@ -60,6 +62,7 @@
 @r_i20   ... imm:s20 rd:5_i
 @rr_ui5     . imm:5 rj:5 rd:5_i
 @rr_ui6   imm:6 rj:5 rd:5_i
+@rr_ui8  ..   imm:8

[PATCH v2 30/43] hw/loongarch: Add support loongson3 virt machine type.

2022-04-25 Thread Xiaojuan Yang
Emulate a 3A5000 board use the new loongarch instruction.
3A5000 belongs to the Loongson3 series processors.
The board consists of a 3A5000 cpu model and the virt
bridge. The host 3A5000 board is really complicated and
contains many functions.Now for the tcg softmmu mode
only part functions are emulated.

More detailed info you can see
https://github.com/loongson/LoongArch-Documentation

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 MAINTAINERS   |  4 +
 .../devices/loongarch64-softmmu/default.mak   |  3 +
 configs/targets/loongarch64-softmmu.mak   |  3 +
 hw/Kconfig|  1 +
 hw/loongarch/Kconfig  |  4 +
 hw/loongarch/loongson3.c  | 89 +++
 hw/loongarch/meson.build  |  4 +
 hw/meson.build|  1 +
 include/exec/poison.h |  2 +
 include/hw/loongarch/virt.h   | 31 +++
 include/sysemu/arch_init.h|  1 +
 qapi/machine.json |  2 +-
 target/Kconfig|  1 +
 target/loongarch/Kconfig  |  2 +
 target/loongarch/cpu.c|  2 +
 15 files changed, 149 insertions(+), 1 deletion(-)
 create mode 100644 configs/devices/loongarch64-softmmu/default.mak
 create mode 100644 configs/targets/loongarch64-softmmu.mak
 create mode 100644 hw/loongarch/Kconfig
 create mode 100644 hw/loongarch/loongson3.c
 create mode 100644 hw/loongarch/meson.build
 create mode 100644 include/hw/loongarch/virt.h
 create mode 100644 target/loongarch/Kconfig

diff --git a/MAINTAINERS b/MAINTAINERS
index 6361c24b3a..69f4f6e60b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1130,6 +1130,10 @@ M: Xiaojuan Yang 
 M: Song Gao 
 S: Maintained
 F: docs/system/loongarch/loongson3.rst
+F: configs/targets/loongarch64-softmmu.mak
+F: configs/devices/loongarch64-softmmu/default.mak
+F: hw/loongarch/
+F: include/hw/loongarch/virt.h
 
 M68K Machines
 -
diff --git a/configs/devices/loongarch64-softmmu/default.mak 
b/configs/devices/loongarch64-softmmu/default.mak
new file mode 100644
index 00..928bc117ef
--- /dev/null
+++ b/configs/devices/loongarch64-softmmu/default.mak
@@ -0,0 +1,3 @@
+# Default configuration for loongarch64-softmmu
+
+CONFIG_LOONGARCH_VIRT=y
diff --git a/configs/targets/loongarch64-softmmu.mak 
b/configs/targets/loongarch64-softmmu.mak
new file mode 100644
index 00..666154022f
--- /dev/null
+++ b/configs/targets/loongarch64-softmmu.mak
@@ -0,0 +1,3 @@
+TARGET_ARCH=loongarch64
+TARGET_BASE_ARCH=loongarch
+TARGET_SUPPORTS_MTTCG=y
diff --git a/hw/Kconfig b/hw/Kconfig
index ad20cce0a9..f71b2155ed 100644
--- a/hw/Kconfig
+++ b/hw/Kconfig
@@ -49,6 +49,7 @@ source avr/Kconfig
 source cris/Kconfig
 source hppa/Kconfig
 source i386/Kconfig
+source loongarch/Kconfig
 source m68k/Kconfig
 source microblaze/Kconfig
 source mips/Kconfig
diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
new file mode 100644
index 00..13e8501897
--- /dev/null
+++ b/hw/loongarch/Kconfig
@@ -0,0 +1,4 @@
+config LOONGARCH_VIRT
+bool
+select PCI
+select PCI_EXPRESS_GENERIC_BRIDGE
diff --git a/hw/loongarch/loongson3.c b/hw/loongarch/loongson3.c
new file mode 100644
index 00..a80ce8d383
--- /dev/null
+++ b/hw/loongarch/loongson3.c
@@ -0,0 +1,89 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU loongson 3a5000 develop board emulation
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "qemu/datadir.h"
+#include "qapi/error.h"
+#include "hw/boards.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/qtest.h"
+#include "sysemu/runstate.h"
+#include "sysemu/reset.h"
+#include "sysemu/rtc.h"
+#include "hw/loongarch/virt.h"
+#include "exec/address-spaces.h"
+#include "target/loongarch/cpu.h"
+
+static void loongarch_init(MachineState *machine)
+{
+const char *cpu_model = machine->cpu_type;
+ram_addr_t offset = 0;
+ram_addr_t ram_size = machine->ram_size;
+uint64_t highram_size = 0;
+MemoryRegion *address_space_mem = get_system_memory();
+LoongArchMachineState *lams = LOONGARCH_MACHINE(machine);
+int i;
+
+if (!cpu_model) {
+cpu_model = LOONGARCH_CPU_TYPE_NAME("Loongson-3A5000");
+}
+
+if (!strstr(cpu_model, "Loongson-3A5000")) {
+error_report("LoongArch/TCG needs cpu type Loongson-3A5000");
+exit(1);
+}
+
+/* Init CPUs */
+for (i = 0; i < machine->smp.cpus; i++) {
+cpu_create(machine->cpu_type);
+}
+
+/* Add memory region */
+memory_region_init_alias(>lowmem, NULL, "loongarch.lowram",
+

[PATCH v2 31/43] hw/loongarch: Add LoongArch ipi interrupt support(IPI)

2022-04-25 Thread Xiaojuan Yang
This patch realize the IPI interrupt controller.

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 MAINTAINERS |   2 +
 hw/intc/Kconfig |   3 +
 hw/intc/loongarch_ipi.c | 166 
 hw/intc/meson.build |   1 +
 hw/intc/trace-events|   4 +
 hw/loongarch/Kconfig|   1 +
 include/hw/intc/loongarch_ipi.h |  50 ++
 include/hw/loongarch/virt.h |   2 +
 8 files changed, 229 insertions(+)
 create mode 100644 hw/intc/loongarch_ipi.c
 create mode 100644 include/hw/intc/loongarch_ipi.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 69f4f6e60b..c9ba2cc858 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1134,6 +1134,8 @@ F: configs/targets/loongarch64-softmmu.mak
 F: configs/devices/loongarch64-softmmu/default.mak
 F: hw/loongarch/
 F: include/hw/loongarch/virt.h
+F: include/hw/intc/loongarch_*.h
+F: hw/intc/loongarch_*.c
 
 M68K Machines
 -
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
index a7cf301eab..6c7e82da64 100644
--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -84,3 +84,6 @@ config GOLDFISH_PIC
 
 config M68K_IRQC
 bool
+
+config LOONGARCH_IPI
+bool
diff --git a/hw/intc/loongarch_ipi.c b/hw/intc/loongarch_ipi.c
new file mode 100644
index 00..053d74ec70
--- /dev/null
+++ b/hw/intc/loongarch_ipi.c
@@ -0,0 +1,166 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch ipi interrupt support
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/intc/loongarch_ipi.h"
+#include "hw/irq.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "exec/address-spaces.h"
+#include "hw/loongarch/virt.h"
+#include "migration/vmstate.h"
+#include "trace.h"
+
+static uint64_t loongarch_ipi_readl(void *opaque, hwaddr addr, unsigned size)
+{
+IPICore *s = opaque;
+uint64_t ret = 0;
+int index = 0;
+
+addr &= 0xff;
+switch (addr) {
+case CORE_STATUS_OFF:
+ret = s->status;
+break;
+case CORE_EN_OFF:
+ret = s->en;
+break;
+case CORE_SET_OFF:
+ret = 0;
+break;
+case CORE_CLEAR_OFF:
+ret = 0;
+break;
+case CORE_BUF_20 ... CORE_BUF_38 + 4:
+index = (addr - CORE_BUF_20) >> 2;
+ret = s->buf[index];
+break;
+default:
+qemu_log_mask(LOG_UNIMP, "invalid read: %x", (uint32_t)addr);
+break;
+}
+
+trace_loongarch_ipi_read(size, (uint64_t)addr, ret);
+return ret;
+}
+
+static void loongarch_ipi_writel(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
+{
+IPICore *s = opaque;
+int index = 0;
+
+addr &= 0xff;
+trace_loongarch_ipi_write(size, (uint64_t)addr, val);
+switch (addr) {
+case CORE_STATUS_OFF:
+qemu_log_mask(LOG_GUEST_ERROR, "can not be written");
+break;
+case CORE_EN_OFF:
+s->en = val;
+break;
+case CORE_SET_OFF:
+s->status |= val;
+if (s->status != 0 && (s->status & s->en) != 0) {
+qemu_irq_raise(s->irq);
+}
+break;
+case CORE_CLEAR_OFF:
+s->status &= ~val;
+if (s->status == 0 && s->en != 0) {
+qemu_irq_lower(s->irq);
+}
+break;
+case CORE_BUF_20 ... CORE_BUF_38 + 4:
+index = (addr - CORE_BUF_20) >> 2;
+s->buf[index] = val;
+break;
+default:
+qemu_log_mask(LOG_UNIMP, "invalid write: %x", (uint32_t)addr);
+break;
+}
+}
+
+static const MemoryRegionOps loongarch_ipi_ops = {
+.read = loongarch_ipi_readl,
+.write = loongarch_ipi_writel,
+.impl.min_access_size = 4,
+.impl.max_access_size = 4,
+.valid.min_access_size = 4,
+.valid.max_access_size = 8,
+.endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void loongarch_ipi_init(Object *obj)
+{
+LoongArchIPI *s = LOONGARCH_IPI(obj);
+SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+int cpu;
+LoongArchMachineState *lams = LOONGARCH_MACHINE(qdev_get_machine());
+
+for (cpu = 0; cpu < MAX_IPI_CORE_NUM; cpu++) {
+/* There are two ways to access IPI: iocsr memory and system memory */
+memory_region_init_io(>ipi_iocsr_mem[cpu], obj, _ipi_ops,
+>ipi_core[cpu], "loongarch_ipi_iocsr", 
0x100);
+sysbus_init_mmio(sbd, >ipi_iocsr_mem[cpu]);
+
+memory_region_init_io(>ipi_system_mem[cpu], obj, _ipi_ops,
+  >ipi_core[cpu], "loongarch_ipi", 0x100);
+sysbus_init_mmio(sbd, >ipi_system_mem[cpu]);
+
+qdev_init_gpio_out(DEVICE(obj), >ipi_core[cpu].irq, 

[PATCH v2 25/43] target/loongarch: Add LoongArch CSR instruction

2022-04-25 Thread Xiaojuan Yang
This includes:
- CSRRD
- CSRWR
- CSRXCHG

Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
---
 target/loongarch/csr_helper.c |  87 ++
 target/loongarch/disas.c  |  95 +++
 target/loongarch/helper.h |   8 +
 .../insn_trans/trans_privileged.c.inc | 258 ++
 target/loongarch/insns.decode |  13 +
 target/loongarch/meson.build  |   1 +
 target/loongarch/translate.c  |  11 +-
 7 files changed, 472 insertions(+), 1 deletion(-)
 create mode 100644 target/loongarch/csr_helper.c
 create mode 100644 target/loongarch/insn_trans/trans_privileged.c.inc

diff --git a/target/loongarch/csr_helper.c b/target/loongarch/csr_helper.c
new file mode 100644
index 00..739cf4d1ec
--- /dev/null
+++ b/target/loongarch/csr_helper.c
@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * LoongArch emulation helpers for CSRs
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/main-loop.h"
+#include "cpu.h"
+#include "internals.h"
+#include "qemu/host-utils.h"
+#include "exec/helper-proto.h"
+#include "exec/exec-all.h"
+#include "exec/cpu_ldst.h"
+#include "hw/irq.h"
+#include "cpu-csr.h"
+#include "tcg/tcg-ldst.h"
+
+target_ulong helper_csrrd_pgd(CPULoongArchState *env)
+{
+int64_t v;
+
+if (env->CSR_TLBRERA & 0x1) {
+v = env->CSR_TLBRBADV;
+} else {
+v = env->CSR_BADV;
+}
+
+if ((v >> 63) & 0x1) {
+v = env->CSR_PGDH;
+} else {
+v = env->CSR_PGDL;
+}
+
+return v;
+}
+
+target_ulong helper_csrrd_tval(CPULoongArchState *env)
+{
+LoongArchCPU *cpu = LOONGARCH_CPU(env_cpu(env));
+
+return cpu_loongarch_get_constant_timer_ticks(cpu);
+}
+
+target_ulong helper_csrwr_estat(CPULoongArchState *env, target_ulong val)
+{
+int64_t old_v = env->CSR_ESTAT;
+
+/* Only IS[1:0] can be written */
+env->CSR_ESTAT = deposit64(env->CSR_ESTAT, 0, 2, val);
+
+return old_v;
+}
+
+target_ulong helper_csrwr_asid(CPULoongArchState *env, target_ulong val)
+{
+int64_t old_v = env->CSR_ASID;
+
+/* Only ASID filed of CSR_ASID can be written */
+env->CSR_ASID = deposit64(env->CSR_ASID, 0, 10, val);
+if (old_v != env->CSR_ASID) {
+tlb_flush(env_cpu(env));
+}
+return old_v;
+}
+
+target_ulong helper_csrwr_tcfg(CPULoongArchState *env, target_ulong val)
+{
+LoongArchCPU *cpu = LOONGARCH_CPU(env_cpu(env));
+int64_t old_v = env->CSR_TCFG;
+
+cpu_loongarch_store_constant_timer_config(cpu, val);
+
+return old_v;
+}
+
+target_ulong helper_csrwr_ticlr(CPULoongArchState *env, target_ulong val)
+{
+LoongArchCPU *cpu = LOONGARCH_CPU(env_cpu(env));
+int64_t old_v = 0;
+
+if (val & 0x1) {
+loongarch_cpu_set_irq(cpu, IRQ_TIMER, 0);
+}
+return old_v;
+}
diff --git a/target/loongarch/disas.c b/target/loongarch/disas.c
index 9454ebb8e9..c76b82dfdf 100644
--- a/target/loongarch/disas.c
+++ b/target/loongarch/disas.c
@@ -8,6 +8,7 @@
 #include "qemu/osdep.h"
 #include "disas/dis-asm.h"
 #include "qemu/bitops.h"
+#include "cpu-csr.h"
 
 typedef struct {
 disassemble_info *info;
@@ -25,6 +26,84 @@ static inline int shl_2(DisasContext *ctx, int x)
 return x << 2;
 }
 
+#define CSR_NAME(REG) \
+[LOONGARCH_CSR_##REG] = (#REG)
+
+static const char * const csr_names[] = {
+CSR_NAME(CRMD),
+CSR_NAME(PRMD),
+CSR_NAME(EUEN),
+CSR_NAME(MISC),
+CSR_NAME(ECFG),
+CSR_NAME(ESTAT),
+CSR_NAME(ERA),
+CSR_NAME(BADV),
+CSR_NAME(BADI),
+CSR_NAME(EENTRY),
+CSR_NAME(TLBIDX),
+CSR_NAME(TLBEHI),
+CSR_NAME(TLBELO0),
+CSR_NAME(TLBELO1),
+CSR_NAME(ASID),
+CSR_NAME(PGDL),
+CSR_NAME(PGDH),
+CSR_NAME(PGD),
+CSR_NAME(PWCL),
+CSR_NAME(PWCH),
+CSR_NAME(STLBPS),
+CSR_NAME(RVACFG),
+CSR_NAME(CPUID),
+CSR_NAME(PRCFG1),
+CSR_NAME(PRCFG2),
+CSR_NAME(PRCFG3),
+CSR_NAME(SAVE(0)),
+CSR_NAME(SAVE(1)),
+CSR_NAME(SAVE(2)),
+CSR_NAME(SAVE(3)),
+CSR_NAME(SAVE(4)),
+CSR_NAME(SAVE(5)),
+CSR_NAME(SAVE(6)),
+CSR_NAME(SAVE(7)),
+CSR_NAME(SAVE(8)),
+CSR_NAME(SAVE(9)),
+CSR_NAME(SAVE(10)),
+CSR_NAME(SAVE(11)),
+CSR_NAME(SAVE(12)),
+CSR_NAME(SAVE(13)),
+CSR_NAME(SAVE(14)),
+CSR_NAME(SAVE(15)),
+CSR_NAME(TID),
+CSR_NAME(TCFG),
+CSR_NAME(TVAL),
+CSR_NAME(CNTC),
+CSR_NAME(TICLR),
+CSR_NAME(LLBCTL),
+CSR_NAME(IMPCTL1),
+CSR_NAME(IMPCTL2),
+CSR_NAME(TLBRENTRY),
+CSR_NAME(TLBRBADV),
+CSR_NAME(TLBRERA),
+CSR_NAME(TLBRSAVE),
+CSR_NAME(TLBRELO0),
+CSR_NAME(TLBRELO1),
+CSR_NAME(TLBREHI),
+CSR_NAME(TLBRPRMD),
+

[PATCH v2 24/43] target/loongarch: Add constant timer support

2022-04-25 Thread Xiaojuan Yang
Signed-off-by: Xiaojuan Yang 
Signed-off-by: Song Gao 
Reviewed-by: Richard Henderson 
---
 target/loongarch/constant_timer.c | 64 +++
 target/loongarch/cpu.c|  2 +
 target/loongarch/cpu.h|  4 ++
 target/loongarch/internals.h  |  6 +++
 target/loongarch/meson.build  |  1 +
 5 files changed, 77 insertions(+)
 create mode 100644 target/loongarch/constant_timer.c

diff --git a/target/loongarch/constant_timer.c 
b/target/loongarch/constant_timer.c
new file mode 100644
index 00..1851f53fd6
--- /dev/null
+++ b/target/loongarch/constant_timer.c
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * QEMU LoongArch constant timer support
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/timer.h"
+#include "cpu.h"
+#include "internals.h"
+#include "cpu-csr.h"
+
+#define TIMER_PERIOD10 /* 10 ns period for 100 MHz frequency */
+#define CONSTANT_TIMER_TICK_MASK0xfffcUL
+#define CONSTANT_TIMER_ENABLE   0x1UL
+
+uint64_t cpu_loongarch_get_constant_timer_counter(LoongArchCPU *cpu)
+{
+return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / TIMER_PERIOD;
+}
+
+uint64_t cpu_loongarch_get_constant_timer_ticks(LoongArchCPU *cpu)
+{
+uint64_t now, expire;
+
+now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+expire = timer_expire_time_ns(>timer);
+
+return (expire - now) / TIMER_PERIOD;
+}
+
+void cpu_loongarch_store_constant_timer_config(LoongArchCPU *cpu,
+   uint64_t value)
+{
+CPULoongArchState *env = >env;
+uint64_t now, next;
+
+env->CSR_TCFG = value;
+if (value & CONSTANT_TIMER_ENABLE) {
+now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+next = now + (value & CONSTANT_TIMER_TICK_MASK) * TIMER_PERIOD;
+timer_mod(>timer, next);
+} else {
+timer_del(>timer);
+}
+}
+
+void loongarch_constant_timer_cb(void *opaque)
+{
+LoongArchCPU *cpu  = opaque;
+CPULoongArchState *env = >env;
+uint64_t now, next;
+
+if (FIELD_EX64(env->CSR_TCFG, CSR_TCFG, PERIODIC)) {
+now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+next = now + (env->CSR_TCFG & CONSTANT_TIMER_TICK_MASK) * TIMER_PERIOD;
+timer_mod(>timer, next);
+} else {
+env->CSR_TCFG = FIELD_DP64(env->CSR_TCFG, CSR_TCFG, EN, 0);
+}
+
+loongarch_cpu_set_irq(opaque, IRQ_TIMER, 1);
+}
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index f7c102dfc5..6d6216a846 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -489,6 +489,8 @@ static void loongarch_cpu_init(Object *obj)
 
 cpu_set_cpustate_pointers(cpu);
 qdev_init_gpio_in(DEVICE(cpu), loongarch_cpu_set_irq, N_IRQS);
+timer_init_ns(>timer, QEMU_CLOCK_VIRTUAL,
+  _constant_timer_cb, cpu);
 }
 
 static ObjectClass *loongarch_cpu_class_by_name(const char *cpu_model)
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index ea50b26eba..e907fe3c51 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -11,6 +11,7 @@
 #include "exec/cpu-defs.h"
 #include "fpu/softfloat-types.h"
 #include "hw/registerfields.h"
+#include "qemu/timer.h"
 
 #define TCG_GUEST_DEFAULT_MO (0)
 
@@ -185,6 +186,8 @@ extern const char * const regnames[32];
 extern const char * const fregnames[32];
 
 #define N_IRQS  13
+#define IRQ_TIMER   11
+#define IRQ_IPI 12
 
 #define LOONGARCH_STLB 2048 /* 2048 STLB */
 #define LOONGARCH_MTLB 64   /* 64 MTLB */
@@ -296,6 +299,7 @@ struct ArchCPU {
 
 CPUNegativeOffsetState neg;
 CPULoongArchState env;
+QEMUTimer timer;
 };
 
 #define TYPE_LOONGARCH_CPU "loongarch-cpu"
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index 69183e8bb5..4b1bcd7c0f 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -32,6 +32,12 @@ extern const VMStateDescription vmstate_loongarch_cpu;
 
 void loongarch_cpu_set_irq(void *opaque, int irq, int level);
 
+void loongarch_constant_timer_cb(void *opaque);
+uint64_t cpu_loongarch_get_constant_timer_counter(LoongArchCPU *cpu);
+uint64_t cpu_loongarch_get_constant_timer_ticks(LoongArchCPU *cpu);
+void cpu_loongarch_store_constant_timer_config(LoongArchCPU *cpu,
+   uint64_t value);
+
 bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
 MMUAccessType access_type, int mmu_idx,
 bool probe, uintptr_t retaddr);
diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
index 435cc75999..04e15ba1e3 100644
--- a/target/loongarch/meson.build
+++ b/target/loongarch/meson.build
@@ -18,6 +18,7 @@ loongarch_softmmu_ss = ss.source_set(

[PATCH v4 01/43] target/loongarch: Add README

2022-05-17 Thread Xiaojuan Yang
From: Song Gao 

This patch gives an introduction to the LoongArch target.

Signed-off-by: Song Gao 
Signed-off-by: Xiaojuan Yang 
Reviewed-by: Richard Henderson 
---
 MAINTAINERS |  6 ++
 target/loongarch/README | 10 ++
 2 files changed, 16 insertions(+)
 create mode 100644 target/loongarch/README

diff --git a/MAINTAINERS b/MAINTAINERS
index dff0200f70..fc3c02f0e5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -212,6 +212,12 @@ S: Maintained
 F: target/hppa/
 F: disas/hppa.c
 
+LoongArch TCG CPUs
+M: Song Gao 
+M: Xiaojuan Yang 
+S: Maintained
+F: target/loongarch/
+
 M68K TCG CPUs
 M: Laurent Vivier 
 S: Maintained
diff --git a/target/loongarch/README b/target/loongarch/README
new file mode 100644
index 00..de141c1a58
--- /dev/null
+++ b/target/loongarch/README
@@ -0,0 +1,10 @@
+- Introduction
+
+  LoongArch is the general processor architecture of Loongson.
+
+  The following versions of the LoongArch core are supported
+core: 3A5000
+
https://github.com/loongson/LoongArch-Documentation/releases/download/2021.08.17/LoongArch-Vol1-v1.00-EN.pdf
+
+  We can get the latest loongarch documents at 
https://github.com/loongson/LoongArch-Documentation/tags.
+
-- 
2.31.1




<    1   2   3   4   5   6   7   >