aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/Makefile.objs1
-rw-r--r--hw/arm/kzm.c5
-rw-r--r--hw/arm/virt.c32
-rw-r--r--hw/char/imx_serial.c159
-rw-r--r--hw/cpu/a15mpcore.c29
-rw-r--r--hw/i386/Makefile.objs10
-rw-r--r--hw/i386/acpi-build.c1
-rw-r--r--hw/i386/acpi-dsdt.dsl1
-rw-r--r--hw/i386/pc.c156
-rw-r--r--hw/i386/pc_piix.c77
-rw-r--r--hw/i386/pc_q35.c69
-rw-r--r--hw/i386/q35-acpi-dsdt.dsl1
-rw-r--r--hw/ide/ahci.h2
-rw-r--r--hw/ide/macio.c28
-rw-r--r--hw/ide/piix.c7
-rw-r--r--hw/intc/arm_gic.c64
-rw-r--r--hw/intc/arm_gic_common.c41
-rw-r--r--hw/intc/arm_gic_kvm.c28
-rw-r--r--hw/intc/imx_avic.c56
-rw-r--r--hw/misc/imx_ccm.c81
-rw-r--r--hw/net/rtl8139.c363
-rw-r--r--hw/net/virtio-net.c8
-rw-r--r--hw/net/vmxnet3.c4
-rw-r--r--hw/pci-host/bonito.c16
-rw-r--r--hw/pci-host/piix.c7
-rw-r--r--hw/pci/pci.c12
-rw-r--r--hw/ppc/spapr.c1
-rw-r--r--hw/smbios/Makefile.objs1
-rw-r--r--hw/smbios/smbios.c (renamed from hw/i386/smbios.c)19
-rw-r--r--hw/timer/imx_epit.c64
-rw-r--r--hw/timer/imx_gpt.c85
-rw-r--r--hw/virtio/virtio.c56
32 files changed, 648 insertions, 836 deletions
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 73afa41b32..7e7c241104 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -31,6 +31,7 @@ devices-dirs-$(CONFIG_VIRTIO) += virtio/
devices-dirs-$(CONFIG_SOFTMMU) += watchdog/
devices-dirs-$(CONFIG_SOFTMMU) += xen/
devices-dirs-$(CONFIG_MEM_HOTPLUG) += mem/
+devices-dirs-$(CONFIG_SMBIOS) += smbios/
devices-dirs-y += core/
common-obj-y += $(devices-dirs-y)
obj-y += $(devices-dirs-y)
diff --git a/hw/arm/kzm.c b/hw/arm/kzm.c
index 5be0369a50..d7af230925 100644
--- a/hw/arm/kzm.c
+++ b/hw/arm/kzm.c
@@ -22,6 +22,7 @@
#include "sysemu/sysemu.h"
#include "hw/boards.h"
#include "hw/char/serial.h"
+#include "hw/intc/imx_avic.h"
#include "hw/arm/imx.h"
/* Memory map for Kzm Emulation Baseboard:
@@ -106,7 +107,7 @@ static void kzm_init(MachineState *machine)
memory_region_init_ram(sram, NULL, "kzm.sram", 0x4000, &error_abort);
memory_region_add_subregion(address_space_mem, 0x1FFFC000, sram);
- dev = sysbus_create_varargs("imx_avic", 0x68000000,
+ dev = sysbus_create_varargs(TYPE_IMX_AVIC, 0x68000000,
qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ),
qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_FIQ),
NULL);
@@ -114,7 +115,7 @@ static void kzm_init(MachineState *machine)
imx_serial_create(0, 0x43f90000, qdev_get_gpio_in(dev, 45));
imx_serial_create(1, 0x43f94000, qdev_get_gpio_in(dev, 32));
- ccm = sysbus_create_simple("imx_ccm", 0x53f80000, NULL);
+ ccm = sysbus_create_simple(TYPE_IMX_CCM, 0x53f80000, NULL);
imx_timerp_create(0x53f94000, qdev_get_gpio_in(dev, 28), ccm);
imx_timerp_create(0x53f98000, qdev_get_gpio_in(dev, 27), ccm);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 484689264c..d5a84175c9 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -48,6 +48,8 @@
#include "hw/arm/sysbus-fdt.h"
#include "hw/platform-bus.h"
#include "hw/arm/fdt.h"
+#include "hw/intc/arm_gic_common.h"
+#include "kvm_arm.h"
/* Number of external interrupt lines to configure the GIC with */
#define NUM_IRQS 256
@@ -365,12 +367,10 @@ static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic)
/* We create a standalone GIC v2 */
DeviceState *gicdev;
SysBusDevice *gicbusdev;
- const char *gictype = "arm_gic";
+ const char *gictype;
int i;
- if (kvm_irqchip_in_kernel()) {
- gictype = "kvm-arm-gic";
- }
+ gictype = gic_class_name();
gicdev = qdev_create(NULL, gictype);
qdev_prop_set_uint32(gicdev, "revision", 2);
@@ -390,15 +390,23 @@ static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic)
*/
for (i = 0; i < smp_cpus; i++) {
DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
- int ppibase = NUM_IRQS + i * 32;
- /* physical timer; we wire it up to the non-secure timer's ID,
- * since a real A15 always has TrustZone but QEMU doesn't.
+ int ppibase = NUM_IRQS + i * GIC_INTERNAL + GIC_NR_SGIS;
+ int irq;
+ /* Mapping from the output timer irq lines from the CPU to the
+ * GIC PPI inputs we use for the virt board.
*/
- qdev_connect_gpio_out(cpudev, 0,
- qdev_get_gpio_in(gicdev, ppibase + 30));
- /* virtual timer */
- qdev_connect_gpio_out(cpudev, 1,
- qdev_get_gpio_in(gicdev, ppibase + 27));
+ const int timer_irq[] = {
+ [GTIMER_PHYS] = ARCH_TIMER_NS_EL1_IRQ,
+ [GTIMER_VIRT] = ARCH_TIMER_VIRT_IRQ,
+ [GTIMER_HYP] = ARCH_TIMER_NS_EL2_IRQ,
+ [GTIMER_SEC] = ARCH_TIMER_S_EL1_IRQ,
+ };
+
+ for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
+ qdev_connect_gpio_out(cpudev, irq,
+ qdev_get_gpio_in(gicdev,
+ ppibase + timer_irq[irq]));
+ }
sysbus_connect_irq(gicbusdev, i, qdev_get_gpio_in(cpudev, ARM_CPU_IRQ));
sysbus_connect_irq(gicbusdev, i + smp_cpus,
diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c
index f3fbc776be..801156db2d 100644
--- a/hw/char/imx_serial.c
+++ b/hw/char/imx_serial.c
@@ -4,6 +4,7 @@
* Copyright (c) 2008 OKL
* Originally Written by Hans Jiang
* Copyright (c) 2011 NICTA Pty Ltd.
+ * Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
@@ -17,8 +18,7 @@
* is a real serial device.
*/
-#include "hw/hw.h"
-#include "hw/sysbus.h"
+#include "hw/char/imx_serial.h"
#include "sysemu/sysemu.h"
#include "sysemu/char.h"
#include "hw/arm/imx.h"
@@ -26,7 +26,7 @@
//#define DEBUG_SERIAL 1
#ifdef DEBUG_SERIAL
#define DPRINTF(fmt, args...) \
-do { printf("imx_serial: " fmt , ##args); } while (0)
+do { printf("%s: " fmt , TYPE_IMX_SERIAL, ##args); } while (0)
#else
#define DPRINTF(fmt, args...) do {} while (0)
#endif
@@ -38,42 +38,13 @@ do { printf("imx_serial: " fmt , ##args); } while (0)
//#define DEBUG_IMPLEMENTATION 1
#ifdef DEBUG_IMPLEMENTATION
# define IPRINTF(fmt, args...) \
- do { fprintf(stderr, "imx_serial: " fmt, ##args); } while (0)
+ do { fprintf(stderr, "%s: " fmt, TYPE_IMX_SERIAL, ##args); } while (0)
#else
# define IPRINTF(fmt, args...) do {} while (0)
#endif
-#define TYPE_IMX_SERIAL "imx-serial"
-#define IMX_SERIAL(obj) OBJECT_CHECK(IMXSerialState, (obj), TYPE_IMX_SERIAL)
-
-typedef struct IMXSerialState {
- SysBusDevice parent_obj;
-
- MemoryRegion iomem;
- int32_t readbuff;
-
- uint32_t usr1;
- uint32_t usr2;
- uint32_t ucr1;
- uint32_t ucr2;
- uint32_t uts1;
-
- /*
- * The registers below are implemented just so that the
- * guest OS sees what it has written
- */
- uint32_t onems;
- uint32_t ufcr;
- uint32_t ubmr;
- uint32_t ubrc;
- uint32_t ucr3;
-
- qemu_irq irq;
- CharDriverState *chr;
-} IMXSerialState;
-
static const VMStateDescription vmstate_imx_serial = {
- .name = "imx-serial",
+ .name = TYPE_IMX_SERIAL,
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
@@ -91,55 +62,6 @@ static const VMStateDescription vmstate_imx_serial = {
},
};
-
-#define URXD_CHARRDY (1<<15) /* character read is valid */
-#define URXD_ERR (1<<14) /* Character has error */
-#define URXD_BRK (1<<11) /* Break received */
-
-#define USR1_PARTYER (1<<15) /* Parity Error */
-#define USR1_RTSS (1<<14) /* RTS pin status */
-#define USR1_TRDY (1<<13) /* Tx ready */
-#define USR1_RTSD (1<<12) /* RTS delta: pin changed state */
-#define USR1_ESCF (1<<11) /* Escape sequence interrupt */
-#define USR1_FRAMERR (1<<10) /* Framing error */
-#define USR1_RRDY (1<<9) /* receiver ready */
-#define USR1_AGTIM (1<<8) /* Aging timer interrupt */
-#define USR1_DTRD (1<<7) /* DTR changed */
-#define USR1_RXDS (1<<6) /* Receiver is idle */
-#define USR1_AIRINT (1<<5) /* Aysnch IR interrupt */
-#define USR1_AWAKE (1<<4) /* Falling edge detected on RXd pin */
-
-#define USR2_ADET (1<<15) /* Autobaud complete */
-#define USR2_TXFE (1<<14) /* Transmit FIFO empty */
-#define USR2_DTRF (1<<13) /* DTR/DSR transition */
-#define USR2_IDLE (1<<12) /* UART has been idle for too long */
-#define USR2_ACST (1<<11) /* Autobaud counter stopped */
-#define USR2_RIDELT (1<<10) /* Ring Indicator delta */
-#define USR2_RIIN (1<<9) /* Ring Indicator Input */
-#define USR2_IRINT (1<<8) /* Serial Infrared Interrupt */
-#define USR2_WAKE (1<<7) /* Start bit detected */
-#define USR2_DCDDELT (1<<6) /* Data Carrier Detect delta */
-#define USR2_DCDIN (1<<5) /* Data Carrier Detect Input */
-#define USR2_RTSF (1<<4) /* RTS transition */
-#define USR2_TXDC (1<<3) /* Transmission complete */
-#define USR2_BRCD (1<<2) /* Break condition detected */
-#define USR2_ORE (1<<1) /* Overrun error */
-#define USR2_RDR (1<<0) /* Receive data ready */
-
-#define UCR1_TRDYEN (1<<13) /* Tx Ready Interrupt Enable */
-#define UCR1_RRDYEN (1<<9) /* Rx Ready Interrupt Enable */
-#define UCR1_TXMPTYEN (1<<6) /* Tx Empty Interrupt Enable */
-#define UCR1_UARTEN (1<<0) /* UART Enable */
-
-#define UCR2_TXEN (1<<2) /* Transmitter enable */
-#define UCR2_RXEN (1<<1) /* Receiver enable */
-#define UCR2_SRST (1<<0) /* Reset complete */
-
-#define UTS1_TXEMPTY (1<<6)
-#define UTS1_RXEMPTY (1<<5)
-#define UTS1_TXFULL (1<<4)
-#define UTS1_RXFULL (1<<3)
-
static void imx_update(IMXSerialState *s)
{
uint32_t flags;
@@ -203,7 +125,9 @@ static uint64_t imx_serial_read(void *opaque, hwaddr offset,
s->usr2 &= ~USR2_RDR;
s->uts1 |= UTS1_RXEMPTY;
imx_update(s);
- qemu_chr_accept_input(s->chr);
+ if (s->chr) {
+ qemu_chr_accept_input(s->chr);
+ }
}
return c;
@@ -242,13 +166,13 @@ static uint64_t imx_serial_read(void *opaque, hwaddr offset,
return 0x0; /* TODO */
default:
- IPRINTF("imx_serial_read: bad offset: 0x%x\n", (int)offset);
+ IPRINTF("%s: bad offset: 0x%x\n", __func__, (int)offset);
return 0;
}
}
static void imx_serial_write(void *opaque, hwaddr offset,
- uint64_t value, unsigned size)
+ uint64_t value, unsigned size)
{
IMXSerialState *s = (IMXSerialState *)opaque;
unsigned char ch;
@@ -290,7 +214,9 @@ static void imx_serial_write(void *opaque, hwaddr offset,
}
if (value & UCR2_RXEN) {
if (!(s->ucr2 & UCR2_RXEN)) {
- qemu_chr_accept_input(s->chr);
+ if (s->chr) {
+ qemu_chr_accept_input(s->chr);
+ }
}
}
s->ucr2 = value & 0xffff;
@@ -298,25 +224,25 @@ static void imx_serial_write(void *opaque, hwaddr offset,
case 0x25: /* USR1 */
value &= USR1_AWAKE | USR1_AIRINT | USR1_DTRD | USR1_AGTIM |
- USR1_FRAMERR | USR1_ESCF | USR1_RTSD | USR1_PARTYER;
+ USR1_FRAMERR | USR1_ESCF | USR1_RTSD | USR1_PARTYER;
s->usr1 &= ~value;
break;
case 0x26: /* USR2 */
- /*
- * Writing 1 to some bits clears them; all other
- * values are ignored
- */
+ /*
+ * Writing 1 to some bits clears them; all other
+ * values are ignored
+ */
value &= USR2_ADET | USR2_DTRF | USR2_IDLE | USR2_ACST |
- USR2_RIDELT | USR2_IRINT | USR2_WAKE |
- USR2_DCDDELT | USR2_RTSF | USR2_BRCD | USR2_ORE;
+ USR2_RIDELT | USR2_IRINT | USR2_WAKE |
+ USR2_DCDDELT | USR2_RTSF | USR2_BRCD | USR2_ORE;
s->usr2 &= ~value;
break;
- /*
- * Linux expects to see what it writes to these registers
- * We don't currently alter the baud rate
- */
+ /*
+ * Linux expects to see what it writes to these registers
+ * We don't currently alter the baud rate
+ */
case 0x29: /* UBIR */
s->ubrc = value & 0xffff;
break;
@@ -344,7 +270,7 @@ static void imx_serial_write(void *opaque, hwaddr offset,
break;
default:
- IPRINTF("imx_serial_write: Bad offset 0x%x\n", (int)offset);
+ IPRINTF("%s: Bad offset 0x%x\n", __func__, (int)offset);
}
}
@@ -384,16 +310,10 @@ static const struct MemoryRegionOps imx_serial_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
-static int imx_serial_init(SysBusDevice *dev)
+static void imx_serial_realize(DeviceState *dev, Error **errp)
{
IMXSerialState *s = IMX_SERIAL(dev);
-
- memory_region_init_io(&s->iomem, OBJECT(s), &imx_serial_ops, s,
- "imx-serial", 0x1000);
- sysbus_init_mmio(dev, &s->iomem);
- sysbus_init_irq(dev, &s->irq);
-
if (s->chr) {
qemu_chr_add_handlers(s->chr, imx_can_receive, imx_receive,
imx_event, s);
@@ -401,8 +321,17 @@ static int imx_serial_init(SysBusDevice *dev)
DPRINTF("No char dev for uart at 0x%lx\n",
(unsigned long)s->iomem.ram_addr);
}
+}
- return 0;
+static void imx_serial_init(Object *obj)
+{
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ IMXSerialState *s = IMX_SERIAL(obj);
+
+ memory_region_init_io(&s->iomem, obj, &imx_serial_ops, s,
+ TYPE_IMX_SERIAL, 0x1000);
+ sysbus_init_mmio(sbd, &s->iomem);
+ sysbus_init_irq(sbd, &s->irq);
}
void imx_serial_create(int uart, const hwaddr addr, qemu_irq irq)
@@ -439,7 +368,7 @@ void imx_serial_create(int uart, const hwaddr addr, qemu_irq irq)
}
-static Property imx32_serial_properties[] = {
+static Property imx_serial_properties[] = {
DEFINE_PROP_CHR("chardev", IMXSerialState, chr),
DEFINE_PROP_END_OF_LIST(),
};
@@ -447,21 +376,21 @@ static Property imx32_serial_properties[] = {
static void imx_serial_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- k->init = imx_serial_init;
+ dc->realize = imx_serial_realize;
dc->vmsd = &vmstate_imx_serial;
dc->reset = imx_serial_reset_at_boot;
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
dc->desc = "i.MX series UART";
- dc->props = imx32_serial_properties;
+ dc->props = imx_serial_properties;
}
static const TypeInfo imx_serial_info = {
- .name = TYPE_IMX_SERIAL,
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(IMXSerialState),
- .class_init = imx_serial_class_init,
+ .name = TYPE_IMX_SERIAL,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(IMXSerialState),
+ .instance_init = imx_serial_init,
+ .class_init = imx_serial_class_init,
};
static void imx_serial_register_types(void)
diff --git a/hw/cpu/a15mpcore.c b/hw/cpu/a15mpcore.c
index acc419e11a..58ac02e610 100644
--- a/hw/cpu/a15mpcore.c
+++ b/hw/cpu/a15mpcore.c
@@ -20,6 +20,7 @@
#include "hw/cpu/a15mpcore.h"
#include "sysemu/kvm.h"
+#include "kvm_arm.h"
static void a15mp_priv_set_irq(void *opaque, int irq, int level)
{
@@ -33,16 +34,11 @@ static void a15mp_priv_initfn(Object *obj)
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
A15MPPrivState *s = A15MPCORE_PRIV(obj);
DeviceState *gicdev;
- const char *gictype = "arm_gic";
-
- if (kvm_irqchip_in_kernel()) {
- gictype = "kvm-arm-gic";
- }
memory_region_init(&s->container, obj, "a15mp-priv-container", 0x8000);
sysbus_init_mmio(sbd, &s->container);
- object_initialize(&s->gic, sizeof(s->gic), gictype);
+ object_initialize(&s->gic, sizeof(s->gic), gic_class_name());
gicdev = DEVICE(&s->gic);
qdev_set_parent_bus(gicdev, sysbus_get_default());
qdev_prop_set_uint32(gicdev, "revision", 2);
@@ -79,14 +75,21 @@ static void a15mp_priv_realize(DeviceState *dev, Error **errp)
for (i = 0; i < s->num_cpu; i++) {
DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
int ppibase = s->num_irq - 32 + i * 32;
- /* physical timer; we wire it up to the non-secure timer's ID,
- * since a real A15 always has TrustZone but QEMU doesn't.
+ int irq;
+ /* Mapping from the output timer irq lines from the CPU to the
+ * GIC PPI inputs used on the A15:
*/
- qdev_connect_gpio_out(cpudev, 0,
- qdev_get_gpio_in(gicdev, ppibase + 30));
- /* virtual timer */
- qdev_connect_gpio_out(cpudev, 1,
- qdev_get_gpio_in(gicdev, ppibase + 27));
+ const int timer_irq[] = {
+ [GTIMER_PHYS] = 30,
+ [GTIMER_VIRT] = 27,
+ [GTIMER_HYP] = 26,
+ [GTIMER_SEC] = 29,
+ };
+ for (irq = 0; irq < ARRAY_SIZE(timer_irq); irq++) {
+ qdev_connect_gpio_out(cpudev, irq,
+ qdev_get_gpio_in(gicdev,
+ ppibase + timer_irq[irq]));
+ }
}
/* Memory map (addresses are offsets from PERIPHBASE):
diff --git a/hw/i386/Makefile.objs b/hw/i386/Makefile.objs
index bd4f147f9d..ebd1015a08 100644
--- a/hw/i386/Makefile.objs
+++ b/hw/i386/Makefile.objs
@@ -1,5 +1,5 @@
obj-$(CONFIG_KVM) += kvm/
-obj-y += multiboot.o smbios.o
+obj-y += multiboot.o
obj-y += pc.o pc_piix.o pc_q35.o
obj-y += pc_sysfw.o
obj-y += intel_iommu.o
@@ -7,8 +7,14 @@ obj-$(CONFIG_XEN) += ../xenpv/ xen/
obj-y += kvmvapic.o
obj-y += acpi-build.o
+
+gen-hex-y += hw/i386/acpi-dsdt.hex
+gen-hex-y += hw/i386/q35-acpi-dsdt.hex
+
hw/i386/acpi-build.o: hw/i386/acpi-build.c \
- hw/i386/acpi-dsdt.hex hw/i386/q35-acpi-dsdt.hex
+ $(gen-hex-y)
+
+-include $(gen-hex-y:.hex=.d)
iasl-option=$(shell if test -z "`$(1) $(2) 2>&1 > /dev/null`" \
; then echo "$(2)"; else echo "$(3)"; fi ;)
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 46eddb8e48..95e0c657a7 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -169,6 +169,7 @@ static void acpi_get_pm_info(AcpiPmInfo *pm)
Object *obj = NULL;
QObject *o;
+ pm->cpu_hp_io_base = 0;
pm->pcihp_io_base = 0;
pm->pcihp_io_len = 0;
if (piix) {
diff --git a/hw/i386/acpi-dsdt.dsl b/hw/i386/acpi-dsdt.dsl
index a2d84ecf8f..8dba096dd8 100644
--- a/hw/i386/acpi-dsdt.dsl
+++ b/hw/i386/acpi-dsdt.dsl
@@ -43,7 +43,6 @@ DefinitionBlock (
#include "acpi-dsdt-hpet.dsl"
-
/****************************************************************
* PIIX4 PM
****************************************************************/
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 7661ea9cdf..9f2924e5df 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -33,7 +33,7 @@
#include "hw/pci/pci_bus.h"
#include "hw/nvram/fw_cfg.h"
#include "hw/timer/hpet.h"
-#include "hw/i386/smbios.h"
+#include "hw/smbios/smbios.h"
#include "hw/loader.h"
#include "elf.h"
#include "multiboot.h"
@@ -428,26 +428,24 @@ static void pc_cmos_init_late(void *opaque)
qemu_unregister_reset(pc_cmos_init_late, opaque);
}
-void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
- const char *boot_device, MachineState *machine,
+void pc_cmos_init(PCMachineState *pcms,
BusState *idebus0, BusState *idebus1,
ISADevice *s)
{
int val;
static pc_cmos_init_late_arg arg;
- PCMachineState *pc_machine = PC_MACHINE(machine);
Error *local_err = NULL;
/* various important CMOS locations needed by PC/Bochs bios */
/* memory size */
/* base memory (first MiB) */
- val = MIN(ram_size / 1024, 640);
+ val = MIN(pcms->below_4g_mem_size / 1024, 640);
rtc_set_memory(s, 0x15, val);
rtc_set_memory(s, 0x16, val >> 8);
/* extended memory (next 64MiB) */
- if (ram_size > 1024 * 1024) {
- val = (ram_size - 1024 * 1024) / 1024;
+ if (pcms->below_4g_mem_size > 1024 * 1024) {
+ val = (pcms->below_4g_mem_size - 1024 * 1024) / 1024;
} else {
val = 0;
}
@@ -458,8 +456,8 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
rtc_set_memory(s, 0x30, val);
rtc_set_memory(s, 0x31, val >> 8);
/* memory between 16MiB and 4GiB */
- if (ram_size > 16 * 1024 * 1024) {
- val = (ram_size - 16 * 1024 * 1024) / 65536;
+ if (pcms->below_4g_mem_size > 16 * 1024 * 1024) {
+ val = (pcms->below_4g_mem_size - 16 * 1024 * 1024) / 65536;
} else {
val = 0;
}
@@ -468,7 +466,7 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
rtc_set_memory(s, 0x34, val);
rtc_set_memory(s, 0x35, val >> 8);
/* memory above 4GiB */
- val = above_4g_mem_size / 65536;
+ val = pcms->above_4g_mem_size / 65536;
rtc_set_memory(s, 0x5b, val);
rtc_set_memory(s, 0x5c, val >> 8);
rtc_set_memory(s, 0x5d, val >> 16);
@@ -476,15 +474,15 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
/* set the number of CPU */
rtc_set_memory(s, 0x5f, smp_cpus - 1);
- object_property_add_link(OBJECT(machine), "rtc_state",
+ object_property_add_link(OBJECT(pcms), "rtc_state",
TYPE_ISA_DEVICE,
- (Object **)&pc_machine->rtc,
+ (Object **)&pcms->rtc,
object_property_allow_set_link,
OBJ_PROP_LINK_UNREF_ON_RELEASE, &error_abort);
- object_property_set_link(OBJECT(machine), OBJECT(s),
+ object_property_set_link(OBJECT(pcms), OBJECT(s),
"rtc_state", &error_abort);
- set_boot_dev(s, boot_device, &local_err);
+ set_boot_dev(s, MACHINE(pcms)->boot_order, &local_err);
if (local_err) {
error_report_err(local_err);
exit(1);
@@ -718,11 +716,46 @@ static unsigned int pc_apic_id_limit(unsigned int max_cpus)
return x86_cpu_apic_id_from_index(max_cpus - 1) + 1;
}
-static FWCfgState *bochs_bios_init(void)
+static void pc_build_smbios(FWCfgState *fw_cfg)
{
- FWCfgState *fw_cfg;
uint8_t *smbios_tables, *smbios_anchor;
size_t smbios_tables_len, smbios_anchor_len;
+ struct smbios_phys_mem_area *mem_array;
+ unsigned i, array_count;
+
+ smbios_tables = smbios_get_table_legacy(&smbios_tables_len);
+ if (smbios_tables) {
+ fw_cfg_add_bytes(fw_cfg, FW_CFG_SMBIOS_ENTRIES,
+ smbios_tables, smbios_tables_len);
+ }
+
+ /* build the array of physical mem area from e820 table */
+ mem_array = g_malloc0(sizeof(*mem_array) * e820_get_num_entries());
+ for (i = 0, array_count = 0; i < e820_get_num_entries(); i++) {
+ uint64_t addr, len;
+
+ if (e820_get_entry(i, E820_RAM, &addr, &len)) {
+ mem_array[array_count].address = addr;
+ mem_array[array_count].length = len;
+ array_count++;
+ }
+ }
+ smbios_get_tables(mem_array, array_count,
+ &smbios_tables, &smbios_tables_len,
+ &smbios_anchor, &smbios_anchor_len);
+ g_free(mem_array);
+
+ if (smbios_anchor) {
+ fw_cfg_add_file(fw_cfg, "etc/smbios/smbios-tables",
+ smbios_tables, smbios_tables_len);
+ fw_cfg_add_file(fw_cfg, "etc/smbios/smbios-anchor",
+ smbios_anchor, smbios_anchor_len);
+ }
+}
+
+static FWCfgState *bochs_bios_init(void)
+{
+ FWCfgState *fw_cfg;
uint64_t *numa_fw_cfg;
int i, j;
unsigned int apic_id_limit = pc_apic_id_limit(max_cpus);
@@ -748,20 +781,7 @@ static FWCfgState *bochs_bios_init(void)
acpi_tables, acpi_tables_len);
fw_cfg_add_i32(fw_cfg, FW_CFG_IRQ0_OVERRIDE, kvm_allows_irq0_override());
- smbios_tables = smbios_get_table_legacy(&smbios_tables_len);
- if (smbios_tables) {
- fw_cfg_add_bytes(fw_cfg, FW_CFG_SMBIOS_ENTRIES,
- smbios_tables, smbios_tables_len);
- }
-
- smbios_get_tables(&smbios_tables, &smbios_tables_len,
- &smbios_anchor, &smbios_anchor_len);
- if (smbios_anchor) {
- fw_cfg_add_file(fw_cfg, "etc/smbios/smbios-tables",
- smbios_tables, smbios_tables_len);
- fw_cfg_add_file(fw_cfg, "etc/smbios/smbios-anchor",
- smbios_anchor, smbios_anchor_len);
- }
+ pc_build_smbios(fw_cfg);
fw_cfg_add_bytes(fw_cfg, FW_CFG_E820_TABLE,
&e820_reserve, sizeof(e820_reserve));
@@ -809,11 +829,8 @@ static long get_file_size(FILE *f)
return size;
}
-static void load_linux(FWCfgState *fw_cfg,
- const char *kernel_filename,
- const char *initrd_filename,
- const char *kernel_cmdline,
- hwaddr max_ram_size)
+static void load_linux(PCMachineState *pcms,
+ FWCfgState *fw_cfg)
{
uint16_t protocol;
int setup_size, kernel_size, initrd_size = 0, cmdline_size;
@@ -822,6 +839,10 @@ static void load_linux(FWCfgState *fw_cfg,
hwaddr real_addr, prot_addr, cmdline_addr, initrd_addr = 0;
FILE *f;
char *vmode;
+ MachineState *machine = MACHINE(pcms);
+ const char *kernel_filename = machine->kernel_filename;
+ const char *initrd_filename = machine->initrd_filename;
+ const char *kernel_cmdline = machine->kernel_cmdline;
/* Align to 16 bytes as a paranoia measure */
cmdline_size = (strlen(kernel_cmdline)+16) & ~15;
@@ -886,8 +907,8 @@ static void load_linux(FWCfgState *fw_cfg,
initrd_max = 0x37ffffff;
}
- if (initrd_max >= max_ram_size - acpi_data_size) {
- initrd_max = max_ram_size - acpi_data_size - 1;
+ if (initrd_max >= pcms->below_4g_mem_size - acpi_data_size) {
+ initrd_max = pcms->below_4g_mem_size - acpi_data_size - 1;
}
fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_ADDR, cmdline_addr);
@@ -1189,15 +1210,14 @@ void pc_guest_info_machine_done(Notifier *notifier, void *data)
acpi_setup(&guest_info_state->info);
}
-PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size,
- ram_addr_t above_4g_mem_size)
+PcGuestInfo *pc_guest_info_init(PCMachineState *pcms)
{
PcGuestInfoState *guest_info_state = g_malloc0(sizeof *guest_info_state);
PcGuestInfo *guest_info = &guest_info_state->info;
int i, j;
- guest_info->ram_size_below_4g = below_4g_mem_size;
- guest_info->ram_size = below_4g_mem_size + above_4g_mem_size;
+ guest_info->ram_size_below_4g = pcms->below_4g_mem_size;
+ guest_info->ram_size = pcms->below_4g_mem_size + pcms->above_4g_mem_size;
guest_info->apic_id_limit = pc_apic_id_limit(max_cpus);
guest_info->apic_xrupt_override = kvm_allows_irq0_override();
guest_info->numa_nodes = nb_numa_nodes;
@@ -1264,22 +1284,18 @@ void pc_acpi_init(const char *default_dsdt)
}
}
-FWCfgState *xen_load_linux(const char *kernel_filename,
- const char *kernel_cmdline,
- const char *initrd_filename,
- ram_addr_t below_4g_mem_size,
+FWCfgState *xen_load_linux(PCMachineState *pcms,
PcGuestInfo *guest_info)
{
int i;
FWCfgState *fw_cfg;
- assert(kernel_filename != NULL);
+ assert(MACHINE(pcms)->kernel_filename != NULL);
fw_cfg = fw_cfg_init_io(BIOS_CFG_IOPORT);
rom_set_fw(fw_cfg);
- load_linux(fw_cfg, kernel_filename, initrd_filename,
- kernel_cmdline, below_4g_mem_size);
+ load_linux(pcms, fw_cfg);
for (i = 0; i < nb_option_roms; i++) {
assert(!strcmp(option_rom[i].name, "linuxboot.bin") ||
!strcmp(option_rom[i].name, "multiboot.bin"));
@@ -1289,10 +1305,8 @@ FWCfgState *xen_load_linux(const char *kernel_filename,
return fw_cfg;
}
-FWCfgState *pc_memory_init(MachineState *machine,
+FWCfgState *pc_memory_init(PCMachineState *pcms,
MemoryRegion *system_memory,
- ram_addr_t below_4g_mem_size,
- ram_addr_t above_4g_mem_size,
MemoryRegion *rom_memory,
MemoryRegion **ram_memory,
PcGuestInfo *guest_info)
@@ -1301,9 +1315,10 @@ FWCfgState *pc_memory_init(MachineState *machine,
MemoryRegion *ram, *option_rom_mr;
MemoryRegion *ram_below_4g, *ram_above_4g;
FWCfgState *fw_cfg;
- PCMachineState *pcms = PC_MACHINE(machine);
+ MachineState *machine = MACHINE(pcms);
- assert(machine->ram_size == below_4g_mem_size + above_4g_mem_size);
+ assert(machine->ram_size == pcms->below_4g_mem_size +
+ pcms->above_4g_mem_size);
linux_boot = (machine->kernel_filename != NULL);
@@ -1317,16 +1332,17 @@ FWCfgState *pc_memory_init(MachineState *machine,
*ram_memory = ram;
ram_below_4g = g_malloc(sizeof(*ram_below_4g));
memory_region_init_alias(ram_below_4g, NULL, "ram-below-4g", ram,
- 0, below_4g_mem_size);
+ 0, pcms->below_4g_mem_size);
memory_region_add_subregion(system_memory, 0, ram_below_4g);
- e820_add_entry(0, below_4g_mem_size, E820_RAM);
- if (above_4g_mem_size > 0) {
+ e820_add_entry(0, pcms->below_4g_mem_size, E820_RAM);
+ if (pcms->above_4g_mem_size > 0) {
ram_above_4g = g_malloc(sizeof(*ram_above_4g));
memory_region_init_alias(ram_above_4g, NULL, "ram-above-4g", ram,
- below_4g_mem_size, above_4g_mem_size);
+ pcms->below_4g_mem_size,
+ pcms->above_4g_mem_size);
memory_region_add_subregion(system_memory, 0x100000000ULL,
ram_above_4g);
- e820_add_entry(0x100000000ULL, above_4g_mem_size, E820_RAM);
+ e820_add_entry(0x100000000ULL, pcms->above_4g_mem_size, E820_RAM);
}
if (!guest_info->has_reserved_memory &&
@@ -1359,7 +1375,7 @@ FWCfgState *pc_memory_init(MachineState *machine,
}
pcms->hotplug_memory.base =
- ROUND_UP(0x100000000ULL + above_4g_mem_size, 1ULL << 30);
+ ROUND_UP(0x100000000ULL + pcms->above_4g_mem_size, 1ULL << 30);
if (pcms->enforce_aligned_dimm) {
/* size hotplug region assuming 1G page max alignment per slot */
@@ -1401,8 +1417,7 @@ FWCfgState *pc_memory_init(MachineState *machine,
}
if (linux_boot) {
- load_linux(fw_cfg, machine->kernel_filename, machine->initrd_filename,
- machine->kernel_cmdline, below_4g_mem_size);
+ load_linux(pcms, fw_cfg);
}
for (i = 0; i < nb_option_roms; i++) {
@@ -1886,39 +1901,39 @@ static void pc_machine_initfn(Object *obj)
object_property_add(obj, PC_MACHINE_MEMHP_REGION_SIZE, "int",
pc_machine_get_hotplug_memory_region_size,
- NULL, NULL, NULL, NULL);
+ NULL, NULL, NULL, &error_abort);
pcms->max_ram_below_4g = 1ULL << 32; /* 4G */
object_property_add(obj, PC_MACHINE_MAX_RAM_BELOW_4G, "size",
pc_machine_get_max_ram_below_4g,
pc_machine_set_max_ram_below_4g,
- NULL, NULL, NULL);
+ NULL, NULL, &error_abort);
object_property_set_description(obj, PC_MACHINE_MAX_RAM_BELOW_4G,
"Maximum ram below the 4G boundary (32bit boundary)",
- NULL);
+ &error_abort);
pcms->smm = ON_OFF_AUTO_AUTO;
object_property_add(obj, PC_MACHINE_SMM, "OnOffAuto",
pc_machine_get_smm,
pc_machine_set_smm,
- NULL, NULL, NULL);
+ NULL, NULL, &error_abort);
object_property_set_description(obj, PC_MACHINE_SMM,
"Enable SMM (pc & q35)",
- NULL);
+ &error_abort);
pcms->vmport = ON_OFF_AUTO_AUTO;
object_property_add(obj, PC_MACHINE_VMPORT, "OnOffAuto",
pc_machine_get_vmport,
pc_machine_set_vmport,
- NULL, NULL, NULL);
+ NULL, NULL, &error_abort);
object_property_set_description(obj, PC_MACHINE_VMPORT,
"Enable vmport (pc & q35)",
- NULL);
+ &error_abort);
pcms->enforce_aligned_dimm = true;
object_property_add_bool(obj, PC_MACHINE_ENFORCE_ALIGNED_DIMM,
pc_machine_get_aligned_dimm,
- NULL, NULL);
+ NULL, &error_abort);
}
static unsigned pc_cpu_index_to_socket_id(unsigned cpu_index)
@@ -1938,6 +1953,9 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
pcmc->get_hotplug_handler = mc->get_hotplug_handler;
mc->get_hotplug_handler = pc_get_hotpug_handler;
mc->cpu_index_to_socket_id = pc_cpu_index_to_socket_id;
+ mc->default_boot_order = "cad";
+ mc->hot_add_cpu = pc_hot_add_cpu;
+ mc->max_cpus = 255;
hc->plug = pc_machine_device_plug_cb;
hc->unplug_request = pc_machine_device_unplug_request_cb;
hc->unplug = pc_machine_device_unplug_cb;
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index a896624f89..95584676e2 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -28,7 +28,7 @@
#include "hw/loader.h"
#include "hw/i386/pc.h"
#include "hw/i386/apic.h"
-#include "hw/i386/smbios.h"
+#include "hw/smbios/smbios.h"
#include "hw/pci/pci.h"
#include "hw/pci/pci_ids.h"
#include "hw/usb.h"
@@ -78,11 +78,10 @@ static bool kvmclock_enabled = true;
/* PC hardware initialisation */
static void pc_init1(MachineState *machine)
{
- PCMachineState *pc_machine = PC_MACHINE(machine);
+ PCMachineState *pcms = PC_MACHINE(machine);
MemoryRegion *system_memory = get_system_memory();
MemoryRegion *system_io = get_system_io();
int i;
- ram_addr_t below_4g_mem_size, above_4g_mem_size;
PCIBus *pci_bus;
ISABus *isa_bus;
PCII440FXState *i440fx_state;
@@ -117,25 +116,26 @@ static void pc_init1(MachineState *machine)
/* Handle the machine opt max-ram-below-4g. It is basically doing
* min(qemu limit, user limit).
*/
- if (lowmem > pc_machine->max_ram_below_4g) {
- lowmem = pc_machine->max_ram_below_4g;
+ if (lowmem > pcms->max_ram_below_4g) {
+ lowmem = pcms->max_ram_below_4g;
if (machine->ram_size - lowmem > lowmem &&
lowmem & ((1ULL << 30) - 1)) {
error_report("Warning: Large machine and max_ram_below_4g(%"PRIu64
") not a multiple of 1G; possible bad performance.",
- pc_machine->max_ram_below_4g);
+ pcms->max_ram_below_4g);
}
}
if (machine->ram_size >= lowmem) {
- above_4g_mem_size = machine->ram_size - lowmem;
- below_4g_mem_size = lowmem;
+ pcms->above_4g_mem_size = machine->ram_size - lowmem;
+ pcms->below_4g_mem_size = lowmem;
} else {
- above_4g_mem_size = 0;
- below_4g_mem_size = machine->ram_size;
+ pcms->above_4g_mem_size = 0;
+ pcms->below_4g_mem_size = machine->ram_size;
}
- if (xen_enabled() && xen_hvm_init(&below_4g_mem_size, &above_4g_mem_size,
+ if (xen_enabled() && xen_hvm_init(&pcms->below_4g_mem_size,
+ &pcms->above_4g_mem_size,
&ram_memory) != 0) {
fprintf(stderr, "xen hardware virtual machine initialisation failed\n");
exit(1);
@@ -160,7 +160,7 @@ static void pc_init1(MachineState *machine)
rom_memory = system_memory;
}
- guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size);
+ guest_info = pc_guest_info_init(pcms);
guest_info->has_acpi_build = has_acpi_build;
guest_info->legacy_acpi_table_size = legacy_acpi_table_size;
@@ -178,16 +178,11 @@ static void pc_init1(MachineState *machine)
/* allocate ram and load rom/bios */
if (!xen_enabled()) {
- pc_memory_init(machine, system_memory,
- below_4g_mem_size, above_4g_mem_size,
+ pc_memory_init(pcms, system_memory,
rom_memory, &ram_memory, guest_info);
} else if (machine->kernel_filename != NULL) {
/* For xen HVM direct kernel boot, load linux here */
- xen_load_linux(machine->kernel_filename,
- machine->kernel_cmdline,
- machine->initrd_filename,
- below_4g_mem_size,
- guest_info);
+ xen_load_linux(pcms, guest_info);
}
gsi_state = g_malloc0(sizeof(*gsi_state));
@@ -202,8 +197,8 @@ static void pc_init1(MachineState *machine)
if (pci_enabled) {
pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, &isa_bus, gsi,
system_memory, system_io, machine->ram_size,
- below_4g_mem_size,
- above_4g_mem_size,
+ pcms->below_4g_mem_size,
+ pcms->above_4g_mem_size,
pci_memory, ram_memory);
} else {
pci_bus = NULL;
@@ -234,14 +229,14 @@ static void pc_init1(MachineState *machine)
pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL);
- assert(pc_machine->vmport != ON_OFF_AUTO_MAX);
- if (pc_machine->vmport == ON_OFF_AUTO_AUTO) {
- pc_machine->vmport = xen_enabled() ? ON_OFF_AUTO_OFF : ON_OFF_AUTO_ON;
+ assert(pcms->vmport != ON_OFF_AUTO_MAX);
+ if (pcms->vmport == ON_OFF_AUTO_AUTO) {
+ pcms->vmport = xen_enabled() ? ON_OFF_AUTO_OFF : ON_OFF_AUTO_ON;
}
/* init basic PC hardware */
pc_basic_device_init(isa_bus, gsi, &rtc_state, true,
- (pc_machine->vmport != ON_OFF_AUTO_ON), 0x4);
+ (pcms->vmport != ON_OFF_AUTO_ON), 0x4);
pc_nic_init(isa_bus, pci_bus);
@@ -271,8 +266,7 @@ static void pc_init1(MachineState *machine)
}
}
- pc_cmos_init(below_4g_mem_size, above_4g_mem_size, machine->boot_order,
- machine, idebus[0], idebus[1], rtc_state);
+ pc_cmos_init(pcms, idebus[0], idebus[1], rtc_state);
if (pci_enabled && usb_enabled()) {
pci_create_simple(pci_bus, piix3_devfn + 2, "piix3-usb-uhci");
@@ -286,13 +280,13 @@ static void pc_init1(MachineState *machine)
/* TODO: Populate SPD eeprom data. */
smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100,
gsi[9], smi_irq,
- pc_machine_is_smm_enabled(pc_machine),
+ pc_machine_is_smm_enabled(pcms),
&piix4_pm);
smbus_eeprom_init(smbus, 8, NULL, 0);
object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP,
TYPE_HOTPLUG_HANDLER,
- (Object **)&pc_machine->acpi_dev,
+ (Object **)&pcms->acpi_dev,
object_property_allow_set_link,
OBJ_PROP_LINK_UNREF_ON_RELEASE, &error_abort);
object_property_set_link(OBJECT(machine), OBJECT(piix4_pm),
@@ -319,24 +313,6 @@ static void pc_compat_2_2(MachineState *machine)
{
pc_compat_2_3(machine);
rsdp_in_ram = false;
- x86_cpu_compat_set_features("kvm64", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("kvm32", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("Conroe", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("Penryn", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("Nehalem", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("Westmere", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("SandyBridge", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("Haswell", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("Broadwell", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("Opteron_G1", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("Opteron_G2", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("Opteron_G3", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("Opteron_G4", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("Opteron_G5", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("Haswell", FEAT_1_ECX, 0, CPUID_EXT_F16C);
- x86_cpu_compat_set_features("Haswell", FEAT_1_ECX, 0, CPUID_EXT_RDRAND);
- x86_cpu_compat_set_features("Broadwell", FEAT_1_ECX, 0, CPUID_EXT_F16C);
- x86_cpu_compat_set_features("Broadwell", FEAT_1_ECX, 0, CPUID_EXT_RDRAND);
machine->suppress_vmdesc = true;
}
@@ -346,8 +322,6 @@ static void pc_compat_2_1(MachineState *machine)
pc_compat_2_2(machine);
smbios_uuid_encoded = false;
- x86_cpu_compat_set_features("coreduo", FEAT_1_ECX, CPUID_EXT_VMX, 0);
- x86_cpu_compat_set_features("core2duo", FEAT_1_ECX, CPUID_EXT_VMX, 0);
x86_cpu_compat_kvm_no_autodisable(FEAT_8000_0001_ECX, CPUID_EXT3_SVM);
pcms->enforce_aligned_dimm = false;
}
@@ -402,8 +376,6 @@ static void pc_compat_1_5(MachineState *machine)
static void pc_compat_1_4(MachineState *machine)
{
pc_compat_1_5(machine);
- x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE);
- x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ);
}
static void pc_compat_1_3(MachineState *machine)
@@ -471,7 +443,6 @@ static void pc_xen_hvm_init(MachineState *machine)
static void pc_i440fx_machine_options(MachineClass *m)
{
- pc_default_machine_options(m);
m->family = "pc_piix";
m->desc = "Standard PC (i440FX + PIIX, 1996)";
m->hot_add_cpu = pc_hot_add_cpu;
@@ -909,7 +880,6 @@ DEFINE_I440FX_MACHINE(v0_10, "pc-0.10", pc_compat_0_13,
static void isapc_machine_options(MachineClass *m)
{
- pc_common_machine_options(m);
m->desc = "ISA-only PC";
m->max_cpus = 1;
}
@@ -921,7 +891,6 @@ DEFINE_PC_MACHINE(isapc, "isapc", pc_init_isa,
#ifdef CONFIG_XEN
static void xenfv_machine_options(MachineClass *m)
{
- pc_common_machine_options(m);
m->desc = "Xen Fully-virtualized PC";
m->max_cpus = HVM_MAX_VCPUS;
m->default_machine_opts = "accel=xen";
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 974aead5a9..c07d65bc46 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -39,7 +39,7 @@
#include "hw/pci-host/q35.h"
#include "exec/address-spaces.h"
#include "hw/i386/ich9.h"
-#include "hw/i386/smbios.h"
+#include "hw/smbios/smbios.h"
#include "hw/ide/pci.h"
#include "hw/ide/ahci.h"
#include "hw/usb.h"
@@ -65,8 +65,7 @@ static bool has_reserved_memory = true;
/* PC hardware initialisation */
static void pc_q35_init(MachineState *machine)
{
- PCMachineState *pc_machine = PC_MACHINE(machine);
- ram_addr_t below_4g_mem_size, above_4g_mem_size;
+ PCMachineState *pcms = PC_MACHINE(machine);
Q35PCIHost *q35_host;
PCIHostState *phb;
PCIBus *host_bus;
@@ -108,25 +107,26 @@ static void pc_q35_init(MachineState *machine)
/* Handle the machine opt max-ram-below-4g. It is basically doing
* min(qemu limit, user limit).
*/
- if (lowmem > pc_machine->max_ram_below_4g) {
- lowmem = pc_machine->max_ram_below_4g;
+ if (lowmem > pcms->max_ram_below_4g) {
+ lowmem = pcms->max_ram_below_4g;
if (machine->ram_size - lowmem > lowmem &&
lowmem & ((1ULL << 30) - 1)) {
error_report("Warning: Large machine and max_ram_below_4g(%"PRIu64
") not a multiple of 1G; possible bad performance.",
- pc_machine->max_ram_below_4g);
+ pcms->max_ram_below_4g);
}
}
if (machine->ram_size >= lowmem) {
- above_4g_mem_size = machine->ram_size - lowmem;
- below_4g_mem_size = lowmem;
+ pcms->above_4g_mem_size = machine->ram_size - lowmem;
+ pcms->below_4g_mem_size = lowmem;
} else {
- above_4g_mem_size = 0;
- below_4g_mem_size = machine->ram_size;
+ pcms->above_4g_mem_size = 0;
+ pcms->below_4g_mem_size = machine->ram_size;
}
- if (xen_enabled() && xen_hvm_init(&below_4g_mem_size, &above_4g_mem_size,
+ if (xen_enabled() && xen_hvm_init(&pcms->below_4g_mem_size,
+ &pcms->above_4g_mem_size,
&ram_memory) != 0) {
fprintf(stderr, "xen hardware virtual machine initialisation failed\n");
exit(1);
@@ -151,7 +151,7 @@ static void pc_q35_init(MachineState *machine)
rom_memory = get_system_memory();
}
- guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size);
+ guest_info = pc_guest_info_init(pcms);
guest_info->isapc_ram_fw = false;
guest_info->has_acpi_build = has_acpi_build;
guest_info->has_reserved_memory = has_reserved_memory;
@@ -170,8 +170,7 @@ static void pc_q35_init(MachineState *machine)
/* allocate ram and load rom/bios */
if (!xen_enabled()) {
- pc_memory_init(machine, get_system_memory(),
- below_4g_mem_size, above_4g_mem_size,
+ pc_memory_init(pcms, get_system_memory(),
rom_memory, &ram_memory, guest_info);
}
@@ -193,8 +192,8 @@ static void pc_q35_init(MachineState *machine)
q35_host->mch.pci_address_space = pci_memory;
q35_host->mch.system_memory = get_system_memory();
q35_host->mch.address_space_io = get_system_io();
- q35_host->mch.below_4g_mem_size = below_4g_mem_size;
- q35_host->mch.above_4g_mem_size = above_4g_mem_size;
+ q35_host->mch.below_4g_mem_size = pcms->below_4g_mem_size;
+ q35_host->mch.above_4g_mem_size = pcms->above_4g_mem_size;
q35_host->mch.guest_info = guest_info;
/* pci */
qdev_init_nofail(DEVICE(q35_host));
@@ -207,7 +206,7 @@ static void pc_q35_init(MachineState *machine)
object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP,
TYPE_HOTPLUG_HANDLER,
- (Object **)&pc_machine->acpi_dev,
+ (Object **)&pcms->acpi_dev,
object_property_allow_set_link,
OBJ_PROP_LINK_UNREF_ON_RELEASE, &error_abort);
object_property_set_link(OBJECT(machine), OBJECT(lpc),
@@ -242,17 +241,17 @@ static void pc_q35_init(MachineState *machine)
pc_register_ferr_irq(gsi[13]);
- assert(pc_machine->vmport != ON_OFF_AUTO_MAX);
- if (pc_machine->vmport == ON_OFF_AUTO_AUTO) {
- pc_machine->vmport = xen_enabled() ? ON_OFF_AUTO_OFF : ON_OFF_AUTO_ON;
+ assert(pcms->vmport != ON_OFF_AUTO_MAX);
+ if (pcms->vmport == ON_OFF_AUTO_AUTO) {
+ pcms->vmport = xen_enabled() ? ON_OFF_AUTO_OFF : ON_OFF_AUTO_ON;
}
/* init basic PC hardware */
pc_basic_device_init(isa_bus, gsi, &rtc_state, !mc->no_floppy,
- (pc_machine->vmport != ON_OFF_AUTO_ON), 0xff0104);
+ (pcms->vmport != ON_OFF_AUTO_ON), 0xff0104);
/* connect pm stuff to lpc */
- ich9_lpc_pm_init(lpc, pc_machine_is_smm_enabled(pc_machine), !mc->no_tco);
+ ich9_lpc_pm_init(lpc, pc_machine_is_smm_enabled(pcms), !mc->no_tco);
/* ahci and SATA device, for q35 1 ahci controller is built-in */
ahci = pci_create_simple_multifunction(host_bus,
@@ -276,8 +275,7 @@ static void pc_q35_init(MachineState *machine)
0xb100),
8, NULL, 0);
- pc_cmos_init(below_4g_mem_size, above_4g_mem_size, machine->boot_order,
- machine, idebus[0], idebus[1], rtc_state);
+ pc_cmos_init(pcms, idebus[0], idebus[1], rtc_state);
/* the rest devices to which pci devfn is automatically assigned */
pc_vga_init(isa_bus, host_bus);
@@ -302,24 +300,6 @@ static void pc_compat_2_2(MachineState *machine)
{
pc_compat_2_3(machine);
rsdp_in_ram = false;
- x86_cpu_compat_set_features("kvm64", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("kvm32", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("Conroe", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("Penryn", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("Nehalem", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("Westmere", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("SandyBridge", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("Haswell", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("Broadwell", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("Opteron_G1", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("Opteron_G2", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("Opteron_G3", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("Opteron_G4", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("Opteron_G5", FEAT_1_EDX, 0, CPUID_VME);
- x86_cpu_compat_set_features("Haswell", FEAT_1_ECX, 0, CPUID_EXT_F16C);
- x86_cpu_compat_set_features("Haswell", FEAT_1_ECX, 0, CPUID_EXT_RDRAND);
- x86_cpu_compat_set_features("Broadwell", FEAT_1_ECX, 0, CPUID_EXT_F16C);
- x86_cpu_compat_set_features("Broadwell", FEAT_1_ECX, 0, CPUID_EXT_RDRAND);
machine->suppress_vmdesc = true;
}
@@ -330,8 +310,6 @@ static void pc_compat_2_1(MachineState *machine)
pc_compat_2_2(machine);
pcms->enforce_aligned_dimm = false;
smbios_uuid_encoded = false;
- x86_cpu_compat_set_features("coreduo", FEAT_1_ECX, CPUID_EXT_VMX, 0);
- x86_cpu_compat_set_features("core2duo", FEAT_1_ECX, CPUID_EXT_VMX, 0);
x86_cpu_compat_kvm_no_autodisable(FEAT_8000_0001_ECX, CPUID_EXT3_SVM);
}
@@ -367,8 +345,6 @@ static void pc_compat_1_5(MachineState *machine)
static void pc_compat_1_4(MachineState *machine)
{
pc_compat_1_5(machine);
- x86_cpu_compat_set_features("n270", FEAT_1_ECX, 0, CPUID_EXT_MOVBE);
- x86_cpu_compat_set_features("Westmere", FEAT_1_ECX, 0, CPUID_EXT_PCLMULQDQ);
}
#define DEFINE_Q35_MACHINE(suffix, name, compatfn, optionfn) \
@@ -385,7 +361,6 @@ static void pc_compat_1_4(MachineState *machine)
static void pc_q35_machine_options(MachineClass *m)
{
- pc_default_machine_options(m);
m->family = "pc_q35";
m->desc = "Standard PC (Q35 + ICH9, 2009)";
m->hot_add_cpu = pc_hot_add_cpu;
diff --git a/hw/i386/q35-acpi-dsdt.dsl b/hw/i386/q35-acpi-dsdt.dsl
index 16eaca3fae..7be7b37b87 100644
--- a/hw/i386/q35-acpi-dsdt.dsl
+++ b/hw/i386/q35-acpi-dsdt.dsl
@@ -22,6 +22,7 @@
* Based on acpi-dsdt.dsl, but heavily modified for q35 chipset.
*/
+
ACPI_EXTRACT_ALL_CODE Q35AcpiDsdtAmlCode
DefinitionBlock (
diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h
index 68d5074b33..79a463d93c 100644
--- a/hw/ide/ahci.h
+++ b/hw/ide/ahci.h
@@ -127,7 +127,7 @@
#define PORT_CMD_SPIN_UP (1 << 1) /* Spin up device */
#define PORT_CMD_START (1 << 0) /* Enable port DMA engine */
-#define PORT_CMD_ICC_MASK (0xf << 28) /* i/f ICC state mask */
+#define PORT_CMD_ICC_MASK (0xfU << 28) /* i/f ICC state mask */
#define PORT_CMD_ICC_ACTIVE (0x1 << 28) /* Put i/f in active state */
#define PORT_CMD_ICC_PARTIAL (0x2 << 28) /* Put i/f in partial state */
#define PORT_CMD_ICC_SLUMBER (0x6 << 28) /* Put i/f in slumber state */
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index a55a479da6..66ac2baa94 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -208,6 +208,33 @@ static void pmac_dma_write(BlockBackend *blk,
cb, io);
}
+static void pmac_dma_trim(BlockBackend *blk,
+ int64_t offset, int bytes,
+ void (*cb)(void *opaque, int ret), void *opaque)
+{
+ DBDMA_io *io = opaque;
+ MACIOIDEState *m = io->opaque;
+ IDEState *s = idebus_active_if(&m->bus);
+ dma_addr_t dma_addr, dma_len;
+ void *mem;
+
+ qemu_iovec_destroy(&io->iov);
+ qemu_iovec_init(&io->iov, io->len / MACIO_PAGE_SIZE + 1);
+
+ dma_addr = io->addr;
+ dma_len = io->len;
+ mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len,
+ DMA_DIRECTION_TO_DEVICE);
+
+ qemu_iovec_add(&io->iov, mem, io->len);
+ s->io_buffer_size -= io->len;
+ s->io_buffer_index += io->len;
+ io->len = 0;
+
+ m->aiocb = ide_issue_trim(blk, (offset >> 9), &io->iov, (bytes >> 9),
+ cb, io);
+}
+
static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
{
DBDMA_io *io = opaque;
@@ -313,6 +340,7 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
pmac_dma_write(s->blk, offset, io->len, pmac_ide_transfer_cb, io);
break;
case IDE_DMA_TRIM:
+ pmac_dma_trim(s->blk, offset, io->len, pmac_ide_transfer_cb, io);
break;
}
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index adb664957c..5a26c86a8a 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -169,6 +169,7 @@ int pci_piix3_xen_ide_unplug(DeviceState *dev)
PCIIDEState *pci_ide;
DriveInfo *di;
int i;
+ IDEDevice *idedev;
pci_ide = PCI_IDE(dev);
@@ -181,6 +182,12 @@ int pci_piix3_xen_ide_unplug(DeviceState *dev)
blk_detach_dev(blk, ds);
}
pci_ide->bus[di->bus].ifs[di->unit].blk = NULL;
+ if (!(i % 2)) {
+ idedev = pci_ide->bus[di->bus].master;
+ } else {
+ idedev = pci_ide->bus[di->bus].slave;
+ }
+ idedev->conf.blk = NULL;
blk_unref(blk);
}
}
diff --git a/hw/intc/arm_gic.c b/hw/intc/arm_gic.c
index 454bfd7df5..a8c5d19448 100644
--- a/hw/intc/arm_gic.c
+++ b/hw/intc/arm_gic.c
@@ -922,12 +922,6 @@ static MemTxResult gic_dist_write(void *opaque, hwaddr offset, uint64_t data,
}
}
-static const MemoryRegionOps gic_dist_ops = {
- .read_with_attrs = gic_dist_read,
- .write_with_attrs = gic_dist_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
-};
-
static MemTxResult gic_cpu_read(GICState *s, int cpu, int offset,
uint64_t *data, MemTxAttrs attrs)
{
@@ -1056,10 +1050,17 @@ static MemTxResult gic_do_cpu_write(void *opaque, hwaddr addr,
return gic_cpu_write(s, id, addr, value, attrs);
}
-static const MemoryRegionOps gic_thiscpu_ops = {
- .read_with_attrs = gic_thiscpu_read,
- .write_with_attrs = gic_thiscpu_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
+static const MemoryRegionOps gic_ops[2] = {
+ {
+ .read_with_attrs = gic_dist_read,
+ .write_with_attrs = gic_dist_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ },
+ {
+ .read_with_attrs = gic_thiscpu_read,
+ .write_with_attrs = gic_thiscpu_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ }
};
static const MemoryRegionOps gic_cpu_ops = {
@@ -1068,31 +1069,10 @@ static const MemoryRegionOps gic_cpu_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
+/* This function is used by nvic model */
void gic_init_irqs_and_distributor(GICState *s)
{
- SysBusDevice *sbd = SYS_BUS_DEVICE(s);
- int i;
-
- i = s->num_irq - GIC_INTERNAL;
- /* For the GIC, also expose incoming GPIO lines for PPIs for each CPU.
- * GPIO array layout is thus:
- * [0..N-1] SPIs
- * [N..N+31] PPIs for CPU 0
- * [N+32..N+63] PPIs for CPU 1
- * ...
- */
- if (s->revision != REV_NVIC) {
- i += (GIC_INTERNAL * s->num_cpu);
- }
- qdev_init_gpio_in(DEVICE(s), gic_set_irq, i);
- for (i = 0; i < NUM_CPU(s); i++) {
- sysbus_init_irq(sbd, &s->parent_irq[i]);
- }
- for (i = 0; i < NUM_CPU(s); i++) {
- sysbus_init_irq(sbd, &s->parent_fiq[i]);
- }
- memory_region_init_io(&s->iomem, OBJECT(s), &gic_dist_ops, s,
- "gic_dist", 0x1000);
+ gic_init_irqs_and_mmio(s, gic_set_irq, gic_ops);
}
static void arm_gic_realize(DeviceState *dev, Error **errp)
@@ -1110,28 +1090,22 @@ static void arm_gic_realize(DeviceState *dev, Error **errp)
return;
}
- gic_init_irqs_and_distributor(s);
+ /* This creates distributor and main CPU interface (s->cpuiomem[0]) */
+ gic_init_irqs_and_mmio(s, gic_set_irq, gic_ops);
- /* Memory regions for the CPU interfaces (NVIC doesn't have these):
- * a region for "CPU interface for this core", then a region for
- * "CPU interface for core 0", "for core 1", ...
+ /* Extra core-specific regions for the CPU interfaces. This is
+ * necessary for "franken-GIC" implementations, for example on
+ * Exynos 4.
* NB that the memory region size of 0x100 applies for the 11MPCore
* and also cores following the GIC v1 spec (ie A9).
* GIC v2 defines a larger memory region (0x1000) so this will need
* to be extended when we implement A15.
*/
- memory_region_init_io(&s->cpuiomem[0], OBJECT(s), &gic_thiscpu_ops, s,
- "gic_cpu", 0x100);
for (i = 0; i < NUM_CPU(s); i++) {
s->backref[i] = s;
memory_region_init_io(&s->cpuiomem[i+1], OBJECT(s), &gic_cpu_ops,
&s->backref[i], "gic_cpu", 0x100);
- }
- /* Distributor */
- sysbus_init_mmio(sbd, &s->iomem);
- /* cpu interfaces (one for "current cpu" plus one per cpu) */
- for (i = 0; i <= NUM_CPU(s); i++) {
- sysbus_init_mmio(sbd, &s->cpuiomem[i]);
+ sysbus_init_mmio(sbd, &s->cpuiomem[i+1]);
}
}
diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c
index a64d0714ea..fe64b51cff 100644
--- a/hw/intc/arm_gic_common.c
+++ b/hw/intc/arm_gic_common.c
@@ -84,6 +84,47 @@ static const VMStateDescription vmstate_gic = {
}
};
+void gic_init_irqs_and_mmio(GICState *s, qemu_irq_handler handler,
+ const MemoryRegionOps *ops)
+{
+ SysBusDevice *sbd = SYS_BUS_DEVICE(s);
+ int i = s->num_irq - GIC_INTERNAL;
+
+ /* For the GIC, also expose incoming GPIO lines for PPIs for each CPU.
+ * GPIO array layout is thus:
+ * [0..N-1] SPIs
+ * [N..N+31] PPIs for CPU 0
+ * [N+32..N+63] PPIs for CPU 1
+ * ...
+ */
+ if (s->revision != REV_NVIC) {
+ i += (GIC_INTERNAL * s->num_cpu);
+ }
+ qdev_init_gpio_in(DEVICE(s), handler, i);
+
+ for (i = 0; i < s->num_cpu; i++) {
+ sysbus_init_irq(sbd, &s->parent_irq[i]);
+ }
+ for (i = 0; i < s->num_cpu; i++) {
+ sysbus_init_irq(sbd, &s->parent_fiq[i]);
+ }
+
+ /* Distributor */
+ memory_region_init_io(&s->iomem, OBJECT(s), ops, s, "gic_dist", 0x1000);
+ sysbus_init_mmio(sbd, &s->iomem);
+
+ if (s->revision != REV_NVIC) {
+ /* This is the main CPU interface "for this core". It is always
+ * present because it is required by both software emulation and KVM.
+ * NVIC is not handled here because its CPU interface is different,
+ * neither it can use KVM.
+ */
+ memory_region_init_io(&s->cpuiomem[0], OBJECT(s), ops ? &ops[1] : NULL,
+ s, "gic_cpu", s->revision == 2 ? 0x1000 : 0x100);
+ sysbus_init_mmio(sbd, &s->cpuiomem[0]);
+ }
+}
+
static void arm_gic_common_realize(DeviceState *dev, Error **errp)
{
GICState *s = ARM_GIC_COMMON(dev);
diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c
index f56bff1afb..e5d0f67186 100644
--- a/hw/intc/arm_gic_kvm.c
+++ b/hw/intc/arm_gic_kvm.c
@@ -543,7 +543,6 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
{
int i;
GICState *s = KVM_ARM_GIC(dev);
- SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
KVMARMGICClass *kgc = KVM_ARM_GIC_GET_CLASS(s);
Error *local_err = NULL;
int ret;
@@ -560,32 +559,13 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
return;
}
- i = s->num_irq - GIC_INTERNAL;
- /* For the GIC, also expose incoming GPIO lines for PPIs for each CPU.
- * GPIO array layout is thus:
- * [0..N-1] SPIs
- * [N..N+31] PPIs for CPU 0
- * [N+32..N+63] PPIs for CPU 1
- * ...
- */
- i += (GIC_INTERNAL * s->num_cpu);
- qdev_init_gpio_in(dev, kvm_arm_gic_set_irq, i);
+ gic_init_irqs_and_mmio(s, kvm_arm_gic_set_irq, NULL);
for (i = 0; i < s->num_irq - GIC_INTERNAL; i++) {
qemu_irq irq = qdev_get_gpio_in(dev, i);
kvm_irqchip_set_qemuirq_gsi(kvm_state, irq, i);
}
- /* We never use our outbound IRQ/FIQ lines but provide them so that
- * we maintain the same interface as the non-KVM GIC.
- */
- for (i = 0; i < s->num_cpu; i++) {
- sysbus_init_irq(sbd, &s->parent_irq[i]);
- }
- for (i = 0; i < s->num_cpu; i++) {
- sysbus_init_irq(sbd, &s->parent_fiq[i]);
- }
-
/* Try to create the device via the device control API */
s->dev_fd = -1;
ret = kvm_create_device(kvm_state, KVM_DEV_TYPE_ARM_VGIC_V2, false);
@@ -609,9 +589,6 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
}
/* Distributor */
- memory_region_init_reservation(&s->iomem, OBJECT(s),
- "kvm-gic_dist", 0x1000);
- sysbus_init_mmio(sbd, &s->iomem);
kvm_arm_register_device(&s->iomem,
(KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT)
| KVM_VGIC_V2_ADDR_TYPE_DIST,
@@ -622,9 +599,6 @@ static void kvm_arm_gic_realize(DeviceState *dev, Error **errp)
* provide the "interface for core #N" memory regions, because
* cores with a VGIC don't have those.
*/
- memory_region_init_reservation(&s->cpuiomem[0], OBJECT(s),
- "kvm-gic_cpu", 0x1000);
- sysbus_init_mmio(sbd, &s->cpuiomem[0]);
kvm_arm_register_device(&s->cpuiomem[0],
(KVM_ARM_DEVICE_VGIC_V2 << KVM_ARM_DEVICE_ID_SHIFT)
| KVM_VGIC_V2_ADDR_TYPE_CPU,
diff --git a/hw/intc/imx_avic.c b/hw/intc/imx_avic.c
index e48f66c8fa..96c376b6af 100644
--- a/hw/intc/imx_avic.c
+++ b/hw/intc/imx_avic.c
@@ -7,6 +7,7 @@
* Copyright (c) 2008 OKL
* Copyright (c) 2011 NICTA Pty Ltd
* Originally written by Hans Jiang
+ * Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
*
* This code is licensed under the GPL version 2 or later. See
* the COPYING file in the top-level directory.
@@ -14,16 +15,14 @@
* TODO: implement vectors.
*/
-#include "hw/hw.h"
-#include "hw/sysbus.h"
-#include "qemu/host-utils.h"
+#include "hw/intc/imx_avic.h"
#define DEBUG_INT 1
#undef DEBUG_INT /* comment out for debugging */
#ifdef DEBUG_INT
#define DPRINTF(fmt, args...) \
-do { printf("imx_avic: " fmt , ##args); } while (0)
+do { printf("%s: " fmt , TYPE_IMX_AVIC, ##args); } while (0)
#else
#define DPRINTF(fmt, args...) do {} while (0)
#endif
@@ -35,46 +34,13 @@ do { printf("imx_avic: " fmt , ##args); } while (0)
#define DEBUG_IMPLEMENTATION 1
#if DEBUG_IMPLEMENTATION
# define IPRINTF(fmt, args...) \
- do { fprintf(stderr, "imx_avic: " fmt, ##args); } while (0)
+ do { fprintf(stderr, "%s: " fmt, TYPE_IMX_AVIC, ##args); } while (0)
#else
# define IPRINTF(fmt, args...) do {} while (0)
#endif
-#define IMX_AVIC_NUM_IRQS 64
-
-/* Interrupt Control Bits */
-#define ABFLAG (1<<25)
-#define ABFEN (1<<24)
-#define NIDIS (1<<22) /* Normal Interrupt disable */
-#define FIDIS (1<<21) /* Fast interrupt disable */
-#define NIAD (1<<20) /* Normal Interrupt Arbiter Rise ARM level */
-#define FIAD (1<<19) /* Fast Interrupt Arbiter Rise ARM level */
-#define NM (1<<18) /* Normal interrupt mode */
-
-
-#define PRIO_PER_WORD (sizeof(uint32_t) * 8 / 4)
-#define PRIO_WORDS (IMX_AVIC_NUM_IRQS/PRIO_PER_WORD)
-
-#define TYPE_IMX_AVIC "imx_avic"
-#define IMX_AVIC(obj) \
- OBJECT_CHECK(IMXAVICState, (obj), TYPE_IMX_AVIC)
-
-typedef struct IMXAVICState {
- SysBusDevice parent_obj;
-
- MemoryRegion iomem;
- uint64_t pending;
- uint64_t enabled;
- uint64_t is_fiq;
- uint32_t intcntl;
- uint32_t intmask;
- qemu_irq irq;
- qemu_irq fiq;
- uint32_t prio[PRIO_WORDS]; /* Priorities are 4-bits each */
-} IMXAVICState;
-
static const VMStateDescription vmstate_imx_avic = {
- .name = "imx-avic",
+ .name = TYPE_IMX_AVIC,
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
@@ -88,8 +54,6 @@ static const VMStateDescription vmstate_imx_avic = {
},
};
-
-
static inline int imx_avic_prio(IMXAVICState *s, int irq)
{
uint32_t word = irq / PRIO_PER_WORD;
@@ -249,7 +213,7 @@ static uint64_t imx_avic_read(void *opaque,
return 0x4;
default:
- IPRINTF("imx_avic_read: Bad offset 0x%x\n", (int)offset);
+ IPRINTF("%s: Bad offset 0x%x\n", __func__, (int)offset);
return 0;
}
}
@@ -261,12 +225,12 @@ static void imx_avic_write(void *opaque, hwaddr offset,
/* Vector Registers not yet supported */
if (offset >= 0x100 && offset <= 0x2fc) {
- IPRINTF("imx_avic_write to vector register %d ignored\n",
+ IPRINTF("%s to vector register %d ignored\n", __func__,
(unsigned int)((offset - 0x100) >> 2));
return;
}
- DPRINTF("imx_avic_write(0x%x) = %x\n",
+ DPRINTF("%s(0x%x) = %x\n", __func__,
(unsigned int)offset>>2, (unsigned int)val);
switch (offset >> 2) {
case 0: /* Interrupt Control Register, INTCNTL */
@@ -341,7 +305,7 @@ static void imx_avic_write(void *opaque, hwaddr offset,
return;
default:
- IPRINTF("imx_avic_write: Bad offset %x\n", (int)offset);
+ IPRINTF("%s: Bad offset %x\n", __func__, (int)offset);
}
imx_avic_update(s);
}
@@ -370,7 +334,7 @@ static int imx_avic_init(SysBusDevice *sbd)
IMXAVICState *s = IMX_AVIC(dev);
memory_region_init_io(&s->iomem, OBJECT(s), &imx_avic_ops, s,
- "imx_avic", 0x1000);
+ TYPE_IMX_AVIC, 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
qdev_init_gpio_in(dev, imx_avic_set_irq, IMX_AVIC_NUM_IRQS);
diff --git a/hw/misc/imx_ccm.c b/hw/misc/imx_ccm.c
index 0920288634..2e19dbb1bb 100644
--- a/hw/misc/imx_ccm.c
+++ b/hw/misc/imx_ccm.c
@@ -2,6 +2,7 @@
* IMX31 Clock Control Module
*
* Copyright (C) 2012 NICTA
+ * Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
@@ -10,51 +11,23 @@
* the CCM.
*/
-#include "hw/hw.h"
-#include "hw/sysbus.h"
-#include "sysemu/sysemu.h"
-#include "hw/arm/imx.h"
+#include "hw/misc/imx_ccm.h"
#define CKIH_FREQ 26000000 /* 26MHz crystal input */
#define CKIL_FREQ 32768 /* nominal 32khz clock */
-
//#define DEBUG_CCM 1
#ifdef DEBUG_CCM
#define DPRINTF(fmt, args...) \
-do { printf("imx_ccm: " fmt , ##args); } while (0)
+do { printf("%s: " fmt , TYPE_IMX_CCM, ##args); } while (0)
#else
#define DPRINTF(fmt, args...) do {} while (0)
#endif
static int imx_ccm_post_load(void *opaque, int version_id);
-#define TYPE_IMX_CCM "imx_ccm"
-#define IMX_CCM(obj) OBJECT_CHECK(IMXCCMState, (obj), TYPE_IMX_CCM)
-
-typedef struct IMXCCMState {
- SysBusDevice parent_obj;
-
- MemoryRegion iomem;
-
- uint32_t ccmr;
- uint32_t pdr0;
- uint32_t pdr1;
- uint32_t mpctl;
- uint32_t spctl;
- uint32_t cgr[3];
- uint32_t pmcr0;
- uint32_t pmcr1;
-
- /* Frequencies precalculated on register changes */
- uint32_t pll_refclk_freq;
- uint32_t mcu_clk_freq;
- uint32_t hsp_clk_freq;
- uint32_t ipg_clk_freq;
-} IMXCCMState;
-
static const VMStateDescription vmstate_imx_ccm = {
- .name = "imx-ccm",
+ .name = TYPE_IMX_CCM,
.version_id = 1,
.minimum_version_id = 1,
.fields = (VMStateField[]) {
@@ -72,44 +45,6 @@ static const VMStateDescription vmstate_imx_ccm = {
.post_load = imx_ccm_post_load,
};
-/* CCMR */
-#define CCMR_FPME (1<<0)
-#define CCMR_MPE (1<<3)
-#define CCMR_MDS (1<<7)
-#define CCMR_FPMF (1<<26)
-#define CCMR_PRCS (3<<1)
-
-/* PDR0 */
-#define PDR0_MCU_PODF_SHIFT (0)
-#define PDR0_MCU_PODF_MASK (0x7)
-#define PDR0_MAX_PODF_SHIFT (3)
-#define PDR0_MAX_PODF_MASK (0x7)
-#define PDR0_IPG_PODF_SHIFT (6)
-#define PDR0_IPG_PODF_MASK (0x3)
-#define PDR0_NFC_PODF_SHIFT (8)
-#define PDR0_NFC_PODF_MASK (0x7)
-#define PDR0_HSP_PODF_SHIFT (11)
-#define PDR0_HSP_PODF_MASK (0x7)
-#define PDR0_PER_PODF_SHIFT (16)
-#define PDR0_PER_PODF_MASK (0x1f)
-#define PDR0_CSI_PODF_SHIFT (23)
-#define PDR0_CSI_PODF_MASK (0x1ff)
-
-#define EXTRACT(value, name) (((value) >> PDR0_##name##_PODF_SHIFT) \
- & PDR0_##name##_PODF_MASK)
-#define INSERT(value, name) (((value) & PDR0_##name##_PODF_MASK) << \
- PDR0_##name##_PODF_SHIFT)
-/* PLL control registers */
-#define PD(v) (((v) >> 26) & 0xf)
-#define MFD(v) (((v) >> 16) & 0x3ff)
-#define MFI(v) (((v) >> 10) & 0xf);
-#define MFN(v) ((v) & 0x3ff)
-
-#define PLL_PD(x) (((x) & 0xf) << 26)
-#define PLL_MFD(x) (((x) & 0x3ff) << 16)
-#define PLL_MFI(x) (((x) & 0xf) << 10)
-#define PLL_MFN(x) (((x) & 0x3ff) << 0)
-
uint32_t imx_clock_frequency(DeviceState *dev, IMXClk clock)
{
IMXCCMState *s = IMX_CCM(dev);
@@ -174,7 +109,7 @@ static void update_clocks(IMXCCMState *s)
s->hsp_clk_freq = s->mcu_clk_freq / (1 + EXTRACT(s->pdr0, HSP));
s->ipg_clk_freq = s->hsp_clk_freq / (1 + EXTRACT(s->pdr0, IPG));
- DPRINTF("Clocks: mcu %uMHz, HSP %uMHz, IPG %uHz\n",
+ DPRINTF("%s: mcu %uMHz, HSP %uMHz, IPG %uHz\n", __func__,
s->mcu_clk_freq / 1000000,
s->hsp_clk_freq / 1000000,
s->ipg_clk_freq);
@@ -200,7 +135,7 @@ static uint64_t imx_ccm_read(void *opaque, hwaddr offset,
{
IMXCCMState *s = (IMXCCMState *)opaque;
- DPRINTF("read(offset=%x)", offset >> 2);
+ DPRINTF("%s(offset=%x)", __func__, offset >> 2);
switch (offset >> 2) {
case 0: /* CCMR */
DPRINTF(" ccmr = 0x%x\n", s->ccmr);
@@ -241,7 +176,7 @@ static void imx_ccm_write(void *opaque, hwaddr offset,
{
IMXCCMState *s = (IMXCCMState *)opaque;
- DPRINTF("write(offset=%x, value = %x)\n",
+ DPRINTF("%s(offset=%x, value = %x)\n", __func__,
offset >> 2, (unsigned int)value);
switch (offset >> 2) {
case 0:
@@ -286,7 +221,7 @@ static int imx_ccm_init(SysBusDevice *dev)
IMXCCMState *s = IMX_CCM(dev);
memory_region_init_io(&s->iomem, OBJECT(dev), &imx_ccm_ops, s,
- "imx_ccm", 0x1000);
+ TYPE_IMX_CCM, 0x1000);
sysbus_init_mmio(dev, &s->iomem);
return 0;
diff --git a/hw/net/rtl8139.c b/hw/net/rtl8139.c
index e0db4727ae..edbb61ccf3 100644
--- a/hw/net/rtl8139.c
+++ b/hw/net/rtl8139.c
@@ -2150,6 +2150,11 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
{
DPRINTF("+++ C+ mode offloaded task checksum\n");
+ /* Large enough for Ethernet and IP headers? */
+ if (saved_size < ETH_HLEN + sizeof(ip_header)) {
+ goto skip_offload;
+ }
+
/* ip packet header */
ip_header *ip = NULL;
int hlen = 0;
@@ -2160,223 +2165,235 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
size_t eth_payload_len = 0;
int proto = be16_to_cpu(*(uint16_t *)(saved_buffer + 12));
- if (proto == ETH_P_IP)
+ if (proto != ETH_P_IP)
{
- DPRINTF("+++ C+ mode has IP packet\n");
-
- /* not aligned */
- eth_payload_data = saved_buffer + ETH_HLEN;
- eth_payload_len = saved_size - ETH_HLEN;
-
- ip = (ip_header*)eth_payload_data;
-
- if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {
- DPRINTF("+++ C+ mode packet has bad IP version %d "
- "expected %d\n", IP_HEADER_VERSION(ip),
- IP_HEADER_VERSION_4);
- ip = NULL;
- } else {
- hlen = IP_HEADER_LENGTH(ip);
- ip_protocol = ip->ip_p;
- ip_data_len = be16_to_cpu(ip->ip_len) - hlen;
- }
+ goto skip_offload;
+ }
+
+ DPRINTF("+++ C+ mode has IP packet\n");
+
+ /* not aligned */
+ eth_payload_data = saved_buffer + ETH_HLEN;
+ eth_payload_len = saved_size - ETH_HLEN;
+
+ ip = (ip_header*)eth_payload_data;
+
+ if (IP_HEADER_VERSION(ip) != IP_HEADER_VERSION_4) {
+ DPRINTF("+++ C+ mode packet has bad IP version %d "
+ "expected %d\n", IP_HEADER_VERSION(ip),
+ IP_HEADER_VERSION_4);
+ goto skip_offload;
}
- if (ip)
+ hlen = IP_HEADER_LENGTH(ip);
+ if (hlen < sizeof(ip_header) || hlen > eth_payload_len) {
+ goto skip_offload;
+ }
+
+ ip_protocol = ip->ip_p;
+
+ ip_data_len = be16_to_cpu(ip->ip_len);
+ if (ip_data_len < hlen || ip_data_len > eth_payload_len) {
+ goto skip_offload;
+ }
+ ip_data_len -= hlen;
+
+ if (txdw0 & CP_TX_IPCS)
{
- if (txdw0 & CP_TX_IPCS)
- {
- DPRINTF("+++ C+ mode need IP checksum\n");
+ DPRINTF("+++ C+ mode need IP checksum\n");
- if (hlen<sizeof(ip_header) || hlen>eth_payload_len) {/* min header length */
- /* bad packet header len */
- /* or packet too short */
- }
- else
- {
- ip->ip_sum = 0;
- ip->ip_sum = ip_checksum(ip, hlen);
- DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n",
- hlen, ip->ip_sum);
- }
+ ip->ip_sum = 0;
+ ip->ip_sum = ip_checksum(ip, hlen);
+ DPRINTF("+++ C+ mode IP header len=%d checksum=%04x\n",
+ hlen, ip->ip_sum);
+ }
+
+ if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP)
+ {
+ /* Large enough for the TCP header? */
+ if (ip_data_len < sizeof(tcp_header)) {
+ goto skip_offload;
}
- if ((txdw0 & CP_TX_LGSEN) && ip_protocol == IP_PROTO_TCP)
- {
- int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK;
+ int large_send_mss = (txdw0 >> 16) & CP_TC_LGSEN_MSS_MASK;
- DPRINTF("+++ C+ mode offloaded task TSO MTU=%d IP data %d "
- "frame data %d specified MSS=%d\n", ETH_MTU,
- ip_data_len, saved_size - ETH_HLEN, large_send_mss);
+ DPRINTF("+++ C+ mode offloaded task TSO MTU=%d IP data %d "
+ "frame data %d specified MSS=%d\n", ETH_MTU,
+ ip_data_len, saved_size - ETH_HLEN, large_send_mss);
- int tcp_send_offset = 0;
- int send_count = 0;
+ int tcp_send_offset = 0;
+ int send_count = 0;
- /* maximum IP header length is 60 bytes */
- uint8_t saved_ip_header[60];
+ /* maximum IP header length is 60 bytes */
+ uint8_t saved_ip_header[60];
- /* save IP header template; data area is used in tcp checksum calculation */
- memcpy(saved_ip_header, eth_payload_data, hlen);
+ /* save IP header template; data area is used in tcp checksum calculation */
+ memcpy(saved_ip_header, eth_payload_data, hlen);
- /* a placeholder for checksum calculation routine in tcp case */
- uint8_t *data_to_checksum = eth_payload_data + hlen - 12;
- // size_t data_to_checksum_len = eth_payload_len - hlen + 12;
+ /* a placeholder for checksum calculation routine in tcp case */
+ uint8_t *data_to_checksum = eth_payload_data + hlen - 12;
+ // size_t data_to_checksum_len = eth_payload_len - hlen + 12;
- /* pointer to TCP header */
- tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + hlen);
+ /* pointer to TCP header */
+ tcp_header *p_tcp_hdr = (tcp_header*)(eth_payload_data + hlen);
- int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr);
+ int tcp_hlen = TCP_HEADER_DATA_OFFSET(p_tcp_hdr);
- /* ETH_MTU = ip header len + tcp header len + payload */
- int tcp_data_len = ip_data_len - tcp_hlen;
- int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen;
+ /* Invalid TCP data offset? */
+ if (tcp_hlen < sizeof(tcp_header) || tcp_hlen > ip_data_len) {
+ goto skip_offload;
+ }
- DPRINTF("+++ C+ mode TSO IP data len %d TCP hlen %d TCP "
- "data len %d TCP chunk size %d\n", ip_data_len,
- tcp_hlen, tcp_data_len, tcp_chunk_size);
+ /* ETH_MTU = ip header len + tcp header len + payload */
+ int tcp_data_len = ip_data_len - tcp_hlen;
+ int tcp_chunk_size = ETH_MTU - hlen - tcp_hlen;
- /* note the cycle below overwrites IP header data,
- but restores it from saved_ip_header before sending packet */
+ DPRINTF("+++ C+ mode TSO IP data len %d TCP hlen %d TCP "
+ "data len %d TCP chunk size %d\n", ip_data_len,
+ tcp_hlen, tcp_data_len, tcp_chunk_size);
- int is_last_frame = 0;
+ /* note the cycle below overwrites IP header data,
+ but restores it from saved_ip_header before sending packet */
- for (tcp_send_offset = 0; tcp_send_offset < tcp_data_len; tcp_send_offset += tcp_chunk_size)
- {
- uint16_t chunk_size = tcp_chunk_size;
-
- /* check if this is the last frame */
- if (tcp_send_offset + tcp_chunk_size >= tcp_data_len)
- {
- is_last_frame = 1;
- chunk_size = tcp_data_len - tcp_send_offset;
- }
-
- DPRINTF("+++ C+ mode TSO TCP seqno %08x\n",
- be32_to_cpu(p_tcp_hdr->th_seq));
-
- /* add 4 TCP pseudoheader fields */
- /* copy IP source and destination fields */
- memcpy(data_to_checksum, saved_ip_header + 12, 8);
-
- DPRINTF("+++ C+ mode TSO calculating TCP checksum for "
- "packet with %d bytes data\n", tcp_hlen +
- chunk_size);
-
- if (tcp_send_offset)
- {
- memcpy((uint8_t*)p_tcp_hdr + tcp_hlen, (uint8_t*)p_tcp_hdr + tcp_hlen + tcp_send_offset, chunk_size);
- }
-
- /* keep PUSH and FIN flags only for the last frame */
- if (!is_last_frame)
- {
- TCP_HEADER_CLEAR_FLAGS(p_tcp_hdr, TCP_FLAG_PUSH|TCP_FLAG_FIN);
- }
-
- /* recalculate TCP checksum */
- ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
- p_tcpip_hdr->zeros = 0;
- p_tcpip_hdr->ip_proto = IP_PROTO_TCP;
- p_tcpip_hdr->ip_payload = cpu_to_be16(tcp_hlen + chunk_size);
-
- p_tcp_hdr->th_sum = 0;
-
- int tcp_checksum = ip_checksum(data_to_checksum, tcp_hlen + chunk_size + 12);
- DPRINTF("+++ C+ mode TSO TCP checksum %04x\n",
- tcp_checksum);
-
- p_tcp_hdr->th_sum = tcp_checksum;
-
- /* restore IP header */
- memcpy(eth_payload_data, saved_ip_header, hlen);
-
- /* set IP data length and recalculate IP checksum */
- ip->ip_len = cpu_to_be16(hlen + tcp_hlen + chunk_size);
-
- /* increment IP id for subsequent frames */
- ip->ip_id = cpu_to_be16(tcp_send_offset/tcp_chunk_size + be16_to_cpu(ip->ip_id));
-
- ip->ip_sum = 0;
- ip->ip_sum = ip_checksum(eth_payload_data, hlen);
- DPRINTF("+++ C+ mode TSO IP header len=%d "
- "checksum=%04x\n", hlen, ip->ip_sum);
-
- int tso_send_size = ETH_HLEN + hlen + tcp_hlen + chunk_size;
- DPRINTF("+++ C+ mode TSO transferring packet size "
- "%d\n", tso_send_size);
- rtl8139_transfer_frame(s, saved_buffer, tso_send_size,
- 0, (uint8_t *) dot1q_buffer);
-
- /* add transferred count to TCP sequence number */
- p_tcp_hdr->th_seq = cpu_to_be32(chunk_size + be32_to_cpu(p_tcp_hdr->th_seq));
- ++send_count;
- }
+ int is_last_frame = 0;
- /* Stop sending this frame */
- saved_size = 0;
- }
- else if (txdw0 & (CP_TX_TCPCS|CP_TX_UDPCS))
+ for (tcp_send_offset = 0; tcp_send_offset < tcp_data_len; tcp_send_offset += tcp_chunk_size)
{
- DPRINTF("+++ C+ mode need TCP or UDP checksum\n");
+ uint16_t chunk_size = tcp_chunk_size;
- /* maximum IP header length is 60 bytes */
- uint8_t saved_ip_header[60];
- memcpy(saved_ip_header, eth_payload_data, hlen);
+ /* check if this is the last frame */
+ if (tcp_send_offset + tcp_chunk_size >= tcp_data_len)
+ {
+ is_last_frame = 1;
+ chunk_size = tcp_data_len - tcp_send_offset;
+ }
- uint8_t *data_to_checksum = eth_payload_data + hlen - 12;
- // size_t data_to_checksum_len = eth_payload_len - hlen + 12;
+ DPRINTF("+++ C+ mode TSO TCP seqno %08x\n",
+ be32_to_cpu(p_tcp_hdr->th_seq));
/* add 4 TCP pseudoheader fields */
/* copy IP source and destination fields */
memcpy(data_to_checksum, saved_ip_header + 12, 8);
- if ((txdw0 & CP_TX_TCPCS) && ip_protocol == IP_PROTO_TCP)
+ DPRINTF("+++ C+ mode TSO calculating TCP checksum for "
+ "packet with %d bytes data\n", tcp_hlen +
+ chunk_size);
+
+ if (tcp_send_offset)
+ {
+ memcpy((uint8_t*)p_tcp_hdr + tcp_hlen, (uint8_t*)p_tcp_hdr + tcp_hlen + tcp_send_offset, chunk_size);
+ }
+
+ /* keep PUSH and FIN flags only for the last frame */
+ if (!is_last_frame)
{
- DPRINTF("+++ C+ mode calculating TCP checksum for "
- "packet with %d bytes data\n", ip_data_len);
+ TCP_HEADER_CLEAR_FLAGS(p_tcp_hdr, TCP_FLAG_PUSH|TCP_FLAG_FIN);
+ }
- ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
- p_tcpip_hdr->zeros = 0;
- p_tcpip_hdr->ip_proto = IP_PROTO_TCP;
- p_tcpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
+ /* recalculate TCP checksum */
+ ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
+ p_tcpip_hdr->zeros = 0;
+ p_tcpip_hdr->ip_proto = IP_PROTO_TCP;
+ p_tcpip_hdr->ip_payload = cpu_to_be16(tcp_hlen + chunk_size);
- tcp_header* p_tcp_hdr = (tcp_header *) (data_to_checksum+12);
+ p_tcp_hdr->th_sum = 0;
- p_tcp_hdr->th_sum = 0;
+ int tcp_checksum = ip_checksum(data_to_checksum, tcp_hlen + chunk_size + 12);
+ DPRINTF("+++ C+ mode TSO TCP checksum %04x\n",
+ tcp_checksum);
- int tcp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
- DPRINTF("+++ C+ mode TCP checksum %04x\n",
- tcp_checksum);
+ p_tcp_hdr->th_sum = tcp_checksum;
- p_tcp_hdr->th_sum = tcp_checksum;
- }
- else if ((txdw0 & CP_TX_UDPCS) && ip_protocol == IP_PROTO_UDP)
- {
- DPRINTF("+++ C+ mode calculating UDP checksum for "
- "packet with %d bytes data\n", ip_data_len);
+ /* restore IP header */
+ memcpy(eth_payload_data, saved_ip_header, hlen);
- ip_pseudo_header *p_udpip_hdr = (ip_pseudo_header *)data_to_checksum;
- p_udpip_hdr->zeros = 0;
- p_udpip_hdr->ip_proto = IP_PROTO_UDP;
- p_udpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
+ /* set IP data length and recalculate IP checksum */
+ ip->ip_len = cpu_to_be16(hlen + tcp_hlen + chunk_size);
- udp_header *p_udp_hdr = (udp_header *) (data_to_checksum+12);
+ /* increment IP id for subsequent frames */
+ ip->ip_id = cpu_to_be16(tcp_send_offset/tcp_chunk_size + be16_to_cpu(ip->ip_id));
- p_udp_hdr->uh_sum = 0;
+ ip->ip_sum = 0;
+ ip->ip_sum = ip_checksum(eth_payload_data, hlen);
+ DPRINTF("+++ C+ mode TSO IP header len=%d "
+ "checksum=%04x\n", hlen, ip->ip_sum);
- int udp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
- DPRINTF("+++ C+ mode UDP checksum %04x\n",
- udp_checksum);
+ int tso_send_size = ETH_HLEN + hlen + tcp_hlen + chunk_size;
+ DPRINTF("+++ C+ mode TSO transferring packet size "
+ "%d\n", tso_send_size);
+ rtl8139_transfer_frame(s, saved_buffer, tso_send_size,
+ 0, (uint8_t *) dot1q_buffer);
- p_udp_hdr->uh_sum = udp_checksum;
- }
+ /* add transferred count to TCP sequence number */
+ p_tcp_hdr->th_seq = cpu_to_be32(chunk_size + be32_to_cpu(p_tcp_hdr->th_seq));
+ ++send_count;
+ }
- /* restore IP header */
- memcpy(eth_payload_data, saved_ip_header, hlen);
+ /* Stop sending this frame */
+ saved_size = 0;
+ }
+ else if (txdw0 & (CP_TX_TCPCS|CP_TX_UDPCS))
+ {
+ DPRINTF("+++ C+ mode need TCP or UDP checksum\n");
+
+ /* maximum IP header length is 60 bytes */
+ uint8_t saved_ip_header[60];
+ memcpy(saved_ip_header, eth_payload_data, hlen);
+
+ uint8_t *data_to_checksum = eth_payload_data + hlen - 12;
+ // size_t data_to_checksum_len = eth_payload_len - hlen + 12;
+
+ /* add 4 TCP pseudoheader fields */
+ /* copy IP source and destination fields */
+ memcpy(data_to_checksum, saved_ip_header + 12, 8);
+
+ if ((txdw0 & CP_TX_TCPCS) && ip_protocol == IP_PROTO_TCP)
+ {
+ DPRINTF("+++ C+ mode calculating TCP checksum for "
+ "packet with %d bytes data\n", ip_data_len);
+
+ ip_pseudo_header *p_tcpip_hdr = (ip_pseudo_header *)data_to_checksum;
+ p_tcpip_hdr->zeros = 0;
+ p_tcpip_hdr->ip_proto = IP_PROTO_TCP;
+ p_tcpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
+
+ tcp_header* p_tcp_hdr = (tcp_header *) (data_to_checksum+12);
+
+ p_tcp_hdr->th_sum = 0;
+
+ int tcp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
+ DPRINTF("+++ C+ mode TCP checksum %04x\n",
+ tcp_checksum);
+
+ p_tcp_hdr->th_sum = tcp_checksum;
}
+ else if ((txdw0 & CP_TX_UDPCS) && ip_protocol == IP_PROTO_UDP)
+ {
+ DPRINTF("+++ C+ mode calculating UDP checksum for "
+ "packet with %d bytes data\n", ip_data_len);
+
+ ip_pseudo_header *p_udpip_hdr = (ip_pseudo_header *)data_to_checksum;
+ p_udpip_hdr->zeros = 0;
+ p_udpip_hdr->ip_proto = IP_PROTO_UDP;
+ p_udpip_hdr->ip_payload = cpu_to_be16(ip_data_len);
+
+ udp_header *p_udp_hdr = (udp_header *) (data_to_checksum+12);
+
+ p_udp_hdr->uh_sum = 0;
+
+ int udp_checksum = ip_checksum(data_to_checksum, ip_data_len + 12);
+ DPRINTF("+++ C+ mode UDP checksum %04x\n",
+ udp_checksum);
+
+ p_udp_hdr->uh_sum = udp_checksum;
+ }
+
+ /* restore IP header */
+ memcpy(eth_payload_data, saved_ip_header, hlen);
}
}
+skip_offload:
/* update tally counter */
++s->tally_counters.TxOk;
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 1510839547..8d28e45afc 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1124,7 +1124,7 @@ static void virtio_net_tx_complete(NetClientState *nc, ssize_t len)
virtqueue_push(q->tx_vq, &q->async_tx.elem, 0);
virtio_notify(vdev, q->tx_vq);
- q->async_tx.elem.out_num = q->async_tx.len = 0;
+ q->async_tx.elem.out_num = 0;
virtio_queue_set_notification(q->tx_vq, 1);
virtio_net_flush_tx(q);
@@ -1148,7 +1148,7 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
}
while (virtqueue_pop(q->tx_vq, &elem)) {
- ssize_t ret, len;
+ ssize_t ret;
unsigned int out_num = elem.out_num;
struct iovec *out_sg = &elem.out_sg[0];
struct iovec sg[VIRTQUEUE_MAX_SIZE], sg2[VIRTQUEUE_MAX_SIZE + 1];
@@ -1196,18 +1196,14 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
out_sg = sg;
}
- len = n->guest_hdr_len;
-
ret = qemu_sendv_packet_async(qemu_get_subqueue(n->nic, queue_index),
out_sg, out_num, virtio_net_tx_complete);
if (ret == 0) {
virtio_queue_set_notification(q->tx_vq, 0);
q->async_tx.elem = elem;
- q->async_tx.len = len;
return -EBUSY;
}
- len += ret;
drop:
virtqueue_push(q->tx_vq, &elem, 0);
virtio_notify(vdev, q->tx_vq);
diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c
index 59b06b8412..071feebf15 100644
--- a/hw/net/vmxnet3.c
+++ b/hw/net/vmxnet3.c
@@ -927,9 +927,9 @@ static void vmxnet3_rx_need_csum_calculate(struct VmxnetRxPkt *pkt,
/* Validate packet len: csum_start + scum_offset + length of csum field */
if (pkt_len < (vhdr->csum_start + vhdr->csum_offset + 2)) {
- VMW_PKPRN("packet len:%d < csum_start(%d) + csum_offset(%d) + 2, "
+ VMW_PKPRN("packet len:%lu < csum_start(%d) + csum_offset(%d) + 2, "
"cannot calculate checksum",
- len, vhdr->csum_start, vhdr->csum_offset);
+ pkt_len, vhdr->csum_start, vhdr->csum_offset);
return;
}
diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c
index 3a731fe18d..4139a2c468 100644
--- a/hw/pci-host/bonito.c
+++ b/hw/pci-host/bonito.c
@@ -355,6 +355,10 @@ static uint64_t bonito_ldma_readl(void *opaque, hwaddr addr,
uint32_t val;
PCIBonitoState *s = opaque;
+ if (addr >= sizeof(s->bonldma)) {
+ return 0;
+ }
+
val = ((uint32_t *)(&s->bonldma))[addr/sizeof(uint32_t)];
return val;
@@ -365,6 +369,10 @@ static void bonito_ldma_writel(void *opaque, hwaddr addr,
{
PCIBonitoState *s = opaque;
+ if (addr >= sizeof(s->bonldma)) {
+ return;
+ }
+
((uint32_t *)(&s->bonldma))[addr/sizeof(uint32_t)] = val & 0xffffffff;
}
@@ -384,6 +392,10 @@ static uint64_t bonito_cop_readl(void *opaque, hwaddr addr,
uint32_t val;
PCIBonitoState *s = opaque;
+ if (addr >= sizeof(s->boncop)) {
+ return 0;
+ }
+
val = ((uint32_t *)(&s->boncop))[addr/sizeof(uint32_t)];
return val;
@@ -394,6 +406,10 @@ static void bonito_cop_writel(void *opaque, hwaddr addr,
{
PCIBonitoState *s = opaque;
+ if (addr >= sizeof(s->boncop)) {
+ return;
+ }
+
((uint32_t *)(&s->boncop))[addr/sizeof(uint32_t)] = val & 0xffffffff;
}
diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index ad55f99663..1cb25f3fa6 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -117,6 +117,11 @@ struct PCII440FXState {
#define I440FX_PAM_SIZE 7
#define I440FX_SMRAM 0x72
+/* Older coreboot versions (4.0 and older) read a config register that doesn't
+ * exist in real hardware, to get the RAM size from QEMU.
+ */
+#define I440FX_COREBOOT_RAM_SIZE 0x57
+
static void piix3_set_irq(void *opaque, int pirq, int level);
static PCIINTxRoute piix3_route_intx_pin_to_irq(void *opaque, int pci_intx);
static void piix3_write_config_xen(PCIDevice *dev,
@@ -394,7 +399,7 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state,
if (ram_size > 255) {
ram_size = 255;
}
- d->config[0x57] = ram_size;
+ d->config[I440FX_COREBOOT_RAM_SIZE] = ram_size;
i440fx_update_memory_mappings(f);
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index a017614d48..9f57aeaeba 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -38,6 +38,7 @@
#include "hw/pci/msix.h"
#include "exec/address-spaces.h"
#include "hw/hotplug.h"
+#include "hw/boards.h"
//#define DEBUG_PCI
#ifdef DEBUG_PCI
@@ -1065,6 +1066,10 @@ static pcibus_t pci_bar_address(PCIDevice *d,
pcibus_t new_addr, last_addr;
int bar = pci_bar(d, reg);
uint16_t cmd = pci_get_word(d->config + PCI_COMMAND);
+ Object *machine = qdev_get_machine();
+ ObjectClass *oc = object_get_class(machine);
+ MachineClass *mc = MACHINE_CLASS(oc);
+ bool allow_0_address = mc->pci_allow_0_address;
if (type & PCI_BASE_ADDRESS_SPACE_IO) {
if (!(cmd & PCI_COMMAND_IO)) {
@@ -1075,7 +1080,8 @@ static pcibus_t pci_bar_address(PCIDevice *d,
/* Check if 32 bit BAR wraps around explicitly.
* TODO: make priorities correct and remove this work around.
*/
- if (last_addr <= new_addr || new_addr == 0 || last_addr >= UINT32_MAX) {
+ if (last_addr <= new_addr || last_addr >= UINT32_MAX ||
+ (!allow_0_address && new_addr == 0)) {
return PCI_BAR_UNMAPPED;
}
return new_addr;
@@ -1099,8 +1105,8 @@ static pcibus_t pci_bar_address(PCIDevice *d,
/* XXX: as we cannot support really dynamic
mappings, we handle specific values as invalid
mappings. */
- if (last_addr <= new_addr || new_addr == 0 ||
- last_addr == PCI_BAR_UNMAPPED) {
+ if (last_addr <= new_addr || last_addr == PCI_BAR_UNMAPPED ||
+ (!allow_0_address && new_addr == 0)) {
return PCI_BAR_UNMAPPED;
}
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index a6f19473cf..bf0c64f2d4 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1835,6 +1835,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
mc->default_ram_size = 512 * M_BYTE;
mc->kvm_type = spapr_kvm_type;
mc->has_dynamic_sysbus = true;
+ mc->pci_allow_0_address = true;
fwc->get_dev_path = spapr_get_fw_dev_path;
nc->nmi_monitor_handler = spapr_nmi;
diff --git a/hw/smbios/Makefile.objs b/hw/smbios/Makefile.objs
new file mode 100644
index 0000000000..f69a92f967
--- /dev/null
+++ b/hw/smbios/Makefile.objs
@@ -0,0 +1 @@
+common-obj-$(CONFIG_SMBIOS) += smbios.o
diff --git a/hw/i386/smbios.c b/hw/smbios/smbios.c
index 1341e02344..efdbb5de6f 100644
--- a/hw/i386/smbios.c
+++ b/hw/smbios/smbios.c
@@ -19,10 +19,9 @@
#include "qemu/error-report.h"
#include "sysemu/sysemu.h"
#include "sysemu/cpus.h"
-#include "hw/i386/pc.h"
-#include "hw/i386/smbios.h"
+#include "hw/smbios/smbios.h"
#include "hw/loader.h"
-
+#include "exec/cpu-common.h"
/* legacy structures and constants for <= 2.0 machines */
struct smbios_header {
@@ -831,10 +830,12 @@ static void smbios_entry_point_setup(void)
ep.structure_table_address = cpu_to_le32(0);
}
-void smbios_get_tables(uint8_t **tables, size_t *tables_len,
+void smbios_get_tables(const struct smbios_phys_mem_area *mem_array,
+ const unsigned int mem_array_size,
+ uint8_t **tables, size_t *tables_len,
uint8_t **anchor, size_t *anchor_len)
{
- unsigned i, dimm_cnt, instance;
+ unsigned i, dimm_cnt;
if (smbios_legacy) {
*tables = *anchor = NULL;
@@ -867,11 +868,9 @@ void smbios_get_tables(uint8_t **tables, size_t *tables_len,
smbios_build_type_17_table(i, GET_DIMM_SZ);
}
- for (i = 0, instance = 0; i < e820_get_num_entries(); i++) {
- uint64_t address, length;
- if (e820_get_entry(i, E820_RAM, &address, &length)) {
- smbios_build_type_19_table(instance++, address, length);
- }
+ for (i = 0; i < mem_array_size; i++) {
+ smbios_build_type_19_table(i, mem_array[i].address,
+ mem_array[i].length);
}
smbios_build_type_32_table();
diff --git a/hw/timer/imx_epit.c b/hw/timer/imx_epit.c
index ffefc22f43..10c5d2b91e 100644
--- a/hw/timer/imx_epit.c
+++ b/hw/timer/imx_epit.c
@@ -5,23 +5,18 @@
* Copyright (c) 2011 NICTA Pty Ltd
* Originally written by Hans Jiang
* Updated by Peter Chubb
- * Updated by Jean-Christophe Dubois
+ * Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
*
* This code is licensed under GPL version 2 or later. See
* the COPYING file in the top-level directory.
*
*/
-#include "hw/hw.h"
-#include "qemu/bitops.h"
-#include "qemu/timer.h"
-#include "hw/ptimer.h"
-#include "hw/sysbus.h"
#include "hw/arm/imx.h"
+#include "hw/timer/imx_epit.h"
+#include "hw/misc/imx_ccm.h"
#include "qemu/main-loop.h"
-#define TYPE_IMX_EPIT "imx.epit"
-
#define DEBUG_TIMER 0
#if DEBUG_TIMER
@@ -61,30 +56,6 @@ static char const *imx_epit_reg_name(uint32_t reg)
# define IPRINTF(fmt, args...) do {} while (0)
#endif
-#define IMX_EPIT(obj) \
- OBJECT_CHECK(IMXEPITState, (obj), TYPE_IMX_EPIT)
-
-/*
- * EPIT: Enhanced periodic interrupt timer
- */
-
-#define CR_EN (1 << 0)
-#define CR_ENMOD (1 << 1)
-#define CR_OCIEN (1 << 2)
-#define CR_RLD (1 << 3)
-#define CR_PRESCALE_SHIFT (4)
-#define CR_PRESCALE_MASK (0xfff)
-#define CR_SWR (1 << 16)
-#define CR_IOVW (1 << 17)
-#define CR_DBGEN (1 << 18)
-#define CR_WAITEN (1 << 19)
-#define CR_DOZEN (1 << 20)
-#define CR_STOPEN (1 << 21)
-#define CR_CLKSRC_SHIFT (24)
-#define CR_CLKSRC_MASK (0x3 << CR_CLKSRC_SHIFT)
-
-#define EPIT_TIMER_MAX 0XFFFFFFFFUL
-
/*
* Exact clock frequencies vary from board to board.
* These are typical.
@@ -96,23 +67,6 @@ static const IMXClk imx_epit_clocks[] = {
CLK_32k, /* 11 ipg_clk_32k -- ~32kHz */
};
-typedef struct {
- SysBusDevice busdev;
- ptimer_state *timer_reload;
- ptimer_state *timer_cmp;
- MemoryRegion iomem;
- DeviceState *ccm;
-
- uint32_t cr;
- uint32_t sr;
- uint32_t lr;
- uint32_t cmp;
- uint32_t cnt;
-
- uint32_t freq;
- qemu_irq irq;
-} IMXEPITState;
-
/*
* Update interrupt status
*/
@@ -174,9 +128,9 @@ static void imx_epit_reset(DeviceState *dev)
static uint32_t imx_epit_update_count(IMXEPITState *s)
{
- s->cnt = ptimer_get_count(s->timer_reload);
+ s->cnt = ptimer_get_count(s->timer_reload);
- return s->cnt;
+ return s->cnt;
}
static uint64_t imx_epit_read(void *opaque, hwaddr offset, unsigned size)
@@ -344,13 +298,13 @@ void imx_timerp_create(const hwaddr addr, qemu_irq irq, DeviceState *ccm)
}
static const MemoryRegionOps imx_epit_ops = {
- .read = imx_epit_read,
- .write = imx_epit_write,
- .endianness = DEVICE_NATIVE_ENDIAN,
+ .read = imx_epit_read,
+ .write = imx_epit_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
};
static const VMStateDescription vmstate_imx_timer_epit = {
- .name = "imx.epit",
+ .name = TYPE_IMX_EPIT,
.version_id = 2,
.minimum_version_id = 2,
.fields = (VMStateField[]) {
diff --git a/hw/timer/imx_gpt.c b/hw/timer/imx_gpt.c
index 3b3101084b..01f802e8f1 100644
--- a/hw/timer/imx_gpt.c
+++ b/hw/timer/imx_gpt.c
@@ -5,23 +5,18 @@
* Copyright (c) 2011 NICTA Pty Ltd
* Originally written by Hans Jiang
* Updated by Peter Chubb
- * Updated by Jean-Christophe Dubois
+ * Updated by Jean-Christophe Dubois <jcd@tribudubois.net>
*
* This code is licensed under GPL version 2 or later. See
* the COPYING file in the top-level directory.
*
*/
-#include "hw/hw.h"
-#include "qemu/bitops.h"
-#include "qemu/timer.h"
-#include "hw/ptimer.h"
-#include "hw/sysbus.h"
#include "hw/arm/imx.h"
+#include "hw/timer/imx_gpt.h"
+#include "hw/misc/imx_ccm.h"
#include "qemu/main-loop.h"
-#define TYPE_IMX_GPT "imx.gpt"
-
/*
* Define to 1 for debug messages
*/
@@ -74,76 +69,8 @@ static char const *imx_gpt_reg_name(uint32_t reg)
# define IPRINTF(fmt, args...) do {} while (0)
#endif
-#define IMX_GPT(obj) \
- OBJECT_CHECK(IMXGPTState, (obj), TYPE_IMX_GPT)
-/*
- * GPT : General purpose timer
- *
- * This timer counts up continuously while it is enabled, resetting itself
- * to 0 when it reaches GPT_TIMER_MAX (in freerun mode) or when it
- * reaches the value of one of the ocrX (in periodic mode).
- */
-
-#define GPT_TIMER_MAX 0XFFFFFFFFUL
-
-/* Control register. Not all of these bits have any effect (yet) */
-#define GPT_CR_EN (1 << 0) /* GPT Enable */
-#define GPT_CR_ENMOD (1 << 1) /* GPT Enable Mode */
-#define GPT_CR_DBGEN (1 << 2) /* GPT Debug mode enable */
-#define GPT_CR_WAITEN (1 << 3) /* GPT Wait Mode Enable */
-#define GPT_CR_DOZEN (1 << 4) /* GPT Doze mode enable */
-#define GPT_CR_STOPEN (1 << 5) /* GPT Stop Mode Enable */
-#define GPT_CR_CLKSRC_SHIFT (6)
-#define GPT_CR_CLKSRC_MASK (0x7)
-
-#define GPT_CR_FRR (1 << 9) /* Freerun or Restart */
-#define GPT_CR_SWR (1 << 15) /* Software Reset */
-#define GPT_CR_IM1 (3 << 16) /* Input capture channel 1 mode (2 bits) */
-#define GPT_CR_IM2 (3 << 18) /* Input capture channel 2 mode (2 bits) */
-#define GPT_CR_OM1 (7 << 20) /* Output Compare Channel 1 Mode (3 bits) */
-#define GPT_CR_OM2 (7 << 23) /* Output Compare Channel 2 Mode (3 bits) */
-#define GPT_CR_OM3 (7 << 26) /* Output Compare Channel 3 Mode (3 bits) */
-#define GPT_CR_FO1 (1 << 29) /* Force Output Compare Channel 1 */
-#define GPT_CR_FO2 (1 << 30) /* Force Output Compare Channel 2 */
-#define GPT_CR_FO3 (1 << 31) /* Force Output Compare Channel 3 */
-
-#define GPT_SR_OF1 (1 << 0)
-#define GPT_SR_OF2 (1 << 1)
-#define GPT_SR_OF3 (1 << 2)
-#define GPT_SR_ROV (1 << 5)
-
-#define GPT_IR_OF1IE (1 << 0)
-#define GPT_IR_OF2IE (1 << 1)
-#define GPT_IR_OF3IE (1 << 2)
-#define GPT_IR_ROVIE (1 << 5)
-
-typedef struct {
- SysBusDevice busdev;
- ptimer_state *timer;
- MemoryRegion iomem;
- DeviceState *ccm;
-
- uint32_t cr;
- uint32_t pr;
- uint32_t sr;
- uint32_t ir;
- uint32_t ocr1;
- uint32_t ocr2;
- uint32_t ocr3;
- uint32_t icr1;
- uint32_t icr2;
- uint32_t cnt;
-
- uint32_t next_timeout;
- uint32_t next_int;
-
- uint32_t freq;
-
- qemu_irq irq;
-} IMXGPTState;
-
static const VMStateDescription vmstate_imx_timer_gpt = {
- .name = "imx.gpt",
+ .name = TYPE_IMX_GPT,
.version_id = 3,
.minimum_version_id = 3,
.fields = (VMStateField[]) {
@@ -180,7 +107,7 @@ static void imx_gpt_set_freq(IMXGPTState *s)
{
uint32_t clksrc = extract32(s->cr, GPT_CR_CLKSRC_SHIFT, 3);
uint32_t freq = imx_clock_frequency(s->ccm, imx_gpt_clocks[clksrc])
- / (1 + s->pr);
+ / (1 + s->pr);
s->freq = freq;
DPRINTF("Setting clksrc %d to frequency %d\n", clksrc, freq);
@@ -207,7 +134,7 @@ static uint32_t imx_gpt_update_count(IMXGPTState *s)
}
static inline uint32_t imx_gpt_find_limit(uint32_t count, uint32_t reg,
- uint32_t timeout)
+ uint32_t timeout)
{
if ((count < reg) && (timeout > reg)) {
timeout = reg;
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index ee4e07c5e7..788b556a74 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -1049,6 +1049,61 @@ static bool virtio_64bit_features_needed(void *opaque)
return (vdev->host_features >> 32) != 0;
}
+static bool virtio_virtqueue_needed(void *opaque)
+{
+ VirtIODevice *vdev = opaque;
+
+ return virtio_host_has_feature(vdev, VIRTIO_F_VERSION_1);
+}
+
+static void put_virtqueue_state(QEMUFile *f, void *pv, size_t size)
+{
+ VirtIODevice *vdev = pv;
+ int i;
+
+ for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
+ qemu_put_be64(f, vdev->vq[i].vring.avail);
+ qemu_put_be64(f, vdev->vq[i].vring.used);
+ }
+}
+
+static int get_virtqueue_state(QEMUFile *f, void *pv, size_t size)
+{
+ VirtIODevice *vdev = pv;
+ int i;
+
+ for (i = 0; i < VIRTIO_QUEUE_MAX; i++) {
+ vdev->vq[i].vring.avail = qemu_get_be64(f);
+ vdev->vq[i].vring.used = qemu_get_be64(f);
+ }
+ return 0;
+}
+
+static VMStateInfo vmstate_info_virtqueue = {
+ .name = "virtqueue_state",
+ .get = get_virtqueue_state,
+ .put = put_virtqueue_state,
+};
+
+static const VMStateDescription vmstate_virtio_virtqueues = {
+ .name = "virtio/virtqueues",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = &virtio_virtqueue_needed,
+ .fields = (VMStateField[]) {
+ {
+ .name = "virtqueues",
+ .version_id = 0,
+ .field_exists = NULL,
+ .size = 0,
+ .info = &vmstate_info_virtqueue,
+ .flags = VMS_SINGLE,
+ .offset = 0,
+ },
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static const VMStateDescription vmstate_virtio_device_endian = {
.name = "virtio/device_endian",
.version_id = 1,
@@ -1082,6 +1137,7 @@ static const VMStateDescription vmstate_virtio = {
.subsections = (const VMStateDescription*[]) {
&vmstate_virtio_device_endian,
&vmstate_virtio_64bit_features,
+ &vmstate_virtio_virtqueues,
NULL
}
};