[PATCH v6 8/8] tests/avocado: Boot Linux for RV32 cpu on RV64 QEMU

2024-07-19 Thread LIU Zhiwei
make check-avocado AVOCADO_TESTS=tests/avocado/tuxrun_baselines.py: \
TuxRunBaselineTest:test_riscv64_rv32

Signed-off-by: LIU Zhiwei 
Suggested-by: Daniel Henrique Barboza 
---
 tests/avocado/tuxrun_baselines.py | 16 
 1 file changed, 16 insertions(+)

diff --git a/tests/avocado/tuxrun_baselines.py 
b/tests/avocado/tuxrun_baselines.py
index 736e4aa289..589c7f254b 100644
--- a/tests/avocado/tuxrun_baselines.py
+++ b/tests/avocado/tuxrun_baselines.py
@@ -533,6 +533,22 @@ def test_riscv64_maxcpu(self):
 
 self.common_tuxrun(csums=sums)
 
+def test_riscv64_rv32(self):
+"""
+:avocado: tags=arch:riscv64
+:avocado: tags=machine:virt
+:avocado: tags=tuxboot:riscv32
+:avocado: tags=cpu:rv32
+"""
+sums = { "Image" :
+ 
"89599407d7334de629a40e7ad6503c73670359eb5f5ae9d686353a3d6deccbd5",
+ "fw_jump.elf" :
+ 
"f2ef28a0b77826f79d085d3e4aa686f1159b315eff9099a37046b18936676985",
+ "rootfs.ext4.zst" :
+ 
"7168d296d0283238ea73cd5a775b3dd608e55e04c7b92b76ecce31bb13108cba" }
+
+self.common_tuxrun(csums=sums)
+
 def test_s390(self):
 """
 :avocado: tags=arch:s390x
-- 
2.25.1




[PATCH v6 7/8] target/riscv: Add any32 and max32 CPU for RV64 QEMU

2024-07-19 Thread LIU Zhiwei
We may need 32-bit max or 32-bit any CPU for RV64 QEMU. Thus we add
these two CPUs for RV64 QEMU.

The reason we don't expose them to RV32 QEMU is that we already have
max or any cpu with the same configuration. Another reason is that
we want to follow the RISC-V custom where addw instruction doesn't
exist in RV32 CPU.

Signed-off-by: LIU Zhiwei 
Suggested-by: Daniel Henrique Barboza 
---
 target/riscv/cpu-qom.h |  2 ++
 target/riscv/cpu.c | 13 -
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h
index 3670cfe6d9..9f91743b78 100644
--- a/target/riscv/cpu-qom.h
+++ b/target/riscv/cpu-qom.h
@@ -31,6 +31,8 @@
 
 #define TYPE_RISCV_CPU_ANY  RISCV_CPU_TYPE_NAME("any")
 #define TYPE_RISCV_CPU_MAX  RISCV_CPU_TYPE_NAME("max")
+#define TYPE_RISCV_CPU_ANY32RISCV_CPU_TYPE_NAME("any32")
+#define TYPE_RISCV_CPU_MAX32RISCV_CPU_TYPE_NAME("max32")
 #define TYPE_RISCV_CPU_BASE32   RISCV_CPU_TYPE_NAME("rv32")
 #define TYPE_RISCV_CPU_BASE64   RISCV_CPU_TYPE_NAME("rv64")
 #define TYPE_RISCV_CPU_BASE128  RISCV_CPU_TYPE_NAME("x-rv128")
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 0df145d90f..ab2512bb19 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -464,11 +464,9 @@ static void riscv_max_cpu_init(Object *obj)
 
 env->priv_ver = PRIV_VERSION_LATEST;
 #ifndef CONFIG_USER_ONLY
-#ifdef TARGET_RISCV32
-set_satp_mode_max_supported(cpu, VM_1_10_SV32);
-#else
-set_satp_mode_max_supported(cpu, VM_1_10_SV57);
-#endif
+set_satp_mode_max_supported(RISCV_CPU(obj),
+riscv_cpu_mxl(_CPU(obj)->env) == MXL_RV32 ?
+VM_1_10_SV32 : VM_1_10_SV57);
 #endif
 }
 
@@ -2962,6 +2960,11 @@ static const TypeInfo riscv_cpu_type_infos[] = {
 DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV32E,MXL_RV32,  
rv32e_bare_cpu_init),
 #endif
 
+#if (defined(TARGET_RISCV64) && !defined(CONFIG_USER_ONLY))
+DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY32, MXL_RV32,  
riscv_any_cpu_init),
+DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX32, MXL_RV32,  
riscv_max_cpu_init),
+#endif
+
 #if defined(TARGET_RISCV64)
 DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE64,MXL_RV64,  
rv64_base_cpu_init),
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E51, MXL_RV64,  
rv64_sifive_e_cpu_init),
-- 
2.25.1




[PATCH v6 6/8] target/riscv: Enable RV32 CPU support in RV64 QEMU

2024-07-19 Thread LIU Zhiwei
From: TANG Tiancheng 

Add gdb XML files and adjust CPU initialization to allow running RV32 CPUs
in RV64 QEMU.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
Reviewed-by: Alistair Francis 
---
 configs/targets/riscv64-softmmu.mak |  2 +-
 target/riscv/cpu.c  | 17 +
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/configs/targets/riscv64-softmmu.mak 
b/configs/targets/riscv64-softmmu.mak
index 917980e63e..6c5de72e03 100644
--- a/configs/targets/riscv64-softmmu.mak
+++ b/configs/targets/riscv64-softmmu.mak
@@ -2,6 +2,6 @@ TARGET_ARCH=riscv64
 TARGET_BASE_ARCH=riscv
 TARGET_SUPPORTS_MTTCG=y
 TARGET_KVM_HAVE_GUEST_DEBUG=y
-TARGET_XML_FILES= gdb-xml/riscv-64bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml 
gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-64bit-virtual.xml
+TARGET_XML_FILES= gdb-xml/riscv-64bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml 
gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-64bit-virtual.xml 
gdb-xml/riscv-32bit-cpu.xml gdb-xml/riscv-32bit-virtual.xml
 # needed by boot.c
 TARGET_NEED_FDT=y
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index c53b0d5b40..0df145d90f 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -630,8 +630,10 @@ static void rv64e_bare_cpu_init(Object *obj)
 riscv_cpu_set_misa_ext(env, RVE);
 }
 
-#else /* !TARGET_RISCV64 */
+#endif /* !TARGET_RISCV64 */
 
+#if defined(TARGET_RISCV32) || \
+(defined(TARGET_RISCV64) && !defined(CONFIG_USER_ONLY))
 static void rv32_base_cpu_init(Object *obj)
 {
 RISCVCPU *cpu = RISCV_CPU(obj);
@@ -2944,6 +2946,13 @@ static const TypeInfo riscv_cpu_type_infos[] = {
 #if defined(TARGET_RISCV32)
 DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,   MXL_RV32,  
riscv_any_cpu_init),
 DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,   MXL_RV32,  
riscv_max_cpu_init),
+#elif defined(TARGET_RISCV64)
+DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,   MXL_RV64,  
riscv_any_cpu_init),
+DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,   MXL_RV64,  
riscv_max_cpu_init),
+#endif
+
+#if defined(TARGET_RISCV32) || \
+(defined(TARGET_RISCV64) && !defined(CONFIG_USER_ONLY))
 DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE32,MXL_RV32,  
rv32_base_cpu_init),
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_IBEX,   MXL_RV32,  
rv32_ibex_cpu_init),
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E31, MXL_RV32,  
rv32_sifive_e_cpu_init),
@@ -2951,9 +2960,9 @@ static const TypeInfo riscv_cpu_type_infos[] = {
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U34, MXL_RV32,  
rv32_sifive_u_cpu_init),
 DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV32I,MXL_RV32,  
rv32i_bare_cpu_init),
 DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV32E,MXL_RV32,  
rv32e_bare_cpu_init),
-#elif defined(TARGET_RISCV64)
-DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,   MXL_RV64,  
riscv_any_cpu_init),
-DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,   MXL_RV64,  
riscv_max_cpu_init),
+#endif
+
+#if defined(TARGET_RISCV64)
 DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE64,MXL_RV64,  
rv64_base_cpu_init),
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E51, MXL_RV64,  
rv64_sifive_e_cpu_init),
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U54, MXL_RV64,  
rv64_sifive_u_cpu_init),
-- 
2.25.1




[PATCH v6 5/8] target/riscv: Correct mcause/scause bit width for RV32 in RV64 QEMU

2024-07-19 Thread LIU Zhiwei
From: TANG Tiancheng 

Ensure mcause high bit is correctly set by using 32-bit width for RV32
mode and 64-bit width for RV64 mode.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu_helper.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 4f0ab90ac7..3eedb26cd9 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -1673,6 +1673,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 target_ulong tinst = 0;
 target_ulong htval = 0;
 target_ulong mtval2 = 0;
+int sxlen = 0;
+int mxlen = 0;
 
 if (!async) {
 /* set tval to badaddr for traps with address information */
@@ -1799,7 +1801,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 s = set_field(s, MSTATUS_SPP, env->priv);
 s = set_field(s, MSTATUS_SIE, 0);
 env->mstatus = s;
-env->scause = cause | ((target_ulong)async << (TARGET_LONG_BITS - 1));
+sxlen = 16 << riscv_cpu_sxl(env);
+env->scause = cause | ((target_ulong)async << (sxlen - 1));
 env->sepc = env->pc;
 env->stval = tval;
 env->htval = htval;
@@ -1830,7 +1833,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 s = set_field(s, MSTATUS_MPP, env->priv);
 s = set_field(s, MSTATUS_MIE, 0);
 env->mstatus = s;
-env->mcause = cause | ~(((target_ulong)-1) >> async);
+mxlen = 16 << riscv_cpu_mxl(env);
+env->mcause = cause | ((target_ulong)async << (mxlen - 1));
 env->mepc = env->pc;
 env->mtval = tval;
 env->mtval2 = mtval2;
-- 
2.25.1




[PATCH v6 4/8] target/riscv: Detect sxl to set bit width for RV32 in RV64

2024-07-19 Thread LIU Zhiwei
From: TANG Tiancheng 

Ensure correct bit width based on sxl when running RV32 on RV64 QEMU.
This is required as MMU address translations run in S-mode.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu_helper.c | 17 -
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 6709622dd3..4f0ab90ac7 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -887,12 +887,14 @@ static int get_physical_address(CPURISCVState *env, 
hwaddr *physical,
 
 CPUState *cs = env_cpu(env);
 int va_bits = PGSHIFT + levels * ptidxbits + widened;
+int sxlen = 16 << riscv_cpu_sxl(env);
+int sxlen_bytes = sxlen / 8;
 
 if (first_stage == true) {
 target_ulong mask, masked_msbs;
 
-if (TARGET_LONG_BITS > (va_bits - 1)) {
-mask = (1L << (TARGET_LONG_BITS - (va_bits - 1))) - 1;
+if (sxlen > (va_bits - 1)) {
+mask = (1L << (sxlen - (va_bits - 1))) - 1;
 } else {
 mask = 0;
 }
@@ -961,7 +963,7 @@ restart:
 
 int pmp_prot;
 int pmp_ret = get_physical_address_pmp(env, _prot, pte_addr,
-   sizeof(target_ulong),
+   sxlen_bytes,
MMU_DATA_LOAD, PRV_S);
 if (pmp_ret != TRANSLATE_SUCCESS) {
 return TRANSLATE_PMP_FAIL;
@@ -1113,7 +1115,7 @@ restart:
  *   it is no longer valid and we must re-walk the page table.
  */
 MemoryRegion *mr;
-hwaddr l = sizeof(target_ulong), addr1;
+hwaddr l = sxlen_bytes, addr1;
 mr = address_space_translate(cs->as, pte_addr, , ,
  false, MEMTXATTRS_UNSPECIFIED);
 if (memory_region_is_ram(mr)) {
@@ -1125,7 +1127,12 @@ restart:
  */
 *pte_pa = pte = updated_pte;
 #else
-target_ulong old_pte = qatomic_cmpxchg(pte_pa, pte, updated_pte);
+target_ulong old_pte;
+if (riscv_cpu_sxl(env) == MXL_RV32) {
+old_pte = qatomic_cmpxchg((uint32_t *)pte_pa, pte, 
updated_pte);
+} else {
+old_pte = qatomic_cmpxchg(pte_pa, pte, updated_pte);
+}
 if (old_pte != pte) {
 goto restart;
 }
-- 
2.25.1




[PATCH v6 3/8] target/riscv: Correct SXL return value for RV32 in RV64 QEMU

2024-07-19 Thread LIU Zhiwei
From: TANG Tiancheng 

Ensure that riscv_cpu_sxl returns MXL_RV32 when runningRV32 in an
RV64 QEMU.

Signed-off-by: TANG Tiancheng 
Fixes: 05e6ca5e156 ("target/riscv: Ignore reserved bits in PTE for RV64")
Reviewed-by: Liu Zhiwei 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.h | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 87742047ce..49de81be7e 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -693,8 +693,11 @@ static inline RISCVMXL riscv_cpu_sxl(CPURISCVState *env)
 #ifdef CONFIG_USER_ONLY
 return env->misa_mxl;
 #else
-return get_field(env->mstatus, MSTATUS64_SXL);
+if (env->misa_mxl != MXL_RV32) {
+return get_field(env->mstatus, MSTATUS64_SXL);
+}
 #endif
+return MXL_RV32;
 }
 #endif
 
-- 
2.25.1




[PATCH v6 1/8] target/riscv: Add fw_dynamic_info32 for booting RV32 OpenSBI

2024-07-19 Thread LIU Zhiwei
From: TANG Tiancheng 

RV32 OpenSBI need a fw_dynamic_info parameter with 32-bit fields instead
of target_ulong.

In RV64 QEMU, target_ulong is 64. So it is not right for booting RV32 OpenSBI.
We create a fw_dynmaic_info32 struct for this purpose.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
Reviewed-by: Alistair Francis 
---
 hw/riscv/boot.c | 35 ++---
 hw/riscv/sifive_u.c |  3 ++-
 include/hw/riscv/boot.h |  4 +++-
 include/hw/riscv/boot_opensbi.h | 29 +++
 4 files changed, 57 insertions(+), 14 deletions(-)

diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
index 47281ca853..1a2c1ff9e0 100644
--- a/hw/riscv/boot.c
+++ b/hw/riscv/boot.c
@@ -342,27 +342,33 @@ void riscv_load_fdt(hwaddr fdt_addr, void *fdt)
 rom_ptr_for_as(_space_memory, fdt_addr, 
fdtsize));
 }
 
-void riscv_rom_copy_firmware_info(MachineState *machine, hwaddr rom_base,
-  hwaddr rom_size, uint32_t reset_vec_size,
+void riscv_rom_copy_firmware_info(MachineState *machine,
+  RISCVHartArrayState *harts,
+  hwaddr rom_base, hwaddr rom_size,
+  uint32_t reset_vec_size,
   uint64_t kernel_entry)
 {
+struct fw_dynamic_info32 dinfo32;
 struct fw_dynamic_info dinfo;
 size_t dinfo_len;
 
-if (sizeof(dinfo.magic) == 4) {
-dinfo.magic = cpu_to_le32(FW_DYNAMIC_INFO_MAGIC_VALUE);
-dinfo.version = cpu_to_le32(FW_DYNAMIC_INFO_VERSION);
-dinfo.next_mode = cpu_to_le32(FW_DYNAMIC_INFO_NEXT_MODE_S);
-dinfo.next_addr = cpu_to_le32(kernel_entry);
+if (riscv_is_32bit(harts)) {
+dinfo32.magic = cpu_to_le32(FW_DYNAMIC_INFO_MAGIC_VALUE);
+dinfo32.version = cpu_to_le32(FW_DYNAMIC_INFO_VERSION);
+dinfo32.next_mode = cpu_to_le32(FW_DYNAMIC_INFO_NEXT_MODE_S);
+dinfo32.next_addr = cpu_to_le32(kernel_entry);
+dinfo32.options = 0;
+dinfo32.boot_hart = 0;
+dinfo_len = sizeof(dinfo32);
 } else {
 dinfo.magic = cpu_to_le64(FW_DYNAMIC_INFO_MAGIC_VALUE);
 dinfo.version = cpu_to_le64(FW_DYNAMIC_INFO_VERSION);
 dinfo.next_mode = cpu_to_le64(FW_DYNAMIC_INFO_NEXT_MODE_S);
 dinfo.next_addr = cpu_to_le64(kernel_entry);
+dinfo.options = 0;
+dinfo.boot_hart = 0;
+dinfo_len = sizeof(dinfo);
 }
-dinfo.options = 0;
-dinfo.boot_hart = 0;
-dinfo_len = sizeof(dinfo);
 
 /**
  * copy the dynamic firmware info. This information is specific to
@@ -374,7 +380,10 @@ void riscv_rom_copy_firmware_info(MachineState *machine, 
hwaddr rom_base,
 exit(1);
 }
 
-rom_add_blob_fixed_as("mrom.finfo", , dinfo_len,
+rom_add_blob_fixed_as("mrom.finfo",
+   riscv_is_32bit(harts) ?
+   (void *) : (void *),
+   dinfo_len,
rom_base + reset_vec_size,
_space_memory);
 }
@@ -430,7 +439,9 @@ void riscv_setup_rom_reset_vec(MachineState *machine, 
RISCVHartArrayState *harts
 }
 rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
   rom_base, _space_memory);
-riscv_rom_copy_firmware_info(machine, rom_base, rom_size, 
sizeof(reset_vec),
+riscv_rom_copy_firmware_info(machine, harts,
+ rom_base, rom_size,
+ sizeof(reset_vec),
  kernel_entry);
 }
 
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index af5f923f54..5010c3eadb 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -646,7 +646,8 @@ static void sifive_u_machine_init(MachineState *machine)
 rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
   memmap[SIFIVE_U_DEV_MROM].base, 
_space_memory);
 
-riscv_rom_copy_firmware_info(machine, memmap[SIFIVE_U_DEV_MROM].base,
+riscv_rom_copy_firmware_info(machine, >soc.u_cpus,
+ memmap[SIFIVE_U_DEV_MROM].base,
  memmap[SIFIVE_U_DEV_MROM].size,
  sizeof(reset_vec), kernel_entry);
 
diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
index a2e4ae9cb0..806256d23f 100644
--- a/include/hw/riscv/boot.h
+++ b/include/hw/riscv/boot.h
@@ -56,7 +56,9 @@ void riscv_setup_rom_reset_vec(MachineState *machine, 
RISCVHartArrayState *harts
hwaddr rom_base, hwaddr rom_size,
uint64_t kernel_entry,
uint64_t fdt_load_addr);
-void riscv_rom_copy_firmware_info(MachineState *machine, hwaddr rom_base,
+void riscv_rom_copy_firmware_info(MachineState *machine,
+ 

[PATCH v6 2/8] target/riscv: Adjust PMP size for no-MMU RV64 QEMU running RV32

2024-07-19 Thread LIU Zhiwei
From: TANG Tiancheng 

Ensure pmp_size is correctly determined using mxl for RV32
in RV64 QEMU.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
Reviewed-by: Alistair Francis 
---
 target/riscv/pmp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
index 9eea397e72..5e74b7220f 100644
--- a/target/riscv/pmp.c
+++ b/target/riscv/pmp.c
@@ -326,7 +326,7 @@ bool pmp_hart_has_privs(CPURISCVState *env, hwaddr addr,
  */
 pmp_size = -(addr | TARGET_PAGE_MASK);
 } else {
-pmp_size = sizeof(target_ulong);
+pmp_size = 2 << riscv_cpu_mxl(env);
 }
 } else {
 pmp_size = size;
-- 
2.25.1




[PATCH v6 0/8] target/riscv: Expose RV32 cpu to RV64 QEMU

2024-07-19 Thread LIU Zhiwei
This patch set aims to expose 32-bit RISC-V cpu to RV64 QEMU. Thus
qemu-system-riscv64 can directly boot a RV32 Linux.

This patch set has been tested with 6.9.0 Linux Image.
And add an avocado tuxrun test in tests/avocado.

v6:
  Use TUXRUN test case instead of boot_linux_console
  Add any32 and max32 cpu for RV64 QEMU 

v5:
  Rebase to master and add tags  

v4:
  Drop UL completely in PATCH v3 2/7, 4/7, 5/7.
  Avocado: Add "if=none" to "-drive" option in QEMU command line

v3:
  Rebase to the master branch

v2:
  Remove the line that was inadvertently left in PATCH v1 4/6.
  Add an avocado test.

v1:
  https://mail.gnu.org/archive/html/qemu-riscv/2024-06/msg00501.html


LIU Zhiwei (2):
  target/riscv: Add any32 and max32 CPU for RV64 QEMU
  tests/avocado: Boot Linux for RV32 cpu on RV64 QEMU

TANG Tiancheng (6):
  target/riscv: Add fw_dynamic_info32 for booting RV32 OpenSBI
  target/riscv: Adjust PMP size for no-MMU RV64 QEMU running RV32
  target/riscv: Correct SXL return value for RV32 in RV64 QEMU
  target/riscv: Detect sxl to set bit width for RV32 in RV64
  target/riscv: Correct mcause/scause bit width for RV32 in RV64 QEMU
  target/riscv: Enable RV32 CPU support in RV64 QEMU

 configs/targets/riscv64-softmmu.mak |  2 +-
 hw/riscv/boot.c | 35 +++--
 hw/riscv/sifive_u.c |  3 ++-
 include/hw/riscv/boot.h |  4 +++-
 include/hw/riscv/boot_opensbi.h | 29 
 target/riscv/cpu-qom.h  |  2 ++
 target/riscv/cpu.c  | 30 +
 target/riscv/cpu.h  |  5 -
 target/riscv/cpu_helper.c   | 25 +++--
 target/riscv/pmp.c  |  2 +-
 tests/avocado/tuxrun_baselines.py   | 16 +
 11 files changed, 120 insertions(+), 33 deletions(-)

-- 
2.25.1




Re: [PATCH v5 0/7] target/riscv: Expose RV32 cpu to RV64 QEMU

2024-07-14 Thread LIU Zhiwei



On 2024/7/12 17:57, Daniel Henrique Barboza wrote:



On 7/9/24 11:24 PM, LIU Zhiwei wrote:

From: 甲一 

This patch set aims to expose 32-bit RISC-V cpu to RV64 QEMU. Thus
qemu-system-riscv64 can directly boot a RV32 Linux.

This patch set has been tested with 6.9.0 Linux Image.
And add an avocado test in tests/avocado.


Thanks for this work and sorry for the late review.

One thing to look out as a follow-up is the 'max' CPU. It has the same 
name
in both 32 and 64 bits so it'll result in a conflict with the 'max' 
CPU for

rv64.

One easy way out is to add a new 'max32' bit CPU for riscv32, which 
would be an

alias for the 'max' CPU, then adding 'max32' support in rv64.


I think it is good. One question is if we should also add any32 cpu for 
rv64, which has the similar conflict of 'max' CPU.


Thanks,
Zhiwei




Thanks,

Daniel




# make check-avocado 
AVOCADO_TESTS=/home/jenkins/git/qemu/tests/avocado/boot_linux_console.py:BootLinuxConsole.test_riscv64_virt_rv32i

   VENVPIP install -e /home/jenkins/git/qemu/python/
/home/jenkins/git/qemu/build/pyvenv/bin/python3 -B 
/home/jenkins/git/qemu/python/scripts/mkvenv.py ensuregroup --online 
/home/jenkins/git/qemu/pythondeps.toml avocado

mkvenv: checking for avocado-framework(>=88.1, <93.0)
mkvenv: checking for pycdlib>=1.11.0
mkvenv: installing avocado-framework==88.1, pycdlib>=1.11.0
   AVOCADO tests/avocado
Fetching asset from 
/home/jenkins/git/qemu/tests/avocado/boot_linux_console.py:BootLinuxConsole.test_riscv64_virt_rv32i
Fetching asset from 
/home/jenkins/git/qemu/tests/avocado/boot_linux_console.py:BootLinuxConsole.test_riscv64_virt_rv32i

JOB ID : 8c2e1ff918d3111d078a52eba9956893afaf9e1d
JOB LOG    : 
/home/jenkins/git/qemu/build/tests/results/job-2024-07-10T09.55-8c2e1ff/job.log
  (1/1) 
/home/jenkins/git/qemu/tests/avocado/boot_linux_console.py:BootLinuxConsole.test_riscv64_virt_rv32i: 
PASS (17.50 s)
RESULTS    : PASS 1 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 
0 | CANCEL 0

JOB TIME   : 29.50 s

v5:
   Rebase to master and add tags

v4:
   Drop UL completely in PATCH v3 2/7, 4/7, 5/7.
   Avocado: Add "if=none" to "-drive" option in QEMU command line

v3:
   Rebase to the master branch

v2:
   Remove the line that was inadvertently left in PATCH v1 4/6.
   Add an avocado test.

v1:
https://mail.gnu.org/archive/html/qemu-riscv/2024-06/msg00501.html

TANG Tiancheng (7):
   target/riscv: Add fw_dynamic_info32 for booting RV32 OpenSBI
   target/riscv: Adjust PMP size for no-MMU RV64 QEMU running RV32
   target/riscv: Correct SXL return value for RV32 in RV64 QEMU
   target/riscv: Detect sxl to set bit width for RV32 in RV64
   target/riscv: Correct mcause/scause bit width for RV32 in RV64 QEMU
   target/riscv: Enable RV32 CPU support in RV64 QEMU
   tests/avocado: Add an avocado test for riscv64

  configs/targets/riscv64-softmmu.mak |  2 +-
  hw/riscv/boot.c | 35 +-
  hw/riscv/sifive_u.c |  3 ++-
  include/hw/riscv/boot.h |  4 ++-
  include/hw/riscv/boot_opensbi.h | 29 ++
  target/riscv/cpu.c  | 17 ++---
  target/riscv/cpu.h  |  5 +++-
  target/riscv/cpu_helper.c   | 25 +--
  target/riscv/pmp.c  |  2 +-
  tests/avocado/boot_linux_console.py | 38 +
  10 files changed, 132 insertions(+), 28 deletions(-)





Re: [PATCH v5 7/7] tests/avocado: Add an avocado test for riscv64

2024-07-14 Thread LIU Zhiwei



On 2024/7/12 17:52, Daniel Henrique Barboza wrote:



On 7/9/24 11:24 PM, LIU Zhiwei wrote:

From: TANG Tiancheng 

To regularly test booting Linux with rv32 on QEMU RV64,
we have added a test to boot_linux_console.py to retrieve
cpuinfo and verify if it shows 'rv32' when using RV64 to
boot rv32 CPUs.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
Acked-by: Alistair Francis 
---
  tests/avocado/boot_linux_console.py | 38 +
  1 file changed, 38 insertions(+)

diff --git a/tests/avocado/boot_linux_console.py 
b/tests/avocado/boot_linux_console.py

index c35fc5e9ba..6d2f3b05cb 100644
--- a/tests/avocado/boot_linux_console.py
+++ b/tests/avocado/boot_linux_console.py
@@ -12,6 +12,7 @@
  import lzma
  import gzip
  import shutil
+import time
    from avocado import skip
  from avocado import skipUnless
@@ -1545,3 +1546,40 @@ def test_xtensa_lx60(self):
  """
  tar_hash = '49e88d9933742f0164b60839886c9739cb7a0d34'
  self.do_test_advcal_2018('02', tar_hash, 
'santas-sleigh-ride.elf')

+
+    def test_riscv64_virt_rv32i(self):
+    """
+    :avocado: tags=arch:riscv64
+    :avocado: tags=machine:virt
+    :avocado: tags=cpu:rv32
+    """
+    kernel_url = 
('https://github.com/romanheros/rv32-linux/raw/master/'

+  'Image32.xz')
+    kernel_hash = 'a7ced5c38722481e0821b7cd70719cf53e46c13b'
+    kernel_path_xz = self.fetch_asset(kernel_url, 
asset_hash=kernel_hash)

+
+    kernel_path =  os.path.join(self.workdir, 'kernel.riscv32')
+    archive.lzma_uncompress(kernel_path_xz, kernel_path)
+
+    rootfs_url = 
('https://github.com/romanheros/rv32-linux/raw/master/'

+  'rootfs.ext2.xz')
+    rootfs_hash = 'dc25ab9d4b233e8e0bcf7eb220d56fd2008fe263'
+    rootfs_path_xz = self.fetch_asset(rootfs_url, 
asset_hash=rootfs_hash)

+
+    rootfs_path =  os.path.join(self.workdir, 'rootfs.riscv32')
+    archive.lzma_uncompress(rootfs_path_xz, rootfs_path)
+
+    self.vm.set_console()
+    kernel_command_line = 'root=/dev/vda ro console=ttyS0'
+    self.vm.add_args('-kernel', kernel_path,
+ '-append', kernel_command_line,
+ '-drive', 'file=' + rootfs_path +
+ ',format=raw,id=hd0,if=none',
+ '-device', 'virtio-blk-device,drive=hd0')
+    self.vm.launch()
+
+    console_pattern = 'Welcome to Buildroot'
+    self.wait_for_console_pattern(console_pattern)
+    exec_command(self, 'root')
+    time.sleep(0.1)
+    exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', 
'rv32i')



Nothing wrong with adding a boot_linux_console.py, but if we could add 
a tuxrun_baselines.py

testsuite instead I think it would be great.

I believe Tuxboot is now the preferable way of testing a distro up to 
boot in QEMU. We have
all other RISC-V CPU boards and CPUs tested in that framework. It's 
also faster to run.


Here's a diff adding it:

$ git diff
diff --git a/tests/avocado/tuxrun_baselines.py 
b/tests/avocado/tuxrun_baselines.py

index 736e4aa289..589c7f254b 100644
--- a/tests/avocado/tuxrun_baselines.py
+++ b/tests/avocado/tuxrun_baselines.py
@@ -533,6 +533,22 @@ def test_riscv64_maxcpu(self):

 self.common_tuxrun(csums=sums)

+    def test_riscv64_rv32(self):
+    """
+    :avocado: tags=arch:riscv64
+    :avocado: tags=machine:virt
+    :avocado: tags=tuxboot:riscv32
+    :avocado: tags=cpu:rv32
+    """
+    sums = { "Image" :
+ "89599407d7334de629a40e7ad6503c73670359eb5f5ae9d686353a3d6deccbd5",
+ "fw_jump.elf" :
+ "f2ef28a0b77826f79d085d3e4aa686f1159b315eff9099a37046b18936676985",
+ "rootfs.ext4.zst" :
+ "7168d296d0283238ea73cd5a775b3dd608e55e04c7b92b76ecce31bb13108cba" }
+
+    self.common_tuxrun(csums=sums)
+
 def test_s390(self):
 """
 :avocado: tags=arch:s390x


$ make check-avocado
(...)
 (01/21) 
tests/avocado/boot_linux_console.py:BootLinuxConsole.test_riscv64_virt_rv32i: 
PASS (22.32 s)

(...)
 (14/21) 
tests/avocado/tuxrun_baselines.py:TuxRunBaselineTest.test_riscv64_rv32: 
PASS (10.34 s)


Hi Daniel,

Thanks for sharing this test way to us. I'd like to replace our test 
with yours. And this commit will be authored to you.


Thanks,
Zhiwei





Thanks,

Daniel




[PATCH v5 7/7] tests/avocado: Add an avocado test for riscv64

2024-07-09 Thread LIU Zhiwei
From: TANG Tiancheng 

To regularly test booting Linux with rv32 on QEMU RV64,
we have added a test to boot_linux_console.py to retrieve
cpuinfo and verify if it shows 'rv32' when using RV64 to
boot rv32 CPUs.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
Acked-by: Alistair Francis 
---
 tests/avocado/boot_linux_console.py | 38 +
 1 file changed, 38 insertions(+)

diff --git a/tests/avocado/boot_linux_console.py 
b/tests/avocado/boot_linux_console.py
index c35fc5e9ba..6d2f3b05cb 100644
--- a/tests/avocado/boot_linux_console.py
+++ b/tests/avocado/boot_linux_console.py
@@ -12,6 +12,7 @@
 import lzma
 import gzip
 import shutil
+import time
 
 from avocado import skip
 from avocado import skipUnless
@@ -1545,3 +1546,40 @@ def test_xtensa_lx60(self):
 """
 tar_hash = '49e88d9933742f0164b60839886c9739cb7a0d34'
 self.do_test_advcal_2018('02', tar_hash, 'santas-sleigh-ride.elf')
+
+def test_riscv64_virt_rv32i(self):
+"""
+:avocado: tags=arch:riscv64
+:avocado: tags=machine:virt
+:avocado: tags=cpu:rv32
+"""
+kernel_url = ('https://github.com/romanheros/rv32-linux/raw/master/'
+  'Image32.xz')
+kernel_hash = 'a7ced5c38722481e0821b7cd70719cf53e46c13b'
+kernel_path_xz = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
+
+kernel_path =  os.path.join(self.workdir, 'kernel.riscv32')
+archive.lzma_uncompress(kernel_path_xz, kernel_path)
+
+rootfs_url = ('https://github.com/romanheros/rv32-linux/raw/master/'
+  'rootfs.ext2.xz')
+rootfs_hash = 'dc25ab9d4b233e8e0bcf7eb220d56fd2008fe263'
+rootfs_path_xz = self.fetch_asset(rootfs_url, asset_hash=rootfs_hash)
+
+rootfs_path =  os.path.join(self.workdir, 'rootfs.riscv32')
+archive.lzma_uncompress(rootfs_path_xz, rootfs_path)
+
+self.vm.set_console()
+kernel_command_line = 'root=/dev/vda ro console=ttyS0'
+self.vm.add_args('-kernel', kernel_path,
+ '-append', kernel_command_line,
+ '-drive', 'file=' + rootfs_path +
+   ',format=raw,id=hd0,if=none',
+ '-device', 'virtio-blk-device,drive=hd0')
+self.vm.launch()
+
+console_pattern = 'Welcome to Buildroot'
+self.wait_for_console_pattern(console_pattern)
+exec_command(self, 'root')
+time.sleep(0.1)
+exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', 'rv32i')
-- 
2.25.1




[PATCH v5 6/7] target/riscv: Enable RV32 CPU support in RV64 QEMU

2024-07-09 Thread LIU Zhiwei
From: TANG Tiancheng 

Add gdb XML files and adjust CPU initialization to allow running RV32 CPUs
in RV64 QEMU.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
Reviewed-by: Alistair Francis 
---
 configs/targets/riscv64-softmmu.mak |  2 +-
 target/riscv/cpu.c  | 17 +
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/configs/targets/riscv64-softmmu.mak 
b/configs/targets/riscv64-softmmu.mak
index 917980e63e..6c5de72e03 100644
--- a/configs/targets/riscv64-softmmu.mak
+++ b/configs/targets/riscv64-softmmu.mak
@@ -2,6 +2,6 @@ TARGET_ARCH=riscv64
 TARGET_BASE_ARCH=riscv
 TARGET_SUPPORTS_MTTCG=y
 TARGET_KVM_HAVE_GUEST_DEBUG=y
-TARGET_XML_FILES= gdb-xml/riscv-64bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml 
gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-64bit-virtual.xml
+TARGET_XML_FILES= gdb-xml/riscv-64bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml 
gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-64bit-virtual.xml 
gdb-xml/riscv-32bit-cpu.xml gdb-xml/riscv-32bit-virtual.xml
 # needed by boot.c
 TARGET_NEED_FDT=y
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index a2640cf259..fdd0f10aa5 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -630,8 +630,10 @@ static void rv64e_bare_cpu_init(Object *obj)
 riscv_cpu_set_misa_ext(env, RVE);
 }
 
-#else /* !TARGET_RISCV64 */
+#endif /* !TARGET_RISCV64 */
 
+#if defined(TARGET_RISCV32) || \
+(defined(TARGET_RISCV64) && !defined(CONFIG_USER_ONLY))
 static void rv32_base_cpu_init(Object *obj)
 {
 RISCVCPU *cpu = RISCV_CPU(obj);
@@ -2944,6 +2946,13 @@ static const TypeInfo riscv_cpu_type_infos[] = {
 #if defined(TARGET_RISCV32)
 DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,   MXL_RV32,  
riscv_any_cpu_init),
 DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,   MXL_RV32,  
riscv_max_cpu_init),
+#elif defined(TARGET_RISCV64)
+DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,   MXL_RV64,  
riscv_any_cpu_init),
+DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,   MXL_RV64,  
riscv_max_cpu_init),
+#endif
+
+#if defined(TARGET_RISCV32) || \
+(defined(TARGET_RISCV64) && !defined(CONFIG_USER_ONLY))
 DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE32,MXL_RV32,  
rv32_base_cpu_init),
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_IBEX,   MXL_RV32,  
rv32_ibex_cpu_init),
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E31, MXL_RV32,  
rv32_sifive_e_cpu_init),
@@ -2951,9 +2960,9 @@ static const TypeInfo riscv_cpu_type_infos[] = {
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U34, MXL_RV32,  
rv32_sifive_u_cpu_init),
 DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV32I,MXL_RV32,  
rv32i_bare_cpu_init),
 DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV32E,MXL_RV32,  
rv32e_bare_cpu_init),
-#elif defined(TARGET_RISCV64)
-DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,   MXL_RV64,  
riscv_any_cpu_init),
-DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,   MXL_RV64,  
riscv_max_cpu_init),
+#endif
+
+#if defined(TARGET_RISCV64)
 DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE64,MXL_RV64,  
rv64_base_cpu_init),
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E51, MXL_RV64,  
rv64_sifive_e_cpu_init),
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U54, MXL_RV64,  
rv64_sifive_u_cpu_init),
-- 
2.25.1




[PATCH v5 5/7] target/riscv: Correct mcause/scause bit width for RV32 in RV64 QEMU

2024-07-09 Thread LIU Zhiwei
From: TANG Tiancheng 

Ensure mcause high bit is correctly set by using 32-bit width for RV32
mode and 64-bit width for RV64 mode.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu_helper.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 4f0ab90ac7..3eedb26cd9 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -1673,6 +1673,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 target_ulong tinst = 0;
 target_ulong htval = 0;
 target_ulong mtval2 = 0;
