diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2013-05-24 17:48:52 +0200 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2013-05-29 16:27:19 +0200 |
commit | a014ed07bd5a93950fe12c88ed5faf188a22ee01 (patch) | |
tree | ae363638e88c6f77b4e301610ac7d3207ab9dc0e | |
parent | 51644ab70ba125cb9545702d64890743d75b444b (diff) |
memory: accept mismatching sizes in memory_region_access_valid
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>
-rw-r--r-- | memory.c | 29 |
1 files changed, 20 insertions, 9 deletions
@@ -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; } |