diff options
Diffstat (limited to 'hw')
-rw-r--r-- | hw/display/qxl.c | 35 | ||||
-rw-r--r-- | hw/display/vga.c | 22 | ||||
-rw-r--r-- | hw/mem/pc-dimm.c | 26 | ||||
-rw-r--r-- | hw/usb/hcd-xhci.c | 15 | ||||
-rw-r--r-- | hw/virtio/virtio-balloon.c | 21 |
5 files changed, 84 insertions, 35 deletions
diff --git a/hw/display/qxl.c b/hw/display/qxl.c index 61df477264..762f75dc2d 100644 --- a/hw/display/qxl.c +++ b/hw/display/qxl.c @@ -120,9 +120,12 @@ static QXLMode qxl_modes[] = { QXL_MODE_EX(2560, 2048), QXL_MODE_EX(2800, 2100), QXL_MODE_EX(3200, 2400), + /* these modes need more than 32 MB video memory */ QXL_MODE_EX(3840, 2160), /* 4k mainstream */ QXL_MODE_EX(4096, 2160), /* 4k */ + /* these modes need more than 64 MB video memory */ QXL_MODE_EX(7680, 4320), /* 8k mainstream */ + /* these modes need more than 128 MB video memory */ QXL_MODE_EX(8192, 4320), /* 8k */ }; @@ -297,19 +300,6 @@ void qxl_spice_reset_cursor(PCIQXLDevice *qxl) qxl->ssd.cursor = cursor_builtin_hidden(); } - -static inline uint32_t msb_mask(uint32_t val) -{ - uint32_t mask; - - do { - mask = ~(val - 1) & val; - val &= ~mask; - } while (mask < val); - - return mask; -} - static ram_addr_t qxl_rom_size(void) { uint32_t required_rom_size = sizeof(QXLRom) + sizeof(QXLModes) + @@ -367,6 +357,8 @@ static void init_qxl_rom(PCIQXLDevice *d) num_pages -= surface0_area_size; num_pages = num_pages / QXL_PAGE_SIZE; + assert(ram_header_size + surface0_area_size <= d->vga.vram_size); + rom->draw_area_offset = cpu_to_le32(0); rom->surface0_area_size = cpu_to_le32(surface0_area_size); rom->pages_offset = cpu_to_le32(surface0_area_size); @@ -1155,7 +1147,6 @@ static void qxl_soft_reset(PCIQXLDevice *d) qxl_enter_vga_mode(d); } else { d->mode = QXL_MODE_UNDEFINED; - update_displaychangelistener(&d->ssd.dcl, GUI_REFRESH_INTERVAL_IDLE); } } @@ -1880,6 +1871,12 @@ static void qxl_init_ramsize(PCIQXLDevice *qxl) if (qxl->vgamem_size_mb < 8) { qxl->vgamem_size_mb = 8; } + /* XXX: we round vgamem_size_mb up to a nearest power of two and it must be + * less than vga_common_init()'s maximum on qxl->vga.vram_size (512 now). + */ + if (qxl->vgamem_size_mb > 256) { + qxl->vgamem_size_mb = 256; + } qxl->vgamem_size = qxl->vgamem_size_mb * 1024 * 1024; /* vga ram (bar 0, total) */ @@ -1910,10 +1907,10 @@ static void qxl_init_ramsize(PCIQXLDevice *qxl) qxl->vram32_size = 4096; qxl->vram_size = 4096; } - qxl->vgamem_size = msb_mask(qxl->vgamem_size * 2 - 1); - qxl->vga.vram_size = msb_mask(qxl->vga.vram_size * 2 - 1); - qxl->vram32_size = msb_mask(qxl->vram32_size * 2 - 1); - qxl->vram_size = msb_mask(qxl->vram_size * 2 - 1); + qxl->vgamem_size = pow2ceil(qxl->vgamem_size); + qxl->vga.vram_size = pow2ceil(qxl->vga.vram_size); + qxl->vram32_size = pow2ceil(qxl->vram32_size); + qxl->vram_size = pow2ceil(qxl->vram_size); } static int qxl_init_common(PCIQXLDevice *qxl) @@ -1945,7 +1942,7 @@ static int qxl_init_common(PCIQXLDevice *qxl) break; case 4: /* qxl-4 */ pci_device_rev = QXL_REVISION_STABLE_V12; - io_size = msb_mask(QXL_IO_RANGE_SIZE * 2 - 1); + io_size = pow2ceil(QXL_IO_RANGE_SIZE); break; default: error_report("Invalid revision %d for qxl device (max %d)", diff --git a/hw/display/vga.c b/hw/display/vga.c index c8c49abc6e..c0f7b343bb 100644 --- a/hw/display/vga.c +++ b/hw/display/vga.c @@ -2094,6 +2094,17 @@ static const GraphicHwOps vga_ops = { .text_update = vga_update_text, }; +static inline uint32_t uint_clamp(uint32_t val, uint32_t vmin, uint32_t vmax) +{ + if (val < vmin) { + return vmin; + } + if (val > vmax) { + return vmax; + } + return val; +} + void vga_common_init(VGACommonState *s, Object *obj, bool global_vmstate) { int i, j, v, b; @@ -2121,13 +2132,10 @@ void vga_common_init(VGACommonState *s, Object *obj, bool global_vmstate) expand4to8[i] = v; } - /* valid range: 1 MB -> 256 MB */ - s->vram_size = 1024 * 1024; - while (s->vram_size < (s->vram_size_mb << 20) && - s->vram_size < (256 << 20)) { - s->vram_size <<= 1; - } - s->vram_size_mb = s->vram_size >> 20; + s->vram_size_mb = uint_clamp(s->vram_size_mb, 1, 512); + s->vram_size_mb = pow2ceil(s->vram_size_mb); + s->vram_size = s->vram_size_mb << 20; + if (!s->vbe_size) { s->vbe_size = s->vram_size; } diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c index f27a087061..de81b9ceab 100644 --- a/hw/mem/pc-dimm.c +++ b/hw/mem/pc-dimm.c @@ -100,6 +100,32 @@ int qmp_pc_dimm_device_list(Object *obj, void *opaque) return 0; } +ram_addr_t get_current_ram_size(void) +{ + MemoryDeviceInfoList *info_list = NULL; + MemoryDeviceInfoList **prev = &info_list; + MemoryDeviceInfoList *info; + ram_addr_t size = ram_size; + + qmp_pc_dimm_device_list(qdev_get_machine(), &prev); + for (info = info_list; info; info = info->next) { + MemoryDeviceInfo *value = info->value; + + if (value) { + switch (value->kind) { + case MEMORY_DEVICE_INFO_KIND_DIMM: + size += value->dimm->size; + break; + default: + break; + } + } + } + qapi_free_MemoryDeviceInfoList(info_list); + + return size; +} + static int pc_dimm_slot2bitmap(Object *obj, void *opaque) { unsigned long *bitmap = opaque; diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c index 776699b44e..828c2a7d78 100644 --- a/hw/usb/hcd-xhci.c +++ b/hw/usb/hcd-xhci.c @@ -1767,9 +1767,18 @@ static void xhci_xfer_report(XHCITransfer *xfer) break; } - if (!reported && ((trb->control & TRB_TR_IOC) || - (shortpkt && (trb->control & TRB_TR_ISP)) || - (xfer->status != CC_SUCCESS && left == 0))) { + /* + * XHCI 1.1, 4.11.3.1 Transfer Event TRB -- "each Transfer TRB + * encountered with its IOC flag set to '1' shall generate a Transfer + * Event." + * + * Otherwise, longer transfers can have multiple data TRBs (for scatter + * gather). Short transfers and errors should be reported once per + * transfer only. + */ + if ((trb->control & TRB_TR_IOC) || + (!reported && ((shortpkt && (trb->control & TRB_TR_ISP)) || + (xfer->status != CC_SUCCESS && left == 0)))) { event.slotid = xfer->slotid; event.epid = xfer->epid; event.length = (trb->status & 0x1ffff) - chunk; diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c index 7bfbb75ad3..8a48d2a178 100644 --- a/hw/virtio/virtio-balloon.c +++ b/hw/virtio/virtio-balloon.c @@ -25,6 +25,7 @@ #include "exec/address-spaces.h" #include "qapi/visitor.h" #include "qapi-event.h" +#include "trace.h" #if defined(__linux__) #include <sys/mman.h> @@ -222,6 +223,8 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq) if (!int128_nz(section.size) || !memory_region_is_ram(section.mr)) continue; + trace_virtio_balloon_handle_output(memory_region_name(section.mr), + pa); /* Using memory_region_get_ram_ptr is bending the rules a bit, but should be OK because we only want a single page. */ addr = section.offset_within_region; @@ -285,6 +288,7 @@ static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data) config.num_pages = cpu_to_le32(dev->num_pages); config.actual = cpu_to_le32(dev->actual); + trace_virtio_balloon_get_config(config.num_pages, config.actual); memcpy(config_data, &config, sizeof(struct virtio_balloon_config)); } @@ -294,13 +298,16 @@ static void virtio_balloon_set_config(VirtIODevice *vdev, VirtIOBalloon *dev = VIRTIO_BALLOON(vdev); struct virtio_balloon_config config; uint32_t oldactual = dev->actual; + ram_addr_t vm_ram_size = get_current_ram_size(); + memcpy(&config, config_data, sizeof(struct virtio_balloon_config)); dev->actual = le32_to_cpu(config.actual); if (dev->actual != oldactual) { - qapi_event_send_balloon_change(ram_size - + qapi_event_send_balloon_change(vm_ram_size - ((ram_addr_t) dev->actual << VIRTIO_BALLOON_PFN_SHIFT), &error_abort); } + trace_virtio_balloon_set_config(dev->actual, oldactual); } static uint32_t virtio_balloon_get_features(VirtIODevice *vdev, uint32_t f) @@ -312,22 +319,24 @@ static uint32_t virtio_balloon_get_features(VirtIODevice *vdev, uint32_t f) static void virtio_balloon_stat(void *opaque, BalloonInfo *info) { VirtIOBalloon *dev = opaque; - info->actual = ram_size - ((uint64_t) dev->actual << - VIRTIO_BALLOON_PFN_SHIFT); + info->actual = get_current_ram_size() - ((uint64_t) dev->actual << + VIRTIO_BALLOON_PFN_SHIFT); } static void virtio_balloon_to_target(void *opaque, ram_addr_t target) { VirtIOBalloon *dev = VIRTIO_BALLOON(opaque); VirtIODevice *vdev = VIRTIO_DEVICE(dev); + ram_addr_t vm_ram_size = get_current_ram_size(); - if (target > ram_size) { - target = ram_size; + if (target > vm_ram_size) { + target = vm_ram_size; } if (target) { - dev->num_pages = (ram_size - target) >> VIRTIO_BALLOON_PFN_SHIFT; + dev->num_pages = (vm_ram_size - target) >> VIRTIO_BALLOON_PFN_SHIFT; virtio_notify_config(vdev); } + trace_virtio_balloon_to_target(target, dev->num_pages); } static void virtio_balloon_save(QEMUFile *f, void *opaque) |