+int sxlen = 0;
+int mxlen = 0;
 
 if (!async) {
 /* set tval to badaddr for traps with address information */
@@ -1799,7 +1801,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 s = set_field(s, MSTATUS_SPP, env->priv);
 s = set_field(s, MSTATUS_SIE, 0);
 env->mstatus = s;
-env->scause = cause | ((target_ulong)async << (TARGET_LONG_BITS - 1));
+sxlen = 16 << riscv_cpu_sxl(env);
+env->scause = cause | ((target_ulong)async << (sxlen - 1));
 env->sepc = env->pc;
 env->stval = tval;
 env->htval = htval;
@@ -1830,7 +1833,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 s = set_field(s, MSTATUS_MPP, env->priv);
 s = set_field(s, MSTATUS_MIE, 0);
 env->mstatus = s;
-env->mcause = cause | ~(((target_ulong)-1) >> async);
+mxlen = 16 << riscv_cpu_mxl(env);
+env->mcause = cause | ((target_ulong)async << (mxlen - 1));
 env->mepc = env->pc;
 env->mtval = tval;
 env->mtval2 = mtval2;
-- 
2.25.1




[PATCH v5 4/7] target/riscv: Detect sxl to set bit width for RV32 in RV64

2024-07-09 Thread LIU Zhiwei
From: TANG Tiancheng 

Ensure correct bit width based on sxl when running RV32 on RV64 QEMU.
This is required as MMU address translations run in S-mode.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu_helper.c | 17 -
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 6709622dd3..4f0ab90ac7 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -887,12 +887,14 @@ static int get_physical_address(CPURISCVState *env, 
hwaddr *physical,
 
 CPUState *cs = env_cpu(env);
 int va_bits = PGSHIFT + levels * ptidxbits + widened;
+int sxlen = 16 << riscv_cpu_sxl(env);
+int sxlen_bytes = sxlen / 8;
 
 if (first_stage == true) {
 target_ulong mask, masked_msbs;
 
-if (TARGET_LONG_BITS > (va_bits - 1)) {
-mask = (1L << (TARGET_LONG_BITS - (va_bits - 1))) - 1;
+if (sxlen > (va_bits - 1)) {
+mask = (1L << (sxlen - (va_bits - 1))) - 1;
 } else {
 mask = 0;
 }
@@ -961,7 +963,7 @@ restart:
 
 int pmp_prot;
 int pmp_ret = get_physical_address_pmp(env, _prot, pte_addr,
-   sizeof(target_ulong),
+   sxlen_bytes,
MMU_DATA_LOAD, PRV_S);
 if (pmp_ret != TRANSLATE_SUCCESS) {
 return TRANSLATE_PMP_FAIL;
@@ -1113,7 +1115,7 @@ restart:
  *   it is no longer valid and we must re-walk the page table.
  */
 MemoryRegion *mr;
-hwaddr l = sizeof(target_ulong), addr1;
+hwaddr l = sxlen_bytes, addr1;
 mr = address_space_translate(cs->as, pte_addr, , ,
  false, MEMTXATTRS_UNSPECIFIED);
 if (memory_region_is_ram(mr)) {
@@ -1125,7 +1127,12 @@ restart:
  */
 *pte_pa = pte = updated_pte;
 #else
-target_ulong old_pte = qatomic_cmpxchg(pte_pa, pte, updated_pte);
+target_ulong old_pte;
+if (riscv_cpu_sxl(env) == MXL_RV32) {
+old_pte = qatomic_cmpxchg((uint32_t *)pte_pa, pte, 
updated_pte);
+} else {
+old_pte = qatomic_cmpxchg(pte_pa, pte, updated_pte);
+}
 if (old_pte != pte) {
 goto restart;
 }
-- 
2.25.1




[PATCH v5 3/7] target/riscv: Correct SXL return value for RV32 in RV64 QEMU

2024-07-09 Thread LIU Zhiwei
From: TANG Tiancheng 

Ensure that riscv_cpu_sxl returns MXL_RV32 when runningRV32 in an
RV64 QEMU.

Signed-off-by: TANG Tiancheng 
Fixes: 05e6ca5e156 ("target/riscv: Ignore reserved bits in PTE for RV64")
Reviewed-by: Liu Zhiwei 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.h | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 87742047ce..49de81be7e 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -693,8 +693,11 @@ static inline RISCVMXL riscv_cpu_sxl(CPURISCVState *env)
 #ifdef CONFIG_USER_ONLY
 return env->misa_mxl;
 #else
-return get_field(env->mstatus, MSTATUS64_SXL);
+if (env->misa_mxl != MXL_RV32) {
+return get_field(env->mstatus, MSTATUS64_SXL);
+}
 #endif
+return MXL_RV32;
 }
 #endif
 
-- 
2.25.1




[PATCH v5 2/7] target/riscv: Adjust PMP size for no-MMU RV64 QEMU running RV32

2024-07-09 Thread LIU Zhiwei
From: TANG Tiancheng 

Ensure pmp_size is correctly determined using mxl for RV32
in RV64 QEMU.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
Reviewed-by: Alistair Francis 
---
 target/riscv/pmp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
index 9eea397e72..5e74b7220f 100644
--- a/target/riscv/pmp.c
+++ b/target/riscv/pmp.c
@@ -326,7 +326,7 @@ bool pmp_hart_has_privs(CPURISCVState *env, hwaddr addr,
  */
 pmp_size = -(addr | TARGET_PAGE_MASK);
 } else {
-pmp_size = sizeof(target_ulong);
+pmp_size = 2 << riscv_cpu_mxl(env);
 }
 } else {
 pmp_size = size;
-- 
2.25.1




[PATCH v5 1/7] target/riscv: Add fw_dynamic_info32 for booting RV32 OpenSBI

2024-07-09 Thread LIU Zhiwei
From: TANG Tiancheng 

RV32 OpenSBI need a fw_dynamic_info parameter with 32-bit fields instead
of target_ulong.

In RV64 QEMU, target_ulong is 64. So it is not right for booting RV32 OpenSBI.
We create a fw_dynmaic_info32 struct for this purpose.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
Reviewed-by: Alistair Francis 
---
 hw/riscv/boot.c | 35 ++---
 hw/riscv/sifive_u.c |  3 ++-
 include/hw/riscv/boot.h |  4 +++-
 include/hw/riscv/boot_opensbi.h | 29 +++
 4 files changed, 57 insertions(+), 14 deletions(-)

diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
index 47281ca853..1a2c1ff9e0 100644
--- a/hw/riscv/boot.c
+++ b/hw/riscv/boot.c
@@ -342,27 +342,33 @@ void riscv_load_fdt(hwaddr fdt_addr, void *fdt)
 rom_ptr_for_as(_space_memory, fdt_addr, 
fdtsize));
 }
 
-void riscv_rom_copy_firmware_info(MachineState *machine, hwaddr rom_base,
-  hwaddr rom_size, uint32_t reset_vec_size,
+void riscv_rom_copy_firmware_info(MachineState *machine,
+  RISCVHartArrayState *harts,
+  hwaddr rom_base, hwaddr rom_size,
+  uint32_t reset_vec_size,
   uint64_t kernel_entry)
 {
+struct fw_dynamic_info32 dinfo32;
 struct fw_dynamic_info dinfo;
 size_t dinfo_len;
 
-if (sizeof(dinfo.magic) == 4) {
-dinfo.magic = cpu_to_le32(FW_DYNAMIC_INFO_MAGIC_VALUE);
-dinfo.version = cpu_to_le32(FW_DYNAMIC_INFO_VERSION);
-dinfo.next_mode = cpu_to_le32(FW_DYNAMIC_INFO_NEXT_MODE_S);
-dinfo.next_addr = cpu_to_le32(kernel_entry);
+if (riscv_is_32bit(harts)) {
+dinfo32.magic = cpu_to_le32(FW_DYNAMIC_INFO_MAGIC_VALUE);
+dinfo32.version = cpu_to_le32(FW_DYNAMIC_INFO_VERSION);
+dinfo32.next_mode = cpu_to_le32(FW_DYNAMIC_INFO_NEXT_MODE_S);
+dinfo32.next_addr = cpu_to_le32(kernel_entry);
+dinfo32.options = 0;
+dinfo32.boot_hart = 0;
+dinfo_len = sizeof(dinfo32);
 } else {
 dinfo.magic = cpu_to_le64(FW_DYNAMIC_INFO_MAGIC_VALUE);
 dinfo.version = cpu_to_le64(FW_DYNAMIC_INFO_VERSION);
 dinfo.next_mode = cpu_to_le64(FW_DYNAMIC_INFO_NEXT_MODE_S);
 dinfo.next_addr = cpu_to_le64(kernel_entry);
+dinfo.options = 0;
+dinfo.boot_hart = 0;
+dinfo_len = sizeof(dinfo);
 }
-dinfo.options = 0;
-dinfo.boot_hart = 0;
-dinfo_len = sizeof(dinfo);
 
 /**
  * copy the dynamic firmware info. This information is specific to
@@ -374,7 +380,10 @@ void riscv_rom_copy_firmware_info(MachineState *machine, 
hwaddr rom_base,
 exit(1);
 }
 
-rom_add_blob_fixed_as("mrom.finfo", , dinfo_len,
+rom_add_blob_fixed_as("mrom.finfo",
+   riscv_is_32bit(harts) ?
+   (void *) : (void *),
+   dinfo_len,
rom_base + reset_vec_size,
_space_memory);
 }
@@ -430,7 +439,9 @@ void riscv_setup_rom_reset_vec(MachineState *machine, 
RISCVHartArrayState *harts
 }
 rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
   rom_base, _space_memory);
-riscv_rom_copy_firmware_info(machine, rom_base, rom_size, 
sizeof(reset_vec),
+riscv_rom_copy_firmware_info(machine, harts,
+ rom_base, rom_size,
+ sizeof(reset_vec),
  kernel_entry);
 }
 
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index af5f923f54..5010c3eadb 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -646,7 +646,8 @@ static void sifive_u_machine_init(MachineState *machine)
 rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
   memmap[SIFIVE_U_DEV_MROM].base, 
_space_memory);
 
-riscv_rom_copy_firmware_info(machine, memmap[SIFIVE_U_DEV_MROM].base,
+riscv_rom_copy_firmware_info(machine, >soc.u_cpus,
+ memmap[SIFIVE_U_DEV_MROM].base,
  memmap[SIFIVE_U_DEV_MROM].size,
  sizeof(reset_vec), kernel_entry);
 
diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
index a2e4ae9cb0..806256d23f 100644
--- a/include/hw/riscv/boot.h
+++ b/include/hw/riscv/boot.h
@@ -56,7 +56,9 @@ void riscv_setup_rom_reset_vec(MachineState *machine, 
RISCVHartArrayState *harts
hwaddr rom_base, hwaddr rom_size,
uint64_t kernel_entry,
uint64_t fdt_load_addr);
-void riscv_rom_copy_firmware_info(MachineState *machine, hwaddr rom_base,
+void riscv_rom_copy_firmware_info(MachineState *machine,
+ 

[PATCH v5 0/7] target/riscv: Expose RV32 cpu to RV64 QEMU

2024-07-09 Thread LIU Zhiwei
From: 甲一 

This patch set aims to expose 32-bit RISC-V cpu to RV64 QEMU. Thus
qemu-system-riscv64 can directly boot a RV32 Linux.

This patch set has been tested with 6.9.0 Linux Image.
And add an avocado test in tests/avocado.

# make check-avocado 
AVOCADO_TESTS=/home/jenkins/git/qemu/tests/avocado/boot_linux_console.py:BootLinuxConsole.test_riscv64_virt_rv32i
  VENVPIP install -e /home/jenkins/git/qemu/python/
/home/jenkins/git/qemu/build/pyvenv/bin/python3 -B 
/home/jenkins/git/qemu/python/scripts/mkvenv.py ensuregroup  --online 
/home/jenkins/git/qemu/pythondeps.toml avocado
mkvenv: checking for avocado-framework(>=88.1, <93.0)
mkvenv: checking for pycdlib>=1.11.0
mkvenv: installing avocado-framework==88.1, pycdlib>=1.11.0
  AVOCADO tests/avocado
Fetching asset from 
/home/jenkins/git/qemu/tests/avocado/boot_linux_console.py:BootLinuxConsole.test_riscv64_virt_rv32i
Fetching asset from 
/home/jenkins/git/qemu/tests/avocado/boot_linux_console.py:BootLinuxConsole.test_riscv64_virt_rv32i
JOB ID : 8c2e1ff918d3111d078a52eba9956893afaf9e1d
JOB LOG: 
/home/jenkins/git/qemu/build/tests/results/job-2024-07-10T09.55-8c2e1ff/job.log
 (1/1) 
/home/jenkins/git/qemu/tests/avocado/boot_linux_console.py:BootLinuxConsole.test_riscv64_virt_rv32i:
 PASS (17.50 s)
RESULTS: PASS 1 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0
JOB TIME   : 29.50 s

v5:
  Rebase to master and add tags  

v4:
  Drop UL completely in PATCH v3 2/7, 4/7, 5/7.
  Avocado: Add "if=none" to "-drive" option in QEMU command line

v3:
  Rebase to the master branch

v2:
  Remove the line that was inadvertently left in PATCH v1 4/6.
  Add an avocado test.

v1:
  https://mail.gnu.org/archive/html/qemu-riscv/2024-06/msg00501.html

TANG Tiancheng (7):
  target/riscv: Add fw_dynamic_info32 for booting RV32 OpenSBI
  target/riscv: Adjust PMP size for no-MMU RV64 QEMU running RV32
  target/riscv: Correct SXL return value for RV32 in RV64 QEMU
  target/riscv: Detect sxl to set bit width for RV32 in RV64
  target/riscv: Correct mcause/scause bit width for RV32 in RV64 QEMU
  target/riscv: Enable RV32 CPU support in RV64 QEMU
  tests/avocado: Add an avocado test for riscv64

 configs/targets/riscv64-softmmu.mak |  2 +-
 hw/riscv/boot.c | 35 +-
 hw/riscv/sifive_u.c |  3 ++-
 include/hw/riscv/boot.h |  4 ++-
 include/hw/riscv/boot_opensbi.h | 29 ++
 target/riscv/cpu.c  | 17 ++---
 target/riscv/cpu.h  |  5 +++-
 target/riscv/cpu_helper.c   | 25 +--
 target/riscv/pmp.c  |  2 +-
 tests/avocado/boot_linux_console.py | 38 +
 10 files changed, 132 insertions(+), 28 deletions(-)

-- 
2.25.1




Re: [PATCH v4 7/7] tests/avocado: Add an avocado test for riscv64

2024-07-09 Thread LIU Zhiwei



On 2024/7/10 9:31, Alistair Francis wrote:

On Mon, Jul 8, 2024 at 11:22 PM LIU Zhiwei  wrote:

From: TANG Tiancheng 

To regularly test booting Linux with rv32 on QEMU RV64,
we have added a test to boot_linux_console.py to retrieve
cpuinfo and verify if it shows 'rv32' when using RV64 to
boot rv32 CPUs.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
Acked-by: Alistair Francis 
Reviewed-by: Alistair Francis 

Something is wrong here, it should only be an Ack


Sorry, I missed checking this. Will fix it in next version.

Zhiwei



Alistair




[PATCH v4 11/11] disas/riscv: Support zabha disassemble

2024-07-09 Thread LIU Zhiwei
Signed-off-by: LIU Zhiwei 
Acked-by: Alistair Francis 
---
 disas/riscv.c | 60 +++
 1 file changed, 60 insertions(+)

diff --git a/disas/riscv.c b/disas/riscv.c
index d29cb1ff7d..c8364c2b07 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -954,6 +954,26 @@ typedef enum {
 rv_c_mop_11= 923,
 rv_c_mop_13= 924,
 rv_c_mop_15= 925,
+rv_op_amoswap_b = 926,
+rv_op_amoadd_b  = 927,
+rv_op_amoxor_b  = 928,
+rv_op_amoor_b   = 929,
+rv_op_amoand_b  = 930,
+rv_op_amomin_b  = 931,
+rv_op_amomax_b  = 932,
+rv_op_amominu_b = 933,
+rv_op_amomaxu_b = 934,
+rv_op_amoswap_h = 935,
+rv_op_amoadd_h  = 936,
+rv_op_amoxor_h  = 937,
+rv_op_amoor_h   = 938,
+rv_op_amoand_h  = 939,
+rv_op_amomin_h  = 940,
+rv_op_amomax_h  = 941,
+rv_op_amominu_h = 942,
+rv_op_amomaxu_h = 943,
+rv_op_amocas_b  = 944,
+rv_op_amocas_h  = 945,
 } rv_op;
 
 /* register names */
@@ -2192,6 +2212,26 @@ const rv_opcode_data rvi_opcode_data[] = {
 { "c.mop.11", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
 { "c.mop.13", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
 { "c.mop.15", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "amoswap.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoadd.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoxor.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoor.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoand.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amomin.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amomax.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amominu.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amomaxu.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoswap.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoadd.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoxor.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoor.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoand.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amomin.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amomax.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amominu.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amomaxu.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amocas.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amocas.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
 };
 
 /* CSR names */
@@ -2986,9 +3026,13 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa 
isa)
 case 11:
 switch (((inst >> 24) & 0b1000) |
 ((inst >> 12) & 0b0111)) {
+case 0: op = rv_op_amoadd_b; break;
+case 1: op = rv_op_amoadd_h; break;
 case 2: op = rv_op_amoadd_w; break;
 case 3: op = rv_op_amoadd_d; break;
 case 4: op = rv_op_amoadd_q; break;
+case 8: op = rv_op_amoswap_b; break;
+case 9: op = rv_op_amoswap_h; break;
 case 10: op = rv_op_amoswap_w; break;
 case 11: op = rv_op_amoswap_d; break;
 case 12: op = rv_op_amoswap_q; break;
@@ -3010,27 +3054,43 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa 
isa)
 case 26: op = rv_op_sc_w; break;
 case 27: op = rv_op_sc_d; break;
 case 28: op = rv_op_sc_q; break;
+case 32: op = rv_op_amoxor_b; break;
+case 33: op = rv_op_amoxor_h; break;
 case 34: op = rv_op_amoxor_w; break;
 case 35: op = rv_op_amoxor_d; break;
 case 36: op = rv_op_amoxor_q; break;
+case 40: op = rv_op_amocas_b; break;
+case 41: op = rv_op_amocas_h; break;
 case 42: op = rv_op_amocas_w; break;
 case 43: op = rv_op_amocas_d; break;
 case 44: op = rv_op_amocas_q; break;
+case 64: op = rv_op_amoor_b; break;
+case 65: op = rv_op_amoor_h; break;
 case 66: op = rv_op_amoor_w; break;
 case 67: op = rv_op_amoor_d; break;
 case 68: op = rv_op_amoor_q; break;
+case 96: op = rv_op_amoand_b; break;
+case 97: op = rv_op_amoand_h; break;
 case 98: op = rv_op_amoand_w; break;
 case 99: op = rv_op_amoand_d; break;
 case 100: op = rv_op_amoand_q; break;
+case 128: op = rv_op_amomin_b; break;
+  

[PATCH v4 10/11] target/riscv: Expose zabha extension as a cpu property

2024-07-09 Thread LIU Zhiwei
Signed-off-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 5219b44176..8cd52e6801 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -117,6 +117,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
 ISA_EXT_DATA_ENTRY(zmmul, PRIV_VERSION_1_12_0, ext_zmmul),
 ISA_EXT_DATA_ENTRY(za64rs, PRIV_VERSION_1_12_0, has_priv_1_11),
 ISA_EXT_DATA_ENTRY(zaamo, PRIV_VERSION_1_12_0, ext_zaamo),
+ISA_EXT_DATA_ENTRY(zabha, PRIV_VERSION_1_13_0, ext_zabha),
 ISA_EXT_DATA_ENTRY(zacas, PRIV_VERSION_1_12_0, ext_zacas),
 ISA_EXT_DATA_ENTRY(zama16b, PRIV_VERSION_1_13_0, ext_zama16b),
 ISA_EXT_DATA_ENTRY(zalrsc, PRIV_VERSION_1_12_0, ext_zalrsc),
@@ -1478,6 +1479,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
 MULTI_EXT_CFG_BOOL("zcmop", ext_zcmop, false),
 MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false),
 MULTI_EXT_CFG_BOOL("zama16b", ext_zama16b, false),
+MULTI_EXT_CFG_BOOL("zabha", ext_zabha, false),
 MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false),
 MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false),
 MULTI_EXT_CFG_BOOL("zawrs", ext_zawrs, true),
-- 
2.25.1




[PATCH v4 09/11] target/riscv: Add amocas.[b|h] for Zabha

2024-07-09 Thread LIU Zhiwei
Signed-off-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
---
 target/riscv/insn32.decode  |  2 ++
 target/riscv/insn_trans/trans_rvzabha.c.inc | 14 ++
 2 files changed, 16 insertions(+)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 3bad6372f2..c45b8fa1d8 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -1041,3 +1041,5 @@ amomin_h   1 . . . . 001 . 010 
@atom_st
 amomax_h   10100 . . . . 001 . 010 @atom_st
 amominu_h  11000 . . . . 001 . 010 @atom_st
 amomaxu_h  11100 . . . . 001 . 010 @atom_st
+amocas_b00101 . . . . 000 . 010 @atom_st
+amocas_h00101 . . . . 001 . 010 @atom_st
diff --git a/target/riscv/insn_trans/trans_rvzabha.c.inc 
b/target/riscv/insn_trans/trans_rvzabha.c.inc
index 9093a1cfc1..ce8edcba62 100644
--- a/target/riscv/insn_trans/trans_rvzabha.c.inc
+++ b/target/riscv/insn_trans/trans_rvzabha.c.inc
@@ -129,3 +129,17 @@ static bool trans_amomaxu_h(DisasContext *ctx, 
arg_amomaxu_h *a)
 REQUIRE_ZABHA(ctx);
 return gen_amo(ctx, a, _gen_atomic_fetch_umax_tl, MO_TESW);
 }
+
+static bool trans_amocas_b(DisasContext *ctx, arg_amocas_b *a)
+{
+REQUIRE_ZACAS(ctx);
+REQUIRE_ZABHA(ctx);
+return gen_cmpxchg(ctx, a, MO_SB);
+}
+
+static bool trans_amocas_h(DisasContext *ctx, arg_amocas_h *a)
+{
+REQUIRE_ZACAS(ctx);
+REQUIRE_ZABHA(ctx);
+return gen_cmpxchg(ctx, a, MO_ALIGN | MO_TESW);
+}
-- 
2.25.1




[PATCH v4 08/11] target/riscv: Move gen_cmpxchg before adding amocas.[b|h]

2024-07-09 Thread LIU Zhiwei
Signed-off-by: LIU Zhiwei 
Acked-by: Alistair Francis 
---
 target/riscv/insn_trans/trans_rvzacas.c.inc | 13 -
 target/riscv/translate.c| 13 +
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rvzacas.c.inc 
b/target/riscv/insn_trans/trans_rvzacas.c.inc
index 5d274d4c08..fcced99fc7 100644
--- a/target/riscv/insn_trans/trans_rvzacas.c.inc
+++ b/target/riscv/insn_trans/trans_rvzacas.c.inc
@@ -22,19 +22,6 @@
 } \
 } while (0)
 
-static bool gen_cmpxchg(DisasContext *ctx, arg_atomic *a, MemOp mop)
-{
-TCGv dest = get_gpr(ctx, a->rd, EXT_NONE);
-TCGv src1 = get_address(ctx, a->rs1, 0);
-TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
-
-decode_save_opc(ctx);
-tcg_gen_atomic_cmpxchg_tl(dest, src1, dest, src2, ctx->mem_idx, mop);
-
-gen_set_gpr(ctx, a->rd, dest);
-return true;
-}
-
 static bool trans_amocas_w(DisasContext *ctx, arg_amocas_w *a)
 {
 REQUIRE_ZACAS(ctx);
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 4a3e786560..acba90f170 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -1099,6 +1099,19 @@ static bool gen_amo(DisasContext *ctx, arg_atomic *a,
 return true;
 }
 
+static bool gen_cmpxchg(DisasContext *ctx, arg_atomic *a, MemOp mop)
+{
+TCGv dest = get_gpr(ctx, a->rd, EXT_NONE);
+TCGv src1 = get_address(ctx, a->rs1, 0);
+TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
+
+decode_save_opc(ctx);
+tcg_gen_atomic_cmpxchg_tl(dest, src1, dest, src2, ctx->mem_idx, mop);
+
+gen_set_gpr(ctx, a->rd, dest);
+return true;
+}
+
 static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
 {
 DisasContext *ctx = container_of(dcbase, DisasContext, base);
-- 
2.25.1




[PATCH v4 07/11] target/riscv: Add AMO instructions for Zabha

2024-07-09 Thread LIU Zhiwei
Signed-off-by: LIU Zhiwei 
Acked-by: Alistair Francis 
---
 target/riscv/cpu_cfg.h  |   1 +
 target/riscv/insn32.decode  |  20 +++
 target/riscv/insn_trans/trans_rvzabha.c.inc | 131 
 target/riscv/translate.c|   4 +-
 4 files changed, 155 insertions(+), 1 deletion(-)
 create mode 100644 target/riscv/insn_trans/trans_rvzabha.c.inc

diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index ddbfae37e5..120905a254 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -84,6 +84,7 @@ struct RISCVCPUConfig {
 bool ext_zaamo;
 bool ext_zacas;
 bool ext_zama16b;
+bool ext_zabha;
 bool ext_zalrsc;
 bool ext_zawrs;
 bool ext_zfa;
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 60da673153..3bad6372f2 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -1021,3 +1021,23 @@ amocas_q00101 . . . . 100 . 010 
@atom_st
 # *** Zimop may-be-operation extension ***
 mop_r_n 1 . 00 .. 0111 .. . 100 . 1110011 @mop5
 mop_rr_n1 . 00 .. 1 . . 100 . 1110011 @mop3
+
+# *** Zabhb Standard Extension ***
+amoswap_b  1 . . . . 000 . 010 @atom_st
+amoadd_b   0 . . . . 000 . 010 @atom_st
+amoxor_b   00100 . . . . 000 . 010 @atom_st
+amoand_b   01100 . . . . 000 . 010 @atom_st
+amoor_b01000 . . . . 000 . 010 @atom_st
+amomin_b   1 . . . . 000 . 010 @atom_st
+amomax_b   10100 . . . . 000 . 010 @atom_st
+amominu_b  11000 . . . . 000 . 010 @atom_st
+amomaxu_b  11100 . . . . 000 . 010 @atom_st
+amoswap_h  1 . . . . 001 . 010 @atom_st
+amoadd_h   0 . . . . 001 . 010 @atom_st
+amoxor_h   00100 . . . . 001 . 010 @atom_st
+amoand_h   01100 . . . . 001 . 010 @atom_st
+amoor_h01000 . . . . 001 . 010 @atom_st
+amomin_h   1 . . . . 001 . 010 @atom_st
+amomax_h   10100 . . . . 001 . 010 @atom_st
+amominu_h  11000 . . . . 001 . 010 @atom_st
+amomaxu_h  11100 . . . . 001 . 010 @atom_st
diff --git a/target/riscv/insn_trans/trans_rvzabha.c.inc 
b/target/riscv/insn_trans/trans_rvzabha.c.inc
new file mode 100644
index 00..9093a1cfc1
--- /dev/null
+++ b/target/riscv/insn_trans/trans_rvzabha.c.inc
@@ -0,0 +1,131 @@
+/*
+ * RISC-V translation routines for the Zabha Standard Extension.
+ *
+ * Copyright (c) 2024 Alibaba Group
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define REQUIRE_ZABHA(ctx) do {   \
+if (!ctx->cfg_ptr->ext_zabha) {   \
+return false; \
+} \
+} while (0)
+
+static bool trans_amoswap_b(DisasContext *ctx, arg_amoswap_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_xchg_tl, MO_SB);
+}
+
+static bool trans_amoadd_b(DisasContext *ctx, arg_amoadd_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_fetch_add_tl, MO_SB);
+}
+
+static bool trans_amoxor_b(DisasContext *ctx, arg_amoxor_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_fetch_xor_tl, MO_SB);
+}
+
+static bool trans_amoand_b(DisasContext *ctx, arg_amoand_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_fetch_and_tl, MO_SB);
+}
+
+static bool trans_amoor_b(DisasContext *ctx, arg_amoor_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_fetch_or_tl, MO_SB);
+}
+
+static bool trans_amomin_b(DisasContext *ctx, arg_amomin_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_fetch_smin_tl, MO_SB);
+}
+
+static bool trans_amomax_b(DisasContext *ctx, arg_amomax_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_fetch_smax_tl, MO_SB);
+}
+
+static bool trans_amominu_b(DisasContext *ctx, arg_amominu_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_fetch_umin_tl, MO_SB);
+}
+
+static bool trans_amomaxu_b(DisasContext *ctx, arg_amomaxu_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_fetch_umax_tl, MO_SB);
+}
+
+static bool trans_amoswap_h(DisasContext *ctx, arg_amoswap_h *a)
+{
+R

[PATCH v4 06/11] target/riscv: Move gen_amo before implement Zabha

2024-07-09 Thread LIU Zhiwei
Signed-off-by: LIU Zhiwei 
Acked-by: Alistair Francis 
---
 target/riscv/insn_trans/trans_rva.c.inc | 21 -
 target/riscv/translate.c| 21 +
 2 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rva.c.inc 
b/target/riscv/insn_trans/trans_rva.c.inc
index eb080baddd..39bbf60f3c 100644
--- a/target/riscv/insn_trans/trans_rva.c.inc
+++ b/target/riscv/insn_trans/trans_rva.c.inc
@@ -96,27 +96,6 @@ static bool gen_sc(DisasContext *ctx, arg_atomic *a, MemOp 
mop)
 return true;
 }
 
-static bool gen_amo(DisasContext *ctx, arg_atomic *a,
-void(*func)(TCGv, TCGv, TCGv, TCGArg, MemOp),
-MemOp mop)
-{
-TCGv dest = dest_gpr(ctx, a->rd);
-TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE);
-
-if (ctx->cfg_ptr->ext_zama16b) {
-mop |= MO_ATOM_WITHIN16;
-} else {
-mop |= MO_ALIGN;
-}
-
-decode_save_opc(ctx);
-src1 = get_address(ctx, a->rs1, 0);
-func(dest, src1, src2, ctx->mem_idx, mop);
-
-gen_set_gpr(ctx, a->rd, dest);
-return true;
-}
-
 static bool trans_lr_w(DisasContext *ctx, arg_lr_w *a)
 {
 REQUIRE_A_OR_ZALRSC(ctx);
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 8a546f4ece..133550d6e2 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -1077,6 +1077,27 @@ static bool gen_unary_per_ol(DisasContext *ctx, arg_r2 
*a, DisasExtend ext,
 return gen_unary(ctx, a, ext, f_tl);
 }
 
+static bool gen_amo(DisasContext *ctx, arg_atomic *a,
+void(*func)(TCGv, TCGv, TCGv, TCGArg, MemOp),
+MemOp mop)
+{
+TCGv dest = dest_gpr(ctx, a->rd);
+TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE);
+
+if (ctx->cfg_ptr->ext_zama16b) {
+mop |= MO_ATOM_WITHIN16;
+} else {
+mop |= MO_ALIGN;
+}
+
+decode_save_opc(ctx);
+src1 = get_address(ctx, a->rs1, 0);
+func(dest, src1, src2, ctx->mem_idx, mop);
+
+gen_set_gpr(ctx, a->rd, dest);
+return true;
+}
+
 static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
 {
 DisasContext *ctx = container_of(dcbase, DisasContext, base);
-- 
2.25.1




[PATCH v4 05/11] target/riscv: Support Zama16b extension

2024-07-09 Thread LIU Zhiwei
Zama16b is the property that misaligned load/stores/atomics within
a naturally aligned 16-byte region are atomic.

According to the specification, Zama16b applies only to AMOs, loads
and stores defined in the base ISAs, and loads and stores of no more
than XLEN bits defined in the F, D, and Q extensions. Thus it should
not apply to zacas or RVC instructions.

For an instruction in that set, if all accessed bytes lie within 16B granule,
the instruction will not raise an exception for reasons of address alignment,
and the instruction will give rise to only one memory operation for the
purposes of RVWMO—i.e., it will execute atomically.

Signed-off-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.c  |  2 ++
 target/riscv/cpu_cfg.h  |  1 +
 target/riscv/insn_trans/trans_rva.c.inc | 42 ++---
 target/riscv/insn_trans/trans_rvd.c.inc | 14 +++--
 target/riscv/insn_trans/trans_rvf.c.inc | 14 +++--
 target/riscv/insn_trans/trans_rvi.c.inc |  6 
 6 files changed, 57 insertions(+), 22 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 1d1402775a..5219b44176 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -118,6 +118,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
 ISA_EXT_DATA_ENTRY(za64rs, PRIV_VERSION_1_12_0, has_priv_1_11),
 ISA_EXT_DATA_ENTRY(zaamo, PRIV_VERSION_1_12_0, ext_zaamo),
 ISA_EXT_DATA_ENTRY(zacas, PRIV_VERSION_1_12_0, ext_zacas),
+ISA_EXT_DATA_ENTRY(zama16b, PRIV_VERSION_1_13_0, ext_zama16b),
 ISA_EXT_DATA_ENTRY(zalrsc, PRIV_VERSION_1_12_0, ext_zalrsc),
 ISA_EXT_DATA_ENTRY(zawrs, PRIV_VERSION_1_12_0, ext_zawrs),
 ISA_EXT_DATA_ENTRY(zfa, PRIV_VERSION_1_12_0, ext_zfa),
@@ -1476,6 +1477,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
 MULTI_EXT_CFG_BOOL("zimop", ext_zimop, false),
 MULTI_EXT_CFG_BOOL("zcmop", ext_zcmop, false),
 MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false),
+MULTI_EXT_CFG_BOOL("zama16b", ext_zama16b, false),
 MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false),
 MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false),
 MULTI_EXT_CFG_BOOL("zawrs", ext_zawrs, true),
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index d85e54b475..ddbfae37e5 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -83,6 +83,7 @@ struct RISCVCPUConfig {
 bool ext_zdinx;
 bool ext_zaamo;
 bool ext_zacas;
+bool ext_zama16b;
 bool ext_zalrsc;
 bool ext_zawrs;
 bool ext_zfa;
diff --git a/target/riscv/insn_trans/trans_rva.c.inc 
b/target/riscv/insn_trans/trans_rva.c.inc
index 4a9e4591d1..eb080baddd 100644
--- a/target/riscv/insn_trans/trans_rva.c.inc
+++ b/target/riscv/insn_trans/trans_rva.c.inc
@@ -103,6 +103,12 @@ static bool gen_amo(DisasContext *ctx, arg_atomic *a,
 TCGv dest = dest_gpr(ctx, a->rd);
 TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE);
 
+if (ctx->cfg_ptr->ext_zama16b) {
+mop |= MO_ATOM_WITHIN16;
+} else {
+mop |= MO_ALIGN;
+}
+
 decode_save_opc(ctx);
 src1 = get_address(ctx, a->rs1, 0);
 func(dest, src1, src2, ctx->mem_idx, mop);
@@ -126,55 +132,55 @@ static bool trans_sc_w(DisasContext *ctx, arg_sc_w *a)
 static bool trans_amoswap_w(DisasContext *ctx, arg_amoswap_w *a)
 {
 REQUIRE_A_OR_ZAAMO(ctx);
-return gen_amo(ctx, a, _gen_atomic_xchg_tl, (MO_ALIGN | MO_TESL));
+return gen_amo(ctx, a, _gen_atomic_xchg_tl, MO_TESL);
 }
 
 static bool trans_amoadd_w(DisasContext *ctx, arg_amoadd_w *a)
 {
 REQUIRE_A_OR_ZAAMO(ctx);
-return gen_amo(ctx, a, _gen_atomic_fetch_add_tl, (MO_ALIGN | MO_TESL));
+return gen_amo(ctx, a, _gen_atomic_fetch_add_tl, MO_TESL);
 }
 
 static bool trans_amoxor_w(DisasContext *ctx, arg_amoxor_w *a)
 {
 REQUIRE_A_OR_ZAAMO(ctx);
-return gen_amo(ctx, a, _gen_atomic_fetch_xor_tl, (MO_ALIGN | MO_TESL));
+return gen_amo(ctx, a, _gen_atomic_fetch_xor_tl, MO_TESL);
 }
 
 static bool trans_amoand_w(DisasContext *ctx, arg_amoand_w *a)
 {
 REQUIRE_A_OR_ZAAMO(ctx);
-return gen_amo(ctx, a, _gen_atomic_fetch_and_tl, (MO_ALIGN | MO_TESL));
+return gen_amo(ctx, a, _gen_atomic_fetch_and_tl, MO_TESL);
 }
 
 static bool trans_amoor_w(DisasContext *ctx, arg_amoor_w *a)
 {
 REQUIRE_A_OR_ZAAMO(ctx);
-return gen_amo(ctx, a, _gen_atomic_fetch_or_tl, (MO_ALIGN | MO_TESL));
+return gen_amo(ctx, a, _gen_atomic_fetch_or_tl, MO_TESL);
 }
 
 static bool trans_amomin_w(DisasContext *ctx, arg_amomin_w *a)
 {
 REQUIRE_A_OR_ZAAMO(ctx);
-return gen_amo(ctx, a, _gen_atomic_fetch_smin_tl, (MO_ALIGN | 
MO_TESL));
+return gen_amo(ctx, a, _gen_atomic_fetch_smin_tl, MO_TESL);
 }
 
 static bool trans_amomax_w(DisasContext *ctx, arg_amomax_w *a)
 {
 REQUIRE_A_OR_ZAAMO(ctx);
-return gen_amo(ctx, a, _gen_atomic_fetch_smax_tl, (MO_ALIGN | 
MO_TESL));
+return gen_amo(ctx, a, 

[PATCH v4 04/11] disas/riscv: Support zcmop disassemble

2024-07-09 Thread LIU Zhiwei
Although in QEMU disassemble, we usually lift compressed instruction
to an normal format when display the instruction name. For C.MOP.n,
it is more reasonable to directly display its compressed name, because
its behavior can be redefined by later extension.

Signed-off-by: LIU Zhiwei 
Acked-by: Alistair Francis 
Reviewed-by: Deepak Gupta 
---
 disas/riscv.c | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/disas/riscv.c b/disas/riscv.c
index 0b82ab2322..d29cb1ff7d 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -946,6 +946,14 @@ typedef enum {
 rv_mop_rr_5= 915,
 rv_mop_rr_6= 916,
 rv_mop_rr_7= 917,
+rv_c_mop_1 = 918,
+rv_c_mop_3 = 919,
+rv_c_mop_5 = 920,
+rv_c_mop_7 = 921,
+rv_c_mop_9 = 922,
+rv_c_mop_11= 923,
+rv_c_mop_13= 924,
+rv_c_mop_15= 925,
 } rv_op;
 
 /* register names */
@@ -2176,6 +2184,14 @@ const rv_opcode_data rvi_opcode_data[] = {
 { "mop.rr.5", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
 { "mop.rr.6", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
 { "mop.rr.7", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "c.mop.1",  rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.3",  rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.5",  rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.7",  rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.9",  rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.11", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.13", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.15", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
 };
 
 /* CSR names */
@@ -2532,6 +2548,13 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa 
isa)
 break;
 case 2: op = rv_op_c_li; break;
 case 3:
+if (dec->cfg->ext_zcmop) {
+if inst >> 2) & 0b11) == 0b10) &&
+(((inst >> 11) & 0b11) == 0b0)) {
+op = rv_c_mop_1 + ((inst >> 8) & 0b111);
+break;
+}
+}
 switch ((inst >> 7) & 0b1) {
 case 2: op = rv_op_c_addi16sp; break;
 default: op = rv_op_c_lui; break;
-- 
2.25.1




[PATCH v4 00/11] target/riscv: Support zimop/zcmop/zama16b/zabha

2024-07-09 Thread LIU Zhiwei
I once used a wrong major opcode for zimop. It should use 0x73 as major opcode.
This was detected after I got a toolchain with zimop support. Before that, I 
tested
this implementation with hardwire code instruction instead of assemble code.

This patch set has been queued to alistair/riscv-to-apply.next, but it is still 
not
merged by the master branch. I think we had better fix it before merging into 
the
master.

v3->v4:
1. Fix zimop opcode and disassemble

v2->v3:
1. Add review tags.
2. Reword the patch 10 in commit log

v1->v2:
1. Fix the isa orders.
2. Make zimop/zcmop/zama16b/zabha depend on priviledged 1.13
3. Add review tags.

The v2 patch set is here
https://mail.gnu.org/archive/html/qemu-riscv/2024-06/msg00489.html

The v1 patch set is here
1. zimop/zcmop
https://mail.gnu.org/archive/html/qemu-riscv/2024-05/msg00207.html
2. zama16b
https://mail.gnu.org/archive/html/qemu-riscv/2024-05/msg00212.html
3. zabha
https://mail.gnu.org/archive/html/qemu-riscv/2024-05/msg00214.html

LIU Zhiwei (11):
  target/riscv: Add zimop extension
  disas/riscv: Support zimop disassemble
  target/riscv: Add zcmop extension
  disas/riscv: Support zcmop disassemble
  target/riscv: Support Zama16b extension
  target/riscv: Move gen_amo before implement Zabha
  target/riscv: Add AMO instructions for Zabha
  target/riscv: Move gen_cmpxchg before adding amocas.[b|h]
  target/riscv: Add amocas.[b|h] for Zabha
  target/riscv: Expose zabha extension as a cpu property
  disas/riscv: Support zabha disassemble

 disas/riscv.c   | 181 
 target/riscv/cpu.c  |   8 +
 target/riscv/cpu_cfg.h  |   4 +
 target/riscv/insn16.decode  |   1 +
 target/riscv/insn32.decode  |  33 
 target/riscv/insn_trans/trans_rva.c.inc |  51 ++
 target/riscv/insn_trans/trans_rvd.c.inc |  14 +-
 target/riscv/insn_trans/trans_rvf.c.inc |  14 +-
 target/riscv/insn_trans/trans_rvi.c.inc |   6 +
 target/riscv/insn_trans/trans_rvzabha.c.inc | 145 
 target/riscv/insn_trans/trans_rvzacas.c.inc |  13 --
 target/riscv/insn_trans/trans_rvzcmop.c.inc |  29 
 target/riscv/insn_trans/trans_rvzimop.c.inc |  37 
 target/riscv/tcg/tcg-cpu.c  |   5 +
 target/riscv/translate.c|  38 
 15 files changed, 529 insertions(+), 50 deletions(-)
 create mode 100644 target/riscv/insn_trans/trans_rvzabha.c.inc
 create mode 100644 target/riscv/insn_trans/trans_rvzcmop.c.inc
 create mode 100644 target/riscv/insn_trans/trans_rvzimop.c.inc

-- 
2.25.1




[PATCH v4 03/11] target/riscv: Add zcmop extension

2024-07-09 Thread LIU Zhiwei
Zcmop defines eight 16-bit MOP instructions named C.MOP.n, where n is
an odd integer between 1 and 15, inclusive. C.MOP.n is encoded in
the reserved encoding space corresponding to C.LUI xn, 0.

Unlike the MOPs defined in the Zimop extension, the C.MOP.n instructions
are defined to not write any register.

In current implementation, C.MOP.n only has an check function, without any
other more behavior.

Signed-off-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
Reviewed-by: Deepak Gupta 
---
 target/riscv/cpu.c  |  2 ++
 target/riscv/cpu_cfg.h  |  1 +
 target/riscv/insn16.decode  |  1 +
 target/riscv/insn_trans/trans_rvzcmop.c.inc | 29 +
 target/riscv/tcg/tcg-cpu.c  |  5 
 target/riscv/translate.c|  1 +
 6 files changed, 39 insertions(+)
 create mode 100644 target/riscv/insn_trans/trans_rvzcmop.c.inc

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index d3853a5804..1d1402775a 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -131,6 +131,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
 ISA_EXT_DATA_ENTRY(zcf, PRIV_VERSION_1_12_0, ext_zcf),
 ISA_EXT_DATA_ENTRY(zcd, PRIV_VERSION_1_12_0, ext_zcd),
 ISA_EXT_DATA_ENTRY(zce, PRIV_VERSION_1_12_0, ext_zce),
+ISA_EXT_DATA_ENTRY(zcmop, PRIV_VERSION_1_13_0, ext_zcmop),
 ISA_EXT_DATA_ENTRY(zcmp, PRIV_VERSION_1_12_0, ext_zcmp),
 ISA_EXT_DATA_ENTRY(zcmt, PRIV_VERSION_1_12_0, ext_zcmt),
 ISA_EXT_DATA_ENTRY(zba, PRIV_VERSION_1_12_0, ext_zba),
@@ -1473,6 +1474,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
 MULTI_EXT_CFG_BOOL("zihintntl", ext_zihintntl, true),
 MULTI_EXT_CFG_BOOL("zihintpause", ext_zihintpause, true),
 MULTI_EXT_CFG_BOOL("zimop", ext_zimop, false),
+MULTI_EXT_CFG_BOOL("zcmop", ext_zcmop, false),
 MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false),
 MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false),
 MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false),
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index 9f53512053..d85e54b475 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -72,6 +72,7 @@ struct RISCVCPUConfig {
 bool ext_zihintpause;
 bool ext_zihpm;
 bool ext_zimop;
+bool ext_zcmop;
 bool ext_ztso;
 bool ext_smstateen;
 bool ext_sstc;
diff --git a/target/riscv/insn16.decode b/target/riscv/insn16.decode
index b96c534e73..3953bcf82d 100644
--- a/target/riscv/insn16.decode
+++ b/target/riscv/insn16.decode
@@ -140,6 +140,7 @@ sw110  ... ... .. ... 00 @cs_w
 addi  000 .  .  . 01 @ci
 addi  010 .  .  . 01 @c_li
 {
+  c_mop_n 011 0 0 n:3 1 0 01
   illegal 011 0  -  0 01 # c.addi16sp and c.lui, RES nzimm=0
   addi011 .  00010  . 01 @c_addi16sp
   lui 011 .  .  . 01 @c_lui
diff --git a/target/riscv/insn_trans/trans_rvzcmop.c.inc 
b/target/riscv/insn_trans/trans_rvzcmop.c.inc
new file mode 100644
index 00..7205586508
--- /dev/null
+++ b/target/riscv/insn_trans/trans_rvzcmop.c.inc
@@ -0,0 +1,29 @@
+/*
+ * RISC-V translation routines for compressed May-Be-Operation(zcmop).
+ *
+ * Copyright (c) 2024 Alibaba Group.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define REQUIRE_ZCMOP(ctx) do {   \
+if (!ctx->cfg_ptr->ext_zcmop) {   \
+return false; \
+} \
+} while (0)
+
+static bool trans_c_mop_n(DisasContext *ctx, arg_c_mop_n *a)
+{
+REQUIRE_ZCMOP(ctx);
+return true;
+}
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index ae25686824..28cc3f80a9 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -547,6 +547,11 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, 
Error **errp)
 }
 }
 
+if (cpu->cfg.ext_zcmop && !cpu->cfg.ext_zca) {
+error_setg(errp, "Zcmop extensions require Zca");
+return;
+}
+
 if (mcc->misa_mxl_max != MXL_RV32 && cpu->cfg.ext_zcf) {
 error_setg(errp, "Zcf extension is only relevant to RV32");
 return;
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 379b68289

[PATCH v4 02/11] disas/riscv: Support zimop disassemble

2024-07-09 Thread LIU Zhiwei
Signed-off-by: LIU Zhiwei 
Acked-by: Alistair Francis 
Reviewed-by: Deepak Gupta 
---
 disas/riscv.c | 98 +++
 1 file changed, 98 insertions(+)

diff --git a/disas/riscv.c b/disas/riscv.c
index 90d6b26de9..0b82ab2322 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -906,6 +906,46 @@ typedef enum {
 rv_op_amocas_w = 875,
 rv_op_amocas_d = 876,
 rv_op_amocas_q = 877,
+rv_mop_r_0 = 878,
+rv_mop_r_1 = 879,
+rv_mop_r_2 = 880,
+rv_mop_r_3 = 881,
+rv_mop_r_4 = 882,
+rv_mop_r_5 = 883,
+rv_mop_r_6 = 884,
+rv_mop_r_7 = 885,
+rv_mop_r_8 = 886,
+rv_mop_r_9 = 887,
+rv_mop_r_10= 888,
+rv_mop_r_11= 889,
+rv_mop_r_12= 890,
+rv_mop_r_13= 891,
+rv_mop_r_14= 892,
+rv_mop_r_15= 893,
+rv_mop_r_16= 894,
+rv_mop_r_17= 895,
+rv_mop_r_18= 896,
+rv_mop_r_19= 897,
+rv_mop_r_20= 898,
+rv_mop_r_21= 899,
+rv_mop_r_22= 900,
+rv_mop_r_23= 901,
+rv_mop_r_24= 902,
+rv_mop_r_25= 903,
+rv_mop_r_26= 904,
+rv_mop_r_27= 905,
+rv_mop_r_28= 906,
+rv_mop_r_29= 907,
+rv_mop_r_30= 908,
+rv_mop_r_31= 909,
+rv_mop_rr_0= 910,
+rv_mop_rr_1= 911,
+rv_mop_rr_2= 912,
+rv_mop_rr_3= 913,
+rv_mop_rr_4= 914,
+rv_mop_rr_5= 915,
+rv_mop_rr_6= 916,
+rv_mop_rr_7= 917,
 } rv_op;
 
 /* register names */
@@ -2096,6 +2136,46 @@ const rv_opcode_data rvi_opcode_data[] = {
 { "amocas.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
 { "amocas.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
 { "amocas.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "mop.r.0", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.1", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.2", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.3", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.4", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.5", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.6", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.7", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.8", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.9", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.10", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.11", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.12", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.13", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.14", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.15", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.16", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.17", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.18", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.19", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.20", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.21", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.22", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.23", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.24", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.25", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.26", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.27", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.28", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.29", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.30", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.31", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.rr.0", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.1", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.2", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.3", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.4", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.5", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.6", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.7", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
 };
 
 /* CSR names */
@@ -3855,6 +3935,24 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa 
isa)
 case 1: op = rv_op_csrrw; break;
 case 2: op = rv_op_csrrs; break;
 case 3: op = rv_op_csrrc; break;
+

[PATCH v4 01/11] target/riscv: Add zimop extension

2024-07-09 Thread LIU Zhiwei
Zimop extension defines an encoding space for 40 MOPs.The Zimop
extension defines 32 MOP instructions named MOP.R.n, where n is
an integer between 0 and 31, inclusive. The Zimop extension
additionally defines 8 MOP instructions named MOP.RR.n, where n
is an integer between 0 and 7.

These 40 MOPs initially are defined to simply write zero to x[rd],
but are designed to be redefined by later extensions to perform some
other action.

Signed-off-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
Reviewed-by: Deepak Gupta 
---
 target/riscv/cpu.c  |  2 ++
 target/riscv/cpu_cfg.h  |  1 +
 target/riscv/insn32.decode  | 11 ++
 target/riscv/insn_trans/trans_rvzimop.c.inc | 37 +
 target/riscv/translate.c|  1 +
 5 files changed, 52 insertions(+)
 create mode 100644 target/riscv/insn_trans/trans_rvzimop.c.inc

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index a2640cf259..d3853a5804 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -113,6 +113,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
 ISA_EXT_DATA_ENTRY(zihintntl, PRIV_VERSION_1_10_0, ext_zihintntl),
 ISA_EXT_DATA_ENTRY(zihintpause, PRIV_VERSION_1_10_0, ext_zihintpause),
 ISA_EXT_DATA_ENTRY(zihpm, PRIV_VERSION_1_12_0, ext_zihpm),
+ISA_EXT_DATA_ENTRY(zimop, PRIV_VERSION_1_13_0, ext_zimop),
 ISA_EXT_DATA_ENTRY(zmmul, PRIV_VERSION_1_12_0, ext_zmmul),
 ISA_EXT_DATA_ENTRY(za64rs, PRIV_VERSION_1_12_0, has_priv_1_11),
 ISA_EXT_DATA_ENTRY(zaamo, PRIV_VERSION_1_12_0, ext_zaamo),
@@ -1471,6 +1472,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
 MULTI_EXT_CFG_BOOL("zicsr", ext_zicsr, true),
 MULTI_EXT_CFG_BOOL("zihintntl", ext_zihintntl, true),
 MULTI_EXT_CFG_BOOL("zihintpause", ext_zihintpause, true),
+MULTI_EXT_CFG_BOOL("zimop", ext_zimop, false),
 MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false),
 MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false),
 MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false),
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index fb7eebde52..9f53512053 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -71,6 +71,7 @@ struct RISCVCPUConfig {
 bool ext_zihintntl;
 bool ext_zihintpause;
 bool ext_zihpm;
+bool ext_zimop;
 bool ext_ztso;
 bool ext_smstateen;
 bool ext_sstc;
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index f22df04cfd..60da673153 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -38,6 +38,8 @@
 %imm_bs   30:2   !function=ex_shift_3
 %imm_rnum 20:4
 %imm_z6   26:1 15:5
+%imm_mop5 30:1 26:2 20:2
+%imm_mop3 30:1 26:2
 
 # Argument sets:
 
@@ -56,6 +58,8 @@
 vm rd rs1 nf
  vm rd rs1 rs2 nf
 _aes shamt rs2 rs1 rd
+ imm rd rs1
+ imm rd rs1 rs2
 
 # Formats 32:
 @r   ...   . . ... . ... %rs2 %rs1 
%rd
@@ -98,6 +102,9 @@
 @k_aes   .. . . .  ... . ... _aes  shamt=%imm_bs   %rs2 
%rs1 %rd
 @i_aes   .. . . .  ... . ...   imm=%imm_rnum
%rs1 %rd
 
+@mop5 . . .. ..  .. . ... . ...  imm=%imm_mop5 %rd %rs1
+@mop3 . . .. .. . . . ... . ...  imm=%imm_mop3 %rd %rs1 
%rs2
+
 # Formats 64:
 @sh5 ...  . .  ... . ...   shamt=%sh5  %rs1 
%rd
 
@@ -1010,3 +1017,7 @@ amocas_w00101 . . . . 010 . 010 
@atom_st
 amocas_d00101 . . . . 011 . 010 @atom_st
 # *** RV64 Zacas Standard Extension ***
 amocas_q00101 . . . . 100 . 010 @atom_st
+
+# *** Zimop may-be-operation extension ***
+mop_r_n 1 . 00 .. 0111 .. . 100 . 1110011 @mop5
+mop_rr_n1 . 00 .. 1 . . 100 . 1110011 @mop3
diff --git a/target/riscv/insn_trans/trans_rvzimop.c.inc 
b/target/riscv/insn_trans/trans_rvzimop.c.inc
new file mode 100644
index 00..165aacd2b6
--- /dev/null
+++ b/target/riscv/insn_trans/trans_rvzimop.c.inc
@@ -0,0 +1,37 @@
+/*
+ * RISC-V translation routines for May-Be-Operation(zimop).
+ *
+ * Copyright (c) 2024 Alibaba Group.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define REQUIRE_ZIMOP(ctx) do {   \
+if (!ctx->cfg_ptr->ext_zimop) {   \
+return false;

[PATCH v4 7/7] tests/avocado: Add an avocado test for riscv64

2024-07-08 Thread LIU Zhiwei
From: TANG Tiancheng 

To regularly test booting Linux with rv32 on QEMU RV64,
we have added a test to boot_linux_console.py to retrieve
cpuinfo and verify if it shows 'rv32' when using RV64 to
boot rv32 CPUs.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
Acked-by: Alistair Francis 
Reviewed-by: Alistair Francis 
---
 tests/avocado/boot_linux_console.py | 37 +
 1 file changed, 37 insertions(+)

diff --git a/tests/avocado/boot_linux_console.py 
b/tests/avocado/boot_linux_console.py
index c35fc5e9ba..f333253f69 100644
--- a/tests/avocado/boot_linux_console.py
+++ b/tests/avocado/boot_linux_console.py
@@ -12,6 +12,7 @@
 import lzma
 import gzip
 import shutil
+import time
 
 from avocado import skip
 from avocado import skipUnless
@@ -1545,3 +1546,39 @@ def test_xtensa_lx60(self):
 """
 tar_hash = '49e88d9933742f0164b60839886c9739cb7a0d34'
 self.do_test_advcal_2018('02', tar_hash, 'santas-sleigh-ride.elf')
+
+def test_riscv64_virt_rv32i(self):
+"""
+:avocado: tags=arch:riscv64
+:avocado: tags=machine:virt
+:avocado: tags=cpu:rv32
+"""
+kernel_url = ('https://github.com/romanheros/rv32-linux/raw/master/'
+  'Image32.xz')
+kernel_hash = 'a7ced5c38722481e0821b7cd70719cf53e46c13b'
+kernel_path_xz = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
+
+kernel_path =  os.path.join(self.workdir, 'kernel.riscv32')
+archive.lzma_uncompress(kernel_path_xz, kernel_path)
+
+rootfs_url = ('https://github.com/romanheros/rv32-linux/raw/master/'
+  'rootfs.ext2.xz')
+rootfs_hash = 'dc25ab9d4b233e8e0bcf7eb220d56fd2008fe263'
+rootfs_path_xz = self.fetch_asset(rootfs_url, asset_hash=rootfs_hash)
+
+rootfs_path =  os.path.join(self.workdir, 'rootfs.riscv32')
+archive.lzma_uncompress(rootfs_path_xz, rootfs_path)
+
+self.vm.set_console()
+kernel_command_line = 'root=/dev/vda ro console=ttyS0'
+self.vm.add_args('-kernel', kernel_path,
+ '-append', kernel_command_line,
+ '-drive', 
f'file={rootfs_path},format=raw,id=hd0,if=none',
+ '-device', 'virtio-blk-device,drive=hd0')
+self.vm.launch()
+
+console_pattern = 'Welcome to Buildroot'
+self.wait_for_console_pattern(console_pattern)
+exec_command(self, 'root')
+time.sleep(0.1)
+exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', 'rv32i')
-- 
2.43.0




[PATCH v4 6/7] target/riscv: Enable RV32 CPU support in RV64 QEMU

2024-07-08 Thread LIU Zhiwei
From: TANG Tiancheng 

Add gdb XML files and adjust CPU initialization to allow running RV32 CPUs
in RV64 QEMU.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
Reviewed-by: Alistair Francis 
---
 configs/targets/riscv64-softmmu.mak |  2 +-
 target/riscv/cpu.c  | 17 +
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/configs/targets/riscv64-softmmu.mak 
b/configs/targets/riscv64-softmmu.mak
index 917980e63e..6c5de72e03 100644
--- a/configs/targets/riscv64-softmmu.mak
+++ b/configs/targets/riscv64-softmmu.mak
@@ -2,6 +2,6 @@ TARGET_ARCH=riscv64
 TARGET_BASE_ARCH=riscv
 TARGET_SUPPORTS_MTTCG=y
 TARGET_KVM_HAVE_GUEST_DEBUG=y
-TARGET_XML_FILES= gdb-xml/riscv-64bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml 
gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-64bit-virtual.xml
+TARGET_XML_FILES= gdb-xml/riscv-64bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml 
gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-64bit-virtual.xml 
gdb-xml/riscv-32bit-cpu.xml gdb-xml/riscv-32bit-virtual.xml
 # needed by boot.c
 TARGET_NEED_FDT=y
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index a2640cf259..fdd0f10aa5 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -630,8 +630,10 @@ static void rv64e_bare_cpu_init(Object *obj)
 riscv_cpu_set_misa_ext(env, RVE);
 }
 
-#else /* !TARGET_RISCV64 */
+#endif /* !TARGET_RISCV64 */
 
+#if defined(TARGET_RISCV32) || \
+(defined(TARGET_RISCV64) && !defined(CONFIG_USER_ONLY))
 static void rv32_base_cpu_init(Object *obj)
 {
 RISCVCPU *cpu = RISCV_CPU(obj);
@@ -2944,6 +2946,13 @@ static const TypeInfo riscv_cpu_type_infos[] = {
 #if defined(TARGET_RISCV32)
 DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,   MXL_RV32,  
riscv_any_cpu_init),
 DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,   MXL_RV32,  
riscv_max_cpu_init),
+#elif defined(TARGET_RISCV64)
+DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,   MXL_RV64,  
riscv_any_cpu_init),
+DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,   MXL_RV64,  
riscv_max_cpu_init),
+#endif
+
+#if defined(TARGET_RISCV32) || \
+(defined(TARGET_RISCV64) && !defined(CONFIG_USER_ONLY))
 DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE32,MXL_RV32,  
rv32_base_cpu_init),
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_IBEX,   MXL_RV32,  
rv32_ibex_cpu_init),
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E31, MXL_RV32,  
rv32_sifive_e_cpu_init),
@@ -2951,9 +2960,9 @@ static const TypeInfo riscv_cpu_type_infos[] = {
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U34, MXL_RV32,  
rv32_sifive_u_cpu_init),
 DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV32I,MXL_RV32,  
