Message ID | alpine.DEB.2.02.1401301223350.4373@kaball.uk.xensource.com |
---|---|
State | New |
Headers | show |
Il 30/01/2014 13:46, Stefano Stabellini ha scritto: > The following commit: > > commit 149f54b53b7666a3facd45e86eece60ce7d3b114 > Author: Paolo Bonzini <pbonzini@redhat.com> > Date: Fri May 24 12:59:37 2013 +0200 > > memory: add address_space_translate > > breaks Xen support in QEMU, in particular the Xen mapcache. The effect > is that one Windows XP installation out of ten would end up with BSOD. > > The reason is that after this commit l in address_space_rw can span a > page boundary, however qemu_get_ram_ptr still calls xen_map_cache asking > to map a single page (if block->offset == 0). > > Fix the issue by reverting to the previous behaviour: do not return a > length from address_space_translate_internal that can span a page > boundary. > > Also in address_space_translate do not ignore the length returned by > address_space_translate_internal. > > This patch should be backported to QEMU 1.6.x. > > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> > Signed-off-by: Anthony Perard <anthony.perard@citrix.com> Tested-by: Paolo Bonzini <pbonzini@redhat.com> Acked-by: Paolo Bonzini <pbonzini@redhat.com> Cc: qemu-stable@nongnu.org > --- > exec.c | 6 ++++-- > 1 files changed, 4 insertions(+), 2 deletions(-) > > diff --git a/exec.c b/exec.c > index 667a718..f3797b7 100644 > --- a/exec.c > +++ b/exec.c > @@ -251,7 +251,7 @@ address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *x > hwaddr *plen, bool resolve_subpage) > { > MemoryRegionSection *section; > - Int128 diff; > + Int128 diff, diff_page; > > section = address_space_lookup_region(d, addr, resolve_subpage); > /* Compute offset within MemoryRegionSection */ > @@ -260,7 +260,9 @@ address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *x > /* Compute offset within MemoryRegion */ > *xlat = addr + section->offset_within_region; > > + diff_page = int128_make64(((addr & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE) - addr); > diff = int128_sub(section->mr->size, int128_make64(addr)); > + diff = int128_min(diff, diff_page); > *plen = int128_get64(int128_min(diff, int128_make64(*plen))); > return section; > } > @@ -275,7 +277,7 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr, > hwaddr len = *plen; > > for (;;) { > - section = address_space_translate_internal(as->dispatch, addr, &addr, plen, true); > + section = address_space_translate_internal(as->dispatch, addr, &addr, &len, true); > mr = section->mr; > > if (!mr->iommu_ops) { > >
diff --git a/exec.c b/exec.c index 667a718..f3797b7 100644 --- a/exec.c +++ b/exec.c @@ -251,7 +251,7 @@ address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *x hwaddr *plen, bool resolve_subpage) { MemoryRegionSection *section; - Int128 diff; + Int128 diff, diff_page; section = address_space_lookup_region(d, addr, resolve_subpage); /* Compute offset within MemoryRegionSection */ @@ -260,7 +260,9 @@ address_space_translate_internal(AddressSpaceDispatch *d, hwaddr addr, hwaddr *x /* Compute offset within MemoryRegion */ *xlat = addr + section->offset_within_region; + diff_page = int128_make64(((addr & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE) - addr); diff = int128_sub(section->mr->size, int128_make64(addr)); + diff = int128_min(diff, diff_page); *plen = int128_get64(int128_min(diff, int128_make64(*plen))); return section; } @@ -275,7 +277,7 @@ MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr, hwaddr len = *plen; for (;;) { - section = address_space_translate_internal(as->dispatch, addr, &addr, plen, true); + section = address_space_translate_internal(as->dispatch, addr, &addr, &len, true); mr = section->mr; if (!mr->iommu_ops) {