Hi Daniel,

On 2/6/26 21:08, Daniel Henrique Barboza wrote:
memory_region_access_valid() returns true and false and nothing else,
but it makes distintions between error types that we can see via each
error_log message: if mr->ops->valid.accepts fails the reason is
set to "rejected", reason is set to "unaligned" if addr is unaligned
and reason is set to "invalid size" if size is less that min_access_size
or greater than max_access_size.

We're particularly interested in the "reason: rejected" result.  In
RISC-V this is thrown when the mem_op tries to access a protected page,
and we need to throw a special exception for this case.
memory_region_dispatch_read() (and write())  will default to
MEMTX_DECODE_ERROR because memory_region_access_valid() does not give
additional info when it fails, and back in the RISC-V side we're having
to make assumptions to determine that this MEMTX_DECODE_ERROR is in fact
a "rejected" error type.

Add a new MemTxResult arg in memory_region_access_valid() that the
funcion will use to set the reason why it failed.  Based on the error
reasons (described above) and the definition of each MemTxResult, we're
setting the following results:

- result ok: MEMTX_OK
- rejected: MEMTX_ACCESS_ERROR
- all other errors: MEMTX_DECODE_ERROR

Orthogonal, in "hw/pci/pci_device.h":

 /**
  * pci_dma_rw: Read from or write to an address space from PCI device.
  *
  * Return a MemTxResult indicating whether the operation succeeded
  * or failed (eg unassigned memory, device rejected the transaction,
  * IOMMU fault).

This could deserve clarification as the  mapping is not obvious to me.

Without looking at the code, I'd expect:

 . unassigned memory -> MEMTX_DECODE_ERROR
 . device rejected the transaction -> MEMTX_ACCESS_ERROR
 . IOMMU fault -> MEMTX_ACCESS_ERROR

What confuses me I guess is having 3 descriptions for 2 enums.


Existing callers are unchanged.  No behavioral change is intended for
now.

Signed-off-by: Daniel Henrique Barboza <[email protected]>
---
  hw/s390x/s390-pci-inst.c |  2 +-
  include/system/memory.h  |  2 +-
  system/memory.c          | 20 +++++++++++++++++---
  system/physmem.c         |  3 ++-
  4 files changed, 21 insertions(+), 6 deletions(-)


diff --git a/include/system/memory.h b/include/system/memory.h
index 1417132f6d..d74fae52e3 100644
--- a/include/system/memory.h
+++ b/include/system/memory.h
@@ -2602,7 +2602,7 @@ void mtree_info(bool flatview, bool dispatch_tree, bool 
owner, bool disabled);

Please update the docstring.

  bool memory_region_access_valid(MemoryRegion *mr, hwaddr addr,
                                  unsigned size, bool is_write,
-                                MemTxAttrs attrs);
+                                MemTxAttrs attrs, MemTxResult *result);
/**
   * memory_region_dispatch_read: perform a read directly to the specified
diff --git a/system/memory.c b/system/memory.c
index 739ba11da6..48348edb96 100644
--- a/system/memory.c
+++ b/system/memory.c
@@ -1403,14 +1403,22 @@ bool memory_region_access_valid(MemoryRegion *mr,
                                  hwaddr addr,
                                  unsigned size,
                                  bool is_write,
-                                MemTxAttrs attrs)
+                                MemTxAttrs attrs,
+                                MemTxResult *result)
  {
+    if (result) {
+        *result = MEMTX_OK;

Per "exec/memattrs.h":

  /* New-style MMIO accessors can indicate that the transaction failed.
   * A zero (MEMTX_OK) response means success; anything else is a
   * failure of some kind. The memory subsystem will bitwise-OR together
   * results if it is synthesizing an operation from multiple smaller
   * accesses.
   */

The caller should initialize to MEMTX_OK.

+    }
+
      if (mr->ops->valid.accepts
          && !mr->ops->valid.accepts(mr->opaque, addr, size, is_write, attrs)) {
          qemu_log_mask(LOG_INVALID_MEM, "Invalid %s at addr 0x%" HWADDR_PRIX
                        ", size %u, region '%s', reason: rejected\n",
                        is_write ? "write" : "read",
                        addr, size, memory_region_name(mr));
+        if (result) {
+            *result = MEMTX_ACCESS_ERROR;

Here I'd OR.

+        }
          return false;
      }
@@ -1419,6 +1427,9 @@ bool memory_region_access_valid(MemoryRegion *mr,
                        ", size %u, region '%s', reason: unaligned\n",
                        is_write ? "write" : "read",
                        addr, size, memory_region_name(mr));
+        if (result) {
+            *result = MEMTX_DECODE_ERROR;

Ditto.

+        }
          return false;
      }
@@ -1436,6 +1447,9 @@ bool memory_region_access_valid(MemoryRegion *mr,
                        addr, size, memory_region_name(mr),
                        mr->ops->valid.min_access_size,
                        mr->ops->valid.max_access_size);
+        if (result) {
+            *result = MEMTX_DECODE_ERROR;

Ditto.

+        }
          return false;
      }
      return true;
@@ -1478,7 +1492,7 @@ MemTxResult memory_region_dispatch_read(MemoryRegion *mr,
                                             mr->alias_offset + addr,
                                             pval, op, attrs);
      }
-    if (!memory_region_access_valid(mr, addr, size, false, attrs)) {
+    if (!memory_region_access_valid(mr, addr, size, false, attrs, NULL)) {

Surely here you want to propagate the dispatched MR result.

          *pval = unassigned_mem_read(mr, addr, size);
          return MEMTX_DECODE_ERROR;
      }
@@ -1527,7 +1541,7 @@ MemTxResult memory_region_dispatch_write(MemoryRegion *mr,
                                              mr->alias_offset + addr,
                                              data, op, attrs);
      }
-    if (!memory_region_access_valid(mr, addr, size, true, attrs)) {
+    if (!memory_region_access_valid(mr, addr, size, true, attrs, NULL)) {
          unassigned_mem_write(mr, addr, data, size);
          return MEMTX_DECODE_ERROR;

Also here.

      }
diff --git a/system/physmem.c b/system/physmem.c
index 7bcbf87573..a0f77aae66 100644
--- a/system/physmem.c
+++ b/system/physmem.c
@@ -3635,7 +3635,8 @@ static bool flatview_access_valid(FlatView *fv, hwaddr 
addr, hwaddr len,
          mr = flatview_translate(fv, addr, &xlat, &l, is_write, attrs);
          if (!memory_access_is_direct(mr, is_write, attrs)) {
              l = memory_access_size(mr, l, addr);
-            if (!memory_region_access_valid(mr, xlat, l, is_write, attrs)) {
+            if (!memory_region_access_valid(mr, xlat, l, is_write, attrs,
+                                            NULL)) {
                  return false;
              }
          }



Reply via email to