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>
This commit is contained in:
Paolo Bonzini 2013-05-24 17:48:52 +02:00
parent 51644ab70b
commit a014ed07bd

View File

@ -856,24 +856,35 @@ bool memory_region_access_valid(MemoryRegion *mr,
unsigned size, unsigned size,
bool is_write) bool is_write)
{ {
if (mr->ops->valid.accepts int access_size_min, access_size_max;
&& !mr->ops->valid.accepts(mr->opaque, addr, size, is_write)) { int access_size, i;
return false;
}
if (!mr->ops->valid.unaligned && (addr & (size - 1))) { if (!mr->ops->valid.unaligned && (addr & (size - 1))) {
return false; return false;
} }
/* Treat zero as compatibility all valid */ if (!mr->ops->valid.accepts) {
if (!mr->ops->valid.max_access_size) {
return true; return true;
} }
if (size > mr->ops->valid.max_access_size access_size_min = mr->ops->valid.min_access_size;
|| size < mr->ops->valid.min_access_size) { if (!mr->ops->valid.min_access_size) {
return false; 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; return true;
} }