rv32i_bare_cpu_init),
 DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV32E,MXL_RV32,  
rv32e_bare_cpu_init),
-#elif defined(TARGET_RISCV64)
-DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,   MXL_RV64,  
riscv_any_cpu_init),
-DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,   MXL_RV64,  
riscv_max_cpu_init),
+#endif
+
+#if defined(TARGET_RISCV64)
 DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE64,MXL_RV64,  
rv64_base_cpu_init),
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E51, MXL_RV64,  
rv64_sifive_e_cpu_init),
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U54, MXL_RV64,  
rv64_sifive_u_cpu_init),
-- 
2.43.0




[PATCH v4 5/7] target/riscv: Correct mcause/scause bit width for RV32 in RV64 QEMU

2024-07-08 Thread LIU Zhiwei
From: TANG Tiancheng 

Ensure mcause high bit is correctly set by using 32-bit width for RV32
mode and 64-bit width for RV64 mode.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
---
 target/riscv/cpu_helper.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 4f0ab90ac7..3eedb26cd9 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -1673,6 +1673,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 target_ulong tinst = 0;
 target_ulong htval = 0;
 target_ulong mtval2 = 0;
+int sxlen = 0;
+int mxlen = 0;
 
 if (!async) {
 /* set tval to badaddr for traps with address information */
@@ -1799,7 +1801,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 s = set_field(s, MSTATUS_SPP, env->priv);
 s = set_field(s, MSTATUS_SIE, 0);
 env->mstatus = s;
-env->scause = cause | ((target_ulong)async << (TARGET_LONG_BITS - 1));
+sxlen = 16 << riscv_cpu_sxl(env);
+env->scause = cause | ((target_ulong)async << (sxlen - 1));
 env->sepc = env->pc;
 env->stval = tval;
 env->htval = htval;
@@ -1830,7 +1833,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 s = set_field(s, MSTATUS_MPP, env->priv);
 s = set_field(s, MSTATUS_MIE, 0);
 env->mstatus = s;
-env->mcause = cause | ~(((target_ulong)-1) >> async);
+mxlen = 16 << riscv_cpu_mxl(env);
+env->mcause = cause | ((target_ulong)async << (mxlen - 1));
 env->mepc = env->pc;
 env->mtval = tval;
 env->mtval2 = mtval2;
-- 
2.43.0




[PATCH v4 4/7] target/riscv: Detect sxl to set bit width for RV32 in RV64

2024-07-08 Thread LIU Zhiwei
From: TANG Tiancheng 

Ensure correct bit width based on sxl when running RV32 on RV64 QEMU.
This is required as MMU address translations run in S-mode.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu_helper.c | 17 -
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 6709622dd3..4f0ab90ac7 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -887,12 +887,14 @@ static int get_physical_address(CPURISCVState *env, 
hwaddr *physical,
 
 CPUState *cs = env_cpu(env);
 int va_bits = PGSHIFT + levels * ptidxbits + widened;
+int sxlen = 16 << riscv_cpu_sxl(env);
+int sxlen_bytes = sxlen / 8;
 
 if (first_stage == true) {
 target_ulong mask, masked_msbs;
 
-if (TARGET_LONG_BITS > (va_bits - 1)) {
-mask = (1L << (TARGET_LONG_BITS - (va_bits - 1))) - 1;
+if (sxlen > (va_bits - 1)) {
+mask = (1L << (sxlen - (va_bits - 1))) - 1;
 } else {
 mask = 0;
 }
@@ -961,7 +963,7 @@ restart:
 
 int pmp_prot;
 int pmp_ret = get_physical_address_pmp(env, _prot, pte_addr,
-   sizeof(target_ulong),
+   sxlen_bytes,
MMU_DATA_LOAD, PRV_S);
 if (pmp_ret != TRANSLATE_SUCCESS) {
 return TRANSLATE_PMP_FAIL;
@@ -1113,7 +1115,7 @@ restart:
  *   it is no longer valid and we must re-walk the page table.
  */
 MemoryRegion *mr;
-hwaddr l = sizeof(target_ulong), addr1;
+hwaddr l = sxlen_bytes, addr1;
 mr = address_space_translate(cs->as, pte_addr, , ,
  false, MEMTXATTRS_UNSPECIFIED);
 if (memory_region_is_ram(mr)) {
@@ -1125,7 +1127,12 @@ restart:
  */
 *pte_pa = pte = updated_pte;
 #else
-target_ulong old_pte = qatomic_cmpxchg(pte_pa, pte, updated_pte);
+target_ulong old_pte;
+if (riscv_cpu_sxl(env) == MXL_RV32) {
+old_pte = qatomic_cmpxchg((uint32_t *)pte_pa, pte, 
updated_pte);
+} else {
+old_pte = qatomic_cmpxchg(pte_pa, pte, updated_pte);
+}
 if (old_pte != pte) {
 goto restart;
 }
-- 
2.43.0




[PATCH v4 3/7] target/riscv: Correct SXL return value for RV32 in RV64 QEMU

2024-07-08 Thread LIU Zhiwei
From: TANG Tiancheng 

Ensure that riscv_cpu_sxl returns MXL_RV32 when runningRV32 in an
RV64 QEMU.

Signed-off-by: TANG Tiancheng 
Fixes: 05e6ca5e156 ("target/riscv: Ignore reserved bits in PTE for RV64")
Reviewed-by: Liu Zhiwei 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.h | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 87742047ce..49de81be7e 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -693,8 +693,11 @@ static inline RISCVMXL riscv_cpu_sxl(CPURISCVState *env)
 #ifdef CONFIG_USER_ONLY
 return env->misa_mxl;
 #else
-return get_field(env->mstatus, MSTATUS64_SXL);
+if (env->misa_mxl != MXL_RV32) {
+return get_field(env->mstatus, MSTATUS64_SXL);
+}
 #endif
+return MXL_RV32;
 }
 #endif
 
-- 
2.43.0




[PATCH v4 2/7] target/riscv: Adjust PMP size for no-MMU RV64 QEMU running RV32

2024-07-08 Thread LIU Zhiwei
From: TANG Tiancheng 

Ensure pmp_size is correctly determined using mxl for RV32
in RV64 QEMU.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
Reviewed-by: Alistair Francis 
---
 target/riscv/pmp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
index 9eea397e72..5e74b7220f 100644
--- a/target/riscv/pmp.c
+++ b/target/riscv/pmp.c
@@ -326,7 +326,7 @@ bool pmp_hart_has_privs(CPURISCVState *env, hwaddr addr,
  */
 pmp_size = -(addr | TARGET_PAGE_MASK);
 } else {
-pmp_size = sizeof(target_ulong);
+pmp_size = 2 << riscv_cpu_mxl(env);
 }
 } else {
 pmp_size = size;
-- 
2.43.0




[PATCH v4 1/7] target/riscv: Add fw_dynamic_info32 for booting RV32 OpenSBI

2024-07-08 Thread LIU Zhiwei
From: TANG Tiancheng 

RV32 OpenSBI need a fw_dynamic_info parameter with 32-bit fields instead
of target_ulong.

In RV64 QEMU, target_ulong is 64. So it is not right for booting RV32 OpenSBI.
We create a fw_dynmaic_info32 struct for this purpose.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
Reviewed-by: Alistair Francis 
---
 hw/riscv/boot.c | 35 ++---
 hw/riscv/sifive_u.c |  3 ++-
 include/hw/riscv/boot.h |  4 +++-
 include/hw/riscv/boot_opensbi.h | 29 +++
 4 files changed, 57 insertions(+), 14 deletions(-)

diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
index 47281ca853..1a2c1ff9e0 100644
--- a/hw/riscv/boot.c
+++ b/hw/riscv/boot.c
@@ -342,27 +342,33 @@ void riscv_load_fdt(hwaddr fdt_addr, void *fdt)
 rom_ptr_for_as(_space_memory, fdt_addr, 
fdtsize));
 }
 
-void riscv_rom_copy_firmware_info(MachineState *machine, hwaddr rom_base,
-  hwaddr rom_size, uint32_t reset_vec_size,
+void riscv_rom_copy_firmware_info(MachineState *machine,
+  RISCVHartArrayState *harts,
+  hwaddr rom_base, hwaddr rom_size,
+  uint32_t reset_vec_size,
   uint64_t kernel_entry)
 {
+struct fw_dynamic_info32 dinfo32;
 struct fw_dynamic_info dinfo;
 size_t dinfo_len;
 
-if (sizeof(dinfo.magic) == 4) {
-dinfo.magic = cpu_to_le32(FW_DYNAMIC_INFO_MAGIC_VALUE);
-dinfo.version = cpu_to_le32(FW_DYNAMIC_INFO_VERSION);
-dinfo.next_mode = cpu_to_le32(FW_DYNAMIC_INFO_NEXT_MODE_S);
-dinfo.next_addr = cpu_to_le32(kernel_entry);
+if (riscv_is_32bit(harts)) {
+dinfo32.magic = cpu_to_le32(FW_DYNAMIC_INFO_MAGIC_VALUE);
+dinfo32.version = cpu_to_le32(FW_DYNAMIC_INFO_VERSION);
+dinfo32.next_mode = cpu_to_le32(FW_DYNAMIC_INFO_NEXT_MODE_S);
+dinfo32.next_addr = cpu_to_le32(kernel_entry);
+dinfo32.options = 0;
+dinfo32.boot_hart = 0;
+dinfo_len = sizeof(dinfo32);
 } else {
 dinfo.magic = cpu_to_le64(FW_DYNAMIC_INFO_MAGIC_VALUE);
 dinfo.version = cpu_to_le64(FW_DYNAMIC_INFO_VERSION);
 dinfo.next_mode = cpu_to_le64(FW_DYNAMIC_INFO_NEXT_MODE_S);
 dinfo.next_addr = cpu_to_le64(kernel_entry);
+dinfo.options = 0;
+dinfo.boot_hart = 0;
+dinfo_len = sizeof(dinfo);
 }
-dinfo.options = 0;
-dinfo.boot_hart = 0;
-dinfo_len = sizeof(dinfo);
 
 /**
  * copy the dynamic firmware info. This information is specific to
@@ -374,7 +380,10 @@ void riscv_rom_copy_firmware_info(MachineState *machine, 
hwaddr rom_base,
 exit(1);
 }
 
-rom_add_blob_fixed_as("mrom.finfo", , dinfo_len,
+rom_add_blob_fixed_as("mrom.finfo",
+   riscv_is_32bit(harts) ?
+   (void *) : (void *),
+   dinfo_len,
rom_base + reset_vec_size,
_space_memory);
 }
@@ -430,7 +439,9 @@ void riscv_setup_rom_reset_vec(MachineState *machine, 
RISCVHartArrayState *harts
 }
 rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
   rom_base, _space_memory);
-riscv_rom_copy_firmware_info(machine, rom_base, rom_size, 
sizeof(reset_vec),
+riscv_rom_copy_firmware_info(machine, harts,
+ rom_base, rom_size,
+ sizeof(reset_vec),
  kernel_entry);
 }
 
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index af5f923f54..5010c3eadb 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -646,7 +646,8 @@ static void sifive_u_machine_init(MachineState *machine)
 rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
   memmap[SIFIVE_U_DEV_MROM].base, 
_space_memory);
 
-riscv_rom_copy_firmware_info(machine, memmap[SIFIVE_U_DEV_MROM].base,
+riscv_rom_copy_firmware_info(machine, >soc.u_cpus,
+ memmap[SIFIVE_U_DEV_MROM].base,
  memmap[SIFIVE_U_DEV_MROM].size,
  sizeof(reset_vec), kernel_entry);
 
diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
index a2e4ae9cb0..806256d23f 100644
--- a/include/hw/riscv/boot.h
+++ b/include/hw/riscv/boot.h
@@ -56,7 +56,9 @@ void riscv_setup_rom_reset_vec(MachineState *machine, 
RISCVHartArrayState *harts
hwaddr rom_base, hwaddr rom_size,
uint64_t kernel_entry,
uint64_t fdt_load_addr);
-void riscv_rom_copy_firmware_info(MachineState *machine, hwaddr rom_base,
+void riscv_rom_copy_firmware_info(MachineState *machine,
+ 

[PATCH v4 0/7] target/riscv: Expose RV32 cpu to RV64 QEMU

2024-07-08 Thread LIU Zhiwei
From: TANG Tiancheng 

This patch set aims to expose 32-bit RISC-V cpu to RV64 QEMU. Thus
qemu-system-riscv64 can directly boot a RV32 Linux.

This patch set has been tested with 6.9.0 Linux Image.
And add an avocado test in tests/avocado.

The recent commit 9b91879b51 ("hw/riscv/virt.c: Make block devices default to 
virtio")
changed the default behavior of block devices in RISCV Virt. To maintain 
compatibility
with the new behavior, add the "if=none" parameter to the "-drive" option in the
Avocado test suite.

Changed from:
  '-drive', f'file={rootfs_path},format=raw,id=hd0'
to:
  '-drive', f'file={rootfs_path},format=raw,id=hd0,if=none'

Test rawesult below:
$ make check-avocado 
AVOCADO_TESTS=/home/developer/qemu/qemu-code-test/qemu/tests/avocado/boot_linux_console.py
...
  AVOCADO tests/avocado
Fetching asset from 
/home/developer/qemu/qemu-code-test/qemu/tests/avocado/boot_linux_console.py:BootLinuxConsole.test_riscv64_virt_rv32i
Fetching asset from 
/home/developer/qemu/qemu-code-test/qemu/tests/avocado/boot_linux_console.py:BootLinuxConsole.test_riscv64_virt_rv32i
JOB ID : fcacf90ad453010550f60d26166911aee2e2a514
JOB LOG: 
/home/developer/qemu/qemu-code-test/qemu/build/tests/results/job-2024-07-08T12.30-fcacf90/job.log
 (1/1) 
/home/developer/qemu/qemu-code-test/qemu/tests/avocado/boot_linux_console.py:BootLinuxConsole.test_riscv64_virt_rv32i:
 PASS (27.64 s)
RESULTS: PASS 1 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | CANCEL 0
JOB TIME   : 28.39 s

v4:
  Drop UL completely in PATCH v3 2/7, 4/7, 5/7.
  Avocado: Add "if=none" to "-drive" option in QEMU command line

v3:
  Rebase to the master branch

v2:
  Remove the line that was inadvertently left in PATCH v1 4/6.
  Add an avocado test.

v1:
  https://mail.gnu.org/archive/html/qemu-riscv/2024-06/msg00501.html

TANG Tiancheng (7):
  target/riscv: Add fw_dynamic_info32 for booting RV32 OpenSBI
  target/riscv: Adjust PMP size for no-MMU RV64 QEMU running RV32
  target/riscv: Correct SXL return value for RV32 in RV64 QEMU
  target/riscv: Detect sxl to set bit width for RV32 in RV64
  target/riscv: Correct mcause/scause bit width for RV32 in RV64 QEMU
  target/riscv: Enable RV32 CPU support in RV64 QEMU
  tests/avocado: Add an avocado test for riscv64

 configs/targets/riscv64-softmmu.mak |  2 +-
 hw/riscv/boot.c | 35 +--
 hw/riscv/sifive_u.c |  3 ++-
 include/hw/riscv/boot.h |  4 +++-
 include/hw/riscv/boot_opensbi.h | 29 ++
 target/riscv/cpu.c  | 17 +
 target/riscv/cpu.h  |  5 +++-
 target/riscv/cpu_helper.c   | 25 +--
 target/riscv/pmp.c  |  2 +-
 tests/avocado/boot_linux_console.py | 37 +
 10 files changed, 131 insertions(+), 28 deletions(-)

-- 
2.43.0




Re: [PATCH] target/riscv: Validate the mode in write_vstvec

2024-07-07 Thread LIU Zhiwei



On 2024/7/1 10:25, Jiayi Li wrote:

Base on the riscv-privileged spec, vstvec substitutes for the usual stvec.
Therefore, the encoding of the MODE should also be restricted to 0 and 1.

Signed-off-by: Jiayi Li 
---
  target/riscv/csr.c | 7 ++-
  1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 432c59dc66..f9229d92ab 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -3791,7 +3791,12 @@ static RISCVException read_vstvec(CPURISCVState *env, 
int csrno,
  static RISCVException write_vstvec(CPURISCVState *env, int csrno,
 target_ulong val)
  {
-env->vstvec = val;
+/* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */
+if ((val & 3) < 2) {
+env->vstvec = val;
+} else {
+qemu_log_mask(LOG_UNIMP, "CSR_VSTVEC: reserved mode not supported\n");
+}


By the way,  you can get the all the reviewers mail by checking the 
patch with scripts/getmaintainer.pl.


Otherwise,

Reviewed-by: LIU Zhiwei 

Zhiwei


  return RISCV_EXCP_NONE;
  }
  




Re: [PATCH v2 0/7] target/riscv: Expose RV32 cpu to RV64 QEMU

2024-07-03 Thread LIU Zhiwei



On 2024/7/3 21:08, Philippe Mathieu-Daudé wrote:

Hi,

On 3/7/24 14:34, LIU Zhiwei wrote:

From: TANG Tiancheng 

This patch set aims to expose 32-bit RISC-V cpu to RV64 QEMU. Thus
qemu-system-riscv64 can directly boot a RV32 Linux.

This patch set has been tested with 6.9.0 Linux Image.
And add an avocado test in tests/avocado.

v2:
   Remove the line that was inadvertently left in PATCH v1 4/6.
   Add an avocado test.

v1:
https://mail.gnu.org/archive/html/qemu-riscv/2024-06/msg00501.html

TANG Tiancheng (7):
   target/riscv: Add fw_dynamic_info32 for booting RV32 OpenSBI
   target/riscv: Adjust PMP size for no-MMU RV64 QEMU running RV32
   target/riscv: Correct SXL return value for RV32 in RV64 QEMU
   target/riscv: Detect sxl to set bit width for RV32 in RV64
   target/riscv: Correct mcause/scause bit width for RV32 in RV64 QEMU
   target/riscv: Enable RV32 CPU support in RV64 QEMU
   tests/avocado: Add an avocado test for riscv64


On what is that based? It fails when applying:


Sorry. I forgot to rebase it to the master branch. And there is a riscv 
PR recently, which makes it fail to apply on the master branch.

Thanks for pointing it out.

The v3 patch set is here:
https://lists.gnu.org/archive/html/qemu-riscv/2024-07/msg00069.html

Thanks,
Zhiwei



Applying: target/riscv: Add fw_dynamic_info32 for booting RV32 OpenSBI
Applying: target/riscv: Adjust PMP size for no-MMU RV64 QEMU running RV32
Applying: target/riscv: Correct SXL return value for RV32 in RV64 QEMU
Applying: target/riscv: Detect sxl to set bit width for RV32 in RV64
Applying: target/riscv: Correct mcause/scause bit width for RV32 in 
RV64 QEMU

Applying: target/riscv: Enable RV32 CPU support in RV64 QEMU
Patch failed at 0006 target/riscv: Enable RV32 CPU support in RV64 QEMU
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".
error: patch failed: configs/targets/riscv64-softmmu.mak:1
error: configs/targets/riscv64-softmmu.mak: patch does not apply
hint: Use 'git am --show-current-patch=diff' to see the failed patch




[PATCH v3 7/7] tests/avocado: Add an avocado test for riscv64

2024-07-03 Thread LIU Zhiwei
From: TANG Tiancheng 

To regularly test booting Linux with rv32 on QEMU RV64,
we have added a test to boot_linux_console.py to retrieve
cpuinfo and verify if it shows 'rv32' when using RV64 to
boot rv32 CPUs.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
---
 tests/avocado/boot_linux_console.py | 37 +
 1 file changed, 37 insertions(+)

diff --git a/tests/avocado/boot_linux_console.py 
b/tests/avocado/boot_linux_console.py
index c35fc5e9ba..193b03d970 100644
--- a/tests/avocado/boot_linux_console.py
+++ b/tests/avocado/boot_linux_console.py
@@ -12,6 +12,7 @@
 import lzma
 import gzip
 import shutil
+import time
 
 from avocado import skip
 from avocado import skipUnless
@@ -1545,3 +1546,39 @@ def test_xtensa_lx60(self):
 """
 tar_hash = '49e88d9933742f0164b60839886c9739cb7a0d34'
 self.do_test_advcal_2018('02', tar_hash, 'santas-sleigh-ride.elf')
+
+def test_riscv64_virt_rv32i(self):
+"""
+:avocado: tags=arch:riscv64
+:avocado: tags=machine:virt
+:avocado: tags=cpu:rv32
+"""
+kernel_url = ('https://github.com/romanheros/rv32-linux/raw'
+  '/master/Image32.xz')
+kernel_hash = 'a7ced5c38722481e0821b7cd70719cf53e46c13b'
+kernel_path_xz = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
+
+kernel_path =  os.path.join(self.workdir, 'kernel.riscv32')
+archive.lzma_uncompress(kernel_path_xz, kernel_path)
+
+rootfs_url = ('https://github.com/romanheros/rv32-linux/raw'
+  '/master/rootfs.ext2.xz')
+rootfs_hash = 'dc25ab9d4b233e8e0bcf7eb220d56fd2008fe263'
+rootfs_path_xz = self.fetch_asset(rootfs_url, asset_hash=rootfs_hash)
+
+rootfs_path =  os.path.join(self.workdir, 'rootfs.riscv32')
+archive.lzma_uncompress(rootfs_path_xz, rootfs_path)
+
+self.vm.set_console()
+kernel_command_line = 'root=/dev/vda ro console=ttyS0'
+self.vm.add_args('-kernel', kernel_path,
+ '-append', kernel_command_line,
+ '-drive', f'file={rootfs_path},format=raw,id=hd0',
+ '-device', 'virtio-blk-device,drive=hd0',)
+self.vm.launch()
+
+console_pattern = 'Welcome to Buildroot'
+self.wait_for_console_pattern(console_pattern)
+exec_command(self, 'root')
+time.sleep(0.1)
+exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', 'rv32i')
-- 
2.25.1




[PATCH v3 6/7] target/riscv: Enable RV32 CPU support in RV64 QEMU

2024-07-03 Thread LIU Zhiwei
From: TANG Tiancheng 

Add gdb XML files and adjust CPU initialization to allow running RV32 CPUs
in RV64 QEMU.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
---
 configs/targets/riscv64-softmmu.mak |  2 +-
 target/riscv/cpu.c  | 17 +
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/configs/targets/riscv64-softmmu.mak 
b/configs/targets/riscv64-softmmu.mak
index 917980e63e..6c5de72e03 100644
--- a/configs/targets/riscv64-softmmu.mak
+++ b/configs/targets/riscv64-softmmu.mak
@@ -2,6 +2,6 @@ TARGET_ARCH=riscv64
 TARGET_BASE_ARCH=riscv
 TARGET_SUPPORTS_MTTCG=y
 TARGET_KVM_HAVE_GUEST_DEBUG=y
-TARGET_XML_FILES= gdb-xml/riscv-64bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml 
gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-64bit-virtual.xml
+TARGET_XML_FILES= gdb-xml/riscv-64bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml 
gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-64bit-virtual.xml 
gdb-xml/riscv-32bit-cpu.xml gdb-xml/riscv-32bit-virtual.xml
 # needed by boot.c
 TARGET_NEED_FDT=y
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index a2640cf259..fdd0f10aa5 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -630,8 +630,10 @@ static void rv64e_bare_cpu_init(Object *obj)
 riscv_cpu_set_misa_ext(env, RVE);
 }
 
-#else /* !TARGET_RISCV64 */
+#endif /* !TARGET_RISCV64 */
 
+#if defined(TARGET_RISCV32) || \
+(defined(TARGET_RISCV64) && !defined(CONFIG_USER_ONLY))
 static void rv32_base_cpu_init(Object *obj)
 {
 RISCVCPU *cpu = RISCV_CPU(obj);
@@ -2944,6 +2946,13 @@ static const TypeInfo riscv_cpu_type_infos[] = {
 #if defined(TARGET_RISCV32)
 DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,   MXL_RV32,  
riscv_any_cpu_init),
 DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,   MXL_RV32,  
riscv_max_cpu_init),
+#elif defined(TARGET_RISCV64)
+DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,   MXL_RV64,  
riscv_any_cpu_init),
+DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,   MXL_RV64,  
riscv_max_cpu_init),
+#endif
+
+#if defined(TARGET_RISCV32) || \
+(defined(TARGET_RISCV64) && !defined(CONFIG_USER_ONLY))
 DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE32,MXL_RV32,  
rv32_base_cpu_init),
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_IBEX,   MXL_RV32,  
rv32_ibex_cpu_init),
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E31, MXL_RV32,  
rv32_sifive_e_cpu_init),
@@ -2951,9 +2960,9 @@ static const TypeInfo riscv_cpu_type_infos[] = {
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U34, MXL_RV32,  
rv32_sifive_u_cpu_init),
 DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV32I,MXL_RV32,  
rv32i_bare_cpu_init),
 DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV32E,MXL_RV32,  
rv32e_bare_cpu_init),
-#elif defined(TARGET_RISCV64)
-DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,   MXL_RV64,  
riscv_any_cpu_init),
-DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,   MXL_RV64,  
riscv_max_cpu_init),
+#endif
+
+#if defined(TARGET_RISCV64)
 DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE64,MXL_RV64,  
rv64_base_cpu_init),
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E51, MXL_RV64,  
rv64_sifive_e_cpu_init),
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U54, MXL_RV64,  
rv64_sifive_u_cpu_init),
-- 
2.25.1




[PATCH v3 5/7] target/riscv: Correct mcause/scause bit width for RV32 in RV64 QEMU

2024-07-03 Thread LIU Zhiwei
From: TANG Tiancheng 

Ensure mcause high bit is correctly set by using 32-bit width for RV32
mode and 64-bit width for RV64 mode.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
---
 target/riscv/cpu_helper.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index fa3b845c85..a79a03c7e0 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -1673,6 +1673,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 target_ulong tinst = 0;
 target_ulong htval = 0;
 target_ulong mtval2 = 0;
+int sxlen = 0;
+int mxlen = 0;
 
 if (!async) {
 /* set tval to badaddr for traps with address information */
@@ -1799,7 +1801,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 s = set_field(s, MSTATUS_SPP, env->priv);
 s = set_field(s, MSTATUS_SIE, 0);
 env->mstatus = s;
-env->scause = cause | ((target_ulong)async << (TARGET_LONG_BITS - 1));
+sxlen = 16UL << riscv_cpu_sxl(env);
+env->scause = cause | ((target_ulong)async << (sxlen - 1));
 env->sepc = env->pc;
 env->stval = tval;
 env->htval = htval;
@@ -1830,7 +1833,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 s = set_field(s, MSTATUS_MPP, env->priv);
 s = set_field(s, MSTATUS_MIE, 0);
 env->mstatus = s;
-env->mcause = cause | ~(((target_ulong)-1) >> async);
+mxlen = 16UL << riscv_cpu_mxl(env);
+env->mcause = cause | ((target_ulong)async << (mxlen - 1));
 env->mepc = env->pc;
 env->mtval = tval;
 env->mtval2 = mtval2;
-- 
2.25.1




[PATCH v3 4/7] target/riscv: Detect sxl to set bit width for RV32 in RV64

2024-07-03 Thread LIU Zhiwei
From: TANG Tiancheng 

Ensure correct bit width based on sxl when running RV32 on RV64 QEMU.
This is required as MMU address translations run in S-mode.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
---
 target/riscv/cpu_helper.c | 17 -
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 6709622dd3..fa3b845c85 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -887,12 +887,14 @@ static int get_physical_address(CPURISCVState *env, 
hwaddr *physical,
 
 CPUState *cs = env_cpu(env);
 int va_bits = PGSHIFT + levels * ptidxbits + widened;
+int sxlen = 16UL << riscv_cpu_sxl(env);
+int sxlen_bytes = sxlen / 8;
 
 if (first_stage == true) {
 target_ulong mask, masked_msbs;
 
-if (TARGET_LONG_BITS > (va_bits - 1)) {
-mask = (1L << (TARGET_LONG_BITS - (va_bits - 1))) - 1;
+if (sxlen > (va_bits - 1)) {
+mask = (1L << (sxlen - (va_bits - 1))) - 1;
 } else {
 mask = 0;
 }
@@ -961,7 +963,7 @@ restart:
 
 int pmp_prot;
 int pmp_ret = get_physical_address_pmp(env, _prot, pte_addr,
-   sizeof(target_ulong),
+   sxlen_bytes,
MMU_DATA_LOAD, PRV_S);
 if (pmp_ret != TRANSLATE_SUCCESS) {
 return TRANSLATE_PMP_FAIL;
@@ -1113,7 +1115,7 @@ restart:
  *   it is no longer valid and we must re-walk the page table.
  */
 MemoryRegion *mr;
-hwaddr l = sizeof(target_ulong), addr1;
+hwaddr l = sxlen_bytes, addr1;
 mr = address_space_translate(cs->as, pte_addr, , ,
  false, MEMTXATTRS_UNSPECIFIED);
 if (memory_region_is_ram(mr)) {
@@ -1125,7 +1127,12 @@ restart:
  */
 *pte_pa = pte = updated_pte;
 #else
-target_ulong old_pte = qatomic_cmpxchg(pte_pa, pte, updated_pte);
+target_ulong old_pte;
+if (riscv_cpu_sxl(env) == MXL_RV32) {
+old_pte = qatomic_cmpxchg((uint32_t *)pte_pa, pte, 
updated_pte);
+} else {
+old_pte = qatomic_cmpxchg(pte_pa, pte, updated_pte);
+}
 if (old_pte != pte) {
 goto restart;
 }
-- 
2.25.1




[PATCH v3 3/7] target/riscv: Correct SXL return value for RV32 in RV64 QEMU

2024-07-03 Thread LIU Zhiwei
From: TANG Tiancheng 

Ensure that riscv_cpu_sxl returns MXL_RV32 when runningRV32 in an
RV64 QEMU.

Signed-off-by: TANG Tiancheng 
Fixes: 05e6ca5e156 ("target/riscv: Ignore reserved bits in PTE for RV64")
Reviewed-by: Liu Zhiwei 
---
 target/riscv/cpu.h | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 87742047ce..49de81be7e 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -693,8 +693,11 @@ static inline RISCVMXL riscv_cpu_sxl(CPURISCVState *env)
 #ifdef CONFIG_USER_ONLY
 return env->misa_mxl;
 #else
-return get_field(env->mstatus, MSTATUS64_SXL);
+if (env->misa_mxl != MXL_RV32) {
+return get_field(env->mstatus, MSTATUS64_SXL);
+}
 #endif
+return MXL_RV32;
 }
 #endif
 
-- 
2.25.1




[PATCH v3 2/7] target/riscv: Adjust PMP size for no-MMU RV64 QEMU running RV32

2024-07-03 Thread LIU Zhiwei
From: TANG Tiancheng 

Ensure pmp_size is correctly determined using mxl for RV32
in RV64 QEMU.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
Reviewed-by: Alistair Francis 
---
 target/riscv/pmp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
index 9eea397e72..f65aa3dba7 100644
--- a/target/riscv/pmp.c
+++ b/target/riscv/pmp.c
@@ -326,7 +326,7 @@ bool pmp_hart_has_privs(CPURISCVState *env, hwaddr addr,
  */
 pmp_size = -(addr | TARGET_PAGE_MASK);
 } else {
-pmp_size = sizeof(target_ulong);
+pmp_size = 2UL << riscv_cpu_mxl(env);
 }
 } else {
 pmp_size = size;
-- 
2.25.1




[PATCH v3 1/7] target/riscv: Add fw_dynamic_info32 for booting RV32 OpenSBI

2024-07-03 Thread LIU Zhiwei
From: TANG Tiancheng 

RV32 OpenSBI need a fw_dynamic_info parameter with 32-bit fields instead
of target_ulong.

In RV64 QEMU, target_ulong is 64. So it is not right for booting RV32 OpenSBI.
We create a fw_dynmaic_info32 struct for this purpose.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
Reviewed-by: Alistair Francis 
---
 hw/riscv/boot.c | 35 ++---
 hw/riscv/sifive_u.c |  3 ++-
 include/hw/riscv/boot.h |  4 +++-
 include/hw/riscv/boot_opensbi.h | 29 +++
 4 files changed, 57 insertions(+), 14 deletions(-)

diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
index 47281ca853..1a2c1ff9e0 100644
--- a/hw/riscv/boot.c
+++ b/hw/riscv/boot.c
@@ -342,27 +342,33 @@ void riscv_load_fdt(hwaddr fdt_addr, void *fdt)
 rom_ptr_for_as(_space_memory, fdt_addr, 
fdtsize));
 }
 
-void riscv_rom_copy_firmware_info(MachineState *machine, hwaddr rom_base,
-  hwaddr rom_size, uint32_t reset_vec_size,
+void riscv_rom_copy_firmware_info(MachineState *machine,
+  RISCVHartArrayState *harts,
+  hwaddr rom_base, hwaddr rom_size,
+  uint32_t reset_vec_size,
   uint64_t kernel_entry)
 {
+struct fw_dynamic_info32 dinfo32;
 struct fw_dynamic_info dinfo;
 size_t dinfo_len;
 
-if (sizeof(dinfo.magic) == 4) {
-dinfo.magic = cpu_to_le32(FW_DYNAMIC_INFO_MAGIC_VALUE);
-dinfo.version = cpu_to_le32(FW_DYNAMIC_INFO_VERSION);
-dinfo.next_mode = cpu_to_le32(FW_DYNAMIC_INFO_NEXT_MODE_S);
-dinfo.next_addr = cpu_to_le32(kernel_entry);
+if (riscv_is_32bit(harts)) {
+dinfo32.magic = cpu_to_le32(FW_DYNAMIC_INFO_MAGIC_VALUE);
+dinfo32.version = cpu_to_le32(FW_DYNAMIC_INFO_VERSION);
+dinfo32.next_mode = cpu_to_le32(FW_DYNAMIC_INFO_NEXT_MODE_S);
+dinfo32.next_addr = cpu_to_le32(kernel_entry);
+dinfo32.options = 0;
+dinfo32.boot_hart = 0;
+dinfo_len = sizeof(dinfo32);
 } else {
 dinfo.magic = cpu_to_le64(FW_DYNAMIC_INFO_MAGIC_VALUE);
 dinfo.version = cpu_to_le64(FW_DYNAMIC_INFO_VERSION);
 dinfo.next_mode = cpu_to_le64(FW_DYNAMIC_INFO_NEXT_MODE_S);
 dinfo.next_addr = cpu_to_le64(kernel_entry);
+dinfo.options = 0;
+dinfo.boot_hart = 0;
+dinfo_len = sizeof(dinfo);
 }
-dinfo.options = 0;
-dinfo.boot_hart = 0;
-dinfo_len = sizeof(dinfo);
 
 /**
  * copy the dynamic firmware info. This information is specific to
@@ -374,7 +380,10 @@ void riscv_rom_copy_firmware_info(MachineState *machine, 
hwaddr rom_base,
 exit(1);
 }
 
-rom_add_blob_fixed_as("mrom.finfo", , dinfo_len,
+rom_add_blob_fixed_as("mrom.finfo",
+   riscv_is_32bit(harts) ?
+   (void *) : (void *),
+   dinfo_len,
rom_base + reset_vec_size,
_space_memory);
 }
@@ -430,7 +439,9 @@ void riscv_setup_rom_reset_vec(MachineState *machine, 
RISCVHartArrayState *harts
 }
 rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
   rom_base, _space_memory);
-riscv_rom_copy_firmware_info(machine, rom_base, rom_size, 
sizeof(reset_vec),
+riscv_rom_copy_firmware_info(machine, harts,
+ rom_base, rom_size,
+ sizeof(reset_vec),
  kernel_entry);
 }
 
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index af5f923f54..5010c3eadb 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -646,7 +646,8 @@ static void sifive_u_machine_init(MachineState *machine)
 rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
   memmap[SIFIVE_U_DEV_MROM].base, 
_space_memory);
 
-riscv_rom_copy_firmware_info(machine, memmap[SIFIVE_U_DEV_MROM].base,
+riscv_rom_copy_firmware_info(machine, >soc.u_cpus,
+ memmap[SIFIVE_U_DEV_MROM].base,
  memmap[SIFIVE_U_DEV_MROM].size,
  sizeof(reset_vec), kernel_entry);
 
diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
index a2e4ae9cb0..806256d23f 100644
--- a/include/hw/riscv/boot.h
+++ b/include/hw/riscv/boot.h
@@ -56,7 +56,9 @@ void riscv_setup_rom_reset_vec(MachineState *machine, 
RISCVHartArrayState *harts
hwaddr rom_base, hwaddr rom_size,
uint64_t kernel_entry,
uint64_t fdt_load_addr);
-void riscv_rom_copy_firmware_info(MachineState *machine, hwaddr rom_base,
+void riscv_rom_copy_firmware_info(MachineState *machine,
+ 

[PATCH v3 0/7] target/riscv: Expose RV32 cpu to RV64 QEMU

2024-07-03 Thread LIU Zhiwei
This patch set aims to expose 32-bit RISC-V cpu to RV64 QEMU. Thus
qemu-system-riscv64 can directly boot a RV32 Linux.

This patch set has been tested with 6.9.0 Linux Image.
And add an avocado test in tests/avocado.

v3:
  Rebase to the master branch

v2:
  Remove the line that was inadvertently left in PATCH v1 4/6.
  Add an avocado test.

v1:
  https://mail.gnu.org/archive/html/qemu-riscv/2024-06/msg00501.html

TANG Tiancheng (7):
  target/riscv: Add fw_dynamic_info32 for booting RV32 OpenSBI
  target/riscv: Adjust PMP size for no-MMU RV64 QEMU running RV32
  target/riscv: Correct SXL return value for RV32 in RV64 QEMU
  target/riscv: Detect sxl to set bit width for RV32 in RV64
  target/riscv: Correct mcause/scause bit width for RV32 in RV64 QEMU
  target/riscv: Enable RV32 CPU support in RV64 QEMU
  tests/avocado: Add an avocado test for riscv64

 configs/targets/riscv64-softmmu.mak |  2 +-
 hw/riscv/boot.c | 35 +--
 hw/riscv/sifive_u.c |  3 ++-
 include/hw/riscv/boot.h |  4 +++-
 include/hw/riscv/boot_opensbi.h | 29 ++
 target/riscv/cpu.c  | 17 +
 target/riscv/cpu.h  |  5 +++-
 target/riscv/cpu_helper.c   | 25 +--
 target/riscv/pmp.c  |  2 +-
 tests/avocado/boot_linux_console.py | 37 +
 10 files changed, 131 insertions(+), 28 deletions(-)

-- 
2.25.1




[PATCH v2 7/7] tests/avocado: Add an avocado test for riscv64

2024-07-03 Thread LIU Zhiwei
From: TANG Tiancheng 

To regularly test booting Linux with rv32 on QEMU RV64,
we have added a test to boot_linux_console.py to retrieve
cpuinfo and verify if it shows 'rv32' when using RV64 to
boot rv32 CPUs.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
---
 tests/avocado/boot_linux_console.py | 35 +
 1 file changed, 35 insertions(+)

diff --git a/tests/avocado/boot_linux_console.py 
b/tests/avocado/boot_linux_console.py
index c35fc5e9ba..408f936f9a 100644
--- a/tests/avocado/boot_linux_console.py
+++ b/tests/avocado/boot_linux_console.py
@@ -12,6 +12,7 @@
 import lzma
 import gzip
 import shutil
+import time
 
 from avocado import skip
 from avocado import skipUnless
@@ -1545,3 +1546,37 @@ def test_xtensa_lx60(self):
 """
 tar_hash = '49e88d9933742f0164b60839886c9739cb7a0d34'
 self.do_test_advcal_2018('02', tar_hash, 'santas-sleigh-ride.elf')
+
+def test_riscv64_virt_rv32i(self):
+"""
+:avocado: tags=arch:riscv64
+:avocado: tags=machine:virt
+:avocado: tags=cpu:rv32
+"""
+kernel_url = 
('https://github.com/romanheros/rv32-linux/raw/master/Image32.xz')
+kernel_hash = 'a7ced5c38722481e0821b7cd70719cf53e46c13b'
+kernel_path_xz = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
+
+kernel_path =  os.path.join(self.workdir, 'kernel.riscv32')
+archive.lzma_uncompress(kernel_path_xz, kernel_path)
+
+rootfs_url = 
('https://github.com/romanheros/rv32-linux/raw/master/rootfs.ext2.xz')
+rootfs_hash = 'dc25ab9d4b233e8e0bcf7eb220d56fd2008fe263'
+rootfs_path_xz = self.fetch_asset(rootfs_url, asset_hash=rootfs_hash)
+
+rootfs_path =  os.path.join(self.workdir, 'rootfs.riscv32')
+archive.lzma_uncompress(rootfs_path_xz, rootfs_path)
+
+self.vm.set_console()
+kernel_command_line = 'root=/dev/vda ro console=ttyS0'
+self.vm.add_args('-kernel', kernel_path,
+ '-append', kernel_command_line,
+ '-drive', f'file={rootfs_path},format=raw,id=hd0',
+ '-device', 'virtio-blk-device,drive=hd0',)
+self.vm.launch()
+
+console_pattern = 'Welcome to Buildroot'
+self.wait_for_console_pattern(console_pattern)
+exec_command(self, 'root')
+time.sleep(0.1)
+exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', 'rv32i')
-- 
2.43.0




[PATCH v2 6/7] target/riscv: Enable RV32 CPU support in RV64 QEMU

2024-07-03 Thread LIU Zhiwei
From: TANG Tiancheng 

Add gdb XML files and adjust CPU initialization to allow running RV32 CPUs
in RV64 QEMU.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
---
 configs/targets/riscv64-softmmu.mak |  2 +-
 target/riscv/cpu.c  | 17 +
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/configs/targets/riscv64-softmmu.mak 
b/configs/targets/riscv64-softmmu.mak
index f688ffa7bc..5c1abb4b51 100644
--- a/configs/targets/riscv64-softmmu.mak
+++ b/configs/targets/riscv64-softmmu.mak
@@ -1,6 +1,6 @@
 TARGET_ARCH=riscv64
 TARGET_BASE_ARCH=riscv
 TARGET_SUPPORTS_MTTCG=y
-TARGET_XML_FILES= gdb-xml/riscv-64bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml 
gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-64bit-virtual.xml
+TARGET_XML_FILES= gdb-xml/riscv-64bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml 
gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-64bit-virtual.xml 
gdb-xml/riscv-32bit-cpu.xml gdb-xml/riscv-32bit-virtual.xml
 # needed by boot.c
 TARGET_NEED_FDT=y
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 69a08e8c2c..58165901a2 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -630,8 +630,10 @@ static void rv64e_bare_cpu_init(Object *obj)
 riscv_cpu_set_misa_ext(env, RVE);
 }
 
-#else /* !TARGET_RISCV64 */
+#endif /* !TARGET_RISCV64 */
 
+#if defined(TARGET_RISCV32) || \
+(defined(TARGET_RISCV64) && !defined(CONFIG_USER_ONLY))
 static void rv32_base_cpu_init(Object *obj)
 {
 RISCVCPU *cpu = RISCV_CPU(obj);
@@ -2544,6 +2546,13 @@ static const TypeInfo riscv_cpu_type_infos[] = {
 #if defined(TARGET_RISCV32)
 DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,   MXL_RV32,  
riscv_any_cpu_init),
 DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,   MXL_RV32,  
riscv_max_cpu_init),
+#elif defined(TARGET_RISCV64)
+DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,   MXL_RV64,  
riscv_any_cpu_init),
+DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,   MXL_RV64,  
riscv_max_cpu_init),
+#endif
+
+#if defined(TARGET_RISCV32) || \
+(defined(TARGET_RISCV64) && !defined(CONFIG_USER_ONLY))
 DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE32,MXL_RV32,  
rv32_base_cpu_init),
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_IBEX,   MXL_RV32,  
rv32_ibex_cpu_init),
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E31, MXL_RV32,  
rv32_sifive_e_cpu_init),
@@ -2551,9 +2560,9 @@ static const TypeInfo riscv_cpu_type_infos[] = {
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U34, MXL_RV32,  
rv32_sifive_u_cpu_init),
 DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV32I,MXL_RV32,  
