Split the GROUP_GUEST half of qxl_phys2virt() into the helper qxl_guest_phys2virt(). Also add a bool 'report_bug' param to the qxl_get_check_slot_offset() called from it: when it's false, a failing check just returns false without calling qxl_set_guest_bug(). All existing callers pass true, so there's no functional change. This is in preparation for a quiet caller that validates guest addresses which might be legitimately stale, when flagging a guest bug would be wrong.
Signed-off-by: Andrey Drobyshev <[email protected]> --- hw/display/qxl.c | 83 +++++++++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 32 deletions(-) diff --git a/hw/display/qxl.c b/hw/display/qxl.c index b7d871b9ee3..be620b9c94d 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -1407,7 +1407,7 @@ static void qxl_reset_surfaces(PCIQXLDevice *d) /* can be also called from spice server thread context */ static bool qxl_get_check_slot_offset(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, uint32_t *s, uint64_t *o, - size_t size_requested) + size_t size_requested, bool report_bug) { uint64_t phys = le64_to_cpu(pqxl); uint32_t slot = (phys >> (64 - 8)) & 0xff; @@ -1415,42 +1415,55 @@ static bool qxl_get_check_slot_offset(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, uint64_t size_available; if (slot >= NUM_MEMSLOTS) { - qxl_set_guest_bug(qxl, "slot too large %d >= %d", slot, - NUM_MEMSLOTS); + if (report_bug) { + qxl_set_guest_bug(qxl, "slot too large %d >= %d", slot, + NUM_MEMSLOTS); + } return false; } if (!qxl->guest_slots[slot].active) { - qxl_set_guest_bug(qxl, "inactive slot %d\n", slot); + if (report_bug) { + qxl_set_guest_bug(qxl, "inactive slot %d\n", slot); + } return false; } if (offset < qxl->guest_slots[slot].delta) { - qxl_set_guest_bug(qxl, - "slot %d offset %"PRIu64" < delta %"PRIu64"\n", - slot, offset, qxl->guest_slots[slot].delta); + if (report_bug) { + qxl_set_guest_bug(qxl, + "slot %d offset %"PRIu64" < delta %"PRIu64"\n", + slot, offset, qxl->guest_slots[slot].delta); + } return false; } offset -= qxl->guest_slots[slot].delta; if (offset > qxl->guest_slots[slot].size) { - qxl_set_guest_bug(qxl, - "slot %d offset %"PRIu64" > size %"PRIu64"\n", - slot, offset, qxl->guest_slots[slot].size); + if (report_bug) { + qxl_set_guest_bug(qxl, + "slot %d offset %"PRIu64" > size %"PRIu64"\n", + slot, offset, qxl->guest_slots[slot].size); + } return false; } size_available = memory_region_size(qxl->guest_slots[slot].mr); if (qxl->guest_slots[slot].offset + offset >= size_available) { - qxl_set_guest_bug(qxl, - "slot %d offset %"PRIu64" > region size %"PRIu64"\n", - slot, qxl->guest_slots[slot].offset + offset, - size_available); + if (report_bug) { + qxl_set_guest_bug(qxl, + "slot %d offset %"PRIu64" > region size %"PRIu64 + "\n", slot, + qxl->guest_slots[slot].offset + offset, + size_available); + } return false; } size_available -= qxl->guest_slots[slot].offset + offset; if (size_requested > size_available) { - qxl_set_guest_bug(qxl, - "slot %d offset %"PRIu64" size %zu: " - "overrun by %"PRIu64" bytes\n", - slot, offset, size_requested, - size_requested - size_available); + if (report_bug) { + qxl_set_guest_bug(qxl, + "slot %d offset %"PRIu64" size %zu: " + "overrun by %"PRIu64" bytes\n", + slot, offset, size_requested, + size_requested - size_available); + } return false; } @@ -1460,25 +1473,31 @@ static bool qxl_get_check_slot_offset(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, } /* can be also called from spice server thread context */ -void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id, - size_t size) +static void *qxl_guest_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, + size_t size, bool report_bug) { uint64_t offset; uint32_t slot; - void *ptr; + uint8_t *ptr; + if (!qxl_get_check_slot_offset(qxl, pqxl, &slot, &offset, size, + report_bug)) { + return NULL; + } + ptr = memory_region_get_ram_ptr(qxl->guest_slots[slot].mr); + ptr += qxl->guest_slots[slot].offset; + ptr += offset; + return ptr; +} + +void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id, + size_t size) +{ switch (group_id) { case MEMSLOT_GROUP_HOST: - offset = le64_to_cpu(pqxl) & 0xffffffffffff; - return (void *)(intptr_t)offset; + return (void *)(intptr_t)(le64_to_cpu(pqxl) & 0xffffffffffff); case MEMSLOT_GROUP_GUEST: - if (!qxl_get_check_slot_offset(qxl, pqxl, &slot, &offset, size)) { - return NULL; - } - ptr = memory_region_get_ram_ptr(qxl->guest_slots[slot].mr); - ptr += qxl->guest_slots[slot].offset; - ptr += offset; - return ptr; + return qxl_guest_phys2virt(qxl, pqxl, size, true); } return NULL; } @@ -1942,7 +1961,7 @@ static void qxl_dirty_one_surface(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, bool rc; size = (uint64_t)height * abs(stride); - rc = qxl_get_check_slot_offset(qxl, pqxl, &slot, &offset, size); + rc = qxl_get_check_slot_offset(qxl, pqxl, &slot, &offset, size, true); assert(rc == true); trace_qxl_surfaces_dirty(qxl->id, offset, size); qxl_set_dirty(qxl->guest_slots[slot].mr, -- 2.47.1
