diff mbox

[16/22] memory: accept mismatching sizes in memory_region_access_valid

Message ID 1369947836-2638-17-git-send-email-pbonzini@redhat.com
State New
Headers show

Commit Message

Paolo Bonzini May 30, 2013, 9:03 p.m. UTC
The memory API is able to use smaller/wider accesses than requested,
match that in memory_region_access_valid.  Of course, the accepts
callback is still free to reject those accesses.

Reviewed-by: Richard Henderson <rth@twiddle.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 memory.c |   29 ++++++++++++++++++++---------
 1 files changed, 20 insertions(+), 9 deletions(-)
diff mbox

Patch

diff --git a/memory.c b/memory.c
index 9e1c1a3..c72f56d 100644
--- a/memory.c
+++ b/memory.c
@@ -856,24 +856,35 @@  bool memory_region_access_valid(MemoryRegion *mr,
                                 unsigned size,
                                 bool is_write)
 {
-    if (mr->ops->valid.accepts
-        && !mr->ops->valid.accepts(mr->opaque, addr, size, is_write)) {
-        return false;
-    }
+    int access_size_min, access_size_max;
+    int access_size, i;
 
     if (!mr->ops->valid.unaligned && (addr & (size - 1))) {
         return false;
     }
 
-    /* Treat zero as compatibility all valid */
-    if (!mr->ops->valid.max_access_size) {
+    if (!mr->ops->valid.accepts) {
         return true;
     }
 
-    if (size > mr->ops->valid.max_access_size
-        || size < mr->ops->valid.min_access_size) {
-        return false;
+    access_size_min = mr->ops->valid.min_access_size;
+    if (!mr->ops->valid.min_access_size) {
+        access_size_min = 1;
+    }
+
+    access_size_max = mr->ops->valid.max_access_size;
+    if (!mr->ops->valid.max_access_size) {
+        access_size_max = 4;
+    }
+
+    access_size = MAX(MIN(size, access_size_max), access_size_min);
+    for (i = 0; i < size; i += access_size) {
+        if (!mr->ops->valid.accepts(mr->opaque, addr + i, access_size,
+                                    is_write)) {
+            return false;
+        }
     }
+
     return true;
 }