diff options
author | David Hildenbrand | 2017-09-11 19:49:29 +0200 |
---|---|---|
committer | Paolo Bonzini | 2017-09-19 14:09:33 +0200 |
commit | 5ea69c2e36148e5b5607f0919756c12c9637039b (patch) | |
tree | ba03b079893a55773a42debafab79a2f53c076ac /accel/kvm | |
parent | kvm: require JOIN_MEMORY_REGIONS_WORKS (diff) | |
download | qemu-5ea69c2e36148e5b5607f0919756c12c9637039b.tar.gz qemu-5ea69c2e36148e5b5607f0919756c12c9637039b.tar.xz qemu-5ea69c2e36148e5b5607f0919756c12c9637039b.zip |
kvm: factor out alignment of memory section
Factor it out, so we can reuse it later.
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20170911174933.20789-3-david@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'accel/kvm')
-rw-r--r-- | accel/kvm/kvm-all.c | 59 |
1 files changed, 39 insertions, 20 deletions
diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index 985b179ab6..e0d100bd30 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -190,6 +190,36 @@ static KVMSlot *kvm_lookup_matching_slot(KVMMemoryListener *kml, } /* + * Calculate and align the start address and the size of the section. + * Return the size. If the size is 0, the aligned section is empty. + */ +static hwaddr kvm_align_section(MemoryRegionSection *section, + hwaddr *start) +{ + hwaddr size = int128_get64(section->size); + hwaddr delta; + + *start = section->offset_within_address_space; + + /* kvm works in page size chunks, but the function may be called + with sub-page size and unaligned start address. Pad the start + address to next and truncate size to previous page boundary. */ + delta = qemu_real_host_page_size - (*start & ~qemu_real_host_page_mask); + delta &= ~qemu_real_host_page_mask; + *start += delta; + if (delta > size) { + return 0; + } + size -= delta; + size &= qemu_real_host_page_mask; + if (*start & ~qemu_real_host_page_mask) { + return 0; + } + + return size; +} + +/* * Find overlapping slot with lowest start address */ static KVMSlot *kvm_lookup_overlapping_slot(KVMMemoryListener *kml, @@ -700,25 +730,8 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml, int err; MemoryRegion *mr = section->mr; bool writeable = !mr->readonly && !mr->rom_device; - hwaddr start_addr = section->offset_within_address_space; - ram_addr_t size = int128_get64(section->size); - void *ram = NULL; - unsigned delta; - - /* kvm works in page size chunks, but the function may be called - with sub-page size and unaligned start address. Pad the start - address to next and truncate size to previous page boundary. */ - delta = qemu_real_host_page_size - (start_addr & ~qemu_real_host_page_mask); - delta &= ~qemu_real_host_page_mask; - if (delta > size) { - return; - } - start_addr += delta; - size -= delta; - size &= qemu_real_host_page_mask; - if (!size || (start_addr & ~qemu_real_host_page_mask)) { - return; - } + hwaddr start_addr, size; + void *ram; if (!memory_region_is_ram(mr)) { if (writeable || !kvm_readonly_mem_allowed) { @@ -730,7 +743,13 @@ static void kvm_set_phys_mem(KVMMemoryListener *kml, } } - ram = memory_region_get_ram_ptr(mr) + section->offset_within_region + delta; + size = kvm_align_section(section, &start_addr); + if (!size) { + return; + } + + ram = memory_region_get_ram_ptr(mr) + section->offset_within_region + + (section->offset_within_address_space - start_addr); while (1) { mem = kvm_lookup_overlapping_slot(kml, start_addr, start_addr + size); |