[Spice-commits] 220 commits - .gitignore MAINTAINERS Makefile.objs Makefile.target VERSION block-migration.c block.c block.h block/qcow2-cache.c block/qcow2-cluster.c block/qcow2-refcount.c block/qcow2.c block/qcow2.h block/qed.c block/raw-win32.c block/sheepdog.c block/vdi.c block_int.h blockdev.c blockdev.h configure console.c console.h cpu-all.h cpus.c cutils.c default-configs/i386-softmmu.mak default-configs/x86_64-softmmu.mak docs/bootindex.txt docs/tracing.txt elf.h exec-all.h exec.c fpu/softfloat-specialize.h fpu/softfloat.c fpu/softfloat.h hmp-commands.hx hw/apic.c hw/device-hotplug.c hw/ecc.c hw/escc.c hw/flash.h hw/gumstix.c hw/hpet.c hw/hw.h hw/i2c.h hw/ide hw/ide.h hw/ioapic.c hw/ioapic.h hw/isa-bus.c hw/isa.h hw/leon3.c hw/mainstone.c hw/mainstone.h hw/max7310.c hw/mc146818rtc.c hw/mips_malta.c hw/mst_fpga.c hw/onenand.c hw/pc.c hw/pc.h hw/pc_piix.c hw/pci-hotplug.c hw/pci.c hw/pci.h hw/pl181.c hw/ppc_prep.c hw/pxa.h hw/pxa2xx.c hw/pxa2xx_gpio.c hw/qdev.c hw/qdev.h hw/q xl.c hw/qxl.h hw/scsi.h hw/sd.c hw/sharpsl.h hw/slavio_intctl.c hw/spitz.c hw/ssi-sd.c hw/sysbus.c hw/sysbus.h hw/tc6393xb.c hw/tosa.c hw/usb-bus.c hw/usb-hid.c hw/usb-hub.c hw/usb-msd.c hw/usb.h hw/vhost.c hw/vhost.h hw/vhost_net.c hw/vhost_net.h hw/virtio-blk.c hw/virtio-console.c hw/virtio-net.c hw/virtio-pci.c hw/virtio-serial-bus.c hw/virtio-serial.h hw/virtio.h hw/vmmouse.c hw/vmport.c hw/vmware_vga.c hw/vmware_vga.h hw/zaurus.c kvm-all.c kvm-stub.c kvm.h linux-user/arm linux-user/elfload.c linux-user/flatload.c linux-user/ioctls.h linux-user/main.c linux-user/qemu.h linux-user/signal.c linux-user/strace.c linux-user/syscall.c linux-user/syscall_defs.h linux-user/target_flat.h migration.c migration.h monitor.c net/tap-linux.c net/tap.c path.c pc-bios/README pc-bios/bios.bin pc-bios/openbios-ppc pc-bios/openbios-sparc32 pc-bios/openbios-sparc64 qemu-char.c qemu-char.h qemu-common.h qemu-config.c qemu-doc.texi qemu-io.c qemu-options.hx qemu-timer.c qmp-commands.hx roms/s eabios savevm.c scripts/checkpatch.pl scripts/tracetool slirp/mbuf.c spice-qemu-char.c target-arm/cpu.h target-arm/helper.c target-arm/helpers.h target-arm/neon_helper.c target-arm/op_helper.c target-arm/translate.c target-cris/exec.h target-i386/cpu.h target-i386/cpuid.c target-i386/helper.c target-i386/kvm.c target-i386/kvm_x86.h target-microblaze/exec.h target-microblaze/translate.c target-mips/op_helper.c target-ppc/kvm.c target-s390x/kvm.c target-sh4/translate.c target-sparc/cpu.h target-sparc/helper.c target-sparc/op_helper.c trace-events ui/qemu-spice.h ui/sdl.c ui/spice-core.c ui/vnc-jobs-async.c ui/vnc.c vl.c
Gerd Hoffmann
kraxel at kemper.freedesktop.org
Fri Feb 18 08:12:26 PST 2011
.gitignore | 3
MAINTAINERS | 8
Makefile.objs | 5
Makefile.target | 4
VERSION | 2
block-migration.c | 9
block.c | 25 +
block.h | 5
block/qcow2-cache.c | 2
block/qcow2-cluster.c | 82 ++++
block/qcow2-refcount.c | 5
block/qcow2.c | 11
block/qcow2.h | 2
block/qed.c | 24 -
block/raw-win32.c | 2
block/sheepdog.c | 17
block/vdi.c | 4
block_int.h | 6
blockdev.c | 195 ++++++---
blockdev.h | 23 -
configure | 45 +-
console.c | 81 ++-
console.h | 1
cpu-all.h | 5
cpus.c | 6
cutils.c | 28 -
default-configs/i386-softmmu.mak | 2
default-configs/x86_64-softmmu.mak | 2
docs/bootindex.txt | 43 ++
docs/tracing.txt | 5
elf.h | 19
exec-all.h | 1
exec.c | 52 +-
fpu/softfloat-specialize.h | 130 ++++++
fpu/softfloat.c | 130 +++---
fpu/softfloat.h | 25 +
hmp-commands.hx | 42 +-
hw/apic.c | 51 +-
hw/device-hotplug.c | 5
hw/ecc.c | 27 -
hw/escc.c | 8
hw/flash.h | 3
hw/gumstix.c | 4
hw/hpet.c | 2
hw/hw.h | 10
hw/i2c.h | 5
hw/ide.h | 2
hw/ide/ahci.c | 496 +++---------------------
hw/ide/ahci.h | 333 ++++++++++++++++
hw/ide/core.c | 6
hw/ide/ich.c | 148 +++++++
hw/ioapic.c | 230 +++++++----
hw/ioapic.h | 20
hw/isa-bus.c | 12
hw/isa.h | 1
hw/leon3.c | 5
hw/mainstone.c | 34 +
hw/mainstone.h | 38 -
hw/max7310.c | 26 -
hw/mc146818rtc.c | 15
hw/mips_malta.c | 6
hw/mst_fpga.c | 130 ++----
hw/onenand.c | 1
hw/pc.c | 30 +
hw/pc.h | 10
hw/pc_piix.c | 2
hw/pci-hotplug.c | 3
hw/pci.c | 24 +
hw/pci.h | 4
hw/pl181.c | 7
hw/ppc_prep.c | 5
hw/pxa.h | 10
hw/pxa2xx.c | 57 ++
hw/pxa2xx_gpio.c | 150 +++----
hw/qdev.c | 29 -
hw/qdev.h | 3
hw/qxl.c | 81 ---
hw/qxl.h | 4
hw/scsi.h | 3
hw/sd.c | 7
hw/sharpsl.h | 7
hw/slavio_intctl.c | 7
hw/spitz.c | 349 +++++++++--------
hw/ssi-sd.c | 7
hw/sysbus.c | 32 +
hw/sysbus.h | 9
hw/tc6393xb.c | 3
hw/tosa.c | 39 +
hw/usb-bus.c | 28 +
hw/usb-hid.c | 317 ++++++++++-----
hw/usb-hub.c | 24 +
hw/usb-msd.c | 5
hw/usb.h | 10
hw/vhost.c | 10
hw/vhost.h | 4
hw/vhost_net.c | 24 -
hw/vhost_net.h | 3
hw/virtio-blk.c | 50 +-
hw/virtio-console.c | 38 -
hw/virtio-net.c | 19
hw/virtio-pci.c | 7
hw/virtio-serial-bus.c | 126 +++++-
hw/virtio-serial.h | 24 +
hw/virtio.h | 1
hw/vmmouse.c | 62 +--
hw/vmport.c | 43 +-
hw/vmware_vga.c | 5
hw/vmware_vga.h | 12
hw/zaurus.c | 123 +++---
kvm-all.c | 255 ++++++------
kvm-stub.c | 2
kvm.h | 14
linux-user/arm/nwfpe/fpa11_cpdt.c | 2
linux-user/arm/nwfpe/fpopcode.c | 32 -
linux-user/elfload.c | 79 +++
linux-user/flatload.c | 38 -
linux-user/ioctls.h | 2
linux-user/main.c | 17
linux-user/qemu.h | 7
linux-user/signal.c | 11
linux-user/strace.c | 6
linux-user/syscall.c | 128 ++++++
linux-user/syscall_defs.h | 1
linux-user/target_flat.h | 10
migration.c | 28 +
migration.h | 5
monitor.c | 49 ++
net/tap-linux.c | 13
net/tap.c | 6
path.c | 28 +
pc-bios/README | 2
pc-bios/bios.bin |binary
pc-bios/openbios-ppc |binary
pc-bios/openbios-sparc32 |binary
pc-bios/openbios-sparc64 |binary
qemu-char.c | 66 +--
qemu-char.h | 2
qemu-common.h | 13
qemu-config.c | 6
qemu-doc.texi | 52 ++
qemu-io.c | 2
qemu-options.hx | 22 -
qemu-timer.c | 71 +--
qmp-commands.hx | 63 +++
roms/seabios | 2
savevm.c | 11
scripts/checkpatch.pl | 2
scripts/tracetool | 60 ++
slirp/mbuf.c | 4
spice-qemu-char.c | 190 +++++++++
target-arm/cpu.h | 7
target-arm/helper.c | 70 ++-
target-arm/helpers.h | 17
target-arm/neon_helper.c | 158 +++++++
target-arm/op_helper.c | 49 --
target-arm/translate.c | 196 ++++++---
target-cris/exec.h | 4
target-i386/cpu.h | 9
target-i386/cpuid.c | 5
target-i386/helper.c | 97 ++++
target-i386/kvm.c | 751 ++++++++++++++++++++-----------------
target-i386/kvm_x86.h | 5
target-microblaze/exec.h | 4
target-microblaze/translate.c | 8
target-mips/op_helper.c | 16
target-ppc/kvm.c | 10
target-s390x/kvm.c | 6
target-sh4/translate.c | 4
target-sparc/cpu.h | 8
target-sparc/helper.c | 2
target-sparc/op_helper.c | 18
trace-events | 6
ui/qemu-spice.h | 7
ui/sdl.c | 14
ui/spice-core.c | 25 +
ui/vnc-jobs-async.c | 4
ui/vnc.c | 41 +-
vl.c | 110 +++--
178 files changed, 4973 insertions(+), 2465 deletions(-)
New commits:
commit 459505a2647a5197cb60ad48a05917f6d8e52695
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date: Sat Feb 12 03:15:25 2011 +0300
Merge mainstone.h header into mainstone.c
Now the only user of mainstone.h is mainstone.c file. Merge header
into board file.
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>
diff --git a/hw/mainstone.c b/hw/mainstone.c
index 04ce8e3..aec8d34 100644
--- a/hw/mainstone.c
+++ b/hw/mainstone.c
@@ -14,12 +14,33 @@
#include "net.h"
#include "devices.h"
#include "boards.h"
-#include "mainstone.h"
#include "sysemu.h"
#include "flash.h"
#include "blockdev.h"
#include "sysbus.h"
+/* Device addresses */
+#define MST_FPGA_PHYS 0x08000000
+#define MST_ETH_PHYS 0x10000300
+#define MST_FLASH_0 0x00000000
+#define MST_FLASH_1 0x04000000
+
+/* IRQ definitions */
+#define MMC_IRQ 0
+#define USIM_IRQ 1
+#define USBC_IRQ 2
+#define ETHERNET_IRQ 3
+#define AC97_IRQ 4
+#define PEN_IRQ 5
+#define MSINS_IRQ 6
+#define EXBRD_IRQ 7
+#define S0_CD_IRQ 9
+#define S0_STSCHG_IRQ 10
+#define S0_IRQ 11
+#define S1_CD_IRQ 13
+#define S1_STSCHG_IRQ 14
+#define S1_IRQ 15
+
static struct keymap map[0xE0] = {
[0 ... 0xDF] = { -1, -1 },
[0x1e] = {0,0}, /* a */
diff --git a/hw/mainstone.h b/hw/mainstone.h
deleted file mode 100644
index e6a2b67..0000000
--- a/hw/mainstone.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * PXA270-based Intel Mainstone platforms.
- *
- * Copyright (c) 2007 by Armin Kuster <akuster at kama-aina.net> or
- * <akuster at mvista.com>
- *
- * This code is licensed under the GNU GPL v2.
- */
-
-#ifndef __MAINSTONE_H__
-#define __MAINSTONE_H__
-
-/* Device addresses */
-#define MST_FPGA_PHYS 0x08000000
-#define MST_ETH_PHYS 0x10000300
-#define MST_FLASH_0 0x00000000
-#define MST_FLASH_1 0x04000000
-
-/* IRQ definitions */
-#define MMC_IRQ 0
-#define USIM_IRQ 1
-#define USBC_IRQ 2
-#define ETHERNET_IRQ 3
-#define AC97_IRQ 4
-#define PEN_IRQ 5
-#define MSINS_IRQ 6
-#define EXBRD_IRQ 7
-#define S0_CD_IRQ 9
-#define S0_STSCHG_IRQ 10
-#define S0_IRQ 11
-#define S1_CD_IRQ 13
-#define S1_STSCHG_IRQ 14
-#define S1_IRQ 15
-
-#endif /* __MAINSTONE_H__ */
commit cb380f615c565804b83c16595185d308c8e1f0e1
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date: Sat Feb 12 03:15:24 2011 +0300
mainstone: convert FPGA emulation code to use QDev/SysBus
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>
diff --git a/hw/mainstone.c b/hw/mainstone.c
index 18d1415..04ce8e3 100644
--- a/hw/mainstone.c
+++ b/hw/mainstone.c
@@ -18,6 +18,7 @@
#include "sysemu.h"
#include "flash.h"
#include "blockdev.h"
+#include "sysbus.h"
static struct keymap map[0xE0] = {
[0 ... 0xDF] = { -1, -1 },
@@ -77,7 +78,7 @@ static void mainstone_common_init(ram_addr_t ram_size,
uint32_t sector_len = 256 * 1024;
target_phys_addr_t mainstone_flash_base[] = { MST_FLASH_0, MST_FLASH_1 };
PXA2xxState *cpu;
- qemu_irq *mst_irq;
+ DeviceState *mst_irq;
DriveInfo *dinfo;
int i;
int be;
@@ -117,16 +118,18 @@ static void mainstone_common_init(ram_addr_t ram_size,
}
}
- mst_irq = mst_irq_init(MST_FPGA_PHYS, cpu->pic[PXA2XX_PIC_GPIO_0]);
+ mst_irq = sysbus_create_simple("mainstone-fpga", MST_FPGA_PHYS,
+ cpu->pic[PXA2XX_PIC_GPIO_0]);
/* setup keypad */
printf("map addr %p\n", &map);
pxa27x_register_keypad(cpu->kp, map, 0xe0);
/* MMC/SD host */
- pxa2xx_mmci_handlers(cpu->mmc, NULL, mst_irq[MMC_IRQ]);
+ pxa2xx_mmci_handlers(cpu->mmc, NULL, qdev_get_gpio_in(mst_irq, MMC_IRQ));
- smc91c111_init(&nd_table[0], MST_ETH_PHYS, mst_irq[ETHERNET_IRQ]);
+ smc91c111_init(&nd_table[0], MST_ETH_PHYS,
+ qdev_get_gpio_in(mst_irq, ETHERNET_IRQ));
mainstone_binfo.kernel_filename = kernel_filename;
mainstone_binfo.kernel_cmdline = kernel_cmdline;
diff --git a/hw/mainstone.h b/hw/mainstone.h
index 35329f1..e6a2b67 100644
--- a/hw/mainstone.h
+++ b/hw/mainstone.h
@@ -32,7 +32,4 @@
#define S1_STSCHG_IRQ 14
#define S1_IRQ 15
-extern qemu_irq
-*mst_irq_init(uint32_t base, qemu_irq irq);
-
#endif /* __MAINSTONE_H__ */
diff --git a/hw/mst_fpga.c b/hw/mst_fpga.c
index 3c594b8..afed2ac 100644
--- a/hw/mst_fpga.c
+++ b/hw/mst_fpga.c
@@ -8,7 +8,7 @@
* This code is licensed under the GNU GPL v2.
*/
#include "hw.h"
-#include "mainstone.h"
+#include "sysbus.h"
/* Mainstone FPGA for extern irqs */
#define FPGA_GPIO_PIN 0
@@ -27,8 +27,9 @@
#define MST_PCMCIA1 0xe4
typedef struct mst_irq_state{
+ SysBusDevice busdev;
+
qemu_irq parent;
- qemu_irq *pins;
uint32_t prev_level;
uint32_t leddat1;
@@ -163,68 +164,67 @@ static CPUWriteMemoryFunc * const mst_fpga_writefn[] = {
mst_fpga_writeb,
};
-static void
-mst_fpga_save(QEMUFile *f, void *opaque)
-{
- struct mst_irq_state *s = (mst_irq_state *) opaque;
-
- qemu_put_be32s(f, &s->prev_level);
- qemu_put_be32s(f, &s->leddat1);
- qemu_put_be32s(f, &s->leddat2);
- qemu_put_be32s(f, &s->ledctrl);
- qemu_put_be32s(f, &s->gpswr);
- qemu_put_be32s(f, &s->mscwr1);
- qemu_put_be32s(f, &s->mscwr2);
- qemu_put_be32s(f, &s->mscwr3);
- qemu_put_be32s(f, &s->mscrd);
- qemu_put_be32s(f, &s->intmskena);
- qemu_put_be32s(f, &s->intsetclr);
- qemu_put_be32s(f, &s->pcmcia0);
- qemu_put_be32s(f, &s->pcmcia1);
-}
-static int
-mst_fpga_load(QEMUFile *f, void *opaque, int version_id)
+static int mst_fpga_post_load(void *opaque, int version_id)
{
mst_irq_state *s = (mst_irq_state *) opaque;
- qemu_get_be32s(f, &s->prev_level);
- qemu_get_be32s(f, &s->leddat1);
- qemu_get_be32s(f, &s->leddat2);
- qemu_get_be32s(f, &s->ledctrl);
- qemu_get_be32s(f, &s->gpswr);
- qemu_get_be32s(f, &s->mscwr1);
- qemu_get_be32s(f, &s->mscwr2);
- qemu_get_be32s(f, &s->mscwr3);
- qemu_get_be32s(f, &s->mscrd);
- qemu_get_be32s(f, &s->intmskena);
- qemu_get_be32s(f, &s->intsetclr);
- qemu_get_be32s(f, &s->pcmcia0);
- qemu_get_be32s(f, &s->pcmcia1);
-
qemu_set_irq(s->parent, s->intsetclr & s->intmskena);
return 0;
}
-qemu_irq *mst_irq_init(uint32_t base, qemu_irq irq)
+static int mst_fpga_init(SysBusDevice *dev)
{
mst_irq_state *s;
int iomemtype;
- qemu_irq *qi;
- s = (mst_irq_state *)
- qemu_mallocz(sizeof(mst_irq_state));
+ s = FROM_SYSBUS(mst_irq_state, dev);
- s->parent = irq;
+ sysbus_init_irq(dev, &s->parent);
/* alloc the external 16 irqs */
- qi = qemu_allocate_irqs(mst_fpga_set_irq, s, MST_NUM_IRQS);
- s->pins = qi;
+ qdev_init_gpio_in(&dev->qdev, mst_fpga_set_irq, MST_NUM_IRQS);
iomemtype = cpu_register_io_memory(mst_fpga_readfn,
mst_fpga_writefn, s, DEVICE_NATIVE_ENDIAN);
- cpu_register_physical_memory(base, 0x00100000, iomemtype);
- register_savevm(NULL, "mainstone_fpga", 0, 0, mst_fpga_save,
- mst_fpga_load, s);
- return qi;
+ sysbus_init_mmio(dev, 0x00100000, iomemtype);
+ return 0;
+}
+
+static VMStateDescription vmstate_mst_fpga_regs = {
+ .name = "mainstone_fpga",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .post_load = mst_fpga_post_load,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT32(prev_level, mst_irq_state),
+ VMSTATE_UINT32(leddat1, mst_irq_state),
+ VMSTATE_UINT32(leddat2, mst_irq_state),
+ VMSTATE_UINT32(ledctrl, mst_irq_state),
+ VMSTATE_UINT32(gpswr, mst_irq_state),
+ VMSTATE_UINT32(mscwr1, mst_irq_state),
+ VMSTATE_UINT32(mscwr2, mst_irq_state),
+ VMSTATE_UINT32(mscwr3, mst_irq_state),
+ VMSTATE_UINT32(mscrd, mst_irq_state),
+ VMSTATE_UINT32(intmskena, mst_irq_state),
+ VMSTATE_UINT32(intsetclr, mst_irq_state),
+ VMSTATE_UINT32(pcmcia0, mst_irq_state),
+ VMSTATE_UINT32(pcmcia1, mst_irq_state),
+ VMSTATE_END_OF_LIST(),
+ },
+};
+
+static SysBusDeviceInfo mst_fpga_info = {
+ .init = mst_fpga_init,
+ .qdev.name = "mainstone-fpga",
+ .qdev.desc = "Mainstone II FPGA",
+ .qdev.size = sizeof(mst_irq_state),
+ .qdev.vmsd = &vmstate_mst_fpga_regs,
+};
+
+static void mst_fpga_register(void)
+{
+ sysbus_register_withprop(&mst_fpga_info);
}
+device_init(mst_fpga_register);
commit 43d91709c10c6227ed2150fc6cb710cb6bf04fc6
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date: Sat Feb 12 03:15:23 2011 +0300
mainstone: correct and simplify irq handling
Simplify IRQ handling to stop setting an input irq pin. As a win, also get
correct IRQ status after save/load cycle.
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>
diff --git a/hw/mst_fpga.c b/hw/mst_fpga.c
index 93c6514..3c594b8 100644
--- a/hw/mst_fpga.c
+++ b/hw/mst_fpga.c
@@ -46,33 +46,21 @@ typedef struct mst_irq_state{
}mst_irq_state;
static void
-mst_fpga_update_gpio(mst_irq_state *s)
-{
- uint32_t level, diff;
- int bit;
- level = s->prev_level ^ s->intsetclr;
-
- for (diff = s->prev_level ^ level; diff; diff ^= 1 << bit) {
- bit = ffs(diff) - 1;
- qemu_set_irq(s->pins[bit], (level >> bit) & 1 );
- }
- s->prev_level = level;
-}
-
-static void
mst_fpga_set_irq(void *opaque, int irq, int level)
{
mst_irq_state *s = (mst_irq_state *)opaque;
+ uint32_t oldint = s->intsetclr;
if (level)
s->prev_level |= 1u << irq;
else
s->prev_level &= ~(1u << irq);
- if(s->intmskena & (1u << irq)) {
- s->intsetclr = 1u << irq;
- qemu_set_irq(s->parent, level);
- }
+ if ((s->intmskena & (1u << irq)) && level)
+ s->intsetclr |= 1u << irq;
+
+ if (oldint != (s->intsetclr & s->intmskena))
+ qemu_set_irq(s->parent, s->intsetclr & s->intmskena);
}
@@ -146,10 +134,11 @@ mst_fpga_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
break;
case MST_INTMSKENA: /* Mask interupt */
s->intmskena = (value & 0xFEEFF);
- mst_fpga_update_gpio(s);
+ qemu_set_irq(s->parent, s->intsetclr & s->intmskena);
break;
case MST_INTSETCLR: /* clear or set interrupt */
s->intsetclr = (value & 0xFEEFF);
+ qemu_set_irq(s->parent, s->intsetclr);
break;
case MST_PCMCIA0:
s->pcmcia0 = value;
@@ -212,6 +201,8 @@ mst_fpga_load(QEMUFile *f, void *opaque, int version_id)
qemu_get_be32s(f, &s->intsetclr);
qemu_get_be32s(f, &s->pcmcia0);
qemu_get_be32s(f, &s->pcmcia1);
+
+ qemu_set_irq(s->parent, s->intsetclr & s->intmskena);
return 0;
}
commit 8fe3046f17ff98469c5874a0e7be823adc768485
Author: Anthony Liguori <aliguori at us.ibm.com>
Date: Mon Feb 14 14:24:24 2011 -0600
Fix build from previous commit
I unfortunately got on an unnamed branch and pushed the wrong bits
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/slirp/mbuf.c b/slirp/mbuf.c
index eadc802..ce2eb84 100644
--- a/slirp/mbuf.c
+++ b/slirp/mbuf.c
@@ -65,7 +65,7 @@ m_get(Slirp *slirp)
m->m_flags = (flags | M_USEDLIST);
/* Initialise it */
- m->m_size = SLIRP_MSIZE - offsetof(struct m_hdr, m_dat);
+ m->m_size = SLIRP_MSIZE - offsetof(struct mbuf, m_dat);
m->m_data = m->m_dat;
m->m_len = 0;
m->m_nextpkt = NULL;
commit 53fae6d27f342a17bdc218dc51ccccebd99f3545
Author: Bruce Rogers <brogers at novell.com>
Date: Sat Feb 5 14:47:56 2011 -0700
PATCH] slirp: fix buffer overrun
Since the addition of the slirp member to struct mbuf, the value of
SLIRP_MSIZE and the initialization of m_size have not been correct,
resulting in overrunning the end of the malloc'd buffer in some cases.
Signed-off-by: Bruce Rogers <brogers at novell.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/slirp/mbuf.c b/slirp/mbuf.c
index 87508ba..eadc802 100644
--- a/slirp/mbuf.c
+++ b/slirp/mbuf.c
@@ -23,7 +23,7 @@
* Find a nice value for msize
* XXX if_maxlinkhdr already in mtu
*/
-#define SLIRP_MSIZE (IF_MTU + IF_MAXLINKHDR + sizeof(struct m_hdr ) + 6)
+#define SLIRP_MSIZE (IF_MTU + IF_MAXLINKHDR + offsetof(struct mbuf, m_dat) + 6)
void
m_init(Slirp *slirp)
@@ -65,7 +65,7 @@ m_get(Slirp *slirp)
m->m_flags = (flags | M_USEDLIST);
/* Initialise it */
- m->m_size = SLIRP_MSIZE - sizeof(struct m_hdr);
+ m->m_size = SLIRP_MSIZE - offsetof(struct m_hdr, m_dat);
m->m_data = m->m_dat;
m->m_len = 0;
m->m_nextpkt = NULL;
commit 0fbfbb59a9766247be20023b17eb7872e7b29323
Author: Gleb Natapov <gleb at redhat.com>
Date: Mon Feb 7 16:14:44 2011 +0200
correctly check ppr priority during interrupt injection]
TPR blocks all interrupts in a priority class, so simple "less or
equal" check is not enough.
Signed-off-by: Gleb Natapov <gleb at redhat.com>
Reviewed-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/hw/apic.c b/hw/apic.c
index 2f8376a..218d1bb 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -372,19 +372,36 @@ static int apic_get_arb_pri(APICState *s)
return 0;
}
-/* signal the CPU if an irq is pending */
-static void apic_update_irq(APICState *s)
+
+/*
+ * <0 - low prio interrupt,
+ * 0 - no interrupt,
+ * >0 - interrupt number
+ */
+static int apic_irq_pending(APICState *s)
{
int irrv, ppr;
- if (!(s->spurious_vec & APIC_SV_ENABLE))
- return;
irrv = get_highest_priority_int(s->irr);
- if (irrv < 0)
- return;
+ if (irrv < 0) {
+ return 0;
+ }
ppr = apic_get_ppr(s);
- if (ppr && (irrv & 0xf0) <= (ppr & 0xf0))
+ if (ppr && (irrv & 0xf0) <= (ppr & 0xf0)) {
+ return -1;
+ }
+
+ return irrv;
+}
+
+/* signal the CPU if an irq is pending */
+static void apic_update_irq(APICState *s)
+{
+ if (!(s->spurious_vec & APIC_SV_ENABLE)) {
return;
- cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
+ }
+ if (apic_irq_pending(s) > 0) {
+ cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
+ }
}
void apic_reset_irq_delivered(void)
@@ -590,12 +607,13 @@ int apic_get_interrupt(DeviceState *d)
if (!(s->spurious_vec & APIC_SV_ENABLE))
return -1;
- /* XXX: spurious IRQ handling */
- intno = get_highest_priority_int(s->irr);
- if (intno < 0)
+ intno = apic_irq_pending(s);
+
+ if (intno == 0) {
return -1;
- if (s->tpr && intno <= s->tpr)
+ } else if (intno < 0) {
return s->spurious_vec & 0xff;
+ }
reset_bit(s->irr, intno);
set_bit(s->isr, intno);
apic_update_irq(s);
commit ed94592be21557054f83962ffcfd7b11c25d3b5d
Author: Anthony Liguori <aliguori at us.ibm.com>
Date: Tue Feb 8 18:18:18 2011 +0100
io-thread: make sure to initialize qemu_work_cond and qemu_cpu_cond
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/cpus.c b/cpus.c
index 4c9928e..2d92090 100644
--- a/cpus.c
+++ b/cpus.c
@@ -412,8 +412,10 @@ int qemu_init_main_loop(void)
if (ret)
return ret;
- qemu_cond_init(&qemu_pause_cond);
+ qemu_cond_init(&qemu_cpu_cond);
qemu_cond_init(&qemu_system_cond);
+ qemu_cond_init(&qemu_pause_cond);
+ qemu_cond_init(&qemu_work_cond);
qemu_mutex_init(&qemu_fair_mutex);
qemu_mutex_init(&qemu_global_mutex);
qemu_mutex_lock(&qemu_global_mutex);
commit 8668f61d20eac971d116ebbe8436b4ae963884a8
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sat Feb 12 17:44:11 2011 +0000
vmmouse: fix queue_size field initialization
Initialize the field queue_size, dropped by
91c9e09147ba1f3604a3d5d29b4de7702082a33f.
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/vmmouse.c b/hw/vmmouse.c
index 11b125c..ab8dbd6 100644
--- a/hw/vmmouse.c
+++ b/hw/vmmouse.c
@@ -253,6 +253,7 @@ static void vmmouse_reset(DeviceState *d)
VMMouseState *s = container_of(d, VMMouseState, dev.qdev);
s->status = 0xffff;
+ s->queue_size = VMMOUSE_QUEUE_SIZE;
}
static int vmmouse_initfn(ISADevice *dev)
commit dd703b991cce99271a032a975885dd37d8c07a94
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sat Feb 5 14:35:00 2011 +0000
hpet: make optional
Ignore failure with hpet device creation.
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/Makefile.objs b/Makefile.objs
index dee251a..adb5842 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -195,6 +195,7 @@ hw-obj-$(CONFIG_FDC) += fdc.o
hw-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o
hw-obj-$(CONFIG_APM) += pm_smbus.o apm.o
hw-obj-$(CONFIG_DMA) += dma.o
+hw-obj-$(CONFIG_HPET) += hpet.o
# PPC devices
hw-obj-$(CONFIG_OPENPIC) += openpic.o
diff --git a/Makefile.target b/Makefile.target
index 3cf5ed9..a6c30dd 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -215,7 +215,7 @@ obj-$(CONFIG_KVM) += ivshmem.o
obj-i386-y += vga.o
obj-i386-y += mc146818rtc.o i8259.o pc.o
obj-i386-y += cirrus_vga.o apic.o ioapic.o piix_pci.o
-obj-i386-y += vmport.o hpet.o applesmc.o
+obj-i386-y += vmport.o applesmc.o
obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
obj-i386-y += debugcon.o multiboot.o
obj-i386-y += pc_piix.o
diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 9246293..3e0eddf 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -19,3 +19,4 @@ CONFIG_IDE_PIIX=y
CONFIG_NE2000_ISA=y
CONFIG_PIIX_PCI=y
CONFIG_SOUND=y
+CONFIG_HPET=y
diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index daf8c48..1cc1b61 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -19,3 +19,4 @@ CONFIG_IDE_PIIX=y
CONFIG_NE2000_ISA=y
CONFIG_PIIX_PCI=y
CONFIG_SOUND=y
+CONFIG_HPET=y
diff --git a/hw/hpet.c b/hw/hpet.c
index 8fb6811..82a9a21 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -74,8 +74,6 @@ typedef struct HPETState {
uint8_t hpet_id; /* instance id */
} HPETState;
-struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX};
-
static uint32_t hpet_in_legacy_mode(HPETState *s)
{
return s->config & HPET_CFG_LEGACY;
diff --git a/hw/pc.c b/hw/pc.c
index 00fe04e..56bf1d6 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -84,6 +84,7 @@ struct e820_table {
} __attribute((__packed__, __aligned__(4)));
static struct e820_table e820_table;
+struct hpet_fw_config hpet_cfg = {.count = UINT8_MAX};
void isa_irq_handler(void *opaque, int n, int level)
{
@@ -1104,12 +1105,14 @@ void pc_basic_device_init(qemu_irq *isa_irq,
register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
if (!no_hpet) {
- DeviceState *hpet = sysbus_create_simple("hpet", HPET_BASE, NULL);
+ DeviceState *hpet = sysbus_try_create_simple("hpet", HPET_BASE, NULL);
- for (i = 0; i < 24; i++) {
- sysbus_connect_irq(sysbus_from_qdev(hpet), i, isa_irq[i]);
+ if (hpet) {
+ for (i = 0; i < 24; i++) {
+ sysbus_connect_irq(sysbus_from_qdev(hpet), i, isa_irq[i]);
+ }
+ rtc_irq = qdev_get_gpio_in(hpet, 0);
}
- rtc_irq = qdev_get_gpio_in(hpet, 0);
}
*rtc_state = rtc_init(2000, rtc_irq);
commit 4912371fc39120fb7eb1a6b3f270fab30d05a7b6
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sat Feb 5 14:34:56 2011 +0000
sysbus: add creation function that may fail
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/sysbus.c b/hw/sysbus.c
index 1928b51..acad72a 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -173,6 +173,37 @@ DeviceState *sysbus_create_varargs(const char *name,
return dev;
}
+DeviceState *sysbus_try_create_varargs(const char *name,
+ target_phys_addr_t addr, ...)
+{
+ DeviceState *dev;
+ SysBusDevice *s;
+ va_list va;
+ qemu_irq irq;
+ int n;
+
+ dev = qdev_try_create(NULL, name);
+ if (!dev) {
+ return NULL;
+ }
+ s = sysbus_from_qdev(dev);
+ qdev_init_nofail(dev);
+ if (addr != (target_phys_addr_t)-1) {
+ sysbus_mmio_map(s, 0, addr);
+ }
+ va_start(va, addr);
+ n = 0;
+ while (1) {
+ irq = va_arg(va, qemu_irq);
+ if (!irq) {
+ break;
+ }
+ sysbus_connect_irq(s, n, irq);
+ n++;
+ }
+ return dev;
+}
+
static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent)
{
SysBusDevice *s = sysbus_from_qdev(dev);
diff --git a/hw/sysbus.h b/hw/sysbus.h
index e9eb618..4e8cb16 100644
--- a/hw/sysbus.h
+++ b/hw/sysbus.h
@@ -57,6 +57,8 @@ void sysbus_mmio_map(SysBusDevice *dev, int n, target_phys_addr_t addr);
/* Legacy helper function for creating devices. */
DeviceState *sysbus_create_varargs(const char *name,
target_phys_addr_t addr, ...);
+DeviceState *sysbus_try_create_varargs(const char *name,
+ target_phys_addr_t addr, ...);
static inline DeviceState *sysbus_create_simple(const char *name,
target_phys_addr_t addr,
qemu_irq irq)
@@ -64,4 +66,11 @@ static inline DeviceState *sysbus_create_simple(const char *name,
return sysbus_create_varargs(name, addr, irq, NULL);
}
+static inline DeviceState *sysbus_try_create_simple(const char *name,
+ target_phys_addr_t addr,
+ qemu_irq irq)
+{
+ return sysbus_try_create_varargs(name, addr, irq, NULL);
+}
+
#endif /* !HW_SYSBUS_H */
commit 86d864140bc597dce0fedf8547f4d615a920c444
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sat Feb 5 14:34:52 2011 +0000
x86: make vmmouse optional
Compile vmmouse in hwlib. Ignore failure if vmmouse device can't be
created.
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/Makefile.objs b/Makefile.objs
index 353b1a8..dee251a 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -258,6 +258,7 @@ hw-obj-$(CONFIG_VGA_PCI) += vga-pci.o
hw-obj-$(CONFIG_VGA_ISA) += vga-isa.o
hw-obj-$(CONFIG_VGA_ISA_MM) += vga-isa-mm.o
hw-obj-$(CONFIG_VMWARE_VGA) += vmware_vga.o
+hw-obj-$(CONFIG_VMMOUSE) += vmmouse.o
hw-obj-$(CONFIG_RC4030) += rc4030.o
hw-obj-$(CONFIG_DP8393X) += dp8393x.o
diff --git a/Makefile.target b/Makefile.target
index 48e6c00..3cf5ed9 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -215,7 +215,7 @@ obj-$(CONFIG_KVM) += ivshmem.o
obj-i386-y += vga.o
obj-i386-y += mc146818rtc.o i8259.o pc.o
obj-i386-y += cirrus_vga.o apic.o ioapic.o piix_pci.o
-obj-i386-y += vmmouse.o vmport.o hpet.o applesmc.o
+obj-i386-y += vmport.o hpet.o applesmc.o
obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
obj-i386-y += debugcon.o multiboot.o
obj-i386-y += pc_piix.o
diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 323fafb..9246293 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -4,6 +4,7 @@ include pci.mak
CONFIG_VGA_PCI=y
CONFIG_VGA_ISA=y
CONFIG_VMWARE_VGA=y
+CONFIG_VMMOUSE=y
CONFIG_SERIAL=y
CONFIG_PARALLEL=y
CONFIG_I8254=y
diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index eff26d2..daf8c48 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -4,6 +4,7 @@ include pci.mak
CONFIG_VGA_PCI=y
CONFIG_VGA_ISA=y
CONFIG_VMWARE_VGA=y
+CONFIG_VMMMOUSE=y
CONFIG_SERIAL=y
CONFIG_PARALLEL=y
CONFIG_I8254=y
diff --git a/hw/pc.c b/hw/pc.c
index cde20c0..00fe04e 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1134,8 +1134,10 @@ void pc_basic_device_init(qemu_irq *isa_irq,
i8042 = isa_create_simple("i8042");
i8042_setup_a20_line(i8042, &a20_line[0]);
vmport_init();
- vmmouse = isa_create("vmmouse");
- qdev_prop_set_ptr(&vmmouse->qdev, "ps2_mouse", i8042);
+ vmmouse = isa_try_create("vmmouse");
+ if (vmmouse) {
+ qdev_prop_set_ptr(&vmmouse->qdev, "ps2_mouse", i8042);
+ }
port92 = isa_create_simple("port92");
port92_init(port92, &a20_line[1]);
diff --git a/hw/pc.h b/hw/pc.h
index 3ae1462..d5d2f42 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -70,6 +70,8 @@ static inline void vmport_init(void)
isa_create_simple("vmport");
}
void vmport_register(unsigned char command, IOPortReadFunc *func, void *opaque);
+void vmmouse_get_data(uint32_t *data);
+void vmmouse_set_data(const uint32_t *data);
/* pckbd.c */
diff --git a/hw/vmmouse.c b/hw/vmmouse.c
index 3b39144..11b125c 100644
--- a/hw/vmmouse.c
+++ b/hw/vmmouse.c
@@ -178,30 +178,6 @@ static void vmmouse_data(VMMouseState *s, uint32_t *data, uint32_t size)
memmove(s->queue, &s->queue[size], sizeof(s->queue[0]) * s->nb_queue);
}
-static void vmmouse_get_data(uint32_t *data)
-{
- CPUState *env = cpu_single_env;
-
- data[0] = env->regs[R_EAX]; data[1] = env->regs[R_EBX];
- data[2] = env->regs[R_ECX]; data[3] = env->regs[R_EDX];
- data[4] = env->regs[R_ESI]; data[5] = env->regs[R_EDI];
-
- DPRINTF("get_data = {%x, %x, %x, %x, %x, %x}\n",
- data[0], data[1], data[2], data[3], data[4], data[5]);
-}
-
-static void vmmouse_set_data(const uint32_t *data)
-{
- CPUState *env = cpu_single_env;
-
- DPRINTF("set_data = {%x, %x, %x, %x, %x, %x}\n",
- data[0], data[1], data[2], data[3], data[4], data[5]);
-
- env->regs[R_EAX] = data[0]; env->regs[R_EBX] = data[1];
- env->regs[R_ECX] = data[2]; env->regs[R_EDX] = data[3];
- env->regs[R_ESI] = data[4]; env->regs[R_EDI] = data[5];
-}
-
static uint32_t vmmouse_ioport_read(void *opaque, uint32_t addr)
{
VMMouseState *s = opaque;
diff --git a/hw/vmport.c b/hw/vmport.c
index 4432be0..292d78f 100644
--- a/hw/vmport.c
+++ b/hw/vmport.c
@@ -102,6 +102,25 @@ static uint32_t vmport_cmd_ram_size(void *opaque, uint32_t addr)
return ram_size;
}
+/* vmmouse helpers */
+void vmmouse_get_data(uint32_t *data)
+{
+ CPUState *env = cpu_single_env;
+
+ data[0] = env->regs[R_EAX]; data[1] = env->regs[R_EBX];
+ data[2] = env->regs[R_ECX]; data[3] = env->regs[R_EDX];
+ data[4] = env->regs[R_ESI]; data[5] = env->regs[R_EDI];
+}
+
+void vmmouse_set_data(const uint32_t *data)
+{
+ CPUState *env = cpu_single_env;
+
+ env->regs[R_EAX] = data[0]; env->regs[R_EBX] = data[1];
+ env->regs[R_ECX] = data[2]; env->regs[R_EDX] = data[3];
+ env->regs[R_ESI] = data[4]; env->regs[R_EDI] = data[5];
+}
+
static int vmport_initfn(ISADevice *dev)
{
VMPortState *s = DO_UPCAST(VMPortState, dev, dev);
commit 86f4a9a5c7f1d98b73520ff9f396206ebc5ddb71
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sat Feb 5 14:34:48 2011 +0000
isa: add creation function that may fail
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/isa-bus.c b/hw/isa-bus.c
index 0cb1afb..6f349a5 100644
--- a/hw/isa-bus.c
+++ b/hw/isa-bus.c
@@ -146,6 +146,18 @@ ISADevice *isa_create(const char *name)
return DO_UPCAST(ISADevice, qdev, dev);
}
+ISADevice *isa_try_create(const char *name)
+{
+ DeviceState *dev;
+
+ if (!isabus) {
+ hw_error("Tried to create isa device %s with no isa bus present.",
+ name);
+ }
+ dev = qdev_try_create(&isabus->qbus, name);
+ return DO_UPCAST(ISADevice, qdev, dev);
+}
+
ISADevice *isa_create_simple(const char *name)
{
ISADevice *dev;
diff --git a/hw/isa.h b/hw/isa.h
index 19aa94c..e26abfa 100644
--- a/hw/isa.h
+++ b/hw/isa.h
@@ -32,6 +32,7 @@ void isa_init_ioport(ISADevice *dev, uint16_t ioport);
void isa_init_ioport_range(ISADevice *dev, uint16_t start, uint16_t length);
void isa_qdev_register(ISADeviceInfo *info);
ISADevice *isa_create(const char *name);
+ISADevice *isa_try_create(const char *name);
ISADevice *isa_create_simple(const char *name);
extern target_phys_addr_t isa_mem_base;
commit 91c9e09147ba1f3604a3d5d29b4de7702082a33f
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sat Feb 5 14:34:45 2011 +0000
vmmouse: convert to qdev
Convert to qdev, also add a proper reset function.
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/pc.c b/hw/pc.c
index c698161..cde20c0 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1096,7 +1096,7 @@ void pc_basic_device_init(qemu_irq *isa_irq,
PITState *pit;
qemu_irq rtc_irq = NULL;
qemu_irq *a20_line;
- ISADevice *i8042, *port92;
+ ISADevice *i8042, *port92, *vmmouse;
qemu_irq *cpu_exit_irq;
register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
@@ -1134,7 +1134,8 @@ void pc_basic_device_init(qemu_irq *isa_irq,
i8042 = isa_create_simple("i8042");
i8042_setup_a20_line(i8042, &a20_line[0]);
vmport_init();
- vmmouse_init(i8042);
+ vmmouse = isa_create("vmmouse");
+ qdev_prop_set_ptr(&vmmouse->qdev, "ps2_mouse", i8042);
port92 = isa_create_simple("port92");
port92_init(port92, &a20_line[1]);
diff --git a/hw/pc.h b/hw/pc.h
index a7feaae..3ae1462 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -71,9 +71,6 @@ static inline void vmport_init(void)
}
void vmport_register(unsigned char command, IOPortReadFunc *func, void *opaque);
-/* vmmouse.c */
-void *vmmouse_init(void *m);
-
/* pckbd.c */
void i8042_init(qemu_irq kbd_irq, qemu_irq mouse_irq, uint32_t io_base);
diff --git a/hw/vmmouse.c b/hw/vmmouse.c
index 2097119..3b39144 100644
--- a/hw/vmmouse.c
+++ b/hw/vmmouse.c
@@ -25,6 +25,7 @@
#include "console.h"
#include "ps2.h"
#include "pc.h"
+#include "qdev.h"
/* debug only vmmouse */
//#define DEBUG_VMMOUSE
@@ -52,6 +53,7 @@
typedef struct _VMMouseState
{
+ ISADevice dev;
uint32_t queue[VMMOUSE_QUEUE_SIZE];
int32_t queue_size;
uint16_t nb_queue;
@@ -270,22 +272,41 @@ static const VMStateDescription vmstate_vmmouse = {
}
};
-void *vmmouse_init(void *m)
+static void vmmouse_reset(DeviceState *d)
{
- VMMouseState *s = NULL;
+ VMMouseState *s = container_of(d, VMMouseState, dev.qdev);
- DPRINTF("vmmouse_init\n");
+ s->status = 0xffff;
+}
- s = qemu_mallocz(sizeof(VMMouseState));
+static int vmmouse_initfn(ISADevice *dev)
+{
+ VMMouseState *s = DO_UPCAST(VMMouseState, dev, dev);
- s->status = 0xffff;
- s->ps2_mouse = m;
- s->queue_size = VMMOUSE_QUEUE_SIZE;
+ DPRINTF("vmmouse_init\n");
vmport_register(VMMOUSE_STATUS, vmmouse_ioport_read, s);
vmport_register(VMMOUSE_COMMAND, vmmouse_ioport_read, s);
vmport_register(VMMOUSE_DATA, vmmouse_ioport_read, s);
vmstate_register(NULL, 0, &vmstate_vmmouse, s);
- return s;
+ return 0;
+}
+
+static ISADeviceInfo vmmouse_info = {
+ .init = vmmouse_initfn,
+ .qdev.name = "vmmouse",
+ .qdev.size = sizeof(VMMouseState),
+ .qdev.no_user = 1,
+ .qdev.reset = vmmouse_reset,
+ .qdev.props = (Property[]) {
+ DEFINE_PROP_PTR("ps2_mouse", VMMouseState, ps2_mouse),
+ DEFINE_PROP_END_OF_LIST(),
+ }
+};
+
+static void vmmouse_dev_register(void)
+{
+ isa_qdev_register(&vmmouse_info);
}
+device_init(vmmouse_dev_register)
commit 6872ef610bad337701e0dcb0ab06558c04a0146f
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sat Feb 5 14:34:41 2011 +0000
vmport: convert to qdev
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/pc.c b/hw/pc.c
index fcee09a..c698161 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1133,6 +1133,7 @@ void pc_basic_device_init(qemu_irq *isa_irq,
a20_line = qemu_allocate_irqs(handle_a20_line_change, first_cpu, 2);
i8042 = isa_create_simple("i8042");
i8042_setup_a20_line(i8042, &a20_line[0]);
+ vmport_init();
vmmouse_init(i8042);
port92 = isa_create_simple("port92");
port92_init(port92, &a20_line[1]);
diff --git a/hw/pc.h b/hw/pc.h
index a048768..a7feaae 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -65,7 +65,10 @@ void hpet_pit_disable(void);
void hpet_pit_enable(void);
/* vmport.c */
-void vmport_init(void);
+static inline void vmport_init(void)
+{
+ isa_create_simple("vmport");
+}
void vmport_register(unsigned char command, IOPortReadFunc *func, void *opaque);
/* vmmouse.c */
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 7b74473..d0bd0cd 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -86,8 +86,6 @@ static void pc_init1(ram_addr_t ram_size,
pc_cpus_init(cpu_model);
- vmport_init();
-
/* allocate ram and load rom/bios */
pc_memory_init(ram_size, kernel_filename, kernel_cmdline, initrd_filename,
&below_4g_mem_size, &above_4g_mem_size);
diff --git a/hw/vmport.c b/hw/vmport.c
index 6c9d7c9..4432be0 100644
--- a/hw/vmport.c
+++ b/hw/vmport.c
@@ -26,6 +26,7 @@
#include "pc.h"
#include "sysemu.h"
#include "kvm.h"
+#include "qdev.h"
//#define VMPORT_DEBUG
@@ -37,6 +38,7 @@
typedef struct _VMPortState
{
+ ISADevice dev;
IOPortReadFunc *func[VMPORT_ENTRIES];
void *opaque[VMPORT_ENTRIES];
} VMPortState;
@@ -100,12 +102,28 @@ static uint32_t vmport_cmd_ram_size(void *opaque, uint32_t addr)
return ram_size;
}
-void vmport_init(void)
+static int vmport_initfn(ISADevice *dev)
{
- register_ioport_read(0x5658, 1, 4, vmport_ioport_read, &port_state);
- register_ioport_write(0x5658, 1, 4, vmport_ioport_write, &port_state);
+ VMPortState *s = DO_UPCAST(VMPortState, dev, dev);
+ register_ioport_read(0x5658, 1, 4, vmport_ioport_read, &s);
+ register_ioport_write(0x5658, 1, 4, vmport_ioport_write, &s);
+ isa_init_ioport(dev, 0x5658);
/* Register some generic port commands */
vmport_register(VMPORT_CMD_GETVERSION, vmport_cmd_get_version, NULL);
vmport_register(VMPORT_CMD_GETRAMSIZE, vmport_cmd_ram_size, NULL);
+ return 0;
}
+
+static ISADeviceInfo vmport_info = {
+ .qdev.name = "vmport",
+ .qdev.size = sizeof(VMPortState),
+ .qdev.no_user = 1,
+ .init = vmport_initfn,
+};
+
+static void vmport_dev_register(void)
+{
+ isa_qdev_register(&vmport_info);
+}
+device_init(vmport_dev_register)
commit 7ba7e49e6a7493e1cd0fe07cc67403846d642fc5
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sat Feb 5 14:34:37 2011 +0000
x86,MIPS: make vmware_vga optional
Allow failure with vmware_vga device creation and use standard
VGA instead.
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 2d3f242..930c51c 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -957,7 +957,11 @@ void mips_malta_init (ram_addr_t ram_size,
if (cirrus_vga_enabled) {
pci_cirrus_vga_init(pci_bus);
} else if (vmsvga_enabled) {
- pci_vmsvga_init(pci_bus);
+ if (!pci_vmsvga_init(pci_bus)) {
+ fprintf(stderr, "Warning: vmware_vga not available,"
+ " using standard VGA instead\n");
+ pci_vga_init(pci_bus);
+ }
} else if (std_vga_enabled) {
pci_vga_init(pci_bus);
}
diff --git a/hw/pc.c b/hw/pc.c
index 4dfdc0b..fcee09a 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1053,10 +1053,15 @@ void pc_vga_init(PCIBus *pci_bus)
isa_cirrus_vga_init();
}
} else if (vmsvga_enabled) {
- if (pci_bus)
- pci_vmsvga_init(pci_bus);
- else
+ if (pci_bus) {
+ if (!pci_vmsvga_init(pci_bus)) {
+ fprintf(stderr, "Warning: vmware_vga not available,"
+ " using standard VGA instead\n");
+ pci_vga_init(pci_bus);
+ }
+ } else {
fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__);
+ }
#ifdef CONFIG_SPICE
} else if (qxl_enabled) {
if (pci_bus)
diff --git a/hw/vmware_vga.h b/hw/vmware_vga.h
index e7bcb22..5132573 100644
--- a/hw/vmware_vga.h
+++ b/hw/vmware_vga.h
@@ -4,9 +4,16 @@
#include "qemu-common.h"
/* vmware_vga.c */
-static inline void pci_vmsvga_init(PCIBus *bus)
+static inline bool pci_vmsvga_init(PCIBus *bus)
{
- pci_create_simple(bus, -1, "vmware-svga");
+ PCIDevice *dev;
+
+ dev = pci_try_create(bus, -1, "vmware-svga");
+ if (!dev || qdev_init(&dev->qdev) < 0) {
+ return false;
+ } else {
+ return true;
+ }
}
#endif
commit 7cc050b1659545d0c87108c17f0bf78561efcf9a
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sat Feb 5 14:34:32 2011 +0000
pci: add creation functions that may fail
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/pci.c b/hw/pci.c
index d5bbba9..5e6e216 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1708,6 +1708,21 @@ PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction,
return DO_UPCAST(PCIDevice, qdev, dev);
}
+PCIDevice *pci_try_create_multifunction(PCIBus *bus, int devfn,
+ bool multifunction,
+ const char *name)
+{
+ DeviceState *dev;
+
+ dev = qdev_try_create(&bus->qbus, name);
+ if (!dev) {
+ return NULL;
+ }
+ qdev_prop_set_uint32(dev, "addr", devfn);
+ qdev_prop_set_bit(dev, "multifunction", multifunction);
+ return DO_UPCAST(PCIDevice, qdev, dev);
+}
+
PCIDevice *pci_create_simple_multifunction(PCIBus *bus, int devfn,
bool multifunction,
const char *name)
@@ -1727,6 +1742,11 @@ PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name)
return pci_create_simple_multifunction(bus, devfn, false, name);
}
+PCIDevice *pci_try_create(PCIBus *bus, int devfn, const char *name)
+{
+ return pci_try_create_multifunction(bus, devfn, false, name);
+}
+
static int pci_find_space(PCIDevice *pdev, uint8_t size)
{
int config_size = pci_config_size(pdev);
diff --git a/hw/pci.h b/hw/pci.h
index 0d2753f..113e556 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -453,8 +453,12 @@ PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction,
PCIDevice *pci_create_simple_multifunction(PCIBus *bus, int devfn,
bool multifunction,
const char *name);
+PCIDevice *pci_try_create_multifunction(PCIBus *bus, int devfn,
+ bool multifunction,
+ const char *name);
PCIDevice *pci_create(PCIBus *bus, int devfn, const char *name);
PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name);
+PCIDevice *pci_try_create(PCIBus *bus, int devfn, const char *name);
static inline int pci_is_express(const PCIDevice *d)
{
commit 0bcdeda7e478f1ce1345585d8240e8d5a9b274d5
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sat Feb 5 14:34:25 2011 +0000
qdev: add creation function that may fail
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/qdev.c b/hw/qdev.c
index c7fec44..1aa1ea0 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -106,6 +106,18 @@ static DeviceState *qdev_create_from_info(BusState *bus, DeviceInfo *info)
initialize the actual device emulation. */
DeviceState *qdev_create(BusState *bus, const char *name)
{
+ DeviceState *dev;
+
+ dev = qdev_try_create(bus, name);
+ if (!dev) {
+ hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
+ }
+
+ return dev;
+}
+
+DeviceState *qdev_try_create(BusState *bus, const char *name)
+{
DeviceInfo *info;
if (!bus) {
@@ -114,7 +126,7 @@ DeviceState *qdev_create(BusState *bus, const char *name)
info = qdev_find_info(bus->info, name);
if (!info) {
- hw_error("Unknown device '%s' for bus '%s'\n", name, bus->info->name);
+ return NULL;
}
return qdev_create_from_info(bus, info);
diff --git a/hw/qdev.h b/hw/qdev.h
index 9808f85..8a13ec9 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -122,6 +122,7 @@ typedef struct GlobalProperty {
/*** Board API. This should go away once we have a machine config file. ***/
DeviceState *qdev_create(BusState *bus, const char *name);
+DeviceState *qdev_try_create(BusState *bus, const char *name);
int qdev_device_help(QemuOpts *opts);
DeviceState *qdev_device_add(QemuOpts *opts);
int qdev_init(DeviceState *dev) QEMU_WARN_UNUSED_RESULT;
commit 5c81e4ca9e5c11239a9db12f0f57c6c1e24b6760
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sat Feb 5 14:34:19 2011 +0000
vmware_vga: refactor device creation
Turn vmsvga_init into an inline function.
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index 6c59053..4656767 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -1309,11 +1309,6 @@ static int pci_vmsvga_initfn(PCIDevice *dev)
return 0;
}
-void pci_vmsvga_init(PCIBus *bus)
-{
- pci_create_simple(bus, -1, "vmware-svga");
-}
-
static PCIDeviceInfo vmsvga_info = {
.qdev.name = "vmware-svga",
.qdev.size = sizeof(struct pci_vmsvga_state_s),
diff --git a/hw/vmware_vga.h b/hw/vmware_vga.h
index 2e0813c..e7bcb22 100644
--- a/hw/vmware_vga.h
+++ b/hw/vmware_vga.h
@@ -4,6 +4,9 @@
#include "qemu-common.h"
/* vmware_vga.c */
-void pci_vmsvga_init(PCIBus *bus);
+static inline void pci_vmsvga_init(PCIBus *bus)
+{
+ pci_create_simple(bus, -1, "vmware-svga");
+}
#endif
commit 55619bb667a681d248009f3b10094b6cf121671f
Author: Andrzej Zaborowski <balrog at zabor.org>
Date: Fri Feb 11 23:35:20 2011 +0100
mst_fpga: Drop one more pxa.h inclusion.
Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>
diff --git a/hw/mst_fpga.c b/hw/mst_fpga.c
index b59352b..93c6514 100644
--- a/hw/mst_fpga.c
+++ b/hw/mst_fpga.c
@@ -8,7 +8,6 @@
* This code is licensed under the GNU GPL v2.
*/
#include "hw.h"
-#include "pxa.h"
#include "mainstone.h"
/* Mainstone FPGA for extern irqs */
commit c8ba63f829631fef24a9aed6451fb7c8830384f6
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date: Fri Feb 11 23:57:39 2011 +0300
pxa2xx: convert i2c master to use qdev/vmsd
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index d966846..9ebbce6 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -1262,10 +1262,12 @@ typedef struct {
} PXA2xxI2CSlaveState;
struct PXA2xxI2CState {
+ SysBusDevice busdev;
PXA2xxI2CSlaveState *slave;
i2c_bus *bus;
qemu_irq irq;
- target_phys_addr_t offset;
+ uint32_t offset;
+ uint32_t region_size;
uint16_t control;
uint16_t status;
@@ -1499,27 +1501,42 @@ static I2CSlaveInfo pxa2xx_i2c_slave_info = {
PXA2xxI2CState *pxa2xx_i2c_init(target_phys_addr_t base,
qemu_irq irq, uint32_t region_size)
{
- int iomemtype;
DeviceState *dev;
- PXA2xxI2CState *s = qemu_mallocz(sizeof(PXA2xxI2CState));
+ SysBusDevice *i2c_dev;
+ PXA2xxI2CState *s;
+
+ i2c_dev = sysbus_from_qdev(qdev_create(NULL, "pxa2xx_i2c"));
+ qdev_prop_set_uint32(&i2c_dev->qdev, "size", region_size + 1);
+ qdev_prop_set_uint32(&i2c_dev->qdev, "offset",
+ base - (base & (~region_size) & TARGET_PAGE_MASK));
+
+ qdev_init_nofail(&i2c_dev->qdev);
+
+ sysbus_mmio_map(i2c_dev, 0, base & ~region_size);
+ sysbus_connect_irq(i2c_dev, 0, irq);
+ s = FROM_SYSBUS(PXA2xxI2CState, i2c_dev);
/* FIXME: Should the slave device really be on a separate bus? */
dev = i2c_create_slave(i2c_init_bus(NULL, "dummy"), "pxa2xx-i2c-slave", 0);
s->slave = FROM_I2C_SLAVE(PXA2xxI2CSlaveState, I2C_SLAVE_FROM_QDEV(dev));
s->slave->host = s;
- s->irq = irq;
- s->bus = i2c_init_bus(NULL, "i2c");
- s->offset = base - (base & (~region_size) & TARGET_PAGE_MASK);
+ return s;
+}
+
+static int pxa2xx_i2c_initfn(SysBusDevice *dev)
+{
+ PXA2xxI2CState *s = FROM_SYSBUS(PXA2xxI2CState, dev);
+ int iomemtype;
+
+ s->bus = i2c_init_bus(&dev->qdev, "i2c");
iomemtype = cpu_register_io_memory(pxa2xx_i2c_readfn,
pxa2xx_i2c_writefn, s, DEVICE_NATIVE_ENDIAN);
- cpu_register_physical_memory(base & ~region_size,
- region_size + 1, iomemtype);
-
- vmstate_register(NULL, base, &vmstate_pxa2xx_i2c, s);
+ sysbus_init_mmio(dev, s->region_size, iomemtype);
+ sysbus_init_irq(dev, &s->irq);
- return s;
+ return 0;
}
i2c_bus *pxa2xx_i2c_bus(PXA2xxI2CState *s)
@@ -1527,6 +1544,19 @@ i2c_bus *pxa2xx_i2c_bus(PXA2xxI2CState *s)
return s->bus;
}
+static SysBusDeviceInfo pxa2xx_i2c_info = {
+ .init = pxa2xx_i2c_initfn,
+ .qdev.name = "pxa2xx_i2c",
+ .qdev.desc = "PXA2xx I2C Bus Controller",
+ .qdev.size = sizeof(PXA2xxI2CState),
+ .qdev.vmsd = &vmstate_pxa2xx_i2c,
+ .qdev.props = (Property[]) {
+ DEFINE_PROP_UINT32("size", PXA2xxI2CState, region_size, 0x10000),
+ DEFINE_PROP_UINT32("offset", PXA2xxI2CState, offset, 0),
+ DEFINE_PROP_END_OF_LIST(),
+ },
+};
+
/* PXA Inter-IC Sound Controller */
static void pxa2xx_i2s_reset(PXA2xxI2SState *i2s)
{
@@ -2287,6 +2317,7 @@ static void pxa2xx_register_devices(void)
{
i2c_register_slave(&pxa2xx_i2c_slave_info);
sysbus_register_dev("pxa2xx-ssp", sizeof(PXA2xxSSPState), pxa2xx_ssp_init);
+ sysbus_register_withprop(&pxa2xx_i2c_info);
}
device_init(pxa2xx_register_devices)
commit 987e8b3b03c2420e451ac91df4330ff767b56bb0
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date: Fri Feb 11 23:57:38 2011 +0300
max7310: finish qdev'ication
1) Move GPIO-related functionality to qdev. Now one can use directly
qdev_get_gpio_in()/qdev_connect_gpio_out() on max7310 devices.
2) Make reset to be called through qdev.reset callback.
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>
diff --git a/hw/i2c.h b/hw/i2c.h
index 83fd917..5514402 100644
--- a/hw/i2c.h
+++ b/hw/i2c.h
@@ -59,11 +59,6 @@ void i2c_register_slave(I2CSlaveInfo *type);
DeviceState *i2c_create_slave(i2c_bus *bus, const char *name, uint8_t addr);
-/* max7310.c */
-void max7310_reset(i2c_slave *i2c);
-qemu_irq *max7310_gpio_in_get(i2c_slave *i2c);
-void max7310_gpio_out_set(i2c_slave *i2c, int line, qemu_irq handler);
-
/* wm8750.c */
void wm8750_data_req_set(DeviceState *dev,
void (*data_req)(void *, int, int), void *opaque);
diff --git a/hw/max7310.c b/hw/max7310.c
index c302eb6..c1bdb2e 100644
--- a/hw/max7310.c
+++ b/hw/max7310.c
@@ -23,9 +23,9 @@ typedef struct {
qemu_irq *gpio_in;
} MAX7310State;
-void max7310_reset(i2c_slave *i2c)
+static void max7310_reset(DeviceState *dev)
{
- MAX7310State *s = (MAX7310State *) i2c;
+ MAX7310State *s = FROM_I2C_SLAVE(MAX7310State, I2C_SLAVE_FROM_QDEV(dev));
s->level &= s->direction;
s->direction = 0xff;
s->polarity = 0xf0;
@@ -179,33 +179,17 @@ static int max7310_init(i2c_slave *i2c)
{
MAX7310State *s = FROM_I2C_SLAVE(MAX7310State, i2c);
- s->gpio_in = qemu_allocate_irqs(max7310_gpio_set, s,
- ARRAY_SIZE(s->handler));
-
- max7310_reset(&s->i2c);
+ qdev_init_gpio_in(&i2c->qdev, max7310_gpio_set, 8);
+ qdev_init_gpio_out(&i2c->qdev, s->handler, 8);
return 0;
}
-qemu_irq *max7310_gpio_in_get(i2c_slave *i2c)
-{
- MAX7310State *s = (MAX7310State *) i2c;
- return s->gpio_in;
-}
-
-void max7310_gpio_out_set(i2c_slave *i2c, int line, qemu_irq handler)
-{
- MAX7310State *s = (MAX7310State *) i2c;
- if (line >= ARRAY_SIZE(s->handler) || line < 0)
- hw_error("bad GPIO line");
-
- s->handler[line] = handler;
-}
-
static I2CSlaveInfo max7310_info = {
.qdev.name = "max7310",
.qdev.size = sizeof(MAX7310State),
.qdev.vmsd = &vmstate_max7310,
+ .qdev.reset = max7310_reset,
.init = max7310_init,
.event = max7310_event,
.recv = max7310_rx,
commit 2e4b4e79c6da9780d5f51a992249b51818ba5959
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date: Fri Feb 11 23:57:37 2011 +0300
tosa: we aren't connected to VBus, pass this info to Linux kernel
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>
diff --git a/hw/tosa.c b/hw/tosa.c
index 0bfab16..b8b6c4f 100644
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -25,6 +25,7 @@
#define TOSA_RAM 0x04000000
#define TOSA_ROM 0x00800000
+#define TOSA_GPIO_USB_IN (5)
#define TOSA_GPIO_nSD_DETECT (9)
#define TOSA_GPIO_ON_RESET (19)
#define TOSA_GPIO_CF_IRQ (21) /* CF slot0 Ready */
@@ -115,6 +116,9 @@ static void tosa_gpio_setup(PXA2xxState *cpu,
qdev_connect_gpio_out(scp1, TOSA_GPIO_WLAN_LED, outsignals[3]);
qdev_connect_gpio_out(scp1, TOSA_GPIO_TC6393XB_L3V_ON, tc6393xb_l3v_get(tmio));
+
+ /* UDC Vbus */
+ qemu_irq_raise(qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_USB_IN));
}
static uint32_t tosa_ssp_tansfer(SSISlave *dev, uint32_t value)
commit bb70651e45c798d301549aa2e12ea6beb858c21d
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date: Fri Feb 11 23:57:35 2011 +0300
mainstone: pass one irq to the mst_fpga instead of the whole PIC
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>
diff --git a/hw/mainstone.c b/hw/mainstone.c
index 58e3f86..18d1415 100644
--- a/hw/mainstone.c
+++ b/hw/mainstone.c
@@ -117,7 +117,7 @@ static void mainstone_common_init(ram_addr_t ram_size,
}
}
- mst_irq = mst_irq_init(cpu, MST_FPGA_PHYS, PXA2XX_PIC_GPIO_0);
+ mst_irq = mst_irq_init(MST_FPGA_PHYS, cpu->pic[PXA2XX_PIC_GPIO_0]);
/* setup keypad */
printf("map addr %p\n", &map);
diff --git a/hw/mainstone.h b/hw/mainstone.h
index 9618c06..35329f1 100644
--- a/hw/mainstone.h
+++ b/hw/mainstone.h
@@ -33,6 +33,6 @@
#define S1_IRQ 15
extern qemu_irq
-*mst_irq_init(PXA2xxState *cpu, uint32_t base, int irq);
+*mst_irq_init(uint32_t base, qemu_irq irq);
#endif /* __MAINSTONE_H__ */
diff --git a/hw/mst_fpga.c b/hw/mst_fpga.c
index 5252fc5..b59352b 100644
--- a/hw/mst_fpga.c
+++ b/hw/mst_fpga.c
@@ -28,7 +28,7 @@
#define MST_PCMCIA1 0xe4
typedef struct mst_irq_state{
- qemu_irq *parent;
+ qemu_irq parent;
qemu_irq *pins;
uint32_t prev_level;
@@ -72,7 +72,7 @@ mst_fpga_set_irq(void *opaque, int irq, int level)
if(s->intmskena & (1u << irq)) {
s->intsetclr = 1u << irq;
- qemu_set_irq(s->parent[0], level);
+ qemu_set_irq(s->parent, level);
}
}
@@ -109,7 +109,7 @@ mst_fpga_readb(void *opaque, target_phys_addr_t addr)
return s->pcmcia1;
default:
printf("Mainstone - mst_fpga_readb: Bad register offset "
- REG_FMT " \n", addr);
+ "0x" TARGET_FMT_plx " \n", addr);
}
return 0;
}
@@ -160,7 +160,7 @@ mst_fpga_writeb(void *opaque, target_phys_addr_t addr, uint32_t value)
break;
default:
printf("Mainstone - mst_fpga_writeb: Bad register offset "
- REG_FMT " \n", addr);
+ "0x" TARGET_FMT_plx " \n", addr);
}
}
@@ -216,7 +216,7 @@ mst_fpga_load(QEMUFile *f, void *opaque, int version_id)
return 0;
}
-qemu_irq *mst_irq_init(PXA2xxState *cpu, uint32_t base, int irq)
+qemu_irq *mst_irq_init(uint32_t base, qemu_irq irq)
{
mst_irq_state *s;
int iomemtype;
@@ -225,7 +225,7 @@ qemu_irq *mst_irq_init(PXA2xxState *cpu, uint32_t base, int irq)
s = (mst_irq_state *)
qemu_mallocz(sizeof(mst_irq_state));
- s->parent = &cpu->pic[irq];
+ s->parent = irq;
/* alloc the external 16 irqs */
qi = qemu_allocate_irqs(mst_fpga_set_irq, s, MST_NUM_IRQS);
commit 21c75ddbf9487cd24bc9cceff1af1946e42143c0
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date: Fri Feb 11 23:57:34 2011 +0300
Drop unnecessary inclusions of pxa.h header
Seceral files contained onnecessary dependencies on hw/pxa.h header.
Drop unused references.
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>
diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c
index 0cadcde..ed49e94 100644
--- a/hw/tc6393xb.c
+++ b/hw/tc6393xb.c
@@ -8,7 +8,6 @@
* This code is licensed under the GNU GPL v2.
*/
#include "hw.h"
-#include "pxa.h"
#include "devices.h"
#include "flash.h"
#include "console.h"
diff --git a/hw/zaurus.c b/hw/zaurus.c
index fb5e228..c24aeb5 100644
--- a/hw/zaurus.c
+++ b/hw/zaurus.c
@@ -16,7 +16,6 @@
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "hw.h"
-#include "pxa.h"
#include "sharpsl.h"
#include "sysbus.h"
commit 7fe63a170addbfadd785b70c6a1e9a49d113c89b
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date: Fri Feb 11 23:57:33 2011 +0300
Add scoop post_load callback that sets IRQs to loaded levels
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>
diff --git a/hw/zaurus.c b/hw/zaurus.c
index fca11a5..fb5e228 100644
--- a/hw/zaurus.c
+++ b/hw/zaurus.c
@@ -181,17 +181,34 @@ static int scoop_init(SysBusDevice *dev)
return 0;
}
+static int scoop_post_load(void *opaque, int version_id)
+{
+ ScoopInfo *s = (ScoopInfo *) opaque;
+ int i;
+ uint32_t level;
+
+ level = s->gpio_level & s->gpio_dir;
+
+ for (i = 0; i < 16; i++) {
+ qemu_set_irq(s->handler[i], (level >> i) & 1);
+ }
+
+ s->prev_level = level;
+
+ return 0;
+}
+
static bool is_version_0 (void *opaque, int version_id)
{
return version_id == 0;
}
-
static const VMStateDescription vmstate_scoop_regs = {
.name = "scoop",
.version_id = 1,
.minimum_version_id = 0,
.minimum_version_id_old = 0,
+ .post_load = scoop_post_load,
.fields = (VMStateField []) {
VMSTATE_UINT16(status, ScoopInfo),
VMSTATE_UINT16(power, ScoopInfo),
commit f23c1b2a38b1c77261c761cc2b9795d98065386f
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date: Mon Jan 31 18:20:46 2011 +0300
tc6393xb: correct NAND isr assertion
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>
diff --git a/hw/tc6393xb.c b/hw/tc6393xb.c
index c3fbe4e..0cadcde 100644
--- a/hw/tc6393xb.c
+++ b/hw/tc6393xb.c
@@ -381,7 +381,7 @@ static void tc6393xb_nand_writeb(TC6393xbState *s, target_phys_addr_t addr, uint
case NAND_DATA + 2:
case NAND_DATA + 3:
nand_setio(s->flash, value);
- s->nand.isr &= 1;
+ s->nand.isr |= 1;
tc6393xb_nand_irq(s);
return;
case NAND_MODE:
commit 0fba9fd6c305fd1fbe950eb4136dc9edc36cb3fd
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date: Mon Jan 31 18:20:41 2011 +0300
sysbus: print number of irqs in dev_print
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>
diff --git a/hw/sysbus.c b/hw/sysbus.c
index 1583bd8..1928b51 100644
--- a/hw/sysbus.c
+++ b/hw/sysbus.c
@@ -178,6 +178,7 @@ static void sysbus_dev_print(Monitor *mon, DeviceState *dev, int indent)
SysBusDevice *s = sysbus_from_qdev(dev);
int i;
+ monitor_printf(mon, "%*sirq %d\n", indent, "", s->num_irq);
for (i = 0; i < s->num_mmio; i++) {
monitor_printf(mon, "%*smmio " TARGET_FMT_plx "/" TARGET_FMT_plx "\n",
indent, "", s->mmio[i].addr, s->mmio[i].size);
commit 7a719c7ce55549dc226f3a4d465d3a5ed99fd8ac
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date: Mon Jan 31 18:20:40 2011 +0300
.gitignore: ignore vi swap files and ctags files
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>
diff --git a/.gitignore b/.gitignore
index 3efb4ec..26703e1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -51,6 +51,8 @@ QMP/qmp-commands.txt
*.vr
*.d
*.o
+*.swp
+*.orig
.pc
patches
pc-bios/bios-pq/status
@@ -60,3 +62,4 @@ pc-bios/optionrom/multiboot.bin
pc-bios/optionrom/multiboot.raw
.stgit-*
cscope.*
+tags
commit 3213883efa336de4e0b573df8e55983eafad1ff3
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date: Mon Jan 31 18:20:42 2011 +0300
arm: drop unused irq-related part of CPUARMState
These two fields were added as a part of ARMv7 support patch (back in
2007), were never used by any code, so can be dropped.
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 0d96325..c9febfa 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -157,10 +157,6 @@ typedef struct CPUARMState {
/* Internal CPU feature flags. */
uint32_t features;
- /* Callback for vectored interrupt controller. */
- int (*get_irq_vector)(struct CPUARMState *);
- void *irq_opaque;
-
/* VFP coprocessor state. */
struct {
float64 regs[32];
commit f2f27b9f9bff33217ad1ee9f975f5e98980a8f1a
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Thu Feb 10 15:47:14 2011 +0000
target-arm: Remove stray #include from middle of neon_helper.c
Remove a stray #include <stdio.h> from the middle of neon_helper.c:
it was harmless but pointless since we include stdio.h at the top
of the file anyway.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index 61890dd..dc09968 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -1484,7 +1484,6 @@ uint64_t HELPER(neon_negl_u16)(uint64_t x)
return result;
}
-#include <stdio.h>
uint64_t HELPER(neon_negl_u32)(uint64_t x)
{
uint32_t low = -x;
commit 005e1a0a02810ee132742d8a29771cd48a2b4285
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Thu Feb 10 13:59:35 2011 +0000
linux-user/arm: fix compilation failures using softfloat's struct types
Add uses of the float32/float64 boxing and unboxing macros so that
the ARM linux-user targets will compile with USE_SOFTFLOAT_STRUCT_TYPES
enabled.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/linux-user/arm/nwfpe/fpa11_cpdt.c b/linux-user/arm/nwfpe/fpa11_cpdt.c
index 1346fd6..b12e27d 100644
--- a/linux-user/arm/nwfpe/fpa11_cpdt.c
+++ b/linux-user/arm/nwfpe/fpa11_cpdt.c
@@ -33,7 +33,7 @@ void loadSingle(const unsigned int Fn, target_ulong addr)
FPA11 *fpa11 = GET_FPA11();
fpa11->fType[Fn] = typeSingle;
/* FIXME - handle failure of get_user() */
- get_user_u32(fpa11->fpreg[Fn].fSingle, addr);
+ get_user_u32(float32_val(fpa11->fpreg[Fn].fSingle), addr);
}
static inline
diff --git a/linux-user/arm/nwfpe/fpopcode.c b/linux-user/arm/nwfpe/fpopcode.c
index 240061d..82ac92f 100644
--- a/linux-user/arm/nwfpe/fpopcode.c
+++ b/linux-user/arm/nwfpe/fpopcode.c
@@ -37,25 +37,25 @@ const floatx80 floatx80Constant[] = {
};
const float64 float64Constant[] = {
- 0x0000000000000000ULL, /* double 0.0 */
- 0x3ff0000000000000ULL, /* double 1.0 */
- 0x4000000000000000ULL, /* double 2.0 */
- 0x4008000000000000ULL, /* double 3.0 */
- 0x4010000000000000ULL, /* double 4.0 */
- 0x4014000000000000ULL, /* double 5.0 */
- 0x3fe0000000000000ULL, /* double 0.5 */
- 0x4024000000000000ULL /* double 10.0 */
+ const_float64(0x0000000000000000ULL), /* double 0.0 */
+ const_float64(0x3ff0000000000000ULL), /* double 1.0 */
+ const_float64(0x4000000000000000ULL), /* double 2.0 */
+ const_float64(0x4008000000000000ULL), /* double 3.0 */
+ const_float64(0x4010000000000000ULL), /* double 4.0 */
+ const_float64(0x4014000000000000ULL), /* double 5.0 */
+ const_float64(0x3fe0000000000000ULL), /* double 0.5 */
+ const_float64(0x4024000000000000ULL) /* double 10.0 */
};
const float32 float32Constant[] = {
- 0x00000000, /* single 0.0 */
- 0x3f800000, /* single 1.0 */
- 0x40000000, /* single 2.0 */
- 0x40400000, /* single 3.0 */
- 0x40800000, /* single 4.0 */
- 0x40a00000, /* single 5.0 */
- 0x3f000000, /* single 0.5 */
- 0x41200000 /* single 10.0 */
+ const_float32(0x00000000), /* single 0.0 */
+ const_float32(0x3f800000), /* single 1.0 */
+ const_float32(0x40000000), /* single 2.0 */
+ const_float32(0x40400000), /* single 3.0 */
+ const_float32(0x40800000), /* single 4.0 */
+ const_float32(0x40a00000), /* single 5.0 */
+ const_float32(0x3f000000), /* single 0.5 */
+ const_float32(0x41200000) /* single 10.0 */
};
unsigned int getRegisterCount(const unsigned int opcode)
diff --git a/linux-user/signal.c b/linux-user/signal.c
index b01bd64..ce033e9 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1299,7 +1299,7 @@ static abi_ulong *setup_sigframe_v2_vfp(abi_ulong *regspace, CPUState *env)
__put_user(TARGET_VFP_MAGIC, &vfpframe->magic);
__put_user(sizeof(*vfpframe), &vfpframe->size);
for (i = 0; i < 32; i++) {
- __put_user(env->vfp.regs[i], &vfpframe->ufp.fpregs[i]);
+ __put_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
}
__put_user(vfp_get_fpscr(env), &vfpframe->ufp.fpscr);
__put_user(env->vfp.xregs[ARM_VFP_FPEXC], &vfpframe->ufp_exc.fpexc);
@@ -1588,7 +1588,7 @@ static abi_ulong *restore_sigframe_v2_vfp(CPUState *env, abi_ulong *regspace)
return 0;
}
for (i = 0; i < 32; i++) {
- __get_user(env->vfp.regs[i], &vfpframe->ufp.fpregs[i]);
+ __get_user(float64_val(env->vfp.regs[i]), &vfpframe->ufp.fpregs[i]);
}
__get_user(fpscr, &vfpframe->ufp.fpscr);
vfp_set_fpscr(env, fpscr);
commit d5138cf4a8f2415d2d568adfd3f65d3cc5a0b736
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Thu Feb 10 13:59:34 2011 +0000
softfloat: Fix compilation failures with USE_SOFTFLOAT_STRUCT_TYPES
Make softfloat compile with USE_SOFTFLOAT_STRUCT_TYPES defined, by
adding and using new macros const_float16(), const_float32() and
const_float64() so you can use array initializers in an array of
float16/float32/float64 whether the types are bare or wrapped in the
structs.
[aurelien at aurel32.net: do the same for float16]
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 3abd170..30b07e9 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -2199,21 +2199,21 @@ float32 float32_sqrt( float32 a STATUS_PARAM )
static const float64 float32_exp2_coefficients[15] =
{
- make_float64( 0x3ff0000000000000ll ), /* 1 */
- make_float64( 0x3fe0000000000000ll ), /* 2 */
- make_float64( 0x3fc5555555555555ll ), /* 3 */
- make_float64( 0x3fa5555555555555ll ), /* 4 */
- make_float64( 0x3f81111111111111ll ), /* 5 */
- make_float64( 0x3f56c16c16c16c17ll ), /* 6 */
- make_float64( 0x3f2a01a01a01a01all ), /* 7 */
- make_float64( 0x3efa01a01a01a01all ), /* 8 */
- make_float64( 0x3ec71de3a556c734ll ), /* 9 */
- make_float64( 0x3e927e4fb7789f5cll ), /* 10 */
- make_float64( 0x3e5ae64567f544e4ll ), /* 11 */
- make_float64( 0x3e21eed8eff8d898ll ), /* 12 */
- make_float64( 0x3de6124613a86d09ll ), /* 13 */
- make_float64( 0x3da93974a8c07c9dll ), /* 14 */
- make_float64( 0x3d6ae7f3e733b81fll ), /* 15 */
+ const_float64( 0x3ff0000000000000ll ), /* 1 */
+ const_float64( 0x3fe0000000000000ll ), /* 2 */
+ const_float64( 0x3fc5555555555555ll ), /* 3 */
+ const_float64( 0x3fa5555555555555ll ), /* 4 */
+ const_float64( 0x3f81111111111111ll ), /* 5 */
+ const_float64( 0x3f56c16c16c16c17ll ), /* 6 */
+ const_float64( 0x3f2a01a01a01a01all ), /* 7 */
+ const_float64( 0x3efa01a01a01a01all ), /* 8 */
+ const_float64( 0x3ec71de3a556c734ll ), /* 9 */
+ const_float64( 0x3e927e4fb7789f5cll ), /* 10 */
+ const_float64( 0x3e5ae64567f544e4ll ), /* 11 */
+ const_float64( 0x3e21eed8eff8d898ll ), /* 12 */
+ const_float64( 0x3de6124613a86d09ll ), /* 13 */
+ const_float64( 0x3da93974a8c07c9dll ), /* 14 */
+ const_float64( 0x3d6ae7f3e733b81fll ), /* 15 */
};
float32 float32_exp2( float32 a STATUS_PARAM )
diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index 2296adb..e57ee1e 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -124,17 +124,20 @@ typedef struct {
} float16;
#define float16_val(x) (((float16)(x)).v)
#define make_float16(x) __extension__ ({ float16 f16_val = {x}; f16_val; })
+#define const_float16(x) { x }
typedef struct {
uint32_t v;
} float32;
/* The cast ensures an error if the wrong type is passed. */
#define float32_val(x) (((float32)(x)).v)
#define make_float32(x) __extension__ ({ float32 f32_val = {x}; f32_val; })
+#define const_float32(x) { x }
typedef struct {
uint64_t v;
} float64;
#define float64_val(x) (((float64)(x)).v)
#define make_float64(x) __extension__ ({ float64 f64_val = {x}; f64_val; })
+#define const_float64(x) { x }
#else
typedef uint16_t float16;
typedef uint32_t float32;
@@ -145,6 +148,9 @@ typedef uint64_t float64;
#define make_float16(x) (x)
#define make_float32(x) (x)
#define make_float64(x) (x)
+#define const_float16(x) (x)
+#define const_float32(x) (x)
+#define const_float64(x) (x)
#endif
#ifdef FLOATX80
typedef struct {
commit 2d981da77d7fb0c3ec83286bc617c4fc64765ac2
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Thu Feb 10 11:29:01 2011 +0000
target-arm: Use standard FPSCR for Neon half-precision operations
The Neon half-precision conversion operations (VCVT.F16.F32 and
VCVT.F32.F16) use ARM standard floating-point arithmetic, unlike
the VFP versions (VCVTB and VCVTT).
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/helper.c b/target-arm/helper.c
index e427747..7f63a28 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2623,9 +2623,8 @@ VFP_CONV_FIX(ul, s, float32, uint32, u)
#undef VFP_CONV_FIX
/* Half precision conversions. */
-float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, CPUState *env)
+static float32 do_fcvt_f16_to_f32(uint32_t a, CPUState *env, float_status *s)
{
- float_status *s = &env->vfp.fp_status;
int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
float32 r = float16_to_float32(make_float16(a), ieee, s);
if (ieee) {
@@ -2634,9 +2633,8 @@ float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, CPUState *env)
return r;
}
-uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, CPUState *env)
+static uint32_t do_fcvt_f32_to_f16(float32 a, CPUState *env, float_status *s)
{
- float_status *s = &env->vfp.fp_status;
int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
float16 r = float32_to_float16(a, ieee, s);
if (ieee) {
@@ -2645,6 +2643,26 @@ uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, CPUState *env)
return float16_val(r);
}
+float32 HELPER(neon_fcvt_f16_to_f32)(uint32_t a, CPUState *env)
+{
+ return do_fcvt_f16_to_f32(a, env, &env->vfp.standard_fp_status);
+}
+
+uint32_t HELPER(neon_fcvt_f32_to_f16)(float32 a, CPUState *env)
+{
+ return do_fcvt_f32_to_f16(a, env, &env->vfp.standard_fp_status);
+}
+
+float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, CPUState *env)
+{
+ return do_fcvt_f16_to_f32(a, env, &env->vfp.fp_status);
+}
+
+uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, CPUState *env)
+{
+ return do_fcvt_f32_to_f16(a, env, &env->vfp.fp_status);
+}
+
float32 HELPER(recps_f32)(float32 a, float32 b, CPUState *env)
{
float_status *s = &env->vfp.fp_status;
diff --git a/target-arm/helpers.h b/target-arm/helpers.h
index 4d0de00..77f1635 100644
--- a/target-arm/helpers.h
+++ b/target-arm/helpers.h
@@ -129,6 +129,8 @@ DEF_HELPER_3(vfp_ultod, f64, f64, i32, env)
DEF_HELPER_2(vfp_fcvt_f16_to_f32, f32, i32, env)
DEF_HELPER_2(vfp_fcvt_f32_to_f16, i32, f32, env)
+DEF_HELPER_2(neon_fcvt_f16_to_f32, f32, i32, env)
+DEF_HELPER_2(neon_fcvt_f32_to_f16, i32, f32, env)
DEF_HELPER_3(recps_f32, f32, f32, f32, env)
DEF_HELPER_3(rsqrts_f32, f32, f32, f32, env)
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 3087a5d..362d1d0 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -5535,17 +5535,17 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
tmp = new_tmp();
tmp2 = new_tmp();
tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
- gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
+ gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
- gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
+ gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
tcg_gen_shli_i32(tmp2, tmp2, 16);
tcg_gen_or_i32(tmp2, tmp2, tmp);
tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
- gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
+ gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
neon_store_reg(rd, 0, tmp2);
tmp2 = new_tmp();
- gen_helper_vfp_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
+ gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
tcg_gen_shli_i32(tmp2, tmp2, 16);
tcg_gen_or_i32(tmp2, tmp2, tmp);
neon_store_reg(rd, 1, tmp2);
@@ -5558,17 +5558,17 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
tmp = neon_load_reg(rm, 0);
tmp2 = neon_load_reg(rm, 1);
tcg_gen_ext16u_i32(tmp3, tmp);
- gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
+ gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
tcg_gen_shri_i32(tmp3, tmp, 16);
- gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
+ gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
dead_tmp(tmp);
tcg_gen_ext16u_i32(tmp3, tmp2);
- gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
+ gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
tcg_gen_shri_i32(tmp3, tmp2, 16);
- gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
+ gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
dead_tmp(tmp2);
dead_tmp(tmp3);
commit fb91678d2c9562484d16b5d7be9119784730c47e
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Thu Feb 10 11:29:00 2011 +0000
target-arm: Silence NaNs resulting from half-precision conversions
Silence the NaNs that may result from half-precision conversion,
as we do for the other conversions.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/helper.c b/target-arm/helper.c
index d29c42b..e427747 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2627,14 +2627,22 @@ float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, CPUState *env)
{
float_status *s = &env->vfp.fp_status;
int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
- return float16_to_float32(make_float16(a), ieee, s);
+ float32 r = float16_to_float32(make_float16(a), ieee, s);
+ if (ieee) {
+ return float32_maybe_silence_nan(r);
+ }
+ return r;
}
uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, CPUState *env)
{
float_status *s = &env->vfp.fp_status;
int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
- return float16_val(float32_to_float16(a, ieee, s));
+ float16 r = float32_to_float16(a, ieee, s);
+ if (ieee) {
+ r = float16_maybe_silence_nan(r);
+ }
+ return float16_val(r);
}
float32 HELPER(recps_f32)(float32 a, float32 b, CPUState *env)
commit f591e1bedf01a4b1de0891a66320a0724412d009
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Thu Feb 10 11:28:59 2011 +0000
softfloat: Correctly handle NaNs in float16_to_float32()
Correctly handle NaNs in float16_to_float32(), by defining and
using a float16ToCommonNaN() function, as we do with the other formats.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 1c0b12b..2d025bf 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -120,6 +120,23 @@ float16 float16_maybe_silence_nan(float16 a_)
}
/*----------------------------------------------------------------------------
+| Returns the result of converting the half-precision floating-point NaN
+| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
+| exception is raised.
+*----------------------------------------------------------------------------*/
+
+static commonNaNT float16ToCommonNaN( float16 a STATUS_PARAM )
+{
+ commonNaNT z;
+
+ if ( float16_is_signaling_nan( a ) ) float_raise( float_flag_invalid STATUS_VAR );
+ z.sign = float16_val(a) >> 15;
+ z.low = 0;
+ z.high = ((bits64) float16_val(a))<<54;
+ return z;
+}
+
+/*----------------------------------------------------------------------------
| Returns the result of converting the canonical NaN `a' to the half-
| precision floating-point format.
*----------------------------------------------------------------------------*/
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 80d8cc4..3abd170 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -2761,9 +2761,7 @@ float32 float16_to_float32(float16 a, flag ieee STATUS_PARAM)
if (aExp == 0x1f && ieee) {
if (aSig) {
- /* Make sure correct exceptions are raised. */
- float32ToCommonNaN(a STATUS_VAR);
- aSig |= 0x200;
+ return commonNaNToFloat32(float16ToCommonNaN(a STATUS_VAR) STATUS_VAR);
}
return packFloat32(aSign, 0xff, aSig << 13);
}
commit 600e30d2b293bd19b0d0cdb7e8a517cecf482d12
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Thu Feb 10 11:28:58 2011 +0000
softfloat: Fix single-to-half precision float conversions
Fix various bugs in the single-to-half-precision conversion code:
* input NaNs not correctly converted in IEEE mode
(fixed by defining and using a commonNaNToFloat16())
* wrong values returned when converting NaN/Inf into non-IEEE
half precision value
* wrong values returned for conversion of values which are
on the boundary between denormal and zero for the half
precision format
* zeroes not correctly identified
* excessively large results in non-IEEE mode should
generate InvalidOp, not Overflow
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 1b7521f..1c0b12b 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -120,6 +120,27 @@ float16 float16_maybe_silence_nan(float16 a_)
}
/*----------------------------------------------------------------------------
+| Returns the result of converting the canonical NaN `a' to the half-
+| precision floating-point format.
+*----------------------------------------------------------------------------*/
+
+static float16 commonNaNToFloat16(commonNaNT a STATUS_PARAM)
+{
+ uint16_t mantissa = a.high>>54;
+
+ if (STATUS(default_nan_mode)) {
+ return float16_default_nan;
+ }
+
+ if (mantissa) {
+ return make_float16(((((uint16_t) a.sign) << 15)
+ | (0x1F << 10) | mantissa));
+ } else {
+ return float16_default_nan;
+ }
+}
+
+/*----------------------------------------------------------------------------
| The pattern for a default generated single-precision NaN.
*----------------------------------------------------------------------------*/
#if defined(TARGET_SPARC)
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index ffc8a99..80d8cc4 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -2796,24 +2796,30 @@ float16 float32_to_float16(float32 a, flag ieee STATUS_PARAM)
aSign = extractFloat32Sign( a );
if ( aExp == 0xFF ) {
if (aSig) {
- /* Make sure correct exceptions are raised. */
- float32ToCommonNaN(a STATUS_VAR);
- aSig |= 0x00400000;
+ /* Input is a NaN */
+ float16 r = commonNaNToFloat16( float32ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
+ if (!ieee) {
+ return packFloat16(aSign, 0, 0);
+ }
+ return r;
}
- return packFloat16(aSign, 0x1f, aSig >> 13);
+ /* Infinity */
+ if (!ieee) {
+ float_raise(float_flag_invalid STATUS_VAR);
+ return packFloat16(aSign, 0x1f, 0x3ff);
+ }
+ return packFloat16(aSign, 0x1f, 0);
}
- if (aExp == 0 && aSign == 0) {
+ if (aExp == 0 && aSig == 0) {
return packFloat16(aSign, 0, 0);
}
/* Decimal point between bits 22 and 23. */
aSig |= 0x00800000;
aExp -= 0x7f;
if (aExp < -14) {
- mask = 0x007fffff;
- if (aExp < -24) {
- aExp = -25;
- } else {
- mask >>= 24 + aExp;
+ mask = 0x00ffffff;
+ if (aExp >= -24) {
+ mask >>= 25 + aExp;
}
} else {
mask = 0x00001fff;
@@ -2855,7 +2861,7 @@ float16 float32_to_float16(float32 a, flag ieee STATUS_PARAM)
}
} else {
if (aExp > 16) {
- float_raise( float_flag_overflow | float_flag_inexact STATUS_VAR);
+ float_raise(float_flag_invalid | float_flag_inexact STATUS_VAR);
return packFloat16(aSign, 0x1f, 0x3ff);
}
}
commit bcd4d9afd411494f9e1cb2a3b4a65dcf4207857e
Author: Christophe Lyon <christophe.lyon at st.com>
Date: Thu Feb 10 11:28:57 2011 +0000
softfloat: Honour default_nan_mode for float-to-float conversions
Honour the default_nan_mode flag when doing conversions between
different floating point formats, as well as when returning a NaN from
a two-operand floating point function. This corrects the behaviour
of float<->double conversions on both ARM and SH4.
Signed-off-by: Christophe Lyon <christophe.lyon at st.com>
Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
Reviewed-by: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index 495f6f3..1b7521f 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -207,9 +207,14 @@ static commonNaNT float32ToCommonNaN( float32 a STATUS_PARAM )
| precision floating-point format.
*----------------------------------------------------------------------------*/
-static float32 commonNaNToFloat32( commonNaNT a )
+static float32 commonNaNToFloat32( commonNaNT a STATUS_PARAM)
{
bits32 mantissa = a.high>>41;
+
+ if ( STATUS(default_nan_mode) ) {
+ return float32_default_nan;
+ }
+
if ( mantissa )
return make_float32(
( ( (bits32) a.sign )<<31 ) | 0x7F800000 | ( a.high>>41 ) );
@@ -461,10 +466,14 @@ static commonNaNT float64ToCommonNaN( float64 a STATUS_PARAM)
| precision floating-point format.
*----------------------------------------------------------------------------*/
-static float64 commonNaNToFloat64( commonNaNT a )
+static float64 commonNaNToFloat64( commonNaNT a STATUS_PARAM)
{
bits64 mantissa = a.high>>12;
+ if ( STATUS(default_nan_mode) ) {
+ return float64_default_nan;
+ }
+
if ( mantissa )
return make_float64(
( ( (bits64) a.sign )<<63 )
@@ -618,10 +627,16 @@ static commonNaNT floatx80ToCommonNaN( floatx80 a STATUS_PARAM)
| double-precision floating-point format.
*----------------------------------------------------------------------------*/
-static floatx80 commonNaNToFloatx80( commonNaNT a )
+static floatx80 commonNaNToFloatx80( commonNaNT a STATUS_PARAM)
{
floatx80 z;
+ if ( STATUS(default_nan_mode) ) {
+ z.low = floatx80_default_nan_low;
+ z.high = floatx80_default_nan_high;
+ return z;
+ }
+
if (a.high)
z.low = a.high;
else
@@ -766,10 +781,16 @@ static commonNaNT float128ToCommonNaN( float128 a STATUS_PARAM)
| precision floating-point format.
*----------------------------------------------------------------------------*/
-static float128 commonNaNToFloat128( commonNaNT a )
+static float128 commonNaNToFloat128( commonNaNT a STATUS_PARAM)
{
float128 z;
+ if ( STATUS(default_nan_mode) ) {
+ z.low = float128_default_nan_low;
+ z.high = float128_default_nan_high;
+ return z;
+ }
+
shift128Right( a.high, a.low, 16, &z.high, &z.low );
z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF000000000000 );
return z;
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 635c74c..ffc8a99 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -1561,7 +1561,7 @@ float64 float32_to_float64( float32 a STATUS_PARAM )
aExp = extractFloat32Exp( a );
aSign = extractFloat32Sign( a );
if ( aExp == 0xFF ) {
- if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a STATUS_VAR ));
+ if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
return packFloat64( aSign, 0x7FF, 0 );
}
if ( aExp == 0 ) {
@@ -1593,7 +1593,7 @@ floatx80 float32_to_floatx80( float32 a STATUS_PARAM )
aExp = extractFloat32Exp( a );
aSign = extractFloat32Sign( a );
if ( aExp == 0xFF ) {
- if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a STATUS_VAR ) );
+ if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
}
if ( aExp == 0 ) {
@@ -1627,7 +1627,7 @@ float128 float32_to_float128( float32 a STATUS_PARAM )
aExp = extractFloat32Exp( a );
aSign = extractFloat32Sign( a );
if ( aExp == 0xFF ) {
- if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a STATUS_VAR ) );
+ if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
return packFloat128( aSign, 0x7FFF, 0, 0 );
}
if ( aExp == 0 ) {
@@ -2716,7 +2716,7 @@ float32 float64_to_float32( float64 a STATUS_PARAM )
aExp = extractFloat64Exp( a );
aSign = extractFloat64Sign( a );
if ( aExp == 0x7FF ) {
- if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a STATUS_VAR ) );
+ if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
return packFloat32( aSign, 0xFF, 0 );
}
shift64RightJamming( aSig, 22, &aSig );
@@ -2889,7 +2889,7 @@ floatx80 float64_to_floatx80( float64 a STATUS_PARAM )
aExp = extractFloat64Exp( a );
aSign = extractFloat64Sign( a );
if ( aExp == 0x7FF ) {
- if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a STATUS_VAR ) );
+ if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
}
if ( aExp == 0 ) {
@@ -2924,7 +2924,7 @@ float128 float64_to_float128( float64 a STATUS_PARAM )
aExp = extractFloat64Exp( a );
aSign = extractFloat64Sign( a );
if ( aExp == 0x7FF ) {
- if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a STATUS_VAR ) );
+ if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
return packFloat128( aSign, 0x7FFF, 0, 0 );
}
if ( aExp == 0 ) {
@@ -3871,7 +3871,7 @@ float32 floatx80_to_float32( floatx80 a STATUS_PARAM )
aSign = extractFloatx80Sign( a );
if ( aExp == 0x7FFF ) {
if ( (bits64) ( aSig<<1 ) ) {
- return commonNaNToFloat32( floatx80ToCommonNaN( a STATUS_VAR ) );
+ return commonNaNToFloat32( floatx80ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
}
return packFloat32( aSign, 0xFF, 0 );
}
@@ -3899,7 +3899,7 @@ float64 floatx80_to_float64( floatx80 a STATUS_PARAM )
aSign = extractFloatx80Sign( a );
if ( aExp == 0x7FFF ) {
if ( (bits64) ( aSig<<1 ) ) {
- return commonNaNToFloat64( floatx80ToCommonNaN( a STATUS_VAR ) );
+ return commonNaNToFloat64( floatx80ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
}
return packFloat64( aSign, 0x7FF, 0 );
}
@@ -3928,7 +3928,7 @@ float128 floatx80_to_float128( floatx80 a STATUS_PARAM )
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) {
- return commonNaNToFloat128( floatx80ToCommonNaN( a STATUS_VAR ) );
+ return commonNaNToFloat128( floatx80ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
}
shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 );
return packFloat128( aSign, aExp, zSig0, zSig1 );
@@ -4891,7 +4891,7 @@ float32 float128_to_float32( float128 a STATUS_PARAM )
aSign = extractFloat128Sign( a );
if ( aExp == 0x7FFF ) {
if ( aSig0 | aSig1 ) {
- return commonNaNToFloat32( float128ToCommonNaN( a STATUS_VAR ) );
+ return commonNaNToFloat32( float128ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
}
return packFloat32( aSign, 0xFF, 0 );
}
@@ -4925,7 +4925,7 @@ float64 float128_to_float64( float128 a STATUS_PARAM )
aSign = extractFloat128Sign( a );
if ( aExp == 0x7FFF ) {
if ( aSig0 | aSig1 ) {
- return commonNaNToFloat64( float128ToCommonNaN( a STATUS_VAR ) );
+ return commonNaNToFloat64( float128ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
}
return packFloat64( aSign, 0x7FF, 0 );
}
@@ -4960,7 +4960,7 @@ floatx80 float128_to_floatx80( float128 a STATUS_PARAM )
aSign = extractFloat128Sign( a );
if ( aExp == 0x7FFF ) {
if ( aSig0 | aSig1 ) {
- return commonNaNToFloatx80( float128ToCommonNaN( a STATUS_VAR ) );
+ return commonNaNToFloatx80( float128ToCommonNaN( a STATUS_VAR ) STATUS_VAR );
}
return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
}
commit bb4d4bb376c6ae4d2dfa6e59dfa4e87a75d3a672
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Thu Feb 10 11:28:56 2011 +0000
softfloat: Add float16 type and float16 NaN handling functions
Add a float16 type to softfloat, rather than using bits16 directly.
Also add the missing functions float16_is_quiet_nan(),
float16_is_signaling_nan() and float16_maybe_silence_nan(),
which are needed for the float16 conversion routines.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/fpu/softfloat-specialize.h b/fpu/softfloat-specialize.h
index eb644b2..495f6f3 100644
--- a/fpu/softfloat-specialize.h
+++ b/fpu/softfloat-specialize.h
@@ -57,6 +57,69 @@ typedef struct {
} commonNaNT;
/*----------------------------------------------------------------------------
+| The pattern for a default generated half-precision NaN.
+*----------------------------------------------------------------------------*/
+#if defined(TARGET_ARM)
+#define float16_default_nan make_float16(0x7E00)
+#elif SNAN_BIT_IS_ONE
+#define float16_default_nan make_float16(0x7DFF)
+#else
+#define float16_default_nan make_float16(0xFE00)
+#endif
+
+/*----------------------------------------------------------------------------
+| Returns 1 if the half-precision floating-point value `a' is a quiet
+| NaN; otherwise returns 0.
+*----------------------------------------------------------------------------*/
+
+int float16_is_quiet_nan(float16 a_)
+{
+ uint16_t a = float16_val(a_);
+#if SNAN_BIT_IS_ONE
+ return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
+#else
+ return ((a & ~0x8000) >= 0x7c80);
+#endif
+}
+
+/*----------------------------------------------------------------------------
+| Returns 1 if the half-precision floating-point value `a' is a signaling
+| NaN; otherwise returns 0.
+*----------------------------------------------------------------------------*/
+
+int float16_is_signaling_nan(float16 a_)
+{
+ uint16_t a = float16_val(a_);
+#if SNAN_BIT_IS_ONE
+ return ((a & ~0x8000) >= 0x7c80);
+#else
+ return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
+#endif
+}
+
+/*----------------------------------------------------------------------------
+| Returns a quiet NaN if the half-precision floating point value `a' is a
+| signaling NaN; otherwise returns `a'.
+*----------------------------------------------------------------------------*/
+float16 float16_maybe_silence_nan(float16 a_)
+{
+ if (float16_is_signaling_nan(a_)) {
+#if SNAN_BIT_IS_ONE
+# if defined(TARGET_MIPS) || defined(TARGET_SH4)
+ return float16_default_nan;
+# else
+# error Rules for silencing a signaling NaN are target-specific
+# endif
+#else
+ uint16_t a = float16_val(a_);
+ a |= (1 << 9);
+ return make_float16(a);
+#endif
+ }
+ return a_;
+}
+
+/*----------------------------------------------------------------------------
| The pattern for a default generated single-precision NaN.
*----------------------------------------------------------------------------*/
#if defined(TARGET_SPARC)
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index 17842f4..635c74c 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -67,6 +67,33 @@ void set_floatx80_rounding_precision(int val STATUS_PARAM)
#endif
/*----------------------------------------------------------------------------
+| Returns the fraction bits of the half-precision floating-point value `a'.
+*----------------------------------------------------------------------------*/
+
+INLINE uint32_t extractFloat16Frac(float16 a)
+{
+ return float16_val(a) & 0x3ff;
+}
+
+/*----------------------------------------------------------------------------
+| Returns the exponent bits of the half-precision floating-point value `a'.
+*----------------------------------------------------------------------------*/
+
+INLINE int16 extractFloat16Exp(float16 a)
+{
+ return (float16_val(a) >> 10) & 0x1f;
+}
+
+/*----------------------------------------------------------------------------
+| Returns the sign bit of the single-precision floating-point value `a'.
+*----------------------------------------------------------------------------*/
+
+INLINE flag extractFloat16Sign(float16 a)
+{
+ return float16_val(a)>>15;
+}
+
+/*----------------------------------------------------------------------------
| Takes a 64-bit fixed-point value `absZ' with binary point between bits 6
| and 7, and returns the properly rounded 32-bit integer corresponding to the
| input. If `zSign' is 1, the input is negated before being converted to an
@@ -2713,23 +2740,24 @@ float32 float64_to_float32( float64 a STATUS_PARAM )
| than the desired result exponent whenever `zSig' is a complete, normalized
| significand.
*----------------------------------------------------------------------------*/
-static bits16 packFloat16(flag zSign, int16 zExp, bits16 zSig)
+static float16 packFloat16(flag zSign, int16 zExp, bits16 zSig)
{
- return (((bits32)zSign) << 15) + (((bits32)zExp) << 10) + zSig;
+ return make_float16(
+ (((bits32)zSign) << 15) + (((bits32)zExp) << 10) + zSig);
}
/* Half precision floats come in two formats: standard IEEE and "ARM" format.
The latter gains extra exponent range by omitting the NaN/Inf encodings. */
-
-float32 float16_to_float32( bits16 a, flag ieee STATUS_PARAM )
+
+float32 float16_to_float32(float16 a, flag ieee STATUS_PARAM)
{
flag aSign;
int16 aExp;
bits32 aSig;
- aSign = a >> 15;
- aExp = (a >> 10) & 0x1f;
- aSig = a & 0x3ff;
+ aSign = extractFloat16Sign(a);
+ aExp = extractFloat16Exp(a);
+ aSig = extractFloat16Frac(a);
if (aExp == 0x1f && ieee) {
if (aSig) {
@@ -2753,7 +2781,7 @@ float32 float16_to_float32( bits16 a, flag ieee STATUS_PARAM )
return packFloat32( aSign, aExp + 0x70, aSig << 13);
}
-bits16 float32_to_float16( float32 a, flag ieee STATUS_PARAM)
+float16 float32_to_float16(float32 a, flag ieee STATUS_PARAM)
{
flag aSign;
int16 aExp;
diff --git a/fpu/softfloat.h b/fpu/softfloat.h
index 4a5345c..2296adb 100644
--- a/fpu/softfloat.h
+++ b/fpu/softfloat.h
@@ -120,6 +120,11 @@ enum {
//#define USE_SOFTFLOAT_STRUCT_TYPES
#ifdef USE_SOFTFLOAT_STRUCT_TYPES
typedef struct {
+ uint16_t v;
+} float16;
+#define float16_val(x) (((float16)(x)).v)
+#define make_float16(x) __extension__ ({ float16 f16_val = {x}; f16_val; })
+typedef struct {
uint32_t v;
} float32;
/* The cast ensures an error if the wrong type is passed. */
@@ -131,10 +136,13 @@ typedef struct {
#define float64_val(x) (((float64)(x)).v)
#define make_float64(x) __extension__ ({ float64 f64_val = {x}; f64_val; })
#else
+typedef uint16_t float16;
typedef uint32_t float32;
typedef uint64_t float64;
+#define float16_val(x) (x)
#define float32_val(x) (x)
#define float64_val(x) (x)
+#define make_float16(x) (x)
#define make_float32(x) (x)
#define make_float64(x) (x)
#endif
@@ -253,8 +261,15 @@ float128 int64_to_float128( int64_t STATUS_PARAM );
/*----------------------------------------------------------------------------
| Software half-precision conversion routines.
*----------------------------------------------------------------------------*/
-bits16 float32_to_float16( float32, flag STATUS_PARAM );
-float32 float16_to_float32( bits16, flag STATUS_PARAM );
+float16 float32_to_float16( float32, flag STATUS_PARAM );
+float32 float16_to_float32( float16, flag STATUS_PARAM );
+
+/*----------------------------------------------------------------------------
+| Software half-precision operations.
+*----------------------------------------------------------------------------*/
+int float16_is_quiet_nan( float16 );
+int float16_is_signaling_nan( float16 );
+float16 float16_maybe_silence_nan( float16 );
/*----------------------------------------------------------------------------
| Software IEC/IEEE single-precision conversion routines.
diff --git a/target-arm/helper.c b/target-arm/helper.c
index d46defc..d29c42b 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -2627,14 +2627,14 @@ float32 HELPER(vfp_fcvt_f16_to_f32)(uint32_t a, CPUState *env)
{
float_status *s = &env->vfp.fp_status;
int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
- return float16_to_float32(a, ieee, s);
+ return float16_to_float32(make_float16(a), ieee, s);
}
uint32_t HELPER(vfp_fcvt_f32_to_f16)(float32 a, CPUState *env)
{
float_status *s = &env->vfp.fp_status;
int ieee = (env->vfp.xregs[ARM_VFP_FPSCR] & (1 << 26)) == 0;
- return float32_to_float16(a, ieee, s);
+ return float16_val(float32_to_float16(a, ieee, s));
}
float32 HELPER(recps_f32)(float32 a, float32 b, CPUState *env)
commit d1a1eb7472b40950dac176a191f3d5d4ae980ecc
Author: Tristan Gingold <gingold at adacore.com>
Date: Thu Feb 10 10:04:57 2011 +0100
Make tb_alloc static
This function is only used within exec.c, so no need to make it public.
Signed-off-by: Tristan Gingold <gingold at adacore.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/exec-all.h b/exec-all.h
index e3a82bc..496c001 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -180,7 +180,6 @@ static inline unsigned int tb_phys_hash_func(tb_page_addr_t pc)
return (pc >> 2) & (CODE_GEN_PHYS_HASH_SIZE - 1);
}
-TranslationBlock *tb_alloc(target_ulong pc);
void tb_free(TranslationBlock *tb);
void tb_flush(CPUState *env);
void tb_link_page(TranslationBlock *tb,
diff --git a/exec.c b/exec.c
index e950df2..1b70dc1 100644
--- a/exec.c
+++ b/exec.c
@@ -649,6 +649,32 @@ void cpu_exec_init(CPUState *env)
#endif
}
+/* Allocate a new translation block. Flush the translation buffer if
+ too many translation blocks or too much generated code. */
+static TranslationBlock *tb_alloc(target_ulong pc)
+{
+ TranslationBlock *tb;
+
+ if (nb_tbs >= code_gen_max_blocks ||
+ (code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size)
+ return NULL;
+ tb = &tbs[nb_tbs++];
+ tb->pc = pc;
+ tb->cflags = 0;
+ return tb;
+}
+
+void tb_free(TranslationBlock *tb)
+{
+ /* In practice this is mostly used for single use temporary TB
+ Ignore the hard cases and just back up if this TB happens to
+ be the last one generated. */
+ if (nb_tbs > 0 && tb == &tbs[nb_tbs - 1]) {
+ code_gen_ptr = tb->tc_ptr;
+ nb_tbs--;
+ }
+}
+
static inline void invalidate_page_bitmap(PageDesc *p)
{
if (p->code_bitmap) {
@@ -1226,32 +1252,6 @@ static inline void tb_alloc_page(TranslationBlock *tb,
#endif /* TARGET_HAS_SMC */
}
-/* Allocate a new translation block. Flush the translation buffer if
- too many translation blocks or too much generated code. */
-TranslationBlock *tb_alloc(target_ulong pc)
-{
- TranslationBlock *tb;
-
- if (nb_tbs >= code_gen_max_blocks ||
- (code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size)
- return NULL;
- tb = &tbs[nb_tbs++];
- tb->pc = pc;
- tb->cflags = 0;
- return tb;
-}
-
-void tb_free(TranslationBlock *tb)
-{
- /* In practice this is mostly used for single use temporary TB
- Ignore the hard cases and just back up if this TB happens to
- be the last one generated. */
- if (nb_tbs > 0 && tb == &tbs[nb_tbs - 1]) {
- code_gen_ptr = tb->tc_ptr;
- nb_tbs--;
- }
-}
-
/* add a new TB and link it to the physical page tables. phys_page2 is
(-1) to indicate that only one page contains the TB. */
void tb_link_page(TranslationBlock *tb,
commit 6c5f738daec123020d32543fe90a6633a4f6643e
Author: Edgar E. Iglesias <edgar.iglesias at petalogix.com>
Date: Thu Feb 10 00:46:09 2011 +0100
microblaze: Handle singlestepping over direct jmps
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at petalogix.com>
diff --git a/target-microblaze/translate.c b/target-microblaze/translate.c
index 2207431..fdb2b40 100644
--- a/target-microblaze/translate.c
+++ b/target-microblaze/translate.c
@@ -1715,9 +1715,13 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
t_sync_flags(dc);
if (unlikely(env->singlestep_enabled)) {
- t_gen_raise_exception(dc, EXCP_DEBUG);
- if (dc->is_jmp == DISAS_NEXT)
+ TCGv_i32 tmp = tcg_const_i32(EXCP_DEBUG);
+
+ if (dc->is_jmp != DISAS_JUMP) {
tcg_gen_movi_tl(cpu_SR[SR_PC], npc);
+ }
+ gen_helper_raise_exception(tmp);
+ tcg_temp_free_i32(tmp);
} else {
switch(dc->is_jmp) {
case DISAS_NEXT:
commit 1c0de9fa509c48aeeb6ef2465307d603abc9ee4e
Merge: 923e650... 898b1be...
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Wed Feb 9 19:53:36 2011 +0100
Merge branch 'linux-user-for-upstream' of git://gitorious.org/qemu-maemo/qemu
* 'linux-user-for-upstream' of git://gitorious.org/qemu-maemo/qemu:
linux-user: fix for loopmount ioctl
linux-user: fix build errors for mmap2-only ports
user: speed up init_paths a bit
linux-user: implement sched_{g,s}etaffinity
linux-user/FLAT: allow targets to override FLAT processing
linux-user/FLAT: fix auto-stack sizing
linux-user: decode MAP_{UNINITIALIZED,EXECUTABLE} in strace
linux-user: add ppoll syscall support
linux-user/elfload: add FDPIC support
linux-user: fix sizeof handling for getsockopt
linux-user: Fix possible realloc memory leak
linux-user: Add support for -version option
commit 923e65097d2101a78f716f7932f4291315d88bbf
Author: Christophe Lyon <christophe.lyon at st.com>
Date: Tue Feb 8 18:39:02 2011 +0100
target-arm: implement vsli.64, vsri.64
Signed-off-by: Christophe Lyon <christophe.lyon at st.com>
Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/translate.c b/target-arm/translate.c
index ef3f369..3087a5d 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4698,7 +4698,19 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
} else if (op == 4 || (op == 5 && u)) {
/* Insert */
- cpu_abort(env, "VS[LR]I.64 not implemented");
+ neon_load_reg64(cpu_V1, rd + pass);
+ uint64_t mask;
+ if (shift < -63 || shift > 63) {
+ mask = 0;
+ } else {
+ if (op == 4) {
+ mask = 0xffffffffffffffffull >> -shift;
+ } else {
+ mask = 0xffffffffffffffffull << shift;
+ }
+ }
+ tcg_gen_andi_i64(cpu_V1, cpu_V1, ~mask);
+ tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
}
neon_store_reg64(cpu_V0, rd + pass);
} else { /* size < 3 */
commit acdf01effa1851780a731ca5ffeab79a474a6335
Author: Christophe Lyon <christophe.lyon at st.com>
Date: Wed Feb 9 13:19:15 2011 +0100
target-arm: fix VSHLL Neon instruction.
Fix bit mask used when widening the result of shift on narrow input.
Signed-off-by: Christophe Lyon <christophe.lyon at st.com>
Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 89c916d..ef3f369 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4880,16 +4880,28 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
/* The shift is less than the width of the source
type, so we can just shift the whole register. */
tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
+ /* Widen the result of shift: we need to clear
+ * the potential overflow bits resulting from
+ * left bits of the narrow input appearing as
+ * right bits of left the neighbour narrow
+ * input. */
if (size < 2 || !u) {
uint64_t imm64;
if (size == 0) {
imm = (0xffu >> (8 - shift));
imm |= imm << 16;
- } else {
+ } else if (size == 1) {
imm = 0xffff >> (16 - shift);
+ } else {
+ /* size == 2 */
+ imm = 0xffffffff >> (32 - shift);
+ }
+ if (size < 2) {
+ imm64 = imm | (((uint64_t)imm) << 32);
+ } else {
+ imm64 = imm;
}
- imm64 = imm | (((uint64_t)imm) << 32);
- tcg_gen_andi_i64(cpu_V0, cpu_V0, imm64);
+ tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
}
}
neon_store_reg64(cpu_V0, rd + pass);
commit efd410373a4551911f3928bb2ccdf28792b294bf
Author: Chris Dearman <chris at mips.com>
Date: Tue Feb 8 19:03:30 2011 -0800
[PATCH] [MIPS] Clear softfpu exception state for round, trunc, ceil and floor
MIPS FPU instructions should start with a clean softfpu status. This
is done for the arithmetic operations and cvt instructions, but not
for round, trunc, ceil and floor.
Signed-off-by: Chris Dearman <chris at mips.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 669faf1..bd16ce3 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -2282,6 +2282,7 @@ uint64_t helper_float_roundl_d(uint64_t fdt0)
{
uint64_t dt2;
+ set_float_exception_flags(0, &env->active_fpu.fp_status);
set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
RESTORE_ROUNDING_MODE;
@@ -2295,6 +2296,7 @@ uint64_t helper_float_roundl_s(uint32_t fst0)
{
uint64_t dt2;
+ set_float_exception_flags(0, &env->active_fpu.fp_status);
set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
RESTORE_ROUNDING_MODE;
@@ -2308,6 +2310,7 @@ uint32_t helper_float_roundw_d(uint64_t fdt0)
{
uint32_t wt2;
+ set_float_exception_flags(0, &env->active_fpu.fp_status);
set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
RESTORE_ROUNDING_MODE;
@@ -2321,6 +2324,7 @@ uint32_t helper_float_roundw_s(uint32_t fst0)
{
uint32_t wt2;
+ set_float_exception_flags(0, &env->active_fpu.fp_status);
set_float_rounding_mode(float_round_nearest_even, &env->active_fpu.fp_status);
wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
RESTORE_ROUNDING_MODE;
@@ -2334,6 +2338,7 @@ uint64_t helper_float_truncl_d(uint64_t fdt0)
{
uint64_t dt2;
+ set_float_exception_flags(0, &env->active_fpu.fp_status);
dt2 = float64_to_int64_round_to_zero(fdt0, &env->active_fpu.fp_status);
update_fcr31();
if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
@@ -2345,6 +2350,7 @@ uint64_t helper_float_truncl_s(uint32_t fst0)
{
uint64_t dt2;
+ set_float_exception_flags(0, &env->active_fpu.fp_status);
dt2 = float32_to_int64_round_to_zero(fst0, &env->active_fpu.fp_status);
update_fcr31();
if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
@@ -2356,6 +2362,7 @@ uint32_t helper_float_truncw_d(uint64_t fdt0)
{
uint32_t wt2;
+ set_float_exception_flags(0, &env->active_fpu.fp_status);
wt2 = float64_to_int32_round_to_zero(fdt0, &env->active_fpu.fp_status);
update_fcr31();
if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
@@ -2367,6 +2374,7 @@ uint32_t helper_float_truncw_s(uint32_t fst0)
{
uint32_t wt2;
+ set_float_exception_flags(0, &env->active_fpu.fp_status);
wt2 = float32_to_int32_round_to_zero(fst0, &env->active_fpu.fp_status);
update_fcr31();
if (GET_FP_CAUSE(env->active_fpu.fcr31) & (FP_OVERFLOW | FP_INVALID))
@@ -2378,6 +2386,7 @@ uint64_t helper_float_ceill_d(uint64_t fdt0)
{
uint64_t dt2;
+ set_float_exception_flags(0, &env->active_fpu.fp_status);
set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
RESTORE_ROUNDING_MODE;
@@ -2391,6 +2400,7 @@ uint64_t helper_float_ceill_s(uint32_t fst0)
{
uint64_t dt2;
+ set_float_exception_flags(0, &env->active_fpu.fp_status);
set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
RESTORE_ROUNDING_MODE;
@@ -2404,6 +2414,7 @@ uint32_t helper_float_ceilw_d(uint64_t fdt0)
{
uint32_t wt2;
+ set_float_exception_flags(0, &env->active_fpu.fp_status);
set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
RESTORE_ROUNDING_MODE;
@@ -2417,6 +2428,7 @@ uint32_t helper_float_ceilw_s(uint32_t fst0)
{
uint32_t wt2;
+ set_float_exception_flags(0, &env->active_fpu.fp_status);
set_float_rounding_mode(float_round_up, &env->active_fpu.fp_status);
wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
RESTORE_ROUNDING_MODE;
@@ -2430,6 +2442,7 @@ uint64_t helper_float_floorl_d(uint64_t fdt0)
{
uint64_t dt2;
+ set_float_exception_flags(0, &env->active_fpu.fp_status);
set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
dt2 = float64_to_int64(fdt0, &env->active_fpu.fp_status);
RESTORE_ROUNDING_MODE;
@@ -2443,6 +2456,7 @@ uint64_t helper_float_floorl_s(uint32_t fst0)
{
uint64_t dt2;
+ set_float_exception_flags(0, &env->active_fpu.fp_status);
set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
dt2 = float32_to_int64(fst0, &env->active_fpu.fp_status);
RESTORE_ROUNDING_MODE;
@@ -2456,6 +2470,7 @@ uint32_t helper_float_floorw_d(uint64_t fdt0)
{
uint32_t wt2;
+ set_float_exception_flags(0, &env->active_fpu.fp_status);
set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
wt2 = float64_to_int32(fdt0, &env->active_fpu.fp_status);
RESTORE_ROUNDING_MODE;
@@ -2469,6 +2484,7 @@ uint32_t helper_float_floorw_s(uint32_t fst0)
{
uint32_t wt2;
+ set_float_exception_flags(0, &env->active_fpu.fp_status);
set_float_rounding_mode(float_round_down, &env->active_fpu.fp_status);
wt2 = float32_to_int32(fst0, &env->active_fpu.fp_status);
RESTORE_ROUNDING_MODE;
commit cc2212c2f851291929becc3f4fd153d05ca4c54a
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Wed Feb 9 15:42:33 2011 +0000
target-arm: Fix 32 bit signed saturating narrow
The returned value when doing saturating signed 64->32 bit
conversion of a negative number was incorrect due to a missing cast.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index a7cf383..61890dd 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -1209,7 +1209,7 @@ uint32_t HELPER(neon_narrow_sat_s32)(CPUState *env, uint64_t x)
{
if ((int64_t)x != (int32_t)x) {
SET_QC();
- return (x >> 63) ^ 0x7fffffff;
+ return ((int64_t)x >> 63) ^ 0x7fffffff;
}
return x;
}
commit af1bbf30c407cb194599a4e1724c38c7bf1d94b3
Author: Juha Riihimäki <juha.riihimaki at nokia.com>
Date: Wed Feb 9 15:42:32 2011 +0000
target-arm: Fix VQMOVUN Neon instruction.
VQMOVUN does a signed-to-unsigned saturating conversion. This is
different from both the signed-to-signed and unsigned-to-unsigned
conversions already implemented, so we need a new set of helper
functions (neon_unarrow_sat*).
Signed-off-by: Juha Riihimäki <juha.riihimaki at nokia.com>
Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/helpers.h b/target-arm/helpers.h
index 8a2564e..4d0de00 100644
--- a/target-arm/helpers.h
+++ b/target-arm/helpers.h
@@ -299,10 +299,13 @@ DEF_HELPER_3(neon_qrdmulh_s32, i32, env, i32, i32)
DEF_HELPER_1(neon_narrow_u8, i32, i64)
DEF_HELPER_1(neon_narrow_u16, i32, i64)
+DEF_HELPER_2(neon_unarrow_sat8, i32, env, i64)
DEF_HELPER_2(neon_narrow_sat_u8, i32, env, i64)
DEF_HELPER_2(neon_narrow_sat_s8, i32, env, i64)
+DEF_HELPER_2(neon_unarrow_sat16, i32, env, i64)
DEF_HELPER_2(neon_narrow_sat_u16, i32, env, i64)
DEF_HELPER_2(neon_narrow_sat_s16, i32, env, i64)
+DEF_HELPER_2(neon_unarrow_sat32, i32, env, i64)
DEF_HELPER_2(neon_narrow_sat_u32, i32, env, i64)
DEF_HELPER_2(neon_narrow_sat_s32, i32, env, i64)
DEF_HELPER_1(neon_narrow_high_u8, i32, i64)
diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index 268af33..a7cf383 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -1053,6 +1053,33 @@ uint32_t HELPER(neon_narrow_round_high_u16)(uint64_t x)
return ((x >> 16) & 0xffff) | ((x >> 32) & 0xffff0000);
}
+uint32_t HELPER(neon_unarrow_sat8)(CPUState *env, uint64_t x)
+{
+ uint16_t s;
+ uint8_t d;
+ uint32_t res = 0;
+#define SAT8(n) \
+ s = x >> n; \
+ if (s & 0x8000) { \
+ SET_QC(); \
+ } else { \
+ if (s > 0xff) { \
+ d = 0xff; \
+ SET_QC(); \
+ } else { \
+ d = s; \
+ } \
+ res |= (uint32_t)d << (n / 2); \
+ }
+
+ SAT8(0);
+ SAT8(16);
+ SAT8(32);
+ SAT8(48);
+#undef SAT8
+ return res;
+}
+
uint32_t HELPER(neon_narrow_sat_u8)(CPUState *env, uint64_t x)
{
uint16_t s;
@@ -1099,6 +1126,29 @@ uint32_t HELPER(neon_narrow_sat_s8)(CPUState *env, uint64_t x)
return res;
}
+uint32_t HELPER(neon_unarrow_sat16)(CPUState *env, uint64_t x)
+{
+ uint32_t high;
+ uint32_t low;
+ low = x;
+ if (low & 0x80000000) {
+ low = 0;
+ SET_QC();
+ } else if (low > 0xffff) {
+ low = 0xffff;
+ SET_QC();
+ }
+ high = x >> 32;
+ if (high & 0x80000000) {
+ high = 0;
+ SET_QC();
+ } else if (high > 0xffff) {
+ high = 0xffff;
+ SET_QC();
+ }
+ return low | (high << 16);
+}
+
uint32_t HELPER(neon_narrow_sat_u16)(CPUState *env, uint64_t x)
{
uint32_t high;
@@ -1133,6 +1183,19 @@ uint32_t HELPER(neon_narrow_sat_s16)(CPUState *env, uint64_t x)
return (uint16_t)low | (high << 16);
}
+uint32_t HELPER(neon_unarrow_sat32)(CPUState *env, uint64_t x)
+{
+ if (x & 0x8000000000000000ull) {
+ SET_QC();
+ return 0;
+ }
+ if (x > 0xffffffffu) {
+ SET_QC();
+ return 0xffffffffu;
+ }
+ return x;
+}
+
uint32_t HELPER(neon_narrow_sat_u32)(CPUState *env, uint64_t x)
{
if (x > 0xffffffffu) {
diff --git a/target-arm/translate.c b/target-arm/translate.c
index e4649e6..89c916d 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4065,6 +4065,16 @@ static inline void gen_neon_narrow_satu(int size, TCGv dest, TCGv_i64 src)
}
}
+static inline void gen_neon_unarrow_sats(int size, TCGv dest, TCGv_i64 src)
+{
+ switch (size) {
+ case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
+ case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
+ case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
+ default: abort();
+ }
+}
+
static inline void gen_neon_shift_narrow(int size, TCGv var, TCGv shift,
int q, int u)
{
@@ -5461,12 +5471,18 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
for (pass = 0; pass < 2; pass++) {
neon_load_reg64(cpu_V0, rm + pass);
tmp = new_tmp();
- if (op == 36 && q == 0) {
- gen_neon_narrow(size, tmp, cpu_V0);
- } else if (q) {
- gen_neon_narrow_satu(size, tmp, cpu_V0);
- } else {
- gen_neon_narrow_sats(size, tmp, cpu_V0);
+ if (op == 36) {
+ if (q) { /* VQMOVUN */
+ gen_neon_unarrow_sats(size, tmp, cpu_V0);
+ } else { /* VMOVN */
+ gen_neon_narrow(size, tmp, cpu_V0);
+ }
+ } else { /* VQMOVN */
+ if (q) {
+ gen_neon_narrow_satu(size, tmp, cpu_V0);
+ } else {
+ gen_neon_narrow_sats(size, tmp, cpu_V0);
+ }
}
if (pass == 0) {
tmp2 = tmp;
commit 898b1bebf97e5f973624a4e513da45dffefdb9b7
Author: Martin Mohring <martin.mohring at 5edatasoft.com>
Date: Tue Feb 8 14:48:56 2011 +0200
linux-user: fix for loopmount ioctl
In case a chrooted build uses XEN or KVM, a looped mount needs to be done to setup the chroot.
The ioctl for loop mount works correctly for arm, mips, ppc32 and sh4, so its now activated.
Signed-off-by: Riku Voipio <riku.voipio at nokia.com>
diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h
index acff781..526aaa2 100644
--- a/linux-user/ioctls.h
+++ b/linux-user/ioctls.h
@@ -312,10 +312,8 @@
IOCTL(LOOP_CLR_FD, 0, TYPE_INT)
IOCTL(LOOP_SET_STATUS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info)))
IOCTL(LOOP_GET_STATUS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info)))
-#if 0 /* These have some problems - not fully tested */
IOCTL(LOOP_SET_STATUS64, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info64)))
IOCTL(LOOP_GET_STATUS64, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info64)))
-#endif
IOCTL(LOOP_CHANGE_FD, 0, TYPE_INT)
IOCTL(MTIOCTOP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_mtop)))
commit 8d9016c0919bab1fdf3a36c0f72d012924bb7efd
Author: Mike Frysinger <vapier at gentoo.org>
Date: Mon Feb 7 01:05:57 2011 -0500
linux-user: fix build errors for mmap2-only ports
The current print_mmap func is only enabled when the target supports the
mmap syscall, but both mmap and mmap2 syscalls use it. This leads to a
build failure when the target supports mmap2 but not mmap.
Signed-off-by: Mike Frysinger <vapier at gentoo.org>
Signed-off-by: Riku Voipio <riku.voipio at nokia.com>
diff --git a/linux-user/strace.c b/linux-user/strace.c
index a8786bb..1836666 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -1203,7 +1203,7 @@ print_utimensat(const struct syscallname *name,
}
#endif
-#ifdef TARGET_NR_mmap
+#if defined(TARGET_NR_mmap) || defined(TARGET_NR_mmap2)
static void
print_mmap(const struct syscallname *name,
abi_long arg0, abi_long arg1, abi_long arg2,
commit 2296f194dfde4c0a54f249d3fdb8c8ca21dc611b
Author: Mike Frysinger <vapier at gentoo.org>
Date: Mon Feb 7 01:05:56 2011 -0500
user: speed up init_paths a bit
The current init_paths code will attempt to opendir() every single file it
finds. This can obviously generated a huge number of syscalls with even a
moderately small sysroot that will fail. Since the readdir() call provides
the file type in the struct itself, use it. On my system, this prevents
over 1000 syscalls from being made at every invocation of a target binary,
and I only have a C library installed.
Signed-off-by: Mike Frysinger <vapier at gentoo.org>
Signed-off-by: Riku Voipio <riku.voipio at nokia.com>
diff --git a/path.c b/path.c
index 0d2bf14..ef3f277 100644
--- a/path.c
+++ b/path.c
@@ -38,7 +38,8 @@ static int strneq(const char *s1, unsigned int n, const char *s2)
return s2[i] == 0;
}
-static struct pathelem *add_entry(struct pathelem *root, const char *name);
+static struct pathelem *add_entry(struct pathelem *root, const char *name,
+ unsigned char type);
static struct pathelem *new_entry(const char *root,
struct pathelem *parent,
@@ -56,6 +57,15 @@ static struct pathelem *new_entry(const char *root,
#define streq(a,b) (strcmp((a), (b)) == 0)
+/* Not all systems provide this feature */
+#if defined(DT_DIR) && defined(DT_UNKNOWN)
+# define dirent_type(dirent) ((dirent)->d_type)
+# define is_dir_maybe(type) ((type) == DT_DIR || (type) == DT_UNKNOWN)
+#else
+# define dirent_type(dirent) (1)
+# define is_dir_maybe(type) (type)
+#endif
+
static struct pathelem *add_dir_maybe(struct pathelem *path)
{
DIR *dir;
@@ -65,7 +75,7 @@ static struct pathelem *add_dir_maybe(struct pathelem *path)
while ((dirent = readdir(dir)) != NULL) {
if (!streq(dirent->d_name,".") && !streq(dirent->d_name,"..")){
- path = add_entry(path, dirent->d_name);
+ path = add_entry(path, dirent->d_name, dirent_type(dirent));
}
}
closedir(dir);
@@ -73,16 +83,22 @@ static struct pathelem *add_dir_maybe(struct pathelem *path)
return path;
}
-static struct pathelem *add_entry(struct pathelem *root, const char *name)
+static struct pathelem *add_entry(struct pathelem *root, const char *name,
+ unsigned char type)
{
+ struct pathelem **e;
+
root->num_entries++;
root = realloc(root, sizeof(*root)
+ sizeof(root->entries[0])*root->num_entries);
+ e = &root->entries[root->num_entries-1];
+
+ *e = new_entry(root->pathname, root, name);
+ if (is_dir_maybe(type)) {
+ *e = add_dir_maybe(*e);
+ }
- root->entries[root->num_entries-1] = new_entry(root->pathname, root, name);
- root->entries[root->num_entries-1]
- = add_dir_maybe(root->entries[root->num_entries-1]);
return root;
}
commit 737de1d1357b13f162b26ca0b775eb375594833a
Author: Mike Frysinger <vapier at gentoo.org>
Date: Mon Feb 7 01:05:55 2011 -0500
linux-user: implement sched_{g,s}etaffinity
Signed-off-by: Mike Frysinger <vapier at gentoo.org>
Signed-off-by: Riku Voipio <riku.voipio at nokia.com>
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index bb6ef43..4412a9b 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -235,6 +235,12 @@ _syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
const struct timespec *,timeout,int *,uaddr2,int,val3)
#endif
#endif
+#define __NR_sys_sched_getaffinity __NR_sched_getaffinity
+_syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
+ unsigned long *, user_mask_ptr);
+#define __NR_sys_sched_setaffinity __NR_sched_setaffinity
+_syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len,
+ unsigned long *, user_mask_ptr);
static bitmask_transtbl fcntl_flags_tbl[] = {
{ TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
@@ -6354,6 +6360,67 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
return value. */
ret = -TARGET_ENOTDIR;
break;
+ case TARGET_NR_sched_getaffinity:
+ {
+ unsigned int mask_size;
+ unsigned long *mask;
+
+ /*
+ * sched_getaffinity needs multiples of ulong, so need to take
+ * care of mismatches between target ulong and host ulong sizes.
+ */
+ if (arg2 & (sizeof(abi_ulong) - 1)) {
+ ret = -TARGET_EINVAL;
+ break;
+ }
+ mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
+
+ mask = alloca(mask_size);
+ ret = get_errno(sys_sched_getaffinity(arg1, mask_size, mask));
+
+ if (!is_error(ret)) {
+ if (arg2 > ret) {
+ /* Zero out any extra space kernel didn't fill */
+ unsigned long zero = arg2 - ret;
+ p = alloca(zero);
+ memset(p, 0, zero);
+ if (copy_to_user(arg3 + zero, p, zero)) {
+ goto efault;
+ }
+ arg2 = ret;
+ }
+ if (copy_to_user(arg3, mask, arg2)) {
+ goto efault;
+ }
+ ret = arg2;
+ }
+ }
+ break;
+ case TARGET_NR_sched_setaffinity:
+ {
+ unsigned int mask_size;
+ unsigned long *mask;
+
+ /*
+ * sched_setaffinity needs multiples of ulong, so need to take
+ * care of mismatches between target ulong and host ulong sizes.
+ */
+ if (arg2 & (sizeof(abi_ulong) - 1)) {
+ ret = -TARGET_EINVAL;
+ break;
+ }
+ mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
+
+ mask = alloca(mask_size);
+ if (!lock_user_struct(VERIFY_READ, p, arg3, 1)) {
+ goto efault;
+ }
+ memcpy(mask, p, arg2);
+ unlock_user_struct(p, arg2, 0);
+
+ ret = get_errno(sys_sched_setaffinity(arg1, mask_size, mask));
+ }
+ break;
case TARGET_NR_sched_setparam:
{
struct sched_param *target_schp;
commit c3109ba1b109f84929abbfe0462d910d5aa8617c
Author: Mike Frysinger <vapier at gentoo.org>
Date: Mon Feb 7 01:05:54 2011 -0500
linux-user/FLAT: allow targets to override FLAT processing
This brings flatload.c more in line with the current Linux FLAT loader
which allows targets to handle various FLAT aspects in their own way.
For the common behavior, the new functions get stubbed out.
Signed-off-by: Mike Frysinger <vapier at gentoo.org>
Signed-off-by: Riku Voipio <riku.voipio at nokia.com>
diff --git a/Makefile.target b/Makefile.target
index b0ba95f..48e6c00 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -107,7 +107,7 @@ ifdef CONFIG_LINUX_USER
$(call set-vpath, $(SRC_PATH)/linux-user:$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR))
-QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR)
+QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) -I$(SRC_PATH)/linux-user
obj-y = main.o syscall.o strace.o mmap.o signal.o thunk.o \
elfload.o linuxload.o uaccess.o gdbstub.o cpu-uname.o \
qemu-malloc.o $(oslib-obj-y)
diff --git a/linux-user/flatload.c b/linux-user/flatload.c
index d8b4476..cd7af7c 100644
--- a/linux-user/flatload.c
+++ b/linux-user/flatload.c
@@ -41,6 +41,8 @@
#include "qemu.h"
#include "flat.h"
+#define ntohl(x) be32_to_cpu(x)
+#include <target_flat.h>
//#define DEBUG
@@ -50,14 +52,6 @@
#define DBG_FLT(...)
#endif
-#define flat_reloc_valid(reloc, size) ((reloc) <= (size))
-#define flat_old_ram_flag(flag) (flag)
-#ifdef TARGET_WORDS_BIGENDIAN
-#define flat_get_relocate_addr(relval) (relval)
-#else
-#define flat_get_relocate_addr(relval) bswap32(relval)
-#endif
-
#define RELOC_FAILED 0xff00ff01 /* Relocation incorrect somewhere */
#define UNLOADED_LIB 0x7ff000ff /* Placeholder for unused library */
@@ -78,8 +72,6 @@ static int load_flat_shared_library(int id, struct lib_info *p);
struct linux_binprm;
-#define ntohl(x) be32_to_cpu(x)
-
/****************************************************************************/
/*
* create_flat_tables() parses the env- and arg-strings in new user
@@ -625,6 +617,7 @@ static int load_flat_file(struct linux_binprm * bprm,
* __start to address 4 so that is okay).
*/
if (rev > OLD_FLAT_VERSION) {
+ abi_ulong persistent = 0;
for (i = 0; i < relocs; i++) {
abi_ulong addr, relval;
@@ -633,6 +626,9 @@ static int load_flat_file(struct linux_binprm * bprm,
relocated first). */
if (get_user_ual(relval, reloc + i * sizeof(abi_ulong)))
return -EFAULT;
+ relval = ntohl(relval);
+ if (flat_set_persistent(relval, &persistent))
+ continue;
addr = flat_get_relocate_addr(relval);
rp = calc_reloc(addr, libinfo, id, 1);
if (rp == RELOC_FAILED)
@@ -641,22 +637,20 @@ static int load_flat_file(struct linux_binprm * bprm,
/* Get the pointer's value. */
if (get_user_ual(addr, rp))
return -EFAULT;
+ addr = flat_get_addr_from_rp(rp, relval, flags, &persistent);
if (addr != 0) {
/*
* Do the relocation. PIC relocs in the data section are
* already in target order
*/
-
-#ifndef TARGET_WORDS_BIGENDIAN
if ((flags & FLAT_FLAG_GOTPIC) == 0)
- addr = bswap32(addr);
-#endif
+ addr = ntohl(addr);
addr = calc_reloc(addr, libinfo, id, 0);
if (addr == RELOC_FAILED)
return -ENOEXEC;
/* Write back the relocated pointer. */
- if (put_user_ual(addr, rp))
+ if (flat_put_addr_at_rp(rp, addr, relval))
return -EFAULT;
}
}
@@ -782,7 +776,8 @@ int load_flt_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
stack_len *= sizeof(abi_ulong);
if ((sp + stack_len) & 15)
sp -= 16 - ((sp + stack_len) & 15);
- sp = loader_build_argptr(bprm->envc, bprm->argc, sp, p, 1);
+ sp = loader_build_argptr(bprm->envc, bprm->argc, sp, p,
+ flat_argvp_envp_on_stack());
/* Fake some return addresses to ensure the call chain will
* initialise library in order for us. We are required to call
diff --git a/linux-user/target_flat.h b/linux-user/target_flat.h
new file mode 100644
index 0000000..0ba6bdd
--- /dev/null
+++ b/linux-user/target_flat.h
@@ -0,0 +1,10 @@
+/* If your arch needs to do custom stuff, create your own target_flat.h
+ * header file in linux-user/<your arch>/
+ */
+#define flat_argvp_envp_on_stack() 1
+#define flat_reloc_valid(reloc, size) ((reloc) <= (size))
+#define flat_old_ram_flag(flag) (flag)
+#define flat_get_relocate_addr(relval) (relval)
+#define flat_get_addr_from_rp(rp, relval, flags, persistent) (rp)
+#define flat_set_persistent(relval, persistent) (*persistent)
+#define flat_put_addr_at_rp(rp, addr, relval) put_user_ual(addr, rp)
commit 82a39595f7c70aecfb4649ae5a125147b62131f8
Author: Mike Frysinger <vapier at gentoo.org>
Date: Mon Feb 7 01:05:53 2011 -0500
linux-user/FLAT: fix auto-stack sizing
The current auto-stack sizing works like it does on a NOMMU system; the
problem is that this only works if the envp/argv arrays are fairly slim.
On a desktop system, this is rarely the case, and can easily blow past
the stack and into data/text regions as the default stack for FLAT progs
is a mere 4KiB. So rather than rely on the NOMMU calculation (which is
only there because NOMMU can't easily allocate gobs of contiguous mem),
calc the full space actually needed and let the MMU host make space.
Signed-off-by: Mike Frysinger <vapier at gentoo.org>
Signed-off-by: Riku Voipio <riku.voipio at nokia.com>
diff --git a/linux-user/flatload.c b/linux-user/flatload.c
index 8f9f4a5..d8b4476 100644
--- a/linux-user/flatload.c
+++ b/linux-user/flatload.c
@@ -733,8 +733,15 @@ int load_flt_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
* pedantic and include space for the argv/envp array as it may have
* a lot of entries.
*/
-#define TOP_OF_ARGS (TARGET_PAGE_SIZE * MAX_ARG_PAGES - sizeof(void *))
- stack_len = TOP_OF_ARGS - bprm->p; /* the strings */
+ stack_len = 0;
+ for (i = 0; i < bprm->argc; ++i) {
+ /* the argv strings */
+ stack_len += strlen(bprm->argv[i]);
+ }
+ for (i = 0; i < bprm->envc; ++i) {
+ /* the envp strings */
+ stack_len += strlen(bprm->envp[i]);
+ }
stack_len += (bprm->argc + 1) * 4; /* the argv array */
stack_len += (bprm->envc + 1) * 4; /* the envp array */
commit 906c1b8ec8ed8987662e2697af20b9ca19c659b5
Author: Mike Frysinger <vapier at gentoo.org>
Date: Mon Feb 7 01:05:52 2011 -0500
linux-user: decode MAP_{UNINITIALIZED,EXECUTABLE} in strace
Signed-off-by: Mike Frysinger <vapier at gentoo.org>
Signed-off-by: Riku Voipio <riku.voipio at nokia.com>
diff --git a/linux-user/strace.c b/linux-user/strace.c
index bf9a0d9..a8786bb 100644
--- a/linux-user/strace.c
+++ b/linux-user/strace.c
@@ -398,6 +398,7 @@ UNUSED static struct flags mmap_flags[] = {
FLAG_TARGET(MAP_DENYWRITE),
FLAG_TARGET(MAP_FIXED),
FLAG_TARGET(MAP_GROWSDOWN),
+ FLAG_TARGET(MAP_EXECUTABLE),
#ifdef MAP_LOCKED
FLAG_TARGET(MAP_LOCKED),
#endif
@@ -408,6 +409,9 @@ UNUSED static struct flags mmap_flags[] = {
#ifdef MAP_POPULATE
FLAG_TARGET(MAP_POPULATE),
#endif
+#ifdef TARGET_MAP_UNINITIALIZED
+ FLAG_TARGET(MAP_UNINITIALIZED),
+#endif
FLAG_END,
};
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index d02a9bf..4742ac0 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -999,6 +999,7 @@ struct target_winsize {
#define TARGET_MAP_NORESERVE 0x4000 /* don't check for reservations */
#define TARGET_MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
#define TARGET_MAP_NONBLOCK 0x10000 /* do not block on IO */
+#define TARGET_MAP_UNINITIALIZED 0x4000000 /* for anonymous mmap, memory could be uninitialized */
#endif
#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_CRIS)
commit d8035d4cfce42e0268e39e109d5abf01d9f25259
Author: Mike Frysinger <vapier at gentoo.org>
Date: Mon Feb 7 01:05:51 2011 -0500
linux-user: add ppoll syscall support
Some architectures (like Blackfin) only implement ppoll (and skip poll).
So add support for it using existing poll code.
Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Mike Frysinger <vapier at gentoo.org>
Signed-off-by: Riku Voipio <riku.voipio at nokia.com>
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 6116ab5..bb6ef43 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -529,6 +529,15 @@ static int sys_inotify_init1(int flags)
#undef TARGET_NR_inotify_rm_watch
#endif /* CONFIG_INOTIFY */
+#if defined(TARGET_NR_ppoll)
+#ifndef __NR_ppoll
+# define __NR_ppoll -1
+#endif
+#define __NR_sys_ppoll __NR_ppoll
+_syscall5(int, sys_ppoll, struct pollfd *, fds, nfds_t, nfds,
+ struct timespec *, timeout, const __sigset_t *, sigmask,
+ size_t, sigsetsize)
+#endif
extern int personality(int);
extern int flock(int, int);
@@ -6230,8 +6239,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = do_select(arg1, arg2, arg3, arg4, arg5);
break;
#endif
-#ifdef TARGET_NR_poll
+#if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll)
+# ifdef TARGET_NR_poll
case TARGET_NR_poll:
+# endif
+# ifdef TARGET_NR_ppoll
+ case TARGET_NR_ppoll:
+# endif
{
struct target_pollfd *target_pfd;
unsigned int nfds = arg2;
@@ -6242,12 +6256,51 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
if (!target_pfd)
goto efault;
+
pfd = alloca(sizeof(struct pollfd) * nfds);
for(i = 0; i < nfds; i++) {
pfd[i].fd = tswap32(target_pfd[i].fd);
pfd[i].events = tswap16(target_pfd[i].events);
}
- ret = get_errno(poll(pfd, nfds, timeout));
+
+# ifdef TARGET_NR_ppoll
+ if (num == TARGET_NR_ppoll) {
+ struct timespec _timeout_ts, *timeout_ts = &_timeout_ts;
+ target_sigset_t *target_set;
+ sigset_t _set, *set = &_set;
+
+ if (arg3) {
+ if (target_to_host_timespec(timeout_ts, arg3)) {
+ unlock_user(target_pfd, arg1, 0);
+ goto efault;
+ }
+ } else {
+ timeout_ts = NULL;
+ }
+
+ if (arg4) {
+ target_set = lock_user(VERIFY_READ, arg4, sizeof(target_sigset_t), 1);
+ if (!target_set) {
+ unlock_user(target_pfd, arg1, 0);
+ goto efault;
+ }
+ target_to_host_sigset(set, target_set);
+ } else {
+ set = NULL;
+ }
+
+ ret = get_errno(sys_ppoll(pfd, nfds, timeout_ts, set, _NSIG/8));
+
+ if (!is_error(ret) && arg3) {
+ host_to_target_timespec(arg3, timeout_ts);
+ }
+ if (arg4) {
+ unlock_user(target_set, arg4, 0);
+ }
+ } else
+# endif
+ ret = get_errno(poll(pfd, nfds, timeout));
+
if (!is_error(ret)) {
for(i = 0; i < nfds; i++) {
target_pfd[i].revents = tswap16(pfd[i].revents);
commit 1af02e83c00fe269fbbaeaccc7c0b914ad277d18
Author: Mike Frysinger <vapier at gentoo.org>
Date: Mon Feb 7 01:05:50 2011 -0500
linux-user/elfload: add FDPIC support
Signed-off-by: Mike Frysinger <vapier at gentoo.org>
Signed-off-by: Riku Voipio <riku.voipio at nokia.com>
diff --git a/elf.h b/elf.h
index 7067c90..d2f24f4 100644
--- a/elf.h
+++ b/elf.h
@@ -1191,6 +1191,25 @@ typedef struct elf64_note {
Elf64_Word n_type; /* Content type */
} Elf64_Nhdr;
+
+/* This data structure represents a PT_LOAD segment. */
+struct elf32_fdpic_loadseg {
+ /* Core address to which the segment is mapped. */
+ Elf32_Addr addr;
+ /* VMA recorded in the program header. */
+ Elf32_Addr p_vaddr;
+ /* Size of this segment in memory. */
+ Elf32_Word p_memsz;
+};
+struct elf32_fdpic_loadmap {
+ /* Protocol version number, must be zero. */
+ Elf32_Half version;
+ /* Number of segments in this map. */
+ Elf32_Half nsegs;
+ /* The actual memory map. */
+ struct elf32_fdpic_loadseg segs[/*nsegs*/];
+};
+
#ifdef ELF_CLASS
#if ELF_CLASS == ELFCLASS32
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 08c44d8..2de83e4 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1075,6 +1075,33 @@ static void zero_bss(abi_ulong elf_bss, abi_ulong last_bss, int prot)
}
}
+#ifdef CONFIG_USE_FDPIC
+static abi_ulong loader_build_fdpic_loadmap(struct image_info *info, abi_ulong sp)
+{
+ uint16_t n;
+ struct elf32_fdpic_loadseg *loadsegs = info->loadsegs;
+
+ /* elf32_fdpic_loadseg */
+ n = info->nsegs;
+ while (n--) {
+ sp -= 12;
+ put_user_u32(loadsegs[n].addr, sp+0);
+ put_user_u32(loadsegs[n].p_vaddr, sp+4);
+ put_user_u32(loadsegs[n].p_memsz, sp+8);
+ }
+
+ /* elf32_fdpic_loadmap */
+ sp -= 4;
+ put_user_u16(0, sp+0); /* version */
+ put_user_u16(info->nsegs, sp+2); /* nsegs */
+
+ info->personality = PER_LINUX_FDPIC;
+ info->loadmap_addr = sp;
+
+ return sp;
+}
+#endif
+
static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
struct elfhdr *exec,
struct image_info *info,
@@ -1087,6 +1114,21 @@ static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
const int n = sizeof(elf_addr_t);
sp = p;
+
+#ifdef CONFIG_USE_FDPIC
+ /* Needs to be before we load the env/argc/... */
+ if (elf_is_fdpic(exec)) {
+ /* Need 4 byte alignment for these structs */
+ sp &= ~3;
+ sp = loader_build_fdpic_loadmap(info, sp);
+ info->other_info = interp_info;
+ if (interp_info) {
+ interp_info->other_info = info;
+ sp = loader_build_fdpic_loadmap(interp_info, sp);
+ }
+ }
+#endif
+
u_platform = 0;
k_platform = ELF_PLATFORM;
if (k_platform) {
@@ -1197,6 +1239,11 @@ static void load_elf_image(const char *image_name, int image_fd,
}
bswap_phdr(phdr, ehdr->e_phnum);
+#ifdef CONFIG_USE_FDPIC
+ info->nsegs = 0;
+ info->pt_dynamic_addr = 0;
+#endif
+
/* Find the maximum size of the image and allocate an appropriate
amount of memory to handle that. */
loaddr = -1, hiaddr = 0;
@@ -1210,6 +1257,9 @@ static void load_elf_image(const char *image_name, int image_fd,
if (a > hiaddr) {
hiaddr = a;
}
+#ifdef CONFIG_USE_FDPIC
+ ++info->nsegs;
+#endif
}
}
@@ -1290,6 +1340,27 @@ static void load_elf_image(const char *image_name, int image_fd,
}
load_bias = load_addr - loaddr;
+#ifdef CONFIG_USE_FDPIC
+ {
+ struct elf32_fdpic_loadseg *loadsegs = info->loadsegs =
+ qemu_malloc(sizeof(*loadsegs) * info->nsegs);
+
+ for (i = 0; i < ehdr->e_phnum; ++i) {
+ switch (phdr[i].p_type) {
+ case PT_DYNAMIC:
+ info->pt_dynamic_addr = phdr[i].p_vaddr + load_bias;
+ break;
+ case PT_LOAD:
+ loadsegs->addr = phdr[i].p_vaddr + load_bias;
+ loadsegs->p_vaddr = phdr[i].p_vaddr;
+ loadsegs->p_memsz = phdr[i].p_memsz;
+ ++loadsegs;
+ break;
+ }
+ }
+ }
+#endif
+
info->load_bias = load_bias;
info->load_addr = load_addr;
info->entry = ehdr->e_entry + load_bias;
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 32de241..250814d 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -51,6 +51,13 @@ struct image_info {
abi_ulong arg_start;
abi_ulong arg_end;
int personality;
+#ifdef CONFIG_USE_FDPIC
+ abi_ulong loadmap_addr;
+ uint16_t nsegs;
+ void *loadsegs;
+ abi_ulong pt_dynamic_addr;
+ struct image_info *other_info;
+#endif
};
#ifdef TARGET_I386
commit 73160d952922157f16946e8ebb4419072de4c657
Author: Mike Frysinger <vapier at gentoo.org>
Date: Mon Feb 7 01:05:49 2011 -0500
linux-user: fix sizeof handling for getsockopt
Signed-off-by: Mike Frysinger <vapier at gentoo.org>
Signed-off-by: Riku Voipio <riku.voipio at nokia.com>
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 499c4d7..6116ab5 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -1448,7 +1448,7 @@ static abi_long do_getsockopt(int sockfd, int level, int optname,
return -TARGET_EFAULT;
if (len < 0)
return -TARGET_EINVAL;
- lv = sizeof(int);
+ lv = sizeof(lv);
ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
if (ret < 0)
return ret;
@@ -1485,7 +1485,7 @@ static abi_long do_getsockopt(int sockfd, int level, int optname,
return -TARGET_EFAULT;
if (len < 0)
return -TARGET_EINVAL;
- lv = sizeof(int);
+ lv = sizeof(lv);
ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
if (ret < 0)
return ret;
commit 8d79de6e42947a4a11ad7c7bb87e8f745a4f8321
Author: Stefan Weil <weil at mail.berlios.de>
Date: Mon Jan 17 21:36:06 2011 +0100
linux-user: Fix possible realloc memory leak
Extract from "man realloc":
"If realloc() fails the original block is left untouched;
it is not freed or moved."
Fix a possible memory leak (reported by cppcheck).
Cc: Riku Voipio <riku.voipio at iki.fi>
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Riku Voipio <riku.voipio at nokia.com>
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 33d776d..08c44d8 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1481,7 +1481,7 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
struct elf_shdr *shdr;
char *strings;
struct syminfo *s;
- struct elf_sym *syms;
+ struct elf_sym *syms, *new_syms;
shnum = hdr->e_shnum;
i = shnum * sizeof(struct elf_shdr);
@@ -1550,12 +1550,14 @@ static void load_symbols(struct elfhdr *hdr, int fd, abi_ulong load_bias)
that we threw away. Whether or not this has any effect on the
memory allocation depends on the malloc implementation and how
many symbols we managed to discard. */
- syms = realloc(syms, nsyms * sizeof(*syms));
- if (syms == NULL) {
+ new_syms = realloc(syms, nsyms * sizeof(*syms));
+ if (new_syms == NULL) {
free(s);
+ free(syms);
free(strings);
return;
}
+ syms = new_syms;
qsort(syms, nsyms, sizeof(*syms), symcmp);
commit 6672b0b22a8ab92ad3a07889c2220a7568a3da30
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Thu Jan 20 03:28:02 2011 +0000
linux-user: Add support for -version option
Add support to the linux-user qemu for the -version command line
option, bringing it into line with the system emulation qemu.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Riku Voipio <riku.voipio at nokia.com>
diff --git a/linux-user/main.c b/linux-user/main.c
index 0d627d6..e651bfd 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2624,14 +2624,21 @@ void cpu_loop (CPUState *env)
}
#endif /* TARGET_ALPHA */
+static void version(void)
+{
+ printf("qemu-" TARGET_ARCH " version " QEMU_VERSION QEMU_PKGVERSION
+ ", Copyright (c) 2003-2008 Fabrice Bellard\n");
+}
+
static void usage(void)
{
- printf("qemu-" TARGET_ARCH " version " QEMU_VERSION QEMU_PKGVERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n"
- "usage: qemu-" TARGET_ARCH " [options] program [arguments...]\n"
+ version();
+ printf("usage: qemu-" TARGET_ARCH " [options] program [arguments...]\n"
"Linux CPU emulator (compiled for %s emulation)\n"
"\n"
"Standard options:\n"
"-h print this help\n"
+ "-version display version information and exit\n"
"-g port wait gdb connection to port\n"
"-L path set the elf interpreter prefix (default=%s)\n"
"-s size set the stack size in bytes (default=%ld)\n"
@@ -2886,8 +2893,10 @@ int main(int argc, char **argv, char **envp)
singlestep = 1;
} else if (!strcmp(r, "strace")) {
do_strace = 1;
- } else
- {
+ } else if (!strcmp(r, "version")) {
+ version();
+ exit(0);
+ } else {
usage();
}
}
commit c0c1dc992584b8ccbae0e8f8b09124b76662633b
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Tue Feb 8 18:18:19 2011 +0100
cris, microblaze: use cpu_has_work
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
diff --git a/target-cris/exec.h b/target-cris/exec.h
index 93ce768..34c0132 100644
--- a/target-cris/exec.h
+++ b/target-cris/exec.h
@@ -37,9 +37,7 @@ static inline int cpu_halted(CPUState *env) {
if (!env->halted)
return 0;
- /* IRQ, NMI and GURU execeptions wakes us up. */
- if (env->interrupt_request
- & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI)) {
+ if (cpu_has_work(env)) {
env->halted = 0;
return 0;
}
diff --git a/target-microblaze/exec.h b/target-microblaze/exec.h
index 87b2494..ab19828 100644
--- a/target-microblaze/exec.h
+++ b/target-microblaze/exec.h
@@ -36,9 +36,7 @@ static inline int cpu_halted(CPUState *env) {
if (!env->halted)
return 0;
- /* IRQ, NMI and GURU execeptions wakes us up. */
- if (env->interrupt_request
- & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_NMI)) {
+ if (cpu_has_work(env)) {
env->halted = 0;
return 0;
}
commit 29057492871e63caeab8ee7cdf1062c0270f19d8
Author: Jan Kiszka <jan.kiszka at web.de>
Date: Fri Feb 4 13:47:25 2011 -0200
x86: Fix MCA broadcast parameters for TCG case
When broadcasting MCEs, we need to set MCIP and RIPV in mcg_status like
it is done for KVM. Use the symbolic constants at this chance.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 1217452..f0c546d 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1147,8 +1147,8 @@ void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
if (cenv == env) {
continue;
}
-
- qemu_inject_x86_mce(env, 1, 0xa000000000000000, 0, 0, 0);
+ qemu_inject_x86_mce(env, 1, MCI_STATUS_VAL | MCI_STATUS_UC,
+ MCG_STATUS_MCIP | MCG_STATUS_RIPV, 0, 0);
}
}
}
commit f26e5a54f0554798a2e6f7a074b809b13635d007
Author: Stefan Weil <weil at mail.berlios.de>
Date: Fri Feb 4 22:01:32 2011 +0100
qemu-timer: Fix compilation of new timer code for w32, w64
qemu_next_alarm_deadline() is needed by MinGW, too.
Cc: Paolo Bonzini <pbonzini at redhat.com>
Cc: Anthony Liguori <aliguori at us.ibm.com>
Acked-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/qemu-timer.c b/qemu-timer.c
index 658f637..b0db780 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -708,8 +708,6 @@ int64_t qemu_next_deadline(void)
return delta;
}
-#ifndef _WIN32
-
static int64_t qemu_next_alarm_deadline(void)
{
int64_t delta;
@@ -922,6 +920,8 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t)
#endif /* defined(__linux__) */
+#if !defined(_WIN32)
+
static int unix_start_timer(struct qemu_alarm_timer *t)
{
struct sigaction act;
commit 8591675f44929a9e4b5d3a5fd702a4b6d41c7903
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date: Wed Jan 26 12:12:35 2011 -0200
block: enable in_use flag
Set block device in use during block migration, disallow drive_del and
bdrv_truncate for in use devices.
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block-migration.c b/block-migration.c
index 323e1e2..8218bac 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -301,6 +301,7 @@ static void init_blk_migration_it(void *opaque, BlockDriverState *bs)
bmds->shared_base = block_mig_state.shared_base;
alloc_aio_bitmap(bmds);
drive_get_ref(drive_get_by_blockdev(bs));
+ bdrv_set_in_use(bs, 1);
block_mig_state.total_sector_sum += sectors;
@@ -539,6 +540,7 @@ static void blk_mig_cleanup(Monitor *mon)
while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) {
QSIMPLEQ_REMOVE_HEAD(&block_mig_state.bmds_list, entry);
+ bdrv_set_in_use(bmds->bs, 0);
drive_put_ref(drive_get_by_blockdev(bmds->bs));
qemu_free(bmds->aio_bitmap);
qemu_free(bmds);
diff --git a/block.c b/block.c
index ee9edfc..b476479 100644
--- a/block.c
+++ b/block.c
@@ -1132,6 +1132,8 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset)
return -ENOTSUP;
if (bs->read_only)
return -EACCES;
+ if (bdrv_in_use(bs))
+ return -EBUSY;
ret = drv->bdrv_truncate(bs, offset);
if (ret == 0) {
ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
diff --git a/blockdev.c b/blockdev.c
index f2a00bd..ecfadc1 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -726,6 +726,10 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
qerror_report(QERR_DEVICE_NOT_FOUND, id);
return -1;
}
+ if (bdrv_in_use(bs)) {
+ qerror_report(QERR_DEVICE_IN_USE, id);
+ return -1;
+ }
/* quiesce block driver; prevent further io */
qemu_aio_flush();
commit db593f2565dc12442d6bac9e8eaefa027dfcada9
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date: Wed Jan 26 12:12:34 2011 -0200
Add flag to indicate external users to block device
Certain operations such as drive_del or resize cannot be performed
while external users (eg. block migration) reference the block device.
Add a flag to indicate that.
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block.c b/block.c
index 998df1b..ee9edfc 100644
--- a/block.c
+++ b/block.c
@@ -2774,6 +2774,17 @@ int64_t bdrv_get_dirty_count(BlockDriverState *bs)
return bs->dirty_count;
}
+void bdrv_set_in_use(BlockDriverState *bs, int in_use)
+{
+ assert(bs->in_use != in_use);
+ bs->in_use = in_use;
+}
+
+int bdrv_in_use(BlockDriverState *bs)
+{
+ return bs->in_use;
+}
+
int bdrv_img_create(const char *filename, const char *fmt,
const char *base_filename, const char *base_fmt,
char *options, uint64_t img_size, int flags)
diff --git a/block.h b/block.h
index 239f729..19f4768 100644
--- a/block.h
+++ b/block.h
@@ -241,6 +241,8 @@ void bdrv_reset_dirty(BlockDriverState *bs, int64_t cur_sector,
int nr_sectors);
int64_t bdrv_get_dirty_count(BlockDriverState *bs);
+void bdrv_set_in_use(BlockDriverState *bs, int in_use);
+int bdrv_in_use(BlockDriverState *bs);
typedef enum {
BLKDBG_L1_UPDATE,
diff --git a/block_int.h b/block_int.h
index 6ebdc3e..545ad11 100644
--- a/block_int.h
+++ b/block_int.h
@@ -199,6 +199,7 @@ struct BlockDriverState {
char device_name[32];
unsigned long *dirty_bitmap;
int64_t dirty_count;
+ int in_use; /* users other than guest access, eg. block migration */
QTAILQ_ENTRY(BlockDriverState) list;
void *private;
};
commit f48905d44f670cd83227b3a8d06ae1406f0c771c
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date: Wed Jan 26 12:12:33 2011 -0200
block-migration: add reference to target DriveInfo
So that ejection of attached device by guest does not free data
in use by block migration instance.
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
CC: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block-migration.c b/block-migration.c
index 483ca7b..323e1e2 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -19,6 +19,7 @@
#include "monitor.h"
#include "block-migration.h"
#include "migration.h"
+#include "blockdev.h"
#include <assert.h>
#define BLOCK_SIZE (BDRV_SECTORS_PER_DIRTY_CHUNK << BDRV_SECTOR_BITS)
@@ -299,6 +300,7 @@ static void init_blk_migration_it(void *opaque, BlockDriverState *bs)
bmds->completed_sectors = 0;
bmds->shared_base = block_mig_state.shared_base;
alloc_aio_bitmap(bmds);
+ drive_get_ref(drive_get_by_blockdev(bs));
block_mig_state.total_sector_sum += sectors;
@@ -537,6 +539,7 @@ static void blk_mig_cleanup(Monitor *mon)
while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) {
QSIMPLEQ_REMOVE_HEAD(&block_mig_state.bmds_list, entry);
+ drive_put_ref(drive_get_by_blockdev(bmds->bs));
qemu_free(bmds->aio_bitmap);
qemu_free(bmds);
}
commit 84fb392526479d54602a3830326d50d44657f630
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date: Wed Jan 26 12:12:32 2011 -0200
blockdev: add refcount to DriveInfo
The host part of a block device can be deleted with in progress
block migration.
To fix this, add a reference count to DriveInfo, freeing resources
on last reference.
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
CC: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/blockdev.c b/blockdev.c
index 1c56da0..f2a00bd 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -71,7 +71,7 @@ void blockdev_auto_del(BlockDriverState *bs)
DriveInfo *dinfo = drive_get_by_blockdev(bs);
if (dinfo && dinfo->auto_del) {
- drive_uninit(dinfo);
+ drive_put_ref(dinfo);
}
}
@@ -178,7 +178,7 @@ static void bdrv_format_print(void *opaque, const char *name)
error_printf(" %s", name);
}
-void drive_uninit(DriveInfo *dinfo)
+static void drive_uninit(DriveInfo *dinfo)
{
qemu_opts_del(dinfo->opts);
bdrv_delete(dinfo->bdrv);
@@ -186,6 +186,19 @@ void drive_uninit(DriveInfo *dinfo)
qemu_free(dinfo);
}
+void drive_put_ref(DriveInfo *dinfo)
+{
+ assert(dinfo->refcount);
+ if (--dinfo->refcount == 0) {
+ drive_uninit(dinfo);
+ }
+}
+
+void drive_get_ref(DriveInfo *dinfo)
+{
+ dinfo->refcount++;
+}
+
static int parse_block_error_action(const char *buf, int is_read)
{
if (!strcmp(buf, "ignore")) {
@@ -453,6 +466,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
dinfo->bus = bus_id;
dinfo->unit = unit_id;
dinfo->opts = opts;
+ dinfo->refcount = 1;
if (serial)
strncpy(dinfo->serial, serial, sizeof(dinfo->serial) - 1);
QTAILQ_INSERT_TAIL(&drives, dinfo, next);
diff --git a/blockdev.h b/blockdev.h
index 84e462a..2c9e780 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -36,13 +36,15 @@ struct DriveInfo {
QemuOpts *opts;
char serial[BLOCK_SERIAL_STRLEN + 1];
QTAILQ_ENTRY(DriveInfo) next;
+ int refcount;
};
DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
DriveInfo *drive_get_by_index(BlockInterfaceType type, int index);
int drive_get_max_bus(BlockInterfaceType type);
DriveInfo *drive_get_next(BlockInterfaceType type);
-void drive_uninit(DriveInfo *dinfo);
+void drive_get_ref(DriveInfo *dinfo);
+void drive_put_ref(DriveInfo *dinfo);
DriveInfo *drive_get_by_blockdev(BlockDriverState *bs);
QemuOpts *drive_def(const char *optstr);
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index b6dcbda..478fe9b 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -147,7 +147,7 @@ void drive_hot_add(Monitor *mon, const QDict *qdict)
err:
if (dinfo)
- drive_uninit(dinfo);
+ drive_put_ref(dinfo);
return;
}
commit 8f794c557c4b51c7a957d47ef6a2230114bb9e79
Author: Marcelo Tosatti <mtosatti at redhat.com>
Date: Wed Jan 26 12:12:31 2011 -0200
block-migration: actually disable dirty tracking on cleanup
Call to set_dirty_tracking() is misplaced.
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block-migration.c b/block-migration.c
index c9d3e81..483ca7b 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -533,6 +533,8 @@ static void blk_mig_cleanup(Monitor *mon)
BlkMigDevState *bmds;
BlkMigBlock *blk;
+ set_dirty_tracking(0);
+
while ((bmds = QSIMPLEQ_FIRST(&block_mig_state.bmds_list)) != NULL) {
QSIMPLEQ_REMOVE_HEAD(&block_mig_state.bmds_list, entry);
qemu_free(bmds->aio_bitmap);
@@ -545,8 +547,6 @@ static void blk_mig_cleanup(Monitor *mon)
qemu_free(blk);
}
- set_dirty_tracking(0);
-
monitor_printf(mon, "\n");
}
commit 2c4b9d0ea42c27ec2112e437a0fa954afe73bd23
Author: Alexander Graf <agraf at suse.de>
Date: Tue Feb 1 15:51:31 2011 +0100
ahci: make number of ports runtime determined
Different AHCI controllers have a different number of ports, so the core
shouldn't care about the amount of ports available.
This patch makes the number of ports available to the AHCI core runtime
configurable, allowing us to have multiple different AHCI implementations
with different amounts of ports.
Signed-off-by: Alexander Graf <agraf at suse.de>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 105dd53..98bdf70 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -145,7 +145,7 @@ static void ahci_check_irq(AHCIState *s)
DPRINTF(-1, "check irq %#x\n", s->control_regs.irqstatus);
- for (i = 0; i < SATA_PORTS; i++) {
+ for (i = 0; i < s->ports; i++) {
AHCIPortRegs *pr = &s->dev[i].port_regs;
if (pr->irq_stat & pr->irq_mask) {
s->control_regs.irqstatus |= (1 << i);
@@ -303,7 +303,8 @@ static uint32_t ahci_mem_readl(void *ptr, target_phys_addr_t addr)
DPRINTF(-1, "(addr 0x%08X), val 0x%08X\n", (unsigned) addr, val);
} else if ((addr >= AHCI_PORT_REGS_START_ADDR) &&
- (addr < AHCI_PORT_REGS_END_ADDR)) {
+ (addr < (AHCI_PORT_REGS_START_ADDR +
+ (s->ports * AHCI_PORT_ADDR_OFFSET_LEN)))) {
val = ahci_port_read(s, (addr - AHCI_PORT_REGS_START_ADDR) >> 7,
addr & AHCI_PORT_ADDR_OFFSET_MASK);
}
@@ -355,7 +356,8 @@ static void ahci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
DPRINTF(-1, "write to unknown register 0x%x\n", (unsigned)addr);
}
} else if ((addr >= AHCI_PORT_REGS_START_ADDR) &&
- (addr < AHCI_PORT_REGS_END_ADDR)) {
+ (addr < (AHCI_PORT_REGS_START_ADDR +
+ (s->ports * AHCI_PORT_ADDR_OFFSET_LEN)))) {
ahci_port_write(s, (addr - AHCI_PORT_REGS_START_ADDR) >> 7,
addr & AHCI_PORT_ADDR_OFFSET_MASK, val);
}
@@ -378,16 +380,16 @@ static void ahci_reg_init(AHCIState *s)
{
int i;
- s->control_regs.cap = (SATA_PORTS - 1) |
+ s->control_regs.cap = (s->ports - 1) |
(AHCI_NUM_COMMAND_SLOTS << 8) |
(AHCI_SUPPORTED_SPEED_GEN1 << AHCI_SUPPORTED_SPEED) |
HOST_CAP_NCQ | HOST_CAP_AHCI;
- s->control_regs.impl = (1 << SATA_PORTS) - 1;
+ s->control_regs.impl = (1 << s->ports) - 1;
s->control_regs.version = AHCI_VERSION_1_0;
- for (i = 0; i < SATA_PORTS; i++) {
+ for (i = 0; i < s->ports; i++) {
s->dev[i].port_state = STATE_RUN;
}
}
@@ -1096,17 +1098,19 @@ static const IDEDMAOps ahci_dma_ops = {
.reset = ahci_dma_reset,
};
-void ahci_init(AHCIState *s, DeviceState *qdev)
+void ahci_init(AHCIState *s, DeviceState *qdev, int ports)
{
qemu_irq *irqs;
int i;
+ s->ports = ports;
+ s->dev = qemu_mallocz(sizeof(AHCIDevice) * ports);
ahci_reg_init(s);
s->mem = cpu_register_io_memory(ahci_readfn, ahci_writefn, s,
DEVICE_LITTLE_ENDIAN);
- irqs = qemu_allocate_irqs(ahci_irq_set, s, SATA_PORTS);
+ irqs = qemu_allocate_irqs(ahci_irq_set, s, s->ports);
- for (i = 0; i < SATA_PORTS; i++) {
+ for (i = 0; i < s->ports; i++) {
AHCIDevice *ad = &s->dev[i];
ide_bus_new(&ad->port, qdev, i);
@@ -1120,6 +1124,11 @@ void ahci_init(AHCIState *s, DeviceState *qdev)
}
}
+void ahci_uninit(AHCIState *s)
+{
+ qemu_free(s->dev);
+}
+
void ahci_pci_map(PCIDevice *pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
@@ -1137,7 +1146,7 @@ void ahci_reset(void *opaque)
d->ahci.control_regs.irqstatus = 0;
d->ahci.control_regs.ghc = 0;
- for (i = 0; i < SATA_PORTS; i++) {
+ for (i = 0; i < d->ahci.ports; i++) {
ahci_reset_port(&d->ahci, i);
}
}
diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h
index b2786d1..a4560c4 100644
--- a/hw/ide/ahci.h
+++ b/hw/ide/ahci.h
@@ -188,11 +188,9 @@
#define AHCI_GENERIC_HOST_CONTROL_REGS_MAX_ADDR 0x20
/* Shouldn't this be 0x2c? */
-#define SATA_PORTS 4
-
#define AHCI_PORT_REGS_START_ADDR 0x100
-#define AHCI_PORT_REGS_END_ADDR (AHCI_PORT_REGS_START_ADDR + SATA_PORTS * 0x80)
#define AHCI_PORT_ADDR_OFFSET_MASK 0x7f
+#define AHCI_PORT_ADDR_OFFSET_LEN 0x80
#define AHCI_NUM_COMMAND_SLOTS 31
#define AHCI_SUPPORTED_SPEED 20
@@ -289,9 +287,10 @@ struct AHCIDevice {
};
typedef struct AHCIState {
- AHCIDevice dev[SATA_PORTS];
+ AHCIDevice *dev;
AHCIControlRegs control_regs;
int mem;
+ int ports;
qemu_irq irq;
} AHCIState;
@@ -323,7 +322,8 @@ typedef struct NCQFrame {
uint8_t reserved10;
} __attribute__ ((packed)) NCQFrame;
-void ahci_init(AHCIState *s, DeviceState *qdev);
+void ahci_init(AHCIState *s, DeviceState *qdev, int ports);
+void ahci_uninit(AHCIState *s);
void ahci_pci_map(PCIDevice *pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type);
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index 70cb766..f242d7a 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -100,7 +100,7 @@ static int pci_ich9_ahci_init(PCIDevice *dev)
msi_init(dev, 0x50, 1, true, false);
- ahci_init(&d->ahci, &dev->qdev);
+ ahci_init(&d->ahci, &dev->qdev, 6);
d->ahci.irq = d->card.irq[0];
return 0;
@@ -116,6 +116,7 @@ static int pci_ich9_uninit(PCIDevice *dev)
}
qemu_unregister_reset(ahci_reset, d);
+ ahci_uninit(&d->ahci);
return 0;
}
commit 760c3e44d3a1d8a7e9d22f0429b1805d1c688178
Author: Alexander Graf <agraf at suse.de>
Date: Tue Feb 1 15:51:30 2011 +0100
ahci: Implement HBA reset
The ahci code was missing its soft reset functionality. This wasn't really an
issue for Linux guests, but Windows gets confused when the controller doesn't
reset when it tells it so.
Using this patch I can now successfully boot Windows 7 from AHCI using AHCI
enabled SeaBIOS.
Signed-off-by: Alexander Graf <agraf at suse.de>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index e6ac77c..105dd53 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -335,7 +335,7 @@ static void ahci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
case HOST_CTL: /* R/W */
if (val & HOST_CTL_RESET) {
DPRINTF(-1, "HBA Reset\n");
- /* FIXME reset? */
+ ahci_reset(container_of(s, AHCIPCIState, ahci));
} else {
s->control_regs.ghc = (val & 0x3) | HOST_CTL_AHCI_EN;
ahci_check_irq(s);
@@ -1134,6 +1134,9 @@ void ahci_reset(void *opaque)
struct AHCIPCIState *d = opaque;
int i;
+ d->ahci.control_regs.irqstatus = 0;
+ d->ahci.control_regs.ghc = 0;
+
for (i = 0; i < SATA_PORTS; i++) {
ahci_reset_port(&d->ahci, i);
}
commit 87e62065bb5e0e544e45e6935e3ac2b053fe446e
Author: Alexander Graf <agraf at suse.de>
Date: Tue Feb 1 15:51:29 2011 +0100
ahci: send init d2h fis on fis enable
The drive sends a d2h init fis on initialization. Usually, the guest doesn't
receive fises yet at that point though, so the delivery is deferred.
Let's reflect that by sending the init fis on fis receive enablement.
Signed-off-by: Alexander Graf <agraf at suse.de>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 6822046..e6ac77c 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -47,6 +47,7 @@ static void check_cmd(AHCIState *s, int port);
static int handle_cmd(AHCIState *s,int port,int slot);
static void ahci_reset_port(AHCIState *s, int port);
static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis);
+static void ahci_init_d2h(AHCIDevice *ad);
static uint32_t ahci_port_read(AHCIState *s, int port, int offset)
{
@@ -230,6 +231,16 @@ static void ahci_port_write(AHCIState *s, int port, int offset, uint32_t val)
pr->cmd |= PORT_CMD_FIS_ON;
}
+ /* XXX usually the FIS would be pending on the bus here and
+ issuing deferred until the OS enables FIS receival.
+ Instead, we only submit it once - which works in most
+ cases, but is a hack. */
+ if ((pr->cmd & PORT_CMD_FIS_ON) &&
+ !s->dev[port].init_d2h_sent) {
+ ahci_init_d2h(&s->dev[port]);
+ s->dev[port].init_d2h_sent = 1;
+ }
+
check_cmd(s, port);
break;
case PORT_TFDATA:
@@ -462,12 +473,29 @@ static void ahci_check_cmd_bh(void *opaque)
check_cmd(ad->hba, ad->port_no);
}
+static void ahci_init_d2h(AHCIDevice *ad)
+{
+ uint8_t init_fis[0x20];
+ IDEState *ide_state = &ad->port.ifs[0];
+
+ memset(init_fis, 0, sizeof(init_fis));
+
+ init_fis[4] = 1;
+ init_fis[12] = 1;
+
+ if (ide_state->drive_kind == IDE_CD) {
+ init_fis[5] = ide_state->lcyl;
+ init_fis[6] = ide_state->hcyl;
+ }
+
+ ahci_write_fis_d2h(ad, init_fis);
+}
+
static void ahci_reset_port(AHCIState *s, int port)
{
AHCIDevice *d = &s->dev[port];
AHCIPortRegs *pr = &d->port_regs;
IDEState *ide_state = &d->port.ifs[0];
- uint8_t init_fis[0x20];
int i;
DPRINTF(port, "reset port\n");
@@ -482,6 +510,7 @@ static void ahci_reset_port(AHCIState *s, int port)
pr->scr_err = 0;
pr->scr_act = 0;
d->busy_slot = -1;
+ d->init_d2h_sent = 0;
ide_state = &s->dev[port].port.ifs[0];
if (!ide_state->bs) {
@@ -504,7 +533,6 @@ static void ahci_reset_port(AHCIState *s, int port)
ncq_tfs->used = 0;
}
- memset(init_fis, 0, sizeof(init_fis));
s->dev[port].port_state = STATE_RUN;
if (!ide_state->bs) {
s->dev[port].port_regs.sig = 0;
@@ -514,8 +542,6 @@ static void ahci_reset_port(AHCIState *s, int port)
ide_state->lcyl = 0x14;
ide_state->hcyl = 0xeb;
DPRINTF(port, "set lcyl = %d\n", ide_state->lcyl);
- init_fis[5] = ide_state->lcyl;
- init_fis[6] = ide_state->hcyl;
ide_state->status = SEEK_STAT | WRERR_STAT | READY_STAT;
} else {
s->dev[port].port_regs.sig = SATA_SIGNATURE_DISK;
@@ -523,9 +549,7 @@ static void ahci_reset_port(AHCIState *s, int port)
}
ide_state->error = 1;
- init_fis[4] = 1;
- init_fis[12] = 1;
- ahci_write_fis_d2h(d, init_fis);
+ ahci_init_d2h(d);
}
static void debug_print_fis(uint8_t *fis, int cmd_len)
diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h
index d65b5e3..b2786d1 100644
--- a/hw/ide/ahci.h
+++ b/hw/ide/ahci.h
@@ -282,6 +282,7 @@ struct AHCIDevice {
int dma_status;
int done_atapi_packet;
int busy_slot;
+ int init_d2h_sent;
BlockDriverCompletionFunc *dma_cb;
AHCICmdHdr *cur_cmd;
NCQTransferState ncq_tfs[AHCI_MAX_CMDS];
commit 7fb6577b130c615e42e1ccf8dad69c27c3eef085
Author: Alexander Graf <agraf at suse.de>
Date: Tue Feb 1 15:51:28 2011 +0100
ahci: split ICH and AHCI even more
Sebastian's patch already did a pretty good job at splitting up ICH-9
AHCI code and the AHCI core. We need some more though. Copyright was missing,
the lspci dump belongs to ICH-9, we don't need the AHCI core to have its
own qdev device duplicate.
So let's split them a bit more in this patch, making things easier to
read an understand.
Signed-off-by: Alexander Graf <agraf at suse.de>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 28412d0..6822046 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -19,47 +19,6 @@
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*
- *
- * lspci dump of a ICH-9 real device in IDE mode (hopefully close enough):
- *
- * 00:1f.2 SATA controller [0106]: Intel Corporation 82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA AHCI Controller [8086:2922] (rev 02) (prog-if 01 [AHCI 1.0])
- * Subsystem: Intel Corporation 82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA AHCI Controller [8086:2922]
- * Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
- * Status: Cap+ 66MHz+ UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
- * Latency: 0
- * Interrupt: pin B routed to IRQ 222
- * Region 0: I/O ports at d000 [size=8]
- * Region 1: I/O ports at cc00 [size=4]
- * Region 2: I/O ports at c880 [size=8]
- * Region 3: I/O ports at c800 [size=4]
- * Region 4: I/O ports at c480 [size=32]
- * Region 5: Memory at febf9000 (32-bit, non-prefetchable) [size=2K]
- * Capabilities: [80] Message Signalled Interrupts: Mask- 64bit- Count=1/16 Enable+
- * Address: fee0f00c Data: 41d9
- * Capabilities: [70] Power Management version 3
- * Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot+,D3cold-)
- * Status: D0 PME-Enable- DSel=0 DScale=0 PME-
- * Capabilities: [a8] SATA HBA <?>
- * Capabilities: [b0] Vendor Specific Information <?>
- * Kernel driver in use: ahci
- * Kernel modules: ahci
- * 00: 86 80 22 29 07 04 b0 02 02 01 06 01 00 00 00 00
- * 10: 01 d0 00 00 01 cc 00 00 81 c8 00 00 01 c8 00 00
- * 20: 81 c4 00 00 00 90 bf fe 00 00 00 00 86 80 22 29
- * 30: 00 00 00 00 80 00 00 00 00 00 00 00 0f 02 00 00
- * 40: 00 80 00 80 00 00 00 00 00 00 00 00 00 00 00 00
- * 50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * 60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * 70: 01 a8 03 40 08 00 00 00 00 00 00 00 00 00 00 00
- * 80: 05 70 09 00 0c f0 e0 fe d9 41 00 00 00 00 00 00
- * 90: 40 00 0f 82 93 01 00 00 00 00 00 00 00 00 00 00
- * a0: ac 00 00 00 0a 00 12 00 12 b0 10 00 48 00 00 00
- * b0: 09 00 06 20 00 00 00 00 00 00 00 00 00 00 00 00
- * c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
- * f0: 00 00 00 00 00 00 00 00 86 0f 02 00 00 00 00 00
- *
*/
#include <hw/hw.h>
@@ -1155,72 +1114,3 @@ void ahci_reset(void *opaque)
ahci_reset_port(&d->ahci, i);
}
}
-
-static int pci_ahci_init(PCIDevice *dev)
-{
- struct AHCIPCIState *d;
- d = DO_UPCAST(struct AHCIPCIState, card, dev);
-
- pci_config_set_vendor_id(d->card.config, PCI_VENDOR_ID_INTEL);
- pci_config_set_device_id(d->card.config, PCI_DEVICE_ID_INTEL_82801IR);
-
- pci_config_set_class(d->card.config, PCI_CLASS_STORAGE_SATA);
- pci_config_set_revision(d->card.config, 0x02);
- pci_config_set_prog_interface(d->card.config, AHCI_PROGMODE_MAJOR_REV_1);
-
- d->card.config[PCI_CACHE_LINE_SIZE] = 0x08; /* Cache line size */
- d->card.config[PCI_LATENCY_TIMER] = 0x00; /* Latency timer */
- pci_config_set_interrupt_pin(d->card.config, 1);
-
- /* XXX Software should program this register */
- d->card.config[0x90] = 1 << 6; /* Address Map Register - AHCI mode */
-
- qemu_register_reset(ahci_reset, d);
-
- /* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */
- pci_register_bar(&d->card, 5, 0x1000, PCI_BASE_ADDRESS_SPACE_MEMORY,
- ahci_pci_map);
-
- msi_init(dev, 0x50, 1, true, false);
-
- ahci_init(&d->ahci, &dev->qdev);
- d->ahci.irq = d->card.irq[0];
-
- return 0;
-}
-
-static int pci_ahci_uninit(PCIDevice *dev)
-{
- struct AHCIPCIState *d;
- d = DO_UPCAST(struct AHCIPCIState, card, dev);
-
- if (msi_enabled(dev)) {
- msi_uninit(dev);
- }
-
- qemu_unregister_reset(ahci_reset, d);
-
- return 0;
-}
-
-static void pci_ahci_write_config(PCIDevice *pci, uint32_t addr,
- uint32_t val, int len)
-{
- pci_default_write_config(pci, addr, val, len);
- msi_write_config(pci, addr, val, len);
-}
-
-static PCIDeviceInfo ahci_info = {
- .qdev.name = "ahci",
- .qdev.size = sizeof(AHCIPCIState),
- .init = pci_ahci_init,
- .exit = pci_ahci_uninit,
- .config_write = pci_ahci_write_config,
-};
-
-static void ahci_pci_register_devices(void)
-{
- pci_qdev_register(&ahci_info);
-}
-
-device_init(ahci_pci_register_devices)
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
index 9868b73..70cb766 100644
--- a/hw/ide/ich.c
+++ b/hw/ide/ich.c
@@ -1,3 +1,65 @@
+/*
+ * QEMU ICH Emulation
+ *
+ * Copyright (c) 2010 Sebastian Herbszt <herbszt at gmx.de>
+ * Copyright (c) 2010 Alexander Graf <agraf at suse.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * lspci dump of a ICH-9 real device
+ *
+ * 00:1f.2 SATA controller [0106]: Intel Corporation 82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA AHCI Controller [8086:2922] (rev 02) (prog-if 01 [AHCI 1.0])
+ * Subsystem: Intel Corporation 82801IR/IO/IH (ICH9R/DO/DH) 6 port SATA AHCI Controller [8086:2922]
+ * Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx+
+ * Status: Cap+ 66MHz+ UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
+ * Latency: 0
+ * Interrupt: pin B routed to IRQ 222
+ * Region 0: I/O ports at d000 [size=8]
+ * Region 1: I/O ports at cc00 [size=4]
+ * Region 2: I/O ports at c880 [size=8]
+ * Region 3: I/O ports at c800 [size=4]
+ * Region 4: I/O ports at c480 [size=32]
+ * Region 5: Memory at febf9000 (32-bit, non-prefetchable) [size=2K]
+ * Capabilities: [80] Message Signalled Interrupts: Mask- 64bit- Count=1/16 Enable+
+ * Address: fee0f00c Data: 41d9
+ * Capabilities: [70] Power Management version 3
+ * Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot+,D3cold-)
+ * Status: D0 PME-Enable- DSel=0 DScale=0 PME-
+ * Capabilities: [a8] SATA HBA <?>
+ * Capabilities: [b0] Vendor Specific Information <?>
+ * Kernel driver in use: ahci
+ * Kernel modules: ahci
+ * 00: 86 80 22 29 07 04 b0 02 02 01 06 01 00 00 00 00
+ * 10: 01 d0 00 00 01 cc 00 00 81 c8 00 00 01 c8 00 00
+ * 20: 81 c4 00 00 00 90 bf fe 00 00 00 00 86 80 22 29
+ * 30: 00 00 00 00 80 00 00 00 00 00 00 00 0f 02 00 00
+ * 40: 00 80 00 80 00 00 00 00 00 00 00 00 00 00 00 00
+ * 50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * 70: 01 a8 03 40 08 00 00 00 00 00 00 00 00 00 00 00
+ * 80: 05 70 09 00 0c f0 e0 fe d9 41 00 00 00 00 00 00
+ * 90: 40 00 0f 82 93 01 00 00 00 00 00 00 00 00 00 00
+ * a0: ac 00 00 00 0a 00 12 00 12 b0 10 00 48 00 00 00
+ * b0: 09 00 06 20 00 00 00 00 00 00 00 00 00 00 00 00
+ * c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ * f0: 00 00 00 00 00 00 00 00 86 0f 02 00 00 00 00 00
+ *
+ */
+
#include <hw/hw.h>
#include <hw/msi.h>
#include <hw/pc.h>
@@ -11,7 +73,7 @@
#include <hw/ide/pci.h>
#include <hw/ide/ahci.h>
-static int pci_ich9_ahci_initfn(PCIDevice *dev)
+static int pci_ich9_ahci_init(PCIDevice *dev)
{
struct AHCIPCIState *d;
d = DO_UPCAST(struct AHCIPCIState, card, dev);
@@ -44,11 +106,35 @@ static int pci_ich9_ahci_initfn(PCIDevice *dev)
return 0;
}
+static int pci_ich9_uninit(PCIDevice *dev)
+{
+ struct AHCIPCIState *d;
+ d = DO_UPCAST(struct AHCIPCIState, card, dev);
+
+ if (msi_enabled(dev)) {
+ msi_uninit(dev);
+ }
+
+ qemu_unregister_reset(ahci_reset, d);
+
+ return 0;
+}
+
+static void pci_ich9_write_config(PCIDevice *pci, uint32_t addr,
+ uint32_t val, int len)
+{
+ pci_default_write_config(pci, addr, val, len);
+ msi_write_config(pci, addr, val, len);
+}
+
static PCIDeviceInfo ich_ahci_info[] = {
{
.qdev.name = "ich9-ahci",
+ .qdev.alias = "ahci",
.qdev.size = sizeof(AHCIPCIState),
- .init = pci_ich9_ahci_initfn,
+ .init = pci_ich9_ahci_init,
+ .exit = pci_ich9_uninit,
+ .config_write = pci_ich9_write_config,
},{
/* end of list */
}
commit f83a40dcd7c38aef8cb4aa93e1f6f0e21c750992
Author: Alexander Graf <agraf at suse.de>
Date: Tue Feb 1 15:51:27 2011 +0100
ahci: add license header in ahci.h
Due to popular request, this patch adds a license header to ahci.h
Signed-off-by: Alexander Graf <agraf at suse.de>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h
index 63ef785..d65b5e3 100644
--- a/hw/ide/ahci.h
+++ b/hw/ide/ahci.h
@@ -1,3 +1,26 @@
+/*
+ * QEMU AHCI Emulation
+ *
+ * Copyright (c) 2010 qiaochong at loongson.cn
+ * Copyright (c) 2010 Roland Elek <elek.roland at gmail.com>
+ * Copyright (c) 2010 Sebastian Herbszt <herbszt at gmx.de>
+ * Copyright (c) 2010 Alexander Graf <agraf at suse.de>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
#ifndef HW_IDE_AHCI_H
#define HW_IDE_AHCI_H
commit 03c7a6a8e7122b9c12a532577046094a69593116
Author: Sebastian Herbszt <herbszt at gmx.de>
Date: Tue Feb 1 15:51:26 2011 +0100
ahci: split ICH9 from core
There are multiple ahci devices out there. The currently implemented ich-9
is only one of the many. So let's split that one out into a separate file
to stress the difference.
Signed-off-by: Sebastian Herbszt <herbszt at gmx.de>
Signed-off-by: Alexander Graf <agraf at suse.de>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/Makefile.objs b/Makefile.objs
index f1c7bfe..353b1a8 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -244,6 +244,7 @@ hw-obj-$(CONFIG_IDE_CMD646) += ide/cmd646.o
hw-obj-$(CONFIG_IDE_MACIO) += ide/macio.o
hw-obj-$(CONFIG_IDE_VIA) += ide/via.o
hw-obj-$(CONFIG_AHCI) += ide/ahci.o
+hw-obj-$(CONFIG_AHCI) += ide/ich.o
# SCSI layer
hw-obj-$(CONFIG_LSI_SCSI_PCI) += lsi53c895a.o
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 671b4df..28412d0 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -72,6 +72,7 @@
#include "cpu-common.h"
#include "internal.h"
#include <hw/ide/pci.h>
+#include <hw/ide/ahci.h>
/* #define DEBUG_AHCI */
@@ -83,304 +84,6 @@ do { fprintf(stderr, "ahci: %s: [%d] ", __FUNCTION__, port); \
#define DPRINTF(port, fmt, ...) do {} while(0)
#endif
-#define AHCI_PCI_BAR 5
-#define AHCI_MAX_PORTS 32
-#define AHCI_MAX_SG 168 /* hardware max is 64K */
-#define AHCI_DMA_BOUNDARY 0xffffffff
-#define AHCI_USE_CLUSTERING 0
-#define AHCI_MAX_CMDS 32
-#define AHCI_CMD_SZ 32
-#define AHCI_CMD_SLOT_SZ (AHCI_MAX_CMDS * AHCI_CMD_SZ)
-#define AHCI_RX_FIS_SZ 256
-#define AHCI_CMD_TBL_CDB 0x40
-#define AHCI_CMD_TBL_HDR_SZ 0x80
-#define AHCI_CMD_TBL_SZ (AHCI_CMD_TBL_HDR_SZ + (AHCI_MAX_SG * 16))
-#define AHCI_CMD_TBL_AR_SZ (AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS)
-#define AHCI_PORT_PRIV_DMA_SZ (AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ + \
- AHCI_RX_FIS_SZ)
-
-#define AHCI_IRQ_ON_SG (1 << 31)
-#define AHCI_CMD_ATAPI (1 << 5)
-#define AHCI_CMD_WRITE (1 << 6)
-#define AHCI_CMD_PREFETCH (1 << 7)
-#define AHCI_CMD_RESET (1 << 8)
-#define AHCI_CMD_CLR_BUSY (1 << 10)
-
-#define RX_FIS_D2H_REG 0x40 /* offset of D2H Register FIS data */
-#define RX_FIS_SDB 0x58 /* offset of SDB FIS data */
-#define RX_FIS_UNK 0x60 /* offset of Unknown FIS data */
-
-/* global controller registers */
-#define HOST_CAP 0x00 /* host capabilities */
-#define HOST_CTL 0x04 /* global host control */
-#define HOST_IRQ_STAT 0x08 /* interrupt status */
-#define HOST_PORTS_IMPL 0x0c /* bitmap of implemented ports */
-#define HOST_VERSION 0x10 /* AHCI spec. version compliancy */
-
-/* HOST_CTL bits */
-#define HOST_CTL_RESET (1 << 0) /* reset controller; self-clear */
-#define HOST_CTL_IRQ_EN (1 << 1) /* global IRQ enable */
-#define HOST_CTL_AHCI_EN (1 << 31) /* AHCI enabled */
-
-/* HOST_CAP bits */
-#define HOST_CAP_SSC (1 << 14) /* Slumber capable */
-#define HOST_CAP_AHCI (1 << 18) /* AHCI only */
-#define HOST_CAP_CLO (1 << 24) /* Command List Override support */
-#define HOST_CAP_SSS (1 << 27) /* Staggered Spin-up */
-#define HOST_CAP_NCQ (1 << 30) /* Native Command Queueing */
-#define HOST_CAP_64 (1 << 31) /* PCI DAC (64-bit DMA) support */
-
-/* registers for each SATA port */
-#define PORT_LST_ADDR 0x00 /* command list DMA addr */
-#define PORT_LST_ADDR_HI 0x04 /* command list DMA addr hi */
-#define PORT_FIS_ADDR 0x08 /* FIS rx buf addr */
-#define PORT_FIS_ADDR_HI 0x0c /* FIS rx buf addr hi */
-#define PORT_IRQ_STAT 0x10 /* interrupt status */
-#define PORT_IRQ_MASK 0x14 /* interrupt enable/disable mask */
-#define PORT_CMD 0x18 /* port command */
-#define PORT_TFDATA 0x20 /* taskfile data */
-#define PORT_SIG 0x24 /* device TF signature */
-#define PORT_SCR_STAT 0x28 /* SATA phy register: SStatus */
-#define PORT_SCR_CTL 0x2c /* SATA phy register: SControl */
-#define PORT_SCR_ERR 0x30 /* SATA phy register: SError */
-#define PORT_SCR_ACT 0x34 /* SATA phy register: SActive */
-#define PORT_CMD_ISSUE 0x38 /* command issue */
-#define PORT_RESERVED 0x3c /* reserved */
-
-/* PORT_IRQ_{STAT,MASK} bits */
-#define PORT_IRQ_COLD_PRES (1 << 31) /* cold presence detect */
-#define PORT_IRQ_TF_ERR (1 << 30) /* task file error */
-#define PORT_IRQ_HBUS_ERR (1 << 29) /* host bus fatal error */
-#define PORT_IRQ_HBUS_DATA_ERR (1 << 28) /* host bus data error */
-#define PORT_IRQ_IF_ERR (1 << 27) /* interface fatal error */
-#define PORT_IRQ_IF_NONFATAL (1 << 26) /* interface non-fatal error */
-#define PORT_IRQ_OVERFLOW (1 << 24) /* xfer exhausted available S/G */
-#define PORT_IRQ_BAD_PMP (1 << 23) /* incorrect port multiplier */
-
-#define PORT_IRQ_PHYRDY (1 << 22) /* PhyRdy changed */
-#define PORT_IRQ_DEV_ILCK (1 << 7) /* device interlock */
-#define PORT_IRQ_CONNECT (1 << 6) /* port connect change status */
-#define PORT_IRQ_SG_DONE (1 << 5) /* descriptor processed */
-#define PORT_IRQ_UNK_FIS (1 << 4) /* unknown FIS rx'd */
-#define PORT_IRQ_SDB_FIS (1 << 3) /* Set Device Bits FIS rx'd */
-#define PORT_IRQ_DMAS_FIS (1 << 2) /* DMA Setup FIS rx'd */
-#define PORT_IRQ_PIOS_FIS (1 << 1) /* PIO Setup FIS rx'd */
-#define PORT_IRQ_D2H_REG_FIS (1 << 0) /* D2H Register FIS rx'd */
-
-#define PORT_IRQ_FREEZE (PORT_IRQ_HBUS_ERR | PORT_IRQ_IF_ERR | \
- PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY | \
- PORT_IRQ_UNK_FIS)
-#define PORT_IRQ_ERROR (PORT_IRQ_FREEZE | PORT_IRQ_TF_ERR | \
- PORT_IRQ_HBUS_DATA_ERR)
-#define DEF_PORT_IRQ (PORT_IRQ_ERROR | PORT_IRQ_SG_DONE | \
- PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS | \
- PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS)
-
-/* PORT_CMD bits */
-#define PORT_CMD_ATAPI (1 << 24) /* Device is ATAPI */
-#define PORT_CMD_LIST_ON (1 << 15) /* cmd list DMA engine running */
-#define PORT_CMD_FIS_ON (1 << 14) /* FIS DMA engine running */
-#define PORT_CMD_FIS_RX (1 << 4) /* Enable FIS receive DMA engine */
-#define PORT_CMD_CLO (1 << 3) /* Command list override */
-#define PORT_CMD_POWER_ON (1 << 2) /* Power up device */
-#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_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 */
-
-#define PORT_IRQ_STAT_DHRS (1 << 0) /* Device to Host Register FIS */
-#define PORT_IRQ_STAT_PSS (1 << 1) /* PIO Setup FIS */
-#define PORT_IRQ_STAT_DSS (1 << 2) /* DMA Setup FIS */
-#define PORT_IRQ_STAT_SDBS (1 << 3) /* Set Device Bits */
-#define PORT_IRQ_STAT_UFS (1 << 4) /* Unknown FIS */
-#define PORT_IRQ_STAT_DPS (1 << 5) /* Descriptor Processed */
-#define PORT_IRQ_STAT_PCS (1 << 6) /* Port Connect Change Status */
-#define PORT_IRQ_STAT_DMPS (1 << 7) /* Device Mechanical Presence
- Status */
-#define PORT_IRQ_STAT_PRCS (1 << 22) /* File Ready Status */
-#define PORT_IRQ_STAT_IPMS (1 << 23) /* Incorrect Port Multiplier
- Status */
-#define PORT_IRQ_STAT_OFS (1 << 24) /* Overflow Status */
-#define PORT_IRQ_STAT_INFS (1 << 26) /* Interface Non-Fatal Error
- Status */
-#define PORT_IRQ_STAT_IFS (1 << 27) /* Interface Fatal Error */
-#define PORT_IRQ_STAT_HBDS (1 << 28) /* Host Bus Data Error Status */
-#define PORT_IRQ_STAT_HBFS (1 << 29) /* Host Bus Fatal Error Status */
-#define PORT_IRQ_STAT_TFES (1 << 30) /* Task File Error Status */
-#define PORT_IRQ_STAT_CPDS (1 << 31) /* Code Port Detect Status */
-
-/* ap->flags bits */
-#define AHCI_FLAG_NO_NCQ (1 << 24)
-#define AHCI_FLAG_IGN_IRQ_IF_ERR (1 << 25) /* ignore IRQ_IF_ERR */
-#define AHCI_FLAG_HONOR_PI (1 << 26) /* honor PORTS_IMPL */
-#define AHCI_FLAG_IGN_SERR_INTERNAL (1 << 27) /* ignore SERR_INTERNAL */
-#define AHCI_FLAG_32BIT_ONLY (1 << 28) /* force 32bit */
-
-#define ATA_SRST (1 << 2) /* software reset */
-
-#define STATE_RUN 0
-#define STATE_RESET 1
-
-#define SATA_SCR_SSTATUS_DET_NODEV 0x0
-#define SATA_SCR_SSTATUS_DET_DEV_PRESENT_PHY_UP 0x3
-
-#define SATA_SCR_SSTATUS_SPD_NODEV 0x00
-#define SATA_SCR_SSTATUS_SPD_GEN1 0x10
-
-#define SATA_SCR_SSTATUS_IPM_NODEV 0x000
-#define SATA_SCR_SSTATUS_IPM_ACTIVE 0X100
-
-#define AHCI_SCR_SCTL_DET 0xf
-
-#define SATA_FIS_TYPE_REGISTER_H2D 0x27
-#define SATA_FIS_REG_H2D_UPDATE_COMMAND_REGISTER 0x80
-
-#define AHCI_CMD_HDR_CMD_FIS_LEN 0x1f
-#define AHCI_CMD_HDR_PRDT_LEN 16
-
-#define SATA_SIGNATURE_CDROM 0xeb140000
-#define SATA_SIGNATURE_DISK 0x00000101
-
-#define AHCI_GENERIC_HOST_CONTROL_REGS_MAX_ADDR 0x20
- /* Shouldn't this be 0x2c? */
-
-#define SATA_PORTS 4
-
-#define AHCI_PORT_REGS_START_ADDR 0x100
-#define AHCI_PORT_REGS_END_ADDR (AHCI_PORT_REGS_START_ADDR + SATA_PORTS * 0x80)
-#define AHCI_PORT_ADDR_OFFSET_MASK 0x7f
-
-#define AHCI_NUM_COMMAND_SLOTS 31
-#define AHCI_SUPPORTED_SPEED 20
-#define AHCI_SUPPORTED_SPEED_GEN1 1
-#define AHCI_VERSION_1_0 0x10000
-
-#define AHCI_PROGMODE_MAJOR_REV_1 1
-
-#define AHCI_COMMAND_TABLE_ACMD 0x40
-
-#define IDE_FEATURE_DMA 1
-
-#define READ_FPDMA_QUEUED 0x60
-#define WRITE_FPDMA_QUEUED 0x61
-
-#define RES_FIS_DSFIS 0x00
-#define RES_FIS_PSFIS 0x20
-#define RES_FIS_RFIS 0x40
-#define RES_FIS_SDBFIS 0x58
-#define RES_FIS_UFIS 0x60
-
-typedef struct AHCIControlRegs {
- uint32_t cap;
- uint32_t ghc;
- uint32_t irqstatus;
- uint32_t impl;
- uint32_t version;
-} AHCIControlRegs;
-
-typedef struct AHCIPortRegs {
- uint32_t lst_addr;
- uint32_t lst_addr_hi;
- uint32_t fis_addr;
- uint32_t fis_addr_hi;
- uint32_t irq_stat;
- uint32_t irq_mask;
- uint32_t cmd;
- uint32_t unused0;
- uint32_t tfdata;
- uint32_t sig;
- uint32_t scr_stat;
- uint32_t scr_ctl;
- uint32_t scr_err;
- uint32_t scr_act;
- uint32_t cmd_issue;
- uint32_t reserved;
-} AHCIPortRegs;
-
-typedef struct AHCICmdHdr {
- uint32_t opts;
- uint32_t status;
- uint64_t tbl_addr;
- uint32_t reserved[4];
-} __attribute__ ((packed)) AHCICmdHdr;
-
-typedef struct AHCI_SG {
- uint64_t addr;
- uint32_t reserved;
- uint32_t flags_size;
-} __attribute__ ((packed)) AHCI_SG;
-
-typedef struct AHCIDevice AHCIDevice;
-
-typedef struct NCQTransferState {
- AHCIDevice *drive;
- BlockDriverAIOCB *aiocb;
- QEMUSGList sglist;
- int is_read;
- uint16_t sector_count;
- uint64_t lba;
- uint8_t tag;
- int slot;
- int used;
-} NCQTransferState;
-
-struct AHCIDevice {
- IDEDMA dma;
- IDEBus port;
- int port_no;
- uint32_t port_state;
- uint32_t finished;
- AHCIPortRegs port_regs;
- struct AHCIState *hba;
- QEMUBH *check_bh;
- uint8_t *lst;
- uint8_t *res_fis;
- int dma_status;
- int done_atapi_packet;
- int busy_slot;
- BlockDriverCompletionFunc *dma_cb;
- AHCICmdHdr *cur_cmd;
- NCQTransferState ncq_tfs[AHCI_MAX_CMDS];
-};
-
-typedef struct AHCIState {
- AHCIDevice dev[SATA_PORTS];
- AHCIControlRegs control_regs;
- int mem;
- qemu_irq irq;
-} AHCIState;
-
-typedef struct AHCIPCIState {
- PCIDevice card;
- AHCIState ahci;
-} AHCIPCIState;
-
-typedef struct NCQFrame {
- uint8_t fis_type;
- uint8_t c;
- uint8_t command;
- uint8_t sector_count_low;
- uint8_t lba0;
- uint8_t lba1;
- uint8_t lba2;
- uint8_t fua;
- uint8_t lba3;
- uint8_t lba4;
- uint8_t lba5;
- uint8_t sector_count_high;
- uint8_t tag;
- uint8_t reserved5;
- uint8_t reserved6;
- uint8_t control;
- uint8_t reserved7;
- uint8_t reserved8;
- uint8_t reserved9;
- uint8_t reserved10;
-} __attribute__ ((packed)) NCQFrame;
-
static void check_cmd(AHCIState *s, int port);
static int handle_cmd(AHCIState *s,int port,int slot);
static void ahci_reset_port(AHCIState *s, int port);
@@ -1410,7 +1113,7 @@ static const IDEDMAOps ahci_dma_ops = {
.reset = ahci_dma_reset,
};
-static void ahci_init(AHCIState *s, DeviceState *qdev)
+void ahci_init(AHCIState *s, DeviceState *qdev)
{
qemu_irq *irqs;
int i;
@@ -1434,7 +1137,7 @@ static void ahci_init(AHCIState *s, DeviceState *qdev)
}
}
-static void ahci_pci_map(PCIDevice *pci_dev, int region_num,
+void ahci_pci_map(PCIDevice *pci_dev, int region_num,
pcibus_t addr, pcibus_t size, int type)
{
struct AHCIPCIState *d = (struct AHCIPCIState *)pci_dev;
@@ -1443,7 +1146,7 @@ static void ahci_pci_map(PCIDevice *pci_dev, int region_num,
cpu_register_physical_memory(addr, size, s->mem);
}
-static void ahci_reset(void *opaque)
+void ahci_reset(void *opaque)
{
struct AHCIPCIState *d = opaque;
int i;
diff --git a/hw/ide/ahci.h b/hw/ide/ahci.h
new file mode 100644
index 0000000..63ef785
--- /dev/null
+++ b/hw/ide/ahci.h
@@ -0,0 +1,309 @@
+#ifndef HW_IDE_AHCI_H
+#define HW_IDE_AHCI_H
+
+#define AHCI_PCI_BAR 5
+#define AHCI_MAX_PORTS 32
+#define AHCI_MAX_SG 168 /* hardware max is 64K */
+#define AHCI_DMA_BOUNDARY 0xffffffff
+#define AHCI_USE_CLUSTERING 0
+#define AHCI_MAX_CMDS 32
+#define AHCI_CMD_SZ 32
+#define AHCI_CMD_SLOT_SZ (AHCI_MAX_CMDS * AHCI_CMD_SZ)
+#define AHCI_RX_FIS_SZ 256
+#define AHCI_CMD_TBL_CDB 0x40
+#define AHCI_CMD_TBL_HDR_SZ 0x80
+#define AHCI_CMD_TBL_SZ (AHCI_CMD_TBL_HDR_SZ + (AHCI_MAX_SG * 16))
+#define AHCI_CMD_TBL_AR_SZ (AHCI_CMD_TBL_SZ * AHCI_MAX_CMDS)
+#define AHCI_PORT_PRIV_DMA_SZ (AHCI_CMD_SLOT_SZ + AHCI_CMD_TBL_AR_SZ + \
+ AHCI_RX_FIS_SZ)
+
+#define AHCI_IRQ_ON_SG (1 << 31)
+#define AHCI_CMD_ATAPI (1 << 5)
+#define AHCI_CMD_WRITE (1 << 6)
+#define AHCI_CMD_PREFETCH (1 << 7)
+#define AHCI_CMD_RESET (1 << 8)
+#define AHCI_CMD_CLR_BUSY (1 << 10)
+
+#define RX_FIS_D2H_REG 0x40 /* offset of D2H Register FIS data */
+#define RX_FIS_SDB 0x58 /* offset of SDB FIS data */
+#define RX_FIS_UNK 0x60 /* offset of Unknown FIS data */
+
+/* global controller registers */
+#define HOST_CAP 0x00 /* host capabilities */
+#define HOST_CTL 0x04 /* global host control */
+#define HOST_IRQ_STAT 0x08 /* interrupt status */
+#define HOST_PORTS_IMPL 0x0c /* bitmap of implemented ports */
+#define HOST_VERSION 0x10 /* AHCI spec. version compliancy */
+
+/* HOST_CTL bits */
+#define HOST_CTL_RESET (1 << 0) /* reset controller; self-clear */
+#define HOST_CTL_IRQ_EN (1 << 1) /* global IRQ enable */
+#define HOST_CTL_AHCI_EN (1 << 31) /* AHCI enabled */
+
+/* HOST_CAP bits */
+#define HOST_CAP_SSC (1 << 14) /* Slumber capable */
+#define HOST_CAP_AHCI (1 << 18) /* AHCI only */
+#define HOST_CAP_CLO (1 << 24) /* Command List Override support */
+#define HOST_CAP_SSS (1 << 27) /* Staggered Spin-up */
+#define HOST_CAP_NCQ (1 << 30) /* Native Command Queueing */
+#define HOST_CAP_64 (1 << 31) /* PCI DAC (64-bit DMA) support */
+
+/* registers for each SATA port */
+#define PORT_LST_ADDR 0x00 /* command list DMA addr */
+#define PORT_LST_ADDR_HI 0x04 /* command list DMA addr hi */
+#define PORT_FIS_ADDR 0x08 /* FIS rx buf addr */
+#define PORT_FIS_ADDR_HI 0x0c /* FIS rx buf addr hi */
+#define PORT_IRQ_STAT 0x10 /* interrupt status */
+#define PORT_IRQ_MASK 0x14 /* interrupt enable/disable mask */
+#define PORT_CMD 0x18 /* port command */
+#define PORT_TFDATA 0x20 /* taskfile data */
+#define PORT_SIG 0x24 /* device TF signature */
+#define PORT_SCR_STAT 0x28 /* SATA phy register: SStatus */
+#define PORT_SCR_CTL 0x2c /* SATA phy register: SControl */
+#define PORT_SCR_ERR 0x30 /* SATA phy register: SError */
+#define PORT_SCR_ACT 0x34 /* SATA phy register: SActive */
+#define PORT_CMD_ISSUE 0x38 /* command issue */
+#define PORT_RESERVED 0x3c /* reserved */
+
+/* PORT_IRQ_{STAT,MASK} bits */
+#define PORT_IRQ_COLD_PRES (1 << 31) /* cold presence detect */
+#define PORT_IRQ_TF_ERR (1 << 30) /* task file error */
+#define PORT_IRQ_HBUS_ERR (1 << 29) /* host bus fatal error */
+#define PORT_IRQ_HBUS_DATA_ERR (1 << 28) /* host bus data error */
+#define PORT_IRQ_IF_ERR (1 << 27) /* interface fatal error */
+#define PORT_IRQ_IF_NONFATAL (1 << 26) /* interface non-fatal error */
+#define PORT_IRQ_OVERFLOW (1 << 24) /* xfer exhausted available S/G */
+#define PORT_IRQ_BAD_PMP (1 << 23) /* incorrect port multiplier */
+
+#define PORT_IRQ_PHYRDY (1 << 22) /* PhyRdy changed */
+#define PORT_IRQ_DEV_ILCK (1 << 7) /* device interlock */
+#define PORT_IRQ_CONNECT (1 << 6) /* port connect change status */
+#define PORT_IRQ_SG_DONE (1 << 5) /* descriptor processed */
+#define PORT_IRQ_UNK_FIS (1 << 4) /* unknown FIS rx'd */
+#define PORT_IRQ_SDB_FIS (1 << 3) /* Set Device Bits FIS rx'd */
+#define PORT_IRQ_DMAS_FIS (1 << 2) /* DMA Setup FIS rx'd */
+#define PORT_IRQ_PIOS_FIS (1 << 1) /* PIO Setup FIS rx'd */
+#define PORT_IRQ_D2H_REG_FIS (1 << 0) /* D2H Register FIS rx'd */
+
+#define PORT_IRQ_FREEZE (PORT_IRQ_HBUS_ERR | PORT_IRQ_IF_ERR | \
+ PORT_IRQ_CONNECT | PORT_IRQ_PHYRDY | \
+ PORT_IRQ_UNK_FIS)
+#define PORT_IRQ_ERROR (PORT_IRQ_FREEZE | PORT_IRQ_TF_ERR | \
+ PORT_IRQ_HBUS_DATA_ERR)
+#define DEF_PORT_IRQ (PORT_IRQ_ERROR | PORT_IRQ_SG_DONE | \
+ PORT_IRQ_SDB_FIS | PORT_IRQ_DMAS_FIS | \
+ PORT_IRQ_PIOS_FIS | PORT_IRQ_D2H_REG_FIS)
+
+/* PORT_CMD bits */
+#define PORT_CMD_ATAPI (1 << 24) /* Device is ATAPI */
+#define PORT_CMD_LIST_ON (1 << 15) /* cmd list DMA engine running */
+#define PORT_CMD_FIS_ON (1 << 14) /* FIS DMA engine running */
+#define PORT_CMD_FIS_RX (1 << 4) /* Enable FIS receive DMA engine */
+#define PORT_CMD_CLO (1 << 3) /* Command list override */
+#define PORT_CMD_POWER_ON (1 << 2) /* Power up device */
+#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_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 */
+
+#define PORT_IRQ_STAT_DHRS (1 << 0) /* Device to Host Register FIS */
+#define PORT_IRQ_STAT_PSS (1 << 1) /* PIO Setup FIS */
+#define PORT_IRQ_STAT_DSS (1 << 2) /* DMA Setup FIS */
+#define PORT_IRQ_STAT_SDBS (1 << 3) /* Set Device Bits */
+#define PORT_IRQ_STAT_UFS (1 << 4) /* Unknown FIS */
+#define PORT_IRQ_STAT_DPS (1 << 5) /* Descriptor Processed */
+#define PORT_IRQ_STAT_PCS (1 << 6) /* Port Connect Change Status */
+#define PORT_IRQ_STAT_DMPS (1 << 7) /* Device Mechanical Presence
+ Status */
+#define PORT_IRQ_STAT_PRCS (1 << 22) /* File Ready Status */
+#define PORT_IRQ_STAT_IPMS (1 << 23) /* Incorrect Port Multiplier
+ Status */
+#define PORT_IRQ_STAT_OFS (1 << 24) /* Overflow Status */
+#define PORT_IRQ_STAT_INFS (1 << 26) /* Interface Non-Fatal Error
+ Status */
+#define PORT_IRQ_STAT_IFS (1 << 27) /* Interface Fatal Error */
+#define PORT_IRQ_STAT_HBDS (1 << 28) /* Host Bus Data Error Status */
+#define PORT_IRQ_STAT_HBFS (1 << 29) /* Host Bus Fatal Error Status */
+#define PORT_IRQ_STAT_TFES (1 << 30) /* Task File Error Status */
+#define PORT_IRQ_STAT_CPDS (1 << 31) /* Code Port Detect Status */
+
+/* ap->flags bits */
+#define AHCI_FLAG_NO_NCQ (1 << 24)
+#define AHCI_FLAG_IGN_IRQ_IF_ERR (1 << 25) /* ignore IRQ_IF_ERR */
+#define AHCI_FLAG_HONOR_PI (1 << 26) /* honor PORTS_IMPL */
+#define AHCI_FLAG_IGN_SERR_INTERNAL (1 << 27) /* ignore SERR_INTERNAL */
+#define AHCI_FLAG_32BIT_ONLY (1 << 28) /* force 32bit */
+
+#define ATA_SRST (1 << 2) /* software reset */
+
+#define STATE_RUN 0
+#define STATE_RESET 1
+
+#define SATA_SCR_SSTATUS_DET_NODEV 0x0
+#define SATA_SCR_SSTATUS_DET_DEV_PRESENT_PHY_UP 0x3
+
+#define SATA_SCR_SSTATUS_SPD_NODEV 0x00
+#define SATA_SCR_SSTATUS_SPD_GEN1 0x10
+
+#define SATA_SCR_SSTATUS_IPM_NODEV 0x000
+#define SATA_SCR_SSTATUS_IPM_ACTIVE 0X100
+
+#define AHCI_SCR_SCTL_DET 0xf
+
+#define SATA_FIS_TYPE_REGISTER_H2D 0x27
+#define SATA_FIS_REG_H2D_UPDATE_COMMAND_REGISTER 0x80
+
+#define AHCI_CMD_HDR_CMD_FIS_LEN 0x1f
+#define AHCI_CMD_HDR_PRDT_LEN 16
+
+#define SATA_SIGNATURE_CDROM 0xeb140000
+#define SATA_SIGNATURE_DISK 0x00000101
+
+#define AHCI_GENERIC_HOST_CONTROL_REGS_MAX_ADDR 0x20
+ /* Shouldn't this be 0x2c? */
+
+#define SATA_PORTS 4
+
+#define AHCI_PORT_REGS_START_ADDR 0x100
+#define AHCI_PORT_REGS_END_ADDR (AHCI_PORT_REGS_START_ADDR + SATA_PORTS * 0x80)
+#define AHCI_PORT_ADDR_OFFSET_MASK 0x7f
+
+#define AHCI_NUM_COMMAND_SLOTS 31
+#define AHCI_SUPPORTED_SPEED 20
+#define AHCI_SUPPORTED_SPEED_GEN1 1
+#define AHCI_VERSION_1_0 0x10000
+
+#define AHCI_PROGMODE_MAJOR_REV_1 1
+
+#define AHCI_COMMAND_TABLE_ACMD 0x40
+
+#define IDE_FEATURE_DMA 1
+
+#define READ_FPDMA_QUEUED 0x60
+#define WRITE_FPDMA_QUEUED 0x61
+
+#define RES_FIS_DSFIS 0x00
+#define RES_FIS_PSFIS 0x20
+#define RES_FIS_RFIS 0x40
+#define RES_FIS_SDBFIS 0x58
+#define RES_FIS_UFIS 0x60
+
+typedef struct AHCIControlRegs {
+ uint32_t cap;
+ uint32_t ghc;
+ uint32_t irqstatus;
+ uint32_t impl;
+ uint32_t version;
+} AHCIControlRegs;
+
+typedef struct AHCIPortRegs {
+ uint32_t lst_addr;
+ uint32_t lst_addr_hi;
+ uint32_t fis_addr;
+ uint32_t fis_addr_hi;
+ uint32_t irq_stat;
+ uint32_t irq_mask;
+ uint32_t cmd;
+ uint32_t unused0;
+ uint32_t tfdata;
+ uint32_t sig;
+ uint32_t scr_stat;
+ uint32_t scr_ctl;
+ uint32_t scr_err;
+ uint32_t scr_act;
+ uint32_t cmd_issue;
+ uint32_t reserved;
+} AHCIPortRegs;
+
+typedef struct AHCICmdHdr {
+ uint32_t opts;
+ uint32_t status;
+ uint64_t tbl_addr;
+ uint32_t reserved[4];
+} __attribute__ ((packed)) AHCICmdHdr;
+
+typedef struct AHCI_SG {
+ uint64_t addr;
+ uint32_t reserved;
+ uint32_t flags_size;
+} __attribute__ ((packed)) AHCI_SG;
+
+typedef struct AHCIDevice AHCIDevice;
+
+typedef struct NCQTransferState {
+ AHCIDevice *drive;
+ BlockDriverAIOCB *aiocb;
+ QEMUSGList sglist;
+ int is_read;
+ uint16_t sector_count;
+ uint64_t lba;
+ uint8_t tag;
+ int slot;
+ int used;
+} NCQTransferState;
+
+struct AHCIDevice {
+ IDEDMA dma;
+ IDEBus port;
+ int port_no;
+ uint32_t port_state;
+ uint32_t finished;
+ AHCIPortRegs port_regs;
+ struct AHCIState *hba;
+ QEMUBH *check_bh;
+ uint8_t *lst;
+ uint8_t *res_fis;
+ int dma_status;
+ int done_atapi_packet;
+ int busy_slot;
+ BlockDriverCompletionFunc *dma_cb;
+ AHCICmdHdr *cur_cmd;
+ NCQTransferState ncq_tfs[AHCI_MAX_CMDS];
+};
+
+typedef struct AHCIState {
+ AHCIDevice dev[SATA_PORTS];
+ AHCIControlRegs control_regs;
+ int mem;
+ qemu_irq irq;
+} AHCIState;
+
+typedef struct AHCIPCIState {
+ PCIDevice card;
+ AHCIState ahci;
+} AHCIPCIState;
+
+typedef struct NCQFrame {
+ uint8_t fis_type;
+ uint8_t c;
+ uint8_t command;
+ uint8_t sector_count_low;
+ uint8_t lba0;
+ uint8_t lba1;
+ uint8_t lba2;
+ uint8_t fua;
+ uint8_t lba3;
+ uint8_t lba4;
+ uint8_t lba5;
+ uint8_t sector_count_high;
+ uint8_t tag;
+ uint8_t reserved5;
+ uint8_t reserved6;
+ uint8_t control;
+ uint8_t reserved7;
+ uint8_t reserved8;
+ uint8_t reserved9;
+ uint8_t reserved10;
+} __attribute__ ((packed)) NCQFrame;
+
+void ahci_init(AHCIState *s, DeviceState *qdev);
+
+void ahci_pci_map(PCIDevice *pci_dev, int region_num,
+ pcibus_t addr, pcibus_t size, int type);
+
+void ahci_reset(void *opaque);
+
+#endif /* HW_IDE_AHCI_H */
diff --git a/hw/ide/ich.c b/hw/ide/ich.c
new file mode 100644
index 0000000..9868b73
--- /dev/null
+++ b/hw/ide/ich.c
@@ -0,0 +1,61 @@
+#include <hw/hw.h>
+#include <hw/msi.h>
+#include <hw/pc.h>
+#include <hw/pci.h>
+#include <hw/isa.h>
+#include "block.h"
+#include "block_int.h"
+#include "sysemu.h"
+#include "dma.h"
+
+#include <hw/ide/pci.h>
+#include <hw/ide/ahci.h>
+
+static int pci_ich9_ahci_initfn(PCIDevice *dev)
+{
+ struct AHCIPCIState *d;
+ d = DO_UPCAST(struct AHCIPCIState, card, dev);
+
+ pci_config_set_vendor_id(d->card.config, PCI_VENDOR_ID_INTEL);
+ pci_config_set_device_id(d->card.config, PCI_DEVICE_ID_INTEL_82801IR);
+
+ pci_config_set_class(d->card.config, PCI_CLASS_STORAGE_SATA);
+ pci_config_set_revision(d->card.config, 0x02);
+ pci_config_set_prog_interface(d->card.config, AHCI_PROGMODE_MAJOR_REV_1);
+
+ d->card.config[PCI_CACHE_LINE_SIZE] = 0x08; /* Cache line size */
+ d->card.config[PCI_LATENCY_TIMER] = 0x00; /* Latency timer */
+ pci_config_set_interrupt_pin(d->card.config, 1);
+
+ /* XXX Software should program this register */
+ d->card.config[0x90] = 1 << 6; /* Address Map Register - AHCI mode */
+
+ qemu_register_reset(ahci_reset, d);
+
+ /* XXX BAR size should be 1k, but that breaks, so bump it to 4k for now */
+ pci_register_bar(&d->card, 5, 0x1000, PCI_BASE_ADDRESS_SPACE_MEMORY,
+ ahci_pci_map);
+
+ msi_init(dev, 0x50, 1, true, false);
+
+ ahci_init(&d->ahci, &dev->qdev);
+ d->ahci.irq = d->card.irq[0];
+
+ return 0;
+}
+
+static PCIDeviceInfo ich_ahci_info[] = {
+ {
+ .qdev.name = "ich9-ahci",
+ .qdev.size = sizeof(AHCIPCIState),
+ .init = pci_ich9_ahci_initfn,
+ },{
+ /* end of list */
+ }
+};
+
+static void ich_ahci_register(void)
+{
+ pci_qdev_register_many(ich_ahci_info);
+}
+device_init(ich_ahci_register);
commit 4f3669ea5bd73ade0dce5f1155cb9ad9788fd54c
Author: Stefan Weil <weil at mail.berlios.de>
Date: Fri Feb 4 21:01:16 2011 +0100
block/vdi: Fix wrong size in conditionally used memset, memcmp
Error report from cppcheck:
block/vdi.c:122: error: Using sizeof for array given as function argument returns the size of pointer.
block/vdi.c:128: error: Using sizeof for array given as function argument returns the size of pointer.
Fix both by setting the correct size.
The buggy code is only used when QEMU is build without uuid support.
The bug is not critical, so there is no urgent need to apply it to
old versions of QEMU.
Cc: Kevin Wolf <kwolf at redhat.com>
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block/vdi.c b/block/vdi.c
index ab8f70f..116b25b 100644
--- a/block/vdi.c
+++ b/block/vdi.c
@@ -119,13 +119,13 @@ void uuid_unparse(const uuid_t uu, char *out);
#if !defined(CONFIG_UUID)
void uuid_generate(uuid_t out)
{
- memset(out, 0, sizeof(out));
+ memset(out, 0, sizeof(uuid_t));
}
int uuid_is_null(const uuid_t uu)
{
uuid_t null_uuid = { 0 };
- return memcmp(uu, null_uuid, sizeof(uu)) == 0;
+ return memcmp(uu, null_uuid, sizeof(uuid_t)) == 0;
}
void uuid_unparse(const uuid_t uu, char *out)
commit 42af9c30ea9a963ce604ac96230fde2f987634db
Author: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
Date: Mon Feb 7 16:04:04 2011 +0900
Documentation: add Sheepdog disk images
Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/qemu-doc.texi b/qemu-doc.texi
index 22a8663..86e017c 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -407,6 +407,7 @@ snapshots.
* host_drives:: Using host drives
* disk_images_fat_images:: Virtual FAT disk images
* disk_images_nbd:: NBD access
+* disk_images_sheepdog:: Sheepdog disk images
@end menu
@node disk_images_quickstart
@@ -630,6 +631,57 @@ qemu -cdrom nbd:localhost:exportname=debian-500-ppc-netinst
qemu -cdrom nbd:localhost:exportname=openSUSE-11.1-ppc-netinst
@end example
+ at node disk_images_sheepdog
+ at subsection Sheepdog disk images
+
+Sheepdog is a distributed storage system for QEMU. It provides highly
+available block level storage volumes that can be attached to
+QEMU-based virtual machines.
+
+You can create a Sheepdog disk image with the command:
+ at example
+qemu-img create sheepdog:@var{image} @var{size}
+ at end example
+where @var{image} is the Sheepdog image name and @var{size} is its
+size.
+
+To import the existing @var{filename} to Sheepdog, you can use a
+convert command.
+ at example
+qemu-img convert @var{filename} sheepdog:@var{image}
+ at end example
+
+You can boot from the Sheepdog disk image with the command:
+ at example
+qemu sheepdog:@var{image}
+ at end example
+
+You can also create a snapshot of the Sheepdog image like qcow2.
+ at example
+qemu-img snapshot -c @var{tag} sheepdog:@var{image}
+ at end example
+where @var{tag} is a tag name of the newly created snapshot.
+
+To boot from the Sheepdog snapshot, specify the tag name of the
+snapshot.
+ at example
+qemu sheepdog:@var{image}:@var{tag}
+ at end example
+
+You can create a cloned image from the existing snapshot.
+ at example
+qemu-img create -b sheepdog:@var{base}:@var{tag} sheepdog:@var{image}
+ at end example
+where @var{base} is a image name of the source snapshot and @var{tag}
+is its tag name.
+
+If the Sheepdog daemon doesn't run on the local host, you need to
+specify one of the Sheepdog servers to connect to.
+ at example
+qemu-img create sheepdog:@var{hostname}:@var{port}:@var{image} @var{size}
+qemu sheepdog:@var{hostname}:@var{port}:@var{image}
+ at end example
+
@node pcsys_network
@section Network emulation
commit e1a7107f2d92af646ec37b74d074dc150e688559
Author: Kevin Wolf <kwolf at redhat.com>
Date: Thu Jan 27 16:46:01 2011 +0100
qcow2: Really use cache=unsafe for image creation
For cache=unsafe we also need to set BDRV_O_CACHE_WB, otherwise we have some
strange unsafe writethrough mode.
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/block/qcow2.c b/block/qcow2.c
index dbe4fdd..a1773e4 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -975,7 +975,8 @@ static int qcow2_create2(const char *filename, int64_t total_size,
*/
BlockDriver* drv = bdrv_find_format("qcow2");
assert(drv != NULL);
- ret = bdrv_open(bs, filename, BDRV_O_RDWR | BDRV_O_NO_FLUSH, drv);
+ ret = bdrv_open(bs, filename,
+ BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_FLUSH, drv);
if (ret < 0) {
goto out;
}
commit ad36ce8ba95a756ef558579c6e9ecedfae4dfd0b
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sat Feb 5 13:18:20 2011 +0000
checkpatch.pl: don't complain about old lines with tabs
Don't complain when the patch includes lines with tabs
only in the hunk's untouched context.
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 4fa06c0..075b614 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -1495,7 +1495,7 @@ sub process {
next if ($realfile !~ /\.(h|c|pl)$/);
# in QEMU, no tabs are allowed
- if ($rawline =~ /\t/) {
+ if ($rawline =~ /^\+.*\t/) {
my $herevet = "$here\n" . cat_vet($rawline) . "\n";
ERROR("code indent should never use tabs\n" . $herevet);
$rpt_cleaners = 1;
commit a2fdc8907bee6eb572fea992be7126e1b616d5bf
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Thu Feb 3 19:43:25 2011 +0000
target-arm: Fix decoding of Thumb preload and hint space
Refine the decoding of the Thumb preload and hint space, so we
UNDEF on the patterns that are supposed to UNDEF rather than NOP.
We also move the tests for this space earlier, so we don't emit
harmless but unnecessary address generation code for preload
hints (which by their nature are likely to be in hot code paths).
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/translate.c b/target-arm/translate.c
index a8f1ffe..e4649e6 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -8306,6 +8306,42 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
goto illegal_op;
break;
}
+ op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
+ if (rs == 15) {
+ if (!(insn & (1 << 20))) {
+ goto illegal_op;
+ }
+ if (op != 2) {
+ /* Byte or halfword load space with dest == r15 : memory hints.
+ * Catch them early so we don't emit pointless addressing code.
+ * This space is a mix of:
+ * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
+ * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
+ * cores)
+ * unallocated hints, which must be treated as NOPs
+ * UNPREDICTABLE space, which we NOP or UNDEF depending on
+ * which is easiest for the decoding logic
+ * Some space which must UNDEF
+ */
+ int op1 = (insn >> 23) & 3;
+ int op2 = (insn >> 6) & 0x3f;
+ if (op & 2) {
+ goto illegal_op;
+ }
+ if (rn == 15) {
+ /* UNPREDICTABLE or unallocated hint */
+ return 0;
+ }
+ if (op1 & 1) {
+ return 0; /* PLD* or unallocated hint */
+ }
+ if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
+ return 0; /* PLD* or unallocated hint */
+ }
+ /* UNDEF space, or an UNPREDICTABLE */
+ return 1;
+ }
+ }
user = IS_USER(s);
if (rn == 15) {
addr = new_tmp();
@@ -8324,9 +8360,8 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
imm = insn & 0xfff;
tcg_gen_addi_i32(addr, addr, imm);
} else {
- op = (insn >> 8) & 7;
imm = insn & 0xff;
- switch (op) {
+ switch ((insn >> 8) & 7) {
case 0: case 8: /* Shifted Register. */
shift = (insn >> 4) & 0xf;
if (shift > 3)
@@ -8363,32 +8398,23 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
}
}
}
- op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
if (insn & (1 << 20)) {
/* Load. */
- if (rs == 15 && op != 2) {
- if (op & 2)
- goto illegal_op;
- /* Memory hint. Implemented as NOP. */
+ switch (op) {
+ case 0: tmp = gen_ld8u(addr, user); break;
+ case 4: tmp = gen_ld8s(addr, user); break;
+ case 1: tmp = gen_ld16u(addr, user); break;
+ case 5: tmp = gen_ld16s(addr, user); break;
+ case 2: tmp = gen_ld32(addr, user); break;
+ default: goto illegal_op;
+ }
+ if (rs == 15) {
+ gen_bx(s, tmp);
} else {
- switch (op) {
- case 0: tmp = gen_ld8u(addr, user); break;
- case 4: tmp = gen_ld8s(addr, user); break;
- case 1: tmp = gen_ld16u(addr, user); break;
- case 5: tmp = gen_ld16s(addr, user); break;
- case 2: tmp = gen_ld32(addr, user); break;
- default: goto illegal_op;
- }
- if (rs == 15) {
- gen_bx(s, tmp);
- } else {
- store_reg(s, rs, tmp);
- }
+ store_reg(s, rs, tmp);
}
} else {
/* Store. */
- if (rs == 15)
- goto illegal_op;
tmp = load_reg(s, rs);
switch (op) {
case 0: gen_st8(tmp, addr, user); break;
commit 3d185e5dd4967b7d03772d806ee566ed09d67485
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Thu Feb 3 19:43:24 2011 +0000
target-arm: Fix decoding of preload and memory hint space
Correct the decoding of the ARM preload and memory hint space,
by adding decoding of PLI, PLDW and the v7MP unallocated hint
space. This commit also corrects a slightly overexuberant
decoding of PLD(register) which was not checking that bit 4
was one.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 5149543..a8f1ffe 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -6100,9 +6100,31 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
goto illegal_op;
return;
}
- if ((insn & 0x0d70f000) == 0x0550f000)
- return; /* PLD */
- else if ((insn & 0x0ffffdff) == 0x01010000) {
+ if (((insn & 0x0f30f000) == 0x0510f000) ||
+ ((insn & 0x0f30f010) == 0x0710f000)) {
+ if ((insn & (1 << 22)) == 0) {
+ /* PLDW; v7MP */
+ if (!arm_feature(env, ARM_FEATURE_V7MP)) {
+ goto illegal_op;
+ }
+ }
+ /* Otherwise PLD; v5TE+ */
+ return;
+ }
+ if (((insn & 0x0f70f000) == 0x0450f000) ||
+ ((insn & 0x0f70f010) == 0x0650f000)) {
+ ARCH(7);
+ return; /* PLI; V7 */
+ }
+ if (((insn & 0x0f700000) == 0x04100000) ||
+ ((insn & 0x0f700010) == 0x06100000)) {
+ if (!arm_feature(env, ARM_FEATURE_V7MP)) {
+ goto illegal_op;
+ }
+ return; /* v7MP: Unallocated memory hint: must NOP */
+ }
+
+ if ((insn & 0x0ffffdff) == 0x01010000) {
ARCH(6);
/* setend */
if (insn & (1 << 9)) {
commit 607b4b0876bd3b1f33786ecc010ca2723de57270
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Thu Feb 3 19:43:23 2011 +0000
target-arm: Clean up handling of MPIDR
The ARM cp15 register 0,c0,c0,5 is standardised in the v7 architecture
as the MPIDR. Clean up its implementation to remove A9 specific handling.
This commit includes fixing an error in the value returned for the
MPIDR on A9, where we were erroneously claiming a cluster ID of 9.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 3cf9181..d46defc 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1608,12 +1608,28 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
return 0;
case 3: /* TLB type register. */
return 0; /* No lockable TLB entries. */
- case 5: /* CPU ID */
- if (ARM_CPUID(env) == ARM_CPUID_CORTEXA9) {
- return env->cpu_index | 0x80000900;
- } else {
- return env->cpu_index;
+ case 5: /* MPIDR */
+ /* The MPIDR was standardised in v7; prior to
+ * this it was implemented only in the 11MPCore.
+ * For all other pre-v7 cores it does not exist.
+ */
+ if (arm_feature(env, ARM_FEATURE_V7) ||
+ ARM_CPUID(env) == ARM_CPUID_ARM11MPCORE) {
+ int mpidr = env->cpu_index;
+ /* We don't support setting cluster ID ([8..11])
+ * so these bits always RAZ.
+ */
+ if (arm_feature(env, ARM_FEATURE_V7MP)) {
+ mpidr |= (1 << 31);
+ /* Cores which are uniprocessor (non-coherent)
+ * but still implement the MP extensions set
+ * bit 30. (For instance, A9UP.) However we do
+ * not currently model any of those cores.
+ */
+ }
+ return mpidr;
}
+ /* otherwise fall through to the unimplemented-reg case */
default:
goto bad_reg;
}
commit e1bbf44636a7435be0582f56aa0947d5186d6009
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Thu Feb 3 19:43:22 2011 +0000
target-arm: Add CPU feature flag for v7MP
Add a CPU feature flag for v7MP (the multiprocessing extensions); some
instructions exist only for v7MP and not for the base v7 architecture.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 5bcd53a..0d96325 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -362,7 +362,8 @@ enum arm_features {
ARM_FEATURE_DIV,
ARM_FEATURE_M, /* Microcontroller profile. */
ARM_FEATURE_OMAPCP, /* OMAP specific CP15 ops handling. */
- ARM_FEATURE_THUMB2EE
+ ARM_FEATURE_THUMB2EE,
+ ARM_FEATURE_V7MP /* v7 Multiprocessing Extensions */
};
static inline int arm_feature(CPUARMState *env, int feature)
diff --git a/target-arm/helper.c b/target-arm/helper.c
index b562767..3cf9181 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -123,6 +123,11 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
set_feature(env, ARM_FEATURE_VFP_FP16);
set_feature(env, ARM_FEATURE_NEON);
set_feature(env, ARM_FEATURE_THUMB2EE);
+ /* Note that A9 supports the MP extensions even for
+ * A9UP and single-core A9MP (which are both different
+ * and valid configurations; we don't model A9UP).
+ */
+ set_feature(env, ARM_FEATURE_V7MP);
env->vfp.xregs[ARM_VFP_FPSID] = 0x41034000; /* Guess */
env->vfp.xregs[ARM_VFP_MVFR0] = 0x11110222;
env->vfp.xregs[ARM_VFP_MVFR1] = 0x01111111;
@@ -152,6 +157,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
set_feature(env, ARM_FEATURE_NEON);
set_feature(env, ARM_FEATURE_THUMB2EE);
set_feature(env, ARM_FEATURE_DIV);
+ set_feature(env, ARM_FEATURE_V7MP);
break;
case ARM_CPUID_TI915T:
case ARM_CPUID_TI925T:
commit 4fef930af8d7fab4b6c777fa4c6e2b902359262a
Author: Gleb Natapov <gleb at redhat.com>
Date: Wed Feb 2 17:34:34 2011 +0200
do not pass NULL to strdup.
Also use qemu_strdup() instead of strdup() in bootindex code.
Signed-off-by: Gleb Natapov <gleb at redhat.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/vl.c b/vl.c
index 655617f..ed2cdfa 100644
--- a/vl.c
+++ b/vl.c
@@ -738,7 +738,7 @@ void add_boot_device_path(int32_t bootindex, DeviceState *dev,
node = qemu_mallocz(sizeof(FWBootEntry));
node->bootindex = bootindex;
- node->suffix = strdup(suffix);
+ node->suffix = suffix ? qemu_strdup(suffix) : NULL;
node->dev = dev;
QTAILQ_FOREACH(i, &fw_boot_order, link) {
@@ -785,7 +785,7 @@ char *get_boot_devices_list(uint32_t *size)
} else if (devpath) {
bootpath = devpath;
} else {
- bootpath = strdup(i->suffix);
+ bootpath = qemu_strdup(i->suffix);
assert(bootpath);
}
commit 72902672dc2ed6281cdb205259c1d52ecf01f6b2
Author: Christophe Lyon <christophe.lyon at st.com>
Date: Fri Feb 4 15:17:51 2011 +0100
Set the right overflow bit for neon 32 and 64 bit saturating add/sub.
Signed-off-by: Christophe Lyon <christophe.lyon at st.com>
Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/helpers.h b/target-arm/helpers.h
index b88ebae..8a2564e 100644
--- a/target-arm/helpers.h
+++ b/target-arm/helpers.h
@@ -137,10 +137,6 @@ DEF_HELPER_2(rsqrte_f32, f32, f32, env)
DEF_HELPER_2(recpe_u32, i32, i32, env)
DEF_HELPER_2(rsqrte_u32, i32, i32, env)
DEF_HELPER_4(neon_tbl, i32, i32, i32, i32, i32)
-DEF_HELPER_2(neon_add_saturate_u64, i64, i64, i64)
-DEF_HELPER_2(neon_add_saturate_s64, i64, i64, i64)
-DEF_HELPER_2(neon_sub_saturate_u64, i64, i64, i64)
-DEF_HELPER_2(neon_sub_saturate_s64, i64, i64, i64)
DEF_HELPER_2(add_cc, i32, i32, i32)
DEF_HELPER_2(adc_cc, i32, i32, i32)
@@ -160,10 +156,18 @@ DEF_HELPER_3(neon_qadd_u8, i32, env, i32, i32)
DEF_HELPER_3(neon_qadd_s8, i32, env, i32, i32)
DEF_HELPER_3(neon_qadd_u16, i32, env, i32, i32)
DEF_HELPER_3(neon_qadd_s16, i32, env, i32, i32)
+DEF_HELPER_3(neon_qadd_u32, i32, env, i32, i32)
+DEF_HELPER_3(neon_qadd_s32, i32, env, i32, i32)
DEF_HELPER_3(neon_qsub_u8, i32, env, i32, i32)
DEF_HELPER_3(neon_qsub_s8, i32, env, i32, i32)
DEF_HELPER_3(neon_qsub_u16, i32, env, i32, i32)
DEF_HELPER_3(neon_qsub_s16, i32, env, i32, i32)
+DEF_HELPER_3(neon_qsub_u32, i32, env, i32, i32)
+DEF_HELPER_3(neon_qsub_s32, i32, env, i32, i32)
+DEF_HELPER_3(neon_qadd_u64, i64, env, i64, i64)
+DEF_HELPER_3(neon_qadd_s64, i64, env, i64, i64)
+DEF_HELPER_3(neon_qsub_u64, i64, env, i64, i64)
+DEF_HELPER_3(neon_qsub_s64, i64, env, i64, i64)
DEF_HELPER_2(neon_hadd_s8, i32, i32, i32)
DEF_HELPER_2(neon_hadd_u8, i32, i32, i32)
diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index fead152..268af33 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -198,6 +198,28 @@ NEON_VOP_ENV(qadd_u16, neon_u16, 2)
#undef NEON_FN
#undef NEON_USAT
+uint32_t HELPER(neon_qadd_u32)(CPUState *env, uint32_t a, uint32_t b)
+{
+ uint32_t res = a + b;
+ if (res < a) {
+ SET_QC();
+ res = ~0;
+ }
+ return res;
+}
+
+uint64_t HELPER(neon_qadd_u64)(CPUState *env, uint64_t src1, uint64_t src2)
+{
+ uint64_t res;
+
+ res = src1 + src2;
+ if (res < src1) {
+ SET_QC();
+ res = ~(uint64_t)0;
+ }
+ return res;
+}
+
#define NEON_SSAT(dest, src1, src2, type) do { \
int32_t tmp = (uint32_t)src1 + (uint32_t)src2; \
if (tmp != (type)tmp) { \
@@ -218,6 +240,28 @@ NEON_VOP_ENV(qadd_s16, neon_s16, 2)
#undef NEON_FN
#undef NEON_SSAT
+uint32_t HELPER(neon_qadd_s32)(CPUState *env, uint32_t a, uint32_t b)
+{
+ uint32_t res = a + b;
+ if (((res ^ a) & SIGNBIT) && !((a ^ b) & SIGNBIT)) {
+ SET_QC();
+ res = ~(((int32_t)a >> 31) ^ SIGNBIT);
+ }
+ return res;
+}
+
+uint64_t HELPER(neon_qadd_s64)(CPUState *env, uint64_t src1, uint64_t src2)
+{
+ uint64_t res;
+
+ res = src1 + src2;
+ if (((res ^ src1) & SIGNBIT64) && !((src1 ^ src2) & SIGNBIT64)) {
+ SET_QC();
+ res = ((int64_t)src1 >> 63) ^ ~SIGNBIT64;
+ }
+ return res;
+}
+
#define NEON_USAT(dest, src1, src2, type) do { \
uint32_t tmp = (uint32_t)src1 - (uint32_t)src2; \
if (tmp != (type)tmp) { \
@@ -234,6 +278,29 @@ NEON_VOP_ENV(qsub_u16, neon_u16, 2)
#undef NEON_FN
#undef NEON_USAT
+uint32_t HELPER(neon_qsub_u32)(CPUState *env, uint32_t a, uint32_t b)
+{
+ uint32_t res = a - b;
+ if (res > a) {
+ SET_QC();
+ res = 0;
+ }
+ return res;
+}
+
+uint64_t HELPER(neon_qsub_u64)(CPUState *env, uint64_t src1, uint64_t src2)
+{
+ uint64_t res;
+
+ if (src1 < src2) {
+ SET_QC();
+ res = 0;
+ } else {
+ res = src1 - src2;
+ }
+ return res;
+}
+
#define NEON_SSAT(dest, src1, src2, type) do { \
int32_t tmp = (uint32_t)src1 - (uint32_t)src2; \
if (tmp != (type)tmp) { \
@@ -254,6 +321,28 @@ NEON_VOP_ENV(qsub_s16, neon_s16, 2)
#undef NEON_FN
#undef NEON_SSAT
+uint32_t HELPER(neon_qsub_s32)(CPUState *env, uint32_t a, uint32_t b)
+{
+ uint32_t res = a - b;
+ if (((res ^ a) & SIGNBIT) && ((a ^ b) & SIGNBIT)) {
+ SET_QC();
+ res = ~(((int32_t)a >> 31) ^ SIGNBIT);
+ }
+ return res;
+}
+
+uint64_t HELPER(neon_qsub_s64)(CPUState *env, uint64_t src1, uint64_t src2)
+{
+ uint64_t res;
+
+ res = src1 - src2;
+ if (((res ^ src1) & SIGNBIT64) && ((src1 ^ src2) & SIGNBIT64)) {
+ SET_QC();
+ res = ((int64_t)src1 >> 63) ^ ~SIGNBIT64;
+ }
+ return res;
+}
+
#define NEON_FN(dest, src1, src2) dest = (src1 + src2) >> 1
NEON_VOP(hadd_s8, neon_s8, 4)
NEON_VOP(hadd_u8, neon_u8, 4)
diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c
index 43baa63..3de2610 100644
--- a/target-arm/op_helper.c
+++ b/target-arm/op_helper.c
@@ -424,52 +424,3 @@ uint32_t HELPER(ror_cc)(uint32_t x, uint32_t i)
return ((uint32_t)x >> shift) | (x << (32 - shift));
}
}
-
-uint64_t HELPER(neon_add_saturate_s64)(uint64_t src1, uint64_t src2)
-{
- uint64_t res;
-
- res = src1 + src2;
- if (((res ^ src1) & SIGNBIT64) && !((src1 ^ src2) & SIGNBIT64)) {
- env->QF = 1;
- res = ((int64_t)src1 >> 63) ^ ~SIGNBIT64;
- }
- return res;
-}
-
-uint64_t HELPER(neon_add_saturate_u64)(uint64_t src1, uint64_t src2)
-{
- uint64_t res;
-
- res = src1 + src2;
- if (res < src1) {
- env->QF = 1;
- res = ~(uint64_t)0;
- }
- return res;
-}
-
-uint64_t HELPER(neon_sub_saturate_s64)(uint64_t src1, uint64_t src2)
-{
- uint64_t res;
-
- res = src1 - src2;
- if (((res ^ src1) & SIGNBIT64) && ((src1 ^ src2) & SIGNBIT64)) {
- env->QF = 1;
- res = ((int64_t)src1 >> 63) ^ ~SIGNBIT64;
- }
- return res;
-}
-
-uint64_t HELPER(neon_sub_saturate_u64)(uint64_t src1, uint64_t src2)
-{
- uint64_t res;
-
- if (src1 < src2) {
- env->QF = 1;
- res = 0;
- } else {
- res = src1 - src2;
- }
- return res;
-}
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 92d0ef0..5149543 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -3539,12 +3539,6 @@ static inline void gen_neon_rsb(int size, TCGv t0, TCGv t1)
#define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
#define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
-/* FIXME: This is wrong. They set the wrong overflow bit. */
-#define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
-#define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
-#define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
-#define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
-
#define GEN_NEON_INTEGER_OP_ENV(name) do { \
switch ((size << 1) | u) { \
case 0: \
@@ -4233,16 +4227,20 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
switch (op) {
case 1: /* VQADD */
if (u) {
- gen_helper_neon_add_saturate_u64(CPU_V001);
+ gen_helper_neon_qadd_u64(cpu_V0, cpu_env,
+ cpu_V0, cpu_V1);
} else {
- gen_helper_neon_add_saturate_s64(CPU_V001);
+ gen_helper_neon_qadd_s64(cpu_V0, cpu_env,
+ cpu_V0, cpu_V1);
}
break;
case 5: /* VQSUB */
if (u) {
- gen_helper_neon_sub_saturate_u64(CPU_V001);
+ gen_helper_neon_qsub_u64(cpu_V0, cpu_env,
+ cpu_V0, cpu_V1);
} else {
- gen_helper_neon_sub_saturate_s64(CPU_V001);
+ gen_helper_neon_qsub_s64(cpu_V0, cpu_env,
+ cpu_V0, cpu_V1);
}
break;
case 8: /* VSHL */
commit 5371cb81405a35ca4c1f6ab23f93a4f7260ffa53
Author: Christophe Lyon <christophe.lyon at st.com>
Date: Tue Jan 25 18:18:08 2011 +0100
target-arm: Fix Neon vsra instructions.
This patch fixes the errors reported by my tests in VSRA.
Signed-off-by: Christophe Lyon <christophe.lyon at st.com>
Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/translate.c b/target-arm/translate.c
index d95133f..92d0ef0 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4686,7 +4686,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
}
if (op == 1 || op == 3) {
/* Accumulate. */
- neon_load_reg64(cpu_V0, rd + pass);
+ neon_load_reg64(cpu_V1, rd + pass);
tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
} else if (op == 4 || (op == 5 && u)) {
/* Insert */
@@ -4750,7 +4750,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
if (op == 1 || op == 3) {
/* Accumulate. */
tmp2 = neon_load_reg(rd, pass);
- gen_neon_add(size, tmp2, tmp);
+ gen_neon_add(size, tmp, tmp2);
dead_tmp(tmp2);
} else if (op == 4 || (op == 5 && u)) {
/* Insert */
commit 7026259f79ffc85ceaaaeee32df518ea96863ee4
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Fri Feb 4 20:19:33 2011 +0100
target-sh4: fix negc
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-sh4/translate.c b/target-sh4/translate.c
index 35573be..58e9b8f 100644
--- a/target-sh4/translate.c
+++ b/target-sh4/translate.c
@@ -960,9 +960,9 @@ static void _decode_opc(DisasContext * ctx)
tcg_gen_andi_i32(t1, cpu_sr, SR_T);
tcg_gen_sub_i32(REG(B11_8), t0, t1);
tcg_gen_andi_i32(cpu_sr, cpu_sr, ~SR_T);
- tcg_gen_setcond_i32(TCG_COND_GE, t1, REG(B11_8), t0);
+ tcg_gen_setcondi_i32(TCG_COND_GTU, t1, t0, 0);
tcg_gen_or_i32(cpu_sr, cpu_sr, t1);
- tcg_gen_setcondi_i32(TCG_COND_GE, t1, t0, 0);
+ tcg_gen_setcond_i32(TCG_COND_GTU, t1, REG(B11_8), t0);
tcg_gen_or_i32(cpu_sr, cpu_sr, t1);
tcg_temp_free(t0);
tcg_temp_free(t1);
commit 1f5e71a8e6b24dce74b156472ff9253b9bd33a11
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Thu Feb 3 22:54:14 2011 +0100
ioapic: Style & magics cleanup
Fix a few style issues and convert magic numbers into prober symbolic
constants, also fixing the wrong but unused IOAPIC_DM_SIPI value.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/hw/ioapic.c b/hw/ioapic.c
index fb3d173..569327d 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -39,20 +39,48 @@
#define MAX_IOAPICS 1
-#define IOAPIC_LVT_MASKED (1 << 16)
-#define IOAPIC_LVT_REMOTE_IRR (1 << 14)
+#define IOAPIC_VERSION 0x11
-#define IOAPIC_TRIGGER_EDGE 0
-#define IOAPIC_TRIGGER_LEVEL 1
+#define IOAPIC_LVT_DEST_SHIFT 56
+#define IOAPIC_LVT_MASKED_SHIFT 16
+#define IOAPIC_LVT_TRIGGER_MODE_SHIFT 15
+#define IOAPIC_LVT_REMOTE_IRR_SHIFT 14
+#define IOAPIC_LVT_POLARITY_SHIFT 13
+#define IOAPIC_LVT_DELIV_STATUS_SHIFT 12
+#define IOAPIC_LVT_DEST_MODE_SHIFT 11
+#define IOAPIC_LVT_DELIV_MODE_SHIFT 8
+
+#define IOAPIC_LVT_MASKED (1 << IOAPIC_LVT_MASKED_SHIFT)
+#define IOAPIC_LVT_REMOTE_IRR (1 << IOAPIC_LVT_REMOTE_IRR_SHIFT)
+
+#define IOAPIC_TRIGGER_EDGE 0
+#define IOAPIC_TRIGGER_LEVEL 1
/*io{apic,sapic} delivery mode*/
-#define IOAPIC_DM_FIXED 0x0
-#define IOAPIC_DM_LOWEST_PRIORITY 0x1
-#define IOAPIC_DM_PMI 0x2
-#define IOAPIC_DM_NMI 0x4
-#define IOAPIC_DM_INIT 0x5
-#define IOAPIC_DM_SIPI 0x5
-#define IOAPIC_DM_EXTINT 0x7
+#define IOAPIC_DM_FIXED 0x0
+#define IOAPIC_DM_LOWEST_PRIORITY 0x1
+#define IOAPIC_DM_PMI 0x2
+#define IOAPIC_DM_NMI 0x4
+#define IOAPIC_DM_INIT 0x5
+#define IOAPIC_DM_SIPI 0x6
+#define IOAPIC_DM_EXTINT 0x7
+#define IOAPIC_DM_MASK 0x7
+
+#define IOAPIC_VECTOR_MASK 0xff
+
+#define IOAPIC_IOREGSEL 0x00
+#define IOAPIC_IOWIN 0x10
+
+#define IOAPIC_REG_ID 0x00
+#define IOAPIC_REG_VER 0x01
+#define IOAPIC_REG_ARB 0x02
+#define IOAPIC_REG_REDTBL_BASE 0x10
+#define IOAPIC_ID 0x00
+
+#define IOAPIC_ID_SHIFT 24
+#define IOAPIC_ID_MASK 0xf
+
+#define IOAPIC_VER_ENTRIES_SHIFT 16
typedef struct IOAPICState IOAPICState;
@@ -60,7 +88,6 @@ struct IOAPICState {
SysBusDevice busdev;
uint8_t id;
uint8_t ioregsel;
-
uint32_t irr;
uint64_t ioredtbl[IOAPIC_NUM_PINS];
};
@@ -84,21 +111,22 @@ static void ioapic_service(IOAPICState *s)
if (s->irr & mask) {
entry = s->ioredtbl[i];
if (!(entry & IOAPIC_LVT_MASKED)) {
- trig_mode = ((entry >> 15) & 1);
- dest = entry >> 56;
- dest_mode = (entry >> 11) & 1;
- delivery_mode = (entry >> 8) & 7;
- polarity = (entry >> 13) & 1;
+ trig_mode = ((entry >> IOAPIC_LVT_TRIGGER_MODE_SHIFT) & 1);
+ dest = entry >> IOAPIC_LVT_DEST_SHIFT;
+ dest_mode = (entry >> IOAPIC_LVT_DEST_MODE_SHIFT) & 1;
+ delivery_mode =
+ (entry >> IOAPIC_LVT_DELIV_MODE_SHIFT) & IOAPIC_DM_MASK;
+ polarity = (entry >> IOAPIC_LVT_POLARITY_SHIFT) & 1;
if (trig_mode == IOAPIC_TRIGGER_EDGE) {
s->irr &= ~mask;
} else {
s->ioredtbl[i] |= IOAPIC_LVT_REMOTE_IRR;
}
- if (delivery_mode == IOAPIC_DM_EXTINT)
+ if (delivery_mode == IOAPIC_DM_EXTINT) {
vector = pic_read_irq(isa_pic);
- else
- vector = entry & 0xff;
-
+ } else {
+ vector = entry & IOAPIC_VECTOR_MASK;
+ }
apic_deliver_irq(dest, dest_mode, delivery_mode,
vector, polarity, trig_mode);
}
@@ -114,15 +142,16 @@ static void ioapic_set_irq(void *opaque, int vector, int level)
* to GSI 2. GSI maps to ioapic 1-1. This is not
* the cleanest way of doing it but it should work. */
- DPRINTF("%s: %s vec %x\n", __func__, level? "raise" : "lower", vector);
- if (vector == 0)
+ DPRINTF("%s: %s vec %x\n", __func__, level ? "raise" : "lower", vector);
+ if (vector == 0) {
vector = 2;
-
+ }
if (vector >= 0 && vector < IOAPIC_NUM_PINS) {
uint32_t mask = 1 << vector;
uint64_t entry = s->ioredtbl[vector];
- if ((entry >> 15) & 1) {
+ if (((entry >> IOAPIC_LVT_TRIGGER_MODE_SHIFT) & 1) ==
+ IOAPIC_TRIGGER_LEVEL) {
/* level triggered */
if (level) {
s->irr |= mask;
@@ -153,7 +182,8 @@ void ioapic_eoi_broadcast(int vector)
}
for (n = 0; n < IOAPIC_NUM_PINS; n++) {
entry = s->ioredtbl[n];
- if ((entry & IOAPIC_LVT_REMOTE_IRR) && (entry & 0xff) == vector) {
+ if ((entry & IOAPIC_LVT_REMOTE_IRR)
+ && (entry & IOAPIC_VECTOR_MASK) == vector) {
s->ioredtbl[n] = entry & ~IOAPIC_LVT_REMOTE_IRR;
if (!(entry & IOAPIC_LVT_MASKED) && (s->irr & (1 << n))) {
ioapic_service(s);
@@ -169,65 +199,71 @@ static uint32_t ioapic_mem_readl(void *opaque, target_phys_addr_t addr)
int index;
uint32_t val = 0;
- addr &= 0xff;
- if (addr == 0x00) {
+ switch (addr & 0xff) {
+ case IOAPIC_IOREGSEL:
val = s->ioregsel;
- } else if (addr == 0x10) {
+ break;
+ case IOAPIC_IOWIN:
switch (s->ioregsel) {
- case 0x00:
- val = s->id << 24;
- break;
- case 0x01:
- val = 0x11 | ((IOAPIC_NUM_PINS - 1) << 16); /* version 0x11 */
- break;
- case 0x02:
- val = 0;
- break;
- default:
- index = (s->ioregsel - 0x10) >> 1;
- if (index >= 0 && index < IOAPIC_NUM_PINS) {
- if (s->ioregsel & 1)
- val = s->ioredtbl[index] >> 32;
- else
- val = s->ioredtbl[index] & 0xffffffff;
+ case IOAPIC_REG_ID:
+ val = s->id << IOAPIC_ID_SHIFT;
+ break;
+ case IOAPIC_REG_VER:
+ val = IOAPIC_VERSION |
+ ((IOAPIC_NUM_PINS - 1) << IOAPIC_VER_ENTRIES_SHIFT);
+ break;
+ case IOAPIC_REG_ARB:
+ val = 0;
+ break;
+ default:
+ index = (s->ioregsel - IOAPIC_REG_REDTBL_BASE) >> 1;
+ if (index >= 0 && index < IOAPIC_NUM_PINS) {
+ if (s->ioregsel & 1) {
+ val = s->ioredtbl[index] >> 32;
+ } else {
+ val = s->ioredtbl[index] & 0xffffffff;
}
+ }
}
DPRINTF("read: %08x = %08x\n", s->ioregsel, val);
+ break;
}
return val;
}
-static void ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void
+ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
IOAPICState *s = opaque;
int index;
- addr &= 0xff;
- if (addr == 0x00) {
+ switch (addr & 0xff) {
+ case IOAPIC_IOREGSEL:
s->ioregsel = val;
- return;
- } else if (addr == 0x10) {
+ break;
+ case IOAPIC_IOWIN:
DPRINTF("write: %08x = %08x\n", s->ioregsel, val);
switch (s->ioregsel) {
- case 0x00:
- s->id = (val >> 24) & 0xff;
- return;
- case 0x01:
- case 0x02:
- return;
- default:
- index = (s->ioregsel - 0x10) >> 1;
- if (index >= 0 && index < IOAPIC_NUM_PINS) {
- if (s->ioregsel & 1) {
- s->ioredtbl[index] &= 0xffffffff;
- s->ioredtbl[index] |= (uint64_t)val << 32;
- } else {
- s->ioredtbl[index] &= ~0xffffffffULL;
- s->ioredtbl[index] |= val;
- }
- ioapic_service(s);
+ case IOAPIC_REG_ID:
+ s->id = (val >> IOAPIC_ID_SHIFT) & IOAPIC_ID_MASK;
+ break;
+ case IOAPIC_REG_VER:
+ case IOAPIC_REG_ARB:
+ break;
+ default:
+ index = (s->ioregsel - IOAPIC_REG_REDTBL_BASE) >> 1;
+ if (index >= 0 && index < IOAPIC_NUM_PINS) {
+ if (s->ioregsel & 1) {
+ s->ioredtbl[index] &= 0xffffffff;
+ s->ioredtbl[index] |= (uint64_t)val << 32;
+ } else {
+ s->ioredtbl[index] &= ~0xffffffffULL;
+ s->ioredtbl[index] |= val;
}
+ ioapic_service(s);
+ }
}
+ break;
}
}
@@ -248,7 +284,7 @@ static const VMStateDescription vmstate_ioapic = {
.post_load = ioapic_post_load,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
- .fields = (VMStateField []) {
+ .fields = (VMStateField[]) {
VMSTATE_UINT8(id, IOAPICState),
VMSTATE_UINT8(ioregsel, IOAPICState),
VMSTATE_UNUSED_V(2, 8), /* to account for qemu-kvm's v2 format */
@@ -266,8 +302,9 @@ static void ioapic_reset(DeviceState *d)
s->id = 0;
s->ioregsel = 0;
s->irr = 0;
- for(i = 0; i < IOAPIC_NUM_PINS; i++)
- s->ioredtbl[i] = 1 << 16; /* mask LVT */
+ for (i = 0; i < IOAPIC_NUM_PINS; i++) {
+ s->ioredtbl[i] = 1 << IOAPIC_LVT_MASKED_SHIFT;
+ }
}
static CPUReadMemoryFunc * const ioapic_mem_read[3] = {
commit 5dce499948e4a4abe62f010baf4a7ed3d49e53cb
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Thu Feb 3 22:54:13 2011 +0100
ioapic: Add support for qemu-kvm's vmstate v2
qemu-kvm carries the IOAPIC base address in its v2 vmstate. We only
support the default base address so far, and saving even that in the
device state was rejected.
Add a padding field to be able to read qemu-kvm's old state, but
increase our version to 3, indicating that we are not saving a valid
address. This also gives downstream the chance to change to stop
evaluating the base_address and move to v3 as well.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/hw/ioapic.c b/hw/ioapic.c
index 8c46c1d..fb3d173 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -244,13 +244,14 @@ static int ioapic_post_load(void *opaque, int version_id)
static const VMStateDescription vmstate_ioapic = {
.name = "ioapic",
- .version_id = 2,
+ .version_id = 3,
.post_load = ioapic_post_load,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField []) {
VMSTATE_UINT8(id, IOAPICState),
VMSTATE_UINT8(ioregsel, IOAPICState),
+ VMSTATE_UNUSED_V(2, 8), /* to account for qemu-kvm's v2 format */
VMSTATE_UINT32_V(irr, IOAPICState, 2),
VMSTATE_UINT64_ARRAY(ioredtbl, IOAPICState, IOAPIC_NUM_PINS),
VMSTATE_END_OF_LIST()
commit 35a74c5c5941b474d8b985237e1bde0b8cd2a20f
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Thu Feb 3 22:54:12 2011 +0100
ioapic: Save/restore irr
This is a guest modifiable state that must be saved/restored properly.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/hw/ioapic.c b/hw/ioapic.c
index 8bc31f7..8c46c1d 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -231,14 +231,27 @@ static void ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t va
}
}
+static int ioapic_post_load(void *opaque, int version_id)
+{
+ IOAPICState *s = opaque;
+
+ if (version_id == 1) {
+ /* set sane value */
+ s->irr = 0;
+ }
+ return 0;
+}
+
static const VMStateDescription vmstate_ioapic = {
.name = "ioapic",
- .version_id = 1,
+ .version_id = 2,
+ .post_load = ioapic_post_load,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField []) {
VMSTATE_UINT8(id, IOAPICState),
VMSTATE_UINT8(ioregsel, IOAPICState),
+ VMSTATE_UINT32_V(irr, IOAPICState, 2),
VMSTATE_UINT64_ARRAY(ioredtbl, IOAPICState, IOAPIC_NUM_PINS),
VMSTATE_END_OF_LIST()
}
commit 0280b571c1a153f8926612d8c8d7359242d596f5
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Thu Feb 3 22:54:11 2011 +0100
ioapic: Implement EOI handling for level-triggered IRQs
Add the missing EOI broadcast from local APIC to the IOAPICs on
completion of level-triggered IRQs. This ensures that a still asserted
IRQ source properly re-triggers an APIC IRQ.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/hw/apic.c b/hw/apic.c
index ff581f0..2f8376a 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -18,6 +18,7 @@
*/
#include "hw.h"
#include "apic.h"
+#include "ioapic.h"
#include "qemu-timer.h"
#include "host-utils.h"
#include "sysbus.h"
@@ -57,7 +58,8 @@
#define ESR_ILLEGAL_ADDRESS (1 << 7)
-#define APIC_SV_ENABLE (1 << 8)
+#define APIC_SV_DIRECTED_IO (1<<12)
+#define APIC_SV_ENABLE (1<<8)
#define MAX_APICS 255
#define MAX_APIC_WORDS 8
@@ -420,8 +422,9 @@ static void apic_eoi(APICState *s)
if (isrv < 0)
return;
reset_bit(s->isr, isrv);
- /* XXX: send the EOI packet to the APIC bus to allow the I/O APIC to
- set the remote IRR bit for level triggered interrupts. */
+ if (!(s->spurious_vec & APIC_SV_DIRECTED_IO) && get_bit(s->tmr, isrv)) {
+ ioapic_eoi_broadcast(isrv);
+ }
apic_update_irq(s);
}
diff --git a/hw/ioapic.c b/hw/ioapic.c
index 2109568..8bc31f7 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -23,6 +23,7 @@
#include "hw.h"
#include "pc.h"
#include "apic.h"
+#include "ioapic.h"
#include "qemu-timer.h"
#include "host-utils.h"
#include "sysbus.h"
@@ -36,7 +37,10 @@
#define DPRINTF(fmt, ...)
#endif
-#define IOAPIC_LVT_MASKED (1<<16)
+#define MAX_IOAPICS 1
+
+#define IOAPIC_LVT_MASKED (1 << 16)
+#define IOAPIC_LVT_REMOTE_IRR (1 << 14)
#define IOAPIC_TRIGGER_EDGE 0
#define IOAPIC_TRIGGER_LEVEL 1
@@ -61,6 +65,8 @@ struct IOAPICState {
uint64_t ioredtbl[IOAPIC_NUM_PINS];
};
+static IOAPICState *ioapics[MAX_IOAPICS];
+
static void ioapic_service(IOAPICState *s)
{
uint8_t i;
@@ -83,8 +89,11 @@ static void ioapic_service(IOAPICState *s)
dest_mode = (entry >> 11) & 1;
delivery_mode = (entry >> 8) & 7;
polarity = (entry >> 13) & 1;
- if (trig_mode == IOAPIC_TRIGGER_EDGE)
+ if (trig_mode == IOAPIC_TRIGGER_EDGE) {
s->irr &= ~mask;
+ } else {
+ s->ioredtbl[i] |= IOAPIC_LVT_REMOTE_IRR;
+ }
if (delivery_mode == IOAPIC_DM_EXTINT)
vector = pic_read_irq(isa_pic);
else
@@ -131,6 +140,29 @@ static void ioapic_set_irq(void *opaque, int vector, int level)
}
}
+void ioapic_eoi_broadcast(int vector)
+{
+ IOAPICState *s;
+ uint64_t entry;
+ int i, n;
+
+ for (i = 0; i < MAX_IOAPICS; i++) {
+ s = ioapics[i];
+ if (!s) {
+ continue;
+ }
+ for (n = 0; n < IOAPIC_NUM_PINS; n++) {
+ entry = s->ioredtbl[n];
+ if ((entry & IOAPIC_LVT_REMOTE_IRR) && (entry & 0xff) == vector) {
+ s->ioredtbl[n] = entry & ~IOAPIC_LVT_REMOTE_IRR;
+ if (!(entry & IOAPIC_LVT_MASKED) && (s->irr & (1 << n))) {
+ ioapic_service(s);
+ }
+ }
+ }
+ }
+}
+
static uint32_t ioapic_mem_readl(void *opaque, target_phys_addr_t addr)
{
IOAPICState *s = opaque;
@@ -240,6 +272,11 @@ static int ioapic_init1(SysBusDevice *dev)
{
IOAPICState *s = FROM_SYSBUS(IOAPICState, dev);
int io_memory;
+ static int ioapic_no;
+
+ if (ioapic_no >= MAX_IOAPICS) {
+ return -1;
+ }
io_memory = cpu_register_io_memory(ioapic_mem_read,
ioapic_mem_write, s,
@@ -248,6 +285,8 @@ static int ioapic_init1(SysBusDevice *dev)
qdev_init_gpio_in(&dev->qdev, ioapic_set_irq, IOAPIC_NUM_PINS);
+ ioapics[ioapic_no++] = s;
+
return 0;
}
diff --git a/hw/ioapic.h b/hw/ioapic.h
new file mode 100644
index 0000000..cb2642a
--- /dev/null
+++ b/hw/ioapic.h
@@ -0,0 +1,20 @@
+/*
+ * ioapic.c IOAPIC emulation logic
+ *
+ * Copyright (c) 2011 Jan Kiszka, Siemens AG
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+void ioapic_eoi_broadcast(int vector);
commit 73eb4c04e9e8ea7f6eb83694cb0c43e38d882a7c
Author: Corentin Chary <corentincj at iksaif.net>
Date: Fri Feb 4 09:05:53 2011 +0100
vnc: qemu can die if the client is disconnected while updating screen
agraf reported that qemu_mutex_destroy(vs->output_mutex) while failing
in vnc_disconnect_finish().
It's because vnc_worker_thread_loop() tries to unlock the mutex while
not locked. The unlocking call doesn't fail (pthread bug ?), but
the destroy call does.
Signed-off-by: Corentin Chary <corentincj at iksaif.net>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/ui/vnc-jobs-async.c b/ui/vnc-jobs-async.c
index 6e9cf08..0b5d750 100644
--- a/ui/vnc-jobs-async.c
+++ b/ui/vnc-jobs-async.c
@@ -227,6 +227,10 @@ static int vnc_worker_thread_loop(VncJobQueue *queue)
if (job->vs->csock == -1) {
vnc_unlock_display(job->vs->vd);
+ /* output mutex must be locked before going to
+ * disconnected:
+ */
+ vnc_lock_output(job->vs);
goto disconnected;
}
commit 7185f9315bcf90e99b123370cf4d19b8c20afbd5
Author: Amit Shah <amit.shah at redhat.com>
Date: Fri Feb 4 14:24:18 2011 +0530
virtio-serial: Make sure virtqueue is ready before discarding data
This can happen if a port gets unplugged before guest has chance to
initialise vqs.
Reported-by: Juan Quintela <quintela at redhat.com>
Signed-off-by: Amit Shah <amit.shah at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 09e22aa..e05ab5e 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -117,6 +117,9 @@ static void discard_vq_data(VirtQueue *vq, VirtIODevice *vdev)
{
VirtQueueElement elem;
+ if (!virtio_queue_ready(vq)) {
+ return;
+ }
while (virtqueue_pop(vq, &elem)) {
virtqueue_push(vq, &elem, 0);
}
commit 4e79bcbb96d3c189e50adbdac7b1e28d834ba43e
Author: Stefan Weil <weil at mail.berlios.de>
Date: Thu Feb 3 22:35:07 2011 +0100
ui/sdl: Fix handling of caps lock and num lock keys
Starting with SDL version 1.2.14, caps lock and num lock keys
will send a SDL_KEYUP when SDL_DISABLE_LOCK_KEYS=1 is set in
the environment.
The new code sets the environment unconditionally
(it won't harm old versions which do not know it).
The workaround for SDL_KEYUP is only compiled with old SDL versions.
A similar patch without handling of old SDL versions was already
published by Benjamin Drung for Ubuntu.
Cc: Anthony Liguori <aliguori at us.ibm.com>
Cc: Kevin Wolf <kwolf at redhat.com>
Cc: Benjamin Drung <benjamin.drung at gmail.com>
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/ui/sdl.c b/ui/sdl.c
index a1458ce..47ac49c 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -388,12 +388,16 @@ static void sdl_process_key(SDL_KeyboardEvent *ev)
else
modifiers_state[keycode] = 1;
break;
+#define QEMU_SDL_VERSION ((SDL_MAJOR_VERSION << 8) + SDL_MINOR_VERSION)
+#if QEMU_SDL_VERSION < 0x102 || QEMU_SDL_VERSION == 0x102 && SDL_PATCHLEVEL < 14
+ /* SDL versions before 1.2.14 don't support key up for caps/num lock. */
case 0x45: /* num lock */
case 0x3a: /* caps lock */
/* SDL does not send the key up event, so we generate it */
kbd_put_keycode(keycode);
kbd_put_keycode(keycode | SCANCODE_UP);
return;
+#endif
}
/* now send the key code */
@@ -831,6 +835,10 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 0);
}
+ /* Enable normal up/down events for Caps-Lock and Num-Lock keys.
+ * This requires SDL >= 1.2.14. */
+ setenv("SDL_DISABLE_LOCK_KEYS", "1", 1);
+
flags = SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE;
if (SDL_Init (flags)) {
fprintf(stderr, "Could not initialize SDL(%s) - exiting\n",
commit 4c3d45eb694de3e0bda10841a06ba98be4d569b1
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Thu Feb 3 14:49:01 2011 +0100
Unify alarm deadline computation
This patch shows how using the correct formula for
qemu_next_deadline_dyntick can simplify the code of
host_alarm_handler and eliminate useless duplication.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/qemu-timer.c b/qemu-timer.c
index 69e71d7..658f637 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -635,6 +635,8 @@ void qemu_run_all_timers(void)
qemu_run_timers(host_clock);
}
+static int64_t qemu_next_alarm_deadline(void);
+
#ifdef _WIN32
static void CALLBACK host_alarm_handler(UINT uTimerID, UINT uMsg,
DWORD_PTR dwUser, DWORD_PTR dw1,
@@ -677,14 +679,7 @@ static void host_alarm_handler(int host_signum)
}
#endif
if (alarm_has_dynticks(t) ||
- (!use_icount &&
- qemu_timer_expired(active_timers[QEMU_CLOCK_VIRTUAL],
- qemu_get_clock(vm_clock))) ||
- qemu_timer_expired(active_timers[QEMU_CLOCK_REALTIME],
- qemu_get_clock(rt_clock)) ||
- qemu_timer_expired(active_timers[QEMU_CLOCK_HOST],
- qemu_get_clock(host_clock))) {
-
+ qemu_next_alarm_deadline () <= 0) {
t->expired = alarm_has_dynticks(t);
t->pending = 1;
qemu_notify_event();
@@ -715,11 +710,7 @@ int64_t qemu_next_deadline(void)
#ifndef _WIN32
-#if defined(__linux__)
-
-#define RTC_FREQ 1024
-
-static uint64_t qemu_next_deadline_dyntick(void)
+static int64_t qemu_next_alarm_deadline(void)
{
int64_t delta;
int64_t rtdelta;
@@ -743,12 +734,13 @@ static uint64_t qemu_next_deadline_dyntick(void)
delta = rtdelta;
}
- if (delta < MIN_TIMER_REARM_NS)
- delta = MIN_TIMER_REARM_NS;
-
return delta;
}
+#if defined(__linux__)
+
+#define RTC_FREQ 1024
+
static void enable_sigio_timer(int fd)
{
struct sigaction act;
@@ -903,7 +895,9 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t)
!active_timers[QEMU_CLOCK_HOST])
return;
- nearest_delta_ns = qemu_next_deadline_dyntick();
+ nearest_delta_ns = qemu_next_alarm_deadline();
+ if (nearest_delta_ns < MIN_TIMER_REARM_NS)
+ nearest_delta_ns = MIN_TIMER_REARM_NS;
/* check whether a timer is already running */
if (timer_gettime(host_timer, &timeout)) {
commit 6ad0a1ed21ecd187dbe3239eb45c3598672af6a8
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Thu Feb 3 14:49:00 2011 +0100
Correct alarm deadline computation
When the QEMU_CLOCK_HOST clock was added, computation of its
deadline was added to qemu_next_deadline, which is correct but
incomplete.
I noticed this by reading the very convoluted rules whereby
qemu_next_deadline_dyntick is computed, which miss QEMU_CLOCK_HOST
when use_icount is true. This patch inlines qemu_next_deadline
into qemu_next_deadline_dyntick, and then corrects the logic to skip
only QEMU_CLOCK_VIRTUAL when use_icount is true.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Cc: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/qemu-timer.c b/qemu-timer.c
index bda072f..69e71d7 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -724,11 +724,18 @@ static uint64_t qemu_next_deadline_dyntick(void)
int64_t delta;
int64_t rtdelta;
- if (use_icount)
+ if (!use_icount && active_timers[QEMU_CLOCK_VIRTUAL]) {
+ delta = active_timers[QEMU_CLOCK_VIRTUAL]->expire_time -
+ qemu_get_clock(vm_clock);
+ } else {
delta = INT32_MAX;
- else
- delta = qemu_next_deadline();
-
+ }
+ if (active_timers[QEMU_CLOCK_HOST]) {
+ int64_t hdelta = active_timers[QEMU_CLOCK_HOST]->expire_time -
+ qemu_get_clock_ns(host_clock);
+ if (hdelta < delta)
+ delta = hdelta;
+ }
if (active_timers[QEMU_CLOCK_REALTIME]) {
rtdelta = (active_timers[QEMU_CLOCK_REALTIME]->expire_time * 1000000 -
qemu_get_clock_ns(rt_clock));
commit 9c13246ac13a87e05b5e6e7158e715dfa65fc7aa
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Thu Feb 3 14:48:59 2011 +0100
use nanoseconds everywhere for timeout computation
Suggested by Aurelien Jarno.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/qemu-timer.c b/qemu-timer.c
index db1ec49..bda072f 100644
--- a/qemu-timer.c
+++ b/qemu-timer.c
@@ -197,8 +197,8 @@ static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
t->rearm(t);
}
-/* TODO: MIN_TIMER_REARM_US should be optimized */
-#define MIN_TIMER_REARM_US 250
+/* TODO: MIN_TIMER_REARM_NS should be optimized */
+#define MIN_TIMER_REARM_NS 250000
#ifdef _WIN32
@@ -698,11 +698,11 @@ int64_t qemu_next_deadline(void)
if (active_timers[QEMU_CLOCK_VIRTUAL]) {
delta = active_timers[QEMU_CLOCK_VIRTUAL]->expire_time -
- qemu_get_clock(vm_clock);
+ qemu_get_clock_ns(vm_clock);
}
if (active_timers[QEMU_CLOCK_HOST]) {
int64_t hdelta = active_timers[QEMU_CLOCK_HOST]->expire_time -
- qemu_get_clock(host_clock);
+ qemu_get_clock_ns(host_clock);
if (hdelta < delta)
delta = hdelta;
}
@@ -727,17 +727,17 @@ static uint64_t qemu_next_deadline_dyntick(void)
if (use_icount)
delta = INT32_MAX;
else
- delta = (qemu_next_deadline() + 999) / 1000;
+ delta = qemu_next_deadline();
if (active_timers[QEMU_CLOCK_REALTIME]) {
- rtdelta = (active_timers[QEMU_CLOCK_REALTIME]->expire_time -
- qemu_get_clock(rt_clock))*1000;
+ rtdelta = (active_timers[QEMU_CLOCK_REALTIME]->expire_time * 1000000 -
+ qemu_get_clock_ns(rt_clock));
if (rtdelta < delta)
delta = rtdelta;
}
- if (delta < MIN_TIMER_REARM_US)
- delta = MIN_TIMER_REARM_US;
+ if (delta < MIN_TIMER_REARM_NS)
+ delta = MIN_TIMER_REARM_NS;
return delta;
}
@@ -887,8 +887,8 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t)
{
timer_t host_timer = (timer_t)(long)t->priv;
struct itimerspec timeout;
- int64_t nearest_delta_us = INT64_MAX;
- int64_t current_us;
+ int64_t nearest_delta_ns = INT64_MAX;
+ int64_t current_ns;
assert(alarm_has_dynticks(t));
if (!active_timers[QEMU_CLOCK_REALTIME] &&
@@ -896,7 +896,7 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t)
!active_timers[QEMU_CLOCK_HOST])
return;
- nearest_delta_us = qemu_next_deadline_dyntick();
+ nearest_delta_ns = qemu_next_deadline_dyntick();
/* check whether a timer is already running */
if (timer_gettime(host_timer, &timeout)) {
@@ -904,14 +904,14 @@ static void dynticks_rearm_timer(struct qemu_alarm_timer *t)
fprintf(stderr, "Internal timer error: aborting\n");
exit(1);
}
- current_us = timeout.it_value.tv_sec * 1000000 + timeout.it_value.tv_nsec/1000;
- if (current_us && current_us <= nearest_delta_us)
+ current_ns = timeout.it_value.tv_sec * 1000000000LL + timeout.it_value.tv_nsec;
+ if (current_ns && current_ns <= nearest_delta_ns)
return;
timeout.it_interval.tv_sec = 0;
timeout.it_interval.tv_nsec = 0; /* 0 for one-shot timer */
- timeout.it_value.tv_sec = nearest_delta_us / 1000000;
- timeout.it_value.tv_nsec = (nearest_delta_us % 1000000) * 1000;
+ timeout.it_value.tv_sec = nearest_delta_ns / 1000000000;
+ timeout.it_value.tv_nsec = nearest_delta_ns % 1000000000;
if (timer_settime(host_timer, 0 /* RELATIVE */, &timeout, NULL)) {
perror("settime");
fprintf(stderr, "Internal timer error: aborting\n");
commit eb60260de0b050a5e8ab725e84d377d0b44c43ae
Author: Yoshiaki Tamura <tamura.yoshiaki at lab.ntt.co.jp>
Date: Thu Feb 3 13:34:08 2011 +0900
savevm: fix corruption in vmstate_subsection_load().
Although it's rare to happen in live migration, when the head of a
byte stream contains 0x05 which is the marker of subsection, the
loader gets corrupted because vmstate_subsection_load() continues even
the device doesn't require it. This patch adds a checker whether
subsection is needed, and skips following routines if not needed.
Signed-off-by: Yoshiaki Tamura <tamura.yoshiaki at lab.ntt.co.jp>
Acked-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/savevm.c b/savevm.c
index 4453217..6d83b0f 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1638,6 +1638,12 @@ static const VMStateDescription *vmstate_get_subsection(const VMStateSubsection
static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
void *opaque)
{
+ const VMStateSubsection *sub = vmsd->subsections;
+
+ if (!sub || !sub->needed) {
+ return 0;
+ }
+
while (qemu_peek_byte(f) == QEMU_VM_SUBSECTION) {
char idstr[256];
int ret;
@@ -1650,10 +1656,11 @@ static int vmstate_subsection_load(QEMUFile *f, const VMStateDescription *vmsd,
idstr[len] = 0;
version_id = qemu_get_be32(f);
- sub_vmsd = vmstate_get_subsection(vmsd->subsections, idstr);
+ sub_vmsd = vmstate_get_subsection(sub, idstr);
if (sub_vmsd == NULL) {
return -ENOENT;
}
+ assert(!sub_vmsd->subsections);
ret = vmstate_load_state(f, sub_vmsd, opaque, version_id);
if (ret) {
return ret;
@@ -1677,6 +1684,7 @@ static void vmstate_subsection_save(QEMUFile *f, const VMStateDescription *vmsd,
qemu_put_byte(f, len);
qemu_put_buffer(f, (uint8_t *)vmsd->name, len);
qemu_put_be32(f, vmsd->version_id);
+ assert(!vmsd->subsections);
vmstate_save_state(f, vmsd, opaque);
}
sub++;
commit bfddb47a343b4718e5768aa80bce8adead0f7fca
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Wed Feb 2 08:39:28 2011 +0100
Open up the 0.15 development branch
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/VERSION b/VERSION
index 0c123d0..d07c6d0 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.13.90
+0.14.50
commit 0e192fae3c79e7d2830f8b1fa694cd8e128084cf
Author: Anthony Liguori <aliguori at us.ibm.com>
Date: Tue Feb 1 16:59:46 2011 -0600
Update version for 0.14.0-rc0
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/VERSION b/VERSION
index d82f77b..0c123d0 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.13.50
+0.13.90
commit f487d6278f75f84378833b8c3a67443346d639dc
Author: Anthony Liguori <aliguori at us.ibm.com>
Date: Tue Feb 1 16:57:00 2011 -0600
Update SeaBIOS to 0.6.1.2
- 06d0bdd Minor build fixes.
- 33abfc0 Update version to 0.6.1.2.
- 484dd56 fix virtio-blk failure after reboot
- dd9c0d3 Update version to 0.6.1.1.
- 50ecfa8 mark irq9 active high in DSDT
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin
index f79c342..e191908 100644
Binary files a/pc-bios/bios.bin and b/pc-bios/bios.bin differ
diff --git a/roms/seabios b/roms/seabios
index 0ff9051..06d0bdd 160000
--- a/roms/seabios
+++ b/roms/seabios
@@ -1 +1 @@
-Subproject commit 0ff9051f756ba739bc2edca77925191c3c6cbc2f
+Subproject commit 06d0bdd9e2e20377b3180e4986b14c8549b393e4
commit 5430a28fe452907c9e1b2097e073bc1ea4b29f39
Author: mst at redhat.com <mst at redhat.com>
Date: Tue Feb 1 22:13:42 2011 +0200
vhost: force vhost off for non-MSI guests
When MSI is off, each interrupt needs to be bounced through the io
thread when it's set/cleared, so vhost-net causes more context switches and
higher CPU utilization than userspace virtio which handles networking in
the same thread.
We'll need to fix this by adding level irq support in kvm irqfd,
for now disable vhost-net in these configurations.
Added a vhostforce flag to force vhost-net back on.
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/hw/vhost.c b/hw/vhost.c
index 6082da2..38cc3b3 100644
--- a/hw/vhost.c
+++ b/hw/vhost.c
@@ -581,7 +581,7 @@ static void vhost_virtqueue_cleanup(struct vhost_dev *dev,
0, virtio_queue_get_desc_size(vdev, idx));
}
-int vhost_dev_init(struct vhost_dev *hdev, int devfd)
+int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force)
{
uint64_t features;
int r;
@@ -613,6 +613,7 @@ int vhost_dev_init(struct vhost_dev *hdev, int devfd)
hdev->log_enabled = false;
hdev->started = false;
cpu_register_phys_memory_client(&hdev->client);
+ hdev->force = force;
return 0;
fail:
r = -errno;
@@ -627,6 +628,13 @@ void vhost_dev_cleanup(struct vhost_dev *hdev)
close(hdev->control);
}
+bool vhost_dev_query(struct vhost_dev *hdev, VirtIODevice *vdev)
+{
+ return !vdev->binding->query_guest_notifiers ||
+ vdev->binding->query_guest_notifiers(vdev->binding_opaque) ||
+ hdev->force;
+}
+
int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
{
int i, r;
diff --git a/hw/vhost.h b/hw/vhost.h
index 86dd834..c8c595a 100644
--- a/hw/vhost.h
+++ b/hw/vhost.h
@@ -38,10 +38,12 @@ struct vhost_dev {
bool log_enabled;
vhost_log_chunk_t *log;
unsigned long long log_size;
+ bool force;
};
-int vhost_dev_init(struct vhost_dev *hdev, int devfd);
+int vhost_dev_init(struct vhost_dev *hdev, int devfd, bool force);
void vhost_dev_cleanup(struct vhost_dev *hdev);
+bool vhost_dev_query(struct vhost_dev *hdev, VirtIODevice *vdev);
int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev);
void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev);
diff --git a/hw/vhost_net.c b/hw/vhost_net.c
index c068be1..420e05f 100644
--- a/hw/vhost_net.c
+++ b/hw/vhost_net.c
@@ -81,7 +81,8 @@ static int vhost_net_get_fd(VLANClientState *backend)
}
}
-struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd)
+struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd,
+ bool force)
{
int r;
struct vhost_net *net = qemu_malloc(sizeof *net);
@@ -98,7 +99,7 @@ struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd)
(1 << VHOST_NET_F_VIRTIO_NET_HDR);
net->backend = r;
- r = vhost_dev_init(&net->dev, devfd);
+ r = vhost_dev_init(&net->dev, devfd, force);
if (r < 0) {
goto fail;
}
@@ -121,6 +122,11 @@ fail:
return NULL;
}
+bool vhost_net_query(VHostNetState *net, VirtIODevice *dev)
+{
+ return vhost_dev_query(&net->dev, dev);
+}
+
int vhost_net_start(struct vhost_net *net,
VirtIODevice *dev)
{
@@ -188,15 +194,21 @@ void vhost_net_cleanup(struct vhost_net *net)
qemu_free(net);
}
#else
-struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd)
+struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd,
+ bool force)
+{
+ return NULL;
+}
+
+bool vhost_net_query(VHostNetState *net, VirtIODevice *dev)
{
- return NULL;
+ return false;
}
int vhost_net_start(struct vhost_net *net,
VirtIODevice *dev)
{
- return -ENOSYS;
+ return -ENOSYS;
}
void vhost_net_stop(struct vhost_net *net,
VirtIODevice *dev)
@@ -209,7 +221,7 @@ void vhost_net_cleanup(struct vhost_net *net)
unsigned vhost_net_get_features(struct vhost_net *net, unsigned features)
{
- return features;
+ return features;
}
void vhost_net_ack_features(struct vhost_net *net, unsigned features)
{
diff --git a/hw/vhost_net.h b/hw/vhost_net.h
index 6c18ff7..91e40b1 100644
--- a/hw/vhost_net.h
+++ b/hw/vhost_net.h
@@ -6,8 +6,9 @@
struct vhost_net;
typedef struct vhost_net VHostNetState;
-VHostNetState *vhost_net_init(VLANClientState *backend, int devfd);
+VHostNetState *vhost_net_init(VLANClientState *backend, int devfd, bool force);
+bool vhost_net_query(VHostNetState *net, VirtIODevice *dev);
int vhost_net_start(VHostNetState *net, VirtIODevice *dev);
void vhost_net_stop(VHostNetState *net, VirtIODevice *dev);
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 161f114..671d952 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -119,7 +119,11 @@ static void virtio_net_vhost_status(VirtIONet *n, uint8_t status)
return;
}
if (!n->vhost_started) {
- int r = vhost_net_start(tap_get_vhost_net(n->nic->nc.peer), &n->vdev);
+ int r;
+ if (!vhost_net_query(tap_get_vhost_net(n->nic->nc.peer), &n->vdev)) {
+ return;
+ }
+ r = vhost_net_start(tap_get_vhost_net(n->nic->nc.peer), &n->vdev);
if (r < 0) {
error_report("unable to start vhost net: %d: "
"falling back on userspace virtio", -r);
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index d07ff97..3911b09 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -595,6 +595,12 @@ static int virtio_pci_set_guest_notifier(void *opaque, int n, bool assign)
return 0;
}
+static bool virtio_pci_query_guest_notifiers(void *opaque)
+{
+ VirtIOPCIProxy *proxy = opaque;
+ return msix_enabled(&proxy->pci_dev);
+}
+
static int virtio_pci_set_guest_notifiers(void *opaque, bool assign)
{
VirtIOPCIProxy *proxy = opaque;
@@ -658,6 +664,7 @@ static const VirtIOBindings virtio_pci_bindings = {
.save_queue = virtio_pci_save_queue,
.load_queue = virtio_pci_load_queue,
.get_features = virtio_pci_get_features,
+ .query_guest_notifiers = virtio_pci_query_guest_notifiers,
.set_host_notifier = virtio_pci_set_host_notifier,
.set_guest_notifiers = virtio_pci_set_guest_notifiers,
.vmstate_change = virtio_pci_vmstate_change,
diff --git a/hw/virtio.h b/hw/virtio.h
index d8546d5..31d16e1 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -93,6 +93,7 @@ typedef struct {
int (*load_config)(void * opaque, QEMUFile *f);
int (*load_queue)(void * opaque, int n, QEMUFile *f);
unsigned (*get_features)(void * opaque);
+ bool (*query_guest_notifiers)(void * opaque);
int (*set_guest_notifiers)(void * opaque, bool assigned);
int (*set_host_notifier)(void * opaque, int n, bool assigned);
void (*vmstate_change)(void * opaque, bool running);
diff --git a/net/tap.c b/net/tap.c
index eada34a..b8cd252 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -491,8 +491,10 @@ int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan
}
}
- if (qemu_opt_get_bool(opts, "vhost", !!qemu_opt_get(opts, "vhostfd"))) {
+ if (qemu_opt_get_bool(opts, "vhost", !!qemu_opt_get(opts, "vhostfd") ||
+ qemu_opt_get_bool(opts, "vhostforce", false))) {
int vhostfd, r;
+ bool force = qemu_opt_get_bool(opts, "vhostforce", false);
if (qemu_opt_get(opts, "vhostfd")) {
r = net_handle_fd_param(mon, qemu_opt_get(opts, "vhostfd"));
if (r == -1) {
@@ -502,7 +504,7 @@ int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan
} else {
vhostfd = -1;
}
- s->vhost_net = vhost_net_init(&s->nc, vhostfd);
+ s->vhost_net = vhost_net_init(&s->nc, vhostfd, force);
if (!s->vhost_net) {
error_report("vhost-net requested but could not be initialized");
return -1;
diff --git a/qemu-options.hx b/qemu-options.hx
index 598a1bd..945edf3 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1050,7 +1050,7 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
"-net tap[,vlan=n][,name=str],ifname=name\n"
" connect the host TAP network interface to VLAN 'n'\n"
#else
- "-net tap[,vlan=n][,name=str][,fd=h][,ifname=name][,script=file][,downscript=dfile][,sndbuf=nbytes][,vnet_hdr=on|off][,vhost=on|off][,vhostfd=h]\n"
+ "-net tap[,vlan=n][,name=str][,fd=h][,ifname=name][,script=file][,downscript=dfile][,sndbuf=nbytes][,vnet_hdr=on|off][,vhost=on|off][,vhostfd=h][,vhostforce=on|off]\n"
" connect the host TAP network interface to VLAN 'n' and use the\n"
" network scripts 'file' (default=" DEFAULT_NETWORK_SCRIPT ")\n"
" and 'dfile' (default=" DEFAULT_NETWORK_DOWN_SCRIPT ")\n"
@@ -1061,6 +1061,8 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
" use vnet_hdr=off to avoid enabling the IFF_VNET_HDR tap flag\n"
" use vnet_hdr=on to make the lack of IFF_VNET_HDR support an error condition\n"
" use vhost=on to enable experimental in kernel accelerator\n"
+ " (only has effect for virtio guests which use MSIX)\n"
+ " use vhostforce=on to force vhost on for non-MSIX virtio guests\n"
" use 'vhostfd=h' to connect to an already opened vhost net device\n"
#endif
"-net socket[,vlan=n][,name=str][,fd=h][,listen=[host]:port][,connect=host:port]\n"
commit f157ed202e51dc2492b201dc34ed28e89c973fb7
Author: Michael S. Tsirkin <mst at redhat.com>
Date: Tue Feb 1 14:25:40 2011 +0200
tap: safe sndbuf default
With current sndbuf default value, a blocked
target guest can prevent another guest from
transmitting any packets. While current
sndbuf value (1M) is reported to help some
UDP based workloads, the default should
be safe (0).
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/net/tap-linux.c b/net/tap-linux.c
index f7aa904..ff8cad0 100644
--- a/net/tap-linux.c
+++ b/net/tap-linux.c
@@ -82,12 +82,17 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required
return fd;
}
-/* sndbuf should be set to a value lower than the tx queue
- * capacity of any destination network interface.
+/* sndbuf implements a kind of flow control for tap.
+ * Unfortunately when it's enabled, and packets are sent
+ * to other guests on the same host, the receiver
+ * can lock up the transmitter indefinitely.
+ *
+ * To avoid packet loss, sndbuf should be set to a value lower than the tx
+ * queue capacity of any destination network interface.
* Ethernet NICs generally have txqueuelen=1000, so 1Mb is
- * a good default, given a 1500 byte MTU.
+ * a good value, given a 1500 byte MTU.
*/
-#define TAP_DEFAULT_SNDBUF 1024*1024
+#define TAP_DEFAULT_SNDBUF 0
int tap_set_sndbuf(int fd, QemuOpts *opts)
{
diff --git a/qemu-options.hx b/qemu-options.hx
index 939297a..598a1bd 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1057,7 +1057,7 @@ DEF("net", HAS_ARG, QEMU_OPTION_net,
" use '[down]script=no' to disable script execution\n"
" use 'fd=h' to connect to an already opened TAP interface\n"
" use 'sndbuf=nbytes' to limit the size of the send buffer (the\n"
- " default of 'sndbuf=1048576' can be disabled using 'sndbuf=0')\n"
+ " default is disabled 'sndbuf=0' to enable flow control set 'sndbuf=1048576')\n"
" use vnet_hdr=off to avoid enabling the IFF_VNET_HDR tap flag\n"
" use vnet_hdr=on to make the lack of IFF_VNET_HDR support an error condition\n"
" use vhost=on to enable experimental in kernel accelerator\n"
commit 466b58648a7b2ba7edb280b585e0b0c26e3be31e
Author: Gleb Natapov <gleb at redhat.com>
Date: Sun Jan 30 12:29:19 2011 +0200
Add boot index documentation.
Signed-off-by: Gleb Natapov <gleb at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/docs/bootindex.txt b/docs/bootindex.txt
new file mode 100644
index 0000000..16083b3
--- /dev/null
+++ b/docs/bootindex.txt
@@ -0,0 +1,43 @@
+= Bootindex propery =
+
+Block and net devices have bootindex property. This property is used to
+determine the order in which firmware will consider devices for booting
+the guest OS. If the bootindex property is not set for a device, it gets
+lowest boot priority. There is no particular order in which devices with
+unset bootindex property will be considered for booting, but they will
+still be bootable.
+
+== Example ==
+
+Lets assume we have QEMU machine with two NICs (virtio, e1000) and two
+disks (IDE, virtio):
+
+qemu -drive file=disk1.img,if=none,id=disk1
+ -device ide-drive,drive=disk1,bootindex=4
+ -drive file=disk2.img,if=none,id=disk2
+ -device virtio-blk-pci,drive=disk2,bootindex=3
+ -netdev type=user,id=net0 -device virtio-net-pci,netdev=net0,bootindex=2
+ -netdev type=user,id=net1 -device e1000,netdev=net1,bootindex=1
+
+Given the command above, firmware should try to boot from the e1000 NIC
+first. If this fails, it should try the virtio NIC next, if this fails
+too, it should try the virtio disk, and then the IDE disk.
+
+== Limitations ==
+
+1. Some firmware has limitations on which devices can be considered for
+booting. For instance, the PC BIOS boot specification allows only one
+disk to be bootable. If boot from disk fails for some reason, the BIOS
+won't retry booting from other disk. It still can try to boot from
+floppy or net, though.
+
+2. Sometimes, firmware cannot map the device path QEMU wants firmware to
+boot from to a boot method. It doesn't happen for devices the firmware
+can natively boot from, but if firmware relies on an option ROM for
+booting, and the same option ROM is used for booting from more then one
+device, the firmware may not be able to ask the option ROM to boot from
+a particular device reliably. For instance with PC BIOS, if a SCSI HBA
+has three bootable devices target1, target3, target5 connected to it,
+the option ROM will have a boot method for each of them, but it is not
+possible to map from boot method back to a specific target. This is a
+shortcoming of PC BIOS boot specification.
commit cf8ce30d03339861a46c31aa44c11279c282f2b0
Author: Gleb Natapov <gleb at redhat.com>
Date: Sun Jan 30 12:29:18 2011 +0200
Add bootindex handling into usb storage device.
Signed-off-by: Gleb Natapov <gleb at redhat.com>
Signed-off-by: Gleb Natapov <gleb at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 97d1e4a..76f5b02 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -532,6 +532,7 @@ static int usb_msd_initfn(USBDevice *dev)
}
}
+ add_boot_device_path(s->conf.bootindex, &dev->qdev, "/disk at 0,0");
return 0;
}
@@ -595,6 +596,7 @@ static USBDevice *usb_msd_init(const char *filename)
static struct USBDeviceInfo msd_info = {
.product_desc = "QEMU USB MSD",
.qdev.name = "usb-storage",
+ .qdev.fw_name = "storage",
.qdev.size = sizeof(MSDState),
.usb_desc = &desc,
.init = usb_msd_initfn,
commit 363f8cb9bcd308bd03d28e04ea5f5557dea5d5e8
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Thu Dec 23 13:42:54 2010 +0100
fix QemuOpts leak
Now that no backend's open function saves the passed QemuOpts, fix a leak
in the qemu_chr_open backwards-compatible parser.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/qemu-char.c b/qemu-char.c
index bb0c32d..ee4f4ca 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2559,6 +2559,7 @@ CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*i
if (chr && qemu_opt_get_bool(opts, "mux", 0)) {
monitor_init(chr, MONITOR_USE_READLINE);
}
+ qemu_opts_del(opts);
return chr;
}
commit 44b37b933745a9005504427dec06f4066af9762e
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Thu Dec 23 13:42:53 2010 +0100
remove text_console_opts
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/console.c b/console.c
index 60b80ee..57d6eb5 100644
--- a/console.c
+++ b/console.c
@@ -1437,7 +1437,6 @@ void console_color_init(DisplayState *ds)
static int n_text_consoles;
static CharDriverState *text_consoles[128];
-static QemuOpts *text_console_opts[128];
static void text_console_set_echo(CharDriverState *chr, bool echo)
{
@@ -1446,7 +1445,7 @@ static void text_console_set_echo(CharDriverState *chr, bool echo)
s->echo = echo;
}
-static void text_console_do_init(CharDriverState *chr, DisplayState *ds, QemuOpts *opts)
+static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
{
TextConsole *s;
static int color_inited;
@@ -1520,7 +1519,6 @@ CharDriverState *text_console_init(QemuOpts *opts)
exit(1);
}
text_consoles[n_text_consoles] = chr;
- text_console_opts[n_text_consoles] = opts;
n_text_consoles++;
width = qemu_opt_get_number(opts, "width", 0);
@@ -1555,9 +1553,7 @@ void text_consoles_set_display(DisplayState *ds)
int i;
for (i = 0; i < n_text_consoles; i++) {
- text_console_do_init(text_consoles[i], ds, text_console_opts[i]);
- qemu_opts_del(text_console_opts[i]);
- text_console_opts[i] = NULL;
+ text_console_do_init(text_consoles[i], ds);
}
n_text_consoles = 0;
commit 4104833f51e9c2e7a3def0411e48159e77bf7906
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Thu Dec 23 13:42:52 2010 +0100
add set_echo implementation for text consoles
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/console.c b/console.c
index 42c2ee3..60b80ee 100644
--- a/console.c
+++ b/console.c
@@ -137,6 +137,7 @@ struct TextConsole {
TextAttributes t_attrib; /* currently active text attributes */
TextCell *cells;
int text_x[2], text_y[2], cursor_invalidate;
+ int echo;
int update_x0;
int update_y0;
@@ -1177,8 +1178,14 @@ void kbd_put_keysym(int keysym)
*q++ = '\033';
*q++ = '[';
*q++ = keysym & 0xff;
+ } else if (s->echo && (keysym == '\r' || keysym == '\n')) {
+ console_puts(s->chr, (const uint8_t *) "\r", 1);
+ *q++ = '\n';
} else {
- *q++ = keysym;
+ *q++ = keysym;
+ }
+ if (s->echo) {
+ console_puts(s->chr, buf, q - buf);
}
if (s->chr->chr_read) {
qemu_fifo_write(&s->out_fifo, buf, q - buf);
@@ -1432,6 +1439,13 @@ static int n_text_consoles;
static CharDriverState *text_consoles[128];
static QemuOpts *text_console_opts[128];
+static void text_console_set_echo(CharDriverState *chr, bool echo)
+{
+ TextConsole *s = chr->opaque;
+
+ s->echo = echo;
+}
+
static void text_console_do_init(CharDriverState *chr, DisplayState *ds, QemuOpts *opts)
{
TextConsole *s;
@@ -1532,6 +1546,7 @@ CharDriverState *text_console_init(QemuOpts *opts)
s->g_width = width;
s->g_height = height;
chr->opaque = s;
+ chr->chr_set_echo = text_console_set_echo;
return chr;
}
commit 491e114a953d746b5787e72516d052aef0b67bc4
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Thu Dec 23 13:42:51 2010 +0100
create TextConsole together with the CharDeviceState
A nicer solution would be to get rid of the opaque pointer and
use containment, but it would also be a much bigger patch.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/console.c b/console.c
index c1728b1..42c2ee3 100644
--- a/console.c
+++ b/console.c
@@ -1435,35 +1435,13 @@ static QemuOpts *text_console_opts[128];
static void text_console_do_init(CharDriverState *chr, DisplayState *ds, QemuOpts *opts)
{
TextConsole *s;
- unsigned width;
- unsigned height;
static int color_inited;
- width = qemu_opt_get_number(opts, "width", 0);
- if (width == 0)
- width = qemu_opt_get_number(opts, "cols", 0) * FONT_WIDTH;
-
- height = qemu_opt_get_number(opts, "height", 0);
- if (height == 0)
- height = qemu_opt_get_number(opts, "rows", 0) * FONT_HEIGHT;
-
- if (width == 0 || height == 0) {
- s = new_console(ds, TEXT_CONSOLE);
- width = ds_get_width(s->ds);
- height = ds_get_height(s->ds);
- } else {
- s = new_console(ds, TEXT_CONSOLE_FIXED_SIZE);
- }
+ s = chr->opaque;
- if (!s) {
- free(chr);
- return;
- }
- chr->opaque = s;
chr->chr_write = console_puts;
chr->chr_send_event = console_send_event;
- s->chr = chr;
s->out_fifo.buf = s->out_fifo_buf;
s->out_fifo.buf_size = sizeof(s->out_fifo_buf);
s->kbd_timer = qemu_new_timer(rt_clock, kbd_send_chars, s);
@@ -1478,8 +1456,10 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds, QemuOpt
s->total_height = DEFAULT_BACKSCROLL;
s->x = 0;
s->y = 0;
- s->g_width = width;
- s->g_height = height;
+ if (s->console_type == TEXT_CONSOLE) {
+ s->g_width = ds_get_width(s->ds);
+ s->g_height = ds_get_height(s->ds);
+ }
s->hw_invalidate = text_console_invalidate;
s->hw_text_update = text_console_update;
@@ -1515,6 +1495,9 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds, QemuOpt
CharDriverState *text_console_init(QemuOpts *opts)
{
CharDriverState *chr;
+ TextConsole *s;
+ unsigned width;
+ unsigned height;
chr = qemu_mallocz(sizeof(CharDriverState));
@@ -1526,6 +1509,29 @@ CharDriverState *text_console_init(QemuOpts *opts)
text_console_opts[n_text_consoles] = opts;
n_text_consoles++;
+ width = qemu_opt_get_number(opts, "width", 0);
+ if (width == 0)
+ width = qemu_opt_get_number(opts, "cols", 0) * FONT_WIDTH;
+
+ height = qemu_opt_get_number(opts, "height", 0);
+ if (height == 0)
+ height = qemu_opt_get_number(opts, "rows", 0) * FONT_HEIGHT;
+
+ if (width == 0 || height == 0) {
+ s = new_console(NULL, TEXT_CONSOLE);
+ } else {
+ s = new_console(NULL, TEXT_CONSOLE_FIXED_SIZE);
+ }
+
+ if (!s) {
+ free(chr);
+ return NULL;
+ }
+
+ s->chr = chr;
+ s->g_width = width;
+ s->g_height = height;
+ chr->opaque = s;
return chr;
}
commit bb002513a9bd2bff169c3d431a8f00c5b2e3aa99
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Thu Dec 23 13:42:50 2010 +0100
add set_echo implementation for qemu_chr_stdio
This also requires moving QemuOpts out of term_init.
Clearing ISIG is independent of whether echo is enabled or disabled.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/qemu-char.c b/qemu-char.c
index a6ea516..bb0c32d 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -716,6 +716,7 @@ static void stdio_read(void *opaque)
/* init terminal so that we can grab keys */
static struct termios oldtty;
static int old_fd0_flags;
+static bool stdio_allow_signal;
static void term_exit(void)
{
@@ -723,22 +724,24 @@ static void term_exit(void)
fcntl(0, F_SETFL, old_fd0_flags);
}
-static void term_init(QemuOpts *opts)
+static void qemu_chr_set_echo_stdio(CharDriverState *chr, bool echo)
{
struct termios tty;
tty = oldtty;
- tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
+ if (!echo) {
+ tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
|INLCR|IGNCR|ICRNL|IXON);
- tty.c_oflag |= OPOST;
- tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
+ tty.c_oflag |= OPOST;
+ tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
+ tty.c_cflag &= ~(CSIZE|PARENB);
+ tty.c_cflag |= CS8;
+ tty.c_cc[VMIN] = 1;
+ tty.c_cc[VTIME] = 0;
+ }
/* if graphical mode, we allow Ctrl-C handling */
- if (!qemu_opt_get_bool(opts, "signal", display_type != DT_NOGRAPHIC))
+ if (!stdio_allow_signal)
tty.c_lflag &= ~ISIG;
- tty.c_cflag &= ~(CSIZE|PARENB);
- tty.c_cflag |= CS8;
- tty.c_cc[VMIN] = 1;
- tty.c_cc[VTIME] = 0;
tcsetattr (0, TCSANOW, &tty);
}
@@ -766,9 +769,12 @@ static CharDriverState *qemu_chr_open_stdio(QemuOpts *opts)
chr = qemu_chr_open_fd(0, 1);
chr->chr_close = qemu_chr_close_stdio;
+ chr->chr_set_echo = qemu_chr_set_echo_stdio;
qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, chr);
stdio_nb_clients++;
- term_init(opts);
+ stdio_allow_signal = qemu_opt_get_bool(opts, "signal",
+ display_type != DT_NOGRAPHIC);
+ qemu_chr_set_echo(chr, false);
return chr;
}
commit 0369364be871f9c4b4429a69ddcd2ba21be34ea3
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Thu Dec 23 13:42:49 2010 +0100
move atexit(term_exit) and O_NONBLOCK to qemu_chr_open_stdio
In the next patch, term_init will be changed to enable or disable
echo at will. Move extraneous stuff out of it.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/qemu-char.c b/qemu-char.c
index b95cfdc..a6ea516 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -716,7 +716,6 @@ static void stdio_read(void *opaque)
/* init terminal so that we can grab keys */
static struct termios oldtty;
static int old_fd0_flags;
-static int term_atexit_done;
static void term_exit(void)
{
@@ -728,10 +727,7 @@ static void term_init(QemuOpts *opts)
{
struct termios tty;
- tcgetattr (0, &tty);
- oldtty = tty;
- old_fd0_flags = fcntl(0, F_GETFL);
-
+ tty = oldtty;
tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
|INLCR|IGNCR|ICRNL|IXON);
tty.c_oflag |= OPOST;
@@ -745,11 +741,6 @@ static void term_init(QemuOpts *opts)
tty.c_cc[VTIME] = 0;
tcsetattr (0, TCSANOW, &tty);
-
- if (!term_atexit_done++)
- atexit(term_exit);
-
- fcntl(0, F_SETFL, O_NONBLOCK);
}
static void qemu_chr_close_stdio(struct CharDriverState *chr)
@@ -766,6 +757,13 @@ static CharDriverState *qemu_chr_open_stdio(QemuOpts *opts)
if (stdio_nb_clients >= STDIO_MAX_CLIENTS)
return NULL;
+ if (stdio_nb_clients == 0) {
+ old_fd0_flags = fcntl(0, F_GETFL);
+ tcgetattr (0, &oldtty);
+ fcntl(0, F_SETFL, O_NONBLOCK);
+ atexit(term_exit);
+ }
+
chr = qemu_chr_open_fd(0, 1);
chr->chr_close = qemu_chr_close_stdio;
qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, chr);
commit c48855e1404e9b5857e07b7839f806fa98b4abdc
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Thu Dec 23 13:42:48 2010 +0100
add qemu_chr_set_echo
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/monitor.c b/monitor.c
index 34c347c..7fc311d 100644
--- a/monitor.c
+++ b/monitor.c
@@ -5175,6 +5175,7 @@ void monitor_init(CharDriverState *chr, int flags)
/* Control mode requires special handlers */
qemu_chr_add_handlers(chr, monitor_can_read, monitor_control_read,
monitor_control_event, mon);
+ qemu_chr_set_echo(chr, true);
} else {
qemu_chr_add_handlers(chr, monitor_can_read, monitor_read,
monitor_event, mon);
diff --git a/qemu-char.c b/qemu-char.c
index b570d60..b95cfdc 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2558,6 +2558,13 @@ CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*i
return chr;
}
+void qemu_chr_set_echo(struct CharDriverState *chr, bool echo)
+{
+ if (chr->chr_set_echo) {
+ chr->chr_set_echo(chr, echo);
+ }
+}
+
void qemu_chr_close(CharDriverState *chr)
{
QTAILQ_REMOVE(&chardevs, chr, next);
diff --git a/qemu-char.h b/qemu-char.h
index e6ee6c4..56d9954 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -64,6 +64,7 @@ struct CharDriverState {
void (*chr_send_event)(struct CharDriverState *chr, int event);
void (*chr_close)(struct CharDriverState *chr);
void (*chr_accept_input)(struct CharDriverState *chr);
+ void (*chr_set_echo)(struct CharDriverState *chr, bool echo);
void *opaque;
QEMUBH *bh;
char *label;
@@ -76,6 +77,7 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename);
CharDriverState *qemu_chr_open_opts(QemuOpts *opts,
void (*init)(struct CharDriverState *s));
CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*init)(struct CharDriverState *s));
+void qemu_chr_set_echo(struct CharDriverState *chr, bool echo);
void qemu_chr_close(CharDriverState *chr);
void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
GCC_FMT_ATTR(2, 3);
commit d55dbc3acdaf92b42c7fd077c8b6c1392131c043
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Thu Dec 23 13:42:47 2010 +0100
remove broken code for tty
This code is taking the settings for a serial port and moving it to
fd 0 when qemu exits. This is likely just cut-and-paste, rip it.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/qemu-char.c b/qemu-char.c
index acc7130..b570d60 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -1013,9 +1013,6 @@ static void tty_serial_init(int fd, int speed,
speed, parity, data_bits, stop_bits);
#endif
tcgetattr (fd, &tty);
- if (!term_atexit_done) {
- oldtty = tty;
- }
#define check_speed(val) if (speed <= val) { spd = B##val; break; }
speed = speed * 10 / 11;
@@ -1187,11 +1184,6 @@ static int tty_serial_ioctl(CharDriverState *chr, int cmd, void *arg)
return 0;
}
-static void tty_exit(void)
-{
- tcsetattr(0, TCSANOW, &oldtty);
-}
-
static void qemu_chr_close_tty(CharDriverState *chr)
{
FDCharDriver *s = chr->opaque;
@@ -1226,8 +1218,6 @@ static CharDriverState *qemu_chr_open_tty(QemuOpts *opts)
}
chr->chr_ioctl = tty_serial_ioctl;
chr->chr_close = qemu_chr_close_tty;
- if (!term_atexit_done++)
- atexit(tty_exit);
return chr;
}
#else /* ! __linux__ && ! __sun__ */
commit b3a98367eec7b2d87acca54ef5e4de3b0e0a7ed5
Merge: 9363ee3... c5999bf...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date: Tue Feb 1 15:23:24 2011 -0600
Merge remote branch 'qemu-kvm/uq/master' into staging
aliguori: fix build with !defined(KVM_CAP_ASYNC_PF)
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --cc target-i386/kvm.c
index 7dfc357,8e8880a..05010bb
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@@ -170,14 -160,15 +160,17 @@@ struct kvm_para_features
static int get_para_features(CPUState *env)
{
- int i, features = 0;
+ int i, features = 0;
- for (i = 0; i < ARRAY_SIZE(para_features) - 1; i++) {
- if (kvm_check_extension(env->kvm_state, para_features[i].cap))
- features |= (1 << para_features[i].feature);
+ for (i = 0; i < ARRAY_SIZE(para_features) - 1; i++) {
+ if (kvm_check_extension(env->kvm_state, para_features[i].cap)) {
+ features |= (1 << para_features[i].feature);
}
-
- return features;
+ }
++#ifdef KVM_CAP_ASYNC_PF
+ has_msr_async_pf_en = features & (1 << KVM_FEATURE_ASYNC_PF);
++#endif
+ return features;
}
#endif
commit 9363ee31ab53fc0fd39fbe5936d9c00a2f4e54a4
Merge: cfb41c8... cbcc633...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date: Tue Feb 1 15:22:48 2011 -0600
Merge remote branch 'spice/spice.v29.pull' into staging
Conflicts:
trace-events
diff --cc trace-events
index c75a7a9,ed754f5..e6138ea
--- a/trace-events
+++ b/trace-events
@@@ -225,26 -225,8 +225,32 @@@ disable qed_aio_write_prefill(void *s,
disable qed_aio_write_postfill(void *s, void *acb, uint64_t start, size_t len, uint64_t offset) "s %p acb %p start %"PRIu64" len %zu offset %"PRIu64""
disable qed_aio_write_main(void *s, void *acb, int ret, uint64_t offset, size_t len) "s %p acb %p ret %d offset %"PRIu64" len %zu"
+# hw/grlib_gptimer.c
+disable grlib_gptimer_enable(int id, uint32_t count) "timer:%d set count 0x%x and run"
+disable grlib_gptimer_disabled(int id, uint32_t config) "timer:%d Timer disable config 0x%x"
+disable grlib_gptimer_restart(int id, uint32_t reload) "timer:%d reload val: 0x%x"
+disable grlib_gptimer_set_scaler(uint32_t scaler, uint32_t freq) "scaler:0x%x freq: 0x%x"
+disable grlib_gptimer_hit(int id) "timer:%d HIT"
+disable grlib_gptimer_readl(int id, const char *s, uint32_t val) "timer:%d %s 0x%x"
+disable grlib_gptimer_writel(int id, const char *s, uint32_t val) "timer:%d %s 0x%x"
+disable grlib_gptimer_unknown_register(const char *op, uint64_t val) "%s unknown register 0x%"PRIx64""
+
+# hw/grlib_irqmp.c
+disable grlib_irqmp_check_irqs(uint32_t pend, uint32_t force, uint32_t mask, uint32_t lvl1, uint32_t lvl2) "pend:0x%04x force:0x%04x mask:0x%04x lvl1:0x%04x lvl0:0x%04x\n"
+disable grlib_irqmp_ack(int intno) "interrupt:%d"
+disable grlib_irqmp_set_irq(int irq) "Raise CPU IRQ %d"
+disable grlib_irqmp_unknown_register(const char *op, uint64_t val) "%s unknown register 0x%"PRIx64""
+
+# hw/grlib_apbuart.c
+disable grlib_apbuart_event(int event) "event:%d"
+disable grlib_apbuart_unknown_register(const char *op, uint64_t val) "%s unknown register 0x%"PRIx64""
+
+# hw/leon3.c
+disable leon3_set_irq(int intno) "Set CPU IRQ %d"
+disable leon3_reset_irq(int intno) "Reset CPU IRQ %d"
++
+ # spice-qemu-char.c
+ disable spice_vmc_write(ssize_t out, int len) "spice wrottn %lu of requested %zd"
+ disable spice_vmc_read(int bytes, int len) "spice read %lu of requested %zd"
+ disable spice_vmc_register_interface(void *scd) "spice vmc registered interface %p"
+ disable spice_vmc_unregister_interface(void *scd) "spice vmc unregistered interface %p"
commit cfb41c82ab9c468e599d3603ffcebeb81b6577ca
Merge: e54b7f5... ea87e95...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date: Tue Feb 1 15:21:23 2011 -0600
Merge remote branch 'spice/usb.5' into staging
commit e54b7f5256659dddaf6b5c021847859829d7ebd7
Merge: 1cd20f8... 37f95bf...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date: Tue Feb 1 15:20:56 2011 -0600
Merge remote branch 'amit/for-anthony' into staging
commit 1cd20f8bf0ecb9d1d1bd5e2ffab3b88835380c9b
Author: Anthony Liguori <aliguori at us.ibm.com>
Date: Mon Jan 31 14:27:36 2011 -0600
vnc: Fix password expiration through 'change vnc ""' (v2)
commit 52c18be9e99dabe295321153fda7fce9f76647ac introduced a regression in the
change vnc password command that changed the behavior of setting the VNC
password to an empty string from disabling login to disabling authentication.
This commit refactors the code to eliminate this overloaded semantics in
vnc_display_password and instead introduces the vnc_display_disable_login. The
monitor implementation then determines the behavior of an empty or missing
string.
Recently, a set_password command was added that allows both the Spice and VNC
password to be set. This command has not shown up in a release yet so the
behavior is not yet defined.
This patch proposes that an empty password be treated as an empty password with
no special handling. For specifically disabling login, I believe a new command
should be introduced instead of overloading semantics.
I'm not sure how Spice handles this but I would recommend that we have Spice
and VNC have consistent semantics here for the 0.14.0 release.
Reported-by: Neil Wilson <neil at aldur.co.uk>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
---
v1 -> v2
- Add a proper return to make sure that login is really disabled instead of
relying on the VNC server to treat empty passwords specially
diff --git a/console.h b/console.h
index 3157330..f4e4741 100644
--- a/console.h
+++ b/console.h
@@ -369,6 +369,7 @@ void vnc_display_init(DisplayState *ds);
void vnc_display_close(DisplayState *ds);
int vnc_display_open(DisplayState *ds, const char *display);
int vnc_display_password(DisplayState *ds, const char *password);
+int vnc_display_disable_login(DisplayState *ds);
int vnc_display_pw_expire(DisplayState *ds, time_t expires);
void do_info_vnc_print(Monitor *mon, const QObject *data);
void do_info_vnc(Monitor *mon, QObject **ret_data);
diff --git a/monitor.c b/monitor.c
index c5f54f4..64e41e3 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1018,6 +1018,14 @@ static int do_quit(Monitor *mon, const QDict *qdict, QObject **ret_data)
static int change_vnc_password(const char *password)
{
+ if (!password || !password[0]) {
+ if (vnc_display_disable_login(NULL)) {
+ qerror_report(QERR_SET_PASSWD_FAILED);
+ return -1;
+ }
+ return 0;
+ }
+
if (vnc_display_password(NULL, password) < 0) {
qerror_report(QERR_SET_PASSWD_FAILED);
return -1;
@@ -1117,6 +1125,8 @@ static int set_password(Monitor *mon, const QDict *qdict, QObject **ret_data)
qerror_report(QERR_INVALID_PARAMETER, "connected");
return -1;
}
+ /* Note that setting an empty password will not disable login through
+ * this interface. */
rc = vnc_display_password(NULL, password);
if (rc != 0) {
qerror_report(QERR_SET_PASSWD_FAILED);
diff --git a/ui/vnc.c b/ui/vnc.c
index 495d6d6..8067b31 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -2084,7 +2084,7 @@ static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
unsigned char key[8];
time_t now = time(NULL);
- if (!vs->vd->password || !vs->vd->password[0]) {
+ if (!vs->vd->password) {
VNC_DEBUG("No password configured on server");
goto reject;
}
@@ -2484,6 +2484,24 @@ void vnc_display_close(DisplayState *ds)
#endif
}
+int vnc_display_disable_login(DisplayState *ds)
+{
+ VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
+
+ if (!vs) {
+ return -1;
+ }
+
+ if (vs->password) {
+ qemu_free(vs->password);
+ }
+
+ vs->password = NULL;
+ vs->auth = VNC_AUTH_VNC;
+
+ return 0;
+}
+
int vnc_display_password(DisplayState *ds, const char *password)
{
VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
@@ -2492,19 +2510,18 @@ int vnc_display_password(DisplayState *ds, const char *password)
return -1;
}
+ if (!password) {
+ /* This is not the intention of this interface but err on the side
+ of being safe */
+ return vnc_display_disable_login(ds);
+ }
+
if (vs->password) {
qemu_free(vs->password);
vs->password = NULL;
}
- if (password && password[0]) {
- if (!(vs->password = qemu_strdup(password)))
- return -1;
- if (vs->auth == VNC_AUTH_NONE) {
- vs->auth = VNC_AUTH_VNC;
- }
- } else {
- vs->auth = VNC_AUTH_NONE;
- }
+ vs->password = qemu_strdup(password);
+ vs->auth = VNC_AUTH_VNC;
return 0;
}
commit e321c34aa1d2560bea4d525af66417147467c515
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Tue Feb 1 15:54:52 2011 +0000
linux-user: avoid gcc array overrun warning for sparc
Suppress a gcc array bounds overrun warning when filling in the SPARC
signal frame by adjusting our definition of the structure so that the
fp and callers_pc membes are part of the ins[] array rather than
separate fields; since qemu has no need to access the fields individually
there is no need to follow the kernel's structure field naming exactly.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/linux-user/signal.c b/linux-user/signal.c
index 0664770..b01bd64 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -1817,9 +1817,10 @@ struct target_sigcontext {
/* A Sparc stack frame */
struct sparc_stackf {
abi_ulong locals[8];
- abi_ulong ins[6];
- struct sparc_stackf *fp;
- abi_ulong callers_pc;
+ abi_ulong ins[8];
+ /* It's simpler to treat fp and callers_pc as elements of ins[]
+ * since we never need to access them ourselves.
+ */
char *structptr;
abi_ulong xargs[6];
abi_ulong xxargs[1];
commit c84a88d8cb298b6757ad01a12a8bbba66cb6eaa2
Author: Peter Maydell <peter.maydell at linaro.org>
Date: Mon Jan 31 10:42:26 2011 +0000
hw/slavio_intctl.c: fix gcc warning about array bounds overrun
The Ubuntu 10.10 gcc for ARM complains that we might be overrunning
the cpu_irqs[][] array: silence this by correcting the bounds on the
loop. (In fact we would not have overrun the array because bit
MAX_PILS in pil_pending and irl_out will always be 0.)
Also add a comment about why the loop's lower bound is OK.
Signed-off-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/slavio_intctl.c b/hw/slavio_intctl.c
index fd69354..a83e5b8 100644
--- a/hw/slavio_intctl.c
+++ b/hw/slavio_intctl.c
@@ -289,7 +289,12 @@ static void slavio_check_interrupts(SLAVIO_INTCTLState *s, int set_irqs)
pil_pending |= (s->slaves[i].intreg_pending & CPU_SOFTIRQ_MASK) >> 16;
if (set_irqs) {
- for (j = MAX_PILS; j > 0; j--) {
+ /* Since there is not really an interrupt 0 (and pil_pending
+ * and irl_out bit zero are thus always zero) there is no need
+ * to do anything with cpu_irqs[i][0] and it is OK not to do
+ * the j=0 iteration of this loop.
+ */
+ for (j = MAX_PILS-1; j > 0; j--) {
if (pil_pending & (1 << j)) {
if (!(s->slaves[i].irl_out & (1 << j))) {
qemu_irq_raise(s->cpu_irqs[i][j]);
commit 60f356e86d66a4a22530ec7570f7582af602d200
Author: Fabien Chouteau <chouteau at adacore.com>
Date: Mon Jan 31 11:36:54 2011 +0100
SPARC: Fix Leon3 cache control
The "leon3_cache_control_int" (op_helper.c) function is called within leon3.c
which leads to segfault error with the global "env".
Now cache control is a CPU feature and everything is handled in op_helper.c.
Signed-off-by: Fabien Chouteau <chouteau at adacore.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/leon3.c b/hw/leon3.c
index 69d8f3b..919f49f 100644
--- a/hw/leon3.c
+++ b/hw/leon3.c
@@ -56,10 +56,9 @@ static void main_cpu_reset(void *opaque)
env->npc = s->entry + 4;
}
-static void leon3_irq_ack(void *irq_manager, int intno)
+void leon3_irq_ack(void *irq_manager, int intno)
{
grlib_irqmp_ack((DeviceState *)irq_manager, intno);
- leon3_cache_control_int();
}
static void leon3_set_pil_in(void *opaque, uint32_t pil_in)
@@ -130,7 +129,7 @@ static void leon3_generic_hw_init(ram_addr_t ram_size,
/* Allocate IRQ manager */
grlib_irqmp_create(0x80000200, env, &cpu_irqs, MAX_PILS, &leon3_set_pil_in);
- env->qemu_irq_ack = leon3_irq_ack;
+ env->qemu_irq_ack = leon3_irq_manager;
/* Allocate RAM */
if ((uint64_t)ram_size > (1UL << 30)) {
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 6f5990b..320530e 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -268,6 +268,8 @@ typedef struct sparc_def_t {
#define CPU_FEATURE_GL (1 << 13)
#define CPU_FEATURE_TA0_SHUTDOWN (1 << 14) /* Shutdown on "ta 0x0" */
#define CPU_FEATURE_ASR17 (1 << 15)
+#define CPU_FEATURE_CACHE_CTRL (1 << 16)
+
#ifndef TARGET_SPARC64
#define CPU_DEFAULT_FEATURES (CPU_FEATURE_FLOAT | CPU_FEATURE_SWAP | \
CPU_FEATURE_MUL | CPU_FEATURE_DIV | \
@@ -476,12 +478,14 @@ void cpu_put_cwp64(CPUState *env1, int cwp);
int cpu_cwp_inc(CPUState *env1, int cwp);
int cpu_cwp_dec(CPUState *env1, int cwp);
void cpu_set_cwp(CPUState *env1, int new_cwp);
-
-void leon3_cache_control_int(void);
+void leon3_irq_manager(void *irq_manager, int intno);
/* sun4m.c, sun4u.c */
void cpu_check_irqs(CPUSPARCState *env);
+/* leon3.c */
+void leon3_irq_ack(void *irq_manager, int intno);
+
#if defined (TARGET_SPARC64)
static inline int compare_masked(uint64_t x, uint64_t y, uint64_t mask)
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 2f3d1e6..b2d4d70 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -1289,7 +1289,7 @@ static const sparc_def_t sparc_defs[] = {
.mmu_trcr_mask = 0xffffffff,
.nwindows = 8,
.features = CPU_DEFAULT_FEATURES | CPU_FEATURE_TA0_SHUTDOWN |
- CPU_FEATURE_ASR17,
+ CPU_FEATURE_ASR17 | CPU_FEATURE_CACHE_CTRL,
},
#endif
};
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index d3e1b63..854f168 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -1653,7 +1653,7 @@ static void dump_asi(const char *txt, target_ulong addr, int asi, int size,
/* Leon3 cache control */
-void leon3_cache_control_int(void)
+static void leon3_cache_control_int(void)
{
uint32_t state = 0;
@@ -1741,11 +1741,17 @@ static uint64_t leon3_cache_control_ld(target_ulong addr, int size)
DPRINTF_CACHE_CONTROL("read unknown register %08x\n", addr);
break;
};
- DPRINTF_CACHE_CONTROL("st addr:%08x, ret:%" PRIx64 ", size:%d\n",
+ DPRINTF_CACHE_CONTROL("ld addr:%08x, ret:0x%" PRIx64 ", size:%d\n",
addr, ret, size);
return ret;
}
+void leon3_irq_manager(void *irq_manager, int intno)
+{
+ leon3_irq_ack(irq_manager, intno);
+ leon3_cache_control_int();
+}
+
uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
{
uint64_t ret = 0;
@@ -1760,7 +1766,9 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
case 0x00: /* Leon3 Cache Control */
case 0x08: /* Leon3 Instruction Cache config */
case 0x0C: /* Leon3 Date Cache config */
- ret = leon3_cache_control_ld(addr, size);
+ if (env->def->features & CPU_FEATURE_CACHE_CTRL) {
+ ret = leon3_cache_control_ld(addr, size);
+ }
break;
case 0x01c00a00: /* MXCC control register */
if (size == 8)
@@ -1994,7 +2002,9 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
case 0x00: /* Leon3 Cache Control */
case 0x08: /* Leon3 Instruction Cache config */
case 0x0C: /* Leon3 Date Cache config */
- leon3_cache_control_st(addr, val, size);
+ if (env->def->features & CPU_FEATURE_CACHE_CTRL) {
+ leon3_cache_control_st(addr, val, size);
+ }
break;
case 0x01c00000: /* MXCC stream data register 0 */
commit 2685d2961b51437d0c7bc71f4ed7c320f6cbd010
Merge: 319ae52... 4c90051...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date: Mon Jan 31 12:07:17 2011 -0600
Merge remote branch 'mst/for_anthony' into staging
commit 319ae529b8d55ea60b1036809aaab2130048d0e1
Author: Markus Armbruster <armbru at redhat.com>
Date: Fri Jan 28 11:21:46 2011 +0100
blockdev: Fix drive_add for drives without media
Watch this:
(qemu) drive_add 0 if=none
(qemu) info block
none0: type=hd removable=0 [not inserted]
(qemu) drive_del none0
Segmentation fault (core dumped)
add_init_drive() is confused about drive_init()'s failure modes, and
cleans up when it shouldn't. This leaves the DriveInfo with member
opts dangling. drive_del attempts to free it, and dies.
drive_init() behaves as follows:
* If it created a drive with media, it returns its DriveInfo.
* If it created a drive without media, it clears *fatal_error and
returns NULL.
* If it couldn't create a drive, it sets *fatal_error and returns
NULL.
Of its three callers:
* drive_init_func() is correct.
* usb_msd_init() assumes drive_init() failed when it returns NULL.
This is correct only because it always passes option "file", and
"drive without media" can't happen then.
* add_init_drive() assumes drive_init() failed when it returns NULL.
This is incorrect.
Clean up drive_init() to return NULL on failure and only on failure.
Drop its parameter fatal_error.
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/blockdev.c b/blockdev.c
index 4b2145c..1c56da0 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -203,7 +203,7 @@ static int parse_block_error_action(const char *buf, int is_read)
}
}
-DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
+DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
{
const char *buf;
const char *file = NULL;
@@ -225,8 +225,6 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
int snapshot = 0;
int ret;
- *fatal_error = 1;
-
translation = BIOS_ATA_TRANSLATION_AUTO;
if (default_to_scsi) {
@@ -499,8 +497,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
abort();
}
if (!file || !*file) {
- *fatal_error = 0;
- return NULL;
+ return dinfo;
}
if (snapshot) {
/* always use cache=unsafe with snapshot */
@@ -529,7 +526,6 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
if (bdrv_key_required(dinfo->bdrv))
autostart = 0;
- *fatal_error = 0;
return dinfo;
}
diff --git a/blockdev.h b/blockdev.h
index e5d8c56..84e462a 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -48,7 +48,7 @@ DriveInfo *drive_get_by_blockdev(BlockDriverState *bs);
QemuOpts *drive_def(const char *optstr);
QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file,
const char *optstr);
-DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi, int *fatal_error);
+DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi);
/* device-hotplug */
diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c
index 95a6372..8b2ed7a 100644
--- a/hw/device-hotplug.c
+++ b/hw/device-hotplug.c
@@ -29,7 +29,6 @@
DriveInfo *add_init_drive(const char *optstr)
{
- int fatal_error;
DriveInfo *dinfo;
QemuOpts *opts;
@@ -37,7 +36,7 @@ DriveInfo *add_init_drive(const char *optstr)
if (!opts)
return NULL;
- dinfo = drive_init(opts, current_machine->use_scsi, &fatal_error);
+ dinfo = drive_init(opts, current_machine->use_scsi);
if (!dinfo) {
qemu_opts_del(opts);
return NULL;
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 11722c7..97d1e4a 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -542,7 +542,6 @@ static USBDevice *usb_msd_init(const char *filename)
QemuOpts *opts;
DriveInfo *dinfo;
USBDevice *dev;
- int fatal_error;
const char *p1;
char fmt[32];
@@ -572,7 +571,7 @@ static USBDevice *usb_msd_init(const char *filename)
qemu_opt_set(opts, "if", "none");
/* create host drive */
- dinfo = drive_init(opts, 0, &fatal_error);
+ dinfo = drive_init(opts, 0);
if (!dinfo) {
qemu_opts_del(opts);
return NULL;
diff --git a/vl.c b/vl.c
index f86724f..ce5708b 100644
--- a/vl.c
+++ b/vl.c
@@ -631,13 +631,8 @@ static int bt_parse(const char *opt)
static int drive_init_func(QemuOpts *opts, void *opaque)
{
int *use_scsi = opaque;
- int fatal_error = 0;
- if (drive_init(opts, *use_scsi, &fatal_error) == NULL) {
- if (fatal_error)
- return 1;
- }
- return 0;
+ return drive_init(opts, *use_scsi) == NULL;
}
static int drive_enable_snapshot(QemuOpts *opts, void *opaque)
@@ -666,7 +661,7 @@ static void default_drive(int enable, int snapshot, int use_scsi,
if (snapshot) {
drive_enable_snapshot(opts, NULL);
}
- if (drive_init_func(opts, &use_scsi)) {
+ if (!drive_init(opts, use_scsi)) {
exit(1);
}
}
commit 5645b0f4f2185437d8df03810ce9c102cc4c90db
Author: Markus Armbruster <armbru at redhat.com>
Date: Mon Jan 31 11:50:09 2011 +0100
blockdev: Replace drive_add()'s fmt, ... by optstr parameter
Let the callers build the optstr. Only one wants to. All the others
become simpler, because they don't have to worry about escaping '%'.
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/blockdev.c b/blockdev.c
index 3f7b560..4b2145c 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -93,17 +93,11 @@ QemuOpts *drive_def(const char *optstr)
}
QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file,
- const char *fmt, ...)
+ const char *optstr)
{
- va_list ap;
- char optstr[1024];
QemuOpts *opts;
char buf[32];
- va_start(ap, fmt);
- vsnprintf(optstr, sizeof(optstr), fmt, ap);
- va_end(ap);
-
opts = drive_def(optstr);
if (!opts) {
return NULL;
diff --git a/blockdev.h b/blockdev.h
index 18278cc..e5d8c56 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -47,10 +47,7 @@ DriveInfo *drive_get_by_blockdev(BlockDriverState *bs);
QemuOpts *drive_def(const char *optstr);
QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file,
- const char *fmt, ...) /*GCC_FMT_ATTR(4, 5)*/;
- /* GCC_FMT_ATTR() commented out to avoid the (pretty useless)
- * "zero-length gnu_printf format string" warning we insist to
- * enable */
+ const char *optstr);
DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi, int *fatal_error);
/* device-hotplug */
diff --git a/vl.c b/vl.c
index 99f5bfe..f86724f 100644
--- a/vl.c
+++ b/vl.c
@@ -621,7 +621,6 @@ static int bt_parse(const char *opt)
/***********************************************************/
/* QEMU Block devices */
-/* Any % in the following strings must be escaped as %% */
#define HD_OPTS "media=disk"
#define CDROM_OPTS "media=cdrom"
#define FD_OPTS ""
@@ -2050,17 +2049,21 @@ int main(int argc, char **argv, char **envp)
initrd_filename = optarg;
break;
case QEMU_OPTION_hda:
- if (cyls == 0)
- hda_opts = drive_add(IF_DEFAULT, 0, optarg, HD_OPTS);
- else
- hda_opts = drive_add(IF_DEFAULT, 0, optarg, HD_OPTS
- ",cyls=%d,heads=%d,secs=%d%s",
- cyls, heads, secs,
- translation == BIOS_ATA_TRANSLATION_LBA ?
+ {
+ char buf[256];
+ if (cyls == 0)
+ snprintf(buf, sizeof(buf), "%s", HD_OPTS);
+ else
+ snprintf(buf, sizeof(buf),
+ "%s,cyls=%d,heads=%d,secs=%d%s",
+ HD_OPTS , cyls, heads, secs,
+ translation == BIOS_ATA_TRANSLATION_LBA ?
",trans=lba" :
- translation == BIOS_ATA_TRANSLATION_NONE ?
+ translation == BIOS_ATA_TRANSLATION_NONE ?
",trans=none" : "");
- break;
+ drive_add(IF_DEFAULT, 0, optarg, buf);
+ break;
+ }
case QEMU_OPTION_hdb:
case QEMU_OPTION_hdc:
case QEMU_OPTION_hdd:
commit 4e5d9b578f5d5ffbf7ef7e26abed23a0548a853a
Author: Markus Armbruster <armbru at redhat.com>
Date: Fri Jan 28 11:21:45 2011 +0100
blockdev: Reject multiple definitions for the same drive
We silently ignore multiple definitions for the same drive:
$ qemu-system-x86_64 -nodefaults -vnc :1 -S -monitor stdio -drive if=ide,index=1,file=tmp.qcow2 -drive if=ide,index=1,file=nonexistant
QEMU 0.13.50 monitor - type 'help' for more information
(qemu) info block
ide0-hd1: type=hd removable=0 file=tmp.qcow2 backing_file=tmp.img ro=0 drv=qcow2 encrypted=0
With if=none, this can become quite confusing:
$ qemu-system-x86_64 -nodefaults -vnc :1 -S -monitor stdio -drive if=none,index=1,file=tmp.qcow2,id=eins -drive if=none,index=1,file=nonexistant,id=zwei -device ide-drive,drive=eins -device ide-drive,drive=zwei
qemu-system-x86_64: -device ide-drive,drive=zwei: Property 'ide-drive.drive' can't find value 'zwei'
The second -device fails, because it refers to drive zwei, which got
silently ignored.
Make multiple drive definitions fail cleanly.
Unfortunately, there's code that relies on multiple drive definitions
being silently ignored: main() merrily adds default drives even when
the user already defined these drives. Fix that up.
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/blockdev.c b/blockdev.c
index 01228f6..3f7b560 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -429,11 +429,12 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
}
/*
- * ignore multiple definitions
+ * catch multiple definitions
*/
if (drive_get(type, bus_id, unit_id) != NULL) {
- *fatal_error = 0;
+ error_report("drive with bus=%d, unit=%d (index=%d) exists",
+ bus_id, unit_id, index);
return NULL;
}
diff --git a/vl.c b/vl.c
index 5399e33..99f5bfe 100644
--- a/vl.c
+++ b/vl.c
@@ -649,6 +649,29 @@ static int drive_enable_snapshot(QemuOpts *opts, void *opaque)
return 0;
}
+static void default_drive(int enable, int snapshot, int use_scsi,
+ BlockInterfaceType type, int index,
+ const char *optstr)
+{
+ QemuOpts *opts;
+
+ if (type == IF_DEFAULT) {
+ type = use_scsi ? IF_SCSI : IF_IDE;
+ }
+
+ if (!enable || drive_get_by_index(type, index)) {
+ return;
+ }
+
+ opts = drive_add(type, index, NULL, optstr);
+ if (snapshot) {
+ drive_enable_snapshot(opts, NULL);
+ }
+ if (drive_init_func(opts, &use_scsi)) {
+ exit(1);
+ }
+}
+
void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque)
{
boot_set_handler = func;
@@ -2893,27 +2916,19 @@ int main(int argc, char **argv, char **envp)
blk_mig_init();
- if (default_cdrom) {
- /* we always create the cdrom drive, even if no disk is there */
- drive_add(IF_DEFAULT, 2, NULL, CDROM_OPTS);
- }
-
- if (default_floppy) {
- /* we always create at least one floppy */
- drive_add(IF_FLOPPY, 0, NULL, FD_OPTS);
- }
-
- if (default_sdcard) {
- /* we always create one sd slot, even if no card is in it */
- drive_add(IF_SD, 0, NULL, SD_OPTS);
- }
-
/* open the virtual block devices */
if (snapshot)
qemu_opts_foreach(qemu_find_opts("drive"), drive_enable_snapshot, NULL, 0);
if (qemu_opts_foreach(qemu_find_opts("drive"), drive_init_func, &machine->use_scsi, 1) != 0)
exit(1);
+ default_drive(default_cdrom, snapshot, machine->use_scsi,
+ IF_DEFAULT, 2, CDROM_OPTS);
+ default_drive(default_floppy, snapshot, machine->use_scsi,
+ IF_FLOPPY, 0, FD_OPTS);
+ default_drive(default_sdcard, snapshot, machine->use_scsi,
+ IF_SD, 0, SD_OPTS);
+
register_savevm_live(NULL, "ram", 0, 4, NULL, ram_save_live, NULL,
ram_load, NULL);
commit f1bd51ac2b6e6ccd3d13dfd52c1c381a68bf261c
Author: Markus Armbruster <armbru at redhat.com>
Date: Fri Jan 28 11:21:44 2011 +0100
blockdev: New drive_get_by_index()
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/blockdev.c b/blockdev.c
index a42c5e4..01228f6 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -136,6 +136,13 @@ DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit)
return NULL;
}
+DriveInfo *drive_get_by_index(BlockInterfaceType type, int index)
+{
+ return drive_get(type,
+ drive_index_to_bus_id(type, index),
+ drive_index_to_unit_id(type, index));
+}
+
int drive_get_max_bus(BlockInterfaceType type)
{
int max_bus;
diff --git a/blockdev.h b/blockdev.h
index 0c01e08..18278cc 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -39,6 +39,7 @@ struct DriveInfo {
};
DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
+DriveInfo *drive_get_by_index(BlockInterfaceType type, int index);
int drive_get_max_bus(BlockInterfaceType type);
DriveInfo *drive_get_next(BlockInterfaceType type);
void drive_uninit(DriveInfo *dinfo);
commit 505a7fb1b1bfa732117d526a8d3a0f27741155d6
Author: Markus Armbruster <armbru at redhat.com>
Date: Fri Jan 28 11:21:43 2011 +0100
blockdev: Factor drive_index_to_{bus,unit}_id out of drive_init()
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/blockdev.c b/blockdev.c
index 6d828f2..a42c5e4 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -75,6 +75,18 @@ void blockdev_auto_del(BlockDriverState *bs)
}
}
+static int drive_index_to_bus_id(BlockInterfaceType type, int index)
+{
+ int max_devs = if_max_devs[type];
+ return max_devs ? index / max_devs : 0;
+}
+
+static int drive_index_to_unit_id(BlockInterfaceType type, int index)
+{
+ int max_devs = if_max_devs[type];
+ return max_devs ? index % max_devs : index;
+}
+
QemuOpts *drive_def(const char *optstr)
{
return qemu_opts_parse(qemu_find_opts("drive"), optstr, 0);
@@ -382,14 +394,8 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
error_report("index cannot be used with bus and unit");
return NULL;
}
- if (max_devs == 0)
- {
- unit_id = index;
- bus_id = 0;
- } else {
- unit_id = index % max_devs;
- bus_id = index / max_devs;
- }
+ bus_id = drive_index_to_bus_id(type, index);
+ unit_id = drive_index_to_unit_id(type, index);
}
/* if user doesn't specify a unit_id,
commit 2292ddaeab3467c68efd9e07e17ca0c9fc510fdc
Author: Markus Armbruster <armbru at redhat.com>
Date: Fri Jan 28 11:21:41 2011 +0100
blockdev: Make drive_add() take explicit type, index parameters
Before, type & index were hidden in printf-like fmt, ... parameters,
which get expanded into an option string. Rather inconvenient for
uses later in this series.
New IF_DEFAULT to ask for the machine's default interface. Before,
that was done by having no option "if" in the option string.
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/blockdev.c b/blockdev.c
index fba53f9..6d828f2 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -75,20 +75,34 @@ void blockdev_auto_del(BlockDriverState *bs)
}
}
-QemuOpts *drive_add(const char *file, const char *fmt, ...)
+QemuOpts *drive_def(const char *optstr)
+{
+ return qemu_opts_parse(qemu_find_opts("drive"), optstr, 0);
+}
+
+QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file,
+ const char *fmt, ...)
{
va_list ap;
char optstr[1024];
QemuOpts *opts;
+ char buf[32];
va_start(ap, fmt);
vsnprintf(optstr, sizeof(optstr), fmt, ap);
va_end(ap);
- opts = qemu_opts_parse(qemu_find_opts("drive"), optstr, 0);
+ opts = drive_def(optstr);
if (!opts) {
return NULL;
}
+ if (type != IF_DEFAULT) {
+ qemu_opt_set(opts, "if", if_name[type]);
+ }
+ if (index >= 0) {
+ snprintf(buf, sizeof(buf), "%d", index);
+ qemu_opt_set(opts, "index", buf);
+ }
if (file)
qemu_opt_set(opts, "file", file);
return opts;
@@ -473,7 +487,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
if (devaddr)
qemu_opt_set(opts, "addr", devaddr);
break;
- case IF_COUNT:
+ default:
abort();
}
if (!file || !*file) {
diff --git a/blockdev.h b/blockdev.h
index cf8fc01..0c01e08 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -19,6 +19,7 @@ void blockdev_auto_del(BlockDriverState *bs);
#define BLOCK_SERIAL_STRLEN 20
typedef enum {
+ IF_DEFAULT = -1, /* for use with drive_add() only */
IF_NONE,
IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN,
IF_COUNT
@@ -43,7 +44,12 @@ DriveInfo *drive_get_next(BlockInterfaceType type);
void drive_uninit(DriveInfo *dinfo);
DriveInfo *drive_get_by_blockdev(BlockDriverState *bs);
-QemuOpts *drive_add(const char *file, const char *fmt, ...) GCC_FMT_ATTR(2, 3);
+QemuOpts *drive_def(const char *optstr);
+QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file,
+ const char *fmt, ...) /*GCC_FMT_ATTR(4, 5)*/;
+ /* GCC_FMT_ATTR() commented out to avoid the (pretty useless)
+ * "zero-length gnu_printf format string" warning we insist to
+ * enable */
DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi, int *fatal_error);
/* device-hotplug */
diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c
index 9704e2f..95a6372 100644
--- a/hw/device-hotplug.c
+++ b/hw/device-hotplug.c
@@ -33,7 +33,7 @@ DriveInfo *add_init_drive(const char *optstr)
DriveInfo *dinfo;
QemuOpts *opts;
- opts = drive_add(NULL, "%s", optstr);
+ opts = drive_def(optstr);
if (!opts)
return NULL;
diff --git a/vl.c b/vl.c
index 14255c4..5399e33 100644
--- a/vl.c
+++ b/vl.c
@@ -621,12 +621,13 @@ static int bt_parse(const char *opt)
/***********************************************************/
/* QEMU Block devices */
-#define HD_ALIAS "index=%d,media=disk"
-#define CDROM_ALIAS "index=2,media=cdrom"
-#define FD_ALIAS "index=%d,if=floppy"
-#define PFLASH_ALIAS "if=pflash"
-#define MTD_ALIAS "if=mtd"
-#define SD_ALIAS "index=0,if=sd"
+/* Any % in the following strings must be escaped as %% */
+#define HD_OPTS "media=disk"
+#define CDROM_OPTS "media=cdrom"
+#define FD_OPTS ""
+#define PFLASH_OPTS ""
+#define MTD_OPTS ""
+#define SD_OPTS ""
static int drive_init_func(QemuOpts *opts, void *opaque)
{
@@ -1987,7 +1988,7 @@ int main(int argc, char **argv, char **envp)
if (optind >= argc)
break;
if (argv[optind][0] != '-') {
- hda_opts = drive_add(argv[optind++], HD_ALIAS, 0);
+ hda_opts = drive_add(IF_DEFAULT, 0, argv[optind++], HD_OPTS);
} else {
const QEMUOption *popt;
@@ -2027,11 +2028,11 @@ int main(int argc, char **argv, char **envp)
break;
case QEMU_OPTION_hda:
if (cyls == 0)
- hda_opts = drive_add(optarg, HD_ALIAS, 0);
+ hda_opts = drive_add(IF_DEFAULT, 0, optarg, HD_OPTS);
else
- hda_opts = drive_add(optarg, HD_ALIAS
+ hda_opts = drive_add(IF_DEFAULT, 0, optarg, HD_OPTS
",cyls=%d,heads=%d,secs=%d%s",
- 0, cyls, heads, secs,
+ cyls, heads, secs,
translation == BIOS_ATA_TRANSLATION_LBA ?
",trans=lba" :
translation == BIOS_ATA_TRANSLATION_NONE ?
@@ -2040,10 +2041,11 @@ int main(int argc, char **argv, char **envp)
case QEMU_OPTION_hdb:
case QEMU_OPTION_hdc:
case QEMU_OPTION_hdd:
- drive_add(optarg, HD_ALIAS, popt->index - QEMU_OPTION_hda);
+ drive_add(IF_DEFAULT, popt->index - QEMU_OPTION_hda, optarg,
+ HD_OPTS);
break;
case QEMU_OPTION_drive:
- drive_add(NULL, "%s", optarg);
+ drive_def(optarg);
break;
case QEMU_OPTION_set:
if (qemu_set_option(optarg) != 0)
@@ -2054,13 +2056,13 @@ int main(int argc, char **argv, char **envp)
exit(1);
break;
case QEMU_OPTION_mtdblock:
- drive_add(optarg, MTD_ALIAS);
+ drive_add(IF_MTD, -1, optarg, MTD_OPTS);
break;
case QEMU_OPTION_sd:
- drive_add(optarg, SD_ALIAS);
+ drive_add(IF_SD, 0, optarg, SD_OPTS);
break;
case QEMU_OPTION_pflash:
- drive_add(optarg, PFLASH_ALIAS);
+ drive_add(IF_PFLASH, -1, optarg, PFLASH_OPTS);
break;
case QEMU_OPTION_snapshot:
snapshot = 1;
@@ -2139,7 +2141,7 @@ int main(int argc, char **argv, char **envp)
kernel_cmdline = optarg;
break;
case QEMU_OPTION_cdrom:
- drive_add(optarg, CDROM_ALIAS);
+ drive_add(IF_DEFAULT, 2, optarg, CDROM_OPTS);
break;
case QEMU_OPTION_boot:
{
@@ -2192,7 +2194,8 @@ int main(int argc, char **argv, char **envp)
break;
case QEMU_OPTION_fda:
case QEMU_OPTION_fdb:
- drive_add(optarg, FD_ALIAS, popt->index - QEMU_OPTION_fda);
+ drive_add(IF_FLOPPY, popt->index - QEMU_OPTION_fda,
+ optarg, FD_OPTS);
break;
case QEMU_OPTION_no_fd_bootchk:
fd_bootchk = 0;
@@ -2892,17 +2895,17 @@ int main(int argc, char **argv, char **envp)
if (default_cdrom) {
/* we always create the cdrom drive, even if no disk is there */
- drive_add(NULL, CDROM_ALIAS);
+ drive_add(IF_DEFAULT, 2, NULL, CDROM_OPTS);
}
if (default_floppy) {
/* we always create at least one floppy */
- drive_add(NULL, FD_ALIAS, 0);
+ drive_add(IF_FLOPPY, 0, NULL, FD_OPTS);
}
if (default_sdcard) {
/* we always create one sd slot, even if no card is in it */
- drive_add(NULL, SD_ALIAS);
+ drive_add(IF_SD, 0, NULL, SD_OPTS);
}
/* open the virtual block devices */
commit 27d6bf40edc346a61ade6d4c5d4f27f6b40acc81
Author: Markus Armbruster <armbru at redhat.com>
Date: Fri Jan 28 11:21:40 2011 +0100
blockdev: Fix regression in -drive if=scsi,index=N
Before commit 622b520f, index=12 meant bus=1,unit=5.
Since the commit, it means bus=0,unit=12. The drive is created, but
not the guest device. That's because the controllers we use with
if=scsi drives (lsi53c895a and esp) support only 7 units, and
scsi_bus_legacy_handle_cmdline() ignores drives with unit numbers
exceeding that limit.
Changing the mapping of index to bus, unit is a regression. Breaking
-drive invocations that used to work just makes it worse.
Revert the part of commit 622b520f that causes this, and clean up
some.
Note that the fix only affects if=scsi. You can still put more than 7
units on a SCSI bus with -device & friends.
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/blockdev.c b/blockdev.c
index 9c883ce..fba53f9 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -32,8 +32,22 @@ static const char *const if_name[IF_COUNT] = {
};
static const int if_max_devs[IF_COUNT] = {
- [IF_IDE] = MAX_IDE_DEVS,
- [IF_SCSI] = MAX_SCSI_DEVS,
+ /*
+ * Do not change these numbers! They govern how drive option
+ * index maps to unit and bus. That mapping is ABI.
+ *
+ * All controllers used to imlement if=T drives need to support
+ * if_max_devs[T] units, for any T with if_max_devs[T] != 0.
+ * Otherwise, some index values map to "impossible" bus, unit
+ * values.
+ *
+ * For instance, if you change [IF_SCSI] to 255, -drive
+ * if=scsi,index=12 no longer means bus=1,unit=5, but
+ * bus=0,unit=12. With an lsi53c895a controller (7 units max),
+ * the drive can't be set up. Regression.
+ */
+ [IF_IDE] = 2,
+ [IF_SCSI] = 7,
};
/*
diff --git a/blockdev.h b/blockdev.h
index 2cbbb87..cf8fc01 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -37,9 +37,6 @@ struct DriveInfo {
QTAILQ_ENTRY(DriveInfo) next;
};
-#define MAX_IDE_DEVS 2
-#define MAX_SCSI_DEVS 255
-
DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
int drive_get_max_bus(BlockInterfaceType type);
DriveInfo *drive_get_next(BlockInterfaceType type);
diff --git a/hw/ide.h b/hw/ide.h
index 2b5ae7c..73fb550 100644
--- a/hw/ide.h
+++ b/hw/ide.h
@@ -4,6 +4,8 @@
#include "isa.h"
#include "pci.h"
+#define MAX_IDE_DEVS 2
+
/* ide-isa.c */
ISADevice *isa_ide_init(int iobase, int iobase2, int isairq,
DriveInfo *hd0, DriveInfo *hd1);
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 433171c..671b4df 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -70,7 +70,6 @@
#include "monitor.h"
#include "dma.h"
#include "cpu-common.h"
-#include "blockdev.h"
#include "internal.h"
#include <hw/ide/pci.h>
diff --git a/hw/qdev.c b/hw/qdev.c
index 0c94fb2..c7fec44 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -29,7 +29,6 @@
#include "qdev.h"
#include "sysemu.h"
#include "monitor.h"
-#include "blockdev.h"
static int qdev_hotplug = 0;
static bool qdev_hot_added = false;
diff --git a/hw/scsi.h b/hw/scsi.h
index 846fbba..d3b5d56 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -3,9 +3,10 @@
#include "qdev.h"
#include "block.h"
-#include "blockdev.h"
#include "block_int.h"
+#define MAX_SCSI_DEVS 255
+
#define SCSI_CMD_BUF_SIZE 16
/* scsi-disk.c */
diff --git a/savevm.c b/savevm.c
index fcd8db4..4453217 100644
--- a/savevm.c
+++ b/savevm.c
@@ -78,7 +78,6 @@
#include "sysemu.h"
#include "qemu-timer.h"
#include "qemu-char.h"
-#include "blockdev.h"
#include "audio/audio.h"
#include "migration.h"
#include "qemu_socket.h"
commit 1960966d1b57628f730b66fe33cd2005846092e0
Author: Markus Armbruster <armbru at redhat.com>
Date: Fri Jan 28 11:21:39 2011 +0100
blockdev: Put BlockInterfaceType names and max_devs in tables
Turns drive_init()'s lengthy conditional into a concise loop, and
makes the data available elsewhere.
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/blockdev.c b/blockdev.c
index 699f312..9c883ce 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -19,6 +19,23 @@
static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
+static const char *const if_name[IF_COUNT] = {
+ [IF_NONE] = "none",
+ [IF_IDE] = "ide",
+ [IF_SCSI] = "scsi",
+ [IF_FLOPPY] = "floppy",
+ [IF_PFLASH] = "pflash",
+ [IF_MTD] = "mtd",
+ [IF_SD] = "sd",
+ [IF_VIRTIO] = "virtio",
+ [IF_XEN] = "xen",
+};
+
+static const int if_max_devs[IF_COUNT] = {
+ [IF_IDE] = MAX_IDE_DEVS,
+ [IF_SCSI] = MAX_SCSI_DEVS,
+};
+
/*
* We automatically delete the drive when a device using it gets
* unplugged. Questionable feature, but we can't just drop it.
@@ -173,11 +190,9 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
if (default_to_scsi) {
type = IF_SCSI;
- max_devs = MAX_SCSI_DEVS;
pstrcpy(devname, sizeof(devname), "scsi");
} else {
type = IF_IDE;
- max_devs = MAX_IDE_DEVS;
pstrcpy(devname, sizeof(devname), "ide");
}
media = MEDIA_DISK;
@@ -199,38 +214,14 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
if ((buf = qemu_opt_get(opts, "if")) != NULL) {
pstrcpy(devname, sizeof(devname), buf);
- if (!strcmp(buf, "ide")) {
- type = IF_IDE;
- max_devs = MAX_IDE_DEVS;
- } else if (!strcmp(buf, "scsi")) {
- type = IF_SCSI;
- max_devs = MAX_SCSI_DEVS;
- } else if (!strcmp(buf, "floppy")) {
- type = IF_FLOPPY;
- max_devs = 0;
- } else if (!strcmp(buf, "pflash")) {
- type = IF_PFLASH;
- max_devs = 0;
- } else if (!strcmp(buf, "mtd")) {
- type = IF_MTD;
- max_devs = 0;
- } else if (!strcmp(buf, "sd")) {
- type = IF_SD;
- max_devs = 0;
- } else if (!strcmp(buf, "virtio")) {
- type = IF_VIRTIO;
- max_devs = 0;
- } else if (!strcmp(buf, "xen")) {
- type = IF_XEN;
- max_devs = 0;
- } else if (!strcmp(buf, "none")) {
- type = IF_NONE;
- max_devs = 0;
- } else {
+ for (type = 0; type < IF_COUNT && strcmp(buf, if_name[type]); type++)
+ ;
+ if (type == IF_COUNT) {
error_report("unsupported bus type '%s'", buf);
return NULL;
}
}
+ max_devs = if_max_devs[type];
if (cyls || heads || secs) {
if (cyls < 1 || (type == IF_IDE && cyls > 16383)) {
commit 904ebffee5a7e7d246039ad5826195fe51ccf769
Author: Markus Armbruster <armbru at redhat.com>
Date: Fri Jan 28 11:21:38 2011 +0100
blockdev: Move BlockInterfaceType from qemu-common.h to blockdev.h
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/blockdev.h b/blockdev.h
index 3ed6634..2cbbb87 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -18,6 +18,12 @@ void blockdev_auto_del(BlockDriverState *bs);
#define BLOCK_SERIAL_STRLEN 20
+typedef enum {
+ IF_NONE,
+ IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN,
+ IF_COUNT
+} BlockInterfaceType;
+
struct DriveInfo {
BlockDriverState *bdrv;
char *id;
diff --git a/qemu-common.h b/qemu-common.h
index 79e1149..c7ff280 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -274,12 +274,6 @@ typedef struct VirtIODevice VirtIODevice;
typedef uint64_t pcibus_t;
-typedef enum {
- IF_NONE,
- IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN,
- IF_COUNT
-} BlockInterfaceType;
-
void cpu_exec_init_all(unsigned long tb_size);
/* CPU save/load. */
commit 13839974d14701626a2f9dcc5f8cf65783d51c11
Author: Markus Armbruster <armbru at redhat.com>
Date: Fri Jan 28 11:21:37 2011 +0100
blockdev: New drive_get_next(), replacing qdev_init_bdrv()
qdev_init_bdrv() doesn't belong into qdev.c; it's about drives, not
qdevs. Rename to drive_get_next, move to blockdev.c, drop the bogus
DeviceState argument, and return DriveInfo instead of
BlockDriverState.
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/blockdev.c b/blockdev.c
index e48d33d..699f312 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -93,6 +93,16 @@ int drive_get_max_bus(BlockInterfaceType type)
return max_bus;
}
+/* Get a block device. This should only be used for single-drive devices
+ (e.g. SD/Floppy/MTD). Multi-disk devices (scsi/ide) should use the
+ appropriate bus. */
+DriveInfo *drive_get_next(BlockInterfaceType type)
+{
+ static int next_block_unit[IF_COUNT];
+
+ return drive_get(type, 0, next_block_unit[type]++);
+}
+
DriveInfo *drive_get_by_blockdev(BlockDriverState *bs)
{
DriveInfo *dinfo;
diff --git a/blockdev.h b/blockdev.h
index b8a88bf..3ed6634 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -36,6 +36,7 @@ struct DriveInfo {
DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
int drive_get_max_bus(BlockInterfaceType type);
+DriveInfo *drive_get_next(BlockInterfaceType type);
void drive_uninit(DriveInfo *dinfo);
DriveInfo *drive_get_by_blockdev(BlockDriverState *bs);
diff --git a/hw/pl181.c b/hw/pl181.c
index 3e5f92f..36d9d02 100644
--- a/hw/pl181.c
+++ b/hw/pl181.c
@@ -7,6 +7,7 @@
* This code is licenced under the GPL.
*/
+#include "blockdev.h"
#include "sysbus.h"
#include "sd.h"
@@ -449,15 +450,15 @@ static int pl181_init(SysBusDevice *dev)
{
int iomemtype;
pl181_state *s = FROM_SYSBUS(pl181_state, dev);
- BlockDriverState *bd;
+ DriveInfo *dinfo;
iomemtype = cpu_register_io_memory(pl181_readfn, pl181_writefn, s,
DEVICE_NATIVE_ENDIAN);
sysbus_init_mmio(dev, 0x1000, iomemtype);
sysbus_init_irq(dev, &s->irq[0]);
sysbus_init_irq(dev, &s->irq[1]);
- bd = qdev_init_bdrv(&dev->qdev, IF_SD);
- s->card = sd_init(bd, 0);
+ dinfo = drive_get_next(IF_SD);
+ s->card = sd_init(dinfo ? dinfo->bdrv : NULL, 0);
qemu_register_reset(pl181_reset, s);
pl181_reset(s);
/* ??? Save/restore. */
diff --git a/hw/qdev.c b/hw/qdev.c
index 5b8d374..0c94fb2 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -458,20 +458,6 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd)
}
}
-static int next_block_unit[IF_COUNT];
-
-/* Get a block device. This should only be used for single-drive devices
- (e.g. SD/Floppy/MTD). Multi-disk devices (scsi/ide) should use the
- appropriate bus. */
-BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type)
-{
- int unit = next_block_unit[type]++;
- DriveInfo *dinfo;
-
- dinfo = drive_get(type, 0, unit);
- return dinfo ? dinfo->bdrv : NULL;
-}
-
BusState *qdev_get_child_bus(DeviceState *dev, const char *name)
{
BusState *bus;
diff --git a/hw/qdev.h b/hw/qdev.h
index e520aaa..9808f85 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -137,8 +137,6 @@ bool qdev_machine_modified(void);
qemu_irq qdev_get_gpio_in(DeviceState *dev, int n);
void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin);
-BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type);
-
BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
/*** Device API. ***/
diff --git a/hw/ssi-sd.c b/hw/ssi-sd.c
index a1a63b2..fb4b649 100644
--- a/hw/ssi-sd.c
+++ b/hw/ssi-sd.c
@@ -7,6 +7,7 @@
* This code is licenced under the GNU GPL v2.
*/
+#include "blockdev.h"
#include "ssi.h"
#include "sd.h"
@@ -231,11 +232,11 @@ static int ssi_sd_load(QEMUFile *f, void *opaque, int version_id)
static int ssi_sd_init(SSISlave *dev)
{
ssi_sd_state *s = FROM_SSI_SLAVE(ssi_sd_state, dev);
- BlockDriverState *bs;
+ DriveInfo *dinfo;
s->mode = SSI_SD_CMD;
- bs = qdev_init_bdrv(&dev->qdev, IF_SD);
- s->sd = sd_init(bs, 1);
+ dinfo = drive_get_next(IF_SD);
+ s->sd = sd_init(dinfo ? dinfo->bdrv : NULL, 1);
register_savevm(&dev->qdev, "ssi_sd", -1, 1, ssi_sd_save, ssi_sd_load, s);
return 0;
}
commit 1869a65385e9d81f490b4203dd070cc49b7749c9
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sat Jan 29 08:19:15 2011 +0000
qcow2-refcount: remove write-only variables
Variables l2_modified and l2_size are not really used, remove them.
Spotted by GCC 4.6.0:
CC block/qcow2-refcount.o
/src/qemu/block/qcow2-refcount.c: In function 'qcow2_update_snapshot_refcount':
/src/qemu/block/qcow2-refcount.c:708:37: error: variable 'l2_modified' set but not used [-Werror=unused-but-set-variable]
/src/qemu/block/qcow2-refcount.c:708:9: error: variable 'l2_size' set but not used [-Werror=unused-but-set-variable]
CC: Kevin Wolf <kwolf at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index e37e226..915d85a 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -705,7 +705,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
BDRVQcowState *s = bs->opaque;
uint64_t *l1_table, *l2_table, l2_offset, offset, l1_size2, l1_allocated;
int64_t old_offset, old_l2_offset;
- int l2_size, i, j, l1_modified, l2_modified, nb_csectors, refcount;
+ int i, j, l1_modified, nb_csectors, refcount;
int ret;
l2_table = NULL;
@@ -729,14 +729,12 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
l1_allocated = 0;
}
- l2_size = s->l2_size * sizeof(uint64_t);
l1_modified = 0;
for(i = 0; i < l1_size; i++) {
l2_offset = l1_table[i];
if (l2_offset) {
old_l2_offset = l2_offset;
l2_offset &= ~QCOW_OFLAG_COPIED;
- l2_modified = 0;
ret = qcow2_cache_get(bs, s->l2_table_cache, l2_offset,
(void**) &l2_table);
@@ -788,7 +786,6 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
s->refcount_block_cache);
}
l2_table[j] = cpu_to_be64(offset);
- l2_modified = 1;
qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
}
}
commit 31e1ea3ee7d05ab1aa134fe07a8f33b42417641f
Author: Markus Armbruster <armbru at redhat.com>
Date: Fri Jan 28 11:21:36 2011 +0100
scsi hotplug: Set DriveInfo member bus correctly
drive_init() picks the first free bus and unit number, unless the user
specifies them.
This isn't a good fit for the drive_add monitor command, because there
we specify the controller by PCI address instead of using bus number
set by drive_init().
scsi_hot_add() takes care to replace the unit number set by
drive_init() by the real one, but it neglects to replace the bus
number. Thus, bus/unit in DriveInfo may be bogus. Affects
drive_get() and drive_get_max_bus(). I'm not aware of anything bad
happening because of that; looks like by the time we're hot-plugging,
the two functions aren't used anymore. Fix it anyway.
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index 270a982..b6dcbda 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -90,6 +90,7 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
* specified).
*/
dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1);
+ dinfo->bus = scsibus->busnr;
scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit, false);
if (!scsidev) {
return -1;
commit 1b40bbd13a2d37dcd88763b84d01ec68bc96ff14
Author: Kevin Wolf <kwolf at redhat.com>
Date: Fri Jan 28 15:57:39 2011 +0100
raw-win32: Fix bdrv_flush return value
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block/raw-win32.c b/block/raw-win32.c
index 06c9710..c204a80 100644
--- a/block/raw-win32.c
+++ b/block/raw-win32.c
@@ -153,7 +153,7 @@ static int raw_flush(BlockDriverState *bs)
int ret;
ret = FlushFileBuffers(s->hfile);
- if (ret != 0) {
+ if (ret == 0) {
return -EIO;
}
commit 0d09c7970063ecdabdc2841ffa32e1cf3e032336
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date: Fri Jan 28 17:11:59 2011 +0000
qed: Images with backing file do not require QED_F_NEED_CHECK
The consistency check on open is necessary in order to fix inconsistent
table offsets left as a result of a crash mid-operation. Images with a
backing file actually flush before updating table offsets and are
therefore guaranteed to be consistent. Do not mark these images dirty.
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block/qed.c b/block/qed.c
index a46f9ef..3273448 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -977,6 +977,19 @@ static void qed_aio_write_prefill(void *opaque, int ret)
}
/**
+ * Check if the QED_F_NEED_CHECK bit should be set during allocating write
+ */
+static bool qed_should_set_need_check(BDRVQEDState *s)
+{
+ /* The flush before L2 update path ensures consistency */
+ if (s->bs->backing_hd) {
+ return false;
+ }
+
+ return !(s->header.features & QED_F_NEED_CHECK);
+}
+
+/**
* Write new data cluster
*
* @acb: Write request
@@ -1001,15 +1014,12 @@ static void qed_aio_write_alloc(QEDAIOCB *acb, size_t len)
acb->cur_cluster = qed_alloc_clusters(s, acb->cur_nclusters);
qemu_iovec_copy(&acb->cur_qiov, acb->qiov, acb->qiov_offset, len);
- /* Write new cluster if the image is already marked dirty */
- if (s->header.features & QED_F_NEED_CHECK) {
+ if (qed_should_set_need_check(s)) {
+ s->header.features |= QED_F_NEED_CHECK;
+ qed_write_header(s, qed_aio_write_prefill, acb);
+ } else {
qed_aio_write_prefill(acb, 0);
- return;
}
-
- /* Mark the image dirty before writing the new cluster */
- s->header.features |= QED_F_NEED_CHECK;
- qed_write_header(s, qed_aio_write_prefill, acb);
}
/**
commit 5ea929e3d13622e5d06ca8795819f1590644cda2
Author: Kevin Wolf <kwolf at redhat.com>
Date: Wed Jan 26 16:56:48 2011 +0100
qcow2: Add bdrv_discard support
This adds a bdrv_discard function to qcow2 that frees the discarded clusters.
It does not yet pass the discard on to the underlying file system driver, but
the space can be reused by future writes to the image.
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 1c2003a..5fb8c66 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -888,3 +888,85 @@ int qcow2_decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset)
}
return 0;
}
+
+/*
+ * This discards as many clusters of nb_clusters as possible at once (i.e.
+ * all clusters in the same L2 table) and returns the number of discarded
+ * clusters.
+ */
+static int discard_single_l2(BlockDriverState *bs, uint64_t offset,
+ unsigned int nb_clusters)
+{
+ BDRVQcowState *s = bs->opaque;
+ uint64_t l2_offset, *l2_table;
+ int l2_index;
+ int ret;
+ int i;
+
+ ret = get_cluster_table(bs, offset, &l2_table, &l2_offset, &l2_index);
+ if (ret < 0) {
+ return ret;
+ }
+
+ /* Limit nb_clusters to one L2 table */
+ nb_clusters = MIN(nb_clusters, s->l2_size - l2_index);
+
+ for (i = 0; i < nb_clusters; i++) {
+ uint64_t old_offset;
+
+ old_offset = be64_to_cpu(l2_table[l2_index + i]);
+ old_offset &= ~QCOW_OFLAG_COPIED;
+
+ if (old_offset == 0) {
+ continue;
+ }
+
+ /* First remove L2 entries */
+ qcow2_cache_entry_mark_dirty(s->l2_table_cache, l2_table);
+ l2_table[l2_index + i] = cpu_to_be64(0);
+
+ /* Then decrease the refcount */
+ qcow2_free_any_clusters(bs, old_offset, 1);
+ }
+
+ ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
+ if (ret < 0) {
+ return ret;
+ }
+
+ return nb_clusters;
+}
+
+int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset,
+ int nb_sectors)
+{
+ BDRVQcowState *s = bs->opaque;
+ uint64_t end_offset;
+ unsigned int nb_clusters;
+ int ret;
+
+ end_offset = offset + (nb_sectors << BDRV_SECTOR_BITS);
+
+ /* Round start up and end down */
+ offset = align_offset(offset, s->cluster_size);
+ end_offset &= ~(s->cluster_size - 1);
+
+ if (offset > end_offset) {
+ return 0;
+ }
+
+ nb_clusters = size_to_clusters(s, end_offset - offset);
+
+ /* Each L2 table is handled by its own loop iteration */
+ while (nb_clusters > 0) {
+ ret = discard_single_l2(bs, offset, nb_clusters);
+ if (ret < 0) {
+ return ret;
+ }
+
+ nb_clusters -= ret;
+ offset += (ret * s->cluster_size);
+ }
+
+ return 0;
+}
diff --git a/block/qcow2.c b/block/qcow2.c
index 49bf7b9..dbe4fdd 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -1084,6 +1084,13 @@ static int qcow2_make_empty(BlockDriverState *bs)
return 0;
}
+static int qcow2_discard(BlockDriverState *bs, int64_t sector_num,
+ int nb_sectors)
+{
+ return qcow2_discard_clusters(bs, sector_num << BDRV_SECTOR_BITS,
+ nb_sectors);
+}
+
static int qcow2_truncate(BlockDriverState *bs, int64_t offset)
{
BDRVQcowState *s = bs->opaque;
@@ -1349,6 +1356,7 @@ static BlockDriver bdrv_qcow2 = {
.bdrv_aio_writev = qcow2_aio_writev,
.bdrv_aio_flush = qcow2_aio_flush,
+ .bdrv_discard = qcow2_discard,
.bdrv_truncate = qcow2_truncate,
.bdrv_write_compressed = qcow2_write_compressed,
diff --git a/block/qcow2.h b/block/qcow2.h
index 6d80120..a019831 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -209,6 +209,8 @@ uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
int compressed_size);
int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m);
+int qcow2_discard_clusters(BlockDriverState *bs, uint64_t offset,
+ int nb_sectors);
/* qcow2-snapshot.c functions */
int qcow2_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info);
commit a9c49a6b023fd3706002fd8d549c58f0343932f8
Author: Kevin Wolf <kwolf at redhat.com>
Date: Wed Jan 26 16:56:34 2011 +0100
qemu-io: Fix discard command
qemu-io passed bytes where it's supposed to pass sectors, so discard requests
were off.
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
diff --git a/qemu-io.c b/qemu-io.c
index 5b24c5e..4470e49 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -1465,7 +1465,7 @@ discard_f(int argc, char **argv)
}
gettimeofday(&t1, NULL);
- ret = bdrv_discard(bs, offset, count);
+ ret = bdrv_discard(bs, offset >> BDRV_SECTOR_BITS, count >> BDRV_SECTOR_BITS);
gettimeofday(&t2, NULL);
if (ret < 0) {
commit b4447363469650fc98f67714336cb0baa6156a5e
Author: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
Date: Fri Jan 28 01:33:10 2011 +0900
sheepdog: support creating images on remote hosts
This patch parses the input filename in sd_create(), and enables us
specifying a target server to create sheepdog images.
Signed-off-by: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block/sheepdog.c b/block/sheepdog.c
index e62820a..a54e0de 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -1294,12 +1294,23 @@ static int do_sd_create(char *filename, int64_t vdi_size,
static int sd_create(const char *filename, QEMUOptionParameter *options)
{
int ret;
- uint32_t vid = 0;
+ uint32_t vid = 0, base_vid = 0;
int64_t vdi_size = 0;
char *backing_file = NULL;
+ BDRVSheepdogState s;
+ char vdi[SD_MAX_VDI_LEN], tag[SD_MAX_VDI_TAG_LEN];
+ uint32_t snapid;
strstart(filename, "sheepdog:", (const char **)&filename);
+ memset(&s, 0, sizeof(s));
+ memset(vdi, 0, sizeof(vdi));
+ memset(tag, 0, sizeof(tag));
+ if (parse_vdiname(&s, filename, vdi, &snapid, tag) < 0) {
+ error_report("invalid filename\n");
+ return -EINVAL;
+ }
+
while (options && options->name) {
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
vdi_size = options->value.n;
@@ -1338,11 +1349,11 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
return -EINVAL;
}
- vid = s->inode.vdi_id;
+ base_vid = s->inode.vdi_id;
bdrv_delete(bs);
}
- return do_sd_create((char *)filename, vdi_size, vid, NULL, 0, NULL, NULL);
+ return do_sd_create((char *)vdi, vdi_size, base_vid, &vid, 0, s.addr, s.port);
}
static void sd_close(BlockDriverState *bs)
commit bf595021c765c8869cf2942874c419d7b73bbaf6
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Thu Jan 27 11:25:03 2011 +0100
Reorganize struct Qcow2Cache for better struct packing
Move size after the two pointers in struct Qcow2Cache to get better
packing of struct elements on 64 bit architectures.
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block/qcow2-cache.c b/block/qcow2-cache.c
index 8f2955b..3824739 100644
--- a/block/qcow2-cache.c
+++ b/block/qcow2-cache.c
@@ -35,9 +35,9 @@ typedef struct Qcow2CachedTable {
} Qcow2CachedTable;
struct Qcow2Cache {
- int size;
Qcow2CachedTable* entries;
struct Qcow2Cache* depends;
+ int size;
bool depends_on_flush;
bool writethrough;
};
commit fe6ceac86041ecdf7b99a3d57991941277fa7694
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date: Wed Jan 26 10:24:56 2011 +0000
ahci: Fix cpu_physical_memory_unmap() argument ordering
The len and is_write arguments to cpu_physical_memory_unmap() were
swapped. This patch changes calls to use the correct argument ordering.
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 968fdce..433171c 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -513,12 +513,12 @@ static void map_page(uint8_t **ptr, uint64_t addr, uint32_t wanted)
target_phys_addr_t len = wanted;
if (*ptr) {
- cpu_physical_memory_unmap(*ptr, 1, len, len);
+ cpu_physical_memory_unmap(*ptr, len, 1, len);
}
*ptr = cpu_physical_memory_map(addr, &len, 1);
if (len < wanted) {
- cpu_physical_memory_unmap(*ptr, 1, len, len);
+ cpu_physical_memory_unmap(*ptr, len, 1, len);
*ptr = NULL;
}
}
@@ -956,7 +956,7 @@ static void ahci_write_fis_d2h(AHCIDevice *ad, uint8_t *cmd_fis)
ahci_trigger_irq(ad->hba, ad, PORT_IRQ_D2H_REG_FIS);
if (cmd_mapped) {
- cpu_physical_memory_unmap(cmd_fis, 0, cmd_len, cmd_len);
+ cpu_physical_memory_unmap(cmd_fis, cmd_len, 0, cmd_len);
}
}
@@ -1002,7 +1002,7 @@ static int ahci_populate_sglist(AHCIDevice *ad, QEMUSGList *sglist)
}
out:
- cpu_physical_memory_unmap(prdt, 0, prdt_len, prdt_len);
+ cpu_physical_memory_unmap(prdt, prdt_len, 0, prdt_len);
return r;
}
@@ -1228,7 +1228,7 @@ static int handle_cmd(AHCIState *s, int port, int slot)
}
out:
- cpu_physical_memory_unmap(cmd_fis, 1, cmd_len, cmd_len);
+ cpu_physical_memory_unmap(cmd_fis, cmd_len, 1, cmd_len);
if (s->dev[port].port.ifs[0].status & (BUSY_STAT|DRQ_STAT)) {
/* async command, complete later */
commit d7142456c4c0a8793a7888e00ef7fbf0553f9c66
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Wed Jan 26 11:54:58 2011 +0100
Add documentation for STRTOSZ_DEFSUFFIX_ macros
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Acked-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/qemu-common.h b/qemu-common.h
index c351131..79e1149 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -153,6 +153,13 @@ int qemu_fls(int i);
int qemu_fdatasync(int fd);
int fcntl_setfl(int fd, int flag);
+/*
+ * strtosz() suffixes used to specify the default treatment of an
+ * argument passed to strtosz() without an explicit suffix.
+ * These should be defined using upper case characters in the range
+ * A-Z, as strtosz() will use qemu_toupper() on the given argument
+ * prior to comparison.
+ */
#define STRTOSZ_DEFSUFFIX_TB 'T'
#define STRTOSZ_DEFSUFFIX_GB 'G'
#define STRTOSZ_DEFSUFFIX_MB 'M'
commit d0dcac833a767dade968a07aba4d116f162ebc72
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date: Tue Jan 25 16:17:14 2011 +0000
virtio-pci: Disable virtio-ioeventfd when !CONFIG_IOTHREAD
It is not possible to use virtio-ioeventfd when building without an I/O
thread. We rely on a signal to kick us out of vcpu execution. Timers
and AIO use SIGALRM and SIGUSR2 respectively. Unfortunately eventfd
does not support O_ASYNC (SIGIO) so eventfd cannot be used in a signal
driven manner.
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Acked-by: Michael S. Tsirkin <mst at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/kvm-all.c b/kvm-all.c
index 255b6fa..8f0e17c 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -449,10 +449,14 @@ int kvm_check_extension(KVMState *s, unsigned int extension)
static int kvm_check_many_ioeventfds(void)
{
- /* Older kernels have a 6 device limit on the KVM io bus. Find out so we
+ /* Userspace can use ioeventfd for io notification. This requires a host
+ * that supports eventfd(2) and an I/O thread; since eventfd does not
+ * support SIGIO it cannot interrupt the vcpu.
+ *
+ * Older kernels have a 6 device limit on the KVM io bus. Find out so we
* can avoid creating too many ioeventfds.
*/
-#ifdef CONFIG_EVENTFD
+#if defined(CONFIG_EVENTFD) && defined(CONFIG_IOTHREAD)
int ioeventfds[7];
int i, ret = 0;
for (i = 0; i < ARRAY_SIZE(ioeventfds); i++) {
commit e5051fc70807750f7a4798d2d83e159793c466d3
Author: Christoph Hellwig <hch at lst.de>
Date: Mon Jan 24 13:32:51 2011 +0100
virtio-blk: tell the guest about size changes
Raise a config change interrupt when the size changed. This allows
virtio-blk guest drivers to read-read the information from the
config space once it got the config chaged interrupt.
Signed-off-by: Christoph Hellwig <hch at lst.de>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 9f2a9c0..ffac5a4 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -514,6 +514,15 @@ static int virtio_blk_load(QEMUFile *f, void *opaque, int version_id)
return 0;
}
+static void virtio_blk_change_cb(void *opaque, int reason)
+{
+ VirtIOBlock *s = opaque;
+
+ if (reason & CHANGE_SIZE) {
+ virtio_notify_config(&s->vdev);
+ }
+}
+
VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
{
VirtIOBlock *s;
@@ -556,6 +565,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
register_savevm(dev, "virtio-blk", virtio_blk_id++, 2,
virtio_blk_save, virtio_blk_load, s);
bdrv_set_removable(s->bs, 0);
+ bdrv_set_change_cb(s->bs, virtio_blk_change_cb, s);
s->bs->buffer_alignment = conf->logical_block_size;
add_boot_device_path(conf->bootindex, dev, "/disk at 0,0");
commit db97ee6a976bacbb0d18818e951cfc41b39269a7
Author: Christoph Hellwig <hch at lst.de>
Date: Mon Jan 24 13:32:41 2011 +0100
block: tell drivers about an image resize
Extend the change_cb callback with a reason argument, and use it
to tell drivers about size changes.
Signed-off-by: Christoph Hellwig <hch at lst.de>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block.c b/block.c
index 7ad3ddf..998df1b 100644
--- a/block.c
+++ b/block.c
@@ -645,7 +645,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
/* call the change callback */
bs->media_changed = 1;
if (bs->change_cb)
- bs->change_cb(bs->change_opaque);
+ bs->change_cb(bs->change_opaque, CHANGE_MEDIA);
}
return 0;
@@ -684,7 +684,7 @@ void bdrv_close(BlockDriverState *bs)
/* call the change callback */
bs->media_changed = 1;
if (bs->change_cb)
- bs->change_cb(bs->change_opaque);
+ bs->change_cb(bs->change_opaque, CHANGE_MEDIA);
}
}
@@ -1135,6 +1135,9 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset)
ret = drv->bdrv_truncate(bs, offset);
if (ret == 0) {
ret = refresh_total_sectors(bs, offset >> BDRV_SECTOR_BITS);
+ if (bs->change_cb) {
+ bs->change_cb(bs->change_opaque, CHANGE_SIZE);
+ }
}
return ret;
}
@@ -1366,7 +1369,8 @@ int bdrv_enable_write_cache(BlockDriverState *bs)
/* XXX: no longer used */
void bdrv_set_change_cb(BlockDriverState *bs,
- void (*change_cb)(void *opaque), void *opaque)
+ void (*change_cb)(void *opaque, int reason),
+ void *opaque)
{
bs->change_cb = change_cb;
bs->change_opaque = opaque;
@@ -1411,7 +1415,7 @@ int bdrv_set_key(BlockDriverState *bs, const char *key)
/* call the change callback now, we skipped it on open */
bs->media_changed = 1;
if (bs->change_cb)
- bs->change_cb(bs->change_opaque);
+ bs->change_cb(bs->change_opaque, CHANGE_MEDIA);
}
return ret;
}
diff --git a/block.h b/block.h
index f923add..239f729 100644
--- a/block.h
+++ b/block.h
@@ -182,7 +182,8 @@ int bdrv_is_locked(BlockDriverState *bs);
void bdrv_set_locked(BlockDriverState *bs, int locked);
int bdrv_eject(BlockDriverState *bs, int eject_flag);
void bdrv_set_change_cb(BlockDriverState *bs,
- void (*change_cb)(void *opaque), void *opaque);
+ void (*change_cb)(void *opaque, int reason),
+ void *opaque);
void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size);
BlockDriverState *bdrv_find(const char *name);
BlockDriverState *bdrv_next(BlockDriverState *bs);
diff --git a/block_int.h b/block_int.h
index 12663e8..6ebdc3e 100644
--- a/block_int.h
+++ b/block_int.h
@@ -153,7 +153,7 @@ struct BlockDriverState {
int valid_key; /* if true, a valid encryption key has been set */
int sg; /* if true, the device is a /dev/sg* */
/* event callback when inserting/removing */
- void (*change_cb)(void *opaque);
+ void (*change_cb)(void *opaque, int reason);
void *change_opaque;
BlockDriver *drv; /* NULL means no media */
@@ -203,6 +203,9 @@ struct BlockDriverState {
void *private;
};
+#define CHANGE_MEDIA 0x01
+#define CHANGE_SIZE 0x02
+
struct BlockDriverAIOCB {
AIOPool *pool;
BlockDriverState *bs;
diff --git a/hw/ide/core.c b/hw/ide/core.c
index e698c13..dd63664 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1584,11 +1584,15 @@ static void ide_cfata_metadata_write(IDEState *s)
}
/* called when the inserted state of the media has changed */
-static void cdrom_change_cb(void *opaque)
+static void cdrom_change_cb(void *opaque, int reason)
{
IDEState *s = opaque;
uint64_t nb_sectors;
+ if (!(reason & CHANGE_MEDIA)) {
+ return;
+ }
+
bdrv_get_geometry(s->bs, &nb_sectors);
s->nb_sectors = nb_sectors;
diff --git a/hw/sd.c b/hw/sd.c
index 601545b..789ca84 100644
--- a/hw/sd.c
+++ b/hw/sd.c
@@ -422,9 +422,14 @@ static void sd_reset(SDState *sd, BlockDriverState *bdrv)
sd->pwd_len = 0;
}
-static void sd_cardchange(void *opaque)
+static void sd_cardchange(void *opaque, int reason)
{
SDState *sd = opaque;
+
+ if (!(reason & CHANGE_MEDIA)) {
+ return;
+ }
+
qemu_set_irq(sd->inserted_cb, bdrv_is_inserted(sd->bdrv));
if (bdrv_is_inserted(sd->bdrv)) {
sd_reset(sd, sd->bdrv);
commit 6d4a2b3a47959f02e7f307f50396e70e8464f95e
Author: Christoph Hellwig <hch at lst.de>
Date: Mon Jan 24 13:32:33 2011 +0100
block: add block_resize monitor command
Add a monitor command that allows resizing of block devices while
qemu is running. It uses the existing bdrv_truncate method already
used by qemu-img to do it's work. Compared to qemu-img the size
parsing is very simplicistic, but I think having a properly numering
object is more useful for non-humand monitor users than having
the units and relative resize parsing.
For SCSI devices the new size can be updated in Linux guests by
doing the following shell command:
echo > /sys/class/scsi_device/0:0:0:0/device/rescan
For ATA devices I don't know of a way to update the block device
size in Linux system, and for virtio-blk the next two patches
will provide an automatic update of the size when this command
is issued on the host.
Signed-off-by: Christoph Hellwig <hch at lst.de>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/blockdev.c b/blockdev.c
index f7f591f..e48d33d 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -705,3 +705,33 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
return 0;
}
+
+/*
+ * XXX: replace the QERR_UNDEFINED_ERROR errors with real values once the
+ * existing QERR_ macro mess is cleaned up. A good example for better
+ * error reports can be found in the qemu-img resize code.
+ */
+int do_block_resize(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+ const char *device = qdict_get_str(qdict, "device");
+ int64_t size = qdict_get_int(qdict, "size");
+ BlockDriverState *bs;
+
+ bs = bdrv_find(device);
+ if (!bs) {
+ qerror_report(QERR_DEVICE_NOT_FOUND, device);
+ return -1;
+ }
+
+ if (size < 0) {
+ qerror_report(QERR_UNDEFINED_ERROR);
+ return -1;
+ }
+
+ if (bdrv_truncate(bs, size)) {
+ qerror_report(QERR_UNDEFINED_ERROR);
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/blockdev.h b/blockdev.h
index 4536b5c..b8a88bf 100644
--- a/blockdev.h
+++ b/blockdev.h
@@ -53,5 +53,6 @@ int do_change_block(Monitor *mon, const char *device,
const char *filename, const char *fmt);
int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data);
+int do_block_resize(Monitor *mon, const QDict *qdict, QObject **ret_data);
#endif
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 1cea572..8df4adf 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -53,6 +53,25 @@ Quit the emulator.
ETEXI
{
+ .name = "block_resize",
+ .args_type = "device:B,size:o",
+ .params = "device size",
+ .help = "resize a block image",
+ .user_print = monitor_user_noop,
+ .mhandler.cmd_new = do_block_resize,
+ },
+
+STEXI
+ at item block_resize
+ at findex block_resize
+Resize a block image while a guest is running. Usually requires guest
+action to see the updated size. Resize to a lower size is supported,
+but should be used with extreme caution. Note that this command only
+resizes image files, it can not resize block devices like LVM volumes.
+ETEXI
+
+
+ {
.name = "eject",
.args_type = "force:-f,device:B",
.params = "[-f] device",
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 56c4d8b..9f79f5f 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -601,6 +601,34 @@ Example:
-> { "execute": "netdev_del", "arguments": { "id": "netdev1" } }
<- { "return": {} }
+
+EQMP
+
+ {
+ .name = "block_resize",
+ .args_type = "device:B,size:o",
+ .params = "device size",
+ .help = "resize a block image",
+ .user_print = monitor_user_noop,
+ .mhandler.cmd_new = do_block_resize,
+ },
+
+SQMP
+block_resize
+------------
+
+Resize a block image while a guest is running.
+
+Arguments:
+
+- "device": the device's ID, must be unique (json-string)
+- "size": new size
+
+Example:
+
+-> { "execute": "block_resize", "arguments": { "device": "scratch", "size": 1073741824 } }
+<- { "return": {} }
+
EQMP
{
commit 2be22ca5a8dd96c68ef0e90fd916aa6555ae915b
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Mon Jan 24 16:33:31 2011 +0100
strtosz(): Use suffix macros in switch() statement
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/cutils.c b/cutils.c
index 369a016..8d562b2 100644
--- a/cutils.c
+++ b/cutils.c
@@ -324,26 +324,26 @@ int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix)
}
}
switch (qemu_toupper(d)) {
- case 'B':
+ case STRTOSZ_DEFSUFFIX_B:
mul = 1;
if (mul_required) {
goto fail;
}
break;
- case 'K':
+ case STRTOSZ_DEFSUFFIX_KB:
mul = 1 << 10;
break;
case 0:
if (mul_required) {
goto fail;
}
- case 'M':
+ case STRTOSZ_DEFSUFFIX_MB:
mul = 1ULL << 20;
break;
- case 'G':
+ case STRTOSZ_DEFSUFFIX_GB:
mul = 1ULL << 30;
break;
- case 'T':
+ case STRTOSZ_DEFSUFFIX_TB:
mul = 1ULL << 40;
break;
default:
commit 7eb053494c76bb417f83b6e6784a5dbb27638dba
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Mon Jan 24 16:33:30 2011 +0100
strtosz(): Fix name confusion in use of modf()
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/cutils.c b/cutils.c
index 78d35e2..369a016 100644
--- a/cutils.c
+++ b/cutils.c
@@ -304,8 +304,8 @@ int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix)
if (isnan(val) || endptr == nptr || errno != 0) {
goto fail;
}
- integral = modf(val, &fraction);
- if (integral != 0) {
+ fraction = modf(val, &integral);
+ if (fraction != 0) {
mul_required = 1;
}
/*
commit a2afc2c16339a85176696738e4c58ed4ff36f8b5
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Mon Jan 24 16:33:29 2011 +0100
strtosz() use qemu_toupper() to simplify switch statement
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/cutils.c b/cutils.c
index a067cf4..78d35e2 100644
--- a/cutils.c
+++ b/cutils.c
@@ -323,16 +323,14 @@ int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix)
d = c;
}
}
- switch (d) {
+ switch (qemu_toupper(d)) {
case 'B':
- case 'b':
mul = 1;
if (mul_required) {
goto fail;
}
break;
case 'K':
- case 'k':
mul = 1 << 10;
break;
case 0:
@@ -340,15 +338,12 @@ int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix)
goto fail;
}
case 'M':
- case 'm':
mul = 1ULL << 20;
break;
case 'G':
- case 'g':
mul = 1ULL << 30;
break;
case 'T':
- case 't':
mul = 1ULL << 40;
break;
default:
commit f3bd362a1857c617a4154062cadd501fc52c4199
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Mon Jan 24 16:33:28 2011 +0100
strtosz(): use unsigned char and switch to qemu_isspace()
isspace() behavior is undefined for signed char.
Bug pointed out by Eric Blake, thanks!
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/cutils.c b/cutils.c
index 4d2e27c..a067cf4 100644
--- a/cutils.c
+++ b/cutils.c
@@ -294,7 +294,8 @@ int fcntl_setfl(int fd, int flag)
int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix)
{
int64_t retval = -1;
- char *endptr, c, d;
+ char *endptr;
+ unsigned char c, d;
int mul_required = 0;
double val, mul, integral, fraction;
@@ -314,7 +315,7 @@ int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix)
*/
c = *endptr;
d = c;
- if (isspace(c) || c == '\0' || c == ',') {
+ if (qemu_isspace(c) || c == '\0' || c == ',') {
c = 0;
if (default_suffix) {
d = default_suffix;
@@ -361,7 +362,7 @@ int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix)
*/
if (c != 0) {
endptr++;
- if (!isspace(*endptr) && *endptr != ',' && *endptr != 0) {
+ if (!qemu_isspace(*endptr) && *endptr != ',' && *endptr != 0) {
goto fail;
}
}
commit 45d1aa828f8c94b082a0aa2dbf76535594ee45df
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sun Jan 30 13:10:10 2011 +0000
Update OpenBIOS images to r1018
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/pc-bios/README b/pc-bios/README
index 4b019e0..3fc0944 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -11,7 +11,7 @@
firmware implementation. The goal is to implement a 100% IEEE
1275-1994 (referred to as Open Firmware) compliant firmware.
The included image for PowerPC (for 32 and 64 bit PPC CPUs), Sparc32
- and Sparc64 are built from OpenBIOS SVN revision 859.
+ and Sparc64 are built from OpenBIOS SVN revision 1018.
- The PXE roms come from Rom-o-Matic gPXE 0.9.9 with BANNER_TIMEOUT=0
diff --git a/pc-bios/openbios-ppc b/pc-bios/openbios-ppc
index cb0af05..ee6f5ae 100644
Binary files a/pc-bios/openbios-ppc and b/pc-bios/openbios-ppc differ
diff --git a/pc-bios/openbios-sparc32 b/pc-bios/openbios-sparc32
index aaff1f0..b2dc5c5 100644
Binary files a/pc-bios/openbios-sparc32 and b/pc-bios/openbios-sparc32 differ
diff --git a/pc-bios/openbios-sparc64 b/pc-bios/openbios-sparc64
index a1b692e..70a223d 100644
Binary files a/pc-bios/openbios-sparc64 and b/pc-bios/openbios-sparc64 differ
commit 1b958498acaeee61f0db648b464c04f228f8aab6
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sat Jan 29 22:52:33 2011 +0000
sdl: remove unused variable
Variable rec is not used, remove it. Spotted by GCC 4.6.0:
CC ui/sdl.o
/src/qemu/ui/sdl.c: In function 'sdl_setdata':
/src/qemu/ui/sdl.c:90:14: error: variable 'rec' set but not used [-Werror=unused-but-set-variable]
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/ui/sdl.c b/ui/sdl.c
index f599d42..a1458ce 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -87,12 +87,6 @@ static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
static void sdl_setdata(DisplayState *ds)
{
- SDL_Rect rec;
- rec.x = 0;
- rec.y = 0;
- rec.w = real_screen->w;
- rec.h = real_screen->h;
-
if (guest_screen != NULL) SDL_FreeSurface(guest_screen);
guest_screen = SDL_CreateRGBSurfaceFrom(ds_get_data(ds), ds_get_width(ds), ds_get_height(ds),
commit 320fba2a1f384e17db150d74540a2cf005eb47b5
Author: Fabien Chouteau <chouteau at adacore.com>
Date: Thu Jan 27 10:24:41 2011 +0100
New trace-event backend: stderr
This backend sends trace events to standard error output during the emulation.
Also add a "--list-backends" option to tracetool, so configure script can
display the list of available backends.
Signed-off-by: Fabien Chouteau <chouteau at adacore.com>
Acked-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/configure b/configure
index 210670c..fcc5a71 100755
--- a/configure
+++ b/configure
@@ -907,7 +907,8 @@ echo " --enable-docs enable documentation build"
echo " --disable-docs disable documentation build"
echo " --disable-vhost-net disable vhost-net acceleration support"
echo " --enable-vhost-net enable vhost-net acceleration support"
-echo " --enable-trace-backend=B Trace backend nop simple ust dtrace"
+echo " --enable-trace-backend=B Set trace backend"
+echo " Available backends:" $("$source_path"/scripts/tracetool --list-backends)
echo " --with-trace-file=NAME Full PATH,NAME of file to store traces"
echo " Default:trace-<pid>"
echo " --disable-spice disable spice"
diff --git a/docs/tracing.txt b/docs/tracing.txt
index 963c504..21183f9 100644
--- a/docs/tracing.txt
+++ b/docs/tracing.txt
@@ -133,6 +133,11 @@ source tree. It may not be as powerful as platform-specific or third-party
trace backends but it is portable. This is the recommended trace backend
unless you have specific needs for more advanced backends.
+=== Stderr ===
+
+The "stderr" backend sends trace events directly to standard error output
+during emulation.
+
==== Monitor commands ====
* info trace
diff --git a/scripts/tracetool b/scripts/tracetool
index fce491c..e046683 100755
--- a/scripts/tracetool
+++ b/scripts/tracetool
@@ -13,12 +13,13 @@ set -f
usage()
{
cat >&2 <<EOF
-usage: $0 [--nop | --simple | --ust] [-h | -c]
+usage: $0 [--nop | --simple | --stderr | --ust | --dtrace] [-h | -c]
Generate tracing code for a file on stdin.
Backends:
--nop Tracing disabled
--simple Simple built-in backend
+ --stderr Stderr built-in backend
--ust LTTng User Space Tracing backend
--dtrace DTrace/SystemTAP backend
@@ -236,6 +237,56 @@ linetoc_end_simple()
EOF
}
+#STDERR
+linetoh_begin_stderr()
+{
+ cat <<EOF
+#include <stdio.h>
+EOF
+}
+
+linetoh_stderr()
+{
+ local name args argnames argc fmt
+ name=$(get_name "$1")
+ args=$(get_args "$1")
+ argnames=$(get_argnames "$1" ",")
+ argc=$(get_argc "$1")
+ fmt=$(get_fmt "$1")
+
+ if [ "$argc" -gt 0 ]; then
+ argnames=", $argnames"
+ fi
+
+ cat <<EOF
+static inline void trace_$name($args)
+{
+ fprintf(stderr, "$name $fmt\n" $argnames);
+}
+EOF
+}
+
+linetoh_end_stderr()
+{
+return
+}
+
+linetoc_begin_stderr()
+{
+return
+}
+
+linetoc_stderr()
+{
+return
+}
+
+linetoc_end_stderr()
+{
+return
+}
+#END OF STDERR
+
# Clean up after UST headers which pollute the namespace
ust_clean_namespace() {
cat <<EOF
@@ -546,7 +597,7 @@ targetarch=
until [ -z "$1" ]
do
case "$1" in
- "--nop" | "--simple" | "--ust" | "--dtrace") backend="${1#--}" ;;
+ "--nop" | "--simple" | "--stderr" | "--ust" | "--dtrace") backend="${1#--}" ;;
"--binary") shift ; binary="$1" ;;
"--target-arch") shift ; targetarch="$1" ;;
@@ -557,6 +608,11 @@ do
"--check-backend") exit 0 ;; # used by ./configure to test for backend
+ "--list-backends") # used by ./configure to list available backends
+ echo "nop simple stderr ust dtrace"
+ exit 0
+ ;;
+
*)
usage;;
esac
commit 491e2a338fdf8310c84f6ebaed1683a871a0700e
Author: Hervé Poussineau <hpoussin at reactos.org>
Date: Tue Jan 18 22:43:56 2011 +0100
prep: Disable second IDE channel, as long as ISA IDE emulation doesn't support same irq for both channels
Cc: Andreas Färber <andreas.faerber at web.de>
Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 6b22122..6c1499a 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -690,7 +690,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS);
}
- for(i = 0; i < MAX_IDE_BUS; i++) {
+ for(i = 0; i < 1/*MAX_IDE_BUS*/; i++) {
isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
hd[2 * i],
hd[2 * i + 1]);
commit 74145374bfc0b7b02415184606236f0390479deb
Author: Andreas Färber <andreas.faerber at web.de>
Date: Tue Jan 18 22:43:55 2011 +0100
prep: Remove bogus BIOS size check
r3480 added this check to account for the entry vector 0xfff00100 to be
available for CPUs that need it. Today however, the NIP is not yet
initialized at this point (zero), so the check always triggers.
Moreover, BIOS size check is already done previously, so this part can
be removed too.
Cc: Alexander Graf <agraf at suse.de>
Signed-off-by: Andreas Färber <andreas.faerber at web.de>
Signed-off-by: Hervé Poussineau <hpoussin at reactos.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 1492266..6b22122 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -600,9 +600,6 @@ static void ppc_prep_init (ram_addr_t ram_size,
if (filename) {
qemu_free(filename);
}
- if (env->nip < 0xFFF80000 && bios_size < 0x00100000) {
- hw_error("PowerPC 601 / 620 / 970 need a 1MB BIOS\n");
- }
if (linux_boot) {
kernel_base = KERNEL_LOAD_ADDR;
commit 51e08f3e4b8a3b6d27fde9a9e75c8fa32eaa72d0
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Tue Jan 25 11:55:15 2011 +0100
mc146818rtc: update registers after a format change
For some unknown reason, the MIPS kernel briefly changes the RTC to
binary mode during boot, switch back to BCD mode and read the time. As
the registers are updated only every second, they may still be in the
old format when they are read.
This patch forces a register update immediately after a format change
(BCD/binary or 12/24H). This avoid long fsck during boot due to time
wrap.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index ec7c4ec..a1b0e31 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -247,7 +247,15 @@ static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
rtc_set_time(s);
}
}
- s->cmos_data[RTC_REG_B] = data;
+ if (((s->cmos_data[RTC_REG_B] ^ data) & (REG_B_DM | REG_B_24H)) &&
+ !(data & REG_B_SET)) {
+ /* If the time format has changed and not in set mode,
+ update the registers immediately. */
+ s->cmos_data[RTC_REG_B] = data;
+ rtc_copy_date(s);
+ } else {
+ s->cmos_data[RTC_REG_B] = data;
+ }
rtc_timer_update(s, qemu_get_clock(rtc_clock));
break;
case RTC_REG_C:
commit c29cd656a8fad633fb9ca45b88ade9838d35fd5c
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Tue Jan 25 11:55:15 2011 +0100
mc146818rtc: constantify
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 6466aff..ec7c4ec 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -72,6 +72,7 @@
#define REG_B_UIE 0x10
#define REG_B_SQWE 0x08
#define REG_B_DM 0x04
+#define REG_B_24H 0x02
#define REG_C_UF 0x10
#define REG_C_IRQF 0x80
@@ -285,7 +286,7 @@ static void rtc_set_time(RTCState *s)
tm->tm_sec = rtc_from_bcd(s, s->cmos_data[RTC_SECONDS]);
tm->tm_min = rtc_from_bcd(s, s->cmos_data[RTC_MINUTES]);
tm->tm_hour = rtc_from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
- if (!(s->cmos_data[RTC_REG_B] & 0x02) &&
+ if (!(s->cmos_data[RTC_REG_B] & REG_B_24H) &&
(s->cmos_data[RTC_HOURS] & 0x80)) {
tm->tm_hour += 12;
}
@@ -304,7 +305,7 @@ static void rtc_copy_date(RTCState *s)
s->cmos_data[RTC_SECONDS] = rtc_to_bcd(s, tm->tm_sec);
s->cmos_data[RTC_MINUTES] = rtc_to_bcd(s, tm->tm_min);
- if (s->cmos_data[RTC_REG_B] & 0x02) {
+ if (s->cmos_data[RTC_REG_B] & REG_B_24H) {
/* 24 hour format */
s->cmos_data[RTC_HOURS] = rtc_to_bcd(s, tm->tm_hour);
} else {
commit 46eece9d8969ac37bcdf0a3f056a9cceb20bc641
Author: Juha Riihimäki <juha.riihimaki at nokia.com>
Date: Thu Jan 27 19:18:35 2011 +0000
target-arm: Fix Neon VQ(R)DMULH.S16 instructions
Correct an error in the implementation of the 16 bit
forms of VQ(R)DMULH, bringing them into line with the
32 bit implementation.
Signed-off-by: Juha Riihimäki <juha.riihimaki at nokia.com>
Reviewed-by: Peter Maydell <peter.maydell at linaro.org>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/neon_helper.c b/target-arm/neon_helper.c
index 20f3c16..fead152 100644
--- a/target-arm/neon_helper.c
+++ b/target-arm/neon_helper.c
@@ -880,8 +880,9 @@ uint32_t HELPER(neon_cnt_u8)(uint32_t x)
if ((tmp ^ (tmp << 1)) & SIGNBIT) { \
SET_QC(); \
tmp = (tmp >> 31) ^ ~SIGNBIT; \
+ } else { \
+ tmp <<= 1; \
} \
- tmp <<= 1; \
if (round) { \
int32_t old = tmp; \
tmp += 1 << 15; \
commit 92e3c2a39e95576dd215b063e493069c67ffaab8
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Tue Jan 25 11:55:14 2011 +0100
virtio-blk: fix cross-endianness targets
virtio-blk doesn't work on cross-endian configuration, as endianness is
not handled correctly.
This patch adds missing endianness conversions to make virtio-blk
working. Tested on the following configurations:
- i386 guest on x86_64 host
- ppc guest on x86_64 host
- i386 guest on mips host
- ppc guest on mips host
Reviewed-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index f62ccd1..9f2a9c0 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -55,7 +55,7 @@ static void virtio_blk_req_complete(VirtIOBlockReq *req, int status)
trace_virtio_blk_req_complete(req, status);
- req->in->status = status;
+ stb_p(&req->in->status, status);
virtqueue_push(s->vq, &req->elem, req->qiov.size + sizeof(*req->in));
virtio_notify(&s->vdev, s->vq);
@@ -94,7 +94,7 @@ static void virtio_blk_rw_complete(void *opaque, int ret)
trace_virtio_blk_rw_complete(req, ret);
if (ret) {
- int is_read = !(req->out->type & VIRTIO_BLK_T_OUT);
+ int is_read = !(ldl_p(&req->out->type) & VIRTIO_BLK_T_OUT);
if (virtio_blk_handle_rw_error(req, -ret, is_read))
return;
}
@@ -223,10 +223,10 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
status = VIRTIO_BLK_S_OK;
}
- req->scsi->errors = hdr.status;
- req->scsi->residual = hdr.resid;
- req->scsi->sense_len = hdr.sb_len_wr;
- req->scsi->data_len = hdr.dxfer_len;
+ stl_p(&req->scsi->errors, hdr.status);
+ stl_p(&req->scsi->residual, hdr.resid);
+ stl_p(&req->scsi->sense_len, hdr.sb_len_wr);
+ stl_p(&req->scsi->data_len, hdr.dxfer_len);
virtio_blk_req_complete(req, status);
}
@@ -280,10 +280,13 @@ static void virtio_blk_handle_flush(VirtIOBlockReq *req, MultiReqBuffer *mrb)
static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb)
{
BlockRequest *blkreq;
+ uint64_t sector;
- trace_virtio_blk_handle_write(req, req->out->sector, req->qiov.size / 512);
+ sector = ldq_p(&req->out->sector);
- if (req->out->sector & req->dev->sector_mask) {
+ trace_virtio_blk_handle_write(req, sector, req->qiov.size / 512);
+
+ if (sector & req->dev->sector_mask) {
virtio_blk_rw_complete(req, -EIO);
return;
}
@@ -293,7 +296,7 @@ static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb)
}
blkreq = &mrb->blkreq[mrb->num_writes];
- blkreq->sector = req->out->sector;
+ blkreq->sector = sector;
blkreq->nb_sectors = req->qiov.size / BDRV_SECTOR_SIZE;
blkreq->qiov = &req->qiov;
blkreq->cb = virtio_blk_rw_complete;
@@ -306,13 +309,16 @@ static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb)
static void virtio_blk_handle_read(VirtIOBlockReq *req)
{
BlockDriverAIOCB *acb;
+ uint64_t sector;
+
+ sector = ldq_p(&req->out->sector);
- if (req->out->sector & req->dev->sector_mask) {
+ if (sector & req->dev->sector_mask) {
virtio_blk_rw_complete(req, -EIO);
return;
}
- acb = bdrv_aio_readv(req->dev->bs, req->out->sector, &req->qiov,
+ acb = bdrv_aio_readv(req->dev->bs, sector, &req->qiov,
req->qiov.size / BDRV_SECTOR_SIZE,
virtio_blk_rw_complete, req);
if (!acb) {
@@ -323,6 +329,8 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req)
static void virtio_blk_handle_request(VirtIOBlockReq *req,
MultiReqBuffer *mrb)
{
+ uint32_t type;
+
if (req->elem.out_num < 1 || req->elem.in_num < 1) {
error_report("virtio-blk missing headers");
exit(1);
@@ -337,17 +345,19 @@ static void virtio_blk_handle_request(VirtIOBlockReq *req,
req->out = (void *)req->elem.out_sg[0].iov_base;
req->in = (void *)req->elem.in_sg[req->elem.in_num - 1].iov_base;
- if (req->out->type & VIRTIO_BLK_T_FLUSH) {
+ type = ldl_p(&req->out->type);
+
+ if (type & VIRTIO_BLK_T_FLUSH) {
virtio_blk_handle_flush(req, mrb);
- } else if (req->out->type & VIRTIO_BLK_T_SCSI_CMD) {
+ } else if (type & VIRTIO_BLK_T_SCSI_CMD) {
virtio_blk_handle_scsi(req);
- } else if (req->out->type & VIRTIO_BLK_T_GET_ID) {
+ } else if (type & VIRTIO_BLK_T_GET_ID) {
VirtIOBlock *s = req->dev;
memcpy(req->elem.in_sg[0].iov_base, s->sn,
MIN(req->elem.in_sg[0].iov_len, sizeof(s->sn)));
virtio_blk_req_complete(req, VIRTIO_BLK_S_OK);
- } else if (req->out->type & VIRTIO_BLK_T_OUT) {
+ } else if (type & VIRTIO_BLK_T_OUT) {
qemu_iovec_init_external(&req->qiov, &req->elem.out_sg[1],
req->elem.out_num - 1);
virtio_blk_handle_write(req, mrb);
commit 44b15bc5c65ab6b3103f508504e4adf8ee9902d7
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Tue Jan 25 11:55:14 2011 +0100
virtio-net: fix cross-endianness support
virtio-net used to work on cross-endianness configurations, but doesn't
anymore with recent guest kernels, as the new features don't handle
endianness correctly.
This patch fixes wrong conversion, and add missing ones to make
virtio-net working. Tested on the following configurations:
- i386 guest on x86_64 host
- ppc guest on x86_64 host
- i386 guest on mips host
- ppc guest on mips host
Cc: Anthony Liguori <aliguori at us.ibm.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index ccb3e63..161f114 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -79,7 +79,7 @@ static void virtio_net_get_config(VirtIODevice *vdev, uint8_t *config)
VirtIONet *n = to_virtio_net(vdev);
struct virtio_net_config netcfg;
- netcfg.status = n->status;
+ netcfg.status = lduw_p(&n->status);
memcpy(netcfg.mac, n->mac, ETH_ALEN);
memcpy(config, &netcfg, sizeof(netcfg));
}
@@ -338,7 +338,7 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd,
n->mac_table.multi_overflow = 0;
memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN);
- mac_data.entries = ldl_le_p(elem->out_sg[1].iov_base);
+ mac_data.entries = ldl_p(elem->out_sg[1].iov_base);
if (sizeof(mac_data.entries) +
(mac_data.entries * ETH_ALEN) > elem->out_sg[1].iov_len)
@@ -354,7 +354,7 @@ static int virtio_net_handle_mac(VirtIONet *n, uint8_t cmd,
n->mac_table.first_multi = n->mac_table.in_use;
- mac_data.entries = ldl_le_p(elem->out_sg[2].iov_base);
+ mac_data.entries = ldl_p(elem->out_sg[2].iov_base);
if (sizeof(mac_data.entries) +
(mac_data.entries * ETH_ALEN) > elem->out_sg[2].iov_len)
@@ -384,7 +384,7 @@ static int virtio_net_handle_vlan_table(VirtIONet *n, uint8_t cmd,
return VIRTIO_NET_ERR;
}
- vid = lduw_le_p(elem->out_sg[1].iov_base);
+ vid = lduw_p(elem->out_sg[1].iov_base);
if (vid >= MAX_VLAN)
return VIRTIO_NET_ERR;
@@ -673,8 +673,9 @@ static ssize_t virtio_net_receive(VLANClientState *nc, const uint8_t *buf, size_
virtqueue_fill(n->rx_vq, &elem, total, i++);
}
- if (mhdr)
- mhdr->num_buffers = i;
+ if (mhdr) {
+ mhdr->num_buffers = lduw_p(&i);
+ }
virtqueue_flush(n->rx_vq, i);
virtio_notify(&n->vdev, n->rx_vq);
commit f53671c054ba0b5d5b10e2a7294786fa2f73479e
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Thu Jan 27 08:21:35 2011 +0100
escc: fix interrupt flags
Recent PowerPC kernel end up in kernel panic during boot in -nographic
mode. In this mode the second serial port is used as the udbg console,
and thus a few characters are sent on this port. This activates the
tx interrupt flag, and later choke the Linux kernel, as it was not
expecting such a flag to be set.
The problem here comes from the fact that contrary to most devices the
interrupt flags are only set if the interrupt is enabled. Quoting the
datasheet: "If the corresponding IE bit is not set, the IP for that
source of interrupt will never be set."
This patch fixes that by enabling the interrupt flag only when the
corresponding interrupt is enabled.
Cc: Blue Swirl <blauwirbel at gmail.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/escc.c b/hw/escc.c
index ba60636..f6fd919 100644
--- a/hw/escc.c
+++ b/hw/escc.c
@@ -369,14 +369,18 @@ static inline void set_txint(ChannelState *s)
if (!s->rxint_under_svc) {
s->txint_under_svc = 1;
if (s->chn == chn_a) {
- s->rregs[R_INTR] |= INTR_TXINTA;
+ if (s->wregs[W_INTR] & INTR_TXINT) {
+ s->rregs[R_INTR] |= INTR_TXINTA;
+ }
if (s->wregs[W_MINTR] & MINTR_STATUSHI)
s->otherchn->rregs[R_IVEC] = IVEC_HITXINTA;
else
s->otherchn->rregs[R_IVEC] = IVEC_LOTXINTA;
} else {
s->rregs[R_IVEC] = IVEC_TXINTB;
- s->otherchn->rregs[R_INTR] |= INTR_TXINTB;
+ if (s->wregs[W_INTR] & INTR_TXINT) {
+ s->otherchn->rregs[R_INTR] |= INTR_TXINTB;
+ }
}
escc_update_irq(s);
}
commit 0bb533374a110f22412d95e75768afb8212f8243
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date: Fri Jan 21 19:57:50 2011 +0300
pxa2xx_gpio: switch to using qdev
As noted by Markus Armbruster pxa2xx_gpio vmstate version bumped
because of a change in the or .ilevel / .olevel arrays are saved,
for convenience.
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>
diff --git a/hw/gumstix.c b/hw/gumstix.c
index af8b464..ee63f63 100644
--- a/hw/gumstix.c
+++ b/hw/gumstix.c
@@ -78,7 +78,7 @@ static void connex_init(ram_addr_t ram_size,
/* Interrupt line of NIC is connected to GPIO line 36 */
smc91c111_init(&nd_table[0], 0x04000300,
- pxa2xx_gpio_in_get(cpu->gpio)[36]);
+ qdev_get_gpio_in(cpu->gpio, 36));
}
static void verdex_init(ram_addr_t ram_size,
@@ -117,7 +117,7 @@ static void verdex_init(ram_addr_t ram_size,
/* Interrupt line of NIC is connected to GPIO line 99 */
smc91c111_init(&nd_table[0], 0x04000300,
- pxa2xx_gpio_in_get(cpu->gpio)[99]);
+ qdev_get_gpio_in(cpu->gpio, 99));
}
static QEMUMachine connex_machine = {
diff --git a/hw/pxa.h b/hw/pxa.h
index 8d6a8c3..f73d33b 100644
--- a/hw/pxa.h
+++ b/hw/pxa.h
@@ -70,13 +70,9 @@ void pxa25x_timer_init(target_phys_addr_t base, qemu_irq *irqs);
void pxa27x_timer_init(target_phys_addr_t base, qemu_irq *irqs, qemu_irq irq4);
/* pxa2xx_gpio.c */
-typedef struct PXA2xxGPIOInfo PXA2xxGPIOInfo;
-PXA2xxGPIOInfo *pxa2xx_gpio_init(target_phys_addr_t base,
+DeviceState *pxa2xx_gpio_init(target_phys_addr_t base,
CPUState *env, qemu_irq *pic, int lines);
-qemu_irq *pxa2xx_gpio_in_get(PXA2xxGPIOInfo *s);
-void pxa2xx_gpio_out_set(PXA2xxGPIOInfo *s,
- int line, qemu_irq handler);
-void pxa2xx_gpio_read_notifier(PXA2xxGPIOInfo *s, qemu_irq handler);
+void pxa2xx_gpio_read_notifier(DeviceState *dev, qemu_irq handler);
/* pxa2xx_dma.c */
typedef struct PXA2xxDMAState PXA2xxDMAState;
@@ -132,7 +128,7 @@ typedef struct {
qemu_irq *pic;
qemu_irq reset;
PXA2xxDMAState *dma;
- PXA2xxGPIOInfo *gpio;
+ DeviceState *gpio;
PXA2xxLCDState *lcd;
SSIBus **ssp;
PXA2xxI2CState *i2c[2];
diff --git a/hw/pxa2xx.c b/hw/pxa2xx.c
index 6e72a5c..d966846 100644
--- a/hw/pxa2xx.c
+++ b/hw/pxa2xx.c
@@ -2158,7 +2158,7 @@ PXA2xxState *pxa270_init(unsigned int sdram_size, const char *revision)
/* GPIO1 resets the processor */
/* The handler can be overridden by board-specific code */
- pxa2xx_gpio_out_set(s->gpio, 1, s->reset);
+ qdev_connect_gpio_out(s->gpio, 1, s->reset);
return s;
}
@@ -2279,7 +2279,7 @@ PXA2xxState *pxa255_init(unsigned int sdram_size)
/* GPIO1 resets the processor */
/* The handler can be overridden by board-specific code */
- pxa2xx_gpio_out_set(s->gpio, 1, s->reset);
+ qdev_connect_gpio_out(s->gpio, 1, s->reset);
return s;
}
diff --git a/hw/pxa2xx_gpio.c b/hw/pxa2xx_gpio.c
index 0d03446..789965d 100644
--- a/hw/pxa2xx_gpio.c
+++ b/hw/pxa2xx_gpio.c
@@ -8,15 +8,18 @@
*/
#include "hw.h"
+#include "sysbus.h"
#include "pxa.h"
#define PXA2XX_GPIO_BANKS 4
+typedef struct PXA2xxGPIOInfo PXA2xxGPIOInfo;
struct PXA2xxGPIOInfo {
- qemu_irq *pic;
+ SysBusDevice busdev;
+ qemu_irq irq0, irq1, irqX;
int lines;
+ int ncpu;
CPUState *cpu_env;
- qemu_irq *in;
/* XXX: GNU C vectors are more suitable */
uint32_t ilevel[PXA2XX_GPIO_BANKS];
@@ -66,19 +69,19 @@ static struct {
static void pxa2xx_gpio_irq_update(PXA2xxGPIOInfo *s)
{
if (s->status[0] & (1 << 0))
- qemu_irq_raise(s->pic[PXA2XX_PIC_GPIO_0]);
+ qemu_irq_raise(s->irq0);
else
- qemu_irq_lower(s->pic[PXA2XX_PIC_GPIO_0]);
+ qemu_irq_lower(s->irq0);
if (s->status[0] & (1 << 1))
- qemu_irq_raise(s->pic[PXA2XX_PIC_GPIO_1]);
+ qemu_irq_raise(s->irq1);
else
- qemu_irq_lower(s->pic[PXA2XX_PIC_GPIO_1]);
+ qemu_irq_lower(s->irq1);
if ((s->status[0] & ~3) | s->status[1] | s->status[2] | s->status[3])
- qemu_irq_raise(s->pic[PXA2XX_PIC_GPIO_X]);
+ qemu_irq_raise(s->irqX);
else
- qemu_irq_lower(s->pic[PXA2XX_PIC_GPIO_X]);
+ qemu_irq_lower(s->irqX);
}
/* Bitmap of pins used as standby and sleep wake-up sources. */
@@ -249,96 +252,89 @@ static CPUWriteMemoryFunc * const pxa2xx_gpio_writefn[] = {
pxa2xx_gpio_write
};
-static void pxa2xx_gpio_save(QEMUFile *f, void *opaque)
-{
- PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
- int i;
-
- qemu_put_be32(f, s->lines);
-
- for (i = 0; i < PXA2XX_GPIO_BANKS; i ++) {
- qemu_put_be32s(f, &s->ilevel[i]);
- qemu_put_be32s(f, &s->olevel[i]);
- qemu_put_be32s(f, &s->dir[i]);
- qemu_put_be32s(f, &s->rising[i]);
- qemu_put_be32s(f, &s->falling[i]);
- qemu_put_be32s(f, &s->status[i]);
- qemu_put_be32s(f, &s->gafr[i * 2 + 0]);
- qemu_put_be32s(f, &s->gafr[i * 2 + 1]);
-
- qemu_put_be32s(f, &s->prev_level[i]);
- }
-}
-
-static int pxa2xx_gpio_load(QEMUFile *f, void *opaque, int version_id)
+DeviceState *pxa2xx_gpio_init(target_phys_addr_t base,
+ CPUState *env, qemu_irq *pic, int lines)
{
- PXA2xxGPIOInfo *s = (PXA2xxGPIOInfo *) opaque;
- int i;
+ DeviceState *dev;
- if (qemu_get_be32(f) != s->lines)
- return -EINVAL;
+ dev = qdev_create(NULL, "pxa2xx-gpio");
+ qdev_prop_set_int32(dev, "lines", lines);
+ qdev_prop_set_int32(dev, "ncpu", env->cpu_index);
+ qdev_init_nofail(dev);
- for (i = 0; i < PXA2XX_GPIO_BANKS; i ++) {
- qemu_get_be32s(f, &s->ilevel[i]);
- qemu_get_be32s(f, &s->olevel[i]);
- qemu_get_be32s(f, &s->dir[i]);
- qemu_get_be32s(f, &s->rising[i]);
- qemu_get_be32s(f, &s->falling[i]);
- qemu_get_be32s(f, &s->status[i]);
- qemu_get_be32s(f, &s->gafr[i * 2 + 0]);
- qemu_get_be32s(f, &s->gafr[i * 2 + 1]);
-
- qemu_get_be32s(f, &s->prev_level[i]);
- }
+ sysbus_mmio_map(sysbus_from_qdev(dev), 0, base);
+ sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[PXA2XX_PIC_GPIO_0]);
+ sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[PXA2XX_PIC_GPIO_1]);
+ sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[PXA2XX_PIC_GPIO_X]);
- return 0;
+ return dev;
}
-PXA2xxGPIOInfo *pxa2xx_gpio_init(target_phys_addr_t base,
- CPUState *env, qemu_irq *pic, int lines)
+static int pxa2xx_gpio_initfn(SysBusDevice *dev)
{
int iomemtype;
PXA2xxGPIOInfo *s;
- s = (PXA2xxGPIOInfo *)
- qemu_mallocz(sizeof(PXA2xxGPIOInfo));
- memset(s, 0, sizeof(PXA2xxGPIOInfo));
- s->pic = pic;
- s->lines = lines;
- s->cpu_env = env;
- s->in = qemu_allocate_irqs(pxa2xx_gpio_set, s, lines);
+ s = FROM_SYSBUS(PXA2xxGPIOInfo, dev);
- iomemtype = cpu_register_io_memory(pxa2xx_gpio_readfn,
- pxa2xx_gpio_writefn, s, DEVICE_NATIVE_ENDIAN);
- cpu_register_physical_memory(base, 0x00001000, iomemtype);
+ s->cpu_env = qemu_get_cpu(s->ncpu);
- register_savevm(NULL, "pxa2xx_gpio", 0, 0,
- pxa2xx_gpio_save, pxa2xx_gpio_load, s);
-
- return s;
-}
+ qdev_init_gpio_in(&dev->qdev, pxa2xx_gpio_set, s->lines);
+ qdev_init_gpio_out(&dev->qdev, s->handler, s->lines);
-qemu_irq *pxa2xx_gpio_in_get(PXA2xxGPIOInfo *s)
-{
- return s->in;
-}
+ iomemtype = cpu_register_io_memory(pxa2xx_gpio_readfn,
+ pxa2xx_gpio_writefn, s, DEVICE_NATIVE_ENDIAN);
-void pxa2xx_gpio_out_set(PXA2xxGPIOInfo *s,
- int line, qemu_irq handler)
-{
- if (line >= s->lines) {
- printf("%s: No GPIO pin %i\n", __FUNCTION__, line);
- return;
- }
+ sysbus_init_mmio(dev, 0x1000, iomemtype);
+ sysbus_init_irq(dev, &s->irq0);
+ sysbus_init_irq(dev, &s->irq1);
+ sysbus_init_irq(dev, &s->irqX);
- s->handler[line] = handler;
+ return 0;
}
/*
* Registers a callback to notify on GPLR reads. This normally
* shouldn't be needed but it is used for the hack on Spitz machines.
*/
-void pxa2xx_gpio_read_notifier(PXA2xxGPIOInfo *s, qemu_irq handler)
+void pxa2xx_gpio_read_notifier(DeviceState *dev, qemu_irq handler)
{
+ PXA2xxGPIOInfo *s = FROM_SYSBUS(PXA2xxGPIOInfo, sysbus_from_qdev(dev));
s->read_notify = handler;
}
+
+static const VMStateDescription vmstate_pxa2xx_gpio_regs = {
+ .name = "pxa2xx-gpio",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_INT32(lines, PXA2xxGPIOInfo),
+ VMSTATE_UINT32_ARRAY(ilevel, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
+ VMSTATE_UINT32_ARRAY(olevel, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
+ VMSTATE_UINT32_ARRAY(dir, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
+ VMSTATE_UINT32_ARRAY(rising, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
+ VMSTATE_UINT32_ARRAY(falling, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
+ VMSTATE_UINT32_ARRAY(status, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS),
+ VMSTATE_UINT32_ARRAY(gafr, PXA2xxGPIOInfo, PXA2XX_GPIO_BANKS * 2),
+ VMSTATE_END_OF_LIST(),
+ },
+};
+
+static SysBusDeviceInfo pxa2xx_gpio_info = {
+ .init = pxa2xx_gpio_initfn,
+ .qdev.name = "pxa2xx-gpio",
+ .qdev.desc = "PXA2xx GPIO controller",
+ .qdev.size = sizeof(PXA2xxGPIOInfo),
+ .qdev.props = (Property []) {
+ DEFINE_PROP_INT32("lines", PXA2xxGPIOInfo, lines, 0),
+ DEFINE_PROP_INT32("ncpu", PXA2xxGPIOInfo, ncpu, 0),
+ DEFINE_PROP_END_OF_LIST(),
+ }
+};
+
+static void pxa2xx_gpio_register(void)
+{
+ sysbus_register_withprop(&pxa2xx_gpio_info);
+}
+device_init(pxa2xx_gpio_register);
diff --git a/hw/spitz.c b/hw/spitz.c
index e225931..5b1e42d 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -470,10 +470,10 @@ static void spitz_keyboard_register(PXA2xxState *cpu)
s = FROM_SYSBUS(SpitzKeyboardState, sysbus_from_qdev(dev));
for (i = 0; i < SPITZ_KEY_SENSE_NUM; i ++)
- qdev_connect_gpio_out(dev, i, pxa2xx_gpio_in_get(cpu->gpio)[spitz_gpio_key_sense[i]]);
+ qdev_connect_gpio_out(dev, i, qdev_get_gpio_in(cpu->gpio, spitz_gpio_key_sense[i]));
for (i = 0; i < 5; i ++)
- s->gpiomap[i] = pxa2xx_gpio_in_get(cpu->gpio)[spitz_gpiomap[i]];
+ s->gpiomap[i] = qdev_get_gpio_in(cpu->gpio, spitz_gpiomap[i]);
if (!graphic_rotate)
s->gpiomap[4] = qemu_irq_invert(s->gpiomap[4]);
@@ -482,7 +482,7 @@ static void spitz_keyboard_register(PXA2xxState *cpu)
qemu_set_irq(s->gpiomap[i], 0);
for (i = 0; i < SPITZ_KEY_STROBE_NUM; i ++)
- pxa2xx_gpio_out_set(cpu->gpio, spitz_gpio_key_strobe[i],
+ qdev_connect_gpio_out(cpu->gpio, spitz_gpio_key_strobe[i],
qdev_get_gpio_in(dev, i));
qemu_mod_timer(s->kbdtimer, qemu_get_clock(vm_clock));
@@ -685,7 +685,7 @@ static void spitz_ssp_attach(PXA2xxState *cpu)
bus = qdev_get_child_bus(mux, "ssi1");
dev = ssi_create_slave(bus, "ads7846");
qdev_connect_gpio_out(dev, 0,
- pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_TP_INT]);
+ qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_TP_INT));
bus = qdev_get_child_bus(mux, "ssi2");
max1111 = ssi_create_slave(bus, "max1111");
@@ -693,11 +693,11 @@ static void spitz_ssp_attach(PXA2xxState *cpu)
max111x_set_input(max1111, MAX1111_BATT_TEMP, 0);
max111x_set_input(max1111, MAX1111_ACIN_VOLT, SPITZ_CHARGEON_ACIN);
- pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_LCDCON_CS,
+ qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_LCDCON_CS,
qdev_get_gpio_in(mux, 0));
- pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_ADS7846_CS,
+ qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_ADS7846_CS,
qdev_get_gpio_in(mux, 1));
- pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_MAX1111_CS,
+ qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_MAX1111_CS,
qdev_get_gpio_in(mux, 2));
}
@@ -747,7 +747,7 @@ static void spitz_i2c_setup(PXA2xxState *cpu)
wm = i2c_create_slave(bus, "wm8750", 0);
spitz_wm8750_addr(wm, 0, 0);
- pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_WM,
+ qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_WM,
qemu_allocate_irqs(spitz_wm8750_addr, wm, 1)[0]);
/* .. and to the sound interface. */
cpu->i2s->opaque = wm;
@@ -840,7 +840,7 @@ static int spitz_hsync;
static void spitz_lcd_hsync_handler(void *opaque, int line, int level)
{
PXA2xxState *cpu = (PXA2xxState *) opaque;
- qemu_set_irq(pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_HSYNC], spitz_hsync);
+ qemu_set_irq(qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_HSYNC), spitz_hsync);
spitz_hsync ^= 1;
}
@@ -860,24 +860,24 @@ static void spitz_gpio_setup(PXA2xxState *cpu, int slots)
/* MMC/SD host */
pxa2xx_mmci_handlers(cpu->mmc,
- pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_SD_WP],
- pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_SD_DETECT]);
+ qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_SD_WP),
+ qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_SD_DETECT));
/* Battery lock always closed */
- qemu_irq_raise(pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_BAT_COVER]);
+ qemu_irq_raise(qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_BAT_COVER));
/* Handle reset */
- pxa2xx_gpio_out_set(cpu->gpio, SPITZ_GPIO_ON_RESET, cpu->reset);
+ qdev_connect_gpio_out(cpu->gpio, SPITZ_GPIO_ON_RESET, cpu->reset);
/* PCMCIA signals: card's IRQ and Card-Detect */
if (slots >= 1)
pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[0],
- pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_CF1_IRQ],
- pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_CF1_CD]);
+ qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_CF1_IRQ),
+ qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_CF1_CD));
if (slots >= 2)
pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[1],
- pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_CF2_IRQ],
- pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_CF2_CD]);
+ qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_CF2_IRQ),
+ qdev_get_gpio_in(cpu->gpio, SPITZ_GPIO_CF2_CD));
}
/* Board init. */
diff --git a/hw/tosa.c b/hw/tosa.c
index 18e3be5..0bfab16 100644
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -95,18 +95,18 @@ static void tosa_gpio_setup(PXA2xxState *cpu,
/* MMC/SD host */
pxa2xx_mmci_handlers(cpu->mmc,
qdev_get_gpio_in(scp0, TOSA_GPIO_SD_WP),
- qemu_irq_invert(pxa2xx_gpio_in_get(cpu->gpio)[TOSA_GPIO_nSD_DETECT]));
+ qemu_irq_invert(qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_nSD_DETECT)));
/* Handle reset */
- pxa2xx_gpio_out_set(cpu->gpio, TOSA_GPIO_ON_RESET, cpu->reset);
+ qdev_connect_gpio_out(cpu->gpio, TOSA_GPIO_ON_RESET, cpu->reset);
/* PCMCIA signals: card's IRQ and Card-Detect */
pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[0],
- pxa2xx_gpio_in_get(cpu->gpio)[TOSA_GPIO_CF_IRQ],
- pxa2xx_gpio_in_get(cpu->gpio)[TOSA_GPIO_CF_CD]);
+ qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_CF_IRQ),
+ qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_CF_CD));
pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[1],
- pxa2xx_gpio_in_get(cpu->gpio)[TOSA_GPIO_JC_CF_IRQ],
+ qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_JC_CF_IRQ),
NULL);
qdev_connect_gpio_out(scp1, TOSA_GPIO_BT_LED, outsignals[0]);
@@ -220,7 +220,7 @@ static void tosa_init(ram_addr_t ram_size,
qemu_ram_alloc(NULL, "tosa.rom", TOSA_ROM) | IO_MEM_ROM);
tmio = tc6393xb_init(0x10000000,
- pxa2xx_gpio_in_get(cpu->gpio)[TOSA_GPIO_TC6393XB_INT]);
+ qdev_get_gpio_in(cpu->gpio, TOSA_GPIO_TC6393XB_INT));
scp0 = sysbus_create_simple("scoop", 0x08800000, NULL);
scp1 = sysbus_create_simple("scoop", 0x14800040, NULL);
commit 7ef4227baae2cdd460bfe714393cb8e7e4cff354
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date: Fri Jan 21 19:56:10 2011 +0300
spitz: make spitz-keyboard to use qdev infrastructure
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>
diff --git a/hw/spitz.c b/hw/spitz.c
index ad26049..e225931 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -219,11 +219,10 @@ static const int spitz_gpiomap[5] = {
SPITZ_GPIO_AK_INT, SPITZ_GPIO_SYNC, SPITZ_GPIO_ON_KEY,
SPITZ_GPIO_SWA, SPITZ_GPIO_SWB,
};
-static int spitz_gpio_invert[5] = { 0, 0, 0, 0, 0, };
typedef struct {
+ SysBusDevice busdev;
qemu_irq sense[SPITZ_KEY_SENSE_NUM];
- qemu_irq *strobe;
qemu_irq gpiomap[5];
int keymap[0x80];
uint16_t keyrow[SPITZ_KEY_SENSE_NUM];
@@ -274,8 +273,7 @@ static void spitz_keyboard_keydown(SpitzKeyboardState *s, int keycode)
/* Handle the additional keys */
if ((spitz_keycode >> 4) == SPITZ_KEY_SENSE_NUM) {
- qemu_set_irq(s->gpiomap[spitz_keycode & 0xf], (keycode < 0x80) ^
- spitz_gpio_invert[spitz_keycode & 0xf]);
+ qemu_set_irq(s->gpiomap[spitz_keycode & 0xf], (keycode < 0x80));
return;
}
@@ -293,8 +291,9 @@ static void spitz_keyboard_keydown(SpitzKeyboardState *s, int keycode)
#define QUEUE_KEY(c) s->fifo[(s->fifopos + s->fifolen ++) & 0xf] = c
-static void spitz_keyboard_handler(SpitzKeyboardState *s, int keycode)
+static void spitz_keyboard_handler(void *opaque, int keycode)
{
+ SpitzKeyboardState *s = opaque;
uint16_t code;
int mapcode;
switch (keycode) {
@@ -440,34 +439,15 @@ static void spitz_keyboard_pre_map(SpitzKeyboardState *s)
s->imodifiers = 0;
s->fifopos = 0;
s->fifolen = 0;
- s->kbdtimer = qemu_new_timer(vm_clock, spitz_keyboard_tick, s);
- spitz_keyboard_tick(s);
}
#undef SHIFT
#undef CTRL
#undef FN
-static void spitz_keyboard_save(QEMUFile *f, void *opaque)
+static int spitz_keyboard_post_load(void *opaque, int version_id)
{
SpitzKeyboardState *s = (SpitzKeyboardState *) opaque;
- int i;
-
- qemu_put_be16s(f, &s->sense_state);
- qemu_put_be16s(f, &s->strobe_state);
- for (i = 0; i < 5; i ++)
- qemu_put_byte(f, spitz_gpio_invert[i]);
-}
-
-static int spitz_keyboard_load(QEMUFile *f, void *opaque, int version_id)
-{
- SpitzKeyboardState *s = (SpitzKeyboardState *) opaque;
- int i;
-
- qemu_get_be16s(f, &s->sense_state);
- qemu_get_be16s(f, &s->strobe_state);
- for (i = 0; i < 5; i ++)
- spitz_gpio_invert[i] = qemu_get_byte(f);
/* Release all pressed keys */
memset(s->keyrow, 0, sizeof(s->keyrow));
@@ -482,36 +462,55 @@ static int spitz_keyboard_load(QEMUFile *f, void *opaque, int version_id)
static void spitz_keyboard_register(PXA2xxState *cpu)
{
- int i, j;
+ int i;
+ DeviceState *dev;
SpitzKeyboardState *s;
- s = (SpitzKeyboardState *)
- qemu_mallocz(sizeof(SpitzKeyboardState));
- memset(s, 0, sizeof(SpitzKeyboardState));
-
- for (i = 0; i < 0x80; i ++)
- s->keymap[i] = -1;
- for (i = 0; i < SPITZ_KEY_SENSE_NUM + 1; i ++)
- for (j = 0; j < SPITZ_KEY_STROBE_NUM; j ++)
- if (spitz_keymap[i][j] != -1)
- s->keymap[spitz_keymap[i][j]] = (i << 4) | j;
+ dev = sysbus_create_simple("spitz-keyboard", -1, NULL);
+ s = FROM_SYSBUS(SpitzKeyboardState, sysbus_from_qdev(dev));
for (i = 0; i < SPITZ_KEY_SENSE_NUM; i ++)
- s->sense[i] = pxa2xx_gpio_in_get(cpu->gpio)[spitz_gpio_key_sense[i]];
+ qdev_connect_gpio_out(dev, i, pxa2xx_gpio_in_get(cpu->gpio)[spitz_gpio_key_sense[i]]);
for (i = 0; i < 5; i ++)
s->gpiomap[i] = pxa2xx_gpio_in_get(cpu->gpio)[spitz_gpiomap[i]];
- s->strobe = qemu_allocate_irqs(spitz_keyboard_strobe, s,
- SPITZ_KEY_STROBE_NUM);
+ if (!graphic_rotate)
+ s->gpiomap[4] = qemu_irq_invert(s->gpiomap[4]);
+
+ for (i = 0; i < 5; i++)
+ qemu_set_irq(s->gpiomap[i], 0);
+
for (i = 0; i < SPITZ_KEY_STROBE_NUM; i ++)
- pxa2xx_gpio_out_set(cpu->gpio, spitz_gpio_key_strobe[i], s->strobe[i]);
+ pxa2xx_gpio_out_set(cpu->gpio, spitz_gpio_key_strobe[i],
+ qdev_get_gpio_in(dev, i));
+
+ qemu_mod_timer(s->kbdtimer, qemu_get_clock(vm_clock));
+
+ qemu_add_kbd_event_handler(spitz_keyboard_handler, s);
+}
+
+static int spitz_keyboard_init(SysBusDevice *dev)
+{
+ SpitzKeyboardState *s;
+ int i, j;
+
+ s = FROM_SYSBUS(SpitzKeyboardState, dev);
+
+ for (i = 0; i < 0x80; i ++)
+ s->keymap[i] = -1;
+ for (i = 0; i < SPITZ_KEY_SENSE_NUM + 1; i ++)
+ for (j = 0; j < SPITZ_KEY_STROBE_NUM; j ++)
+ if (spitz_keymap[i][j] != -1)
+ s->keymap[spitz_keymap[i][j]] = (i << 4) | j;
spitz_keyboard_pre_map(s);
- qemu_add_kbd_event_handler((QEMUPutKBDEvent *) spitz_keyboard_handler, s);
- register_savevm(NULL, "spitz_keyboard", 0, 0,
- spitz_keyboard_save, spitz_keyboard_load, s);
+ s->kbdtimer = qemu_new_timer(vm_clock, spitz_keyboard_tick, s);
+ qdev_init_gpio_in(&dev->qdev, spitz_keyboard_strobe, SPITZ_KEY_STROBE_NUM);
+ qdev_init_gpio_out(&dev->qdev, s->sense, SPITZ_KEY_SENSE_NUM);
+
+ return 0;
}
/* LCD backlight controller */
@@ -879,18 +878,6 @@ static void spitz_gpio_setup(PXA2xxState *cpu, int slots)
pxa2xx_pcmcia_set_irq_cb(cpu->pcmcia[1],
pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_CF2_IRQ],
pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_CF2_CD]);
-
- /* Initialise the screen rotation related signals */
- spitz_gpio_invert[3] = 0; /* Always open */
- if (graphic_rotate) { /* Tablet mode */
- spitz_gpio_invert[4] = 0;
- } else { /* Portrait mode */
- spitz_gpio_invert[4] = 1;
- }
- qemu_set_irq(pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_SWA],
- spitz_gpio_invert[3]);
- qemu_set_irq(pxa2xx_gpio_in_get(cpu->gpio)[SPITZ_GPIO_SWB],
- spitz_gpio_invert[4]);
}
/* Board init. */
@@ -1027,6 +1014,11 @@ static void spitz_machine_init(void)
machine_init(spitz_machine_init);
+static bool is_version_0(void *opaque, int version_id)
+{
+ return version_id == 0;
+}
+
static VMStateDescription vmstate_sl_nand_info = {
.name = "sl-nand",
.version_id = 0,
@@ -1051,6 +1043,30 @@ static SysBusDeviceInfo sl_nand_info = {
},
};
+static VMStateDescription vmstate_spitz_kbd = {
+ .name = "spitz-keyboard",
+ .version_id = 1,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .post_load = spitz_keyboard_post_load,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT16(sense_state, SpitzKeyboardState),
+ VMSTATE_UINT16(strobe_state, SpitzKeyboardState),
+ VMSTATE_UNUSED_TEST(is_version_0, 5),
+ VMSTATE_END_OF_LIST(),
+ },
+};
+
+static SysBusDeviceInfo spitz_keyboard_info = {
+ .init = spitz_keyboard_init,
+ .qdev.name = "spitz-keyboard",
+ .qdev.size = sizeof(SpitzKeyboardState),
+ .qdev.vmsd = &vmstate_spitz_kbd,
+ .qdev.props = (Property []) {
+ DEFINE_PROP_END_OF_LIST(),
+ },
+};
+
static const VMStateDescription vmstate_corgi_ssp_regs = {
.name = "corgi-ssp",
.version_id = 1,
@@ -1094,6 +1110,7 @@ static void spitz_register_devices(void)
{
ssi_register_slave(&corgi_ssp_info);
ssi_register_slave(&spitz_lcdtg_info);
+ sysbus_register_withprop(&spitz_keyboard_info);
sysbus_register_withprop(&sl_nand_info);
}
commit 34f9f0b5802a6ff9ec0be00810f7910d3935df3e
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date: Fri Jan 21 13:12:11 2011 +0300
spitz: make sl-nand emulation use qdev infrastructure
Switch sl-nand emulation to use qdev and vmstate. Also drop ecc_get/_put
functions as sl-nand was the only user of that code.
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>
diff --git a/hw/ecc.c b/hw/ecc.c
index 2fbf167..a75408b 100644
--- a/hw/ecc.c
+++ b/hw/ecc.c
@@ -74,18 +74,15 @@ void ecc_reset(ECCState *s)
}
/* Save/restore */
-void ecc_put(QEMUFile *f, ECCState *s)
-{
- qemu_put_8s(f, &s->cp);
- qemu_put_be16s(f, &s->lp[0]);
- qemu_put_be16s(f, &s->lp[1]);
- qemu_put_be16s(f, &s->count);
-}
-
-void ecc_get(QEMUFile *f, ECCState *s)
-{
- qemu_get_8s(f, &s->cp);
- qemu_get_be16s(f, &s->lp[0]);
- qemu_get_be16s(f, &s->lp[1]);
- qemu_get_be16s(f, &s->count);
-}
+VMStateDescription vmstate_ecc_state = {
+ .name = "ecc-state",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT8(cp, ECCState),
+ VMSTATE_UINT16_ARRAY(lp, ECCState, 2),
+ VMSTATE_UINT16(count, ECCState),
+ VMSTATE_END_OF_LIST(),
+ },
+};
diff --git a/hw/flash.h b/hw/flash.h
index a80205c..d7d103e 100644
--- a/hw/flash.h
+++ b/hw/flash.h
@@ -51,5 +51,4 @@ typedef struct {
uint8_t ecc_digest(ECCState *s, uint8_t sample);
void ecc_reset(ECCState *s);
-void ecc_put(QEMUFile *f, ECCState *s);
-void ecc_get(QEMUFile *f, ECCState *s);
+extern VMStateDescription vmstate_ecc_state;
diff --git a/hw/onenand.c b/hw/onenand.c
index d9cdcf2..71c1ab4 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -19,6 +19,7 @@
*/
#include "qemu-common.h"
+#include "hw.h"
#include "flash.h"
#include "irq.h"
#include "blockdev.h"
diff --git a/hw/spitz.c b/hw/spitz.c
index c7a1c60..ad26049 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -47,8 +47,11 @@
#define FLASHCTL_NCE (FLASHCTL_CE0 | FLASHCTL_CE1)
typedef struct {
+ SysBusDevice busdev;
NANDFlashState *nand;
uint8_t ctl;
+ uint8_t manf_id;
+ uint8_t chip_id;
ECCState ecc;
} SLNANDState;
@@ -131,56 +134,53 @@ static void sl_writeb(void *opaque, target_phys_addr_t addr,
}
}
-static void sl_save(QEMUFile *f, void *opaque)
-{
- SLNANDState *s = (SLNANDState *) opaque;
-
- qemu_put_8s(f, &s->ctl);
- ecc_put(f, &s->ecc);
-}
-
-static int sl_load(QEMUFile *f, void *opaque, int version_id)
-{
- SLNANDState *s = (SLNANDState *) opaque;
-
- qemu_get_8s(f, &s->ctl);
- ecc_get(f, &s->ecc);
-
- return 0;
-}
-
enum {
FLASH_128M,
FLASH_1024M,
};
+static CPUReadMemoryFunc * const sl_readfn[] = {
+ sl_readb,
+ sl_readb,
+ sl_readl,
+};
+static CPUWriteMemoryFunc * const sl_writefn[] = {
+ sl_writeb,
+ sl_writeb,
+ sl_writeb,
+};
+
static void sl_flash_register(PXA2xxState *cpu, int size)
{
+ DeviceState *dev;
+
+ dev = qdev_create(NULL, "sl-nand");
+
+ qdev_prop_set_uint8(dev, "manf_id", NAND_MFR_SAMSUNG);
+ if (size == FLASH_128M)
+ qdev_prop_set_uint8(dev, "chip_id", 0x73);
+ else if (size == FLASH_1024M)
+ qdev_prop_set_uint8(dev, "chip_id", 0xf1);
+
+ qdev_init_nofail(dev);
+ sysbus_mmio_map(sysbus_from_qdev(dev), 0, FLASH_BASE);
+}
+
+static int sl_nand_init(SysBusDevice *dev) {
int iomemtype;
SLNANDState *s;
- CPUReadMemoryFunc * const sl_readfn[] = {
- sl_readb,
- sl_readb,
- sl_readl,
- };
- CPUWriteMemoryFunc * const sl_writefn[] = {
- sl_writeb,
- sl_writeb,
- sl_writeb,
- };
-
- s = (SLNANDState *) qemu_mallocz(sizeof(SLNANDState));
+
+ s = FROM_SYSBUS(SLNANDState, dev);
+
s->ctl = 0;
- if (size == FLASH_128M)
- s->nand = nand_init(NAND_MFR_SAMSUNG, 0x73);
- else if (size == FLASH_1024M)
- s->nand = nand_init(NAND_MFR_SAMSUNG, 0xf1);
+ s->nand = nand_init(s->manf_id, s->chip_id);
iomemtype = cpu_register_io_memory(sl_readfn,
sl_writefn, s, DEVICE_NATIVE_ENDIAN);
- cpu_register_physical_memory(FLASH_BASE, 0x40, iomemtype);
- register_savevm(NULL, "sl_flash", 0, 0, sl_save, sl_load, s);
+ sysbus_init_mmio(dev, 0x40, iomemtype);
+
+ return 0;
}
/* Spitz Keyboard */
@@ -1027,6 +1027,30 @@ static void spitz_machine_init(void)
machine_init(spitz_machine_init);
+static VMStateDescription vmstate_sl_nand_info = {
+ .name = "sl-nand",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT8(ctl, SLNANDState),
+ VMSTATE_STRUCT(ecc, SLNANDState, 0, vmstate_ecc_state, ECCState),
+ VMSTATE_END_OF_LIST(),
+ },
+};
+
+static SysBusDeviceInfo sl_nand_info = {
+ .init = sl_nand_init,
+ .qdev.name = "sl-nand",
+ .qdev.size = sizeof(SLNANDState),
+ .qdev.vmsd = &vmstate_sl_nand_info,
+ .qdev.props = (Property []) {
+ DEFINE_PROP_UINT8("manf_id", SLNANDState, manf_id, NAND_MFR_SAMSUNG),
+ DEFINE_PROP_UINT8("chip_id", SLNANDState, chip_id, 0xf1),
+ DEFINE_PROP_END_OF_LIST(),
+ },
+};
+
static const VMStateDescription vmstate_corgi_ssp_regs = {
.name = "corgi-ssp",
.version_id = 1,
@@ -1070,6 +1094,7 @@ static void spitz_register_devices(void)
{
ssi_register_slave(&corgi_ssp_info);
ssi_register_slave(&spitz_lcdtg_info);
+ sysbus_register_withprop(&sl_nand_info);
}
device_init(spitz_register_devices)
commit 43842120f482564ea2059a78ae6b8a93bb18c91d
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date: Thu Jan 20 18:52:28 2011 +0300
Use vmstate to save/load spitz-lcdtg and corgi-ssp state
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>
diff --git a/hw/spitz.c b/hw/spitz.c
index 1e2f16b..c7a1c60 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -527,8 +527,8 @@ static void spitz_keyboard_register(PXA2xxState *cpu)
typedef struct {
SSISlave ssidev;
- int bl_intensity;
- int bl_power;
+ uint32_t bl_intensity;
+ uint32_t bl_power;
} SpitzLCDTG;
static void spitz_bl_update(SpitzLCDTG *s)
@@ -592,21 +592,6 @@ static uint32_t spitz_lcdtg_transfer(SSISlave *dev, uint32_t value)
return 0;
}
-static void spitz_lcdtg_save(QEMUFile *f, void *opaque)
-{
- SpitzLCDTG *s = (SpitzLCDTG *)opaque;
- qemu_put_be32(f, s->bl_intensity);
- qemu_put_be32(f, s->bl_power);
-}
-
-static int spitz_lcdtg_load(QEMUFile *f, void *opaque, int version_id)
-{
- SpitzLCDTG *s = (SpitzLCDTG *)opaque;
- s->bl_intensity = qemu_get_be32(f);
- s->bl_power = qemu_get_be32(f);
- return 0;
-}
-
static int spitz_lcdtg_init(SSISlave *dev)
{
SpitzLCDTG *s = FROM_SSI_SLAVE(SpitzLCDTG, dev);
@@ -615,8 +600,6 @@ static int spitz_lcdtg_init(SSISlave *dev)
s->bl_power = 0;
s->bl_intensity = 0x20;
- register_savevm(&dev->qdev, "spitz-lcdtg", -1, 1,
- spitz_lcdtg_save, spitz_lcdtg_load, s);
return 0;
}
@@ -635,7 +618,7 @@ static DeviceState *max1111;
typedef struct {
SSISlave ssidev;
SSIBus *bus[3];
- int enable[3];
+ uint32_t enable[3];
} CorgiSSPState;
static uint32_t corgi_ssp_transfer(SSISlave *dev, uint32_t value)
@@ -677,30 +660,6 @@ static void spitz_adc_temp_on(void *opaque, int line, int level)
max111x_set_input(max1111, MAX1111_BATT_TEMP, 0);
}
-static void spitz_ssp_save(QEMUFile *f, void *opaque)
-{
- CorgiSSPState *s = (CorgiSSPState *)opaque;
- int i;
-
- for (i = 0; i < 3; i++) {
- qemu_put_be32(f, s->enable[i]);
- }
-}
-
-static int spitz_ssp_load(QEMUFile *f, void *opaque, int version_id)
-{
- CorgiSSPState *s = (CorgiSSPState *)opaque;
- int i;
-
- if (version_id != 1) {
- return -EINVAL;
- }
- for (i = 0; i < 3; i++) {
- s->enable[i] = qemu_get_be32(f);
- }
- return 0;
-}
-
static int corgi_ssp_init(SSISlave *dev)
{
CorgiSSPState *s = FROM_SSI_SLAVE(CorgiSSPState, dev);
@@ -710,8 +669,6 @@ static int corgi_ssp_init(SSISlave *dev)
s->bus[1] = ssi_create_bus(&dev->qdev, "ssi1");
s->bus[2] = ssi_create_bus(&dev->qdev, "ssi2");
- register_savevm(&dev->qdev, "spitz_ssp", -1, 1,
- spitz_ssp_save, spitz_ssp_load, s);
return 0;
}
@@ -1070,16 +1027,41 @@ static void spitz_machine_init(void)
machine_init(spitz_machine_init);
+static const VMStateDescription vmstate_corgi_ssp_regs = {
+ .name = "corgi-ssp",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT32_ARRAY(enable, CorgiSSPState, 3),
+ VMSTATE_END_OF_LIST(),
+ }
+};
+
static SSISlaveInfo corgi_ssp_info = {
.qdev.name = "corgi-ssp",
.qdev.size = sizeof(CorgiSSPState),
+ .qdev.vmsd = &vmstate_corgi_ssp_regs,
.init = corgi_ssp_init,
.transfer = corgi_ssp_transfer
};
+static const VMStateDescription vmstate_spitz_lcdtg_regs = {
+ .name = "spitz-lcdtg",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT32(bl_intensity, SpitzLCDTG),
+ VMSTATE_UINT32(bl_power, SpitzLCDTG),
+ VMSTATE_END_OF_LIST(),
+ }
+};
+
static SSISlaveInfo spitz_lcdtg_info = {
.qdev.name = "spitz-lcdtg",
.qdev.size = sizeof(SpitzLCDTG),
+ .qdev.vmsd = &vmstate_spitz_lcdtg_regs,
.init = spitz_lcdtg_init,
.transfer = spitz_lcdtg_transfer
};
commit 383d01c663290e09d4529bf539ee9e91b75d2fec
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date: Thu Jan 20 18:52:27 2011 +0300
SharpSL scoop device - convert to qdev
Convert SharpSL scoop device to qdev, remove lots of supporting code, as
lot of init and gpio related things can now be done automagically.
Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>
diff --git a/hw/sharpsl.h b/hw/sharpsl.h
index c5ccf79..0b3a774 100644
--- a/hw/sharpsl.h
+++ b/hw/sharpsl.h
@@ -10,13 +10,6 @@
fprintf(stderr, "%s: " format, __FUNCTION__, ##__VA_ARGS__)
/* zaurus.c */
-typedef struct ScoopInfo ScoopInfo;
-ScoopInfo *scoop_init(PXA2xxState *cpu,
- int instance, target_phys_addr_t target_base);
-void scoop_gpio_set(void *opaque, int line, int level);
-qemu_irq *scoop_gpio_in_get(ScoopInfo *s);
-void scoop_gpio_out_set(ScoopInfo *s, int line,
- qemu_irq handler);
#define SL_PXA_PARAM_BASE 0xa0000a00
void sl_bootparam_write(target_phys_addr_t ptr);
diff --git a/hw/spitz.c b/hw/spitz.c
index 092bb64..1e2f16b 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -23,6 +23,7 @@
#include "audio/audio.h"
#include "boards.h"
#include "blockdev.h"
+#include "sysbus.h"
#undef REG_FMT
#define REG_FMT "0x%02lx"
@@ -851,21 +852,21 @@ static void spitz_out_switch(void *opaque, int line, int level)
#define SPITZ_SCP2_MIC_BIAS 9
static void spitz_scoop_gpio_setup(PXA2xxState *cpu,
- ScoopInfo *scp0, ScoopInfo *scp1)
+ DeviceState *scp0, DeviceState *scp1)
{
qemu_irq *outsignals = qemu_allocate_irqs(spitz_out_switch, cpu, 8);
- scoop_gpio_out_set(scp0, SPITZ_SCP_CHRG_ON, outsignals[0]);
- scoop_gpio_out_set(scp0, SPITZ_SCP_JK_B, outsignals[1]);
- scoop_gpio_out_set(scp0, SPITZ_SCP_LED_GREEN, outsignals[2]);
- scoop_gpio_out_set(scp0, SPITZ_SCP_LED_ORANGE, outsignals[3]);
+ qdev_connect_gpio_out(scp0, SPITZ_SCP_CHRG_ON, outsignals[0]);
+ qdev_connect_gpio_out(scp0, SPITZ_SCP_JK_B, outsignals[1]);
+ qdev_connect_gpio_out(scp0, SPITZ_SCP_LED_GREEN, outsignals[2]);
+ qdev_connect_gpio_out(scp0, SPITZ_SCP_LED_ORANGE, outsignals[3]);
if (scp1) {
- scoop_gpio_out_set(scp1, SPITZ_SCP2_BACKLIGHT_CONT, outsignals[4]);
- scoop_gpio_out_set(scp1, SPITZ_SCP2_BACKLIGHT_ON, outsignals[5]);
+ qdev_connect_gpio_out(scp1, SPITZ_SCP2_BACKLIGHT_CONT, outsignals[4]);
+ qdev_connect_gpio_out(scp1, SPITZ_SCP2_BACKLIGHT_ON, outsignals[5]);
}
- scoop_gpio_out_set(scp0, SPITZ_SCP_ADC_TEMP_ON, outsignals[6]);
+ qdev_connect_gpio_out(scp0, SPITZ_SCP_ADC_TEMP_ON, outsignals[6]);
}
#define SPITZ_GPIO_HSYNC 22
@@ -952,7 +953,7 @@ static void spitz_common_init(ram_addr_t ram_size,
const char *cpu_model, enum spitz_model_e model, int arm_id)
{
PXA2xxState *cpu;
- ScoopInfo *scp0, *scp1 = NULL;
+ DeviceState *scp0, *scp1 = NULL;
if (!cpu_model)
cpu_model = (model == terrier) ? "pxa270-c5" : "pxa270-c0";
@@ -970,9 +971,9 @@ static void spitz_common_init(ram_addr_t ram_size,
spitz_ssp_attach(cpu);
- scp0 = scoop_init(cpu, 0, 0x10800000);
+ scp0 = sysbus_create_simple("scoop", 0x10800000, NULL);
if (model != akita) {
- scp1 = scoop_init(cpu, 1, 0x08800040);
+ scp1 = sysbus_create_simple("scoop", 0x08800040, NULL);
}
spitz_scoop_gpio_setup(cpu, scp0, scp1);
diff --git a/hw/tosa.c b/hw/tosa.c
index cc8ce6d..18e3be5 100644
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -20,6 +20,7 @@
#include "i2c.h"
#include "ssi.h"
#include "blockdev.h"
+#include "sysbus.h"
#define TOSA_RAM 0x04000000
#define TOSA_ROM 0x00800000
@@ -86,14 +87,14 @@ static void tosa_out_switch(void *opaque, int line, int level)
static void tosa_gpio_setup(PXA2xxState *cpu,
- ScoopInfo *scp0,
- ScoopInfo *scp1,
+ DeviceState *scp0,
+ DeviceState *scp1,
TC6393xbState *tmio)
{
qemu_irq *outsignals = qemu_allocate_irqs(tosa_out_switch, cpu, 4);
/* MMC/SD host */
pxa2xx_mmci_handlers(cpu->mmc,
- scoop_gpio_in_get(scp0)[TOSA_GPIO_SD_WP],
+ qdev_get_gpio_in(scp0, TOSA_GPIO_SD_WP),
qemu_irq_invert(pxa2xx_gpio_in_get(cpu->gpio)[TOSA_GPIO_nSD_DETECT]));
/* Handle reset */
@@ -108,12 +109,12 @@ static void tosa_gpio_setup(PXA2xxState *cpu,
pxa2xx_gpio_in_get(cpu->gpio)[TOSA_GPIO_JC_CF_IRQ],
NULL);
- scoop_gpio_out_set(scp1, TOSA_GPIO_BT_LED, outsignals[0]);
- scoop_gpio_out_set(scp1, TOSA_GPIO_NOTE_LED, outsignals[1]);
- scoop_gpio_out_set(scp1, TOSA_GPIO_CHRG_ERR_LED, outsignals[2]);
- scoop_gpio_out_set(scp1, TOSA_GPIO_WLAN_LED, outsignals[3]);
+ qdev_connect_gpio_out(scp1, TOSA_GPIO_BT_LED, outsignals[0]);
+ qdev_connect_gpio_out(scp1, TOSA_GPIO_NOTE_LED, outsignals[1]);
+ qdev_connect_gpio_out(scp1, TOSA_GPIO_CHRG_ERR_LED, outsignals[2]);
+ qdev_connect_gpio_out(scp1, TOSA_GPIO_WLAN_LED, outsignals[3]);
- scoop_gpio_out_set(scp1, TOSA_GPIO_TC6393XB_L3V_ON, tc6393xb_l3v_get(tmio));
+ qdev_connect_gpio_out(scp1, TOSA_GPIO_TC6393XB_L3V_ON, tc6393xb_l3v_get(tmio));
}
static uint32_t tosa_ssp_tansfer(SSISlave *dev, uint32_t value)
@@ -208,7 +209,7 @@ static void tosa_init(ram_addr_t ram_size,
{
PXA2xxState *cpu;
TC6393xbState *tmio;
- ScoopInfo *scp0, *scp1;
+ DeviceState *scp0, *scp1;
if (!cpu_model)
cpu_model = "pxa255";
@@ -221,8 +222,8 @@ static void tosa_init(ram_addr_t ram_size,
tmio = tc6393xb_init(0x10000000,
pxa2xx_gpio_in_get(cpu->gpio)[TOSA_GPIO_TC6393XB_INT]);
- scp0 = scoop_init(cpu, 0, 0x08800000);
- scp1 = scoop_init(cpu, 1, 0x14800040);
+ scp0 = sysbus_create_simple("scoop", 0x08800000, NULL);
+ scp1 = sysbus_create_simple("scoop", 0x14800040, NULL);
tosa_gpio_setup(cpu, scp0, scp1, tmio);
diff --git a/hw/zaurus.c b/hw/zaurus.c
index 36be94a..fca11a5 100644
--- a/hw/zaurus.c
+++ b/hw/zaurus.c
@@ -18,15 +18,17 @@
#include "hw.h"
#include "pxa.h"
#include "sharpsl.h"
+#include "sysbus.h"
#undef REG_FMT
#define REG_FMT "0x%02lx"
/* SCOOP devices */
+typedef struct ScoopInfo ScoopInfo;
struct ScoopInfo {
+ SysBusDevice busdev;
qemu_irq handler[16];
- qemu_irq *in;
uint16_t status;
uint16_t power;
uint32_t gpio_level;
@@ -153,7 +155,7 @@ static CPUWriteMemoryFunc * const scoop_writefn[] = {
scoop_writeb,
};
-void scoop_gpio_set(void *opaque, int line, int level)
+static void scoop_gpio_set(void *opaque, int line, int level)
{
ScoopInfo *s = (ScoopInfo *) opaque;
@@ -163,77 +165,66 @@ void scoop_gpio_set(void *opaque, int line, int level)
s->gpio_level &= ~(1 << line);
}
-qemu_irq *scoop_gpio_in_get(ScoopInfo *s)
+static int scoop_init(SysBusDevice *dev)
{
- return s->in;
-}
+ ScoopInfo *s = FROM_SYSBUS(ScoopInfo, dev);
+ int iomemtype;
-void scoop_gpio_out_set(ScoopInfo *s, int line,
- qemu_irq handler) {
- if (line >= 16) {
- fprintf(stderr, "No GPIO pin %i\n", line);
- exit(-1);
- }
+ s->status = 0x02;
+ qdev_init_gpio_out(&s->busdev.qdev, s->handler, 16);
+ qdev_init_gpio_in(&s->busdev.qdev, scoop_gpio_set, 16);
+ iomemtype = cpu_register_io_memory(scoop_readfn,
+ scoop_writefn, s, DEVICE_NATIVE_ENDIAN);
- s->handler[line] = handler;
-}
+ sysbus_init_mmio(dev, 0x1000, iomemtype);
-static void scoop_save(QEMUFile *f, void *opaque)
-{
- ScoopInfo *s = (ScoopInfo *) opaque;
- qemu_put_be16s(f, &s->status);
- qemu_put_be16s(f, &s->power);
- qemu_put_be32s(f, &s->gpio_level);
- qemu_put_be32s(f, &s->gpio_dir);
- qemu_put_be32s(f, &s->prev_level);
- qemu_put_be16s(f, &s->mcr);
- qemu_put_be16s(f, &s->cdr);
- qemu_put_be16s(f, &s->ccr);
- qemu_put_be16s(f, &s->irr);
- qemu_put_be16s(f, &s->imr);
- qemu_put_be16s(f, &s->isr);
+ return 0;
}
-static int scoop_load(QEMUFile *f, void *opaque, int version_id)
+static bool is_version_0 (void *opaque, int version_id)
{
- uint16_t dummy;
- ScoopInfo *s = (ScoopInfo *) opaque;
- qemu_get_be16s(f, &s->status);
- qemu_get_be16s(f, &s->power);
- qemu_get_be32s(f, &s->gpio_level);
- qemu_get_be32s(f, &s->gpio_dir);
- qemu_get_be32s(f, &s->prev_level);
- qemu_get_be16s(f, &s->mcr);
- qemu_get_be16s(f, &s->cdr);
- qemu_get_be16s(f, &s->ccr);
- qemu_get_be16s(f, &s->irr);
- qemu_get_be16s(f, &s->imr);
- qemu_get_be16s(f, &s->isr);
- if (version_id < 1)
- qemu_get_be16s(f, &dummy);
-
- return 0;
+ return version_id == 0;
}
-ScoopInfo *scoop_init(PXA2xxState *cpu,
- int instance,
- target_phys_addr_t target_base) {
- int iomemtype;
- ScoopInfo *s;
- s = (ScoopInfo *)
- qemu_mallocz(sizeof(ScoopInfo));
- memset(s, 0, sizeof(ScoopInfo));
+static const VMStateDescription vmstate_scoop_regs = {
+ .name = "scoop",
+ .version_id = 1,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT16(status, ScoopInfo),
+ VMSTATE_UINT16(power, ScoopInfo),
+ VMSTATE_UINT32(gpio_level, ScoopInfo),
+ VMSTATE_UINT32(gpio_dir, ScoopInfo),
+ VMSTATE_UINT32(prev_level, ScoopInfo),
+ VMSTATE_UINT16(mcr, ScoopInfo),
+ VMSTATE_UINT16(cdr, ScoopInfo),
+ VMSTATE_UINT16(ccr, ScoopInfo),
+ VMSTATE_UINT16(irr, ScoopInfo),
+ VMSTATE_UINT16(imr, ScoopInfo),
+ VMSTATE_UINT16(isr, ScoopInfo),
+ VMSTATE_UNUSED_TEST(is_version_0, 2),
+ VMSTATE_END_OF_LIST(),
+ },
+};
- s->status = 0x02;
- s->in = qemu_allocate_irqs(scoop_gpio_set, s, 16);
- iomemtype = cpu_register_io_memory(scoop_readfn,
- scoop_writefn, s, DEVICE_NATIVE_ENDIAN);
- cpu_register_physical_memory(target_base, 0x1000, iomemtype);
- register_savevm(NULL, "scoop", instance, 1, scoop_save, scoop_load, s);
+static SysBusDeviceInfo scoop_sysbus_info = {
+ .init = scoop_init,
+ .qdev.name = "scoop",
+ .qdev.desc = "Scoop2 Sharp custom ASIC",
+ .qdev.size = sizeof(ScoopInfo),
+ .qdev.vmsd = &vmstate_scoop_regs,
+ .qdev.props = (Property[]) {
+ DEFINE_PROP_END_OF_LIST(),
+ }
+};
- return s;
+static void scoop_register(void)
+{
+ sysbus_register_withprop(&scoop_sysbus_info);
}
+device_init(scoop_register);
/* Write the bootloader parameters memory area. */
commit 4c90051801725d5bd12979a585a8da5f1eecd497
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date: Thu Jan 27 12:49:04 2011 +0900
pci: typo in pcibus_get_dev_path()
This patch fixes typo in pcibus_get_dev_path().
Without this patch, the result of pcibus_get_dev_path() isn't unique.
Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/pci.c b/hw/pci.c
index 712280a..d5bbba9 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -2072,7 +2072,7 @@ static char *pcibus_get_dev_path(DeviceState *dev)
for (t = d; t; t = t->bus->parent_dev) {
p -= slot_len;
s = snprintf(slot, sizeof slot, ":%02x.%x",
- PCI_SLOT(t->devfn), PCI_FUNC(d->devfn));
+ PCI_SLOT(t->devfn), PCI_FUNC(t->devfn));
assert(s == slot_len);
memcpy(p, slot, slot_len);
}
commit bb34007e86aa2a7902ee60e0f6fa2f0e4cccbffe
Author: Michael S. Tsirkin <mst at redhat.com>
Date: Wed Jan 26 15:55:07 2011 +0200
pci: bridge control fixup
PCI_BRIDGE_CTL_DISCARD_STATUS (bit 10 in bridge control register)
is W1C so we should not make it writeable, otherwise the assert(!(wmask
& w1cmask)) in pci_default_write_config() is hit
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
Reported-by: Isaku Yamahata <yamahata at valinux.co.jp>
Tested-by: Isaku Yamahata <yamahata at valinux.co.jp>
diff --git a/hw/pci.c b/hw/pci.c
index 044c4bd..712280a 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -641,7 +641,6 @@ static void pci_init_wmask_bridge(PCIDevice *d)
PCI_BRIDGE_CTL_FAST_BACK |
PCI_BRIDGE_CTL_DISCARD |
PCI_BRIDGE_CTL_SEC_DISCARD |
- PCI_BRIDGE_CTL_DISCARD_STATUS |
PCI_BRIDGE_CTL_DISCARD_SERR);
/* Below does not do anything as we never set this bit, put here for
* completeness. */
commit ea87e95f8fda609fa665c2abd33c30ae65e6fae2
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sun Jan 23 08:48:41 2011 +0000
usb-bus: use snprintf
Avoid this warning from OpenBSD linker:
LINK i386-softmmu/qemu
../usb-bus.o(.text+0x27c): In function `usb_get_fw_dev_path':
/src/qemu/hw/usb-bus.c:294: warning: sprintf() is often misused,
please use snprintf()
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index ac56fbc..abc7e61 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -298,20 +298,22 @@ static char *usb_get_fw_dev_path(DeviceState *qdev)
{
USBDevice *dev = DO_UPCAST(USBDevice, qdev, qdev);
char *fw_path, *in;
- int pos = 0;
+ ssize_t pos = 0, fw_len;
long nr;
- fw_path = qemu_malloc(32 + strlen(dev->port->path) * 6);
+ fw_len = 32 + strlen(dev->port->path) * 6;
+ fw_path = qemu_malloc(fw_len);
in = dev->port->path;
- while (true) {
+ while (fw_len - pos > 0) {
nr = strtol(in, &in, 10);
if (in[0] == '.') {
/* some hub between root port and device */
- pos += sprintf(fw_path + pos, "hub@%ld/", nr);
+ pos += snprintf(fw_path + pos, fw_len - pos, "hub@%ld/", nr);
in++;
} else {
/* the device itself */
- pos += sprintf(fw_path + pos, "%s@%ld", qdev_fw_name(qdev), nr);
+ pos += snprintf(fw_path + pos, fw_len - pos, "%s@%ld",
+ qdev_fw_name(qdev), nr);
break;
}
}
commit ee59e6b3bf2074774a0626bc3d5389f2b7bd05bd
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Fri Dec 10 14:40:30 2010 +0100
usb hid: add migration support
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 168e67d..79b20df 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -65,7 +65,7 @@ typedef struct USBKeyboardState {
uint16_t modifiers;
uint8_t leds;
uint8_t key[16];
- int keys;
+ int32_t keys;
} USBKeyboardState;
typedef struct USBHIDState {
@@ -77,7 +77,7 @@ typedef struct USBHIDState {
uint32_t head; /* index into circular queue */
uint32_t n;
int kind;
- int protocol;
+ int32_t protocol;
uint8_t idle;
int64_t next_idle_clock;
int changed;
@@ -895,12 +895,72 @@ void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
s->datain = datain;
}
+static int usb_hid_post_load(void *opaque, int version_id)
+{
+ USBHIDState *s = opaque;
+
+ if (s->idle) {
+ usb_hid_set_next_idle(s, qemu_get_clock(vm_clock));
+ }
+ return 0;
+}
+
+static const VMStateDescription vmstate_usb_ptr_queue = {
+ .name = "usb-ptr-queue",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_INT32(xdx, USBPointerEvent),
+ VMSTATE_INT32(ydy, USBPointerEvent),
+ VMSTATE_INT32(dz, USBPointerEvent),
+ VMSTATE_INT32(buttons_state, USBPointerEvent),
+ VMSTATE_END_OF_LIST()
+ }
+};
+static const VMStateDescription vmstate_usb_ptr = {
+ .name = "usb-ptr",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .post_load = usb_hid_post_load,
+ .fields = (VMStateField []) {
+ VMSTATE_USB_DEVICE(dev, USBHIDState),
+ VMSTATE_STRUCT_ARRAY(ptr.queue, USBHIDState, QUEUE_LENGTH, 0,
+ vmstate_usb_ptr_queue, USBPointerEvent),
+ VMSTATE_UINT32(head, USBHIDState),
+ VMSTATE_UINT32(n, USBHIDState),
+ VMSTATE_INT32(protocol, USBHIDState),
+ VMSTATE_UINT8(idle, USBHIDState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_usb_kbd = {
+ .name = "usb-kbd",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .post_load = usb_hid_post_load,
+ .fields = (VMStateField []) {
+ VMSTATE_USB_DEVICE(dev, USBHIDState),
+ VMSTATE_UINT32_ARRAY(kbd.keycodes, USBHIDState, QUEUE_LENGTH),
+ VMSTATE_UINT32(head, USBHIDState),
+ VMSTATE_UINT32(n, USBHIDState),
+ VMSTATE_UINT16(kbd.modifiers, USBHIDState),
+ VMSTATE_UINT8(kbd.leds, USBHIDState),
+ VMSTATE_UINT8_ARRAY(kbd.key, USBHIDState, 16),
+ VMSTATE_INT32(kbd.keys, USBHIDState),
+ VMSTATE_INT32(protocol, USBHIDState),
+ VMSTATE_UINT8(idle, USBHIDState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static struct USBDeviceInfo hid_info[] = {
{
.product_desc = "QEMU USB Tablet",
.qdev.name = "usb-tablet",
.usbdevice_name = "tablet",
.qdev.size = sizeof(USBHIDState),
+ .qdev.vmsd = &vmstate_usb_ptr,
.usb_desc = &desc_tablet,
.init = usb_tablet_initfn,
.handle_packet = usb_generic_handle_packet,
@@ -913,6 +973,7 @@ static struct USBDeviceInfo hid_info[] = {
.qdev.name = "usb-mouse",
.usbdevice_name = "mouse",
.qdev.size = sizeof(USBHIDState),
+ .qdev.vmsd = &vmstate_usb_ptr,
.usb_desc = &desc_mouse,
.init = usb_mouse_initfn,
.handle_packet = usb_generic_handle_packet,
@@ -925,6 +986,7 @@ static struct USBDeviceInfo hid_info[] = {
.qdev.name = "usb-kbd",
.usbdevice_name = "keyboard",
.qdev.size = sizeof(USBHIDState),
+ .qdev.vmsd = &vmstate_usb_kbd,
.usb_desc = &desc_keyboard,
.init = usb_keyboard_initfn,
.handle_packet = usb_generic_handle_packet,
commit d15500902adb79034ef40ee3a06bbc0a7e0d8b19
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Wed Dec 15 12:45:24 2010 +0100
usb hub: add migration support
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index 78698ca..3dd31ba 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -544,11 +544,35 @@ static int usb_hub_initfn(USBDevice *dev)
return 0;
}
+static const VMStateDescription vmstate_usb_hub_port = {
+ .name = "usb-hub-port",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT16(wPortStatus, USBHubPort),
+ VMSTATE_UINT16(wPortChange, USBHubPort),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_usb_hub = {
+ .name = "usb-hub",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_USB_DEVICE(dev, USBHubState),
+ VMSTATE_STRUCT_ARRAY(ports, USBHubState, NUM_PORTS, 0,
+ vmstate_usb_hub_port, USBHubPort),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static struct USBDeviceInfo hub_info = {
.product_desc = "QEMU USB Hub",
.qdev.name = "usb-hub",
.qdev.fw_name = "hub",
.qdev.size = sizeof(USBHubState),
+ .qdev.vmsd = &vmstate_usb_hub,
.usb_desc = &desc_hub,
.init = usb_hub_initfn,
.handle_packet = usb_hub_handle_packet,
commit c1ecb40a6124b80f1e346e38a1975e82da6507ca
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Fri Dec 10 14:20:46 2010 +0100
usb core: add migration support
Yes, seriously. There is no migration support at all for usb devices.
They loose state, especially the device address, and stop responding
because of that. Oops.
Luckily there is so much broken usb hardware out there that the guest
usually just kicks the device hard (via port reset and
reinitialization), then continues without a hitch. So we got away with
that in a surprising high number of cases.
The arrival of remote wakeup (which enables autosuspend support) changes
that picture though. The usb devices also forget that it they are
supposed to wakeup, so they don't do that. The host also doesn't notice
the device stopped working in case it suspended the device and thus
expects it waking up instead of polling it. Result is that your mouse
is dead.
Lets start fixing that. Add a vmstate struct for USBDevice.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/hw.h b/hw/hw.h
index dd993de..5e24329 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -587,6 +587,16 @@ extern const VMStateDescription vmstate_i2c_slave;
.offset = vmstate_offset_value(_state, _field, i2c_slave), \
}
+extern const VMStateDescription vmstate_usb_device;
+
+#define VMSTATE_USB_DEVICE(_field, _state) { \
+ .name = (stringify(_field)), \
+ .size = sizeof(USBDevice), \
+ .vmsd = &vmstate_usb_device, \
+ .flags = VMS_STRUCT, \
+ .offset = vmstate_offset_value(_state, _field, USBDevice), \
+}
+
#define vmstate_offset_macaddr(_state, _field) \
vmstate_offset_array(_state, _field.a, uint8_t, \
sizeof(typeof_field(_state, _field)))
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index 6e2e5fd..ac56fbc 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -23,6 +23,22 @@ static struct BusInfo usb_bus_info = {
static int next_usb_bus = 0;
static QTAILQ_HEAD(, USBBus) busses = QTAILQ_HEAD_INITIALIZER(busses);
+const VMStateDescription vmstate_usb_device = {
+ .name = "USBDevice",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT8(addr, USBDevice),
+ VMSTATE_INT32(state, USBDevice),
+ VMSTATE_INT32(remote_wakeup, USBDevice),
+ VMSTATE_INT32(setup_state, USBDevice),
+ VMSTATE_INT32(setup_len, USBDevice),
+ VMSTATE_INT32(setup_index, USBDevice),
+ VMSTATE_UINT8_ARRAY(setup_buf, USBDevice, 8),
+ VMSTATE_END_OF_LIST(),
+ }
+};
+
void usb_bus_new(USBBus *bus, DeviceState *host)
{
qbus_create_inplace(&bus->qbus, &usb_bus_info, host, NULL);
diff --git a/hw/usb.h b/hw/usb.h
index 5c1da3e..d3d755d 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -165,13 +165,13 @@ struct USBDevice {
int auto_attach;
int attached;
- int state;
+ int32_t state;
uint8_t setup_buf[8];
uint8_t data_buf[1024];
- int remote_wakeup;
- int setup_state;
- int setup_len;
- int setup_index;
+ int32_t remote_wakeup;
+ int32_t setup_state;
+ int32_t setup_len;
+ int32_t setup_index;
QLIST_HEAD(, USBDescString) strings;
const USBDescDevice *device;
commit 9892088b52da05c3944e84982922fa984e048044
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Fri Jan 14 10:56:54 2011 +0100
vnc: fix numlock+capslock tracking
This patch makes the numlock+capslock tracking logic only look at
keydown events. Without this patch the vnc server will insert
bogous capslock keypress in case it sees the following key sequence:
shift down --- 'A' down --- shift up --- 'A' up
^ here
It doesn't hurt with a PS/2 keyboard, but it disturbs the USB Keyboard.
And with the key event queue just added to the usb keyboard the guest
will actually notice.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/ui/vnc.c b/ui/vnc.c
index 495d6d6..0820d99 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -1504,7 +1504,7 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
break;
}
- if (vs->vd->lock_key_sync &&
+ if (down && vs->vd->lock_key_sync &&
keycode_is_keypad(vs->vd->kbd_layout, keycode)) {
/* If the numlock state needs to change then simulate an additional
keypress before sending this one. This will happen if the user
@@ -1523,7 +1523,7 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
}
}
- if (vs->vd->lock_key_sync &&
+ if (down && vs->vd->lock_key_sync &&
((sym >= 'A' && sym <= 'Z') || (sym >= 'a' && sym <= 'z'))) {
/* If the capslock state needs to change then simulate an additional
keypress before sending this one. This will happen if the user
commit 42292d4e51ac01eb28360d53127337fe275c39c5
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Fri Jan 14 09:23:22 2011 +0100
usb hid: move head+n to common struct
This patch moves the 'head' and 'n' fields from USBMouseState and
USBKeyboardState to the common USBHIDState struct.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 5f1451b..168e67d 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -56,16 +56,12 @@ typedef struct USBPointerEvent {
typedef struct USBMouseState {
USBPointerEvent queue[QUEUE_LENGTH];
- uint32_t head; /* index into circular queue */
- uint32_t n;
int mouse_grabbed;
QEMUPutMouseEntry *eh_entry;
} USBMouseState;
typedef struct USBKeyboardState {
uint32_t keycodes[QUEUE_LENGTH];
- uint32_t head; /* index into circular queue */
- uint32_t n;
uint16_t modifiers;
uint8_t leds;
uint8_t key[16];
@@ -78,6 +74,8 @@ typedef struct USBHIDState {
USBMouseState ptr;
USBKeyboardState kbd;
};
+ uint32_t head; /* index into circular queue */
+ uint32_t n;
int kind;
int protocol;
uint8_t idle;
@@ -468,7 +466,7 @@ static void usb_pointer_event(void *opaque,
{
USBHIDState *hs = opaque;
USBMouseState *s = &hs->ptr;
- unsigned use_slot = (s->head + s->n - 1) & QUEUE_MASK;
+ unsigned use_slot = (hs->head + hs->n - 1) & QUEUE_MASK;
unsigned previous_slot = (use_slot - 1) & QUEUE_MASK;
/* We combine events where feasible to keep the queue small. We shouldn't
@@ -476,15 +474,15 @@ static void usb_pointer_event(void *opaque,
* that would change the location of the button state change. When the
* queue is empty, a second event is needed because we don't know if
* the first event changed the button state. */
- if (s->n == QUEUE_LENGTH) {
+ if (hs->n == QUEUE_LENGTH) {
/* Queue full. Discard old button state, combine motion normally. */
s->queue[use_slot].buttons_state = buttons_state;
- } else if (s->n < 2 ||
+ } else if (hs->n < 2 ||
s->queue[use_slot].buttons_state != buttons_state ||
s->queue[previous_slot].buttons_state != s->queue[use_slot].buttons_state) {
/* Cannot or should not combine, so add an empty item to the queue. */
QUEUE_INCR(use_slot);
- s->n++;
+ hs->n++;
usb_pointer_event_clear(&s->queue[use_slot], buttons_state);
}
usb_pointer_event_combine(&s->queue[use_slot],
@@ -499,24 +497,25 @@ static void usb_keyboard_event(void *opaque, int keycode)
USBKeyboardState *s = &hs->kbd;
int slot;
- if (s->n == QUEUE_LENGTH) {
+ if (hs->n == QUEUE_LENGTH) {
fprintf(stderr, "usb-kbd: warning: key event queue full\n");
return;
}
- slot = (s->head + s->n) & QUEUE_MASK; s->n++;
+ slot = (hs->head + hs->n) & QUEUE_MASK; hs->n++;
s->keycodes[slot] = keycode;
usb_hid_changed(hs);
}
-static void usb_keyboard_process_keycode(USBKeyboardState *s)
+static void usb_keyboard_process_keycode(USBHIDState *hs)
{
+ USBKeyboardState *s = &hs->kbd;
uint8_t hid_code, key;
int i, keycode, slot;
- if (s->n == 0) {
+ if (hs->n == 0) {
return;
}
- slot = s->head & QUEUE_MASK; QUEUE_INCR(s->head); s->n--;
+ slot = hs->head & QUEUE_MASK; QUEUE_INCR(hs->head); hs->n--;
keycode = s->keycodes[slot];
key = keycode & 0x7f;
@@ -590,7 +589,7 @@ static int usb_pointer_poll(USBHIDState *hs, uint8_t *buf, int len)
/* When the buffer is empty, return the last event. Relative
movements will all be zero. */
- index = (s->n ? s->head : s->head - 1);
+ index = (hs->n ? hs->head : hs->head - 1);
e = &s->queue[index & QUEUE_MASK];
if (hs->kind == USB_MOUSE) {
@@ -613,12 +612,12 @@ static int usb_pointer_poll(USBHIDState *hs, uint8_t *buf, int len)
if (e->buttons_state & MOUSE_EVENT_MBUTTON)
b |= 0x04;
- if (s->n &&
+ if (hs->n &&
!e->dz &&
(hs->kind == USB_TABLET || (!e->xdx && !e->ydy))) {
/* that deals with this event */
- QUEUE_INCR(s->head);
- s->n--;
+ QUEUE_INCR(hs->head);
+ hs->n--;
}
/* Appears we have to invert the wheel direction */
@@ -664,7 +663,7 @@ static int usb_keyboard_poll(USBHIDState *hs, uint8_t *buf, int len)
if (len < 2)
return 0;
- usb_keyboard_process_keycode(s);
+ usb_keyboard_process_keycode(hs);
buf[0] = s->modifiers & 0xff;
buf[1] = 0;
@@ -702,8 +701,8 @@ static void usb_mouse_handle_reset(USBDevice *dev)
USBHIDState *s = (USBHIDState *)dev;
memset(s->ptr.queue, 0, sizeof (s->ptr.queue));
- s->ptr.head = 0;
- s->ptr.n = 0;
+ s->head = 0;
+ s->n = 0;
s->protocol = 1;
}
@@ -713,8 +712,8 @@ static void usb_keyboard_handle_reset(USBDevice *dev)
qemu_add_kbd_event_handler(usb_keyboard_event, s);
memset(s->kbd.keycodes, 0, sizeof (s->kbd.keycodes));
- s->kbd.head = 0;
- s->kbd.n = 0;
+ s->head = 0;
+ s->n = 0;
memset(s->kbd.key, 0, sizeof (s->kbd.key));
s->kbd.keys = 0;
s->protocol = 1;
@@ -822,12 +821,11 @@ static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
usb_hid_set_next_idle(s, curtime);
if (s->kind == USB_MOUSE || s->kind == USB_TABLET) {
ret = usb_pointer_poll(s, p->data, p->len);
- s->changed = s->ptr.n > 0;
}
else if (s->kind == USB_KEYBOARD) {
ret = usb_keyboard_poll(s, p->data, p->len);
- s->changed = s->kbd.n > 0;
}
+ s->changed = s->n > 0;
} else {
goto fail;
}
commit 5fae51a9c26c025b94f8d7c40f54b65049de7227
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Thu Jan 13 17:42:06 2011 +0100
usb keyboard: add event event queue
This patch adds a event queue to the usb keyboard. This makes sure the
guest will see all key events even if they come in bursts. With this
patch applied sending Ctrl-Alt-Del using vncviewer's F8 menu works.
Also with autosuspend enabled the first keypress on a suspended keyboard
takes a little longer to be delivered to the guest because the usb bus
must be resumed first. Without event queue this easily gets lost.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index ea49543..5f1451b 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -63,6 +63,9 @@ typedef struct USBMouseState {
} USBMouseState;
typedef struct USBKeyboardState {
+ uint32_t keycodes[QUEUE_LENGTH];
+ uint32_t head; /* index into circular queue */
+ uint32_t n;
uint16_t modifiers;
uint8_t leds;
uint8_t key[16];
@@ -494,8 +497,27 @@ static void usb_keyboard_event(void *opaque, int keycode)
{
USBHIDState *hs = opaque;
USBKeyboardState *s = &hs->kbd;
+ int slot;
+
+ if (s->n == QUEUE_LENGTH) {
+ fprintf(stderr, "usb-kbd: warning: key event queue full\n");
+ return;
+ }
+ slot = (s->head + s->n) & QUEUE_MASK; s->n++;
+ s->keycodes[slot] = keycode;
+ usb_hid_changed(hs);
+}
+
+static void usb_keyboard_process_keycode(USBKeyboardState *s)
+{
uint8_t hid_code, key;
- int i;
+ int i, keycode, slot;
+
+ if (s->n == 0) {
+ return;
+ }
+ slot = s->head & QUEUE_MASK; QUEUE_INCR(s->head); s->n--;
+ keycode = s->keycodes[slot];
key = keycode & 0x7f;
hid_code = usb_hid_usage_keys[key | ((s->modifiers >> 1) & (1 << 7))];
@@ -528,7 +550,6 @@ static void usb_keyboard_event(void *opaque, int keycode)
if (s->key[i] == hid_code) {
s->key[i] = s->key[-- s->keys];
s->key[s->keys] = 0x00;
- usb_hid_changed(hs);
break;
}
if (i < 0)
@@ -543,8 +564,6 @@ static void usb_keyboard_event(void *opaque, int keycode)
} else
return;
}
-
- usb_hid_changed(hs);
}
static inline int int_clamp(int val, int vmin, int vmax)
@@ -645,6 +664,8 @@ static int usb_keyboard_poll(USBHIDState *hs, uint8_t *buf, int len)
if (len < 2)
return 0;
+ usb_keyboard_process_keycode(s);
+
buf[0] = s->modifiers & 0xff;
buf[1] = 0;
if (s->keys > 6)
@@ -680,7 +701,7 @@ static void usb_mouse_handle_reset(USBDevice *dev)
{
USBHIDState *s = (USBHIDState *)dev;
- memset (s->ptr.queue, 0, sizeof (s->ptr.queue));
+ memset(s->ptr.queue, 0, sizeof (s->ptr.queue));
s->ptr.head = 0;
s->ptr.n = 0;
s->protocol = 1;
@@ -691,6 +712,11 @@ static void usb_keyboard_handle_reset(USBDevice *dev)
USBHIDState *s = (USBHIDState *)dev;
qemu_add_kbd_event_handler(usb_keyboard_event, s);
+ memset(s->kbd.keycodes, 0, sizeof (s->kbd.keycodes));
+ s->kbd.head = 0;
+ s->kbd.n = 0;
+ memset(s->kbd.key, 0, sizeof (s->kbd.key));
+ s->kbd.keys = 0;
s->protocol = 1;
}
@@ -800,7 +826,7 @@ static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
}
else if (s->kind == USB_KEYBOARD) {
ret = usb_keyboard_poll(s, p->data, p->len);
- s->changed = 0;
+ s->changed = s->kbd.n > 0;
}
} else {
goto fail;
commit 13f8b97a57450534ccb7aaeb55095a668183fbee
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Wed Jan 12 13:19:20 2011 +0100
add event queueing to USB HID
The polling nature of the USB HID device makes it very hard to double
click or drag while on a high-latency VNC connection. This patch,
based on work done in the Xen qemu-dm tree by Ian Jackson, fixes this
bug by adding an event queue to the device. The event queue associates
each movement with the correct button state, and remembers all button
presses and releases as well.
Signed-off-by: Ian Jackson <ian.jackson at eu.citrix.com>
Signed-off-by: Stefano Stabellini <stefano.stabellini at eu.citrix.com>
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Gerd Hoffman <kraxel at redhat.com>
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 90a2b49..ea49543 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -45,9 +45,19 @@
#define USB_TABLET 2
#define USB_KEYBOARD 3
+typedef struct USBPointerEvent {
+ int32_t xdx, ydy; /* relative iff it's a mouse, otherwise absolute */
+ int32_t dz, buttons_state;
+} USBPointerEvent;
+
+#define QUEUE_LENGTH 16 /* should be enough for a triple-click */
+#define QUEUE_MASK (QUEUE_LENGTH-1u)
+#define QUEUE_INCR(v) ((v)++, (v) &= QUEUE_MASK)
+
typedef struct USBMouseState {
- int dx, dy, dz, buttons_state;
- int x, y;
+ USBPointerEvent queue[QUEUE_LENGTH];
+ uint32_t head; /* index into circular queue */
+ uint32_t n;
int mouse_grabbed;
QEMUPutMouseEntry *eh_entry;
} USBMouseState;
@@ -433,31 +443,50 @@ static void usb_hid_changed(USBHIDState *hs)
usb_wakeup(&hs->dev);
}
-static void usb_mouse_event(void *opaque,
- int dx1, int dy1, int dz1, int buttons_state)
-{
- USBHIDState *hs = opaque;
- USBMouseState *s = &hs->ptr;
-
- s->dx += dx1;
- s->dy += dy1;
- s->dz += dz1;
- s->buttons_state = buttons_state;
+static void usb_pointer_event_clear(USBPointerEvent *e, int buttons) {
+ e->xdx = e->ydy = e->dz = 0;
+ e->buttons_state = buttons;
+}
- usb_hid_changed(hs);
+static void usb_pointer_event_combine(USBPointerEvent *e, int xyrel,
+ int x1, int y1, int z1) {
+ if (xyrel) {
+ e->xdx += x1;
+ e->ydy += y1;
+ } else {
+ e->xdx = x1;
+ e->ydy = y1;
+ }
+ e->dz += z1;
}
-static void usb_tablet_event(void *opaque,
- int x, int y, int dz, int buttons_state)
+static void usb_pointer_event(void *opaque,
+ int x1, int y1, int z1, int buttons_state)
{
USBHIDState *hs = opaque;
USBMouseState *s = &hs->ptr;
-
- s->x = x;
- s->y = y;
- s->dz += dz;
- s->buttons_state = buttons_state;
-
+ unsigned use_slot = (s->head + s->n - 1) & QUEUE_MASK;
+ unsigned previous_slot = (use_slot - 1) & QUEUE_MASK;
+
+ /* We combine events where feasible to keep the queue small. We shouldn't
+ * combine anything with the first event of a particular button state, as
+ * that would change the location of the button state change. When the
+ * queue is empty, a second event is needed because we don't know if
+ * the first event changed the button state. */
+ if (s->n == QUEUE_LENGTH) {
+ /* Queue full. Discard old button state, combine motion normally. */
+ s->queue[use_slot].buttons_state = buttons_state;
+ } else if (s->n < 2 ||
+ s->queue[use_slot].buttons_state != buttons_state ||
+ s->queue[previous_slot].buttons_state != s->queue[use_slot].buttons_state) {
+ /* Cannot or should not combine, so add an empty item to the queue. */
+ QUEUE_INCR(use_slot);
+ s->n++;
+ usb_pointer_event_clear(&s->queue[use_slot], buttons_state);
+ }
+ usb_pointer_event_combine(&s->queue[use_slot],
+ hs->kind == USB_MOUSE,
+ x1, y1, z1);
usb_hid_changed(hs);
}
@@ -528,83 +557,91 @@ static inline int int_clamp(int val, int vmin, int vmax)
return val;
}
-static int usb_mouse_poll(USBHIDState *hs, uint8_t *buf, int len)
+static int usb_pointer_poll(USBHIDState *hs, uint8_t *buf, int len)
{
int dx, dy, dz, b, l;
+ int index;
USBMouseState *s = &hs->ptr;
+ USBPointerEvent *e;
if (!s->mouse_grabbed) {
qemu_activate_mouse_event_handler(s->eh_entry);
- s->mouse_grabbed = 1;
+ s->mouse_grabbed = 1;
}
- dx = int_clamp(s->dx, -127, 127);
- dy = int_clamp(s->dy, -127, 127);
- dz = int_clamp(s->dz, -127, 127);
-
- s->dx -= dx;
- s->dy -= dy;
- s->dz -= dz;
+ /* When the buffer is empty, return the last event. Relative
+ movements will all be zero. */
+ index = (s->n ? s->head : s->head - 1);
+ e = &s->queue[index & QUEUE_MASK];
- /* Appears we have to invert the wheel direction */
- dz = 0 - dz;
+ if (hs->kind == USB_MOUSE) {
+ dx = int_clamp(e->xdx, -127, 127);
+ dy = int_clamp(e->ydy, -127, 127);
+ e->xdx -= dx;
+ e->ydy -= dy;
+ } else {
+ dx = e->xdx;
+ dy = e->ydy;
+ }
+ dz = int_clamp(e->dz, -127, 127);
+ e->dz -= dz;
b = 0;
- if (s->buttons_state & MOUSE_EVENT_LBUTTON)
+ if (e->buttons_state & MOUSE_EVENT_LBUTTON)
b |= 0x01;
- if (s->buttons_state & MOUSE_EVENT_RBUTTON)
+ if (e->buttons_state & MOUSE_EVENT_RBUTTON)
b |= 0x02;
- if (s->buttons_state & MOUSE_EVENT_MBUTTON)
+ if (e->buttons_state & MOUSE_EVENT_MBUTTON)
b |= 0x04;
- l = 0;
- if (len > l)
- buf[l ++] = b;
- if (len > l)
- buf[l ++] = dx;
- if (len > l)
- buf[l ++] = dy;
- if (len > l)
- buf[l ++] = dz;
- return l;
-}
-
-static int usb_tablet_poll(USBHIDState *hs, uint8_t *buf, int len)
-{
- int dz, b, l;
- USBMouseState *s = &hs->ptr;
-
- if (!s->mouse_grabbed) {
- qemu_activate_mouse_event_handler(s->eh_entry);
- s->mouse_grabbed = 1;
+ if (s->n &&
+ !e->dz &&
+ (hs->kind == USB_TABLET || (!e->xdx && !e->ydy))) {
+ /* that deals with this event */
+ QUEUE_INCR(s->head);
+ s->n--;
}
- dz = int_clamp(s->dz, -127, 127);
- s->dz -= dz;
-
/* Appears we have to invert the wheel direction */
dz = 0 - dz;
- b = 0;
- if (s->buttons_state & MOUSE_EVENT_LBUTTON)
- b |= 0x01;
- if (s->buttons_state & MOUSE_EVENT_RBUTTON)
- b |= 0x02;
- if (s->buttons_state & MOUSE_EVENT_MBUTTON)
- b |= 0x04;
+ l = 0;
+ switch (hs->kind) {
+ case USB_MOUSE:
+ if (len > l)
+ buf[l++] = b;
+ if (len > l)
+ buf[l++] = dx;
+ if (len > l)
+ buf[l++] = dy;
+ if (len > l)
+ buf[l++] = dz;
+ break;
- buf[0] = b;
- buf[1] = s->x & 0xff;
- buf[2] = s->x >> 8;
- buf[3] = s->y & 0xff;
- buf[4] = s->y >> 8;
- buf[5] = dz;
- l = 6;
+ case USB_TABLET:
+ if (len > l)
+ buf[l++] = b;
+ if (len > l)
+ buf[l++] = dx & 0xff;
+ if (len > l)
+ buf[l++] = dx >> 8;
+ if (len > l)
+ buf[l++] = dy & 0xff;
+ if (len > l)
+ buf[l++] = dy >> 8;
+ if (len > l)
+ buf[l++] = dz;
+ break;
+
+ default:
+ abort();
+ }
return l;
}
-static int usb_keyboard_poll(USBKeyboardState *s, uint8_t *buf, int len)
+static int usb_keyboard_poll(USBHIDState *hs, uint8_t *buf, int len)
{
+ USBKeyboardState *s = &hs->kbd;
if (len < 2)
return 0;
@@ -643,12 +680,9 @@ static void usb_mouse_handle_reset(USBDevice *dev)
{
USBHIDState *s = (USBHIDState *)dev;
- s->ptr.dx = 0;
- s->ptr.dy = 0;
- s->ptr.dz = 0;
- s->ptr.x = 0;
- s->ptr.y = 0;
- s->ptr.buttons_state = 0;
+ memset (s->ptr.queue, 0, sizeof (s->ptr.queue));
+ s->ptr.head = 0;
+ s->ptr.n = 0;
s->protocol = 1;
}
@@ -708,12 +742,10 @@ static int usb_hid_handle_control(USBDevice *dev, int request, int value,
}
break;
case GET_REPORT:
- if (s->kind == USB_MOUSE)
- ret = usb_mouse_poll(s, data, length);
- else if (s->kind == USB_TABLET)
- ret = usb_tablet_poll(s, data, length);
+ if (s->kind == USB_MOUSE || s->kind == USB_TABLET)
+ ret = usb_pointer_poll(s, data, length);
else if (s->kind == USB_KEYBOARD)
- ret = usb_keyboard_poll(&s->kbd, data, length);
+ ret = usb_keyboard_poll(s, data, length);
break;
case SET_REPORT:
if (s->kind == USB_KEYBOARD)
@@ -762,13 +794,14 @@ static int usb_hid_handle_data(USBDevice *dev, USBPacket *p)
if (!s->changed && (!s->idle || s->next_idle_clock - curtime > 0))
return USB_RET_NAK;
usb_hid_set_next_idle(s, curtime);
- s->changed = 0;
- if (s->kind == USB_MOUSE)
- ret = usb_mouse_poll(s, p->data, p->len);
- else if (s->kind == USB_TABLET)
- ret = usb_tablet_poll(s, p->data, p->len);
- else if (s->kind == USB_KEYBOARD)
- ret = usb_keyboard_poll(&s->kbd, p->data, p->len);
+ if (s->kind == USB_MOUSE || s->kind == USB_TABLET) {
+ ret = usb_pointer_poll(s, p->data, p->len);
+ s->changed = s->ptr.n > 0;
+ }
+ else if (s->kind == USB_KEYBOARD) {
+ ret = usb_keyboard_poll(s, p->data, p->len);
+ s->changed = 0;
+ }
} else {
goto fail;
}
@@ -803,13 +836,13 @@ static int usb_hid_initfn(USBDevice *dev, int kind)
s->kind = kind;
if (s->kind == USB_MOUSE) {
- s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_mouse_event, s,
+ s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_pointer_event, s,
0, "QEMU USB Mouse");
} else if (s->kind == USB_TABLET) {
- s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_tablet_event, s,
+ s->ptr.eh_entry = qemu_add_mouse_event_handler(usb_pointer_event, s,
1, "QEMU USB Tablet");
}
-
+
/* Force poll routine to be run and grab input the first time. */
s->changed = 1;
return 0;
commit cbcc6336ce9e5c048821b136649712e078c4d05f
Author: Alon Levy <alevy at redhat.com>
Date: Wed Jan 19 10:49:50 2011 +0200
spice: add chardev (v5)
Adding a chardev backend for spice, where spice determines what
to do with it based on the name attribute given during chardev creation.
For usage by spice vdagent in conjunction with a properly named
virtio-serial device, and future smartcard channel usage.
Example usage:
qemu -device virtio-serial -chardev spicevmc,name=vdagent,id=vdagent \
-device virtserialport,chardev=vdagent,name=com.redhat.spice.0
v4->v5:
* add tracing events
* fix missing comma
* fix help string to show debug is optional
v3->v4:
* updated commit message
v1->v3 changes: (v2 had a wrong commit message)
* removed spice-qemu-char.h, folded into ui/qemu-spice.h
* removed dead IOCTL code
* removed comment
* removed ifdef CONFIG_SPICE from qemu-config.c and qemu-options.hx help.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/Makefile.objs b/Makefile.objs
index fda366d..13f6b38 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -105,7 +105,7 @@ common-obj-$(CONFIG_BRLAPI) += baum.o
common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o
common-obj-$(CONFIG_WIN32) += version.o
-common-obj-$(CONFIG_SPICE) += ui/spice-core.o ui/spice-input.o ui/spice-display.o
+common-obj-$(CONFIG_SPICE) += ui/spice-core.o ui/spice-input.o ui/spice-display.o spice-qemu-char.o
audio-obj-y = audio.o noaudio.o wavaudio.o mixeng.o
audio-obj-$(CONFIG_SDL) += sdlaudio.o
diff --git a/qemu-char.c b/qemu-char.c
index edc9ad6..acc7130 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -97,6 +97,7 @@
#endif
#include "qemu_socket.h"
+#include "ui/qemu-spice.h"
#define READ_BUF_LEN 4096
@@ -2495,6 +2496,9 @@ static const struct {
|| defined(__FreeBSD_kernel__)
{ .name = "parport", .open = qemu_chr_open_pp },
#endif
+#ifdef CONFIG_SPICE
+ { .name = "spicevmc", .open = qemu_chr_open_spice },
+#endif
};
CharDriverState *qemu_chr_open_opts(QemuOpts *opts,
diff --git a/qemu-config.c b/qemu-config.c
index 965fa46..323d3c2 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -146,6 +146,12 @@ static QemuOptsList qemu_chardev_opts = {
},{
.name = "signal",
.type = QEMU_OPT_BOOL,
+ },{
+ .name = "name",
+ .type = QEMU_OPT_STRING,
+ },{
+ .name = "debug",
+ .type = QEMU_OPT_NUMBER,
},
{ /* end of list */ }
},
diff --git a/qemu-options.hx b/qemu-options.hx
index 898561d..939297a 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1368,6 +1368,9 @@ DEF("chardev", HAS_ARG, QEMU_OPTION_chardev,
#if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__)
"-chardev parport,id=id,path=path[,mux=on|off]\n"
#endif
+#if defined(CONFIG_SPICE)
+ "-chardev spicevmc,id=id,name=name[,debug=debug]\n"
+#endif
, QEMU_ARCH_ALL
)
@@ -1392,7 +1395,8 @@ Backend is one of:
@option{stdio},
@option{braille},
@option{tty},
- at option{parport}.
+ at option{parport},
+ at option{spicevmc}.
The specific backend will determine the applicable options.
All devices must have an id, which can be any string up to 127 characters long.
@@ -1568,6 +1572,16 @@ Connect to a local parallel port.
@option{path} specifies the path to the parallel port device. @option{path} is
required.
+#if defined(CONFIG_SPICE)
+ at item -chardev spicevmc ,id=@var{id} ,debug=@var{debug}, name=@var{name}
+
+ at option{debug} debug level for spicevmc
+
+ at option{name} name of spice channel to connect to
+
+Connect to a spice virtual machine channel, such as vdiport.
+#endif
+
@end table
ETEXI
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
new file mode 100644
index 0000000..517f337
--- /dev/null
+++ b/spice-qemu-char.c
@@ -0,0 +1,190 @@
+#include "config-host.h"
+#include "trace.h"
+#include "ui/qemu-spice.h"
+#include <spice.h>
+#include <spice-experimental.h>
+
+#include "osdep.h"
+
+#define dprintf(_scd, _level, _fmt, ...) \
+ do { \
+ static unsigned __dprintf_counter = 0; \
+ if (_scd->debug >= _level) { \
+ fprintf(stderr, "scd: %3d: " _fmt, ++__dprintf_counter, ## __VA_ARGS__);\
+ } \
+ } while (0)
+
+#define VMC_MAX_HOST_WRITE 2048
+
+typedef struct SpiceCharDriver {
+ CharDriverState* chr;
+ SpiceCharDeviceInstance sin;
+ char *subtype;
+ bool active;
+ uint8_t *buffer;
+ uint8_t *datapos;
+ ssize_t bufsize, datalen;
+ uint32_t debug;
+} SpiceCharDriver;
+
+static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
+{
+ SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
+ ssize_t out = 0;
+ ssize_t last_out;
+ uint8_t* p = (uint8_t*)buf;
+
+ while (len > 0) {
+ last_out = MIN(len, VMC_MAX_HOST_WRITE);
+ qemu_chr_read(scd->chr, p, last_out);
+ if (last_out > 0) {
+ out += last_out;
+ len -= last_out;
+ p += last_out;
+ } else {
+ break;
+ }
+ }
+
+ dprintf(scd, 3, "%s: %lu/%zd\n", __func__, out, len + out);
+ trace_spice_vmc_write(out, len + out);
+ return out;
+}
+
+static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
+{
+ SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
+ int bytes = MIN(len, scd->datalen);
+
+ dprintf(scd, 2, "%s: %p %d/%d/%zd\n", __func__, scd->datapos, len, bytes, scd->datalen);
+ if (bytes > 0) {
+ memcpy(buf, scd->datapos, bytes);
+ scd->datapos += bytes;
+ scd->datalen -= bytes;
+ assert(scd->datalen >= 0);
+ if (scd->datalen == 0) {
+ scd->datapos = 0;
+ }
+ }
+ trace_spice_vmc_read(bytes, len);
+ return bytes;
+}
+
+static SpiceCharDeviceInterface vmc_interface = {
+ .base.type = SPICE_INTERFACE_CHAR_DEVICE,
+ .base.description = "spice virtual channel char device",
+ .base.major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR,
+ .base.minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR,
+ .write = vmc_write,
+ .read = vmc_read,
+};
+
+
+static void vmc_register_interface(SpiceCharDriver *scd)
+{
+ if (scd->active) {
+ return;
+ }
+ dprintf(scd, 1, "%s\n", __func__);
+ scd->sin.base.sif = &vmc_interface.base;
+ qemu_spice_add_interface(&scd->sin.base);
+ scd->active = true;
+ trace_spice_vmc_register_interface(scd);
+}
+
+static void vmc_unregister_interface(SpiceCharDriver *scd)
+{
+ if (!scd->active) {
+ return;
+ }
+ dprintf(scd, 1, "%s\n", __func__);
+ spice_server_remove_interface(&scd->sin.base);
+ scd->active = false;
+ trace_spice_vmc_unregister_interface(scd);
+}
+
+
+static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+{
+ SpiceCharDriver *s = chr->opaque;
+
+ dprintf(s, 2, "%s: %d\n", __func__, len);
+ vmc_register_interface(s);
+ assert(s->datalen == 0);
+ if (s->bufsize < len) {
+ s->bufsize = len;
+ s->buffer = qemu_realloc(s->buffer, s->bufsize);
+ }
+ memcpy(s->buffer, buf, len);
+ s->datapos = s->buffer;
+ s->datalen = len;
+ spice_server_char_device_wakeup(&s->sin);
+ return len;
+}
+
+static void spice_chr_close(struct CharDriverState *chr)
+{
+ SpiceCharDriver *s = chr->opaque;
+
+ printf("%s\n", __func__);
+ vmc_unregister_interface(s);
+ qemu_free(s);
+}
+
+static void print_allowed_subtypes(void)
+{
+ const char** psubtype;
+ int i;
+
+ fprintf(stderr, "allowed names: ");
+ for(i=0, psubtype = spice_server_char_device_recognized_subtypes();
+ *psubtype != NULL; ++psubtype, ++i) {
+ if (i == 0) {
+ fprintf(stderr, "%s", *psubtype);
+ } else {
+ fprintf(stderr, ", %s", *psubtype);
+ }
+ }
+ fprintf(stderr, "\n");
+}
+
+CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
+{
+ CharDriverState *chr;
+ SpiceCharDriver *s;
+ const char* name = qemu_opt_get(opts, "name");
+ uint32_t debug = qemu_opt_get_number(opts, "debug", 0);
+ const char** psubtype = spice_server_char_device_recognized_subtypes();
+ const char *subtype = NULL;
+
+ if (name == NULL) {
+ fprintf(stderr, "spice-qemu-char: missing name parameter\n");
+ print_allowed_subtypes();
+ return NULL;
+ }
+ for(;*psubtype != NULL; ++psubtype) {
+ if (strcmp(name, *psubtype) == 0) {
+ subtype = *psubtype;
+ break;
+ }
+ }
+ if (subtype == NULL) {
+ fprintf(stderr, "spice-qemu-char: unsupported name\n");
+ print_allowed_subtypes();
+ return NULL;
+ }
+
+ chr = qemu_mallocz(sizeof(CharDriverState));
+ s = qemu_mallocz(sizeof(SpiceCharDriver));
+ s->chr = chr;
+ s->debug = debug;
+ s->active = false;
+ s->sin.subtype = subtype;
+ chr->opaque = s;
+ chr->chr_write = spice_chr_write;
+ chr->chr_close = spice_chr_close;
+
+ qemu_chr_generic_open(chr);
+
+ return chr;
+}
diff --git a/trace-events b/trace-events
index 19cee6a..ed754f5 100644
--- a/trace-events
+++ b/trace-events
@@ -224,3 +224,9 @@ disable qed_aio_write_data(void *s, void *acb, int ret, uint64_t offset, size_t
disable qed_aio_write_prefill(void *s, void *acb, uint64_t start, size_t len, uint64_t offset) "s %p acb %p start %"PRIu64" len %zu offset %"PRIu64""
disable qed_aio_write_postfill(void *s, void *acb, uint64_t start, size_t len, uint64_t offset) "s %p acb %p start %"PRIu64" len %zu offset %"PRIu64""
disable qed_aio_write_main(void *s, void *acb, int ret, uint64_t offset, size_t len) "s %p acb %p ret %d offset %"PRIu64" len %zu"
+
+# spice-qemu-char.c
+disable spice_vmc_write(ssize_t out, int len) "spice wrottn %lu of requested %zd"
+disable spice_vmc_read(int bytes, int len) "spice read %lu of requested %zd"
+disable spice_vmc_register_interface(void *scd) "spice vmc registered interface %p"
+disable spice_vmc_unregister_interface(void *scd) "spice vmc unregistered interface %p"
diff --git a/ui/qemu-spice.h b/ui/qemu-spice.h
index 05dc50a..916e5dc 100644
--- a/ui/qemu-spice.h
+++ b/ui/qemu-spice.h
@@ -24,6 +24,7 @@
#include "qemu-option.h"
#include "qemu-config.h"
+#include "qemu-char.h"
extern int using_spice;
@@ -41,6 +42,8 @@ int qemu_spice_migrate_info(const char *hostname, int port, int tls_port,
void do_info_spice_print(Monitor *mon, const QObject *data);
void do_info_spice(Monitor *mon, QObject **ret_data);
+CharDriverState *qemu_chr_open_spice(QemuOpts *opts);
+
#else /* CONFIG_SPICE */
#define using_spice 0
commit 710fc4f5f1cbb6d2cebdc575def9f9dba4b0263f
Author: Jiri Denemark <Jiri.Denemark at gmail.com>
Date: Mon Jan 24 13:20:29 2011 +0100
configure: Fix spice probe
Non-existent $pkgconfig instead of $pkg_config was used when configure
probes for spice availability.
Signed-off-by: Jiri Denemark <jdenemar at redhat.com>
diff --git a/configure b/configure
index 210670c..dc469b2 100755
--- a/configure
+++ b/configure
@@ -2207,9 +2207,9 @@ if test "$spice" != "no" ; then
#include <spice.h>
int main(void) { spice_server_new(); return 0; }
EOF
- spice_cflags=$($pkgconfig --cflags spice-protocol spice-server 2>/dev/null)
- spice_libs=$($pkgconfig --libs spice-protocol spice-server 2>/dev/null)
- if $pkgconfig --atleast-version=0.5.3 spice-server >/dev/null 2>&1 && \
+ spice_cflags=$($pkg_config --cflags spice-protocol spice-server 2>/dev/null)
+ spice_libs=$($pkg_config --libs spice-protocol spice-server 2>/dev/null)
+ if $pkg_config --atleast-version=0.5.3 spice-server >/dev/null 2>&1 && \
compile_prog "$spice_cflags" "$spice_libs" ; then
spice="yes"
libs_softmmu="$libs_softmmu $spice_libs"
commit 17268d54be2e15b0d8ccfc4102bc48c84299b027
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Fri Jan 21 10:32:03 2011 +0100
qxl: locking fix
One spice worker call lacks the unlock/relock calls,
which may lead to deadlocks, add them.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/qxl.c b/hw/qxl.c
index dcea65d..fe4212b 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -866,7 +866,9 @@ static void qxl_destroy_primary(PCIQXLDevice *d)
dprint(d, 1, "%s\n", __FUNCTION__);
d->mode = QXL_MODE_UNDEFINED;
+ qemu_mutex_unlock_iothread();
d->ssd.worker->destroy_primary_surface(d->ssd.worker, 0);
+ qemu_mutex_lock_iothread();
}
static void qxl_set_mode(PCIQXLDevice *d, int modenr, int loadvm)
commit b67737a6cf71d1f029a692e5dc2dc26579299b97
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Wed Jan 5 18:05:52 2011 +0100
spice/qxl: zap spice 0.4 migration compatibility bits
Live migration from and to spice 0.4 qxl devices isn't going to work.
Rip out the bits which attempt to support that. Zap the subsection
logic which is obsolete now. Bumb the version to make a clean cut.
This should obviously go in before 0.14 is released.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hw/qxl.c b/hw/qxl.c
index bd71e58..dcea65d 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -1418,43 +1418,10 @@ static int qxl_post_load(void *opaque, int version)
}
dprint(d, 1, "%s: done\n", __FUNCTION__);
- /* spice 0.4 compatibility -- accept but ignore */
- qemu_free(d->worker_data);
- d->worker_data = NULL;
- d->worker_data_size = 0;
-
return 0;
}
-#define QXL_SAVE_VERSION 20
-
-static bool qxl_test_worker_data(void *opaque, int version_id)
-{
- PCIQXLDevice* d = opaque;
-
- if (d->revision != 1) {
- return false;
- }
- if (!d->worker_data_size) {
- return false;
- }
- if (!d->worker_data) {
- d->worker_data = qemu_malloc(d->worker_data_size);
- }
- return true;
-}
-
-static bool qxl_test_spice04(void *opaque, int version_id)
-{
- PCIQXLDevice* d = opaque;
- return d->revision == 1;
-}
-
-static bool qxl_test_spice06(void *opaque)
-{
- PCIQXLDevice* d = opaque;
- return d->revision > 1;
-}
+#define QXL_SAVE_VERSION 21
static VMStateDescription qxl_memslot = {
.name = "qxl-memslot",
@@ -1486,24 +1453,6 @@ static VMStateDescription qxl_surface = {
}
};
-static VMStateDescription qxl_vmstate_spice06 = {
- .name = "qxl/spice06",
- .version_id = QXL_SAVE_VERSION,
- .minimum_version_id = QXL_SAVE_VERSION,
- .fields = (VMStateField []) {
- VMSTATE_INT32_EQUAL(num_memslots, PCIQXLDevice),
- VMSTATE_STRUCT_ARRAY(guest_slots, PCIQXLDevice, NUM_MEMSLOTS, 0,
- qxl_memslot, struct guest_slots),
- VMSTATE_STRUCT(guest_primary.surface, PCIQXLDevice, 0,
- qxl_surface, QXLSurfaceCreate),
- VMSTATE_INT32_EQUAL(num_surfaces, PCIQXLDevice),
- VMSTATE_ARRAY(guest_surfaces.cmds, PCIQXLDevice, NUM_SURFACES, 0,
- vmstate_info_uint64, uint64_t),
- VMSTATE_UINT64(guest_cursor, PCIQXLDevice),
- VMSTATE_END_OF_LIST()
- },
-};
-
static VMStateDescription qxl_vmstate = {
.name = "qxl",
.version_id = QXL_SAVE_VERSION,
@@ -1519,25 +1468,17 @@ static VMStateDescription qxl_vmstate = {
VMSTATE_UINT32(last_release_offset, PCIQXLDevice),
VMSTATE_UINT32(mode, PCIQXLDevice),
VMSTATE_UINT32(ssd.unique, PCIQXLDevice),
-
- /* spice 0.4 sends/expects them */
- VMSTATE_VBUFFER_UINT32(vga.vram_ptr, PCIQXLDevice, 0, qxl_test_spice04, 0,
- vga.vram_size),
- VMSTATE_UINT32_TEST(worker_data_size, PCIQXLDevice, qxl_test_spice04),
- VMSTATE_VBUFFER_UINT32(worker_data, PCIQXLDevice, 0, qxl_test_worker_data, 0,
- worker_data_size),
-
+ VMSTATE_INT32_EQUAL(num_memslots, PCIQXLDevice),
+ VMSTATE_STRUCT_ARRAY(guest_slots, PCIQXLDevice, NUM_MEMSLOTS, 0,
+ qxl_memslot, struct guest_slots),
+ VMSTATE_STRUCT(guest_primary.surface, PCIQXLDevice, 0,
+ qxl_surface, QXLSurfaceCreate),
+ VMSTATE_INT32_EQUAL(num_surfaces, PCIQXLDevice),
+ VMSTATE_ARRAY(guest_surfaces.cmds, PCIQXLDevice, NUM_SURFACES, 0,
+ vmstate_info_uint64, uint64_t),
+ VMSTATE_UINT64(guest_cursor, PCIQXLDevice),
VMSTATE_END_OF_LIST()
},
- .subsections = (VMStateSubsection[]) {
- {
- /* additional spice 0.6 state */
- .vmsd = &qxl_vmstate_spice06,
- .needed = qxl_test_spice06,
- },{
- /* end of list */
- },
- },
};
static PCIDeviceInfo qxl_info_primary = {
diff --git a/hw/qxl.h b/hw/qxl.h
index 98e11ce..f6c450d 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -80,10 +80,6 @@ typedef struct PCIQXLDevice {
/* io bar */
uint32_t io_base;
-
- /* spice 0.4 loadvm compatibility */
- void *worker_data;
- uint32_t worker_data_size;
} PCIQXLDevice;
#define PANIC_ON(x) if ((x)) { \
commit 8d86e2bfe36ae8e03bf2ba0c8206b91e29ad292f
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date: Thu Jan 6 11:43:17 2011 +0100
vnc/spice: fix "never" and "now" expire_time
diff --git a/monitor.c b/monitor.c
index 4c92d38..6aa1bb9 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1136,9 +1136,9 @@ static int expire_password(Monitor *mon, const QDict *qdict, QObject **ret_data)
time_t when;
int rc;
- if (strcmp(whenstr, "now")) {
+ if (strcmp(whenstr, "now") == 0) {
when = 0;
- } else if (strcmp(whenstr, "never")) {
+ } else if (strcmp(whenstr, "never") == 0) {
when = TIME_MAX;
} else if (whenstr[0] == '+') {
when = time(NULL) + strtoull(whenstr+1, NULL, 10);
commit 7ee3bf03984ada1ac7c7a4f27d8583a5718adadb
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Mon Dec 13 21:30:37 2010 +0100
spice: MAINTAINERS update
diff --git a/MAINTAINERS b/MAINTAINERS
index f20d390..ab48380 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -383,6 +383,14 @@ S: Odd Fixes
F: gdbstub*
F: gdb-xml/
+SPICE
+M: Gerd Hoffmann <kraxel at redhat.com>
+S: Supported
+F: ui/qemu-spice.h
+F: ui/spice-*.c
+F: audio/spiceaudio.c
+F: hw/qxl*
+
Graphics
M: Anthony Liguori <aliguori at us.ibm.com>
S: Maintained
commit e866e23959b45325414ac84a21f31dea79867ee6
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Fri Apr 23 13:28:21 2010 +0200
spice/vnc: client migration.
Handle spice client migration, i.e. inform a spice client connected
about the new host and connection parameters, so it can move over the
connection automatically.
The monitor command has a not-yet used protocol argument simliar to
set_password and expire_password commands. This allows to add a simliar
feature to vnc in the future. Daniel Berrange plans to work on this.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 1cea572..4906d89 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -815,6 +815,23 @@ ETEXI
},
STEXI
+ at item client_migrate_info @var{protocol} @var{hostname} @var{port} @var{tls-port} @var{cert-subject}
+ at findex client_migrate_info
+Set the spice/vnc connection info for the migration target. The spice/vnc
+server will ask the spice/vnc client to automatically reconnect using the
+new parameters (if specified) once the vm migration finished successfully.
+ETEXI
+
+ {
+ .name = "client_migrate_info",
+ .args_type = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?",
+ .params = "protocol hostname port tls-port cert-subject",
+ .help = "send migration info to spice/vnc client",
+ .user_print = monitor_user_noop,
+ .mhandler.cmd_new = client_migrate_info,
+ },
+
+STEXI
@item snapshot_blkdev
@findex snapshot_blkdev
Snapshot device, using snapshot file as target if provided
diff --git a/monitor.c b/monitor.c
index d291158..4c92d38 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1173,6 +1173,33 @@ static int expire_password(Monitor *mon, const QDict *qdict, QObject **ret_data)
return -1;
}
+static int client_migrate_info(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+ const char *protocol = qdict_get_str(qdict, "protocol");
+ const char *hostname = qdict_get_str(qdict, "hostname");
+ const char *subject = qdict_get_try_str(qdict, "cert-subject");
+ int port = qdict_get_try_int(qdict, "port", -1);
+ int tls_port = qdict_get_try_int(qdict, "tls-port", -1);
+ int ret;
+
+ if (strcmp(protocol, "spice") == 0) {
+ if (!using_spice) {
+ qerror_report(QERR_DEVICE_NOT_ACTIVE, "spice");
+ return -1;
+ }
+
+ ret = qemu_spice_migrate_info(hostname, port, tls_port, subject);
+ if (ret != 0) {
+ qerror_report(QERR_UNDEFINED_ERROR);
+ return -1;
+ }
+ return 0;
+ }
+
+ qerror_report(QERR_INVALID_PARAMETER, "protocol");
+ return -1;
+}
+
static int do_screen_dump(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
vga_hw_screen_dump(qdict_get_str(qdict, "filename"));
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 56c4d8b..2ed8f44 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -503,6 +503,41 @@ EQMP
},
SQMP
+client_migrate_info
+------------------
+
+Set the spice/vnc connection info for the migration target. The spice/vnc
+server will ask the spice/vnc client to automatically reconnect using the
+new parameters (if specified) once the vm migration finished successfully.
+
+Arguments:
+
+- "protocol": protocol: "spice" or "vnc" (json-string)
+- "hostname": migration target hostname (json-string)
+- "port": spice/vnc tcp port for plaintext channels (json-int, optional)
+- "tls-port": spice tcp port for tls-secured channels (json-int, optional)
+- "cert-subject": server certificate subject (json-string, optional)
+
+Example:
+
+-> { "execute": "client_migrate_info",
+ "arguments": { "protocol": "spice",
+ "hostname": "virt42.lab.kraxel.org",
+ "port": 1234 } }
+<- { "return": {} }
+
+EQMP
+
+ {
+ .name = "client_migrate_info",
+ .args_type = "protocol:s,hostname:s,port:i?,tls-port:i?,cert-subject:s?",
+ .params = "protocol hostname port tls-port cert-subject",
+ .help = "send migration info to spice/vnc client",
+ .user_print = monitor_user_noop,
+ .mhandler.cmd_new = client_migrate_info,
+ },
+
+SQMP
migrate_set_speed
-----------------
diff --git a/ui/qemu-spice.h b/ui/qemu-spice.h
index 48239c3..05dc50a 100644
--- a/ui/qemu-spice.h
+++ b/ui/qemu-spice.h
@@ -35,6 +35,8 @@ int qemu_spice_add_interface(SpiceBaseInstance *sin);
int qemu_spice_set_passwd(const char *passwd,
bool fail_if_connected, bool disconnect_if_connected);
int qemu_spice_set_pw_expire(time_t expires);
+int qemu_spice_migrate_info(const char *hostname, int port, int tls_port,
+ const char *subject);
void do_info_spice_print(Monitor *mon, const QObject *data);
void do_info_spice(Monitor *mon, QObject **ret_data);
@@ -44,6 +46,8 @@ void do_info_spice(Monitor *mon, QObject **ret_data);
#define using_spice 0
#define qemu_spice_set_passwd(_p, _f1, _f2) (-1)
#define qemu_spice_set_pw_expire(_e) (-1)
+static inline int qemu_spice_migrate_info(const char *h, int p, int t, const char *s)
+{ return -1; }
#endif /* CONFIG_SPICE */
diff --git a/ui/spice-core.c b/ui/spice-core.c
index 27a1ced..1aa1a5e 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -30,11 +30,15 @@
#include "qbool.h"
#include "qstring.h"
#include "qjson.h"
+#include "notify.h"
+#include "migration.h"
#include "monitor.h"
+#include "hw/hw.h"
/* core bits */
static SpiceServer *spice_server;
+static Notifier migration_state;
static const char *auth = "spice";
static char *auth_passwd;
static time_t auth_expires = TIME_MAX;
@@ -416,6 +420,24 @@ void do_info_spice(Monitor *mon, QObject **ret_data)
*ret_data = QOBJECT(server);
}
+static void migration_state_notifier(Notifier *notifier)
+{
+ int state = get_migration_state();
+
+ if (state == MIG_STATE_COMPLETED) {
+#if SPICE_SERVER_VERSION >= 0x000701 /* 0.7.1 */
+ spice_server_migrate_switch(spice_server);
+#endif
+ }
+}
+
+int qemu_spice_migrate_info(const char *hostname, int port, int tls_port,
+ const char *subject)
+{
+ return spice_server_migrate_info(spice_server, hostname,
+ port, tls_port, subject);
+}
+
static int add_channel(const char *name, const char *value, void *opaque)
{
int security = 0;
@@ -573,6 +595,9 @@ void qemu_spice_init(void)
spice_server_init(spice_server, &core_interface);
using_spice = 1;
+ migration_state.notify = migration_state_notifier;
+ add_migration_state_change_notifier(&migration_state);
+
qemu_spice_input_init();
qemu_spice_audio_init();
commit 99a0db9b8dd72ea20a2d4cd99fe91b08903ae857
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Mon Dec 13 17:30:12 2010 +0100
add migration state change notifiers
This patch adds functions to register and unregister notifiers for
migration state changes and a function to query the migration state.
The notifier is called on every state change. Once after establishing a
new migration object (which is in active state then) and once when the
state changes from active to completed, canceled or error.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
diff --git a/migration.c b/migration.c
index d593b1d..3612572 100644
--- a/migration.c
+++ b/migration.c
@@ -36,6 +36,9 @@ static int64_t max_throttle = (32 << 20);
static MigrationState *current_migration;
+static NotifierList migration_state_notifiers =
+ NOTIFIER_LIST_INITIALIZER(migration_state_notifiers);
+
int qemu_start_incoming_migration(const char *uri)
{
const char *p;
@@ -121,6 +124,7 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
}
current_migration = s;
+ notifier_list_notify(&migration_state_notifiers);
return 0;
}
@@ -272,6 +276,7 @@ void migrate_fd_error(FdMigrationState *s)
{
DPRINTF("setting error state\n");
s->state = MIG_STATE_ERROR;
+ notifier_list_notify(&migration_state_notifiers);
migrate_fd_cleanup(s);
}
@@ -329,6 +334,7 @@ ssize_t migrate_fd_put_buffer(void *opaque, const void *data, size_t size)
monitor_resume(s->mon);
}
s->state = MIG_STATE_ERROR;
+ notifier_list_notify(&migration_state_notifiers);
}
return ret;
@@ -389,6 +395,7 @@ void migrate_fd_put_ready(void *opaque)
state = MIG_STATE_ERROR;
}
s->state = state;
+ notifier_list_notify(&migration_state_notifiers);
}
}
@@ -408,6 +415,7 @@ void migrate_fd_cancel(MigrationState *mig_state)
DPRINTF("cancelling migration\n");
s->state = MIG_STATE_CANCELLED;
+ notifier_list_notify(&migration_state_notifiers);
qemu_savevm_state_cancel(s->mon, s->file);
migrate_fd_cleanup(s);
@@ -421,6 +429,7 @@ void migrate_fd_release(MigrationState *mig_state)
if (s->state == MIG_STATE_ACTIVE) {
s->state = MIG_STATE_CANCELLED;
+ notifier_list_notify(&migration_state_notifiers);
migrate_fd_cleanup(s);
}
qemu_free(s);
@@ -452,3 +461,22 @@ int migrate_fd_close(void *opaque)
qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
return s->close(s);
}
+
+void add_migration_state_change_notifier(Notifier *notify)
+{
+ notifier_list_add(&migration_state_notifiers, notify);
+}
+
+void remove_migration_state_change_notifier(Notifier *notify)
+{
+ notifier_list_remove(&migration_state_notifiers, notify);
+}
+
+int get_migration_state(void)
+{
+ if (current_migration) {
+ return migrate_fd_get_status(current_migration);
+ } else {
+ return MIG_STATE_ERROR;
+ }
+}
diff --git a/migration.h b/migration.h
index d13ed4f..2170792 100644
--- a/migration.h
+++ b/migration.h
@@ -16,6 +16,7 @@
#include "qdict.h"
#include "qemu-common.h"
+#include "notify.h"
#define MIG_STATE_ERROR -1
#define MIG_STATE_COMPLETED 0
@@ -134,4 +135,8 @@ static inline FdMigrationState *migrate_to_fms(MigrationState *mig_state)
return container_of(mig_state, FdMigrationState, mig_state);
}
+void add_migration_state_change_notifier(Notifier *notify);
+void remove_migration_state_change_notifier(Notifier *notify);
+int get_migration_state(void);
+
#endif
commit be7052c2a8f667f1dc42b06afcebb964ee0b03ff
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date: Mon Jan 24 19:00:47 2011 +0900
pci: memory leak of PCIDevice::rom_file
PCIDevice::rom_file is leaked.
PCIDevice::rom_file is allocated in pci_qdev_init(), but not freed anywhere.
free it in qemu_unregister_device().
Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/pci.c b/hw/pci.c
index b8f5385..044c4bd 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -833,6 +833,7 @@ static int pci_unregister_device(DeviceState *dev)
pci_unregister_io_regions(pci_dev);
pci_del_option_rom(pci_dev);
+ qemu_free(pci_dev->romfile);
do_pci_unregister_device(pci_dev);
return 0;
}
commit c5999bfcfdf66390c98115044cb6fd174fbcf36d
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Fri Jan 21 21:48:22 2011 +0100
kvm: x86: Only read/write MSR_KVM_ASYNC_PF_EN if supported
If the kernel does not support KVM_CAP_ASYNC_PF, it also does not know
about the related MSR. So skip it during state synchronization in that
case. Fixes annoying kernel warnings.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index b2c5ee0..8e8880a 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -63,6 +63,9 @@ const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
static bool has_msr_star;
static bool has_msr_hsave_pa;
+#if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ASYNC_PF)
+static bool has_msr_async_pf_en;
+#endif
static int lm_capable_kernel;
static struct kvm_cpuid2 *try_get_cpuid(KVMState *s, int max)
@@ -164,6 +167,7 @@ static int get_para_features(CPUState *env)
features |= (1 << para_features[i].feature);
}
}
+ has_msr_async_pf_en = features & (1 << KVM_FEATURE_ASYNC_PF);
return features;
}
#endif
@@ -828,7 +832,10 @@ static int kvm_put_msrs(CPUState *env, int level)
env->system_time_msr);
kvm_msr_entry_set(&msrs[n++], MSR_KVM_WALL_CLOCK, env->wall_clock_msr);
#if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ASYNC_PF)
- kvm_msr_entry_set(&msrs[n++], MSR_KVM_ASYNC_PF_EN, env->async_pf_en_msr);
+ if (has_msr_async_pf_en) {
+ kvm_msr_entry_set(&msrs[n++], MSR_KVM_ASYNC_PF_EN,
+ env->async_pf_en_msr);
+ }
#endif
}
#ifdef KVM_CAP_MCE
@@ -1064,7 +1071,9 @@ static int kvm_get_msrs(CPUState *env)
msrs[n++].index = MSR_KVM_SYSTEM_TIME;
msrs[n++].index = MSR_KVM_WALL_CLOCK;
#if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ASYNC_PF)
- msrs[n++].index = MSR_KVM_ASYNC_PF_EN;
+ if (has_msr_async_pf_en) {
+ msrs[n++].index = MSR_KVM_ASYNC_PF_EN;
+ }
#endif
#ifdef KVM_CAP_MCE
commit d8f771d9124e9a295b564d47d7546d93e844b526
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Fri Jan 21 21:48:21 2011 +0100
kvm: x86: Implicitly clear nmi_injected/pending on reset
All CPUX86State variables before CPU_COMMON are automatically cleared on
reset. Reorder nmi_injected and nmi_pending to avoid having to touch
them explicitly.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index a457423..af701a4 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -699,6 +699,10 @@ typedef struct CPUX86State {
uint32_t smbase;
int old_exception; /* exception in flight */
+ /* KVM states, automatically cleared on reset */
+ uint8_t nmi_injected;
+ uint8_t nmi_pending;
+
CPU_COMMON
/* processor features (e.g. for CPUID insn) */
@@ -726,8 +730,6 @@ typedef struct CPUX86State {
int32_t exception_injected;
int32_t interrupt_injected;
uint8_t soft_interrupt;
- uint8_t nmi_injected;
- uint8_t nmi_pending;
uint8_t has_error_code;
uint32_t sipi_vector;
uint32_t cpuid_kvm_features;
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 72f9fdf..b2c5ee0 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -435,8 +435,6 @@ void kvm_arch_reset_vcpu(CPUState *env)
{
env->exception_injected = -1;
env->interrupt_injected = -1;
- env->nmi_injected = 0;
- env->nmi_pending = 0;
env->xcr0 = 1;
if (kvm_irqchip_in_kernel()) {
env->mp_state = cpu_is_bsp(env) ? KVM_MP_STATE_RUNNABLE :
commit b66042c722e4e7b2811a08873b1ecf2c2c1e5f0a
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Fri Jan 21 21:48:20 2011 +0100
kvm: Do not use qemu_fair_mutex
The imbalance in the hold time of qemu_global_mutex only exists in TCG
mode. In contrast to TCG VCPUs, KVM drops the global lock during guest
execution. We already avoid touching the fairness lock from the
IO-thread in KVM mode, so also stop using it from the VCPU threads.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
diff --git a/cpus.c b/cpus.c
index 0309189..4c9928e 100644
--- a/cpus.c
+++ b/cpus.c
@@ -735,9 +735,7 @@ static sigset_t block_io_signals(void)
void qemu_mutex_lock_iothread(void)
{
if (kvm_enabled()) {
- qemu_mutex_lock(&qemu_fair_mutex);
qemu_mutex_lock(&qemu_global_mutex);
- qemu_mutex_unlock(&qemu_fair_mutex);
} else {
qemu_mutex_lock(&qemu_fair_mutex);
if (qemu_mutex_trylock(&qemu_global_mutex)) {
commit b0c883b5e079a4f719c43f875034e5e665ccc232
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Fri Jan 21 21:48:19 2011 +0100
kvm: Flush coalesced mmio buffer on IO window exits
We must flush pending mmio writes if we leave kvm_cpu_exec for an IO
window. Otherwise we risk to loose those requests when migrating to a
different host during that window.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
diff --git a/kvm-all.c b/kvm-all.c
index 3a1f63b..9976762 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -918,6 +918,8 @@ int kvm_cpu_exec(CPUState *env)
cpu_single_env = env;
kvm_arch_post_run(env, run);
+ kvm_flush_coalesced_mmio_buffer();
+
if (ret == -EINTR || ret == -EAGAIN) {
cpu_exit(env);
DPRINTF("io window exit\n");
@@ -930,8 +932,6 @@ int kvm_cpu_exec(CPUState *env)
abort();
}
- kvm_flush_coalesced_mmio_buffer();
-
ret = 0; /* exit loop */
switch (run->exit_reason) {
case KVM_EXIT_IO:
commit 110761987d10c6e6983cc445618acfd158d7ce02
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Fri Jan 21 21:48:18 2011 +0100
kvm: x86: Rework identity map and TSS setup for larger BIOS sizes
In order to support loading BIOSes > 256K, reorder the code, adjusting
the base if the kernel supports moving the identity map.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 1db8227..72f9fdf 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -493,27 +493,9 @@ static int kvm_get_supported_msrs(KVMState *s)
return ret;
}
-static int kvm_init_identity_map_page(KVMState *s)
-{
-#ifdef KVM_CAP_SET_IDENTITY_MAP_ADDR
- int ret;
- uint64_t addr = 0xfffbc000;
-
- if (!kvm_check_extension(s, KVM_CAP_SET_IDENTITY_MAP_ADDR)) {
- return 0;
- }
-
- ret = kvm_vm_ioctl(s, KVM_SET_IDENTITY_MAP_ADDR, &addr);
- if (ret < 0) {
- fprintf(stderr, "kvm_set_identity_map_addr: %s\n", strerror(ret));
- return ret;
- }
-#endif
- return 0;
-}
-
int kvm_arch_init(KVMState *s)
{
+ uint64_t identity_base = 0xfffbc000;
int ret;
struct utsname utsname;
@@ -525,27 +507,42 @@ int kvm_arch_init(KVMState *s)
uname(&utsname);
lm_capable_kernel = strcmp(utsname.machine, "x86_64") == 0;
- /* create vm86 tss. KVM uses vm86 mode to emulate 16-bit code
- * directly. In order to use vm86 mode, a TSS is needed. Since this
- * must be part of guest physical memory, we need to allocate it. */
-
- /* this address is 3 pages before the bios, and the bios should present
- * as unavaible memory. FIXME, need to ensure the e820 map deals with
- * this?
- */
/*
- * Tell fw_cfg to notify the BIOS to reserve the range.
+ * On older Intel CPUs, KVM uses vm86 mode to emulate 16-bit code directly.
+ * In order to use vm86 mode, an EPT identity map and a TSS are needed.
+ * Since these must be part of guest physical memory, we need to allocate
+ * them, both by setting their start addresses in the kernel and by
+ * creating a corresponding e820 entry. We need 4 pages before the BIOS.
+ *
+ * Older KVM versions may not support setting the identity map base. In
+ * that case we need to stick with the default, i.e. a 256K maximum BIOS
+ * size.
*/
- if (e820_add_entry(0xfffbc000, 0x4000, E820_RESERVED) < 0) {
- perror("e820_add_entry() table is full");
- exit(1);
+#ifdef KVM_CAP_SET_IDENTITY_MAP_ADDR
+ if (kvm_check_extension(s, KVM_CAP_SET_IDENTITY_MAP_ADDR)) {
+ /* Allows up to 16M BIOSes. */
+ identity_base = 0xfeffc000;
+
+ ret = kvm_vm_ioctl(s, KVM_SET_IDENTITY_MAP_ADDR, &identity_base);
+ if (ret < 0) {
+ return ret;
+ }
}
- ret = kvm_vm_ioctl(s, KVM_SET_TSS_ADDR, 0xfffbd000);
+#endif
+ /* Set TSS base one page after EPT identity map. */
+ ret = kvm_vm_ioctl(s, KVM_SET_TSS_ADDR, identity_base + 0x1000);
+ if (ret < 0) {
+ return ret;
+ }
+
+ /* Tell fw_cfg to notify the BIOS to reserve the range. */
+ ret = e820_add_entry(identity_base, 0x4000, E820_RESERVED);
if (ret < 0) {
+ fprintf(stderr, "e820_add_entry() table is full\n");
return ret;
}
- return kvm_init_identity_map_page(s);
+ return 0;
}
static void set_v8086_seg(struct kvm_segment *lhs, const SegmentCache *rhs)
commit 94a8d39afd8ccfdbf578af04c3385fdb5f545af1
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Fri Jan 21 21:48:17 2011 +0100
kvm: Consolidate must-have capability checks
Instead of splattering the code with #ifdefs and runtime checks for
capabilities we cannot work without anyway, provide central test
infrastructure for verifying their availability both at build and
runtime.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
diff --git a/configure b/configure
index 9a02d1f..4673bf0 100755
--- a/configure
+++ b/configure
@@ -1662,18 +1662,31 @@ if test "$kvm" != "no" ; then
#if !defined(KVM_API_VERSION) || KVM_API_VERSION < 12 || KVM_API_VERSION > 12
#error Invalid KVM version
#endif
-#if !defined(KVM_CAP_USER_MEMORY)
-#error Missing KVM capability KVM_CAP_USER_MEMORY
-#endif
-#if !defined(KVM_CAP_SET_TSS_ADDR)
-#error Missing KVM capability KVM_CAP_SET_TSS_ADDR
-#endif
-#if !defined(KVM_CAP_DESTROY_MEMORY_REGION_WORKS)
-#error Missing KVM capability KVM_CAP_DESTROY_MEMORY_REGION_WORKS
-#endif
-#if !defined(KVM_CAP_USER_NMI)
-#error Missing KVM capability KVM_CAP_USER_NMI
+EOF
+ must_have_caps="KVM_CAP_USER_MEMORY \
+ KVM_CAP_DESTROY_MEMORY_REGION_WORKS \
+ KVM_CAP_COALESCED_MMIO \
+ KVM_CAP_SYNC_MMU \
+ "
+ if test \( "$cpu" = "i386" -o "$cpu" = "x86_64" \) ; then
+ must_have_caps="$caps \
+ KVM_CAP_SET_TSS_ADDR \
+ KVM_CAP_EXT_CPUID \
+ KVM_CAP_CLOCKSOURCE \
+ KVM_CAP_NOP_IO_DELAY \
+ KVM_CAP_PV_MMU \
+ KVM_CAP_MP_STATE \
+ KVM_CAP_USER_NMI \
+ "
+ fi
+ for c in $must_have_caps ; do
+ cat >> $TMPC <<EOF
+#if !defined($c)
+#error Missing KVM capability $c
#endif
+EOF
+ done
+ cat >> $TMPC <<EOF
int main(void) { return 0; }
EOF
if test "$kerneldir" != "" ; then
@@ -1708,8 +1721,8 @@ EOF
| awk -F "error: " '{if (NR>1) printf(", "); printf("%s",$2);}'`
if test "$kvmerr" != "" ; then
echo -e "${kvmerr}\n\
- NOTE: To enable KVM support, update your kernel to 2.6.29+ or install \
- recent kvm-kmod from http://sourceforge.net/projects/kvm."
+NOTE: To enable KVM support, update your kernel to 2.6.29+ or install \
+recent kvm-kmod from http://sourceforge.net/projects/kvm."
fi
fi
feature_not_found "kvm"
diff --git a/kvm-all.c b/kvm-all.c
index 8053f92..3a1f63b 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -63,9 +63,7 @@ struct KVMState
int fd;
int vmfd;
int coalesced_mmio;
-#ifdef KVM_CAP_COALESCED_MMIO
struct kvm_coalesced_mmio_ring *coalesced_mmio_ring;
-#endif
int broken_set_mem_region;
int migration_log;
int vcpu_events;
@@ -82,6 +80,12 @@ struct KVMState
static KVMState *kvm_state;
+static const KVMCapabilityInfo kvm_required_capabilites[] = {
+ KVM_CAP_INFO(USER_MEMORY),
+ KVM_CAP_INFO(DESTROY_MEMORY_REGION_WORKS),
+ KVM_CAP_LAST_INFO
+};
+
static KVMSlot *kvm_alloc_slot(KVMState *s)
{
int i;
@@ -227,12 +231,10 @@ int kvm_init_vcpu(CPUState *env)
goto err;
}
-#ifdef KVM_CAP_COALESCED_MMIO
if (s->coalesced_mmio && !s->coalesced_mmio_ring) {
s->coalesced_mmio_ring =
(void *)env->kvm_run + s->coalesced_mmio * PAGE_SIZE;
}
-#endif
ret = kvm_arch_init_vcpu(env);
if (ret == 0) {
@@ -401,7 +403,6 @@ static int kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
{
int ret = -ENOSYS;
-#ifdef KVM_CAP_COALESCED_MMIO
KVMState *s = kvm_state;
if (s->coalesced_mmio) {
@@ -412,7 +413,6 @@ int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
ret = kvm_vm_ioctl(s, KVM_REGISTER_COALESCED_MMIO, &zone);
}
-#endif
return ret;
}
@@ -420,7 +420,6 @@ int kvm_coalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
{
int ret = -ENOSYS;
-#ifdef KVM_CAP_COALESCED_MMIO
KVMState *s = kvm_state;
if (s->coalesced_mmio) {
@@ -431,7 +430,6 @@ int kvm_uncoalesce_mmio_region(target_phys_addr_t start, ram_addr_t size)
ret = kvm_vm_ioctl(s, KVM_UNREGISTER_COALESCED_MMIO, &zone);
}
-#endif
return ret;
}
@@ -481,6 +479,18 @@ static int kvm_check_many_ioeventfds(void)
#endif
}
+static const KVMCapabilityInfo *
+kvm_check_extension_list(KVMState *s, const KVMCapabilityInfo *list)
+{
+ while (list->name) {
+ if (!kvm_check_extension(s, list->value)) {
+ return list;
+ }
+ list++;
+ }
+ return NULL;
+}
+
static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
ram_addr_t phys_offset)
{
@@ -642,6 +652,7 @@ int kvm_init(void)
"Please upgrade to at least kernel 2.6.29 or recent kvm-kmod\n"
"(see http://sourceforge.net/projects/kvm).\n";
KVMState *s;
+ const KVMCapabilityInfo *missing_cap;
int ret;
int i;
@@ -685,35 +696,19 @@ int kvm_init(void)
goto err;
}
- /* initially, KVM allocated its own memory and we had to jump through
- * hooks to make phys_ram_base point to this. Modern versions of KVM
- * just use a user allocated buffer so we can use regular pages
- * unmodified. Make sure we have a sufficiently modern version of KVM.
- */
- if (!kvm_check_extension(s, KVM_CAP_USER_MEMORY)) {
- ret = -EINVAL;
- fprintf(stderr, "kvm does not support KVM_CAP_USER_MEMORY\n%s",
- upgrade_note);
- goto err;
+ missing_cap = kvm_check_extension_list(s, kvm_required_capabilites);
+ if (!missing_cap) {
+ missing_cap =
+ kvm_check_extension_list(s, kvm_arch_required_capabilities);
}
-
- /* There was a nasty bug in < kvm-80 that prevents memory slots from being
- * destroyed properly. Since we rely on this capability, refuse to work
- * with any kernel without this capability. */
- if (!kvm_check_extension(s, KVM_CAP_DESTROY_MEMORY_REGION_WORKS)) {
+ if (missing_cap) {
ret = -EINVAL;
-
- fprintf(stderr,
- "KVM kernel module broken (DESTROY_MEMORY_REGION).\n%s",
- upgrade_note);
+ fprintf(stderr, "kvm does not support %s\n%s",
+ missing_cap->name, upgrade_note);
goto err;
}
- s->coalesced_mmio = 0;
-#ifdef KVM_CAP_COALESCED_MMIO
s->coalesced_mmio = kvm_check_extension(s, KVM_CAP_COALESCED_MMIO);
- s->coalesced_mmio_ring = NULL;
-#endif
s->broken_set_mem_region = 1;
#ifdef KVM_CAP_JOIN_MEMORY_REGIONS_WORKS
@@ -845,7 +840,6 @@ static int kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
void kvm_flush_coalesced_mmio_buffer(void)
{
-#ifdef KVM_CAP_COALESCED_MMIO
KVMState *s = kvm_state;
if (s->coalesced_mmio_ring) {
struct kvm_coalesced_mmio_ring *ring = s->coalesced_mmio_ring;
@@ -859,7 +853,6 @@ void kvm_flush_coalesced_mmio_buffer(void)
ring->first = (ring->first + 1) % KVM_COALESCED_MMIO_MAX;
}
}
-#endif
}
static void do_kvm_cpu_synchronize_state(void *_env)
@@ -1059,13 +1052,7 @@ int kvm_vcpu_ioctl(CPUState *env, int type, ...)
int kvm_has_sync_mmu(void)
{
-#ifdef KVM_CAP_SYNC_MMU
- KVMState *s = kvm_state;
-
- return kvm_check_extension(s, KVM_CAP_SYNC_MMU);
-#else
- return 0;
-#endif
+ return kvm_check_extension(kvm_state, KVM_CAP_SYNC_MMU);
}
int kvm_has_vcpu_events(void)
diff --git a/kvm.h b/kvm.h
index a971752..ca57517 100644
--- a/kvm.h
+++ b/kvm.h
@@ -32,6 +32,14 @@ extern int kvm_allowed;
struct kvm_run;
+typedef struct KVMCapabilityInfo {
+ const char *name;
+ int value;
+} KVMCapabilityInfo;
+
+#define KVM_CAP_INFO(CAP) { "KVM_CAP_" stringify(CAP), KVM_CAP_##CAP }
+#define KVM_CAP_LAST_INFO { NULL, 0 }
+
/* external API */
int kvm_init(void);
@@ -86,6 +94,8 @@ int kvm_vcpu_ioctl(CPUState *env, int type, ...);
/* Arch specific hooks */
+extern const KVMCapabilityInfo kvm_arch_required_capabilities[];
+
int kvm_arch_post_run(CPUState *env, struct kvm_run *run);
int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run);
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 016b67d..1db8227 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -54,12 +54,17 @@
#define BUS_MCEERR_AO 5
#endif
+const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
+ KVM_CAP_INFO(SET_TSS_ADDR),
+ KVM_CAP_INFO(EXT_CPUID),
+ KVM_CAP_INFO(MP_STATE),
+ KVM_CAP_LAST_INFO
+};
+
static bool has_msr_star;
static bool has_msr_hsave_pa;
static int lm_capable_kernel;
-#ifdef KVM_CAP_EXT_CPUID
-
static struct kvm_cpuid2 *try_get_cpuid(KVMState *s, int max)
{
struct kvm_cpuid2 *cpuid;
@@ -93,10 +98,6 @@ uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
uint32_t ret = 0;
uint32_t cpuid_1_edx;
- if (!kvm_check_extension(env->kvm_state, KVM_CAP_EXT_CPUID)) {
- return -1U;
- }
-
max = 1;
while ((cpuid = try_get_cpuid(env->kvm_state, max)) == NULL) {
max *= 2;
@@ -140,30 +141,14 @@ uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
return ret;
}
-#else
-
-uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
- uint32_t index, int reg)
-{
- return -1U;
-}
-
-#endif
-
#ifdef CONFIG_KVM_PARA
struct kvm_para_features {
int cap;
int feature;
} para_features[] = {
-#ifdef KVM_CAP_CLOCKSOURCE
{ KVM_CAP_CLOCKSOURCE, KVM_FEATURE_CLOCKSOURCE },
-#endif
-#ifdef KVM_CAP_NOP_IO_DELAY
{ KVM_CAP_NOP_IO_DELAY, KVM_FEATURE_NOP_IO_DELAY },
-#endif
-#ifdef KVM_CAP_PV_MMU
{ KVM_CAP_PV_MMU, KVM_FEATURE_MMU_OP },
-#endif
#ifdef KVM_CAP_ASYNC_PF
{ KVM_CAP_ASYNC_PF, KVM_FEATURE_ASYNC_PF },
#endif
@@ -542,15 +527,7 @@ int kvm_arch_init(KVMState *s)
/* create vm86 tss. KVM uses vm86 mode to emulate 16-bit code
* directly. In order to use vm86 mode, a TSS is needed. Since this
- * must be part of guest physical memory, we need to allocate it. Older
- * versions of KVM just assumed that it would be at the end of physical
- * memory but that doesn't work with more than 4GB of memory. We simply
- * refuse to work with those older versions of KVM. */
- ret = kvm_check_extension(s, KVM_CAP_SET_TSS_ADDR);
- if (ret <= 0) {
- fprintf(stderr, "kvm does not support KVM_CAP_SET_TSS_ADDR\n");
- return ret;
- }
+ * must be part of guest physical memory, we need to allocate it. */
/* this address is 3 pages before the bios, and the bios should present
* as unavaible memory. FIXME, need to ensure the e820 map deals with
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 3c05630..710eca1 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -37,6 +37,10 @@
do { } while (0)
#endif
+const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
+ KVM_CAP_LAST_INFO
+};
+
static int cap_interrupt_unset = false;
static int cap_interrupt_level = false;
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index b177e10..38823f5 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -70,6 +70,10 @@
#define SCLP_CMDW_READ_SCP_INFO 0x00020001
#define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001
+const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
+ KVM_CAP_LAST_INFO
+};
+
int kvm_arch_init(KVMState *s)
{
return 0;
commit cad1e2827b616487e3574300f2eaeea13a355197
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Fri Jan 21 21:48:16 2011 +0100
kvm: Drop smp_cpus argument from init functions
No longer used.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
diff --git a/kvm-all.c b/kvm-all.c
index 41decde..8053f92 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -636,7 +636,7 @@ static CPUPhysMemoryClient kvm_cpu_phys_memory_client = {
.migration_log = kvm_client_migration_log,
};
-int kvm_init(int smp_cpus)
+int kvm_init(void)
{
static const char upgrade_note[] =
"Please upgrade to at least kernel 2.6.29 or recent kvm-kmod\n"
@@ -749,7 +749,7 @@ int kvm_init(int smp_cpus)
s->xcrs = kvm_check_extension(s, KVM_CAP_XCRS);
#endif
- ret = kvm_arch_init(s, smp_cpus);
+ ret = kvm_arch_init(s);
if (ret < 0) {
goto err;
}
diff --git a/kvm-stub.c b/kvm-stub.c
index 33d4476..88682f2 100644
--- a/kvm-stub.c
+++ b/kvm-stub.c
@@ -58,7 +58,7 @@ int kvm_check_extension(KVMState *s, unsigned int extension)
return 0;
}
-int kvm_init(int smp_cpus)
+int kvm_init(void)
{
return -ENOSYS;
}
diff --git a/kvm.h b/kvm.h
index ce08d42..a971752 100644
--- a/kvm.h
+++ b/kvm.h
@@ -34,7 +34,7 @@ struct kvm_run;
/* external API */
-int kvm_init(int smp_cpus);
+int kvm_init(void);
int kvm_has_sync_mmu(void);
int kvm_has_vcpu_events(void);
@@ -105,7 +105,7 @@ int kvm_arch_get_registers(CPUState *env);
int kvm_arch_put_registers(CPUState *env, int level);
-int kvm_arch_init(KVMState *s, int smp_cpus);
+int kvm_arch_init(KVMState *s);
int kvm_arch_init_vcpu(CPUState *env);
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index feaf33d..016b67d 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -527,7 +527,7 @@ static int kvm_init_identity_map_page(KVMState *s)
return 0;
}
-int kvm_arch_init(KVMState *s, int smp_cpus)
+int kvm_arch_init(KVMState *s)
{
int ret;
struct utsname utsname;
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 849b404..3c05630 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -56,7 +56,7 @@ static void kvm_kick_env(void *env)
qemu_cpu_kick(env);
}
-int kvm_arch_init(KVMState *s, int smp_cpus)
+int kvm_arch_init(KVMState *s)
{
#ifdef KVM_CAP_PPC_UNSET_IRQ
cap_interrupt_unset = kvm_check_extension(s, KVM_CAP_PPC_UNSET_IRQ);
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index adf4a9e..b177e10 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -70,7 +70,7 @@
#define SCLP_CMDW_READ_SCP_INFO 0x00020001
#define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001
-int kvm_arch_init(KVMState *s, int smp_cpus)
+int kvm_arch_init(KVMState *s)
{
return 0;
}
diff --git a/vl.c b/vl.c
index 0292184..33f844f 100644
--- a/vl.c
+++ b/vl.c
@@ -2836,7 +2836,7 @@ int main(int argc, char **argv, char **envp)
}
if (kvm_allowed) {
- int ret = kvm_init(smp_cpus);
+ int ret = kvm_init();
if (ret < 0) {
if (!kvm_available()) {
printf("KVM not supported for this target\n");
commit 521f0798d7e38c21983211a6585ebcf79de4c14a
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Fri Jan 21 21:48:15 2011 +0100
kvm: x86: Fix !CONFIG_KVM_PARA build
If we lack kvm_para.h, MSR_KVM_ASYNC_PF_EN is not defined. The change in
kvm_arch_init_vcpu is just for consistency reasons.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 825af42..feaf33d 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -319,7 +319,7 @@ int kvm_arch_init_vcpu(CPUState *env)
uint32_t limit, i, j, cpuid_i;
uint32_t unused;
struct kvm_cpuid_entry2 *c;
-#ifdef KVM_CPUID_SIGNATURE
+#ifdef CONFIG_KVM_PARA
uint32_t signature[3];
#endif
@@ -855,7 +855,7 @@ static int kvm_put_msrs(CPUState *env, int level)
kvm_msr_entry_set(&msrs[n++], MSR_KVM_SYSTEM_TIME,
env->system_time_msr);
kvm_msr_entry_set(&msrs[n++], MSR_KVM_WALL_CLOCK, env->wall_clock_msr);
-#ifdef KVM_CAP_ASYNC_PF
+#if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ASYNC_PF)
kvm_msr_entry_set(&msrs[n++], MSR_KVM_ASYNC_PF_EN, env->async_pf_en_msr);
#endif
}
@@ -1091,7 +1091,7 @@ static int kvm_get_msrs(CPUState *env)
#endif
msrs[n++].index = MSR_KVM_SYSTEM_TIME;
msrs[n++].index = MSR_KVM_WALL_CLOCK;
-#ifdef KVM_CAP_ASYNC_PF
+#if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ASYNC_PF)
msrs[n++].index = MSR_KVM_ASYNC_PF_EN;
#endif
@@ -1167,7 +1167,7 @@ static int kvm_get_msrs(CPUState *env)
}
#endif
break;
-#ifdef KVM_CAP_ASYNC_PF
+#if defined(CONFIG_KVM_PARA) && defined(KVM_CAP_ASYNC_PF)
case MSR_KVM_ASYNC_PF_EN:
env->async_pf_en_msr = msrs[i].data;
break;
commit ff5c186b8b6169bf25a6f30670a75fb9d4c945e3
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Fri Jan 21 21:48:14 2011 +0100
kvm: x86: Reset paravirtual MSRs
Make sure to write the cleared MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK,
and MSR_KVM_ASYNC_PF_EN to the kernel state so that a freshly booted
guest cannot be disturbed by old values.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
CC: Glauber Costa <glommer at redhat.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 454ddb1..825af42 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -845,6 +845,13 @@ static int kvm_put_msrs(CPUState *env, int level)
if (smp_cpus == 1 || env->tsc != 0) {
kvm_msr_entry_set(&msrs[n++], MSR_IA32_TSC, env->tsc);
}
+ }
+ /*
+ * The following paravirtual MSRs have side effects on the guest or are
+ * too heavy for normal writeback. Limit them to reset or full state
+ * updates.
+ */
+ if (level >= KVM_PUT_RESET_STATE) {
kvm_msr_entry_set(&msrs[n++], MSR_KVM_SYSTEM_TIME,
env->system_time_msr);
kvm_msr_entry_set(&msrs[n++], MSR_KVM_WALL_CLOCK, env->wall_clock_msr);
commit c3a3a7d356c4df2fe145037172ae52cba5f545a5
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Fri Jan 21 21:48:13 2011 +0100
kvm: x86: Refactor msr_star/hsave_pa setup and checks
Simplify kvm_has_msr_star/hsave_pa to booleans and push their one-time
initialization into kvm_arch_init. Also handle potential errors of that
setup procedure.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index c4a22dd..454ddb1 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -54,6 +54,8 @@
#define BUS_MCEERR_AO 5
#endif
+static bool has_msr_star;
+static bool has_msr_hsave_pa;
static int lm_capable_kernel;
#ifdef KVM_CAP_EXT_CPUID
@@ -459,13 +461,10 @@ void kvm_arch_reset_vcpu(CPUState *env)
}
}
-int has_msr_star;
-int has_msr_hsave_pa;
-
-static void kvm_supported_msrs(CPUState *env)
+static int kvm_get_supported_msrs(KVMState *s)
{
static int kvm_supported_msrs;
- int ret;
+ int ret = 0;
/* first time */
if (kvm_supported_msrs == 0) {
@@ -476,9 +475,9 @@ static void kvm_supported_msrs(CPUState *env)
/* Obtain MSR list from KVM. These are the MSRs that we must
* save/restore */
msr_list.nmsrs = 0;
- ret = kvm_ioctl(env->kvm_state, KVM_GET_MSR_INDEX_LIST, &msr_list);
+ ret = kvm_ioctl(s, KVM_GET_MSR_INDEX_LIST, &msr_list);
if (ret < 0 && ret != -E2BIG) {
- return;
+ return ret;
}
/* Old kernel modules had a bug and could write beyond the provided
memory. Allocate at least a safe amount of 1K. */
@@ -487,17 +486,17 @@ static void kvm_supported_msrs(CPUState *env)
sizeof(msr_list.indices[0])));
kvm_msr_list->nmsrs = msr_list.nmsrs;
- ret = kvm_ioctl(env->kvm_state, KVM_GET_MSR_INDEX_LIST, kvm_msr_list);
+ ret = kvm_ioctl(s, KVM_GET_MSR_INDEX_LIST, kvm_msr_list);
if (ret >= 0) {
int i;
for (i = 0; i < kvm_msr_list->nmsrs; i++) {
if (kvm_msr_list->indices[i] == MSR_STAR) {
- has_msr_star = 1;
+ has_msr_star = true;
continue;
}
if (kvm_msr_list->indices[i] == MSR_VM_HSAVE_PA) {
- has_msr_hsave_pa = 1;
+ has_msr_hsave_pa = true;
continue;
}
}
@@ -506,19 +505,7 @@ static void kvm_supported_msrs(CPUState *env)
free(kvm_msr_list);
}
- return;
-}
-
-static int kvm_has_msr_hsave_pa(CPUState *env)
-{
- kvm_supported_msrs(env);
- return has_msr_hsave_pa;
-}
-
-static int kvm_has_msr_star(CPUState *env)
-{
- kvm_supported_msrs(env);
- return has_msr_star;
+ return ret;
}
static int kvm_init_identity_map_page(KVMState *s)
@@ -543,9 +530,13 @@ static int kvm_init_identity_map_page(KVMState *s)
int kvm_arch_init(KVMState *s, int smp_cpus)
{
int ret;
-
struct utsname utsname;
+ ret = kvm_get_supported_msrs(s);
+ if (ret < 0) {
+ return ret;
+ }
+
uname(&utsname);
lm_capable_kernel = strcmp(utsname.machine, "x86_64") == 0;
@@ -830,10 +821,10 @@ static int kvm_put_msrs(CPUState *env, int level)
kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_CS, env->sysenter_cs);
kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_ESP, env->sysenter_esp);
kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_EIP, env->sysenter_eip);
- if (kvm_has_msr_star(env)) {
+ if (has_msr_star) {
kvm_msr_entry_set(&msrs[n++], MSR_STAR, env->star);
}
- if (kvm_has_msr_hsave_pa(env)) {
+ if (has_msr_hsave_pa) {
kvm_msr_entry_set(&msrs[n++], MSR_VM_HSAVE_PA, env->vm_hsave);
}
#ifdef TARGET_X86_64
@@ -1076,10 +1067,10 @@ static int kvm_get_msrs(CPUState *env)
msrs[n++].index = MSR_IA32_SYSENTER_CS;
msrs[n++].index = MSR_IA32_SYSENTER_ESP;
msrs[n++].index = MSR_IA32_SYSENTER_EIP;
- if (kvm_has_msr_star(env)) {
+ if (has_msr_star) {
msrs[n++].index = MSR_STAR;
}
- if (kvm_has_msr_hsave_pa(env)) {
+ if (has_msr_hsave_pa) {
msrs[n++].index = MSR_VM_HSAVE_PA;
}
msrs[n++].index = MSR_IA32_TSC;
commit 1a5e9d2fafa5d31587e218cea462637bfad52b53
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Fri Jan 21 21:48:12 2011 +0100
kvm: x86: Fix xcr0 reset mismerge
For unknown reasons, xcr0 reset ended up in kvm_arch_update_guest_debug
on upstream merge. Fix this and also remove the misleading comment (1 is
THE reset value).
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 07c75c0..c4a22dd 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -450,6 +450,7 @@ void kvm_arch_reset_vcpu(CPUState *env)
env->interrupt_injected = -1;
env->nmi_injected = 0;
env->nmi_pending = 0;
+ env->xcr0 = 1;
if (kvm_irqchip_in_kernel()) {
env->mp_state = cpu_is_bsp(env) ? KVM_MP_STATE_RUNNABLE :
KVM_MP_STATE_UNINITIALIZED;
@@ -1759,8 +1760,6 @@ void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
((uint32_t)len_code[hw_breakpoint[n].len] << (18 + n*4));
}
}
- /* Legal xcr0 for loading */
- env->xcr0 = 1;
}
#endif /* KVM_CAP_SET_GUEST_DEBUG */
commit 3390e7f79784cbc75df408740cda4edbcf57ac58
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Fri Jan 21 21:48:11 2011 +0100
kvm: x86: Remove redundant mp_state initialization
kvm_arch_reset_vcpu initializes mp_state, and that function is invoked
right after kvm_arch_init_vcpu.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 531b69e..07c75c0 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -321,8 +321,6 @@ int kvm_arch_init_vcpu(CPUState *env)
uint32_t signature[3];
#endif
- env->mp_state = KVM_MP_STATE_RUNNABLE;
-
env->cpuid_features &= kvm_arch_get_supported_cpuid(env, 1, 0, R_EDX);
i = env->cpuid_ext_features & CPUID_EXT_HYPERVISOR;
commit c14750e8ad4a9d8d7621e2594abda34df19a6eff
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Fri Jan 21 21:48:10 2011 +0100
kvm: x86: Prepare kvm_get_mp_state for in-kernel irqchip
This code path will not yet be taken as we still lack in-kernel irqchip
support. But qemu-kvm can already make use of it and drop its own
mp_state access services.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 9bb34ab..531b69e 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1198,6 +1198,9 @@ static int kvm_get_mp_state(CPUState *env)
return ret;
}
env->mp_state = mp_state.mp_state;
+ if (kvm_irqchip_in_kernel()) {
+ env->halted = (mp_state.mp_state == KVM_MP_STATE_HALTED);
+ }
return 0;
}
commit 0d75a9ecd7ff77db0f1b5bfb3a3fee2438acefa4
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Fri Jan 21 21:48:09 2011 +0100
kvm: x86: Align kvm_arch_put_registers code with comment
The ordering doesn't matter in this case, but better keep it consistent.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 0ba13fc..9bb34ab 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1388,12 +1388,12 @@ int kvm_arch_put_registers(CPUState *env, int level)
if (ret < 0) {
return ret;
}
- /* must be last */
- ret = kvm_guest_debug_workarounds(env);
+ ret = kvm_put_debugregs(env);
if (ret < 0) {
return ret;
}
- ret = kvm_put_debugregs(env);
+ /* must be last */
+ ret = kvm_guest_debug_workarounds(env);
if (ret < 0) {
return ret;
}
commit f5c848eed769b795ac9c06bfb315e4aa9116337c
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Fri Jan 21 21:48:08 2011 +0100
x86: Optionally dump code bytes on cpu_dump_state
Introduce the cpu_dump_state flag CPU_DUMP_CODE and implement it for
x86. This writes out the code bytes around the current instruction
pointer. Make use of this feature in KVM to help debugging fatal vm
exits.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
diff --git a/cpu-all.h b/cpu-all.h
index 4ce4e83..ffbd6a4 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -765,6 +765,8 @@ int page_check_range(target_ulong start, target_ulong len, int flags);
CPUState *cpu_copy(CPUState *env);
CPUState *qemu_get_cpu(int cpu);
+#define CPU_DUMP_CODE 0x00010000
+
void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
int flags);
void cpu_dump_statistics(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
diff --git a/kvm-all.c b/kvm-all.c
index 10e1194..41decde 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -832,7 +832,7 @@ static int kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
if (run->internal.suberror == KVM_INTERNAL_ERROR_EMULATION) {
fprintf(stderr, "emulation failure\n");
if (!kvm_arch_stop_on_emulation_error(env)) {
- cpu_dump_state(env, stderr, fprintf, 0);
+ cpu_dump_state(env, stderr, fprintf, CPU_DUMP_CODE);
return 0;
}
}
@@ -994,7 +994,7 @@ int kvm_cpu_exec(CPUState *env)
} while (ret > 0);
if (ret < 0) {
- cpu_dump_state(env, stderr, fprintf, 0);
+ cpu_dump_state(env, stderr, fprintf, CPU_DUMP_CODE);
vm_stop(0);
env->exit_request = 1;
}
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 6dfa27d..1217452 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -249,6 +249,9 @@ done:
cpu_fprintf(f, "\n");
}
+#define DUMP_CODE_BYTES_TOTAL 50
+#define DUMP_CODE_BYTES_BACKWARD 20
+
void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
int flags)
{
@@ -434,6 +437,24 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
cpu_fprintf(f, " ");
}
}
+ if (flags & CPU_DUMP_CODE) {
+ target_ulong base = env->segs[R_CS].base + env->eip;
+ target_ulong offs = MIN(env->eip, DUMP_CODE_BYTES_BACKWARD);
+ uint8_t code;
+ char codestr[3];
+
+ cpu_fprintf(f, "Code=");
+ for (i = 0; i < DUMP_CODE_BYTES_TOTAL; i++) {
+ if (cpu_memory_rw_debug(env, base - offs + i, &code, 1, 0) == 0) {
+ snprintf(codestr, sizeof(codestr), "%02x", code);
+ } else {
+ snprintf(codestr, sizeof(codestr), "??");
+ }
+ cpu_fprintf(f, "%s%s%s%s", i > 0 ? " " : "",
+ i == offs ? "<" : "", codestr, i == offs ? ">" : "");
+ }
+ cpu_fprintf(f, "\n");
+ }
}
/***********************************************************/
commit bb44e0d12df70bd4a653341db4446daf6a9326be
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Fri Jan 21 21:48:07 2011 +0100
kvm: Improve reporting of fatal errors
Report KVM_EXIT_UNKNOWN, KVM_EXIT_FAIL_ENTRY, and KVM_EXIT_EXCEPTION
with more details to stderr. The latter two are so far x86-only, so move
them into the arch-specific handler. Integrate the Intel real mode
warning on KVM_EXIT_FAIL_ENTRY that qemu-kvm carries, but actually
restrict it to Intel CPUs. Moreover, always dump the CPU state in case
we fail.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
diff --git a/kvm-all.c b/kvm-all.c
index eaf9272..10e1194 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -817,22 +817,22 @@ static int kvm_handle_io(uint16_t port, void *data, int direction, int size,
#ifdef KVM_CAP_INTERNAL_ERROR_DATA
static int kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
{
-
+ fprintf(stderr, "KVM internal error.");
if (kvm_check_extension(kvm_state, KVM_CAP_INTERNAL_ERROR_DATA)) {
int i;
- fprintf(stderr, "KVM internal error. Suberror: %d\n",
- run->internal.suberror);
-
+ fprintf(stderr, " Suberror: %d\n", run->internal.suberror);
for (i = 0; i < run->internal.ndata; ++i) {
fprintf(stderr, "extra data[%d]: %"PRIx64"\n",
i, (uint64_t)run->internal.data[i]);
}
+ } else {
+ fprintf(stderr, "\n");
}
- cpu_dump_state(env, stderr, fprintf, 0);
if (run->internal.suberror == KVM_INTERNAL_ERROR_EMULATION) {
fprintf(stderr, "emulation failure\n");
if (!kvm_arch_stop_on_emulation_error(env)) {
+ cpu_dump_state(env, stderr, fprintf, 0);
return 0;
}
}
@@ -966,15 +966,8 @@ int kvm_cpu_exec(CPUState *env)
ret = 1;
break;
case KVM_EXIT_UNKNOWN:
- DPRINTF("kvm_exit_unknown\n");
- ret = -1;
- break;
- case KVM_EXIT_FAIL_ENTRY:
- DPRINTF("kvm_exit_fail_entry\n");
- ret = -1;
- break;
- case KVM_EXIT_EXCEPTION:
- DPRINTF("kvm_exit_exception\n");
+ fprintf(stderr, "KVM: unknown exit, hardware reason %" PRIx64 "\n",
+ (uint64_t)run->hw.hardware_exit_reason);
ret = -1;
break;
#ifdef KVM_CAP_INTERNAL_ERROR_DATA
@@ -1001,6 +994,7 @@ int kvm_cpu_exec(CPUState *env)
} while (ret > 0);
if (ret < 0) {
+ cpu_dump_state(env, stderr, fprintf, 0);
vm_stop(0);
env->exit_request = 1;
}
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index dddcd74..a457423 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -874,6 +874,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
uint32_t *ecx, uint32_t *edx);
int cpu_x86_register (CPUX86State *env, const char *cpu_model);
void cpu_clear_apic_feature(CPUX86State *env);
+void host_cpuid(uint32_t function, uint32_t count,
+ uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
/* helper.c */
int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index 165045e..5382a28 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -103,9 +103,8 @@ typedef struct model_features_t {
int check_cpuid = 0;
int enforce_cpuid = 0;
-static void host_cpuid(uint32_t function, uint32_t count,
- uint32_t *eax, uint32_t *ebx,
- uint32_t *ecx, uint32_t *edx)
+void host_cpuid(uint32_t function, uint32_t count,
+ uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
{
#if defined(CONFIG_KVM)
uint32_t vec[4];
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 6b4abaa..0ba13fc 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1525,8 +1525,19 @@ static int kvm_handle_halt(CPUState *env)
return 1;
}
+static bool host_supports_vmx(void)
+{
+ uint32_t ecx, unused;
+
+ host_cpuid(1, 0, &unused, &unused, &ecx, &unused);
+ return ecx & CPUID_EXT_VMX;
+}
+
+#define VMX_INVALID_GUEST_STATE 0x80000021
+
int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
{
+ uint64_t code;
int ret = 0;
switch (run->exit_reason) {
@@ -1537,6 +1548,28 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
case KVM_EXIT_SET_TPR:
ret = 1;
break;
+ case KVM_EXIT_FAIL_ENTRY:
+ code = run->fail_entry.hardware_entry_failure_reason;
+ fprintf(stderr, "KVM: entry failed, hardware error 0x%" PRIx64 "\n",
+ code);
+ if (host_supports_vmx() && code == VMX_INVALID_GUEST_STATE) {
+ fprintf(stderr,
+ "\nIf you're runnning a guest on an Intel machine without "
+ "unrestricted mode\n"
+ "support, the failure can be most likely due to the guest "
+ "entering an invalid\n"
+ "state for Intel VT. For example, the guest maybe running "
+ "in big real mode\n"
+ "which is not supported on less recent Intel processors."
+ "\n\n");
+ }
+ ret = -1;
+ break;
+ case KVM_EXIT_EXCEPTION:
+ fprintf(stderr, "KVM: exception %d exit (error code 0x%x)\n",
+ run->ex.exception, run->ex.error_code);
+ ret = -1;
+ break;
default:
fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
ret = -1;
commit 73aaec4a39b3cf11082303a6cf6bcde8796c09c6
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Fri Jan 21 21:48:06 2011 +0100
kvm: Stop on all fatal exit reasons
Ensure that we stop the guest whenever we face a fatal or unknown exit
reason. If we stop, we also have to enforce a cpu loop exit.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
diff --git a/kvm-all.c b/kvm-all.c
index 86ddbd6..eaf9272 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -815,7 +815,7 @@ static int kvm_handle_io(uint16_t port, void *data, int direction, int size,
}
#ifdef KVM_CAP_INTERNAL_ERROR_DATA
-static void kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
+static int kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
{
if (kvm_check_extension(kvm_state, KVM_CAP_INTERNAL_ERROR_DATA)) {
@@ -833,13 +833,13 @@ static void kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
if (run->internal.suberror == KVM_INTERNAL_ERROR_EMULATION) {
fprintf(stderr, "emulation failure\n");
if (!kvm_arch_stop_on_emulation_error(env)) {
- return;
+ return 0;
}
}
/* FIXME: Should trigger a qmp message to let management know
* something went wrong.
*/
- vm_stop(0);
+ return -1;
}
#endif
@@ -967,16 +967,19 @@ int kvm_cpu_exec(CPUState *env)
break;
case KVM_EXIT_UNKNOWN:
DPRINTF("kvm_exit_unknown\n");
+ ret = -1;
break;
case KVM_EXIT_FAIL_ENTRY:
DPRINTF("kvm_exit_fail_entry\n");
+ ret = -1;
break;
case KVM_EXIT_EXCEPTION:
DPRINTF("kvm_exit_exception\n");
+ ret = -1;
break;
#ifdef KVM_CAP_INTERNAL_ERROR_DATA
case KVM_EXIT_INTERNAL_ERROR:
- kvm_handle_internal_error(env, run);
+ ret = kvm_handle_internal_error(env, run);
break;
#endif
case KVM_EXIT_DEBUG:
@@ -997,6 +1000,10 @@ int kvm_cpu_exec(CPUState *env)
}
} while (ret > 0);
+ if (ret < 0) {
+ vm_stop(0);
+ env->exit_request = 1;
+ }
if (env->exit_request) {
env->exit_request = 0;
env->exception_index = EXCP_INTERRUPT;
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 0aeb079..6b4abaa 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1537,6 +1537,10 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
case KVM_EXIT_SET_TPR:
ret = 1;
break;
+ default:
+ fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
+ ret = -1;
+ break;
}
return ret;
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 5caa07c..849b404 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -307,6 +307,10 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
dprintf("handle halt\n");
ret = kvmppc_handle_halt(env);
break;
+ default:
+ fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
+ ret = -1;
+ break;
}
return ret;
commit 646042e1aba31f377892e48f6145fbc8487d4481
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Fri Jan 21 21:48:05 2011 +0100
kvm: x86: Swallow KVM_EXIT_SET_TPR
This exit only triggers activity in the common exit path, but we should
accept it in order to be able to detect unknown exit types.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index fda07d2..0aeb079 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1534,6 +1534,9 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
DPRINTF("handle_hlt\n");
ret = kvm_handle_halt(env);
break;
+ case KVM_EXIT_SET_TPR:
+ ret = 1;
+ break;
}
return ret;
commit a426e122173f36f05ea2cb72dcff77b7408546ce
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Tue Jan 4 09:32:13 2011 +0100
kvm: Fix coding style violations
No functional changes.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
diff --git a/kvm-all.c b/kvm-all.c
index 935c436..86ddbd6 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -88,10 +88,12 @@ static KVMSlot *kvm_alloc_slot(KVMState *s)
for (i = 0; i < ARRAY_SIZE(s->slots); i++) {
/* KVM private memory slots */
- if (i >= 8 && i < 12)
+ if (i >= 8 && i < 12) {
continue;
- if (s->slots[i].memory_size == 0)
+ }
+ if (s->slots[i].memory_size == 0) {
return &s->slots[i];
+ }
}
fprintf(stderr, "%s: no free slot available\n", __func__);
@@ -226,9 +228,10 @@ int kvm_init_vcpu(CPUState *env)
}
#ifdef KVM_CAP_COALESCED_MMIO
- if (s->coalesced_mmio && !s->coalesced_mmio_ring)
- s->coalesced_mmio_ring = (void *) env->kvm_run +
- s->coalesced_mmio * PAGE_SIZE;
+ if (s->coalesced_mmio && !s->coalesced_mmio_ring) {
+ s->coalesced_mmio_ring =
+ (void *)env->kvm_run + s->coalesced_mmio * PAGE_SIZE;
+ }
#endif
ret = kvm_arch_init_vcpu(env);
@@ -275,16 +278,14 @@ static int kvm_dirty_pages_log_change(target_phys_addr_t phys_addr,
int kvm_log_start(target_phys_addr_t phys_addr, ram_addr_t size)
{
- return kvm_dirty_pages_log_change(phys_addr, size,
- KVM_MEM_LOG_DIRTY_PAGES,
- KVM_MEM_LOG_DIRTY_PAGES);
+ return kvm_dirty_pages_log_change(phys_addr, size, KVM_MEM_LOG_DIRTY_PAGES,
+ KVM_MEM_LOG_DIRTY_PAGES);
}
int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size)
{
- return kvm_dirty_pages_log_change(phys_addr, size,
- 0,
- KVM_MEM_LOG_DIRTY_PAGES);
+ return kvm_dirty_pages_log_change(phys_addr, size, 0,
+ KVM_MEM_LOG_DIRTY_PAGES);
}
static int kvm_set_migration_log(int enable)
@@ -356,7 +357,7 @@ static int kvm_get_dirty_pages_log_range(unsigned long start_addr,
* @end_addr: end of logged region.
*/
static int kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
- target_phys_addr_t end_addr)
+ target_phys_addr_t end_addr)
{
KVMState *s = kvm_state;
unsigned long size, allocated_size = 0;
@@ -480,9 +481,8 @@ static int kvm_check_many_ioeventfds(void)
#endif
}
-static void kvm_set_phys_mem(target_phys_addr_t start_addr,
- ram_addr_t size,
- ram_addr_t phys_offset)
+static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
+ ram_addr_t phys_offset)
{
KVMState *s = kvm_state;
ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
@@ -589,13 +589,13 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr,
}
/* in case the KVM bug workaround already "consumed" the new slot */
- if (!size)
+ if (!size) {
return;
-
+ }
/* KVM does not need to know about this memory */
- if (flags >= IO_MEM_UNASSIGNED)
+ if (flags >= IO_MEM_UNASSIGNED) {
return;
-
+ }
mem = kvm_alloc_slot(s);
mem->memory_size = size;
mem->start_addr = start_addr;
@@ -611,30 +611,29 @@ static void kvm_set_phys_mem(target_phys_addr_t start_addr,
}
static void kvm_client_set_memory(struct CPUPhysMemoryClient *client,
- target_phys_addr_t start_addr,
- ram_addr_t size,
- ram_addr_t phys_offset)
+ target_phys_addr_t start_addr,
+ ram_addr_t size, ram_addr_t phys_offset)
{
- kvm_set_phys_mem(start_addr, size, phys_offset);
+ kvm_set_phys_mem(start_addr, size, phys_offset);
}
static int kvm_client_sync_dirty_bitmap(struct CPUPhysMemoryClient *client,
- target_phys_addr_t start_addr,
- target_phys_addr_t end_addr)
+ target_phys_addr_t start_addr,
+ target_phys_addr_t end_addr)
{
- return kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
+ return kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
}
static int kvm_client_migration_log(struct CPUPhysMemoryClient *client,
- int enable)
+ int enable)
{
- return kvm_set_migration_log(enable);
+ return kvm_set_migration_log(enable);
}
static CPUPhysMemoryClient kvm_cpu_phys_memory_client = {
- .set_memory = kvm_client_set_memory,
- .sync_dirty_bitmap = kvm_client_sync_dirty_bitmap,
- .migration_log = kvm_client_migration_log,
+ .set_memory = kvm_client_set_memory,
+ .sync_dirty_bitmap = kvm_client_sync_dirty_bitmap,
+ .migration_log = kvm_client_migration_log,
};
int kvm_init(int smp_cpus)
@@ -651,9 +650,9 @@ int kvm_init(int smp_cpus)
#ifdef KVM_CAP_SET_GUEST_DEBUG
QTAILQ_INIT(&s->kvm_sw_breakpoints);
#endif
- for (i = 0; i < ARRAY_SIZE(s->slots); i++)
+ for (i = 0; i < ARRAY_SIZE(s->slots); i++) {
s->slots[i].slot = i;
-
+ }
s->vmfd = -1;
s->fd = qemu_open("/dev/kvm", O_RDWR);
if (s->fd == -1) {
@@ -664,8 +663,9 @@ int kvm_init(int smp_cpus)
ret = kvm_ioctl(s, KVM_GET_API_VERSION, 0);
if (ret < KVM_API_VERSION) {
- if (ret > 0)
+ if (ret > 0) {
ret = -EINVAL;
+ }
fprintf(stderr, "kvm version too old\n");
goto err;
}
@@ -750,8 +750,9 @@ int kvm_init(int smp_cpus)
#endif
ret = kvm_arch_init(s, smp_cpus);
- if (ret < 0)
+ if (ret < 0) {
goto err;
+ }
kvm_state = s;
cpu_register_phys_memory_client(&kvm_cpu_phys_memory_client);
@@ -762,10 +763,12 @@ int kvm_init(int smp_cpus)
err:
if (s) {
- if (s->vmfd != -1)
+ if (s->vmfd != -1) {
close(s->vmfd);
- if (s->fd != -1)
+ }
+ if (s->fd != -1) {
close(s->fd);
+ }
}
qemu_free(s);
@@ -829,8 +832,9 @@ static void kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
cpu_dump_state(env, stderr, fprintf, 0);
if (run->internal.suberror == KVM_INTERNAL_ERROR_EMULATION) {
fprintf(stderr, "emulation failure\n");
- if (!kvm_arch_stop_on_emulation_error(env))
- return;
+ if (!kvm_arch_stop_on_emulation_error(env)) {
+ return;
+ }
}
/* FIXME: Should trigger a qmp message to let management know
* something went wrong.
@@ -870,8 +874,9 @@ static void do_kvm_cpu_synchronize_state(void *_env)
void kvm_cpu_synchronize_state(CPUState *env)
{
- if (!env->kvm_vcpu_dirty)
+ if (!env->kvm_vcpu_dirty) {
run_on_cpu(env, do_kvm_cpu_synchronize_state, env);
+ }
}
void kvm_cpu_synchronize_post_reset(CPUState *env)
@@ -1011,9 +1016,9 @@ int kvm_ioctl(KVMState *s, int type, ...)
va_end(ap);
ret = ioctl(s->fd, type, arg);
- if (ret == -1)
+ if (ret == -1) {
ret = -errno;
-
+ }
return ret;
}
@@ -1028,9 +1033,9 @@ int kvm_vm_ioctl(KVMState *s, int type, ...)
va_end(ap);
ret = ioctl(s->vmfd, type, arg);
- if (ret == -1)
+ if (ret == -1) {
ret = -errno;
-
+ }
return ret;
}
@@ -1045,9 +1050,9 @@ int kvm_vcpu_ioctl(CPUState *env, int type, ...)
va_end(ap);
ret = ioctl(env->kvm_fd, type, arg);
- if (ret == -1)
+ if (ret == -1) {
ret = -errno;
-
+ }
return ret;
}
@@ -1116,8 +1121,9 @@ struct kvm_sw_breakpoint *kvm_find_sw_breakpoint(CPUState *env,
struct kvm_sw_breakpoint *bp;
QTAILQ_FOREACH(bp, &env->kvm_state->kvm_sw_breakpoints, entry) {
- if (bp->pc == pc)
+ if (bp->pc == pc) {
return bp;
+ }
}
return NULL;
}
@@ -1172,8 +1178,9 @@ int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
}
bp = qemu_malloc(sizeof(struct kvm_sw_breakpoint));
- if (!bp)
+ if (!bp) {
return -ENOMEM;
+ }
bp->pc = addr;
bp->use_count = 1;
@@ -1187,14 +1194,16 @@ int kvm_insert_breakpoint(CPUState *current_env, target_ulong addr,
bp, entry);
} else {
err = kvm_arch_insert_hw_breakpoint(addr, len, type);
- if (err)
+ if (err) {
return err;
+ }
}
for (env = first_cpu; env != NULL; env = env->next_cpu) {
err = kvm_update_guest_debug(env, 0);
- if (err)
+ if (err) {
return err;
+ }
}
return 0;
}
@@ -1208,8 +1217,9 @@ int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
if (type == GDB_BREAKPOINT_SW) {
bp = kvm_find_sw_breakpoint(current_env, addr);
- if (!bp)
+ if (!bp) {
return -ENOENT;
+ }
if (bp->use_count > 1) {
bp->use_count--;
@@ -1217,21 +1227,24 @@ int kvm_remove_breakpoint(CPUState *current_env, target_ulong addr,
}
err = kvm_arch_remove_sw_breakpoint(current_env, bp);
- if (err)
+ if (err) {
return err;
+ }
QTAILQ_REMOVE(¤t_env->kvm_state->kvm_sw_breakpoints, bp, entry);
qemu_free(bp);
} else {
err = kvm_arch_remove_hw_breakpoint(addr, len, type);
- if (err)
+ if (err) {
return err;
+ }
}
for (env = first_cpu; env != NULL; env = env->next_cpu) {
err = kvm_update_guest_debug(env, 0);
- if (err)
+ if (err) {
return err;
+ }
}
return 0;
}
@@ -1246,15 +1259,17 @@ void kvm_remove_all_breakpoints(CPUState *current_env)
if (kvm_arch_remove_sw_breakpoint(current_env, bp) != 0) {
/* Try harder to find a CPU that currently sees the breakpoint. */
for (env = first_cpu; env != NULL; env = env->next_cpu) {
- if (kvm_arch_remove_sw_breakpoint(env, bp) == 0)
+ if (kvm_arch_remove_sw_breakpoint(env, bp) == 0) {
break;
+ }
}
}
}
kvm_arch_remove_all_hw_breakpoints();
- for (env = first_cpu; env != NULL; env = env->next_cpu)
+ for (env = first_cpu; env != NULL; env = env->next_cpu) {
kvm_update_guest_debug(env, 0);
+ }
}
#else /* !KVM_CAP_SET_GUEST_DEBUG */
@@ -1286,8 +1301,9 @@ int kvm_set_signal_mask(CPUState *env, const sigset_t *sigset)
struct kvm_signal_mask *sigmask;
int r;
- if (!sigset)
+ if (!sigset) {
return kvm_vcpu_ioctl(env, KVM_SET_SIGNAL_MASK, NULL);
+ }
sigmask = qemu_malloc(sizeof(*sigmask) + sizeof(*sigset));
@@ -1342,13 +1358,16 @@ int kvm_set_ioeventfd_pio_word(int fd, uint16_t addr, uint16_t val, bool assign)
.fd = fd,
};
int r;
- if (!kvm_enabled())
+ if (!kvm_enabled()) {
return -ENOSYS;
- if (!assign)
+ }
+ if (!assign) {
kick.flags |= KVM_IOEVENTFD_FLAG_DEASSIGN;
+ }
r = kvm_vm_ioctl(kvm_state, KVM_IOEVENTFD, &kick);
- if (r < 0)
+ if (r < 0) {
return r;
+ }
return 0;
#else
return -ENOSYS;
commit b9bec74bcb16519a876ec21cd5277c526a9b512d
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Mon Dec 27 16:19:29 2010 +0100
kvm: x86: Fix a few coding style violations
No functional changes.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Avi Kivity <avi at redhat.com>
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 85edacc..fda07d2 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -150,34 +150,34 @@ uint32_t kvm_arch_get_supported_cpuid(CPUState *env, uint32_t function,
#ifdef CONFIG_KVM_PARA
struct kvm_para_features {
- int cap;
- int feature;
+ int cap;
+ int feature;
} para_features[] = {
#ifdef KVM_CAP_CLOCKSOURCE
- { KVM_CAP_CLOCKSOURCE, KVM_FEATURE_CLOCKSOURCE },
+ { KVM_CAP_CLOCKSOURCE, KVM_FEATURE_CLOCKSOURCE },
#endif
#ifdef KVM_CAP_NOP_IO_DELAY
- { KVM_CAP_NOP_IO_DELAY, KVM_FEATURE_NOP_IO_DELAY },
+ { KVM_CAP_NOP_IO_DELAY, KVM_FEATURE_NOP_IO_DELAY },
#endif
#ifdef KVM_CAP_PV_MMU
- { KVM_CAP_PV_MMU, KVM_FEATURE_MMU_OP },
+ { KVM_CAP_PV_MMU, KVM_FEATURE_MMU_OP },
#endif
#ifdef KVM_CAP_ASYNC_PF
- { KVM_CAP_ASYNC_PF, KVM_FEATURE_ASYNC_PF },
+ { KVM_CAP_ASYNC_PF, KVM_FEATURE_ASYNC_PF },
#endif
- { -1, -1 }
+ { -1, -1 }
};
static int get_para_features(CPUState *env)
{
- int i, features = 0;
+ int i, features = 0;
- for (i = 0; i < ARRAY_SIZE(para_features) - 1; i++) {
- if (kvm_check_extension(env->kvm_state, para_features[i].cap))
- features |= (1 << para_features[i].feature);
+ for (i = 0; i < ARRAY_SIZE(para_features) - 1; i++) {
+ if (kvm_check_extension(env->kvm_state, para_features[i].cap)) {
+ features |= (1 << para_features[i].feature);
}
-
- return features;
+ }
+ return features;
}
#endif
@@ -389,13 +389,15 @@ int kvm_arch_init_vcpu(CPUState *env)
c->index = j;
cpu_x86_cpuid(env, i, j, &c->eax, &c->ebx, &c->ecx, &c->edx);
- if (i == 4 && c->eax == 0)
+ if (i == 4 && c->eax == 0) {
break;
- if (i == 0xb && !(c->ecx & 0xff00))
+ }
+ if (i == 0xb && !(c->ecx & 0xff00)) {
break;
- if (i == 0xd && c->eax == 0)
+ }
+ if (i == 0xd && c->eax == 0) {
break;
-
+ }
c = &cpuid_data.entries[cpuid_i++];
}
break;
@@ -425,17 +427,18 @@ int kvm_arch_init_vcpu(CPUState *env)
uint64_t mcg_cap;
int banks;
- if (kvm_get_mce_cap_supported(env->kvm_state, &mcg_cap, &banks))
+ if (kvm_get_mce_cap_supported(env->kvm_state, &mcg_cap, &banks)) {
perror("kvm_get_mce_cap_supported FAILED");
- else {
+ } else {
if (banks > MCE_BANKS_DEF)
banks = MCE_BANKS_DEF;
mcg_cap &= MCE_CAP_DEF;
mcg_cap |= banks;
- if (kvm_setup_mce(env, &mcg_cap))
+ if (kvm_setup_mce(env, &mcg_cap)) {
perror("kvm_setup_mce FAILED");
- else
+ } else {
env->mcg_cap = mcg_cap;
+ }
}
}
#endif
@@ -577,7 +580,7 @@ int kvm_arch_init(KVMState *s, int smp_cpus)
return kvm_init_identity_map_page(s);
}
-
+
static void set_v8086_seg(struct kvm_segment *lhs, const SegmentCache *rhs)
{
lhs->selector = rhs->selector;
@@ -616,23 +619,23 @@ static void get_seg(SegmentCache *lhs, const struct kvm_segment *rhs)
lhs->selector = rhs->selector;
lhs->base = rhs->base;
lhs->limit = rhs->limit;
- lhs->flags =
- (rhs->type << DESC_TYPE_SHIFT)
- | (rhs->present * DESC_P_MASK)
- | (rhs->dpl << DESC_DPL_SHIFT)
- | (rhs->db << DESC_B_SHIFT)
- | (rhs->s * DESC_S_MASK)
- | (rhs->l << DESC_L_SHIFT)
- | (rhs->g * DESC_G_MASK)
- | (rhs->avl * DESC_AVL_MASK);
+ lhs->flags = (rhs->type << DESC_TYPE_SHIFT) |
+ (rhs->present * DESC_P_MASK) |
+ (rhs->dpl << DESC_DPL_SHIFT) |
+ (rhs->db << DESC_B_SHIFT) |
+ (rhs->s * DESC_S_MASK) |
+ (rhs->l << DESC_L_SHIFT) |
+ (rhs->g * DESC_G_MASK) |
+ (rhs->avl * DESC_AVL_MASK);
}
static void kvm_getput_reg(__u64 *kvm_reg, target_ulong *qemu_reg, int set)
{
- if (set)
+ if (set) {
*kvm_reg = *qemu_reg;
- else
+ } else {
*qemu_reg = *kvm_reg;
+ }
}
static int kvm_getput_regs(CPUState *env, int set)
@@ -642,8 +645,9 @@ static int kvm_getput_regs(CPUState *env, int set)
if (!set) {
ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s);
- if (ret < 0)
+ if (ret < 0) {
return ret;
+ }
}
kvm_getput_reg(®s.rax, &env->regs[R_EAX], set);
@@ -668,8 +672,9 @@ static int kvm_getput_regs(CPUState *env, int set)
kvm_getput_reg(®s.rflags, &env->eflags, set);
kvm_getput_reg(®s.rip, &env->eip, set);
- if (set)
+ if (set) {
ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, ®s);
+ }
return ret;
}
@@ -683,8 +688,9 @@ static int kvm_put_fpu(CPUState *env)
fpu.fsw = env->fpus & ~(7 << 11);
fpu.fsw |= (env->fpstt & 7) << 11;
fpu.fcw = env->fpuc;
- for (i = 0; i < 8; ++i)
- fpu.ftwx |= (!env->fptags[i]) << i;
+ for (i = 0; i < 8; ++i) {
+ fpu.ftwx |= (!env->fptags[i]) << i;
+ }
memcpy(fpu.fpr, env->fpregs, sizeof env->fpregs);
memcpy(fpu.xmm, env->xmm_regs, sizeof env->xmm_regs);
fpu.mxcsr = env->mxcsr;
@@ -709,8 +715,9 @@ static int kvm_put_xsave(CPUState *env)
struct kvm_xsave* xsave;
uint16_t cwd, swd, twd, fop;
- if (!kvm_has_xsave())
+ if (!kvm_has_xsave()) {
return kvm_put_fpu(env);
+ }
xsave = qemu_memalign(4096, sizeof(struct kvm_xsave));
memset(xsave, 0, sizeof(struct kvm_xsave));
@@ -718,8 +725,9 @@ static int kvm_put_xsave(CPUState *env)
swd = env->fpus & ~(7 << 11);
swd |= (env->fpstt & 7) << 11;
cwd = env->fpuc;
- for (i = 0; i < 8; ++i)
+ for (i = 0; i < 8; ++i) {
twd |= (!env->fptags[i]) << i;
+ }
xsave->region[0] = (uint32_t)(swd << 16) + cwd;
xsave->region[1] = (uint32_t)(fop << 16) + twd;
memcpy(&xsave->region[XSAVE_ST_SPACE], env->fpregs,
@@ -743,8 +751,9 @@ static int kvm_put_xcrs(CPUState *env)
#ifdef KVM_CAP_XCRS
struct kvm_xcrs xcrs;
- if (!kvm_has_xcrs())
+ if (!kvm_has_xcrs()) {
return 0;
+ }
xcrs.nr_xcrs = 1;
xcrs.flags = 0;
@@ -767,19 +776,19 @@ static int kvm_put_sregs(CPUState *env)
}
if ((env->eflags & VM_MASK)) {
- set_v8086_seg(&sregs.cs, &env->segs[R_CS]);
- set_v8086_seg(&sregs.ds, &env->segs[R_DS]);
- set_v8086_seg(&sregs.es, &env->segs[R_ES]);
- set_v8086_seg(&sregs.fs, &env->segs[R_FS]);
- set_v8086_seg(&sregs.gs, &env->segs[R_GS]);
- set_v8086_seg(&sregs.ss, &env->segs[R_SS]);
+ set_v8086_seg(&sregs.cs, &env->segs[R_CS]);
+ set_v8086_seg(&sregs.ds, &env->segs[R_DS]);
+ set_v8086_seg(&sregs.es, &env->segs[R_ES]);
+ set_v8086_seg(&sregs.fs, &env->segs[R_FS]);
+ set_v8086_seg(&sregs.gs, &env->segs[R_GS]);
+ set_v8086_seg(&sregs.ss, &env->segs[R_SS]);
} else {
- set_seg(&sregs.cs, &env->segs[R_CS]);
- set_seg(&sregs.ds, &env->segs[R_DS]);
- set_seg(&sregs.es, &env->segs[R_ES]);
- set_seg(&sregs.fs, &env->segs[R_FS]);
- set_seg(&sregs.gs, &env->segs[R_GS]);
- set_seg(&sregs.ss, &env->segs[R_SS]);
+ set_seg(&sregs.cs, &env->segs[R_CS]);
+ set_seg(&sregs.ds, &env->segs[R_DS]);
+ set_seg(&sregs.es, &env->segs[R_ES]);
+ set_seg(&sregs.fs, &env->segs[R_FS]);
+ set_seg(&sregs.gs, &env->segs[R_GS]);
+ set_seg(&sregs.ss, &env->segs[R_SS]);
}
set_seg(&sregs.tr, &env->tr);
@@ -822,10 +831,12 @@ static int kvm_put_msrs(CPUState *env, int level)
kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_CS, env->sysenter_cs);
kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_ESP, env->sysenter_esp);
kvm_msr_entry_set(&msrs[n++], MSR_IA32_SYSENTER_EIP, env->sysenter_eip);
- if (kvm_has_msr_star(env))
- kvm_msr_entry_set(&msrs[n++], MSR_STAR, env->star);
- if (kvm_has_msr_hsave_pa(env))
+ if (kvm_has_msr_star(env)) {
+ kvm_msr_entry_set(&msrs[n++], MSR_STAR, env->star);
+ }
+ if (kvm_has_msr_hsave_pa(env)) {
kvm_msr_entry_set(&msrs[n++], MSR_VM_HSAVE_PA, env->vm_hsave);
+ }
#ifdef TARGET_X86_64
if (lm_capable_kernel) {
kvm_msr_entry_set(&msrs[n++], MSR_CSTAR, env->cstar);
@@ -854,13 +865,15 @@ static int kvm_put_msrs(CPUState *env, int level)
#ifdef KVM_CAP_MCE
if (env->mcg_cap) {
int i;
- if (level == KVM_PUT_RESET_STATE)
+
+ if (level == KVM_PUT_RESET_STATE) {
kvm_msr_entry_set(&msrs[n++], MSR_MCG_STATUS, env->mcg_status);
- else if (level == KVM_PUT_FULL_STATE) {
+ } else if (level == KVM_PUT_FULL_STATE) {
kvm_msr_entry_set(&msrs[n++], MSR_MCG_STATUS, env->mcg_status);
kvm_msr_entry_set(&msrs[n++], MSR_MCG_CTL, env->mcg_ctl);
- for (i = 0; i < (env->mcg_cap & 0xff) * 4; i++)
+ for (i = 0; i < (env->mcg_cap & 0xff) * 4; i++) {
kvm_msr_entry_set(&msrs[n++], MSR_MC0_CTL + i, env->mce_banks[i]);
+ }
}
}
#endif
@@ -878,14 +891,16 @@ static int kvm_get_fpu(CPUState *env)
int i, ret;
ret = kvm_vcpu_ioctl(env, KVM_GET_FPU, &fpu);
- if (ret < 0)
+ if (ret < 0) {
return ret;
+ }
env->fpstt = (fpu.fsw >> 11) & 7;
env->fpus = fpu.fsw;
env->fpuc = fpu.fcw;
- for (i = 0; i < 8; ++i)
- env->fptags[i] = !((fpu.ftwx >> i) & 1);
+ for (i = 0; i < 8; ++i) {
+ env->fptags[i] = !((fpu.ftwx >> i) & 1);
+ }
memcpy(env->fpregs, fpu.fpr, sizeof env->fpregs);
memcpy(env->xmm_regs, fpu.xmm, sizeof env->xmm_regs);
env->mxcsr = fpu.mxcsr;
@@ -900,8 +915,9 @@ static int kvm_get_xsave(CPUState *env)
int ret, i;
uint16_t cwd, swd, twd, fop;
- if (!kvm_has_xsave())
+ if (!kvm_has_xsave()) {
return kvm_get_fpu(env);
+ }
xsave = qemu_memalign(4096, sizeof(struct kvm_xsave));
ret = kvm_vcpu_ioctl(env, KVM_GET_XSAVE, xsave);
@@ -917,8 +933,9 @@ static int kvm_get_xsave(CPUState *env)
env->fpstt = (swd >> 11) & 7;
env->fpus = swd;
env->fpuc = cwd;
- for (i = 0; i < 8; ++i)
+ for (i = 0; i < 8; ++i) {
env->fptags[i] = !((twd >> i) & 1);
+ }
env->mxcsr = xsave->region[XSAVE_MXCSR];
memcpy(env->fpregs, &xsave->region[XSAVE_ST_SPACE],
sizeof env->fpregs);
@@ -940,19 +957,22 @@ static int kvm_get_xcrs(CPUState *env)
int i, ret;
struct kvm_xcrs xcrs;
- if (!kvm_has_xcrs())
+ if (!kvm_has_xcrs()) {
return 0;
+ }
ret = kvm_vcpu_ioctl(env, KVM_GET_XCRS, &xcrs);
- if (ret < 0)
+ if (ret < 0) {
return ret;
+ }
- for (i = 0; i < xcrs.nr_xcrs; i++)
+ for (i = 0; i < xcrs.nr_xcrs; i++) {
/* Only support xcr0 now */
if (xcrs.xcrs[0].xcr == 0) {
env->xcr0 = xcrs.xcrs[0].value;
break;
}
+ }
return 0;
#else
return 0;
@@ -966,8 +986,9 @@ static int kvm_get_sregs(CPUState *env)
int bit, i, ret;
ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs);
- if (ret < 0)
+ if (ret < 0) {
return ret;
+ }
/* There can only be one pending IRQ set in the bitmap at a time, so try
to find it and save its number instead (-1 for none). */
@@ -1005,21 +1026,19 @@ static int kvm_get_sregs(CPUState *env)
env->efer = sregs.efer;
//cpu_set_apic_tpr(env->apic_state, sregs.cr8);
-#define HFLAG_COPY_MASK ~( \
- HF_CPL_MASK | HF_PE_MASK | HF_MP_MASK | HF_EM_MASK | \
- HF_TS_MASK | HF_TF_MASK | HF_VM_MASK | HF_IOPL_MASK | \
- HF_OSFXSR_MASK | HF_LMA_MASK | HF_CS32_MASK | \
- HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK)
-
-
+#define HFLAG_COPY_MASK \
+ ~( HF_CPL_MASK | HF_PE_MASK | HF_MP_MASK | HF_EM_MASK | \
+ HF_TS_MASK | HF_TF_MASK | HF_VM_MASK | HF_IOPL_MASK | \
+ HF_OSFXSR_MASK | HF_LMA_MASK | HF_CS32_MASK | \
+ HF_SS32_MASK | HF_CS64_MASK | HF_ADDSEG_MASK)
hflags = (env->segs[R_CS].flags >> DESC_DPL_SHIFT) & HF_CPL_MASK;
hflags |= (env->cr[0] & CR0_PE_MASK) << (HF_PE_SHIFT - CR0_PE_SHIFT);
hflags |= (env->cr[0] << (HF_MP_SHIFT - CR0_MP_SHIFT)) &
- (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK);
+ (HF_MP_MASK | HF_EM_MASK | HF_TS_MASK);
hflags |= (env->eflags & (HF_TF_MASK | HF_VM_MASK | HF_IOPL_MASK));
hflags |= (env->cr[4] & CR4_OSFXSR_MASK) <<
- (HF_OSFXSR_SHIFT - CR4_OSFXSR_SHIFT);
+ (HF_OSFXSR_SHIFT - CR4_OSFXSR_SHIFT);
if (env->efer & MSR_EFER_LMA) {
hflags |= HF_LMA_MASK;
@@ -1029,19 +1048,16 @@ static int kvm_get_sregs(CPUState *env)
hflags |= HF_CS32_MASK | HF_SS32_MASK | HF_CS64_MASK;
} else {
hflags |= (env->segs[R_CS].flags & DESC_B_MASK) >>
- (DESC_B_SHIFT - HF_CS32_SHIFT);
+ (DESC_B_SHIFT - HF_CS32_SHIFT);
hflags |= (env->segs[R_SS].flags & DESC_B_MASK) >>
- (DESC_B_SHIFT - HF_SS32_SHIFT);
- if (!(env->cr[0] & CR0_PE_MASK) ||
- (env->eflags & VM_MASK) ||
- !(hflags & HF_CS32_MASK)) {
- hflags |= HF_ADDSEG_MASK;
- } else {
- hflags |= ((env->segs[R_DS].base |
- env->segs[R_ES].base |
- env->segs[R_SS].base) != 0) <<
- HF_ADDSEG_SHIFT;
- }
+ (DESC_B_SHIFT - HF_SS32_SHIFT);
+ if (!(env->cr[0] & CR0_PE_MASK) || (env->eflags & VM_MASK) ||
+ !(hflags & HF_CS32_MASK)) {
+ hflags |= HF_ADDSEG_MASK;
+ } else {
+ hflags |= ((env->segs[R_DS].base | env->segs[R_ES].base |
+ env->segs[R_SS].base) != 0) << HF_ADDSEG_SHIFT;
+ }
}
env->hflags = (env->hflags & HFLAG_COPY_MASK) | hflags;
@@ -1061,10 +1077,12 @@ static int kvm_get_msrs(CPUState *env)
msrs[n++].index = MSR_IA32_SYSENTER_CS;
msrs[n++].index = MSR_IA32_SYSENTER_ESP;
msrs[n++].index = MSR_IA32_SYSENTER_EIP;
- if (kvm_has_msr_star(env))
- msrs[n++].index = MSR_STAR;
- if (kvm_has_msr_hsave_pa(env))
+ if (kvm_has_msr_star(env)) {
+ msrs[n++].index = MSR_STAR;
+ }
+ if (kvm_has_msr_hsave_pa(env)) {
msrs[n++].index = MSR_VM_HSAVE_PA;
+ }
msrs[n++].index = MSR_IA32_TSC;
#ifdef TARGET_X86_64
if (lm_capable_kernel) {
@@ -1084,15 +1102,17 @@ static int kvm_get_msrs(CPUState *env)
if (env->mcg_cap) {
msrs[n++].index = MSR_MCG_STATUS;
msrs[n++].index = MSR_MCG_CTL;
- for (i = 0; i < (env->mcg_cap & 0xff) * 4; i++)
+ for (i = 0; i < (env->mcg_cap & 0xff) * 4; i++) {
msrs[n++].index = MSR_MC0_CTL + i;
+ }
}
#endif
msr_data.info.nmsrs = n;
ret = kvm_vcpu_ioctl(env, KVM_GET_MSRS, &msr_data);
- if (ret < 0)
+ if (ret < 0) {
return ret;
+ }
for (i = 0; i < ret; i++) {
switch (msrs[i].index) {
@@ -1320,7 +1340,7 @@ static int kvm_get_debugregs(CPUState *env)
ret = kvm_vcpu_ioctl(env, KVM_GET_DEBUGREGS, &dbgregs);
if (ret < 0) {
- return ret;
+ return ret;
}
for (i = 0; i < 4; i++) {
env->dr[i] = dbgregs.db[i];
@@ -1339,44 +1359,44 @@ int kvm_arch_put_registers(CPUState *env, int level)
assert(cpu_is_stopped(env) || qemu_cpu_self(env));
ret = kvm_getput_regs(env, 1);
- if (ret < 0)
+ if (ret < 0) {
return ret;
-
+ }
ret = kvm_put_xsave(env);
- if (ret < 0)
+ if (ret < 0) {
return ret;
-
+ }
ret = kvm_put_xcrs(env);
- if (ret < 0)
+ if (ret < 0) {
return ret;
-
+ }
ret = kvm_put_sregs(env);
- if (ret < 0)
+ if (ret < 0) {
return ret;
-
+ }
ret = kvm_put_msrs(env, level);
- if (ret < 0)
+ if (ret < 0) {
return ret;
-
+ }
if (level >= KVM_PUT_RESET_STATE) {
ret = kvm_put_mp_state(env);
- if (ret < 0)
+ if (ret < 0) {
return ret;
+ }
}
-
ret = kvm_put_vcpu_events(env, level);
- if (ret < 0)
+ if (ret < 0) {
return ret;
-
+ }
/* must be last */
ret = kvm_guest_debug_workarounds(env);
- if (ret < 0)
+ if (ret < 0) {
return ret;
-
+ }
ret = kvm_put_debugregs(env);
- if (ret < 0)
+ if (ret < 0) {
return ret;
-
+ }
return 0;
}
@@ -1387,37 +1407,37 @@ int kvm_arch_get_registers(CPUState *env)
assert(cpu_is_stopped(env) || qemu_cpu_self(env));
ret = kvm_getput_regs(env, 0);
- if (ret < 0)
+ if (ret < 0) {
return ret;
-
+ }
ret = kvm_get_xsave(env);
- if (ret < 0)
+ if (ret < 0) {
return ret;
-
+ }
ret = kvm_get_xcrs(env);
- if (ret < 0)
+ if (ret < 0) {
return ret;
-
+ }
ret = kvm_get_sregs(env);
- if (ret < 0)
+ if (ret < 0) {
return ret;
-
+ }
ret = kvm_get_msrs(env);
- if (ret < 0)
+ if (ret < 0) {
return ret;
-
+ }
ret = kvm_get_mp_state(env);
- if (ret < 0)
+ if (ret < 0) {
return ret;
-
+ }
ret = kvm_get_vcpu_events(env);
- if (ret < 0)
+ if (ret < 0) {
return ret;
-
+ }
ret = kvm_get_debugregs(env);
- if (ret < 0)
+ if (ret < 0) {
return ret;
-
+ }
return 0;
}
@@ -1451,10 +1471,11 @@ int kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
* interrupt, request an interrupt window exit. This will
* cause a return to userspace as soon as the guest is ready to
* receive interrupts. */
- if ((env->interrupt_request & CPU_INTERRUPT_HARD))
+ if ((env->interrupt_request & CPU_INTERRUPT_HARD)) {
run->request_interrupt_window = 1;
- else
+ } else {
run->request_interrupt_window = 0;
+ }
DPRINTF("setting tpr\n");
run->cr8 = cpu_get_apic_tpr(env->apic_state);
@@ -1464,11 +1485,11 @@ int kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
int kvm_arch_post_run(CPUState *env, struct kvm_run *run)
{
- if (run->if_flag)
+ if (run->if_flag) {
env->eflags |= IF_MASK;
- else
+ } else {
env->eflags &= ~IF_MASK;
-
+ }
cpu_set_apic_tpr(env->apic_state, run->cr8);
cpu_set_apic_base(env->apic_state, run->apic_base);
@@ -1524,8 +1545,9 @@ int kvm_arch_insert_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
static const uint8_t int3 = 0xcc;
if (cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 1, 0) ||
- cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&int3, 1, 1))
+ cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&int3, 1, 1)) {
return -EINVAL;
+ }
return 0;
}
@@ -1534,8 +1556,9 @@ int kvm_arch_remove_sw_breakpoint(CPUState *env, struct kvm_sw_breakpoint *bp)
uint8_t int3;
if (cpu_memory_rw_debug(env, bp->pc, &int3, 1, 0) || int3 != 0xcc ||
- cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 1, 1))
+ cpu_memory_rw_debug(env, bp->pc, (uint8_t *)&bp->saved_insn, 1, 1)) {
return -EINVAL;
+ }
return 0;
}
@@ -1551,10 +1574,12 @@ static int find_hw_breakpoint(target_ulong addr, int len, int type)
{
int n;
- for (n = 0; n < nb_hw_breakpoint; n++)
+ for (n = 0; n < nb_hw_breakpoint; n++) {
if (hw_breakpoint[n].addr == addr && hw_breakpoint[n].type == type &&
- (hw_breakpoint[n].len == len || len == -1))
+ (hw_breakpoint[n].len == len || len == -1)) {
return n;
+ }
+ }
return -1;
}
@@ -1573,8 +1598,9 @@ int kvm_arch_insert_hw_breakpoint(target_ulong addr,
case 2:
case 4:
case 8:
- if (addr & (len - 1))
+ if (addr & (len - 1)) {
return -EINVAL;
+ }
break;
default:
return -EINVAL;
@@ -1584,12 +1610,12 @@ int kvm_arch_insert_hw_breakpoint(target_ulong addr,
return -ENOSYS;
}
- if (nb_hw_breakpoint == 4)
+ if (nb_hw_breakpoint == 4) {
return -ENOBUFS;
-
- if (find_hw_breakpoint(addr, len, type) >= 0)
+ }
+ if (find_hw_breakpoint(addr, len, type) >= 0) {
return -EEXIST;
-
+ }
hw_breakpoint[nb_hw_breakpoint].addr = addr;
hw_breakpoint[nb_hw_breakpoint].len = len;
hw_breakpoint[nb_hw_breakpoint].type = type;
@@ -1604,9 +1630,9 @@ int kvm_arch_remove_hw_breakpoint(target_ulong addr,
int n;
n = find_hw_breakpoint(addr, (type == GDB_BREAKPOINT_HW) ? 1 : len, type);
- if (n < 0)
+ if (n < 0) {
return -ENOENT;
-
+ }
nb_hw_breakpoint--;
hw_breakpoint[n] = hw_breakpoint[nb_hw_breakpoint];
@@ -1627,11 +1653,12 @@ int kvm_arch_debug(struct kvm_debug_exit_arch *arch_info)
if (arch_info->exception == 1) {
if (arch_info->dr6 & (1 << 14)) {
- if (cpu_single_env->singlestep_enabled)
+ if (cpu_single_env->singlestep_enabled) {
handle = 1;
+ }
} else {
- for (n = 0; n < 4; n++)
- if (arch_info->dr6 & (1 << n))
+ for (n = 0; n < 4; n++) {
+ if (arch_info->dr6 & (1 << n)) {
switch ((arch_info->dr7 >> (16 + n*4)) & 0x3) {
case 0x0:
handle = 1;
@@ -1649,10 +1676,12 @@ int kvm_arch_debug(struct kvm_debug_exit_arch *arch_info)
hw_watchpoint.flags = BP_MEM_ACCESS;
break;
}
+ }
+ }
}
- } else if (kvm_find_sw_breakpoint(cpu_single_env, arch_info->pc))
+ } else if (kvm_find_sw_breakpoint(cpu_single_env, arch_info->pc)) {
handle = 1;
-
+ }
if (!handle) {
cpu_synchronize_state(cpu_single_env);
assert(cpu_single_env->exception_injected == -1);
@@ -1676,9 +1705,9 @@ void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
};
int n;
- if (kvm_sw_breakpoints_active(env))
+ if (kvm_sw_breakpoints_active(env)) {
dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP;
-
+ }
if (nb_hw_breakpoint > 0) {
dbg->control |= KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_HW_BP;
dbg->arch.debugreg[7] = 0x0600;
@@ -1696,8 +1725,8 @@ void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
bool kvm_arch_stop_on_emulation_error(CPUState *env)
{
- return !(env->cr[0] & CR0_PE_MASK) ||
- ((env->segs[R_CS].selector & 3) != 3);
+ return !(env->cr[0] & CR0_PE_MASK) ||
+ ((env->segs[R_CS].selector & 3) != 3);
}
static void hardware_memory_error(void)
commit 95c077c91900c1420cd4f0be996ffeea6fb6cec8
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Mon Dec 27 15:58:23 2010 +0100
kvm: x86: Prevent sign extension of DR7 in guest debugging mode
This unbreaks guest debugging when the 4th hardware breakpoint used for
guest debugging is a watchpoint of 4 or 8 byte lenght. The 31st bit of
DR7 is set in that case and used to cause a sign extension to the high
word which was breaking the guest state (vm entry failure).
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Avi Kivity <avi at redhat.com>
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 7e5982b..85edacc 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1686,7 +1686,7 @@ void kvm_arch_update_guest_debug(CPUState *env, struct kvm_guest_debug *dbg)
dbg->arch.debugreg[n] = hw_breakpoint[n].addr;
dbg->arch.debugreg[7] |= (2 << (n * 2)) |
(type_code[hw_breakpoint[n].type] << (16 + n*4)) |
- (len_code[hw_breakpoint[n].len] << (18 + n*4));
+ ((uint32_t)len_code[hw_breakpoint[n].len] << (18 + n*4));
}
}
/* Legal xcr0 for loading */
commit 3980e3024b2d1677a9910de5e35d22d5d8392522
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Mon Dec 27 15:57:35 2010 +0100
kvm: x86: Remove obsolete SS.RPL/DPL aligment
This seems to date back to the days KVM didn't support real mode. The
check is no longer needed and, even worse, is corrupting the guest state
in case SS.RPL != DPL.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Avi Kivity <avi at redhat.com>
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index ee7bdf8..7e5982b 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -780,13 +780,6 @@ static int kvm_put_sregs(CPUState *env)
set_seg(&sregs.fs, &env->segs[R_FS]);
set_seg(&sregs.gs, &env->segs[R_GS]);
set_seg(&sregs.ss, &env->segs[R_SS]);
-
- if (env->cr[0] & CR0_PE_MASK) {
- /* force ss cpl to cs cpl */
- sregs.ss.selector = (sregs.ss.selector & ~3) |
- (sregs.cs.selector & 3);
- sregs.ss.dpl = sregs.ss.selector & 3;
- }
}
set_seg(&sregs.tr, &env->tr);
commit acaa75507b34f7b588924a09c76c6848d209e08c
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Mon Dec 27 15:56:44 2010 +0100
kvm: x86: Fix DPL write back of segment registers
The DPL is stored in the flags and not in the selector. In fact, the RPL
may differ from the DPL at some point in time, and so we were corrupting
the guest state so far.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Avi Kivity <avi at redhat.com>
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 9a4bf98..ee7bdf8 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -602,7 +602,7 @@ static void set_seg(struct kvm_segment *lhs, const SegmentCache *rhs)
lhs->limit = rhs->limit;
lhs->type = (flags >> DESC_TYPE_SHIFT) & 15;
lhs->present = (flags & DESC_P_MASK) != 0;
- lhs->dpl = rhs->selector & 3;
+ lhs->dpl = (flags >> DESC_DPL_SHIFT) & 3;
lhs->db = (flags >> DESC_B_SHIFT) & 1;
lhs->s = (flags & DESC_S_MASK) != 0;
lhs->l = (flags >> DESC_L_SHIFT) & 1;
commit 7cc2cc3e2608b182f1e0fc7ecae6e3b1fa4f46e0
Author: Jin Dongming <jin.dongming at np.css.fujitsu.com>
Date: Wed Dec 22 12:24:51 2010 +0900
kvm: introduce kvm_inject_x86_mce_on
Pass a table instead of multiple args.
Note:
kvm_inject_x86_mce(env, bank, status, mcg_status, addr, misc,
abort_on_error);
is equal to:
struct kvm_x86_mce mce = {
.bank = bank,
.status = status,
.mcg_status = mcg_status,
.addr = addr,
.misc = misc,
};
kvm_inject_x86_mce_on(env, &mce, abort_on_error);
Signed-off-by: Hidetoshi Seto <seto.hidetoshi at jp.fujitsu.com>
Signed-off-by: Jin Dongming <jin.dongming at np.css.fujitsu.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index ce01e18..9a4bf98 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -263,6 +263,23 @@ static void kvm_do_inject_x86_mce(void *_data)
}
}
+static void kvm_inject_x86_mce_on(CPUState *env, struct kvm_x86_mce *mce,
+ int flag)
+{
+ struct kvm_x86_mce_data data = {
+ .env = env,
+ .mce = mce,
+ .abort_on_error = (flag & ABORT_ON_ERROR),
+ };
+
+ if (!env->mcg_cap) {
+ fprintf(stderr, "MCE support is not enabled!\n");
+ return;
+ }
+
+ run_on_cpu(env, kvm_do_inject_x86_mce, &data);
+}
+
static void kvm_mce_broadcast_rest(CPUState *env);
#endif
@@ -278,21 +295,12 @@ void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
.addr = addr,
.misc = misc,
};
- struct kvm_x86_mce_data data = {
- .env = cenv,
- .mce = &mce,
- };
-
- if (!cenv->mcg_cap) {
- fprintf(stderr, "MCE support is not enabled!\n");
- return;
- }
if (flag & MCE_BROADCAST) {
kvm_mce_broadcast_rest(cenv);
}
- run_on_cpu(cenv, kvm_do_inject_x86_mce, &data);
+ kvm_inject_x86_mce_on(cenv, &mce, flag);
#else
if (flag & ABORT_ON_ERROR) {
abort();
@@ -1708,6 +1716,13 @@ static void hardware_memory_error(void)
#ifdef KVM_CAP_MCE
static void kvm_mce_broadcast_rest(CPUState *env)
{
+ struct kvm_x86_mce mce = {
+ .bank = 1,
+ .status = MCI_STATUS_VAL | MCI_STATUS_UC,
+ .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV,
+ .addr = 0,
+ .misc = 0,
+ };
CPUState *cenv;
/* Broadcast MCA signal for processor version 06H_EH and above */
@@ -1716,9 +1731,7 @@ static void kvm_mce_broadcast_rest(CPUState *env)
if (cenv == env) {
continue;
}
- kvm_inject_x86_mce(cenv, 1, MCI_STATUS_VAL | MCI_STATUS_UC,
- MCG_STATUS_MCIP | MCG_STATUS_RIPV, 0, 0,
- ABORT_ON_ERROR);
+ kvm_inject_x86_mce_on(cenv, &mce, ABORT_ON_ERROR);
}
}
}
@@ -1767,15 +1780,17 @@ static void kvm_mce_inj_srao_memscrub(CPUState *env, target_phys_addr_t paddr)
static void kvm_mce_inj_srao_memscrub2(CPUState *env, target_phys_addr_t paddr)
{
- uint64_t status;
-
- status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
- | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
- | 0xc0;
- kvm_inject_x86_mce(env, 9, status,
- MCG_STATUS_MCIP | MCG_STATUS_RIPV, paddr,
- (MCM_ADDR_PHYS << 6) | 0xc, ABORT_ON_ERROR);
+ struct kvm_x86_mce mce = {
+ .bank = 9,
+ .status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
+ | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
+ | 0xc0,
+ .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV,
+ .addr = paddr,
+ .misc = (MCM_ADDR_PHYS << 6) | 0xc,
+ };
+ kvm_inject_x86_mce_on(env, &mce, ABORT_ON_ERROR);
kvm_mce_broadcast_rest(env);
}
commit e387c33892be35ca70255739a2fe118f76c95ac3
Author: Jin Dongming <jin.dongming at np.css.fujitsu.com>
Date: Wed Dec 22 12:24:38 2010 +0900
kvm: kvm_mce_inj_* subroutines for templated error injections
Refactor codes for maintainability.
Signed-off-by: Hidetoshi Seto <seto.hidetoshi at jp.fujitsu.com>
Signed-off-by: Jin Dongming <jin.dongming at np.css.fujitsu.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 5a699fc..ce01e18 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1722,44 +1722,75 @@ static void kvm_mce_broadcast_rest(CPUState *env)
}
}
}
+
+static void kvm_mce_inj_srar_dataload(CPUState *env, target_phys_addr_t paddr)
+{
+ struct kvm_x86_mce mce = {
+ .bank = 9,
+ .status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
+ | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
+ | MCI_STATUS_AR | 0x134,
+ .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_EIPV,
+ .addr = paddr,
+ .misc = (MCM_ADDR_PHYS << 6) | 0xc,
+ };
+ int r;
+
+ r = kvm_set_mce(env, &mce);
+ if (r < 0) {
+ fprintf(stderr, "kvm_set_mce: %s\n", strerror(errno));
+ abort();
+ }
+ kvm_mce_broadcast_rest(env);
+}
+
+static void kvm_mce_inj_srao_memscrub(CPUState *env, target_phys_addr_t paddr)
+{
+ struct kvm_x86_mce mce = {
+ .bank = 9,
+ .status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
+ | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
+ | 0xc0,
+ .mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV,
+ .addr = paddr,
+ .misc = (MCM_ADDR_PHYS << 6) | 0xc,
+ };
+ int r;
+
+ r = kvm_set_mce(env, &mce);
+ if (r < 0) {
+ fprintf(stderr, "kvm_set_mce: %s\n", strerror(errno));
+ abort();
+ }
+ kvm_mce_broadcast_rest(env);
+}
+
+static void kvm_mce_inj_srao_memscrub2(CPUState *env, target_phys_addr_t paddr)
+{
+ uint64_t status;
+
+ status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
+ | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
+ | 0xc0;
+ kvm_inject_x86_mce(env, 9, status,
+ MCG_STATUS_MCIP | MCG_STATUS_RIPV, paddr,
+ (MCM_ADDR_PHYS << 6) | 0xc, ABORT_ON_ERROR);
+
+ kvm_mce_broadcast_rest(env);
+}
+
#endif
int kvm_on_sigbus_vcpu(CPUState *env, int code, void *addr)
{
#if defined(KVM_CAP_MCE)
- struct kvm_x86_mce mce = {
- .bank = 9,
- };
void *vaddr;
ram_addr_t ram_addr;
target_phys_addr_t paddr;
- int r;
if ((env->mcg_cap & MCG_SER_P) && addr
&& (code == BUS_MCEERR_AR
|| code == BUS_MCEERR_AO)) {
- if (code == BUS_MCEERR_AR) {
- /* Fake an Intel architectural Data Load SRAR UCR */
- mce.status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
- | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
- | MCI_STATUS_AR | 0x134;
- mce.misc = (MCM_ADDR_PHYS << 6) | 0xc;
- mce.mcg_status = MCG_STATUS_MCIP | MCG_STATUS_EIPV;
- } else {
- /*
- * If there is an MCE excpetion being processed, ignore
- * this SRAO MCE
- */
- if (kvm_mce_in_progress(env)) {
- return 0;
- }
- /* Fake an Intel architectural Memory scrubbing UCR */
- mce.status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
- | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
- | 0xc0;
- mce.misc = (MCM_ADDR_PHYS << 6) | 0xc;
- mce.mcg_status = MCG_STATUS_MCIP | MCG_STATUS_RIPV;
- }
vaddr = (void *)addr;
if (qemu_ram_addr_from_host(vaddr, &ram_addr) ||
!kvm_physical_memory_addr_from_ram(env->kvm_state, ram_addr, &paddr)) {
@@ -1772,13 +1803,20 @@ int kvm_on_sigbus_vcpu(CPUState *env, int code, void *addr)
hardware_memory_error();
}
}
- mce.addr = paddr;
- r = kvm_set_mce(env, &mce);
- if (r < 0) {
- fprintf(stderr, "kvm_set_mce: %s\n", strerror(errno));
- abort();
+
+ if (code == BUS_MCEERR_AR) {
+ /* Fake an Intel architectural Data Load SRAR UCR */
+ kvm_mce_inj_srar_dataload(env, paddr);
+ } else {
+ /*
+ * If there is an MCE excpetion being processed, ignore
+ * this SRAO MCE
+ */
+ if (!kvm_mce_in_progress(env)) {
+ /* Fake an Intel architectural Memory scrubbing UCR */
+ kvm_mce_inj_srao_memscrub(env, paddr);
+ }
}
- kvm_mce_broadcast_rest(env);
} else
#endif
{
@@ -1797,7 +1835,6 @@ int kvm_on_sigbus(int code, void *addr)
{
#if defined(KVM_CAP_MCE)
if ((first_cpu->mcg_cap & MCG_SER_P) && addr && code == BUS_MCEERR_AO) {
- uint64_t status;
void *vaddr;
ram_addr_t ram_addr;
target_phys_addr_t paddr;
@@ -1810,13 +1847,7 @@ int kvm_on_sigbus(int code, void *addr)
"QEMU itself instead of guest system!: %p\n", addr);
return 0;
}
- status = MCI_STATUS_VAL | MCI_STATUS_UC | MCI_STATUS_EN
- | MCI_STATUS_MISCV | MCI_STATUS_ADDRV | MCI_STATUS_S
- | 0xc0;
- kvm_inject_x86_mce(first_cpu, 9, status,
- MCG_STATUS_MCIP | MCG_STATUS_RIPV, paddr,
- (MCM_ADDR_PHYS << 6) | 0xc, ABORT_ON_ERROR);
- kvm_mce_broadcast_rest(first_cpu);
+ kvm_mce_inj_srao_memscrub2(first_cpu, paddr);
} else
#endif
{
commit 6643e2f001f207bdb85646a4c48d1e13244d87c3
Author: Jin Dongming <jin.dongming at np.css.fujitsu.com>
Date: Wed Dec 22 12:24:22 2010 +0900
kvm: introduce kvm_mce_in_progress
Share same error handing, and rename this function after
MCIP (Machine Check In Progress) flag.
Signed-off-by: Hidetoshi Seto <seto.hidetoshi at jp.fujitsu.com>
Signed-off-by: Jin Dongming <jin.dongming at np.css.fujitsu.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 2115a58..5a699fc 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -219,7 +219,7 @@ static int kvm_get_msr(CPUState *env, struct kvm_msr_entry *msrs, int n)
}
/* FIXME: kill this and kvm_get_msr, use env->mcg_status instead */
-static int kvm_mce_in_exception(CPUState *env)
+static int kvm_mce_in_progress(CPUState *env)
{
struct kvm_msr_entry msr_mcg_status = {
.index = MSR_MCG_STATUS,
@@ -228,7 +228,8 @@ static int kvm_mce_in_exception(CPUState *env)
r = kvm_get_msr(env, &msr_mcg_status, 1);
if (r == -1 || r == 0) {
- return -1;
+ fprintf(stderr, "Failed to get MCE status\n");
+ return 0;
}
return !!(msr_mcg_status.data & MCG_STATUS_MCIP);
}
@@ -248,10 +249,7 @@ static void kvm_do_inject_x86_mce(void *_data)
/* If there is an MCE exception being processed, ignore this SRAO MCE */
if ((data->env->mcg_cap & MCG_SER_P) &&
!(data->mce->status & MCI_STATUS_AR)) {
- r = kvm_mce_in_exception(data->env);
- if (r == -1) {
- fprintf(stderr, "Failed to get MCE status\n");
- } else if (r) {
+ if (kvm_mce_in_progress(data->env)) {
return;
}
}
@@ -1752,10 +1750,7 @@ int kvm_on_sigbus_vcpu(CPUState *env, int code, void *addr)
* If there is an MCE excpetion being processed, ignore
* this SRAO MCE
*/
- r = kvm_mce_in_exception(env);
- if (r == -1) {
- fprintf(stderr, "Failed to get MCE status\n");
- } else if (r) {
+ if (kvm_mce_in_progress(env)) {
return 0;
}
/* Fake an Intel architectural Memory scrubbing UCR */
commit 2bd3e04c3b3c76d573435a299a4d85bad0021a90
Author: Jin Dongming <jin.dongming at np.css.fujitsu.com>
Date: Fri Dec 10 17:21:14 2010 +0900
Add function for checking mca broadcast of CPU
Add function for checking whether current CPU support mca broadcast.
Signed-off-by: Jin Dongming <jin.dongming at np.css.fujitsu.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index f0c07cd..dddcd74 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -760,6 +760,7 @@ int cpu_x86_exec(CPUX86State *s);
void cpu_x86_close(CPUX86State *s);
void x86_cpu_list (FILE *f, fprintf_function cpu_fprintf, const char *optarg);
void x86_cpudef_setup(void);
+int cpu_x86_support_mca_broadcast(CPUState *env);
int cpu_get_pic_interrupt(CPUX86State *s);
/* MSDOS compatibility mode FPU exception support */
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 2cfb4a4..6dfa27d 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -110,6 +110,32 @@ void cpu_x86_close(CPUX86State *env)
qemu_free(env);
}
+static void cpu_x86_version(CPUState *env, int *family, int *model)
+{
+ int cpuver = env->cpuid_version;
+
+ if (family == NULL || model == NULL) {
+ return;
+ }
+
+ *family = (cpuver >> 8) & 0x0f;
+ *model = ((cpuver >> 12) & 0xf0) + ((cpuver >> 4) & 0x0f);
+}
+
+/* Broadcast MCA signal for processor version 06H_EH and above */
+int cpu_x86_support_mca_broadcast(CPUState *env)
+{
+ int family = 0;
+ int model = 0;
+
+ cpu_x86_version(env, &family, &model);
+ if ((family == 6 && model >= 14) || family > 6) {
+ return 1;
+ }
+
+ return 0;
+}
+
/***********************************************************/
/* x86 debug */
@@ -1080,6 +1106,13 @@ void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
return;
}
+ if (broadcast) {
+ if (!cpu_x86_support_mca_broadcast(cenv)) {
+ fprintf(stderr, "Current CPU does not support broadcast\n");
+ return;
+ }
+ }
+
if (kvm_enabled()) {
if (broadcast) {
flag |= MCE_BROADCAST;
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 8b868ad..2115a58 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1711,13 +1711,9 @@ static void hardware_memory_error(void)
static void kvm_mce_broadcast_rest(CPUState *env)
{
CPUState *cenv;
- int family, model, cpuver = env->cpuid_version;
-
- family = (cpuver >> 8) & 0xf;
- model = ((cpuver >> 12) & 0xf0) + ((cpuver >> 4) & 0xf);
/* Broadcast MCA signal for processor version 06H_EH and above */
- if ((family == 6 && model >= 14) || family > 6) {
+ if (cpu_x86_support_mca_broadcast(env)) {
for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
if (cenv == env) {
continue;
commit 31ce5e0c49821d92fb30cce2f3055ef33613b287
Author: Jin Dongming <jin.dongming at np.css.fujitsu.com>
Date: Fri Dec 10 17:21:02 2010 +0900
Add "broadcast" option for mce command
When the following test case is injected with mce command, maybe user could not
get the expected result.
DATA
command cpu bank status mcg_status addr misc
(qemu) mce 1 1 0xbd00000000000000 0x05 0x1234 0x8c
Expected Result
panic type: "Fatal Machine check"
That is because each mce command can only inject the given cpu and could not
inject mce interrupt to other cpus. So user will get the following result:
panic type: "Fatal machine check on current CPU"
"broadcast" option is used for injecting dummy data into other cpus. Injecting
mce with this option the expected result could be gotten.
Usage:
Broadcast[on]
command broadcast cpu bank status mcg_status addr misc
(qemu) mce -b 1 1 0xbd00000000000000 0x05 0x1234 0x8c
Broadcast[off]
command cpu bank status mcg_status addr misc
(qemu) mce 1 1 0xbd00000000000000 0x05 0x1234 0x8c
Signed-off-by: Jin Dongming <jin.dongming at np.css.fujitsu.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
diff --git a/cpu-all.h b/cpu-all.h
index 30ae17d..4ce4e83 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -964,6 +964,7 @@ int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
uint8_t *buf, int len, int is_write);
void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
- uint64_t mcg_status, uint64_t addr, uint64_t misc);
+ uint64_t mcg_status, uint64_t addr, uint64_t misc,
+ int broadcast);
#endif /* CPU_ALL_H */
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 1cea572..d65a41f 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1116,9 +1116,9 @@ ETEXI
{
.name = "mce",
- .args_type = "cpu_index:i,bank:i,status:l,mcg_status:l,addr:l,misc:l",
- .params = "cpu bank status mcgstatus addr misc",
- .help = "inject a MCE on the given CPU",
+ .args_type = "broadcast:-b,cpu_index:i,bank:i,status:l,mcg_status:l,addr:l,misc:l",
+ .params = "[-b] cpu bank status mcgstatus addr misc",
+ .help = "inject a MCE on the given CPU [and broadcast to other CPUs with -b option]",
.mhandler.cmd = do_inject_mce,
},
diff --git a/monitor.c b/monitor.c
index d291158..396d5cd 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2671,12 +2671,15 @@ static void do_inject_mce(Monitor *mon, const QDict *qdict)
uint64_t mcg_status = qdict_get_int(qdict, "mcg_status");
uint64_t addr = qdict_get_int(qdict, "addr");
uint64_t misc = qdict_get_int(qdict, "misc");
+ int broadcast = qdict_get_try_bool(qdict, "broadcast", 0);
- for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu)
+ for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
if (cenv->cpu_index == cpu_index && cenv->mcg_cap) {
- cpu_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc);
+ cpu_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc,
+ broadcast);
break;
}
+ }
}
#endif
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 2c94130..2cfb4a4 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1069,18 +1069,34 @@ static void qemu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
}
void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
- uint64_t mcg_status, uint64_t addr, uint64_t misc)
+ uint64_t mcg_status, uint64_t addr, uint64_t misc,
+ int broadcast)
{
unsigned bank_num = cenv->mcg_cap & 0xff;
+ CPUState *env;
+ int flag = 0;
if (bank >= bank_num || !(status & MCI_STATUS_VAL)) {
return;
}
if (kvm_enabled()) {
- kvm_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc, 0);
+ if (broadcast) {
+ flag |= MCE_BROADCAST;
+ }
+
+ kvm_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc, flag);
} else {
qemu_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc);
+ if (broadcast) {
+ for (env = first_cpu; env != NULL; env = env->next_cpu) {
+ if (cenv == env) {
+ continue;
+ }
+
+ qemu_inject_x86_mce(env, 1, 0xa000000000000000, 0, 0, 0);
+ }
+ }
}
}
#endif /* !CONFIG_USER_ONLY */
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 4004de7..8b868ad 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -264,11 +264,13 @@ static void kvm_do_inject_x86_mce(void *_data)
}
}
}
+
+static void kvm_mce_broadcast_rest(CPUState *env);
#endif
void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
uint64_t mcg_status, uint64_t addr, uint64_t misc,
- int abort_on_error)
+ int flag)
{
#ifdef KVM_CAP_MCE
struct kvm_x86_mce mce = {
@@ -288,10 +290,15 @@ void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
return;
}
+ if (flag & MCE_BROADCAST) {
+ kvm_mce_broadcast_rest(cenv);
+ }
+
run_on_cpu(cenv, kvm_do_inject_x86_mce, &data);
#else
- if (abort_on_error)
+ if (flag & ABORT_ON_ERROR) {
abort();
+ }
#endif
}
@@ -1716,7 +1723,8 @@ static void kvm_mce_broadcast_rest(CPUState *env)
continue;
}
kvm_inject_x86_mce(cenv, 1, MCI_STATUS_VAL | MCI_STATUS_UC,
- MCG_STATUS_MCIP | MCG_STATUS_RIPV, 0, 0, 1);
+ MCG_STATUS_MCIP | MCG_STATUS_RIPV, 0, 0,
+ ABORT_ON_ERROR);
}
}
}
@@ -1816,7 +1824,7 @@ int kvm_on_sigbus(int code, void *addr)
| 0xc0;
kvm_inject_x86_mce(first_cpu, 9, status,
MCG_STATUS_MCIP | MCG_STATUS_RIPV, paddr,
- (MCM_ADDR_PHYS << 6) | 0xc, 1);
+ (MCM_ADDR_PHYS << 6) | 0xc, ABORT_ON_ERROR);
kvm_mce_broadcast_rest(first_cpu);
} else
#endif
diff --git a/target-i386/kvm_x86.h b/target-i386/kvm_x86.h
index 04932cf..9d7b584 100644
--- a/target-i386/kvm_x86.h
+++ b/target-i386/kvm_x86.h
@@ -15,8 +15,11 @@
#ifndef __KVM_X86_H__
#define __KVM_X86_H__
+#define ABORT_ON_ERROR 0x01
+#define MCE_BROADCAST 0x02
+
void kvm_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
uint64_t mcg_status, uint64_t addr, uint64_t misc,
- int abort_on_error);
+ int flag);
#endif
commit b3cd24e04a2aea342429c09ed93468dd3206fede
Author: Jin Dongming <jin.dongming at np.css.fujitsu.com>
Date: Fri Dec 10 17:20:44 2010 +0900
Clean up cpu_inject_x86_mce()
Clean up cpu_inject_x86_mce() for later patch.
Signed-off-by: Jin Dongming <jin.dongming at np.css.fujitsu.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 25a3e36..2c94130 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1021,21 +1021,12 @@ static void breakpoint_handler(CPUState *env)
/* This should come from sysemu.h - if we could include it here... */
void qemu_system_reset_request(void);
-void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
+static void qemu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
uint64_t mcg_status, uint64_t addr, uint64_t misc)
{
uint64_t mcg_cap = cenv->mcg_cap;
- unsigned bank_num = mcg_cap & 0xff;
uint64_t *banks = cenv->mce_banks;
- if (bank >= bank_num || !(status & MCI_STATUS_VAL))
- return;
-
- if (kvm_enabled()) {
- kvm_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc, 0);
- return;
- }
-
/*
* if MSR_MCG_CTL is not all 1s, the uncorrected error
* reporting is disabled
@@ -1076,6 +1067,22 @@ void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
} else
banks[1] |= MCI_STATUS_OVER;
}
+
+void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
+ uint64_t mcg_status, uint64_t addr, uint64_t misc)
+{
+ unsigned bank_num = cenv->mcg_cap & 0xff;
+
+ if (bank >= bank_num || !(status & MCI_STATUS_VAL)) {
+ return;
+ }
+
+ if (kvm_enabled()) {
+ kvm_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc, 0);
+ } else {
+ qemu_inject_x86_mce(cenv, bank, status, mcg_status, addr, misc);
+ }
+}
#endif /* !CONFIG_USER_ONLY */
static void mce_init(CPUX86State *cenv)
commit 14a095184c6068c78e67f17c200cf00b4170f704
Author: Lai Jiangshan <laijs at cn.fujitsu.com>
Date: Fri Dec 10 15:52:36 2010 +0800
kvm: convert kvm_ioctl(KVM_CHECK_EXTENSION) to kvm_check_extension()
simple cleanup and use existing helper: kvm_check_extension().
Signed-off-by: Lai Jiangshan <laijs at cn.fujitsu.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
diff --git a/kvm-all.c b/kvm-all.c
index 255b6fa..935c436 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -717,7 +717,7 @@ int kvm_init(int smp_cpus)
s->broken_set_mem_region = 1;
#ifdef KVM_CAP_JOIN_MEMORY_REGIONS_WORKS
- ret = kvm_ioctl(s, KVM_CHECK_EXTENSION, KVM_CAP_JOIN_MEMORY_REGIONS_WORKS);
+ ret = kvm_check_extension(s, KVM_CAP_JOIN_MEMORY_REGIONS_WORKS);
if (ret > 0) {
s->broken_set_mem_region = 0;
}
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 755f8c9..4004de7 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -187,7 +187,7 @@ static int kvm_get_mce_cap_supported(KVMState *s, uint64_t *mce_cap,
{
int r;
- r = kvm_ioctl(s, KVM_CHECK_EXTENSION, KVM_CAP_MCE);
+ r = kvm_check_extension(s, KVM_CAP_MCE);
if (r > 0) {
*max_banks = r;
return kvm_ioctl(s, KVM_X86_GET_MCE_CAP_SUPPORTED, mce_cap);
@@ -540,7 +540,7 @@ int kvm_arch_init(KVMState *s, int smp_cpus)
* versions of KVM just assumed that it would be at the end of physical
* memory but that doesn't work with more than 4GB of memory. We simply
* refuse to work with those older versions of KVM. */
- ret = kvm_ioctl(s, KVM_CHECK_EXTENSION, KVM_CAP_SET_TSS_ADDR);
+ ret = kvm_check_extension(s, KVM_CAP_SET_TSS_ADDR);
if (ret <= 0) {
fprintf(stderr, "kvm does not support KVM_CAP_SET_TSS_ADDR\n");
return ret;
commit 276ce81563aeadea5493fbc4fbc84647d5bfbdeb
Author: Lai Jiangshan <laijs at cn.fujitsu.com>
Date: Fri Dec 10 15:42:53 2010 +0800
kvm: Enable user space NMI injection for kvm guest
Make use of the new KVM_NMI IOCTL to send NMIs into the KVM guest if the
user space raised them. (example: qemu monitor's "nmi" command)
Signed-off-by: Lai Jiangshan <laijs at cn.fujitsu.com>
Acked-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
diff --git a/configure b/configure
index 210670c..9a02d1f 100755
--- a/configure
+++ b/configure
@@ -1671,6 +1671,9 @@ if test "$kvm" != "no" ; then
#if !defined(KVM_CAP_DESTROY_MEMORY_REGION_WORKS)
#error Missing KVM capability KVM_CAP_DESTROY_MEMORY_REGION_WORKS
#endif
+#if !defined(KVM_CAP_USER_NMI)
+#error Missing KVM capability KVM_CAP_USER_NMI
+#endif
int main(void) { return 0; }
EOF
if test "$kerneldir" != "" ; then
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 7dfc357..755f8c9 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1417,6 +1417,13 @@ int kvm_arch_get_registers(CPUState *env)
int kvm_arch_pre_run(CPUState *env, struct kvm_run *run)
{
+ /* Inject NMI */
+ if (env->interrupt_request & CPU_INTERRUPT_NMI) {
+ env->interrupt_request &= ~CPU_INTERRUPT_NMI;
+ DPRINTF("injected NMI\n");
+ kvm_vcpu_ioctl(env, KVM_NMI);
+ }
+
/* Try to inject an interrupt if the guest can accept it */
if (run->ready_for_interrupt_injection &&
(env->interrupt_request & CPU_INTERRUPT_HARD) &&
commit 37f95bf3d063fcfcb3b05f82203629dc50f18615
Author: Amit Shah <amit.shah at redhat.com>
Date: Wed Jan 19 16:07:10 2011 +0530
virtio-serial: save/restore new fields in port struct
The new fields that got added as part of not copying over the guest
buffer to the host need to be saved/restored across migration. Do that
and bump up the version number.
Signed-off-by: Amit Shah <amit.shah at redhat.com>
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 32938b5..2ca97a9 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -527,9 +527,24 @@ static void virtio_serial_save(QEMUFile *f, void *opaque)
* Items in struct VirtIOSerialPort.
*/
QTAILQ_FOREACH(port, &s->ports, next) {
+ uint32_t elem_popped;
+
qemu_put_be32s(f, &port->id);
qemu_put_byte(f, port->guest_connected);
qemu_put_byte(f, port->host_connected);
+
+ elem_popped = 0;
+ if (port->elem.out_num) {
+ elem_popped = 1;
+ }
+ qemu_put_be32s(f, &elem_popped);
+ if (elem_popped) {
+ qemu_put_be32s(f, &port->iov_idx);
+ qemu_put_be64s(f, &port->iov_offset);
+
+ qemu_put_buffer(f, (unsigned char *)&port->elem,
+ sizeof(port->elem));
+ }
}
}
@@ -540,7 +555,7 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
uint32_t max_nr_ports, nr_active_ports, ports_map;
unsigned int i;
- if (version_id > 2) {
+ if (version_id > 3) {
return -EINVAL;
}
@@ -593,6 +608,29 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN,
port->host_connected);
}
+
+ if (version_id > 2) {
+ uint32_t elem_popped;
+
+ qemu_get_be32s(f, &elem_popped);
+ if (elem_popped) {
+ qemu_get_be32s(f, &port->iov_idx);
+ qemu_get_be64s(f, &port->iov_offset);
+
+ qemu_get_buffer(f, (unsigned char *)&port->elem,
+ sizeof(port->elem));
+ virtqueue_map_sg(port->elem.in_sg, port->elem.in_addr,
+ port->elem.in_num, 1);
+ virtqueue_map_sg(port->elem.out_sg, port->elem.out_addr,
+ port->elem.out_num, 1);
+
+ /*
+ * Port was throttled on source machine. Let's
+ * unthrottle it here so data starts flowing again.
+ */
+ virtio_serial_throttle_port(port, false);
+ }
+ }
}
return 0;
}
@@ -841,7 +879,7 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports)
* Register for the savevm section with the virtio-console name
* to preserve backward compat
*/
- register_savevm(dev, "virtio-console", -1, 2, virtio_serial_save,
+ register_savevm(dev, "virtio-console", -1, 3, virtio_serial_save,
virtio_serial_load, vser);
return vdev;
commit f1925dff7e6c4799f5951cf167a437c0737a266c
Author: Amit Shah <amit.shah at redhat.com>
Date: Fri Dec 10 16:51:14 2010 +0530
virtio-serial: Add support for flow control
This commit lets apps signal an incomplete write. When that happens,
stop sending out any more data to the app and wait for it to unthrottle
the port.
Signed-off-by: Amit Shah <amit.shah at redhat.com>
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 6726f72..32938b5 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -126,24 +126,49 @@ static void discard_vq_data(VirtQueue *vq, VirtIODevice *vdev)
static void do_flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq,
VirtIODevice *vdev)
{
- VirtQueueElement elem;
-
assert(port);
assert(virtio_queue_ready(vq));
- while (!port->throttled && virtqueue_pop(vq, &elem)) {
+ while (!port->throttled) {
unsigned int i;
- for (i = 0; i < elem.out_num; i++) {
- size_t buf_size;
-
- buf_size = elem.out_sg[i].iov_len;
+ /* Pop an elem only if we haven't left off a previous one mid-way */
+ if (!port->elem.out_num) {
+ if (!virtqueue_pop(vq, &port->elem)) {
+ break;
+ }
+ port->iov_idx = 0;
+ port->iov_offset = 0;
+ }
- port->info->have_data(port,
- elem.out_sg[i].iov_base,
- buf_size);
+ for (i = port->iov_idx; i < port->elem.out_num; i++) {
+ size_t buf_size;
+ ssize_t ret;
+
+ buf_size = port->elem.out_sg[i].iov_len - port->iov_offset;
+ ret = port->info->have_data(port,
+ port->elem.out_sg[i].iov_base
+ + port->iov_offset,
+ buf_size);
+ if (ret < 0 && ret != -EAGAIN) {
+ /* We don't handle any other type of errors here */
+ abort();
+ }
+ if (ret == -EAGAIN || (ret >= 0 && ret < buf_size)) {
+ virtio_serial_throttle_port(port, true);
+ port->iov_idx = i;
+ if (ret > 0) {
+ port->iov_offset += ret;
+ }
+ break;
+ }
+ port->iov_offset = 0;
}
- virtqueue_push(vq, &elem, 0);
+ if (port->throttled) {
+ break;
+ }
+ virtqueue_push(vq, &port->elem, 0);
+ port->elem.out_num = 0;
}
virtio_notify(vdev, vq);
}
@@ -709,6 +734,8 @@ static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
port->guest_connected = true;
}
+ port->elem.out_num = 0;
+
QTAILQ_INSERT_TAIL(&port->vser->ports, port, next);
port->ivq = port->vser->ivqs[port->id];
port->ovq = port->vser->ovqs[port->id];
diff --git a/hw/virtio-serial.h b/hw/virtio-serial.h
index 9cc0fb3..a308196 100644
--- a/hw/virtio-serial.h
+++ b/hw/virtio-serial.h
@@ -102,6 +102,23 @@ struct VirtIOSerialPort {
*/
uint32_t id;
+ /*
+ * This is the elem that we pop from the virtqueue. A slow
+ * backend that consumes guest data (e.g. the file backend for
+ * qemu chardevs) can cause the guest to block till all the output
+ * is flushed. This isn't desired, so we keep a note of the last
+ * element popped and continue consuming it once the backend
+ * becomes writable again.
+ */
+ VirtQueueElement elem;
+
+ /*
+ * The index and the offset into the iov buffer that was popped in
+ * elem above.
+ */
+ uint32_t iov_idx;
+ uint64_t iov_offset;
+
/* Identify if this is a port that binds with hvc in the guest */
uint8_t is_console;
commit e300ac275bbf19b31cf5968b8de8abe52c26e163
Author: Amit Shah <amit.shah at redhat.com>
Date: Mon Dec 13 17:50:07 2010 +0530
virtio-serial: Let virtio-serial-bus know if all data was consumed
The have_data() API to hand off guest data to apps using virtio-serial
so far assumed all the data was consumed. Relax this assumption.
Future commits will allow for incomplete writes.
Signed-off-by: Amit Shah <amit.shah at redhat.com>
diff --git a/hw/virtio-console.c b/hw/virtio-console.c
index d0b9354..62624ec 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -20,11 +20,11 @@ typedef struct VirtConsole {
/* Callback function that's called when the guest sends us data */
-static void flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
+static ssize_t flush_buf(VirtIOSerialPort *port, const uint8_t *buf, size_t len)
{
VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
- qemu_chr_write(vcon->chr, buf, len);
+ return qemu_chr_write(vcon->chr, buf, len);
}
/* Readiness of the guest to accept data on a port */
diff --git a/hw/virtio-serial.h b/hw/virtio-serial.h
index ff08c40..9cc0fb3 100644
--- a/hw/virtio-serial.h
+++ b/hw/virtio-serial.h
@@ -137,10 +137,11 @@ struct VirtIOSerialPortInfo {
/*
* Guest wrote some data to the port. This data is handed over to
- * the app via this callback. The app is supposed to consume all
- * the data that is presented to it.
+ * the app via this callback. The app can return a size less than
+ * 'len'. In this case, throttling will be enabled for this port.
*/
- void (*have_data)(VirtIOSerialPort *port, const uint8_t *buf, size_t len);
+ ssize_t (*have_data)(VirtIOSerialPort *port, const uint8_t *buf,
+ size_t len);
};
/* Interface to the virtio-serial bus */
commit 471344db88cc3e7adf7664aa34d54ce0cacc3419
Author: Amit Shah <amit.shah at redhat.com>
Date: Fri Dec 10 17:29:49 2010 +0530
virtio-serial: Don't copy over guest buffer to host
When the guest writes something to a host, we copied over the entire
buffer first into the host and then processed it. Do away with that, it
could result in a malicious guest causing a DoS on the host.
Reported-by: Paul Brook <paul at codesourcery.com>
Signed-off-by: Amit Shah <amit.shah at redhat.com>
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index e8c2a16..6726f72 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -132,16 +132,17 @@ static void do_flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq,
assert(virtio_queue_ready(vq));
while (!port->throttled && virtqueue_pop(vq, &elem)) {
- uint8_t *buf;
- size_t ret, buf_size;
+ unsigned int i;
- buf_size = iov_size(elem.out_sg, elem.out_num);
- buf = qemu_malloc(buf_size);
- ret = iov_to_buf(elem.out_sg, elem.out_num, buf, 0, buf_size);
+ for (i = 0; i < elem.out_num; i++) {
+ size_t buf_size;
- port->info->have_data(port, buf, ret);
- qemu_free(buf);
+ buf_size = elem.out_sg[i].iov_len;
+ port->info->have_data(port,
+ elem.out_sg[i].iov_base,
+ buf_size);
+ }
virtqueue_push(vq, &elem, 0);
}
virtio_notify(vdev, vq);
commit 6bff86560d42a9c391cf1e502ebd764c293c4d02
Author: Amit Shah <amit.shah at redhat.com>
Date: Fri Jan 7 14:33:36 2011 +0530
virtio-serial: move out discard logic in a separate function
Instead of combining flush logic into the discard case and not discard
case, have one function doing discard case. This will help later when
adding flow control logic to the do_flush_queued_data() function.
Signed-off-by: Amit Shah <amit.shah at redhat.com>
diff --git a/hw/virtio-serial-bus.c b/hw/virtio-serial-bus.c
index 74ba5ec..e8c2a16 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -113,39 +113,48 @@ static size_t write_to_port(VirtIOSerialPort *port,
return offset;
}
+static void discard_vq_data(VirtQueue *vq, VirtIODevice *vdev)
+{
+ VirtQueueElement elem;
+
+ while (virtqueue_pop(vq, &elem)) {
+ virtqueue_push(vq, &elem, 0);
+ }
+ virtio_notify(vdev, vq);
+}
+
static void do_flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq,
- VirtIODevice *vdev, bool discard)
+ VirtIODevice *vdev)
{
VirtQueueElement elem;
- assert(port || discard);
+ assert(port);
assert(virtio_queue_ready(vq));
- while ((discard || !port->throttled) && virtqueue_pop(vq, &elem)) {
+ while (!port->throttled && virtqueue_pop(vq, &elem)) {
uint8_t *buf;
size_t ret, buf_size;
- if (!discard) {
- buf_size = iov_size(elem.out_sg, elem.out_num);
- buf = qemu_malloc(buf_size);
- ret = iov_to_buf(elem.out_sg, elem.out_num, buf, 0, buf_size);
+ buf_size = iov_size(elem.out_sg, elem.out_num);
+ buf = qemu_malloc(buf_size);
+ ret = iov_to_buf(elem.out_sg, elem.out_num, buf, 0, buf_size);
+
+ port->info->have_data(port, buf, ret);
+ qemu_free(buf);
- port->info->have_data(port, buf, ret);
- qemu_free(buf);
- }
virtqueue_push(vq, &elem, 0);
}
virtio_notify(vdev, vq);
}
-static void flush_queued_data(VirtIOSerialPort *port, bool discard)
+static void flush_queued_data(VirtIOSerialPort *port)
{
assert(port);
if (!virtio_queue_ready(port->ovq)) {
return;
}
- do_flush_queued_data(port, port->ovq, &port->vser->vdev, discard);
+ do_flush_queued_data(port, port->ovq, &port->vser->vdev);
}
static size_t send_control_msg(VirtIOSerialPort *port, void *buf, size_t len)
@@ -204,7 +213,7 @@ int virtio_serial_close(VirtIOSerialPort *port)
* consume, reset the throttling flag and discard the data.
*/
port->throttled = false;
- flush_queued_data(port, true);
+ discard_vq_data(port->ovq, &port->vser->vdev);
send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN, 0);
@@ -258,7 +267,7 @@ void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle)
return;
}
- flush_queued_data(port, false);
+ flush_queued_data(port);
}
/* Guest wants to notify us of some event */
@@ -414,11 +423,15 @@ static void handle_output(VirtIODevice *vdev, VirtQueue *vq)
discard = true;
}
- if (!discard && port->throttled) {
+ if (discard) {
+ discard_vq_data(vq, vdev);
+ return;
+ }
+ if (port->throttled) {
return;
}
- do_flush_queued_data(port, vq, vdev, discard);
+ do_flush_queued_data(port, vq, vdev);
}
static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
@@ -634,7 +647,7 @@ static void remove_port(VirtIOSerial *vser, uint32_t port_id)
port = find_port_by_id(vser, port_id);
/* Flush out any unconsumed buffers first */
- flush_queued_data(port, true);
+ discard_vq_data(port->ovq, &port->vser->vdev);
send_control_event(port, VIRTIO_CONSOLE_PORT_REMOVE, 1);
}
commit 28eaf465316491884952f855f7bfc9dab597e6fb
Author: Amit Shah <amit.shah at redhat.com>
Date: Fri Dec 10 17:10:43 2010 +0530
virtio-console: Remove unnecessary braces
Remove unnecessary braces around a case statement.
Signed-off-by: Amit Shah <amit.shah at redhat.com>
diff --git a/hw/virtio-console.c b/hw/virtio-console.c
index d7fe68b..d0b9354 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -48,10 +48,9 @@ static void chr_event(void *opaque, int event)
VirtConsole *vcon = opaque;
switch (event) {
- case CHR_EVENT_OPENED: {
+ case CHR_EVENT_OPENED:
virtio_serial_open(&vcon->port);
break;
- }
case CHR_EVENT_CLOSED:
virtio_serial_close(&vcon->port);
break;
commit cbe77b616cb73d0a0aedbf9c80cb3dcb7d324535
Author: Amit Shah <amit.shah at redhat.com>
Date: Mon Apr 5 14:20:29 2010 +0530
virtio-console: Factor out common init between console and generic ports
The initialisation for generic ports and console ports is similar.
Factor out the parts that are the same in a different function that can
be called from each of the initfns.
Signed-off-by: Amit Shah <amit.shah at redhat.com>
diff --git a/hw/virtio-console.c b/hw/virtio-console.c
index caea11f..d7fe68b 100644
--- a/hw/virtio-console.c
+++ b/hw/virtio-console.c
@@ -58,24 +58,28 @@ static void chr_event(void *opaque, int event)
}
}
-/* Virtio Console Ports */
-static int virtconsole_initfn(VirtIOSerialDevice *dev)
+static int generic_port_init(VirtConsole *vcon, VirtIOSerialDevice *dev)
{
- VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
- VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
-
- port->info = dev->info;
-
- port->is_console = true;
+ vcon->port.info = dev->info;
if (vcon->chr) {
qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
vcon);
- port->info->have_data = flush_buf;
+ vcon->port.info->have_data = flush_buf;
}
return 0;
}
+/* Virtio Console Ports */
+static int virtconsole_initfn(VirtIOSerialDevice *dev)
+{
+ VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
+ VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
+
+ port->is_console = true;
+ return generic_port_init(vcon, dev);
+}
+
static int virtconsole_exitfn(VirtIOSerialDevice *dev)
{
VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
@@ -115,14 +119,7 @@ static int virtserialport_initfn(VirtIOSerialDevice *dev)
VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, &dev->qdev);
VirtConsole *vcon = DO_UPCAST(VirtConsole, port, port);
- port->info = dev->info;
-
- if (vcon->chr) {
- qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read, chr_event,
- vcon);
- port->info->have_data = flush_buf;
- }
- return 0;
+ return generic_port_init(vcon, dev);
}
static VirtIOSerialPortInfo virtserialport_info = {
More information about the Spice-commits
mailing list