aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/display/qxl.c35
-rw-r--r--hw/display/vga.c22
-rw-r--r--hw/mem/pc-dimm.c26
-rw-r--r--hw/usb/hcd-xhci.c15
-rw-r--r--hw/virtio/virtio-balloon.c21
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)