rv32i_bare_cpu_init),
 DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV32E,MXL_RV32,  
rv32e_bare_cpu_init),
-#elif defined(TARGET_RISCV64)
-DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,   MXL_RV64,  
riscv_any_cpu_init),
-DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,   MXL_RV64,  
riscv_max_cpu_init),
+#endif
+
+#if defined(TARGET_RISCV64)
 DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE64,MXL_RV64,  
rv64_base_cpu_init),
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E51, MXL_RV64,  
rv64_sifive_e_cpu_init),
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U54, MXL_RV64,  
rv64_sifive_u_cpu_init),
-- 
2.43.0




[PATCH v2 5/7] target/riscv: Correct mcause/scause bit width for RV32 in RV64 QEMU

2024-07-03 Thread LIU Zhiwei
From: TANG Tiancheng 

Ensure mcause high bit is correctly set by using 32-bit width for RV32
mode and 64-bit width for RV64 mode.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
---
 target/riscv/cpu_helper.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index fa3b845c85..a79a03c7e0 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -1673,6 +1673,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 target_ulong tinst = 0;
 target_ulong htval = 0;
 target_ulong mtval2 = 0;
+int sxlen = 0;
+int mxlen = 0;
 
 if (!async) {
 /* set tval to badaddr for traps with address information */
@@ -1799,7 +1801,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 s = set_field(s, MSTATUS_SPP, env->priv);
 s = set_field(s, MSTATUS_SIE, 0);
 env->mstatus = s;
-env->scause = cause | ((target_ulong)async << (TARGET_LONG_BITS - 1));
+sxlen = 16UL << riscv_cpu_sxl(env);
+env->scause = cause | ((target_ulong)async << (sxlen - 1));
 env->sepc = env->pc;
 env->stval = tval;
 env->htval = htval;
@@ -1830,7 +1833,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 s = set_field(s, MSTATUS_MPP, env->priv);
 s = set_field(s, MSTATUS_MIE, 0);
 env->mstatus = s;
-env->mcause = cause | ~(((target_ulong)-1) >> async);
+mxlen = 16UL << riscv_cpu_mxl(env);
+env->mcause = cause | ((target_ulong)async << (mxlen - 1));
 env->mepc = env->pc;
 env->mtval = tval;
 env->mtval2 = mtval2;
-- 
2.43.0




[PATCH v2 4/7] target/riscv: Detect sxl to set bit width for RV32 in RV64

2024-07-03 Thread LIU Zhiwei
From: TANG Tiancheng 

Ensure correct bit width based on sxl when running RV32 on RV64 QEMU.
This is required as MMU address translations run in S-mode.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
---
 target/riscv/cpu_helper.c | 17 -
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 6709622dd3..fa3b845c85 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -887,12 +887,14 @@ static int get_physical_address(CPURISCVState *env, 
hwaddr *physical,
 
 CPUState *cs = env_cpu(env);
 int va_bits = PGSHIFT + levels * ptidxbits + widened;
+int sxlen = 16UL << riscv_cpu_sxl(env);
+int sxlen_bytes = sxlen / 8;
 
 if (first_stage == true) {
 target_ulong mask, masked_msbs;
 
-if (TARGET_LONG_BITS > (va_bits - 1)) {
-mask = (1L << (TARGET_LONG_BITS - (va_bits - 1))) - 1;
+if (sxlen > (va_bits - 1)) {
+mask = (1L << (sxlen - (va_bits - 1))) - 1;
 } else {
 mask = 0;
 }
@@ -961,7 +963,7 @@ restart:
 
 int pmp_prot;
 int pmp_ret = get_physical_address_pmp(env, _prot, pte_addr,
-   sizeof(target_ulong),
+   sxlen_bytes,
MMU_DATA_LOAD, PRV_S);
 if (pmp_ret != TRANSLATE_SUCCESS) {
 return TRANSLATE_PMP_FAIL;
@@ -1113,7 +1115,7 @@ restart:
  *   it is no longer valid and we must re-walk the page table.
  */
 MemoryRegion *mr;
-hwaddr l = sizeof(target_ulong), addr1;
+hwaddr l = sxlen_bytes, addr1;
 mr = address_space_translate(cs->as, pte_addr, , ,
  false, MEMTXATTRS_UNSPECIFIED);
 if (memory_region_is_ram(mr)) {
@@ -1125,7 +1127,12 @@ restart:
  */
 *pte_pa = pte = updated_pte;
 #else
-target_ulong old_pte = qatomic_cmpxchg(pte_pa, pte, updated_pte);
+target_ulong old_pte;
+if (riscv_cpu_sxl(env) == MXL_RV32) {
+old_pte = qatomic_cmpxchg((uint32_t *)pte_pa, pte, 
updated_pte);
+} else {
+old_pte = qatomic_cmpxchg(pte_pa, pte, updated_pte);
+}
 if (old_pte != pte) {
 goto restart;
 }
-- 
2.43.0




[PATCH v2 3/7] target/riscv: Correct SXL return value for RV32 in RV64 QEMU

2024-07-03 Thread LIU Zhiwei
From: TANG Tiancheng 

Ensure that riscv_cpu_sxl returns MXL_RV32 when runningRV32 in an
RV64 QEMU.

Signed-off-by: TANG Tiancheng 
Fixes: 05e6ca5e156 ("target/riscv: Ignore reserved bits in PTE for RV64")
Reviewed-by: Liu Zhiwei 
---
 target/riscv/cpu.h | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 6fe0d712b4..36a712044a 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -668,8 +668,11 @@ static inline RISCVMXL riscv_cpu_sxl(CPURISCVState *env)
 #ifdef CONFIG_USER_ONLY
 return env->misa_mxl;
 #else
-return get_field(env->mstatus, MSTATUS64_SXL);
+if (env->misa_mxl != MXL_RV32) {
+return get_field(env->mstatus, MSTATUS64_SXL);
+}
 #endif
+return MXL_RV32;
 }
 #endif
 
-- 
2.43.0




[PATCH v2 2/7] target/riscv: Adjust PMP size for no-MMU RV64 QEMU running RV32

2024-07-03 Thread LIU Zhiwei
From: TANG Tiancheng 

Ensure pmp_size is correctly determined using mxl for RV32
in RV64 QEMU.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
Reviewed-by: Alistair Francis 
---
 target/riscv/pmp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
index 9eea397e72..f65aa3dba7 100644
--- a/target/riscv/pmp.c
+++ b/target/riscv/pmp.c
@@ -326,7 +326,7 @@ bool pmp_hart_has_privs(CPURISCVState *env, hwaddr addr,
  */
 pmp_size = -(addr | TARGET_PAGE_MASK);
 } else {
-pmp_size = sizeof(target_ulong);
+pmp_size = 2UL << riscv_cpu_mxl(env);
 }
 } else {
 pmp_size = size;
-- 
2.43.0




[PATCH v2 1/7] target/riscv: Add fw_dynamic_info32 for booting RV32 OpenSBI

2024-07-03 Thread LIU Zhiwei
From: TANG Tiancheng 

RV32 OpenSBI need a fw_dynamic_info parameter with 32-bit fields instead
of target_ulong.

In RV64 QEMU, target_ulong is 64. So it is not right for booting RV32 OpenSBI.
We create a fw_dynmaic_info32 struct for this purpose.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
Reviewed-by: Alistair Francis 
---
 hw/riscv/boot.c | 35 ++---
 hw/riscv/sifive_u.c |  3 ++-
 include/hw/riscv/boot.h |  4 +++-
 include/hw/riscv/boot_opensbi.h | 29 +++
 4 files changed, 57 insertions(+), 14 deletions(-)

diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
index 47281ca853..1a2c1ff9e0 100644
--- a/hw/riscv/boot.c
+++ b/hw/riscv/boot.c
@@ -342,27 +342,33 @@ void riscv_load_fdt(hwaddr fdt_addr, void *fdt)
 rom_ptr_for_as(_space_memory, fdt_addr, 
fdtsize));
 }
 
-void riscv_rom_copy_firmware_info(MachineState *machine, hwaddr rom_base,
-  hwaddr rom_size, uint32_t reset_vec_size,
+void riscv_rom_copy_firmware_info(MachineState *machine,
+  RISCVHartArrayState *harts,
+  hwaddr rom_base, hwaddr rom_size,
+  uint32_t reset_vec_size,
   uint64_t kernel_entry)
 {
+struct fw_dynamic_info32 dinfo32;
 struct fw_dynamic_info dinfo;
 size_t dinfo_len;
 
-if (sizeof(dinfo.magic) == 4) {
-dinfo.magic = cpu_to_le32(FW_DYNAMIC_INFO_MAGIC_VALUE);
-dinfo.version = cpu_to_le32(FW_DYNAMIC_INFO_VERSION);
-dinfo.next_mode = cpu_to_le32(FW_DYNAMIC_INFO_NEXT_MODE_S);
-dinfo.next_addr = cpu_to_le32(kernel_entry);
+if (riscv_is_32bit(harts)) {
+dinfo32.magic = cpu_to_le32(FW_DYNAMIC_INFO_MAGIC_VALUE);
+dinfo32.version = cpu_to_le32(FW_DYNAMIC_INFO_VERSION);
+dinfo32.next_mode = cpu_to_le32(FW_DYNAMIC_INFO_NEXT_MODE_S);
+dinfo32.next_addr = cpu_to_le32(kernel_entry);
+dinfo32.options = 0;
+dinfo32.boot_hart = 0;
+dinfo_len = sizeof(dinfo32);
 } else {
 dinfo.magic = cpu_to_le64(FW_DYNAMIC_INFO_MAGIC_VALUE);
 dinfo.version = cpu_to_le64(FW_DYNAMIC_INFO_VERSION);
 dinfo.next_mode = cpu_to_le64(FW_DYNAMIC_INFO_NEXT_MODE_S);
 dinfo.next_addr = cpu_to_le64(kernel_entry);
+dinfo.options = 0;
+dinfo.boot_hart = 0;
+dinfo_len = sizeof(dinfo);
 }
-dinfo.options = 0;
-dinfo.boot_hart = 0;
-dinfo_len = sizeof(dinfo);
 
 /**
  * copy the dynamic firmware info. This information is specific to
@@ -374,7 +380,10 @@ void riscv_rom_copy_firmware_info(MachineState *machine, 
hwaddr rom_base,
 exit(1);
 }
 
-rom_add_blob_fixed_as("mrom.finfo", , dinfo_len,
+rom_add_blob_fixed_as("mrom.finfo",
+   riscv_is_32bit(harts) ?
+   (void *) : (void *),
+   dinfo_len,
rom_base + reset_vec_size,
_space_memory);
 }
@@ -430,7 +439,9 @@ void riscv_setup_rom_reset_vec(MachineState *machine, 
RISCVHartArrayState *harts
 }
 rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
   rom_base, _space_memory);
-riscv_rom_copy_firmware_info(machine, rom_base, rom_size, 
sizeof(reset_vec),
+riscv_rom_copy_firmware_info(machine, harts,
+ rom_base, rom_size,
+ sizeof(reset_vec),
  kernel_entry);
 }
 
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index af5f923f54..5010c3eadb 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -646,7 +646,8 @@ static void sifive_u_machine_init(MachineState *machine)
 rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
   memmap[SIFIVE_U_DEV_MROM].base, 
_space_memory);
 
-riscv_rom_copy_firmware_info(machine, memmap[SIFIVE_U_DEV_MROM].base,
+riscv_rom_copy_firmware_info(machine, >soc.u_cpus,
+ memmap[SIFIVE_U_DEV_MROM].base,
  memmap[SIFIVE_U_DEV_MROM].size,
  sizeof(reset_vec), kernel_entry);
 
diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
index a2e4ae9cb0..806256d23f 100644
--- a/include/hw/riscv/boot.h
+++ b/include/hw/riscv/boot.h
@@ -56,7 +56,9 @@ void riscv_setup_rom_reset_vec(MachineState *machine, 
RISCVHartArrayState *harts
hwaddr rom_base, hwaddr rom_size,
uint64_t kernel_entry,
uint64_t fdt_load_addr);
-void riscv_rom_copy_firmware_info(MachineState *machine, hwaddr rom_base,
+void riscv_rom_copy_firmware_info(MachineState *machine,
+ 

[PATCH v2 0/7] target/riscv: Expose RV32 cpu to RV64 QEMU

2024-07-03 Thread LIU Zhiwei
From: TANG Tiancheng 

This patch set aims to expose 32-bit RISC-V cpu to RV64 QEMU. Thus
qemu-system-riscv64 can directly boot a RV32 Linux.

This patch set has been tested with 6.9.0 Linux Image.
And add an avocado test in tests/avocado.

v2:
  Remove the line that was inadvertently left in PATCH v1 4/6.
  Add an avocado test.

v1:
  https://mail.gnu.org/archive/html/qemu-riscv/2024-06/msg00501.html

TANG Tiancheng (7):
  target/riscv: Add fw_dynamic_info32 for booting RV32 OpenSBI
  target/riscv: Adjust PMP size for no-MMU RV64 QEMU running RV32
  target/riscv: Correct SXL return value for RV32 in RV64 QEMU
  target/riscv: Detect sxl to set bit width for RV32 in RV64
  target/riscv: Correct mcause/scause bit width for RV32 in RV64 QEMU
  target/riscv: Enable RV32 CPU support in RV64 QEMU
  tests/avocado: Add an avocado test for riscv64

 configs/targets/riscv64-softmmu.mak |  2 +-
 hw/riscv/boot.c | 35 +++--
 hw/riscv/sifive_u.c |  3 ++-
 include/hw/riscv/boot.h |  4 +++-
 include/hw/riscv/boot_opensbi.h | 29 
 target/riscv/cpu.c  | 17 ++
 target/riscv/cpu.h  |  5 -
 target/riscv/cpu_helper.c   | 25 +++--
 target/riscv/pmp.c  |  2 +-
 tests/avocado/boot_linux_console.py | 35 +
 10 files changed, 129 insertions(+), 28 deletions(-)

-- 
2.43.0




Re: [PATCH 1/3] util/cpuinfo-riscv: Support host/cpuinfo.h for riscv

2024-07-03 Thread LIU Zhiwei



On 2024/6/28 2:03, Richard Henderson wrote:

Move detection code out of tcg, similar to other hosts.

Signed-off-by: Richard Henderson 

Reviewed-by: LIU Zhiwei 

Zhiwei


---
  host/include/riscv/host/cpuinfo.h | 23 +
  tcg/riscv/tcg-target.h| 46 -
  util/cpuinfo-riscv.c  | 85 +++
  tcg/riscv/tcg-target.c.inc| 84 +++---
  util/meson.build  |  2 +
  5 files changed, 139 insertions(+), 101 deletions(-)
  create mode 100644 host/include/riscv/host/cpuinfo.h
  create mode 100644 util/cpuinfo-riscv.c

diff --git a/host/include/riscv/host/cpuinfo.h 
b/host/include/riscv/host/cpuinfo.h
new file mode 100644
index 00..2b00660e36
--- /dev/null
+++ b/host/include/riscv/host/cpuinfo.h
@@ -0,0 +1,23 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ * Host specific cpu identification for RISC-V.
+ */
+
+#ifndef HOST_CPUINFO_H
+#define HOST_CPUINFO_H
+
+#define CPUINFO_ALWAYS  (1u << 0)  /* so cpuinfo is nonzero */
+#define CPUINFO_ZBA (1u << 1)
+#define CPUINFO_ZBB (1u << 2)
+#define CPUINFO_ZICOND  (1u << 3)
+
+/* Initialized with a constructor. */
+extern unsigned cpuinfo;
+
+/*
+ * We cannot rely on constructor ordering, so other constructors must
+ * use the function interface rather than the variable above.
+ */
+unsigned cpuinfo_init(void);
+
+#endif /* HOST_CPUINFO_H */
diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
index 2c1b680b93..1a347eaf6e 100644
--- a/tcg/riscv/tcg-target.h
+++ b/tcg/riscv/tcg-target.h
@@ -25,6 +25,8 @@
  #ifndef RISCV_TCG_TARGET_H
  #define RISCV_TCG_TARGET_H
  
+#include "host/cpuinfo.h"

+
  #define TCG_TARGET_INSN_UNIT_SIZE 4
  #define TCG_TARGET_NB_REGS 32
  #define MAX_CODE_GEN_BUFFER_SIZE  ((size_t)-1)
@@ -80,18 +82,12 @@ typedef enum {
  #define TCG_TARGET_CALL_ARG_I128TCG_CALL_ARG_NORMAL
  #define TCG_TARGET_CALL_RET_I128TCG_CALL_RET_NORMAL
  
-#if defined(__riscv_arch_test) && defined(__riscv_zbb)

-# define have_zbb true
-#else
-extern bool have_zbb;
-#endif
-
  /* optional instructions */
  #define TCG_TARGET_HAS_negsetcond_i32   1
  #define TCG_TARGET_HAS_div_i32  1
  #define TCG_TARGET_HAS_rem_i32  1
  #define TCG_TARGET_HAS_div2_i32 0
-#define TCG_TARGET_HAS_rot_i32  have_zbb
+#define TCG_TARGET_HAS_rot_i32  (cpuinfo & CPUINFO_ZBB)
  #define TCG_TARGET_HAS_deposit_i32  0
  #define TCG_TARGET_HAS_extract_i32  0
  #define TCG_TARGET_HAS_sextract_i32 0
@@ -106,17 +102,17 @@ extern bool have_zbb;
  #define TCG_TARGET_HAS_ext16s_i32   1
  #define TCG_TARGET_HAS_ext8u_i321
  #define TCG_TARGET_HAS_ext16u_i32   1
-#define TCG_TARGET_HAS_bswap16_i32  have_zbb
-#define TCG_TARGET_HAS_bswap32_i32  have_zbb
+#define TCG_TARGET_HAS_bswap16_i32  (cpuinfo & CPUINFO_ZBB)
+#define TCG_TARGET_HAS_bswap32_i32  (cpuinfo & CPUINFO_ZBB)
  #define TCG_TARGET_HAS_not_i32  1
-#define TCG_TARGET_HAS_andc_i32 have_zbb
-#define TCG_TARGET_HAS_orc_i32  have_zbb
-#define TCG_TARGET_HAS_eqv_i32  have_zbb
+#define TCG_TARGET_HAS_andc_i32 (cpuinfo & CPUINFO_ZBB)
+#define TCG_TARGET_HAS_orc_i32  (cpuinfo & CPUINFO_ZBB)
+#define TCG_TARGET_HAS_eqv_i32  (cpuinfo & CPUINFO_ZBB)
  #define TCG_TARGET_HAS_nand_i32 0
  #define TCG_TARGET_HAS_nor_i32  0
-#define TCG_TARGET_HAS_clz_i32  have_zbb
-#define TCG_TARGET_HAS_ctz_i32  have_zbb
-#define TCG_TARGET_HAS_ctpop_i32have_zbb
+#define TCG_TARGET_HAS_clz_i32  (cpuinfo & CPUINFO_ZBB)
+#define TCG_TARGET_HAS_ctz_i32  (cpuinfo & CPUINFO_ZBB)
+#define TCG_TARGET_HAS_ctpop_i32(cpuinfo & CPUINFO_ZBB)
  #define TCG_TARGET_HAS_brcond2  1
  #define TCG_TARGET_HAS_setcond2 1
  #define TCG_TARGET_HAS_qemu_st8_i32 0
@@ -125,7 +121,7 @@ extern bool have_zbb;
  #define TCG_TARGET_HAS_div_i64  1
  #define TCG_TARGET_HAS_rem_i64  1
  #define TCG_TARGET_HAS_div2_i64 0
-#define TCG_TARGET_HAS_rot_i64  have_zbb
+#define TCG_TARGET_HAS_rot_i64  (cpuinfo & CPUINFO_ZBB)
  #define TCG_TARGET_HAS_deposit_i64  0
  #define TCG_TARGET_HAS_extract_i64  0
  #define TCG_TARGET_HAS_sextract_i64 0
@@ -137,18 +133,18 @@ extern bool have_zbb;
  #define TCG_TARGET_HAS_ext8u_i641
  #define TCG_TARGET_HAS_ext16u_i64   1
  #define TCG_TARGET_HAS_ext32u_i64   1
-#define TCG_TARGET_HAS_bswap16_i64  have_zbb
-#define TCG_TARGET_HAS_bswap32_i64  have_zbb
-#define TCG_TARGET_HAS_bswap64_i64  have_zbb
+#define TCG_TARGET_HAS_bswap16_i64  (cpuinfo & CPUINFO_ZBB)
+#define TCG_TARGET_HAS_bswap32_i64  (cpuinfo & CPUINFO_ZBB)
+#define TCG_TARGET_HAS_bswap64_i64  (cpuinfo & CPUINFO_ZBB)
  #defin

Re: [PATCH 4/6] target/riscv: Detect sxl to set bit width for RV32 in RV64

2024-07-02 Thread LIU Zhiwei



On 2024/7/3 10:33, Alistair Francis wrote:

On Mon, Jul 1, 2024 at 1:41 PM LIU Zhiwei  wrote:

From: TANG Tiancheng 

Ensure correct bit width based on sxl when running RV32 on RV64 QEMU.
This is required as MMU address translations run in S-mode.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
---
  target/riscv/cpu_helper.c | 15 +++
  1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 6709622dd3..1af83a0a36 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -887,12 +887,14 @@ static int get_physical_address(CPURISCVState *env, 
hwaddr *physical,

  CPUState *cs = env_cpu(env);
  int va_bits = PGSHIFT + levels * ptidxbits + widened;
+int sxlen = 16UL << riscv_cpu_sxl(env);
+int sxlen_bytes = sxlen / 8;

  if (first_stage == true) {
  target_ulong mask, masked_msbs;

-if (TARGET_LONG_BITS > (va_bits - 1)) {
-mask = (1L << (TARGET_LONG_BITS - (va_bits - 1))) - 1;
+if (sxlen > (va_bits - 1)) {
+mask = (1L << (sxlen - (va_bits - 1))) - 1;
  } else {
  mask = 0;
  }
@@ -961,7 +963,7 @@ restart:

  int pmp_prot;
  int pmp_ret = get_physical_address_pmp(env, _prot, pte_addr,
-   sizeof(target_ulong),
+   sxlen_bytes,
 MMU_DATA_LOAD, PRV_S);
  if (pmp_ret != TRANSLATE_SUCCESS) {
  return TRANSLATE_PMP_FAIL;
@@ -1113,7 +1115,7 @@ restart:
   *   it is no longer valid and we must re-walk the page table.
   */
  MemoryRegion *mr;
-hwaddr l = sizeof(target_ulong), addr1;
+hwaddr l = sxlen_bytes, addr1;
  mr = address_space_translate(cs->as, pte_addr, , ,
   false, MEMTXATTRS_UNSPECIFIED);
  if (memory_region_is_ram(mr)) {
@@ -1126,6 +1128,11 @@ restart:
  *pte_pa = pte = updated_pte;
  #else
  target_ulong old_pte = qatomic_cmpxchg(pte_pa, pte, updated_pte);

I think you missed removing this line


Good catch.  We will fix this in v2 patch set.

Thanks,
Zhiwei



Alistair


+if (riscv_cpu_sxl(env) == MXL_RV32) {
+old_pte = qatomic_cmpxchg((uint32_t *)pte_pa, pte, 
updated_pte);
+} else {
+old_pte = qatomic_cmpxchg(pte_pa, pte, updated_pte);
+}
  if (old_pte != pte) {
  goto restart;
  }
--
2.43.0






[PATCH v3 05/11] target/riscv: Support Zama16b extension

2024-07-02 Thread LIU Zhiwei
Zama16b is the property that misaligned load/stores/atomics within
a naturally aligned 16-byte region are atomic.

According to the specification, Zama16b applies only to AMOs, loads
and stores defined in the base ISAs, and loads and stores of no more
than XLEN bits defined in the F, D, and Q extensions. Thus it should
not apply to zacas or RVC instructions.

For an instruction in that set, if all accessed bytes lie within 16B granule,
the instruction will not raise an exception for reasons of address alignment,
and the instruction will give rise to only one memory operation for the
purposes of RVWMO—i.e., it will execute atomically.

Signed-off-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.c  |  2 ++
 target/riscv/cpu_cfg.h  |  1 +
 target/riscv/insn_trans/trans_rva.c.inc | 42 ++---
 target/riscv/insn_trans/trans_rvd.c.inc | 14 +++--
 target/riscv/insn_trans/trans_rvf.c.inc | 14 +++--
 target/riscv/insn_trans/trans_rvi.c.inc |  6 
 6 files changed, 57 insertions(+), 22 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 1d1402775a..5219b44176 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -118,6 +118,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
 ISA_EXT_DATA_ENTRY(za64rs, PRIV_VERSION_1_12_0, has_priv_1_11),
 ISA_EXT_DATA_ENTRY(zaamo, PRIV_VERSION_1_12_0, ext_zaamo),
 ISA_EXT_DATA_ENTRY(zacas, PRIV_VERSION_1_12_0, ext_zacas),
+ISA_EXT_DATA_ENTRY(zama16b, PRIV_VERSION_1_13_0, ext_zama16b),
 ISA_EXT_DATA_ENTRY(zalrsc, PRIV_VERSION_1_12_0, ext_zalrsc),
 ISA_EXT_DATA_ENTRY(zawrs, PRIV_VERSION_1_12_0, ext_zawrs),
 ISA_EXT_DATA_ENTRY(zfa, PRIV_VERSION_1_12_0, ext_zfa),
@@ -1476,6 +1477,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
 MULTI_EXT_CFG_BOOL("zimop", ext_zimop, false),
 MULTI_EXT_CFG_BOOL("zcmop", ext_zcmop, false),
 MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false),
+MULTI_EXT_CFG_BOOL("zama16b", ext_zama16b, false),
 MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false),
 MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false),
 MULTI_EXT_CFG_BOOL("zawrs", ext_zawrs, true),
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index d85e54b475..ddbfae37e5 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -83,6 +83,7 @@ struct RISCVCPUConfig {
 bool ext_zdinx;
 bool ext_zaamo;
 bool ext_zacas;
+bool ext_zama16b;
 bool ext_zalrsc;
 bool ext_zawrs;
 bool ext_zfa;
diff --git a/target/riscv/insn_trans/trans_rva.c.inc 
b/target/riscv/insn_trans/trans_rva.c.inc
index 4a9e4591d1..eb080baddd 100644
--- a/target/riscv/insn_trans/trans_rva.c.inc
+++ b/target/riscv/insn_trans/trans_rva.c.inc
@@ -103,6 +103,12 @@ static bool gen_amo(DisasContext *ctx, arg_atomic *a,
 TCGv dest = dest_gpr(ctx, a->rd);
 TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE);
 
+if (ctx->cfg_ptr->ext_zama16b) {
+mop |= MO_ATOM_WITHIN16;
+} else {
+mop |= MO_ALIGN;
+}
+
 decode_save_opc(ctx);
 src1 = get_address(ctx, a->rs1, 0);
 func(dest, src1, src2, ctx->mem_idx, mop);
@@ -126,55 +132,55 @@ static bool trans_sc_w(DisasContext *ctx, arg_sc_w *a)
 static bool trans_amoswap_w(DisasContext *ctx, arg_amoswap_w *a)
 {
 REQUIRE_A_OR_ZAAMO(ctx);
-return gen_amo(ctx, a, _gen_atomic_xchg_tl, (MO_ALIGN | MO_TESL));
+return gen_amo(ctx, a, _gen_atomic_xchg_tl, MO_TESL);
 }
 
 static bool trans_amoadd_w(DisasContext *ctx, arg_amoadd_w *a)
 {
 REQUIRE_A_OR_ZAAMO(ctx);
-return gen_amo(ctx, a, _gen_atomic_fetch_add_tl, (MO_ALIGN | MO_TESL));
+return gen_amo(ctx, a, _gen_atomic_fetch_add_tl, MO_TESL);
 }
 
 static bool trans_amoxor_w(DisasContext *ctx, arg_amoxor_w *a)
 {
 REQUIRE_A_OR_ZAAMO(ctx);
-return gen_amo(ctx, a, _gen_atomic_fetch_xor_tl, (MO_ALIGN | MO_TESL));
+return gen_amo(ctx, a, _gen_atomic_fetch_xor_tl, MO_TESL);
 }
 
 static bool trans_amoand_w(DisasContext *ctx, arg_amoand_w *a)
 {
 REQUIRE_A_OR_ZAAMO(ctx);
-return gen_amo(ctx, a, _gen_atomic_fetch_and_tl, (MO_ALIGN | MO_TESL));
+return gen_amo(ctx, a, _gen_atomic_fetch_and_tl, MO_TESL);
 }
 
 static bool trans_amoor_w(DisasContext *ctx, arg_amoor_w *a)
 {
 REQUIRE_A_OR_ZAAMO(ctx);
-return gen_amo(ctx, a, _gen_atomic_fetch_or_tl, (MO_ALIGN | MO_TESL));
+return gen_amo(ctx, a, _gen_atomic_fetch_or_tl, MO_TESL);
 }
 
 static bool trans_amomin_w(DisasContext *ctx, arg_amomin_w *a)
 {
 REQUIRE_A_OR_ZAAMO(ctx);
-return gen_amo(ctx, a, _gen_atomic_fetch_smin_tl, (MO_ALIGN | 
MO_TESL));
+return gen_amo(ctx, a, _gen_atomic_fetch_smin_tl, MO_TESL);
 }
 
 static bool trans_amomax_w(DisasContext *ctx, arg_amomax_w *a)
 {
 REQUIRE_A_OR_ZAAMO(ctx);
-return gen_amo(ctx, a, _gen_atomic_fetch_smax_tl, (MO_ALIGN | 
MO_TESL));
+return gen_amo(ctx, a, 

[PATCH v3 11/11] disas/riscv: Support zabha disassemble

2024-07-02 Thread LIU Zhiwei
Signed-off-by: LIU Zhiwei 
Acked-by: Alistair Francis 
---
 disas/riscv.c | 60 +++
 1 file changed, 60 insertions(+)

diff --git a/disas/riscv.c b/disas/riscv.c
index 2e315b4936..05b663ebfe 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -954,6 +954,26 @@ typedef enum {
 rv_c_mop_11= 923,
 rv_c_mop_13= 924,
 rv_c_mop_15= 925,
+rv_op_amoswap_b = 926,
+rv_op_amoadd_b  = 927,
+rv_op_amoxor_b  = 928,
+rv_op_amoor_b   = 929,
+rv_op_amoand_b  = 930,
+rv_op_amomin_b  = 931,
+rv_op_amomax_b  = 932,
+rv_op_amominu_b = 933,
+rv_op_amomaxu_b = 934,
+rv_op_amoswap_h = 935,
+rv_op_amoadd_h  = 936,
+rv_op_amoxor_h  = 937,
+rv_op_amoor_h   = 938,
+rv_op_amoand_h  = 939,
+rv_op_amomin_h  = 940,
+rv_op_amomax_h  = 941,
+rv_op_amominu_h = 942,
+rv_op_amomaxu_h = 943,
+rv_op_amocas_b  = 944,
+rv_op_amocas_h  = 945,
 } rv_op;
 
 /* register names */
@@ -2192,6 +2212,26 @@ const rv_opcode_data rvi_opcode_data[] = {
 { "c.mop.11", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
 { "c.mop.13", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
 { "c.mop.15", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "amoswap.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoadd.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoxor.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoor.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoand.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amomin.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amomax.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amominu.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amomaxu.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoswap.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoadd.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoxor.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoor.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoand.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amomin.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amomax.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amominu.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amomaxu.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amocas.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amocas.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
 };
 
 /* CSR names */
@@ -2986,9 +3026,13 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa 
isa)
 case 11:
 switch (((inst >> 24) & 0b1000) |
 ((inst >> 12) & 0b0111)) {
+case 0: op = rv_op_amoadd_b; break;
+case 1: op = rv_op_amoadd_h; break;
 case 2: op = rv_op_amoadd_w; break;
 case 3: op = rv_op_amoadd_d; break;
 case 4: op = rv_op_amoadd_q; break;
+case 8: op = rv_op_amoswap_b; break;
+case 9: op = rv_op_amoswap_h; break;
 case 10: op = rv_op_amoswap_w; break;
 case 11: op = rv_op_amoswap_d; break;
 case 12: op = rv_op_amoswap_q; break;
@@ -3010,27 +3054,43 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa 
isa)
 case 26: op = rv_op_sc_w; break;
 case 27: op = rv_op_sc_d; break;
 case 28: op = rv_op_sc_q; break;
+case 32: op = rv_op_amoxor_b; break;
+case 33: op = rv_op_amoxor_h; break;
 case 34: op = rv_op_amoxor_w; break;
 case 35: op = rv_op_amoxor_d; break;
 case 36: op = rv_op_amoxor_q; break;
+case 40: op = rv_op_amocas_b; break;
+case 41: op = rv_op_amocas_h; break;
 case 42: op = rv_op_amocas_w; break;
 case 43: op = rv_op_amocas_d; break;
 case 44: op = rv_op_amocas_q; break;
+case 64: op = rv_op_amoor_b; break;
+case 65: op = rv_op_amoor_h; break;
 case 66: op = rv_op_amoor_w; break;
 case 67: op = rv_op_amoor_d; break;
 case 68: op = rv_op_amoor_q; break;
+case 96: op = rv_op_amoand_b; break;
+case 97: op = rv_op_amoand_h; break;
 case 98: op = rv_op_amoand_w; break;
 case 99: op = rv_op_amoand_d; break;
 case 100: op = rv_op_amoand_q; break;
+case 128: op = rv_op_amomin_b; break;
+  

[PATCH v3 10/11] target/riscv: Expose zabha extension as a cpu property

2024-07-02 Thread LIU Zhiwei
Signed-off-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 5219b44176..8cd52e6801 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -117,6 +117,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
 ISA_EXT_DATA_ENTRY(zmmul, PRIV_VERSION_1_12_0, ext_zmmul),
 ISA_EXT_DATA_ENTRY(za64rs, PRIV_VERSION_1_12_0, has_priv_1_11),
 ISA_EXT_DATA_ENTRY(zaamo, PRIV_VERSION_1_12_0, ext_zaamo),
+ISA_EXT_DATA_ENTRY(zabha, PRIV_VERSION_1_13_0, ext_zabha),
 ISA_EXT_DATA_ENTRY(zacas, PRIV_VERSION_1_12_0, ext_zacas),
 ISA_EXT_DATA_ENTRY(zama16b, PRIV_VERSION_1_13_0, ext_zama16b),
 ISA_EXT_DATA_ENTRY(zalrsc, PRIV_VERSION_1_12_0, ext_zalrsc),
@@ -1478,6 +1479,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
 MULTI_EXT_CFG_BOOL("zcmop", ext_zcmop, false),
 MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false),
 MULTI_EXT_CFG_BOOL("zama16b", ext_zama16b, false),
+MULTI_EXT_CFG_BOOL("zabha", ext_zabha, false),
 MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false),
 MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false),
 MULTI_EXT_CFG_BOOL("zawrs", ext_zawrs, true),
-- 
2.25.1




[PATCH v3 09/11] target/riscv: Add amocas.[b|h] for Zabha

2024-07-02 Thread LIU Zhiwei
Signed-off-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
---
 target/riscv/insn32.decode  |  2 ++
 target/riscv/insn_trans/trans_rvzabha.c.inc | 14 ++
 2 files changed, 16 insertions(+)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 8a4801d442..eee48f92d3 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -1041,3 +1041,5 @@ amomin_h   1 . . . . 001 . 010 
@atom_st
 amomax_h   10100 . . . . 001 . 010 @atom_st
 amominu_h  11000 . . . . 001 . 010 @atom_st
 amomaxu_h  11100 . . . . 001 . 010 @atom_st
+amocas_b00101 . . . . 000 . 010 @atom_st
+amocas_h00101 . . . . 001 . 010 @atom_st
diff --git a/target/riscv/insn_trans/trans_rvzabha.c.inc 
b/target/riscv/insn_trans/trans_rvzabha.c.inc
index 9093a1cfc1..ce8edcba62 100644
--- a/target/riscv/insn_trans/trans_rvzabha.c.inc
+++ b/target/riscv/insn_trans/trans_rvzabha.c.inc
@@ -129,3 +129,17 @@ static bool trans_amomaxu_h(DisasContext *ctx, 
arg_amomaxu_h *a)
 REQUIRE_ZABHA(ctx);
 return gen_amo(ctx, a, _gen_atomic_fetch_umax_tl, MO_TESW);
 }
+
+static bool trans_amocas_b(DisasContext *ctx, arg_amocas_b *a)
+{
+REQUIRE_ZACAS(ctx);
+REQUIRE_ZABHA(ctx);
+return gen_cmpxchg(ctx, a, MO_SB);
+}
+
+static bool trans_amocas_h(DisasContext *ctx, arg_amocas_h *a)
+{
+REQUIRE_ZACAS(ctx);
+REQUIRE_ZABHA(ctx);
+return gen_cmpxchg(ctx, a, MO_ALIGN | MO_TESW);
+}
-- 
2.25.1




[PATCH v3 08/11] target/riscv: Move gen_cmpxchg before adding amocas.[b|h]

2024-07-02 Thread LIU Zhiwei
Signed-off-by: LIU Zhiwei 
Acked-by: Alistair Francis 
---
 target/riscv/insn_trans/trans_rvzacas.c.inc | 13 -
 target/riscv/translate.c| 13 +
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rvzacas.c.inc 
b/target/riscv/insn_trans/trans_rvzacas.c.inc
index 5d274d4c08..fcced99fc7 100644
--- a/target/riscv/insn_trans/trans_rvzacas.c.inc
+++ b/target/riscv/insn_trans/trans_rvzacas.c.inc
@@ -22,19 +22,6 @@
 } \
 } while (0)
 
-static bool gen_cmpxchg(DisasContext *ctx, arg_atomic *a, MemOp mop)
-{
-TCGv dest = get_gpr(ctx, a->rd, EXT_NONE);
-TCGv src1 = get_address(ctx, a->rs1, 0);
-TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
-
-decode_save_opc(ctx);
-tcg_gen_atomic_cmpxchg_tl(dest, src1, dest, src2, ctx->mem_idx, mop);
-
-gen_set_gpr(ctx, a->rd, dest);
-return true;
-}
-
 static bool trans_amocas_w(DisasContext *ctx, arg_amocas_w *a)
 {
 REQUIRE_ZACAS(ctx);
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 4a3e786560..acba90f170 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -1099,6 +1099,19 @@ static bool gen_amo(DisasContext *ctx, arg_atomic *a,
 return true;
 }
 
+static bool gen_cmpxchg(DisasContext *ctx, arg_atomic *a, MemOp mop)
+{
+TCGv dest = get_gpr(ctx, a->rd, EXT_NONE);
+TCGv src1 = get_address(ctx, a->rs1, 0);
+TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
+
+decode_save_opc(ctx);
+tcg_gen_atomic_cmpxchg_tl(dest, src1, dest, src2, ctx->mem_idx, mop);
+
+gen_set_gpr(ctx, a->rd, dest);
+return true;
+}
+
 static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
 {
 DisasContext *ctx = container_of(dcbase, DisasContext, base);
-- 
2.25.1




[PATCH v3 07/11] target/riscv: Add AMO instructions for Zabha

2024-07-02 Thread LIU Zhiwei
Signed-off-by: LIU Zhiwei 
Acked-by: Alistair Francis 
---
 target/riscv/cpu_cfg.h  |   1 +
 target/riscv/insn32.decode  |  20 +++
 target/riscv/insn_trans/trans_rvzabha.c.inc | 131 
 target/riscv/translate.c|   4 +-
 4 files changed, 155 insertions(+), 1 deletion(-)
 create mode 100644 target/riscv/insn_trans/trans_rvzabha.c.inc

diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index ddbfae37e5..120905a254 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -84,6 +84,7 @@ struct RISCVCPUConfig {
 bool ext_zaamo;
 bool ext_zacas;
 bool ext_zama16b;
+bool ext_zabha;
 bool ext_zalrsc;
 bool ext_zawrs;
 bool ext_zfa;
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 972a1e8fd1..8a4801d442 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -1021,3 +1021,23 @@ amocas_q00101 . . . . 100 . 010 
@atom_st
 # *** Zimop may-be-operation extension ***
 mop_r_n 1 . 00 .. 0111 .. . 100 . 0111011 @mop5
 mop_rr_n1 . 00 .. 1 . . 100 . 0111011 @mop3
+
+# *** Zabhb Standard Extension ***
+amoswap_b  1 . . . . 000 . 010 @atom_st
+amoadd_b   0 . . . . 000 . 010 @atom_st
+amoxor_b   00100 . . . . 000 . 010 @atom_st
+amoand_b   01100 . . . . 000 . 010 @atom_st
+amoor_b01000 . . . . 000 . 010 @atom_st
+amomin_b   1 . . . . 000 . 010 @atom_st
+amomax_b   10100 . . . . 000 . 010 @atom_st
+amominu_b  11000 . . . . 000 . 010 @atom_st
+amomaxu_b  11100 . . . . 000 . 010 @atom_st
+amoswap_h  1 . . . . 001 . 010 @atom_st
+amoadd_h   0 . . . . 001 . 010 @atom_st
+amoxor_h   00100 . . . . 001 . 010 @atom_st
+amoand_h   01100 . . . . 001 . 010 @atom_st
+amoor_h01000 . . . . 001 . 010 @atom_st
+amomin_h   1 . . . . 001 . 010 @atom_st
+amomax_h   10100 . . . . 001 . 010 @atom_st
+amominu_h  11000 . . . . 001 . 010 @atom_st
+amomaxu_h  11100 . . . . 001 . 010 @atom_st
diff --git a/target/riscv/insn_trans/trans_rvzabha.c.inc 
b/target/riscv/insn_trans/trans_rvzabha.c.inc
new file mode 100644
index 00..9093a1cfc1
--- /dev/null
+++ b/target/riscv/insn_trans/trans_rvzabha.c.inc
@@ -0,0 +1,131 @@
+/*
+ * RISC-V translation routines for the Zabha Standard Extension.
+ *
+ * Copyright (c) 2024 Alibaba Group
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define REQUIRE_ZABHA(ctx) do {   \
+if (!ctx->cfg_ptr->ext_zabha) {   \
+return false; \
+} \
+} while (0)
+
+static bool trans_amoswap_b(DisasContext *ctx, arg_amoswap_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_xchg_tl, MO_SB);
+}
+
+static bool trans_amoadd_b(DisasContext *ctx, arg_amoadd_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_fetch_add_tl, MO_SB);
+}
+
+static bool trans_amoxor_b(DisasContext *ctx, arg_amoxor_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_fetch_xor_tl, MO_SB);
+}
+
+static bool trans_amoand_b(DisasContext *ctx, arg_amoand_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_fetch_and_tl, MO_SB);
+}
+
+static bool trans_amoor_b(DisasContext *ctx, arg_amoor_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_fetch_or_tl, MO_SB);
+}
+
+static bool trans_amomin_b(DisasContext *ctx, arg_amomin_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_fetch_smin_tl, MO_SB);
+}
+
+static bool trans_amomax_b(DisasContext *ctx, arg_amomax_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_fetch_smax_tl, MO_SB);
+}
+
+static bool trans_amominu_b(DisasContext *ctx, arg_amominu_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_fetch_umin_tl, MO_SB);
+}
+
+static bool trans_amomaxu_b(DisasContext *ctx, arg_amomaxu_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_fetch_umax_tl, MO_SB);
+}
+
+static bool trans_amoswap_h(DisasContext *ctx, arg_amoswap_h *a)
+{
+R

[PATCH v3 06/11] target/riscv: Move gen_amo before implement Zabha

2024-07-02 Thread LIU Zhiwei
Signed-off-by: LIU Zhiwei 
Acked-by: Alistair Francis 
---
 target/riscv/insn_trans/trans_rva.c.inc | 21 -
 target/riscv/translate.c| 21 +
 2 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rva.c.inc 
b/target/riscv/insn_trans/trans_rva.c.inc
index eb080baddd..39bbf60f3c 100644
--- a/target/riscv/insn_trans/trans_rva.c.inc
+++ b/target/riscv/insn_trans/trans_rva.c.inc
@@ -96,27 +96,6 @@ static bool gen_sc(DisasContext *ctx, arg_atomic *a, MemOp 
mop)
 return true;
 }
 
-static bool gen_amo(DisasContext *ctx, arg_atomic *a,
-void(*func)(TCGv, TCGv, TCGv, TCGArg, MemOp),
-MemOp mop)
-{
-TCGv dest = dest_gpr(ctx, a->rd);
-TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE);
-
-if (ctx->cfg_ptr->ext_zama16b) {
-mop |= MO_ATOM_WITHIN16;
-} else {
-mop |= MO_ALIGN;
-}
-
-decode_save_opc(ctx);
-src1 = get_address(ctx, a->rs1, 0);
-func(dest, src1, src2, ctx->mem_idx, mop);
-
-gen_set_gpr(ctx, a->rd, dest);
-return true;
-}
-
 static bool trans_lr_w(DisasContext *ctx, arg_lr_w *a)
 {
 REQUIRE_A_OR_ZALRSC(ctx);
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 8a546f4ece..133550d6e2 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -1077,6 +1077,27 @@ static bool gen_unary_per_ol(DisasContext *ctx, arg_r2 
*a, DisasExtend ext,
 return gen_unary(ctx, a, ext, f_tl);
 }
 
+static bool gen_amo(DisasContext *ctx, arg_atomic *a,
+void(*func)(TCGv, TCGv, TCGv, TCGArg, MemOp),
+MemOp mop)
+{
+TCGv dest = dest_gpr(ctx, a->rd);
+TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE);
+
+if (ctx->cfg_ptr->ext_zama16b) {
+mop |= MO_ATOM_WITHIN16;
+} else {
+mop |= MO_ALIGN;
+}
+
+decode_save_opc(ctx);
+src1 = get_address(ctx, a->rs1, 0);
+func(dest, src1, src2, ctx->mem_idx, mop);
+
+gen_set_gpr(ctx, a->rd, dest);
+return true;
+}
+
 static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
 {
 DisasContext *ctx = container_of(dcbase, DisasContext, base);
-- 
2.25.1




[PATCH v3 04/11] disas/riscv: Support zcmop disassemble

2024-07-02 Thread LIU Zhiwei
Although in QEMU disassemble, we usually lift compressed instruction
to an normal format when display the instruction name. For C.MOP.n,
it is more reasonable to directly display its compressed name, because
its behavior can be redefined by later extension.

Signed-off-by: LIU Zhiwei 
Acked-by: Alistair Francis 
Reviewed-by: Deepak Gupta 
---
 disas/riscv.c | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/disas/riscv.c b/disas/riscv.c
index 3ecbdcbe8d..2e315b4936 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -946,6 +946,14 @@ typedef enum {
 rv_mop_rr_5= 915,
 rv_mop_rr_6= 916,
 rv_mop_rr_7= 917,
+rv_c_mop_1 = 918,
+rv_c_mop_3 = 919,
+rv_c_mop_5 = 920,
+rv_c_mop_7 = 921,
+rv_c_mop_9 = 922,
+rv_c_mop_11= 923,
+rv_c_mop_13= 924,
+rv_c_mop_15= 925,
 } rv_op;
 
 /* register names */
@@ -2176,6 +2184,14 @@ const rv_opcode_data rvi_opcode_data[] = {
 { "mop.rr.5", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
 { "mop.rr.6", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
 { "mop.rr.7", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "c.mop.1",  rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.3",  rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.5",  rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.7",  rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.9",  rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.11", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.13", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.15", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
 };
 
 /* CSR names */
@@ -2532,6 +2548,13 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa 
isa)
 break;
 case 2: op = rv_op_c_li; break;
 case 3:
+if (dec->cfg->ext_zcmop) {
+if inst >> 2) & 0b11) == 0b10) &&
+(((inst >> 11) & 0b11) == 0b0)) {
+op = rv_c_mop_1 + ((inst >> 8) & 0b111);
+break;
+}
+}
 switch ((inst >> 7) & 0b1) {
 case 2: op = rv_op_c_addi16sp; break;
 default: op = rv_op_c_lui; break;
-- 
2.25.1




[PATCH v3 03/11] target/riscv: Add zcmop extension

2024-07-02 Thread LIU Zhiwei
Zcmop defines eight 16-bit MOP instructions named C.MOP.n, where n is
an odd integer between 1 and 15, inclusive. C.MOP.n is encoded in
the reserved encoding space corresponding to C.LUI xn, 0.

Unlike the MOPs defined in the Zimop extension, the C.MOP.n instructions
are defined to not write any register.

In current implementation, C.MOP.n only has an check function, without any
other more behavior.

Signed-off-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
Reviewed-by: Deepak Gupta 
---
 target/riscv/cpu.c  |  2 ++
 target/riscv/cpu_cfg.h  |  1 +
 target/riscv/insn16.decode  |  1 +
 target/riscv/insn_trans/trans_rvzcmop.c.inc | 29 +
 target/riscv/tcg/tcg-cpu.c  |  5 
 target/riscv/translate.c|  1 +
 6 files changed, 39 insertions(+)
 create mode 100644 target/riscv/insn_trans/trans_rvzcmop.c.inc

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index d3853a5804..1d1402775a 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -131,6 +131,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
 ISA_EXT_DATA_ENTRY(zcf, PRIV_VERSION_1_12_0, ext_zcf),
 ISA_EXT_DATA_ENTRY(zcd, PRIV_VERSION_1_12_0, ext_zcd),
 ISA_EXT_DATA_ENTRY(zce, PRIV_VERSION_1_12_0, ext_zce),
+ISA_EXT_DATA_ENTRY(zcmop, PRIV_VERSION_1_13_0, ext_zcmop),
 ISA_EXT_DATA_ENTRY(zcmp, PRIV_VERSION_1_12_0, ext_zcmp),
 ISA_EXT_DATA_ENTRY(zcmt, PRIV_VERSION_1_12_0, ext_zcmt),
 ISA_EXT_DATA_ENTRY(zba, PRIV_VERSION_1_12_0, ext_zba),
@@ -1473,6 +1474,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
 MULTI_EXT_CFG_BOOL("zihintntl", ext_zihintntl, true),
 MULTI_EXT_CFG_BOOL("zihintpause", ext_zihintpause, true),
 MULTI_EXT_CFG_BOOL("zimop", ext_zimop, false),
+MULTI_EXT_CFG_BOOL("zcmop", ext_zcmop, false),
 MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false),
 MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false),
 MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false),
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index 9f53512053..d85e54b475 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -72,6 +72,7 @@ struct RISCVCPUConfig {
 bool ext_zihintpause;
 bool ext_zihpm;
 bool ext_zimop;
+bool ext_zcmop;
 bool ext_ztso;
 bool ext_smstateen;
 bool ext_sstc;
diff --git a/target/riscv/insn16.decode b/target/riscv/insn16.decode
index b96c534e73..3953bcf82d 100644
--- a/target/riscv/insn16.decode
+++ b/target/riscv/insn16.decode
@@ -140,6 +140,7 @@ sw110  ... ... .. ... 00 @cs_w
 addi  000 .  .  . 01 @ci
 addi  010 .  .  . 01 @c_li
 {
+  c_mop_n 011 0 0 n:3 1 0 01
   illegal 011 0  -  0 01 # c.addi16sp and c.lui, RES nzimm=0
   addi011 .  00010  . 01 @c_addi16sp
   lui 011 .  .  . 01 @c_lui
diff --git a/target/riscv/insn_trans/trans_rvzcmop.c.inc 
b/target/riscv/insn_trans/trans_rvzcmop.c.inc
new file mode 100644
index 00..7205586508
--- /dev/null
+++ b/target/riscv/insn_trans/trans_rvzcmop.c.inc
@@ -0,0 +1,29 @@
+/*
+ * RISC-V translation routines for compressed May-Be-Operation(zcmop).
+ *
+ * Copyright (c) 2024 Alibaba Group.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define REQUIRE_ZCMOP(ctx) do {   \
+if (!ctx->cfg_ptr->ext_zcmop) {   \
+return false; \
+} \
+} while (0)
+
+static bool trans_c_mop_n(DisasContext *ctx, arg_c_mop_n *a)
+{
+REQUIRE_ZCMOP(ctx);
+return true;
+}
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index ae25686824..28cc3f80a9 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -547,6 +547,11 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, 
Error **errp)
 }
 }
 
+if (cpu->cfg.ext_zcmop && !cpu->cfg.ext_zca) {
+error_setg(errp, "Zcmop extensions require Zca");
+return;
+}
+
 if (mcc->misa_mxl_max != MXL_RV32 && cpu->cfg.ext_zcf) {
 error_setg(errp, "Zcf extension is only relevant to RV32");
 return;
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 379b68289

[PATCH v3 02/11] disas/riscv: Support zimop disassemble

2024-07-02 Thread LIU Zhiwei
Signed-off-by: LIU Zhiwei 
Acked-by: Alistair Francis 
Reviewed-by: Deepak Gupta 
---
 disas/riscv.c | 100 ++
 1 file changed, 100 insertions(+)

diff --git a/disas/riscv.c b/disas/riscv.c
index 90d6b26de9..3ecbdcbe8d 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -906,6 +906,46 @@ typedef enum {
 rv_op_amocas_w = 875,
 rv_op_amocas_d = 876,
 rv_op_amocas_q = 877,
+rv_mop_r_0 = 878,
+rv_mop_r_1 = 879,
+rv_mop_r_2 = 880,
+rv_mop_r_3 = 881,
+rv_mop_r_4 = 882,
+rv_mop_r_5 = 883,
+rv_mop_r_6 = 884,
+rv_mop_r_7 = 885,
+rv_mop_r_8 = 886,
+rv_mop_r_9 = 887,
+rv_mop_r_10= 888,
+rv_mop_r_11= 889,
+rv_mop_r_12= 890,
+rv_mop_r_13= 891,
+rv_mop_r_14= 892,
+rv_mop_r_15= 893,
+rv_mop_r_16= 894,
+rv_mop_r_17= 895,
+rv_mop_r_18= 896,
+rv_mop_r_19= 897,
+rv_mop_r_20= 898,
+rv_mop_r_21= 899,
+rv_mop_r_22= 900,
+rv_mop_r_23= 901,
+rv_mop_r_24= 902,
+rv_mop_r_25= 903,
+rv_mop_r_26= 904,
+rv_mop_r_27= 905,
+rv_mop_r_28= 906,
+rv_mop_r_29= 907,
+rv_mop_r_30= 908,
+rv_mop_r_31= 909,
+rv_mop_rr_0= 910,
+rv_mop_rr_1= 911,
+rv_mop_rr_2= 912,
+rv_mop_rr_3= 913,
+rv_mop_rr_4= 914,
+rv_mop_rr_5= 915,
+rv_mop_rr_6= 916,
+rv_mop_rr_7= 917,
 } rv_op;
 
 /* register names */
@@ -2096,6 +2136,46 @@ const rv_opcode_data rvi_opcode_data[] = {
 { "amocas.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
 { "amocas.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
 { "amocas.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "mop.r.0", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.1", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.2", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.3", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.4", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.5", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.6", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.7", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.8", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.9", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.10", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.11", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.12", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.13", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.14", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.15", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.16", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.17", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.18", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.19", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.20", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.21", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.22", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.23", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.24", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.25", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.26", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.27", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.28", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.29", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.30", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.31", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.rr.0", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.1", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.2", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.3", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.4", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.5", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.6", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.7", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
 };
 
 /* CSR names */
@@ -3008,6 +3088,26 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa 
isa)
 break;
 case 13: op = rv_op_lui; break;
 case 14:
+if (dec->cfg->ext_zimop) {
+int imm_mop5, imm_mop3;
+ 

[PATCH v3 00/11] target/riscv: Support zimop/zcmop/zama16b/zabha

2024-07-02 Thread LIU Zhiwei
All the patches in this patch set have been reviewed or acked.

v2->v3:
1. Add review tags.
2. Reword the patch 10 in commit log

v1->v2:
1. Fix the isa orders.
2. Make zimop/zcmop/zama16b/zabha depend on priviledged 1.13
3. Add review tags.

The v2 patch set is here
https://mail.gnu.org/archive/html/qemu-riscv/2024-06/msg00489.html

The v1 patch set is here
1. zimop/zcmop
https://mail.gnu.org/archive/html/qemu-riscv/2024-05/msg00207.html
2. zama16b
https://mail.gnu.org/archive/html/qemu-riscv/2024-05/msg00212.html
3. zabha
https://mail.gnu.org/archive/html/qemu-riscv/2024-05/msg00214.html

LIU Zhiwei (11):
  target/riscv: Add zimop extension
  disas/riscv: Support zimop disassemble
  target/riscv: Add zcmop extension
  disas/riscv: Support zcmop disassemble
  target/riscv: Support Zama16b extension
  target/riscv: Move gen_amo before implement Zabha
  target/riscv: Add AMO instructions for Zabha
  target/riscv: Move gen_cmpxchg before adding amocas.[b|h]
  target/riscv: Add amocas.[b|h] for Zabha
  target/riscv: Expose zabha extension as a cpu property
  disas/riscv: Support zabha disassemble

 disas/riscv.c   | 183 
 target/riscv/cpu.c  |   8 +
 target/riscv/cpu_cfg.h  |   4 +
 target/riscv/insn16.decode  |   1 +
 target/riscv/insn32.decode  |  33 
 target/riscv/insn_trans/trans_rva.c.inc |  51 ++
 target/riscv/insn_trans/trans_rvd.c.inc |  14 +-
 target/riscv/insn_trans/trans_rvf.c.inc |  14 +-
 target/riscv/insn_trans/trans_rvi.c.inc |   6 +
 target/riscv/insn_trans/trans_rvzabha.c.inc | 145 
 target/riscv/insn_trans/trans_rvzacas.c.inc |  13 --
 target/riscv/insn_trans/trans_rvzcmop.c.inc |  29 
 target/riscv/insn_trans/trans_rvzimop.c.inc |  37 
 target/riscv/tcg/tcg-cpu.c  |   5 +
 target/riscv/translate.c|  38 
 15 files changed, 531 insertions(+), 50 deletions(-)
 create mode 100644 target/riscv/insn_trans/trans_rvzabha.c.inc
 create mode 100644 target/riscv/insn_trans/trans_rvzcmop.c.inc
 create mode 100644 target/riscv/insn_trans/trans_rvzimop.c.inc

-- 
2.25.1




[PATCH v3 01/11] target/riscv: Add zimop extension

2024-07-02 Thread LIU Zhiwei
Zimop extension defines an encoding space for 40 MOPs.The Zimop
extension defines 32 MOP instructions named MOP.R.n, where n is
an integer between 0 and 31, inclusive. The Zimop extension
additionally defines 8 MOP instructions named MOP.RR.n, where n
is an integer between 0 and 7.

These 40 MOPs initially are defined to simply write zero to x[rd],
but are designed to be redefined by later extensions to perform some
other action.

Signed-off-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
Reviewed-by: Deepak Gupta 
---
 target/riscv/cpu.c  |  2 ++
 target/riscv/cpu_cfg.h  |  1 +
 target/riscv/insn32.decode  | 11 ++
 target/riscv/insn_trans/trans_rvzimop.c.inc | 37 +
 target/riscv/translate.c|  1 +
 5 files changed, 52 insertions(+)
 create mode 100644 target/riscv/insn_trans/trans_rvzimop.c.inc

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index a2640cf259..d3853a5804 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -113,6 +113,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
 ISA_EXT_DATA_ENTRY(zihintntl, PRIV_VERSION_1_10_0, ext_zihintntl),
 ISA_EXT_DATA_ENTRY(zihintpause, PRIV_VERSION_1_10_0, ext_zihintpause),
 ISA_EXT_DATA_ENTRY(zihpm, PRIV_VERSION_1_12_0, ext_zihpm),
+ISA_EXT_DATA_ENTRY(zimop, PRIV_VERSION_1_13_0, ext_zimop),
 ISA_EXT_DATA_ENTRY(zmmul, PRIV_VERSION_1_12_0, ext_zmmul),
 ISA_EXT_DATA_ENTRY(za64rs, PRIV_VERSION_1_12_0, has_priv_1_11),
 ISA_EXT_DATA_ENTRY(zaamo, PRIV_VERSION_1_12_0, ext_zaamo),
@@ -1471,6 +1472,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
 MULTI_EXT_CFG_BOOL("zicsr", ext_zicsr, true),
 MULTI_EXT_CFG_BOOL("zihintntl", ext_zihintntl, true),
 MULTI_EXT_CFG_BOOL("zihintpause", ext_zihintpause, true),
+MULTI_EXT_CFG_BOOL("zimop", ext_zimop, false),
 MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false),
 MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false),
 MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false),
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index fb7eebde52..9f53512053 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -71,6 +71,7 @@ struct RISCVCPUConfig {
 bool ext_zihintntl;
 bool ext_zihintpause;
 bool ext_zihpm;
+bool ext_zimop;
 bool ext_ztso;
 bool ext_smstateen;
 bool ext_sstc;
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index f22df04cfd..972a1e8fd1 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -38,6 +38,8 @@
 %imm_bs   30:2   !function=ex_shift_3
 %imm_rnum 20:4
 %imm_z6   26:1 15:5
+%imm_mop5 30:1 26:2 20:2
+%imm_mop3 30:1 26:2
 
 # Argument sets:
 
@@ -56,6 +58,8 @@
 vm rd rs1 nf
  vm rd rs1 rs2 nf
 _aes shamt rs2 rs1 rd
+ imm rd rs1
+ imm rd rs1 rs2
 
 # Formats 32:
 @r   ...   . . ... . ... %rs2 %rs1 
%rd
@@ -98,6 +102,9 @@
 @k_aes   .. . . .  ... . ... _aes  shamt=%imm_bs   %rs2 
%rs1 %rd
 @i_aes   .. . . .  ... . ...   imm=%imm_rnum
%rs1 %rd
 
+@mop5 . . .. ..  .. . ... . ...  imm=%imm_mop5 %rd %rs1
+@mop3 . . .. .. . . . ... . ...  imm=%imm_mop3 %rd %rs1 
%rs2
+
 # Formats 64:
 @sh5 ...  . .  ... . ...   shamt=%sh5  %rs1 
%rd
 
@@ -1010,3 +1017,7 @@ amocas_w00101 . . . . 010 . 010 
@atom_st
 amocas_d00101 . . . . 011 . 010 @atom_st
 # *** RV64 Zacas Standard Extension ***
 amocas_q00101 . . . . 100 . 010 @atom_st
+
+# *** Zimop may-be-operation extension ***
+mop_r_n 1 . 00 .. 0111 .. . 100 . 0111011 @mop5
+mop_rr_n1 . 00 .. 1 . . 100 . 0111011 @mop3
diff --git a/target/riscv/insn_trans/trans_rvzimop.c.inc 
b/target/riscv/insn_trans/trans_rvzimop.c.inc
new file mode 100644
index 00..165aacd2b6
--- /dev/null
+++ b/target/riscv/insn_trans/trans_rvzimop.c.inc
@@ -0,0 +1,37 @@
+/*
+ * RISC-V translation routines for May-Be-Operation(zimop).
+ *
+ * Copyright (c) 2024 Alibaba Group.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define REQUIRE_ZIMOP(ctx) do {   \
+if (!ctx->cfg_ptr->ext_zimop) {   \
+return false;

Re: [PATCH 3/6] target/riscv: Correct SXL return value for RV32 in RV64 QEMU

2024-07-01 Thread LIU Zhiwei


On 2024/7/1 23:10, Philippe Mathieu-Daudé wrote:

Hi Tiancheng, Zhiwei,

On 1/7/24 05:37, LIU Zhiwei wrote:

From: TANG Tiancheng 

Ensure that riscv_cpu_sxl returns MXL_RV32 when runningRV32 in an
RV64 QEMU.

Signed-off-by: TANG Tiancheng 
Fixes: 05e6ca5e156 ("target/riscv: Ignore reserved bits in PTE for 
RV64")

Reviewed-by: Liu Zhiwei 
---
  target/riscv/cpu.h | 5 -
  1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 6fe0d712b4..36a712044a 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -668,8 +668,11 @@ static inline RISCVMXL 
riscv_cpu_sxl(CPURISCVState *env)

  #ifdef CONFIG_USER_ONLY
  return env->misa_mxl;
  #else
-    return get_field(env->mstatus, MSTATUS64_SXL);
+    if (env->misa_mxl != MXL_RV32) {
+    return get_field(env->mstatus, MSTATUS64_SXL);
+    }
  #endif
+    return MXL_RV32;


Can we simplify the previous TARGET_RISCV32 ifdef'ry?


I think you mean the TARGET_RISCV32 macro here:

#ifdef TARGET_RISCV32
#define riscv_cpu_sxl(env)  ((void)(env), MXL_RV32)
#else
static inline RISCVMXL riscv_cpu_sxl(CPURISCVState *env)
{
#ifdef CONFIG_USER_ONLY
    return env->misa_mxl;
#else
    return get_field(env->mstatus, MSTATUS64_SXL);
#endif
}
#endif

I think it is better to keep it here for better performance(as a constant).

If you mean whether we  can simplify all the ifdef TARGET_RISCV32 in 
target/riscv or hw/riscv, IMHO, it depends. I git grep the 
TARGET_RISCV32 from target/riscv:


target/riscv/cpu-param.h:#elif defined(TARGET_RISCV32)

target/riscv/cpu.c:#ifdef TARGET_RISCV32

target/riscv/cpu.c:#if defined(TARGET_RISCV32)

target/riscv/cpu.h:#if defined(TARGET_RISCV32)

target/riscv/cpu.h:#ifdef TARGET_RISCV32

target/riscv/cpu.h:#if defined(TARGET_RISCV32)

target/riscv/cpu.h:#if defined(TARGET_RISCV32)

target/riscv/cpu.h:#ifdef TARGET_RISCV32

target/riscv/insn_trans/trans_rvzacas.c.inc:#ifdef TARGET_RISCV32

target/riscv/kvm/kvm-cpu.c:#if defined(TARGET_RISCV32)

target/riscv/translate.c:#ifdef TARGET_RISCV32

target/riscv/translate.c:#ifdef TARGET_RISCV32

target/riscv/translate.c:#ifdef TARGET_RISCV32

target/riscv/translate.c:#ifdef TARGET_RISCV32

target/riscv/translate.c:#ifdef TARGET_RISCV32

target/riscv/translate.c:#ifdef TARGET_RISCV32

target/riscv/translate.c:#ifdef TARGET_RISCV32

One case we can remove the TARGET_RISCV32 is in translate.c.

static void gen_set_fpr_hs(DisasContext *ctx, int reg_num, TCGv_i64 t)

{

    if (!ctx->cfg_ptr->ext_zfinx) {

    tcg_gen_mov_i64(cpu_fpr[reg_num], t);

    return;

    }

    if (reg_num != 0) {

    switch (get_xl(ctx)) {

    case MXL_RV32:

#ifdef TARGET_RISCV32

    tcg_gen_extrl_i64_i32(cpu_gpr[reg_num], t);

    break;

#else

    /* fall through */

    case MXL_RV64:

    tcg_gen_mov_i64(cpu_gpr[reg_num], t);

    break;

#endif

    default:

    g_assert_not_reached();

    }

    }

}

We can simplify this code by tcg_gen_trunc_i64_tl.

One case we can't remove the TARGET_RISCV32 is in cpu.c, where we define 
any or max cpu with the width depending on this macro.
I don't analyze all TARGET_RISCV32 using here.  We will upstream a 
standalone patch for validating all its using later.


Thanks,
Zhiwei




  }
  #endif

[PATCH 6/6] target/riscv: Enable RV32 CPU support in RV64 QEMU

2024-06-30 Thread LIU Zhiwei
From: TANG Tiancheng 

Add gdb XML files and adjust CPU initialization to allow running RV32 CPUs
in RV64 QEMU.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
---
 configs/targets/riscv64-softmmu.mak |  2 +-
 target/riscv/cpu.c  | 17 +
 2 files changed, 14 insertions(+), 5 deletions(-)

diff --git a/configs/targets/riscv64-softmmu.mak 
b/configs/targets/riscv64-softmmu.mak
index f688ffa7bc..5c1abb4b51 100644
--- a/configs/targets/riscv64-softmmu.mak
+++ b/configs/targets/riscv64-softmmu.mak
@@ -1,6 +1,6 @@
 TARGET_ARCH=riscv64
 TARGET_BASE_ARCH=riscv
 TARGET_SUPPORTS_MTTCG=y
-TARGET_XML_FILES= gdb-xml/riscv-64bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml 
gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-64bit-virtual.xml
+TARGET_XML_FILES= gdb-xml/riscv-64bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml 
gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-64bit-virtual.xml 
gdb-xml/riscv-32bit-cpu.xml gdb-xml/riscv-32bit-virtual.xml
 # needed by boot.c
 TARGET_NEED_FDT=y
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 69a08e8c2c..58165901a2 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -630,8 +630,10 @@ static void rv64e_bare_cpu_init(Object *obj)
 riscv_cpu_set_misa_ext(env, RVE);
 }
 
-#else /* !TARGET_RISCV64 */
+#endif /* !TARGET_RISCV64 */
 
+#if defined(TARGET_RISCV32) || \
+(defined(TARGET_RISCV64) && !defined(CONFIG_USER_ONLY))
 static void rv32_base_cpu_init(Object *obj)
 {
 RISCVCPU *cpu = RISCV_CPU(obj);
@@ -2544,6 +2546,13 @@ static const TypeInfo riscv_cpu_type_infos[] = {
 #if defined(TARGET_RISCV32)
 DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,   MXL_RV32,  
riscv_any_cpu_init),
 DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,   MXL_RV32,  
riscv_max_cpu_init),
+#elif defined(TARGET_RISCV64)
+DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,   MXL_RV64,  
riscv_any_cpu_init),
+DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,   MXL_RV64,  
riscv_max_cpu_init),
+#endif
+
+#if defined(TARGET_RISCV32) || \
+(defined(TARGET_RISCV64) && !defined(CONFIG_USER_ONLY))
 DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE32,MXL_RV32,  
rv32_base_cpu_init),
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_IBEX,   MXL_RV32,  
rv32_ibex_cpu_init),
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E31, MXL_RV32,  
rv32_sifive_e_cpu_init),
@@ -2551,9 +2560,9 @@ static const TypeInfo riscv_cpu_type_infos[] = {
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U34, MXL_RV32,  
rv32_sifive_u_cpu_init),
 DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV32I,MXL_RV32,  
