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

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/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c
index 10066ca618..877ed84b94 100644
--- a/hw/s390x/s390-pci-inst.c
+++ b/hw/s390x/s390-pci-inst.c
@@ -904,7 +904,7 @@ int pcistb_service_call(S390CPU *cpu, uint8_t r1, uint8_t 
r3, uint64_t gaddr,
 
     for (i = 0; i < len; i += 8) {
         if (!memory_region_access_valid(mr, offset + i, 8, true,
-                                        MEMTXATTRS_UNSPECIFIED)) {
+                                        MEMTXATTRS_UNSPECIFIED, NULL)) {
             s390_program_interrupt(env, PGM_OPERAND, ra);
             return 0;
         }
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);
 
 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;
+    }
+
     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;
+        }
         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;
+        }
         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;
+        }
         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)) {
         *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;
     }
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;
             }
         }
-- 
2.43.0


Reply via email to