summaryrefslogtreecommitdiffstats
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2015-06-08 15:57:41 +0100
committerPeter Maydell <peter.maydell@linaro.org>2015-06-08 15:57:41 +0100
commitee09f84e6bf5383a23c9624115c26b72aa1e076c (patch)
tree49fe5c021ca71f8be8fc6ae630d4792c5b8b9354 /hw
parent2e29dd7c44db30e3d3c108ab2a622cbdac6d16f0 (diff)
parent24a314269281a175b5540b3b6a8981ed2e8220e1 (diff)
downloadhqemu-ee09f84e6bf5383a23c9624115c26b72aa1e076c.zip
hqemu-ee09f84e6bf5383a23c9624115c26b72aa1e076c.tar.gz
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
* KVM error improvement from Laurent * CONFIG_PARALLEL fix from Mirek * Atomic/optimized dirty bitmap access from myself and Stefan * BUILD_DIR convenience/bugfix from Peter C * Memory leak fix from Shannon * SMM improvements (though still TCG only) from myself and Gerd, acked by mst # gpg: Signature made Fri Jun 5 18:45:20 2015 BST using RSA key ID 78C7AE83 # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" # gpg: WARNING: This key is not certified with sufficiently trusted signatures! # gpg: It is not certain that the signature belongs to the owner. # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * remotes/bonzini/tags/for-upstream: (62 commits) update Linux headers from kvm/next atomics: add explicit compiler fence in __atomic memory barriers ich9: implement SMI_LOCK q35: implement TSEG q35: add test for SMRAM.D_LCK q35: implement SMRAM.D_LCK q35: add config space wmask for SMRAM and ESMRAMC q35: fix ESMRAMC default q35: implement high SMRAM hw/i386: remove smram_update target-i386: use memory API to implement SMRAM hw/i386: add a separate region that tracks the SMRAME bit target-i386: create a separate AddressSpace for each CPU vl: run "late" notifiers immediately qom: add object_property_add_const_link vl: allow full-blown QemuOpts syntax for -global pflash_cfi01: add secure property pflash_cfi01: change to new-style MMIO accessors pflash_cfi01: change big-endian property to BIT type target-i386: wake up processors that receive an SMI ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/acpi/ich9.c4
-rw-r--r--hw/arm/vexpress.c2
-rw-r--r--hw/arm/virt.c2
-rw-r--r--hw/block/pflash_cfi01.c204
-rw-r--r--hw/char/parallel.c25
-rw-r--r--hw/display/cg3.c2
-rw-r--r--hw/display/exynos4210_fimd.c20
-rw-r--r--hw/display/framebuffer.c4
-rw-r--r--hw/display/g364fb.c3
-rw-r--r--hw/display/sm501.c2
-rw-r--r--hw/display/tcx.c3
-rw-r--r--hw/display/vmware_vga.c2
-rw-r--r--hw/i386/pc.c21
-rw-r--r--hw/isa/isa-bus.c26
-rw-r--r--hw/isa/lpc_ich9.c19
-rw-r--r--hw/pci-host/pam.c20
-rw-r--r--hw/pci-host/piix.c44
-rw-r--r--hw/pci-host/q35.c142
-rw-r--r--hw/virtio/dataplane/vring.c2
-rw-r--r--hw/virtio/vhost.c9
20 files changed, 311 insertions, 245 deletions
diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
index 799351e..25bc023 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -94,7 +94,8 @@ static void ich9_smi_writel(void *opaque, hwaddr addr, uint64_t val,
ICH9LPCPMRegs *pm = opaque;
switch (addr) {
case 0:
- pm->smi_en = val;
+ pm->smi_en &= ~pm->smi_en_wmask;
+ pm->smi_en |= (val & pm->smi_en_wmask);
break;
}
}
@@ -198,6 +199,7 @@ static void pm_reset(void *opaque)
* support SMM mode. */
pm->smi_en |= ICH9_PMIO_SMI_EN_APMC_EN;
}
+ pm->smi_en_wmask = ~0;
acpi_update_sci(&pm->acpi_regs, pm->irq);
}
diff --git a/hw/arm/vexpress.c b/hw/arm/vexpress.c
index 8f1a5ea..da21788 100644
--- a/hw/arm/vexpress.c
+++ b/hw/arm/vexpress.c
@@ -525,7 +525,7 @@ static pflash_t *ve_pflash_cfi01_register(hwaddr base, const char *name,
qdev_prop_set_uint64(dev, "sector-length", VEXPRESS_FLASH_SECT_SIZE);
qdev_prop_set_uint8(dev, "width", 4);
qdev_prop_set_uint8(dev, "device-width", 2);
- qdev_prop_set_uint8(dev, "big-endian", 0);
+ qdev_prop_set_bit(dev, "big-endian", false);
qdev_prop_set_uint16(dev, "id0", 0x89);
qdev_prop_set_uint16(dev, "id1", 0x18);
qdev_prop_set_uint16(dev, "id2", 0x00);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 0a75cc8..1b1cc71 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -555,7 +555,7 @@ static void create_one_flash(const char *name, hwaddr flashbase,
qdev_prop_set_uint64(dev, "sector-length", sectorlength);
qdev_prop_set_uint8(dev, "width", 4);
qdev_prop_set_uint8(dev, "device-width", 2);
- qdev_prop_set_uint8(dev, "big-endian", 0);
+ qdev_prop_set_bit(dev, "big-endian", false);
qdev_prop_set_uint16(dev, "id0", 0x89);
qdev_prop_set_uint16(dev, "id1", 0x18);
qdev_prop_set_uint16(dev, "id2", 0x00);
diff --git a/hw/block/pflash_cfi01.c b/hw/block/pflash_cfi01.c
index d282695..2ba6c77 100644
--- a/hw/block/pflash_cfi01.c
+++ b/hw/block/pflash_cfi01.c
@@ -64,6 +64,9 @@ do { \
#define TYPE_CFI_PFLASH01 "cfi.pflash01"
#define CFI_PFLASH01(obj) OBJECT_CHECK(pflash_t, (obj), TYPE_CFI_PFLASH01)
+#define PFLASH_BE 0
+#define PFLASH_SECURE 1
+
struct pflash_t {
/*< private >*/
SysBusDevice parent_obj;
@@ -75,7 +78,7 @@ struct pflash_t {
uint8_t bank_width;
uint8_t device_width; /* If 0, device width not specified. */
uint8_t max_device_width; /* max device width in bytes */
- uint8_t be;
+ uint32_t features;
uint8_t wcycle; /* if 0, the flash is read normally */
int ro;
uint8_t cmd;
@@ -235,12 +238,57 @@ static uint32_t pflash_devid_query(pflash_t *pfl, hwaddr offset)
return resp;
}
+static uint32_t pflash_data_read(pflash_t *pfl, hwaddr offset,
+ int width, int be)
+{
+ uint8_t *p;
+ uint32_t ret;
+
+ p = pfl->storage;
+ switch (width) {
+ case 1:
+ ret = p[offset];
+ DPRINTF("%s: data offset " TARGET_FMT_plx " %02x\n",
+ __func__, offset, ret);
+ break;
+ case 2:
+ if (be) {
+ ret = p[offset] << 8;
+ ret |= p[offset + 1];
+ } else {
+ ret = p[offset];
+ ret |= p[offset + 1] << 8;
+ }
+ DPRINTF("%s: data offset " TARGET_FMT_plx " %04x\n",
+ __func__, offset, ret);
+ break;
+ case 4:
+ if (be) {
+ ret = p[offset] << 24;
+ ret |= p[offset + 1] << 16;
+ ret |= p[offset + 2] << 8;
+ ret |= p[offset + 3];
+ } else {
+ ret = p[offset];
+ ret |= p[offset + 1] << 8;
+ ret |= p[offset + 2] << 16;
+ ret |= p[offset + 3] << 24;
+ }
+ DPRINTF("%s: data offset " TARGET_FMT_plx " %08x\n",
+ __func__, offset, ret);
+ break;
+ default:
+ DPRINTF("BUG in %s\n", __func__);
+ abort();
+ }
+ return ret;
+}
+
static uint32_t pflash_read (pflash_t *pfl, hwaddr offset,
int width, int be)
{
hwaddr boff;
uint32_t ret;
- uint8_t *p;
ret = -1;
@@ -257,43 +305,7 @@ static uint32_t pflash_read (pflash_t *pfl, hwaddr offset,
/* fall through to read code */
case 0x00:
/* Flash area read */
- p = pfl->storage;
- switch (width) {
- case 1:
- ret = p[offset];
- DPRINTF("%s: data offset " TARGET_FMT_plx " %02x\n",
- __func__, offset, ret);
- break;
- case 2:
- if (be) {
- ret = p[offset] << 8;
- ret |= p[offset + 1];
- } else {
- ret = p[offset];
- ret |= p[offset + 1] << 8;
- }
- DPRINTF("%s: data offset " TARGET_FMT_plx " %04x\n",
- __func__, offset, ret);
- break;
- case 4:
- if (be) {
- ret = p[offset] << 24;
- ret |= p[offset + 1] << 16;
- ret |= p[offset + 2] << 8;
- ret |= p[offset + 3];
- } else {
- ret = p[offset];
- ret |= p[offset + 1] << 8;
- ret |= p[offset + 2] << 16;
- ret |= p[offset + 3] << 24;
- }
- DPRINTF("%s: data offset " TARGET_FMT_plx " %08x\n",
- __func__, offset, ret);
- break;
- default:
- DPRINTF("BUG in %s\n", __func__);
- }
-
+ ret = pflash_data_read(pfl, offset, width, be);
break;
case 0x10: /* Single byte program */
case 0x20: /* Block erase */
@@ -648,101 +660,37 @@ static void pflash_write(pflash_t *pfl, hwaddr offset,
}
-static uint32_t pflash_readb_be(void *opaque, hwaddr addr)
-{
- return pflash_read(opaque, addr, 1, 1);
-}
-
-static uint32_t pflash_readb_le(void *opaque, hwaddr addr)
-{
- return pflash_read(opaque, addr, 1, 0);
-}
-
-static uint32_t pflash_readw_be(void *opaque, hwaddr addr)
-{
- pflash_t *pfl = opaque;
-
- return pflash_read(pfl, addr, 2, 1);
-}
-
-static uint32_t pflash_readw_le(void *opaque, hwaddr addr)
-{
- pflash_t *pfl = opaque;
-
- return pflash_read(pfl, addr, 2, 0);
-}
-
-static uint32_t pflash_readl_be(void *opaque, hwaddr addr)
-{
- pflash_t *pfl = opaque;
-
- return pflash_read(pfl, addr, 4, 1);
-}
-
-static uint32_t pflash_readl_le(void *opaque, hwaddr addr)
+static MemTxResult pflash_mem_read_with_attrs(void *opaque, hwaddr addr, uint64_t *value,
+ unsigned len, MemTxAttrs attrs)
{
pflash_t *pfl = opaque;
+ bool be = !!(pfl->features & (1 << PFLASH_BE));
- return pflash_read(pfl, addr, 4, 0);
-}
-
-static void pflash_writeb_be(void *opaque, hwaddr addr,
- uint32_t value)
-{
- pflash_write(opaque, addr, value, 1, 1);
-}
-
-static void pflash_writeb_le(void *opaque, hwaddr addr,
- uint32_t value)
-{
- pflash_write(opaque, addr, value, 1, 0);
-}
-
-static void pflash_writew_be(void *opaque, hwaddr addr,
- uint32_t value)
-{
- pflash_t *pfl = opaque;
-
- pflash_write(pfl, addr, value, 2, 1);
-}
-
-static void pflash_writew_le(void *opaque, hwaddr addr,
- uint32_t value)
-{
- pflash_t *pfl = opaque;
-
- pflash_write(pfl, addr, value, 2, 0);
-}
-
-static void pflash_writel_be(void *opaque, hwaddr addr,
- uint32_t value)
-{
- pflash_t *pfl = opaque;
-
- pflash_write(pfl, addr, value, 4, 1);
+ if ((pfl->features & (1 << PFLASH_SECURE)) && !attrs.secure) {
+ *value = pflash_data_read(opaque, addr, len, be);
+ } else {
+ *value = pflash_read(opaque, addr, len, be);
+ }
+ return MEMTX_OK;
}
-static void pflash_writel_le(void *opaque, hwaddr addr,
- uint32_t value)
+static MemTxResult pflash_mem_write_with_attrs(void *opaque, hwaddr addr, uint64_t value,
+ unsigned len, MemTxAttrs attrs)
{
pflash_t *pfl = opaque;
+ bool be = !!(pfl->features & (1 << PFLASH_BE));
- pflash_write(pfl, addr, value, 4, 0);
+ if ((pfl->features & (1 << PFLASH_SECURE)) && !attrs.secure) {
+ return MEMTX_ERROR;
+ } else {
+ pflash_write(opaque, addr, value, len, be);
+ return MEMTX_OK;
+ }
}
-static const MemoryRegionOps pflash_cfi01_ops_be = {
- .old_mmio = {
- .read = { pflash_readb_be, pflash_readw_be, pflash_readl_be, },
- .write = { pflash_writeb_be, pflash_writew_be, pflash_writel_be, },
- },
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static const MemoryRegionOps pflash_cfi01_ops_le = {
- .old_mmio = {
- .read = { pflash_readb_le, pflash_readw_le, pflash_readl_le, },
- .write = { pflash_writeb_le, pflash_writew_le, pflash_writel_le, },
- },
+static const MemoryRegionOps pflash_cfi01_ops = {
+ .read_with_attrs = pflash_mem_read_with_attrs,
+ .write_with_attrs = pflash_mem_write_with_attrs,
.endianness = DEVICE_NATIVE_ENDIAN,
};
@@ -773,7 +721,8 @@ static void pflash_cfi01_realize(DeviceState *dev, Error **errp)
memory_region_init_rom_device(
&pfl->mem, OBJECT(dev),
- pfl->be ? &pflash_cfi01_ops_be : &pflash_cfi01_ops_le, pfl,
+ &pflash_cfi01_ops,
+ pfl,
pfl->name, total_len, &local_err);
if (local_err) {
error_propagate(errp, local_err);
@@ -925,7 +874,8 @@ static Property pflash_cfi01_properties[] = {
DEFINE_PROP_UINT8("width", struct pflash_t, bank_width, 0),
DEFINE_PROP_UINT8("device-width", struct pflash_t, device_width, 0),
DEFINE_PROP_UINT8("max-device-width", struct pflash_t, max_device_width, 0),
- DEFINE_PROP_UINT8("big-endian", struct pflash_t, be, 0),
+ DEFINE_PROP_BIT("big-endian", struct pflash_t, features, PFLASH_BE, 0),
+ DEFINE_PROP_BIT("secure", struct pflash_t, features, PFLASH_SECURE, 0),
DEFINE_PROP_UINT16("id0", struct pflash_t, ident0, 0),
DEFINE_PROP_UINT16("id1", struct pflash_t, ident1, 0),
DEFINE_PROP_UINT16("id2", struct pflash_t, ident2, 0),
@@ -975,7 +925,7 @@ pflash_t *pflash_cfi01_register(hwaddr base,
qdev_prop_set_uint32(dev, "num-blocks", nb_blocs);
qdev_prop_set_uint64(dev, "sector-length", sector_len);
qdev_prop_set_uint8(dev, "width", bank_width);
- qdev_prop_set_uint8(dev, "big-endian", !!be);
+ qdev_prop_set_bit(dev, "big-endian", !!be);
qdev_prop_set_uint16(dev, "id0", id0);
qdev_prop_set_uint16(dev, "id1", id1);
qdev_prop_set_uint16(dev, "id2", id2);
diff --git a/hw/char/parallel.c b/hw/char/parallel.c
index 4079554..c2b553f 100644
--- a/hw/char/parallel.c
+++ b/hw/char/parallel.c
@@ -641,28 +641,3 @@ static void parallel_register_types(void)
}
type_init(parallel_register_types)
-
-static void parallel_init(ISABus *bus, int index, CharDriverState *chr)
-{
- DeviceState *dev;
- ISADevice *isadev;
-
- isadev = isa_create(bus, "isa-parallel");
- dev = DEVICE(isadev);
- qdev_prop_set_uint32(dev, "index", index);
- qdev_prop_set_chr(dev, "chardev", chr);
- qdev_init_nofail(dev);
-}
-
-void parallel_hds_isa_init(ISABus *bus, int n)
-{
- int i;
-
- assert(n <= MAX_PARALLEL_PORTS);
-
- for (i = 0; i < n; i++) {
- if (parallel_hds[i]) {
- parallel_init(bus, i, parallel_hds[i]);
- }
- }
-}
diff --git a/hw/display/cg3.c b/hw/display/cg3.c
index 1e6ff2b..b94e5e0 100644
--- a/hw/display/cg3.c
+++ b/hw/display/cg3.c
@@ -106,6 +106,7 @@ static void cg3_update_display(void *opaque)
pix = memory_region_get_ram_ptr(&s->vram_mem);
data = (uint32_t *)surface_data(surface);
+ memory_region_sync_dirty_bitmap(&s->vram_mem);
for (y = 0; y < height; y++) {
int update = s->full_update;
@@ -309,6 +310,7 @@ static void cg3_realizefn(DeviceState *dev, Error **errp)
memory_region_init_ram(&s->vram_mem, NULL, "cg3.vram", s->vram_size,
&error_abort);
+ memory_region_set_log(&s->vram_mem, true, DIRTY_MEMORY_VGA);
vmstate_register_ram_global(&s->vram_mem);
sysbus_init_mmio(sbd, &s->vram_mem);
diff --git a/hw/display/exynos4210_fimd.c b/hw/display/exynos4210_fimd.c
index 45c62af..72b3a1d 100644
--- a/hw/display/exynos4210_fimd.c
+++ b/hw/display/exynos4210_fimd.c
@@ -1109,6 +1109,12 @@ static inline int fimd_get_buffer_id(Exynos4210fimdWindow *w)
}
}
+static void exynos4210_fimd_invalidate(void *opaque)
+{
+ Exynos4210fimdState *s = (Exynos4210fimdState *)opaque;
+ s->invalidate = true;
+}
+
/* Updates specified window's MemorySection based on values of WINCON,
* VIDOSDA, VIDOSDB, VIDWADDx and SHADOWCON registers */
static void fimd_update_memory_section(Exynos4210fimdState *s, unsigned win)
@@ -1136,7 +1142,11 @@ static void fimd_update_memory_section(Exynos4210fimdState *s, unsigned win)
/* TODO: add .exit and unref the region there. Not needed yet since sysbus
* does not support hot-unplug.
*/
- memory_region_unref(w->mem_section.mr);
+ if (w->mem_section.mr) {
+ memory_region_set_log(w->mem_section.mr, false, DIRTY_MEMORY_VGA);
+ memory_region_unref(w->mem_section.mr);
+ }
+
w->mem_section = memory_region_find(sysbus_address_space(sbd),
fb_start_addr, w->fb_len);
assert(w->mem_section.mr);
@@ -1162,6 +1172,8 @@ static void fimd_update_memory_section(Exynos4210fimdState *s, unsigned win)
cpu_physical_memory_unmap(w->host_fb_addr, fb_mapped_len, 0, 0);
goto error_return;
}
+ memory_region_set_log(w->mem_section.mr, true, DIRTY_MEMORY_VGA);
+ exynos4210_fimd_invalidate(s);
return;
error_return:
@@ -1224,12 +1236,6 @@ static void exynos4210_fimd_update_irq(Exynos4210fimdState *s)
}
}
-static void exynos4210_fimd_invalidate(void *opaque)
-{
- Exynos4210fimdState *s = (Exynos4210fimdState *)opaque;
- s->invalidate = true;
-}
-
static void exynos4210_update_resolution(Exynos4210fimdState *s)
{
DisplaySurface *surface = qemu_console_surface(s->console);
diff --git a/hw/display/framebuffer.c b/hw/display/framebuffer.c
index 4546e42..2cabced 100644
--- a/hw/display/framebuffer.c
+++ b/hw/display/framebuffer.c
@@ -63,6 +63,10 @@ void framebuffer_update_display(
assert(mem_section.offset_within_address_space == base);
memory_region_sync_dirty_bitmap(mem);
+ if (!memory_region_is_logging(mem, DIRTY_MEMORY_VGA)) {
+ invalidate = true;
+ }
+
src_base = cpu_physical_memory_map(base, &src_len, 0);
/* If we can't map the framebuffer then bail. We could try harder,
but it's not really worth it as dirty flag tracking will probably
diff --git a/hw/display/g364fb.c b/hw/display/g364fb.c
index 46f7b41..52a9733 100644
--- a/hw/display/g364fb.c
+++ b/hw/display/g364fb.c
@@ -260,6 +260,7 @@ static void g364fb_update_display(void *opaque)
qemu_console_resize(s->con, s->width, s->height);
}
+ memory_region_sync_dirty_bitmap(&s->mem_vram);
if (s->ctla & CTLA_FORCE_BLANK) {
g364fb_draw_blank(s);
} else if (s->depth == 8) {
@@ -489,7 +490,7 @@ static void g364fb_init(DeviceState *dev, G364State *s)
memory_region_init_ram_ptr(&s->mem_vram, NULL, "vram",
s->vram_size, s->vram);
vmstate_register_ram(&s->mem_vram, dev);
- memory_region_set_coalescing(&s->mem_vram);
+ memory_region_set_log(&s->mem_vram, true, DIRTY_MEMORY_VGA);
}
#define TYPE_G364 "sysbus-g364"
diff --git a/hw/display/sm501.c b/hw/display/sm501.c
index c72154b..15a5ba8 100644
--- a/hw/display/sm501.c
+++ b/hw/display/sm501.c
@@ -1322,6 +1322,7 @@ static void sm501_draw_crt(SM501State * s)
}
/* draw each line according to conditions */
+ memory_region_sync_dirty_bitmap(&s->local_mem_region);
for (y = 0; y < height; y++) {
int update_hwc = draw_hwc_line ? within_hwc_y_range(s, y, 1) : 0;
int update = full_update || update_hwc;
@@ -1412,6 +1413,7 @@ void sm501_init(MemoryRegion *address_space_mem, uint32_t base,
memory_region_init_ram(&s->local_mem_region, NULL, "sm501.local",
local_mem_bytes, &error_abort);
vmstate_register_ram_global(&s->local_mem_region);
+ memory_region_set_log(&s->local_mem_region, true, DIRTY_MEMORY_VGA);
s->local_mem = memory_region_get_ram_ptr(&s->local_mem_region);
memory_region_add_subregion(address_space_mem, base, &s->local_mem_region);
diff --git a/hw/display/tcx.c b/hw/display/tcx.c
index a9f9f66..f3faf78 100644
--- a/hw/display/tcx.c
+++ b/hw/display/tcx.c
@@ -353,6 +353,7 @@ static void tcx_update_display(void *opaque)
return;
}
+ memory_region_sync_dirty_bitmap(&ts->vram_mem);
for (y = 0; y < ts->height; page += TARGET_PAGE_SIZE) {
if (memory_region_get_dirty(&ts->vram_mem, page, TARGET_PAGE_SIZE,
DIRTY_MEMORY_VGA)) {
@@ -446,6 +447,7 @@ static void tcx24_update_display(void *opaque)
dd = surface_stride(surface);
ds = 1024;
+ memory_region_sync_dirty_bitmap(&ts->vram_mem);
for (y = 0; y < ts->height; page += TARGET_PAGE_SIZE,
page24 += TARGET_PAGE_SIZE, cpage += TARGET_PAGE_SIZE) {
if (tcx24_check_dirty(ts, page, page24, cpage)) {
@@ -1006,6 +1008,7 @@ static void tcx_realizefn(DeviceState *dev, Error **errp)
memory_region_init_ram(&s->vram_mem, OBJECT(s), "tcx.vram",
s->vram_size * (1 + 4 + 4), &error_abort);
vmstate_register_ram_global(&s->vram_mem);
+ memory_region_set_log(&s->vram_mem, true, DIRTY_MEMORY_VGA);
vram_base = memory_region_get_ram_ptr(&s->vram_mem);
/* 10/ROM : FCode ROM */
diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
index c17ddd1..7f397d3 100644
--- a/hw/display/vmware_vga.c
+++ b/hw/display/vmware_vga.c
@@ -1124,7 +1124,7 @@ static void vmsvga_update_display(void *opaque)
* Is it more efficient to look at vram VGA-dirty bits or wait
* for the driver to issue SVGA_CMD_UPDATE?
*/
- if (memory_region_is_logging(&s->vga.vram)) {
+ if (memory_region_is_logging(&s->vga.vram, DIRTY_MEMORY_VGA)) {
vga_sync_dirty_bitmap(&s->vga);
dirty = memory_region_get_dirty(&s->vga.vram, 0,
surface_stride(surface) * surface_height(surface),
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 2baff4a..3f0d435 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -164,27 +164,6 @@ uint64_t cpu_get_tsc(CPUX86State *env)
return cpu_get_ticks();
}
-/* SMM support */
-
-static cpu_set_smm_t smm_set;
-static void *smm_arg;
-
-void cpu_smm_register(cpu_set_smm_t callback, void *arg)
-{
- assert(smm_set == NULL);
- assert(smm_arg == NULL);
- smm_set = callback;
- smm_arg = arg;
-}
-
-void cpu_smm_update(CPUX86State *env)
-{
- if (smm_set && smm_arg && CPU(x86_env_get_cpu(env)) == first_cpu) {
- smm_set(!!(env->hflags & HF_SMM_MASK), smm_arg);
- }
-}
-
-
/* IRQ handling */
int cpu_get_pic_interrupt(CPUX86State *env)
{
diff --git a/hw/isa/isa-bus.c b/hw/isa/isa-bus.c
index 825aa62..ec8e7de 100644
--- a/hw/isa/isa-bus.c
+++ b/hw/isa/isa-bus.c
@@ -21,6 +21,7 @@
#include "hw/sysbus.h"
#include "sysemu/sysemu.h"
#include "hw/isa/isa.h"
+#include "hw/i386/pc.h"
static ISABus *isabus;
@@ -267,3 +268,28 @@ MemoryRegion *isa_address_space_io(ISADevice *dev)
}
type_init(isabus_register_types)
+
+static void parallel_init(ISABus *bus, int index, CharDriverState *chr)
+{
+ DeviceState *dev;
+ ISADevice *isadev;
+
+ isadev = isa_create(bus, "isa-parallel");
+ dev = DEVICE(isadev);
+ qdev_prop_set_uint32(dev, "index", index);
+ qdev_prop_set_chr(dev, "chardev", chr);
+ qdev_init_nofail(dev);
+}
+
+void parallel_hds_isa_init(ISABus *bus, int n)
+{
+ int i;
+
+ assert(n <= MAX_PARALLEL_PORTS);
+
+ for (i = 0; i < n; i++) {
+ if (parallel_hds[i]) {
+ parallel_init(bus, i, parallel_hds[i]);
+ }
+ }
+}
diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
index 18718d7..71a9f7a 100644
--- a/hw/isa/lpc_ich9.c
+++ b/hw/isa/lpc_ich9.c
@@ -407,12 +407,28 @@ static void ich9_lpc_rcba_update(ICH9LPCState *lpc, uint32_t rbca_old)
}
}
+/* config:GEN_PMCON* */
+static void
+ich9_lpc_pmcon_update(ICH9LPCState *lpc)
+{
+ uint16_t gen_pmcon_1 = pci_get_word(lpc->d.config + ICH9_LPC_GEN_PMCON_1);
+ uint16_t wmask;
+
+ if (gen_pmcon_1 & ICH9_LPC_GEN_PMCON_1_SMI_LOCK) {
+ wmask = pci_get_word(lpc->d.wmask + ICH9_LPC_GEN_PMCON_1);
+ wmask &= ~ICH9_LPC_GEN_PMCON_1_SMI_LOCK;
+ pci_set_word(lpc->d.wmask + ICH9_LPC_GEN_PMCON_1, wmask);
+ lpc->pm.smi_en_wmask &= ~1;
+ }
+}
+
static int ich9_lpc_post_load(void *opaque, int version_id)
{
ICH9LPCState *lpc = opaque;
ich9_lpc_pmbase_update(lpc);
ich9_lpc_rcba_update(lpc, 0 /* disabled ICH9_LPC_RBCA_EN */);
+ ich9_lpc_pmcon_update(lpc);
return 0;
}
@@ -435,6 +451,9 @@ static void ich9_lpc_config_write(PCIDevice *d,
if (ranges_overlap(addr, len, ICH9_LPC_PIRQE_ROUT, 4)) {
pci_bus_fire_intx_routing_notifier(lpc->d.bus);
}
+ if (ranges_overlap(addr, len, ICH9_LPC_GEN_PMCON_1, 8)) {
+ ich9_lpc_pmcon_update(lpc);
+ }
}
static void ich9_lpc_reset(DeviceState *qdev)
diff --git a/hw/pci-host/pam.c b/hw/pci-host/pam.c
index 8272de3..17d826c 100644
--- a/hw/pci-host/pam.c
+++ b/hw/pci-host/pam.c
@@ -31,26 +31,6 @@
#include "sysemu/sysemu.h"
#include "hw/pci-host/pam.h"
-void smram_update(MemoryRegion *smram_region, uint8_t smram,
- uint8_t smm_enabled)
-{
- bool smram_enabled;
-
- smram_enabled = ((smm_enabled && (smram & SMRAM_G_SMRAME)) ||
- (smram & SMRAM_D_OPEN));
- memory_region_set_enabled(smram_region, !smram_enabled);
-}
-
-void smram_set_smm(uint8_t *host_smm_enabled, int smm, uint8_t smram,
- MemoryRegion *smram_region)
-{
- uint8_t smm_enabled = (smm != 0);
- if (*host_smm_enabled != smm_enabled) {
- *host_smm_enabled = smm_enabled;
- smram_update(smram_region, smram, *host_smm_enabled);
- }
-}
-
void init_pam(DeviceState *dev, MemoryRegion *ram_memory,
MemoryRegion *system_memory, MemoryRegion *pci_address_space,
PAMMemoryRegion *mem, uint32_t start, uint32_t size)
diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index 723836f..f1712b8 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -105,7 +105,7 @@ struct PCII440FXState {
MemoryRegion *ram_memory;
PAMMemoryRegion pam_regions[13];
MemoryRegion smram_region;
- uint8_t smm_enabled;
+ MemoryRegion smram, low_smram;
};
@@ -138,18 +138,10 @@ static void i440fx_update_memory_mappings(PCII440FXState *d)
pam_update(&d->pam_regions[i], i,
pd->config[I440FX_PAM + ((i + 1) / 2)]);
}
- smram_update(&d->smram_region, pd->config[I440FX_SMRAM], d->smm_enabled);
- memory_region_transaction_commit();
-}
-
-static void i440fx_set_smm(int val, void *arg)
-{
- PCII440FXState *d = arg;
- PCIDevice *pd = PCI_DEVICE(d);
-
- memory_region_transaction_begin();
- smram_set_smm(&d->smm_enabled, val, pd->config[I440FX_SMRAM],
- &d->smram_region);
+ memory_region_set_enabled(&d->smram_region,
+ !(pd->config[I440FX_SMRAM] & SMRAM_D_OPEN));
+ memory_region_set_enabled(&d->smram,
+ pd->config[I440FX_SMRAM] & SMRAM_G_SMRAME);
memory_region_transaction_commit();
}
@@ -172,12 +164,13 @@ static int i440fx_load_old(QEMUFile* f, void *opaque, int version_id)
PCII440FXState *d = opaque;
PCIDevice *pd = PCI_DEVICE(d);
int ret, i;
+ uint8_t smm_enabled;
ret = pci_device_load(pd, f);
if (ret < 0)
return ret;
i440fx_update_memory_mappings(d);
- qemu_get_8s(f, &d->smm_enabled);
+ qemu_get_8s(f, &smm_enabled);
if (version_id == 2) {
for (i = 0; i < PIIX_NUM_PIRQS; i++) {
@@ -205,7 +198,10 @@ static const VMStateDescription vmstate_i440fx = {
.post_load = i440fx_post_load,
.fields = (VMStateField[]) {
VMSTATE_PCI_DEVICE(parent_obj, PCII440FXState),
- VMSTATE_UINT8(smm_enabled, PCII440FXState),
+ /* Used to be smm_enabled, which was basically always zero because
+ * SeaBIOS hardly uses SMM. SMRAM is now handled by CPU code.
+ */
+ VMSTATE_UNUSED(1),
VMSTATE_END_OF_LIST()
}
};
@@ -297,11 +293,7 @@ static void i440fx_pcihost_realize(DeviceState *dev, Error **errp)
static void i440fx_realize(PCIDevice *dev, Error **errp)
{
- PCII440FXState *d = I440FX_PCI_DEVICE(dev);
-
dev->config[I440FX_SMRAM] = 0x02;
-
- cpu_smm_register(&i440fx_set_smm, d);
}
PCIBus *i440fx_init(PCII440FXState **pi440fx_state,
@@ -346,11 +338,23 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state,
pc_pci_as_mapping_init(OBJECT(f), f->system_memory,
f->pci_address_space);
+ /* if *disabled* show SMRAM to all CPUs */
memory_region_init_alias(&f->smram_region, OBJECT(d), "smram-region",
f->pci_address_space, 0xa0000, 0x20000);
memory_region_add_subregion_overlap(f->system_memory, 0xa0000,
&f->smram_region, 1);
- memory_region_set_enabled(&f->smram_region, false);
+ memory_region_set_enabled(&f->smram_region, true);
+
+ /* smram, as seen by SMM CPUs */
+ memory_region_init(&f->smram, OBJECT(d), "smram", 1ull << 32);
+ memory_region_set_enabled(&f->smram, true);
+ memory_region_init_alias(&f->low_smram, OBJECT(d), "smram-low",
+ f->ram_memory, 0xa0000, 0x20000);
+ memory_region_set_enabled(&f->low_smram, true);
+ memory_region_add_subregion(&f->smram, 0xa0000, &f->low_smram);
+ object_property_add_const_link(qdev_get_machine(), "smram",
+ OBJECT(&f->smram), &error_abort);
+
init_pam(dev, f->ram_memory, f->system_memory, f->pci_address_space,
&f->pam_regions[0], PAM_BIOS_BASE, PAM_BIOS_SIZE);
for (i = 0; i < 12; ++i) {
diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c
index c8827cc..bd74094 100644
--- a/hw/pci-host/q35.c
+++ b/hw/pci-host/q35.c
@@ -198,6 +198,28 @@ static const TypeInfo q35_host_info = {
* MCH D0:F0
*/
+static uint64_t tseg_blackhole_read(void *ptr, hwaddr reg, unsigned size)
+{
+ return 0xffffffff;
+}
+
+static void tseg_blackhole_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned width)
+{
+ /* nothing */
+}
+
+static const MemoryRegionOps tseg_blackhole_ops = {
+ .read = tseg_blackhole_read,
+ .write = tseg_blackhole_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid.min_access_size = 1,
+ .valid.max_access_size = 4,
+ .impl.min_access_size = 4,
+ .impl.max_access_size = 4,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
/* PCIe MMCFG */
static void mch_update_pciexbar(MCHPCIState *mch)
{
@@ -266,21 +288,70 @@ static void mch_update_pam(MCHPCIState *mch)
static void mch_update_smram(MCHPCIState *mch)
{
PCIDevice *pd = PCI_DEVICE(mch);
+ bool h_smrame = (pd->config[MCH_HOST_BRIDGE_ESMRAMC] & MCH_HOST_BRIDGE_ESMRAMC_H_SMRAME);
+ uint32_t tseg_size;
+
+ /* implement SMRAM.D_LCK */
+ if (pd->config[MCH_HOST_BRIDGE_SMRAM] & MCH_HOST_BRIDGE_SMRAM_D_LCK) {
+ pd->config[MCH_HOST_BRIDGE_SMRAM] &= ~MCH_HOST_BRIDGE_SMRAM_D_OPEN;
+ pd->wmask[MCH_HOST_BRIDGE_SMRAM] = MCH_HOST_BRIDGE_SMRAM_WMASK_LCK;
+ pd->wmask[MCH_HOST_BRIDGE_ESMRAMC] = MCH_HOST_BRIDGE_ESMRAMC_WMASK_LCK;
+ }
memory_region_transaction_begin();
- smram_update(&mch->smram_region, pd->config[MCH_HOST_BRIDGE_SMRAM],
- mch->smm_enabled);
- memory_region_transaction_commit();
-}
-static void mch_set_smm(int smm, void *arg)
-{
- MCHPCIState *mch = arg;
- PCIDevice *pd = PCI_DEVICE(mch);
+ if (pd->config[MCH_HOST_BRIDGE_SMRAM] & SMRAM_D_OPEN) {
+ /* Hide (!) low SMRAM if H_SMRAME = 1 */
+ memory_region_set_enabled(&mch->smram_region, h_smrame);
+ /* Show high SMRAM if H_SMRAME = 1 */
+ memory_region_set_enabled(&mch->open_high_smram, h_smrame);
+ } else {
+ /* Hide high SMRAM and low SMRAM */
+ memory_region_set_enabled(&mch->smram_region, true);
+ memory_region_set_enabled(&mch->open_high_smram, false);
+ }
+
+ if (pd->config[MCH_HOST_BRIDGE_SMRAM] & SMRAM_G_SMRAME) {
+ memory_region_set_enabled(&mch->low_smram, !h_smrame);
+ memory_region_set_enabled(&mch->high_smram, h_smrame);
+ } else {
+ memory_region_set_enabled(&mch->low_smram, false);
+ memory_region_set_enabled(&mch->high_smram, false);
+ }
+
+ if (pd->config[MCH_HOST_BRIDGE_ESMRAMC] & MCH_HOST_BRIDGE_ESMRAMC_T_EN) {
+ switch (pd->config[MCH_HOST_BRIDGE_ESMRAMC] &
+ MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_MASK) {
+ case MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_1MB:
+ tseg_size = 1024 * 1024;
+ break;
+ case MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_2MB:
+ tseg_size = 1024 * 1024 * 2;
+ break;
+ case MCH_HOST_BRIDGE_ESMRAMC_TSEG_SZ_8MB:
+ tseg_size = 1024 * 1024 * 8;
+ break;
+ default:
+ tseg_size = 0;
+ break;
+ }
+ } else {
+ tseg_size = 0;
+ }
+ memory_region_del_subregion(mch->system_memory, &mch->tseg_blackhole);
+ memory_region_set_enabled(&mch->tseg_blackhole, tseg_size);
+ memory_region_set_size(&mch->tseg_blackhole, tseg_size);
+ memory_region_add_subregion_overlap(mch->system_memory,
+ mch->below_4g_mem_size - tseg_size,
+ &mch->tseg_blackhole, 1);
+
+ memory_region_set_enabled(&mch->tseg_window, tseg_size);
+ memory_region_set_size(&mch->tseg_window, tseg_size);
+ memory_region_set_address(&mch->tseg_window,
+ mch->below_4g_mem_size - tseg_size);
+ memory_region_set_alias_offset(&mch->tseg_window,
+ mch->below_4g_mem_size - tseg_size);
- memory_region_transaction_begin();
- smram_set_smm(&mch->smm_enabled, smm, pd->config[MCH_HOST_BRIDGE_SMRAM],
- &mch->smram_region);
memory_region_transaction_commit();
}
@@ -289,7 +360,6 @@ static void mch_write_config(PCIDevice *d,
{
MCHPCIState *mch = MCH_PCI_DEVICE(d);
- /* XXX: implement SMRAM.D_LOCK */
pci_default_write_config(d, address, val, len);
if (ranges_overlap(address, len, MCH_HOST_BRIDGE_PAM0,
@@ -329,7 +399,10 @@ static const VMStateDescription vmstate_mch = {
.post_load = mch_post_load,
.fields = (VMStateField[]) {
VMSTATE_PCI_DEVICE(parent_obj, MCHPCIState),
- VMSTATE_UINT8(smm_enabled, MCHPCIState),
+ /* Used to be smm_enabled, which was basically always zero because
+ * SeaBIOS hardly uses SMM. SMRAM is now handled by CPU code.
+ */
+ VMSTATE_UNUSED(1),
VMSTATE_END_OF_LIST()
}
};
@@ -343,6 +416,9 @@ static void mch_reset(DeviceState *qdev)
MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT);
d->config[MCH_HOST_BRIDGE_SMRAM] = MCH_HOST_BRIDGE_SMRAM_DEFAULT;
+ d->config[MCH_HOST_BRIDGE_ESMRAMC] = MCH_HOST_BRIDGE_ESMRAMC_DEFAULT;
+ d->wmask[MCH_HOST_BRIDGE_SMRAM] = MCH_HOST_BRIDGE_SMRAM_WMASK;
+ d->wmask[MCH_HOST_BRIDGE_ESMRAMC] = MCH_HOST_BRIDGE_ESMRAMC_WMASK;
mch_update(mch);
}
@@ -399,13 +475,47 @@ static void mch_realize(PCIDevice *d, Error **errp)
pc_pci_as_mapping_init(OBJECT(mch), mch->system_memory,
mch->pci_address_space);
- /* smram */
- cpu_smm_register(&mch_set_smm, mch);
+ /* if *disabled* show SMRAM to all CPUs */
memory_region_init_alias(&mch->smram_region, OBJECT(mch), "smram-region",
mch->pci_address_space, 0xa0000, 0x20000);
memory_region_add_subregion_overlap(mch->system_memory, 0xa0000,
&mch->smram_region, 1);
- memory_region_set_enabled(&mch->smram_region, false);
+ memory_region_set_enabled(&mch->smram_region, true);
+
+ memory_region_init_alias(&mch->open_high_smram, OBJECT(mch), "smram-open-high",
+ mch->ram_memory, 0xa0000, 0x20000);
+ memory_region_add_subregion_overlap(mch->system_memory, 0xfeda0000,
+ &mch->open_high_smram, 1);
+ memory_region_set_enabled(&mch->open_high_smram, false);
+
+ /* smram, as seen by SMM CPUs */
+ memory_region_init(&mch->smram, OBJECT(mch), "smram", 1ull << 32);
+ memory_region_set_enabled(&mch->smram, true);
+ memory_region_init_alias(&mch->low_smram, OBJECT(mch), "smram-low",
+ mch->ram_memory, 0xa0000, 0x20000);
+ memory_region_set_enabled(&mch->low_smram, true);
+ memory_region_add_subregion(&mch->smram, 0xa0000, &mch->low_smram);
+ memory_region_init_alias(&mch->high_smram, OBJECT(mch), "smram-high",
+ mch->ram_memory, 0xa0000, 0x20000);
+ memory_region_set_enabled(&mch->high_smram, true);
+ memory_region_add_subregion(&mch->smram, 0xfeda0000, &mch->high_smram);
+
+ memory_region_init_io(&mch->tseg_blackhole, OBJECT(mch),
+ &tseg_blackhole_ops, NULL,
+ "tseg-blackhole", 0);
+ memory_region_set_enabled(&mch->tseg_blackhole, false);
+ memory_region_add_subregion_overlap(mch->system_memory,
+ mch->below_4g_mem_size,
+ &mch->tseg_blackhole, 1);
+
+ memory_region_init_alias(&mch->tseg_window, OBJECT(mch), "tseg-window",
+ mch->ram_memory, mch->below_4g_mem_size, 0);
+ memory_region_set_enabled(&mch->tseg_window, false);
+ memory_region_add_subregion(&mch->smram, mch->below_4g_mem_size,
+ &mch->tseg_window);
+ object_property_add_const_link(qdev_get_machine(), "smram",
+ OBJECT(&mch->smram), &error_abort);
+
init_pam(DEVICE(mch), mch->ram_memory, mch->system_memory,
mch->pci_address_space, &mch->pam_regions[0],
PAM_BIOS_BASE, PAM_BIOS_SIZE);
diff --git a/hw/virtio/dataplane/vring.c b/hw/virtio/dataplane/vring.c
index 5c7b8c2..e378733 100644
--- a/hw/virtio/dataplane/vring.c
+++ b/hw/virtio/dataplane/vring.c
@@ -42,7 +42,7 @@ static void *vring_map(MemoryRegion **mr, hwaddr phys, hwaddr len,
}
/* Ignore regions with dirty logging, we cannot mark them dirty */
- if (memory_region_is_logging(section.mr)) {
+ if (memory_region_get_dirty_log_mask(section.mr)) {
goto out;
}
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 01f1e04..a7fe3c5 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -416,7 +416,8 @@ static void vhost_set_memory(MemoryListener *listener,
memory_listener);
hwaddr start_addr = section->offset_within_address_space;
ram_addr_t size = int128_get64(section->size);
- bool log_dirty = memory_region_is_logging(section->mr);
+ bool log_dirty =
+ memory_region_get_dirty_log_mask(section->mr) & ~(1 << DIRTY_MEMORY_MIGRATION);
int s = offsetof(struct vhost_memory, regions) +
(dev->mem->nregions + 1) * sizeof dev->mem->regions[0];
void *ram;
@@ -675,13 +676,15 @@ static void vhost_log_global_stop(MemoryListener *listener)
}
static void vhost_log_start(MemoryListener *listener,
- MemoryRegionSection *section)
+ MemoryRegionSection *section,
+ int old, int new)
{
/* FIXME: implement */
}
static void vhost_log_stop(MemoryListener *listener,
- MemoryRegionSection *section)
+ MemoryRegionSection *section,
+ int old, int new)
{
/* FIXME: implement */
}
OpenPOWER on IntegriCloud