Re: [PATCH v9 2/6] target/riscv: Add new CSR fields for S{sn, mn, m}pm extensions as part of Zjpm v0.8

2024-06-02 Thread Daniel Henrique Barboza




On 5/11/24 7:10 AM, Alexey Baturo wrote:

From: Alexey Baturo 

Signed-off-by: Alexey Baturo 

Reviewed-by: Alistair Francis 
---
  target/riscv/cpu.h  |  8 
  target/riscv/cpu_bits.h |  3 +++
  target/riscv/cpu_cfg.h  |  3 +++
  target/riscv/csr.c  | 11 +++
  target/riscv/machine.c  | 10 +++---
  target/riscv/pmp.c  | 13 ++---
  target/riscv/pmp.h  | 11 ++-
  7 files changed, 48 insertions(+), 11 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 232521bb87..52b6ba73c8 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -121,6 +121,14 @@ typedef enum {
  EXT_STATUS_DIRTY,
  } RISCVExtStatus;
  
+/* Enum holds PMM field values for Zjpm v0.8 extension */

+typedef enum {
+PMM_FIELD_DISABLED = 0,
+PMM_FIELD_RESERVED = 1,
+PMM_FIELD_PMLEN7   = 2,
+PMM_FIELD_PMLEN16  = 3,
+} RISCVPmPmm;
+
  #define MMU_USER_IDX 3
  
  #define MAX_RISCV_PMPS (16)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index da16ba236a..13ce2218d1 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -708,6 +708,7 @@ typedef enum RISCVException {
  #define MENVCFG_CBIE   (3UL << 4)
  #define MENVCFG_CBCFE  BIT(6)
  #define MENVCFG_CBZE   BIT(7)
+#define MENVCFG_PMM(3ULL << 32)
  #define MENVCFG_ADUE   (1ULL << 61)
  #define MENVCFG_PBMTE  (1ULL << 62)
  #define MENVCFG_STCE   (1ULL << 63)
@@ -721,11 +722,13 @@ typedef enum RISCVException {
  #define SENVCFG_CBIE   MENVCFG_CBIE
  #define SENVCFG_CBCFE  MENVCFG_CBCFE
  #define SENVCFG_CBZE   MENVCFG_CBZE
+#define SENVCFG_PMMMENVCFG_PMM
  
  #define HENVCFG_FIOM   MENVCFG_FIOM

  #define HENVCFG_CBIE   MENVCFG_CBIE
  #define HENVCFG_CBCFE  MENVCFG_CBCFE
  #define HENVCFG_CBZE   MENVCFG_CBZE
+#define HENVCFG_PMMMENVCFG_PMM
  #define HENVCFG_ADUE   MENVCFG_ADUE
  #define HENVCFG_PBMTE  MENVCFG_PBMTE
  #define HENVCFG_STCE   MENVCFG_STCE
diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index e1e4f32698..9ecdc792c5 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -120,6 +120,9 @@ struct RISCVCPUConfig {
  bool ext_ssaia;
  bool ext_sscofpmf;
  bool ext_smepmp;
+bool ext_ssnpm;
+bool ext_smnpm;
+bool ext_smmpm;
  bool rvv_ta_all_1s;
  bool rvv_ma_all_1s;
  
diff --git a/target/riscv/csr.c b/target/riscv/csr.c

index 4b2c932564..45b548eb0b 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -530,6 +530,9 @@ static RISCVException have_mseccfg(CPURISCVState *env, int 
csrno)
  if (riscv_cpu_cfg(env)->ext_zkr) {
  return RISCV_EXCP_NONE;
  }
+if (riscv_cpu_cfg(env)->ext_smmpm) {
+return RISCV_EXCP_NONE;
+}
  
  return RISCV_EXCP_ILLEGAL_INST;

  }
@@ -2083,6 +2086,10 @@ static RISCVException write_menvcfg(CPURISCVState *env, 
int csrno,
  (cfg->ext_sstc ? MENVCFG_STCE : 0) |
  (cfg->ext_svadu ? MENVCFG_ADUE : 0);
  }
+/* Update PMM field only if the value is valid according to Zjpm v0.8 */
+if (((val & MENVCFG_PMM) >> 32) != PMM_FIELD_RESERVED) {
+mask |= MENVCFG_PMM;
+}
  env->menvcfg = (env->menvcfg & ~mask) | (val & mask);
  
  return RISCV_EXCP_NONE;

@@ -2127,6 +2134,10 @@ static RISCVException write_senvcfg(CPURISCVState *env, 
int csrno,
  target_ulong val)
  {
  uint64_t mask = SENVCFG_FIOM | SENVCFG_CBIE | SENVCFG_CBCFE | 
SENVCFG_CBZE;
+/* Update PMM field only if the value is valid according to Zjpm v0.8 */
+if (((val & SENVCFG_PMM) >> 32) != PMM_FIELD_RESERVED) {
+mask |= SENVCFG_PMM;
+}
  RISCVException ret;
  
  ret = smstateen_acc_ok(env, 0, SMSTATEEN0_HSENVCFG);

diff --git a/target/riscv/machine.c b/target/riscv/machine.c
index 64ab66e332..28f373 100644
--- a/target/riscv/machine.c
+++ b/target/riscv/machine.c
@@ -152,15 +152,19 @@ static const VMStateDescription vmstate_vector = {
  
  static bool pointermasking_needed(void *opaque)

  {
-return false;
+RISCVCPU *cpu = opaque;
+return cpu->cfg.ext_ssnpm || cpu->cfg.ext_smnpm || cpu->cfg.ext_smmpm;
  }
  
  static const VMStateDescription vmstate_pointermasking = {

  .name = "cpu/pointer_masking",
-.version_id = 1,
-.minimum_version_id = 1,
+.version_id = 2,
+.minimum_version_id = 2,
  .needed = pointermasking_needed,
  .fields = (const VMStateField[]) {
+VMSTATE_UINTTL(env.mseccfg, RISCVCPU),
+VMSTATE_UINTTL(env.senvcfg, RISCVCPU),
+VMSTATE_UINTTL(env.menvcfg, RISCVCPU),
  VMSTATE_END_OF_LIST()
  

Re: [PATCH RFC 0/8] Add Counter delegation ISA extension support

2024-06-01 Thread Daniel Henrique Barboza

Hi Atish,


I see that Rajnesh sent some patches that were built on top of this
work [1], and this series no longer applies neither to alistair's
risc-to-apply.next nor to master.

If you could send a rebased version of this series that would be great.


Thanks,


Daniel



[1] 
https://lore.kernel.org/qemu-riscv/20240529160950.132754-1-rkan...@rivosinc.com/


On 2/16/24 21:01, Atish Patra wrote:

This series adds the counter delegation extension support. The counter
delegation ISA extension(Smcdeleg/Ssccfg) actually depends on multiple ISA
extensions.

1. S[m|s]csrind : The indirect CSR extension[1] which defines additional
5 ([M|S|VS]IREG2-[M|S|VS]IREG6) register to address size limitation of
RISC-V CSR address space.
2. Smstateen: The stateen bit[60] controls the access to the registers
indirectly via the above indirect registers.
3. Smcdeleg/Ssccfg: The counter delegation extensions[2]

The counter delegation extension allows Supervisor mode to program the
hpmevent and hpmcounters directly without needing the assistance from the
M-mode via SBI calls. This results in a faster perf profiling and very
few traps. This extension also introduces a scountinhibit CSR which allows
to stop/start any counter directly from the S-mode. As the counter
delegation extension potentially can have more than 100 CSRs, the specificaiton
leverages the indirect CSR extension to save the precious CSR address range.

Due to the dependancy of these extensions, the following extensions must be
enabled to use the counter delegation feature in S-mode.

"smstateen=true,sscofpmf=true,ssccfg=true,smcdeleg=true,smcsrind=true,sscsrind=true"

This makes the qemu command line quite tedious. In stead of that, I think we
can enable these features by default if there is no objection.

The first 2 patches decouple the indirect CSR usage from AIA implementation
while patch3 adds stateen bits validation for AIA.
The PATCH4 implements indirect CSR extensions while remaining patches
implement the counter delegation extensions.

The Qemu patches can be found here:
https://github.com/atishp04/qemu/tree/counter_delegation_rfc

The opensbi patch can be found here:
https://github.com/atishp04/opensbi/tree/counter_delegation_v1

The Linux kernel patches can be found here:
https://github.com/atishp04/linux/tree/counter_delegation_rfc

[1] https://github.com/riscv/riscv-indirect-csr-access
[2] https://github.com/riscv/riscv-smcdeleg-ssccfg

Atish Patra (1):
target/riscv: Enable S*stateen bits for AIA

Kaiwen Xue (7):
target/riscv: Add properties for Indirect CSR Access extension
target/riscv: Decouple AIA processing from xiselect and xireg
target/riscv: Support generic CSR indirect access
target/riscv: Add smcdeleg/ssccfg properties
target/riscv: Add counter delegation definitions
target/riscv: Add select value range check for counter delegation
target/riscv: Add counter delegation/configuration support

target/riscv/cpu.c  |   8 +
target/riscv/cpu.h  |   1 +
target/riscv/cpu_bits.h |  34 +-
target/riscv/cpu_cfg.h  |   4 +
target/riscv/csr.c  | 713 +---
target/riscv/machine.c  |   1 +
6 files changed, 722 insertions(+), 39 deletions(-)

--
2.34.1





[PATCH v2 2/8] hw/riscv/virt.c: add aplic nodename helper

2024-05-31 Thread Daniel Henrique Barboza
We'll change the aplic DT nodename in the next patch and the name is
hardcoded in 2 different functions. Create a helper to change a single
place later.

While we're at it, in create_fdt_socket_aplic(), move 'aplic_name'
inside the conditional to avoid allocating a string that won't be used
when socket == NULL.

Signed-off-by: Daniel Henrique Barboza 
---
 hw/riscv/virt.c | 13 -
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 1a7e1e73c5..07a07f5ce1 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -588,6 +588,12 @@ static void create_fdt_imsic(RISCVVirtState *s, const 
MemMapEntry *memmap,
 
 }
 
+/* Caller must free string after use */
+static char *fdt_get_aplic_nodename(unsigned long aplic_addr)
+{
+return g_strdup_printf("/soc/aplic@%lx", aplic_addr);
+}
+
 static void create_fdt_one_aplic(RISCVVirtState *s, int socket,
  unsigned long aplic_addr, uint32_t aplic_size,
  uint32_t msi_phandle,
@@ -597,7 +603,7 @@ static void create_fdt_one_aplic(RISCVVirtState *s, int 
socket,
  bool m_mode, int num_harts)
 {
 int cpu;
-g_autofree char *aplic_name = NULL;
+g_autofree char *aplic_name = fdt_get_aplic_nodename(aplic_addr);
 g_autofree uint32_t *aplic_cells = g_new0(uint32_t, num_harts * 2);
 MachineState *ms = MACHINE(s);
 
@@ -606,7 +612,6 @@ static void create_fdt_one_aplic(RISCVVirtState *s, int 
socket,
 aplic_cells[cpu * 2 + 1] = cpu_to_be32(m_mode ? IRQ_M_EXT : IRQ_S_EXT);
 }
 
-aplic_name = g_strdup_printf("/soc/aplic@%lx", aplic_addr);
 qemu_fdt_add_subnode(ms->fdt, aplic_name);
 qemu_fdt_setprop_string(ms->fdt, aplic_name, "compatible", "riscv,aplic");
 qemu_fdt_setprop_cell(ms->fdt, aplic_name, "#address-cells",
@@ -648,7 +653,6 @@ static void create_fdt_socket_aplic(RISCVVirtState *s,
 uint32_t *aplic_phandles,
 int num_harts)
 {
-g_autofree char *aplic_name = NULL;
 unsigned long aplic_addr;
 MachineState *ms = MACHINE(s);
 uint32_t aplic_m_phandle, aplic_s_phandle;
@@ -674,9 +678,8 @@ static void create_fdt_socket_aplic(RISCVVirtState *s,
  aplic_s_phandle, 0,
  false, num_harts);
 
-aplic_name = g_strdup_printf("/soc/aplic@%lx", aplic_addr);
-
 if (!socket) {
+g_autofree char *aplic_name = fdt_get_aplic_nodename(aplic_addr);
 platform_bus_add_all_fdt_nodes(ms->fdt, aplic_name,
memmap[VIRT_PLATFORM_BUS].base,
memmap[VIRT_PLATFORM_BUS].size,
-- 
2.45.1




[PATCH v2 7/8] hw/riscv/virt.c: imsics DT: add 'qemu, imsics' to 'compatible'

2024-05-31 Thread Daniel Henrique Barboza
The DT docs for riscv,imsics [1] predicts a 'qemu,imsics' enum in the
'compatible' property.

[1] Documentation/devicetree/bindings/interrupt-controller/riscv,imsics.yaml

Reported-by: Conor Dooley 
Fixes: 28d8c281200f ("hw/riscv: virt: Add optional AIA IMSIC support to virt 
machine")
Signed-off-by: Daniel Henrique Barboza 
---
 hw/riscv/virt.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 56d7e945c6..ac70993679 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -515,6 +515,9 @@ static void create_fdt_one_imsic(RISCVVirtState *s, hwaddr 
base_addr,
 uint32_t imsic_max_hart_per_socket, imsic_addr, imsic_size;
 g_autofree uint32_t *imsic_cells = NULL;
 g_autofree uint32_t *imsic_regs = NULL;
+static const char * const imsic_compat[2] = {
+"qemu,imsics", "riscv,imsics"
+};
 
 imsic_cells = g_new0(uint32_t, ms->smp.cpus * 2);
 imsic_regs = g_new0(uint32_t, socket_count * 4);
@@ -541,7 +544,10 @@ static void create_fdt_one_imsic(RISCVVirtState *s, hwaddr 
base_addr,
 imsic_name = g_strdup_printf("/soc/interrupt-controller@%lx",
  (unsigned long)base_addr);
 qemu_fdt_add_subnode(ms->fdt, imsic_name);
-qemu_fdt_setprop_string(ms->fdt, imsic_name, "compatible", "riscv,imsics");
+qemu_fdt_setprop_string_array(ms->fdt, imsic_name, "compatible",
+  (char **)_compat,
+  ARRAY_SIZE(imsic_compat));
+
 qemu_fdt_setprop_cell(ms->fdt, imsic_name, "#interrupt-cells",
   FDT_IMSIC_INT_CELLS);
 qemu_fdt_setprop(ms->fdt, imsic_name, "interrupt-controller", NULL, 0);
-- 
2.45.1




[PATCH v2 5/8] hw/riscv/virt.c: aplic DT: rename prop to 'riscv, delegation'

2024-05-31 Thread Daniel Henrique Barboza
The DT docs for riscv,aplic [1] predicts a 'riscv,delegation' property.
Not 'riscv,delegate'.

[1] Documentation/devicetree/bindings/interrupt-controller/riscv,aplic.yaml

Reported-by: Conor Dooley 
Fixes: e6faee65855b ("hw/riscv: virt: Add optional AIA APLIC support to virt 
machine")
Signed-off-by: Daniel Henrique Barboza 
---
 hw/riscv/virt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 366fe042cc..0a18547c6d 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -640,7 +640,7 @@ static void create_fdt_one_aplic(RISCVVirtState *s, int 
socket,
 if (aplic_child_phandle) {
 qemu_fdt_setprop_cell(ms->fdt, aplic_name, "riscv,children",
   aplic_child_phandle);
-qemu_fdt_setprop_cells(ms->fdt, aplic_name, "riscv,delegate",
+qemu_fdt_setprop_cells(ms->fdt, aplic_name, "riscv,delegation",
aplic_child_phandle, 0x1,
VIRT_IRQCHIP_NUM_SOURCES);
 }
-- 
2.45.1




[PATCH v2 4/8] hw/riscv/virt.c: aplic DT: add 'qemu, aplic' to 'compatible'

2024-05-31 Thread Daniel Henrique Barboza
The DT docs for riscv,aplic [1] predicts a 'qemu,aplic' enum in the
'compatible' property.

[1] Documentation/devicetree/bindings/interrupt-controller/riscv,aplic.yaml

Reported-by: Conor Dooley 
Fixes: e6faee65855b ("hw/riscv: virt: Add optional AIA APLIC support to virt 
machine")
Signed-off-by: Daniel Henrique Barboza 
---
 hw/riscv/virt.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 5505047945..366fe042cc 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -606,6 +606,9 @@ static void create_fdt_one_aplic(RISCVVirtState *s, int 
socket,
 g_autofree char *aplic_name = fdt_get_aplic_nodename(aplic_addr);
 g_autofree uint32_t *aplic_cells = g_new0(uint32_t, num_harts * 2);
 MachineState *ms = MACHINE(s);
+static const char * const aplic_compat[2] = {
+"qemu,aplic", "riscv,aplic"
+};
 
 for (cpu = 0; cpu < num_harts; cpu++) {
 aplic_cells[cpu * 2 + 0] = cpu_to_be32(intc_phandles[cpu]);
@@ -613,7 +616,9 @@ static void create_fdt_one_aplic(RISCVVirtState *s, int 
socket,
 }
 
 qemu_fdt_add_subnode(ms->fdt, aplic_name);
-qemu_fdt_setprop_string(ms->fdt, aplic_name, "compatible", "riscv,aplic");
+qemu_fdt_setprop_string_array(ms->fdt, aplic_name, "compatible",
+  (char **)_compat,
+  ARRAY_SIZE(aplic_compat));
 qemu_fdt_setprop_cell(ms->fdt, aplic_name, "#address-cells",
   FDT_APLIC_ADDR_CELLS);
 qemu_fdt_setprop_cell(ms->fdt, aplic_name,
-- 
2.45.1




[PATCH v2 0/8] hw/riscv/virt.c: aplic/imsic DT fixes

2024-05-31 Thread Daniel Henrique Barboza
Hi,

This is a series that is being spun from the reviews given on patch 1
[1]. We'll fix some DT validation issues we have in the 'virt' machine
[2] that aren't related to missing extensions in the DT spec.

I'll leave to maintainers to squash the patches as they see fit. I
split it this way to make it easier to bissect possible bugs that these
individual changes can cause.

These are the types of DT warnings solved by this series:

/home/danielhb/work/qemu/riscv64_virt.dtb: aplic@d00: $nodename:0: 
'aplic@d00' does not match '^interrupt-controller(@[0-9a-f,]+)*$'
from schema $id: 
http://devicetree.org/schemas/interrupt-controller/riscv,aplic.yaml#
/home/danielhb/work/qemu/riscv64_virt.dtb: aplic@d00: compatible:0: 
'riscv,aplic' is not one of ['qemu,aplic']
from schema $id: 
http://devicetree.org/schemas/interrupt-controller/riscv,aplic.yaml#
/home/danielhb/work/qemu/riscv64_virt.dtb: aplic@d00: compatible: 
['riscv,aplic'] is too short
from schema $id: 
http://devicetree.org/schemas/interrupt-controller/riscv,aplic.yaml#
/home/danielhb/work/qemu/riscv64_virt.dtb: aplic@d00: Unevaluated 
properties are not allowed ('compatible' was unexpected)
from schema $id: 
http://devicetree.org/schemas/interrupt-controller/riscv,aplic.yaml#
(...)
/home/danielhb/work/qemu/riscv64_virt.dtb: imsics@2800: $nodename:0: 
'imsics@2800' does not match '^interrupt-controller(@[0-9a-f,]+)*$'
from schema $id: 
http://devicetree.org/schemas/interrupt-controller/riscv,imsics.yaml#
/home/danielhb/work/qemu/riscv64_virt.dtb: imsics@2800: compatible:0: 
'riscv,imsics' is not one of ['qemu,imsics']
from schema $id: 
http://devicetree.org/schemas/interrupt-controller/riscv,imsics.yaml#
/home/danielhb/work/qemu/riscv64_virt.dtb: imsics@2800: compatible: 
['riscv,imsics'] is too short
from schema $id: 
http://devicetree.org/schemas/interrupt-controller/riscv,imsics.yaml#
/home/danielhb/work/qemu/riscv64_virt.dtb: imsics@2800: '#msi-cells' is a 
required property
from schema $id: 
http://devicetree.org/schemas/interrupt-controller/riscv,imsics.yaml#
/home/danielhb/work/qemu/riscv64_virt.dtb: imsics@2800: Unevaluated 
properties are not allowed ('compatible' was unexpected)
from schema $id: 
http://devicetree.org/schemas/interrupt-controller/riscv,imsics.yaml#

[3] explains how to run 'dt-validate' to reproduce them. To generate a
'processed schema' file what I did was:

- in the Linux kernel tree, run 'make dt_binding_check'. Please note
  that this might require installation of additional python stuff
  (e.g.swig, python3-devel)

- I used the generated file 
'Documentation/devicetree/bindings/processed-schema.json'
  as a 'processed schema'.

Series applicable on both master and alistair/riscv-to-apply.next. 

Changes from v1:
- added patches 2 to 7 to fix the dt-validate warnings on imsics and
  aplic notes
- v1 link: 
https://lore.kernel.org/qemu-riscv/20240530084949.761034-1-dbarb...@ventanamicro.com/

[1] 
https://lore.kernel.org/qemu-riscv/20240530084949.761034-1-dbarb...@ventanamicro.com/
[2] https://lore.kernel.org/all/20240529-rust-tile-a05517a6260f@spud/
[3] 
https://lore.kernel.org/qemu-riscv/20240530-landed-shriek-9362981afade@spud/ 

Daniel Henrique Barboza (8):
  hw/riscv/virt.c: add address-cells in create_fdt_one_aplic()
  hw/riscv/virt.c: add aplic nodename helper
  hw/riscv/virt.c: rename aplic nodename to 'interrupt-controller'
  hw/riscv/virt.c: aplic DT: add 'qemu,aplic' to 'compatible'
  hw/riscv/virt.c: aplic DT: rename prop to 'riscv,delegation'
  hw/riscv/virt.c: change imsic nodename to 'interrupt-controller'
  hw/riscv/virt.c: imsics DT: add 'qemu,imsics' to 'compatible'
  hw/riscv/virt.c: imsics DT: add '#msi-cells'

 hw/riscv/virt.c | 36 +++-
 include/hw/riscv/virt.h |  1 +
 2 files changed, 28 insertions(+), 9 deletions(-)

-- 
2.45.1




[PATCH v2 8/8] hw/riscv/virt.c: imsics DT: add '#msi-cells'

2024-05-31 Thread Daniel Henrique Barboza
The DT docs for riscv,imsics [1] requires a 'msi-cell' property. Add one
and set it zero.

[1] Documentation/devicetree/bindings/interrupt-controller/riscv,imsics.yaml

Reported-by: Conor Dooley 
Fixes: 28d8c281200f ("hw/riscv: virt: Add optional AIA IMSIC support to virt 
machine")
Signed-off-by: Daniel Henrique Barboza 
---
 hw/riscv/virt.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index ac70993679..8675c3a7d1 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -552,6 +552,7 @@ static void create_fdt_one_imsic(RISCVVirtState *s, hwaddr 
base_addr,
   FDT_IMSIC_INT_CELLS);
 qemu_fdt_setprop(ms->fdt, imsic_name, "interrupt-controller", NULL, 0);
 qemu_fdt_setprop(ms->fdt, imsic_name, "msi-controller", NULL, 0);
+qemu_fdt_setprop_cell(ms->fdt, imsic_name, "#msi-cells", 0);
 qemu_fdt_setprop(ms->fdt, imsic_name, "interrupts-extended",
  imsic_cells, ms->smp.cpus * sizeof(uint32_t) * 2);
 qemu_fdt_setprop(ms->fdt, imsic_name, "reg", imsic_regs,
-- 
2.45.1




[PATCH v2 3/8] hw/riscv/virt.c: rename aplic nodename to 'interrupt-controller'

2024-05-31 Thread Daniel Henrique Barboza
The correct name of the aplic controller node, as per Linux kernel DT
docs [1], is 'interrupt-controller@addr'.

[1] Documentation/devicetree/bindings/interrupt-controller/riscv,aplic.yaml

Reported-by: Conor Dooley 
Fixes: e6faee65855b ("hw/riscv: virt: Add optional AIA APLIC support to virt 
machine")
Signed-off-by: Daniel Henrique Barboza 
---
 hw/riscv/virt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 07a07f5ce1..5505047945 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -591,7 +591,7 @@ static void create_fdt_imsic(RISCVVirtState *s, const 
MemMapEntry *memmap,
 /* Caller must free string after use */
 static char *fdt_get_aplic_nodename(unsigned long aplic_addr)
 {
-return g_strdup_printf("/soc/aplic@%lx", aplic_addr);
+return g_strdup_printf("/soc/interrupt-controller@%lx", aplic_addr);
 }
 
 static void create_fdt_one_aplic(RISCVVirtState *s, int socket,
-- 
2.45.1




[PATCH v2 6/8] hw/riscv/virt.c: change imsic nodename to 'interrupt-controller'

2024-05-31 Thread Daniel Henrique Barboza
The Linux DT docs for imsic [1] predicts an 'interrupt-controller@addr'
node, not 'imsic@addr', given this node inherits the
'interrupt-controller' node.

[1] Documentation/devicetree/bindings/interrupt-controller/riscv,imsics.yaml

Reported-by: Conor Dooley 
Fixes: 28d8c281200f ("hw/riscv: virt: Add optional AIA IMSIC support to virt 
machine")
Signed-off-by: Daniel Henrique Barboza 
---
 hw/riscv/virt.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 0a18547c6d..56d7e945c6 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -538,7 +538,8 @@ static void create_fdt_one_imsic(RISCVVirtState *s, hwaddr 
base_addr,
 }
 }
 
-imsic_name = g_strdup_printf("/soc/imsics@%lx", (unsigned long)base_addr);
+imsic_name = g_strdup_printf("/soc/interrupt-controller@%lx",
+ (unsigned long)base_addr);
 qemu_fdt_add_subnode(ms->fdt, imsic_name);
 qemu_fdt_setprop_string(ms->fdt, imsic_name, "compatible", "riscv,imsics");
 qemu_fdt_setprop_cell(ms->fdt, imsic_name, "#interrupt-cells",
-- 
2.45.1




[PATCH v2 1/8] hw/riscv/virt.c: add address-cells in create_fdt_one_aplic()

2024-05-31 Thread Daniel Henrique Barboza
We need #address-cells properties in all interrupt controllers that are
referred by an interrupt-map [1]. For the RISC-V machine, both PLIC and
APLIC controllers must have this property.

PLIC already sets it in create_fdt_socket_plic(). Set the property for
APLIC in create_fdt_one_aplic().

[1] 
https://lore.kernel.org/linux-arm-kernel/cal_jsqje15d-xxxmelsmud+jqhzzxgzdxvikchn6kfwqk6n...@mail.gmail.com/

Suggested-by: Anup Patel 
Fixes: e6faee65855b ("hw/riscv: virt: Add optional AIA APLIC support to virt 
machine")
Signed-off-by: Daniel Henrique Barboza 
---
 hw/riscv/virt.c | 2 ++
 include/hw/riscv/virt.h | 1 +
 2 files changed, 3 insertions(+)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 4fdb660525..1a7e1e73c5 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -609,6 +609,8 @@ static void create_fdt_one_aplic(RISCVVirtState *s, int 
socket,
 aplic_name = g_strdup_printf("/soc/aplic@%lx", aplic_addr);
 qemu_fdt_add_subnode(ms->fdt, aplic_name);
 qemu_fdt_setprop_string(ms->fdt, aplic_name, "compatible", "riscv,aplic");
+qemu_fdt_setprop_cell(ms->fdt, aplic_name, "#address-cells",
+  FDT_APLIC_ADDR_CELLS);
 qemu_fdt_setprop_cell(ms->fdt, aplic_name,
   "#interrupt-cells", FDT_APLIC_INT_CELLS);
 qemu_fdt_setprop(ms->fdt, aplic_name, "interrupt-controller", NULL, 0);
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
index 3db839160f..c0dc41ff9a 100644
--- a/include/hw/riscv/virt.h
+++ b/include/hw/riscv/virt.h
@@ -118,6 +118,7 @@ enum {
 #define FDT_PLIC_ADDR_CELLS   0
 #define FDT_PLIC_INT_CELLS1
 #define FDT_APLIC_INT_CELLS   2
+#define FDT_APLIC_ADDR_CELLS  0
 #define FDT_IMSIC_INT_CELLS   0
 #define FDT_MAX_INT_CELLS 2
 #define FDT_MAX_INT_MAP_WIDTH (FDT_PCI_ADDR_CELLS + FDT_PCI_INT_CELLS + \
-- 
2.45.1




Re: [PATCH] hw/riscv/virt.c: add address-cells in create_fdt_one_aplic()

2024-05-30 Thread Daniel Henrique Barboza




On 5/30/24 08:06, Andrew Jones wrote:

On Thu, May 30, 2024 at 01:05:41PM GMT, Andrew Jones wrote:

On Thu, May 30, 2024 at 05:49:49AM GMT, Daniel Henrique Barboza wrote:

We need #address-cells properties in all interrupt controllers that are
referred by an interrupt-map [1]. For the RISC-V machine, both PLIC and
APLIC controllers must have this property.

PLIC already sets it in create_fdt_socket_plic(). Set the property for
APLIC in create_fdt_one_aplic().

[1] 
https://lore.kernel.org/linux-arm-kernel/cal_jsqje15d-xxxmelsmud+jqhzzxgzdxvikchn6kfwqk6n...@mail.gmail.com/


There are other issues[2] with the DT nodes that we should address at the
same time.

[2] https://lore.kernel.org/all/20240529-rust-tile-a05517a6260f@spud/


I meant to CC Conor. Doing that now.


I'll take a look at these other DT nodes issues.

Conor, mind give me pointers on how do I reproduce the validation you did
in [2]? Using upstream 'dtc' I have stuff like:

../qemu/qemu_dts.dts:261.4-68: Warning (interrupts_extended_property): 
/soc/aplic@d00:interrupts-extended: cell 0 is not a phandle reference

Which seems to also be an error but it's not what you reported. Are you
using 'dt-validate' from dt-schema?


Thanks,

Daniel





Thanks,
drew



Suggested-by: Anup Patel 
Fixes: e6faee65855b ("hw/riscv: virt: Add optional AIA APLIC support to virt 
machine")
Signed-off-by: Daniel Henrique Barboza 
---
  hw/riscv/virt.c | 2 ++
  include/hw/riscv/virt.h | 1 +
  2 files changed, 3 insertions(+)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 4fdb660525..1a7e1e73c5 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -609,6 +609,8 @@ static void create_fdt_one_aplic(RISCVVirtState *s, int 
socket,
  aplic_name = g_strdup_printf("/soc/aplic@%lx", aplic_addr);
  qemu_fdt_add_subnode(ms->fdt, aplic_name);
  qemu_fdt_setprop_string(ms->fdt, aplic_name, "compatible", "riscv,aplic");
+qemu_fdt_setprop_cell(ms->fdt, aplic_name, "#address-cells",
+  FDT_APLIC_ADDR_CELLS);
  qemu_fdt_setprop_cell(ms->fdt, aplic_name,
"#interrupt-cells", FDT_APLIC_INT_CELLS);
  qemu_fdt_setprop(ms->fdt, aplic_name, "interrupt-controller", NULL, 0);
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
index 3db839160f..c0dc41ff9a 100644
--- a/include/hw/riscv/virt.h
+++ b/include/hw/riscv/virt.h
@@ -118,6 +118,7 @@ enum {
  #define FDT_PLIC_ADDR_CELLS   0
  #define FDT_PLIC_INT_CELLS1
  #define FDT_APLIC_INT_CELLS   2
+#define FDT_APLIC_ADDR_CELLS  0
  #define FDT_IMSIC_INT_CELLS   0
  #define FDT_MAX_INT_CELLS 2
  #define FDT_MAX_INT_MAP_WIDTH (FDT_PCI_ADDR_CELLS + FDT_PCI_INT_CELLS + \
--
2.45.1






Re: [RESEND PATCH v2 0/5] target/riscv: Support RISC-V privilege 1.13 spec

2024-05-30 Thread Daniel Henrique Barboza

Hi Fea,

On 5/30/24 00:30, Fea Wang wrote:

Hi Daniel,
thank you for your help.

I found that only the cover is without many maintainers. I used to send patches by git send-email 
--dry-run --to 'qemu-devel@nongnu.org <mailto:qemu-devel@nongnu.org>,qemu-ri...@nongnu.org 
<mailto:qemu-ri...@nongnu.org>' --cc-cmd='scripts/get_maintainer.pl 
<http://get_maintainer.pl> -i' patches/*. Do you have a better script for me?


Hmmm no I don't actually :) my script is worse than yours. I just use a git
alias that hardcode everyone in the CC:

askreview-riscv = send-email --suppress-cc=sob --to 
qemu-devel@nongnu.org \
--cc qemu-ri...@nongnu.org \
--cc (everyone from the output of get_maintainers.pl for RISC-V 
files)

And then "git askreview-riscv (patches)"

From reading git docs it seems like one detail with your script is that the CC
is calculated patch by patch via the "--cc-cmd" output, but the cover letter is
considered an empty commit, so the script returns nothing. This is why every
other patch has a CC but the cover doesn't.

This is more a get_maintainer.pl detail than anything, so don't worry about it.
Having the patches properly CCed is enough. We'll go after the cover-letter
manually if needed.


Thanks,

Daniel



Thank you.

Sincerely,
Fea

On Mon, May 27, 2024 at 5:21 PM Daniel Henrique Barboza mailto:dbarb...@ventanamicro.com>> wrote:

Fea,

Please try to also add all RISC-V QEMU maintainers and reviewers when 
sending
patches. It will get your patches reviewed and queued faster. Otherwise the
maintainers can miss you your series due to high ML traffic.

You can fetch who you want to CC using the get_maintainer.pl 
<http://get_maintainer.pl> script with the
patch files or any source file in particular, e.g.:

$ ./scripts/get_maintainer.pl <http://get_maintainer.pl> -f 
target/riscv/cpu.c
Palmer Dabbelt mailto:pal...@dabbelt.com>> 
(supporter:RISC-V TCG CPUs)
Alistair Francis mailto:alistair.fran...@wdc.com>> (supporter:RISC-V TCG CPUs)
Bin Meng mailto:bmeng...@gmail.com>> (supporter:RISC-V 
TCG CPUs)
    Weiwei Li mailto:liwei1...@gmail.com>> 
(reviewer:RISC-V TCG CPUs)
Daniel Henrique Barboza mailto:dbarb...@ventanamicro.com>> (reviewer:RISC-V TCG CPUs)
Liu Zhiwei mailto:zhiwei_...@linux.alibaba.com>> (reviewer:RISC-V TCG CPUs)
qemu-ri...@nongnu.org <mailto:qemu-ri...@nongnu.org> (open list:RISC-V TCG 
CPUs)
qemu-devel@nongnu.org <mailto:qemu-devel@nongnu.org> (open list:All patches 
CC here)


I added the extra folk in the CC for this reply so don't worry about it.


Alistair, please queue this series. It's already fully acked and I would 
like to add
some bits on top of the priv_spec 1.13 support.


Thanks,


Daniel

On 5/15/24 05:05, Fea.Wang wrote:
 > Based on the change log for the RISC-V privilege 1.13 spec, add the
 > support for ss1p13.
 >
 > 
Ref:https://github.com/riscv/riscv-isa-manual/blob/a7d93c9/src/priv-preface.adoc?plain=1#L40-L72
 
<https://github.com/riscv/riscv-isa-manual/blob/a7d93c9/src/priv-preface.adoc?plain=1#L40-L72>
 >
 > Lists what to do without clarification or document format.
 > * Redefined misa.MXL to be read-only, making MXLEN a constant.(Skip, 
implementation ignored)
 > * Added the constraint that SXLEN≥UXLEN.(Skip, implementation ignored)
 > * Defined the misa.V field to reflect that the V extension has been 
implemented.(Skip, existed)
 > * Defined the RV32-only medelegh and hedelegh CSRs.(Done in these 
patches)
 > * Defined the misaligned atomicity granule PMA, superseding the proposed 
Zam extension..(Skip, implementation ignored)
 > * Allocated interrupt 13 for Sscofpmf LCOFI interrupt.(Skip, existed)
 > * Defined hardware error and software check exception codes.(Done in 
these patches)
 > * Specified synchronization requirements when changing the PBMTE fields 
in menvcfg and henvcfg.(Skip, implementation ignored)
 > * Incorporated Svade and Svadu extension specifications.(Skip, existed)
 >
 >
 > Fea.Wang (4):
 >    target/riscv: Support the version for ss1p13
 >    target/riscv: Add 'P1P13' bit in SMSTATEEN0
 >    target/riscv: Add MEDELEGH, HEDELEGH csrs for RV32
 >    target/riscv: Reserve exception codes for sw-check and hw-err
 >
 > Jim Shu (1):
 >    target/riscv: Reuse the conversion function of priv_spec
 >
 >   target/riscv/cpu.c         |  8 ++--
 >   target/riscv/cpu.h         |  5 -
 >   target/riscv/cpu_bits.h    |  5 +
 >   target/riscv/cpu_cfg.h     |  1 +
 >   target/riscv/csr.c         | 39 ++
 >   target/riscv/tcg/tcg-cpu.c | 17 -
 >   6 files changed, 63 insertions(+), 12 deletions(-)
 >





[PATCH] hw/riscv/virt.c: add address-cells in create_fdt_one_aplic()

2024-05-30 Thread Daniel Henrique Barboza
We need #address-cells properties in all interrupt controllers that are
referred by an interrupt-map [1]. For the RISC-V machine, both PLIC and
APLIC controllers must have this property.

PLIC already sets it in create_fdt_socket_plic(). Set the property for
APLIC in create_fdt_one_aplic().

[1] 
https://lore.kernel.org/linux-arm-kernel/cal_jsqje15d-xxxmelsmud+jqhzzxgzdxvikchn6kfwqk6n...@mail.gmail.com/

Suggested-by: Anup Patel 
Fixes: e6faee65855b ("hw/riscv: virt: Add optional AIA APLIC support to virt 
machine")
Signed-off-by: Daniel Henrique Barboza 
---
 hw/riscv/virt.c | 2 ++
 include/hw/riscv/virt.h | 1 +
 2 files changed, 3 insertions(+)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 4fdb660525..1a7e1e73c5 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -609,6 +609,8 @@ static void create_fdt_one_aplic(RISCVVirtState *s, int 
socket,
 aplic_name = g_strdup_printf("/soc/aplic@%lx", aplic_addr);
 qemu_fdt_add_subnode(ms->fdt, aplic_name);
 qemu_fdt_setprop_string(ms->fdt, aplic_name, "compatible", "riscv,aplic");
+qemu_fdt_setprop_cell(ms->fdt, aplic_name, "#address-cells",
+  FDT_APLIC_ADDR_CELLS);
 qemu_fdt_setprop_cell(ms->fdt, aplic_name,
   "#interrupt-cells", FDT_APLIC_INT_CELLS);
 qemu_fdt_setprop(ms->fdt, aplic_name, "interrupt-controller", NULL, 0);
diff --git a/include/hw/riscv/virt.h b/include/hw/riscv/virt.h
index 3db839160f..c0dc41ff9a 100644
--- a/include/hw/riscv/virt.h
+++ b/include/hw/riscv/virt.h
@@ -118,6 +118,7 @@ enum {
 #define FDT_PLIC_ADDR_CELLS   0
 #define FDT_PLIC_INT_CELLS1
 #define FDT_APLIC_INT_CELLS   2
+#define FDT_APLIC_ADDR_CELLS  0
 #define FDT_IMSIC_INT_CELLS   0
 #define FDT_MAX_INT_CELLS 2
 #define FDT_MAX_INT_MAP_WIDTH (FDT_PCI_ADDR_CELLS + FDT_PCI_INT_CELLS + \
-- 
2.45.1




Re: [PATCH 1/1] target/riscv: Support Zama16b extension

2024-05-27 Thread Daniel Henrique Barboza

Zhiwei,

On 5/22/24 06:13, LIU Zhiwei wrote:

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 eb1a2e7d6d..911e9892ed 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -117,6 +117,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_12_0, ext_zama16b),



Isn't zama16b a 1.13 spec extension? Looking it up I think it is.

In this case I think it's wise to make this patch (and any other 1.13 extension
that we might be adding now) dependent on

"[RESEND PATCH v2 0/5] target/riscv: Support RISC-V privilege 1.13 spec​"

And then we can set the proper spec versions for each one. Thanks,


Daniel


  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),
@@ -1464,6 +1465,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("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 cb750154bd..eaa66eb4f8 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -81,6 +81,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);
-

Re: [PATCH v2 1/3] hw/riscv/virt: Add memory hotplugging and virtio-md-pci support

2024-05-27 Thread Daniel Henrique Barboza




On 5/27/24 09:03, Björn Töpel wrote:

David Hildenbrand  writes:


On 24.05.24 15:14, Daniel Henrique Barboza wrote:



On 5/21/24 07:56, Björn Töpel wrote:

From: Björn Töpel 

Virtio-based memory devices (virtio-mem/virtio-pmem) allows for
dynamic resizing of virtual machine memory, and requires proper
hotplugging (add/remove) support to work.

Add device memory support for RISC-V "virt" machine, and enable
virtio-md-pci with the corresponding missing hotplugging callbacks.

Signed-off-by: Björn Töpel 
---
hw/riscv/Kconfig   |  2 +
hw/riscv/virt.c| 83 +-
hw/virtio/virtio-mem.c |  5 ++-
3 files changed, 87 insertions(+), 3 deletions(-)

diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
index a2030e3a6ff0..08f82dbb681a 100644
--- a/hw/riscv/Kconfig
+++ b/hw/riscv/Kconfig
@@ -56,6 +56,8 @@ config RISCV_VIRT
select PLATFORM_BUS
select ACPI
select ACPI_PCI
+select VIRTIO_MEM_SUPPORTED
+select VIRTIO_PMEM_SUPPORTED

config SHAKTI_C

bool
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 4fdb66052587..443902f919d2 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -53,6 +53,8 @@
#include "hw/pci-host/gpex.h"
#include "hw/display/ramfb.h"
#include "hw/acpi/aml-build.h"
+#include "hw/mem/memory-device.h"
+#include "hw/virtio/virtio-mem-pci.h"
#include "qapi/qapi-visit-common.h"
#include "hw/virtio/virtio-iommu.h"

@@ -1407,6 +1409,7 @@ static void virt_machine_init(MachineState *machine)

DeviceState *mmio_irqchip, *virtio_irqchip, *pcie_irqchip;
int i, base_hartid, hart_count;
int socket_count = riscv_socket_count(machine);
+hwaddr device_memory_base, device_memory_size;

/* Check socket count limit */

if (VIRT_SOCKETS_MAX < socket_count) {
@@ -1420,6 +1423,12 @@ static void virt_machine_init(MachineState *machine)
exit(1);
}

+if (machine->ram_slots > ACPI_MAX_RAM_SLOTS) {

+error_report("unsupported amount of memory slots: %"PRIu64,
+ machine->ram_slots);
+exit(EXIT_FAILURE);
+}
+
/* Initialize sockets */
mmio_irqchip = virtio_irqchip = pcie_irqchip = NULL;
for (i = 0; i < socket_count; i++) {
@@ -1553,6 +1562,37 @@ static void virt_machine_init(MachineState *machine)
memory_region_add_subregion(system_memory, memmap[VIRT_MROM].base,
mask_rom);

+/* device memory */

+device_memory_base = ROUND_UP(s->memmap[VIRT_DRAM].base + 
machine->ram_size,
+  GiB);
+device_memory_size = machine->maxram_size - machine->ram_size;
+if (device_memory_size > 0) {
+/*
+ * Each DIMM is aligned based on the backend's alignment value.
+ * Assume max 1G hugepage alignment per slot.
+ */
+device_memory_size += machine->ram_slots * GiB;


We don't need to align to 1GiB. This calc can use 2MiB instead (or 4MiB if we're
running 32 bits).


+
+if (riscv_is_32bit(>soc[0])) {
+hwaddr memtop = device_memory_base + ROUND_UP(device_memory_size,
+  GiB);


Same here - alignment is 2/4 MiB.


+
+if (memtop > UINT32_MAX) {
+error_report("memory exceeds 32-bit limit by %lu bytes",
+ memtop - UINT32_MAX);
+exit(EXIT_FAILURE);
+}
+}
+
+if (device_memory_base + device_memory_size < device_memory_size) {
+error_report("unsupported amount of device memory");
+exit(EXIT_FAILURE);
+}


Took another look and found this a bit strange. These are all unsigned vars, so
if (unsigned a + unsigned b < unsigned b) will always be 'false'. The compiler 
is
probably cropping this out.


No. Unsigned interger overflow is defined behavior and this is a common
check to detect such overflow. tI's consistent with what we do for other
architectures.



The calc we need to do is to ensure that the extra ram_slots * alignment will 
fit into
the VIRT_DRAM block, i.e. maxram_size + (ram_slots * alignment) < 
memmap[VIRT_DRAM].size.


TBH I'm starting to have second thoughts about letting users hotplug whatever 
they want.
It seems cleaner to just force the 2/4 Mb alignment in pre_plug() and be done 
with it,
no need to allocate ram_slots * alignment and doing all these extra checks.


It's worth noting that if user space decides to specify addresses
manually, it can mess up everything already. There are other events that
can result in fragmentation of the memory device area (repeated
hot(un)plug of differing DIMMs).

Assume you have 1 GiB range and hotplug a 512 MiB DIMM at offset 256
MiB. Y

Re: [PATCH v6 0/3] Support RISC-V IOPMP

2024-05-27 Thread Daniel Henrique Barboza

Hi Ethan,


Did you send v7 already and I somehow missed it? This is the latest version I
have for this IOPMP work in my inbox.

If this is the latest, do you plan to send a new version? Most of the comments
made in patche 2 are simple code style changes and there's no technical reason 
to
not get this work merged for this release.


Thanks,

Daniel

On 2/7/24 06:34, Ethan Chen wrote:

This series implements IOPMP specification v1.0.0-draft4 rapid-k model and add
IOPMP device to RISC-V virt machine.

Patch 1 add config STREAM make other device can reuse /hw/core/stream.c, IOPMP
implementation will use it. Patch 2 implement IOPMP deivce. Patch 3 add IOPMP
device to RISC-V virt machine.

The IOPMP specification url:
https://github.com/riscv-non-isa/iopmp-spec/blob/main/riscv_iopmp_specification.pdf

Changes for v6:
   - Rebased
   - IOPMP: Fix MDLCK_MD and ENTRYLCK_F did not lock correspond registers
Fix iopmp_write for ENTRY_ADDRH and ENTRYLCK_L
   - Refine coding style (Daniel Henrique Barboza)

Thanks,
Ethan Chen

Ethan Chen (3):
   hw/core: Add config stream
   Add RISC-V IOPMP support
   hw/riscv/virt: Add IOPMP support

  docs/system/riscv/virt.rst|   12 +
  hw/Kconfig|1 +
  hw/core/Kconfig   |3 +
  hw/core/meson.build   |2 +-
  hw/misc/Kconfig   |4 +
  hw/misc/meson.build   |1 +
  hw/misc/riscv_iopmp.c | 1202 +
  hw/misc/trace-events  |4 +
  hw/riscv/Kconfig  |1 +
  hw/riscv/virt.c   |  110 +-
  include/hw/misc/riscv_iopmp.h |  187 +++
  .../hw/misc/riscv_iopmp_transaction_info.h|   28 +
  include/hw/riscv/virt.h   |8 +-
  13 files changed, 1559 insertions(+), 4 deletions(-)
  create mode 100644 hw/misc/riscv_iopmp.c
  create mode 100644 include/hw/misc/riscv_iopmp.h
  create mode 100644 include/hw/misc/riscv_iopmp_transaction_info.h





Re: [PATCH v1 4/4] target/riscv/kvm: define TARGET_KVM_HAVE_GUEST_DEBUG

2024-05-27 Thread Daniel Henrique Barboza




On 5/26/24 23:19, Chao Du wrote:

To enable the KVM GUEST DEBUG for RISC-V at QEMU side.

Signed-off-by: Chao Du 
---


Reviewed-by: Daniel Henrique Barboza 


  configs/targets/riscv64-softmmu.mak | 1 +
  1 file changed, 1 insertion(+)

diff --git a/configs/targets/riscv64-softmmu.mak 
b/configs/targets/riscv64-softmmu.mak
index 7c0e7eeb42..f938cc1ee6 100644
--- a/configs/targets/riscv64-softmmu.mak
+++ b/configs/targets/riscv64-softmmu.mak
@@ -1,5 +1,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_NEED_FDT=y




Re: [PATCH v1 2/4] target/riscv/kvm: implement kvm_arch_update_guest_debug()

2024-05-27 Thread Daniel Henrique Barboza




On 5/26/24 23:19, Chao Du wrote:

Set the control flag when there are active breakpoints. This will
help KVM to know the status in the userspace.

Signed-off-by: Chao Du 
---


Reviewed-by: Daniel Henrique Barboza 


  target/riscv/kvm/kvm-cpu.c | 4 +++-
  1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
index cba55c552d..0bc3348b91 100644
--- a/target/riscv/kvm/kvm-cpu.c
+++ b/target/riscv/kvm/kvm-cpu.c
@@ -2039,5 +2039,7 @@ void kvm_arch_remove_all_hw_breakpoints(void)
  
  void kvm_arch_update_guest_debug(CPUState *cs, struct kvm_guest_debug *dbg)

  {
-/* TODO; To be implemented later. */
+if (kvm_sw_breakpoints_active(cs)) {
+dbg->control |= KVM_GUESTDBG_ENABLE;
+}
  }




Re: [PATCH v1 3/4] target/riscv/kvm: handle the exit with debug reason

2024-05-27 Thread Daniel Henrique Barboza




On 5/26/24 23:19, Chao Du wrote:

If the breakpoint belongs to the userspace then set the ret value.

Signed-off-by: Chao Du 
---


Reviewed-by: Daniel Henrique Barboza 


  target/riscv/kvm/kvm-cpu.c | 20 
  1 file changed, 20 insertions(+)

diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
index 0bc3348b91..0c45e520b2 100644
--- a/target/riscv/kvm/kvm-cpu.c
+++ b/target/riscv/kvm/kvm-cpu.c
@@ -1555,6 +1555,21 @@ static int kvm_riscv_handle_csr(CPUState *cs, struct 
kvm_run *run)
  return ret;
  }
  
+static bool kvm_riscv_handle_debug(CPUState *cs)

+{
+RISCVCPU *cpu = RISCV_CPU(cs);
+CPURISCVState *env = >env;
+
+/* Ensure PC is synchronised */
+kvm_cpu_synchronize_state(cs);
+
+if (kvm_find_sw_breakpoint(cs, env->pc)) {
+return true;
+}
+
+return false;
+}
+
  int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
  {
  int ret = 0;
@@ -1565,6 +1580,11 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run 
*run)
  case KVM_EXIT_RISCV_CSR:
  ret = kvm_riscv_handle_csr(cs, run);
  break;
+case KVM_EXIT_DEBUG:
+if (kvm_riscv_handle_debug(cs)) {
+ret = EXCP_DEBUG;
+}
+break;
  default:
  qemu_log_mask(LOG_UNIMP, "%s: un-handled exit reason %d\n",
__func__, run->exit_reason);




Re: [PATCH v1 1/4] target/riscv/kvm: add software breakpoints support

2024-05-27 Thread Daniel Henrique Barboza




On 5/26/24 23:19, Chao Du wrote:

This patch implements insert/remove software breakpoint process:

Add an input parameter for kvm_arch_insert_sw_breakpoint() and
kvm_arch_remove_sw_breakpoint() to pass the length information,
which helps us to know whether it is a RVC instruction.
For some remove cases, we do not have the length info, so we need
to judge by ourselves.

For RISC-V, GDB treats single-step similarly to breakpoint: add a
breakpoint at the next step address, then continue. So this also
works for single-step debugging.

Add some stubs which are necessary for building, and will be
implemented later.

Signed-off-by: Chao Du 
---


Reviewed-by: Daniel Henrique Barboza 



  accel/kvm/kvm-all.c|  8 ++--
  include/sysemu/kvm.h   |  6 ++-
  target/arm/kvm.c   |  6 ++-
  target/i386/kvm/kvm.c  |  6 ++-
  target/mips/kvm.c  |  6 ++-
  target/ppc/kvm.c   |  6 ++-
  target/riscv/kvm/kvm-cpu.c | 79 ++
  target/s390x/kvm/kvm.c |  6 ++-
  8 files changed, 107 insertions(+), 16 deletions(-)

diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index c0be9f5eed..d27e77dbb2 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -3357,7 +3357,7 @@ int kvm_insert_breakpoint(CPUState *cpu, int type, vaddr 
addr, vaddr len)
  bp = g_new(struct kvm_sw_breakpoint, 1);
  bp->pc = addr;
  bp->use_count = 1;
-err = kvm_arch_insert_sw_breakpoint(cpu, bp);
+err = kvm_arch_insert_sw_breakpoint(cpu, bp, len);
  if (err) {
  g_free(bp);
  return err;
@@ -3396,7 +3396,7 @@ int kvm_remove_breakpoint(CPUState *cpu, int type, vaddr 
addr, vaddr len)
  return 0;
  }
  
-err = kvm_arch_remove_sw_breakpoint(cpu, bp);

+err = kvm_arch_remove_sw_breakpoint(cpu, bp, len);
  if (err) {
  return err;
  }
@@ -3426,10 +3426,10 @@ void kvm_remove_all_breakpoints(CPUState *cpu)
  CPUState *tmpcpu;
  
  QTAILQ_FOREACH_SAFE(bp, >kvm_sw_breakpoints, entry, next) {

-if (kvm_arch_remove_sw_breakpoint(cpu, bp) != 0) {
+if (kvm_arch_remove_sw_breakpoint(cpu, bp, 0) != 0) {
  /* Try harder to find a CPU that currently sees the breakpoint. */
  CPU_FOREACH(tmpcpu) {
-if (kvm_arch_remove_sw_breakpoint(tmpcpu, bp) == 0) {
+if (kvm_arch_remove_sw_breakpoint(tmpcpu, bp, 0) == 0) {
  break;
  }
  }
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index c31d9c7356..340e094ffb 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -391,9 +391,11 @@ struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState 
*cpu,
  int kvm_sw_breakpoints_active(CPUState *cpu);
  
  int kvm_arch_insert_sw_breakpoint(CPUState *cpu,

-  struct kvm_sw_breakpoint *bp);
+  struct kvm_sw_breakpoint *bp,
+  vaddr len);
  int kvm_arch_remove_sw_breakpoint(CPUState *cpu,
-  struct kvm_sw_breakpoint *bp);
+  struct kvm_sw_breakpoint *bp,
+  vaddr len);
  int kvm_arch_insert_hw_breakpoint(vaddr addr, vaddr len, int type);
  int kvm_arch_remove_hw_breakpoint(vaddr addr, vaddr len, int type);
  void kvm_arch_remove_all_hw_breakpoints(void);
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index 7cf5cf31de..84593db544 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -2402,7 +2402,8 @@ void kvm_arch_on_sigbus_vcpu(CPUState *c, int code, void 
*addr)
  /* C6.6.29 BRK instruction */
  static const uint32_t brk_insn = 0xd420;
  
-int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)

+int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp,
+  vaddr len)
  {
  if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)>saved_insn, 4, 0) ||
  cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)_insn, 4, 1)) {
@@ -2411,7 +2412,8 @@ int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct 
kvm_sw_breakpoint *bp)
  return 0;
  }
  
-int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)

+int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp,
+  vaddr len)
  {
  static uint32_t brk;
  
diff --git a/target/i386/kvm/kvm.c b/target/i386/kvm/kvm.c

index c5943605ee..6449f796d0 100644
--- a/target/i386/kvm/kvm.c
+++ b/target/i386/kvm/kvm.c
@@ -4992,7 +4992,8 @@ static int kvm_handle_tpr_access(X86CPU *cpu)
  return 1;
  }
  
-int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)

+int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp,
+  vaddr len)
  {
  static const u

Re: [RESEND PATCH v2 0/5] target/riscv: Support RISC-V privilege 1.13 spec

2024-05-27 Thread Daniel Henrique Barboza

Fea,

Please try to also add all RISC-V QEMU maintainers and reviewers when sending
patches. It will get your patches reviewed and queued faster. Otherwise the
maintainers can miss you your series due to high ML traffic.

You can fetch who you want to CC using the get_maintainer.pl script with the
patch files or any source file in particular, e.g.:

$ ./scripts/get_maintainer.pl -f target/riscv/cpu.c
Palmer Dabbelt  (supporter:RISC-V TCG CPUs)
Alistair Francis  (supporter:RISC-V TCG CPUs)
Bin Meng  (supporter:RISC-V TCG CPUs)
Weiwei Li  (reviewer:RISC-V TCG CPUs)
Daniel Henrique Barboza  (reviewer:RISC-V TCG CPUs)
Liu Zhiwei  (reviewer:RISC-V TCG CPUs)
qemu-ri...@nongnu.org (open list:RISC-V TCG CPUs)
qemu-devel@nongnu.org (open list:All patches CC here)


I added the extra folk in the CC for this reply so don't worry about it.


Alistair, please queue this series. It's already fully acked and I would like 
to add
some bits on top of the priv_spec 1.13 support.


Thanks,


Daniel

On 5/15/24 05:05, Fea.Wang wrote:

Based on the change log for the RISC-V privilege 1.13 spec, add the
support for ss1p13.

Ref:https://github.com/riscv/riscv-isa-manual/blob/a7d93c9/src/priv-preface.adoc?plain=1#L40-L72

Lists what to do without clarification or document format.
* Redefined misa.MXL to be read-only, making MXLEN a constant.(Skip, 
implementation ignored)
* Added the constraint that SXLEN≥UXLEN.(Skip, implementation ignored)
* Defined the misa.V field to reflect that the V extension has been 
implemented.(Skip, existed)
* Defined the RV32-only medelegh and hedelegh CSRs.(Done in these patches)
* Defined the misaligned atomicity granule PMA, superseding the proposed Zam 
extension..(Skip, implementation ignored)
* Allocated interrupt 13 for Sscofpmf LCOFI interrupt.(Skip, existed)
* Defined hardware error and software check exception codes.(Done in these 
patches)
* Specified synchronization requirements when changing the PBMTE fields in 
menvcfg and henvcfg.(Skip, implementation ignored)
* Incorporated Svade and Svadu extension specifications.(Skip, existed)


Fea.Wang (4):
   target/riscv: Support the version for ss1p13
   target/riscv: Add 'P1P13' bit in SMSTATEEN0
   target/riscv: Add MEDELEGH, HEDELEGH csrs for RV32
   target/riscv: Reserve exception codes for sw-check and hw-err

Jim Shu (1):
   target/riscv: Reuse the conversion function of priv_spec

  target/riscv/cpu.c |  8 ++--
  target/riscv/cpu.h |  5 -
  target/riscv/cpu_bits.h|  5 +
  target/riscv/cpu_cfg.h |  1 +
  target/riscv/csr.c | 39 ++
  target/riscv/tcg/tcg-cpu.c | 17 -
  6 files changed, 63 insertions(+), 12 deletions(-)





Re: [PATCH 0/6] target/riscv: Support Zabha extension

2024-05-26 Thread Daniel Henrique Barboza




On 5/25/24 21:37, LIU Zhiwei wrote:


On 2024/5/24 19:44, Daniel Henrique Barboza wrote:

Hi Zhiwei!



On 5/23/24 09:40, LIU Zhiwei wrote:

Zabha adds support AMO operations for byte and half word. If zacas has been 
implemented,
zabha also adds support amocas.b and amocas.h.

More details is on the specification here:
https://github.com/riscv/riscv-zabha

The implemenation of zabha follows the way of AMOs and zacas.

This patch set is based on these two patch set:
1. https://mail.gnu.org/archive/html/qemu-riscv/2024-05/msg00207.html
2. https://mail.gnu.org/archive/html/qemu-riscv/2024-05/msg00212.html


These 2 series doesn't seem to apply on top of each other, doesn't matter which
order I try. Applying zimop/zcmop first, then zama16b:

$ git am \[PATCH\ 1_1\]\ target_riscv\:\ Support\ Zama16b\ extension\ -\ LIU\ Zhiwei\ 
\\ -\ 2024-05-22\ 0613.eml
Applying: target/riscv: Support Zama16b extension
error: patch failed: target/riscv/cpu.c:1464
error: target/riscv/cpu.c: patch does not apply
Patch failed at 0001 target/riscv: Support Zama16b extension
hint: Use 'git am --show-current-patch=diff' to see the failed patch


Applying zama16b first, then zimop/zcmop:

$ git am \[PATCH\ 1_1\]\ target_riscv\:\ Support\ Zama16b\ extension\ -\ LIU\ Zhiwei\ 
\\ -\ 2024-05-22\ 0613.eml
Applying: target/riscv: Support Zama16b extension
$
$ git am \[PATCH\ 1_4\]\ target_riscv\:\ Add\ zimop\ extension\ -\ LIU\ Zhiwei\ 
\\ -\ 2024-05-22\ 0329.eml \[PATCH\ 2_4\]\ 
disas_riscv\:\ Support\ zimop\ disassemble\ -\ LIU\ Zhiwei\ 
\\ -\ 2024-05-22\ 0329.eml
Applying: target/riscv: Add zimop extension
error: patch failed: target/riscv/cpu.c:1463
error: target/riscv/cpu.c: patch does not apply
Patch failed at 0001 target/riscv: Add zimop extension


If the series are dependent on each other perhaps it's easier to send everything
in a single 11 patches series.


They don't have dependency on each other. But if we both rebase them to the 
master branch, they
couldn't be merged at the time, as them both modify cpu.h and cpu.c in the same 
place.


I will send them as a whole patch set(RVA23 patch set) after I fix other issues 
on implementing the RVA23 profile.



Be aware that we have some RVA23 extensions that are implemented in the ML
but not merged no master yet. E.g. sstvala ended up being implemented after some
changes I did w.r.t tval and EBREAK. These patches are on riscv-to-apply.next.

Also, I took another look at RVA23 mandatory exts and what we have. I think 
we're
not that far off after these extensions you're adding. What we really seems to 
be
missing is supm and ssnpm.


Thanks,

Daniel



Thanks,

Zhiwei




Thanks,

Daniel




LIU Zhiwei (6):
   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   |  60 
  target/riscv/cpu.c  |   2 +
  target/riscv/cpu_cfg.h  |   1 +
  target/riscv/insn32.decode  |  22 +++
  target/riscv/insn_trans/trans_rva.c.inc |  21 ---
  target/riscv/insn_trans/trans_rvzabha.c.inc | 145 
  target/riscv/insn_trans/trans_rvzacas.c.inc |  13 --
  target/riscv/translate.c    |  36 +
  8 files changed, 266 insertions(+), 34 deletions(-)
  create mode 100644 target/riscv/insn_trans/trans_rvzabha.c.inc





Re: [PATCH v2 1/3] hw/riscv/virt: Add memory hotplugging and virtio-md-pci support

2024-05-24 Thread Daniel Henrique Barboza




On 5/24/24 12:02, David Hildenbrand wrote:

On 24.05.24 15:14, Daniel Henrique Barboza wrote:



On 5/21/24 07:56, Björn Töpel wrote:

From: Björn Töpel 

Virtio-based memory devices (virtio-mem/virtio-pmem) allows for
dynamic resizing of virtual machine memory, and requires proper
hotplugging (add/remove) support to work.

Add device memory support for RISC-V "virt" machine, and enable
virtio-md-pci with the corresponding missing hotplugging callbacks.

Signed-off-by: Björn Töpel 
---
   hw/riscv/Kconfig   |  2 +
   hw/riscv/virt.c    | 83 +-
   hw/virtio/virtio-mem.c |  5 ++-
   3 files changed, 87 insertions(+), 3 deletions(-)

diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
index a2030e3a6ff0..08f82dbb681a 100644
--- a/hw/riscv/Kconfig
+++ b/hw/riscv/Kconfig
@@ -56,6 +56,8 @@ config RISCV_VIRT
   select PLATFORM_BUS
   select ACPI
   select ACPI_PCI
+    select VIRTIO_MEM_SUPPORTED
+    select VIRTIO_PMEM_SUPPORTED
   config SHAKTI_C
   bool
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 4fdb66052587..443902f919d2 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -53,6 +53,8 @@
   #include "hw/pci-host/gpex.h"
   #include "hw/display/ramfb.h"
   #include "hw/acpi/aml-build.h"
+#include "hw/mem/memory-device.h"
+#include "hw/virtio/virtio-mem-pci.h"
   #include "qapi/qapi-visit-common.h"
   #include "hw/virtio/virtio-iommu.h"
@@ -1407,6 +1409,7 @@ static void virt_machine_init(MachineState *machine)
   DeviceState *mmio_irqchip, *virtio_irqchip, *pcie_irqchip;
   int i, base_hartid, hart_count;
   int socket_count = riscv_socket_count(machine);
+    hwaddr device_memory_base, device_memory_size;
   /* Check socket count limit */
   if (VIRT_SOCKETS_MAX < socket_count) {
@@ -1420,6 +1423,12 @@ static void virt_machine_init(MachineState *machine)
   exit(1);
   }
+    if (machine->ram_slots > ACPI_MAX_RAM_SLOTS) {
+    error_report("unsupported amount of memory slots: %"PRIu64,
+ machine->ram_slots);
+    exit(EXIT_FAILURE);
+    }
+
   /* Initialize sockets */
   mmio_irqchip = virtio_irqchip = pcie_irqchip = NULL;
   for (i = 0; i < socket_count; i++) {
@@ -1553,6 +1562,37 @@ static void virt_machine_init(MachineState *machine)
   memory_region_add_subregion(system_memory, memmap[VIRT_MROM].base,
   mask_rom);
+    /* device memory */
+    device_memory_base = ROUND_UP(s->memmap[VIRT_DRAM].base + 
machine->ram_size,
+  GiB);
+    device_memory_size = machine->maxram_size - machine->ram_size;
+    if (device_memory_size > 0) {
+    /*
+ * Each DIMM is aligned based on the backend's alignment value.
+ * Assume max 1G hugepage alignment per slot.
+ */
+    device_memory_size += machine->ram_slots * GiB;


We don't need to align to 1GiB. This calc can use 2MiB instead (or 4MiB if we're
running 32 bits).


+
+    if (riscv_is_32bit(>soc[0])) {
+    hwaddr memtop = device_memory_base + ROUND_UP(device_memory_size,
+  GiB);


Same here - alignment is 2/4 MiB.


+
+    if (memtop > UINT32_MAX) {
+    error_report("memory exceeds 32-bit limit by %lu bytes",
+ memtop - UINT32_MAX);
+    exit(EXIT_FAILURE);
+    }
+    }
+
+    if (device_memory_base + device_memory_size < device_memory_size) {
+    error_report("unsupported amount of device memory");
+    exit(EXIT_FAILURE);
+    }


Took another look and found this a bit strange. These are all unsigned vars, so
if (unsigned a + unsigned b < unsigned b) will always be 'false'. The compiler 
is
probably cropping this out.


No. Unsigned interger overflow is defined behavior and this is a common check 
to detect such overflow. tI's consistent with what we do for other 
architectures.



Oh, ok. We're so far away from UINT64_MAX that it didn't occur to me doing an 
overflow
check here. Fair enough.

 


The calc we need to do is to ensure that the extra ram_slots * alignment will 
fit into
the VIRT_DRAM block, i.e. maxram_size + (ram_slots * alignment) < 
memmap[VIRT_DRAM].size.


TBH I'm starting to have second thoughts about letting users hotplug whatever 
they want.
It seems cleaner to just force the 2/4 Mb alignment in pre_plug() and be done 
with it,
no need to allocate ram_slots * alignment and doing all these extra checks.


It's worth noting that if user space decides to specify addresses manually, it 
can mess up everything already. There are other events that can result in 
fragmentation of the memory device area (repeated hot(un)plug of differing 
DIMMs).

Assume you have 1 GiB range and hot

Re: [PATCH v2 1/3] hw/riscv/virt: Add memory hotplugging and virtio-md-pci support

2024-05-24 Thread Daniel Henrique Barboza




On 5/21/24 07:56, Björn Töpel wrote:

From: Björn Töpel 

Virtio-based memory devices (virtio-mem/virtio-pmem) allows for
dynamic resizing of virtual machine memory, and requires proper
hotplugging (add/remove) support to work.

Add device memory support for RISC-V "virt" machine, and enable
virtio-md-pci with the corresponding missing hotplugging callbacks.

Signed-off-by: Björn Töpel 
---
  hw/riscv/Kconfig   |  2 +
  hw/riscv/virt.c| 83 +-
  hw/virtio/virtio-mem.c |  5 ++-
  3 files changed, 87 insertions(+), 3 deletions(-)

diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
index a2030e3a6ff0..08f82dbb681a 100644
--- a/hw/riscv/Kconfig
+++ b/hw/riscv/Kconfig
@@ -56,6 +56,8 @@ config RISCV_VIRT
  select PLATFORM_BUS
  select ACPI
  select ACPI_PCI
+select VIRTIO_MEM_SUPPORTED
+select VIRTIO_PMEM_SUPPORTED
  
  config SHAKTI_C

  bool
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 4fdb66052587..443902f919d2 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -53,6 +53,8 @@
  #include "hw/pci-host/gpex.h"
  #include "hw/display/ramfb.h"
  #include "hw/acpi/aml-build.h"
+#include "hw/mem/memory-device.h"
+#include "hw/virtio/virtio-mem-pci.h"
  #include "qapi/qapi-visit-common.h"
  #include "hw/virtio/virtio-iommu.h"
  
@@ -1407,6 +1409,7 @@ static void virt_machine_init(MachineState *machine)

  DeviceState *mmio_irqchip, *virtio_irqchip, *pcie_irqchip;
  int i, base_hartid, hart_count;
  int socket_count = riscv_socket_count(machine);
+hwaddr device_memory_base, device_memory_size;
  
  /* Check socket count limit */

  if (VIRT_SOCKETS_MAX < socket_count) {
@@ -1420,6 +1423,12 @@ static void virt_machine_init(MachineState *machine)
  exit(1);
  }
  
+if (machine->ram_slots > ACPI_MAX_RAM_SLOTS) {

+error_report("unsupported amount of memory slots: %"PRIu64,
+ machine->ram_slots);
+exit(EXIT_FAILURE);
+}
+
  /* Initialize sockets */
  mmio_irqchip = virtio_irqchip = pcie_irqchip = NULL;
  for (i = 0; i < socket_count; i++) {
@@ -1553,6 +1562,37 @@ static void virt_machine_init(MachineState *machine)
  memory_region_add_subregion(system_memory, memmap[VIRT_MROM].base,
  mask_rom);
  
+/* device memory */

+device_memory_base = ROUND_UP(s->memmap[VIRT_DRAM].base + 
machine->ram_size,
+  GiB);
+device_memory_size = machine->maxram_size - machine->ram_size;
+if (device_memory_size > 0) {
+/*
+ * Each DIMM is aligned based on the backend's alignment value.
+ * Assume max 1G hugepage alignment per slot.
+ */
+device_memory_size += machine->ram_slots * GiB;


We don't need to align to 1GiB. This calc can use 2MiB instead (or 4MiB if we're
running 32 bits).


+
+if (riscv_is_32bit(>soc[0])) {
+hwaddr memtop = device_memory_base + ROUND_UP(device_memory_size,
+  GiB);


Same here - alignment is 2/4 MiB.


+
+if (memtop > UINT32_MAX) {
+error_report("memory exceeds 32-bit limit by %lu bytes",
+ memtop - UINT32_MAX);
+exit(EXIT_FAILURE);
+}
+}
+
+if (device_memory_base + device_memory_size < device_memory_size) {
+error_report("unsupported amount of device memory");
+exit(EXIT_FAILURE);
+}


Took another look and found this a bit strange. These are all unsigned vars, so
if (unsigned a + unsigned b < unsigned b) will always be 'false'. The compiler 
is
probably cropping this out.

The calc we need to do is to ensure that the extra ram_slots * alignment will 
fit into
the VIRT_DRAM block, i.e. maxram_size + (ram_slots * alignment) < 
memmap[VIRT_DRAM].size.


TBH I'm starting to have second thoughts about letting users hotplug whatever 
they want.
It seems cleaner to just force the 2/4 Mb alignment in pre_plug() and be done 
with it,
no need to allocate ram_slots * alignment and doing all these extra checks.

As I sent in an earlier email, users must already comply to the alignment of 
the host
memory when plugging pc-dimms, so I'm not sure our value/proposition with all 
this
extra code is worth it - the alignment will most likely be forced by the host 
memory
backend, so might as well force ourselves in pre_plug().


Thanks,


Daniel



+
+machine_memory_devices_init(machine, device_memory_base,
+device_memory_size);
+}
+
  /*
   * Init fw_cfg. Must be done before riscv_load_fdt, otherwise the
   * device tree cannot be altered and we get FDT_ERR_NOSPACE.
@@ -1712,12 +1752,21 @@ static HotplugHandler 
*virt_machine_get_hotplug_handler(MachineState *machine,
  MachineClass *mc = MACHINE_GET_CLASS(machine);
  
  if (device_is_dynamic_sysbus(mc, dev) 

Re: [PATCH 0/6] target/riscv: Support Zabha extension

2024-05-24 Thread Daniel Henrique Barboza

Hi Zhiwei!



On 5/23/24 09:40, LIU Zhiwei wrote:

Zabha adds support AMO operations for byte and half word. If zacas has been 
implemented,
zabha also adds support amocas.b and amocas.h.

More details is on the specification here:
https://github.com/riscv/riscv-zabha

The implemenation of zabha follows the way of AMOs and zacas.

This patch set is based on these two patch set:
1. https://mail.gnu.org/archive/html/qemu-riscv/2024-05/msg00207.html
2. https://mail.gnu.org/archive/html/qemu-riscv/2024-05/msg00212.html


These 2 series doesn't seem to apply on top of each other, doesn't matter which
order I try. Applying zimop/zcmop first, then zama16b:

$ git am \[PATCH\ 1_1\]\ target_riscv\:\ Support\ Zama16b\ extension\ -\ LIU\ Zhiwei\ 
\\ -\ 2024-05-22\ 0613.eml
Applying: target/riscv: Support Zama16b extension
error: patch failed: target/riscv/cpu.c:1464
error: target/riscv/cpu.c: patch does not apply
Patch failed at 0001 target/riscv: Support Zama16b extension
hint: Use 'git am --show-current-patch=diff' to see the failed patch


Applying zama16b first, then zimop/zcmop:

$ git am \[PATCH\ 1_1\]\ target_riscv\:\ Support\ Zama16b\ extension\ -\ LIU\ Zhiwei\ 
\\ -\ 2024-05-22\ 0613.eml
Applying: target/riscv: Support Zama16b extension
$
$ git am \[PATCH\ 1_4\]\ target_riscv\:\ Add\ zimop\ extension\ -\ LIU\ Zhiwei\ 
\\ -\ 2024-05-22\ 0329.eml \[PATCH\ 2_4\]\ 
disas_riscv\:\ Support\ zimop\ disassemble\ -\ LIU\ Zhiwei\ 
\\ -\ 2024-05-22\ 0329.eml
Applying: target/riscv: Add zimop extension
error: patch failed: target/riscv/cpu.c:1463
error: target/riscv/cpu.c: patch does not apply
Patch failed at 0001 target/riscv: Add zimop extension


If the series are dependent on each other perhaps it's easier to send everything
in a single 11 patches series.


Thanks,

Daniel




LIU Zhiwei (6):
   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   |  60 
  target/riscv/cpu.c  |   2 +
  target/riscv/cpu_cfg.h  |   1 +
  target/riscv/insn32.decode  |  22 +++
  target/riscv/insn_trans/trans_rva.c.inc |  21 ---
  target/riscv/insn_trans/trans_rvzabha.c.inc | 145 
  target/riscv/insn_trans/trans_rvzacas.c.inc |  13 --
  target/riscv/translate.c|  36 +
  8 files changed, 266 insertions(+), 34 deletions(-)
  create mode 100644 target/riscv/insn_trans/trans_rvzabha.c.inc





Re: [PATCH 5/6] target/riscv: Enable zabha for max cpu

2024-05-24 Thread Daniel Henrique Barboza




On 5/23/24 09:40, LIU Zhiwei wrote:

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 21d4e36405..9ec03a1edc 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -118,6 +118,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
  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_12_0, ext_zama16b),
+ISA_EXT_DATA_ENTRY(zabha, PRIV_VERSION_1_12_0, ext_zabha),


I think this should be place right after zaamo. Thanks,


Daniel


  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),
@@ -1470,6 +1471,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),




Re: [PATCH 1/1] target/riscv: Support Zama16b extension

2024-05-24 Thread Daniel Henrique Barboza




On 5/22/24 06:13, LIU Zhiwei wrote:

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 eb1a2e7d6d..911e9892ed 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -117,6 +117,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_12_0, ext_zama16b),


Is this the right order? Shouldn't it be after zalrsc?


LGTM otherwise. Thanks,


Daniel


  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),
@@ -1464,6 +1465,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("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 cb750154bd..eaa66eb4f8 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -81,6 +81,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 

Re: [PATCH 3/4] target/riscv: Add zcmop extension

2024-05-24 Thread Daniel Henrique Barboza




On 5/22/24 03:29, LIU Zhiwei wrote:

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 
---
  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 c1ac521142..5052237a5b 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -176,6 +176,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
  ISA_EXT_DATA_ENTRY(zhinx, PRIV_VERSION_1_12_0, ext_zhinx),
  ISA_EXT_DATA_ENTRY(zhinxmin, PRIV_VERSION_1_12_0, ext_zhinxmin),
  ISA_EXT_DATA_ENTRY(zimop, PRIV_VERSION_1_12_0, ext_zimop),
+ISA_EXT_DATA_ENTRY(zcmop, PRIV_VERSION_1_12_0, ext_zcmop),



I'm not sure if zcmop goes here. Perhaps here?


ISA_EXT_DATA_ENTRY(zce, PRIV_VERSION_1_12_0, ext_zce),

+ISA_EXT_DATA_ENTRY(zcmop, PRIV_VERSION_1_12_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),


Thanks,


Daniel



  ISA_EXT_DATA_ENTRY(smaia, PRIV_VERSION_1_12_0, ext_smaia),
  ISA_EXT_DATA_ENTRY(smepmp, PRIV_VERSION_1_12_0, ext_smepmp),
  ISA_EXT_DATA_ENTRY(smstateen, PRIV_VERSION_1_12_0, ext_smstateen),
@@ -1465,6 +1466,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 b547fbba9d..e29d4f6f9c 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 .
+ */
+
+#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 40054a391a..499b48dce8 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -583,6 +583,11 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, 
Error **errp)
  }
  }
  
+if (cpu->cfg.ext_zcmop && !cpu->cfg.ext_zca) {

+

Re: [PATCH 1/4] target/riscv: Add zimop extension

2024-05-24 Thread Daniel Henrique Barboza




On 5/22/24 03:29, LIU Zhiwei wrote:

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 
---
  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 eb1a2e7d6d..c1ac521142 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -175,6 +175,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
  ISA_EXT_DATA_ENTRY(zvkt, PRIV_VERSION_1_12_0, ext_zvkt),
  ISA_EXT_DATA_ENTRY(zhinx, PRIV_VERSION_1_12_0, ext_zhinx),
  ISA_EXT_DATA_ENTRY(zhinxmin, PRIV_VERSION_1_12_0, ext_zhinxmin),
+ISA_EXT_DATA_ENTRY(zimop, PRIV_VERSION_1_12_0, ext_zimop),


Shouldn't this be placed right after zihpm?

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_12_0, ext_zimop),

ISA_EXT_DATA_ENTRY(zmmul, PRIV_VERSION_1_12_0, ext_zmmul),


Thanks,

Daniel



  ISA_EXT_DATA_ENTRY(smaia, PRIV_VERSION_1_12_0, ext_smaia),
  ISA_EXT_DATA_ENTRY(smepmp, PRIV_VERSION_1_12_0, ext_smepmp),
  ISA_EXT_DATA_ENTRY(smstateen, PRIV_VERSION_1_12_0, ext_smstateen),
@@ -1463,6 +1464,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 cb750154bd..b547fbba9d 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.
+ *
+ 

Re: [PATCH v2 3/3] hw/riscv/virt: Add ACPI GED and PC-DIMM MHP support

2024-05-24 Thread Daniel Henrique Barboza




On 5/21/24 07:56, Björn Töpel wrote:

From: Björn Töpel 

Add ACPI GED for the RISC-V "virt" machine, and wire up PC-DIMM memory
hotplugging support. Heavily based/copied from hw/arm/virt.c.

Signed-off-by: Björn Töpel 
---
  hw/riscv/Kconfig   |   3 ++
  hw/riscv/virt-acpi-build.c |  16 ++
  hw/riscv/virt.c| 104 -
  include/hw/riscv/virt.h|   6 ++-
  4 files changed, 126 insertions(+), 3 deletions(-)

diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
index 08f82dbb681a..bebe412f2107 100644
--- a/hw/riscv/Kconfig
+++ b/hw/riscv/Kconfig
@@ -56,6 +56,9 @@ config RISCV_VIRT
  select PLATFORM_BUS
  select ACPI
  select ACPI_PCI
+select MEM_DEVICE
+select DIMM
+select ACPI_HW_REDUCED
  select VIRTIO_MEM_SUPPORTED
  select VIRTIO_PMEM_SUPPORTED
  
diff --git a/hw/riscv/virt-acpi-build.c b/hw/riscv/virt-acpi-build.c

index 6dc3baa9ec86..61813abdef3f 100644
--- a/hw/riscv/virt-acpi-build.c
+++ b/hw/riscv/virt-acpi-build.c
@@ -27,6 +27,8 @@
  #include "hw/acpi/acpi-defs.h"
  #include "hw/acpi/acpi.h"
  #include "hw/acpi/aml-build.h"
+#include "hw/acpi/memory_hotplug.h"
+#include "hw/acpi/generic_event_device.h"
  #include "hw/acpi/pci.h"
  #include "hw/acpi/utils.h"
  #include "hw/intc/riscv_aclint.h"
@@ -432,6 +434,20 @@ static void build_dsdt(GArray *table_data,
  acpi_dsdt_add_gpex_host(scope, PCIE_IRQ + VIRT_IRQCHIP_NUM_SOURCES * 
2);
  }
  
+if (s->acpi_dev) {

+uint32_t event = object_property_get_uint(OBJECT(s->acpi_dev),
+  "ged-event", _abort);
+
+build_ged_aml(scope, "\\_SB."GED_DEVICE, HOTPLUG_HANDLER(s->acpi_dev),
+  GED_IRQ, AML_SYSTEM_MEMORY, memmap[VIRT_ACPI_GED].base);
+
+if (event & ACPI_GED_MEM_HOTPLUG_EVT) {
+build_memory_hotplug_aml(scope, ms->ram_slots, "\\_SB", NULL,
+ AML_SYSTEM_MEMORY,
+ memmap[VIRT_PCDIMM_ACPI].base);
+}
+}
+
  aml_append(dsdt, scope);
  
  /* copy AML table into ACPI tables blob and patch header there */

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 443902f919d2..2e35890187f2 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -53,10 +53,13 @@
  #include "hw/pci-host/gpex.h"
  #include "hw/display/ramfb.h"
  #include "hw/acpi/aml-build.h"
+#include "hw/acpi/generic_event_device.h"
+#include "hw/acpi/memory_hotplug.h"
  #include "hw/mem/memory-device.h"
  #include "hw/virtio/virtio-mem-pci.h"
  #include "qapi/qapi-visit-common.h"
  #include "hw/virtio/virtio-iommu.h"
+#include "hw/mem/pc-dimm.h"
  
  /* KVM AIA only supports APLIC MSI. APLIC Wired is always emulated by QEMU. */

  static bool virt_use_kvm_aia(RISCVVirtState *s)
@@ -84,6 +87,8 @@ static const MemMapEntry virt_memmap[] = {
  [VIRT_UART0] ={ 0x1000, 0x100 },
  [VIRT_VIRTIO] =   { 0x10001000,0x1000 },
  [VIRT_FW_CFG] =   { 0x1010,  0x18 },
+[VIRT_PCDIMM_ACPI] =  { 0x1020, MEMORY_HOTPLUG_IO_LEN },
+[VIRT_ACPI_GED] = { 0x1021, ACPI_GED_EVT_SEL_LEN },
  [VIRT_FLASH] ={ 0x2000, 0x400 },
  [VIRT_IMSIC_M] =  { 0x2400, VIRT_IMSIC_MAX_SIZE },
  [VIRT_IMSIC_S] =  { 0x2800, VIRT_IMSIC_MAX_SIZE },
@@ -1400,6 +1405,28 @@ static void virt_machine_done(Notifier *notifier, void 
*data)
  }
  }
  
+static DeviceState *create_acpi_ged(RISCVVirtState *s)

+{
+DeviceState *dev;
+MachineState *ms = MACHINE(s);
+uint32_t event = 0;
+
+if (ms->ram_slots) {
+event |= ACPI_GED_MEM_HOTPLUG_EVT;
+}
+
+dev = qdev_new(TYPE_ACPI_GED);
+qdev_prop_set_uint32(dev, "ged-event", event);
+sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), _fatal);
+
+sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, s->memmap[VIRT_ACPI_GED].base);
+sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, s->memmap[VIRT_PCDIMM_ACPI].base);
+sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(s->irqchip[0],
+GED_IRQ));
+
+return dev;
+}
+
  static void virt_machine_init(MachineState *machine)
  {
  const MemMapEntry *memmap = virt_memmap;
@@ -1612,6 +1639,10 @@ static void virt_machine_init(MachineState *machine)
  
  gpex_pcie_init(system_memory, pcie_irqchip, s);
  
+if (virt_is_acpi_enabled(s)) {

+s->acpi_dev = create_acpi_ged(s);
+}
+
  create_platform_bus(s, mmio_irqchip);
  
  serial_mm_init(system_memory, memmap[VIRT_UART0].base,

@@ -1752,6 +1783,7 @@ static HotplugHandler 
*virt_machine_get_hotplug_handler(MachineState *machine,
  MachineClass *mc = MACHINE_GET_CLASS(machine);
  
  if (device_is_dynamic_sysbus(mc, dev) ||

+object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM) ||
  object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI) ||
  

Re: [PATCH v2 1/3] hw/riscv/virt: Add memory hotplugging and virtio-md-pci support

2024-05-24 Thread Daniel Henrique Barboza




On 5/21/24 07:56, Björn Töpel wrote:

From: Björn Töpel 

Virtio-based memory devices (virtio-mem/virtio-pmem) allows for
dynamic resizing of virtual machine memory, and requires proper
hotplugging (add/remove) support to work.

Add device memory support for RISC-V "virt" machine, and enable
virtio-md-pci with the corresponding missing hotplugging callbacks.

Signed-off-by: Björn Töpel 
---
  hw/riscv/Kconfig   |  2 +
  hw/riscv/virt.c| 83 +-
  hw/virtio/virtio-mem.c |  5 ++-
  3 files changed, 87 insertions(+), 3 deletions(-)

diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
index a2030e3a6ff0..08f82dbb681a 100644
--- a/hw/riscv/Kconfig
+++ b/hw/riscv/Kconfig
@@ -56,6 +56,8 @@ config RISCV_VIRT
  select PLATFORM_BUS
  select ACPI
  select ACPI_PCI
+select VIRTIO_MEM_SUPPORTED
+select VIRTIO_PMEM_SUPPORTED
  
  config SHAKTI_C

  bool
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 4fdb66052587..443902f919d2 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -53,6 +53,8 @@
  #include "hw/pci-host/gpex.h"
  #include "hw/display/ramfb.h"
  #include "hw/acpi/aml-build.h"
+#include "hw/mem/memory-device.h"
+#include "hw/virtio/virtio-mem-pci.h"
  #include "qapi/qapi-visit-common.h"
  #include "hw/virtio/virtio-iommu.h"
  
@@ -1407,6 +1409,7 @@ static void virt_machine_init(MachineState *machine)

  DeviceState *mmio_irqchip, *virtio_irqchip, *pcie_irqchip;
  int i, base_hartid, hart_count;
  int socket_count = riscv_socket_count(machine);
+hwaddr device_memory_base, device_memory_size;
  
  /* Check socket count limit */

  if (VIRT_SOCKETS_MAX < socket_count) {
@@ -1420,6 +1423,12 @@ static void virt_machine_init(MachineState *machine)
  exit(1);
  }
  
+if (machine->ram_slots > ACPI_MAX_RAM_SLOTS) {

+error_report("unsupported amount of memory slots: %"PRIu64,
+ machine->ram_slots);


Let's also add the maximum amount allowed in this message, e.g. this error:

$ (...) -m 2G,slots=512,maxmem=8G
qemu-system-riscv64: unsupported amount of memory slots: 512

could be something like:

qemu-system-riscv64: unsupported amount of memory slots (512), maximum amount: 
256


LGTM otherwise. Thanks,


Daniel




+exit(EXIT_FAILURE);
+}
+
  /* Initialize sockets */
  mmio_irqchip = virtio_irqchip = pcie_irqchip = NULL;
  for (i = 0; i < socket_count; i++) {
@@ -1553,6 +1562,37 @@ static void virt_machine_init(MachineState *machine)
  memory_region_add_subregion(system_memory, memmap[VIRT_MROM].base,
  mask_rom);
  
+/* device memory */

+device_memory_base = ROUND_UP(s->memmap[VIRT_DRAM].base + 
machine->ram_size,
+  GiB);
+device_memory_size = machine->maxram_size - machine->ram_size;
+if (device_memory_size > 0) {
+/*
+ * Each DIMM is aligned based on the backend's alignment value.
+ * Assume max 1G hugepage alignment per slot.
+ */
+device_memory_size += machine->ram_slots * GiB;
+
+if (riscv_is_32bit(>soc[0])) {
+hwaddr memtop = device_memory_base + ROUND_UP(device_memory_size,
+  GiB);
+
+if (memtop > UINT32_MAX) {
+error_report("memory exceeds 32-bit limit by %lu bytes",
+ memtop - UINT32_MAX);
+exit(EXIT_FAILURE);
+}
+}
+
+if (device_memory_base + device_memory_size < device_memory_size) {
+error_report("unsupported amount of device memory");
+exit(EXIT_FAILURE);
+}
+
+machine_memory_devices_init(machine, device_memory_base,
+device_memory_size);
+}
+>   /*
   * Init fw_cfg. Must be done before riscv_load_fdt, otherwise the
   * device tree cannot be altered and we get FDT_ERR_NOSPACE.
@@ -1712,12 +1752,21 @@ static HotplugHandler 
*virt_machine_get_hotplug_handler(MachineState *machine,
  MachineClass *mc = MACHINE_GET_CLASS(machine);
  
  if (device_is_dynamic_sysbus(mc, dev) ||

-object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) {
+object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI) ||
+object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI)) {
  return HOTPLUG_HANDLER(machine);
  }
  return NULL;
  }
  
+static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev,

+DeviceState *dev, Error **errp)
+{
+if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_MD_PCI)) {
+virtio_md_pci_pre_plug(VIRTIO_MD_PCI(dev), MACHINE(hotplug_dev), errp);
+}
+}
+
  static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev,
  DeviceState *dev, Error **errp)
  {
@@ -1735,6 +1784,35 @@ static void 

[PATCH v3 12/13] hw/riscv/riscv-iommu: Add another irq for mrif notifications

2024-05-23 Thread Daniel Henrique Barboza
From: Andrew Jones 

And add mrif notification trace.

Signed-off-by: Andrew Jones 
Reviewed-by: Daniel Henrique Barboza 
Reviewed-by: Frank Chang 
---
 hw/riscv/riscv-iommu-pci.c | 2 +-
 hw/riscv/riscv-iommu.c | 1 +
 hw/riscv/trace-events  | 1 +
 3 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/hw/riscv/riscv-iommu-pci.c b/hw/riscv/riscv-iommu-pci.c
index 7635cc64ff..ad3df8ffe6 100644
--- a/hw/riscv/riscv-iommu-pci.c
+++ b/hw/riscv/riscv-iommu-pci.c
@@ -80,7 +80,7 @@ static void riscv_iommu_pci_realize(PCIDevice *dev, Error 
**errp)
 pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
  PCI_BASE_ADDRESS_MEM_TYPE_64, >bar0);
 
-int ret = msix_init(dev, RISCV_IOMMU_INTR_COUNT,
+int ret = msix_init(dev, RISCV_IOMMU_INTR_COUNT + 1,
 >bar0, 0, RISCV_IOMMU_REG_MSI_CONFIG,
 >bar0, 0, RISCV_IOMMU_REG_MSI_CONFIG + 256, 0, 
);
 
diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
index 52f0851895..a27f56419a 100644
--- a/hw/riscv/riscv-iommu.c
+++ b/hw/riscv/riscv-iommu.c
@@ -623,6 +623,7 @@ static MemTxResult riscv_iommu_msi_write(RISCVIOMMUState *s,
 cause = RISCV_IOMMU_FQ_CAUSE_MSI_WR_FAULT;
 goto err;
 }
+trace_riscv_iommu_mrif_notification(s->parent_obj.id, n190, addr);
 
 return MEMTX_OK;
 
diff --git a/hw/riscv/trace-events b/hw/riscv/trace-events
index 4b486b6420..d69719a27a 100644
--- a/hw/riscv/trace-events
+++ b/hw/riscv/trace-events
@@ -6,6 +6,7 @@ riscv_iommu_flt(const char *id, unsigned b, unsigned d, 
unsigned f, uint64_t rea
 riscv_iommu_pri(const char *id, unsigned b, unsigned d, unsigned f, uint64_t 
iova) "%s: page request %04x:%02x.%u iova: 0x%"PRIx64
 riscv_iommu_dma(const char *id, unsigned b, unsigned d, unsigned f, unsigned 
pasid, const char *dir, uint64_t iova, uint64_t phys) "%s: translate 
%04x:%02x.%u #%u %s 0x%"PRIx64" -> 0x%"PRIx64
 riscv_iommu_msi(const char *id, unsigned b, unsigned d, unsigned f, uint64_t 
iova, uint64_t phys) "%s: translate %04x:%02x.%u MSI 0x%"PRIx64" -> 0x%"PRIx64
+riscv_iommu_mrif_notification(const char *id, uint32_t nid, uint64_t phys) 
"%s: sent MRIF notification 0x%x to 0x%"PRIx64
 riscv_iommu_cmd(const char *id, uint64_t l, uint64_t u) "%s: command 
0x%"PRIx64" 0x%"PRIx64
 riscv_iommu_notifier_add(const char *id) "%s: dev-iotlb notifier added"
 riscv_iommu_notifier_del(const char *id) "%s: dev-iotlb notifier removed"
-- 
2.44.0




[PATCH v3 02/13] hw/riscv: add riscv-iommu-bits.h

2024-05-23 Thread Daniel Henrique Barboza
From: Tomasz Jeznach 

This header will be used by the RISC-V IOMMU emulation to be added
in the next patch. Due to its size it's being sent in separate for
an easier review.

One thing to notice is that this header can be replaced by the future
Linux RISC-V IOMMU driver header, which would become a linux-header we
would import instead of keeping our own. The Linux implementation isn't
upstream yet so for now we'll have to manage riscv-iommu-bits.h.

Signed-off-by: Tomasz Jeznach 
Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Frank Chang 
---
 hw/riscv/riscv-iommu-bits.h | 347 
 1 file changed, 347 insertions(+)
 create mode 100644 hw/riscv/riscv-iommu-bits.h

diff --git a/hw/riscv/riscv-iommu-bits.h b/hw/riscv/riscv-iommu-bits.h
new file mode 100644
index 00..f29b916acb
--- /dev/null
+++ b/hw/riscv/riscv-iommu-bits.h
@@ -0,0 +1,347 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright © 2022-2023 Rivos Inc.
+ * Copyright © 2023 FORTH-ICS/CARV
+ * Copyright © 2023 RISC-V IOMMU Task Group
+ *
+ * RISC-V IOMMU - Register Layout and Data Structures.
+ *
+ * Based on the IOMMU spec version 1.0, 3/2023
+ * https://github.com/riscv-non-isa/riscv-iommu
+ */
+
+#ifndef HW_RISCV_IOMMU_BITS_H
+#define HW_RISCV_IOMMU_BITS_H
+
+#include "qemu/osdep.h"
+
+#define RISCV_IOMMU_SPEC_DOT_VER 0x010
+
+#ifndef GENMASK_ULL
+#define GENMASK_ULL(h, l) (((~0ULL) >> (63 - (h) + (l))) << (l))
+#endif
+
+/*
+ * struct riscv_iommu_fq_record - Fault/Event Queue Record
+ * See section 3.2 for more info.
+ */
+struct riscv_iommu_fq_record {
+uint64_t hdr;
+uint64_t _reserved;
+uint64_t iotval;
+uint64_t iotval2;
+};
+/* Header fields */
+#define RISCV_IOMMU_FQ_HDR_CAUSEGENMASK_ULL(11, 0)
+#define RISCV_IOMMU_FQ_HDR_PID  GENMASK_ULL(31, 12)
+#define RISCV_IOMMU_FQ_HDR_PV   BIT_ULL(32)
+#define RISCV_IOMMU_FQ_HDR_TTYPEGENMASK_ULL(39, 34)
+#define RISCV_IOMMU_FQ_HDR_DID  GENMASK_ULL(63, 40)
+
+/*
+ * struct riscv_iommu_pq_record - PCIe Page Request record
+ * For more infos on the PCIe Page Request queue see chapter 3.3.
+ */
+struct riscv_iommu_pq_record {
+  uint64_t hdr;
+  uint64_t payload;
+};
+/* Header fields */
+#define RISCV_IOMMU_PREQ_HDR_PIDGENMASK_ULL(31, 12)
+#define RISCV_IOMMU_PREQ_HDR_PV BIT_ULL(32)
+#define RISCV_IOMMU_PREQ_HDR_PRIV   BIT_ULL(33)
+#define RISCV_IOMMU_PREQ_HDR_EXEC   BIT_ULL(34)
+#define RISCV_IOMMU_PREQ_HDR_DIDGENMASK_ULL(63, 40)
+/* Payload fields */
+#define RISCV_IOMMU_PREQ_PAYLOAD_M  GENMASK_ULL(2, 0)
+
+/* Common field positions */
+#define RISCV_IOMMU_PPN_FIELD   GENMASK_ULL(53, 10)
+#define RISCV_IOMMU_QUEUE_LOGSZ_FIELD   GENMASK_ULL(4, 0)
+#define RISCV_IOMMU_QUEUE_INDEX_FIELD   GENMASK_ULL(31, 0)
+#define RISCV_IOMMU_QUEUE_ENABLEBIT(0)
+#define RISCV_IOMMU_QUEUE_INTR_ENABLE   BIT(1)
+#define RISCV_IOMMU_QUEUE_MEM_FAULT BIT(8)
+#define RISCV_IOMMU_QUEUE_OVERFLOW  BIT(9)
+#define RISCV_IOMMU_QUEUE_ACTIVEBIT(16)
+#define RISCV_IOMMU_QUEUE_BUSY  BIT(17)
+#define RISCV_IOMMU_ATP_PPN_FIELD   GENMASK_ULL(43, 0)
+#define RISCV_IOMMU_ATP_MODE_FIELD  GENMASK_ULL(63, 60)
+
+/* 5.3 IOMMU Capabilities (64bits) */
+#define RISCV_IOMMU_REG_CAP 0x
+#define RISCV_IOMMU_CAP_VERSION GENMASK_ULL(7, 0)
+#define RISCV_IOMMU_CAP_MSI_FLATBIT_ULL(22)
+#define RISCV_IOMMU_CAP_MSI_MRIFBIT_ULL(23)
+#define RISCV_IOMMU_CAP_T2GPA   BIT_ULL(26)
+#define RISCV_IOMMU_CAP_IGS GENMASK_ULL(29, 28)
+#define RISCV_IOMMU_CAP_PAS GENMASK_ULL(37, 32)
+#define RISCV_IOMMU_CAP_PD8 BIT_ULL(38)
+#define RISCV_IOMMU_CAP_PD17BIT_ULL(39)
+#define RISCV_IOMMU_CAP_PD20BIT_ULL(40)
+
+/* 5.4 Features control register (32bits) */
+#define RISCV_IOMMU_REG_FCTL0x0008
+#define RISCV_IOMMU_FCTL_WSIBIT(1)
+
+/* 5.5 Device-directory-table pointer (64bits) */
+#define RISCV_IOMMU_REG_DDTP0x0010
+#define RISCV_IOMMU_DDTP_MODE   GENMASK_ULL(3, 0)
+#define RISCV_IOMMU_DDTP_BUSY   BIT_ULL(4)
+#define RISCV_IOMMU_DDTP_PPNRISCV_IOMMU_PPN_FIELD
+
+enum riscv_iommu_ddtp_modes {
+RISCV_IOMMU_DDTP_MODE_OFF = 0,
+RISCV_IOMMU_DDTP_MODE_BARE = 1,
+RISCV_IOMMU_DDTP_MODE_1LVL = 2,
+RISCV_IOMMU_DDTP_MODE_2LVL = 3,
+RISCV_IOMMU_DDTP_MODE_3LVL = 4,
+RISCV_IOMMU_DDTP_MODE_MAX = 4
+};
+
+/* 5.6 Command Queue Base (64bits) */
+#define RISCV_IOMMU_REG_CQB 0x0018
+#define RISCV_IOMMU_CQB_LOG2SZ  RISCV_IOMMU_QUEUE_LOGSZ_FIELD
+#define RISCV_IOMMU_CQB_PPN RISCV_IOMMU_PPN_FIELD
+
+/* 5.7 Command Queue head (32bits) */
+#define RISCV_IOMMU_REG_CQH 0x0020
+
+/* 5.8 Command Queue tail (32bits) */
+#define RISCV_IOMMU_REG_CQT 0x0024
+
+/* 5.9 Fault Queue Base (64bits) */
+#define RISCV_IOMMU_REG_FQB  

[PATCH v3 11/13] hw/riscv/riscv-iommu: add DBG support

2024-05-23 Thread Daniel Henrique Barboza
From: Tomasz Jeznach 

DBG support adds three additional registers: tr_req_iova, tr_req_ctl and
tr_response.

The DBG cap is always enabled. No on/off toggle is provided for it.

Signed-off-by: Tomasz Jeznach 
Signed-off-by: Daniel Henrique Barboza 
---
 hw/riscv/riscv-iommu-bits.h | 17 +++
 hw/riscv/riscv-iommu.c  | 59 +
 2 files changed, 76 insertions(+)

diff --git a/hw/riscv/riscv-iommu-bits.h b/hw/riscv/riscv-iommu-bits.h
index e253b29b16..f143c4a926 100644
--- a/hw/riscv/riscv-iommu-bits.h
+++ b/hw/riscv/riscv-iommu-bits.h
@@ -84,6 +84,7 @@ struct riscv_iommu_pq_record {
 #define RISCV_IOMMU_CAP_ATS BIT_ULL(25)
 #define RISCV_IOMMU_CAP_T2GPA   BIT_ULL(26)
 #define RISCV_IOMMU_CAP_IGS GENMASK_ULL(29, 28)
+#define RISCV_IOMMU_CAP_DBG BIT_ULL(31)
 #define RISCV_IOMMU_CAP_PAS GENMASK_ULL(37, 32)
 #define RISCV_IOMMU_CAP_PD8 BIT_ULL(38)
 #define RISCV_IOMMU_CAP_PD17BIT_ULL(39)
@@ -185,6 +186,22 @@ enum {
 RISCV_IOMMU_INTR_COUNT
 };
 
+/* 5.24 Translation request IOVA (64bits) */
+#define RISCV_IOMMU_REG_TR_REQ_IOVA 0x0258
+
+/* 5.25 Translation request control (64bits) */
+#define RISCV_IOMMU_REG_TR_REQ_CTL  0x0260
+#define RISCV_IOMMU_TR_REQ_CTL_GO_BUSY  BIT_ULL(0)
+#define RISCV_IOMMU_TR_REQ_CTL_NW   BIT_ULL(3)
+#define RISCV_IOMMU_TR_REQ_CTL_PID  GENMASK_ULL(31, 12)
+#define RISCV_IOMMU_TR_REQ_CTL_DID  GENMASK_ULL(63, 40)
+
+/* 5.26 Translation request response (64bits) */
+#define RISCV_IOMMU_REG_TR_RESPONSE 0x0268
+#define RISCV_IOMMU_TR_RESPONSE_FAULT   BIT_ULL(0)
+#define RISCV_IOMMU_TR_RESPONSE_S   BIT_ULL(9)
+#define RISCV_IOMMU_TR_RESPONSE_PPN RISCV_IOMMU_PPN_FIELD
+
 /* 5.27 Interrupt cause to vector (64bits) */
 #define RISCV_IOMMU_REG_IVEC0x02F8
 
diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
index 3516b82081..52f0851895 100644
--- a/hw/riscv/riscv-iommu.c
+++ b/hw/riscv/riscv-iommu.c
@@ -1655,6 +1655,50 @@ static void 
riscv_iommu_process_pq_control(RISCVIOMMUState *s)
 riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_PQCSR, ctrl_set, ctrl_clr);
 }
 
+static void riscv_iommu_process_dbg(RISCVIOMMUState *s)
+{
+uint64_t iova = riscv_iommu_reg_get64(s, RISCV_IOMMU_REG_TR_REQ_IOVA);
+uint64_t ctrl = riscv_iommu_reg_get64(s, RISCV_IOMMU_REG_TR_REQ_CTL);
+unsigned devid = get_field(ctrl, RISCV_IOMMU_TR_REQ_CTL_DID);
+unsigned pid = get_field(ctrl, RISCV_IOMMU_TR_REQ_CTL_PID);
+RISCVIOMMUContext *ctx;
+void *ref;
+
+if (!(ctrl & RISCV_IOMMU_TR_REQ_CTL_GO_BUSY)) {
+return;
+}
+
+ctx = riscv_iommu_ctx(s, devid, pid, );
+if (ctx == NULL) {
+riscv_iommu_reg_set64(s, RISCV_IOMMU_REG_TR_RESPONSE,
+ RISCV_IOMMU_TR_RESPONSE_FAULT |
+ (RISCV_IOMMU_FQ_CAUSE_DMA_DISABLED << 10));
+} else {
+IOMMUTLBEntry iotlb = {
+.iova = iova,
+.perm = ctrl & RISCV_IOMMU_TR_REQ_CTL_NW ? IOMMU_RO : IOMMU_RW,
+.addr_mask = ~0,
+.target_as = NULL,
+};
+int fault = riscv_iommu_translate(s, ctx, , false);
+if (fault) {
+iova = RISCV_IOMMU_TR_RESPONSE_FAULT | (((uint64_t) fault) << 10);
+} else {
+iova = iotlb.translated_addr & ~iotlb.addr_mask;
+iova >>= TARGET_PAGE_BITS;
+iova &= RISCV_IOMMU_TR_RESPONSE_PPN;
+
+/* We do not support superpages (> 4kbs) for now */
+iova &= ~RISCV_IOMMU_TR_RESPONSE_S;
+}
+riscv_iommu_reg_set64(s, RISCV_IOMMU_REG_TR_RESPONSE, iova);
+}
+
+riscv_iommu_reg_mod64(s, RISCV_IOMMU_REG_TR_REQ_CTL, 0,
+RISCV_IOMMU_TR_REQ_CTL_GO_BUSY);
+riscv_iommu_ctx_put(s, ref);
+}
+
 typedef void riscv_iommu_process_fn(RISCVIOMMUState *s);
 
 static void riscv_iommu_update_ipsr(RISCVIOMMUState *s, uint64_t data)
@@ -1778,6 +1822,12 @@ static MemTxResult riscv_iommu_mmio_write(void *opaque, 
hwaddr addr,
 
 return MEMTX_OK;
 
+case RISCV_IOMMU_REG_TR_REQ_CTL:
+process_fn = riscv_iommu_process_dbg;
+regb = RISCV_IOMMU_REG_TR_REQ_CTL;
+busy = RISCV_IOMMU_TR_REQ_CTL_GO_BUSY;
+break;
+
 default:
 break;
 }
@@ -1950,6 +2000,9 @@ static void riscv_iommu_realize(DeviceState *dev, Error 
**errp)
 s->cap |= RISCV_IOMMU_CAP_SV32X4 | RISCV_IOMMU_CAP_SV39X4 |
   RISCV_IOMMU_CAP_SV48X4 | RISCV_IOMMU_CAP_SV57X4;
 }
+/* Enable translation debug interface */
+s->cap |= RISCV_IOMMU_CAP_DBG;
+
 /* Report QEMU target physical address space limits */
 s->cap = set_field(s->cap, RISCV_IOMMU_CAP_PAS,
TARGET_PHYS_ADDR_SPACE_BITS);
@@ -2004,6 +2057,12 @@ static void riscv_iommu_realize(DeviceState *dev, Error 
**errp)
 stl_le_p(>regs_wc[RISCV_IOMMU_REG_IPS

[PATCH v3 08/13] hw/riscv/riscv-iommu: add Address Translation Cache (IOATC)

2024-05-23 Thread Daniel Henrique Barboza
From: Tomasz Jeznach 

The RISC-V IOMMU spec predicts that the IOMMU can use translation caches
to hold entries from the DDT. This includes implementation for all cache
commands that are marked as 'not implemented'.

There are some artifacts included in the cache that predicts s-stage and
g-stage elements, although we don't support it yet. We'll introduce them
next.

Signed-off-by: Tomasz Jeznach 
Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Frank Chang 
---
 hw/riscv/riscv-iommu.c | 189 -
 hw/riscv/riscv-iommu.h |   2 +
 2 files changed, 187 insertions(+), 4 deletions(-)

diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
index 39b4ff1405..abf6ae7726 100644
--- a/hw/riscv/riscv-iommu.c
+++ b/hw/riscv/riscv-iommu.c
@@ -63,6 +63,16 @@ struct RISCVIOMMUContext {
 uint64_t msiptp;/* MSI redirection page table pointer */
 };
 
+/* Address translation cache entry */
+struct RISCVIOMMUEntry {
+uint64_t iova:44;   /* IOVA Page Number */
+uint64_t pscid:20;  /* Process Soft-Context identifier */
+uint64_t phys:44;   /* Physical Page Number */
+uint64_t gscid:16;  /* Guest Soft-Context identifier */
+uint64_t perm:2;/* IOMMU_RW flags */
+uint64_t __rfu:2;
+};
+
 /* IOMMU index for transactions without PASID specified. */
 #define RISCV_IOMMU_NOPASID 0
 
@@ -751,13 +761,125 @@ static AddressSpace *riscv_iommu_space(RISCVIOMMUState 
*s, uint32_t devid)
 return >iova_as;
 }
 
+/* Translation Object cache support */
+static gboolean __iot_equal(gconstpointer v1, gconstpointer v2)
+{
+RISCVIOMMUEntry *t1 = (RISCVIOMMUEntry *) v1;
+RISCVIOMMUEntry *t2 = (RISCVIOMMUEntry *) v2;
+return t1->gscid == t2->gscid && t1->pscid == t2->pscid &&
+   t1->iova == t2->iova;
+}
+
+static guint __iot_hash(gconstpointer v)
+{
+RISCVIOMMUEntry *t = (RISCVIOMMUEntry *) v;
+return (guint)t->iova;
+}
+
+/* GV: 1 PSCV: 1 AV: 1 */
+static void __iot_inval_pscid_iova(gpointer key, gpointer value, gpointer data)
+{
+RISCVIOMMUEntry *iot = (RISCVIOMMUEntry *) value;
+RISCVIOMMUEntry *arg = (RISCVIOMMUEntry *) data;
+if (iot->gscid == arg->gscid &&
+iot->pscid == arg->pscid &&
+iot->iova == arg->iova) {
+iot->perm = IOMMU_NONE;
+}
+}
+
+/* GV: 1 PSCV: 1 AV: 0 */
+static void __iot_inval_pscid(gpointer key, gpointer value, gpointer data)
+{
+RISCVIOMMUEntry *iot = (RISCVIOMMUEntry *) value;
+RISCVIOMMUEntry *arg = (RISCVIOMMUEntry *) data;
+if (iot->gscid == arg->gscid &&
+iot->pscid == arg->pscid) {
+iot->perm = IOMMU_NONE;
+}
+}
+
+/* GV: 1 GVMA: 1 */
+static void __iot_inval_gscid_gpa(gpointer key, gpointer value, gpointer data)
+{
+RISCVIOMMUEntry *iot = (RISCVIOMMUEntry *) value;
+RISCVIOMMUEntry *arg = (RISCVIOMMUEntry *) data;
+if (iot->gscid == arg->gscid) {
+/* simplified cache, no GPA matching */
+iot->perm = IOMMU_NONE;
+}
+}
+
+/* GV: 1 GVMA: 0 */
+static void __iot_inval_gscid(gpointer key, gpointer value, gpointer data)
+{
+RISCVIOMMUEntry *iot = (RISCVIOMMUEntry *) value;
+RISCVIOMMUEntry *arg = (RISCVIOMMUEntry *) data;
+if (iot->gscid == arg->gscid) {
+iot->perm = IOMMU_NONE;
+}
+}
+
+/* GV: 0 */
+static void __iot_inval_all(gpointer key, gpointer value, gpointer data)
+{
+RISCVIOMMUEntry *iot = (RISCVIOMMUEntry *) value;
+iot->perm = IOMMU_NONE;
+}
+
+/* caller should keep ref-count for iot_cache object */
+static RISCVIOMMUEntry *riscv_iommu_iot_lookup(RISCVIOMMUContext *ctx,
+GHashTable *iot_cache, hwaddr iova)
+{
+RISCVIOMMUEntry key = {
+.pscid = get_field(ctx->ta, RISCV_IOMMU_DC_TA_PSCID),
+.iova  = PPN_DOWN(iova),
+};
+return g_hash_table_lookup(iot_cache, );
+}
+
+/* caller should keep ref-count for iot_cache object */
+static void riscv_iommu_iot_update(RISCVIOMMUState *s,
+GHashTable *iot_cache, RISCVIOMMUEntry *iot)
+{
+if (!s->iot_limit) {
+return;
+}
+
+if (g_hash_table_size(s->iot_cache) >= s->iot_limit) {
+iot_cache = g_hash_table_new_full(__iot_hash, __iot_equal,
+  g_free, NULL);
+g_hash_table_unref(qatomic_xchg(>iot_cache, iot_cache));
+}
+g_hash_table_add(iot_cache, iot);
+}
+
+static void riscv_iommu_iot_inval(RISCVIOMMUState *s, GHFunc func,
+uint32_t gscid, uint32_t pscid, hwaddr iova)
+{
+GHashTable *iot_cache;
+RISCVIOMMUEntry key = {
+.gscid = gscid,
+.pscid = pscid,
+.iova  = PPN_DOWN(iova),
+};
+
+iot_cache = g_hash_table_ref(s->iot_cache);
+g_hash_table_foreach(iot_cache, func, );
+g_hash_table_unref(iot_cache);
+}
+
 static int riscv_iommu_translate(RISCVIOMMUState *s, RISCVIOMMUC

[PATCH v3 03/13] hw/riscv: add RISC-V IOMMU base emulation

2024-05-23 Thread Daniel Henrique Barboza
From: Tomasz Jeznach 

The RISC-V IOMMU specification is now ratified as-per the RISC-V
international process. The latest frozen specifcation can be found
at:

https://github.com/riscv-non-isa/riscv-iommu/releases/download/v1.0/riscv-iommu.pdf

Add the foundation of the device emulation for RISC-V IOMMU, which
includes an IOMMU that has no capabilities but MSI interrupt support and
fault queue interfaces. We'll add add more features incrementally in the
next patches.

Co-developed-by: Sebastien Boeuf 
Signed-off-by: Sebastien Boeuf 
Signed-off-by: Tomasz Jeznach 
Signed-off-by: Daniel Henrique Barboza 
---
 hw/riscv/Kconfig |4 +
 hw/riscv/meson.build |1 +
 hw/riscv/riscv-iommu.c   | 1602 ++
 hw/riscv/riscv-iommu.h   |  141 
 hw/riscv/trace-events|   11 +
 hw/riscv/trace.h |1 +
 include/hw/riscv/iommu.h |   36 +
 meson.build  |1 +
 8 files changed, 1797 insertions(+)
 create mode 100644 hw/riscv/riscv-iommu.c
 create mode 100644 hw/riscv/riscv-iommu.h
 create mode 100644 hw/riscv/trace-events
 create mode 100644 hw/riscv/trace.h
 create mode 100644 include/hw/riscv/iommu.h

diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
index a2030e3a6f..f69d6e3c8e 100644
--- a/hw/riscv/Kconfig
+++ b/hw/riscv/Kconfig
@@ -1,3 +1,6 @@
+config RISCV_IOMMU
+bool
+
 config RISCV_NUMA
 bool
 
@@ -47,6 +50,7 @@ config RISCV_VIRT
 select SERIAL
 select RISCV_ACLINT
 select RISCV_APLIC
+select RISCV_IOMMU
 select RISCV_IMSIC
 select SIFIVE_PLIC
 select SIFIVE_TEST
diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build
index f872674093..cbc99c6e8e 100644
--- a/hw/riscv/meson.build
+++ b/hw/riscv/meson.build
@@ -10,5 +10,6 @@ riscv_ss.add(when: 'CONFIG_SIFIVE_U', if_true: 
files('sifive_u.c'))
 riscv_ss.add(when: 'CONFIG_SPIKE', if_true: files('spike.c'))
 riscv_ss.add(when: 'CONFIG_MICROCHIP_PFSOC', if_true: 
files('microchip_pfsoc.c'))
 riscv_ss.add(when: 'CONFIG_ACPI', if_true: files('virt-acpi-build.c'))
+riscv_ss.add(when: 'CONFIG_RISCV_IOMMU', if_true: files('riscv-iommu.c'))
 
 hw_arch += {'riscv': riscv_ss}
diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
new file mode 100644
index 00..39b4ff1405
--- /dev/null
+++ b/hw/riscv/riscv-iommu.c
@@ -0,0 +1,1602 @@
+/*
+ * QEMU emulation of an RISC-V IOMMU
+ *
+ * Copyright (C) 2021-2023, Rivos Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qom/object.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/pci/pci_device.h"
+#include "hw/qdev-properties.h"
+#include "hw/riscv/riscv_hart.h"
+#include "migration/vmstate.h"
+#include "qapi/error.h"
+#include "qemu/timer.h"
+
+#include "cpu_bits.h"
+#include "riscv-iommu.h"
+#include "riscv-iommu-bits.h"
+#include "trace.h"
+
+#define LIMIT_CACHE_CTX   (1U << 7)
+#define LIMIT_CACHE_IOT   (1U << 20)
+
+/* Physical page number coversions */
+#define PPN_PHYS(ppn) ((ppn) << TARGET_PAGE_BITS)
+#define PPN_DOWN(phy) ((phy) >> TARGET_PAGE_BITS)
+
+typedef struct RISCVIOMMUContext RISCVIOMMUContext;
+typedef struct RISCVIOMMUEntry RISCVIOMMUEntry;
+
+/* Device assigned I/O address space */
+struct RISCVIOMMUSpace {
+IOMMUMemoryRegion iova_mr;  /* IOVA memory region for attached device */
+AddressSpace iova_as;   /* IOVA address space for attached device */
+RISCVIOMMUState *iommu; /* Managing IOMMU device state */
+uint32_t devid; /* Requester identifier, AKA device_id */
+bool notifier;  /* IOMMU unmap notifier enabled */
+QLIST_ENTRY(RISCVIOMMUSpace) list;
+};
+
+/* Device translation context state. */
+struct RISCVIOMMUContext {
+uint64_t devid:24;  /* Requester Id, AKA device_id */
+uint64_t pasid:20;  /* Process Address Space ID */
+uint64_t __rfu:20;  /* reserved */
+uint64_t tc;/* Translation Control */
+uint64_t ta;/* Translation Attributes */
+uint64_t msi_addr_mask; /* MSI filtering - address mask */
+uint64_t msi_addr_pattern;  /* MSI filtering - address pattern */
+uint64_t msiptp;/* MSI redirection page table pointe

[PATCH v3 06/13] hw/riscv/virt.c: support for RISC-V IOMMU PCIDevice hotplug

2024-05-23 Thread Daniel Henrique Barboza
From: Tomasz Jeznach 

Generate device tree entry for riscv-iommu PCI device, along with
mapping all PCI device identifiers to the single IOMMU device instance.

Signed-off-by: Tomasz Jeznach 
Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Frank Chang 
---
 hw/riscv/virt.c | 33 -
 1 file changed, 32 insertions(+), 1 deletion(-)

diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 4fdb660525..b6ebbb3baf 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -32,6 +32,7 @@
 #include "hw/core/sysbus-fdt.h"
 #include "target/riscv/pmu.h"
 #include "hw/riscv/riscv_hart.h"
+#include "hw/riscv/iommu.h"
 #include "hw/riscv/virt.h"
 #include "hw/riscv/boot.h"
 #include "hw/riscv/numa.h"
@@ -1006,6 +1007,30 @@ static void create_fdt_virtio_iommu(RISCVVirtState *s, 
uint16_t bdf)
bdf + 1, iommu_phandle, bdf + 1, 0x - bdf);
 }
 
+static void create_fdt_iommu(RISCVVirtState *s, uint16_t bdf)
+{
+const char comp[] = "riscv,pci-iommu";
+void *fdt = MACHINE(s)->fdt;
+uint32_t iommu_phandle;
+g_autofree char *iommu_node = NULL;
+g_autofree char *pci_node = NULL;
+
+pci_node = g_strdup_printf("/soc/pci@%lx",
+   (long) virt_memmap[VIRT_PCIE_ECAM].base);
+iommu_node = g_strdup_printf("%s/iommu@%x", pci_node, bdf);
+iommu_phandle = qemu_fdt_alloc_phandle(fdt);
+qemu_fdt_add_subnode(fdt, iommu_node);
+
+qemu_fdt_setprop(fdt, iommu_node, "compatible", comp, sizeof(comp));
+qemu_fdt_setprop_cell(fdt, iommu_node, "#iommu-cells", 1);
+qemu_fdt_setprop_cell(fdt, iommu_node, "phandle", iommu_phandle);
+qemu_fdt_setprop_cells(fdt, iommu_node, "reg",
+   bdf << 8, 0, 0, 0, 0);
+qemu_fdt_setprop_cells(fdt, pci_node, "iommu-map",
+   0, iommu_phandle, 0, bdf,
+   bdf + 1, iommu_phandle, bdf + 1, 0x - bdf);
+}
+
 static void finalize_fdt(RISCVVirtState *s)
 {
 uint32_t phandle = 1, irq_mmio_phandle = 1, msi_pcie_phandle = 1;
@@ -1712,9 +1737,11 @@ static HotplugHandler 
*virt_machine_get_hotplug_handler(MachineState *machine,
 MachineClass *mc = MACHINE_GET_CLASS(machine);
 
 if (device_is_dynamic_sysbus(mc, dev) ||
-object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) {
+object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI) ||
+object_dynamic_cast(OBJECT(dev), TYPE_RISCV_IOMMU_PCI)) {
 return HOTPLUG_HANDLER(machine);
 }
+
 return NULL;
 }
 
@@ -1735,6 +1762,10 @@ static void virt_machine_device_plug_cb(HotplugHandler 
*hotplug_dev,
 if (object_dynamic_cast(OBJECT(dev), TYPE_VIRTIO_IOMMU_PCI)) {
 create_fdt_virtio_iommu(s, pci_get_bdf(PCI_DEVICE(dev)));
 }
+
+if (object_dynamic_cast(OBJECT(dev), TYPE_RISCV_IOMMU_PCI)) {
+create_fdt_iommu(s, pci_get_bdf(PCI_DEVICE(dev)));
+}
 }
 
 static void virt_machine_class_init(ObjectClass *oc, void *data)
-- 
2.44.0




[PATCH v3 05/13] hw/riscv: add riscv-iommu-pci reference device

2024-05-23 Thread Daniel Henrique Barboza
From: Tomasz Jeznach 

The RISC-V IOMMU can be modelled as a PCIe device following the
guidelines of the RISC-V IOMMU spec, chapter 7.1, "Integrating an IOMMU
as a PCIe device".

Signed-off-by: Tomasz Jeznach 
Signed-off-by: Daniel Henrique Barboza 
---
 hw/riscv/meson.build   |   2 +-
 hw/riscv/riscv-iommu-pci.c | 177 +
 2 files changed, 178 insertions(+), 1 deletion(-)
 create mode 100644 hw/riscv/riscv-iommu-pci.c

diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build
index cbc99c6e8e..adbef8a9b2 100644
--- a/hw/riscv/meson.build
+++ b/hw/riscv/meson.build
@@ -10,6 +10,6 @@ riscv_ss.add(when: 'CONFIG_SIFIVE_U', if_true: 
files('sifive_u.c'))
 riscv_ss.add(when: 'CONFIG_SPIKE', if_true: files('spike.c'))
 riscv_ss.add(when: 'CONFIG_MICROCHIP_PFSOC', if_true: 
files('microchip_pfsoc.c'))
 riscv_ss.add(when: 'CONFIG_ACPI', if_true: files('virt-acpi-build.c'))
-riscv_ss.add(when: 'CONFIG_RISCV_IOMMU', if_true: files('riscv-iommu.c'))
+riscv_ss.add(when: 'CONFIG_RISCV_IOMMU', if_true: files('riscv-iommu.c', 
'riscv-iommu-pci.c'))
 
 hw_arch += {'riscv': riscv_ss}
diff --git a/hw/riscv/riscv-iommu-pci.c b/hw/riscv/riscv-iommu-pci.c
new file mode 100644
index 00..7635cc64ff
--- /dev/null
+++ b/hw/riscv/riscv-iommu-pci.c
@@ -0,0 +1,177 @@
+/*
+ * QEMU emulation of an RISC-V IOMMU
+ *
+ * Copyright (C) 2022-2023 Rivos Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/pci/msi.h"
+#include "hw/pci/msix.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/qdev-properties.h"
+#include "hw/riscv/riscv_hart.h"
+#include "migration/vmstate.h"
+#include "qapi/error.h"
+#include "qemu/error-report.h"
+#include "qemu/host-utils.h"
+#include "qom/object.h"
+
+#include "cpu_bits.h"
+#include "riscv-iommu.h"
+#include "riscv-iommu-bits.h"
+
+/* RISC-V IOMMU PCI Device Emulation */
+
+typedef struct RISCVIOMMUStatePci {
+PCIDevicepci; /* Parent PCIe device state */
+uint16_t vendor_id;
+uint16_t device_id;
+uint8_t  revision;
+MemoryRegion bar0;/* PCI BAR (including MSI-x config) */
+RISCVIOMMUState  iommu;   /* common IOMMU state */
+} RISCVIOMMUStatePci;
+
+/* interrupt delivery callback */
+static void riscv_iommu_pci_notify(RISCVIOMMUState *iommu, unsigned vector)
+{
+RISCVIOMMUStatePci *s = container_of(iommu, RISCVIOMMUStatePci, iommu);
+
+if (msix_enabled(&(s->pci))) {
+msix_notify(&(s->pci), vector);
+}
+}
+
+static void riscv_iommu_pci_realize(PCIDevice *dev, Error **errp)
+{
+RISCVIOMMUStatePci *s = DO_UPCAST(RISCVIOMMUStatePci, pci, dev);
+RISCVIOMMUState *iommu = >iommu;
+uint8_t *pci_conf = dev->config;
+Error *err = NULL;
+
+pci_set_word(pci_conf + PCI_VENDOR_ID, s->vendor_id);
+pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID, s->vendor_id);
+pci_set_word(pci_conf + PCI_DEVICE_ID, s->device_id);
+pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, s->device_id);
+pci_set_byte(pci_conf + PCI_REVISION_ID, s->revision);
+
+/* Set device id for trace / debug */
+DEVICE(iommu)->id = g_strdup_printf("%02x:%02x.%01x",
+pci_dev_bus_num(dev), PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+qdev_realize(DEVICE(iommu), NULL, errp);
+
+memory_region_init(>bar0, OBJECT(s), "riscv-iommu-bar0",
+QEMU_ALIGN_UP(memory_region_size(>regs_mr), TARGET_PAGE_SIZE));
+memory_region_add_subregion(>bar0, 0, >regs_mr);
+
+pcie_endpoint_cap_init(dev, 0);
+
+pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY |
+ PCI_BASE_ADDRESS_MEM_TYPE_64, >bar0);
+
+int ret = msix_init(dev, RISCV_IOMMU_INTR_COUNT,
+>bar0, 0, RISCV_IOMMU_REG_MSI_CONFIG,
+>bar0, 0, RISCV_IOMMU_REG_MSI_CONFIG + 256, 0, 
);
+
+if (ret == -ENOTSUP) {
+/*
+ * MSI-x is not supported by the platform.
+ * Driver should use timer/polling based notification handlers.
+ */
+warn_report_err(err);
+} else if (ret < 0) {
+error_propagate(errp, err);
+return;
+} else {
+/* mark 

[PATCH v3 10/13] hw/riscv/riscv-iommu: add ATS support

2024-05-23 Thread Daniel Henrique Barboza
From: Tomasz Jeznach 

Add PCIe Address Translation Services (ATS) capabilities to the IOMMU.
This will add support for ATS translation requests in Fault/Event
queues, Page-request queue and IOATC invalidations.

Signed-off-by: Tomasz Jeznach 
Signed-off-by: Daniel Henrique Barboza 
---
 hw/riscv/riscv-iommu-bits.h |  43 +++-
 hw/riscv/riscv-iommu.c  | 129 +++-
 hw/riscv/riscv-iommu.h  |   1 +
 hw/riscv/trace-events   |   3 +
 4 files changed, 173 insertions(+), 3 deletions(-)

diff --git a/hw/riscv/riscv-iommu-bits.h b/hw/riscv/riscv-iommu-bits.h
index a4def7b8ec..e253b29b16 100644
--- a/hw/riscv/riscv-iommu-bits.h
+++ b/hw/riscv/riscv-iommu-bits.h
@@ -81,6 +81,7 @@ struct riscv_iommu_pq_record {
 #define RISCV_IOMMU_CAP_SV57X4  BIT_ULL(19)
 #define RISCV_IOMMU_CAP_MSI_FLATBIT_ULL(22)
 #define RISCV_IOMMU_CAP_MSI_MRIFBIT_ULL(23)
+#define RISCV_IOMMU_CAP_ATS BIT_ULL(25)
 #define RISCV_IOMMU_CAP_T2GPA   BIT_ULL(26)
 #define RISCV_IOMMU_CAP_IGS GENMASK_ULL(29, 28)
 #define RISCV_IOMMU_CAP_PAS GENMASK_ULL(37, 32)
@@ -209,6 +210,7 @@ struct riscv_iommu_dc {
 
 /* Translation control fields */
 #define RISCV_IOMMU_DC_TC_V BIT_ULL(0)
+#define RISCV_IOMMU_DC_TC_EN_ATSBIT_ULL(1)
 #define RISCV_IOMMU_DC_TC_EN_PRIBIT_ULL(2)
 #define RISCV_IOMMU_DC_TC_T2GPA BIT_ULL(3)
 #define RISCV_IOMMU_DC_TC_DTF   BIT_ULL(4)
@@ -270,6 +272,20 @@ struct riscv_iommu_command {
 #define RISCV_IOMMU_CMD_IODIR_DVBIT_ULL(33)
 #define RISCV_IOMMU_CMD_IODIR_DID   GENMASK_ULL(63, 40)
 
+/* 3.1.4 I/O MMU PCIe ATS */
+#define RISCV_IOMMU_CMD_ATS_OPCODE  4
+#define RISCV_IOMMU_CMD_ATS_FUNC_INVAL  0
+#define RISCV_IOMMU_CMD_ATS_FUNC_PRGR   1
+#define RISCV_IOMMU_CMD_ATS_PID GENMASK_ULL(31, 12)
+#define RISCV_IOMMU_CMD_ATS_PV  BIT_ULL(32)
+#define RISCV_IOMMU_CMD_ATS_DSV BIT_ULL(33)
+#define RISCV_IOMMU_CMD_ATS_RID GENMASK_ULL(55, 40)
+#define RISCV_IOMMU_CMD_ATS_DSEGGENMASK_ULL(63, 56)
+/* dword1 is the ATS payload, two different payload types for INVAL and PRGR */
+
+/* ATS.PRGR payload */
+#define RISCV_IOMMU_CMD_ATS_PRGR_RESP_CODE  GENMASK_ULL(47, 44)
+
 enum riscv_iommu_dc_fsc_atp_modes {
 RISCV_IOMMU_DC_FSC_MODE_BARE = 0,
 RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV32 = 8,
@@ -334,7 +350,32 @@ enum riscv_iommu_fq_ttypes {
 RISCV_IOMMU_FQ_TTYPE_TADDR_INST_FETCH = 5,
 RISCV_IOMMU_FQ_TTYPE_TADDR_RD = 6,
 RISCV_IOMMU_FQ_TTYPE_TADDR_WR = 7,
-RISCV_IOMMU_FW_TTYPE_PCIE_MSG_REQ = 8,
+RISCV_IOMMU_FQ_TTYPE_PCIE_ATS_REQ = 8,
+RISCV_IOMMU_FW_TTYPE_PCIE_MSG_REQ = 9,
+};
+
+/* Header fields */
+#define RISCV_IOMMU_PREQ_HDR_PIDGENMASK_ULL(31, 12)
+#define RISCV_IOMMU_PREQ_HDR_PV BIT_ULL(32)
+#define RISCV_IOMMU_PREQ_HDR_PRIV   BIT_ULL(33)
+#define RISCV_IOMMU_PREQ_HDR_EXEC   BIT_ULL(34)
+#define RISCV_IOMMU_PREQ_HDR_DIDGENMASK_ULL(63, 40)
+
+/* Payload fields */
+#define RISCV_IOMMU_PREQ_PAYLOAD_R  BIT_ULL(0)
+#define RISCV_IOMMU_PREQ_PAYLOAD_W  BIT_ULL(1)
+#define RISCV_IOMMU_PREQ_PAYLOAD_L  BIT_ULL(2)
+#define RISCV_IOMMU_PREQ_PAYLOAD_M  GENMASK_ULL(2, 0)
+#define RISCV_IOMMU_PREQ_PRG_INDEX  GENMASK_ULL(11, 3)
+#define RISCV_IOMMU_PREQ_UADDR  GENMASK_ULL(63, 12)
+
+
+/*
+ * struct riscv_iommu_msi_pte - MSI Page Table Entry
+ */
+struct riscv_iommu_msi_pte {
+  uint64_t pte;
+  uint64_t mrif_info;
 };
 
 /* Fields on pte */
diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
index 11c418b548..3516b82081 100644
--- a/hw/riscv/riscv-iommu.c
+++ b/hw/riscv/riscv-iommu.c
@@ -641,6 +641,20 @@ static bool 
riscv_iommu_validate_device_ctx(RISCVIOMMUState *s,
 RISCVIOMMUContext *ctx)
 {
 uint32_t fsc_mode, msi_mode;
+uint64_t gatp;
+
+if (!(s->cap & RISCV_IOMMU_CAP_ATS) &&
+(ctx->tc & RISCV_IOMMU_DC_TC_EN_ATS ||
+ ctx->tc & RISCV_IOMMU_DC_TC_EN_PRI ||
+ ctx->tc & RISCV_IOMMU_DC_TC_PRPR)) {
+return false;
+}
+
+if (!(ctx->tc & RISCV_IOMMU_DC_TC_EN_ATS) &&
+(ctx->tc & RISCV_IOMMU_DC_TC_T2GPA ||
+ ctx->tc & RISCV_IOMMU_DC_TC_EN_PRI)) {
+return false;
+}
 
 if (!(ctx->tc & RISCV_IOMMU_DC_TC_EN_PRI) &&
 ctx->tc & RISCV_IOMMU_DC_TC_PRPR) {
@@ -661,6 +675,12 @@ static bool 
riscv_iommu_validate_device_ctx(RISCVIOMMUState *s,
 }
 }
 
+gatp = get_field(ctx->gatp, RISCV_IOMMU_ATP_MODE_FIELD);
+if (ctx->tc & RISCV_IOMMU_DC_TC_T2GPA &&
+gatp == RISCV_IOMMU_DC_IOHGATP_MODE_BARE) {
+return false;
+}
+
 fsc_mode = get_field(ctx->satp, RISCV_IOMMU_DC_FSC_MODE);
 
 if (ctx->tc & RISCV_IOMMU_DC_TC_PDTV) {
@@ -754,7 +774,12 @@ static i

[PATCH v3 01/13] exec/memtxattr: add process identifier to the transaction attributes

2024-05-23 Thread Daniel Henrique Barboza
From: Tomasz Jeznach 

Extend memory transaction attributes with process identifier to allow
per-request address translation logic to use requester_id / process_id
to identify memory mapping (e.g. enabling IOMMU w/ PASID translations).

Signed-off-by: Tomasz Jeznach 
Reviewed-by: Frank Chang 
---
 include/exec/memattrs.h | 5 +
 1 file changed, 5 insertions(+)

diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h
index 14cdd8d582..46d0725416 100644
--- a/include/exec/memattrs.h
+++ b/include/exec/memattrs.h
@@ -52,6 +52,11 @@ typedef struct MemTxAttrs {
 unsigned int memory:1;
 /* Requester ID (for MSI for example) */
 unsigned int requester_id:16;
+
+/*
+ * PCI PASID support: Limited to 8 bits process identifier.
+ */
+unsigned int pasid:8;
 } MemTxAttrs;
 
 /* Bus masters which don't specify any attributes will get this,
-- 
2.44.0




[PATCH v3 09/13] hw/riscv/riscv-iommu: add s-stage and g-stage support

2024-05-23 Thread Daniel Henrique Barboza
From: Tomasz Jeznach 

Add support for s-stage (sv32, sv39, sv48, sv57 caps) and g-stage
(sv32x4, sv39x4, sv48x4, sv57x4 caps). Most of the work is done in the
riscv_iommu_spa_fetch() function that now has to consider how many
translation stages we need to walk the page table.

Signed-off-by: Tomasz Jeznach 
Signed-off-by: Daniel Henrique Barboza 
---
 hw/riscv/riscv-iommu-bits.h |  11 ++
 hw/riscv/riscv-iommu.c  | 331 +++-
 hw/riscv/riscv-iommu.h  |   2 +
 3 files changed, 336 insertions(+), 8 deletions(-)

diff --git a/hw/riscv/riscv-iommu-bits.h b/hw/riscv/riscv-iommu-bits.h
index f29b916acb..a4def7b8ec 100644
--- a/hw/riscv/riscv-iommu-bits.h
+++ b/hw/riscv/riscv-iommu-bits.h
@@ -71,6 +71,14 @@ struct riscv_iommu_pq_record {
 /* 5.3 IOMMU Capabilities (64bits) */
 #define RISCV_IOMMU_REG_CAP 0x
 #define RISCV_IOMMU_CAP_VERSION GENMASK_ULL(7, 0)
+#define RISCV_IOMMU_CAP_SV32BIT_ULL(8)
+#define RISCV_IOMMU_CAP_SV39BIT_ULL(9)
+#define RISCV_IOMMU_CAP_SV48BIT_ULL(10)
+#define RISCV_IOMMU_CAP_SV57BIT_ULL(11)
+#define RISCV_IOMMU_CAP_SV32X4  BIT_ULL(16)
+#define RISCV_IOMMU_CAP_SV39X4  BIT_ULL(17)
+#define RISCV_IOMMU_CAP_SV48X4  BIT_ULL(18)
+#define RISCV_IOMMU_CAP_SV57X4  BIT_ULL(19)
 #define RISCV_IOMMU_CAP_MSI_FLATBIT_ULL(22)
 #define RISCV_IOMMU_CAP_MSI_MRIFBIT_ULL(23)
 #define RISCV_IOMMU_CAP_T2GPA   BIT_ULL(26)
@@ -83,6 +91,7 @@ struct riscv_iommu_pq_record {
 /* 5.4 Features control register (32bits) */
 #define RISCV_IOMMU_REG_FCTL0x0008
 #define RISCV_IOMMU_FCTL_WSIBIT(1)
+#define RISCV_IOMMU_FCTL_GXLBIT(2)
 
 /* 5.5 Device-directory-table pointer (64bits) */
 #define RISCV_IOMMU_REG_DDTP0x0010
@@ -205,6 +214,8 @@ struct riscv_iommu_dc {
 #define RISCV_IOMMU_DC_TC_DTF   BIT_ULL(4)
 #define RISCV_IOMMU_DC_TC_PDTV  BIT_ULL(5)
 #define RISCV_IOMMU_DC_TC_PRPR  BIT_ULL(6)
+#define RISCV_IOMMU_DC_TC_GADE  BIT_ULL(7)
+#define RISCV_IOMMU_DC_TC_SADE  BIT_ULL(8)
 #define RISCV_IOMMU_DC_TC_DPE   BIT_ULL(9)
 #define RISCV_IOMMU_DC_TC_SBE   BIT_ULL(10)
 #define RISCV_IOMMU_DC_TC_SXL   BIT_ULL(11)
diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
index abf6ae7726..11c418b548 100644
--- a/hw/riscv/riscv-iommu.c
+++ b/hw/riscv/riscv-iommu.c
@@ -58,6 +58,8 @@ struct RISCVIOMMUContext {
 uint64_t __rfu:20;  /* reserved */
 uint64_t tc;/* Translation Control */
 uint64_t ta;/* Translation Attributes */
+uint64_t satp;  /* S-Stage address translation and protection 
*/
+uint64_t gatp;  /* G-Stage address translation and protection 
*/
 uint64_t msi_addr_mask; /* MSI filtering - address mask */
 uint64_t msi_addr_pattern;  /* MSI filtering - address pattern */
 uint64_t msiptp;/* MSI redirection page table pointer */
@@ -201,12 +203,45 @@ static bool riscv_iommu_msi_check(RISCVIOMMUState *s, 
RISCVIOMMUContext *ctx,
 return true;
 }
 
-/* RISCV IOMMU Address Translation Lookup - Page Table Walk */
+/*
+ * RISCV IOMMU Address Translation Lookup - Page Table Walk
+ *
+ * Note: Code is based on get_physical_address() from target/riscv/cpu_helper.c
+ * Both implementation can be merged into single helper function in future.
+ * Keeping them separate for now, as error reporting and flow specifics are
+ * sufficiently different for separate implementation.
+ *
+ * @s: IOMMU Device State
+ * @ctx  : Translation context for device id and process address space id.
+ * @iotlb: translation data: physical address and access mode.
+ * @return   : success or fault cause code.
+ */
 static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, RISCVIOMMUContext *ctx,
 IOMMUTLBEntry *iotlb)
 {
+dma_addr_t addr, base;
+uint64_t satp, gatp, pte;
+bool en_s, en_g;
+struct {
+unsigned char step;
+unsigned char levels;
+unsigned char ptidxbits;
+unsigned char ptesize;
+} sc[2];
+/* Translation stage phase */
+enum {
+S_STAGE = 0,
+G_STAGE = 1,
+} pass;
+
+satp = get_field(ctx->satp, RISCV_IOMMU_ATP_MODE_FIELD);
+gatp = get_field(ctx->gatp, RISCV_IOMMU_ATP_MODE_FIELD);
+
+en_s = satp != RISCV_IOMMU_DC_FSC_MODE_BARE;
+en_g = gatp != RISCV_IOMMU_DC_IOHGATP_MODE_BARE;
+
 /* Early check for MSI address match when IOVA == GPA */
-if (iotlb->perm & IOMMU_WO &&
+if ((iotlb->perm & IOMMU_WO) &&
 riscv_iommu_msi_check(s, ctx, iotlb->iova)) {
 iotlb->target_as = >trap_as;
 iotlb->translated_addr = iotlb->iova;
@@ -215,11 +250,196 @@ static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, 
RISCVIOMMUContext *ctx,
 }
 
 /* Exit early for pass-through

[PATCH v3 13/13] qtest/riscv-iommu-test: add init queues test

2024-05-23 Thread Daniel Henrique Barboza
Add an additional test to further exercise the IOMMU where we attempt to
initialize the command, fault and page-request queues.

These steps are taken from chapter 6.2 of the RISC-V IOMMU spec,
"Guidelines for initialization". It emulates what we expect from the
software/OS when initializing the IOMMU.

Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Frank Chang 
---
 tests/qtest/libqos/riscv-iommu.h |  29 +++
 tests/qtest/riscv-iommu-test.c   | 141 +++
 2 files changed, 170 insertions(+)

diff --git a/tests/qtest/libqos/riscv-iommu.h b/tests/qtest/libqos/riscv-iommu.h
index d123efb41f..c62ddedbac 100644
--- a/tests/qtest/libqos/riscv-iommu.h
+++ b/tests/qtest/libqos/riscv-iommu.h
@@ -62,6 +62,35 @@
 
 #define RISCV_IOMMU_REG_IPSR0x0054
 
+#define RISCV_IOMMU_REG_IVEC0x02F8
+#define RISCV_IOMMU_REG_IVEC_CIVGENMASK_ULL(3, 0)
+#define RISCV_IOMMU_REG_IVEC_FIVGENMASK_ULL(7, 4)
+#define RISCV_IOMMU_REG_IVEC_PIVGENMASK_ULL(15, 12)
+
+#define RISCV_IOMMU_REG_CQB 0x0018
+#define RISCV_IOMMU_CQB_PPN_START   10
+#define RISCV_IOMMU_CQB_PPN_LEN 44
+#define RISCV_IOMMU_CQB_LOG2SZ_START0
+#define RISCV_IOMMU_CQB_LOG2SZ_LEN  5
+
+#define RISCV_IOMMU_REG_CQT 0x0024
+
+#define RISCV_IOMMU_REG_FQB 0x0028
+#define RISCV_IOMMU_FQB_PPN_START   10
+#define RISCV_IOMMU_FQB_PPN_LEN 44
+#define RISCV_IOMMU_FQB_LOG2SZ_START0
+#define RISCV_IOMMU_FQB_LOG2SZ_LEN  5
+
+#define RISCV_IOMMU_REG_FQT 0x0034
+
+#define RISCV_IOMMU_REG_PQB 0x0038
+#define RISCV_IOMMU_PQB_PPN_START   10
+#define RISCV_IOMMU_PQB_PPN_LEN 44
+#define RISCV_IOMMU_PQB_LOG2SZ_START0
+#define RISCV_IOMMU_PQB_LOG2SZ_LEN  5
+
+#define RISCV_IOMMU_REG_PQT 0x0044
+
 typedef struct QRISCVIOMMU {
 QOSGraphObject obj;
 QPCIDevice dev;
diff --git a/tests/qtest/riscv-iommu-test.c b/tests/qtest/riscv-iommu-test.c
index 7f0dbd0211..9e2afcb4b9 100644
--- a/tests/qtest/riscv-iommu-test.c
+++ b/tests/qtest/riscv-iommu-test.c
@@ -33,6 +33,20 @@ static uint64_t riscv_iommu_read_reg64(QRISCVIOMMU *r_iommu, 
int reg_offset)
 return reg;
 }
 
+static void riscv_iommu_write_reg32(QRISCVIOMMU *r_iommu, int reg_offset,
+uint32_t val)
+{
+qpci_memwrite(_iommu->dev, r_iommu->reg_bar, reg_offset,
+  , sizeof(val));
+}
+
+static void riscv_iommu_write_reg64(QRISCVIOMMU *r_iommu, int reg_offset,
+uint64_t val)
+{
+qpci_memwrite(_iommu->dev, r_iommu->reg_bar, reg_offset,
+  , sizeof(val));
+}
+
 static void test_pci_config(void *obj, void *data, QGuestAllocator *t_alloc)
 {
 QRISCVIOMMU *r_iommu = obj;
@@ -84,10 +98,137 @@ static void test_reg_reset(void *obj, void *data, 
QGuestAllocator *t_alloc)
 g_assert_cmpuint(reg, ==, 0);
 }
 
+/*
+ * Common timeout-based poll for CQCSR, FQCSR and PQCSR. All
+ * their ON bits are mapped as RISCV_IOMMU_QUEUE_ACTIVE (16),
+ */
+static void qtest_wait_for_queue_active(QRISCVIOMMU *r_iommu,
+uint32_t queue_csr)
+{
+QTestState *qts = global_qtest;
+guint64 timeout_us = 2 * 1000 * 1000;
+gint64 start_time = g_get_monotonic_time();
+uint32_t reg;
+
+for (;;) {
+qtest_clock_step(qts, 100);
+
+reg = riscv_iommu_read_reg32(r_iommu, queue_csr);
+if (reg & RISCV_IOMMU_QUEUE_ACTIVE) {
+break;
+}
+g_assert(g_get_monotonic_time() - start_time <= timeout_us);
+}
+}
+
+/*
+ * Goes through the queue activation procedures of chapter 6.2,
+ * "Guidelines for initialization", of the RISCV-IOMMU spec.
+ */
+static void test_iommu_init_queues(void *obj, void *data,
+   QGuestAllocator *t_alloc)
+{
+QRISCVIOMMU *r_iommu = obj;
+uint64_t reg64, q_addr;
+uint32_t reg;
+int k;
+
+reg64 = riscv_iommu_read_reg64(r_iommu, RISCV_IOMMU_REG_CAP);
+g_assert_cmpuint(reg64 & RISCV_IOMMU_CAP_VERSION, ==, 0x10);
+
+/*
+ * Program the command queue. Write 0xF to civ, assert that
+ * we have 4 writable bits (k = 4). The amount of entries N in the
+ * command queue is 2^4 = 16. We need to alloc a N*16 bytes
+ * buffer and use it to set cqb.
+ */
+riscv_iommu_write_reg32(r_iommu, RISCV_IOMMU_REG_IVEC,
+0x & RISCV_IOMMU_REG_IVEC_CIV);
+reg = riscv_iommu_read_reg32(r_iommu, RISCV_IOMMU_REG_IVEC);
+g_assert_cmpuint(reg & RISCV_IOMMU_REG_IVEC_CIV, ==, 0xF);
+
+q_addr = guest_alloc(t_alloc, 16 * 16);
+reg64 = 0;
+k = 4;
+deposit64(reg64, RISCV_IOMMU_CQB_PPN_START,
+  RISCV_IOMMU_CQB_PPN_LEN, q_addr);
+deposit64(reg64, RISCV_IOMMU_CQB_LOG2SZ_START,
+  RISCV_IOMMU_CQB_LOG2SZ_LEN, k - 1);
+riscv_iommu_write_reg64(r_io

[PATCH v3 07/13] test/qtest: add riscv-iommu-pci tests

2024-05-23 Thread Daniel Henrique Barboza
To test the RISC-V IOMMU emulation we'll use its PCI representation.
Create a new 'riscv-iommu-pci' libqos device that will be present with
CONFIG_RISCV_IOMMU.  This config is only available for RISC-V, so this
device will only be consumed by the RISC-V libqos machine.

Start with basic tests: a PCI sanity check and a reset state register
test. The reset test was taken from the RISC-V IOMMU spec chapter 5.2,
"Reset behavior".

More tests will be added later.

Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Frank Chang 
---
 tests/qtest/libqos/meson.build   |  4 ++
 tests/qtest/libqos/riscv-iommu.c | 76 ++
 tests/qtest/libqos/riscv-iommu.h | 71 
 tests/qtest/meson.build  |  1 +
 tests/qtest/riscv-iommu-test.c   | 93 
 5 files changed, 245 insertions(+)
 create mode 100644 tests/qtest/libqos/riscv-iommu.c
 create mode 100644 tests/qtest/libqos/riscv-iommu.h
 create mode 100644 tests/qtest/riscv-iommu-test.c

diff --git a/tests/qtest/libqos/meson.build b/tests/qtest/libqos/meson.build
index 3aed6efcb8..07fe20eacb 100644
--- a/tests/qtest/libqos/meson.build
+++ b/tests/qtest/libqos/meson.build
@@ -67,6 +67,10 @@ if have_virtfs
   libqos_srcs += files('virtio-9p.c', 'virtio-9p-client.c')
 endif
 
+if config_all_devices.has_key('CONFIG_RISCV_IOMMU')
+  libqos_srcs += files('riscv-iommu.c')
+endif
+
 libqos = static_library('qos', libqos_srcs + genh,
 name_suffix: 'fa',
 build_by_default: false)
diff --git a/tests/qtest/libqos/riscv-iommu.c b/tests/qtest/libqos/riscv-iommu.c
new file mode 100644
index 00..01e3b31c0b
--- /dev/null
+++ b/tests/qtest/libqos/riscv-iommu.c
@@ -0,0 +1,76 @@
+/*
+ * libqos driver riscv-iommu-pci framework
+ *
+ * Copyright (c) 2024 Ventana Micro Systems Inc.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at your
+ * option) any later version.  See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "../libqtest.h"
+#include "qemu/module.h"
+#include "qgraph.h"
+#include "pci.h"
+#include "riscv-iommu.h"
+
+static void *riscv_iommu_pci_get_driver(void *obj, const char *interface)
+{
+QRISCVIOMMU *r_iommu_pci = obj;
+
+if (!g_strcmp0(interface, "pci-device")) {
+return _iommu_pci->dev;
+}
+
+fprintf(stderr, "%s not present in riscv_iommu_pci\n", interface);
+g_assert_not_reached();
+}
+
+static void riscv_iommu_pci_start_hw(QOSGraphObject *obj)
+{
+QRISCVIOMMU *pci = (QRISCVIOMMU *)obj;
+qpci_device_enable(>dev);
+}
+
+static void riscv_iommu_pci_destructor(QOSGraphObject *obj)
+{
+QRISCVIOMMU *pci = (QRISCVIOMMU *)obj;
+qpci_iounmap(>dev, pci->reg_bar);
+}
+
+static void *riscv_iommu_pci_create(void *pci_bus, QGuestAllocator *alloc,
+void *addr)
+{
+QRISCVIOMMU *r_iommu_pci = g_new0(QRISCVIOMMU, 1);
+QPCIBus *bus = pci_bus;
+
+qpci_device_init(_iommu_pci->dev, bus, addr);
+r_iommu_pci->reg_bar = qpci_iomap(_iommu_pci->dev, 0, NULL);
+
+r_iommu_pci->obj.get_driver = riscv_iommu_pci_get_driver;
+r_iommu_pci->obj.start_hw = riscv_iommu_pci_start_hw;
+r_iommu_pci->obj.destructor = riscv_iommu_pci_destructor;
+return _iommu_pci->obj;
+}
+
+static void riscv_iommu_pci_register_nodes(void)
+{
+QPCIAddress addr = {
+.vendor_id = RISCV_IOMMU_PCI_VENDOR_ID,
+.device_id = RISCV_IOMMU_PCI_DEVICE_ID,
+.devfn = QPCI_DEVFN(1, 0),
+};
+
+QOSGraphEdgeOptions opts = {
+.extra_device_opts = "addr=01.0",
+};
+
+add_qpci_address(, );
+
+qos_node_create_driver("riscv-iommu-pci", riscv_iommu_pci_create);
+qos_node_produces("riscv-iommu-pci", "pci-device");
+qos_node_consumes("riscv-iommu-pci", "pci-bus", );
+}
+
+libqos_init(riscv_iommu_pci_register_nodes);
diff --git a/tests/qtest/libqos/riscv-iommu.h b/tests/qtest/libqos/riscv-iommu.h
new file mode 100644
index 00..d123efb41f
--- /dev/null
+++ b/tests/qtest/libqos/riscv-iommu.h
@@ -0,0 +1,71 @@
+/*
+ * libqos driver riscv-iommu-pci framework
+ *
+ * Copyright (c) 2024 Ventana Micro Systems Inc.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at your
+ * option) any later version.  See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef TESTS_LIBQOS_RISCV_IOMMU_H
+#define TESTS_LIBQOS_RISCV_IOMMU_H
+
+#include "qgraph.h"
+#include "pci.h"
+#include "qemu/bitops.h"
+
+#ifndef GENMASK_ULL
+#define GENMASK_ULL(h, l) (((~0ULL) >> (63 - (h) + (l))) << (l))
+#endif
+
+/*
+ * RISC-V IOMMU uses PCI_VENDOR_ID_REDHAT 0x1b36 and
+ * PCI_DEVICE_ID_REDHAT_RISCV_IOMMU 0x0014.
+ */
+#define RISCV_IOMMU_PCI_VENDOR_ID   

[PATCH v3 04/13] pci-ids.rst: add Red Hat pci-id for RISC-V IOMMU device

2024-05-23 Thread Daniel Henrique Barboza
The RISC-V IOMMU PCI device we're going to add next is a reference
implementation of the riscv-iommu spec [1], which predicts that the
IOMMU can be implemented as a PCIe device.

However, RISC-V International (RVI), the entity that ratified the
riscv-iommu spec, didn't bother assigning a PCI ID for this IOMMU PCIe
implementation that the spec predicts. This puts us in an uncommon
situation because we want to add the reference IOMMU PCIe implementation
but we don't have a PCI ID for it.

Given that RVI doesn't provide a PCI ID for it we reached out to Red Hat
and Gerd Hoffman, and they were kind enough to give us a PCI ID for the
RISC-V IOMMU PCI reference device.

Thanks Red Hat and Gerd for this RISC-V IOMMU PCIe device ID.

[1] https://github.com/riscv-non-isa/riscv-iommu/releases/tag/v1.0.0

Cc: Gerd Hoffmann 
Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Frank Chang 
---
 docs/specs/pci-ids.rst | 2 ++
 include/hw/pci/pci.h   | 1 +
 2 files changed, 3 insertions(+)

diff --git a/docs/specs/pci-ids.rst b/docs/specs/pci-ids.rst
index c0a3dec2e7..a89a9d0939 100644
--- a/docs/specs/pci-ids.rst
+++ b/docs/specs/pci-ids.rst
@@ -94,6 +94,8 @@ PCI devices (other than virtio):
   PCI ACPI ERST device (``-device acpi-erst``)
 1b36:0013
   PCI UFS device (``-device ufs``)
+1b36:0014
+  PCI RISC-V IOMMU device
 
 All these devices are documented in :doc:`index`.
 
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index eaa3fc99d8..462aed1503 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -115,6 +115,7 @@ extern bool pci_available;
 #define PCI_DEVICE_ID_REDHAT_PVPANIC 0x0011
 #define PCI_DEVICE_ID_REDHAT_ACPI_ERST   0x0012
 #define PCI_DEVICE_ID_REDHAT_UFS 0x0013
+#define PCI_DEVICE_ID_REDHAT_RISCV_IOMMU 0x0014
 #define PCI_DEVICE_ID_REDHAT_QXL 0x0100
 
 #define FMT_PCIBUS  PRIx64
-- 
2.44.0




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

2024-05-23 Thread Daniel Henrique Barboza
or early MSI address match

- patch 10:
  - add ATS steps in riscv_iommu_validate_device_ctx()
  - check for 's->enable_ats' before adding RISCV_IOMMU_DC_TC_EN_ATS in device 
context
  - check for 's->enable_ats' before processing ATS commands in 
riscv_iommu_process_cq_tail()
  - remove ambiguous trace_riscv_iommu_ats() from riscv_iommu_translate()

- patch 11:
  - removed unused bits
  - added RISCV_IOMMU_TR_REQ_CTL_NW and RISCV_IOMMU_TR_RESPONSE_S
bits
  - set IOMMUTLBEntry 'perm' using RISCV_IOMMU_TR_REQ_CTL_NW in 
riscv_iommu_process_dbg()
  - clear RISCV_IOMMU_TR_RESPONSE_S in riscv_iommu_process_dbg(). Added a 
comment talking about the (lack of) superpage support
 
[1] 
https://lore.kernel.org/qemu-riscv/20240307160319.675044-1-dbarb...@ventanamicro.com/
[2] https://github.com/vlsunil/qemu/commits/acpi_rimt_poc_v1/

Andrew Jones (1):
  hw/riscv/riscv-iommu: Add another irq for mrif notifications

Daniel Henrique Barboza (3):
  pci-ids.rst: add Red Hat pci-id for RISC-V IOMMU device
  test/qtest: add riscv-iommu-pci tests
  qtest/riscv-iommu-test: add init queues test

Tomasz Jeznach (9):
  exec/memtxattr: add process identifier to the transaction attributes
  hw/riscv: add riscv-iommu-bits.h
  hw/riscv: add RISC-V IOMMU base emulation
  hw/riscv: add riscv-iommu-pci reference device
  hw/riscv/virt.c: support for RISC-V IOMMU PCIDevice hotplug
  hw/riscv/riscv-iommu: add Address Translation Cache (IOATC)
  hw/riscv/riscv-iommu: add s-stage and g-stage support
  hw/riscv/riscv-iommu: add ATS support
  hw/riscv/riscv-iommu: add DBG support

 docs/specs/pci-ids.rst   |2 +
 hw/riscv/Kconfig |4 +
 hw/riscv/meson.build |1 +
 hw/riscv/riscv-iommu-bits.h  |  416 ++
 hw/riscv/riscv-iommu-pci.c   |  177 +++
 hw/riscv/riscv-iommu.c   | 2283 ++
 hw/riscv/riscv-iommu.h   |  146 ++
 hw/riscv/trace-events|   15 +
 hw/riscv/trace.h |1 +
 hw/riscv/virt.c  |   33 +-
 include/exec/memattrs.h  |5 +
 include/hw/pci/pci.h |1 +
 include/hw/riscv/iommu.h |   36 +
 meson.build  |1 +
 tests/qtest/libqos/meson.build   |4 +
 tests/qtest/libqos/riscv-iommu.c |   76 +
 tests/qtest/libqos/riscv-iommu.h |  100 ++
 tests/qtest/meson.build  |1 +
 tests/qtest/riscv-iommu-test.c   |  234 +++
 19 files changed, 3535 insertions(+), 1 deletion(-)
 create mode 100644 hw/riscv/riscv-iommu-bits.h
 create mode 100644 hw/riscv/riscv-iommu-pci.c
 create mode 100644 hw/riscv/riscv-iommu.c
 create mode 100644 hw/riscv/riscv-iommu.h
 create mode 100644 hw/riscv/trace-events
 create mode 100644 hw/riscv/trace.h
 create mode 100644 include/hw/riscv/iommu.h
 create mode 100644 tests/qtest/libqos/riscv-iommu.c
 create mode 100644 tests/qtest/libqos/riscv-iommu.h
 create mode 100644 tests/qtest/riscv-iommu-test.c

-- 
2.44.0




Re: [PATCH v2 2/2] target/riscv: Move Guest irqs out of the core local irqs range.

2024-05-22 Thread Daniel Henrique Barboza




On 5/20/24 09:51, Rajnesh Kanwal wrote:

Qemu maps IRQs 0:15 for core interrupts and 16 onward for
guest interrupts which are later translated to hgiep in
`riscv_cpu_set_irq()` function.

With virtual IRQ support added, software now can fully
use the whole local interrupt range without any actual
hardware attached.

This change moves the guest interrupt range after the
core local interrupt range to avoid clash.

Fixes: 1697837ed9 ("target/riscv: Add M-mode virtual interrupt and IRQ filtering 
support.")
Fixes: 40336d5b1d ("target/riscv: Add HS-mode virtual interrupt and IRQ filtering 
support.")

Signed-off-by: Rajnesh Kanwal 
---


Reviewed-by: Daniel Henrique Barboza 


  target/riscv/cpu_bits.h | 3 ++-
  target/riscv/csr.c  | 9 -
  2 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 74318a925c..a470fda9be 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -695,7 +695,8 @@ typedef enum RISCVException {
  #define IRQ_M_EXT  11
  #define IRQ_S_GEXT 12
  #define IRQ_PMU_OVF13
-#define IRQ_LOCAL_MAX  16
+#define IRQ_LOCAL_MAX  64
+/* -1 is due to bit zero of hgeip and hgeie being ROZ. */
  #define IRQ_LOCAL_GUEST_MAX(TARGET_LONG_BITS - 1)
  
  /* mip masks */

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 152796ebc0..464e0e57a3 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1148,7 +1148,14 @@ static RISCVException write_stimecmph(CPURISCVState 
*env, int csrno,
  
  #define VSTOPI_NUM_SRCS 5
  
-#define LOCAL_INTERRUPTS (~0x1FFF)

+/*
+ * All core local interrupts except the fixed ones 0:12. This macro is for
+ * virtual interrupts logic so please don't change this to avoid messing up
+ * the whole support, For reference see AIA spec: `5.3 Interrupt filtering and
+ * virtual interrupts for supervisor level` and `6.3.2 Virtual interrupts for
+ * VS level`.
+ */
+#define LOCAL_INTERRUPTS   (~0x1FFFULL)
  
  static const uint64_t delegable_ints =

  S_MODE_INTERRUPTS | VS_MODE_INTERRUPTS | MIP_LCOFIP;




Re: [PATCH v2 03/15] hw/riscv: add RISC-V IOMMU base emulation

2024-05-21 Thread Daniel Henrique Barboza




On 5/21/24 07:52, Frank Chang wrote:

Hi Daniel,

On Tue, May 21, 2024 at 12:17 AM Daniel Henrique Barboza mailto:dbarb...@ventanamicro.com>> wrote:

Hi Frank,

On 5/16/24 04:13, Frank Chang wrote:
 > On Mon, May 13, 2024 at 8:37 PM Daniel Henrique Barboza mailto:dbarb...@ventanamicro.com> <mailto:dbarb...@ventanamicro.com 
<mailto:dbarb...@ventanamicro.com>>> wrote:
 >
 >     Hi Frank,
 >
 >
 >     On 5/8/24 08:15, Daniel Henrique Barboza wrote:
 >      > Hi Frank,
 >      >
 >      > I'll reply with that I've done so far. Still missing some stuff:
 >      >
 >      > On 5/2/24 08:37, Frank Chang wrote:
 >      >> Hi Daniel,
 >      >>
 >      >> Daniel Henrique Barboza mailto:dbarb...@ventanamicro.com> <mailto:dbarb...@ventanamicro.com 
<mailto:dbarb...@ventanamicro.com>>> 於 2024年3月8日 週五 上午12:04寫道:
 >      >>>
 >      >>> From: Tomasz Jeznach mailto:tjezn...@rivosinc.com> 
<mailto:tjezn...@rivosinc.com <mailto:tjezn...@rivosinc.com>>>
 >      >>>
 >      >>> The RISC-V IOMMU specification is now ratified as-per the RISC-V
 >      >>> international process. The latest frozen specifcation can be 
found
 >      >>> at:
 >      >>>
 >      >>> 
https://github.com/riscv-non-isa/riscv-iommu/releases/download/v1.0/riscv-iommu.pdf 
<https://github.com/riscv-non-isa/riscv-iommu/releases/download/v1.0/riscv-iommu.pdf> 
<https://github.com/riscv-non-isa/riscv-iommu/releases/download/v1.0/riscv-iommu.pdf 
<https://github.com/riscv-non-isa/riscv-iommu/releases/download/v1.0/riscv-iommu.pdf>>
 >      >>>
 >      >>> Add the foundation of the device emulation for RISC-V IOMMU, 
which
 >      >>> includes an IOMMU that has no capabilities but MSI interrupt 
support and
 >      >>> fault queue interfaces. We'll add add more features 
incrementally in the
 >      >>> next patches.
 >      >>>
 >      >>> Co-developed-by: Sebastien Boeuf mailto:s...@rivosinc.com> 
<mailto:s...@rivosinc.com <mailto:s...@rivosinc.com>>>
 >      >>> Signed-off-by: Sebastien Boeuf mailto:s...@rivosinc.com> 
<mailto:s...@rivosinc.com <mailto:s...@rivosinc.com>>>
 >      >>> Signed-off-by: Tomasz Jeznach mailto:tjezn...@rivosinc.com> <mailto:tjezn...@rivosinc.com <mailto:tjezn...@rivosinc.com>>>
 >      >>> Signed-off-by: Daniel Henrique Barboza mailto:dbarb...@ventanamicro.com> <mailto:dbarb...@ventanamicro.com 
<mailto:dbarb...@ventanamicro.com>>>
 >      >>> ---
 >      >>>   hw/riscv/Kconfig |    4 +
 >
 >     (...)
 >
 >      >>> +
 >      >>> +    s->iommus.le_next = NULL;
 >      >>> +    s->iommus.le_prev = NULL;
 >      >>> +    QLIST_INIT(>spaces);
 >      >>> +    qemu_cond_init(>core_cond);
 >      >>> +    qemu_mutex_init(>core_lock);
 >      >>> +    qemu_spin_init(>regs_lock);
 >      >>> +    qemu_thread_create(>core_proc, "riscv-iommu-core",
 >      >>> +    riscv_iommu_core_proc, s, QEMU_THREAD_JOINABLE);
 >      >>
 >      >> In our experience, using QEMU thread increases the latency of 
command
 >      >> queue processing,
 >      >> which leads to the potential IOMMU fence timeout in the Linux 
driver
 >      >> when using IOMMU with KVM,
 >      >> e.g. booting the guest Linux.
 >      >>
 >      >> Is it possible to remove the thread from the IOMMU just like 
ARM, AMD,
 >      >> and Intel IOMMU models?
 >      >
 >      > Interesting. We've been using this emulation internally in 
Ventana, with
 >      > KVM and VFIO, and didn't experience this issue. Drew is on CC and 
can talk
 >      > more about it.
 >      >
 >      > That said, I don't mind this change, assuming it's feasible to 
make it for this
 >      > first version.  I'll need to check it how other IOMMUs are doing 
it.
 >
 >
 >     I removed the threading and it seems to be working fine without it. 
I'll commit this
 >     change for v3.
 >
 >      >
 >      >
 >      >
 >      >>
 >      >>> +}
 >      >>> +
 >      >
 >      > (...)

Re: [PATCH] hw/riscv/virt: Add hotplugging and virtio-md-pci support

2024-05-20 Thread Daniel Henrique Barboza




On 5/20/24 15:51, Björn Töpel wrote:

Daniel/David,

Daniel Henrique Barboza  writes:


On 5/18/24 16:50, David Hildenbrand wrote:


Hi,



diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 4fdb66052587..16c2bdbfe6b6 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -53,6 +53,8 @@
    #include "hw/pci-host/gpex.h"
    #include "hw/display/ramfb.h"
    #include "hw/acpi/aml-build.h"
+#include "hw/mem/memory-device.h"
+#include "hw/virtio/virtio-mem-pci.h"
    #include "qapi/qapi-visit-common.h"
    #include "hw/virtio/virtio-iommu.h"
@@ -1407,6 +1409,7 @@ static void virt_machine_init(MachineState *machine)
    DeviceState *mmio_irqchip, *virtio_irqchip, *pcie_irqchip;
    int i, base_hartid, hart_count;
    int socket_count = riscv_socket_count(machine);
+    hwaddr device_memory_base, device_memory_size;
    /* Check socket count limit */
    if (VIRT_SOCKETS_MAX < socket_count) {
@@ -1553,6 +1556,25 @@ static void virt_machine_init(MachineState *machine)
    memory_region_add_subregion(system_memory, memmap[VIRT_MROM].base,
    mask_rom);
+    device_memory_base = ROUND_UP(s->memmap[VIRT_DRAM].base + 
machine->ram_size,
+  GiB);
+    device_memory_size = machine->maxram_size - machine->ram_size;
+
+    if (riscv_is_32bit(>soc[0])) {
+    hwaddr memtop = device_memory_base + ROUND_UP(device_memory_size, GiB);
+
+    if (memtop > UINT32_MAX) {
+    error_report("Memory exceeds 32-bit limit by %lu bytes",
+ memtop - UINT32_MAX);
+    exit(EXIT_FAILURE);
+    }
+    }
+
+    if (device_memory_size > 0) {
+    machine_memory_devices_init(machine, device_memory_base,
+    device_memory_size);
+    }
+


I think we need a design discussion before proceeding here. You're allocating 
all
available memory as a memory device area, but in theory we might also support
pc-dimm hotplugs (which would be the equivalent of adding physical RAM dimms to
the board.) in the future too. If you're not familiar with this feature you can
check it out the docs in [1].


Note that DIMMs are memory devices as well. You can plug into the memory device 
area both, ACPI-based memory devices (DIMM, NVDIMM) or virtio-based memory 
devices (virtio-mem, virtio-pmem).



As an example, the 'virt' ARM board (hw/arm/virt.c) reserves a space for this
type of hotplug by checking how much 'ram_slots' we're allocating for it:

device_memory_size = ms->maxram_size - ms->ram_size + ms->ram_slots * GiB;



Note that we increased the region size to be able to fit most requests even if 
alignment of memory devices is weird. See below.

In sane setups, this is usually not required (adding a single additional GB for 
some flexiility might be good enough).


Other boards do the same with ms->ram_slots. We should consider doing it as 
well,
now, even if we're not up to the point of supporting pc-dimm hotplug, to avoid
having to change the memory layout later in the road and breaking existing
setups.

If we want to copy the ARM board, ram_slots is capped to ACPI_MAX_RAM_SLOTS 
(256).
Each RAM slot is considered to be a 1GiB dimm, i.e. we would reserve 256GiB for
them.


This only reserves some *additional* space to fixup weird alignment of memory 
devices. *not* the actual space for these devices.

We don't consider each DIMM to be 1 GiB in size, but add an additional 1 GiB in 
case we have to align DIMMs in physical address space.

I *think* this dates back to old x86 handling where we aligned the address of 
each DIMM to be at a 1 GiB boundary. So if you would have plugged two 128 MiB 
DIMMs, you'd have required more than 256 MiB of space in the area after 
aligning inside the memory device area.



Thanks for the explanation. I missed the part where the ram_slots were being
used just to solve potential alignment issues and pc-dimms could occupy the same
space being allocated via machine_memory_devices_init().

This patch isn't far off then. If we take care to avoid plugging unaligned 
memory
we might not even need this spare area.


I'm a bit lost here, so please bare with me. We don't require the 1 GiB
alignment on RV AFAIU. I'm having a hard time figuring out what missing
in my patch.


Forget about the 1 GiB size. This is something that we won't need to deal with
because we don't align in 1 Gib.

Let's say for example that we want to support pc-dimm hotplug of 256 slots like 
the
'virt' ARM machine does. Let's also say that we will allow users to hotplug any
DIMM size they want, taking care of any alignment issues by ourselves.

In hw/riscv/boot.c I see that our alignment sizes are 4Mb for 32 bits and 2Mb 
for
64 bits. Forget 32 bits a bit and let's say that our alignment is 2Mb.

So, in a worst case scenario, an user could hotplug 256 slots, all of

Re: [PATCH] hw/riscv/virt: Add hotplugging and virtio-md-pci support

2024-05-20 Thread Daniel Henrique Barboza




On 5/20/24 15:33, Björn Töpel wrote:

Daniel,

Thanks for taking a look!

Daniel Henrique Barboza  writes:


Hi Björj,

On 5/14/24 08:06, Björn Töpel wrote:

From: Björn Töpel 

Virtio-based memory devices allows for dynamic resizing of virtual
machine memory, and requires proper hotplugging (add/remove) support
to work.

Enable virtio-md-pci with the corresponding missing hotplugging
callbacks for the RISC-V "virt" machine.

Signed-off-by: Björn Töpel 
---
This is basic support for MHP that works with DT. There some minor
ACPI SRAT plumbing in there as well. Ideally we'd like proper ACPI MHP
support as well. I have a branch [1], where I've applied this patch,
plus ACPI GED/PC-DIMM MHP support on top of Sunil's QEMU branch
(contains some ACPI DSDT additions) [2], for the curious/brave ones.
However, the ACPI MHP support this is not testable on upstream Linux
yet (ACPI AIA support, and ACPI NUMA SRAT series are ongoing).

I'll follow-up with proper ACPI GED/PC-DIMM MHP patches, once the
dependencies land (Linux kernel and QEMU).

I'll post the Linux MHP/virtio-mem v2 patches later this week!


Cheers,
Björn

[1] https://github.com/bjoto/qemu/commits/virtio-mem-pc-dimm-mhp-acpi/
[2] 
https://lore.kernel.org/linux-riscv/20240501121742.1215792-1-suni...@ventanamicro.com/
---
   hw/riscv/Kconfig   |  2 ++
   hw/riscv/virt-acpi-build.c |  7 +
   hw/riscv/virt.c| 64 +-
   hw/virtio/virtio-mem.c |  2 +-
   4 files changed, 73 insertions(+), 2 deletions(-)

diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
index a2030e3a6ff0..08f82dbb681a 100644
--- a/hw/riscv/Kconfig
+++ b/hw/riscv/Kconfig
@@ -56,6 +56,8 @@ config RISCV_VIRT
   select PLATFORM_BUS
   select ACPI
   select ACPI_PCI
+select VIRTIO_MEM_SUPPORTED
+select VIRTIO_PMEM_SUPPORTED
   
   config SHAKTI_C

   bool
diff --git a/hw/riscv/virt-acpi-build.c b/hw/riscv/virt-acpi-build.c
index 0925528160f8..6dc3baa9ec86 100644
--- a/hw/riscv/virt-acpi-build.c
+++ b/hw/riscv/virt-acpi-build.c
@@ -610,6 +610,13 @@ build_srat(GArray *table_data, BIOSLinker *linker, 
RISCVVirtState *vms)
   }
   }
   
+if (ms->device_memory) {

+build_srat_memory(table_data, ms->device_memory->base,
+  memory_region_size(>device_memory->mr),
+  ms->numa_state->num_nodes - 1,
+  MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
+}
+
   acpi_table_end(linker, );


When the time comes I believe we'll want this chunk in a separated ACPI patch.


Hmm, I first thought about adding this to the ACPI MHP series, but then
realized that virtio-mem relies on SRAT for ACPI boots (again -- RISC-V
Linux does not support that upstream yet...).

Do you mean that you'd prefer this chunk in a separate patch?


TBH I wouldn't mind keeping this ACPI chunk here but I reckon that the ACPI
subsystem review is usually done in separate, with a different set of people
reviewing it and so on.

We might as well keep it here for now. If more ACPI changes ended up being done
(e.g. ACPI unit test changes) then doing a separated ACPI patch makes more 
sense.


Thanks,

Daniel





Björn




Re: [RFC PATCH 0/1] pci: allocate a PCI ID for RISC-V IOMMU

2024-05-20 Thread Daniel Henrique Barboza




On 5/10/24 07:47, Frank Chang wrote:

Hi Daniel,

Daniel Henrique Barboza  於 2024年5月8日 週三 下午8:42寫道:




On 5/7/24 12:44, Peter Maydell wrote:

On Fri, 3 May 2024 at 13:43, Daniel Henrique Barboza
 wrote:


Hi,

In this RFC I want to check with Gerd and others if it's ok to add a PCI
id for the RISC-V IOMMU device. It's currently under review in [1]. The
idea is to fold this patch into the RISC-V IOMMU series if we're all ok
with this change.


My question here would be "why is this risc-v specific?" (and more
generally "what is this for?" -- the cover letter and patch and
documentation page provide almost no information about what this
device is and why it needs to exist rather than using either
virtio-iommu or else a model of a real hardware IOMMU.)


The RISC-V IOMMU device emulation under review ([1]) is a reference 
implementation of
the riscv-iommu spec [2]. AFAIK it is similar to what we already have with 
aarch64 'smmuv3'
'virt' bus, i.e. an impl of ARM's SMMUv3 that isn't tied to a specific vendor.

The difference here is that the riscv-iommu spec, ratified by RISC-V 
International (RVI),
predicts that the device could be implemented as a PCIe device. But RVI didn't 
bother
assigning a PCI ID for their reference IOMMU. The existing implementation in 
[1] is using
a Rivos PCI ID that we're treating as a placeholder only. We need an ID that 
reflects that
this is a device that adheres to the riscv-iommu spec, not to an IOMMU of any 
particular
vendor.

Since RVI doesn't provide a PCI ID for it we went to Red Hat, and they were 
kind enough
to give us a PCI ID for the RISC-V IOMMU reference device.


That's great. Thanks to Red Hat.
I'm wondering do we have the plan to document the new PCI ID to the IOMMU spec
or somewhere else that's publicly accessible?


It will be documented in QEMU, as you've already seen in this patch. I'm sure
that this info will be cascaded for other databases but I'm not sure how or 
when.
I think Gerd can give us more info about it.

I guess we'll end up using this same generic ID from QEMU in the kernel side 
too.
As of now the kernel IOMMU support is using a Rivos ID ([1], patch 3). Assuming 
that
[1] stays this way (I'm not sure if the kernel driver is a Rivos implementation 
or a
canonical implementation like we're doing here), we'll need to add a generic 
kernel
support that uses the generic ID too.


Thanks,

Daniel

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





Regards,
Frank Chang



I'll do a proper job this time and add all this context in the commit msg. 
Including a
proper shout-out to Gerd and Red Hat.



Thanks,


Daniel


[1] 
https://lore.kernel.org/qemu-riscv/20240307160319.675044-1-dbarb...@ventanamicro.com/
[2] https://github.com/riscv-non-isa/riscv-iommu/releases/tag/v1.0.0



thanks
-- PMM






Re: [PATCH v2 00/15] riscv: QEMU RISC-V IOMMU Support

2024-05-20 Thread Daniel Henrique Barboza




On 5/10/24 08:14, Frank Chang wrote:

Hi Daniel,

Thanks for the upstream work.
Sorry that it took a while for me to review the patchset.

Please let me know if you need any help from us to update the IOMMU model.
We would like to see it merged for QEMU 9.1.0.


Thanks for the help in the reviews!

I'll do some last changes in the riscv-iommu-pci device, and check if we have 
any
DT changes that happened that we need to sync up.

The plan is to send v3 in the next couple of days. Let's see how it goes.


Thanks,


Daniel




Regards,
Frank Chang

Daniel Henrique Barboza  於 2024年3月8日 週五 上午12:04寫道:


Hi,

This is the second version of the work Tomasz sent in July 2023 [1].
I'll be helping Tomasz upstreaming it.

The core emulation code is left unchanged but a few tweaks were made in
v2:

- The most notable difference in this version is that the code was split
   in smaller chunks. Patch 03 is still a 1700 lines patch, which is an
   improvement from the 3800 lines patch from v1, but we can only go so
   far when splitting the core components of the emulation. The reality
   is that the IOMMU emulation is a rather complex piece of software and
   there's not much we can do to alleviate it;

- I'm not contributing the HPM support that was present in v1. It shaved
   off 600 lines of code from the series, which is already large enough
   as is. We'll introduce HPM in later versions or as a follow-up;

- The riscv-iommu-header.h header was also trimmed. I shaved it of 300
   or so from it, all of them from definitions that the emulation isn't
   using it. The header will be eventually be imported from the Linux
   driver (not upstream yet), so for now we can live with a trimmed
   header for the emulation usage alone;

- I added libqos tests for the riscv-iommu-pci device. The idea of these
   tests is to give us more confidence in the emulation code;

- 'edu' device support. The support was retrieved from Tomasz EDU branch
   [2]. This device can then be used to test PCI passthrough to exercise
   the IOMMU.


Patches based on alistair/riscv-to-apply.next.

v1 link: 
https://lore.kernel.org/qemu-riscv/cover.1689819031.git.tjezn...@rivosinc.com/

[1] 
https://lore.kernel.org/qemu-riscv/cover.1689819031.git.tjezn...@rivosinc.com/
[2] https://github.com/tjeznach/qemu.git, branch 'riscv_iommu_edu_impl'

Andrew Jones (1):
   hw/riscv/riscv-iommu: Add another irq for mrif notifications

Daniel Henrique Barboza (2):
   test/qtest: add riscv-iommu-pci tests
   qtest/riscv-iommu-test: add init queues test

Tomasz Jeznach (12):
   exec/memtxattr: add process identifier to the transaction attributes
   hw/riscv: add riscv-iommu-bits.h
   hw/riscv: add RISC-V IOMMU base emulation
   hw/riscv: add riscv-iommu-pci device
   hw/riscv: add riscv-iommu-sys platform device
   hw/riscv/virt.c: support for RISC-V IOMMU PCIDevice hotplug
   hw/riscv/riscv-iommu: add Address Translation Cache (IOATC)
   hw/riscv/riscv-iommu: add s-stage and g-stage support
   hw/riscv/riscv-iommu: add ATS support
   hw/riscv/riscv-iommu: add DBG support
   hw/misc: EDU: added PASID support
   hw/misc: EDU: add ATS/PRI capability

  hw/misc/edu.c|  297 -
  hw/riscv/Kconfig |4 +
  hw/riscv/meson.build |1 +
  hw/riscv/riscv-iommu-bits.h  |  407 ++
  hw/riscv/riscv-iommu-pci.c   |  173 +++
  hw/riscv/riscv-iommu-sys.c   |   93 ++
  hw/riscv/riscv-iommu.c   | 2085 ++
  hw/riscv/riscv-iommu.h   |  146 +++
  hw/riscv/trace-events|   15 +
  hw/riscv/trace.h |2 +
  hw/riscv/virt.c  |   33 +-
  include/exec/memattrs.h  |5 +
  include/hw/riscv/iommu.h |   40 +
  meson.build  |1 +
  tests/qtest/libqos/meson.build   |4 +
  tests/qtest/libqos/riscv-iommu.c |   79 ++
  tests/qtest/libqos/riscv-iommu.h |   96 ++
  tests/qtest/meson.build  |1 +
  tests/qtest/riscv-iommu-test.c   |  234 
  19 files changed, 3704 insertions(+), 12 deletions(-)
  create mode 100644 hw/riscv/riscv-iommu-bits.h
  create mode 100644 hw/riscv/riscv-iommu-pci.c
  create mode 100644 hw/riscv/riscv-iommu-sys.c
  create mode 100644 hw/riscv/riscv-iommu.c
  create mode 100644 hw/riscv/riscv-iommu.h
  create mode 100644 hw/riscv/trace-events
  create mode 100644 hw/riscv/trace.h
  create mode 100644 include/hw/riscv/iommu.h
  create mode 100644 tests/qtest/libqos/riscv-iommu.c
  create mode 100644 tests/qtest/libqos/riscv-iommu.h
  create mode 100644 tests/qtest/riscv-iommu-test.c

--
2.43.2






Re: [PATCH v2 03/15] hw/riscv: add RISC-V IOMMU base emulation

2024-05-20 Thread Daniel Henrique Barboza

Hi Frank,

On 5/16/24 04:13, Frank Chang wrote:

On Mon, May 13, 2024 at 8:37 PM Daniel Henrique Barboza mailto:dbarb...@ventanamicro.com>> wrote:

Hi Frank,


On 5/8/24 08:15, Daniel Henrique Barboza wrote:
 > Hi Frank,
 >
 > I'll reply with that I've done so far. Still missing some stuff:
 >
 > On 5/2/24 08:37, Frank Chang wrote:
 >> Hi Daniel,
 >>
 >> Daniel Henrique Barboza mailto:dbarb...@ventanamicro.com>> 於 2024年3月8日 週五 上午12:04寫道:
 >>>
 >>> From: Tomasz Jeznach mailto:tjezn...@rivosinc.com>>
 >>>
 >>> The RISC-V IOMMU specification is now ratified as-per the RISC-V
 >>> international process. The latest frozen specifcation can be found
 >>> at:
 >>>
 >>> 
https://github.com/riscv-non-isa/riscv-iommu/releases/download/v1.0/riscv-iommu.pdf 
<https://github.com/riscv-non-isa/riscv-iommu/releases/download/v1.0/riscv-iommu.pdf>
 >>>
 >>> Add the foundation of the device emulation for RISC-V IOMMU, which
 >>> includes an IOMMU that has no capabilities but MSI interrupt support 
and
 >>> fault queue interfaces. We'll add add more features incrementally in 
the
 >>> next patches.
 >>>
 >>> Co-developed-by: Sebastien Boeuf mailto:s...@rivosinc.com>>
 >>> Signed-off-by: Sebastien Boeuf mailto:s...@rivosinc.com>>
 >>> Signed-off-by: Tomasz Jeznach mailto:tjezn...@rivosinc.com>>
 >>> Signed-off-by: Daniel Henrique Barboza mailto:dbarb...@ventanamicro.com>>
 >>> ---
 >>>   hw/riscv/Kconfig |    4 +

(...)

 >>> +
 >>> +    s->iommus.le_next = NULL;
 >>> +    s->iommus.le_prev = NULL;
 >>> +    QLIST_INIT(>spaces);
 >>> +    qemu_cond_init(>core_cond);
 >>> +    qemu_mutex_init(>core_lock);
 >>> +    qemu_spin_init(>regs_lock);
 >>> +    qemu_thread_create(>core_proc, "riscv-iommu-core",
 >>> +    riscv_iommu_core_proc, s, QEMU_THREAD_JOINABLE);
 >>
 >> In our experience, using QEMU thread increases the latency of command
 >> queue processing,
 >> which leads to the potential IOMMU fence timeout in the Linux driver
 >> when using IOMMU with KVM,
 >> e.g. booting the guest Linux.
 >>
 >> Is it possible to remove the thread from the IOMMU just like ARM, AMD,
 >> and Intel IOMMU models?
 >
 > Interesting. We've been using this emulation internally in Ventana, with
 > KVM and VFIO, and didn't experience this issue. Drew is on CC and can 
talk
 > more about it.
 >
 > That said, I don't mind this change, assuming it's feasible to make it 
for this
 > first version.  I'll need to check it how other IOMMUs are doing it.


I removed the threading and it seems to be working fine without it. I'll 
commit this
change for v3.

 >
 >
 >
 >>
 >>> +}
 >>> +
 >
 > (...)
 >
 >>> +
 >>> +static AddressSpace *riscv_iommu_find_as(PCIBus *bus, void *opaque, 
int devfn)
 >>> +{
 >>> +    RISCVIOMMUState *s = (RISCVIOMMUState *) opaque;
 >>> +    PCIDevice *pdev = pci_find_device(bus, pci_bus_num(bus), devfn);
 >>> +    AddressSpace *as = NULL;
 >>> +
 >>> +    if (pdev && pci_is_iommu(pdev)) {
 >>> +    return s->target_as;
 >>> +    }
 >>> +
 >>> +    /* Find first registered IOMMU device */
 >>> +    while (s->iommus.le_prev) {
 >>> +    s = *(s->iommus.le_prev);
 >>> +    }
 >>> +
 >>> +    /* Find first matching IOMMU */
 >>> +    while (s != NULL && as == NULL) {
 >>> +    as = riscv_iommu_space(s, PCI_BUILD_BDF(pci_bus_num(bus), 
devfn));
 >>
 >> For pci_bus_num(),
 >> riscv_iommu_find_as() can be called at the very early stage
 >> where software has no chance to enumerate the bus numbers.

I investigated and this doesn't seem to be a problem. This function is 
called at the
last step of the realize() steps of both riscv_iommu_pci_realize() and
riscv_iommu_sys_realize(), and by that time the pci_bus_num() is already 
assigned.
Other iommus use pci_bus_num() into their own get_address_space() callbacks 
like
this too.


Hi Daniel,

IIUC, pci_bus_num() by default is assigned to pcibus_num():

static int pcibus_num(PCIBus *bus)
{

Re: [PATCH] hw/riscv/virt: Add hotplugging and virtio-md-pci support

2024-05-19 Thread Daniel Henrique Barboza



On 5/18/24 16:50, David Hildenbrand wrote:


Hi,



diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 4fdb66052587..16c2bdbfe6b6 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -53,6 +53,8 @@
   #include "hw/pci-host/gpex.h"
   #include "hw/display/ramfb.h"
   #include "hw/acpi/aml-build.h"
+#include "hw/mem/memory-device.h"
+#include "hw/virtio/virtio-mem-pci.h"
   #include "qapi/qapi-visit-common.h"
   #include "hw/virtio/virtio-iommu.h"
@@ -1407,6 +1409,7 @@ static void virt_machine_init(MachineState *machine)
   DeviceState *mmio_irqchip, *virtio_irqchip, *pcie_irqchip;
   int i, base_hartid, hart_count;
   int socket_count = riscv_socket_count(machine);
+    hwaddr device_memory_base, device_memory_size;
   /* Check socket count limit */
   if (VIRT_SOCKETS_MAX < socket_count) {
@@ -1553,6 +1556,25 @@ static void virt_machine_init(MachineState *machine)
   memory_region_add_subregion(system_memory, memmap[VIRT_MROM].base,
   mask_rom);
+    device_memory_base = ROUND_UP(s->memmap[VIRT_DRAM].base + 
machine->ram_size,
+  GiB);
+    device_memory_size = machine->maxram_size - machine->ram_size;
+
+    if (riscv_is_32bit(>soc[0])) {
+    hwaddr memtop = device_memory_base + ROUND_UP(device_memory_size, GiB);
+
+    if (memtop > UINT32_MAX) {
+    error_report("Memory exceeds 32-bit limit by %lu bytes",
+ memtop - UINT32_MAX);
+    exit(EXIT_FAILURE);
+    }
+    }
+
+    if (device_memory_size > 0) {
+    machine_memory_devices_init(machine, device_memory_base,
+    device_memory_size);
+    }
+


I think we need a design discussion before proceeding here. You're allocating 
all
available memory as a memory device area, but in theory we might also support
pc-dimm hotplugs (which would be the equivalent of adding physical RAM dimms to
the board.) in the future too. If you're not familiar with this feature you can
check it out the docs in [1].


Note that DIMMs are memory devices as well. You can plug into the memory device 
area both, ACPI-based memory devices (DIMM, NVDIMM) or virtio-based memory 
devices (virtio-mem, virtio-pmem).



As an example, the 'virt' ARM board (hw/arm/virt.c) reserves a space for this
type of hotplug by checking how much 'ram_slots' we're allocating for it:

device_memory_size = ms->maxram_size - ms->ram_size + ms->ram_slots * GiB;



Note that we increased the region size to be able to fit most requests even if 
alignment of memory devices is weird. See below.

In sane setups, this is usually not required (adding a single additional GB for 
some flexiility might be good enough).


Other boards do the same with ms->ram_slots. We should consider doing it as 
well,
now, even if we're not up to the point of supporting pc-dimm hotplug, to avoid
having to change the memory layout later in the road and breaking existing
setups.

If we want to copy the ARM board, ram_slots is capped to ACPI_MAX_RAM_SLOTS 
(256).
Each RAM slot is considered to be a 1GiB dimm, i.e. we would reserve 256GiB for
them.


This only reserves some *additional* space to fixup weird alignment of memory 
devices. *not* the actual space for these devices.

We don't consider each DIMM to be 1 GiB in size, but add an additional 1 GiB in 
case we have to align DIMMs in physical address space.

I *think* this dates back to old x86 handling where we aligned the address of 
each DIMM to be at a 1 GiB boundary. So if you would have plugged two 128 MiB 
DIMMs, you'd have required more than 256 MiB of space in the area after 
aligning inside the memory device area.



Thanks for the explanation. I missed the part where the ram_slots were being
used just to solve potential alignment issues and pc-dimms could occupy the same
space being allocated via machine_memory_devices_init().

This patch isn't far off then. If we take care to avoid plugging unaligned 
memory
we might not even need this spare area.



Note: I do not have the visibility of discussions on the memory management 
space,
and I might be missing details such as "we don't care about pc-dimm hotplug
anymore, it's legacy, we're going to support only virtio-md-pci from now on". We
had a situation like that with virtio-balloon and virtio-mem in the past, and 
I'm
not sure if this might fall in the same category.


Not sure if I got your comment right, but virtio-mem was never supposed to be a 
virtio-balloon replacement (especially of the free-page-reporting and memory 
stats part).


I was trying to refer to a situation we faced 3+ years ago in the powerpc 
machines,
where we were trying to add virtio-mem support there given that virtio-mem 
is/was
been seen (as far as I can remember anyways) as a more robust solution than
virtio-balloon + DIMM hotplug for guest memory management from the host point of
view.

I'm probably misrepresenting the whole situation though, it has been 

Re: [PATCH] hw/riscv/virt: Add hotplugging and virtio-md-pci support

2024-05-18 Thread Daniel Henrique Barboza

Hi Björj,

On 5/14/24 08:06, Björn Töpel wrote:

From: Björn Töpel 

Virtio-based memory devices allows for dynamic resizing of virtual
machine memory, and requires proper hotplugging (add/remove) support
to work.

Enable virtio-md-pci with the corresponding missing hotplugging
callbacks for the RISC-V "virt" machine.

Signed-off-by: Björn Töpel 
---
This is basic support for MHP that works with DT. There some minor
ACPI SRAT plumbing in there as well. Ideally we'd like proper ACPI MHP
support as well. I have a branch [1], where I've applied this patch,
plus ACPI GED/PC-DIMM MHP support on top of Sunil's QEMU branch
(contains some ACPI DSDT additions) [2], for the curious/brave ones.
However, the ACPI MHP support this is not testable on upstream Linux
yet (ACPI AIA support, and ACPI NUMA SRAT series are ongoing).

I'll follow-up with proper ACPI GED/PC-DIMM MHP patches, once the
dependencies land (Linux kernel and QEMU).

I'll post the Linux MHP/virtio-mem v2 patches later this week!


Cheers,
Björn

[1] https://github.com/bjoto/qemu/commits/virtio-mem-pc-dimm-mhp-acpi/
[2] 
https://lore.kernel.org/linux-riscv/20240501121742.1215792-1-suni...@ventanamicro.com/
---
  hw/riscv/Kconfig   |  2 ++
  hw/riscv/virt-acpi-build.c |  7 +
  hw/riscv/virt.c| 64 +-
  hw/virtio/virtio-mem.c |  2 +-
  4 files changed, 73 insertions(+), 2 deletions(-)

diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
index a2030e3a6ff0..08f82dbb681a 100644
--- a/hw/riscv/Kconfig
+++ b/hw/riscv/Kconfig
@@ -56,6 +56,8 @@ config RISCV_VIRT
  select PLATFORM_BUS
  select ACPI
  select ACPI_PCI
+select VIRTIO_MEM_SUPPORTED
+select VIRTIO_PMEM_SUPPORTED
  
  config SHAKTI_C

  bool
diff --git a/hw/riscv/virt-acpi-build.c b/hw/riscv/virt-acpi-build.c
index 0925528160f8..6dc3baa9ec86 100644
--- a/hw/riscv/virt-acpi-build.c
+++ b/hw/riscv/virt-acpi-build.c
@@ -610,6 +610,13 @@ build_srat(GArray *table_data, BIOSLinker *linker, 
RISCVVirtState *vms)
  }
  }
  
+if (ms->device_memory) {

+build_srat_memory(table_data, ms->device_memory->base,
+  memory_region_size(>device_memory->mr),
+  ms->numa_state->num_nodes - 1,
+  MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
+}
+
  acpi_table_end(linker, );


When the time comes I believe we'll want this chunk in a separated ACPI patch.


  }
  
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c

index 4fdb66052587..16c2bdbfe6b6 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -53,6 +53,8 @@
  #include "hw/pci-host/gpex.h"
  #include "hw/display/ramfb.h"
  #include "hw/acpi/aml-build.h"
+#include "hw/mem/memory-device.h"
+#include "hw/virtio/virtio-mem-pci.h"
  #include "qapi/qapi-visit-common.h"
  #include "hw/virtio/virtio-iommu.h"
  
@@ -1407,6 +1409,7 @@ static void virt_machine_init(MachineState *machine)

  DeviceState *mmio_irqchip, *virtio_irqchip, *pcie_irqchip;
  int i, base_hartid, hart_count;
  int socket_count = riscv_socket_count(machine);
+hwaddr device_memory_base, device_memory_size;
  
  /* Check socket count limit */

  if (VIRT_SOCKETS_MAX < socket_count) {
@@ -1553,6 +1556,25 @@ static void virt_machine_init(MachineState *machine)
  memory_region_add_subregion(system_memory, memmap[VIRT_MROM].base,
  mask_rom);
  
+device_memory_base = ROUND_UP(s->memmap[VIRT_DRAM].base + machine->ram_size,

+  GiB);
+device_memory_size = machine->maxram_size - machine->ram_size;
+
+if (riscv_is_32bit(>soc[0])) {
+hwaddr memtop = device_memory_base + ROUND_UP(device_memory_size, GiB);
+
+if (memtop > UINT32_MAX) {
+error_report("Memory exceeds 32-bit limit by %lu bytes",
+ memtop - UINT32_MAX);
+exit(EXIT_FAILURE);
+}
+}
+
+if (device_memory_size > 0) {
+machine_memory_devices_init(machine, device_memory_base,
+device_memory_size);
+}
+


I think we need a design discussion before proceeding here. You're allocating 
all
available memory as a memory device area, but in theory we might also support
pc-dimm hotplugs (which would be the equivalent of adding physical RAM dimms to
the board.) in the future too. If you're not familiar with this feature you can
check it out the docs in [1].

As an example, the 'virt' ARM board (hw/arm/virt.c) reserves a space for this
type of hotplug by checking how much 'ram_slots' we're allocating for it:

device_memory_size = ms->maxram_size - ms->ram_size + ms->ram_slots * GiB;

Other boards do the same with ms->ram_slots. We should consider doing it as 
well,
now, even if we're not up to the point of supporting pc-dimm hotplug, to avoid
having to change the memory layout later in the road and breaking existing
setups.

If we want to copy the ARM 

Re: [PATCH] dias/riscv: Decode all of the pmpcfg and pmpaddr CSRs

2024-05-18 Thread Daniel Henrique Barboza

^ typo in the commit subject: 'disas/riscv: ...'

On 5/14/24 02:16, Alistair Francis wrote:

Previously we only listed a single pmpcfg CSR and the first 16 pmpaddr
CSRs. This patch fixes this to list all 16 pmpcfg and all 64 pmpaddr
CSRs are part of the dissassembly.


I think the correct here is 'disassembly'.



Reported-by: Eric DeVolder 
Signed-off-by: Alistair Francis 
---
  disas/riscv.c | 65 ++-
  1 file changed, 64 insertions(+), 1 deletion(-)

diff --git a/disas/riscv.c b/disas/riscv.c
index e236c8b5b7..297cfa2f63 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -2190,7 +2190,22 @@ static const char *csr_name(int csrno)
  case 0x0383: return "mibound";
  case 0x0384: return "mdbase";
  case 0x0385: return "mdbound";
-case 0x03a0: return "pmpcfg3";
+case 0x03a0: return "pmpcfg0";


Hmm it seems that the code for 'pmpcfg3' was incorrect from the get go.
Perhaps it's worth adding a:

Fixes: ea10325917 ("RISC-V Disassembler")


Regardless of adding a 'Fixes' tag or not:


Reviewed-by: Daniel Henrique Barboza 




Thanks,

Daniel


+case 0x03a1: return "pmpcfg1";
+case 0x03a2: return "pmpcfg2";
+case 0x03a3: return "pmpcfg3";
+case 0x03a4: return "pmpcfg4";
+case 0x03a5: return "pmpcfg5";
+case 0x03a6: return "pmpcfg6";
+case 0x03a7: return "pmpcfg7";
+case 0x03a8: return "pmpcfg8";
+case 0x03a9: return "pmpcfg9";
+case 0x03aa: return "pmpcfg10";
+case 0x03ab: return "pmpcfg11";
+case 0x03ac: return "pmpcfg12";
+case 0x03ad: return "pmpcfg13";
+case 0x03ae: return "pmpcfg14";
+case 0x03af: return "pmpcfg15";
  case 0x03b0: return "pmpaddr0";
  case 0x03b1: return "pmpaddr1";
  case 0x03b2: return "pmpaddr2";
@@ -2207,6 +,54 @@ static const char *csr_name(int csrno)
  case 0x03bd: return "pmpaddr13";
  case 0x03be: return "pmpaddr14";
  case 0x03bf: return "pmpaddr15";
+case 0x03c0: return "pmpaddr16";
+case 0x03c1: return "pmpaddr17";
+case 0x03c2: return "pmpaddr18";
+case 0x03c3: return "pmpaddr19";
+case 0x03c4: return "pmpaddr20";
+case 0x03c5: return "pmpaddr21";
+case 0x03c6: return "pmpaddr22";
+case 0x03c7: return "pmpaddr23";
+case 0x03c8: return "pmpaddr24";
+case 0x03c9: return "pmpaddr25";
+case 0x03ca: return "pmpaddr26";
+case 0x03cb: return "pmpaddr27";
+case 0x03cc: return "pmpaddr28";
+case 0x03cd: return "pmpaddr29";
+case 0x03ce: return "pmpaddr30";
+case 0x03cf: return "pmpaddr31";
+case 0x03d0: return "pmpaddr32";
+case 0x03d1: return "pmpaddr33";
+case 0x03d2: return "pmpaddr34";
+case 0x03d3: return "pmpaddr35";
+case 0x03d4: return "pmpaddr36";
+case 0x03d5: return "pmpaddr37";
+case 0x03d6: return "pmpaddr38";
+case 0x03d7: return "pmpaddr39";
+case 0x03d8: return "pmpaddr40";
+case 0x03d9: return "pmpaddr41";
+case 0x03da: return "pmpaddr42";
+case 0x03db: return "pmpaddr43";
+case 0x03dc: return "pmpaddr44";
+case 0x03dd: return "pmpaddr45";
+case 0x03de: return "pmpaddr46";
+case 0x03df: return "pmpaddr47";
+case 0x03e0: return "pmpaddr48";
+case 0x03e1: return "pmpaddr49";
+case 0x03e2: return "pmpaddr50";
+case 0x03e3: return "pmpaddr51";
+case 0x03e4: return "pmpaddr52";
+case 0x03e5: return "pmpaddr53";
+case 0x03e6: return "pmpaddr54";
+case 0x03e7: return "pmpaddr55";
+case 0x03e8: return "pmpaddr56";
+case 0x03e9: return "pmpaddr57";
+case 0x03ea: return "pmpaddr58";
+case 0x03eb: return "pmpaddr59";
+case 0x03ec: return "pmpaddr60";
+case 0x03ed: return "pmpaddr61";
+case 0x03ee: return "pmpaddr62";
+case 0x03ef: return "pmpaddr63";
  case 0x0780: return "mtohost";
  case 0x0781: return "mfromhost";
  case 0x0782: return "mreset";




Re: [PATCH 2/2] target/riscv: Move Guest irqs out of the core local irqs range.

2024-05-18 Thread Daniel Henrique Barboza




On 5/13/24 08:46, Rajnesh Kanwal wrote:

Qemu maps IRQs 0:15 for core interrupts and 16 onward for
guest interrupts which are later translated to hgiep in
`riscv_cpu_set_irq()` function.

With virtual IRQ support added, software now can fully
use the whole local interrupt range without any actual
hardware attached.

This change moves the guest interrupt range after the
core local interrupt range to avoid clash.

Fixes: 1697837ed9 ("target/riscv: Add M-mode virtual
interrupt and IRQ filtering support.")
Fixes: 40336d5b1d ("target/riscv: Add HS-mode virtual
interrupt and IRQ filtering support.")



As I said in patch 1, please do not split the commit titles in a
"Fixes" tag:


Fixes: 1697837ed9 ("target/riscv: Add M-mode virtual interrupt and IRQ filtering 
support.")
Fixes: 40336d5b1d ("target/riscv: Add HS-mode virtual interrupt and IRQ filtering 
support.")




Signed-off-by: Rajnesh Kanwal 
---
  target/riscv/cpu_bits.h | 3 ++-
  target/riscv/csr.c  | 7 ++-
  2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 13ce2218d1..33f28bb115 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -664,7 +664,8 @@ typedef enum RISCVException {
  #define IRQ_M_EXT  11
  #define IRQ_S_GEXT 12
  #define IRQ_PMU_OVF13
-#define IRQ_LOCAL_MAX  16
+#define IRQ_LOCAL_MAX  64
+/* -1 is due to bit zero of hgeip and hgeie being ROZ. */
  #define IRQ_LOCAL_GUEST_MAX(TARGET_LONG_BITS - 1)
  
  /* mip masks */

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index c9d685dcc5..78f42fcae5 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1141,7 +1141,12 @@ static RISCVException write_stimecmph(CPURISCVState 
*env, int csrno,
  
  #define VSTOPI_NUM_SRCS 5
  
-#define LOCAL_INTERRUPTS (~0x1FFF)

+/* All core local interrupts except the fixed ones 0:12. This macro is for 
virtual
+ * interrupts logic so please don't change this to avoid messing up the whole 
support,
+ * For reference see AIA spec: `5.3 Interrupt filtering and virtual interrupts 
for
+ * supervisor level` and `6.3.2 Virtual interrupts for VS level`.
+ */


The comment format we use is capped at 80 chars per line and starts with a
leading /*  on a separated line:



+/*
+/* All core local interrupts except the fixed ones 0:12. This macro is
+/* for virtual interrupts logic so please don't change this to avoid
+/* messing up the whole support. For reference see AIA spec:
+/* `5.3 Interrupt filtering and virtual interrupts for supervisor level`
+/* and `6.3.2 Virtual interrupts for VS level`.
+ */


You can run ./scripts/checkpatch.pl in the generated patch file to see if the
patch is compliant with the expected code style.



Thanks,


Daniel




+#define LOCAL_INTERRUPTS   (~0x1FFFULL)
  
  static const uint64_t delegable_ints =

  S_MODE_INTERRUPTS | VS_MODE_INTERRUPTS | MIP_LCOFIP;




Re: [PATCH 1/2] target/riscv: Extend virtual irq csrs masks to be 64 bit wide.

2024-05-18 Thread Daniel Henrique Barboza




On 5/13/24 08:46, Rajnesh Kanwal wrote:

AIA extends the width of all IRQ CSRs to 64bit even
in 32bit systems by adding missing half CSRs.

This seems to be missed while adding support for
virtual IRQs. The whole logic seems to be correct
except the width of the masks.

Fixes: 1697837ed9 ("target/riscv: Add M-mode virtual
interrupt and IRQ filtering support.")
Fixes: 40336d5b1d ("target/riscv: Add HS-mode virtual
interrupt and IRQ filtering support.")



Please avoid splitting the commit title when including them in a "Fixes"
tag. It is ok if the commit this breaks the usual char limit:


Fixes: 1697837ed9 ("target/riscv: Add M-mode virtual interrupt and IRQ filtering 
support.")
Fixes: 40336d5b1d ("target/riscv: Add HS-mode virtual interrupt and IRQ filtering 
support.")



As for the code:


Reviewed-by: Daniel Henrique Barboza 


Signed-off-by: Rajnesh Kanwal 
---
  target/riscv/csr.c | 14 +++---
  1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 45b548eb0b..c9d685dcc5 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1193,18 +1193,18 @@ static const target_ulong sstatus_v1_10_mask = 
SSTATUS_SIE | SSTATUS_SPIE |
   */
  
  /* Bit STIP can be an alias of mip.STIP that's why it's writable in mvip. */

-static const target_ulong mvip_writable_mask = MIP_SSIP | MIP_STIP | MIP_SEIP |
+static const uint64_t mvip_writable_mask = MIP_SSIP | MIP_STIP | MIP_SEIP |
  LOCAL_INTERRUPTS;
-static const target_ulong mvien_writable_mask = MIP_SSIP | MIP_SEIP |
+static const uint64_t mvien_writable_mask = MIP_SSIP | MIP_SEIP |
  LOCAL_INTERRUPTS;
  
-static const target_ulong sip_writable_mask = SIP_SSIP | LOCAL_INTERRUPTS;

-static const target_ulong hip_writable_mask = MIP_VSSIP;
-static const target_ulong hvip_writable_mask = MIP_VSSIP | MIP_VSTIP |
+static const uint64_t sip_writable_mask = SIP_SSIP | LOCAL_INTERRUPTS;
+static const uint64_t hip_writable_mask = MIP_VSSIP;
+static const uint64_t hvip_writable_mask = MIP_VSSIP | MIP_VSTIP |
  MIP_VSEIP | LOCAL_INTERRUPTS;
-static const target_ulong hvien_writable_mask = LOCAL_INTERRUPTS;
+static const uint64_t hvien_writable_mask = LOCAL_INTERRUPTS;
  
-static const target_ulong vsip_writable_mask = MIP_VSSIP | LOCAL_INTERRUPTS;

+static const uint64_t vsip_writable_mask = MIP_VSSIP | LOCAL_INTERRUPTS;
  
  const bool valid_vm_1_10_32[16] = {

  [VM_1_10_MBARE] = true,




[PATCH v2 1/1] riscv, gdbstub.c: fix reg_width in ricsv_gen_dynamic_vector_feature()

2024-05-17 Thread Daniel Henrique Barboza
Commit 33a24910ae changed 'reg_width' to use 'vlenb', i.e. vector length
in bytes, when in this context we want 'reg_width' as the length in
bits.

Fix 'reg_width' back to the value in bits like 7cb59921c05a
("target/riscv/gdbstub.c: use 'vlenb' instead of shifting 'vlen'") set
beforehand.

While we're at it, rename 'reg_width' to 'bitsize' to provide a bit more
clarity about what the variable represents. 'bitsize' is also used in
riscv_gen_dynamic_csr_feature() with the same purpose, i.e. as an input to
gdb_feature_builder_append_reg().

Cc: Akihiko Odaki 
Cc: Alex Bennée 
Reported-by: Robin Dapp 
Fixes: 33a24910ae ("target/riscv: Use GDBFeature for dynamic XML")
Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: LIU Zhiwei 
Acked-by: Alex Bennée 
---
 target/riscv/gdbstub.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index d0cc5762c2..c07df972f1 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -288,7 +288,7 @@ static GDBFeature *riscv_gen_dynamic_csr_feature(CPUState 
*cs, int base_reg)
 static GDBFeature *ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg)
 {
 RISCVCPU *cpu = RISCV_CPU(cs);
-int reg_width = cpu->cfg.vlenb;
+int bitsize = cpu->cfg.vlenb << 3;
 GDBFeatureBuilder builder;
 int i;
 
@@ -298,7 +298,7 @@ static GDBFeature 
*ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg)
 
 /* First define types and totals in a whole VL */
 for (i = 0; i < ARRAY_SIZE(vec_lanes); i++) {
-int count = reg_width / vec_lanes[i].size;
+int count = bitsize / vec_lanes[i].size;
 gdb_feature_builder_append_tag(
 , "",
 vec_lanes[i].id, vec_lanes[i].gdb_type, count);
@@ -316,7 +316,7 @@ static GDBFeature 
*ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg)
 /* Define vector registers */
 for (i = 0; i < 32; i++) {
 gdb_feature_builder_append_reg(, g_strdup_printf("v%d", i),
-   reg_width, i, "riscv_vector", "vector");
+   bitsize, i, "riscv_vector", "vector");
 }
 
 gdb_feature_builder_end();
-- 
2.44.0




[PATCH v2 0/1] riscv, gdbstub.c: fix reg_width in ricsv_gen_dynamic_vector_feature()

2024-05-17 Thread Daniel Henrique Barboza
Hi,

In this v2 'reg_width' was renamed to 'bitsize' to provide a bit more
clarity about what's the value type of the variable. It is the same name
used by riscv_gen_dynamic_csr_feature() for a variable that has the same
purpose. The variable rename was suggested by Alex in v1.

Changes from v1:
- rename 'reg_width' to 'bitsize'
- v1 link: 
https://lore.kernel.org/qemu-riscv/20240516171010.639591-1-dbarb...@ventanamicro.com/

Daniel Henrique Barboza (1):
  riscv, gdbstub.c: fix reg_width in ricsv_gen_dynamic_vector_feature()

 target/riscv/gdbstub.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

-- 
2.44.0




Re: [PATCH v2 10/15] hw/riscv/riscv-iommu: add ATS support

2024-05-17 Thread Daniel Henrique Barboza

Hi Frank,


On 5/7/24 23:57, Frank Chang wrote:

Hi Daniel,

Daniel Henrique Barboza  於 2024年3月8日 週五 上午12:06寫道:


From: Tomasz Jeznach 

Add PCIe Address Translation Services (ATS) capabilities to the IOMMU.
This will add support for ATS translation requests in Fault/Event
queues, Page-request queue and IOATC invalidations.

Signed-off-by: Tomasz Jeznach 
Signed-off-by: Daniel Henrique Barboza 
---
  hw/riscv/riscv-iommu-bits.h |  43 ++-
  hw/riscv/riscv-iommu.c  | 107 +---
  hw/riscv/riscv-iommu.h  |   1 +
  hw/riscv/trace-events   |   3 +
  4 files changed, 145 insertions(+), 9 deletions(-)

diff --git a/hw/riscv/riscv-iommu-bits.h b/hw/riscv/riscv-iommu-bits.h
index 9d645d69ea..0994f5ce48 100644
--- a/hw/riscv/riscv-iommu-bits.h
+++ b/hw/riscv/riscv-iommu-bits.h
@@ -81,6 +81,7 @@ struct riscv_iommu_pq_record {
  #define RISCV_IOMMU_CAP_SV57X4  BIT_ULL(19)
  #define RISCV_IOMMU_CAP_MSI_FLATBIT_ULL(22)
  #define RISCV_IOMMU_CAP_MSI_MRIFBIT_ULL(23)
+#define RISCV_IOMMU_CAP_ATS BIT_ULL(25)
  #define RISCV_IOMMU_CAP_IGS GENMASK_ULL(29, 28)
  #define RISCV_IOMMU_CAP_PAS GENMASK_ULL(37, 32)
  #define RISCV_IOMMU_CAP_PD8 BIT_ULL(38)
@@ -201,6 +202,7 @@ struct riscv_iommu_dc {

  /* Translation control fields */
  #define RISCV_IOMMU_DC_TC_V BIT_ULL(0)
+#define RISCV_IOMMU_DC_TC_EN_ATSBIT_ULL(1)
  #define RISCV_IOMMU_DC_TC_DTF   BIT_ULL(4)
  #define RISCV_IOMMU_DC_TC_PDTV  BIT_ULL(5)
  #define RISCV_IOMMU_DC_TC_PRPR  BIT_ULL(6)
@@ -259,6 +261,20 @@ struct riscv_iommu_command {
  #define RISCV_IOMMU_CMD_IODIR_DVBIT_ULL(33)
  #define RISCV_IOMMU_CMD_IODIR_DID   GENMASK_ULL(63, 40)

+/* 3.1.4 I/O MMU PCIe ATS */
+#define RISCV_IOMMU_CMD_ATS_OPCODE  4
+#define RISCV_IOMMU_CMD_ATS_FUNC_INVAL  0
+#define RISCV_IOMMU_CMD_ATS_FUNC_PRGR   1
+#define RISCV_IOMMU_CMD_ATS_PID GENMASK_ULL(31, 12)
+#define RISCV_IOMMU_CMD_ATS_PV  BIT_ULL(32)
+#define RISCV_IOMMU_CMD_ATS_DSV BIT_ULL(33)
+#define RISCV_IOMMU_CMD_ATS_RID GENMASK_ULL(55, 40)
+#define RISCV_IOMMU_CMD_ATS_DSEGGENMASK_ULL(63, 56)
+/* dword1 is the ATS payload, two different payload types for INVAL and PRGR */
+
+/* ATS.PRGR payload */
+#define RISCV_IOMMU_CMD_ATS_PRGR_RESP_CODE  GENMASK_ULL(47, 44)
+
  enum riscv_iommu_dc_fsc_atp_modes {
  RISCV_IOMMU_DC_FSC_MODE_BARE = 0,
  RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV32 = 8,
@@ -322,7 +338,32 @@ enum riscv_iommu_fq_ttypes {
  RISCV_IOMMU_FQ_TTYPE_TADDR_INST_FETCH = 5,
  RISCV_IOMMU_FQ_TTYPE_TADDR_RD = 6,
  RISCV_IOMMU_FQ_TTYPE_TADDR_WR = 7,
-RISCV_IOMMU_FW_TTYPE_PCIE_MSG_REQ = 8,
+RISCV_IOMMU_FQ_TTYPE_PCIE_ATS_REQ = 8,
+RISCV_IOMMU_FW_TTYPE_PCIE_MSG_REQ = 9,
+};
+
+/* Header fields */
+#define RISCV_IOMMU_PREQ_HDR_PIDGENMASK_ULL(31, 12)
+#define RISCV_IOMMU_PREQ_HDR_PV BIT_ULL(32)
+#define RISCV_IOMMU_PREQ_HDR_PRIV   BIT_ULL(33)
+#define RISCV_IOMMU_PREQ_HDR_EXEC   BIT_ULL(34)
+#define RISCV_IOMMU_PREQ_HDR_DIDGENMASK_ULL(63, 40)
+
+/* Payload fields */
+#define RISCV_IOMMU_PREQ_PAYLOAD_R  BIT_ULL(0)
+#define RISCV_IOMMU_PREQ_PAYLOAD_W  BIT_ULL(1)
+#define RISCV_IOMMU_PREQ_PAYLOAD_L  BIT_ULL(2)
+#define RISCV_IOMMU_PREQ_PAYLOAD_M  GENMASK_ULL(2, 0)
+#define RISCV_IOMMU_PREQ_PRG_INDEX  GENMASK_ULL(11, 3)
+#define RISCV_IOMMU_PREQ_UADDR  GENMASK_ULL(63, 12)
+
+
+/*
+ * struct riscv_iommu_msi_pte - MSI Page Table Entry
+ */
+struct riscv_iommu_msi_pte {
+  uint64_t pte;
+  uint64_t mrif_info;
  };

  /* Fields on pte */
diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
index 03a610fa75..7af5929b10 100644
--- a/hw/riscv/riscv-iommu.c
+++ b/hw/riscv/riscv-iommu.c
@@ -576,7 +576,7 @@ static int riscv_iommu_ctx_fetch(RISCVIOMMUState *s, 
RISCVIOMMUContext *ctx)
  RISCV_IOMMU_DC_IOHGATP_MODE_BARE);
  ctx->satp = set_field(0, RISCV_IOMMU_ATP_MODE_FIELD,
  RISCV_IOMMU_DC_FSC_MODE_BARE);
-ctx->tc = RISCV_IOMMU_DC_TC_V;
+ctx->tc = RISCV_IOMMU_DC_TC_EN_ATS | RISCV_IOMMU_DC_TC_V;


We should OR RISCV_IOMMU_DC_TC_EN_ATS only when IOMMU has ATS capability.
(i.e. s->enable_ats == true).


  ctx->ta = 0;
  ctx->msiptp = 0;
  return 0;
@@ -1021,6 +1021,18 @@ static int riscv_iommu_translate(RISCVIOMMUState *s, 
RISCVIOMMUContext *ctx,
  enable_pri = (iotlb->perm == IOMMU_NONE) && (ctx->tc & BIT_ULL(32));
  enable_pasid = (ctx->tc & RISCV_IOMMU_DC_TC_PDTV);

+/* Check for ATS request. */
+if (iotlb->perm == IOMMU_NONE) {
+/* Check if ATS is disabled. */
+if (!(ctx->tc & RISCV_IOMMU_DC_TC_EN_ATS)) {
+enable_pri = false;
+fault = RISCV_IOMMU_FQ_CAUSE_TTYPE_BLOCKED;
+goto done;
+}
+  

Re: [PATCH v2 08/15] hw/riscv/riscv-iommu: add Address Translation Cache (IOATC)

2024-05-16 Thread Daniel Henrique Barboza




On 5/8/24 04:26, Frank Chang wrote:

Hi Daniel,

Daniel Henrique Barboza  於 2024年3月8日 週五 上午12:05寫道:


From: Tomasz Jeznach 

The RISC-V IOMMU spec predicts that the IOMMU can use translation caches
to hold entries from the DDT. This includes implementation for all cache
commands that are marked as 'not implemented'.

There are some artifacts included in the cache that predicts s-stage and
g-stage elements, although we don't support it yet. We'll introduce them
next.

Signed-off-by: Tomasz Jeznach 
Signed-off-by: Daniel Henrique Barboza 
---
  hw/riscv/riscv-iommu.c | 190 -
  hw/riscv/riscv-iommu.h |   2 +
  2 files changed, 188 insertions(+), 4 deletions(-)

diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
index df534b99b0..0b93146327 100644
--- a/hw/riscv/riscv-iommu.c
+++ b/hw/riscv/riscv-iommu.c
@@ -63,6 +63,16 @@ struct RISCVIOMMUContext {
  uint64_t msiptp;/* MSI redirection page table pointer */
  };

+/* Address translation cache entry */
+struct RISCVIOMMUEntry {
+uint64_t iova:44;   /* IOVA Page Number */
+uint64_t pscid:20;  /* Process Soft-Context identifier */
+uint64_t phys:44;   /* Physical Page Number */
+uint64_t gscid:16;  /* Guest Soft-Context identifier */
+uint64_t perm:2;/* IOMMU_RW flags */
+uint64_t __rfu:2;
+};
+
  /* IOMMU index for transactions without PASID specified. */
  #define RISCV_IOMMU_NOPASID 0

@@ -629,14 +639,127 @@ static AddressSpace *riscv_iommu_space(RISCVIOMMUState 
*s, uint32_t devid)
  return >iova_as;
  }

+/* Translation Object cache support */
+static gboolean __iot_equal(gconstpointer v1, gconstpointer v2)
+{
+RISCVIOMMUEntry *t1 = (RISCVIOMMUEntry *) v1;
+RISCVIOMMUEntry *t2 = (RISCVIOMMUEntry *) v2;
+return t1->gscid == t2->gscid && t1->pscid == t2->pscid &&
+   t1->iova == t2->iova;
+}
+
+static guint __iot_hash(gconstpointer v)
+{
+RISCVIOMMUEntry *t = (RISCVIOMMUEntry *) v;
+return (guint)t->iova;
+}
+
+/* GV: 1 PSCV: 1 AV: 1 */
+static void __iot_inval_pscid_iova(gpointer key, gpointer value, gpointer data)
+{
+RISCVIOMMUEntry *iot = (RISCVIOMMUEntry *) value;
+RISCVIOMMUEntry *arg = (RISCVIOMMUEntry *) data;
+if (iot->gscid == arg->gscid &&
+iot->pscid == arg->pscid &&
+iot->iova == arg->iova) {
+iot->perm = 0;


Maybe using IOMMU_NONE would be clearer?


Agree. I changed all relevant "iot->perm = 0" instances to "iot->perm = 
IOMMU_NONE".


Thanks,


Daniel



Otherwise,
Reviewed-by: Frank Chang 


+}
+}
+
+/* GV: 1 PSCV: 1 AV: 0 */
+static void __iot_inval_pscid(gpointer key, gpointer value, gpointer data)
+{
+RISCVIOMMUEntry *iot = (RISCVIOMMUEntry *) value;
+RISCVIOMMUEntry *arg = (RISCVIOMMUEntry *) data;
+if (iot->gscid == arg->gscid &&
+iot->pscid == arg->pscid) {
+iot->perm = 0;
+}
+}
+
+/* GV: 1 GVMA: 1 */
+static void __iot_inval_gscid_gpa(gpointer key, gpointer value, gpointer data)
+{
+RISCVIOMMUEntry *iot = (RISCVIOMMUEntry *) value;
+RISCVIOMMUEntry *arg = (RISCVIOMMUEntry *) data;
+if (iot->gscid == arg->gscid) {
+/* simplified cache, no GPA matching */
+iot->perm = 0;
+}
+}
+
+/* GV: 1 GVMA: 0 */
+static void __iot_inval_gscid(gpointer key, gpointer value, gpointer data)
+{
+RISCVIOMMUEntry *iot = (RISCVIOMMUEntry *) value;
+RISCVIOMMUEntry *arg = (RISCVIOMMUEntry *) data;
+if (iot->gscid == arg->gscid) {
+iot->perm = 0;
+}
+}
+
+/* GV: 0 */
+static void __iot_inval_all(gpointer key, gpointer value, gpointer data)
+{
+RISCVIOMMUEntry *iot = (RISCVIOMMUEntry *) value;
+iot->perm = 0;
+}
+
+/* caller should keep ref-count for iot_cache object */
+static RISCVIOMMUEntry *riscv_iommu_iot_lookup(RISCVIOMMUContext *ctx,
+GHashTable *iot_cache, hwaddr iova)
+{
+RISCVIOMMUEntry key = {
+.pscid = get_field(ctx->ta, RISCV_IOMMU_DC_TA_PSCID),
+.iova  = PPN_DOWN(iova),
+};
+return g_hash_table_lookup(iot_cache, );
+}
+
+/* caller should keep ref-count for iot_cache object */
+static void riscv_iommu_iot_update(RISCVIOMMUState *s,
+GHashTable *iot_cache, RISCVIOMMUEntry *iot)
+{
+if (!s->iot_limit) {
+return;
+}
+
+if (g_hash_table_size(s->iot_cache) >= s->iot_limit) {
+iot_cache = g_hash_table_new_full(__iot_hash, __iot_equal,
+  g_free, NULL);
+g_hash_table_unref(qatomic_xchg(>iot_cache, iot_cache));
+}
+g_hash_table_add(iot_cache, iot);
+}
+
+static void riscv_iommu_iot_inval(RISCVIOMMUState *s, GHFunc func,
+uint32_t gscid, uint32_t pscid, hwaddr iova)
+{
+GHashTable *iot_cache;
+RISCVIOMMUEntry key = {
+.gscid = gscid,
+.pscid = psci

Re: [PATCH v2 09/15] hw/riscv/riscv-iommu: add s-stage and g-stage support

2024-05-16 Thread Daniel Henrique Barboza




On 5/10/24 08:14, Andrew Jones wrote:

On Fri, May 10, 2024 at 06:36:51PM GMT, Frank Chang wrote:
...

  static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, RISCVIOMMUContext *ctx,
-IOMMUTLBEntry *iotlb)
+IOMMUTLBEntry *iotlb, bool gpa)
  {
+dma_addr_t addr, base;
+uint64_t satp, gatp, pte;
+bool en_s, en_g;
+struct {
+unsigned char step;
+unsigned char levels;
+unsigned char ptidxbits;
+unsigned char ptesize;
+} sc[2];
+/* Translation stage phase */
+enum {
+S_STAGE = 0,
+G_STAGE = 1,
+} pass;
+
+satp = get_field(ctx->satp, RISCV_IOMMU_ATP_MODE_FIELD);
+gatp = get_field(ctx->gatp, RISCV_IOMMU_ATP_MODE_FIELD);
+
+en_s = satp != RISCV_IOMMU_DC_FSC_MODE_BARE && !gpa;
+en_g = gatp != RISCV_IOMMU_DC_IOHGATP_MODE_BARE;
+
  /* Early check for MSI address match when IOVA == GPA */
-if (iotlb->perm & IOMMU_WO &&
+if (!en_s && (iotlb->perm & IOMMU_WO) &&


I'm wondering do we need to check "en_s" for MSI writes?

IOMMU spec Section 2.3.3. Process to translate addresses of MSIs says:
"Determine if the address A is an access to a virtual interrupt file
as specified in Section 2.1.3.6."

and Section 2.1.3.6 says:

"An incoming memory access made by a device is recognized as
an access to a virtual interrupt file if the destination guest physical page
matches the supplied address pattern in all bit positions that are zeros
in the supplied address mask. In detail, a memory access to
guest physical address A is recognized as an access to a virtual
interrupt file’s
memory-mapped page if:
(A >> 12) & ~msi_addr_mask = (msi_addr_pattern & ~msi_addr_mask)"

Is checking the address pattern sufficient enough to determine
the address is an MSI to a virtual interrupt file?



I think so. In fact, I've removed that en_s check on our internal build in
order to get things working for my irqbypass work, as we can do device
assignment with VFIO with only S-stage enabled.


The following code will be fixed up here:

 static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, RISCVIOMMUContext *ctx,
-IOMMUTLBEntry *iotlb, bool gpa)
+IOMMUTLBEntry *iotlb)
 {
 dma_addr_t addr, base;
 uint64_t satp, gatp, pte;
@@ -238,11 +237,11 @@ static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, 
RISCVIOMMUContext *ctx,
 satp = get_field(ctx->satp, RISCV_IOMMU_ATP_MODE_FIELD);
 gatp = get_field(ctx->gatp, RISCV_IOMMU_ATP_MODE_FIELD);
 
-en_s = satp != RISCV_IOMMU_DC_FSC_MODE_BARE && !gpa;

+en_s = satp != RISCV_IOMMU_DC_FSC_MODE_BARE;
 en_g = gatp != RISCV_IOMMU_DC_IOHGATP_MODE_BARE;
 
 /* Early check for MSI address match when IOVA == GPA */

-if (!en_s && (iotlb->perm & IOMMU_WO) &&
+if ((iotlb->perm & IOMMU_WO) &&
 riscv_iommu_msi_check(s, ctx, iotlb->iova)) {
 iotlb->target_as = >trap_as;
 iotlb->translated_addr = iotlb->iova;
@@ -1203,7 +1202,7 @@ static int riscv_iommu_translate(RISCVIOMMUState *s, 
RISCVIOMMUContext *ctx,
 }
 
 /* Translate using device directory / page table information. */

-fault = riscv_iommu_spa_fetch(s, ctx, iotlb, false);
+fault = riscv_iommu_spa_fetch(s, ctx, iotlb);
 
 if (!fault && iotlb->target_as == >trap_as) {

 /* Do not cache trapped MSI translations */

'gpa' is eliminated since it was only being used as 'false' by the only
caller of riscv_iommu_spa_fetch(). The boolean was used only to calculate
en_s as "&& !gpa", so it's always 'true' and had no impact in en_s. My
understand here is that 'gpa' was a prototype of the first implementation
that got left behind and ended up not being used.

As for the MSI check, we won't skip translation if satp is bare (!en_s) because
we might be using just stage2 for a guest, thus en_s is removed from the
conditional. As Frank said, this change also complies with the spec since we 
don't
need to check satp to determine if the address is an MSI to a virtual interrupt
file.

And, last but not the least, this change doesn't break my KVM VFIO passthrough
test case :) I'll document more about the test case I'm using in the v3 cover
letter.


Thanks,

Daniel




Thanks,
drew




[PATCH 0/1] riscv, gdbstub.c: fix reg_width in ricsv_gen_dynamic_vector_feature()

2024-05-16 Thread Daniel Henrique Barboza
Hi,

Commit 33a24910ae ("target/riscv: Use GDBFeature for dynamic XML")
changed 'reg_width' for vector regs, a change that I believe to be
unintended, and we're unable to print vector regs in GDB ATM.

The following is a gdb output of a simple program running with
qemu-riscv64 when trying to print the value of 'v1' after a 'vle'
insns:

(gdb) p $v1
$1 = {q = 0x0, l = 0x0, w = 0x0, s = {57920}, b = {64, 226}}
(gdb) 

After this patch:

(gdb) p $v1
$1 = {q = {9781192033638379298842687819604544}, l = {530239482618432, 
530239482618432}, w = {123456, 123456, 
123456, 123456}, s = {57920, 1, 57920, 1, 57920, 1, 57920, 1}, b = {64, 
226, 1, 0, 64, 226, 1, 0, 64, 226, 1, 
0, 64, 226, 1, 0}}
(gdb) 


Michael, this is a good pick for qemu-stable.

Daniel Henrique Barboza (1):
  riscv, gdbstub.c: fix reg_width in ricsv_gen_dynamic_vector_feature()

 target/riscv/gdbstub.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

-- 
2.44.0




[PATCH 1/1] riscv, gdbstub.c: fix reg_width in ricsv_gen_dynamic_vector_feature()

2024-05-16 Thread Daniel Henrique Barboza
Commit 33a24910ae changed 'reg_width' to use 'vlenb', i.e. vector length
in bytes, when in this context we want 'reg_width' as the length in
bits.

Fix 'reg_width' back to the value in bits like 7cb59921c05a
("target/riscv/gdbstub.c: use 'vlenb' instead of shifting 'vlen'") set
beforehand.

Cc: Akihiko Odaki 
Cc: Alex Bennée 
Reported-by: Robin Dapp 
Fixes: 33a24910ae ("target/riscv: Use GDBFeature for dynamic XML")
Signed-off-by: Daniel Henrique Barboza 
---
 target/riscv/gdbstub.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index d0cc5762c2..358158c42a 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -288,7 +288,7 @@ static GDBFeature *riscv_gen_dynamic_csr_feature(CPUState 
*cs, int base_reg)
 static GDBFeature *ricsv_gen_dynamic_vector_feature(CPUState *cs, int base_reg)
 {
 RISCVCPU *cpu = RISCV_CPU(cs);
-int reg_width = cpu->cfg.vlenb;
+int reg_width = cpu->cfg.vlenb << 3;
 GDBFeatureBuilder builder;
 int i;
 
-- 
2.44.0




Re: [PATCH v2 15/15] hw/misc: EDU: add ATS/PRI capability

2024-05-16 Thread Daniel Henrique Barboza

Hi Frank!

On 5/7/24 12:32, Frank Chang wrote:

Hi Daniel,

Daniel Henrique Barboza  於 2024年3月8日 週五 上午12:05寫道:


From: Tomasz Jeznach 

Mimic ATS interface with IOMMU translate request with IOMMU_NONE.  If
mapping exists, translation service will return current permission
flags, otherwise will report no permissions.

Implement and register the IOMMU memory region listener to be notified
whenever an ATS invalidation request is sent from the IOMMU.

Implement and register the IOMMU memory region listener to be notified
whenever an ATS page request group response is triggered from the IOMMU.

Introduces a retry mechanism to the timer design so that any page that's
not available should be only accessed after the PRGR notification has
been received.

Signed-off-by: Tomasz Jeznach 
Signed-off-by: Sebastien Boeuf 
---
  hw/misc/edu.c | 258 --
  1 file changed, 251 insertions(+), 7 deletions(-)


(...)



+
  static void pci_edu_realize(PCIDevice *pdev, Error **errp)
  {
  EduState *edu = EDU(pdev);
+AddressSpace *dma_as = NULL;
  uint8_t *pci_conf = pdev->config;
  int pos;

@@ -390,9 +603,28 @@ static void pci_edu_realize(PCIDevice *pdev, Error **errp)
  pos = PCI_CONFIG_SPACE_SIZE;
  if (edu->enable_pasid) {
  /* PCIe Spec 7.8.9 PASID Extended Capability Structure */
-pcie_add_capability(pdev, 0x1b, 1, pos, 8);
+pcie_add_capability(pdev, PCI_EXT_CAP_ID_PASID, 1, pos, 8);


This should be included in the 14th commit.


  pci_set_long(pdev->config + pos + 4, 0x1400);
  pci_set_long(pdev->wmask + pos + 4,  0xfff0);
+pos += 8;
+
+/* ATS Capability */
+pcie_ats_init(pdev, pos, true);
+pos += PCI_EXT_CAP_ATS_SIZEOF;
+
+/* PRI Capability */
+pcie_add_capability(pdev, PCI_EXT_CAP_ID_PRI, 1, pos, 16);
+/* PRI STOPPED */
+pci_set_long(pdev->config + pos +  4, 0x0100);
+/* PRI ENABLE bit writable */
+pci_set_long(pdev->wmask  + pos +  4, 0x0001);
+/* PRI Capacity Supported */
+pci_set_long(pdev->config + pos +  8, 0x0080);
+/* PRI Allocations Allowed, 32 */
+pci_set_long(pdev->config + pos + 12, 0x0040);
+pci_set_long(pdev->wmask  + pos + 12, 0x007f);


We should use the defines declared in
include/standard-headers/linux/pci_regs.h for readability,
though some of the bitfields are not defined in the header file.

Regards,
Frank Chang


+
+pos += 8;
  }


I'll reply here for both patches 14 and 15.

I changed it to use the defines we have in pci_regs.h if we have the definition
in the header. When we don't have the definition I ended up adding a manual
comment in the line like it's being done up above.

I'll also add doc changes for each new feature added.

All this said, I'm inclined to remove these 2 patches from the series. It's a
way of experiment with the riscv-iommu impl but it's not a crucial part of it.
The changes I made so far, based on your review, were uploaded here:


https://gitlab.com/danielhb/qemu/-/commits/edu_pasid_v3


Thanks,

Daniel




  if (msi_init(pdev, 0, 1, true, false, errp)) {
@@ -409,12 +641,24 @@ static void pci_edu_realize(PCIDevice *pdev, Error **errp)
  memory_region_init_io(>mmio, OBJECT(edu), _mmio_ops, edu,
  "edu-mmio", 1 * MiB);
  pci_register_bar(pdev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, >mmio);
+
+/* Register IOMMU listener */
+edu->iommu_listener = (MemoryListener) {
+.name = "edu-iommu",
+.region_add = edu_iommu_region_add,
+.region_del = edu_iommu_region_del,
+};
+
+dma_as = pci_device_iommu_address_space(pdev);
+memory_listener_register(>iommu_listener, dma_as);
  }

  static void pci_edu_uninit(PCIDevice *pdev)
  {
  EduState *edu = EDU(pdev);

+memory_listener_unregister(>iommu_listener);
+
  qemu_mutex_lock(>thr_mutex);
  edu->stopping = true;
  qemu_mutex_unlock(>thr_mutex);
--
2.43.2






Re: [PATCH v2 02/15] hw/riscv: add riscv-iommu-bits.h

2024-05-15 Thread Daniel Henrique Barboza




On 5/15/24 07:02, Eric Cheng wrote:

On 3/8/2024 12:03 AM, Daniel Henrique Barboza wrote:

From: Tomasz Jeznach 

This header will be used by the RISC-V IOMMU emulation to be added
in the next patch. Due to its size it's being sent in separate for
an easier review.

One thing to notice is that this header can be replaced by the future
Linux RISC-V IOMMU driver header, which would become a linux-header we
would import instead of keeping our own. The Linux implementation isn't
upstream yet so for now we'll have to manage riscv-iommu-bits.h.

Signed-off-by: Tomasz Jeznach 
Signed-off-by: Daniel Henrique Barboza 
---
  hw/riscv/riscv-iommu-bits.h | 335 
  1 file changed, 335 insertions(+)
  create mode 100644 hw/riscv/riscv-iommu-bits.h

diff --git a/hw/riscv/riscv-iommu-bits.h b/hw/riscv/riscv-iommu-bits.h
new file mode 100644
index 00..8e80b1e52a
--- /dev/null
+++ b/hw/riscv/riscv-iommu-bits.h
@@ -0,0 +1,335 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright © 2022-2023 Rivos Inc.
+ * Copyright © 2023 FORTH-ICS/CARV
+ * Copyright © 2023 RISC-V IOMMU Task Group
+ *
+ * RISC-V Ziommu - Register Layout and Data Structures.


Is there still the term Ziommu today? cannot be googled. May be just a 
transient term during spec development? it puzzles new comers.


Fair point. I'll remove any 'ziommu' references in all patches.


Thanks,

Daniel



+ *
+ * Based on the IOMMU spec version 1.0, 3/2023
+ * https://github.com/riscv-non-isa/riscv-iommu
+ */
+







Re: [PATCH v2 03/15] hw/riscv: add RISC-V IOMMU base emulation

2024-05-14 Thread Daniel Henrique Barboza

Hi Jason,

On 5/1/24 08:57, Jason Chien wrote:

Daniel Henrique Barboza 於 2024/3/8 上午 12:03 寫道:

From: Tomasz Jeznach

The RISC-V IOMMU specification is now ratified as-per the RISC-V
international process. The latest frozen specifcation can be found
at:

https://github.com/riscv-non-isa/riscv-iommu/releases/download/v1.0/riscv-iommu.pdf

Add the foundation of the device emulation for RISC-V IOMMU, which
includes an IOMMU that has no capabilities but MSI interrupt support and
fault queue interfaces. We'll add add more features incrementally in the
next patches.

Co-developed-by: Sebastien Boeuf
Signed-off-by: Sebastien Boeuf
Signed-off-by: Tomasz Jeznach
Signed-off-by: Daniel Henrique Barboza
---
  hw/riscv/Kconfig |4 +
  hw/riscv/meson.build |1 +
  hw/riscv/riscv-iommu.c   | 1492 ++
  hw/riscv/riscv-iommu.h   |  141 
  hw/riscv/trace-events|   11 +
  hw/riscv/trace.h |2 +
  include/hw/riscv/iommu.h |   36 +
  meson.build  |1 +
  8 files changed, 1688 insertions(+)
  create mode 100644 hw/riscv/riscv-iommu.c
  create mode 100644 hw/riscv/riscv-iommu.h
  create mode 100644 hw/riscv/trace-events
  create mode 100644 hw/riscv/trace.h
  create mode 100644 include/hw/riscv/iommu.h

diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
index 5d644eb7b1..faf6a10029 100644
--- a/hw/riscv/Kconfig
+++ b/hw/riscv/Kconfig
@@ -1,3 +1,6 @@
+config RISCV_IOMMU
+bool
+


(...)


+
+/* IOMMU index for transactions without PASID specified. */
+#define RISCV_IOMMU_NOPASID 0
+
+static void riscv_iommu_notify(RISCVIOMMUState *s, int vec)
+{
+const uint32_t ipsr =
+riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_IPSR, (1 << vec), 0);
+const uint32_t ivec = riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_IVEC);
+if (s->notify && !(ipsr & (1 << vec))) {
+s->notify(s, (ivec >> (vec * 4)) & 0x0F);
+}
+}

The RISC-V IOMMU also supports WSI.

+


I mentioned in the review with Frank that this impl does not support WSI, but
it really seems clearer to do the check here nevertheless. I'll add it.



+static void riscv_iommu_fault(RISCVIOMMUState *s,
+  struct riscv_iommu_fq_record *ev)
+{


(...)


+
+/*
+ * Check supported device id width (in bits).
+ * See IOMMU Specification, Chapter 6. Software guidelines.
+ * - if extended device-context format is used:
+ *   1LVL: 6, 2LVL: 15, 3LVL: 24
+ * - if base device-context format is used:
+ *   1LVL: 7, 2LVL: 16, 3LVL: 24
+ */
+if (ctx->devid >= (1 << (depth * 9 + 6 + (dc_fmt && depth != 2 {
+return RISCV_IOMMU_FQ_CAUSE_DDT_INVALID;


The cause should be 260 not 258.

 From the RISC-V IOMMU Architecture Spec v1.0.0 section 2.3:
If the device_id is wider than that supported by the IOMMU mode, as determined by the 
following checks then stop and report "Transaction type disallowed" (cause = 
260).
a. ddtp.iommu_mode is 2LVL and DDI[2] is not 0
b. ddtp.iommu_mode is 1LVL and either DDI[2] is not 0 or DDI[1] is not 0



Changed.


+}
+
+/* Device directory tree walk */
+for (; depth-- > 0; ) {
+/*
+ * Select device id index bits based on device directory tree level
+ * and device context format.
+ * See IOMMU Specification, Chapter 2. Data Structures.
+ * - if extended device-context format is used:
+ *   device index: [23:15][14:6][5:0]
+ * - if base device-context format is used:
+ *   device index: [23:16][15:7][6:0]
+ */
+const int split = depth * 9 + 6 + dc_fmt;
+addr |= ((ctx->devid >> split) << 3) & ~TARGET_PAGE_MASK;
+if (dma_memory_read(s->target_as, addr, , sizeof(de),
+MEMTXATTRS_UNSPECIFIED) != MEMTX_OK) {
+return RISCV_IOMMU_FQ_CAUSE_DDT_LOAD_FAULT;
+}
+le64_to_cpus();
+if (!(de & RISCV_IOMMU_DDTE_VALID)) {
+/* invalid directory entry */
+return RISCV_IOMMU_FQ_CAUSE_DDT_INVALID;
+}
+if (de & ~(RISCV_IOMMU_DDTE_PPN | RISCV_IOMMU_DDTE_VALID)) {
+/* reserved bits set */
+return RISCV_IOMMU_FQ_CAUSE_DDT_INVALID;


The cause should be 259 not 258.

 From RISC-V IOMMU Architecture Spec v1.0.0 section 2.3.1:
If any bits or encoding that are reserved for future standard use are set within ddte, 
stop and report "DDT entry misconfigured" (cause = 259).


Changed




+}
+addr = PPN_PHYS(get_field(de, RISCV_IOMMU_DDTE_PPN));
+}
+
+/* index into device context entry page */
+addr |= (ctx->devid * dc_len) & ~TARGET_PAGE_MASK;
+
+memset(, 0, sizeof(dc));
+if (dma_memory_read(s->target_as, addr, , dc_len,
+MEMTXATTRS_UNSPECIFIED) != MEMTX_OK) {
+return RISCV_IOMMU_FQ_CAUSE_DDT_LOAD_FAULT;

Re: [PATCH v2] target/riscv: Remove experimental prefix from "B" extension

2024-05-14 Thread Daniel Henrique Barboza




On 5/14/24 08:02, Rob Bradford wrote:

This extension has now been ratified:
https://jira.riscv.org/browse/RVS-2006 so the "x-" prefix can be
removed.

Since this is now a ratified extension add it to the list of extensions
included in the "max" CPU variant.

Signed-off-by: Rob Bradford 
Reviewed-by: Andrew Jones 
---


Reviewed-by: Daniel Henrique Barboza 


  target/riscv/cpu.c | 2 +-
  target/riscv/tcg/tcg-cpu.c | 2 +-
  2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index eb1a2e7d6d..861d9f4350 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1396,7 +1396,7 @@ static const MISAExtInfo misa_ext_info_arr[] = {
  MISA_EXT_INFO(RVJ, "x-j", "Dynamic translated languages"),
  MISA_EXT_INFO(RVV, "v", "Vector operations"),
  MISA_EXT_INFO(RVG, "g", "General purpose (IMAFD_Zicsr_Zifencei)"),
-MISA_EXT_INFO(RVB, "x-b", "Bit manipulation (Zba_Zbb_Zbs)")
+MISA_EXT_INFO(RVB, "b", "Bit manipulation (Zba_Zbb_Zbs)")
  };
  
  static void riscv_cpu_validate_misa_mxl(RISCVCPUClass *mcc)

diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index 40054a391a..164a13ad0f 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -1281,7 +1281,7 @@ static void riscv_init_max_cpu_extensions(Object *obj)
  const RISCVCPUMultiExtConfig *prop;
  
  /* Enable RVG, RVJ and RVV that are disabled by default */

-riscv_cpu_set_misa_ext(env, env->misa_ext | RVG | RVJ | RVV);
+riscv_cpu_set_misa_ext(env, env->misa_ext | RVB | RVG | RVJ | RVV);
  
  for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {

  isa_ext_update_enabled(cpu, prop->offset, true);




Re: [PATCH] target/riscv: rvzicbo: Fixup CBO extension register calculation

2024-05-14 Thread Daniel Henrique Barboza




On 5/13/24 23:39, Alistair Francis wrote:

When running the instruction

```
 cbo.flush 0(x0)
```

QEMU would segfault.

The issue was in cpu_gpr[a->rs1] as QEMU does not have cpu_gpr[0]
allocated.

In order to fix this let's use the existing get_address()
helper. This also has the benefit of performing pointer mask
calculations on the address specified in rs1.

The pointer masking specificiation specifically states:

"""
Cache Management Operations: All instructions in Zicbom, Zicbop and Zicboz
"""

So this is the correct behaviour and we previously have been incorrectly
not masking the address.

Signed-off-by: Alistair Francis 
Reported-by: Fabian Thomas 
Fixes: e05da09b7cfd ("target/riscv: implement Zicbom extension")
---


LGTM but I wonder if this is the same fix as this one sent by Phil a month
ago or so:

https://lore.kernel.org/qemu-riscv/20240419110514.69697-1-phi...@linaro.org/
("[PATCH] target/riscv: Use get_address() to get address with Zicbom 
extensions")


Thanks,

Daniel


  target/riscv/insn_trans/trans_rvzicbo.c.inc | 16 
  1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/target/riscv/insn_trans/trans_rvzicbo.c.inc 
b/target/riscv/insn_trans/trans_rvzicbo.c.inc
index d5d7095903..15711c3140 100644
--- a/target/riscv/insn_trans/trans_rvzicbo.c.inc
+++ b/target/riscv/insn_trans/trans_rvzicbo.c.inc
@@ -31,27 +31,35 @@
  static bool trans_cbo_clean(DisasContext *ctx, arg_cbo_clean *a)
  {
  REQUIRE_ZICBOM(ctx);
-gen_helper_cbo_clean_flush(tcg_env, cpu_gpr[a->rs1]);
+TCGv src = get_address(ctx, a->rs1, 0);
+
+gen_helper_cbo_clean_flush(tcg_env, src);
  return true;
  }
  
  static bool trans_cbo_flush(DisasContext *ctx, arg_cbo_flush *a)

  {
  REQUIRE_ZICBOM(ctx);
-gen_helper_cbo_clean_flush(tcg_env, cpu_gpr[a->rs1]);
+TCGv src = get_address(ctx, a->rs1, 0);
+
+gen_helper_cbo_clean_flush(tcg_env, src);
  return true;
  }
  
  static bool trans_cbo_inval(DisasContext *ctx, arg_cbo_inval *a)

  {
  REQUIRE_ZICBOM(ctx);
-gen_helper_cbo_inval(tcg_env, cpu_gpr[a->rs1]);
+TCGv src = get_address(ctx, a->rs1, 0);
+
+gen_helper_cbo_inval(tcg_env, src);
  return true;
  }
  
  static bool trans_cbo_zero(DisasContext *ctx, arg_cbo_zero *a)

  {
  REQUIRE_ZICBOZ(ctx);
-gen_helper_cbo_zero(tcg_env, cpu_gpr[a->rs1]);
+TCGv src = get_address(ctx, a->rs1, 0);
+
+gen_helper_cbo_zero(tcg_env, src);
  return true;
  }




Re: [PATCH v2 03/15] hw/riscv: add RISC-V IOMMU base emulation

2024-05-13 Thread Daniel Henrique Barboza

Hi Frank,

On 5/10/24 07:58, Frank Chang wrote:

Hi Daniel,

Daniel Henrique Barboza  於 2024年5月8日 週三 下午7:16寫道:


Hi Frank,

I'll reply with that I've done so far. Still missing some stuff:

On 5/2/24 08:37, Frank Chang wrote:

Hi Daniel,

Daniel Henrique Barboza  於 2024年3月8日 週五 上午12:04寫道:



(...)



In our experience, using QEMU thread increases the latency of command
queue processing,
which leads to the potential IOMMU fence timeout in the Linux driver
when using IOMMU with KVM,
e.g. booting the guest Linux.

Is it possible to remove the thread from the IOMMU just like ARM, AMD,
and Intel IOMMU models?


Interesting. We've been using this emulation internally in Ventana, with
KVM and VFIO, and didn't experience this issue. Drew is on CC and can talk
more about it.


We've developed IOFENCE timeout detection mechanism in our Linux
driver internally
to detect the long-run IOFENCE command on the hardware.

However, we hit the assertion when running on QEMU
and the issue was resolved after we removed the thread from IOMMU model.
However, the assertion didn't happen on our hardware.

Regards,
Frank CHang



I see. Well, one more reason to remove the threading for v3 then. I removed it 
and
it seems to be working as usual in my tests, i.e. no perceptible performance or
behavior impacts. Thanks,


Daniel






That said, I don't mind this change, assuming it's feasible to make it for this
first version.  I'll need to check it how other IOMMUs are doing it.






+}
+


(...)


+
+static AddressSpace *riscv_iommu_find_as(PCIBus *bus, void *opaque, int devfn)
+{
+RISCVIOMMUState *s = (RISCVIOMMUState *) opaque;
+PCIDevice *pdev = pci_find_device(bus, pci_bus_num(bus), devfn);
+AddressSpace *as = NULL;
+
+if (pdev && pci_is_iommu(pdev)) {
+return s->target_as;
+}
+
+/* Find first registered IOMMU device */
+while (s->iommus.le_prev) {
+s = *(s->iommus.le_prev);
+}
+
+/* Find first matching IOMMU */
+while (s != NULL && as == NULL) {
+as = riscv_iommu_space(s, PCI_BUILD_BDF(pci_bus_num(bus), devfn));


For pci_bus_num(),
riscv_iommu_find_as() can be called at the very early stage
where software has no chance to enumerate the bus numbers.


I'll see how other IOMMUs are handling their iommu_find_as()


Thanks,


Daniel








+s = s->iommus.le_next;
+}
+
+return as ? as : _space_memory;
+}
+
+static const PCIIOMMUOps riscv_iommu_ops = {
+.get_address_space = riscv_iommu_find_as,
+};
+
+void riscv_iommu_pci_setup_iommu(RISCVIOMMUState *iommu, PCIBus *bus,
+Error **errp)
+{
+if (bus->iommu_ops &&
+bus->iommu_ops->get_address_space == riscv_iommu_find_as) {
+/* Allow multiple IOMMUs on the same PCIe bus, link known devices */
+RISCVIOMMUState *last = (RISCVIOMMUState *)bus->iommu_opaque;
+QLIST_INSERT_AFTER(last, iommu, iommus);
+} else if (bus->iommu_ops == NULL) {
+pci_setup_iommu(bus, _iommu_ops, iommu);
+} else {
+error_setg(errp, "can't register secondary IOMMU for PCI bus #%d",
+pci_bus_num(bus));
+}
+}
+
+static int riscv_iommu_memory_region_index(IOMMUMemoryRegion *iommu_mr,
+MemTxAttrs attrs)
+{
+return attrs.unspecified ? RISCV_IOMMU_NOPASID : (int)attrs.pasid;
+}
+
+static int riscv_iommu_memory_region_index_len(IOMMUMemoryRegion *iommu_mr)
+{
+RISCVIOMMUSpace *as = container_of(iommu_mr, RISCVIOMMUSpace, iova_mr);
+return 1 << as->iommu->pasid_bits;
+}
+
+static void riscv_iommu_memory_region_init(ObjectClass *klass, void *data)
+{
+IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
+
+imrc->translate = riscv_iommu_memory_region_translate;
+imrc->notify_flag_changed = riscv_iommu_memory_region_notify;
+imrc->attrs_to_index = riscv_iommu_memory_region_index;
+imrc->num_indexes = riscv_iommu_memory_region_index_len;
+}
+
+static const TypeInfo riscv_iommu_memory_region_info = {
+.parent = TYPE_IOMMU_MEMORY_REGION,
+.name = TYPE_RISCV_IOMMU_MEMORY_REGION,
+.class_init = riscv_iommu_memory_region_init,
+};
+
+static void riscv_iommu_register_mr_types(void)
+{
+type_register_static(_iommu_memory_region_info);
+type_register_static(_iommu_info);
+}
+
+type_init(riscv_iommu_register_mr_types);
diff --git a/hw/riscv/riscv-iommu.h b/hw/riscv/riscv-iommu.h
new file mode 100644
index 00..6f740de690
--- /dev/null
+++ b/hw/riscv/riscv-iommu.h
@@ -0,0 +1,141 @@
+/*
+ * QEMU emulation of an RISC-V IOMMU (Ziommu)
+ *
+ * Copyright (C) 2022-2023 Rivos Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied 

Re: [PATCH v2 03/15] hw/riscv: add RISC-V IOMMU base emulation

2024-05-13 Thread Daniel Henrique Barboza

Hi Frank,


On 5/8/24 08:15, Daniel Henrique Barboza wrote:

Hi Frank,

I'll reply with that I've done so far. Still missing some stuff:

On 5/2/24 08:37, Frank Chang wrote:

Hi Daniel,

Daniel Henrique Barboza  於 2024年3月8日 週五 上午12:04寫道:


From: Tomasz Jeznach 

The RISC-V IOMMU specification is now ratified as-per the RISC-V
international process. The latest frozen specifcation can be found
at:

https://github.com/riscv-non-isa/riscv-iommu/releases/download/v1.0/riscv-iommu.pdf

Add the foundation of the device emulation for RISC-V IOMMU, which
includes an IOMMU that has no capabilities but MSI interrupt support and
fault queue interfaces. We'll add add more features incrementally in the
next patches.

Co-developed-by: Sebastien Boeuf 
Signed-off-by: Sebastien Boeuf 
Signed-off-by: Tomasz Jeznach 
Signed-off-by: Daniel Henrique Barboza 
---
  hw/riscv/Kconfig |    4 +


(...)


+
+    s->iommus.le_next = NULL;
+    s->iommus.le_prev = NULL;
+    QLIST_INIT(>spaces);
+    qemu_cond_init(>core_cond);
+    qemu_mutex_init(>core_lock);
+    qemu_spin_init(>regs_lock);
+    qemu_thread_create(>core_proc, "riscv-iommu-core",
+    riscv_iommu_core_proc, s, QEMU_THREAD_JOINABLE);


In our experience, using QEMU thread increases the latency of command
queue processing,
which leads to the potential IOMMU fence timeout in the Linux driver
when using IOMMU with KVM,
e.g. booting the guest Linux.

Is it possible to remove the thread from the IOMMU just like ARM, AMD,
and Intel IOMMU models?


Interesting. We've been using this emulation internally in Ventana, with
KVM and VFIO, and didn't experience this issue. Drew is on CC and can talk
more about it.

That said, I don't mind this change, assuming it's feasible to make it for this
first version.  I'll need to check it how other IOMMUs are doing it.



I removed the threading and it seems to be working fine without it. I'll commit 
this
change for v3.








+}
+


(...)


+
+static AddressSpace *riscv_iommu_find_as(PCIBus *bus, void *opaque, int devfn)
+{
+    RISCVIOMMUState *s = (RISCVIOMMUState *) opaque;
+    PCIDevice *pdev = pci_find_device(bus, pci_bus_num(bus), devfn);
+    AddressSpace *as = NULL;
+
+    if (pdev && pci_is_iommu(pdev)) {
+    return s->target_as;
+    }
+
+    /* Find first registered IOMMU device */
+    while (s->iommus.le_prev) {
+    s = *(s->iommus.le_prev);
+    }
+
+    /* Find first matching IOMMU */
+    while (s != NULL && as == NULL) {
+    as = riscv_iommu_space(s, PCI_BUILD_BDF(pci_bus_num(bus), devfn));


For pci_bus_num(),
riscv_iommu_find_as() can be called at the very early stage
where software has no chance to enumerate the bus numbers.


I investigated and this doesn't seem to be a problem. This function is called 
at the
last step of the realize() steps of both riscv_iommu_pci_realize() and
riscv_iommu_sys_realize(), and by that time the pci_bus_num() is already 
assigned.
Other iommus use pci_bus_num() into their own get_address_space() callbacks like
this too.


Thanks,


Daniel




I'll see how other IOMMUs are handling their iommu_find_as()


Thanks,


Daniel








+    s = s->iommus.le_next;
+    }
+
+    return as ? as : _space_memory;
+}
+
+static const PCIIOMMUOps riscv_iommu_ops = {
+    .get_address_space = riscv_iommu_find_as,
+};
+
+void riscv_iommu_pci_setup_iommu(RISCVIOMMUState *iommu, PCIBus *bus,
+    Error **errp)
+{
+    if (bus->iommu_ops &&
+    bus->iommu_ops->get_address_space == riscv_iommu_find_as) {
+    /* Allow multiple IOMMUs on the same PCIe bus, link known devices */
+    RISCVIOMMUState *last = (RISCVIOMMUState *)bus->iommu_opaque;
+    QLIST_INSERT_AFTER(last, iommu, iommus);
+    } else if (bus->iommu_ops == NULL) {
+    pci_setup_iommu(bus, _iommu_ops, iommu);
+    } else {
+    error_setg(errp, "can't register secondary IOMMU for PCI bus #%d",
+    pci_bus_num(bus));
+    }
+}
+
+static int riscv_iommu_memory_region_index(IOMMUMemoryRegion *iommu_mr,
+    MemTxAttrs attrs)
+{
+    return attrs.unspecified ? RISCV_IOMMU_NOPASID : (int)attrs.pasid;
+}
+
+static int riscv_iommu_memory_region_index_len(IOMMUMemoryRegion *iommu_mr)
+{
+    RISCVIOMMUSpace *as = container_of(iommu_mr, RISCVIOMMUSpace, iova_mr);
+    return 1 << as->iommu->pasid_bits;
+}
+
+static void riscv_iommu_memory_region_init(ObjectClass *klass, void *data)
+{
+    IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
+
+    imrc->translate = riscv_iommu_memory_region_translate;
+    imrc->notify_flag_changed = riscv_iommu_memory_region_notify;
+    imrc->attrs_to_index = riscv_iommu_memory_region_index;
+    imrc->num_indexes = riscv_iommu_memory_region_index_len;
+}
+
+static const TypeInfo riscv_iommu_memory_region_info = {
+    .parent = TYPE_IOMMU_MEMORY_REGION,
+    .name = TYPE_RISCV_IOMMU_MEM

Re: [PATCH RESEND] target/riscv/cpu.c: fix Zvkb extension config

2024-05-13 Thread Daniel Henrique Barboza




On 5/11/24 08:26, Yangyu Chen wrote:

This code has a typo that writes zvkb to zvkg, causing users can't
enable zvkb through the config. This patch gets this fixed.


My bad!





Signed-off-by: Yangyu Chen 
Fixes: ea61ef7097d0 ("target/riscv: Move vector crypto extensions to 
riscv_cpu_extensions")
Reviewed-by: LIU Zhiwei 
---



Reviewed-by: Daniel Henrique Barboza 


Michael, here's another one for stable.


Thanks,


Daniel


  target/riscv/cpu.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index eb1a2e7d6d..13cd34adbd 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1535,7 +1535,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
  /* Vector cryptography extensions */
  MULTI_EXT_CFG_BOOL("zvbb", ext_zvbb, false),
  MULTI_EXT_CFG_BOOL("zvbc", ext_zvbc, false),
-MULTI_EXT_CFG_BOOL("zvkb", ext_zvkg, false),
+MULTI_EXT_CFG_BOOL("zvkb", ext_zvkb, false),
  MULTI_EXT_CFG_BOOL("zvkg", ext_zvkg, false),
  MULTI_EXT_CFG_BOOL("zvkned", ext_zvkned, false),
  MULTI_EXT_CFG_BOOL("zvknha", ext_zvknha, false),




Re: [PATCH] target/riscv: Remove experimental prefix from "B" extension

2024-05-10 Thread Daniel Henrique Barboza




On 5/10/24 05:29, Andrew Jones wrote:

On Thu, May 09, 2024 at 02:23:42PM GMT, Daniel Henrique Barboza wrote:



On 5/8/24 08:22, Andrew Jones wrote:

On Tue, May 07, 2024 at 11:27:21AM GMT, Rob Bradford wrote:

This extension has now been ratified:
https://jira.riscv.org/browse/RVS-2006 so the "x-" prefix can be
removed.

Signed-off-by: Rob Bradford 
---
   target/riscv/cpu.c | 2 +-
   1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index eb1a2e7d6d..861d9f4350 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1396,7 +1396,7 @@ static const MISAExtInfo misa_ext_info_arr[] = {
   MISA_EXT_INFO(RVJ, "x-j", "Dynamic translated languages"),
   MISA_EXT_INFO(RVV, "v", "Vector operations"),
   MISA_EXT_INFO(RVG, "g", "General purpose (IMAFD_Zicsr_Zifencei)"),
-MISA_EXT_INFO(RVB, "x-b", "Bit manipulation (Zba_Zbb_Zbs)")
+MISA_EXT_INFO(RVB, "b", "Bit manipulation (Zba_Zbb_Zbs)")
   };
   static void riscv_cpu_validate_misa_mxl(RISCVCPUClass *mcc)
--
2.44.0




Reviewed-by: Andrew Jones 

I think we should also either change the false to true for RVB in
misa_ext_cfgs[] or at least ensure RVB is set for the 'max' cpu
type in riscv_init_max_cpu_extensions().


I prefer if we keep misa_ext_cfgs[] as is. Changing the defaults in this array
will also change the defaults for rv64. IMO we should enable RVB manually in
riscv_init_max_cpu_extensions().

We already have some precedence for it: RVV is enabled in 'max' while is default
'false' for rv64.


But do we care if rv64 gets B? rv64 doesn't have any particular set of
extensions, afaik. And B seems like it should be generally adopted enough
to be in a "general" cpu type like rv64. Anyway, either way works for me
as long as 'max' gets B one way or another.


Yes, as long as we enable it in 'max' it's good enough for this patch.

It's not like we're enabling extensions in rv64 just because they were ratified
(e.g. RVV isn't enabled in rv64), so even if we want to enable RVB in rv64 I'd
rather do it in a separated patch with a proper justification.


Thanks,

Daniel



Thanks,
drew




Re: [PATCH] target/riscv: Remove experimental prefix from "B" extension

2024-05-09 Thread Daniel Henrique Barboza




On 5/8/24 08:22, Andrew Jones wrote:

On Tue, May 07, 2024 at 11:27:21AM GMT, Rob Bradford wrote:

This extension has now been ratified:
https://jira.riscv.org/browse/RVS-2006 so the "x-" prefix can be
removed.

Signed-off-by: Rob Bradford 
---
  target/riscv/cpu.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index eb1a2e7d6d..861d9f4350 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1396,7 +1396,7 @@ static const MISAExtInfo misa_ext_info_arr[] = {
  MISA_EXT_INFO(RVJ, "x-j", "Dynamic translated languages"),
  MISA_EXT_INFO(RVV, "v", "Vector operations"),
  MISA_EXT_INFO(RVG, "g", "General purpose (IMAFD_Zicsr_Zifencei)"),
-MISA_EXT_INFO(RVB, "x-b", "Bit manipulation (Zba_Zbb_Zbs)")
+MISA_EXT_INFO(RVB, "b", "Bit manipulation (Zba_Zbb_Zbs)")
  };
  
  static void riscv_cpu_validate_misa_mxl(RISCVCPUClass *mcc)

--
2.44.0




Reviewed-by: Andrew Jones 

I think we should also either change the false to true for RVB in
misa_ext_cfgs[] or at least ensure RVB is set for the 'max' cpu
type in riscv_init_max_cpu_extensions().


I prefer if we keep misa_ext_cfgs[] as is. Changing the defaults in this array
will also change the defaults for rv64. IMO we should enable RVB manually in
riscv_init_max_cpu_extensions().

We already have some precedence for it: RVV is enabled in 'max' while is default
'false' for rv64.


Thanks,

Daniel




Thanks,
drew




Re: [RFC PATCH 0/1] pci: allocate a PCI ID for RISC-V IOMMU

2024-05-08 Thread Daniel Henrique Barboza




On 5/7/24 12:44, Peter Maydell wrote:

On Fri, 3 May 2024 at 13:43, Daniel Henrique Barboza
 wrote:


Hi,

In this RFC I want to check with Gerd and others if it's ok to add a PCI
id for the RISC-V IOMMU device. It's currently under review in [1]. The
idea is to fold this patch into the RISC-V IOMMU series if we're all ok
with this change.


My question here would be "why is this risc-v specific?" (and more
generally "what is this for?" -- the cover letter and patch and
documentation page provide almost no information about what this
device is and why it needs to exist rather than using either
virtio-iommu or else a model of a real hardware IOMMU.)


The RISC-V IOMMU device emulation under review ([1]) is a reference 
implementation of
the riscv-iommu spec [2]. AFAIK it is similar to what we already have with 
aarch64 'smmuv3'
'virt' bus, i.e. an impl of ARM's SMMUv3 that isn't tied to a specific vendor.

The difference here is that the riscv-iommu spec, ratified by RISC-V 
International (RVI),
predicts that the device could be implemented as a PCIe device. But RVI didn't 
bother
assigning a PCI ID for their reference IOMMU. The existing implementation in 
[1] is using
a Rivos PCI ID that we're treating as a placeholder only. We need an ID that 
reflects that
this is a device that adheres to the riscv-iommu spec, not to an IOMMU of any 
particular
vendor.

Since RVI doesn't provide a PCI ID for it we went to Red Hat, and they were 
kind enough
to give us a PCI ID for the RISC-V IOMMU reference device.

I'll do a proper job this time and add all this context in the commit msg. 
Including a
proper shout-out to Gerd and Red Hat.



Thanks,


Daniel


[1] 
https://lore.kernel.org/qemu-riscv/20240307160319.675044-1-dbarb...@ventanamicro.com/
[2] https://github.com/riscv-non-isa/riscv-iommu/releases/tag/v1.0.0



thanks
-- PMM




Re: [RFC PATCH 0/1] pci: allocate a PCI ID for RISC-V IOMMU

2024-05-08 Thread Daniel Henrique Barboza




On 5/7/24 12:53, Gerd Hoffmann wrote:

On Tue, May 07, 2024 at 11:37:05PM GMT, Frank Chang wrote:

Hi Daniel,

Daniel Henrique Barboza  於 2024年5月3日 週五 下午8:43寫道:


Hi,

In this RFC I want to check with Gerd and others if it's ok to add a PCI
id for the RISC-V IOMMU device. It's currently under review in [1]. The


Is the link [1] missing?


Yes ;)

Also:  A bit more background on the iommu would be great, for example a
pointer to the specification.


Fair enough. I'll add a pointer to the latest version of the spec:


https://github.com/riscv-non-isa/riscv-iommu/releases/tag/v1.0.0



Thanks,

Daniel



take care,
   Gerd





Re: [RFC PATCH 0/1] pci: allocate a PCI ID for RISC-V IOMMU

2024-05-08 Thread Daniel Henrique Barboza




On 5/7/24 12:37, Frank Chang wrote:

Hi Daniel,

Daniel Henrique Barboza  於 2024年5月3日 週五 下午8:43寫道:


Hi,

In this RFC I want to check with Gerd and others if it's ok to add a PCI
id for the RISC-V IOMMU device. It's currently under review in [1]. The


Is the link [1] missing?


Ooops. Here's the link:


[1] 
https://lore.kernel.org/qemu-riscv/20240307160319.675044-1-dbarb...@ventanamicro.com/


Thanks,

Daniel



Regards,
Frank Chang


idea is to fold this patch into the RISC-V IOMMU series if we're all ok
with this change.

Gerd, we picked the ID right after the PCI UFS device. Let me know if
you want another ID instead.


Daniel Henrique Barboza (1):
   pci-ids.rst: add Red Hat pci-id for generic IOMMU device

  docs/specs/pci-ids.rst | 2 ++
  include/hw/pci/pci.h   | 1 +
  2 files changed, 3 insertions(+)

--
2.44.0






Re: [PATCH v2 03/15] hw/riscv: add RISC-V IOMMU base emulation

2024-05-08 Thread Daniel Henrique Barboza

Hi Frank,

I'll reply with that I've done so far. Still missing some stuff:

On 5/2/24 08:37, Frank Chang wrote:

Hi Daniel,

Daniel Henrique Barboza  於 2024年3月8日 週五 上午12:04寫道:


From: Tomasz Jeznach 

The RISC-V IOMMU specification is now ratified as-per the RISC-V
international process. The latest frozen specifcation can be found
at:

https://github.com/riscv-non-isa/riscv-iommu/releases/download/v1.0/riscv-iommu.pdf

Add the foundation of the device emulation for RISC-V IOMMU, which
includes an IOMMU that has no capabilities but MSI interrupt support and
fault queue interfaces. We'll add add more features incrementally in the
next patches.

Co-developed-by: Sebastien Boeuf 
Signed-off-by: Sebastien Boeuf 
Signed-off-by: Tomasz Jeznach 
Signed-off-by: Daniel Henrique Barboza 
---
  hw/riscv/Kconfig |4 +
  hw/riscv/meson.build |1 +
  hw/riscv/riscv-iommu.c   | 1492 ++
  hw/riscv/riscv-iommu.h   |  141 
  hw/riscv/trace-events|   11 +
  hw/riscv/trace.h |2 +
  include/hw/riscv/iommu.h |   36 +
  meson.build  |1 +
  8 files changed, 1688 insertions(+)
  create mode 100644 hw/riscv/riscv-iommu.c
  create mode 100644 hw/riscv/riscv-iommu.h
  create mode 100644 hw/riscv/trace-events
  create mode 100644 hw/riscv/trace.h
  create mode 100644 include/hw/riscv/iommu.h



(...)

+{

+const uint32_t ipsr =
+riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_IPSR, (1 << vec), 0);
+const uint32_t ivec = riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_IVEC);
+if (s->notify && !(ipsr & (1 << vec))) {
+s->notify(s, (ivec >> (vec * 4)) & 0x0F);
+}


s->notify is assigned to riscv_iommu_pci_notify() only.
There's no way to assert the wire-signaled interrupt.

We should also check fctl.WSI before asserting the interrupt.



This implementation does not support wire-signalled interrupts. It supports only
MSI, i.e. capabililities.IGS is always MSI (0). For this reason the code is also
not checking for fctl.WSI.




+}

 (...)


+g_hash_table_unref(ctx_cache);
+*ref = NULL;
+
+if (!(ctx->tc & RISCV_IOMMU_DC_TC_DTF)) {


riscv_iommu_ctx_fetch() may return:
RISCV_IOMMU_FQ_CAUSE_DMA_DISABLED (256)
RISCV_IOMMU_FQ_CAUSE_DDT_LOAD_FAULT (257)
RISCV_IOMMU_FQ_CAUSE_DDT_INVALID (258)
RISCV_IOMMU_FQ_CAUSE_DDT_MISCONFIGURED (259)

These faults are reported even when DTF is set to 1.
We should report these faults regardless of DTF setting.



I created a "riscv_iommu_report_fault()" helper to centralize all the report 
fault
logic. This helper will check for DTF and, if set, we'll check the 'cause' to 
see if
we still want the fault to be reported or not. This helper is then used in 
these 2
instances where we're creating a fault by hand. It's also used extensively in
riscv_iommu_msi_write() to handle all the cases you mentioned above where we
weren't issuing faults.





+struct riscv_iommu_fq_record ev = { 0 };
+ev.hdr = set_field(ev.hdr, RISCV_IOMMU_FQ_HDR_CAUSE, fault);
+ev.hdr = set_field(ev.hdr, RISCV_IOMMU_FQ_HDR_TTYPE,
+RISCV_IOMMU_FQ_TTYPE_UADDR_RD);
+ev.hdr = set_field(ev.hdr, RISCV_IOMMU_FQ_HDR_DID, devid);
+ev.hdr = set_field(ev.hdr, RISCV_IOMMU_FQ_HDR_PID, pasid);
+ev.hdr = set_field(ev.hdr, RISCV_IOMMU_FQ_HDR_PV, !!pasid);
+riscv_iommu_fault(s, );
+}
+
+g_free(ctx);
+return NULL;
+}
+
+static void riscv_iommu_ctx_put(RISCVIOMMUState *s, void *ref)
+{
+if (ref) {
+g_hash_table_unref((GHashTable *)ref);
+}
+}
+
+/* Find or allocate address space for a given device */
+static AddressSpace *riscv_iommu_space(RISCVIOMMUState *s, uint32_t devid)
+{
+RISCVIOMMUSpace *as;
+
+/* FIXME: PCIe bus remapping for attached endpoints. */
+devid |= s->bus << 8;
+
+qemu_mutex_lock(>core_lock);
+QLIST_FOREACH(as, >spaces, list) {
+if (as->devid == devid) {
+break;
+}
+}
+qemu_mutex_unlock(>core_lock);
+
+if (as == NULL) {
+char name[64];
+as = g_new0(RISCVIOMMUSpace, 1);
+
+as->iommu = s;
+as->devid = devid;
+
+snprintf(name, sizeof(name), "riscv-iommu-%04x:%02x.%d-iova",
+PCI_BUS_NUM(as->devid), PCI_SLOT(as->devid), PCI_FUNC(as->devid));
+
+/* IOVA address space, untranslated addresses */
+memory_region_init_iommu(>iova_mr, sizeof(as->iova_mr),
+TYPE_RISCV_IOMMU_MEMORY_REGION,
+OBJECT(as), name, UINT64_MAX);
+address_space_init(>iova_as, MEMORY_REGION(>iova_mr),
+TYPE_RISCV_IOMMU_PCI);


Why do we use TYPE_RISCV_IOMMU_PCI as the address space name here?



This is an error. TYPE_RISCV_IOMMU_PCI is the name of the PCI IOMMU device.

Seeing other iommus in QEMU it seems like the name of memory region is a simple
string, e.g. "amd_iomm

Re: [PATCH v2 11/15] hw/riscv/riscv-iommu: add DBG support

2024-05-06 Thread Daniel Henrique Barboza

Hi Frank,

On 5/6/24 01:09, Frank Chang wrote:

Hi Daniel,

Daniel Henrique Barboza  於 2024年3月8日 週五 上午12:05寫道:


From: Tomasz Jeznach 

DBG support adds three additional registers: tr_req_iova, tr_req_ctl and
tr_response.

The DBG cap is always enabled. No on/off toggle is provided for it.

Signed-off-by: Tomasz Jeznach 
Signed-off-by: Daniel Henrique Barboza 
---
  hw/riscv/riscv-iommu-bits.h | 20 +
  hw/riscv/riscv-iommu.c  | 57 -
  2 files changed, 76 insertions(+), 1 deletion(-)

diff --git a/hw/riscv/riscv-iommu-bits.h b/hw/riscv/riscv-iommu-bits.h
index 0994f5ce48..b3f92411bb 100644
--- a/hw/riscv/riscv-iommu-bits.h
+++ b/hw/riscv/riscv-iommu-bits.h
@@ -83,6 +83,7 @@ struct riscv_iommu_pq_record {
  #define RISCV_IOMMU_CAP_MSI_MRIFBIT_ULL(23)
  #define RISCV_IOMMU_CAP_ATS BIT_ULL(25)
  #define RISCV_IOMMU_CAP_IGS GENMASK_ULL(29, 28)
+#define RISCV_IOMMU_CAP_DBG BIT_ULL(31)
  #define RISCV_IOMMU_CAP_PAS GENMASK_ULL(37, 32)
  #define RISCV_IOMMU_CAP_PD8 BIT_ULL(38)

@@ -177,6 +178,25 @@ enum {
  RISCV_IOMMU_INTR_COUNT
  };

+#define RISCV_IOMMU_IPSR_CIPBIT(RISCV_IOMMU_INTR_CQ)
+#define RISCV_IOMMU_IPSR_FIPBIT(RISCV_IOMMU_INTR_FQ)
+#define RISCV_IOMMU_IPSR_PMIP   BIT(RISCV_IOMMU_INTR_PM)
+#define RISCV_IOMMU_IPSR_PIPBIT(RISCV_IOMMU_INTR_PQ)


These are not related to the DBG.


+
+/* 5.24 Translation request IOVA (64bits) */
+#define RISCV_IOMMU_REG_TR_REQ_IOVA 0x0258
+
+/* 5.25 Translation request control (64bits) */
+#define RISCV_IOMMU_REG_TR_REQ_CTL  0x0260
+#define RISCV_IOMMU_TR_REQ_CTL_GO_BUSY  BIT_ULL(0)
+#define RISCV_IOMMU_TR_REQ_CTL_PID  GENMASK_ULL(31, 12)
+#define RISCV_IOMMU_TR_REQ_CTL_DID  GENMASK_ULL(63, 40)
+
+/* 5.26 Translation request response (64bits) */
+#define RISCV_IOMMU_REG_TR_RESPONSE 0x0268
+#define RISCV_IOMMU_TR_RESPONSE_FAULT   BIT_ULL(0)
+#define RISCV_IOMMU_TR_RESPONSE_PPN RISCV_IOMMU_PPN_FIELD
+
  /* 5.27 Interrupt cause to vector (64bits) */
  #define RISCV_IOMMU_REG_IVEC0x02F8

diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
index 7af5929b10..1fa1286d07 100644
--- a/hw/riscv/riscv-iommu.c
+++ b/hw/riscv/riscv-iommu.c
@@ -1457,6 +1457,46 @@ static void 
riscv_iommu_process_pq_control(RISCVIOMMUState *s)
  riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_PQCSR, ctrl_set, ctrl_clr);
  }

+static void riscv_iommu_process_dbg(RISCVIOMMUState *s)
+{
+uint64_t iova = riscv_iommu_reg_get64(s, RISCV_IOMMU_REG_TR_REQ_IOVA);
+uint64_t ctrl = riscv_iommu_reg_get64(s, RISCV_IOMMU_REG_TR_REQ_CTL);
+unsigned devid = get_field(ctrl, RISCV_IOMMU_TR_REQ_CTL_DID);
+unsigned pid = get_field(ctrl, RISCV_IOMMU_TR_REQ_CTL_PID);
+RISCVIOMMUContext *ctx;
+void *ref;
+
+if (!(ctrl & RISCV_IOMMU_TR_REQ_CTL_GO_BUSY)) {
+return;
+}
+
+ctx = riscv_iommu_ctx(s, devid, pid, );
+if (ctx == NULL) {
+riscv_iommu_reg_set64(s, RISCV_IOMMU_REG_TR_RESPONSE,
+ RISCV_IOMMU_TR_RESPONSE_FAULT |
+ (RISCV_IOMMU_FQ_CAUSE_DMA_DISABLED << 10));
+} else {
+IOMMUTLBEntry iotlb = {
+.iova = iova,
+.perm = IOMMU_NONE,


.perm should honor tr_req_ctl.[Exe|Nw]


+.addr_mask = ~0,
+.target_as = NULL,
+};
+int fault = riscv_iommu_translate(s, ctx, , false);
+if (fault) {
+iova = RISCV_IOMMU_TR_RESPONSE_FAULT | (((uint64_t) fault) << 10);
+} else {
+iova = ((iotlb.translated_addr & ~iotlb.addr_mask) >> 2) &


For 4-KB page, we should right-shift 12 bits.


+RISCV_IOMMU_TR_RESPONSE_PPN;


It's possible that the translation is not 4-KB page (i.e. superpage),
which we should set tr_response.S
and encode translation range size in tr_response.PPN.


At this moment this emulation doesn't support superpages, at least from my
understanding. Tomasz is welcome to correct me if I'm wrong. I'll explictly
set tr_response.S to 0 here to make it clearer.

The idea here IIUC is to, in the future, merge the IOMMU translation lookup code
with the existing lookup code we have (cpu_helper.c, get_physical_address()), 
and
with that the IOMMU will end up supporting both super-pages and svnapot.



Thanks,

Daniel




Regards,
Frank Chang


+}
+riscv_iommu_reg_set64(s, RISCV_IOMMU_REG_TR_RESPONSE, iova);
+}
+
+riscv_iommu_reg_mod64(s, RISCV_IOMMU_REG_TR_REQ_CTL, 0,
+RISCV_IOMMU_TR_REQ_CTL_GO_BUSY);
+riscv_iommu_ctx_put(s, ref);
+}
+
  /* Core IOMMU execution activation */
  enum {
  RISCV_IOMMU_EXEC_DDTP,
@@ -1502,7 +1542,7 @@ static void *riscv_iommu_core_proc(void* arg)
  /* NOP */
  break;
  case BIT(RISCV_IOMMU_EXEC_TR_REQUEST):
-/* D

[RFC PATCH 1/1] pci-ids.rst: add Red Hat pci-id for generic IOMMU device

2024-05-03 Thread Daniel Henrique Barboza
Reserve an id to be used by the RISC-V IOMMU PCI device.

Cc: Gerd Hoffmann 
Signed-off-by: Daniel Henrique Barboza 
---
 docs/specs/pci-ids.rst | 2 ++
 include/hw/pci/pci.h   | 1 +
 2 files changed, 3 insertions(+)

diff --git a/docs/specs/pci-ids.rst b/docs/specs/pci-ids.rst
index c0a3dec2e7..a89a9d0939 100644
--- a/docs/specs/pci-ids.rst
+++ b/docs/specs/pci-ids.rst
@@ -94,6 +94,8 @@ PCI devices (other than virtio):
   PCI ACPI ERST device (``-device acpi-erst``)
 1b36:0013
   PCI UFS device (``-device ufs``)
+1b36:0014
+  PCI RISC-V IOMMU device
 
 All these devices are documented in :doc:`index`.
 
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index eaa3fc99d8..462aed1503 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -115,6 +115,7 @@ extern bool pci_available;
 #define PCI_DEVICE_ID_REDHAT_PVPANIC 0x0011
 #define PCI_DEVICE_ID_REDHAT_ACPI_ERST   0x0012
 #define PCI_DEVICE_ID_REDHAT_UFS 0x0013
+#define PCI_DEVICE_ID_REDHAT_RISCV_IOMMU 0x0014
 #define PCI_DEVICE_ID_REDHAT_QXL 0x0100
 
 #define FMT_PCIBUS  PRIx64
-- 
2.44.0




[RFC PATCH 0/1] pci: allocate a PCI ID for RISC-V IOMMU

2024-05-03 Thread Daniel Henrique Barboza
Hi,

In this RFC I want to check with Gerd and others if it's ok to add a PCI
id for the RISC-V IOMMU device. It's currently under review in [1]. The
idea is to fold this patch into the RISC-V IOMMU series if we're all ok
with this change.

Gerd, we picked the ID right after the PCI UFS device. Let me know if
you want another ID instead. 


Daniel Henrique Barboza (1):
  pci-ids.rst: add Red Hat pci-id for generic IOMMU device

 docs/specs/pci-ids.rst | 2 ++
 include/hw/pci/pci.h   | 1 +
 2 files changed, 3 insertions(+)

-- 
2.44.0




Re: [PATCH v2 04/15] hw/riscv: add riscv-iommu-pci device

2024-05-02 Thread Daniel Henrique Barboza




On 4/29/24 04:21, Frank Chang wrote:

Daniel Henrique Barboza mailto:dbarb...@ventanamicro.com>> 於 2024年3月8日 週五 上午12:04寫道:
 >
 > From: Tomasz Jeznach mailto:tjezn...@rivosinc.com>>
 >
 > The RISC-V IOMMU can be modelled as a PCIe device following the
 > guidelines of the RISC-V IOMMU spec, chapter 7.1, "Integrating an IOMMU
 > as a PCIe device".
 >
 > Signed-off-by: Tomasz Jeznach mailto:tjezn...@rivosinc.com>>
 > Signed-off-by: Daniel Henrique Barboza mailto:dbarb...@ventanamicro.com>>
 > ---
 >  hw/riscv/meson.build       |   2 +-
 >  hw/riscv/riscv-iommu-pci.c | 173 +
 >  2 files changed, 174 insertions(+), 1 deletion(-)
 >  create mode 100644 hw/riscv/riscv-iommu-pci.c
 >
 > diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build
 > index ba9eebd605..4674cec6c4 100644
 > --- a/hw/riscv/meson.build
 > +++ b/hw/riscv/meson.build
 > @@ -10,6 +10,6 @@ riscv_ss.add(when: 'CONFIG_SIFIVE_U', if_true: 
files('sifive_u.c'))
 >  riscv_ss.add(when: 'CONFIG_SPIKE', if_true: files('spike.c'))
 >  riscv_ss.add(when: 'CONFIG_MICROCHIP_PFSOC', if_true: 
files('microchip_pfsoc.c'))
 >  riscv_ss.add(when: 'CONFIG_ACPI', if_true: files('virt-acpi-build.c'))
 > -riscv_ss.add(when: 'CONFIG_RISCV_IOMMU', if_true: files('riscv-iommu.c'))
 > +riscv_ss.add(when: 'CONFIG_RISCV_IOMMU', if_true: files('riscv-iommu.c', 
'riscv-iommu-pci.c'))
 >
 >  hw_arch += {'riscv': riscv_ss}
 > diff --git a/hw/riscv/riscv-iommu-pci.c b/hw/riscv/riscv-iommu-pci.c
 > new file mode 100644
 > index 00..4eb1057210
 > --- /dev/null
 > +++ b/hw/riscv/riscv-iommu-pci.c
 > @@ -0,0 +1,173 @@
 > +/*
 > + * QEMU emulation of an RISC-V IOMMU (Ziommu)
 > + *
 > + * Copyright (C) 2022-2023 Rivos Inc.
 > + *
 > + * This program is free software; you can redistribute it and/or modify
 > + * it under the terms of the GNU General Public License as published by
 > + * the Free Software Foundation; either version 2 of the License.
 > + *
 > + * This program is distributed in the hope that it will be useful,
 > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
 > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 > + * GNU General Public License for more details.
 > + *
 > + * You should have received a copy of the GNU General Public License along
 > + * with this program; if not, see <http://www.gnu.org/licenses/ 
<http://www.gnu.org/licenses/>>.
 > + */
 > +
 > +#include "qemu/osdep.h"
 > +#include "hw/pci/msi.h"
 > +#include "hw/pci/msix.h"
 > +#include "hw/pci/pci_bus.h"
 > +#include "hw/qdev-properties.h"
 > +#include "hw/riscv/riscv_hart.h"
 > +#include "migration/vmstate.h"
 > +#include "qapi/error.h"
 > +#include "qemu/error-report.h"
 > +#include "qemu/host-utils.h"
 > +#include "qom/object.h"
 > +
 > +#include "cpu_bits.h"
 > +#include "riscv-iommu.h"
 > +#include "riscv-iommu-bits.h"
 > +
 > +#ifndef PCI_VENDOR_ID_RIVOS
 > +#define PCI_VENDOR_ID_RIVOS           0x1efd
 > +#endif
 > +
 > +#ifndef PCI_DEVICE_ID_RIVOS_IOMMU
 > +#define PCI_DEVICE_ID_RIVOS_IOMMU     0xedf1
 > +#endif
 > +
 > +/* RISC-V IOMMU PCI Device Emulation */
 > +
 > +typedef struct RISCVIOMMUStatePci {
 > +    PCIDevice        pci;     /* Parent PCIe device state */
 > +    MemoryRegion     bar0;    /* PCI BAR (including MSI-x config) */
 > +    RISCVIOMMUState  iommu;   /* common IOMMU state */
 > +} RISCVIOMMUStatePci;
 > +
 > +/* interrupt delivery callback */
 > +static void riscv_iommu_pci_notify(RISCVIOMMUState *iommu, unsigned vector)
 > +{
 > +    RISCVIOMMUStatePci *s = container_of(iommu, RISCVIOMMUStatePci, iommu);
 > +
 > +    if (msix_enabled(&(s->pci))) {
 > +        msix_notify(&(s->pci), vector);
 > +    }
 > +}
 > +
 > +static void riscv_iommu_pci_realize(PCIDevice *dev, Error **errp)
 > +{
 > +    RISCVIOMMUStatePci *s = DO_UPCAST(RISCVIOMMUStatePci, pci, dev);
 > +    RISCVIOMMUState *iommu = >iommu;
 > +    Error *err = NULL;
 > +
 > +    /* Set device id for trace / debug */
 > +    DEVICE(iommu)->id = g_strdup_printf("%02x:%02x.%01x",
 > +        pci_dev_bus_num(dev), PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));

pci_dev_bus_num() calls pci_bus_num(),
and pci_bus_num() is assigned to pcibus_num(),
which returns bus->parent_dev->config[PCI_SECONDARY_BUS]
However, PCI bus number is not initialized by SW when IOMMU is initialized.
So pci_bus_num() will always return 0, IIRC.
Same issue as pci_bus_num() above.

 > +    qdev_realize

Re: [PATCH 2/3] target/riscv: Enforce WARL behavior for scounteren/hcounteren

2024-04-30 Thread Daniel Henrique Barboza




On 4/29/24 16:28, Atish Patra wrote:

scounteren/hcountern are also WARL registers similar to mcountern.
Only set the bits for the available counters during the write to
preserve the WARL behavior.

Signed-off-by: Atish Patra 
---


Reviewed-by: Daniel Henrique Barboza 


  target/riscv/csr.c | 12 ++--
  1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 68ca31aff47d..a01911541d67 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -2843,7 +2843,11 @@ static RISCVException read_scounteren(CPURISCVState 
*env, int csrno,
  static RISCVException write_scounteren(CPURISCVState *env, int csrno,
 target_ulong val)
  {
-env->scounteren = val;
+RISCVCPU *cpu = env_archcpu(env);
+
+/* WARL register - disable unavailable counters */
+env->scounteren = val & (cpu->pmu_avail_ctrs | COUNTEREN_CY | COUNTEREN_TM 
|
+ COUNTEREN_IR);
  return RISCV_EXCP_NONE;
  }
  
@@ -3475,7 +3479,11 @@ static RISCVException read_hcounteren(CPURISCVState *env, int csrno,

  static RISCVException write_hcounteren(CPURISCVState *env, int csrno,
 target_ulong val)
  {
-env->hcounteren = val;
+RISCVCPU *cpu = env_archcpu(env);
+
+/* WARL register - disable unavailable counters */
+env->hcounteren = val & (cpu->pmu_avail_ctrs | COUNTEREN_CY | COUNTEREN_TM 
|
+ COUNTEREN_IR);
  return RISCV_EXCP_NONE;
  }
  





Re: [PATCH 1/3] target/riscv: Save counter values during countinhibit update

2024-04-30 Thread Daniel Henrique Barboza




On 4/29/24 16:28, Atish Patra wrote:

Currently, if a counter monitoring cycle/instret is stopped via
mcountinhibit we just update the state while the value is saved
during the next read. This is not accurate as the read may happen
many cycles after the counter is stopped. Ideally, the read should
return the value saved when the counter is stopped.

Thus, save the value of the counter during the inhibit update
operation and return that value during the read if corresponding bit
in mcountihibit is set.

Signed-off-by: Atish Patra 
---
  target/riscv/cpu.h |  1 -
  target/riscv/csr.c | 32 
  target/riscv/machine.c |  1 -
  3 files changed, 20 insertions(+), 14 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 3b1a02b9449a..09bbf7ce9880 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -153,7 +153,6 @@ typedef struct PMUCTRState {
  target_ulong mhpmcounter_prev;
  /* Snapshort value of a counter in RV32 */
  target_ulong mhpmcounterh_prev;
-bool started;
  /* Value beyond UINT32_MAX/UINT64_MAX before overflow interrupt trigger */
  target_ulong irq_overflow_left;
  } PMUCTRState;
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 726096444fae..68ca31aff47d 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -929,17 +929,11 @@ static RISCVException riscv_pmu_read_ctr(CPURISCVState 
*env, target_ulong *val,
  
  if (get_field(env->mcountinhibit, BIT(ctr_idx))) {

  /*
- * Counter should not increment if inhibit bit is set. We can't really
- * stop the icount counting. Just return the counter value written by
- * the supervisor to indicate that counter was not incremented.
+ * Counter should not increment if inhibit bit is set. Just return the
+ * current counter value.
   */
-if (!counter->started) {
-*val = ctr_val;
-return RISCV_EXCP_NONE;
-} else {
-/* Mark that the counter has been stopped */
-counter->started = false;
-}
+ *val = ctr_val;
+ return RISCV_EXCP_NONE;
  }
  
  /*

@@ -1973,9 +1967,23 @@ static RISCVException write_mcountinhibit(CPURISCVState 
*env, int csrno,
  
  /* Check if any other counter is also monitoring cycles/instructions */

  for (cidx = 0; cidx < RV_MAX_MHPMCOUNTERS; cidx++) {
-if (!get_field(env->mcountinhibit, BIT(cidx))) {
  counter = >pmu_ctrs[cidx];
-counter->started = true;
+if (get_field(env->mcountinhibit, BIT(cidx)) && (val & BIT(cidx))) {
+   /*
+ * Update the counter value for cycle/instret as we can't stop the
+ * host ticks. But we should show the current value at this moment.
+ */
+if (riscv_pmu_ctr_monitor_cycles(env, cidx) ||
+riscv_pmu_ctr_monitor_instructions(env, cidx)) {
+counter->mhpmcounter_val = get_ticks(false) -
+   counter->mhpmcounter_prev +
+   counter->mhpmcounter_val;
+if (riscv_cpu_mxl(env) == MXL_RV32) {
+counter->mhpmcounterh_val = get_ticks(false) -
+counter->mhpmcounterh_prev +
+counter->mhpmcounterh_val;
+   }
+}
  }
  }
  
diff --git a/target/riscv/machine.c b/target/riscv/machine.c

index 76f2150f78b5..3e0f2dd2ce2a 100644
--- a/target/riscv/machine.c
+++ b/target/riscv/machine.c
@@ -328,7 +328,6 @@ static const VMStateDescription vmstate_pmu_ctr_state = {
  VMSTATE_UINTTL(mhpmcounterh_val, PMUCTRState),
  VMSTATE_UINTTL(mhpmcounter_prev, PMUCTRState),
  VMSTATE_UINTTL(mhpmcounterh_prev, PMUCTRState),
-VMSTATE_BOOL(started, PMUCTRState),


Unfortunately we can't remove fields from the VMStateDescription without 
breaking
migration backward compatibility. Older QEMUs will attempt to read a field that
doesn't exist and migration will fail.

I'm assuming that we care about backward compat. If we're not up to this point 
yet
then we can just bump the version_id of vmstate_pmu_ctr_state and be done with 
it.
This is fine to do unless someone jumps in and complains that we broke a 
migration
case for the 'virt' board. Granted, we don't have versioned boards yet so I'm 
unsure
if someone would actually have a base to complain. Alistair, Drew, care to 
comment?


Now, if we care about backward migration compat, we'll need to do as described 
in
devel/migration/main.rst, section "Not sending existing elements". An example on
how we need to proceed can also be seen in commit 6cc88d6bf9. But in short we
would need to:

- add a dummy property, e.g. a 'mig_started' bool

- use a slightly different macro in vmstate:


-VMSTATE_BOOL(started, PMUCTRState),
+

Re: [PATCH 2/2] target/riscv: do not set mtval2 for non guest-page faults

2024-04-29 Thread Daniel Henrique Barboza




On 4/13/24 07:59, Alexei Filippov wrote:

Previous patch fixed the PMP priority in raise_mmu_exception() but we're still
setting mtval2 incorrectly. In riscv_cpu_tlb_fill(), after pmp check in 2 stage
translation part, mtval2 will be set in case of successes 2 stage translation 
but
failed pmp check.

In this case we gonna set mtval2 via env->guest_phys_fault_addr in context of
riscv_cpu_tlb_fill(), as this was a guest-page-fault, but it didn't and mtval2
should be zero, according to RISCV privileged spec sect. 9.4.4: When a guest
page-fault is taken into M-mode, mtval2 is written with either zero or guest
physical address that faulted, shifted by 2 bits. *For other traps, mtval2
is set to zero...*

Signed-off-by: Alexei Filippov 
---


Reviewed-by: Daniel Henrique Barboza 


  target/riscv/cpu_helper.c | 12 ++--
  1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 196166f8dd..89e659fe3a 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -1410,17 +1410,17 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, 
int size,
__func__, pa, ret, prot_pmp, tlb_size);
  
  prot &= prot_pmp;

-}
-
-if (ret != TRANSLATE_SUCCESS) {
+} else {
  /*
   * Guest physical address translation failed, this is a HS
   * level exception
   */
  first_stage_error = false;
-env->guest_phys_fault_addr = (im_address |
-  (address &
-   (TARGET_PAGE_SIZE - 1))) >> 2;
+if (ret != TRANSLATE_PMP_FAIL) {
+env->guest_phys_fault_addr = (im_address |
+  (address &
+   (TARGET_PAGE_SIZE - 1))) >> 
2;
+}
  }
  }
  } else {




Re: [PATCH v3] target/riscv: Raise exceptions on wrs.nto

2024-04-26 Thread Daniel Henrique Barboza




On 4/24/24 11:28, Andrew Jones wrote:

Implementing wrs.nto to always just return is consistent with the
specification, as the instruction is permitted to terminate the
stall for any reason, but it's not useful for virtualization, where
we'd like the guest to trap to the hypervisor in order to allow
scheduling of the lock holding VCPU. Change to always immediately
raise exceptions when the appropriate conditions are present,
otherwise continue to just return. Note, immediately raising
exceptions is also consistent with the specification since the
time limit that should expire prior to the exception is
implementation-specific.

Signed-off-by: Andrew Jones 
Reviewed-by: Christoph Müllner 
---


Reviewed-by: Daniel Henrique Barboza 


v3:
  - Sending again, hoping the ü remains in Müllner
v2:
  - Added #ifndef CONFIG_USER_ONLY around helper call

  target/riscv/helper.h   |  1 +
  target/riscv/insn_trans/trans_rvzawrs.c.inc | 29 ++---
  target/riscv/op_helper.c| 11 
  3 files changed, 32 insertions(+), 9 deletions(-)

diff --git a/target/riscv/helper.h b/target/riscv/helper.h
index 8a635238514d..451261ce5a4f 100644
--- a/target/riscv/helper.h
+++ b/target/riscv/helper.h
@@ -132,6 +132,7 @@ DEF_HELPER_6(csrrw_i128, tl, env, int, tl, tl, tl, tl)
  DEF_HELPER_1(sret, tl, env)
  DEF_HELPER_1(mret, tl, env)
  DEF_HELPER_1(wfi, void, env)
+DEF_HELPER_1(wrs_nto, void, env)
  DEF_HELPER_1(tlb_flush, void, env)
  DEF_HELPER_1(tlb_flush_all, void, env)
  /* Native Debug */
diff --git a/target/riscv/insn_trans/trans_rvzawrs.c.inc 
b/target/riscv/insn_trans/trans_rvzawrs.c.inc
index 32efbff4d5a5..0eef03383889 100644
--- a/target/riscv/insn_trans/trans_rvzawrs.c.inc
+++ b/target/riscv/insn_trans/trans_rvzawrs.c.inc
@@ -16,7 +16,7 @@
   * this program.  If not, see <http://www.gnu.org/licenses/>.
   */
  
-static bool trans_wrs(DisasContext *ctx)

+static bool trans_wrs_sto(DisasContext *ctx, arg_wrs_sto *a)
  {
  if (!ctx->cfg_ptr->ext_zawrs) {
  return false;
@@ -40,12 +40,23 @@ static bool trans_wrs(DisasContext *ctx)
  return true;
  }
  
-#define GEN_TRANS_WRS(insn) \

-static bool trans_ ## insn(DisasContext *ctx, arg_ ## insn *a)  \
-{   \
-(void)a;\
-return trans_wrs(ctx);  \
-}
+static bool trans_wrs_nto(DisasContext *ctx, arg_wrs_nto *a)
+{
+if (!ctx->cfg_ptr->ext_zawrs) {
+return false;
+}
  
-GEN_TRANS_WRS(wrs_nto)

-GEN_TRANS_WRS(wrs_sto)
+/*
+ * Depending on the mode of execution, mstatus.TW and hstatus.VTW, wrs.nto
+ * should raise an exception when the implementation-specific bounded time
+ * limit has expired. Our time limit is zero, so we either return
+ * immediately, as does our implementation of wrs.sto, or raise an
+ * exception, as handled by the wrs.nto helper.
+ */
+#ifndef CONFIG_USER_ONLY
+gen_helper_wrs_nto(tcg_env);
+#endif
+
+/* We only get here when helper_wrs_nto() doesn't raise an exception. */
+return trans_wrs_sto(ctx, NULL);
+}
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index f414aaebdbab..2baf5bc3ca19 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -380,6 +380,17 @@ void helper_wfi(CPURISCVState *env)
  }
  }
  
+void helper_wrs_nto(CPURISCVState *env)

+{
+if (env->virt_enabled && (env->priv == PRV_S || env->priv == PRV_U) &&
+get_field(env->hstatus, HSTATUS_VTW) &&
+!get_field(env->mstatus, MSTATUS_TW)) {
+riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, GETPC());
+} else if (env->priv != PRV_M && get_field(env->mstatus, MSTATUS_TW)) {
+riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC());
+}
+}
+
  void helper_tlb_flush(CPURISCVState *env)
  {
  CPUState *cs = env_cpu(env);




[PATCH] target/riscv/kvm: implement SBI debug console (DBCN) calls

2024-04-25 Thread Daniel Henrique Barboza
SBI defines a Debug Console extension "DBCN" that will, in time, replace
the legacy console putchar and getchar SBI extensions.

The appeal of the DBCN extension is that it allows multiple bytes to be
read/written in the SBI console in a single SBI call.

As far as KVM goes, the DBCN calls are forwarded by an in-kernel KVM
module to userspace. But this will only happens if the KVM module
actually supports this SBI extension and we activate it.

We'll check for DBCN support during init time, checking if get-reg-list
is advertising KVM_RISCV_SBI_EXT_DBCN. In that case, we'll enable it via
kvm_set_one_reg() during kvm_arch_init_vcpu().

Finally, change kvm_riscv_handle_sbi() to handle the incoming calls for
SBI_EXT_DBCN, reading and writing as required.

A simple KVM guest with 'earlycon=sbi', running in an emulated RISC-V
host, takes around 20 seconds to boot without using DBCN. With this
patch we're taking around 14 seconds to boot due to the speed-up in the
terminal output.  There's no change in boot time if the guest isn't
using earlycon.

Signed-off-by: Daniel Henrique Barboza 
---
 target/riscv/kvm/kvm-cpu.c | 111 +
 target/riscv/sbi_ecall_interface.h |  17 +
 2 files changed, 128 insertions(+)

diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
index 03e3fee607..54a9ab9fd7 100644
--- a/target/riscv/kvm/kvm-cpu.c
+++ b/target/riscv/kvm/kvm-cpu.c
@@ -409,6 +409,12 @@ static KVMCPUConfig kvm_v_vlenb = {
KVM_REG_RISCV_VECTOR_CSR_REG(vlenb)
 };
 
+static KVMCPUConfig kvm_sbi_dbcn = {
+.name = "sbi_dbcn",
+.kvm_reg_id = KVM_REG_RISCV | KVM_REG_SIZE_U64 |
+  KVM_REG_RISCV_SBI_EXT | KVM_RISCV_SBI_EXT_DBCN
+};
+
 static void kvm_riscv_update_cpu_cfg_isa_ext(RISCVCPU *cpu, CPUState *cs)
 {
 CPURISCVState *env = >env;
@@ -1041,6 +1047,20 @@ static int uint64_cmp(const void *a, const void *b)
 return 0;
 }
 
+static void kvm_riscv_check_sbi_dbcn_support(RISCVCPU *cpu,
+ KVMScratchCPU *kvmcpu,
+ struct kvm_reg_list *reglist)
+{
+struct kvm_reg_list *reg_search;
+
+reg_search = bsearch(_sbi_dbcn.kvm_reg_id, reglist->reg, reglist->n,
+ sizeof(uint64_t), uint64_cmp);
+
+if (reg_search) {
+kvm_sbi_dbcn.supported = true;
+}
+}
+
 static void kvm_riscv_read_vlenb(RISCVCPU *cpu, KVMScratchCPU *kvmcpu,
  struct kvm_reg_list *reglist)
 {
@@ -1146,6 +1166,8 @@ static void kvm_riscv_init_multiext_cfg(RISCVCPU *cpu, 
KVMScratchCPU *kvmcpu)
 if (riscv_has_ext(>env, RVV)) {
 kvm_riscv_read_vlenb(cpu, kvmcpu, reglist);
 }
+
+kvm_riscv_check_sbi_dbcn_support(cpu, kvmcpu, reglist);
 }
 
 static void riscv_init_kvm_registers(Object *cpu_obj)
@@ -1320,6 +1342,17 @@ static int kvm_vcpu_set_machine_ids(RISCVCPU *cpu, 
CPUState *cs)
 return ret;
 }
 
+static int kvm_vcpu_enable_sbi_dbcn(RISCVCPU *cpu, CPUState *cs)
+{
+target_ulong reg = 1;
+
+if (!kvm_sbi_dbcn.supported) {
+return 0;
+}
+
+return kvm_set_one_reg(cs, kvm_sbi_dbcn.kvm_reg_id, );
+}
+
 int kvm_arch_init_vcpu(CPUState *cs)
 {
 int ret = 0;
@@ -1337,6 +1370,8 @@ int kvm_arch_init_vcpu(CPUState *cs)
 kvm_riscv_update_cpu_misa_ext(cpu, cs);
 kvm_riscv_update_cpu_cfg_isa_ext(cpu, cs);
 
+ret = kvm_vcpu_enable_sbi_dbcn(cpu, cs);
+
 return ret;
 }
 
@@ -1394,6 +1429,79 @@ bool kvm_arch_stop_on_emulation_error(CPUState *cs)
 return true;
 }
 
+static void kvm_riscv_handle_sbi_dbcn(CPUState *cs, struct kvm_run *run)
+{
+g_autofree uint8_t *buf = NULL;
+RISCVCPU *cpu = RISCV_CPU(cs);
+target_ulong num_bytes;
+uint64_t addr;
+unsigned char ch;
+int ret;
+
+switch (run->riscv_sbi.function_id) {
+case SBI_EXT_DBCN_CONSOLE_READ:
+case SBI_EXT_DBCN_CONSOLE_WRITE:
+num_bytes = run->riscv_sbi.args[0];
+
+if (num_bytes == 0) {
+run->riscv_sbi.ret[0] = SBI_SUCCESS;
+run->riscv_sbi.ret[1] = 0;
+break;
+}
+
+addr = run->riscv_sbi.args[1];
+
+/*
+ * Handle the case where a 32 bit CPU is running in a
+ * 64 bit addressing env.
+ */
+if (riscv_cpu_mxl(>env) == MXL_RV32) {
+addr |= (uint64_t)run->riscv_sbi.args[2] << 32;
+}
+
+buf = g_malloc0(num_bytes);
+
+if (run->riscv_sbi.function_id == SBI_EXT_DBCN_CONSOLE_READ) {
+ret = qemu_chr_fe_read_all(serial_hd(0)->be, buf, num_bytes);
+if (ret < 0) {
+error_report("SBI_EXT_DBCN_CONSOLE_READ: error when "
+ "reading chardev");
+exit(1);
+}
+
+cpu_physical_memory_write(addr, buf, ret);
+} else {
+cpu_physical_m

[PATCH v2 1/2] target/riscv/kvm: remove sneaky strerrorname_np() instance

2024-04-24 Thread Daniel Henrique Barboza
Commit d424db2354 excluded some strerrorname_np() instances because they
break musl libc builds. Another instance happened to slip by via commit
d4ff3da8f4.

Remove it before it causes trouble again.

Fixes: d4ff3da8f4 (target/riscv/kvm: initialize 'vlenb' via get-reg-list)
Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Thomas Huth 
Reviewed-by: Philippe Mathieu-Daudé 
---
 target/riscv/kvm/kvm-cpu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
index 6a6c6cae80..ee69ea9785 100644
--- a/target/riscv/kvm/kvm-cpu.c
+++ b/target/riscv/kvm/kvm-cpu.c
@@ -1054,8 +1054,8 @@ static void kvm_riscv_read_vlenb(RISCVCPU *cpu, 
KVMScratchCPU *kvmcpu,
 
 ret = ioctl(kvmcpu->cpufd, KVM_GET_ONE_REG, );
 if (ret != 0) {
-error_report("Unable to read vlenb register, error code: %s",
- strerrorname_np(errno));
+error_report("Unable to read vlenb register, error code: %d",
+ errno);
 exit(EXIT_FAILURE);
 }
 
-- 
2.44.0




[PATCH v2 0/2] riscv,kvm: remove another strerrorname_np()

2024-04-24 Thread Daniel Henrique Barboza
Hi,

In this new version a small change suggested by Phil was made in patch
2. No other changes made.

Note: checkpatch.pl is nagging quite a bit about the checkpatch.pl change
this time, claiming that I'm adding a line > 90 chars when in reality the
line has 80 chars:

ERROR: line over 90 characters
#39: FILE: scripts/checkpatch.pl:3082:
+   ERROR("use strerror() instead of strerrorname_np()\n" . 
$herecurr);

total: 1 errors, 0 warnings, 9 lines checked

I supposed it's counting each TAB as more than one char. Let me know if
I need to care about this error and I'll send a v3.


Changes from v1:
- patch 2:
  - move the strerrorname_np() check to the "non-portable libc calls"
section
- v1 link: 
https://lore.kernel.org/qemu-riscv/20240424094700.453356-1-dbarb...@ventanamicro.com/

Daniel Henrique Barboza (2):
  target/riscv/kvm: remove sneaky strerrorname_np() instance
  checkpatch.pl: forbid strerrorname_np()

 scripts/checkpatch.pl  | 3 +++
 target/riscv/kvm/kvm-cpu.c | 4 ++--
 2 files changed, 5 insertions(+), 2 deletions(-)

-- 
2.44.0




[PATCH v2 2/2] checkpatch.pl: forbid strerrorname_np()

2024-04-24 Thread Daniel Henrique Barboza
Commit d424db2354 removed an instance of strerrorname_np() because it
was breaking building with musl libc. A recent RISC-V patch ended up
re-introducing it again by accident.

Put this function in the baddies list in checkpatch.pl to avoid this
situation again. This is what it will look like next time:

 $ ./scripts/checkpatch.pl 0001-temp-test.patch
 ERROR: use strerror() instead of strerrorname_np()
 #22: FILE: target/riscv/kvm/kvm-cpu.c:1058:
 + strerrorname_np(errno));

 total: 1 errors, 0 warnings, 10 lines checked

Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Thomas Huth 
Reviewed-by: Philippe Mathieu-Daudé 
---
 scripts/checkpatch.pl | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 7026895074..f7ffa74858 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -3078,6 +3078,9 @@ sub process {
if ($line =~ /\b(g_)?assert\(0\)/) {
ERROR("use g_assert_not_reached() instead of 
assert(0)\n" . $herecurr);
}
+   if ($line =~ /\bstrerrorname_np\(/) {
+   ERROR("use strerror() instead of strerrorname_np()\n" . 
$herecurr);
+   }
my $non_exit_glib_asserts = qr{g_assert_cmpstr|
g_assert_cmpint|
g_assert_cmpuint|
-- 
2.44.0




Re: [PATCH 1/2] target/riscv/kvm: remove sneaky strerrorname_np() instance

2024-04-24 Thread Daniel Henrique Barboza




On 4/24/24 06:55, Philippe Mathieu-Daudé wrote:

On 24/4/24 11:46, Daniel Henrique Barboza wrote:

Commit d424db2354 excluded some strerrorname_np() instances because they
break musl libc builds. Another instance happened to slip by via commit
d4ff3da8f4.

Remove it before it causes trouble again.

Fixes: d4ff3da8f4 (target/riscv/kvm: initialize 'vlenb' via get-reg-list)
Signed-off-by: Daniel Henrique Barboza 
---
  target/riscv/kvm/kvm-cpu.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
index 6a6c6cae80..ee69ea9785 100644
--- a/target/riscv/kvm/kvm-cpu.c
+++ b/target/riscv/kvm/kvm-cpu.c
@@ -1054,8 +1054,8 @@ static void kvm_riscv_read_vlenb(RISCVCPU *cpu, 
KVMScratchCPU *kvmcpu,
  ret = ioctl(kvmcpu->cpufd, KVM_GET_ONE_REG, );
  if (ret != 0) {
-    error_report("Unable to read vlenb register, error code: %s",
- strerrorname_np(errno));
+    error_report("Unable to read vlenb register, error code: %d",
+ errno);


Why not use "%s" strerror(errno)?


It's not exactly the same. For errno = 2 strerrorname_np() gives "ENOENT", and
sterror() gives "No such file or directory". In this particular context I think
just printing a "error code -2" is clearer because we're not mentioning files 
and
dirs in a KVM reg context.

But in the end I don't mind changing to strerror() if you feel strong about it. 
It's
fine either way.


Thanks,


Daniel




  exit(EXIT_FAILURE);
  }






[PATCH 1/2] target/riscv/kvm: remove sneaky strerrorname_np() instance

2024-04-24 Thread Daniel Henrique Barboza
Commit d424db2354 excluded some strerrorname_np() instances because they
break musl libc builds. Another instance happened to slip by via commit
d4ff3da8f4.

Remove it before it causes trouble again.

Fixes: d4ff3da8f4 (target/riscv/kvm: initialize 'vlenb' via get-reg-list)
Signed-off-by: Daniel Henrique Barboza 
---
 target/riscv/kvm/kvm-cpu.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
index 6a6c6cae80..ee69ea9785 100644
--- a/target/riscv/kvm/kvm-cpu.c
+++ b/target/riscv/kvm/kvm-cpu.c
@@ -1054,8 +1054,8 @@ static void kvm_riscv_read_vlenb(RISCVCPU *cpu, 
KVMScratchCPU *kvmcpu,
 
 ret = ioctl(kvmcpu->cpufd, KVM_GET_ONE_REG, );
 if (ret != 0) {
-error_report("Unable to read vlenb register, error code: %s",
- strerrorname_np(errno));
+error_report("Unable to read vlenb register, error code: %d",
+ errno);
 exit(EXIT_FAILURE);
 }
 
-- 
2.44.0




[PATCH 2/2] checkpatch.pl: forbid strerrorname_np()

2024-04-24 Thread Daniel Henrique Barboza
Commit d424db2354 removed an instance of strerrorname_np() because it
was breaking building with musl libc. A recent RISC-V patch ended up
re-introducing it again by accident.

Put this function in the baddies list in checkpatch.pl to avoid this
situation again. This is what it will look like next time:

 $ ./scripts/checkpatch.pl 0001-temp-test.patch
 ERROR: use strerror() instead of strerrorname_np()
 #22: FILE: target/riscv/kvm/kvm-cpu.c:1058:
 + strerrorname_np(errno));

 total: 1 errors, 0 warnings, 10 lines checked

Signed-off-by: Daniel Henrique Barboza 
---
 scripts/checkpatch.pl | 4 
 1 file changed, 4 insertions(+)

diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 7026895074..be0982246d 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -3056,6 +3056,10 @@ sub process {
}
}
 
+   if ($line =~ /\bstrerrorname_np\(/) {
+   ERROR("use strerror() instead of strerrorname_np()\n" . 
$herecurr);
+   }
+
 # check for non-portable libc calls that have portable alternatives in QEMU
if ($line =~ /\bffs\(/) {
ERROR("use ctz32() instead of ffs()\n" . $herecurr);
-- 
2.44.0




[PATCH 0/2] riscv,kvm: remove another strerrorname_np()

2024-04-24 Thread Daniel Henrique Barboza
Hi,

strerrorname_np() was removed last December due to problems with musl
libc builds. And then I ended up adding another instance during the 9.0
cycle (commit ).

So here I am removing the newly added instance and, this time, patching
checkpatch.pl to forbid this function from showing up again.

Michael, patch 1 is qemu-stable material.

Daniel Henrique Barboza (2):
  target/riscv/kvm: remove sneaky strerrorname_np() instance
  checkpatch.pl: forbid strerrorname_np()

 scripts/checkpatch.pl  | 4 
 target/riscv/kvm/kvm-cpu.c | 4 ++--
 2 files changed, 6 insertions(+), 2 deletions(-)

-- 
2.44.0




Re: [PATCH] target/riscv: change RISCV_EXCP_SEMIHOST exception number to 63

2024-04-22 Thread Daniel Henrique Barboza




On 4/22/24 16:44, Richard Henderson wrote:

On 4/22/24 10:45, Daniel Henrique Barboza wrote:

Palmer, Anup,

On 4/22/24 10:58, Clément Léger wrote:

The current semihost exception number (16) is a reserved number (range
[16-17]). The upcoming double trap specification uses that number for
the double trap exception. Since the privileged spec (Table 22) defines
ranges for custom uses change the semihosting exception number to 63
which belongs to the range [48-63] in order to avoid any future
collisions with reserved exception.



I didn't find any reference to a number for the SEMIHOST exception here:


https://github.com/riscv-non-isa/riscv-semihosting


Do we have any potential candidates? I would like to avoid, if possible, setting
RISCV_EXCP_SEMIHOST to 63 as a band-aid just to replace it later on by the real
value.


RISCV_EXCP_SEMIHOST is internal to the qemu implementation and will never be 
delivered to the guest.

I suggest using a number high in the >64 reserved range which will (likely) never be used 
by any implementation, including ones that *do* define implementation-specific exceptions.  
Which seems more likely than not within the "implementation defined" range.

E.g. target/i386 uses 0x100+n for qemu internal exceptions.


I'm not sure if we have a range for risc-v qemu internal exceptions only. IIRC 
we don't.

If that's really the case I believe we could use whatever i386/ARM uses. At 
least we'll have some
standardization.


Thanks,

Daniel



But in any case, the number can be redefined at will and not cause 
compatibility issues.


r~




Re: [PATCH] target/riscv/kvm: Fix exposure of Zkr

2024-04-22 Thread Daniel Henrique Barboza




On 4/22/24 10:46, Andrew Jones wrote:

The Zkr extension may only be exposed to KVM guests if the VMM
implements the SEED CSR. Use the same implementation as TCG.

Without this patch, running with a KVM which does not forward the
SEED CSR access to QEMU will result in an ILL exception being
injected into the guest (this results in Linux guests crashing on
boot). And, when running with a KVM which does forward the access,
QEMU will crash, since QEMU doesn't know what to do with the exit.

Fixes: 3108e2f1c69d ("target/riscv/kvm: update KVM exts to Linux 6.8")
Signed-off-by: Andrew Jones 
---


Reviewed-by: Daniel Henrique Barboza 


  target/riscv/cpu.h |  3 +++
  target/riscv/csr.c | 18 ++
  target/riscv/kvm/kvm-cpu.c | 25 +
  3 files changed, 42 insertions(+), 4 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 3b1a02b9449a..52fb8c15d08f 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -821,6 +821,9 @@ void riscv_set_csr_ops(int csrno, riscv_csr_operations 
*ops);
  
  void riscv_cpu_register_gdb_regs_for_features(CPUState *cs);
  
+target_ulong riscv_new_csr_seed(target_ulong new_value,

+target_ulong write_mask);
+
  uint8_t satp_mode_max_from_map(uint32_t map);
  const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit);
  
diff --git a/target/riscv/csr.c b/target/riscv/csr.c

index 726096444fae..829d8346ed4e 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -4267,10 +4267,8 @@ static RISCVException write_upmbase(CPURISCVState *env, 
int csrno,
  #endif
  
  /* Crypto Extension */

-static RISCVException rmw_seed(CPURISCVState *env, int csrno,
-   target_ulong *ret_value,
-   target_ulong new_value,
-   target_ulong write_mask)
+target_ulong riscv_new_csr_seed(target_ulong new_value,
+target_ulong write_mask)
  {
  uint16_t random_v;
  Error *random_e = NULL;
@@ -4294,6 +4292,18 @@ static RISCVException rmw_seed(CPURISCVState *env, int 
csrno,
  rval = random_v | SEED_OPST_ES16;
  }
  
+return rval;

+}
+
+static RISCVException rmw_seed(CPURISCVState *env, int csrno,
+   target_ulong *ret_value,
+   target_ulong new_value,
+   target_ulong write_mask)
+{
+target_ulong rval;
+
+rval = riscv_new_csr_seed(new_value, write_mask);
+
  if (ret_value) {
  *ret_value = rval;
  }
diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
index 6a6c6cae80f1..50bdbd24a878 100644
--- a/target/riscv/kvm/kvm-cpu.c
+++ b/target/riscv/kvm/kvm-cpu.c
@@ -1418,6 +1418,28 @@ static int kvm_riscv_handle_sbi(CPUState *cs, struct 
kvm_run *run)
  return ret;
  }
  
+static int kvm_riscv_handle_csr(CPUState *cs, struct kvm_run *run)

+{
+target_ulong csr_num = run->riscv_csr.csr_num;
+target_ulong new_value = run->riscv_csr.new_value;
+target_ulong write_mask = run->riscv_csr.write_mask;
+int ret = 0;
+
+switch (csr_num) {
+case CSR_SEED:
+run->riscv_csr.ret_value = riscv_new_csr_seed(new_value, write_mask);
+break;
+default:
+qemu_log_mask(LOG_UNIMP,
+  "%s: un-handled CSR EXIT for CSR %lx\n",
+  __func__, csr_num);
+ret = -1;
+break;
+}
+
+return ret;
+}
+
  int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
  {
  int ret = 0;
@@ -1425,6 +1447,9 @@ int kvm_arch_handle_exit(CPUState *cs, struct kvm_run 
*run)
  case KVM_EXIT_RISCV_SBI:
  ret = kvm_riscv_handle_sbi(cs, run);
  break;
+case KVM_EXIT_RISCV_CSR:
+ret = kvm_riscv_handle_csr(cs, run);
+break;
  default:
  qemu_log_mask(LOG_UNIMP, "%s: un-handled exit reason %d\n",
__func__, run->exit_reason);




Re: [PATCH] target/riscv: change RISCV_EXCP_SEMIHOST exception number to 63

2024-04-22 Thread Daniel Henrique Barboza

Palmer, Anup,

On 4/22/24 10:58, Clément Léger wrote:

The current semihost exception number (16) is a reserved number (range
[16-17]). The upcoming double trap specification uses that number for
the double trap exception. Since the privileged spec (Table 22) defines
ranges for custom uses change the semihosting exception number to 63
which belongs to the range [48-63] in order to avoid any future
collisions with reserved exception.



I didn't find any reference to a number for the SEMIHOST exception here:


https://github.com/riscv-non-isa/riscv-semihosting


Do we have any potential candidates? I would like to avoid, if possible, setting
RISCV_EXCP_SEMIHOST to 63 as a band-aid just to replace it later on by the real
value.


Thanks,

Daniel



Signed-off-by: Clément Léger 

---
  target/riscv/cpu_bits.h | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index fc2068ee4d..74318a925c 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -670,11 +670,11 @@ typedef enum RISCVException {
  RISCV_EXCP_INST_PAGE_FAULT = 0xc, /* since: priv-1.10.0 */
  RISCV_EXCP_LOAD_PAGE_FAULT = 0xd, /* since: priv-1.10.0 */
  RISCV_EXCP_STORE_PAGE_FAULT = 0xf, /* since: priv-1.10.0 */
-RISCV_EXCP_SEMIHOST = 0x10,
  RISCV_EXCP_INST_GUEST_PAGE_FAULT = 0x14,
  RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT = 0x15,
  RISCV_EXCP_VIRT_INSTRUCTION_FAULT = 0x16,
  RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT = 0x17,
+RISCV_EXCP_SEMIHOST = 0x3f,
  } RISCVException;
  
  #define RISCV_EXCP_INT_FLAG0x8000




[PATCH v2 1/1] target/riscv/kvm: tolerate KVM disable ext errors

2024-04-22 Thread Daniel Henrique Barboza
Running a KVM guest using a 6.9-rc3 kernel, in a 6.8 host that has zkr
enabled, will fail with a kernel oops SIGILL right at the start. The
reason is that we can't expose zkr without implementing the SEED CSR.
Disabling zkr in the guest would be a workaround, but if the KVM doesn't
allow it we'll error out and never boot.

In hindsight this is too strict. If we keep proceeding, despite not
disabling the extension in the KVM vcpu, we'll not add the extension in
the riscv,isa. The guest kernel will be unaware of the extension, i.e.
it doesn't matter if the KVM vcpu has it enabled underneath or not. So
it's ok to keep booting in this case.

Change our current logic to not error out if we fail to disable an
extension in kvm_set_one_reg(), but show a warning and keep booting. It
is important to throw a warning because we must make the user aware that
the extension is still available in the vcpu, meaning that an
ill-behaved guest can ignore the riscv,isa settings and  use the
extension.

The case we're handling happens with an EINVAL error code. If we fail to
disable the extension in KVM for any other reason, error out.

We'll also keep erroring out when we fail to enable an extension in KVM,
since adding the extension in riscv,isa at this point will cause a guest
malfunction because the extension isn't enabled in the vcpu.

Suggested-by: Andrew Jones 
Signed-off-by: Daniel Henrique Barboza 
---
 target/riscv/kvm/kvm-cpu.c | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
index 6a6c6cae80..03e3fee607 100644
--- a/target/riscv/kvm/kvm-cpu.c
+++ b/target/riscv/kvm/kvm-cpu.c
@@ -427,10 +427,14 @@ static void kvm_riscv_update_cpu_cfg_isa_ext(RISCVCPU 
*cpu, CPUState *cs)
 reg = kvm_cpu_cfg_get(cpu, multi_ext_cfg);
 ret = kvm_set_one_reg(cs, id, );
 if (ret != 0) {
-error_report("Unable to %s extension %s in KVM, error %d",
- reg ? "enable" : "disable",
- multi_ext_cfg->name, ret);
-exit(EXIT_FAILURE);
+if (!reg && ret == -EINVAL) {
+warn_report("KVM cannot disable extension %s",
+multi_ext_cfg->name);
+} else {
+error_report("Unable to enable extension %s in KVM, error %d",
+ multi_ext_cfg->name, ret);
+exit(EXIT_FAILURE);
+}
 }
 }
 }
-- 
2.44.0




[PATCH v2 0/1] target/riscv/kvm: tolerate KVM disable ext errors

2024-04-22 Thread Daniel Henrique Barboza
Hi,

In this new version we changed the commit message a bit and we're now
only handling the case for EINVAL. Both were suggested by Drew in v1.

Changes from v1:
- added an extra paragraph explaining why we're throwing an warning
- changed the warning string
- warning is now being thrown only if EINVAL is returned. We'll keep
  erroring out otherwise.
- v1 link: 
https://lore.kernel.org/qemu-riscv/20240422131253.313869-1-dbarb...@ventanamicro.com/

Daniel Henrique Barboza (1):
  target/riscv/kvm: tolerate KVM disable ext errors

 target/riscv/kvm/kvm-cpu.c | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

-- 
2.44.0




  1   2   3   4   5   6   7   8   9   10   >