All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/31] Add Loongarch softmmu support.
@ 2021-10-19  7:34 Xiaojuan Yang
  2021-10-19  7:34 ` [PATCH 02/31] target/loongarch: Add CSR registers definition Xiaojuan Yang
                   ` (21 more replies)
  0 siblings, 22 replies; 37+ messages in thread
From: Xiaojuan Yang @ 2021-10-19  7:34 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, richard.henderson,
	laurent, peterx, f4bug, yangxiaojuan, alistair.francis, maobibo,
	gaosong, pbonzini, mark.cave-ayland, bmeng.cn, alex.bennee,
	david

This series patch add softmmu support for LoongArch.
Base on the linux-user emulation support V7 patch.

The latest kernel:
  * https://github.com/loongson/linux/tree/loongarch-next
The manual:
  * https://github.com/loongson/LoongArch-Documentation/releases/tag/2021.10.11

Patch 1 Add a readme for code download and supply binary for test.
Patch 2-3 define CSR registers and set the init/reset value.
Patch 4-5 Add cpu related functions.
Patch 6-12 Add Privileged instruction simulation used by LoongArch.
Patch 13 Emulate a virt pci host based on the LoongArch 7A1000.
Patch 14 Emulate a virt 3a5000 board different from host.
Patch 15-20 Emulate the interrupt controller used by the virt board.
Patch 21-22 Add devices used by the board.
Patch 23-25 Add bios and smbios support needed for the start.
Patch 26 Add a simple acpi model.
Patch 27 Enable mttcg mode.
Patch 28-29 Support for numa more than 4 cpus.
Patch 30-31 Add some functions for debug.

Xiaojuan Yang (31):
  target/loongarch: Upate the README for the softmmu.
  target/loongarch: Add CSR registers definition
  target/loongarch: Set default csr values.
  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 csr/iocsr instruction support
  target/loongarch: Add tlb instruction support
  target/loongarch: Add other core instructions support
  target/loongarch: Add loongarch interrupt and exception handle
  target/loongarch: Add stabletimer support
  target/loongarch: Add timer related instructions support.
  hw/pci-host: Add ls7a1000 PCIe Host bridge support for Loongson
    Platform
  hw/loongarch: Add a virt loongarch 3A5000 board support
  hw/loongarch: Add loongarch cpu interrupt support(CPUINTC)
  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
  hw/loongarch: Add some devices support for 3A5000.
  hw/loongarch: Add loongarch ls7a rtc device support
  hw/loongarch: Add default bios startup support.
  hw/loongarch: Add -kernel and -initrd options support
  hw/loongarch: Add loongarch smbios support
  hw/loongarch: Add loongarch acpi support
  hw/loongarch: Add mttcg mode support
  hw/loongarch: use machine->possible_cpus for storing possible topology
    info
  hw/loongarch: Add numa support.
  target/loongarch: Add gdb support.
  target/loongarch: Add privilege instructions diassembly

 .../devices/loongarch64-softmmu/default.mak   |   3 +
 configs/targets/loongarch64-softmmu.mak       |   4 +
 disas/loongarch.c                             | 173 ++++
 gdb-xml/loongarch-base64.xml                  |  43 +
 gdb-xml/loongarch-fpu64.xml                   |  57 ++
 hw/Kconfig                                    |   1 +
 hw/acpi/Kconfig                               |   4 +
 hw/acpi/ls7a.c                                | 351 +++++++
 hw/acpi/meson.build                           |   1 +
 hw/intc/Kconfig                               |  12 +
 hw/intc/loongarch_extioi.c                    | 589 +++++++++++
 hw/intc/loongarch_pch_msi.c                   |  74 ++
 hw/intc/loongarch_pch_pic.c                   | 284 ++++++
 hw/intc/meson.build                           |   3 +
 hw/loongarch/Kconfig                          |  22 +
 hw/loongarch/acpi-build.c                     | 661 +++++++++++++
 hw/loongarch/fw_cfg.c                         |  34 +
 hw/loongarch/fw_cfg.h                         |  16 +
 hw/loongarch/ipi.c                            | 147 +++
 hw/loongarch/loongarch_int.c                  |  62 ++
 hw/loongarch/ls3a5000_virt.c                  | 638 ++++++++++++
 hw/loongarch/meson.build                      |   7 +
 hw/meson.build                                |   1 +
 hw/pci-host/Kconfig                           |   4 +
 hw/pci-host/ls7a.c                            | 224 +++++
 hw/pci-host/meson.build                       |   1 +
 hw/rtc/Kconfig                                |   3 +
 hw/rtc/ls7a_rtc.c                             | 327 +++++++
 hw/rtc/meson.build                            |   1 +
 include/exec/poison.h                         |   2 +
 include/hw/acpi/ls7a.h                        |  54 ++
 include/hw/intc/loongarch_extioi.h            | 102 ++
 include/hw/intc/loongarch_pch_msi.h           |  17 +
 include/hw/intc/loongarch_pch_pic.h           |  50 +
 include/hw/loongarch/gipi.h                   |  38 +
 include/hw/loongarch/loongarch.h              |  79 ++
 include/hw/pci-host/ls7a.h                    |  67 ++
 include/sysemu/arch_init.h                    |   1 +
 linux-user/loongarch64/cpu_loop.c             |   3 +-
 pc-bios/loongarch_bios.bin                    | Bin 0 -> 4128768 bytes
 qapi/machine-target.json                      |   6 +-
 qapi/machine.json                             |   2 +-
 softmmu/qdev-monitor.c                        |   3 +-
 target/Kconfig                                |   1 +
 target/loongarch/Kconfig                      |   2 +
 target/loongarch/README                       | 134 +++
 target/loongarch/cpu-csr.h                    | 493 ++++++++++
 target/loongarch/cpu.c                        | 448 ++++++++-
 target/loongarch/cpu.h                        |  56 +-
 target/loongarch/csr_helper.c                 | 765 +++++++++++++++
 target/loongarch/gdbstub.c                    |  95 ++
 target/loongarch/helper.h                     |  24 +
 target/loongarch/insn_trans/trans_core.c      | 302 ++++++
 target/loongarch/insn_trans/trans_extra.c     |   2 +
 target/loongarch/insns.decode                 |  45 +
 target/loongarch/internals.h                  |  93 ++
 target/loongarch/machine.c                    | 253 +++++
 target/loongarch/meson.build                  |  10 +
 target/loongarch/op_helper.c                  |  77 +-
 target/loongarch/ramdisk                      | Bin 0 -> 3077952 bytes
 target/loongarch/stabletimer.c                |  71 ++
 target/loongarch/tlb_helper.c                 | 918 ++++++++++++++++++
 target/loongarch/translate.c                  |   8 +-
 target/loongarch/vmlinux                      | Bin 0 -> 24565536 bytes
 64 files changed, 7955 insertions(+), 13 deletions(-)
 create mode 100644 configs/devices/loongarch64-softmmu/default.mak
 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 hw/acpi/ls7a.c
 create mode 100644 hw/intc/loongarch_extioi.c
 create mode 100644 hw/intc/loongarch_pch_msi.c
 create mode 100644 hw/intc/loongarch_pch_pic.c
 create mode 100644 hw/loongarch/Kconfig
 create mode 100644 hw/loongarch/acpi-build.c
 create mode 100644 hw/loongarch/fw_cfg.c
 create mode 100644 hw/loongarch/fw_cfg.h
 create mode 100644 hw/loongarch/ipi.c
 create mode 100644 hw/loongarch/loongarch_int.c
 create mode 100644 hw/loongarch/ls3a5000_virt.c
 create mode 100644 hw/loongarch/meson.build
 create mode 100644 hw/pci-host/ls7a.c
 create mode 100644 hw/rtc/ls7a_rtc.c
 create mode 100644 include/hw/acpi/ls7a.h
 create mode 100644 include/hw/intc/loongarch_extioi.h
 create mode 100644 include/hw/intc/loongarch_pch_msi.h
 create mode 100644 include/hw/intc/loongarch_pch_pic.h
 create mode 100644 include/hw/loongarch/gipi.h
 create mode 100644 include/hw/loongarch/loongarch.h
 create mode 100644 include/hw/pci-host/ls7a.h
 create mode 100644 pc-bios/loongarch_bios.bin
 create mode 100644 target/loongarch/Kconfig
 create mode 100644 target/loongarch/cpu-csr.h
 create mode 100644 target/loongarch/csr_helper.c
 create mode 100644 target/loongarch/gdbstub.c
 create mode 100644 target/loongarch/insn_trans/trans_core.c
 create mode 100644 target/loongarch/machine.c
 create mode 100644 target/loongarch/ramdisk
 create mode 100644 target/loongarch/stabletimer.c
 create mode 100644 target/loongarch/tlb_helper.c
 create mode 100755 target/loongarch/vmlinux

-- 
2.27.0



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

* [PATCH 02/31] target/loongarch: Add CSR registers definition
  2021-10-19  7:34 [PATCH 00/31] Add Loongarch softmmu support Xiaojuan Yang
@ 2021-10-19  7:34 ` Xiaojuan Yang
  2021-10-19 19:10   ` Richard Henderson
  2021-10-19  7:34 ` [PATCH 03/31] target/loongarch: Set default csr values Xiaojuan Yang
                   ` (20 subsequent siblings)
  21 siblings, 1 reply; 37+ messages in thread
From: Xiaojuan Yang @ 2021-10-19  7:34 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, richard.henderson,
	laurent, peterx, f4bug, yangxiaojuan, alistair.francis, maobibo,
	gaosong, pbonzini, mark.cave-ayland, bmeng.cn, alex.bennee,
	david

This patch define All the CSR registers and its field.

Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 target/loongarch/cpu-csr.h | 493 +++++++++++++++++++++++++++++++++++++
 1 file changed, 493 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 0000000000..26fef4079d
--- /dev/null
+++ b/target/loongarch/cpu-csr.h
@@ -0,0 +1,493 @@
+/*
+ * QEMU LoongArch CPU CSR registers
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#ifndef LOONGARCH_CPU_CSR_H
+#define LOONGARCH_CPU_CSR_H
+
+/* Base on: kernal: arch/loongarch/include/asm/loongarch.h */
+
+/* Basic CSR register */
+#define LOONGARCH_CSR_CRMD           0x0 /* Current mode info */
+FIELD(CSR_CRMD, PLV, 0, 2)
+FIELD(CSR_CRMD, IE, 2, 1)
+FIELD(CSR_CRMD, DA, 3, 1)
+FIELD(CSR_CRMD, PG, 4, 1)
+FIELD(CSR_CRMD, DATF, 5, 2)
+FIELD(CSR_CRMD, DATM, 7, 2)
+FIELD(CSR_CRMD, WE, 9, 1)
+
+#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  EXCODE_IP                   64
+#define  EXCCODE_INT                 0
+#define  EXCCODE_PIL                 1
+#define  EXCCODE_PIS                 2
+#define  EXCCODE_PIF                 3
+#define  EXCCODE_PME                 4
+#define  EXCCODE_PNR                 5
+#define  EXCCODE_PNX                 6
+#define  EXCCODE_PPI                 7
+#define  EXCCODE_ADEF                8 /* Have different expsubcode */
+#define  EXCCODE_ADEM                8
+#define  EXCCODE_ALE                 9
+#define  EXCCODE_BCE                 10
+#define  EXCCODE_SYS                 11
+#define  EXCCODE_BRK                 12
+#define  EXCCODE_INE                 13
+#define  EXCCODE_IPE                 14
+#define  EXCCODE_FPD                 15
+#define  EXCCODE_SXD                 16
+#define  EXCCODE_ASXD                17
+#define  EXCCODE_FPE                 18 /* Have different expsubcode */
+#define  EXCCODE_VFPE                18
+#define  EXCCODE_WPEF                19 /* Have different expsubcode */
+#define  EXCCODE_WPEM                19
+#define  EXCCODE_BTD                 20
+#define  EXCCODE_BTE                 21
+
+#define LOONGARCH_CSR_ERA            0x6 /* ERA */
+
+#define LOONGARCH_CSR_BADV           0x7 /* Bad virtual address */
+
+#define LOONGARCH_CSR_BADI           0x8 /* Bad instruction */
+
+#define LOONGARCH_CSR_EENTRY         0xc /* Exception enter base address */
+
+/* TLB related CSR register */
+#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 without ASID */
+
+#define LOONGARCH_CSR_TLBELO0        0x12 /* TLB EntryLo0 */
+FIELD(CSR_TLBELO0, V, 0, 1)
+FIELD(CSR_TLBELO0, D, 1, 1)
+FIELD(CSR_TLBELO0, PLV, 2, 2)
+FIELD(CSR_TLBELO0, MAT, 4, 2)
+FIELD(CSR_TLBELO0, G, 6, 1)
+FIELD(CSR_TLBELO0, PPN, 12, 36)
+FIELD(CSR_TLBELO0, NR, 61, 1)
+FIELD(CSR_TLBELO0, NX, 62, 1)
+FIELD(CSR_TLBELO0, RPLV, 63, 1)
+
+#define LOONGARCH_CSR_TLBELO1        0x13 /* 64 TLB EntryLo1 */
+FIELD(CSR_TLBELO1, V, 0, 1)
+FIELD(CSR_TLBELO1, D, 1, 1)
+FIELD(CSR_TLBELO1, PLV, 2, 2)
+FIELD(CSR_TLBELO1, MAT, 4, 2)
+FIELD(CSR_TLBELO1, G, 6, 1)
+FIELD(CSR_TLBELO1, PPN, 12, 36)
+FIELD(CSR_TLBELO1, NR, 61, 1)
+FIELD(CSR_TLBELO1, NX, 62, 1)
+FIELD(CSR_TLBELO1, RPLV, 63, 1)
+
+#define LOONGARCH_CSR_ASID           0x18 /* ASID */
+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_PGD            0x1b /* Page table base */
+
+#define LOONGARCH_CSR_PWCL           0x1c /* PWCl */
+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)
+
+#define LOONGARCH_CSR_PWCH           0x1d /* PWCh */
+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 /* 64 */
+
+#define LOONGARCH_CSR_RVACFG         0x1f
+
+/* Config CSR registers */
+#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)
+
+/* Kscratch registers */
+#define LOONGARCH_CSR_KS0            0x30
+#define LOONGARCH_CSR_KS1            0x31
+#define LOONGARCH_CSR_KS2            0x32
+#define LOONGARCH_CSR_KS3            0x33
+#define LOONGARCH_CSR_KS4            0x34
+#define LOONGARCH_CSR_KS5            0x35
+#define LOONGARCH_CSR_KS6            0x36
+#define LOONGARCH_CSR_KS7            0x37
+#define LOONGARCH_CSR_KS8            0x38
+
+/* Timer registers */
+#define LOONGARCH_CSR_TMID           0x40 /* 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_TINTCLR        0x44 /* Timer interrupt clear */
+
+/* LLBCTL register */
+#define LOONGARCH_CSR_LLBCTL         0x60 /* LLBit control */
+
+/* Implement dependent */
+#define LOONGARCH_CSR_IMPCTL1        0x80 /* Loongarch config1 */
+
+#define LOONGARCH_CSR_IMPCTL2        0x81 /* Loongarch config2*/
+
+/* TLB Refill registers */
+#define LOONGARCH_CSR_TLBRENTRY      0x88 /* TLB refill exception address */
+#define LOONGARCH_CSR_TLBRBADV       0x89 /* TLB refill badvaddr */
+#define LOONGARCH_CSR_TLBRERA        0x8a /* TLB refill ERA */
+#define LOONGARCH_CSR_TLBRSAVE       0x8b /* KScratch for TLB refill */
+#define LOONGARCH_CSR_TLBRELO0       0x8c /* TLB refill entrylo0 */
+#define LOONGARCH_CSR_TLBRELO1       0x8d /* TLB refill entrylo1 */
+#define LOONGARCH_CSR_TLBREHI        0x8e /* TLB refill entryhi */
+#define LOONGARCH_CSR_TLBRPRMD       0x8f /* TLB refill mode info */
+FIELD(CSR_TLBRPRMD, PPLV, 0, 2)
+FIELD(CSR_TLBRPRMD, PIE, 2, 1)
+FIELD(CSR_TLBRPRMD, PWE, 4, 1)
+
+/* Machine Error registers */
+#define LOONGARCH_CSR_MERRCTL        0x90 /* ERRCTL */
+#define LOONGARCH_CSR_MERRINFO       0x91
+#define LOONGARCH_CSR_MERRINFO1      0x92
+#define LOONGARCH_CSR_MERRENT        0x93 /* MError exception base */
+#define LOONGARCH_CSR_MERRERA        0x94 /* MError exception PC */
+#define LOONGARCH_CSR_MERRSAVE       0x95 /* KScratch for error exception */
+
+#define LOONGARCH_CSR_CTAG           0x98 /* TagLo + TagHi */
+
+/* Direct map windows */
+#define LOONGARCH_CSR_DMWIN0         0x180 /* 64 direct map win0: MEM & IF */
+#define LOONGARCH_CSR_DMWIN1         0x181 /* 64 direct map win1: MEM & IF */
+#define LOONGARCH_CSR_DMWIN2         0x182 /* 64 direct map win2: MEM */
+#define LOONGARCH_CSR_DMWIN3         0x183 /* 64 direct map win3: MEM */
+#define  CSR_DMW_BASE_SH             48
+#define dmwin_va2pa(va) \
+    (va & (((unsigned long)1 << CSR_DMW_BASE_SH) - 1))
+
+/* Performance Counter registers */
+#define LOONGARCH_CSR_PERFCTRL0      0x200 /* 32 perf event 0 config */
+#define LOONGARCH_CSR_PERFCNTR0      0x201 /* 64 perf event 0 count value */
+#define LOONGARCH_CSR_PERFCTRL1      0x202 /* 32 perf event 1 config */
+#define LOONGARCH_CSR_PERFCNTR1      0x203 /* 64 perf event 1 count value */
+#define LOONGARCH_CSR_PERFCTRL2      0x204 /* 32 perf event 2 config */
+#define LOONGARCH_CSR_PERFCNTR2      0x205 /* 64 perf event 2 count value */
+#define LOONGARCH_CSR_PERFCTRL3      0x206 /* 32 perf event 3 config */
+#define LOONGARCH_CSR_PERFCNTR3      0x207 /* 64 perf event 3 count value */
+
+/* Debug registers */
+#define LOONGARCH_CSR_MWPC           0x300 /* data breakpoint config */
+#define LOONGARCH_CSR_MWPS           0x301 /* data breakpoint status */
+
+#define LOONGARCH_CSR_DB0ADDR        0x310 /* data breakpoint 0 address */
+#define LOONGARCH_CSR_DB0MASK        0x311 /* data breakpoint 0 mask */
+#define LOONGARCH_CSR_DB0CTL         0x312 /* data breakpoint 0 control */
+#define LOONGARCH_CSR_DB0ASID        0x313 /* data breakpoint 0 asid */
+
+#define LOONGARCH_CSR_DB1ADDR        0x318 /* data breakpoint 1 address */
+#define LOONGARCH_CSR_DB1MASK        0x319 /* data breakpoint 1 mask */
+#define LOONGARCH_CSR_DB1CTL         0x31a /* data breakpoint 1 control */
+#define LOONGARCH_CSR_DB1ASID        0x31b /* data breakpoint 1 asid */
+
+#define LOONGARCH_CSR_DB2ADDR        0x320 /* data breakpoint 2 address */
+#define LOONGARCH_CSR_DB2MASK        0x321 /* data breakpoint 2 mask */
+#define LOONGARCH_CSR_DB2CTL         0x322 /* data breakpoint 2 control */
+#define LOONGARCH_CSR_DB2ASID        0x323 /* data breakpoint 2 asid */
+
+#define LOONGARCH_CSR_DB3ADDR        0x328 /* data breakpoint 3 address */
+#define LOONGARCH_CSR_DB3MASK        0x329 /* data breakpoint 3 mask */
+#define LOONGARCH_CSR_DB3CTL         0x32a /* data breakpoint 3 control */
+#define LOONGARCH_CSR_DB3ASID        0x32b /* data breakpoint 3 asid */
+
+#define LOONGARCH_CSR_DB4ADDR        0x330 /* data breakpoint 4 address */
+#define LOONGARCH_CSR_DB4MASK        0x331 /* data breakpoint 4 maks */
+#define LOONGARCH_CSR_DB4CTL         0x332 /* data breakpoint 4 control */
+#define LOONGARCH_CSR_DB4ASID        0x333 /* data breakpoint 4 asid */
+
+#define LOONGARCH_CSR_DB5ADDR        0x338 /* data breakpoint 5 address */
+#define LOONGARCH_CSR_DB5MASK        0x339 /* data breakpoint 5 mask */
+#define LOONGARCH_CSR_DB5CTL         0x33a /* data breakpoint 5 control */
+#define LOONGARCH_CSR_DB5ASID        0x33b /* data breakpoint 5 asid */
+
+#define LOONGARCH_CSR_DB6ADDR        0x340 /* data breakpoint 6 address */
+#define LOONGARCH_CSR_DB6MASK        0x341 /* data breakpoint 6 mask */
+#define LOONGARCH_CSR_DB6CTL         0x342 /* data breakpoint 6 control */
+#define LOONGARCH_CSR_DB6ASID        0x343 /* data breakpoint 6 asid */
+
+#define LOONGARCH_CSR_DB7ADDR        0x348 /* data breakpoint 7 address */
+#define LOONGARCH_CSR_DB7MASK        0x349 /* data breakpoint 7 mask */
+#define LOONGARCH_CSR_DB7CTL         0x34a /* data breakpoint 7 control */
+#define LOONGARCH_CSR_DB7ASID        0x34b /* data breakpoint 7 asid */
+
+#define LOONGARCH_CSR_FWPC           0x380 /* instruction breakpoint config */
+#define LOONGARCH_CSR_FWPS           0x381 /* instruction breakpoint status */
+
+#define LOONGARCH_CSR_IB0ADDR        0x390 /* inst breakpoint 0 address */
+#define LOONGARCH_CSR_IB0MASK        0x391 /* inst breakpoint 0 mask */
+#define LOONGARCH_CSR_IB0CTL         0x392 /* inst breakpoint 0 control */
+#define LOONGARCH_CSR_IB0ASID        0x393 /* inst breakpoint 0 asid */
+
+#define LOONGARCH_CSR_IB1ADDR        0x398 /* inst breakpoint 1 address */
+#define LOONGARCH_CSR_IB1MASK        0x399 /* inst breakpoint 1 mask */
+#define LOONGARCH_CSR_IB1CTL         0x39a /* inst breakpoint 1 control */
+#define LOONGARCH_CSR_IB1ASID        0x39b /* inst breakpoint 1 asid */
+
+#define LOONGARCH_CSR_IB2ADDR        0x3a0 /* inst breakpoint 2 address */
+#define LOONGARCH_CSR_IB2MASK        0x3a1 /* inst breakpoint 2 mask */
+#define LOONGARCH_CSR_IB2CTL         0x3a2 /* inst breakpoint 2 control */
+#define LOONGARCH_CSR_IB2ASID        0x3a3 /* inst breakpoint 2 asid */
+
+#define LOONGARCH_CSR_IB3ADDR        0x3a8 /* inst breakpoint 3 address */
+#define LOONGARCH_CSR_IB3MASK        0x3a9 /* inst breakpoint 3 mask */
+#define LOONGARCH_CSR_IB3CTL         0x3aa /* inst breakpoint 3 control */
+#define LOONGARCH_CSR_IB3ASID        0x3ab /* inst breakpoint 3 asid */
+
+#define LOONGARCH_CSR_IB4ADDR        0x3b0 /* inst breakpoint 4 address */
+#define LOONGARCH_CSR_IB4MASK        0x3b1 /* inst breakpoint 4 mask */
+#define LOONGARCH_CSR_IB4CTL         0x3b2 /* inst breakpoint 4 control */
+#define LOONGARCH_CSR_IB4ASID        0x3b3 /* inst breakpoint 4 asid */
+
+#define LOONGARCH_CSR_IB5ADDR        0x3b8 /* inst breakpoint 5 address */
+#define LOONGARCH_CSR_IB5MASK        0x3b9 /* inst breakpoint 5 mask */
+#define LOONGARCH_CSR_IB5CTL         0x3ba /* inst breakpoint 5 control */
+#define LOONGARCH_CSR_IB5ASID        0x3bb /* inst breakpoint 5 asid */
+
+#define LOONGARCH_CSR_IB6ADDR        0x3c0 /* inst breakpoint 6 address */
+#define LOONGARCH_CSR_IB6MASK        0x3c1 /* inst breakpoint 6 mask */
+#define LOONGARCH_CSR_IB6CTL         0x3c2 /* inst breakpoint 6 control */
+#define LOONGARCH_CSR_IB6ASID        0x3c3 /* inst breakpoint 6 asid */
+
+#define LOONGARCH_CSR_IB7ADDR        0x3c8 /* inst breakpoint 7 address */
+#define LOONGARCH_CSR_IB7MASK        0x3c9 /* inst breakpoint 7 mask */
+#define LOONGARCH_CSR_IB7CTL         0x3ca /* inst breakpoint 7 control */
+#define LOONGARCH_CSR_IB7ASID        0x3cb /* inst breakpoint 7 asid */
+
+#define LOONGARCH_CSR_DBG            0x500 /* debug config */
+FIELD(CSR_DBG, DST, 0, 1)
+FIELD(CSR_DBG, DREV, 1, 7)
+FIELD(CSR_DBG, DEI, 8, 1)
+FIELD(CSR_DBG, DCL, 9, 1)
+FIELD(CSR_DBG, DFW, 10, 1)
+FIELD(CSR_DBG, DMW, 11, 1)
+FIELD(CSR_DBG, ECODE, 16, 6)
+
+#define LOONGARCH_CSR_DERA           0x501 /* Debug era */
+#define LOONGARCH_CSR_DESAVE         0x502 /* Debug save */
+
+#define LOONGARCH_PAGE_HUGE          0x40
+#define LOONGARCH_HUGE_GLOBAL        0x1000
+#define LOONGARCH_HUGE_GLOBAL_SH     12
+
+/*
+ * All Possible CSR registers used by tcg
+ *
+ * default value  in target/loongarch/cpu.c
+ *
+ * This macro will be used only in:
+ *  > target/loongarch/cpu.h:CPULoongArchState
+ *
+ * during translate:
+ *  > helper_csr_rdq()
+ *  > helper_csr_wrq()
+ *  > helper_csr_xchgq()
+ *  > helper_csr_xchgq_r0()
+ */
+#define CPU_LOONGARCH_CSR    \
+    uint64_t CSR_CRMD;       \
+    uint64_t CSR_PRMD;       \
+    uint64_t CSR_EUEN;       \
+    uint64_t CSR_MISC;       \
+    uint64_t CSR_ECFG;       \
+    uint64_t CSR_ESTAT;      \
+    uint64_t CSR_ERA;        \
+    uint64_t CSR_BADV;       \
+    uint64_t CSR_BADI;       \
+    uint64_t CSR_EENTRY;     \
+    uint64_t CSR_TLBIDX;     \
+    uint64_t CSR_TLBEHI;     \
+    uint64_t CSR_TLBELO0;    \
+    uint64_t CSR_TLBELO1;    \
+    uint64_t CSR_ASID;       \
+    uint64_t CSR_PGDL;       \
+    uint64_t CSR_PGDH;       \
+    uint64_t CSR_PGD;        \
+    uint64_t CSR_PWCL;       \
+    uint64_t CSR_PWCH;       \
+    uint64_t CSR_STLBPS;     \
+    uint64_t CSR_RVACFG;     \
+    uint64_t CSR_CPUID;      \
+    uint64_t CSR_PRCFG1;     \
+    uint64_t CSR_PRCFG2;     \
+    uint64_t CSR_PRCFG3;     \
+    uint64_t CSR_KS0;        \
+    uint64_t CSR_KS1;        \
+    uint64_t CSR_KS2;        \
+    uint64_t CSR_KS3;        \
+    uint64_t CSR_KS4;        \
+    uint64_t CSR_KS5;        \
+    uint64_t CSR_KS6;        \
+    uint64_t CSR_KS7;        \
+    uint64_t CSR_KS8;        \
+    uint64_t CSR_TMID;       \
+    uint64_t CSR_TCFG;       \
+    uint64_t CSR_TVAL;       \
+    uint64_t CSR_CNTC;       \
+    uint64_t CSR_TINTCLR;    \
+    uint64_t CSR_LLBCTL;     \
+    uint64_t CSR_IMPCTL1;    \
+    uint64_t CSR_IMPCTL2;    \
+    uint64_t CSR_TLBRENTRY;  \
+    uint64_t CSR_TLBRBADV;   \
+    uint64_t CSR_TLBRERA;    \
+    uint64_t CSR_TLBRSAVE;   \
+    uint64_t CSR_TLBRELO0;   \
+    uint64_t CSR_TLBRELO1;   \
+    uint64_t CSR_TLBREHI;    \
+    uint64_t CSR_TLBRPRMD;   \
+    uint64_t CSR_MERRCTL;    \
+    uint64_t CSR_MERRINFO;   \
+    uint64_t CSR_MERRINFO1;  \
+    uint64_t CSR_MERRENT;    \
+    uint64_t CSR_MERRERA;    \
+    uint64_t CSR_MERRSAVE;   \
+    uint64_t CSR_CTAG;       \
+    uint64_t CSR_MCSR0;      \
+    uint64_t CSR_MCSR1;      \
+    uint64_t CSR_MCSR2;      \
+    uint64_t CSR_MCSR3;      \
+    uint64_t CSR_MCSR8;      \
+    uint64_t CSR_MCSR9;      \
+    uint64_t CSR_MCSR10;     \
+    uint64_t CSR_MCSR24;     \
+    uint64_t CSR_UCAWIN;     \
+    uint64_t CSR_UCAWIN0_LO; \
+    uint64_t CSR_UCAWIN0_HI; \
+    uint64_t CSR_UCAWIN1_LO; \
+    uint64_t CSR_UCAWIN1_HI; \
+    uint64_t CSR_UCAWIN2_LO; \
+    uint64_t CSR_UCAWIN2_HI; \
+    uint64_t CSR_UCAWIN3_LO; \
+    uint64_t CSR_UCAWIN3_HI; \
+    uint64_t CSR_DMWIN0;     \
+    uint64_t CSR_DMWIN1;     \
+    uint64_t CSR_DMWIN2;     \
+    uint64_t CSR_DMWIN3;     \
+    uint64_t CSR_PERFCTRL0;  \
+    uint64_t CSR_PERFCNTR0;  \
+    uint64_t CSR_PERFCTRL1;  \
+    uint64_t CSR_PERFCNTR1;  \
+    uint64_t CSR_PERFCTRL2;  \
+    uint64_t CSR_PERFCNTR2;  \
+    uint64_t CSR_PERFCTRL3;  \
+    uint64_t CSR_PERFCNTR3;  \
+    uint64_t CSR_MWPC;       \
+    uint64_t CSR_MWPS;       \
+    uint64_t CSR_DB0ADDR;    \
+    uint64_t CSR_DB0MASK;    \
+    uint64_t CSR_DB0CTL;     \
+    uint64_t CSR_DB0ASID;    \
+    uint64_t CSR_DB1ADDR;    \
+    uint64_t CSR_DB1MASK;    \
+    uint64_t CSR_DB1CTL;     \
+    uint64_t CSR_DB1ASID;    \
+    uint64_t CSR_DB2ADDR;    \
+    uint64_t CSR_DB2MASK;    \
+    uint64_t CSR_DB2CTL;     \
+    uint64_t CSR_DB2ASID;    \
+    uint64_t CSR_DB3ADDR;    \
+    uint64_t CSR_DB3MASK;    \
+    uint64_t CSR_DB3CTL;     \
+    uint64_t CSR_DB3ASID;    \
+    uint64_t CSR_FWPC;       \
+    uint64_t CSR_FWPS;       \
+    uint64_t CSR_IB0ADDR;    \
+    uint64_t CSR_IB0MASK;    \
+    uint64_t CSR_IB0CTL;     \
+    uint64_t CSR_IB0ASID;    \
+    uint64_t CSR_IB1ADDR;    \
+    uint64_t CSR_IB1MASK;    \
+    uint64_t CSR_IB1CTL;     \
+    uint64_t CSR_IB1ASID;    \
+    uint64_t CSR_IB2ADDR;    \
+    uint64_t CSR_IB2MASK;    \
+    uint64_t CSR_IB2CTL;     \
+    uint64_t CSR_IB2ASID;    \
+    uint64_t CSR_IB3ADDR;    \
+    uint64_t CSR_IB3MASK;    \
+    uint64_t CSR_IB3CTL;     \
+    uint64_t CSR_IB3ASID;    \
+    uint64_t CSR_IB4ADDR;    \
+    uint64_t CSR_IB4MASK;    \
+    uint64_t CSR_IB4CTL;     \
+    uint64_t CSR_IB4ASID;    \
+    uint64_t CSR_IB5ADDR;    \
+    uint64_t CSR_IB5MASK;    \
+    uint64_t CSR_IB5CTL;     \
+    uint64_t CSR_IB5ASID;    \
+    uint64_t CSR_IB6ADDR;    \
+    uint64_t CSR_IB6MASK;    \
+    uint64_t CSR_IB6CTL;     \
+    uint64_t CSR_IB6ASID;    \
+    uint64_t CSR_IB7ADDR;    \
+    uint64_t CSR_IB7MASK;    \
+    uint64_t CSR_IB7CTL;     \
+    uint64_t CSR_IB7ASID;    \
+    uint64_t CSR_DBG;      \
+    uint64_t CSR_DERA;       \
+    uint64_t CSR_DESAVE;     \
+
+#endif /* LOONGARCH_CPU_CSR_H */
-- 
2.27.0



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

* [PATCH 03/31] target/loongarch: Set default csr values.
  2021-10-19  7:34 [PATCH 00/31] Add Loongarch softmmu support Xiaojuan Yang
  2021-10-19  7:34 ` [PATCH 02/31] target/loongarch: Add CSR registers definition Xiaojuan Yang
@ 2021-10-19  7:34 ` Xiaojuan Yang
  2021-10-19 19:18   ` Richard Henderson
  2021-10-19  7:34 ` [PATCH 04/31] target/loongarch: Add basic vmstate description of CPU Xiaojuan Yang
                   ` (19 subsequent siblings)
  21 siblings, 1 reply; 37+ messages in thread
From: Xiaojuan Yang @ 2021-10-19  7:34 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, richard.henderson,
	laurent, peterx, f4bug, yangxiaojuan, alistair.francis, maobibo,
	gaosong, pbonzini, mark.cave-ayland, bmeng.cn, alex.bennee,
	david

This patch set default csr values Mainly used for
cpu_initfn and cpu_reset.

Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 target/loongarch/cpu.c | 40 ++++++++++++++++++++++++++++++++++++++++
 target/loongarch/cpu.h |  6 ++++++
 2 files changed, 46 insertions(+)

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index e9f67cf976..57f9264c1f 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -106,6 +106,40 @@ static void set_loongarch_cpucfg(CPULoongArchState *env)
     env->cpucfg[20] = 0x60f000f;
 }
 
+#ifndef CONFIG_USER_ONLY
+static void set_loongarch_csr(CPULoongArchState *env)
+{
+    uint64_t t;
+
+    t = FIELD_DP64(0, CSR_PRCFG1, SAVE_NUM, 8);
+    t = FIELD_DP64(t, CSR_PRCFG1, TIMER_BITS, 0x2f);
+    t = FIELD_DP64(t, CSR_PRCFG1, VSMAX, 0x7);
+    env->CSR_PRCFG1 = t;
+
+    env->CSR_PRCFG2 = 0x3ffff000;
+
+    t = FIELD_DP64(0, CSR_PRCFG3, TLB_TYPE, 2);
+    t = FIELD_DP64(t, CSR_PRCFG3, MTLB_ENTRY, 0x3f);
+    t = FIELD_DP64(t, CSR_PRCFG3, STLB_WAYS, 0x7);
+    t = FIELD_DP64(t, CSR_PRCFG3, STLB_SETS, 0x8);
+    env->CSR_PRCFG3 = t;
+
+    t = FIELD_DP64(0, CSR_CRMD, PLV, 0);
+    t = FIELD_DP64(t, CSR_CRMD, IE, 0);
+    t = FIELD_DP64(t, CSR_CRMD, DA, 1);
+    t = FIELD_DP64(t, CSR_CRMD, PG, 0);
+    t = FIELD_DP64(t, CSR_CRMD, DATF, 1);
+    t = FIELD_DP64(t, CSR_CRMD, DATM, 1);
+    env->CSR_CRMD = t;
+
+    env->CSR_ECFG = FIELD_DP64(0, CSR_ECFG, VS, 7);
+    env->CSR_STLBPS  = 0xe;
+    env->CSR_RVACFG = 0x0;
+    env->CSR_ASID = 0xa0000;
+    env->CSR_ERA = env->pc;
+}
+#endif
+
 /* LoongArch CPU definitions */
 static void loongarch_3a5000_initfn(Object *obj)
 {
@@ -113,6 +147,9 @@ static void loongarch_3a5000_initfn(Object *obj)
     CPULoongArchState *env = &cpu->env;
 
     set_loongarch_cpucfg(env);
+#ifndef CONFIG_USER_ONLY
+    set_loongarch_csr(env);
+#endif
 }
 
 static void loongarch_cpu_list_entry(gpointer data, gpointer user_data)
@@ -140,6 +177,9 @@ static void loongarch_cpu_reset(DeviceState *dev)
     lacc->parent_reset(dev);
 
     set_loongarch_cpucfg(env);
+#ifndef CONFIG_USER_ONLY
+    set_loongarch_csr(env);
+#endif
     env->fcsr0_mask = 0x1f1f031f;
     env->fcsr0 = 0x0;
 
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index a4991f9481..5aa0c75ad9 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -12,6 +12,7 @@
 #include "exec/cpu-defs.h"
 #include "fpu/softfloat-types.h"
 #include "hw/registerfields.h"
+#include "cpu-csr.h"
 
 #define TCG_GUEST_DEFAULT_MO (0)
 
@@ -68,6 +69,11 @@ struct CPULoongArchState {
     uint64_t llval;
 
     uint64_t badaddr;
+
+#ifndef CONFIG_USER_ONLY
+    /* LoongArch CSR registers */
+    CPU_LOONGARCH_CSR
+#endif
 };
 
 /**
-- 
2.27.0



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

* [PATCH 04/31] target/loongarch: Add basic vmstate description of CPU.
  2021-10-19  7:34 [PATCH 00/31] Add Loongarch softmmu support Xiaojuan Yang
  2021-10-19  7:34 ` [PATCH 02/31] target/loongarch: Add CSR registers definition Xiaojuan Yang
  2021-10-19  7:34 ` [PATCH 03/31] target/loongarch: Set default csr values Xiaojuan Yang
@ 2021-10-19  7:34 ` Xiaojuan Yang
  2021-10-19 19:35   ` Richard Henderson
  2021-10-19  7:34 ` [PATCH 05/31] target/loongarch: Implement qmp_query_cpu_definitions() Xiaojuan Yang
                   ` (18 subsequent siblings)
  21 siblings, 1 reply; 37+ messages in thread
From: Xiaojuan Yang @ 2021-10-19  7:34 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, richard.henderson,
	laurent, peterx, f4bug, yangxiaojuan, alistair.francis, maobibo,
	gaosong, pbonzini, mark.cave-ayland, bmeng.cn, alex.bennee,
	david

This patch introduce vmstate_loongarch_cpu

Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 target/loongarch/cpu.c       |  12 +++
 target/loongarch/internals.h |   4 +
 target/loongarch/machine.c   | 155 +++++++++++++++++++++++++++++++++++
 target/loongarch/meson.build |   6 ++
 4 files changed, 177 insertions(+)
 create mode 100644 target/loongarch/machine.c

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 57f9264c1f..14352fb139 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -13,6 +13,7 @@
 #include "sysemu/qtest.h"
 #include "exec/exec-all.h"
 #include "qapi/qapi-commands-machine-target.h"
+#include "migration/vmstate.h"
 #include "cpu.h"
 #include "internals.h"
 #include "fpu/softfloat-helpers.h"
@@ -260,6 +261,14 @@ void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags)
     }
 }
 
+#ifndef CONFIG_USER_ONLY
+#include "hw/core/sysemu-cpu-ops.h"
+
+static const struct SysemuCPUOps loongarch_sysemu_ops = {
+    .legacy_vmsd = &vmstate_loongarch_cpu,
+};
+#endif
+
 #ifdef CONFIG_TCG
 #include "hw/core/tcg-cpu-ops.h"
 
@@ -296,6 +305,9 @@ static void loongarch_cpu_class_init(ObjectClass *c, void *data)
     cc->has_work = loongarch_cpu_has_work;
     cc->dump_state = loongarch_cpu_dump_state;
     cc->set_pc = loongarch_cpu_set_pc;
+#ifndef CONFIG_USER_ONLY
+    cc->sysemu_ops = &loongarch_sysemu_ops;
+#endif
     cc->disas_set_info = loongarch_cpu_disas_set_info;
 #ifdef CONFIG_TCG
     cc->tcg_ops = &loongarch_tcg_ops;
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index b408aed6ec..50eb58a62e 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -26,4 +26,8 @@ const char *loongarch_exception_name(int32_t exception);
 
 void restore_fp_status(CPULoongArchState *env);
 
+#ifndef CONFIG_USER_ONLY
+extern const VMStateDescription vmstate_loongarch_cpu;
+#endif
+
 #endif
diff --git a/target/loongarch/machine.c b/target/loongarch/machine.c
new file mode 100644
index 0000000000..8855e6bbf9
--- /dev/null
+++ b/target/loongarch/machine.c
@@ -0,0 +1,155 @@
+/*
+ * QEMU LoongArch machine State
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include "qemu/osdep.h"
+#include "cpu.h"
+#include "migration/cpu.h"
+
+/* LoongArch CPU state */
+
+const VMStateDescription vmstate_loongarch_cpu = {
+    .name = "cpu",
+    .version_id = 20,
+    .minimum_version_id = 20,
+    .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 CSR registers */
+        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(env.CSR_KS0, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_KS1, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_KS2, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_KS3, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_KS4, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_KS5, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_KS6, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_KS7, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_TMID, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_TCFG, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_TVAL, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_CNTC, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_TINTCLR, 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_MERRINFO, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_MERRINFO1, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_MERRENT, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_MERRERA, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_MERRSAVE, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_CTAG, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_DMWIN0, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_DMWIN1, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_DMWIN2, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_DMWIN3, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_PERFCTRL0, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_PERFCNTR0, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_PERFCTRL1, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_PERFCNTR1, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_PERFCTRL2, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_PERFCNTR2, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_PERFCTRL3, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_PERFCNTR3, LoongArchCPU),
+        /* debug */
+        VMSTATE_UINT64(env.CSR_MWPC, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_MWPS, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_DB0ADDR, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_DB0MASK, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_DB0CTL, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_DB0ASID, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_DB1ADDR, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_DB1MASK, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_DB1CTL, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_DB1ASID, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_DB2ADDR, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_DB2MASK, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_DB2CTL, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_DB2ASID, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_DB3ADDR, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_DB3MASK, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_DB3CTL, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_DB3ASID, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_FWPC, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_FWPS, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB0ADDR, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB0MASK, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB0CTL, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB0ASID, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB1ADDR, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB1MASK, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB1CTL, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB1ASID, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB2ADDR, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB2MASK, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB2CTL, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB2ASID, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB3ADDR, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB3MASK, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB3CTL, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB3ASID, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB4ADDR, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB4MASK, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB4CTL, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB4ASID, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB5ADDR, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB5MASK, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB5CTL, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB5ASID, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB6ADDR, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB6MASK, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB6CTL, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB6ASID, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB7ADDR, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB7MASK, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB7CTL, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_IB7ASID, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_DBG, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_DERA, LoongArchCPU),
+        VMSTATE_UINT64(env.CSR_DESAVE, LoongArchCPU),
+
+        VMSTATE_END_OF_LIST()
+    },
+};
diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
index 31f9e9fa5f..98bf83b499 100644
--- a/target/loongarch/meson.build
+++ b/target/loongarch/meson.build
@@ -13,6 +13,12 @@ loongarch_tcg_ss.add(files(
 ))
 loongarch_tcg_ss.add(zlib)
 
+loongarch_softmmu_ss = ss.source_set()
+loongarch_softmmu_ss.add(files(
+  'machine.c',
+))
+
 loongarch_ss.add_all(when: 'CONFIG_TCG', if_true: [loongarch_tcg_ss])
 
 target_arch += {'loongarch': loongarch_ss}
+target_softmmu_arch += {'loongarch': loongarch_softmmu_ss}
-- 
2.27.0



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

* [PATCH 05/31] target/loongarch: Implement qmp_query_cpu_definitions()
  2021-10-19  7:34 [PATCH 00/31] Add Loongarch softmmu support Xiaojuan Yang
                   ` (2 preceding siblings ...)
  2021-10-19  7:34 ` [PATCH 04/31] target/loongarch: Add basic vmstate description of CPU Xiaojuan Yang
@ 2021-10-19  7:34 ` Xiaojuan Yang
  2021-10-19 20:25   ` Richard Henderson
  2021-10-19  7:34 ` [PATCH 08/31] target/loongarch: Add tlb instruction support Xiaojuan Yang
                   ` (17 subsequent siblings)
  21 siblings, 1 reply; 37+ messages in thread
From: Xiaojuan Yang @ 2021-10-19  7:34 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, richard.henderson,
	laurent, peterx, f4bug, yangxiaojuan, alistair.francis, maobibo,
	gaosong, pbonzini, mark.cave-ayland, bmeng.cn, alex.bennee,
	david

This patch introduce qmp_query_cpu_definitions interface.

Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 qapi/machine-target.json |  6 ++++--
 target/loongarch/cpu.c   | 28 ++++++++++++++++++++++++++++
 2 files changed, 32 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 14352fb139..dcd951c377 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -336,3 +336,31 @@ 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;
+    const char *typename;
+
+    typename = object_class_get_name(oc);
+    info = g_malloc0(sizeof(*info));
+    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, &cpu_list);
+    g_slist_free(list);
+
+    return cpu_list;
+}
-- 
2.27.0



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

* [PATCH 08/31] target/loongarch: Add tlb instruction support
  2021-10-19  7:34 [PATCH 00/31] Add Loongarch softmmu support Xiaojuan Yang
                   ` (3 preceding siblings ...)
  2021-10-19  7:34 ` [PATCH 05/31] target/loongarch: Implement qmp_query_cpu_definitions() Xiaojuan Yang
@ 2021-10-19  7:34 ` Xiaojuan Yang
  2021-10-20  4:19   ` Richard Henderson
  2021-10-19  7:34 ` [PATCH 09/31] target/loongarch: Add other core instructions support Xiaojuan Yang
                   ` (16 subsequent siblings)
  21 siblings, 1 reply; 37+ messages in thread
From: Xiaojuan Yang @ 2021-10-19  7:34 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, richard.henderson,
	laurent, peterx, f4bug, yangxiaojuan, alistair.francis, maobibo,
	gaosong, pbonzini, mark.cave-ayland, bmeng.cn, alex.bennee,
	david

This includes:
- TLBSRCH
- TLBRD
- TLBWR
- TLBFILL
- TLBCLR
- TLBFLUSH
- INVTLB

Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 target/loongarch/cpu.c                   |  19 +
 target/loongarch/helper.h                |   8 +
 target/loongarch/insn_trans/trans_core.c |  54 +++
 target/loongarch/insns.decode            |  14 +
 target/loongarch/internals.h             |  18 +
 target/loongarch/tlb_helper.c            | 468 +++++++++++++++++++++++
 6 files changed, 581 insertions(+)

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index f145afb603..afd186abac 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -118,6 +118,7 @@ static void set_loongarch_cpucfg(CPULoongArchState *env)
 static void set_loongarch_csr(CPULoongArchState *env)
 {
     uint64_t t;
+    CPUState *cs = env_cpu(env);
 
     t = FIELD_DP64(0, CSR_PRCFG1, SAVE_NUM, 8);
     t = FIELD_DP64(t, CSR_PRCFG1, TIMER_BITS, 0x2f);
@@ -145,6 +146,9 @@ static void set_loongarch_csr(CPULoongArchState *env)
     env->CSR_RVACFG = 0x0;
     env->CSR_ASID = 0xa0000;
     env->CSR_ERA = env->pc;
+    env->CSR_CPUID = (cs->cpu_index & 0x1ff);
+    env->CSR_EENTRY |= (uint64_t)0x80000000;
+    env->CSR_TLBRENTRY |= (uint64_t)0x80000000;
 }
 #endif
 
@@ -265,6 +269,21 @@ void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags)
         }
     }
 
+#ifndef CONFIG_USER_ONLY
+    qemu_fprintf(f, "EUEN            0x%lx\n", env->CSR_EUEN);
+    qemu_fprintf(f, "ESTAT           0x%lx\n", env->CSR_ESTAT);
+    qemu_fprintf(f, "ERA             0x%lx\n", env->CSR_ERA);
+    qemu_fprintf(f, "CRMD            0x%lx\n", env->CSR_CRMD);
+    qemu_fprintf(f, "PRMD            0x%lx\n", env->CSR_PRMD);
+    qemu_fprintf(f, "BadVAddr        0x%lx\n", env->CSR_BADV);
+    qemu_fprintf(f, "TLB refill ERA  0x%lx\n", env->CSR_TLBRERA);
+    qemu_fprintf(f, "TLB refill BadV 0x%lx\n", env->CSR_TLBRBADV);
+    qemu_fprintf(f, "EENTRY            0x%lx\n", env->CSR_EENTRY);
+    qemu_fprintf(f, "BadInstr        0x%lx\n", env->CSR_BADI);
+    qemu_fprintf(f, "PRCFG1    0x%lx\nPRCFG2     0x%lx\nPRCFG3     0x%lx\n",
+                 env->CSR_PRCFG1, env->CSR_PRCFG3, env->CSR_PRCFG3);
+#endif
+
     /* fpr */
     if (flags & CPU_DUMP_FPU) {
         for (i = 0; i < 32; i++) {
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index d1f18d71f7..1bb1df91b3 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -102,6 +102,14 @@ DEF_HELPER_2(csr_rdq, i64, env, i64)
 DEF_HELPER_3(csr_wrq, i64, env, tl, i64)
 DEF_HELPER_4(csr_xchgq, i64, env, tl, tl, i64)
 DEF_HELPER_3(csr_xchgq_r0, void, env, tl, i64)
+
+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_4(invtlb, void, env, tl, tl, tl)
 DEF_HELPER_2(iocsr_read, i64, env, tl)
 DEF_HELPER_4(iocsr_write, void, env, tl, tl, i32)
 #endif /* !CONFIG_USER_ONLY */
diff --git a/target/loongarch/insn_trans/trans_core.c b/target/loongarch/insn_trans/trans_core.c
index b1ca2faf04..f8a72436dd 100644
--- a/target/loongarch/insn_trans/trans_core.c
+++ b/target/loongarch/insn_trans/trans_core.c
@@ -27,6 +27,13 @@ GEN_FALSE_TRANS(iocsrwr_b)
 GEN_FALSE_TRANS(iocsrwr_h)
 GEN_FALSE_TRANS(iocsrwr_w)
 GEN_FALSE_TRANS(iocsrwr_d)
+GEN_FALSE_TRANS(tlbsrch)
+GEN_FALSE_TRANS(tlbrd)
+GEN_FALSE_TRANS(tlbwr)
+GEN_FALSE_TRANS(tlbfill)
+GEN_FALSE_TRANS(tlbclr)
+GEN_FALSE_TRANS(tlbflush)
+GEN_FALSE_TRANS(invtlb)
 
 #else
 static bool trans_csrrd(DisasContext *ctx, unsigned rd, unsigned csr)
@@ -165,4 +172,51 @@ static bool trans_iocsrwr_d(DisasContext *ctx, arg_iocsrwr_d *a)
     gen_helper_iocsr_write(cpu_env, addr, val, tcg_constant_i32(oi));
     return true;
 }
+
+static bool trans_tlbsrch(DisasContext *ctx, arg_tlbsrch *a)
+{
+    gen_helper_tlbsrch(cpu_env);
+    return true;
+}
+
+static bool trans_tlbrd(DisasContext *ctx, arg_tlbrd *a)
+{
+    gen_helper_tlbrd(cpu_env);
+    return true;
+}
+
+static bool trans_tlbwr(DisasContext *ctx, arg_tlbwr *a)
+{
+    gen_helper_tlbwr(cpu_env);
+    return true;
+}
+
+static bool trans_tlbfill(DisasContext *ctx, arg_tlbfill *a)
+{
+    gen_helper_tlbfill(cpu_env);
+    return true;
+}
+
+static bool trans_tlbclr(DisasContext *ctx, arg_tlbclr *a)
+{
+    gen_helper_tlbclr(cpu_env);
+    return true;
+}
+
+static bool trans_tlbflush(DisasContext *ctx, arg_tlbflush *a)
+{
+    gen_helper_tlbflush(cpu_env);
+    return true;
+}
+
+static bool trans_invtlb(DisasContext *ctx, arg_invtlb *a)
+{
+    TCGv addr = gpr_src(ctx, a->addr, EXT_NONE);
+    TCGv info = gpr_src(ctx, a->info, EXT_NONE);
+    TCGv op = tcg_constant_tl(a->invop);
+
+    gen_helper_invtlb(cpu_env, addr, info, op);
+    return true;
+}
+
 #endif
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index a4a6df4f1a..aa40ecfca7 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -42,6 +42,9 @@
 %offs16  10:s16
 %offs    0:s10 10:16
 %csr     10:14
+%addr    10:5
+%info    5:5
+%invop   0:5
 
 #
 # Argument sets
@@ -84,6 +87,8 @@
 &fmt_offs           offs
 &fmt_rjrdoffs16     rj rd offs16
 &fmt_rdrjcsr        rd rj csr
+&fmt_empty
+&fmt_invtlb         addr info invop
 
 #
 # Formats
@@ -126,6 +131,8 @@
 @fmt_offs            .... .. ..........................       &fmt_offs           %offs
 @fmt_rjrdoffs16      .... .. ................ ..... .....     &fmt_rjrdoffs16     %rj %rd %offs16
 @fmt_rdrjcsr         .... .... .............. ..... .....     &fmt_rdrjcsr        %rd %rj %csr
+@fmt_empty           .... ........ ..... ..... ..... .....    &fmt_empty
+@fmt_invtlb          ...... ...... ..... ..... ..... .....    &fmt_invtlb         %addr %info %invop
 
 #
 # Fixed point arithmetic operation instruction
@@ -494,3 +501,10 @@ iocsrwr_b        0000 01100100 10000 00100 ..... .....    @fmt_rdrj
 iocsrwr_h        0000 01100100 10000 00101 ..... .....    @fmt_rdrj
 iocsrwr_w        0000 01100100 10000 00110 ..... .....    @fmt_rdrj
 iocsrwr_d        0000 01100100 10000 00111 ..... .....    @fmt_rdrj
+tlbsrch          0000 01100100 10000 01010 00000 00000    @fmt_empty
+tlbrd            0000 01100100 10000 01011 00000 00000    @fmt_empty
+tlbwr            0000 01100100 10000 01100 00000 00000    @fmt_empty
+tlbfill          0000 01100100 10000 01101 00000 00000    @fmt_empty
+tlbclr           0000 01100100 10000 01000 00000 00000    @fmt_empty
+tlbflush         0000 01100100 10000 01001 00000 00000    @fmt_empty
+invtlb           0000 01100100 10011 ..... ..... .....    @fmt_invtlb
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
index 1251e7f21c..916c675680 100644
--- a/target/loongarch/internals.h
+++ b/target/loongarch/internals.h
@@ -76,6 +76,14 @@ struct CPULoongArchTLBContext {
     int (*map_address)(struct CPULoongArchState *env, hwaddr *physical,
                        int *prot, target_ulong address,
                        MMUAccessType access_type);
+    void (*helper_tlbwr)(struct CPULoongArchState *env);
+    void (*helper_tlbfill)(struct CPULoongArchState *env);
+    void (*helper_tlbsrch)(struct CPULoongArchState *env);
+    void (*helper_tlbrd)(struct CPULoongArchState *env);
+    void (*helper_tlbclr)(struct CPULoongArchState *env);
+    void (*helper_tlbflush)(struct CPULoongArchState *env);
+    void (*helper_invtlb)(struct CPULoongArchState *env, target_ulong addr,
+                          target_ulong info, int op);
     struct {
         uint64_t     stlb_mask;
         uint32_t     stlb_size; /* at most : 8 * 256 = 2048 */
@@ -89,6 +97,16 @@ int ls3a5k_map_address(CPULoongArchState *env, hwaddr *physical, int *prot,
 
 void ls3a5k_mmu_init(CPULoongArchState *env);
 hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
+void ls3a5k_helper_tlbwr(CPULoongArchState *env);
+void ls3a5k_helper_tlbfill(CPULoongArchState *env);
+void ls3a5k_helper_tlbsrch(CPULoongArchState *env);
+void ls3a5k_helper_tlbrd(CPULoongArchState *env);
+void ls3a5k_helper_tlbclr(CPULoongArchState *env);
+void ls3a5k_helper_tlbflush(CPULoongArchState *env);
+void ls3a5k_invalidate_tlb(CPULoongArchState *env, int idx);
+void ls3a5k_helper_invtlb(CPULoongArchState *env, target_ulong addr,
+                          target_ulong info, int op);
+void cpu_loongarch_tlb_flush(CPULoongArchState *env);
 #endif
 
 #endif
diff --git a/target/loongarch/tlb_helper.c b/target/loongarch/tlb_helper.c
index 70105cdced..fd844d5a46 100644
--- a/target/loongarch/tlb_helper.c
+++ b/target/loongarch/tlb_helper.c
@@ -10,6 +10,7 @@
 
 #include "cpu.h"
 #include "internals.h"
+#include "exec/helper-proto.h"
 #include "exec/exec-all.h"
 #include "exec/cpu_ldst.h"
 #include "exec/log.h"
@@ -277,6 +278,428 @@ static void raise_mmu_exception(CPULoongArchState *env, target_ulong address,
     env->CSR_TLBEHI = address & (TARGET_PAGE_MASK << 1);
 }
 
+void cpu_loongarch_tlb_flush(CPULoongArchState *env)
+{
+    /* Flush qemu's TLB and discard all shadowed entries. */
+    tlb_flush(env_cpu(env));
+}
+
+static void ls3a5k_invalidate_tlb_entry(CPULoongArchState *env,
+                                        ls3a5k_tlb_t *tlb)
+{
+    CPUState *cs = env_cpu(env);
+    target_ulong    addr;
+    target_ulong    end;
+    target_ulong    mask;
+
+    mask = tlb->PageMask; /* 000...000111...111 */
+
+    if (tlb->V0) {
+        addr = tlb->VPN & ~mask;    /* xxx...xxx[0]000..0000 */
+        end = addr | (mask >> 1);   /* xxx...xxx[0]111..1111 */
+        while (addr < end) {
+            tlb_flush_page(cs, addr);
+            addr += TARGET_PAGE_SIZE;
+        }
+    }
+
+    if (tlb->V1) {
+        /* xxx...xxx[1]000..0000 */
+        addr = (tlb->VPN & ~mask) | ((mask >> 1) + 1);
+        end = addr | mask;              /* xxx...xxx[1]111..1111 */
+        while (addr - 1 < end) {
+            tlb_flush_page(cs, addr);
+            addr += TARGET_PAGE_SIZE;
+        }
+    }
+}
+
+void ls3a5k_invalidate_tlb(CPULoongArchState *env, int idx)
+{
+    ls3a5k_tlb_t *tlb;
+    uint16_t asid = FIELD_EX64(env->CSR_ASID, CSR_ASID, ASID);
+
+    tlb = &env->tlb->ls3a5k.tlb[idx];
+    if (tlb->G == 0 && tlb->ASID != asid) {
+        return;
+    }
+    ls3a5k_invalidate_tlb_entry(env, tlb);
+}
+
+static uint64_t ls3a5k_pagesize_to_mask(int pagesize)
+{
+    /* 4KB - 1GB */
+    if (pagesize < 12 && pagesize > 30) {
+        qemu_log_mask(CPU_LOG_MMU, "unsupported page size %d\n", pagesize);
+        exit(-1);
+    }
+
+    return (1 << (pagesize + 1)) - 1;
+}
+
+static void ls3a5k_fill_tlb_entry(CPULoongArchState *env,
+                                  ls3a5k_tlb_t *tlb, int is_stlb)
+{
+    uint64_t page_mask;  /* 0000...00001111...1111 */
+    uint32_t page_size;
+    uint64_t entryhi;
+    uint64_t lo0, lo1;
+
+    if (env->CSR_TLBRERA & 0x1) {
+        page_size = env->CSR_TLBREHI & 0x3f;
+        entryhi = env->CSR_TLBREHI;
+        lo0 = env->CSR_TLBRELO0;
+        lo1 = env->CSR_TLBRELO1;
+    } else {
+        page_size = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, PS);
+        entryhi = env->CSR_TLBEHI;
+        lo0 = env->CSR_TLBELO0;
+        lo1 = env->CSR_TLBELO1;
+    }
+
+    if (page_size == 0) {
+        qemu_log_mask(CPU_LOG_MMU, "page size is 0\n");
+    }
+
+    /*
+     *       15-12  11-8   7-4    3-0
+     *  4KB: 0001   1111   1111   1111 // double 4KB  mask [12:0]
+     * 16KB: 0111   1111   1111   1111 // double 16KB mask [14:0]
+     */
+    if (is_stlb) {
+        page_mask = env->tlb->ls3a5k.stlb_mask;
+    } else {
+        page_mask = ls3a5k_pagesize_to_mask(page_size);
+    }
+
+    tlb->VPN = entryhi & 0xffffffffe000 & ~page_mask;
+
+    tlb->ASID = FIELD_EX64(env->CSR_ASID, CSR_ASID, ASID);
+    tlb->NE = 0;
+    tlb->G = FIELD_EX64(env->CSR_TLBELO0, CSR_TLBELO0, G) &
+             FIELD_EX64(env->CSR_TLBELO1, CSR_TLBELO1, G);
+
+    tlb->PageMask = page_mask;
+    tlb->PageSize = page_size;
+
+    tlb->V0 = FIELD_EX64(lo0, CSR_TLBELO0, V);      /* [0] */
+    tlb->D0 = FIELD_EX64(lo0, CSR_TLBELO0, D);      /* [1] */
+    tlb->PLV0 = FIELD_EX64(lo0, CSR_TLBELO0, PLV);  /* [3:2] */
+    tlb->MAT0 = FIELD_EX64(lo0, CSR_TLBELO0, MAT);  /* [5:4] */
+    tlb->PPN0 = (lo0 & 0xfffffffff000 & ~(page_mask >> 1));
+    tlb->NR0 = FIELD_EX64(lo0, CSR_TLBELO0, NR);    /* [61] */
+    tlb->NX0 = FIELD_EX64(lo0, CSR_TLBELO0, NX);    /* [62] */
+    tlb->RPLV0 = FIELD_EX64(lo0, CSR_TLBELO0, RPLV);/* [63] */
+
+    tlb->V1 = FIELD_EX64(lo1, CSR_TLBELO1, V);      /* [0] */
+    tlb->D1 = FIELD_EX64(lo1, CSR_TLBELO1, D);      /* [1] */
+    tlb->PLV1 = FIELD_EX64(lo1, CSR_TLBELO1, PLV);  /* [3:2] */
+    tlb->MAT1 = FIELD_EX64(lo1, CSR_TLBELO1, MAT);  /* [5:4] */
+    tlb->PPN1 = (lo1 & 0xfffffffff000 & ~(page_mask >> 1));
+    tlb->NR1 = FIELD_EX64(lo1, CSR_TLBELO1, NR);    /* [61] */
+    tlb->NX1 = FIELD_EX64(lo1, CSR_TLBELO1, NX);    /* [62] */
+    tlb->RPLV1 = FIELD_EX64(lo1, CSR_TLBELO1, RPLV);/* [63] */
+}
+
+static void ls3a5k_fill_tlb(CPULoongArchState *env, int idx, bool tlbwr)
+{
+    ls3a5k_tlb_t *tlb;
+
+    tlb = &env->tlb->ls3a5k.tlb[idx];
+    if (tlbwr) {
+        if (FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, NE)) {
+            tlb->NE = 1;
+            return;
+        }
+    }
+
+    if (idx < 2048) {
+        ls3a5k_fill_tlb_entry(env, tlb, 1);
+    } else {
+        ls3a5k_fill_tlb_entry(env, tlb, 0);
+    }
+}
+
+/* return random value in [low, high] */
+static uint32_t cpu_loongarch_get_random_ls3a5k_tlb(uint32_t low, uint32_t high)
+{
+    static uint32_t seed = 5;
+    static uint32_t prev_idx;
+    uint32_t idx;
+    uint32_t nb_rand_tlb = high - low + 1;
+
+    do {
+        seed = 1103515245 * seed + 12345;
+        idx = (seed >> 16) % nb_rand_tlb + low;
+    } while (idx == prev_idx);
+    prev_idx = idx;
+
+    return idx;
+}
+
+void ls3a5k_helper_tlbsrch(CPULoongArchState *env)
+{
+    uint64_t mask;
+    uint64_t vpn;
+    uint64_t tag;
+    uint16_t asid;
+
+    int stlb_size = env->tlb->ls3a5k.stlb_size;
+    int mtlb_size = env->tlb->ls3a5k.mtlb_size;
+    int i;
+    ls3a5k_tlb_t *tlb;
+    asid = FIELD_EX64(env->CSR_ASID, CSR_ASID, ASID);
+
+    /* search MTLB + STLB */
+    for (i = 0; i < stlb_size + mtlb_size; ++i) {
+        tlb = &env->tlb->ls3a5k.tlb[i];
+        mask = tlb->PageMask;
+        vpn = env->CSR_TLBEHI & 0xffffffffe000 & ~mask;
+        tag = tlb->VPN & ~mask;
+
+        if ((tlb->G == 1 || tlb->ASID == asid) && vpn == tag && tlb->NE != 1) {
+            env->CSR_TLBIDX = FIELD_DP64(env->CSR_TLBIDX, CSR_TLBIDX,
+                                         INDEX, (i & 0xfff));
+            env->CSR_TLBIDX = FIELD_DP64(env->CSR_TLBIDX, CSR_TLBIDX,
+                                         PS, (tlb->PageSize & 0x3f));
+            return;
+        }
+    }
+
+    env->CSR_TLBIDX = FIELD_DP64(env->CSR_TLBIDX, CSR_TLBIDX, NE, 1);
+}
+
+void ls3a5k_helper_tlbrd(CPULoongArchState *env)
+{
+    ls3a5k_tlb_t    *tlb;
+    int             idx;
+    uint16_t        asid;
+
+    idx = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, INDEX);
+    tlb = &env->tlb->ls3a5k.tlb[idx];
+
+    asid = FIELD_EX64(env->CSR_ASID, CSR_ASID, ASID);
+
+    if (asid != tlb->ASID) {
+        cpu_loongarch_tlb_flush(env);
+    }
+
+    if (tlb->NE) {
+        /* invalid TLB entry */
+        env->CSR_TLBIDX = FIELD_DP64(env->CSR_TLBIDX, CSR_TLBIDX, NE, 1);
+        env->CSR_TLBEHI = 0;
+        env->CSR_TLBELO0 = 0;
+        env->CSR_TLBELO1 = 0;
+    } else {
+        /* valid TLB entry */
+        env->CSR_TLBIDX = FIELD_DP64(env->CSR_TLBIDX, CSR_TLBIDX,
+                                     INDEX, (idx & 0xfff));
+        env->CSR_TLBIDX = FIELD_DP64(env->CSR_TLBIDX, CSR_TLBIDX,
+                                     PS, (tlb->PageSize & 0x3f));
+        env->CSR_TLBEHI = tlb->VPN;
+
+        env->CSR_TLBELO0 = FIELD_DP64(0, CSR_TLBELO0, V, tlb->V0);
+        env->CSR_TLBELO0 = FIELD_DP64(env->CSR_TLBELO0, CSR_TLBELO0, D, tlb->D0);
+        env->CSR_TLBELO0 = FIELD_DP64(env->CSR_TLBELO0, CSR_TLBELO0, PLV, tlb->PLV0);
+        env->CSR_TLBELO0 = FIELD_DP64(env->CSR_TLBELO0, CSR_TLBELO0, MAT, tlb->MAT0);
+        env->CSR_TLBELO0 = FIELD_DP64(env->CSR_TLBELO0, CSR_TLBELO0, G, tlb->G);
+        env->CSR_TLBELO0 = FIELD_DP64(env->CSR_TLBELO0, CSR_TLBELO0, PPN, tlb->PPN0);
+        env->CSR_TLBELO0 = FIELD_DP64(env->CSR_TLBELO0, CSR_TLBELO0, NR, tlb->NR0);
+        env->CSR_TLBELO0 = FIELD_DP64(env->CSR_TLBELO0, CSR_TLBELO0, NX, tlb->NX0);
+        env->CSR_TLBELO0 = FIELD_DP64(env->CSR_TLBELO0, CSR_TLBELO0, RPLV, tlb->RPLV0);
+
+        env->CSR_TLBELO1 = FIELD_DP64(0, CSR_TLBELO1, V, tlb->V1);
+        env->CSR_TLBELO1 = FIELD_DP64(env->CSR_TLBELO1, CSR_TLBELO1, D, tlb->D1);
+        env->CSR_TLBELO1 = FIELD_DP64(env->CSR_TLBELO1, CSR_TLBELO1, PLV, tlb->PLV1);
+        env->CSR_TLBELO1 = FIELD_DP64(env->CSR_TLBELO1, CSR_TLBELO1, MAT, tlb->MAT1);
+        env->CSR_TLBELO1 = FIELD_DP64(env->CSR_TLBELO1, CSR_TLBELO1, G, tlb->G);
+        env->CSR_TLBELO1 = FIELD_DP64(env->CSR_TLBELO1, CSR_TLBELO1, PPN, tlb->PPN1);
+        env->CSR_TLBELO1 = FIELD_DP64(env->CSR_TLBELO1, CSR_TLBELO1, NR, tlb->NR1);
+        env->CSR_TLBELO1 = FIELD_DP64(env->CSR_TLBELO1, CSR_TLBELO1, NX, tlb->NX1);
+        env->CSR_TLBELO1 = FIELD_DP64(env->CSR_TLBELO1, CSR_TLBELO1, RPLV, tlb->RPLV1);
+
+        env->CSR_ASID  = FIELD_DP64(env->CSR_ASID, CSR_ASID, ASID, tlb->ASID);
+    }
+}
+
+void ls3a5k_helper_tlbwr(CPULoongArchState *env)
+{
+    int idx = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, INDEX); /* 0-11 */
+
+    ls3a5k_invalidate_tlb(env, idx);
+    ls3a5k_fill_tlb(env, idx, true);
+}
+
+void ls3a5k_helper_tlbfill(CPULoongArchState *env)
+{
+    uint64_t mask;
+    uint64_t address;
+    int idx;
+    int set, stlb_idx;
+
+    uint64_t entryhi;
+    uint32_t pagesize;
+
+    if (env->CSR_TLBRERA & 0x1) {
+        entryhi = env->CSR_TLBREHI & ~0x3f;
+        pagesize = env->CSR_TLBREHI & 0x3f;
+    } else {
+        entryhi = env->CSR_TLBEHI;
+        pagesize = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, PS);
+    }
+
+    uint32_t stlb_size = env->tlb->ls3a5k.stlb_size;
+    uint32_t mtlb_size = env->tlb->ls3a5k.mtlb_size;
+
+    mask = ls3a5k_pagesize_to_mask(pagesize);
+
+    if (mask == env->tlb->ls3a5k.stlb_mask &&
+        env->tlb->ls3a5k.stlb_size > 0) {
+        /* only write into STLB */
+        address = entryhi & 0xffffffffe000; /* [47:13] */
+
+        /* choose one set ramdomly */
+        set = cpu_loongarch_get_random_ls3a5k_tlb(0, 7);
+
+        /* index in one set */
+        stlb_idx = (address >> 15) & 0xff; /* [0,255] */
+
+        idx = set * 256 + stlb_idx;
+    } else {
+        /* only write into MTLB */
+        idx = cpu_loongarch_get_random_ls3a5k_tlb(
+                stlb_size, stlb_size + mtlb_size - 1);
+    }
+
+    ls3a5k_invalidate_tlb(env, idx);
+    ls3a5k_fill_tlb(env, idx, false);
+}
+
+void ls3a5k_helper_tlbclr(CPULoongArchState *env)
+{
+    int i;
+    uint16_t asid;
+    int msize, ssize, index;
+    ls3a5k_tlb_t *tlb;
+
+    asid = FIELD_EX64(env->CSR_ASID, CSR_ASID, ASID);
+    msize = env->tlb->ls3a5k.mtlb_size;
+    ssize = env->tlb->ls3a5k.stlb_size;
+    index = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, INDEX);
+
+    if (index < ssize) {
+        /* STLB. One line per operation */
+        for (i = 0; i < 8; i++) {
+            tlb = &env->tlb->ls3a5k.tlb[i * 256 + (index % 256)];
+            if (!tlb->G && tlb->ASID == asid) {
+                tlb->NE = 1;
+            }
+        }
+    } else if (index < (ssize + msize)) {
+        /* MTLB. All entries */
+        for (i = ssize; i < ssize + msize; i++) {
+            tlb = &env->tlb->ls3a5k.tlb[i];
+            if (!tlb->G && tlb->ASID == asid) {
+                tlb->NE = 1;
+            }
+        }
+    }
+
+    cpu_loongarch_tlb_flush(env);
+}
+
+void ls3a5k_helper_tlbflush(CPULoongArchState *env)
+{
+    int i;
+    int msize, ssize, index;
+
+    msize = env->tlb->ls3a5k.mtlb_size;
+    ssize = env->tlb->ls3a5k.stlb_size;
+    index = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, INDEX);
+
+    if (index < ssize) {
+        /* STLB. One line per operation */
+        for (i = 0; i < 8; i++) {
+            int idx = i * 256 + (index % 256);
+            env->tlb->ls3a5k.tlb[idx].NE = 1;
+        }
+    } else if (index < (ssize + msize)) {
+        /* MTLB. All entries */
+        for (i = ssize; i < ssize + msize; i++) {
+            env->tlb->ls3a5k.tlb[i].NE = 1;
+        }
+    }
+
+    cpu_loongarch_tlb_flush(env);
+}
+
+void ls3a5k_helper_invtlb(CPULoongArchState *env, target_ulong addr,
+                          target_ulong info, int op)
+{
+    uint32_t asid = info & 0x3ff;
+    int i;
+
+    switch (op) {
+    case 0:
+    case 1:
+        for (i = 0; i < env->tlb->nb_tlb; i++) {
+            env->tlb->ls3a5k.tlb[i].NE = 1;
+        }
+        break;
+    case 2:
+        for (i = 0; i < env->tlb->nb_tlb; i++) {
+            struct ls3a5k_tlb_t *tlb = &env->tlb->ls3a5k.tlb[i];
+
+            if (tlb->G) {
+                tlb->NE = 1;
+            }
+        }
+        break;
+    case 3:
+        for (i = 0; i < env->tlb->nb_tlb; i++) {
+            struct ls3a5k_tlb_t *tlb = &env->tlb->ls3a5k.tlb[i];
+
+            if (!tlb->G) {
+                tlb->NE = 1;
+            }
+        }
+        break;
+    case 4:
+        for (i = 0; i < env->tlb->nb_tlb; i++) {
+            struct ls3a5k_tlb_t *tlb = &env->tlb->ls3a5k.tlb[i];
+
+            if (!tlb->G && tlb->ASID == asid) {
+                tlb->NE = 1;
+            }
+        }
+        break;
+    case 5:
+        for (i = 0; i < env->tlb->nb_tlb; i++) {
+            struct ls3a5k_tlb_t *tlb = &env->tlb->ls3a5k.tlb[i];
+            uint64_t vpn = addr & 0xffffffffe000 & ~tlb->PageMask;
+
+            if (!tlb->G && tlb->ASID == asid && vpn == tlb->VPN) {
+                tlb->NE = 1;
+            }
+        }
+        break;
+    case 6:
+        for (i = 0; i < env->tlb->nb_tlb; i++) {
+            struct ls3a5k_tlb_t *tlb = &env->tlb->ls3a5k.tlb[i];
+            uint64_t vpn = addr & 0xffffffffe000 & ~tlb->PageMask;
+
+            if ((tlb->G || tlb->ASID == asid) && vpn == tlb->VPN) {
+                tlb->NE = 1;
+            }
+        }
+        break;
+    default:
+        do_raise_exception(env, EXCP_INE, GETPC());
+    }
+
+    cpu_loongarch_tlb_flush(env);
+}
+
 void ls3a5k_mmu_init(CPULoongArchState *env)
 {
     env->tlb = g_malloc0(sizeof(CPULoongArchTLBContext));
@@ -324,6 +747,51 @@ void ls3a5k_mmu_init(CPULoongArchState *env)
     }
 
     env->tlb->map_address = &ls3a5k_map_address;
+
+    /* TLB's helper functions */
+    env->tlb->helper_tlbsrch  = ls3a5k_helper_tlbsrch;
+    env->tlb->helper_tlbrd    = ls3a5k_helper_tlbrd;
+    env->tlb->helper_tlbwr    = ls3a5k_helper_tlbwr;
+    env->tlb->helper_tlbfill  = ls3a5k_helper_tlbfill;
+    env->tlb->helper_tlbclr   = ls3a5k_helper_tlbclr;
+    env->tlb->helper_tlbflush = ls3a5k_helper_tlbflush;
+    env->tlb->helper_invtlb   = ls3a5k_helper_invtlb;
+}
+
+void helper_tlbwr(CPULoongArchState *env)
+{
+    env->tlb->helper_tlbwr(env);
+}
+
+void helper_tlbfill(CPULoongArchState *env)
+{
+    env->tlb->helper_tlbfill(env);
+}
+
+void helper_tlbsrch(CPULoongArchState *env)
+{
+    env->tlb->helper_tlbsrch(env);
+}
+
+void helper_tlbrd(CPULoongArchState *env)
+{
+    env->tlb->helper_tlbrd(env);
+}
+
+void helper_tlbclr(CPULoongArchState *env)
+{
+    env->tlb->helper_tlbclr(env);
+}
+
+void helper_tlbflush(CPULoongArchState *env)
+{
+    env->tlb->helper_tlbflush(env);
+}
+
+void helper_invtlb(CPULoongArchState *env, target_ulong addr,
+                   target_ulong info, target_ulong op)
+{
+    env->tlb->helper_invtlb(env, addr, info, op);
 }
 
 bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
-- 
2.27.0



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

* [PATCH 09/31] target/loongarch: Add other core instructions support
  2021-10-19  7:34 [PATCH 00/31] Add Loongarch softmmu support Xiaojuan Yang
                   ` (4 preceding siblings ...)
  2021-10-19  7:34 ` [PATCH 08/31] target/loongarch: Add tlb instruction support Xiaojuan Yang
@ 2021-10-19  7:34 ` Xiaojuan Yang
  2021-10-20  4:45   ` Richard Henderson
  2021-10-19  7:34 ` [PATCH 10/31] target/loongarch: Add loongarch interrupt and exception handle Xiaojuan Yang
                   ` (15 subsequent siblings)
  21 siblings, 1 reply; 37+ messages in thread
From: Xiaojuan Yang @ 2021-10-19  7:34 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, richard.henderson,
	laurent, peterx, f4bug, yangxiaojuan, alistair.francis, maobibo,
	gaosong, pbonzini, mark.cave-ayland, bmeng.cn, alex.bennee,
	david

This includes:
-CACOP
-LDDIR
-LDPTE
-ERTN
-DBCL
-IDLE

Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 target/loongarch/cpu.c                   |  1 +
 target/loongarch/cpu.h                   |  5 +-
 target/loongarch/helper.h                |  4 ++
 target/loongarch/insn_trans/trans_core.c | 57 ++++++++++++++++
 target/loongarch/insns.decode            | 15 +++++
 target/loongarch/op_helper.c             | 48 ++++++++++++++
 target/loongarch/tlb_helper.c            | 83 ++++++++++++++++++++++++
 7 files changed, 212 insertions(+), 1 deletion(-)

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index afd186abac..7fa3851251 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -45,6 +45,7 @@ static const char * const excp_names[EXCP_LAST + 1] = {
     [EXCP_TLBPE] = "TLB priviledged error",
     [EXCP_TLBNX] = "TLB execute-inhibit",
     [EXCP_TLBNR] = "TLB read-inhibit",
+    [EXCP_DBP] = "debug breakpoint",
 };
 
 const char *loongarch_exception_name(int32_t exception)
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 567fc7620d..d39c618d6b 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -166,10 +166,13 @@ enum {
     EXCP_TLBPE,
     EXCP_TLBNX,
     EXCP_TLBNR,
+    EXCP_DBP,
 
-    EXCP_LAST = EXCP_TLBNR,
+    EXCP_LAST = EXCP_DBP,
 };
 
+#define CPU_INTERRUPT_WAKE CPU_INTERRUPT_TGT_INT_0
+
 #define LOONGARCH_CPU_TYPE_SUFFIX "-" TYPE_LOONGARCH_CPU
 #define LOONGARCH_CPU_TYPE_NAME(model) model LOONGARCH_CPU_TYPE_SUFFIX
 #define CPU_RESOLVING_TYPE TYPE_LOONGARCH_CPU
diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 1bb1df91b3..8544771790 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -112,4 +112,8 @@ DEF_HELPER_1(tlbflush, void, env)
 DEF_HELPER_4(invtlb, void, env, tl, tl, tl)
 DEF_HELPER_2(iocsr_read, i64, env, tl)
 DEF_HELPER_4(iocsr_write, void, env, tl, tl, i32)
+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)
 #endif /* !CONFIG_USER_ONLY */
diff --git a/target/loongarch/insn_trans/trans_core.c b/target/loongarch/insn_trans/trans_core.c
index f8a72436dd..7fa13e65b9 100644
--- a/target/loongarch/insn_trans/trans_core.c
+++ b/target/loongarch/insn_trans/trans_core.c
@@ -34,6 +34,12 @@ GEN_FALSE_TRANS(tlbfill)
 GEN_FALSE_TRANS(tlbclr)
 GEN_FALSE_TRANS(tlbflush)
 GEN_FALSE_TRANS(invtlb)
+GEN_FALSE_TRANS(cacop)
+GEN_FALSE_TRANS(ldpte)
+GEN_FALSE_TRANS(lddir)
+GEN_FALSE_TRANS(ertn)
+GEN_FALSE_TRANS(dbcl)
+GEN_FALSE_TRANS(idle)
 
 #else
 static bool trans_csrrd(DisasContext *ctx, unsigned rd, unsigned csr)
@@ -173,6 +179,11 @@ static bool trans_iocsrwr_d(DisasContext *ctx, arg_iocsrwr_d *a)
     return true;
 }
 
+static bool trans_cacop(DisasContext *ctx, arg_cacop *a)
+{
+    return false;
+}
+
 static bool trans_tlbsrch(DisasContext *ctx, arg_tlbsrch *a)
 {
     gen_helper_tlbsrch(cpu_env);
@@ -219,4 +230,50 @@ static bool trans_invtlb(DisasContext *ctx, arg_invtlb *a)
     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);
+
+    gen_helper_ldpte(cpu_env, src1, tcg_constant_tl(a->seq), 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);
+
+    gen_helper_lddir(dest, cpu_env, src, tcg_constant_tl(a->level), mem_idx);
+    return true;
+}
+
+static bool trans_ertn(DisasContext *ctx, arg_ertn *a)
+{
+    gen_helper_ertn(cpu_env);
+    ctx->base.is_jmp = DISAS_EXIT;
+    return true;
+}
+
+static bool trans_dbcl(DisasContext *ctx, arg_dbcl *a)
+{
+    /*
+     * XXX: not clear which exception should be raised
+     *      when in debug mode...
+     */
+    generate_exception(ctx, EXCP_DBP);
+    return true;
+}
+
+static bool trans_idle(DisasContext *ctx, arg_idle *a)
+{
+    ctx->base.pc_next += 4;
+    tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
+    ctx->base.pc_next -= 4;
+    gen_helper_idle(cpu_env);
+    ctx->base.is_jmp = DISAS_NORETURN;
+    return true;
+}
+
 #endif
diff --git a/target/loongarch/insns.decode b/target/loongarch/insns.decode
index aa40ecfca7..2b18b27c88 100644
--- a/target/loongarch/insns.decode
+++ b/target/loongarch/insns.decode
@@ -42,9 +42,12 @@
 %offs16  10:s16
 %offs    0:s10 10:16
 %csr     10:14
+%cop     0:5
 %addr    10:5
 %info    5:5
 %invop   0:5
+%level   10:8
+%seq     10:8
 
 #
 # Argument sets
@@ -87,8 +90,11 @@
 &fmt_offs           offs
 &fmt_rjrdoffs16     rj rd offs16
 &fmt_rdrjcsr        rd rj csr
+&fmt_coprjsi12      cop rj si12
 &fmt_empty
 &fmt_invtlb         addr info invop
+&fmt_rdrjlevel      rd rj level
+&fmt_rjseq          rj seq
 
 #
 # Formats
@@ -131,8 +137,11 @@
 @fmt_offs            .... .. ..........................       &fmt_offs           %offs
 @fmt_rjrdoffs16      .... .. ................ ..... .....     &fmt_rjrdoffs16     %rj %rd %offs16
 @fmt_rdrjcsr         .... .... .............. ..... .....     &fmt_rdrjcsr        %rd %rj %csr
+@fmt_coprjsi12       .... ...... ............ ..... .....     &fmt_coprjsi12      %cop %rj %si12
 @fmt_empty           .... ........ ..... ..... ..... .....    &fmt_empty
 @fmt_invtlb          ...... ...... ..... ..... ..... .....    &fmt_invtlb         %addr %info %invop
+@fmt_rdrjlevel       .... ........ .. ........ ..... .....    &fmt_rdrjlevel      %rd %rj %level
+@fmt_rjseq           .... ........ .. ........ ..... .....    &fmt_rjseq          %rj %seq
 
 #
 # Fixed point arithmetic operation instruction
@@ -501,6 +510,7 @@ iocsrwr_b        0000 01100100 10000 00100 ..... .....    @fmt_rdrj
 iocsrwr_h        0000 01100100 10000 00101 ..... .....    @fmt_rdrj
 iocsrwr_w        0000 01100100 10000 00110 ..... .....    @fmt_rdrj
 iocsrwr_d        0000 01100100 10000 00111 ..... .....    @fmt_rdrj
+cacop            0000 011000 ............ ..... .....     @fmt_coprjsi12
 tlbsrch          0000 01100100 10000 01010 00000 00000    @fmt_empty
 tlbrd            0000 01100100 10000 01011 00000 00000    @fmt_empty
 tlbwr            0000 01100100 10000 01100 00000 00000    @fmt_empty
@@ -508,3 +518,8 @@ tlbfill          0000 01100100 10000 01101 00000 00000    @fmt_empty
 tlbclr           0000 01100100 10000 01000 00000 00000    @fmt_empty
 tlbflush         0000 01100100 10000 01001 00000 00000    @fmt_empty
 invtlb           0000 01100100 10011 ..... ..... .....    @fmt_invtlb
+lddir            0000 01100100 00 ........ ..... .....    @fmt_rdrjlevel
+ldpte            0000 01100100 01 ........ ..... 00000    @fmt_rjseq
+ertn             0000 01100100 10000 01110 00000 00000    @fmt_empty
+idle             0000 01100100 10001 ...............      @fmt_whint
+dbcl             0000 00000010 10101 ...............      @fmt_code
diff --git a/target/loongarch/op_helper.c b/target/loongarch/op_helper.c
index c560a9be26..4547880c8f 100644
--- a/target/loongarch/op_helper.c
+++ b/target/loongarch/op_helper.c
@@ -83,3 +83,51 @@ target_ulong helper_cpucfg(CPULoongArchState *env, target_ulong rj)
 {
     return env->cpucfg[rj];
 }
+
+#ifndef CONFIG_USER_ONLY
+static inline void exception_return(CPULoongArchState *env)
+{
+    if (env->CSR_TLBRERA & 0x1) {
+        env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PLV,
+                                   FIELD_EX64(env->CSR_TLBRPRMD, CSR_TLBRPRMD, PPLV));
+        env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, IE,
+                                   FIELD_EX64(env->CSR_TLBRPRMD, CSR_TLBRPRMD, PIE));
+        /* Clear Refill flag and set pc */
+        env->CSR_TLBRERA &= (~0x1);
+        env->pc = env->CSR_TLBRERA;
+        if (qemu_loglevel_mask(CPU_LOG_INT)) {
+            qemu_log("%s: TLBRERA 0x%lx\n", __func__, env->CSR_TLBRERA);
+        }
+    } else {
+        env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PLV,
+                                   FIELD_EX64(env->CSR_PRMD, CSR_PRMD, PPLV));
+        env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, IE,
+                                   FIELD_EX64(env->CSR_PRMD, CSR_PRMD, PIE));
+        /* set pc*/
+        env->pc = env->CSR_ERA;
+        if (qemu_loglevel_mask(CPU_LOG_INT)) {
+            qemu_log("%s: ERA 0x%lx\n", __func__, env->CSR_ERA);
+        }
+    }
+}
+
+void helper_ertn(CPULoongArchState *env)
+{
+    exception_return(env);
+    env->lladdr = 1;
+}
+
+void helper_idle(CPULoongArchState *env)
+{
+    CPUState *cs = env_cpu(env);
+
+    cs->halted = 1;
+    cpu_reset_interrupt(cs, CPU_INTERRUPT_WAKE);
+    /*
+     * Last instruction in the block, PC was updated before
+     * - no need to recover PC and icount
+     */
+    do_raise_exception(env, EXCP_HLT, 0);
+}
+
+#endif /* !CONFIG_USER_ONLY */
diff --git a/target/loongarch/tlb_helper.c b/target/loongarch/tlb_helper.c
index fd844d5a46..1eea4e1dc4 100644
--- a/target/loongarch/tlb_helper.c
+++ b/target/loongarch/tlb_helper.c
@@ -833,3 +833,86 @@ bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
         do_raise_exception(env, cs->exception_index, retaddr);
     }
 }
+
+target_ulong helper_lddir(CPULoongArchState *env, target_ulong base,
+                          target_ulong level, uint32_t mem_idx)
+{
+    target_ulong badvaddr;
+    target_ulong index;
+    target_ulong vaddr;
+    int shift;
+    uint64_t dir1_base, dir1_width;
+    uint64_t dir3_base, dir3_width;
+
+    badvaddr = env->CSR_TLBRBADV;
+
+    /* 0:8B, 1:16B, 2:32B, 3:64B */
+    shift = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTEWIDTH);
+    shift = (shift + 1) * 3;
+
+    switch (level) {
+    case 1:
+        dir1_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_BASE);
+        dir1_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_WIDTH);
+        index = (badvaddr >> dir1_base) & ((1 << dir1_width) - 1);
+        break;
+    case 3:
+        dir3_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_BASE);
+        dir3_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_WIDTH);
+        index = (badvaddr >> dir3_base) & ((1 << dir3_width) - 1);
+        break;
+    default:
+        do_raise_exception(env, EXCP_INE, GETPC());
+        return 0;
+    }
+
+    vaddr = base | index << shift;
+    return cpu_ldq_mmuidx_ra(env, vaddr, mem_idx, GETPC());
+}
+
+void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd,
+                  uint32_t mem_idx)
+{
+    target_ulong vaddr;
+    target_ulong tmp0;
+    target_ulong ptindex, ptoffset0, ptoffset1;
+    target_ulong pagesize;
+    target_ulong badv;
+    int shift;
+    bool huge = base & LOONGARCH_PAGE_HUGE;
+    uint64_t ptbase = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTBASE);
+    uint64_t ptwidth = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTWIDTH);
+
+    if (huge) {
+        /* Huge Page. base is paddr */
+        tmp0 = base ^ LOONGARCH_PAGE_HUGE;
+        /* move Global bit */
+        tmp0 |= ((tmp0 & LOONGARCH_HUGE_GLOBAL)
+                 >> (LOONGARCH_HUGE_GLOBAL_SH - R_CSR_TLBELO0_G_SHIFT));
+        pagesize = ptbase + ptwidth - 1;
+        if (odd) {
+            tmp0 += (1 << pagesize);
+        }
+    } else {
+        /* 0:8B, 1:16B, 2:32B, 3:64B */
+        shift = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTEWIDTH);
+        shift = (shift + 1) * 3;
+        badv = env->CSR_TLBRBADV;
+
+        ptindex = (badv >> ptbase) & ((1 << ptwidth) - 1);
+        ptindex = ptindex & ~0x1;   /* clear bit 0 */
+        ptoffset0 = ptindex << shift;
+        ptoffset1 = (ptindex + 1) << shift;
+
+        vaddr = base | (odd ? ptoffset1 : ptoffset0);
+        tmp0 = cpu_ldq_mmuidx_ra(env, vaddr, mem_idx, GETPC());
+        pagesize = ptbase;
+    }
+    if (odd) {
+        env->CSR_TLBRELO1 = tmp0;
+    } else {
+        env->CSR_TLBRELO0 = tmp0;
+    }
+    env->CSR_TLBREHI = env->CSR_TLBREHI & (~0x3f);
+    env->CSR_TLBREHI = env->CSR_TLBREHI | pagesize;
+}
-- 
2.27.0



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

* [PATCH 10/31] target/loongarch: Add loongarch interrupt and exception handle
  2021-10-19  7:34 [PATCH 00/31] Add Loongarch softmmu support Xiaojuan Yang
                   ` (5 preceding siblings ...)
  2021-10-19  7:34 ` [PATCH 09/31] target/loongarch: Add other core instructions support Xiaojuan Yang
@ 2021-10-19  7:34 ` Xiaojuan Yang
  2021-10-20  4:59   ` Richard Henderson
  2021-10-19  7:34 ` [PATCH 11/31] target/loongarch: Add stabletimer support Xiaojuan Yang
                   ` (14 subsequent siblings)
  21 siblings, 1 reply; 37+ messages in thread
From: Xiaojuan Yang @ 2021-10-19  7:34 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, richard.henderson,
	laurent, peterx, f4bug, yangxiaojuan, alistair.francis, maobibo,
	gaosong, pbonzini, mark.cave-ayland, bmeng.cn, alex.bennee,
	david

This patch Add loongarch interrupt and exception handle.

Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 target/loongarch/cpu.c | 293 +++++++++++++++++++++++++++++++++++++++++
 target/loongarch/cpu.h |   6 +-
 2 files changed, 298 insertions(+), 1 deletion(-)

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 7fa3851251..3e3cf233db 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -45,7 +45,10 @@ static const char * const excp_names[EXCP_LAST + 1] = {
     [EXCP_TLBPE] = "TLB priviledged error",
     [EXCP_TLBNX] = "TLB execute-inhibit",
     [EXCP_TLBNR] = "TLB read-inhibit",
+    [EXCP_EXT_INTERRUPT] = "interrupt",
     [EXCP_DBP] = "debug breakpoint",
+    [EXCP_IBE] = "instruction bus error",
+    [EXCP_DBE] = "data bus error",
 };
 
 const char *loongarch_exception_name(int32_t exception)
@@ -79,6 +82,275 @@ static void loongarch_cpu_set_pc(CPUState *cs, vaddr value)
     env->pc = value;
 }
 
+#if !defined(CONFIG_USER_ONLY)
+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)
+{
+    unsigned int size = 0;
+    uint64_t vs = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, VS);
+
+    switch (vs) {
+    case 0:
+        break;
+    case 1:
+        size = 2 * 4;   /* #Insts * inst_size */
+        break;
+    case 2:
+        size = 4 * 4;
+        break;
+    case 3:
+        size = 8 * 4;
+        break;
+    case 4:
+        size = 16 * 4;
+        break;
+    case 5:
+        size = 32 * 4;
+        break;
+    case 6:
+        size = 64 * 4;
+        break;
+    case 7:
+        size = 128 * 4;
+        break;
+    default:
+        qemu_log("%s: unexpected value", __func__);
+        assert(0);
+    }
+
+    return size;
+}
+
+#define is_refill(cs, env) (((cs->exception_index == EXCP_TLBL) \
+        || (cs->exception_index == EXCP_TLBS))  \
+        && (env->error_code & EXCP_TLB_NOMATCH))
+
+static void loongarch_cpu_do_interrupt(CPUState *cs)
+{
+    LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+    CPULoongArchState *env = &cpu->env;
+    bool update_badinstr = 0;
+    int cause = -1;
+    const char *name;
+
+    if (qemu_loglevel_mask(CPU_LOG_INT)
+        && cs->exception_index != EXCP_EXT_INTERRUPT) {
+        if (cs->exception_index < 0 || cs->exception_index > EXCP_LAST) {
+            name = "unknown";
+        } else {
+            name = excp_names[cs->exception_index];
+        }
+
+        qemu_log("%s enter: pc " TARGET_FMT_lx " ERA " TARGET_FMT_lx
+                 " TLBRERA 0x%016lx" " %s exception\n", __func__,
+                 env->pc, env->CSR_ERA, env->CSR_TLBRERA, name);
+    }
+
+    switch (cs->exception_index) {
+    case EXCP_SYSCALL:
+        cause = EXCCODE_SYS;
+        update_badinstr = 1;
+        break;
+    case EXCP_BREAK:
+        cause = EXCCODE_BRK;
+        update_badinstr = 1;
+        break;
+    case EXCP_INE:
+        cause = EXCCODE_INE;
+        update_badinstr = 1;
+        break;
+    case EXCP_FPE:
+        cause = EXCCODE_FPE;
+        update_badinstr = 1;
+        break;
+    case EXCP_ADEL:
+        cause = EXCCODE_ADEF;
+        update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL);
+        break;
+    case EXCP_ADES:
+        cause = EXCCODE_ADEM;
+        update_badinstr = 1;
+        break;
+    case EXCP_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);
+        env->CSR_DERA = env->pc;
+        env->CSR_DBG = FIELD_DP64(env->CSR_DBG, CSR_DBG, DST, 1);
+        env->pc = env->exception_base + 0x480;
+        break;
+    case EXCP_EXT_INTERRUPT:
+        cause = 0;
+        break;
+    case EXCP_TLBL:
+        if (env->error_code & EXCP_INST_NOTAVAIL) {
+            cause = EXCCODE_PIF;
+        } else {
+            cause = EXCCODE_PIL;
+        }
+        update_badinstr = !(env->error_code & EXCP_INST_NOTAVAIL);
+        break;
+    case EXCP_TLBS:
+        cause = EXCCODE_PIS;
+        update_badinstr = 1;
+        break;
+    case EXCP_TLBM:
+        cause = EXCCODE_PME;
+        break;
+    case EXCP_TLBPE:
+        cause = EXCCODE_PPI;
+        break;
+    case EXCP_TLBNX:
+        cause = EXCCODE_PNX;
+        break;
+    case EXCP_TLBNR:
+        cause = EXCCODE_PNR;
+        update_badinstr = 1;
+        break;
+    case EXCP_IBE:
+        cause = EXCCODE_ADEF;
+        break;
+    case EXCP_DBE:
+        cause = EXCCODE_ADEM;
+        break;
+    default:
+        qemu_log("Error: exception(%d) '%s' has not been supported\n",
+                 cs->exception_index, excp_names[cs->exception_index]);
+        abort();
+    }
+
+    if (is_refill(cs, env)) {
+        env->CSR_TLBRERA = env->pc;
+        env->CSR_TLBRERA |= 1;
+    } else {
+        env->CSR_ERA = env->pc;
+    }
+
+    if (update_badinstr) {
+        env->CSR_BADI = cpu_ldl_code(env, env->pc);
+    }
+
+    /* save PLV and IE */
+    if (is_refill(cs, env)) {
+        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));
+    } else {
+        env->CSR_PRMD = FIELD_DP64(env->CSR_PRMD, CSR_PRMD, PPLV,
+                                   FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV));
+        env->CSR_PRMD = FIELD_DP64(env->CSR_PRMD, CSR_PRMD, PIE,
+                                   FIELD_EX64(env->CSR_CRMD, CSR_CRMD, IE));
+    }
+
+    env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PLV, 0);
+    env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, IE, 0);
+
+    uint32_t vec_size = get_vint_size(env);
+    env->pc = env->CSR_EENTRY;
+    env->pc += cause * vec_size;
+    if (is_refill(cs, env)) {
+        /* TLB Refill */
+        env->pc = env->CSR_TLBRENTRY;
+    }
+    if  (cs->exception_index == EXCP_EXT_INTERRUPT) {
+        /* Interrupt */
+        uint32_t vector = 0;
+        uint32_t pending = FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS);
+        pending &= FIELD_EX64(env->CSR_ECFG, CSR_ECFG, LIE);
+
+        /* Find the highest-priority interrupt. */
+        while (pending >>= 1) {
+            vector++;
+        }
+        env->pc = env->CSR_EENTRY + (EXCODE_IP + vector) * vec_size;
+        if (qemu_loglevel_mask(CPU_LOG_INT)) {
+            qemu_log("%s: PC " TARGET_FMT_lx " ERA " TARGET_FMT_lx
+                     " cause %d\n" "    A " TARGET_FMT_lx " D "
+                     TARGET_FMT_lx " vector = %d ExC %08lx ExS %08lx\n",
+                     __func__, env->pc, env->CSR_ERA,
+                     cause, env->CSR_BADV, env->CSR_DERA, vector,
+                     env->CSR_ECFG, env->CSR_ESTAT);
+        }
+    }
+
+    /* Excode */
+    env->CSR_ESTAT = FIELD_DP64(env->CSR_ESTAT, CSR_ESTAT, ECODE, cause);
+
+    if (qemu_loglevel_mask(CPU_LOG_INT) && cs->exception_index != EXCP_EXT_INTERRUPT) {
+        qemu_log("%s: PC " TARGET_FMT_lx " ERA 0x%08lx"  " cause %d%s\n"
+                 " ESTAT %08lx EXCFG 0x%08lx BADVA 0x%08lx BADI 0x%08lx \
+                 SYS_NUM %lu cpu %d asid 0x%lx" "\n",
+                 __func__, env->pc,
+                 is_refill(cs, env) ? env->CSR_TLBRERA : env->CSR_ERA,
+                 cause,
+                 is_refill(cs, env) ? "(refill)" : "",
+                 env->CSR_ESTAT, env->CSR_ECFG,
+                 is_refill(cs, env) ? env->CSR_TLBRBADV : env->CSR_BADV,
+                 env->CSR_BADI, env->gpr[11], cs->cpu_index,
+                 env->CSR_ASID
+         );
+    }
+    cs->exception_index = EXCP_NONE;
+}
+
+static void loongarch_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
+                                    vaddr addr, unsigned size,
+                                    MMUAccessType access_type,
+                                    int mmu_idx, MemTxAttrs attrs,
+                                    MemTxResult response, uintptr_t retaddr)
+{
+    LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+    CPULoongArchState *env = &cpu->env;
+
+    if (access_type == MMU_INST_FETCH) {
+        do_raise_exception(env, EXCP_IBE, retaddr);
+    } else {
+        do_raise_exception(env, EXCP_DBE, retaddr);
+    }
+}
+
+static bool loongarch_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
+{
+    if (interrupt_request & CPU_INTERRUPT_HARD) {
+        LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+        CPULoongArchState *env = &cpu->env;
+
+        if (cpu_loongarch_hw_interrupts_enabled(env) &&
+            cpu_loongarch_hw_interrupts_pending(env)) {
+            /* Raise it */
+            cs->exception_index = EXCP_EXT_INTERRUPT;
+            env->error_code = 0;
+            loongarch_cpu_do_interrupt(cs);
+            return true;
+        }
+    }
+    return false;
+}
+#endif
+
 #ifdef CONFIG_TCG
 static void loongarch_cpu_synchronize_from_tb(CPUState *cs,
                                               const TranslationBlock *tb)
@@ -92,7 +364,20 @@ static void loongarch_cpu_synchronize_from_tb(CPUState *cs,
 
 static bool loongarch_cpu_has_work(CPUState *cs)
 {
+#ifdef CONFIG_USER_ONLY
     return true;
+#else
+    LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+    CPULoongArchState *env = &cpu->env;
+    bool has_work = false;
+
+    if ((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
+        cpu_loongarch_hw_interrupts_pending(env)) {
+            has_work = true;
+    }
+
+    return has_work;
+#endif
 }
 
 static void set_loongarch_cpucfg(CPULoongArchState *env)
@@ -192,6 +477,7 @@ static void loongarch_cpu_reset(DeviceState *dev)
     set_loongarch_cpucfg(env);
 #ifndef CONFIG_USER_ONLY
     set_loongarch_csr(env);
+    env->pc = env->exception_base;
 #endif
     env->fcsr0_mask = 0x1f1f031f;
     env->fcsr0 = 0x0;
@@ -223,6 +509,7 @@ static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp)
 
 #ifndef CONFIG_USER_ONLY
     ls3a5k_mmu_init(env);
+    env->exception_base = 0x1C000000;
 #endif
 
     cpu_reset(cs);
@@ -330,6 +617,12 @@ static struct TCGCPUOps loongarch_tcg_ops = {
     .initialize = loongarch_translate_init,
     .synchronize_from_tb = loongarch_cpu_synchronize_from_tb,
     .tlb_fill = loongarch_cpu_tlb_fill,
+
+#if !defined(CONFIG_USER_ONLY)
+    .cpu_exec_interrupt = loongarch_cpu_exec_interrupt,
+    .do_interrupt = loongarch_cpu_do_interrupt,
+    .do_transaction_failed = loongarch_cpu_do_transaction_failed,
+#endif /* !CONFIG_USER_ONLY */
 };
 #endif /* CONFIG_TCG */
 
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index d39c618d6b..182b03fb33 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -82,6 +82,7 @@ struct CPULoongArchState {
     CPU_LOONGARCH_CSR
     CPULoongArchTLBContext *tlb;
     int error_code;
+    target_ulong exception_base;
 #endif
 };
 
@@ -166,9 +167,12 @@ enum {
     EXCP_TLBPE,
     EXCP_TLBNX,
     EXCP_TLBNR,
+    EXCP_EXT_INTERRUPT,
     EXCP_DBP,
+    EXCP_IBE,
+    EXCP_DBE,
 
-    EXCP_LAST = EXCP_DBP,
+    EXCP_LAST = EXCP_DBE,
 };
 
 #define CPU_INTERRUPT_WAKE CPU_INTERRUPT_TGT_INT_0
-- 
2.27.0



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

* [PATCH 11/31] target/loongarch: Add stabletimer support
  2021-10-19  7:34 [PATCH 00/31] Add Loongarch softmmu support Xiaojuan Yang
                   ` (6 preceding siblings ...)
  2021-10-19  7:34 ` [PATCH 10/31] target/loongarch: Add loongarch interrupt and exception handle Xiaojuan Yang
@ 2021-10-19  7:34 ` Xiaojuan Yang
  2021-10-19  7:34 ` [PATCH 12/31] target/loongarch: Add timer related instructions support Xiaojuan Yang
                   ` (13 subsequent siblings)
  21 siblings, 0 replies; 37+ messages in thread
From: Xiaojuan Yang @ 2021-10-19  7:34 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, richard.henderson,
	laurent, peterx, f4bug, yangxiaojuan, alistair.francis, maobibo,
	gaosong, pbonzini, mark.cave-ayland, bmeng.cn, alex.bennee,
	david

This patch add a stabletimer support.

Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 target/loongarch/cpu.c         |  1 +
 target/loongarch/cpu.h         | 10 +++++
 target/loongarch/csr_helper.c  | 26 +++++++++++++
 target/loongarch/meson.build   |  1 +
 target/loongarch/stabletimer.c | 71 ++++++++++++++++++++++++++++++++++
 5 files changed, 109 insertions(+)
 create mode 100644 target/loongarch/stabletimer.c

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 3e3cf233db..2886dbd642 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -435,6 +435,7 @@ static void set_loongarch_csr(CPULoongArchState *env)
     env->CSR_CPUID = (cs->cpu_index & 0x1ff);
     env->CSR_EENTRY |= (uint64_t)0x80000000;
     env->CSR_TLBRENTRY |= (uint64_t)0x80000000;
+    env->CSR_TMID = cs->cpu_index;
 }
 #endif
 
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 182b03fb33..e77517d375 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -46,6 +46,9 @@ FIELD(FCSR0, CAUSE, 24, 5)
 extern const char * const regnames[];
 extern const char * const fregnames[];
 
+#define N_IRQS      14
+#define IRQ_TIMER   11
+
 #define LOONGARCH_HFLAG_KU     0x00003 /* kernel/user mode mask   */
 #define LOONGARCH_HFLAG_UM     0x00003 /* user mode flag                     */
 #define LOONGARCH_HFLAG_KM     0x00000 /* kernel mode flag                   */
@@ -84,6 +87,8 @@ struct CPULoongArchState {
     int error_code;
     target_ulong exception_base;
 #endif
+    void *irq[N_IRQS];
+    QEMUTimer *timer; /* Internal timer */
 };
 
 /**
@@ -181,4 +186,9 @@ enum {
 #define LOONGARCH_CPU_TYPE_NAME(model) model LOONGARCH_CPU_TYPE_SUFFIX
 #define CPU_RESOLVING_TYPE TYPE_LOONGARCH_CPU
 
+void cpu_loongarch_clock_init(LoongArchCPU *cpu);
+uint64_t cpu_loongarch_get_stable_counter(CPULoongArchState *env);
+uint64_t cpu_loongarch_get_stable_timer_ticks(CPULoongArchState *env);
+void cpu_loongarch_store_stable_timer_config(CPULoongArchState *env,
+                                             uint64_t value);
 #endif /* LOONGARCH_CPU_H */
diff --git a/target/loongarch/csr_helper.c b/target/loongarch/csr_helper.c
index 9251bfa2a6..6cfb910799 100644
--- a/target/loongarch/csr_helper.c
+++ b/target/loongarch/csr_helper.c
@@ -14,6 +14,7 @@
 #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"
 
@@ -78,7 +79,12 @@ target_ulong helper_csr_rdq(CPULoongArchState *env, uint64_t csr)
     CASE_CSR_RDQ(KS7)
     CASE_CSR_RDQ(KS8)
     CASE_CSR_RDQ(TMID)
+    CASE_CSR_RDQ(TCFG)
+    case LOONGARCH_CSR_TVAL:
+        v = cpu_loongarch_get_stable_timer_ticks(env);
+        break;
     CASE_CSR_RDQ(CNTC)
+    CASE_CSR_RDQ(TINTCLR)
     CASE_CSR_RDQ(LLBCTL)
     CASE_CSR_RDQ(IMPCTL1)
     CASE_CSR_RDQ(IMPCTL2)
@@ -223,8 +229,16 @@ target_ulong helper_csr_wrq(CPULoongArchState *env, target_ulong val,
     CASE_CSR_WRQ(KS7)
     CASE_CSR_WRQ(KS8)
     CASE_CSR_WRQ(TMID)
+    case LOONGARCH_CSR_TCFG:
+        old_v = env->CSR_TCFG;
+        cpu_loongarch_store_stable_timer_config(env, val);
+        break;
     CASE_CSR_WRQ(TVAL)
     CASE_CSR_WRQ(CNTC)
+    case LOONGARCH_CSR_TINTCLR:
+        old_v = 0;
+        qemu_irq_lower(env->irq[IRQ_TIMER]);
+        break;
     CASE_CSR_WRQ(LLBCTL)
     CASE_CSR_WRQ(IMPCTL1)
     CASE_CSR_WRQ(IMPCTL2)
@@ -373,8 +387,12 @@ void helper_csr_xchgq_r0(CPULoongArchState *env, target_ulong mask, uint64_t csr
     CASE_CSR_XCHGQ(KS7)
     CASE_CSR_XCHGQ(KS8)
     CASE_CSR_XCHGQ(TMID)
+    case LOONGARCH_CSR_TCFG:
+        cpu_loongarch_store_stable_timer_config(env, env->CSR_TCFG & (~mask));
+        break;
     CASE_CSR_XCHGQ(TVAL)
     CASE_CSR_XCHGQ(CNTC)
+    CASE_CSR_XCHGQ(TINTCLR)
     CASE_CSR_XCHGQ(LLBCTL)
     CASE_CSR_XCHGQ(IMPCTL1)
     CASE_CSR_XCHGQ(IMPCTL2)
@@ -471,6 +489,7 @@ void helper_csr_xchgq_r0(CPULoongArchState *env, target_ulong mask, uint64_t csr
 target_ulong helper_csr_xchgq(CPULoongArchState *env, target_ulong val,
                               target_ulong mask, uint64_t csr)
 {
+    target_ulong tmp;
     target_ulong v = val & mask;
 
 #define CASE_CSR_XCHGQ(csr)                                 \
@@ -523,8 +542,15 @@ target_ulong helper_csr_xchgq(CPULoongArchState *env, target_ulong val,
     CASE_CSR_XCHGQ(KS7)
     CASE_CSR_XCHGQ(KS8)
     CASE_CSR_XCHGQ(TMID)
+    case LOONGARCH_CSR_TCFG:
+        val = env->CSR_TCFG;
+        tmp = val & ~mask;
+        tmp |= v;
+        cpu_loongarch_store_stable_timer_config(env, tmp);
+        break;
     CASE_CSR_XCHGQ(TVAL)
     CASE_CSR_XCHGQ(CNTC)
+    CASE_CSR_XCHGQ(TINTCLR)
     CASE_CSR_XCHGQ(LLBCTL)
     CASE_CSR_XCHGQ(IMPCTL1)
     CASE_CSR_XCHGQ(IMPCTL2)
diff --git a/target/loongarch/meson.build b/target/loongarch/meson.build
index 74f4a63d15..fd0365cffd 100644
--- a/target/loongarch/meson.build
+++ b/target/loongarch/meson.build
@@ -18,6 +18,7 @@ loongarch_softmmu_ss.add(files(
   'machine.c',
   'tlb_helper.c',
   'csr_helper.c',
+  'stabletimer.c',
 ))
 
 loongarch_ss.add_all(when: 'CONFIG_TCG', if_true: [loongarch_tcg_ss])
diff --git a/target/loongarch/stabletimer.c b/target/loongarch/stabletimer.c
new file mode 100644
index 0000000000..a3bf32a865
--- /dev/null
+++ b/target/loongarch/stabletimer.c
@@ -0,0 +1,71 @@
+/*
+ * QEMU LoongArch timer support
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include "qemu/osdep.h"
+#include "hw/irq.h"
+#include "hw/loongarch/loongarch.h"
+#include "qemu/timer.h"
+#include "cpu.h"
+
+#define TIMER_PERIOD                10 /* 10 ns period for 100 Mhz frequency */
+#define STABLETIMER_TICK_MASK       0xfffffffffffcUL
+#define STABLETIMER_ENABLE          0x1UL
+
+/* LoongArch timer */
+uint64_t cpu_loongarch_get_stable_counter(CPULoongArchState *env)
+{
+    return qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / TIMER_PERIOD;
+}
+
+uint64_t cpu_loongarch_get_stable_timer_ticks(CPULoongArchState *env)
+{
+    uint64_t now, expire;
+
+    now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+    expire = timer_expire_time_ns(env->timer);
+
+    return (expire - now) / TIMER_PERIOD;
+}
+
+void cpu_loongarch_store_stable_timer_config(CPULoongArchState *env,
+                                             uint64_t value)
+{
+    uint64_t now, next;
+
+    env->CSR_TCFG = value;
+    if (value & STABLETIMER_ENABLE) {
+        now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+        next = now + (value & STABLETIMER_TICK_MASK) * TIMER_PERIOD;
+        timer_mod(env->timer, next);
+    }
+}
+
+static void loongarch_stable_timer_cb(void *opaque)
+{
+    CPULoongArchState *env;
+    uint64_t now, next;
+
+    env = opaque;
+    if (FIELD_EX64(env->CSR_TCFG, CSR_TCFG, PERIODIC)) {
+        now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+        next = now + (env->CSR_TCFG & STABLETIMER_TICK_MASK) * TIMER_PERIOD;
+        timer_mod(env->timer, next);
+    } else {
+        env->CSR_TCFG = FIELD_DP64(env->CSR_TCFG, CSR_TCFG, EN, 0);
+    }
+
+   qemu_irq_raise(env->irq[IRQ_TIMER]);
+}
+
+void cpu_loongarch_clock_init(LoongArchCPU *cpu)
+{
+    CPULoongArchState *env = &cpu->env;
+
+    env->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
+                              &loongarch_stable_timer_cb, env);
+}
-- 
2.27.0



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

* [PATCH 12/31] target/loongarch: Add timer related instructions support.
  2021-10-19  7:34 [PATCH 00/31] Add Loongarch softmmu support Xiaojuan Yang
                   ` (7 preceding siblings ...)
  2021-10-19  7:34 ` [PATCH 11/31] target/loongarch: Add stabletimer support Xiaojuan Yang
@ 2021-10-19  7:34 ` Xiaojuan Yang
  2021-10-20  5:17   ` Richard Henderson
  2021-10-19  7:34 ` [PATCH 13/31] hw/pci-host: Add ls7a1000 PCIe Host bridge support for Loongson Platform Xiaojuan Yang
                   ` (12 subsequent siblings)
  21 siblings, 1 reply; 37+ messages in thread
From: Xiaojuan Yang @ 2021-10-19  7:34 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, richard.henderson,
	laurent, peterx, f4bug, yangxiaojuan, alistair.francis, maobibo,
	gaosong, pbonzini, mark.cave-ayland, bmeng.cn, alex.bennee,
	david

This includes:
-RDTIME{L/H}.W
-RDTIME.D

Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 target/loongarch/helper.h                 |  2 ++
 target/loongarch/insn_trans/trans_core.c  | 23 +++++++++++++++++++++
 target/loongarch/insn_trans/trans_extra.c |  2 ++
 target/loongarch/op_helper.c              | 25 +++++++++++++++++++++++
 4 files changed, 52 insertions(+)

diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
index 8544771790..b4ed62896f 100644
--- a/target/loongarch/helper.h
+++ b/target/loongarch/helper.h
@@ -116,4 +116,6 @@ 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_4(rdtime_w, void, env, tl, tl, i64)
+DEF_HELPER_3(rdtime_d, void, env, tl, tl)
 #endif /* !CONFIG_USER_ONLY */
diff --git a/target/loongarch/insn_trans/trans_core.c b/target/loongarch/insn_trans/trans_core.c
index 7fa13e65b9..24eb12b97a 100644
--- a/target/loongarch/insn_trans/trans_core.c
+++ b/target/loongarch/insn_trans/trans_core.c
@@ -276,4 +276,27 @@ static bool trans_idle(DisasContext *ctx, arg_idle *a)
     return true;
 }
 
+static bool trans_rdtimel_w(DisasContext *ctx, arg_rdtimel_w *a)
+{
+    TCGv t0 = tcg_constant_tl(a->rd);
+    TCGv t1 = tcg_constant_tl(a->rj);
+    gen_helper_rdtime_w(cpu_env, t0, t1, tcg_constant_tl(0));
+    return true;
+}
+
+static bool trans_rdtimeh_w(DisasContext *ctx, arg_rdtimeh_w *a)
+{
+    TCGv t0 = tcg_constant_tl(a->rd);
+    TCGv t1 = tcg_constant_tl(a->rj);
+    gen_helper_rdtime_w(cpu_env, t0, t1, tcg_constant_tl(1));
+    return true;
+}
+
+static bool trans_rdtime_d(DisasContext *ctx, arg_rdtime_d *a)
+{
+    TCGv t0 = tcg_constant_tl(a->rd);
+    TCGv t1 = tcg_constant_tl(a->rj);
+    gen_helper_rdtime_d(cpu_env, t0, t1);
+    return true;
+}
 #endif
diff --git a/target/loongarch/insn_trans/trans_extra.c b/target/loongarch/insn_trans/trans_extra.c
index 8da3b404f3..426b67f154 100644
--- a/target/loongarch/insn_trans/trans_extra.c
+++ b/target/loongarch/insn_trans/trans_extra.c
@@ -36,6 +36,7 @@ static bool trans_asrtgt_d(DisasContext *ctx, arg_asrtgt_d * a)
     return true;
 }
 
+#ifdef CONFIG_USER_ONLY
 static bool trans_rdtimel_w(DisasContext *ctx, arg_rdtimel_w *a)
 {
     tcg_gen_movi_tl(cpu_gpr[a->rd], 0);
@@ -53,6 +54,7 @@ static bool trans_rdtime_d(DisasContext *ctx, arg_rdtime_d *a)
     tcg_gen_movi_tl(cpu_gpr[a->rd], 0);
     return true;
 }
+#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 4547880c8f..41b1ec2f1b 100644
--- a/target/loongarch/op_helper.c
+++ b/target/loongarch/op_helper.c
@@ -130,4 +130,29 @@ void helper_idle(CPULoongArchState *env)
     do_raise_exception(env, EXCP_HLT, 0);
 }
 
+void helper_rdtime_w(CPULoongArchState *env, target_ulong rd,
+                     target_ulong rj, target_ulong high)
+{
+    if (rd) {
+        if (high) {
+            env->gpr[rd] = cpu_loongarch_get_stable_counter(env) >> 32;
+        } else {
+            env->gpr[rd] = cpu_loongarch_get_stable_counter(env) & 0xffffffff;
+        }
+    }
+    if (rj) {
+        env->gpr[rj] = env->CSR_TMID;
+    }
+}
+
+void helper_rdtime_d(CPULoongArchState *env, target_ulong rd, target_ulong rj)
+{
+    if (rd) {
+        env->gpr[rd] = cpu_loongarch_get_stable_counter(env);
+    }
+    if (rj) {
+        env->gpr[rj] = env->CSR_TMID;
+    }
+}
+
 #endif /* !CONFIG_USER_ONLY */
-- 
2.27.0



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

* [PATCH 13/31] hw/pci-host: Add ls7a1000 PCIe Host bridge support for Loongson Platform
  2021-10-19  7:34 [PATCH 00/31] Add Loongarch softmmu support Xiaojuan Yang
                   ` (8 preceding siblings ...)
  2021-10-19  7:34 ` [PATCH 12/31] target/loongarch: Add timer related instructions support Xiaojuan Yang
@ 2021-10-19  7:34 ` Xiaojuan Yang
  2021-10-19  7:35 ` [PATCH 14/31] hw/loongarch: Add a virt loongarch 3A5000 board support Xiaojuan Yang
                   ` (11 subsequent siblings)
  21 siblings, 0 replies; 37+ messages in thread
From: Xiaojuan Yang @ 2021-10-19  7:34 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, richard.henderson,
	laurent, peterx, f4bug, yangxiaojuan, alistair.francis, maobibo,
	gaosong, pbonzini, mark.cave-ayland, bmeng.cn, alex.bennee,
	david

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 we only emulate 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 <yangxiaojuan@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 hw/pci-host/Kconfig        |   4 +
 hw/pci-host/ls7a.c         | 188 +++++++++++++++++++++++++++++++++++++
 hw/pci-host/meson.build    |   1 +
 include/hw/pci-host/ls7a.h |  48 ++++++++++
 4 files changed, 241 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 0000000000..1d6d5ea35a
--- /dev/null
+++ b/hw/pci-host/ls7a.c
@@ -0,0 +1,188 @@
+/*
+ * QEMU Loongson 7A1000 North Bridge Emulation
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include "qemu/osdep.h"
+
+#include "hw/pci/pci.h"
+#include "hw/pci/pcie_host.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_PCIE",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_PCI_DEVICE(dev, 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_NATIVE_ENDIAN,
+};
+
+static void ls7a_pciehost_realize(DeviceState *dev, Error **errp)
+{
+    LS7APCIEHost *pciehost = LS7A_PCIE_HOST_BRIDGE(dev);
+    PCIExpressHost *e = PCIE_HOST_BRIDGE(dev);
+    PCIHostState *phb = PCI_HOST_BRIDGE(e);
+
+    phb->bus = pci_register_root_bus(dev, "pcie.0", NULL,
+                                     NULL, pciehost,
+                                     get_system_memory(), get_system_io(),
+                                     PCI_DEVFN(1, 0), 128, TYPE_PCIE_BUS);
+
+    memory_region_init_io(&pciehost->pci_conf, OBJECT(dev),
+                          &pci_ls7a_config_ops, phb->bus,
+                          "ls7a_pci_conf", HT1LO_PCICFG_SIZE);
+    memory_region_add_subregion(get_system_memory(), HT1LO_PCICFG_BASE,
+                                &pciehost->pci_conf);
+
+    /* Add ls7a pci-io */
+    memory_region_init_alias(&pciehost->pci_io, OBJECT(dev), "ls7a-pci-io",
+                             get_system_io(), 0, LS7A_PCI_IO_SIZE);
+    memory_region_add_subregion(get_system_memory(), LS7A_PCI_IO_BASE,
+                                &pciehost->pci_io);
+
+    pcie_host_mmcfg_update(e, true, LS_PCIECFG_BASE, LS_PCIECFG_SIZE);
+}
+
+PCIBus *ls7a_init(MachineState *machine, qemu_irq *pic)
+{
+    DeviceState *dev;
+    PCIHostState *phb;
+    LS7APCIState *pbs;
+    LS7APCIEHost *pciehost;
+    PCIDevice *pci_dev;
+    PCIExpressHost *e;
+
+    dev = qdev_new(TYPE_LS7A_PCIE_HOST_BRIDGE);
+    e = PCIE_HOST_BRIDGE(dev);
+    phb = PCI_HOST_BRIDGE(e);
+    pciehost = LS7A_PCIE_HOST_BRIDGE(dev);
+    pciehost->pic = pic;
+
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
+
+    pci_dev = pci_new(PCI_DEVFN(0, 0), TYPE_LS7A_PCIE);
+    pbs = LS7A_PCIE(pci_dev);
+    pbs->pciehost = pciehost;
+    pbs->pciehost->pci_dev = pbs;
+
+    pci_realize_and_unref(pci_dev, phb->bus, &error_fatal);
+
+    return phb->bus;
+}
+
+static void ls7a_reset(DeviceState *qdev)
+{
+    uint64_t wmask;
+    wmask = ~(-1);
+    PCIDevice *dev = PCI_DEVICE(qdev);
+
+    pci_set_word(dev->config + PCI_STATUS, 0x0010);
+    pci_set_word(dev->wmask + PCI_STATUS, wmask & 0xffff);
+    pci_set_word(dev->cmask + PCI_STATUS, 0xffff);
+    pci_set_byte(dev->config + PCI_HEADER_TYPE, 0x1);
+    pci_set_byte(dev->wmask + PCI_HEADER_TYPE, wmask & 0xff);
+    pci_set_byte(dev->cmask + PCI_HEADER_TYPE, 0xff);
+    pci_set_word(dev->config + PCI_SUBSYSTEM_VENDOR_ID, 0x0014);
+    pci_set_word(dev->wmask + PCI_SUBSYSTEM_VENDOR_ID, wmask & 0xffff);
+    pci_set_word(dev->cmask + PCI_SUBSYSTEM_VENDOR_ID, 0xffff);
+    pci_set_word(dev->config + PCI_SUBSYSTEM_ID, 0x7a00);
+    pci_set_word(dev->wmask + PCI_SUBSYSTEM_ID, wmask & 0xffff);
+    pci_set_word(dev->cmask + PCI_SUBSYSTEM_ID, 0xffff);
+    pci_set_byte(dev->config + PCI_CAPABILITY_LIST, 0x40);
+    pci_set_byte(dev->wmask + PCI_CAPABILITY_LIST, wmask & 0xff);
+    pci_set_byte(dev->cmask + PCI_CAPABILITY_LIST, 0xff);
+}
+
+static void ls7a_pcie_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->vendor_id = 0x0014;
+    k->device_id = 0x7a00;
+    k->revision = 0x00;
+    k->class_id = PCI_CLASS_BRIDGE_HOST;
+    dc->reset = ls7a_reset;
+    dc->desc = "LS7A1000 PCIE Host bridge";
+    dc->vmsd = &vmstate_ls7a_pcie;
+    /*
+     * PCI-facing part of the host bridge, not usable without the
+     * host-facing part, which can't be device_add'ed, yet.
+     */
+    dc->user_creatable = false;
+}
+
+static const TypeInfo ls7a_pcie_device_info = {
+    .name          = TYPE_LS7A_PCIE,
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(LS7APCIState),
+    .class_init    = ls7a_pcie_class_init,
+    .interfaces = (InterfaceInfo[]) {
+        { INTERFACE_CONVENTIONAL_PCI_DEVICE },
+        { },
+    },
+};
+
+static void ls7a_pciehost_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    dc->realize = ls7a_pciehost_realize;
+    dc->fw_name = "pci";
+    dc->user_creatable = false;
+}
+
+static const TypeInfo ls7a_pciehost_info = {
+    .name          = TYPE_LS7A_PCIE_HOST_BRIDGE,
+    .parent        = TYPE_PCIE_HOST_BRIDGE,
+    .instance_size = sizeof(LS7APCIEHost),
+    .class_init    = ls7a_pciehost_class_init,
+};
+
+static void ls7a_register_types(void)
+{
+    type_register_static(&ls7a_pciehost_info);
+    type_register_static(&ls7a_pcie_device_info);
+}
+
+type_init(ls7a_register_types)
diff --git a/hw/pci-host/meson.build b/hw/pci-host/meson.build
index 4c4f39c15c..c4955455fd 100644
--- a/hw/pci-host/meson.build
+++ b/hw/pci-host/meson.build
@@ -11,6 +11,7 @@ pci_ss.add(when: 'CONFIG_PCI_SABRE', if_true: files('sabre.c'))
 pci_ss.add(when: 'CONFIG_XEN_IGD_PASSTHROUGH', if_true: files('xen_igd_pt.c'))
 pci_ss.add(when: 'CONFIG_REMOTE_PCIHOST', if_true: files('remote.c'))
 pci_ss.add(when: 'CONFIG_SH_PCI', if_true: files('sh_pci.c'))
+pci_ss.add(when: 'CONFIG_PCI_EXPRESS_7A', if_true: files('ls7a.c'))
 
 # PPC devices
 pci_ss.add(when: 'CONFIG_RAVEN_PCI', if_true: files('raven.c'))
diff --git a/include/hw/pci-host/ls7a.h b/include/hw/pci-host/ls7a.h
new file mode 100644
index 0000000000..4c95a11ab8
--- /dev/null
+++ b/include/hw/pci-host/ls7a.h
@@ -0,0 +1,48 @@
+/*
+ * QEMU LoongArch CPU
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#ifndef HW_LS7A_H
+#define HW_LS7A_H
+
+#include "hw/pci/pci.h"
+#include "hw/pci/pcie_host.h"
+#include "hw/pci-host/pam.h"
+#include "qemu/units.h"
+#include "qemu/range.h"
+#include "qom/object.h"
+
+#define HT1LO_PCICFG_BASE        0x1a000000
+#define HT1LO_PCICFG_SIZE        0x02000000
+
+#define LS_PCIECFG_BASE          0x20000000
+#define LS_PCIECFG_SIZE          0x08000000
+
+#define LS7A_PCI_IO_BASE        0x18000000UL
+#define LS7A_PCI_IO_SIZE        0x00010000
+typedef struct LS7APCIState LS7APCIState;
+typedef struct LS7APCIEHost {
+    PCIExpressHost parent_obj;
+    LS7APCIState *pci_dev;
+    qemu_irq *pic;
+    MemoryRegion pci_conf;
+    MemoryRegion pci_io;
+} LS7APCIEHost;
+
+struct LS7APCIState {
+    PCIDevice dev;
+    LS7APCIEHost *pciehost;
+};
+
+#define TYPE_LS7A_PCIE_HOST_BRIDGE "ls7a1000-pciehost"
+OBJECT_DECLARE_SIMPLE_TYPE(LS7APCIEHost, LS7A_PCIE_HOST_BRIDGE)
+
+#define TYPE_LS7A_PCIE "ls7a1000_pcie"
+OBJECT_DECLARE_SIMPLE_TYPE(LS7APCIState, LS7A_PCIE)
+
+PCIBus *ls7a_init(MachineState *machine, qemu_irq *irq);
+#endif /* HW_LS7A_H */
-- 
2.27.0



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

* [PATCH 14/31] hw/loongarch: Add a virt loongarch 3A5000 board support
  2021-10-19  7:34 [PATCH 00/31] Add Loongarch softmmu support Xiaojuan Yang
                   ` (9 preceding siblings ...)
  2021-10-19  7:34 ` [PATCH 13/31] hw/pci-host: Add ls7a1000 PCIe Host bridge support for Loongson Platform Xiaojuan Yang
@ 2021-10-19  7:35 ` Xiaojuan Yang
  2021-10-19  7:35 ` [PATCH 15/31] hw/loongarch: Add loongarch cpu interrupt support(CPUINTC) Xiaojuan Yang
                   ` (10 subsequent siblings)
  21 siblings, 0 replies; 37+ messages in thread
From: Xiaojuan Yang @ 2021-10-19  7:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, richard.henderson,
	laurent, peterx, f4bug, yangxiaojuan, alistair.francis, maobibo,
	gaosong, pbonzini, mark.cave-ayland, bmeng.cn, alex.bennee,
	david

LoongArch is a new RISC ISA, support 32bit mode
or 64bit mode. Now we only add 64bit support.

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

Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 .../devices/loongarch64-softmmu/default.mak   |   3 +
 configs/targets/loongarch64-softmmu.mak       |   2 +
 hw/Kconfig                                    |   1 +
 hw/loongarch/Kconfig                          |   3 +
 hw/loongarch/ls3a5000_virt.c                  | 207 ++++++++++++++++++
 hw/loongarch/meson.build                      |   4 +
 hw/meson.build                                |   1 +
 include/exec/poison.h                         |   2 +
 include/hw/loongarch/loongarch.h              |  47 ++++
 include/sysemu/arch_init.h                    |   1 +
 qapi/machine.json                             |   2 +-
 target/Kconfig                                |   1 +
 target/loongarch/Kconfig                      |   2 +
 target/loongarch/cpu.c                        |   8 +
 target/loongarch/cpu.h                        |   4 +
 15 files changed, 287 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/ls3a5000_virt.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/configs/devices/loongarch64-softmmu/default.mak b/configs/devices/loongarch64-softmmu/default.mak
new file mode 100644
index 0000000000..a6705b9e4a
--- /dev/null
+++ b/configs/devices/loongarch64-softmmu/default.mak
@@ -0,0 +1,3 @@
+# Default configuration for loongarch64-softmmu
+
+CONFIG_LOONGSON_3A5000=y
diff --git a/configs/targets/loongarch64-softmmu.mak b/configs/targets/loongarch64-softmmu.mak
new file mode 100644
index 0000000000..77c266b3b1
--- /dev/null
+++ b/configs/targets/loongarch64-softmmu.mak
@@ -0,0 +1,2 @@
+TARGET_ARCH=loongarch64
+TARGET_BASE_ARCH=loongarch
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 0000000000..720822f32c
--- /dev/null
+++ b/hw/loongarch/Kconfig
@@ -0,0 +1,3 @@
+config LOONGSON_3A5000
+    bool
+    select PCI_EXPRESS_7A
diff --git a/hw/loongarch/ls3a5000_virt.c b/hw/loongarch/ls3a5000_virt.c
new file mode 100644
index 0000000000..71ffc2b81f
--- /dev/null
+++ b/hw/loongarch/ls3a5000_virt.c
@@ -0,0 +1,207 @@
+/*
+ * QEMU loongson 3a5000 develop board emulation
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+#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 "hw/loongarch/loongarch.h"
+#include "hw/pci-host/ls7a.h"
+
+CPULoongArchState *cpu_states[LOONGARCH_MAX_VCPUS];
+
+static void main_cpu_reset(void *opaque)
+{
+    LoongArchCPU *cpu = opaque;
+
+    cpu_reset(CPU(cpu));
+}
+
+static uint64_t loongarch_pm_mem_read(void *opaque, hwaddr addr, unsigned size)
+{
+    return 0;
+}
+
+static void loongarch_pm_mem_write(void *opaque, hwaddr addr,
+                                   uint64_t val, unsigned size)
+{
+
+    if (addr != PM_CNT_MODE) {
+        return;
+    }
+
+    switch (val) {
+    case 0x00:
+        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
+        return;
+    case 0xff:
+        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
+        return;
+    default:
+        return;
+    }
+}
+
+static const MemoryRegionOps loongarch_pm_ops = {
+    .read  = loongarch_pm_mem_read,
+    .write = loongarch_pm_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+#define LOONGARCH_SIMPLE_MMIO_OPS(ADDR, NAME, SIZE) \
+({\
+     MemoryRegion *iomem = g_new(MemoryRegion, 1);\
+     memory_region_init_io(iomem, NULL, &loongarch_qemu_ops,\
+                           (void *)ADDR, NAME, SIZE);\
+     memory_region_add_subregion_overlap(address_space_mem, ADDR, iomem, 1);\
+})
+
+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)
+{
+    uint64_t feature = 0UL;
+    addr = ((hwaddr)(long)opaque) + addr;
+    addr = addr & 0xffffffff;
+    switch (addr) {
+    case FEATURE_REG:
+        feature |= 1UL << IOCSRF_MSI | 1UL << IOCSRF_EXTIOI |
+                   1UL << IOCSRF_CSRIPI;
+        return feature ;
+    case VENDOR_REG:
+        return *(uint64_t *)"Loongson-3A5000";
+    case CPUNAME_REG:
+        return *(uint64_t *)"3A5000";
+    }
+    return 0;
+}
+
+static const MemoryRegionOps loongarch_qemu_ops = {
+    .read = loongarch_qemu_read,
+    .write = loongarch_qemu_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+    .valid = {
+        .min_access_size = 4,
+        .max_access_size = 8,
+    },
+    .impl = {
+        .min_access_size = 4,
+        .max_access_size = 8,
+    },
+};
+
+static void ls3a5000_virt_init(MachineState *machine)
+{
+    const char *cpu_model = machine->cpu_type;
+    LoongArchCPU *cpu;
+    CPULoongArchState *env;
+    uint64_t lowram_size = 0, highram_size = 0;
+    MemoryRegion *lowmem = g_new(MemoryRegion, 1);
+    char *ramName = NULL;
+    ram_addr_t ram_size = machine->ram_size;
+    MemoryRegion *address_space_mem = get_system_memory();
+    int i;
+    MemoryRegion *iomem = NULL;
+
+    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++) {
+        Object *cpuobj = NULL;
+        CPUState *cs;
+
+        cpuobj = object_new(machine->cpu_type);
+
+        cs = CPU(cpuobj);
+        cs->cpu_index = i;
+
+        qdev_realize(DEVICE(cpuobj), NULL, &error_fatal);
+        object_unref(cpuobj);
+
+        cpu = LOONGARCH_CPU(cs);
+        if (cpu == NULL) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        env = &cpu->env;
+        cpu_states[i] = env;
+
+        cpu_loongarch_clock_init(cpu);
+        qemu_register_reset(main_cpu_reset, cpu);
+    }
+
+    ramName = g_strdup_printf("loongarch.lowram");
+    lowram_size = MIN(ram_size, 256 * 0x100000);
+    memory_region_init_alias(lowmem, NULL, ramName, machine->ram,
+                             0, lowram_size);
+    memory_region_add_subregion(address_space_mem, 0, lowmem);
+
+    highram_size = ram_size > lowram_size ? ram_size - 256 * 0x100000 : 0;
+    if (highram_size > 0) {
+        MemoryRegion *highmem = g_new(MemoryRegion, 1);
+        ramName = g_strdup_printf("loongarch.highram");
+        memory_region_init_alias(highmem, NULL, ramName, machine->ram,
+                                 lowram_size, highram_size);
+        memory_region_add_subregion(address_space_mem, 0x90000000, highmem);
+    }
+
+    /*Add PM mmio memory for reboot and shutdown*/
+    iomem = g_new(MemoryRegion, 1);
+    memory_region_init_io(iomem, NULL, &loongarch_pm_ops, NULL,
+                          "loongarch_pm", PM_MMIO_SIZE);
+    memory_region_add_subregion(address_space_mem,
+                                PM_MMIO_ADDR, iomem);
+
+    LOONGARCH_SIMPLE_MMIO_OPS(FEATURE_REG, "loongarch_feature", 0x8);
+    LOONGARCH_SIMPLE_MMIO_OPS(VENDOR_REG, "loongarch_vendor", 0x8);
+    LOONGARCH_SIMPLE_MMIO_OPS(CPUNAME_REG, "loongarch_cpuname", 0x8);
+    LOONGARCH_SIMPLE_MMIO_OPS(MISC_FUNC_REG, "loongarch_misc", 0x8);
+    LOONGARCH_SIMPLE_MMIO_OPS(FREQ_REG, "loongarch_freq", 0x8);
+}
+
+static void loongarch_class_init(ObjectClass *oc, void *data)
+{
+    MachineClass *mc = MACHINE_CLASS(oc);
+
+    mc->desc = "Loongson-5000 LS7A1000 machine";
+    mc->init = ls3a5000_virt_init;
+    mc->default_ram_size = 1 * GiB;
+    mc->default_cpu_type = LOONGARCH_CPU_TYPE_NAME("Loongson-3A5000");
+    mc->default_ram_id = "loongarch.ram";
+    mc->max_cpus = LOONGARCH_MAX_VCPUS;
+    mc->is_default = 1;
+    mc->default_kernel_irqchip_split = false;
+    mc->block_default_type = IF_VIRTIO;
+    mc->default_boot_order = "c";
+    mc->no_cdrom = 1;
+}
+
+static const TypeInfo loongarch_machine_types[] = {
+    {
+        .name           = TYPE_LOONGARCH_MACHINE,
+        .parent         = TYPE_MACHINE,
+        .instance_size  = sizeof(LoongarchMachineState),
+        .class_init     = loongarch_class_init,
+    }
+};
+
+DEFINE_TYPES(loongarch_machine_types)
diff --git a/hw/loongarch/meson.build b/hw/loongarch/meson.build
new file mode 100644
index 0000000000..1e743cadb8
--- /dev/null
+++ b/hw/loongarch/meson.build
@@ -0,0 +1,4 @@
+loongarch_ss = ss.source_set()
+loongarch_ss.add(when: 'CONFIG_LOONGSON_3A5000', if_true: files('ls3a5000_virt.c'))
+
+hw_arch += {'loongarch': loongarch_ss}
diff --git a/hw/meson.build b/hw/meson.build
index b3366c888e..95202649b7 100644
--- a/hw/meson.build
+++ b/hw/meson.build
@@ -49,6 +49,7 @@ subdir('avr')
 subdir('cris')
 subdir('hppa')
 subdir('i386')
+subdir('loongarch')
 subdir('m68k')
 subdir('microblaze')
 subdir('mips')
diff --git a/include/exec/poison.h b/include/exec/poison.h
index 7ad4ad18e8..590bc305c7 100644
--- a/include/exec/poison.h
+++ b/include/exec/poison.h
@@ -14,6 +14,7 @@
 #pragma GCC poison TARGET_CRIS
 #pragma GCC poison TARGET_HEXAGON
 #pragma GCC poison TARGET_HPPA
+#pragma GCC poison TARGET_LOONGARCH64
 #pragma GCC poison TARGET_M68K
 #pragma GCC poison TARGET_MICROBLAZE
 #pragma GCC poison TARGET_MIPS
@@ -73,6 +74,7 @@
 #pragma GCC poison CONFIG_HPPA_DIS
 #pragma GCC poison CONFIG_I386_DIS
 #pragma GCC poison CONFIG_HEXAGON_DIS
+#pragma GCC poison CONFIG_LOONGARCH_DIS
 #pragma GCC poison CONFIG_M68K_DIS
 #pragma GCC poison CONFIG_MICROBLAZE_DIS
 #pragma GCC poison CONFIG_MIPS_DIS
diff --git a/include/hw/loongarch/loongarch.h b/include/hw/loongarch/loongarch.h
new file mode 100644
index 0000000000..087a988c34
--- /dev/null
+++ b/include/hw/loongarch/loongarch.h
@@ -0,0 +1,47 @@
+/*
+ * Definitions for loongarch board emulation.
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#ifndef HW_LOONGARCH_H
+#define HW_LOONGARCH_H
+
+#include "target/loongarch/cpu.h"
+#include "qemu-common.h"
+#include "hw/boards.h"
+#include "qemu/queue.h"
+
+#define LOONGARCH_MAX_VCPUS     4
+#define PM_MMIO_ADDR            0x10080000UL
+#define PM_MMIO_SIZE            0x100
+#define PM_CNT_MODE             0x10
+#define FEATURE_REG             0x1fe00008
+#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_FREQSCALE        6
+#define IOCSRF_DVFSV1           7
+#define IOCSRF_GMOD             9
+#define IOCSRF_VM               11
+
+#define VENDOR_REG              0x1fe00010
+#define CPUNAME_REG             0x1fe00020
+#define MISC_FUNC_REG           0x1fe00420
+#define FREQ_REG                0x1fe001d0
+
+typedef struct LoongarchMachineState {
+    /*< private >*/
+    MachineState parent_obj;
+
+} LoongarchMachineState;
+
+#define TYPE_LOONGARCH_MACHINE  MACHINE_TYPE_NAME("loongson7a")
+DECLARE_INSTANCE_CHECKER(LoongarchMachineState, LOONGARCH_MACHINE,
+                         TYPE_LOONGARCH_MACHINE)
+#endif
diff --git a/include/sysemu/arch_init.h b/include/sysemu/arch_init.h
index 70c579560a..3ac3634bbb 100644
--- a/include/sysemu/arch_init.h
+++ b/include/sysemu/arch_init.h
@@ -24,6 +24,7 @@ enum {
     QEMU_ARCH_RX = (1 << 20),
     QEMU_ARCH_AVR = (1 << 21),
     QEMU_ARCH_HEXAGON = (1 << 22),
+    QEMU_ARCH_LOONGARCH = (1 << 23),
 };
 
 extern const uint32_t arch_type;
diff --git a/qapi/machine.json b/qapi/machine.json
index 5db54df298..0ffe84f074 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -30,7 +30,7 @@
 ##
 { 'enum' : 'SysEmuTarget',
   'data' : [ 'aarch64', 'alpha', 'arm', 'avr', 'cris', 'hppa', 'i386',
-             'm68k', 'microblaze', 'microblazeel', 'mips', 'mips64',
+             'loongarch64', 'm68k', 'microblaze', 'microblazeel', 'mips', 'mips64',
              'mips64el', 'mipsel', 'nios2', 'or1k', 'ppc',
              'ppc64', 'riscv32', 'riscv64', 'rx', 's390x', 'sh4',
              'sh4eb', 'sparc', 'sparc64', 'tricore',
diff --git a/target/Kconfig b/target/Kconfig
index ae7f24fc66..83da0bd293 100644
--- a/target/Kconfig
+++ b/target/Kconfig
@@ -4,6 +4,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/target/loongarch/Kconfig b/target/loongarch/Kconfig
new file mode 100644
index 0000000000..46b26b1a85
--- /dev/null
+++ b/target/loongarch/Kconfig
@@ -0,0 +1,2 @@
+config LOONGARCH64
+    bool
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 2886dbd642..532b229c05 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -12,6 +12,7 @@
 #include "qemu/module.h"
 #include "sysemu/qtest.h"
 #include "exec/exec-all.h"
+#include "hw/qdev-properties.h"
 #include "qapi/qapi-commands-machine-target.h"
 #include "migration/vmstate.h"
 #include "cpu.h"
@@ -537,6 +538,12 @@ static ObjectClass *loongarch_cpu_class_by_name(const char *cpu_model)
     return oc;
 }
 
+static Property loongarch_cpu_properties[] = {
+    DEFINE_PROP_INT32("core-id", LoongArchCPU, core_id, -1),
+    DEFINE_PROP_UINT32("id", LoongArchCPU, id, UNASSIGNED_CPU_ID),
+    DEFINE_PROP_END_OF_LIST()
+};
+
 void loongarch_cpu_dump_state(CPUState *cs, FILE *f, int flags)
 {
     LoongArchCPU *cpu = LOONGARCH_CPU(cs);
@@ -636,6 +643,7 @@ static void loongarch_cpu_class_init(ObjectClass *c, void *data)
     device_class_set_parent_realize(dc, loongarch_cpu_realizefn,
                                     &lacc->parent_realize);
     device_class_set_parent_reset(dc, loongarch_cpu_reset, &lacc->parent_reset);
+    device_class_set_props(dc, loongarch_cpu_properties);
 
     cc->class_by_name = loongarch_cpu_class_by_name;
     cc->has_work = loongarch_cpu_has_work;
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index e77517d375..cfdcf1d4a0 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -16,6 +16,8 @@
 
 #define TCG_GUEST_DEFAULT_MO (0)
 
+#define UNASSIGNED_CPU_ID 0xFFFFFFFF
+
 #define FCSR0_M1    0x1f         /* FCSR1 mask, Enables */
 #define FCSR0_M2    0x1f1f0000   /* FCSR2 mask, Cause and Flags */
 #define FCSR0_M3    0x300        /* FCSR3 mask, Round Mode */
@@ -104,6 +106,8 @@ struct LoongArchCPU {
 
     CPUNegativeOffsetState neg;
     CPULoongArchState env;
+    uint32_t id;
+    int32_t core_id;
 };
 
 #define TYPE_LOONGARCH_CPU "loongarch64-cpu"
-- 
2.27.0



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

* [PATCH 15/31] hw/loongarch: Add loongarch cpu interrupt support(CPUINTC)
  2021-10-19  7:34 [PATCH 00/31] Add Loongarch softmmu support Xiaojuan Yang
                   ` (10 preceding siblings ...)
  2021-10-19  7:35 ` [PATCH 14/31] hw/loongarch: Add a virt loongarch 3A5000 board support Xiaojuan Yang
@ 2021-10-19  7:35 ` Xiaojuan Yang
  2021-10-19  7:35 ` [PATCH 16/31] hw/loongarch: Add loongarch ipi interrupt support(IPI) Xiaojuan Yang
                   ` (9 subsequent siblings)
  21 siblings, 0 replies; 37+ messages in thread
From: Xiaojuan Yang @ 2021-10-19  7:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, richard.henderson,
	laurent, peterx, f4bug, yangxiaojuan, alistair.francis, maobibo,
	gaosong, pbonzini, mark.cave-ayland, bmeng.cn, alex.bennee,
	david

Loongson-3A5000 support 14 interrupts from 64 - 77(Timer->75 IPI->76)
Loongson-3A5000 and ls7a form a legacy model and extended model irq
hierarchy.Tcg mode emulate a simplified extended model which
has no Legacy I/O Interrupt Controller(LIOINTC) and LPC.
e.g:

 |    +-----+    +---------+     +-------+             |
 |    | IPI |--> | CPUINTC | <-- | Timer |             |
 |    +-----+    +---------+     +-------+             |
 |                    ^                                |
 |                    |                                |
 |               +---------+
 |               | EIOINTC |
 |               +---------+
 |                ^       ^                            |
 |                |       |                            |
 |         +---------+ +---------+                     |
 |         | PCH-PIC | | PCH-MSI |                     |
 |         +---------+ +---------+                     |
 |           ^     ^           ^                       |
 |           |     |           |                       |
 |   +---------+ +---------+ +---------+               |
 |   | UARTs | | Devices | | Devices |                 |
 |   +---------+ +---------+ +---------+               |
 |        ^                                            |

The following series patch will realize the interrupt
controller in this model.

More detailed info can be found at the kernel doc or manual
1.https://git.kernel.org/pub/scm/linux/kernel/git/chenhuacai/
linux-loongson.git/tree/Documentation/loongarch?h=loongarch-next
2.https://github.com/loongson/LoongArch-Documentation

Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 hw/loongarch/loongarch_int.c     | 62 ++++++++++++++++++++++++++++++++
 hw/loongarch/ls3a5000_virt.c     |  2 ++
 hw/loongarch/meson.build         |  1 +
 include/hw/loongarch/loongarch.h |  2 ++
 4 files changed, 67 insertions(+)
 create mode 100644 hw/loongarch/loongarch_int.c

diff --git a/hw/loongarch/loongarch_int.c b/hw/loongarch/loongarch_int.c
new file mode 100644
index 0000000000..7282bc28f6
--- /dev/null
+++ b/hw/loongarch/loongarch_int.c
@@ -0,0 +1,62 @@
+/*
+ * QEMU LOONGARCH interrupt support
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/main-loop.h"
+#include "hw/irq.h"
+#include "hw/loongarch/loongarch.h"
+#include "cpu.h"
+
+static void cpu_loongarch_irq_request(void *opaque, int irq, int level)
+{
+    LoongArchCPU *cpu = opaque;
+    CPULoongArchState *env = &cpu->env;
+    CPUState *cs = CPU(cpu);
+    bool locked = false;
+
+    if (irq < 0 || irq > N_IRQS) {
+        return;
+    }
+
+    /* Make sure locking works even if BQL is already held by the caller */
+    if (!qemu_mutex_iothread_locked()) {
+        locked = true;
+        qemu_mutex_lock_iothread();
+    }
+
+    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);
+    }
+
+    if (locked) {
+        qemu_mutex_unlock_iothread();
+    }
+}
+
+void cpu_loongarch_init_irq(LoongArchCPU *cpu)
+{
+    CPULoongArchState *env = &cpu->env;
+    qemu_irq *qi;
+    int i;
+
+    qi = qemu_allocate_irqs(cpu_loongarch_irq_request, cpu, N_IRQS);
+    for (i = 0; i < N_IRQS; i++) {
+        env->irq[i] = qi[i];
+    }
+    g_free(qi);
+}
+
+
diff --git a/hw/loongarch/ls3a5000_virt.c b/hw/loongarch/ls3a5000_virt.c
index 71ffc2b81f..222c76bc0d 100644
--- a/hw/loongarch/ls3a5000_virt.c
+++ b/hw/loongarch/ls3a5000_virt.c
@@ -145,6 +145,8 @@ static void ls3a5000_virt_init(MachineState *machine)
         env = &cpu->env;
         cpu_states[i] = env;
 
+        /* Init CPU internal devices */
+        cpu_loongarch_init_irq(cpu);
         cpu_loongarch_clock_init(cpu);
         qemu_register_reset(main_cpu_reset, cpu);
     }
diff --git a/hw/loongarch/meson.build b/hw/loongarch/meson.build
index 1e743cadb8..a972210680 100644
--- a/hw/loongarch/meson.build
+++ b/hw/loongarch/meson.build
@@ -1,4 +1,5 @@
 loongarch_ss = ss.source_set()
+loongarch_ss.add(files('loongarch_int.c'))
 loongarch_ss.add(when: 'CONFIG_LOONGSON_3A5000', if_true: files('ls3a5000_virt.c'))
 
 hw_arch += {'loongarch': loongarch_ss}
diff --git a/include/hw/loongarch/loongarch.h b/include/hw/loongarch/loongarch.h
index 087a988c34..0edc313546 100644
--- a/include/hw/loongarch/loongarch.h
+++ b/include/hw/loongarch/loongarch.h
@@ -44,4 +44,6 @@ typedef struct LoongarchMachineState {
 #define TYPE_LOONGARCH_MACHINE  MACHINE_TYPE_NAME("loongson7a")
 DECLARE_INSTANCE_CHECKER(LoongarchMachineState, LOONGARCH_MACHINE,
                          TYPE_LOONGARCH_MACHINE)
+
+void cpu_loongarch_init_irq(LoongArchCPU *cpu);
 #endif
-- 
2.27.0



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

* [PATCH 16/31] hw/loongarch: Add loongarch ipi interrupt support(IPI)
  2021-10-19  7:34 [PATCH 00/31] Add Loongarch softmmu support Xiaojuan Yang
                   ` (11 preceding siblings ...)
  2021-10-19  7:35 ` [PATCH 15/31] hw/loongarch: Add loongarch cpu interrupt support(CPUINTC) Xiaojuan Yang
@ 2021-10-19  7:35 ` Xiaojuan Yang
  2021-10-19  7:35 ` [PATCH 17/31] hw/intc: Add loongarch ls7a interrupt controller support(PCH-PIC) Xiaojuan Yang
                   ` (8 subsequent siblings)
  21 siblings, 0 replies; 37+ messages in thread
From: Xiaojuan Yang @ 2021-10-19  7:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, richard.henderson,
	laurent, peterx, f4bug, yangxiaojuan, alistair.francis, maobibo,
	gaosong, pbonzini, mark.cave-ayland, bmeng.cn, alex.bennee,
	david

This patch realize the IPI interrupt controller.

Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 hw/loongarch/ipi.c               | 145 +++++++++++++++++++++++++++++++
 hw/loongarch/ls3a5000_virt.c     |   2 +
 hw/loongarch/meson.build         |   2 +-
 include/hw/loongarch/gipi.h      |  38 ++++++++
 include/hw/loongarch/loongarch.h |   3 +
 target/loongarch/cpu.h           |   1 +
 6 files changed, 190 insertions(+), 1 deletion(-)
 create mode 100644 hw/loongarch/ipi.c
 create mode 100644 include/hw/loongarch/gipi.h

diff --git a/hw/loongarch/ipi.c b/hw/loongarch/ipi.c
new file mode 100644
index 0000000000..a5c82b2143
--- /dev/null
+++ b/hw/loongarch/ipi.c
@@ -0,0 +1,145 @@
+/*
+ * Loongarch ipi interrupt support
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "qapi/error.h"
+#include "exec/address-spaces.h"
+#include "hw/hw.h"
+#include "hw/irq.h"
+#include "sysemu/sysemu.h"
+#include "sysemu/cpus.h"
+#include "cpu.h"
+#include "qemu/log.h"
+#include "hw/loongarch/loongarch.h"
+#include "migration/vmstate.h"
+
+static const VMStateDescription vmstate_gipi_core = {
+    .name = "gipi-single",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(status, gipi_core),
+        VMSTATE_UINT32(en, gipi_core),
+        VMSTATE_UINT32(set, gipi_core),
+        VMSTATE_UINT32(clear, gipi_core),
+        VMSTATE_UINT64_ARRAY(buf, gipi_core, MAX_GIPI_MBX_NUM),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_gipi = {
+    .name = "gipi",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_STRUCT_ARRAY(core, gipiState, MAX_GIPI_CORE_NUM, 0,
+                             vmstate_gipi_core, gipi_core),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void gipi_writel(void *opaque, hwaddr addr, uint64_t val, unsigned size)
+{
+    gipi_core *s = opaque;
+    void *pbuf;
+
+    if (size != 4) {
+        hw_error("size not 4");
+    }
+    addr &= 0xff;
+    switch (addr) {
+    case CORE_STATUS_OFF:
+        hw_error("CORE_SET_OFF Can't be write\n");
+        break;
+    case CORE_EN_OFF:
+        s->en = val;
+        break;
+    case CORE_SET_OFF:
+        s->status |= val;
+        if (s->status != 0) {
+            qemu_irq_raise(s->irq);
+        }
+        break;
+    case CORE_CLEAR_OFF:
+        s->status ^= val;
+        if (s->status == 0) {
+            qemu_irq_lower(s->irq);
+        }
+        break;
+    case CORE_BUF_20 ... CORE_BUF_38:
+        pbuf =  (void *)s->buf + (addr - 0x20);
+        *(unsigned int *)pbuf = val;
+        break;
+    default:
+        break;
+    }
+}
+
+static uint64_t gipi_readl(void *opaque, hwaddr addr, unsigned size)
+{
+    gipi_core *s = opaque;
+    uint64_t ret = 0;
+    void *pbuf;
+
+    addr &= 0xff;
+    if (size != 4) {
+        hw_error("size not 4 %d\n", size);
+    }
+    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:
+        pbuf =  (void *)s->buf + (addr - 0x20);
+        ret = *(unsigned int *)pbuf;
+        break;
+    default:
+        break;
+    }
+
+    return ret;
+}
+
+static const MemoryRegionOps gipi_ops = {
+    .read = gipi_readl,
+    .write = gipi_writel,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+int cpu_init_ipi(LoongarchMachineState *lsms, qemu_irq parent, int cpu)
+{
+    int core_num = cpu % 4;
+    hwaddr addr;
+    MemoryRegion *region;
+    char str[32];
+
+    if (lsms->gipi == NULL) {
+        lsms->gipi = g_malloc0(sizeof(gipiState));
+        vmstate_register(NULL, 0, &vmstate_gipi, lsms->gipi);
+    }
+
+    lsms->gipi->core[cpu].irq = parent;
+
+    addr = SMP_GIPI_MAILBOX + core_num * 0x100;
+    region = g_new(MemoryRegion, 1);
+    sprintf(str, "gipi%d", cpu);
+    memory_region_init_io(region, NULL, &gipi_ops,
+                          &lsms->gipi->core[cpu], str, 0x100);
+    memory_region_add_subregion(get_system_memory(), addr, region);
+    return 0;
+}
diff --git a/hw/loongarch/ls3a5000_virt.c b/hw/loongarch/ls3a5000_virt.c
index 222c76bc0d..115954033e 100644
--- a/hw/loongarch/ls3a5000_virt.c
+++ b/hw/loongarch/ls3a5000_virt.c
@@ -113,6 +113,7 @@ static void ls3a5000_virt_init(MachineState *machine)
     char *ramName = NULL;
     ram_addr_t ram_size = machine->ram_size;
     MemoryRegion *address_space_mem = get_system_memory();
+    LoongarchMachineState *lsms = LOONGARCH_MACHINE(machine);
     int i;
     MemoryRegion *iomem = NULL;
 
@@ -148,6 +149,7 @@ static void ls3a5000_virt_init(MachineState *machine)
         /* Init CPU internal devices */
         cpu_loongarch_init_irq(cpu);
         cpu_loongarch_clock_init(cpu);
+        cpu_init_ipi(lsms, env->irq[IRQ_IPI], i);
         qemu_register_reset(main_cpu_reset, cpu);
     }
 
diff --git a/hw/loongarch/meson.build b/hw/loongarch/meson.build
index a972210680..1bd209c9eb 100644
--- a/hw/loongarch/meson.build
+++ b/hw/loongarch/meson.build
@@ -1,5 +1,5 @@
 loongarch_ss = ss.source_set()
 loongarch_ss.add(files('loongarch_int.c'))
-loongarch_ss.add(when: 'CONFIG_LOONGSON_3A5000', if_true: files('ls3a5000_virt.c'))
+loongarch_ss.add(when: 'CONFIG_LOONGSON_3A5000', if_true: files('ls3a5000_virt.c', 'ipi.c'))
 
 hw_arch += {'loongarch': loongarch_ss}
diff --git a/include/hw/loongarch/gipi.h b/include/hw/loongarch/gipi.h
new file mode 100644
index 0000000000..9844b6992f
--- /dev/null
+++ b/include/hw/loongarch/gipi.h
@@ -0,0 +1,38 @@
+/*
+ * Loongarch ipi interrupt header files
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#ifndef HW_LOONGARCH_GIPI_H
+#define HW_LOONGARCH_GIPI_H
+
+#define SMP_GIPI_MAILBOX                0x1fe01000ULL
+#define CORE_STATUS_OFF       0x000
+#define CORE_EN_OFF           0x004
+#define CORE_SET_OFF          0x008
+#define CORE_CLEAR_OFF        0x00c
+#define CORE_BUF_20           0x020
+#define CORE_BUF_28           0x028
+#define CORE_BUF_30           0x030
+#define CORE_BUF_38           0x038
+
+#define MAX_GIPI_CORE_NUM      4
+#define MAX_GIPI_MBX_NUM       4
+
+typedef struct gipi_core {
+    uint32_t status;
+    uint32_t en;
+    uint32_t set;
+    uint32_t clear;
+    uint64_t buf[MAX_GIPI_MBX_NUM];
+    qemu_irq irq;
+} gipi_core;
+
+typedef struct gipiState {
+    gipi_core core[MAX_GIPI_CORE_NUM];
+} gipiState;
+
+#endif
diff --git a/include/hw/loongarch/loongarch.h b/include/hw/loongarch/loongarch.h
index 0edc313546..8e98430747 100644
--- a/include/hw/loongarch/loongarch.h
+++ b/include/hw/loongarch/loongarch.h
@@ -13,6 +13,7 @@
 #include "qemu-common.h"
 #include "hw/boards.h"
 #include "qemu/queue.h"
+#include "hw/loongarch/gipi.h"
 
 #define LOONGARCH_MAX_VCPUS     4
 #define PM_MMIO_ADDR            0x10080000UL
@@ -39,6 +40,7 @@ typedef struct LoongarchMachineState {
     /*< private >*/
     MachineState parent_obj;
 
+    gipiState   *gipi;
 } LoongarchMachineState;
 
 #define TYPE_LOONGARCH_MACHINE  MACHINE_TYPE_NAME("loongson7a")
@@ -46,4 +48,5 @@ DECLARE_INSTANCE_CHECKER(LoongarchMachineState, LOONGARCH_MACHINE,
                          TYPE_LOONGARCH_MACHINE)
 
 void cpu_loongarch_init_irq(LoongArchCPU *cpu);
+int cpu_init_ipi(LoongarchMachineState *ms, qemu_irq parent, int cpu);
 #endif
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index cfdcf1d4a0..4acbc08179 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -50,6 +50,7 @@ extern const char * const fregnames[];
 
 #define N_IRQS      14
 #define IRQ_TIMER   11
+#define IRQ_IPI     12
 
 #define LOONGARCH_HFLAG_KU     0x00003 /* kernel/user mode mask   */
 #define LOONGARCH_HFLAG_UM     0x00003 /* user mode flag                     */
-- 
2.27.0



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

* [PATCH 17/31] hw/intc: Add loongarch ls7a interrupt controller support(PCH-PIC)
  2021-10-19  7:34 [PATCH 00/31] Add Loongarch softmmu support Xiaojuan Yang
                   ` (12 preceding siblings ...)
  2021-10-19  7:35 ` [PATCH 16/31] hw/loongarch: Add loongarch ipi interrupt support(IPI) Xiaojuan Yang
@ 2021-10-19  7:35 ` Xiaojuan Yang
  2021-10-19  7:35 ` [PATCH 18/31] hw/intc: Add loongarch ls7a msi interrupt controller support(PCH-MSI) Xiaojuan Yang
                   ` (7 subsequent siblings)
  21 siblings, 0 replies; 37+ messages in thread
From: Xiaojuan Yang @ 2021-10-19  7:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, richard.henderson,
	laurent, peterx, f4bug, yangxiaojuan, alistair.francis, maobibo,
	gaosong, pbonzini, mark.cave-ayland, bmeng.cn, alex.bennee,
	david

This patch realize the PCH-PIC interrupt controller.

Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 hw/intc/Kconfig                     |   4 +
 hw/intc/loongarch_pch_pic.c         | 284 ++++++++++++++++++++++++++++
 hw/intc/meson.build                 |   1 +
 hw/loongarch/Kconfig                |   1 +
 include/hw/intc/loongarch_pch_pic.h |  50 +++++
 5 files changed, 340 insertions(+)
 create mode 100644 hw/intc/loongarch_pch_pic.c
 create mode 100644 include/hw/intc/loongarch_pch_pic.h

diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
index 78aed93c45..3b7eca7b03 100644
--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -73,3 +73,7 @@ config GOLDFISH_PIC
 
 config M68K_IRQC
     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 0000000000..9d0673b98a
--- /dev/null
+++ b/hw/intc/loongarch_pch_pic.c
@@ -0,0 +1,284 @@
+/*
+ * QEMU Loongson 7A1000 I/O interrupt controller.
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "hw/intc/loongarch_pch_pic.h"
+#include "migration/vmstate.h"
+
+#define DEBUG_LOONGARCH_PCH_PIC 0
+
+#define DPRINTF(fmt, ...) \
+do { \
+    if (DEBUG_LOONGARCH_PCH_PIC) { \
+        fprintf(stderr, "LOONGARCH_PCH_PIC: " fmt , ## __VA_ARGS__); \
+    } \
+} while (0)
+
+ #define for_each_set_bit(bit, addr, size) \
+         for ((bit) = find_first_bit((addr), (size));            \
+              (bit) < (size);                                    \
+              (bit) = find_next_bit((addr), (size), (bit) + 1))
+
+static void update_irq(loongarch_pch_pic *s, int mask, int level)
+{
+    int i;
+    uint64_t val;
+    val = mask & s->intirr & (~s->int_mask);
+
+    for_each_set_bit(i, &val, 32) {
+        if (level == 1) {
+            if ((s->intisr & (0x1ULL << i)) == 0) {
+                s->intisr |= 1ULL << i;
+                qemu_set_irq(s->parent_irq[s->htmsi_vector[i]], 1);
+            }
+        } else if (level == 0) {
+            if (s->intisr & (0x1ULL << i)) {
+                s->intisr &= ~(0x1ULL << i);
+                qemu_set_irq(s->parent_irq[s->htmsi_vector[i]], 0);
+            }
+        }
+    }
+}
+
+static void irq_handler(void *opaque, int irq, int level)
+{
+    loongarch_pch_pic *s = opaque;
+
+    assert(irq < 32);
+    uint32_t mask = 1ULL << irq;
+    DPRINTF("------ %s irq %d %d\n", __func__, 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;
+        }
+
+    }
+    update_irq(s, mask, level);
+}
+
+static uint64_t loongarch_pch_pic_reg_read(void *opaque, hwaddr addr,
+                                           unsigned size)
+{
+    loongarch_pch_pic *s = opaque;
+    uint32_t val = 0;
+    uint32_t offset;
+    int32_t offset_tmp;
+    offset = addr & 0xfff;
+    if (4 == size) {
+        switch (offset) {
+        case PCH_PIC_INT_ID_OFFSET:
+            val = PCH_PIC_INT_ID_VAL;
+            break;
+        case PCH_PIC_INT_MASK_OFFSET:
+            val = s->int_mask;
+            break;
+        case PCH_PIC_INT_STATUS_OFFSET:
+            val = s->intisr & (~s->int_mask);
+            break;
+        case PCH_PIC_INT_EDGE_OFFSET:
+            val = s->intedge;
+            break;
+        case PCH_PIC_INT_POL_OFFSET:
+            val = s->int_polarity;
+            break;
+        case PCH_PIC_HTMSI_EN_OFFSET:
+            val = s->htmsi_en;
+            break;
+        case PCH_PIC_AUTO_CTRL0_OFFSET:
+        case PCH_PIC_AUTO_CTRL1_OFFSET:
+            break;
+        default:
+            break;
+        }
+    } else if (1 == size) {
+        if (offset >= PCH_PIC_HTMSI_VEC_OFFSET) {
+            offset_tmp = offset - PCH_PIC_HTMSI_VEC_OFFSET;
+            if (offset_tmp >= 0 && offset_tmp < 32) {
+                val = s->htmsi_vector[offset_tmp];
+            }
+        } else if (offset >=  PCH_PIC_ROUTE_ENTRY_OFFSET) {
+            offset_tmp = offset - PCH_PIC_ROUTE_ENTRY_OFFSET;
+            if (offset_tmp >= 0 && offset_tmp < 32) {
+                val = s->route_entry[offset_tmp];
+            }
+        }
+    }
+
+    return val;
+}
+
+static void loongarch_pch_pic_reg_write(void *opaque, hwaddr addr,
+                                        uint64_t data, unsigned size)
+{
+    loongarch_pch_pic *s = opaque;
+    int32_t offset_tmp;
+    uint32_t offset, old;
+    offset = addr & 0xfff;
+
+    if (4 == size) {
+        switch (offset) {
+        case PCH_PIC_INT_MASK_OFFSET:
+            old = s->int_mask;
+            s->int_mask = data;
+            if (old & ~data) {
+                update_irq(s, (old & ~data), 1);
+            } else if (~old & data) {
+                update_irq(s, (~old & data), 0);
+            }
+            break;
+        case PCH_PIC_INT_STATUS_OFFSET:
+            s->intisr = data;
+            break;
+        case PCH_PIC_INT_EDGE_OFFSET:
+            s->intedge = data;
+            break;
+        case PCH_PIC_INT_CLEAR_OFFSET:
+            s->intirr &= (~(data & s->intedge));
+            update_irq(s, data, 0);
+            s->intisr &= (~data);
+            break;
+        case PCH_PIC_INT_POL_OFFSET:
+            s->int_polarity = data;
+            break;
+        case PCH_PIC_HTMSI_EN_OFFSET:
+            s->htmsi_en = data;
+            break;
+        case PCH_PIC_AUTO_CTRL0_OFFSET:
+        case PCH_PIC_AUTO_CTRL1_OFFSET:
+            break;
+        default:
+            break;
+        }
+    } else if (1 == size) {
+        if (offset >= PCH_PIC_HTMSI_VEC_OFFSET) {
+            offset_tmp = offset - PCH_PIC_HTMSI_VEC_OFFSET;
+            if (offset_tmp >= 0 && offset_tmp < 32) {
+                s->htmsi_vector[offset_tmp] = (uint8_t)(data & 0xff);
+            }
+        } else if (offset >=  PCH_PIC_ROUTE_ENTRY_OFFSET) {
+            offset_tmp = offset - PCH_PIC_ROUTE_ENTRY_OFFSET;
+            if (offset_tmp >= 0 && offset_tmp < 32) {
+                s->route_entry[offset_tmp] = (uint8_t)(data & 0xff);
+            }
+        }
+    }
+}
+
+static const MemoryRegionOps loongarch_pch_pic_ops = {
+    .read = loongarch_pch_pic_reg_read,
+    .write = loongarch_pch_pic_reg_write,
+    .valid = {
+        .min_access_size = 1,
+        .max_access_size = 8,
+    },
+    .impl = {
+        .min_access_size = 1,
+        .max_access_size = 8,
+    },
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void loongarch_pch_pic_reset(DeviceState *d)
+{
+    loongarch_pch_pic *s = LOONGARCH_PCH_PIC(d);
+    int i;
+
+    s->int_id   = 0x0;
+    s->int_mask = 0xffffffff;
+    s->htmsi_en = 0x0;
+    s->intedge  = 0x0;
+    s->intclr   = 0x0;
+    s->auto_crtl0 = 0x0;
+    s->auto_crtl1 = 0x0;
+    for (i = 0; i < 32; i++) {
+        s->route_entry[i] = 0x1;
+        s->htmsi_vector[i] = 0x0;
+    }
+    s->intirr = 0x0;
+    s->intisr = 0x0;
+    s->last_intirr = 0x0;
+    s->int_polarity = 0x0;
+}
+
+static void loongarch_pch_pic_init(Object *obj)
+{
+    loongarch_pch_pic *s = LOONGARCH_PCH_PIC(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    int tmp;
+
+    memory_region_init_io(&s->iomem, obj, &loongarch_pch_pic_ops,
+                          s, TYPE_LOONGARCH_PCH_PIC, 0x1000);
+    sysbus_init_mmio(sbd, &s->iomem);
+
+    for (tmp = 0; tmp < 32; tmp++) {
+        sysbus_init_irq(sbd, &s->parent_irq[tmp]);
+    }
+    qdev_init_gpio_in(DEVICE(obj), irq_handler, 32);
+}
+
+static const VMStateDescription vmstate_loongarch_pch_pic = {
+    .name = TYPE_LOONGARCH_PCH_PIC,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(int_mask, loongarch_pch_pic),
+        VMSTATE_UINT32(htmsi_en, loongarch_pch_pic),
+        VMSTATE_UINT32(intedge, loongarch_pch_pic),
+        VMSTATE_UINT32(intclr, loongarch_pch_pic),
+        VMSTATE_UINT32(auto_crtl0, loongarch_pch_pic),
+        VMSTATE_UINT32(auto_crtl1, loongarch_pch_pic),
+        VMSTATE_UINT8_ARRAY(route_entry, loongarch_pch_pic, 32),
+        VMSTATE_UINT8_ARRAY(htmsi_vector, loongarch_pch_pic, 32),
+        VMSTATE_UINT32(last_intirr, loongarch_pch_pic),
+        VMSTATE_UINT32(intirr, loongarch_pch_pic),
+        VMSTATE_UINT32(intisr, loongarch_pch_pic),
+        VMSTATE_UINT32(int_polarity, loongarch_pch_pic),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void loongarch_pch_pic_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->reset = loongarch_pch_pic_reset;
+    dc->vmsd = &vmstate_loongarch_pch_pic;
+}
+
+static const TypeInfo loongarch_pch_pic_info = {
+    .name          = TYPE_LOONGARCH_PCH_PIC,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(loongarch_pch_pic),
+    .instance_init = loongarch_pch_pic_init,
+    .class_init    = loongarch_pch_pic_class_init,
+};
+
+static void loongarch_pch_pic_register_types(void)
+{
+    type_register_static(&loongarch_pch_pic_info);
+}
+
+type_init(loongarch_pch_pic_register_types)
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
index a1d00aa48d..c61f171d5c 100644
--- a/hw/intc/meson.build
+++ b/hw/intc/meson.build
@@ -58,3 +58,4 @@ specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_XIVE'],
 		if_true: files('spapr_xive_kvm.c'))
 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_PCH_PIC', if_true: files('loongarch_pch_pic.c'))
diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
index 720822f32c..c6d7ebcd5b 100644
--- a/hw/loongarch/Kconfig
+++ b/hw/loongarch/Kconfig
@@ -1,3 +1,4 @@
 config LOONGSON_3A5000
     bool
     select PCI_EXPRESS_7A
+    select LOONGARCH_PCH_PIC
diff --git a/include/hw/intc/loongarch_pch_pic.h b/include/hw/intc/loongarch_pch_pic.h
new file mode 100644
index 0000000000..f85606de78
--- /dev/null
+++ b/include/hw/intc/loongarch_pch_pic.h
@@ -0,0 +1,50 @@
+/*
+ * Loongarch 7A1000 I/O interrupt controller definitions
+ *
+ * Copyright (c) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#define TYPE_LOONGARCH_PCH_PIC "loongarch_pch_pic"
+DECLARE_INSTANCE_CHECKER(struct loongarch_pch_pic, LOONGARCH_PCH_PIC,
+                         TYPE_LOONGARCH_PCH_PIC)
+
+#define PCH_PIC_ROUTE_ENTRY_OFFSET      0x100
+#define PCH_PIC_INT_ID_OFFSET           0x00
+#define PCH_PIC_INT_ID_VAL              0x7000000UL
+#define PCH_PIC_INT_ID_VER              0x1f0001UL
+#define PCH_PIC_INT_MASK_OFFSET         0x20
+#define PCH_PIC_INT_EDGE_OFFSET         0x60
+#define PCH_PIC_INT_CLEAR_OFFSET        0x80
+#define PCH_PIC_INT_STATUS_OFFSET       0x3a0
+#define PCH_PIC_INT_POL_OFFSET          0x3e0
+#define PCH_PIC_HTMSI_EN_OFFSET         0x40
+#define PCH_PIC_HTMSI_VEC_OFFSET        0x200
+#define PCH_PIC_AUTO_CTRL0_OFFSET       0xc0
+#define PCH_PIC_AUTO_CTRL1_OFFSET       0xe0
+
+typedef struct loongarch_pch_pic {
+    SysBusDevice parent_obj;
+    qemu_irq parent_irq[32];
+    uint32_t int_id;
+    uint32_t int_mask; /*0x020 interrupt mask register*/
+    uint32_t htmsi_en;/*0x040 1=msi*/
+    uint32_t intedge; /*0x060 edge=1 level  =0*/
+    uint32_t intclr; /*0x080 for clean edge int,set 1 clean,set 0 is noused*/
+    uint32_t auto_crtl0; /*0x0c0*/
+    uint32_t auto_crtl1; /*0x0e0*/
+    uint8_t route_entry[32]; /*0x100 - 0x120*/
+    uint8_t htmsi_vector[32]; /*0x200 - 0x220*/
+    uint32_t last_intirr;    /* edge detection */
+    uint32_t intirr; /* 0x380 interrupt request register */
+    uint32_t intisr; /* 0x3a0 interrupt service register */
+    /*
+     * 0x3e0 interrupt level polarity selection
+     * register 0 for high level trigger
+     */
+    uint32_t int_polarity;
+    MemoryRegion iomem;
+} loongarch_pch_pic;
+
+
-- 
2.27.0



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

* [PATCH 18/31] hw/intc: Add loongarch ls7a msi interrupt controller support(PCH-MSI)
  2021-10-19  7:34 [PATCH 00/31] Add Loongarch softmmu support Xiaojuan Yang
                   ` (13 preceding siblings ...)
  2021-10-19  7:35 ` [PATCH 17/31] hw/intc: Add loongarch ls7a interrupt controller support(PCH-PIC) Xiaojuan Yang
@ 2021-10-19  7:35 ` Xiaojuan Yang
  2021-10-19  7:35 ` [PATCH 19/31] hw/intc: Add loongarch extioi interrupt controller(EIOINTC) Xiaojuan Yang
                   ` (6 subsequent siblings)
  21 siblings, 0 replies; 37+ messages in thread
From: Xiaojuan Yang @ 2021-10-19  7:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, richard.henderson,
	laurent, peterx, f4bug, yangxiaojuan, alistair.francis, maobibo,
	gaosong, pbonzini, mark.cave-ayland, bmeng.cn, alex.bennee,
	david

This patch realize PCH-MSI interrupt controller.

Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 hw/intc/Kconfig                     |  5 ++
 hw/intc/loongarch_pch_msi.c         | 74 +++++++++++++++++++++++++++++
 hw/intc/meson.build                 |  1 +
 hw/loongarch/Kconfig                |  1 +
 include/hw/intc/loongarch_pch_msi.h | 17 +++++++
 5 files changed, 98 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 3b7eca7b03..c0dc12dfa0 100644
--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -77,3 +77,8 @@ config M68K_IRQC
 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 0000000000..78ccabd468
--- /dev/null
+++ b/hw/intc/loongarch_pch_msi.c
@@ -0,0 +1,74 @@
+/*
+ * QEMU Loongson 7A1000 msi interrupt controller.
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include "qemu/osdep.h"
+#include "hw/sysbus.h"
+#include "hw/irq.h"
+#include "hw/intc/loongarch_pch_msi.h"
+#include "hw/pci/msi.h"
+#include "hw/misc/unimp.h"
+#include "migration/vmstate.h"
+
+#define DEBUG_LOONGARCH_PCH_MSI 0
+
+#define DPRINTF(fmt, ...) \
+do { \
+    if (DEBUG_LOONGARCH_PCH_MSI) { \
+        fprintf(stderr, "LOONGARCH_PCH_MSI: " fmt , ## __VA_ARGS__); \
+    } \
+} while (0)
+
+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)
+{
+    loongarch_pch_msi *s = opaque;
+    int irq_num = val & 0xff;
+
+    qemu_set_irq(s->pch_msi_irq[irq_num - 32], 1);
+}
+
+static const MemoryRegionOps loongarch_pch_msi_ops = {
+    .read  = loongarch_msi_mem_read,
+    .write = loongarch_msi_mem_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void loongarch_pch_msi_init(Object *obj)
+{
+    loongarch_pch_msi *s = LOONGARCH_PCH_MSI(obj);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+    int tmp;
+
+    memory_region_init_io(&s->msi_mmio, obj, &loongarch_pch_msi_ops,
+                          s, TYPE_LOONGARCH_PCH_MSI, 0x8);
+    sysbus_init_mmio(sbd, &s->msi_mmio);
+    msi_nonbroken = true;
+
+    for (tmp = 0; tmp < 224; tmp++) {
+        sysbus_init_irq(sbd, &s->pch_msi_irq[tmp]);
+    }
+}
+
+static const TypeInfo loongarch_pch_msi_info = {
+    .name          = TYPE_LOONGARCH_PCH_MSI,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(loongarch_pch_msi),
+    .instance_init = loongarch_pch_msi_init,
+};
+
+static void loongarch_pch_msi_register_types(void)
+{
+    type_register_static(&loongarch_pch_msi_info);
+}
+
+type_init(loongarch_pch_msi_register_types)
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
index c61f171d5c..749c27e072 100644
--- a/hw/intc/meson.build
+++ b/hw/intc/meson.build
@@ -59,3 +59,4 @@ specific_ss.add(when: ['CONFIG_KVM', 'CONFIG_XIVE'],
 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_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/loongarch/Kconfig b/hw/loongarch/Kconfig
index c6d7ebcd5b..4500fd3a57 100644
--- a/hw/loongarch/Kconfig
+++ b/hw/loongarch/Kconfig
@@ -2,3 +2,4 @@ config LOONGSON_3A5000
     bool
     select PCI_EXPRESS_7A
     select LOONGARCH_PCH_PIC
+    select LOONGARCH_PCH_MSI
diff --git a/include/hw/intc/loongarch_pch_msi.h b/include/hw/intc/loongarch_pch_msi.h
new file mode 100644
index 0000000000..e069663dc8
--- /dev/null
+++ b/include/hw/intc/loongarch_pch_msi.h
@@ -0,0 +1,17 @@
+/*
+ * Loongarch 7A1000 I/O interrupt controller definitions
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#define TYPE_LOONGARCH_PCH_MSI "loongarch_pch_msi"
+DECLARE_INSTANCE_CHECKER(struct loongarch_pch_msi, LOONGARCH_PCH_MSI,
+                         TYPE_LOONGARCH_PCH_MSI)
+
+typedef struct loongarch_pch_msi {
+    SysBusDevice parent_obj;
+    qemu_irq pch_msi_irq[224];
+    MemoryRegion msi_mmio;
+} loongarch_pch_msi;
-- 
2.27.0



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

* [PATCH 19/31] hw/intc: Add loongarch extioi interrupt controller(EIOINTC)
  2021-10-19  7:34 [PATCH 00/31] Add Loongarch softmmu support Xiaojuan Yang
                   ` (14 preceding siblings ...)
  2021-10-19  7:35 ` [PATCH 18/31] hw/intc: Add loongarch ls7a msi interrupt controller support(PCH-MSI) Xiaojuan Yang
@ 2021-10-19  7:35 ` Xiaojuan Yang
  2021-10-19  7:35 ` [PATCH 20/31] hw/loongarch: Add irq hierarchy for the system Xiaojuan Yang
                   ` (5 subsequent siblings)
  21 siblings, 0 replies; 37+ messages in thread
From: Xiaojuan Yang @ 2021-10-19  7:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, richard.henderson,
	laurent, peterx, f4bug, yangxiaojuan, alistair.francis, maobibo,
	gaosong, pbonzini, mark.cave-ayland, bmeng.cn, alex.bennee,
	david

This patch realize the EIOINTC interrupt controller.

Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 hw/intc/Kconfig                    |   3 +
 hw/intc/loongarch_extioi.c         | 571 +++++++++++++++++++++++++++++
 hw/intc/meson.build                |   1 +
 hw/loongarch/Kconfig               |   1 +
 include/hw/intc/loongarch_extioi.h | 100 +++++
 include/hw/loongarch/loongarch.h   |   1 +
 6 files changed, 677 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 c0dc12dfa0..a2d9efd5aa 100644
--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -82,3 +82,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 0000000000..f12dec35dd
--- /dev/null
+++ b/hw/intc/loongarch_extioi.c
@@ -0,0 +1,571 @@
+/*
+ * Loongson 3A5000 ext interrupt controller emulation
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#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"
+
+#define DEBUG_APIC 0
+
+#define DPRINTF(fmt, ...) \
+do { \
+    if (DEBUG_APIC) { \
+        fprintf(stderr, "APIC: " fmt , ## __VA_ARGS__); \
+    } \
+} while (0)
+
+static void extioi_update_irq(void *opaque, int irq_num, int level)
+{
+    loongarch_extioi *s = opaque;
+    uint8_t  ipnum, cpu;
+    unsigned long found1, found2;
+
+    ipnum = s->sw_ipmap[irq_num];
+    cpu   = s->sw_coremap[irq_num];
+    if (level == 1) {
+        if (test_bit(irq_num, (void *)s->en_reg8) == false) {
+            return;
+        }
+        bitmap_set((void *)s->coreisr_reg8[cpu], irq_num, 1);
+        found1 = find_next_bit((void *)&(s->sw_ipisr[cpu][ipnum]),
+                               EXTIOI_IRQS, 0);
+        bitmap_set((void *)&(s->sw_ipisr[cpu][ipnum]), irq_num, 1);
+
+        if (found1 >= EXTIOI_IRQS) {
+            qemu_set_irq(s->parent_irq[cpu][ipnum], level);
+        }
+    } else {
+        bitmap_clear((void *)s->coreisr_reg8[cpu], irq_num, 1);
+        found1 = find_next_bit((void *)&(s->sw_ipisr[cpu][ipnum]),
+                               EXTIOI_IRQS, 0);
+        bitmap_clear((void *)&(s->sw_ipisr[cpu][ipnum]), irq_num, 1);
+        found2 = find_next_bit((void *)&(s->sw_ipisr[cpu][ipnum]),
+                               EXTIOI_IRQS, 0);
+
+        if ((found1 < EXTIOI_IRQS) && (found2 >= EXTIOI_IRQS)) {
+            qemu_set_irq(s->parent_irq[cpu][ipnum], level);
+        }
+    }
+}
+
+static void extioi_setirq(void *opaque, int irq, int level)
+{
+    loongarch_extioi *s = opaque;
+    extioi_update_irq(s, irq, level);
+}
+
+static void extioi_handler(void *opaque, int irq, int level)
+{
+    loongarch_extioi *extioi = (loongarch_extioi *)opaque;
+
+    qemu_set_irq(extioi->irq[irq], level);
+}
+
+static uint32_t extioi_readb(void *opaque, hwaddr addr)
+{
+    loongarch_extioi *state = opaque;
+    unsigned long offset, reg_count;
+    uint8_t ret;
+    int cpu;
+
+    offset = addr & 0xffff;
+
+    if ((offset >= EXTIOI_ENABLE_START) && (offset < EXTIOI_ENABLE_END)) {
+        reg_count = (offset - EXTIOI_ENABLE_START);
+        ret = state->en_reg8[reg_count];
+    } else if ((offset >= EXTIOI_BOUNCE_START) &&
+               (offset < EXTIOI_BOUNCE_END)) {
+        reg_count = (offset - EXTIOI_BOUNCE_START);
+        ret = state->bounce_reg8[reg_count];
+    } else if ((offset >= EXTIOI_COREISR_START) &&
+               (offset < EXTIOI_COREISR_END)) {
+        reg_count = ((offset - EXTIOI_COREISR_START) & 0x1f);
+        cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3;
+        ret = state->coreisr_reg8[cpu][reg_count];
+    } else if ((offset >= EXTIOI_IPMAP_START) &&
+               (offset < EXTIOI_IPMAP_END)) {
+        reg_count = (offset - EXTIOI_IPMAP_START);
+        ret = state->ipmap_reg8[reg_count];
+    } else if ((offset >= EXTIOI_COREMAP_START) &&
+               (offset < EXTIOI_COREMAP_END)) {
+        reg_count = (offset - EXTIOI_COREMAP_START);
+        ret = state->coremap_reg8[reg_count];
+    } else if ((offset >= EXTIOI_NODETYPE_START) &&
+               (offset < EXTIOI_NODETYPE_END)) {
+        reg_count = (offset - EXTIOI_NODETYPE_START);
+        ret = state->nodetype_reg8[reg_count];
+    }
+
+    DPRINTF("readb reg 0x" TARGET_FMT_plx " = %x\n", addr, ret);
+    return ret;
+}
+
+static uint32_t extioi_readw(void *opaque, hwaddr addr)
+{
+    loongarch_extioi *state = opaque;
+    unsigned long offset, reg_count;
+    uint32_t ret;
+    int cpu;
+
+    offset = addr & 0xffff;
+
+    if ((offset >= EXTIOI_ENABLE_START) && (offset < EXTIOI_ENABLE_END)) {
+        reg_count = (offset - EXTIOI_ENABLE_START) / 4;
+        ret = state->en_reg32[reg_count];
+    } else if ((offset >= EXTIOI_BOUNCE_START) &&
+               (offset < EXTIOI_BOUNCE_END)) {
+        reg_count = (offset - EXTIOI_BOUNCE_START) / 4;
+        ret = state->bounce_reg32[reg_count];
+    } else if ((offset >= EXTIOI_COREISR_START) &&
+               (offset < EXTIOI_COREISR_END)) {
+        reg_count = ((offset - EXTIOI_COREISR_START) & 0x1f) / 4;
+        cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3;
+        ret = state->coreisr_reg32[cpu][reg_count];
+    } else if ((offset >= EXTIOI_IPMAP_START) &&
+               (offset < EXTIOI_IPMAP_END)) {
+        reg_count = (offset - EXTIOI_IPMAP_START) / 4;
+        ret = state->ipmap_reg32[reg_count];
+    } else if ((offset >= EXTIOI_COREMAP_START) &&
+               (offset < EXTIOI_COREMAP_END)) {
+        reg_count = (offset - EXTIOI_COREMAP_START) / 4;
+        ret = state->coremap_reg32[reg_count];
+    } else if ((offset >= EXTIOI_NODETYPE_START) &&
+               (offset < EXTIOI_NODETYPE_END)) {
+        reg_count = (offset - EXTIOI_NODETYPE_START) / 4;
+        ret = state->nodetype_reg32[reg_count];
+    }
+
+    DPRINTF("readw reg 0x" TARGET_FMT_plx " = %x\n", addr, ret);
+    return ret;
+}
+
+static uint64_t extioi_readl(void *opaque, hwaddr addr)
+{
+    loongarch_extioi *state = opaque;
+    unsigned long offset, reg_count;
+    uint64_t ret;
+    int cpu;
+
+    offset = addr & 0xffff;
+
+    if ((offset >= EXTIOI_ENABLE_START) && (offset < EXTIOI_ENABLE_END)) {
+        reg_count = (offset - EXTIOI_ENABLE_START) / 8;
+        ret = state->en_reg64[reg_count];
+    } else if ((offset >= EXTIOI_BOUNCE_START) &&
+               (offset < EXTIOI_BOUNCE_END)) {
+        reg_count = (offset - EXTIOI_BOUNCE_START) / 8;
+        ret = state->bounce_reg64[reg_count];
+    } else if ((offset >= EXTIOI_COREISR_START) &&
+               (offset < EXTIOI_COREISR_END)) {
+        reg_count = ((offset - EXTIOI_COREISR_START) & 0x1f) / 8;
+        cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3;
+        ret = state->coreisr_reg64[cpu][reg_count];
+    } else if ((offset >= EXTIOI_IPMAP_START) &&
+               (offset < EXTIOI_IPMAP_END)) {
+        ret = state->ipmap_reg64;
+    } else if ((offset >= EXTIOI_COREMAP_START) &&
+               (offset < EXTIOI_COREMAP_END)) {
+        reg_count = (offset - EXTIOI_COREMAP_START) / 8;
+        ret = state->coremap_reg64[reg_count];
+    } else if ((offset >= EXTIOI_NODETYPE_START) &&
+               (offset < EXTIOI_NODETYPE_END)) {
+        reg_count = (offset - EXTIOI_NODETYPE_START) / 8;
+        ret = state->nodetype_reg64[reg_count];
+    }
+
+    DPRINTF("readl reg 0x" TARGET_FMT_plx " = %lx\n", addr, ret);
+    return ret;
+}
+
+static void extioi_writeb(void *opaque, hwaddr addr, uint32_t val)
+{
+    loongarch_extioi *state = opaque;
+    unsigned long offset, reg_count;
+    uint8_t old_data_u8;
+    int cpu, i, ipnum, level, mask, irqnum;
+
+    offset = addr & 0xffff;
+    val = val & 0xffUL;
+
+    if ((offset >= EXTIOI_ENABLE_START) && (offset < EXTIOI_ENABLE_END)) {
+        reg_count = (offset - EXTIOI_ENABLE_START);
+        old_data_u8 = state->en_reg8[reg_count];
+        if (old_data_u8 != val) {
+            state->en_reg8[reg_count] = val;
+            old_data_u8 = old_data_u8 ^ val;
+            mask = 0x1;
+
+            for (i = 0; i < 8; i++) {
+                if (old_data_u8 & mask) {
+                    level = !!(val & (0x1 << i));
+                    extioi_update_irq(state, i + reg_count * 8, level);
+                }
+                mask = mask << 1;
+            }
+        }
+    } else if ((offset >= EXTIOI_BOUNCE_START) &&
+               (offset < EXTIOI_BOUNCE_END)) {
+        reg_count = (offset - EXTIOI_BOUNCE_START);
+        state->bounce_reg8[reg_count] = val;
+    } else if ((offset >= EXTIOI_ISR_START) && (offset < EXTIOI_ISR_END)) {
+        /* can not be writen */
+        reg_count = (offset - EXTIOI_ISR_START) & 0x1f;
+        old_data_u8 = state->isr_reg8[reg_count];
+        state->isr_reg8[reg_count] = old_data_u8 & (~val);
+
+        mask = 0x1;
+        for (i = 0; i < 8; i++) {
+            if ((old_data_u8 & mask) && (val & mask)) {
+                extioi_update_irq(state, i + reg_count * 8, 0);
+            }
+            mask = mask << 1;
+        }
+    } else if ((offset >= EXTIOI_COREISR_START) &&
+               (offset < EXTIOI_COREISR_END)) {
+        reg_count = (offset - EXTIOI_COREISR_START) & 0x1f;
+        cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3;
+
+        /* ext_isr */
+        old_data_u8 = state->isr_reg8[reg_count];
+        state->isr_reg8[reg_count] = old_data_u8 & (~val);
+
+        old_data_u8 = state->coreisr_reg8[cpu][reg_count];
+        state->coreisr_reg8[cpu][reg_count] = old_data_u8 & (~val);
+
+        if (old_data_u8 != state->coreisr_reg8[cpu][reg_count]) {
+            mask = 0x1;
+            for (i = 0; i < 8; i++) {
+                if ((old_data_u8 & mask) && (val & mask)) {
+                    extioi_update_irq(state, i + reg_count * 8, 0);
+                }
+                mask = mask << 1;
+            }
+        }
+    } else if ((offset >= EXTIOI_IPMAP_START) && (offset < EXTIOI_IPMAP_END)) {
+        /* drop arch.core_ip_mask use state->ipmap */
+        reg_count = (offset - EXTIOI_IPMAP_START);
+        state->ipmap_reg8[reg_count] = val;
+
+        ipnum = 0;
+        for (i = 0; i < 4; i++) {
+            if (val & (0x1 << i)) {
+                ipnum = i;
+                break;
+            }
+        }
+
+        if (val) {
+            for (i = 0; i < 32; i++) {
+                irqnum = reg_count * 32 + i;
+                state->sw_ipmap[irqnum] = ipnum;
+            }
+        } else {
+            for (i = 0; i < 32; i++) {
+                irqnum = reg_count * 32 + i;
+                state->sw_ipmap[irqnum] = 0;
+            }
+        }
+    } else if ((offset >= EXTIOI_COREMAP_START) &&
+               (offset < EXTIOI_COREMAP_END)) {
+        reg_count = (offset - EXTIOI_COREMAP_START);
+        cpu = val & 0xf;
+
+        /* node map different from kernel */
+        if (cpu) {
+            cpu = ctz32(cpu);
+            state->coremap_reg8[reg_count] = val;
+            state->sw_coremap[reg_count] = cpu;
+        }
+    } else if ((offset >= EXTIOI_NODETYPE_START) &&
+               (offset < EXTIOI_NODETYPE_END)) {
+        reg_count = (offset - EXTIOI_NODETYPE_START);
+        state->nodetype_reg8[reg_count] = val;
+    }
+
+    DPRINTF("writeb reg 0x" TARGET_FMT_plx " = %x\n", addr, val);
+}
+
+static void extioi_writew(void *opaque, hwaddr addr, uint32_t val)
+{
+    loongarch_extioi *state = opaque;
+    int cpu, level;
+    uint32_t offset, old_data_u32, reg_count, mask, i;
+
+    offset = addr & 0xffff;
+
+    if ((offset >= EXTIOI_ENABLE_START) && (offset < EXTIOI_ENABLE_END)) {
+        reg_count = (offset - EXTIOI_ENABLE_START) / 4;
+        old_data_u32 = state->en_reg32[reg_count];
+        if (old_data_u32 != val) {
+            state->en_reg32[reg_count] = val;
+            old_data_u32 = old_data_u32 ^ val;
+
+            mask = 0x1;
+            for (i = 0; i < 8 * sizeof(old_data_u32); i++) {
+                if (old_data_u32 & mask) {
+                    level = !!(val & (0x1 << i));
+                    extioi_update_irq(state, i + reg_count * 32, level);
+                }
+                mask = mask << 1;
+            }
+        }
+    } else if ((offset >= EXTIOI_BOUNCE_START) &&
+               (offset < EXTIOI_BOUNCE_END)) {
+        reg_count = (offset - EXTIOI_BOUNCE_START) / 4;
+        state->bounce_reg32[reg_count] = val;
+    } else if ((offset >= EXTIOI_COREISR_START) &&
+               (offset < EXTIOI_COREISR_END)) {
+        reg_count = ((offset - EXTIOI_COREISR_START) & 0x1f) / 4;
+        cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3;
+
+        /* ext_isr */
+        old_data_u32 = state->isr_reg32[reg_count];
+        state->isr_reg32[reg_count] = old_data_u32 & (~val);
+
+        /* ext_core_ioisr */
+        old_data_u32 = state->coreisr_reg32[cpu][reg_count];
+        state->coreisr_reg32[cpu][reg_count] = old_data_u32 & (~val);
+
+        if (old_data_u32 != state->coreisr_reg32[cpu][reg_count]) {
+            mask = 0x1;
+            for (i = 0; i < 8 * sizeof(old_data_u32); i++) {
+                if ((old_data_u32 & mask) && (val & mask)) {
+                    extioi_update_irq(state, i + reg_count * 8, 0);
+                }
+                mask = mask << 1;
+            }
+        }
+    } else if ((offset >= EXTIOI_IPMAP_START) &&
+               (offset < EXTIOI_IPMAP_END)) {
+        extioi_writeb(opaque, addr, (val) & 0xff);
+        extioi_writeb(opaque, addr + 1, (val >> 8) & 0xff);
+        extioi_writeb(opaque, addr + 2, (val >> 16) & 0xff);
+        extioi_writeb(opaque, addr + 3, (val >> 24) & 0xff);
+    } else if ((offset >= EXTIOI_COREMAP_START) &&
+               (offset < EXTIOI_COREMAP_END)) {
+        extioi_writeb(opaque, addr, (val) & 0xff);
+        extioi_writeb(opaque, addr + 1, (val >> 8) & 0xff);
+        extioi_writeb(opaque, addr + 2, (val >> 16) & 0xff);
+        extioi_writeb(opaque, addr + 3, (val >> 24) & 0xff);
+    } else if ((offset >= EXTIOI_NODETYPE_START) &&
+               (offset < EXTIOI_NODETYPE_END)) {
+        reg_count = (offset - EXTIOI_NODETYPE_START) / 4;
+        state->nodetype_reg32[reg_count] = val;
+    }
+
+    DPRINTF("writew reg 0x" TARGET_FMT_plx " = %x\n", addr, val);
+}
+
+static void extioi_writel(void *opaque, hwaddr addr, uint64_t val)
+{
+    loongarch_extioi *state = (loongarch_extioi *)opaque;
+    int cpu, level;
+    uint64_t offset, old_data_u64, reg_count, mask, i;
+
+    offset = addr & 0xffff;
+
+    if ((offset >= EXTIOI_ENABLE_START) && (offset < EXTIOI_ENABLE_END)) {
+        reg_count = (offset - EXTIOI_ENABLE_START) / 8;
+        old_data_u64 = state->en_reg64[reg_count];
+        if (old_data_u64 != val) {
+            state->en_reg64[reg_count] = val;
+            old_data_u64 = old_data_u64 ^ val;
+            mask = 0x1;
+            for (i = 0; i < 8 * sizeof(old_data_u64); i++) {
+                if (old_data_u64 & mask) {
+                    level = !!(val & (0x1 << i));
+                    extioi_update_irq(state, i + reg_count * 64, level);
+                }
+                mask = mask << 1;
+            }
+        }
+    } else if ((offset >= EXTIOI_BOUNCE_START) &&
+               (offset < EXTIOI_BOUNCE_END)) {
+        reg_count = (offset - EXTIOI_BOUNCE_START) / 8;
+        state->bounce_reg64[reg_count] = val;
+    } else if ((offset >= EXTIOI_COREISR_START) &&
+               (offset < EXTIOI_COREISR_END)) {
+        reg_count = ((offset - EXTIOI_COREISR_START) & 0x1f) / 8;
+        cpu = ((offset - EXTIOI_COREISR_START) >> 8) & 0x3;
+
+        /* core_ext_ioisr */
+        old_data_u64 = state->coreisr_reg64[cpu][reg_count];
+        state->coreisr_reg64[cpu][reg_count] = old_data_u64 & (~val);
+
+        if (old_data_u64 != state->coreisr_reg64[cpu][reg_count]) {
+            mask = 0x1;
+            for (i = 0; i < 8 * sizeof(old_data_u64); i++) {
+                if ((old_data_u64 & mask) && (val & mask)) {
+                    extioi_update_irq(state, i + reg_count * 64, 0);
+                }
+                mask = mask << 1;
+            }
+        }
+    } else if ((offset >= EXTIOI_IPMAP_START) &&
+               (offset < EXTIOI_IPMAP_END)) {
+        extioi_writeb(opaque, addr, (val) & 0xff);
+        extioi_writeb(opaque, addr + 1, (val >> 8) & 0xff);
+        extioi_writeb(opaque, addr + 2, (val >> 16) & 0xff);
+        extioi_writeb(opaque, addr + 3, (val >> 24) & 0xff);
+        extioi_writeb(opaque, addr + 4, (val >> 32) & 0xff);
+        extioi_writeb(opaque, addr + 5, (val >> 40) & 0xff);
+        extioi_writeb(opaque, addr + 6, (val >> 48) & 0xff);
+        extioi_writeb(opaque, addr + 7, (val >> 56) & 0xff);
+    } else if ((offset >= EXTIOI_COREMAP_START) &&
+               (offset < EXTIOI_COREMAP_END)) {
+        extioi_writeb(opaque, addr, (val) & 0xff);
+        extioi_writeb(opaque, addr + 1, (val >> 8) & 0xff);
+        extioi_writeb(opaque, addr + 2, (val >> 16) & 0xff);
+        extioi_writeb(opaque, addr + 3, (val >> 24) & 0xff);
+        extioi_writeb(opaque, addr + 4, (val >> 32) & 0xff);
+        extioi_writeb(opaque, addr + 5, (val >> 40) & 0xff);
+        extioi_writeb(opaque, addr + 6, (val >> 48) & 0xff);
+        extioi_writeb(opaque, addr + 7, (val >> 56) & 0xff);
+    } else if ((offset >= EXTIOI_NODETYPE_START) &&
+               (offset < EXTIOI_NODETYPE_END)) {
+        reg_count = (offset - EXTIOI_NODETYPE_START) / 8;
+        state->nodetype_reg64[reg_count] = val;
+    }
+
+    DPRINTF("writel reg 0x" TARGET_FMT_plx " = %lx\n", addr, val);
+}
+
+static uint64_t extioi_readfn(void *opaque, hwaddr addr, unsigned size)
+{
+    switch (size) {
+    case 1:
+        return extioi_readb(opaque, addr);
+    case 4:
+        return extioi_readw(opaque, addr);
+    case 8:
+        return extioi_readl(opaque, addr);
+    default:
+        g_assert_not_reached();
+    }
+}
+
+static void extioi_writefn(void *opaque, hwaddr addr,
+                           uint64_t value, unsigned size)
+{
+    switch (size) {
+    case 1:
+        extioi_writeb(opaque, addr, value);
+        break;
+    case 4:
+        extioi_writew(opaque, addr, value);
+        break;
+    case 8:
+        extioi_writel(opaque, addr, value);
+        break;
+    default:
+        g_assert_not_reached();
+    }
+}
+
+static const MemoryRegionOps extioi_ops = {
+    .read = extioi_readfn,
+    .write = extioi_writefn,
+    .impl.min_access_size = 1,
+    .impl.max_access_size = 8,
+    .valid.min_access_size = 1,
+    .valid.max_access_size = 8,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static void loongarch_extioi_realize(DeviceState *dev, Error **errp)
+{
+    LoongarchMachineState *lsms = LOONGARCH_MACHINE(qdev_get_machine());
+    MachineState *ms = MACHINE(lsms);
+    loongarch_extioi *p = LOONGARCH_EXTIOI(dev);
+    int cpu, pin;
+
+    qdev_init_gpio_in(dev, extioi_setirq, EXTIOI_IRQS);
+
+    for (int i = 0; i < EXTIOI_IRQS; i++) {
+        sysbus_init_irq(SYS_BUS_DEVICE(dev), &p->irq[i]);
+    }
+
+    memory_region_init_io(&p->mmio, OBJECT(p), &extioi_ops, p,
+                          TYPE_LOONGARCH_EXTIOI, 0x900);
+    sysbus_init_mmio(SYS_BUS_DEVICE(dev), &p->mmio);
+
+    for (cpu = 0; cpu < ms->smp.cpus; cpu++) {
+        for (pin = 0; pin < LS3A_INTC_IP; pin++) {
+            sysbus_init_irq(SYS_BUS_DEVICE(dev), &p->parent_irq[cpu][pin]);
+        }
+    }
+
+    /* 0-31 is for non msi device.32-256 for msi/msix device */
+    lsms->pch_irq = qemu_allocate_irqs(extioi_handler, p, 256);
+}
+
+static const VMStateDescription vmstate_ext_sw_ipisr = {
+    .name = "ext_sw_ipisr",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8_ARRAY(irq, ext_sw_ipisr, EXTIOI_IRQS_BITMAP_SIZE),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_loongarch_extioi = {
+    .name = TYPE_LOONGARCH_EXTIOI,
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT8_ARRAY(en_reg8, loongarch_extioi, EXTIOI_IRQS_BITMAP_SIZE),
+        VMSTATE_UINT8_ARRAY(bounce_reg8, loongarch_extioi,
+                            EXTIOI_IRQS_BITMAP_SIZE),
+        VMSTATE_UINT8_ARRAY(isr_reg8, loongarch_extioi,
+                            EXTIOI_IRQS_BITMAP_SIZE),
+        VMSTATE_UINT8_2DARRAY(coreisr_reg8, loongarch_extioi, MAX_CORES,
+                              EXTIOI_IRQS_BITMAP_SIZE),
+        VMSTATE_UINT8_ARRAY(ipmap_reg8, loongarch_extioi,
+                            EXTIOI_IRQS_IPMAP_SIZE),
+        VMSTATE_UINT8_ARRAY(coremap_reg8, loongarch_extioi,
+                            EXTIOI_IRQS_COREMAP_SIZE),
+        VMSTATE_UINT16_ARRAY(nodetype_reg16, loongarch_extioi,
+                             EXTIOI_IRQS_NODETYPE_SIZE),
+        VMSTATE_UINT8_ARRAY(sw_ipmap, loongarch_extioi, EXTIOI_IRQS),
+        VMSTATE_UINT8_ARRAY(sw_coremap, loongarch_extioi, EXTIOI_IRQS),
+        VMSTATE_STRUCT_2DARRAY(sw_ipisr, loongarch_extioi, MAX_CORES,
+                               LS3A_INTC_IP, 1, vmstate_ext_sw_ipisr,
+                               ext_sw_ipisr),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void loongarch_extioi_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+
+    dc->vmsd = &vmstate_loongarch_extioi;
+    dc->realize = loongarch_extioi_realize;
+}
+
+static const TypeInfo loongarch_extioi_info = {
+    .name          = TYPE_LOONGARCH_EXTIOI,
+    .parent        = TYPE_SYS_BUS_DEVICE,
+    .instance_size = sizeof(struct loongarch_extioi),
+    .class_init    = loongarch_extioi_class_init,
+};
+
+static void loongarch_extioi_register_types(void)
+{
+    type_register_static(&loongarch_extioi_info);
+}
+
+type_init(loongarch_extioi_register_types)
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
index 749c27e072..189c73fa9d 100644
--- a/hw/intc/meson.build
+++ b/hw/intc/meson.build
@@ -60,3 +60,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_PCH_PIC', if_true: files('loongarch_pch_pic.c'))
 specific_ss.add(when: 'CONFIG_LOONGARCH_PCH_MSI', if_true: files('loongarch_pch_msi.c'))
+specific_ss.add(when: 'CONFIG_LOONGARCH_EXTIOI', if_true: files('loongarch_extioi.c'))
diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
index 4500fd3a57..9212127701 100644
--- a/hw/loongarch/Kconfig
+++ b/hw/loongarch/Kconfig
@@ -3,3 +3,4 @@ config LOONGSON_3A5000
     select PCI_EXPRESS_7A
     select LOONGARCH_PCH_PIC
     select LOONGARCH_PCH_MSI
+    select LOONGARCH_EXTIOI
diff --git a/include/hw/intc/loongarch_extioi.h b/include/hw/intc/loongarch_extioi.h
new file mode 100644
index 0000000000..0096c775c7
--- /dev/null
+++ b/include/hw/intc/loongarch_extioi.h
@@ -0,0 +1,100 @@
+/*
+ * Loongarch 3A5000 ext interrupt controller definitions
+ *
+ * Copyright (C) 2021 Loongson Technology Corporation Limited
+ *
+ * SPDX-License-Identifier: LGPL-2.1+
+ */
+
+#include "hw/sysbus.h"
+#include "hw/loongarch/loongarch.h"
+
+#ifndef LOONGARCH_EXTIOI_H
+#define LOONGARCH_EXTIOI_H
+
+#define LS3A_INTC_IP               8
+#define MAX_CORES                  LOONGARCH_MAX_VCPUS
+#define EXTIOI_IRQS                (256)
+#define EXTIOI_IRQS_BITMAP_SIZE    (256 / 8)
+/* map to ipnum per 32 irqs */
+#define EXTIOI_IRQS_IPMAP_SIZE     (256 / 32)
+#define EXTIOI_IRQS_COREMAP_SIZE   256
+#define EXTIOI_IRQS_NODETYPE_SIZE  16
+
+#define APIC_OFFSET                  0x400
+#define APIC_BASE                    (0x1fe01000ULL + APIC_OFFSET)
+
+#define EXTIOI_NODETYPE_START        (0x4a0 - APIC_OFFSET)
+#define EXTIOI_NODETYPE_END          (0x4c0 - APIC_OFFSET)
+#define EXTIOI_IPMAP_START           (0x4c0 - APIC_OFFSET)
+#define EXTIOI_IPMAP_END             (0x4c8 - APIC_OFFSET)
+#define EXTIOI_ENABLE_START          (0x600 - APIC_OFFSET)
+#define EXTIOI_ENABLE_END            (0x620 - APIC_OFFSET)
+#define EXTIOI_BOUNCE_START          (0x680 - APIC_OFFSET)
+#define EXTIOI_BOUNCE_END            (0x6a0 - APIC_OFFSET)
+#define EXTIOI_ISR_START             (0x700 - APIC_OFFSET)
+#define EXTIOI_ISR_END               (0x720 - APIC_OFFSET)
+#define EXTIOI_COREISR_START         (0x800 - APIC_OFFSET)
+#define EXTIOI_COREISR_END           (0xB20 - APIC_OFFSET)
+#define EXTIOI_COREMAP_START         (0xC00 - APIC_OFFSET)
+#define EXTIOI_COREMAP_END           (0xD00 - APIC_OFFSET)
+
+#define TYPE_LOONGARCH_EXTIOI "loongarch.extioi"
+DECLARE_INSTANCE_CHECKER(struct loongarch_extioi, LOONGARCH_EXTIOI,
+                         TYPE_LOONGARCH_EXTIOI)
+
+typedef struct ext_sw_ipisr {
+    uint8_t irq[EXTIOI_IRQS_BITMAP_SIZE];
+} ext_sw_ipisr;
+
+typedef struct loongarch_extioi {
+    SysBusDevice parent_obj;
+    /* hardware state */
+    union {
+        uint64_t en_reg64[EXTIOI_IRQS_BITMAP_SIZE / 8];
+        uint32_t en_reg32[EXTIOI_IRQS_BITMAP_SIZE / 4];
+        uint8_t en_reg8[EXTIOI_IRQS_BITMAP_SIZE];
+    };
+    union {
+        uint64_t bounce_reg64[EXTIOI_IRQS_BITMAP_SIZE / 8];
+        uint32_t bounce_reg32[EXTIOI_IRQS_BITMAP_SIZE / 4];
+        uint8_t bounce_reg8[EXTIOI_IRQS_BITMAP_SIZE];
+    };
+    union {
+        uint64_t isr_reg64[EXTIOI_IRQS_BITMAP_SIZE / 8];
+        uint32_t isr_reg32[EXTIOI_IRQS_BITMAP_SIZE / 4];
+        uint8_t isr_reg8[EXTIOI_IRQS_BITMAP_SIZE];
+    };
+    union {
+        uint64_t coreisr_reg64[MAX_CORES][EXTIOI_IRQS_BITMAP_SIZE / 8];
+        uint32_t coreisr_reg32[MAX_CORES][EXTIOI_IRQS_BITMAP_SIZE / 4];
+        uint8_t coreisr_reg8[MAX_CORES][EXTIOI_IRQS_BITMAP_SIZE];
+    };
+    union {
+        uint64_t ipmap_reg64;
+        uint32_t ipmap_reg32[EXTIOI_IRQS_IPMAP_SIZE / 4];
+        uint8_t ipmap_reg8[EXTIOI_IRQS_IPMAP_SIZE];
+    };
+    union {
+        uint64_t coremap_reg64[EXTIOI_IRQS_COREMAP_SIZE / 8];
+        uint32_t coremap_reg32[EXTIOI_IRQS_COREMAP_SIZE / 4];
+        uint8_t coremap_reg8[EXTIOI_IRQS_COREMAP_SIZE];
+    };
+    union {
+        uint64_t nodetype_reg64[EXTIOI_IRQS_NODETYPE_SIZE / 4];
+        uint32_t nodetype_reg32[EXTIOI_IRQS_NODETYPE_SIZE / 2];
+        uint16_t nodetype_reg16[EXTIOI_IRQS_NODETYPE_SIZE];
+        uint8_t nodetype_reg8[EXTIOI_IRQS_NODETYPE_SIZE * 2];
+    };
+
+    /*software state */
+    uint8_t sw_ipmap[EXTIOI_IRQS];
+    uint8_t sw_coremap[EXTIOI_IRQS];
+    ext_sw_ipisr sw_ipisr[MAX_CORES][LS3A_INTC_IP];
+
+    qemu_irq parent_irq[MAX_CORES][LS3A_INTC_IP];
+    qemu_irq irq[EXTIOI_IRQS];
+    MemoryRegion mmio;
+} loongarch_extioi;
+
+#endif /* LOONGARCH_EXTIOI_H */
diff --git a/include/hw/loongarch/loongarch.h b/include/hw/loongarch/loongarch.h
index 8e98430747..210173471d 100644
--- a/include/hw/loongarch/loongarch.h
+++ b/include/hw/loongarch/loongarch.h
@@ -41,6 +41,7 @@ typedef struct LoongarchMachineState {
     MachineState parent_obj;
 
     gipiState   *gipi;
+    qemu_irq    *pch_irq;
 } LoongarchMachineState;
 
 #define TYPE_LOONGARCH_MACHINE  MACHINE_TYPE_NAME("loongson7a")
-- 
2.27.0



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

* [PATCH 20/31] hw/loongarch: Add irq hierarchy for the system
  2021-10-19  7:34 [PATCH 00/31] Add Loongarch softmmu support Xiaojuan Yang
                   ` (15 preceding siblings ...)
  2021-10-19  7:35 ` [PATCH 19/31] hw/intc: Add loongarch extioi interrupt controller(EIOINTC) Xiaojuan Yang
@ 2021-10-19  7:35 ` Xiaojuan Yang
  2021-10-19 14:52 ` [PATCH 00/31] Add Loongarch softmmu support WANG Xuerui
                   ` (4 subsequent siblings)
  21 siblings, 0 replies; 37+ messages in thread
From: Xiaojuan Yang @ 2021-10-19  7:35 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, richard.henderson,
	laurent, peterx, f4bug, yangxiaojuan, alistair.francis, maobibo,
	gaosong, pbonzini, mark.cave-ayland, bmeng.cn, alex.bennee,
	david

This patch add the irq hierarchy for the virt board.

Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
Signed-off-by: Song Gao <gaosong@loongson.cn>
---
 hw/loongarch/ls3a5000_virt.c | 49 ++++++++++++++++++++++++++++++++++++
 include/hw/pci-host/ls7a.h   |  4 +++
 2 files changed, 53 insertions(+)

diff --git a/hw/loongarch/ls3a5000_virt.c b/hw/loongarch/ls3a5000_virt.c
index 115954033e..89fee1fd9b 100644
--- a/hw/loongarch/ls3a5000_virt.c
+++ b/hw/loongarch/ls3a5000_virt.c
@@ -16,6 +16,9 @@
 #include "sysemu/runstate.h"
 #include "sysemu/reset.h"
 #include "hw/loongarch/loongarch.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"
 
 CPULoongArchState *cpu_states[LOONGARCH_MAX_VCPUS];
@@ -103,6 +106,49 @@ static const MemoryRegionOps loongarch_qemu_ops = {
     },
 };
 
+static void ls3a5000_irq_init(MachineState *machine, CPULoongArchState *env[])
+{
+    LoongarchMachineState *lsms = LOONGARCH_MACHINE(machine);
+    DeviceState *extioi, *pch_pic, *pch_msi;
+    SysBusDevice *d;
+    int cpu, pin, i;
+
+    extioi = qdev_new(TYPE_LOONGARCH_EXTIOI);
+    d = SYS_BUS_DEVICE(extioi);
+    sysbus_realize_and_unref(d, &error_fatal);
+    sysbus_mmio_map(d, 0, APIC_BASE);
+
+    for (i = 0; i < EXTIOI_IRQS; i++) {
+        sysbus_connect_irq(d, i, qdev_get_gpio_in(extioi, i));
+    }
+
+    for (cpu = 0; cpu < machine->smp.cpus; cpu++) {
+        /* cpu_pin[9:2] <= intc_pin[7:0] */
+        for (pin = 0; pin < LS3A_INTC_IP; pin++) {
+            sysbus_connect_irq(d, (EXTIOI_IRQS + cpu * 8 + pin),
+                               env[cpu]->irq[pin + 2]);
+        }
+    }
+
+    pch_pic = qdev_new(TYPE_LOONGARCH_PCH_PIC);
+    d = SYS_BUS_DEVICE(pch_pic);
+    sysbus_realize_and_unref(d, &error_fatal);
+    sysbus_mmio_map(d, 0, LS7A_IOAPIC_REG_BASE);
+
+    for (int i = 0; i < 32; i++) {
+        sysbus_connect_irq(d, i, lsms->pch_irq[i]);
+    }
+
+    pch_msi = qdev_new(TYPE_LOONGARCH_PCH_MSI);
+    d = SYS_BUS_DEVICE(pch_msi);
+    sysbus_realize_and_unref(d, &error_fatal);
+    sysbus_mmio_map(d, 0, LS7A_PCH_MSI_ADDR_LOW);
+    for (i = 0; i < 224; i++) {
+        sysbus_connect_irq(d, i, lsms->pch_irq[i + 32]);
+    }
+
+}
+
 static void ls3a5000_virt_init(MachineState *machine)
 {
     const char *cpu_model = machine->cpu_type;
@@ -175,6 +221,9 @@ static void ls3a5000_virt_init(MachineState *machine)
     memory_region_add_subregion(address_space_mem,
                                 PM_MMIO_ADDR, iomem);
 
+    /*Initialize the IO interrupt subsystem*/
+    ls3a5000_irq_init(machine, cpu_states);
+
     LOONGARCH_SIMPLE_MMIO_OPS(FEATURE_REG, "loongarch_feature", 0x8);
     LOONGARCH_SIMPLE_MMIO_OPS(VENDOR_REG, "loongarch_vendor", 0x8);
     LOONGARCH_SIMPLE_MMIO_OPS(CPUNAME_REG, "loongarch_cpuname", 0x8);
diff --git a/include/hw/pci-host/ls7a.h b/include/hw/pci-host/ls7a.h
index 4c95a11ab8..e957c8c855 100644
--- a/include/hw/pci-host/ls7a.h
+++ b/include/hw/pci-host/ls7a.h
@@ -24,6 +24,10 @@
 
 #define LS7A_PCI_IO_BASE        0x18000000UL
 #define LS7A_PCI_IO_SIZE        0x00010000
+#define LS7A_PCH_REG_BASE       0x10000000UL
+#define LS7A_IOAPIC_REG_BASE    (LS7A_PCH_REG_BASE)
+#define LS7A_PCH_MSI_ADDR_LOW   0x2FF00000UL
+
 typedef struct LS7APCIState LS7APCIState;
 typedef struct LS7APCIEHost {
     PCIExpressHost parent_obj;
-- 
2.27.0



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

* Re: [PATCH 00/31] Add Loongarch softmmu support.
  2021-10-19  7:34 [PATCH 00/31] Add Loongarch softmmu support Xiaojuan Yang
                   ` (16 preceding siblings ...)
  2021-10-19  7:35 ` [PATCH 20/31] hw/loongarch: Add irq hierarchy for the system Xiaojuan Yang
@ 2021-10-19 14:52 ` WANG Xuerui
       [not found]   ` <7d933f8d.228e.17c9b556e98.Coremail.yangxiaojuan@loongson.cn>
       [not found] ` <1634628917-10031-24-git-send-email-yangxiaojuan@loongson.cn>
                   ` (3 subsequent siblings)
  21 siblings, 1 reply; 37+ messages in thread
From: WANG Xuerui @ 2021-10-19 14:52 UTC (permalink / raw)
  To: Xiaojuan Yang, qemu-devel
  Cc: peter.maydell, thuth, mst, david, mark.cave-ayland,
	richard.henderson, laurent, peterx, f4bug, alex.bennee,
	alistair.francis, maobibo, gaosong, pbonzini, bmeng.cn, philmd,
	chenhuacai

Hi Xiaojuan,

On 10/19/21 15:34, Xiaojuan Yang wrote:
> This series patch add softmmu support for LoongArch.
> Base on the linux-user emulation support V7 patch.
>
> The latest kernel:
>    * https://github.com/loongson/linux/tree/loongarch-next
> The manual:
>    * https://github.com/loongson/LoongArch-Documentation/releases/tag/2021.10.11
>
> Patch 1 Add a readme for code download and supply binary for test.
> Patch 2-3 define CSR registers and set the init/reset value.
> Patch 4-5 Add cpu related functions.
> Patch 6-12 Add Privileged instruction simulation used by LoongArch.
> Patch 13 Emulate a virt pci host based on the LoongArch 7A1000.
> Patch 14 Emulate a virt 3a5000 board different from host.
> Patch 15-20 Emulate the interrupt controller used by the virt board.
> Patch 21-22 Add devices used by the board.
> Patch 23-25 Add bios and smbios support needed for the start.
> Patch 26 Add a simple acpi model.
> Patch 27 Enable mttcg mode.
> Patch 28-29 Support for numa more than 4 cpus.
> Patch 30-31 Add some functions for debug.
>
> Xiaojuan Yang (31):
>    target/loongarch: Upate the README for the softmmu.

Nit: "Update", also remove the trailing period -- QEMU style doesn't 
mandate full sentences for title line of commit messages AFAIK. Other 
places should be fixed as well.

>    target/loongarch: Add CSR registers definition
>    target/loongarch: Set default csr values.
>    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 csr/iocsr instruction support
And please use consistent casing for "LoongArch", "CSR", "IOCSR", "MMU", 
"TLB" etc etc -- again fix everywhere you can.
>    target/loongarch: Add tlb instruction support
>    target/loongarch: Add other core instructions support
>    target/loongarch: Add loongarch interrupt and exception handle
>    target/loongarch: Add stabletimer support
>    target/loongarch: Add timer related instructions support.
>    hw/pci-host: Add ls7a1000 PCIe Host bridge support for Loongson
>      Platform
>    hw/loongarch: Add a virt loongarch 3A5000 board support
>    hw/loongarch: Add loongarch cpu interrupt support(CPUINTC)
>    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
>    hw/loongarch: Add some devices support for 3A5000.
>    hw/loongarch: Add loongarch ls7a rtc device support
>    hw/loongarch: Add default bios startup support.
>    hw/loongarch: Add -kernel and -initrd options support
>    hw/loongarch: Add loongarch smbios support
>    hw/loongarch: Add loongarch acpi support
>    hw/loongarch: Add mttcg mode support
>    hw/loongarch: use machine->possible_cpus for storing possible topology
>      info
>    hw/loongarch: Add numa support.
>    target/loongarch: Add gdb support.
>    target/loongarch: Add privilege instructions diassembly
>
>   .../devices/loongarch64-softmmu/default.mak   |   3 +
>   configs/targets/loongarch64-softmmu.mak       |   4 +
>   disas/loongarch.c                             | 173 ++++
>   gdb-xml/loongarch-base64.xml                  |  43 +
>   gdb-xml/loongarch-fpu64.xml                   |  57 ++
>   hw/Kconfig                                    |   1 +
>   hw/acpi/Kconfig                               |   4 +
>   hw/acpi/ls7a.c                                | 351 +++++++
>   hw/acpi/meson.build                           |   1 +
>   hw/intc/Kconfig                               |  12 +
>   hw/intc/loongarch_extioi.c                    | 589 +++++++++++
>   hw/intc/loongarch_pch_msi.c                   |  74 ++
>   hw/intc/loongarch_pch_pic.c                   | 284 ++++++
>   hw/intc/meson.build                           |   3 +
>   hw/loongarch/Kconfig                          |  22 +
>   hw/loongarch/acpi-build.c                     | 661 +++++++++++++
>   hw/loongarch/fw_cfg.c                         |  34 +
>   hw/loongarch/fw_cfg.h                         |  16 +
>   hw/loongarch/ipi.c                            | 147 +++
>   hw/loongarch/loongarch_int.c                  |  62 ++
>   hw/loongarch/ls3a5000_virt.c                  | 638 ++++++++++++
>   hw/loongarch/meson.build                      |   7 +
>   hw/meson.build                                |   1 +
>   hw/pci-host/Kconfig                           |   4 +
>   hw/pci-host/ls7a.c                            | 224 +++++
>   hw/pci-host/meson.build                       |   1 +
>   hw/rtc/Kconfig                                |   3 +
>   hw/rtc/ls7a_rtc.c                             | 327 +++++++
>   hw/rtc/meson.build                            |   1 +
>   include/exec/poison.h                         |   2 +
>   include/hw/acpi/ls7a.h                        |  54 ++
>   include/hw/intc/loongarch_extioi.h            | 102 ++
>   include/hw/intc/loongarch_pch_msi.h           |  17 +
>   include/hw/intc/loongarch_pch_pic.h           |  50 +
>   include/hw/loongarch/gipi.h                   |  38 +
>   include/hw/loongarch/loongarch.h              |  79 ++
>   include/hw/pci-host/ls7a.h                    |  67 ++
>   include/sysemu/arch_init.h                    |   1 +
>   linux-user/loongarch64/cpu_loop.c             |   3 +-
>   pc-bios/loongarch_bios.bin                    | Bin 0 -> 4128768 bytes
>   qapi/machine-target.json                      |   6 +-
>   qapi/machine.json                             |   2 +-
>   softmmu/qdev-monitor.c                        |   3 +-
>   target/Kconfig                                |   1 +
>   target/loongarch/Kconfig                      |   2 +
>   target/loongarch/README                       | 134 +++
>   target/loongarch/cpu-csr.h                    | 493 ++++++++++
>   target/loongarch/cpu.c                        | 448 ++++++++-
>   target/loongarch/cpu.h                        |  56 +-
>   target/loongarch/csr_helper.c                 | 765 +++++++++++++++
>   target/loongarch/gdbstub.c                    |  95 ++
>   target/loongarch/helper.h                     |  24 +
>   target/loongarch/insn_trans/trans_core.c      | 302 ++++++
>   target/loongarch/insn_trans/trans_extra.c     |   2 +
>   target/loongarch/insns.decode                 |  45 +
>   target/loongarch/internals.h                  |  93 ++
>   target/loongarch/machine.c                    | 253 +++++
>   target/loongarch/meson.build                  |  10 +
>   target/loongarch/op_helper.c                  |  77 +-
>   target/loongarch/ramdisk                      | Bin 0 -> 3077952 bytes
>   target/loongarch/stabletimer.c                |  71 ++
>   target/loongarch/tlb_helper.c                 | 918 ++++++++++++++++++
>   target/loongarch/translate.c                  |   8 +-
>   target/loongarch/vmlinux                      | Bin 0 -> 24565536 bytes

Well, it might not be exactly nice to add ~30MiB of blob right here, via 
mailing list? IIUC everyone here can only see 17 of your 31 patches, 
maybe the blob-containing mail and subsequent ones all got blocked?

And perhaps it's not okay to put blobs inside target/ in the first 
place, a quick `tree` look at main branch reveals no such file. You may 
host these blobs (better yet, properly open-sourced repos) elsewhere and 
link to them in README instead.

>   64 files changed, 7955 insertions(+), 13 deletions(-)
>   create mode 100644 configs/devices/loongarch64-softmmu/default.mak
>   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 hw/acpi/ls7a.c
>   create mode 100644 hw/intc/loongarch_extioi.c
>   create mode 100644 hw/intc/loongarch_pch_msi.c
>   create mode 100644 hw/intc/loongarch_pch_pic.c
>   create mode 100644 hw/loongarch/Kconfig
>   create mode 100644 hw/loongarch/acpi-build.c
>   create mode 100644 hw/loongarch/fw_cfg.c
>   create mode 100644 hw/loongarch/fw_cfg.h
>   create mode 100644 hw/loongarch/ipi.c
>   create mode 100644 hw/loongarch/loongarch_int.c
>   create mode 100644 hw/loongarch/ls3a5000_virt.c
>   create mode 100644 hw/loongarch/meson.build
>   create mode 100644 hw/pci-host/ls7a.c
>   create mode 100644 hw/rtc/ls7a_rtc.c
While I haven't seen the entirety of the series, these files got created 
but MAINTAINERS is not updated. Please update the corresponding entries.
>   create mode 100644 include/hw/acpi/ls7a.h
>   create mode 100644 include/hw/intc/loongarch_extioi.h
>   create mode 100644 include/hw/intc/loongarch_pch_msi.h
>   create mode 100644 include/hw/intc/loongarch_pch_pic.h
>   create mode 100644 include/hw/loongarch/gipi.h
>   create mode 100644 include/hw/loongarch/loongarch.h
>   create mode 100644 include/hw/pci-host/ls7a.h
>   create mode 100644 pc-bios/loongarch_bios.bin
>   create mode 100644 target/loongarch/Kconfig
>   create mode 100644 target/loongarch/cpu-csr.h
>   create mode 100644 target/loongarch/csr_helper.c
>   create mode 100644 target/loongarch/gdbstub.c
>   create mode 100644 target/loongarch/insn_trans/trans_core.c
>   create mode 100644 target/loongarch/machine.c
>   create mode 100644 target/loongarch/ramdisk
>   create mode 100644 target/loongarch/stabletimer.c
>   create mode 100644 target/loongarch/tlb_helper.c
>   create mode 100755 target/loongarch/vmlinux
>


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

* Re: [PATCH 23/31] hw/loongarch: Add default bios startup support.
       [not found] ` <1634628917-10031-24-git-send-email-yangxiaojuan@loongson.cn>
@ 2021-10-19 16:19   ` Michael S. Tsirkin
  0 siblings, 0 replies; 37+ messages in thread
From: Michael S. Tsirkin @ 2021-10-19 16:19 UTC (permalink / raw)
  To: Xiaojuan Yang
  Cc: gaosong, peter.maydell, thuth, chenhuacai, philmd,
	richard.henderson, qemu-devel, peterx, laurent, alistair.francis,
	maobibo, david, pbonzini, mark.cave-ayland, bmeng.cn,
	alex.bennee, f4bug

On Tue, Oct 19, 2021 at 03:35:09PM +0800, Xiaojuan Yang wrote:
> This patch add default bios startup.
> The bios source code will be opened int the near future.

That pretty much rules out including this patchset for now ...
Does not mean people won't review, but please tag the subject RFC
until it's all open source and can be merged.
And I would really appreciate not getting CC'd until it is.

Thanks!

> Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
>  hw/loongarch/Kconfig             |   4 +++
>  hw/loongarch/fw_cfg.c            |  34 ++++++++++++++++++
>  hw/loongarch/fw_cfg.h            |  16 +++++++++
>  hw/loongarch/ls3a5000_virt.c     |  60 ++++++++++++++++++++++++-------
>  hw/loongarch/meson.build         |   1 +
>  include/hw/loongarch/loongarch.h |   5 +++
>  pc-bios/loongarch_bios.bin       | Bin 0 -> 4128768 bytes
>  7 files changed, 108 insertions(+), 12 deletions(-)
>  create mode 100644 hw/loongarch/fw_cfg.c
>  create mode 100644 hw/loongarch/fw_cfg.h
>  create mode 100644 pc-bios/loongarch_bios.bin
> 
> diff --git a/hw/loongarch/Kconfig b/hw/loongarch/Kconfig
> index fe100b01eb..b59cd98a7a 100644
> --- a/hw/loongarch/Kconfig
> +++ b/hw/loongarch/Kconfig
> @@ -13,3 +13,7 @@ config LOONGSON_3A5000
>      select LOONGARCH_PCH_MSI
>      select LOONGARCH_EXTIOI
>      select LS7A_RTC
> +    select FW_CFG_LOONGARCH
> +
> +config FW_CFG_LOONGARCH
> +    bool
> diff --git a/hw/loongarch/fw_cfg.c b/hw/loongarch/fw_cfg.c
> new file mode 100644
> index 0000000000..42229c5c91
> --- /dev/null
> +++ b/hw/loongarch/fw_cfg.c
> @@ -0,0 +1,34 @@
> +/*
> + * QEMU fw_cfg helpers (LOONGARCH specific)
> + *
> + * Copyright (C) 2021 Loongson Technology Corporation Limited
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include "qemu/osdep.h"
> +#include "hw/loongarch/fw_cfg.h"
> +#include "hw/loongarch/loongarch.h"
> +#include "hw/nvram/fw_cfg.h"
> +#include "sysemu/sysemu.h"
> +
> +static void fw_cfg_boot_set(void *opaque, const char *boot_device,
> +                            Error **errp)
> +{
> +    fw_cfg_modify_i16(opaque, FW_CFG_BOOT_DEVICE, boot_device[0]);
> +}
> +
> +FWCfgState *loongarch_fw_cfg_init(ram_addr_t ram_size, MachineState *ms)
> +{
> +    FWCfgState *fw_cfg;
> +    int max_cpus = ms->smp.max_cpus;
> +    int smp_cpus = ms->smp.cpus;
> +
> +    fw_cfg = fw_cfg_init_mem_wide(FW_CFG_ADDR, FW_CFG_ADDR + 8, 8, 0, NULL);
> +    fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus);
> +    fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size);
> +    fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus);
> +
> +    qemu_register_boot_set(fw_cfg_boot_set, fw_cfg);
> +    return fw_cfg;
> +}
> diff --git a/hw/loongarch/fw_cfg.h b/hw/loongarch/fw_cfg.h
> new file mode 100644
> index 0000000000..d51dfb241a
> --- /dev/null
> +++ b/hw/loongarch/fw_cfg.h
> @@ -0,0 +1,16 @@
> +/*
> + * QEMU fw_cfg helpers (Loongarch specific)
> + *
> + * Copyright (C) 2021 Loongson Technology Corporation Limited
> + *
> + * SPDX-License-Identifier: MIT
> + */
> +
> +#ifndef HW_LOONGARCH_FW_CFG_H
> +#define HW_LOONGARCH_FW_CFG_H
> +
> +#include "hw/boards.h"
> +#include "hw/nvram/fw_cfg.h"
> +
> +FWCfgState *loongarch_fw_cfg_init(ram_addr_t ram_size, MachineState *ms);
> +#endif
> diff --git a/hw/loongarch/ls3a5000_virt.c b/hw/loongarch/ls3a5000_virt.c
> index 79e6605cd8..e8057f7772 100644
> --- a/hw/loongarch/ls3a5000_virt.c
> +++ b/hw/loongarch/ls3a5000_virt.c
> @@ -14,6 +14,8 @@
>  #include "hw/char/serial.h"
>  #include "sysemu/sysemu.h"
>  #include "sysemu/qtest.h"
> +#include "hw/loader.h"
> +#include "elf.h"
>  #include "hw/irq.h"
>  #include "net/net.h"
>  #include "sysemu/runstate.h"
> @@ -24,6 +26,9 @@
>  #include "hw/intc/loongarch_pch_msi.h"
>  #include "hw/pci-host/ls7a.h"
>  #include "hw/misc/unimp.h"
> +#include "hw/loongarch/fw_cfg.h"
> +
> +#define LOONGSON3_BIOSNAME "loongarch_bios.bin"
>  
>  CPULoongArchState *cpu_states[LOONGARCH_MAX_VCPUS];
>  
> @@ -181,8 +186,9 @@ static void ls3a5000_virt_init(MachineState *machine)
>      const char *cpu_model = machine->cpu_type;
>      LoongArchCPU *cpu;
>      CPULoongArchState *env;
> -    uint64_t lowram_size = 0, highram_size = 0;
> +    uint64_t highram_size = 0;
>      MemoryRegion *lowmem = g_new(MemoryRegion, 1);
> +    MemoryRegion *highmem = g_new(MemoryRegion, 1);
>      char *ramName = NULL;
>      ram_addr_t ram_size = machine->ram_size;
>      MemoryRegion *address_space_mem = get_system_memory();
> @@ -190,6 +196,10 @@ static void ls3a5000_virt_init(MachineState *machine)
>      int i;
>      MemoryRegion *iomem = NULL;
>      PCIBus *pci_bus = NULL;
> +    int bios_size;
> +    char *filename;
> +    MemoryRegion *bios = g_new(MemoryRegion, 1);
> +    ram_addr_t offset = 0;
>  
>      if (!cpu_model) {
>          cpu_model = LOONGARCH_CPU_TYPE_NAME("Loongson-3A5000");
> @@ -227,21 +237,46 @@ static void ls3a5000_virt_init(MachineState *machine)
>          qemu_register_reset(main_cpu_reset, cpu);
>      }
>  
> +    if (ram_size < 1 * GiB) {
> +        error_report("ram_size must be greater than 1G due to the bios memory layout");
> +        exit(1);
> +    }
> +
>      ramName = g_strdup_printf("loongarch.lowram");
> -    lowram_size = MIN(ram_size, 256 * 0x100000);
>      memory_region_init_alias(lowmem, NULL, ramName, machine->ram,
> -                             0, lowram_size);
> -    memory_region_add_subregion(address_space_mem, 0, lowmem);
> -
> -    highram_size = ram_size > lowram_size ? ram_size - 256 * 0x100000 : 0;
> -    if (highram_size > 0) {
> -        MemoryRegion *highmem = g_new(MemoryRegion, 1);
> -        ramName = g_strdup_printf("loongarch.highram");
> -        memory_region_init_alias(highmem, NULL, ramName, machine->ram,
> -                                 lowram_size, highram_size);
> -        memory_region_add_subregion(address_space_mem, 0x90000000, highmem);
> +                             0, 256 * MiB);
> +    memory_region_add_subregion(address_space_mem, offset, lowmem);
> +    offset += 256 * MiB;
> +
> +    highram_size = ram_size - 256 * MiB;
> +    ramName = g_strdup_printf("loongarch.highram");
> +    memory_region_init_alias(highmem, NULL, ramName, machine->ram,
> +                             offset, highram_size);
> +    memory_region_add_subregion(address_space_mem, 0x90000000, highmem);
> +    offset += highram_size;
> +
> +    /* load the BIOS image. */
> +    filename = qemu_find_file(QEMU_FILE_TYPE_BIOS,
> +                              machine->firmware ?: LOONGSON3_BIOSNAME);
> +    if (filename) {
> +        bios_size = load_image_targphys(filename, LA_BIOS_BASE, LA_BIOS_SIZE);
> +        lsms->fw_cfg = loongarch_fw_cfg_init(ram_size, machine);
> +        rom_set_fw(lsms->fw_cfg);
> +        g_free(filename);
> +    } else {
> +        bios_size = -1;
>      }
>  
> +    if ((bios_size < 0 || bios_size > LA_BIOS_SIZE) && !qtest_enabled()) {
> +        error_report("Could not load LOONGARCH bios '%s'", machine->firmware);
> +        exit(1);
> +    }
> +
> +    memory_region_init_ram(bios, NULL, "loongarch.bios",
> +                           LA_BIOS_SIZE, &error_fatal);
> +    memory_region_set_readonly(bios, true);
> +    memory_region_add_subregion(get_system_memory(), LA_BIOS_BASE, bios);
> +
>      /*Add PM mmio memory for reboot and shutdown*/
>      iomem = g_new(MemoryRegion, 1);
>      memory_region_init_io(iomem, NULL, &loongarch_pm_ops, NULL,
> @@ -293,6 +328,7 @@ static void loongarch_class_init(ObjectClass *oc, void *data)
>      mc->default_ram_id = "loongarch.ram";
>      mc->max_cpus = LOONGARCH_MAX_VCPUS;
>      mc->is_default = 1;
> +    mc->default_machine_opts = "firmware=loongarch_bios.bin";
>      mc->default_kernel_irqchip_split = false;
>      mc->block_default_type = IF_VIRTIO;
>      mc->default_boot_order = "c";
> diff --git a/hw/loongarch/meson.build b/hw/loongarch/meson.build
> index 1bd209c9eb..3fabfa72dc 100644
> --- a/hw/loongarch/meson.build
> +++ b/hw/loongarch/meson.build
> @@ -1,5 +1,6 @@
>  loongarch_ss = ss.source_set()
>  loongarch_ss.add(files('loongarch_int.c'))
>  loongarch_ss.add(when: 'CONFIG_LOONGSON_3A5000', if_true: files('ls3a5000_virt.c', 'ipi.c'))
> +loongarch_ss.add(when: 'CONFIG_FW_CFG_LOONGARCH', if_true: files('fw_cfg.c'))
>  
>  hw_arch += {'loongarch': loongarch_ss}
> diff --git a/include/hw/loongarch/loongarch.h b/include/hw/loongarch/loongarch.h
> index 210173471d..1316707f49 100644
> --- a/include/hw/loongarch/loongarch.h
> +++ b/include/hw/loongarch/loongarch.h
> @@ -35,6 +35,10 @@
>  #define CPUNAME_REG             0x1fe00020
>  #define MISC_FUNC_REG           0x1fe00420
>  #define FREQ_REG                0x1fe001d0
> +#define FW_CFG_ADDR             0x1e020000
> +
> +#define LA_BIOS_BASE            0x1c000000
> +#define LA_BIOS_SIZE            (4 * 1024 * 1024)
>  
>  typedef struct LoongarchMachineState {
>      /*< private >*/
> @@ -42,6 +46,7 @@ typedef struct LoongarchMachineState {
>  
>      gipiState   *gipi;
>      qemu_irq    *pch_irq;
> +    FWCfgState  *fw_cfg;
>  } LoongarchMachineState;
>  
>  #define TYPE_LOONGARCH_MACHINE  MACHINE_TYPE_NAME("loongson7a")

> new file mode 100644
> index 0000000000000000000000000000000000000000..ac6a691b00ac4fec9a5f4c32aad3865ac24efbb2
> GIT binary patch
> literal 4128768
> zcmeFaeSB5bmH)qTZUU$YBpL)1^`ZgKNkOsI7FumjAQU@;6`PrcY8-A%fLMccI<`Eh
> z^#F-&r#C#PE#MOuB~;r4@mXsfP6C3Rl7QoPs`iPig0{bg2ggo>59EA5YoFYk+-ssv
> 


snipped a ton of binary

> literal 0
> HcmV?d00001
> 
> -- 
> 2.27.0



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

* Re: [PATCH 01/31] target/loongarch: Upate the README for the softmmu.
       [not found] ` <1634628917-10031-2-git-send-email-yangxiaojuan@loongson.cn>
@ 2021-10-19 18:56   ` Richard Henderson
  2021-10-22  2:25     ` yangxiaojuan
  0 siblings, 1 reply; 37+ messages in thread
From: Richard Henderson @ 2021-10-19 18:56 UTC (permalink / raw)
  To: Xiaojuan Yang, qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, mark.cave-ayland,
	laurent, peterx, f4bug, alistair.francis, maobibo, gaosong,
	pbonzini, bmeng.cn, alex.bennee, david

On 10/19/21 12:34 AM, Xiaojuan Yang wrote:
> ---
>   target/loongarch/README  | 134 +++++++++++++++++++++++++++++++++++++++
>   target/loongarch/ramdisk | Bin 0 -> 3077952 bytes
>   target/loongarch/vmlinux | Bin 0 -> 24565536 bytes
>   3 files changed, 134 insertions(+)
>   create mode 100644 target/loongarch/ramdisk
>   create mode 100755 target/loongarch/vmlinux

Wang Xuerui has already mentioned this, but let's make sure not to include such large test 
binaries in future.

The proper place for this is in a stable url, which could then either be referenced in the 
documentation.  But even better than that would be an acceptance test entry -- see 
tests/acceptance/boot_linux_console.py.

> +  2.Modify the kernel code for the tcg. Modifications are listed later. I will try to
> +    commit to the kernel host.

This sounds like a bug in the qemu emulation of the device or boot environment.


r~


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

* Re: [PATCH 02/31] target/loongarch: Add CSR registers definition
  2021-10-19  7:34 ` [PATCH 02/31] target/loongarch: Add CSR registers definition Xiaojuan Yang
@ 2021-10-19 19:10   ` Richard Henderson
  0 siblings, 0 replies; 37+ messages in thread
From: Richard Henderson @ 2021-10-19 19:10 UTC (permalink / raw)
  To: Xiaojuan Yang, qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, mark.cave-ayland,
	laurent, peterx, f4bug, alistair.francis, maobibo, gaosong,
	pbonzini, bmeng.cn, alex.bennee, david

On 10/19/21 12:34 AM, Xiaojuan Yang wrote:
> +/*
> + * All Possible CSR registers used by tcg
> + *
> + * default value  in target/loongarch/cpu.c
> + *
> + * This macro will be used only in:
> + *  > target/loongarch/cpu.h:CPULoongArchState
> + *
> + * during translate:
> + *  > helper_csr_rdq()
> + *  > helper_csr_wrq()
> + *  > helper_csr_xchgq()
> + *  > helper_csr_xchgq_r0()
> + */
> +#define CPU_LOONGARCH_CSR    \
> +    uint64_t CSR_CRMD;       \
> +    uint64_t CSR_PRMD;       \

I don't see the point in this macro.  Just put the structure members directly into 
CPULoongArchState.

In addition, I think you'll want to include these members unconditionally.  We have found 
for ARM that it is easiest to minimize the differences between system and user emulation. 
  Having to ifdef each use of the csrs does not help.


r~


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

* Re: [PATCH 03/31] target/loongarch: Set default csr values.
  2021-10-19  7:34 ` [PATCH 03/31] target/loongarch: Set default csr values Xiaojuan Yang
@ 2021-10-19 19:18   ` Richard Henderson
  0 siblings, 0 replies; 37+ messages in thread
From: Richard Henderson @ 2021-10-19 19:18 UTC (permalink / raw)
  To: Xiaojuan Yang, qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, mark.cave-ayland,
	laurent, peterx, f4bug, alistair.francis, maobibo, gaosong,
	pbonzini, bmeng.cn, alex.bennee, david

On 10/19/21 12:34 AM, Xiaojuan Yang wrote:
> +#ifndef CONFIG_USER_ONLY
> +static void set_loongarch_csr(CPULoongArchState *env)
> +{
> +    uint64_t t;
> +
> +    t = FIELD_DP64(0, CSR_PRCFG1, SAVE_NUM, 8);
> +    t = FIELD_DP64(t, CSR_PRCFG1, TIMER_BITS, 0x2f);
> +    t = FIELD_DP64(t, CSR_PRCFG1, VSMAX, 0x7);
> +    env->CSR_PRCFG1 = t;
> +
> +    env->CSR_PRCFG2 = 0x3ffff000;
> +
> +    t = FIELD_DP64(0, CSR_PRCFG3, TLB_TYPE, 2);
> +    t = FIELD_DP64(t, CSR_PRCFG3, MTLB_ENTRY, 0x3f);
> +    t = FIELD_DP64(t, CSR_PRCFG3, STLB_WAYS, 0x7);
> +    t = FIELD_DP64(t, CSR_PRCFG3, STLB_SETS, 0x8);
> +    env->CSR_PRCFG3 = t;
> +
> +    t = FIELD_DP64(0, CSR_CRMD, PLV, 0);
> +    t = FIELD_DP64(t, CSR_CRMD, IE, 0);
> +    t = FIELD_DP64(t, CSR_CRMD, DA, 1);
> +    t = FIELD_DP64(t, CSR_CRMD, PG, 0);
> +    t = FIELD_DP64(t, CSR_CRMD, DATF, 1);
> +    t = FIELD_DP64(t, CSR_CRMD, DATM, 1);
> +    env->CSR_CRMD = t;
> +
> +    env->CSR_ECFG = FIELD_DP64(0, CSR_ECFG, VS, 7);
> +    env->CSR_STLBPS  = 0xe;
> +    env->CSR_RVACFG = 0x0;
> +    env->CSR_ASID = 0xa0000;
> +    env->CSR_ERA = env->pc;
> +}
> +#endif
> +
>   /* LoongArch CPU definitions */
>   static void loongarch_3a5000_initfn(Object *obj)
>   {
> @@ -113,6 +147,9 @@ static void loongarch_3a5000_initfn(Object *obj)
>       CPULoongArchState *env = &cpu->env;
>   
>       set_loongarch_cpucfg(env);
> +#ifndef CONFIG_USER_ONLY
> +    set_loongarch_csr(env);
> +#endif
>   }
>   
>   static void loongarch_cpu_list_entry(gpointer data, gpointer user_data)
> @@ -140,6 +177,9 @@ static void loongarch_cpu_reset(DeviceState *dev)
>       lacc->parent_reset(dev);
>   
>       set_loongarch_cpucfg(env);
> +#ifndef CONFIG_USER_ONLY
> +    set_loongarch_csr(env);
> +#endif

As I said vs patch 2, I think you'll want to set all of these unconditionally.


r~


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

* Re: [PATCH 04/31] target/loongarch: Add basic vmstate description of CPU.
  2021-10-19  7:34 ` [PATCH 04/31] target/loongarch: Add basic vmstate description of CPU Xiaojuan Yang
@ 2021-10-19 19:35   ` Richard Henderson
  0 siblings, 0 replies; 37+ messages in thread
From: Richard Henderson @ 2021-10-19 19:35 UTC (permalink / raw)
  To: Xiaojuan Yang, qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, mark.cave-ayland,
	laurent, peterx, f4bug, alistair.francis, maobibo, gaosong,
	pbonzini, bmeng.cn, alex.bennee, david

On 10/19/21 12:34 AM, Xiaojuan Yang wrote:
> +#ifndef CONFIG_USER_ONLY
> +#include "hw/core/sysemu-cpu-ops.h"
> +
> +static const struct SysemuCPUOps loongarch_sysemu_ops = {
> +    .legacy_vmsd = &vmstate_loongarch_cpu,
> +};
> +#endif
The documentation for legacy_vmsd is quite clear:

     Do not use in new targets, use #DeviceClass::vmsd instead.

> +/* LoongArch CPU state */
> +
> +const VMStateDescription vmstate_loongarch_cpu = {
> +    .name = "cpu",
> +    .version_id = 20,
> +    .minimum_version_id = 20,

Version id should start at 0.


r~


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

* Re: [PATCH 05/31] target/loongarch: Implement qmp_query_cpu_definitions()
  2021-10-19  7:34 ` [PATCH 05/31] target/loongarch: Implement qmp_query_cpu_definitions() Xiaojuan Yang
@ 2021-10-19 20:25   ` Richard Henderson
  0 siblings, 0 replies; 37+ messages in thread
From: Richard Henderson @ 2021-10-19 20:25 UTC (permalink / raw)
  To: Xiaojuan Yang, qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, mark.cave-ayland,
	laurent, peterx, f4bug, alistair.francis, maobibo, gaosong,
	pbonzini, bmeng.cn, alex.bennee, david

On 10/19/21 12:34 AM, Xiaojuan Yang wrote:
> This patch introduce qmp_query_cpu_definitions interface.
> 
> Signed-off-by: Xiaojuan Yang<yangxiaojuan@loongson.cn>
> Signed-off-by: Song Gao<gaosong@loongson.cn>
> ---
>   qapi/machine-target.json |  6 ++++--
>   target/loongarch/cpu.c   | 28 ++++++++++++++++++++++++++++
>   2 files changed, 32 insertions(+), 2 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>

r~


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

* Re: [PATCH 06/31] target/loongarch: Add mmu support for Loongarch CPU.
       [not found] ` <1634628917-10031-7-git-send-email-yangxiaojuan@loongson.cn>
@ 2021-10-19 21:11   ` Richard Henderson
  0 siblings, 0 replies; 37+ messages in thread
From: Richard Henderson @ 2021-10-19 21:11 UTC (permalink / raw)
  To: Xiaojuan Yang, qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, mark.cave-ayland,
	laurent, peterx, f4bug, alistair.francis, maobibo, gaosong,
	pbonzini, bmeng.cn, alex.bennee, david

On 10/19/21 12:34 AM, Xiaojuan Yang wrote:
> @@ -272,6 +288,7 @@ static const struct SysemuCPUOps loongarch_sysemu_ops = {
>   #ifdef CONFIG_TCG
>   #include "hw/core/tcg-cpu-ops.h"
>   
> +#ifdef CONFIG_USER_ONLY
>   static bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
>                          MMUAccessType access_type, int mmu_idx,
>                          bool probe, uintptr_t retaddr)
> @@ -280,9 +297,14 @@ static bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
>       CPULoongArchState *env = &cpu->env;
>   
>       env->badaddr = address;
> -    cs->exception_index = EXCP_ADE;
> +    if (access_type == MMU_DATA_STORE) {
> +        cs->exception_index = EXCP_ADES;
> +    } else {
> +        cs->exception_index = EXCP_ADEL;
> +    }
>       do_raise_exception(env, cs->exception_index, retaddr);
>   }
> +#endif

It's too early to add this ifdef.  With what's upstream at the moment, you've broken 
loongarch-linux-user build by removing loongarch_cpu_tlb_fill.

There are patches out for review that would require tlb_fill be a system-only hook, but 
they have not landed yet.

> +#define LOONGARCH_HFLAG_KU     0x00003 /* kernel/user mode mask   */
> +#define LOONGARCH_HFLAG_UM     0x00003 /* user mode flag                     */
> +#define LOONGARCH_HFLAG_KM     0x00000 /* kernel mode flag                   */

I think you might as well represent all 3 priv levels: it's not a "kernel/user" mask.

> +#define EXCP_TLB_NOMATCH   0x1
> +#define EXCP_INST_NOTAVAIL 0x2 /* No valid instruction word for BadInstr */

These should be with the other EXCP values in the enum.
At the moment you're overlapping EXCP_ADES and EXCP_SYSCALL.

> @@ -130,7 +139,11 @@ void loongarch_cpu_list(void);
>   
>   static inline int cpu_mmu_index(CPULoongArchState *env, bool ifetch)
>   {
> +#ifdef CONFIG_USER_ONLY
>       return MMU_USER_IDX;
> +#else
> +    return env->CSR_CRMD & LOONGARCH_HFLAG_KU;

Better would be

     return FIELD_EX64(env->CSR_CRMD, CSR_CRMD, PLV);

since that's the field you're extracting from CRMD.

> +typedef struct ls3a5k_tlb_t ls3a5k_tlb_t;

Types should be in CamelCase, without _t suffix.

> +struct ls3a5k_tlb_t {
> +    target_ulong VPN;
> +    uint64_t PageMask;
> +    uint32_t PageSize;
> +    uint16_t ASID;
> +    unsigned int V0:1;     /* CSR_TLBLO[0] */
> +    unsigned int V1:1;
> +
> +    unsigned int D0:1;     /* CSR_TLBLO[1] */
> +    unsigned int D1:1;
> +
> +    unsigned int PLV0:2;   /* CSR_TLBLO[3:2] */
> +    unsigned int PLV1:2;
> +
> +    unsigned int MAT0:3;   /* CSR_TLBLO[5:4] */
> +    unsigned int MAT1:3;
> +
> +    unsigned int G:1;      /* CSR_TLBLO[6] */
> +
> +    uint64_t PPN0;         /* CSR_TLBLO[47:12] */
> +    uint64_t PPN1;
> +
> +    unsigned int NR0:1;    /* CSR_TLBLO[61] */
> +    unsigned int NR1:1;
> +
> +    unsigned int NX0:1;    /* CSR_TLBLO[62] */
> +    unsigned int NX1:1;
> +
> +    unsigned int NE:1;     /* CSR_TLBIDX[31] */
> +
> +    unsigned int RPLV0:1;
> +    unsigned int RPLV1:1;  /* CSR_TLBLO[63] */
> +};

It would be much better if you didn't use bitfields at all.  This was a bad idea when mips 
did it; let us not compound the error.

Just use the format defined by the architecture for the CSRs: a couple of uint64_t.  Use 
FIELD definitions to give the parts intelligible names.

> +typedef struct ls3a5k_tlb_t ls3a5k_tlb_t;
> +
> +struct CPULoongArchTLBContext {
> +    uint32_t nb_tlb;
> +    int (*map_address)(struct CPULoongArchState *env, hwaddr *physical,
> +                       int *prot, target_ulong address,
> +                       MMUAccessType access_type);
> +    struct {
> +        uint64_t     stlb_mask;
> +        uint32_t     stlb_size; /* at most : 8 * 256 = 2048 */
> +        uint32_t     mtlb_size; /* at most : 64 */
> +        ls3a5k_tlb_t tlb[LOONGARCH_TLB_MAX];
> +    } ls3a5k;
> +};

There's probably no point in using an indirect function call until you've got more than 
one mmu implementation.  You're copying too much from mips.

> +/* TLB state */
> +static int get_tlb(QEMUFile *f, void *pv, size_t size,
> +                   const VMStateField *field)
> +{
> +    ls3a5k_tlb_t *v = pv;
> +    uint32_t flags;
> +
> +    qemu_get_betls(f, &v->VPN);
> +    qemu_get_be64s(f, &v->PageMask);
> +    qemu_get_be32s(f, &v->PageSize);
> +    qemu_get_be16s(f, &v->ASID);
> +    qemu_get_be32s(f, &flags);
> +    v->RPLV1 = (flags >> 21) & 1;
> +    v->RPLV0 = (flags >> 20) & 1;
> +    v->PLV1 = (flags >> 18) & 3;
> +    v->PLV0 = (flags >> 16) & 3;
> +    v->NE = (flags >> 15) & 1;
> +    v->NR1 = (flags >> 14) & 1;
> +    v->NR0 = (flags >> 13) & 1;
> +    v->NX1 = (flags >> 12) & 1;
> +    v->NX0 = (flags >> 11) & 1;
> +    v->D1 = (flags >> 10) & 1;
> +    v->D0 = (flags >> 9) & 1;
> +    v->V1 = (flags >> 8) & 1;
> +    v->V0 = (flags >> 7) & 1;
> +    v->MAT1 = (flags >> 4) & 7;
> +    v->MAT0 = (flags >> 1) & 7;
> +    v->G = (flags >> 0) & 1;
> +    qemu_get_be64s(f, &v->PPN0);
> +    qemu_get_be64s(f, &v->PPN1);

Some of the ugly things that go away if you don't use bitfields.

> +const VMStateDescription vmstate_tlb = {
> +    .name = "cpu/tlb",
> +    .version_id = 2,
> +    .minimum_version_id = 2,

Too much copying again: version numbers do not start at 2.

> +void ls3a5k_mmu_init(CPULoongArchState *env)
> +{
> +    env->tlb = g_malloc0(sizeof(CPULoongArchTLBContext));

I think you should not make this a separate structure, and instead allocate this with 
CPULoongArchState.

> diff --git a/target/loongarch/translate.c b/target/loongarch/translate.c
> index bea290df66..0be29994f9 100644
> --- a/target/loongarch/translate.c
> +++ b/target/loongarch/translate.c
> @@ -61,9 +61,10 @@ static void loongarch_tr_init_disas_context(DisasContextBase *dcbase,
>   {
>       int64_t bound;
>       DisasContext *ctx = container_of(dcbase, DisasContext, base);
> +    CPULoongArchState *env = cs->env_ptr;
>   
>       ctx->page_start = ctx->base.pc_first & TARGET_PAGE_MASK;
> -    ctx->mem_idx = MMU_USER_IDX;
> +    ctx->mem_idx = cpu_mmu_index(env, false);

This is incorrect.  You want

     tb_flags = ctx->base.tb->flags;
     mem_idx = tb_flags & LOONGARCH_HFLAG_PRIV.

It is almost always incorrect to dereference env at this point.  Everything should have 
been encoded into tb_flags so that when we do the hashing of the TranslationBlocks we find 
the one that has been compiled for the correct privilege level, etc.


r~


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

* Re: [PATCH 07/31] target/loongarch: Add loongarch csr/iocsr instruction support
       [not found] ` <1634628917-10031-8-git-send-email-yangxiaojuan@loongson.cn>
@ 2021-10-20  1:36   ` Richard Henderson
  2021-10-29  6:26     ` yangxiaojuan
  0 siblings, 1 reply; 37+ messages in thread
From: Richard Henderson @ 2021-10-20  1:36 UTC (permalink / raw)
  To: Xiaojuan Yang, qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, mark.cave-ayland,
	laurent, peterx, f4bug, alistair.francis, maobibo, gaosong,
	pbonzini, bmeng.cn, alex.bennee, david

On 10/19/21 12:34 AM, Xiaojuan Yang wrote:
> +target_ulong helper_csr_rdq(CPULoongArchState *env, uint64_t csr)
> +{
> +    int64_t v;
> +
> +#define CASE_CSR_RDQ(csr)            \
> +    case LOONGARCH_CSR_ ## csr:      \
> +    {                                \
> +        v = env->CSR_ ## csr;        \
> +        break;                       \
> +    };                               \

There's absolutely no reason to call a helper function for a simple load.

> +    case LOONGARCH_CSR_PGD:
> +
> +        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;
> +        }
> +        break;

This is the only one that requires a helper on read.

> +    if (csr == LOONGARCH_CSR_ASID) {
> +        if (old_v != val) {
> +            tlb_flush(env_cpu(env));
> +        }
> +    }

And this is the only one that requires a helper on write.

> +    case LOONGARCH_CSR_ESTAT:
> +        qatomic_and(&env->CSR_ESTAT, ~mask);

Why do you believe this requires an atomic update?
What is going to race with the update to a cpu private value?

> +static bool trans_csrrd(DisasContext *ctx, unsigned rd, unsigned csr)
> +{
> +    TCGv dest = gpr_dst(ctx, rd, EXT_NONE);
> +    gen_helper_csr_rdq(dest, cpu_env, tcg_constant_i64(csr));
> +    return true;
> +}
> +
> +static bool trans_csrwr(DisasContext *ctx, unsigned rd, unsigned csr)
> +{
> +    TCGv dest = gpr_dst(ctx, rd, EXT_NONE);
> +    TCGv src1 = gpr_src(ctx, rd, EXT_NONE);
> +
> +    switch (csr) {
> +    case LOONGARCH_CSR_CRMD:
> +        tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
> +        gen_helper_csr_wrq(dest, cpu_env, src1, tcg_constant_i64(LOONGARCH_CSR_CRMD));
> +        tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next + 4);
> +        ctx->base.is_jmp = DISAS_EXIT;
> +        break;
> +    case LOONGARCH_CSR_EUEN:
> +        gen_helper_csr_wrq(dest, cpu_env, src1, tcg_constant_i64(LOONGARCH_CSR_EUEN));
> +        /* Stop translation */
> +        tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next + 4);
> +        ctx->base.is_jmp = DISAS_EXIT;
> +        break;
> +    default:
> +        gen_helper_csr_wrq(dest, cpu_env, src1, tcg_constant_i64(csr));
> +        break;
> +    }
> +    return true;
> +}
> +
> +static bool trans_csrxchg(DisasContext *ctx, arg_csrxchg *a)
> +{
> +    TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
> +    TCGv src1 = gpr_src(ctx, a->rd, EXT_NONE);
> +    TCGv src2 = gpr_src(ctx, a->rj, EXT_NONE);
> +
> +    if (a->rj == 0) {
> +        return trans_csrrd(ctx, a->rd, a->csr);
> +    } else if (a->rj == 1) {
> +        return trans_csrwr(ctx, a->rd, a->csr);
> +    }

These should have been decoded separately; see below.

You're missing the check for priv 0 here and in all other functions.

> +
> +    if (a->rd == 0) {
> +        gen_helper_csr_xchgq_r0(cpu_env, src2, tcg_constant_i64(a->csr));
> +    } else {
> +        gen_helper_csr_xchgq(dest, cpu_env, src1, src2, tcg_constant_i64(a->csr));
> +    }

Why do you believe r0 to require a special case?

> +static bool trans_iocsrrd_b(DisasContext *ctx, arg_iocsrrd_b *a)
> +{
> +    TCGv tmp = tcg_temp_new();
> +    TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
> +    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
> +
> +    gen_helper_iocsr_read(tmp, cpu_env, src1);
> +    tcg_gen_qemu_ld_tl(dest, tmp, ctx->mem_idx, MO_SB);

This is wrong.  From the manual:

   All IOCSR registers use independent addressing space

therefore you cannot simply read from a modified address, you must use a completely 
different address space.

There are a couple of different solutions that are possible.

(1) Use helper functions calling address_space_ld/st*.

(2) Use a separate mmu_idx, which uses its own address space.
     This requires bouncing through MemTxAttrs, since
     cpu_asidx_from_attrs only take attrs and not mmu_idx.

The second one is may be overkill, unless there will be any cachable memory in iospace.  I 
would expect most of it to be device memory.

> +csrxchg          0000 0100 .............. ..... .....     @fmt_rdrjcsr

{
   csrrd             0000 0100 .............. 00000 .....     @fmt_rdcsr
   csrwr             0000 0100 .............. 00001 .....     @fmt_rdcsr
   csrxchg           0000 0100 .............. ..... .....     @fmt_rdrjcsr
}


r~


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

* Re: [PATCH 08/31] target/loongarch: Add tlb instruction support
  2021-10-19  7:34 ` [PATCH 08/31] target/loongarch: Add tlb instruction support Xiaojuan Yang
@ 2021-10-20  4:19   ` Richard Henderson
  2021-10-29  7:01     ` yangxiaojuan
  0 siblings, 1 reply; 37+ messages in thread
From: Richard Henderson @ 2021-10-20  4:19 UTC (permalink / raw)
  To: Xiaojuan Yang, qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, mark.cave-ayland,
	laurent, peterx, f4bug, alistair.francis, maobibo, gaosong,
	pbonzini, bmeng.cn, alex.bennee, david

On 10/19/21 12:34 AM, Xiaojuan Yang wrote:
> This includes:
> - TLBSRCH
> - TLBRD
> - TLBWR
> - TLBFILL
> - TLBCLR
> - TLBFLUSH
> - INVTLB
> 
> Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
>   target/loongarch/cpu.c                   |  19 +
>   target/loongarch/helper.h                |   8 +
>   target/loongarch/insn_trans/trans_core.c |  54 +++
>   target/loongarch/insns.decode            |  14 +
>   target/loongarch/internals.h             |  18 +
>   target/loongarch/tlb_helper.c            | 468 +++++++++++++++++++++++
>   6 files changed, 581 insertions(+)
> 
> diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
> index f145afb603..afd186abac 100644
> --- a/target/loongarch/cpu.c
> +++ b/target/loongarch/cpu.c
> @@ -118,6 +118,7 @@ static void set_loongarch_cpucfg(CPULoongArchState *env)
>   static void set_loongarch_csr(CPULoongArchState *env)
>   {
>       uint64_t t;
> +    CPUState *cs = env_cpu(env);
>   
>       t = FIELD_DP64(0, CSR_PRCFG1, SAVE_NUM, 8);
>       t = FIELD_DP64(t, CSR_PRCFG1, TIMER_BITS, 0x2f);
> @@ -145,6 +146,9 @@ static void set_loongarch_csr(CPULoongArchState *env)
>       env->CSR_RVACFG = 0x0;
>       env->CSR_ASID = 0xa0000;
>       env->CSR_ERA = env->pc;
> +    env->CSR_CPUID = (cs->cpu_index & 0x1ff);

Any reason to have a copy of cpu_index, as opposed to just using that field?  CSR_CPUID is 
read-only after all.

> +    env->CSR_EENTRY |= (uint64_t)0x80000000;
> +    env->CSR_TLBRENTRY |= (uint64_t)0x80000000;

Are there really a defined reset values?  The documentation doesn't say.  It would appear 
that the kernel must set these before enabling interrupts or turning on paging.

> +#ifndef CONFIG_USER_ONLY
> +    qemu_fprintf(f, "EUEN            0x%lx\n", env->CSR_EUEN);
> +    qemu_fprintf(f, "ESTAT           0x%lx\n", env->CSR_ESTAT);
> +    qemu_fprintf(f, "ERA             0x%lx\n", env->CSR_ERA);
> +    qemu_fprintf(f, "CRMD            0x%lx\n", env->CSR_CRMD);
> +    qemu_fprintf(f, "PRMD            0x%lx\n", env->CSR_PRMD);
> +    qemu_fprintf(f, "BadVAddr        0x%lx\n", env->CSR_BADV);
> +    qemu_fprintf(f, "TLB refill ERA  0x%lx\n", env->CSR_TLBRERA);
> +    qemu_fprintf(f, "TLB refill BadV 0x%lx\n", env->CSR_TLBRBADV);
> +    qemu_fprintf(f, "EENTRY            0x%lx\n", env->CSR_EENTRY);
> +    qemu_fprintf(f, "BadInstr        0x%lx\n", env->CSR_BADI);
> +    qemu_fprintf(f, "PRCFG1    0x%lx\nPRCFG2     0x%lx\nPRCFG3     0x%lx\n",
> +                 env->CSR_PRCFG1, env->CSR_PRCFG3, env->CSR_PRCFG3);
> +#endif

This probably belongs to a different patch?

> @@ -165,4 +172,51 @@ static bool trans_iocsrwr_d(DisasContext *ctx, arg_iocsrwr_d *a)
>       gen_helper_iocsr_write(cpu_env, addr, val, tcg_constant_i32(oi));
>       return true;
>   }
> +
> +static bool trans_tlbsrch(DisasContext *ctx, arg_tlbsrch *a)
> +{
> +    gen_helper_tlbsrch(cpu_env);
> +    return true;
> +}

Missing priv check, all functions.

> +static bool trans_invtlb(DisasContext *ctx, arg_invtlb *a)
> +{
> +    TCGv addr = gpr_src(ctx, a->addr, EXT_NONE);
> +    TCGv info = gpr_src(ctx, a->info, EXT_NONE);
> +    TCGv op = tcg_constant_tl(a->invop);
> +
> +    gen_helper_invtlb(cpu_env, addr, info, op);
> +    return true;
> +}

Decode op here -- there are only 7 defined opcodes.

Note that you'll need to end the TB after most TLB instructions, since the translation of 
PC could change between one insn and the next.


> +&fmt_invtlb         addr info invop
> +@fmt_invtlb          ...... ...... ..... ..... ..... .....    &fmt_invtlb         %addr %info %invop

Why are you using the names addr and info instead of rk and rj?

> diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
> index 1251e7f21c..916c675680 100644
> --- a/target/loongarch/internals.h
> +++ b/target/loongarch/internals.h
> @@ -76,6 +76,14 @@ struct CPULoongArchTLBContext {
>       int (*map_address)(struct CPULoongArchState *env, hwaddr *physical,
>                          int *prot, target_ulong address,
>                          MMUAccessType access_type);
> +    void (*helper_tlbwr)(struct CPULoongArchState *env);
> +    void (*helper_tlbfill)(struct CPULoongArchState *env);
> +    void (*helper_tlbsrch)(struct CPULoongArchState *env);
> +    void (*helper_tlbrd)(struct CPULoongArchState *env);
> +    void (*helper_tlbclr)(struct CPULoongArchState *env);
> +    void (*helper_tlbflush)(struct CPULoongArchState *env);
> +    void (*helper_invtlb)(struct CPULoongArchState *env, target_ulong addr,
> +                          target_ulong info, int op);

Again, function pointers are premature.

> +static uint64_t ls3a5k_pagesize_to_mask(int pagesize)
> +{
> +    /* 4KB - 1GB */
> +    if (pagesize < 12 && pagesize > 30) {
> +        qemu_log_mask(CPU_LOG_MMU, "unsupported page size %d\n", pagesize);
> +        exit(-1);

Do not call exit.  Make up something sensible that won't crash qemu.

> +/* return random value in [low, high] */
> +static uint32_t cpu_loongarch_get_random_ls3a5k_tlb(uint32_t low, uint32_t high)
> +{
> +    static uint32_t seed = 5;
> +    static uint32_t prev_idx;

No static variables like this, as they cannot be migrated, and are a race condition 
between multiple cpus.  That said...

> +    uint32_t idx;
> +    uint32_t nb_rand_tlb = high - low + 1;
> +
> +    do {
> +        seed = 1103515245 * seed + 12345;
> +        idx = (seed >> 16) % nb_rand_tlb + low;
> +    } while (idx == prev_idx);

... we have defined interfaces for getting random numbers.


r~


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

* Re: [PATCH 09/31] target/loongarch: Add other core instructions support
  2021-10-19  7:34 ` [PATCH 09/31] target/loongarch: Add other core instructions support Xiaojuan Yang
@ 2021-10-20  4:45   ` Richard Henderson
  0 siblings, 0 replies; 37+ messages in thread
From: Richard Henderson @ 2021-10-20  4:45 UTC (permalink / raw)
  To: Xiaojuan Yang, qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, mark.cave-ayland,
	laurent, peterx, f4bug, alistair.francis, maobibo, gaosong,
	pbonzini, bmeng.cn, alex.bennee, david

On 10/19/21 12:34 AM, Xiaojuan Yang wrote:
> diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
> index afd186abac..7fa3851251 100644
> --- a/target/loongarch/cpu.c
> +++ b/target/loongarch/cpu.c
> @@ -45,6 +45,7 @@ static const char * const excp_names[EXCP_LAST + 1] = {
>       [EXCP_TLBPE] = "TLB priviledged error",
>       [EXCP_TLBNX] = "TLB execute-inhibit",
>       [EXCP_TLBNR] = "TLB read-inhibit",
> +    [EXCP_DBP] = "debug breakpoint",
>   };
>   
>   const char *loongarch_exception_name(int32_t exception)
> diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
> index 567fc7620d..d39c618d6b 100644
> --- a/target/loongarch/cpu.h
> +++ b/target/loongarch/cpu.h
> @@ -166,10 +166,13 @@ enum {
>       EXCP_TLBPE,
>       EXCP_TLBNX,
>       EXCP_TLBNR,
> +    EXCP_DBP,
>   
> -    EXCP_LAST = EXCP_TLBNR,
> +    EXCP_LAST = EXCP_DBP,
>   };

These should have been added with the other exceptions earlier.

> @@ -173,6 +179,11 @@ static bool trans_iocsrwr_d(DisasContext *ctx, arg_iocsrwr_d *a)
>       return true;
>   }
>   
> +static bool trans_cacop(DisasContext *ctx, arg_cacop *a)
> +{
> +    return false;
> +}

I think you meant to return true here, so that cacop is interpreted as a nop.  You would 
add a comment to that effect.

> +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);
> +
> +    gen_helper_ldpte(cpu_env, src1, tcg_constant_tl(a->seq), mem_idx);
> +    return true;
> +}

Missing priv checks again.

> +static bool trans_idle(DisasContext *ctx, arg_idle *a)
> +{
> +    ctx->base.pc_next += 4;
> +    tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
> +    ctx->base.pc_next -= 4;

Why would you add and subtract like this?

> +#ifndef CONFIG_USER_ONLY
> +static inline void exception_return(CPULoongArchState *env)
> +{
> +    if (env->CSR_TLBRERA & 0x1) {
> +        env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PLV,
> +                                   FIELD_EX64(env->CSR_TLBRPRMD, CSR_TLBRPRMD, PPLV));
> +        env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, IE,
> +                                   FIELD_EX64(env->CSR_TLBRPRMD, CSR_TLBRPRMD, PIE));
> +        /* Clear Refill flag and set pc */
> +        env->CSR_TLBRERA &= (~0x1);
> +        env->pc = env->CSR_TLBRERA;
> +        if (qemu_loglevel_mask(CPU_LOG_INT)) {
> +            qemu_log("%s: TLBRERA 0x%lx\n", __func__, env->CSR_TLBRERA);
> +        }
> +    } else {
> +        env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, PLV,
> +                                   FIELD_EX64(env->CSR_PRMD, CSR_PRMD, PPLV));
> +        env->CSR_CRMD = FIELD_DP64(env->CSR_CRMD, CSR_CRMD, IE,
> +                                   FIELD_EX64(env->CSR_PRMD, CSR_PRMD, PIE));
> +        /* set pc*/
> +        env->pc = env->CSR_ERA;
> +        if (qemu_loglevel_mask(CPU_LOG_INT)) {
> +            qemu_log("%s: ERA 0x%lx\n", __func__, env->CSR_ERA);
> +        }
> +    }
> +}
> +
> +void helper_ertn(CPULoongArchState *env)
> +{
> +    exception_return(env);
> +    env->lladdr = 1;
> +}

Any reason to have exception_return be a separate function?

> +target_ulong helper_lddir(CPULoongArchState *env, target_ulong base,
> +                          target_ulong level, uint32_t mem_idx)
> +{
> +    target_ulong badvaddr;
> +    target_ulong index;
> +    target_ulong vaddr;
> +    int shift;
> +    uint64_t dir1_base, dir1_width;
> +    uint64_t dir3_base, dir3_width;
> +
> +    badvaddr = env->CSR_TLBRBADV;
> +
> +    /* 0:8B, 1:16B, 2:32B, 3:64B */
> +    shift = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTEWIDTH);
> +    shift = (shift + 1) * 3;
> +
> +    switch (level) {
> +    case 1:
> +        dir1_base = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_BASE);
> +        dir1_width = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, DIR1_WIDTH);
> +        index = (badvaddr >> dir1_base) & ((1 << dir1_width) - 1);
> +        break;
> +    case 3:
> +        dir3_base = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_BASE);
> +        dir3_width = FIELD_EX64(env->CSR_PWCH, CSR_PWCH, DIR3_WIDTH);
> +        index = (badvaddr >> dir3_base) & ((1 << dir3_width) - 1);
> +        break;
> +    default:
> +        do_raise_exception(env, EXCP_INE, GETPC());
> +        return 0;
> +    }
> +
> +    vaddr = base | index << shift;
> +    return cpu_ldq_mmuidx_ra(env, vaddr, mem_idx, GETPC());

A load from mem_idx is incorrect -- you have a physical address (thus the name "vaddr" is 
at best misleading). There are two possible solutions:

(1) ldq_phys.

(2) Add a separate MMU_PHYS_IDX, which you could use here.  You would also return this 
value from cpu_mem_index when CRMD.{DA,PG} indicates that direct address translation is 
enabled.

> +void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd,
> +                  uint32_t mem_idx)
> +{
...
> +        vaddr = base | (odd ? ptoffset1 : ptoffset0);
> +        tmp0 = cpu_ldq_mmuidx_ra(env, vaddr, mem_idx, GETPC());

Likewise.


r~


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

* Re: [PATCH 10/31] target/loongarch: Add loongarch interrupt and exception handle
  2021-10-19  7:34 ` [PATCH 10/31] target/loongarch: Add loongarch interrupt and exception handle Xiaojuan Yang
@ 2021-10-20  4:59   ` Richard Henderson
  0 siblings, 0 replies; 37+ messages in thread
From: Richard Henderson @ 2021-10-20  4:59 UTC (permalink / raw)
  To: Xiaojuan Yang, qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, mark.cave-ayland,
	laurent, peterx, f4bug, alistair.francis, maobibo, gaosong,
	pbonzini, bmeng.cn, alex.bennee, david

On 10/19/21 12:34 AM, Xiaojuan Yang wrote:
> This patch Add loongarch interrupt and exception handle.
> 
> Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
>   target/loongarch/cpu.c | 293 +++++++++++++++++++++++++++++++++++++++++
>   target/loongarch/cpu.h |   6 +-
>   2 files changed, 298 insertions(+), 1 deletion(-)
> 
> diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
> index 7fa3851251..3e3cf233db 100644
> --- a/target/loongarch/cpu.c
> +++ b/target/loongarch/cpu.c
> @@ -45,7 +45,10 @@ static const char * const excp_names[EXCP_LAST + 1] = {
>       [EXCP_TLBPE] = "TLB priviledged error",
>       [EXCP_TLBNX] = "TLB execute-inhibit",
>       [EXCP_TLBNR] = "TLB read-inhibit",
> +    [EXCP_EXT_INTERRUPT] = "interrupt",
>       [EXCP_DBP] = "debug breakpoint",
> +    [EXCP_IBE] = "instruction bus error",
> +    [EXCP_DBE] = "data bus error",
>   };

More incomplete update from before.

> +/* 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;

Return the expression directly?

> +}
> +
> +static inline unsigned int get_vint_size(CPULoongArchState *env)
> +{
> +    unsigned int size = 0;
> +    uint64_t vs = FIELD_EX64(env->CSR_ECFG, CSR_ECFG, VS);
> +
> +    switch (vs) {
> +    case 0:
> +        break;
> +    case 1:
> +        size = 2 * 4;   /* #Insts * inst_size */
> +        break;
> +    case 2:
> +        size = 4 * 4;
> +        break;
> +    case 3:
> +        size = 8 * 4;
> +        break;
> +    case 4:
> +        size = 16 * 4;
> +        break;
> +    case 5:
> +        size = 32 * 4;
> +        break;
> +    case 6:
> +        size = 64 * 4;
> +        break;
> +    case 7:
> +        size = 128 * 4;
> +        break;

This is a pretty simple expression to turn into a switch.

> +#define is_refill(cs, env) (((cs->exception_index == EXCP_TLBL) \
> +        || (cs->exception_index == EXCP_TLBS))  \
> +        && (env->error_code & EXCP_TLB_NOMATCH))

This should be a function, not a macro.
It's probably worth computing once, not multiple times within loongarch_cpu_do_interrupt.

> +    default:
> +        qemu_log("Error: exception(%d) '%s' has not been supported\n",
> +                 cs->exception_index, excp_names[cs->exception_index]);

../qemu/target/loongarch/cpu.c: In function ‘loongarch_cpu_do_interrupt’:
../qemu/target/loongarch/cpu.c:250:9: error: array subscript [0, 16] is outside array 
bounds of ‘const char * const[17]’ [-Werror=array-bounds]
   250 |         qemu_log("Error: exception(%d) '%s' has not been supported\n",
       |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   251 |                  cs->exception_index, excp_names[cs->exception_index]);
       |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
../qemu/target/loongarch/cpu.c:36:27: note: while referencing ‘excp_names’
    36 | static const char * const excp_names[EXCP_LAST + 1] = {
       |                           ^~~~~~~~~~
cc1: all warnings being treated as errors

> @@ -223,6 +509,7 @@ static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp)
>   
>   #ifndef CONFIG_USER_ONLY
>       ls3a5k_mmu_init(env);
> +    env->exception_base = 0x1C000000;
>   #endif

What is exception_base if it's not EENTRY?  Too much copying from MIPS?


r~


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

* Re: [PATCH 00/31] Add Loongarch softmmu support.
       [not found]   ` <7d933f8d.228e.17c9b556e98.Coremail.yangxiaojuan@loongson.cn>
@ 2021-10-20  5:11     ` WANG Xuerui
  0 siblings, 0 replies; 37+ messages in thread
From: WANG Xuerui @ 2021-10-20  5:11 UTC (permalink / raw)
  To: 杨小娟
  Cc: peter.maydell, thuth, f4bug, mst, david, mark.cave-ayland,
	richard.henderson, qemu-devel, peterx, laurent, alex.bennee,
	alistair.francis, maobibo, gaosong, pbonzini, bmeng.cn, philmd,
	chenhuacai

Hi Xiaojuan,


On 2021/10/20 09:33, 杨小娟 wrote:
> Hi, Xuerui
>     Thank you for your advice, I‘ll modify the README and put the binary in the github.
>     The remaining patches are send backed, I’ll find the cause and send them again.

Okay, understood; thanks for the quick response.

You may address the several review comments then just send v2. This way
the threading is less likely to be damaged (you need to exactly specify
In-Reply-To headers and such for the re-sent patches to correctly link
to this thread, I think it's not worth the effort).

> </yangxiaojuan@loongson.cn></i.qemu@xen0n.name>
>
> 本邮件及其附件含有龙芯中科的商业秘密信息,仅限于发送给上面地址中列出的个人或群组。禁止任何其他人以任何形式使用(包括但不限于全部或部分地泄露、复制或散发)本邮件及其附件中的信息。如果您错收本邮件,请您立即电话或邮件通知发件人并删除本邮件。 
> This email and its attachments contain confidential information from Loongson Technology , which is intended only for the person or entity whose address is listed above. Any use of the information contained herein in any way (including, but not limited to, total or partial disclosure, reproduction or dissemination) by persons other than the intended recipient(s) is prohibited. If you receive this email in error, please notify the sender by phone or email immediately and delete it. 
BTW really, ask your IT department to fix this nonsense. Multiple
upstreams using mailing lists as primary means of communication
(binutils etc) find problems with the mangling of contents, added
nonsense HTML-like tags and this footer not applicable to public
communication.


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

* Re: [PATCH 12/31] target/loongarch: Add timer related instructions support.
  2021-10-19  7:34 ` [PATCH 12/31] target/loongarch: Add timer related instructions support Xiaojuan Yang
@ 2021-10-20  5:17   ` Richard Henderson
  0 siblings, 0 replies; 37+ messages in thread
From: Richard Henderson @ 2021-10-20  5:17 UTC (permalink / raw)
  To: Xiaojuan Yang, qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, mark.cave-ayland,
	laurent, peterx, f4bug, alistair.francis, maobibo, gaosong,
	pbonzini, bmeng.cn, alex.bennee, david

On 10/19/21 12:34 AM, Xiaojuan Yang wrote:
> This includes:
> -RDTIME{L/H}.W
> -RDTIME.D
> 
> Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
> Signed-off-by: Song Gao <gaosong@loongson.cn>
> ---
>   target/loongarch/helper.h                 |  2 ++
>   target/loongarch/insn_trans/trans_core.c  | 23 +++++++++++++++++++++
>   target/loongarch/insn_trans/trans_extra.c |  2 ++
>   target/loongarch/op_helper.c              | 25 +++++++++++++++++++++++
>   4 files changed, 52 insertions(+)
> 
> diff --git a/target/loongarch/helper.h b/target/loongarch/helper.h
> index 8544771790..b4ed62896f 100644
> --- a/target/loongarch/helper.h
> +++ b/target/loongarch/helper.h
> @@ -116,4 +116,6 @@ 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_4(rdtime_w, void, env, tl, tl, i64)
> +DEF_HELPER_3(rdtime_d, void, env, tl, tl)
>   #endif /* !CONFIG_USER_ONLY */
> diff --git a/target/loongarch/insn_trans/trans_core.c b/target/loongarch/insn_trans/trans_core.c
> index 7fa13e65b9..24eb12b97a 100644
> --- a/target/loongarch/insn_trans/trans_core.c
> +++ b/target/loongarch/insn_trans/trans_core.c
> @@ -276,4 +276,27 @@ static bool trans_idle(DisasContext *ctx, arg_idle *a)
>       return true;
>   }
>   
> +static bool trans_rdtimel_w(DisasContext *ctx, arg_rdtimel_w *a)
> +{
> +    TCGv t0 = tcg_constant_tl(a->rd);
> +    TCGv t1 = tcg_constant_tl(a->rj);
> +    gen_helper_rdtime_w(cpu_env, t0, t1, tcg_constant_tl(0));
> +    return true;
> +}

Missing icount boilerplate:

     if (tb_cflags(ctx->base.tb) & CF_USE_ICOUNT) {
         gen_io_start();
         ctx->base.is_jmp = DISAS_TOO_MANY;
     }

Something similar is probably required before some of the other instructions that always 
result in i/o.

> diff --git a/target/loongarch/insn_trans/trans_extra.c b/target/loongarch/insn_trans/trans_extra.c
> index 8da3b404f3..426b67f154 100644
> --- a/target/loongarch/insn_trans/trans_extra.c
> +++ b/target/loongarch/insn_trans/trans_extra.c
> @@ -36,6 +36,7 @@ static bool trans_asrtgt_d(DisasContext *ctx, arg_asrtgt_d * a)
>       return true;
>   }
>   
> +#ifdef CONFIG_USER_ONLY
>   static bool trans_rdtimel_w(DisasContext *ctx, arg_rdtimel_w *a)
>   {
>       tcg_gen_movi_tl(cpu_gpr[a->rd], 0);
> @@ -53,6 +54,7 @@ static bool trans_rdtime_d(DisasContext *ctx, arg_rdtime_d *a)
>       tcg_gen_movi_tl(cpu_gpr[a->rd], 0);
>       return true;
>   }
> +#endif

You shouldn't have two copies of these.

> +void helper_rdtime_w(CPULoongArchState *env, target_ulong rd,
> +                     target_ulong rj, target_ulong high)
> +{
> +    if (rd) {
> +        if (high) {
> +            env->gpr[rd] = cpu_loongarch_get_stable_counter(env) >> 32;
> +        } else {
> +            env->gpr[rd] = cpu_loongarch_get_stable_counter(env) & 0xffffffff;
> +        }

This is incorrect -- the result should be sign-extended in RD.

> +void helper_rdtime_d(CPULoongArchState *env, target_ulong rd, target_ulong rj)
> +{
> +    if (rd) {
> +        env->gpr[rd] = cpu_loongarch_get_stable_counter(env);
> +    }
> +    if (rj) {
> +        env->gpr[rj] = env->CSR_TMID;
> +    }

You shouldn't need two functions.  Just return the full 64-bit result, placing that into 
RD, then read TMID separately.

     rd = gpr_dst(ctx, a->rd, EXT_NONE);
     gen_helper_rdtime_d(rd, cpu_env);
     if (word) {
         tcg_gen_sextract_tl(rd, rd, high ? 32 : 0, 32);
     }

     rj = gpr_dst(ctx, a->rj, EXT_NONE);
     tcg_gen_ld_i64(rj, cpu_env, offsetof(CPULoongArchState, CSR_TMID));


r~


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

* Re: [PATCH 01/31] target/loongarch: Upate the README for the softmmu.
  2021-10-19 18:56   ` [PATCH 01/31] target/loongarch: Upate the README for the softmmu Richard Henderson
@ 2021-10-22  2:25     ` yangxiaojuan
  0 siblings, 0 replies; 37+ messages in thread
From: yangxiaojuan @ 2021-10-22  2:25 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, mst, philmd, mark.cave-ayland,
	laurent, peterx, f4bug, alistair.francis, maobibo, gaosong,
	pbonzini, bmeng.cn, alex.bennee, david



在 2021年10月20日 02:56, Richard Henderson 写道:
> On 10/19/21 12:34 AM, Xiaojuan Yang wrote:
>> ---
>>   target/loongarch/README  | 134 +++++++++++++++++++++++++++++++++++++++
>>   target/loongarch/ramdisk | Bin 0 -> 3077952 bytes
>>   target/loongarch/vmlinux | Bin 0 -> 24565536 bytes
>>   3 files changed, 134 insertions(+)
>>   create mode 100644 target/loongarch/ramdisk
>>   create mode 100755 target/loongarch/vmlinux
> 
> Wang Xuerui has already mentioned this, but let's make sure not to include such large test binaries in future.
Yes, I will put the test binaries on the github.
> 
> The proper place for this is in a stable url, which could then either be referenced in the documentation.  But even better than that would be an acceptance test entry -- see tests/acceptance/boot_linux_console.py.
> 
>> +  2.Modify the kernel code for the tcg. Modifications are listed later. I will try to
>> +    commit to the kernel host.
> 
> This sounds like a bug in the qemu emulation of the device or boot environment.
>
Yes, qemu needs some adjustments, in the next version we can use the kernel directly. Thanks
> 
> r~



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

* Re: [PATCH 07/31] target/loongarch: Add loongarch csr/iocsr instruction support
  2021-10-20  1:36   ` [PATCH 07/31] target/loongarch: Add loongarch csr/iocsr instruction support Richard Henderson
@ 2021-10-29  6:26     ` yangxiaojuan
  2021-10-29 17:38       ` Richard Henderson
  0 siblings, 1 reply; 37+ messages in thread
From: yangxiaojuan @ 2021-10-29  6:26 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, philmd, mark.cave-ayland,
	laurent, peterx, f4bug, alistair.francis, maobibo, gaosong,
	pbonzini, bmeng.cn, alex.bennee, david

Hi, Richard:

On 10/20/2021 09:36 AM, Richard Henderson wrote:
> On 10/19/21 12:34 AM, Xiaojuan Yang wrote:
>> +target_ulong helper_csr_rdq(CPULoongArchState *env, uint64_t csr)
>> +{
>> +    int64_t v;
>> +
>> +#define CASE_CSR_RDQ(csr)            \
>> +    case LOONGARCH_CSR_ ## csr:      \
>> +    {                                \
>> +        v = env->CSR_ ## csr;        \
>> +        break;                       \
>> +    };                               \
> 
> There's absolutely no reason to call a helper function for a simple load.
> 
>> +    case LOONGARCH_CSR_PGD:
>> +
>> +        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;
>> +        }
>> +        break;
> 
> This is the only one that requires a helper on read.
> 
>> +    if (csr == LOONGARCH_CSR_ASID) {
>> +        if (old_v != val) {
>> +            tlb_flush(env_cpu(env));
>> +        }
>> +    }
> 
> And this is the only one that requires a helper on write.
> 
>> +    case LOONGARCH_CSR_ESTAT:
>> +        qatomic_and(&env->CSR_ESTAT, ~mask);
> 
> Why do you believe this requires an atomic update?
> What is going to race with the update to a cpu private value?
> 
>> +static bool trans_csrrd(DisasContext *ctx, unsigned rd, unsigned csr)
>> +{
>> +    TCGv dest = gpr_dst(ctx, rd, EXT_NONE);
>> +    gen_helper_csr_rdq(dest, cpu_env, tcg_constant_i64(csr));
>> +    return true;
>> +}
>> +
>> +static bool trans_csrwr(DisasContext *ctx, unsigned rd, unsigned csr)
>> +{
>> +    TCGv dest = gpr_dst(ctx, rd, EXT_NONE);
>> +    TCGv src1 = gpr_src(ctx, rd, EXT_NONE);
>> +
>> +    switch (csr) {
>> +    case LOONGARCH_CSR_CRMD:
>> +        tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next);
>> +        gen_helper_csr_wrq(dest, cpu_env, src1, tcg_constant_i64(LOONGARCH_CSR_CRMD));
>> +        tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next + 4);
>> +        ctx->base.is_jmp = DISAS_EXIT;
>> +        break;
>> +    case LOONGARCH_CSR_EUEN:
>> +        gen_helper_csr_wrq(dest, cpu_env, src1, tcg_constant_i64(LOONGARCH_CSR_EUEN));
>> +        /* Stop translation */
>> +        tcg_gen_movi_tl(cpu_pc, ctx->base.pc_next + 4);
>> +        ctx->base.is_jmp = DISAS_EXIT;
>> +        break;
>> +    default:
>> +        gen_helper_csr_wrq(dest, cpu_env, src1, tcg_constant_i64(csr));
>> +        break;
>> +    }
>> +    return true;
>> +}
>> +
>> +static bool trans_csrxchg(DisasContext *ctx, arg_csrxchg *a)
>> +{
>> +    TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
>> +    TCGv src1 = gpr_src(ctx, a->rd, EXT_NONE);
>> +    TCGv src2 = gpr_src(ctx, a->rj, EXT_NONE);
>> +
>> +    if (a->rj == 0) {
>> +        return trans_csrrd(ctx, a->rd, a->csr);
>> +    } else if (a->rj == 1) {
>> +        return trans_csrwr(ctx, a->rd, a->csr);
>> +    }
> 
> These should have been decoded separately; see below.
> 
> You're missing the check for priv 0 here and in all other functions.
> 
>> +
>> +    if (a->rd == 0) {
>> +        gen_helper_csr_xchgq_r0(cpu_env, src2, tcg_constant_i64(a->csr));
>> +    } else {
>> +        gen_helper_csr_xchgq(dest, cpu_env, src1, src2, tcg_constant_i64(a->csr));
>> +    }
> 
> Why do you believe r0 to require a special case?
>
 
OK, I have modified  all above.

>> +static bool trans_iocsrrd_b(DisasContext *ctx, arg_iocsrrd_b *a)
>> +{
>> +    TCGv tmp = tcg_temp_new();
>> +    TCGv dest = gpr_dst(ctx, a->rd, EXT_NONE);
>> +    TCGv src1 = gpr_src(ctx, a->rj, EXT_NONE);
>> +
>> +    gen_helper_iocsr_read(tmp, cpu_env, src1);
>> +    tcg_gen_qemu_ld_tl(dest, tmp, ctx->mem_idx, MO_SB);
> 
> This is wrong.  From the manual:
> 
>   All IOCSR registers use independent addressing space
> 
> therefore you cannot simply read from a modified address, you must use a completely different address space.
> 
> There are a couple of different solutions that are possible.
> 
> (1) Use helper functions calling address_space_ld/st*.
> 
> (2) Use a separate mmu_idx, which uses its own address space.
>     This requires bouncing through MemTxAttrs, since
>     cpu_asidx_from_attrs only take attrs and not mmu_idx.
> 
> The second one is may be overkill, unless there will be any cachable memory in iospace.  I would expect most of it to be device memory.
> 
(1) For the iocsr registers, most of them act on the interrupt controller, the read and write will go to interrupt's mmio read/write.
So I modified the addr to their mmio range. The ext interrupt controller use the sysbus's function to handle the interrupt cascade and
sysbus_mmio_map to map the address which use the system memory region. So if I use a different address space, I realize a different 
sysbus_mmio_map function use a different address space, is it feasible ?

(2)Can you help me review the remaining patches? Thanks.

>> +csrxchg          0000 0100 .............. ..... .....     @fmt_rdrjcsr
> 
> {
>   csrrd             0000 0100 .............. 00000 .....     @fmt_rdcsr
>   csrwr             0000 0100 .............. 00001 .....     @fmt_rdcsr
>   csrxchg           0000 0100 .............. ..... .....     @fmt_rdrjcsr
> }
> 
> 
> r~



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

* Re: [PATCH 08/31] target/loongarch: Add tlb instruction support
  2021-10-20  4:19   ` Richard Henderson
@ 2021-10-29  7:01     ` yangxiaojuan
  2021-10-29 17:48       ` Richard Henderson
  0 siblings, 1 reply; 37+ messages in thread
From: yangxiaojuan @ 2021-10-29  7:01 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, philmd, mark.cave-ayland,
	laurent, peterx, f4bug, alistair.francis, maobibo, gaosong,
	pbonzini, bmeng.cn, alex.bennee, david

Hi, Richard:

On 10/20/2021 12:19 PM, Richard Henderson wrote:
> On 10/19/21 12:34 AM, Xiaojuan Yang wrote:
>> This includes:
>> - TLBSRCH
>> - TLBRD
>> - TLBWR
>> - TLBFILL
>> - TLBCLR
>> - TLBFLUSH
>> - INVTLB
>>
>> Signed-off-by: Xiaojuan Yang <yangxiaojuan@loongson.cn>
>> Signed-off-by: Song Gao <gaosong@loongson.cn>
>> ---
>>   target/loongarch/cpu.c                   |  19 +
>>   target/loongarch/helper.h                |   8 +
>>   target/loongarch/insn_trans/trans_core.c |  54 +++
>>   target/loongarch/insns.decode            |  14 +
>>   target/loongarch/internals.h             |  18 +
>>   target/loongarch/tlb_helper.c            | 468 +++++++++++++++++++++++
>>   6 files changed, 581 insertions(+)
>>
>> diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
>> index f145afb603..afd186abac 100644
>> --- a/target/loongarch/cpu.c
>> +++ b/target/loongarch/cpu.c
>> @@ -118,6 +118,7 @@ static void set_loongarch_cpucfg(CPULoongArchState *env)
>>   static void set_loongarch_csr(CPULoongArchState *env)
>>   {
>>       uint64_t t;
>> +    CPUState *cs = env_cpu(env);
>>         t = FIELD_DP64(0, CSR_PRCFG1, SAVE_NUM, 8);
>>       t = FIELD_DP64(t, CSR_PRCFG1, TIMER_BITS, 0x2f);
>> @@ -145,6 +146,9 @@ static void set_loongarch_csr(CPULoongArchState *env)
>>       env->CSR_RVACFG = 0x0;
>>       env->CSR_ASID = 0xa0000;
>>       env->CSR_ERA = env->pc;
>> +    env->CSR_CPUID = (cs->cpu_index & 0x1ff);
> 
> Any reason to have a copy of cpu_index, as opposed to just using that field?  CSR_CPUID is read-only after all.
> 
Yes, we need this value, the uefi code read this CPUID when Start slave cores.

>> +    env->CSR_EENTRY |= (uint64_t)0x80000000;
>> +    env->CSR_TLBRENTRY |= (uint64_t)0x80000000;
> 
> Are there really a defined reset values?  The documentation doesn't say.  It would appear that the kernel must set these before enabling interrupts or turning on paging.
> 
OK, it can be removed.

>> +#ifndef CONFIG_USER_ONLY
>> +    qemu_fprintf(f, "EUEN            0x%lx\n", env->CSR_EUEN);
>> +    qemu_fprintf(f, "ESTAT           0x%lx\n", env->CSR_ESTAT);
>> +    qemu_fprintf(f, "ERA             0x%lx\n", env->CSR_ERA);
>> +    qemu_fprintf(f, "CRMD            0x%lx\n", env->CSR_CRMD);
>> +    qemu_fprintf(f, "PRMD            0x%lx\n", env->CSR_PRMD);
>> +    qemu_fprintf(f, "BadVAddr        0x%lx\n", env->CSR_BADV);
>> +    qemu_fprintf(f, "TLB refill ERA  0x%lx\n", env->CSR_TLBRERA);
>> +    qemu_fprintf(f, "TLB refill BadV 0x%lx\n", env->CSR_TLBRBADV);
>> +    qemu_fprintf(f, "EENTRY            0x%lx\n", env->CSR_EENTRY);
>> +    qemu_fprintf(f, "BadInstr        0x%lx\n", env->CSR_BADI);
>> +    qemu_fprintf(f, "PRCFG1    0x%lx\nPRCFG2     0x%lx\nPRCFG3     0x%lx\n",
>> +                 env->CSR_PRCFG1, env->CSR_PRCFG3, env->CSR_PRCFG3);
>> +#endif
> 
> This probably belongs to a different patch?
> 
>> @@ -165,4 +172,51 @@ static bool trans_iocsrwr_d(DisasContext *ctx, arg_iocsrwr_d *a)
>>       gen_helper_iocsr_write(cpu_env, addr, val, tcg_constant_i32(oi));
>>       return true;
>>   }
>> +
>> +static bool trans_tlbsrch(DisasContext *ctx, arg_tlbsrch *a)
>> +{
>> +    gen_helper_tlbsrch(cpu_env);
>> +    return true;
>> +}
> 
> Missing priv check, all functions.
> 
>> +static bool trans_invtlb(DisasContext *ctx, arg_invtlb *a)
>> +{
>> +    TCGv addr = gpr_src(ctx, a->addr, EXT_NONE);
>> +    TCGv info = gpr_src(ctx, a->info, EXT_NONE);
>> +    TCGv op = tcg_constant_tl(a->invop);
>> +
>> +    gen_helper_invtlb(cpu_env, addr, info, op);
>> +    return true;
>> +}
> 
> Decode op here -- there are only 7 defined opcodes.
> 
> Note that you'll need to end the TB after most TLB instructions, since the translation of PC could change between one insn and the next.
> 
> 
>> +&fmt_invtlb         addr info invop
>> +@fmt_invtlb          ...... ...... ..... ..... ..... .....    &fmt_invtlb         %addr %info %invop
> 
> Why are you using the names addr and info instead of rk and rj?
> 
>> diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
>> index 1251e7f21c..916c675680 100644
>> --- a/target/loongarch/internals.h
>> +++ b/target/loongarch/internals.h
>> @@ -76,6 +76,14 @@ struct CPULoongArchTLBContext {
>>       int (*map_address)(struct CPULoongArchState *env, hwaddr *physical,
>>                          int *prot, target_ulong address,
>>                          MMUAccessType access_type);
>> +    void (*helper_tlbwr)(struct CPULoongArchState *env);
>> +    void (*helper_tlbfill)(struct CPULoongArchState *env);
>> +    void (*helper_tlbsrch)(struct CPULoongArchState *env);
>> +    void (*helper_tlbrd)(struct CPULoongArchState *env);
>> +    void (*helper_tlbclr)(struct CPULoongArchState *env);
>> +    void (*helper_tlbflush)(struct CPULoongArchState *env);
>> +    void (*helper_invtlb)(struct CPULoongArchState *env, target_ulong addr,
>> +                          target_ulong info, int op);
> 
> Again, function pointers are premature.
> 
>> +static uint64_t ls3a5k_pagesize_to_mask(int pagesize)
>> +{
>> +    /* 4KB - 1GB */
>> +    if (pagesize < 12 && pagesize > 30) {
>> +        qemu_log_mask(CPU_LOG_MMU, "unsupported page size %d\n", pagesize);
>> +        exit(-1);
> 
> Do not call exit.  Make up something sensible that won't crash qemu.
> 
>> +/* return random value in [low, high] */
>> +static uint32_t cpu_loongarch_get_random_ls3a5k_tlb(uint32_t low, uint32_t high)
>> +{
>> +    static uint32_t seed = 5;
>> +    static uint32_t prev_idx;
> 
> No static variables like this, as they cannot be migrated, and are a race condition between multiple cpus.  That said...
> 
>> +    uint32_t idx;
>> +    uint32_t nb_rand_tlb = high - low + 1;
>> +
>> +    do {
>> +        seed = 1103515245 * seed + 12345;
>> +        idx = (seed >> 16) % nb_rand_tlb + low;
>> +    } while (idx == prev_idx);
> 
> ... we have defined interfaces for getting random numbers.
> 
>
Do you mean the qemu_guest_getrandom function? It gets random values that do not limit the range.
But I need a random in a fixed range, I cannot find the  Similar interface. Thanks. 

 
> r~



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

* Re: [PATCH 07/31] target/loongarch: Add loongarch csr/iocsr instruction support
  2021-10-29  6:26     ` yangxiaojuan
@ 2021-10-29 17:38       ` Richard Henderson
  0 siblings, 0 replies; 37+ messages in thread
From: Richard Henderson @ 2021-10-29 17:38 UTC (permalink / raw)
  To: yangxiaojuan, qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, philmd, mark.cave-ayland,
	laurent, peterx, f4bug, alistair.francis, maobibo, gaosong,
	pbonzini, bmeng.cn, alex.bennee, david

On 10/28/21 11:26 PM, yangxiaojuan wrote:
> (1) For the iocsr registers, most of them act on the interrupt controller, the read and write will go to interrupt's mmio read/write.
> So I modified the addr to their mmio range. The ext interrupt controller use the sysbus's function to handle the interrupt cascade and
> sysbus_mmio_map to map the address which use the system memory region. So if I use a different address space, I realize a different
> sysbus_mmio_map function use a different address space, is it feasible ?

You shouldn't need a different function at all.  All of the difference will be in how you 
construct the mmio region: create a new address space, and add the mmio region to that 
address space at the correct base address.

> (2)Can you help me review the remaining patches? Thanks.

The remaining patches are harder for me to review, because I'm not as familiar with the 
fine details in hw/, but I'll try.


r~


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

* Re: [PATCH 08/31] target/loongarch: Add tlb instruction support
  2021-10-29  7:01     ` yangxiaojuan
@ 2021-10-29 17:48       ` Richard Henderson
  0 siblings, 0 replies; 37+ messages in thread
From: Richard Henderson @ 2021-10-29 17:48 UTC (permalink / raw)
  To: yangxiaojuan, qemu-devel
  Cc: peter.maydell, thuth, chenhuacai, philmd, mark.cave-ayland,
	laurent, peterx, f4bug, alistair.francis, maobibo, gaosong,
	pbonzini, bmeng.cn, alex.bennee, david

On 10/29/21 12:01 AM, yangxiaojuan wrote:
>>> +    env->CSR_CPUID = (cs->cpu_index & 0x1ff);
>>
>> Any reason to have a copy of cpu_index, as opposed to just using that field?  CSR_CPUID is read-only after all.
>>
> Yes, we need this value, the uefi code read this CPUID when Start slave cores.

That's not what I meant.  You could arrange for the csr read from CPUID to read from 
cs->cpu_index instead of env->CSR_CPUID.  You don't need a *separate* copy of this value.

I'm a bit concerned about the masking as well.  It would be better for hw/ to ensure that 
there are no more than 511 cpus.  Otherwise you'll have multiple cpus with identical CPUID.

>> ... we have defined interfaces for getting random numbers.
>>
>>
> Do you mean the qemu_guest_getrandom function? It gets random values that do not limit the range.
> But I need a random in a fixed range, I cannot find the  Similar interface. Thanks.

Yes, I mean qemu_guest_getrandom.

     uint32_t val;
     qemu_guest_getrandom_nofail(&val, sizeof(val));
     return val % (high - low + 1) + low;


r~


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

end of thread, other threads:[~2021-10-29 18:00 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-19  7:34 [PATCH 00/31] Add Loongarch softmmu support Xiaojuan Yang
2021-10-19  7:34 ` [PATCH 02/31] target/loongarch: Add CSR registers definition Xiaojuan Yang
2021-10-19 19:10   ` Richard Henderson
2021-10-19  7:34 ` [PATCH 03/31] target/loongarch: Set default csr values Xiaojuan Yang
2021-10-19 19:18   ` Richard Henderson
2021-10-19  7:34 ` [PATCH 04/31] target/loongarch: Add basic vmstate description of CPU Xiaojuan Yang
2021-10-19 19:35   ` Richard Henderson
2021-10-19  7:34 ` [PATCH 05/31] target/loongarch: Implement qmp_query_cpu_definitions() Xiaojuan Yang
2021-10-19 20:25   ` Richard Henderson
2021-10-19  7:34 ` [PATCH 08/31] target/loongarch: Add tlb instruction support Xiaojuan Yang
2021-10-20  4:19   ` Richard Henderson
2021-10-29  7:01     ` yangxiaojuan
2021-10-29 17:48       ` Richard Henderson
2021-10-19  7:34 ` [PATCH 09/31] target/loongarch: Add other core instructions support Xiaojuan Yang
2021-10-20  4:45   ` Richard Henderson
2021-10-19  7:34 ` [PATCH 10/31] target/loongarch: Add loongarch interrupt and exception handle Xiaojuan Yang
2021-10-20  4:59   ` Richard Henderson
2021-10-19  7:34 ` [PATCH 11/31] target/loongarch: Add stabletimer support Xiaojuan Yang
2021-10-19  7:34 ` [PATCH 12/31] target/loongarch: Add timer related instructions support Xiaojuan Yang
2021-10-20  5:17   ` Richard Henderson
2021-10-19  7:34 ` [PATCH 13/31] hw/pci-host: Add ls7a1000 PCIe Host bridge support for Loongson Platform Xiaojuan Yang
2021-10-19  7:35 ` [PATCH 14/31] hw/loongarch: Add a virt loongarch 3A5000 board support Xiaojuan Yang
2021-10-19  7:35 ` [PATCH 15/31] hw/loongarch: Add loongarch cpu interrupt support(CPUINTC) Xiaojuan Yang
2021-10-19  7:35 ` [PATCH 16/31] hw/loongarch: Add loongarch ipi interrupt support(IPI) Xiaojuan Yang
2021-10-19  7:35 ` [PATCH 17/31] hw/intc: Add loongarch ls7a interrupt controller support(PCH-PIC) Xiaojuan Yang
2021-10-19  7:35 ` [PATCH 18/31] hw/intc: Add loongarch ls7a msi interrupt controller support(PCH-MSI) Xiaojuan Yang
2021-10-19  7:35 ` [PATCH 19/31] hw/intc: Add loongarch extioi interrupt controller(EIOINTC) Xiaojuan Yang
2021-10-19  7:35 ` [PATCH 20/31] hw/loongarch: Add irq hierarchy for the system Xiaojuan Yang
2021-10-19 14:52 ` [PATCH 00/31] Add Loongarch softmmu support WANG Xuerui
     [not found]   ` <7d933f8d.228e.17c9b556e98.Coremail.yangxiaojuan@loongson.cn>
2021-10-20  5:11     ` WANG Xuerui
     [not found] ` <1634628917-10031-24-git-send-email-yangxiaojuan@loongson.cn>
2021-10-19 16:19   ` [PATCH 23/31] hw/loongarch: Add default bios startup support Michael S. Tsirkin
     [not found] ` <1634628917-10031-2-git-send-email-yangxiaojuan@loongson.cn>
2021-10-19 18:56   ` [PATCH 01/31] target/loongarch: Upate the README for the softmmu Richard Henderson
2021-10-22  2:25     ` yangxiaojuan
     [not found] ` <1634628917-10031-7-git-send-email-yangxiaojuan@loongson.cn>
2021-10-19 21:11   ` [PATCH 06/31] target/loongarch: Add mmu support for Loongarch CPU Richard Henderson
     [not found] ` <1634628917-10031-8-git-send-email-yangxiaojuan@loongson.cn>
2021-10-20  1:36   ` [PATCH 07/31] target/loongarch: Add loongarch csr/iocsr instruction support Richard Henderson
2021-10-29  6:26     ` yangxiaojuan
2021-10-29 17:38       ` Richard Henderson

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