rv32i_bare_cpu_init),
 DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV32E,MXL_RV32,  
rv32e_bare_cpu_init),
-#elif defined(TARGET_RISCV64)
-DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,   MXL_RV64,  
riscv_any_cpu_init),
-DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,   MXL_RV64,  
riscv_max_cpu_init),
+#endif
+
+#if defined(TARGET_RISCV64)
 DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE64,MXL_RV64,  
rv64_base_cpu_init),
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E51, MXL_RV64,  
rv64_sifive_e_cpu_init),
 DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U54, MXL_RV64,  
rv64_sifive_u_cpu_init),
-- 
2.43.0




[PATCH 5/6] target/riscv: Correct mcause/scause bit width for RV32 in RV64 QEMU

2024-06-30 Thread LIU Zhiwei
From: TANG Tiancheng 

Ensure mcause high bit is correctly set by using 32-bit width for RV32
mode and 64-bit width for RV64 mode.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
---
 target/riscv/cpu_helper.c | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 1af83a0a36..88a187c10a 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -1673,6 +1673,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 target_ulong tinst = 0;
 target_ulong htval = 0;
 target_ulong mtval2 = 0;
+int sxlen = 0;
+int mxlen = 0;
 
 if (!async) {
 /* set tval to badaddr for traps with address information */
@@ -1799,7 +1801,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 s = set_field(s, MSTATUS_SPP, env->priv);
 s = set_field(s, MSTATUS_SIE, 0);
 env->mstatus = s;
-env->scause = cause | ((target_ulong)async << (TARGET_LONG_BITS - 1));
+sxlen = 16UL << riscv_cpu_sxl(env);
+env->scause = cause | ((target_ulong)async << (sxlen - 1));
 env->sepc = env->pc;
 env->stval = tval;
 env->htval = htval;
@@ -1830,7 +1833,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 s = set_field(s, MSTATUS_MPP, env->priv);
 s = set_field(s, MSTATUS_MIE, 0);
 env->mstatus = s;
-env->mcause = cause | ~(((target_ulong)-1) >> async);
+mxlen = 16UL << riscv_cpu_mxl(env);
+env->mcause = cause | ((target_ulong)async << (mxlen - 1));
 env->mepc = env->pc;
 env->mtval = tval;
 env->mtval2 = mtval2;
-- 
2.43.0




[PATCH 4/6] target/riscv: Detect sxl to set bit width for RV32 in RV64

2024-06-30 Thread LIU Zhiwei
From: TANG Tiancheng 

Ensure correct bit width based on sxl when running RV32 on RV64 QEMU.
This is required as MMU address translations run in S-mode.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
---
 target/riscv/cpu_helper.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 6709622dd3..1af83a0a36 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -887,12 +887,14 @@ static int get_physical_address(CPURISCVState *env, 
hwaddr *physical,
 
 CPUState *cs = env_cpu(env);
 int va_bits = PGSHIFT + levels * ptidxbits + widened;
+int sxlen = 16UL << riscv_cpu_sxl(env);
+int sxlen_bytes = sxlen / 8;
 
 if (first_stage == true) {
 target_ulong mask, masked_msbs;
 
-if (TARGET_LONG_BITS > (va_bits - 1)) {
-mask = (1L << (TARGET_LONG_BITS - (va_bits - 1))) - 1;
+if (sxlen > (va_bits - 1)) {
+mask = (1L << (sxlen - (va_bits - 1))) - 1;
 } else {
 mask = 0;
 }
@@ -961,7 +963,7 @@ restart:
 
 int pmp_prot;
 int pmp_ret = get_physical_address_pmp(env, _prot, pte_addr,
-   sizeof(target_ulong),
+   sxlen_bytes,
MMU_DATA_LOAD, PRV_S);
 if (pmp_ret != TRANSLATE_SUCCESS) {
 return TRANSLATE_PMP_FAIL;
@@ -1113,7 +1115,7 @@ restart:
  *   it is no longer valid and we must re-walk the page table.
  */
 MemoryRegion *mr;
-hwaddr l = sizeof(target_ulong), addr1;
+hwaddr l = sxlen_bytes, addr1;
 mr = address_space_translate(cs->as, pte_addr, , ,
  false, MEMTXATTRS_UNSPECIFIED);
 if (memory_region_is_ram(mr)) {
@@ -1126,6 +1128,11 @@ restart:
 *pte_pa = pte = updated_pte;
 #else
 target_ulong old_pte = qatomic_cmpxchg(pte_pa, pte, updated_pte);
+if (riscv_cpu_sxl(env) == MXL_RV32) {
+old_pte = qatomic_cmpxchg((uint32_t *)pte_pa, pte, 
updated_pte);
+} else {
+old_pte = qatomic_cmpxchg(pte_pa, pte, updated_pte);
+}
 if (old_pte != pte) {
 goto restart;
 }
-- 
2.43.0




[PATCH 3/6] target/riscv: Correct SXL return value for RV32 in RV64 QEMU

2024-06-30 Thread LIU Zhiwei
From: TANG Tiancheng 

Ensure that riscv_cpu_sxl returns MXL_RV32 when runningRV32 in an
RV64 QEMU.

Signed-off-by: TANG Tiancheng 
Fixes: 05e6ca5e156 ("target/riscv: Ignore reserved bits in PTE for RV64")
Reviewed-by: Liu Zhiwei 
---
 target/riscv/cpu.h | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 6fe0d712b4..36a712044a 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -668,8 +668,11 @@ static inline RISCVMXL riscv_cpu_sxl(CPURISCVState *env)
 #ifdef CONFIG_USER_ONLY
 return env->misa_mxl;
 #else
-return get_field(env->mstatus, MSTATUS64_SXL);
+if (env->misa_mxl != MXL_RV32) {
+return get_field(env->mstatus, MSTATUS64_SXL);
+}
 #endif
+return MXL_RV32;
 }
 #endif
 
-- 
2.43.0




[PATCH 2/6] target/riscv: Adjust PMP size for no-MMU RV64 QEMU running RV32

2024-06-30 Thread LIU Zhiwei
From: TANG Tiancheng 

Ensure pmp_size is correctly determined using mxl for RV32
in RV64 QEMU.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
---
 target/riscv/pmp.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
index 9eea397e72..f65aa3dba7 100644
--- a/target/riscv/pmp.c
+++ b/target/riscv/pmp.c
@@ -326,7 +326,7 @@ bool pmp_hart_has_privs(CPURISCVState *env, hwaddr addr,
  */
 pmp_size = -(addr | TARGET_PAGE_MASK);
 } else {
-pmp_size = sizeof(target_ulong);
+pmp_size = 2UL << riscv_cpu_mxl(env);
 }
 } else {
 pmp_size = size;
-- 
2.43.0




[PATCH 1/6] target/riscv: Add fw_dynamic_info32 for booting RV32 OpenSBI

2024-06-30 Thread LIU Zhiwei
From: TANG Tiancheng 

RV32 OpenSBI need a fw_dynamic_info parameter with 32-bit fields instead
of target_ulong.

In RV64 QEMU, target_ulong is 64. So it is not right for booting RV32 OpenSBI.
We create a fw_dynmaic_info32 struct for this purpose.

Signed-off-by: TANG Tiancheng 
Reviewed-by: Liu Zhiwei 
---
 hw/riscv/boot.c | 35 ++---
 hw/riscv/sifive_u.c |  3 ++-
 include/hw/riscv/boot.h |  4 +++-
 include/hw/riscv/boot_opensbi.h | 29 +++
 4 files changed, 57 insertions(+), 14 deletions(-)

diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
index 47281ca853..1a2c1ff9e0 100644
--- a/hw/riscv/boot.c
+++ b/hw/riscv/boot.c
@@ -342,27 +342,33 @@ void riscv_load_fdt(hwaddr fdt_addr, void *fdt)
 rom_ptr_for_as(_space_memory, fdt_addr, 
fdtsize));
 }
 
-void riscv_rom_copy_firmware_info(MachineState *machine, hwaddr rom_base,
-  hwaddr rom_size, uint32_t reset_vec_size,
+void riscv_rom_copy_firmware_info(MachineState *machine,
+  RISCVHartArrayState *harts,
+  hwaddr rom_base, hwaddr rom_size,
+  uint32_t reset_vec_size,
   uint64_t kernel_entry)
 {
+struct fw_dynamic_info32 dinfo32;
 struct fw_dynamic_info dinfo;
 size_t dinfo_len;
 
-if (sizeof(dinfo.magic) == 4) {
-dinfo.magic = cpu_to_le32(FW_DYNAMIC_INFO_MAGIC_VALUE);
-dinfo.version = cpu_to_le32(FW_DYNAMIC_INFO_VERSION);
-dinfo.next_mode = cpu_to_le32(FW_DYNAMIC_INFO_NEXT_MODE_S);
-dinfo.next_addr = cpu_to_le32(kernel_entry);
+if (riscv_is_32bit(harts)) {
+dinfo32.magic = cpu_to_le32(FW_DYNAMIC_INFO_MAGIC_VALUE);
+dinfo32.version = cpu_to_le32(FW_DYNAMIC_INFO_VERSION);
+dinfo32.next_mode = cpu_to_le32(FW_DYNAMIC_INFO_NEXT_MODE_S);
+dinfo32.next_addr = cpu_to_le32(kernel_entry);
+dinfo32.options = 0;
+dinfo32.boot_hart = 0;
+dinfo_len = sizeof(dinfo32);
 } else {
 dinfo.magic = cpu_to_le64(FW_DYNAMIC_INFO_MAGIC_VALUE);
 dinfo.version = cpu_to_le64(FW_DYNAMIC_INFO_VERSION);
 dinfo.next_mode = cpu_to_le64(FW_DYNAMIC_INFO_NEXT_MODE_S);
 dinfo.next_addr = cpu_to_le64(kernel_entry);
+dinfo.options = 0;
+dinfo.boot_hart = 0;
+dinfo_len = sizeof(dinfo);
 }
-dinfo.options = 0;
-dinfo.boot_hart = 0;
-dinfo_len = sizeof(dinfo);
 
 /**
  * copy the dynamic firmware info. This information is specific to
@@ -374,7 +380,10 @@ void riscv_rom_copy_firmware_info(MachineState *machine, 
hwaddr rom_base,
 exit(1);
 }
 
-rom_add_blob_fixed_as("mrom.finfo", , dinfo_len,
+rom_add_blob_fixed_as("mrom.finfo",
+   riscv_is_32bit(harts) ?
+   (void *) : (void *),
+   dinfo_len,
rom_base + reset_vec_size,
_space_memory);
 }
@@ -430,7 +439,9 @@ void riscv_setup_rom_reset_vec(MachineState *machine, 
RISCVHartArrayState *harts
 }
 rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
   rom_base, _space_memory);
-riscv_rom_copy_firmware_info(machine, rom_base, rom_size, 
sizeof(reset_vec),
+riscv_rom_copy_firmware_info(machine, harts,
+ rom_base, rom_size,
+ sizeof(reset_vec),
  kernel_entry);
 }
 
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index af5f923f54..5010c3eadb 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -646,7 +646,8 @@ static void sifive_u_machine_init(MachineState *machine)
 rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
   memmap[SIFIVE_U_DEV_MROM].base, 
_space_memory);
 
-riscv_rom_copy_firmware_info(machine, memmap[SIFIVE_U_DEV_MROM].base,
+riscv_rom_copy_firmware_info(machine, >soc.u_cpus,
+ memmap[SIFIVE_U_DEV_MROM].base,
  memmap[SIFIVE_U_DEV_MROM].size,
  sizeof(reset_vec), kernel_entry);
 
diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
index a2e4ae9cb0..806256d23f 100644
--- a/include/hw/riscv/boot.h
+++ b/include/hw/riscv/boot.h
@@ -56,7 +56,9 @@ void riscv_setup_rom_reset_vec(MachineState *machine, 
RISCVHartArrayState *harts
hwaddr rom_base, hwaddr rom_size,
uint64_t kernel_entry,
uint64_t fdt_load_addr);
-void riscv_rom_copy_firmware_info(MachineState *machine, hwaddr rom_base,
+void riscv_rom_copy_firmware_info(MachineState *machine,
+ 

[PATCH 0/6] target/riscv: Expose RV32 cpu to RV64 QEMU

2024-06-30 Thread LIU Zhiwei
From: TANG Tiancheng 

This patch set aims to expose 32-bit RISC-V cpu to RV64 QEMU. Thus
qemu-system-riscv64 can directly boot a RV32 Linux.

This patch set has been tested with 6.9.0 Linux Image.

- Run RV64 QEMU with RV32 CPU
qemu-system-riscv64 -cpu rv32 -M virt -nographic \
-kernel Image \
-append "root=/dev/vda ro console=ttyS0" \
-drive file=rootfs.ext2,format=raw,id=hd0 \
-device virtio-blk-device,drive=hd0 -netdev user,id=net0 \
-device virtio-net-device,netdev=net0

OpenSBI v1.4
QEMU emulator version 9.0.50 (v9.0.0-1132-g7799dc2e3b)
[0.00] Linux version 6.9.0 (developer@11109ca35736) 
(riscv32-unknown-linux-gnu-gcc (gc891d8dc23e-dirty) 13.2.0, GNU ld (GNU 
Binutils) 2.42) #3 SMP Fri May 31 08:42:15 UTC 2024
[0.00] random: crng init done
[0.00] OF: fdt: Ignoring memory range 0x8000 - 0x8040
[0.00] Machine model: riscv-virtio,qemu
[0.00] SBI specification v2.0 detected
[0.00] SBI implementation ID=0x1 Version=0x10004
[0.00] SBI TIME extension detected
[0.00] SBI IPI extension detected
[0.00] SBI RFENCE extension detected
[0.00] SBI SRST extension detected
[0.00] SBI DBCN extension detected
[0.00] efi: UEFI not found.
[0.00] OF: reserved mem: 0x8000..0x8003 (256 KiB) nomap 
non-reusable mmode_resv1@8000
[0.00] OF: reserved mem: 0x8004..0x8004 (64 KiB) nomap 
non-reusable mmode_resv0@8004
[0.00] Zone ranges:
[0.00]   Normal   [mem 0x8040-0x87ff]
[0.00] Movable zone start for each node
[0.00] Early memory node ranges
[0.00]   node   0: [mem 0x8040-0x87ff]
[0.00] Initmem setup node 0 [mem 0x8040-0x87ff]
[0.00] On node 0, zone Normal: 1024 pages in unavailable ranges
[0.00] SBI HSM extension detected
[0.00] riscv: base ISA extensions acdfhim
[0.00] riscv: ELF capabilities acdfim
[0.00] percpu: Embedded 17 pages/cpu s37728 r8192 d23712 u69632
[0.00] Kernel command line: root=/dev/vda ro console=ttyS0
[0.00] Dentry cache hash table entries: 16384 (order: 4, 65536 bytes, 
linear)
[0.00] Inode-cache hash table entries: 8192 (order: 3, 32768 bytes, 
linear)
[0.00] Built 1 zonelists, mobility grouping on.  Total pages: 31465
[0.00] mem auto-init: stack:all(zero), heap alloc:off, heap free:off
[0.00] Virtual kernel memory layout:
[0.00]   fixmap : 0x9c80 - 0x9d00   (8192 kB)
[0.00]   pci io : 0x9d00 - 0x9e00   (  16 MB)
[0.00]  vmemmap : 0x9e00 - 0xa000   (  32 MB)
[0.00]  vmalloc : 0xa000 - 0xc000   ( 512 MB)
[0.00]   lowmem : 0xc000 - 0xc7c0   ( 124 MB)
[0.00] Memory: 95700K/126976K available (9090K kernel code, 8845K 
rwdata, 4096K rodata, 4231K init, 341K bss, 31276K reserved, 0K cma-reserved)
...
Welcome to Buildroot
buildroot login: root
# cat /proc/cpuinfo
processor   : 0
hart: 0
isa : 
rv32imafdch_zicbom_zicboz_zicntr_zicsr_zifencei_zihintntl_zihintpause_zihpm_zfa_zba_zbb_zbc_zbs_sstc
mmu : sv32

TANG Tiancheng (6):
  target/riscv: Add fw_dynamic_info32 for booting RV32 OpenSBI
  target/riscv: Adjust PMP size for no-MMU RV64 QEMU running RV32
  target/riscv: Correct SXL return value for RV32 in RV64 QEMU
  target/riscv: Detect sxl to set bit width for RV32 in RV64
  target/riscv: Correct mcause/scause bit width for RV32 in RV64 QEMU
  target/riscv: Enable RV32 CPU support in RV64 QEMU

 configs/targets/riscv64-softmmu.mak |  2 +-
 hw/riscv/boot.c | 35 +++--
 hw/riscv/sifive_u.c |  3 ++-
 include/hw/riscv/boot.h |  4 +++-
 include/hw/riscv/boot_opensbi.h | 29 
 target/riscv/cpu.c  | 17 ++
 target/riscv/cpu.h  |  5 -
 target/riscv/cpu_helper.c   | 23 ++-
 target/riscv/pmp.c  |  2 +-
 9 files changed, 93 insertions(+), 27 deletions(-)

-- 
2.43.0




[PATCH v2 11/11] disas/riscv: Support zabha disassemble

2024-06-29 Thread LIU Zhiwei
Signed-off-by: LIU Zhiwei 
Acked-by: Alistair Francis 
---
 disas/riscv.c | 60 +++
 1 file changed, 60 insertions(+)

diff --git a/disas/riscv.c b/disas/riscv.c
index 2e315b4936..05b663ebfe 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -954,6 +954,26 @@ typedef enum {
 rv_c_mop_11= 923,
 rv_c_mop_13= 924,
 rv_c_mop_15= 925,
+rv_op_amoswap_b = 926,
+rv_op_amoadd_b  = 927,
+rv_op_amoxor_b  = 928,
+rv_op_amoor_b   = 929,
+rv_op_amoand_b  = 930,
+rv_op_amomin_b  = 931,
+rv_op_amomax_b  = 932,
+rv_op_amominu_b = 933,
+rv_op_amomaxu_b = 934,
+rv_op_amoswap_h = 935,
+rv_op_amoadd_h  = 936,
+rv_op_amoxor_h  = 937,
+rv_op_amoor_h   = 938,
+rv_op_amoand_h  = 939,
+rv_op_amomin_h  = 940,
+rv_op_amomax_h  = 941,
+rv_op_amominu_h = 942,
+rv_op_amomaxu_h = 943,
+rv_op_amocas_b  = 944,
+rv_op_amocas_h  = 945,
 } rv_op;
 
 /* register names */
@@ -2192,6 +2212,26 @@ const rv_opcode_data rvi_opcode_data[] = {
 { "c.mop.11", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
 { "c.mop.13", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
 { "c.mop.15", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "amoswap.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoadd.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoxor.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoor.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoand.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amomin.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amomax.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amominu.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amomaxu.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoswap.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoadd.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoxor.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoor.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoand.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amomin.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amomax.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amominu.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amomaxu.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amocas.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amocas.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
 };
 
 /* CSR names */
@@ -2986,9 +3026,13 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa 
isa)
 case 11:
 switch (((inst >> 24) & 0b1000) |
 ((inst >> 12) & 0b0111)) {
+case 0: op = rv_op_amoadd_b; break;
+case 1: op = rv_op_amoadd_h; break;
 case 2: op = rv_op_amoadd_w; break;
 case 3: op = rv_op_amoadd_d; break;
 case 4: op = rv_op_amoadd_q; break;
+case 8: op = rv_op_amoswap_b; break;
+case 9: op = rv_op_amoswap_h; break;
 case 10: op = rv_op_amoswap_w; break;
 case 11: op = rv_op_amoswap_d; break;
 case 12: op = rv_op_amoswap_q; break;
@@ -3010,27 +3054,43 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa 
isa)
 case 26: op = rv_op_sc_w; break;
 case 27: op = rv_op_sc_d; break;
 case 28: op = rv_op_sc_q; break;
+case 32: op = rv_op_amoxor_b; break;
+case 33: op = rv_op_amoxor_h; break;
 case 34: op = rv_op_amoxor_w; break;
 case 35: op = rv_op_amoxor_d; break;
 case 36: op = rv_op_amoxor_q; break;
+case 40: op = rv_op_amocas_b; break;
+case 41: op = rv_op_amocas_h; break;
 case 42: op = rv_op_amocas_w; break;
 case 43: op = rv_op_amocas_d; break;
 case 44: op = rv_op_amocas_q; break;
+case 64: op = rv_op_amoor_b; break;
+case 65: op = rv_op_amoor_h; break;
 case 66: op = rv_op_amoor_w; break;
 case 67: op = rv_op_amoor_d; break;
 case 68: op = rv_op_amoor_q; break;
+case 96: op = rv_op_amoand_b; break;
+case 97: op = rv_op_amoand_h; break;
 case 98: op = rv_op_amoand_w; break;
 case 99: op = rv_op_amoand_d; break;
 case 100: op = rv_op_amoand_q; break;
+case 128: op = rv_op_amomin_b; break;
+  

[PATCH v2 10/11] target/riscv: Enable zabha for max cpu

2024-06-29 Thread LIU Zhiwei
Signed-off-by: LIU Zhiwei 
---
 target/riscv/cpu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 5219b44176..8cd52e6801 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -117,6 +117,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
 ISA_EXT_DATA_ENTRY(zmmul, PRIV_VERSION_1_12_0, ext_zmmul),
 ISA_EXT_DATA_ENTRY(za64rs, PRIV_VERSION_1_12_0, has_priv_1_11),
 ISA_EXT_DATA_ENTRY(zaamo, PRIV_VERSION_1_12_0, ext_zaamo),
+ISA_EXT_DATA_ENTRY(zabha, PRIV_VERSION_1_13_0, ext_zabha),
 ISA_EXT_DATA_ENTRY(zacas, PRIV_VERSION_1_12_0, ext_zacas),
 ISA_EXT_DATA_ENTRY(zama16b, PRIV_VERSION_1_13_0, ext_zama16b),
 ISA_EXT_DATA_ENTRY(zalrsc, PRIV_VERSION_1_12_0, ext_zalrsc),
@@ -1478,6 +1479,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
 MULTI_EXT_CFG_BOOL("zcmop", ext_zcmop, false),
 MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false),
 MULTI_EXT_CFG_BOOL("zama16b", ext_zama16b, false),
+MULTI_EXT_CFG_BOOL("zabha", ext_zabha, false),
 MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false),
 MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false),
 MULTI_EXT_CFG_BOOL("zawrs", ext_zawrs, true),
-- 
2.25.1




[PATCH v2 09/11] target/riscv: Add amocas.[b|h] for Zabha

2024-06-29 Thread LIU Zhiwei
Signed-off-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
---
 target/riscv/insn32.decode  |  2 ++
 target/riscv/insn_trans/trans_rvzabha.c.inc | 14 ++
 2 files changed, 16 insertions(+)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 8a4801d442..eee48f92d3 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -1041,3 +1041,5 @@ amomin_h   1 . . . . 001 . 010 
@atom_st
 amomax_h   10100 . . . . 001 . 010 @atom_st
 amominu_h  11000 . . . . 001 . 010 @atom_st
 amomaxu_h  11100 . . . . 001 . 010 @atom_st
+amocas_b00101 . . . . 000 . 010 @atom_st
+amocas_h00101 . . . . 001 . 010 @atom_st
diff --git a/target/riscv/insn_trans/trans_rvzabha.c.inc 
b/target/riscv/insn_trans/trans_rvzabha.c.inc
index 9093a1cfc1..ce8edcba62 100644
--- a/target/riscv/insn_trans/trans_rvzabha.c.inc
+++ b/target/riscv/insn_trans/trans_rvzabha.c.inc
@@ -129,3 +129,17 @@ static bool trans_amomaxu_h(DisasContext *ctx, 
arg_amomaxu_h *a)
 REQUIRE_ZABHA(ctx);
 return gen_amo(ctx, a, _gen_atomic_fetch_umax_tl, MO_TESW);
 }
+
+static bool trans_amocas_b(DisasContext *ctx, arg_amocas_b *a)
+{
+REQUIRE_ZACAS(ctx);
+REQUIRE_ZABHA(ctx);
+return gen_cmpxchg(ctx, a, MO_SB);
+}
+
+static bool trans_amocas_h(DisasContext *ctx, arg_amocas_h *a)
+{
+REQUIRE_ZACAS(ctx);
+REQUIRE_ZABHA(ctx);
+return gen_cmpxchg(ctx, a, MO_ALIGN | MO_TESW);
+}
-- 
2.25.1




[PATCH v2 08/11] target/riscv: Move gen_cmpxchg before adding amocas.[b|h]

2024-06-29 Thread LIU Zhiwei
Signed-off-by: LIU Zhiwei 
Acked-by: Alistair Francis 
---
 target/riscv/insn_trans/trans_rvzacas.c.inc | 13 -
 target/riscv/translate.c| 13 +
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rvzacas.c.inc 
b/target/riscv/insn_trans/trans_rvzacas.c.inc
index 5d274d4c08..fcced99fc7 100644
--- a/target/riscv/insn_trans/trans_rvzacas.c.inc
+++ b/target/riscv/insn_trans/trans_rvzacas.c.inc
@@ -22,19 +22,6 @@
 } \
 } while (0)
 
-static bool gen_cmpxchg(DisasContext *ctx, arg_atomic *a, MemOp mop)
-{
-TCGv dest = get_gpr(ctx, a->rd, EXT_NONE);
-TCGv src1 = get_address(ctx, a->rs1, 0);
-TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
-
-decode_save_opc(ctx);
-tcg_gen_atomic_cmpxchg_tl(dest, src1, dest, src2, ctx->mem_idx, mop);
-
-gen_set_gpr(ctx, a->rd, dest);
-return true;
-}
-
 static bool trans_amocas_w(DisasContext *ctx, arg_amocas_w *a)
 {
 REQUIRE_ZACAS(ctx);
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 4a3e786560..acba90f170 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -1099,6 +1099,19 @@ static bool gen_amo(DisasContext *ctx, arg_atomic *a,
 return true;
 }
 
+static bool gen_cmpxchg(DisasContext *ctx, arg_atomic *a, MemOp mop)
+{
+TCGv dest = get_gpr(ctx, a->rd, EXT_NONE);
+TCGv src1 = get_address(ctx, a->rs1, 0);
+TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
+
+decode_save_opc(ctx);
+tcg_gen_atomic_cmpxchg_tl(dest, src1, dest, src2, ctx->mem_idx, mop);
+
+gen_set_gpr(ctx, a->rd, dest);
+return true;
+}
+
 static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
 {
 DisasContext *ctx = container_of(dcbase, DisasContext, base);
-- 
2.25.1




[PATCH v2 07/11] target/riscv: Add AMO instructions for Zabha

2024-06-29 Thread LIU Zhiwei
Signed-off-by: LIU Zhiwei 
Acked-by: Alistair Francis 
---
 target/riscv/cpu_cfg.h  |   1 +
 target/riscv/insn32.decode  |  20 +++
 target/riscv/insn_trans/trans_rvzabha.c.inc | 131 
 target/riscv/translate.c|   4 +-
 4 files changed, 155 insertions(+), 1 deletion(-)
 create mode 100644 target/riscv/insn_trans/trans_rvzabha.c.inc

diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index ddbfae37e5..120905a254 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -84,6 +84,7 @@ struct RISCVCPUConfig {
 bool ext_zaamo;
 bool ext_zacas;
 bool ext_zama16b;
+bool ext_zabha;
 bool ext_zalrsc;
 bool ext_zawrs;
 bool ext_zfa;
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 972a1e8fd1..8a4801d442 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -1021,3 +1021,23 @@ amocas_q00101 . . . . 100 . 010 
@atom_st
 # *** Zimop may-be-operation extension ***
 mop_r_n 1 . 00 .. 0111 .. . 100 . 0111011 @mop5
 mop_rr_n1 . 00 .. 1 . . 100 . 0111011 @mop3
+
+# *** Zabhb Standard Extension ***
+amoswap_b  1 . . . . 000 . 010 @atom_st
+amoadd_b   0 . . . . 000 . 010 @atom_st
+amoxor_b   00100 . . . . 000 . 010 @atom_st
+amoand_b   01100 . . . . 000 . 010 @atom_st
+amoor_b01000 . . . . 000 . 010 @atom_st
+amomin_b   1 . . . . 000 . 010 @atom_st
+amomax_b   10100 . . . . 000 . 010 @atom_st
+amominu_b  11000 . . . . 000 . 010 @atom_st
+amomaxu_b  11100 . . . . 000 . 010 @atom_st
+amoswap_h  1 . . . . 001 . 010 @atom_st
+amoadd_h   0 . . . . 001 . 010 @atom_st
+amoxor_h   00100 . . . . 001 . 010 @atom_st
+amoand_h   01100 . . . . 001 . 010 @atom_st
+amoor_h01000 . . . . 001 . 010 @atom_st
+amomin_h   1 . . . . 001 . 010 @atom_st
+amomax_h   10100 . . . . 001 . 010 @atom_st
+amominu_h  11000 . . . . 001 . 010 @atom_st
+amomaxu_h  11100 . . . . 001 . 010 @atom_st
diff --git a/target/riscv/insn_trans/trans_rvzabha.c.inc 
b/target/riscv/insn_trans/trans_rvzabha.c.inc
new file mode 100644
index 00..9093a1cfc1
--- /dev/null
+++ b/target/riscv/insn_trans/trans_rvzabha.c.inc
@@ -0,0 +1,131 @@
+/*
+ * RISC-V translation routines for the Zabha Standard Extension.
+ *
+ * Copyright (c) 2024 Alibaba Group
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define REQUIRE_ZABHA(ctx) do {   \
+if (!ctx->cfg_ptr->ext_zabha) {   \
+return false; \
+} \
+} while (0)
+
+static bool trans_amoswap_b(DisasContext *ctx, arg_amoswap_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_xchg_tl, MO_SB);
+}
+
+static bool trans_amoadd_b(DisasContext *ctx, arg_amoadd_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_fetch_add_tl, MO_SB);
+}
+
+static bool trans_amoxor_b(DisasContext *ctx, arg_amoxor_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_fetch_xor_tl, MO_SB);
+}
+
+static bool trans_amoand_b(DisasContext *ctx, arg_amoand_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_fetch_and_tl, MO_SB);
+}
+
+static bool trans_amoor_b(DisasContext *ctx, arg_amoor_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_fetch_or_tl, MO_SB);
+}
+
+static bool trans_amomin_b(DisasContext *ctx, arg_amomin_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_fetch_smin_tl, MO_SB);
+}
+
+static bool trans_amomax_b(DisasContext *ctx, arg_amomax_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_fetch_smax_tl, MO_SB);
+}
+
+static bool trans_amominu_b(DisasContext *ctx, arg_amominu_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_fetch_umin_tl, MO_SB);
+}
+
+static bool trans_amomaxu_b(DisasContext *ctx, arg_amomaxu_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_fetch_umax_tl, MO_SB);
+}
+
+static bool trans_amoswap_h(DisasContext *ctx, arg_amoswap_h *a)
+{
+R

[PATCH v2 06/11] target/riscv: Move gen_amo before implement Zabha

2024-06-29 Thread LIU Zhiwei
Signed-off-by: LIU Zhiwei 
Acked-by: Alistair Francis 
---
 target/riscv/insn_trans/trans_rva.c.inc | 21 -
 target/riscv/translate.c| 21 +
 2 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rva.c.inc 
b/target/riscv/insn_trans/trans_rva.c.inc
index eb080baddd..39bbf60f3c 100644
--- a/target/riscv/insn_trans/trans_rva.c.inc
+++ b/target/riscv/insn_trans/trans_rva.c.inc
@@ -96,27 +96,6 @@ static bool gen_sc(DisasContext *ctx, arg_atomic *a, MemOp 
mop)
 return true;
 }
 
-static bool gen_amo(DisasContext *ctx, arg_atomic *a,
-void(*func)(TCGv, TCGv, TCGv, TCGArg, MemOp),
-MemOp mop)
-{
-TCGv dest = dest_gpr(ctx, a->rd);
-TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE);
-
-if (ctx->cfg_ptr->ext_zama16b) {
-mop |= MO_ATOM_WITHIN16;
-} else {
-mop |= MO_ALIGN;
-}
-
-decode_save_opc(ctx);
-src1 = get_address(ctx, a->rs1, 0);
-func(dest, src1, src2, ctx->mem_idx, mop);
-
-gen_set_gpr(ctx, a->rd, dest);
-return true;
-}
-
 static bool trans_lr_w(DisasContext *ctx, arg_lr_w *a)
 {
 REQUIRE_A_OR_ZALRSC(ctx);
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 8a546f4ece..133550d6e2 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -1077,6 +1077,27 @@ static bool gen_unary_per_ol(DisasContext *ctx, arg_r2 
*a, DisasExtend ext,
 return gen_unary(ctx, a, ext, f_tl);
 }
 
+static bool gen_amo(DisasContext *ctx, arg_atomic *a,
+void(*func)(TCGv, TCGv, TCGv, TCGArg, MemOp),
+MemOp mop)
+{
+TCGv dest = dest_gpr(ctx, a->rd);
+TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE);
+
+if (ctx->cfg_ptr->ext_zama16b) {
+mop |= MO_ATOM_WITHIN16;
+} else {
+mop |= MO_ALIGN;
+}
+
+decode_save_opc(ctx);
+src1 = get_address(ctx, a->rs1, 0);
+func(dest, src1, src2, ctx->mem_idx, mop);
+
+gen_set_gpr(ctx, a->rd, dest);
+return true;
+}
+
 static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
 {
 DisasContext *ctx = container_of(dcbase, DisasContext, base);
-- 
2.25.1




[PATCH v2 05/11] target/riscv: Support Zama16b extension

2024-06-29 Thread LIU Zhiwei
Zama16b is the property that misaligned load/stores/atomics within
a naturally aligned 16-byte region are atomic.

According to the specification, Zama16b applies only to AMOs, loads
and stores defined in the base ISAs, and loads and stores of no more
than XLEN bits defined in the F, D, and Q extensions. Thus it should
not apply to zacas or RVC instructions.

For an instruction in that set, if all accessed bytes lie within 16B granule,
the instruction will not raise an exception for reasons of address alignment,
and the instruction will give rise to only one memory operation for the
purposes of RVWMO—i.e., it will execute atomically.

Signed-off-by: LIU Zhiwei 
---
 target/riscv/cpu.c  |  2 ++
 target/riscv/cpu_cfg.h  |  1 +
 target/riscv/insn_trans/trans_rva.c.inc | 42 ++---
 target/riscv/insn_trans/trans_rvd.c.inc | 14 +++--
 target/riscv/insn_trans/trans_rvf.c.inc | 14 +++--
 target/riscv/insn_trans/trans_rvi.c.inc |  6 
 6 files changed, 57 insertions(+), 22 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 1d1402775a..5219b44176 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -118,6 +118,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
 ISA_EXT_DATA_ENTRY(za64rs, PRIV_VERSION_1_12_0, has_priv_1_11),
 ISA_EXT_DATA_ENTRY(zaamo, PRIV_VERSION_1_12_0, ext_zaamo),
 ISA_EXT_DATA_ENTRY(zacas, PRIV_VERSION_1_12_0, ext_zacas),
+ISA_EXT_DATA_ENTRY(zama16b, PRIV_VERSION_1_13_0, ext_zama16b),
 ISA_EXT_DATA_ENTRY(zalrsc, PRIV_VERSION_1_12_0, ext_zalrsc),
 ISA_EXT_DATA_ENTRY(zawrs, PRIV_VERSION_1_12_0, ext_zawrs),
 ISA_EXT_DATA_ENTRY(zfa, PRIV_VERSION_1_12_0, ext_zfa),
@@ -1476,6 +1477,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
 MULTI_EXT_CFG_BOOL("zimop", ext_zimop, false),
 MULTI_EXT_CFG_BOOL("zcmop", ext_zcmop, false),
 MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false),
+MULTI_EXT_CFG_BOOL("zama16b", ext_zama16b, false),
 MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false),
 MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false),
 MULTI_EXT_CFG_BOOL("zawrs", ext_zawrs, true),
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index d85e54b475..ddbfae37e5 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -83,6 +83,7 @@ struct RISCVCPUConfig {
 bool ext_zdinx;
 bool ext_zaamo;
 bool ext_zacas;
+bool ext_zama16b;
 bool ext_zalrsc;
 bool ext_zawrs;
 bool ext_zfa;
diff --git a/target/riscv/insn_trans/trans_rva.c.inc 
b/target/riscv/insn_trans/trans_rva.c.inc
index 4a9e4591d1..eb080baddd 100644
--- a/target/riscv/insn_trans/trans_rva.c.inc
+++ b/target/riscv/insn_trans/trans_rva.c.inc
@@ -103,6 +103,12 @@ static bool gen_amo(DisasContext *ctx, arg_atomic *a,
 TCGv dest = dest_gpr(ctx, a->rd);
 TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE);
 
+if (ctx->cfg_ptr->ext_zama16b) {
+mop |= MO_ATOM_WITHIN16;
+} else {
+mop |= MO_ALIGN;
+}
+
 decode_save_opc(ctx);
 src1 = get_address(ctx, a->rs1, 0);
 func(dest, src1, src2, ctx->mem_idx, mop);
@@ -126,55 +132,55 @@ static bool trans_sc_w(DisasContext *ctx, arg_sc_w *a)
 static bool trans_amoswap_w(DisasContext *ctx, arg_amoswap_w *a)
 {
 REQUIRE_A_OR_ZAAMO(ctx);
-return gen_amo(ctx, a, _gen_atomic_xchg_tl, (MO_ALIGN | MO_TESL));
+return gen_amo(ctx, a, _gen_atomic_xchg_tl, MO_TESL);
 }
 
 static bool trans_amoadd_w(DisasContext *ctx, arg_amoadd_w *a)
 {
 REQUIRE_A_OR_ZAAMO(ctx);
-return gen_amo(ctx, a, _gen_atomic_fetch_add_tl, (MO_ALIGN | MO_TESL));
+return gen_amo(ctx, a, _gen_atomic_fetch_add_tl, MO_TESL);
 }
 
 static bool trans_amoxor_w(DisasContext *ctx, arg_amoxor_w *a)
 {
 REQUIRE_A_OR_ZAAMO(ctx);
-return gen_amo(ctx, a, _gen_atomic_fetch_xor_tl, (MO_ALIGN | MO_TESL));
+return gen_amo(ctx, a, _gen_atomic_fetch_xor_tl, MO_TESL);
 }
 
 static bool trans_amoand_w(DisasContext *ctx, arg_amoand_w *a)
 {
 REQUIRE_A_OR_ZAAMO(ctx);
-return gen_amo(ctx, a, _gen_atomic_fetch_and_tl, (MO_ALIGN | MO_TESL));
+return gen_amo(ctx, a, _gen_atomic_fetch_and_tl, MO_TESL);
 }
 
 static bool trans_amoor_w(DisasContext *ctx, arg_amoor_w *a)
 {
 REQUIRE_A_OR_ZAAMO(ctx);
-return gen_amo(ctx, a, _gen_atomic_fetch_or_tl, (MO_ALIGN | MO_TESL));
+return gen_amo(ctx, a, _gen_atomic_fetch_or_tl, MO_TESL);
 }
 
 static bool trans_amomin_w(DisasContext *ctx, arg_amomin_w *a)
 {
 REQUIRE_A_OR_ZAAMO(ctx);
-return gen_amo(ctx, a, _gen_atomic_fetch_smin_tl, (MO_ALIGN | 
MO_TESL));
+return gen_amo(ctx, a, _gen_atomic_fetch_smin_tl, MO_TESL);
 }
 
 static bool trans_amomax_w(DisasContext *ctx, arg_amomax_w *a)
 {
 REQUIRE_A_OR_ZAAMO(ctx);
-return gen_amo(ctx, a, _gen_atomic_fetch_smax_tl, (MO_ALIGN | 
MO_TESL));
+return gen_amo(ctx, a, _gen_atomic_fet

[PATCH v2 04/11] disas/riscv: Support zcmop disassemble

2024-06-29 Thread LIU Zhiwei
Although in QEMU disassemble, we usually lift compressed instruction
to an normal format when display the instruction name. For C.MOP.n,
it is more reasonable to directly display its compressed name, because
its behavior can be redefined by later extension.

Signed-off-by: LIU Zhiwei 
Acked-by: Alistair Francis 
---
 disas/riscv.c | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/disas/riscv.c b/disas/riscv.c
index 3ecbdcbe8d..2e315b4936 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -946,6 +946,14 @@ typedef enum {
 rv_mop_rr_5= 915,
 rv_mop_rr_6= 916,
 rv_mop_rr_7= 917,
+rv_c_mop_1 = 918,
+rv_c_mop_3 = 919,
+rv_c_mop_5 = 920,
+rv_c_mop_7 = 921,
+rv_c_mop_9 = 922,
+rv_c_mop_11= 923,
+rv_c_mop_13= 924,
+rv_c_mop_15= 925,
 } rv_op;
 
 /* register names */
@@ -2176,6 +2184,14 @@ const rv_opcode_data rvi_opcode_data[] = {
 { "mop.rr.5", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
 { "mop.rr.6", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
 { "mop.rr.7", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "c.mop.1",  rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.3",  rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.5",  rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.7",  rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.9",  rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.11", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.13", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.15", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
 };
 
 /* CSR names */
@@ -2532,6 +2548,13 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa 
isa)
 break;
 case 2: op = rv_op_c_li; break;
 case 3:
+if (dec->cfg->ext_zcmop) {
+if inst >> 2) & 0b11) == 0b10) &&
+(((inst >> 11) & 0b11) == 0b0)) {
+op = rv_c_mop_1 + ((inst >> 8) & 0b111);
+break;
+}
+}
 switch ((inst >> 7) & 0b1) {
 case 2: op = rv_op_c_addi16sp; break;
 default: op = rv_op_c_lui; break;
-- 
2.25.1




[PATCH v2 02/11] disas/riscv: Support zimop disassemble

2024-06-29 Thread LIU Zhiwei
Signed-off-by: LIU Zhiwei 
Acked-by: Alistair Francis 
---
 disas/riscv.c | 100 ++
 1 file changed, 100 insertions(+)

diff --git a/disas/riscv.c b/disas/riscv.c
index 90d6b26de9..3ecbdcbe8d 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -906,6 +906,46 @@ typedef enum {
 rv_op_amocas_w = 875,
 rv_op_amocas_d = 876,
 rv_op_amocas_q = 877,
+rv_mop_r_0 = 878,
+rv_mop_r_1 = 879,
+rv_mop_r_2 = 880,
+rv_mop_r_3 = 881,
+rv_mop_r_4 = 882,
+rv_mop_r_5 = 883,
+rv_mop_r_6 = 884,
+rv_mop_r_7 = 885,
+rv_mop_r_8 = 886,
+rv_mop_r_9 = 887,
+rv_mop_r_10= 888,
+rv_mop_r_11= 889,
+rv_mop_r_12= 890,
+rv_mop_r_13= 891,
+rv_mop_r_14= 892,
+rv_mop_r_15= 893,
+rv_mop_r_16= 894,
+rv_mop_r_17= 895,
+rv_mop_r_18= 896,
+rv_mop_r_19= 897,
+rv_mop_r_20= 898,
+rv_mop_r_21= 899,
+rv_mop_r_22= 900,
+rv_mop_r_23= 901,
+rv_mop_r_24= 902,
+rv_mop_r_25= 903,
+rv_mop_r_26= 904,
+rv_mop_r_27= 905,
+rv_mop_r_28= 906,
+rv_mop_r_29= 907,
+rv_mop_r_30= 908,
+rv_mop_r_31= 909,
+rv_mop_rr_0= 910,
+rv_mop_rr_1= 911,
+rv_mop_rr_2= 912,
+rv_mop_rr_3= 913,
+rv_mop_rr_4= 914,
+rv_mop_rr_5= 915,
+rv_mop_rr_6= 916,
+rv_mop_rr_7= 917,
 } rv_op;
 
 /* register names */
@@ -2096,6 +2136,46 @@ const rv_opcode_data rvi_opcode_data[] = {
 { "amocas.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
 { "amocas.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
 { "amocas.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "mop.r.0", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.1", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.2", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.3", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.4", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.5", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.6", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.7", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.8", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.9", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.10", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.11", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.12", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.13", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.14", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.15", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.16", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.17", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.18", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.19", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.20", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.21", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.22", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.23", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.24", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.25", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.26", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.27", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.28", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.29", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.30", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.31", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.rr.0", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.1", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.2", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.3", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.4", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.5", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.6", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.7", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
 };
 
 /* CSR names */
@@ -3008,6 +3088,26 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa 
isa)
 break;
 case 13: op = rv_op_lui; break;
 case 14:
+if (dec->cfg->ext_zimop) {
+int imm_mop5, imm_mop3;
+if (extra

[PATCH v2 03/11] target/riscv: Add zcmop extension

2024-06-29 Thread LIU Zhiwei
Zcmop defines eight 16-bit MOP instructions named C.MOP.n, where n is
an odd integer between 1 and 15, inclusive. C.MOP.n is encoded in
the reserved encoding space corresponding to C.LUI xn, 0.

Unlike the MOPs defined in the Zimop extension, the C.MOP.n instructions
are defined to not write any register.

In current implementation, C.MOP.n only has an check function, without any
other more behavior.

Signed-off-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.c  |  2 ++
 target/riscv/cpu_cfg.h  |  1 +
 target/riscv/insn16.decode  |  1 +
 target/riscv/insn_trans/trans_rvzcmop.c.inc | 29 +
 target/riscv/tcg/tcg-cpu.c  |  5 
 target/riscv/translate.c|  1 +
 6 files changed, 39 insertions(+)
 create mode 100644 target/riscv/insn_trans/trans_rvzcmop.c.inc

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index d3853a5804..1d1402775a 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -131,6 +131,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
 ISA_EXT_DATA_ENTRY(zcf, PRIV_VERSION_1_12_0, ext_zcf),
 ISA_EXT_DATA_ENTRY(zcd, PRIV_VERSION_1_12_0, ext_zcd),
 ISA_EXT_DATA_ENTRY(zce, PRIV_VERSION_1_12_0, ext_zce),
+ISA_EXT_DATA_ENTRY(zcmop, PRIV_VERSION_1_13_0, ext_zcmop),
 ISA_EXT_DATA_ENTRY(zcmp, PRIV_VERSION_1_12_0, ext_zcmp),
 ISA_EXT_DATA_ENTRY(zcmt, PRIV_VERSION_1_12_0, ext_zcmt),
 ISA_EXT_DATA_ENTRY(zba, PRIV_VERSION_1_12_0, ext_zba),
@@ -1473,6 +1474,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
 MULTI_EXT_CFG_BOOL("zihintntl", ext_zihintntl, true),
 MULTI_EXT_CFG_BOOL("zihintpause", ext_zihintpause, true),
 MULTI_EXT_CFG_BOOL("zimop", ext_zimop, false),
+MULTI_EXT_CFG_BOOL("zcmop", ext_zcmop, false),
 MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false),
 MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false),
 MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false),
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index 9f53512053..d85e54b475 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -72,6 +72,7 @@ struct RISCVCPUConfig {
 bool ext_zihintpause;
 bool ext_zihpm;
 bool ext_zimop;
+bool ext_zcmop;
 bool ext_ztso;
 bool ext_smstateen;
 bool ext_sstc;
diff --git a/target/riscv/insn16.decode b/target/riscv/insn16.decode
index b96c534e73..3953bcf82d 100644
--- a/target/riscv/insn16.decode
+++ b/target/riscv/insn16.decode
@@ -140,6 +140,7 @@ sw110  ... ... .. ... 00 @cs_w
 addi  000 .  .  . 01 @ci
 addi  010 .  .  . 01 @c_li
 {
+  c_mop_n 011 0 0 n:3 1 0 01
   illegal 011 0  -  0 01 # c.addi16sp and c.lui, RES nzimm=0
   addi011 .  00010  . 01 @c_addi16sp
   lui 011 .  .  . 01 @c_lui
diff --git a/target/riscv/insn_trans/trans_rvzcmop.c.inc 
b/target/riscv/insn_trans/trans_rvzcmop.c.inc
new file mode 100644
index 00..7205586508
--- /dev/null
+++ b/target/riscv/insn_trans/trans_rvzcmop.c.inc
@@ -0,0 +1,29 @@
+/*
+ * RISC-V translation routines for compressed May-Be-Operation(zcmop).
+ *
+ * Copyright (c) 2024 Alibaba Group.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define REQUIRE_ZCMOP(ctx) do {   \
+if (!ctx->cfg_ptr->ext_zcmop) {   \
+return false; \
+} \
+} while (0)
+
+static bool trans_c_mop_n(DisasContext *ctx, arg_c_mop_n *a)
+{
+REQUIRE_ZCMOP(ctx);
+return true;
+}
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index ae25686824..28cc3f80a9 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -547,6 +547,11 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, 
Error **errp)
 }
 }
 
+if (cpu->cfg.ext_zcmop && !cpu->cfg.ext_zca) {
+error_setg(errp, "Zcmop extensions require Zca");
+return;
+}
+
 if (mcc->misa_mxl_max != MXL_RV32 && cpu->cfg.ext_zcf) {
 error_setg(errp, "Zcf extension is only relevant to RV32");
 return;
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 379b68289f..8a546f4ece 100644
--- 

[PATCH v2 00/11] target/riscv: Support zimop/zcmop/zama16b/zabha

2024-06-29 Thread LIU Zhiwei
We have sent their implementations separately, and we have received few 
objective
comments except for some ISA extensions order. So, I have put them together
as one patch set to make it easier for merging.

v1->v2:
1. Fix the isa orders.
2. Make zimop/zcmop/zama16b/zabha depend on priviledged 1.13
2. Add review tags.

The v1 patch set is here
1. zimop/zcmop
https://mail.gnu.org/archive/html/qemu-riscv/2024-05/msg00207.html
2. zama16b
https://mail.gnu.org/archive/html/qemu-riscv/2024-05/msg00212.html
3. zabha
https://mail.gnu.org/archive/html/qemu-riscv/2024-05/msg00214.html

LIU Zhiwei (11):
  target/riscv: Add zimop extension
  disas/riscv: Support zimop disassemble
  target/riscv: Add zcmop extension
  disas/riscv: Support zcmop disassemble
  target/riscv: Support Zama16b extension
  target/riscv: Move gen_amo before implement Zabha
  target/riscv: Add AMO instructions for Zabha
  target/riscv: Move gen_cmpxchg before adding amocas.[b|h]
  target/riscv: Add amocas.[b|h] for Zabha
  target/riscv: Enable zabha for max cpu
  disas/riscv: Support zabha disassemble

 disas/riscv.c   | 183 
 target/riscv/cpu.c  |   8 +
 target/riscv/cpu_cfg.h  |   4 +
 target/riscv/insn16.decode  |   1 +
 target/riscv/insn32.decode  |  33 
 target/riscv/insn_trans/trans_rva.c.inc |  51 ++
 target/riscv/insn_trans/trans_rvd.c.inc |  14 +-
 target/riscv/insn_trans/trans_rvf.c.inc |  14 +-
 target/riscv/insn_trans/trans_rvi.c.inc |   6 +
 target/riscv/insn_trans/trans_rvzabha.c.inc | 145 
 target/riscv/insn_trans/trans_rvzacas.c.inc |  13 --
 target/riscv/insn_trans/trans_rvzcmop.c.inc |  29 
 target/riscv/insn_trans/trans_rvzimop.c.inc |  37 
 target/riscv/tcg/tcg-cpu.c  |   5 +
 target/riscv/translate.c|  38 
 15 files changed, 531 insertions(+), 50 deletions(-)
 create mode 100644 target/riscv/insn_trans/trans_rvzabha.c.inc
 create mode 100644 target/riscv/insn_trans/trans_rvzcmop.c.inc
 create mode 100644 target/riscv/insn_trans/trans_rvzimop.c.inc

-- 
2.25.1




[PATCH v2 01/11] target/riscv: Add zimop extension

2024-06-29 Thread LIU Zhiwei
Zimop extension defines an encoding space for 40 MOPs.The Zimop
extension defines 32 MOP instructions named MOP.R.n, where n is
an integer between 0 and 31, inclusive. The Zimop extension
additionally defines 8 MOP instructions named MOP.RR.n, where n
is an integer between 0 and 7.

These 40 MOPs initially are defined to simply write zero to x[rd],
but are designed to be redefined by later extensions to perform some
other action.

Signed-off-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.c  |  2 ++
 target/riscv/cpu_cfg.h  |  1 +
 target/riscv/insn32.decode  | 11 ++
 target/riscv/insn_trans/trans_rvzimop.c.inc | 37 +
 target/riscv/translate.c|  1 +
 5 files changed, 52 insertions(+)
 create mode 100644 target/riscv/insn_trans/trans_rvzimop.c.inc

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index a2640cf259..d3853a5804 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -113,6 +113,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
 ISA_EXT_DATA_ENTRY(zihintntl, PRIV_VERSION_1_10_0, ext_zihintntl),
 ISA_EXT_DATA_ENTRY(zihintpause, PRIV_VERSION_1_10_0, ext_zihintpause),
 ISA_EXT_DATA_ENTRY(zihpm, PRIV_VERSION_1_12_0, ext_zihpm),
+ISA_EXT_DATA_ENTRY(zimop, PRIV_VERSION_1_13_0, ext_zimop),
 ISA_EXT_DATA_ENTRY(zmmul, PRIV_VERSION_1_12_0, ext_zmmul),
 ISA_EXT_DATA_ENTRY(za64rs, PRIV_VERSION_1_12_0, has_priv_1_11),
 ISA_EXT_DATA_ENTRY(zaamo, PRIV_VERSION_1_12_0, ext_zaamo),
@@ -1471,6 +1472,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
 MULTI_EXT_CFG_BOOL("zicsr", ext_zicsr, true),
 MULTI_EXT_CFG_BOOL("zihintntl", ext_zihintntl, true),
 MULTI_EXT_CFG_BOOL("zihintpause", ext_zihintpause, true),
+MULTI_EXT_CFG_BOOL("zimop", ext_zimop, false),
 MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false),
 MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false),
 MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false),
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index fb7eebde52..9f53512053 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -71,6 +71,7 @@ struct RISCVCPUConfig {
 bool ext_zihintntl;
 bool ext_zihintpause;
 bool ext_zihpm;
+bool ext_zimop;
 bool ext_ztso;
 bool ext_smstateen;
 bool ext_sstc;
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index f22df04cfd..972a1e8fd1 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -38,6 +38,8 @@
 %imm_bs   30:2   !function=ex_shift_3
 %imm_rnum 20:4
 %imm_z6   26:1 15:5
+%imm_mop5 30:1 26:2 20:2
+%imm_mop3 30:1 26:2
 
 # Argument sets:
 
@@ -56,6 +58,8 @@
 vm rd rs1 nf
  vm rd rs1 rs2 nf
 _aes shamt rs2 rs1 rd
+ imm rd rs1
+ imm rd rs1 rs2
 
 # Formats 32:
 @r   ...   . . ... . ... %rs2 %rs1 
%rd
@@ -98,6 +102,9 @@
 @k_aes   .. . . .  ... . ... _aes  shamt=%imm_bs   %rs2 
%rs1 %rd
 @i_aes   .. . . .  ... . ...   imm=%imm_rnum
%rs1 %rd
 
+@mop5 . . .. ..  .. . ... . ...  imm=%imm_mop5 %rd %rs1
+@mop3 . . .. .. . . . ... . ...  imm=%imm_mop3 %rd %rs1 
%rs2
+
 # Formats 64:
 @sh5 ...  . .  ... . ...   shamt=%sh5  %rs1 
%rd
 
@@ -1010,3 +1017,7 @@ amocas_w00101 . . . . 010 . 010 
@atom_st
 amocas_d00101 . . . . 011 . 010 @atom_st
 # *** RV64 Zacas Standard Extension ***
 amocas_q00101 . . . . 100 . 010 @atom_st
+
+# *** Zimop may-be-operation extension ***
+mop_r_n 1 . 00 .. 0111 .. . 100 . 0111011 @mop5
+mop_rr_n1 . 00 .. 1 . . 100 . 0111011 @mop3
diff --git a/target/riscv/insn_trans/trans_rvzimop.c.inc 
b/target/riscv/insn_trans/trans_rvzimop.c.inc
new file mode 100644
index 00..165aacd2b6
--- /dev/null
+++ b/target/riscv/insn_trans/trans_rvzimop.c.inc
@@ -0,0 +1,37 @@
+/*
+ * RISC-V translation routines for May-Be-Operation(zimop).
+ *
+ * Copyright (c) 2024 Alibaba Group.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define REQUIRE_ZIMOP(ctx) do {   \
+if (!ctx->cfg_ptr->ext_zimop) {   \
+return false; \
+   

Re: [PATCH v7 1/2] hw/misc/riscv_iopmp: Add RISC-V IOPMP device

2024-06-17 Thread LIU Zhiwei



On 2024/6/12 11:17, Ethan Chen wrote:

Support basic functions of IOPMP specification v0.9.1 rapid-k model.
The specification url:
https://github.com/riscv-non-isa/iopmp-spec/releases/tag/v0.9.1

IOPMP check memory access from device is valid or not. This implementation uses
IOMMU to change address space that device access. There are three possible
results of an access: valid, blocked, and stalled(stall is not supported in this
  patch).

If an access is valid, target address space is downstream_as.
If an access is blocked, it will go to blocked_io_as. The operation of
blocked_io_as could be a bus error, or it can respond a success with fabricated
data depending on IOPMP ERR_CFG register value.

Signed-off-by: Ethan Chen 
---
  hw/misc/Kconfig   |3 +
  hw/misc/meson.build   |1 +
  hw/misc/riscv_iopmp.c | 1002 +
  hw/misc/trace-events  |4 +
  include/hw/misc/riscv_iopmp.h |  152 +
  5 files changed, 1162 insertions(+)
  create mode 100644 hw/misc/riscv_iopmp.c
  create mode 100644 include/hw/misc/riscv_iopmp.h

diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 1e08785b83..427f0c702e 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -213,4 +213,7 @@ config IOSB
  config XLNX_VERSAL_TRNG
  bool
  
+config RISCV_IOPMP

+bool
+
  source macio/Kconfig
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 86596a3888..f83cd108f8 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -34,6 +34,7 @@ system_ss.add(when: 'CONFIG_SIFIVE_E_PRCI', if_true: 
files('sifive_e_prci.c'))
  system_ss.add(when: 'CONFIG_SIFIVE_E_AON', if_true: files('sifive_e_aon.c'))
  system_ss.add(when: 'CONFIG_SIFIVE_U_OTP', if_true: files('sifive_u_otp.c'))
  system_ss.add(when: 'CONFIG_SIFIVE_U_PRCI', if_true: files('sifive_u_prci.c'))
+specific_ss.add(when: 'CONFIG_RISCV_IOPMP', if_true: files('riscv_iopmp.c'))
  
  subdir('macio')
  
diff --git a/hw/misc/riscv_iopmp.c b/hw/misc/riscv_iopmp.c

new file mode 100644
index 00..75b28dc559
--- /dev/null
+++ b/hw/misc/riscv_iopmp.c
@@ -0,0 +1,1002 @@
+/*
+ * QEMU RISC-V IOPMP (Input Output Physical Memory Protection)
+ *
+ * Copyright (c) 2023 Andes Tech. Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "trace.h"
+#include "exec/exec-all.h"
+#include "exec/address-spaces.h"
+#include "hw/qdev-properties.h"
+#include "hw/sysbus.h"
+#include "hw/misc/riscv_iopmp.h"
+#include "memory.h"
+#include "hw/irq.h"
+#include "hw/registerfields.h"
+#include "trace.h"
+
+#define TYPE_IOPMP_IOMMU_MEMORY_REGION "iopmp-iommu-memory-region"
+
+REG32(VERSION, 0x00)
+FIELD(VERSION, VENDOR, 0, 24)
+FIELD(VERSION, SPECVER , 24, 8)
+REG32(IMP, 0x04)
+FIELD(IMP, IMPID, 0, 32)
+REG32(HWCFG0, 0x08)
+FIELD(HWCFG0, MODEL, 0, 4)
+FIELD(HWCFG0, TOR_EN, 4, 1)
+FIELD(HWCFG0, SPS_EN, 5, 1)
+FIELD(HWCFG0, USER_CFG_EN, 6, 1)
+FIELD(HWCFG0, PRIENT_PROG, 7, 1)
+FIELD(HWCFG0, RRID_TRANSL_EN, 8, 1)
+FIELD(HWCFG0, RRID_TRANSL_PROG, 9, 1)
+FIELD(HWCFG0, CHK_X, 10, 1)
+FIELD(HWCFG0, NO_X, 11, 1)
+FIELD(HWCFG0, NO_W, 12, 1)
+FIELD(HWCFG0, STALL_EN, 13, 1)
+FIELD(HWCFG0, PEIS, 14, 1)
+FIELD(HWCFG0, PEES, 15, 1)
+FIELD(HWCFG0, MFR_EN, 16, 1)
+FIELD(HWCFG0, MD_NUM, 24, 7)
+FIELD(HWCFG0, ENABLE, 31, 1)
+REG32(HWCFG1, 0x0C)
+FIELD(HWCFG1, RRID_NUM, 0, 16)
+FIELD(HWCFG1, ENTRY_NUM, 16, 16)
+REG32(HWCFG2, 0x10)
+FIELD(HWCFG2, PRIO_ENTRY, 0, 16)
+FIELD(HWCFG2, RRID_TRANSL, 16, 16)
+REG32(ENTRYOFFSET, 0x14)
+FIELD(ENTRYOFFSET, OFFSET, 0, 32)
+REG32(MDSTALL, 0x30)
+FIELD(MDSTALL, EXEMPT, 0, 1)
+FIELD(MDSTALL, MD, 1, 31)
+REG32(MDSTALLH, 0x34)
+FIELD(MDSTALLH, MD, 0, 32)
+REG32(RRIDSCP, 0x38)
+FIELD(RRIDSCP, RRID, 0, 16)
+FIELD(RRIDSCP, OP, 30, 2)
+REG32(MDLCK, 0x40)
+FIELD(MDLCK, L, 0, 1)
+FIELD(MDLCK, MD, 1, 31)
+REG32(MDLCKH, 0x44)
+FIELD(MDLCKH, MDH, 0, 32)
+REG32(MDCFGLCK, 0x48)
+FIELD(MDCFGLCK, L, 0, 1)
+FIELD(MDCFGLCK, F, 1, 7)
+REG32(ENTRYLCK, 0x4C)
+FIELD(ENTRYLCK, L, 0, 1)
+FIELD(ENTRYLCK, F, 1, 16)
+REG32(ERR_CFG, 0x60)
+FIELD(ERR_CFG, L, 0, 1)
+FIELD(ERR_CFG, IE, 1, 1)
+FIELD(ERR_CFG, IRE, 2, 1)
+FIELD(ERR_CFG, IWE, 3, 1)
+FIELD(ERR_CFG, IXE, 4, 1)
+FIELD(ERR_CFG, RRE, 5, 1)
+FIELD(ERR_CFG, 

Re: [RFC PATCH 01/16] accel/tcg: Store section pointer in CPUTLBEntryFull

2024-06-14 Thread LIU Zhiwei



On 2024/6/13 18:37, Jim Shu wrote:

Hi Zhiwei,

Common IOMMU devices will not have IOMMUMemoryRegion in the path of
CPU access since It only affects DMA access.
In QEMU, it usually places this IOMMU MR as the parent of
"system_memory", and changes the target_mr of DMA from "system_memory"
to IOMMU MR.

For the wgChecker, it is in front of memory or device MMIO and
protects both CPU/DMA access to memory or device MMIO.
In QEMU, wgChecker re-use IOMMUMemoryRegion to implement the memory
protection inside the translate() function of IOMMU MR.
In the machine code, wgChecker replaces the MemoryRegion of protected
resources with the checker's IOMMU MR in the MemoryRegion tree of
"system_memory".
Both CPU/DMA access will go through the "system_memory". They will go
through the checker's IOMMU MR when accessing the protected resources.


Thanks. It is clear and very helpful.

Zhiwei



This mechanism is used by Cortex-M MPC devices (hw/misc/tz-mpc.c)
originally. I have leveraged it and extended it little (in patch 2) as
MPC doesn't support RO/WO permission.
If we'd like to have a device to do the memory protection of both CPU
& DMA access, we could implement it in this mechanism.
(p.s. Cortex-A TZASC is not supported in QEMU, which is similar to MPC
or wgChecker device.)

Thanks,
Jim Shu





On Thu, Jun 13, 2024 at 2:23 PM LIU Zhiwei  wrote:

On 2024/6/12 16:14, Jim Shu wrote:

'CPUTLBEntryFull.xlat_section' stores section_index in last 12 bits to
find the correct section when CPU access the IO region over the IOTLB
(iotlb_to_section()).

However, section_index is only unique inside single AddressSpace. If
address space translation is over IOMMUMemoryRegion, it could return
section from other AddressSpace. 'iotlb_to_section()' API only finds the
sections from CPU's AddressSpace so that it couldn't find section in
other AddressSpace. Thus, using 'iotlb_to_section()' API will find the
wrong section and QEMU will have wrong load/store access.

To fix this bug, store complete MemoryRegionSection pointer in
CPUTLBEntryFull instead of section_index.

This bug occurs only when
(1) IOMMUMemoryRegion is in the path of CPU access.

Hi Jim,

Can you explain a little more on when IOMMUMemoryRegion is in the path
of CPU access?

Thanks,
Zhiwei


(2) IOMMUMemoryRegion returns different target_as and the section is in
the IO region.

Common IOMMU devices don't have this issue since they are only in the
path of DMA access. Currently, the bug only occurs when ARM MPC device
(hw/misc/tz-mpc.c) returns 'blocked_io_as' to emulate blocked access
handling. Upcoming RISC-V wgChecker device is also affected by this bug.

Signed-off-by: Jim Shu 
---
   accel/tcg/cputlb.c| 19 +--
   include/hw/core/cpu.h |  3 +++
   2 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index 117b516739..8cf124b760 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -1169,6 +1169,7 @@ void tlb_set_page_full(CPUState *cpu, int mmu_idx,
   desc->fulltlb[index] = *full;
   full = >fulltlb[index];
   full->xlat_section = iotlb - addr_page;
+full->section = section;
   full->phys_addr = paddr_page;

   /* Now calculate the new entry */
@@ -1248,14 +1249,14 @@ static inline void cpu_unaligned_access(CPUState *cpu, 
vaddr addr,
   }

   static MemoryRegionSection *
-io_prepare(hwaddr *out_offset, CPUState *cpu, hwaddr xlat,
+io_prepare(hwaddr *out_offset, CPUState *cpu, CPUTLBEntryFull *full,
  MemTxAttrs attrs, vaddr addr, uintptr_t retaddr)
   {
   MemoryRegionSection *section;
   hwaddr mr_offset;

-section = iotlb_to_section(cpu, xlat, attrs);
-mr_offset = (xlat & TARGET_PAGE_MASK) + addr;
+section = full->section;
+mr_offset = (full->xlat_section & TARGET_PAGE_MASK) + addr;
   cpu->mem_io_pc = retaddr;
   if (!cpu->neg.can_do_io) {
   cpu_io_recompile(cpu, retaddr);
@@ -1571,9 +1572,7 @@ bool tlb_plugin_lookup(CPUState *cpu, vaddr addr, int 
mmu_idx,

   /* We must have an iotlb entry for MMIO */
   if (tlb_addr & TLB_MMIO) {
-MemoryRegionSection *section =
-iotlb_to_section(cpu, full->xlat_section & ~TARGET_PAGE_MASK,
- full->attrs);
+MemoryRegionSection *section = full->section;
   data->is_io = true;
   data->mr = section->mr;
   } else {
@@ -1972,7 +1971,7 @@ static uint64_t do_ld_mmio_beN(CPUState *cpu, 
CPUTLBEntryFull *full,
   tcg_debug_assert(size > 0 && size <= 8);

   attrs = full->attrs;
-section = io_prepare(_offset, cpu, full->xlat_section, attrs, addr, ra);
+section = io_prepare(_offset, cpu, full, attrs, addr, ra);
   mr = section->mr;

   BQL_LOCK_GUARD();
@@ -1993,7 +1992,7 @@ static Int128 do_ld16_mmio_beN(CPUState *cpu, 
CPUTLBEntryFull *

Re: [PATCH v3 00/13] riscv: QEMU RISC-V IOMMU Support

2024-06-14 Thread LIU Zhiwei



On 2024/6/12 20:10, Daniel Henrique Barboza wrote:



On 6/12/24 4:50 AM, LIU Zhiwei wrote:


On 2024/6/11 18:13, Daniel Henrique Barboza wrote:

Hi Zhiwei,

On 6/10/24 10:51 PM, LIU Zhiwei wrote:

Hi Daniel,

I want to know if we can use the IOMMU and IOPMP at the same time.


AFAIK we can. They're not mutually exclusive since they offer 
protection

and isolation at different layers/stages.


OK. Thanks. I will dive into more details.

I see the IOMMU and IOPMP implementations on mail list both set IOMMU 
for PCI root bus.

Is it right?


For now the riscv-iommu-pci device must be placed at a root bus for the
sake of simplicity. 

Agree.

We'll want to lift this restriction in the future as
the support matures.


I think it's OK if it only belongs to virt machine.

If we both support IOPMP and IOMMU for PCI, I think we should call 
pci_setup_iommu only once and use the same address space finding 
function for them.


At least, currently I don't find a reason that they can't share the same 
address space finding function.


Thanks,
Zhiwei




Thanks,

Daniel



Thanks,
Zhiwei






The relationship between them is more similar to MMU and sPMP or to 
MMU and PMP?


I'd say MMU and PMP since the IOMMU can isolate devices regardless of
s-mode context or not.


Thanks,

Daniel



Thanks,
Zhiwei

On 2024/5/24 1:39, Daniel Henrique Barboza wrote:

Hi,

In this new version a lot of changes were made throughout all the 
code,

most notably on patch 3. Link for the previous version is [1].

* How it was tested *

This series was tested using an emulated QEMU RISC-V host booting 
a QEMU
KVM guest, passing through an emulated e1000 network card from the 
host

to the guest. I can provide more details (e.g. QEMU command lines) if
required, just let me know. For now this cover-letter is too much 
of an

essay as is.

The Linux kernel used for tests can be found here:

https://github.com/tjeznach/linux/tree/riscv_iommu_v6-rc3

This is a newer version of the following work from Tomasz:

https://lore.kernel.org/linux-riscv/cover.1715708679.git.tjezn...@rivosinc.com/ 


("[PATCH v5 0/7] Linux RISC-V IOMMU Support")

The v5 wasn't enough for the testing being done. v6-rc3 did the 
trick.


Note that to test this work using riscv-iommu-pci we'll need to 
provide

the Rivos PCI ID in the command line. More details down below.

* Highlights of this version *

- patches removed from v2: platform driver (riscv-iommu-sys, former
patch 05) and the EDU changes (patches 14 and 15). The platform 
driver

will be sent later with a working example on the 'virt' machine,
either on a newer version of this series or via a follow-up 
series. We

already have a PoC on [2] created by Sunil. More tests are needed, so
it'll be left behind for now. The EDU changes will be sent in 
separate

after I finish the doc changes that Frank cited in v2.

- patch 3 contains the bulk of changes made from v2. Please give 
special
attention to the following functions since this is entirely new 
code I

ended up adding:
  - riscv_iommu_report_fault()
  - riscv_iommu_validate_device_ctx()
  - riscv_iommu_update_ipsr()
   Aside from these helpers most of the changes made in this patch 
3 were

punctual.

- Red HAT PCI ID related changes. A new patch (4) that introduces a
generic RISC-V IOMMU PCI ID was added. This PCI ID was gracefully 
given

to us by Red Hat and Gerd Hoffman from their ID space. The
riscv-iommu-pci device now defaults to this PCI ID instead of 
Rivos PCI
ID. The device was changed slightly to allow vendor-id and 
device-id to
be set in the command-line, so it's now possible to use this 
reference

device as another RISC-V IOMMU PCI device to ease the burden of
testing/development.

   To instantiate the riscv-iommu-pci device using the previous 
Rivos PCI

ID, use the following cmd line:

   -device riscv-iommu-pci,vendor-id=0x1efd,device-id=0xedf1

   I'm using these options to test the series with the existing 
Linux RISC-V

IOMMU support that uses just a Rivos ID to identify the device.


Series based on alistair/riscv-to-apply.next. It's also applicable on
current QEMU master. It can also be fetched from:

https://gitlab.com/danielhb/qemu/-/tree/riscv_iommu_v3

Patches missing reviews/acks: 3, 5, 9, 10, 11.

Changes from v2 [1]:
- patch 05 (hw/riscv: add riscv-iommu-sys platform device): dropped
   - will be reintroduced in a later review or as a follow-up series

- patches 14 and 15: dropped
   - will be sent in separate

- patches 2, 3, 4 and 5:
   - removed all 'Ziommu' references

- patch 2:
   - added extra bits that patch 3 ended up using

- patch 3:
   - fixed blank line at EOF in hw/riscv/trace.h
   - added a riscv_iommu_report_fault() helper to report faults. 
The helper checks if

 a given fault is eligible to be reported if DTF is 1
   - Use riscv_iommu_report_fault() in riscv_iommu_ctx() and 
riscv_iommu_translate()

 to avoid code repetition
   - added a riscv_iommu_validate_device_ctx() helper t

Re: [PATCH v7 1/2] hw/misc/riscv_iopmp: Add RISC-V IOPMP device

2024-06-14 Thread LIU Zhiwei



On 2024/6/14 9:46, Ethan Chen wrote:

On Thu, Jun 13, 2024 at 05:26:03PM +0800, LIU Zhiwei wrote:

Hi Ethan,

On 2024/6/12 11:17, Ethan Chen wrote:

Support basic functions of IOPMP specification v0.9.1 rapid-k model.
The specification url:
https://github.com/riscv-non-isa/iopmp-spec/releases/tag/v0.9.1

IOPMP check memory access from device is valid or not. This implementation uses
IOMMU to change address space that device access. There are three possible
results of an access: valid, blocked, and stalled(stall is not supported in this
   patch).

If an access is valid, target address space is downstream_as.
If an access is blocked, it will go to blocked_io_as. The operation of
blocked_io_as could be a bus error, or it can respond a success with fabricated
data depending on IOPMP ERR_CFG register value.

Signed-off-by: Ethan Chen 
---
   hw/misc/Kconfig   |3 +
   hw/misc/meson.build   |1 +
   hw/misc/riscv_iopmp.c | 1002 +
   hw/misc/trace-events  |4 +
   include/hw/misc/riscv_iopmp.h |  152 +
   5 files changed, 1162 insertions(+)
   create mode 100644 hw/misc/riscv_iopmp.c
   create mode 100644 include/hw/misc/riscv_iopmp.h

diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 1e08785b83..427f0c702e 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -213,4 +213,7 @@ config IOSB
   config XLNX_VERSAL_TRNG
   bool

+config RISCV_IOPMP
+bool
+
   source macio/Kconfig
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 86596a3888..f83cd108f8 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -34,6 +34,7 @@ system_ss.add(when: 'CONFIG_SIFIVE_E_PRCI', if_true: 
files('sifive_e_prci.c'))
   system_ss.add(when: 'CONFIG_SIFIVE_E_AON', if_true: files('sifive_e_aon.c'))
   system_ss.add(when: 'CONFIG_SIFIVE_U_OTP', if_true: files('sifive_u_otp.c'))
   system_ss.add(when: 'CONFIG_SIFIVE_U_PRCI', if_true: 
files('sifive_u_prci.c'))
+specific_ss.add(when: 'CONFIG_RISCV_IOPMP', if_true: files('riscv_iopmp.c'))

   subdir('macio')

diff --git a/hw/misc/riscv_iopmp.c b/hw/misc/riscv_iopmp.c
new file mode 100644
index 00..75b28dc559
--- /dev/null
+++ b/hw/misc/riscv_iopmp.c
@@ -0,0 +1,1002 @@
+/*
+ * QEMU RISC-V IOPMP (Input Output Physical Memory Protection)
+ *
+ * Copyright (c) 2023 Andes Tech. Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "trace.h"
+#include "exec/exec-all.h"
+#include "exec/address-spaces.h"
+#include "hw/qdev-properties.h"
+#include "hw/sysbus.h"
+#include "hw/misc/riscv_iopmp.h"
+#include "memory.h"
+#include "hw/irq.h"
+#include "hw/registerfields.h"
+#include "trace.h"
+
+#define TYPE_IOPMP_IOMMU_MEMORY_REGION "iopmp-iommu-memory-region"
+
+REG32(VERSION, 0x00)
+FIELD(VERSION, VENDOR, 0, 24)
+FIELD(VERSION, SPECVER , 24, 8)
+REG32(IMP, 0x04)
+FIELD(IMP, IMPID, 0, 32)
+REG32(HWCFG0, 0x08)
+FIELD(HWCFG0, MODEL, 0, 4)
+FIELD(HWCFG0, TOR_EN, 4, 1)
+FIELD(HWCFG0, SPS_EN, 5, 1)
+FIELD(HWCFG0, USER_CFG_EN, 6, 1)
+FIELD(HWCFG0, PRIENT_PROG, 7, 1)
+FIELD(HWCFG0, RRID_TRANSL_EN, 8, 1)
+FIELD(HWCFG0, RRID_TRANSL_PROG, 9, 1)
+FIELD(HWCFG0, CHK_X, 10, 1)
+FIELD(HWCFG0, NO_X, 11, 1)
+FIELD(HWCFG0, NO_W, 12, 1)
+FIELD(HWCFG0, STALL_EN, 13, 1)
+FIELD(HWCFG0, PEIS, 14, 1)
+FIELD(HWCFG0, PEES, 15, 1)
+FIELD(HWCFG0, MFR_EN, 16, 1)
+FIELD(HWCFG0, MD_NUM, 24, 7)
+FIELD(HWCFG0, ENABLE, 31, 1)
+REG32(HWCFG1, 0x0C)
+FIELD(HWCFG1, RRID_NUM, 0, 16)
+FIELD(HWCFG1, ENTRY_NUM, 16, 16)
+REG32(HWCFG2, 0x10)
+FIELD(HWCFG2, PRIO_ENTRY, 0, 16)
+FIELD(HWCFG2, RRID_TRANSL, 16, 16)
+REG32(ENTRYOFFSET, 0x14)
+FIELD(ENTRYOFFSET, OFFSET, 0, 32)
+REG32(MDSTALL, 0x30)
+FIELD(MDSTALL, EXEMPT, 0, 1)
+FIELD(MDSTALL, MD, 1, 31)
+REG32(MDSTALLH, 0x34)
+FIELD(MDSTALLH, MD, 0, 32)
+REG32(RRIDSCP, 0x38)
+FIELD(RRIDSCP, RRID, 0, 16)
+FIELD(RRIDSCP, OP, 30, 2)
+REG32(MDLCK, 0x40)
+FIELD(MDLCK, L, 0, 1)
+FIELD(MDLCK, MD, 1, 31)
+REG32(MDLCKH, 0x44)
+FIELD(MDLCKH, MDH, 0, 32)
+REG32(MDCFGLCK, 0x48)
+FIELD(MDCFGLCK, L, 0, 1)
+FIELD(MDCFGLCK, F, 1, 7)
+REG32(ENTRYLCK, 0x4C)
+FIELD(ENTRYLCK, L

Re: [PATCH v7 1/2] hw/misc/riscv_iopmp: Add RISC-V IOPMP device

2024-06-13 Thread LIU Zhiwei

Hi Ethan,

On 2024/6/12 11:17, Ethan Chen wrote:

Support basic functions of IOPMP specification v0.9.1 rapid-k model.
The specification url:
https://github.com/riscv-non-isa/iopmp-spec/releases/tag/v0.9.1

IOPMP check memory access from device is valid or not. This implementation uses
IOMMU to change address space that device access. There are three possible
results of an access: valid, blocked, and stalled(stall is not supported in this
  patch).

If an access is valid, target address space is downstream_as.
If an access is blocked, it will go to blocked_io_as. The operation of
blocked_io_as could be a bus error, or it can respond a success with fabricated
data depending on IOPMP ERR_CFG register value.

Signed-off-by: Ethan Chen 
---
  hw/misc/Kconfig   |3 +
  hw/misc/meson.build   |1 +
  hw/misc/riscv_iopmp.c | 1002 +
  hw/misc/trace-events  |4 +
  include/hw/misc/riscv_iopmp.h |  152 +
  5 files changed, 1162 insertions(+)
  create mode 100644 hw/misc/riscv_iopmp.c
  create mode 100644 include/hw/misc/riscv_iopmp.h

diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index 1e08785b83..427f0c702e 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -213,4 +213,7 @@ config IOSB
  config XLNX_VERSAL_TRNG
  bool
  
+config RISCV_IOPMP

+bool
+
  source macio/Kconfig
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 86596a3888..f83cd108f8 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -34,6 +34,7 @@ system_ss.add(when: 'CONFIG_SIFIVE_E_PRCI', if_true: 
files('sifive_e_prci.c'))
  system_ss.add(when: 'CONFIG_SIFIVE_E_AON', if_true: files('sifive_e_aon.c'))
  system_ss.add(when: 'CONFIG_SIFIVE_U_OTP', if_true: files('sifive_u_otp.c'))
  system_ss.add(when: 'CONFIG_SIFIVE_U_PRCI', if_true: files('sifive_u_prci.c'))
+specific_ss.add(when: 'CONFIG_RISCV_IOPMP', if_true: files('riscv_iopmp.c'))
  
  subdir('macio')
  
diff --git a/hw/misc/riscv_iopmp.c b/hw/misc/riscv_iopmp.c

new file mode 100644
index 00..75b28dc559
--- /dev/null
+++ b/hw/misc/riscv_iopmp.c
@@ -0,0 +1,1002 @@
+/*
+ * QEMU RISC-V IOPMP (Input Output Physical Memory Protection)
+ *
+ * Copyright (c) 2023 Andes Tech. Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see .
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qapi/error.h"
+#include "trace.h"
+#include "exec/exec-all.h"
+#include "exec/address-spaces.h"
+#include "hw/qdev-properties.h"
+#include "hw/sysbus.h"
+#include "hw/misc/riscv_iopmp.h"
+#include "memory.h"
+#include "hw/irq.h"
+#include "hw/registerfields.h"
+#include "trace.h"
+
+#define TYPE_IOPMP_IOMMU_MEMORY_REGION "iopmp-iommu-memory-region"
+
+REG32(VERSION, 0x00)
+FIELD(VERSION, VENDOR, 0, 24)
+FIELD(VERSION, SPECVER , 24, 8)
+REG32(IMP, 0x04)
+FIELD(IMP, IMPID, 0, 32)
+REG32(HWCFG0, 0x08)
+FIELD(HWCFG0, MODEL, 0, 4)
+FIELD(HWCFG0, TOR_EN, 4, 1)
+FIELD(HWCFG0, SPS_EN, 5, 1)
+FIELD(HWCFG0, USER_CFG_EN, 6, 1)
+FIELD(HWCFG0, PRIENT_PROG, 7, 1)
+FIELD(HWCFG0, RRID_TRANSL_EN, 8, 1)
+FIELD(HWCFG0, RRID_TRANSL_PROG, 9, 1)
+FIELD(HWCFG0, CHK_X, 10, 1)
+FIELD(HWCFG0, NO_X, 11, 1)
+FIELD(HWCFG0, NO_W, 12, 1)
+FIELD(HWCFG0, STALL_EN, 13, 1)
+FIELD(HWCFG0, PEIS, 14, 1)
+FIELD(HWCFG0, PEES, 15, 1)
+FIELD(HWCFG0, MFR_EN, 16, 1)
+FIELD(HWCFG0, MD_NUM, 24, 7)
+FIELD(HWCFG0, ENABLE, 31, 1)
+REG32(HWCFG1, 0x0C)
+FIELD(HWCFG1, RRID_NUM, 0, 16)
+FIELD(HWCFG1, ENTRY_NUM, 16, 16)
+REG32(HWCFG2, 0x10)
+FIELD(HWCFG2, PRIO_ENTRY, 0, 16)
+FIELD(HWCFG2, RRID_TRANSL, 16, 16)
+REG32(ENTRYOFFSET, 0x14)
+FIELD(ENTRYOFFSET, OFFSET, 0, 32)
+REG32(MDSTALL, 0x30)
+FIELD(MDSTALL, EXEMPT, 0, 1)
+FIELD(MDSTALL, MD, 1, 31)
+REG32(MDSTALLH, 0x34)
+FIELD(MDSTALLH, MD, 0, 32)
+REG32(RRIDSCP, 0x38)
+FIELD(RRIDSCP, RRID, 0, 16)
+FIELD(RRIDSCP, OP, 30, 2)
+REG32(MDLCK, 0x40)
+FIELD(MDLCK, L, 0, 1)
+FIELD(MDLCK, MD, 1, 31)
+REG32(MDLCKH, 0x44)
+FIELD(MDLCKH, MDH, 0, 32)
+REG32(MDCFGLCK, 0x48)
+FIELD(MDCFGLCK, L, 0, 1)
+FIELD(MDCFGLCK, F, 1, 7)
+REG32(ENTRYLCK, 0x4C)
+FIELD(ENTRYLCK, L, 0, 1)
+FIELD(ENTRYLCK, F, 1, 16)
+REG32(ERR_CFG, 0x60)
+FIELD(ERR_CFG, L, 0, 1)
+FIELD(ERR_CFG, IE, 1, 1)
+FIELD(ERR_CFG, IRE, 2, 1)
+FIELD(ERR_CFG, IWE, 3, 1)
+FIELD(ERR_CFG, IXE, 4, 1)
+FIELD(ERR_CFG, RRE, 5, 1)
+

Re: [RFC PATCH 01/16] accel/tcg: Store section pointer in CPUTLBEntryFull

2024-06-13 Thread LIU Zhiwei

On 2024/6/12 16:14, Jim Shu wrote:

'CPUTLBEntryFull.xlat_section' stores section_index in last 12 bits to
find the correct section when CPU access the IO region over the IOTLB
(iotlb_to_section()).

However, section_index is only unique inside single AddressSpace. If
address space translation is over IOMMUMemoryRegion, it could return
section from other AddressSpace. 'iotlb_to_section()' API only finds the
sections from CPU's AddressSpace so that it couldn't find section in
other AddressSpace. Thus, using 'iotlb_to_section()' API will find the
wrong section and QEMU will have wrong load/store access.

To fix this bug, store complete MemoryRegionSection pointer in
CPUTLBEntryFull instead of section_index.

This bug occurs only when
(1) IOMMUMemoryRegion is in the path of CPU access.


Hi Jim,

Can you explain a little more on when IOMMUMemoryRegion is in the path 
of CPU access?


Thanks,
Zhiwei


(2) IOMMUMemoryRegion returns different target_as and the section is in
the IO region.

Common IOMMU devices don't have this issue since they are only in the
path of DMA access. Currently, the bug only occurs when ARM MPC device
(hw/misc/tz-mpc.c) returns 'blocked_io_as' to emulate blocked access
handling. Upcoming RISC-V wgChecker device is also affected by this bug.

Signed-off-by: Jim Shu 
---
  accel/tcg/cputlb.c| 19 +--
  include/hw/core/cpu.h |  3 +++
  2 files changed, 12 insertions(+), 10 deletions(-)

diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index 117b516739..8cf124b760 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -1169,6 +1169,7 @@ void tlb_set_page_full(CPUState *cpu, int mmu_idx,
  desc->fulltlb[index] = *full;
  full = >fulltlb[index];
  full->xlat_section = iotlb - addr_page;
+full->section = section;
  full->phys_addr = paddr_page;
  
  /* Now calculate the new entry */

@@ -1248,14 +1249,14 @@ static inline void cpu_unaligned_access(CPUState *cpu, 
vaddr addr,
  }
  
  static MemoryRegionSection *

-io_prepare(hwaddr *out_offset, CPUState *cpu, hwaddr xlat,
+io_prepare(hwaddr *out_offset, CPUState *cpu, CPUTLBEntryFull *full,
 MemTxAttrs attrs, vaddr addr, uintptr_t retaddr)
  {
  MemoryRegionSection *section;
  hwaddr mr_offset;
  
-section = iotlb_to_section(cpu, xlat, attrs);

-mr_offset = (xlat & TARGET_PAGE_MASK) + addr;
+section = full->section;
+mr_offset = (full->xlat_section & TARGET_PAGE_MASK) + addr;
  cpu->mem_io_pc = retaddr;
  if (!cpu->neg.can_do_io) {
  cpu_io_recompile(cpu, retaddr);
@@ -1571,9 +1572,7 @@ bool tlb_plugin_lookup(CPUState *cpu, vaddr addr, int 
mmu_idx,
  
  /* We must have an iotlb entry for MMIO */

  if (tlb_addr & TLB_MMIO) {
-MemoryRegionSection *section =
-iotlb_to_section(cpu, full->xlat_section & ~TARGET_PAGE_MASK,
- full->attrs);
+MemoryRegionSection *section = full->section;
  data->is_io = true;
  data->mr = section->mr;
  } else {
@@ -1972,7 +1971,7 @@ static uint64_t do_ld_mmio_beN(CPUState *cpu, 
CPUTLBEntryFull *full,
  tcg_debug_assert(size > 0 && size <= 8);
  
  attrs = full->attrs;

-section = io_prepare(_offset, cpu, full->xlat_section, attrs, addr, ra);
+section = io_prepare(_offset, cpu, full, attrs, addr, ra);
  mr = section->mr;
  
  BQL_LOCK_GUARD();

@@ -1993,7 +1992,7 @@ static Int128 do_ld16_mmio_beN(CPUState *cpu, 
CPUTLBEntryFull *full,
  tcg_debug_assert(size > 8 && size <= 16);
  
  attrs = full->attrs;

-section = io_prepare(_offset, cpu, full->xlat_section, attrs, addr, ra);
+section = io_prepare(_offset, cpu, full, attrs, addr, ra);
  mr = section->mr;
  
  BQL_LOCK_GUARD();

@@ -2513,7 +2512,7 @@ static uint64_t do_st_mmio_leN(CPUState *cpu, 
CPUTLBEntryFull *full,
  tcg_debug_assert(size > 0 && size <= 8);
  
  attrs = full->attrs;

-section = io_prepare(_offset, cpu, full->xlat_section, attrs, addr, ra);
+section = io_prepare(_offset, cpu, full, attrs, addr, ra);
  mr = section->mr;
  
  BQL_LOCK_GUARD();

@@ -2533,7 +2532,7 @@ static uint64_t do_st16_mmio_leN(CPUState *cpu, 
CPUTLBEntryFull *full,
  tcg_debug_assert(size > 8 && size <= 16);
  
  attrs = full->attrs;

-section = io_prepare(_offset, cpu, full->xlat_section, attrs, addr, ra);
+section = io_prepare(_offset, cpu, full, attrs, addr, ra);
  mr = section->mr;
  
  BQL_LOCK_GUARD();

diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
index a2c8536943..3f6c10897b 100644
--- a/include/hw/core/cpu.h
+++ b/include/hw/core/cpu.h
@@ -217,6 +217,9 @@ typedef struct CPUTLBEntryFull {
   */
  hwaddr xlat_section;
  
+/* @section contains physical section. */

+MemoryRegionSection *section;
+
  /*
   * @phys_addr contains the physical address in the address space
   * given by cpu_asidx_from_attrs(cpu, @attrs).




Re: [PATCH v3 00/13] riscv: QEMU RISC-V IOMMU Support

2024-06-12 Thread LIU Zhiwei



On 2024/6/11 18:13, Daniel Henrique Barboza wrote:

Hi Zhiwei,

On 6/10/24 10:51 PM, LIU Zhiwei wrote:

Hi Daniel,

I want to know if we can use the IOMMU and IOPMP at the same time.


AFAIK we can. They're not mutually exclusive since they offer protection
and isolation at different layers/stages.


OK. Thanks. I will dive into more details.

I see the IOMMU and IOPMP implementations on mail list both set IOMMU 
for PCI root bus.

Is it right?

Thanks,
Zhiwei






The relationship between them is more similar to MMU and sPMP or to 
MMU and PMP?


I'd say MMU and PMP since the IOMMU can isolate devices regardless of
s-mode context or not.


Thanks,

Daniel



Thanks,
Zhiwei

On 2024/5/24 1:39, Daniel Henrique Barboza wrote:

Hi,

In this new version a lot of changes were made throughout all the code,
most notably on patch 3. Link for the previous version is [1].

* How it was tested *

This series was tested using an emulated QEMU RISC-V host booting a 
QEMU

KVM guest, passing through an emulated e1000 network card from the host
to the guest. I can provide more details (e.g. QEMU command lines) if
required, just let me know. For now this cover-letter is too much of an
essay as is.

The Linux kernel used for tests can be found here:

https://github.com/tjeznach/linux/tree/riscv_iommu_v6-rc3

This is a newer version of the following work from Tomasz:

https://lore.kernel.org/linux-riscv/cover.1715708679.git.tjezn...@rivosinc.com/ 


("[PATCH v5 0/7] Linux RISC-V IOMMU Support")

The v5 wasn't enough for the testing being done. v6-rc3 did the trick.

Note that to test this work using riscv-iommu-pci we'll need to provide
the Rivos PCI ID in the command line. More details down below.

* Highlights of this version *

- patches removed from v2: platform driver (riscv-iommu-sys, former
patch 05) and the EDU changes (patches 14 and 15). The platform driver
will be sent later with a working example on the 'virt' machine,
either on a newer version of this series or via a follow-up series. We
already have a PoC on [2] created by Sunil. More tests are needed, so
it'll be left behind for now. The EDU changes will be sent in separate
after I finish the doc changes that Frank cited in v2.

- patch 3 contains the bulk of changes made from v2. Please give 
special

attention to the following functions since this is entirely new code I
ended up adding:
  - riscv_iommu_report_fault()
  - riscv_iommu_validate_device_ctx()
  - riscv_iommu_update_ipsr()
   Aside from these helpers most of the changes made in this patch 3 
were

punctual.

- Red HAT PCI ID related changes. A new patch (4) that introduces a
generic RISC-V IOMMU PCI ID was added. This PCI ID was gracefully given
to us by Red Hat and Gerd Hoffman from their ID space. The
riscv-iommu-pci device now defaults to this PCI ID instead of Rivos PCI
ID. The device was changed slightly to allow vendor-id and device-id to
be set in the command-line, so it's now possible to use this reference
device as another RISC-V IOMMU PCI device to ease the burden of
testing/development.

   To instantiate the riscv-iommu-pci device using the previous 
Rivos PCI

ID, use the following cmd line:

   -device riscv-iommu-pci,vendor-id=0x1efd,device-id=0xedf1

   I'm using these options to test the series with the existing 
Linux RISC-V

IOMMU support that uses just a Rivos ID to identify the device.


Series based on alistair/riscv-to-apply.next. It's also applicable on
current QEMU master. It can also be fetched from:

https://gitlab.com/danielhb/qemu/-/tree/riscv_iommu_v3

Patches missing reviews/acks: 3, 5, 9, 10, 11.

Changes from v2 [1]:
- patch 05 (hw/riscv: add riscv-iommu-sys platform device): dropped
   - will be reintroduced in a later review or as a follow-up series

- patches 14 and 15: dropped
   - will be sent in separate

- patches 2, 3, 4 and 5:
   - removed all 'Ziommu' references

- patch 2:
   - added extra bits that patch 3 ended up using

- patch 3:
   - fixed blank line at EOF in hw/riscv/trace.h
   - added a riscv_iommu_report_fault() helper to report faults. The 
helper checks if

 a given fault is eligible to be reported if DTF is 1
   - Use riscv_iommu_report_fault() in riscv_iommu_ctx() and 
riscv_iommu_translate()

 to avoid code repetition
   - added a riscv_iommu_validate_device_ctx() helper to validate 
the device context
 as specified in "Device configuration checks" section. This 
helper is being used

 in riscv_iommu_ctx_fetch()
   - added a new riscv_iommu_update_ipsr() helper to handle IPSR 
updates

 in riscv_iommu_mmio_write()
   - riscv_iommmu_msi_write() now reports a fault in all error paths
   - check for fctl.WSI before issuing a MSI interrupt in 
riscv_iommu_notify()

   - change riscv-iommu region name to 'riscv-iommu'
   - change address_space_init() name for PCI devices to 'name' 
instead of using TYPE_RISCV_IOMMU_PCI

   - changed riscv_iommu_mmio_ops min_access_size to 4
   - do not check f

Re: [PATCH v3 00/13] riscv: QEMU RISC-V IOMMU Support

2024-06-10 Thread LIU Zhiwei

Hi Daniel,

I want to know if we can use the IOMMU and IOPMP at the same time.

The relationship between them is more similar to MMU and sPMP or to MMU 
and PMP?


Thanks,
Zhiwei

On 2024/5/24 1:39, Daniel Henrique Barboza wrote:

Hi,

In this new version a lot of changes were made throughout all the code,
most notably on patch 3. Link for the previous version is [1].

* How it was tested *

This series was tested using an emulated QEMU RISC-V host booting a QEMU
KVM guest, passing through an emulated e1000 network card from the host
to the guest. I can provide more details (e.g. QEMU command lines) if
required, just let me know. For now this cover-letter is too much of an
essay as is.

The Linux kernel used for tests can be found here:

https://github.com/tjeznach/linux/tree/riscv_iommu_v6-rc3

This is a newer version of the following work from Tomasz:

https://lore.kernel.org/linux-riscv/cover.1715708679.git.tjezn...@rivosinc.com/
("[PATCH v5 0/7] Linux RISC-V IOMMU Support")

The v5 wasn't enough for the testing being done. v6-rc3 did the trick.

Note that to test this work using riscv-iommu-pci we'll need to provide
the Rivos PCI ID in the command line. More details down below.

* Highlights of this version *

- patches removed from v2: platform driver (riscv-iommu-sys, former
patch 05) and the EDU changes (patches 14 and 15). The platform driver
will be sent later with a working example on the 'virt' machine,
either on a newer version of this series or via a follow-up series. We
already have a PoC on [2] created by Sunil. More tests are needed, so
it'll be left behind for now. The EDU changes will be sent in separate
after I finish the doc changes that Frank cited in v2.

- patch 3 contains the bulk of changes made from v2. Please give special
attention to the following functions since this is entirely new code I
ended up adding:
  
  - riscv_iommu_report_fault()

  - riscv_iommu_validate_device_ctx()
  - riscv_iommu_update_ipsr()
  
   Aside from these helpers most of the changes made in this patch 3 were

punctual.

- Red HAT PCI ID related changes. A new patch (4) that introduces a
generic RISC-V IOMMU PCI ID was added. This PCI ID was gracefully given
to us by Red Hat and Gerd Hoffman from their ID space. The
riscv-iommu-pci device now defaults to this PCI ID instead of Rivos PCI
ID. The device was changed slightly to allow vendor-id and device-id to
be set in the command-line, so it's now possible to use this reference
device as another RISC-V IOMMU PCI device to ease the burden of
testing/development.

   To instantiate the riscv-iommu-pci device using the previous Rivos PCI
ID, use the following cmd line:

   -device riscv-iommu-pci,vendor-id=0x1efd,device-id=0xedf1

   I'm using these options to test the series with the existing Linux RISC-V
IOMMU support that uses just a Rivos ID to identify the device.


Series based on alistair/riscv-to-apply.next. It's also applicable on
current QEMU master. It can also be fetched from:

https://gitlab.com/danielhb/qemu/-/tree/riscv_iommu_v3
  


Patches missing reviews/acks: 3, 5, 9, 10, 11.

Changes from v2 [1]:
- patch 05 (hw/riscv: add riscv-iommu-sys platform device): dropped
   - will be reintroduced in a later review or as a follow-up series

- patches 14 and 15: dropped
   - will be sent in separate

- patches 2, 3, 4 and 5:
   - removed all 'Ziommu' references

- patch 2:
   - added extra bits that patch 3 ended up using

- patch 3:
   - fixed blank line at EOF in hw/riscv/trace.h
   - added a riscv_iommu_report_fault() helper to report faults. The helper 
checks if
 a given fault is eligible to be reported if DTF is 1
   - Use riscv_iommu_report_fault() in riscv_iommu_ctx() and 
riscv_iommu_translate()
 to avoid code repetition
   - added a riscv_iommu_validate_device_ctx() helper to validate the device 
context
 as specified in "Device configuration checks" section. This helper is 
being used
 in riscv_iommu_ctx_fetch()
   - added a new riscv_iommu_update_ipsr() helper to handle IPSR updates
 in riscv_iommu_mmio_write()
   - riscv_iommmu_msi_write() now reports a fault in all error paths
   - check for fctl.WSI before issuing a MSI interrupt in riscv_iommu_notify()
   - change riscv-iommu region name to 'riscv-iommu'
   - change address_space_init() name for PCI devices to 'name' instead of 
using TYPE_RISCV_IOMMU_PCI
   - changed riscv_iommu_mmio_ops min_access_size to 4
   - do not check for min and max sizes on riscv_iommu_mmio_write()
   - changed riscv_iommu_trap_ops  min_access_size to 4
   - removed IOMMU qemu_thread thread:
 - riscv_iommu_mmio_write() will now execute a riscv_iommu_process_fn by 
holding
   'core_lock'
   - init FSCR as zero explicitly
   - check for bus->iommu_opaque == NULL before calling pci_setup_iommu()

- patch 4 (new):
   - add Red-Hat PCI RISC-V IOMMU ID

- patch 5 (former 4):
   - create vendor-id and device-id properties
   - set Red-hat PCI RISC-V IOMMU ID as default ID

- patch 

  1   2   3   4   5   6   7   8   9   10   >