aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/acpi/ich9.c10
-rw-r--r--hw/acpi/piix4.c10
-rw-r--r--hw/arm/boot.c20
-rw-r--r--hw/arm/pxa2xx.c248
-rw-r--r--hw/arm/pxa2xx_pic.c2
-rw-r--r--hw/arm/virt-acpi-build.c43
-rw-r--r--hw/arm/virt.c7
-rw-r--r--hw/block/fdc.c42
-rw-r--r--hw/char/serial.c41
-rw-r--r--hw/core/nmi.c20
-rw-r--r--hw/display/exynos4210_fimd.c2
-rw-r--r--hw/display/qxl.c11
-rw-r--r--hw/display/vga.c11
-rw-r--r--hw/dma/rc4030.c462
-rw-r--r--hw/i386/pc_piix.c2
-rw-r--r--hw/i386/pc_q35.c2
-rw-r--r--hw/ide/core.c32
-rw-r--r--hw/ide/pci.c16
-rw-r--r--hw/input/pckbd.c22
-rw-r--r--hw/input/ps2.c11
-rw-r--r--hw/intc/apic_common.c10
-rw-r--r--hw/intc/arm_gic.c2
-rw-r--r--hw/isa/lpc_ich9.c10
-rw-r--r--hw/mips/Makefile.objs3
-rw-r--r--hw/mips/mips_jazz.c53
-rw-r--r--hw/mips/mips_malta.c15
-rw-r--r--hw/net/Makefile.objs1
-rw-r--r--hw/net/dp8393x.c369
-rw-r--r--hw/net/e1000.c11
-rw-r--r--hw/net/rocker/qmp-norocker.c50
-rw-r--r--hw/net/rocker/rocker.c68
-rw-r--r--hw/net/rocker/rocker_fp.c29
-rw-r--r--hw/net/rocker/rocker_fp.h2
-rw-r--r--hw/net/rocker/rocker_hw.h1
-rw-r--r--hw/net/rocker/rocker_of_dpa.c312
-rw-r--r--hw/net/rtl8139.c11
-rw-r--r--hw/net/vmxnet3.c12
-rw-r--r--hw/pci-host/piix.c10
-rw-r--r--hw/scsi/scsi-bus.c11
-rw-r--r--hw/sd/pxa2xx_mmci.c68
-rw-r--r--hw/sh4/r2d.c12
-rw-r--r--hw/timer/hpet.c11
-rw-r--r--hw/timer/mc146818rtc.c23
-rw-r--r--hw/usb/hcd-ohci.c11
-rw-r--r--hw/usb/redirect.c34
-rw-r--r--hw/virtio/virtio.c16
-rw-r--r--hw/watchdog/Makefile.objs1
-rw-r--r--hw/watchdog/watchdog.c10
-rw-r--r--hw/watchdog/wdt_diag288.c122
-rw-r--r--hw/xen/xen_backend.c4
50 files changed, 1446 insertions, 860 deletions
diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
index 25bc023882..8a64ffb38f 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -152,6 +152,7 @@ static const VMStateDescription vmstate_memhp_state = {
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
+ .needed = vmstate_test_use_memhp,
.fields = (VMStateField[]) {
VMSTATE_MEMORY_HOTPLUG(acpi_memory_hotplug, ICH9LPCPMRegs),
VMSTATE_END_OF_LIST()
@@ -175,12 +176,9 @@ const VMStateDescription vmstate_ich9_pm = {
VMSTATE_UINT32(smi_sts, ICH9LPCPMRegs),
VMSTATE_END_OF_LIST()
},
- .subsections = (VMStateSubsection[]) {
- {
- .vmsd = &vmstate_memhp_state,
- .needed = vmstate_test_use_memhp,
- },
- VMSTATE_END_OF_LIST()
+ .subsections = (const VMStateDescription*[]) {
+ &vmstate_memhp_state,
+ NULL
}
};
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index b730ca6ced..3bd1d5a865 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -260,6 +260,7 @@ static const VMStateDescription vmstate_memhp_state = {
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
+ .needed = vmstate_test_use_memhp,
.fields = (VMStateField[]) {
VMSTATE_MEMORY_HOTPLUG(acpi_memory_hotplug, PIIX4PMState),
VMSTATE_END_OF_LIST()
@@ -298,12 +299,9 @@ static const VMStateDescription vmstate_acpi = {
vmstate_test_use_acpi_pci_hotplug),
VMSTATE_END_OF_LIST()
},
- .subsections = (VMStateSubsection[]) {
- {
- .vmsd = &vmstate_memhp_state,
- .needed = vmstate_test_use_memhp,
- },
- VMSTATE_END_OF_LIST()
+ .subsections = (const VMStateDescription*[]) {
+ &vmstate_memhp_state,
+ NULL
}
};
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index d036624948..1e7fd28daa 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -574,15 +574,6 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
struct arm_boot_info *info =
container_of(n, struct arm_boot_info, load_kernel_notifier);
- /* CPU objects (unlike devices) are not automatically reset on system
- * reset, so we must always register a handler to do so. If we're
- * actually loading a kernel, the handler is also responsible for
- * arranging that we start it correctly.
- */
- for (cs = CPU(cpu); cs; cs = CPU_NEXT(cs)) {
- qemu_register_reset(do_cpu_reset, ARM_CPU(cs));
- }
-
/* Load the kernel. */
if (!info->kernel_filename || info->firmware_loaded) {
@@ -783,7 +774,18 @@ static void arm_load_kernel_notify(Notifier *notifier, void *data)
void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
{
+ CPUState *cs;
+
info->load_kernel_notifier.cpu = cpu;
info->load_kernel_notifier.notifier.notify = arm_load_kernel_notify;
qemu_add_machine_init_done_notifier(&info->load_kernel_notifier.notifier);
+
+ /* CPU objects (unlike devices) are not automatically reset on system
+ * reset, so we must always register a handler to do so. If we're
+ * actually loading a kernel, the handler is also responsible for
+ * arranging that we start it correctly.
+ */
+ for (cs = CPU(cpu); cs; cs = CPU_NEXT(cs)) {
+ qemu_register_reset(do_cpu_reset, ARM_CPU(cs));
+ }
}
diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c
index f921a5680c..ec353f79c4 100644
--- a/hw/arm/pxa2xx.c
+++ b/hw/arm/pxa2xx.c
@@ -334,10 +334,10 @@ static uint64_t pxa2xx_cpccnt_read(CPUARMState *env, const ARMCPRegInfo *ri)
static const ARMCPRegInfo pxa_cp_reginfo[] = {
/* cp14 crm==1: perf registers */
{ .name = "CPPMNC", .cp = 14, .crn = 0, .crm = 1, .opc1 = 0, .opc2 = 0,
- .access = PL1_RW,
+ .access = PL1_RW, .type = ARM_CP_IO,
.readfn = pxa2xx_cppmnc_read, .writefn = pxa2xx_cppmnc_write },
{ .name = "CPCCNT", .cp = 14, .crn = 1, .crm = 1, .opc1 = 0, .opc2 = 0,
- .access = PL1_RW,
+ .access = PL1_RW, .type = ARM_CP_IO,
.readfn = pxa2xx_cpccnt_read, .writefn = arm_cp_write_ignore },
{ .name = "CPINTEN", .cp = 14, .crn = 4, .crm = 1, .opc1 = 0, .opc2 = 0,
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
@@ -356,11 +356,11 @@ static const ARMCPRegInfo pxa_cp_reginfo[] = {
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
/* cp14 crn==6: CLKCFG */
{ .name = "CLKCFG", .cp = 14, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 0,
- .access = PL1_RW,
+ .access = PL1_RW, .type = ARM_CP_IO,
.readfn = pxa2xx_clkcfg_read, .writefn = pxa2xx_clkcfg_write },
/* cp14 crn==7: PWRMODE */
{ .name = "PWRMODE", .cp = 14, .crn = 7, .crm = 0, .opc1 = 0, .opc2 = 0,
- .access = PL1_RW,
+ .access = PL1_RW, .type = ARM_CP_IO,
.readfn = arm_cp_read_zero, .writefn = pxa2xx_pwrmode_write },
REGINFO_SENTINEL
};
@@ -457,7 +457,7 @@ typedef struct {
MemoryRegion iomem;
qemu_irq irq;
- int enable;
+ uint32_t enable;
SSIBus *bus;
uint32_t sscr[2];
@@ -470,10 +470,39 @@ typedef struct {
uint8_t ssacd;
uint32_t rx_fifo[16];
- int rx_level;
- int rx_start;
+ uint32_t rx_level;
+ uint32_t rx_start;
} PXA2xxSSPState;
+static bool pxa2xx_ssp_vmstate_validate(void *opaque, int version_id)
+{
+ PXA2xxSSPState *s = opaque;
+
+ return s->rx_start < sizeof(s->rx_fifo);
+}
+
+static const VMStateDescription vmstate_pxa2xx_ssp = {
+ .name = "pxa2xx-ssp",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(enable, PXA2xxSSPState),
+ VMSTATE_UINT32_ARRAY(sscr, PXA2xxSSPState, 2),
+ VMSTATE_UINT32(sspsp, PXA2xxSSPState),
+ VMSTATE_UINT32(ssto, PXA2xxSSPState),
+ VMSTATE_UINT32(ssitr, PXA2xxSSPState),
+ VMSTATE_UINT32(sssr, PXA2xxSSPState),
+ VMSTATE_UINT8(sstsa, PXA2xxSSPState),
+ VMSTATE_UINT8(ssrsa, PXA2xxSSPState),
+ VMSTATE_UINT8(ssacd, PXA2xxSSPState),
+ VMSTATE_UINT32(rx_level, PXA2xxSSPState),
+ VMSTATE_UINT32(rx_start, PXA2xxSSPState),
+ VMSTATE_VALIDATE("fifo is 16 bytes", pxa2xx_ssp_vmstate_validate),
+ VMSTATE_UINT32_ARRAY(rx_fifo, PXA2xxSSPState, 16),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
#define SSCR0 0x00 /* SSP Control register 0 */
#define SSCR1 0x04 /* SSP Control register 1 */
#define SSSR 0x08 /* SSP Status register */
@@ -705,55 +734,20 @@ static const MemoryRegionOps pxa2xx_ssp_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static void pxa2xx_ssp_save(QEMUFile *f, void *opaque)
+static void pxa2xx_ssp_reset(DeviceState *d)
{
- PXA2xxSSPState *s = (PXA2xxSSPState *) opaque;
- int i;
-
- qemu_put_be32(f, s->enable);
+ PXA2xxSSPState *s = PXA2XX_SSP(d);
- qemu_put_be32s(f, &s->sscr[0]);
- qemu_put_be32s(f, &s->sscr[1]);
- qemu_put_be32s(f, &s->sspsp);
- qemu_put_be32s(f, &s->ssto);
- qemu_put_be32s(f, &s->ssitr);
- qemu_put_be32s(f, &s->sssr);
- qemu_put_8s(f, &s->sstsa);
- qemu_put_8s(f, &s->ssrsa);
- qemu_put_8s(f, &s->ssacd);
-
- qemu_put_byte(f, s->rx_level);
- for (i = 0; i < s->rx_level; i ++)
- qemu_put_byte(f, s->rx_fifo[(s->rx_start + i) & 0xf]);
-}
-
-static int pxa2xx_ssp_load(QEMUFile *f, void *opaque, int version_id)
-{
- PXA2xxSSPState *s = (PXA2xxSSPState *) opaque;
- int i, v;
-
- s->enable = qemu_get_be32(f);
-
- qemu_get_be32s(f, &s->sscr[0]);
- qemu_get_be32s(f, &s->sscr[1]);
- qemu_get_be32s(f, &s->sspsp);
- qemu_get_be32s(f, &s->ssto);
- qemu_get_be32s(f, &s->ssitr);
- qemu_get_be32s(f, &s->sssr);
- qemu_get_8s(f, &s->sstsa);
- qemu_get_8s(f, &s->ssrsa);
- qemu_get_8s(f, &s->ssacd);
-
- v = qemu_get_byte(f);
- if (v < 0 || v > ARRAY_SIZE(s->rx_fifo)) {
- return -EINVAL;
- }
- s->rx_level = v;
- s->rx_start = 0;
- for (i = 0; i < s->rx_level; i ++)
- s->rx_fifo[i] = qemu_get_byte(f);
-
- return 0;
+ s->enable = 0;
+ s->sscr[0] = s->sscr[1] = 0;
+ s->sspsp = 0;
+ s->ssto = 0;
+ s->ssitr = 0;
+ s->sssr = 0;
+ s->sstsa = 0;
+ s->ssrsa = 0;
+ s->ssacd = 0;
+ s->rx_start = s->rx_level = 0;
}
static int pxa2xx_ssp_init(SysBusDevice *sbd)
@@ -766,8 +760,6 @@ static int pxa2xx_ssp_init(SysBusDevice *sbd)
memory_region_init_io(&s->iomem, OBJECT(s), &pxa2xx_ssp_ops, s,
"pxa2xx-ssp", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
- register_savevm(dev, "pxa2xx_ssp", -1, 0,
- pxa2xx_ssp_save, pxa2xx_ssp_load, s);
s->bus = ssi_create_bus(dev, "ssi");
return 0;
@@ -1759,24 +1751,33 @@ static PXA2xxI2SState *pxa2xx_i2s_init(MemoryRegion *sysmem,
}
/* PXA Fast Infra-red Communications Port */
+#define TYPE_PXA2XX_FIR "pxa2xx-fir"
+#define PXA2XX_FIR(obj) OBJECT_CHECK(PXA2xxFIrState, (obj), TYPE_PXA2XX_FIR)
+
struct PXA2xxFIrState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+ /*< public >*/
+
MemoryRegion iomem;
qemu_irq irq;
qemu_irq rx_dma;
qemu_irq tx_dma;
- int enable;
+ uint32_t enable;
CharDriverState *chr;
uint8_t control[3];
uint8_t status[2];
- int rx_len;
- int rx_start;
+ uint32_t rx_len;
+ uint32_t rx_start;
uint8_t rx_fifo[64];
};
-static void pxa2xx_fir_reset(PXA2xxFIrState *s)
+static void pxa2xx_fir_reset(DeviceState *d)
{
+ PXA2xxFIrState *s = PXA2XX_FIR(d);
+
s->control[0] = 0x00;
s->control[1] = 0x00;
s->control[2] = 0x00;
@@ -1953,73 +1954,94 @@ static void pxa2xx_fir_event(void *opaque, int event)
{
}
-static void pxa2xx_fir_save(QEMUFile *f, void *opaque)
+static void pxa2xx_fir_instance_init(Object *obj)
{
- PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
- int i;
+ PXA2xxFIrState *s = PXA2XX_FIR(obj);
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
- qemu_put_be32(f, s->enable);
-
- qemu_put_8s(f, &s->control[0]);
- qemu_put_8s(f, &s->control[1]);
- qemu_put_8s(f, &s->control[2]);
- qemu_put_8s(f, &s->status[0]);
- qemu_put_8s(f, &s->status[1]);
-
- qemu_put_byte(f, s->rx_len);
- for (i = 0; i < s->rx_len; i ++)
- qemu_put_byte(f, s->rx_fifo[(s->rx_start + i) & 63]);
+ memory_region_init_io(&s->iomem, NULL, &pxa2xx_fir_ops, s,
+ "pxa2xx-fir", 0x1000);
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->irq);
+ sysbus_init_irq(sbd, &s->rx_dma);
+ sysbus_init_irq(sbd, &s->tx_dma);
}
-static int pxa2xx_fir_load(QEMUFile *f, void *opaque, int version_id)
+static void pxa2xx_fir_realize(DeviceState *dev, Error **errp)
{
- PXA2xxFIrState *s = (PXA2xxFIrState *) opaque;
- int i;
-
- s->enable = qemu_get_be32(f);
+ PXA2xxFIrState *s = PXA2XX_FIR(dev);
- qemu_get_8s(f, &s->control[0]);
- qemu_get_8s(f, &s->control[1]);
- qemu_get_8s(f, &s->control[2]);
- qemu_get_8s(f, &s->status[0]);
- qemu_get_8s(f, &s->status[1]);
+ if (s->chr) {
+ qemu_chr_fe_claim_no_fail(s->chr);
+ qemu_chr_add_handlers(s->chr, pxa2xx_fir_is_empty,
+ pxa2xx_fir_rx, pxa2xx_fir_event, s);
+ }
+}
- s->rx_len = qemu_get_byte(f);
- s->rx_start = 0;
- for (i = 0; i < s->rx_len; i ++)
- s->rx_fifo[i] = qemu_get_byte(f);
+static bool pxa2xx_fir_vmstate_validate(void *opaque, int version_id)
+{
+ PXA2xxFIrState *s = opaque;
- return 0;
+ return s->rx_start < ARRAY_SIZE(s->rx_fifo);
}
-static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem,
- hwaddr base,
- qemu_irq irq, qemu_irq rx_dma, qemu_irq tx_dma,
- CharDriverState *chr)
-{
- PXA2xxFIrState *s = (PXA2xxFIrState *)
- g_malloc0(sizeof(PXA2xxFIrState));
+static const VMStateDescription pxa2xx_fir_vmsd = {
+ .name = "pxa2xx-fir",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(enable, PXA2xxFIrState),
+ VMSTATE_UINT8_ARRAY(control, PXA2xxFIrState, 3),
+ VMSTATE_UINT8_ARRAY(status, PXA2xxFIrState, 2),
+ VMSTATE_UINT32(rx_len, PXA2xxFIrState),
+ VMSTATE_UINT32(rx_start, PXA2xxFIrState),
+ VMSTATE_VALIDATE("fifo is 64 bytes", pxa2xx_fir_vmstate_validate),
+ VMSTATE_UINT8_ARRAY(rx_fifo, PXA2xxFIrState, 64),
+ VMSTATE_END_OF_LIST()
+ }
+};
- s->irq = irq;
- s->rx_dma = rx_dma;
- s->tx_dma = tx_dma;
- s->chr = chr;
+static Property pxa2xx_fir_properties[] = {
+ DEFINE_PROP_CHR("chardev", PXA2xxFIrState, chr),
+ DEFINE_PROP_END_OF_LIST(),
+};
- pxa2xx_fir_reset(s);
+static void pxa2xx_fir_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
- memory_region_init_io(&s->iomem, NULL, &pxa2xx_fir_ops, s, "pxa2xx-fir", 0x1000);
- memory_region_add_subregion(sysmem, base, &s->iomem);
+ dc->realize = pxa2xx_fir_realize;
+ dc->vmsd = &pxa2xx_fir_vmsd;
+ dc->props = pxa2xx_fir_properties;
+ dc->reset = pxa2xx_fir_reset;
+}
- if (chr) {
- qemu_chr_fe_claim_no_fail(chr);
- qemu_chr_add_handlers(chr, pxa2xx_fir_is_empty,
- pxa2xx_fir_rx, pxa2xx_fir_event, s);
- }
+static const TypeInfo pxa2xx_fir_info = {
+ .name = TYPE_PXA2XX_FIR,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(PXA2xxFIrState),
+ .class_init = pxa2xx_fir_class_init,
+ .instance_init = pxa2xx_fir_instance_init,
+};
- register_savevm(NULL, "pxa2xx_fir", 0, 0, pxa2xx_fir_save,
- pxa2xx_fir_load, s);
+static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem,
+ hwaddr base,
+ qemu_irq irq, qemu_irq rx_dma,
+ qemu_irq tx_dma,
+ CharDriverState *chr)
+{
+ DeviceState *dev;
+ SysBusDevice *sbd;
- return s;
+ dev = qdev_create(NULL, TYPE_PXA2XX_FIR);
+ qdev_prop_set_chr(dev, "chardev", chr);
+ qdev_init_nofail(dev);
+ sbd = SYS_BUS_DEVICE(dev);
+ sysbus_mmio_map(sbd, 0, base);
+ sysbus_connect_irq(sbd, 0, irq);
+ sysbus_connect_irq(sbd, 1, rx_dma);
+ sysbus_connect_irq(sbd, 2, tx_dma);
+ return PXA2XX_FIR(dev);
}
static void pxa2xx_reset(void *opaque, int line, int level)
@@ -2306,8 +2328,11 @@ PXA2xxState *pxa255_init(MemoryRegion *address_space, unsigned int sdram_size)
static void pxa2xx_ssp_class_init(ObjectClass *klass, void *data)
{
SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
sdc->init = pxa2xx_ssp_init;
+ dc->reset = pxa2xx_ssp_reset;
+ dc->vmsd = &vmstate_pxa2xx_ssp;
}
static const TypeInfo pxa2xx_ssp_info = {
@@ -2323,6 +2348,7 @@ static void pxa2xx_register_types(void)
type_register_static(&pxa2xx_ssp_info);
type_register_static(&pxa2xx_i2c_info);
type_register_static(&pxa2xx_rtc_sysbus_info);
+ type_register_static(&pxa2xx_fir_info);
}
type_init(pxa2xx_register_types)
diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c
index 9cfc714874..d41ac93416 100644
--- a/hw/arm/pxa2xx_pic.c
+++ b/hw/arm/pxa2xx_pic.c
@@ -232,7 +232,7 @@ static void pxa2xx_pic_cp_write(CPUARMState *env, const ARMCPRegInfo *ri,
#define REGINFO_FOR_PIC_CP(NAME, CRN) \
{ .name = NAME, .cp = 6, .crn = CRN, .crm = 0, .opc1 = 0, .opc2 = 0, \
- .access = PL1_RW, \
+ .access = PL1_RW, .type = ARM_CP_IO, \
.readfn = pxa2xx_pic_cp_read, .writefn = pxa2xx_pic_cp_write }
static const ARMCPRegInfo pxa_pic_cp_reginfo[] = {
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index a9373ccaca..d5a8b9c017 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -84,6 +84,12 @@ static void acpi_dsdt_add_uart(Aml *scope, const MemMapEntry *uart_memmap,
aml_interrupt(AML_CONSUMER, AML_LEVEL, AML_ACTIVE_HIGH,
AML_EXCLUSIVE, uart_irq));
aml_append(dev, aml_name_decl("_CRS", crs));
+
+ /* The _ADR entry is used to link this device to the UART described
+ * in the SPCR table, i.e. SPCR.base_address.address == _ADR.
+ */
+ aml_append(dev, aml_name_decl("_ADR", aml_int(uart_memmap->base)));
+
aml_append(scope, dev);
}
@@ -334,6 +340,38 @@ build_rsdp(GArray *rsdp_table, GArray *linker, unsigned rsdt)
}
static void
+build_spcr(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
+{
+ AcpiSerialPortConsoleRedirection *spcr;
+ const MemMapEntry *uart_memmap = &guest_info->memmap[VIRT_UART];
+ int irq = guest_info->irqmap[VIRT_UART] + ARM_SPI_BASE;
+
+ spcr = acpi_data_push(table_data, sizeof(*spcr));
+
+ spcr->interface_type = 0x3; /* ARM PL011 UART */
+
+ spcr->base_address.space_id = AML_SYSTEM_MEMORY;
+ spcr->base_address.bit_width = 8;
+ spcr->base_address.bit_offset = 0;
+ spcr->base_address.access_width = 1;
+ spcr->base_address.address = cpu_to_le64(uart_memmap->base);
+
+ spcr->interrupt_types = (1 << 3); /* Bit[3] ARMH GIC interrupt */
+ spcr->gsi = cpu_to_le32(irq); /* Global System Interrupt */
+
+ spcr->baud = 3; /* Baud Rate: 3 = 9600 */
+ spcr->parity = 0; /* No Parity */
+ spcr->stopbits = 1; /* 1 Stop bit */
+ spcr->flowctrl = (1 << 1); /* Bit[1] = RTS/CTS hardware flow control */
+ spcr->term_type = 0; /* Terminal Type: 0 = VT100 */
+
+ spcr->pci_device_id = 0xffff; /* PCI Device ID: not a PCI device */
+ spcr->pci_vendor_id = 0xffff; /* PCI Vendor ID: not a PCI device */
+
+ build_header(linker, table_data, (void *)spcr, "SPCR", sizeof(*spcr), 2);
+}
+
+static void
build_mcfg(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
{
AcpiTableMcfg *mcfg;
@@ -514,7 +552,7 @@ void virt_acpi_build(VirtGuestInfo *guest_info, AcpiBuildTables *tables)
dsdt = tables_blob->len;
build_dsdt(tables_blob, tables->linker, guest_info);
- /* FADT MADT GTDT pointed to by RSDT */
+ /* FADT MADT GTDT SPCR pointed to by RSDT */
acpi_add_table(table_offsets, tables_blob);
build_fadt(tables_blob, tables->linker, dsdt);
@@ -527,6 +565,9 @@ void virt_acpi_build(VirtGuestInfo *guest_info, AcpiBuildTables *tables)
acpi_add_table(table_offsets, tables_blob);
build_mcfg(tables_blob, tables->linker, guest_info);
+ acpi_add_table(table_offsets, tables_blob);
+ build_spcr(tables_blob, tables->linker, guest_info);
+
/* RSDT is pointed to by RSDP */
rsdt = tables_blob->len;
build_rsdt(tables_blob, tables->linker, table_offsets);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 1b1cc716ad..f1e85c8e92 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -145,6 +145,11 @@ static VirtBoardInfo machines[] = {
.irqmap = a15irqmap,
},
{
+ .cpu_model = "cortex-a53",
+ .memmap = a15memmap,
+ .irqmap = a15irqmap,
+ },
+ {
.cpu_model = "cortex-a57",
.memmap = a15memmap,
.irqmap = a15irqmap,
@@ -306,7 +311,7 @@ static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi)
"enable-method", "psci");
}
- qemu_fdt_setprop_cell(vbi->fdt, nodename, "reg", cpu);
+ qemu_fdt_setprop_cell(vbi->fdt, nodename, "reg", armcpu->mp_affinity);
g_free(nodename);
}
}
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
index 6e794597dc..5e1b67ee43 100644
--- a/hw/block/fdc.c
+++ b/hw/block/fdc.c
@@ -699,6 +699,7 @@ static const VMStateDescription vmstate_fdrive_media_changed = {
.name = "fdrive/media_changed",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = fdrive_media_changed_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT8(media_changed, FDrive),
VMSTATE_END_OF_LIST()
@@ -716,6 +717,7 @@ static const VMStateDescription vmstate_fdrive_media_rate = {
.name = "fdrive/media_rate",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = fdrive_media_rate_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT8(media_rate, FDrive),
VMSTATE_END_OF_LIST()
@@ -733,6 +735,7 @@ static const VMStateDescription vmstate_fdrive_perpendicular = {
.name = "fdrive/perpendicular",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = fdrive_perpendicular_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT8(perpendicular, FDrive),
VMSTATE_END_OF_LIST()
@@ -756,19 +759,11 @@ static const VMStateDescription vmstate_fdrive = {
VMSTATE_UINT8(sect, FDrive),
VMSTATE_END_OF_LIST()
},
- .subsections = (VMStateSubsection[]) {
- {
- .vmsd = &vmstate_fdrive_media_changed,
- .needed = &fdrive_media_changed_needed,
- } , {
- .vmsd = &vmstate_fdrive_media_rate,
- .needed = &fdrive_media_rate_needed,
- } , {
- .vmsd = &vmstate_fdrive_perpendicular,
- .needed = &fdrive_perpendicular_needed,
- } , {
- /* empty */
- }
+ .subsections = (const VMStateDescription*[]) {
+ &vmstate_fdrive_media_changed,
+ &vmstate_fdrive_media_rate,
+ &vmstate_fdrive_perpendicular,
+ NULL
}
};
@@ -833,6 +828,7 @@ static const VMStateDescription vmstate_fdc_reset_sensei = {
.name = "fdc/reset_sensei",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = fdc_reset_sensei_needed,
.fields = (VMStateField[]) {
VMSTATE_INT32(reset_sensei, FDCtrl),
VMSTATE_END_OF_LIST()
@@ -850,6 +846,7 @@ static const VMStateDescription vmstate_fdc_result_timer = {
.name = "fdc/result_timer",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = fdc_result_timer_needed,
.fields = (VMStateField[]) {
VMSTATE_TIMER_PTR(result_timer, FDCtrl),
VMSTATE_END_OF_LIST()
@@ -867,6 +864,7 @@ static const VMStateDescription vmstate_fdc_phase = {
.name = "fdc/phase",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = fdc_phase_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT8(phase, FDCtrl),
VMSTATE_END_OF_LIST()
@@ -911,19 +909,11 @@ static const VMStateDescription vmstate_fdc = {
vmstate_fdrive, FDrive),
VMSTATE_END_OF_LIST()
},
- .subsections = (VMStateSubsection[]) {
- {
- .vmsd = &vmstate_fdc_reset_sensei,
- .needed = fdc_reset_sensei_needed,
- } , {
- .vmsd = &vmstate_fdc_result_timer,
- .needed = fdc_result_timer_needed,
- } , {
- .vmsd = &vmstate_fdc_phase,
- .needed = fdc_phase_needed,
- } , {
- /* empty */
- }
+ .subsections = (const VMStateDescription*[]) {
+ &vmstate_fdc_reset_sensei,
+ &vmstate_fdc_result_timer,
+ &vmstate_fdc_phase,
+ NULL
}
};
diff --git a/hw/char/serial.c b/hw/char/serial.c
index 55011cfd26..513d73c27f 100644
--- a/hw/char/serial.c
+++ b/hw/char/serial.c
@@ -662,6 +662,7 @@ static const VMStateDescription vmstate_serial_thr_ipending = {
.name = "serial/thr_ipending",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = serial_thr_ipending_needed,
.fields = (VMStateField[]) {
VMSTATE_INT32(thr_ipending, SerialState),
VMSTATE_END_OF_LIST()
@@ -678,6 +679,7 @@ static const VMStateDescription vmstate_serial_tsr = {
.name = "serial/tsr",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = serial_tsr_needed,
.fields = (VMStateField[]) {
VMSTATE_INT32(tsr_retry, SerialState),
VMSTATE_UINT8(thr, SerialState),
@@ -697,6 +699,7 @@ static const VMStateDescription vmstate_serial_recv_fifo = {
.name = "serial/recv_fifo",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = serial_recv_fifo_needed,
.fields = (VMStateField[]) {
VMSTATE_STRUCT(recv_fifo, SerialState, 1, vmstate_fifo8, Fifo8),
VMSTATE_END_OF_LIST()
@@ -713,6 +716,7 @@ static const VMStateDescription vmstate_serial_xmit_fifo = {
.name = "serial/xmit_fifo",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = serial_xmit_fifo_needed,
.fields = (VMStateField[]) {
VMSTATE_STRUCT(xmit_fifo, SerialState, 1, vmstate_fifo8, Fifo8),
VMSTATE_END_OF_LIST()
@@ -729,6 +733,7 @@ static const VMStateDescription vmstate_serial_fifo_timeout_timer = {
.name = "serial/fifo_timeout_timer",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = serial_fifo_timeout_timer_needed,
.fields = (VMStateField[]) {
VMSTATE_TIMER_PTR(fifo_timeout_timer, SerialState),
VMSTATE_END_OF_LIST()
@@ -745,6 +750,7 @@ static const VMStateDescription vmstate_serial_timeout_ipending = {
.name = "serial/timeout_ipending",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = serial_timeout_ipending_needed,
.fields = (VMStateField[]) {
VMSTATE_INT32(timeout_ipending, SerialState),
VMSTATE_END_OF_LIST()
@@ -760,6 +766,7 @@ static bool serial_poll_needed(void *opaque)
static const VMStateDescription vmstate_serial_poll = {
.name = "serial/poll",
.version_id = 1,
+ .needed = serial_poll_needed,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_INT32(poll_msl, SerialState),
@@ -788,31 +795,15 @@ const VMStateDescription vmstate_serial = {
VMSTATE_UINT8_V(fcr_vmstate, SerialState, 3),
VMSTATE_END_OF_LIST()
},
- .subsections = (VMStateSubsection[]) {
- {
- .vmsd = &vmstate_serial_thr_ipending,
- .needed = &serial_thr_ipending_needed,
- } , {
- .vmsd = &vmstate_serial_tsr,
- .needed = &serial_tsr_needed,
- } , {
- .vmsd = &vmstate_serial_recv_fifo,
- .needed = &serial_recv_fifo_needed,
- } , {
- .vmsd = &vmstate_serial_xmit_fifo,
- .needed = &serial_xmit_fifo_needed,
- } , {
- .vmsd = &vmstate_serial_fifo_timeout_timer,
- .needed = &serial_fifo_timeout_timer_needed,
- } , {
- .vmsd = &vmstate_serial_timeout_ipending,
- .needed = &serial_timeout_ipending_needed,
- } , {
- .vmsd = &vmstate_serial_poll,
- .needed = &serial_poll_needed,
- } , {
- /* empty */
- }
+ .subsections = (const VMStateDescription*[]) {
+ &vmstate_serial_thr_ipending,
+ &vmstate_serial_tsr,
+ &vmstate_serial_recv_fifo,
+ &vmstate_serial_xmit_fifo,
+ &vmstate_serial_fifo_timeout_timer,
+ &vmstate_serial_timeout_ipending,
+ &vmstate_serial_poll,
+ NULL
}
};
diff --git a/hw/core/nmi.c b/hw/core/nmi.c
index 3dff020659..5260d6c1ec 100644
--- a/hw/core/nmi.c
+++ b/hw/core/nmi.c
@@ -21,6 +21,7 @@
#include "hw/nmi.h"
#include "qapi/qmp/qerror.h"
+#include "monitor/monitor.h"
struct do_nmi_s {
int cpu_index;
@@ -70,6 +71,25 @@ void nmi_monitor_handle(int cpu_index, Error **errp)
}
}
+void inject_nmi(void)
+{
+#if defined(TARGET_I386)
+ CPUState *cs;
+
+ CPU_FOREACH(cs) {
+ X86CPU *cpu = X86_CPU(cs);
+
+ if (!cpu->apic_state) {
+ cpu_interrupt(cs, CPU_INTERRUPT_NMI);
+ } else {
+ apic_deliver_nmi(cpu->apic_state);
+ }
+ }
+#else
+ nmi_monitor_handle(0, NULL);
+#endif
+}
+
static const TypeInfo nmi_info = {
.name = TYPE_NMI,
.parent = TYPE_INTERFACE,
diff --git a/hw/display/exynos4210_fimd.c b/hw/display/exynos4210_fimd.c
index 72b3a1d063..603ef50568 100644
--- a/hw/display/exynos4210_fimd.c
+++ b/hw/display/exynos4210_fimd.c
@@ -337,7 +337,7 @@ static inline void fimd_swap_data(unsigned int swap_ctl, uint64_t *data)
if (swap_ctl & FIMD_WINCON_SWAP_BITS) {
res = 0;
for (i = 0; i < 64; i++) {
- if (x & (1ULL << (64 - i))) {
+ if (x & (1ULL << (63 - i))) {
res |= (1ULL << i);
}
}
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index b220e2d5d2..722146ec3a 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -2220,6 +2220,7 @@ static VMStateDescription qxl_vmstate_monitors_config = {
.name = "qxl/monitors-config",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = qxl_monitors_config_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT64(guest_monitors_config, PCIQXLDevice),
VMSTATE_END_OF_LIST()
@@ -2253,13 +2254,9 @@ static VMStateDescription qxl_vmstate = {
VMSTATE_UINT64(guest_cursor, PCIQXLDevice),
VMSTATE_END_OF_LIST()
},
- .subsections = (VMStateSubsection[]) {
- {
- .vmsd = &qxl_vmstate_monitors_config,
- .needed = qxl_monitors_config_needed,
- }, {
- /* empty */
- }
+ .subsections = (const VMStateDescription*[]) {
+ &qxl_vmstate_monitors_config,
+ NULL
}
};
diff --git a/hw/display/vga.c b/hw/display/vga.c
index d1d296c74e..b35d523e65 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -2035,6 +2035,7 @@ static const VMStateDescription vmstate_vga_endian = {
.name = "vga.endian",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = vga_endian_state_needed,
.fields = (VMStateField[]) {
VMSTATE_BOOL(big_endian_fb, VGACommonState),
VMSTATE_END_OF_LIST()
@@ -2078,13 +2079,9 @@ const VMStateDescription vmstate_vga_common = {
VMSTATE_UINT32(vbe_bank_mask, VGACommonState),
VMSTATE_END_OF_LIST()
},
- .subsections = (VMStateSubsection []) {
- {
- .vmsd = &vmstate_vga_endian,
- .needed = vga_endian_state_needed,
- }, {
- /* empty */
- }
+ .subsections = (const VMStateDescription*[]) {
+ &vmstate_vga_endian,
+ NULL
}
};
diff --git a/hw/dma/rc4030.c b/hw/dma/rc4030.c
index af2663256e..3efa6de352 100644
--- a/hw/dma/rc4030.c
+++ b/hw/dma/rc4030.c
@@ -1,7 +1,7 @@
/*
* QEMU JAZZ RC4030 chipset
*
- * Copyright (c) 2007-2009 Herve Poussineau
+ * Copyright (c) 2007-2013 Hervé Poussineau
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -24,29 +24,16 @@
#include "hw/hw.h"
#include "hw/mips/mips.h"
+#include "hw/sysbus.h"
#include "qemu/timer.h"
-
-/********************************************************/
-/* debug rc4030 */
-
-//#define DEBUG_RC4030
-//#define DEBUG_RC4030_DMA
-
-#ifdef DEBUG_RC4030
-#define DPRINTF(fmt, ...) \
-do { printf("rc4030: " fmt , ## __VA_ARGS__); } while (0)
-static const char* irq_names[] = { "parallel", "floppy", "sound", "video",
- "network", "scsi", "keyboard", "mouse", "serial0", "serial1" };
-#else
-#define DPRINTF(fmt, ...)
-#endif
-
-#define RC4030_ERROR(fmt, ...) \
-do { fprintf(stderr, "rc4030 ERROR: %s: " fmt, __func__ , ## __VA_ARGS__); } while (0)
+#include "exec/address-spaces.h"
+#include "trace.h"
/********************************************************/
/* rc4030 emulation */
+#define MAX_TL_ENTRIES 512
+
typedef struct dma_pagetable_entry {
int32_t frame;
int32_t owner;
@@ -63,8 +50,14 @@ typedef struct dma_pagetable_entry {
#define DMA_FLAG_MEM_INTR 0x0200
#define DMA_FLAG_ADDR_INTR 0x0400
+#define TYPE_RC4030 "rc4030"
+#define RC4030(obj) \
+ OBJECT_CHECK(rc4030State, (obj), TYPE_RC4030)
+
typedef struct rc4030State
{
+ SysBusDevice parent;
+
uint32_t config; /* 0x0000: RC4030 config register */
uint32_t revision; /* 0x0008: RC4030 Revision register */
uint32_t invalid_address_register; /* 0x0010: Invalid Address register */
@@ -83,7 +76,7 @@ typedef struct rc4030State
uint32_t cache_bmask; /* 0x0058: I/O Cache Byte Mask */
uint32_t nmi_interrupt; /* 0x0200: interrupt source */
- uint32_t offset210;
+ uint32_t memory_refresh_rate; /* 0x0210: memory refresh rate */
uint32_t nvram_protect; /* 0x0220: NV ram protect register */
uint32_t rem_speed[16];
uint32_t imr_jazz; /* Local bus int enable mask */
@@ -96,6 +89,16 @@ typedef struct rc4030State
qemu_irq timer_irq;
qemu_irq jazz_bus_irq;
+ /* biggest translation table */
+ MemoryRegion dma_tt;
+ /* translation table memory region alias, added to system RAM */
+ MemoryRegion dma_tt_alias;
+ /* whole DMA memory region, root of DMA address space */
+ MemoryRegion dma_mr;
+ /* translation table entry aliases, added to DMA memory region */
+ MemoryRegion dma_mrs[MAX_TL_ENTRIES];
+ AddressSpace dma_as;
+
MemoryRegion iomem_chipset;
MemoryRegion iomem_jazzio;
} rc4030State;
@@ -112,7 +115,7 @@ static void set_next_tick(rc4030State *s)
}
/* called for accesses to rc4030 */
-static uint32_t rc4030_readl(void *opaque, hwaddr addr)
+static uint64_t rc4030_read(void *opaque, hwaddr addr, unsigned int size)
{
rc4030State *s = opaque;
uint32_t val;
@@ -220,9 +223,9 @@ static uint32_t rc4030_readl(void *opaque, hwaddr addr)
case 0x0208:
val = 0;
break;
- /* Offset 0x0210 */
+ /* Memory refresh rate */
case 0x0210:
- val = s->offset210;
+ val = s->memory_refresh_rate;
break;
/* NV ram protect register */
case 0x0220:
@@ -238,39 +241,117 @@ static uint32_t rc4030_readl(void *opaque, hwaddr addr)
val = 7; /* FIXME: should be read from EISA controller */
break;
default:
- RC4030_ERROR("invalid read [" TARGET_FMT_plx "]\n", addr);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "rc4030: invalid read at 0x%x", (int)addr);
val = 0;
break;
}
if ((addr & ~3) != 0x230) {
- DPRINTF("read 0x%02x at " TARGET_FMT_plx "\n", val, addr);
+ trace_rc4030_read(addr, val);
}
return val;
}
-static uint32_t rc4030_readw(void *opaque, hwaddr addr)
+static void rc4030_dma_as_update_one(rc4030State *s, int index, uint32_t frame)
{
- uint32_t v = rc4030_readl(opaque, addr & ~0x3);
- if (addr & 0x2)
- return v >> 16;
- else
- return v & 0xffff;
+ if (index < MAX_TL_ENTRIES) {
+ memory_region_set_enabled(&s->dma_mrs[index], false);
+ }
+
+ if (!frame) {
+ return;
+ }
+
+ if (index >= MAX_TL_ENTRIES) {
+ qemu_log_mask(LOG_UNIMP,
+ "rc4030: trying to use too high "
+ "translation table entry %d (max allowed=%d)",
+ index, MAX_TL_ENTRIES);
+ return;
+ }
+ memory_region_set_alias_offset(&s->dma_mrs[index], frame);
+ memory_region_set_enabled(&s->dma_mrs[index], true);
}
-static uint32_t rc4030_readb(void *opaque, hwaddr addr)
+static void rc4030_dma_tt_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned int size)
{
- uint32_t v = rc4030_readl(opaque, addr & ~0x3);
- return (v >> (8 * (addr & 0x3))) & 0xff;
+ rc4030State *s = opaque;
+
+ /* write memory */
+ memcpy(memory_region_get_ram_ptr(&s->dma_tt) + addr, &data, size);
+
+ /* update dma address space (only if frame field has been written) */
+ if (addr % sizeof(dma_pagetable_entry) == 0) {
+ int index = addr / sizeof(dma_pagetable_entry);
+ memory_region_transaction_begin();
+ rc4030_dma_as_update_one(s, index, (uint32_t)data);
+ memory_region_transaction_commit();
+ }
}
-static void rc4030_writel(void *opaque, hwaddr addr, uint32_t val)
+static const MemoryRegionOps rc4030_dma_tt_ops = {
+ .write = rc4030_dma_tt_write,
+ .impl.min_access_size = 4,
+ .impl.max_access_size = 4,
+};
+
+static void rc4030_dma_tt_update(rc4030State *s, uint32_t new_tl_base,
+ uint32_t new_tl_limit)
+{
+ int entries, i;
+ dma_pagetable_entry *dma_tl_contents;
+
+ if (s->dma_tl_limit) {
+ /* write old dma tl table to physical memory */
+ memory_region_del_subregion(get_system_memory(), &s->dma_tt_alias);
+ cpu_physical_memory_write(s->dma_tl_limit & 0x7fffffff,
+ memory_region_get_ram_ptr(&s->dma_tt),
+ memory_region_size(&s->dma_tt_alias));
+ }
+ object_unparent(OBJECT(&s->dma_tt_alias));
+
+ s->dma_tl_base = new_tl_base;
+ s->dma_tl_limit = new_tl_limit;
+ new_tl_base &= 0x7fffffff;
+
+ if (s->dma_tl_limit) {
+ uint64_t dma_tt_size;
+ if (s->dma_tl_limit <= memory_region_size(&s->dma_tt)) {
+ dma_tt_size = s->dma_tl_limit;
+ } else {
+ dma_tt_size = memory_region_size(&s->dma_tt);
+ }
+ memory_region_init_alias(&s->dma_tt_alias, OBJECT(s),
+ "dma-table-alias",
+ &s->dma_tt, 0, dma_tt_size);
+ dma_tl_contents = memory_region_get_ram_ptr(&s->dma_tt);
+ cpu_physical_memory_read(new_tl_base, dma_tl_contents, dma_tt_size);
+
+ memory_region_transaction_begin();
+ entries = dma_tt_size / sizeof(dma_pagetable_entry);
+ for (i = 0; i < entries; i++) {
+ rc4030_dma_as_update_one(s, i, dma_tl_contents[i].frame);
+ }
+ memory_region_add_subregion(get_system_memory(), new_tl_base,
+ &s->dma_tt_alias);
+ memory_region_transaction_commit();
+ } else {
+ memory_region_init(&s->dma_tt_alias, OBJECT(s),
+ "dma-table-alias", 0);
+ }
+}
+
+static void rc4030_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned int size)
{
rc4030State *s = opaque;
+ uint32_t val = data;
addr &= 0x3fff;
- DPRINTF("write 0x%02x at " TARGET_FMT_plx "\n", val, addr);
+ trace_rc4030_write(addr, val);
switch (addr & ~0x3) {
/* Global config register */
@@ -279,11 +360,11 @@ static void rc4030_writel(void *opaque, hwaddr addr, uint32_t val)
break;
/* DMA transl. table base */
case 0x0018:
- s->dma_tl_base = val;
+ rc4030_dma_tt_update(s, val, s->dma_tl_limit);
break;
/* DMA transl. table limit */
case 0x0020:
- s->dma_tl_limit = val;
+ rc4030_dma_tt_update(s, s->dma_tl_base, val);
break;
/* DMA transl. table invalidated */
case 0x0028:
@@ -371,9 +452,9 @@ static void rc4030_writel(void *opaque, hwaddr addr, uint32_t val)
s->dma_regs[entry][idx] = val;
}
break;
- /* Offset 0x0210 */
+ /* Memory refresh rate */
case 0x0210:
- s->offset210 = val;
+ s->memory_refresh_rate = val;
break;
/* Interval timer reload */
case 0x0228:
@@ -385,48 +466,18 @@ static void rc4030_writel(void *opaque, hwaddr addr, uint32_t val)
case 0x0238:
break;
default:
- RC4030_ERROR("invalid write of 0x%02x at [" TARGET_FMT_plx "]\n", val, addr);
- break;
- }
-}
-
-static void rc4030_writew(void *opaque, hwaddr addr, uint32_t val)
-{
- uint32_t old_val = rc4030_readl(opaque, addr & ~0x3);
-
- if (addr & 0x2)
- val = (val << 16) | (old_val & 0x0000ffff);
- else
- val = val | (old_val & 0xffff0000);
- rc4030_writel(opaque, addr & ~0x3, val);
-}
-
-static void rc4030_writeb(void *opaque, hwaddr addr, uint32_t val)
-{
- uint32_t old_val = rc4030_readl(opaque, addr & ~0x3);
-
- switch (addr & 3) {
- case 0:
- val = val | (old_val & 0xffffff00);
- break;
- case 1:
- val = (val << 8) | (old_val & 0xffff00ff);
- break;
- case 2:
- val = (val << 16) | (old_val & 0xff00ffff);
- break;
- case 3:
- val = (val << 24) | (old_val & 0x00ffffff);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "rc4030: invalid write of 0x%02x at 0x%x",
+ val, (int)addr);
break;
}
- rc4030_writel(opaque, addr & ~0x3, val);
}
static const MemoryRegionOps rc4030_ops = {
- .old_mmio = {
- .read = { rc4030_readb, rc4030_readw, rc4030_readl, },
- .write = { rc4030_writeb, rc4030_writew, rc4030_writel, },
- },
+ .read = rc4030_read,
+ .write = rc4030_write,
+ .impl.min_access_size = 4,
+ .impl.max_access_size = 4,
.endianness = DEVICE_NATIVE_ENDIAN,
};
@@ -436,22 +487,6 @@ static void update_jazz_irq(rc4030State *s)
pending = s->isr_jazz & s->imr_jazz;
-#ifdef DEBUG_RC4030
- if (s->isr_jazz != 0) {
- uint32_t irq = 0;
- DPRINTF("pending irqs:");
- for (irq = 0; irq < ARRAY_SIZE(irq_names); irq++) {
- if (s->isr_jazz & (1 << irq)) {
- printf(" %s", irq_names[irq]);
- if (!(s->imr_jazz & (1 << irq))) {
- printf("(ignored)");
- }
- }
- }
- printf("\n");
- }
-#endif
-
if (pending != 0)
qemu_irq_raise(s->jazz_bus_irq);
else
@@ -479,7 +514,7 @@ static void rc4030_periodic_timer(void *opaque)
qemu_irq_raise(s->timer_irq);
}
-static uint32_t jazzio_readw(void *opaque, hwaddr addr)
+static uint64_t jazzio_read(void *opaque, hwaddr addr, unsigned int size)
{
rc4030State *s = opaque;
uint32_t val;
@@ -494,7 +529,6 @@ static uint32_t jazzio_readw(void *opaque, hwaddr addr)
irq = 0;
while (pending) {
if (pending & 1) {
- DPRINTF("returning irq %s\n", irq_names[irq]);
val = (irq + 1) << 2;
break;
}
@@ -508,36 +542,25 @@ static uint32_t jazzio_readw(void *opaque, hwaddr addr)
val = s->imr_jazz;
break;
default:
- RC4030_ERROR("(jazz io controller) invalid read [" TARGET_FMT_plx "]\n", addr);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "rc4030/jazzio: invalid read at 0x%x", (int)addr);
val = 0;
+ break;
}
- DPRINTF("(jazz io controller) read 0x%04x at " TARGET_FMT_plx "\n", val, addr);
+ trace_jazzio_read(addr, val);
return val;
}
-static uint32_t jazzio_readb(void *opaque, hwaddr addr)
-{
- uint32_t v;
- v = jazzio_readw(opaque, addr & ~0x1);
- return (v >> (8 * (addr & 0x1))) & 0xff;
-}
-
-static uint32_t jazzio_readl(void *opaque, hwaddr addr)
-{
- uint32_t v;
- v = jazzio_readw(opaque, addr);
- v |= jazzio_readw(opaque, addr + 2) << 16;
- return v;
-}
-
-static void jazzio_writew(void *opaque, hwaddr addr, uint32_t val)
+static void jazzio_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned int size)
{
rc4030State *s = opaque;
+ uint32_t val = data;
addr &= 0xfff;
- DPRINTF("(jazz io controller) write 0x%04x at " TARGET_FMT_plx "\n", val, addr);
+ trace_jazzio_write(addr, val);
switch (addr) {
/* Local bus int enable mask */
@@ -546,43 +569,24 @@ static void jazzio_writew(void *opaque, hwaddr addr, uint32_t val)
update_jazz_irq(s);
break;
default:
- RC4030_ERROR("(jazz io controller) invalid write of 0x%04x at [" TARGET_FMT_plx "]\n", val, addr);
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "rc4030/jazzio: invalid write of 0x%02x at 0x%x",
+ val, (int)addr);
break;
}
}
-static void jazzio_writeb(void *opaque, hwaddr addr, uint32_t val)
-{
- uint32_t old_val = jazzio_readw(opaque, addr & ~0x1);
-
- switch (addr & 1) {
- case 0:
- val = val | (old_val & 0xff00);
- break;
- case 1:
- val = (val << 8) | (old_val & 0x00ff);
- break;
- }
- jazzio_writew(opaque, addr & ~0x1, val);
-}
-
-static void jazzio_writel(void *opaque, hwaddr addr, uint32_t val)
-{
- jazzio_writew(opaque, addr, val & 0xffff);
- jazzio_writew(opaque, addr + 2, (val >> 16) & 0xffff);
-}
-
static const MemoryRegionOps jazzio_ops = {
- .old_mmio = {
- .read = { jazzio_readb, jazzio_readw, jazzio_readl, },
- .write = { jazzio_writeb, jazzio_writew, jazzio_writel, },
- },
+ .read = jazzio_read,
+ .write = jazzio_write,
+ .impl.min_access_size = 2,
+ .impl.max_access_size = 2,
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static void rc4030_reset(void *opaque)
+static void rc4030_reset(DeviceState *dev)
{
- rc4030State *s = opaque;
+ rc4030State *s = RC4030(dev);
int i;
s->config = 0x410; /* some boards seem to accept 0x104 too */
@@ -590,14 +594,14 @@ static void rc4030_reset(void *opaque)
s->invalid_address_register = 0;
memset(s->dma_regs, 0, sizeof(s->dma_regs));
- s->dma_tl_base = s->dma_tl_limit = 0;
+ rc4030_dma_tt_update(s, 0, 0);
s->remote_failed_address = s->memory_failed_address = 0;
s->cache_maint = 0;
s->cache_ptag = s->cache_ltag = 0;
s->cache_bmask = 0;
- s->offset210 = 0x18186;
+ s->memory_refresh_rate = 0x18186;
s->nvram_protect = 7;
for (i = 0; i < 15; i++)
s->rem_speed[i] = 7;
@@ -631,7 +635,7 @@ static int rc4030_load(QEMUFile *f, void *opaque, int version_id)
s->cache_ptag = qemu_get_be32(f);
s->cache_ltag = qemu_get_be32(f);
s->cache_bmask = qemu_get_be32(f);
- s->offset210 = qemu_get_be32(f);
+ s->memory_refresh_rate = qemu_get_be32(f);
s->nvram_protect = qemu_get_be32(f);
for (i = 0; i < 15; i++)
s->rem_speed[i] = qemu_get_be32(f);
@@ -663,7 +667,7 @@ static void rc4030_save(QEMUFile *f, void *opaque)
qemu_put_be32(f, s->cache_ptag);
qemu_put_be32(f, s->cache_ltag);
qemu_put_be32(f, s->cache_bmask);
- qemu_put_be32(f, s->offset210);
+ qemu_put_be32(f, s->memory_refresh_rate);
qemu_put_be32(f, s->nvram_protect);
for (i = 0; i < 15; i++)
qemu_put_be32(f, s->rem_speed[i]);
@@ -672,44 +676,6 @@ static void rc4030_save(QEMUFile *f, void *opaque)
qemu_put_be32(f, s->itr);
}
-void rc4030_dma_memory_rw(void *opaque, hwaddr addr, uint8_t *buf, int len, int is_write)
-{
- rc4030State *s = opaque;
- hwaddr entry_addr;
- hwaddr phys_addr;
- dma_pagetable_entry entry;
- int index;
- int ncpy, i;
-
- i = 0;
- for (;;) {
- if (i == len) {
- break;
- }
-
- ncpy = DMA_PAGESIZE - (addr & (DMA_PAGESIZE - 1));
- if (ncpy > len - i)
- ncpy = len - i;
-
- /* Get DMA translation table entry */
- index = addr / DMA_PAGESIZE;
- if (index >= s->dma_tl_limit / sizeof(dma_pagetable_entry)) {
- break;
- }
- entry_addr = s->dma_tl_base + index * sizeof(dma_pagetable_entry);
- /* XXX: not sure. should we really use only lowest bits? */
- entry_addr &= 0x7fffffff;
- cpu_physical_memory_read(entry_addr, &entry, sizeof(entry));
-
- /* Read/write data at right place */
- phys_addr = entry.frame + (addr & (DMA_PAGESIZE - 1));
- cpu_physical_memory_rw(phys_addr, &buf[i], ncpy, is_write);
-
- i += ncpy;
- addr += ncpy;
- }
-}
-
static void rc4030_do_dma(void *opaque, int n, uint8_t *buf, int len, int is_write)
{
rc4030State *s = opaque;
@@ -733,32 +699,11 @@ static void rc4030_do_dma(void *opaque, int n, uint8_t *buf, int len, int is_wri
dma_addr = s->dma_regs[n][DMA_REG_ADDRESS];
/* Read/write data at right place */
- rc4030_dma_memory_rw(opaque, dma_addr, buf, len, is_write);
+ address_space_rw(&s->dma_as, dma_addr, MEMTXATTRS_UNSPECIFIED,
+ buf, len, is_write);
s->dma_regs[n][DMA_REG_ENABLE] |= DMA_FLAG_TC_INTR;
s->dma_regs[n][DMA_REG_COUNT] -= len;
-
-#ifdef DEBUG_RC4030_DMA
- {
- int i, j;
- printf("rc4030 dma: Copying %d bytes %s host %p\n",
- len, is_write ? "from" : "to", buf);
- for (i = 0; i < len; i += 16) {
- int n = 16;
- if (n > len - i) {
- n = len - i;
- }
- for (j = 0; j < n; j++)
- printf("%02x ", buf[i + j]);
- while (j++ < 16)
- printf(" ");
- printf("| ");
- for (j = 0; j < n; j++)
- printf("%c", isprint(buf[i + j]) ? buf[i + j] : '.');
- printf("\n");
- }
- }
-#endif
}
struct rc4030DMAState {
@@ -795,31 +740,102 @@ static rc4030_dma *rc4030_allocate_dmas(void *opaque, int n)
return s;
}
-void *rc4030_init(qemu_irq timer, qemu_irq jazz_bus,
- qemu_irq **irqs, rc4030_dma **dmas,
- MemoryRegion *sysmem)
+static void rc4030_initfn(Object *obj)
{
- rc4030State *s;
+ DeviceState *dev = DEVICE(obj);
+ rc4030State *s = RC4030(obj);
+ SysBusDevice *sysbus = SYS_BUS_DEVICE(obj);
- s = g_malloc0(sizeof(rc4030State));
+ qdev_init_gpio_in(dev, rc4030_irq_jazz_request, 16);
- *irqs = qemu_allocate_irqs(rc4030_irq_jazz_request, s, 16);
- *dmas = rc4030_allocate_dmas(s, 4);
+ sysbus_init_irq(sysbus, &s->timer_irq);
+ sysbus_init_irq(sysbus, &s->jazz_bus_irq);
- s->periodic_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, rc4030_periodic_timer, s);
- s->timer_irq = timer;
- s->jazz_bus_irq = jazz_bus;
-
- qemu_register_reset(rc4030_reset, s);
register_savevm(NULL, "rc4030", 0, 2, rc4030_save, rc4030_load, s);
- rc4030_reset(s);
+
+ sysbus_init_mmio(sysbus, &s->iomem_chipset);
+ sysbus_init_mmio(sysbus, &s->iomem_jazzio);
+}
+
+static void rc4030_realize(DeviceState *dev, Error **errp)
+{
+ rc4030State *s = RC4030(dev);
+ Object *o = OBJECT(dev);
+ int i;
+
+ s->periodic_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
+ rc4030_periodic_timer, s);
memory_region_init_io(&s->iomem_chipset, NULL, &rc4030_ops, s,
"rc4030.chipset", 0x300);
- memory_region_add_subregion(sysmem, 0x80000000, &s->iomem_chipset);
memory_region_init_io(&s->iomem_jazzio, NULL, &jazzio_ops, s,
"rc4030.jazzio", 0x00001000);
- memory_region_add_subregion(sysmem, 0xf0000000, &s->iomem_jazzio);
- return s;
+ memory_region_init_rom_device(&s->dma_tt, o,
+ &rc4030_dma_tt_ops, s, "dma-table",
+ MAX_TL_ENTRIES * sizeof(dma_pagetable_entry),
+ NULL);
+ memory_region_init(&s->dma_tt_alias, o, "dma-table-alias", 0);
+ memory_region_init(&s->dma_mr, o, "dma", INT32_MAX);
+ for (i = 0; i < MAX_TL_ENTRIES; ++i) {
+ memory_region_init_alias(&s->dma_mrs[i], o, "dma-alias",
+ get_system_memory(), 0, DMA_PAGESIZE);
+ memory_region_set_enabled(&s->dma_mrs[i], false);
+ memory_region_add_subregion(&s->dma_mr, i * DMA_PAGESIZE,
+ &s->dma_mrs[i]);
+ }
+ address_space_init(&s->dma_as, &s->dma_mr, "rc4030-dma");
+}
+
+static void rc4030_unrealize(DeviceState *dev, Error **errp)
+{
+ rc4030State *s = RC4030(dev);
+ int i;
+
+ timer_free(s->periodic_timer);
+
+ address_space_destroy(&s->dma_as);
+ object_unparent(OBJECT(&s->dma_tt));
+ object_unparent(OBJECT(&s->dma_tt_alias));
+ object_unparent(OBJECT(&s->dma_mr));
+ for (i = 0; i < MAX_TL_ENTRIES; ++i) {
+ memory_region_del_subregion(&s->dma_mr, &s->dma_mrs[i]);
+ object_unparent(OBJECT(&s->dma_mrs[i]));
+ }
+}
+
+static void rc4030_class_init(ObjectClass *klass, void *class_data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ dc->realize = rc4030_realize;
+ dc->unrealize = rc4030_unrealize;
+ dc->reset = rc4030_reset;
+}
+
+static const TypeInfo rc4030_info = {
+ .name = TYPE_RC4030,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(rc4030State),
+ .instance_init = rc4030_initfn,
+ .class_init = rc4030_class_init,
+};
+
+static void rc4030_register_types(void)
+{
+ type_register_static(&rc4030_info);
+}
+
+type_init(rc4030_register_types)
+
+DeviceState *rc4030_init(rc4030_dma **dmas, MemoryRegion **dma_mr)
+{
+ DeviceState *dev;
+
+ dev = qdev_create(NULL, TYPE_RC4030);
+ qdev_init_nofail(dev);
+
+ *dmas = rc4030_allocate_dmas(dev, 4);
+ *dma_mr = &RC4030(dev)->dma_mr;
+ return dev;
}
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 5253e6d4fa..e142f75649 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -52,6 +52,7 @@
#ifdef CONFIG_XEN
# include <xen/hvm/hvm_info_table.h>
#endif
+#include "migration/migration.h"
#define MAX_IDE_BUS 2
@@ -305,6 +306,7 @@ static void pc_init1(MachineState *machine)
static void pc_compat_2_3(MachineState *machine)
{
+ savevm_skip_section_footers();
}
static void pc_compat_2_2(MachineState *machine)
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 110dfb78a8..b68263d231 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -45,6 +45,7 @@
#include "hw/usb.h"
#include "hw/cpu/icc_bus.h"
#include "qemu/error-report.h"
+#include "migration/migration.h"
/* ICH9 AHCI has 6 ports */
#define MAX_SATA_PORTS 6
@@ -289,6 +290,7 @@ static void pc_q35_init(MachineState *machine)
static void pc_compat_2_3(MachineState *machine)
{
+ savevm_skip_section_footers();
}
static void pc_compat_2_2(MachineState *machine)
diff --git a/hw/ide/core.c b/hw/ide/core.c
index fcb908061c..1efd98af63 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -2561,6 +2561,7 @@ static const VMStateDescription vmstate_ide_atapi_gesn_state = {
.name ="ide_drive/atapi/gesn_state",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = ide_atapi_gesn_needed,
.fields = (VMStateField[]) {
VMSTATE_BOOL(events.new_media, IDEState),
VMSTATE_BOOL(events.eject_request, IDEState),
@@ -2572,6 +2573,7 @@ static const VMStateDescription vmstate_ide_tray_state = {
.name = "ide_drive/tray_state",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = ide_tray_state_needed,
.fields = (VMStateField[]) {
VMSTATE_BOOL(tray_open, IDEState),
VMSTATE_BOOL(tray_locked, IDEState),
@@ -2585,6 +2587,7 @@ static const VMStateDescription vmstate_ide_drive_pio_state = {
.minimum_version_id = 1,
.pre_save = ide_drive_pio_pre_save,
.post_load = ide_drive_pio_post_load,
+ .needed = ide_drive_pio_state_needed,
.fields = (VMStateField[]) {
VMSTATE_INT32(req_nb_sectors, IDEState),
VMSTATE_VARRAY_INT32(io_buffer, IDEState, io_buffer_total_len, 1,
@@ -2626,19 +2629,11 @@ const VMStateDescription vmstate_ide_drive = {
VMSTATE_UINT8_V(cdrom_changed, IDEState, 3),
VMSTATE_END_OF_LIST()
},
- .subsections = (VMStateSubsection []) {
- {
- .vmsd = &vmstate_ide_drive_pio_state,
- .needed = ide_drive_pio_state_needed,
- }, {
- .vmsd = &vmstate_ide_tray_state,
- .needed = ide_tray_state_needed,
- }, {
- .vmsd = &vmstate_ide_atapi_gesn_state,
- .needed = ide_atapi_gesn_needed,
- }, {
- /* empty */
- }
+ .subsections = (const VMStateDescription*[]) {
+ &vmstate_ide_drive_pio_state,
+ &vmstate_ide_tray_state,
+ &vmstate_ide_atapi_gesn_state,
+ NULL
}
};
@@ -2646,6 +2641,7 @@ static const VMStateDescription vmstate_ide_error_status = {
.name ="ide_bus/error",
.version_id = 2,
.minimum_version_id = 1,
+ .needed = ide_error_needed,
.fields = (VMStateField[]) {
VMSTATE_INT32(error_status, IDEBus),
VMSTATE_INT64_V(retry_sector_num, IDEBus, 2),
@@ -2664,13 +2660,9 @@ const VMStateDescription vmstate_ide_bus = {
VMSTATE_UINT8(unit, IDEBus),
VMSTATE_END_OF_LIST()
},
- .subsections = (VMStateSubsection []) {
- {
- .vmsd = &vmstate_ide_error_status,
- .needed = ide_error_needed,
- }, {
- /* empty */
- }
+ .subsections = (const VMStateDescription*[]) {
+ &vmstate_ide_error_status,
+ NULL
}
};
diff --git a/hw/ide/pci.c b/hw/ide/pci.c
index 4b5e32dcbe..4afd0cfe8c 100644
--- a/hw/ide/pci.c
+++ b/hw/ide/pci.c
@@ -350,6 +350,7 @@ static const VMStateDescription vmstate_bmdma_current = {
.name = "ide bmdma_current",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = ide_bmdma_current_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT32(cur_addr, BMDMAState),
VMSTATE_UINT32(cur_prd_last, BMDMAState),
@@ -363,6 +364,7 @@ static const VMStateDescription vmstate_bmdma_status = {
.name ="ide bmdma/status",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = ide_bmdma_status_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT8(status, BMDMAState),
VMSTATE_END_OF_LIST()
@@ -383,16 +385,10 @@ static const VMStateDescription vmstate_bmdma = {
VMSTATE_UINT8(migration_retry_unit, BMDMAState),
VMSTATE_END_OF_LIST()
},
- .subsections = (VMStateSubsection []) {
- {
- .vmsd = &vmstate_bmdma_current,
- .needed = ide_bmdma_current_needed,
- }, {
- .vmsd = &vmstate_bmdma_status,
- .needed = ide_bmdma_status_needed,
- }, {
- /* empty */
- }
+ .subsections = (const VMStateDescription*[]) {
+ &vmstate_bmdma_current,
+ &vmstate_bmdma_status,
+ NULL
}
};
diff --git a/hw/input/pckbd.c b/hw/input/pckbd.c
index 9b9a7d7a8a..ddac69df6f 100644
--- a/hw/input/pckbd.c
+++ b/hw/input/pckbd.c
@@ -391,23 +391,24 @@ static int kbd_outport_post_load(void *opaque, int version_id)
return 0;
}
+static bool kbd_outport_needed(void *opaque)
+{
+ KBDState *s = opaque;
+ return s->outport != kbd_outport_default(s);
+}
+
static const VMStateDescription vmstate_kbd_outport = {
.name = "pckbd_outport",
.version_id = 1,
.minimum_version_id = 1,
.post_load = kbd_outport_post_load,
+ .needed = kbd_outport_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT8(outport, KBDState),
VMSTATE_END_OF_LIST()
}
};
-static bool kbd_outport_needed(void *opaque)
-{
- KBDState *s = opaque;
- return s->outport != kbd_outport_default(s);
-}
-
static int kbd_post_load(void *opaque, int version_id)
{
KBDState *s = opaque;
@@ -430,12 +431,9 @@ static const VMStateDescription vmstate_kbd = {
VMSTATE_UINT8(pending, KBDState),
VMSTATE_END_OF_LIST()
},
- .subsections = (VMStateSubsection[]) {
- {
- .vmsd = &vmstate_kbd_outport,
- .needed = kbd_outport_needed,
- },
- VMSTATE_END_OF_LIST()
+ .subsections = (const VMStateDescription*[]) {
+ &vmstate_kbd_outport,
+ NULL
}
};
diff --git a/hw/input/ps2.c b/hw/input/ps2.c
index 4baeea2b56..fdbe565e62 100644
--- a/hw/input/ps2.c
+++ b/hw/input/ps2.c
@@ -677,6 +677,7 @@ static const VMStateDescription vmstate_ps2_keyboard_ledstate = {
.version_id = 3,
.minimum_version_id = 2,
.post_load = ps2_kbd_ledstate_post_load,
+ .needed = ps2_keyboard_ledstate_needed,
.fields = (VMStateField[]) {
VMSTATE_INT32(ledstate, PS2KbdState),
VMSTATE_END_OF_LIST()
@@ -717,13 +718,9 @@ static const VMStateDescription vmstate_ps2_keyboard = {
VMSTATE_INT32_V(scancode_set, PS2KbdState,3),
VMSTATE_END_OF_LIST()
},
- .subsections = (VMStateSubsection []) {
- {
- .vmsd = &vmstate_ps2_keyboard_ledstate,
- .needed = ps2_keyboard_ledstate_needed,
- }, {
- /* empty */
- }
+ .subsections = (const VMStateDescription*[]) {
+ &vmstate_ps2_keyboard_ledstate,
+ NULL
}
};
diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c
index d595d63a51..0032b97c5f 100644
--- a/hw/intc/apic_common.c
+++ b/hw/intc/apic_common.c
@@ -369,6 +369,7 @@ static const VMStateDescription vmstate_apic_common_sipi = {
.name = "apic_sipi",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = apic_common_sipi_needed,
.fields = (VMStateField[]) {
VMSTATE_INT32(sipi_vector, APICCommonState),
VMSTATE_INT32(wait_for_sipi, APICCommonState),
@@ -408,12 +409,9 @@ static const VMStateDescription vmstate_apic_common = {
APICCommonState), /* open-coded timer state */
VMSTATE_END_OF_LIST()
},
- .subsections = (VMStateSubsection[]) {
- {
- .vmsd = &vmstate_apic_common_sipi,
- .needed = apic_common_sipi_needed,
- },
- VMSTATE_END_OF_LIST()
+ .subsections = (const VMStateDescription*[]) {
+ &vmstate_apic_common_sipi,
+ NULL
}
};
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index c1d2e704ec..454bfd7df5 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -71,7 +71,7 @@ void gic_update(GICState *s)
|| !(s->cpu_ctlr[cpu] & (GICC_CTLR_EN_GRP0 | GICC_CTLR_EN_GRP1))) {
qemu_irq_lower(s->parent_irq[cpu]);
qemu_irq_lower(s->parent_fiq[cpu]);
- return;
+ continue;
}
best_prio = 0x100;
best_irq = 1023;
diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
index 71a9f7a716..b3e0b1fd52 100644
--- a/hw/isa/lpc_ich9.c
+++ b/hw/isa/lpc_ich9.c
@@ -650,6 +650,7 @@ static const VMStateDescription vmstate_ich9_rst_cnt = {
.name = "ICH9LPC/rst_cnt",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = ich9_rst_cnt_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT8(rst_cnt, ICH9LPCState),
VMSTATE_END_OF_LIST()
@@ -669,12 +670,9 @@ static const VMStateDescription vmstate_ich9_lpc = {
VMSTATE_UINT32(sci_level, ICH9LPCState),
VMSTATE_END_OF_LIST()
},
- .subsections = (VMStateSubsection[]) {
- {
- .vmsd = &vmstate_ich9_rst_cnt,
- .needed = ich9_rst_cnt_needed
- },
- { 0 }
+ .subsections = (const VMStateDescription*[]) {
+ &vmstate_ich9_rst_cnt,
+ NULL
}
};
diff --git a/hw/mips/Makefile.objs b/hw/mips/Makefile.objs
index 0a652f8521..9633f3a57d 100644
--- a/hw/mips/Makefile.objs
+++ b/hw/mips/Makefile.objs
@@ -1,4 +1,5 @@
-obj-y += mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
+obj-y += mips_r4k.o mips_malta.o mips_mipssim.o
obj-y += addr.o cputimer.o mips_int.o
+obj-$(CONFIG_JAZZ) += mips_jazz.o
obj-$(CONFIG_FULONG) += mips_fulong2e.o
obj-y += gt64xxx_pci.o
diff --git a/hw/mips/mips_jazz.c b/hw/mips/mips_jazz.c
index 2c153e092f..9d60633efb 100644
--- a/hw/mips/mips_jazz.c
+++ b/hw/mips/mips_jazz.c
@@ -135,16 +135,16 @@ static void mips_jazz_init(MachineState *machine,
MIPSCPU *cpu;
CPUClass *cc;
CPUMIPSState *env;
- qemu_irq *rc4030, *i8259;
+ qemu_irq *i8259;
rc4030_dma *dmas;
- void* rc4030_opaque;
+ MemoryRegion *rc4030_dma_mr;
MemoryRegion *isa_mem = g_new(MemoryRegion, 1);
MemoryRegion *isa_io = g_new(MemoryRegion, 1);
MemoryRegion *rtc = g_new(MemoryRegion, 1);
MemoryRegion *i8042 = g_new(MemoryRegion, 1);
MemoryRegion *dma_dummy = g_new(MemoryRegion, 1);
NICInfo *nd;
- DeviceState *dev;
+ DeviceState *dev, *rc4030;
SysBusDevice *sysbus;
ISABus *isa_bus;
ISADevice *pit;
@@ -157,12 +157,7 @@ static void mips_jazz_init(MachineState *machine,
/* init CPUs */
if (cpu_model == NULL) {
-#ifdef TARGET_MIPS64
cpu_model = "R4000";
-#else
- /* FIXME: All wrong, this maybe should be R3000 for the older JAZZs. */
- cpu_model = "24Kf";
-#endif
}
cpu = cpu_mips_init(cpu_model);
if (cpu == NULL) {
@@ -218,8 +213,14 @@ static void mips_jazz_init(MachineState *machine,
cpu_mips_clock_init(env);
/* Chipset */
- rc4030_opaque = rc4030_init(env->irq[6], env->irq[3], &rc4030, &dmas,
- address_space);
+ rc4030 = rc4030_init(&dmas, &rc4030_dma_mr);
+ sysbus = SYS_BUS_DEVICE(rc4030);
+ sysbus_connect_irq(sysbus, 0, env->irq[6]);
+ sysbus_connect_irq(sysbus, 1, env->irq[3]);
+ memory_region_add_subregion(address_space, 0x80000000,
+ sysbus_mmio_get_region(sysbus, 0));
+ memory_region_add_subregion(address_space, 0xf0000000,
+ sysbus_mmio_get_region(sysbus, 1));
memory_region_init_io(dma_dummy, NULL, &dma_dummy_ops, NULL, "dummy_dma", 0x1000);
memory_region_add_subregion(address_space, 0x8000d000, dma_dummy);
@@ -246,7 +247,7 @@ static void mips_jazz_init(MachineState *machine,
sysbus = SYS_BUS_DEVICE(dev);
sysbus_mmio_map(sysbus, 0, 0x60080000);
sysbus_mmio_map(sysbus, 1, 0x40000000);
- sysbus_connect_irq(sysbus, 0, rc4030[3]);
+ sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in(rc4030, 3));
{
/* Simple ROM, so user doesn't have to provide one */
MemoryRegion *rom_mr = g_new(MemoryRegion, 1);
@@ -272,8 +273,17 @@ static void mips_jazz_init(MachineState *machine,
if (!nd->model)
nd->model = g_strdup("dp83932");
if (strcmp(nd->model, "dp83932") == 0) {
- dp83932_init(nd, 0x80001000, 2, get_system_memory(), rc4030[4],
- rc4030_opaque, rc4030_dma_memory_rw);
+ qemu_check_nic_model(nd, "dp83932");
+
+ dev = qdev_create(NULL, "dp8393x");
+ qdev_set_nic_properties(dev, nd);
+ qdev_prop_set_uint8(dev, "it_shift", 2);
+ qdev_prop_set_ptr(dev, "dma_mr", rc4030_dma_mr);
+ qdev_init_nofail(dev);
+ sysbus = SYS_BUS_DEVICE(dev);
+ sysbus_mmio_map(sysbus, 0, 0x80001000);
+ sysbus_mmio_map(sysbus, 1, 0x8000b000);
+ sysbus_connect_irq(sysbus, 0, qdev_get_gpio_in(rc4030, 4));
break;
} else if (is_help_option(nd->model)) {
fprintf(stderr, "qemu: Supported NICs: dp83932\n");
@@ -287,7 +297,7 @@ static void mips_jazz_init(MachineState *machine,
/* SCSI adapter */
esp_init(0x80002000, 0,
rc4030_dma_read, rc4030_dma_write, dmas[0],
- rc4030[5], &esp_reset, &dma_enable);
+ qdev_get_gpio_in(rc4030, 5), &esp_reset, &dma_enable);
/* Floppy */
if (drive_get_max_bus(IF_FLOPPY) >= MAX_FD) {
@@ -297,7 +307,7 @@ static void mips_jazz_init(MachineState *machine,
for (n = 0; n < MAX_FD; n++) {
fds[n] = drive_get(IF_FLOPPY, 0, n);
}
- fdctrl_init_sysbus(rc4030[1], 0, 0x80003000, fds);
+ fdctrl_init_sysbus(qdev_get_gpio_in(rc4030, 1), 0, 0x80003000, fds);
/* Real time clock */
rtc_init(isa_bus, 1980, NULL);
@@ -305,23 +315,26 @@ static void mips_jazz_init(MachineState *machine,
memory_region_add_subregion(address_space, 0x80004000, rtc);
/* Keyboard (i8042) */
- i8042_mm_init(rc4030[6], rc4030[7], i8042, 0x1000, 0x1);
+ i8042_mm_init(qdev_get_gpio_in(rc4030, 6), qdev_get_gpio_in(rc4030, 7),
+ i8042, 0x1000, 0x1);
memory_region_add_subregion(address_space, 0x80005000, i8042);
/* Serial ports */
if (serial_hds[0]) {
- serial_mm_init(address_space, 0x80006000, 0, rc4030[8], 8000000/16,
+ serial_mm_init(address_space, 0x80006000, 0,
+ qdev_get_gpio_in(rc4030, 8), 8000000/16,
serial_hds[0], DEVICE_NATIVE_ENDIAN);
}
if (serial_hds[1]) {
- serial_mm_init(address_space, 0x80007000, 0, rc4030[9], 8000000/16,
+ serial_mm_init(address_space, 0x80007000, 0,
+ qdev_get_gpio_in(rc4030, 9), 8000000/16,
serial_hds[1], DEVICE_NATIVE_ENDIAN);
}
/* Parallel port */
if (parallel_hds[0])
- parallel_mm_init(address_space, 0x80008000, 0, rc4030[0],
- parallel_hds[0]);
+ parallel_mm_init(address_space, 0x80008000, 0,
+ qdev_get_gpio_in(rc4030, 0), parallel_hds[0]);
/* FIXME: missing Jazz sound at 0x8000c000, rc4030[2] */
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index 5140882c00..786a8f0638 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -97,7 +97,7 @@ typedef struct {
static ISADevice *pit;
static struct _loaderparams {
- int ram_size;
+ int ram_size, ram_low_size;
const char *kernel_filename;
const char *kernel_cmdline;
const char *initrd_filename;
@@ -641,8 +641,8 @@ static void write_bootloader (CPUMIPSState *env, uint8_t *base,
stl_p(p++, 0x34a50000 | (ENVP_ADDR & 0xffff)); /* ori a1, a1, low(ENVP_ADDR) */
stl_p(p++, 0x3c060000 | (((ENVP_ADDR + 8) >> 16) & 0xffff)); /* lui a2, high(ENVP_ADDR + 8) */
stl_p(p++, 0x34c60000 | ((ENVP_ADDR + 8) & 0xffff)); /* ori a2, a2, low(ENVP_ADDR + 8) */
- stl_p(p++, 0x3c070000 | (loaderparams.ram_size >> 16)); /* lui a3, high(ram_size) */
- stl_p(p++, 0x34e70000 | (loaderparams.ram_size & 0xffff)); /* ori a3, a3, low(ram_size) */
+ stl_p(p++, 0x3c070000 | (loaderparams.ram_low_size >> 16)); /* lui a3, high(ram_low_size) */
+ stl_p(p++, 0x34e70000 | (loaderparams.ram_low_size & 0xffff)); /* ori a3, a3, low(ram_low_size) */
/* Load BAR registers as done by YAMON */
stl_p(p++, 0x3c09b400); /* lui t1, 0xb400 */
@@ -851,8 +851,10 @@ static int64_t load_kernel (void)
}
prom_set(prom_buf, prom_index++, "memsize");
- prom_set(prom_buf, prom_index++, "%i",
- MIN(loaderparams.ram_size, 256 << 20));
+ prom_set(prom_buf, prom_index++, "%u", loaderparams.ram_low_size);
+
+ prom_set(prom_buf, prom_index++, "ememsize");
+ prom_set(prom_buf, prom_index++, "%u", loaderparams.ram_size);
prom_set(prom_buf, prom_index++, "modetty0");
prom_set(prom_buf, prom_index++, "38400n8r");
@@ -1054,7 +1056,8 @@ void mips_malta_init(MachineState *machine)
}
/* Write a small bootloader to the flash location. */
- loaderparams.ram_size = ram_low_size;
+ loaderparams.ram_size = ram_size;
+ loaderparams.ram_low_size = ram_low_size;
loaderparams.kernel_filename = kernel_filename;
loaderparams.kernel_cmdline = kernel_cmdline;
loaderparams.initrd_filename = initrd_filename;
diff --git a/hw/net/Makefile.objs b/hw/net/Makefile.objs
index 7b91c4e51d..98801739ef 100644
--- a/hw/net/Makefile.objs
+++ b/hw/net/Makefile.objs
@@ -39,3 +39,4 @@ obj-$(CONFIG_ETSEC) += fsl_etsec/etsec.o fsl_etsec/registers.o \
common-obj-$(CONFIG_ROCKER) += rocker/rocker.o rocker/rocker_fp.o \
rocker/rocker_desc.o rocker/rocker_world.o \
rocker/rocker_of_dpa.o
+obj-$(call lnot,$(CONFIG_ROCKER)) += rocker/qmp-norocker.o
diff --git a/hw/net/dp8393x.c b/hw/net/dp8393x.c
index 7ce13d2b46..cd889bce86 100644
--- a/hw/net/dp8393x.c
+++ b/hw/net/dp8393x.c
@@ -17,20 +17,15 @@
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-#include "hw/hw.h"
-#include "qemu/timer.h"
+#include "hw/sysbus.h"
+#include "hw/devices.h"
#include "net/net.h"
-#include "hw/mips/mips.h"
+#include "qemu/timer.h"
+#include <zlib.h>
//#define DEBUG_SONIC
-/* Calculate CRCs properly on Rx packets */
-#define SONIC_CALCULATE_RXCRC
-
-#if defined(SONIC_CALCULATE_RXCRC)
-/* For crc32 */
-#include <zlib.h>
-#endif
+#define SONIC_PROM_SIZE 0x1000
#ifdef DEBUG_SONIC
#define DPRINTF(fmt, ...) \
@@ -145,9 +140,14 @@ do { printf("sonic ERROR: %s: " fmt, __func__ , ## __VA_ARGS__); } while (0)
#define SONIC_ISR_PINT 0x0800
#define SONIC_ISR_LCD 0x1000
+#define TYPE_DP8393X "dp8393x"
+#define DP8393X(obj) OBJECT_CHECK(dp8393xState, (obj), TYPE_DP8393X)
+
typedef struct dp8393xState {
+ SysBusDevice parent_obj;
+
/* Hardware */
- int it_shift;
+ uint8_t it_shift;
qemu_irq irq;
#ifdef DEBUG_SONIC
int irq_level;
@@ -156,8 +156,8 @@ typedef struct dp8393xState {
int64_t wt_last_update;
NICConf conf;
NICState *nic;
- MemoryRegion *address_space;
MemoryRegion mmio;
+ MemoryRegion prom;
/* Registers */
uint8_t cam[16][6];
@@ -168,8 +168,8 @@ typedef struct dp8393xState {
int loopback_packet;
/* Memory access */
- void (*memory_rw)(void *opaque, hwaddr addr, uint8_t *buf, int len, int is_write);
- void* mem_opaque;
+ void *dma_mr;
+ AddressSpace as;
} dp8393xState;
static void dp8393x_update_irq(dp8393xState *s)
@@ -190,7 +190,7 @@ static void dp8393x_update_irq(dp8393xState *s)
qemu_set_irq(s->irq, level);
}
-static void do_load_cam(dp8393xState *s)
+static void dp8393x_do_load_cam(dp8393xState *s)
{
uint16_t data[8];
int width, size;
@@ -201,9 +201,9 @@ static void do_load_cam(dp8393xState *s)
while (s->regs[SONIC_CDC] & 0x1f) {
/* Fill current entry */
- s->memory_rw(s->mem_opaque,
+ address_space_rw(&s->as,
(s->regs[SONIC_URRA] << 16) | s->regs[SONIC_CDP],
- (uint8_t *)data, size, 0);
+ MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0);
s->cam[index][0] = data[1 * width] & 0xff;
s->cam[index][1] = data[1 * width] >> 8;
s->cam[index][2] = data[2 * width] & 0xff;
@@ -220,9 +220,9 @@ static void do_load_cam(dp8393xState *s)
}
/* Read CAM enable */
- s->memory_rw(s->mem_opaque,
+ address_space_rw(&s->as,
(s->regs[SONIC_URRA] << 16) | s->regs[SONIC_CDP],
- (uint8_t *)data, size, 0);
+ MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0);
s->regs[SONIC_CE] = data[0 * width];
DPRINTF("load cam done. cam enable mask 0x%04x\n", s->regs[SONIC_CE]);
@@ -232,7 +232,7 @@ static void do_load_cam(dp8393xState *s)
dp8393x_update_irq(s);
}
-static void do_read_rra(dp8393xState *s)
+static void dp8393x_do_read_rra(dp8393xState *s)
{
uint16_t data[8];
int width, size;
@@ -240,9 +240,9 @@ static void do_read_rra(dp8393xState *s)
/* Read memory */
width = (s->regs[SONIC_DCR] & SONIC_DCR_DW) ? 2 : 1;
size = sizeof(uint16_t) * 4 * width;
- s->memory_rw(s->mem_opaque,
+ address_space_rw(&s->as,
(s->regs[SONIC_URRA] << 16) | s->regs[SONIC_RRP],
- (uint8_t *)data, size, 0);
+ MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0);
/* Update SONIC registers */
s->regs[SONIC_CRBA0] = data[0 * width];
@@ -272,7 +272,7 @@ static void do_read_rra(dp8393xState *s)
s->regs[SONIC_CR] &= ~SONIC_CR_RRRA;
}
-static void do_software_reset(dp8393xState *s)
+static void dp8393x_do_software_reset(dp8393xState *s)
{
timer_del(s->watchdog);
@@ -280,7 +280,7 @@ static void do_software_reset(dp8393xState *s)
s->regs[SONIC_CR] |= SONIC_CR_RST | SONIC_CR_RXDIS;
}
-static void set_next_tick(dp8393xState *s)
+static void dp8393x_set_next_tick(dp8393xState *s)
{
uint32_t ticks;
int64_t delay;
@@ -296,7 +296,7 @@ static void set_next_tick(dp8393xState *s)
timer_mod(s->watchdog, s->wt_last_update + delay);
}
-static void update_wt_regs(dp8393xState *s)
+static void dp8393x_update_wt_regs(dp8393xState *s)
{
int64_t elapsed;
uint32_t val;
@@ -311,33 +311,33 @@ static void update_wt_regs(dp8393xState *s)
val -= elapsed / 5000000;
s->regs[SONIC_WT1] = (val >> 16) & 0xffff;
s->regs[SONIC_WT0] = (val >> 0) & 0xffff;
- set_next_tick(s);
+ dp8393x_set_next_tick(s);
}
-static void do_start_timer(dp8393xState *s)
+static void dp8393x_do_start_timer(dp8393xState *s)
{
s->regs[SONIC_CR] &= ~SONIC_CR_STP;
- set_next_tick(s);
+ dp8393x_set_next_tick(s);
}
-static void do_stop_timer(dp8393xState *s)
+static void dp8393x_do_stop_timer(dp8393xState *s)
{
s->regs[SONIC_CR] &= ~SONIC_CR_ST;
- update_wt_regs(s);
+ dp8393x_update_wt_regs(s);
}
-static void do_receiver_enable(dp8393xState *s)
+static void dp8393x_do_receiver_enable(dp8393xState *s)
{
s->regs[SONIC_CR] &= ~SONIC_CR_RXDIS;
}
-static void do_receiver_disable(dp8393xState *s)
+static void dp8393x_do_receiver_disable(dp8393xState *s)
{
s->regs[SONIC_CR] &= ~SONIC_CR_RXEN;
}
-static void do_transmit_packets(dp8393xState *s)
+static void dp8393x_do_transmit_packets(dp8393xState *s)
{
NetClientState *nc = qemu_get_queue(s->nic);
uint16_t data[12];
@@ -353,9 +353,9 @@ static void do_transmit_packets(dp8393xState *s)
(s->regs[SONIC_UTDA] << 16) | s->regs[SONIC_CTDA]);
size = sizeof(uint16_t) * 6 * width;
s->regs[SONIC_TTDA] = s->regs[SONIC_CTDA];
- s->memory_rw(s->mem_opaque,
+ address_space_rw(&s->as,
((s->regs[SONIC_UTDA] << 16) | s->regs[SONIC_TTDA]) + sizeof(uint16_t) * width,
- (uint8_t *)data, size, 0);
+ MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0);
tx_len = 0;
/* Update registers */
@@ -379,18 +379,18 @@ static void do_transmit_packets(dp8393xState *s)
if (tx_len + len > sizeof(s->tx_buffer)) {
len = sizeof(s->tx_buffer) - tx_len;
}
- s->memory_rw(s->mem_opaque,
+ address_space_rw(&s->as,
(s->regs[SONIC_TSA1] << 16) | s->regs[SONIC_TSA0],
- &s->tx_buffer[tx_len], len, 0);
+ MEMTXATTRS_UNSPECIFIED, &s->tx_buffer[tx_len], len, 0);
tx_len += len;
i++;
if (i != s->regs[SONIC_TFC]) {
/* Read next fragment details */
size = sizeof(uint16_t) * 3 * width;
- s->memory_rw(s->mem_opaque,
+ address_space_rw(&s->as,
((s->regs[SONIC_UTDA] << 16) | s->regs[SONIC_TTDA]) + sizeof(uint16_t) * (4 + 3 * i) * width,
- (uint8_t *)data, size, 0);
+ MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0);
s->regs[SONIC_TSA0] = data[0 * width];
s->regs[SONIC_TSA1] = data[1 * width];
s->regs[SONIC_TFS] = data[2 * width];
@@ -422,16 +422,16 @@ static void do_transmit_packets(dp8393xState *s)
/* Write status */
data[0 * width] = s->regs[SONIC_TCR] & 0x0fff; /* status */
size = sizeof(uint16_t) * width;
- s->memory_rw(s->mem_opaque,
+ address_space_rw(&s->as,
(s->regs[SONIC_UTDA] << 16) | s->regs[SONIC_TTDA],
- (uint8_t *)data, size, 1);
+ MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 1);
if (!(s->regs[SONIC_CR] & SONIC_CR_HTX)) {
/* Read footer of packet */
size = sizeof(uint16_t) * width;
- s->memory_rw(s->mem_opaque,
+ address_space_rw(&s->as,
((s->regs[SONIC_UTDA] << 16) | s->regs[SONIC_TTDA]) + sizeof(uint16_t) * (4 + 3 * s->regs[SONIC_TFC]) * width,
- (uint8_t *)data, size, 0);
+ MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0);
s->regs[SONIC_CTDA] = data[0 * width] & ~0x1;
if (data[0 * width] & 0x1) {
/* EOL detected */
@@ -446,12 +446,12 @@ static void do_transmit_packets(dp8393xState *s)
dp8393x_update_irq(s);
}
-static void do_halt_transmission(dp8393xState *s)
+static void dp8393x_do_halt_transmission(dp8393xState *s)
{
/* Nothing to do */
}
-static void do_command(dp8393xState *s, uint16_t command)
+static void dp8393x_do_command(dp8393xState *s, uint16_t command)
{
if ((s->regs[SONIC_CR] & SONIC_CR_RST) && !(command & SONIC_CR_RST)) {
s->regs[SONIC_CR] &= ~SONIC_CR_RST;
@@ -461,34 +461,36 @@ static void do_command(dp8393xState *s, uint16_t command)
s->regs[SONIC_CR] |= (command & SONIC_CR_MASK);
if (command & SONIC_CR_HTX)
- do_halt_transmission(s);
+ dp8393x_do_halt_transmission(s);
if (command & SONIC_CR_TXP)
- do_transmit_packets(s);
+ dp8393x_do_transmit_packets(s);
if (command & SONIC_CR_RXDIS)
- do_receiver_disable(s);
+ dp8393x_do_receiver_disable(s);
if (command & SONIC_CR_RXEN)
- do_receiver_enable(s);
+ dp8393x_do_receiver_enable(s);
if (command & SONIC_CR_STP)
- do_stop_timer(s);
+ dp8393x_do_stop_timer(s);
if (command & SONIC_CR_ST)
- do_start_timer(s);
+ dp8393x_do_start_timer(s);
if (command & SONIC_CR_RST)
- do_software_reset(s);
+ dp8393x_do_software_reset(s);
if (command & SONIC_CR_RRRA)
- do_read_rra(s);
+ dp8393x_do_read_rra(s);
if (command & SONIC_CR_LCAM)
- do_load_cam(s);
+ dp8393x_do_load_cam(s);
}
-static uint16_t read_register(dp8393xState *s, int reg)
+static uint64_t dp8393x_read(void *opaque, hwaddr addr, unsigned int size)
{
+ dp8393xState *s = opaque;
+ int reg = addr >> s->it_shift;
uint16_t val = 0;
switch (reg) {
/* Update data before reading it */
case SONIC_WT0:
case SONIC_WT1:
- update_wt_regs(s);
+ dp8393x_update_wt_regs(s);
val = s->regs[reg];
break;
/* Accept read to some registers only when in reset mode */
@@ -510,14 +512,18 @@ static uint16_t read_register(dp8393xState *s, int reg)
return val;
}
-static void write_register(dp8393xState *s, int reg, uint16_t val)
+static void dp8393x_write(void *opaque, hwaddr addr, uint64_t data,
+ unsigned int size)
{
- DPRINTF("write 0x%04x to reg %s\n", val, reg_names[reg]);
+ dp8393xState *s = opaque;
+ int reg = addr >> s->it_shift;
+
+ DPRINTF("write 0x%04x to reg %s\n", (uint16_t)data, reg_names[reg]);
switch (reg) {
/* Command register */
case SONIC_CR:
- do_command(s, val);
+ dp8393x_do_command(s, data);
break;
/* Prevent write to read-only registers */
case SONIC_CAP2:
@@ -530,37 +536,37 @@ static void write_register(dp8393xState *s, int reg, uint16_t val)
/* Accept write to some registers only when in reset mode */
case SONIC_DCR:
if (s->regs[SONIC_CR] & SONIC_CR_RST) {
- s->regs[reg] = val & 0xbfff;
+ s->regs[reg] = data & 0xbfff;
} else {
DPRINTF("writing to DCR invalid\n");
}
break;
case SONIC_DCR2:
if (s->regs[SONIC_CR] & SONIC_CR_RST) {
- s->regs[reg] = val & 0xf017;
+ s->regs[reg] = data & 0xf017;
} else {
DPRINTF("writing to DCR2 invalid\n");
}
break;
/* 12 lower bytes are Read Only */
case SONIC_TCR:
- s->regs[reg] = val & 0xf000;
+ s->regs[reg] = data & 0xf000;
break;
/* 9 lower bytes are Read Only */
case SONIC_RCR:
- s->regs[reg] = val & 0xffe0;
+ s->regs[reg] = data & 0xffe0;
break;
/* Ignore most significant bit */
case SONIC_IMR:
- s->regs[reg] = val & 0x7fff;
+ s->regs[reg] = data & 0x7fff;
dp8393x_update_irq(s);
break;
/* Clear bits by writing 1 to them */
case SONIC_ISR:
- val &= s->regs[reg];
- s->regs[reg] &= ~val;
- if (val & SONIC_ISR_RBE) {
- do_read_rra(s);
+ data &= s->regs[reg];
+ s->regs[reg] &= ~data;
+ if (data & SONIC_ISR_RBE) {
+ dp8393x_do_read_rra(s);
}
dp8393x_update_irq(s);
break;
@@ -569,24 +575,32 @@ static void write_register(dp8393xState *s, int reg, uint16_t val)
case SONIC_REA:
case SONIC_RRP:
case SONIC_RWP:
- s->regs[reg] = val & 0xfffe;
+ s->regs[reg] = data & 0xfffe;
break;
/* Invert written value for some registers */
case SONIC_CRCT:
case SONIC_FAET:
case SONIC_MPT:
- s->regs[reg] = val ^ 0xffff;
+ s->regs[reg] = data ^ 0xffff;
break;
/* All other registers have no special contrainst */
default:
- s->regs[reg] = val;
+ s->regs[reg] = data;
}
if (reg == SONIC_WT0 || reg == SONIC_WT1) {
- set_next_tick(s);
+ dp8393x_set_next_tick(s);
}
}
+static const MemoryRegionOps dp8393x_ops = {
+ .read = dp8393x_read,
+ .write = dp8393x_write,
+ .impl.min_access_size = 2,
+ .impl.max_access_size = 2,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
static void dp8393x_watchdog(void *opaque)
{
dp8393xState *s = opaque;
@@ -597,84 +611,14 @@ static void dp8393x_watchdog(void *opaque)
s->regs[SONIC_WT1] = 0xffff;
s->regs[SONIC_WT0] = 0xffff;
- set_next_tick(s);
+ dp8393x_set_next_tick(s);
/* Signal underflow */
s->regs[SONIC_ISR] |= SONIC_ISR_TC;
dp8393x_update_irq(s);
}
-static uint32_t dp8393x_readw(void *opaque, hwaddr addr)
-{
- dp8393xState *s = opaque;
- int reg;
-
- if ((addr & ((1 << s->it_shift) - 1)) != 0) {
- return 0;
- }
-
- reg = addr >> s->it_shift;
- return read_register(s, reg);
-}
-
-static uint32_t dp8393x_readb(void *opaque, hwaddr addr)
-{
- uint16_t v = dp8393x_readw(opaque, addr & ~0x1);
- return (v >> (8 * (addr & 0x1))) & 0xff;
-}
-
-static uint32_t dp8393x_readl(void *opaque, hwaddr addr)
-{
- uint32_t v;
- v = dp8393x_readw(opaque, addr);
- v |= dp8393x_readw(opaque, addr + 2) << 16;
- return v;
-}
-
-static void dp8393x_writew(void *opaque, hwaddr addr, uint32_t val)
-{
- dp8393xState *s = opaque;
- int reg;
-
- if ((addr & ((1 << s->it_shift) - 1)) != 0) {
- return;
- }
-
- reg = addr >> s->it_shift;
-
- write_register(s, reg, (uint16_t)val);
-}
-
-static void dp8393x_writeb(void *opaque, hwaddr addr, uint32_t val)
-{
- uint16_t old_val = dp8393x_readw(opaque, addr & ~0x1);
-
- switch (addr & 3) {
- case 0:
- val = val | (old_val & 0xff00);
- break;
- case 1:
- val = (val << 8) | (old_val & 0x00ff);
- break;
- }
- dp8393x_writew(opaque, addr & ~0x1, val);
-}
-
-static void dp8393x_writel(void *opaque, hwaddr addr, uint32_t val)
-{
- dp8393x_writew(opaque, addr, val & 0xffff);
- dp8393x_writew(opaque, addr + 2, (val >> 16) & 0xffff);
-}
-
-static const MemoryRegionOps dp8393x_ops = {
- .old_mmio = {
- .read = { dp8393x_readb, dp8393x_readw, dp8393x_readl, },
- .write = { dp8393x_writeb, dp8393x_writew, dp8393x_writel, },
- },
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
-static int nic_can_receive(NetClientState *nc)
+static int dp8393x_can_receive(NetClientState *nc)
{
dp8393xState *s = qemu_get_nic_opaque(nc);
@@ -685,7 +629,8 @@ static int nic_can_receive(NetClientState *nc)
return 1;
}
-static int receive_filter(dp8393xState *s, const uint8_t * buf, int size)
+static int dp8393x_receive_filter(dp8393xState *s, const uint8_t * buf,
+ int size)
{
static const uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
int i;
@@ -723,7 +668,8 @@ static int receive_filter(dp8393xState *s, const uint8_t * buf, int size)
return -1;
}
-static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size)
+static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
+ size_t size)
{
dp8393xState *s = qemu_get_nic_opaque(nc);
uint16_t data[10];
@@ -737,7 +683,7 @@ static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size)
s->regs[SONIC_RCR] &= ~(SONIC_RCR_PRX | SONIC_RCR_LBK | SONIC_RCR_FAER |
SONIC_RCR_CRCR | SONIC_RCR_LPKT | SONIC_RCR_BC | SONIC_RCR_MC);
- packet_type = receive_filter(s, buf, size);
+ packet_type = dp8393x_receive_filter(s, buf, size);
if (packet_type < 0) {
DPRINTF("packet not for netcard\n");
return -1;
@@ -750,7 +696,8 @@ static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size)
/* Are we still in resource exhaustion? */
size = sizeof(uint16_t) * 1 * width;
address = ((s->regs[SONIC_URDA] << 16) | s->regs[SONIC_CRDA]) + sizeof(uint16_t) * 5 * width;
- s->memory_rw(s->mem_opaque, address, (uint8_t*)data, size, 0);
+ address_space_rw(&s->as, address, MEMTXATTRS_UNSPECIFIED,
+ (uint8_t *)data, size, 0);
if (data[0 * width] & 0x1) {
/* Still EOL ; stop reception */
return -1;
@@ -764,18 +711,16 @@ static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size)
s->regs[SONIC_TRBA0] = s->regs[SONIC_CRBA0];
/* Calculate the ethernet checksum */
-#ifdef SONIC_CALCULATE_RXCRC
checksum = cpu_to_le32(crc32(0, buf, rx_len));
-#else
- checksum = 0;
-#endif
/* Put packet into RBA */
DPRINTF("Receive packet at %08x\n", (s->regs[SONIC_CRBA1] << 16) | s->regs[SONIC_CRBA0]);
address = (s->regs[SONIC_CRBA1] << 16) | s->regs[SONIC_CRBA0];
- s->memory_rw(s->mem_opaque, address, (uint8_t*)buf, rx_len, 1);
+ address_space_rw(&s->as, address,
+ MEMTXATTRS_UNSPECIFIED, (uint8_t *)buf, rx_len, 1);
address += rx_len;
- s->memory_rw(s->mem_opaque, address, (uint8_t*)&checksum, 4, 1);
+ address_space_rw(&s->as, address,
+ MEMTXATTRS_UNSPECIFIED, (uint8_t *)&checksum, 4, 1);
rx_len += 4;
s->regs[SONIC_CRBA1] = address >> 16;
s->regs[SONIC_CRBA0] = address & 0xffff;
@@ -803,29 +748,30 @@ static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size)
data[3 * width] = s->regs[SONIC_TRBA1]; /* pkt_ptr1 */
data[4 * width] = s->regs[SONIC_RSC]; /* seq_no */
size = sizeof(uint16_t) * 5 * width;
- s->memory_rw(s->mem_opaque, (s->regs[SONIC_URDA] << 16) | s->regs[SONIC_CRDA], (uint8_t *)data, size, 1);
+ address_space_rw(&s->as, (s->regs[SONIC_URDA] << 16) | s->regs[SONIC_CRDA],
+ MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 1);
/* Move to next descriptor */
size = sizeof(uint16_t) * width;
- s->memory_rw(s->mem_opaque,
+ address_space_rw(&s->as,
((s->regs[SONIC_URDA] << 16) | s->regs[SONIC_CRDA]) + sizeof(uint16_t) * 5 * width,
- (uint8_t *)data, size, 0);
+ MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0);
s->regs[SONIC_LLFA] = data[0 * width];
if (s->regs[SONIC_LLFA] & 0x1) {
/* EOL detected */
s->regs[SONIC_ISR] |= SONIC_ISR_RDE;
} else {
data[0 * width] = 0; /* in_use */
- s->memory_rw(s->mem_opaque,
+ address_space_rw(&s->as,
((s->regs[SONIC_URDA] << 16) | s->regs[SONIC_CRDA]) + sizeof(uint16_t) * 6 * width,
- (uint8_t *)data, size, 1);
+ MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, sizeof(uint16_t), 1);
s->regs[SONIC_CRDA] = s->regs[SONIC_LLFA];
s->regs[SONIC_ISR] |= SONIC_ISR_PKTRX;
s->regs[SONIC_RSC] = (s->regs[SONIC_RSC] & 0xff00) | (((s->regs[SONIC_RSC] & 0x00ff) + 1) & 0x00ff);
if (s->regs[SONIC_RCR] & SONIC_RCR_LPKT) {
/* Read next RRA */
- do_read_rra(s);
+ dp8393x_do_read_rra(s);
}
}
@@ -835,11 +781,12 @@ static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size)
return size;
}
-static void nic_reset(void *opaque)
+static void dp8393x_reset(DeviceState *dev)
{
- dp8393xState *s = opaque;
+ dp8393xState *s = DP8393X(dev);
timer_del(s->watchdog);
+ memset(s->regs, 0, sizeof(s->regs));
s->regs[SONIC_CR] = SONIC_CR_RST | SONIC_CR_STP | SONIC_CR_RXDIS;
s->regs[SONIC_DCR] &= ~(SONIC_DCR_EXBUS | SONIC_DCR_LBR);
s->regs[SONIC_RCR] &= ~(SONIC_RCR_LB0 | SONIC_RCR_LB1 | SONIC_RCR_BRD | SONIC_RCR_RNT);
@@ -862,39 +809,91 @@ static void nic_reset(void *opaque)
static NetClientInfo net_dp83932_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState),
- .can_receive = nic_can_receive,
- .receive = nic_receive,
+ .can_receive = dp8393x_can_receive,
+ .receive = dp8393x_receive,
};
-void dp83932_init(NICInfo *nd, hwaddr base, int it_shift,
- MemoryRegion *address_space,
- qemu_irq irq, void* mem_opaque,
- void (*memory_rw)(void *opaque, hwaddr addr, uint8_t *buf, int len, int is_write))
+static void dp8393x_instance_init(Object *obj)
{
- dp8393xState *s;
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ dp8393xState *s = DP8393X(obj);
+
+ sysbus_init_mmio(sbd, &s->mmio);
+ sysbus_init_mmio(sbd, &s->prom);
+ sysbus_init_irq(sbd, &s->irq);
+}
- qemu_check_nic_model(nd, "dp83932");
+static void dp8393x_realize(DeviceState *dev, Error **errp)
+{
+ dp8393xState *s = DP8393X(dev);
+ int i, checksum;
+ uint8_t *prom;
- s = g_malloc0(sizeof(dp8393xState));
+ address_space_init(&s->as, s->dma_mr, "dp8393x");
+ memory_region_init_io(&s->mmio, OBJECT(dev), &dp8393x_ops, s,
+ "dp8393x-regs", 0x40 << s->it_shift);
+
+ s->nic = qemu_new_nic(&net_dp83932_info, &s->conf,
+ object_get_typename(OBJECT(dev)), dev->id, s);
+ qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
- s->address_space = address_space;
- s->mem_opaque = mem_opaque;
- s->memory_rw = memory_rw;
- s->it_shift = it_shift;
- s->irq = irq;
s->watchdog = timer_new_ns(QEMU_CLOCK_VIRTUAL, dp8393x_watchdog, s);
s->regs[SONIC_SR] = 0x0004; /* only revision recognized by Linux */
- s->conf.macaddr = nd->macaddr;
- s->conf.peers.ncs[0] = nd->netdev;
+ memory_region_init_rom_device(&s->prom, OBJECT(dev), NULL, NULL,
+ "dp8393x-prom", SONIC_PROM_SIZE, NULL);
+ prom = memory_region_get_ram_ptr(&s->prom);
+ checksum = 0;
+ for (i = 0; i < 6; i++) {
+ prom[i] = s->conf.macaddr.a[i];
+ checksum += prom[i];
+ if (checksum > 0xff) {
+ checksum = (checksum + 1) & 0xff;
+ }
+ }
+ prom[7] = 0xff - checksum;
+}
- s->nic = qemu_new_nic(&net_dp83932_info, &s->conf, nd->model, nd->name, s);
+static const VMStateDescription vmstate_dp8393x = {
+ .name = "dp8393x",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .fields = (VMStateField []) {
+ VMSTATE_BUFFER_UNSAFE(cam, dp8393xState, 0, 16 * 6),
+ VMSTATE_UINT16_ARRAY(regs, dp8393xState, 0x40),
+ VMSTATE_END_OF_LIST()
+ }
+};
- qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
- qemu_register_reset(nic_reset, s);
- nic_reset(s);
+static Property dp8393x_properties[] = {
+ DEFINE_NIC_PROPERTIES(dp8393xState, conf),
+ DEFINE_PROP_PTR("dma_mr", dp8393xState, dma_mr),
+ DEFINE_PROP_UINT8("it_shift", dp8393xState, it_shift, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void dp8393x_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
- memory_region_init_io(&s->mmio, NULL, &dp8393x_ops, s,
- "dp8393x", 0x40 << it_shift);
- memory_region_add_subregion(address_space, base, &s->mmio);
+ set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
+ dc->realize = dp8393x_realize;
+ dc->reset = dp8393x_reset;
+ dc->vmsd = &vmstate_dp8393x;
+ dc->props = dp8393x_properties;
}
+
+static const TypeInfo dp8393x_info = {
+ .name = TYPE_DP8393X,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(dp8393xState),
+ .instance_init = dp8393x_instance_init,
+ .class_init = dp8393x_class_init,
+};
+
+static void dp8393x_register_types(void)
+{
+ type_register_static(&dp8393x_info);
+}
+
+type_init(dp8393x_register_types)
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index 091d61acc3..bab8e2abfb 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -1370,6 +1370,7 @@ static const VMStateDescription vmstate_e1000_mit_state = {
.name = "e1000/mit_state",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = e1000_mit_state_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT32(mac_reg[RDTR], E1000State),
VMSTATE_UINT32(mac_reg[RADV], E1000State),
@@ -1457,13 +1458,9 @@ static const VMStateDescription vmstate_e1000 = {
VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, VFTA, 128),
VMSTATE_END_OF_LIST()
},
- .subsections = (VMStateSubsection[]) {
- {
- .vmsd = &vmstate_e1000_mit_state,
- .needed = e1000_mit_state_needed,
- }, {
- /* empty */
- }
+ .subsections = (const VMStateDescription*[]) {
+ &vmstate_e1000_mit_state,
+ NULL
}
};
diff --git a/hw/net/rocker/qmp-norocker.c b/hw/net/rocker/qmp-norocker.c
new file mode 100644
index 0000000000..f253747361
--- /dev/null
+++ b/hw/net/rocker/qmp-norocker.c
@@ -0,0 +1,50 @@
+/*
+ * QMP Target options - Commands handled based on a target config
+ * versus a host config
+ *
+ * Copyright (c) 2015 David Ahern <dsahern@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include "qemu-common.h"
+#include "qmp-commands.h"
+#include "qapi/qmp/qerror.h"
+
+RockerSwitch *qmp_query_rocker(const char *name, Error **errp)
+{
+ error_set(errp, QERR_FEATURE_DISABLED, "rocker");
+ return NULL;
+};
+
+RockerPortList *qmp_query_rocker_ports(const char *name, Error **errp)
+{
+ error_set(errp, QERR_FEATURE_DISABLED, "rocker");
+ return NULL;
+};
+
+RockerOfDpaFlowList *qmp_query_rocker_of_dpa_flows(const char *name,
+ bool has_tbl_id,
+ uint32_t tbl_id,
+ Error **errp)
+{
+ error_set(errp, QERR_FEATURE_DISABLED, "rocker");
+ return NULL;
+};
+
+RockerOfDpaGroupList *qmp_query_rocker_of_dpa_groups(const char *name,
+ bool has_type,
+ uint8_t type,
+ Error **errp)
+{
+ error_set(errp, QERR_FEATURE_DISABLED, "rocker");
+ return NULL;
+};
diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c
index 55b6c46157..4d25842509 100644
--- a/hw/net/rocker/rocker.c
+++ b/hw/net/rocker/rocker.c
@@ -94,6 +94,51 @@ World *rocker_get_world(Rocker *r, enum rocker_world_type type)
return NULL;
}
+RockerSwitch *qmp_query_rocker(const char *name, Error **errp)
+{
+ RockerSwitch *rocker = g_malloc0(sizeof(*rocker));
+ Rocker *r;
+
+ r = rocker_find(name);
+ if (!r) {
+ error_set(errp, ERROR_CLASS_GENERIC_ERROR,
+ "rocker %s not found", name);
+ return NULL;
+ }
+
+ rocker->name = g_strdup(r->name);
+ rocker->id = r->switch_id;
+ rocker->ports = r->fp_ports;
+
+ return rocker;
+}
+
+RockerPortList *qmp_query_rocker_ports(const char *name, Error **errp)
+{
+ RockerPortList *list = NULL;
+ Rocker *r;
+ int i;
+
+ r = rocker_find(name);
+ if (!r) {
+ error_set(errp, ERROR_CLASS_GENERIC_ERROR,
+ "rocker %s not found", name);
+ return NULL;
+ }
+
+ for (i = r->fp_ports - 1; i >= 0; i--) {
+ RockerPortList *info = g_malloc0(sizeof(*info));
+ info->value = g_malloc0(sizeof(*info->value));
+ struct fp_port *port = r->fp_port[i];
+
+ fp_port_get_info(port, info);
+ info->next = list;
+ list = info;
+ }
+
+ return list;
+}
+
uint32_t rocker_fp_ports(Rocker *r)
{
return r->fp_ports;
@@ -238,6 +283,7 @@ static int cmd_get_port_settings(Rocker *r,
uint8_t duplex;
uint8_t autoneg;
uint8_t learning;
+ char *phys_name;
MACAddr macaddr;
enum rocker_world_type mode;
size_t tlv_size;
@@ -265,6 +311,7 @@ static int cmd_get_port_settings(Rocker *r,
fp_port_get_macaddr(fp_port, &macaddr);
mode = world_type(fp_port_get_world(fp_port));
learning = fp_port_get_learning(fp_port);
+ phys_name = fp_port_get_name(fp_port);
tlv_size = rocker_tlv_total_size(0) + /* nest */
rocker_tlv_total_size(sizeof(uint32_t)) + /* pport */
@@ -273,7 +320,8 @@ static int cmd_get_port_settings(Rocker *r,
rocker_tlv_total_size(sizeof(uint8_t)) + /* autoneg */
rocker_tlv_total_size(sizeof(macaddr.a)) + /* macaddr */
rocker_tlv_total_size(sizeof(uint8_t)) + /* mode */
- rocker_tlv_total_size(sizeof(uint8_t)); /* learning */
+ rocker_tlv_total_size(sizeof(uint8_t)) + /* learning */
+ rocker_tlv_total_size(strlen(phys_name));
if (tlv_size > desc_buf_size(info)) {
return -ROCKER_EMSGSIZE;
@@ -290,6 +338,8 @@ static int cmd_get_port_settings(Rocker *r,
rocker_tlv_put_u8(buf, &pos, ROCKER_TLV_CMD_PORT_SETTINGS_MODE, mode);
rocker_tlv_put_u8(buf, &pos, ROCKER_TLV_CMD_PORT_SETTINGS_LEARNING,
learning);
+ rocker_tlv_put(buf, &pos, ROCKER_TLV_CMD_PORT_SETTINGS_PHYS_NAME,
+ strlen(phys_name), phys_name);
rocker_tlv_nest_end(buf, &pos, nest);
return desc_set_buf(info, tlv_size);
@@ -1277,6 +1327,22 @@ static int pci_rocker_init(PCIDevice *dev)
goto err_duplicate;
}
+ /* Rocker name is passed in port name requests to OS with the intention
+ * that the name is used in interface names. Limit the length of the
+ * rocker name to avoid naming problems in the OS. Also, adding the
+ * port number as p# and unganged breakout b#, where # is at most 2
+ * digits, so leave room for it too (-1 for string terminator, -3 for
+ * p# and -3 for b#)
+ */
+#define ROCKER_IFNAMSIZ 16
+#define MAX_ROCKER_NAME_LEN (ROCKER_IFNAMSIZ - 1 - 3 - 3)
+ if (strlen(r->name) > MAX_ROCKER_NAME_LEN) {
+ fprintf(stderr,
+ "rocker: name too long; please shorten to at most %d chars\n",
+ MAX_ROCKER_NAME_LEN);
+ return -EINVAL;
+ }
+
if (memcmp(&r->fp_start_macaddr, &zero, sizeof(zero)) == 0) {
memcpy(&r->fp_start_macaddr, &dflt, sizeof(dflt));
r->fp_start_macaddr.a[4] += (sw_index++);
diff --git a/hw/net/rocker/rocker_fp.c b/hw/net/rocker/rocker_fp.c
index 2f1e3b348a..d8d934c396 100644
--- a/hw/net/rocker/rocker_fp.c
+++ b/hw/net/rocker/rocker_fp.c
@@ -41,11 +41,26 @@ struct fp_port {
NICConf conf;
};
+char *fp_port_get_name(FpPort *port)
+{
+ return port->name;
+}
+
bool fp_port_get_link_up(FpPort *port)
{
return !qemu_get_queue(port->nic)->link_down;
}
+void fp_port_get_info(FpPort *port, RockerPortList *info)
+{
+ info->value->name = g_strdup(port->name);
+ info->value->enabled = port->enabled;
+ info->value->link_up = fp_port_get_link_up(port);
+ info->value->speed = port->speed;
+ info->value->duplex = port->duplex;
+ info->value->autoneg = port->autoneg;
+}
+
void fp_port_get_macaddr(FpPort *port, MACAddr *macaddr)
{
memcpy(macaddr->a, port->conf.macaddr.a, sizeof(macaddr->a));
@@ -173,8 +188,19 @@ bool fp_port_enabled(FpPort *port)
return port->enabled;
}
+static void fp_port_set_link(FpPort *port, bool up)
+{
+ NetClientState *nc = qemu_get_queue(port->nic);
+
+ if (up == nc->link_down) {
+ nc->link_down = !up;
+ nc->info->link_status_changed(nc);
+ }
+}
+
void fp_port_enable(FpPort *port)
{
+ fp_port_set_link(port, true);
port->enabled = true;
DPRINTF("port %d enabled\n", port->index);
}
@@ -182,6 +208,7 @@ void fp_port_enable(FpPort *port)
void fp_port_disable(FpPort *port)
{
port->enabled = false;
+ fp_port_set_link(port, false);
DPRINTF("port %d disabled\n", port->index);
}
@@ -201,7 +228,7 @@ FpPort *fp_port_alloc(Rocker *r, char *sw_name,
/* front-panel switch port names are 1-based */
- port->name = g_strdup_printf("%s.%d", sw_name, port->pport);
+ port->name = g_strdup_printf("%sp%d", sw_name, port->pport);
memcpy(port->conf.macaddr.a, start_mac, sizeof(port->conf.macaddr.a));
port->conf.macaddr.a[5] += index;
diff --git a/hw/net/rocker/rocker_fp.h b/hw/net/rocker/rocker_fp.h
index a5f28f120d..ab80fd833c 100644
--- a/hw/net/rocker/rocker_fp.h
+++ b/hw/net/rocker/rocker_fp.h
@@ -26,7 +26,9 @@ typedef struct fp_port FpPort;
int fp_port_eg(FpPort *port, const struct iovec *iov, int iovcnt);
+char *fp_port_get_name(FpPort *port);
bool fp_port_get_link_up(FpPort *port);
+void fp_port_get_info(FpPort *port, RockerPortList *info);
void fp_port_get_macaddr(FpPort *port, MACAddr *macaddr);
void fp_port_set_macaddr(FpPort *port, MACAddr *macaddr);
uint8_t fp_port_get_learning(FpPort *port);
diff --git a/hw/net/rocker/rocker_hw.h b/hw/net/rocker/rocker_hw.h
index c9c85a75bd..fe639badd4 100644
--- a/hw/net/rocker/rocker_hw.h
+++ b/hw/net/rocker/rocker_hw.h
@@ -179,6 +179,7 @@ enum {
ROCKER_TLV_CMD_PORT_SETTINGS_MACADDR, /* binary */
ROCKER_TLV_CMD_PORT_SETTINGS_MODE, /* u8 */
ROCKER_TLV_CMD_PORT_SETTINGS_LEARNING, /* u8 */
+ ROCKER_TLV_CMD_PORT_SETTINGS_PHYS_NAME, /* binary */
__ROCKER_TLV_CMD_PORT_SETTINGS_MAX,
ROCKER_TLV_CMD_PORT_SETTINGS_MAX = __ROCKER_TLV_CMD_PORT_SETTINGS_MAX - 1,
diff --git a/hw/net/rocker/rocker_of_dpa.c b/hw/net/rocker/rocker_of_dpa.c
index 1bcb7af5ef..b25a17d6d7 100644
--- a/hw/net/rocker/rocker_of_dpa.c
+++ b/hw/net/rocker/rocker_of_dpa.c
@@ -2302,6 +2302,318 @@ static void of_dpa_uninit(World *world)
g_hash_table_destroy(of_dpa->flow_tbl);
}
+struct of_dpa_flow_fill_context {
+ RockerOfDpaFlowList *list;
+ uint32_t tbl_id;
+};
+
+static void of_dpa_flow_fill(void *cookie, void *value, void *user_data)
+{
+ struct of_dpa_flow *flow = value;
+ struct of_dpa_flow_key *key = &flow->key;
+ struct of_dpa_flow_key *mask = &flow->mask;
+ struct of_dpa_flow_fill_context *flow_context = user_data;
+ RockerOfDpaFlowList *new;
+ RockerOfDpaFlow *nflow;
+ RockerOfDpaFlowKey *nkey;
+ RockerOfDpaFlowMask *nmask;
+ RockerOfDpaFlowAction *naction;
+
+ if (flow_context->tbl_id != -1 &&
+ flow_context->tbl_id != key->tbl_id) {
+ return;
+ }
+
+ new = g_malloc0(sizeof(*new));
+ nflow = new->value = g_malloc0(sizeof(*nflow));
+ nkey = nflow->key = g_malloc0(sizeof(*nkey));
+ nmask = nflow->mask = g_malloc0(sizeof(*nmask));
+ naction = nflow->action = g_malloc0(sizeof(*naction));
+
+ nflow->cookie = flow->cookie;
+ nflow->hits = flow->stats.hits;
+ nkey->priority = flow->priority;
+ nkey->tbl_id = key->tbl_id;
+
+ if (key->in_pport || mask->in_pport) {
+ nkey->has_in_pport = true;
+ nkey->in_pport = key->in_pport;
+ }
+
+ if (nkey->has_in_pport && mask->in_pport != 0xffffffff) {
+ nmask->has_in_pport = true;
+ nmask->in_pport = mask->in_pport;
+ }
+
+ if (key->eth.vlan_id || mask->eth.vlan_id) {
+ nkey->has_vlan_id = true;
+ nkey->vlan_id = ntohs(key->eth.vlan_id);
+ }
+
+ if (nkey->has_vlan_id && mask->eth.vlan_id != 0xffff) {
+ nmask->has_vlan_id = true;
+ nmask->vlan_id = ntohs(mask->eth.vlan_id);
+ }
+
+ if (key->tunnel_id || mask->tunnel_id) {
+ nkey->has_tunnel_id = true;
+ nkey->tunnel_id = key->tunnel_id;
+ }
+
+ if (nkey->has_tunnel_id && mask->tunnel_id != 0xffffffff) {
+ nmask->has_tunnel_id = true;
+ nmask->tunnel_id = mask->tunnel_id;
+ }
+
+ if (memcmp(key->eth.src.a, zero_mac.a, ETH_ALEN) ||
+ memcmp(mask->eth.src.a, zero_mac.a, ETH_ALEN)) {
+ nkey->has_eth_src = true;
+ nkey->eth_src = qemu_mac_strdup_printf(key->eth.src.a);
+ }
+
+ if (nkey->has_eth_src && memcmp(mask->eth.src.a, ff_mac.a, ETH_ALEN)) {
+ nmask->has_eth_src = true;
+ nmask->eth_src = qemu_mac_strdup_printf(mask->eth.src.a);
+ }
+
+ if (memcmp(key->eth.dst.a, zero_mac.a, ETH_ALEN) ||
+ memcmp(mask->eth.dst.a, zero_mac.a, ETH_ALEN)) {
+ nkey->has_eth_dst = true;
+ nkey->eth_dst = qemu_mac_strdup_printf(key->eth.dst.a);
+ }
+
+ if (nkey->has_eth_dst && memcmp(mask->eth.dst.a, ff_mac.a, ETH_ALEN)) {
+ nmask->has_eth_dst = true;
+ nmask->eth_dst = qemu_mac_strdup_printf(mask->eth.dst.a);
+ }
+
+ if (key->eth.type) {
+
+ nkey->has_eth_type = true;
+ nkey->eth_type = ntohs(key->eth.type);
+
+ switch (ntohs(key->eth.type)) {
+ case 0x0800:
+ case 0x86dd:
+ if (key->ip.proto || mask->ip.proto) {
+ nkey->has_ip_proto = true;
+ nkey->ip_proto = key->ip.proto;
+ }
+ if (nkey->has_ip_proto && mask->ip.proto != 0xff) {
+ nmask->has_ip_proto = true;
+ nmask->ip_proto = mask->ip.proto;
+ }
+ if (key->ip.tos || mask->ip.tos) {
+ nkey->has_ip_tos = true;
+ nkey->ip_tos = key->ip.tos;
+ }
+ if (nkey->has_ip_tos && mask->ip.tos != 0xff) {
+ nmask->has_ip_tos = true;
+ nmask->ip_tos = mask->ip.tos;
+ }
+ break;
+ }
+
+ switch (ntohs(key->eth.type)) {
+ case 0x0800:
+ if (key->ipv4.addr.dst || mask->ipv4.addr.dst) {
+ char *dst = inet_ntoa(*(struct in_addr *)&key->ipv4.addr.dst);
+ int dst_len = of_dpa_mask2prefix(mask->ipv4.addr.dst);
+ nkey->has_ip_dst = true;
+ nkey->ip_dst = g_strdup_printf("%s/%d", dst, dst_len);
+ }
+ break;
+ }
+ }
+
+ if (flow->action.goto_tbl) {
+ naction->has_goto_tbl = true;
+ naction->goto_tbl = flow->action.goto_tbl;
+ }
+
+ if (flow->action.write.group_id) {
+ naction->has_group_id = true;
+ naction->group_id = flow->action.write.group_id;
+ }
+
+ if (flow->action.apply.new_vlan_id) {
+ naction->has_new_vlan_id = true;
+ naction->new_vlan_id = flow->action.apply.new_vlan_id;
+ }
+
+ new->next = flow_context->list;
+ flow_context->list = new;
+}
+
+RockerOfDpaFlowList *qmp_query_rocker_of_dpa_flows(const char *name,
+ bool has_tbl_id,
+ uint32_t tbl_id,
+ Error **errp)
+{
+ struct rocker *r;
+ struct world *w;
+ struct of_dpa *of_dpa;
+ struct of_dpa_flow_fill_context fill_context = {
+ .list = NULL,
+ .tbl_id = tbl_id,
+ };
+
+ r = rocker_find(name);
+ if (!r) {
+ error_set(errp, ERROR_CLASS_GENERIC_ERROR,
+ "rocker %s not found", name);
+ return NULL;
+ }
+
+ w = rocker_get_world(r, ROCKER_WORLD_TYPE_OF_DPA);
+ if (!w) {
+ error_set(errp, ERROR_CLASS_GENERIC_ERROR,
+ "rocker %s doesn't have OF-DPA world", name);
+ return NULL;
+ }
+
+ of_dpa = world_private(w);
+
+ g_hash_table_foreach(of_dpa->flow_tbl, of_dpa_flow_fill, &fill_context);
+
+ return fill_context.list;
+}
+
+struct of_dpa_group_fill_context {
+ RockerOfDpaGroupList *list;
+ uint8_t type;
+};
+
+static void of_dpa_group_fill(void *key, void *value, void *user_data)
+{
+ struct of_dpa_group *group = value;
+ struct of_dpa_group_fill_context *flow_context = user_data;
+ RockerOfDpaGroupList *new;
+ RockerOfDpaGroup *ngroup;
+ struct uint32List *id;
+ int i;
+
+ if (flow_context->type != 9 &&
+ flow_context->type != ROCKER_GROUP_TYPE_GET(group->id)) {
+ return;
+ }
+
+ new = g_malloc0(sizeof(*new));
+ ngroup = new->value = g_malloc0(sizeof(*ngroup));
+
+ ngroup->id = group->id;
+
+ ngroup->type = ROCKER_GROUP_TYPE_GET(group->id);
+
+ switch (ngroup->type) {
+ case ROCKER_OF_DPA_GROUP_TYPE_L2_INTERFACE:
+ ngroup->has_vlan_id = true;
+ ngroup->vlan_id = ROCKER_GROUP_VLAN_GET(group->id);
+ ngroup->has_pport = true;
+ ngroup->pport = ROCKER_GROUP_PORT_GET(group->id);
+ ngroup->has_out_pport = true;
+ ngroup->out_pport = group->l2_interface.out_pport;
+ ngroup->has_pop_vlan = true;
+ ngroup->pop_vlan = group->l2_interface.pop_vlan;
+ break;
+ case ROCKER_OF_DPA_GROUP_TYPE_L2_REWRITE:
+ ngroup->has_index = true;
+ ngroup->index = ROCKER_GROUP_INDEX_LONG_GET(group->id);
+ ngroup->has_group_id = true;
+ ngroup->group_id = group->l2_rewrite.group_id;
+ if (group->l2_rewrite.vlan_id) {
+ ngroup->has_set_vlan_id = true;
+ ngroup->set_vlan_id = ntohs(group->l2_rewrite.vlan_id);
+ }
+ break;
+ if (memcmp(group->l2_rewrite.src_mac.a, zero_mac.a, ETH_ALEN)) {
+ ngroup->has_set_eth_src = true;
+ ngroup->set_eth_src =
+ qemu_mac_strdup_printf(group->l2_rewrite.src_mac.a);
+ }
+ if (memcmp(group->l2_rewrite.dst_mac.a, zero_mac.a, ETH_ALEN)) {
+ ngroup->has_set_eth_dst = true;
+ ngroup->set_eth_dst =
+ qemu_mac_strdup_printf(group->l2_rewrite.dst_mac.a);
+ }
+ case ROCKER_OF_DPA_GROUP_TYPE_L2_FLOOD:
+ case ROCKER_OF_DPA_GROUP_TYPE_L2_MCAST:
+ ngroup->has_vlan_id = true;
+ ngroup->vlan_id = ROCKER_GROUP_VLAN_GET(group->id);
+ ngroup->has_index = true;
+ ngroup->index = ROCKER_GROUP_INDEX_GET(group->id);
+ for (i = 0; i < group->l2_flood.group_count; i++) {
+ ngroup->has_group_ids = true;
+ id = g_malloc0(sizeof(*id));
+ id->value = group->l2_flood.group_ids[i];
+ id->next = ngroup->group_ids;
+ ngroup->group_ids = id;
+ }
+ break;
+ case ROCKER_OF_DPA_GROUP_TYPE_L3_UCAST:
+ ngroup->has_index = true;
+ ngroup->index = ROCKER_GROUP_INDEX_LONG_GET(group->id);
+ ngroup->has_group_id = true;
+ ngroup->group_id = group->l3_unicast.group_id;
+ if (group->l3_unicast.vlan_id) {
+ ngroup->has_set_vlan_id = true;
+ ngroup->set_vlan_id = ntohs(group->l3_unicast.vlan_id);
+ }
+ if (memcmp(group->l3_unicast.src_mac.a, zero_mac.a, ETH_ALEN)) {
+ ngroup->has_set_eth_src = true;
+ ngroup->set_eth_src =
+ qemu_mac_strdup_printf(group->l3_unicast.src_mac.a);
+ }
+ if (memcmp(group->l3_unicast.dst_mac.a, zero_mac.a, ETH_ALEN)) {
+ ngroup->has_set_eth_dst = true;
+ ngroup->set_eth_dst =
+ qemu_mac_strdup_printf(group->l3_unicast.dst_mac.a);
+ }
+ if (group->l3_unicast.ttl_check) {
+ ngroup->has_ttl_check = true;
+ ngroup->ttl_check = group->l3_unicast.ttl_check;
+ }
+ break;
+ }
+
+ new->next = flow_context->list;
+ flow_context->list = new;
+}
+
+RockerOfDpaGroupList *qmp_query_rocker_of_dpa_groups(const char *name,
+ bool has_type,
+ uint8_t type,
+ Error **errp)
+{
+ struct rocker *r;
+ struct world *w;
+ struct of_dpa *of_dpa;
+ struct of_dpa_group_fill_context fill_context = {
+ .list = NULL,
+ .type = type,
+ };
+
+ r = rocker_find(name);
+ if (!r) {
+ error_set(errp, ERROR_CLASS_GENERIC_ERROR,
+ "rocker %s not found", name);
+ return NULL;
+ }
+
+ w = rocker_get_world(r, ROCKER_WORLD_TYPE_OF_DPA);
+ if (!w) {
+ error_set(errp, ERROR_CLASS_GENERIC_ERROR,
+ "rocker %s doesn't have OF-DPA world", name);
+ return NULL;
+ }
+
+ of_dpa = world_private(w);
+
+ g_hash_table_foreach(of_dpa->group_tbl, of_dpa_group_fill, &fill_context);
+
+ return fill_context.list;
+}
+
static WorldOps of_dpa_ops = {
.init = of_dpa_init,
.uninit = of_dpa_uninit,
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
index f868108dfe..e0db4727ae 100644
--- a/hw/net/rtl8139.c
+++ b/hw/net/rtl8139.c
@@ -3240,6 +3240,7 @@ static const VMStateDescription vmstate_rtl8139_hotplug_ready ={
.name = "rtl8139/hotplug_ready",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = rtl8139_hotplug_ready_needed,
.fields = (VMStateField[]) {
VMSTATE_END_OF_LIST()
}
@@ -3335,13 +3336,9 @@ static const VMStateDescription vmstate_rtl8139 = {
VMSTATE_UINT32_V(cplus_enabled, RTL8139State, 4),
VMSTATE_END_OF_LIST()
},
- .subsections = (VMStateSubsection []) {
- {
- .vmsd = &vmstate_rtl8139_hotplug_ready,
- .needed = rtl8139_hotplug_ready_needed,
- }, {
- /* empty */
- }
+ .subsections = (const VMStateDescription*[]) {
+ &vmstate_rtl8139_hotplug_ready,
+ NULL
}
};
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index dfb328debd..8bcdf3ed77 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -2226,6 +2226,7 @@ static const VMStateDescription vmxstate_vmxnet3_mcast_list = {
.version_id = 1,
.minimum_version_id = 1,
.pre_load = vmxnet3_mcast_list_pre_load,
+ .needed = vmxnet3_mc_list_needed,
.fields = (VMStateField[]) {
VMSTATE_VBUFFER_UINT32(mcast_list, VMXNET3State, 0, NULL, 0,
mcast_list_buff_size),
@@ -2470,14 +2471,9 @@ static const VMStateDescription vmstate_vmxnet3 = {
VMSTATE_END_OF_LIST()
},
- .subsections = (VMStateSubsection[]) {
- {
- .vmsd = &vmxstate_vmxnet3_mcast_list,
- .needed = vmxnet3_mc_list_needed
- },
- {
- /* empty element. */
- }
+ .subsections = (const VMStateDescription*[]) {
+ &vmxstate_vmxnet3_mcast_list,
+ NULL
}
};
diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index f1712b86fe..ed2424c4cd 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -582,6 +582,7 @@ static const VMStateDescription vmstate_piix3_rcr = {
.name = "PIIX3/rcr",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = piix3_rcr_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT8(rcr, PIIX3State),
VMSTATE_END_OF_LIST()
@@ -600,12 +601,9 @@ static const VMStateDescription vmstate_piix3 = {
PIIX_NUM_PIRQS, 3),
VMSTATE_END_OF_LIST()
},
- .subsections = (VMStateSubsection[]) {
- {
- .vmsd = &vmstate_piix3_rcr,
- .needed = piix3_rcr_needed,
- },
- { 0 }
+ .subsections = (const VMStateDescription*[]) {
+ &vmstate_piix3_rcr,
+ NULL
}
};
diff --git a/hw/scsi/scsi-bus.c b/hw/scsi/scsi-bus.c
index bd2c0e4caa..f50b2f08af 100644
--- a/hw/scsi/scsi-bus.c
+++ b/hw/scsi/scsi-bus.c
@@ -1968,6 +1968,7 @@ static const VMStateDescription vmstate_scsi_sense_state = {
.name = "SCSIDevice/sense",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = scsi_sense_state_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT8_SUB_ARRAY(sense, SCSIDevice,
SCSI_SENSE_BUF_SIZE_OLD,
@@ -1998,13 +1999,9 @@ const VMStateDescription vmstate_scsi_device = {
},
VMSTATE_END_OF_LIST()
},
- .subsections = (VMStateSubsection []) {
- {
- .vmsd = &vmstate_scsi_sense_state,
- .needed = scsi_sense_state_needed,
- }, {
- /* empty */
- }
+ .subsections = (const VMStateDescription*[]) {
+ &vmstate_scsi_sense_state,
+ NULL
}
};
diff --git a/hw/sd/pxa2xx_mmci.c b/hw/sd/pxa2xx_mmci.c
index ac3ab39bea..d1fe6d58e8 100644
--- a/hw/sd/pxa2xx_mmci.c
+++ b/hw/sd/pxa2xx_mmci.c
@@ -48,7 +48,6 @@ struct PXA2xxMMCIState {
int resp_len;
int cmdreq;
- int ac_width;
};
#define MMC_STRPCL 0x00 /* MMC Clock Start/Stop register */
@@ -215,7 +214,7 @@ static void pxa2xx_mmci_wakequeues(PXA2xxMMCIState *s)
pxa2xx_mmci_fifo_update(s);
}
-static uint32_t pxa2xx_mmci_read(void *opaque, hwaddr offset)
+static uint64_t pxa2xx_mmci_read(void *opaque, hwaddr offset, unsigned size)
{
PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque;
uint32_t ret;
@@ -257,8 +256,8 @@ static uint32_t pxa2xx_mmci_read(void *opaque, hwaddr offset)
return 0;
case MMC_RXFIFO:
ret = 0;
- while (s->ac_width -- && s->rx_len) {
- ret |= s->rx_fifo[s->rx_start ++] << (s->ac_width << 3);
+ while (size-- && s->rx_len) {
+ ret |= s->rx_fifo[s->rx_start++] << (size << 3);
s->rx_start &= 0x1f;
s->rx_len --;
}
@@ -277,7 +276,7 @@ static uint32_t pxa2xx_mmci_read(void *opaque, hwaddr offset)
}
static void pxa2xx_mmci_write(void *opaque,
- hwaddr offset, uint32_t value)
+ hwaddr offset, uint64_t value, unsigned size)
{
PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque;
@@ -370,9 +369,9 @@ static void pxa2xx_mmci_write(void *opaque,
break;
case MMC_TXFIFO:
- while (s->ac_width -- && s->tx_len < 0x20)
+ while (size-- && s->tx_len < 0x20)
s->tx_fifo[(s->tx_start + (s->tx_len ++)) & 0x1f] =
- (value >> (s->ac_width << 3)) & 0xff;
+ (value >> (size << 3)) & 0xff;
s->intreq &= ~INT_TXFIFO_REQ;
pxa2xx_mmci_fifo_update(s);
break;
@@ -386,60 +385,9 @@ static void pxa2xx_mmci_write(void *opaque,
}
}
-static uint32_t pxa2xx_mmci_readb(void *opaque, hwaddr offset)
-{
- PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque;
- s->ac_width = 1;
- return pxa2xx_mmci_read(opaque, offset);
-}
-
-static uint32_t pxa2xx_mmci_readh(void *opaque, hwaddr offset)
-{
- PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque;
- s->ac_width = 2;
- return pxa2xx_mmci_read(opaque, offset);
-}
-
-static uint32_t pxa2xx_mmci_readw(void *opaque, hwaddr offset)
-{
- PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque;
- s->ac_width = 4;
- return pxa2xx_mmci_read(opaque, offset);
-}
-
-static void pxa2xx_mmci_writeb(void *opaque,
- hwaddr offset, uint32_t value)
-{
- PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque;
- s->ac_width = 1;
- pxa2xx_mmci_write(opaque, offset, value);
-}
-
-static void pxa2xx_mmci_writeh(void *opaque,
- hwaddr offset, uint32_t value)
-{
- PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque;
- s->ac_width = 2;
- pxa2xx_mmci_write(opaque, offset, value);
-}
-
-static void pxa2xx_mmci_writew(void *opaque,
- hwaddr offset, uint32_t value)
-{
- PXA2xxMMCIState *s = (PXA2xxMMCIState *) opaque;
- s->ac_width = 4;
- pxa2xx_mmci_write(opaque, offset, value);
-}
-
static const MemoryRegionOps pxa2xx_mmci_ops = {
- .old_mmio = {
- .read = { pxa2xx_mmci_readb,
- pxa2xx_mmci_readh,
- pxa2xx_mmci_readw, },
- .write = { pxa2xx_mmci_writeb,
- pxa2xx_mmci_writeh,
- pxa2xx_mmci_writew, },
- },
+ .read = pxa2xx_mmci_read,
+ .write = pxa2xx_mmci_write,
.endianness = DEVICE_NATIVE_ENDIAN,
};
diff --git a/hw/sh4/r2d.c b/hw/sh4/r2d.c
index 4221060308..5e22ed79b2 100644
--- a/hw/sh4/r2d.c
+++ b/hw/sh4/r2d.c
@@ -127,7 +127,7 @@ static void r2d_fpga_irq_set(void *opaque, int n, int level)
update_irl(fpga);
}
-static uint32_t r2d_fpga_read(void *opaque, hwaddr addr)
+static uint64_t r2d_fpga_read(void *opaque, hwaddr addr, unsigned int size)
{
r2d_fpga_t *s = opaque;
@@ -146,7 +146,7 @@ static uint32_t r2d_fpga_read(void *opaque, hwaddr addr)
}
static void
-r2d_fpga_write(void *opaque, hwaddr addr, uint32_t value)
+r2d_fpga_write(void *opaque, hwaddr addr, uint64_t value, unsigned int size)
{
r2d_fpga_t *s = opaque;
@@ -170,10 +170,10 @@ r2d_fpga_write(void *opaque, hwaddr addr, uint32_t value)
}
static const MemoryRegionOps r2d_fpga_ops = {
- .old_mmio = {
- .read = { r2d_fpga_read, r2d_fpga_read, NULL, },
- .write = { r2d_fpga_write, r2d_fpga_write, NULL, },
- },
+ .read = r2d_fpga_read,
+ .write = r2d_fpga_write,
+ .impl.min_access_size = 2,
+ .impl.max_access_size = 2,
.endianness = DEVICE_NATIVE_ENDIAN,
};
diff --git a/hw/timer/hpet.c b/hw/timer/hpet.c
index b6b8a2063d..b50071ef93 100644
--- a/hw/timer/hpet.c
+++ b/hw/timer/hpet.c
@@ -283,6 +283,7 @@ static const VMStateDescription vmstate_hpet_rtc_irq_level = {
.name = "hpet/rtc_irq_level",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = hpet_rtc_irq_level_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT8(rtc_irq_level, HPETState),
VMSTATE_END_OF_LIST()
@@ -322,13 +323,9 @@ static const VMStateDescription vmstate_hpet = {
vmstate_hpet_timer, HPETTimer),
VMSTATE_END_OF_LIST()
},
- .subsections = (VMStateSubsection[]) {
- {
- .vmsd = &vmstate_hpet_rtc_irq_level,
- .needed = hpet_rtc_irq_level_needed,
- }, {
- /* empty */
- }
+ .subsections = (const VMStateDescription*[]) {
+ &vmstate_hpet_rtc_irq_level,
+ NULL
}
};
diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c
index f2b77fa118..32048258c9 100644
--- a/hw/timer/mc146818rtc.c
+++ b/hw/timer/mc146818rtc.c
@@ -733,22 +733,23 @@ static int rtc_post_load(void *opaque, int version_id)
return 0;
}
+static bool rtc_irq_reinject_on_ack_count_needed(void *opaque)
+{
+ RTCState *s = (RTCState *)opaque;
+ return s->irq_reinject_on_ack_count != 0;
+}
+
static const VMStateDescription vmstate_rtc_irq_reinject_on_ack_count = {
.name = "mc146818rtc/irq_reinject_on_ack_count",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = rtc_irq_reinject_on_ack_count_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT16(irq_reinject_on_ack_count, RTCState),
VMSTATE_END_OF_LIST()
}
};
-static bool rtc_irq_reinject_on_ack_count_needed(void *opaque)
-{
- RTCState *s = (RTCState *)opaque;
- return s->irq_reinject_on_ack_count != 0;
-}
-
static const VMStateDescription vmstate_rtc = {
.name = "mc146818rtc",
.version_id = 3,
@@ -770,13 +771,9 @@ static const VMStateDescription vmstate_rtc = {
VMSTATE_UINT64_V(next_alarm_time, RTCState, 3),
VMSTATE_END_OF_LIST()
},
- .subsections = (VMStateSubsection[]) {
- {
- .vmsd = &vmstate_rtc_irq_reinject_on_ack_count,
- .needed = rtc_irq_reinject_on_ack_count_needed,
- }, {
- /* empty */
- }
+ .subsections = (const VMStateDescription*[]) {
+ &vmstate_rtc_irq_reinject_on_ack_count,
+ NULL
}
};
diff --git a/hw/usb/hcd-ohci.c b/hw/usb/hcd-ohci.c
index 1a22c9c0cb..7d65818064 100644
--- a/hw/usb/hcd-ohci.c
+++ b/hw/usb/hcd-ohci.c
@@ -2034,6 +2034,7 @@ static const VMStateDescription vmstate_ohci_eof_timer = {
.version_id = 1,
.minimum_version_id = 1,
.pre_load = ohci_eof_timer_pre_load,
+ .needed = ohci_eof_timer_needed,
.fields = (VMStateField[]) {
VMSTATE_TIMER_PTR(eof_timer, OHCIState),
VMSTATE_END_OF_LIST()
@@ -2081,13 +2082,9 @@ static const VMStateDescription vmstate_ohci_state = {
VMSTATE_BOOL(async_complete, OHCIState),
VMSTATE_END_OF_LIST()
},
- .subsections = (VMStateSubsection []) {
- {
- .vmsd = &vmstate_ohci_eof_timer,
- .needed = ohci_eof_timer_needed,
- } , {
- /* empty */
- }
+ .subsections = (const VMStateDescription*[]) {
+ &vmstate_ohci_eof_timer,
+ NULL
}
};
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 242a654583..6b4218c037 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -2257,40 +2257,42 @@ static const VMStateInfo usbredir_ep_bufpq_vmstate_info = {
/* For endp_data migration */
+static bool usbredir_bulk_receiving_needed(void *priv)
+{
+ struct endp_data *endp = priv;
+
+ return endp->bulk_receiving_started;
+}
+
static const VMStateDescription usbredir_bulk_receiving_vmstate = {
.name = "usb-redir-ep/bulk-receiving",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = usbredir_bulk_receiving_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT8(bulk_receiving_started, struct endp_data),
VMSTATE_END_OF_LIST()
}
};
-static bool usbredir_bulk_receiving_needed(void *priv)
+static bool usbredir_stream_needed(void *priv)
{
struct endp_data *endp = priv;
- return endp->bulk_receiving_started;
+ return endp->max_streams;
}
static const VMStateDescription usbredir_stream_vmstate = {
.name = "usb-redir-ep/stream-state",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = usbredir_stream_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT32(max_streams, struct endp_data),
VMSTATE_END_OF_LIST()
}
};
-static bool usbredir_stream_needed(void *priv)
-{
- struct endp_data *endp = priv;
-
- return endp->max_streams;
-}
-
static const VMStateDescription usbredir_ep_vmstate = {
.name = "usb-redir-ep",
.version_id = 1,
@@ -2318,16 +2320,10 @@ static const VMStateDescription usbredir_ep_vmstate = {
VMSTATE_INT32(bufpq_target_size, struct endp_data),
VMSTATE_END_OF_LIST()
},
- .subsections = (VMStateSubsection[]) {
- {
- .vmsd = &usbredir_bulk_receiving_vmstate,
- .needed = usbredir_bulk_receiving_needed,
- }, {
- .vmsd = &usbredir_stream_vmstate,
- .needed = usbredir_stream_needed,
- }, {
- /* empty */
- }
+ .subsections = (const VMStateDescription*[]) {
+ &usbredir_bulk_receiving_vmstate,
+ &usbredir_stream_vmstate,
+ NULL
}
};
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index fb49ffcb2d..ee4e07c5e7 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -1053,6 +1053,7 @@ static const VMStateDescription vmstate_virtio_device_endian = {
.name = "virtio/device_endian",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = &virtio_device_endian_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT8(device_endian, VirtIODevice),
VMSTATE_END_OF_LIST()
@@ -1063,6 +1064,7 @@ static const VMStateDescription vmstate_virtio_64bit_features = {
.name = "virtio/64bit_features",
.version_id = 1,
.minimum_version_id = 1,
+ .needed = &virtio_64bit_features_needed,
.fields = (VMStateField[]) {
VMSTATE_UINT64(guest_features, VirtIODevice),
VMSTATE_END_OF_LIST()
@@ -1077,16 +1079,10 @@ static const VMStateDescription vmstate_virtio = {
.fields = (VMStateField[]) {
VMSTATE_END_OF_LIST()
},
- .subsections = (VMStateSubsection[]) {
- {
- .vmsd = &vmstate_virtio_device_endian,
- .needed = &virtio_device_endian_needed
- },
- {
- .vmsd = &vmstate_virtio_64bit_features,
- .needed = &virtio_64bit_features_needed
- },
- { 0 }
+ .subsections = (const VMStateDescription*[]) {
+ &vmstate_virtio_device_endian,
+ &vmstate_virtio_64bit_features,
+ NULL
}
};
diff --git a/hw/watchdog/Makefile.objs b/hw/watchdog/Makefile.objs
index 4b0374a555..72e3ffd93c 100644
--- a/hw/watchdog/Makefile.objs
+++ b/hw/watchdog/Makefile.objs
@@ -1,3 +1,4 @@
common-obj-y += watchdog.o
common-obj-$(CONFIG_WDT_IB6300ESB) += wdt_i6300esb.o
common-obj-$(CONFIG_WDT_IB700) += wdt_ib700.o
+common-obj-$(CONFIG_WDT_DIAG288) += wdt_diag288.o
diff --git a/hw/watchdog/watchdog.c b/hw/watchdog/watchdog.c
index 54440c91c5..8d4b0eeeb0 100644
--- a/hw/watchdog/watchdog.c
+++ b/hw/watchdog/watchdog.c
@@ -27,6 +27,7 @@
#include "sysemu/sysemu.h"
#include "sysemu/watchdog.h"
#include "qapi-event.h"
+#include "hw/nmi.h"
/* Possible values for action parameter. */
#define WDT_RESET 1 /* Hard reset. */
@@ -35,6 +36,7 @@
#define WDT_PAUSE 4 /* Pause. */
#define WDT_DEBUG 5 /* Prints a message and continues running. */
#define WDT_NONE 6 /* Do nothing. */
+#define WDT_NMI 7 /* Inject nmi into the guest */
static int watchdog_action = WDT_RESET;
static QLIST_HEAD(watchdog_list, WatchdogTimerModel) watchdog_list;
@@ -95,6 +97,8 @@ int select_watchdog_action(const char *p)
watchdog_action = WDT_DEBUG;
else if (strcasecmp(p, "none") == 0)
watchdog_action = WDT_NONE;
+ else if (strcasecmp(p, "inject-nmi") == 0)
+ watchdog_action = WDT_NMI;
else
return -1;
@@ -138,5 +142,11 @@ void watchdog_perform_action(void)
case WDT_NONE:
qapi_event_send_watchdog(WATCHDOG_EXPIRATION_ACTION_NONE, &error_abort);
break;
+
+ case WDT_NMI:
+ qapi_event_send_watchdog(WATCHDOG_EXPIRATION_ACTION_INJECT_NMI,
+ &error_abort);
+ inject_nmi();
+ break;
}
}
diff --git a/hw/watchdog/wdt_diag288.c b/hw/watchdog/wdt_diag288.c
new file mode 100644
index 0000000000..1185e0681c
--- /dev/null
+++ b/hw/watchdog/wdt_diag288.c
@@ -0,0 +1,122 @@
+/*
+ * watchdog device diag288 support
+ *
+ * Copyright IBM, Corp. 2015
+ *
+ * Authors:
+ * Xu Wang <gesaint@linux.vnet.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or (at your
+ * option) any later version. See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "sysemu/watchdog.h"
+#include "hw/sysbus.h"
+#include "qemu/timer.h"
+#include "hw/watchdog/wdt_diag288.h"
+
+static WatchdogTimerModel model = {
+ .wdt_name = TYPE_WDT_DIAG288,
+ .wdt_description = "diag288 device for s390x platform",
+};
+
+static const VMStateDescription vmstate_diag288 = {
+ .name = "vmstate_diag288",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_TIMER_PTR(timer, DIAG288State),
+ VMSTATE_BOOL(enabled, DIAG288State),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void wdt_diag288_reset(DeviceState *dev)
+{
+ DIAG288State *diag288 = DIAG288(dev);
+
+ diag288->enabled = false;
+ timer_del(diag288->timer);
+}
+
+static void diag288_timer_expired(void *dev)
+{
+ qemu_log_mask(CPU_LOG_RESET, "Watchdog timer expired.\n");
+ watchdog_perform_action();
+ wdt_diag288_reset(dev);
+}
+
+static int wdt_diag288_handle_timer(DIAG288State *diag288,
+ uint64_t func, uint64_t timeout)
+{
+ switch (func) {
+ case WDT_DIAG288_INIT:
+ diag288->enabled = true;
+ /* fall through */
+ case WDT_DIAG288_CHANGE:
+ if (!diag288->enabled) {
+ return -1;
+ }
+ timer_mod(diag288->timer,
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
+ timeout * get_ticks_per_sec());
+ break;
+ case WDT_DIAG288_CANCEL:
+ if (!diag288->enabled) {
+ return -1;
+ }
+ diag288->enabled = false;
+ timer_del(diag288->timer);
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+static void wdt_diag288_realize(DeviceState *dev, Error **errp)
+{
+ DIAG288State *diag288 = DIAG288(dev);
+
+ diag288->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, diag288_timer_expired,
+ dev);
+}
+
+static void wdt_diag288_unrealize(DeviceState *dev, Error **errp)
+{
+ DIAG288State *diag288 = DIAG288(dev);
+
+ timer_del(diag288->timer);
+ timer_free(diag288->timer);
+}
+
+static void wdt_diag288_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ DIAG288Class *diag288 = DIAG288_CLASS(klass);
+
+ dc->realize = wdt_diag288_realize;
+ dc->unrealize = wdt_diag288_unrealize;
+ dc->reset = wdt_diag288_reset;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+ dc->vmsd = &vmstate_diag288;
+ diag288->handle_timer = wdt_diag288_handle_timer;
+}
+
+static const TypeInfo wdt_diag288_info = {
+ .class_init = wdt_diag288_class_init,
+ .parent = TYPE_DEVICE,
+ .name = TYPE_WDT_DIAG288,
+ .instance_size = sizeof(DIAG288State),
+ .class_size = sizeof(DIAG288Class),
+};
+
+static void wdt_diag288_register_types(void)
+{
+ watchdog_add_model(&model);
+ type_register_static(&wdt_diag288_info);
+}
+
+type_init(wdt_diag288_register_types)
diff --git a/hw/xen/xen_backend.c b/hw/xen/xen_backend.c
index b2cb22b99d..2510e2e4ff 100644
--- a/hw/xen/xen_backend.c
+++ b/hw/xen/xen_backend.c
@@ -714,9 +714,7 @@ int xen_be_init(void)
return -1;
}
- if (qemu_set_fd_handler(xs_fileno(xenstore), xenstore_update, NULL, NULL) < 0) {
- goto err;
- }
+ qemu_set_fd_handler(xs_fileno(xenstore), xenstore_update, NULL, NULL);
if (xen_xc == XC_HANDLER_INITIAL_VALUE) {
/* Check if xen_init() have been called */