Message ID | 1369133851-1894-14-git-send-email-pbonzini@redhat.com |
---|---|
State | New |
Headers | show |
On 21 May 2013 11:57, Paolo Bonzini <pbonzini@redhat.com> wrote: > From: Avi Kivity <avi.kivity@gmail.com> > > The radix tree is statically sized to fit TARGET_PHYS_ADDR_SPACE_BITS. > If a larger memory region is registered, it will overflow. > > Fix by limiting any section in the radix tree to the supported size. > > This problem was not observed earlier since artificial regions (containers > and aliases) are eliminated by the memory core, leaving only device regions > which have reasonable sizes. An IOMMU however cannot be eliminated by the > memory core, and may have an artificial size. > > Signed-off-by: Avi Kivity <avi.kivity@gmail.com> > [ Fail the build if TARGET_PHYS_ADDR_SPACE_BITS is too large - Paolo ] > Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> -- PMM
diff --git a/exec.c b/exec.c index 380245f..8d91221 100644 --- a/exec.c +++ b/exec.c @@ -771,10 +771,21 @@ static void register_multipage(AddressSpaceDispatch *d, MemoryRegionSection *sec section_index); } +QEMU_BUILD_BUG_ON(TARGET_PHYS_ADDR_SPACE_BITS > MAX_PHYS_ADDR_SPACE_BITS) + +static MemoryRegionSection limit(MemoryRegionSection section) +{ + section.size = MIN(section.offset_within_address_space + section.size, + MAX_PHYS_ADDR + 1) + - section.offset_within_address_space; + + return section; +} + static void mem_add(MemoryListener *listener, MemoryRegionSection *section) { AddressSpaceDispatch *d = container_of(listener, AddressSpaceDispatch, listener); - MemoryRegionSection now = *section, remain = *section; + MemoryRegionSection now = limit(*section), remain = limit(*section); if ((now.offset_within_address_space & ~TARGET_PAGE_MASK) || (now.size < TARGET_PAGE_SIZE)) { diff --git a/include/exec/memory.h b/include/exec/memory.h index 9fae89b..6ed593c 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -26,6 +26,9 @@ #include "exec/ioport.h" #include "qemu/int128.h" +#define MAX_PHYS_ADDR_SPACE_BITS 62 +#define MAX_PHYS_ADDR (((hwaddr)1 << MAX_PHYS_ADDR_SPACE_BITS) - 1) + typedef struct MemoryRegionOps MemoryRegionOps; typedef struct MemoryRegionPortio MemoryRegionPortio; typedef struct MemoryRegionMmio MemoryRegionMmio;