[Spice-commits] 336 commits - .gitignore Makefile Makefile.hw Makefile.objs Makefile.target QMP/README QMP/qmp-spec.txt QMP/vm-info aio.c arch_init.c audio/audio_template.h block.c block.h block/blkdebug.c block/curl.c block/qcow2-cluster.c block/qcow2-refcount.c block/qcow2.c block/qcow2.h block/raw-posix.c block/vvfat.c blockdev.c blockdev.h bsd-user/main.c bswap.h check-qdict.c check-qfloat.c check-qint.c check-qjson.c check-qlist.c check-qstring.c configure console.c console.h cpu-all.h cpu-exec.c cpus.c create_config cursor.c cursor_hidden.xpm cursor_left_ptr.xpm darwin-user/commpage.c darwin-user/syscall.c default-configs/i386-softmmu.mak default-configs/mips-softmmu.mak default-configs/mips64-softmmu.mak default-configs/mips64el-softmmu.mak default-configs/mipsel-softmmu.mak default-configs/ppc-softmmu.mak default-configs/ppc64-softmmu.mak default-configs/ppcemb-softmmu.mak default-configs/sparc64-softmmu.mak default-configs/x86_64-softmmu.mak dyngen-exec.h elf.h exec-all.h e xec.c hw/9p.h hw/acpi_piix4.c hw/apb_pci.c hw/apic.c hw/arm_boot.c hw/arm_timer.c hw/axis_dev88.c hw/cirrus_vga.c hw/cris-boot.c hw/cris-boot.h hw/device-hotplug.c hw/dma.c hw/e1000.c hw/eepro100.c hw/elf_ops.h hw/esp.c hw/etraxfs.c hw/etraxfs_ser.c hw/fdc.c hw/fdc.h hw/gt64xxx.c hw/gumstix.c hw/hpet.c hw/hpet_emul.h hw/hw.h hw/i8259.c hw/ide hw/ioapic.c hw/isa.h hw/lan9118.c hw/lsi53c895a.c hw/mainstone.c hw/mc146818rtc.c hw/mc146818rtc.h hw/mips_jazz.c hw/mips_malta.c hw/mips_mipssim.c hw/mips_r4k.c hw/msix.c hw/multiboot.c hw/musicpal.c hw/nand.c hw/nseries.c hw/omap2.c hw/omap_sx1.c hw/onenand.c hw/palm.c hw/parallel.c hw/pc.c hw/pc.h hw/pc_piix.c hw/pci-hotplug.c hw/pci.c hw/pci.h hw/pckbd.c hw/pcmcia.h hw/petalogix_s3adsp1800_mmu.c hw/pflash_cfi01.c hw/piix_pci.c hw/pl181.c hw/ppc_prep.c hw/qdev-properties.c hw/qdev.c hw/qdev.h hw/scsi-bus.c hw/scsi-disk.c hw/scsi-generic.c hw/serial.c hw/sparc32_dma.c hw/spitz.c hw/ssi-sd.c hw/sun4m.c hw/sun4u.c hw/tosa.c hw/usb-hid.c hw/usb-msd.c hw/usb-ohci.c hw/vga-isa-mm.c hw/vga.c hw/vhost_net.c hw/virtio-blk.c hw/virtio-net.c hw/virtio-net.h hw/virtio-pci.c hw/virtio-serial-bus.c hw/virtio-serial.h hw/vmmouse.c hw/vmware_vga.c hw/xenfb.c hxtool ia64-dis.c input.c json-lexer.c json-parser.c json-streamer.c kvm.h linux-user/elfload.c linux-user/flatload.c linux-user/main.c linux-user/mmap.c linux-user/syscall.c linux-user/syscall_defs.h migration-exec.c migration-tcp.c migration.c migration.h monitor.c nbd.c nbd.h net.c net.h os-posix.c os-win32.c pc-bios/optionrom posix-aio-compat.c qbool.c qdict.c qdict.h qemu-char.c qemu-common.h qemu-config.c qemu-doc.texi qemu-img-cmds.hx qemu-img.c qemu-io.c qemu-malloc.c qemu-monitor.hx qemu-objects.h qemu-option.c qemu-option.h qemu-options.h qemu-options.hx qemu-os-posix.h qemu-os-win32.h qemu-thread.c qerror.c qerror.h qfloat.c qint.c qint.h qjson.c qlist.c qlist.h qobject.h qstring.c qstring.h rules.mak s390-dis.c savevm.c sdl.c softmmu_header.h sysemu.h t arget-arm/cpu.h target-arm/helper.c target-arm/translate.c target-cris/cpu.h target-cris/mmu.c target-cris/translate.c target-i386/cpuid.c target-i386/translate.c target-microblaze/cpu.h target-mips/cpu.h target-mips/helper.c target-mips/helper.h target-mips/mips-defs.h target-mips/op_helper.c target-mips/translate.c target-ppc/helper.c target-ppc/op_helper.c target-ppc/translate.c target-sparc/cpu.h target-sparc/helper.c target-sparc/op_helper.c target-sparc/translate.c tcg/arm tcg/hppa tcg/i386 tcg/ia64 tcg/mips tcg/ppc tcg/ppc64 tcg/s390 tcg/sparc tcg/tcg-op.h tcg/tcg-opc.h tcg/tcg.c tcg/tcg.h tcg/x86_64 translate-all.c vl.c vnc-encoding-hextile.c vnc-encoding-tight.c vnc-encoding-tight.h vnc-encoding-zlib.c vnc.c vnc.h vnchextile.h
Gerd Hoffmann
kraxel at kemper.freedesktop.org
Tue Jun 15 05:04:40 PDT 2010
.gitignore | 1
Makefile | 60
Makefile.hw | 2
Makefile.objs | 16
Makefile.target | 19
QMP/README | 5
QMP/qmp-spec.txt | 55
QMP/vm-info | 2
aio.c | 4
arch_init.c | 35
audio/audio_template.h | 2
block.c | 219 +-
block.h | 5
block/blkdebug.c | 2
block/curl.c | 14
block/qcow2-cluster.c | 94 -
block/qcow2-refcount.c | 42
block/qcow2.c | 24
block/qcow2.h | 4
block/raw-posix.c | 20
block/vvfat.c | 10
blockdev.c | 600 ++++++
blockdev.h | 71
bsd-user/main.c | 11
bswap.h | 2
check-qdict.c | 3
check-qfloat.c | 5
check-qint.c | 3
check-qjson.c | 113 +
check-qlist.c | 4
check-qstring.c | 3
configure | 168 +
console.c | 18
console.h | 27
cpu-all.h | 29
cpu-exec.c | 42
cpus.c | 38
create_config | 12
cursor.c | 210 ++
cursor_hidden.xpm | 37
cursor_left_ptr.xpm | 39
darwin-user/commpage.c | 2
darwin-user/syscall.c | 2
default-configs/i386-softmmu.mak | 2
default-configs/mips-softmmu.mak | 2
default-configs/mips64-softmmu.mak | 2
default-configs/mips64el-softmmu.mak | 2
default-configs/mipsel-softmmu.mak | 2
default-configs/ppc-softmmu.mak | 2
default-configs/ppc64-softmmu.mak | 2
default-configs/ppcemb-softmmu.mak | 2
default-configs/sparc64-softmmu.mak | 1
default-configs/x86_64-softmmu.mak | 2
dyngen-exec.h | 1
elf.h | 3
exec-all.h | 1
exec.c | 92 -
hw/9p.h | 2
hw/acpi_piix4.c | 30
hw/apb_pci.c | 50
hw/apic.c | 43
hw/arm_boot.c | 1
hw/arm_timer.c | 4
hw/axis_dev88.c | 54
hw/cirrus_vga.c | 1
hw/cris-boot.c | 97 +
hw/cris-boot.h | 11
hw/device-hotplug.c | 4
hw/dma.c | 17
hw/e1000.c | 4
hw/eepro100.c | 1
hw/elf_ops.h | 5
hw/esp.c | 19
hw/etraxfs.c | 55
hw/etraxfs_ser.c | 73
hw/fdc.c | 1
hw/fdc.h | 2
hw/gt64xxx.c | 2
hw/gumstix.c | 4
hw/hpet.c | 599 ++++--
hw/hpet_emul.h | 57
hw/hw.h | 11
hw/i8259.c | 23
hw/ide/cmd646.c | 4
hw/ide/core.c | 108 -
hw/ide/internal.h | 13
hw/ide/isa.c | 2
hw/ide/macio.c | 2
hw/ide/microdrive.c | 3
hw/ide/mmio.c | 2
hw/ide/piix.c | 4
hw/ide/qdev.c | 21
hw/ioapic.c | 16
hw/isa.h | 2
hw/lan9118.c | 1
hw/lsi53c895a.c | 4
hw/mainstone.c | 3
hw/mc146818rtc.c | 71
hw/mc146818rtc.h | 4
hw/mips_jazz.c | 15
hw/mips_malta.c | 15
hw/mips_mipssim.c | 5
hw/mips_r4k.c | 2
hw/msix.c | 17
hw/multiboot.c | 9
hw/musicpal.c | 2
hw/nand.c | 3
hw/nseries.c | 7
hw/omap2.c | 2
hw/omap_sx1.c | 5
hw/onenand.c | 3
hw/palm.c | 4
hw/parallel.c | 1
hw/pc.c | 81
hw/pc.h | 7
hw/pc_piix.c | 1
hw/pci-hotplug.c | 58
hw/pci.c | 103 -
hw/pci.h | 16
hw/pckbd.c | 112 -
hw/pcmcia.h | 2
hw/petalogix_s3adsp1800_mmu.c | 4
hw/pflash_cfi01.c | 20
hw/piix_pci.c | 2
hw/pl181.c | 1
hw/ppc_prep.c | 17
hw/qdev-properties.c | 12
hw/qdev.c | 20
hw/qdev.h | 6
hw/scsi-bus.c | 1
hw/scsi-disk.c | 26
hw/scsi-generic.c | 1
hw/serial.c | 1
hw/sparc32_dma.c | 12
hw/spitz.c | 3
hw/ssi-sd.c | 1
hw/sun4m.c | 20
hw/sun4u.c | 12
hw/tosa.c | 3
hw/usb-hid.c | 9
hw/usb-msd.c | 4
hw/usb-ohci.c | 4
hw/vga-isa-mm.c | 6
hw/vga.c | 2
hw/vhost_net.c | 4
hw/virtio-blk.c | 89
hw/virtio-net.c | 26
hw/virtio-net.h | 4
hw/virtio-pci.c | 1
hw/virtio-serial-bus.c | 3
hw/virtio-serial.h | 1
hw/vmmouse.c | 2
hw/vmware_vga.c | 40
hw/xenfb.c | 1
hxtool | 62
ia64-dis.c | 9
input.c | 24
json-lexer.c | 114 -
json-parser.c | 5
json-streamer.c | 8
kvm.h | 1
linux-user/elfload.c | 24
linux-user/flatload.c | 2
linux-user/main.c | 97 -
linux-user/mmap.c | 172 +
linux-user/syscall.c | 103 -
linux-user/syscall_defs.h | 10
migration-exec.c | 14
migration-tcp.c | 4
migration.c | 57
migration.h | 2
monitor.c | 230 --
nbd.c | 3
nbd.h | 1
net.c | 33
net.h | 1
os-posix.c | 329 +++
os-win32.c | 221 ++
pc-bios/optionrom/linuxboot.S | 8
pc-bios/optionrom/optionrom.h | 32
posix-aio-compat.c | 58
qbool.c | 8
qdict.c | 6
qdict.h | 12
qemu-char.c | 17
qemu-common.h | 1
qemu-config.c | 14
qemu-doc.texi | 5
qemu-img-cmds.hx | 2
qemu-img.c | 59
qemu-io.c | 254 ++
qemu-malloc.c | 8
qemu-monitor.hx | 1485 +++++++++++++++-
qemu-objects.h | 5
qemu-option.c | 74
qemu-option.h | 2
qemu-options.h | 41
qemu-options.hx | 32
qemu-os-posix.h | 39
qemu-os-win32.h | 52
qemu-thread.c | 7
qerror.c | 2
qerror.h | 2
qfloat.c | 8
qint.c | 7
qint.h | 12
qjson.c | 3
qlist.c | 7
qlist.h | 7
qobject.h | 4
qstring.c | 7
qstring.h | 12
rules.mak | 2
s390-dis.c | 166 +
savevm.c | 7
sdl.c | 56
softmmu_header.h | 2
sysemu.h | 92 -
target-arm/cpu.h | 14
target-arm/helper.c | 1
target-arm/translate.c | 6
target-cris/cpu.h | 2
target-cris/mmu.c | 2
target-cris/translate.c | 4
target-i386/cpuid.c | 14
target-i386/translate.c | 2
target-microblaze/cpu.h | 9
target-mips/cpu.h | 1
target-mips/helper.c | 21
target-mips/helper.h | 9
target-mips/mips-defs.h | 1
target-mips/op_helper.c | 136 +
target-mips/translate.c | 3121 +++++++++++++++++++++++++++++++----
target-ppc/helper.c | 2
target-ppc/op_helper.c | 6
target-ppc/translate.c | 7
target-sparc/cpu.h | 73
target-sparc/helper.c | 135 +
target-sparc/op_helper.c | 373 ++--
target-sparc/translate.c | 351 ++-
tcg/arm/tcg-target.c | 6
tcg/hppa/tcg-target.c | 54
tcg/i386/tcg-target.c | 1925 ++++++++++++++-------
tcg/i386/tcg-target.h | 61
tcg/ia64/tcg-target.c | 206 +-
tcg/mips/tcg-target.c | 32
tcg/ppc/tcg-target.c | 52
tcg/ppc64/tcg-target.c | 14
tcg/s390/tcg-target.c | 6
tcg/s390/tcg-target.h | 5
tcg/sparc/tcg-target.c | 14
tcg/tcg-op.h | 8
tcg/tcg-opc.h | 293 +--
tcg/tcg.c | 21
tcg/tcg.h | 18
tcg/x86_64/tcg-target.c | 1454 ----------------
tcg/x86_64/tcg-target.h | 101 -
translate-all.c | 16
vl.c | 1031 -----------
vnc-encoding-hextile.c | 5
vnc-encoding-tight.c | 959 ++++++++++
vnc-encoding-tight.h | 176 +
vnc-encoding-zlib.c | 40
vnc.c | 220 +-
vnc.h | 34
vnchextile.h | 7
266 files changed, 13096 insertions(+), 6543 deletions(-)
New commits:
commit fd42deeb4cb42f90084046e3ebdb4383953195e3
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Fri Jun 4 14:08:07 2010 +0200
Add exit notifiers.
Hook up any cleanup work which needs to be done here. Advantages over
using atexit(3):
(1) You get passed in a pointer to the notifier. If you embed that
into your state struct you can use container_of() to get get your
state info.
(2) You can unregister, say when un-plugging a device.
[ v2: move code out of #ifndef _WIN32 ]
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/sysemu.h b/sysemu.h
index fbe103b..c758243 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -6,6 +6,7 @@
#include "qemu-option.h"
#include "qemu-queue.h"
#include "qemu-timer.h"
+#include "notify.h"
#ifdef _WIN32
#include <windows.h>
@@ -56,6 +57,9 @@ int qemu_powerdown_requested(void);
extern qemu_irq qemu_system_powerdown;
void qemu_system_reset(void);
+void qemu_add_exit_notifier(Notifier *notify);
+void qemu_remove_exit_notifier(Notifier *notify);
+
void do_savevm(Monitor *mon, const QDict *qdict);
int load_vmstate(const char *name);
void do_delvm(Monitor *mon, const QDict *qdict);
diff --git a/vl.c b/vl.c
index df18198..e5e43b3 100644
--- a/vl.c
+++ b/vl.c
@@ -234,6 +234,9 @@ uint8_t qemu_uuid[16];
static QEMUBootSetHandler *boot_set_handler;
static void *boot_set_opaque;
+static NotifierList exit_notifiers =
+ NOTIFIER_LIST_INITIALIZER(exit_notifiers);
+
int kvm_allowed = 0;
uint32_t xen_domid;
enum xen_mode xen_mode = XEN_EMULATE;
@@ -1740,6 +1743,21 @@ static int debugcon_parse(const char *devname)
return 0;
}
+void qemu_add_exit_notifier(Notifier *notify)
+{
+ notifier_list_add(&exit_notifiers, notify);
+}
+
+void qemu_remove_exit_notifier(Notifier *notify)
+{
+ notifier_list_remove(&exit_notifiers, notify);
+}
+
+static void qemu_run_exit_notifiers(void)
+{
+ notifier_list_notify(&exit_notifiers);
+}
+
static const QEMUOption *lookup_opt(int argc, char **argv,
const char **poptarg, int *poptind)
{
@@ -1804,6 +1822,7 @@ int main(int argc, char **argv, char **envp)
int show_vnc_port = 0;
int defconfig = 1;
+ atexit(qemu_run_exit_notifiers);
error_set_progname(argv[0]);
init_clocks();
commit 4cf3e6f3d85492f20a773dd6c9068ab89ba24a18
Author: Alex Williamson <alex.williamson at redhat.com>
Date: Wed Jun 2 10:58:29 2010 -0600
acpi_piix4: save gpe and pci hotplug slot status
PCI hotplug currently doesn't work after a migration because
we don't migrate the enable bits of the GPE state. Pull hotplug
structs into vmstate.
Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index a87286b..8d1a628 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -283,9 +283,33 @@ static int vmstate_acpi_post_load(void *opaque, int version_id)
return 0;
}
+static const VMStateDescription vmstate_gpe = {
+ .name = "gpe",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT16(sts, struct gpe_regs),
+ VMSTATE_UINT16(en, struct gpe_regs),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_pci_status = {
+ .name = "pci_status",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .minimum_version_id_old = 1,
+ .fields = (VMStateField []) {
+ VMSTATE_UINT32(up, struct pci_status),
+ VMSTATE_UINT32(down, struct pci_status),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static const VMStateDescription vmstate_acpi = {
.name = "piix4_pm",
- .version_id = 1,
+ .version_id = 2,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.post_load = vmstate_acpi_post_load,
@@ -297,6 +321,9 @@ static const VMStateDescription vmstate_acpi = {
VMSTATE_STRUCT(apm, PIIX4PMState, 0, vmstate_apm, APMState),
VMSTATE_TIMER(tmr_timer, PIIX4PMState),
VMSTATE_INT64(tmr_overflow_time, PIIX4PMState),
+ VMSTATE_STRUCT(gpe, PIIX4PMState, 2, vmstate_gpe, struct gpe_regs),
+ VMSTATE_STRUCT(pci0_status, PIIX4PMState, 2, vmstate_pci_status,
+ struct pci_status),
VMSTATE_END_OF_LIST()
}
};
commit b560a9ab9be06afcbb78b3791ab836dad208a239
Author: Markus Armbruster <armbru at redhat.com>
Date: Tue Jun 8 13:54:26 2010 +0200
qemu-option: Reject anti-social IDs
Restrict IDs to letters, digits, '-', '.', '_', starting with a
letter.
This takes care of '/' in qdev IDs breaking qbus_find().
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/qemu-option.c b/qemu-option.c
index f884865..7f70d0f 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -673,11 +673,31 @@ QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id)
return NULL;
}
+static int id_wellformed(const char *id)
+{
+ int i;
+
+ if (!qemu_isalpha(id[0])) {
+ return 0;
+ }
+ for (i = 1; id[i]; i++) {
+ if (!qemu_isalnum(id[i]) && !strchr("-._", id[i])) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, int fail_if_exists)
{
QemuOpts *opts = NULL;
if (id) {
+ if (!id_wellformed(id)) {
+ qerror_report(QERR_INVALID_PARAMETER_VALUE, "id", "an identifier");
+ error_printf_unless_qmp("Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.\n");
+ return NULL;
+ }
opts = qemu_opts_find(list, id);
if (opts != NULL) {
if (fail_if_exists) {
commit 1bb650420021ced718d550559034a5147c053068
Author: Markus Armbruster <armbru at redhat.com>
Date: Tue Jun 8 13:54:04 2010 +0200
qdev: Revert the hack to let -net nic and pci_add set qdev ID
Setting the ID in pci_nic_init() is a blatant violation of the
DeviceState abstraction. Which even carries a comment advising
against this:
/* This structure should not be accessed directly. We declare it here
so that it can be embedded in individual device state structures. */
What's worse, it bypasses the code ensuring unique qdev IDs: "-device
virtio-net-pci,id=foo -net nic,id=foo -net nic,name=foo" happily
creates three qdevs with ID "foo". That's because qdev relies on
qemu_opts_create() to ensure unique IDs, but -net nic uses a different
QemuOptsList, which means id is in a different namespace. And its
name is not checked for uniqueness at all.
-net nic and pci_add are legacy. Use -device and device_add if you
want a NIC with a qdev ID.
This reverts what's still left of commit eb54b6dc "qdev: add id=
support for pci nics."
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/hw/pci.c b/hw/pci.c
index cd7ce8d..7787005 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1446,8 +1446,6 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model,
pci_dev = pci_create(bus, devfn, pci_nic_names[i]);
dev = &pci_dev->qdev;
- if (nd->name)
- dev->id = qemu_strdup(nd->name);
qdev_set_nic_properties(dev, nd);
if (qdev_init(dev) < 0)
return NULL;
commit 3709c1b7ccad238e129c219c0081f1d55330e900
Author: Daniel P. Berrange <berrange at redhat.com>
Date: Tue Jun 8 15:24:25 2010 +0100
Clarify error message when a PCI slot is already in use (v2)
When mistakenly configuring two devices in the same PCI slot,
QEMU gives a not entirely obvious message about a 'devfn' being
in use:
$ qemu -device rtl8139 -device virtio-balloon-pci,bus=pci.0,addr=0x3
qemu-kvm: -device virtio-balloon-pci,bus=pci.0,addr=0x3: PCI: devfn 24 not available for virtio-balloon-pci, in use by rtl8139
The user does not configure 'devfn' numbers, they use slot+function.
Thus the error messages should be reported back to the user with that
same terminology rather than the internal QEMU terminology. This
patch makes it report:
$ qemu -device rtl8139 -device virtio-balloon-pci,bus=pci.0,addr=0x3
qemu: -device virtio-balloon-pci,bus=pci.0,addr=0x3.7: PCI: slot 3 function 0 not available for virtio-balloon-pci, in use by rtl8139
Signed-off-by: Daniel P. Berrange <berrange at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/hw/pci.c b/hw/pci.c
index cbbd1dd..cd7ce8d 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -609,12 +609,12 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
if (!bus->devices[devfn])
goto found;
}
- error_report("PCI: no devfn available for %s, all in use", name);
+ error_report("PCI: no slot/function available for %s, all in use", name);
return NULL;
found: ;
} else if (bus->devices[devfn]) {
- error_report("PCI: devfn %d not available for %s, in use by %s",
- devfn, name, bus->devices[devfn]->name);
+ error_report("PCI: slot %d function %d not available for %s, in use by %s",
+ PCI_SLOT(devfn), PCI_FUNC(devfn), name, bus->devices[devfn]->name);
return NULL;
}
pci_dev->bus = bus;
commit c20fd872257fb9abd2ce99741937c0f65aa162b7
Author: Christoph Hellwig <hch at lst.de>
Date: Tue Jun 8 18:26:07 2010 +0200
virtio-blk: simplify multiwrite calling conventions
Pass the MultiReqBuffer structure down all the way to the I/O submission
instead of takin it apart. Also mark num_writes unsigned as it can't
go negative, and take the check for any pending I/O requests into the
submission function. Last but not least rename do_multiwrite to
virtio_submit_multiwrite to fit the general naming scheme and make clear
what it does.
Signed-off-by: Christoph Hellwig <hch at lst.de>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 4e67088..4cc94f6 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -223,33 +223,39 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
}
#endif /* __linux__ */
-static void do_multiwrite(BlockDriverState *bs, BlockRequest *blkreq,
- int num_writes)
+typedef struct MultiReqBuffer {
+ BlockRequest blkreq[32];
+ unsigned int num_writes;
+} MultiReqBuffer;
+
+static void virtio_submit_multiwrite(BlockDriverState *bs, MultiReqBuffer *mrb)
{
int i, ret;
- ret = bdrv_aio_multiwrite(bs, blkreq, num_writes);
+ if (!mrb->num_writes) {
+ return;
+ }
+
+ ret = bdrv_aio_multiwrite(bs, mrb->blkreq, mrb->num_writes);
if (ret != 0) {
- for (i = 0; i < num_writes; i++) {
- if (blkreq[i].error) {
- virtio_blk_rw_complete(blkreq[i].opaque, -EIO);
+ for (i = 0; i < mrb->num_writes; i++) {
+ if (mrb->blkreq[i].error) {
+ virtio_blk_rw_complete(mrb->blkreq[i].opaque, -EIO);
}
}
}
+
+ mrb->num_writes = 0;
}
-static void virtio_blk_handle_flush(BlockRequest *blkreq, int *num_writes,
- VirtIOBlockReq *req)
+static void virtio_blk_handle_flush(VirtIOBlockReq *req, MultiReqBuffer *mrb)
{
BlockDriverAIOCB *acb;
/*
* Make sure all outstanding writes are posted to the backing device.
*/
- if (*num_writes > 0) {
- do_multiwrite(req->dev->bs, blkreq, *num_writes);
- }
- *num_writes = 0;
+ virtio_submit_multiwrite(req->dev->bs, mrb);
acb = bdrv_aio_flush(req->dev->bs, virtio_blk_flush_complete, req);
if (!acb) {
@@ -257,27 +263,28 @@ static void virtio_blk_handle_flush(BlockRequest *blkreq, int *num_writes,
}
}
-static void virtio_blk_handle_write(BlockRequest *blkreq, int *num_writes,
- VirtIOBlockReq *req)
+static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb)
{
+ BlockRequest *blkreq;
+
if (req->out->sector & req->dev->sector_mask) {
virtio_blk_rw_complete(req, -EIO);
return;
}
- if (*num_writes == 32) {
- do_multiwrite(req->dev->bs, blkreq, *num_writes);
- *num_writes = 0;
+ if (mrb->num_writes == 32) {
+ virtio_submit_multiwrite(req->dev->bs, mrb);
}
- blkreq[*num_writes].sector = req->out->sector;
- blkreq[*num_writes].nb_sectors = req->qiov.size / BDRV_SECTOR_SIZE;
- blkreq[*num_writes].qiov = &req->qiov;
- blkreq[*num_writes].cb = virtio_blk_rw_complete;
- blkreq[*num_writes].opaque = req;
- blkreq[*num_writes].error = 0;
+ blkreq = &mrb->blkreq[mrb->num_writes];
+ blkreq->sector = req->out->sector;
+ blkreq->nb_sectors = req->qiov.size / BDRV_SECTOR_SIZE;
+ blkreq->qiov = &req->qiov;
+ blkreq->cb = virtio_blk_rw_complete;
+ blkreq->opaque = req;
+ blkreq->error = 0;
- (*num_writes)++;
+ mrb->num_writes++;
}
static void virtio_blk_handle_read(VirtIOBlockReq *req)
@@ -297,11 +304,6 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req)
}
}
-typedef struct MultiReqBuffer {
- BlockRequest blkreq[32];
- int num_writes;
-} MultiReqBuffer;
-
static void virtio_blk_handle_request(VirtIOBlockReq *req,
MultiReqBuffer *mrb)
{
@@ -320,13 +322,13 @@ static void virtio_blk_handle_request(VirtIOBlockReq *req,
req->in = (void *)req->elem.in_sg[req->elem.in_num - 1].iov_base;
if (req->out->type & VIRTIO_BLK_T_FLUSH) {
- virtio_blk_handle_flush(mrb->blkreq, &mrb->num_writes, req);
+ virtio_blk_handle_flush(req, mrb);
} else if (req->out->type & VIRTIO_BLK_T_SCSI_CMD) {
virtio_blk_handle_scsi(req);
} else if (req->out->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(mrb->blkreq, &mrb->num_writes, req);
+ virtio_blk_handle_write(req, mrb);
} else {
qemu_iovec_init_external(&req->qiov, &req->elem.in_sg[0],
req->elem.in_num - 1);
@@ -346,9 +348,7 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
virtio_blk_handle_request(req, &mrb);
}
- if (mrb.num_writes > 0) {
- do_multiwrite(s->bs, mrb.blkreq, mrb.num_writes);
- }
+ virtio_submit_multiwrite(s->bs, &mrb);
/*
* FIXME: Want to check for completions before returning to guest mode,
@@ -375,9 +375,7 @@ static void virtio_blk_dma_restart_bh(void *opaque)
req = req->next;
}
- if (mrb.num_writes > 0) {
- do_multiwrite(s->bs, mrb.blkreq, mrb.num_writes);
- }
+ virtio_submit_multiwrite(s->bs, &mrb);
}
static void virtio_blk_dma_restart_cb(void *opaque, int running, int reason)
commit 7e608e8903a39157c28ced12b2a061eafa43c905
Author: Christoph Hellwig <hch at lst.de>
Date: Tue Jun 8 18:25:54 2010 +0200
virtio-blk: stop tracking old_bs
There is a 1:1 relation between VirtIOBlock and BlockDriverState instances,
no need to track it because it won't change.
Signed-off-by: Christoph Hellwig <hch at lst.de>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index cdcb492..4e67088 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -239,18 +239,17 @@ static void do_multiwrite(BlockDriverState *bs, BlockRequest *blkreq,
}
static void virtio_blk_handle_flush(BlockRequest *blkreq, int *num_writes,
- VirtIOBlockReq *req, BlockDriverState **old_bs)
+ VirtIOBlockReq *req)
{
BlockDriverAIOCB *acb;
/*
* Make sure all outstanding writes are posted to the backing device.
*/
- if (*old_bs != NULL) {
- do_multiwrite(*old_bs, blkreq, *num_writes);
+ if (*num_writes > 0) {
+ do_multiwrite(req->dev->bs, blkreq, *num_writes);
}
*num_writes = 0;
- *old_bs = req->dev->bs;
acb = bdrv_aio_flush(req->dev->bs, virtio_blk_flush_complete, req);
if (!acb) {
@@ -259,19 +258,16 @@ static void virtio_blk_handle_flush(BlockRequest *blkreq, int *num_writes,
}
static void virtio_blk_handle_write(BlockRequest *blkreq, int *num_writes,
- VirtIOBlockReq *req, BlockDriverState **old_bs)
+ VirtIOBlockReq *req)
{
if (req->out->sector & req->dev->sector_mask) {
virtio_blk_rw_complete(req, -EIO);
return;
}
- if (req->dev->bs != *old_bs || *num_writes == 32) {
- if (*old_bs != NULL) {
- do_multiwrite(*old_bs, blkreq, *num_writes);
- }
+ if (*num_writes == 32) {
+ do_multiwrite(req->dev->bs, blkreq, *num_writes);
*num_writes = 0;
- *old_bs = req->dev->bs;
}
blkreq[*num_writes].sector = req->out->sector;
@@ -304,7 +300,6 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req)
typedef struct MultiReqBuffer {
BlockRequest blkreq[32];
int num_writes;
- BlockDriverState *old_bs;
} MultiReqBuffer;
static void virtio_blk_handle_request(VirtIOBlockReq *req,
@@ -325,15 +320,13 @@ static void virtio_blk_handle_request(VirtIOBlockReq *req,
req->in = (void *)req->elem.in_sg[req->elem.in_num - 1].iov_base;
if (req->out->type & VIRTIO_BLK_T_FLUSH) {
- virtio_blk_handle_flush(mrb->blkreq, &mrb->num_writes,
- req, &mrb->old_bs);
+ virtio_blk_handle_flush(mrb->blkreq, &mrb->num_writes, req);
} else if (req->out->type & VIRTIO_BLK_T_SCSI_CMD) {
virtio_blk_handle_scsi(req);
} else if (req->out->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(mrb->blkreq, &mrb->num_writes,
- req, &mrb->old_bs);
+ virtio_blk_handle_write(mrb->blkreq, &mrb->num_writes, req);
} else {
qemu_iovec_init_external(&req->qiov, &req->elem.in_sg[0],
req->elem.in_num - 1);
@@ -347,7 +340,6 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
VirtIOBlockReq *req;
MultiReqBuffer mrb = {
.num_writes = 0,
- .old_bs = NULL,
};
while ((req = virtio_blk_get_request(s))) {
@@ -355,7 +347,7 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
}
if (mrb.num_writes > 0) {
- do_multiwrite(mrb.old_bs, mrb.blkreq, mrb.num_writes);
+ do_multiwrite(s->bs, mrb.blkreq, mrb.num_writes);
}
/*
@@ -371,7 +363,6 @@ static void virtio_blk_dma_restart_bh(void *opaque)
VirtIOBlockReq *req = s->rq;
MultiReqBuffer mrb = {
.num_writes = 0,
- .old_bs = NULL,
};
qemu_bh_delete(s->bh);
@@ -385,7 +376,7 @@ static void virtio_blk_dma_restart_bh(void *opaque)
}
if (mrb.num_writes > 0) {
- do_multiwrite(mrb.old_bs, mrb.blkreq, mrb.num_writes);
+ do_multiwrite(s->bs, mrb.blkreq, mrb.num_writes);
}
}
commit 46aaebff40f942e7b17b426916a3dee9b8b6f274
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Tue Jun 8 15:12:18 2010 +0200
un-register kbd driver in case of USB kbd unplug.
If a USB keyboard is unplugged, the keyboard eventhandler is never
removed, and events will continue to be passed through to the device,
causing crashes or memory corruption.
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/console.h b/console.h
index cac959f..aafb031 100644
--- a/console.h
+++ b/console.h
@@ -42,6 +42,7 @@ typedef struct QEMUPutLEDEntry {
} QEMUPutLEDEntry;
void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque);
+void qemu_remove_kbd_event_handler(void);
QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
void *opaque, int absolute,
const char *name);
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 228d0a0..882d933 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -855,9 +855,13 @@ static void usb_hid_handle_destroy(USBDevice *dev)
{
USBHIDState *s = (USBHIDState *)dev;
- if (s->kind != USB_KEYBOARD)
+ switch(s->kind) {
+ case USB_KEYBOARD:
+ qemu_remove_kbd_event_handler();
+ break;
+ default:
qemu_remove_mouse_event_handler(s->ptr.eh_entry);
- /* TODO: else */
+ }
}
static int usb_hid_initfn(USBDevice *dev, int kind)
diff --git a/input.c b/input.c
index 651442d..ec05548 100644
--- a/input.c
+++ b/input.c
@@ -42,6 +42,12 @@ void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
qemu_put_kbd_event = func;
}
+void qemu_remove_kbd_event_handler(void)
+{
+ qemu_put_kbd_event_opaque = NULL;
+ qemu_put_kbd_event = NULL;
+}
+
static void check_mode_change(void)
{
static int current_is_absolute, current_has_absolute;
commit 55541c8afc1a2d75de890c6ee858769d7d605526
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Thu Jun 3 15:20:32 2010 +0200
make qemu_thread_create block all signals
All signals will thus be routed through the IO thread.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/cpus.c b/cpus.c
index 8341f6c..fcd0f09 100644
--- a/cpus.c
+++ b/cpus.c
@@ -318,8 +318,8 @@ static QemuCond qemu_system_cond;
static QemuCond qemu_pause_cond;
static QemuCond qemu_work_cond;
-static void tcg_block_io_signals(void);
-static void kvm_block_io_signals(CPUState *env);
+static void tcg_init_ipi(void);
+static void kvm_init_ipi(CPUState *env);
static void unblock_io_signals(void);
int qemu_init_main_loop(void)
@@ -464,7 +464,7 @@ static void *kvm_cpu_thread_fn(void *arg)
if (kvm_enabled())
kvm_init_vcpu(env);
- kvm_block_io_signals(env);
+ kvm_init_ipi(env);
/* signal CPU creation */
env->created = 1;
@@ -487,7 +487,7 @@ static void *tcg_cpu_thread_fn(void *arg)
{
CPUState *env = arg;
- tcg_block_io_signals();
+ tcg_init_ipi();
qemu_thread_self(env->thread);
/* signal CPU creation */
@@ -532,52 +532,36 @@ static void cpu_signal(int sig)
exit_request = 1;
}
-static void tcg_block_io_signals(void)
+static void tcg_init_ipi(void)
{
sigset_t set;
struct sigaction sigact;
- sigemptyset(&set);
- sigaddset(&set, SIGUSR2);
- sigaddset(&set, SIGIO);
- sigaddset(&set, SIGALRM);
- sigaddset(&set, SIGCHLD);
- pthread_sigmask(SIG_BLOCK, &set, NULL);
+ memset(&sigact, 0, sizeof(sigact));
+ sigact.sa_handler = cpu_signal;
+ sigaction(SIG_IPI, &sigact, NULL);
sigemptyset(&set);
sigaddset(&set, SIG_IPI);
pthread_sigmask(SIG_UNBLOCK, &set, NULL);
-
- memset(&sigact, 0, sizeof(sigact));
- sigact.sa_handler = cpu_signal;
- sigaction(SIG_IPI, &sigact, NULL);
}
static void dummy_signal(int sig)
{
}
-static void kvm_block_io_signals(CPUState *env)
+static void kvm_init_ipi(CPUState *env)
{
int r;
sigset_t set;
struct sigaction sigact;
- sigemptyset(&set);
- sigaddset(&set, SIGUSR2);
- sigaddset(&set, SIGIO);
- sigaddset(&set, SIGALRM);
- sigaddset(&set, SIGCHLD);
- sigaddset(&set, SIG_IPI);
- pthread_sigmask(SIG_BLOCK, &set, NULL);
-
- pthread_sigmask(SIG_BLOCK, NULL, &set);
- sigdelset(&set, SIG_IPI);
-
memset(&sigact, 0, sizeof(sigact));
sigact.sa_handler = dummy_signal;
sigaction(SIG_IPI, &sigact, NULL);
+ pthread_sigmask(SIG_BLOCK, NULL, &set);
+ sigdelset(&set, SIG_IPI);
r = kvm_set_signal_mask(env, &set);
if (r) {
fprintf(stderr, "kvm_set_signal_mask: %s\n", strerror(r));
diff --git a/qemu-thread.c b/qemu-thread.c
index 3923db7..faf4061 100644
--- a/qemu-thread.c
+++ b/qemu-thread.c
@@ -137,9 +137,16 @@ void qemu_thread_create(QemuThread *thread,
{
int err;
+ /* Leave signal handling to the iothread. */
+ sigset_t set, oldset;
+
+ sigfillset(&set);
+ pthread_sigmask(SIG_SETMASK, &set, &oldset);
err = pthread_create(&thread->thread, NULL, start_routine, arg);
if (err)
error_exit(err, __func__);
+
+ pthread_sigmask(SIG_SETMASK, &oldset, NULL);
}
void qemu_thread_signal(QemuThread *thread, int sig)
commit 304e3a7c802969811fe82b6247f63fcba063f52e
Author: Yoshiaki Tamura <tamura.yoshiaki at lab.ntt.co.jp>
Date: Thu Jun 10 06:50:10 2010 +0900
migration-tcp: call migrate_fd_error() instead of close() and free().
This patch fixes the following error report. When changing
migration-tcp.c to call migrate_fd_error() instead of close() and
free() by itself, monitor is resumed, and returns allocated mig_state
is set to current_migration in migration.c allows us to print "info
migrate".
Reported-by: Cole Robinson <crobinso at redhat.com>
Signed-off-by: Yoshiaki Tamura <tamura.yoshiaki at lab.ntt.co.jp>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/migration-tcp.c b/migration-tcp.c
index 95ce722..43af2e0 100644
--- a/migration-tcp.c
+++ b/migration-tcp.c
@@ -128,9 +128,7 @@ MigrationState *tcp_start_outgoing_migration(Monitor *mon,
if (ret < 0 && ret != -EINPROGRESS && ret != -EWOULDBLOCK) {
DPRINTF("connect failed\n");
- close(s->fd);
- qemu_free(s);
- return NULL;
+ migrate_fd_error(s);
} else if (ret >= 0)
migrate_fd_connect(s);
commit faa1f8ddc18fe30257f2ed6c378fce848b159dab
Author: Yoshiaki Tamura <tamura.yoshiaki at lab.ntt.co.jp>
Date: Wed Jun 9 14:44:31 2010 +0900
migration: use qemu_free() instead of free().
Although there is no difference, other migration related code use
qemu_free(), and it should be better to be consistent.
Signed-off-by: Yoshiaki Tamura <tamura.yoshiaki at lab.ntt.co.jp>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/migration.c b/migration.c
index fbf2339..64ed36e 100644
--- a/migration.c
+++ b/migration.c
@@ -396,7 +396,7 @@ void migrate_fd_release(MigrationState *mig_state)
s->state = MIG_STATE_CANCELLED;
migrate_fd_cleanup(s);
}
- free(s);
+ qemu_free(s);
}
void migrate_fd_wait_for_unfreeze(void *opaque)
commit f2fcffbbe8d7d2720a5ce992dedbf328be25c03a
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date: Mon Jun 14 18:41:12 2010 +0200
etrax-ser: Support the uart rx fifo.
Add support for the rx fifo to speed up bulk transfers.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at axis.com>
diff --git a/hw/etraxfs_ser.c b/hw/etraxfs_ser.c
index e1f9615..336cc54 100644
--- a/hw/etraxfs_ser.c
+++ b/hw/etraxfs_ser.c
@@ -49,20 +49,27 @@ struct etrax_serial
CharDriverState *chr;
qemu_irq irq;
- /* This pending thing is a hack. */
int pending_tx;
+ uint8_t rx_fifo[16];
+ unsigned int rx_fifo_pos;
+ unsigned int rx_fifo_len;
+
/* Control registers. */
uint32_t regs[R_MAX];
};
static void ser_update_irq(struct etrax_serial *s)
{
- s->regs[R_INTR] &= ~(s->regs[RW_ACK_INTR]);
- s->regs[R_MASKED_INTR] = s->regs[R_INTR] & s->regs[RW_INTR_MASK];
+ if (s->rx_fifo_len) {
+ s->regs[R_INTR] |= 8;
+ } else {
+ s->regs[R_INTR] &= ~8;
+ }
+
+ s->regs[R_MASKED_INTR] = s->regs[R_INTR] & s->regs[RW_INTR_MASK];
qemu_set_irq(s->irq, !!s->regs[R_MASKED_INTR]);
- s->regs[RW_ACK_INTR] = 0;
}
static uint32_t ser_readl (void *opaque, target_phys_addr_t addr)
@@ -75,16 +82,25 @@ static uint32_t ser_readl (void *opaque, target_phys_addr_t addr)
switch (addr)
{
case R_STAT_DIN:
- r = s->regs[RS_STAT_DIN];
+ r = s->rx_fifo[(s->rx_fifo_pos - s->rx_fifo_len) & 15];
+ if (s->rx_fifo_len) {
+ r |= 1 << STAT_DAV;
+ }
+ r |= 1 << STAT_TR_RDY;
+ r |= 1 << STAT_TR_IDLE;
break;
case RS_STAT_DIN:
- r = s->regs[addr];
- /* Read side-effect: clear dav. */
- s->regs[addr] &= ~(1 << STAT_DAV);
+ r = s->rx_fifo[(s->rx_fifo_pos - s->rx_fifo_len) & 15];
+ if (s->rx_fifo_len) {
+ r |= 1 << STAT_DAV;
+ s->rx_fifo_len--;
+ }
+ r |= 1 << STAT_TR_RDY;
+ r |= 1 << STAT_TR_IDLE;
break;
default:
r = s->regs[addr];
- D(printf ("%s %x=%x\n", __func__, addr, r));
+ D(printf ("%s " TARGET_FMT_plx "=%x\n", __func__, addr, r));
break;
}
return r;
@@ -97,23 +113,25 @@ ser_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
unsigned char ch = value;
D(CPUState *env = s->env);
- D(printf ("%s %x %x\n", __func__, addr, value));
+ D(printf ("%s " TARGET_FMT_plx "=%x\n", __func__, addr, value));
addr >>= 2;
switch (addr)
{
case RW_DOUT:
qemu_chr_write(s->chr, &ch, 1);
- s->regs[R_INTR] |= 1;
+ s->regs[R_INTR] |= 3;
s->pending_tx = 1;
s->regs[addr] = value;
break;
case RW_ACK_INTR:
- s->regs[addr] = value;
- if (s->pending_tx && (s->regs[addr] & 1)) {
- s->regs[R_INTR] |= 1;
+ if (s->pending_tx) {
+ value &= ~1;
s->pending_tx = 0;
- s->regs[addr] &= ~1;
+ D(printf("fixedup value=%x r_intr=%x\n", value, s->regs[R_INTR]));
}
+ s->regs[addr] = value;
+ s->regs[R_INTR] &= ~value;
+ D(printf("r_intr=%x\n", s->regs[R_INTR]));
break;
default:
s->regs[addr] = value;
@@ -135,11 +153,21 @@ static CPUWriteMemoryFunc * const ser_write[] = {
static void serial_receive(void *opaque, const uint8_t *buf, int size)
{
struct etrax_serial *s = opaque;
+ int i;
+
+ /* Got a byte. */
+ if (s->rx_fifo_len >= 16) {
+ printf("WARNING: UART dropped char.\n");
+ return;
+ }
+
+ for (i = 0; i < size; i++) {
+ s->rx_fifo[s->rx_fifo_pos] = buf[i];
+ s->rx_fifo_pos++;
+ s->rx_fifo_pos &= 15;
+ s->rx_fifo_len++;
+ }
- s->regs[R_INTR] |= 8;
- s->regs[RS_STAT_DIN] &= ~0xff;
- s->regs[RS_STAT_DIN] |= (buf[0] & 0xff);
- s->regs[RS_STAT_DIN] |= (1 << STAT_DAV); /* dav. */
ser_update_irq(s);
}
@@ -149,10 +177,11 @@ static int serial_can_receive(void *opaque)
int r;
/* Is the receiver enabled? */
- r = s->regs[RW_REC_CTRL] & 1;
+ if (!(s->regs[RW_REC_CTRL] & (1 << 3))) {
+ return 0;
+ }
- /* Pending rx data? */
- r |= !(s->regs[R_INTR] & 8);
+ r = sizeof(s->rx_fifo) - s->rx_fifo_len;
return r;
}
commit f471a17e9d869df3c6573f7ec02c4725676d6f3a
Author: Alex Williamson <alex.williamson at redhat.com>
Date: Fri Jun 11 11:11:42 2010 -0600
ram_blocks: Convert to a QLIST
This makes the RAM block list easier to manipulate. Also incorporate
relevant variables into the RAMList struct.
Signed-off-by: Alex Williamson <alex.williamson at redhat.com>
Acked-by: Chris Wright <chrisw at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/arch_init.c b/arch_init.c
index 8e849a8..eb5b67c 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -110,7 +110,7 @@ static int ram_save_block(QEMUFile *f)
ram_addr_t addr = 0;
int bytes_sent = 0;
- while (addr < last_ram_offset) {
+ while (addr < ram_list.last_offset) {
if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) {
uint8_t *p;
@@ -133,7 +133,7 @@ static int ram_save_block(QEMUFile *f)
break;
}
addr += TARGET_PAGE_SIZE;
- current_addr = (saved_addr + addr) % last_ram_offset;
+ current_addr = (saved_addr + addr) % ram_list.last_offset;
}
return bytes_sent;
@@ -146,7 +146,7 @@ static ram_addr_t ram_save_remaining(void)
ram_addr_t addr;
ram_addr_t count = 0;
- for (addr = 0; addr < last_ram_offset; addr += TARGET_PAGE_SIZE) {
+ for (addr = 0; addr < ram_list.last_offset; addr += TARGET_PAGE_SIZE) {
if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
count++;
}
@@ -167,7 +167,7 @@ uint64_t ram_bytes_transferred(void)
uint64_t ram_bytes_total(void)
{
- return last_ram_offset;
+ return ram_list.last_offset;
}
int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
@@ -191,7 +191,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
bytes_transferred = 0;
/* Make sure all dirty bits are set */
- for (addr = 0; addr < last_ram_offset; addr += TARGET_PAGE_SIZE) {
+ for (addr = 0; addr < ram_list.last_offset; addr += TARGET_PAGE_SIZE) {
if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG)) {
cpu_physical_memory_set_dirty(addr);
}
@@ -200,7 +200,7 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
/* Enable dirty memory tracking */
cpu_physical_memory_set_dirty_tracking(1);
- qemu_put_be64(f, last_ram_offset | RAM_SAVE_FLAG_MEM_SIZE);
+ qemu_put_be64(f, ram_list.last_offset | RAM_SAVE_FLAG_MEM_SIZE);
}
bytes_transferred_last = bytes_transferred;
@@ -259,7 +259,7 @@ int ram_load(QEMUFile *f, void *opaque, int version_id)
addr &= TARGET_PAGE_MASK;
if (flags & RAM_SAVE_FLAG_MEM_SIZE) {
- if (addr != last_ram_offset) {
+ if (addr != ram_list.last_offset) {
return -EINVAL;
}
}
diff --git a/cpu-all.h b/cpu-all.h
index 77eaf85..e31c2de 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -859,9 +859,21 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr);
/* memory API */
extern int phys_ram_fd;
-extern uint8_t *phys_ram_dirty;
extern ram_addr_t ram_size;
-extern ram_addr_t last_ram_offset;
+
+typedef struct RAMBlock {
+ uint8_t *host;
+ ram_addr_t offset;
+ ram_addr_t length;
+ QLIST_ENTRY(RAMBlock) next;
+} RAMBlock;
+
+typedef struct RAMList {
+ uint8_t *phys_dirty;
+ ram_addr_t last_offset;
+ QLIST_HEAD(ram, RAMBlock) blocks;
+} RAMList;
+extern RAMList ram_list;
extern const char *mem_path;
extern int mem_prealloc;
@@ -891,29 +903,29 @@ extern int mem_prealloc;
/* read dirty bit (return 0 or 1) */
static inline int cpu_physical_memory_is_dirty(ram_addr_t addr)
{
- return phys_ram_dirty[addr >> TARGET_PAGE_BITS] == 0xff;
+ return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] == 0xff;
}
static inline int cpu_physical_memory_get_dirty_flags(ram_addr_t addr)
{
- return phys_ram_dirty[addr >> TARGET_PAGE_BITS];
+ return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS];
}
static inline int cpu_physical_memory_get_dirty(ram_addr_t addr,
int dirty_flags)
{
- return phys_ram_dirty[addr >> TARGET_PAGE_BITS] & dirty_flags;
+ return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] & dirty_flags;
}
static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
{
- phys_ram_dirty[addr >> TARGET_PAGE_BITS] = 0xff;
+ ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] = 0xff;
}
static inline int cpu_physical_memory_set_dirty_flags(ram_addr_t addr,
int dirty_flags)
{
- return phys_ram_dirty[addr >> TARGET_PAGE_BITS] |= dirty_flags;
+ return ram_list.phys_dirty[addr >> TARGET_PAGE_BITS] |= dirty_flags;
}
static inline void cpu_physical_memory_mask_dirty_range(ram_addr_t start,
@@ -925,7 +937,7 @@ static inline void cpu_physical_memory_mask_dirty_range(ram_addr_t start,
len = length >> TARGET_PAGE_BITS;
mask = ~dirty_flags;
- p = phys_ram_dirty + (start >> TARGET_PAGE_BITS);
+ p = ram_list.phys_dirty + (start >> TARGET_PAGE_BITS);
for (i = 0; i < len; i++) {
p[i] &= mask;
}
diff --git a/exec.c b/exec.c
index 4273797..7f64384 100644
--- a/exec.c
+++ b/exec.c
@@ -110,21 +110,9 @@ uint8_t *code_gen_ptr;
#if !defined(CONFIG_USER_ONLY)
int phys_ram_fd;
-uint8_t *phys_ram_dirty;
static int in_migration;
-typedef struct RAMBlock {
- uint8_t *host;
- ram_addr_t offset;
- ram_addr_t length;
- struct RAMBlock *next;
-} RAMBlock;
-
-static RAMBlock *ram_blocks;
-/* TODO: When we implement (and use) ram deallocation (e.g. for hotplug)
- then we can no longer assume contiguous ram offsets, and external uses
- of this variable will break. */
-ram_addr_t last_ram_offset;
+RAMList ram_list = { .blocks = QLIST_HEAD_INITIALIZER(ram_list) };
#endif
CPUState *first_cpu;
@@ -2810,18 +2798,17 @@ ram_addr_t qemu_ram_alloc(ram_addr_t size)
madvise(new_block->host, size, MADV_MERGEABLE);
#endif
}
- new_block->offset = last_ram_offset;
+ new_block->offset = ram_list.last_offset;
new_block->length = size;
- new_block->next = ram_blocks;
- ram_blocks = new_block;
+ QLIST_INSERT_HEAD(&ram_list.blocks, new_block, next);
- phys_ram_dirty = qemu_realloc(phys_ram_dirty,
- (last_ram_offset + size) >> TARGET_PAGE_BITS);
- memset(phys_ram_dirty + (last_ram_offset >> TARGET_PAGE_BITS),
+ ram_list.phys_dirty = qemu_realloc(ram_list.phys_dirty,
+ (ram_list.last_offset + size) >> TARGET_PAGE_BITS);
+ memset(ram_list.phys_dirty + (ram_list.last_offset >> TARGET_PAGE_BITS),
0xff, size >> TARGET_PAGE_BITS);
- last_ram_offset += size;
+ ram_list.last_offset += size;
if (kvm_enabled())
kvm_setup_guest_memory(new_block->host, size);
@@ -2844,31 +2831,20 @@ void qemu_ram_free(ram_addr_t addr)
*/
void *qemu_get_ram_ptr(ram_addr_t addr)
{
- RAMBlock *prev;
- RAMBlock **prevp;
RAMBlock *block;
- prev = NULL;
- prevp = &ram_blocks;
- block = ram_blocks;
- while (block && (block->offset > addr
- || block->offset + block->length <= addr)) {
- if (prev)
- prevp = &prev->next;
- prev = block;
- block = block->next;
- }
- if (!block) {
- fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
- abort();
- }
- /* Move this entry to to start of the list. */
- if (prev) {
- prev->next = block->next;
- block->next = *prevp;
- *prevp = block;
+ QLIST_FOREACH(block, &ram_list.blocks, next) {
+ if (addr - block->offset < block->length) {
+ QLIST_REMOVE(block, next);
+ QLIST_INSERT_HEAD(&ram_list.blocks, block, next);
+ return block->host + (addr - block->offset);
+ }
}
- return block->host + (addr - block->offset);
+
+ fprintf(stderr, "Bad ram offset %" PRIx64 "\n", (uint64_t)addr);
+ abort();
+
+ return NULL;
}
/* Some of the softmmu routines need to translate from a host pointer
@@ -2878,16 +2854,16 @@ ram_addr_t qemu_ram_addr_from_host(void *ptr)
RAMBlock *block;
uint8_t *host = ptr;
- block = ram_blocks;
- while (block && (block->host > host
- || block->host + block->length <= host)) {
- block = block->next;
- }
- if (!block) {
- fprintf(stderr, "Bad ram pointer %p\n", ptr);
- abort();
+ QLIST_FOREACH(block, &ram_list.blocks, next) {
+ if (host - block->host < block->length) {
+ return block->offset + (host - block->host);
+ }
}
- return block->offset + (host - block->host);
+
+ fprintf(stderr, "Bad ram pointer %p\n", ptr);
+ abort();
+
+ return 0;
}
static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
commit 2ffcb18de0bc02ad8a836ec955584c02b70e0e24
Author: Markus Armbruster <armbru at redhat.com>
Date: Fri Jun 11 14:21:34 2010 +0200
Make netdev_del delete the netdev even when it's in use
To hot-unplug guest and host part of a network device, you do:
device_del NIC-ID
netdev_del NETDEV-ID
For PCI devices, device_del merely tells ACPI to unplug the device.
The device goes away for real only after the guest processed the ACPI
unplug event.
You have to wait until then (e.g. by polling info pci) before you can
unplug the netdev. Not good.
Fix by removing the "in use" check from do_netdev_del(). Deleting a
netdev while it's in use is safe; packets simply get routed to the bit
bucket.
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/net.c b/net.c
index 4cb93ed..0703698 100644
--- a/net.c
+++ b/net.c
@@ -1221,10 +1221,6 @@ int do_netdev_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
qerror_report(QERR_DEVICE_NOT_FOUND, id);
return -1;
}
- if (vc->peer) {
- qerror_report(QERR_DEVICE_IN_USE, id);
- return -1;
- }
qemu_del_vlan_client(vc);
qemu_opts_del(qemu_opts_find(&qemu_netdev_opts, id));
return 0;
commit 40ac17cd56eb5c5a89559ea0fa53f7eea80cbd07
Author: Gleb Natapov <gleb at redhat.com>
Date: Mon Jun 14 11:29:28 2010 +0300
pass info about hpets to seabios.]
Currently HPET ACPI table is created regardless of whether qemu actually
created hpet device. This may confuse some guests that don't check that
hpet is functional before using it. Solve this by passing info about
hpets in qemu to seabios via fw config interface. Additional benefit is
that seabios no longer uses hard coded hpet configuration. Proposed
interface supports up to 8 hpets. This is the number defined by hpet
spec.
Signed-off-by: Gleb Natapov <gleb at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/hw/hpet.c b/hw/hpet.c
index e9b585c..0c80ee5 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -71,8 +71,11 @@ typedef struct HPETState {
uint64_t config; /* configuration */
uint64_t isr; /* interrupt status reg */
uint64_t hpet_counter; /* main counter */
+ uint8_t hpet_id; /* instance id */
} HPETState;
+struct hpet_fw_config hpet_cfg = {.count = ~0};
+
static uint32_t hpet_in_legacy_mode(HPETState *s)
{
return s->config & HPET_CFG_LEGACY;
@@ -228,6 +231,7 @@ static int hpet_post_load(void *opaque, int version_id)
/* Push number of timers into capability returned via HPET_ID */
s->capability &= ~HPET_ID_NUM_TIM_MASK;
s->capability |= (s->num_timers - 1) << HPET_ID_NUM_TIM_SHIFT;
+ hpet_cfg.hpet[s->hpet_id].event_timer_block_id = (uint32_t)s->capability;
/* Derive HPET_MSI_SUPPORT from the capability of the first timer. */
s->flags &= ~(1 << HPET_MSI_SUPPORT);
@@ -657,6 +661,8 @@ static void hpet_reset(DeviceState *d)
*/
hpet_pit_enable();
}
+ hpet_cfg.hpet[s->hpet_id].event_timer_block_id = (uint32_t)s->capability;
+ hpet_cfg.hpet[s->hpet_id].address = sysbus_from_qdev(d)->mmio[0].addr;
count = 1;
}
@@ -676,6 +682,16 @@ static int hpet_init(SysBusDevice *dev)
int i, iomemtype;
HPETTimer *timer;
+ if (hpet_cfg.count == ~0) /* first instance */
+ hpet_cfg.count = 0;
+
+ if (hpet_cfg.count == 8) {
+ fprintf(stderr, "Only 8 instances of HPET is allowed\n");
+ return -1;
+ }
+
+ s->hpet_id = hpet_cfg.count++;
+
for (i = 0; i < HPET_NUM_IRQ_ROUTES; i++) {
sysbus_init_irq(dev, &s->irqs[i]);
}
diff --git a/hw/hpet_emul.h b/hw/hpet_emul.h
index d7bc102..8bf312a 100644
--- a/hw/hpet_emul.h
+++ b/hw/hpet_emul.h
@@ -53,4 +53,19 @@
#define HPET_TN_INT_ROUTE_CAP_SHIFT 32
#define HPET_TN_CFG_BITS_READONLY_OR_RESERVED 0xffff80b1U
+struct hpet_fw_entry
+{
+ uint32_t event_timer_block_id;
+ uint64_t address;
+ uint16_t min_tick;
+ uint8_t page_prot;
+} __attribute__ ((packed));
+
+struct hpet_fw_config
+{
+ uint8_t count;
+ struct hpet_fw_entry hpet[8];
+} __attribute__ ((packed));
+
+extern struct hpet_fw_config hpet_cfg;
#endif
diff --git a/hw/pc.c b/hw/pc.c
index 0f7d330..0211fbf 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -62,6 +62,7 @@
#define FW_CFG_SMBIOS_ENTRIES (FW_CFG_ARCH_LOCAL + 1)
#define FW_CFG_IRQ0_OVERRIDE (FW_CFG_ARCH_LOCAL + 2)
#define FW_CFG_E820_TABLE (FW_CFG_ARCH_LOCAL + 3)
+#define FW_CFG_HPET (FW_CFG_ARCH_LOCAL + 4)
#define E820_NR_ENTRIES 16
@@ -485,6 +486,8 @@ static void *bochs_bios_init(void)
fw_cfg_add_bytes(fw_cfg, FW_CFG_E820_TABLE, (uint8_t *)&e820_table,
sizeof(struct e820_table));
+ fw_cfg_add_bytes(fw_cfg, FW_CFG_HPET, (uint8_t *)&hpet_cfg,
+ sizeof(struct hpet_fw_config));
/* allocate memory for the NUMA channel: one (64bit) word for the number
* of nodes, one word for each VCPU->node and one word for each node to
* hold the amount of memory.
commit 072c2c31c27204e8e1897c52e481d2ab0b4d075d
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Mon Jun 14 08:40:29 2010 +0200
hpet: Init capability register only once
The capability register is read-only from guest POV, so we do not need
to update it on reset.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/hw/hpet.c b/hw/hpet.c
index 93fc399..e9b585c 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -648,10 +648,6 @@ static void hpet_reset(DeviceState *d)
s->hpet_counter = 0ULL;
s->hpet_offset = 0ULL;
- /* 64-bit main counter; LegacyReplacementRoute. */
- s->capability = 0x8086a001ULL;
- s->capability |= (s->num_timers - 1) << HPET_ID_NUM_TIM_SHIFT;
- s->capability |= ((HPET_CLK_PERIOD) << 32);
s->config = 0ULL;
if (count > 0) {
/* we don't enable pit when hpet_reset is first called (by hpet_init)
@@ -696,6 +692,11 @@ static int hpet_init(SysBusDevice *dev)
timer->state = s;
}
+ /* 64-bit main counter; LegacyReplacementRoute. */
+ s->capability = 0x8086a001ULL;
+ s->capability |= (s->num_timers - 1) << HPET_ID_NUM_TIM_SHIFT;
+ s->capability |= ((HPET_CLK_PERIOD) << 32);
+
isa_reserve_irq(RTC_ISA_IRQ);
qdev_init_gpio_in(&dev->qdev, hpet_handle_rtc_irq, 1);
commit bd69fe8448024258d046e2a15d4cf5c498188144
Author: Kevin Wolf <kwolf at redhat.com>
Date: Fri Jun 11 10:19:41 2010 +0200
qemu-option: Fix uninitialized value in append_option_parameter
When dest is NULL, i.e. a new copy of the list is created, we don't get a
properly terminated list after the realloc. Initialize it as an empty list.
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/qemu-option.c b/qemu-option.c
index acd74f9..f884865 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -378,6 +378,7 @@ QEMUOptionParameter *append_option_parameters(QEMUOptionParameter *dest,
num_options += count_option_parameters(list);
dest = qemu_realloc(dest, (num_options + 1) * sizeof(QEMUOptionParameter));
+ dest[num_dest_options].name = NULL;
while (list && list->name) {
if (get_option_parameter(dest, list->name) == NULL) {
commit 271248886e6110b4af0545f6a2d3ef38217cd58f
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Mon Jun 14 17:05:17 2010 +0200
Change #define DEBUG to #define E1000_DEBUG in hw/e1000.c
Change #define DEBUG to #define E1000_DEBUG in hw/e1000.c to make
it possible to build QEMU with -DDEBUG
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/hw/e1000.c b/hw/e1000.c
index 96d045d..0da65f9 100644
--- a/hw/e1000.c
+++ b/hw/e1000.c
@@ -33,9 +33,9 @@
#include "e1000_hw.h"
-#define DEBUG
+#define E1000_DEBUG
-#ifdef DEBUG
+#ifdef E1000_DEBUG
enum {
DEBUG_GENERAL, DEBUG_IO, DEBUG_MMIO, DEBUG_INTERRUPT,
DEBUG_RX, DEBUG_TX, DEBUG_MDIC, DEBUG_EEPROM,
commit ac7045cff7db837cfcc552bdc0f0baa15699f21a
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Mon Jun 14 17:05:16 2010 +0200
Remove unused DEBUG defines from hw/msix.c
Remove unused DEBUG defines from hw/msix.c to avoid having anything
define the word DEBUG without any additions such as MSIX_DEBUG.
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/hw/msix.c b/hw/msix.c
index 1613bb4..d99403a 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -42,15 +42,6 @@
#define MSIX_MAX_ENTRIES 32
-#ifdef MSIX_DEBUG
-#define DEBUG(fmt, ...) \
- do { \
- fprintf(stderr, "%s: " fmt, __func__ , __VA_ARGS__); \
- } while (0)
-#else
-#define DEBUG(fmt, ...) do { } while(0)
-#endif
-
/* Flag for interrupt controller to declare MSI-X support */
int msix_supported;
commit a4673e276248ada38f40d39191a197e7e35d3f8b
Merge: a2da039... 653dbec...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date: Mon Jun 14 10:33:36 2010 -0500
Merge remote branch 'kwolf/for-anthony' into staging
Conflicts:
hw/pc.c
diff --cc hw/pc.c
index 1491129,6e7c468..0f7d330
--- a/hw/pc.c
+++ b/hw/pc.c
@@@ -35,7 -35,7 +35,8 @@@
#include "elf.h"
#include "multiboot.h"
#include "mc146818rtc.h"
+#include "sysbus.h"
+ #include "sysemu.h"
/* output Bochs bios info messages */
//#define DEBUG_BIOS
commit a2da0395c12bd2b26e2180d735c83988ff66a559
Merge: 0956457... 02e9591...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date: Mon Jun 14 09:39:01 2010 -0500
Merge remote branch 'qmp/for-anthony' into staging
commit 09564574b868f591fb1a9cf426f0c1d64f280431
Author: Paul Brook <paul at codesourcery.com>
Date: Sun Jun 13 23:37:31 2010 +0100
OHCI address decoding fix
Ignore high address bits when PCI memory window is not mapped on a page
boundary.
Signed-off-by: Paul Brook <paul at codesourcery.com>
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 9f80e15..c60fd8d 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1415,6 +1415,8 @@ static uint32_t ohci_mem_read(void *ptr, target_phys_addr_t addr)
OHCIState *ohci = ptr;
uint32_t retval;
+ addr &= 0xff;
+
/* Only aligned reads are allowed on OHCI */
if (addr & 3) {
fprintf(stderr, "usb-ohci: Mis-aligned read\n");
@@ -1538,6 +1540,8 @@ static void ohci_mem_write(void *ptr, target_phys_addr_t addr, uint32_t val)
{
OHCIState *ohci = ptr;
+ addr &= 0xff;
+
#ifdef TARGET_WORDS_BIGENDIAN
val = bswap32(val);
#endif
commit 11165820d194478d493d667a11ea8480ce893c70
Author: Paul Brook <paul at codesourcery.com>
Date: Sun Jun 13 19:00:50 2010 +0100
Move stdbool.h
Move inclusion of stdbool.h to common header files, instead of including
in an ad-hoc manner.
Signed-off-by: Paul Brook <paul at codesourcery.com>
diff --git a/block/blkdebug.c b/block/blkdebug.c
index 8325f75..98fed94 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -26,8 +26,6 @@
#include "block_int.h"
#include "module.h"
-#include <stdbool.h>
-
typedef struct BlkdebugVars {
int state;
diff --git a/check-qjson.c b/check-qjson.c
index 109e777..86e780c 100644
--- a/check-qjson.c
+++ b/check-qjson.c
@@ -9,7 +9,6 @@
*
*/
#include <check.h>
-#include <stdbool.h>
#include "qstring.h"
#include "qint.h"
diff --git a/dyngen-exec.h b/dyngen-exec.h
index 0700a2d..5bfef3f 100644
--- a/dyngen-exec.h
+++ b/dyngen-exec.h
@@ -31,6 +31,7 @@
host headers do not allow that. */
#include <stddef.h>
#include <stdint.h>
+#include <stdbool.h>
#ifdef __OpenBSD__
#include <sys/types.h>
diff --git a/hw/9p.h b/hw/9p.h
index 5fdd770..d9951d6 100644
--- a/hw/9p.h
+++ b/hw/9p.h
@@ -14,8 +14,6 @@
#ifndef QEMU_9P_H
#define QEMU_9P_H
-#include <stdbool.h>
-
typedef struct V9fsConf
{
/* tag name for the device */
diff --git a/hw/eepro100.c b/hw/eepro100.c
index a74d834..97afa2c 100644
--- a/hw/eepro100.c
+++ b/hw/eepro100.c
@@ -41,7 +41,6 @@
* * Wake-on-LAN is not implemented.
*/
-#include <stdbool.h> /* bool */
#include <stddef.h> /* offsetof */
#include "hw.h"
#include "pci.h"
diff --git a/hw/hw.h b/hw/hw.h
index 36be0be..a49d866 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -8,7 +8,6 @@
#include "cpu-common.h"
#endif
-#include <stdbool.h>
#include "ioport.h"
#include "irq.h"
diff --git a/hw/virtio-serial.h b/hw/virtio-serial.h
index a93b545..ff08c40 100644
--- a/hw/virtio-serial.h
+++ b/hw/virtio-serial.h
@@ -15,7 +15,6 @@
#ifndef _QEMU_VIRTIO_SERIAL_H
#define _QEMU_VIRTIO_SERIAL_H
-#include <stdbool.h>
#include "qdev.h"
#include "virtio.h"
diff --git a/hw/xenfb.c b/hw/xenfb.c
index 422cd53..da5297b 100644
--- a/hw/xenfb.c
+++ b/hw/xenfb.c
@@ -29,7 +29,6 @@
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
-#include <stdbool.h>
#include <sys/mman.h>
#include <errno.h>
#include <stdio.h>
diff --git a/json-parser.c b/json-parser.c
index b55d763..1c88ed8 100644
--- a/json-parser.c
+++ b/json-parser.c
@@ -11,7 +11,6 @@
*
*/
-#include <stdbool.h>
#include <stdarg.h>
#include "qemu-common.h"
diff --git a/kvm.h b/kvm.h
index a28e7aa..a30529c 100644
--- a/kvm.h
+++ b/kvm.h
@@ -14,7 +14,6 @@
#ifndef QEMU_KVM_H
#define QEMU_KVM_H
-#include <stdbool.h>
#include <errno.h>
#include "config-host.h"
#include "qemu-queue.h"
diff --git a/nbd.h b/nbd.h
index 5deac29..5a1fbdf 100644
--- a/nbd.h
+++ b/nbd.h
@@ -20,7 +20,6 @@
#define NBD_H
#include <sys/types.h>
-#include <stdbool.h>
#include <qemu-common.h>
#include "block_int.h"
diff --git a/net.h b/net.h
index b83f615..518cf9c 100644
--- a/net.h
+++ b/net.h
@@ -1,7 +1,6 @@
#ifndef QEMU_NET_H
#define QEMU_NET_H
-#include <stdbool.h>
#include "qemu-queue.h"
#include "qemu-common.h"
#include "qdict.h"
diff --git a/qemu-common.h b/qemu-common.h
index a4888e5..d133f35 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -26,6 +26,7 @@ typedef struct QEMUBH QEMUBH;
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
+#include <stdbool.h>
#include <string.h>
#include <strings.h>
#include <inttypes.h>
diff --git a/vnc-encoding-tight.c b/vnc-encoding-tight.c
index e8604a8..faba483 100644
--- a/vnc-encoding-tight.c
+++ b/vnc-encoding-tight.c
@@ -26,8 +26,6 @@
* THE SOFTWARE.
*/
-#include <stdbool.h>
-
#include "qdict.h"
#include "qint.h"
#include "vnc.h"
commit ea4e78e590e5dbef9c41d987d2553d752ecb49b1
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Sun Jun 13 14:15:46 2010 +0200
monitor/QMP: Drop info hpet / query-hpet
This command was of minimal use before, now it is useless as the hpet
become a qdev device and is thus easily discoverable. We should
definitely not set query-hpet in QMP's stone, and there is also no good
reason to keep it for the interactive monitor.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/QMP/vm-info b/QMP/vm-info
index b150d82..8ebaeb3 100755
--- a/QMP/vm-info
+++ b/QMP/vm-info
@@ -25,7 +25,7 @@ def main():
qemu = qmp.QEMUMonitorProtocol(argv[1])
qemu.connect()
- for cmd in [ 'version', 'hpet', 'kvm', 'status', 'uuid', 'balloon' ]:
+ for cmd in [ 'version', 'kvm', 'status', 'uuid', 'balloon' ]:
print cmd + ': ' + str(qemu.send('query-' + cmd))
if __name__ == '__main__':
diff --git a/monitor.c b/monitor.c
index 15b53b9..14f77bd 100644
--- a/monitor.c
+++ b/monitor.c
@@ -740,20 +740,6 @@ static void do_info_commands(Monitor *mon, QObject **ret_data)
*ret_data = QOBJECT(cmd_list);
}
-#if defined(TARGET_I386)
-static void do_info_hpet_print(Monitor *mon, const QObject *data)
-{
- monitor_printf(mon, "HPET is %s by QEMU\n",
- qdict_get_bool(qobject_to_qdict(data), "enabled") ?
- "enabled" : "disabled");
-}
-
-static void do_info_hpet(Monitor *mon, QObject **ret_data)
-{
- *ret_data = qobject_from_jsonf("{ 'enabled': %i }", !no_hpet);
-}
-#endif
-
static void do_info_uuid_print(Monitor *mon, const QObject *data)
{
monitor_printf(mon, "%s\n", qdict_get_str(qobject_to_qdict(data), "UUID"));
@@ -2509,14 +2495,6 @@ static const mon_cmd_t info_cmds[] = {
.help = "show the active virtual memory mappings",
.mhandler.info = mem_info,
},
- {
- .name = "hpet",
- .args_type = "",
- .params = "",
- .help = "show state of HPET",
- .user_print = do_info_hpet_print,
- .mhandler.info_new = do_info_hpet,
- },
#endif
{
.name = "jit",
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index f6a94f2..9f62b94 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -2144,27 +2144,6 @@ show the active virtual memory mappings (i386 only)
ETEXI
STEXI
- at item info hpet
-show state of HPET (i386 only)
-ETEXI
-SQMP
-query-hpet
-----------
-
-Show HPET state.
-
-Return a json-object with the following information:
-
-- "enabled": true if hpet if enabled, false otherwise (json-bool)
-
-Example:
-
--> { "execute": "query-hpet" }
-<- { "return": { "enabled": true } }
-
-EQMP
-
-STEXI
@item info jit
show dynamic compiler info
@item info kvm
commit 8caa0065b82c1a223aeaca62e7d572c89db2b6eb
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Sun Jun 13 14:15:45 2010 +0200
hpet: Add MSI support
This implements the HPET capability of routing IRQs to the front-side
bus, aka MSI support. This feature can be enabled via the qdev property
"msi" and is off by default.
Note that switching it on can cause guests (at least Linux) to use the
HPET as timer instead of the LAPIC. KVM users should recall that only
the latter is currently available as fast in-kernel model.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/hpet.c b/hw/hpet.c
index 6187e5e..93fc399 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -39,6 +39,8 @@
#define DPRINTF(...)
#endif
+#define HPET_MSI_SUPPORT 0
+
struct HPETState;
typedef struct HPETTimer { /* timers */
uint8_t tn; /*timer number*/
@@ -47,7 +49,7 @@ typedef struct HPETTimer { /* timers */
/* Memory-mapped, software visible timer registers */
uint64_t config; /* configuration/cap */
uint64_t cmp; /* comparator */
- uint64_t fsb; /* FSB route, not supported now */
+ uint64_t fsb; /* FSB route */
/* Hidden register state */
uint64_t period; /* Last value written to comparator */
uint8_t wrap_flag; /* timer pop will indicate wrap for one-shot 32-bit
@@ -59,6 +61,7 @@ typedef struct HPETState {
SysBusDevice busdev;
uint64_t hpet_offset;
qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
+ uint32_t flags;
uint8_t rtc_irq_level;
uint8_t num_timers;
HPETTimer timer[HPET_MAX_TIMERS];
@@ -80,6 +83,11 @@ static uint32_t timer_int_route(struct HPETTimer *timer)
return (timer->config & HPET_TN_INT_ROUTE_MASK) >> HPET_TN_INT_ROUTE_SHIFT;
}
+static uint32_t timer_fsb_route(HPETTimer *t)
+{
+ return t->config & HPET_TN_FSB_ENABLE;
+}
+
static uint32_t hpet_enabled(HPETState *s)
{
return s->config & HPET_CFG_ENABLE;
@@ -179,7 +187,11 @@ static void update_irq(struct HPETTimer *timer, int set)
mask = 1 << timer->tn;
if (!set || !timer_enabled(timer) || !hpet_enabled(timer->state)) {
s->isr &= ~mask;
- qemu_irq_lower(s->irqs[route]);
+ if (!timer_fsb_route(timer)) {
+ qemu_irq_lower(s->irqs[route]);
+ }
+ } else if (timer_fsb_route(timer)) {
+ stl_phys(timer->fsb >> 32, timer->fsb & 0xffffffff);
} else if (timer->config & HPET_TN_TYPE_LEVEL) {
s->isr |= mask;
qemu_irq_raise(s->irqs[route]);
@@ -216,6 +228,12 @@ static int hpet_post_load(void *opaque, int version_id)
/* Push number of timers into capability returned via HPET_ID */
s->capability &= ~HPET_ID_NUM_TIM_MASK;
s->capability |= (s->num_timers - 1) << HPET_ID_NUM_TIM_SHIFT;
+
+ /* Derive HPET_MSI_SUPPORT from the capability of the first timer. */
+ s->flags &= ~(1 << HPET_MSI_SUPPORT);
+ if (s->timer[0].config & HPET_TN_FSB_CAP) {
+ s->flags |= 1 << HPET_MSI_SUPPORT;
+ }
return 0;
}
@@ -361,6 +379,8 @@ static uint32_t hpet_ram_readl(void *opaque, target_phys_addr_t addr)
case HPET_TN_CMP + 4:
return timer->cmp >> 32;
case HPET_TN_ROUTE:
+ return timer->fsb;
+ case HPET_TN_ROUTE + 4:
return timer->fsb >> 32;
default:
DPRINTF("qemu: invalid hpet_ram_readl\n");
@@ -444,6 +464,9 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
switch ((addr - 0x100) % 0x20) {
case HPET_TN_CFG:
DPRINTF("qemu: hpet_ram_writel HPET_TN_CFG\n");
+ if (activating_bit(old_val, new_val, HPET_TN_FSB_ENABLE)) {
+ update_irq(timer, 0);
+ }
val = hpet_fixup_reg(new_val, old_val, HPET_TN_CFG_WRITE_MASK);
timer->config = (timer->config & 0xffffffff00000000ULL) | val;
if (new_val & HPET_TN_32BIT) {
@@ -501,8 +524,11 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
hpet_set_timer(timer);
}
break;
+ case HPET_TN_ROUTE:
+ timer->fsb = (timer->fsb & 0xffffffff00000000ULL) | new_val;
+ break;
case HPET_TN_ROUTE + 4:
- DPRINTF("qemu: hpet_ram_writel HPET_TN_ROUTE + 4\n");
+ timer->fsb = (new_val << 32) | (timer->fsb & 0xffffffff);
break;
default:
DPRINTF("qemu: invalid hpet_ram_writel\n");
@@ -610,7 +636,10 @@ static void hpet_reset(DeviceState *d)
hpet_del_timer(timer);
timer->cmp = ~0ULL;
- timer->config = HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP;
+ timer->config = HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP;
+ if (s->flags & (1 << HPET_MSI_SUPPORT)) {
+ timer->config |= HPET_TN_FSB_CAP;
+ }
/* advertise availability of ioapic inti2 */
timer->config |= 0x00000004ULL << 32;
timer->period = 0ULL;
@@ -686,6 +715,7 @@ static SysBusDeviceInfo hpet_device_info = {
.init = hpet_init,
.qdev.props = (Property[]) {
DEFINE_PROP_UINT8("timers", HPETState, num_timers, HPET_MIN_TIMERS),
+ DEFINE_PROP_BIT("msi", HPETState, flags, HPET_MSI_SUPPORT, false),
DEFINE_PROP_END_OF_LIST(),
},
};
diff --git a/hw/hpet_emul.h b/hw/hpet_emul.h
index e8b794c..d7bc102 100644
--- a/hw/hpet_emul.h
+++ b/hw/hpet_emul.h
@@ -46,7 +46,9 @@
#define HPET_TN_SETVAL 0x040
#define HPET_TN_32BIT 0x100
#define HPET_TN_INT_ROUTE_MASK 0x3e00
-#define HPET_TN_CFG_WRITE_MASK 0x3f4e
+#define HPET_TN_FSB_ENABLE 0x4000
+#define HPET_TN_FSB_CAP 0x8000
+#define HPET_TN_CFG_WRITE_MASK 0x7f4e
#define HPET_TN_INT_ROUTE_SHIFT 9
#define HPET_TN_INT_ROUTE_CAP_SHIFT 32
#define HPET_TN_CFG_BITS_READONLY_OR_RESERVED 0xffff80b1U
commit be4b44c59bcee4b3d63bfef137c0ac7d68ef514b
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Sun Jun 13 14:15:44 2010 +0200
hpet: Make number of timers configurable
One HPET block supports up to 32 timers. Allow to instantiate more than
the recommended and implemented minimum of 3. The number is configured
via the qdev property "timers". It is also saved/restored so that it
need not match between migration peers.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/hpet.c b/hw/hpet.c
index f24b227..6187e5e 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -60,7 +60,8 @@ typedef struct HPETState {
uint64_t hpet_offset;
qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
uint8_t rtc_irq_level;
- HPETTimer timer[HPET_NUM_TIMERS];
+ uint8_t num_timers;
+ HPETTimer timer[HPET_MAX_TIMERS];
/* Memory-mapped, software visible registers */
uint64_t capability; /* capabilities */
@@ -196,12 +197,25 @@ static void hpet_pre_save(void *opaque)
s->hpet_counter = hpet_get_ticks(s);
}
+static int hpet_pre_load(void *opaque)
+{
+ HPETState *s = opaque;
+
+ /* version 1 only supports 3, later versions will load the actual value */
+ s->num_timers = HPET_MIN_TIMERS;
+ return 0;
+}
+
static int hpet_post_load(void *opaque, int version_id)
{
HPETState *s = opaque;
/* Recalculate the offset between the main counter and guest time */
s->hpet_offset = ticks_to_ns(s->hpet_counter) - qemu_get_clock(vm_clock);
+
+ /* Push number of timers into capability returned via HPET_ID */
+ s->capability &= ~HPET_ID_NUM_TIM_MASK;
+ s->capability |= (s->num_timers - 1) << HPET_ID_NUM_TIM_SHIFT;
return 0;
}
@@ -224,17 +238,19 @@ static const VMStateDescription vmstate_hpet_timer = {
static const VMStateDescription vmstate_hpet = {
.name = "hpet",
- .version_id = 1,
+ .version_id = 2,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.pre_save = hpet_pre_save,
+ .pre_load = hpet_pre_load,
.post_load = hpet_post_load,
.fields = (VMStateField []) {
VMSTATE_UINT64(config, HPETState),
VMSTATE_UINT64(isr, HPETState),
VMSTATE_UINT64(hpet_counter, HPETState),
- VMSTATE_STRUCT_ARRAY(timer, HPETState, HPET_NUM_TIMERS, 0,
- vmstate_hpet_timer, HPETTimer),
+ VMSTATE_UINT8_V(num_timers, HPETState, 2),
+ VMSTATE_STRUCT_VARRAY_UINT8(timer, HPETState, num_timers, 0,
+ vmstate_hpet_timer, HPETTimer),
VMSTATE_END_OF_LIST()
}
};
@@ -330,7 +346,7 @@ static uint32_t hpet_ram_readl(void *opaque, target_phys_addr_t addr)
uint8_t timer_id = (addr - 0x100) / 0x20;
HPETTimer *timer = &s->timer[timer_id];
- if (timer_id > HPET_NUM_TIMERS - 1) {
+ if (timer_id > s->num_timers) {
DPRINTF("qemu: timer id out of range\n");
return 0;
}
@@ -421,7 +437,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
HPETTimer *timer = &s->timer[timer_id];
DPRINTF("qemu: hpet_ram_writel timer_id = %#x \n", timer_id);
- if (timer_id > HPET_NUM_TIMERS - 1) {
+ if (timer_id > s->num_timers) {
DPRINTF("qemu: timer id out of range\n");
return;
}
@@ -504,7 +520,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
/* Enable main counter and interrupt generation. */
s->hpet_offset =
ticks_to_ns(s->hpet_counter) - qemu_get_clock(vm_clock);
- for (i = 0; i < HPET_NUM_TIMERS; i++) {
+ for (i = 0; i < s->num_timers; i++) {
if ((&s->timer[i])->cmp != ~0ULL) {
hpet_set_timer(&s->timer[i]);
}
@@ -512,7 +528,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
} else if (deactivating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
/* Halt main counter and disable interrupt generation. */
s->hpet_counter = hpet_get_ticks(s);
- for (i = 0; i < HPET_NUM_TIMERS; i++) {
+ for (i = 0; i < s->num_timers; i++) {
hpet_del_timer(&s->timer[i]);
}
}
@@ -530,7 +546,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
break;
case HPET_STATUS:
val = new_val & s->isr;
- for (i = 0; i < HPET_NUM_TIMERS; i++) {
+ for (i = 0; i < s->num_timers; i++) {
if (val & (1 << i)) {
update_irq(&s->timer[i], 0);
}
@@ -589,7 +605,7 @@ static void hpet_reset(DeviceState *d)
int i;
static int count = 0;
- for (i = 0; i < HPET_NUM_TIMERS; i++) {
+ for (i = 0; i < s->num_timers; i++) {
HPETTimer *timer = &s->timer[i];
hpet_del_timer(timer);
@@ -603,8 +619,9 @@ static void hpet_reset(DeviceState *d)
s->hpet_counter = 0ULL;
s->hpet_offset = 0ULL;
- /* 64-bit main counter; 3 timers supported; LegacyReplacementRoute. */
- s->capability = 0x8086a201ULL;
+ /* 64-bit main counter; LegacyReplacementRoute. */
+ s->capability = 0x8086a001ULL;
+ s->capability |= (s->num_timers - 1) << HPET_ID_NUM_TIM_SHIFT;
s->capability |= ((HPET_CLK_PERIOD) << 32);
s->config = 0ULL;
if (count > 0) {
@@ -637,7 +654,13 @@ static int hpet_init(SysBusDevice *dev)
for (i = 0; i < HPET_NUM_IRQ_ROUTES; i++) {
sysbus_init_irq(dev, &s->irqs[i]);
}
- for (i = 0; i < HPET_NUM_TIMERS; i++) {
+
+ if (s->num_timers < HPET_MIN_TIMERS) {
+ s->num_timers = HPET_MIN_TIMERS;
+ } else if (s->num_timers > HPET_MAX_TIMERS) {
+ s->num_timers = HPET_MAX_TIMERS;
+ }
+ for (i = 0; i < HPET_MAX_TIMERS; i++) {
timer = &s->timer[i];
timer->qemu_timer = qemu_new_timer(vm_clock, hpet_timer, timer);
timer->tn = i;
@@ -661,6 +684,10 @@ static SysBusDeviceInfo hpet_device_info = {
.qdev.vmsd = &vmstate_hpet,
.qdev.reset = hpet_reset,
.init = hpet_init,
+ .qdev.props = (Property[]) {
+ DEFINE_PROP_UINT8("timers", HPETState, num_timers, HPET_MIN_TIMERS),
+ DEFINE_PROP_END_OF_LIST(),
+ },
};
static void hpet_register_device(void)
diff --git a/hw/hpet_emul.h b/hw/hpet_emul.h
index 9c268cc..e8b794c 100644
--- a/hw/hpet_emul.h
+++ b/hw/hpet_emul.h
@@ -17,7 +17,8 @@
#define HPET_CLK_PERIOD 10000000ULL /* 10000000 femtoseconds == 10ns*/
#define FS_PER_NS 1000000
-#define HPET_NUM_TIMERS 3
+#define HPET_MIN_TIMERS 3
+#define HPET_MAX_TIMERS 32
#define HPET_NUM_IRQ_ROUTES 32
@@ -34,6 +35,9 @@
#define HPET_TN_ROUTE 0x010
#define HPET_CFG_WRITE_MASK 0x3
+#define HPET_ID_NUM_TIM_SHIFT 8
+#define HPET_ID_NUM_TIM_MASK 0x1f00
+
#define HPET_TN_TYPE_LEVEL 0x002
#define HPET_TN_ENABLE 0x004
#define HPET_TN_PERIODIC 0x008
commit cea1adfda7cca55788fbe55107e5e7943d374065
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Sun Jun 13 14:15:43 2010 +0200
vmstate: Add VMSTATE_STRUCT_VARRAY_UINT8
Required for hpet.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/hw.h b/hw/hw.h
index fc2d184..36be0be 100644
--- a/hw/hw.h
+++ b/hw/hw.h
@@ -474,6 +474,16 @@ extern const VMStateInfo vmstate_info_unused_buffer;
.offset = vmstate_offset_array(_state, _field, _type, _num), \
}
+#define VMSTATE_STRUCT_VARRAY_UINT8(_field, _state, _field_num, _version, _vmsd, _type) { \
+ .name = (stringify(_field)), \
+ .num_offset = vmstate_offset_value(_state, _field_num, uint8_t), \
+ .version_id = (_version), \
+ .vmsd = &(_vmsd), \
+ .size = sizeof(_type), \
+ .flags = VMS_STRUCT|VMS_VARRAY_INT32, \
+ .offset = offsetof(_state, _field), \
+}
+
#define VMSTATE_STATIC_BUFFER(_field, _state, _version, _test, _start, _size) { \
.name = (stringify(_field)), \
.version_id = (_version), \
commit 22a9fe38a37efc2feb67fac533309ea219242cb5
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Sun Jun 13 14:15:42 2010 +0200
hpet: Add support for level-triggered interrupts
By implementing this feature we can also remove a nasty way to kill qemu
(by trying to enable level-triggered hpet interrupts).
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/hpet.c b/hw/hpet.c
index 59a06f6..f24b227 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -159,8 +159,10 @@ static inline uint64_t hpet_calculate_diff(HPETTimer *t, uint64_t current)
}
}
-static void update_irq(struct HPETTimer *timer)
+static void update_irq(struct HPETTimer *timer, int set)
{
+ uint64_t mask;
+ HPETState *s;
int route;
if (timer->tn <= 1 && hpet_in_legacy_mode(timer->state)) {
@@ -172,10 +174,18 @@ static void update_irq(struct HPETTimer *timer)
} else {
route = timer_int_route(timer);
}
- if (!timer_enabled(timer) || !hpet_enabled(timer->state)) {
- return;
+ s = timer->state;
+ mask = 1 << timer->tn;
+ if (!set || !timer_enabled(timer) || !hpet_enabled(timer->state)) {
+ s->isr &= ~mask;
+ qemu_irq_lower(s->irqs[route]);
+ } else if (timer->config & HPET_TN_TYPE_LEVEL) {
+ s->isr |= mask;
+ qemu_irq_raise(s->irqs[route]);
+ } else {
+ s->isr &= ~mask;
+ qemu_irq_pulse(s->irqs[route]);
}
- qemu_irq_pulse(timer->state->irqs[route]);
}
static void hpet_pre_save(void *opaque)
@@ -261,7 +271,7 @@ static void hpet_timer(void *opaque)
t->wrap_flag = 0;
}
}
- update_irq(t);
+ update_irq(t, 1);
}
static void hpet_set_timer(HPETTimer *t)
@@ -291,6 +301,7 @@ static void hpet_set_timer(HPETTimer *t)
static void hpet_del_timer(HPETTimer *t)
{
qemu_del_timer(t->qemu_timer);
+ update_irq(t, 0);
}
#ifdef HPET_DEBUG
@@ -423,10 +434,6 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
timer->cmp = (uint32_t)timer->cmp;
timer->period = (uint32_t)timer->period;
}
- if (new_val & HPET_TN_TYPE_LEVEL) {
- printf("qemu: level-triggered hpet not supported\n");
- exit (-1);
- }
if (activating_bit(old_val, new_val, HPET_TN_ENABLE)) {
hpet_set_timer(timer);
} else if (deactivating_bit(old_val, new_val, HPET_TN_ENABLE)) {
@@ -522,7 +529,12 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
DPRINTF("qemu: invalid HPET_CFG+4 write \n");
break;
case HPET_STATUS:
- /* FIXME: need to handle level-triggered interrupts */
+ val = new_val & s->isr;
+ for (i = 0; i < HPET_NUM_TIMERS; i++) {
+ if (val & (1 << i)) {
+ update_irq(&s->timer[i], 0);
+ }
+ }
break;
case HPET_COUNTER:
if (hpet_enabled(s)) {
commit b7eaa6c77c67c2f2e821a51c6b2758aa482b2d71
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Sun Jun 13 14:15:41 2010 +0200
hpet: Drop static state
Instead of keeping a static reference around, pass the state to
hpet_enabled and hpet_get_ticks. All callers now have it at hand. Will
once allow to instantiate the HPET more than a single time.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/hpet.c b/hw/hpet.c
index edfe02e..59a06f6 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -69,8 +69,6 @@ typedef struct HPETState {
uint64_t hpet_counter; /* main counter */
} HPETState;
-static HPETState *hpet_statep;
-
static uint32_t hpet_in_legacy_mode(HPETState *s)
{
return s->config & HPET_CFG_LEGACY;
@@ -81,9 +79,9 @@ static uint32_t timer_int_route(struct HPETTimer *timer)
return (timer->config & HPET_TN_INT_ROUTE_MASK) >> HPET_TN_INT_ROUTE_SHIFT;
}
-static uint32_t hpet_enabled(void)
+static uint32_t hpet_enabled(HPETState *s)
{
- return hpet_statep->config & HPET_CFG_ENABLE;
+ return s->config & HPET_CFG_ENABLE;
}
static uint32_t timer_is_periodic(HPETTimer *t)
@@ -133,9 +131,9 @@ static int deactivating_bit(uint64_t old, uint64_t new, uint64_t mask)
return ((old & mask) && !(new & mask));
}
-static uint64_t hpet_get_ticks(void)
+static uint64_t hpet_get_ticks(HPETState *s)
{
- return ns_to_ticks(qemu_get_clock(vm_clock) + hpet_statep->hpet_offset);
+ return ns_to_ticks(qemu_get_clock(vm_clock) + s->hpet_offset);
}
/*
@@ -174,7 +172,7 @@ static void update_irq(struct HPETTimer *timer)
} else {
route = timer_int_route(timer);
}
- if (!timer_enabled(timer) || !hpet_enabled()) {
+ if (!timer_enabled(timer) || !hpet_enabled(timer->state)) {
return;
}
qemu_irq_pulse(timer->state->irqs[route]);
@@ -185,7 +183,7 @@ static void hpet_pre_save(void *opaque)
HPETState *s = opaque;
/* save current counter value */
- s->hpet_counter = hpet_get_ticks();
+ s->hpet_counter = hpet_get_ticks(s);
}
static int hpet_post_load(void *opaque, int version_id)
@@ -240,7 +238,7 @@ static void hpet_timer(void *opaque)
uint64_t diff;
uint64_t period = t->period;
- uint64_t cur_tick = hpet_get_ticks();
+ uint64_t cur_tick = hpet_get_ticks(t->state);
if (timer_is_periodic(t) && period != 0) {
if (t->config & HPET_TN_32BIT) {
@@ -270,7 +268,7 @@ static void hpet_set_timer(HPETTimer *t)
{
uint64_t diff;
uint32_t wrap_diff; /* how many ticks until we wrap? */
- uint64_t cur_tick = hpet_get_ticks();
+ uint64_t cur_tick = hpet_get_ticks(t->state);
/* whenever new timer is being set up, make sure wrap_flag is 0 */
t->wrap_flag = 0;
@@ -353,16 +351,16 @@ static uint32_t hpet_ram_readl(void *opaque, target_phys_addr_t addr)
DPRINTF("qemu: invalid HPET_CFG + 4 hpet_ram_readl \n");
return 0;
case HPET_COUNTER:
- if (hpet_enabled()) {
- cur_tick = hpet_get_ticks();
+ if (hpet_enabled(s)) {
+ cur_tick = hpet_get_ticks(s);
} else {
cur_tick = s->hpet_counter;
}
DPRINTF("qemu: reading counter = %" PRIx64 "\n", cur_tick);
return cur_tick;
case HPET_COUNTER + 4:
- if (hpet_enabled()) {
- cur_tick = hpet_get_ticks();
+ if (hpet_enabled(s)) {
+ cur_tick = hpet_get_ticks(s);
} else {
cur_tick = s->hpet_counter;
}
@@ -457,7 +455,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
(timer->period & 0xffffffff00000000ULL) | new_val;
}
timer->config &= ~HPET_TN_SETVAL;
- if (hpet_enabled()) {
+ if (hpet_enabled(s)) {
hpet_set_timer(timer);
}
break;
@@ -476,7 +474,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
(timer->period & 0xffffffffULL) | new_val << 32;
}
timer->config &= ~HPET_TN_SETVAL;
- if (hpet_enabled()) {
+ if (hpet_enabled(s)) {
hpet_set_timer(timer);
}
break;
@@ -506,7 +504,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
}
} else if (deactivating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
/* Halt main counter and disable interrupt generation. */
- s->hpet_counter = hpet_get_ticks();
+ s->hpet_counter = hpet_get_ticks(s);
for (i = 0; i < HPET_NUM_TIMERS; i++) {
hpet_del_timer(&s->timer[i]);
}
@@ -527,7 +525,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
/* FIXME: need to handle level-triggered interrupts */
break;
case HPET_COUNTER:
- if (hpet_enabled()) {
+ if (hpet_enabled(s)) {
DPRINTF("qemu: Writing counter while HPET enabled!\n");
}
s->hpet_counter =
@@ -536,7 +534,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
value, s->hpet_counter);
break;
case HPET_COUNTER + 4:
- if (hpet_enabled()) {
+ if (hpet_enabled(s)) {
DPRINTF("qemu: Writing counter while HPET enabled!\n");
}
s->hpet_counter =
@@ -624,8 +622,6 @@ static int hpet_init(SysBusDevice *dev)
int i, iomemtype;
HPETTimer *timer;
- assert(!hpet_statep);
- hpet_statep = s;
for (i = 0; i < HPET_NUM_IRQ_ROUTES; i++) {
sysbus_init_irq(dev, &s->irqs[i]);
}
commit 7d932dfdc5ebc07a7bfed9c01e587c9c7e9b6e26
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Sun Jun 13 14:15:40 2010 +0200
hpet/rtc: Rework RTC IRQ replacement by HPET
Allow the intercept the RTC IRQ for the HPET legacy mode. Then push
routing to IRQ8 completely into the HPET. This allows to turn
hpet_in_legacy_mode() into a private function. Furthermore, this stops
the RTC from clearing IRQ8 even if the HPET is in control.
This patch comes with a side effect: The RTC timers will no longer be
stoppend when there is no IRQ consumer, possibly causing a minor
performance degration. But as the guest may want to redirect the RTC to
the SCI in that mode, it should normally disable unused IRQ source
anyway.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/hpet.c b/hw/hpet.c
index 041dd84..edfe02e 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -30,6 +30,7 @@
#include "qemu-timer.h"
#include "hpet_emul.h"
#include "sysbus.h"
+#include "mc146818rtc.h"
//#define HPET_DEBUG
#ifdef HPET_DEBUG
@@ -58,6 +59,7 @@ typedef struct HPETState {
SysBusDevice busdev;
uint64_t hpet_offset;
qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
+ uint8_t rtc_irq_level;
HPETTimer timer[HPET_NUM_TIMERS];
/* Memory-mapped, software visible registers */
@@ -69,12 +71,9 @@ typedef struct HPETState {
static HPETState *hpet_statep;
-uint32_t hpet_in_legacy_mode(void)
+static uint32_t hpet_in_legacy_mode(HPETState *s)
{
- if (!hpet_statep) {
- return 0;
- }
- return hpet_statep->config & HPET_CFG_LEGACY;
+ return s->config & HPET_CFG_LEGACY;
}
static uint32_t timer_int_route(struct HPETTimer *timer)
@@ -166,12 +165,12 @@ static void update_irq(struct HPETTimer *timer)
{
int route;
- if (timer->tn <= 1 && hpet_in_legacy_mode()) {
+ if (timer->tn <= 1 && hpet_in_legacy_mode(timer->state)) {
/* if LegacyReplacementRoute bit is set, HPET specification requires
* timer0 be routed to IRQ0 in NON-APIC or IRQ2 in the I/O APIC,
* timer1 be routed to IRQ8 in NON-APIC or IRQ8 in the I/O APIC.
*/
- route = (timer->tn == 0) ? 0 : 8;
+ route = (timer->tn == 0) ? 0 : RTC_ISA_IRQ;
} else {
route = timer_int_route(timer);
}
@@ -515,8 +514,10 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
/* i8254 and RTC are disabled when HPET is in legacy mode */
if (activating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
hpet_pit_disable();
+ qemu_irq_lower(s->irqs[RTC_ISA_IRQ]);
} else if (deactivating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
hpet_pit_enable();
+ qemu_set_irq(s->irqs[RTC_ISA_IRQ], s->rtc_irq_level);
}
break;
case HPET_CFG + 4:
@@ -607,6 +608,16 @@ static void hpet_reset(DeviceState *d)
count = 1;
}
+static void hpet_handle_rtc_irq(void *opaque, int n, int level)
+{
+ HPETState *s = FROM_SYSBUS(HPETState, opaque);
+
+ s->rtc_irq_level = level;
+ if (!hpet_in_legacy_mode(s)) {
+ qemu_set_irq(s->irqs[RTC_ISA_IRQ], level);
+ }
+}
+
static int hpet_init(SysBusDevice *dev)
{
HPETState *s = FROM_SYSBUS(HPETState, dev);
@@ -625,6 +636,9 @@ static int hpet_init(SysBusDevice *dev)
timer->state = s;
}
+ isa_reserve_irq(RTC_ISA_IRQ);
+ qdev_init_gpio_in(&dev->qdev, hpet_handle_rtc_irq, 1);
+
/* HPET Area */
iomemtype = cpu_register_io_memory(hpet_ram_read,
hpet_ram_write, s);
diff --git a/hw/hpet_emul.h b/hw/hpet_emul.h
index 785f850..9c268cc 100644
--- a/hw/hpet_emul.h
+++ b/hw/hpet_emul.h
@@ -47,8 +47,4 @@
#define HPET_TN_INT_ROUTE_CAP_SHIFT 32
#define HPET_TN_CFG_BITS_READONLY_OR_RESERVED 0xffff80b1U
-#if defined TARGET_I386
-extern uint32_t hpet_in_legacy_mode(void);
-#endif
-
#endif
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index c3e6a70..c3459bf 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -27,7 +27,6 @@
#include "pc.h"
#include "apic.h"
#include "isa.h"
-#include "hpet_emul.h"
#include "mc146818rtc.h"
//#define DEBUG_CMOS
@@ -101,19 +100,6 @@ typedef struct RTCState {
QEMUTimer *second_timer2;
} RTCState;
-static void rtc_irq_raise(qemu_irq irq)
-{
- /* When HPET is operating in legacy mode, RTC interrupts are disabled
- * We block qemu_irq_raise, but not qemu_irq_lower, in case legacy
- * mode is established while interrupt is raised. We want it to
- * be lowered in any case
- */
-#if defined TARGET_I386
- if (!hpet_in_legacy_mode())
-#endif
- qemu_irq_raise(irq);
-}
-
static void rtc_set_time(RTCState *s);
static void rtc_copy_date(RTCState *s);
@@ -139,7 +125,7 @@ static void rtc_coalesced_timer(void *opaque)
apic_reset_irq_delivered();
s->cmos_data[RTC_REG_C] |= 0xc0;
DPRINTF_C("cmos: injecting from timer\n");
- rtc_irq_raise(s->irq);
+ qemu_irq_raise(s->irq);
if (apic_get_irq_delivered()) {
s->irq_coalesced--;
DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
@@ -155,19 +141,10 @@ static void rtc_timer_update(RTCState *s, int64_t current_time)
{
int period_code, period;
int64_t cur_clock, next_irq_clock;
- int enable_pie;
period_code = s->cmos_data[RTC_REG_A] & 0x0f;
-#if defined TARGET_I386
- /* disable periodic timer if hpet is in legacy mode, since interrupts are
- * disabled anyway.
- */
- enable_pie = !hpet_in_legacy_mode();
-#else
- enable_pie = 1;
-#endif
if (period_code != 0
- && (((s->cmos_data[RTC_REG_B] & REG_B_PIE) && enable_pie)
+ && ((s->cmos_data[RTC_REG_B] & REG_B_PIE)
|| ((s->cmos_data[RTC_REG_B] & REG_B_SQWE) && s->sqw_irq))) {
if (period_code <= 2)
period_code += 7;
@@ -206,7 +183,7 @@ static void rtc_periodic_timer(void *opaque)
if (s->irq_reinject_on_ack_count >= RTC_REINJECT_ON_ACK_COUNT)
s->irq_reinject_on_ack_count = 0;
apic_reset_irq_delivered();
- rtc_irq_raise(s->irq);
+ qemu_irq_raise(s->irq);
if (!apic_get_irq_delivered()) {
s->irq_coalesced++;
rtc_coalesced_timer_update(s);
@@ -215,7 +192,7 @@ static void rtc_periodic_timer(void *opaque)
}
} else
#endif
- rtc_irq_raise(s->irq);
+ qemu_irq_raise(s->irq);
}
if (s->cmos_data[RTC_REG_B] & REG_B_SQWE) {
/* Not square wave at all but we don't want 2048Hz interrupts!
@@ -444,15 +421,15 @@ static void rtc_update_second2(void *opaque)
s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) {
s->cmos_data[RTC_REG_C] |= 0xa0;
- rtc_irq_raise(s->irq);
+ qemu_irq_raise(s->irq);
}
}
/* update ended interrupt */
s->cmos_data[RTC_REG_C] |= REG_C_UF;
if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
- s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
- rtc_irq_raise(s->irq);
+ s->cmos_data[RTC_REG_C] |= REG_C_IRQF;
+ qemu_irq_raise(s->irq);
}
/* clear update in progress bit */
@@ -606,9 +583,6 @@ static int rtc_initfn(ISADevice *dev)
{
RTCState *s = DO_UPCAST(RTCState, dev, dev);
int base = 0x70;
- int isairq = 8;
-
- isa_init_irq(dev, &s->irq, isairq);
s->cmos_data[RTC_REG_A] = 0x26;
s->cmos_data[RTC_REG_B] = 0x02;
@@ -638,13 +612,20 @@ static int rtc_initfn(ISADevice *dev)
return 0;
}
-ISADevice *rtc_init(int base_year)
+ISADevice *rtc_init(int base_year, qemu_irq intercept_irq)
{
ISADevice *dev;
+ RTCState *s;
dev = isa_create("mc146818rtc");
+ s = DO_UPCAST(RTCState, dev, dev);
qdev_prop_set_int32(&dev->qdev, "base_year", base_year);
qdev_init_nofail(&dev->qdev);
+ if (intercept_irq) {
+ s->irq = intercept_irq;
+ } else {
+ isa_init_irq(dev, &s->irq, RTC_ISA_IRQ);
+ }
return dev;
}
diff --git a/hw/mc146818rtc.h b/hw/mc146818rtc.h
index 6f46a68..575968c 100644
--- a/hw/mc146818rtc.h
+++ b/hw/mc146818rtc.h
@@ -3,7 +3,9 @@
#include "isa.h"
-ISADevice *rtc_init(int base_year);
+#define RTC_ISA_IRQ 8
+
+ISADevice *rtc_init(int base_year, qemu_irq intercept_irq);
void rtc_set_memory(ISADevice *dev, int addr, int val);
void rtc_set_date(ISADevice *dev, const struct tm *tm);
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index ead3a00..22db7a2 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -259,7 +259,7 @@ void mips_jazz_init (ram_addr_t ram_size,
fdctrl_init_sysbus(rc4030[1], 0, 0x80003000, fds);
/* Real time clock */
- rtc_init(1980);
+ rtc_init(1980, NULL);
s_rtc = cpu_register_io_memory(rtc_read, rtc_write, NULL);
cpu_register_physical_memory(0x80004000, 0x00001000, s_rtc);
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index a8f9d15..23de7f0 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -959,7 +959,7 @@ void mips_malta_init (ram_addr_t ram_size,
/* Super I/O */
isa_dev = isa_create_simple("i8042");
- rtc_state = rtc_init(2000);
+ rtc_state = rtc_init(2000, NULL);
serial_isa_init(0, serial_hds[0]);
serial_isa_init(1, serial_hds[1]);
if (parallel_hds[0])
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
index f1fcfcd..5a96dea 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -267,7 +267,7 @@ void mips_r4k_init (ram_addr_t ram_size,
isa_bus_new(NULL);
isa_bus_irqs(i8259);
- rtc_state = rtc_init(2000);
+ rtc_state = rtc_init(2000, NULL);
/* Register 64 KB of ISA IO space at 0x14000000 */
#ifdef TARGET_WORDS_BIGENDIAN
diff --git a/hw/pc.c b/hw/pc.c
index ae31e2e..1491129 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -943,6 +943,7 @@ void pc_basic_device_init(qemu_irq *isa_irq,
int i;
DriveInfo *fd[MAX_FD];
PITState *pit;
+ qemu_irq rtc_irq = NULL;
qemu_irq *a20_line;
ISADevice *i8042;
qemu_irq *cpu_exit_irq;
@@ -951,19 +952,20 @@ void pc_basic_device_init(qemu_irq *isa_irq,
register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
- *rtc_state = rtc_init(2000);
-
- qemu_register_boot_set(pc_boot_set, *rtc_state);
-
- pit = pit_init(0x40, isa_reserve_irq(0));
- pcspk_init(pit);
if (!no_hpet) {
DeviceState *hpet = sysbus_create_simple("hpet", HPET_BASE, NULL);
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_state = rtc_init(2000, rtc_irq);
+
+ qemu_register_boot_set(pc_boot_set, *rtc_state);
+
+ pit = pit_init(0x40, isa_reserve_irq(0));
+ pcspk_init(pit);
for(i = 0; i < MAX_SERIAL_PORTS; i++) {
if (serial_hds[i]) {
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 16c9950..bb9e15f 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -696,7 +696,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
pci_vga_init(pci_bus, 0, 0);
// openpic = openpic_init(0x00000000, 0xF0000000, 1);
// pit = pit_init(0x40, i8259[0]);
- rtc_init(2000);
+ rtc_init(2000, NULL);
if (serial_hds[0])
serial_isa_init(0, serial_hds[0]);
commit 9cec89e8db494df43faf242a5a030bc6540c89dd
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Sun Jun 13 14:15:39 2010 +0200
hpet: Start/stop timer when HPET_TN_ENABLE is modified
We have to update the qemu timer when the per-timer enable bit is
toggled, just like for HPET_CFG_ENABLE changes.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/hpet.c b/hw/hpet.c
index 6974935..041dd84 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -430,6 +430,11 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
printf("qemu: level-triggered hpet not supported\n");
exit (-1);
}
+ if (activating_bit(old_val, new_val, HPET_TN_ENABLE)) {
+ hpet_set_timer(timer);
+ } else if (deactivating_bit(old_val, new_val, HPET_TN_ENABLE)) {
+ hpet_del_timer(timer);
+ }
break;
case HPET_TN_CFG + 4: // Interrupt capabilities
DPRINTF("qemu: invalid HPET_TN_CFG+4 write\n");
commit 822557eb8ea4694d1a91b68cbf6152f5277f5599
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Sun Jun 13 14:15:38 2010 +0200
hpet: Convert to qdev
Register the HPET as a sysbus device and create it that way. As it can
route its IRQs to any ISA IRQ, we need to connect it to all 24 of them.
Once converted to qdev, we can move reset handler and vmstate
registration into its hands as well.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/hpet.c b/hw/hpet.c
index fd7a1fd..6974935 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -29,6 +29,7 @@
#include "console.h"
#include "qemu-timer.h"
#include "hpet_emul.h"
+#include "sysbus.h"
//#define HPET_DEBUG
#ifdef HPET_DEBUG
@@ -54,8 +55,9 @@ typedef struct HPETTimer { /* timers */
} HPETTimer;
typedef struct HPETState {
+ SysBusDevice busdev;
uint64_t hpet_offset;
- qemu_irq *irqs;
+ qemu_irq irqs[HPET_NUM_IRQ_ROUTES];
HPETTimer timer[HPET_NUM_TIMERS];
/* Memory-mapped, software visible registers */
@@ -565,9 +567,9 @@ static CPUWriteMemoryFunc * const hpet_ram_write[] = {
hpet_ram_writel,
};
-static void hpet_reset(void *opaque)
+static void hpet_reset(DeviceState *d)
{
- HPETState *s = opaque;
+ HPETState *s = FROM_SYSBUS(HPETState, sysbus_from_qdev(d));
int i;
static int count = 0;
@@ -600,28 +602,43 @@ static void hpet_reset(void *opaque)
count = 1;
}
-
-void hpet_init(qemu_irq *irq)
+static int hpet_init(SysBusDevice *dev)
{
+ HPETState *s = FROM_SYSBUS(HPETState, dev);
int i, iomemtype;
HPETTimer *timer;
- HPETState *s;
-
- DPRINTF ("hpet_init\n");
- s = qemu_mallocz(sizeof(HPETState));
+ assert(!hpet_statep);
hpet_statep = s;
- s->irqs = irq;
+ for (i = 0; i < HPET_NUM_IRQ_ROUTES; i++) {
+ sysbus_init_irq(dev, &s->irqs[i]);
+ }
for (i = 0; i < HPET_NUM_TIMERS; i++) {
timer = &s->timer[i];
timer->qemu_timer = qemu_new_timer(vm_clock, hpet_timer, timer);
timer->tn = i;
timer->state = s;
}
- vmstate_register(-1, &vmstate_hpet, s);
- qemu_register_reset(hpet_reset, s);
+
/* HPET Area */
iomemtype = cpu_register_io_memory(hpet_ram_read,
hpet_ram_write, s);
- cpu_register_physical_memory(HPET_BASE, 0x400, iomemtype);
+ sysbus_init_mmio(dev, 0x400, iomemtype);
+ return 0;
}
+
+static SysBusDeviceInfo hpet_device_info = {
+ .qdev.name = "hpet",
+ .qdev.size = sizeof(HPETState),
+ .qdev.no_user = 1,
+ .qdev.vmsd = &vmstate_hpet,
+ .qdev.reset = hpet_reset,
+ .init = hpet_init,
+};
+
+static void hpet_register_device(void)
+{
+ sysbus_register_withprop(&hpet_device_info);
+}
+
+device_init(hpet_register_device)
diff --git a/hw/hpet_emul.h b/hw/hpet_emul.h
index 2f5f8ba..785f850 100644
--- a/hw/hpet_emul.h
+++ b/hw/hpet_emul.h
@@ -19,6 +19,8 @@
#define FS_PER_NS 1000000
#define HPET_NUM_TIMERS 3
+#define HPET_NUM_IRQ_ROUTES 32
+
#define HPET_CFG_ENABLE 0x001
#define HPET_CFG_LEGACY 0x002
@@ -47,7 +49,6 @@
#if defined TARGET_I386
extern uint32_t hpet_in_legacy_mode(void);
-extern void hpet_init(qemu_irq *irq);
#endif
#endif
diff --git a/hw/pc.c b/hw/pc.c
index 9b85c42..ae31e2e 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -35,6 +35,7 @@
#include "elf.h"
#include "multiboot.h"
#include "mc146818rtc.h"
+#include "sysbus.h"
/* output Bochs bios info messages */
//#define DEBUG_BIOS
@@ -957,7 +958,11 @@ void pc_basic_device_init(qemu_irq *isa_irq,
pit = pit_init(0x40, isa_reserve_irq(0));
pcspk_init(pit);
if (!no_hpet) {
- hpet_init(isa_irq);
+ DeviceState *hpet = sysbus_create_simple("hpet", HPET_BASE, NULL);
+
+ for (i = 0; i < 24; i++) {
+ sysbus_connect_irq(sysbus_from_qdev(hpet), i, isa_irq[i]);
+ }
}
for(i = 0; i < MAX_SERIAL_PORTS; i++) {
commit 7afbecc9efa64a88ab6194c2cf1d6feabd03d119
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Sun Jun 13 14:15:37 2010 +0200
hpet: Move static timer field initialization
Properly initialize HPETTimer::tn and HPETTimer::state once during
hpet_init instead of (re-)writing them on every reset.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/hpet.c b/hw/hpet.c
index bcb160b..fd7a1fd 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -575,12 +575,10 @@ static void hpet_reset(void *opaque)
HPETTimer *timer = &s->timer[i];
hpet_del_timer(timer);
- timer->tn = i;
timer->cmp = ~0ULL;
timer->config = HPET_TN_PERIODIC_CAP | HPET_TN_SIZE_CAP;
/* advertise availability of ioapic inti2 */
timer->config |= 0x00000004ULL << 32;
- timer->state = s;
timer->period = 0ULL;
timer->wrap_flag = 0;
}
@@ -617,6 +615,8 @@ void hpet_init(qemu_irq *irq)
for (i = 0; i < HPET_NUM_TIMERS; i++) {
timer = &s->timer[i];
timer->qemu_timer = qemu_new_timer(vm_clock, hpet_timer, timer);
+ timer->tn = i;
+ timer->state = s;
}
vmstate_register(-1, &vmstate_hpet, s);
qemu_register_reset(hpet_reset, s);
commit ad0a655161a487007742b65d0b1b55aea8051cea
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Sun Jun 13 14:15:36 2010 +0200
hpet: Silence warning on write to running main counter
Setting the main counter while the HPET is enabled may not be a good
idea of the guest, but it is supported and should, thus, not spam the
host console with warnings.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/hpet.c b/hw/hpet.c
index 2836fb0..bcb160b 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -520,7 +520,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
break;
case HPET_COUNTER:
if (hpet_enabled()) {
- printf("qemu: Writing counter while HPET enabled!\n");
+ DPRINTF("qemu: Writing counter while HPET enabled!\n");
}
s->hpet_counter =
(s->hpet_counter & 0xffffffff00000000ULL) | value;
@@ -529,7 +529,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
break;
case HPET_COUNTER + 4:
if (hpet_enabled()) {
- printf("qemu: Writing counter while HPET enabled!\n");
+ DPRINTF("qemu: Writing counter while HPET enabled!\n");
}
s->hpet_counter =
(s->hpet_counter & 0xffffffffULL) | (((uint64_t)value) << 32);
commit 27bb0b2d6f80f058bdb6fcc8fcdfa69b0c8a6d71
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Sun Jun 13 14:15:35 2010 +0200
hpet: Coding style cleanups and some refactorings
This moves the private HPET structures into the C module, simplifies
some helper functions and fixes most coding style issues (biggest chunk
was improper switch-case indention). No functional changes.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Reviewed-by: Juan Quintela <quintela at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/hpet.c b/hw/hpet.c
index 1980906..2836fb0 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -37,21 +37,47 @@
#define DPRINTF(...)
#endif
+struct HPETState;
+typedef struct HPETTimer { /* timers */
+ uint8_t tn; /*timer number*/
+ QEMUTimer *qemu_timer;
+ struct HPETState *state;
+ /* Memory-mapped, software visible timer registers */
+ uint64_t config; /* configuration/cap */
+ uint64_t cmp; /* comparator */
+ uint64_t fsb; /* FSB route, not supported now */
+ /* Hidden register state */
+ uint64_t period; /* Last value written to comparator */
+ uint8_t wrap_flag; /* timer pop will indicate wrap for one-shot 32-bit
+ * mode. Next pop will be actual timer expiration.
+ */
+} HPETTimer;
+
+typedef struct HPETState {
+ uint64_t hpet_offset;
+ qemu_irq *irqs;
+ HPETTimer timer[HPET_NUM_TIMERS];
+
+ /* Memory-mapped, software visible registers */
+ uint64_t capability; /* capabilities */
+ uint64_t config; /* configuration */
+ uint64_t isr; /* interrupt status reg */
+ uint64_t hpet_counter; /* main counter */
+} HPETState;
+
static HPETState *hpet_statep;
uint32_t hpet_in_legacy_mode(void)
{
- if (hpet_statep)
- return hpet_statep->config & HPET_CFG_LEGACY;
- else
+ if (!hpet_statep) {
return 0;
+ }
+ return hpet_statep->config & HPET_CFG_LEGACY;
}
static uint32_t timer_int_route(struct HPETTimer *timer)
{
- uint32_t route;
- route = (timer->config & HPET_TN_INT_ROUTE_MASK) >> HPET_TN_INT_ROUTE_SHIFT;
- return route;
+ return (timer->config & HPET_TN_INT_ROUTE_MASK) >> HPET_TN_INT_ROUTE_SHIFT;
}
static uint32_t hpet_enabled(void)
@@ -108,9 +134,7 @@ static int deactivating_bit(uint64_t old, uint64_t new, uint64_t mask)
static uint64_t hpet_get_ticks(void)
{
- uint64_t ticks;
- ticks = ns_to_ticks(qemu_get_clock(vm_clock) + hpet_statep->hpet_offset);
- return ticks;
+ return ns_to_ticks(qemu_get_clock(vm_clock) + hpet_statep->hpet_offset);
}
/*
@@ -121,12 +145,14 @@ static inline uint64_t hpet_calculate_diff(HPETTimer *t, uint64_t current)
if (t->config & HPET_TN_32BIT) {
uint32_t diff, cmp;
+
cmp = (uint32_t)t->cmp;
diff = cmp - (uint32_t)current;
diff = (int32_t)diff > 0 ? diff : (uint32_t)0;
return (uint64_t)diff;
} else {
uint64_t diff, cmp;
+
cmp = t->cmp;
diff = cmp - current;
diff = (int64_t)diff > 0 ? diff : (uint64_t)0;
@@ -136,7 +162,6 @@ static inline uint64_t hpet_calculate_diff(HPETTimer *t, uint64_t current)
static void update_irq(struct HPETTimer *timer)
{
- qemu_irq irq;
int route;
if (timer->tn <= 1 && hpet_in_legacy_mode()) {
@@ -144,22 +169,20 @@ static void update_irq(struct HPETTimer *timer)
* timer0 be routed to IRQ0 in NON-APIC or IRQ2 in the I/O APIC,
* timer1 be routed to IRQ8 in NON-APIC or IRQ8 in the I/O APIC.
*/
- if (timer->tn == 0) {
- irq=timer->state->irqs[0];
- } else
- irq=timer->state->irqs[8];
+ route = (timer->tn == 0) ? 0 : 8;
} else {
- route=timer_int_route(timer);
- irq=timer->state->irqs[route];
+ route = timer_int_route(timer);
}
- if (timer_enabled(timer) && hpet_enabled()) {
- qemu_irq_pulse(irq);
+ if (!timer_enabled(timer) || !hpet_enabled()) {
+ return;
}
+ qemu_irq_pulse(timer->state->irqs[route]);
}
static void hpet_pre_save(void *opaque)
{
HPETState *s = opaque;
+
/* save current counter value */
s->hpet_counter = hpet_get_ticks();
}
@@ -212,7 +235,7 @@ static const VMStateDescription vmstate_hpet = {
*/
static void hpet_timer(void *opaque)
{
- HPETTimer *t = (HPETTimer*)opaque;
+ HPETTimer *t = opaque;
uint64_t diff;
uint64_t period = t->period;
@@ -220,20 +243,22 @@ static void hpet_timer(void *opaque)
if (timer_is_periodic(t) && period != 0) {
if (t->config & HPET_TN_32BIT) {
- while (hpet_time_after(cur_tick, t->cmp))
+ while (hpet_time_after(cur_tick, t->cmp)) {
t->cmp = (uint32_t)(t->cmp + t->period);
- } else
- while (hpet_time_after64(cur_tick, t->cmp))
+ }
+ } else {
+ while (hpet_time_after64(cur_tick, t->cmp)) {
t->cmp += period;
-
+ }
+ }
diff = hpet_calculate_diff(t, cur_tick);
- qemu_mod_timer(t->qemu_timer, qemu_get_clock(vm_clock)
- + (int64_t)ticks_to_ns(diff));
+ qemu_mod_timer(t->qemu_timer,
+ qemu_get_clock(vm_clock) + (int64_t)ticks_to_ns(diff));
} else if (t->config & HPET_TN_32BIT && !timer_is_periodic(t)) {
if (t->wrap_flag) {
diff = hpet_calculate_diff(t, cur_tick);
- qemu_mod_timer(t->qemu_timer, qemu_get_clock(vm_clock)
- + (int64_t)ticks_to_ns(diff));
+ qemu_mod_timer(t->qemu_timer, qemu_get_clock(vm_clock) +
+ (int64_t)ticks_to_ns(diff));
t->wrap_flag = 0;
}
}
@@ -260,8 +285,8 @@ static void hpet_set_timer(HPETTimer *t)
t->wrap_flag = 1;
}
}
- qemu_mod_timer(t->qemu_timer, qemu_get_clock(vm_clock)
- + (int64_t)ticks_to_ns(diff));
+ qemu_mod_timer(t->qemu_timer,
+ qemu_get_clock(vm_clock) + (int64_t)ticks_to_ns(diff));
}
static void hpet_del_timer(HPETTimer *t)
@@ -285,7 +310,7 @@ static uint32_t hpet_ram_readw(void *opaque, target_phys_addr_t addr)
static uint32_t hpet_ram_readl(void *opaque, target_phys_addr_t addr)
{
- HPETState *s = (HPETState *)opaque;
+ HPETState *s = opaque;
uint64_t cur_tick, index;
DPRINTF("qemu: Enter hpet_ram_readl at %" PRIx64 "\n", addr);
@@ -293,57 +318,60 @@ static uint32_t hpet_ram_readl(void *opaque, target_phys_addr_t addr)
/*address range of all TN regs*/
if (index >= 0x100 && index <= 0x3ff) {
uint8_t timer_id = (addr - 0x100) / 0x20;
+ HPETTimer *timer = &s->timer[timer_id];
+
if (timer_id > HPET_NUM_TIMERS - 1) {
DPRINTF("qemu: timer id out of range\n");
return 0;
}
- HPETTimer *timer = &s->timer[timer_id];
switch ((addr - 0x100) % 0x20) {
- case HPET_TN_CFG:
- return timer->config;
- case HPET_TN_CFG + 4: // Interrupt capabilities
- return timer->config >> 32;
- case HPET_TN_CMP: // comparator register
- return timer->cmp;
- case HPET_TN_CMP + 4:
- return timer->cmp >> 32;
- case HPET_TN_ROUTE:
- return timer->fsb >> 32;
- default:
- DPRINTF("qemu: invalid hpet_ram_readl\n");
- break;
+ case HPET_TN_CFG:
+ return timer->config;
+ case HPET_TN_CFG + 4: // Interrupt capabilities
+ return timer->config >> 32;
+ case HPET_TN_CMP: // comparator register
+ return timer->cmp;
+ case HPET_TN_CMP + 4:
+ return timer->cmp >> 32;
+ case HPET_TN_ROUTE:
+ return timer->fsb >> 32;
+ default:
+ DPRINTF("qemu: invalid hpet_ram_readl\n");
+ break;
}
} else {
switch (index) {
- case HPET_ID:
- return s->capability;
- case HPET_PERIOD:
- return s->capability >> 32;
- case HPET_CFG:
- return s->config;
- case HPET_CFG + 4:
- DPRINTF("qemu: invalid HPET_CFG + 4 hpet_ram_readl \n");
- return 0;
- case HPET_COUNTER:
- if (hpet_enabled())
- cur_tick = hpet_get_ticks();
- else
- cur_tick = s->hpet_counter;
- DPRINTF("qemu: reading counter = %" PRIx64 "\n", cur_tick);
- return cur_tick;
- case HPET_COUNTER + 4:
- if (hpet_enabled())
- cur_tick = hpet_get_ticks();
- else
- cur_tick = s->hpet_counter;
- DPRINTF("qemu: reading counter + 4 = %" PRIx64 "\n", cur_tick);
- return cur_tick >> 32;
- case HPET_STATUS:
- return s->isr;
- default:
- DPRINTF("qemu: invalid hpet_ram_readl\n");
- break;
+ case HPET_ID:
+ return s->capability;
+ case HPET_PERIOD:
+ return s->capability >> 32;
+ case HPET_CFG:
+ return s->config;
+ case HPET_CFG + 4:
+ DPRINTF("qemu: invalid HPET_CFG + 4 hpet_ram_readl \n");
+ return 0;
+ case HPET_COUNTER:
+ if (hpet_enabled()) {
+ cur_tick = hpet_get_ticks();
+ } else {
+ cur_tick = s->hpet_counter;
+ }
+ DPRINTF("qemu: reading counter = %" PRIx64 "\n", cur_tick);
+ return cur_tick;
+ case HPET_COUNTER + 4:
+ if (hpet_enabled()) {
+ cur_tick = hpet_get_ticks();
+ } else {
+ cur_tick = s->hpet_counter;
+ }
+ DPRINTF("qemu: reading counter + 4 = %" PRIx64 "\n", cur_tick);
+ return cur_tick >> 32;
+ case HPET_STATUS:
+ return s->isr;
+ default:
+ DPRINTF("qemu: invalid hpet_ram_readl\n");
+ break;
}
}
return 0;
@@ -369,7 +397,7 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
uint32_t value)
{
int i;
- HPETState *s = (HPETState *)opaque;
+ HPETState *s = opaque;
uint64_t old_val, new_val, val, index;
DPRINTF("qemu: Enter hpet_ram_writel at %" PRIx64 " = %#x\n", addr, value);
@@ -380,133 +408,137 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
/*address range of all TN regs*/
if (index >= 0x100 && index <= 0x3ff) {
uint8_t timer_id = (addr - 0x100) / 0x20;
- DPRINTF("qemu: hpet_ram_writel timer_id = %#x \n", timer_id);
HPETTimer *timer = &s->timer[timer_id];
+ DPRINTF("qemu: hpet_ram_writel timer_id = %#x \n", timer_id);
if (timer_id > HPET_NUM_TIMERS - 1) {
DPRINTF("qemu: timer id out of range\n");
return;
}
switch ((addr - 0x100) % 0x20) {
- case HPET_TN_CFG:
- DPRINTF("qemu: hpet_ram_writel HPET_TN_CFG\n");
- val = hpet_fixup_reg(new_val, old_val, HPET_TN_CFG_WRITE_MASK);
- timer->config = (timer->config & 0xffffffff00000000ULL) | val;
- if (new_val & HPET_TN_32BIT) {
- timer->cmp = (uint32_t)timer->cmp;
- timer->period = (uint32_t)timer->period;
- }
- if (new_val & HPET_TIMER_TYPE_LEVEL) {
- printf("qemu: level-triggered hpet not supported\n");
- exit (-1);
- }
-
- break;
- case HPET_TN_CFG + 4: // Interrupt capabilities
- DPRINTF("qemu: invalid HPET_TN_CFG+4 write\n");
- break;
- case HPET_TN_CMP: // comparator register
- DPRINTF("qemu: hpet_ram_writel HPET_TN_CMP \n");
- if (timer->config & HPET_TN_32BIT)
- new_val = (uint32_t)new_val;
- if (!timer_is_periodic(timer) ||
- (timer->config & HPET_TN_SETVAL))
- timer->cmp = (timer->cmp & 0xffffffff00000000ULL)
- | new_val;
- if (timer_is_periodic(timer)) {
- /*
- * FIXME: Clamp period to reasonable min value?
- * Clamp period to reasonable max value
- */
- new_val &= (timer->config & HPET_TN_32BIT ? ~0u : ~0ull) >> 1;
- timer->period = (timer->period & 0xffffffff00000000ULL)
- | new_val;
+ case HPET_TN_CFG:
+ DPRINTF("qemu: hpet_ram_writel HPET_TN_CFG\n");
+ val = hpet_fixup_reg(new_val, old_val, HPET_TN_CFG_WRITE_MASK);
+ timer->config = (timer->config & 0xffffffff00000000ULL) | val;
+ if (new_val & HPET_TN_32BIT) {
+ timer->cmp = (uint32_t)timer->cmp;
+ timer->period = (uint32_t)timer->period;
+ }
+ if (new_val & HPET_TN_TYPE_LEVEL) {
+ printf("qemu: level-triggered hpet not supported\n");
+ exit (-1);
+ }
+ break;
+ case HPET_TN_CFG + 4: // Interrupt capabilities
+ DPRINTF("qemu: invalid HPET_TN_CFG+4 write\n");
+ break;
+ case HPET_TN_CMP: // comparator register
+ DPRINTF("qemu: hpet_ram_writel HPET_TN_CMP \n");
+ if (timer->config & HPET_TN_32BIT) {
+ new_val = (uint32_t)new_val;
+ }
+ if (!timer_is_periodic(timer)
+ || (timer->config & HPET_TN_SETVAL)) {
+ timer->cmp = (timer->cmp & 0xffffffff00000000ULL) | new_val;
+ }
+ if (timer_is_periodic(timer)) {
+ /*
+ * FIXME: Clamp period to reasonable min value?
+ * Clamp period to reasonable max value
+ */
+ new_val &= (timer->config & HPET_TN_32BIT ? ~0u : ~0ull) >> 1;
+ timer->period =
+ (timer->period & 0xffffffff00000000ULL) | new_val;
+ }
+ timer->config &= ~HPET_TN_SETVAL;
+ if (hpet_enabled()) {
+ hpet_set_timer(timer);
+ }
+ break;
+ case HPET_TN_CMP + 4: // comparator register high order
+ DPRINTF("qemu: hpet_ram_writel HPET_TN_CMP + 4\n");
+ if (!timer_is_periodic(timer)
+ || (timer->config & HPET_TN_SETVAL)) {
+ timer->cmp = (timer->cmp & 0xffffffffULL) | new_val << 32;
+ } else {
+ /*
+ * FIXME: Clamp period to reasonable min value?
+ * Clamp period to reasonable max value
+ */
+ new_val &= (timer->config & HPET_TN_32BIT ? ~0u : ~0ull) >> 1;
+ timer->period =
+ (timer->period & 0xffffffffULL) | new_val << 32;
}
timer->config &= ~HPET_TN_SETVAL;
- if (hpet_enabled())
+ if (hpet_enabled()) {
hpet_set_timer(timer);
- break;
- case HPET_TN_CMP + 4: // comparator register high order
- DPRINTF("qemu: hpet_ram_writel HPET_TN_CMP + 4\n");
- if (!timer_is_periodic(timer) ||
- (timer->config & HPET_TN_SETVAL))
- timer->cmp = (timer->cmp & 0xffffffffULL)
- | new_val << 32;
- else {
- /*
- * FIXME: Clamp period to reasonable min value?
- * Clamp period to reasonable max value
- */
- new_val &= (timer->config
- & HPET_TN_32BIT ? ~0u : ~0ull) >> 1;
- timer->period = (timer->period & 0xffffffffULL)
- | new_val << 32;
}
- timer->config &= ~HPET_TN_SETVAL;
- if (hpet_enabled())
- hpet_set_timer(timer);
- break;
- case HPET_TN_ROUTE + 4:
- DPRINTF("qemu: hpet_ram_writel HPET_TN_ROUTE + 4\n");
- break;
- default:
- DPRINTF("qemu: invalid hpet_ram_writel\n");
break;
+ case HPET_TN_ROUTE + 4:
+ DPRINTF("qemu: hpet_ram_writel HPET_TN_ROUTE + 4\n");
+ break;
+ default:
+ DPRINTF("qemu: invalid hpet_ram_writel\n");
+ break;
}
return;
} else {
switch (index) {
- case HPET_ID:
- return;
- case HPET_CFG:
- val = hpet_fixup_reg(new_val, old_val, HPET_CFG_WRITE_MASK);
- s->config = (s->config & 0xffffffff00000000ULL) | val;
- if (activating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
- /* Enable main counter and interrupt generation. */
- s->hpet_offset = ticks_to_ns(s->hpet_counter)
- - qemu_get_clock(vm_clock);
- for (i = 0; i < HPET_NUM_TIMERS; i++)
- if ((&s->timer[i])->cmp != ~0ULL)
- hpet_set_timer(&s->timer[i]);
- }
- else if (deactivating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
- /* Halt main counter and disable interrupt generation. */
- s->hpet_counter = hpet_get_ticks();
- for (i = 0; i < HPET_NUM_TIMERS; i++)
- hpet_del_timer(&s->timer[i]);
+ case HPET_ID:
+ return;
+ case HPET_CFG:
+ val = hpet_fixup_reg(new_val, old_val, HPET_CFG_WRITE_MASK);
+ s->config = (s->config & 0xffffffff00000000ULL) | val;
+ if (activating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
+ /* Enable main counter and interrupt generation. */
+ s->hpet_offset =
+ ticks_to_ns(s->hpet_counter) - qemu_get_clock(vm_clock);
+ for (i = 0; i < HPET_NUM_TIMERS; i++) {
+ if ((&s->timer[i])->cmp != ~0ULL) {
+ hpet_set_timer(&s->timer[i]);
+ }
}
- /* i8254 and RTC are disabled when HPET is in legacy mode */
- if (activating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
- hpet_pit_disable();
- } else if (deactivating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
- hpet_pit_enable();
+ } else if (deactivating_bit(old_val, new_val, HPET_CFG_ENABLE)) {
+ /* Halt main counter and disable interrupt generation. */
+ s->hpet_counter = hpet_get_ticks();
+ for (i = 0; i < HPET_NUM_TIMERS; i++) {
+ hpet_del_timer(&s->timer[i]);
}
- break;
- case HPET_CFG + 4:
- DPRINTF("qemu: invalid HPET_CFG+4 write \n");
- break;
- case HPET_STATUS:
- /* FIXME: need to handle level-triggered interrupts */
- break;
- case HPET_COUNTER:
- if (hpet_enabled())
- printf("qemu: Writing counter while HPET enabled!\n");
- s->hpet_counter = (s->hpet_counter & 0xffffffff00000000ULL)
- | value;
- DPRINTF("qemu: HPET counter written. ctr = %#x -> %" PRIx64 "\n",
- value, s->hpet_counter);
- break;
- case HPET_COUNTER + 4:
- if (hpet_enabled())
- printf("qemu: Writing counter while HPET enabled!\n");
- s->hpet_counter = (s->hpet_counter & 0xffffffffULL)
- | (((uint64_t)value) << 32);
- DPRINTF("qemu: HPET counter + 4 written. ctr = %#x -> %" PRIx64 "\n",
- value, s->hpet_counter);
- break;
- default:
- DPRINTF("qemu: invalid hpet_ram_writel\n");
- break;
+ }
+ /* i8254 and RTC are disabled when HPET is in legacy mode */
+ if (activating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
+ hpet_pit_disable();
+ } else if (deactivating_bit(old_val, new_val, HPET_CFG_LEGACY)) {
+ hpet_pit_enable();
+ }
+ break;
+ case HPET_CFG + 4:
+ DPRINTF("qemu: invalid HPET_CFG+4 write \n");
+ break;
+ case HPET_STATUS:
+ /* FIXME: need to handle level-triggered interrupts */
+ break;
+ case HPET_COUNTER:
+ if (hpet_enabled()) {
+ printf("qemu: Writing counter while HPET enabled!\n");
+ }
+ s->hpet_counter =
+ (s->hpet_counter & 0xffffffff00000000ULL) | value;
+ DPRINTF("qemu: HPET counter written. ctr = %#x -> %" PRIx64 "\n",
+ value, s->hpet_counter);
+ break;
+ case HPET_COUNTER + 4:
+ if (hpet_enabled()) {
+ printf("qemu: Writing counter while HPET enabled!\n");
+ }
+ s->hpet_counter =
+ (s->hpet_counter & 0xffffffffULL) | (((uint64_t)value) << 32);
+ DPRINTF("qemu: HPET counter + 4 written. ctr = %#x -> %" PRIx64 "\n",
+ value, s->hpet_counter);
+ break;
+ default:
+ DPRINTF("qemu: invalid hpet_ram_writel\n");
+ break;
}
}
}
@@ -533,13 +565,15 @@ static CPUWriteMemoryFunc * const hpet_ram_write[] = {
hpet_ram_writel,
};
-static void hpet_reset(void *opaque) {
+static void hpet_reset(void *opaque)
+{
HPETState *s = opaque;
int i;
static int count = 0;
- for (i=0; i<HPET_NUM_TIMERS; i++) {
+ for (i = 0; i < HPET_NUM_TIMERS; i++) {
HPETTimer *timer = &s->timer[i];
+
hpet_del_timer(timer);
timer->tn = i;
timer->cmp = ~0ULL;
@@ -557,19 +591,22 @@ static void hpet_reset(void *opaque) {
s->capability = 0x8086a201ULL;
s->capability |= ((HPET_CLK_PERIOD) << 32);
s->config = 0ULL;
- if (count > 0)
+ if (count > 0) {
/* we don't enable pit when hpet_reset is first called (by hpet_init)
* because hpet is taking over for pit here. On subsequent invocations,
* hpet_reset is called due to system reset. At this point control must
* be returned to pit until SW reenables hpet.
*/
hpet_pit_enable();
+ }
count = 1;
}
-void hpet_init(qemu_irq *irq) {
+void hpet_init(qemu_irq *irq)
+{
int i, iomemtype;
+ HPETTimer *timer;
HPETState *s;
DPRINTF ("hpet_init\n");
@@ -577,8 +614,8 @@ void hpet_init(qemu_irq *irq) {
s = qemu_mallocz(sizeof(HPETState));
hpet_statep = s;
s->irqs = irq;
- for (i=0; i<HPET_NUM_TIMERS; i++) {
- HPETTimer *timer = &s->timer[i];
+ for (i = 0; i < HPET_NUM_TIMERS; i++) {
+ timer = &s->timer[i];
timer->qemu_timer = qemu_new_timer(vm_clock, hpet_timer, timer);
}
vmstate_register(-1, &vmstate_hpet, s);
diff --git a/hw/hpet_emul.h b/hw/hpet_emul.h
index cfd95b4..2f5f8ba 100644
--- a/hw/hpet_emul.h
+++ b/hw/hpet_emul.h
@@ -18,7 +18,6 @@
#define FS_PER_NS 1000000
#define HPET_NUM_TIMERS 3
-#define HPET_TIMER_TYPE_LEVEL 0x002
#define HPET_CFG_ENABLE 0x001
#define HPET_CFG_LEGACY 0x002
@@ -33,7 +32,7 @@
#define HPET_TN_ROUTE 0x010
#define HPET_CFG_WRITE_MASK 0x3
-
+#define HPET_TN_TYPE_LEVEL 0x002
#define HPET_TN_ENABLE 0x004
#define HPET_TN_PERIODIC 0x008
#define HPET_TN_PERIODIC_CAP 0x010
@@ -46,34 +45,6 @@
#define HPET_TN_INT_ROUTE_CAP_SHIFT 32
#define HPET_TN_CFG_BITS_READONLY_OR_RESERVED 0xffff80b1U
-struct HPETState;
-typedef struct HPETTimer { /* timers */
- uint8_t tn; /*timer number*/
- QEMUTimer *qemu_timer;
- struct HPETState *state;
- /* Memory-mapped, software visible timer registers */
- uint64_t config; /* configuration/cap */
- uint64_t cmp; /* comparator */
- uint64_t fsb; /* FSB route, not supported now */
- /* Hidden register state */
- uint64_t period; /* Last value written to comparator */
- uint8_t wrap_flag; /* timer pop will indicate wrap for one-shot 32-bit
- * mode. Next pop will be actual timer expiration.
- */
-} HPETTimer;
-
-typedef struct HPETState {
- uint64_t hpet_offset;
- qemu_irq *irqs;
- HPETTimer timer[HPET_NUM_TIMERS];
-
- /* Memory-mapped, software visible registers */
- uint64_t capability; /* capabilities */
- uint64_t config; /* configuration */
- uint64_t isr; /* interrupt status reg */
- uint64_t hpet_counter; /* main counter */
-} HPETState;
-
#if defined TARGET_I386
extern uint32_t hpet_in_legacy_mode(void);
extern void hpet_init(qemu_irq *irq);
commit 6982d6647ea98544f76d5ef40ddc23115ff44a77
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Sun Jun 13 14:15:34 2010 +0200
hpet: Catch out-of-bounds timer access
Also prevent out-of-bounds write access to the timers but don't spam the
host console if it triggers.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/hpet.c b/hw/hpet.c
index 8729fb2..1980906 100644
--- a/hw/hpet.c
+++ b/hw/hpet.c
@@ -294,7 +294,7 @@ static uint32_t hpet_ram_readl(void *opaque, target_phys_addr_t addr)
if (index >= 0x100 && index <= 0x3ff) {
uint8_t timer_id = (addr - 0x100) / 0x20;
if (timer_id > HPET_NUM_TIMERS - 1) {
- printf("qemu: timer id out of range\n");
+ DPRINTF("qemu: timer id out of range\n");
return 0;
}
HPETTimer *timer = &s->timer[timer_id];
@@ -383,6 +383,10 @@ static void hpet_ram_writel(void *opaque, target_phys_addr_t addr,
DPRINTF("qemu: hpet_ram_writel timer_id = %#x \n", timer_id);
HPETTimer *timer = &s->timer[timer_id];
+ if (timer_id > HPET_NUM_TIMERS - 1) {
+ DPRINTF("qemu: timer id out of range\n");
+ return;
+ }
switch ((addr - 0x100) % 0x20) {
case HPET_TN_CFG:
DPRINTF("qemu: hpet_ram_writel HPET_TN_CFG\n");
commit c3d96978d0faaa8e54003b45619ec0768147d168
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Fri Jun 11 22:58:29 2010 +0200
configure: Fix evaluation of config-host.mak in create_config
Only match on true dir variable assignments, avoid generating garbage
due to the "# Configured with: ..." line which may contain "*dir=" as
well.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/create_config b/create_config
index 23c0cd5..0098e68 100755
--- a/create_config
+++ b/create_config
@@ -13,7 +13,7 @@ case $line in
pkgversion=${line#*=}
echo "#define QEMU_PKGVERSION \"$pkgversion\""
;;
- prefix=* | *dir=*) # directory configuration
+ prefix=* | [a-z]*dir=*) # directory configuration
name=${line%=*}
value=${line#*=}
define_name=`echo $name | tr '[:lower:]' '[:upper:]'`
commit d66ed0eae9c82b657bf7f3ea969490ad72155734
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Sun Jun 13 12:28:21 2010 +0200
tcg-s390: correctly detect s390 with a 64-bit kernel
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/configure b/configure
index ced4d2f..c0d8aa5 100755
--- a/configure
+++ b/configure
@@ -193,6 +193,12 @@ elif check_define __mips__ ; then
cpu="mips"
elif check_define __ia64__ ; then
cpu="ia64"
+elif check_define __s390__ ; then
+ if check_define __s390x__ ; then
+ cpu="s390x"
+ else
+ cpu="s390"
+ fi
else
cpu=`uname -m`
fi
commit b0cb640ac177c94af9e43a820cbb4085ac984ca1
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sat Jun 12 05:49:30 2010 +0000
Compile OS specific files only once for all targets
OS specific files are not target dependent, so they can be compiled
once for all targets.
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/Makefile.objs b/Makefile.objs
index 27595df..2dad0f9 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -49,6 +49,8 @@ common-obj-y += $(net-obj-y)
common-obj-y += $(qobject-obj-y)
common-obj-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX))
common-obj-y += readline.o console.o cursor.o async.o qemu-error.o
+common-obj-$(CONFIG_WIN32) += os-win32.o
+common-obj-$(CONFIG_POSIX) += os-posix.o
common-obj-y += tcg-runtime.o host-utils.o
common-obj-y += irq.o ioport.o input.o
@@ -144,8 +146,6 @@ hw-obj-$(CONFIG_ECC) += ecc.o
hw-obj-$(CONFIG_NAND) += nand.o
hw-obj-$(CONFIG_PFLASH_CFI01) += pflash_cfi01.o
hw-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o
-hw-obj-$(CONFIG_WIN32) += os-win32.o
-hw-obj-$(CONFIG_POSIX) += os-posix.o
hw-obj-$(CONFIG_M48T59) += m48t59.o
hw-obj-$(CONFIG_ESCC) += escc.o
commit ce798cf2a261eaf4186f416f150b7361d395c3a5
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Thu Jun 10 11:42:31 2010 +0200
Move set_proc_name() to OS specific files.
Move handling to change process name to POSIX specific files
plus add a better error message to cover the case where the
feature isn't supported.
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Acked-by: Juan Quintela <quintela at redhat.com>
Acked-by: Richard Henderson <rth at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/os-posix.c b/os-posix.c
index 9bae8fe..804e20c 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -37,6 +37,10 @@
#include "net/slirp.h"
#include "qemu-options.h"
+#ifdef CONFIG_LINUX
+#include <sys/prctl.h>
+#endif
+
static struct passwd *user_pwd;
static const char *chroot_dir;
static int daemonize;
@@ -139,6 +143,26 @@ char *os_find_datadir(const char *argv0)
#undef SHARE_SUFFIX
#undef BUILD_SUFFIX
+void os_set_proc_name(const char *s)
+{
+#if defined(PR_SET_NAME)
+ char name[16];
+ if (!s)
+ return;
+ name[sizeof(name) - 1] = 0;
+ strncpy(name, s, sizeof(name));
+ /* Could rewrite argv[0] too, but that's a bit more complicated.
+ This simple way is enough for `top'. */
+ if (prctl(PR_SET_NAME, name)) {
+ perror("unable to change process name");
+ exit(1);
+ }
+#else
+ fprintf(stderr, "Change of process name not supported by your OS\n");
+ exit(1);
+#endif
+}
+
/*
* Parse OS specific command line options.
* return 0 if option handled, -1 otherwise
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
index cb210ba..ed5c058 100644
--- a/qemu-os-posix.h
+++ b/qemu-os-posix.h
@@ -31,6 +31,7 @@ static inline void os_host_main_loop_wait(int *timeout)
}
void os_set_line_buffering(void);
+void os_set_proc_name(const char *s);
void os_setup_signal_handling(void);
void os_daemonize(void);
void os_setup_post(void);
diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index 5a97d8d..6323f7f 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -47,5 +47,6 @@ static inline void os_daemonize(void) {}
static inline void os_setup_post(void) {}
/* Win32 doesn't support line-buffering and requires size >= 2 */
static inline void os_set_line_buffering(void) {}
+static inline void os_set_proc_name(const char *dummy) {}
#endif
diff --git a/vl.c b/vl.c
index ba23e06..9cf5334 100644
--- a/vl.c
+++ b/vl.c
@@ -59,7 +59,6 @@
#ifdef __linux__
#include <pty.h>
#include <malloc.h>
-#include <sys/prctl.h>
#include <linux/ppdev.h>
#include <linux/parport.h>
@@ -284,22 +283,6 @@ static int default_driver_check(QemuOpts *opts, void *opaque)
}
/***********************************************************/
-
-static void set_proc_name(const char *s)
-{
-#if defined(__linux__) && defined(PR_SET_NAME)
- char name[16];
- if (!s)
- return;
- name[sizeof(name) - 1] = 0;
- strncpy(name, s, sizeof(name));
- /* Could rewrite argv[0] too, but that's a bit more complicated.
- This simple way is enough for `top'. */
- prctl(PR_SET_NAME, name);
-#endif
-}
-
-/***********************************************************/
/* real time host monotonic timer */
/* compute with 96 bit intermediate result: (a*b)/c */
@@ -2988,7 +2971,7 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
p += 8;
- set_proc_name(p);
+ os_set_proc_name(p);
}
}
break;
commit 9156d76331f2d51ce5b17cc945dd97788fc64c5a
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Thu Jun 10 11:42:30 2010 +0200
Move line-buffering setup to OS specific files.
Move line-buffering setup to OS specific files.
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Acked-by: Juan Quintela <quintela at redhat.com>
Acked-by: Richard Henderson <rth at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/os-posix.c b/os-posix.c
index 3a96c91..9bae8fe 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -298,3 +298,8 @@ void os_pidfile_error(void)
} else
fprintf(stderr, "Could not acquire pid file: %s\n", strerror(errno));
}
+
+void os_set_line_buffering(void)
+{
+ setvbuf(stdout, NULL, _IOLBF, 0);
+}
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
index 8be583d..cb210ba 100644
--- a/qemu-os-posix.h
+++ b/qemu-os-posix.h
@@ -30,6 +30,7 @@ static inline void os_host_main_loop_wait(int *timeout)
{
}
+void os_set_line_buffering(void);
void os_setup_signal_handling(void);
void os_daemonize(void);
void os_setup_post(void);
diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index 39df333..5a97d8d 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -45,5 +45,7 @@ void os_host_main_loop_wait(int *timeout);
static inline void os_setup_signal_handling(void) {}
static inline void os_daemonize(void) {}
static inline void os_setup_post(void) {}
+/* Win32 doesn't support line-buffering and requires size >= 2 */
+static inline void os_set_line_buffering(void) {}
#endif
diff --git a/vl.c b/vl.c
index cadd988..ba23e06 100644
--- a/vl.c
+++ b/vl.c
@@ -3215,10 +3215,7 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
-#ifndef _WIN32
- /* Win32 doesn't support line-buffering and requires size >= 2 */
- setvbuf(stdout, NULL, _IOLBF, 0);
-#endif
+ os_set_line_buffering();
if (init_timer_alarm() < 0) {
fprintf(stderr, "could not initialize alarm timer\n");
commit e06eb601b098d9bcb32eb1ce5e00920d638c6d51
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Thu Jun 10 11:42:29 2010 +0200
Make os_change_process_uid and os_change_root os-posix.c local
os_change_process_uid() and os_change_root() are now only called
from os-posix.c, so no need to keep win32 stubs for them.
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Acked-by: Juan Quintela <quintela at redhat.com>
Acked-by: Richard Henderson <rth at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/os-posix.c b/os-posix.c
index 1672e06..3a96c91 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -169,7 +169,7 @@ void os_parse_cmd_args(int index, const char *optarg)
return;
}
-void os_change_process_uid(void)
+static void change_process_uid(void)
{
if (user_pwd) {
if (setgid(user_pwd->pw_gid) < 0) {
@@ -187,7 +187,7 @@ void os_change_process_uid(void)
}
}
-void os_change_root(void)
+static void change_root(void)
{
if (chroot_dir) {
if (chroot(chroot_dir) < 0) {
@@ -276,8 +276,8 @@ void os_setup_post(void)
exit(1);
}
- os_change_root();
- os_change_process_uid();
+ change_root();
+ change_process_uid();
if (daemonize) {
dup2(fd, 0);
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
index 9b07660..8be583d 100644
--- a/qemu-os-posix.h
+++ b/qemu-os-posix.h
@@ -31,8 +31,6 @@ static inline void os_host_main_loop_wait(int *timeout)
}
void os_setup_signal_handling(void);
-void os_change_process_uid(void);
-void os_change_root(void);
void os_daemonize(void);
void os_setup_post(void);
diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index c4aa84a..39df333 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -43,8 +43,6 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
void os_host_main_loop_wait(int *timeout);
static inline void os_setup_signal_handling(void) {}
-static inline void os_change_process_uid(void) {}
-static inline void os_change_root(void) {}
static inline void os_daemonize(void) {}
static inline void os_setup_post(void) {}
commit eb505be11b18b09c621dfb19a4e3b5f703c69eeb
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Thu Jun 10 11:42:28 2010 +0200
Move daemonize handling to OS specific files
Move daemonize handling from vl.c to OS specific files. Provide dummy
stubs for Win32.
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Acked-by: Juan Quintela <quintela at redhat.com>
Acked-by: Richard Henderson <rth at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/os-posix.c b/os-posix.c
index 6417d16..1672e06 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -39,6 +39,8 @@
static struct passwd *user_pwd;
static const char *chroot_dir;
+static int daemonize;
+static int fds[2];
void os_setup_early_signal_handling(void)
{
@@ -160,6 +162,9 @@ void os_parse_cmd_args(int index, const char *optarg)
case QEMU_OPTION_chroot:
chroot_dir = optarg;
break;
+ case QEMU_OPTION_daemonize:
+ daemonize = 1;
+ break;
}
return;
}
@@ -196,3 +201,100 @@ void os_change_root(void)
}
}
+
+void os_daemonize(void)
+{
+ if (daemonize) {
+ pid_t pid;
+
+ if (pipe(fds) == -1)
+ exit(1);
+
+ pid = fork();
+ if (pid > 0) {
+ uint8_t status;
+ ssize_t len;
+
+ close(fds[1]);
+
+ again:
+ len = read(fds[0], &status, 1);
+ if (len == -1 && (errno == EINTR))
+ goto again;
+
+ if (len != 1)
+ exit(1);
+ else if (status == 1) {
+ fprintf(stderr, "Could not acquire pidfile: %s\n", strerror(errno));
+ exit(1);
+ } else
+ exit(0);
+ } else if (pid < 0)
+ exit(1);
+
+ close(fds[0]);
+ qemu_set_cloexec(fds[1]);
+
+ setsid();
+
+ pid = fork();
+ if (pid > 0)
+ exit(0);
+ else if (pid < 0)
+ exit(1);
+
+ umask(027);
+
+ signal(SIGTSTP, SIG_IGN);
+ signal(SIGTTOU, SIG_IGN);
+ signal(SIGTTIN, SIG_IGN);
+ }
+}
+
+void os_setup_post(void)
+{
+ int fd = 0;
+
+ if (daemonize) {
+ uint8_t status = 0;
+ ssize_t len;
+
+ again1:
+ len = write(fds[1], &status, 1);
+ if (len == -1 && (errno == EINTR))
+ goto again1;
+
+ if (len != 1)
+ exit(1);
+
+ if (chdir("/")) {
+ perror("not able to chdir to /");
+ exit(1);
+ }
+ TFR(fd = qemu_open("/dev/null", O_RDWR));
+ if (fd == -1)
+ exit(1);
+ }
+
+ os_change_root();
+ os_change_process_uid();
+
+ if (daemonize) {
+ dup2(fd, 0);
+ dup2(fd, 1);
+ dup2(fd, 2);
+
+ close(fd);
+ }
+}
+
+void os_pidfile_error(void)
+{
+ if (daemonize) {
+ uint8_t status = 1;
+ if (write(fds[1], &status, 1) != 1) {
+ perror("daemonize. Writing to pipe\n");
+ }
+ } else
+ fprintf(stderr, "Could not acquire pid file: %s\n", strerror(errno));
+}
diff --git a/os-win32.c b/os-win32.c
index aefc535..d98fd77 100644
--- a/os-win32.c
+++ b/os-win32.c
@@ -214,3 +214,8 @@ void os_parse_cmd_args(int index, const char *optarg)
{
return;
}
+
+void os_pidfile_error(void)
+{
+ fprintf(stderr, "Could not acquire pid file: %s\n", strerror(errno));
+}
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
index 91c7b68..9b07660 100644
--- a/qemu-os-posix.h
+++ b/qemu-os-posix.h
@@ -33,5 +33,7 @@ static inline void os_host_main_loop_wait(int *timeout)
void os_setup_signal_handling(void);
void os_change_process_uid(void);
void os_change_root(void);
+void os_daemonize(void);
+void os_setup_post(void);
#endif
diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index e2a97d2..c4aa84a 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -45,5 +45,7 @@ void os_host_main_loop_wait(int *timeout);
static inline void os_setup_signal_handling(void) {}
static inline void os_change_process_uid(void) {}
static inline void os_change_root(void) {}
+static inline void os_daemonize(void) {}
+static inline void os_setup_post(void) {}
#endif
diff --git a/sysemu.h b/sysemu.h
index 2162b1d..346cccd 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -83,6 +83,7 @@ void do_info_slirp(Monitor *mon);
void os_setup_early_signal_handling(void);
char *os_find_datadir(const char *argv0);
void os_parse_cmd_args(int index, const char *optarg);
+void os_pidfile_error(void);
typedef enum DisplayType
{
diff --git a/vl.c b/vl.c
index a536784..cadd988 100644
--- a/vl.c
+++ b/vl.c
@@ -216,9 +216,6 @@ int no_shutdown = 0;
int cursor_hide = 1;
int graphic_rotate = 0;
uint8_t irq0override = 1;
-#ifndef _WIN32
-int daemonize = 0;
-#endif
const char *watchdog;
const char *option_rom[MAX_OPTION_ROMS];
int nb_option_roms;
@@ -2301,15 +2298,9 @@ int main(int argc, char **argv, char **envp)
const char *loadvm = NULL;
QEMUMachine *machine;
const char *cpu_model;
-#ifndef _WIN32
- int fds[2];
-#endif
int tb_size;
const char *pid_file = NULL;
const char *incoming = NULL;
-#ifndef _WIN32
- int fd = 0;
-#endif
int show_vnc_port = 0;
int defconfig = 1;
@@ -2975,11 +2966,6 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
break;
-#ifndef _WIN32
- case QEMU_OPTION_daemonize:
- daemonize = 1;
- break;
-#endif
case QEMU_OPTION_option_rom:
if (nb_option_roms >= MAX_OPTION_ROMS) {
fprintf(stderr, "Too many option ROMs\n");
@@ -3194,64 +3180,10 @@ int main(int argc, char **argv, char **envp)
}
#endif
-#ifndef _WIN32
- if (daemonize) {
- pid_t pid;
-
- if (pipe(fds) == -1)
- exit(1);
-
- pid = fork();
- if (pid > 0) {
- uint8_t status;
- ssize_t len;
-
- close(fds[1]);
-
- again:
- len = read(fds[0], &status, 1);
- if (len == -1 && (errno == EINTR))
- goto again;
-
- if (len != 1)
- exit(1);
- else if (status == 1) {
- fprintf(stderr, "Could not acquire pidfile: %s\n", strerror(errno));
- exit(1);
- } else
- exit(0);
- } else if (pid < 0)
- exit(1);
-
- close(fds[0]);
- qemu_set_cloexec(fds[1]);
-
- setsid();
-
- pid = fork();
- if (pid > 0)
- exit(0);
- else if (pid < 0)
- exit(1);
-
- umask(027);
-
- signal(SIGTSTP, SIG_IGN);
- signal(SIGTTOU, SIG_IGN);
- signal(SIGTTIN, SIG_IGN);
- }
-#endif
+ os_daemonize();
if (pid_file && qemu_create_pidfile(pid_file) != 0) {
-#ifndef _WIN32
- if (daemonize) {
- uint8_t status = 1;
- if (write(fds[1], &status, 1) != 1) {
- perror("daemonize. Writing to pipe\n");
- }
- } else
-#endif
- fprintf(stderr, "Could not acquire pid file: %s\n", strerror(errno));
+ os_pidfile_error();
exit(1);
}
@@ -3520,39 +3452,7 @@ int main(int argc, char **argv, char **envp)
vm_start();
}
-#ifndef _WIN32
- if (daemonize) {
- uint8_t status = 0;
- ssize_t len;
-
- again1:
- len = write(fds[1], &status, 1);
- if (len == -1 && (errno == EINTR))
- goto again1;
-
- if (len != 1)
- exit(1);
-
- if (chdir("/")) {
- perror("not able to chdir to /");
- exit(1);
- }
- TFR(fd = qemu_open("/dev/null", O_RDWR));
- if (fd == -1)
- exit(1);
- }
-
- os_change_root();
- os_change_process_uid();
-
- if (daemonize) {
- dup2(fd, 0);
- dup2(fd, 1);
- dup2(fd, 2);
-
- close(fd);
- }
-#endif
+ os_setup_post();
main_loop();
quit_timers();
commit 0766379d4c58c5c1edc6adc414bfb25fc979b083
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Thu Jun 10 11:42:27 2010 +0200
Move chroot handling to OS specific files.
Move chroot handling to OS specific files.
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Acked-by: Juan Quintela <quintela at redhat.com>
Acked-by: Richard Henderson <rth at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/os-posix.c b/os-posix.c
index 8b686a4..6417d16 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -38,6 +38,7 @@
#include "qemu-options.h"
static struct passwd *user_pwd;
+static const char *chroot_dir;
void os_setup_early_signal_handling(void)
{
@@ -156,6 +157,9 @@ void os_parse_cmd_args(int index, const char *optarg)
exit(1);
}
break;
+ case QEMU_OPTION_chroot:
+ chroot_dir = optarg;
+ break;
}
return;
}
@@ -177,3 +181,18 @@ void os_change_process_uid(void)
}
}
}
+
+void os_change_root(void)
+{
+ if (chroot_dir) {
+ if (chroot(chroot_dir) < 0) {
+ fprintf(stderr, "chroot failed\n");
+ exit(1);
+ }
+ if (chdir("/")) {
+ perror("not able to chdir to /");
+ exit(1);
+ }
+ }
+
+}
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
index 6d8cf79..91c7b68 100644
--- a/qemu-os-posix.h
+++ b/qemu-os-posix.h
@@ -32,5 +32,6 @@ static inline void os_host_main_loop_wait(int *timeout)
void os_setup_signal_handling(void);
void os_change_process_uid(void);
+void os_change_root(void);
#endif
diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index 70fdca5..e2a97d2 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -44,5 +44,6 @@ void os_host_main_loop_wait(int *timeout);
static inline void os_setup_signal_handling(void) {}
static inline void os_change_process_uid(void) {}
+static inline void os_change_root(void) {}
#endif
diff --git a/vl.c b/vl.c
index 723154b..a536784 100644
--- a/vl.c
+++ b/vl.c
@@ -2309,7 +2309,6 @@ int main(int argc, char **argv, char **envp)
const char *incoming = NULL;
#ifndef _WIN32
int fd = 0;
- const char *chroot_dir = NULL;
#endif
int show_vnc_port = 0;
int defconfig = 1;
@@ -3053,11 +3052,6 @@ int main(int argc, char **argv, char **envp)
default_cdrom = 0;
default_sdcard = 0;
break;
-#ifndef _WIN32
- case QEMU_OPTION_chroot:
- chroot_dir = optarg;
- break;
-#endif
case QEMU_OPTION_xen_domid:
if (!(xen_available())) {
printf("Option %s not supported for this target\n", popt->name);
@@ -3548,17 +3542,7 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
- if (chroot_dir) {
- if (chroot(chroot_dir) < 0) {
- fprintf(stderr, "chroot failed\n");
- exit(1);
- }
- if (chdir("/")) {
- perror("not able to chdir to /");
- exit(1);
- }
- }
-
+ os_change_root();
os_change_process_uid();
if (daemonize) {
commit 8847cfe8aa9d8f6b8648aafd5d929a57d836cc61
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Thu Jun 10 11:42:26 2010 +0200
Move runas handling from vl.c to OS specific files.
Move code to handle runas, ie. change of user id of QEMU process
to OS specific files and provide dummy stub for Win32.
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Acked-by: Juan Quintela <quintela at redhat.com>
Acked-by: Richard Henderson <rth at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/os-posix.c b/os-posix.c
index 0deddf3..8b686a4 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -28,6 +28,7 @@
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <pwd.h>
#include <libgen.h>
/* Needed early for CONFIG_BSD etc. */
@@ -36,6 +37,8 @@
#include "net/slirp.h"
#include "qemu-options.h"
+static struct passwd *user_pwd;
+
void os_setup_early_signal_handling(void)
{
struct sigaction act;
@@ -146,6 +149,31 @@ void os_parse_cmd_args(int index, const char *optarg)
exit(1);
break;
#endif
+ case QEMU_OPTION_runas:
+ user_pwd = getpwnam(optarg);
+ if (!user_pwd) {
+ fprintf(stderr, "User \"%s\" doesn't exist\n", optarg);
+ exit(1);
+ }
+ break;
}
return;
}
+
+void os_change_process_uid(void)
+{
+ if (user_pwd) {
+ if (setgid(user_pwd->pw_gid) < 0) {
+ fprintf(stderr, "Failed to setgid(%d)\n", user_pwd->pw_gid);
+ exit(1);
+ }
+ if (setuid(user_pwd->pw_uid) < 0) {
+ fprintf(stderr, "Failed to setuid(%d)\n", user_pwd->pw_uid);
+ exit(1);
+ }
+ if (setuid(0) != -1) {
+ fprintf(stderr, "Dropping privileges failed\n");
+ exit(1);
+ }
+ }
+}
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
index ff5adb1..6d8cf79 100644
--- a/qemu-os-posix.h
+++ b/qemu-os-posix.h
@@ -31,5 +31,6 @@ static inline void os_host_main_loop_wait(int *timeout)
}
void os_setup_signal_handling(void);
+void os_change_process_uid(void);
#endif
diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index e7e2ee3..70fdca5 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -43,5 +43,6 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
void os_host_main_loop_wait(int *timeout);
static inline void os_setup_signal_handling(void) {}
+static inline void os_change_process_uid(void) {}
#endif
diff --git a/vl.c b/vl.c
index b08b5ad..723154b 100644
--- a/vl.c
+++ b/vl.c
@@ -34,7 +34,6 @@
#ifndef _WIN32
#include <libgen.h>
-#include <pwd.h>
#include <sys/times.h>
#include <sys/wait.h>
#include <termios.h>
@@ -2310,9 +2309,7 @@ int main(int argc, char **argv, char **envp)
const char *incoming = NULL;
#ifndef _WIN32
int fd = 0;
- struct passwd *pwd = NULL;
const char *chroot_dir = NULL;
- const char *run_as = NULL;
#endif
int show_vnc_port = 0;
int defconfig = 1;
@@ -3060,9 +3057,6 @@ int main(int argc, char **argv, char **envp)
case QEMU_OPTION_chroot:
chroot_dir = optarg;
break;
- case QEMU_OPTION_runas:
- run_as = optarg;
- break;
#endif
case QEMU_OPTION_xen_domid:
if (!(xen_available())) {
@@ -3554,14 +3548,6 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
- if (run_as) {
- pwd = getpwnam(run_as);
- if (!pwd) {
- fprintf(stderr, "User \"%s\" doesn't exist\n", run_as);
- exit(1);
- }
- }
-
if (chroot_dir) {
if (chroot(chroot_dir) < 0) {
fprintf(stderr, "chroot failed\n");
@@ -3573,20 +3559,7 @@ int main(int argc, char **argv, char **envp)
}
}
- if (run_as) {
- if (setgid(pwd->pw_gid) < 0) {
- fprintf(stderr, "Failed to setgid(%d)\n", pwd->pw_gid);
- exit(1);
- }
- if (setuid(pwd->pw_uid) < 0) {
- fprintf(stderr, "Failed to setuid(%d)\n", pwd->pw_uid);
- exit(1);
- }
- if (setuid(0) != -1) {
- fprintf(stderr, "Dropping privileges failed\n");
- exit(1);
- }
- }
+ os_change_process_uid();
if (daemonize) {
dup2(fd, 0);
commit 59a5264b994343f01d19faf95c0e5df70346ded8
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Thu Jun 10 11:42:25 2010 +0200
Introduce OS specific cmdline argument handling and move SMB arg to os-posix.c
Introduce OS specific cmdline argument handling by calling
os_parse_cmd_args() at the end of switch() statement. Move option
enum to qemu-options.h and have it included from os-posix.c and
os-win32.c in addition to vl.c.
In addition move SMB argument to os-posix.c
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Acked-by: Juan Quintela <quintela at redhat.com>
Acked-by: Richard Henderson <rth at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/Makefile.objs b/Makefile.objs
index 124afe7..27595df 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -259,6 +259,8 @@ vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS)
vl.o: qemu-options.def
+os-posix.o: qemu-options.def
+os-win32.o: qemu-options.def
qemu-options.def: $(SRC_PATH)/qemu-options.hx
$(call quiet-command,sh $(SRC_PATH)/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
diff --git a/os-posix.c b/os-posix.c
index 621ad06..0deddf3 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -33,6 +33,8 @@
/* Needed early for CONFIG_BSD etc. */
#include "config-host.h"
#include "sysemu.h"
+#include "net/slirp.h"
+#include "qemu-options.h"
void os_setup_early_signal_handling(void)
{
@@ -130,3 +132,20 @@ char *os_find_datadir(const char *argv0)
}
#undef SHARE_SUFFIX
#undef BUILD_SUFFIX
+
+/*
+ * Parse OS specific command line options.
+ * return 0 if option handled, -1 otherwise
+ */
+void os_parse_cmd_args(int index, const char *optarg)
+{
+ switch (index) {
+#ifdef CONFIG_SLIRP
+ case QEMU_OPTION_smb:
+ if (net_slirp_smb(optarg) < 0)
+ exit(1);
+ break;
+#endif
+ }
+ return;
+}
diff --git a/os-win32.c b/os-win32.c
index 1758538..aefc535 100644
--- a/os-win32.c
+++ b/os-win32.c
@@ -31,6 +31,7 @@
#include <sys/time.h>
#include "config-host.h"
#include "sysemu.h"
+#include "qemu-options.h"
/***********************************************************/
/* Polling handling */
@@ -204,3 +205,12 @@ char *os_find_datadir(const char *argv0)
}
return NULL;
}
+
+/*
+ * Parse OS specific command line options.
+ * return 0 if option handled, -1 otherwise
+ */
+void os_parse_cmd_args(int index, const char *optarg)
+{
+ return;
+}
diff --git a/qemu-options.h b/qemu-options.h
new file mode 100644
index 0000000..c96f994
--- /dev/null
+++ b/qemu-options.h
@@ -0,0 +1,41 @@
+/*
+ * qemu-options.h
+ *
+ * Defines needed for command line argument processing.
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ * Copyright (c) 2010 Jes Sorensen <Jes.Sorensen at redhat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef _QEMU_OPTIONS_H_
+#define _QEMU_OPTIONS_H_
+
+enum {
+#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask) \
+ opt_enum,
+#define DEFHEADING(text)
+#include "qemu-options.def"
+#undef DEF
+#undef DEFHEADING
+#undef GEN_DOCS
+};
+
+#endif
diff --git a/sysemu.h b/sysemu.h
index 72f3734..2162b1d 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -82,6 +82,7 @@ void do_info_slirp(Monitor *mon);
/* OS specific functions */
void os_setup_early_signal_handling(void);
char *os_find_datadir(const char *argv0);
+void os_parse_cmd_args(int index, const char *optarg);
typedef enum DisplayType
{
diff --git a/vl.c b/vl.c
index 4998e87..b08b5ad 100644
--- a/vl.c
+++ b/vl.c
@@ -148,6 +148,7 @@ int main(int argc, char **argv)
#include "qemu-option.h"
#include "qemu-config.h"
#include "qemu-objects.h"
+#include "qemu-options.h"
#ifdef CONFIG_LINUX
#include "fsdev/qemu-fsdev.h"
#endif
@@ -1899,16 +1900,6 @@ static void help(int exitcode)
#define HAS_ARG 0x0001
-enum {
-#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask) \
- opt_enum,
-#define DEFHEADING(text)
-#include "qemu-options.def"
-#undef DEF
-#undef DEFHEADING
-#undef GEN_DOCS
-};
-
typedef struct QEMUOption {
const char *name;
int flags;
@@ -2624,12 +2615,6 @@ int main(int argc, char **argv, char **envp)
case QEMU_OPTION_bootp:
legacy_bootp_filename = optarg;
break;
-#ifndef _WIN32
- case QEMU_OPTION_smb:
- if (net_slirp_smb(optarg) < 0)
- exit(1);
- break;
-#endif
case QEMU_OPTION_redir:
if (net_slirp_redir(optarg) < 0)
exit(1);
@@ -3126,6 +3111,8 @@ int main(int argc, char **argv, char **envp)
fclose(fp);
break;
}
+ default:
+ os_parse_cmd_args(popt->index, optarg);
}
}
}
commit 9f16732a062fc7a3ffc5909dc681f05455cfdabc
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Thu Jun 10 11:42:24 2010 +0200
Rename qemu-options.h to qemu-options.def
Rename qemu-options.h to qemu-options.def as it is not a header file
for general use and this leaves space for a proper qemu-options.h
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Acked-by: Juan Quintela <quintela at redhat.com>
Acked-by: Richard Henderson <rth at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/Makefile.objs b/Makefile.objs
index 2d94677..124afe7 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -258,8 +258,8 @@ vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS)
-vl.o: qemu-options.h
+vl.o: qemu-options.def
-qemu-options.h: $(SRC_PATH)/qemu-options.hx
+qemu-options.def: $(SRC_PATH)/qemu-options.hx
$(call quiet-command,sh $(SRC_PATH)/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
diff --git a/vl.c b/vl.c
index 484cc44..4998e87 100644
--- a/vl.c
+++ b/vl.c
@@ -1875,7 +1875,7 @@ static void help(int exitcode)
#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask) \
opt_help
#define DEFHEADING(text) stringify(text) "\n"
-#include "qemu-options.h"
+#include "qemu-options.def"
#undef DEF
#undef DEFHEADING
#undef GEN_DOCS
@@ -1903,7 +1903,7 @@ enum {
#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask) \
opt_enum,
#define DEFHEADING(text)
-#include "qemu-options.h"
+#include "qemu-options.def"
#undef DEF
#undef DEFHEADING
#undef GEN_DOCS
@@ -1921,7 +1921,7 @@ static const QEMUOption qemu_options[] = {
#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask) \
{ option, opt_arg, opt_enum, arch_mask },
#define DEFHEADING(text)
-#include "qemu-options.h"
+#include "qemu-options.def"
#undef DEF
#undef DEFHEADING
#undef GEN_DOCS
commit 6170540b824635a29eb7a0360affac9394c84c52
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Thu Jun 10 11:42:23 2010 +0200
Move find_datadir to OS specific files.
This moves the win32 and POSIX versions of find_datadir() to OS
specific files, and removes some #ifdef clutter from vl.c
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Acked-by: Juan Quintela <quintela at redhat.com>
Acked-by: Richard Henderson <rth at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/os-posix.c b/os-posix.c
index 01dbec2..621ad06 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -28,6 +28,7 @@
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <libgen.h>
/* Needed early for CONFIG_BSD etc. */
#include "config-host.h"
@@ -66,3 +67,66 @@ void os_setup_signal_handling(void)
act.sa_flags = SA_NOCLDSTOP;
sigaction(SIGCHLD, &act, NULL);
}
+
+/* Find a likely location for support files using the location of the binary.
+ For installed binaries this will be "$bindir/../share/qemu". When
+ running from the build tree this will be "$bindir/../pc-bios". */
+#define SHARE_SUFFIX "/share/qemu"
+#define BUILD_SUFFIX "/pc-bios"
+char *os_find_datadir(const char *argv0)
+{
+ char *dir;
+ char *p = NULL;
+ char *res;
+ char buf[PATH_MAX];
+ size_t max_len;
+
+#if defined(__linux__)
+ {
+ int len;
+ len = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
+ if (len > 0) {
+ buf[len] = 0;
+ p = buf;
+ }
+ }
+#elif defined(__FreeBSD__)
+ {
+ static int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
+ size_t len = sizeof(buf) - 1;
+
+ *buf = '\0';
+ if (!sysctl(mib, sizeof(mib)/sizeof(*mib), buf, &len, NULL, 0) &&
+ *buf) {
+ buf[sizeof(buf) - 1] = '\0';
+ p = buf;
+ }
+ }
+#endif
+ /* If we don't have any way of figuring out the actual executable
+ location then try argv[0]. */
+ if (!p) {
+ p = realpath(argv0, buf);
+ if (!p) {
+ return NULL;
+ }
+ }
+ dir = dirname(p);
+ dir = dirname(dir);
+
+ max_len = strlen(dir) +
+ MAX(strlen(SHARE_SUFFIX), strlen(BUILD_SUFFIX)) + 1;
+ res = qemu_mallocz(max_len);
+ snprintf(res, max_len, "%s%s", dir, SHARE_SUFFIX);
+ if (access(res, R_OK)) {
+ snprintf(res, max_len, "%s%s", dir, BUILD_SUFFIX);
+ if (access(res, R_OK)) {
+ qemu_free(res);
+ res = NULL;
+ }
+ }
+
+ return res;
+}
+#undef SHARE_SUFFIX
+#undef BUILD_SUFFIX
diff --git a/os-win32.c b/os-win32.c
index a936f7a..1758538 100644
--- a/os-win32.c
+++ b/os-win32.c
@@ -181,3 +181,26 @@ void os_setup_early_signal_handling(void)
}
}
}
+
+/* Look for support files in the same directory as the executable. */
+char *os_find_datadir(const char *argv0)
+{
+ char *p;
+ char buf[MAX_PATH];
+ DWORD len;
+
+ len = GetModuleFileName(NULL, buf, sizeof(buf) - 1);
+ if (len == 0) {
+ return NULL;
+ }
+
+ buf[len] = 0;
+ p = buf + len - 1;
+ while (p != buf && *p != '\\')
+ p--;
+ *p = 0;
+ if (access(buf, R_OK) == 0) {
+ return qemu_strdup(buf);
+ }
+ return NULL;
+}
diff --git a/sysemu.h b/sysemu.h
index bb05cf4..72f3734 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -79,7 +79,9 @@ int qemu_loadvm_state(QEMUFile *f);
/* SLIRP */
void do_info_slirp(Monitor *mon);
+/* OS specific functions */
void os_setup_early_signal_handling(void);
+char *os_find_datadir(const char *argv0);
typedef enum DisplayType
{
diff --git a/vl.c b/vl.c
index 807da7b..484cc44 100644
--- a/vl.c
+++ b/vl.c
@@ -1986,95 +1986,6 @@ static int balloon_parse(const char *arg)
return -1;
}
-#ifdef _WIN32
-/* Look for support files in the same directory as the executable. */
-static char *find_datadir(const char *argv0)
-{
- char *p;
- char buf[MAX_PATH];
- DWORD len;
-
- len = GetModuleFileName(NULL, buf, sizeof(buf) - 1);
- if (len == 0) {
- return NULL;
- }
-
- buf[len] = 0;
- p = buf + len - 1;
- while (p != buf && *p != '\\')
- p--;
- *p = 0;
- if (access(buf, R_OK) == 0) {
- return qemu_strdup(buf);
- }
- return NULL;
-}
-#else /* !_WIN32 */
-
-/* Find a likely location for support files using the location of the binary.
- For installed binaries this will be "$bindir/../share/qemu". When
- running from the build tree this will be "$bindir/../pc-bios". */
-#define SHARE_SUFFIX "/share/qemu"
-#define BUILD_SUFFIX "/pc-bios"
-static char *find_datadir(const char *argv0)
-{
- char *dir;
- char *p = NULL;
- char *res;
- char buf[PATH_MAX];
- size_t max_len;
-
-#if defined(__linux__)
- {
- int len;
- len = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
- if (len > 0) {
- buf[len] = 0;
- p = buf;
- }
- }
-#elif defined(__FreeBSD__)
- {
- static int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
- size_t len = sizeof(buf) - 1;
-
- *buf = '\0';
- if (!sysctl(mib, sizeof(mib)/sizeof(*mib), buf, &len, NULL, 0) &&
- *buf) {
- buf[sizeof(buf) - 1] = '\0';
- p = buf;
- }
- }
-#endif
- /* If we don't have any way of figuring out the actual executable
- location then try argv[0]. */
- if (!p) {
- p = realpath(argv0, buf);
- if (!p) {
- return NULL;
- }
- }
- dir = dirname(p);
- dir = dirname(dir);
-
- max_len = strlen(dir) +
- MAX(strlen(SHARE_SUFFIX), strlen(BUILD_SUFFIX)) + 1;
- res = qemu_mallocz(max_len);
- snprintf(res, max_len, "%s%s", dir, SHARE_SUFFIX);
- if (access(res, R_OK)) {
- snprintf(res, max_len, "%s%s", dir, BUILD_SUFFIX);
- if (access(res, R_OK)) {
- qemu_free(res);
- res = NULL;
- }
- }
-
- return res;
-}
-#undef SHARE_SUFFIX
-#undef BUILD_SUFFIX
-#endif
-
char *qemu_find_file(int type, const char *name)
{
int len;
@@ -3223,7 +3134,7 @@ int main(int argc, char **argv, char **envp)
/* If no data_dir is specified then try to find it relative to the
executable path. */
if (!data_dir) {
- data_dir = find_datadir(argv[0]);
+ data_dir = os_find_datadir(argv[0]);
}
/* If all else fails use the install patch specified when building. */
if (!data_dir) {
commit 8d963e6ae700b2a46dd3a2bde5d1e5f925702f47
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Thu Jun 10 11:42:22 2010 +0200
Move main signal handler setup to os specificfiles.
Move main signal handler setup to os specific files.
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Acked-by: Juan Quintela <quintela at redhat.com>
Acked-by: Richard Henderson <rth at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/os-posix.c b/os-posix.c
index 948f662..01dbec2 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -26,6 +26,8 @@
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
/* Needed early for CONFIG_BSD etc. */
#include "config-host.h"
@@ -39,3 +41,28 @@ void os_setup_early_signal_handling(void)
act.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &act, NULL);
}
+
+static void termsig_handler(int signal)
+{
+ qemu_system_shutdown_request();
+}
+
+static void sigchld_handler(int signal)
+{
+ waitpid(-1, NULL, WNOHANG);
+}
+
+void os_setup_signal_handling(void)
+{
+ struct sigaction act;
+
+ memset(&act, 0, sizeof(act));
+ act.sa_handler = termsig_handler;
+ sigaction(SIGINT, &act, NULL);
+ sigaction(SIGHUP, &act, NULL);
+ sigaction(SIGTERM, &act, NULL);
+
+ act.sa_handler = sigchld_handler;
+ act.sa_flags = SA_NOCLDSTOP;
+ sigaction(SIGCHLD, &act, NULL);
+}
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
index 96d1036..ff5adb1 100644
--- a/qemu-os-posix.h
+++ b/qemu-os-posix.h
@@ -30,4 +30,6 @@ static inline void os_host_main_loop_wait(int *timeout)
{
}
+void os_setup_signal_handling(void);
+
#endif
diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index 4d1cac8..e7e2ee3 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -41,4 +41,7 @@ int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
void os_host_main_loop_wait(int *timeout);
+
+static inline void os_setup_signal_handling(void) {}
+
#endif
diff --git a/vl.c b/vl.c
index 4fcedbf..807da7b 100644
--- a/vl.c
+++ b/vl.c
@@ -1986,35 +1986,6 @@ static int balloon_parse(const char *arg)
return -1;
}
-#ifndef _WIN32
-
-static void termsig_handler(int signal)
-{
- qemu_system_shutdown_request();
-}
-
-static void sigchld_handler(int signal)
-{
- waitpid(-1, NULL, WNOHANG);
-}
-
-static void sighandler_setup(void)
-{
- struct sigaction act;
-
- memset(&act, 0, sizeof(act));
- act.sa_handler = termsig_handler;
- sigaction(SIGINT, &act, NULL);
- sigaction(SIGHUP, &act, NULL);
- sigaction(SIGTERM, &act, NULL);
-
- act.sa_handler = sigchld_handler;
- act.sa_flags = SA_NOCLDSTOP;
- sigaction(SIGCHLD, &act, NULL);
-}
-
-#endif
-
#ifdef _WIN32
/* Look for support files in the same directory as the executable. */
static char *find_datadir(const char *argv0)
@@ -3556,10 +3527,8 @@ int main(int argc, char **argv, char **envp)
cpu_synchronize_all_post_init();
-#ifndef _WIN32
/* must be after terminal init, SDL library changes signal handlers */
- sighandler_setup();
-#endif
+ os_setup_signal_handling();
set_numa_modes();
commit fe98ac146109e307d7e19486dcfebbc89259d34d
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Thu Jun 10 11:42:21 2010 +0200
Rename os_setup_signal_handling() to os_setup_early_signal_handling()
Rename os_setup_signal_handling() to os_setup_early_signal_handling()
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Acked-by: Juan Quintela <quintela at redhat.com>
Acked-by: Richard Henderson <rth at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/os-posix.c b/os-posix.c
index 914a4d1..948f662 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -31,7 +31,7 @@
#include "config-host.h"
#include "sysemu.h"
-void os_setup_signal_handling(void)
+void os_setup_early_signal_handling(void)
{
struct sigaction act;
sigfillset(&act.sa_mask);
diff --git a/os-win32.c b/os-win32.c
index dfa90bc..a936f7a 100644
--- a/os-win32.c
+++ b/os-win32.c
@@ -159,7 +159,7 @@ static BOOL WINAPI qemu_ctrl_handler(DWORD type)
return TRUE;
}
-void os_setup_signal_handling(void)
+void os_setup_early_signal_handling(void)
{
/* Note: cpu_interrupt() is currently not SMP safe, so we force
QEMU to run on a single CPU */
diff --git a/sysemu.h b/sysemu.h
index e3643ad..bb05cf4 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -79,7 +79,7 @@ int qemu_loadvm_state(QEMUFile *f);
/* SLIRP */
void do_info_slirp(Monitor *mon);
-void os_setup_signal_handling(void);
+void os_setup_early_signal_handling(void);
typedef enum DisplayType
{
diff --git a/vl.c b/vl.c
index 8638c62..4fcedbf 100644
--- a/vl.c
+++ b/vl.c
@@ -2451,7 +2451,7 @@ int main(int argc, char **argv, char **envp)
qemu_cache_utils_init(envp);
QLIST_INIT (&vm_change_state_head);
- os_setup_signal_handling();
+ os_setup_early_signal_handling();
module_call_init(MODULE_INIT_MACHINE);
machine = find_default_machine();
commit 69bd73b1b027f56ad68ac83aa5628c89fa05c10f
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Thu Jun 10 11:42:20 2010 +0200
Move win32 early signal handling setup to os_setup_signal_handling()
Move win32 early signal handling setup to os_setup_signal_handling()
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Acked-by: Juan Quintela <quintela at redhat.com>
Acked-by: Richard Henderson <rth at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/os-win32.c b/os-win32.c
index 1f7e28b..dfa90bc 100644
--- a/os-win32.c
+++ b/os-win32.c
@@ -152,3 +152,32 @@ void os_host_main_loop_wait(int *timeout)
*timeout = 0;
}
+
+static BOOL WINAPI qemu_ctrl_handler(DWORD type)
+{
+ exit(STATUS_CONTROL_C_EXIT);
+ return TRUE;
+}
+
+void os_setup_signal_handling(void)
+{
+ /* Note: cpu_interrupt() is currently not SMP safe, so we force
+ QEMU to run on a single CPU */
+ HANDLE h;
+ DWORD mask, smask;
+ int i;
+
+ SetConsoleCtrlHandler(qemu_ctrl_handler, TRUE);
+
+ h = GetCurrentProcess();
+ if (GetProcessAffinityMask(h, &mask, &smask)) {
+ for(i = 0; i < 32; i++) {
+ if (mask & (1 << i))
+ break;
+ }
+ if (i != 32) {
+ mask = 1 << i;
+ SetProcessAffinityMask(h, mask);
+ }
+ }
+}
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
index ff5adb1..96d1036 100644
--- a/qemu-os-posix.h
+++ b/qemu-os-posix.h
@@ -30,6 +30,4 @@ static inline void os_host_main_loop_wait(int *timeout)
{
}
-void os_setup_signal_handling(void);
-
#endif
diff --git a/sysemu.h b/sysemu.h
index 5e4feae..e3643ad 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -79,6 +79,8 @@ int qemu_loadvm_state(QEMUFile *f);
/* SLIRP */
void do_info_slirp(Monitor *mon);
+void os_setup_signal_handling(void);
+
typedef enum DisplayType
{
DT_DEFAULT,
diff --git a/vl.c b/vl.c
index 5640d35..8638c62 100644
--- a/vl.c
+++ b/vl.c
@@ -1986,14 +1986,6 @@ static int balloon_parse(const char *arg)
return -1;
}
-#ifdef _WIN32
-static BOOL WINAPI qemu_ctrl_handler(DWORD type)
-{
- exit(STATUS_CONTROL_C_EXIT);
- return TRUE;
-}
-#endif
-
#ifndef _WIN32
static void termsig_handler(int signal)
@@ -2459,29 +2451,7 @@ int main(int argc, char **argv, char **envp)
qemu_cache_utils_init(envp);
QLIST_INIT (&vm_change_state_head);
-#ifndef _WIN32
os_setup_signal_handling();
-#else
- SetConsoleCtrlHandler(qemu_ctrl_handler, TRUE);
- /* Note: cpu_interrupt() is currently not SMP safe, so we force
- QEMU to run on a single CPU */
- {
- HANDLE h;
- DWORD mask, smask;
- int i;
- h = GetCurrentProcess();
- if (GetProcessAffinityMask(h, &mask, &smask)) {
- for(i = 0; i < 32; i++) {
- if (mask & (1 << i))
- break;
- }
- if (i != 32) {
- mask = 1 << i;
- SetProcessAffinityMask(h, mask);
- }
- }
- }
-#endif
module_call_init(MODULE_INIT_MACHINE);
machine = find_default_machine();
commit 86b645e753b9396f8cc5b74a9eadf2d36f76ae5c
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Thu Jun 10 11:42:19 2010 +0200
Introduce os-posix.c and create os_setup_signal_handling()
Introcuce os-posix.c and move posix specific signal handling
there.
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Acked-by: Juan Quintela <quintela at redhat.com>
Acked-by: Richard Henderson <rth at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/Makefile.objs b/Makefile.objs
index 58fdb03..2d94677 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -145,6 +145,7 @@ hw-obj-$(CONFIG_NAND) += nand.o
hw-obj-$(CONFIG_PFLASH_CFI01) += pflash_cfi01.o
hw-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o
hw-obj-$(CONFIG_WIN32) += os-win32.o
+hw-obj-$(CONFIG_POSIX) += os-posix.o
hw-obj-$(CONFIG_M48T59) += m48t59.o
hw-obj-$(CONFIG_ESCC) += escc.o
diff --git a/os-posix.c b/os-posix.c
new file mode 100644
index 0000000..914a4d1
--- /dev/null
+++ b/os-posix.c
@@ -0,0 +1,41 @@
+/*
+ * os-posix.c
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ * Copyright (c) 2010 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+
+/* Needed early for CONFIG_BSD etc. */
+#include "config-host.h"
+#include "sysemu.h"
+
+void os_setup_signal_handling(void)
+{
+ struct sigaction act;
+ sigfillset(&act.sa_mask);
+ act.sa_flags = 0;
+ act.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &act, NULL);
+}
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
index 96d1036..ff5adb1 100644
--- a/qemu-os-posix.h
+++ b/qemu-os-posix.h
@@ -30,4 +30,6 @@ static inline void os_host_main_loop_wait(int *timeout)
{
}
+void os_setup_signal_handling(void);
+
#endif
diff --git a/vl.c b/vl.c
index 3bbfd22..5640d35 100644
--- a/vl.c
+++ b/vl.c
@@ -2460,13 +2460,7 @@ int main(int argc, char **argv, char **envp)
QLIST_INIT (&vm_change_state_head);
#ifndef _WIN32
- {
- struct sigaction act;
- sigfillset(&act.sa_mask);
- act.sa_flags = 0;
- act.sa_handler = SIG_IGN;
- sigaction(SIGPIPE, &act, NULL);
- }
+ os_setup_signal_handling();
#else
SetConsoleCtrlHandler(qemu_ctrl_handler, TRUE);
/* Note: cpu_interrupt() is currently not SMP safe, so we force
commit 0d93ca7c3b4c93a87723e3397daf6df2034b455a
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Thu Jun 10 11:42:18 2010 +0200
vl.c: Move host_main_loop_wait() to OS specific files.
Move host_main_loop_wait() to OS specific files. Create
qemu-os-posix.h and provide empty inline for the POSIX case.
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Acked-by: Juan Quintela <quintela at redhat.com>
Acked-by: Richard Henderson <rth at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/os-win32.c b/os-win32.c
index 5a464cc..1f7e28b 100644
--- a/os-win32.c
+++ b/os-win32.c
@@ -109,3 +109,46 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
if (found)
w->num--;
}
+
+void os_host_main_loop_wait(int *timeout)
+{
+ int ret, ret2, i;
+ PollingEntry *pe;
+
+ /* XXX: need to suppress polling by better using win32 events */
+ ret = 0;
+ for(pe = first_polling_entry; pe != NULL; pe = pe->next) {
+ ret |= pe->func(pe->opaque);
+ }
+ if (ret == 0) {
+ int err;
+ WaitObjects *w = &wait_objects;
+
+ ret = WaitForMultipleObjects(w->num, w->events, FALSE, *timeout);
+ if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
+ if (w->func[ret - WAIT_OBJECT_0])
+ w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
+
+ /* Check for additional signaled events */
+ for(i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) {
+
+ /* Check if event is signaled */
+ ret2 = WaitForSingleObject(w->events[i], 0);
+ if(ret2 == WAIT_OBJECT_0) {
+ if (w->func[i])
+ w->func[i](w->opaque[i]);
+ } else if (ret2 == WAIT_TIMEOUT) {
+ } else {
+ err = GetLastError();
+ fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err);
+ }
+ }
+ } else if (ret == WAIT_TIMEOUT) {
+ } else {
+ err = GetLastError();
+ fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err);
+ }
+ }
+
+ *timeout = 0;
+}
diff --git a/qemu-os-posix.h b/qemu-os-posix.h
new file mode 100644
index 0000000..96d1036
--- /dev/null
+++ b/qemu-os-posix.h
@@ -0,0 +1,33 @@
+/*
+ * posix specific declarations
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ * Copyright (c) 2010 Jes Sorensen <Jes.Sorensen at redhat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef QEMU_OS_POSIX_H
+#define QEMU_OS_POSIX_H
+
+static inline void os_host_main_loop_wait(int *timeout)
+{
+}
+
+#endif
diff --git a/qemu-os-win32.h b/qemu-os-win32.h
index be108ad..4d1cac8 100644
--- a/qemu-os-win32.h
+++ b/qemu-os-win32.h
@@ -40,4 +40,5 @@ typedef void WaitObjectFunc(void *opaque);
int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
+void os_host_main_loop_wait(int *timeout);
#endif
diff --git a/sysemu.h b/sysemu.h
index 13fc9a9..5e4feae 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -12,6 +12,10 @@
#include "qemu-os-win32.h"
#endif
+#ifdef CONFIG_POSIX
+#include "qemu-os-posix.h"
+#endif
+
/* vl.c */
extern const char *bios_name;
diff --git a/vl.c b/vl.c
index 73a3915..3bbfd22 100644
--- a/vl.c
+++ b/vl.c
@@ -1722,56 +1722,6 @@ void qemu_system_powerdown_request(void)
qemu_notify_event();
}
-#ifdef _WIN32
-static void host_main_loop_wait(int *timeout)
-{
- int ret, ret2, i;
- PollingEntry *pe;
-
-
- /* XXX: need to suppress polling by better using win32 events */
- ret = 0;
- for(pe = first_polling_entry; pe != NULL; pe = pe->next) {
- ret |= pe->func(pe->opaque);
- }
- if (ret == 0) {
- int err;
- WaitObjects *w = &wait_objects;
-
- ret = WaitForMultipleObjects(w->num, w->events, FALSE, *timeout);
- if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
- if (w->func[ret - WAIT_OBJECT_0])
- w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
-
- /* Check for additional signaled events */
- for(i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) {
-
- /* Check if event is signaled */
- ret2 = WaitForSingleObject(w->events[i], 0);
- if(ret2 == WAIT_OBJECT_0) {
- if (w->func[i])
- w->func[i](w->opaque[i]);
- } else if (ret2 == WAIT_TIMEOUT) {
- } else {
- err = GetLastError();
- fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err);
- }
- }
- } else if (ret == WAIT_TIMEOUT) {
- } else {
- err = GetLastError();
- fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err);
- }
- }
-
- *timeout = 0;
-}
-#else
-static void host_main_loop_wait(int *timeout)
-{
-}
-#endif
-
void main_loop_wait(int nonblocking)
{
IOHandlerRecord *ioh;
@@ -1787,7 +1737,7 @@ void main_loop_wait(int nonblocking)
qemu_bh_update_timeout(&timeout);
}
- host_main_loop_wait(&timeout);
+ os_host_main_loop_wait(&timeout);
/* poll any events */
/* XXX: separate device handlers from system ones */
commit 19113504dea4504f69d414f72f8a18d3c1a941d5
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Thu Jun 10 11:42:17 2010 +0200
Introduce os-win32.c and move polling functions from vl.c
This introduces os-win32.c. It is meant to carry win32 specific
functions thata are not relevant for all of QEMU as well as win32
versions of various pieces like signal handling etc.
Move win32 polling handler helper functions from vl.c to os-win32.c
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Acked-by: Juan Quintela <quintela at redhat.com>
Acked-by: Richard Henderson <rth at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/Makefile.objs b/Makefile.objs
index 9796dcb..58fdb03 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -144,6 +144,7 @@ hw-obj-$(CONFIG_ECC) += ecc.o
hw-obj-$(CONFIG_NAND) += nand.o
hw-obj-$(CONFIG_PFLASH_CFI01) += pflash_cfi01.o
hw-obj-$(CONFIG_PFLASH_CFI02) += pflash_cfi02.o
+hw-obj-$(CONFIG_WIN32) += os-win32.o
hw-obj-$(CONFIG_M48T59) += m48t59.o
hw-obj-$(CONFIG_ESCC) += escc.o
diff --git a/os-win32.c b/os-win32.c
new file mode 100644
index 0000000..5a464cc
--- /dev/null
+++ b/os-win32.c
@@ -0,0 +1,111 @@
+/*
+ * os-win32.c
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ * Copyright (c) 2010 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include <windows.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <time.h>
+#include <errno.h>
+#include <sys/time.h>
+#include "config-host.h"
+#include "sysemu.h"
+
+/***********************************************************/
+/* Polling handling */
+
+typedef struct PollingEntry {
+ PollingFunc *func;
+ void *opaque;
+ struct PollingEntry *next;
+} PollingEntry;
+
+static PollingEntry *first_polling_entry;
+
+int qemu_add_polling_cb(PollingFunc *func, void *opaque)
+{
+ PollingEntry **ppe, *pe;
+ pe = qemu_mallocz(sizeof(PollingEntry));
+ pe->func = func;
+ pe->opaque = opaque;
+ for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next);
+ *ppe = pe;
+ return 0;
+}
+
+void qemu_del_polling_cb(PollingFunc *func, void *opaque)
+{
+ PollingEntry **ppe, *pe;
+ for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next) {
+ pe = *ppe;
+ if (pe->func == func && pe->opaque == opaque) {
+ *ppe = pe->next;
+ qemu_free(pe);
+ break;
+ }
+ }
+}
+
+/***********************************************************/
+/* Wait objects support */
+typedef struct WaitObjects {
+ int num;
+ HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
+ WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1];
+ void *opaque[MAXIMUM_WAIT_OBJECTS + 1];
+} WaitObjects;
+
+static WaitObjects wait_objects = {0};
+
+int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
+{
+ WaitObjects *w = &wait_objects;
+
+ if (w->num >= MAXIMUM_WAIT_OBJECTS)
+ return -1;
+ w->events[w->num] = handle;
+ w->func[w->num] = func;
+ w->opaque[w->num] = opaque;
+ w->num++;
+ return 0;
+}
+
+void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
+{
+ int i, found;
+ WaitObjects *w = &wait_objects;
+
+ found = 0;
+ for (i = 0; i < w->num; i++) {
+ if (w->events[i] == handle)
+ found = 1;
+ if (found) {
+ w->events[i] = w->events[i + 1];
+ w->func[i] = w->func[i + 1];
+ w->opaque[i] = w->opaque[i + 1];
+ }
+ }
+ if (found)
+ w->num--;
+}
diff --git a/vl.c b/vl.c
index a9be190..73a3915 100644
--- a/vl.c
+++ b/vl.c
@@ -1497,86 +1497,6 @@ int qemu_set_fd_handler(int fd,
return qemu_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque);
}
-#ifdef _WIN32
-/***********************************************************/
-/* Polling handling */
-
-typedef struct PollingEntry {
- PollingFunc *func;
- void *opaque;
- struct PollingEntry *next;
-} PollingEntry;
-
-static PollingEntry *first_polling_entry;
-
-int qemu_add_polling_cb(PollingFunc *func, void *opaque)
-{
- PollingEntry **ppe, *pe;
- pe = qemu_mallocz(sizeof(PollingEntry));
- pe->func = func;
- pe->opaque = opaque;
- for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next);
- *ppe = pe;
- return 0;
-}
-
-void qemu_del_polling_cb(PollingFunc *func, void *opaque)
-{
- PollingEntry **ppe, *pe;
- for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next) {
- pe = *ppe;
- if (pe->func == func && pe->opaque == opaque) {
- *ppe = pe->next;
- qemu_free(pe);
- break;
- }
- }
-}
-
-/***********************************************************/
-/* Wait objects support */
-typedef struct WaitObjects {
- int num;
- HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
- WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1];
- void *opaque[MAXIMUM_WAIT_OBJECTS + 1];
-} WaitObjects;
-
-static WaitObjects wait_objects = {0};
-
-int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
-{
- WaitObjects *w = &wait_objects;
-
- if (w->num >= MAXIMUM_WAIT_OBJECTS)
- return -1;
- w->events[w->num] = handle;
- w->func[w->num] = func;
- w->opaque[w->num] = opaque;
- w->num++;
- return 0;
-}
-
-void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
-{
- int i, found;
- WaitObjects *w = &wait_objects;
-
- found = 0;
- for (i = 0; i < w->num; i++) {
- if (w->events[i] == handle)
- found = 1;
- if (found) {
- w->events[i] = w->events[i + 1];
- w->func[i] = w->func[i + 1];
- w->opaque[i] = w->opaque[i + 1];
- }
- }
- if (found)
- w->num--;
-}
-#endif
-
/***********************************************************/
/* machine registration */
commit 39626c037585b4ad9f83b86854ac14c9b9523db5
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Thu Jun 10 11:42:16 2010 +0200
Create qemu-os-win32.h and move WIN32 specific declarations there
Create qemu-os-win32.h for WIN32 specific declarations. Move polling
handling declaration into this file from sysemu.h
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Acked-by: Juan Quintela <quintela at redhat.com>
Acked-by: Richard Henderson <rth at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/qemu-os-win32.h b/qemu-os-win32.h
new file mode 100644
index 0000000..be108ad
--- /dev/null
+++ b/qemu-os-win32.h
@@ -0,0 +1,43 @@
+/*
+ * win32 specific declarations
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ * Copyright (c) 2010 Jes Sorensen <Jes.Sorensen at redhat.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef QEMU_OS_WIN32_H
+#define QEMU_OS_WIN32_H
+
+/* Polling handling */
+
+/* return TRUE if no sleep should be done afterwards */
+typedef int PollingFunc(void *opaque);
+
+int qemu_add_polling_cb(PollingFunc *func, void *opaque);
+void qemu_del_polling_cb(PollingFunc *func, void *opaque);
+
+/* Wait objects handling */
+typedef void WaitObjectFunc(void *opaque);
+
+int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
+void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
+
+#endif
diff --git a/sysemu.h b/sysemu.h
index 879446a..13fc9a9 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -9,6 +9,7 @@
#ifdef _WIN32
#include <windows.h>
+#include "qemu-os-win32.h"
#endif
/* vl.c */
@@ -71,22 +72,6 @@ int qemu_savevm_state_complete(Monitor *mon, QEMUFile *f);
void qemu_savevm_state_cancel(Monitor *mon, QEMUFile *f);
int qemu_loadvm_state(QEMUFile *f);
-#ifdef _WIN32
-/* Polling handling */
-
-/* return TRUE if no sleep should be done afterwards */
-typedef int PollingFunc(void *opaque);
-
-int qemu_add_polling_cb(PollingFunc *func, void *opaque);
-void qemu_del_polling_cb(PollingFunc *func, void *opaque);
-
-/* Wait objects handling */
-typedef void WaitObjectFunc(void *opaque);
-
-int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
-void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque);
-#endif
-
/* SLIRP */
void do_info_slirp(Monitor *mon);
commit ddc9120e90199e3fe93116928de13a2dd72fa35a
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Thu Jun 10 11:42:15 2010 +0200
vl.c: Remove double include of netinet/in.h for Solaris
vl.c: netinet/in.h is already included once above for the
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Acked-by: Andreas Faerber <afaerber at opensolaris.org>
Acked-by: Juan Quintela <quintela at redhat.com>
Acked-by: Richard Henderson <rth at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/vl.c b/vl.c
index 3d7ce52..a9be190 100644
--- a/vl.c
+++ b/vl.c
@@ -70,7 +70,6 @@
#include <sys/ethernet.h>
#include <sys/sockio.h>
#include <netinet/arp.h>
-#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h> // must come after ip.h
commit 41ba834146f1d8b9cbc09a9f25f5c6b84bf405d9
Author: Paul Brook <paul at codesourcery.com>
Date: Fri Jun 11 20:01:00 2010 +0100
NEON vldN optimization
When combining multiple values as part of a NEON array load, do explcit
shift/or rather than using gen_bfi. This voids redundant mask
operations.
Signed-off-by: Paul Brook <paul at codesourcery.com>
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 0eccca5..a28e2ff 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -3854,7 +3854,8 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
tcg_gen_addi_i32(addr, addr, stride);
tmp2 = gen_ld16u(addr, IS_USER(s));
tcg_gen_addi_i32(addr, addr, stride);
- gen_bfi(tmp, tmp, tmp2, 16, 0xffff);
+ tcg_gen_shli_i32(tmp2, tmp2, 16);
+ tcg_gen_or_i32(tmp, tmp, tmp2);
dead_tmp(tmp2);
neon_store_reg(rd, pass, tmp);
} else {
@@ -3875,7 +3876,8 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn)
if (n == 0) {
tmp2 = tmp;
} else {
- gen_bfi(tmp2, tmp2, tmp, n * 8, 0xff);
+ tcg_gen_shli_i32(tmp, tmp, n * 8);
+ tcg_gen_or_i32(tmp2, tmp2, tmp);
dead_tmp(tmp);
}
}
commit 02e95918b82efde24db1d759300ec3c61bd694b3
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Wed Jun 2 09:06:03 2010 +0200
hxtool: Fix line number reporting on SQMP/EQMP errors
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
diff --git a/hxtool b/hxtool
index d499dc0..7ca83ed 100644
--- a/hxtool
+++ b/hxtool
@@ -59,6 +59,7 @@ hxtoqmp()
{
IFS=
flag=0
+ line=1
while read -r str; do
case "$str" in
HXCOMM*)
@@ -87,6 +88,7 @@ hxtoqmp()
test $flag -eq 1 && echo "$str"
;;
esac
+ line=$((line+1))
done
}
commit 28e91a681a284b02b18cdbeee011430e5d061533
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Mon May 24 09:39:53 2010 +0200
remove unnecessary lookaheads
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
diff --git a/json-lexer.c b/json-lexer.c
index 5ea64a7..c736f42 100644
--- a/json-lexer.c
+++ b/json-lexer.c
@@ -29,7 +29,6 @@
enum json_lexer_state {
ERROR = 0,
- IN_DONE_STRING,
IN_DQ_UCODE3,
IN_DQ_UCODE2,
IN_DQ_UCODE1,
@@ -57,9 +56,7 @@ enum json_lexer_state {
IN_ESCAPE_I,
IN_ESCAPE_I6,
IN_ESCAPE_I64,
- IN_ESCAPE_DONE,
IN_WHITESPACE,
- IN_OPERATOR_DONE,
IN_START,
};
@@ -72,10 +69,6 @@ enum json_lexer_state {
(json_lexer[(old_state)][0] == (terminal))
static const uint8_t json_lexer[][256] = {
- [IN_DONE_STRING] = {
- TERMINAL(JSON_STRING),
- },
-
/* double quote string */
[IN_DQ_UCODE3] = {
['0' ... '9'] = IN_DQ_STRING,
@@ -112,7 +105,7 @@ static const uint8_t json_lexer[][256] = {
[IN_DQ_STRING] = {
[1 ... 0xFF] = IN_DQ_STRING,
['\\'] = IN_DQ_STRING_ESCAPE,
- ['"'] = IN_DONE_STRING,
+ ['"'] = JSON_STRING,
},
/* single quote string */
@@ -151,7 +144,7 @@ static const uint8_t json_lexer[][256] = {
[IN_SQ_STRING] = {
[1 ... 0xFF] = IN_SQ_STRING,
['\\'] = IN_SQ_STRING_ESCAPE,
- ['\''] = IN_DONE_STRING,
+ ['\''] = JSON_STRING,
},
/* Zero */
@@ -217,27 +210,18 @@ static const uint8_t json_lexer[][256] = {
['\n'] = IN_WHITESPACE,
},
- /* operator */
- [IN_OPERATOR_DONE] = {
- TERMINAL(JSON_OPERATOR),
- },
-
/* escape */
- [IN_ESCAPE_DONE] = {
- TERMINAL(JSON_ESCAPE),
- },
-
[IN_ESCAPE_LL] = {
- ['d'] = IN_ESCAPE_DONE,
+ ['d'] = JSON_ESCAPE,
},
[IN_ESCAPE_L] = {
- ['d'] = IN_ESCAPE_DONE,
+ ['d'] = JSON_ESCAPE,
['l'] = IN_ESCAPE_LL,
},
[IN_ESCAPE_I64] = {
- ['d'] = IN_ESCAPE_DONE,
+ ['d'] = JSON_ESCAPE,
},
[IN_ESCAPE_I6] = {
@@ -249,11 +233,11 @@ static const uint8_t json_lexer[][256] = {
},
[IN_ESCAPE] = {
- ['d'] = IN_ESCAPE_DONE,
- ['i'] = IN_ESCAPE_DONE,
- ['p'] = IN_ESCAPE_DONE,
- ['s'] = IN_ESCAPE_DONE,
- ['f'] = IN_ESCAPE_DONE,
+ ['d'] = JSON_ESCAPE,
+ ['i'] = JSON_ESCAPE,
+ ['p'] = JSON_ESCAPE,
+ ['s'] = JSON_ESCAPE,
+ ['f'] = JSON_ESCAPE,
['l'] = IN_ESCAPE_L,
['I'] = IN_ESCAPE_I,
},
@@ -265,12 +249,12 @@ static const uint8_t json_lexer[][256] = {
['0'] = IN_ZERO,
['1' ... '9'] = IN_NONZERO_NUMBER,
['-'] = IN_NEG_NONZERO_NUMBER,
- ['{'] = IN_OPERATOR_DONE,
- ['}'] = IN_OPERATOR_DONE,
- ['['] = IN_OPERATOR_DONE,
- [']'] = IN_OPERATOR_DONE,
- [','] = IN_OPERATOR_DONE,
- [':'] = IN_OPERATOR_DONE,
+ ['{'] = JSON_OPERATOR,
+ ['}'] = JSON_OPERATOR,
+ ['['] = JSON_OPERATOR,
+ [']'] = JSON_OPERATOR,
+ [','] = JSON_OPERATOR,
+ [':'] = JSON_OPERATOR,
['a' ... 'z'] = IN_KEYWORD,
['%'] = IN_ESCAPE,
[' '] = IN_WHITESPACE,
commit f7c052747e4b139df16e1d5b7851f4729acc2bb7
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Mon May 24 09:39:52 2010 +0200
implement optional lookahead in json lexer
Not requiring one extra character when lookahead is not necessary
ensures that clients behave properly even if they, for example,
send QMP requests without a trailing newline.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
diff --git a/json-lexer.c b/json-lexer.c
index 1d9b81f..5ea64a7 100644
--- a/json-lexer.c
+++ b/json-lexer.c
@@ -65,6 +65,12 @@ enum json_lexer_state {
#define TERMINAL(state) [0 ... 0x7F] = (state)
+/* Return whether TERMINAL is a terminal state and the transition to it
+ from OLD_STATE required lookahead. This happens whenever the table
+ below uses the TERMINAL macro. */
+#define TERMINAL_NEEDED_LOOKAHEAD(old_state, terminal) \
+ (json_lexer[(old_state)][0] == (terminal))
+
static const uint8_t json_lexer[][256] = {
[IN_DONE_STRING] = {
TERMINAL(JSON_STRING),
@@ -284,35 +290,41 @@ void json_lexer_init(JSONLexer *lexer, JSONLexerEmitter func)
static int json_lexer_feed_char(JSONLexer *lexer, char ch)
{
+ int char_consumed, new_state;
+
lexer->x++;
if (ch == '\n') {
lexer->x = 0;
lexer->y++;
}
- lexer->state = json_lexer[lexer->state][(uint8_t)ch];
-
- switch (lexer->state) {
- case JSON_OPERATOR:
- case JSON_ESCAPE:
- case JSON_INTEGER:
- case JSON_FLOAT:
- case JSON_KEYWORD:
- case JSON_STRING:
- lexer->emit(lexer, lexer->token, lexer->state, lexer->x, lexer->y);
- case JSON_SKIP:
- lexer->state = json_lexer[IN_START][(uint8_t)ch];
- QDECREF(lexer->token);
- lexer->token = qstring_new();
- break;
- case ERROR:
- return -EINVAL;
- default:
- break;
- }
-
- qstring_append_chr(lexer->token, ch);
+ do {
+ new_state = json_lexer[lexer->state][(uint8_t)ch];
+ char_consumed = !TERMINAL_NEEDED_LOOKAHEAD(lexer->state, new_state);
+ if (char_consumed) {
+ qstring_append_chr(lexer->token, ch);
+ }
+ switch (new_state) {
+ case JSON_OPERATOR:
+ case JSON_ESCAPE:
+ case JSON_INTEGER:
+ case JSON_FLOAT:
+ case JSON_KEYWORD:
+ case JSON_STRING:
+ lexer->emit(lexer, lexer->token, new_state, lexer->x, lexer->y);
+ case JSON_SKIP:
+ QDECREF(lexer->token);
+ lexer->token = qstring_new();
+ new_state = IN_START;
+ break;
+ case ERROR:
+ return -EINVAL;
+ default:
+ break;
+ }
+ lexer->state = new_state;
+ } while (!char_consumed);
return 0;
}
@@ -334,7 +346,7 @@ int json_lexer_feed(JSONLexer *lexer, const char *buffer, size_t size)
int json_lexer_flush(JSONLexer *lexer)
{
- return json_lexer_feed_char(lexer, 0);
+ return lexer->state == IN_START ? 0 : json_lexer_feed_char(lexer, 0);
}
void json_lexer_destroy(JSONLexer *lexer)
commit 7f8fca7c8add770d6533c44d2d001c0442ed0371
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Mon May 24 09:39:51 2010 +0200
add some tests for invalid JSON
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
diff --git a/check-qjson.c b/check-qjson.c
index d365799..2e52450 100644
--- a/check-qjson.c
+++ b/check-qjson.c
@@ -638,11 +638,90 @@ START_TEST(simple_varargs)
}
END_TEST
+START_TEST(empty_input)
+{
+ QObject *obj = qobject_from_json("");
+ fail_unless(obj == NULL);
+}
+END_TEST
+
+START_TEST(unterminated_string)
+{
+ QObject *obj = qobject_from_json("\"abc");
+ fail_unless(obj == NULL);
+}
+END_TEST
+
+START_TEST(unterminated_sq_string)
+{
+ QObject *obj = qobject_from_json("'abc");
+ fail_unless(obj == NULL);
+}
+END_TEST
+
+START_TEST(unterminated_escape)
+{
+ QObject *obj = qobject_from_json("\"abc\\\"");
+ fail_unless(obj == NULL);
+}
+END_TEST
+
+START_TEST(unterminated_array)
+{
+ QObject *obj = qobject_from_json("[32");
+ fail_unless(obj == NULL);
+}
+END_TEST
+
+START_TEST(unterminated_array_comma)
+{
+ QObject *obj = qobject_from_json("[32,");
+ fail_unless(obj == NULL);
+}
+END_TEST
+
+START_TEST(invalid_array_comma)
+{
+ QObject *obj = qobject_from_json("[32,}");
+ fail_unless(obj == NULL);
+}
+END_TEST
+
+START_TEST(unterminated_dict)
+{
+ QObject *obj = qobject_from_json("{'abc':32");
+ fail_unless(obj == NULL);
+}
+END_TEST
+
+START_TEST(unterminated_dict_comma)
+{
+ QObject *obj = qobject_from_json("{'abc':32,");
+ fail_unless(obj == NULL);
+}
+END_TEST
+
+#if 0
+START_TEST(invalid_dict_comma)
+{
+ QObject *obj = qobject_from_json("{'abc':32,}");
+ fail_unless(obj == NULL);
+}
+END_TEST
+
+START_TEST(unterminated_literal)
+{
+ QObject *obj = qobject_from_json("nul");
+ fail_unless(obj == NULL);
+}
+END_TEST
+#endif
+
static Suite *qjson_suite(void)
{
Suite *suite;
TCase *string_literals, *number_literals, *keyword_literals;
- TCase *dicts, *lists, *whitespace, *varargs;
+ TCase *dicts, *lists, *whitespace, *varargs, *errors;
string_literals = tcase_create("String Literals");
tcase_add_test(string_literals, simple_string);
@@ -668,6 +747,22 @@ static Suite *qjson_suite(void)
varargs = tcase_create("Varargs");
tcase_add_test(varargs, simple_varargs);
+ errors = tcase_create("Invalid JSON");
+ tcase_add_test(errors, empty_input);
+ tcase_add_test(errors, unterminated_string);
+ tcase_add_test(errors, unterminated_escape);
+ tcase_add_test(errors, unterminated_sq_string);
+ tcase_add_test(errors, unterminated_array);
+ tcase_add_test(errors, unterminated_array_comma);
+ tcase_add_test(errors, invalid_array_comma);
+ tcase_add_test(errors, unterminated_dict);
+ tcase_add_test(errors, unterminated_dict_comma);
+#if 0
+ /* FIXME: this print parse error messages on stderr. */
+ tcase_add_test(errors, invalid_dict_comma);
+ tcase_add_test(errors, unterminated_literal);
+#endif
+
suite = suite_create("QJSON test-suite");
suite_add_tcase(suite, string_literals);
suite_add_tcase(suite, number_literals);
@@ -676,6 +771,7 @@ static Suite *qjson_suite(void)
suite_add_tcase(suite, lists);
suite_add_tcase(suite, whitespace);
suite_add_tcase(suite, varargs);
+ suite_add_tcase(suite, errors);
return suite;
}
commit 2e89c0688993447ed62a1832dcd97c19c878a382
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date: Wed May 19 17:17:05 2010 -0300
json-streamer: Don't use qdict_put_obj()
It's not needed, use qobject_put() instead and get a cleaner code.
Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
diff --git a/json-streamer.c b/json-streamer.c
index 610ffea..f7e7a68 100644
--- a/json-streamer.c
+++ b/json-streamer.c
@@ -43,11 +43,11 @@ static void json_message_process_token(JSONLexer *lexer, QString *token, JSONTok
}
dict = qdict_new();
- qdict_put_obj(dict, "type", QOBJECT(qint_from_int(type)));
+ qdict_put(dict, "type", qint_from_int(type));
QINCREF(token);
- qdict_put_obj(dict, "token", QOBJECT(token));
- qdict_put_obj(dict, "x", QOBJECT(qint_from_int(x)));
- qdict_put_obj(dict, "y", QOBJECT(qint_from_int(y)));
+ qdict_put(dict, "token", token);
+ qdict_put(dict, "x", qint_from_int(x));
+ qdict_put(dict, "y", qint_from_int(y));
qlist_append(parser->tokens, dict);
commit ecb50f5fefe7e1360818bd199218a295d87df042
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date: Mon May 17 17:59:00 2010 -0300
json-lexer: Drop 'buf'
QString supports adding a single char, 'buf' is unneeded.
Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
diff --git a/json-lexer.c b/json-lexer.c
index 5cc7e6c..1d9b81f 100644
--- a/json-lexer.c
+++ b/json-lexer.c
@@ -284,8 +284,6 @@ void json_lexer_init(JSONLexer *lexer, JSONLexerEmitter func)
static int json_lexer_feed_char(JSONLexer *lexer, char ch)
{
- char buf[2];
-
lexer->x++;
if (ch == '\n') {
lexer->x = 0;
@@ -313,10 +311,7 @@ static int json_lexer_feed_char(JSONLexer *lexer, char ch)
break;
}
- buf[0] = ch;
- buf[1] = 0;
-
- qstring_append(lexer->token, buf);
+ qstring_append_chr(lexer->token, ch);
return 0;
}
commit d22b0bd7fc85f991275ffc60a550ed42f4c1b04c
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date: Wed May 19 17:08:37 2010 -0300
check-qjson: Add more escape tests
While there make the fail_unless() calls print error messages.
IMPORTANT: The test for "\/" is failing, don't know why.
Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
diff --git a/check-qjson.c b/check-qjson.c
index 109e777..d365799 100644
--- a/check-qjson.c
+++ b/check-qjson.c
@@ -29,6 +29,13 @@ START_TEST(escaped_string)
const char *decoded;
int skip;
} test_cases[] = {
+ { "\"\\b\"", "\b" },
+ { "\"\\f\"", "\f" },
+ { "\"\\n\"", "\n" },
+ { "\"\\r\"", "\r" },
+ { "\"\\t\"", "\t" },
+ { "\"\\/\"", "\\/" },
+ { "\"\\\\\"", "\\" },
{ "\"\\\"\"", "\"" },
{ "\"hello world \\\"embedded string\\\"\"",
"hello world \"embedded string\"" },
@@ -49,11 +56,14 @@ START_TEST(escaped_string)
fail_unless(qobject_type(obj) == QTYPE_QSTRING);
str = qobject_to_qstring(obj);
- fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0);
+ fail_unless(strcmp(qstring_get_str(str), test_cases[i].decoded) == 0,
+ "%s != %s\n", qstring_get_str(str), test_cases[i].decoded);
if (test_cases[i].skip == 0) {
str = qobject_to_json(obj);
- fail_unless(strcmp(qstring_get_str(str), test_cases[i].encoded) == 0);
+ fail_unless(strcmp(qstring_get_str(str),test_cases[i].encoded) == 0,
+ "%s != %s\n", qstring_get_str(str),
+ test_cases[i].encoded);
qobject_decref(obj);
}
commit bd0326950f99faa8e50cf52499dd1af42829aa93
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date: Wed May 19 17:06:15 2010 -0300
qjson: Handle "\f"
It's valid JSON and should be handled.
Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
diff --git a/json-parser.c b/json-parser.c
index b55d763..83212bc 100644
--- a/json-parser.c
+++ b/json-parser.c
@@ -206,6 +206,10 @@ static QString *qstring_from_escaped_str(JSONParserContext *ctxt, QObject *token
qstring_append(str, "\b");
ptr++;
break;
+ case 'f':
+ qstring_append(str, "\f");
+ ptr++;
+ break;
case 'n':
qstring_append(str, "\n");
ptr++;
diff --git a/qjson.c b/qjson.c
index 483c667..e4ee433 100644
--- a/qjson.c
+++ b/qjson.c
@@ -158,6 +158,9 @@ static void to_json(const QObject *obj, QString *str)
case '\b':
qstring_append(str, "\\b");
break;
+ case '\f':
+ qstring_append(str, "\\f");
+ break;
case '\n':
qstring_append(str, "\\n");
break;
commit 1041ba7a14260b490f3062f428b014b415a23f38
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date: Wed May 19 16:57:28 2010 -0300
json-lexer: Handle missing escapes
The JSON escape sequence "\/" and "\\" are valid and should be
handled.
Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
diff --git a/json-lexer.c b/json-lexer.c
index 0b145d1..5cc7e6c 100644
--- a/json-lexer.c
+++ b/json-lexer.c
@@ -97,6 +97,8 @@ static const uint8_t json_lexer[][256] = {
['n'] = IN_DQ_STRING,
['r'] = IN_DQ_STRING,
['t'] = IN_DQ_STRING,
+ ['/'] = IN_DQ_STRING,
+ ['\\'] = IN_DQ_STRING,
['\''] = IN_DQ_STRING,
['\"'] = IN_DQ_STRING,
['u'] = IN_DQ_UCODE0,
@@ -134,6 +136,8 @@ static const uint8_t json_lexer[][256] = {
['n'] = IN_SQ_STRING,
['r'] = IN_SQ_STRING,
['t'] = IN_SQ_STRING,
+ ['/'] = IN_DQ_STRING,
+ ['\\'] = IN_DQ_STRING,
['\''] = IN_SQ_STRING,
['\"'] = IN_SQ_STRING,
['u'] = IN_SQ_UCODE0,
commit 03308f6c2746a756a8404d00caa20f8f35248167
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date: Mon May 17 17:50:01 2010 -0300
json-lexer: Initialize 'x' and 'y'
The 'lexer' variable is passed by the caller, it can contain anything
(eg. garbage).
Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
diff --git a/json-lexer.c b/json-lexer.c
index 9d64920..0b145d1 100644
--- a/json-lexer.c
+++ b/json-lexer.c
@@ -275,6 +275,7 @@ void json_lexer_init(JSONLexer *lexer, JSONLexerEmitter func)
lexer->emit = func;
lexer->state = IN_START;
lexer->token = qstring_new();
+ lexer->x = lexer->y = 0;
}
static int json_lexer_feed_char(JSONLexer *lexer, char ch)
commit 0e2029a063405091ee34170ef71aa321715e4357
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Fri Jun 11 18:39:47 2010 +0200
tcg: fix DEF macro after commit c61aaf7a388c4ad95d8b546fdb9267dc01183317
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 30b5106..3a18b76 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -69,7 +69,7 @@ static void patch_reloc(uint8_t *code_ptr, int type,
tcg_target_long value, tcg_target_long addend);
static TCGOpDef tcg_op_defs[] = {
-#define DEF(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags, 0 },
+#define DEF(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags },
#include "tcg-opc.h"
#undef DEF
};
commit 28d7cc493e8b58f63fda05eb7df2552f5d420459
Author: Richard Henderson <rth at twiddle.net>
Date: Fri Jun 4 12:14:09 2010 -0700
tcg-s390: Adjust compilation flags.
Force -m31/-m64 based on s390/s390x target.
Force -march=z990. The TCG backend will always require the
long-displacement facility, so the compiler may as well make
use of that as well.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/configure b/configure
index 927e104..ced4d2f 100755
--- a/configure
+++ b/configure
@@ -720,7 +720,12 @@ case "$cpu" in
fi
;;
s390)
- QEMU_CFLAGS="-march=z900 $QEMU_CFLAGS"
+ QEMU_CFLAGS="-m31 -march=z990 $QEMU_CFLAGS"
+ LDFLAGS="-m31 $LDFLAGS"
+ ;;
+ s390x)
+ QEMU_CFLAGS="-m64 -march=z990 $QEMU_CFLAGS"
+ LDFLAGS="-m64 $LDFLAGS"
;;
i386)
QEMU_CFLAGS="-m32 $QEMU_CFLAGS"
commit 6a1621b917352122ad025e102f450de382dae407
Author: Richard Henderson <rth at twiddle.net>
Date: Fri Jun 4 12:14:12 2010 -0700
tcg-s390: Compute is_write in cpu_signal_handler.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/cpu-exec.c b/cpu-exec.c
index c776605..026980a 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -1156,11 +1156,47 @@ int cpu_signal_handler(int host_signum, void *pinfo,
siginfo_t *info = pinfo;
struct ucontext *uc = puc;
unsigned long pc;
- int is_write;
+ uint16_t *pinsn;
+ int is_write = 0;
pc = uc->uc_mcontext.psw.addr;
- /* XXX: compute is_write */
- is_write = 0;
+
+ /* ??? On linux, the non-rt signal handler has 4 (!) arguments instead
+ of the normal 2 arguments. The 3rd argument contains the "int_code"
+ from the hardware which does in fact contain the is_write value.
+ The rt signal handler, as far as I can tell, does not give this value
+ at all. Not that we could get to it from here even if it were. */
+ /* ??? This is not even close to complete, since it ignores all
+ of the read-modify-write instructions. */
+ pinsn = (uint16_t *)pc;
+ switch (pinsn[0] >> 8) {
+ case 0x50: /* ST */
+ case 0x42: /* STC */
+ case 0x40: /* STH */
+ is_write = 1;
+ break;
+ case 0xc4: /* RIL format insns */
+ switch (pinsn[0] & 0xf) {
+ case 0xf: /* STRL */
+ case 0xb: /* STGRL */
+ case 0x7: /* STHRL */
+ is_write = 1;
+ }
+ break;
+ case 0xe3: /* RXY format insns */
+ switch (pinsn[2] & 0xff) {
+ case 0x50: /* STY */
+ case 0x24: /* STG */
+ case 0x72: /* STCY */
+ case 0x70: /* STHY */
+ case 0x8e: /* STPQ */
+ case 0x3f: /* STRVH */
+ case 0x3e: /* STRV */
+ case 0x2f: /* STRVG */
+ is_write = 1;
+ }
+ break;
+ }
return handle_cpu_signal(pc, (unsigned long)info->si_addr,
is_write, &uc->uc_sigmask, puc);
}
commit 4d58be0628bf1d30b8c1b3600f0ce44db1b38b2f
Author: Richard Henderson <rth at twiddle.net>
Date: Fri Jun 4 12:14:11 2010 -0700
s390x: Don't use a linker script for user-only.
The default placement of the application at 0x80000000 is fine,
and will avoid the default placement for most other guests.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/configure b/configure
index fa7f299..927e104 100755
--- a/configure
+++ b/configure
@@ -2763,6 +2763,9 @@ if test "$target_linux_user" = "yes" -o "$target_bsd_user" = "yes" ; then
# -static is used to avoid g1/g3 usage by the dynamic linker
ldflags="$linker_script -static $ldflags"
;;
+ alpha | s390x)
+ # The default placement of the application is fine.
+ ;;
*)
ldflags="$linker_script $ldflags"
;;
commit d35b261c7a94be9e2fcad5484343544d58ff99be
Author: Richard Henderson <rth at twiddle.net>
Date: Fri Jun 4 12:14:10 2010 -0700
s390x: Avoid _llseek.
There's no _llseek on s390x either. Replace the existing
test for __x86_64__ with a functional test for __NR_llseek.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 8222cb9..e94f1ee 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -208,7 +208,7 @@ _syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count)
_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
#endif
_syscall2(int, sys_getpriority, int, which, int, who);
-#if defined(TARGET_NR__llseek) && !defined (__x86_64__)
+#if defined(TARGET_NR__llseek) && defined(__NR_llseek)
_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
loff_t *, res, uint, wh);
#endif
@@ -5933,7 +5933,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#ifdef TARGET_NR__llseek /* Not on alpha */
case TARGET_NR__llseek:
{
-#if defined (__x86_64__)
+#if !defined(__NR_llseek)
ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
if (put_user_s64(ret, arg4))
goto efault;
commit eba0b89379b3af98b51a8c1559868de89f5f713e
Author: Richard Henderson <rth at twiddle.net>
Date: Fri Jun 4 12:14:14 2010 -0700
tcg-s390: Allocate the code_gen_buffer near the main program.
This allows the use of direct calls to the helpers,
and a direct branch back to the epilogue.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/exec.c b/exec.c
index aedfda4..4273797 100644
--- a/exec.c
+++ b/exec.c
@@ -519,6 +519,13 @@ static void code_gen_alloc(unsigned long tb_size)
start = (void *) 0x01000000UL;
if (code_gen_buffer_size > 16 * 1024 * 1024)
code_gen_buffer_size = 16 * 1024 * 1024;
+#elif defined(__s390x__)
+ /* Map the buffer so that we can use direct calls and branches. */
+ /* We have a +- 4GB range on the branches; leave some slop. */
+ if (code_gen_buffer_size > (3ul * 1024 * 1024 * 1024)) {
+ code_gen_buffer_size = 3ul * 1024 * 1024 * 1024;
+ }
+ start = (void *)0x90000000UL;
#endif
code_gen_buffer = mmap(start, code_gen_buffer_size,
PROT_WRITE | PROT_READ | PROT_EXEC,
commit 1bcaae666fdcda03f768c2894091ec2e441abb57
Author: Richard Henderson <rth at twiddle.net>
Date: Fri Jun 4 12:14:13 2010 -0700
tcg-s390: Icache flush is a no-op.
Before gcc 4.2, __builtin___clear_cache doesn't exist, and
afterward the gcc s390 backend implements it as nothing.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/s390/tcg-target.h b/tcg/s390/tcg-target.h
index d8a2955..d7fe0c7 100644
--- a/tcg/s390/tcg-target.h
+++ b/tcg/s390/tcg-target.h
@@ -94,9 +94,4 @@ enum {
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
-#if QEMU_GNUC_PREREQ(4, 1)
- __builtin___clear_cache((char *) start, (char *) stop);
-#else
-#error not implemented
-#endif
}
commit dc397ca35e332770ede6899122e5d012bd92c37c
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Thu Jun 10 20:52:47 2010 +0200
tcg-i386: fix andi r, r, 0xff
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 8b902ab..bb19a95 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -679,7 +679,7 @@ static void tgen_arithi(TCGContext *s, int c, int r0,
rexw = 0;
}
}
- if (val == 0xffu) {
+ if (val == 0xffu && (r0 < 4 || TCG_TARGET_REG_BITS == 64)) {
tcg_out_ext8u(s, r0, r0);
return;
}
commit 447d681e8b23fec360c95131c0b037d82dce495c
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Thu Jun 10 20:40:24 2010 +0200
tcg-i386: remove use of _Bool that slipped code review
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 4d95200..8b902ab 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -656,7 +656,7 @@ static void tgen_arithi(TCGContext *s, int c, int r0,
partial flags update stalls on Pentium4 and are not recommended
by current Intel optimization manuals. */
if (!cf && (c == ARITH_ADD || c == ARITH_SUB) && (val == 1 || val == -1)) {
- _Bool is_inc = (c == ARITH_ADD) ^ (val < 0);
+ int is_inc = (c == ARITH_ADD) ^ (val < 0);
if (TCG_TARGET_REG_BITS == 64) {
/* The single-byte increment encodings are re-tasked as the
REX prefixes. Use the MODRM encoding. */
commit 85948643b8df28ca87e41a1c4c7f16a66b4ac6cd
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Thu Jun 10 17:57:39 2010 +0000
esp: lower IRQ on soft reset
42f1ced228c9b616cfa2b69846025271618e4ef5 removed irq lowering
during reset. However, for chip reset command and DMA reset signal,
its actually the correct thing to do.
Lower IRQ on soft reset only.
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/esp.c b/hw/esp.c
index 0a8cf6e..7740879 100644
--- a/hw/esp.c
+++ b/hw/esp.c
@@ -419,7 +419,7 @@ static void handle_ti(ESPState *s)
}
}
-static void esp_reset(DeviceState *d)
+static void esp_hard_reset(DeviceState *d)
{
ESPState *s = container_of(d, ESPState, busdev.qdev);
@@ -435,10 +435,19 @@ static void esp_reset(DeviceState *d)
s->rregs[ESP_CFG1] = 7;
}
+static void esp_soft_reset(DeviceState *d)
+{
+ ESPState *s = container_of(d, ESPState, busdev.qdev);
+
+ qemu_irq_lower(s->irq);
+ esp_hard_reset(d);
+}
+
static void parent_esp_reset(void *opaque, int irq, int level)
{
- if (level)
- esp_reset(opaque);
+ if (level) {
+ esp_soft_reset(opaque);
+ }
}
static uint32_t esp_mem_readb(void *opaque, target_phys_addr_t addr)
@@ -528,7 +537,7 @@ static void esp_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
break;
case CMD_RESET:
DPRINTF("Chip reset (%2.2x)\n", val);
- esp_reset(&s->busdev.qdev);
+ esp_soft_reset(&s->busdev.qdev);
break;
case CMD_BUSRESET:
DPRINTF("Bus reset (%2.2x)\n", val);
@@ -679,7 +688,7 @@ static SysBusDeviceInfo esp_info = {
.qdev.name = "esp",
.qdev.size = sizeof(ESPState),
.qdev.vmsd = &vmstate_esp,
- .qdev.reset = esp_reset,
+ .qdev.reset = esp_hard_reset,
.qdev.props = (Property[]) {
{.name = NULL}
}
commit e163ae7b8f80dc4eb38445956929409601a8321c
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date: Thu May 27 14:35:58 2010 +0900
qbus: fix memory leak in qbus_free()
BusState::name is allocated in qbus_create_inplace().
So it should be freed by qbus_free().
Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/qdev.c b/hw/qdev.c
index aa2ce01..36f29ea 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -700,6 +700,7 @@ void qbus_free(BusState *bus)
QLIST_REMOVE(bus, sibling);
bus->parent->num_child_bus--;
}
+ qemu_free((void*)bus->name);
if (bus->qdev_allocated) {
qemu_free(bus);
}
commit bd418d90d0c67d7ea88420c6754a4677c09f91c1
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date: Thu May 27 14:37:09 2010 +0900
multiboot: compilation fix with DEBUG_MULTIBOOT enabled.
This patch fixes the following compilation errors in multiboot.c
when DEBUG_MULTIBOOT is defined.
Use TARGET_FMT_plx instead of %x for target_phys_addr_t.
CC i386-softmmu/multiboot.o
cc1: warnings being treated as errors
qemu/hw/multiboot.c: In function 'mb_add_mod':
qemu/hw/multiboot.c:121: error: format '%08x' expects type 'unsigned int', but argument 4 has type 'target_phys_addr_t'
qemu/hw/multiboot.c:121: error: format '%08x' expects type 'unsigned int', but argument 5 has type 'target_phys_addr_t'
qemu/hw/multiboot.c: In function 'load_multiboot':
qemu/hw/multiboot.c:279: error: format '%#x' expects type 'unsigned int', but argument 5 has type 'target_phys_addr_t'
qemu/hw/multiboot.c:307: error: format '%x' expects type 'unsigned int', but argument 3 has type 'target_phys_addr_t'
qemu/hw/multiboot.c:308: error: format '%x' expects type 'unsigned int', but argument 3 has type 'target_phys_addr_t'
make[1]: *** [multiboot.o] Error 1
Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/multiboot.c b/hw/multiboot.c
index a1b665c..dc980e6 100644
--- a/hw/multiboot.c
+++ b/hw/multiboot.c
@@ -118,7 +118,8 @@ static void mb_add_mod(MultibootState *s,
stl_p(p + MB_MOD_END, end);
stl_p(p + MB_MOD_CMDLINE, cmdline_phys);
- mb_debug("mod%02d: %08x - %08x\n", s->mb_mods_count, start, end);
+ mb_debug("mod%02d: "TARGET_FMT_plx" - "TARGET_FMT_plx"\n",
+ s->mb_mods_count, start, end);
s->mb_mods_count++;
}
@@ -276,7 +277,7 @@ int load_multiboot(void *fw_cfg,
mb_add_mod(&mbs, mbs.mb_buf_phys + offs,
mbs.mb_buf_phys + offs + mb_mod_length, c);
- mb_debug("mod_start: %p\nmod_end: %p\n cmdline: %#x\n",
+ mb_debug("mod_start: %p\nmod_end: %p\n cmdline: "TARGET_FMT_plx"\n",
(char *)mbs.mb_buf + offs,
(char *)mbs.mb_buf + offs + mb_mod_length, c);
initrd_filename = next_initrd+1;
@@ -304,8 +305,8 @@ int load_multiboot(void *fw_cfg,
stl_p(bootinfo + MBI_MMAP_ADDR, ADDR_E820_MAP);
mb_debug("multiboot: mh_entry_addr = %#x\n", mh_entry_addr);
- mb_debug(" mb_buf_phys = %x\n", mbs.mb_buf_phys);
- mb_debug(" mod_start = %x\n", mbs.mb_buf_phys + mbs.offset_mods);
+ mb_debug(" mb_buf_phys = "TARGET_FMT_plx"\n", mbs.mb_buf_phys);
+ mb_debug(" mod_start = "TARGET_FMT_plx"\n", mbs.mb_buf_phys + mbs.offset_mods);
mb_debug(" mb_mods_count = %d\n", mbs.mb_mods_count);
/* save bootinfo off the stack */
commit fe7f9567a6934566641751df233cb45675a9130c
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date: Thu May 27 14:37:53 2010 +0900
vga-isa-mm: remove one #ifdef CONFIG_BOCHS_VBE.
remove one #ifdef CONFIG_BOCHS_VBE.
Call vga_init_vbe() instead.
Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/vga-isa-mm.c b/hw/vga-isa-mm.c
index 2faefa5..8e31e36 100644
--- a/hw/vga-isa-mm.c
+++ b/hw/vga-isa-mm.c
@@ -121,10 +121,6 @@ int isa_vga_mm_init(target_phys_addr_t vram_base,
s->vga.ds = graphic_console_init(s->vga.update, s->vga.invalidate,
s->vga.screen_dump, s->vga.text_update, s);
-#ifdef CONFIG_BOCHS_VBE
- /* XXX: use optimized standard vga accesses */
- cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
- VGA_RAM_SIZE, s->vga.vram_offset);
-#endif
+ vga_init_vbe(&s->vga);
return 0;
}
commit 0f2ad63fcb75c9679ff7d47f6b2235dfc646de35
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date: Thu May 27 14:38:47 2010 +0900
main: allocate gui_timer only once.
fix memory leak.
there is no need to allocate more than one gui_timer.
Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/vl.c b/vl.c
index 6d08ec8..3d7ce52 100644
--- a/vl.c
+++ b/vl.c
@@ -3794,6 +3794,7 @@ int main(int argc, char **argv, char **envp)
if (dcl->dpy_refresh != NULL) {
ds->gui_timer = qemu_new_timer(rt_clock, gui_update, ds);
qemu_mod_timer(ds->gui_timer, qemu_get_clock(rt_clock));
+ break;
}
dcl = dcl->next;
}
commit 60a3992e759d92b9111871b0881e65519c750b01
Merge: 77d4f95... 50e32ea...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date: Thu Jun 10 09:21:43 2010 -0500
Merge remote branch 'mst/for_anthony' into staging
commit 77d4f95e111a7c82bf21908f4de170b7e0e722bb
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date: Thu Jun 10 14:45:46 2010 +0200
cris: Break out image loading to hw/cris-boot.c.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at axis.com>
diff --git a/Makefile.target b/Makefile.target
index d06c679..478b89d 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -233,7 +233,10 @@ obj-microblaze-y += xilinx_ethlite.o
obj-microblaze-$(CONFIG_FDT) += device_tree.o
# Boards
-obj-cris-y = cris_pic_cpu.o etraxfs.o axis_dev88.o
+obj-cris-y = cris_pic_cpu.o
+obj-cris-y += cris-boot.o
+obj-cris-y += etraxfs.o axis_dev88.o
+obj-cris-y += axis_dev88.o
# IO blocks
obj-cris-y += etraxfs_dma.o
diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index 7d59c96..3ae4105 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -30,6 +30,7 @@
#include "etraxfs.h"
#include "loader.h"
#include "elf.h"
+#include "cris-boot.h"
#define D(x)
#define DNAND(x)
@@ -240,28 +241,7 @@ static CPUWriteMemoryFunc * const gpio_write[] = {
#define INTMEM_SIZE (128 * 1024)
-static struct {
- uint32_t bootstrap_pc;
- uint32_t regs[16];
-} loadargs;
-
-static void main_cpu_reset(void *opaque)
-{
- int i;
-
- CPUState *env = opaque;
- cpu_reset(env);
-
- env->pc = loadargs.bootstrap_pc;
- for (i = 0; i < 16; i++) {
- env->regs[i] = loadargs.regs[i];
- }
-}
-
-static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
-{
- return addr - 0x80000000LL;
-}
+static struct cris_load_info li;
static
void axisdev88_init (ram_addr_t ram_size,
@@ -275,7 +255,6 @@ void axisdev88_init (ram_addr_t ram_size,
qemu_irq irq[30], nmi[2], *cpu_irq;
void *etraxfs_dmac;
struct etraxfs_dma_client *eth[2] = {NULL, NULL};
- int kernel_size;
int i;
int nand_regs;
int gpio_regs;
@@ -287,7 +266,6 @@ void axisdev88_init (ram_addr_t ram_size,
cpu_model = "crisv32";
}
env = cpu_init(cpu_model);
- qemu_register_reset(main_cpu_reset, env);
/* allocate RAM */
phys_ram = qemu_ram_alloc(ram_size);
@@ -353,35 +331,14 @@ void axisdev88_init (ram_addr_t ram_size,
irq[0x14 + i]);
}
- if (kernel_filename) {
- uint64_t entry, high;
- int kcmdline_len;
-
- /* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis
- devboard SDK. */
- kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
- &entry, NULL, &high, 0, ELF_MACHINE, 0);
- loadargs.bootstrap_pc = entry;
- if (kernel_size < 0) {
- /* Takes a kimage from the axis devboard SDK. */
- kernel_size = load_image_targphys(kernel_filename, 0x40004000,
- ram_size);
- loadargs.bootstrap_pc = 0x40004000;
- loadargs.regs[9] = 0x40004000 + kernel_size;
- }
- loadargs.regs[8] = 0x56902387; /* RAM init magic. */
-
- if (kernel_cmdline && (kcmdline_len = strlen(kernel_cmdline))) {
- if (kcmdline_len > 256) {
- fprintf(stderr, "Too long CRIS kernel cmdline (max 256)\n");
- exit(1);
- }
- /* Let the kernel know we are modifying the cmdline. */
- loadargs.regs[10] = 0x87109563;
- loadargs.regs[11] = 0x40000000;
- pstrcpy_targphys("cmdline", loadargs.regs[11], 256, kernel_cmdline);
- }
+ if (!kernel_filename) {
+ fprintf(stderr, "Kernel image must be specified\n");
+ exit(1);
}
+
+ li.image_filename = kernel_filename;
+ li.cmdline = kernel_cmdline;
+ cris_load_image(env, &li);
}
static QEMUMachine axisdev88_machine = {
diff --git a/hw/cris-boot.c b/hw/cris-boot.c
new file mode 100644
index 0000000..2ef17f6
--- /dev/null
+++ b/hw/cris-boot.c
@@ -0,0 +1,97 @@
+/*
+ * CRIS image loading.
+ *
+ * Copyright (c) 2010 Edgar E. Iglesias, Axis Communications AB.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw.h"
+#include "sysemu.h"
+#include "loader.h"
+#include "elf.h"
+#include "cris-boot.h"
+
+static void main_cpu_reset(void *opaque)
+{
+ CPUState *env = opaque;
+ struct cris_load_info *li;
+
+ li = env->load_info;
+
+ cpu_reset(env);
+
+ if (!li) {
+ /* nothing more to do. */
+ return;
+ }
+
+ env->pc = li->entry;
+
+ if (li->image_filename) {
+ env->regs[8] = 0x56902387; /* RAM boot magic. */
+ env->regs[9] = 0x40004000 + li->image_size;
+ }
+
+ if (li->cmdline) {
+ /* Let the kernel know we are modifying the cmdline. */
+ env->regs[10] = 0x87109563;
+ env->regs[11] = 0x40000000;
+ }
+}
+
+static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
+{
+ return addr - 0x80000000LL;
+}
+
+void cris_load_image(CPUState *env, struct cris_load_info *li)
+{
+ uint64_t entry, high;
+ int kcmdline_len;
+ int image_size;
+
+ env->load_info = li;
+ /* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis
+ devboard SDK. */
+ image_size = load_elf(li->image_filename, translate_kernel_address, NULL,
+ &entry, NULL, &high, 0, ELF_MACHINE, 0);
+ li->entry = entry;
+ if (image_size < 0) {
+ /* Takes a kimage from the axis devboard SDK. */
+ image_size = load_image_targphys(li->image_filename, 0x40004000,
+ ram_size);
+ li->entry = 0x40004000;
+ }
+
+ if (image_size < 0) {
+ fprintf(stderr, "qemu: could not load kernel '%s'\n",
+ li->image_filename);
+ exit(1);
+ }
+
+ if (li->cmdline && (kcmdline_len = strlen(li->cmdline))) {
+ if (kcmdline_len > 256) {
+ fprintf(stderr, "Too long CRIS kernel cmdline (max 256)\n");
+ exit(1);
+ }
+ pstrcpy_targphys("cmdline", 0x40000000, 256, li->cmdline);
+ }
+ qemu_register_reset(main_cpu_reset, env);
+}
diff --git a/hw/cris-boot.h b/hw/cris-boot.h
new file mode 100644
index 0000000..e9caf8d
--- /dev/null
+++ b/hw/cris-boot.h
@@ -0,0 +1,11 @@
+
+struct cris_load_info
+{
+ const char *image_filename;
+ const char *cmdline;
+ int image_size;
+
+ target_phys_addr_t entry;
+};
+
+void cris_load_image(CPUState *env, struct cris_load_info *li);
diff --git a/hw/etraxfs.c b/hw/etraxfs.c
index b88d00a..01bf929 100644
--- a/hw/etraxfs.c
+++ b/hw/etraxfs.c
@@ -30,23 +30,17 @@
#include "etraxfs.h"
#include "loader.h"
#include "elf.h"
+#include "cris-boot.h"
#define FLASH_SIZE 0x2000000
#define INTMEM_SIZE (128 * 1024)
-static uint32_t bootstrap_pc;
+static struct cris_load_info li;
-static void main_cpu_reset(void *opaque)
+static void flash_cpu_reset(void *opaque)
{
CPUState *env = opaque;
cpu_reset(env);
-
- env->pc = bootstrap_pc;
-}
-
-static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
-{
- return addr - 0x80000000LL;
}
static
@@ -61,7 +55,6 @@ void bareetraxfs_init (ram_addr_t ram_size,
qemu_irq irq[30], nmi[2], *cpu_irq;
void *etraxfs_dmac;
struct etraxfs_dma_client *eth[2] = {NULL, NULL};
- int kernel_size;
DriveInfo *dinfo;
int i;
ram_addr_t phys_ram;
@@ -73,7 +66,6 @@ void bareetraxfs_init (ram_addr_t ram_size,
cpu_model = "crisv32";
}
env = cpu_init(cpu_model);
- qemu_register_reset(main_cpu_reset, env);
/* allocate RAM */
phys_ram = qemu_ram_alloc(ram_size);
@@ -137,38 +129,19 @@ void bareetraxfs_init (ram_addr_t ram_size,
}
if (kernel_filename) {
- uint64_t entry, high;
- int kcmdline_len;
-
- /* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis
- devboard SDK. */
- kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
- &entry, NULL, &high, 0, ELF_MACHINE, 0);
- bootstrap_pc = entry;
- if (kernel_size < 0) {
- /* Takes a kimage from the axis devboard SDK. */
- kernel_size = load_image_targphys(kernel_filename, 0x40004000,
- ram_size);
- bootstrap_pc = 0x40004000;
- env->regs[9] = 0x40004000 + kernel_size;
+ li.image_filename = kernel_filename;
+ li.cmdline = kernel_cmdline;
+ cris_load_image(env, &li);
+ } else {
+ if (!dinfo) {
+ fprintf(stderr,
+ "Provide a kernel image or a flash image to boot from.\n");
+ exit(1);
}
- env->regs[8] = 0x56902387; /* RAM init magic. */
-
- if (kernel_cmdline && (kcmdline_len = strlen(kernel_cmdline))) {
- if (kcmdline_len > 256) {
- fprintf(stderr, "Too long CRIS kernel cmdline (max 256)\n");
- exit(1);
- }
- /* Let the kernel know we are modifying the cmdline. */
- env->regs[10] = 0x87109563;
- env->regs[11] = 0x40000000;
- pstrcpy_targphys("cmdline", env->regs[11], 256, kernel_cmdline);
- }
- }
- env->pc = bootstrap_pc;
- printf ("pc =%x\n", env->pc);
- printf ("ram size =%ld\n", ram_size);
+ /* Nothing more to do for flash images, those boot from addr 0. */
+ qemu_register_reset(flash_cpu_reset, env);
+ }
}
static QEMUMachine bareetraxfs_machine = {
diff --git a/target-cris/cpu.h b/target-cris/cpu.h
index 063a240..a62d57c 100644
--- a/target-cris/cpu.h
+++ b/target-cris/cpu.h
@@ -155,6 +155,8 @@ typedef struct CPUCRISState {
uint32_t lo;
} tlbsets[2][4][16];
+ void *load_info;
+
CPU_COMMON
} CPUCRISState;
commit 2024c53950fe2886e460ca3a5d3d2ce0f06bf0f8
Author: Richard Henderson <rth at twiddle.net>
Date: Fri Jun 4 12:14:17 2010 -0700
s390: Disassemble some general-instruction-extension insns.
The full general-instruction-extension facility was added to binutils
after the change to GPLv3. This is not the entire extension, just
what we're using in TCG.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/s390-dis.c b/s390-dis.c
index db460f8..8abcdf0 100644
--- a/s390-dis.c
+++ b/s390-dis.c
@@ -172,6 +172,31 @@ static const struct s390_operand s390_operands[];
the instruction may be optional. */
#define S390_OPERAND_OPTIONAL 0x400
+/* QEMU-ADD */
+/* ??? Not quite the format the assembler takes, but easy to implement
+ without recourse to the table generator. */
+#define S390_OPERAND_CCODE 0x800
+
+static const char s390_ccode_name[16][4] = {
+ "n", /* 0000 */
+ "o", /* 0001 */
+ "h", /* 0010 */
+ "nle", /* 0011 */
+ "l", /* 0100 */
+ "nhe", /* 0101 */
+ "lh", /* 0110 */
+ "ne", /* 0111 */
+ "e", /* 1000 */
+ "nlh", /* 1001 */
+ "he", /* 1010 */
+ "nl", /* 1011 */
+ "le", /* 1100 */
+ "nh", /* 1101 */
+ "no", /* 1110 */
+ "a" /* 1111 */
+};
+/* QEMU-END */
+
#endif /* S390_H */
static int init_flag = 0;
@@ -325,13 +350,16 @@ print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info)
continue;
/* The instruction is valid. */
- if (opcode->operands[0] != 0)
- (*info->fprintf_func) (info->stream, "%s\t", opcode->name);
- else
- (*info->fprintf_func) (info->stream, "%s", opcode->name);
+/* QEMU-MOD */
+ (*info->fprintf_func) (info->stream, "%s", opcode->name);
+
+ if (s390_operands[opcode->operands[0]].flags & S390_OPERAND_CCODE)
+ separator = 0;
+ else
+ separator = '\t';
+/* QEMU-END */
/* Extract the operands. */
- separator = 0;
for (opindex = opcode->operands; *opindex != 0; opindex++)
{
unsigned int value;
@@ -363,6 +391,15 @@ print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info)
(*info->print_address_func) (memaddr + (int) value, info);
else if (operand->flags & S390_OPERAND_SIGNED)
(*info->fprintf_func) (info->stream, "%i", (int) value);
+/* QEMU-ADD */
+ else if (operand->flags & S390_OPERAND_CCODE)
+ {
+ (*info->fprintf_func) (info->stream, "%s",
+ s390_ccode_name[(int) value]);
+ separator = '\t';
+ continue;
+ }
+/* QEMU-END */
else
(*info->fprintf_func) (info->stream, "%u", value);
@@ -543,8 +580,16 @@ static const struct s390_operand s390_operands[] =
#define M_16 42 /* 4 bit optional mask starting at 16 */
{ 4, 16, S390_OPERAND_OPTIONAL },
#define RO_28 43 /* optional GPR starting at position 28 */
- { 4, 28, (S390_OPERAND_GPR | S390_OPERAND_OPTIONAL) }
-
+ { 4, 28, (S390_OPERAND_GPR | S390_OPERAND_OPTIONAL) },
+
+/* QEMU-ADD: */
+#define M4_12 44 /* 4-bit condition-code starting at 12 */
+ { 4, 12, S390_OPERAND_CCODE },
+#define M4_32 45 /* 4-bit condition-code starting at 32 */
+ { 4, 32, S390_OPERAND_CCODE },
+#define I8_32 46 /* 8 bit signed value starting at 32 */
+ { 8, 32, S390_OPERAND_SIGNED },
+/* QEMU-END */
};
@@ -755,6 +800,14 @@ static const struct s390_operand s390_operands[] =
#define MASK_S_RD { 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }
#define MASK_SSF_RRDRD { 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00 }
+/* QEMU-ADD: */
+#define INSTR_RIE_MRRP 6, { M4_32,R_8,R_12,J16_16,0,0 } /* e.g. crj */
+#define MASK_RIE_MRRP { 0xff, 0x00, 0x00, 0x00, 0x0f, 0xff }
+
+#define INSTR_RIE_MRIP 6, { M4_12,R_8,I8_32,J16_16,0,0 } /* e.g. cij */
+#define MASK_RIE_MRIP { 0xff, 0x00, 0x00, 0x00, 0x00, 0xff }
+/* QEMU-END */
+
/* The opcode formats table (blueprints for .insn pseudo mnemonic). */
static const struct s390_opcode s390_opformats[] =
@@ -1092,6 +1145,10 @@ static const struct s390_opcode s390_opcodes[] =
{ "agfi", OP16(0xc208LL), MASK_RIL_RI, INSTR_RIL_RI, 2, 4},
{ "slfi", OP16(0xc205LL), MASK_RIL_RU, INSTR_RIL_RU, 2, 4},
{ "slgfi", OP16(0xc204LL), MASK_RIL_RU, INSTR_RIL_RU, 2, 4},
+/* QEMU-ADD: */
+ { "msfi", OP16(0xc201ll), MASK_RIL_RI, INSTR_RIL_RI, 3, 6},
+ { "msgfi", OP16(0xc200ll), MASK_RIL_RI, INSTR_RIL_RI, 3, 6},
+/* QEMU-END */
{ "jg", OP16(0xc0f4LL), MASK_RIL_0P, INSTR_RIL_0P, 3, 2},
{ "jgno", OP16(0xc0e4LL), MASK_RIL_0P, INSTR_RIL_0P, 3, 2},
{ "jgnh", OP16(0xc0d4LL), MASK_RIL_0P, INSTR_RIL_0P, 3, 2},
@@ -1716,7 +1773,23 @@ static const struct s390_opcode s390_opcodes[] =
{ "pfpo", OP16(0x010aLL), MASK_E, INSTR_E, 2, 5},
{ "sckpf", OP16(0x0107LL), MASK_E, INSTR_E, 3, 0},
{ "upt", OP16(0x0102LL), MASK_E, INSTR_E, 3, 0},
- { "pr", OP16(0x0101LL), MASK_E, INSTR_E, 3, 0}
+ { "pr", OP16(0x0101LL), MASK_E, INSTR_E, 3, 0},
+
+/* QEMU-ADD: */
+ { "crj", OP48(0xec0000000076LL), MASK_RIE_MRRP, INSTR_RIE_MRRP, 3, 6},
+ { "cgrj", OP48(0xec0000000064LL), MASK_RIE_MRRP, INSTR_RIE_MRRP, 3, 6},
+ { "clrj", OP48(0xec0000000077LL), MASK_RIE_MRRP, INSTR_RIE_MRRP, 3, 6},
+ { "clgrj", OP48(0xec0000000065LL), MASK_RIE_MRRP, INSTR_RIE_MRRP, 3, 6},
+
+ { "cij", OP48(0xec000000007eLL), MASK_RIE_MRIP, INSTR_RIE_MRIP, 3, 6},
+ { "cgij", OP48(0xec000000007cLL), MASK_RIE_MRIP, INSTR_RIE_MRIP, 3, 6},
+ { "clij", OP48(0xec000000007fLL), MASK_RIE_MRIP, INSTR_RIE_MRIP, 3, 6},
+ { "clgij", OP48(0xec000000007dLL), MASK_RIE_MRIP, INSTR_RIE_MRIP, 3, 6},
+
+ { "lrl", OP16(0xc40dll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+ { "lgrl", OP16(0xc408ll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+ { "lgfrl", OP16(0xc40cll), MASK_RIL_RP, INSTR_RIL_RP, 3, 6},
+/* QEMU-END */
};
static const int s390_num_opcodes =
commit 402ce448af52a9dcb635b2f2020c469feeece3f5
Author: Richard Henderson <rth at twiddle.net>
Date: Fri Jun 4 12:14:16 2010 -0700
s390: Update disassembler to the last GPLv2 from binutils.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/s390-dis.c b/s390-dis.c
index 86dd84f..db460f8 100644
--- a/s390-dis.c
+++ b/s390-dis.c
@@ -1,3 +1,4 @@
+/* opcodes/s390-dis.c revision 1.12 */
/* s390-dis.c -- Disassemble S390 instructions
Copyright 2000, 2001, 2002, 2003, 2005 Free Software Foundation, Inc.
Contributed by Martin Schwidefsky (schwidefsky at de.ibm.com).
@@ -15,11 +16,14 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, see <http://www.gnu.org/licenses/>. */
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA. */
-#include <stdio.h>
+#include "qemu-common.h"
#include "dis-asm.h"
+/* include/opcode/s390.h revision 1.9 */
/* s390.h -- Header file for S390 opcode table
Copyright 2000, 2001, 2003 Free Software Foundation, Inc.
Contributed by Martin Schwidefsky (schwidefsky at de.ibm.com).
@@ -37,7 +41,9 @@
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, see <http://www.gnu.org/licenses/>. */
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA. */
#ifndef S390_H
#define S390_H
@@ -57,7 +63,8 @@ enum s390_opcode_cpu_val
S390_OPCODE_Z900,
S390_OPCODE_Z990,
S390_OPCODE_Z9_109,
- S390_OPCODE_Z9_EC
+ S390_OPCODE_Z9_EC,
+ S390_OPCODE_Z10
};
/* The opcode table is an array of struct s390_opcode. */
@@ -95,12 +102,13 @@ struct s390_opcode
/* The table itself is sorted by major opcode number, and is otherwise
in the order in which the disassembler should consider
instructions. */
-extern const struct s390_opcode s390_opcodes[];
-extern const int s390_num_opcodes;
+/* QEMU: Mark these static. */
+static const struct s390_opcode s390_opcodes[];
+static const int s390_num_opcodes;
/* A opcode format table for the .insn pseudo mnemonic. */
-extern const struct s390_opcode s390_opformats[];
-extern const int s390_num_opformats;
+static const struct s390_opcode s390_opformats[];
+static const int s390_num_opformats;
/* Values defined for the flags field of a struct powerpc_opcode. */
@@ -121,7 +129,7 @@ struct s390_operand
/* Elements in the table are retrieved by indexing with values from
the operands field of the powerpc_opcodes table. */
-extern const struct s390_operand s390_operands[];
+static const struct s390_operand s390_operands[];
/* Values defined for the flags field of a struct s390_operand. */
@@ -164,12 +172,13 @@ extern const struct s390_operand s390_operands[];
the instruction may be optional. */
#define S390_OPERAND_OPTIONAL 0x400
- #endif /* S390_H */
-
+#endif /* S390_H */
static int init_flag = 0;
static int opc_index[256];
-static int current_arch_mask = 0;
+
+/* QEMU: We've disabled the architecture check below. */
+/* static int current_arch_mask = 0; */
/* Set up index table for first opcode byte. */
@@ -188,17 +197,21 @@ init_disasm (struct disassemble_info *info)
(opcode[1].opcode[0] == opcode->opcode[0]))
opcode++;
}
-// switch (info->mach)
-// {
-// case bfd_mach_s390_31:
+
+#ifdef QEMU_DISABLE
+ switch (info->mach)
+ {
+ case bfd_mach_s390_31:
current_arch_mask = 1 << S390_OPCODE_ESA;
-// break;
-// case bfd_mach_s390_64:
-// current_arch_mask = 1 << S390_OPCODE_ZARCH;
-// break;
-// default:
-// abort ();
-// }
+ break;
+ case bfd_mach_s390_64:
+ current_arch_mask = 1 << S390_OPCODE_ZARCH;
+ break;
+ default:
+ abort ();
+ }
+#endif /* QEMU_DISABLE */
+
init_flag = 1;
}
@@ -297,9 +310,12 @@ print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info)
const struct s390_operand *operand;
const unsigned char *opindex;
+#ifdef QEMU_DISABLE
/* Check architecture. */
if (!(opcode->modes & current_arch_mask))
continue;
+#endif /* QEMU_DISABLE */
+
/* Check signature of the opcode. */
if ((buffer[1] & opcode->mask[1]) != opcode->opcode[1]
|| (buffer[2] & opcode->mask[2]) != opcode->opcode[2]
@@ -392,6 +408,8 @@ print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info)
return 1;
}
}
+
+/* opcodes/s390-opc.c revision 1.16 */
/* s390-opc.c -- S390 opcode list
Copyright 2000, 2001, 2003 Free Software Foundation, Inc.
Contributed by Martin Schwidefsky (schwidefsky at de.ibm.com).
@@ -409,9 +427,9 @@ print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info)
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, see <http://www.gnu.org/licenses/>. */
-
-#include <stdio.h>
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
+ 02110-1301, USA. */
/* This file holds the S390 opcode table. The opcode table
includes almost all of the extended instruction mnemonics. This
@@ -427,7 +445,7 @@ print_insn_s390 (bfd_vma memaddr, struct disassemble_info *info)
/* The operands table.
The fields are bits, shift, insert, extract, flags. */
-const struct s390_operand s390_operands[] =
+static const struct s390_operand s390_operands[] =
{
#define UNUSED 0
{ 0, 0, 0 }, /* Indicates the end of the operand list */
@@ -739,7 +757,7 @@ const struct s390_operand s390_operands[] =
/* The opcode formats table (blueprints for .insn pseudo mnemonic). */
-const struct s390_opcode s390_opformats[] =
+static const struct s390_opcode s390_opformats[] =
{
{ "e", OP8(0x00LL), MASK_E, INSTR_E, 3, 0 },
{ "ri", OP8(0x00LL), MASK_RI_RI, INSTR_RI_RI, 3, 0 },
@@ -765,9 +783,10 @@ const struct s390_opcode s390_opformats[] =
{ "ssf", OP8(0x00LL), MASK_SSF_RRDRD, INSTR_SSF_RRDRD,3, 0 },
};
-const int s390_num_opformats =
+static const int s390_num_opformats =
sizeof (s390_opformats) / sizeof (s390_opformats[0]);
+/* include "s390-opc.tab" generated from opcodes/s390-opc.txt rev 1.17 */
/* The opcode table. This file was generated by s390-mkopc.
The format of the opcode table is:
@@ -783,7 +802,7 @@ const int s390_num_opformats =
The disassembler reads the table in order and prints the first
instruction which matches. */
-const struct s390_opcode s390_opcodes[] =
+static const struct s390_opcode s390_opcodes[] =
{
{ "dp", OP8(0xfdLL), MASK_SS_LLRDRD, INSTR_SS_LLRDRD, 3, 0},
{ "mp", OP8(0xfcLL), MASK_SS_LLRDRD, INSTR_SS_LLRDRD, 3, 0},
@@ -1700,5 +1719,5 @@ const struct s390_opcode s390_opcodes[] =
{ "pr", OP16(0x0101LL), MASK_E, INSTR_E, 3, 0}
};
-const int s390_num_opcodes =
+static const int s390_num_opcodes =
sizeof (s390_opcodes) / sizeof (s390_opcodes[0]);
commit 5d8a4f8f4aa5b63eb3cc2a2234ffb8d4f0a2af50
Author: Richard Henderson <rth at twiddle.net>
Date: Thu Jun 3 17:35:17 2010 -0700
tcg-i386: Merge 64-bit generation.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/configure b/configure
index 46b8e39..fa7f299 100755
--- a/configure
+++ b/configure
@@ -2643,6 +2643,8 @@ if test "$ARCH" = "sparc64" ; then
cflags="-I\$(SRC_PATH)/tcg/sparc $cflags"
elif test "$ARCH" = "s390x" ; then
cflags="-I\$(SRC_PATH)/tcg/s390 $cflags"
+elif test "$ARCH" = "x86_64" ; then
+ cflags="-I\$(SRC_PATH)/tcg/i386 $cflags"
else
cflags="-I\$(SRC_PATH)/tcg/\$(ARCH) $cflags"
fi
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 147ba17..4d95200 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -24,18 +24,33 @@
#ifndef NDEBUG
static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
- "%eax",
- "%ecx",
- "%edx",
- "%ebx",
- "%esp",
- "%ebp",
- "%esi",
- "%edi",
+#if TCG_TARGET_REG_BITS == 64
+ "%rax", "%rcx", "%rdx", "%rbx", "%rsp", "%rbp", "%rsi", "%rdi",
+ "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
+#else
+ "%eax", "%ecx", "%edx", "%ebx", "%esp", "%ebp", "%esi", "%edi",
+#endif
};
#endif
static const int tcg_target_reg_alloc_order[] = {
+#if TCG_TARGET_REG_BITS == 64
+ TCG_REG_RBP,
+ TCG_REG_RBX,
+ TCG_REG_R12,
+ TCG_REG_R13,
+ TCG_REG_R14,
+ TCG_REG_R15,
+ TCG_REG_R10,
+ TCG_REG_R11,
+ TCG_REG_R9,
+ TCG_REG_R8,
+ TCG_REG_RCX,
+ TCG_REG_RDX,
+ TCG_REG_RSI,
+ TCG_REG_RDI,
+ TCG_REG_RAX,
+#else
TCG_REG_EBX,
TCG_REG_ESI,
TCG_REG_EDI,
@@ -43,10 +58,28 @@ static const int tcg_target_reg_alloc_order[] = {
TCG_REG_ECX,
TCG_REG_EDX,
TCG_REG_EAX,
+#endif
};
-static const int tcg_target_call_iarg_regs[3] = { TCG_REG_EAX, TCG_REG_EDX, TCG_REG_ECX };
-static const int tcg_target_call_oarg_regs[2] = { TCG_REG_EAX, TCG_REG_EDX };
+static const int tcg_target_call_iarg_regs[] = {
+#if TCG_TARGET_REG_BITS == 64
+ TCG_REG_RDI,
+ TCG_REG_RSI,
+ TCG_REG_RDX,
+ TCG_REG_RCX,
+ TCG_REG_R8,
+ TCG_REG_R9,
+#else
+ TCG_REG_EAX,
+ TCG_REG_EDX,
+ TCG_REG_ECX
+#endif
+};
+
+static const int tcg_target_call_oarg_regs[2] = {
+ TCG_REG_EAX,
+ TCG_REG_EDX
+};
static uint8_t *tb_ret_addr;
@@ -55,14 +88,15 @@ static void patch_reloc(uint8_t *code_ptr, int type,
{
value += addend;
switch(type) {
- case R_386_32:
- *(uint32_t *)code_ptr = value;
- break;
case R_386_PC32:
- *(uint32_t *)code_ptr = value - (long)code_ptr;
+ value -= (uintptr_t)code_ptr;
+ if (value != (int32_t)value) {
+ tcg_abort();
+ }
+ *(uint32_t *)code_ptr = value;
break;
case R_386_PC8:
- value -= (long)code_ptr;
+ value -= (uintptr_t)code_ptr;
if (value != (int8_t)value) {
tcg_abort();
}
@@ -76,6 +110,10 @@ static void patch_reloc(uint8_t *code_ptr, int type,
/* maximum number of register used for input function arguments */
static inline int tcg_target_get_call_iarg_regs_count(int flags)
{
+ if (TCG_TARGET_REG_BITS == 64) {
+ return 6;
+ }
+
flags &= TCG_CALL_TYPE_MASK;
switch(flags) {
case TCG_CALL_TYPE_STD:
@@ -122,20 +160,42 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
break;
case 'q':
ct->ct |= TCG_CT_REG;
- tcg_regset_set32(ct->u.regs, 0, 0xf);
+ if (TCG_TARGET_REG_BITS == 64) {
+ tcg_regset_set32(ct->u.regs, 0, 0xffff);
+ } else {
+ tcg_regset_set32(ct->u.regs, 0, 0xf);
+ }
break;
case 'r':
ct->ct |= TCG_CT_REG;
- tcg_regset_set32(ct->u.regs, 0, 0xff);
+ if (TCG_TARGET_REG_BITS == 64) {
+ tcg_regset_set32(ct->u.regs, 0, 0xffff);
+ } else {
+ tcg_regset_set32(ct->u.regs, 0, 0xff);
+ }
break;
/* qemu_ld/st address constraint */
case 'L':
ct->ct |= TCG_CT_REG;
- tcg_regset_set32(ct->u.regs, 0, 0xff);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_EAX);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_EDX);
+ if (TCG_TARGET_REG_BITS == 64) {
+ tcg_regset_set32(ct->u.regs, 0, 0xffff);
+ tcg_regset_reset_reg(ct->u.regs, TCG_REG_RSI);
+ tcg_regset_reset_reg(ct->u.regs, TCG_REG_RDI);
+ } else {
+ tcg_regset_set32(ct->u.regs, 0, 0xff);
+ tcg_regset_reset_reg(ct->u.regs, TCG_REG_EAX);
+ tcg_regset_reset_reg(ct->u.regs, TCG_REG_EDX);
+ }
+ break;
+
+ case 'e':
+ ct->ct |= TCG_CT_CONST_S32;
+ break;
+ case 'Z':
+ ct->ct |= TCG_CT_CONST_U32;
break;
+
default:
return -1;
}
@@ -148,16 +208,38 @@ static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
static inline int tcg_target_const_match(tcg_target_long val,
const TCGArgConstraint *arg_ct)
{
- int ct;
- ct = arg_ct->ct;
- if (ct & TCG_CT_CONST)
+ int ct = arg_ct->ct;
+ if (ct & TCG_CT_CONST) {
return 1;
- else
- return 0;
+ }
+ if ((ct & TCG_CT_CONST_S32) && val == (int32_t)val) {
+ return 1;
+ }
+ if ((ct & TCG_CT_CONST_U32) && val == (uint32_t)val) {
+ return 1;
+ }
+ return 0;
}
+#if TCG_TARGET_REG_BITS == 64
+# define LOWREGMASK(x) ((x) & 7)
+#else
+# define LOWREGMASK(x) (x)
+#endif
+
#define P_EXT 0x100 /* 0x0f opcode prefix */
#define P_DATA16 0x200 /* 0x66 opcode prefix */
+#if TCG_TARGET_REG_BITS == 64
+# define P_ADDR32 0x400 /* 0x67 opcode prefix */
+# define P_REXW 0x800 /* Set REX.W = 1 */
+# define P_REXB_R 0x1000 /* REG field as byte register */
+# define P_REXB_RM 0x2000 /* R/M field as byte register */
+#else
+# define P_ADDR32 0
+# define P_REXW 0
+# define P_REXB_R 0
+# define P_REXB_RM 0
+#endif
#define OPC_ARITH_EvIz (0x81)
#define OPC_ARITH_EvIb (0x83)
@@ -179,9 +261,11 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define OPC_MOVB_EvGv (0x88) /* stores, more or less */
#define OPC_MOVL_EvGv (0x89) /* stores, more or less */
#define OPC_MOVL_GvEv (0x8b) /* loads, more or less */
+#define OPC_MOVL_EvIz (0xc7)
#define OPC_MOVL_Iv (0xb8)
#define OPC_MOVSBL (0xbe | P_EXT)
#define OPC_MOVSWL (0xbf | P_EXT)
+#define OPC_MOVSLQ (0x63 | P_REXW)
#define OPC_MOVZBL (0xb6 | P_EXT)
#define OPC_MOVZWL (0xb7 | P_EXT)
#define OPC_POP_r32 (0x58)
@@ -189,7 +273,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define OPC_PUSH_Iv (0x68)
#define OPC_PUSH_Ib (0x6a)
#define OPC_RET (0xc3)
-#define OPC_SETCC (0x90 | P_EXT) /* ... plus condition code */
+#define OPC_SETCC (0x90 | P_EXT | P_REXB_RM) /* ... plus cc */
#define OPC_SHIFT_1 (0xd1)
#define OPC_SHIFT_Ib (0xc1)
#define OPC_SHIFT_cl (0xd3)
@@ -226,6 +310,8 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define EXT3_IDIV 7
/* Group 5 opcode extensions for 0xff. To be used with OPC_GRP5. */
+#define EXT5_INC_Ev 0
+#define EXT5_DEC_Ev 1
#define EXT5_CALLN_Ev 2
#define EXT5_JMPN_Ev 4
@@ -261,7 +347,45 @@ static const uint8_t tcg_cond_to_jcc[10] = {
[TCG_COND_GTU] = JCC_JA,
};
-static inline void tcg_out_opc(TCGContext *s, int opc)
+#if TCG_TARGET_REG_BITS == 64
+static void tcg_out_opc(TCGContext *s, int opc, int r, int rm, int x)
+{
+ int rex;
+
+ if (opc & P_DATA16) {
+ /* We should never be asking for both 16 and 64-bit operation. */
+ assert((opc & P_REXW) == 0);
+ tcg_out8(s, 0x66);
+ }
+ if (opc & P_ADDR32) {
+ tcg_out8(s, 0x67);
+ }
+
+ rex = 0;
+ rex |= (opc & P_REXW) >> 8; /* REX.W */
+ rex |= (r & 8) >> 1; /* REX.R */
+ rex |= (x & 8) >> 2; /* REX.X */
+ rex |= (rm & 8) >> 3; /* REX.B */
+
+ /* P_REXB_{R,RM} indicates that the given register is the low byte.
+ For %[abcd]l we need no REX prefix, but for %{si,di,bp,sp}l we do,
+ as otherwise the encoding indicates %[abcd]h. Note that the values
+ that are ORed in merely indicate that the REX byte must be present;
+ those bits get discarded in output. */
+ rex |= opc & (r >= 4 ? P_REXB_R : 0);
+ rex |= opc & (rm >= 4 ? P_REXB_RM : 0);
+
+ if (rex) {
+ tcg_out8(s, (uint8_t)(rex | 0x40));
+ }
+
+ if (opc & P_EXT) {
+ tcg_out8(s, 0x0f);
+ }
+ tcg_out8(s, opc);
+}
+#else
+static void tcg_out_opc(TCGContext *s, int opc)
{
if (opc & P_DATA16) {
tcg_out8(s, 0x66);
@@ -271,36 +395,69 @@ static inline void tcg_out_opc(TCGContext *s, int opc)
}
tcg_out8(s, opc);
}
+/* Discard the register arguments to tcg_out_opc early, so as not to penalize
+ the 32-bit compilation paths. This method works with all versions of gcc,
+ whereas relying on optimization may not be able to exclude them. */
+#define tcg_out_opc(s, opc, r, rm, x) (tcg_out_opc)(s, opc)
+#endif
-static inline void tcg_out_modrm(TCGContext *s, int opc, int r, int rm)
+static void tcg_out_modrm(TCGContext *s, int opc, int r, int rm)
{
- tcg_out_opc(s, opc);
- tcg_out8(s, 0xc0 | (r << 3) | rm);
+ tcg_out_opc(s, opc, r, rm, 0);
+ tcg_out8(s, 0xc0 | (LOWREGMASK(r) << 3) | LOWREGMASK(rm));
}
/* Output an opcode with a full "rm + (index<<shift) + offset" address mode.
- We handle either RM and INDEX missing with a -1 value. */
+ We handle either RM and INDEX missing with a negative value. In 64-bit
+ mode for absolute addresses, ~RM is the size of the immediate operand
+ that will follow the instruction. */
static void tcg_out_modrm_sib_offset(TCGContext *s, int opc, int r, int rm,
- int index, int shift, int32_t offset)
+ int index, int shift,
+ tcg_target_long offset)
{
int mod, len;
- if (index == -1 && rm == -1) {
- /* Absolute address. */
- tcg_out_opc(s, opc);
- tcg_out8(s, (r << 3) | 5);
- tcg_out32(s, offset);
- return;
- }
+ if (index < 0 && rm < 0) {
+ if (TCG_TARGET_REG_BITS == 64) {
+ /* Try for a rip-relative addressing mode. This has replaced
+ the 32-bit-mode absolute addressing encoding. */
+ tcg_target_long pc = (tcg_target_long)s->code_ptr + 5 + ~rm;
+ tcg_target_long disp = offset - pc;
+ if (disp == (int32_t)disp) {
+ tcg_out_opc(s, opc, r, 0, 0);
+ tcg_out8(s, (LOWREGMASK(r) << 3) | 5);
+ tcg_out32(s, disp);
+ return;
+ }
- tcg_out_opc(s, opc);
+ /* Try for an absolute address encoding. This requires the
+ use of the MODRM+SIB encoding and is therefore larger than
+ rip-relative addressing. */
+ if (offset == (int32_t)offset) {
+ tcg_out_opc(s, opc, r, 0, 0);
+ tcg_out8(s, (LOWREGMASK(r) << 3) | 4);
+ tcg_out8(s, (4 << 3) | 5);
+ tcg_out32(s, offset);
+ return;
+ }
+
+ /* ??? The memory isn't directly addressable. */
+ tcg_abort();
+ } else {
+ /* Absolute address. */
+ tcg_out_opc(s, opc, r, 0, 0);
+ tcg_out8(s, (r << 3) | 5);
+ tcg_out32(s, offset);
+ return;
+ }
+ }
/* Find the length of the immediate addend. Note that the encoding
that would be used for (%ebp) indicates absolute addressing. */
- if (rm == -1) {
+ if (rm < 0) {
mod = 0, len = 4, rm = 5;
- } else if (offset == 0 && rm != TCG_REG_EBP) {
+ } else if (offset == 0 && LOWREGMASK(rm) != TCG_REG_EBP) {
mod = 0, len = 0;
} else if (offset == (int8_t)offset) {
mod = 0x40, len = 1;
@@ -310,22 +467,25 @@ static void tcg_out_modrm_sib_offset(TCGContext *s, int opc, int r, int rm,
/* Use a single byte MODRM format if possible. Note that the encoding
that would be used for %esp is the escape to the two byte form. */
- if (index == -1 && rm != TCG_REG_ESP) {
+ if (index < 0 && LOWREGMASK(rm) != TCG_REG_ESP) {
/* Single byte MODRM format. */
- tcg_out8(s, mod | (r << 3) | rm);
+ tcg_out_opc(s, opc, r, rm, 0);
+ tcg_out8(s, mod | (LOWREGMASK(r) << 3) | LOWREGMASK(rm));
} else {
/* Two byte MODRM+SIB format. */
/* Note that the encoding that would place %esp into the index
- field indicates no index register. */
- if (index == -1) {
+ field indicates no index register. In 64-bit mode, the REX.X
+ bit counts, so %r12 can be used as the index. */
+ if (index < 0) {
index = 4;
} else {
assert(index != TCG_REG_ESP);
}
- tcg_out8(s, mod | (r << 3) | 4);
- tcg_out8(s, (shift << 6) | (index << 3) | rm);
+ tcg_out_opc(s, opc, r, rm, index);
+ tcg_out8(s, mod | (LOWREGMASK(r) << 3) | 4);
+ tcg_out8(s, (shift << 6) | (LOWREGMASK(index) << 3) | LOWREGMASK(rm));
}
if (len == 1) {
@@ -335,9 +495,9 @@ static void tcg_out_modrm_sib_offset(TCGContext *s, int opc, int r, int rm,
}
}
-/* rm == -1 means no register index */
-static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r, int rm,
- int32_t offset)
+/* A simplification of the above with no index or shift. */
+static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r,
+ int rm, tcg_target_long offset)
{
tcg_out_modrm_sib_offset(s, opc, r, rm, -1, 0, offset);
}
@@ -345,58 +505,75 @@ static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r, int rm,
/* Generate dest op= src. Uses the same ARITH_* codes as tgen_arithi. */
static inline void tgen_arithr(TCGContext *s, int subop, int dest, int src)
{
- tcg_out_modrm(s, OPC_ARITH_GvEv + (subop << 3), dest, src);
+ /* Propagate an opcode prefix, such as P_REXW. */
+ int ext = subop & ~0x7;
+ subop &= 0x7;
+
+ tcg_out_modrm(s, OPC_ARITH_GvEv + (subop << 3) + ext, dest, src);
}
static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
{
if (arg != ret) {
- tcg_out_modrm(s, OPC_MOVL_GvEv, ret, arg);
+ int opc = OPC_MOVL_GvEv + (type == TCG_TYPE_I64 ? P_REXW : 0);
+ tcg_out_modrm(s, opc, ret, arg);
}
}
-static inline void tcg_out_movi(TCGContext *s, TCGType type,
- int ret, int32_t arg)
+static void tcg_out_movi(TCGContext *s, TCGType type,
+ int ret, tcg_target_long arg)
{
if (arg == 0) {
tgen_arithr(s, ARITH_XOR, ret, ret);
+ return;
+ } else if (arg == (uint32_t)arg || type == TCG_TYPE_I32) {
+ tcg_out_opc(s, OPC_MOVL_Iv + LOWREGMASK(ret), 0, ret, 0);
+ tcg_out32(s, arg);
+ } else if (arg == (int32_t)arg) {
+ tcg_out_modrm(s, OPC_MOVL_EvIz + P_REXW, 0, ret);
+ tcg_out32(s, arg);
} else {
- tcg_out8(s, OPC_MOVL_Iv + ret);
+ tcg_out_opc(s, OPC_MOVL_Iv + P_REXW + LOWREGMASK(ret), 0, ret, 0);
tcg_out32(s, arg);
+ tcg_out32(s, arg >> 31 >> 1);
}
}
static inline void tcg_out_pushi(TCGContext *s, tcg_target_long val)
{
if (val == (int8_t)val) {
- tcg_out_opc(s, OPC_PUSH_Ib);
+ tcg_out_opc(s, OPC_PUSH_Ib, 0, 0, 0);
tcg_out8(s, val);
- } else {
- tcg_out_opc(s, OPC_PUSH_Iv);
+ } else if (val == (int32_t)val) {
+ tcg_out_opc(s, OPC_PUSH_Iv, 0, 0, 0);
tcg_out32(s, val);
+ } else {
+ tcg_abort();
}
}
static inline void tcg_out_push(TCGContext *s, int reg)
{
- tcg_out_opc(s, OPC_PUSH_r32 + reg);
+ tcg_out_opc(s, OPC_PUSH_r32 + LOWREGMASK(reg), 0, reg, 0);
}
static inline void tcg_out_pop(TCGContext *s, int reg)
{
- tcg_out_opc(s, OPC_POP_r32 + reg);
+ tcg_out_opc(s, OPC_POP_r32 + LOWREGMASK(reg), 0, reg, 0);
}
static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
int arg1, tcg_target_long arg2)
{
- tcg_out_modrm_offset(s, OPC_MOVL_GvEv, ret, arg1, arg2);
+ int opc = OPC_MOVL_GvEv + (type == TCG_TYPE_I64 ? P_REXW : 0);
+ tcg_out_modrm_offset(s, opc, ret, arg1, arg2);
}
static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
int arg1, tcg_target_long arg2)
{
- tcg_out_modrm_offset(s, OPC_MOVL_EvGv, arg, arg1, arg2);
+ int opc = OPC_MOVL_EvGv + (type == TCG_TYPE_I64 ? P_REXW : 0);
+ tcg_out_modrm_offset(s, opc, arg, arg1, arg2);
}
static void tcg_out_shifti(TCGContext *s, int subopc, int reg, int count)
@@ -406,35 +583,35 @@ static void tcg_out_shifti(TCGContext *s, int subopc, int reg, int count)
subopc &= 0x7;
if (count == 1) {
- tcg_out_modrm(s, OPC_SHIFT_1 | ext, subopc, reg);
+ tcg_out_modrm(s, OPC_SHIFT_1 + ext, subopc, reg);
} else {
- tcg_out_modrm(s, OPC_SHIFT_Ib | ext, subopc, reg);
+ tcg_out_modrm(s, OPC_SHIFT_Ib + ext, subopc, reg);
tcg_out8(s, count);
}
}
static inline void tcg_out_bswap32(TCGContext *s, int reg)
{
- tcg_out_opc(s, OPC_BSWAP + reg);
+ tcg_out_opc(s, OPC_BSWAP + LOWREGMASK(reg), 0, reg, 0);
}
static inline void tcg_out_rolw_8(TCGContext *s, int reg)
{
- tcg_out_shifti(s, SHIFT_ROL | P_DATA16, reg, 8);
+ tcg_out_shifti(s, SHIFT_ROL + P_DATA16, reg, 8);
}
static inline void tcg_out_ext8u(TCGContext *s, int dest, int src)
{
/* movzbl */
- assert(src < 4);
- tcg_out_modrm(s, OPC_MOVZBL, dest, src);
+ assert(src < 4 || TCG_TARGET_REG_BITS == 64);
+ tcg_out_modrm(s, OPC_MOVZBL + P_REXB_RM, dest, src);
}
-static void tcg_out_ext8s(TCGContext *s, int dest, int src)
+static void tcg_out_ext8s(TCGContext *s, int dest, int src, int rexw)
{
/* movsbl */
- assert(src < 4);
- tcg_out_modrm(s, OPC_MOVSBL, dest, src);
+ assert(src < 4 || TCG_TARGET_REG_BITS == 64);
+ tcg_out_modrm(s, OPC_MOVSBL + P_REXB_RM + rexw, dest, src);
}
static inline void tcg_out_ext16u(TCGContext *s, int dest, int src)
@@ -443,38 +620,94 @@ static inline void tcg_out_ext16u(TCGContext *s, int dest, int src)
tcg_out_modrm(s, OPC_MOVZWL, dest, src);
}
-static inline void tcg_out_ext16s(TCGContext *s, int dest, int src)
+static inline void tcg_out_ext16s(TCGContext *s, int dest, int src, int rexw)
{
- /* movswl */
- tcg_out_modrm(s, OPC_MOVSWL, dest, src);
+ /* movsw[lq] */
+ tcg_out_modrm(s, OPC_MOVSWL + rexw, dest, src);
}
-static inline void tgen_arithi(TCGContext *s, int c, int r0,
- int32_t val, int cf)
+static inline void tcg_out_ext32u(TCGContext *s, int dest, int src)
{
+ /* 32-bit mov zero extends. */
+ tcg_out_modrm(s, OPC_MOVL_GvEv, dest, src);
+}
+
+static inline void tcg_out_ext32s(TCGContext *s, int dest, int src)
+{
+ tcg_out_modrm(s, OPC_MOVSLQ, dest, src);
+}
+
+static inline void tcg_out_bswap64(TCGContext *s, int reg)
+{
+ tcg_out_opc(s, OPC_BSWAP + P_REXW + LOWREGMASK(reg), 0, reg, 0);
+}
+
+static void tgen_arithi(TCGContext *s, int c, int r0,
+ tcg_target_long val, int cf)
+{
+ int rexw = 0;
+
+ if (TCG_TARGET_REG_BITS == 64) {
+ rexw = c & -8;
+ c &= 7;
+ }
+
/* ??? While INC is 2 bytes shorter than ADDL $1, they also induce
partial flags update stalls on Pentium4 and are not recommended
by current Intel optimization manuals. */
if (!cf && (c == ARITH_ADD || c == ARITH_SUB) && (val == 1 || val == -1)) {
- int opc = ((c == ARITH_ADD) ^ (val < 0) ? OPC_INC_r32 : OPC_DEC_r32);
- tcg_out_opc(s, opc + r0);
- } else if (val == (int8_t)val) {
- tcg_out_modrm(s, OPC_ARITH_EvIb, c, r0);
+ _Bool is_inc = (c == ARITH_ADD) ^ (val < 0);
+ if (TCG_TARGET_REG_BITS == 64) {
+ /* The single-byte increment encodings are re-tasked as the
+ REX prefixes. Use the MODRM encoding. */
+ tcg_out_modrm(s, OPC_GRP5 + rexw,
+ (is_inc ? EXT5_INC_Ev : EXT5_DEC_Ev), r0);
+ } else {
+ tcg_out8(s, (is_inc ? OPC_INC_r32 : OPC_DEC_r32) + r0);
+ }
+ return;
+ }
+
+ if (c == ARITH_AND) {
+ if (TCG_TARGET_REG_BITS == 64) {
+ if (val == 0xffffffffu) {
+ tcg_out_ext32u(s, r0, r0);
+ return;
+ }
+ if (val == (uint32_t)val) {
+ /* AND with no high bits set can use a 32-bit operation. */
+ rexw = 0;
+ }
+ }
+ if (val == 0xffu) {
+ tcg_out_ext8u(s, r0, r0);
+ return;
+ }
+ if (val == 0xffffu) {
+ tcg_out_ext16u(s, r0, r0);
+ return;
+ }
+ }
+
+ if (val == (int8_t)val) {
+ tcg_out_modrm(s, OPC_ARITH_EvIb + rexw, c, r0);
tcg_out8(s, val);
- } else if (c == ARITH_AND && val == 0xffu && r0 < 4) {
- tcg_out_ext8u(s, r0, r0);
- } else if (c == ARITH_AND && val == 0xffffu) {
- tcg_out_ext16u(s, r0, r0);
- } else {
- tcg_out_modrm(s, OPC_ARITH_EvIz, c, r0);
+ return;
+ }
+ if (rexw == 0 || val == (int32_t)val) {
+ tcg_out_modrm(s, OPC_ARITH_EvIz + rexw, c, r0);
tcg_out32(s, val);
+ return;
}
+
+ tcg_abort();
}
static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
{
- if (val != 0)
- tgen_arithi(s, ARITH_ADD, reg, val, 0);
+ if (val != 0) {
+ tgen_arithi(s, ARITH_ADD + P_REXW, reg, val, 0);
+ }
}
/* Use SMALL != 0 to force a short forward branch. */
@@ -501,7 +734,7 @@ static void tcg_out_jxx(TCGContext *s, int opc, int label_index, int small)
tcg_out8(s, OPC_JMP_long);
tcg_out32(s, val - 5);
} else {
- tcg_out_opc(s, OPC_JCC_long + opc);
+ tcg_out_opc(s, OPC_JCC_long + opc, 0, 0, 0);
tcg_out32(s, val - 6);
}
}
@@ -517,7 +750,7 @@ static void tcg_out_jxx(TCGContext *s, int opc, int label_index, int small)
if (opc == -1) {
tcg_out8(s, OPC_JMP_long);
} else {
- tcg_out_opc(s, OPC_JCC_long + opc);
+ tcg_out_opc(s, OPC_JCC_long + opc, 0, 0, 0);
}
tcg_out_reloc(s, s->code_ptr, R_386_PC32, label_index, -4);
s->code_ptr += 4;
@@ -525,28 +758,37 @@ static void tcg_out_jxx(TCGContext *s, int opc, int label_index, int small)
}
static void tcg_out_cmp(TCGContext *s, TCGArg arg1, TCGArg arg2,
- int const_arg2)
+ int const_arg2, int rexw)
{
if (const_arg2) {
if (arg2 == 0) {
/* test r, r */
- tcg_out_modrm(s, OPC_TESTL, arg1, arg1);
+ tcg_out_modrm(s, OPC_TESTL + rexw, arg1, arg1);
} else {
- tgen_arithi(s, ARITH_CMP, arg1, arg2, 0);
+ tgen_arithi(s, ARITH_CMP + rexw, arg1, arg2, 0);
}
} else {
- tgen_arithr(s, ARITH_CMP, arg1, arg2);
+ tgen_arithr(s, ARITH_CMP + rexw, arg1, arg2);
}
}
-static void tcg_out_brcond(TCGContext *s, TCGCond cond,
- TCGArg arg1, TCGArg arg2, int const_arg2,
- int label_index, int small)
+static void tcg_out_brcond32(TCGContext *s, TCGCond cond,
+ TCGArg arg1, TCGArg arg2, int const_arg2,
+ int label_index, int small)
{
- tcg_out_cmp(s, arg1, arg2, const_arg2);
+ tcg_out_cmp(s, arg1, arg2, const_arg2, 0);
tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index, small);
}
+#if TCG_TARGET_REG_BITS == 64
+static void tcg_out_brcond64(TCGContext *s, TCGCond cond,
+ TCGArg arg1, TCGArg arg2, int const_arg2,
+ int label_index, int small)
+{
+ tcg_out_cmp(s, arg1, arg2, const_arg2, P_REXW);
+ tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index, small);
+}
+#else
/* XXX: we implement it at the target level to avoid having to
handle cross basic blocks temporaries */
static void tcg_out_brcond2(TCGContext *s, const TCGArg *args,
@@ -556,87 +798,97 @@ static void tcg_out_brcond2(TCGContext *s, const TCGArg *args,
label_next = gen_new_label();
switch(args[4]) {
case TCG_COND_EQ:
- tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2],
- label_next, 1);
- tcg_out_brcond(s, TCG_COND_EQ, args[1], args[3], const_args[3],
- args[5], small);
+ tcg_out_brcond32(s, TCG_COND_NE, args[0], args[2], const_args[2],
+ label_next, 1);
+ tcg_out_brcond32(s, TCG_COND_EQ, args[1], args[3], const_args[3],
+ args[5], small);
break;
case TCG_COND_NE:
- tcg_out_brcond(s, TCG_COND_NE, args[0], args[2], const_args[2],
- args[5], small);
- tcg_out_brcond(s, TCG_COND_NE, args[1], args[3], const_args[3],
- args[5], small);
+ tcg_out_brcond32(s, TCG_COND_NE, args[0], args[2], const_args[2],
+ args[5], small);
+ tcg_out_brcond32(s, TCG_COND_NE, args[1], args[3], const_args[3],
+ args[5], small);
break;
case TCG_COND_LT:
- tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3],
- args[5], small);
+ tcg_out_brcond32(s, TCG_COND_LT, args[1], args[3], const_args[3],
+ args[5], small);
tcg_out_jxx(s, JCC_JNE, label_next, 1);
- tcg_out_brcond(s, TCG_COND_LTU, args[0], args[2], const_args[2],
- args[5], small);
+ tcg_out_brcond32(s, TCG_COND_LTU, args[0], args[2], const_args[2],
+ args[5], small);
break;
case TCG_COND_LE:
- tcg_out_brcond(s, TCG_COND_LT, args[1], args[3], const_args[3],
- args[5], small);
+ tcg_out_brcond32(s, TCG_COND_LT, args[1], args[3], const_args[3],
+ args[5], small);
tcg_out_jxx(s, JCC_JNE, label_next, 1);
- tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2],
- args[5], small);
+ tcg_out_brcond32(s, TCG_COND_LEU, args[0], args[2], const_args[2],
+ args[5], small);
break;
case TCG_COND_GT:
- tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3],
- args[5], small);
+ tcg_out_brcond32(s, TCG_COND_GT, args[1], args[3], const_args[3],
+ args[5], small);
tcg_out_jxx(s, JCC_JNE, label_next, 1);
- tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2],
- args[5], small);
+ tcg_out_brcond32(s, TCG_COND_GTU, args[0], args[2], const_args[2],
+ args[5], small);
break;
case TCG_COND_GE:
- tcg_out_brcond(s, TCG_COND_GT, args[1], args[3], const_args[3],
- args[5], small);
+ tcg_out_brcond32(s, TCG_COND_GT, args[1], args[3], const_args[3],
+ args[5], small);
tcg_out_jxx(s, JCC_JNE, label_next, 1);
- tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2],
- args[5], small);
+ tcg_out_brcond32(s, TCG_COND_GEU, args[0], args[2], const_args[2],
+ args[5], small);
break;
case TCG_COND_LTU:
- tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3],
- args[5], small);
+ tcg_out_brcond32(s, TCG_COND_LTU, args[1], args[3], const_args[3],
+ args[5], small);
tcg_out_jxx(s, JCC_JNE, label_next, 1);
- tcg_out_brcond(s, TCG_COND_LTU, args[0], args[2], const_args[2],
- args[5], small);
+ tcg_out_brcond32(s, TCG_COND_LTU, args[0], args[2], const_args[2],
+ args[5], small);
break;
case TCG_COND_LEU:
- tcg_out_brcond(s, TCG_COND_LTU, args[1], args[3], const_args[3],
- args[5], small);
+ tcg_out_brcond32(s, TCG_COND_LTU, args[1], args[3], const_args[3],
+ args[5], small);
tcg_out_jxx(s, JCC_JNE, label_next, 1);
- tcg_out_brcond(s, TCG_COND_LEU, args[0], args[2], const_args[2],
- args[5], small);
+ tcg_out_brcond32(s, TCG_COND_LEU, args[0], args[2], const_args[2],
+ args[5], small);
break;
case TCG_COND_GTU:
- tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3],
- args[5], small);
+ tcg_out_brcond32(s, TCG_COND_GTU, args[1], args[3], const_args[3],
+ args[5], small);
tcg_out_jxx(s, JCC_JNE, label_next, 1);
- tcg_out_brcond(s, TCG_COND_GTU, args[0], args[2], const_args[2],
- args[5], small);
+ tcg_out_brcond32(s, TCG_COND_GTU, args[0], args[2], const_args[2],
+ args[5], small);
break;
case TCG_COND_GEU:
- tcg_out_brcond(s, TCG_COND_GTU, args[1], args[3], const_args[3],
- args[5], small);
+ tcg_out_brcond32(s, TCG_COND_GTU, args[1], args[3], const_args[3],
+ args[5], small);
tcg_out_jxx(s, JCC_JNE, label_next, 1);
- tcg_out_brcond(s, TCG_COND_GEU, args[0], args[2], const_args[2],
- args[5], small);
+ tcg_out_brcond32(s, TCG_COND_GEU, args[0], args[2], const_args[2],
+ args[5], small);
break;
default:
tcg_abort();
}
tcg_out_label(s, label_next, (tcg_target_long)s->code_ptr);
}
+#endif
-static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGArg dest,
- TCGArg arg1, TCGArg arg2, int const_arg2)
+static void tcg_out_setcond32(TCGContext *s, TCGCond cond, TCGArg dest,
+ TCGArg arg1, TCGArg arg2, int const_arg2)
{
- tcg_out_cmp(s, arg1, arg2, const_arg2);
+ tcg_out_cmp(s, arg1, arg2, const_arg2, 0);
tcg_out_modrm(s, OPC_SETCC | tcg_cond_to_jcc[cond], 0, dest);
tcg_out_ext8u(s, dest, dest);
}
+#if TCG_TARGET_REG_BITS == 64
+static void tcg_out_setcond64(TCGContext *s, TCGCond cond, TCGArg dest,
+ TCGArg arg1, TCGArg arg2, int const_arg2)
+{
+ tcg_out_cmp(s, arg1, arg2, const_arg2, P_REXW);
+ tcg_out_modrm(s, OPC_SETCC | tcg_cond_to_jcc[cond], 0, dest);
+ tcg_out_ext8u(s, dest, dest);
+}
+#else
static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
const int *const_args)
{
@@ -678,11 +930,30 @@ static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
tcg_out_label(s, label_over, (tcg_target_long)s->code_ptr);
}
}
+#endif
+
+static void tcg_out_branch(TCGContext *s, int call, tcg_target_long dest)
+{
+ tcg_target_long disp = dest - (tcg_target_long)s->code_ptr - 5;
+
+ if (disp == (int32_t)disp) {
+ tcg_out_opc(s, call ? OPC_CALL_Jz : OPC_JMP_long, 0, 0, 0);
+ tcg_out32(s, disp);
+ } else {
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R10, dest);
+ tcg_out_modrm(s, OPC_GRP5,
+ call ? EXT5_CALLN_Ev : EXT5_JMPN_Ev, TCG_REG_R10);
+ }
+}
+
+static inline void tcg_out_calli(TCGContext *s, tcg_target_long dest)
+{
+ tcg_out_branch(s, 1, dest);
+}
-static void tcg_out_calli(TCGContext *s, tcg_target_long dest)
+static void tcg_out_jmp(TCGContext *s, tcg_target_long dest)
{
- tcg_out_opc(s, OPC_CALL_Jz);
- tcg_out32(s, dest - (tcg_target_long)s->code_ptr - 4);
+ tcg_out_branch(s, 0, dest);
}
#if defined(CONFIG_SOFTMMU)
@@ -718,11 +989,12 @@ static void *qemu_st_helpers[4] = {
LABEL_PTRS is filled with 1 (32-bit addresses) or 2 (64-bit addresses)
positions of the displacements of forward jumps to the TLB miss case.
- EAX is loaded with the low part of the address. In the TLB hit case,
- it has been adjusted as indicated by the TLB and so is a host address.
- In the TLB miss case, it continues to hold a guest address.
+ First argument register is loaded with the low part of the address.
+ In the TLB hit case, it has been adjusted as indicated by the TLB
+ and so is a host address. In the TLB miss case, it continues to
+ hold a guest address.
- EDX is clobbered. */
+ Second argument register is clobbered. */
static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx,
int mem_index, int s_bits,
@@ -730,32 +1002,42 @@ static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx,
uint8_t **label_ptr, int which)
{
const int addrlo = args[addrlo_idx];
- const int r0 = TCG_REG_EAX;
- const int r1 = TCG_REG_EDX;
+ const int r0 = tcg_target_call_iarg_regs[0];
+ const int r1 = tcg_target_call_iarg_regs[1];
+ TCGType type = TCG_TYPE_I32;
+ int rexw = 0;
+
+ if (TCG_TARGET_REG_BITS == 64 && TARGET_LONG_BITS == 64) {
+ type = TCG_TYPE_I64;
+ rexw = P_REXW;
+ }
- tcg_out_mov(s, TCG_TYPE_I32, r1, addrlo);
- tcg_out_mov(s, TCG_TYPE_I32, r0, addrlo);
+ tcg_out_mov(s, type, r1, addrlo);
+ tcg_out_mov(s, type, r0, addrlo);
- tcg_out_shifti(s, SHIFT_SHR, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
+ tcg_out_shifti(s, SHIFT_SHR + rexw, r1,
+ TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
- tgen_arithi(s, ARITH_AND, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
- tgen_arithi(s, ARITH_AND, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
+ tgen_arithi(s, ARITH_AND + rexw, r0,
+ TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
+ tgen_arithi(s, ARITH_AND + rexw, r1,
+ (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
- tcg_out_modrm_sib_offset(s, OPC_LEA, r1, TCG_AREG0, r1, 0,
+ tcg_out_modrm_sib_offset(s, OPC_LEA + P_REXW, r1, TCG_AREG0, r1, 0,
offsetof(CPUState, tlb_table[mem_index][0])
+ which);
/* cmp 0(r1), r0 */
- tcg_out_modrm_offset(s, OPC_CMP_GvEv, r0, r1, 0);
+ tcg_out_modrm_offset(s, OPC_CMP_GvEv + rexw, r0, r1, 0);
- tcg_out_mov(s, TCG_TYPE_I32, r0, addrlo);
+ tcg_out_mov(s, type, r0, addrlo);
/* jne label1 */
tcg_out8(s, OPC_JCC_short + JCC_JNE);
label_ptr[0] = s->code_ptr;
s->code_ptr++;
- if (TARGET_LONG_BITS == 64) {
+ if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
/* cmp 4(r1), addrhi */
tcg_out_modrm_offset(s, OPC_CMP_GvEv, args[addrlo_idx+1], r1, 4);
@@ -768,7 +1050,7 @@ static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx,
/* TLB Hit. */
/* add addend(r1), r0 */
- tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
+ tcg_out_modrm_offset(s, OPC_ADD_GvEv + P_REXW, r0, r1,
offsetof(CPUTLBEntry, addend) - which);
}
#endif
@@ -783,26 +1065,24 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi,
#endif
switch (sizeop) {
case 0:
- /* movzbl */
tcg_out_modrm_offset(s, OPC_MOVZBL, datalo, base, ofs);
break;
case 0 | 4:
- /* movsbl */
- tcg_out_modrm_offset(s, OPC_MOVSBL, datalo, base, ofs);
+ tcg_out_modrm_offset(s, OPC_MOVSBL + P_REXW, datalo, base, ofs);
break;
case 1:
- /* movzwl */
tcg_out_modrm_offset(s, OPC_MOVZWL, datalo, base, ofs);
if (bswap) {
tcg_out_rolw_8(s, datalo);
}
break;
case 1 | 4:
- /* movswl */
- tcg_out_modrm_offset(s, OPC_MOVSWL, datalo, base, ofs);
if (bswap) {
+ tcg_out_modrm_offset(s, OPC_MOVZWL, datalo, base, ofs);
tcg_out_rolw_8(s, datalo);
- tcg_out_modrm(s, OPC_MOVSWL, datalo, datalo);
+ tcg_out_modrm(s, OPC_MOVSWL + P_REXW, datalo, datalo);
+ } else {
+ tcg_out_modrm_offset(s, OPC_MOVSWL + P_REXW, datalo, base, ofs);
}
break;
case 2:
@@ -811,22 +1091,40 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi,
tcg_out_bswap32(s, datalo);
}
break;
- case 3:
+#if TCG_TARGET_REG_BITS == 64
+ case 2 | 4:
if (bswap) {
- int t = datalo;
- datalo = datahi;
- datahi = t;
- }
- if (base != datalo) {
tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
- tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4);
+ tcg_out_bswap32(s, datalo);
+ tcg_out_ext32s(s, datalo, datalo);
} else {
- tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4);
- tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
+ tcg_out_modrm_offset(s, OPC_MOVSLQ, datalo, base, ofs);
}
- if (bswap) {
- tcg_out_bswap32(s, datalo);
- tcg_out_bswap32(s, datahi);
+ break;
+#endif
+ case 3:
+ if (TCG_TARGET_REG_BITS == 64) {
+ tcg_out_ld(s, TCG_TYPE_I64, datalo, base, ofs);
+ if (bswap) {
+ tcg_out_bswap64(s, datalo);
+ }
+ } else {
+ if (bswap) {
+ int t = datalo;
+ datalo = datahi;
+ datahi = t;
+ }
+ if (base != datalo) {
+ tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
+ tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4);
+ } else {
+ tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4);
+ tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
+ }
+ if (bswap) {
+ tcg_out_bswap32(s, datalo);
+ tcg_out_bswap32(s, datahi);
+ }
}
break;
default:
@@ -849,20 +1147,21 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
data_reg = args[0];
addrlo_idx = 1;
- if (opc == 3) {
+ if (TCG_TARGET_REG_BITS == 32 && opc == 3) {
data_reg2 = args[1];
addrlo_idx = 2;
}
#if defined(CONFIG_SOFTMMU)
- mem_index = args[addrlo_idx + (TARGET_LONG_BITS / 32)];
+ mem_index = args[addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS)];
s_bits = opc & 3;
tcg_out_tlb_load(s, addrlo_idx, mem_index, s_bits, args,
label_ptr, offsetof(CPUTLBEntry, addr_read));
/* TLB Hit. */
- tcg_out_qemu_ld_direct(s, data_reg, data_reg2, TCG_REG_EAX, 0, opc);
+ tcg_out_qemu_ld_direct(s, data_reg, data_reg2,
+ tcg_target_call_iarg_regs[0], 0, opc);
/* jmp label2 */
tcg_out8(s, OPC_JMP_short);
@@ -873,14 +1172,14 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
/* label1: */
*label_ptr[0] = s->code_ptr - label_ptr[0] - 1;
- if (TARGET_LONG_BITS == 64) {
+ if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
*label_ptr[1] = s->code_ptr - label_ptr[1] - 1;
}
/* XXX: move that code at the end of the TB */
- /* EAX is already loaded. */
+ /* The first argument is already loaded with addrlo. */
arg_idx = 1;
- if (TARGET_LONG_BITS == 64) {
+ if (TCG_TARGET_REG_BITS == 32 && TARGET_LONG_BITS == 64) {
tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[arg_idx++],
args[addrlo_idx + 1]);
}
@@ -890,10 +1189,10 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
switch(opc) {
case 0 | 4:
- tcg_out_ext8s(s, data_reg, TCG_REG_EAX);
+ tcg_out_ext8s(s, data_reg, TCG_REG_EAX, P_REXW);
break;
case 1 | 4:
- tcg_out_ext16s(s, data_reg, TCG_REG_EAX);
+ tcg_out_ext16s(s, data_reg, TCG_REG_EAX, P_REXW);
break;
case 0:
tcg_out_ext8u(s, data_reg, TCG_REG_EAX);
@@ -902,26 +1201,52 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
tcg_out_ext16u(s, data_reg, TCG_REG_EAX);
break;
case 2:
- default:
tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
break;
+#if TCG_TARGET_REG_BITS == 64
+ case 2 | 4:
+ tcg_out_ext32s(s, data_reg, TCG_REG_EAX);
+ break;
+#endif
case 3:
- if (data_reg == TCG_REG_EDX) {
+ if (TCG_TARGET_REG_BITS == 64) {
+ tcg_out_mov(s, TCG_TYPE_I64, data_reg, TCG_REG_RAX);
+ } else if (data_reg == TCG_REG_EDX) {
/* xchg %edx, %eax */
- tcg_out_opc(s, OPC_XCHG_ax_r32 + TCG_REG_EDX);
+ tcg_out_opc(s, OPC_XCHG_ax_r32 + TCG_REG_EDX, 0, 0, 0);
tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_EAX);
} else {
tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_EDX);
}
break;
+ default:
+ tcg_abort();
}
/* label2: */
*label_ptr[2] = s->code_ptr - label_ptr[2] - 1;
#else
- tcg_out_qemu_ld_direct(s, data_reg, data_reg2,
- args[addrlo_idx], GUEST_BASE, opc);
+ {
+ int32_t offset = GUEST_BASE;
+ int base = args[addrlo_idx];
+
+ if (TCG_TARGET_REG_BITS == 64) {
+ /* ??? We assume all operations have left us with register
+ contents that are zero extended. So far this appears to
+ be true. If we want to enforce this, we can either do
+ an explicit zero-extension here, or (if GUEST_BASE == 0)
+ use the ADDR32 prefix. For now, do nothing. */
+
+ if (offset != GUEST_BASE) {
+ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_RDI, GUEST_BASE);
+ tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_RDI, base);
+ base = TCG_REG_RDI, offset = 0;
+ }
+ }
+
+ tcg_out_qemu_ld_direct(s, data_reg, data_reg2, base, offset, opc);
+ }
#endif
}
@@ -936,12 +1261,12 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
/* ??? Ideally we wouldn't need a scratch register. For user-only,
we could perform the bswap twice to restore the original value
instead of moving to the scratch. But as it is, the L constraint
- means that EDX is definitely free here. */
- int scratch = TCG_REG_EDX;
+ means that the second argument reg is definitely free here. */
+ int scratch = tcg_target_call_iarg_regs[1];
switch (sizeop) {
case 0:
- tcg_out_modrm_offset(s, OPC_MOVB_EvGv, datalo, base, ofs);
+ tcg_out_modrm_offset(s, OPC_MOVB_EvGv + P_REXB_R, datalo, base, ofs);
break;
case 1:
if (bswap) {
@@ -949,9 +1274,7 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
tcg_out_rolw_8(s, scratch);
datalo = scratch;
}
- /* movw */
- tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16,
- datalo, base, ofs);
+ tcg_out_modrm_offset(s, OPC_MOVL_EvGv + P_DATA16, datalo, base, ofs);
break;
case 2:
if (bswap) {
@@ -962,7 +1285,14 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
tcg_out_st(s, TCG_TYPE_I32, datalo, base, ofs);
break;
case 3:
- if (bswap) {
+ if (TCG_TARGET_REG_BITS == 64) {
+ if (bswap) {
+ tcg_out_mov(s, TCG_TYPE_I64, scratch, datalo);
+ tcg_out_bswap64(s, scratch);
+ datalo = scratch;
+ }
+ tcg_out_st(s, TCG_TYPE_I64, datalo, base, ofs);
+ } else if (bswap) {
tcg_out_mov(s, TCG_TYPE_I32, scratch, datahi);
tcg_out_bswap32(s, scratch);
tcg_out_st(s, TCG_TYPE_I32, scratch, base, ofs);
@@ -992,20 +1322,21 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
data_reg = args[0];
addrlo_idx = 1;
- if (opc == 3) {
+ if (TCG_TARGET_REG_BITS == 32 && opc == 3) {
data_reg2 = args[1];
addrlo_idx = 2;
}
#if defined(CONFIG_SOFTMMU)
- mem_index = args[addrlo_idx + (TARGET_LONG_BITS / 32)];
+ mem_index = args[addrlo_idx + 1 + (TARGET_LONG_BITS > TCG_TARGET_REG_BITS)];
s_bits = opc;
tcg_out_tlb_load(s, addrlo_idx, mem_index, s_bits, args,
label_ptr, offsetof(CPUTLBEntry, addr_write));
/* TLB Hit. */
- tcg_out_qemu_st_direct(s, data_reg, data_reg2, TCG_REG_EAX, 0, opc);
+ tcg_out_qemu_st_direct(s, data_reg, data_reg2,
+ tcg_target_call_iarg_regs[0], 0, opc);
/* jmp label2 */
tcg_out8(s, OPC_JMP_short);
@@ -1016,12 +1347,17 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
/* label1: */
*label_ptr[0] = s->code_ptr - label_ptr[0] - 1;
- if (TARGET_LONG_BITS == 64) {
+ if (TARGET_LONG_BITS > TCG_TARGET_REG_BITS) {
*label_ptr[1] = s->code_ptr - label_ptr[1] - 1;
}
/* XXX: move that code at the end of the TB */
- if (TARGET_LONG_BITS == 32) {
+ if (TCG_TARGET_REG_BITS == 64) {
+ tcg_out_mov(s, (opc == 3 ? TCG_TYPE_I64 : TCG_TYPE_I32),
+ TCG_REG_RSI, data_reg);
+ tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RDX, mem_index);
+ stack_adjust = 0;
+ } else if (TARGET_LONG_BITS == 32) {
tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_EDX, data_reg);
if (opc == 3) {
tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_ECX, data_reg2);
@@ -1058,7 +1394,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
tcg_out_calli(s, (tcg_target_long)qemu_st_helpers[s_bits]);
- if (stack_adjust == 4) {
+ if (stack_adjust == (TCG_TARGET_REG_BITS / 8)) {
/* Pop and discard. This is 2 bytes smaller than the add. */
tcg_out_pop(s, TCG_REG_ECX);
} else if (stack_adjust != 0) {
@@ -1068,21 +1404,48 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
/* label2: */
*label_ptr[2] = s->code_ptr - label_ptr[2] - 1;
#else
- tcg_out_qemu_st_direct(s, data_reg, data_reg2,
- args[addrlo_idx], GUEST_BASE, opc);
+ {
+ int32_t offset = GUEST_BASE;
+ int base = args[addrlo_idx];
+
+ if (TCG_TARGET_REG_BITS == 64) {
+ /* ??? We assume all operations have left us with register
+ contents that are zero extended. So far this appears to
+ be true. If we want to enforce this, we can either do
+ an explicit zero-extension here, or (if GUEST_BASE == 0)
+ use the ADDR32 prefix. For now, do nothing. */
+
+ if (offset != GUEST_BASE) {
+ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_RDI, GUEST_BASE);
+ tgen_arithr(s, ARITH_ADD + P_REXW, TCG_REG_RDI, base);
+ base = TCG_REG_RDI, offset = 0;
+ }
+ }
+
+ tcg_out_qemu_st_direct(s, data_reg, data_reg2, base, offset, opc);
+ }
#endif
}
static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
const TCGArg *args, const int *const_args)
{
- int c;
+ int c, rexw = 0;
+
+#if TCG_TARGET_REG_BITS == 64
+# define OP_32_64(x) \
+ case glue(glue(INDEX_op_, x), _i64): \
+ rexw = P_REXW; /* FALLTHRU */ \
+ case glue(glue(INDEX_op_, x), _i32)
+#else
+# define OP_32_64(x) \
+ case glue(glue(INDEX_op_, x), _i32)
+#endif
switch(opc) {
case INDEX_op_exit_tb:
- tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EAX, args[0]);
- tcg_out8(s, OPC_JMP_long); /* jmp tb_ret_addr */
- tcg_out32(s, tb_ret_addr - s->code_ptr - 4);
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_EAX, args[0]);
+ tcg_out_jmp(s, (tcg_target_long) tb_ret_addr);
break;
case INDEX_op_goto_tb:
if (s->tb_jmp_offset) {
@@ -1107,8 +1470,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
break;
case INDEX_op_jmp:
if (const_args[0]) {
- tcg_out8(s, OPC_JMP_long);
- tcg_out32(s, args[0] - (tcg_target_long)s->code_ptr - 4);
+ tcg_out_jmp(s, args[0]);
} else {
/* jmp *reg */
tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, args[0]);
@@ -1120,38 +1482,43 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
case INDEX_op_movi_i32:
tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
break;
- case INDEX_op_ld8u_i32:
- /* movzbl */
+ OP_32_64(ld8u):
+ /* Note that we can ignore REXW for the zero-extend to 64-bit. */
tcg_out_modrm_offset(s, OPC_MOVZBL, args[0], args[1], args[2]);
break;
- case INDEX_op_ld8s_i32:
- /* movsbl */
- tcg_out_modrm_offset(s, OPC_MOVSBL, args[0], args[1], args[2]);
+ OP_32_64(ld8s):
+ tcg_out_modrm_offset(s, OPC_MOVSBL + rexw, args[0], args[1], args[2]);
break;
- case INDEX_op_ld16u_i32:
- /* movzwl */
+ OP_32_64(ld16u):
+ /* Note that we can ignore REXW for the zero-extend to 64-bit. */
tcg_out_modrm_offset(s, OPC_MOVZWL, args[0], args[1], args[2]);
break;
- case INDEX_op_ld16s_i32:
- /* movswl */
- tcg_out_modrm_offset(s, OPC_MOVSWL, args[0], args[1], args[2]);
+ OP_32_64(ld16s):
+ tcg_out_modrm_offset(s, OPC_MOVSWL + rexw, args[0], args[1], args[2]);
break;
+#if TCG_TARGET_REG_BITS == 64
+ case INDEX_op_ld32u_i64:
+#endif
case INDEX_op_ld_i32:
tcg_out_ld(s, TCG_TYPE_I32, args[0], args[1], args[2]);
break;
- case INDEX_op_st8_i32:
- /* movb */
- tcg_out_modrm_offset(s, OPC_MOVB_EvGv, args[0], args[1], args[2]);
+
+ OP_32_64(st8):
+ tcg_out_modrm_offset(s, OPC_MOVB_EvGv | P_REXB_R,
+ args[0], args[1], args[2]);
break;
- case INDEX_op_st16_i32:
- /* movw */
+ OP_32_64(st16):
tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16,
args[0], args[1], args[2]);
break;
+#if TCG_TARGET_REG_BITS == 64
+ case INDEX_op_st32_i64:
+#endif
case INDEX_op_st_i32:
tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]);
break;
- case INDEX_op_add_i32:
+
+ OP_32_64(add):
/* For 3-operand addition, use LEA. */
if (args[0] != args[1]) {
TCGArg a0 = args[0], a1 = args[1], a2 = args[2], c3 = 0;
@@ -1161,147 +1528,117 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
} else if (a0 == a2) {
/* Watch out for dest = src + dest, since we've removed
the matching constraint on the add. */
- tgen_arithr(s, ARITH_ADD, a0, a1);
+ tgen_arithr(s, ARITH_ADD + rexw, a0, a1);
break;
}
- tcg_out_modrm_sib_offset(s, OPC_LEA, a0, a1, a2, 0, c3);
+ tcg_out_modrm_sib_offset(s, OPC_LEA + rexw, a0, a1, a2, 0, c3);
break;
}
c = ARITH_ADD;
goto gen_arith;
- case INDEX_op_sub_i32:
+ OP_32_64(sub):
c = ARITH_SUB;
goto gen_arith;
- case INDEX_op_and_i32:
+ OP_32_64(and):
c = ARITH_AND;
goto gen_arith;
- case INDEX_op_or_i32:
+ OP_32_64(or):
c = ARITH_OR;
goto gen_arith;
- case INDEX_op_xor_i32:
+ OP_32_64(xor):
c = ARITH_XOR;
goto gen_arith;
gen_arith:
if (const_args[2]) {
- tgen_arithi(s, c, args[0], args[2], 0);
+ tgen_arithi(s, c + rexw, args[0], args[2], 0);
} else {
- tgen_arithr(s, c, args[0], args[2]);
+ tgen_arithr(s, c + rexw, args[0], args[2]);
}
break;
- case INDEX_op_mul_i32:
+
+ OP_32_64(mul):
if (const_args[2]) {
int32_t val;
val = args[2];
if (val == (int8_t)val) {
- tcg_out_modrm(s, OPC_IMUL_GvEvIb, args[0], args[0]);
+ tcg_out_modrm(s, OPC_IMUL_GvEvIb + rexw, args[0], args[0]);
tcg_out8(s, val);
} else {
- tcg_out_modrm(s, OPC_IMUL_GvEvIz, args[0], args[0]);
+ tcg_out_modrm(s, OPC_IMUL_GvEvIz + rexw, args[0], args[0]);
tcg_out32(s, val);
}
} else {
- tcg_out_modrm(s, OPC_IMUL_GvEv, args[0], args[2]);
+ tcg_out_modrm(s, OPC_IMUL_GvEv + rexw, args[0], args[2]);
}
break;
- case INDEX_op_mulu2_i32:
- tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_MUL, args[3]);
- break;
- case INDEX_op_div2_i32:
- tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_IDIV, args[4]);
+
+ OP_32_64(div2):
+ tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_IDIV, args[4]);
break;
- case INDEX_op_divu2_i32:
- tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_DIV, args[4]);
+ OP_32_64(divu2):
+ tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_DIV, args[4]);
break;
- case INDEX_op_shl_i32:
+
+ OP_32_64(shl):
c = SHIFT_SHL;
- gen_shift32:
- if (const_args[2]) {
- tcg_out_shifti(s, c, args[0], args[2]);
- } else {
- tcg_out_modrm(s, OPC_SHIFT_cl, c, args[0]);
- }
- break;
- case INDEX_op_shr_i32:
+ goto gen_shift;
+ OP_32_64(shr):
c = SHIFT_SHR;
- goto gen_shift32;
- case INDEX_op_sar_i32:
+ goto gen_shift;
+ OP_32_64(sar):
c = SHIFT_SAR;
- goto gen_shift32;
- case INDEX_op_rotl_i32:
+ goto gen_shift;
+ OP_32_64(rotl):
c = SHIFT_ROL;
- goto gen_shift32;
- case INDEX_op_rotr_i32:
+ goto gen_shift;
+ OP_32_64(rotr):
c = SHIFT_ROR;
- goto gen_shift32;
-
- case INDEX_op_add2_i32:
- if (const_args[4]) {
- tgen_arithi(s, ARITH_ADD, args[0], args[4], 1);
- } else {
- tgen_arithr(s, ARITH_ADD, args[0], args[4]);
- }
- if (const_args[5]) {
- tgen_arithi(s, ARITH_ADC, args[1], args[5], 1);
+ goto gen_shift;
+ gen_shift:
+ if (const_args[2]) {
+ tcg_out_shifti(s, c + rexw, args[0], args[2]);
} else {
- tgen_arithr(s, ARITH_ADC, args[1], args[5]);
- }
- break;
- case INDEX_op_sub2_i32:
- if (const_args[4]) {
- tgen_arithi(s, ARITH_SUB, args[0], args[4], 1);
- } else {
- tgen_arithr(s, ARITH_SUB, args[0], args[4]);
- }
- if (const_args[5]) {
- tgen_arithi(s, ARITH_SBB, args[1], args[5], 1);
- } else {
- tgen_arithr(s, ARITH_SBB, args[1], args[5]);
+ tcg_out_modrm(s, OPC_SHIFT_cl + rexw, c, args[0]);
}
break;
+
case INDEX_op_brcond_i32:
- tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
- args[3], 0);
+ tcg_out_brcond32(s, args[2], args[0], args[1], const_args[1],
+ args[3], 0);
break;
- case INDEX_op_brcond2_i32:
- tcg_out_brcond2(s, args, const_args, 0);
+ case INDEX_op_setcond_i32:
+ tcg_out_setcond32(s, args[3], args[0], args[1],
+ args[2], const_args[2]);
break;
- case INDEX_op_bswap16_i32:
+ OP_32_64(bswap16):
tcg_out_rolw_8(s, args[0]);
break;
- case INDEX_op_bswap32_i32:
+ OP_32_64(bswap32):
tcg_out_bswap32(s, args[0]);
break;
- case INDEX_op_neg_i32:
- tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_NEG, args[0]);
+ OP_32_64(neg):
+ tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_NEG, args[0]);
break;
-
- case INDEX_op_not_i32:
- tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_NOT, args[0]);
+ OP_32_64(not):
+ tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_NOT, args[0]);
break;
- case INDEX_op_ext8s_i32:
- tcg_out_ext8s(s, args[0], args[1]);
+ OP_32_64(ext8s):
+ tcg_out_ext8s(s, args[0], args[1], rexw);
break;
- case INDEX_op_ext16s_i32:
- tcg_out_ext16s(s, args[0], args[1]);
+ OP_32_64(ext16s):
+ tcg_out_ext16s(s, args[0], args[1], rexw);
break;
- case INDEX_op_ext8u_i32:
+ OP_32_64(ext8u):
tcg_out_ext8u(s, args[0], args[1]);
break;
- case INDEX_op_ext16u_i32:
+ OP_32_64(ext16u):
tcg_out_ext16u(s, args[0], args[1]);
break;
- case INDEX_op_setcond_i32:
- tcg_out_setcond(s, args[3], args[0], args[1], args[2], const_args[2]);
- break;
- case INDEX_op_setcond2_i32:
- tcg_out_setcond2(s, args, const_args);
- break;
-
case INDEX_op_qemu_ld8u:
tcg_out_qemu_ld(s, args, 0);
break;
@@ -1314,6 +1651,9 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
case INDEX_op_qemu_ld16s:
tcg_out_qemu_ld(s, args, 1 | 4);
break;
+#if TCG_TARGET_REG_BITS == 64
+ case INDEX_op_qemu_ld32u:
+#endif
case INDEX_op_qemu_ld32:
tcg_out_qemu_ld(s, args, 2);
break;
@@ -1334,9 +1674,82 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_qemu_st(s, args, 3);
break;
+#if TCG_TARGET_REG_BITS == 32
+ case INDEX_op_brcond2_i32:
+ tcg_out_brcond2(s, args, const_args, 0);
+ break;
+ case INDEX_op_setcond2_i32:
+ tcg_out_setcond2(s, args, const_args);
+ break;
+ case INDEX_op_mulu2_i32:
+ tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_MUL, args[3]);
+ break;
+ case INDEX_op_add2_i32:
+ if (const_args[4]) {
+ tgen_arithi(s, ARITH_ADD, args[0], args[4], 1);
+ } else {
+ tgen_arithr(s, ARITH_ADD, args[0], args[4]);
+ }
+ if (const_args[5]) {
+ tgen_arithi(s, ARITH_ADC, args[1], args[5], 1);
+ } else {
+ tgen_arithr(s, ARITH_ADC, args[1], args[5]);
+ }
+ break;
+ case INDEX_op_sub2_i32:
+ if (const_args[4]) {
+ tgen_arithi(s, ARITH_SUB, args[0], args[4], 1);
+ } else {
+ tgen_arithr(s, ARITH_SUB, args[0], args[4]);
+ }
+ if (const_args[5]) {
+ tgen_arithi(s, ARITH_SBB, args[1], args[5], 1);
+ } else {
+ tgen_arithr(s, ARITH_SBB, args[1], args[5]);
+ }
+ break;
+#else /* TCG_TARGET_REG_BITS == 64 */
+ case INDEX_op_movi_i64:
+ tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]);
+ break;
+ case INDEX_op_ld32s_i64:
+ tcg_out_modrm_offset(s, OPC_MOVSLQ, args[0], args[1], args[2]);
+ break;
+ case INDEX_op_ld_i64:
+ tcg_out_ld(s, TCG_TYPE_I64, args[0], args[1], args[2]);
+ break;
+ case INDEX_op_st_i64:
+ tcg_out_st(s, TCG_TYPE_I64, args[0], args[1], args[2]);
+ break;
+ case INDEX_op_qemu_ld32s:
+ tcg_out_qemu_ld(s, args, 2 | 4);
+ break;
+
+ case INDEX_op_brcond_i64:
+ tcg_out_brcond64(s, args[2], args[0], args[1], const_args[1],
+ args[3], 0);
+ break;
+ case INDEX_op_setcond_i64:
+ tcg_out_setcond64(s, args[3], args[0], args[1],
+ args[2], const_args[2]);
+ break;
+
+ case INDEX_op_bswap64_i64:
+ tcg_out_bswap64(s, args[0]);
+ break;
+ case INDEX_op_ext32u_i64:
+ tcg_out_ext32u(s, args[0], args[1]);
+ break;
+ case INDEX_op_ext32s_i64:
+ tcg_out_ext32s(s, args[0], args[1]);
+ break;
+#endif
+
default:
tcg_abort();
}
+
+#undef OP_32_64
}
static const TCGTargetOpDef x86_op_defs[] = {
@@ -1359,7 +1772,6 @@ static const TCGTargetOpDef x86_op_defs[] = {
{ INDEX_op_add_i32, { "r", "r", "ri" } },
{ INDEX_op_sub_i32, { "r", "0", "ri" } },
{ INDEX_op_mul_i32, { "r", "0", "ri" } },
- { INDEX_op_mulu2_i32, { "a", "d", "a", "r" } },
{ INDEX_op_div2_i32, { "a", "d", "0", "1", "r" } },
{ INDEX_op_divu2_i32, { "a", "d", "0", "1", "r" } },
{ INDEX_op_and_i32, { "r", "0", "ri" } },
@@ -1374,10 +1786,6 @@ static const TCGTargetOpDef x86_op_defs[] = {
{ INDEX_op_brcond_i32, { "r", "ri" } },
- { INDEX_op_add2_i32, { "r", "r", "0", "1", "ri", "ri" } },
- { INDEX_op_sub2_i32, { "r", "r", "0", "1", "ri", "ri" } },
- { INDEX_op_brcond2_i32, { "r", "r", "ri", "ri" } },
-
{ INDEX_op_bswap16_i32, { "r", "0" } },
{ INDEX_op_bswap32_i32, { "r", "0" } },
@@ -1391,9 +1799,75 @@ static const TCGTargetOpDef x86_op_defs[] = {
{ INDEX_op_ext16u_i32, { "r", "r" } },
{ INDEX_op_setcond_i32, { "q", "r", "ri" } },
+
+#if TCG_TARGET_REG_BITS == 32
+ { INDEX_op_mulu2_i32, { "a", "d", "a", "r" } },
+ { INDEX_op_add2_i32, { "r", "r", "0", "1", "ri", "ri" } },
+ { INDEX_op_sub2_i32, { "r", "r", "0", "1", "ri", "ri" } },
+ { INDEX_op_brcond2_i32, { "r", "r", "ri", "ri" } },
{ INDEX_op_setcond2_i32, { "r", "r", "r", "ri", "ri" } },
+#else
+ { INDEX_op_mov_i64, { "r", "r" } },
+ { INDEX_op_movi_i64, { "r" } },
+ { INDEX_op_ld8u_i64, { "r", "r" } },
+ { INDEX_op_ld8s_i64, { "r", "r" } },
+ { INDEX_op_ld16u_i64, { "r", "r" } },
+ { INDEX_op_ld16s_i64, { "r", "r" } },
+ { INDEX_op_ld32u_i64, { "r", "r" } },
+ { INDEX_op_ld32s_i64, { "r", "r" } },
+ { INDEX_op_ld_i64, { "r", "r" } },
+ { INDEX_op_st8_i64, { "r", "r" } },
+ { INDEX_op_st16_i64, { "r", "r" } },
+ { INDEX_op_st32_i64, { "r", "r" } },
+ { INDEX_op_st_i64, { "r", "r" } },
+
+ { INDEX_op_add_i64, { "r", "0", "re" } },
+ { INDEX_op_mul_i64, { "r", "0", "re" } },
+ { INDEX_op_div2_i64, { "a", "d", "0", "1", "r" } },
+ { INDEX_op_divu2_i64, { "a", "d", "0", "1", "r" } },
+ { INDEX_op_sub_i64, { "r", "0", "re" } },
+ { INDEX_op_and_i64, { "r", "0", "reZ" } },
+ { INDEX_op_or_i64, { "r", "0", "re" } },
+ { INDEX_op_xor_i64, { "r", "0", "re" } },
+
+ { INDEX_op_shl_i64, { "r", "0", "ci" } },
+ { INDEX_op_shr_i64, { "r", "0", "ci" } },
+ { INDEX_op_sar_i64, { "r", "0", "ci" } },
+ { INDEX_op_rotl_i64, { "r", "0", "ci" } },
+ { INDEX_op_rotr_i64, { "r", "0", "ci" } },
+
+ { INDEX_op_brcond_i64, { "r", "re" } },
+ { INDEX_op_setcond_i64, { "r", "r", "re" } },
+
+ { INDEX_op_bswap16_i64, { "r", "0" } },
+ { INDEX_op_bswap32_i64, { "r", "0" } },
+ { INDEX_op_bswap64_i64, { "r", "0" } },
+ { INDEX_op_neg_i64, { "r", "0" } },
+ { INDEX_op_not_i64, { "r", "0" } },
+
+ { INDEX_op_ext8s_i64, { "r", "r" } },
+ { INDEX_op_ext16s_i64, { "r", "r" } },
+ { INDEX_op_ext32s_i64, { "r", "r" } },
+ { INDEX_op_ext8u_i64, { "r", "r" } },
+ { INDEX_op_ext16u_i64, { "r", "r" } },
+ { INDEX_op_ext32u_i64, { "r", "r" } },
+#endif
-#if TARGET_LONG_BITS == 32
+#if TCG_TARGET_REG_BITS == 64
+ { INDEX_op_qemu_ld8u, { "r", "L" } },
+ { INDEX_op_qemu_ld8s, { "r", "L" } },
+ { INDEX_op_qemu_ld16u, { "r", "L" } },
+ { INDEX_op_qemu_ld16s, { "r", "L" } },
+ { INDEX_op_qemu_ld32, { "r", "L" } },
+ { INDEX_op_qemu_ld32u, { "r", "L" } },
+ { INDEX_op_qemu_ld32s, { "r", "L" } },
+ { INDEX_op_qemu_ld64, { "r", "L" } },
+
+ { INDEX_op_qemu_st8, { "L", "L" } },
+ { INDEX_op_qemu_st16, { "L", "L" } },
+ { INDEX_op_qemu_st32, { "L", "L" } },
+ { INDEX_op_qemu_st64, { "L", "L" } },
+#elif TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
{ INDEX_op_qemu_ld8u, { "r", "L" } },
{ INDEX_op_qemu_ld8s, { "r", "L" } },
{ INDEX_op_qemu_ld16u, { "r", "L" } },
@@ -1422,11 +1896,19 @@ static const TCGTargetOpDef x86_op_defs[] = {
};
static int tcg_target_callee_save_regs[] = {
- /* TCG_REG_EBP, */ /* currently used for the global env, so no
- need to save */
+#if TCG_TARGET_REG_BITS == 64
+ TCG_REG_RBP,
+ TCG_REG_RBX,
+ TCG_REG_R12,
+ TCG_REG_R13,
+ /* TCG_REG_R14, */ /* Currently used for the global env. */
+ TCG_REG_R15,
+#else
+ /* TCG_REG_EBP, */ /* Currently used for the global env. */
TCG_REG_EBX,
TCG_REG_ESI,
TCG_REG_EDI,
+#endif
};
/* Generate global QEMU prologue and epilogue code */
@@ -1435,27 +1917,34 @@ static void tcg_target_qemu_prologue(TCGContext *s)
int i, frame_size, push_size, stack_addend;
/* TB prologue */
- /* save all callee saved registers */
- for(i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
+
+ /* Save all callee saved registers. */
+ for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
tcg_out_push(s, tcg_target_callee_save_regs[i]);
}
- /* reserve some stack space */
- push_size = 4 + ARRAY_SIZE(tcg_target_callee_save_regs) * 4;
+
+ /* Reserve some stack space. */
+ push_size = 1 + ARRAY_SIZE(tcg_target_callee_save_regs);
+ push_size *= TCG_TARGET_REG_BITS / 8;
+
frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE;
frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
~(TCG_TARGET_STACK_ALIGN - 1);
stack_addend = frame_size - push_size;
tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
- tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, TCG_REG_EAX); /* jmp *%eax */
+ /* jmp *tb. */
+ tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, tcg_target_call_iarg_regs[0]);
/* TB epilogue */
tb_ret_addr = s->code_ptr;
+
tcg_out_addi(s, TCG_REG_ESP, stack_addend);
- for(i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {
+
+ for (i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {
tcg_out_pop(s, tcg_target_callee_save_regs[i]);
}
- tcg_out_opc(s, OPC_RET);
+ tcg_out_opc(s, OPC_RET, 0, 0, 0);
}
static void tcg_target_init(TCGContext *s)
@@ -1466,12 +1955,25 @@ static void tcg_target_init(TCGContext *s)
tcg_abort();
#endif
- tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xff);
+ if (TCG_TARGET_REG_BITS == 64) {
+ tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
+ tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffff);
+ } else {
+ tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xff);
+ }
tcg_regset_clear(tcg_target_call_clobber_regs);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EAX);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_EDX);
tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_ECX);
+ if (TCG_TARGET_REG_BITS == 64) {
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_RDI);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_RSI);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R8);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R9);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R10);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R11);
+ }
tcg_regset_clear(s->reserved_regs);
tcg_regset_set_reg(s->reserved_regs, TCG_REG_ESP);
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
index ca1d730..bfafbfc 100644
--- a/tcg/i386/tcg-target.h
+++ b/tcg/i386/tcg-target.h
@@ -23,10 +23,18 @@
*/
#define TCG_TARGET_I386 1
-#define TCG_TARGET_REG_BITS 32
+#if defined(__x86_64__)
+# define TCG_TARGET_REG_BITS 64
+#else
+# define TCG_TARGET_REG_BITS 32
+#endif
//#define TCG_TARGET_WORDS_BIGENDIAN
-#define TCG_TARGET_NB_REGS 8
+#if TCG_TARGET_REG_BITS == 64
+# define TCG_TARGET_NB_REGS 16
+#else
+# define TCG_TARGET_NB_REGS 8
+#endif
enum {
TCG_REG_EAX = 0,
@@ -37,8 +45,30 @@ enum {
TCG_REG_EBP,
TCG_REG_ESI,
TCG_REG_EDI,
+
+ /* 64-bit registers; always define the symbols to avoid
+ too much if-deffing. */
+ TCG_REG_R8,
+ TCG_REG_R9,
+ TCG_REG_R10,
+ TCG_REG_R11,
+ TCG_REG_R12,
+ TCG_REG_R13,
+ TCG_REG_R14,
+ TCG_REG_R15,
+ TCG_REG_RAX = TCG_REG_EAX,
+ TCG_REG_RCX = TCG_REG_ECX,
+ TCG_REG_RDX = TCG_REG_EDX,
+ TCG_REG_RBX = TCG_REG_EBX,
+ TCG_REG_RSP = TCG_REG_ESP,
+ TCG_REG_RBP = TCG_REG_EBP,
+ TCG_REG_RSI = TCG_REG_ESI,
+ TCG_REG_RDI = TCG_REG_EDI,
};
+#define TCG_CT_CONST_S32 0x100
+#define TCG_CT_CONST_U32 0x200
+
/* used for function call generation */
#define TCG_REG_CALL_STACK TCG_REG_ESP
#define TCG_TARGET_STACK_ALIGN 16
@@ -61,10 +91,35 @@ enum {
// #define TCG_TARGET_HAS_nand_i32
// #define TCG_TARGET_HAS_nor_i32
+#if TCG_TARGET_REG_BITS == 64
+#define TCG_TARGET_HAS_div2_i64
+#define TCG_TARGET_HAS_rot_i64
+#define TCG_TARGET_HAS_ext8s_i64
+#define TCG_TARGET_HAS_ext16s_i64
+#define TCG_TARGET_HAS_ext32s_i64
+#define TCG_TARGET_HAS_ext8u_i64
+#define TCG_TARGET_HAS_ext16u_i64
+#define TCG_TARGET_HAS_ext32u_i64
+#define TCG_TARGET_HAS_bswap16_i64
+#define TCG_TARGET_HAS_bswap32_i64
+#define TCG_TARGET_HAS_bswap64_i64
+#define TCG_TARGET_HAS_neg_i64
+#define TCG_TARGET_HAS_not_i64
+// #define TCG_TARGET_HAS_andc_i64
+// #define TCG_TARGET_HAS_orc_i64
+// #define TCG_TARGET_HAS_eqv_i64
+// #define TCG_TARGET_HAS_nand_i64
+// #define TCG_TARGET_HAS_nor_i64
+#endif
+
#define TCG_TARGET_HAS_GUEST_BASE
/* Note: must be synced with dyngen-exec.h */
-#define TCG_AREG0 TCG_REG_EBP
+#if TCG_TARGET_REG_BITS == 64
+# define TCG_AREG0 TCG_REG_R14
+#else
+# define TCG_AREG0 TCG_REG_EBP
+#endif
static inline void flush_icache_range(unsigned long start, unsigned long stop)
{
diff --git a/tcg/x86_64/tcg-target.c b/tcg/x86_64/tcg-target.c
deleted file mode 100644
index 490666e..0000000
--- a/tcg/x86_64/tcg-target.c
+++ /dev/null
@@ -1,1445 +0,0 @@
-/*
- * Tiny Code Generator for QEMU
- *
- * Copyright (c) 2008 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#ifndef NDEBUG
-static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
- "%rax",
- "%rcx",
- "%rdx",
- "%rbx",
- "%rsp",
- "%rbp",
- "%rsi",
- "%rdi",
- "%r8",
- "%r9",
- "%r10",
- "%r11",
- "%r12",
- "%r13",
- "%r14",
- "%r15",
-};
-#endif
-
-static const int tcg_target_reg_alloc_order[] = {
- TCG_REG_RBP,
- TCG_REG_RBX,
- TCG_REG_R12,
- TCG_REG_R13,
- TCG_REG_R14,
- TCG_REG_R15,
- TCG_REG_R10,
- TCG_REG_R11,
- TCG_REG_R9,
- TCG_REG_R8,
- TCG_REG_RCX,
- TCG_REG_RDX,
- TCG_REG_RSI,
- TCG_REG_RDI,
- TCG_REG_RAX,
-};
-
-static const int tcg_target_call_iarg_regs[6] = {
- TCG_REG_RDI,
- TCG_REG_RSI,
- TCG_REG_RDX,
- TCG_REG_RCX,
- TCG_REG_R8,
- TCG_REG_R9,
-};
-
-static const int tcg_target_call_oarg_regs[2] = {
- TCG_REG_RAX,
- TCG_REG_RDX
-};
-
-static uint8_t *tb_ret_addr;
-
-static void patch_reloc(uint8_t *code_ptr, int type,
- tcg_target_long value, tcg_target_long addend)
-{
- value += addend;
- switch(type) {
- case R_X86_64_32:
- if (value != (uint32_t)value)
- tcg_abort();
- *(uint32_t *)code_ptr = value;
- break;
- case R_X86_64_32S:
- if (value != (int32_t)value)
- tcg_abort();
- *(uint32_t *)code_ptr = value;
- break;
- case R_386_PC32:
- value -= (long)code_ptr;
- if (value != (int32_t)value)
- tcg_abort();
- *(uint32_t *)code_ptr = value;
- break;
- default:
- tcg_abort();
- }
-}
-
-/* maximum number of register used for input function arguments */
-static inline int tcg_target_get_call_iarg_regs_count(int flags)
-{
- return 6;
-}
-
-/* parse target specific constraints */
-static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str)
-{
- const char *ct_str;
-
- ct_str = *pct_str;
- switch(ct_str[0]) {
- case 'a':
- ct->ct |= TCG_CT_REG;
- tcg_regset_set_reg(ct->u.regs, TCG_REG_RAX);
- break;
- case 'b':
- ct->ct |= TCG_CT_REG;
- tcg_regset_set_reg(ct->u.regs, TCG_REG_RBX);
- break;
- case 'c':
- ct->ct |= TCG_CT_REG;
- tcg_regset_set_reg(ct->u.regs, TCG_REG_RCX);
- break;
- case 'd':
- ct->ct |= TCG_CT_REG;
- tcg_regset_set_reg(ct->u.regs, TCG_REG_RDX);
- break;
- case 'S':
- ct->ct |= TCG_CT_REG;
- tcg_regset_set_reg(ct->u.regs, TCG_REG_RSI);
- break;
- case 'D':
- ct->ct |= TCG_CT_REG;
- tcg_regset_set_reg(ct->u.regs, TCG_REG_RDI);
- break;
- case 'q':
- ct->ct |= TCG_CT_REG;
- tcg_regset_set32(ct->u.regs, 0, 0xf);
- break;
- case 'r':
- ct->ct |= TCG_CT_REG;
- tcg_regset_set32(ct->u.regs, 0, 0xffff);
- break;
- case 'L': /* qemu_ld/st constraint */
- ct->ct |= TCG_CT_REG;
- tcg_regset_set32(ct->u.regs, 0, 0xffff);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_RSI);
- tcg_regset_reset_reg(ct->u.regs, TCG_REG_RDI);
- break;
- case 'e':
- ct->ct |= TCG_CT_CONST_S32;
- break;
- case 'Z':
- ct->ct |= TCG_CT_CONST_U32;
- break;
- default:
- return -1;
- }
- ct_str++;
- *pct_str = ct_str;
- return 0;
-}
-
-/* test if a constant matches the constraint */
-static inline int tcg_target_const_match(tcg_target_long val,
- const TCGArgConstraint *arg_ct)
-{
- int ct;
- ct = arg_ct->ct;
- if (ct & TCG_CT_CONST)
- return 1;
- else if ((ct & TCG_CT_CONST_S32) && val == (int32_t)val)
- return 1;
- else if ((ct & TCG_CT_CONST_U32) && val == (uint32_t)val)
- return 1;
- else
- return 0;
-}
-
-#define ARITH_ADD 0
-#define ARITH_OR 1
-#define ARITH_ADC 2
-#define ARITH_SBB 3
-#define ARITH_AND 4
-#define ARITH_SUB 5
-#define ARITH_XOR 6
-#define ARITH_CMP 7
-
-#define SHIFT_ROL 0
-#define SHIFT_ROR 1
-#define SHIFT_SHL 4
-#define SHIFT_SHR 5
-#define SHIFT_SAR 7
-
-#define JCC_JMP (-1)
-#define JCC_JO 0x0
-#define JCC_JNO 0x1
-#define JCC_JB 0x2
-#define JCC_JAE 0x3
-#define JCC_JE 0x4
-#define JCC_JNE 0x5
-#define JCC_JBE 0x6
-#define JCC_JA 0x7
-#define JCC_JS 0x8
-#define JCC_JNS 0x9
-#define JCC_JP 0xa
-#define JCC_JNP 0xb
-#define JCC_JL 0xc
-#define JCC_JGE 0xd
-#define JCC_JLE 0xe
-#define JCC_JG 0xf
-
-#define P_EXT 0x100 /* 0x0f opcode prefix */
-#define P_REXW 0x200 /* set rex.w = 1 */
-#define P_REXB_R 0x400 /* REG field as byte register */
-#define P_REXB_RM 0x800 /* R/M field as byte register */
-
-static const uint8_t tcg_cond_to_jcc[10] = {
- [TCG_COND_EQ] = JCC_JE,
- [TCG_COND_NE] = JCC_JNE,
- [TCG_COND_LT] = JCC_JL,
- [TCG_COND_GE] = JCC_JGE,
- [TCG_COND_LE] = JCC_JLE,
- [TCG_COND_GT] = JCC_JG,
- [TCG_COND_LTU] = JCC_JB,
- [TCG_COND_GEU] = JCC_JAE,
- [TCG_COND_LEU] = JCC_JBE,
- [TCG_COND_GTU] = JCC_JA,
-};
-
-static void tcg_out_opc(TCGContext *s, int opc, int r, int rm, int x)
-{
- int rex = 0;
-
- rex |= (opc & P_REXW) >> 6; /* REX.W */
- rex |= (r & 8) >> 1; /* REX.R */
- rex |= (x & 8) >> 2; /* REX.X */
- rex |= (rm & 8) >> 3; /* REX.B */
-
- /* P_REXB_{R,RM} indicates that the given register is the low byte.
- For %[abcd]l we need no REX prefix, but for %{si,di,bp,sp}l we do,
- as otherwise the encoding indicates %[abcd]h. Note that the values
- that are ORed in merely indicate that the REX byte must be present;
- those bits get discarded in output. */
- rex |= opc & (r >= 4 ? P_REXB_R : 0);
- rex |= opc & (rm >= 4 ? P_REXB_RM : 0);
-
- if (rex) {
- tcg_out8(s, (uint8_t)(rex | 0x40));
- }
- if (opc & P_EXT) {
- tcg_out8(s, 0x0f);
- }
- tcg_out8(s, opc & 0xff);
-}
-
-static inline void tcg_out_modrm(TCGContext *s, int opc, int r, int rm)
-{
- tcg_out_opc(s, opc, r, rm, 0);
- tcg_out8(s, 0xc0 | ((r & 7) << 3) | (rm & 7));
-}
-
-/* rm < 0 means no register index plus (-rm - 1 immediate bytes) */
-static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r, int rm,
- tcg_target_long offset)
-{
- if (rm < 0) {
- tcg_target_long val;
- tcg_out_opc(s, opc, r, 0, 0);
- val = offset - ((tcg_target_long)s->code_ptr + 5 + (-rm - 1));
- if (val == (int32_t)val) {
- /* eip relative */
- tcg_out8(s, 0x05 | ((r & 7) << 3));
- tcg_out32(s, val);
- } else if (offset == (int32_t)offset) {
- tcg_out8(s, 0x04 | ((r & 7) << 3));
- tcg_out8(s, 0x25); /* sib */
- tcg_out32(s, offset);
- } else {
- tcg_abort();
- }
- } else if (offset == 0 && (rm & 7) != TCG_REG_RBP) {
- tcg_out_opc(s, opc, r, rm, 0);
- if ((rm & 7) == TCG_REG_RSP) {
- tcg_out8(s, 0x04 | ((r & 7) << 3));
- tcg_out8(s, 0x24);
- } else {
- tcg_out8(s, 0x00 | ((r & 7) << 3) | (rm & 7));
- }
- } else if ((int8_t)offset == offset) {
- tcg_out_opc(s, opc, r, rm, 0);
- if ((rm & 7) == TCG_REG_RSP) {
- tcg_out8(s, 0x44 | ((r & 7) << 3));
- tcg_out8(s, 0x24);
- } else {
- tcg_out8(s, 0x40 | ((r & 7) << 3) | (rm & 7));
- }
- tcg_out8(s, offset);
- } else {
- tcg_out_opc(s, opc, r, rm, 0);
- if ((rm & 7) == TCG_REG_RSP) {
- tcg_out8(s, 0x84 | ((r & 7) << 3));
- tcg_out8(s, 0x24);
- } else {
- tcg_out8(s, 0x80 | ((r & 7) << 3) | (rm & 7));
- }
- tcg_out32(s, offset);
- }
-}
-
-#if defined(CONFIG_SOFTMMU)
-/* XXX: incomplete. index must be different from ESP */
-static void tcg_out_modrm_offset2(TCGContext *s, int opc, int r, int rm,
- int index, int shift,
- tcg_target_long offset)
-{
- int mod;
- if (rm == -1)
- tcg_abort();
- if (offset == 0 && (rm & 7) != TCG_REG_RBP) {
- mod = 0;
- } else if (offset == (int8_t)offset) {
- mod = 0x40;
- } else if (offset == (int32_t)offset) {
- mod = 0x80;
- } else {
- tcg_abort();
- }
- if (index == -1) {
- tcg_out_opc(s, opc, r, rm, 0);
- if ((rm & 7) == TCG_REG_RSP) {
- tcg_out8(s, mod | ((r & 7) << 3) | 0x04);
- tcg_out8(s, 0x04 | (rm & 7));
- } else {
- tcg_out8(s, mod | ((r & 7) << 3) | (rm & 7));
- }
- } else {
- tcg_out_opc(s, opc, r, rm, index);
- tcg_out8(s, mod | ((r & 7) << 3) | 0x04);
- tcg_out8(s, (shift << 6) | ((index & 7) << 3) | (rm & 7));
- }
- if (mod == 0x40) {
- tcg_out8(s, offset);
- } else if (mod == 0x80) {
- tcg_out32(s, offset);
- }
-}
-#endif
-
-static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
-{
- int rexw = (type == TCG_TYPE_I64 ? P_REXW : 0);
- tcg_out_modrm(s, 0x8b | rexw, ret, arg);
-}
-
-static inline void tcg_out_movi(TCGContext *s, TCGType type,
- int ret, tcg_target_long arg)
-{
- if (arg == 0) {
- tcg_out_modrm(s, 0x01 | (ARITH_XOR << 3), ret, ret); /* xor r0,r0 */
- } else if (arg == (uint32_t)arg || type == TCG_TYPE_I32) {
- tcg_out_opc(s, 0xb8 + (ret & 7), 0, ret, 0);
- tcg_out32(s, arg);
- } else if (arg == (int32_t)arg) {
- tcg_out_modrm(s, 0xc7 | P_REXW, 0, ret);
- tcg_out32(s, arg);
- } else {
- tcg_out_opc(s, (0xb8 + (ret & 7)) | P_REXW, 0, ret, 0);
- tcg_out32(s, arg);
- tcg_out32(s, arg >> 32);
- }
-}
-
-static void tcg_out_goto(TCGContext *s, int call, uint8_t *target)
-{
- int32_t disp;
-
- disp = target - s->code_ptr - 5;
- if (disp == (target - s->code_ptr - 5)) {
- tcg_out8(s, call ? 0xe8 : 0xe9);
- tcg_out32(s, disp);
- } else {
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_R10, (tcg_target_long) target);
- tcg_out_modrm(s, 0xff, call ? 2 : 4, TCG_REG_R10);
- }
-}
-
-static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
- int arg1, tcg_target_long arg2)
-{
- if (type == TCG_TYPE_I32)
- tcg_out_modrm_offset(s, 0x8b, ret, arg1, arg2); /* movl */
- else
- tcg_out_modrm_offset(s, 0x8b | P_REXW, ret, arg1, arg2); /* movq */
-}
-
-static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
- int arg1, tcg_target_long arg2)
-{
- if (type == TCG_TYPE_I32)
- tcg_out_modrm_offset(s, 0x89, arg, arg1, arg2); /* movl */
- else
- tcg_out_modrm_offset(s, 0x89 | P_REXW, arg, arg1, arg2); /* movq */
-}
-
-static inline void tgen_arithi32(TCGContext *s, int c, int r0, int32_t val)
-{
- if ((c == ARITH_ADD && val == 1) || (c == ARITH_SUB && val == -1)) {
- /* inc */
- tcg_out_modrm(s, 0xff, 0, r0);
- } else if ((c == ARITH_ADD && val == -1) || (c == ARITH_SUB && val == 1)) {
- /* dec */
- tcg_out_modrm(s, 0xff, 1, r0);
- } else if (val == (int8_t)val) {
- tcg_out_modrm(s, 0x83, c, r0);
- tcg_out8(s, val);
- } else if (c == ARITH_AND && val == 0xffu) {
- /* movzbl */
- tcg_out_modrm(s, 0xb6 | P_EXT | P_REXB_RM, r0, r0);
- } else if (c == ARITH_AND && val == 0xffffu) {
- /* movzwl */
- tcg_out_modrm(s, 0xb7 | P_EXT, r0, r0);
- } else {
- tcg_out_modrm(s, 0x81, c, r0);
- tcg_out32(s, val);
- }
-}
-
-static inline void tgen_arithi64(TCGContext *s, int c, int r0, int64_t val)
-{
- if ((c == ARITH_ADD && val == 1) || (c == ARITH_SUB && val == -1)) {
- /* inc */
- tcg_out_modrm(s, 0xff | P_REXW, 0, r0);
- } else if ((c == ARITH_ADD && val == -1) || (c == ARITH_SUB && val == 1)) {
- /* dec */
- tcg_out_modrm(s, 0xff | P_REXW, 1, r0);
- } else if (c == ARITH_AND && val == 0xffffffffu) {
- /* 32-bit mov zero extends */
- tcg_out_modrm(s, 0x8b, r0, r0);
- } else if (c == ARITH_AND && val == (uint32_t)val) {
- /* AND with no high bits set can use a 32-bit operation. */
- tgen_arithi32(s, c, r0, (uint32_t)val);
- } else if (val == (int8_t)val) {
- tcg_out_modrm(s, 0x83 | P_REXW, c, r0);
- tcg_out8(s, val);
- } else if (val == (int32_t)val) {
- tcg_out_modrm(s, 0x81 | P_REXW, c, r0);
- tcg_out32(s, val);
- } else {
- tcg_abort();
- }
-}
-
-static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
-{
- if (val != 0)
- tgen_arithi64(s, ARITH_ADD, reg, val);
-}
-
-static void tcg_out_jxx(TCGContext *s, int opc, int label_index)
-{
- int32_t val, val1;
- TCGLabel *l = &s->labels[label_index];
-
- if (l->has_value) {
- val = l->u.value - (tcg_target_long)s->code_ptr;
- val1 = val - 2;
- if ((int8_t)val1 == val1) {
- if (opc == -1)
- tcg_out8(s, 0xeb);
- else
- tcg_out8(s, 0x70 + opc);
- tcg_out8(s, val1);
- } else {
- if (opc == -1) {
- tcg_out8(s, 0xe9);
- tcg_out32(s, val - 5);
- } else {
- tcg_out8(s, 0x0f);
- tcg_out8(s, 0x80 + opc);
- tcg_out32(s, val - 6);
- }
- }
- } else {
- if (opc == -1) {
- tcg_out8(s, 0xe9);
- } else {
- tcg_out8(s, 0x0f);
- tcg_out8(s, 0x80 + opc);
- }
- tcg_out_reloc(s, s->code_ptr, R_386_PC32, label_index, -4);
- s->code_ptr += 4;
- }
-}
-
-static void tcg_out_cmp(TCGContext *s, TCGArg arg1, TCGArg arg2,
- int const_arg2, int rexw)
-{
- if (const_arg2) {
- if (arg2 == 0) {
- /* test r, r */
- tcg_out_modrm(s, 0x85 | rexw, arg1, arg1);
- } else {
- if (rexw) {
- tgen_arithi64(s, ARITH_CMP, arg1, arg2);
- } else {
- tgen_arithi32(s, ARITH_CMP, arg1, arg2);
- }
- }
- } else {
- tcg_out_modrm(s, 0x01 | (ARITH_CMP << 3) | rexw, arg2, arg1);
- }
-}
-
-static void tcg_out_brcond(TCGContext *s, TCGCond cond,
- TCGArg arg1, TCGArg arg2, int const_arg2,
- int label_index, int rexw)
-{
- tcg_out_cmp(s, arg1, arg2, const_arg2, rexw);
- tcg_out_jxx(s, tcg_cond_to_jcc[cond], label_index);
-}
-
-static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGArg dest,
- TCGArg arg1, TCGArg arg2, int const_arg2, int rexw)
-{
- tcg_out_cmp(s, arg1, arg2, const_arg2, rexw);
- /* setcc */
- tcg_out_modrm(s, 0x90 | tcg_cond_to_jcc[cond] | P_EXT | P_REXB_RM, 0, dest);
- tgen_arithi32(s, ARITH_AND, dest, 0xff);
-}
-
-#if defined(CONFIG_SOFTMMU)
-
-#include "../../softmmu_defs.h"
-
-static void *qemu_ld_helpers[4] = {
- __ldb_mmu,
- __ldw_mmu,
- __ldl_mmu,
- __ldq_mmu,
-};
-
-static void *qemu_st_helpers[4] = {
- __stb_mmu,
- __stw_mmu,
- __stl_mmu,
- __stq_mmu,
-};
-#endif
-
-static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
- int opc)
-{
- int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, rexw;
- int32_t offset;
-#if defined(CONFIG_SOFTMMU)
- uint8_t *label1_ptr, *label2_ptr;
-#endif
-
- data_reg = *args++;
- addr_reg = *args++;
- mem_index = *args;
- s_bits = opc & 3;
-
- r0 = TCG_REG_RDI;
- r1 = TCG_REG_RSI;
-
-#if TARGET_LONG_BITS == 32
- rexw = 0;
-#else
- rexw = P_REXW;
-#endif
-#if defined(CONFIG_SOFTMMU)
- tcg_out_mov(s, TCG_TYPE_TL, r1, addr_reg);
- tcg_out_mov(s, TCG_TYPE_TL, r0, addr_reg);
-
- tcg_out_modrm(s, 0xc1 | rexw, 5, r1); /* shr $x, r1 */
- tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
-
- tcg_out_modrm(s, 0x81 | rexw, 4, r0); /* andl $x, r0 */
- tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
-
- tcg_out_modrm(s, 0x81, 4, r1); /* andl $x, r1 */
- tcg_out32(s, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
-
- /* lea offset(r1, env), r1 */
- tcg_out_modrm_offset2(s, 0x8d | P_REXW, r1, r1, TCG_AREG0, 0,
- offsetof(CPUState, tlb_table[mem_index][0].addr_read));
-
- /* cmp 0(r1), r0 */
- tcg_out_modrm_offset(s, 0x3b | rexw, r0, r1, 0);
-
- tcg_out_mov(s, TCG_TYPE_TL, r0, addr_reg);
-
- /* je label1 */
- tcg_out8(s, 0x70 + JCC_JE);
- label1_ptr = s->code_ptr;
- s->code_ptr++;
-
- /* XXX: move that code at the end of the TB */
- tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RSI, mem_index);
- tcg_out_goto(s, 1, qemu_ld_helpers[s_bits]);
-
- switch(opc) {
- case 0 | 4:
- /* movsbq */
- tcg_out_modrm(s, 0xbe | P_EXT | P_REXW, data_reg, TCG_REG_RAX);
- break;
- case 1 | 4:
- /* movswq */
- tcg_out_modrm(s, 0xbf | P_EXT | P_REXW, data_reg, TCG_REG_RAX);
- break;
- case 2 | 4:
- /* movslq */
- tcg_out_modrm(s, 0x63 | P_REXW, data_reg, TCG_REG_RAX);
- break;
- case 0:
- /* movzbq */
- tcg_out_modrm(s, 0xb6 | P_EXT | P_REXW, data_reg, TCG_REG_RAX);
- break;
- case 1:
- /* movzwq */
- tcg_out_modrm(s, 0xb7 | P_EXT | P_REXW, data_reg, TCG_REG_RAX);
- break;
- case 2:
- default:
- tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_RAX);
- break;
- case 3:
- tcg_out_mov(s, TCG_TYPE_I64, data_reg, TCG_REG_RAX);
- break;
- }
-
- /* jmp label2 */
- tcg_out8(s, 0xeb);
- label2_ptr = s->code_ptr;
- s->code_ptr++;
-
- /* label1: */
- *label1_ptr = s->code_ptr - label1_ptr - 1;
-
- /* add x(r1), r0 */
- tcg_out_modrm_offset(s, 0x03 | P_REXW, r0, r1, offsetof(CPUTLBEntry, addend) -
- offsetof(CPUTLBEntry, addr_read));
- offset = 0;
-#else
- if (GUEST_BASE == (int32_t)GUEST_BASE) {
- r0 = addr_reg;
- offset = GUEST_BASE;
- } else {
- offset = 0;
- /* movq $GUEST_BASE, r0 */
- tcg_out_opc(s, (0xb8 + (r0 & 7)) | P_REXW, 0, r0, 0);
- tcg_out32(s, GUEST_BASE);
- tcg_out32(s, GUEST_BASE >> 32);
- /* addq addr_reg, r0 */
- tcg_out_modrm(s, 0x01 | P_REXW, addr_reg, r0);
- }
-#endif
-
-#ifdef TARGET_WORDS_BIGENDIAN
- bswap = 1;
-#else
- bswap = 0;
-#endif
- switch(opc) {
- case 0:
- /* movzbl */
- tcg_out_modrm_offset(s, 0xb6 | P_EXT, data_reg, r0, offset);
- break;
- case 0 | 4:
- /* movsbX */
- tcg_out_modrm_offset(s, 0xbe | P_EXT | rexw, data_reg, r0, offset);
- break;
- case 1:
- /* movzwl */
- tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, offset);
- if (bswap) {
- /* rolw $8, data_reg */
- tcg_out8(s, 0x66);
- tcg_out_modrm(s, 0xc1, 0, data_reg);
- tcg_out8(s, 8);
- }
- break;
- case 1 | 4:
- if (bswap) {
- /* movzwl */
- tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, offset);
- /* rolw $8, data_reg */
- tcg_out8(s, 0x66);
- tcg_out_modrm(s, 0xc1, 0, data_reg);
- tcg_out8(s, 8);
-
- /* movswX data_reg, data_reg */
- tcg_out_modrm(s, 0xbf | P_EXT | rexw, data_reg, data_reg);
- } else {
- /* movswX */
- tcg_out_modrm_offset(s, 0xbf | P_EXT | rexw, data_reg, r0, offset);
- }
- break;
- case 2:
- /* movl (r0), data_reg */
- tcg_out_modrm_offset(s, 0x8b, data_reg, r0, offset);
- if (bswap) {
- /* bswap */
- tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT, 0, data_reg, 0);
- }
- break;
- case 2 | 4:
- if (bswap) {
- /* movl (r0), data_reg */
- tcg_out_modrm_offset(s, 0x8b, data_reg, r0, offset);
- /* bswap */
- tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT, 0, data_reg, 0);
- /* movslq */
- tcg_out_modrm(s, 0x63 | P_REXW, data_reg, data_reg);
- } else {
- /* movslq */
- tcg_out_modrm_offset(s, 0x63 | P_REXW, data_reg, r0, offset);
- }
- break;
- case 3:
- /* movq (r0), data_reg */
- tcg_out_modrm_offset(s, 0x8b | P_REXW, data_reg, r0, offset);
- if (bswap) {
- /* bswap */
- tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT | P_REXW, 0, data_reg, 0);
- }
- break;
- default:
- tcg_abort();
- }
-
-#if defined(CONFIG_SOFTMMU)
- /* label2: */
- *label2_ptr = s->code_ptr - label2_ptr - 1;
-#endif
-}
-
-static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
- int opc)
-{
- int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, rexw;
- int32_t offset;
-#if defined(CONFIG_SOFTMMU)
- uint8_t *label1_ptr, *label2_ptr;
-#endif
-
- data_reg = *args++;
- addr_reg = *args++;
- mem_index = *args;
-
- s_bits = opc;
-
- r0 = TCG_REG_RDI;
- r1 = TCG_REG_RSI;
-
-#if TARGET_LONG_BITS == 32
- rexw = 0;
-#else
- rexw = P_REXW;
-#endif
-#if defined(CONFIG_SOFTMMU)
- tcg_out_mov(s, TCG_TYPE_TL, r1, addr_reg);
- tcg_out_mov(s, TCG_TYPE_TL, r0, addr_reg);
-
- tcg_out_modrm(s, 0xc1 | rexw, 5, r1); /* shr $x, r1 */
- tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
-
- tcg_out_modrm(s, 0x81 | rexw, 4, r0); /* andl $x, r0 */
- tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
-
- tcg_out_modrm(s, 0x81, 4, r1); /* andl $x, r1 */
- tcg_out32(s, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
-
- /* lea offset(r1, env), r1 */
- tcg_out_modrm_offset2(s, 0x8d | P_REXW, r1, r1, TCG_AREG0, 0,
- offsetof(CPUState, tlb_table[mem_index][0].addr_write));
-
- /* cmp 0(r1), r0 */
- tcg_out_modrm_offset(s, 0x3b | rexw, r0, r1, 0);
-
- tcg_out_mov(s, TCG_TYPE_TL, r0, addr_reg);
-
- /* je label1 */
- tcg_out8(s, 0x70 + JCC_JE);
- label1_ptr = s->code_ptr;
- s->code_ptr++;
-
- /* XXX: move that code at the end of the TB */
- switch(opc) {
- case 0:
- /* movzbl */
- tcg_out_modrm(s, 0xb6 | P_EXT | P_REXB_RM, TCG_REG_RSI, data_reg);
- break;
- case 1:
- /* movzwl */
- tcg_out_modrm(s, 0xb7 | P_EXT, TCG_REG_RSI, data_reg);
- break;
- case 2:
- tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_RSI, data_reg);
- break;
- default:
- case 3:
- tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_RSI, data_reg);
- break;
- }
- tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RDX, mem_index);
- tcg_out_goto(s, 1, qemu_st_helpers[s_bits]);
-
- /* jmp label2 */
- tcg_out8(s, 0xeb);
- label2_ptr = s->code_ptr;
- s->code_ptr++;
-
- /* label1: */
- *label1_ptr = s->code_ptr - label1_ptr - 1;
-
- /* add x(r1), r0 */
- tcg_out_modrm_offset(s, 0x03 | P_REXW, r0, r1, offsetof(CPUTLBEntry, addend) -
- offsetof(CPUTLBEntry, addr_write));
- offset = 0;
-#else
- if (GUEST_BASE == (int32_t)GUEST_BASE) {
- r0 = addr_reg;
- offset = GUEST_BASE;
- } else {
- offset = 0;
- /* movq $GUEST_BASE, r0 */
- tcg_out_opc(s, (0xb8 + (r0 & 7)) | P_REXW, 0, r0, 0);
- tcg_out32(s, GUEST_BASE);
- tcg_out32(s, GUEST_BASE >> 32);
- /* addq addr_reg, r0 */
- tcg_out_modrm(s, 0x01 | P_REXW, addr_reg, r0);
- }
-#endif
-
-#ifdef TARGET_WORDS_BIGENDIAN
- bswap = 1;
-#else
- bswap = 0;
-#endif
- switch(opc) {
- case 0:
- /* movb */
- tcg_out_modrm_offset(s, 0x88 | P_REXB_R, data_reg, r0, offset);
- break;
- case 1:
- if (bswap) {
- tcg_out_mov(s, TCG_TYPE_I32, r1, data_reg);
- tcg_out8(s, 0x66); /* rolw $8, %ecx */
- tcg_out_modrm(s, 0xc1, 0, r1);
- tcg_out8(s, 8);
- data_reg = r1;
- }
- /* movw */
- tcg_out8(s, 0x66);
- tcg_out_modrm_offset(s, 0x89, data_reg, r0, offset);
- break;
- case 2:
- if (bswap) {
- tcg_out_mov(s, TCG_TYPE_I32, r1, data_reg);
- /* bswap data_reg */
- tcg_out_opc(s, (0xc8 + r1) | P_EXT, 0, r1, 0);
- data_reg = r1;
- }
- /* movl */
- tcg_out_modrm_offset(s, 0x89, data_reg, r0, offset);
- break;
- case 3:
- if (bswap) {
- tcg_out_mov(s, TCG_TYPE_I64, r1, data_reg);
- /* bswap data_reg */
- tcg_out_opc(s, (0xc8 + r1) | P_EXT | P_REXW, 0, r1, 0);
- data_reg = r1;
- }
- /* movq */
- tcg_out_modrm_offset(s, 0x89 | P_REXW, data_reg, r0, offset);
- break;
- default:
- tcg_abort();
- }
-
-#if defined(CONFIG_SOFTMMU)
- /* label2: */
- *label2_ptr = s->code_ptr - label2_ptr - 1;
-#endif
-}
-
-static inline void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
- const int *const_args)
-{
- int c;
-
- switch(opc) {
- case INDEX_op_exit_tb:
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_RAX, args[0]);
- tcg_out_goto(s, 0, tb_ret_addr);
- break;
- case INDEX_op_goto_tb:
- if (s->tb_jmp_offset) {
- /* direct jump method */
- tcg_out8(s, 0xe9); /* jmp im */
- s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
- tcg_out32(s, 0);
- } else {
- /* indirect jump method */
- /* jmp Ev */
- tcg_out_modrm_offset(s, 0xff, 4, -1,
- (tcg_target_long)(s->tb_next +
- args[0]));
- }
- s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
- break;
- case INDEX_op_call:
- if (const_args[0]) {
- tcg_out_goto(s, 1, (void *) args[0]);
- } else {
- tcg_out_modrm(s, 0xff, 2, args[0]);
- }
- break;
- case INDEX_op_jmp:
- if (const_args[0]) {
- tcg_out_goto(s, 0, (void *) args[0]);
- } else {
- tcg_out_modrm(s, 0xff, 4, args[0]);
- }
- break;
- case INDEX_op_br:
- tcg_out_jxx(s, JCC_JMP, args[0]);
- break;
- case INDEX_op_movi_i32:
- tcg_out_movi(s, TCG_TYPE_I32, args[0], (uint32_t)args[1]);
- break;
- case INDEX_op_movi_i64:
- tcg_out_movi(s, TCG_TYPE_I64, args[0], args[1]);
- break;
- case INDEX_op_ld8u_i32:
- case INDEX_op_ld8u_i64:
- /* movzbl */
- tcg_out_modrm_offset(s, 0xb6 | P_EXT, args[0], args[1], args[2]);
- break;
- case INDEX_op_ld8s_i32:
- /* movsbl */
- tcg_out_modrm_offset(s, 0xbe | P_EXT, args[0], args[1], args[2]);
- break;
- case INDEX_op_ld8s_i64:
- /* movsbq */
- tcg_out_modrm_offset(s, 0xbe | P_EXT | P_REXW, args[0], args[1], args[2]);
- break;
- case INDEX_op_ld16u_i32:
- case INDEX_op_ld16u_i64:
- /* movzwl */
- tcg_out_modrm_offset(s, 0xb7 | P_EXT, args[0], args[1], args[2]);
- break;
- case INDEX_op_ld16s_i32:
- /* movswl */
- tcg_out_modrm_offset(s, 0xbf | P_EXT, args[0], args[1], args[2]);
- break;
- case INDEX_op_ld16s_i64:
- /* movswq */
- tcg_out_modrm_offset(s, 0xbf | P_EXT | P_REXW, args[0], args[1], args[2]);
- break;
- case INDEX_op_ld_i32:
- case INDEX_op_ld32u_i64:
- /* movl */
- tcg_out_modrm_offset(s, 0x8b, args[0], args[1], args[2]);
- break;
- case INDEX_op_ld32s_i64:
- /* movslq */
- tcg_out_modrm_offset(s, 0x63 | P_REXW, args[0], args[1], args[2]);
- break;
- case INDEX_op_ld_i64:
- /* movq */
- tcg_out_modrm_offset(s, 0x8b | P_REXW, args[0], args[1], args[2]);
- break;
-
- case INDEX_op_st8_i32:
- case INDEX_op_st8_i64:
- /* movb */
- tcg_out_modrm_offset(s, 0x88 | P_REXB_R, args[0], args[1], args[2]);
- break;
- case INDEX_op_st16_i32:
- case INDEX_op_st16_i64:
- /* movw */
- tcg_out8(s, 0x66);
- tcg_out_modrm_offset(s, 0x89, args[0], args[1], args[2]);
- break;
- case INDEX_op_st_i32:
- case INDEX_op_st32_i64:
- /* movl */
- tcg_out_modrm_offset(s, 0x89, args[0], args[1], args[2]);
- break;
- case INDEX_op_st_i64:
- /* movq */
- tcg_out_modrm_offset(s, 0x89 | P_REXW, args[0], args[1], args[2]);
- break;
-
- case INDEX_op_sub_i32:
- c = ARITH_SUB;
- goto gen_arith32;
- case INDEX_op_and_i32:
- c = ARITH_AND;
- goto gen_arith32;
- case INDEX_op_or_i32:
- c = ARITH_OR;
- goto gen_arith32;
- case INDEX_op_xor_i32:
- c = ARITH_XOR;
- goto gen_arith32;
- case INDEX_op_add_i32:
- c = ARITH_ADD;
- gen_arith32:
- if (const_args[2]) {
- tgen_arithi32(s, c, args[0], args[2]);
- } else {
- tcg_out_modrm(s, 0x01 | (c << 3), args[2], args[0]);
- }
- break;
-
- case INDEX_op_sub_i64:
- c = ARITH_SUB;
- goto gen_arith64;
- case INDEX_op_and_i64:
- c = ARITH_AND;
- goto gen_arith64;
- case INDEX_op_or_i64:
- c = ARITH_OR;
- goto gen_arith64;
- case INDEX_op_xor_i64:
- c = ARITH_XOR;
- goto gen_arith64;
- case INDEX_op_add_i64:
- c = ARITH_ADD;
- gen_arith64:
- if (const_args[2]) {
- tgen_arithi64(s, c, args[0], args[2]);
- } else {
- tcg_out_modrm(s, 0x01 | (c << 3) | P_REXW, args[2], args[0]);
- }
- break;
-
- case INDEX_op_mul_i32:
- if (const_args[2]) {
- int32_t val;
- val = args[2];
- if (val == (int8_t)val) {
- tcg_out_modrm(s, 0x6b, args[0], args[0]);
- tcg_out8(s, val);
- } else {
- tcg_out_modrm(s, 0x69, args[0], args[0]);
- tcg_out32(s, val);
- }
- } else {
- tcg_out_modrm(s, 0xaf | P_EXT, args[0], args[2]);
- }
- break;
- case INDEX_op_mul_i64:
- if (const_args[2]) {
- int32_t val;
- val = args[2];
- if (val == (int8_t)val) {
- tcg_out_modrm(s, 0x6b | P_REXW, args[0], args[0]);
- tcg_out8(s, val);
- } else {
- tcg_out_modrm(s, 0x69 | P_REXW, args[0], args[0]);
- tcg_out32(s, val);
- }
- } else {
- tcg_out_modrm(s, 0xaf | P_EXT | P_REXW, args[0], args[2]);
- }
- break;
- case INDEX_op_div2_i32:
- tcg_out_modrm(s, 0xf7, 7, args[4]);
- break;
- case INDEX_op_divu2_i32:
- tcg_out_modrm(s, 0xf7, 6, args[4]);
- break;
- case INDEX_op_div2_i64:
- tcg_out_modrm(s, 0xf7 | P_REXW, 7, args[4]);
- break;
- case INDEX_op_divu2_i64:
- tcg_out_modrm(s, 0xf7 | P_REXW, 6, args[4]);
- break;
-
- case INDEX_op_shl_i32:
- c = SHIFT_SHL;
- gen_shift32:
- if (const_args[2]) {
- if (args[2] == 1) {
- tcg_out_modrm(s, 0xd1, c, args[0]);
- } else {
- tcg_out_modrm(s, 0xc1, c, args[0]);
- tcg_out8(s, args[2]);
- }
- } else {
- tcg_out_modrm(s, 0xd3, c, args[0]);
- }
- break;
- case INDEX_op_shr_i32:
- c = SHIFT_SHR;
- goto gen_shift32;
- case INDEX_op_sar_i32:
- c = SHIFT_SAR;
- goto gen_shift32;
- case INDEX_op_rotl_i32:
- c = SHIFT_ROL;
- goto gen_shift32;
- case INDEX_op_rotr_i32:
- c = SHIFT_ROR;
- goto gen_shift32;
-
- case INDEX_op_shl_i64:
- c = SHIFT_SHL;
- gen_shift64:
- if (const_args[2]) {
- if (args[2] == 1) {
- tcg_out_modrm(s, 0xd1 | P_REXW, c, args[0]);
- } else {
- tcg_out_modrm(s, 0xc1 | P_REXW, c, args[0]);
- tcg_out8(s, args[2]);
- }
- } else {
- tcg_out_modrm(s, 0xd3 | P_REXW, c, args[0]);
- }
- break;
- case INDEX_op_shr_i64:
- c = SHIFT_SHR;
- goto gen_shift64;
- case INDEX_op_sar_i64:
- c = SHIFT_SAR;
- goto gen_shift64;
- case INDEX_op_rotl_i64:
- c = SHIFT_ROL;
- goto gen_shift64;
- case INDEX_op_rotr_i64:
- c = SHIFT_ROR;
- goto gen_shift64;
-
- case INDEX_op_brcond_i32:
- tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
- args[3], 0);
- break;
- case INDEX_op_brcond_i64:
- tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
- args[3], P_REXW);
- break;
-
- case INDEX_op_bswap16_i32:
- case INDEX_op_bswap16_i64:
- tcg_out8(s, 0x66);
- tcg_out_modrm(s, 0xc1, SHIFT_ROL, args[0]);
- tcg_out8(s, 8);
- break;
- case INDEX_op_bswap32_i32:
- case INDEX_op_bswap32_i64:
- tcg_out_opc(s, (0xc8 + (args[0] & 7)) | P_EXT, 0, args[0], 0);
- break;
- case INDEX_op_bswap64_i64:
- tcg_out_opc(s, (0xc8 + (args[0] & 7)) | P_EXT | P_REXW, 0, args[0], 0);
- break;
-
- case INDEX_op_neg_i32:
- tcg_out_modrm(s, 0xf7, 3, args[0]);
- break;
- case INDEX_op_neg_i64:
- tcg_out_modrm(s, 0xf7 | P_REXW, 3, args[0]);
- break;
-
- case INDEX_op_not_i32:
- tcg_out_modrm(s, 0xf7, 2, args[0]);
- break;
- case INDEX_op_not_i64:
- tcg_out_modrm(s, 0xf7 | P_REXW, 2, args[0]);
- break;
-
- case INDEX_op_ext8s_i32:
- tcg_out_modrm(s, 0xbe | P_EXT | P_REXB_RM, args[0], args[1]);
- break;
- case INDEX_op_ext16s_i32:
- tcg_out_modrm(s, 0xbf | P_EXT, args[0], args[1]);
- break;
- case INDEX_op_ext8s_i64:
- tcg_out_modrm(s, 0xbe | P_EXT | P_REXW, args[0], args[1]);
- break;
- case INDEX_op_ext16s_i64:
- tcg_out_modrm(s, 0xbf | P_EXT | P_REXW, args[0], args[1]);
- break;
- case INDEX_op_ext32s_i64:
- tcg_out_modrm(s, 0x63 | P_REXW, args[0], args[1]);
- break;
- case INDEX_op_ext8u_i32:
- case INDEX_op_ext8u_i64:
- tcg_out_modrm(s, 0xb6 | P_EXT | P_REXB_RM, args[0], args[1]);
- break;
- case INDEX_op_ext16u_i32:
- case INDEX_op_ext16u_i64:
- tcg_out_modrm(s, 0xb7 | P_EXT, args[0], args[1]);
- break;
- case INDEX_op_ext32u_i64:
- tcg_out_modrm(s, 0x8b, args[0], args[1]);
- break;
-
- case INDEX_op_setcond_i32:
- tcg_out_setcond(s, args[3], args[0], args[1], args[2],
- const_args[2], 0);
- break;
- case INDEX_op_setcond_i64:
- tcg_out_setcond(s, args[3], args[0], args[1], args[2],
- const_args[2], P_REXW);
- break;
-
- case INDEX_op_qemu_ld8u:
- tcg_out_qemu_ld(s, args, 0);
- break;
- case INDEX_op_qemu_ld8s:
- tcg_out_qemu_ld(s, args, 0 | 4);
- break;
- case INDEX_op_qemu_ld16u:
- tcg_out_qemu_ld(s, args, 1);
- break;
- case INDEX_op_qemu_ld16s:
- tcg_out_qemu_ld(s, args, 1 | 4);
- break;
- case INDEX_op_qemu_ld32:
- case INDEX_op_qemu_ld32u:
- tcg_out_qemu_ld(s, args, 2);
- break;
- case INDEX_op_qemu_ld32s:
- tcg_out_qemu_ld(s, args, 2 | 4);
- break;
- case INDEX_op_qemu_ld64:
- tcg_out_qemu_ld(s, args, 3);
- break;
-
- case INDEX_op_qemu_st8:
- tcg_out_qemu_st(s, args, 0);
- break;
- case INDEX_op_qemu_st16:
- tcg_out_qemu_st(s, args, 1);
- break;
- case INDEX_op_qemu_st32:
- tcg_out_qemu_st(s, args, 2);
- break;
- case INDEX_op_qemu_st64:
- tcg_out_qemu_st(s, args, 3);
- break;
-
- default:
- tcg_abort();
- }
-}
-
-static int tcg_target_callee_save_regs[] = {
- TCG_REG_RBP,
- TCG_REG_RBX,
- TCG_REG_R12,
- TCG_REG_R13,
- /* TCG_REG_R14, */ /* currently used for the global env, so no
- need to save */
- TCG_REG_R15,
-};
-
-static inline void tcg_out_push(TCGContext *s, int reg)
-{
- tcg_out_opc(s, (0x50 + (reg & 7)), 0, reg, 0);
-}
-
-static inline void tcg_out_pop(TCGContext *s, int reg)
-{
- tcg_out_opc(s, (0x58 + (reg & 7)), 0, reg, 0);
-}
-
-/* Generate global QEMU prologue and epilogue code */
-static void tcg_target_qemu_prologue(TCGContext *s)
-{
- int i, frame_size, push_size, stack_addend;
-
- /* TB prologue */
- /* save all callee saved registers */
- for(i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
- tcg_out_push(s, tcg_target_callee_save_regs[i]);
-
- }
- /* reserve some stack space */
- push_size = 8 + ARRAY_SIZE(tcg_target_callee_save_regs) * 8;
- frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE;
- frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
- ~(TCG_TARGET_STACK_ALIGN - 1);
- stack_addend = frame_size - push_size;
- tcg_out_addi(s, TCG_REG_RSP, -stack_addend);
-
- tcg_out_modrm(s, 0xff, 4, TCG_REG_RDI); /* jmp *%rdi */
-
- /* TB epilogue */
- tb_ret_addr = s->code_ptr;
- tcg_out_addi(s, TCG_REG_RSP, stack_addend);
- for(i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {
- tcg_out_pop(s, tcg_target_callee_save_regs[i]);
- }
- tcg_out8(s, 0xc3); /* ret */
-}
-
-static const TCGTargetOpDef x86_64_op_defs[] = {
- { INDEX_op_exit_tb, { } },
- { INDEX_op_goto_tb, { } },
- { INDEX_op_call, { "ri" } }, /* XXX: might need a specific constant constraint */
- { INDEX_op_jmp, { "ri" } }, /* XXX: might need a specific constant constraint */
- { INDEX_op_br, { } },
-
- { INDEX_op_mov_i32, { "r", "r" } },
- { INDEX_op_movi_i32, { "r" } },
- { INDEX_op_ld8u_i32, { "r", "r" } },
- { INDEX_op_ld8s_i32, { "r", "r" } },
- { INDEX_op_ld16u_i32, { "r", "r" } },
- { INDEX_op_ld16s_i32, { "r", "r" } },
- { INDEX_op_ld_i32, { "r", "r" } },
- { INDEX_op_st8_i32, { "r", "r" } },
- { INDEX_op_st16_i32, { "r", "r" } },
- { INDEX_op_st_i32, { "r", "r" } },
-
- { INDEX_op_add_i32, { "r", "0", "ri" } },
- { INDEX_op_mul_i32, { "r", "0", "ri" } },
- { INDEX_op_div2_i32, { "a", "d", "0", "1", "r" } },
- { INDEX_op_divu2_i32, { "a", "d", "0", "1", "r" } },
- { INDEX_op_sub_i32, { "r", "0", "ri" } },
- { INDEX_op_and_i32, { "r", "0", "ri" } },
- { INDEX_op_or_i32, { "r", "0", "ri" } },
- { INDEX_op_xor_i32, { "r", "0", "ri" } },
-
- { INDEX_op_shl_i32, { "r", "0", "ci" } },
- { INDEX_op_shr_i32, { "r", "0", "ci" } },
- { INDEX_op_sar_i32, { "r", "0", "ci" } },
- { INDEX_op_rotl_i32, { "r", "0", "ci" } },
- { INDEX_op_rotr_i32, { "r", "0", "ci" } },
-
- { INDEX_op_brcond_i32, { "r", "ri" } },
-
- { INDEX_op_mov_i64, { "r", "r" } },
- { INDEX_op_movi_i64, { "r" } },
- { INDEX_op_ld8u_i64, { "r", "r" } },
- { INDEX_op_ld8s_i64, { "r", "r" } },
- { INDEX_op_ld16u_i64, { "r", "r" } },
- { INDEX_op_ld16s_i64, { "r", "r" } },
- { INDEX_op_ld32u_i64, { "r", "r" } },
- { INDEX_op_ld32s_i64, { "r", "r" } },
- { INDEX_op_ld_i64, { "r", "r" } },
- { INDEX_op_st8_i64, { "r", "r" } },
- { INDEX_op_st16_i64, { "r", "r" } },
- { INDEX_op_st32_i64, { "r", "r" } },
- { INDEX_op_st_i64, { "r", "r" } },
-
- { INDEX_op_add_i64, { "r", "0", "re" } },
- { INDEX_op_mul_i64, { "r", "0", "re" } },
- { INDEX_op_div2_i64, { "a", "d", "0", "1", "r" } },
- { INDEX_op_divu2_i64, { "a", "d", "0", "1", "r" } },
- { INDEX_op_sub_i64, { "r", "0", "re" } },
- { INDEX_op_and_i64, { "r", "0", "reZ" } },
- { INDEX_op_or_i64, { "r", "0", "re" } },
- { INDEX_op_xor_i64, { "r", "0", "re" } },
-
- { INDEX_op_shl_i64, { "r", "0", "ci" } },
- { INDEX_op_shr_i64, { "r", "0", "ci" } },
- { INDEX_op_sar_i64, { "r", "0", "ci" } },
- { INDEX_op_rotl_i64, { "r", "0", "ci" } },
- { INDEX_op_rotr_i64, { "r", "0", "ci" } },
-
- { INDEX_op_brcond_i64, { "r", "re" } },
-
- { INDEX_op_bswap16_i32, { "r", "0" } },
- { INDEX_op_bswap16_i64, { "r", "0" } },
- { INDEX_op_bswap32_i32, { "r", "0" } },
- { INDEX_op_bswap32_i64, { "r", "0" } },
- { INDEX_op_bswap64_i64, { "r", "0" } },
-
- { INDEX_op_neg_i32, { "r", "0" } },
- { INDEX_op_neg_i64, { "r", "0" } },
-
- { INDEX_op_not_i32, { "r", "0" } },
- { INDEX_op_not_i64, { "r", "0" } },
-
- { INDEX_op_ext8s_i32, { "r", "r"} },
- { INDEX_op_ext16s_i32, { "r", "r"} },
- { INDEX_op_ext8s_i64, { "r", "r"} },
- { INDEX_op_ext16s_i64, { "r", "r"} },
- { INDEX_op_ext32s_i64, { "r", "r"} },
- { INDEX_op_ext8u_i32, { "r", "r"} },
- { INDEX_op_ext16u_i32, { "r", "r"} },
- { INDEX_op_ext8u_i64, { "r", "r"} },
- { INDEX_op_ext16u_i64, { "r", "r"} },
- { INDEX_op_ext32u_i64, { "r", "r"} },
-
- { INDEX_op_setcond_i32, { "r", "r", "ri" } },
- { INDEX_op_setcond_i64, { "r", "r", "re" } },
-
- { INDEX_op_qemu_ld8u, { "r", "L" } },
- { INDEX_op_qemu_ld8s, { "r", "L" } },
- { INDEX_op_qemu_ld16u, { "r", "L" } },
- { INDEX_op_qemu_ld16s, { "r", "L" } },
- { INDEX_op_qemu_ld32, { "r", "L" } },
- { INDEX_op_qemu_ld32u, { "r", "L" } },
- { INDEX_op_qemu_ld32s, { "r", "L" } },
- { INDEX_op_qemu_ld64, { "r", "L" } },
-
- { INDEX_op_qemu_st8, { "L", "L" } },
- { INDEX_op_qemu_st16, { "L", "L" } },
- { INDEX_op_qemu_st32, { "L", "L" } },
- { INDEX_op_qemu_st64, { "L", "L" } },
-
- { -1 },
-};
-
-static void tcg_target_init(TCGContext *s)
-{
-#if !defined(CONFIG_USER_ONLY)
- /* fail safe */
- if ((1 << CPU_TLB_ENTRY_BITS) != sizeof(CPUTLBEntry))
- tcg_abort();
-#endif
-
- tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffff);
- tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffff);
- tcg_regset_set32(tcg_target_call_clobber_regs, 0,
- (1 << TCG_REG_RDI) |
- (1 << TCG_REG_RSI) |
- (1 << TCG_REG_RDX) |
- (1 << TCG_REG_RCX) |
- (1 << TCG_REG_R8) |
- (1 << TCG_REG_R9) |
- (1 << TCG_REG_RAX) |
- (1 << TCG_REG_R10) |
- (1 << TCG_REG_R11));
-
- tcg_regset_clear(s->reserved_regs);
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_RSP);
-
- tcg_add_target_add_op_defs(x86_64_op_defs);
-}
diff --git a/tcg/x86_64/tcg-target.h b/tcg/x86_64/tcg-target.h
deleted file mode 100644
index e0eabaa..0000000
--- a/tcg/x86_64/tcg-target.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Tiny Code Generator for QEMU
- *
- * Copyright (c) 2008 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-#define TCG_TARGET_X86_64 1
-
-#define TCG_TARGET_REG_BITS 64
-//#define TCG_TARGET_WORDS_BIGENDIAN
-
-#define TCG_TARGET_NB_REGS 16
-
-enum {
- TCG_REG_RAX = 0,
- TCG_REG_RCX,
- TCG_REG_RDX,
- TCG_REG_RBX,
- TCG_REG_RSP,
- TCG_REG_RBP,
- TCG_REG_RSI,
- TCG_REG_RDI,
- TCG_REG_R8,
- TCG_REG_R9,
- TCG_REG_R10,
- TCG_REG_R11,
- TCG_REG_R12,
- TCG_REG_R13,
- TCG_REG_R14,
- TCG_REG_R15,
-};
-
-#define TCG_CT_CONST_S32 0x100
-#define TCG_CT_CONST_U32 0x200
-
-/* used for function call generation */
-#define TCG_REG_CALL_STACK TCG_REG_RSP
-#define TCG_TARGET_STACK_ALIGN 16
-#define TCG_TARGET_CALL_STACK_OFFSET 0
-
-/* optional instructions */
-#define TCG_TARGET_HAS_div2_i32
-#define TCG_TARGET_HAS_div2_i64
-#define TCG_TARGET_HAS_bswap16_i32
-#define TCG_TARGET_HAS_bswap16_i64
-#define TCG_TARGET_HAS_bswap32_i32
-#define TCG_TARGET_HAS_bswap32_i64
-#define TCG_TARGET_HAS_bswap64_i64
-#define TCG_TARGET_HAS_neg_i32
-#define TCG_TARGET_HAS_neg_i64
-#define TCG_TARGET_HAS_not_i32
-#define TCG_TARGET_HAS_not_i64
-#define TCG_TARGET_HAS_ext8s_i32
-#define TCG_TARGET_HAS_ext16s_i32
-#define TCG_TARGET_HAS_ext8s_i64
-#define TCG_TARGET_HAS_ext16s_i64
-#define TCG_TARGET_HAS_ext32s_i64
-#define TCG_TARGET_HAS_ext8u_i32
-#define TCG_TARGET_HAS_ext16u_i32
-#define TCG_TARGET_HAS_ext8u_i64
-#define TCG_TARGET_HAS_ext16u_i64
-#define TCG_TARGET_HAS_ext32u_i64
-#define TCG_TARGET_HAS_rot_i32
-#define TCG_TARGET_HAS_rot_i64
-
-// #define TCG_TARGET_HAS_andc_i32
-// #define TCG_TARGET_HAS_andc_i64
-// #define TCG_TARGET_HAS_orc_i32
-// #define TCG_TARGET_HAS_orc_i64
-// #define TCG_TARGET_HAS_eqv_i32
-// #define TCG_TARGET_HAS_eqv_i64
-// #define TCG_TARGET_HAS_nand_i32
-// #define TCG_TARGET_HAS_nand_i64
-// #define TCG_TARGET_HAS_nor_i32
-// #define TCG_TARGET_HAS_nor_i64
-
-#define TCG_TARGET_HAS_GUEST_BASE
-
-/* Note: must be synced with dyngen-exec.h */
-#define TCG_AREG0 TCG_REG_R14
-
-static inline void flush_icache_range(unsigned long start, unsigned long stop)
-{
-}
commit 1c0fd16018384daeb340b389a00768ceecc45611
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Thu Jun 10 00:14:02 2010 +0200
configure: display sysconfdir in summary
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/configure b/configure
index b2edb37..46b8e39 100755
--- a/configure
+++ b/configure
@@ -2015,6 +2015,7 @@ fi
echo "Install prefix $prefix"
echo "BIOS directory `eval echo $datadir`"
echo "binary directory `eval echo $bindir`"
+echo "config directory `eval echo $sysconfdir`"
if test "$mingw32" = "no" ; then
echo "Manual directory `eval echo $mandir`"
echo "ELF interp prefix $interp_prefix"
commit ca35f780ac4654bfa086613c72b011448afff327
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Wed May 26 16:08:29 2010 +0200
move computation of tools and roms outside of config-host.mak generation
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/configure b/configure
index cfecdd6..b2edb37 100755
--- a/configure
+++ b/configure
@@ -1991,6 +1991,27 @@ fi
confdir=$sysconfdir$confsuffix
+tools=
+if test "$softmmu" = yes ; then
+ tools="qemu-img\$(EXESUF) qemu-io\$(EXESUF) $tools"
+ if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
+ tools="qemu-nbd\$(EXESUF) $tools"
+ if [ "$check_utests" = "yes" ]; then
+ tools="check-qint check-qstring check-qdict check-qlist $tools"
+ tools="check-qfloat check-qjson $tools"
+ fi
+ fi
+fi
+
+# Mac OS X ships with a broken assembler
+roms=
+if test \( "$cpu" = "i386" -o "$cpu" = "x86_64" \) -a \
+ "$targetos" != "Darwin" -a "$targetos" != "SunOS" -a \
+ "$softmmu" = yes ; then
+ roms="optionrom"
+fi
+
+
echo "Install prefix $prefix"
echo "BIOS directory `eval echo $datadir`"
echo "binary directory `eval echo $bindir`"
@@ -2293,26 +2314,7 @@ bsd)
;;
esac
-tools=
-if test "$softmmu" = yes ; then
- tools="qemu-img\$(EXESUF) qemu-io\$(EXESUF) $tools"
- if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
- tools="qemu-nbd\$(EXESUF) $tools"
- if [ "$check_utests" = "yes" ]; then
- tools="check-qint check-qstring check-qdict check-qlist $tools"
- tools="check-qfloat check-qjson $tools"
- fi
- fi
-fi
echo "TOOLS=$tools" >> $config_host_mak
-
-# Mac OS X ships with a broken assembler
-roms=
-if test \( "$cpu" = "i386" -o "$cpu" = "x86_64" \) -a \
- "$targetos" != "Darwin" -a "$targetos" != "SunOS" -a \
- "$softmmu" = yes ; then
- roms="optionrom"
-fi
echo "ROMS=$roms" >> $config_host_mak
echo "MAKE=$make" >> $config_host_mak
echo "INSTALL=$install" >> $config_host_mak
commit 683035de789e3a0141b1c3bbfdc6180fbc67aaf1
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Wed May 26 16:08:28 2010 +0200
configure: move directory defaults earlier
Unify with existing special-purpose configure code for win32.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/configure b/configure
index fa1b2d0..cfecdd6 100755
--- a/configure
+++ b/configure
@@ -65,14 +65,8 @@ path_of() {
# default parameters
cpu=""
-prefix=""
interp_prefix="/usr/gnemul/qemu-%M"
static="no"
-mandir=""
-datadir=""
-docdir=""
-bindir=""
-sysconfdir=""
sparc_cpu=""
cross_prefix=""
cc="gcc"
@@ -280,6 +274,13 @@ strip_opt="yes"
bigendian="no"
mingw32="no"
EXESUF=""
+prefix="/usr/local"
+mandir="\${prefix}/share/man"
+datadir="\${prefix}/share/qemu"
+docdir="\${prefix}/share/doc/qemu"
+bindir="\${prefix}/bin"
+sysconfdir="\${prefix}/etc"
+confsuffix="/qemu"
slirp="yes"
fmod_lib=""
fmod_inc=""
@@ -454,6 +455,13 @@ if test "$mingw32" = "yes" ; then
# enable C99/POSIX format strings (needs mingw32-runtime 3.15 or later)
QEMU_CFLAGS="-D__USE_MINGW_ANSI_STDIO=1 $QEMU_CFLAGS"
LIBS="-lwinmm -lws2_32 -liphlpapi $LIBS"
+ prefix="c:/Program Files/Qemu"
+ mandir="\${prefix}"
+ datadir="\${prefix}"
+ docdir="\${prefix}"
+ bindir="\${prefix}"
+ sysconfdir="\${prefix}"
+ confsuffix=""
fi
# find source path
@@ -1981,33 +1989,6 @@ if test "$solaris" = "no" ; then
fi
fi
-if test "$mingw32" = "yes" ; then
- if test -z "$prefix" ; then
- prefix="c:/Program Files/Qemu"
- fi
- mansuffix=""
- datasuffix=""
- docsuffix=""
- binsuffix=""
- sysconfsuffix=""
- confsuffix=""
-else
- if test -z "$prefix" ; then
- prefix="/usr/local"
- fi
- mansuffix="/share/man"
- datasuffix="/share/qemu"
- docsuffix="/share/doc/qemu"
- binsuffix="/bin"
- sysconfsuffix="/etc"
- confsuffix="/qemu"
-fi
-
-: ${mandir:="\${prefix}$mansuffix"}
-: ${datadir:="\${prefix}$datasuffix"}
-: ${docdir:="\${prefix}$docsuffix"}
-: ${bindir:="\${prefix}$binsuffix"}
-: ${sysconfdir:="\${prefix}$sysconfsuffix"}
confdir=$sysconfdir$confsuffix
echo "Install prefix $prefix"
commit 6bde81cb03898b725ae6f94050aa060772c836e8
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Wed May 26 16:08:27 2010 +0200
configure: ignore unknown --xyzdir options
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/configure b/configure
index 5eb3ecd..fa1b2d0 100755
--- a/configure
+++ b/configure
@@ -673,6 +673,8 @@ for opt do
;;
--enable-vhost-net) vhost_net="yes"
;;
+ --*dir)
+ ;;
*) echo "ERROR: unknown option $opt"; show_help="yes"
;;
esac
commit 0b24e75f85c251b7ae699631768f129ddf03ae5e
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Wed May 26 16:08:26 2010 +0200
configure: introduce more --xyzdir options
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/configure b/configure
index 9d8b4b3..5eb3ecd 100755
--- a/configure
+++ b/configure
@@ -68,6 +68,10 @@ cpu=""
prefix=""
interp_prefix="/usr/gnemul/qemu-%M"
static="no"
+mandir=""
+datadir=""
+docdir=""
+bindir=""
sysconfdir=""
sparc_cpu=""
cross_prefix=""
@@ -501,6 +505,14 @@ for opt do
static="yes"
LDFLAGS="-static $LDFLAGS"
;;
+ --mandir=*) mandir="$optarg"
+ ;;
+ --bindir=*) bindir="$optarg"
+ ;;
+ --datadir=*) datadir="$optarg"
+ ;;
+ --docdir=*) docdir="$optarg"
+ ;;
--sysconfdir=*) sysconfdir="$optarg"
;;
--disable-sdl) sdl="no"
@@ -755,7 +767,11 @@ echo " --extra-ldflags=LDFLAGS append extra linker flags LDFLAGS"
echo " --make=MAKE use specified make [$make]"
echo " --install=INSTALL use specified install [$install]"
echo " --static enable static build [$static]"
-echo " --sysconfdir=PATH install config in PATH"
+echo " --mandir=PATH install man pages in PATH"
+echo " --datadir=PATH install firmware in PATH"
+echo " --docdir=PATH install documentation in PATH"
+echo " --bindir=PATH install binaries in PATH"
+echo " --sysconfdir=PATH install config in PATH/qemu"
echo " --enable-debug-tcg enable TCG debugging"
echo " --disable-debug-tcg disable TCG debugging (default)"
echo " --enable-debug enable common debug build options"
@@ -1985,10 +2001,10 @@ else
confsuffix="/qemu"
fi
-mandir="\${prefix}$mansuffix"
-datadir="\${prefix}$datasuffix"
-docdir="\${prefix}$docsuffix"
-bindir="\${prefix}$binsuffix"
+: ${mandir:="\${prefix}$mansuffix"}
+: ${datadir:="\${prefix}$datasuffix"}
+: ${docdir:="\${prefix}$docsuffix"}
+: ${bindir:="\${prefix}$binsuffix"}
: ${sysconfdir:="\${prefix}$sysconfsuffix"}
confdir=$sysconfdir$confsuffix
commit 1dabe05ce40010588a7b2485219a2692fe1e7472
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Wed May 26 16:08:25 2010 +0200
configure: expand ${prefix} in create_config
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/configure b/configure
index c99461a..9d8b4b3 100755
--- a/configure
+++ b/configure
@@ -2073,8 +2073,7 @@ echo "mandir=$mandir" >> $config_host_mak
echo "datadir=$datadir" >> $config_host_mak
echo "sysconfdir=$sysconfdir" >> $config_host_mak
echo "docdir=$docdir" >> $config_host_mak
-echo "CONFIG_QEMU_SHAREDIR=\"$prefix$datasuffix\"" >> $config_host_mak
-echo "CONFIG_QEMU_CONFDIR=\"$confdir\"" >> $config_host_mak
+echo "confdir=$confdir" >> $config_host_mak
case "$cpu" in
i386|x86_64|alpha|cris|hppa|ia64|m68k|microblaze|mips|mips64|ppc|ppc64|s390|s390x|sparc|sparc64)
diff --git a/create_config b/create_config
index edcad25..23c0cd5 100755
--- a/create_config
+++ b/create_config
@@ -13,6 +13,15 @@ case $line in
pkgversion=${line#*=}
echo "#define QEMU_PKGVERSION \"$pkgversion\""
;;
+ prefix=* | *dir=*) # directory configuration
+ name=${line%=*}
+ value=${line#*=}
+ define_name=`echo $name | tr '[:lower:]' '[:upper:]'`
+ eval "define_value=\"$value\""
+ echo "#define CONFIG_QEMU_$define_name \"$define_value\""
+ # save for the next definitions
+ eval "$name=\$define_value"
+ ;;
CONFIG_AUDIO_DRIVERS=*)
drivers=${line#*=}
echo "#define CONFIG_AUDIO_DRIVERS \\"
diff --git a/vl.c b/vl.c
index 7121cd0..6d08ec8 100644
--- a/vl.c
+++ b/vl.c
@@ -3423,7 +3423,7 @@ int main(int argc, char **argv, char **envp)
}
/* If all else fails use the install patch specified when building. */
if (!data_dir) {
- data_dir = CONFIG_QEMU_SHAREDIR;
+ data_dir = CONFIG_QEMU_DATADIR;
}
/*
commit 99d7cc75dd1f1167a02294804f993deb354d8159
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Wed May 26 16:08:24 2010 +0200
configure: move all directory entries in config-host.mak close
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/configure b/configure
index 23a056f..c99461a 100755
--- a/configure
+++ b/configure
@@ -2067,6 +2067,12 @@ printf "# Configured with:" >> $config_host_mak
printf " '%s'" "$0" "$@" >> $config_host_mak
echo >> $config_host_mak
+echo "prefix=$prefix" >> $config_host_mak
+echo "bindir=$bindir" >> $config_host_mak
+echo "mandir=$mandir" >> $config_host_mak
+echo "datadir=$datadir" >> $config_host_mak
+echo "sysconfdir=$sysconfdir" >> $config_host_mak
+echo "docdir=$docdir" >> $config_host_mak
echo "CONFIG_QEMU_SHAREDIR=\"$prefix$datasuffix\"" >> $config_host_mak
echo "CONFIG_QEMU_CONFDIR=\"$confdir\"" >> $config_host_mak
@@ -2310,13 +2316,6 @@ if test \( "$cpu" = "i386" -o "$cpu" = "x86_64" \) -a \
roms="optionrom"
fi
echo "ROMS=$roms" >> $config_host_mak
-
-echo "prefix=$prefix" >> $config_host_mak
-echo "bindir=$bindir" >> $config_host_mak
-echo "mandir=$mandir" >> $config_host_mak
-echo "datadir=$datadir" >> $config_host_mak
-echo "sysconfdir=$sysconfdir" >> $config_host_mak
-echo "docdir=$docdir" >> $config_host_mak
echo "MAKE=$make" >> $config_host_mak
echo "INSTALL=$install" >> $config_host_mak
echo "INSTALL_DIR=$install -d -m0755 -p" >> $config_host_mak
commit f2b9e1e37d9f4eaae35a7b568f913093897b121e
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Wed May 26 16:08:23 2010 +0200
configure: unify handling of xyzdir variables
Making an xyzdir variable for each directory prepares for the next
patches introducing config-host.h defines and configure options for them.
It also fixes the problem where overriding prefix at "make install"
time did not override it for sysconfdir.
Removes some of the differences between sysconfdir and other variables,
the rest will go away later.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/configure b/configure
index 6f282a3..23a056f 100755
--- a/configure
+++ b/configure
@@ -1985,14 +1985,18 @@ else
confsuffix="/qemu"
fi
-: ${sysconfdir:="${prefix}$sysconfsuffix"}
+mandir="\${prefix}$mansuffix"
+datadir="\${prefix}$datasuffix"
+docdir="\${prefix}$docsuffix"
+bindir="\${prefix}$binsuffix"
+: ${sysconfdir:="\${prefix}$sysconfsuffix"}
confdir=$sysconfdir$confsuffix
echo "Install prefix $prefix"
-echo "BIOS directory $prefix$datasuffix"
-echo "binary directory $prefix$binsuffix"
+echo "BIOS directory `eval echo $datadir`"
+echo "binary directory `eval echo $bindir`"
if test "$mingw32" = "no" ; then
-echo "Manual directory $prefix$mansuffix"
+echo "Manual directory `eval echo $mandir`"
echo "ELF interp prefix $interp_prefix"
fi
echo "Source path $source_path"
@@ -2308,11 +2312,11 @@ fi
echo "ROMS=$roms" >> $config_host_mak
echo "prefix=$prefix" >> $config_host_mak
-echo "bindir=\${prefix}$binsuffix" >> $config_host_mak
-echo "mandir=\${prefix}$mansuffix" >> $config_host_mak
-echo "datadir=\${prefix}$datasuffix" >> $config_host_mak
+echo "bindir=$bindir" >> $config_host_mak
+echo "mandir=$mandir" >> $config_host_mak
+echo "datadir=$datadir" >> $config_host_mak
echo "sysconfdir=$sysconfdir" >> $config_host_mak
-echo "docdir=\${prefix}$docsuffix" >> $config_host_mak
+echo "docdir=$docdir" >> $config_host_mak
echo "MAKE=$make" >> $config_host_mak
echo "INSTALL=$install" >> $config_host_mak
echo "INSTALL_DIR=$install -d -m0755 -p" >> $config_host_mak
commit 7ee2822cbeb06dbf38f5b38b5d7fa7829d598350
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Wed May 26 16:08:22 2010 +0200
rename CONFIG_QEMU_PREFIX
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 05cc3d9..aff9f13 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -43,7 +43,7 @@ unsigned long guest_base;
int have_guest_base;
#endif
-static const char *interp_prefix = CONFIG_QEMU_PREFIX;
+static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
extern char **environ;
enum BSDType bsd_type;
diff --git a/configure b/configure
index f7b0a6d..6f282a3 100755
--- a/configure
+++ b/configure
@@ -2430,7 +2430,7 @@ echo "# Automatically generated by configure - do not modify" > $config_target_m
bflt="no"
target_nptl="no"
interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_arch2/g"`
-echo "CONFIG_QEMU_PREFIX=\"$interp_prefix1\"" >> $config_target_mak
+echo "CONFIG_QEMU_INTERP_PREFIX=\"$interp_prefix1\"" >> $config_target_mak
gdb_xml_files=""
TARGET_ARCH="$target_arch2"
diff --git a/linux-user/main.c b/linux-user/main.c
index ad292f1..403c8d3 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -47,7 +47,7 @@ int have_guest_base;
unsigned long reserved_va;
#endif
-static const char *interp_prefix = CONFIG_QEMU_PREFIX;
+static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX;
const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
commit 190e9c59c0d4f56c98e378d1024d46cc7166409b
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Wed May 26 16:08:21 2010 +0200
configure: introduce confdir and confsuffix
confsuffix was write-only, flesh it out.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/configure b/configure
index 553607a..f7b0a6d 100755
--- a/configure
+++ b/configure
@@ -1969,10 +1969,10 @@ if test "$mingw32" = "yes" ; then
fi
mansuffix=""
datasuffix=""
- confsuffix=""
docsuffix=""
binsuffix=""
sysconfsuffix=""
+ confsuffix=""
else
if test -z "$prefix" ; then
prefix="/usr/local"
@@ -1982,9 +1982,11 @@ else
docsuffix="/share/doc/qemu"
binsuffix="/bin"
sysconfsuffix="/etc"
+ confsuffix="/qemu"
fi
: ${sysconfdir:="${prefix}$sysconfsuffix"}
+confdir=$sysconfdir$confsuffix
echo "Install prefix $prefix"
echo "BIOS directory $prefix$datasuffix"
@@ -2062,11 +2064,7 @@ printf " '%s'" "$0" "$@" >> $config_host_mak
echo >> $config_host_mak
echo "CONFIG_QEMU_SHAREDIR=\"$prefix$datasuffix\"" >> $config_host_mak
-if test "$mingw32" = "yes" ; then
- echo "CONFIG_QEMU_CONFDIR=\"$sysconfdir\"" >> $config_host_mak
-else
- echo "CONFIG_QEMU_CONFDIR=\"${sysconfdir}/qemu\"" >> $config_host_mak
-fi
+echo "CONFIG_QEMU_CONFDIR=\"$confdir\"" >> $config_host_mak
case "$cpu" in
i386|x86_64|alpha|cris|hppa|ia64|m68k|microblaze|mips|mips64|ppc|ppc64|s390|s390x|sparc|sparc64)
commit e7b45cc4467f9bbae46acdc8d21ceb2a16d63b50
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Wed May 26 16:08:20 2010 +0200
configure: introduce sysconfsuffix
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/configure b/configure
index 31bd7ec..553607a 100755
--- a/configure
+++ b/configure
@@ -1972,9 +1972,7 @@ if test "$mingw32" = "yes" ; then
confsuffix=""
docsuffix=""
binsuffix=""
- if test -z "$sysconfdir" ; then
- sysconfdir="${prefix}"
- fi
+ sysconfsuffix=""
else
if test -z "$prefix" ; then
prefix="/usr/local"
@@ -1983,11 +1981,11 @@ else
datasuffix="/share/qemu"
docsuffix="/share/doc/qemu"
binsuffix="/bin"
- if test -z "$sysconfdir" ; then
- sysconfdir="${prefix}/etc"
- fi
+ sysconfsuffix="/etc"
fi
+: ${sysconfdir:="${prefix}$sysconfsuffix"}
+
echo "Install prefix $prefix"
echo "BIOS directory $prefix$datasuffix"
echo "binary directory $prefix$binsuffix"
commit 604f78e06e41526924890d83f9dab168268f4702
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Wed May 26 16:08:19 2010 +0200
configure: delete duplicate create_config case stanza
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/create_config b/create_config
index 2f052ae..edcad25 100755
--- a/create_config
+++ b/create_config
@@ -13,11 +13,6 @@ case $line in
pkgversion=${line#*=}
echo "#define QEMU_PKGVERSION \"$pkgversion\""
;;
- ARCH=*) # configuration
- arch=${line#*=}
- arch_name=`echo $arch | tr '[:lower:]' '[:upper:]'`
- echo "#define HOST_$arch_name 1"
- ;;
CONFIG_AUDIO_DRIVERS=*)
drivers=${line#*=}
echo "#define CONFIG_AUDIO_DRIVERS \\"
commit 0bfe8cc01259dff2b0d4d464d9154d0a2c25daca
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Wed May 26 16:08:18 2010 +0200
configure: dyngen is long time gone
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/configure b/configure
index 57eb27f..31bd7ec 100755
--- a/configure
+++ b/configure
@@ -748,7 +748,8 @@ echo "Advanced options (experts only):"
echo " --source-path=PATH path of source code [$source_path]"
echo " --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]"
echo " --cc=CC use C compiler CC [$cc]"
-echo " --host-cc=CC use C compiler CC [$host_cc] for dyngen etc."
+echo " --host-cc=CC use C compiler CC [$host_cc] for code run at"
+echo " build time"
echo " --extra-cflags=CFLAGS append extra C compiler flags QEMU_CFLAGS"
echo " --extra-ldflags=LDFLAGS append extra linker flags LDFLAGS"
echo " --make=MAKE use specified make [$make]"
commit f55fe2785c017a00b3aef547a68e2dd1a4843a16
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Wed May 26 16:08:17 2010 +0200
configure: avoid using expr
Just a personal preference against duplicating hieroglyphics.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/configure b/configure
index 1d4f1e4..57eb27f 100755
--- a/configure
+++ b/configure
@@ -928,6 +928,13 @@ if test -z "$target_list" ; then
echo "No targets enabled"
exit 1
fi
+# see if system emulation was really requested
+case " $target_list " in
+ *"-softmmu "*) softmmu=yes
+ ;;
+ *) softmmu=no
+ ;;
+esac
feature_not_found() {
feature=$1
@@ -2282,7 +2289,7 @@ bsd)
esac
tools=
-if test `expr "$target_list" : ".*softmmu.*"` != 0 ; then
+if test "$softmmu" = yes ; then
tools="qemu-img\$(EXESUF) qemu-io\$(EXESUF) $tools"
if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
tools="qemu-nbd\$(EXESUF) $tools"
@@ -2298,7 +2305,7 @@ echo "TOOLS=$tools" >> $config_host_mak
roms=
if test \( "$cpu" = "i386" -o "$cpu" = "x86_64" \) -a \
"$targetos" != "Darwin" -a "$targetos" != "SunOS" -a \
- `expr "$target_list" : ".*softmmu.*"` != 0 ; then
+ "$softmmu" = yes ; then
roms="optionrom"
fi
echo "ROMS=$roms" >> $config_host_mak
commit a447d4dc5607176a70361aed9361e1b63dc67ec9
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Wed May 26 16:08:16 2010 +0200
configure: bail out early on invalid -cpu option
It would fail later anyway.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/configure b/configure
index 8d3084a..1d4f1e4 100755
--- a/configure
+++ b/configure
@@ -232,7 +232,8 @@ case "$cpu" in
cpu="sparc"
;;
*)
- cpu="unknown"
+ echo "Unsupported CPU = $cpu"
+ exit 1
;;
esac
@@ -2068,10 +2069,6 @@ case "$cpu" in
armv4b|armv4l)
ARCH=arm
;;
- *)
- echo "Unsupported CPU = $cpu"
- exit 1
- ;;
esac
echo "ARCH=$ARCH" >> $config_host_mak
if test "$debug_tcg" = "yes" ; then
commit 4021d2476c61ff101f97b6642d1fbb3c34844091
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Thu Jun 10 00:06:55 2010 +0200
configure: remove some bashisms
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/configure b/configure
index 72d8924..8d3084a 100755
--- a/configure
+++ b/configure
@@ -15,7 +15,7 @@ TMPC="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.c"
TMPO="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.o"
TMPE="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.exe"
-trap "rm -f $TMPC $TMPO $TMPE ; exit" 0 2 3 15
+trap "rm -f $TMPC $TMPO $TMPE ; exit" EXIT INT QUIT TERM
compile_object() {
$cc $QEMU_CFLAGS -c -o $TMPO $TMPC > /dev/null 2> /dev/null
@@ -1546,7 +1546,7 @@ EOF
fi
else
if test "$vhost_net" = "yes" ; then
- echo -e "NOTE: vhost-net feature requires KVM (--enable-kvm)."
+ echo "NOTE: vhost-net feature requires KVM (--enable-kvm)."
feature_not_found "vhost-net"
fi
vhost_net=no
commit 330875984432c26ef78bad85c4ee9816d3c41ca5
Author: Stefan Weil <weil at mail.berlios.de>
Date: Wed Jun 9 22:09:40 2010 +0200
target-mips: Fix compilation
TCGv t1 needs tcg_temp_free instead of tcg_temp_free_i32.
Cc: Nathan Froyd <froydnj at codesourcery.com>
Cc: Aurelien Jarno <aurelien at aurel32.net>
Signed-off-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-mips/translate.c b/target-mips/translate.c
index ab8f974..d43d72d 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -9484,7 +9484,7 @@ static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
}
MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
tcg_temp_free(t0);
- tcg_temp_free_i32(t1);
+ tcg_temp_free(t1);
tcg_temp_free_i32(t2);
}
commit aecf13769852a4e14b51e8403860b18871826298
Author: Nathan Froyd <froydnj at codesourcery.com>
Date: Tue Jun 8 13:30:03 2010 -0700
hw: honor low bit in mipssim machine
Signed-off-by: Nathan Froyd <froydnj at codesourcery.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c
index a747de5..293d99e 100644
--- a/hw/mips_mipssim.c
+++ b/hw/mips_mipssim.c
@@ -106,7 +106,10 @@ static void main_cpu_reset(void *opaque)
CPUState *env = s->env;
cpu_reset(env);
- env->active_tc.PC = s->vector;
+ env->active_tc.PC = s->vector & ~(target_ulong)1;
+ if (s->vector & 1) {
+ env->hflags |= MIPS_HFLAG_M16;
+ }
}
static void
commit 0fddbbf2559579ab6274c50819001f4eb9896b2a
Author: Nathan Froyd <froydnj at codesourcery.com>
Date: Tue Jun 8 13:30:02 2010 -0700
linux-user: honor low bit of entry PC for MIPS
Signed-off-by: Nathan Froyd <froydnj at codesourcery.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/linux-user/main.c b/linux-user/main.c
index 0f23fc9..ad292f1 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -3271,7 +3271,10 @@ int main(int argc, char **argv, char **envp)
for(i = 0; i < 32; i++) {
env->active_tc.gpr[i] = regs->regs[i];
}
- env->active_tc.PC = regs->cp0_epc;
+ env->active_tc.PC = regs->cp0_epc & ~(target_ulong)1;
+ if (regs->cp0_epc & 1) {
+ env->hflags |= MIPS_HFLAG_M16;
+ }
}
#elif defined(TARGET_SH4)
{
commit bbfa8f72e99baa0514b2b39e671830cf9a3adc44
Author: Nathan Froyd <froydnj at codesourcery.com>
Date: Tue Jun 8 13:30:01 2010 -0700
target-mips: add microMIPS exception handler support
Unlike MIPS16, microMIPS lets you choose the ISA mode for your exception
handlers. The ISA mode is selectable via a user-writable CP0.Config3
flag.
Signed-off-by: Nathan Froyd <froydnj at codesourcery.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-mips/cpu.h b/target-mips/cpu.h
index 7285636..c21b8e4 100644
--- a/target-mips/cpu.h
+++ b/target-mips/cpu.h
@@ -363,6 +363,7 @@ struct CPUMIPSState {
#define CP0C2_SA 0
int32_t CP0_Config3;
#define CP0C3_M 31
+#define CP0C3_ISA_ON_EXC 16
#define CP0C3_DSPP 10
#define CP0C3_LPA 7
#define CP0C3_VEIC 6
diff --git a/target-mips/helper.c b/target-mips/helper.c
index 8102f03..ea221ab 100644
--- a/target-mips/helper.c
+++ b/target-mips/helper.c
@@ -385,6 +385,18 @@ static target_ulong exception_resume_pc (CPUState *env)
return bad_pc;
}
+
+static void set_hflags_for_handler (CPUState *env)
+{
+ /* Exception handlers are entered in 32-bit mode. */
+ env->hflags &= ~(MIPS_HFLAG_M16);
+ /* ...except that microMIPS lets you choose. */
+ if (env->insn_flags & ASE_MICROMIPS) {
+ env->hflags |= (!!(env->CP0_Config3
+ & (1 << CP0C3_ISA_ON_EXC))
+ << MIPS_HFLAG_M16_SHIFT);
+ }
+}
#endif
void do_interrupt (CPUState *env)
@@ -440,8 +452,7 @@ void do_interrupt (CPUState *env)
if (!(env->CP0_Status & (1 << CP0St_EXL)))
env->CP0_Cause &= ~(1 << CP0Ca_BD);
env->active_tc.PC = (int32_t)0xBFC00480;
- /* Exception handlers are entered in 32-bit mode. */
- env->hflags &= ~(MIPS_HFLAG_M16);
+ set_hflags_for_handler(env);
break;
case EXCP_RESET:
cpu_reset(env);
@@ -461,8 +472,7 @@ void do_interrupt (CPUState *env)
if (!(env->CP0_Status & (1 << CP0St_EXL)))
env->CP0_Cause &= ~(1 << CP0Ca_BD);
env->active_tc.PC = (int32_t)0xBFC00000;
- /* Exception handlers are entered in 32-bit mode. */
- env->hflags &= ~(MIPS_HFLAG_M16);
+ set_hflags_for_handler(env);
break;
case EXCP_EXT_INTERRUPT:
cause = 0;
@@ -581,8 +591,7 @@ void do_interrupt (CPUState *env)
env->active_tc.PC = (int32_t)(env->CP0_EBase & ~0x3ff);
}
env->active_tc.PC += offset;
- /* Exception handlers are entered in 32-bit mode. */
- env->hflags &= ~(MIPS_HFLAG_M16);
+ set_hflags_for_handler(env);
env->CP0_Cause = (env->CP0_Cause & ~(0x1f << CP0Ca_EC)) | (cause << CP0Ca_EC);
break;
default:
commit 3c824109da076d2a1df4b798f9df81b385131f92
Author: Nathan Froyd <froydnj at codesourcery.com>
Date: Tue Jun 8 13:29:59 2010 -0700
target-mips: microMIPS ASE support
Add instruction decoding for the microMIPS ASE. All we do is decode and
then forward to the existing gen_* routines.
Signed-off-by: Nathan Froyd <froydnj at codesourcery.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-mips/helper.h b/target-mips/helper.h
index ab47b1a..a6ba75d 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -160,6 +160,15 @@ DEF_HELPER_1(emt, tl, tl)
DEF_HELPER_1(dvpe, tl, tl)
DEF_HELPER_1(evpe, tl, tl)
#endif /* !CONFIG_USER_ONLY */
+
+/* microMIPS functions */
+DEF_HELPER_3(lwm, void, tl, tl, i32);
+DEF_HELPER_3(swm, void, tl, tl, i32);
+#ifdef TARGET_MIPS64
+DEF_HELPER_3(ldm, void, tl, tl, i32);
+DEF_HELPER_3(sdm, void, tl, tl, i32);
+#endif
+
DEF_HELPER_2(fork, void, tl, tl)
DEF_HELPER_1(yield, tl, tl)
diff --git a/target-mips/mips-defs.h b/target-mips/mips-defs.h
index c57de02..a7f4697 100644
--- a/target-mips/mips-defs.h
+++ b/target-mips/mips-defs.h
@@ -38,6 +38,7 @@
#define ASE_DSPR2 0x00010000
#define ASE_MT 0x00020000
#define ASE_SMARTMIPS 0x00040000
+#define ASE_MICROMIPS 0x00080000
/* Chip specific instructions. */
#define INSN_VR54XX 0x80000000
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 2bfdd50..d09d6ed 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -565,6 +565,142 @@ void helper_sdr(target_ulong arg1, target_ulong arg2, int mem_idx)
}
#endif /* TARGET_MIPS64 */
+static const int multiple_regs[] = { 16, 17, 18, 19, 20, 21, 22, 23, 30 };
+
+void helper_lwm (target_ulong addr, target_ulong reglist, uint32_t mem_idx)
+{
+ target_ulong base_reglist = reglist & 0xf;
+ target_ulong do_r31 = reglist & 0x10;
+#ifdef CONFIG_USER_ONLY
+#undef ldfun
+#define ldfun ldl_raw
+#else
+ uint32_t (*ldfun)(target_ulong);
+
+ switch (mem_idx)
+ {
+ case 0: ldfun = ldl_kernel; break;
+ case 1: ldfun = ldl_super; break;
+ default:
+ case 2: ldfun = ldl_user; break;
+ }
+#endif
+
+ if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
+ target_ulong i;
+
+ for (i = 0; i < base_reglist; i++) {
+ env->active_tc.gpr[multiple_regs[i]] = (target_long) ldfun(addr);
+ addr += 4;
+ }
+ }
+
+ if (do_r31) {
+ env->active_tc.gpr[31] = (target_long) ldfun(addr);
+ }
+}
+
+void helper_swm (target_ulong addr, target_ulong reglist, uint32_t mem_idx)
+{
+ target_ulong base_reglist = reglist & 0xf;
+ target_ulong do_r31 = reglist & 0x10;
+#ifdef CONFIG_USER_ONLY
+#undef stfun
+#define stfun stl_raw
+#else
+ void (*stfun)(target_ulong, uint32_t);
+
+ switch (mem_idx)
+ {
+ case 0: stfun = stl_kernel; break;
+ case 1: stfun = stl_super; break;
+ default:
+ case 2: stfun = stl_user; break;
+ }
+#endif
+
+ if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
+ target_ulong i;
+
+ for (i = 0; i < base_reglist; i++) {
+ stfun(addr, env->active_tc.gpr[multiple_regs[i]]);
+ addr += 4;
+ }
+ }
+
+ if (do_r31) {
+ stfun(addr, env->active_tc.gpr[31]);
+ }
+}
+
+#if defined(TARGET_MIPS64)
+void helper_ldm (target_ulong addr, target_ulong reglist, uint32_t mem_idx)
+{
+ target_ulong base_reglist = reglist & 0xf;
+ target_ulong do_r31 = reglist & 0x10;
+#ifdef CONFIG_USER_ONLY
+#undef ldfun
+#define ldfun ldq_raw
+#else
+ uint64_t (*ldfun)(target_ulong);
+
+ switch (mem_idx)
+ {
+ case 0: ldfun = ldq_kernel; break;
+ case 1: ldfun = ldq_super; break;
+ default:
+ case 2: ldfun = ldq_user; break;
+ }
+#endif
+
+ if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
+ target_ulong i;
+
+ for (i = 0; i < base_reglist; i++) {
+ env->active_tc.gpr[multiple_regs[i]] = ldfun(addr);
+ addr += 8;
+ }
+ }
+
+ if (do_r31) {
+ env->active_tc.gpr[31] = ldfun(addr);
+ }
+}
+
+void helper_sdm (target_ulong addr, target_ulong reglist, uint32_t mem_idx)
+{
+ target_ulong base_reglist = reglist & 0xf;
+ target_ulong do_r31 = reglist & 0x10;
+#ifdef CONFIG_USER_ONLY
+#undef stfun
+#define stfun stq_raw
+#else
+ void (*stfun)(target_ulong, uint64_t);
+
+ switch (mem_idx)
+ {
+ case 0: stfun = stq_kernel; break;
+ case 1: stfun = stq_super; break;
+ default:
+ case 2: stfun = stq_user; break;
+ }
+#endif
+
+ if (base_reglist > 0 && base_reglist <= ARRAY_SIZE (multiple_regs)) {
+ target_ulong i;
+
+ for (i = 0; i < base_reglist; i++) {
+ stfun(addr, env->active_tc.gpr[multiple_regs[i]]);
+ addr += 8;
+ }
+ }
+
+ if (do_r31) {
+ stfun(addr, env->active_tc.gpr[31]);
+ }
+}
+#endif
+
#ifndef CONFIG_USER_ONLY
/* CP0 helpers */
target_ulong helper_mfc0_mvpcontrol (void)
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 78783a8..ab8f974 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -4,7 +4,7 @@
* Copyright (c) 2004-2005 Jocelyn Mayer
* Copyright (c) 2006 Marius Groeger (FPU operations)
* Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support)
- * Copyright (c) 2009 CodeSourcery (MIPS16 support)
+ * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -243,8 +243,10 @@ enum {
OPC_BGEZ = (0x01 << 16) | OPC_REGIMM,
OPC_BGEZL = (0x03 << 16) | OPC_REGIMM,
OPC_BLTZAL = (0x10 << 16) | OPC_REGIMM,
+ OPC_BLTZALS = OPC_BLTZAL | 0x5, /* microMIPS */
OPC_BLTZALL = (0x12 << 16) | OPC_REGIMM,
OPC_BGEZAL = (0x11 << 16) | OPC_REGIMM,
+ OPC_BGEZALS = OPC_BGEZAL | 0x5, /* microMIPS */
OPC_BGEZALL = (0x13 << 16) | OPC_REGIMM,
OPC_TGEI = (0x08 << 16) | OPC_REGIMM,
OPC_TGEIU = (0x09 << 16) | OPC_REGIMM,
@@ -2449,6 +2451,7 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
break;
case OPC_BGEZ:
case OPC_BGEZAL:
+ case OPC_BGEZALS:
case OPC_BGEZALL:
case OPC_BGEZL:
case OPC_BGTZ:
@@ -2457,6 +2460,7 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
case OPC_BLEZL:
case OPC_BLTZ:
case OPC_BLTZAL:
+ case OPC_BLTZALS:
case OPC_BLTZALL:
case OPC_BLTZL:
/* Compare to zero */
@@ -2506,8 +2510,12 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
ctx->hflags |= MIPS_HFLAG_B;
MIPS_DEBUG("balways");
break;
+ case OPC_BGEZALS:
case OPC_BGEZAL: /* 0 >= 0 */
case OPC_BGEZALL: /* 0 >= 0 likely */
+ ctx->hflags |= (opc == OPC_BGEZALS
+ ? MIPS_HFLAG_BDS16
+ : MIPS_HFLAG_BDS32);
/* Always take and link */
blink = 31;
ctx->hflags |= MIPS_HFLAG_B;
@@ -2519,10 +2527,18 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
/* Treat as NOP. */
MIPS_DEBUG("bnever (NOP)");
goto out;
+ case OPC_BLTZALS:
case OPC_BLTZAL: /* 0 < 0 */
- tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
+ ctx->hflags |= (opc == OPC_BLTZALS
+ ? MIPS_HFLAG_BDS16
+ : MIPS_HFLAG_BDS32);
+ /* Handle as an unconditional branch to get correct delay
+ slot checking. */
+ blink = 31;
+ btgt = ctx->pc + (opc == OPC_BLTZALS ? 6 : 8);
+ ctx->hflags |= MIPS_HFLAG_B;
MIPS_DEBUG("bnever and link");
- goto out;
+ break;
case OPC_BLTZALL: /* 0 < 0 likely */
tcg_gen_movi_tl(cpu_gpr[31], ctx->pc + 8);
/* Skip the instruction in the delay slot */
@@ -2604,7 +2620,11 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
MIPS_DEBUG("bgezl %s, " TARGET_FMT_lx, regnames[rs], btgt);
goto likely;
+ case OPC_BGEZALS:
case OPC_BGEZAL:
+ ctx->hflags |= (opc == OPC_BGEZALS
+ ? MIPS_HFLAG_BDS16
+ : MIPS_HFLAG_BDS32);
tcg_gen_setcondi_tl(TCG_COND_GE, bcond, t0, 0);
MIPS_DEBUG("bgezal %s, " TARGET_FMT_lx, regnames[rs], btgt);
blink = 31;
@@ -2638,7 +2658,11 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
MIPS_DEBUG("bltzl %s, " TARGET_FMT_lx, regnames[rs], btgt);
goto likely;
+ case OPC_BLTZALS:
case OPC_BLTZAL:
+ ctx->hflags |= (opc == OPC_BLTZALS
+ ? MIPS_HFLAG_BDS16
+ : MIPS_HFLAG_BDS32);
tcg_gen_setcondi_tl(TCG_COND_LT, bcond, t0, 0);
blink = 31;
MIPS_DEBUG("bltzal %s, " TARGET_FMT_lx, regnames[rs], btgt);
@@ -7785,7 +7809,7 @@ static void handle_delay_slot (CPUState *env, DisasContext *ctx,
case MIPS_HFLAG_BR:
/* unconditional branch to register */
MIPS_DEBUG("branch to register");
- if (env->insn_flags & ASE_MIPS16) {
+ if (env->insn_flags & (ASE_MIPS16 | ASE_MICROMIPS)) {
TCGv t0 = tcg_temp_new();
TCGv_i32 t1 = tcg_temp_new_i32();
@@ -8906,6 +8930,2358 @@ static int decode_mips16_opc (CPUState *env, DisasContext *ctx,
return n_bytes;
}
+/* microMIPS extension to MIPS32 */
+
+/* microMIPS32 major opcodes */
+
+enum {
+ POOL32A = 0x00,
+ POOL16A = 0x01,
+ LBU16 = 0x02,
+ MOVE16 = 0x03,
+ ADDI32 = 0x04,
+ LBU32 = 0x05,
+ SB32 = 0x06,
+ LB32 = 0x07,
+
+ POOL32B = 0x08,
+ POOL16B = 0x09,
+ LHU16 = 0x0a,
+ ANDI16 = 0x0b,
+ ADDIU32 = 0x0c,
+ LHU32 = 0x0d,
+ SH32 = 0x0e,
+ LH32 = 0x0f,
+
+ POOL32I = 0x10,
+ POOL16C = 0x11,
+ LWSP16 = 0x12,
+ POOL16D = 0x13,
+ ORI32 = 0x14,
+ POOL32F = 0x15,
+ POOL32S = 0x16,
+ DADDIU32 = 0x17,
+
+ POOL32C = 0x18,
+ LWGP16 = 0x19,
+ LW16 = 0x1a,
+ POOL16E = 0x1b,
+ XORI32 = 0x1c,
+ JALS32 = 0x1d,
+ ADDIUPC = 0x1e,
+ POOL48A = 0x1f,
+
+ /* 0x20 is reserved */
+ RES_20 = 0x20,
+ POOL16F = 0x21,
+ SB16 = 0x22,
+ BEQZ16 = 0x23,
+ SLTI32 = 0x24,
+ BEQ32 = 0x25,
+ SWC132 = 0x26,
+ LWC132 = 0x27,
+
+ /* 0x28 and 0x29 are reserved */
+ RES_28 = 0x28,
+ RES_29 = 0x29,
+ SH16 = 0x2a,
+ BNEZ16 = 0x2b,
+ SLTIU32 = 0x2c,
+ BNE32 = 0x2d,
+ SDC132 = 0x2e,
+ LDC132 = 0x2f,
+
+ /* 0x30 and 0x31 are reserved */
+ RES_30 = 0x30,
+ RES_31 = 0x31,
+ SWSP16 = 0x32,
+ B16 = 0x33,
+ ANDI32 = 0x34,
+ J32 = 0x35,
+ SD32 = 0x36,
+ LD32 = 0x37,
+
+ /* 0x38 and 0x39 are reserved */
+ RES_38 = 0x38,
+ RES_39 = 0x39,
+ SW16 = 0x3a,
+ LI16 = 0x3b,
+ JALX32 = 0x3c,
+ JAL32 = 0x3d,
+ SW32 = 0x3e,
+ LW32 = 0x3f
+};
+
+/* POOL32A encoding of minor opcode field */
+
+enum {
+ /* These opcodes are distinguished only by bits 9..6; those bits are
+ * what are recorded below. */
+ SLL32 = 0x0,
+ SRL32 = 0x1,
+ SRA = 0x2,
+ ROTR = 0x3,
+
+ SLLV = 0x0,
+ SRLV = 0x1,
+ SRAV = 0x2,
+ ROTRV = 0x3,
+ ADD = 0x4,
+ ADDU32 = 0x5,
+ SUB = 0x6,
+ SUBU32 = 0x7,
+ MUL = 0x8,
+ AND = 0x9,
+ OR32 = 0xa,
+ NOR = 0xb,
+ XOR32 = 0xc,
+ SLT = 0xd,
+ SLTU = 0xe,
+
+ MOVN = 0x0,
+ MOVZ = 0x1,
+ LWXS = 0x4,
+
+ /* The following can be distinguished by their lower 6 bits. */
+ INS = 0x0c,
+ EXT = 0x2c,
+ POOL32AXF = 0x3c
+};
+
+/* POOL32AXF encoding of minor opcode field extension */
+
+enum {
+ /* bits 11..6 */
+ TEQ = 0x00,
+ TGE = 0x08,
+ TGEU = 0x10,
+ TLT = 0x20,
+ TLTU = 0x28,
+ TNE = 0x30,
+
+ MFC0 = 0x03,
+ MTC0 = 0x0b,
+
+ /* bits 13..12 for 0x01 */
+ MFHI_ACC = 0x0,
+ MFLO_ACC = 0x1,
+ MTHI_ACC = 0x2,
+ MTLO_ACC = 0x3,
+
+ /* bits 13..12 for 0x2a */
+ MADD_ACC = 0x0,
+ MADDU_ACC = 0x1,
+ MSUB_ACC = 0x2,
+ MSUBU_ACC = 0x3,
+
+ /* bits 13..12 for 0x32 */
+ MULT_ACC = 0x0,
+ MULTU_ACC = 0x0,
+
+ /* bits 15..12 for 0x2c */
+ SEB = 0x2,
+ SEH = 0x3,
+ CLO = 0x4,
+ CLZ = 0x5,
+ RDHWR = 0x6,
+ WSBH = 0x7,
+ MULT = 0x8,
+ MULTU = 0x9,
+ DIV = 0xa,
+ DIVU = 0xb,
+ MADD = 0xc,
+ MADDU = 0xd,
+ MSUB = 0xe,
+ MSUBU = 0xf,
+
+ /* bits 15..12 for 0x34 */
+ MFC2 = 0x4,
+ MTC2 = 0x5,
+ MFHC2 = 0x8,
+ MTHC2 = 0x9,
+ CFC2 = 0xc,
+ CTC2 = 0xd,
+
+ /* bits 15..12 for 0x3c */
+ JALR = 0x0,
+ JR = 0x0, /* alias */
+ JALR_HB = 0x1,
+ JALRS = 0x4,
+ JALRS_HB = 0x5,
+
+ /* bits 15..12 for 0x05 */
+ RDPGPR = 0xe,
+ WRPGPR = 0xf,
+
+ /* bits 15..12 for 0x0d */
+ TLBP = 0x0,
+ TLBR = 0x1,
+ TLBWI = 0x2,
+ TLBWR = 0x3,
+ WAIT = 0x9,
+ IRET = 0xd,
+ DERET = 0xe,
+ ERET = 0xf,
+
+ /* bits 15..12 for 0x15 */
+ DMT = 0x0,
+ DVPE = 0x1,
+ EMT = 0x2,
+ EVPE = 0x3,
+
+ /* bits 15..12 for 0x1d */
+ DI = 0x4,
+ EI = 0x5,
+
+ /* bits 15..12 for 0x2d */
+ SYNC = 0x6,
+ SYSCALL = 0x8,
+ SDBBP = 0xd,
+
+ /* bits 15..12 for 0x35 */
+ MFHI32 = 0x0,
+ MFLO32 = 0x1,
+ MTHI32 = 0x2,
+ MTLO32 = 0x3,
+};
+
+/* POOL32B encoding of minor opcode field (bits 15..12) */
+
+enum {
+ LWC2 = 0x0,
+ LWP = 0x1,
+ LDP = 0x4,
+ LWM32 = 0x5,
+ CACHE = 0x6,
+ LDM = 0x7,
+ SWC2 = 0x8,
+ SWP = 0x9,
+ SDP = 0xc,
+ SWM32 = 0xd,
+ SDM = 0xf
+};
+
+/* POOL32C encoding of minor opcode field (bits 15..12) */
+
+enum {
+ LWL = 0x0,
+ SWL = 0x8,
+ LWR = 0x1,
+ SWR = 0x9,
+ PREF = 0x2,
+ /* 0xa is reserved */
+ LL = 0x3,
+ SC = 0xb,
+ LDL = 0x4,
+ SDL = 0xc,
+ LDR = 0x5,
+ SDR = 0xd,
+ /* 0x6 is reserved */
+ LWU = 0xe,
+ LLD = 0x7,
+ SCD = 0xf
+};
+
+/* POOL32F encoding of minor opcode field (bits 5..0) */
+
+enum {
+ /* These are the bit 7..6 values */
+ ADD_FMT = 0x0,
+ MOVN_FMT = 0x0,
+
+ SUB_FMT = 0x1,
+ MOVZ_FMT = 0x1,
+
+ MUL_FMT = 0x2,
+
+ DIV_FMT = 0x3,
+
+ /* These are the bit 8..6 values */
+ RSQRT2_FMT = 0x0,
+ MOVF_FMT = 0x0,
+
+ LWXC1 = 0x1,
+ MOVT_FMT = 0x1,
+
+ PLL_PS = 0x2,
+ SWXC1 = 0x2,
+
+ PLU_PS = 0x3,
+ LDXC1 = 0x3,
+
+ PUL_PS = 0x4,
+ SDXC1 = 0x4,
+ RECIP2_FMT = 0x4,
+
+ PUU_PS = 0x5,
+ LUXC1 = 0x5,
+
+ CVT_PS_S = 0x6,
+ SUXC1 = 0x6,
+ ADDR_PS = 0x6,
+ PREFX = 0x6,
+
+ MULR_PS = 0x7,
+
+ MADD_S = 0x01,
+ MADD_D = 0x09,
+ MADD_PS = 0x11,
+ ALNV_PS = 0x19,
+ MSUB_S = 0x21,
+ MSUB_D = 0x29,
+ MSUB_PS = 0x31,
+
+ NMADD_S = 0x02,
+ NMADD_D = 0x0a,
+ NMADD_PS = 0x12,
+ NMSUB_S = 0x22,
+ NMSUB_D = 0x2a,
+ NMSUB_PS = 0x32,
+
+ POOL32FXF = 0x3b,
+
+ CABS_COND_FMT = 0x1c, /* MIPS3D */
+ C_COND_FMT = 0x3c
+};
+
+/* POOL32Fxf encoding of minor opcode extension field */
+
+enum {
+ CVT_L = 0x04,
+ RSQRT_FMT = 0x08,
+ FLOOR_L = 0x0c,
+ CVT_PW_PS = 0x1c,
+ CVT_W = 0x24,
+ SQRT_FMT = 0x28,
+ FLOOR_W = 0x2c,
+ CVT_PS_PW = 0x3c,
+ CFC1 = 0x40,
+ RECIP_FMT = 0x48,
+ CEIL_L = 0x4c,
+ CTC1 = 0x60,
+ CEIL_W = 0x6c,
+ MFC1 = 0x80,
+ CVT_S_PL = 0x84,
+ TRUNC_L = 0x8c,
+ MTC1 = 0xa0,
+ CVT_S_PU = 0xa4,
+ TRUNC_W = 0xac,
+ MFHC1 = 0xc0,
+ ROUND_L = 0xcc,
+ MTHC1 = 0xe0,
+ ROUND_W = 0xec,
+
+ MOV_FMT = 0x01,
+ MOVF = 0x05,
+ ABS_FMT = 0x0d,
+ RSQRT1_FMT = 0x1d,
+ MOVT = 0x25,
+ NEG_FMT = 0x2d,
+ CVT_D = 0x4d,
+ RECIP1_FMT = 0x5d,
+ CVT_S = 0x6d
+};
+
+/* POOL32I encoding of minor opcode field (bits 25..21) */
+
+enum {
+ BLTZ = 0x00,
+ BLTZAL = 0x01,
+ BGEZ = 0x02,
+ BGEZAL = 0x03,
+ BLEZ = 0x04,
+ BNEZC = 0x05,
+ BGTZ = 0x06,
+ BEQZC = 0x07,
+ TLTI = 0x08,
+ TGEI = 0x09,
+ TLTIU = 0x0a,
+ TGEIU = 0x0b,
+ TNEI = 0x0c,
+ LUI = 0x0d,
+ TEQI = 0x0e,
+ SYNCI = 0x10,
+ BLTZALS = 0x11,
+ BGEZALS = 0x13,
+ BC2F = 0x14,
+ BC2T = 0x15,
+ BPOSGE64 = 0x1a,
+ BPOSGE32 = 0x1b,
+ /* These overlap and are distinguished by bit16 of the instruction */
+ BC1F = 0x1c,
+ BC1T = 0x1d,
+ BC1ANY2F = 0x1c,
+ BC1ANY2T = 0x1d,
+ BC1ANY4F = 0x1e,
+ BC1ANY4T = 0x1f
+};
+
+/* POOL16A encoding of minor opcode field */
+
+enum {
+ ADDU16 = 0x0,
+ SUBU16 = 0x1
+};
+
+/* POOL16B encoding of minor opcode field */
+
+enum {
+ SLL16 = 0x0,
+ SRL16 = 0x1
+};
+
+/* POOL16C encoding of minor opcode field */
+
+enum {
+ NOT16 = 0x00,
+ XOR16 = 0x04,
+ AND16 = 0x08,
+ OR16 = 0x0c,
+ LWM16 = 0x10,
+ SWM16 = 0x14,
+ JR16 = 0x18,
+ JRC16 = 0x1a,
+ JALR16 = 0x1c,
+ JALR16S = 0x1e,
+ MFHI16 = 0x20,
+ MFLO16 = 0x24,
+ BREAK16 = 0x28,
+ SDBBP16 = 0x2c,
+ JRADDIUSP = 0x30
+};
+
+/* POOL16D encoding of minor opcode field */
+
+enum {
+ ADDIUS5 = 0x0,
+ ADDIUSP = 0x1
+};
+
+/* POOL16E encoding of minor opcode field */
+
+enum {
+ ADDIUR2 = 0x0,
+ ADDIUR1SP = 0x1
+};
+
+static int mmreg (int r)
+{
+ static const int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 };
+
+ return map[r];
+}
+
+/* Used for 16-bit store instructions. */
+static int mmreg2 (int r)
+{
+ static const int map[] = { 0, 17, 2, 3, 4, 5, 6, 7 };
+
+ return map[r];
+}
+
+#define uMIPS_RD(op) ((op >> 7) & 0x7)
+#define uMIPS_RS(op) ((op >> 4) & 0x7)
+#define uMIPS_RS2(op) uMIPS_RS(op)
+#define uMIPS_RS1(op) ((op >> 1) & 0x7)
+#define uMIPS_RD5(op) ((op >> 5) & 0x1f)
+#define uMIPS_RS5(op) (op & 0x1f)
+
+/* Signed immediate */
+#define SIMM(op, start, width) \
+ ((int32_t)(((op >> start) & ((~0U) >> (32-width))) \
+ << (32-width)) \
+ >> (32-width))
+/* Zero-extended immediate */
+#define ZIMM(op, start, width) ((op >> start) & ((~0U) >> (32-width)))
+
+static void gen_addiur1sp (CPUState *env, DisasContext *ctx)
+{
+ int rd = mmreg(uMIPS_RD(ctx->opcode));
+
+ gen_arith_imm(env, ctx, OPC_ADDIU, rd, 29, ((ctx->opcode >> 1) & 0x3f) << 2);
+}
+
+static void gen_addiur2 (CPUState *env, DisasContext *ctx)
+{
+ static const int decoded_imm[] = { 1, 4, 8, 12, 16, 20, 24, -1 };
+ int rd = mmreg(uMIPS_RD(ctx->opcode));
+ int rs = mmreg(uMIPS_RS(ctx->opcode));
+
+ gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, decoded_imm[ZIMM(ctx->opcode, 1, 3)]);
+}
+
+static void gen_addiusp (CPUState *env, DisasContext *ctx)
+{
+ int encoded = ZIMM(ctx->opcode, 1, 9);
+ int decoded;
+
+ if (encoded <= 1) {
+ decoded = 256 + encoded;
+ } else if (encoded <= 255) {
+ decoded = encoded;
+ } else if (encoded <= 509) {
+ decoded = encoded - 512;
+ } else {
+ decoded = encoded - 768;
+ }
+
+ gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, decoded << 2);
+}
+
+static void gen_addius5 (CPUState *env, DisasContext *ctx)
+{
+ int imm = SIMM(ctx->opcode, 1, 4);
+ int rd = (ctx->opcode >> 5) & 0x1f;
+
+ gen_arith_imm(env, ctx, OPC_ADDIU, rd, rd, imm);
+}
+
+static void gen_andi16 (CPUState *env, DisasContext *ctx)
+{
+ static const int decoded_imm[] = { 128, 1, 2, 3, 4, 7, 8, 15, 16,
+ 31, 32, 63, 64, 255, 32768, 65535 };
+ int rd = mmreg(uMIPS_RD(ctx->opcode));
+ int rs = mmreg(uMIPS_RS(ctx->opcode));
+ int encoded = ZIMM(ctx->opcode, 0, 4);
+
+ gen_logic_imm(env, OPC_ANDI, rd, rs, decoded_imm[encoded]);
+}
+
+static void gen_ldst_multiple (DisasContext *ctx, uint32_t opc, int reglist,
+ int base, int16_t offset)
+{
+ TCGv t0, t1;
+ TCGv_i32 t2;
+
+ if (ctx->hflags & MIPS_HFLAG_BMASK) {
+ generate_exception(ctx, EXCP_RI);
+ return;
+ }
+
+ t0 = tcg_temp_new();
+
+ gen_base_offset_addr(ctx, t0, base, offset);
+
+ t1 = tcg_const_tl(reglist);
+ t2 = tcg_const_i32(ctx->mem_idx);
+
+ save_cpu_state(ctx, 1);
+ switch (opc) {
+ case LWM32:
+ gen_helper_lwm(t0, t1, t2);
+ break;
+ case SWM32:
+ gen_helper_swm(t0, t1, t2);
+ break;
+#ifdef TARGET_MIPS64
+ case LDM:
+ gen_helper_ldm(t0, t1, t2);
+ break;
+ case SDM:
+ gen_helper_sdm(t0, t1, t2);
+ break;
+#endif
+ }
+ MIPS_DEBUG("%s, %x, %d(%s)", opn, reglist, offset, regnames[base]);
+ tcg_temp_free(t0);
+ tcg_temp_free_i32(t1);
+ tcg_temp_free_i32(t2);
+}
+
+
+static void gen_pool16c_insn (CPUState *env, DisasContext *ctx, int *is_branch)
+{
+ int rd = mmreg((ctx->opcode >> 3) & 0x7);
+ int rs = mmreg(ctx->opcode & 0x7);
+ int opc;
+
+ switch (((ctx->opcode) >> 4) & 0x3f) {
+ case NOT16 + 0:
+ case NOT16 + 1:
+ case NOT16 + 2:
+ case NOT16 + 3:
+ gen_logic(env, OPC_NOR, rd, rs, 0);
+ break;
+ case XOR16 + 0:
+ case XOR16 + 1:
+ case XOR16 + 2:
+ case XOR16 + 3:
+ gen_logic(env, OPC_XOR, rd, rd, rs);
+ break;
+ case AND16 + 0:
+ case AND16 + 1:
+ case AND16 + 2:
+ case AND16 + 3:
+ gen_logic(env, OPC_AND, rd, rd, rs);
+ break;
+ case OR16 + 0:
+ case OR16 + 1:
+ case OR16 + 2:
+ case OR16 + 3:
+ gen_logic(env, OPC_OR, rd, rd, rs);
+ break;
+ case LWM16 + 0:
+ case LWM16 + 1:
+ case LWM16 + 2:
+ case LWM16 + 3:
+ {
+ static const int lwm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
+ int offset = ZIMM(ctx->opcode, 0, 4);
+
+ gen_ldst_multiple(ctx, LWM32, lwm_convert[(ctx->opcode >> 4) & 0x3],
+ 29, offset << 2);
+ }
+ break;
+ case SWM16 + 0:
+ case SWM16 + 1:
+ case SWM16 + 2:
+ case SWM16 + 3:
+ {
+ static const int swm_convert[] = { 0x11, 0x12, 0x13, 0x14 };
+ int offset = ZIMM(ctx->opcode, 0, 4);
+
+ gen_ldst_multiple(ctx, SWM32, swm_convert[(ctx->opcode >> 4) & 0x3],
+ 29, offset << 2);
+ }
+ break;
+ case JR16 + 0:
+ case JR16 + 1:
+ {
+ int reg = ctx->opcode & 0x1f;
+
+ gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
+ }
+ *is_branch = 1;
+ break;
+ case JRC16 + 0:
+ case JRC16 + 1:
+ {
+ int reg = ctx->opcode & 0x1f;
+
+ gen_compute_branch(ctx, OPC_JR, 2, reg, 0, 0);
+ /* Let normal delay slot handling in our caller take us
+ to the branch target. */
+ }
+ break;
+ case JALR16 + 0:
+ case JALR16 + 1:
+ opc = OPC_JALR;
+ goto do_jalr;
+ case JALR16S + 0:
+ case JALR16S + 1:
+ opc = OPC_JALRS;
+ do_jalr:
+ {
+ int reg = ctx->opcode & 0x1f;
+
+ gen_compute_branch(ctx, opc, 2, reg, 31, 0);
+ }
+ *is_branch = 1;
+ break;
+ case MFHI16 + 0:
+ case MFHI16 + 1:
+ gen_HILO(ctx, OPC_MFHI, uMIPS_RS5(ctx->opcode));
+ break;
+ case MFLO16 + 0:
+ case MFLO16 + 1:
+ gen_HILO(ctx, OPC_MFLO, uMIPS_RS5(ctx->opcode));
+ break;
+ case BREAK16:
+ generate_exception(ctx, EXCP_BREAK);
+ break;
+ case SDBBP16:
+ /* XXX: not clear which exception should be raised
+ * when in debug mode...
+ */
+ check_insn(env, ctx, ISA_MIPS32);
+ if (!(ctx->hflags & MIPS_HFLAG_DM)) {
+ generate_exception(ctx, EXCP_DBp);
+ } else {
+ generate_exception(ctx, EXCP_DBp);
+ }
+ break;
+ case JRADDIUSP + 0:
+ case JRADDIUSP + 1:
+ {
+ int imm = ZIMM(ctx->opcode, 0, 5);
+
+ gen_compute_branch(ctx, OPC_JR, 2, 31, 0, 0);
+ gen_arith_imm(env, ctx, OPC_ADDIU, 29, 29, imm << 2);
+ /* Let normal delay slot handling in our caller take us
+ to the branch target. */
+ }
+ break;
+ default:
+ generate_exception(ctx, EXCP_RI);
+ break;
+ }
+}
+
+static void gen_ldxs (DisasContext *ctx, int base, int index, int rd)
+{
+ TCGv t0 = tcg_temp_new();
+ TCGv t1 = tcg_temp_new();
+
+ gen_load_gpr(t0, base);
+
+ if (index != 0) {
+ gen_load_gpr(t1, index);
+ tcg_gen_shli_tl(t1, t1, 2);
+ gen_op_addr_add(ctx, t0, t1, t0);
+ }
+
+ save_cpu_state(ctx, 0);
+ op_ldst_lw(t1, t0, ctx);
+ gen_store_gpr(t1, rd);
+
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+}
+
+static void gen_ldst_pair (DisasContext *ctx, uint32_t opc, int rd,
+ int base, int16_t offset)
+{
+ const char *opn = "ldst_pair";
+ TCGv t0, t1;
+
+ if (ctx->hflags & MIPS_HFLAG_BMASK || rd == 31 || rd == base) {
+ generate_exception(ctx, EXCP_RI);
+ return;
+ }
+
+ t0 = tcg_temp_new();
+ t1 = tcg_temp_new();
+
+ gen_base_offset_addr(ctx, t0, base, offset);
+
+ switch (opc) {
+ case LWP:
+ save_cpu_state(ctx, 0);
+ op_ldst_lw(t1, t0, ctx);
+ gen_store_gpr(t1, rd);
+ tcg_gen_movi_tl(t1, 4);
+ gen_op_addr_add(ctx, t0, t0, t1);
+ op_ldst_lw(t1, t0, ctx);
+ gen_store_gpr(t1, rd+1);
+ opn = "lwp";
+ break;
+ case SWP:
+ save_cpu_state(ctx, 1);
+ gen_load_gpr(t1, rd);
+ op_ldst_sw(t1, t0, ctx);
+ tcg_gen_movi_tl(t1, 4);
+ gen_op_addr_add(ctx, t0, t0, t1);
+ gen_load_gpr(t1, rd+1);
+ op_ldst_sw(t1, t0, ctx);
+ opn = "swp";
+ break;
+#ifdef TARGET_MIPS64
+ case LDP:
+ save_cpu_state(ctx, 0);
+ op_ldst_ld(t1, t0, ctx);
+ gen_store_gpr(t1, rd);
+ tcg_gen_movi_tl(t1, 8);
+ gen_op_addr_add(ctx, t0, t0, t1);
+ op_ldst_ld(t1, t0, ctx);
+ gen_store_gpr(t1, rd+1);
+ opn = "ldp";
+ break;
+ case SDP:
+ save_cpu_state(ctx, 1);
+ gen_load_gpr(t1, rd);
+ op_ldst_sd(t1, t0, ctx);
+ tcg_gen_movi_tl(t1, 8);
+ gen_op_addr_add(ctx, t0, t0, t1);
+ gen_load_gpr(t1, rd+1);
+ op_ldst_sd(t1, t0, ctx);
+ opn = "sdp";
+ break;
+#endif
+ }
+ MIPS_DEBUG("%s, %s, %d(%s)", opn, regnames[rd], offset, regnames[base]);
+ tcg_temp_free(t0);
+ tcg_temp_free(t1);
+}
+
+static void gen_pool32axf (CPUState *env, DisasContext *ctx, int rt, int rs,
+ int *is_branch)
+{
+ int extension = (ctx->opcode >> 6) & 0x3f;
+ int minor = (ctx->opcode >> 12) & 0xf;
+ uint32_t mips32_op;
+
+ switch (extension) {
+ case TEQ:
+ mips32_op = OPC_TEQ;
+ goto do_trap;
+ case TGE:
+ mips32_op = OPC_TGE;
+ goto do_trap;
+ case TGEU:
+ mips32_op = OPC_TGEU;
+ goto do_trap;
+ case TLT:
+ mips32_op = OPC_TLT;
+ goto do_trap;
+ case TLTU:
+ mips32_op = OPC_TLTU;
+ goto do_trap;
+ case TNE:
+ mips32_op = OPC_TNE;
+ do_trap:
+ gen_trap(ctx, mips32_op, rs, rt, -1);
+ break;
+#ifndef CONFIG_USER_ONLY
+ case MFC0:
+ case MFC0 + 32:
+ if (rt == 0) {
+ /* Treat as NOP. */
+ break;
+ }
+ gen_mfc0(env, ctx, cpu_gpr[rt], rs, (ctx->opcode >> 11) & 0x7);
+ break;
+ case MTC0:
+ case MTC0 + 32:
+ {
+ TCGv t0 = tcg_temp_new();
+
+ gen_load_gpr(t0, rt);
+ gen_mtc0(env, ctx, t0, rs, (ctx->opcode >> 11) & 0x7);
+ tcg_temp_free(t0);
+ }
+ break;
+#endif
+ case 0x2c:
+ switch (minor) {
+ case SEB:
+ gen_bshfl(ctx, OPC_SEB, rs, rt);
+ break;
+ case SEH:
+ gen_bshfl(ctx, OPC_SEH, rs, rt);
+ break;
+ case CLO:
+ mips32_op = OPC_CLO;
+ goto do_cl;
+ case CLZ:
+ mips32_op = OPC_CLZ;
+ do_cl:
+ check_insn(env, ctx, ISA_MIPS32);
+ gen_cl(ctx, mips32_op, rt, rs);
+ break;
+ case RDHWR:
+ gen_rdhwr(env, ctx, rt, rs);
+ break;
+ case WSBH:
+ gen_bshfl(ctx, OPC_WSBH, rs, rt);
+ break;
+ case MULT:
+ mips32_op = OPC_MULT;
+ goto do_muldiv;
+ case MULTU:
+ mips32_op = OPC_MULTU;
+ goto do_muldiv;
+ case DIV:
+ mips32_op = OPC_DIV;
+ goto do_muldiv;
+ case DIVU:
+ mips32_op = OPC_DIVU;
+ goto do_muldiv;
+ case MADD:
+ mips32_op = OPC_MADD;
+ goto do_muldiv;
+ case MADDU:
+ mips32_op = OPC_MADDU;
+ goto do_muldiv;
+ case MSUB:
+ mips32_op = OPC_MSUB;
+ goto do_muldiv;
+ case MSUBU:
+ mips32_op = OPC_MSUBU;
+ do_muldiv:
+ check_insn(env, ctx, ISA_MIPS32);
+ gen_muldiv(ctx, mips32_op, rs, rt);
+ break;
+ default:
+ goto pool32axf_invalid;
+ }
+ break;
+ case 0x34:
+ switch (minor) {
+ case MFC2:
+ case MTC2:
+ case MFHC2:
+ case MTHC2:
+ case CFC2:
+ case CTC2:
+ generate_exception_err(ctx, EXCP_CpU, 2);
+ break;
+ default:
+ goto pool32axf_invalid;
+ }
+ break;
+ case 0x3c:
+ switch (minor) {
+ case JALR:
+ case JALR_HB:
+ gen_compute_branch (ctx, OPC_JALR, 4, rs, rt, 0);
+ *is_branch = 1;
+ break;
+ case JALRS:
+ case JALRS_HB:
+ gen_compute_branch (ctx, OPC_JALRS, 4, rs, rt, 0);
+ *is_branch = 1;
+ break;
+ default:
+ goto pool32axf_invalid;
+ }
+ break;
+ case 0x05:
+ switch (minor) {
+ case RDPGPR:
+ check_insn(env, ctx, ISA_MIPS32R2);
+ gen_load_srsgpr(rt, rs);
+ break;
+ case WRPGPR:
+ check_insn(env, ctx, ISA_MIPS32R2);
+ gen_store_srsgpr(rt, rs);
+ break;
+ default:
+ goto pool32axf_invalid;
+ }
+ break;
+#ifndef CONFIG_USER_ONLY
+ case 0x0d:
+ switch (minor) {
+ case TLBP:
+ mips32_op = OPC_TLBP;
+ goto do_cp0;
+ case TLBR:
+ mips32_op = OPC_TLBR;
+ goto do_cp0;
+ case TLBWI:
+ mips32_op = OPC_TLBWI;
+ goto do_cp0;
+ case TLBWR:
+ mips32_op = OPC_TLBWR;
+ goto do_cp0;
+ case WAIT:
+ mips32_op = OPC_WAIT;
+ goto do_cp0;
+ case DERET:
+ mips32_op = OPC_DERET;
+ goto do_cp0;
+ case ERET:
+ mips32_op = OPC_ERET;
+ do_cp0:
+ gen_cp0(env, ctx, mips32_op, rt, rs);
+ break;
+ default:
+ goto pool32axf_invalid;
+ }
+ break;
+ case 0x1d:
+ switch (minor) {
+ case DI:
+ {
+ TCGv t0 = tcg_temp_new();
+
+ save_cpu_state(ctx, 1);
+ gen_helper_di(t0);
+ gen_store_gpr(t0, rs);
+ /* Stop translation as we may have switched the execution mode */
+ ctx->bstate = BS_STOP;
+ tcg_temp_free(t0);
+ }
+ break;
+ case EI:
+ {
+ TCGv t0 = tcg_temp_new();
+
+ save_cpu_state(ctx, 1);
+ gen_helper_ei(t0);
+ gen_store_gpr(t0, rs);
+ /* Stop translation as we may have switched the execution mode */
+ ctx->bstate = BS_STOP;
+ tcg_temp_free(t0);
+ }
+ break;
+ default:
+ goto pool32axf_invalid;
+ }
+ break;
+#endif
+ case 0x2d:
+ switch (minor) {
+ case SYNC:
+ /* NOP */
+ break;
+ case SYSCALL:
+ generate_exception(ctx, EXCP_SYSCALL);
+ ctx->bstate = BS_STOP;
+ break;
+ case SDBBP:
+ check_insn(env, ctx, ISA_MIPS32);
+ if (!(ctx->hflags & MIPS_HFLAG_DM)) {
+ generate_exception(ctx, EXCP_DBp);
+ } else {
+ generate_exception(ctx, EXCP_DBp);
+ }
+ break;
+ default:
+ goto pool32axf_invalid;
+ }
+ break;
+ case 0x35:
+ switch (minor) {
+ case MFHI32:
+ gen_HILO(ctx, OPC_MFHI, rs);
+ break;
+ case MFLO32:
+ gen_HILO(ctx, OPC_MFLO, rs);
+ break;
+ case MTHI32:
+ gen_HILO(ctx, OPC_MTHI, rs);
+ break;
+ case MTLO32:
+ gen_HILO(ctx, OPC_MTLO, rs);
+ break;
+ default:
+ goto pool32axf_invalid;
+ }
+ break;
+ default:
+ pool32axf_invalid:
+ MIPS_INVAL("pool32axf");
+ generate_exception(ctx, EXCP_RI);
+ break;
+ }
+}
+
+/* Values for microMIPS fmt field. Variable-width, depending on which
+ formats the instruction supports. */
+
+enum {
+ FMT_SD_S = 0,
+ FMT_SD_D = 1,
+
+ FMT_SDPS_S = 0,
+ FMT_SDPS_D = 1,
+ FMT_SDPS_PS = 2,
+
+ FMT_SWL_S = 0,
+ FMT_SWL_W = 1,
+ FMT_SWL_L = 2,
+
+ FMT_DWL_D = 0,
+ FMT_DWL_W = 1,
+ FMT_DWL_L = 2
+};
+
+static void gen_pool32fxf (CPUState *env, DisasContext *ctx, int rt, int rs)
+{
+ int extension = (ctx->opcode >> 6) & 0x3ff;
+ uint32_t mips32_op;
+
+#define FLOAT_1BIT_FMT(opc, fmt) (fmt << 8) | opc
+#define FLOAT_2BIT_FMT(opc, fmt) (fmt << 7) | opc
+#define COND_FLOAT_MOV(opc, cond) (cond << 7) | opc
+
+ switch (extension) {
+ case FLOAT_1BIT_FMT(CFC1, 0):
+ mips32_op = OPC_CFC1;
+ goto do_cp1;
+ case FLOAT_1BIT_FMT(CTC1, 0):
+ mips32_op = OPC_CTC1;
+ goto do_cp1;
+ case FLOAT_1BIT_FMT(MFC1, 0):
+ mips32_op = OPC_MFC1;
+ goto do_cp1;
+ case FLOAT_1BIT_FMT(MTC1, 0):
+ mips32_op = OPC_MTC1;
+ goto do_cp1;
+ case FLOAT_1BIT_FMT(MFHC1, 0):
+ mips32_op = OPC_MFHC1;
+ goto do_cp1;
+ case FLOAT_1BIT_FMT(MTHC1, 0):
+ mips32_op = OPC_MTHC1;
+ do_cp1:
+ gen_cp1(ctx, mips32_op, rt, rs);
+ break;
+
+ /* Reciprocal square root */
+ case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_S):
+ mips32_op = OPC_RSQRT_S;
+ goto do_unaryfp;
+ case FLOAT_1BIT_FMT(RSQRT_FMT, FMT_SD_D):
+ mips32_op = OPC_RSQRT_D;
+ goto do_unaryfp;
+
+ /* Square root */
+ case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_S):
+ mips32_op = OPC_SQRT_S;
+ goto do_unaryfp;
+ case FLOAT_1BIT_FMT(SQRT_FMT, FMT_SD_D):
+ mips32_op = OPC_SQRT_D;
+ goto do_unaryfp;
+
+ /* Reciprocal */
+ case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_S):
+ mips32_op = OPC_RECIP_S;
+ goto do_unaryfp;
+ case FLOAT_1BIT_FMT(RECIP_FMT, FMT_SD_D):
+ mips32_op = OPC_RECIP_D;
+ goto do_unaryfp;
+
+ /* Floor */
+ case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_S):
+ mips32_op = OPC_FLOOR_L_S;
+ goto do_unaryfp;
+ case FLOAT_1BIT_FMT(FLOOR_L, FMT_SD_D):
+ mips32_op = OPC_FLOOR_L_D;
+ goto do_unaryfp;
+ case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_S):
+ mips32_op = OPC_FLOOR_W_S;
+ goto do_unaryfp;
+ case FLOAT_1BIT_FMT(FLOOR_W, FMT_SD_D):
+ mips32_op = OPC_FLOOR_W_D;
+ goto do_unaryfp;
+
+ /* Ceiling */
+ case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_S):
+ mips32_op = OPC_CEIL_L_S;
+ goto do_unaryfp;
+ case FLOAT_1BIT_FMT(CEIL_L, FMT_SD_D):
+ mips32_op = OPC_CEIL_L_D;
+ goto do_unaryfp;
+ case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_S):
+ mips32_op = OPC_CEIL_W_S;
+ goto do_unaryfp;
+ case FLOAT_1BIT_FMT(CEIL_W, FMT_SD_D):
+ mips32_op = OPC_CEIL_W_D;
+ goto do_unaryfp;
+
+ /* Truncation */
+ case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_S):
+ mips32_op = OPC_TRUNC_L_S;
+ goto do_unaryfp;
+ case FLOAT_1BIT_FMT(TRUNC_L, FMT_SD_D):
+ mips32_op = OPC_TRUNC_L_D;
+ goto do_unaryfp;
+ case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_S):
+ mips32_op = OPC_TRUNC_W_S;
+ goto do_unaryfp;
+ case FLOAT_1BIT_FMT(TRUNC_W, FMT_SD_D):
+ mips32_op = OPC_TRUNC_W_D;
+ goto do_unaryfp;
+
+ /* Round */
+ case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_S):
+ mips32_op = OPC_ROUND_L_S;
+ goto do_unaryfp;
+ case FLOAT_1BIT_FMT(ROUND_L, FMT_SD_D):
+ mips32_op = OPC_ROUND_L_D;
+ goto do_unaryfp;
+ case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_S):
+ mips32_op = OPC_ROUND_W_S;
+ goto do_unaryfp;
+ case FLOAT_1BIT_FMT(ROUND_W, FMT_SD_D):
+ mips32_op = OPC_ROUND_W_D;
+ goto do_unaryfp;
+
+ /* Integer to floating-point conversion */
+ case FLOAT_1BIT_FMT(CVT_L, FMT_SD_S):
+ mips32_op = OPC_CVT_L_S;
+ goto do_unaryfp;
+ case FLOAT_1BIT_FMT(CVT_L, FMT_SD_D):
+ mips32_op = OPC_CVT_L_D;
+ goto do_unaryfp;
+ case FLOAT_1BIT_FMT(CVT_W, FMT_SD_S):
+ mips32_op = OPC_CVT_W_S;
+ goto do_unaryfp;
+ case FLOAT_1BIT_FMT(CVT_W, FMT_SD_D):
+ mips32_op = OPC_CVT_W_D;
+ goto do_unaryfp;
+
+ /* Paired-foo conversions */
+ case FLOAT_1BIT_FMT(CVT_S_PL, 0):
+ mips32_op = OPC_CVT_S_PL;
+ goto do_unaryfp;
+ case FLOAT_1BIT_FMT(CVT_S_PU, 0):
+ mips32_op = OPC_CVT_S_PU;
+ goto do_unaryfp;
+ case FLOAT_1BIT_FMT(CVT_PW_PS, 0):
+ mips32_op = OPC_CVT_PW_PS;
+ goto do_unaryfp;
+ case FLOAT_1BIT_FMT(CVT_PS_PW, 0):
+ mips32_op = OPC_CVT_PS_PW;
+ goto do_unaryfp;
+
+ /* Floating-point moves */
+ case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_S):
+ mips32_op = OPC_MOV_S;
+ goto do_unaryfp;
+ case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_D):
+ mips32_op = OPC_MOV_D;
+ goto do_unaryfp;
+ case FLOAT_2BIT_FMT(MOV_FMT, FMT_SDPS_PS):
+ mips32_op = OPC_MOV_PS;
+ goto do_unaryfp;
+
+ /* Absolute value */
+ case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_S):
+ mips32_op = OPC_ABS_S;
+ goto do_unaryfp;
+ case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_D):
+ mips32_op = OPC_ABS_D;
+ goto do_unaryfp;
+ case FLOAT_2BIT_FMT(ABS_FMT, FMT_SDPS_PS):
+ mips32_op = OPC_ABS_PS;
+ goto do_unaryfp;
+
+ /* Negation */
+ case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_S):
+ mips32_op = OPC_NEG_S;
+ goto do_unaryfp;
+ case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_D):
+ mips32_op = OPC_NEG_D;
+ goto do_unaryfp;
+ case FLOAT_2BIT_FMT(NEG_FMT, FMT_SDPS_PS):
+ mips32_op = OPC_NEG_PS;
+ goto do_unaryfp;
+
+ /* Reciprocal square root step */
+ case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_S):
+ mips32_op = OPC_RSQRT1_S;
+ goto do_unaryfp;
+ case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_D):
+ mips32_op = OPC_RSQRT1_D;
+ goto do_unaryfp;
+ case FLOAT_2BIT_FMT(RSQRT1_FMT, FMT_SDPS_PS):
+ mips32_op = OPC_RSQRT1_PS;
+ goto do_unaryfp;
+
+ /* Reciprocal step */
+ case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_S):
+ mips32_op = OPC_RECIP1_S;
+ goto do_unaryfp;
+ case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_D):
+ mips32_op = OPC_RECIP1_S;
+ goto do_unaryfp;
+ case FLOAT_2BIT_FMT(RECIP1_FMT, FMT_SDPS_PS):
+ mips32_op = OPC_RECIP1_PS;
+ goto do_unaryfp;
+
+ /* Conversions from double */
+ case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_S):
+ mips32_op = OPC_CVT_D_S;
+ goto do_unaryfp;
+ case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_W):
+ mips32_op = OPC_CVT_D_W;
+ goto do_unaryfp;
+ case FLOAT_2BIT_FMT(CVT_D, FMT_SWL_L):
+ mips32_op = OPC_CVT_D_L;
+ goto do_unaryfp;
+
+ /* Conversions from single */
+ case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_D):
+ mips32_op = OPC_CVT_S_D;
+ goto do_unaryfp;
+ case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_W):
+ mips32_op = OPC_CVT_S_W;
+ goto do_unaryfp;
+ case FLOAT_2BIT_FMT(CVT_S, FMT_DWL_L):
+ mips32_op = OPC_CVT_S_L;
+ do_unaryfp:
+ gen_farith(ctx, mips32_op, -1, rs, rt, 0);
+ break;
+
+ /* Conditional moves on floating-point codes */
+ case COND_FLOAT_MOV(MOVT, 0):
+ case COND_FLOAT_MOV(MOVT, 1):
+ case COND_FLOAT_MOV(MOVT, 2):
+ case COND_FLOAT_MOV(MOVT, 3):
+ case COND_FLOAT_MOV(MOVT, 4):
+ case COND_FLOAT_MOV(MOVT, 5):
+ case COND_FLOAT_MOV(MOVT, 6):
+ case COND_FLOAT_MOV(MOVT, 7):
+ gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 1);
+ break;
+ case COND_FLOAT_MOV(MOVF, 0):
+ case COND_FLOAT_MOV(MOVF, 1):
+ case COND_FLOAT_MOV(MOVF, 2):
+ case COND_FLOAT_MOV(MOVF, 3):
+ case COND_FLOAT_MOV(MOVF, 4):
+ case COND_FLOAT_MOV(MOVF, 5):
+ case COND_FLOAT_MOV(MOVF, 6):
+ case COND_FLOAT_MOV(MOVF, 7):
+ gen_movci(ctx, rt, rs, (ctx->opcode >> 13) & 0x7, 0);
+ break;
+ default:
+ MIPS_INVAL("pool32fxf");
+ generate_exception(ctx, EXCP_RI);
+ break;
+ }
+}
+
+static void decode_micromips32_opc (CPUState *env, DisasContext *ctx,
+ uint16_t insn_hw1, int *is_branch)
+{
+ int32_t offset;
+ uint16_t insn;
+ int rt, rs, rd, rr;
+ int16_t imm;
+ uint32_t op, minor, mips32_op;
+ uint32_t cond, fmt, cc;
+
+ insn = lduw_code(ctx->pc + 2);
+ ctx->opcode = (ctx->opcode << 16) | insn;
+
+ rt = (ctx->opcode >> 21) & 0x1f;
+ rs = (ctx->opcode >> 16) & 0x1f;
+ rd = (ctx->opcode >> 11) & 0x1f;
+ rr = (ctx->opcode >> 6) & 0x1f;
+ imm = (int16_t) ctx->opcode;
+
+ op = (ctx->opcode >> 26) & 0x3f;
+ switch (op) {
+ case POOL32A:
+ minor = ctx->opcode & 0x3f;
+ switch (minor) {
+ case 0x00:
+ minor = (ctx->opcode >> 6) & 0xf;
+ switch (minor) {
+ case SLL32:
+ mips32_op = OPC_SLL;
+ goto do_shifti;
+ case SRA:
+ mips32_op = OPC_SRA;
+ goto do_shifti;
+ case SRL32:
+ mips32_op = OPC_SRL;
+ goto do_shifti;
+ case ROTR:
+ mips32_op = OPC_ROTR;
+ do_shifti:
+ gen_shift_imm(env, ctx, mips32_op, rt, rs, rd);
+ break;
+ default:
+ goto pool32a_invalid;
+ }
+ break;
+ case 0x10:
+ minor = (ctx->opcode >> 6) & 0xf;
+ switch (minor) {
+ /* Arithmetic */
+ case ADD:
+ mips32_op = OPC_ADD;
+ goto do_arith;
+ case ADDU32:
+ mips32_op = OPC_ADDU;
+ goto do_arith;
+ case SUB:
+ mips32_op = OPC_SUB;
+ goto do_arith;
+ case SUBU32:
+ mips32_op = OPC_SUBU;
+ goto do_arith;
+ case MUL:
+ mips32_op = OPC_MUL;
+ do_arith:
+ gen_arith(env, ctx, mips32_op, rd, rs, rt);
+ break;
+ /* Shifts */
+ case SLLV:
+ mips32_op = OPC_SLLV;
+ goto do_shift;
+ case SRLV:
+ mips32_op = OPC_SRLV;
+ goto do_shift;
+ case SRAV:
+ mips32_op = OPC_SRAV;
+ goto do_shift;
+ case ROTRV:
+ mips32_op = OPC_ROTRV;
+ do_shift:
+ gen_shift(env, ctx, mips32_op, rd, rs, rt);
+ break;
+ /* Logical operations */
+ case AND:
+ mips32_op = OPC_AND;
+ goto do_logic;
+ case OR32:
+ mips32_op = OPC_OR;
+ goto do_logic;
+ case NOR:
+ mips32_op = OPC_NOR;
+ goto do_logic;
+ case XOR32:
+ mips32_op = OPC_XOR;
+ do_logic:
+ gen_logic(env, mips32_op, rd, rs, rt);
+ break;
+ /* Set less than */
+ case SLT:
+ mips32_op = OPC_SLT;
+ goto do_slt;
+ case SLTU:
+ mips32_op = OPC_SLTU;
+ do_slt:
+ gen_slt(env, mips32_op, rd, rs, rt);
+ break;
+ default:
+ goto pool32a_invalid;
+ }
+ break;
+ case 0x18:
+ minor = (ctx->opcode >> 6) & 0xf;
+ switch (minor) {
+ /* Conditional moves */
+ case MOVN:
+ mips32_op = OPC_MOVN;
+ goto do_cmov;
+ case MOVZ:
+ mips32_op = OPC_MOVZ;
+ do_cmov:
+ gen_cond_move(env, mips32_op, rd, rs, rt);
+ break;
+ case LWXS:
+ gen_ldxs(ctx, rs, rt, rd);
+ break;
+ default:
+ goto pool32a_invalid;
+ }
+ break;
+ case INS:
+ gen_bitops(ctx, OPC_INS, rt, rs, rr, rd);
+ return;
+ case EXT:
+ gen_bitops(ctx, OPC_EXT, rt, rs, rr, rd);
+ return;
+ case POOL32AXF:
+ gen_pool32axf(env, ctx, rt, rs, is_branch);
+ break;
+ case 0x07:
+ generate_exception(ctx, EXCP_BREAK);
+ break;
+ default:
+ pool32a_invalid:
+ MIPS_INVAL("pool32a");
+ generate_exception(ctx, EXCP_RI);
+ break;
+ }
+ break;
+ case POOL32B:
+ minor = (ctx->opcode >> 12) & 0xf;
+ switch (minor) {
+ case CACHE:
+ /* Treat as no-op. */
+ break;
+ case LWC2:
+ case SWC2:
+ /* COP2: Not implemented. */
+ generate_exception_err(ctx, EXCP_CpU, 2);
+ break;
+ case LWP:
+ case SWP:
+#ifdef TARGET_MIPS64
+ case LDP:
+ case SDP:
+#endif
+ gen_ldst_pair(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
+ break;
+ case LWM32:
+ case SWM32:
+#ifdef TARGET_MIPS64
+ case LDM:
+ case SDM:
+#endif
+ gen_ldst_multiple(ctx, minor, rt, rs, SIMM(ctx->opcode, 0, 12));
+ break;
+ default:
+ MIPS_INVAL("pool32b");
+ generate_exception(ctx, EXCP_RI);
+ break;
+ }
+ break;
+ case POOL32F:
+ if (env->CP0_Config1 & (1 << CP0C1_FP)) {
+ minor = ctx->opcode & 0x3f;
+ check_cp1_enabled(ctx);
+ switch (minor) {
+ case ALNV_PS:
+ mips32_op = OPC_ALNV_PS;
+ goto do_madd;
+ case MADD_S:
+ mips32_op = OPC_MADD_S;
+ goto do_madd;
+ case MADD_D:
+ mips32_op = OPC_MADD_D;
+ goto do_madd;
+ case MADD_PS:
+ mips32_op = OPC_MADD_PS;
+ goto do_madd;
+ case MSUB_S:
+ mips32_op = OPC_MSUB_S;
+ goto do_madd;
+ case MSUB_D:
+ mips32_op = OPC_MSUB_D;
+ goto do_madd;
+ case MSUB_PS:
+ mips32_op = OPC_MSUB_PS;
+ goto do_madd;
+ case NMADD_S:
+ mips32_op = OPC_NMADD_S;
+ goto do_madd;
+ case NMADD_D:
+ mips32_op = OPC_NMADD_D;
+ goto do_madd;
+ case NMADD_PS:
+ mips32_op = OPC_NMADD_PS;
+ goto do_madd;
+ case NMSUB_S:
+ mips32_op = OPC_NMSUB_S;
+ goto do_madd;
+ case NMSUB_D:
+ mips32_op = OPC_NMSUB_D;
+ goto do_madd;
+ case NMSUB_PS:
+ mips32_op = OPC_NMSUB_PS;
+ do_madd:
+ gen_flt3_arith(ctx, mips32_op, rd, rr, rs, rt);
+ break;
+ case CABS_COND_FMT:
+ cond = (ctx->opcode >> 6) & 0xf;
+ cc = (ctx->opcode >> 13) & 0x7;
+ fmt = (ctx->opcode >> 10) & 0x3;
+ switch (fmt) {
+ case 0x0:
+ gen_cmpabs_s(ctx, cond, rt, rs, cc);
+ break;
+ case 0x1:
+ gen_cmpabs_d(ctx, cond, rt, rs, cc);
+ break;
+ case 0x2:
+ gen_cmpabs_ps(ctx, cond, rt, rs, cc);
+ break;
+ default:
+ goto pool32f_invalid;
+ }
+ break;
+ case C_COND_FMT:
+ cond = (ctx->opcode >> 6) & 0xf;
+ cc = (ctx->opcode >> 13) & 0x7;
+ fmt = (ctx->opcode >> 10) & 0x3;
+ switch (fmt) {
+ case 0x0:
+ gen_cmp_s(ctx, cond, rt, rs, cc);
+ break;
+ case 0x1:
+ gen_cmp_d(ctx, cond, rt, rs, cc);
+ break;
+ case 0x2:
+ gen_cmp_ps(ctx, cond, rt, rs, cc);
+ break;
+ default:
+ goto pool32f_invalid;
+ }
+ break;
+ case POOL32FXF:
+ gen_pool32fxf(env, ctx, rt, rs);
+ break;
+ case 0x00:
+ /* PLL foo */
+ switch ((ctx->opcode >> 6) & 0x7) {
+ case PLL_PS:
+ mips32_op = OPC_PLL_PS;
+ goto do_ps;
+ case PLU_PS:
+ mips32_op = OPC_PLU_PS;
+ goto do_ps;
+ case PUL_PS:
+ mips32_op = OPC_PUL_PS;
+ goto do_ps;
+ case PUU_PS:
+ mips32_op = OPC_PUU_PS;
+ goto do_ps;
+ case CVT_PS_S:
+ mips32_op = OPC_CVT_PS_S;
+ do_ps:
+ gen_farith(ctx, mips32_op, rt, rs, rd, 0);
+ break;
+ default:
+ goto pool32f_invalid;
+ }
+ break;
+ case 0x08:
+ /* [LS][WDU]XC1 */
+ switch ((ctx->opcode >> 6) & 0x7) {
+ case LWXC1:
+ mips32_op = OPC_LWXC1;
+ goto do_ldst_cp1;
+ case SWXC1:
+ mips32_op = OPC_SWXC1;
+ goto do_ldst_cp1;
+ case LDXC1:
+ mips32_op = OPC_LDXC1;
+ goto do_ldst_cp1;
+ case SDXC1:
+ mips32_op = OPC_SDXC1;
+ goto do_ldst_cp1;
+ case LUXC1:
+ mips32_op = OPC_LUXC1;
+ goto do_ldst_cp1;
+ case SUXC1:
+ mips32_op = OPC_SUXC1;
+ do_ldst_cp1:
+ gen_flt3_ldst(ctx, mips32_op, rd, rd, rt, rs);
+ break;
+ default:
+ goto pool32f_invalid;
+ }
+ break;
+ case 0x18:
+ /* 3D insns */
+ fmt = (ctx->opcode >> 9) & 0x3;
+ switch ((ctx->opcode >> 6) & 0x7) {
+ case RSQRT2_FMT:
+ switch (fmt) {
+ case FMT_SDPS_S:
+ mips32_op = OPC_RSQRT2_S;
+ goto do_3d;
+ case FMT_SDPS_D:
+ mips32_op = OPC_RSQRT2_D;
+ goto do_3d;
+ case FMT_SDPS_PS:
+ mips32_op = OPC_RSQRT2_PS;
+ goto do_3d;
+ default:
+ goto pool32f_invalid;
+ }
+ break;
+ case RECIP2_FMT:
+ switch (fmt) {
+ case FMT_SDPS_S:
+ mips32_op = OPC_RECIP2_S;
+ goto do_3d;
+ case FMT_SDPS_D:
+ mips32_op = OPC_RECIP2_D;
+ goto do_3d;
+ case FMT_SDPS_PS:
+ mips32_op = OPC_RECIP2_PS;
+ goto do_3d;
+ default:
+ goto pool32f_invalid;
+ }
+ break;
+ case ADDR_PS:
+ mips32_op = OPC_ADDR_PS;
+ goto do_3d;
+ case MULR_PS:
+ mips32_op = OPC_MULR_PS;
+ do_3d:
+ gen_farith(ctx, mips32_op, rt, rs, rd, 0);
+ break;
+ default:
+ goto pool32f_invalid;
+ }
+ break;
+ case 0x20:
+ /* MOV[FT].fmt and PREFX */
+ cc = (ctx->opcode >> 13) & 0x7;
+ fmt = (ctx->opcode >> 9) & 0x3;
+ switch ((ctx->opcode >> 6) & 0x7) {
+ case MOVF_FMT:
+ switch (fmt) {
+ case FMT_SDPS_S:
+ gen_movcf_s(rs, rt, cc, 0);
+ break;
+ case FMT_SDPS_D:
+ gen_movcf_d(ctx, rs, rt, cc, 0);
+ break;
+ case FMT_SDPS_PS:
+ gen_movcf_ps(rs, rt, cc, 0);
+ break;
+ default:
+ goto pool32f_invalid;
+ }
+ break;
+ case MOVT_FMT:
+ switch (fmt) {
+ case FMT_SDPS_S:
+ gen_movcf_s(rs, rt, cc, 1);
+ break;
+ case FMT_SDPS_D:
+ gen_movcf_d(ctx, rs, rt, cc, 1);
+ break;
+ case FMT_SDPS_PS:
+ gen_movcf_ps(rs, rt, cc, 1);
+ break;
+ default:
+ goto pool32f_invalid;
+ }
+ break;
+ case PREFX:
+ break;
+ default:
+ goto pool32f_invalid;
+ }
+ break;
+#define FINSN_3ARG_SDPS(prfx) \
+ switch ((ctx->opcode >> 8) & 0x3) { \
+ case FMT_SDPS_S: \
+ mips32_op = OPC_##prfx##_S; \
+ goto do_fpop; \
+ case FMT_SDPS_D: \
+ mips32_op = OPC_##prfx##_D; \
+ goto do_fpop; \
+ case FMT_SDPS_PS: \
+ mips32_op = OPC_##prfx##_PS; \
+ goto do_fpop; \
+ default: \
+ goto pool32f_invalid; \
+ }
+ case 0x30:
+ /* regular FP ops */
+ switch ((ctx->opcode >> 6) & 0x3) {
+ case ADD_FMT:
+ FINSN_3ARG_SDPS(ADD);
+ break;
+ case SUB_FMT:
+ FINSN_3ARG_SDPS(SUB);
+ break;
+ case MUL_FMT:
+ FINSN_3ARG_SDPS(MUL);
+ break;
+ case DIV_FMT:
+ fmt = (ctx->opcode >> 8) & 0x3;
+ if (fmt == 1) {
+ mips32_op = OPC_DIV_D;
+ } else if (fmt == 0) {
+ mips32_op = OPC_DIV_S;
+ } else {
+ goto pool32f_invalid;
+ }
+ goto do_fpop;
+ default:
+ goto pool32f_invalid;
+ }
+ break;
+ case 0x38:
+ /* cmovs */
+ switch ((ctx->opcode >> 6) & 0x3) {
+ case MOVN_FMT:
+ FINSN_3ARG_SDPS(MOVN);
+ break;
+ case MOVZ_FMT:
+ FINSN_3ARG_SDPS(MOVZ);
+ break;
+ default:
+ goto pool32f_invalid;
+ }
+ break;
+ do_fpop:
+ gen_farith(ctx, mips32_op, rt, rs, rd, 0);
+ break;
+ default:
+ pool32f_invalid:
+ MIPS_INVAL("pool32f");
+ generate_exception(ctx, EXCP_RI);
+ break;
+ }
+ } else {
+ generate_exception_err(ctx, EXCP_CpU, 1);
+ }
+ break;
+ case POOL32I:
+ minor = (ctx->opcode >> 21) & 0x1f;
+ switch (minor) {
+ case BLTZ:
+ mips32_op = OPC_BLTZ;
+ goto do_branch;
+ case BLTZAL:
+ mips32_op = OPC_BLTZAL;
+ goto do_branch;
+ case BLTZALS:
+ mips32_op = OPC_BLTZALS;
+ goto do_branch;
+ case BGEZ:
+ mips32_op = OPC_BGEZ;
+ goto do_branch;
+ case BGEZAL:
+ mips32_op = OPC_BGEZAL;
+ goto do_branch;
+ case BGEZALS:
+ mips32_op = OPC_BGEZALS;
+ goto do_branch;
+ case BLEZ:
+ mips32_op = OPC_BLEZ;
+ goto do_branch;
+ case BGTZ:
+ mips32_op = OPC_BGTZ;
+ do_branch:
+ gen_compute_branch(ctx, mips32_op, 4, rs, -1, imm << 1);
+ *is_branch = 1;
+ break;
+
+ /* Traps */
+ case TLTI:
+ mips32_op = OPC_TLTI;
+ goto do_trapi;
+ case TGEI:
+ mips32_op = OPC_TGEI;
+ goto do_trapi;
+ case TLTIU:
+ mips32_op = OPC_TLTIU;
+ goto do_trapi;
+ case TGEIU:
+ mips32_op = OPC_TGEIU;
+ goto do_trapi;
+ case TNEI:
+ mips32_op = OPC_TNEI;
+ goto do_trapi;
+ case TEQI:
+ mips32_op = OPC_TEQI;
+ do_trapi:
+ gen_trap(ctx, mips32_op, rs, -1, imm);
+ break;
+
+ case BNEZC:
+ case BEQZC:
+ gen_compute_branch(ctx, minor == BNEZC ? OPC_BNE : OPC_BEQ,
+ 4, rs, 0, imm << 1);
+ /* Compact branches don't have a delay slot, so just let
+ the normal delay slot handling take us to the branch
+ target. */
+ break;
+ case LUI:
+ gen_logic_imm(env, OPC_LUI, rs, -1, imm);
+ break;
+ case SYNCI:
+ break;
+ case BC2F:
+ case BC2T:
+ /* COP2: Not implemented. */
+ generate_exception_err(ctx, EXCP_CpU, 2);
+ break;
+ case BC1F:
+ mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1FANY2 : OPC_BC1F;
+ goto do_cp1branch;
+ case BC1T:
+ mips32_op = (ctx->opcode & (1 << 16)) ? OPC_BC1TANY2 : OPC_BC1T;
+ goto do_cp1branch;
+ case BC1ANY4F:
+ mips32_op = OPC_BC1FANY4;
+ goto do_cp1mips3d;
+ case BC1ANY4T:
+ mips32_op = OPC_BC1TANY4;
+ do_cp1mips3d:
+ check_cop1x(ctx);
+ check_insn(env, ctx, ASE_MIPS3D);
+ /* Fall through */
+ do_cp1branch:
+ gen_compute_branch1(env, ctx, mips32_op,
+ (ctx->opcode >> 18) & 0x7, imm << 1);
+ *is_branch = 1;
+ break;
+ case BPOSGE64:
+ case BPOSGE32:
+ /* MIPS DSP: not implemented */
+ /* Fall through */
+ default:
+ MIPS_INVAL("pool32i");
+ generate_exception(ctx, EXCP_RI);
+ break;
+ }
+ break;
+ case POOL32C:
+ minor = (ctx->opcode >> 12) & 0xf;
+ switch (minor) {
+ case LWL:
+ mips32_op = OPC_LWL;
+ goto do_ldst_lr;
+ case SWL:
+ mips32_op = OPC_SWL;
+ goto do_ldst_lr;
+ case LWR:
+ mips32_op = OPC_LWR;
+ goto do_ldst_lr;
+ case SWR:
+ mips32_op = OPC_SWR;
+ goto do_ldst_lr;
+#if defined(TARGET_MIPS64)
+ case LDL:
+ mips32_op = OPC_LDL;
+ goto do_ldst_lr;
+ case SDL:
+ mips32_op = OPC_SDL;
+ goto do_ldst_lr;
+ case LDR:
+ mips32_op = OPC_LDR;
+ goto do_ldst_lr;
+ case SDR:
+ mips32_op = OPC_SDR;
+ goto do_ldst_lr;
+ case LWU:
+ mips32_op = OPC_LWU;
+ goto do_ldst_lr;
+ case LLD:
+ mips32_op = OPC_LLD;
+ goto do_ldst_lr;
+#endif
+ case LL:
+ mips32_op = OPC_LL;
+ do_ldst_lr:
+ gen_ldst(ctx, mips32_op, rt, rs, SIMM(ctx->opcode, 0, 12));
+ break;
+ case SC:
+ gen_st_cond(ctx, OPC_SC, rt, rs, SIMM(ctx->opcode, 0, 12));
+ break;
+#if defined(TARGET_MIPS64)
+ case SCD:
+ gen_st_cond(ctx, OPC_SCD, rt, rs, SIMM(ctx->opcode, 0, 12));
+ break;
+#endif
+ case PREF:
+ /* Treat as no-op */
+ break;
+ default:
+ MIPS_INVAL("pool32c");
+ generate_exception(ctx, EXCP_RI);
+ break;
+ }
+ break;
+ case ADDI32:
+ mips32_op = OPC_ADDI;
+ goto do_addi;
+ case ADDIU32:
+ mips32_op = OPC_ADDIU;
+ do_addi:
+ gen_arith_imm(env, ctx, mips32_op, rt, rs, imm);
+ break;
+
+ /* Logical operations */
+ case ORI32:
+ mips32_op = OPC_ORI;
+ goto do_logici;
+ case XORI32:
+ mips32_op = OPC_XORI;
+ goto do_logici;
+ case ANDI32:
+ mips32_op = OPC_ANDI;
+ do_logici:
+ gen_logic_imm(env, mips32_op, rt, rs, imm);
+ break;
+
+ /* Set less than immediate */
+ case SLTI32:
+ mips32_op = OPC_SLTI;
+ goto do_slti;
+ case SLTIU32:
+ mips32_op = OPC_SLTIU;
+ do_slti:
+ gen_slt_imm(env, mips32_op, rt, rs, imm);
+ break;
+ case JALX32:
+ offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
+ gen_compute_branch(ctx, OPC_JALX, 4, rt, rs, offset);
+ *is_branch = 1;
+ break;
+ case JALS32:
+ offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 1;
+ gen_compute_branch(ctx, OPC_JALS, 4, rt, rs, offset);
+ *is_branch = 1;
+ break;
+ case BEQ32:
+ gen_compute_branch(ctx, OPC_BEQ, 4, rt, rs, imm << 1);
+ *is_branch = 1;
+ break;
+ case BNE32:
+ gen_compute_branch(ctx, OPC_BNE, 4, rt, rs, imm << 1);
+ *is_branch = 1;
+ break;
+ case J32:
+ gen_compute_branch(ctx, OPC_J, 4, rt, rs,
+ (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
+ *is_branch = 1;
+ break;
+ case JAL32:
+ gen_compute_branch(ctx, OPC_JAL, 4, rt, rs,
+ (int32_t)(ctx->opcode & 0x3FFFFFF) << 1);
+ *is_branch = 1;
+ break;
+ /* Floating point (COP1) */
+ case LWC132:
+ mips32_op = OPC_LWC1;
+ goto do_cop1;
+ case LDC132:
+ mips32_op = OPC_LDC1;
+ goto do_cop1;
+ case SWC132:
+ mips32_op = OPC_SWC1;
+ goto do_cop1;
+ case SDC132:
+ mips32_op = OPC_SDC1;
+ do_cop1:
+ gen_cop1_ldst(env, ctx, mips32_op, rt, rs, imm);
+ break;
+ case ADDIUPC:
+ {
+ int reg = mmreg(ZIMM(ctx->opcode, 23, 3));
+ int offset = SIMM(ctx->opcode, 0, 23) << 2;
+
+ gen_addiupc(ctx, reg, offset, 0, 0);
+ }
+ break;
+ /* Loads and stores */
+ case LB32:
+ mips32_op = OPC_LB;
+ goto do_ldst;
+ case LBU32:
+ mips32_op = OPC_LBU;
+ goto do_ldst;
+ case LH32:
+ mips32_op = OPC_LH;
+ goto do_ldst;
+ case LHU32:
+ mips32_op = OPC_LHU;
+ goto do_ldst;
+ case LW32:
+ mips32_op = OPC_LW;
+ goto do_ldst;
+#ifdef TARGET_MIPS64
+ case LD32:
+ mips32_op = OPC_LD;
+ goto do_ldst;
+ case SD32:
+ mips32_op = OPC_SD;
+ goto do_ldst;
+#endif
+ case SB32:
+ mips32_op = OPC_SB;
+ goto do_ldst;
+ case SH32:
+ mips32_op = OPC_SH;
+ goto do_ldst;
+ case SW32:
+ mips32_op = OPC_SW;
+ do_ldst:
+ gen_ldst(ctx, mips32_op, rt, rs, imm);
+ break;
+ default:
+ generate_exception(ctx, EXCP_RI);
+ break;
+ }
+}
+
+static int decode_micromips_opc (CPUState *env, DisasContext *ctx, int *is_branch)
+{
+ uint32_t op;
+
+ /* make sure instructions are on a halfword boundary */
+ if (ctx->pc & 0x1) {
+ env->CP0_BadVAddr = ctx->pc;
+ generate_exception(ctx, EXCP_AdEL);
+ ctx->bstate = BS_STOP;
+ return 2;
+ }
+
+ op = (ctx->opcode >> 10) & 0x3f;
+ /* Enforce properly-sized instructions in a delay slot */
+ if (ctx->hflags & MIPS_HFLAG_BMASK) {
+ int bits = ctx->hflags & MIPS_HFLAG_BMASK_EXT;
+
+ switch (op) {
+ case POOL32A:
+ case POOL32B:
+ case POOL32I:
+ case POOL32C:
+ case ADDI32:
+ case ADDIU32:
+ case ORI32:
+ case XORI32:
+ case SLTI32:
+ case SLTIU32:
+ case ANDI32:
+ case JALX32:
+ case LBU32:
+ case LHU32:
+ case POOL32F:
+ case JALS32:
+ case BEQ32:
+ case BNE32:
+ case J32:
+ case JAL32:
+ case SB32:
+ case SH32:
+ case POOL32S:
+ case ADDIUPC:
+ case SWC132:
+ case SDC132:
+ case SD32:
+ case SW32:
+ case LB32:
+ case LH32:
+ case DADDIU32:
+ case POOL48A: /* ??? */
+ case LWC132:
+ case LDC132:
+ case LD32:
+ case LW32:
+ if (bits & MIPS_HFLAG_BDS16) {
+ generate_exception(ctx, EXCP_RI);
+ /* Just stop translation; the user is confused. */
+ ctx->bstate = BS_STOP;
+ return 2;
+ }
+ break;
+ case POOL16A:
+ case POOL16B:
+ case POOL16C:
+ case LWGP16:
+ case POOL16F:
+ case LBU16:
+ case LHU16:
+ case LWSP16:
+ case LW16:
+ case SB16:
+ case SH16:
+ case SWSP16:
+ case SW16:
+ case MOVE16:
+ case ANDI16:
+ case POOL16D:
+ case POOL16E:
+ case BEQZ16:
+ case BNEZ16:
+ case B16:
+ case LI16:
+ if (bits & MIPS_HFLAG_BDS32) {
+ generate_exception(ctx, EXCP_RI);
+ /* Just stop translation; the user is confused. */
+ ctx->bstate = BS_STOP;
+ return 2;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ switch (op) {
+ case POOL16A:
+ {
+ int rd = mmreg(uMIPS_RD(ctx->opcode));
+ int rs1 = mmreg(uMIPS_RS1(ctx->opcode));
+ int rs2 = mmreg(uMIPS_RS2(ctx->opcode));
+ uint32_t opc = 0;
+
+ switch (ctx->opcode & 0x1) {
+ case ADDU16:
+ opc = OPC_ADDU;
+ break;
+ case SUBU16:
+ opc = OPC_SUBU;
+ break;
+ }
+
+ gen_arith(env, ctx, opc, rd, rs1, rs2);
+ }
+ break;
+ case POOL16B:
+ {
+ int rd = mmreg(uMIPS_RD(ctx->opcode));
+ int rs = mmreg(uMIPS_RS(ctx->opcode));
+ int amount = (ctx->opcode >> 1) & 0x7;
+ uint32_t opc = 0;
+ amount = amount == 0 ? 8 : amount;
+
+ switch (ctx->opcode & 0x1) {
+ case SLL16:
+ opc = OPC_SLL;
+ break;
+ case SRL16:
+ opc = OPC_SRL;
+ break;
+ }
+
+ gen_shift_imm(env, ctx, opc, rd, rs, amount);
+ }
+ break;
+ case POOL16C:
+ gen_pool16c_insn(env, ctx, is_branch);
+ break;
+ case LWGP16:
+ {
+ int rd = mmreg(uMIPS_RD(ctx->opcode));
+ int rb = 28; /* GP */
+ int16_t offset = SIMM(ctx->opcode, 0, 7) << 2;
+
+ gen_ldst(ctx, OPC_LW, rd, rb, offset);
+ }
+ break;
+ case POOL16F:
+ if (ctx->opcode & 1) {
+ generate_exception(ctx, EXCP_RI);
+ } else {
+ /* MOVEP */
+ int enc_dest = uMIPS_RD(ctx->opcode);
+ int enc_rt = uMIPS_RS2(ctx->opcode);
+ int enc_rs = uMIPS_RS1(ctx->opcode);
+ int rd, rs, re, rt;
+ static const int rd_enc[] = { 5, 5, 6, 4, 4, 4, 4, 4 };
+ static const int re_enc[] = { 6, 7, 7, 21, 22, 5, 6, 7 };
+ static const int rs_rt_enc[] = { 0, 17, 2, 3, 16, 18, 19, 20 };
+
+ rd = rd_enc[enc_dest];
+ re = re_enc[enc_dest];
+ rs = rs_rt_enc[enc_rs];
+ rt = rs_rt_enc[enc_rt];
+
+ gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
+ gen_arith_imm(env, ctx, OPC_ADDIU, re, rt, 0);
+ }
+ break;
+ case LBU16:
+ {
+ int rd = mmreg(uMIPS_RD(ctx->opcode));
+ int rb = mmreg(uMIPS_RS(ctx->opcode));
+ int16_t offset = ZIMM(ctx->opcode, 0, 4);
+ offset = (offset == 0xf ? -1 : offset);
+
+ gen_ldst(ctx, OPC_LBU, rd, rb, offset);
+ }
+ break;
+ case LHU16:
+ {
+ int rd = mmreg(uMIPS_RD(ctx->opcode));
+ int rb = mmreg(uMIPS_RS(ctx->opcode));
+ int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
+
+ gen_ldst(ctx, OPC_LHU, rd, rb, offset);
+ }
+ break;
+ case LWSP16:
+ {
+ int rd = (ctx->opcode >> 5) & 0x1f;
+ int rb = 29; /* SP */
+ int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
+
+ gen_ldst(ctx, OPC_LW, rd, rb, offset);
+ }
+ break;
+ case LW16:
+ {
+ int rd = mmreg(uMIPS_RD(ctx->opcode));
+ int rb = mmreg(uMIPS_RS(ctx->opcode));
+ int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
+
+ gen_ldst(ctx, OPC_LW, rd, rb, offset);
+ }
+ break;
+ case SB16:
+ {
+ int rd = mmreg2(uMIPS_RD(ctx->opcode));
+ int rb = mmreg(uMIPS_RS(ctx->opcode));
+ int16_t offset = ZIMM(ctx->opcode, 0, 4);
+
+ gen_ldst(ctx, OPC_SB, rd, rb, offset);
+ }
+ break;
+ case SH16:
+ {
+ int rd = mmreg2(uMIPS_RD(ctx->opcode));
+ int rb = mmreg(uMIPS_RS(ctx->opcode));
+ int16_t offset = ZIMM(ctx->opcode, 0, 4) << 1;
+
+ gen_ldst(ctx, OPC_SH, rd, rb, offset);
+ }
+ break;
+ case SWSP16:
+ {
+ int rd = (ctx->opcode >> 5) & 0x1f;
+ int rb = 29; /* SP */
+ int16_t offset = ZIMM(ctx->opcode, 0, 5) << 2;
+
+ gen_ldst(ctx, OPC_SW, rd, rb, offset);
+ }
+ break;
+ case SW16:
+ {
+ int rd = mmreg2(uMIPS_RD(ctx->opcode));
+ int rb = mmreg(uMIPS_RS(ctx->opcode));
+ int16_t offset = ZIMM(ctx->opcode, 0, 4) << 2;
+
+ gen_ldst(ctx, OPC_SW, rd, rb, offset);
+ }
+ break;
+ case MOVE16:
+ {
+ int rd = uMIPS_RD5(ctx->opcode);
+ int rs = uMIPS_RS5(ctx->opcode);
+
+ gen_arith_imm(env, ctx, OPC_ADDIU, rd, rs, 0);
+ }
+ break;
+ case ANDI16:
+ gen_andi16(env, ctx);
+ break;
+ case POOL16D:
+ switch (ctx->opcode & 0x1) {
+ case ADDIUS5:
+ gen_addius5(env, ctx);
+ break;
+ case ADDIUSP:
+ gen_addiusp(env, ctx);
+ break;
+ }
+ break;
+ case POOL16E:
+ switch (ctx->opcode & 0x1) {
+ case ADDIUR2:
+ gen_addiur2(env, ctx);
+ break;
+ case ADDIUR1SP:
+ gen_addiur1sp(env, ctx);
+ break;
+ }
+ break;
+ case B16:
+ gen_compute_branch(ctx, OPC_BEQ, 2, 0, 0,
+ SIMM(ctx->opcode, 0, 10) << 1);
+ *is_branch = 1;
+ break;
+ case BNEZ16:
+ case BEQZ16:
+ gen_compute_branch(ctx, op == BNEZ16 ? OPC_BNE : OPC_BEQ, 2,
+ mmreg(uMIPS_RD(ctx->opcode)),
+ 0, SIMM(ctx->opcode, 0, 7) << 1);
+ *is_branch = 1;
+ break;
+ case LI16:
+ {
+ int reg = mmreg(uMIPS_RD(ctx->opcode));
+ int imm = ZIMM(ctx->opcode, 0, 7);
+
+ imm = (imm == 0x7f ? -1 : imm);
+ tcg_gen_movi_tl(cpu_gpr[reg], imm);
+ }
+ break;
+ case RES_20:
+ case RES_28:
+ case RES_29:
+ case RES_30:
+ case RES_31:
+ case RES_38:
+ case RES_39:
+ generate_exception(ctx, EXCP_RI);
+ break;
+ default:
+ decode_micromips32_opc (env, ctx, op, is_branch);
+ return 4;
+ }
+
+ return 2;
+}
+
/* SmartMIPS extension to MIPS32 */
#if defined(TARGET_MIPS64)
@@ -9548,7 +11924,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
break;
#endif
case OPC_JALX:
- check_insn(env, ctx, ASE_MIPS16);
+ check_insn(env, ctx, ASE_MIPS16 | ASE_MICROMIPS);
offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
gen_compute_branch(ctx, op, 4, rs, rt, offset);
*is_branch = 1;
@@ -9636,11 +12012,15 @@ gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
ctx.opcode = ldl_code(ctx.pc);
insn_bytes = 4;
decode_opc(env, &ctx, &is_branch);
+ } else if (env->insn_flags & ASE_MICROMIPS) {
+ ctx.opcode = lduw_code(ctx.pc);
+ insn_bytes = decode_micromips_opc(env, &ctx, &is_branch);
} else if (env->insn_flags & ASE_MIPS16) {
ctx.opcode = lduw_code(ctx.pc);
insn_bytes = decode_mips16_opc(env, &ctx, &is_branch);
} else {
generate_exception(&ctx, EXCP_RI);
+ ctx.bstate = BS_STOP;
break;
}
if (!is_branch) {
commit 620e48f66350991918dd78e9a686a9b159fec111
Author: Nathan Froyd <froydnj at codesourcery.com>
Date: Tue Jun 8 13:29:58 2010 -0700
target-mips: mips16 cleanups
Change code handling mips16-specific branches to use ISA-neutral special
opcodes. Since there are several places where the delay slot
requirements for microMIPS branches differ from mips16 branches, using
opcodes is easier than checking hflags, then checking mips16
vs. microMIPS.
Signed-off-by: Nathan Froyd <froydnj at codesourcery.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-mips/translate.c b/target-mips/translate.c
index c3182c5..78783a8 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -68,6 +68,7 @@ enum {
/* Jump and branches */
OPC_J = (0x02 << 26),
OPC_JAL = (0x03 << 26),
+ OPC_JALS = OPC_JAL | 0x5,
OPC_BEQ = (0x04 << 26), /* Unconditional if rs = rt = 0 (B) */
OPC_BEQL = (0x14 << 26),
OPC_BNE = (0x05 << 26),
@@ -77,6 +78,7 @@ enum {
OPC_BGTZ = (0x07 << 26),
OPC_BGTZL = (0x17 << 26),
OPC_JALX = (0x1D << 26), /* MIPS 16 only */
+ OPC_JALXS = OPC_JALX | 0x5,
/* Load and stores */
OPC_LDL = (0x1A << 26),
OPC_LDR = (0x1B << 26),
@@ -177,6 +179,7 @@ enum {
OPC_JR = 0x08 | OPC_SPECIAL, /* Also JR.HB */
OPC_JALR = 0x09 | OPC_SPECIAL, /* Also JALR.HB */
OPC_JALRC = OPC_JALR | (0x5 << 6),
+ OPC_JALRS = 0x10 | OPC_SPECIAL | (0x5 << 6),
/* Traps */
OPC_TGE = 0x30 | OPC_SPECIAL,
OPC_TGEU = 0x31 | OPC_SPECIAL,
@@ -2466,12 +2469,15 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
case OPC_J:
case OPC_JAL:
case OPC_JALX:
+ case OPC_JALS:
+ case OPC_JALXS:
/* Jump to immediate */
btgt = ((ctx->pc + insn_bytes) & (int32_t)0xF0000000) | (uint32_t)offset;
break;
case OPC_JR:
case OPC_JALR:
case OPC_JALRC:
+ case OPC_JALRS:
/* Jump to register */
if (offset != 0 && offset != 16) {
/* Hint = 0 is JR/JALR, hint 16 is JR.HB/JALR.HB, the
@@ -2534,29 +2540,33 @@ static void gen_compute_branch (DisasContext *ctx, uint32_t opc,
ctx->hflags |= MIPS_HFLAG_B;
MIPS_DEBUG("j " TARGET_FMT_lx, btgt);
break;
+ case OPC_JALXS:
case OPC_JALX:
ctx->hflags |= MIPS_HFLAG_BX;
/* Fallthrough */
+ case OPC_JALS:
case OPC_JAL:
blink = 31;
ctx->hflags |= MIPS_HFLAG_B;
- ctx->hflags |= (ctx->hflags & MIPS_HFLAG_M16
+ ctx->hflags |= ((opc == OPC_JALS || opc == OPC_JALXS)
? MIPS_HFLAG_BDS16
: MIPS_HFLAG_BDS32);
MIPS_DEBUG("jal " TARGET_FMT_lx, btgt);
break;
case OPC_JR:
ctx->hflags |= MIPS_HFLAG_BR;
- if (ctx->hflags & MIPS_HFLAG_M16)
- ctx->hflags |= MIPS_HFLAG_BDS16;
+ if (insn_bytes == 4)
+ ctx->hflags |= MIPS_HFLAG_BDS32;
MIPS_DEBUG("jr %s", regnames[rs]);
break;
+ case OPC_JALRS:
case OPC_JALR:
case OPC_JALRC:
blink = rt;
ctx->hflags |= MIPS_HFLAG_BR;
- if (ctx->hflags & MIPS_HFLAG_M16)
- ctx->hflags |= MIPS_HFLAG_BDS16;
+ ctx->hflags |= (opc == OPC_JALRS
+ ? MIPS_HFLAG_BDS16
+ : MIPS_HFLAG_BDS32);
MIPS_DEBUG("jalr %s, %s", regnames[rt], regnames[rs]);
break;
default:
@@ -8487,7 +8497,7 @@ static int decode_mips16_opc (CPUState *env, DisasContext *ctx,
offset = (((ctx->opcode & 0x1f) << 21)
| ((ctx->opcode >> 5) & 0x1f) << 16
| offset) << 2;
- op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALX : OPC_JAL;
+ op = ((ctx->opcode >> 10) & 0x1) ? OPC_JALXS : OPC_JALS;
gen_compute_branch(ctx, op, 4, rx, ry, offset);
n_bytes = 4;
*is_branch = 1;
@@ -8726,7 +8736,7 @@ static int decode_mips16_opc (CPUState *env, DisasContext *ctx,
int ra = (ctx->opcode >> 5) & 0x1;
if (link) {
- op = nd ? OPC_JALRC : OPC_JALR;
+ op = nd ? OPC_JALRC : OPC_JALRS;
} else {
op = OPC_JR;
}
commit 8153667c718e359368f306e1b2c144596dec5f80
Author: Nathan Froyd <froydnj at codesourcery.com>
Date: Tue Jun 8 13:29:57 2010 -0700
target-mips: refactor c{, abs}.cond.fmt insns
Move all knowledge about coprocessor-checking and register numbering
into the gen_cmp* helper functions.
Signed-off-by: Nathan Froyd <froydnj at codesourcery.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 380312f..c3182c5 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -676,39 +676,6 @@ static inline int get_fp_bit (int cc)
return 23;
}
-#define FOP_CONDS(type, fmt, bits) \
-static inline void gen_cmp ## type ## _ ## fmt(int n, TCGv_i##bits a, \
- TCGv_i##bits b, int cc) \
-{ \
- switch (n) { \
- case 0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, a, b, cc); break;\
- case 1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, a, b, cc); break;\
- case 2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, a, b, cc); break;\
- case 3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, a, b, cc); break;\
- case 4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, a, b, cc); break;\
- case 5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, a, b, cc); break;\
- case 6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, a, b, cc); break;\
- case 7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, a, b, cc); break;\
- case 8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, a, b, cc); break;\
- case 9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, a, b, cc); break;\
- case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, a, b, cc); break;\
- case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, a, b, cc); break;\
- case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, a, b, cc); break;\
- case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, a, b, cc); break;\
- case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, a, b, cc); break;\
- case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, a, b, cc); break;\
- default: abort(); \
- } \
-}
-
-FOP_CONDS(, d, 64)
-FOP_CONDS(abs, d, 64)
-FOP_CONDS(, s, 32)
-FOP_CONDS(abs, s, 32)
-FOP_CONDS(, ps, 64)
-FOP_CONDS(abs, ps, 64)
-#undef FOP_CONDS
-
/* Tests */
static inline void gen_save_pc(target_ulong pc)
{
@@ -849,6 +816,69 @@ static inline void check_mips_64(DisasContext *ctx)
generate_exception(ctx, EXCP_RI);
}
+/* Define small wrappers for gen_load_fpr* so that we have a uniform
+ calling interface for 32 and 64-bit FPRs. No sense in changing
+ all callers for gen_load_fpr32 when we need the CTX parameter for
+ this one use. */
+#define gen_ldcmp_fpr32(ctx, x, y) gen_load_fpr32(x, y)
+#define gen_ldcmp_fpr64(ctx, x, y) gen_load_fpr64(ctx, x, y)
+#define FOP_CONDS(type, abs, fmt, ifmt, bits) \
+static inline void gen_cmp ## type ## _ ## fmt(DisasContext *ctx, int n, \
+ int ft, int fs, int cc) \
+{ \
+ TCGv_i##bits fp0 = tcg_temp_new_i##bits (); \
+ TCGv_i##bits fp1 = tcg_temp_new_i##bits (); \
+ switch (ifmt) { \
+ case FMT_PS: \
+ check_cp1_64bitmode(ctx); \
+ break; \
+ case FMT_D: \
+ if (abs) { \
+ check_cop1x(ctx); \
+ } \
+ check_cp1_registers(ctx, fs | ft); \
+ break; \
+ case FMT_S: \
+ if (abs) { \
+ check_cop1x(ctx); \
+ } \
+ break; \
+ } \
+ gen_ldcmp_fpr##bits (ctx, fp0, fs); \
+ gen_ldcmp_fpr##bits (ctx, fp1, ft); \
+ switch (n) { \
+ case 0: gen_helper_2i(cmp ## type ## _ ## fmt ## _f, fp0, fp1, cc); break;\
+ case 1: gen_helper_2i(cmp ## type ## _ ## fmt ## _un, fp0, fp1, cc); break;\
+ case 2: gen_helper_2i(cmp ## type ## _ ## fmt ## _eq, fp0, fp1, cc); break;\
+ case 3: gen_helper_2i(cmp ## type ## _ ## fmt ## _ueq, fp0, fp1, cc); break;\
+ case 4: gen_helper_2i(cmp ## type ## _ ## fmt ## _olt, fp0, fp1, cc); break;\
+ case 5: gen_helper_2i(cmp ## type ## _ ## fmt ## _ult, fp0, fp1, cc); break;\
+ case 6: gen_helper_2i(cmp ## type ## _ ## fmt ## _ole, fp0, fp1, cc); break;\
+ case 7: gen_helper_2i(cmp ## type ## _ ## fmt ## _ule, fp0, fp1, cc); break;\
+ case 8: gen_helper_2i(cmp ## type ## _ ## fmt ## _sf, fp0, fp1, cc); break;\
+ case 9: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngle, fp0, fp1, cc); break;\
+ case 10: gen_helper_2i(cmp ## type ## _ ## fmt ## _seq, fp0, fp1, cc); break;\
+ case 11: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngl, fp0, fp1, cc); break;\
+ case 12: gen_helper_2i(cmp ## type ## _ ## fmt ## _lt, fp0, fp1, cc); break;\
+ case 13: gen_helper_2i(cmp ## type ## _ ## fmt ## _nge, fp0, fp1, cc); break;\
+ case 14: gen_helper_2i(cmp ## type ## _ ## fmt ## _le, fp0, fp1, cc); break;\
+ case 15: gen_helper_2i(cmp ## type ## _ ## fmt ## _ngt, fp0, fp1, cc); break;\
+ default: abort(); \
+ } \
+ tcg_temp_free_i##bits (fp0); \
+ tcg_temp_free_i##bits (fp1); \
+}
+
+FOP_CONDS(, 0, d, FMT_D, 64)
+FOP_CONDS(abs, 1, d, FMT_D, 64)
+FOP_CONDS(, 0, s, FMT_S, 32)
+FOP_CONDS(abs, 1, s, FMT_S, 32)
+FOP_CONDS(, 0, ps, FMT_PS, 64)
+FOP_CONDS(abs, 1, ps, FMT_PS, 64)
+#undef FOP_CONDS
+#undef gen_ldcmp_fpr32
+#undef gen_ldcmp_fpr64
+
/* load/store instructions. */
#define OP_LD(insn,fname) \
static inline void op_ldst_##insn(TCGv ret, TCGv arg1, DisasContext *ctx) \
@@ -6480,22 +6510,12 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
case OPC_CMP_NGE_S:
case OPC_CMP_LE_S:
case OPC_CMP_NGT_S:
- {
- TCGv_i32 fp0 = tcg_temp_new_i32();
- TCGv_i32 fp1 = tcg_temp_new_i32();
-
- gen_load_fpr32(fp0, fs);
- gen_load_fpr32(fp1, ft);
- if (ctx->opcode & (1 << 6)) {
- check_cop1x(ctx);
- gen_cmpabs_s(func-48, fp0, fp1, cc);
- opn = condnames_abs[func-48];
- } else {
- gen_cmp_s(func-48, fp0, fp1, cc);
- opn = condnames[func-48];
- }
- tcg_temp_free_i32(fp0);
- tcg_temp_free_i32(fp1);
+ if (ctx->opcode & (1 << 6)) {
+ gen_cmpabs_s(ctx, func-48, ft, fs, cc);
+ opn = condnames_abs[func-48];
+ } else {
+ gen_cmp_s(ctx, func-48, ft, fs, cc);
+ opn = condnames[func-48];
}
break;
case OPC_ADD_D:
@@ -6843,24 +6863,12 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
case OPC_CMP_NGE_D:
case OPC_CMP_LE_D:
case OPC_CMP_NGT_D:
- {
- TCGv_i64 fp0 = tcg_temp_new_i64();
- TCGv_i64 fp1 = tcg_temp_new_i64();
-
- gen_load_fpr64(ctx, fp0, fs);
- gen_load_fpr64(ctx, fp1, ft);
- if (ctx->opcode & (1 << 6)) {
- check_cop1x(ctx);
- check_cp1_registers(ctx, fs | ft);
- gen_cmpabs_d(func-48, fp0, fp1, cc);
- opn = condnames_abs[func-48];
- } else {
- check_cp1_registers(ctx, fs | ft);
- gen_cmp_d(func-48, fp0, fp1, cc);
- opn = condnames[func-48];
- }
- tcg_temp_free_i64(fp0);
- tcg_temp_free_i64(fp1);
+ if (ctx->opcode & (1 << 6)) {
+ gen_cmpabs_d(ctx, func-48, ft, fs, cc);
+ opn = condnames_abs[func-48];
+ } else {
+ gen_cmp_d(ctx, func-48, ft, fs, cc);
+ opn = condnames[func-48];
}
break;
case OPC_CVT_S_D:
@@ -7280,22 +7288,12 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
case OPC_CMP_NGE_PS:
case OPC_CMP_LE_PS:
case OPC_CMP_NGT_PS:
- check_cp1_64bitmode(ctx);
- {
- TCGv_i64 fp0 = tcg_temp_new_i64();
- TCGv_i64 fp1 = tcg_temp_new_i64();
-
- gen_load_fpr64(ctx, fp0, fs);
- gen_load_fpr64(ctx, fp1, ft);
- if (ctx->opcode & (1 << 6)) {
- gen_cmpabs_ps(func-48, fp0, fp1, cc);
- opn = condnames_abs[func-48];
- } else {
- gen_cmp_ps(func-48, fp0, fp1, cc);
- opn = condnames[func-48];
- }
- tcg_temp_free_i64(fp0);
- tcg_temp_free_i64(fp1);
+ if (ctx->opcode & (1 << 6)) {
+ gen_cmpabs_ps(ctx, func-48, ft, fs, cc);
+ opn = condnames_abs[func-48];
+ } else {
+ gen_cmp_ps(ctx, func-48, ft, fs, cc);
+ opn = condnames[func-48];
}
break;
default:
commit e459440a896166b65875767f081d9add8db6c9ea
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Wed Jun 9 15:13:17 2010 +0200
target-mips: move FP FMT comments closer to the definitions
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 4e54940..380312f 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -357,13 +357,13 @@ enum {
/* Values for the fmt field in FP instructions */
enum {
/* 0 - 15 are reserved */
- FMT_S = 16,
- FMT_D = 17,
- FMT_E = 18,
- FMT_Q = 19,
- FMT_W = 20,
- FMT_L = 21,
- FMT_PS = 22,
+ FMT_S = 16, /* single fp */
+ FMT_D = 17, /* double fp */
+ FMT_E = 18, /* extended fp */
+ FMT_Q = 19, /* quad fp */
+ FMT_W = 20, /* 32-bit fixed */
+ FMT_L = 21, /* 64-bit fixed */
+ FMT_PS = 22, /* paired single fp */
/* 23 - 31 are reserved */
};
@@ -379,13 +379,13 @@ enum {
OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
- OPC_S_FMT = (FMT_S << 21) | OPC_CP1, /* 16: fmt=single fp */
- OPC_D_FMT = (FMT_D << 21) | OPC_CP1, /* 17: fmt=double fp */
- OPC_E_FMT = (FMT_E << 21) | OPC_CP1, /* 18: fmt=extended fp */
- OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1, /* 19: fmt=quad fp */
- OPC_W_FMT = (FMT_W << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
- OPC_L_FMT = (FMT_L << 21) | OPC_CP1, /* 21: fmt=64bit fixed */
- OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1, /* 22: fmt=paired single fp */
+ OPC_S_FMT = (FMT_S << 21) | OPC_CP1,
+ OPC_D_FMT = (FMT_D << 21) | OPC_CP1,
+ OPC_E_FMT = (FMT_E << 21) | OPC_CP1,
+ OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1,
+ OPC_W_FMT = (FMT_W << 21) | OPC_CP1,
+ OPC_L_FMT = (FMT_L << 21) | OPC_CP1,
+ OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1,
};
#define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
commit bf4120adaabb540fe66742b4d26cac69713af0c1
Author: Nathan Froyd <froydnj at codesourcery.com>
Date: Tue Jun 8 13:29:56 2010 -0700
target-mips: define constants for magic numbers
Add FMT_* constants for the floating-point format field in opcodes and
tweak a few places to use them. Add enums for various invocations of
FOP and tweak gen_farith and its lone caller accordingly.
Signed-off-by: Nathan Froyd <froydnj at codesourcery.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 2075d09..4e54940 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -354,6 +354,19 @@ enum {
/* Coprocessor 1 (rs field) */
#define MASK_CP1(op) MASK_OP_MAJOR(op) | (op & (0x1F << 21))
+/* Values for the fmt field in FP instructions */
+enum {
+ /* 0 - 15 are reserved */
+ FMT_S = 16,
+ FMT_D = 17,
+ FMT_E = 18,
+ FMT_Q = 19,
+ FMT_W = 20,
+ FMT_L = 21,
+ FMT_PS = 22,
+ /* 23 - 31 are reserved */
+};
+
enum {
OPC_MFC1 = (0x00 << 21) | OPC_CP1,
OPC_DMFC1 = (0x01 << 21) | OPC_CP1,
@@ -366,13 +379,13 @@ enum {
OPC_BC1 = (0x08 << 21) | OPC_CP1, /* bc */
OPC_BC1ANY2 = (0x09 << 21) | OPC_CP1,
OPC_BC1ANY4 = (0x0A << 21) | OPC_CP1,
- OPC_S_FMT = (0x10 << 21) | OPC_CP1, /* 16: fmt=single fp */
- OPC_D_FMT = (0x11 << 21) | OPC_CP1, /* 17: fmt=double fp */
- OPC_E_FMT = (0x12 << 21) | OPC_CP1, /* 18: fmt=extended fp */
- OPC_Q_FMT = (0x13 << 21) | OPC_CP1, /* 19: fmt=quad fp */
- OPC_W_FMT = (0x14 << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
- OPC_L_FMT = (0x15 << 21) | OPC_CP1, /* 21: fmt=64bit fixed */
- OPC_PS_FMT = (0x16 << 21) | OPC_CP1, /* 22: fmt=paired single fp */
+ OPC_S_FMT = (FMT_S << 21) | OPC_CP1, /* 16: fmt=single fp */
+ OPC_D_FMT = (FMT_D << 21) | OPC_CP1, /* 17: fmt=double fp */
+ OPC_E_FMT = (FMT_E << 21) | OPC_CP1, /* 18: fmt=extended fp */
+ OPC_Q_FMT = (FMT_Q << 21) | OPC_CP1, /* 19: fmt=quad fp */
+ OPC_W_FMT = (FMT_W << 21) | OPC_CP1, /* 20: fmt=32bit fixed */
+ OPC_L_FMT = (FMT_L << 21) | OPC_CP1, /* 21: fmt=64bit fixed */
+ OPC_PS_FMT = (FMT_PS << 21) | OPC_CP1, /* 22: fmt=paired single fp */
};
#define MASK_CP1_FUNC(op) MASK_CP1(op) | (op & 0x3F)
@@ -5714,6 +5727,146 @@ static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
#define FOP(func, fmt) (((fmt) << 21) | (func))
+enum fopcode {
+ OPC_ADD_S = FOP(0, FMT_S),
+ OPC_SUB_S = FOP(1, FMT_S),
+ OPC_MUL_S = FOP(2, FMT_S),
+ OPC_DIV_S = FOP(3, FMT_S),
+ OPC_SQRT_S = FOP(4, FMT_S),
+ OPC_ABS_S = FOP(5, FMT_S),
+ OPC_MOV_S = FOP(6, FMT_S),
+ OPC_NEG_S = FOP(7, FMT_S),
+ OPC_ROUND_L_S = FOP(8, FMT_S),
+ OPC_TRUNC_L_S = FOP(9, FMT_S),
+ OPC_CEIL_L_S = FOP(10, FMT_S),
+ OPC_FLOOR_L_S = FOP(11, FMT_S),
+ OPC_ROUND_W_S = FOP(12, FMT_S),
+ OPC_TRUNC_W_S = FOP(13, FMT_S),
+ OPC_CEIL_W_S = FOP(14, FMT_S),
+ OPC_FLOOR_W_S = FOP(15, FMT_S),
+ OPC_MOVCF_S = FOP(17, FMT_S),
+ OPC_MOVZ_S = FOP(18, FMT_S),
+ OPC_MOVN_S = FOP(19, FMT_S),
+ OPC_RECIP_S = FOP(21, FMT_S),
+ OPC_RSQRT_S = FOP(22, FMT_S),
+ OPC_RECIP2_S = FOP(28, FMT_S),
+ OPC_RECIP1_S = FOP(29, FMT_S),
+ OPC_RSQRT1_S = FOP(30, FMT_S),
+ OPC_RSQRT2_S = FOP(31, FMT_S),
+ OPC_CVT_D_S = FOP(33, FMT_S),
+ OPC_CVT_W_S = FOP(36, FMT_S),
+ OPC_CVT_L_S = FOP(37, FMT_S),
+ OPC_CVT_PS_S = FOP(38, FMT_S),
+ OPC_CMP_F_S = FOP (48, FMT_S),
+ OPC_CMP_UN_S = FOP (49, FMT_S),
+ OPC_CMP_EQ_S = FOP (50, FMT_S),
+ OPC_CMP_UEQ_S = FOP (51, FMT_S),
+ OPC_CMP_OLT_S = FOP (52, FMT_S),
+ OPC_CMP_ULT_S = FOP (53, FMT_S),
+ OPC_CMP_OLE_S = FOP (54, FMT_S),
+ OPC_CMP_ULE_S = FOP (55, FMT_S),
+ OPC_CMP_SF_S = FOP (56, FMT_S),
+ OPC_CMP_NGLE_S = FOP (57, FMT_S),
+ OPC_CMP_SEQ_S = FOP (58, FMT_S),
+ OPC_CMP_NGL_S = FOP (59, FMT_S),
+ OPC_CMP_LT_S = FOP (60, FMT_S),
+ OPC_CMP_NGE_S = FOP (61, FMT_S),
+ OPC_CMP_LE_S = FOP (62, FMT_S),
+ OPC_CMP_NGT_S = FOP (63, FMT_S),
+
+ OPC_ADD_D = FOP(0, FMT_D),
+ OPC_SUB_D = FOP(1, FMT_D),
+ OPC_MUL_D = FOP(2, FMT_D),
+ OPC_DIV_D = FOP(3, FMT_D),
+ OPC_SQRT_D = FOP(4, FMT_D),
+ OPC_ABS_D = FOP(5, FMT_D),
+ OPC_MOV_D = FOP(6, FMT_D),
+ OPC_NEG_D = FOP(7, FMT_D),
+ OPC_ROUND_L_D = FOP(8, FMT_D),
+ OPC_TRUNC_L_D = FOP(9, FMT_D),
+ OPC_CEIL_L_D = FOP(10, FMT_D),
+ OPC_FLOOR_L_D = FOP(11, FMT_D),
+ OPC_ROUND_W_D = FOP(12, FMT_D),
+ OPC_TRUNC_W_D = FOP(13, FMT_D),
+ OPC_CEIL_W_D = FOP(14, FMT_D),
+ OPC_FLOOR_W_D = FOP(15, FMT_D),
+ OPC_MOVCF_D = FOP(17, FMT_D),
+ OPC_MOVZ_D = FOP(18, FMT_D),
+ OPC_MOVN_D = FOP(19, FMT_D),
+ OPC_RECIP_D = FOP(21, FMT_D),
+ OPC_RSQRT_D = FOP(22, FMT_D),
+ OPC_RECIP2_D = FOP(28, FMT_D),
+ OPC_RECIP1_D = FOP(29, FMT_D),
+ OPC_RSQRT1_D = FOP(30, FMT_D),
+ OPC_RSQRT2_D = FOP(31, FMT_D),
+ OPC_CVT_S_D = FOP(32, FMT_D),
+ OPC_CVT_W_D = FOP(36, FMT_D),
+ OPC_CVT_L_D = FOP(37, FMT_D),
+ OPC_CMP_F_D = FOP (48, FMT_D),
+ OPC_CMP_UN_D = FOP (49, FMT_D),
+ OPC_CMP_EQ_D = FOP (50, FMT_D),
+ OPC_CMP_UEQ_D = FOP (51, FMT_D),
+ OPC_CMP_OLT_D = FOP (52, FMT_D),
+ OPC_CMP_ULT_D = FOP (53, FMT_D),
+ OPC_CMP_OLE_D = FOP (54, FMT_D),
+ OPC_CMP_ULE_D = FOP (55, FMT_D),
+ OPC_CMP_SF_D = FOP (56, FMT_D),
+ OPC_CMP_NGLE_D = FOP (57, FMT_D),
+ OPC_CMP_SEQ_D = FOP (58, FMT_D),
+ OPC_CMP_NGL_D = FOP (59, FMT_D),
+ OPC_CMP_LT_D = FOP (60, FMT_D),
+ OPC_CMP_NGE_D = FOP (61, FMT_D),
+ OPC_CMP_LE_D = FOP (62, FMT_D),
+ OPC_CMP_NGT_D = FOP (63, FMT_D),
+
+ OPC_CVT_S_W = FOP(32, FMT_W),
+ OPC_CVT_D_W = FOP(33, FMT_W),
+ OPC_CVT_S_L = FOP(32, FMT_L),
+ OPC_CVT_D_L = FOP(33, FMT_L),
+ OPC_CVT_PS_PW = FOP(38, FMT_W),
+
+ OPC_ADD_PS = FOP(0, FMT_PS),
+ OPC_SUB_PS = FOP(1, FMT_PS),
+ OPC_MUL_PS = FOP(2, FMT_PS),
+ OPC_DIV_PS = FOP(3, FMT_PS),
+ OPC_ABS_PS = FOP(5, FMT_PS),
+ OPC_MOV_PS = FOP(6, FMT_PS),
+ OPC_NEG_PS = FOP(7, FMT_PS),
+ OPC_MOVCF_PS = FOP(17, FMT_PS),
+ OPC_MOVZ_PS = FOP(18, FMT_PS),
+ OPC_MOVN_PS = FOP(19, FMT_PS),
+ OPC_ADDR_PS = FOP(24, FMT_PS),
+ OPC_MULR_PS = FOP(26, FMT_PS),
+ OPC_RECIP2_PS = FOP(28, FMT_PS),
+ OPC_RECIP1_PS = FOP(29, FMT_PS),
+ OPC_RSQRT1_PS = FOP(30, FMT_PS),
+ OPC_RSQRT2_PS = FOP(31, FMT_PS),
+
+ OPC_CVT_S_PU = FOP(32, FMT_PS),
+ OPC_CVT_PW_PS = FOP(36, FMT_PS),
+ OPC_CVT_S_PL = FOP(40, FMT_PS),
+ OPC_PLL_PS = FOP(44, FMT_PS),
+ OPC_PLU_PS = FOP(45, FMT_PS),
+ OPC_PUL_PS = FOP(46, FMT_PS),
+ OPC_PUU_PS = FOP(47, FMT_PS),
+ OPC_CMP_F_PS = FOP (48, FMT_PS),
+ OPC_CMP_UN_PS = FOP (49, FMT_PS),
+ OPC_CMP_EQ_PS = FOP (50, FMT_PS),
+ OPC_CMP_UEQ_PS = FOP (51, FMT_PS),
+ OPC_CMP_OLT_PS = FOP (52, FMT_PS),
+ OPC_CMP_ULT_PS = FOP (53, FMT_PS),
+ OPC_CMP_OLE_PS = FOP (54, FMT_PS),
+ OPC_CMP_ULE_PS = FOP (55, FMT_PS),
+ OPC_CMP_SF_PS = FOP (56, FMT_PS),
+ OPC_CMP_NGLE_PS = FOP (57, FMT_PS),
+ OPC_CMP_SEQ_PS = FOP (58, FMT_PS),
+ OPC_CMP_NGL_PS = FOP (59, FMT_PS),
+ OPC_CMP_LT_PS = FOP (60, FMT_PS),
+ OPC_CMP_NGE_PS = FOP (61, FMT_PS),
+ OPC_CMP_LE_PS = FOP (62, FMT_PS),
+ OPC_CMP_NGT_PS = FOP (63, FMT_PS),
+};
+
static void gen_cp1 (DisasContext *ctx, uint32_t opc, int rt, int fs)
{
const char *opn = "cp1 move";
@@ -5894,7 +6047,7 @@ static inline void gen_movcf_ps (int fs, int fd, int cc, int tf)
}
-static void gen_farith (DisasContext *ctx, uint32_t op1,
+static void gen_farith (DisasContext *ctx, enum fopcode op1,
int ft, int fs, int fd, int cc)
{
const char *opn = "farith";
@@ -5937,8 +6090,8 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
uint32_t func = ctx->opcode & 0x3f;
- switch (ctx->opcode & FOP(0x3f, 0x1f)) {
- case FOP(0, 16):
+ switch (op1) {
+ case OPC_ADD_S:
{
TCGv_i32 fp0 = tcg_temp_new_i32();
TCGv_i32 fp1 = tcg_temp_new_i32();
@@ -5953,7 +6106,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
opn = "add.s";
optype = BINOP;
break;
- case FOP(1, 16):
+ case OPC_SUB_S:
{
TCGv_i32 fp0 = tcg_temp_new_i32();
TCGv_i32 fp1 = tcg_temp_new_i32();
@@ -5968,7 +6121,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
opn = "sub.s";
optype = BINOP;
break;
- case FOP(2, 16):
+ case OPC_MUL_S:
{
TCGv_i32 fp0 = tcg_temp_new_i32();
TCGv_i32 fp1 = tcg_temp_new_i32();
@@ -5983,7 +6136,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
opn = "mul.s";
optype = BINOP;
break;
- case FOP(3, 16):
+ case OPC_DIV_S:
{
TCGv_i32 fp0 = tcg_temp_new_i32();
TCGv_i32 fp1 = tcg_temp_new_i32();
@@ -5998,7 +6151,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
opn = "div.s";
optype = BINOP;
break;
- case FOP(4, 16):
+ case OPC_SQRT_S:
{
TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -6009,7 +6162,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "sqrt.s";
break;
- case FOP(5, 16):
+ case OPC_ABS_S:
{
TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -6020,7 +6173,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "abs.s";
break;
- case FOP(6, 16):
+ case OPC_MOV_S:
{
TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -6030,7 +6183,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "mov.s";
break;
- case FOP(7, 16):
+ case OPC_NEG_S:
{
TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -6041,7 +6194,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "neg.s";
break;
- case FOP(8, 16):
+ case OPC_ROUND_L_S:
check_cp1_64bitmode(ctx);
{
TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6055,7 +6208,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "round.l.s";
break;
- case FOP(9, 16):
+ case OPC_TRUNC_L_S:
check_cp1_64bitmode(ctx);
{
TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6069,7 +6222,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "trunc.l.s";
break;
- case FOP(10, 16):
+ case OPC_CEIL_L_S:
check_cp1_64bitmode(ctx);
{
TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6083,7 +6236,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "ceil.l.s";
break;
- case FOP(11, 16):
+ case OPC_FLOOR_L_S:
check_cp1_64bitmode(ctx);
{
TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6097,7 +6250,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "floor.l.s";
break;
- case FOP(12, 16):
+ case OPC_ROUND_W_S:
{
TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -6108,7 +6261,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "round.w.s";
break;
- case FOP(13, 16):
+ case OPC_TRUNC_W_S:
{
TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -6119,7 +6272,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "trunc.w.s";
break;
- case FOP(14, 16):
+ case OPC_CEIL_W_S:
{
TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -6130,7 +6283,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "ceil.w.s";
break;
- case FOP(15, 16):
+ case OPC_FLOOR_W_S:
{
TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -6141,11 +6294,11 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "floor.w.s";
break;
- case FOP(17, 16):
+ case OPC_MOVCF_S:
gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
opn = "movcf.s";
break;
- case FOP(18, 16):
+ case OPC_MOVZ_S:
{
int l1 = gen_new_label();
TCGv_i32 fp0;
@@ -6161,7 +6314,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "movz.s";
break;
- case FOP(19, 16):
+ case OPC_MOVN_S:
{
int l1 = gen_new_label();
TCGv_i32 fp0;
@@ -6177,7 +6330,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "movn.s";
break;
- case FOP(21, 16):
+ case OPC_RECIP_S:
check_cop1x(ctx);
{
TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -6189,7 +6342,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "recip.s";
break;
- case FOP(22, 16):
+ case OPC_RSQRT_S:
check_cop1x(ctx);
{
TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -6201,7 +6354,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "rsqrt.s";
break;
- case FOP(28, 16):
+ case OPC_RECIP2_S:
check_cp1_64bitmode(ctx);
{
TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -6216,7 +6369,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "recip2.s";
break;
- case FOP(29, 16):
+ case OPC_RECIP1_S:
check_cp1_64bitmode(ctx);
{
TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -6228,7 +6381,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "recip1.s";
break;
- case FOP(30, 16):
+ case OPC_RSQRT1_S:
check_cp1_64bitmode(ctx);
{
TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -6240,7 +6393,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "rsqrt1.s";
break;
- case FOP(31, 16):
+ case OPC_RSQRT2_S:
check_cp1_64bitmode(ctx);
{
TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -6255,7 +6408,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "rsqrt2.s";
break;
- case FOP(33, 16):
+ case OPC_CVT_D_S:
check_cp1_registers(ctx, fd);
{
TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6269,7 +6422,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "cvt.d.s";
break;
- case FOP(36, 16):
+ case OPC_CVT_W_S:
{
TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -6280,7 +6433,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "cvt.w.s";
break;
- case FOP(37, 16):
+ case OPC_CVT_L_S:
check_cp1_64bitmode(ctx);
{
TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6294,7 +6447,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "cvt.l.s";
break;
- case FOP(38, 16):
+ case OPC_CVT_PS_S:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp64 = tcg_temp_new_i64();
@@ -6311,22 +6464,22 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "cvt.ps.s";
break;
- case FOP(48, 16):
- case FOP(49, 16):
- case FOP(50, 16):
- case FOP(51, 16):
- case FOP(52, 16):
- case FOP(53, 16):
- case FOP(54, 16):
- case FOP(55, 16):
- case FOP(56, 16):
- case FOP(57, 16):
- case FOP(58, 16):
- case FOP(59, 16):
- case FOP(60, 16):
- case FOP(61, 16):
- case FOP(62, 16):
- case FOP(63, 16):
+ case OPC_CMP_F_S:
+ case OPC_CMP_UN_S:
+ case OPC_CMP_EQ_S:
+ case OPC_CMP_UEQ_S:
+ case OPC_CMP_OLT_S:
+ case OPC_CMP_ULT_S:
+ case OPC_CMP_OLE_S:
+ case OPC_CMP_ULE_S:
+ case OPC_CMP_SF_S:
+ case OPC_CMP_NGLE_S:
+ case OPC_CMP_SEQ_S:
+ case OPC_CMP_NGL_S:
+ case OPC_CMP_LT_S:
+ case OPC_CMP_NGE_S:
+ case OPC_CMP_LE_S:
+ case OPC_CMP_NGT_S:
{
TCGv_i32 fp0 = tcg_temp_new_i32();
TCGv_i32 fp1 = tcg_temp_new_i32();
@@ -6345,7 +6498,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
tcg_temp_free_i32(fp1);
}
break;
- case FOP(0, 17):
+ case OPC_ADD_D:
check_cp1_registers(ctx, fs | ft | fd);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6361,7 +6514,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
opn = "add.d";
optype = BINOP;
break;
- case FOP(1, 17):
+ case OPC_SUB_D:
check_cp1_registers(ctx, fs | ft | fd);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6377,7 +6530,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
opn = "sub.d";
optype = BINOP;
break;
- case FOP(2, 17):
+ case OPC_MUL_D:
check_cp1_registers(ctx, fs | ft | fd);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6393,7 +6546,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
opn = "mul.d";
optype = BINOP;
break;
- case FOP(3, 17):
+ case OPC_DIV_D:
check_cp1_registers(ctx, fs | ft | fd);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6409,7 +6562,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
opn = "div.d";
optype = BINOP;
break;
- case FOP(4, 17):
+ case OPC_SQRT_D:
check_cp1_registers(ctx, fs | fd);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6421,7 +6574,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "sqrt.d";
break;
- case FOP(5, 17):
+ case OPC_ABS_D:
check_cp1_registers(ctx, fs | fd);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6433,7 +6586,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "abs.d";
break;
- case FOP(6, 17):
+ case OPC_MOV_D:
check_cp1_registers(ctx, fs | fd);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6444,7 +6597,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "mov.d";
break;
- case FOP(7, 17):
+ case OPC_NEG_D:
check_cp1_registers(ctx, fs | fd);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6456,7 +6609,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "neg.d";
break;
- case FOP(8, 17):
+ case OPC_ROUND_L_D:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6468,7 +6621,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "round.l.d";
break;
- case FOP(9, 17):
+ case OPC_TRUNC_L_D:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6480,7 +6633,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "trunc.l.d";
break;
- case FOP(10, 17):
+ case OPC_CEIL_L_D:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6492,7 +6645,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "ceil.l.d";
break;
- case FOP(11, 17):
+ case OPC_FLOOR_L_D:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6504,7 +6657,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "floor.l.d";
break;
- case FOP(12, 17):
+ case OPC_ROUND_W_D:
check_cp1_registers(ctx, fs);
{
TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6518,7 +6671,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "round.w.d";
break;
- case FOP(13, 17):
+ case OPC_TRUNC_W_D:
check_cp1_registers(ctx, fs);
{
TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6532,7 +6685,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "trunc.w.d";
break;
- case FOP(14, 17):
+ case OPC_CEIL_W_D:
check_cp1_registers(ctx, fs);
{
TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6546,7 +6699,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "ceil.w.d";
break;
- case FOP(15, 17):
+ case OPC_FLOOR_W_D:
check_cp1_registers(ctx, fs);
{
TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6560,11 +6713,11 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "floor.w.d";
break;
- case FOP(17, 17):
+ case OPC_MOVCF_D:
gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
opn = "movcf.d";
break;
- case FOP(18, 17):
+ case OPC_MOVZ_D:
{
int l1 = gen_new_label();
TCGv_i64 fp0;
@@ -6580,7 +6733,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "movz.d";
break;
- case FOP(19, 17):
+ case OPC_MOVN_D:
{
int l1 = gen_new_label();
TCGv_i64 fp0;
@@ -6596,7 +6749,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "movn.d";
break;
- case FOP(21, 17):
+ case OPC_RECIP_D:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6608,7 +6761,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "recip.d";
break;
- case FOP(22, 17):
+ case OPC_RSQRT_D:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6620,7 +6773,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "rsqrt.d";
break;
- case FOP(28, 17):
+ case OPC_RECIP2_D:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6635,7 +6788,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "recip2.d";
break;
- case FOP(29, 17):
+ case OPC_RECIP1_D:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6647,7 +6800,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "recip1.d";
break;
- case FOP(30, 17):
+ case OPC_RSQRT1_D:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6659,7 +6812,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "rsqrt1.d";
break;
- case FOP(31, 17):
+ case OPC_RSQRT2_D:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6674,22 +6827,22 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "rsqrt2.d";
break;
- case FOP(48, 17):
- case FOP(49, 17):
- case FOP(50, 17):
- case FOP(51, 17):
- case FOP(52, 17):
- case FOP(53, 17):
- case FOP(54, 17):
- case FOP(55, 17):
- case FOP(56, 17):
- case FOP(57, 17):
- case FOP(58, 17):
- case FOP(59, 17):
- case FOP(60, 17):
- case FOP(61, 17):
- case FOP(62, 17):
- case FOP(63, 17):
+ case OPC_CMP_F_D:
+ case OPC_CMP_UN_D:
+ case OPC_CMP_EQ_D:
+ case OPC_CMP_UEQ_D:
+ case OPC_CMP_OLT_D:
+ case OPC_CMP_ULT_D:
+ case OPC_CMP_OLE_D:
+ case OPC_CMP_ULE_D:
+ case OPC_CMP_SF_D:
+ case OPC_CMP_NGLE_D:
+ case OPC_CMP_SEQ_D:
+ case OPC_CMP_NGL_D:
+ case OPC_CMP_LT_D:
+ case OPC_CMP_NGE_D:
+ case OPC_CMP_LE_D:
+ case OPC_CMP_NGT_D:
{
TCGv_i64 fp0 = tcg_temp_new_i64();
TCGv_i64 fp1 = tcg_temp_new_i64();
@@ -6710,7 +6863,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
tcg_temp_free_i64(fp1);
}
break;
- case FOP(32, 17):
+ case OPC_CVT_S_D:
check_cp1_registers(ctx, fs);
{
TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6724,7 +6877,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "cvt.s.d";
break;
- case FOP(36, 17):
+ case OPC_CVT_W_D:
check_cp1_registers(ctx, fs);
{
TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6738,7 +6891,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "cvt.w.d";
break;
- case FOP(37, 17):
+ case OPC_CVT_L_D:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6750,7 +6903,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "cvt.l.d";
break;
- case FOP(32, 20):
+ case OPC_CVT_S_W:
{
TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -6761,7 +6914,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "cvt.s.w";
break;
- case FOP(33, 20):
+ case OPC_CVT_D_W:
check_cp1_registers(ctx, fd);
{
TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6775,7 +6928,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "cvt.d.w";
break;
- case FOP(32, 21):
+ case OPC_CVT_S_L:
check_cp1_64bitmode(ctx);
{
TCGv_i32 fp32 = tcg_temp_new_i32();
@@ -6789,7 +6942,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "cvt.s.l";
break;
- case FOP(33, 21):
+ case OPC_CVT_D_L:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6801,7 +6954,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "cvt.d.l";
break;
- case FOP(38, 20):
+ case OPC_CVT_PS_PW:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6813,7 +6966,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "cvt.ps.pw";
break;
- case FOP(0, 22):
+ case OPC_ADD_PS:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6828,7 +6981,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "add.ps";
break;
- case FOP(1, 22):
+ case OPC_SUB_PS:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6843,7 +6996,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "sub.ps";
break;
- case FOP(2, 22):
+ case OPC_MUL_PS:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6858,7 +7011,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "mul.ps";
break;
- case FOP(5, 22):
+ case OPC_ABS_PS:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6870,7 +7023,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "abs.ps";
break;
- case FOP(6, 22):
+ case OPC_MOV_PS:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6881,7 +7034,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "mov.ps";
break;
- case FOP(7, 22):
+ case OPC_NEG_PS:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6893,12 +7046,12 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "neg.ps";
break;
- case FOP(17, 22):
+ case OPC_MOVCF_PS:
check_cp1_64bitmode(ctx);
gen_movcf_ps(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
opn = "movcf.ps";
break;
- case FOP(18, 22):
+ case OPC_MOVZ_PS:
check_cp1_64bitmode(ctx);
{
int l1 = gen_new_label();
@@ -6914,7 +7067,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "movz.ps";
break;
- case FOP(19, 22):
+ case OPC_MOVN_PS:
check_cp1_64bitmode(ctx);
{
int l1 = gen_new_label();
@@ -6931,7 +7084,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "movn.ps";
break;
- case FOP(24, 22):
+ case OPC_ADDR_PS:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6946,7 +7099,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "addr.ps";
break;
- case FOP(26, 22):
+ case OPC_MULR_PS:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6961,7 +7114,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "mulr.ps";
break;
- case FOP(28, 22):
+ case OPC_RECIP2_PS:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6976,7 +7129,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "recip2.ps";
break;
- case FOP(29, 22):
+ case OPC_RECIP1_PS:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -6988,7 +7141,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "recip1.ps";
break;
- case FOP(30, 22):
+ case OPC_RSQRT1_PS:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -7000,7 +7153,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "rsqrt1.ps";
break;
- case FOP(31, 22):
+ case OPC_RSQRT2_PS:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -7015,7 +7168,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "rsqrt2.ps";
break;
- case FOP(32, 22):
+ case OPC_CVT_S_PU:
check_cp1_64bitmode(ctx);
{
TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -7027,7 +7180,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "cvt.s.pu";
break;
- case FOP(36, 22):
+ case OPC_CVT_PW_PS:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -7039,7 +7192,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "cvt.pw.ps";
break;
- case FOP(40, 22):
+ case OPC_CVT_S_PL:
check_cp1_64bitmode(ctx);
{
TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -7051,7 +7204,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "cvt.s.pl";
break;
- case FOP(44, 22):
+ case OPC_PLL_PS:
check_cp1_64bitmode(ctx);
{
TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -7066,7 +7219,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "pll.ps";
break;
- case FOP(45, 22):
+ case OPC_PLU_PS:
check_cp1_64bitmode(ctx);
{
TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -7081,7 +7234,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "plu.ps";
break;
- case FOP(46, 22):
+ case OPC_PUL_PS:
check_cp1_64bitmode(ctx);
{
TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -7096,7 +7249,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "pul.ps";
break;
- case FOP(47, 22):
+ case OPC_PUU_PS:
check_cp1_64bitmode(ctx);
{
TCGv_i32 fp0 = tcg_temp_new_i32();
@@ -7111,22 +7264,22 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
}
opn = "puu.ps";
break;
- case FOP(48, 22):
- case FOP(49, 22):
- case FOP(50, 22):
- case FOP(51, 22):
- case FOP(52, 22):
- case FOP(53, 22):
- case FOP(54, 22):
- case FOP(55, 22):
- case FOP(56, 22):
- case FOP(57, 22):
- case FOP(58, 22):
- case FOP(59, 22):
- case FOP(60, 22):
- case FOP(61, 22):
- case FOP(62, 22):
- case FOP(63, 22):
+ case OPC_CMP_F_PS:
+ case OPC_CMP_UN_PS:
+ case OPC_CMP_EQ_PS:
+ case OPC_CMP_UEQ_PS:
+ case OPC_CMP_OLT_PS:
+ case OPC_CMP_ULT_PS:
+ case OPC_CMP_OLE_PS:
+ case OPC_CMP_ULE_PS:
+ case OPC_CMP_SF_PS:
+ case OPC_CMP_NGLE_PS:
+ case OPC_CMP_SEQ_PS:
+ case OPC_CMP_NGL_PS:
+ case OPC_CMP_LT_PS:
+ case OPC_CMP_NGE_PS:
+ case OPC_CMP_LE_PS:
+ case OPC_CMP_NGT_PS:
check_cp1_64bitmode(ctx);
{
TCGv_i64 fp0 = tcg_temp_new_i64();
@@ -9298,7 +9451,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
case OPC_W_FMT:
case OPC_L_FMT:
case OPC_PS_FMT:
- gen_farith(ctx, MASK_CP1_FUNC(ctx->opcode), rt, rd, sa,
+ gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
(imm >> 8) & 0x7);
break;
default:
commit c61aaf7a388c4ad95d8b546fdb9267dc01183317
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Thu Jun 3 19:40:04 2010 +0200
tcg: get rid of DEF2 in tcg-opc.h
Now that tcg-opc.h is only used in TCG code, get rid of DEF2 in
tcg-opc.h.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h
index 5531da7..2a98fed 100644
--- a/tcg/tcg-opc.h
+++ b/tcg/tcg-opc.h
@@ -21,283 +21,284 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-#ifndef DEF2
-#define DEF2(name, oargs, iargs, cargs, flags) DEF(name, oargs + iargs + cargs)
-#endif
+
+/*
+ * DEF(name, oargs, iargs, cargs, flags)
+ */
/* predefined ops */
-DEF2(end, 0, 0, 0, 0) /* must be kept first */
-DEF2(nop, 0, 0, 0, 0)
-DEF2(nop1, 0, 0, 1, 0)
-DEF2(nop2, 0, 0, 2, 0)
-DEF2(nop3, 0, 0, 3, 0)
-DEF2(nopn, 0, 0, 1, 0) /* variable number of parameters */
+DEF(end, 0, 0, 0, 0) /* must be kept first */
+DEF(nop, 0, 0, 0, 0)
+DEF(nop1, 0, 0, 1, 0)
+DEF(nop2, 0, 0, 2, 0)
+DEF(nop3, 0, 0, 3, 0)
+DEF(nopn, 0, 0, 1, 0) /* variable number of parameters */
-DEF2(discard, 1, 0, 0, 0)
+DEF(discard, 1, 0, 0, 0)
-DEF2(set_label, 0, 0, 1, 0)
-DEF2(call, 0, 1, 2, TCG_OPF_SIDE_EFFECTS) /* variable number of parameters */
-DEF2(jmp, 0, 1, 0, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
-DEF2(br, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
+DEF(set_label, 0, 0, 1, 0)
+DEF(call, 0, 1, 2, TCG_OPF_SIDE_EFFECTS) /* variable number of parameters */
+DEF(jmp, 0, 1, 0, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
+DEF(br, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
-DEF2(mov_i32, 1, 1, 0, 0)
-DEF2(movi_i32, 1, 0, 1, 0)
-DEF2(setcond_i32, 1, 2, 1, 0)
+DEF(mov_i32, 1, 1, 0, 0)
+DEF(movi_i32, 1, 0, 1, 0)
+DEF(setcond_i32, 1, 2, 1, 0)
/* load/store */
-DEF2(ld8u_i32, 1, 1, 1, 0)
-DEF2(ld8s_i32, 1, 1, 1, 0)
-DEF2(ld16u_i32, 1, 1, 1, 0)
-DEF2(ld16s_i32, 1, 1, 1, 0)
-DEF2(ld_i32, 1, 1, 1, 0)
-DEF2(st8_i32, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
-DEF2(st16_i32, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
-DEF2(st_i32, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
+DEF(ld8u_i32, 1, 1, 1, 0)
+DEF(ld8s_i32, 1, 1, 1, 0)
+DEF(ld16u_i32, 1, 1, 1, 0)
+DEF(ld16s_i32, 1, 1, 1, 0)
+DEF(ld_i32, 1, 1, 1, 0)
+DEF(st8_i32, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
+DEF(st16_i32, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
+DEF(st_i32, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
/* arith */
-DEF2(add_i32, 1, 2, 0, 0)
-DEF2(sub_i32, 1, 2, 0, 0)
-DEF2(mul_i32, 1, 2, 0, 0)
+DEF(add_i32, 1, 2, 0, 0)
+DEF(sub_i32, 1, 2, 0, 0)
+DEF(mul_i32, 1, 2, 0, 0)
#ifdef TCG_TARGET_HAS_div_i32
-DEF2(div_i32, 1, 2, 0, 0)
-DEF2(divu_i32, 1, 2, 0, 0)
-DEF2(rem_i32, 1, 2, 0, 0)
-DEF2(remu_i32, 1, 2, 0, 0)
+DEF(div_i32, 1, 2, 0, 0)
+DEF(divu_i32, 1, 2, 0, 0)
+DEF(rem_i32, 1, 2, 0, 0)
+DEF(remu_i32, 1, 2, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_div2_i32
-DEF2(div2_i32, 2, 3, 0, 0)
-DEF2(divu2_i32, 2, 3, 0, 0)
+DEF(div2_i32, 2, 3, 0, 0)
+DEF(divu2_i32, 2, 3, 0, 0)
#endif
-DEF2(and_i32, 1, 2, 0, 0)
-DEF2(or_i32, 1, 2, 0, 0)
-DEF2(xor_i32, 1, 2, 0, 0)
+DEF(and_i32, 1, 2, 0, 0)
+DEF(or_i32, 1, 2, 0, 0)
+DEF(xor_i32, 1, 2, 0, 0)
/* shifts/rotates */
-DEF2(shl_i32, 1, 2, 0, 0)
-DEF2(shr_i32, 1, 2, 0, 0)
-DEF2(sar_i32, 1, 2, 0, 0)
+DEF(shl_i32, 1, 2, 0, 0)
+DEF(shr_i32, 1, 2, 0, 0)
+DEF(sar_i32, 1, 2, 0, 0)
#ifdef TCG_TARGET_HAS_rot_i32
-DEF2(rotl_i32, 1, 2, 0, 0)
-DEF2(rotr_i32, 1, 2, 0, 0)
+DEF(rotl_i32, 1, 2, 0, 0)
+DEF(rotr_i32, 1, 2, 0, 0)
#endif
-DEF2(brcond_i32, 0, 2, 2, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
+DEF(brcond_i32, 0, 2, 2, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
#if TCG_TARGET_REG_BITS == 32
-DEF2(add2_i32, 2, 4, 0, 0)
-DEF2(sub2_i32, 2, 4, 0, 0)
-DEF2(brcond2_i32, 0, 4, 2, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
-DEF2(mulu2_i32, 2, 2, 0, 0)
-DEF2(setcond2_i32, 1, 4, 1, 0)
+DEF(add2_i32, 2, 4, 0, 0)
+DEF(sub2_i32, 2, 4, 0, 0)
+DEF(brcond2_i32, 0, 4, 2, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
+DEF(mulu2_i32, 2, 2, 0, 0)
+DEF(setcond2_i32, 1, 4, 1, 0)
#endif
#ifdef TCG_TARGET_HAS_ext8s_i32
-DEF2(ext8s_i32, 1, 1, 0, 0)
+DEF(ext8s_i32, 1, 1, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_ext16s_i32
-DEF2(ext16s_i32, 1, 1, 0, 0)
+DEF(ext16s_i32, 1, 1, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_ext8u_i32
-DEF2(ext8u_i32, 1, 1, 0, 0)
+DEF(ext8u_i32, 1, 1, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_ext16u_i32
-DEF2(ext16u_i32, 1, 1, 0, 0)
+DEF(ext16u_i32, 1, 1, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_bswap16_i32
-DEF2(bswap16_i32, 1, 1, 0, 0)
+DEF(bswap16_i32, 1, 1, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_bswap32_i32
-DEF2(bswap32_i32, 1, 1, 0, 0)
+DEF(bswap32_i32, 1, 1, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_not_i32
-DEF2(not_i32, 1, 1, 0, 0)
+DEF(not_i32, 1, 1, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_neg_i32
-DEF2(neg_i32, 1, 1, 0, 0)
+DEF(neg_i32, 1, 1, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_andc_i32
-DEF2(andc_i32, 1, 2, 0, 0)
+DEF(andc_i32, 1, 2, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_orc_i32
-DEF2(orc_i32, 1, 2, 0, 0)
+DEF(orc_i32, 1, 2, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_eqv_i32
-DEF2(eqv_i32, 1, 2, 0, 0)
+DEF(eqv_i32, 1, 2, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_nand_i32
-DEF2(nand_i32, 1, 2, 0, 0)
+DEF(nand_i32, 1, 2, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_nor_i32
-DEF2(nor_i32, 1, 2, 0, 0)
+DEF(nor_i32, 1, 2, 0, 0)
#endif
#if TCG_TARGET_REG_BITS == 64
-DEF2(mov_i64, 1, 1, 0, 0)
-DEF2(movi_i64, 1, 0, 1, 0)
-DEF2(setcond_i64, 1, 2, 1, 0)
+DEF(mov_i64, 1, 1, 0, 0)
+DEF(movi_i64, 1, 0, 1, 0)
+DEF(setcond_i64, 1, 2, 1, 0)
/* load/store */
-DEF2(ld8u_i64, 1, 1, 1, 0)
-DEF2(ld8s_i64, 1, 1, 1, 0)
-DEF2(ld16u_i64, 1, 1, 1, 0)
-DEF2(ld16s_i64, 1, 1, 1, 0)
-DEF2(ld32u_i64, 1, 1, 1, 0)
-DEF2(ld32s_i64, 1, 1, 1, 0)
-DEF2(ld_i64, 1, 1, 1, 0)
-DEF2(st8_i64, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
-DEF2(st16_i64, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
-DEF2(st32_i64, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
-DEF2(st_i64, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
+DEF(ld8u_i64, 1, 1, 1, 0)
+DEF(ld8s_i64, 1, 1, 1, 0)
+DEF(ld16u_i64, 1, 1, 1, 0)
+DEF(ld16s_i64, 1, 1, 1, 0)
+DEF(ld32u_i64, 1, 1, 1, 0)
+DEF(ld32s_i64, 1, 1, 1, 0)
+DEF(ld_i64, 1, 1, 1, 0)
+DEF(st8_i64, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
+DEF(st16_i64, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
+DEF(st32_i64, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
+DEF(st_i64, 0, 2, 1, TCG_OPF_SIDE_EFFECTS)
/* arith */
-DEF2(add_i64, 1, 2, 0, 0)
-DEF2(sub_i64, 1, 2, 0, 0)
-DEF2(mul_i64, 1, 2, 0, 0)
+DEF(add_i64, 1, 2, 0, 0)
+DEF(sub_i64, 1, 2, 0, 0)
+DEF(mul_i64, 1, 2, 0, 0)
#ifdef TCG_TARGET_HAS_div_i64
-DEF2(div_i64, 1, 2, 0, 0)
-DEF2(divu_i64, 1, 2, 0, 0)
-DEF2(rem_i64, 1, 2, 0, 0)
-DEF2(remu_i64, 1, 2, 0, 0)
+DEF(div_i64, 1, 2, 0, 0)
+DEF(divu_i64, 1, 2, 0, 0)
+DEF(rem_i64, 1, 2, 0, 0)
+DEF(remu_i64, 1, 2, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_div2_i64
-DEF2(div2_i64, 2, 3, 0, 0)
-DEF2(divu2_i64, 2, 3, 0, 0)
+DEF(div2_i64, 2, 3, 0, 0)
+DEF(divu2_i64, 2, 3, 0, 0)
#endif
-DEF2(and_i64, 1, 2, 0, 0)
-DEF2(or_i64, 1, 2, 0, 0)
-DEF2(xor_i64, 1, 2, 0, 0)
+DEF(and_i64, 1, 2, 0, 0)
+DEF(or_i64, 1, 2, 0, 0)
+DEF(xor_i64, 1, 2, 0, 0)
/* shifts/rotates */
-DEF2(shl_i64, 1, 2, 0, 0)
-DEF2(shr_i64, 1, 2, 0, 0)
-DEF2(sar_i64, 1, 2, 0, 0)
+DEF(shl_i64, 1, 2, 0, 0)
+DEF(shr_i64, 1, 2, 0, 0)
+DEF(sar_i64, 1, 2, 0, 0)
#ifdef TCG_TARGET_HAS_rot_i64
-DEF2(rotl_i64, 1, 2, 0, 0)
-DEF2(rotr_i64, 1, 2, 0, 0)
+DEF(rotl_i64, 1, 2, 0, 0)
+DEF(rotr_i64, 1, 2, 0, 0)
#endif
-DEF2(brcond_i64, 0, 2, 2, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
+DEF(brcond_i64, 0, 2, 2, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
#ifdef TCG_TARGET_HAS_ext8s_i64
-DEF2(ext8s_i64, 1, 1, 0, 0)
+DEF(ext8s_i64, 1, 1, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_ext16s_i64
-DEF2(ext16s_i64, 1, 1, 0, 0)
+DEF(ext16s_i64, 1, 1, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_ext32s_i64
-DEF2(ext32s_i64, 1, 1, 0, 0)
+DEF(ext32s_i64, 1, 1, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_ext8u_i64
-DEF2(ext8u_i64, 1, 1, 0, 0)
+DEF(ext8u_i64, 1, 1, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_ext16u_i64
-DEF2(ext16u_i64, 1, 1, 0, 0)
+DEF(ext16u_i64, 1, 1, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_ext32u_i64
-DEF2(ext32u_i64, 1, 1, 0, 0)
+DEF(ext32u_i64, 1, 1, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_bswap16_i64
-DEF2(bswap16_i64, 1, 1, 0, 0)
+DEF(bswap16_i64, 1, 1, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_bswap32_i64
-DEF2(bswap32_i64, 1, 1, 0, 0)
+DEF(bswap32_i64, 1, 1, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_bswap64_i64
-DEF2(bswap64_i64, 1, 1, 0, 0)
+DEF(bswap64_i64, 1, 1, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_not_i64
-DEF2(not_i64, 1, 1, 0, 0)
+DEF(not_i64, 1, 1, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_neg_i64
-DEF2(neg_i64, 1, 1, 0, 0)
+DEF(neg_i64, 1, 1, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_andc_i64
-DEF2(andc_i64, 1, 2, 0, 0)
+DEF(andc_i64, 1, 2, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_orc_i64
-DEF2(orc_i64, 1, 2, 0, 0)
+DEF(orc_i64, 1, 2, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_eqv_i64
-DEF2(eqv_i64, 1, 2, 0, 0)
+DEF(eqv_i64, 1, 2, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_nand_i64
-DEF2(nand_i64, 1, 2, 0, 0)
+DEF(nand_i64, 1, 2, 0, 0)
#endif
#ifdef TCG_TARGET_HAS_nor_i64
-DEF2(nor_i64, 1, 2, 0, 0)
+DEF(nor_i64, 1, 2, 0, 0)
#endif
#endif
/* QEMU specific */
#if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
-DEF2(debug_insn_start, 0, 0, 2, 0)
+DEF(debug_insn_start, 0, 0, 2, 0)
#else
-DEF2(debug_insn_start, 0, 0, 1, 0)
+DEF(debug_insn_start, 0, 0, 1, 0)
#endif
-DEF2(exit_tb, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
-DEF2(goto_tb, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
+DEF(exit_tb, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
+DEF(goto_tb, 0, 0, 1, TCG_OPF_BB_END | TCG_OPF_SIDE_EFFECTS)
/* Note: even if TARGET_LONG_BITS is not defined, the INDEX_op
constants must be defined */
#if TCG_TARGET_REG_BITS == 32
#if TARGET_LONG_BITS == 32
-DEF2(qemu_ld8u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld8u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
#else
-DEF2(qemu_ld8u, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld8u, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
#endif
#if TARGET_LONG_BITS == 32
-DEF2(qemu_ld8s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld8s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
#else
-DEF2(qemu_ld8s, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld8s, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
#endif
#if TARGET_LONG_BITS == 32
-DEF2(qemu_ld16u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld16u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
#else
-DEF2(qemu_ld16u, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld16u, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
#endif
#if TARGET_LONG_BITS == 32
-DEF2(qemu_ld16s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld16s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
#else
-DEF2(qemu_ld16s, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld16s, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
#endif
#if TARGET_LONG_BITS == 32
-DEF2(qemu_ld32, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld32, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
#else
-DEF2(qemu_ld32, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld32, 1, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
#endif
#if TARGET_LONG_BITS == 32
-DEF2(qemu_ld64, 2, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld64, 2, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
#else
-DEF2(qemu_ld64, 2, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld64, 2, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
#endif
#if TARGET_LONG_BITS == 32
-DEF2(qemu_st8, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st8, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
#else
-DEF2(qemu_st8, 0, 3, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st8, 0, 3, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
#endif
#if TARGET_LONG_BITS == 32
-DEF2(qemu_st16, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st16, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
#else
-DEF2(qemu_st16, 0, 3, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st16, 0, 3, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
#endif
#if TARGET_LONG_BITS == 32
-DEF2(qemu_st32, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st32, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
#else
-DEF2(qemu_st32, 0, 3, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st32, 0, 3, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
#endif
#if TARGET_LONG_BITS == 32
-DEF2(qemu_st64, 0, 3, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st64, 0, 3, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
#else
-DEF2(qemu_st64, 0, 4, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st64, 0, 4, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
#endif
#else /* TCG_TARGET_REG_BITS == 32 */
-DEF2(qemu_ld8u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF2(qemu_ld8s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF2(qemu_ld16u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF2(qemu_ld16s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF2(qemu_ld32, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF2(qemu_ld32u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF2(qemu_ld32s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF2(qemu_ld64, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld8u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld8s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld16u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld16s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld32, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld32u, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld32s, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_ld64, 1, 1, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF2(qemu_st8, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF2(qemu_st16, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF2(qemu_st32, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
-DEF2(qemu_st64, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st8, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st16, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st32, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
+DEF(qemu_st64, 0, 2, 1, TCG_OPF_CALL_CLOBBER | TCG_OPF_SIDE_EFFECTS)
#endif /* TCG_TARGET_REG_BITS != 32 */
-#undef DEF2
+#undef DEF
diff --git a/tcg/tcg.c b/tcg/tcg.c
index b1fe470..30b5106 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -69,11 +69,9 @@ static void patch_reloc(uint8_t *code_ptr, int type,
tcg_target_long value, tcg_target_long addend);
static TCGOpDef tcg_op_defs[] = {
-#define DEF(s, n) { #s, 0, 0, n, n, 0 },
-#define DEF2(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags, 0 },
+#define DEF(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags, 0 },
#include "tcg-opc.h"
#undef DEF
-#undef DEF2
};
static TCGRegSet tcg_target_available_regs[2];
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 7fe7ab0..972df72 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -48,7 +48,7 @@ typedef uint64_t TCGRegSet;
#endif
typedef enum TCGOpcode {
-#define DEF(s, n) INDEX_op_ ## s,
+#define DEF(name, oargs, iargs, cargs, flags) INDEX_op_ ## name,
#include "tcg-opc.h"
#undef DEF
NB_OPS,
commit 239fda311a6f7784bc4f732795722c909b835651
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Thu Jun 3 19:29:31 2010 +0200
tcg: get rid of copy_size in TCGOpDef
copy_size is a left-over from the dyngen era, remove it.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/exec-all.h b/exec-all.h
index 4565dd0..a775582 100644
--- a/exec-all.h
+++ b/exec-all.h
@@ -80,7 +80,6 @@ void gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb);
void gen_pc_load(CPUState *env, struct TranslationBlock *tb,
unsigned long searched_pc, int pc_pos, void *puc);
-unsigned long code_gen_max_block_size(void);
void cpu_gen_init(void);
int cpu_gen_code(CPUState *env, struct TranslationBlock *tb,
int *gen_code_size_ptr);
diff --git a/exec.c b/exec.c
index bb3dcad..aedfda4 100644
--- a/exec.c
+++ b/exec.c
@@ -557,7 +557,7 @@ static void code_gen_alloc(unsigned long tb_size)
#endif /* !USE_STATIC_CODE_GEN_BUFFER */
map_exec(code_gen_prologue, sizeof(code_gen_prologue));
code_gen_buffer_max_size = code_gen_buffer_size -
- code_gen_max_block_size();
+ (TCG_MAX_OP_SIZE * OPC_MAX_SIZE);
code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE;
tbs = qemu_malloc(code_gen_max_blocks * sizeof(TranslationBlock));
}
diff --git a/tcg/tcg-opc.h b/tcg/tcg-opc.h
index 674c73a..5531da7 100644
--- a/tcg/tcg-opc.h
+++ b/tcg/tcg-opc.h
@@ -22,7 +22,7 @@
* THE SOFTWARE.
*/
#ifndef DEF2
-#define DEF2(name, oargs, iargs, cargs, flags) DEF(name, oargs + iargs + cargs, 0)
+#define DEF2(name, oargs, iargs, cargs, flags) DEF(name, oargs + iargs + cargs)
#endif
/* predefined ops */
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 3368d93..b1fe470 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -69,7 +69,7 @@ static void patch_reloc(uint8_t *code_ptr, int type,
tcg_target_long value, tcg_target_long addend);
static TCGOpDef tcg_op_defs[] = {
-#define DEF(s, n, copy_size) { #s, 0, 0, n, n, 0, copy_size },
+#define DEF(s, n) { #s, 0, 0, n, n, 0 },
#define DEF2(s, oargs, iargs, cargs, flags) { #s, oargs, iargs, cargs, iargs + oargs + cargs, flags, 0 },
#include "tcg-opc.h"
#undef DEF
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 9134700..7fe7ab0 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -48,7 +48,7 @@ typedef uint64_t TCGRegSet;
#endif
typedef enum TCGOpcode {
-#define DEF(s, n, copy_size) INDEX_op_ ## s,
+#define DEF(s, n) INDEX_op_ ## s,
#include "tcg-opc.h"
#undef DEF
NB_OPS,
@@ -422,7 +422,6 @@ typedef struct TCGOpDef {
const char *name;
uint8_t nb_oargs, nb_iargs, nb_cargs, nb_args;
uint8_t flags;
- uint16_t copy_size;
TCGArgConstraint *args_ct;
int *sorted_args;
#if defined(CONFIG_DEBUG_TCG)
diff --git a/translate-all.c b/translate-all.c
index 91cbbc4..efcfb9a 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -41,22 +41,6 @@ target_ulong gen_opc_pc[OPC_BUF_SIZE];
uint16_t gen_opc_icount[OPC_BUF_SIZE];
uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
-/* XXX: suppress that */
-unsigned long code_gen_max_block_size(void)
-{
- static unsigned long max;
-
- if (max == 0) {
- max = TCG_MAX_OP_SIZE;
-#define DEF(s, n, copy_size) max = copy_size > max? copy_size : max;
-#include "tcg-opc.h"
-#undef DEF
- max *= OPC_MAX_SIZE;
- }
-
- return max;
-}
-
void cpu_gen_init(void)
{
tcg_context_init(&tcg_ctx);
commit 590bf491a49670843ee902c47f7ab1de5e9acd06
Author: Alexander Graf <agraf at suse.de>
Date: Wed Jun 2 01:56:50 2010 +0200
Fix multiboot compilation
Commit dd4239d6574ca41c94fc0d0f77ddc728510ffc57 broke multiboot. It replaced the
instruction "rep insb (%dx), %es:(%edi)" by the binary output of
"addr32 rep insb (%dx), %es:(%di)".
Linuxboot calls the respective helper function in a code16 section. So the
original instruction was automatically translated to its "addr32" equivalent.
For multiboot, we're running in code32 so gcc didn't add the "addr32" which
breaks the instruction.
This patch splits that helper function in one which uses addr32 and one which
does not, so everyone's happy.
The good news is that nobody probably cared so far. The bundled multiboot.bin
binary was built before the change and is thus correct.
Please also put this patch into -stable.
Signed-off-by: Alexander Graf <agraf at suse.de>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/pc-bios/optionrom/linuxboot.S b/pc-bios/optionrom/linuxboot.S
index 8aebe51..c109363 100644
--- a/pc-bios/optionrom/linuxboot.S
+++ b/pc-bios/optionrom/linuxboot.S
@@ -106,10 +106,10 @@ copy_kernel:
/* We're now running in 16-bit CS, but 32-bit ES! */
/* Load kernel and initrd */
- read_fw_blob(FW_CFG_KERNEL)
- read_fw_blob(FW_CFG_INITRD)
- read_fw_blob(FW_CFG_CMDLINE)
- read_fw_blob(FW_CFG_SETUP)
+ read_fw_blob_addr32(FW_CFG_KERNEL)
+ read_fw_blob_addr32(FW_CFG_INITRD)
+ read_fw_blob_addr32(FW_CFG_CMDLINE)
+ read_fw_blob_addr32(FW_CFG_SETUP)
/* And now jump into Linux! */
mov $0, %eax
diff --git a/pc-bios/optionrom/optionrom.h b/pc-bios/optionrom/optionrom.h
index 4dcb906..fbdd48a 100644
--- a/pc-bios/optionrom/optionrom.h
+++ b/pc-bios/optionrom/optionrom.h
@@ -50,13 +50,7 @@
bswap %eax
.endm
-/*
- * Read a blob from the fw_cfg device.
- * Requires _ADDR, _SIZE and _DATA values for the parameter.
- *
- * Clobbers: %eax, %edx, %es, %ecx, %edi
- */
-#define read_fw_blob(var) \
+#define read_fw_blob_pre(var) \
read_fw var ## _ADDR; \
mov %eax, %edi; \
read_fw var ## _SIZE; \
@@ -65,10 +59,32 @@
mov $BIOS_CFG_IOPORT_CFG, %edx; \
outw %ax, (%dx); \
mov $BIOS_CFG_IOPORT_DATA, %dx; \
- cld; \
+ cld
+
+/*
+ * Read a blob from the fw_cfg device.
+ * Requires _ADDR, _SIZE and _DATA values for the parameter.
+ *
+ * Clobbers: %eax, %edx, %es, %ecx, %edi
+ */
+#define read_fw_blob(var) \
+ read_fw_blob_pre(var); \
/* old as(1) doesn't like this insn so emit the bytes instead: \
rep insb (%dx), %es:(%edi); \
*/ \
+ .dc.b 0xf3,0x6c
+
+/*
+ * Read a blob from the fw_cfg device in forced addr32 mode.
+ * Requires _ADDR, _SIZE and _DATA values for the parameter.
+ *
+ * Clobbers: %eax, %edx, %es, %ecx, %edi
+ */
+#define read_fw_blob_addr32(var) \
+ read_fw_blob_pre(var); \
+ /* old as(1) doesn't like this insn so emit the bytes instead: \
+ addr32 rep insb (%dx), %es:(%edi); \
+ */ \
.dc.b 0x67,0xf3,0x6c
#define OPTION_ROM_START \
commit 50e32ea8f31035877decc10f1075aa0e619e09cb
Author: Amit Shah <amit.shah at redhat.com>
Date: Tue Jun 8 21:13:58 2010 +0530
net: Fix hotplug with pci_add
The correct model type wasn't getting added when hotplugging nics with
pci_add.
Testcase: start VM with default nic type. In the qemu_monitor:
(qemu) pci_add auto nic model=virtio
This results in a nic hot-plug of the same nic type as the default.
This was broken in 5294e2c774f120e10b44652ac143abda356f44eb
Also changes the behaviour where no .init is defined for a
net_client_type. Previously, 0 was returned, which indicated the init
was successful and that 0 was the index into the nd_tables[] array.
Return -1, indicating unsuccessful init, in such a case.
Signed-off-by: Amit Shah <amit.shah at redhat.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/net.c b/net.c
index 378edfc..22f5cf1 100644
--- a/net.c
+++ b/net.c
@@ -1106,6 +1106,7 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
for (i = 0; net_client_types[i].type != NULL; i++) {
if (!strcmp(net_client_types[i].type, type)) {
VLANState *vlan = NULL;
+ int ret;
if (qemu_opts_validate(opts, &net_client_types[i].desc[0]) == -1) {
return -1;
@@ -1118,14 +1119,16 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
vlan = qemu_find_vlan(qemu_opt_get_number(opts, "vlan", 0), 1);
}
+ ret = -1;
if (net_client_types[i].init) {
- if (net_client_types[i].init(opts, mon, name, vlan) < 0) {
+ ret = net_client_types[i].init(opts, mon, name, vlan);
+ if (ret < 0) {
/* TODO push error reporting into init() methods */
qerror_report(QERR_DEVICE_INIT_FAILED, type);
return -1;
}
}
- return 0;
+ return ret;
}
}
commit e4d58b41f9fb6d7ea8281fe42fd5e00db2fd1455
Author: Richard Henderson <rth at twiddle.net>
Date: Wed Jun 2 17:26:56 2010 -0700
tcg: Make some tcg-target.c routines static.
Both tcg_target_init and tcg_target_qemu_prologue
are unused outside of tcg.c.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index b3169a9..a3af5b2 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1746,7 +1746,7 @@ static const TCGTargetOpDef arm_op_defs[] = {
{ -1 },
};
-void tcg_target_init(TCGContext *s)
+static void tcg_target_init(TCGContext *s)
{
#if !defined(CONFIG_USER_ONLY)
/* fail safe */
@@ -1809,7 +1809,7 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type,
tcg_out_movi32(s, COND_AL, ret, arg);
}
-void tcg_target_qemu_prologue(TCGContext *s)
+static void tcg_target_qemu_prologue(TCGContext *s)
{
/* There is no need to save r7, it is used to store the address
of the env structure and is not modified by GCC. */
diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index a5f2162..7f4653e 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -1600,7 +1600,7 @@ static int tcg_target_callee_save_regs[] = {
TCG_REG_R18
};
-void tcg_target_qemu_prologue(TCGContext *s)
+static void tcg_target_qemu_prologue(TCGContext *s)
{
int frame_size, i;
@@ -1652,7 +1652,7 @@ void tcg_target_qemu_prologue(TCGContext *s)
TCG_REG_SP, -frame_size, INSN_LDWM);
}
-void tcg_target_init(TCGContext *s)
+static void tcg_target_init(TCGContext *s)
{
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 8745ad1..147ba17 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -1430,7 +1430,7 @@ static int tcg_target_callee_save_regs[] = {
};
/* Generate global QEMU prologue and epilogue code */
-void tcg_target_qemu_prologue(TCGContext *s)
+static void tcg_target_qemu_prologue(TCGContext *s)
{
int i, frame_size, push_size, stack_addend;
@@ -1458,7 +1458,7 @@ void tcg_target_qemu_prologue(TCGContext *s)
tcg_out_opc(s, OPC_RET);
}
-void tcg_target_init(TCGContext *s)
+static void tcg_target_init(TCGContext *s)
{
#if !defined(CONFIG_USER_ONLY)
/* fail safe */
diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c
index 0d275e9..a0f3877 100644
--- a/tcg/ia64/tcg-target.c
+++ b/tcg/ia64/tcg-target.c
@@ -2266,7 +2266,7 @@ static const TCGTargetOpDef ia64_op_defs[] = {
};
/* Generate global QEMU prologue and epilogue code */
-void tcg_target_qemu_prologue(TCGContext *s)
+static void tcg_target_qemu_prologue(TCGContext *s)
{
int frame_size;
@@ -2321,7 +2321,7 @@ void tcg_target_qemu_prologue(TCGContext *s)
TCG_REG_B0));
}
-void tcg_target_init(TCGContext *s)
+static void tcg_target_init(TCGContext *s)
{
tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32],
0xffffffffffffffffull);
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index 8d9c12f..2af7a2e 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -1466,7 +1466,7 @@ static int tcg_target_callee_save_regs[] = {
};
/* Generate global QEMU prologue and epilogue code */
-void tcg_target_qemu_prologue(TCGContext *s)
+static void tcg_target_qemu_prologue(TCGContext *s)
{
int i, frame_size;
@@ -1498,7 +1498,7 @@ void tcg_target_qemu_prologue(TCGContext *s)
tcg_out_addi(s, TCG_REG_SP, frame_size);
}
-void tcg_target_init(TCGContext *s)
+static void tcg_target_init(TCGContext *s)
{
tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I32], 0xffffffff);
tcg_regset_set(tcg_target_call_clobber_regs,
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index ce078e4..2e5bb9f 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -900,7 +900,7 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
#endif
}
-void tcg_target_qemu_prologue (TCGContext *s)
+static void tcg_target_qemu_prologue (TCGContext *s)
{
int i, frame_size;
@@ -1885,7 +1885,7 @@ static const TCGTargetOpDef ppc_op_defs[] = {
{ -1 },
};
-void tcg_target_init(TCGContext *s)
+static void tcg_target_init(TCGContext *s)
{
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
tcg_regset_set32(tcg_target_call_clobber_regs, 0,
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 2d436a5..0483d6b 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -860,7 +860,7 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
#endif
}
-void tcg_target_qemu_prologue (TCGContext *s)
+static void tcg_target_qemu_prologue (TCGContext *s)
{
int i, frame_size;
#ifndef __APPLE__
@@ -1663,7 +1663,7 @@ static const TCGTargetOpDef ppc_op_defs[] = {
{ -1 },
};
-void tcg_target_init (TCGContext *s)
+static void tcg_target_init (TCGContext *s)
{
tcg_regset_set32 (tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
tcg_regset_set32 (tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff);
diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c
index 06b6db3..6f08aa4 100644
--- a/tcg/s390/tcg-target.c
+++ b/tcg/s390/tcg-target.c
@@ -84,12 +84,12 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_abort();
}
-void tcg_target_init(TCGContext *s)
+static void tcg_target_init(TCGContext *s)
{
/* gets called with KVM */
}
-void tcg_target_qemu_prologue(TCGContext *s)
+static void tcg_target_qemu_prologue(TCGContext *s)
{
/* gets called with KVM */
}
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 9f970cd..5f1353a 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -691,7 +691,7 @@ static void tcg_out_setcond2_i32(TCGContext *s, TCGCond cond, TCGArg ret,
#endif
/* Generate global QEMU prologue and epilogue code */
-void tcg_target_qemu_prologue(TCGContext *s)
+static void tcg_target_qemu_prologue(TCGContext *s)
{
tcg_out32(s, SAVE | INSN_RD(TCG_REG_O6) | INSN_RS1(TCG_REG_O6) |
INSN_IMM13(-TCG_TARGET_STACK_MINFRAME));
@@ -1533,7 +1533,7 @@ static const TCGTargetOpDef sparc_op_defs[] = {
{ -1 },
};
-void tcg_target_init(TCGContext *s)
+static void tcg_target_init(TCGContext *s)
{
tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
#if TCG_TARGET_REG_BITS == 64
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 32f9e17..3368d93 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -63,6 +63,8 @@
#error GUEST_BASE not supported on this host.
#endif
+static void tcg_target_init(TCGContext *s);
+static void tcg_target_qemu_prologue(TCGContext *s);
static void patch_reloc(uint8_t *code_ptr, int type,
tcg_target_long value, tcg_target_long addend);
diff --git a/tcg/tcg.h b/tcg/tcg.h
index d6cb9e7..9134700 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -435,9 +435,6 @@ typedef struct TCGTargetOpDef {
const char *args_ct_str[TCG_MAX_OP_ARGS];
} TCGTargetOpDef;
-void tcg_target_init(TCGContext *s);
-void tcg_target_qemu_prologue(TCGContext *s);
-
#define tcg_abort() \
do {\
fprintf(stderr, "%s:%d: tcg fatal error\n", __FILE__, __LINE__);\
diff --git a/tcg/x86_64/tcg-target.c b/tcg/x86_64/tcg-target.c
index 9844a57..490666e 100644
--- a/tcg/x86_64/tcg-target.c
+++ b/tcg/x86_64/tcg-target.c
@@ -1279,7 +1279,7 @@ static inline void tcg_out_pop(TCGContext *s, int reg)
}
/* Generate global QEMU prologue and epilogue code */
-void tcg_target_qemu_prologue(TCGContext *s)
+static void tcg_target_qemu_prologue(TCGContext *s)
{
int i, frame_size, push_size, stack_addend;
@@ -1417,7 +1417,7 @@ static const TCGTargetOpDef x86_64_op_defs[] = {
{ -1 },
};
-void tcg_target_init(TCGContext *s)
+static void tcg_target_init(TCGContext *s)
{
#if !defined(CONFIG_USER_ONLY)
/* fail safe */
commit 3b6dac34161bc0a342336072643c2f6d17e0ec45
Author: Richard Henderson <rth at twiddle.net>
Date: Wed Jun 2 17:26:55 2010 -0700
tcg: Add TYPE parameter to tcg_out_mov.
Mirror tcg_out_movi in having a TYPE parameter. This allows x86_64
to perform the move at the proper width, which may elide a REX prefix.
Introduce a TCG_TYPE_REG enumerator to represent the "native width"
of the host register, and to distinguish the usage from "pointer data"
as represented by the existing TCG_TYPE_PTR.
Update all targets to match.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index 8d23f47..b3169a9 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1798,7 +1798,7 @@ static void tcg_out_addi(TCGContext *s, int reg, tcg_target_long val)
}
}
-static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
+static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
{
tcg_out_dat_reg(s, COND_AL, ARITH_MOV, ret, 0, arg, SHIFT_IMM_LSL(0));
}
diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index 558c21f..a5f2162 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -338,7 +338,7 @@ static int tcg_target_const_match(tcg_target_long val,
/* supplied by libgcc */
extern void *__canonicalize_funcptr_for_compare(void *);
-static void tcg_out_mov(TCGContext *s, int ret, int arg)
+static void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
{
/* PA1.1 defines COPY as OR r,0,t; PA2.0 defines COPY as LDO 0(r),t
but hppa-dis.c is unaware of this definition */
@@ -498,7 +498,7 @@ static void tcg_out_ori(TCGContext *s, int ret, int arg, tcg_target_ulong m)
}
assert(bs1 == 32 || (1ul << bs1) > m);
- tcg_out_mov(s, ret, arg);
+ tcg_out_mov(s, TCG_TYPE_I32, ret, arg);
tcg_out32(s, INSN_DEPI | INSN_R2(ret) | INSN_IM5(-1)
| INSN_SHDEP_CP(31 - bs0) | INSN_DEP_LEN(bs1 - bs0));
}
@@ -528,7 +528,7 @@ static void tcg_out_andi(TCGContext *s, int ret, int arg, tcg_target_ulong m)
if (ls1 == 32) {
tcg_out_extr(s, ret, arg, 0, ls0, 0);
} else {
- tcg_out_mov(s, ret, arg);
+ tcg_out_mov(s, TCG_TYPE_I32, ret, arg);
tcg_out32(s, INSN_DEPI | INSN_R2(ret) | INSN_IM5(0)
| INSN_SHDEP_CP(31 - ls0) | INSN_DEP_LEN(ls1 - ls0));
}
@@ -608,7 +608,7 @@ static void tcg_out_rotr(TCGContext *s, int ret, int arg, int creg)
static void tcg_out_bswap16(TCGContext *s, int ret, int arg, int sign)
{
if (ret != arg) {
- tcg_out_mov(s, ret, arg); /* arg = xxAB */
+ tcg_out_mov(s, TCG_TYPE_I32, ret, arg); /* arg = xxAB */
}
tcg_out_dep(s, ret, ret, 16, 8); /* ret = xBAB */
tcg_out_extr(s, ret, ret, 8, 16, sign); /* ret = ..BA */
@@ -638,7 +638,7 @@ static void tcg_out_call(TCGContext *s, void *func)
tcg_out32(s, INSN_LDIL | INSN_R2(TCG_REG_R20) | reassemble_21(hi));
tcg_out32(s, INSN_BLE_SR4 | INSN_R2(TCG_REG_R20)
| reassemble_17(lo >> 2));
- tcg_out_mov(s, TCG_REG_RP, TCG_REG_R31);
+ tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_RP, TCG_REG_R31);
}
}
@@ -685,7 +685,7 @@ static void tcg_out_add2(TCGContext *s, int destl, int desth,
}
tcg_out_arith(s, desth, ah, bh, INSN_ADDC);
- tcg_out_mov(s, destl, tmp);
+ tcg_out_mov(s, TCG_TYPE_I32, destl, tmp);
}
static void tcg_out_sub2(TCGContext *s, int destl, int desth, int al, int ah,
@@ -706,7 +706,7 @@ static void tcg_out_sub2(TCGContext *s, int destl, int desth, int al, int ah,
}
tcg_out_arith(s, desth, ah, bh, INSN_SUBB);
- tcg_out_mov(s, destl, tmp);
+ tcg_out_mov(s, TCG_TYPE_I32, destl, tmp);
}
static void tcg_out_branch(TCGContext *s, int label_index, int nul)
@@ -869,7 +869,7 @@ static void tcg_out_setcond2(TCGContext *s, int cond, TCGArg ret,
break;
}
- tcg_out_mov(s, ret, scratch);
+ tcg_out_mov(s, TCG_TYPE_I32, ret, scratch);
}
#if defined(CONFIG_SOFTMMU)
@@ -1048,9 +1048,9 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
tcg_out_label(s, lab1, (tcg_target_long)s->code_ptr);
argreg = TCG_REG_R26;
- tcg_out_mov(s, argreg--, addrlo_reg);
+ tcg_out_mov(s, TCG_TYPE_I32, argreg--, addrlo_reg);
if (TARGET_LONG_BITS == 64) {
- tcg_out_mov(s, argreg--, addrhi_reg);
+ tcg_out_mov(s, TCG_TYPE_I32, argreg--, addrhi_reg);
}
tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index);
@@ -1071,11 +1071,11 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
break;
case 2:
case 2 | 4:
- tcg_out_mov(s, datalo_reg, TCG_REG_RET0);
+ tcg_out_mov(s, TCG_TYPE_I32, datalo_reg, TCG_REG_RET0);
break;
case 3:
- tcg_out_mov(s, datahi_reg, TCG_REG_RET0);
- tcg_out_mov(s, datalo_reg, TCG_REG_RET1);
+ tcg_out_mov(s, TCG_TYPE_I32, datahi_reg, TCG_REG_RET0);
+ tcg_out_mov(s, TCG_TYPE_I32, datalo_reg, TCG_REG_RET1);
break;
default:
tcg_abort();
@@ -1167,9 +1167,9 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
tcg_out_label(s, lab1, (tcg_target_long)s->code_ptr);
argreg = TCG_REG_R26;
- tcg_out_mov(s, argreg--, addrlo_reg);
+ tcg_out_mov(s, TCG_TYPE_I32, argreg--, addrlo_reg);
if (TARGET_LONG_BITS == 64) {
- tcg_out_mov(s, argreg--, addrhi_reg);
+ tcg_out_mov(s, TCG_TYPE_I32, argreg--, addrhi_reg);
}
switch(opc) {
@@ -1182,7 +1182,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index);
break;
case 2:
- tcg_out_mov(s, argreg--, datalo_reg);
+ tcg_out_mov(s, TCG_TYPE_I32, argreg--, datalo_reg);
tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index);
break;
case 3:
@@ -1196,8 +1196,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
argreg = TCG_REG_R20;
tcg_out_movi(s, TCG_TYPE_I32, argreg, mem_index);
}
- tcg_out_mov(s, TCG_REG_R23, datahi_reg);
- tcg_out_mov(s, TCG_REG_R24, datalo_reg);
+ tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R23, datahi_reg);
+ tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R24, datalo_reg);
tcg_out_st(s, TCG_TYPE_I32, argreg, TCG_REG_SP,
TCG_TARGET_CALL_STACK_OFFSET - 4);
break;
@@ -1637,7 +1637,7 @@ void tcg_target_qemu_prologue(TCGContext *s)
/* Jump to TB, and adjust R18 to be the return address. */
tcg_out32(s, INSN_BLE_SR4 | INSN_R2(TCG_REG_R26));
- tcg_out_mov(s, TCG_REG_R18, TCG_REG_R31);
+ tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_R18, TCG_REG_R31);
/* Restore callee saved registers. */
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_RP, TCG_REG_SP, -frame_size - 20);
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 3600c35..8745ad1 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -348,7 +348,7 @@ static inline void tgen_arithr(TCGContext *s, int subop, int dest, int src)
tcg_out_modrm(s, OPC_ARITH_GvEv + (subop << 3), dest, src);
}
-static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
+static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
{
if (arg != ret) {
tcg_out_modrm(s, OPC_MOVL_GvEv, ret, arg);
@@ -733,8 +733,8 @@ static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx,
const int r0 = TCG_REG_EAX;
const int r1 = TCG_REG_EDX;
- tcg_out_mov(s, r1, addrlo);
- tcg_out_mov(s, r0, addrlo);
+ tcg_out_mov(s, TCG_TYPE_I32, r1, addrlo);
+ tcg_out_mov(s, TCG_TYPE_I32, r0, addrlo);
tcg_out_shifti(s, SHIFT_SHR, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
@@ -748,7 +748,7 @@ static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx,
/* cmp 0(r1), r0 */
tcg_out_modrm_offset(s, OPC_CMP_GvEv, r0, r1, 0);
- tcg_out_mov(s, r0, addrlo);
+ tcg_out_mov(s, TCG_TYPE_I32, r0, addrlo);
/* jne label1 */
tcg_out8(s, OPC_JCC_short + JCC_JNE);
@@ -881,7 +881,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
/* EAX is already loaded. */
arg_idx = 1;
if (TARGET_LONG_BITS == 64) {
- tcg_out_mov(s, tcg_target_call_iarg_regs[arg_idx++],
+ tcg_out_mov(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[arg_idx++],
args[addrlo_idx + 1]);
}
tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[arg_idx],
@@ -903,16 +903,16 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
break;
case 2:
default:
- tcg_out_mov(s, data_reg, TCG_REG_EAX);
+ tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
break;
case 3:
if (data_reg == TCG_REG_EDX) {
/* xchg %edx, %eax */
tcg_out_opc(s, OPC_XCHG_ax_r32 + TCG_REG_EDX);
- tcg_out_mov(s, data_reg2, TCG_REG_EAX);
+ tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_EAX);
} else {
- tcg_out_mov(s, data_reg, TCG_REG_EAX);
- tcg_out_mov(s, data_reg2, TCG_REG_EDX);
+ tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_EAX);
+ tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_EDX);
}
break;
}
@@ -945,7 +945,7 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
break;
case 1:
if (bswap) {
- tcg_out_mov(s, scratch, datalo);
+ tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
tcg_out_rolw_8(s, scratch);
datalo = scratch;
}
@@ -955,7 +955,7 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
break;
case 2:
if (bswap) {
- tcg_out_mov(s, scratch, datalo);
+ tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
tcg_out_bswap32(s, scratch);
datalo = scratch;
}
@@ -963,10 +963,10 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
break;
case 3:
if (bswap) {
- tcg_out_mov(s, scratch, datahi);
+ tcg_out_mov(s, TCG_TYPE_I32, scratch, datahi);
tcg_out_bswap32(s, scratch);
tcg_out_st(s, TCG_TYPE_I32, scratch, base, ofs);
- tcg_out_mov(s, scratch, datalo);
+ tcg_out_mov(s, TCG_TYPE_I32, scratch, datalo);
tcg_out_bswap32(s, scratch);
tcg_out_st(s, TCG_TYPE_I32, scratch, base, ofs + 4);
} else {
@@ -1022,9 +1022,9 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
/* XXX: move that code at the end of the TB */
if (TARGET_LONG_BITS == 32) {
- tcg_out_mov(s, TCG_REG_EDX, data_reg);
+ tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_EDX, data_reg);
if (opc == 3) {
- tcg_out_mov(s, TCG_REG_ECX, data_reg2);
+ tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_ECX, data_reg2);
tcg_out_pushi(s, mem_index);
stack_adjust = 4;
} else {
@@ -1033,13 +1033,13 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
}
} else {
if (opc == 3) {
- tcg_out_mov(s, TCG_REG_EDX, args[addrlo_idx + 1]);
+ tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_EDX, args[addrlo_idx + 1]);
tcg_out_pushi(s, mem_index);
tcg_out_push(s, data_reg2);
tcg_out_push(s, data_reg);
stack_adjust = 12;
} else {
- tcg_out_mov(s, TCG_REG_EDX, args[addrlo_idx + 1]);
+ tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_EDX, args[addrlo_idx + 1]);
switch(opc) {
case 0:
tcg_out_ext8u(s, TCG_REG_ECX, data_reg);
@@ -1048,7 +1048,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
tcg_out_ext16u(s, TCG_REG_ECX, data_reg);
break;
case 2:
- tcg_out_mov(s, TCG_REG_ECX, data_reg);
+ tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_ECX, data_reg);
break;
}
tcg_out_pushi(s, mem_index);
diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c
index 905f48b..0d275e9 100644
--- a/tcg/ia64/tcg-target.c
+++ b/tcg/ia64/tcg-target.c
@@ -827,7 +827,8 @@ static inline void tcg_out_bundle(TCGContext *s, int template,
s->code_ptr += 16;
}
-static inline void tcg_out_mov(TCGContext *s, TCGArg ret, TCGArg arg)
+static inline void tcg_out_mov(TCGContext *s, TCGType type,
+ TCGArg ret, TCGArg arg)
{
tcg_out_bundle(s, mmI,
tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index f38eb28..8d9c12f 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -377,7 +377,7 @@ static inline void tcg_out_nop(TCGContext *s)
tcg_out32(s, 0);
}
-static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
+static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
{
tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
}
@@ -849,9 +849,9 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
/* slow path */
sp_args = TCG_REG_A0;
- tcg_out_mov(s, sp_args++, addr_reg1);
+ tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg1);
# if TARGET_LONG_BITS == 64
- tcg_out_mov(s, sp_args++, addr_reg2);
+ tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg2);
# endif
tcg_out_movi(s, TCG_TYPE_I32, sp_args++, mem_index);
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_T9, (tcg_target_long)qemu_ld_helpers[s_bits]);
@@ -872,11 +872,11 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
tcg_out_ext16s(s, data_reg1, TCG_REG_V0);
break;
case 2:
- tcg_out_mov(s, data_reg1, TCG_REG_V0);
+ tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
break;
case 3:
- tcg_out_mov(s, data_reg2, TCG_REG_V1);
- tcg_out_mov(s, data_reg1, TCG_REG_V0);
+ tcg_out_mov(s, TCG_TYPE_I32, data_reg2, TCG_REG_V1);
+ tcg_out_mov(s, TCG_TYPE_I32, data_reg1, TCG_REG_V0);
break;
default:
tcg_abort();
@@ -1035,9 +1035,9 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
/* slow path */
sp_args = TCG_REG_A0;
- tcg_out_mov(s, sp_args++, addr_reg1);
+ tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg1);
# if TARGET_LONG_BITS == 64
- tcg_out_mov(s, sp_args++, addr_reg2);
+ tcg_out_mov(s, TCG_TYPE_I32, sp_args++, addr_reg2);
# endif
switch(opc) {
case 0:
@@ -1047,12 +1047,12 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
tcg_out_opc_imm(s, OPC_ANDI, sp_args++, data_reg1, 0xffff);
break;
case 2:
- tcg_out_mov(s, sp_args++, data_reg1);
+ tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg1);
break;
case 3:
sp_args = (sp_args + 1) & ~1;
- tcg_out_mov(s, sp_args++, data_reg1);
- tcg_out_mov(s, sp_args++, data_reg2);
+ tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg1);
+ tcg_out_mov(s, TCG_TYPE_I32, sp_args++, data_reg2);
break;
default:
tcg_abort();
@@ -1165,7 +1165,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
break;
case INDEX_op_mov_i32:
- tcg_out_mov(s, args[0], args[1]);
+ tcg_out_mov(s, TCG_TYPE_I32, args[0], args[1]);
break;
case INDEX_op_movi_i32:
tcg_out_movi(s, TCG_TYPE_I32, args[0], args[1]);
@@ -1216,7 +1216,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_opc_reg(s, OPC_ADDU, args[1], args[3], args[5]);
}
tcg_out_opc_reg(s, OPC_ADDU, args[1], args[1], TCG_REG_T0);
- tcg_out_mov(s, args[0], TCG_REG_AT);
+ tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
break;
case INDEX_op_sub_i32:
if (const_args[2]) {
@@ -1238,7 +1238,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_opc_reg(s, OPC_SUBU, args[1], args[3], args[5]);
}
tcg_out_opc_reg(s, OPC_SUBU, args[1], args[1], TCG_REG_T0);
- tcg_out_mov(s, args[0], TCG_REG_AT);
+ tcg_out_mov(s, TCG_TYPE_I32, args[0], TCG_REG_AT);
break;
case INDEX_op_mul_i32:
tcg_out_opc_reg(s, OPC_MULT, 0, args[1], args[2]);
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index 2b85928..ce078e4 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -437,7 +437,7 @@ static const uint32_t tcg_to_bc[10] = {
[TCG_COND_GTU] = BC | BI (7, CR_GT) | BO_COND_TRUE,
};
-static void tcg_out_mov(TCGContext *s, int ret, int arg)
+static void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
{
tcg_out32 (s, OR | SAB (arg, ret, arg));
}
@@ -591,11 +591,11 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
/* slow path */
#if TARGET_LONG_BITS == 32
- tcg_out_mov (s, 3, addr_reg);
+ tcg_out_mov (s, TCG_TYPE_I32, 3, addr_reg);
tcg_out_movi (s, TCG_TYPE_I32, 4, mem_index);
#else
- tcg_out_mov (s, 3, addr_reg2);
- tcg_out_mov (s, 4, addr_reg);
+ tcg_out_mov (s, TCG_TYPE_I32, 3, addr_reg2);
+ tcg_out_mov (s, TCG_TYPE_I32, 4, addr_reg);
tcg_out_movi (s, TCG_TYPE_I32, 5, mem_index);
#endif
@@ -611,23 +611,23 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
case 1:
case 2:
if (data_reg != 3)
- tcg_out_mov (s, data_reg, 3);
+ tcg_out_mov (s, TCG_TYPE_I32, data_reg, 3);
break;
case 3:
if (data_reg == 3) {
if (data_reg2 == 4) {
- tcg_out_mov (s, 0, 4);
- tcg_out_mov (s, 4, 3);
- tcg_out_mov (s, 3, 0);
+ tcg_out_mov (s, TCG_TYPE_I32, 0, 4);
+ tcg_out_mov (s, TCG_TYPE_I32, 4, 3);
+ tcg_out_mov (s, TCG_TYPE_I32, 3, 0);
}
else {
- tcg_out_mov (s, data_reg2, 3);
- tcg_out_mov (s, 3, 4);
+ tcg_out_mov (s, TCG_TYPE_I32, data_reg2, 3);
+ tcg_out_mov (s, TCG_TYPE_I32, 3, 4);
}
}
else {
- if (data_reg != 4) tcg_out_mov (s, data_reg, 4);
- if (data_reg2 != 3) tcg_out_mov (s, data_reg2, 3);
+ if (data_reg != 4) tcg_out_mov (s, TCG_TYPE_I32, data_reg, 4);
+ if (data_reg2 != 3) tcg_out_mov (s, TCG_TYPE_I32, data_reg2, 3);
}
break;
}
@@ -705,7 +705,7 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
if (r0 == data_reg2) {
tcg_out32 (s, LWZ | RT (0) | RA (r0));
tcg_out32 (s, LWZ | RT (data_reg) | RA (r0) | 4);
- tcg_out_mov (s, data_reg2, 0);
+ tcg_out_mov (s, TCG_TYPE_I32, data_reg2, 0);
}
else {
tcg_out32 (s, LWZ | RT (data_reg2) | RA (r0));
@@ -787,11 +787,11 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
/* slow path */
#if TARGET_LONG_BITS == 32
- tcg_out_mov (s, 3, addr_reg);
+ tcg_out_mov (s, TCG_TYPE_I32, 3, addr_reg);
ir = 4;
#else
- tcg_out_mov (s, 3, addr_reg2);
- tcg_out_mov (s, 4, addr_reg);
+ tcg_out_mov (s, TCG_TYPE_I32, 3, addr_reg2);
+ tcg_out_mov (s, TCG_TYPE_I32, 4, addr_reg);
#ifdef TCG_TARGET_CALL_ALIGN_ARGS
ir = 5;
#else
@@ -817,14 +817,14 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
| ME (31)));
break;
case 2:
- tcg_out_mov (s, ir, data_reg);
+ tcg_out_mov (s, TCG_TYPE_I32, ir, data_reg);
break;
case 3:
#ifdef TCG_TARGET_CALL_ALIGN_ARGS
ir = 5;
#endif
- tcg_out_mov (s, ir++, data_reg2);
- tcg_out_mov (s, ir, data_reg);
+ tcg_out_mov (s, TCG_TYPE_I32, ir++, data_reg2);
+ tcg_out_mov (s, TCG_TYPE_I32, ir, data_reg);
break;
}
ir++;
@@ -1526,7 +1526,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
if (args[0] == args[2] || args[0] == args[3]) {
tcg_out32 (s, MULLW | TAB (0, args[2], args[3]));
tcg_out32 (s, MULHWU | TAB (args[1], args[2], args[3]));
- tcg_out_mov (s, args[0], 0);
+ tcg_out_mov (s, TCG_TYPE_I32, args[0], 0);
}
else {
tcg_out32 (s, MULLW | TAB (args[0], args[2], args[3]));
@@ -1584,7 +1584,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
case INDEX_op_rotr_i32:
if (const_args[2]) {
if (!args[2]) {
- tcg_out_mov (s, args[0], args[1]);
+ tcg_out_mov (s, TCG_TYPE_I32, args[0], args[1]);
}
else {
tcg_out32 (s, RLWINM
@@ -1612,7 +1612,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
if (args[0] == args[3] || args[0] == args[5]) {
tcg_out32 (s, ADDC | TAB (0, args[2], args[4]));
tcg_out32 (s, ADDE | TAB (args[1], args[3], args[5]));
- tcg_out_mov (s, args[0], 0);
+ tcg_out_mov (s, TCG_TYPE_I32, args[0], 0);
}
else {
tcg_out32 (s, ADDC | TAB (args[0], args[2], args[4]));
@@ -1623,7 +1623,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
if (args[0] == args[3] || args[0] == args[5]) {
tcg_out32 (s, SUBFC | TAB (0, args[4], args[2]));
tcg_out32 (s, SUBFE | TAB (args[1], args[5], args[3]));
- tcg_out_mov (s, args[0], 0);
+ tcg_out_mov (s, TCG_TYPE_I32, args[0], 0);
}
else {
tcg_out32 (s, SUBFC | TAB (args[0], args[4], args[2]));
@@ -1782,7 +1782,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
);
if (!a0) {
- tcg_out_mov (s, args[0], a0);
+ tcg_out_mov (s, TCG_TYPE_I32, args[0], a0);
}
}
break;
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 0b6c61f..2d436a5 100644
--- a/tcg/ppc64/tcg-target.c
+++ b/tcg/ppc64/tcg-target.c
@@ -435,7 +435,7 @@ static const uint32_t tcg_to_bc[10] = {
[TCG_COND_GTU] = BC | BI (7, CR_GT) | BO_COND_TRUE,
};
-static void tcg_out_mov (TCGContext *s, int ret, int arg)
+static void tcg_out_mov (TCGContext *s, TCGType type, int ret, int arg)
{
tcg_out32 (s, OR | SAB (arg, ret, arg));
}
@@ -644,7 +644,7 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
#endif
/* slow path */
- tcg_out_mov (s, 3, addr_reg);
+ tcg_out_mov (s, TCG_TYPE_I64, 3, addr_reg);
tcg_out_movi (s, TCG_TYPE_I64, 4, mem_index);
tcg_out_call (s, (tcg_target_long) qemu_ld_helpers[s_bits], 1);
@@ -664,7 +664,7 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
case 2:
case 3:
if (data_reg != 3)
- tcg_out_mov (s, data_reg, 3);
+ tcg_out_mov (s, TCG_TYPE_I64, data_reg, 3);
break;
}
label2_ptr = s->code_ptr;
@@ -746,7 +746,7 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
else tcg_out32 (s, LDX | TAB (data_reg, rbase, r0));
#else
if (bswap) {
- tcg_out_movi32 (s, 0, 4);
+ tcg_out_movi32 (s, TCG_TYPE_I64, 0, 4);
tcg_out32 (s, LWBRX | RT (data_reg) | RB (r0));
tcg_out32 (s, LWBRX | RT ( r1) | RA (r0));
tcg_out_rld (s, RLDIMI, data_reg, r1, 32, 0);
@@ -790,7 +790,7 @@ static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
#endif
/* slow path */
- tcg_out_mov (s, 3, addr_reg);
+ tcg_out_mov (s, TCG_TYPE_I64, 3, addr_reg);
tcg_out_rld (s, RLDICL, 4, data_reg, 0, 64 - (1 << (3 + opc)));
tcg_out_movi (s, TCG_TYPE_I64, 5, mem_index);
diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c
index 265194a..06b6db3 100644
--- a/tcg/s390/tcg-target.c
+++ b/tcg/s390/tcg-target.c
@@ -94,7 +94,7 @@ void tcg_target_qemu_prologue(TCGContext *s)
/* gets called with KVM */
}
-static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
+static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
{
tcg_abort();
}
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index e460d44..9f970cd 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -304,7 +304,7 @@ static void tcg_out_arithc(TCGContext *s, int rd, int rs1,
| (val2const ? INSN_IMM13(val2) : INSN_RS2(val2)));
}
-static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
+static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
{
tcg_out_arith(s, ret, arg, TCG_REG_G0, ARITH_OR);
}
@@ -795,7 +795,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
tcg_out32(s, 0);
/* mov (delay slot) */
- tcg_out_mov(s, arg0, addr_reg);
+ tcg_out_mov(s, TCG_TYPE_PTR, arg0, addr_reg);
/* mov */
tcg_out_movi(s, TCG_TYPE_I32, arg1, mem_index);
@@ -845,7 +845,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
case 3:
default:
/* mov */
- tcg_out_mov(s, data_reg, arg0);
+ tcg_out_mov(s, TCG_TYPE_REG, data_reg, arg0);
break;
}
@@ -1007,10 +1007,10 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
tcg_out32(s, 0);
/* mov (delay slot) */
- tcg_out_mov(s, arg0, addr_reg);
+ tcg_out_mov(s, TCG_TYPE_PTR, arg0, addr_reg);
/* mov */
- tcg_out_mov(s, arg1, data_reg);
+ tcg_out_mov(s, TCG_TYPE_REG, arg1, data_reg);
/* mov */
tcg_out_movi(s, TCG_TYPE_I32, arg2, mem_index);
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 880e7ce..32f9e17 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1547,7 +1547,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
reg = tcg_reg_alloc(s, arg_ct->u.regs, s->reserved_regs);
}
if (ts->reg != reg) {
- tcg_out_mov(s, reg, ts->reg);
+ tcg_out_mov(s, ots->type, reg, ts->reg);
}
}
} else if (ts->val_type == TEMP_VAL_MEM) {
@@ -1652,7 +1652,7 @@ static void tcg_reg_alloc_op(TCGContext *s,
/* allocate a new register matching the constraint
and move the temporary register into it */
reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
- tcg_out_mov(s, reg, ts->reg);
+ tcg_out_mov(s, ts->type, reg, ts->reg);
}
new_args[i] = reg;
const_args[i] = 0;
@@ -1734,7 +1734,7 @@ static void tcg_reg_alloc_op(TCGContext *s,
ts = &s->temps[args[i]];
reg = new_args[i];
if (ts->fixed_reg && ts->reg != reg) {
- tcg_out_mov(s, ts->reg, reg);
+ tcg_out_mov(s, ts->type, ts->reg, reg);
}
}
}
@@ -1820,7 +1820,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
tcg_reg_free(s, reg);
if (ts->val_type == TEMP_VAL_REG) {
if (ts->reg != reg) {
- tcg_out_mov(s, reg, ts->reg);
+ tcg_out_mov(s, ts->type, reg, ts->reg);
}
} else if (ts->val_type == TEMP_VAL_MEM) {
tcg_out_ld(s, ts->type, reg, ts->mem_reg, ts->mem_offset);
@@ -1849,7 +1849,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
reg = ts->reg;
if (!tcg_regset_test_reg(arg_ct->u.regs, reg)) {
reg = tcg_reg_alloc(s, arg_ct->u.regs, allocated_regs);
- tcg_out_mov(s, reg, ts->reg);
+ tcg_out_mov(s, ts->type, reg, ts->reg);
}
func_arg = reg;
tcg_regset_set_reg(allocated_regs, reg);
@@ -1908,7 +1908,7 @@ static int tcg_reg_alloc_call(TCGContext *s, const TCGOpDef *def,
assert(s->reg_to_temp[reg] == -1);
if (ts->fixed_reg) {
if (ts->reg != reg) {
- tcg_out_mov(s, ts->reg, reg);
+ tcg_out_mov(s, ts->type, ts->reg, reg);
}
} else {
if (ts->val_type == TEMP_VAL_REG)
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 5853823..d6cb9e7 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -101,11 +101,18 @@ typedef enum TCGType {
TCG_TYPE_I64,
TCG_TYPE_COUNT, /* number of different types */
+ /* An alias for the size of the host register. */
#if TCG_TARGET_REG_BITS == 32
- TCG_TYPE_PTR = TCG_TYPE_I32,
+ TCG_TYPE_REG = TCG_TYPE_I32,
#else
- TCG_TYPE_PTR = TCG_TYPE_I64,
+ TCG_TYPE_REG = TCG_TYPE_I64,
#endif
+
+ /* An alias for the size of the native pointer. We don't currently
+ support any hosts with 64-bit registers and 32-bit pointers. */
+ TCG_TYPE_PTR = TCG_TYPE_REG,
+
+ /* An alias for the size of the target "long", aka register. */
#if TARGET_LONG_BITS == 64
TCG_TYPE_TL = TCG_TYPE_I64,
#else
diff --git a/tcg/x86_64/tcg-target.c b/tcg/x86_64/tcg-target.c
index 3892f75..9844a57 100644
--- a/tcg/x86_64/tcg-target.c
+++ b/tcg/x86_64/tcg-target.c
@@ -354,9 +354,10 @@ static void tcg_out_modrm_offset2(TCGContext *s, int opc, int r, int rm,
}
#endif
-static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
+static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
{
- tcg_out_modrm(s, 0x8b | P_REXW, ret, arg);
+ int rexw = (type == TCG_TYPE_I64 ? P_REXW : 0);
+ tcg_out_modrm(s, 0x8b | rexw, ret, arg);
}
static inline void tcg_out_movi(TCGContext *s, TCGType type,
@@ -577,11 +578,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
rexw = P_REXW;
#endif
#if defined(CONFIG_SOFTMMU)
- /* mov */
- tcg_out_modrm(s, 0x8b | rexw, r1, addr_reg);
-
- /* mov */
- tcg_out_modrm(s, 0x8b | rexw, r0, addr_reg);
+ tcg_out_mov(s, TCG_TYPE_TL, r1, addr_reg);
+ tcg_out_mov(s, TCG_TYPE_TL, r0, addr_reg);
tcg_out_modrm(s, 0xc1 | rexw, 5, r1); /* shr $x, r1 */
tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
@@ -599,8 +597,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
/* cmp 0(r1), r0 */
tcg_out_modrm_offset(s, 0x3b | rexw, r0, r1, 0);
- /* mov */
- tcg_out_modrm(s, 0x8b | rexw, r0, addr_reg);
+ tcg_out_mov(s, TCG_TYPE_TL, r0, addr_reg);
/* je label1 */
tcg_out8(s, 0x70 + JCC_JE);
@@ -634,11 +631,10 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
break;
case 2:
default:
- /* movl */
- tcg_out_modrm(s, 0x8b, data_reg, TCG_REG_RAX);
+ tcg_out_mov(s, TCG_TYPE_I32, data_reg, TCG_REG_RAX);
break;
case 3:
- tcg_out_mov(s, data_reg, TCG_REG_RAX);
+ tcg_out_mov(s, TCG_TYPE_I64, data_reg, TCG_REG_RAX);
break;
}
@@ -772,11 +768,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
rexw = P_REXW;
#endif
#if defined(CONFIG_SOFTMMU)
- /* mov */
- tcg_out_modrm(s, 0x8b | rexw, r1, addr_reg);
-
- /* mov */
- tcg_out_modrm(s, 0x8b | rexw, r0, addr_reg);
+ tcg_out_mov(s, TCG_TYPE_TL, r1, addr_reg);
+ tcg_out_mov(s, TCG_TYPE_TL, r0, addr_reg);
tcg_out_modrm(s, 0xc1 | rexw, 5, r1); /* shr $x, r1 */
tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
@@ -793,10 +786,9 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
/* cmp 0(r1), r0 */
tcg_out_modrm_offset(s, 0x3b | rexw, r0, r1, 0);
-
- /* mov */
- tcg_out_modrm(s, 0x8b | rexw, r0, addr_reg);
-
+
+ tcg_out_mov(s, TCG_TYPE_TL, r0, addr_reg);
+
/* je label1 */
tcg_out8(s, 0x70 + JCC_JE);
label1_ptr = s->code_ptr;
@@ -813,12 +805,11 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
tcg_out_modrm(s, 0xb7 | P_EXT, TCG_REG_RSI, data_reg);
break;
case 2:
- /* movl */
- tcg_out_modrm(s, 0x8b, TCG_REG_RSI, data_reg);
+ tcg_out_mov(s, TCG_TYPE_I32, TCG_REG_RSI, data_reg);
break;
default:
case 3:
- tcg_out_mov(s, TCG_REG_RSI, data_reg);
+ tcg_out_mov(s, TCG_TYPE_I64, TCG_REG_RSI, data_reg);
break;
}
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_RDX, mem_index);
@@ -863,7 +854,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
break;
case 1:
if (bswap) {
- tcg_out_modrm(s, 0x8b, r1, data_reg); /* movl */
+ tcg_out_mov(s, TCG_TYPE_I32, r1, data_reg);
tcg_out8(s, 0x66); /* rolw $8, %ecx */
tcg_out_modrm(s, 0xc1, 0, r1);
tcg_out8(s, 8);
@@ -875,7 +866,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
break;
case 2:
if (bswap) {
- tcg_out_modrm(s, 0x8b, r1, data_reg); /* movl */
+ tcg_out_mov(s, TCG_TYPE_I32, r1, data_reg);
/* bswap data_reg */
tcg_out_opc(s, (0xc8 + r1) | P_EXT, 0, r1, 0);
data_reg = r1;
@@ -885,7 +876,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
break;
case 3:
if (bswap) {
- tcg_out_mov(s, r1, data_reg);
+ tcg_out_mov(s, TCG_TYPE_I64, r1, data_reg);
/* bswap data_reg */
tcg_out_opc(s, (0xc8 + r1) | P_EXT | P_REXW, 0, r1, 0);
data_reg = r1;
commit 26ebe46848ecb2462cc53d4de20ac6590709643b
Author: Nathan Froyd <froydnj at codesourcery.com>
Date: Mon May 24 09:19:35 2010 -0700
target-mips: break out [ls][wd]c1 and rdhwr insn generation
Signed-off-by: Nathan Froyd <froydnj at codesourcery.com>
Acked-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-mips/translate.c b/target-mips/translate.c
index c95ecb1..2075d09 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -1220,6 +1220,17 @@ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
tcg_temp_free(t0);
}
+static void gen_cop1_ldst(CPUState *env, DisasContext *ctx,
+ uint32_t op, int rt, int rs, int16_t imm)
+{
+ if (env->CP0_Config1 & (1 << CP0C1_FP)) {
+ check_cp1_enabled(ctx);
+ gen_flt_ldst(ctx, op, rt, rs, imm);
+ } else {
+ generate_exception_err(ctx, EXCP_CpU, 1);
+ }
+}
+
/* Arithmetic with immediate operand */
static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
int rt, int rs, int16_t imm)
@@ -7528,6 +7539,52 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
fregnames[fs], fregnames[ft]);
}
+static void
+gen_rdhwr (CPUState *env, DisasContext *ctx, int rt, int rd)
+{
+ TCGv t0;
+
+ check_insn(env, ctx, ISA_MIPS32R2);
+ t0 = tcg_temp_new();
+
+ switch (rd) {
+ case 0:
+ save_cpu_state(ctx, 1);
+ gen_helper_rdhwr_cpunum(t0);
+ gen_store_gpr(t0, rt);
+ break;
+ case 1:
+ save_cpu_state(ctx, 1);
+ gen_helper_rdhwr_synci_step(t0);
+ gen_store_gpr(t0, rt);
+ break;
+ case 2:
+ save_cpu_state(ctx, 1);
+ gen_helper_rdhwr_cc(t0);
+ gen_store_gpr(t0, rt);
+ break;
+ case 3:
+ save_cpu_state(ctx, 1);
+ gen_helper_rdhwr_ccres(t0);
+ gen_store_gpr(t0, rt);
+ break;
+ case 29:
+#if defined(CONFIG_USER_ONLY)
+ tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
+ gen_store_gpr(t0, rt);
+ break;
+#else
+ /* XXX: Some CPUs implement this in hardware.
+ Not supported yet. */
+#endif
+ default: /* Invalid */
+ MIPS_INVAL("rdhwr");
+ generate_exception(ctx, EXCP_RI);
+ break;
+ }
+ tcg_temp_free(t0);
+}
+
static void handle_delay_slot (CPUState *env, DisasContext *ctx,
int insn_bytes)
{
@@ -8999,47 +9056,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
gen_bshfl(ctx, op2, rt, rd);
break;
case OPC_RDHWR:
- check_insn(env, ctx, ISA_MIPS32R2);
- {
- TCGv t0 = tcg_temp_new();
-
- switch (rd) {
- case 0:
- save_cpu_state(ctx, 1);
- gen_helper_rdhwr_cpunum(t0);
- gen_store_gpr(t0, rt);
- break;
- case 1:
- save_cpu_state(ctx, 1);
- gen_helper_rdhwr_synci_step(t0);
- gen_store_gpr(t0, rt);
- break;
- case 2:
- save_cpu_state(ctx, 1);
- gen_helper_rdhwr_cc(t0);
- gen_store_gpr(t0, rt);
- break;
- case 3:
- save_cpu_state(ctx, 1);
- gen_helper_rdhwr_ccres(t0);
- gen_store_gpr(t0, rt);
- break;
- case 29:
-#if defined(CONFIG_USER_ONLY)
- tcg_gen_ld_tl(t0, cpu_env, offsetof(CPUState, tls_value));
- gen_store_gpr(t0, rt);
- break;
-#else
- /* XXX: Some CPUs implement this in hardware.
- Not supported yet. */
-#endif
- default: /* Invalid */
- MIPS_INVAL("rdhwr");
- generate_exception(ctx, EXCP_RI);
- break;
- }
- tcg_temp_free(t0);
- }
+ gen_rdhwr(env, ctx, rt, rd);
break;
case OPC_FORK:
check_insn(env, ctx, ASE_MT);
@@ -9242,12 +9259,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
case OPC_LDC1:
case OPC_SWC1:
case OPC_SDC1:
- if (env->CP0_Config1 & (1 << CP0C1_FP)) {
- check_cp1_enabled(ctx);
- gen_flt_ldst(ctx, op, rt, rs, imm);
- } else {
- generate_exception_err(ctx, EXCP_CpU, 1);
- }
+ gen_cop1_ldst(env, ctx, op, rt, rs, imm);
break;
case OPC_CP1:
commit d44cff22047651aefe8ea68f173e1dcbb56b07a7
Author: Richard Henderson <rth at twiddle.net>
Date: Fri May 21 10:04:46 2010 -0700
Fix --enable-user-pie compilation.
We forgot to propagate -fpie to the libdis-user directory.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Acked-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/configure b/configure
index 653c8d2..72d8924 100755
--- a/configure
+++ b/configure
@@ -2355,6 +2355,9 @@ for d in libdis libdis-user; do
ln -s $source_path/Makefile.dis $d/Makefile
echo > $d/config.mak
done
+if test "$static" = "no" -a "$user_pie" = "yes" ; then
+ echo "QEMU_CFLAGS+=-fpie" > libdis-user/config.mak
+fi
for target in $target_list; do
target_dir="$target"
commit 940cda94dc01e955b6008c47b782817a1ed3b201
Author: Michael S. Tsirkin <mst at redhat.com>
Date: Sun Jun 6 18:53:10 2010 +0300
virtio-net: truncating packet
virtio net attempts to peek into virtio queue to
determine that we have enough space for the complete
packet to fit. However, it fails to account for space
consumed by virtio net header when it does this,
under stress this results in a failure
with the message 'truncating packet'.
redhat bz 591494.
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index 6a9d560..06ba481 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -532,16 +532,17 @@ static ssize_t virtio_net_receive(VLANClientState *nc, const uint8_t *buf, size_
if (!virtio_net_can_receive(&n->nic->nc))
return -1;
- if (!virtio_net_has_buffers(n, size))
+ /* hdr_len refers to the header we supply to the guest */
+ hdr_len = n->mergeable_rx_bufs ?
+ sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr);
+
+
+ if (!virtio_net_has_buffers(n, size + hdr_len))
return 0;
if (!receive_filter(n, buf, size))
return size;
- /* hdr_len refers to the header we supply to the guest */
- hdr_len = n->mergeable_rx_bufs ?
- sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr);
-
offset = i = 0;
while (offset < size) {
@@ -555,7 +556,9 @@ static ssize_t virtio_net_receive(VLANClientState *nc, const uint8_t *buf, size_
virtqueue_pop(n->rx_vq, &elem) == 0) {
if (i == 0)
return -1;
- fprintf(stderr, "virtio-net truncating packet\n");
+ fprintf(stderr, "virtio-net truncating packet: "
+ "offset %zd, size %zd, hdr_len %zd\n",
+ offset, size, hdr_len);
exit(1);
}
commit fd1dc858370d9a9ac7ea2512812c3a152ee6484b
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date: Mon Jun 7 11:54:27 2010 +0200
microblaze: Make MSR_UM and MSR_VM part of the tb flags
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at petalogix.com>
diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index 3316797..ff8c8c8 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -217,8 +217,7 @@ typedef struct CPUMBState {
#define DRTB_FLAG (1 << 18)
#define D_FLAG (1 << 19) /* Bit in ESR. */
/* TB dependant CPUState. */
-#define IFLAGS_TB_MASK (D_FLAG | IMM_FLAG | DRTI_FLAG \
- | DRTE_FLAG | DRTB_FLAG | MSR_EE_FLAG)
+#define IFLAGS_TB_MASK (D_FLAG | IMM_FLAG | DRTI_FLAG | DRTE_FLAG | DRTB_FLAG)
uint32_t iflags;
struct {
@@ -323,8 +322,8 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
{
*pc = env->sregs[SR_PC];
*cs_base = 0;
- env->iflags |= env->sregs[SR_MSR] & MSR_EE;
- *flags = env->iflags & IFLAGS_TB_MASK;
+ *flags = (env->iflags & IFLAGS_TB_MASK) |
+ (env->sregs[SR_MSR] & (MSR_UM | MSR_VM | MSR_EE));
}
#if !defined(CONFIG_USER_ONLY)
commit 7375c86f0b1b1ac6f71a8728c6416c99850b30d9
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date: Mon Jun 7 11:53:09 2010 +0200
petlogix-3adsp: Tweak displacement of cmdline and fdt blob.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at petalogix.com>
diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
index 93344b1..cdde991 100644
--- a/hw/petalogix_s3adsp1800_mmu.c
+++ b/hw/petalogix_s3adsp1800_mmu.c
@@ -185,12 +185,12 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
boot_info.bootstrap_pc = ddr_base;
}
- boot_info.cmdline = ddr_base + kernel_size + 8192;
+ boot_info.cmdline = high + 4096;
if (kernel_cmdline && strlen(kernel_cmdline)) {
pstrcpy_targphys("cmdline", boot_info.cmdline, 256, kernel_cmdline);
}
/* Provide a device-tree. */
- boot_info.fdt = boot_info.cmdline + 256;
+ boot_info.fdt = boot_info.cmdline + 4096;
petalogix_load_device_tree(boot_info.fdt, ram_size,
0, 0,
kernel_cmdline);
commit 0ffbba357c557d9fa5caf9476878a4b9c155a614
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Fri Jun 4 20:01:07 2010 +0000
migration-exec: fix OpenBSD build warning
Add include directives to get WIFEXITED() and WEXITSTATUS() macros defined.
Fixes warnings:
CC migration-exec.o
/src/qemu/migration-exec.c: In function `exec_close':
/src/qemu/migration-exec.c:53: warning: implicit declaration of function `WIFEXITED'
/src/qemu/migration-exec.c:54: warning: implicit declaration of function `WEXITSTATUS'
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/migration-exec.c b/migration-exec.c
index 93bde62..a8813b4 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -20,6 +20,8 @@
#include "sysemu.h"
#include "buffered_file.h"
#include "block.h"
+#include <sys/types.h>
+#include <sys/wait.h>
//#define DEBUG_MIGRATION_EXEC
commit 8c0e6340fb53cb3f94c0f43abb19eb485f30840e
Author: Paolo Bonzini <pbonzini at redhat.com>
Date: Fri Jun 4 16:27:33 2010 +0200
target-i386: fix decoding of negative 4-byte displacements
Negative four byte displacements need to be sign-extended after
c086b783eb7a578993d6d2ab62c4c2666800b63d. Do so.
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Acked-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 38c6016..708b0a1 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -2016,7 +2016,7 @@ static void gen_lea_modrm(DisasContext *s, int modrm, int *reg_ptr, int *offset_
break;
default:
case 2:
- disp = ldl_code(s->pc);
+ disp = (int32_t)ldl_code(s->pc);
s->pc += 4;
break;
}
commit 653dbec7c97cb51d19636423902719e5850da265
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date: Wed Jun 2 17:46:31 2010 -0300
block: Fix serial number assignment
We should use 'dinfo->serial' length, 'serial' is a pointer, so
the serial number length is currently limited to the pointer size.
This fixes https://bugs.launchpad.net/qemu/+bug/584143 and is also
valid for stable.
Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/blockdev.c b/blockdev.c
index bd9783a..642ce75 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -422,7 +422,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
dinfo->on_write_error = on_write_error;
dinfo->opts = opts;
if (serial)
- strncpy(dinfo->serial, serial, sizeof(serial));
+ strncpy(dinfo->serial, serial, sizeof(dinfo->serial) - 1);
QTAILQ_INSERT_TAIL(&drives, dinfo, next);
switch(type) {
commit 666daa68234b5b1758652633cab07d5ca6046a5b
Author: Markus Armbruster <armbru at redhat.com>
Date: Wed Jun 2 18:48:27 2010 +0200
blockdev: Collect block device code in new blockdev.c
Anything that moves hundreds of lines out of vl.c can't be all bad.
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/Makefile.objs b/Makefile.objs
index 9796dcb..54dec26 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -44,7 +44,7 @@ fsdev-obj-$(CONFIG_LINUX) += $(addprefix fsdev/, $(fsdev-nested-y))
# system emulation, i.e. a single QEMU executable should support all
# CPUs and machines.
-common-obj-y = $(block-obj-y)
+common-obj-y = $(block-obj-y) blockdev.o
common-obj-y += $(net-obj-y)
common-obj-y += $(qobject-obj-y)
common-obj-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX))
diff --git a/blockdev.c b/blockdev.c
new file mode 100644
index 0000000..bd9783a
--- /dev/null
+++ b/blockdev.c
@@ -0,0 +1,600 @@
+/*
+ * QEMU host block devices
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later. See the COPYING file in the top-level directory.
+ */
+
+#include "block.h"
+#include "blockdev.h"
+#include "monitor.h"
+#include "qerror.h"
+#include "qemu-option.h"
+#include "qemu-config.h"
+#include "sysemu.h"
+
+struct drivelist drives = QTAILQ_HEAD_INITIALIZER(drives);
+
+QemuOpts *drive_add(const char *file, const char *fmt, ...)
+{
+ va_list ap;
+ char optstr[1024];
+ QemuOpts *opts;
+
+ va_start(ap, fmt);
+ vsnprintf(optstr, sizeof(optstr), fmt, ap);
+ va_end(ap);
+
+ opts = qemu_opts_parse(&qemu_drive_opts, optstr, 0);
+ if (!opts) {
+ return NULL;
+ }
+ if (file)
+ qemu_opt_set(opts, "file", file);
+ return opts;
+}
+
+DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit)
+{
+ DriveInfo *dinfo;
+
+ /* seek interface, bus and unit */
+
+ QTAILQ_FOREACH(dinfo, &drives, next) {
+ if (dinfo->type == type &&
+ dinfo->bus == bus &&
+ dinfo->unit == unit)
+ return dinfo;
+ }
+
+ return NULL;
+}
+
+DriveInfo *drive_get_by_id(const char *id)
+{
+ DriveInfo *dinfo;
+
+ QTAILQ_FOREACH(dinfo, &drives, next) {
+ if (strcmp(id, dinfo->id))
+ continue;
+ return dinfo;
+ }
+ return NULL;
+}
+
+int drive_get_max_bus(BlockInterfaceType type)
+{
+ int max_bus;
+ DriveInfo *dinfo;
+
+ max_bus = -1;
+ QTAILQ_FOREACH(dinfo, &drives, next) {
+ if(dinfo->type == type &&
+ dinfo->bus > max_bus)
+ max_bus = dinfo->bus;
+ }
+ return max_bus;
+}
+
+const char *drive_get_serial(BlockDriverState *bdrv)
+{
+ DriveInfo *dinfo;
+
+ QTAILQ_FOREACH(dinfo, &drives, next) {
+ if (dinfo->bdrv == bdrv)
+ return dinfo->serial;
+ }
+
+ return "\0";
+}
+
+BlockInterfaceErrorAction drive_get_on_error(
+ BlockDriverState *bdrv, int is_read)
+{
+ DriveInfo *dinfo;
+
+ QTAILQ_FOREACH(dinfo, &drives, next) {
+ if (dinfo->bdrv == bdrv)
+ return is_read ? dinfo->on_read_error : dinfo->on_write_error;
+ }
+
+ return is_read ? BLOCK_ERR_REPORT : BLOCK_ERR_STOP_ENOSPC;
+}
+
+static void bdrv_format_print(void *opaque, const char *name)
+{
+ fprintf(stderr, " %s", name);
+}
+
+void drive_uninit(DriveInfo *dinfo)
+{
+ qemu_opts_del(dinfo->opts);
+ bdrv_delete(dinfo->bdrv);
+ QTAILQ_REMOVE(&drives, dinfo, next);
+ qemu_free(dinfo);
+}
+
+static int parse_block_error_action(const char *buf, int is_read)
+{
+ if (!strcmp(buf, "ignore")) {
+ return BLOCK_ERR_IGNORE;
+ } else if (!is_read && !strcmp(buf, "enospc")) {
+ return BLOCK_ERR_STOP_ENOSPC;
+ } else if (!strcmp(buf, "stop")) {
+ return BLOCK_ERR_STOP_ANY;
+ } else if (!strcmp(buf, "report")) {
+ return BLOCK_ERR_REPORT;
+ } else {
+ fprintf(stderr, "qemu: '%s' invalid %s error action\n",
+ buf, is_read ? "read" : "write");
+ return -1;
+ }
+}
+
+DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
+{
+ const char *buf;
+ const char *file = NULL;
+ char devname[128];
+ const char *serial;
+ const char *mediastr = "";
+ BlockInterfaceType type;
+ enum { MEDIA_DISK, MEDIA_CDROM } media;
+ int bus_id, unit_id;
+ int cyls, heads, secs, translation;
+ BlockDriver *drv = NULL;
+ int max_devs;
+ int index;
+ int ro = 0;
+ int bdrv_flags = 0;
+ int on_read_error, on_write_error;
+ const char *devaddr;
+ DriveInfo *dinfo;
+ int snapshot = 0;
+ int ret;
+
+ *fatal_error = 1;
+
+ translation = BIOS_ATA_TRANSLATION_AUTO;
+
+ 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;
+
+ /* extract parameters */
+ bus_id = qemu_opt_get_number(opts, "bus", 0);
+ unit_id = qemu_opt_get_number(opts, "unit", -1);
+ index = qemu_opt_get_number(opts, "index", -1);
+
+ cyls = qemu_opt_get_number(opts, "cyls", 0);
+ heads = qemu_opt_get_number(opts, "heads", 0);
+ secs = qemu_opt_get_number(opts, "secs", 0);
+
+ snapshot = qemu_opt_get_bool(opts, "snapshot", 0);
+ ro = qemu_opt_get_bool(opts, "readonly", 0);
+
+ file = qemu_opt_get(opts, "file");
+ serial = qemu_opt_get(opts, "serial");
+
+ 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 {
+ fprintf(stderr, "qemu: unsupported bus type '%s'\n", buf);
+ return NULL;
+ }
+ }
+
+ if (cyls || heads || secs) {
+ if (cyls < 1 || (type == IF_IDE && cyls > 16383)) {
+ fprintf(stderr, "qemu: '%s' invalid physical cyls number\n", buf);
+ return NULL;
+ }
+ if (heads < 1 || (type == IF_IDE && heads > 16)) {
+ fprintf(stderr, "qemu: '%s' invalid physical heads number\n", buf);
+ return NULL;
+ }
+ if (secs < 1 || (type == IF_IDE && secs > 63)) {
+ fprintf(stderr, "qemu: '%s' invalid physical secs number\n", buf);
+ return NULL;
+ }
+ }
+
+ if ((buf = qemu_opt_get(opts, "trans")) != NULL) {
+ if (!cyls) {
+ fprintf(stderr,
+ "qemu: '%s' trans must be used with cyls,heads and secs\n",
+ buf);
+ return NULL;
+ }
+ if (!strcmp(buf, "none"))
+ translation = BIOS_ATA_TRANSLATION_NONE;
+ else if (!strcmp(buf, "lba"))
+ translation = BIOS_ATA_TRANSLATION_LBA;
+ else if (!strcmp(buf, "auto"))
+ translation = BIOS_ATA_TRANSLATION_AUTO;
+ else {
+ fprintf(stderr, "qemu: '%s' invalid translation type\n", buf);
+ return NULL;
+ }
+ }
+
+ if ((buf = qemu_opt_get(opts, "media")) != NULL) {
+ if (!strcmp(buf, "disk")) {
+ media = MEDIA_DISK;
+ } else if (!strcmp(buf, "cdrom")) {
+ if (cyls || secs || heads) {
+ fprintf(stderr,
+ "qemu: '%s' invalid physical CHS format\n", buf);
+ return NULL;
+ }
+ media = MEDIA_CDROM;
+ } else {
+ fprintf(stderr, "qemu: '%s' invalid media\n", buf);
+ return NULL;
+ }
+ }
+
+ if ((buf = qemu_opt_get(opts, "cache")) != NULL) {
+ if (!strcmp(buf, "off") || !strcmp(buf, "none")) {
+ bdrv_flags |= BDRV_O_NOCACHE;
+ } else if (!strcmp(buf, "writeback")) {
+ bdrv_flags |= BDRV_O_CACHE_WB;
+ } else if (!strcmp(buf, "unsafe")) {
+ bdrv_flags |= BDRV_O_CACHE_WB;
+ bdrv_flags |= BDRV_O_NO_FLUSH;
+ } else if (!strcmp(buf, "writethrough")) {
+ /* this is the default */
+ } else {
+ fprintf(stderr, "qemu: invalid cache option\n");
+ return NULL;
+ }
+ }
+
+#ifdef CONFIG_LINUX_AIO
+ if ((buf = qemu_opt_get(opts, "aio")) != NULL) {
+ if (!strcmp(buf, "native")) {
+ bdrv_flags |= BDRV_O_NATIVE_AIO;
+ } else if (!strcmp(buf, "threads")) {
+ /* this is the default */
+ } else {
+ fprintf(stderr, "qemu: invalid aio option\n");
+ return NULL;
+ }
+ }
+#endif
+
+ if ((buf = qemu_opt_get(opts, "format")) != NULL) {
+ if (strcmp(buf, "?") == 0) {
+ fprintf(stderr, "qemu: Supported formats:");
+ bdrv_iterate_format(bdrv_format_print, NULL);
+ fprintf(stderr, "\n");
+ return NULL;
+ }
+ drv = bdrv_find_whitelisted_format(buf);
+ if (!drv) {
+ fprintf(stderr, "qemu: '%s' invalid format\n", buf);
+ return NULL;
+ }
+ }
+
+ on_write_error = BLOCK_ERR_STOP_ENOSPC;
+ if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
+ if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
+ fprintf(stderr, "werror is no supported by this format\n");
+ return NULL;
+ }
+
+ on_write_error = parse_block_error_action(buf, 0);
+ if (on_write_error < 0) {
+ return NULL;
+ }
+ }
+
+ on_read_error = BLOCK_ERR_REPORT;
+ if ((buf = qemu_opt_get(opts, "rerror")) != NULL) {
+ if (type != IF_IDE && type != IF_VIRTIO && type != IF_NONE) {
+ fprintf(stderr, "rerror is no supported by this format\n");
+ return NULL;
+ }
+
+ on_read_error = parse_block_error_action(buf, 1);
+ if (on_read_error < 0) {
+ return NULL;
+ }
+ }
+
+ if ((devaddr = qemu_opt_get(opts, "addr")) != NULL) {
+ if (type != IF_VIRTIO) {
+ fprintf(stderr, "addr is not supported\n");
+ return NULL;
+ }
+ }
+
+ /* compute bus and unit according index */
+
+ if (index != -1) {
+ if (bus_id != 0 || unit_id != -1) {
+ fprintf(stderr,
+ "qemu: index cannot be used with bus and unit\n");
+ return NULL;
+ }
+ if (max_devs == 0)
+ {
+ unit_id = index;
+ bus_id = 0;
+ } else {
+ unit_id = index % max_devs;
+ bus_id = index / max_devs;
+ }
+ }
+
+ /* if user doesn't specify a unit_id,
+ * try to find the first free
+ */
+
+ if (unit_id == -1) {
+ unit_id = 0;
+ while (drive_get(type, bus_id, unit_id) != NULL) {
+ unit_id++;
+ if (max_devs && unit_id >= max_devs) {
+ unit_id -= max_devs;
+ bus_id++;
+ }
+ }
+ }
+
+ /* check unit id */
+
+ if (max_devs && unit_id >= max_devs) {
+ fprintf(stderr, "qemu: unit %d too big (max is %d)\n",
+ unit_id, max_devs - 1);
+ return NULL;
+ }
+
+ /*
+ * ignore multiple definitions
+ */
+
+ if (drive_get(type, bus_id, unit_id) != NULL) {
+ *fatal_error = 0;
+ return NULL;
+ }
+
+ /* init */
+
+ dinfo = qemu_mallocz(sizeof(*dinfo));
+ if ((buf = qemu_opts_id(opts)) != NULL) {
+ dinfo->id = qemu_strdup(buf);
+ } else {
+ /* no id supplied -> create one */
+ dinfo->id = qemu_mallocz(32);
+ if (type == IF_IDE || type == IF_SCSI)
+ mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd";
+ if (max_devs)
+ snprintf(dinfo->id, 32, "%s%i%s%i",
+ devname, bus_id, mediastr, unit_id);
+ else
+ snprintf(dinfo->id, 32, "%s%s%i",
+ devname, mediastr, unit_id);
+ }
+ dinfo->bdrv = bdrv_new(dinfo->id);
+ dinfo->devaddr = devaddr;
+ dinfo->type = type;
+ dinfo->bus = bus_id;
+ dinfo->unit = unit_id;
+ dinfo->on_read_error = on_read_error;
+ dinfo->on_write_error = on_write_error;
+ dinfo->opts = opts;
+ if (serial)
+ strncpy(dinfo->serial, serial, sizeof(serial));
+ QTAILQ_INSERT_TAIL(&drives, dinfo, next);
+
+ switch(type) {
+ case IF_IDE:
+ case IF_SCSI:
+ case IF_XEN:
+ case IF_NONE:
+ switch(media) {
+ case MEDIA_DISK:
+ if (cyls != 0) {
+ bdrv_set_geometry_hint(dinfo->bdrv, cyls, heads, secs);
+ bdrv_set_translation_hint(dinfo->bdrv, translation);
+ }
+ break;
+ case MEDIA_CDROM:
+ bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_CDROM);
+ break;
+ }
+ break;
+ case IF_SD:
+ /* FIXME: This isn't really a floppy, but it's a reasonable
+ approximation. */
+ case IF_FLOPPY:
+ bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_FLOPPY);
+ break;
+ case IF_PFLASH:
+ case IF_MTD:
+ break;
+ case IF_VIRTIO:
+ /* add virtio block device */
+ opts = qemu_opts_create(&qemu_device_opts, NULL, 0);
+ qemu_opt_set(opts, "driver", "virtio-blk-pci");
+ qemu_opt_set(opts, "drive", dinfo->id);
+ if (devaddr)
+ qemu_opt_set(opts, "addr", devaddr);
+ break;
+ case IF_COUNT:
+ abort();
+ }
+ if (!file) {
+ *fatal_error = 0;
+ return NULL;
+ }
+ if (snapshot) {
+ /* always use cache=unsafe with snapshot */
+ bdrv_flags &= ~BDRV_O_CACHE_MASK;
+ bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH);
+ }
+
+ if (media == MEDIA_CDROM) {
+ /* CDROM is fine for any interface, don't check. */
+ ro = 1;
+ } else if (ro == 1) {
+ if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY && type != IF_NONE) {
+ fprintf(stderr, "qemu: readonly flag not supported for drive with this interface\n");
+ return NULL;
+ }
+ }
+
+ bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
+
+ ret = bdrv_open(dinfo->bdrv, file, bdrv_flags, drv);
+ if (ret < 0) {
+ fprintf(stderr, "qemu: could not open disk image %s: %s\n",
+ file, strerror(-ret));
+ return NULL;
+ }
+
+ if (bdrv_key_required(dinfo->bdrv))
+ autostart = 0;
+ *fatal_error = 0;
+ return dinfo;
+}
+
+void do_commit(Monitor *mon, const QDict *qdict)
+{
+ int all_devices;
+ DriveInfo *dinfo;
+ const char *device = qdict_get_str(qdict, "device");
+
+ all_devices = !strcmp(device, "all");
+ QTAILQ_FOREACH(dinfo, &drives, next) {
+ if (!all_devices)
+ if (strcmp(bdrv_get_device_name(dinfo->bdrv), device))
+ continue;
+ bdrv_commit(dinfo->bdrv);
+ }
+}
+
+static int eject_device(Monitor *mon, BlockDriverState *bs, int force)
+{
+ if (bdrv_is_inserted(bs)) {
+ if (!force) {
+ if (!bdrv_is_removable(bs)) {
+ qerror_report(QERR_DEVICE_NOT_REMOVABLE,
+ bdrv_get_device_name(bs));
+ return -1;
+ }
+ if (bdrv_is_locked(bs)) {
+ qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs));
+ return -1;
+ }
+ }
+ bdrv_close(bs);
+ }
+ return 0;
+}
+
+int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+ BlockDriverState *bs;
+ int force = qdict_get_int(qdict, "force");
+ const char *filename = qdict_get_str(qdict, "device");
+
+ bs = bdrv_find(filename);
+ if (!bs) {
+ qerror_report(QERR_DEVICE_NOT_FOUND, filename);
+ return -1;
+ }
+ return eject_device(mon, bs, force);
+}
+
+int do_block_set_passwd(Monitor *mon, const QDict *qdict,
+ QObject **ret_data)
+{
+ BlockDriverState *bs;
+ int err;
+
+ bs = bdrv_find(qdict_get_str(qdict, "device"));
+ if (!bs) {
+ qerror_report(QERR_DEVICE_NOT_FOUND, qdict_get_str(qdict, "device"));
+ return -1;
+ }
+
+ err = bdrv_set_key(bs, qdict_get_str(qdict, "password"));
+ if (err == -EINVAL) {
+ qerror_report(QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs));
+ return -1;
+ } else if (err < 0) {
+ qerror_report(QERR_INVALID_PASSWORD);
+ return -1;
+ }
+
+ return 0;
+}
+
+int do_change_block(Monitor *mon, const char *device,
+ const char *filename, const char *fmt)
+{
+ BlockDriverState *bs;
+ BlockDriver *drv = NULL;
+ int bdrv_flags;
+
+ bs = bdrv_find(device);
+ if (!bs) {
+ qerror_report(QERR_DEVICE_NOT_FOUND, device);
+ return -1;
+ }
+ if (fmt) {
+ drv = bdrv_find_whitelisted_format(fmt);
+ if (!drv) {
+ qerror_report(QERR_INVALID_BLOCK_FORMAT, fmt);
+ return -1;
+ }
+ }
+ if (eject_device(mon, bs, 0) < 0) {
+ return -1;
+ }
+ bdrv_flags = bdrv_get_type_hint(bs) == BDRV_TYPE_CDROM ? 0 : BDRV_O_RDWR;
+ if (bdrv_open(bs, filename, bdrv_flags, drv) < 0) {
+ qerror_report(QERR_OPEN_FILE_FAILED, filename);
+ return -1;
+ }
+ return monitor_read_bdrv_key_start(mon, bs, NULL, NULL);
+}
diff --git a/blockdev.h b/blockdev.h
new file mode 100644
index 0000000..dfc9de1
--- /dev/null
+++ b/blockdev.h
@@ -0,0 +1,71 @@
+/*
+ * QEMU host block devices
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or
+ * later. See the COPYING file in the top-level directory.
+ */
+
+#ifndef BLOCKDEV_H
+#define BLOCKDEV_H
+
+#include "block.h"
+#include "qemu-queue.h"
+
+typedef enum {
+ IF_NONE,
+ IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN,
+ IF_COUNT
+} BlockInterfaceType;
+
+typedef enum {
+ BLOCK_ERR_REPORT, BLOCK_ERR_IGNORE, BLOCK_ERR_STOP_ENOSPC,
+ BLOCK_ERR_STOP_ANY
+} BlockInterfaceErrorAction;
+
+#define BLOCK_SERIAL_STRLEN 20
+
+typedef struct DriveInfo {
+ BlockDriverState *bdrv;
+ char *id;
+ const char *devaddr;
+ BlockInterfaceType type;
+ int bus;
+ int unit;
+ QemuOpts *opts;
+ BlockInterfaceErrorAction on_read_error;
+ BlockInterfaceErrorAction on_write_error;
+ char serial[BLOCK_SERIAL_STRLEN + 1];
+ QTAILQ_ENTRY(DriveInfo) next;
+} DriveInfo;
+
+#define MAX_IDE_DEVS 2
+#define MAX_SCSI_DEVS 7
+
+extern QTAILQ_HEAD(drivelist, DriveInfo) drives;
+
+extern DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
+extern DriveInfo *drive_get_by_id(const char *id);
+extern int drive_get_max_bus(BlockInterfaceType type);
+extern void drive_uninit(DriveInfo *dinfo);
+extern const char *drive_get_serial(BlockDriverState *bdrv);
+
+extern BlockInterfaceErrorAction drive_get_on_error(
+ BlockDriverState *bdrv, int is_read);
+
+extern QemuOpts *drive_add(const char *file, const char *fmt, ...);
+extern DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi,
+ int *fatal_error);
+
+/* device-hotplug */
+
+DriveInfo *add_init_drive(const char *opts);
+
+void do_commit(Monitor *mon, const QDict *qdict);
+int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data);
+int do_block_set_passwd(Monitor *mon, const QDict *qdict, QObject **ret_data);
+int do_change_block(Monitor *mon, const char *device,
+ const char *filename, const char *fmt);
+
+#endif
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 0fce958..a87286b 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -21,6 +21,7 @@
#include "pm_smbus.h"
#include "pci.h"
#include "acpi.h"
+#include "sysemu.h"
//#define DEBUG
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index b53e3c3..31c8d70 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -31,6 +31,7 @@
#include "pci_host.h"
#include "rwhandler.h"
#include "apb_pci.h"
+#include "sysemu.h"
/* debug APB */
//#define DEBUG_APB
diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c
index a3fe99e..c1a9a56 100644
--- a/hw/device-hotplug.c
+++ b/hw/device-hotplug.c
@@ -25,8 +25,6 @@
#include "hw.h"
#include "boards.h"
#include "net.h"
-#include "block_int.h"
-#include "sysemu.h"
DriveInfo *add_init_drive(const char *optstr)
{
diff --git a/hw/fdc.c b/hw/fdc.c
index 6306496..b978957 100644
--- a/hw/fdc.c
+++ b/hw/fdc.c
@@ -29,7 +29,6 @@
#include "hw.h"
#include "fdc.h"
-#include "block.h"
#include "qemu-timer.h"
#include "isa.h"
#include "sysbus.h"
diff --git a/hw/fdc.h b/hw/fdc.h
index c48b5e0..b6b3772 100644
--- a/hw/fdc.h
+++ b/hw/fdc.h
@@ -2,7 +2,7 @@
#define HW_FDC_H
/* fdc.c */
-#include "sysemu.h"
+#include "blockdev.h"
#define MAX_FD 2
typedef struct FDCtrl FDCtrl;
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 70af1b6..045d18d 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -26,8 +26,6 @@
#include <hw/pc.h>
#include <hw/pci.h>
#include <hw/scsi.h>
-#include "block.h"
-#include "block_int.h"
#include "qemu-timer.h"
#include "sysemu.h"
#include "dma.h"
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index 6231d77..0f9f22e 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -17,7 +17,6 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include <hw/hw.h>
-#include "sysemu.h"
#include "dma.h"
#include <hw/ide/internal.h>
diff --git a/hw/lan9118.c b/hw/lan9118.c
index 16d3330..b996dc4 100644
--- a/hw/lan9118.c
+++ b/hw/lan9118.c
@@ -10,6 +10,7 @@
#include "sysbus.h"
#include "net.h"
#include "devices.h"
+#include "sysemu.h"
/* For crc32 */
#include <zlib.h>
diff --git a/hw/nand.c b/hw/nand.c
index 40d5a6a..cd7444f 100644
--- a/hw/nand.c
+++ b/hw/nand.c
@@ -13,9 +13,8 @@
# include "hw.h"
# include "flash.h"
-# include "block.h"
+# include "blockdev.h"
/* FIXME: Pass block device as an argument. */
-# include "sysemu.h"
# define NAND_CMD_READ0 0x00
# define NAND_CMD_READ1 0x01
diff --git a/hw/omap2.c b/hw/omap2.c
index bd1b35e..666c15a 100644
--- a/hw/omap2.c
+++ b/hw/omap2.c
@@ -17,6 +17,8 @@
* You should have received a copy of the GNU General Public License along
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
+
+#include "blockdev.h"
#include "hw.h"
#include "arm-misc.h"
#include "omap.h"
diff --git a/hw/onenand.c b/hw/onenand.c
index c1e7e4d..4118db9 100644
--- a/hw/onenand.c
+++ b/hw/onenand.c
@@ -21,8 +21,7 @@
#include "qemu-common.h"
#include "flash.h"
#include "irq.h"
-#include "sysemu.h"
-#include "block.h"
+#include "blockdev.h"
/* 11 for 2kB-page OneNAND ("2nd generation") and 10 for 1kB-page chips */
#define PAGE_SHIFT 11
diff --git a/hw/parallel.c b/hw/parallel.c
index be8e2d5..6b11672 100644
--- a/hw/parallel.c
+++ b/hw/parallel.c
@@ -26,6 +26,7 @@
#include "qemu-char.h"
#include "isa.h"
#include "pc.h"
+#include "sysemu.h"
//#define DEBUG_PARALLEL
diff --git a/hw/pc.c b/hw/pc.c
index 9b85c42..6e7c468 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -35,6 +35,7 @@
#include "elf.h"
#include "multiboot.h"
#include "mc146818rtc.h"
+#include "sysemu.h"
/* output Bochs bios info messages */
//#define DEBUG_BIOS
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 70f563a..dc46846 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -32,6 +32,7 @@
#include "boards.h"
#include "ide.h"
#include "kvm.h"
+#include "sysemu.h"
#define MAX_IDE_BUS 2
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index a8f3df1..c39e640 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -26,10 +26,8 @@
#include "boards.h"
#include "pci.h"
#include "net.h"
-#include "sysemu.h"
#include "pc.h"
#include "monitor.h"
-#include "block_int.h"
#include "scsi.h"
#include "virtio-blk.h"
#include "qemu-config.h"
diff --git a/hw/pcmcia.h b/hw/pcmcia.h
index cf2db9d..3602923 100644
--- a/hw/pcmcia.h
+++ b/hw/pcmcia.h
@@ -1,7 +1,7 @@
/* PCMCIA/Cardbus */
#include "qemu-common.h"
-#include "sysemu.h"
+#include "blockdev.h"
typedef struct {
qemu_irq irq;
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 48a6b45..5a8739d 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -1,4 +1,3 @@
-#include "sysemu.h"
#include "net.h"
#include "qdev.h"
#include "qerror.h"
diff --git a/hw/qdev.h b/hw/qdev.h
index 0ad6c95..be5ad67 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -2,7 +2,7 @@
#define QDEV_H
#include "hw.h"
-#include "sysemu.h"
+#include "blockdev.h"
#include "qemu-queue.h"
#include "qemu-char.h"
#include "qemu-option.h"
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index 383240b..055a94d 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -2,7 +2,6 @@
#include "qemu-error.h"
#include "scsi.h"
#include "scsi-defs.h"
-#include "block.h"
#include "qdev.h"
static struct BusInfo scsi_bus_info = {
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index a3559d1..a9bf7d2 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -33,9 +33,9 @@ do { fprintf(stderr, "scsi-disk: " fmt , ## __VA_ARGS__); } while (0)
#include "qemu-common.h"
#include "qemu-error.h"
-#include "block.h"
#include "scsi.h"
#include "scsi-defs.h"
+#include "sysemu.h"
#define SCSI_DMA_BUF_SIZE 131072
#define SCSI_MAX_INQUIRY_LEN 256
diff --git a/hw/scsi-generic.c b/hw/scsi-generic.c
index c9aa853..e31060e 100644
--- a/hw/scsi-generic.c
+++ b/hw/scsi-generic.c
@@ -13,7 +13,6 @@
#include "qemu-common.h"
#include "qemu-error.h"
-#include "block.h"
#include "scsi.h"
#ifdef __linux__
diff --git a/hw/serial.c b/hw/serial.c
index 9102edb..c7e4e77 100644
--- a/hw/serial.c
+++ b/hw/serial.c
@@ -27,6 +27,7 @@
#include "isa.h"
#include "pc.h"
#include "qemu-timer.h"
+#include "sysemu.h"
//#define DEBUG_SERIAL
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index 8e6c6e0..228d0a0 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -25,6 +25,7 @@
#include "hw.h"
#include "console.h"
#include "usb.h"
+#include "sysemu.h"
/* HID interface requests */
#define GET_REPORT 0xa101
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index 0ba4a64..003bd8a 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -11,10 +11,10 @@
#include "qemu-option.h"
#include "qemu-config.h"
#include "usb.h"
-#include "block.h"
#include "scsi.h"
#include "console.h"
#include "monitor.h"
+#include "sysemu.h"
//#define DEBUG_MSD
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 80d51c4..cdcb492 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -12,9 +12,7 @@
*/
#include <qemu-common.h>
-#include <sysemu.h>
#include "virtio-blk.h"
-#include "block_int.h"
#ifdef __linux__
# include <scsi/sg.h>
#endif
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index 7ddf612..e101fa0 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -22,7 +22,6 @@
#include "qemu-error.h"
#include "msix.h"
#include "net.h"
-#include "block_int.h"
#include "loader.h"
#include "kvm.h"
diff --git a/monitor.c b/monitor.c
index 15b53b9..57f24ff 100644
--- a/monitor.c
+++ b/monitor.c
@@ -38,7 +38,7 @@
#include "monitor.h"
#include "readline.h"
#include "console.h"
-#include "block.h"
+#include "blockdev.h"
#include "audio/audio.h"
#include "disas.h"
#include "balloon.h"
@@ -530,21 +530,6 @@ static void do_help_cmd(Monitor *mon, const QDict *qdict)
help_cmd(mon, qdict_get_try_str(qdict, "name"));
}
-static void do_commit(Monitor *mon, const QDict *qdict)
-{
- int all_devices;
- DriveInfo *dinfo;
- const char *device = qdict_get_str(qdict, "device");
-
- all_devices = !strcmp(device, "all");
- QTAILQ_FOREACH(dinfo, &drives, next) {
- if (!all_devices)
- if (strcmp(bdrv_get_device_name(dinfo->bdrv), device))
- continue;
- bdrv_commit(dinfo->bdrv);
- }
-}
-
static void user_monitor_complete(void *opaque, QObject *ret_data)
{
MonitorCompletionData *data = (MonitorCompletionData *)opaque;
@@ -949,93 +934,6 @@ static int do_quit(Monitor *mon, const QDict *qdict, QObject **ret_data)
return 0;
}
-static int eject_device(Monitor *mon, BlockDriverState *bs, int force)
-{
- if (bdrv_is_inserted(bs)) {
- if (!force) {
- if (!bdrv_is_removable(bs)) {
- qerror_report(QERR_DEVICE_NOT_REMOVABLE,
- bdrv_get_device_name(bs));
- return -1;
- }
- if (bdrv_is_locked(bs)) {
- qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs));
- return -1;
- }
- }
- bdrv_close(bs);
- }
- return 0;
-}
-
-static int do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data)
-{
- BlockDriverState *bs;
- int force = qdict_get_int(qdict, "force");
- const char *filename = qdict_get_str(qdict, "device");
-
- bs = bdrv_find(filename);
- if (!bs) {
- qerror_report(QERR_DEVICE_NOT_FOUND, filename);
- return -1;
- }
- return eject_device(mon, bs, force);
-}
-
-static int do_block_set_passwd(Monitor *mon, const QDict *qdict,
- QObject **ret_data)
-{
- BlockDriverState *bs;
- int err;
-
- bs = bdrv_find(qdict_get_str(qdict, "device"));
- if (!bs) {
- qerror_report(QERR_DEVICE_NOT_FOUND, qdict_get_str(qdict, "device"));
- return -1;
- }
-
- err = bdrv_set_key(bs, qdict_get_str(qdict, "password"));
- if (err == -EINVAL) {
- qerror_report(QERR_DEVICE_NOT_ENCRYPTED, bdrv_get_device_name(bs));
- return -1;
- } else if (err < 0) {
- qerror_report(QERR_INVALID_PASSWORD);
- return -1;
- }
-
- return 0;
-}
-
-static int do_change_block(Monitor *mon, const char *device,
- const char *filename, const char *fmt)
-{
- BlockDriverState *bs;
- BlockDriver *drv = NULL;
- int bdrv_flags;
-
- bs = bdrv_find(device);
- if (!bs) {
- qerror_report(QERR_DEVICE_NOT_FOUND, device);
- return -1;
- }
- if (fmt) {
- drv = bdrv_find_whitelisted_format(fmt);
- if (!drv) {
- qerror_report(QERR_INVALID_BLOCK_FORMAT, fmt);
- return -1;
- }
- }
- if (eject_device(mon, bs, 0) < 0) {
- return -1;
- }
- bdrv_flags = bdrv_get_type_hint(bs) == BDRV_TYPE_CDROM ? 0 : BDRV_O_RDWR;
- if (bdrv_open(bs, filename, bdrv_flags, drv) < 0) {
- qerror_report(QERR_OPEN_FILE_FAILED, filename);
- return -1;
- }
- return monitor_read_bdrv_key_start(mon, bs, NULL, NULL);
-}
-
static int change_vnc_password(const char *password)
{
if (vnc_display_password(NULL, password) < 0) {
diff --git a/qemu-char.c b/qemu-char.c
index faaf624..87628ea 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -28,7 +28,6 @@
#include "sysemu.h"
#include "qemu-timer.h"
#include "qemu-char.h"
-#include "block.h"
#include "hw/usb.h"
#include "hw/baum.h"
#include "hw/msmouse.h"
diff --git a/savevm.c b/savevm.c
index af92ba2..1173a22 100644
--- a/savevm.c
+++ b/savevm.c
@@ -77,7 +77,7 @@
#include "sysemu.h"
#include "qemu-timer.h"
#include "qemu-char.h"
-#include "block.h"
+#include "blockdev.h"
#include "audio/audio.h"
#include "migration.h"
#include "qemu_socket.h"
diff --git a/sysemu.h b/sysemu.h
index dce13c1..5fa45ed 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -147,55 +147,6 @@ extern int nb_option_roms;
extern const char *prom_envs[MAX_PROM_ENVS];
extern unsigned int nb_prom_envs;
-typedef enum {
- IF_NONE,
- IF_IDE, IF_SCSI, IF_FLOPPY, IF_PFLASH, IF_MTD, IF_SD, IF_VIRTIO, IF_XEN,
- IF_COUNT
-} BlockInterfaceType;
-
-typedef enum {
- BLOCK_ERR_REPORT, BLOCK_ERR_IGNORE, BLOCK_ERR_STOP_ENOSPC,
- BLOCK_ERR_STOP_ANY
-} BlockInterfaceErrorAction;
-
-#define BLOCK_SERIAL_STRLEN 20
-
-typedef struct DriveInfo {
- BlockDriverState *bdrv;
- char *id;
- const char *devaddr;
- BlockInterfaceType type;
- int bus;
- int unit;
- QemuOpts *opts;
- BlockInterfaceErrorAction on_read_error;
- BlockInterfaceErrorAction on_write_error;
- char serial[BLOCK_SERIAL_STRLEN + 1];
- QTAILQ_ENTRY(DriveInfo) next;
-} DriveInfo;
-
-#define MAX_IDE_DEVS 2
-#define MAX_SCSI_DEVS 7
-
-extern QTAILQ_HEAD(drivelist, DriveInfo) drives;
-
-extern DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
-extern DriveInfo *drive_get_by_id(const char *id);
-extern int drive_get_max_bus(BlockInterfaceType type);
-extern void drive_uninit(DriveInfo *dinfo);
-extern const char *drive_get_serial(BlockDriverState *bdrv);
-
-extern BlockInterfaceErrorAction drive_get_on_error(
- BlockDriverState *bdrv, int is_read);
-
-extern QemuOpts *drive_add(const char *file, const char *fmt, ...);
-extern DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi,
- int *fatal_error);
-
-/* device-hotplug */
-
-DriveInfo *add_init_drive(const char *opts);
-
/* pci-hotplug */
void pci_device_hot_add(Monitor *mon, const QDict *qdict);
void drive_hot_add(Monitor *mon, const QDict *qdict);
diff --git a/vl.c b/vl.c
index db1fefd..0a9862f 100644
--- a/vl.c
+++ b/vl.c
@@ -140,7 +140,7 @@ int main(int argc, char **argv)
#include "qemu-char.h"
#include "cache-utils.h"
#include "block.h"
-#include "block_int.h"
+#include "blockdev.h"
#include "block-migration.h"
#include "dma.h"
#include "audio/audio.h"
@@ -172,7 +172,6 @@ int main(int argc, char **argv)
static const char *data_dir;
const char *bios_name = NULL;
-struct drivelist drives = QTAILQ_HEAD_INITIALIZER(drives);
enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
DisplayType display_type = DT_DEFAULT;
const char* keyboard_layout = NULL;
@@ -651,486 +650,6 @@ static int bt_parse(const char *opt)
#define MTD_ALIAS "if=mtd"
#define SD_ALIAS "index=0,if=sd"
-QemuOpts *drive_add(const char *file, const char *fmt, ...)
-{
- va_list ap;
- char optstr[1024];
- QemuOpts *opts;
-
- va_start(ap, fmt);
- vsnprintf(optstr, sizeof(optstr), fmt, ap);
- va_end(ap);
-
- opts = qemu_opts_parse(&qemu_drive_opts, optstr, 0);
- if (!opts) {
- return NULL;
- }
- if (file)
- qemu_opt_set(opts, "file", file);
- return opts;
-}
-
-DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit)
-{
- DriveInfo *dinfo;
-
- /* seek interface, bus and unit */
-
- QTAILQ_FOREACH(dinfo, &drives, next) {
- if (dinfo->type == type &&
- dinfo->bus == bus &&
- dinfo->unit == unit)
- return dinfo;
- }
-
- return NULL;
-}
-
-DriveInfo *drive_get_by_id(const char *id)
-{
- DriveInfo *dinfo;
-
- QTAILQ_FOREACH(dinfo, &drives, next) {
- if (strcmp(id, dinfo->id))
- continue;
- return dinfo;
- }
- return NULL;
-}
-
-int drive_get_max_bus(BlockInterfaceType type)
-{
- int max_bus;
- DriveInfo *dinfo;
-
- max_bus = -1;
- QTAILQ_FOREACH(dinfo, &drives, next) {
- if(dinfo->type == type &&
- dinfo->bus > max_bus)
- max_bus = dinfo->bus;
- }
- return max_bus;
-}
-
-const char *drive_get_serial(BlockDriverState *bdrv)
-{
- DriveInfo *dinfo;
-
- QTAILQ_FOREACH(dinfo, &drives, next) {
- if (dinfo->bdrv == bdrv)
- return dinfo->serial;
- }
-
- return "\0";
-}
-
-BlockInterfaceErrorAction drive_get_on_error(
- BlockDriverState *bdrv, int is_read)
-{
- DriveInfo *dinfo;
-
- QTAILQ_FOREACH(dinfo, &drives, next) {
- if (dinfo->bdrv == bdrv)
- return is_read ? dinfo->on_read_error : dinfo->on_write_error;
- }
-
- return is_read ? BLOCK_ERR_REPORT : BLOCK_ERR_STOP_ENOSPC;
-}
-
-static void bdrv_format_print(void *opaque, const char *name)
-{
- fprintf(stderr, " %s", name);
-}
-
-void drive_uninit(DriveInfo *dinfo)
-{
- qemu_opts_del(dinfo->opts);
- bdrv_delete(dinfo->bdrv);
- QTAILQ_REMOVE(&drives, dinfo, next);
- qemu_free(dinfo);
-}
-
-static int parse_block_error_action(const char *buf, int is_read)
-{
- if (!strcmp(buf, "ignore")) {
- return BLOCK_ERR_IGNORE;
- } else if (!is_read && !strcmp(buf, "enospc")) {
- return BLOCK_ERR_STOP_ENOSPC;
- } else if (!strcmp(buf, "stop")) {
- return BLOCK_ERR_STOP_ANY;
- } else if (!strcmp(buf, "report")) {
- return BLOCK_ERR_REPORT;
- } else {
- fprintf(stderr, "qemu: '%s' invalid %s error action\n",
- buf, is_read ? "read" : "write");
- return -1;
- }
-}
-
-DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
-{
- const char *buf;
- const char *file = NULL;
- char devname[128];
- const char *serial;
- const char *mediastr = "";
- BlockInterfaceType type;
- enum { MEDIA_DISK, MEDIA_CDROM } media;
- int bus_id, unit_id;
- int cyls, heads, secs, translation;
- BlockDriver *drv = NULL;
- int max_devs;
- int index;
- int ro = 0;
- int bdrv_flags = 0;
- int on_read_error, on_write_error;
- const char *devaddr;
- DriveInfo *dinfo;
- int snapshot = 0;
- int ret;
-
- *fatal_error = 1;
-
- translation = BIOS_ATA_TRANSLATION_AUTO;
-
- 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;
-
- /* extract parameters */
- bus_id = qemu_opt_get_number(opts, "bus", 0);
- unit_id = qemu_opt_get_number(opts, "unit", -1);
- index = qemu_opt_get_number(opts, "index", -1);
-
- cyls = qemu_opt_get_number(opts, "cyls", 0);
- heads = qemu_opt_get_number(opts, "heads", 0);
- secs = qemu_opt_get_number(opts, "secs", 0);
-
- snapshot = qemu_opt_get_bool(opts, "snapshot", 0);
- ro = qemu_opt_get_bool(opts, "readonly", 0);
-
- file = qemu_opt_get(opts, "file");
- serial = qemu_opt_get(opts, "serial");
-
- 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 {
- fprintf(stderr, "qemu: unsupported bus type '%s'\n", buf);
- return NULL;
- }
- }
-
- if (cyls || heads || secs) {
- if (cyls < 1 || (type == IF_IDE && cyls > 16383)) {
- fprintf(stderr, "qemu: '%s' invalid physical cyls number\n", buf);
- return NULL;
- }
- if (heads < 1 || (type == IF_IDE && heads > 16)) {
- fprintf(stderr, "qemu: '%s' invalid physical heads number\n", buf);
- return NULL;
- }
- if (secs < 1 || (type == IF_IDE && secs > 63)) {
- fprintf(stderr, "qemu: '%s' invalid physical secs number\n", buf);
- return NULL;
- }
- }
-
- if ((buf = qemu_opt_get(opts, "trans")) != NULL) {
- if (!cyls) {
- fprintf(stderr,
- "qemu: '%s' trans must be used with cyls,heads and secs\n",
- buf);
- return NULL;
- }
- if (!strcmp(buf, "none"))
- translation = BIOS_ATA_TRANSLATION_NONE;
- else if (!strcmp(buf, "lba"))
- translation = BIOS_ATA_TRANSLATION_LBA;
- else if (!strcmp(buf, "auto"))
- translation = BIOS_ATA_TRANSLATION_AUTO;
- else {
- fprintf(stderr, "qemu: '%s' invalid translation type\n", buf);
- return NULL;
- }
- }
-
- if ((buf = qemu_opt_get(opts, "media")) != NULL) {
- if (!strcmp(buf, "disk")) {
- media = MEDIA_DISK;
- } else if (!strcmp(buf, "cdrom")) {
- if (cyls || secs || heads) {
- fprintf(stderr,
- "qemu: '%s' invalid physical CHS format\n", buf);
- return NULL;
- }
- media = MEDIA_CDROM;
- } else {
- fprintf(stderr, "qemu: '%s' invalid media\n", buf);
- return NULL;
- }
- }
-
- if ((buf = qemu_opt_get(opts, "cache")) != NULL) {
- if (!strcmp(buf, "off") || !strcmp(buf, "none")) {
- bdrv_flags |= BDRV_O_NOCACHE;
- } else if (!strcmp(buf, "writeback")) {
- bdrv_flags |= BDRV_O_CACHE_WB;
- } else if (!strcmp(buf, "unsafe")) {
- bdrv_flags |= BDRV_O_CACHE_WB;
- bdrv_flags |= BDRV_O_NO_FLUSH;
- } else if (!strcmp(buf, "writethrough")) {
- /* this is the default */
- } else {
- fprintf(stderr, "qemu: invalid cache option\n");
- return NULL;
- }
- }
-
-#ifdef CONFIG_LINUX_AIO
- if ((buf = qemu_opt_get(opts, "aio")) != NULL) {
- if (!strcmp(buf, "native")) {
- bdrv_flags |= BDRV_O_NATIVE_AIO;
- } else if (!strcmp(buf, "threads")) {
- /* this is the default */
- } else {
- fprintf(stderr, "qemu: invalid aio option\n");
- return NULL;
- }
- }
-#endif
-
- if ((buf = qemu_opt_get(opts, "format")) != NULL) {
- if (strcmp(buf, "?") == 0) {
- fprintf(stderr, "qemu: Supported formats:");
- bdrv_iterate_format(bdrv_format_print, NULL);
- fprintf(stderr, "\n");
- return NULL;
- }
- drv = bdrv_find_whitelisted_format(buf);
- if (!drv) {
- fprintf(stderr, "qemu: '%s' invalid format\n", buf);
- return NULL;
- }
- }
-
- on_write_error = BLOCK_ERR_STOP_ENOSPC;
- if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
- if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
- fprintf(stderr, "werror is no supported by this format\n");
- return NULL;
- }
-
- on_write_error = parse_block_error_action(buf, 0);
- if (on_write_error < 0) {
- return NULL;
- }
- }
-
- on_read_error = BLOCK_ERR_REPORT;
- if ((buf = qemu_opt_get(opts, "rerror")) != NULL) {
- if (type != IF_IDE && type != IF_VIRTIO && type != IF_NONE) {
- fprintf(stderr, "rerror is no supported by this format\n");
- return NULL;
- }
-
- on_read_error = parse_block_error_action(buf, 1);
- if (on_read_error < 0) {
- return NULL;
- }
- }
-
- if ((devaddr = qemu_opt_get(opts, "addr")) != NULL) {
- if (type != IF_VIRTIO) {
- fprintf(stderr, "addr is not supported\n");
- return NULL;
- }
- }
-
- /* compute bus and unit according index */
-
- if (index != -1) {
- if (bus_id != 0 || unit_id != -1) {
- fprintf(stderr,
- "qemu: index cannot be used with bus and unit\n");
- return NULL;
- }
- if (max_devs == 0)
- {
- unit_id = index;
- bus_id = 0;
- } else {
- unit_id = index % max_devs;
- bus_id = index / max_devs;
- }
- }
-
- /* if user doesn't specify a unit_id,
- * try to find the first free
- */
-
- if (unit_id == -1) {
- unit_id = 0;
- while (drive_get(type, bus_id, unit_id) != NULL) {
- unit_id++;
- if (max_devs && unit_id >= max_devs) {
- unit_id -= max_devs;
- bus_id++;
- }
- }
- }
-
- /* check unit id */
-
- if (max_devs && unit_id >= max_devs) {
- fprintf(stderr, "qemu: unit %d too big (max is %d)\n",
- unit_id, max_devs - 1);
- return NULL;
- }
-
- /*
- * ignore multiple definitions
- */
-
- if (drive_get(type, bus_id, unit_id) != NULL) {
- *fatal_error = 0;
- return NULL;
- }
-
- /* init */
-
- dinfo = qemu_mallocz(sizeof(*dinfo));
- if ((buf = qemu_opts_id(opts)) != NULL) {
- dinfo->id = qemu_strdup(buf);
- } else {
- /* no id supplied -> create one */
- dinfo->id = qemu_mallocz(32);
- if (type == IF_IDE || type == IF_SCSI)
- mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd";
- if (max_devs)
- snprintf(dinfo->id, 32, "%s%i%s%i",
- devname, bus_id, mediastr, unit_id);
- else
- snprintf(dinfo->id, 32, "%s%s%i",
- devname, mediastr, unit_id);
- }
- dinfo->bdrv = bdrv_new(dinfo->id);
- dinfo->devaddr = devaddr;
- dinfo->type = type;
- dinfo->bus = bus_id;
- dinfo->unit = unit_id;
- dinfo->on_read_error = on_read_error;
- dinfo->on_write_error = on_write_error;
- dinfo->opts = opts;
- if (serial)
- strncpy(dinfo->serial, serial, sizeof(serial));
- QTAILQ_INSERT_TAIL(&drives, dinfo, next);
-
- switch(type) {
- case IF_IDE:
- case IF_SCSI:
- case IF_XEN:
- case IF_NONE:
- switch(media) {
- case MEDIA_DISK:
- if (cyls != 0) {
- bdrv_set_geometry_hint(dinfo->bdrv, cyls, heads, secs);
- bdrv_set_translation_hint(dinfo->bdrv, translation);
- }
- break;
- case MEDIA_CDROM:
- bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_CDROM);
- break;
- }
- break;
- case IF_SD:
- /* FIXME: This isn't really a floppy, but it's a reasonable
- approximation. */
- case IF_FLOPPY:
- bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_FLOPPY);
- break;
- case IF_PFLASH:
- case IF_MTD:
- break;
- case IF_VIRTIO:
- /* add virtio block device */
- opts = qemu_opts_create(&qemu_device_opts, NULL, 0);
- qemu_opt_set(opts, "driver", "virtio-blk-pci");
- qemu_opt_set(opts, "drive", dinfo->id);
- if (devaddr)
- qemu_opt_set(opts, "addr", devaddr);
- break;
- case IF_COUNT:
- abort();
- }
- if (!file) {
- *fatal_error = 0;
- return NULL;
- }
- if (snapshot) {
- /* always use cache=unsafe with snapshot */
- bdrv_flags &= ~BDRV_O_CACHE_MASK;
- bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH);
- }
-
- if (media == MEDIA_CDROM) {
- /* CDROM is fine for any interface, don't check. */
- ro = 1;
- } else if (ro == 1) {
- if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY && type != IF_NONE) {
- fprintf(stderr, "qemu: readonly flag not supported for drive with this interface\n");
- return NULL;
- }
- }
-
- bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
-
- ret = bdrv_open(dinfo->bdrv, file, bdrv_flags, drv);
- if (ret < 0) {
- fprintf(stderr, "qemu: could not open disk image %s: %s\n",
- file, strerror(-ret));
- return NULL;
- }
-
- if (bdrv_key_required(dinfo->bdrv))
- autostart = 0;
- *fatal_error = 0;
- return dinfo;
-}
-
static int drive_init_func(QemuOpts *opts, void *opaque)
{
int *use_scsi = opaque;
commit 7b370f513002b340a383fac961dc8c6fdf39eddc
Author: Markus Armbruster <armbru at redhat.com>
Date: Wed Jun 2 13:31:56 2010 +0200
qdev: Move declaration of qdev_init_bdrv() into qdev.h
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/pl181.c b/hw/pl181.c
index 1924053..85cadc4 100644
--- a/hw/pl181.c
+++ b/hw/pl181.c
@@ -9,7 +9,6 @@
#include "sysbus.h"
#include "sd.h"
-#include "sysemu.h"
//#define DEBUG_PL181 1
diff --git a/hw/qdev.h b/hw/qdev.h
index 51a24e2..0ad6c95 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -125,6 +125,8 @@ void qdev_machine_creation_done(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 5e74e5d..96b33ed 100644
--- a/hw/ssi-sd.c
+++ b/hw/ssi-sd.c
@@ -9,7 +9,6 @@
#include "ssi.h"
#include "sd.h"
-#include "sysemu.h"
//#define DEBUG_SSI_SD 1
diff --git a/sysemu.h b/sysemu.h
index 46a1b2f..dce13c1 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -188,8 +188,6 @@ extern const char *drive_get_serial(BlockDriverState *bdrv);
extern BlockInterfaceErrorAction drive_get_on_error(
BlockDriverState *bdrv, int is_read);
-BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type);
-
extern QemuOpts *drive_add(const char *file, const char *fmt, ...);
extern DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi,
int *fatal_error);
commit a803cb8eb8ada1add74f1b393b8a553a7e7f3acf
Author: Markus Armbruster <armbru at redhat.com>
Date: Wed Jun 2 13:31:55 2010 +0200
blockdev: Hide QEMUMachine from drive_init()
To pave the way for moving it out of vl.c.
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c
index 9cc8376..a3fe99e 100644
--- a/hw/device-hotplug.c
+++ b/hw/device-hotplug.c
@@ -38,7 +38,7 @@ DriveInfo *add_init_drive(const char *optstr)
if (!opts)
return NULL;
- dinfo = drive_init(opts, current_machine, &fatal_error);
+ dinfo = drive_init(opts, current_machine->use_scsi, &fatal_error);
if (!dinfo) {
qemu_opts_del(opts);
return NULL;
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index c1c2537..0ba4a64 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -584,7 +584,7 @@ static USBDevice *usb_msd_init(const char *filename)
qemu_opt_set(opts, "if", "none");
/* create host drive */
- dinfo = drive_init(opts, NULL, &fatal_error);
+ dinfo = drive_init(opts, 0, &fatal_error);
if (!dinfo) {
qemu_opts_del(opts);
return NULL;
diff --git a/sysemu.h b/sysemu.h
index fd83b7d..46a1b2f 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -191,7 +191,8 @@ extern BlockInterfaceErrorAction drive_get_on_error(
BlockDriverState *qdev_init_bdrv(DeviceState *dev, BlockInterfaceType type);
extern QemuOpts *drive_add(const char *file, const char *fmt, ...);
-extern DriveInfo *drive_init(QemuOpts *arg, void *machine, int *fatal_error);
+extern DriveInfo *drive_init(QemuOpts *arg, int default_to_scsi,
+ int *fatal_error);
/* device-hotplug */
diff --git a/vl.c b/vl.c
index 551138f..db1fefd 100644
--- a/vl.c
+++ b/vl.c
@@ -767,8 +767,7 @@ static int parse_block_error_action(const char *buf, int is_read)
}
}
-DriveInfo *drive_init(QemuOpts *opts, void *opaque,
- int *fatal_error)
+DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi, int *fatal_error)
{
const char *buf;
const char *file = NULL;
@@ -780,7 +779,6 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque,
int bus_id, unit_id;
int cyls, heads, secs, translation;
BlockDriver *drv = NULL;
- QEMUMachine *machine = opaque;
int max_devs;
int index;
int ro = 0;
@@ -795,7 +793,7 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque,
translation = BIOS_ATA_TRANSLATION_AUTO;
- if (machine && machine->use_scsi) {
+ if (default_to_scsi) {
type = IF_SCSI;
max_devs = MAX_SCSI_DEVS;
pstrcpy(devname, sizeof(devname), "scsi");
@@ -1135,10 +1133,10 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque,
static int drive_init_func(QemuOpts *opts, void *opaque)
{
- QEMUMachine *machine = opaque;
+ int *use_scsi = opaque;
int fatal_error = 0;
- if (drive_init(opts, machine, &fatal_error) == NULL) {
+ if (drive_init(opts, *use_scsi, &fatal_error) == NULL) {
if (fatal_error)
return 1;
}
@@ -3641,7 +3639,7 @@ int main(int argc, char **argv, char **envp)
/* open the virtual block devices */
if (snapshot)
qemu_opts_foreach(&qemu_drive_opts, drive_enable_snapshot, NULL, 0);
- if (qemu_opts_foreach(&qemu_drive_opts, drive_init_func, machine, 1) != 0)
+ if (qemu_opts_foreach(&qemu_drive_opts, drive_init_func, &machine->use_scsi, 1) != 0)
exit(1);
register_savevm_live("ram", 0, 3, NULL, ram_save_live, NULL,
commit 7cdb1f6d305e1000b5f882257cbee71b8bb08ef5
Author: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
Date: Fri May 28 11:44:58 2010 +0900
block: call the snapshot handlers of the protocol drivers
When snapshot handlers are not defined in the format driver, it is
better to call the ones of the protocol driver. This enables us to
implement snapshot support in the protocol driver.
We need to call bdrv_close() and bdrv_open() handlers of the format
driver before and after bdrv_snapshot_goto() call of the protocol. It is
because the contents of the block driver state may need to be changed
after loading vmstate.
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.c b/block.c
index b1ef85c..cacf11b 100644
--- a/block.c
+++ b/block.c
@@ -1631,9 +1631,11 @@ int bdrv_save_vmstate(BlockDriverState *bs, const uint8_t *buf,
BlockDriver *drv = bs->drv;
if (!drv)
return -ENOMEDIUM;
- if (!drv->bdrv_save_vmstate)
- return -ENOTSUP;
- return drv->bdrv_save_vmstate(bs, buf, pos, size);
+ if (drv->bdrv_save_vmstate)
+ return drv->bdrv_save_vmstate(bs, buf, pos, size);
+ if (bs->file)
+ return bdrv_save_vmstate(bs->file, buf, pos, size);
+ return -ENOTSUP;
}
int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
@@ -1642,9 +1644,11 @@ int bdrv_load_vmstate(BlockDriverState *bs, uint8_t *buf,
BlockDriver *drv = bs->drv;
if (!drv)
return -ENOMEDIUM;
- if (!drv->bdrv_load_vmstate)
- return -ENOTSUP;
- return drv->bdrv_load_vmstate(bs, buf, pos, size);
+ if (drv->bdrv_load_vmstate)
+ return drv->bdrv_load_vmstate(bs, buf, pos, size);
+ if (bs->file)
+ return bdrv_load_vmstate(bs->file, buf, pos, size);
+ return -ENOTSUP;
}
void bdrv_debug_event(BlockDriverState *bs, BlkDebugEvent event)
@@ -1668,20 +1672,37 @@ int bdrv_snapshot_create(BlockDriverState *bs,
BlockDriver *drv = bs->drv;
if (!drv)
return -ENOMEDIUM;
- if (!drv->bdrv_snapshot_create)
- return -ENOTSUP;
- return drv->bdrv_snapshot_create(bs, sn_info);
+ if (drv->bdrv_snapshot_create)
+ return drv->bdrv_snapshot_create(bs, sn_info);
+ if (bs->file)
+ return bdrv_snapshot_create(bs->file, sn_info);
+ return -ENOTSUP;
}
int bdrv_snapshot_goto(BlockDriverState *bs,
const char *snapshot_id)
{
BlockDriver *drv = bs->drv;
+ int ret, open_ret;
+
if (!drv)
return -ENOMEDIUM;
- if (!drv->bdrv_snapshot_goto)
- return -ENOTSUP;
- return drv->bdrv_snapshot_goto(bs, snapshot_id);
+ if (drv->bdrv_snapshot_goto)
+ return drv->bdrv_snapshot_goto(bs, snapshot_id);
+
+ if (bs->file) {
+ drv->bdrv_close(bs);
+ ret = bdrv_snapshot_goto(bs->file, snapshot_id);
+ open_ret = drv->bdrv_open(bs, bs->open_flags);
+ if (open_ret < 0) {
+ bdrv_delete(bs->file);
+ bs->drv = NULL;
+ return open_ret;
+ }
+ return ret;
+ }
+
+ return -ENOTSUP;
}
int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
@@ -1689,9 +1710,11 @@ int bdrv_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
BlockDriver *drv = bs->drv;
if (!drv)
return -ENOMEDIUM;
- if (!drv->bdrv_snapshot_delete)
- return -ENOTSUP;
- return drv->bdrv_snapshot_delete(bs, snapshot_id);
+ if (drv->bdrv_snapshot_delete)
+ return drv->bdrv_snapshot_delete(bs, snapshot_id);
+ if (bs->file)
+ return bdrv_snapshot_delete(bs->file, snapshot_id);
+ return -ENOTSUP;
}
int bdrv_snapshot_list(BlockDriverState *bs,
@@ -1700,9 +1723,11 @@ int bdrv_snapshot_list(BlockDriverState *bs,
BlockDriver *drv = bs->drv;
if (!drv)
return -ENOMEDIUM;
- if (!drv->bdrv_snapshot_list)
- return -ENOTSUP;
- return drv->bdrv_snapshot_list(bs, psn_info);
+ if (drv->bdrv_snapshot_list)
+ return drv->bdrv_snapshot_list(bs, psn_info);
+ if (bs->file)
+ return bdrv_snapshot_list(bs->file, psn_info);
+ return -ENOTSUP;
}
#define NB_SUFFIXES 4
commit 2bc93fed76c89f7adaa0e5bb357dcdc6c2b097a8
Author: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
Date: Fri May 28 11:44:57 2010 +0900
close all the block drivers before the qemu process exits
This patch calls the close handler of the block driver before the qemu
process exits.
This is necessary because the sheepdog block driver releases the lock
of VM images in the close handler.
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.c b/block.c
index ecd9867..b1ef85c 100644
--- a/block.c
+++ b/block.c
@@ -648,6 +648,15 @@ void bdrv_close(BlockDriverState *bs)
}
}
+void bdrv_close_all(void)
+{
+ BlockDriverState *bs;
+
+ QTAILQ_FOREACH(bs, &bdrv_states, list) {
+ bdrv_close(bs);
+ }
+}
+
void bdrv_delete(BlockDriverState *bs)
{
/* remove from list, if necessary */
diff --git a/block.h b/block.h
index 756670d..25744b1 100644
--- a/block.h
+++ b/block.h
@@ -123,6 +123,7 @@ BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
/* Ensure contents are flushed to disk. */
void bdrv_flush(BlockDriverState *bs);
void bdrv_flush_all(void);
+void bdrv_close_all(void);
int bdrv_has_zero_init(BlockDriverState *bs);
int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
diff --git a/vl.c b/vl.c
index 2769d1a..551138f 100644
--- a/vl.c
+++ b/vl.c
@@ -1991,6 +1991,7 @@ static void main_loop(void)
vm_stop(r);
}
}
+ bdrv_close_all();
pause_all_vcpus();
}
commit 08a00559f00975cebcb3f844fe7c708d65b6a3b3
Author: Kevin Wolf <kwolf at redhat.com>
Date: Tue Jun 1 18:37:31 2010 +0200
block: Assume raw for drives without media
qemu -cdrom /dev/cdrom with an empty CD-ROM drive doesn't work any more because
we try to guess the format and when this fails (because there is no medium) we
exit with an error message.
This patch should restore the old behaviour by assuming raw format for such
drives.
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block.c b/block.c
index 9c43332..ecd9867 100644
--- a/block.c
+++ b/block.c
@@ -331,8 +331,8 @@ static BlockDriver *find_image_format(const char *filename)
if (ret < 0)
return NULL;
- /* Return the raw BlockDriver * to scsi-generic devices */
- if (bs->sg) {
+ /* Return the raw BlockDriver * to scsi-generic devices or empty drives */
+ if (bs->sg || !bdrv_is_inserted(bs)) {
bdrv_delete(bs);
return bdrv_find_format("raw");
}
commit 236f1f672ca4b5dea70c0c101036224297c53895
Author: Kevin Wolf <kwolf at redhat.com>
Date: Tue Jun 1 13:20:57 2010 +0200
Fix error message in drive_init
The real error is the return value of bdrv_open. errno might be overwritten or
not even set to that value in the first place.
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/vl.c b/vl.c
index 76a9b25..2769d1a 100644
--- a/vl.c
+++ b/vl.c
@@ -789,6 +789,7 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque,
const char *devaddr;
DriveInfo *dinfo;
int snapshot = 0;
+ int ret;
*fatal_error = 1;
@@ -1119,9 +1120,10 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque,
bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
- if (bdrv_open(dinfo->bdrv, file, bdrv_flags, drv) < 0) {
+ ret = bdrv_open(dinfo->bdrv, file, bdrv_flags, drv);
+ if (ret < 0) {
fprintf(stderr, "qemu: could not open disk image %s: %s\n",
- file, strerror(errno));
+ file, strerror(-ret));
return NULL;
}
commit 552fee931bf52bf60f4210f607a78f415000f015
Author: Markus Armbruster <armbru at redhat.com>
Date: Tue Jun 1 20:32:35 2010 +0200
scsi: Fix info qtree for scsi-disk.ver
Show the actual default value instead of <null> when the property has
not been set.
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index e8c066a..a3559d1 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -462,8 +462,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
}
memcpy(&outbuf[8], "QEMU ", 8);
memset(&outbuf[32], 0, 4);
- memcpy(&outbuf[32], s->version ? s->version : QEMU_VERSION,
- MIN(4, strlen(s->version ? s->version : QEMU_VERSION)));
+ memcpy(&outbuf[32], s->version, MIN(4, strlen(s->version)));
/*
* We claim conformance to SPC-3, which is required for guests
* to ask for modern features like READ CAPACITY(16) or the
@@ -1066,6 +1065,10 @@ static int scsi_disk_initfn(SCSIDevice *dev)
}
}
+ if (!s->version) {
+ s->version = qemu_strdup(QEMU_VERSION);
+ }
+
if (bdrv_is_sg(s->bs)) {
error_report("scsi-disk: unwanted /dev/sg*");
return -1;
commit a0fef654f6dec1348a074a17a6b809d0ba77b34e
Author: Markus Armbruster <armbru at redhat.com>
Date: Tue Jun 1 20:32:34 2010 +0200
scsi: Turn drive serial into a qdev property scsi-disk.serial
It needs to be a qdev property, because it belongs to the drive's
guest part.
Bonus: info qtree now shows the serial number.
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 4d20919..e8c066a 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -66,6 +66,7 @@ struct SCSIDiskState
uint64_t max_lba;
QEMUBH *bh;
char *version;
+ char *serial;
};
static SCSIDiskReq *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun)
@@ -359,9 +360,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
case 0x80: /* Device serial number, optional */
{
- const char *serial = req->dev->conf.dinfo->serial ?
- req->dev->conf.dinfo->serial : "0";
- int l = strlen(serial);
+ int l = strlen(s->serial);
if (l > req->cmd.xfer)
l = req->cmd.xfer;
@@ -371,7 +370,7 @@ static int scsi_disk_emulate_inquiry(SCSIRequest *req, uint8_t *outbuf)
DPRINTF("Inquiry EVPD[Serial number] "
"buffer size %zd\n", req->cmd.xfer);
outbuf[buflen++] = l;
- memcpy(outbuf+buflen, serial, l);
+ memcpy(outbuf+buflen, s->serial, l);
buflen += l;
break;
}
@@ -1058,6 +1057,15 @@ static int scsi_disk_initfn(SCSIDevice *dev)
}
s->bs = s->qdev.conf.dinfo->bdrv;
+ if (!s->serial) {
+ if (*dev->conf.dinfo->serial) {
+ /* try to fall back to value set with legacy -drive serial=... */
+ s->serial = qemu_strdup(dev->conf.dinfo->serial);
+ } else {
+ s->serial = qemu_strdup("0");
+ }
+ }
+
if (bdrv_is_sg(s->bs)) {
error_report("scsi-disk: unwanted /dev/sg*");
return -1;
@@ -1090,6 +1098,7 @@ static SCSIDeviceInfo scsi_disk_info = {
.qdev.props = (Property[]) {
DEFINE_BLOCK_PROPERTIES(SCSIDiskState, qdev.conf),
DEFINE_PROP_STRING("ver", SCSIDiskState, version),
+ DEFINE_PROP_STRING("serial", SCSIDiskState, serial),
DEFINE_PROP_END_OF_LIST(),
},
};
commit 03432407256b8e39d76c9e6cd39dc553e7b646d8
Author: Markus Armbruster <armbru at redhat.com>
Date: Tue Jun 1 20:32:33 2010 +0200
ide: Fix info qtree for ide-drive.ver
Show the actual default value instead of <null> when the property has
not been set.
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index 5e549d9..6231d77 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -110,6 +110,9 @@ static int ide_drive_initfn(IDEDevice *dev)
ide_init_drive(s, dev->conf.dinfo, dev->version, serial);
+ if (!dev->version) {
+ dev->version = qemu_strdup(s->version);
+ }
if (!dev->serial) {
dev->serial = qemu_strdup(s->drive_serial_str);
}
commit 6ced55a57d7f6e647d683b5c41df0c176594f824
Author: Markus Armbruster <armbru at redhat.com>
Date: Tue Jun 1 20:32:32 2010 +0200
ide: Turn drive serial into a qdev property ide-drive.serial
It needs to be a qdev property, because it belongs to the drive's
guest part.
Bonus: info qtree now shows the serial number.
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/ide/core.c b/hw/ide/core.c
index d3328cd..70af1b6 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -2596,7 +2596,8 @@ void ide_bus_reset(IDEBus *bus)
ide_clear_hob(bus);
}
-void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version)
+void ide_init_drive(IDEState *s, DriveInfo *dinfo,
+ const char *version, const char *serial)
{
int cylinders, heads, secs;
uint64_t nb_sectors;
@@ -2618,9 +2619,9 @@ void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version)
s->is_cdrom = 1;
bdrv_set_change_cb(s->bs, cdrom_change_cb, s);
}
- strncpy(s->drive_serial_str, drive_get_serial(s->bs),
- sizeof(s->drive_serial_str));
- if (!*s->drive_serial_str) {
+ if (serial && *serial) {
+ strncpy(s->drive_serial_str, serial, sizeof(s->drive_serial_str));
+ } else {
snprintf(s->drive_serial_str, sizeof(s->drive_serial_str),
"QM%05d", s->drive_serial);
}
@@ -2669,7 +2670,7 @@ void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
dinfo = i == 0 ? hd0 : hd1;
ide_init1(bus, i);
if (dinfo) {
- ide_init_drive(&bus->ifs[i], dinfo, NULL);
+ ide_init_drive(&bus->ifs[i], dinfo, NULL, dinfo->serial);
} else {
ide_reset(&bus->ifs[i]);
}
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index 6b0024d..eef1ee1 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -457,6 +457,7 @@ struct IDEDevice {
uint32_t unit;
BlockConf conf;
char *version;
+ char *serial;
};
typedef int (*ide_qdev_initfn)(IDEDevice *dev);
@@ -554,7 +555,8 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr);
void ide_data_writel(void *opaque, uint32_t addr, uint32_t val);
uint32_t ide_data_readl(void *opaque, uint32_t addr);
-void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version);
+void ide_init_drive(IDEState *s, DriveInfo *dinfo,
+ const char *version, const char *serial);
void ide_init2(IDEBus *bus, qemu_irq irq);
void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
DriveInfo *hd1, qemu_irq irq);
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index 9ebb906..5e549d9 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -99,7 +99,20 @@ typedef struct IDEDrive {
static int ide_drive_initfn(IDEDevice *dev)
{
IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus);
- ide_init_drive(bus->ifs + dev->unit, dev->conf.dinfo, dev->version);
+ IDEState *s = bus->ifs + dev->unit;
+ const char *serial;
+
+ serial = dev->serial;
+ if (!serial) {
+ /* try to fall back to value set with legacy -drive serial=... */
+ serial = dev->conf.dinfo->serial;
+ }
+
+ ide_init_drive(s, dev->conf.dinfo, dev->version, serial);
+
+ if (!dev->serial) {
+ dev->serial = qemu_strdup(s->drive_serial_str);
+ }
return 0;
}
@@ -111,6 +124,7 @@ static IDEDeviceInfo ide_drive_info = {
DEFINE_PROP_UINT32("unit", IDEDrive, dev.unit, -1),
DEFINE_BLOCK_PROPERTIES(IDEDrive, dev.conf),
DEFINE_PROP_STRING("ver", IDEDrive, dev.version),
+ DEFINE_PROP_STRING("serial", IDEDrive, dev.serial),
DEFINE_PROP_END_OF_LIST(),
}
};
commit d21357df9a2a6b7e6bb2f579d04877f3bd65c557
Author: Markus Armbruster <armbru at redhat.com>
Date: Tue Jun 1 20:32:31 2010 +0200
qdev: Don't leak string property value on hot unplug
parse_string() qemu_strdup()s the property value. It is never freed.
It needs to be freed along with the device. Otherwise, the value of
scsi-disk property "ver" gets leaked when hot-unplugging the disk, for
instance.
Call new PropertyInfo method free() from qdev_free(). Implement it
for qdev_prop_string.
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index b6ee50f..48a6b45 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -260,6 +260,11 @@ static int parse_string(DeviceState *dev, Property *prop, const char *str)
return 0;
}
+static void free_string(DeviceState *dev, Property *prop)
+{
+ qemu_free(*(char **)qdev_get_prop_ptr(dev, prop));
+}
+
static int print_string(DeviceState *dev, Property *prop, char *dest, size_t len)
{
char **ptr = qdev_get_prop_ptr(dev, prop);
@@ -274,6 +279,7 @@ PropertyInfo qdev_prop_string = {
.size = sizeof(char*),
.parse = parse_string,
.print = print_string,
+ .free = free_string,
};
/* --- drive --- */
diff --git a/hw/qdev.c b/hw/qdev.c
index aa2ce01..29f6e9f 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -334,6 +334,7 @@ void qdev_init_nofail(DeviceState *dev)
void qdev_free(DeviceState *dev)
{
BusState *bus;
+ Property *prop;
if (dev->state == DEV_STATE_INITIALIZED) {
while (dev->num_child_bus) {
@@ -349,6 +350,11 @@ void qdev_free(DeviceState *dev)
}
qemu_unregister_reset(qdev_reset, dev);
QLIST_REMOVE(dev, sibling);
+ for (prop = dev->info->props; prop && prop->name; prop++) {
+ if (prop->info->free) {
+ prop->info->free(dev, prop);
+ }
+ }
qemu_free(dev);
}
diff --git a/hw/qdev.h b/hw/qdev.h
index 7c25a94..51a24e2 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -98,6 +98,7 @@ struct PropertyInfo {
enum PropertyType type;
int (*parse)(DeviceState *dev, Property *prop, const char *str);
int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len);
+ void (*free)(DeviceState *dev, Property *prop);
};
typedef struct GlobalProperty {
commit cc98467327e13adca8f65b5a841c08930ee68220
Author: Markus Armbruster <armbru at redhat.com>
Date: Tue Jun 1 20:32:30 2010 +0200
qdev: New qdev_prop_set_string()
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 9ffdba7..b6ee50f 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -617,6 +617,11 @@ void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value)
qdev_prop_set(dev, name, &value, PROP_TYPE_UINT64);
}
+void qdev_prop_set_string(DeviceState *dev, const char *name, char *value)
+{
+ qdev_prop_set(dev, name, &value, PROP_TYPE_STRING);
+}
+
void qdev_prop_set_drive(DeviceState *dev, const char *name, DriveInfo *value)
{
qdev_prop_set(dev, name, &value, PROP_TYPE_DRIVE);
diff --git a/hw/qdev.h b/hw/qdev.h
index a44060e..7c25a94 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -268,6 +268,7 @@ void qdev_prop_set_uint16(DeviceState *dev, const char *name, uint16_t value);
void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value);
void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value);
void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value);
+void qdev_prop_set_string(DeviceState *dev, const char *name, char *value);
void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value);
void qdev_prop_set_netdev(DeviceState *dev, const char *name, VLANClientState *value);
void qdev_prop_set_vlan(DeviceState *dev, const char *name, VLANState *value);
commit 57234ee40d314f91cf5bd16a926f30a6985e06e2
Author: Markus Armbruster <armbru at redhat.com>
Date: Tue Jun 1 20:32:29 2010 +0200
ide: Split non-qdev code off ide_init2()
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index cdcc9bf..559147f 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -260,8 +260,8 @@ static int pci_cmd646_ide_initfn(PCIDevice *dev)
irq = qemu_allocate_irqs(cmd646_set_irq, d, 2);
ide_bus_new(&d->bus[0], &d->dev.qdev);
ide_bus_new(&d->bus[1], &d->dev.qdev);
- ide_init2(&d->bus[0], NULL, NULL, irq[0]);
- ide_init2(&d->bus[1], NULL, NULL, irq[1]);
+ ide_init2(&d->bus[0], irq[0]);
+ ide_init2(&d->bus[1], irq[1]);
vmstate_register(0, &vmstate_ide_pci, d);
qemu_register_reset(cmd646_reset, d);
diff --git a/hw/ide/core.c b/hw/ide/core.c
index cb7af38..d3328cd 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -2632,7 +2632,7 @@ void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version)
ide_reset(s);
}
-static void ide_init1(IDEBus *bus, int unit, DriveInfo *dinfo)
+static void ide_init1(IDEBus *bus, int unit)
{
static int drive_serial = 1;
IDEState *s = &bus->ifs[unit];
@@ -2645,20 +2645,34 @@ static void ide_init1(IDEBus *bus, int unit, DriveInfo *dinfo)
s->smart_selftest_data = qemu_blockalign(s->bs, 512);
s->sector_write_timer = qemu_new_timer(vm_clock,
ide_sector_write_timer_cb, s);
- if (dinfo) {
- ide_init_drive(s, dinfo, NULL);
- } else {
- ide_reset(s);
+}
+
+void ide_init2(IDEBus *bus, qemu_irq irq)
+{
+ int i;
+
+ for(i = 0; i < 2; i++) {
+ ide_init1(bus, i);
+ ide_reset(&bus->ifs[i]);
}
+ bus->irq = irq;
}
-void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1,
- qemu_irq irq)
+/* TODO convert users to qdev and remove */
+void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
+ DriveInfo *hd1, qemu_irq irq)
{
int i;
+ DriveInfo *dinfo;
for(i = 0; i < 2; i++) {
- ide_init1(bus, i, i == 0 ? hd0 : hd1);
+ dinfo = i == 0 ? hd0 : hd1;
+ ide_init1(bus, i);
+ if (dinfo) {
+ ide_init_drive(&bus->ifs[i], dinfo, NULL);
+ } else {
+ ide_reset(&bus->ifs[i]);
+ }
}
bus->irq = irq;
}
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index cf71019..6b0024d 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -555,8 +555,9 @@ void ide_data_writel(void *opaque, uint32_t addr, uint32_t val);
uint32_t ide_data_readl(void *opaque, uint32_t addr);
void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version);
-void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1,
- qemu_irq irq);
+void ide_init2(IDEBus *bus, qemu_irq irq);
+void ide_init2_with_non_qdev_drives(IDEBus *bus, DriveInfo *hd0,
+ DriveInfo *hd1, qemu_irq irq);
void ide_init_ioport(IDEBus *bus, int iobase, int iobase2);
/* hw/ide/qdev.c */
diff --git a/hw/ide/isa.c b/hw/ide/isa.c
index dff7c79..b6c6347 100644
--- a/hw/ide/isa.c
+++ b/hw/ide/isa.c
@@ -70,7 +70,7 @@ static int isa_ide_initfn(ISADevice *dev)
ide_bus_new(&s->bus, &s->dev.qdev);
ide_init_ioport(&s->bus, s->iobase, s->iobase2);
isa_init_irq(dev, &s->irq, s->isairq);
- ide_init2(&s->bus, NULL, NULL, s->irq);
+ ide_init2(&s->bus, s->irq);
vmstate_register(0, &vmstate_ide_isa, s);
return 0;
};
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index 639f3f6..f76c0fa 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -314,7 +314,7 @@ int pmac_ide_init (DriveInfo **hd_table, qemu_irq irq,
int pmac_ide_memory;
d = qemu_mallocz(sizeof(MACIOIDEState));
- ide_init2(&d->bus, hd_table[0], hd_table[1], irq);
+ ide_init2_with_non_qdev_drives(&d->bus, hd_table[0], hd_table[1], irq);
if (dbdma)
DBDMA_register_channel(dbdma, channel, dma_irq, pmac_ide_transfer, pmac_ide_flush, d);
diff --git a/hw/ide/microdrive.c b/hw/ide/microdrive.c
index bfdb8c8..a7beac5 100644
--- a/hw/ide/microdrive.c
+++ b/hw/ide/microdrive.c
@@ -539,7 +539,8 @@ PCMCIACardState *dscm1xxxx_init(DriveInfo *bdrv)
md->card.cis = dscm1xxxx_cis;
md->card.cis_len = sizeof(dscm1xxxx_cis);
- ide_init2(&md->bus, bdrv, NULL, qemu_allocate_irqs(md_set_irq, md, 1)[0]);
+ ide_init2_with_non_qdev_drives(&md->bus, bdrv, NULL,
+ qemu_allocate_irqs(md_set_irq, md, 1)[0]);
md->bus.ifs[0].is_cf = 1;
md->bus.ifs[0].mdata_size = METADATA_SIZE;
md->bus.ifs[0].mdata_storage = (uint8_t *) qemu_mallocz(METADATA_SIZE);
diff --git a/hw/ide/mmio.c b/hw/ide/mmio.c
index cca883f..e75cccf 100644
--- a/hw/ide/mmio.c
+++ b/hw/ide/mmio.c
@@ -125,7 +125,7 @@ void mmio_ide_init (target_phys_addr_t membase, target_phys_addr_t membase2,
MMIOState *s = qemu_mallocz(sizeof(MMIOState));
int mem1, mem2;
- ide_init2(&s->bus, hd0, hd1, irq);
+ ide_init2_with_non_qdev_drives(&s->bus, hd0, hd1, irq);
s->shift = shift;
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index 4fa3851..dad6e86 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -135,8 +135,8 @@ static int pci_piix_ide_initfn(PCIIDEState *d)
ide_init_ioport(&d->bus[0], 0x1f0, 0x3f6);
ide_init_ioport(&d->bus[1], 0x170, 0x376);
- ide_init2(&d->bus[0], NULL, NULL, isa_reserve_irq(14));
- ide_init2(&d->bus[1], NULL, NULL, isa_reserve_irq(15));
+ ide_init2(&d->bus[0], isa_reserve_irq(14));
+ ide_init2(&d->bus[1], isa_reserve_irq(15));
return 0;
}
commit 870111c8ed95df62a101eae0acd08c84233a6341
Author: Markus Armbruster <armbru at redhat.com>
Date: Tue Jun 1 20:32:28 2010 +0200
ide: Change ide_init_drive() to require valid dinfo argument
IDEState members drive_serial_str and version are now left empty until
an actual drive is connected. Before, they got a default value that
was overwritten when a drive got connected. Doesn't matter, because
they're used only while a drive is connected.
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 443ff10..cb7af38 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -2601,30 +2601,29 @@ void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version)
int cylinders, heads, secs;
uint64_t nb_sectors;
- if (dinfo && dinfo->bdrv) {
- s->bs = dinfo->bdrv;
- bdrv_get_geometry(s->bs, &nb_sectors);
- bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
- s->cylinders = cylinders;
- s->heads = heads;
- s->sectors = secs;
- s->nb_sectors = nb_sectors;
- /* The SMART values should be preserved across power cycles
- but they aren't. */
- s->smart_enabled = 1;
- s->smart_autosave = 1;
- s->smart_errors = 0;
- s->smart_selftest_count = 0;
- if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
- s->is_cdrom = 1;
- bdrv_set_change_cb(s->bs, cdrom_change_cb, s);
- }
- strncpy(s->drive_serial_str, drive_get_serial(s->bs),
- sizeof(s->drive_serial_str));
+ s->bs = dinfo->bdrv;
+ bdrv_get_geometry(s->bs, &nb_sectors);
+ bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
+ s->cylinders = cylinders;
+ s->heads = heads;
+ s->sectors = secs;
+ s->nb_sectors = nb_sectors;
+ /* The SMART values should be preserved across power cycles
+ but they aren't. */
+ s->smart_enabled = 1;
+ s->smart_autosave = 1;
+ s->smart_errors = 0;
+ s->smart_selftest_count = 0;
+ if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
+ s->is_cdrom = 1;
+ bdrv_set_change_cb(s->bs, cdrom_change_cb, s);
}
- if (strlen(s->drive_serial_str) == 0)
+ strncpy(s->drive_serial_str, drive_get_serial(s->bs),
+ sizeof(s->drive_serial_str));
+ if (!*s->drive_serial_str) {
snprintf(s->drive_serial_str, sizeof(s->drive_serial_str),
"QM%05d", s->drive_serial);
+ }
if (version) {
pstrcpy(s->version, sizeof(s->version), version);
} else {
@@ -2646,7 +2645,11 @@ static void ide_init1(IDEBus *bus, int unit, DriveInfo *dinfo)
s->smart_selftest_data = qemu_blockalign(s->bs, 512);
s->sector_write_timer = qemu_new_timer(vm_clock,
ide_sector_write_timer_cb, s);
- ide_init_drive(s, dinfo, NULL);
+ if (dinfo) {
+ ide_init_drive(s, dinfo, NULL);
+ } else {
+ ide_reset(s);
+ }
}
void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1,
commit d459da0ed4bcdc38d5aaaa78f0c83fdeac6dd190
Author: Markus Armbruster <armbru at redhat.com>
Date: Fri May 28 15:38:47 2010 +0200
ide: Split ide_init1() off ide_init2()
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/ide/core.c b/hw/ide/core.c
index c3334b1..443ff10 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -2633,27 +2633,29 @@ void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version)
ide_reset(s);
}
+static void ide_init1(IDEBus *bus, int unit, DriveInfo *dinfo)
+{
+ static int drive_serial = 1;
+ IDEState *s = &bus->ifs[unit];
+
+ s->bus = bus;
+ s->unit = unit;
+ s->drive_serial = drive_serial++;
+ s->io_buffer = qemu_blockalign(s->bs, IDE_DMA_BUF_SECTORS*512 + 4);
+ s->io_buffer_total_len = IDE_DMA_BUF_SECTORS*512 + 4;
+ s->smart_selftest_data = qemu_blockalign(s->bs, 512);
+ s->sector_write_timer = qemu_new_timer(vm_clock,
+ ide_sector_write_timer_cb, s);
+ ide_init_drive(s, dinfo, NULL);
+}
+
void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1,
qemu_irq irq)
{
- IDEState *s;
- static int drive_serial = 1;
int i;
for(i = 0; i < 2; i++) {
- s = bus->ifs + i;
- s->bus = bus;
- s->unit = i;
- s->drive_serial = drive_serial++;
- s->io_buffer = qemu_blockalign(s->bs, IDE_DMA_BUF_SECTORS*512 + 4);
- s->io_buffer_total_len = IDE_DMA_BUF_SECTORS*512 + 4;
- s->smart_selftest_data = qemu_blockalign(s->bs, 512);
- s->sector_write_timer = qemu_new_timer(vm_clock,
- ide_sector_write_timer_cb, s);
- if (i == 0)
- ide_init_drive(s, hd0, NULL);
- if (i == 1)
- ide_init_drive(s, hd1, NULL);
+ ide_init1(bus, i, i == 0 ? hd0 : hd1);
}
bus->irq = irq;
}
commit 57dac7ef8aeabcd17b1ceee2296917bc48ccd526
Author: Markus Armbruster <armbru at redhat.com>
Date: Fri May 28 15:38:46 2010 +0200
ide: Remove redundant IDEState member conf
Commit 428c149b added IDEState member conf to let commit 0009baf1 find
the BlockConf from there. It exists only for qdev drives, created via
ide_drive_initfn(), not for drives created via ide_init2().
But for a qdev drive, we can just as well reach its IDEDevice, which
contains the BlockConf. Do that, and revert the parts of commit
428c149b that add IDEState member conf.
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/ide/core.c b/hw/ide/core.c
index 066fecb..c3334b1 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -98,6 +98,7 @@ static void ide_identify(IDEState *s)
{
uint16_t *p;
unsigned int oldsize;
+ IDEDevice *dev;
if (s->identify_set) {
memcpy(s->io_buffer, s->identify_data, sizeof(s->identify_data));
@@ -165,8 +166,9 @@ static void ide_identify(IDEState *s)
put_le16(p + 101, s->nb_sectors >> 16);
put_le16(p + 102, s->nb_sectors >> 32);
put_le16(p + 103, s->nb_sectors >> 48);
- if (s->conf && s->conf->physical_block_size)
- put_le16(p + 106, 0x6000 | get_physical_block_exp(s->conf));
+ dev = s->unit ? s->bus->slave : s->bus->master;
+ if (dev && dev->conf.physical_block_size)
+ put_le16(p + 106, 0x6000 | get_physical_block_exp(&dev->conf));
memcpy(s->identify_data, p, sizeof(s->identify_data));
s->identify_set = 1;
@@ -2594,8 +2596,7 @@ void ide_bus_reset(IDEBus *bus)
ide_clear_hob(bus);
}
-void ide_init_drive(IDEState *s, DriveInfo *dinfo, BlockConf *conf,
- const char *version)
+void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version)
{
int cylinders, heads, secs;
uint64_t nb_sectors;
@@ -2620,9 +2621,6 @@ void ide_init_drive(IDEState *s, DriveInfo *dinfo, BlockConf *conf,
}
strncpy(s->drive_serial_str, drive_get_serial(s->bs),
sizeof(s->drive_serial_str));
- if (conf) {
- s->conf = conf;
- }
}
if (strlen(s->drive_serial_str) == 0)
snprintf(s->drive_serial_str, sizeof(s->drive_serial_str),
@@ -2653,9 +2651,9 @@ void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1,
s->sector_write_timer = qemu_new_timer(vm_clock,
ide_sector_write_timer_cb, s);
if (i == 0)
- ide_init_drive(s, hd0, NULL, NULL);
+ ide_init_drive(s, hd0, NULL);
if (i == 1)
- ide_init_drive(s, hd1, NULL, NULL);
+ ide_init_drive(s, hd1, NULL);
}
bus->irq = irq;
}
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index b4554ce..cf71019 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -398,7 +398,6 @@ struct IDEState {
/* set for lba48 access */
uint8_t lba48;
BlockDriverState *bs;
- BlockConf *conf;
char version[9];
/* ATAPI specific */
uint8_t sense_key;
@@ -555,8 +554,7 @@ uint32_t ide_data_readw(void *opaque, uint32_t addr);
void ide_data_writel(void *opaque, uint32_t addr, uint32_t val);
uint32_t ide_data_readl(void *opaque, uint32_t addr);
-void ide_init_drive(IDEState *s, DriveInfo *dinfo, BlockConf *conf,
- const char *version);
+void ide_init_drive(IDEState *s, DriveInfo *dinfo, const char *version);
void ide_init2(IDEBus *bus, DriveInfo *hd0, DriveInfo *hd1,
qemu_irq irq);
void ide_init_ioport(IDEBus *bus, int iobase, int iobase2);
diff --git a/hw/ide/qdev.c b/hw/ide/qdev.c
index b18693d..9ebb906 100644
--- a/hw/ide/qdev.c
+++ b/hw/ide/qdev.c
@@ -99,8 +99,7 @@ typedef struct IDEDrive {
static int ide_drive_initfn(IDEDevice *dev)
{
IDEBus *bus = DO_UPCAST(IDEBus, qbus, dev->qdev.parent_bus);
- ide_init_drive(bus->ifs + dev->unit, dev->conf.dinfo, &dev->conf,
- dev->version);
+ ide_init_drive(bus->ifs + dev->unit, dev->conf.dinfo, dev->version);
return 0;
}
commit 124964b54e0c50706385691142795b6e43dad817
Author: Markus Armbruster <armbru at redhat.com>
Date: Fri May 28 15:38:45 2010 +0200
ide: Remove useless IDEDeviceInfo members unit, drive
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/ide/internal.h b/hw/ide/internal.h
index 2efc784..b4554ce 100644
--- a/hw/ide/internal.h
+++ b/hw/ide/internal.h
@@ -464,8 +464,6 @@ typedef int (*ide_qdev_initfn)(IDEDevice *dev);
struct IDEDeviceInfo {
DeviceInfo qdev;
ide_qdev_initfn init;
- uint32_t unit;
- DriveInfo *drive;
};
#define BM_STATUS_DMAING 0x01
commit fb08000cee257bbd3f3a043933a6474d870c665f
Author: Markus Armbruster <armbru at redhat.com>
Date: Fri May 28 15:38:44 2010 +0200
usb: Remove unused usb_device_add() parameter is_hotplug
Unused since commit b3e461d3.
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/vl.c b/vl.c
index 9283469..76a9b25 100644
--- a/vl.c
+++ b/vl.c
@@ -1315,7 +1315,7 @@ static void smp_parse(const char *optarg)
/***********************************************************/
/* USB devices */
-static int usb_device_add(const char *devname, int is_hotplug)
+static int usb_device_add(const char *devname)
{
const char *p;
USBDevice *dev = NULL;
@@ -1367,7 +1367,7 @@ static int usb_device_del(const char *devname)
static int usb_parse(const char *cmdline)
{
int r;
- r = usb_device_add(cmdline, 0);
+ r = usb_device_add(cmdline);
if (r < 0) {
fprintf(stderr, "qemu: could not add USB device '%s'\n", cmdline);
}
@@ -1377,7 +1377,7 @@ static int usb_parse(const char *cmdline)
void do_usb_add(Monitor *mon, const QDict *qdict)
{
const char *devname = qdict_get_str(qdict, "devname");
- if (usb_device_add(devname, 1) < 0) {
+ if (usb_device_add(devname) < 0) {
error_report("could not add USB device '%s'", devname);
}
}
commit f274776028ddb026f8891cabaf59bd58dbfc31bd
Author: Markus Armbruster <armbru at redhat.com>
Date: Fri May 28 15:38:43 2010 +0200
blockdev: Belatedly remove driveopts
Unused since commit 9dfd7c7a.
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/sysemu.h b/sysemu.h
index 063319c..fd83b7d 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -178,7 +178,6 @@ typedef struct DriveInfo {
#define MAX_SCSI_DEVS 7
extern QTAILQ_HEAD(drivelist, DriveInfo) drives;
-extern QTAILQ_HEAD(driveoptlist, DriveOpt) driveopts;
extern DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit);
extern DriveInfo *drive_get_by_id(const char *id);
diff --git a/vl.c b/vl.c
index f8d3034..9283469 100644
--- a/vl.c
+++ b/vl.c
@@ -173,7 +173,6 @@ int main(int argc, char **argv)
static const char *data_dir;
const char *bios_name = NULL;
struct drivelist drives = QTAILQ_HEAD_INITIALIZER(drives);
-struct driveoptlist driveopts = QTAILQ_HEAD_INITIALIZER(driveopts);
enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
DisplayType display_type = DT_DEFAULT;
const char* keyboard_layout = NULL;
commit 1a43782e34e148a00a0bb8f5de56f2d93a0f0320
Author: Markus Armbruster <armbru at redhat.com>
Date: Fri May 28 15:38:42 2010 +0200
blockdev: Belatedly remove MAX_DRIVES
Unused since commit 751c6a17.
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/sysemu.h b/sysemu.h
index 879446a..063319c 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -176,7 +176,6 @@ typedef struct DriveInfo {
#define MAX_IDE_DEVS 2
#define MAX_SCSI_DEVS 7
-#define MAX_DRIVES 32
extern QTAILQ_HEAD(drivelist, DriveInfo) drives;
extern QTAILQ_HEAD(driveoptlist, DriveOpt) driveopts;
diff --git a/vl.c b/vl.c
index 7121cd0..f8d3034 100644
--- a/vl.c
+++ b/vl.c
@@ -172,8 +172,6 @@ int main(int argc, char **argv)
static const char *data_dir;
const char *bios_name = NULL;
-/* Note: drives_table[MAX_DRIVES] is a dummy block driver if none available
- to store the VM snapshots */
struct drivelist drives = QTAILQ_HEAD_INITIALIZER(drives);
struct driveoptlist driveopts = QTAILQ_HEAD_INITIALIZER(driveopts);
enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
commit 0923c577f993d61eeaf41f66db1e1010fa113976
Author: Kevin Wolf <kwolf at redhat.com>
Date: Fri May 28 20:10:48 2010 +0200
qemu-io: Fix error messages
The truncate and getlength commands passed a negative error number to strerror.
They also happen to be the two functions that are lacking a newline at the end
of their error message.
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/qemu-io.c b/qemu-io.c
index 72a4524..7c6120b 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -1317,7 +1317,7 @@ truncate_f(int argc, char **argv)
ret = bdrv_truncate(bs, offset);
if (ret < 0) {
- printf("truncate: %s", strerror(ret));
+ printf("truncate: %s\n", strerror(-ret));
return 0;
}
@@ -1342,7 +1342,7 @@ length_f(int argc, char **argv)
size = bdrv_getlength(bs);
if (size < 0) {
- printf("getlength: %s", strerror(size));
+ printf("getlength: %s\n", strerror(-size));
return 0;
}
commit 1573a35d99fe60f98d30f50e9187040586c2b801
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Thu May 27 16:20:33 2010 +0200
Cleanup: virtio-blk.c: Be more consistent using BDRV_SECTOR_SIZE instead
Clean up virtio-blk.c to be more consistent using BDRV_SECTOR_SIZE
instead of hard coded 512 values.
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index 5d7f1a2..80d51c4 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -277,7 +277,7 @@ static void virtio_blk_handle_write(BlockRequest *blkreq, int *num_writes,
}
blkreq[*num_writes].sector = req->out->sector;
- blkreq[*num_writes].nb_sectors = req->qiov.size / 512;
+ blkreq[*num_writes].nb_sectors = req->qiov.size / BDRV_SECTOR_SIZE;
blkreq[*num_writes].qiov = &req->qiov;
blkreq[*num_writes].cb = virtio_blk_rw_complete;
blkreq[*num_writes].opaque = req;
@@ -296,7 +296,8 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req)
}
acb = bdrv_aio_readv(req->dev->bs, req->out->sector, &req->qiov,
- req->qiov.size / 512, virtio_blk_rw_complete, req);
+ req->qiov.size / BDRV_SECTOR_SIZE,
+ virtio_blk_rw_complete, req);
if (!acb) {
virtio_blk_rw_complete(req, -EIO);
}
@@ -505,7 +506,7 @@ VirtIODevice *virtio_blk_init(DeviceState *dev, BlockConf *conf)
s->bs = conf->dinfo->bdrv;
s->conf = conf;
s->rq = NULL;
- s->sector_mask = (s->conf->logical_block_size / 512) - 1;
+ s->sector_mask = (s->conf->logical_block_size / BDRV_SECTOR_SIZE) - 1;
bdrv_guess_geometry(s->bs, &cylinders, &heads, &secs);
s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);
commit 9040385dcc0a4b32ca8ceeda6dc679aea56e3832
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Thu May 27 16:20:32 2010 +0200
Cleanup: raw-posix.c: Be more consistent using BDRV_SECTOR_SIZE instead of 512
Clean up raw-posix.c to be more consistent using BDRV_SECTOR_SIZE
instead of hard coded 512 values.
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block/raw-posix.c b/block/raw-posix.c
index 7541ed2..3f0701b 100644
--- a/block/raw-posix.c
+++ b/block/raw-posix.c
@@ -392,8 +392,9 @@ static int raw_read(BlockDriverState *bs, int64_t sector_num,
{
int ret;
- ret = raw_pread(bs, sector_num * 512, buf, nb_sectors * 512);
- if (ret == (nb_sectors * 512))
+ ret = raw_pread(bs, sector_num * BDRV_SECTOR_SIZE, buf,
+ nb_sectors * BDRV_SECTOR_SIZE);
+ if (ret == (nb_sectors * BDRV_SECTOR_SIZE))
ret = 0;
return ret;
}
@@ -480,8 +481,9 @@ static int raw_write(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors)
{
int ret;
- ret = raw_pwrite(bs, sector_num * 512, buf, nb_sectors * 512);
- if (ret == (nb_sectors * 512))
+ ret = raw_pwrite(bs, sector_num * BDRV_SECTOR_SIZE, buf,
+ nb_sectors * BDRV_SECTOR_SIZE);
+ if (ret == (nb_sectors * BDRV_SECTOR_SIZE))
ret = 0;
return ret;
}
@@ -494,7 +496,7 @@ static int qiov_is_aligned(QEMUIOVector *qiov)
int i;
for (i = 0; i < qiov->niov; i++) {
- if ((uintptr_t) qiov->iov[i].iov_base % 512) {
+ if ((uintptr_t) qiov->iov[i].iov_base % BDRV_SECTOR_SIZE) {
return 0;
}
}
@@ -703,7 +705,7 @@ static int raw_create(const char *filename, QEMUOptionParameter *options)
/* Read out options */
while (options && options->name) {
if (!strcmp(options->name, BLOCK_OPT_SIZE)) {
- total_size = options->value.n / 512;
+ total_size = options->value.n / BDRV_SECTOR_SIZE;
}
options++;
}
@@ -713,7 +715,7 @@ static int raw_create(const char *filename, QEMUOptionParameter *options)
if (fd < 0) {
result = -errno;
} else {
- if (ftruncate(fd, total_size * 512) != 0) {
+ if (ftruncate(fd, total_size * BDRV_SECTOR_SIZE) != 0) {
result = -errno;
}
if (close(fd) != 0) {
@@ -976,7 +978,7 @@ static int hdev_create(const char *filename, QEMUOptionParameter *options)
/* Read out options */
while (options && options->name) {
if (!strcmp(options->name, "size")) {
- total_size = options->value.n / 512;
+ total_size = options->value.n / BDRV_SECTOR_SIZE;
}
options++;
}
@@ -989,7 +991,7 @@ static int hdev_create(const char *filename, QEMUOptionParameter *options)
ret = -errno;
else if (!S_ISBLK(stat_buf.st_mode) && !S_ISCHR(stat_buf.st_mode))
ret = -ENODEV;
- else if (lseek(fd, 0, SEEK_END) < total_size * 512)
+ else if (lseek(fd, 0, SEEK_END) < total_size * BDRV_SECTOR_SIZE)
ret = -ENOSPC;
close(fd);
commit eb5a316514144bc1def4cb9b88fb996420ca80cc
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Thu May 27 16:20:31 2010 +0200
Cleanup: Be consistent and use BDRV_SECTOR_SIZE instead of 512
Clean up block.c and use BDRV_SECTOR_SIZE rather than hard coded
numbers (512) when referring to sector size throughout the code.
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block.c b/block.c
index 8385b4f..9c43332 100644
--- a/block.c
+++ b/block.c
@@ -684,7 +684,7 @@ int bdrv_commit(BlockDriverState *bs)
int64_t i, total_sectors;
int n, j, ro, open_flags;
int ret = 0, rw_ret = 0;
- unsigned char sector[512];
+ unsigned char sector[BDRV_SECTOR_SIZE];
char filename[1024];
BlockDriverState *bs_rw, *bs_ro;
@@ -824,7 +824,8 @@ static int bdrv_check_byte_request(BlockDriverState *bs, int64_t offset,
static int bdrv_check_request(BlockDriverState *bs, int64_t sector_num,
int nb_sectors)
{
- return bdrv_check_byte_request(bs, sector_num * 512, nb_sectors * 512);
+ return bdrv_check_byte_request(bs, sector_num * BDRV_SECTOR_SIZE,
+ nb_sectors * BDRV_SECTOR_SIZE);
}
/* return < 0 if error. See bdrv_write() for the return codes */
@@ -1059,7 +1060,7 @@ struct partition {
static int guess_disk_lchs(BlockDriverState *bs,
int *pcylinders, int *pheads, int *psectors)
{
- uint8_t buf[512];
+ uint8_t buf[BDRV_SECTOR_SIZE];
int ret, i, heads, sectors, cylinders;
struct partition *p;
uint32_t nr_sects;
@@ -1535,7 +1536,7 @@ static QObject* bdrv_info_stats_bs(BlockDriverState *bs)
"} }",
bs->rd_bytes, bs->wr_bytes,
bs->rd_ops, bs->wr_ops,
- bs->wr_highest_sector * 512);
+ bs->wr_highest_sector * (long)BDRV_SECTOR_SIZE);
dict = qobject_to_qdict(res);
if (*bs->device_name) {
@@ -2197,7 +2198,7 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
async_ret = NOT_DONE;
iov.iov_base = (void *)buf;
- iov.iov_len = nb_sectors * 512;
+ iov.iov_len = nb_sectors * BDRV_SECTOR_SIZE;
qemu_iovec_init_external(&qiov, &iov, 1);
acb = bdrv_aio_readv(bs, sector_num, &qiov, nb_sectors,
bdrv_rw_em_cb, &async_ret);
@@ -2228,7 +2229,7 @@ static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
async_ret = NOT_DONE;
iov.iov_base = (void *)buf;
- iov.iov_len = nb_sectors * 512;
+ iov.iov_len = nb_sectors * BDRV_SECTOR_SIZE;
qemu_iovec_init_external(&qiov, &iov, 1);
acb = bdrv_aio_writev(bs, sector_num, &qiov, nb_sectors,
bdrv_rw_em_cb, &async_ret);
commit 3e82990b52d5afeb4957dd9b87be83d752e369b9
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Thu May 27 16:20:30 2010 +0200
Cleanup: bdrv_open() no need to shift total_size just to shift back.
In bdrv_open() there is no need to shift total_size >> 9 just to
multiply it by 512 again just a few lines later, since this is the
only place the variable is used.
Mask with BDRV_SECTOR_MASK to protect against case where we are
passed a corrupted image.
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block.c b/block.c
index 39724c1..8385b4f 100644
--- a/block.c
+++ b/block.c
@@ -522,7 +522,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
bdrv_delete(bs1);
return ret;
}
- total_size = bdrv_getlength(bs1) >> BDRV_SECTOR_BITS;
+ total_size = bdrv_getlength(bs1) & BDRV_SECTOR_MASK;
if (bs1->drv && bs1->drv->protocol_name)
is_protocol = 1;
@@ -541,7 +541,7 @@ int bdrv_open(BlockDriverState *bs, const char *filename, int flags,
bdrv_qcow2 = bdrv_find_format("qcow2");
options = parse_option_parameters("", bdrv_qcow2->create_options, NULL);
- set_option_parameter_int(options, BLOCK_OPT_SIZE, total_size * 512);
+ set_option_parameter_int(options, BLOCK_OPT_SIZE, total_size);
set_option_parameter(options, BLOCK_OPT_BACKING_FILE, backing_filename);
if (drv) {
set_option_parameter(options, BLOCK_OPT_BACKING_FMT,
commit 358c360feb346dff8f911e2d1dbcdd6319393f1d
Merge: 41ef56e... 1a39685...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date: Thu Jun 3 14:55:49 2010 -0500
Merge remote branch 'kwolf/for-anthony' into staging
commit 41ef56e61153d7bd27d34a634633bb51b1c5988d
Author: Anthony Liguori <aliguori at us.ibm.com>
Date: Wed Jun 2 14:55:25 2010 -0500
migration: respect exit status with exec:
This patch makes sure that if the exec: process exits with a non-zero return
status, we treat the migration as failed.
This fixes https://bugs.launchpad.net/qemu/+bug/391879
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/migration-exec.c b/migration-exec.c
index 5435827..93bde62 100644
--- a/migration-exec.c
+++ b/migration-exec.c
@@ -43,13 +43,21 @@ static int file_write(FdMigrationState *s, const void * buf, size_t size)
static int exec_close(FdMigrationState *s)
{
+ int ret = 0;
DPRINTF("exec_close\n");
if (s->opaque) {
- qemu_fclose(s->opaque);
+ ret = qemu_fclose(s->opaque);
s->opaque = NULL;
s->fd = -1;
+ if (ret != -1 &&
+ WIFEXITED(ret)
+ && WEXITSTATUS(ret) == 0) {
+ ret = 0;
+ } else {
+ ret = -1;
+ }
}
- return 0;
+ return ret;
}
MigrationState *exec_start_outgoing_migration(Monitor *mon,
diff --git a/migration.c b/migration.c
index 706fe55..fbf2339 100644
--- a/migration.c
+++ b/migration.c
@@ -252,13 +252,17 @@ void migrate_fd_error(FdMigrationState *s)
migrate_fd_cleanup(s);
}
-void migrate_fd_cleanup(FdMigrationState *s)
+int migrate_fd_cleanup(FdMigrationState *s)
{
+ int ret = 0;
+
qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
if (s->file) {
DPRINTF("closing file\n");
- qemu_fclose(s->file);
+ if (qemu_fclose(s->file) != 0) {
+ ret = -1;
+ }
s->file = NULL;
}
@@ -271,6 +275,8 @@ void migrate_fd_cleanup(FdMigrationState *s)
}
s->fd = -1;
+
+ return ret;
}
void migrate_fd_put_notify(void *opaque)
@@ -349,7 +355,12 @@ void migrate_fd_put_ready(void *opaque)
} else {
state = MIG_STATE_COMPLETED;
}
- migrate_fd_cleanup(s);
+ if (migrate_fd_cleanup(s) < 0) {
+ if (old_vm_running) {
+ vm_start();
+ }
+ state = MIG_STATE_ERROR;
+ }
s->state = state;
}
}
diff --git a/migration.h b/migration.h
index 385423f..97eef4a 100644
--- a/migration.h
+++ b/migration.h
@@ -107,7 +107,7 @@ void migrate_fd_monitor_suspend(FdMigrationState *s, Monitor *mon);
void migrate_fd_error(FdMigrationState *s);
-void migrate_fd_cleanup(FdMigrationState *s);
+int migrate_fd_cleanup(FdMigrationState *s);
void migrate_fd_put_notify(void *opaque);
diff --git a/savevm.c b/savevm.c
index dc20390..af92ba2 100644
--- a/savevm.c
+++ b/savevm.c
@@ -235,9 +235,10 @@ static int stdio_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
static int stdio_pclose(void *opaque)
{
QEMUFileStdio *s = opaque;
- pclose(s->stdio_file);
+ int ret;
+ ret = pclose(s->stdio_file);
qemu_free(s);
- return 0;
+ return ret;
}
static int stdio_fclose(void *opaque)
commit 4309a79bffce10d6d8de82c5ee403ffa4f45db64
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Thu Jun 3 00:02:30 2010 +0200
tcg-i386: fix a typo
Fix a typo introduced by c28b14c694d759f39fe3ae4f8d03b567da5b93f8.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index e16557e..3600c35 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -726,7 +726,7 @@ static void *qemu_st_helpers[4] = {
static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx,
int mem_index, int s_bits,
- const TCGArg *args
+ const TCGArg *args,
uint8_t **label_ptr, int which)
{
const int addrlo = args[addrlo_idx];
commit c28b14c694d759f39fe3ae4f8d03b567da5b93f8
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Tue Jun 1 13:55:18 2010 +0200
tcg-i386: declare tcg_out_tlb_load() inline
Declare tcg_out_tlb_load() inline so that we don't loose optimisations
with commit 8516a04467cb7954cdc32e8b79b4b7df56dccb16.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 8a9122c..e16557e 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -724,9 +724,10 @@ static void *qemu_st_helpers[4] = {
EDX is clobbered. */
-static void tcg_out_tlb_load(TCGContext *s, int addrlo_idx, int mem_index,
- int s_bits, const TCGArg *args,
- uint8_t **label_ptr, int which)
+static inline void tcg_out_tlb_load(TCGContext *s, int addrlo_idx,
+ int mem_index, int s_bits,
+ const TCGArg *args
+ uint8_t **label_ptr, int which)
{
const int addrlo = args[addrlo_idx];
const int r0 = TCG_REG_EAX;
commit 82bb07db0c3f0685dbdc5050d57f0c26ad6ff844
Author: Richard Henderson <rth at twiddle.net>
Date: Fri May 21 09:03:04 2010 -0700
tcg-i386: Remove some ifdefs in qemu_ld/st.
Tidy some code by replacing ifdefs by C ifs.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index cf621da..8a9122c 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -842,7 +842,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
int data_reg, data_reg2 = 0;
int addrlo_idx;
#if defined(CONFIG_SOFTMMU)
- int mem_index, s_bits;
+ int mem_index, s_bits, arg_idx;
uint8_t *label_ptr[3];
#endif
@@ -877,12 +877,14 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
}
/* XXX: move that code at the end of the TB */
-#if TARGET_LONG_BITS == 32
- tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EDX, mem_index);
-#else
- tcg_out_mov(s, TCG_REG_EDX, args[addrlo_idx + 1]);
- tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
-#endif
+ /* EAX is already loaded. */
+ arg_idx = 1;
+ if (TARGET_LONG_BITS == 64) {
+ tcg_out_mov(s, tcg_target_call_iarg_regs[arg_idx++],
+ args[addrlo_idx + 1]);
+ }
+ tcg_out_movi(s, TCG_TYPE_I32, tcg_target_call_iarg_regs[arg_idx],
+ mem_index);
tcg_out_calli(s, (tcg_target_long)qemu_ld_helpers[s_bits]);
switch(opc) {
@@ -1018,51 +1020,40 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
}
/* XXX: move that code at the end of the TB */
-#if TARGET_LONG_BITS == 32
- if (opc == 3) {
+ if (TARGET_LONG_BITS == 32) {
tcg_out_mov(s, TCG_REG_EDX, data_reg);
- tcg_out_mov(s, TCG_REG_ECX, data_reg2);
- tcg_out_pushi(s, mem_index);
- stack_adjust = 4;
- } else {
- switch(opc) {
- case 0:
- tcg_out_ext8u(s, TCG_REG_EDX, data_reg);
- break;
- case 1:
- tcg_out_ext16u(s, TCG_REG_EDX, data_reg);
- break;
- case 2:
- tcg_out_mov(s, TCG_REG_EDX, data_reg);
- break;
+ if (opc == 3) {
+ tcg_out_mov(s, TCG_REG_ECX, data_reg2);
+ tcg_out_pushi(s, mem_index);
+ stack_adjust = 4;
+ } else {
+ tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
+ stack_adjust = 0;
}
- tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
- stack_adjust = 0;
- }
-#else
- if (opc == 3) {
- tcg_out_mov(s, TCG_REG_EDX, args[addrlo_idx + 1]);
- tcg_out_pushi(s, mem_index);
- tcg_out_push(s, data_reg2);
- tcg_out_push(s, data_reg);
- stack_adjust = 12;
} else {
- tcg_out_mov(s, TCG_REG_EDX, args[addrlo_idx + 1]);
- switch(opc) {
- case 0:
- tcg_out_ext8u(s, TCG_REG_ECX, data_reg);
- break;
- case 1:
- tcg_out_ext16u(s, TCG_REG_ECX, data_reg);
- break;
- case 2:
- tcg_out_mov(s, TCG_REG_ECX, data_reg);
- break;
+ if (opc == 3) {
+ tcg_out_mov(s, TCG_REG_EDX, args[addrlo_idx + 1]);
+ tcg_out_pushi(s, mem_index);
+ tcg_out_push(s, data_reg2);
+ tcg_out_push(s, data_reg);
+ stack_adjust = 12;
+ } else {
+ tcg_out_mov(s, TCG_REG_EDX, args[addrlo_idx + 1]);
+ switch(opc) {
+ case 0:
+ tcg_out_ext8u(s, TCG_REG_ECX, data_reg);
+ break;
+ case 1:
+ tcg_out_ext16u(s, TCG_REG_ECX, data_reg);
+ break;
+ case 2:
+ tcg_out_mov(s, TCG_REG_ECX, data_reg);
+ break;
+ }
+ tcg_out_pushi(s, mem_index);
+ stack_adjust = 4;
}
- tcg_out_pushi(s, mem_index);
- stack_adjust = 4;
}
-#endif
tcg_out_calli(s, (tcg_target_long)qemu_st_helpers[s_bits]);
commit 8516a04467cb7954cdc32e8b79b4b7df56dccb16
Author: Richard Henderson <rth at twiddle.net>
Date: Fri May 21 09:03:03 2010 -0700
tcg-i386: Split out tlb load function.
Share some code between qemu_ld and qemu_st.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 0d85ec0..cf621da 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -702,6 +702,74 @@ static void *qemu_st_helpers[4] = {
__stl_mmu,
__stq_mmu,
};
+
+/* Perform the TLB load and compare.
+
+ Inputs:
+ ADDRLO_IDX contains the index into ARGS of the low part of the
+ address; the high part of the address is at ADDR_LOW_IDX+1.
+
+ MEM_INDEX and S_BITS are the memory context and log2 size of the load.
+
+ WHICH is the offset into the CPUTLBEntry structure of the slot to read.
+ This should be offsetof addr_read or addr_write.
+
+ Outputs:
+ LABEL_PTRS is filled with 1 (32-bit addresses) or 2 (64-bit addresses)
+ positions of the displacements of forward jumps to the TLB miss case.
+
+ EAX is loaded with the low part of the address. In the TLB hit case,
+ it has been adjusted as indicated by the TLB and so is a host address.
+ In the TLB miss case, it continues to hold a guest address.
+
+ EDX is clobbered. */
+
+static void tcg_out_tlb_load(TCGContext *s, int addrlo_idx, int mem_index,
+ int s_bits, const TCGArg *args,
+ uint8_t **label_ptr, int which)
+{
+ const int addrlo = args[addrlo_idx];
+ const int r0 = TCG_REG_EAX;
+ const int r1 = TCG_REG_EDX;
+
+ tcg_out_mov(s, r1, addrlo);
+ tcg_out_mov(s, r0, addrlo);
+
+ tcg_out_shifti(s, SHIFT_SHR, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
+
+ tgen_arithi(s, ARITH_AND, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
+ tgen_arithi(s, ARITH_AND, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
+
+ tcg_out_modrm_sib_offset(s, OPC_LEA, r1, TCG_AREG0, r1, 0,
+ offsetof(CPUState, tlb_table[mem_index][0])
+ + which);
+
+ /* cmp 0(r1), r0 */
+ tcg_out_modrm_offset(s, OPC_CMP_GvEv, r0, r1, 0);
+
+ tcg_out_mov(s, r0, addrlo);
+
+ /* jne label1 */
+ tcg_out8(s, OPC_JCC_short + JCC_JNE);
+ label_ptr[0] = s->code_ptr;
+ s->code_ptr++;
+
+ if (TARGET_LONG_BITS == 64) {
+ /* cmp 4(r1), addrhi */
+ tcg_out_modrm_offset(s, OPC_CMP_GvEv, args[addrlo_idx+1], r1, 4);
+
+ /* jne label1 */
+ tcg_out8(s, OPC_JCC_short + JCC_JNE);
+ label_ptr[1] = s->code_ptr;
+ s->code_ptr++;
+ }
+
+ /* TLB Hit. */
+
+ /* add addend(r1), r0 */
+ tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
+ offsetof(CPUTLBEntry, addend) - which);
+}
#endif
static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi,
@@ -771,68 +839,29 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi,
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
int opc)
{
- int addr_reg, addr_reg2 = 0;
int data_reg, data_reg2 = 0;
- int r0, r1, mem_index, s_bits;
+ int addrlo_idx;
#if defined(CONFIG_SOFTMMU)
+ int mem_index, s_bits;
uint8_t *label_ptr[3];
#endif
- data_reg = *args++;
+ data_reg = args[0];
+ addrlo_idx = 1;
if (opc == 3) {
- data_reg2 = *args++;
+ data_reg2 = args[1];
+ addrlo_idx = 2;
}
- addr_reg = *args++;
- if (TARGET_LONG_BITS == 64) {
- addr_reg2 = *args++;
- }
- mem_index = *args;
- s_bits = opc & 3;
-
- r0 = TCG_REG_EAX;
- r1 = TCG_REG_EDX;
#if defined(CONFIG_SOFTMMU)
- tcg_out_mov(s, r1, addr_reg);
- tcg_out_mov(s, r0, addr_reg);
-
- tcg_out_shifti(s, SHIFT_SHR, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
-
- tgen_arithi(s, ARITH_AND, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
- tgen_arithi(s, ARITH_AND, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
-
- tcg_out_modrm_sib_offset(s, OPC_LEA, r1, TCG_AREG0, r1, 0,
- offsetof(CPUState,
- tlb_table[mem_index][0].addr_read));
-
- /* cmp 0(r1), r0 */
- tcg_out_modrm_offset(s, OPC_CMP_GvEv, r0, r1, 0);
-
- tcg_out_mov(s, r0, addr_reg);
-
- /* jne label1 */
- tcg_out8(s, OPC_JCC_short + JCC_JNE);
- label_ptr[0] = s->code_ptr;
- s->code_ptr++;
-
- if (TARGET_LONG_BITS == 64) {
- /* cmp 4(r1), addr_reg2 */
- tcg_out_modrm_offset(s, OPC_CMP_GvEv, addr_reg2, r1, 4);
+ mem_index = args[addrlo_idx + (TARGET_LONG_BITS / 32)];
+ s_bits = opc & 3;
- /* jne label1 */
- tcg_out8(s, OPC_JCC_short + JCC_JNE);
- label_ptr[1] = s->code_ptr;
- s->code_ptr++;
- }
+ tcg_out_tlb_load(s, addrlo_idx, mem_index, s_bits, args,
+ label_ptr, offsetof(CPUTLBEntry, addr_read));
/* TLB Hit. */
-
- /* add x(r1), r0 */
- tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
- offsetof(CPUTLBEntry, addend) -
- offsetof(CPUTLBEntry, addr_read));
-
- tcg_out_qemu_ld_direct(s, data_reg, data_reg2, r0, 0, opc);
+ tcg_out_qemu_ld_direct(s, data_reg, data_reg2, TCG_REG_EAX, 0, opc);
/* jmp label2 */
tcg_out8(s, OPC_JMP_short);
@@ -851,7 +880,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
#if TARGET_LONG_BITS == 32
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EDX, mem_index);
#else
- tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
+ tcg_out_mov(s, TCG_REG_EDX, args[addrlo_idx + 1]);
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
#endif
tcg_out_calli(s, (tcg_target_long)qemu_ld_helpers[s_bits]);
@@ -888,7 +917,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
/* label2: */
*label_ptr[2] = s->code_ptr - label_ptr[2] - 1;
#else
- tcg_out_qemu_ld_direct(s, data_reg, data_reg2, addr_reg, GUEST_BASE, opc);
+ tcg_out_qemu_ld_direct(s, data_reg, data_reg2,
+ args[addrlo_idx], GUEST_BASE, opc);
#endif
}
@@ -949,70 +979,30 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
int opc)
{
- int addr_reg, addr_reg2 = 0;
int data_reg, data_reg2 = 0;
- int r0, r1, mem_index, s_bits;
+ int addrlo_idx;
#if defined(CONFIG_SOFTMMU)
+ int mem_index, s_bits;
int stack_adjust;
uint8_t *label_ptr[3];
#endif
- data_reg = *args++;
+ data_reg = args[0];
+ addrlo_idx = 1;
if (opc == 3) {
- data_reg2 = *args++;
+ data_reg2 = args[1];
+ addrlo_idx = 2;
}
- addr_reg = *args++;
- if (TARGET_LONG_BITS == 64) {
- addr_reg2 = *args++;
- }
- mem_index = *args;
-
- s_bits = opc;
-
- r0 = TCG_REG_EAX;
- r1 = TCG_REG_EDX;
#if defined(CONFIG_SOFTMMU)
- tcg_out_mov(s, r1, addr_reg);
- tcg_out_mov(s, r0, addr_reg);
-
- tcg_out_shifti(s, SHIFT_SHR, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
-
- tgen_arithi(s, ARITH_AND, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
- tgen_arithi(s, ARITH_AND, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
-
- tcg_out_modrm_sib_offset(s, OPC_LEA, r1, TCG_AREG0, r1, 0,
- offsetof(CPUState,
- tlb_table[mem_index][0].addr_write));
-
- /* cmp 0(r1), r0 */
- tcg_out_modrm_offset(s, OPC_CMP_GvEv, r0, r1, 0);
-
- tcg_out_mov(s, r0, addr_reg);
-
- /* jne label1 */
- tcg_out8(s, OPC_JCC_short + JCC_JNE);
- label_ptr[0] = s->code_ptr;
- s->code_ptr++;
-
- if (TARGET_LONG_BITS == 64) {
- /* cmp 4(r1), addr_reg2 */
- tcg_out_modrm_offset(s, OPC_CMP_GvEv, addr_reg2, r1, 4);
+ mem_index = args[addrlo_idx + (TARGET_LONG_BITS / 32)];
+ s_bits = opc;
- /* jne label1 */
- tcg_out8(s, OPC_JCC_short + JCC_JNE);
- label_ptr[1] = s->code_ptr;
- s->code_ptr++;
- }
+ tcg_out_tlb_load(s, addrlo_idx, mem_index, s_bits, args,
+ label_ptr, offsetof(CPUTLBEntry, addr_write));
/* TLB Hit. */
-
- /* add x(r1), r0 */
- tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
- offsetof(CPUTLBEntry, addend) -
- offsetof(CPUTLBEntry, addr_write));
-
- tcg_out_qemu_st_direct(s, data_reg, data_reg2, r0, 0, opc);
+ tcg_out_qemu_st_direct(s, data_reg, data_reg2, TCG_REG_EAX, 0, opc);
/* jmp label2 */
tcg_out8(s, OPC_JMP_short);
@@ -1051,13 +1041,13 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
}
#else
if (opc == 3) {
- tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
+ tcg_out_mov(s, TCG_REG_EDX, args[addrlo_idx + 1]);
tcg_out_pushi(s, mem_index);
tcg_out_push(s, data_reg2);
tcg_out_push(s, data_reg);
stack_adjust = 12;
} else {
- tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
+ tcg_out_mov(s, TCG_REG_EDX, args[addrlo_idx + 1]);
switch(opc) {
case 0:
tcg_out_ext8u(s, TCG_REG_ECX, data_reg);
@@ -1086,7 +1076,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
/* label2: */
*label_ptr[2] = s->code_ptr - label_ptr[2] - 1;
#else
- tcg_out_qemu_st_direct(s, data_reg, data_reg2, addr_reg, GUEST_BASE, opc);
+ tcg_out_qemu_st_direct(s, data_reg, data_reg2,
+ args[addrlo_idx], GUEST_BASE, opc);
#endif
}
commit 1a6dc1e4060e3c5dd44735f2a210b2efc56b7726
Author: Richard Henderson <rth at twiddle.net>
Date: Fri May 21 09:03:02 2010 -0700
tcg-i386: Swap order of TLB hit and miss paths.
Make fallthru be TLB hit and branch be TLB miss. Doing this
both improves branch prediction and will allow further cleanup.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 30c933c..0d85ec0 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -771,26 +771,21 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi,
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
int opc)
{
- int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits;
+ int addr_reg, addr_reg2 = 0;
+ int data_reg, data_reg2 = 0;
+ int r0, r1, mem_index, s_bits;
#if defined(CONFIG_SOFTMMU)
- uint8_t *label1_ptr, *label2_ptr;
-#endif
-#if TARGET_LONG_BITS == 64
-#if defined(CONFIG_SOFTMMU)
- uint8_t *label3_ptr;
-#endif
- int addr_reg2;
+ uint8_t *label_ptr[3];
#endif
data_reg = *args++;
- if (opc == 3)
+ if (opc == 3) {
data_reg2 = *args++;
- else
- data_reg2 = 0;
+ }
addr_reg = *args++;
-#if TARGET_LONG_BITS == 64
- addr_reg2 = *args++;
-#endif
+ if (TARGET_LONG_BITS == 64) {
+ addr_reg2 = *args++;
+ }
mem_index = *args;
s_bits = opc & 3;
@@ -815,28 +810,42 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
tcg_out_mov(s, r0, addr_reg);
-#if TARGET_LONG_BITS == 32
- /* je label1 */
- tcg_out8(s, OPC_JCC_short + JCC_JE);
- label1_ptr = s->code_ptr;
- s->code_ptr++;
-#else
- /* jne label3 */
+ /* jne label1 */
tcg_out8(s, OPC_JCC_short + JCC_JNE);
- label3_ptr = s->code_ptr;
+ label_ptr[0] = s->code_ptr;
s->code_ptr++;
- /* cmp 4(r1), addr_reg2 */
- tcg_out_modrm_offset(s, OPC_CMP_GvEv, addr_reg2, r1, 4);
+ if (TARGET_LONG_BITS == 64) {
+ /* cmp 4(r1), addr_reg2 */
+ tcg_out_modrm_offset(s, OPC_CMP_GvEv, addr_reg2, r1, 4);
+
+ /* jne label1 */
+ tcg_out8(s, OPC_JCC_short + JCC_JNE);
+ label_ptr[1] = s->code_ptr;
+ s->code_ptr++;
+ }
+
+ /* TLB Hit. */
+
+ /* add x(r1), r0 */
+ tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
+ offsetof(CPUTLBEntry, addend) -
+ offsetof(CPUTLBEntry, addr_read));
+
+ tcg_out_qemu_ld_direct(s, data_reg, data_reg2, r0, 0, opc);
- /* je label1 */
- tcg_out8(s, OPC_JCC_short + JCC_JE);
- label1_ptr = s->code_ptr;
+ /* jmp label2 */
+ tcg_out8(s, OPC_JMP_short);
+ label_ptr[2] = s->code_ptr;
s->code_ptr++;
- /* label3: */
- *label3_ptr = s->code_ptr - label3_ptr - 1;
-#endif
+ /* TLB Miss. */
+
+ /* label1: */
+ *label_ptr[0] = s->code_ptr - label_ptr[0] - 1;
+ if (TARGET_LONG_BITS == 64) {
+ *label_ptr[1] = s->code_ptr - label_ptr[1] - 1;
+ }
/* XXX: move that code at the end of the TB */
#if TARGET_LONG_BITS == 32
@@ -876,23 +885,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
break;
}
- /* jmp label2 */
- tcg_out8(s, OPC_JMP_short);
- label2_ptr = s->code_ptr;
- s->code_ptr++;
-
- /* label1: */
- *label1_ptr = s->code_ptr - label1_ptr - 1;
-
- /* add x(r1), r0 */
- tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
- offsetof(CPUTLBEntry, addend) -
- offsetof(CPUTLBEntry, addr_read));
-
- tcg_out_qemu_ld_direct(s, data_reg, data_reg2, r0, 0, opc);
-
/* label2: */
- *label2_ptr = s->code_ptr - label2_ptr - 1;
+ *label_ptr[2] = s->code_ptr - label_ptr[2] - 1;
#else
tcg_out_qemu_ld_direct(s, data_reg, data_reg2, addr_reg, GUEST_BASE, opc);
#endif
@@ -955,27 +949,22 @@ static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
int opc)
{
- int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits;
+ int addr_reg, addr_reg2 = 0;
+ int data_reg, data_reg2 = 0;
+ int r0, r1, mem_index, s_bits;
#if defined(CONFIG_SOFTMMU)
int stack_adjust;
- uint8_t *label1_ptr, *label2_ptr;
-#endif
-#if TARGET_LONG_BITS == 64
-#if defined(CONFIG_SOFTMMU)
- uint8_t *label3_ptr;
-#endif
- int addr_reg2;
+ uint8_t *label_ptr[3];
#endif
data_reg = *args++;
- if (opc == 3)
+ if (opc == 3) {
data_reg2 = *args++;
- else
- data_reg2 = 0;
+ }
addr_reg = *args++;
-#if TARGET_LONG_BITS == 64
- addr_reg2 = *args++;
-#endif
+ if (TARGET_LONG_BITS == 64) {
+ addr_reg2 = *args++;
+ }
mem_index = *args;
s_bits = opc;
@@ -1001,28 +990,42 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
tcg_out_mov(s, r0, addr_reg);
-#if TARGET_LONG_BITS == 32
- /* je label1 */
- tcg_out8(s, OPC_JCC_short + JCC_JE);
- label1_ptr = s->code_ptr;
- s->code_ptr++;
-#else
- /* jne label3 */
+ /* jne label1 */
tcg_out8(s, OPC_JCC_short + JCC_JNE);
- label3_ptr = s->code_ptr;
+ label_ptr[0] = s->code_ptr;
s->code_ptr++;
- /* cmp 4(r1), addr_reg2 */
- tcg_out_modrm_offset(s, OPC_CMP_GvEv, addr_reg2, r1, 4);
+ if (TARGET_LONG_BITS == 64) {
+ /* cmp 4(r1), addr_reg2 */
+ tcg_out_modrm_offset(s, OPC_CMP_GvEv, addr_reg2, r1, 4);
+
+ /* jne label1 */
+ tcg_out8(s, OPC_JCC_short + JCC_JNE);
+ label_ptr[1] = s->code_ptr;
+ s->code_ptr++;
+ }
+
+ /* TLB Hit. */
+
+ /* add x(r1), r0 */
+ tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
+ offsetof(CPUTLBEntry, addend) -
+ offsetof(CPUTLBEntry, addr_write));
+
+ tcg_out_qemu_st_direct(s, data_reg, data_reg2, r0, 0, opc);
- /* je label1 */
- tcg_out8(s, OPC_JCC_short + JCC_JE);
- label1_ptr = s->code_ptr;
+ /* jmp label2 */
+ tcg_out8(s, OPC_JMP_short);
+ label_ptr[2] = s->code_ptr;
s->code_ptr++;
- /* label3: */
- *label3_ptr = s->code_ptr - label3_ptr - 1;
-#endif
+ /* TLB Miss. */
+
+ /* label1: */
+ *label_ptr[0] = s->code_ptr - label_ptr[0] - 1;
+ if (TARGET_LONG_BITS == 64) {
+ *label_ptr[1] = s->code_ptr - label_ptr[1] - 1;
+ }
/* XXX: move that code at the end of the TB */
#if TARGET_LONG_BITS == 32
@@ -1080,23 +1083,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
tcg_out_addi(s, TCG_REG_ESP, stack_adjust);
}
- /* jmp label2 */
- tcg_out8(s, OPC_JMP_short);
- label2_ptr = s->code_ptr;
- s->code_ptr++;
-
- /* label1: */
- *label1_ptr = s->code_ptr - label1_ptr - 1;
-
- /* add x(r1), r0 */
- tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
- offsetof(CPUTLBEntry, addend) -
- offsetof(CPUTLBEntry, addr_write));
-
- tcg_out_qemu_st_direct(s, data_reg, data_reg2, r0, 0, opc);
-
/* label2: */
- *label2_ptr = s->code_ptr - label2_ptr - 1;
+ *label_ptr[2] = s->code_ptr - label_ptr[2] - 1;
#else
tcg_out_qemu_st_direct(s, data_reg, data_reg2, addr_reg, GUEST_BASE, opc);
#endif
commit be5a4eb7f071e358cefca78e3f93bf9d199cd4fa
Author: Richard Henderson <rth at twiddle.net>
Date: Fri May 21 09:03:01 2010 -0700
tcg-i386: Split out TLB Hit path from qemu_ld/st.
Splitting out these functions will allow further cleanups.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 9226c1e..30c933c 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -704,9 +704,66 @@ static void *qemu_st_helpers[4] = {
};
#endif
-#ifndef CONFIG_USER_ONLY
-#define GUEST_BASE 0
+static void tcg_out_qemu_ld_direct(TCGContext *s, int datalo, int datahi,
+ int base, tcg_target_long ofs, int sizeop)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+ const int bswap = 1;
+#else
+ const int bswap = 0;
#endif
+ switch (sizeop) {
+ case 0:
+ /* movzbl */
+ tcg_out_modrm_offset(s, OPC_MOVZBL, datalo, base, ofs);
+ break;
+ case 0 | 4:
+ /* movsbl */
+ tcg_out_modrm_offset(s, OPC_MOVSBL, datalo, base, ofs);
+ break;
+ case 1:
+ /* movzwl */
+ tcg_out_modrm_offset(s, OPC_MOVZWL, datalo, base, ofs);
+ if (bswap) {
+ tcg_out_rolw_8(s, datalo);
+ }
+ break;
+ case 1 | 4:
+ /* movswl */
+ tcg_out_modrm_offset(s, OPC_MOVSWL, datalo, base, ofs);
+ if (bswap) {
+ tcg_out_rolw_8(s, datalo);
+ tcg_out_modrm(s, OPC_MOVSWL, datalo, datalo);
+ }
+ break;
+ case 2:
+ tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
+ if (bswap) {
+ tcg_out_bswap32(s, datalo);
+ }
+ break;
+ case 3:
+ if (bswap) {
+ int t = datalo;
+ datalo = datahi;
+ datahi = t;
+ }
+ if (base != datalo) {
+ tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
+ tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4);
+ } else {
+ tcg_out_ld(s, TCG_TYPE_I32, datahi, base, ofs + 4);
+ tcg_out_ld(s, TCG_TYPE_I32, datalo, base, ofs);
+ }
+ if (bswap) {
+ tcg_out_bswap32(s, datalo);
+ tcg_out_bswap32(s, datahi);
+ }
+ break;
+ default:
+ tcg_abort();
+ }
+}
/* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and
EAX. It will be useful once fixed registers globals are less
@@ -714,7 +771,7 @@ static void *qemu_st_helpers[4] = {
static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
int opc)
{
- int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
+ int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits;
#if defined(CONFIG_SOFTMMU)
uint8_t *label1_ptr, *label2_ptr;
#endif
@@ -831,80 +888,74 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
offsetof(CPUTLBEntry, addend) -
offsetof(CPUTLBEntry, addr_read));
+
+ tcg_out_qemu_ld_direct(s, data_reg, data_reg2, r0, 0, opc);
+
+ /* label2: */
+ *label2_ptr = s->code_ptr - label2_ptr - 1;
#else
- r0 = addr_reg;
+ tcg_out_qemu_ld_direct(s, data_reg, data_reg2, addr_reg, GUEST_BASE, opc);
#endif
+}
+static void tcg_out_qemu_st_direct(TCGContext *s, int datalo, int datahi,
+ int base, tcg_target_long ofs, int sizeop)
+{
#ifdef TARGET_WORDS_BIGENDIAN
- bswap = 1;
+ const int bswap = 1;
#else
- bswap = 0;
+ const int bswap = 0;
#endif
- switch(opc) {
+ /* ??? Ideally we wouldn't need a scratch register. For user-only,
+ we could perform the bswap twice to restore the original value
+ instead of moving to the scratch. But as it is, the L constraint
+ means that EDX is definitely free here. */
+ int scratch = TCG_REG_EDX;
+
+ switch (sizeop) {
case 0:
- /* movzbl */
- tcg_out_modrm_offset(s, OPC_MOVZBL, data_reg, r0, GUEST_BASE);
- break;
- case 0 | 4:
- /* movsbl */
- tcg_out_modrm_offset(s, OPC_MOVSBL, data_reg, r0, GUEST_BASE);
+ tcg_out_modrm_offset(s, OPC_MOVB_EvGv, datalo, base, ofs);
break;
case 1:
- /* movzwl */
- tcg_out_modrm_offset(s, OPC_MOVZWL, data_reg, r0, GUEST_BASE);
- if (bswap) {
- tcg_out_rolw_8(s, data_reg);
- }
- break;
- case 1 | 4:
- /* movswl */
- tcg_out_modrm_offset(s, OPC_MOVSWL, data_reg, r0, GUEST_BASE);
if (bswap) {
- tcg_out_rolw_8(s, data_reg);
-
- /* movswl data_reg, data_reg */
- tcg_out_modrm(s, OPC_MOVSWL, data_reg, data_reg);
+ tcg_out_mov(s, scratch, datalo);
+ tcg_out_rolw_8(s, scratch);
+ datalo = scratch;
}
+ /* movw */
+ tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16,
+ datalo, base, ofs);
break;
case 2:
- tcg_out_ld(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
if (bswap) {
- tcg_out_bswap32(s, data_reg);
+ tcg_out_mov(s, scratch, datalo);
+ tcg_out_bswap32(s, scratch);
+ datalo = scratch;
}
+ tcg_out_st(s, TCG_TYPE_I32, datalo, base, ofs);
break;
case 3:
if (bswap) {
- int t = data_reg;
- data_reg = data_reg2;
- data_reg2 = t;
- }
- if (r0 != data_reg) {
- tcg_out_ld(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
- tcg_out_ld(s, TCG_TYPE_I32, data_reg2, r0, GUEST_BASE + 4);
+ tcg_out_mov(s, scratch, datahi);
+ tcg_out_bswap32(s, scratch);
+ tcg_out_st(s, TCG_TYPE_I32, scratch, base, ofs);
+ tcg_out_mov(s, scratch, datalo);
+ tcg_out_bswap32(s, scratch);
+ tcg_out_st(s, TCG_TYPE_I32, scratch, base, ofs + 4);
} else {
- tcg_out_ld(s, TCG_TYPE_I32, data_reg2, r0, GUEST_BASE + 4);
- tcg_out_ld(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
- }
- if (bswap) {
- tcg_out_bswap32(s, data_reg);
- tcg_out_bswap32(s, data_reg2);
+ tcg_out_st(s, TCG_TYPE_I32, datalo, base, ofs);
+ tcg_out_st(s, TCG_TYPE_I32, datahi, base, ofs + 4);
}
break;
default:
tcg_abort();
}
-
-#if defined(CONFIG_SOFTMMU)
- /* label2: */
- *label2_ptr = s->code_ptr - label2_ptr - 1;
-#endif
}
-
static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
int opc)
{
- int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
+ int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits;
#if defined(CONFIG_SOFTMMU)
int stack_adjust;
uint8_t *label1_ptr, *label2_ptr;
@@ -1041,57 +1092,13 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
offsetof(CPUTLBEntry, addend) -
offsetof(CPUTLBEntry, addr_write));
-#else
- r0 = addr_reg;
-#endif
-#ifdef TARGET_WORDS_BIGENDIAN
- bswap = 1;
-#else
- bswap = 0;
-#endif
- switch(opc) {
- case 0:
- tcg_out_modrm_offset(s, OPC_MOVB_EvGv, data_reg, r0, GUEST_BASE);
- break;
- case 1:
- if (bswap) {
- tcg_out_mov(s, r1, data_reg);
- tcg_out_rolw_8(s, r1);
- data_reg = r1;
- }
- /* movw */
- tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16,
- data_reg, r0, GUEST_BASE);
- break;
- case 2:
- if (bswap) {
- tcg_out_mov(s, r1, data_reg);
- tcg_out_bswap32(s, r1);
- data_reg = r1;
- }
- tcg_out_st(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
- break;
- case 3:
- if (bswap) {
- tcg_out_mov(s, r1, data_reg2);
- tcg_out_bswap32(s, r1);
- tcg_out_st(s, TCG_TYPE_I32, r1, r0, GUEST_BASE);
- tcg_out_mov(s, r1, data_reg);
- tcg_out_bswap32(s, r1);
- tcg_out_st(s, TCG_TYPE_I32, r1, r0, GUEST_BASE + 4);
- } else {
- tcg_out_st(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
- tcg_out_st(s, TCG_TYPE_I32, data_reg2, r0, GUEST_BASE + 4);
- }
- break;
- default:
- tcg_abort();
- }
+ tcg_out_qemu_st_direct(s, data_reg, data_reg2, r0, 0, opc);
-#if defined(CONFIG_SOFTMMU)
/* label2: */
*label2_ptr = s->code_ptr - label2_ptr - 1;
+#else
+ tcg_out_qemu_st_direct(s, data_reg, data_reg2, addr_reg, GUEST_BASE, opc);
#endif
}
commit 96b4cf38f050d61d01d23d373ce059013b8a6090
Author: Richard Henderson <rth at twiddle.net>
Date: Fri May 21 09:03:00 2010 -0700
tcg-i386: Tidy data16 prefixes.
Include it in the opcode as an extension, as with P_EXT
or the REX bits in the x86-64 port.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 396a2f1..9226c1e 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -156,7 +156,8 @@ static inline int tcg_target_const_match(tcg_target_long val,
return 0;
}
-#define P_EXT 0x100 /* 0x0f opcode prefix */
+#define P_EXT 0x100 /* 0x0f opcode prefix */
+#define P_DATA16 0x200 /* 0x66 opcode prefix */
#define OPC_ARITH_EvIz (0x81)
#define OPC_ARITH_EvIb (0x83)
@@ -262,8 +263,12 @@ static const uint8_t tcg_cond_to_jcc[10] = {
static inline void tcg_out_opc(TCGContext *s, int opc)
{
- if (opc & P_EXT)
+ if (opc & P_DATA16) {
+ tcg_out8(s, 0x66);
+ }
+ if (opc & P_EXT) {
tcg_out8(s, 0x0f);
+ }
tcg_out8(s, opc);
}
@@ -396,10 +401,14 @@ static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
static void tcg_out_shifti(TCGContext *s, int subopc, int reg, int count)
{
+ /* Propagate an opcode prefix, such as P_DATA16. */
+ int ext = subopc & ~0x7;
+ subopc &= 0x7;
+
if (count == 1) {
- tcg_out_modrm(s, OPC_SHIFT_1, subopc, reg);
+ tcg_out_modrm(s, OPC_SHIFT_1 | ext, subopc, reg);
} else {
- tcg_out_modrm(s, OPC_SHIFT_Ib, subopc, reg);
+ tcg_out_modrm(s, OPC_SHIFT_Ib | ext, subopc, reg);
tcg_out8(s, count);
}
}
@@ -411,8 +420,7 @@ static inline void tcg_out_bswap32(TCGContext *s, int reg)
static inline void tcg_out_rolw_8(TCGContext *s, int reg)
{
- tcg_out8(s, 0x66);
- tcg_out_shifti(s, SHIFT_ROL, reg, 8);
+ tcg_out_shifti(s, SHIFT_ROL | P_DATA16, reg, 8);
}
static inline void tcg_out_ext8u(TCGContext *s, int dest, int src)
@@ -1053,8 +1061,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
data_reg = r1;
}
/* movw */
- tcg_out8(s, 0x66);
- tcg_out_modrm_offset(s, OPC_MOVL_EvGv, data_reg, r0, GUEST_BASE);
+ tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16,
+ data_reg, r0, GUEST_BASE);
break;
case 2:
if (bswap) {
@@ -1159,8 +1167,8 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
break;
case INDEX_op_st16_i32:
/* movw */
- tcg_out8(s, 0x66);
- tcg_out_modrm_offset(s, OPC_MOVL_EvGv, args[0], args[1], args[2]);
+ tcg_out_modrm_offset(s, OPC_MOVL_EvGv | P_DATA16,
+ args[0], args[1], args[2]);
break;
case INDEX_op_st_i32:
tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]);
commit fb170183e7387ade9aef2bddd59a8a62fceedac6
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date: Wed Jun 2 00:12:58 2010 +0400
sparc64: fix umul and smul insns
- truncate and sign or zero extend operands before multiplication
- factor out common code to gen_op_multiply() with parameter to sign/zero extend
- call gen_op_multiply from gen_op_umul and gen_op_smul
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 0bc1a82..23f9519 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -662,50 +662,53 @@ static inline void gen_op_mulscc(TCGv dst, TCGv src1, TCGv src2)
tcg_gen_mov_tl(dst, cpu_cc_dst);
}
-static inline void gen_op_umul(TCGv dst, TCGv src1, TCGv src2)
+static inline void gen_op_multiply(TCGv dst, TCGv src1, TCGv src2, int sign_ext)
{
+ TCGv_i32 r_src1, r_src2;
TCGv_i64 r_temp, r_temp2;
+ r_src1 = tcg_temp_new_i32();
+ r_src2 = tcg_temp_new_i32();
+
+ tcg_gen_trunc_tl_i32(r_src1, src1);
+ tcg_gen_trunc_tl_i32(r_src2, src2);
+
r_temp = tcg_temp_new_i64();
r_temp2 = tcg_temp_new_i64();
- tcg_gen_extu_tl_i64(r_temp, src2);
- tcg_gen_extu_tl_i64(r_temp2, src1);
+ if (sign_ext) {
+ tcg_gen_ext_i32_i64(r_temp, r_src2);
+ tcg_gen_ext_i32_i64(r_temp2, r_src1);
+ } else {
+ tcg_gen_extu_i32_i64(r_temp, r_src2);
+ tcg_gen_extu_i32_i64(r_temp2, r_src1);
+ }
+
tcg_gen_mul_i64(r_temp2, r_temp, r_temp2);
tcg_gen_shri_i64(r_temp, r_temp2, 32);
tcg_gen_trunc_i64_tl(cpu_tmp0, r_temp);
tcg_temp_free_i64(r_temp);
tcg_gen_andi_tl(cpu_y, cpu_tmp0, 0xffffffff);
-#ifdef TARGET_SPARC64
- tcg_gen_mov_i64(dst, r_temp2);
-#else
+
tcg_gen_trunc_i64_tl(dst, r_temp2);
-#endif
+
tcg_temp_free_i64(r_temp2);
+
+ tcg_temp_free_i32(r_src1);
+ tcg_temp_free_i32(r_src2);
}
-static inline void gen_op_smul(TCGv dst, TCGv src1, TCGv src2)
+static inline void gen_op_umul(TCGv dst, TCGv src1, TCGv src2)
{
- TCGv_i64 r_temp, r_temp2;
-
- r_temp = tcg_temp_new_i64();
- r_temp2 = tcg_temp_new_i64();
-
- tcg_gen_ext_tl_i64(r_temp, src2);
- tcg_gen_ext_tl_i64(r_temp2, src1);
- tcg_gen_mul_i64(r_temp2, r_temp, r_temp2);
+ /* zero-extend truncated operands before multiplication */
+ gen_op_multiply(dst, src1, src2, 0);
+}
- tcg_gen_shri_i64(r_temp, r_temp2, 32);
- tcg_gen_trunc_i64_tl(cpu_tmp0, r_temp);
- tcg_temp_free_i64(r_temp);
- tcg_gen_andi_tl(cpu_y, cpu_tmp0, 0xffffffff);
-#ifdef TARGET_SPARC64
- tcg_gen_mov_i64(dst, r_temp2);
-#else
- tcg_gen_trunc_i64_tl(dst, r_temp2);
-#endif
- tcg_temp_free_i64(r_temp2);
+static inline void gen_op_smul(TCGv dst, TCGv src1, TCGv src2)
+{
+ /* sign-extend truncated operands before multiplication */
+ gen_op_multiply(dst, src1, src2, 1);
}
#ifdef TARGET_SPARC64
commit 09487205bb03548d260300d32595ba17ab597337
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date: Wed Jun 2 00:12:53 2010 +0400
sparc64: fix udiv and sdiv insns
- truncate second operand to 32bit
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 470c710..be3c1e0 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -3306,7 +3306,7 @@ target_ulong helper_udiv(target_ulong a, target_ulong b)
uint32_t x1;
x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
- x1 = b;
+ x1 = (b & 0xffffffff);
if (x1 == 0) {
raise_exception(TT_DIV_ZERO);
@@ -3328,7 +3328,7 @@ target_ulong helper_sdiv(target_ulong a, target_ulong b)
int32_t x1;
x0 = (a & 0xffffffff) | ((int64_t) (env->y) << 32);
- x1 = b;
+ x1 = (b & 0xffffffff);
if (x1 == 0) {
raise_exception(TT_DIV_ZERO);
commit 0e2fa9cab9c124788077de728f1e6744d1dd8bb2
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date: Wed Jun 2 00:12:48 2010 +0400
sparc64: improve ldf and stf insns
- implemented block load/store primary/secondary with user privilege
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 842dbd3..470c710 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -3164,6 +3164,20 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
}
return;
+ case 0x70: // Block load primary, user privilege
+ case 0x71: // Block load secondary, user privilege
+ if (rd & 7) {
+ raise_exception(TT_ILL_INSN);
+ return;
+ }
+ helper_check_align(addr, 0x3f);
+ for (i = 0; i < 16; i++) {
+ *(uint32_t *)&env->fpr[rd++] = helper_ld_asi(addr, asi & 0x1f, 4,
+ 0);
+ addr += 4;
+ }
+
+ return;
default:
break;
}
@@ -3210,6 +3224,20 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
}
return;
+ case 0x70: // Block store primary, user privilege
+ case 0x71: // Block store secondary, user privilege
+ if (rd & 7) {
+ raise_exception(TT_ILL_INSN);
+ return;
+ }
+ helper_check_align(addr, 0x3f);
+ for (i = 0; i < 16; i++) {
+ val = *(uint32_t *)&env->fpr[rd++];
+ helper_st_asi(addr, val, asi & 0x1f, 4);
+ addr += 4;
+ }
+
+ return;
default:
break;
}
commit b219094acea73602e3a5ef8bfb4f3ca60c2ee56f
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date: Wed Jun 2 23:39:09 2010 +0400
sparc64: use symbolic name for MMU index v1
- use symbolic name for MMU index
v0->v1:
- change debug traces to DPRINTF_MMU
- fix debug trace function names
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index f5e4633..842dbd3 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -3321,18 +3321,19 @@ void helper_stdf(target_ulong addr, int mem_idx)
helper_check_align(addr, 7);
#if !defined(CONFIG_USER_ONLY)
switch (mem_idx) {
- case 0:
+ case MMU_USER_IDX:
stfq_user(addr, DT0);
break;
- case 1:
+ case MMU_KERNEL_IDX:
stfq_kernel(addr, DT0);
break;
#ifdef TARGET_SPARC64
- case 2:
+ case MMU_HYPV_IDX:
stfq_hypv(addr, DT0);
break;
#endif
default:
+ DPRINTF_MMU("helper_stdf: need to check MMU idx %d\n", mem_idx);
break;
}
#else
@@ -3345,18 +3346,19 @@ void helper_lddf(target_ulong addr, int mem_idx)
helper_check_align(addr, 7);
#if !defined(CONFIG_USER_ONLY)
switch (mem_idx) {
- case 0:
+ case MMU_USER_IDX:
DT0 = ldfq_user(addr);
break;
- case 1:
+ case MMU_KERNEL_IDX:
DT0 = ldfq_kernel(addr);
break;
#ifdef TARGET_SPARC64
- case 2:
+ case MMU_HYPV_IDX:
DT0 = ldfq_hypv(addr);
break;
#endif
default:
+ DPRINTF_MMU("helper_lddf: need to check MMU idx %d\n", mem_idx);
break;
}
#else
@@ -3372,24 +3374,25 @@ void helper_ldqf(target_ulong addr, int mem_idx)
helper_check_align(addr, 7);
#if !defined(CONFIG_USER_ONLY)
switch (mem_idx) {
- case 0:
+ case MMU_USER_IDX:
u.ll.upper = ldq_user(addr);
u.ll.lower = ldq_user(addr + 8);
QT0 = u.q;
break;
- case 1:
+ case MMU_KERNEL_IDX:
u.ll.upper = ldq_kernel(addr);
u.ll.lower = ldq_kernel(addr + 8);
QT0 = u.q;
break;
#ifdef TARGET_SPARC64
- case 2:
+ case MMU_HYPV_IDX:
u.ll.upper = ldq_hypv(addr);
u.ll.lower = ldq_hypv(addr + 8);
QT0 = u.q;
break;
#endif
default:
+ DPRINTF_MMU("helper_ldqf: need to check MMU idx %d\n", mem_idx);
break;
}
#else
@@ -3407,24 +3410,25 @@ void helper_stqf(target_ulong addr, int mem_idx)
helper_check_align(addr, 7);
#if !defined(CONFIG_USER_ONLY)
switch (mem_idx) {
- case 0:
+ case MMU_USER_IDX:
u.q = QT0;
stq_user(addr, u.ll.upper);
stq_user(addr + 8, u.ll.lower);
break;
- case 1:
+ case MMU_KERNEL_IDX:
u.q = QT0;
stq_kernel(addr, u.ll.upper);
stq_kernel(addr + 8, u.ll.lower);
break;
#ifdef TARGET_SPARC64
- case 2:
+ case MMU_HYPV_IDX:
u.q = QT0;
stq_hypv(addr, u.ll.upper);
stq_hypv(addr + 8, u.ll.lower);
break;
#endif
default:
+ DPRINTF_MMU("helper_stqf: need to check MMU idx %d\n", mem_idx);
break;
}
#else
commit fe987e2394e1fca01aba581095f219423fbbdd39
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date: Wed Jun 2 00:12:37 2010 +0400
sparc64: fix ldxfsr insn
- rearrange code to break from switch when appropriate
- allow deprecated ldfsr insn
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index eff64d4..0bc1a82 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -4476,7 +4476,11 @@ static void disas_sparc_insn(DisasContext * dc)
if (rd == 1) {
tcg_gen_qemu_ld64(cpu_tmp64, cpu_addr, dc->mem_idx);
gen_helper_ldxfsr(cpu_tmp64);
- } else
+ } else {
+ tcg_gen_qemu_ld32u(cpu_tmp0, cpu_addr, dc->mem_idx);
+ tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
+ gen_helper_ldfsr(cpu_tmp32);
+ }
#else
{
tcg_gen_qemu_ld32u(cpu_tmp32, cpu_addr, dc->mem_idx);
commit c086b783eb7a578993d6d2ab62c4c2666800b63d
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date: Wed Jun 2 00:12:32 2010 +0400
sparc64: fix 32bit load sign extension
- change return type of ldl_* to uint32_t to prevent unwanted sign extension
visible in sparc64 load alternate address space methods
- note this change makes ldl_* softmmu implementations match ldl_phys one
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/softmmu_header.h b/softmmu_header.h
index 6a36e01..2f95c33 100644
--- a/softmmu_header.h
+++ b/softmmu_header.h
@@ -60,7 +60,7 @@
#if DATA_SIZE == 8
#define RES_TYPE uint64_t
#else
-#define RES_TYPE int
+#define RES_TYPE uint32_t
#endif
#if ACCESS_TYPE == (NB_MMU_MODES + 1)
commit 1295001c53fe816776bae810bed0a653ea0c6475
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date: Wed Jun 2 23:38:45 2010 +0400
sparc64: fix missing address masking v1
- address masking for ldqf and stqf insns
- address masking for lddf and stdf insns
- address masking for translating ASI (Ultrasparc IIi)
v0->v1:
- move arch-specific code to helpers and drop more ifdefs at call sites
using new helper asi_address_mask()
- change user emulation to use asi_address_mask()
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index ef3504f..f5e4633 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -247,6 +247,42 @@ static inline target_ulong address_mask(CPUState *env1, target_ulong addr)
return addr;
}
+/* returns true if access using this ASI is to have address translated by MMU
+ otherwise access is to raw physical address */
+static inline int is_translating_asi(int asi)
+{
+#ifdef TARGET_SPARC64
+ /* Ultrasparc IIi translating asi
+ - note this list is defined by cpu implementation
+ */
+ switch (asi) {
+ case 0x04 ... 0x11:
+ case 0x18 ... 0x19:
+ case 0x24 ... 0x2C:
+ case 0x70 ... 0x73:
+ case 0x78 ... 0x79:
+ case 0x80 ... 0xFF:
+ return 1;
+
+ default:
+ return 0;
+ }
+#else
+ /* TODO: check sparc32 bits */
+ return 0;
+#endif
+}
+
+static inline target_ulong asi_address_mask(CPUState *env1,
+ int asi, target_ulong addr)
+{
+ if (is_translating_asi(asi)) {
+ return address_mask(env, addr);
+ } else {
+ return addr;
+ }
+}
+
static void raise_exception(int tt)
{
env->exception_index = tt;
@@ -2151,7 +2187,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
raise_exception(TT_PRIV_ACT);
helper_check_align(addr, size - 1);
- addr = address_mask(env, addr);
+ addr = asi_address_mask(env, asi, addr);
switch (asi) {
case 0x82: // Primary no-fault
@@ -2254,7 +2290,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
raise_exception(TT_PRIV_ACT);
helper_check_align(addr, size - 1);
- addr = address_mask(env, addr);
+ addr = asi_address_mask(env, asi, addr);
/* Convert to little endian */
switch (asi) {
@@ -2331,6 +2367,8 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
raise_exception(TT_PRIV_ACT);
helper_check_align(addr, size - 1);
+ addr = asi_address_mask(env, asi, addr);
+
switch (asi) {
case 0x82: // Primary no-fault
case 0x8a: // Primary no-fault LE
@@ -2682,6 +2720,8 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
raise_exception(TT_PRIV_ACT);
helper_check_align(addr, size - 1);
+ addr = asi_address_mask(env, asi, addr);
+
/* Convert to little endian */
switch (asi) {
case 0x0c: // Nucleus Little Endian (LE)
@@ -3056,6 +3096,8 @@ void helper_ldda_asi(target_ulong addr, int asi, int rd)
&& !(env->hpstate & HS_PRIV)))
raise_exception(TT_PRIV_ACT);
+ addr = asi_address_mask(env, asi, addr);
+
switch (asi) {
#if !defined(CONFIG_USER_ONLY)
case 0x24: // Nucleus quad LDD 128 bit atomic
@@ -3103,6 +3145,8 @@ void helper_ldf_asi(target_ulong addr, int asi, int size, int rd)
target_ulong val;
helper_check_align(addr, 3);
+ addr = asi_address_mask(env, asi, addr);
+
switch (asi) {
case 0xf0: // Block load primary
case 0xf1: // Block load secondary
@@ -3145,6 +3189,8 @@ void helper_stf_asi(target_ulong addr, int asi, int size, int rd)
target_ulong val = 0;
helper_check_align(addr, 3);
+ addr = asi_address_mask(env, asi, addr);
+
switch (asi) {
case 0xe0: // UA2007 Block commit store primary (cache flush)
case 0xe1: // UA2007 Block commit store secondary (cache flush)
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 72ca0b4..eff64d4 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -4490,6 +4490,7 @@ static void disas_sparc_insn(DisasContext * dc)
CHECK_FPU_FEATURE(dc, FLOAT128);
r_const = tcg_const_i32(dc->mem_idx);
+ gen_address_mask(dc, cpu_addr);
gen_helper_ldqf(cpu_addr, r_const);
tcg_temp_free_i32(r_const);
gen_op_store_QT0_fpr(QFPREG(rd));
@@ -4500,6 +4501,7 @@ static void disas_sparc_insn(DisasContext * dc)
TCGv_i32 r_const;
r_const = tcg_const_i32(dc->mem_idx);
+ gen_address_mask(dc, cpu_addr);
gen_helper_lddf(cpu_addr, r_const);
tcg_temp_free_i32(r_const);
gen_op_store_DT0_fpr(DFPREG(rd));
@@ -4635,6 +4637,7 @@ static void disas_sparc_insn(DisasContext * dc)
CHECK_FPU_FEATURE(dc, FLOAT128);
gen_op_load_fpr_QT0(QFPREG(rd));
r_const = tcg_const_i32(dc->mem_idx);
+ gen_address_mask(dc, cpu_addr);
gen_helper_stqf(cpu_addr, r_const);
tcg_temp_free_i32(r_const);
}
@@ -4657,6 +4660,7 @@ static void disas_sparc_insn(DisasContext * dc)
gen_op_load_fpr_DT0(DFPREG(rd));
r_const = tcg_const_i32(dc->mem_idx);
+ gen_address_mask(dc, cpu_addr);
gen_helper_stdf(cpu_addr, r_const);
tcg_temp_free_i32(r_const);
}
commit 9168b3a545fae3db8ad0ee7de872c4302651ba7f
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date: Wed Jun 2 00:12:22 2010 +0400
sparc64: fix tag access register on mmu traps
- set mmu tag access register on FAULT and PROT traps as well
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 96a22f3..aa1fd63 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -495,6 +495,9 @@ static int get_physical_address_data(CPUState *env,
env->dmmu.sfsr |= (fault_type << 7);
env->dmmu.sfar = address; /* Fault address register */
+
+ env->dmmu.tag_access = (address & ~0x1fffULL) | context;
+
return 1;
}
}
@@ -544,6 +547,8 @@ static int get_physical_address_code(CPUState *env,
env->immu.sfsr |= (is_user << 3) | 1;
env->exception_index = TT_TFAULT;
+ env->immu.tag_access = (address & ~0x1fffULL) | context;
+
DPRINTF_MMU("TFAULT at %" PRIx64 " context %" PRIx64 "\n",
address, context);
commit 7f9744812291853425b614f68668f48d49882a1f
Author: Michael S. Tsirkin <mst at redhat.com>
Date: Wed Jun 2 11:40:54 2010 +0300
virtio-net: stop vhost backend on vmstop
vhost net currently keeps running after vmstop,
which causes trouble as qemy does not check
for dirty pages anymore.
The fix is to simply keep vm and vhost running/stopped
status in sync.
Tested-by: David L Stevens <dlstevens at us.ibm.com>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/virtio-net.c b/hw/virtio-net.c
index cb664e6..6a9d560 100644
--- a/hw/virtio-net.c
+++ b/hw/virtio-net.c
@@ -877,12 +877,11 @@ static void virtio_net_set_status(struct VirtIODevice *vdev, uint8_t status)
static void virtio_net_vmstate_change(void *opaque, int running, int reason)
{
VirtIONet *n = opaque;
- if (!running) {
- return;
- }
- /* This is called when vm is started, it will start vhost backend if
- * appropriate e.g. after migration. */
- virtio_net_set_status(&n->vdev, n->vdev.status);
+ uint8_t status = running ? VIRTIO_CONFIG_S_DRIVER_OK : 0;
+ /* This is called when vm is started/stopped,
+ * it will start/stop vhost backend if * appropriate
+ * e.g. after migration. */
+ virtio_net_set_status(&n->vdev, n->vdev.status & status);
}
VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf)
commit d9b73e47a3d596c5b33802597ec5bd91ef3348e2
Author: Corentin Chary <corentincj at iksaif.net>
Date: Tue Jun 1 23:05:44 2010 +0200
vnc: add missing target for vnc-encodings-*.o
vnc-encodings-*.c dependencies where missing.
Signed-off-by: Corentin Chary <corentincj at iksaif.net>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/Makefile b/Makefile
index cc5fc45..221fbd8 100644
--- a/Makefile
+++ b/Makefile
@@ -120,11 +120,11 @@ vnc-auth-vencrypt.o: vnc-auth-vencrypt.c vnc.h
vnc-auth-sasl.o: vnc-auth-sasl.c vnc.h
-vnc-encoding-zlib.o: vnc.h
+vnc-encoding-zlib.o: vnc-encoding-zlib.c vnc.h
-vnc-encoding-hextile.o: vnc.h
+vnc-encoding-hextile.o: vnc-encoding-hextile.c vnc.h
-vnc-encoding-tight.o: vnc.h vnc-encoding-tight.h
+vnc-encoding-tight.o: vnc-encoding-tight.c vnc.h vnc-encoding-tight.h
curses.o: curses.c keymaps.h curses_keys.h
commit 270ec21929b029e6cca27656fcbf1c775e42f6d7
Author: Corentin Chary <corentincj at iksaif.net>
Date: Tue Jun 1 23:05:43 2010 +0200
vnc: tight: don't forget the third color
While couting color, if the third color was only present one
time it wasn't added to the palette.
Signed-off-by: Corentin Chary <corentincj at iksaif.net>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/vnc-encoding-tight.c b/vnc-encoding-tight.c
index 7bde44d..e8604a8 100644
--- a/vnc-encoding-tight.c
+++ b/vnc-encoding-tight.c
@@ -177,6 +177,7 @@ static int tight_palette_insert(QDict *palette, uint32_t rgb, int bpp, int max)
*palette = qdict_new(); \
tight_palette_insert(*palette, c0, bpp, max); \
tight_palette_insert(*palette, c1, bpp, max); \
+ tight_palette_insert(*palette, ci, bpp, max); \
\
for (i++; i < count; i++) { \
if (data[i] == ci) { \
commit 54d43eacc5ca300d5a5ce5a83abe75e0167946b5
Author: Corentin Chary <corentincj at iksaif.net>
Date: Tue Jun 1 23:05:42 2010 +0200
vnc: tight: don't forget last pixel in tight_encode_indexed_rect
A simple patch would have been to just remove count -= 1, but this
one also replace the while (count--) with a for(i = 0; i < count; i++)
which I believe is more easy to understand.
Signed-off-by: Corentin Chary <corentincj at iksaif.net>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/vnc-encoding-tight.c b/vnc-encoding-tight.c
index 50be44e..7bde44d 100644
--- a/vnc-encoding-tight.c
+++ b/vnc-encoding-tight.c
@@ -249,17 +249,16 @@ static void print_palette(const char *key, QObject *obj, void *opaque)
uint##bpp##_t *src; \
uint##bpp##_t rgb; \
uint8_t key[6]; \
- int rep = 0; \
+ int i, rep; \
uint8_t idx; \
\
src = (uint##bpp##_t *) buf; \
\
- count -= 1; \
- while (count--) { \
+ for (i = 0; i < count; i++) { \
rgb = *src++; \
rep = 0; \
- while (count && *src == rgb) { \
- rep++, src++, count--; \
+ while (i < count && *src == rgb) { \
+ rep++, src++, i++; \
} \
tight_palette_rgb2buf(rgb, bpp, key); \
if (!qdict_haskey(palette, (char *)key)) { \
commit 637503d122eb7656d91a8489e254d9e880be7504
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date: Mon May 31 14:43:32 2010 -0300
Monitor: Drop QMP documentation from code
Previous commit added QMP documentation to the qemu-monitor.hx
file, it's is a copy of this information.
While it's good to keep it near code, maintaining two copies of
the same information is too hard and has little benefit as we
don't expect client writers to consult the code to find how to
use a QMP command.
Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/block.c b/block.c
index cd70730..67f0998 100644
--- a/block.c
+++ b/block.c
@@ -1444,33 +1444,6 @@ void bdrv_info_print(Monitor *mon, const QObject *data)
qlist_iter(qobject_to_qlist(data), bdrv_print_dict, mon);
}
-/**
- * bdrv_info(): Block devices information
- *
- * Each block device information is stored in a QDict and the
- * returned QObject is a QList of all devices.
- *
- * The QDict contains the following:
- *
- * - "device": device name
- * - "type": device type
- * - "removable": true if the device is removable, false otherwise
- * - "locked": true if the device is locked, false otherwise
- * - "inserted": only present if the device is inserted, it is a QDict
- * containing the following:
- * - "file": device file name
- * - "ro": true if read-only, false otherwise
- * - "drv": driver format name
- * - "backing_file": backing file name if one is used
- * - "encrypted": true if encrypted, false otherwise
- *
- * Example:
- *
- * [ { "device": "ide0-hd0", "type": "hd", "removable": false, "locked": false,
- * "inserted": { "file": "/tmp/foobar", "ro": false, "drv": "qcow2" } },
- * { "device": "floppy0", "type": "floppy", "removable": true,
- * "locked": false } ]
- */
void bdrv_info(Monitor *mon, QObject **ret_data)
{
QList *bs_list;
@@ -1576,48 +1549,6 @@ static QObject* bdrv_info_stats_bs(BlockDriverState *bs)
return res;
}
-/**
- * bdrv_info_stats(): show block device statistics
- *
- * Each device statistic information is stored in a QDict and
- * the returned QObject is a QList of all devices.
- *
- * The QDict contains the following:
- *
- * - "device": device name
- * - "stats": A QDict with the statistics information, it contains:
- * - "rd_bytes": bytes read
- * - "wr_bytes": bytes written
- * - "rd_operations": read operations
- * - "wr_operations": write operations
- * - "wr_highest_offset": Highest offset of a sector written since the
- * BlockDriverState has been opened
- * - "parent": A QDict recursively holding the statistics of the underlying
- * protocol (e.g. the host file for a qcow2 image). If there is no
- * underlying protocol, this field is omitted.
- *
- * Example:
- *
- * [ { "device": "ide0-hd0",
- * "stats": { "rd_bytes": 512,
- * "wr_bytes": 0,
- * "rd_operations": 1,
- * "wr_operations": 0,
- * "wr_highest_offset": 0 },
- * "parent": {
- * "stats": { "rd_bytes": 1024,
- * "wr_bytes": 0,
- * "rd_operations": 2,
- * "wr_operations": 0,
- * "wr_highest_offset": 0,
- * } } },
- * { "device": "ide1-cd0",
- * "stats": { "rd_bytes": 0,
- * "wr_bytes": 0,
- * "rd_operations": 0,
- * "wr_operations": 0,
- * "wr_highest_offset": 0 } },
- */
void bdrv_info_stats(Monitor *mon, QObject **ret_data)
{
QObject *obj;
diff --git a/hw/pci.c b/hw/pci.c
index f084cc0..cbbd1dd 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -1380,67 +1380,6 @@ static QObject *pci_get_bus_dict(PCIBus *bus, int bus_num)
return NULL;
}
-/**
- * do_pci_info(): PCI buses and devices information
- *
- * The returned QObject is a QList of all buses. Each bus is
- * represented by a QDict, which has a key with a QList of all
- * PCI devices attached to it. Each device is represented by
- * a QDict.
- *
- * The bus QDict contains the following:
- *
- * - "bus": bus number
- * - "devices": a QList of QDicts, each QDict represents a PCI
- * device
- *
- * The PCI device QDict contains the following:
- *
- * - "bus": identical to the parent's bus number
- * - "slot": slot number
- * - "function": function number
- * - "class_info": a QDict containing:
- * - "desc": device class description (optional)
- * - "class": device class number
- * - "id": a QDict containing:
- * - "device": device ID
- * - "vendor": vendor ID
- * - "irq": device's IRQ if assigned (optional)
- * - "qdev_id": qdev id string
- * - "pci_bridge": It's a QDict, only present if this device is a
- * PCI bridge, contains:
- * - "bus": bus number
- * - "secondary": secondary bus number
- * - "subordinate": subordinate bus number
- * - "io_range": a QDict with memory range information
- * - "memory_range": a QDict with memory range information
- * - "prefetchable_range": a QDict with memory range information
- * - "devices": a QList of PCI devices if there's any attached (optional)
- * - "regions": a QList of QDicts, each QDict represents a
- * memory region of this device
- *
- * The memory range QDict contains the following:
- *
- * - "base": base memory address
- * - "limit": limit value
- *
- * The region QDict can be an I/O region or a memory region,
- * an I/O region QDict contains the following:
- *
- * - "type": "io"
- * - "bar": BAR number
- * - "address": memory address
- * - "size": memory size
- *
- * A memory region QDict contains the following:
- *
- * - "type": "memory"
- * - "bar": BAR number
- * - "address": memory address
- * - "size": memory size
- * - "mem_type_64": true or false
- * - "prefetch": true or false
- */
void do_pci_info(Monitor *mon, QObject **ret_data)
{
QList *bus_list;
diff --git a/hw/qdev.c b/hw/qdev.c
index af17486..aa2ce01 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -779,19 +779,6 @@ void do_info_qdm(Monitor *mon)
}
}
-/**
- * do_device_add(): Add a device
- *
- * Argument qdict contains
- * - "driver": the name of the new device's driver
- * - "bus": the device's parent bus (device tree path)
- * - "id": the device's ID (must be unique)
- * - device properties
- *
- * Example:
- *
- * { "driver": "usb-net", "id": "eth1", "netdev": "netdev1" }
- */
int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
QemuOpts *opts;
diff --git a/input.c b/input.c
index 8f0941e..651442d 100644
--- a/input.c
+++ b/input.c
@@ -214,24 +214,6 @@ void do_info_mice_print(Monitor *mon, const QObject *data)
qlist_iter(mice_list, info_mice_iter, mon);
}
-/**
- * do_info_mice(): Show VM mice information
- *
- * Each mouse is represented by a QDict, the returned QObject is a QList of
- * all mice.
- *
- * The mouse QDict contains the following:
- *
- * - "name": mouse's name
- * - "index": mouse's index
- * - "current": true if this mouse is receiving events, false otherwise
- * - "absolute": true if the mouse generates absolute input events
- *
- * Example:
- *
- * [ { "name": "QEMU Microsoft Mouse", "index": 0, "current": false, "absolute": false },
- * { "name": "QEMU PS/2 Mouse", "index": 1, "current": true, "absolute": true } ]
- */
void do_info_mice(Monitor *mon, QObject **ret_data)
{
QEMUPutMouseEntry *cursor;
diff --git a/migration.c b/migration.c
index 05f6cc5..706fe55 100644
--- a/migration.c
+++ b/migration.c
@@ -197,44 +197,6 @@ static void migrate_put_status(QDict *qdict, const char *name,
qdict_put_obj(qdict, name, obj);
}
-/**
- * do_info_migrate(): Migration status
- *
- * Return a QDict. If migration is active there will be another
- * QDict with RAM migration status and if block migration is active
- * another one with block migration status.
- *
- * The main QDict contains the following:
- *
- * - "status": migration status
- * - "ram": only present if "status" is "active", it is a QDict with the
- * following RAM information (in bytes):
- * - "transferred": amount transferred
- * - "remaining": amount remaining
- * - "total": total
- * - "disk": only present if "status" is "active" and it is a block migration,
- * it is a QDict with the following disk information (in bytes):
- * - "transferred": amount transferred
- * - "remaining": amount remaining
- * - "total": total
- *
- * Examples:
- *
- * 1. Migration is "completed":
- *
- * { "status": "completed" }
- *
- * 2. Migration is "active" and it is not a block migration:
- *
- * { "status": "active",
- * "ram": { "transferred": 123, "remaining": 123, "total": 246 } }
- *
- * 3. Migration is "active" and it is a block migration:
- *
- * { "status": "active",
- * "ram": { "total": 1057024, "remaining": 1053304, "transferred": 3720 },
- * "disk": { "total": 20971520, "remaining": 20880384, "transferred": 91136 }}
- */
void do_info_migrate(Monitor *mon, QObject **ret_data)
{
QDict *qdict;
diff --git a/monitor.c b/monitor.c
index ad50f12..15b53b9 100644
--- a/monitor.c
+++ b/monitor.c
@@ -677,18 +677,6 @@ static void do_info_version_print(Monitor *mon, const QObject *data)
qdict_get_str(qdict, "package"));
}
-/**
- * do_info_version(): Show QEMU version
- *
- * Return a QDict with the following information:
- *
- * - "qemu": QEMU's version
- * - "package": package's version
- *
- * Example:
- *
- * { "qemu": "0.11.50", "package": "" }
- */
static void do_info_version(Monitor *mon, QObject **ret_data)
{
*ret_data = qobject_from_jsonf("{ 'qemu': %s, 'package': %s }",
@@ -707,17 +695,6 @@ static void do_info_name_print(Monitor *mon, const QObject *data)
monitor_printf(mon, "%s\n", qdict_get_str(qdict, "name"));
}
-/**
- * do_info_name(): Show VM name
- *
- * Return a QDict with the following information:
- *
- * - "name": VM's name (optional)
- *
- * Example:
- *
- * { "name": "qemu-name" }
- */
static void do_info_name(Monitor *mon, QObject **ret_data)
{
*ret_data = qemu_name ? qobject_from_jsonf("{'name': %s }", qemu_name) :
@@ -739,20 +716,6 @@ static QObject *get_cmd_dict(const char *name)
return qobject_from_jsonf("{ 'name': %s }", p);
}
-/**
- * do_info_commands(): List QMP available commands
- *
- * Each command is represented by a QDict, the returned QObject is a QList
- * of all commands.
- *
- * The QDict contains:
- *
- * - "name": command's name
- *
- * Example:
- *
- * { [ { "name": "query-balloon" }, { "name": "system_powerdown" } ] }
- */
static void do_info_commands(Monitor *mon, QObject **ret_data)
{
QList *cmd_list;
@@ -785,17 +748,6 @@ static void do_info_hpet_print(Monitor *mon, const QObject *data)
"enabled" : "disabled");
}
-/**
- * do_info_hpet(): Show HPET state
- *
- * Return a QDict with the following information:
- *
- * - "enabled": true if hpet if enabled, false otherwise
- *
- * Example:
- *
- * { "enabled": true }
- */
static void do_info_hpet(Monitor *mon, QObject **ret_data)
{
*ret_data = qobject_from_jsonf("{ 'enabled': %i }", !no_hpet);
@@ -807,17 +759,6 @@ static void do_info_uuid_print(Monitor *mon, const QObject *data)
monitor_printf(mon, "%s\n", qdict_get_str(qobject_to_qdict(data), "UUID"));
}
-/**
- * do_info_uuid(): Show VM UUID
- *
- * Return a QDict with the following information:
- *
- * - "UUID": Universally Unique Identifier
- *
- * Example:
- *
- * { "UUID": "550e8400-e29b-41d4-a716-446655440000" }
- */
static void do_info_uuid(Monitor *mon, QObject **ret_data)
{
char uuid[64];
@@ -913,25 +854,6 @@ static void monitor_print_cpus(Monitor *mon, const QObject *data)
qlist_iter(cpu_list, print_cpu_iter, mon);
}
-/**
- * do_info_cpus(): Show CPU information
- *
- * Return a QList. Each CPU is represented by a QDict, which contains:
- *
- * - "cpu": CPU index
- * - "current": true if this is the current CPU, false otherwise
- * - "halted": true if the cpu is halted, false otherwise
- * - Current program counter. The key's name depends on the architecture:
- * "pc": i386/x86)64
- * "nip": PPC
- * "pc" and "npc": sparc
- * "PC": mips
- *
- * Example:
- *
- * [ { "CPU": 0, "current": true, "halted": false, "pc": 3227107138 },
- * { "CPU": 1, "current": false, "halted": true, "pc": 7108165 } ]
- */
static void do_info_cpus(Monitor *mon, QObject **ret_data)
{
CPUState *env;
@@ -2106,18 +2028,6 @@ static void do_info_kvm_print(Monitor *mon, const QObject *data)
}
}
-/**
- * do_info_kvm(): Show KVM information
- *
- * Return a QDict with the following information:
- *
- * - "enabled": true if KVM support is enabled, false otherwise
- * - "present": true if QEMU has KVM support, false otherwise
- *
- * Example:
- *
- * { "enabled": true, "present": true }
- */
static void do_info_kvm(Monitor *mon, QObject **ret_data)
{
#ifdef CONFIG_KVM
@@ -2261,18 +2171,6 @@ static void do_info_status_print(Monitor *mon, const QObject *data)
monitor_printf(mon, "\n");
}
-/**
- * do_info_status(): VM status
- *
- * Return a QDict with the following information:
- *
- * - "running": true if the VM is running, or false if it is paused
- * - "singlestep": true if the VM is in single step mode, false otherwise
- *
- * Example:
- *
- * { "running": true, "singlestep": false }
- */
static void do_info_status(Monitor *mon, QObject **ret_data)
{
*ret_data = qobject_from_jsonf("{ 'running': %i, 'singlestep': %i }",
diff --git a/net.c b/net.c
index 378edfc..efa8b3d 100644
--- a/net.c
+++ b/net.c
@@ -1194,18 +1194,6 @@ void net_host_device_remove(Monitor *mon, const QDict *qdict)
qemu_del_vlan_client(vc);
}
-/**
- * do_netdev_add(): Add a host network device
- *
- * Argument qdict contains
- * - "type": the device type, "tap", "user", ...
- * - "id": the device's ID (must be unique)
- * - device options
- *
- * Example:
- *
- * { "type": "user", "id": "netdev1", "hostname": "a-guest" }
- */
int do_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
QemuOpts *opts;
@@ -1220,16 +1208,6 @@ int do_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
return res;
}
-/**
- * do_netdev_del(): Delete a host network device
- *
- * Argument qdict contains
- * - "id": the device's ID
- *
- * Example:
- *
- * { "id": "netdev1" }
- */
int do_netdev_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
const char *id = qdict_get_str(qdict, "id");
diff --git a/qemu-char.c b/qemu-char.c
index ac65a1c..faaf624 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2528,22 +2528,6 @@ void qemu_chr_info_print(Monitor *mon, const QObject *ret_data)
qlist_iter(qobject_to_qlist(ret_data), qemu_chr_qlist_iter, mon);
}
-/**
- * qemu_chr_info(): Character devices information
- *
- * Each device is represented by a QDict. The returned QObject is a QList
- * of all devices.
- *
- * The QDict contains the following:
- *
- * - "label": device's label
- * - "filename": device's file
- *
- * Example:
- *
- * [ { "label": "monitor", "filename", "stdio" },
- * { "label": "serial0", "filename": "vc" } ]
- */
void qemu_chr_info(Monitor *mon, QObject **ret_data)
{
QList *chr_list;
diff --git a/vnc.c b/vnc.c
index 30db8b1..ed0e096 100644
--- a/vnc.c
+++ b/vnc.c
@@ -323,35 +323,6 @@ void do_info_vnc_print(Monitor *mon, const QObject *data)
}
}
-/**
- * do_info_vnc(): Show VNC server information
- *
- * Return a QDict with server information. Connected clients are returned
- * as a QList of QDicts.
- *
- * The main QDict contains the following:
- *
- * - "enabled": true or false
- * - "host": server's IP address
- * - "family": address family ("ipv4" or "ipv6")
- * - "service": server's port number
- * - "auth": authentication method
- * - "clients": a QList of all connected clients
- *
- * Clients are described by a QDict, with the following information:
- *
- * - "host": client's IP address
- * - "family": address family ("ipv4" or "ipv6")
- * - "service": client's port number
- * - "x509_dname": TLS dname (optional)
- * - "sasl_username": SASL username (optional)
- *
- * Example:
- *
- * { "enabled": true, "host": "0.0.0.0", "service": "50402", "auth": "vnc",
- * "family": "ipv4",
- * "clients": [{ "host": "127.0.0.1", "service": "50401", "family": "ipv4" }]}
- */
void do_info_vnc(Monitor *mon, QObject **ret_data)
{
if (vnc_display == NULL || vnc_display->display == NULL) {
commit b40292e7115da8814da3d8acd33267202d27d678
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Mon May 31 14:43:31 2010 -0300
QMP: Introduce commands documentation
One of the most important missing feature in QMP today is its
supported commands documentation.
The plan is to make it part of self-description support, however
self-description is a big task we have been postponing for a
long time now and still don't know when it's going to be done.
In order not to compromise QMP adoption and make users' life easier,
this commit adds a simple text documentation which fully describes
all QMP supported commands.
This is not ideal for a number of reasons (harder to maintain,
text-only, etc) but does improve the current situation. To avoid at
least divering from the user monitor help and texi snippets, QMP bits
are also maintained inside qemu-monitor.hx, and hxtool is extended to
generate a single text file from them.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/Makefile b/Makefile
index 8fa593b..cc5fc45 100644
--- a/Makefile
+++ b/Makefile
@@ -29,7 +29,7 @@ $(call set-vpath, $(SRC_PATH):$(SRC_PATH)/hw)
LIBS+=-lz $(LIBS_TOOLS)
ifdef BUILD_DOCS
-DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1 qemu-nbd.8
+DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1 qemu-nbd.8 QMP/qmp-commands.txt
else
DOCS=
endif
@@ -263,6 +263,9 @@ qemu-options.texi: $(SRC_PATH)/qemu-options.hx
qemu-monitor.texi: $(SRC_PATH)/qemu-monitor.hx
$(call quiet-command,sh $(SRC_PATH)/hxtool -t < $< > $@," GEN $@")
+QMP/qmp-commands.txt: $(SRC_PATH)/qemu-monitor.hx
+ $(call quiet-command,sh $(SRC_PATH)/hxtool -q < $< > $@," GEN $@")
+
qemu-img-cmds.texi: $(SRC_PATH)/qemu-img-cmds.hx
$(call quiet-command,sh $(SRC_PATH)/hxtool -t < $< > $@," GEN $@")
diff --git a/QMP/README b/QMP/README
index 9334c25..35a80c7 100644
--- a/QMP/README
+++ b/QMP/README
@@ -15,8 +15,9 @@ QMP is JSON[1] based and has the following features:
For more information, please, refer to the following files:
-o qmp-spec.txt QEMU Monitor Protocol current specification
-o qmp-events.txt List of available asynchronous events
+o qmp-spec.txt QEMU Monitor Protocol current specification
+o qmp-commands.txt QMP supported commands
+o qmp-events.txt List of available asynchronous events
There are also two simple Python scripts available:
diff --git a/configure b/configure
index 3cd2c5f..653c8d2 100755
--- a/configure
+++ b/configure
@@ -2817,3 +2817,7 @@ ln -s $source_path/Makefile.user $d/Makefile
if test "$static" = "no" -a "$user_pie" = "yes" ; then
echo "QEMU_CFLAGS+=-fpie" > $d/config.mak
fi
+
+if test "$docs" = "yes" ; then
+ mkdir -p QMP
+fi
diff --git a/hxtool b/hxtool
index 8f65532..d499dc0 100644
--- a/hxtool
+++ b/hxtool
@@ -7,7 +7,7 @@ hxtoh()
case $str in
HXCOMM*)
;;
- STEXI*|ETEXI*) flag=$(($flag^1))
+ STEXI*|ETEXI*|SQMP*|EQMP*) flag=$(($flag^1))
;;
*)
test $flag -eq 1 && printf "%s\n" "$str"
@@ -38,6 +38,12 @@ hxtotexi()
fi
flag=0
;;
+ SQMP*|EQMP*)
+ if test $flag -eq 1 ; then
+ echo "line $line: syntax error: expected ETEXI, found $str" >&2
+ exit 1
+ fi
+ ;;
DEFHEADING*)
echo "$(expr "$str" : "DEFHEADING(\(.*\))")"
;;
@@ -49,9 +55,45 @@ hxtotexi()
done
}
+hxtoqmp()
+{
+ IFS=
+ flag=0
+ while read -r str; do
+ case "$str" in
+ HXCOMM*)
+ ;;
+ SQMP*)
+ if test $flag -eq 1 ; then
+ echo "line $line: syntax error: expected EQMP, found $str" >&2
+ exit 1
+ fi
+ flag=1
+ ;;
+ EQMP*)
+ if test $flag -ne 1 ; then
+ echo "line $line: syntax error: expected SQMP, found $str" >&2
+ exit 1
+ fi
+ flag=0
+ ;;
+ STEXI*|ETEXI*)
+ if test $flag -eq 1 ; then
+ echo "line $line: syntax error: expected EQMP, found $str" >&2
+ exit 1
+ fi
+ ;;
+ *)
+ test $flag -eq 1 && echo "$str"
+ ;;
+ esac
+ done
+}
+
case "$1" in
"-h") hxtoh ;;
"-t") hxtotexi ;;
+"-q") hxtoqmp ;;
*) exit 1 ;;
esac
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index b8c765b..f6a94f2 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -1,10 +1,48 @@
HXCOMM Use DEFHEADING() to define headings in both help text and texi
HXCOMM Text between STEXI and ETEXI are copied to texi version and
HXCOMM discarded from C version
+HXCOMM Text between SQMP and EQMP is copied to the QMP documention file and
+HXCOMM does not show up in the other formats.
HXCOMM DEF(command, args, callback, arg_string, help) is used to construct
HXCOMM monitor commands
HXCOMM HXCOMM can be used for comments, discarded from both texi and C
+SQMP
+ QMP Supported Commands
+ ----------------------
+
+This document describes all commands currently supported by QMP.
+
+Most of the time their usage is exactly the same as in the user Monitor, this
+means that any other document which also describe commands (the manpage,
+QEMU's manual, etc) can and should be consulted.
+
+QMP has two types of commands: regular and query commands. Regular commands
+usually change the Virtual Machine's state someway, while query commands just
+return information. The sections below are divided accordingly.
+
+It's important to observe that all communication examples are formatted in
+a reader-friendly way, so that they're easier to understand. However, in real
+protocol usage, they're emitted as a single line.
+
+Also, the following notation is used to denote data flow:
+
+-> data issued by the Client
+<- Server data response
+
+Please, refer to the QMP specification (QMP/qmp-spec.txt) for detailed
+information on the Server command and response formats.
+
+NOTE: This document is temporary and will be replaced soon.
+
+1. Regular Commands
+===================
+
+Server's responses in the examples below are always a success response, please
+refer to the QMP specification for more details on error responses.
+
+EQMP
+
STEXI
@table @option
ETEXI
@@ -51,6 +89,20 @@ STEXI
@findex quit
Quit the emulator.
ETEXI
+SQMP
+quit
+----
+
+Quit the emulator.
+
+Arguments: None.
+
+Example:
+
+-> { "execute": "quit" }
+<- { "return": {} }
+
+EQMP
{
.name = "eject",
@@ -66,6 +118,25 @@ STEXI
@findex eject
Eject a removable medium (use -f to force it).
ETEXI
+SQMP
+eject
+-----
+
+Eject a removable medium.
+
+Arguments:
+
+- force: force ejection (json-bool, optional)
+- device: device name (json-string)
+
+Example:
+
+-> { "execute": "eject", "arguments": { "device": "ide1-cd0" } }
+<- { "return": {} }
+
+Note: The "force" argument defaults to false.
+
+EQMP
{
.name = "change",
@@ -113,6 +184,35 @@ Password: ********
@end table
ETEXI
+SQMP
+change
+------
+
+Change a removable medium or VNC configuration.
+
+Arguments:
+
+- "device": device name (json-string)
+- "target": filename or item (json-string)
+- "arg": additional argument (json-string, optional)
+
+Examples:
+
+1. Change a removable medium
+
+-> { "execute": "change",
+ "arguments": { "device": "ide1-cd0",
+ "target": "/srv/images/Fedora-12-x86_64-DVD.iso" } }
+<- { "return": {} }
+
+2. Change VNC password
+
+-> { "execute": "change",
+ "arguments": { "device": "vnc", "target": "password",
+ "arg": "foobar1" } }
+<- { "return": {} }
+
+EQMP
{
.name = "screendump",
@@ -128,6 +228,22 @@ STEXI
@findex screendump
Save screen into PPM image @var{filename}.
ETEXI
+SQMP
+screendump
+----------
+
+Save screen into PPM image.
+
+Arguments:
+
+- "filename": file path (json-string)
+
+Example:
+
+-> { "execute": "screendump", "arguments": { "filename": "/tmp/image" } }
+<- { "return": {} }
+
+EQMP
{
.name = "logfile",
@@ -232,6 +348,20 @@ STEXI
@findex stop
Stop emulation.
ETEXI
+SQMP
+stop
+----
+
+Stop the emulator.
+
+Arguments: None.
+
+Example:
+
+-> { "execute": "stop" }
+<- { "return": {} }
+
+EQMP
{
.name = "c|cont",
@@ -247,6 +377,20 @@ STEXI
@findex cont
Resume emulation.
ETEXI
+SQMP
+cont
+----
+
+Resume emulation.
+
+Arguments: None.
+
+Example:
+
+-> { "execute": "cont" }
+<- { "return": {} }
+
+EQMP
{
.name = "gdbserver",
@@ -421,6 +565,20 @@ STEXI
Reset the system.
ETEXI
+SQMP
+system_reset
+------------
+
+Reset the system.
+
+Arguments: None.
+
+Example:
+
+-> { "execute": "system_reset" }
+<- { "return": {} }
+
+EQMP
{
.name = "system_powerdown",
@@ -437,6 +595,20 @@ STEXI
Power down the system (if supported).
ETEXI
+SQMP
+system_powerdown
+----------------
+
+Send system power down event.
+
+Arguments: None.
+
+Example:
+
+-> { "execute": "system_powerdown" }
+<- { "return": {} }
+
+EQMP
{
.name = "sum",
@@ -501,6 +673,33 @@ STEXI
Add device.
ETEXI
+SQMP
+device_add
+----------
+
+Add a device.
+
+Arguments:
+
+- "driver": the name of the new device's driver (json-string)
+- "bus": the device's parent bus (device tree path, json-string, optional)
+- "id": the device's ID, must be unique (json-string)
+- device properties
+
+Example:
+
+-> { "execute": "device_add", "arguments": { "driver": "e1000", "id": "net1" } }
+<- { "return": {} }
+
+Notes:
+
+(1) For detailed information about this command, please refer to the
+ 'docs/qdev-device-use.txt' file.
+
+(2) It's possible to list device properties by running QEMU with the
+ "-device DEVICE,\?" command-line argument, where DEVICE is the device's name
+
+EQMP
{
.name = "device_del",
@@ -517,6 +716,22 @@ STEXI
Remove device @var{id}.
ETEXI
+SQMP
+device_del
+----------
+
+Remove a device.
+
+Arguments:
+
+- "id": the device's ID (json-string)
+
+Example:
+
+-> { "execute": "device_del", "arguments": { "id": "net1" } }
+<- { "return": {} }
+
+EQMP
{
.name = "cpu",
@@ -532,6 +747,24 @@ STEXI
@findex cpu
Set the default CPU.
ETEXI
+SQMP
+cpu
+---
+
+Set the default CPU.
+
+Arguments:
+
+- "index": the CPU's index (json-int)
+
+Example:
+
+-> { "execute": "cpu", "arguments": { "index": 0 } }
+<- { "return": {} }
+
+Note: CPUs' indexes are obtained with the 'query-cpus' command.
+
+EQMP
{
.name = "mouse_move",
@@ -635,6 +868,29 @@ STEXI
@findex memsave
save to disk virtual memory dump starting at @var{addr} of size @var{size}.
ETEXI
+SQMP
+memsave
+-------
+
+Save to disk virtual memory dump starting at 'val' of size 'size'.
+
+Arguments:
+
+- "val": the starting address (json-int)
+- "size": the memory size, in bytes (json-int)
+- "filename": file path (json-string)
+
+Example:
+
+-> { "execute": "memsave",
+ "arguments": { "val": 10,
+ "size": 100,
+ "filename": "/tmp/virtual-mem-dump" } }
+<- { "return": {} }
+
+Note: Depends on the current CPU.
+
+EQMP
{
.name = "pmemsave",
@@ -650,6 +906,27 @@ STEXI
@findex pmemsave
save to disk physical memory dump starting at @var{addr} of size @var{size}.
ETEXI
+SQMP
+pmemsave
+--------
+
+Save to disk physical memory dump starting at 'val' of size 'size'.
+
+Arguments:
+
+- "val": the starting address (json-int)
+- "size": the memory size, in bytes (json-int)
+- "filename": file path (json-string)
+
+Example:
+
+-> { "execute": "pmemsave",
+ "arguments": { "val": 10,
+ "size": 100,
+ "filename": "/tmp/physical-mem-dump" } }
+<- { "return": {} }
+
+EQMP
{
.name = "boot_set",
@@ -706,6 +983,32 @@ Migrate to @var{uri} (using -d to not wait for completion).
-b for migration with full copy of disk
-i for migration with incremental copy of disk (base image is shared)
ETEXI
+SQMP
+migrate
+-------
+
+Migrate to URI.
+
+Arguments:
+
+- "blk": block migration, full disk copy (json-bool, optional)
+- "inc": incremental disk copy (json-bool, optional)
+- "uri": Destination URI (json-string)
+
+Example:
+
+-> { "execute": "migrate", "arguments": { "uri": "tcp:0:4446" } }
+<- { "return": {} }
+
+Notes:
+
+(1) The 'query-migrate' command should be used to check migration's progress
+ and final result (this information is provided by the 'status' member)
+(2) All boolean arguments default to false
+(3) The user Monitor's "detach" argument is invalid in QMP and should not
+ be used
+
+EQMP
{
.name = "migrate_cancel",
@@ -721,6 +1024,20 @@ STEXI
@findex migrate_cancel
Cancel the current VM migration.
ETEXI
+SQMP
+migrate_cancel
+--------------
+
+Cancel the current migration.
+
+Arguments: None.
+
+Example:
+
+-> { "execute": "migrate_cancel" }
+<- { "return": {} }
+
+EQMP
{
.name = "migrate_set_speed",
@@ -736,6 +1053,22 @@ STEXI
@findex migrate_set_speed
Set maximum speed to @var{value} (in bytes) for migrations.
ETEXI
+SQMP
+migrate_set_speed
+-----------------
+
+Set maximum speed for migrations.
+
+Arguments:
+
+- "value": maximum speed, in bytes per second (json-number)
+
+Example:
+
+-> { "execute": "migrate_set_speed", "arguments": { "value": 1024 } }
+<- { "return": {} }
+
+EQMP
{
.name = "migrate_set_downtime",
@@ -751,6 +1084,22 @@ STEXI
@findex migrate_set_downtime
Set maximum tolerated downtime (in seconds) for migration.
ETEXI
+SQMP
+migrate_set_downtime
+--------------------
+
+Set maximum tolerated downtime (in seconds) for migrations.
+
+Arguments:
+
+- "value": maximum downtime (json-number)
+
+Example:
+
+-> { "execute": "migrate_set_downtime", "arguments": { "value": 0.1 } }
+<- { "return": {} }
+
+EQMP
#if defined(TARGET_I386)
{
@@ -846,6 +1195,28 @@ STEXI
@findex netdev_add
Add host network device.
ETEXI
+SQMP
+netdev_add
+----------
+
+Add host network device.
+
+Arguments:
+
+- "type": the device type, "tap", "user", ... (json-string)
+- "id": the device's ID, must be unique (json-string)
+- device options
+
+Example:
+
+-> { "execute": "netdev_add", "arguments": { "type": "user", "id": "netdev1" } }
+<- { "return": {} }
+
+Note: The supported device options are the same ones supported by the '-net'
+ command-line argument, which are listed in the '-help' output or QEMU's
+ manual
+
+EQMP
{
.name = "netdev_del",
@@ -861,6 +1232,22 @@ STEXI
@findex netdev_del
Remove host network device.
ETEXI
+SQMP
+netdev_del
+----------
+
+Remove host network device.
+
+Arguments:
+
+- "id": the device's ID, must be unique (json-string)
+
+Example:
+
+-> { "execute": "netdev_del", "arguments": { "id": "netdev1" } }
+<- { "return": {} }
+
+EQMP
#ifdef CONFIG_SLIRP
{
@@ -908,6 +1295,22 @@ STEXI
@findex balloon
Request VM to change its memory allocation to @var{value} (in MB).
ETEXI
+SQMP
+balloon
+-------
+
+Request VM to change its memory allocation (in bytes).
+
+Arguments:
+
+- "value": New memory allocation (json-int)
+
+Example:
+
+-> { "execute": "balloon", "arguments": { "value": 536870912 } }
+<- { "return": {} }
+
+EQMP
{
.name = "set_link",
@@ -923,6 +1326,23 @@ STEXI
@findex set_link
Switch link @var{name} on (i.e. up) or off (i.e. down).
ETEXI
+SQMP
+set_link
+--------
+
+Change the link status of a network adapter.
+
+Arguments:
+
+- "name": network device name (json-string)
+- "up": status is up (json-bool)
+
+Example:
+
+-> { "execute": "set_link", "arguments": { "name": "e1000.0", "up": false } }
+<- { "return": {} }
+
+EQMP
{
.name = "watchdog_action",
@@ -1052,6 +1472,22 @@ If a file descriptor is passed alongside this command using the SCM_RIGHTS
mechanism on unix sockets, it is stored using the name @var{fdname} for
later use by other monitor commands.
ETEXI
+SQMP
+getfd
+-----
+
+Receive a file descriptor via SCM rights and assign it a name.
+
+Arguments:
+
+- "fdname": file descriptor name (json-string)
+
+Example:
+
+-> { "execute": "getfd", "arguments": { "fdname": "fd1" } }
+<- { "return": {} }
+
+EQMP
{
.name = "closefd",
@@ -1069,6 +1505,22 @@ Close the file descriptor previously assigned to @var{fdname} using the
@code{getfd} command. This is only needed if the file descriptor was never
used by another monitor command.
ETEXI
+SQMP
+closefd
+-------
+
+Close a file descriptor previously passed via SCM rights.
+
+Arguments:
+
+- "fdname": file descriptor name (json-string)
+
+Example:
+
+-> { "execute": "closefd", "arguments": { "fdname": "fd1" } }
+<- { "return": {} }
+
+EQMP
{
.name = "block_passwd",
@@ -1084,6 +1536,24 @@ STEXI
@findex block_passwd
Set the encrypted device @var{device} password to @var{password}
ETEXI
+SQMP
+block_passwd
+------------
+
+Set the password of encrypted block devices.
+
+Arguments:
+
+- "device": device name (json-string)
+- "password": password (json-string)
+
+Example:
+
+-> { "execute": "block_passwd", "arguments": { "device": "ide0-hd0",
+ "password": "12345" } }
+<- { "return": {} }
+
+EQMP
{
.name = "qmp_capabilities",
@@ -1099,11 +1569,34 @@ STEXI
@findex qmp_capabilities
Enable the specified QMP capabilities
ETEXI
+SQMP
+qmp_capabilities
+----------------
+
+Enable QMP capabilities.
+
+Arguments: None.
+
+Example:
+
+-> { "execute": "qmp_capabilities" }
+<- { "return": {} }
+
+Note: This command must be issued before issuing any other command.
+
+EQMP
HXCOMM Keep the 'info' command at the end!
HXCOMM This is required for the QMP documentation layout.
+SQMP
+
+2. Query Commands
+=================
+
+EQMP
+
{
.name = "info",
.args_type = "item:s?",
@@ -1121,40 +1614,588 @@ Show various information about the system state.
@table @option
@item info version
show the version of QEMU
+ETEXI
+SQMP
+query-version
+-------------
+
+Show QEMU version.
+
+Return a json-object with the following information:
+
+- "qemu": QEMU's version (json-string)
+- "package": package's version (json-string)
+
+Example:
+
+-> { "execute": "query-version" }
+<- { "return": { "qemu": "0.11.50", "package": "" } }
+
+EQMP
+
+STEXI
@item info commands
list QMP available commands
+ETEXI
+SQMP
+query-commands
+--------------
+
+List QMP available commands.
+
+Each command is represented by a json-object, the returned value is a json-array
+of all commands.
+
+Each json-object contain:
+
+- "name": command's name (json-string)
+
+Example:
+
+-> { "execute": "query-commands" }
+<- {
+ "return":[
+ {
+ "name":"query-balloon"
+ },
+ {
+ "name":"system_powerdown"
+ }
+ ]
+ }
+
+Note: This example has been shortened as the real response is too long.
+
+EQMP
+
+STEXI
@item info network
show the various VLANs and the associated devices
+ETEXI
+
+STEXI
@item info chardev
show the character devices
+ETEXI
+SQMP
+query-chardev
+-------------
+
+Each device is represented by a json-object. The returned value is a json-array
+of all devices.
+
+Each json-object contain the following:
+
+- "label": device's label (json-string)
+- "filename": device's file (json-string)
+
+Example:
+
+-> { "execute": "query-chardev" }
+<- {
+ "return":[
+ {
+ "label":"monitor",
+ "filename":"stdio"
+ },
+ {
+ "label":"serial0",
+ "filename":"vc"
+ }
+ ]
+ }
+
+EQMP
+
+STEXI
@item info block
show the block devices
+ETEXI
+SQMP
+query-block
+-----------
+
+Show the block devices.
+
+Each block device information is stored in a json-object and the returned value
+is a json-array of all devices.
+
+Each json-object contain the following:
+
+- "device": device name (json-string)
+- "type": device type (json-string)
+ - Possible values: "hd", "cdrom", "floppy", "unknown"
+- "removable": true if the device is removable, false otherwise (json-bool)
+- "locked": true if the device is locked, false otherwise (json-bool)
+- "inserted": only present if the device is inserted, it is a json-object
+ containing the following:
+ - "file": device file name (json-string)
+ - "ro": true if read-only, false otherwise (json-bool)
+ - "drv": driver format name (json-string)
+ - Possible values: "blkdebug", "bochs", "cloop", "cow", "dmg",
+ "file", "file", "ftp", "ftps", "host_cdrom",
+ "host_device", "host_floppy", "http", "https",
+ "nbd", "parallels", "qcow", "qcow2", "raw",
+ "tftp", "vdi", "vmdk", "vpc", "vvfat"
+ - "backing_file": backing file name (json-string, optional)
+ - "encrypted": true if encrypted, false otherwise (json-bool)
+
+Example:
+
+-> { "execute": "query-block" }
+<- {
+ "return":[
+ {
+ "device":"ide0-hd0",
+ "locked":false,
+ "removable":false,
+ "inserted":{
+ "ro":false,
+ "drv":"qcow2",
+ "encrypted":false,
+ "file":"disks/test.img"
+ },
+ "type":"hd"
+ },
+ {
+ "device":"ide1-cd0",
+ "locked":false,
+ "removable":true,
+ "type":"cdrom"
+ },
+ {
+ "device":"floppy0",
+ "locked":false,
+ "removable":true,
+ "type": "floppy"
+ },
+ {
+ "device":"sd0",
+ "locked":false,
+ "removable":true,
+ "type":"floppy"
+ }
+ ]
+ }
+
+EQMP
+
+STEXI
@item info blockstats
show block device statistics
+ETEXI
+SQMP
+query-blockstats
+----------------
+
+Show block device statistics.
+
+Each device statistic information is stored in a json-object and the returned
+value is a json-array of all devices.
+
+Each json-object contain the following:
+
+- "device": device name (json-string)
+- "stats": A json-object with the statistics information, it contains:
+ - "rd_bytes": bytes read (json-int)
+ - "wr_bytes": bytes written (json-int)
+ - "rd_operations": read operations (json-int)
+ - "wr_operations": write operations (json-int)
+ - "wr_highest_offset": Highest offset of a sector written since the
+ BlockDriverState has been opened (json-int)
+- "parent": Contains recursively the statistics of the underlying
+ protocol (e.g. the host file for a qcow2 image). If there is
+ no underlying protocol, this field is omitted
+ (json-object, optional)
+
+Example:
+
+-> { "execute": "query-blockstats" }
+<- {
+ "return":[
+ {
+ "device":"ide0-hd0",
+ "parent":{
+ "stats":{
+ "wr_highest_offset":3686448128,
+ "wr_bytes":9786368,
+ "wr_operations":751,
+ "rd_bytes":122567168,
+ "rd_operations":36772
+ }
+ },
+ "stats":{
+ "wr_highest_offset":2821110784,
+ "wr_bytes":9786368,
+ "wr_operations":692,
+ "rd_bytes":122739200,
+ "rd_operations":36604
+ }
+ },
+ {
+ "device":"ide1-cd0",
+ "stats":{
+ "wr_highest_offset":0,
+ "wr_bytes":0,
+ "wr_operations":0,
+ "rd_bytes":0,
+ "rd_operations":0
+ }
+ },
+ {
+ "device":"floppy0",
+ "stats":{
+ "wr_highest_offset":0,
+ "wr_bytes":0,
+ "wr_operations":0,
+ "rd_bytes":0,
+ "rd_operations":0
+ }
+ },
+ {
+ "device":"sd0",
+ "stats":{
+ "wr_highest_offset":0,
+ "wr_bytes":0,
+ "wr_operations":0,
+ "rd_bytes":0,
+ "rd_operations":0
+ }
+ }
+ ]
+ }
+
+EQMP
+
+STEXI
@item info registers
show the cpu registers
@item info cpus
show infos for each CPU
+ETEXI
+SQMP
+query-cpus
+----------
+
+Show CPU information.
+
+Return a json-array. Each CPU is represented by a json-object, which contains:
+
+- "CPU": CPU index (json-int)
+- "current": true if this is the current CPU, false otherwise (json-bool)
+- "halted": true if the cpu is halted, false otherwise (json-bool)
+- Current program counter. The key's name depends on the architecture:
+ "pc": i386/x86_64 (json-int)
+ "nip": PPC (json-int)
+ "pc" and "npc": sparc (json-int)
+ "PC": mips (json-int)
+
+Example:
+
+-> { "execute": "query-cpus" }
+<- {
+ "return":[
+ {
+ "CPU":0,
+ "current":true,
+ "halted":false,
+ "pc":3227107138
+ },
+ {
+ "CPU":1,
+ "current":false,
+ "halted":true,
+ "pc":7108165
+ }
+ ]
+ }
+
+EQMP
+
+STEXI
@item info history
show the command line history
@item info irq
show the interrupts statistics (if available)
@item info pic
show i8259 (PIC) state
+ETEXI
+
+STEXI
@item info pci
show emulated PCI device info
+ETEXI
+SQMP
+query-pci
+---------
+
+PCI buses and devices information.
+
+The returned value is a json-array of all buses. Each bus is represented by
+a json-object, which has a key with a json-array of all PCI devices attached
+to it. Each device is represented by a json-object.
+
+The bus json-object contains the following:
+
+- "bus": bus number (json-int)
+- "devices": a json-array of json-objects, each json-object represents a
+ PCI device
+
+The PCI device json-object contains the following:
+
+- "bus": identical to the parent's bus number (json-int)
+- "slot": slot number (json-int)
+- "function": function number (json-int)
+- "class_info": a json-object containing:
+ - "desc": device class description (json-string, optional)
+ - "class": device class number (json-int)
+- "id": a json-object containing:
+ - "device": device ID (json-int)
+ - "vendor": vendor ID (json-int)
+- "irq": device's IRQ if assigned (json-int, optional)
+- "qdev_id": qdev id string (json-string)
+- "pci_bridge": It's a json-object, only present if this device is a
+ PCI bridge, contains:
+ - "bus": bus number (json-int)
+ - "secondary": secondary bus number (json-int)
+ - "subordinate": subordinate bus number (json-int)
+ - "io_range": I/O memory range information, a json-object with the
+ following members:
+ - "base": base address, in bytes (json-int)
+ - "limit": limit address, in bytes (json-int)
+ - "memory_range": memory range information, a json-object with the
+ following members:
+ - "base": base address, in bytes (json-int)
+ - "limit": limit address, in bytes (json-int)
+ - "prefetchable_range": Prefetchable memory range information, a
+ json-object with the following members:
+ - "base": base address, in bytes (json-int)
+ - "limit": limit address, in bytes (json-int)
+ - "devices": a json-array of PCI devices if there's any attached, each
+ each element is represented by a json-object, which contains
+ the same members of the 'PCI device json-object' described
+ above (optional)
+- "regions": a json-array of json-objects, each json-object represents a
+ memory region of this device
+
+The memory range json-object contains the following:
+
+- "base": base memory address (json-int)
+- "limit": limit value (json-int)
+
+The region json-object can be an I/O region or a memory region, an I/O region
+json-object contains the following:
+
+- "type": "io" (json-string, fixed)
+- "bar": BAR number (json-int)
+- "address": memory address (json-int)
+- "size": memory size (json-int)
+
+A memory region json-object contains the following:
+
+- "type": "memory" (json-string, fixed)
+- "bar": BAR number (json-int)
+- "address": memory address (json-int)
+- "size": memory size (json-int)
+- "mem_type_64": true or false (json-bool)
+- "prefetch": true or false (json-bool)
+
+Example:
+
+-> { "execute": "query-pci" }
+<- {
+ "return":[
+ {
+ "bus":0,
+ "devices":[
+ {
+ "bus":0,
+ "qdev_id":"",
+ "slot":0,
+ "class_info":{
+ "class":1536,
+ "desc":"Host bridge"
+ },
+ "id":{
+ "device":32902,
+ "vendor":4663
+ },
+ "function":0,
+ "regions":[
+
+ ]
+ },
+ {
+ "bus":0,
+ "qdev_id":"",
+ "slot":1,
+ "class_info":{
+ "class":1537,
+ "desc":"ISA bridge"
+ },
+ "id":{
+ "device":32902,
+ "vendor":28672
+ },
+ "function":0,
+ "regions":[
+
+ ]
+ },
+ {
+ "bus":0,
+ "qdev_id":"",
+ "slot":1,
+ "class_info":{
+ "class":257,
+ "desc":"IDE controller"
+ },
+ "id":{
+ "device":32902,
+ "vendor":28688
+ },
+ "function":1,
+ "regions":[
+ {
+ "bar":4,
+ "size":16,
+ "address":49152,
+ "type":"io"
+ }
+ ]
+ },
+ {
+ "bus":0,
+ "qdev_id":"",
+ "slot":2,
+ "class_info":{
+ "class":768,
+ "desc":"VGA controller"
+ },
+ "id":{
+ "device":4115,
+ "vendor":184
+ },
+ "function":0,
+ "regions":[
+ {
+ "prefetch":true,
+ "mem_type_64":false,
+ "bar":0,
+ "size":33554432,
+ "address":4026531840,
+ "type":"memory"
+ },
+ {
+ "prefetch":false,
+ "mem_type_64":false,
+ "bar":1,
+ "size":4096,
+ "address":4060086272,
+ "type":"memory"
+ },
+ {
+ "prefetch":false,
+ "mem_type_64":false,
+ "bar":6,
+ "size":65536,
+ "address":-1,
+ "type":"memory"
+ }
+ ]
+ },
+ {
+ "bus":0,
+ "qdev_id":"",
+ "irq":11,
+ "slot":4,
+ "class_info":{
+ "class":1280,
+ "desc":"RAM controller"
+ },
+ "id":{
+ "device":6900,
+ "vendor":4098
+ },
+ "function":0,
+ "regions":[
+ {
+ "bar":0,
+ "size":32,
+ "address":49280,
+ "type":"io"
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+
+Note: This example has been shortened as the real response is too long.
+
+EQMP
+
+STEXI
@item info tlb
show virtual to physical memory mappings (i386 only)
@item info mem
show the active virtual memory mappings (i386 only)
+ETEXI
+
+STEXI
@item info hpet
show state of HPET (i386 only)
+ETEXI
+SQMP
+query-hpet
+----------
+
+Show HPET state.
+
+Return a json-object with the following information:
+
+- "enabled": true if hpet if enabled, false otherwise (json-bool)
+
+Example:
+
+-> { "execute": "query-hpet" }
+<- { "return": { "enabled": true } }
+
+EQMP
+
+STEXI
@item info jit
show dynamic compiler info
@item info kvm
show KVM information
@item info numa
show NUMA information
+ETEXI
+
+STEXI
+ at item info kvm
+show KVM information
+ETEXI
+SQMP
+query-kvm
+---------
+
+Show KVM information.
+
+Return a json-object with the following information:
+
+- "enabled": true if KVM support is enabled, false otherwise (json-bool)
+- "present": true if QEMU has KVM support, false otherwise (json-bool)
+
+Example:
+
+-> { "execute": "query-kvm" }
+<- { "return": { "enabled": true, "present": true } }
+
+EQMP
+
+STEXI
@item info usb
show USB devices plugged on the virtual USB hub
@item info usbhost
@@ -1165,26 +2206,307 @@ show profiling information
show information about active capturing
@item info snapshots
show list of VM snapshots
+ETEXI
+
+STEXI
@item info status
show the current VM status (running|paused)
+ETEXI
+SQMP
+query-status
+------------
+
+Return a json-object with the following information:
+
+- "running": true if the VM is running, or false if it is paused (json-bool)
+- "singlestep": true if the VM is in single step mode,
+ false otherwise (json-bool)
+
+Example:
+
+-> { "execute": "query-status" }
+<- { "return": { "running": true, "singlestep": false } }
+
+EQMP
+
+STEXI
@item info pcmcia
show guest PCMCIA status
+ETEXI
+
+STEXI
@item info mice
show which guest mouse is receiving events
+ETEXI
+SQMP
+query-mice
+----------
+
+Show VM mice information.
+
+Each mouse is represented by a json-object, the returned value is a json-array
+of all mice.
+
+The mouse json-object contains the following:
+
+- "name": mouse's name (json-string)
+- "index": mouse's index (json-int)
+- "current": true if this mouse is receiving events, false otherwise (json-bool)
+- "absolute": true if the mouse generates absolute input events (json-bool)
+
+Example:
+
+-> { "execute": "query-mice" }
+<- {
+ "return":[
+ {
+ "name":"QEMU Microsoft Mouse",
+ "index":0,
+ "current":false,
+ "absolute":false
+ },
+ {
+ "name":"QEMU PS/2 Mouse",
+ "index":1,
+ "current":true,
+ "absolute":true
+ }
+ ]
+ }
+
+EQMP
+
+STEXI
@item info vnc
show the vnc server status
+ETEXI
+SQMP
+query-vnc
+---------
+
+Show VNC server information.
+
+Return a json-object with server information. Connected clients are returned
+as a json-array of json-objects.
+
+The main json-object contains the following:
+
+- "enabled": true or false (json-bool)
+- "host": server's IP address (json-string)
+- "family": address family (json-string)
+ - Possible values: "ipv4", "ipv6", "unix", "unknown"
+- "service": server's port number (json-string)
+- "auth": authentication method (json-string)
+ - Possible values: "invalid", "none", "ra2", "ra2ne", "sasl", "tight",
+ "tls", "ultra", "unknown", "vencrypt", "vencrypt",
+ "vencrypt+plain", "vencrypt+tls+none",
+ "vencrypt+tls+plain", "vencrypt+tls+sasl",
+ "vencrypt+tls+vnc", "vencrypt+x509+none",
+ "vencrypt+x509+plain", "vencrypt+x509+sasl",
+ "vencrypt+x509+vnc", "vnc"
+- "clients": a json-array of all connected clients
+
+Clients are described by a json-object, each one contain the following:
+
+- "host": client's IP address (json-string)
+- "family": address family (json-string)
+ - Possible values: "ipv4", "ipv6", "unix", "unknown"
+- "service": client's port number (json-string)
+- "x509_dname": TLS dname (json-string, optional)
+- "sasl_username": SASL username (json-string, optional)
+
+Example:
+
+-> { "execute": "query-vnc" }
+<- {
+ "return":{
+ "enabled":true,
+ "host":"0.0.0.0",
+ "service":"50402",
+ "auth":"vnc",
+ "family":"ipv4",
+ "clients":[
+ {
+ "host":"127.0.0.1",
+ "service":"50401",
+ "family":"ipv4"
+ }
+ ]
+ }
+ }
+
+EQMP
+
+STEXI
@item info name
show the current VM name
+ETEXI
+SQMP
+query-name
+----------
+
+Show VM name.
+
+Return a json-object with the following information:
+
+- "name": VM's name (json-string, optional)
+
+Example:
+
+-> { "execute": "query-name" }
+<- { "return": { "name": "qemu-name" } }
+
+EQMP
+
+STEXI
@item info uuid
show the current VM UUID
+ETEXI
+SQMP
+query-uuid
+----------
+
+Show VM UUID.
+
+Return a json-object with the following information:
+
+- "UUID": Universally Unique Identifier (json-string)
+
+Example:
+
+-> { "execute": "query-uuid" }
+<- { "return": { "UUID": "550e8400-e29b-41d4-a716-446655440000" } }
+
+EQMP
+
+STEXI
@item info cpustats
show CPU statistics
@item info usernet
show user network stack connection states
+ETEXI
+
+STEXI
@item info migrate
show migration status
+ETEXI
+SQMP
+query-migrate
+-------------
+
+Migration status.
+
+Return a json-object. If migration is active there will be another json-object
+with RAM migration status and if block migration is active another one with
+block migration status.
+
+The main json-object contains the following:
+
+- "status": migration status (json-string)
+ - Possible values: "active", "completed", "failed", "cancelled"
+- "ram": only present if "status" is "active", it is a json-object with the
+ following RAM information (in bytes):
+ - "transferred": amount transferred (json-int)
+ - "remaining": amount remaining (json-int)
+ - "total": total (json-int)
+- "disk": only present if "status" is "active" and it is a block migration,
+ it is a json-object with the following disk information (in bytes):
+ - "transferred": amount transferred (json-int)
+ - "remaining": amount remaining (json-int)
+ - "total": total (json-int)
+
+Examples:
+
+1. Before the first migration
+
+-> { "execute": "query-migrate" }
+<- { "return": {} }
+
+2. Migration is done and has succeeded
+
+-> { "execute": "query-migrate" }
+<- { "return": { "status": "completed" } }
+
+3. Migration is done and has failed
+
+-> { "execute": "query-migrate" }
+<- { "return": { "status": "failed" } }
+
+4. Migration is being performed and is not a block migration:
+
+-> { "execute": "query-migrate" }
+<- {
+ "return":{
+ "status":"active",
+ "ram":{
+ "transferred":123,
+ "remaining":123,
+ "total":246
+ }
+ }
+ }
+
+5. Migration is being performed and is a block migration:
+
+-> { "execute": "query-migrate" }
+<- {
+ "return":{
+ "status":"active",
+ "ram":{
+ "total":1057024,
+ "remaining":1053304,
+ "transferred":3720
+ },
+ "disk":{
+ "total":20971520,
+ "remaining":20880384,
+ "transferred":91136
+ }
+ }
+ }
+
+EQMP
+
+STEXI
@item info balloon
show balloon information
+ETEXI
+SQMP
+query-balloon
+-------------
+
+Show balloon information.
+
+Make an asynchronous request for balloon info. When the request completes a
+json-object will be returned containing the following data:
+
+- "actual": current balloon value in bytes (json-int)
+- "mem_swapped_in": Amount of memory swapped in bytes (json-int, optional)
+- "mem_swapped_out": Amount of memory swapped out in bytes (json-int, optional)
+- "major_page_faults": Number of major faults (json-int, optional)
+- "minor_page_faults": Number of minor faults (json-int, optional)
+- "free_mem": Total amount of free and unused memory in
+ bytes (json-int, optional)
+- "total_mem": Total amount of available memory in bytes (json-int, optional)
+
+Example:
+
+-> { "execute": "query-balloon" }
+<- {
+ "return":{
+ "actual":1073741824,
+ "mem_swapped_in":0,
+ "mem_swapped_out":0,
+ "major_page_faults":142,
+ "minor_page_faults":239245,
+ "free_mem":1014185984,
+ "total_mem":1044668416
+ }
+ }
+
+EQMP
+
+STEXI
@item info qtree
show device tree
@item info qdm
commit 33572ece26744889b14b7d72ac81870d076725ac
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Mon May 31 14:43:30 2010 -0300
monitor: Reorder info documentation
Push the doc fragments for the info command to the end of
qemu-monitor.hx. This helps to establish a proper layout in the upcoming
QMP documentation.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index f4f88df..b8c765b 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -38,96 +38,6 @@ Commit changes to the disk images (if -snapshot is used) or backing files.
ETEXI
{
- .name = "info",
- .args_type = "item:s?",
- .params = "[subcommand]",
- .help = "show various information about the system state",
- .user_print = monitor_user_noop,
- .mhandler.cmd_new = do_info,
- },
-
-STEXI
- at item info @var{subcommand}
- at findex info
-Show various information about the system state.
-
- at table @option
- at item info version
-show the version of QEMU
- at item info commands
-list QMP available commands
- at item info network
-show the various VLANs and the associated devices
- at item info chardev
-show the character devices
- at item info block
-show the block devices
- at item info blockstats
-show block device statistics
- at item info registers
-show the cpu registers
- at item info cpus
-show infos for each CPU
- at item info history
-show the command line history
- at item info irq
-show the interrupts statistics (if available)
- at item info pic
-show i8259 (PIC) state
- at item info pci
-show emulated PCI device info
- at item info tlb
-show virtual to physical memory mappings (i386 only)
- at item info mem
-show the active virtual memory mappings (i386 only)
- at item info hpet
-show state of HPET (i386 only)
- at item info jit
-show dynamic compiler info
- at item info kvm
-show KVM information
- at item info numa
-show NUMA information
- at item info usb
-show USB devices plugged on the virtual USB hub
- at item info usbhost
-show all USB host devices
- at item info profile
-show profiling information
- at item info capture
-show information about active capturing
- at item info snapshots
-show list of VM snapshots
- at item info status
-show the current VM status (running|paused)
- at item info pcmcia
-show guest PCMCIA status
- at item info mice
-show which guest mouse is receiving events
- at item info vnc
-show the vnc server status
- at item info name
-show the current VM name
- at item info uuid
-show the current VM UUID
- at item info cpustats
-show CPU statistics
- at item info usernet
-show user network stack connection states
- at item info migrate
-show migration status
- at item info balloon
-show balloon information
- at item info qtree
-show device tree
- at item info qdm
-show qdev device model list
- at item info roms
-show roms
- at end table
-ETEXI
-
- {
.name = "q|quit",
.args_type = "",
.params = "",
@@ -1190,6 +1100,102 @@ STEXI
Enable the specified QMP capabilities
ETEXI
+
+HXCOMM Keep the 'info' command at the end!
+HXCOMM This is required for the QMP documentation layout.
+
+ {
+ .name = "info",
+ .args_type = "item:s?",
+ .params = "[subcommand]",
+ .help = "show various information about the system state",
+ .user_print = monitor_user_noop,
+ .mhandler.cmd_new = do_info,
+ },
+
+STEXI
+ at item info @var{subcommand}
+ at findex info
+Show various information about the system state.
+
+ at table @option
+ at item info version
+show the version of QEMU
+ at item info commands
+list QMP available commands
+ at item info network
+show the various VLANs and the associated devices
+ at item info chardev
+show the character devices
+ at item info block
+show the block devices
+ at item info blockstats
+show block device statistics
+ at item info registers
+show the cpu registers
+ at item info cpus
+show infos for each CPU
+ at item info history
+show the command line history
+ at item info irq
+show the interrupts statistics (if available)
+ at item info pic
+show i8259 (PIC) state
+ at item info pci
+show emulated PCI device info
+ at item info tlb
+show virtual to physical memory mappings (i386 only)
+ at item info mem
+show the active virtual memory mappings (i386 only)
+ at item info hpet
+show state of HPET (i386 only)
+ at item info jit
+show dynamic compiler info
+ at item info kvm
+show KVM information
+ at item info numa
+show NUMA information
+ at item info usb
+show USB devices plugged on the virtual USB hub
+ at item info usbhost
+show all USB host devices
+ at item info profile
+show profiling information
+ at item info capture
+show information about active capturing
+ at item info snapshots
+show list of VM snapshots
+ at item info status
+show the current VM status (running|paused)
+ at item info pcmcia
+show guest PCMCIA status
+ at item info mice
+show which guest mouse is receiving events
+ at item info vnc
+show the vnc server status
+ at item info name
+show the current VM name
+ at item info uuid
+show the current VM UUID
+ at item info cpustats
+show CPU statistics
+ at item info usernet
+show user network stack connection states
+ at item info migrate
+show migration status
+ at item info balloon
+show balloon information
+ at item info qtree
+show device tree
+ at item info qdm
+show qdev device model list
+ at item info roms
+show roms
+ at end table
+ETEXI
+
+HXCOMM DO NOT add new commands after 'info', move your addition before it!
+
STEXI
@end table
ETEXI
commit 38141097142199a65db142b974c45b3a9c0c809c
Merge: 1d4b638... e075e78...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date: Tue Jun 1 13:34:20 2010 -0500
Merge remote branch 'mst/for_anthony' into HEAD
commit 1d4b638ad1fc273a19d93c7d4725fecdd7e5182a
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Tue May 25 18:25:20 2010 +0200
vnc: move size-changed check into the vnc_desktop_resize function.
This make sure we send a desktop resize message only in case we actually
have to, using the new variables which track the clients desktop size.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/vnc.c b/vnc.c
index 5fc7012..30db8b1 100644
--- a/vnc.c
+++ b/vnc.c
@@ -529,6 +529,10 @@ static void vnc_desktop_resize(VncState *vs)
if (vs->csock == -1 || !vnc_has_feature(vs, VNC_FEATURE_RESIZE)) {
return;
}
+ if (vs->client_width == ds_get_width(ds) &&
+ vs->client_height == ds_get_height(ds)) {
+ return;
+ }
vs->client_width = ds_get_width(ds);
vs->client_height = ds_get_height(ds);
vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
@@ -541,7 +545,6 @@ static void vnc_desktop_resize(VncState *vs)
static void vnc_dpy_resize(DisplayState *ds)
{
- int size_changed;
VncDisplay *vd = ds->opaque;
VncState *vs;
@@ -559,16 +562,12 @@ static void vnc_dpy_resize(DisplayState *ds)
vd->guest.ds = qemu_mallocz(sizeof(*vd->guest.ds));
if (ds_get_bytes_per_pixel(ds) != vd->guest.ds->pf.bytes_per_pixel)
console_color_init(ds);
- size_changed = ds_get_width(ds) != vd->guest.ds->width ||
- ds_get_height(ds) != vd->guest.ds->height;
*(vd->guest.ds) = *(ds->surface);
memset(vd->guest.dirty, 0xFF, sizeof(vd->guest.dirty));
QTAILQ_FOREACH(vs, &vd->clients, next) {
vnc_colordepth(vs);
- if (size_changed) {
- vnc_desktop_resize(vs);
- }
+ vnc_desktop_resize(vs);
if (vs->vd->cursor) {
vnc_cursor_define(vs);
}
commit 847ce6a185f9ccbc089ef24a6c402b8c99113341
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Tue May 25 18:25:19 2010 +0200
vnc: don't send invalid screen updates.
Don't send updates for screen areas which are outside the clients
desktop. May happed with vnc clients which don't support the desktop
resize message.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/vnc.c b/vnc.c
index c8fe659..5fc7012 100644
--- a/vnc.c
+++ b/vnc.c
@@ -851,6 +851,7 @@ static int vnc_update_client(VncState *vs, int has_dirty)
int y;
int n_rectangles;
int saved_offset;
+ int width, height;
int n;
if (vs->output.offset && !vs->audio_cap && !vs->force_update)
@@ -872,10 +873,13 @@ static int vnc_update_client(VncState *vs, int has_dirty)
saved_offset = vs->output.offset;
vnc_write_u16(vs, 0);
- for (y = 0; y < vd->server->height; y++) {
+ width = MIN(vd->server->width, vs->client_width);
+ height = MIN(vd->server->height, vs->client_height);
+
+ for (y = 0; y < height; y++) {
int x;
int last_x = -1;
- for (x = 0; x < vd->server->width / 16; x++) {
+ for (x = 0; x < width / 16; x++) {
if (vnc_get_bit(vs->dirty[y], x)) {
if (last_x == -1) {
last_x = x;
commit 5862d195f90cb63c53b9dc3f54e10f8b9372bcf6
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Tue May 25 18:25:18 2010 +0200
vnc: keep track of client desktop size
Add two new variables to keep track of the vnc clients desktop size.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/vnc.c b/vnc.c
index a3a7840..c8fe659 100644
--- a/vnc.c
+++ b/vnc.c
@@ -529,10 +529,12 @@ static void vnc_desktop_resize(VncState *vs)
if (vs->csock == -1 || !vnc_has_feature(vs, VNC_FEATURE_RESIZE)) {
return;
}
+ vs->client_width = ds_get_width(ds);
+ vs->client_height = ds_get_height(ds);
vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
vnc_write_u8(vs, 0);
vnc_write_u16(vs, 1); /* number of rects */
- vnc_framebuffer_update(vs, 0, 0, ds_get_width(ds), ds_get_height(ds),
+ vnc_framebuffer_update(vs, 0, 0, vs->client_width, vs->client_height,
VNC_ENCODING_DESKTOPRESIZE);
vnc_flush(vs);
}
@@ -1975,8 +1977,10 @@ static int protocol_client_init(VncState *vs, uint8_t *data, size_t len)
char buf[1024];
int size;
- vnc_write_u16(vs, ds_get_width(vs->ds));
- vnc_write_u16(vs, ds_get_height(vs->ds));
+ vs->client_width = ds_get_width(vs->ds);
+ vs->client_height = ds_get_height(vs->ds);
+ vnc_write_u16(vs, vs->client_width);
+ vnc_write_u16(vs, vs->client_height);
pixel_format_message(vs);
diff --git a/vnc.h b/vnc.h
index 51595e6..7b64cf7 100644
--- a/vnc.h
+++ b/vnc.h
@@ -134,6 +134,8 @@ struct VncState
int absolute;
int last_x;
int last_y;
+ int client_width;
+ int client_height;
uint32_t vnc_encoding;
commit 6356e472512c55a5dc3aaf12ce12a6eb916dd045
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Tue May 25 18:25:17 2010 +0200
vnc: send desktopresize event as reply to set encodings
In case the desktop did resize while the vnc connection setup was still
in progress the client isn't informed about it. Send a desktop resize
event as soon as the client told us it can handle deskop resize via set
encodings message to make sure the client us up to date.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/vnc.c b/vnc.c
index 4fb13ba..a3a7840 100644
--- a/vnc.c
+++ b/vnc.c
@@ -1726,6 +1726,7 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
break;
}
}
+ vnc_desktop_resize(vs);
check_pointer_type_change(&vs->mouse_mode_notifier);
}
commit 621aaeb9991933a367e3964ecfc88a8f96af1f6a
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Tue May 25 18:25:16 2010 +0200
vnc: factor out vnc_desktop_resize()
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/vnc.c b/vnc.c
index 046bd38..4fb13ba 100644
--- a/vnc.c
+++ b/vnc.c
@@ -522,6 +522,21 @@ void buffer_append(Buffer *buffer, const void *data, size_t len)
buffer->offset += len;
}
+static void vnc_desktop_resize(VncState *vs)
+{
+ DisplayState *ds = vs->ds;
+
+ if (vs->csock == -1 || !vnc_has_feature(vs, VNC_FEATURE_RESIZE)) {
+ return;
+ }
+ vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
+ vnc_write_u8(vs, 0);
+ vnc_write_u16(vs, 1); /* number of rects */
+ vnc_framebuffer_update(vs, 0, 0, ds_get_width(ds), ds_get_height(ds),
+ VNC_ENCODING_DESKTOPRESIZE);
+ vnc_flush(vs);
+}
+
static void vnc_dpy_resize(DisplayState *ds)
{
int size_changed;
@@ -550,14 +565,7 @@ static void vnc_dpy_resize(DisplayState *ds)
QTAILQ_FOREACH(vs, &vd->clients, next) {
vnc_colordepth(vs);
if (size_changed) {
- if (vs->csock != -1 && vnc_has_feature(vs, VNC_FEATURE_RESIZE)) {
- vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
- vnc_write_u8(vs, 0);
- vnc_write_u16(vs, 1); /* number of rects */
- vnc_framebuffer_update(vs, 0, 0, ds_get_width(ds), ds_get_height(ds),
- VNC_ENCODING_DESKTOPRESIZE);
- vnc_flush(vs);
- }
+ vnc_desktop_resize(vs);
}
if (vs->vd->cursor) {
vnc_cursor_define(vs);
commit b627808462de92fd2635de16fa7d10b18d806802
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Fri May 21 11:59:14 2010 +0200
Add support for depth 15 to qemu_default_pixelformat()
Makes qemu_default_pixelformat(15) return pixelformat filled for 15 bit
color depth (16 bpp, 5 bits for red,green,blue each, 1 bit unused).
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/console.c b/console.c
index 4c42b28..698bc10 100644
--- a/console.c
+++ b/console.c
@@ -1621,6 +1621,22 @@ PixelFormat qemu_default_pixelformat(int bpp)
pf.depth = bpp == 32 ? 24 : bpp;
switch (bpp) {
+ case 15:
+ pf.bits_per_pixel = 16;
+ pf.bytes_per_pixel = 2;
+ pf.rmask = 0x00007c00;
+ pf.gmask = 0x000003E0;
+ pf.bmask = 0x0000001F;
+ pf.rmax = 31;
+ pf.gmax = 31;
+ pf.bmax = 31;
+ pf.rshift = 10;
+ pf.gshift = 5;
+ pf.bshift = 0;
+ pf.rbits = 5;
+ pf.gbits = 5;
+ pf.bbits = 5;
+ break;
case 16:
pf.rmask = 0x0000F800;
pf.gmask = 0x000007E0;
commit 26572b8a0e90ee0c77587173a78fa293a1d2beb6
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Thu May 20 15:23:06 2010 +0200
check for active_console before using it
Other vga_hw_* functions do the same.
Fixes a segmentation fault. Trigger: boot with -nodefaults,
then connect via vnc.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/console.c b/console.c
index 7070b1b..4c42b28 100644
--- a/console.c
+++ b/console.c
@@ -167,7 +167,7 @@ void vga_hw_update(void)
void vga_hw_invalidate(void)
{
- if (active_console->hw_invalidate)
+ if (active_console && active_console->hw_invalidate)
active_console->hw_invalidate(active_console->hw);
}
commit 4091da4b7cc251c7d422ccc5707900ed595b1ee0
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Thu May 20 09:18:52 2010 +0200
Add dependency of JSON unit tests on config-host.h
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/Makefile b/Makefile
index 9deb0f7..8fa593b 100644
--- a/Makefile
+++ b/Makefile
@@ -146,6 +146,8 @@ qemu-io$(EXESUF): qemu-io.o cmd.o qemu-tool.o qemu-error.o $(block-obj-y) $(qobj
qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
$(call quiet-command,sh $(SRC_PATH)/hxtool -h < $< > $@," GEN $@")
+check-qint.o check-qstring.o check-qdict.o check-qlist.o check-qfloat.o check-qjson.o: $(GENERATED_HEADERS)
+
check-qint: check-qint.o qint.o qemu-malloc.o
check-qstring: check-qstring.o qstring.o qemu-malloc.o
check-qdict: check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qemu-malloc.o qlist.o
commit 3fc250b4be58cac2e392d8d01949f9e8471c36f9
Author: Pierre Riteau <Pierre.Riteau at irisa.fr>
Date: Wed May 12 15:12:44 2010 +0200
migration: Fix calculation of bytes_transferred
When a page with all identical bytes is transferred, it is counted
as a full page (TARGET_PAGE_SIZE) although only one byte is actually
sent. Fix this by changing ram_save_block() to return the number of
bytes sent instead of a boolean value. This makes bandwidth
estimation, and consequently downtime estimation, more precise.
Signed-off-by: Pierre Riteau <Pierre.Riteau at irisa.fr>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/arch_init.c b/arch_init.c
index cfc03ea..8e849a8 100644
--- a/arch_init.c
+++ b/arch_init.c
@@ -108,7 +108,7 @@ static int ram_save_block(QEMUFile *f)
static ram_addr_t current_addr = 0;
ram_addr_t saved_addr = current_addr;
ram_addr_t addr = 0;
- int found = 0;
+ int bytes_sent = 0;
while (addr < last_ram_offset) {
if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) {
@@ -123,19 +123,20 @@ static int ram_save_block(QEMUFile *f)
if (is_dup_page(p, *p)) {
qemu_put_be64(f, current_addr | RAM_SAVE_FLAG_COMPRESS);
qemu_put_byte(f, *p);
+ bytes_sent = 1;
} else {
qemu_put_be64(f, current_addr | RAM_SAVE_FLAG_PAGE);
qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
+ bytes_sent = TARGET_PAGE_SIZE;
}
- found = 1;
break;
}
addr += TARGET_PAGE_SIZE;
current_addr = (saved_addr + addr) % last_ram_offset;
}
- return found;
+ return bytes_sent;
}
static uint64_t bytes_transferred;
@@ -206,11 +207,11 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
bwidth = qemu_get_clock_ns(rt_clock);
while (!qemu_file_rate_limit(f)) {
- int ret;
+ int bytes_sent;
- ret = ram_save_block(f);
- bytes_transferred += ret * TARGET_PAGE_SIZE;
- if (ret == 0) { /* no more blocks */
+ bytes_sent = ram_save_block(f);
+ bytes_transferred += bytes_sent;
+ if (bytes_sent == 0) { /* no more blocks */
break;
}
}
@@ -226,9 +227,11 @@ int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
/* try transferring iterative blocks of memory */
if (stage == 3) {
+ int bytes_sent;
+
/* flush all remaining blocks regardless of rate limiting */
- while (ram_save_block(f) != 0) {
- bytes_transferred += TARGET_PAGE_SIZE;
+ while ((bytes_sent = ram_save_block(f)) != 0) {
+ bytes_transferred += bytes_sent;
}
cpu_physical_memory_set_dirty_tracking(0);
}
commit a132a679c33ae2f8f6935f92c2a8043015cd917c
Author: Alon Levy <alevy at redhat.com>
Date: Wed May 19 15:01:38 2010 +0530
virtio-serial-bus: fix ports_map allocation on init
Fix for too small allocation to ports_map
Signed-off-by: Alon Levy <alevy 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 3ce95e8..7f9d28f 100644
--- a/hw/virtio-serial-bus.c
+++ b/hw/virtio-serial-bus.c
@@ -774,7 +774,8 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports)
}
vser->config.max_nr_ports = max_nr_ports;
- vser->ports_map = qemu_mallocz((max_nr_ports + 31) / 32);
+ vser->ports_map = qemu_mallocz(((max_nr_ports + 31) / 32)
+ * sizeof(vser->ports_map[0]));
/*
* Reserve location 0 for a console port for backward compat
* (old kernel, new qemu)
commit eafaf1e5ab30346d6e9ac676ec6b7a3eca4ccce3
Author: Andre Przywara <andre.przywara at amd.com>
Date: Fri May 21 09:50:51 2010 +0200
resent: x86/cpuid: Add kvm32 CPU model
Create a kvm32 CPU model that describes a least common denominator
for KVM capable guest CPUs. Useful for migration purposes.
Signed-off-by: Andre Przywara <andre.przywara at amd.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index 56938e2..7a11215 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -364,6 +364,20 @@ static x86_def_t builtin_x86_defs[] = {
.model_id = "QEMU Virtual CPU version " QEMU_VERSION,
},
{
+ .name = "kvm32",
+ .level = 5,
+ .family = 15,
+ .model = 6,
+ .stepping = 1,
+ .features = PPRO_FEATURES |
+ CPUID_MTRR | CPUID_CLFLUSH | CPUID_MCA | CPUID_PSE36,
+ .ext_features = CPUID_EXT_SSE3,
+ .ext2_features = PPRO_FEATURES & EXT2_FEATURE_MASK,
+ .ext3_features = 0,
+ .xlevel = 0x80000008,
+ .model_id = "Common 32-bit KVM processor"
+ },
+ {
.name = "coreduo",
.level = 10,
.family = 6,
commit aa7d73fd3db9262f426017a1eeef0d681373db5d
Author: Corentin Chary <corentincj at iksaif.net>
Date: Wed May 19 09:24:12 2010 +0200
vnc: tight: add palette encoding
Add palette tight encoding. Palette encoding will try to count the number
of colors for a given rectangle, and if this number is low enough
(< 256) it will send the palette + the rectangle with indexed colors.
Signed-off-by: Corentin Chary <corentincj at iksaif.net>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/vnc-encoding-tight.c b/vnc-encoding-tight.c
index 2c9dab6..50be44e 100644
--- a/vnc-encoding-tight.c
+++ b/vnc-encoding-tight.c
@@ -28,6 +28,8 @@
#include <stdbool.h>
+#include "qdict.h"
+#include "qint.h"
#include "vnc.h"
#include "vnc-encoding-tight.h"
@@ -56,6 +58,285 @@ static const struct {
};
/*
+ * Code to determine how many different colors used in rectangle.
+ */
+
+static void tight_palette_rgb2buf(uint32_t rgb, int bpp, uint8_t buf[6])
+{
+ memset(buf, 0, 6);
+
+ if (bpp == 32) {
+ buf[0] = ((rgb >> 24) & 0xFF);
+ buf[1] = ((rgb >> 16) & 0xFF);
+ buf[2] = ((rgb >> 8) & 0xFF);
+ buf[3] = ((rgb >> 0) & 0xFF);
+ buf[4] = ((buf[0] & 1) == 0) << 3 | ((buf[1] & 1) == 0) << 2;
+ buf[4]|= ((buf[2] & 1) == 0) << 1 | ((buf[3] & 1) == 0) << 0;
+ buf[0] |= 1;
+ buf[1] |= 1;
+ buf[2] |= 1;
+ buf[3] |= 1;
+ }
+ if (bpp == 16) {
+ buf[0] = ((rgb >> 8) & 0xFF);
+ buf[1] = ((rgb >> 0) & 0xFF);
+ buf[2] = ((buf[0] & 1) == 0) << 1 | ((buf[1] & 1) == 0) << 0;
+ buf[0] |= 1;
+ buf[1] |= 1;
+ }
+}
+
+static uint32_t tight_palette_buf2rgb(int bpp, const uint8_t *buf)
+{
+ uint32_t rgb = 0;
+
+ if (bpp == 32) {
+ rgb |= ((buf[0] & ~1) | !((buf[4] >> 3) & 1)) << 24;
+ rgb |= ((buf[1] & ~1) | !((buf[4] >> 2) & 1)) << 16;
+ rgb |= ((buf[2] & ~1) | !((buf[4] >> 1) & 1)) << 8;
+ rgb |= ((buf[3] & ~1) | !((buf[4] >> 0) & 1)) << 0;
+ }
+ if (bpp == 16) {
+ rgb |= ((buf[0] & ~1) | !((buf[2] >> 1) & 1)) << 8;
+ rgb |= ((buf[1] & ~1) | !((buf[2] >> 0) & 1)) << 0;
+ }
+ return rgb;
+}
+
+
+static int tight_palette_insert(QDict *palette, uint32_t rgb, int bpp, int max)
+{
+ uint8_t key[6];
+ int idx = qdict_size(palette);
+ bool present;
+
+ tight_palette_rgb2buf(rgb, bpp, key);
+ present = qdict_haskey(palette, (char *)key);
+ if (idx >= max && !present) {
+ return 0;
+ }
+ if (!present) {
+ qdict_put(palette, (char *)key, qint_from_int(idx));
+ }
+ return qdict_size(palette);
+}
+
+#define DEFINE_FILL_PALETTE_FUNCTION(bpp) \
+ \
+ static int \
+ tight_fill_palette##bpp(VncState *vs, int x, int y, \
+ int max, size_t count, \
+ uint32_t *bg, uint32_t *fg, \
+ struct QDict **palette) { \
+ uint##bpp##_t *data; \
+ uint##bpp##_t c0, c1, ci; \
+ int i, n0, n1; \
+ \
+ data = (uint##bpp##_t *)vs->tight.buffer; \
+ \
+ c0 = data[0]; \
+ i = 1; \
+ while (i < count && data[i] == c0) \
+ i++; \
+ if (i >= count) { \
+ *bg = *fg = c0; \
+ return 1; \
+ } \
+ \
+ if (max < 2) { \
+ return 0; \
+ } \
+ \
+ n0 = i; \
+ c1 = data[i]; \
+ n1 = 0; \
+ for (i++; i < count; i++) { \
+ ci = data[i]; \
+ if (ci == c0) { \
+ n0++; \
+ } else if (ci == c1) { \
+ n1++; \
+ } else \
+ break; \
+ } \
+ if (i >= count) { \
+ if (n0 > n1) { \
+ *bg = (uint32_t)c0; \
+ *fg = (uint32_t)c1; \
+ } else { \
+ *bg = (uint32_t)c1; \
+ *fg = (uint32_t)c0; \
+ } \
+ return 2; \
+ } \
+ \
+ if (max == 2) { \
+ return 0; \
+ } \
+ \
+ *palette = qdict_new(); \
+ tight_palette_insert(*palette, c0, bpp, max); \
+ tight_palette_insert(*palette, c1, bpp, max); \
+ \
+ for (i++; i < count; i++) { \
+ if (data[i] == ci) { \
+ continue; \
+ } else { \
+ if (!tight_palette_insert(*palette, (uint32_t)ci, \
+ bpp, max)) { \
+ return 0; \
+ } \
+ ci = data[i]; \
+ } \
+ } \
+ \
+ return qdict_size(*palette); \
+ }
+
+DEFINE_FILL_PALETTE_FUNCTION(8)
+DEFINE_FILL_PALETTE_FUNCTION(16)
+DEFINE_FILL_PALETTE_FUNCTION(32)
+
+static int tight_fill_palette(VncState *vs, int x, int y,
+ size_t count, uint32_t *bg, uint32_t *fg,
+ struct QDict **palette)
+{
+ int max;
+
+ max = count / tight_conf[vs->tight_compression].idx_max_colors_divisor;
+ if (max < 2 &&
+ count >= tight_conf[vs->tight_compression].mono_min_rect_size) {
+ max = 2;
+ }
+ if (max >= 256) {
+ max = 256;
+ }
+
+ switch(vs->clientds.pf.bytes_per_pixel) {
+ case 4:
+ return tight_fill_palette32(vs, x, y, max, count, bg, fg, palette);
+ case 2:
+ return tight_fill_palette16(vs, x, y, max, count, bg, fg, palette);
+ default:
+ max = 2;
+ return tight_fill_palette8(vs, x, y, max, count, bg, fg, palette);
+ }
+ return 0;
+}
+
+/* Callback to dump a palette with qdict_iter
+static void print_palette(const char *key, QObject *obj, void *opaque)
+{
+ uint8_t idx = qint_get_int(qobject_to_qint(obj));
+ uint32_t rgb = tight_palette_buf2rgb(32, (uint8_t *)key);
+
+ fprintf(stderr, "%.2x ", (unsigned char)*key);
+ while (*key++)
+ fprintf(stderr, "%.2x ", (unsigned char)*key);
+
+ fprintf(stderr, ": idx: %x rgb: %x\n", idx, rgb);
+}
+*/
+
+/*
+ * Converting truecolor samples into palette indices.
+ */
+#define DEFINE_IDX_ENCODE_FUNCTION(bpp) \
+ \
+ static void \
+ tight_encode_indexed_rect##bpp(uint8_t *buf, int count, \
+ struct QDict *palette) { \
+ uint##bpp##_t *src; \
+ uint##bpp##_t rgb; \
+ uint8_t key[6]; \
+ int rep = 0; \
+ uint8_t idx; \
+ \
+ src = (uint##bpp##_t *) buf; \
+ \
+ count -= 1; \
+ while (count--) { \
+ rgb = *src++; \
+ rep = 0; \
+ while (count && *src == rgb) { \
+ rep++, src++, count--; \
+ } \
+ tight_palette_rgb2buf(rgb, bpp, key); \
+ if (!qdict_haskey(palette, (char *)key)) { \
+ /* \
+ * Should never happen, but don't break everything \
+ * if it does, use the first color instead \
+ */ \
+ idx = 0; \
+ } else { \
+ idx = qdict_get_int(palette, (char *)key); \
+ } \
+ while (rep >= 0) { \
+ *buf++ = idx; \
+ rep--; \
+ } \
+ } \
+ }
+
+DEFINE_IDX_ENCODE_FUNCTION(16)
+DEFINE_IDX_ENCODE_FUNCTION(32)
+
+#define DEFINE_MONO_ENCODE_FUNCTION(bpp) \
+ \
+ static void \
+ tight_encode_mono_rect##bpp(uint8_t *buf, int w, int h, \
+ uint##bpp##_t bg, uint##bpp##_t fg) { \
+ uint##bpp##_t *ptr; \
+ unsigned int value, mask; \
+ int aligned_width; \
+ int x, y, bg_bits; \
+ \
+ ptr = (uint##bpp##_t *) buf; \
+ aligned_width = w - w % 8; \
+ \
+ for (y = 0; y < h; y++) { \
+ for (x = 0; x < aligned_width; x += 8) { \
+ for (bg_bits = 0; bg_bits < 8; bg_bits++) { \
+ if (*ptr++ != bg) { \
+ break; \
+ } \
+ } \
+ if (bg_bits == 8) { \
+ *buf++ = 0; \
+ continue; \
+ } \
+ mask = 0x80 >> bg_bits; \
+ value = mask; \
+ for (bg_bits++; bg_bits < 8; bg_bits++) { \
+ mask >>= 1; \
+ if (*ptr++ != bg) { \
+ value |= mask; \
+ } \
+ } \
+ *buf++ = (uint8_t)value; \
+ } \
+ \
+ mask = 0x80; \
+ value = 0; \
+ if (x >= w) { \
+ continue; \
+ } \
+ \
+ for (; x < w; x++) { \
+ if (*ptr++ != bg) { \
+ value |= mask; \
+ } \
+ mask >>= 1; \
+ } \
+ *buf++ = (uint8_t)value; \
+ } \
+ }
+
+DEFINE_MONO_ENCODE_FUNCTION(8)
+DEFINE_MONO_ENCODE_FUNCTION(16)
+DEFINE_MONO_ENCODE_FUNCTION(32)
+
+/*
* Check if a rectangle is all of the same color. If needSameColor is
* set to non-zero, then also check that its color equals to the
* *colorPtr value. The result is 1 if the test is successfull, and in
@@ -288,14 +569,12 @@ static int tight_compress_data(VncState *vs, int stream_id, size_t bytes,
/*
* Subencoding implementations.
*/
-static void tight_pack24(VncState *vs, size_t count)
+static void tight_pack24(VncState *vs, uint8_t *buf, size_t count, size_t *ret)
{
- unsigned char *buf;
uint32_t *buf32;
uint32_t pix;
int rshift, gshift, bshift;
- buf = vs->tight.buffer;
buf32 = (uint32_t *)buf;
if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) ==
@@ -309,7 +588,9 @@ static void tight_pack24(VncState *vs, size_t count)
bshift = 24 - vs->clientds.pf.bshift;
}
- vs->tight.offset = count * 3;
+ if (ret) {
+ *ret = count * 3;
+ }
while (count--) {
pix = *buf32++;
@@ -327,7 +608,7 @@ static int send_full_color_rect(VncState *vs, int w, int h)
vnc_write_u8(vs, stream << 4); /* no flushing, no filter */
if (vs->tight_pixel24) {
- tight_pack24(vs, w * h);
+ tight_pack24(vs, vs->tight.buffer, w * h, &vs->tight.offset);
bytes = 3;
} else {
bytes = vs->clientds.pf.bytes_per_pixel;
@@ -347,7 +628,7 @@ static int send_solid_rect(VncState *vs)
vnc_write_u8(vs, VNC_TIGHT_FILL << 4); /* no flushing, no filter */
if (vs->tight_pixel24) {
- tight_pack24(vs, 1);
+ tight_pack24(vs, vs->tight.buffer, 1, &vs->tight.offset);
bytes = 3;
} else {
bytes = vs->clientds.pf.bytes_per_pixel;
@@ -357,6 +638,126 @@ static int send_solid_rect(VncState *vs)
return 1;
}
+static int send_mono_rect(VncState *vs, int w, int h, uint32_t bg, uint32_t fg)
+{
+ size_t bytes;
+ int stream = 1;
+ int level = tight_conf[vs->tight_compression].mono_zlib_level;
+
+ bytes = ((w + 7) / 8) * h;
+
+ vnc_write_u8(vs, (stream | VNC_TIGHT_EXPLICIT_FILTER) << 4);
+ vnc_write_u8(vs, VNC_TIGHT_FILTER_PALETTE);
+ vnc_write_u8(vs, 1);
+
+ switch(vs->clientds.pf.bytes_per_pixel) {
+ case 4:
+ {
+ uint32_t buf[2] = {bg, fg};
+ size_t ret = sizeof (buf);
+
+ if (vs->tight_pixel24) {
+ tight_pack24(vs, (unsigned char*)buf, 2, &ret);
+ }
+ vnc_write(vs, buf, ret);
+
+ tight_encode_mono_rect32(vs->tight.buffer, w, h, bg, fg);
+ break;
+ }
+ case 2:
+ vnc_write(vs, &bg, 2);
+ vnc_write(vs, &fg, 2);
+ tight_encode_mono_rect16(vs->tight.buffer, w, h, bg, fg);
+ break;
+ default:
+ vnc_write_u8(vs, bg);
+ vnc_write_u8(vs, fg);
+ tight_encode_mono_rect8(vs->tight.buffer, w, h, bg, fg);
+ break;
+ }
+ vs->tight.offset = bytes;
+
+ bytes = tight_compress_data(vs, stream, bytes, level, Z_DEFAULT_STRATEGY);
+ return (bytes >= 0);
+}
+
+struct palette_cb_priv {
+ VncState *vs;
+ uint8_t *header;
+};
+
+static void write_palette(const char *key, QObject *obj, void *opaque)
+{
+ struct palette_cb_priv *priv = opaque;
+ VncState *vs = priv->vs;
+ uint32_t bytes = vs->clientds.pf.bytes_per_pixel;
+ uint8_t idx = qint_get_int(qobject_to_qint(obj));
+
+ if (bytes == 4) {
+ uint32_t color = tight_palette_buf2rgb(32, (uint8_t *)key);
+
+ ((uint32_t*)priv->header)[idx] = color;
+ } else {
+ uint16_t color = tight_palette_buf2rgb(16, (uint8_t *)key);
+
+ ((uint16_t*)priv->header)[idx] = color;
+ }
+}
+
+static int send_palette_rect(VncState *vs, int w, int h, struct QDict *palette)
+{
+ int stream = 2;
+ int level = tight_conf[vs->tight_compression].idx_zlib_level;
+ int colors;
+ size_t bytes;
+
+ colors = qdict_size(palette);
+
+ vnc_write_u8(vs, (stream | VNC_TIGHT_EXPLICIT_FILTER) << 4);
+ vnc_write_u8(vs, VNC_TIGHT_FILTER_PALETTE);
+ vnc_write_u8(vs, colors - 1);
+
+ switch(vs->clientds.pf.bytes_per_pixel) {
+ case 4:
+ {
+ size_t old_offset, offset;
+ uint32_t header[qdict_size(palette)];
+ struct palette_cb_priv priv = { vs, (uint8_t *)header };
+
+ old_offset = vs->output.offset;
+ qdict_iter(palette, write_palette, &priv);
+ vnc_write(vs, header, sizeof(header));
+
+ if (vs->tight_pixel24) {
+ tight_pack24(vs, vs->output.buffer + old_offset, colors, &offset);
+ vs->output.offset = old_offset + offset;
+ }
+
+ tight_encode_indexed_rect32(vs->tight.buffer, w * h, palette);
+ break;
+ }
+ case 2:
+ {
+ uint16_t header[qdict_size(palette)];
+ struct palette_cb_priv priv = { vs, (uint8_t *)header };
+
+ qdict_iter(palette, write_palette, &priv);
+ vnc_write(vs, header, sizeof(header));
+ tight_encode_indexed_rect16(vs->tight.buffer, w * h, palette);
+ break;
+ }
+ default:
+ return -1; /* No palette for 8bits colors */
+ break;
+ }
+ bytes = w * h;
+ vs->tight.offset = bytes;
+
+ bytes = tight_compress_data(vs, stream, bytes,
+ level, Z_DEFAULT_STRATEGY);
+ return (bytes >= 0);
+}
+
static void vnc_tight_start(VncState *vs)
{
buffer_reset(&vs->tight);
@@ -375,18 +776,30 @@ static void vnc_tight_stop(VncState *vs)
static int send_sub_rect(VncState *vs, int x, int y, int w, int h)
{
+ struct QDict *palette = NULL;
+ uint32_t bg = 0, fg = 0;
+ int colors;
+ int ret = 0;
+
vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_TIGHT);
- /*
- * Convert pixels and store them in vs->tight
- * We will probably rework that later, probably
- * when adding other sub-encodings
- */
vnc_tight_start(vs);
vnc_raw_send_framebuffer_update(vs, x, y, w, h);
vnc_tight_stop(vs);
- return send_full_color_rect(vs, w, h);
+ colors = tight_fill_palette(vs, x, y, w * h, &fg, &bg, &palette);
+
+ if (colors == 0) {
+ ret = send_full_color_rect(vs, w, h);
+ } else if (colors == 1) {
+ ret = send_solid_rect(vs);
+ } else if (colors == 2) {
+ ret = send_mono_rect(vs, w, h, bg, fg);
+ } else if (colors <= 256) {
+ ret = send_palette_rect(vs, w, h, palette);
+ }
+ QDECREF(palette);
+ return ret;
}
static int send_sub_rect_solid(VncState *vs, int x, int y, int w, int h)
commit b4bea3f2b848a0815a28e316c14dc22919bc082b
Author: Corentin Chary <corentincj at iksaif.net>
Date: Wed May 19 09:24:11 2010 +0200
vnc: add support for tight fill encoding
Fill encoding detects rectangles using only one color and send only
one pixel value.
Signed-off-by: Corentin Chary <corentincj at iksaif.net>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/vnc-encoding-tight.c b/vnc-encoding-tight.c
index ce9cc49..2c9dab6 100644
--- a/vnc-encoding-tight.c
+++ b/vnc-encoding-tight.c
@@ -55,6 +55,139 @@ static const struct {
{ 65536, 2048, 32, 8192, 9, 9, 9, 6, 200, 500, 96, 80, 200, 500 }
};
+/*
+ * Check if a rectangle is all of the same color. If needSameColor is
+ * set to non-zero, then also check that its color equals to the
+ * *colorPtr value. The result is 1 if the test is successfull, and in
+ * that case new color will be stored in *colorPtr.
+ */
+
+#define DEFINE_CHECK_SOLID_FUNCTION(bpp) \
+ \
+ static bool \
+ check_solid_tile##bpp(VncState *vs, int x, int y, int w, int h, \
+ uint32_t* color, bool samecolor) \
+ { \
+ VncDisplay *vd = vs->vd; \
+ uint##bpp##_t *fbptr; \
+ uint##bpp##_t c; \
+ int dx, dy; \
+ \
+ fbptr = (uint##bpp##_t *) \
+ (vd->server->data + y * ds_get_linesize(vs->ds) + \
+ x * ds_get_bytes_per_pixel(vs->ds)); \
+ \
+ c = *fbptr; \
+ if (samecolor && (uint32_t)c != *color) { \
+ return false; \
+ } \
+ \
+ for (dy = 0; dy < h; dy++) { \
+ for (dx = 0; dx < w; dx++) { \
+ if (c != fbptr[dx]) { \
+ return false; \
+ } \
+ } \
+ fbptr = (uint##bpp##_t *) \
+ ((uint8_t *)fbptr + ds_get_linesize(vs->ds)); \
+ } \
+ \
+ *color = (uint32_t)c; \
+ return true; \
+ }
+
+DEFINE_CHECK_SOLID_FUNCTION(32)
+DEFINE_CHECK_SOLID_FUNCTION(16)
+DEFINE_CHECK_SOLID_FUNCTION(8)
+
+static bool check_solid_tile(VncState *vs, int x, int y, int w, int h,
+ uint32_t* color, bool samecolor)
+{
+ VncDisplay *vd = vs->vd;
+
+ switch(vd->server->pf.bytes_per_pixel) {
+ case 4:
+ return check_solid_tile32(vs, x, y, w, h, color, samecolor);
+ case 2:
+ return check_solid_tile16(vs, x, y, w, h, color, samecolor);
+ default:
+ return check_solid_tile8(vs, x, y, w, h, color, samecolor);
+ }
+}
+
+static void find_best_solid_area(VncState *vs, int x, int y, int w, int h,
+ uint32_t color, int *w_ptr, int *h_ptr)
+{
+ int dx, dy, dw, dh;
+ int w_prev;
+ int w_best = 0, h_best = 0;
+
+ w_prev = w;
+
+ for (dy = y; dy < y + h; dy += VNC_TIGHT_MAX_SPLIT_TILE_SIZE) {
+
+ dh = MIN(VNC_TIGHT_MAX_SPLIT_TILE_SIZE, y + h - dy);
+ dw = MIN(VNC_TIGHT_MAX_SPLIT_TILE_SIZE, w_prev);
+
+ if (!check_solid_tile(vs, x, dy, dw, dh, &color, true)) {
+ break;
+ }
+
+ for (dx = x + dw; dx < x + w_prev;) {
+ dw = MIN(VNC_TIGHT_MAX_SPLIT_TILE_SIZE, x + w_prev - dx);
+
+ if (!check_solid_tile(vs, dx, dy, dw, dh, &color, true)) {
+ break;
+ }
+ dx += dw;
+ }
+
+ w_prev = dx - x;
+ if (w_prev * (dy + dh - y) > w_best * h_best) {
+ w_best = w_prev;
+ h_best = dy + dh - y;
+ }
+ }
+
+ *w_ptr = w_best;
+ *h_ptr = h_best;
+}
+
+static void extend_solid_area(VncState *vs, int x, int y, int w, int h,
+ uint32_t color, int *x_ptr, int *y_ptr,
+ int *w_ptr, int *h_ptr)
+{
+ int cx, cy;
+
+ /* Try to extend the area upwards. */
+ for ( cy = *y_ptr - 1;
+ cy >= y && check_solid_tile(vs, *x_ptr, cy, *w_ptr, 1, &color, true);
+ cy-- );
+ *h_ptr += *y_ptr - (cy + 1);
+ *y_ptr = cy + 1;
+
+ /* ... downwards. */
+ for ( cy = *y_ptr + *h_ptr;
+ cy < y + h &&
+ check_solid_tile(vs, *x_ptr, cy, *w_ptr, 1, &color, true);
+ cy++ );
+ *h_ptr += cy - (*y_ptr + *h_ptr);
+
+ /* ... to the left. */
+ for ( cx = *x_ptr - 1;
+ cx >= x && check_solid_tile(vs, cx, *y_ptr, 1, *h_ptr, &color, true);
+ cx-- );
+ *w_ptr += *x_ptr - (cx + 1);
+ *x_ptr = cx + 1;
+
+ /* ... to the right. */
+ for ( cx = *x_ptr + *w_ptr;
+ cx < x + w &&
+ check_solid_tile(vs, cx, *y_ptr, 1, *h_ptr, &color, true);
+ cx++ );
+ *w_ptr += cx - (*x_ptr + *w_ptr);
+}
+
static int tight_init_stream(VncState *vs, int stream_id,
int level, int strategy)
{
@@ -104,7 +237,7 @@ static void tight_send_compact_size(VncState *vs, size_t len)
buf[bytes++] = (len >> 14) & 0xFF;
}
}
- for(lpc = 0; lpc < bytes; lpc++) {
+ for (lpc = 0; lpc < bytes; lpc++) {
vnc_write_u8(vs, buf[lpc]);
}
}
@@ -207,6 +340,23 @@ static int send_full_color_rect(VncState *vs, int w, int h)
return (bytes >= 0);
}
+static int send_solid_rect(VncState *vs)
+{
+ size_t bytes;
+
+ vnc_write_u8(vs, VNC_TIGHT_FILL << 4); /* no flushing, no filter */
+
+ if (vs->tight_pixel24) {
+ tight_pack24(vs, 1);
+ bytes = 3;
+ } else {
+ bytes = vs->clientds.pf.bytes_per_pixel;
+ }
+
+ vnc_write(vs, vs->tight.buffer, bytes);
+ return 1;
+}
+
static void vnc_tight_start(VncState *vs)
{
buffer_reset(&vs->tight);
@@ -239,6 +389,17 @@ static int send_sub_rect(VncState *vs, int x, int y, int w, int h)
return send_full_color_rect(vs, w, h);
}
+static int send_sub_rect_solid(VncState *vs, int x, int y, int w, int h)
+{
+ vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_TIGHT);
+
+ vnc_tight_start(vs);
+ vnc_raw_send_framebuffer_update(vs, x, y, w, h);
+ vnc_tight_stop(vs);
+
+ return send_solid_rect(vs);
+}
+
static int send_rect_simple(VncState *vs, int x, int y, int w, int h)
{
int max_size, max_width;
@@ -268,9 +429,93 @@ static int send_rect_simple(VncState *vs, int x, int y, int w, int h)
return n;
}
+static int find_large_solid_color_rect(VncState *vs, int x, int y,
+ int w, int h, int max_rows)
+{
+ int dx, dy, dw, dh;
+ int n = 0;
+
+ /* Try to find large solid-color areas and send them separately. */
+
+ for (dy = y; dy < y + h; dy += VNC_TIGHT_MAX_SPLIT_TILE_SIZE) {
+
+ /* If a rectangle becomes too large, send its upper part now. */
+
+ if (dy - y >= max_rows) {
+ n += send_rect_simple(vs, x, y, w, max_rows);
+ y += max_rows;
+ h -= max_rows;
+ }
+
+ dh = MIN(VNC_TIGHT_MAX_SPLIT_TILE_SIZE, (y + h - dy));
+
+ for (dx = x; dx < x + w; dx += VNC_TIGHT_MAX_SPLIT_TILE_SIZE) {
+ uint32_t color_value;
+ int x_best, y_best, w_best, h_best;
+
+ dw = MIN(VNC_TIGHT_MAX_SPLIT_TILE_SIZE, (x + w - dx));
+
+ if (!check_solid_tile(vs, dx, dy, dw, dh, &color_value, false)) {
+ continue ;
+ }
+
+ /* Get dimensions of solid-color area. */
+
+ find_best_solid_area(vs, dx, dy, w - (dx - x), h - (dy - y),
+ color_value, &w_best, &h_best);
+
+ /* Make sure a solid rectangle is large enough
+ (or the whole rectangle is of the same color). */
+
+ if (w_best * h_best != w * h &&
+ w_best * h_best < VNC_TIGHT_MIN_SOLID_SUBRECT_SIZE) {
+ continue;
+ }
+
+ /* Try to extend solid rectangle to maximum size. */
+
+ x_best = dx; y_best = dy;
+ extend_solid_area(vs, x, y, w, h, color_value,
+ &x_best, &y_best, &w_best, &h_best);
+
+ /* Send rectangles at top and left to solid-color area. */
+
+ if (y_best != y) {
+ n += send_rect_simple(vs, x, y, w, y_best-y);
+ }
+ if (x_best != x) {
+ n += vnc_tight_send_framebuffer_update(vs, x, y_best,
+ x_best-x, h_best);
+ }
+
+ /* Send solid-color rectangle. */
+ n += send_sub_rect_solid(vs, x_best, y_best, w_best, h_best);
+
+ /* Send remaining rectangles (at right and bottom). */
+
+ if (x_best + w_best != x + w) {
+ n += vnc_tight_send_framebuffer_update(vs, x_best+w_best,
+ y_best,
+ w-(x_best-x)-w_best,
+ h_best);
+ }
+ if (y_best + h_best != y + h) {
+ n += vnc_tight_send_framebuffer_update(vs, x, y_best+h_best,
+ w, h-(y_best-y)-h_best);
+ }
+
+ /* Return after all recursive calls are done. */
+ return n;
+ }
+ }
+ return n + send_rect_simple(vs, x, y, w, h);
+}
+
int vnc_tight_send_framebuffer_update(VncState *vs, int x, int y,
int w, int h)
{
+ int max_rows;
+
if (vs->clientds.pf.bytes_per_pixel == 4 && vs->clientds.pf.rmax == 0xFF &&
vs->clientds.pf.bmax == 0xFF && vs->clientds.pf.gmax == 0xFF) {
vs->tight_pixel24 = true;
@@ -278,7 +523,15 @@ int vnc_tight_send_framebuffer_update(VncState *vs, int x, int y,
vs->tight_pixel24 = false;
}
- return send_rect_simple(vs, x, y, w, h);
+ if (w * h < VNC_TIGHT_MIN_SPLIT_RECT_SIZE)
+ return send_rect_simple(vs, x, y, w, h);
+
+ /* Calculate maximum number of rows in one non-solid rectangle. */
+
+ max_rows = tight_conf[vs->tight_compression].max_rect_size;
+ max_rows /= MIN(tight_conf[vs->tight_compression].max_rect_width, w);
+
+ return find_large_solid_color_rect(vs, x, y, w, h, max_rows);
}
void vnc_tight_clear(VncState *vs)
commit 380282b07dcc262f011aa665972dacba5d2178bc
Author: Corentin Chary <corentincj at iksaif.net>
Date: Wed May 19 09:24:10 2010 +0200
vnc: add basic tight support
Add support for tight encoding [1]. This patch only add support
for "basic" tight compression without any filter.
[1] http://tigervnc.org/cgi-bin/rfbproto#tight-encoding.
Signed-off-by: Corentin Chary <corentincj at iksaif.net>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/Makefile b/Makefile
index 7986bf6..9deb0f7 100644
--- a/Makefile
+++ b/Makefile
@@ -124,6 +124,8 @@ vnc-encoding-zlib.o: vnc.h
vnc-encoding-hextile.o: vnc.h
+vnc-encoding-tight.o: vnc.h vnc-encoding-tight.h
+
curses.o: curses.c keymaps.h curses_keys.h
bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS)
diff --git a/Makefile.objs b/Makefile.objs
index 1a942e5..9796dcb 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -105,6 +105,7 @@ common-obj-$(CONFIG_SDL) += sdl.o sdl_zoom.o x_keymap.o
common-obj-$(CONFIG_CURSES) += curses.o
common-obj-y += vnc.o acl.o d3des.o
common-obj-y += vnc-encoding-zlib.o vnc-encoding-hextile.o
+common-obj-y += vnc-encoding-tight.o
common-obj-y += iov.o
common-obj-$(CONFIG_VNC_TLS) += vnc-tls.o vnc-auth-vencrypt.o
common-obj-$(CONFIG_VNC_SASL) += vnc-auth-sasl.o
diff --git a/vnc-encoding-tight.c b/vnc-encoding-tight.c
new file mode 100644
index 0000000..ce9cc49
--- /dev/null
+++ b/vnc-encoding-tight.c
@@ -0,0 +1,295 @@
+/*
+ * QEMU VNC display driver: tight encoding
+ *
+ * From libvncserver/libvncserver/tight.c
+ * Copyright (C) 2000, 2001 Const Kaplinsky. All Rights Reserved.
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ * Copyright (C) 2010 Corentin Chary <corentin.chary at gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <stdbool.h>
+
+#include "vnc.h"
+#include "vnc-encoding-tight.h"
+
+/* Compression level stuff. The following array contains various
+ encoder parameters for each of 10 compression levels (0..9).
+ Last three parameters correspond to JPEG quality levels (0..9). */
+
+static const struct {
+ int max_rect_size, max_rect_width;
+ int mono_min_rect_size, gradient_min_rect_size;
+ int idx_zlib_level, mono_zlib_level, raw_zlib_level, gradient_zlib_level;
+ int gradient_threshold, gradient_threshold24;
+ int idx_max_colors_divisor;
+ int jpeg_quality, jpeg_threshold, jpeg_threshold24;
+} tight_conf[] = {
+ { 512, 32, 6, 65536, 0, 0, 0, 0, 0, 0, 4, 5, 10000, 23000 },
+ { 2048, 128, 6, 65536, 1, 1, 1, 0, 0, 0, 8, 10, 8000, 18000 },
+ { 6144, 256, 8, 65536, 3, 3, 2, 0, 0, 0, 24, 15, 6500, 15000 },
+ { 10240, 1024, 12, 65536, 5, 5, 3, 0, 0, 0, 32, 25, 5000, 12000 },
+ { 16384, 2048, 12, 65536, 6, 6, 4, 0, 0, 0, 32, 37, 4000, 10000 },
+ { 32768, 2048, 12, 4096, 7, 7, 5, 4, 150, 380, 32, 50, 3000, 8000 },
+ { 65536, 2048, 16, 4096, 7, 7, 6, 4, 170, 420, 48, 60, 2000, 5000 },
+ { 65536, 2048, 16, 4096, 8, 8, 7, 5, 180, 450, 64, 70, 1000, 2500 },
+ { 65536, 2048, 32, 8192, 9, 9, 8, 6, 190, 475, 64, 75, 500, 1200 },
+ { 65536, 2048, 32, 8192, 9, 9, 9, 6, 200, 500, 96, 80, 200, 500 }
+};
+
+static int tight_init_stream(VncState *vs, int stream_id,
+ int level, int strategy)
+{
+ z_streamp zstream = &vs->tight_stream[stream_id];
+
+ if (zstream->opaque == NULL) {
+ int err;
+
+ VNC_DEBUG("VNC: TIGHT: initializing zlib stream %d\n", stream_id);
+ VNC_DEBUG("VNC: TIGHT: opaque = %p | vs = %p\n", zstream->opaque, vs);
+ zstream->zalloc = vnc_zlib_zalloc;
+ zstream->zfree = vnc_zlib_zfree;
+
+ err = deflateInit2(zstream, level, Z_DEFLATED, MAX_WBITS,
+ MAX_MEM_LEVEL, strategy);
+
+ if (err != Z_OK) {
+ fprintf(stderr, "VNC: error initializing zlib\n");
+ return -1;
+ }
+
+ vs->tight_levels[stream_id] = level;
+ zstream->opaque = vs;
+ }
+
+ if (vs->tight_levels[stream_id] != level) {
+ if (deflateParams(zstream, level, strategy) != Z_OK) {
+ return -1;
+ }
+ vs->tight_levels[stream_id] = level;
+ }
+ return 0;
+}
+
+static void tight_send_compact_size(VncState *vs, size_t len)
+{
+ int lpc = 0;
+ int bytes = 0;
+ char buf[3] = {0, 0, 0};
+
+ buf[bytes++] = len & 0x7F;
+ if (len > 0x7F) {
+ buf[bytes-1] |= 0x80;
+ buf[bytes++] = (len >> 7) & 0x7F;
+ if (len > 0x3FFF) {
+ buf[bytes-1] |= 0x80;
+ buf[bytes++] = (len >> 14) & 0xFF;
+ }
+ }
+ for(lpc = 0; lpc < bytes; lpc++) {
+ vnc_write_u8(vs, buf[lpc]);
+ }
+}
+
+static int tight_compress_data(VncState *vs, int stream_id, size_t bytes,
+ int level, int strategy)
+{
+ z_streamp zstream = &vs->tight_stream[stream_id];
+ int previous_out;
+
+ if (bytes < VNC_TIGHT_MIN_TO_COMPRESS) {
+ vnc_write(vs, vs->tight.buffer, vs->tight.offset);
+ return bytes;
+ }
+
+ if (tight_init_stream(vs, stream_id, level, strategy)) {
+ return -1;
+ }
+
+ /* reserve memory in output buffer */
+ buffer_reserve(&vs->tight_zlib, bytes + 64);
+
+ /* set pointers */
+ zstream->next_in = vs->tight.buffer;
+ zstream->avail_in = vs->tight.offset;
+ zstream->next_out = vs->tight_zlib.buffer + vs->tight_zlib.offset;
+ zstream->avail_out = vs->tight_zlib.capacity - vs->tight_zlib.offset;
+ zstream->data_type = Z_BINARY;
+ previous_out = zstream->total_out;
+
+ /* start encoding */
+ if (deflate(zstream, Z_SYNC_FLUSH) != Z_OK) {
+ fprintf(stderr, "VNC: error during tight compression\n");
+ return -1;
+ }
+
+ vs->tight_zlib.offset = vs->tight_zlib.capacity - zstream->avail_out;
+ bytes = zstream->total_out - previous_out;
+
+ tight_send_compact_size(vs, bytes);
+ vnc_write(vs, vs->tight_zlib.buffer, bytes);
+
+ buffer_reset(&vs->tight_zlib);
+
+ return bytes;
+}
+
+/*
+ * Subencoding implementations.
+ */
+static void tight_pack24(VncState *vs, size_t count)
+{
+ unsigned char *buf;
+ uint32_t *buf32;
+ uint32_t pix;
+ int rshift, gshift, bshift;
+
+ buf = vs->tight.buffer;
+ buf32 = (uint32_t *)buf;
+
+ if ((vs->clientds.flags & QEMU_BIG_ENDIAN_FLAG) ==
+ (vs->ds->surface->flags & QEMU_BIG_ENDIAN_FLAG)) {
+ rshift = vs->clientds.pf.rshift;
+ gshift = vs->clientds.pf.gshift;
+ bshift = vs->clientds.pf.bshift;
+ } else {
+ rshift = 24 - vs->clientds.pf.rshift;
+ gshift = 24 - vs->clientds.pf.gshift;
+ bshift = 24 - vs->clientds.pf.bshift;
+ }
+
+ vs->tight.offset = count * 3;
+
+ while (count--) {
+ pix = *buf32++;
+ *buf++ = (char)(pix >> rshift);
+ *buf++ = (char)(pix >> gshift);
+ *buf++ = (char)(pix >> bshift);
+ }
+}
+
+static int send_full_color_rect(VncState *vs, int w, int h)
+{
+ int stream = 0;
+ size_t bytes;
+
+ vnc_write_u8(vs, stream << 4); /* no flushing, no filter */
+
+ if (vs->tight_pixel24) {
+ tight_pack24(vs, w * h);
+ bytes = 3;
+ } else {
+ bytes = vs->clientds.pf.bytes_per_pixel;
+ }
+
+ bytes = tight_compress_data(vs, stream, w * h * bytes,
+ tight_conf[vs->tight_compression].raw_zlib_level,
+ Z_DEFAULT_STRATEGY);
+
+ return (bytes >= 0);
+}
+
+static void vnc_tight_start(VncState *vs)
+{
+ buffer_reset(&vs->tight);
+
+ // make the output buffer be the zlib buffer, so we can compress it later
+ vs->tight_tmp = vs->output;
+ vs->output = vs->tight;
+}
+
+static void vnc_tight_stop(VncState *vs)
+{
+ // switch back to normal output/zlib buffers
+ vs->tight = vs->output;
+ vs->output = vs->tight_tmp;
+}
+
+static int send_sub_rect(VncState *vs, int x, int y, int w, int h)
+{
+ vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_TIGHT);
+
+ /*
+ * Convert pixels and store them in vs->tight
+ * We will probably rework that later, probably
+ * when adding other sub-encodings
+ */
+ vnc_tight_start(vs);
+ vnc_raw_send_framebuffer_update(vs, x, y, w, h);
+ vnc_tight_stop(vs);
+
+ return send_full_color_rect(vs, w, h);
+}
+
+static int send_rect_simple(VncState *vs, int x, int y, int w, int h)
+{
+ int max_size, max_width;
+ int max_sub_width, max_sub_height;
+ int dx, dy;
+ int rw, rh;
+ int n = 0;
+
+ max_size = tight_conf[vs->tight_compression].max_rect_size;
+ max_width = tight_conf[vs->tight_compression].max_rect_width;
+
+ if (w > max_width || w * h > max_size) {
+ max_sub_width = (w > max_width) ? max_width : w;
+ max_sub_height = max_size / max_sub_width;
+
+ for (dy = 0; dy < h; dy += max_sub_height) {
+ for (dx = 0; dx < w; dx += max_width) {
+ rw = MIN(max_sub_width, w - dx);
+ rh = MIN(max_sub_height, h - dy);
+ n += send_sub_rect(vs, x+dx, y+dy, rw, rh);
+ }
+ }
+ } else {
+ n += send_sub_rect(vs, x, y, w, h);
+ }
+
+ return n;
+}
+
+int vnc_tight_send_framebuffer_update(VncState *vs, int x, int y,
+ int w, int h)
+{
+ if (vs->clientds.pf.bytes_per_pixel == 4 && vs->clientds.pf.rmax == 0xFF &&
+ vs->clientds.pf.bmax == 0xFF && vs->clientds.pf.gmax == 0xFF) {
+ vs->tight_pixel24 = true;
+ } else {
+ vs->tight_pixel24 = false;
+ }
+
+ return send_rect_simple(vs, x, y, w, h);
+}
+
+void vnc_tight_clear(VncState *vs)
+{
+ int i;
+ for (i=0; i<ARRAY_SIZE(vs->tight_stream); i++) {
+ if (vs->tight_stream[i].opaque) {
+ deflateEnd(&vs->tight_stream[i]);
+ }
+ }
+
+ buffer_free(&vs->tight);
+ buffer_free(&vs->tight_zlib);
+}
diff --git a/vnc-encoding-tight.h b/vnc-encoding-tight.h
new file mode 100644
index 0000000..64d1062
--- /dev/null
+++ b/vnc-encoding-tight.h
@@ -0,0 +1,176 @@
+/*
+ * QEMU VNC display driver: tight encoding
+ *
+ * From libvncserver/rfb/rfbproto.h
+ * Copyright (C) 2005 Rohit Kumar, Johannes E. Schindelin
+ * Copyright (C) 2000-2002 Constantin Kaplinsky. All Rights Reserved.
+ * Copyright (C) 2000 Tridia Corporation. All Rights Reserved.
+ * Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
+ *
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef VNC_ENCODING_TIGHT_H
+#define VNC_ENCODING_TIGHT_H
+
+/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+ * Tight Encoding.
+ *
+ *-- The first byte of each Tight-encoded rectangle is a "compression control
+ * byte". Its format is as follows (bit 0 is the least significant one):
+ *
+ * bit 0: if 1, then compression stream 0 should be reset;
+ * bit 1: if 1, then compression stream 1 should be reset;
+ * bit 2: if 1, then compression stream 2 should be reset;
+ * bit 3: if 1, then compression stream 3 should be reset;
+ * bits 7-4: if 1000 (0x08), then the compression type is "fill",
+ * if 1001 (0x09), then the compression type is "jpeg",
+ * if 0xxx, then the compression type is "basic",
+ * values greater than 1001 are not valid.
+ *
+ * If the compression type is "basic", then bits 6..4 of the
+ * compression control byte (those xxx in 0xxx) specify the following:
+ *
+ * bits 5-4: decimal representation is the index of a particular zlib
+ * stream which should be used for decompressing the data;
+ * bit 6: if 1, then a "filter id" byte is following this byte.
+ *
+ *-- The data that follows after the compression control byte described
+ * above depends on the compression type ("fill", "jpeg" or "basic").
+ *
+ *-- If the compression type is "fill", then the only pixel value follows, in
+ * client pixel format (see NOTE 1). This value applies to all pixels of the
+ * rectangle.
+ *
+ *-- If the compression type is "jpeg", the following data stream looks like
+ * this:
+ *
+ * 1..3 bytes: data size (N) in compact representation;
+ * N bytes: JPEG image.
+ *
+ * Data size is compactly represented in one, two or three bytes, according
+ * to the following scheme:
+ *
+ * 0xxxxxxx (for values 0..127)
+ * 1xxxxxxx 0yyyyyyy (for values 128..16383)
+ * 1xxxxxxx 1yyyyyyy zzzzzzzz (for values 16384..4194303)
+ *
+ * Here each character denotes one bit, xxxxxxx are the least significant 7
+ * bits of the value (bits 0-6), yyyyyyy are bits 7-13, and zzzzzzzz are the
+ * most significant 8 bits (bits 14-21). For example, decimal value 10000
+ * should be represented as two bytes: binary 10010000 01001110, or
+ * hexadecimal 90 4E.
+ *
+ *-- If the compression type is "basic" and bit 6 of the compression control
+ * byte was set to 1, then the next (second) byte specifies "filter id" which
+ * tells the decoder what filter type was used by the encoder to pre-process
+ * pixel data before the compression. The "filter id" byte can be one of the
+ * following:
+ *
+ * 0: no filter ("copy" filter);
+ * 1: "palette" filter;
+ * 2: "gradient" filter.
+ *
+ *-- If bit 6 of the compression control byte is set to 0 (no "filter id"
+ * byte), or if the filter id is 0, then raw pixel values in the client
+ * format (see NOTE 1) will be compressed. See below details on the
+ * compression.
+ *
+ *-- The "gradient" filter pre-processes pixel data with a simple algorithm
+ * which converts each color component to a difference between a "predicted"
+ * intensity and the actual intensity. Such a technique does not affect
+ * uncompressed data size, but helps to compress photo-like images better.
+ * Pseudo-code for converting intensities to differences is the following:
+ *
+ * P[i,j] := V[i-1,j] + V[i,j-1] - V[i-1,j-1];
+ * if (P[i,j] < 0) then P[i,j] := 0;
+ * if (P[i,j] > MAX) then P[i,j] := MAX;
+ * D[i,j] := V[i,j] - P[i,j];
+ *
+ * Here V[i,j] is the intensity of a color component for a pixel at
+ * coordinates (i,j). MAX is the maximum value of intensity for a color
+ * component.
+ *
+ *-- The "palette" filter converts true-color pixel data to indexed colors
+ * and a palette which can consist of 2..256 colors. If the number of colors
+ * is 2, then each pixel is encoded in 1 bit, otherwise 8 bits is used to
+ * encode one pixel. 1-bit encoding is performed such way that the most
+ * significant bits correspond to the leftmost pixels, and each raw of pixels
+ * is aligned to the byte boundary. When "palette" filter is used, the
+ * palette is sent before the pixel data. The palette begins with an unsigned
+ * byte which value is the number of colors in the palette minus 1 (i.e. 1
+ * means 2 colors, 255 means 256 colors in the palette). Then follows the
+ * palette itself which consist of pixel values in client pixel format (see
+ * NOTE 1).
+ *
+ *-- The pixel data is compressed using the zlib library. But if the data
+ * size after applying the filter but before the compression is less then 12,
+ * then the data is sent as is, uncompressed. Four separate zlib streams
+ * (0..3) can be used and the decoder should read the actual stream id from
+ * the compression control byte (see NOTE 2).
+ *
+ * If the compression is not used, then the pixel data is sent as is,
+ * otherwise the data stream looks like this:
+ *
+ * 1..3 bytes: data size (N) in compact representation;
+ * N bytes: zlib-compressed data.
+ *
+ * Data size is compactly represented in one, two or three bytes, just like
+ * in the "jpeg" compression method (see above).
+ *
+ *-- NOTE 1. If the color depth is 24, and all three color components are
+ * 8-bit wide, then one pixel in Tight encoding is always represented by
+ * three bytes, where the first byte is red component, the second byte is
+ * green component, and the third byte is blue component of the pixel color
+ * value. This applies to colors in palettes as well.
+ *
+ *-- NOTE 2. The decoder must reset compression streams' states before
+ * decoding the rectangle, if some of bits 0,1,2,3 in the compression control
+ * byte are set to 1. Note that the decoder must reset zlib streams even if
+ * the compression type is "fill" or "jpeg".
+ *
+ *-- NOTE 3. The "gradient" filter and "jpeg" compression may be used only
+ * when bits-per-pixel value is either 16 or 32, not 8.
+ *
+ *-- NOTE 4. The width of any Tight-encoded rectangle cannot exceed 2048
+ * pixels. If a rectangle is wider, it must be split into several rectangles
+ * and each one should be encoded separately.
+ *
+ */
+
+#define VNC_TIGHT_EXPLICIT_FILTER 0x04
+#define VNC_TIGHT_FILL 0x08
+#define VNC_TIGHT_JPEG 0x09
+#define VNC_TIGHT_MAX_SUBENCODING 0x09
+
+/* Filters to improve compression efficiency */
+#define VNC_TIGHT_FILTER_COPY 0x00
+#define VNC_TIGHT_FILTER_PALETTE 0x01
+#define VNC_TIGHT_FILTER_GRADIENT 0x02
+
+/* Note: The following constant should not be changed. */
+#define VNC_TIGHT_MIN_TO_COMPRESS 12
+
+/* The parameters below may be adjusted. */
+#define VNC_TIGHT_MIN_SPLIT_RECT_SIZE 4096
+#define VNC_TIGHT_MIN_SOLID_SUBRECT_SIZE 2048
+#define VNC_TIGHT_MAX_SPLIT_TILE_SIZE 16
+
+#endif /* VNC_ENCODING_TIGHT_H */
diff --git a/vnc-encoding-zlib.c b/vnc-encoding-zlib.c
index 88ac863..a99bc38 100644
--- a/vnc-encoding-zlib.c
+++ b/vnc-encoding-zlib.c
@@ -28,7 +28,7 @@
#define ZALLOC_ALIGNMENT 16
-static void *zalloc(void *x, unsigned items, unsigned size)
+void *vnc_zlib_zalloc(void *x, unsigned items, unsigned size)
{
void *p;
@@ -40,7 +40,7 @@ static void *zalloc(void *x, unsigned items, unsigned size)
return (p);
}
-static void zfree(void *x, void *addr)
+void vnc_zlib_zfree(void *x, void *addr)
{
qemu_free(addr);
}
@@ -72,8 +72,8 @@ static int vnc_zlib_stop(VncState *vs)
VNC_DEBUG("VNC: initializing zlib stream\n");
VNC_DEBUG("VNC: opaque = %p | vs = %p\n", zstream->opaque, vs);
- zstream->zalloc = zalloc;
- zstream->zfree = zfree;
+ zstream->zalloc = vnc_zlib_zalloc;
+ zstream->zfree = vnc_zlib_zfree;
err = deflateInit2(zstream, vs->tight_compression, Z_DEFLATED, MAX_WBITS,
MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY);
diff --git a/vnc.c b/vnc.c
index 626f173..046bd38 100644
--- a/vnc.c
+++ b/vnc.c
@@ -678,6 +678,9 @@ static int send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_HEXTILE);
n = vnc_hextile_send_framebuffer_update(vs, x, y, w, h);
break;
+ case VNC_ENCODING_TIGHT:
+ n = vnc_tight_send_framebuffer_update(vs, x, y, w, h);
+ break;
default:
vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_RAW);
n = vnc_raw_send_framebuffer_update(vs, x, y, w, h);
@@ -982,6 +985,7 @@ static void vnc_disconnect_finish(VncState *vs)
qobject_decref(vs->info);
vnc_zlib_clear(vs);
+ vnc_tight_clear(vs);
#ifdef CONFIG_VNC_TLS
vnc_tls_client_cleanup(vs);
@@ -1677,6 +1681,10 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
vs->features |= VNC_FEATURE_HEXTILE_MASK;
vs->vnc_encoding = enc;
break;
+ case VNC_ENCODING_TIGHT:
+ vs->features |= VNC_FEATURE_TIGHT_MASK;
+ vs->vnc_encoding = enc;
+ break;
case VNC_ENCODING_ZLIB:
vs->features |= VNC_FEATURE_ZLIB_MASK;
vs->vnc_encoding = enc;
diff --git a/vnc.h b/vnc.h
index cd6495f..51595e6 100644
--- a/vnc.h
+++ b/vnc.h
@@ -170,6 +170,12 @@ struct VncState
/* Tight */
uint8_t tight_quality;
uint8_t tight_compression;
+ uint8_t tight_pixel24;
+ Buffer tight;
+ Buffer tight_tmp;
+ Buffer tight_zlib;
+ int tight_levels[4];
+ z_stream tight_stream[4];
/* Hextile */
VncSendHextileTile *send_hextile_tile;
@@ -404,7 +410,13 @@ int vnc_hextile_send_framebuffer_update(VncState *vs, int x,
int y, int w, int h);
void vnc_hextile_set_pixel_conversion(VncState *vs, int generic);
+void *vnc_zlib_zalloc(void *x, unsigned items, unsigned size);
+void vnc_zlib_zfree(void *x, void *addr);
int vnc_zlib_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
void vnc_zlib_clear(VncState *vs);
+
+int vnc_tight_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
+void vnc_tight_clear(VncState *vs);
+
#endif /* __QEMU_VNC_H */
commit a885211eed4e853c64d1419a0113c12048ecd5a1
Author: Corentin Chary <corentincj at iksaif.net>
Date: Wed May 19 09:24:09 2010 +0200
vnc: return the number of rectangles
Some encodings like tight supports tiling (spliting in
multiple sub-rectangles). So we needed a way to tell
vnc_update_client() how much rectangles are in the buffer.
zlib, raw and hextile always send a full rectangle.
Signed-off-by: Corentin Chary <corentincj at iksaif.net>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/vnc-encoding-hextile.c b/vnc-encoding-hextile.c
index a01c5e2..728f25e 100644
--- a/vnc-encoding-hextile.c
+++ b/vnc-encoding-hextile.c
@@ -62,8 +62,8 @@ static void hextile_enc_cord(uint8_t *ptr, int x, int y, int w, int h)
#undef BPP
#undef GENERIC
-void vnc_hextile_send_framebuffer_update(VncState *vs, int x,
- int y, int w, int h)
+int vnc_hextile_send_framebuffer_update(VncState *vs, int x,
+ int y, int w, int h)
{
int i, j;
int has_fg, has_bg;
@@ -83,6 +83,7 @@ void vnc_hextile_send_framebuffer_update(VncState *vs, int x,
free(last_fg);
free(last_bg);
+ return 1;
}
void vnc_hextile_set_pixel_conversion(VncState *vs, int generic)
diff --git a/vnc-encoding-zlib.c b/vnc-encoding-zlib.c
index 1d4dd1a..88ac863 100644
--- a/vnc-encoding-zlib.c
+++ b/vnc-encoding-zlib.c
@@ -116,7 +116,7 @@ static int vnc_zlib_stop(VncState *vs)
return zstream->total_out - previous_out;
}
-void vnc_zlib_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
+int vnc_zlib_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
{
int old_offset, new_offset, bytes_written;
@@ -132,13 +132,15 @@ void vnc_zlib_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
bytes_written = vnc_zlib_stop(vs);
if (bytes_written == -1)
- return;
+ return 0;
// hack in the size
new_offset = vs->output.offset;
vs->output.offset = old_offset;
vnc_write_u32(vs, bytes_written);
vs->output.offset = new_offset;
+
+ return 1;
}
void vnc_zlib_clear(VncState *vs)
diff --git a/vnc.c b/vnc.c
index f48f253..626f173 100644
--- a/vnc.c
+++ b/vnc.c
@@ -652,7 +652,7 @@ static void vnc_write_pixels_generic(VncState *vs, struct PixelFormat *pf,
}
}
-void vnc_raw_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
+int vnc_raw_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
{
int i;
uint8_t *row;
@@ -663,23 +663,27 @@ void vnc_raw_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
vs->write_pixels(vs, &vd->server->pf, row, w * ds_get_bytes_per_pixel(vs->ds));
row += ds_get_linesize(vs->ds);
}
+ return 1;
}
-static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
+static int send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
{
+ int n = 0;
+
switch(vs->vnc_encoding) {
case VNC_ENCODING_ZLIB:
- vnc_zlib_send_framebuffer_update(vs, x, y, w, h);
+ n = vnc_zlib_send_framebuffer_update(vs, x, y, w, h);
break;
case VNC_ENCODING_HEXTILE:
vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_HEXTILE);
- vnc_hextile_send_framebuffer_update(vs, x, y, w, h);
+ n = vnc_hextile_send_framebuffer_update(vs, x, y, w, h);
break;
default:
vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_RAW);
- vnc_raw_send_framebuffer_update(vs, x, y, w, h);
+ n = vnc_raw_send_framebuffer_update(vs, x, y, w, h);
break;
}
+ return n;
}
static void vnc_copy(VncState *vs, int src_x, int src_y, int dst_x, int dst_y, int w, int h)
@@ -834,6 +838,7 @@ static int vnc_update_client(VncState *vs, int has_dirty)
int y;
int n_rectangles;
int saved_offset;
+ int n;
if (vs->output.offset && !vs->audio_cap && !vs->force_update)
/* kernel send buffers are full -> drop frames to throttle */
@@ -866,16 +871,18 @@ static int vnc_update_client(VncState *vs, int has_dirty)
} else {
if (last_x != -1) {
int h = find_and_clear_dirty_height(vs, y, last_x, x);
- send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h);
- n_rectangles++;
+ n = send_framebuffer_update(vs, last_x * 16, y,
+ (x - last_x) * 16, h);
+ n_rectangles += n;
}
last_x = -1;
}
}
if (last_x != -1) {
int h = find_and_clear_dirty_height(vs, y, last_x, x);
- send_framebuffer_update(vs, last_x * 16, y, (x - last_x) * 16, h);
- n_rectangles++;
+ n = send_framebuffer_update(vs, last_x * 16, y,
+ (x - last_x) * 16, h);
+ n_rectangles += n;
}
}
vs->output.buffer[saved_offset] = (n_rectangles >> 8) & 0xFF;
diff --git a/vnc.h b/vnc.h
index 2fbe614..cd6495f 100644
--- a/vnc.h
+++ b/vnc.h
@@ -398,13 +398,13 @@ void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v);
/* Encodings */
-void vnc_raw_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
+int vnc_raw_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
-void vnc_hextile_send_framebuffer_update(VncState *vs, int x,
+int vnc_hextile_send_framebuffer_update(VncState *vs, int x,
int y, int w, int h);
void vnc_hextile_set_pixel_conversion(VncState *vs, int generic);
-void vnc_zlib_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
+int vnc_zlib_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
void vnc_zlib_clear(VncState *vs);
#endif /* __QEMU_VNC_H */
commit 161c4f20bfbd54f0b77426adccb68ee831678af0
Author: Corentin Chary <corentincj at iksaif.net>
Date: Wed May 19 09:24:08 2010 +0200
vnc: remove a memory leak in zlib
Makes sure we free all ressources used in zlib encoding (zlib stream
and buffer).
Signed-off-by: Corentin Chary <corentincj at iksaif.net>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/vnc-encoding-zlib.c b/vnc-encoding-zlib.c
index 52b18aa..1d4dd1a 100644
--- a/vnc-encoding-zlib.c
+++ b/vnc-encoding-zlib.c
@@ -140,3 +140,11 @@ void vnc_zlib_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
vnc_write_u32(vs, bytes_written);
vs->output.offset = new_offset;
}
+
+void vnc_zlib_clear(VncState *vs)
+{
+ if (vs->zlib_stream.opaque) {
+ deflateEnd(&vs->zlib_stream);
+ }
+ buffer_free(&vs->zlib);
+}
diff --git a/vnc.c b/vnc.c
index 6b2f724..f48f253 100644
--- a/vnc.c
+++ b/vnc.c
@@ -974,6 +974,8 @@ static void vnc_disconnect_finish(VncState *vs)
qobject_decref(vs->info);
+ vnc_zlib_clear(vs);
+
#ifdef CONFIG_VNC_TLS
vnc_tls_client_cleanup(vs);
#endif /* CONFIG_VNC_TLS */
diff --git a/vnc.h b/vnc.h
index c97113b..2fbe614 100644
--- a/vnc.h
+++ b/vnc.h
@@ -405,5 +405,6 @@ void vnc_hextile_send_framebuffer_update(VncState *vs, int x,
void vnc_hextile_set_pixel_conversion(VncState *vs, int generic);
void vnc_zlib_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
+void vnc_zlib_clear(VncState *vs);
#endif /* __QEMU_VNC_H */
commit 5d418e3ba96cfa810e00885a52b55f19cac8f9a6
Author: Corentin Chary <corentincj at iksaif.net>
Date: Wed May 19 09:24:07 2010 +0200
vnc: add buffer_free()
Add a buffer_free() helper to free vnc buffers and
remove some duplicated code in vnc_disconnect_finish().
Signed-off-by: Corentin Chary <corentincj at iksaif.net>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/vnc.c b/vnc.c
index 42ff253..6b2f724 100644
--- a/vnc.c
+++ b/vnc.c
@@ -508,6 +508,14 @@ void buffer_reset(Buffer *buffer)
buffer->offset = 0;
}
+void buffer_free(Buffer *buffer)
+{
+ qemu_free(buffer->buffer);
+ buffer->offset = 0;
+ buffer->capacity = 0;
+ buffer->buffer = NULL;
+}
+
void buffer_append(Buffer *buffer, const void *data, size_t len)
{
memcpy(buffer->buffer + buffer->offset, data, len);
@@ -961,14 +969,8 @@ static void vnc_disconnect_finish(VncState *vs)
{
vnc_qmp_event(vs, QEVENT_VNC_DISCONNECTED);
- if (vs->input.buffer) {
- qemu_free(vs->input.buffer);
- vs->input.buffer = NULL;
- }
- if (vs->output.buffer) {
- qemu_free(vs->output.buffer);
- vs->output.buffer = NULL;
- }
+ buffer_free(&vs->input);
+ buffer_free(&vs->output);
qobject_decref(vs->info);
diff --git a/vnc.h b/vnc.h
index c8200e9..c97113b 100644
--- a/vnc.h
+++ b/vnc.h
@@ -382,6 +382,7 @@ void buffer_reserve(Buffer *buffer, size_t len);
int buffer_empty(Buffer *buffer);
uint8_t *buffer_end(Buffer *buffer);
void buffer_reset(Buffer *buffer);
+void buffer_free(Buffer *buffer);
void buffer_append(Buffer *buffer, const void *data, size_t len);
commit 78c98c78705452e439f5b2ef5447ada23de9988e
Author: Corentin Chary <corentincj at iksaif.net>
Date: Wed May 19 09:24:06 2010 +0200
vnc: don't clear zlib stream on set_encoding
On init, values are already NULL, but we shouldn't try
to reset them each time a client send a set encoding
command because this break everything. For example,
libvncclient re-send a set encoding command if the
framebuffer is resized.
This fix framebuffer resizing for zlib encoding.
Signed-off-by: Corentin Chary <corentincj at iksaif.net>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/vnc-encoding-zlib.c b/vnc-encoding-zlib.c
index 29dd1b7..52b18aa 100644
--- a/vnc-encoding-zlib.c
+++ b/vnc-encoding-zlib.c
@@ -140,8 +140,3 @@ void vnc_zlib_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
vnc_write_u32(vs, bytes_written);
vs->output.offset = new_offset;
}
-
-void vnc_zlib_init(VncState *vs)
-{
- vs->zlib_stream.opaque = NULL;
-}
diff --git a/vnc.c b/vnc.c
index 8db1557..42ff253 100644
--- a/vnc.c
+++ b/vnc.c
@@ -1642,7 +1642,6 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
int i;
unsigned int enc = 0;
- vnc_zlib_init(vs);
vs->features = 0;
vs->vnc_encoding = 0;
vs->tight_compression = 9;
diff --git a/vnc.h b/vnc.h
index 3800687..c8200e9 100644
--- a/vnc.h
+++ b/vnc.h
@@ -403,7 +403,6 @@ void vnc_hextile_send_framebuffer_update(VncState *vs, int x,
int y, int w, int h);
void vnc_hextile_set_pixel_conversion(VncState *vs, int generic);
-void vnc_zlib_init(VncState *vs);
void vnc_zlib_send_framebuffer_update(VncState *vs, int x, int y, int w, int h);
#endif /* __QEMU_VNC_H */
commit 9f643ec0f81c1836ce55319709dd387e27c55d3b
Author: Corentin Chary <corentincj at iksaif.net>
Date: Wed May 19 09:24:05 2010 +0200
vnc: adjust compression zstream level
Adjust zlib compression level if needed by calling deflateParams.
Signed-off-by: Corentin Chary <corentincj at iksaif.net>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/vnc-encoding-zlib.c b/vnc-encoding-zlib.c
index 6a16a79..29dd1b7 100644
--- a/vnc-encoding-zlib.c
+++ b/vnc-encoding-zlib.c
@@ -83,10 +83,17 @@ static int vnc_zlib_stop(VncState *vs)
return -1;
}
+ vs->zlib_level = vs->tight_compression;
zstream->opaque = vs;
}
- // XXX what to do if tight_compression changed in between?
+ if (vs->tight_compression != vs->zlib_level) {
+ if (deflateParams(zstream, vs->tight_compression,
+ Z_DEFAULT_STRATEGY) != Z_OK) {
+ return -1;
+ }
+ vs->zlib_level = vs->tight_compression;
+ }
// reserve memory in output buffer
buffer_reserve(&vs->output, vs->zlib.offset + 64);
diff --git a/vnc.h b/vnc.h
index 6d92c60..3800687 100644
--- a/vnc.h
+++ b/vnc.h
@@ -178,6 +178,7 @@ struct VncState
Buffer zlib;
Buffer zlib_tmp;
z_stream zlib_stream;
+ int zlib_level;
Notifier mouse_mode_notifier;
commit b05ad290e2a5d9074179fede31d54371e1a09a6a
Author: Corentin Chary <corentincj at iksaif.net>
Date: Wed May 19 09:24:04 2010 +0200
vnc: only use a single zlib stream
According to http://tigervnc.org/cgi-bin/rfbproto#zlib-encoding
zlib encoding only uses a single stream. Current implementation defines
4 streams but only uses the first one. Remove them and only use a single
stream.
Signed-off-by: Corentin Chary <corentincj at iksaif.net>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/vnc-encoding-zlib.c b/vnc-encoding-zlib.c
index 4a495ad..6a16a79 100644
--- a/vnc-encoding-zlib.c
+++ b/vnc-encoding-zlib.c
@@ -54,9 +54,9 @@ static void vnc_zlib_start(VncState *vs)
vs->output = vs->zlib;
}
-static int vnc_zlib_stop(VncState *vs, int stream_id)
+static int vnc_zlib_stop(VncState *vs)
{
- z_streamp zstream = &vs->zlib_stream[stream_id];
+ z_streamp zstream = &vs->zlib_stream;
int previous_out;
// switch back to normal output/zlib buffers
@@ -70,7 +70,7 @@ static int vnc_zlib_stop(VncState *vs, int stream_id)
if (zstream->opaque != vs) {
int err;
- VNC_DEBUG("VNC: initializing zlib stream %d\n", stream_id);
+ VNC_DEBUG("VNC: initializing zlib stream\n");
VNC_DEBUG("VNC: opaque = %p | vs = %p\n", zstream->opaque, vs);
zstream->zalloc = zalloc;
zstream->zfree = zfree;
@@ -122,7 +122,7 @@ void vnc_zlib_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
// compress the stream
vnc_zlib_start(vs);
vnc_raw_send_framebuffer_update(vs, x, y, w, h);
- bytes_written = vnc_zlib_stop(vs, 0);
+ bytes_written = vnc_zlib_stop(vs);
if (bytes_written == -1)
return;
@@ -136,7 +136,5 @@ void vnc_zlib_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
void vnc_zlib_init(VncState *vs)
{
- int i;
- for (i=0; i<(sizeof(vs->zlib_stream) / sizeof(z_stream)); i++)
- vs->zlib_stream[i].opaque = NULL;
+ vs->zlib_stream.opaque = NULL;
}
diff --git a/vnc.h b/vnc.h
index 0d39897..6d92c60 100644
--- a/vnc.h
+++ b/vnc.h
@@ -177,7 +177,7 @@ struct VncState
/* Zlib */
Buffer zlib;
Buffer zlib_tmp;
- z_stream zlib_stream[4];
+ z_stream zlib_stream;
Notifier mouse_mode_notifier;
commit 780a049e29447275bd234a3974b2574316140a5f
Author: Corentin Chary <corentincj at iksaif.net>
Date: Wed May 19 09:24:03 2010 +0200
vnc: really call zlib if we want zlib
send_framebuffer_update() was calling hextile instead of zlib
since commit 70a4568fe0c5a64adaa3da5030b7109e5199e692.
Signed-off-by: Corentin Chary <corentincj at iksaif.net>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/vnc.c b/vnc.c
index 774a0b3..8db1557 100644
--- a/vnc.c
+++ b/vnc.c
@@ -661,7 +661,7 @@ static void send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
{
switch(vs->vnc_encoding) {
case VNC_ENCODING_ZLIB:
- vnc_hextile_send_framebuffer_update(vs, x, y, w, h);
+ vnc_zlib_send_framebuffer_update(vs, x, y, w, h);
break;
case VNC_ENCODING_HEXTILE:
vnc_framebuffer_update(vs, x, y, w, h, VNC_ENCODING_HEXTILE);
commit 8a0f0d0ca343e406aab7161c883187f1d2b85d89
Author: Corentin Chary <corentincj at iksaif.net>
Date: Wed May 19 09:24:02 2010 +0200
vnc: explain why set_encodings loop is reversed
Add a small comment to explain why we need to start from
the end of the array to set the right prefered encoding.
Signed-off-by: Corentin Chary <corentincj at iksaif.net>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/vnc.c b/vnc.c
index 1fb46bd..774a0b3 100644
--- a/vnc.c
+++ b/vnc.c
@@ -1649,6 +1649,11 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
vs->tight_quality = 9;
vs->absolute = -1;
+ /*
+ * Start from the end because the encodings are sent in order of preference.
+ * This way the prefered encoding (first encoding defined in the array)
+ * will be set at the end of the loop.
+ */
for (i = n_encodings - 1; i >= 0; i--) {
enc = encodings[i];
switch (enc) {
commit a9f20d31a8332ea4d6a0c90b9731f11a51cff6db
Author: Corentin Chary <corentincj at iksaif.net>
Date: Wed May 19 09:24:01 2010 +0200
Revert "vnc: set the right prefered encoding"
This patch was wrong, because the loop was already reversed,
so the first encoding was correctly set at the end of the loopp.
This reverts commit 14eb8b6829ad9dee7035de729e083844a425f274.
Signed-off-by: Corentin Chary <corentincj at iksaif.net>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/vnc.c b/vnc.c
index 11ae3e5..1fb46bd 100644
--- a/vnc.c
+++ b/vnc.c
@@ -1644,7 +1644,7 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
vnc_zlib_init(vs);
vs->features = 0;
- vs->vnc_encoding = -1;
+ vs->vnc_encoding = 0;
vs->tight_compression = 9;
vs->tight_quality = 9;
vs->absolute = -1;
@@ -1653,24 +1653,18 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
enc = encodings[i];
switch (enc) {
case VNC_ENCODING_RAW:
- if (vs->vnc_encoding != -1) {
- vs->vnc_encoding = enc;
- }
+ vs->vnc_encoding = enc;
break;
case VNC_ENCODING_COPYRECT:
vs->features |= VNC_FEATURE_COPYRECT_MASK;
break;
case VNC_ENCODING_HEXTILE:
vs->features |= VNC_FEATURE_HEXTILE_MASK;
- if (vs->vnc_encoding != -1) {
- vs->vnc_encoding = enc;
- }
+ vs->vnc_encoding = enc;
break;
case VNC_ENCODING_ZLIB:
vs->features |= VNC_FEATURE_ZLIB_MASK;
- if (vs->vnc_encoding != -1) {
- vs->vnc_encoding = enc;
- }
+ vs->vnc_encoding = enc;
break;
case VNC_ENCODING_DESKTOPRESIZE:
vs->features |= VNC_FEATURE_RESIZE_MASK;
commit 9af9b330c5e77024efdc5698ee38ed8ef246337b
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Mon May 31 18:59:45 2010 +0000
ioapic: improve debugging
Add a DPRINTF macro, use it also to see irq deliveries.
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/ioapic.c b/hw/ioapic.c
index 7ad8018..335da6e 100644
--- a/hw/ioapic.c
+++ b/hw/ioapic.c
@@ -28,6 +28,13 @@
//#define DEBUG_IOAPIC
+#ifdef DEBUG_IOAPIC
+#define DPRINTF(fmt, ...) \
+ do { printf("ioapic: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...)
+#endif
+
#define IOAPIC_NUM_PINS 0x18
#define IOAPIC_LVT_MASKED (1<<16)
@@ -95,6 +102,7 @@ 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)
vector = 2;
@@ -149,9 +157,7 @@ static uint32_t ioapic_mem_readl(void *opaque, target_phys_addr_t addr)
val = s->ioredtbl[index] & 0xffffffff;
}
}
-#ifdef DEBUG_IOAPIC
- printf("I/O APIC read: %08x = %08x\n", s->ioregsel, val);
-#endif
+ DPRINTF("read: %08x = %08x\n", s->ioregsel, val);
}
return val;
}
@@ -166,9 +172,7 @@ static void ioapic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t va
s->ioregsel = val;
return;
} else if (addr == 0x10) {
-#ifdef DEBUG_IOAPIC
- printf("I/O APIC write: %08x = %08x\n", s->ioregsel, val);
-#endif
+ DPRINTF("write: %08x = %08x\n", s->ioregsel, val);
switch (s->ioregsel) {
case 0x00:
s->id = (val >> 24) & 0xff;
commit 17e6a53f8223e469034e3ba95b67ec0501f39325
Author: Alexander Graf <agraf at suse.de>
Date: Tue May 11 17:38:17 2010 +0200
Fix leul_to_cpu on big endian hosts
Commit 213acd2e introduced leul_to_cpu with a special code path for big endian
hosts. Unfortunately that code used preprocessor magic that didn't work.
This patch replaces the explicit ##s by glue() which is proven to work reliably,
enabling me to compile qemu on ppc again.
Signed-off-by: Alexander Graf <agraf at suse.de>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/bswap.h b/bswap.h
index 956f3fa..20caae6 100644
--- a/bswap.h
+++ b/bswap.h
@@ -205,7 +205,7 @@ static inline void cpu_to_be32wu(uint32_t *p, uint32_t v)
#ifdef HOST_WORDS_BIGENDIAN
#define cpu_to_32wu cpu_to_be32wu
-#define leul_to_cpu(v) le ## HOST_LONG_BITS ## _to_cpu(v)
+#define leul_to_cpu(v) glue(glue(le,HOST_LONG_BITS),_to_cpu)(v)
#else
#define cpu_to_32wu cpu_to_le32wu
#define leul_to_cpu(v) (v)
commit e03c22a98cf5deffd0dec2f9ff88a600aa330bc4
Author: Lars Munch <lars at segv.dk>
Date: Sat May 8 22:43:35 2010 +0200
arm: fix arm kernel boot for non zero start addr
Booting an arm kernel has been broken a while when booting from non zero start
address. This is due to the order of events: board init loads the kernel and
sets register 15 to the start address and then qemu_system_reset reset the cpu
making register 15 zero again.
This patch fixes the usage of the register 15 start address trick in
combination with arm_load_kernel.
Signed-off-by: Lars Munch <lars at segv.dk>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index df031a5..620550b 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -187,6 +187,7 @@ static void main_cpu_reset(void *opaque)
env->regs[15] = info->entry & 0xfffffffe;
env->thumb = info->entry & 1;
} else {
+ env->regs[15] = info->loader_start;
if (old_param) {
set_kernel_args_old(info, info->initrd_size,
info->loader_start);
diff --git a/hw/gumstix.c b/hw/gumstix.c
index 3fd31f4..b64e04e 100644
--- a/hw/gumstix.c
+++ b/hw/gumstix.c
@@ -74,8 +74,6 @@ static void connex_init(ram_addr_t ram_size,
exit(1);
}
- cpu->env->regs[15] = 0x00000000;
-
/* Interrupt line of NIC is connected to GPIO line 36 */
smc91c111_init(&nd_table[0], 0x04000300,
pxa2xx_gpio_in_get(cpu->gpio)[36]);
@@ -114,8 +112,6 @@ static void verdex_init(ram_addr_t ram_size,
exit(1);
}
- cpu->env->regs[15] = 0x00000000;
-
/* Interrupt line of NIC is connected to GPIO line 99 */
smc91c111_init(&nd_table[0], 0x04000300,
pxa2xx_gpio_in_get(cpu->gpio)[99]);
diff --git a/hw/mainstone.c b/hw/mainstone.c
index a4379e3..54bacfb 100644
--- a/hw/mainstone.c
+++ b/hw/mainstone.c
@@ -89,9 +89,6 @@ static void mainstone_common_init(ram_addr_t ram_size,
cpu_register_physical_memory(0, MAINSTONE_ROM,
qemu_ram_alloc(MAINSTONE_ROM) | IO_MEM_ROM);
- /* Setup initial (reset) machine state */
- cpu->env->regs[15] = mainstone_binfo.loader_start;
-
#ifdef TARGET_WORDS_BIGENDIAN
be = 1;
#else
diff --git a/hw/nseries.c b/hw/nseries.c
index 0273eee..04a028d 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -1016,7 +1016,6 @@ static void n8x0_boot_init(void *opaque)
n800_dss_init(&s->blizzard);
/* CPU setup */
- s->cpu->env->regs[15] = s->cpu->env->boot_info->loader_start;
s->cpu->env->GE = 0x5;
/* If the machine has a slided keyboard, open it */
@@ -1317,11 +1316,6 @@ static void n8x0_init(ram_addr_t ram_size, const char *boot_device,
if (usb_enabled)
n8x0_usb_setup(s);
- /* Setup initial (reset) machine state */
-
- /* Start at the OneNAND bootloader. */
- s->cpu->env->regs[15] = 0;
-
if (kernel_filename) {
/* Or at the linux loader. */
binfo->kernel_filename = kernel_filename;
@@ -1330,7 +1324,6 @@ static void n8x0_init(ram_addr_t ram_size, const char *boot_device,
arm_load_kernel(s->cpu->env, binfo);
qemu_register_reset(n8x0_boot_init, s);
- n8x0_boot_init(s);
}
if (option_rom[0] && (boot_device[0] == 'n' || !kernel_filename)) {
diff --git a/hw/omap_sx1.c b/hw/omap_sx1.c
index ca0a7d1..2e9879f 100644
--- a/hw/omap_sx1.c
+++ b/hw/omap_sx1.c
@@ -195,15 +195,10 @@ static void sx1_init(ram_addr_t ram_size,
/* Load the kernel. */
if (kernel_filename) {
- /* Start at bootloader. */
- cpu->env->regs[15] = sx1_binfo.loader_start;
-
sx1_binfo.kernel_filename = kernel_filename;
sx1_binfo.kernel_cmdline = kernel_cmdline;
sx1_binfo.initrd_filename = initrd_filename;
arm_load_kernel(cpu->env, &sx1_binfo);
- } else {
- cpu->env->regs[15] = 0x00000000;
}
/* TODO: fix next line */
diff --git a/hw/palm.c b/hw/palm.c
index ba7c398..8db133d 100644
--- a/hw/palm.c
+++ b/hw/palm.c
@@ -243,7 +243,6 @@ static void palmte_init(ram_addr_t ram_size,
rom_size = load_image_targphys(option_rom[0], OMAP_CS0_BASE,
flash_size);
rom_loaded = 1;
- cpu->env->regs[15] = 0x00000000;
}
if (rom_size < 0) {
fprintf(stderr, "%s: error loading '%s'\n",
@@ -258,9 +257,6 @@ static void palmte_init(ram_addr_t ram_size,
/* Load the kernel. */
if (kernel_filename) {
- /* Start at bootloader. */
- cpu->env->regs[15] = palmte_binfo.loader_start;
-
palmte_binfo.kernel_filename = kernel_filename;
palmte_binfo.kernel_cmdline = kernel_cmdline;
palmte_binfo.initrd_filename = initrd_filename;
diff --git a/hw/spitz.c b/hw/spitz.c
index c3b5cd8..4f82e24 100644
--- a/hw/spitz.c
+++ b/hw/spitz.c
@@ -993,9 +993,6 @@ static void spitz_common_init(ram_addr_t ram_size,
/* A 4.0 GB microdrive is permanently sitting in CF slot 0. */
spitz_microdrive_attach(cpu, 0);
- /* Setup initial (reset) machine state */
- cpu->env->regs[15] = spitz_binfo.loader_start;
-
spitz_binfo.kernel_filename = kernel_filename;
spitz_binfo.kernel_cmdline = kernel_cmdline;
spitz_binfo.initrd_filename = initrd_filename;
diff --git a/hw/tosa.c b/hw/tosa.c
index bc6591f..fbe8d8c 100644
--- a/hw/tosa.c
+++ b/hw/tosa.c
@@ -229,9 +229,6 @@ static void tosa_init(ram_addr_t ram_size,
tosa_tg_init(cpu);
- /* Setup initial (reset) machine state */
- cpu->env->regs[15] = tosa_binfo.loader_start;
-
tosa_binfo.kernel_filename = kernel_filename;
tosa_binfo.kernel_cmdline = kernel_cmdline;
tosa_binfo.initrd_filename = initrd_filename;
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 99e0394..63e5dc7 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -207,7 +207,6 @@ void cpu_reset(CPUARMState *env)
#else
/* SVC mode with interrupts disabled. */
env->uncached_cpsr = ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
- env->regs[15] = 0;
/* On ARMv7-M the CPSR_I is the value of the PRIMASK register, and is
clear at reset. Initial SP and PC are loaded from ROM. */
if (IS_M(env)) {
commit 0f89cc7b6c33418f268126cc908b222e0d052f69
Author: Thomas Monjalon <thomas at monjalon.net>
Date: Fri May 28 21:00:45 2010 +0200
target-ppc: remove useless line
This line was a bit clear.
The next lines set or reset this bit (LE) depending of another bit (ILE).
So the first line is useless.
Signed-off-by: Thomas Monjalon <thomas at monjalon.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index 4830dd9..d342b09 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -2593,7 +2593,6 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
#if 0 /* Fix this: not on all targets */
new_msr &= ~((target_ulong)1 << MSR_PMM);
#endif
- new_msr &= ~((target_ulong)1 << MSR_LE);
if (msr_ile)
new_msr |= (target_ulong)1 << MSR_LE;
else
commit c3d420ead1aee9fcfd12be11cbdf6b1620134773
Author: Thomas Monjalon <thomas at monjalon.net>
Date: Fri May 28 21:07:32 2010 +0200
target-ppc: fix RFI by clearing some bits of MSR
Since commit 2ada0ed, "Return From Interrupt" is broken for PPC processors
because some interrupt specifics bits of SRR1 are copied to MSR.
SRR1 is a save of MSR during interrupt.
During RFI, MSR must be restored from SRR1.
But some bits of SRR1 are interrupt-specific and are not used for MSR saving.
This is the specification (ISA 2.06) at chapter 6.4.3 (Interrupt Processing):
"2. Bits 33:36 and 42:47 of SRR1 or HSRR1 are loaded with information specific
to the interrupt type.
3. Bits 0:32, 37:41, and 48:63 of SRR1 or HSRR1 are loaded with a copy of the
corresponding bits of the MSR."
Below is a representation of MSR bits which are not saved:
0:15 16:31 32 33:36 37:41 42:47 48:63
âââ | âââ | â X X X X â â â â â X X X X X X | ââââ
0000 0000 | 7 | 8 | 3 | F | 0000
History:
In the initial Qemu implementation (e1833e1), the mask 0x783F0000 was used for
saving MSR in SRR1. But all the bits 32:47 were cleared during RFI restoring.
This was wrong. The commit 2ada0ed explains that this breaks Altivec.
Indeed, bit 38 (for Altivec support) must be saved and restored.
The change of 2ada0ed was to restore all the bits of SRR1 to MSR.
But it's also wrong.
Explanation:
As an example, let's see what's happening after a TLB miss.
According to the e300 manual (E300CORERM table 5-6), the TLB miss interrupts
set the bits 44-47 for KEY, I/D, WAY and S/L. These bits are specifics to the
interrupt and must not be copied into MSR at the end of the interrupt.
With the current implementation, a TLB miss overwrite bits POW, TGPR and ILE.
Fix:
It shouldn't be needed to filter-out bits on MSR saving when interrupt occurs.
Specific bits overwrite MSR ones in SRR1.
But at the end of interrupt (RFI), specifics bits must be cleared before
restoring MSR from SRR1. The mask 0x783F0000 apply here.
Discussion:
The bits of the mask 0x783F0000 are cleared after an interrupt.
I cannot find a specification which talks about this
but I assume it is the truth since Linux can run this way.
Maybe it's not perfect but it's better (works for e300).
Signed-off-by: Thomas Monjalon <thomas at monjalon.net>
Acked-by: Alexander Graf <agraf at suse.de>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index a5479c4..4830dd9 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -2080,7 +2080,6 @@ static inline void powerpc_excp(CPUState *env, int excp_model, int excp)
srr1 = SPR_SRR1;
asrr0 = -1;
asrr1 = -1;
- msr &= ~((target_ulong)0x783F0000);
switch (excp) {
case POWERPC_EXCP_NONE:
/* Should never happen */
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 8f2ee98..3c3aa60 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -1646,20 +1646,20 @@ static inline void do_rfi(target_ulong nip, target_ulong msr,
void helper_rfi (void)
{
do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
- ~((target_ulong)0x0), 1);
+ ~((target_ulong)0x783F0000), 1);
}
#if defined(TARGET_PPC64)
void helper_rfid (void)
{
do_rfi(env->spr[SPR_SRR0], env->spr[SPR_SRR1],
- ~((target_ulong)0x0), 0);
+ ~((target_ulong)0x783F0000), 0);
}
void helper_hrfid (void)
{
do_rfi(env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
- ~((target_ulong)0x0), 0);
+ ~((target_ulong)0x783F0000), 0);
}
#endif
#endif
commit e075e788c9e882f5bebfb350f725ee7e4273033f
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date: Fri May 28 18:30:46 2010 +0900
pci-hotplug: make them aware of pci domain.
add helper function which converts root bus to pci domain.
make them aware of pci domain.
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-hotplug.c b/hw/pci-hotplug.c
index 37ac015..a8f3df1 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -124,7 +124,7 @@ void drive_hot_add(Monitor *mon, const QDict *qdict)
if (pci_read_devaddr(mon, pci_addr, &dom, &pci_bus, &slot)) {
goto err;
}
- dev = pci_find_device(pci_find_root_bus(0), pci_bus, slot, 0);
+ dev = pci_find_device(pci_find_root_bus(dom), pci_bus, slot, 0);
if (!dev) {
monitor_printf(mon, "no pci device with address %s\n", pci_addr);
goto err;
@@ -252,7 +252,8 @@ void pci_device_hot_add(Monitor *mon, const QDict *qdict)
if (dev) {
monitor_printf(mon, "OK domain %d, bus %d, slot %d, function %d\n",
- 0, pci_bus_num(dev->bus), PCI_SLOT(dev->devfn),
+ pci_find_domain(dev->bus),
+ pci_bus_num(dev->bus), PCI_SLOT(dev->devfn),
PCI_FUNC(dev->devfn));
} else
monitor_printf(mon, "failed to add %s\n", opts);
@@ -269,7 +270,7 @@ int pci_device_hot_remove(Monitor *mon, const char *pci_addr)
return -1;
}
- d = pci_find_device(pci_find_root_bus(0), bus, slot, 0);
+ d = pci_find_device(pci_find_root_bus(dom), bus, slot, 0);
if (!d) {
monitor_printf(mon, "slot %d empty\n", slot);
return -1;
diff --git a/hw/pci.c b/hw/pci.c
index 3362842..f084cc0 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -200,6 +200,26 @@ PCIBus *pci_find_root_bus(int domain)
return NULL;
}
+int pci_find_domain(const PCIBus *bus)
+{
+ PCIDevice *d;
+ struct PCIHostBus *host;
+
+ /* obtain root bus */
+ while ((d = bus->parent_dev) != NULL) {
+ bus = d->bus;
+ }
+
+ QLIST_FOREACH(host, &host_buses, next) {
+ if (host->bus == bus) {
+ return host->domain;
+ }
+ }
+
+ abort(); /* should not be reached */
+ return -1;
+}
+
void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
const char *name, int devfn_min)
{
@@ -505,7 +525,7 @@ PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr)
}
*devfnp = slot << 3;
- return pci_find_bus(pci_find_root_bus(0), bus);
+ return pci_find_bus(pci_find_root_bus(dom), bus);
}
static void pci_init_cmask(PCIDevice *dev)
diff --git a/hw/pci.h b/hw/pci.h
index b803593..3a15bd4 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -218,6 +218,7 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, const char *default_model,
int pci_bus_num(PCIBus *s);
void pci_for_each_device(PCIBus *bus, int bus_num, void (*fn)(PCIBus *bus, PCIDevice *d));
PCIBus *pci_find_root_bus(int domain);
+int pci_find_domain(const PCIBus *bus);
PCIBus *pci_find_bus(PCIBus *bus, int bus_num);
PCIDevice *pci_find_device(PCIBus *bus, int bus_num, int slot, int function);
PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr);
commit 1b4e8f732d118d1bd64c49e3c9d90832f8214272
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date: Thu May 27 14:40:37 2010 +0900
msix: remove duplicated defines.
remove defines which are already defined in pci_regs.h
Signed-off-by: Isaku Yamahata <yamahata at valinux.co.jp>
Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
diff --git a/hw/msix.c b/hw/msix.c
index 2ca0900..1613bb4 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -15,14 +15,6 @@
#include "msix.h"
#include "pci.h"
-/* Declaration from linux/pci_regs.h */
-#define PCI_CAP_ID_MSIX 0x11 /* MSI-X */
-#define PCI_MSIX_FLAGS 2 /* Table at lower 11 bits */
-#define PCI_MSIX_FLAGS_QSIZE 0x7FF
-#define PCI_MSIX_FLAGS_ENABLE (1 << 15)
-#define PCI_MSIX_FLAGS_MASKALL (1 << 14)
-#define PCI_MSIX_FLAGS_BIRMASK (7 << 0)
-
/* MSI-X capability structure */
#define MSIX_TABLE_OFFSET 4
#define MSIX_PBA_OFFSET 8
commit 0c6fcb62100d5ed0819963b2b20879b1e61691db
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date: Thu May 27 14:40:02 2010 +0900
pci.h: remove unused constants.
So remove unused constants,
PCI_STATUS_RESERVED_MASK_LO, PCI_STATUS_RESERVED_MASK_HI,
PCI_COMMAND_RESERVED, PCI_COMMAND_RESERVED_MASK_HI.
They were used once, but they aren't used anymore.
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.h b/hw/pci.h
index 1e76ef0..b803593 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -97,17 +97,6 @@ typedef struct PCIIORegion {
/* PCI HEADER_TYPE */
#define PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
-#define PCI_STATUS_RESERVED_MASK_LO (PCI_STATUS_RESERVED1 | \
- PCI_STATUS_INT_STATUS | PCI_STATUS_CAPABILITIES | \
- PCI_STATUS_66MHZ | PCI_STATUS_RESERVED2 | PCI_STATUS_FAST_BACK)
-
-#define PCI_STATUS_RESERVED_MASK_HI (PCI_STATUS_DEVSEL >> 8)
-
-/* Bits in the PCI Command Register (PCI 2.3 spec) */
-#define PCI_COMMAND_RESERVED 0xf800
-
-#define PCI_COMMAND_RESERVED_MASK_HI (PCI_COMMAND_RESERVED >> 8)
-
/* Size of the standard PCI config header */
#define PCI_CONFIG_HEADER_SIZE 0x40
/* Size of the standard PCI config space */
commit 3c18685f43acd81626e7e7bafc5967f04ee48090
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date: Thu May 27 14:42:37 2010 +0900
pci: add const to pci_is_express(), pci_config_size().
add const to pci_is_express(), pci_config_size().
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.h b/hw/pci.h
index f6e6c5f..1e76ef0 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -350,12 +350,12 @@ void pci_qdev_register_many(PCIDeviceInfo *info);
PCIDevice *pci_create(PCIBus *bus, int devfn, const char *name);
PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name);
-static inline int pci_is_express(PCIDevice *d)
+static inline int pci_is_express(const PCIDevice *d)
{
return d->cap_present & QEMU_PCI_CAP_EXPRESS;
}
-static inline uint32_t pci_config_size(PCIDevice *d)
+static inline uint32_t pci_config_size(const PCIDevice *d)
{
return pci_is_express(d) ? PCIE_CONFIG_SPACE_SIZE : PCI_CONFIG_SPACE_SIZE;
}
commit 5e434f4e60f8e5a9dadf324b3ee31c3ce0e80165
Author: Isaku Yamahata <yamahata at valinux.co.jp>
Date: Thu May 27 14:42:06 2010 +0900
pci: clean up of pci_set_default_subsystem_id().
Use pci accessor function.
don't return value because it always return 0 and
the caller doesn't check the return value.
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 8d84651..3362842 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -419,14 +419,12 @@ int pci_device_load(PCIDevice *s, QEMUFile *f)
return ret;
}
-static int pci_set_default_subsystem_id(PCIDevice *pci_dev)
+static void pci_set_default_subsystem_id(PCIDevice *pci_dev)
{
- uint16_t *id;
-
- id = (void*)(&pci_dev->config[PCI_SUBSYSTEM_VENDOR_ID]);
- id[0] = cpu_to_le16(pci_default_sub_vendor_id);
- id[1] = cpu_to_le16(pci_default_sub_device_id);
- return 0;
+ pci_set_word(pci_dev->config + PCI_SUBSYSTEM_VENDOR_ID,
+ pci_default_sub_vendor_id);
+ pci_set_word(pci_dev->config + PCI_SUBSYSTEM_ID,
+ pci_default_sub_device_id);
}
/*
commit aa6f63fff62faf2fe9ffba5a789675d49293614d
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sun May 30 19:20:07 2010 +0000
mc146818rtc: improve debugging
Add a separate flag for debugging coalesced interrupts.
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index 571c593..c3e6a70 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -31,6 +31,7 @@
#include "mc146818rtc.h"
//#define DEBUG_CMOS
+//#define DEBUG_COALESCED
#ifdef DEBUG_CMOS
# define CMOS_DPRINTF(format, ...) printf(format, ## __VA_ARGS__)
@@ -38,6 +39,12 @@
# define CMOS_DPRINTF(format, ...) do { } while (0)
#endif
+#ifdef DEBUG_COALESCED
+# define DPRINTF_C(format, ...) printf(format, ## __VA_ARGS__)
+#else
+# define DPRINTF_C(format, ...) do { } while (0)
+#endif
+
#define RTC_REINJECT_ON_ACK_COUNT 20
#define RTC_SECONDS 0
@@ -131,9 +138,12 @@ static void rtc_coalesced_timer(void *opaque)
if (s->irq_coalesced != 0) {
apic_reset_irq_delivered();
s->cmos_data[RTC_REG_C] |= 0xc0;
+ DPRINTF_C("cmos: injecting from timer\n");
rtc_irq_raise(s->irq);
if (apic_get_irq_delivered()) {
s->irq_coalesced--;
+ DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
+ s->irq_coalesced);
}
}
@@ -164,8 +174,10 @@ static void rtc_timer_update(RTCState *s, int64_t current_time)
/* period in 32 Khz cycles */
period = 1 << (period_code - 1);
#ifdef TARGET_I386
- if(period != s->period)
+ if (period != s->period) {
s->irq_coalesced = (s->irq_coalesced * s->period) / period;
+ DPRINTF_C("cmos: coalesced irqs scaled to %d\n", s->irq_coalesced);
+ }
s->period = period;
#endif
/* compute 32 khz clock */
@@ -198,6 +210,8 @@ static void rtc_periodic_timer(void *opaque)
if (!apic_get_irq_delivered()) {
s->irq_coalesced++;
rtc_coalesced_timer_update(s);
+ DPRINTF_C("cmos: coalesced irqs increased to %d\n",
+ s->irq_coalesced);
}
} else
#endif
@@ -476,9 +490,13 @@ static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
s->irq_reinject_on_ack_count < RTC_REINJECT_ON_ACK_COUNT) {
s->irq_reinject_on_ack_count++;
apic_reset_irq_delivered();
+ DPRINTF_C("cmos: injecting on ack\n");
qemu_irq_raise(s->irq);
- if (apic_get_irq_delivered())
+ if (apic_get_irq_delivered()) {
s->irq_coalesced--;
+ DPRINTF_C("cmos: coalesced irqs decreased to %d\n",
+ s->irq_coalesced);
+ }
break;
}
#endif
commit da7ed37955d955b47a538fcfe65ad1cc730e69a5
Author: Artyom Tarasenko <atar4qemu at googlemail.com>
Date: Sat May 29 22:48:25 2010 +0200
sparc32 SuperSPARC MMU Breakpoint Action register (SS-20 OBP fix)
SuperSPARC MMU Breakpoint Action register is used by OBP at boot
The patch allows booting Solaris and some other OS with
SPARCStation-20 OBP.
Signed-off-by: Artyom Tarasenko <atar4qemu at gmail.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index aaacfc4..ef3504f 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -1745,6 +1745,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
case 0x31: // Turbosparc RAM snoop
case 0x32: // Turbosparc page table descriptor diagnostic
case 0x39: /* data cache diagnostic register */
+ case 0x4c: /* SuperSPARC MMU Breakpoint Action register */
ret = 0;
break;
case 0x38: /* SuperSPARC MMU Breakpoint Control Registers */
commit 471fd34221dcda9b271a3016f95e1ad12842c5ff
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sat May 29 20:23:49 2010 +0000
pc: improve debugging
Add a DPRINTF macro and use it for ISA and PIC interrupts.
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/pc.c b/hw/pc.c
index e7f31d3..9b85c42 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -39,6 +39,16 @@
/* output Bochs bios info messages */
//#define DEBUG_BIOS
+/* debug PC/ISA interrupts */
+//#define DEBUG_IRQ
+
+#ifdef DEBUG_IRQ
+#define DPRINTF(fmt, ...) \
+ do { printf("CPUIRQ: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...)
+#endif
+
#define BIOS_FILENAME "bios.bin"
#define PC_MAX_BIOS_SIZE (4 * 1024 * 1024)
@@ -70,6 +80,7 @@ void isa_irq_handler(void *opaque, int n, int level)
{
IsaIrqState *isa = (IsaIrqState *)opaque;
+ DPRINTF("isa_irqs: %s irq %d\n", level? "raise" : "lower", n);
if (n < 16) {
qemu_set_irq(isa->i8259[n], level);
}
@@ -150,6 +161,7 @@ static void pic_irq_request(void *opaque, int irq, int level)
{
CPUState *env = first_cpu;
+ DPRINTF("pic_irqs: %s irq %d\n", level? "raise" : "lower", irq);
if (env->apic_state) {
while (env) {
if (apic_accept_pic_intr(env))
commit 0a3c59216673e71ca53daef6f05fade33f41e83b
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sat May 29 20:23:48 2010 +0000
apic: improve debugging
Add a DPRINTF macro. Use TARGET_FMT_plx for printing target_phys_addr_t
items. Add a separate flag for debugging coalescing interrupts.
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/apic.c b/hw/apic.c
index 9029dad..7fbd79b 100644
--- a/hw/apic.c
+++ b/hw/apic.c
@@ -26,6 +26,21 @@
#include "kvm.h"
//#define DEBUG_APIC
+//#define DEBUG_COALESCING
+
+#ifdef DEBUG_APIC
+#define DPRINTF(fmt, ...) \
+ do { printf("apic: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...)
+#endif
+
+#ifdef DEBUG_COALESCING
+#define DPRINTF_C(fmt, ...) \
+ do { printf("apic: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF_C(fmt, ...)
+#endif
/* APIC Local Vector Table */
#define APIC_LVT_TIMER 0
@@ -158,6 +173,8 @@ static void apic_local_deliver(CPUState *env, int vector)
uint32_t lvt = s->lvt[vector];
int trigger_mode;
+ DPRINTF("%s: vector %d delivery mode %d\n", __func__, vector,
+ (lvt >> 8) & 7);
if (lvt & APIC_LVT_MASKED)
return;
@@ -287,6 +304,9 @@ void apic_deliver_irq(uint8_t dest, uint8_t dest_mode,
{
uint32_t deliver_bitmask[MAX_APIC_WORDS];
+ DPRINTF("%s: dest %d dest_mode %d delivery_mode %d vector %d"
+ " polarity %d trigger_mode %d\n", __func__, dest, dest_mode,
+ delivery_mode, vector_num, polarity, trigger_mode);
apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode);
apic_bus_deliver(deliver_bitmask, delivery_mode, vector_num, polarity,
trigger_mode);
@@ -295,9 +315,8 @@ void apic_deliver_irq(uint8_t dest, uint8_t dest_mode,
void cpu_set_apic_base(CPUState *env, uint64_t val)
{
APICState *s = env->apic_state;
-#ifdef DEBUG_APIC
- printf("cpu_set_apic_base: %016" PRIx64 "\n", val);
-#endif
+
+ DPRINTF("cpu_set_apic_base: %016" PRIx64 "\n", val);
if (!s)
return;
s->apicbase = (val & 0xfffff000) |
@@ -313,10 +332,9 @@ void cpu_set_apic_base(CPUState *env, uint64_t val)
uint64_t cpu_get_apic_base(CPUState *env)
{
APICState *s = env->apic_state;
-#ifdef DEBUG_APIC
- printf("cpu_get_apic_base: %016" PRIx64 "\n",
- s ? (uint64_t)s->apicbase: 0);
-#endif
+
+ DPRINTF("cpu_get_apic_base: %016" PRIx64 "\n",
+ s ? (uint64_t)s->apicbase: 0);
return s ? s->apicbase : 0;
}
@@ -386,17 +404,20 @@ static void apic_update_irq(APICState *s)
void apic_reset_irq_delivered(void)
{
+ DPRINTF_C("%s: old coalescing %d\n", __func__, apic_irq_delivered);
apic_irq_delivered = 0;
}
int apic_get_irq_delivered(void)
{
+ DPRINTF_C("%s: returning coalescing %d\n", __func__, apic_irq_delivered);
return apic_irq_delivered;
}
static void apic_set_irq(APICState *s, int vector_num, int trigger_mode)
{
apic_irq_delivered += !get_bit(s->irr, vector_num);
+ DPRINTF_C("%s: coalescing %d\n", __func__, apic_irq_delivered);
set_bit(s->irr, vector_num);
if (trigger_mode)
@@ -755,9 +776,7 @@ static uint32_t apic_mem_readl(void *opaque, target_phys_addr_t addr)
val = 0;
break;
}
-#ifdef DEBUG_APIC
- printf("APIC read: %08x = %08x\n", (uint32_t)addr, val);
-#endif
+ DPRINTF("read: " TARGET_FMT_plx " = %08x\n", addr, val);
return val;
}
@@ -792,9 +811,7 @@ static void apic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
return;
s = env->apic_state;
-#ifdef DEBUG_APIC
- printf("APIC write: %08x = %08x\n", (uint32_t)addr, val);
-#endif
+ DPRINTF("write: " TARGET_FMT_plx " = %08x\n", addr, val);
switch(index) {
case 0x02:
commit 8ac02ff882d48e40571c5b346ceda44dc3925f1b
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sat May 29 20:23:19 2010 +0000
i8259: improve debugging
Add a DPRINTF macro.
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/i8259.c b/hw/i8259.c
index ea48e0e..a995280 100644
--- a/hw/i8259.c
+++ b/hw/i8259.c
@@ -30,6 +30,13 @@
/* debug PIC */
//#define DEBUG_PIC
+#ifdef DEBUG_PIC
+#define DPRINTF(fmt, ...) \
+ do { printf("pic: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...)
+#endif
+
//#define DEBUG_IRQ_LATENCY
//#define DEBUG_IRQ_COUNT
@@ -185,9 +192,7 @@ static void i8259_set_irq(void *opaque, int irq, int level)
#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
if (level != irq_level[irq]) {
-#if defined(DEBUG_PIC)
- printf("i8259_set_irq: irq=%d level=%d\n", irq, level);
-#endif
+ DPRINTF("i8259_set_irq: irq=%d level=%d\n", irq, level);
irq_level[irq] = level;
#ifdef DEBUG_IRQ_COUNT
if (level == 1)
@@ -253,9 +258,7 @@ int pic_read_irq(PicState2 *s)
(double)(qemu_get_clock(vm_clock) -
irq_time[irq]) * 1000000.0 / get_ticks_per_sec());
#endif
-#if defined(DEBUG_PIC)
- printf("pic_interrupt: irq=%d\n", irq);
-#endif
+ DPRINTF("pic_interrupt: irq=%d\n", irq);
return intno;
}
@@ -286,9 +289,7 @@ static void pic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
PicState *s = opaque;
int priority, cmd, irq;
-#ifdef DEBUG_PIC
- printf("pic_write: addr=0x%02x val=0x%02x\n", addr, val);
-#endif
+ DPRINTF("write: addr=0x%02x val=0x%02x\n", addr, val);
addr &= 1;
if (addr == 0) {
if (val & 0x10) {
@@ -416,9 +417,7 @@ static uint32_t pic_ioport_read(void *opaque, uint32_t addr1)
ret = s->imr;
}
}
-#ifdef DEBUG_PIC
- printf("pic_read: addr=0x%02x val=0x%02x\n", addr1, ret);
-#endif
+ DPRINTF("read: addr=0x%02x val=0x%02x\n", addr1, ret);
return ret;
}
commit 03ae77d6d2ba949fa8d0ceaac588a1075b6257b3
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sat May 29 10:20:44 2010 +0000
sparc64: fix user emulator build
Accesses with _nucleus prefix are not available when building user
emulators:
CC sparc64-linux-user/op_helper.o
cc1: warnings being treated as errors
/src/qemu/target-sparc/op_helper.c: In function 'helper_ldda_asi':
/src/qemu/target-sparc/op_helper.c:3063: error: implicit declaration of function 'ldq_nucleus'
Avoid making such accesses. Fixes breakage by 54a3c0f032abf93d1cedc75456af75401ac10360.
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index f468e7b..aaacfc4 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -3056,6 +3056,7 @@ void helper_ldda_asi(target_ulong addr, int asi, int rd)
raise_exception(TT_PRIV_ACT);
switch (asi) {
+#if !defined(CONFIG_USER_ONLY)
case 0x24: // Nucleus quad LDD 128 bit atomic
case 0x2c: // Nucleus quad LDD 128 bit atomic LE
helper_check_align(addr, 0xf);
@@ -3079,6 +3080,7 @@ void helper_ldda_asi(target_ulong addr, int asi, int rd)
}
}
break;
+#endif
default:
helper_check_align(addr, 0x3);
if (rd == 0)
commit 3386376c04533288ff51d8f3a6f0fba77af4d209
Author: Artyom Tarasenko <atar4qemu at googlemail.com>
Date: Sat May 8 16:10:14 2010 +0200
Pad iommu with an empty slot (necessary for SunOS 4.1.4)
On the real hardware (SS-5, LX) the MMU is not padded, but aliased.
Software shouldn't use aliased addresses, neither should it crash
when it uses (on the real hardware it wouldn't). Using empty_slot
instead of aliasing can help with debugging such accesses.
Signed-off-by: Artyom Tarasenko <atar4qemu at googlemail.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 7ba0f76..e4ca8f3 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -93,7 +93,7 @@
#define ESCC_CLOCK 4915200
struct sun4m_hwdef {
- target_phys_addr_t iommu_base, slavio_base;
+ target_phys_addr_t iommu_base, iommu_pad_base, iommu_pad_len, slavio_base;
target_phys_addr_t intctl_base, counter_base, nvram_base, ms_kb_base;
target_phys_addr_t serial_base, fd_base;
target_phys_addr_t afx_base, idreg_base, dma_base, esp_base, le_base;
@@ -854,6 +854,14 @@ static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, ram_addr_t RAM_size,
iommu = iommu_init(hwdef->iommu_base, hwdef->iommu_version,
slavio_irq[30]);
+ if (hwdef->iommu_pad_base) {
+ /* On the real hardware (SS-5, LX) the MMU is not padded, but aliased.
+ Software shouldn't use aliased addresses, neither should it crash
+ when does. Using empty_slot instead of aliasing can help with
+ debugging such accesses */
+ empty_slot_init(hwdef->iommu_pad_base,hwdef->iommu_pad_len);
+ }
+
espdma = sparc32_dma_init(hwdef->dma_base, slavio_irq[18],
iommu, &espdma_irq);
@@ -965,6 +973,8 @@ static const struct sun4m_hwdef sun4m_hwdefs[] = {
/* SS-5 */
{
.iommu_base = 0x10000000,
+ .iommu_pad_base = 0x10004000,
+ .iommu_pad_len = 0x0fffb000,
.tcx_base = 0x50000000,
.cs_base = 0x6c000000,
.slavio_base = 0x70000000,
@@ -1091,6 +1101,8 @@ static const struct sun4m_hwdef sun4m_hwdefs[] = {
/* LX */
{
.iommu_base = 0x10000000,
+ .iommu_pad_base = 0x10004000,
+ .iommu_pad_len = 0x0fffb000,
.tcx_base = 0x50000000,
.slavio_base = 0x70000000,
.ms_kb_base = 0x71000000,
commit 54a3c0f032abf93d1cedc75456af75401ac10360
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date: Sat May 29 01:05:46 2010 +0400
sparc64: fix 128-bit atomic load from nucleus context v1
- change 128-bit atomic loads to reference nucleus context
v0->v1: dropped disassembler change
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index edeeb44..f468e7b 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -3060,19 +3060,19 @@ void helper_ldda_asi(target_ulong addr, int asi, int rd)
case 0x2c: // Nucleus quad LDD 128 bit atomic LE
helper_check_align(addr, 0xf);
if (rd == 0) {
- env->gregs[1] = ldq_kernel(addr + 8);
+ env->gregs[1] = ldq_nucleus(addr + 8);
if (asi == 0x2c)
bswap64s(&env->gregs[1]);
} else if (rd < 8) {
- env->gregs[rd] = ldq_kernel(addr);
- env->gregs[rd + 1] = ldq_kernel(addr + 8);
+ env->gregs[rd] = ldq_nucleus(addr);
+ env->gregs[rd + 1] = ldq_nucleus(addr + 8);
if (asi == 0x2c) {
bswap64s(&env->gregs[rd]);
bswap64s(&env->gregs[rd + 1]);
}
} else {
- env->regwptr[rd] = ldq_kernel(addr);
- env->regwptr[rd + 1] = ldq_kernel(addr + 8);
+ env->regwptr[rd] = ldq_nucleus(addr);
+ env->regwptr[rd + 1] = ldq_nucleus(addr + 8);
if (asi == 0x2c) {
bswap64s(&env->regwptr[rd]);
bswap64s(&env->regwptr[rd + 1]);
commit 68a1c816868b3e35a1da698af412b29e61b1948a
Author: Paul Brook <paul at codesourcery.com>
Date: Sat May 29 02:27:35 2010 +0100
Pre-allocate guest address space
Allow pre-allocation of the guest virtual address space in usermode emulation.
Signed-off-by: Paul Brook <paul at codesourcery.com>
diff --git a/cpu-all.h b/cpu-all.h
index 47a5722..77eaf85 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -627,6 +627,7 @@ static inline void stfq_be_p(void *ptr, float64 v)
#if defined(CONFIG_USE_GUEST_BASE)
extern unsigned long guest_base;
extern int have_guest_base;
+extern unsigned long reserved_va;
#define GUEST_BASE guest_base
#else
#define GUEST_BASE 0ul
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 1f27918..2d920f2 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1682,7 +1682,7 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
* In case where user has not explicitly set the guest_base, we
* probe here that should we set it automatically.
*/
- if (!have_guest_base) {
+ if (!(have_guest_base || reserved_va)) {
/*
* Go through ELF program header table and find the address
* range used by loadable segments. Check that this is available on
diff --git a/linux-user/main.c b/linux-user/main.c
index de1076b..0f23fc9 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -44,6 +44,7 @@ unsigned long mmap_min_addr;
#if defined(CONFIG_USE_GUEST_BASE)
unsigned long guest_base;
int have_guest_base;
+unsigned long reserved_va;
#endif
static const char *interp_prefix = CONFIG_QEMU_PREFIX;
@@ -2610,6 +2611,7 @@ static void usage(void)
"-0 argv0 forces target process argv[0] to be argv0\n"
#if defined(CONFIG_USE_GUEST_BASE)
"-B address set guest_base address to address\n"
+ "-R size reserve size bytes for guest virtual address space\n"
#endif
"\n"
"Debug options:\n"
@@ -2805,6 +2807,39 @@ int main(int argc, char **argv, char **envp)
} else if (!strcmp(r, "B")) {
guest_base = strtol(argv[optind++], NULL, 0);
have_guest_base = 1;
+ } else if (!strcmp(r, "R")) {
+ char *p;
+ int shift = 0;
+ reserved_va = strtoul(argv[optind++], &p, 0);
+ switch (*p) {
+ case 'k':
+ case 'K':
+ shift = 10;
+ break;
+ case 'M':
+ shift = 20;
+ break;
+ case 'G':
+ shift = 30;
+ break;
+ }
+ if (shift) {
+ unsigned long unshifted = reserved_va;
+ p++;
+ reserved_va <<= shift;
+ if (((reserved_va >> shift) != unshifted)
+#if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS
+ || (reserved_va > (1ul << TARGET_VIRT_ADDR_SPACE_BITS))
+#endif
+ ) {
+ fprintf(stderr, "Reserved virtual address too big\n");
+ exit(1);
+ }
+ }
+ if (*p) {
+ fprintf(stderr, "Unrecognised -R size suffix '%s'\n", p);
+ exit(1);
+ }
#endif
} else if (!strcmp(r, "drop-ld-preload")) {
(void) envlist_unsetenv(envlist, "LD_PRELOAD");
@@ -2893,6 +2928,34 @@ int main(int argc, char **argv, char **envp)
* proper page alignment for guest_base.
*/
guest_base = HOST_PAGE_ALIGN(guest_base);
+
+ if (reserved_va) {
+ void *p;
+ int flags;
+
+ flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE;
+ if (have_guest_base) {
+ flags |= MAP_FIXED;
+ }
+ p = mmap((void *)guest_base, reserved_va, PROT_NONE, flags, -1, 0);
+ if (p == MAP_FAILED) {
+ fprintf(stderr, "Unable to reserve guest address space\n");
+ exit(1);
+ }
+ guest_base = (unsigned long)p;
+ /* Make sure the address is properly aligned. */
+ if (guest_base & ~qemu_host_page_mask) {
+ munmap(p, reserved_va);
+ p = mmap((void *)guest_base, reserved_va + qemu_host_page_size,
+ PROT_NONE, flags, -1, 0);
+ if (p == MAP_FAILED) {
+ fprintf(stderr, "Unable to reserve guest address space\n");
+ exit(1);
+ }
+ guest_base = HOST_PAGE_ALIGN((unsigned long)p);
+ }
+ qemu_log("Reserved 0x%lx bytes of guest address space\n", reserved_va);
+ }
#endif /* CONFIG_USE_GUEST_BASE */
/*
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index fd315aa..39da6df 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -216,6 +216,40 @@ static abi_ulong mmap_next_start = TASK_UNMAPPED_BASE;
unsigned long last_brk;
+/* Subroutine of mmap_find_vma, used when we have pre-allocated a chunk
+ of guest address space. */
+static abi_ulong mmap_find_vma_reserved(abi_ulong start, abi_ulong size)
+{
+ abi_ulong addr;
+ abi_ulong last_addr;
+ int prot;
+ int looped = 0;
+
+ if (size > reserved_va) {
+ return (abi_ulong)-1;
+ }
+
+ last_addr = start;
+ for (addr = start; last_addr + size != addr; addr += qemu_host_page_size) {
+ if (last_addr + size >= reserved_va
+ || (abi_ulong)(last_addr + size) < last_addr) {
+ if (looped) {
+ return (abi_ulong)-1;
+ }
+ last_addr = qemu_host_page_size;
+ addr = 0;
+ looped = 1;
+ continue;
+ }
+ prot = page_get_flags(addr);
+ if (prot) {
+ last_addr = addr + qemu_host_page_size;
+ }
+ }
+ mmap_next_start = addr;
+ return last_addr;
+}
+
/*
* Find and reserve a free memory area of size 'size'. The search
* starts at 'start'.
@@ -237,6 +271,10 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size)
size = HOST_PAGE_ALIGN(size);
+ if (reserved_va) {
+ return mmap_find_vma_reserved(start, size);
+ }
+
addr = start;
wrapped = repeat = 0;
prev = 0;
@@ -525,6 +563,47 @@ fail:
return -1;
}
+static void mmap_reserve(abi_ulong start, abi_ulong size)
+{
+ abi_ulong real_start;
+ abi_ulong real_end;
+ abi_ulong addr;
+ abi_ulong end;
+ int prot;
+
+ real_start = start & qemu_host_page_mask;
+ real_end = HOST_PAGE_ALIGN(start + size);
+ end = start + size;
+ if (start > real_start) {
+ /* handle host page containing start */
+ prot = 0;
+ for (addr = real_start; addr < start; addr += TARGET_PAGE_SIZE) {
+ prot |= page_get_flags(addr);
+ }
+ if (real_end == real_start + qemu_host_page_size) {
+ for (addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) {
+ prot |= page_get_flags(addr);
+ }
+ end = real_end;
+ }
+ if (prot != 0)
+ real_start += qemu_host_page_size;
+ }
+ if (end < real_end) {
+ prot = 0;
+ for (addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) {
+ prot |= page_get_flags(addr);
+ }
+ if (prot != 0)
+ real_end -= qemu_host_page_size;
+ }
+ if (real_start != real_end) {
+ mmap(g2h(real_start), real_end - real_start, PROT_NONE,
+ MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE,
+ -1, 0);
+ }
+}
+
int target_munmap(abi_ulong start, abi_ulong len)
{
abi_ulong end, real_start, real_end, addr;
@@ -572,7 +651,11 @@ int target_munmap(abi_ulong start, abi_ulong len)
ret = 0;
/* unmap what we can */
if (real_start < real_end) {
- ret = munmap(g2h(real_start), real_end - real_start);
+ if (reserved_va) {
+ mmap_reserve(real_start, real_end - real_start);
+ } else {
+ ret = munmap(g2h(real_start), real_end - real_start);
+ }
}
if (ret == 0)
@@ -590,12 +673,18 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
mmap_lock();
- if (flags & MREMAP_FIXED)
+ if (flags & MREMAP_FIXED) {
host_addr = (void *) syscall(__NR_mremap, g2h(old_addr),
old_size, new_size,
flags,
- new_addr);
- else if (flags & MREMAP_MAYMOVE) {
+ g2h(new_addr));
+
+ if (reserved_va && host_addr != MAP_FAILED) {
+ /* If new and old addresses overlap then the above mremap will
+ already have failed with EINVAL. */
+ mmap_reserve(old_addr, old_size);
+ }
+ } else if (flags & MREMAP_MAYMOVE) {
abi_ulong mmap_start;
mmap_start = mmap_find_vma(0, new_size);
@@ -603,13 +692,32 @@ abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size,
if (mmap_start == -1) {
errno = ENOMEM;
host_addr = MAP_FAILED;
- } else
+ } else {
host_addr = (void *) syscall(__NR_mremap, g2h(old_addr),
old_size, new_size,
flags | MREMAP_FIXED,
g2h(mmap_start));
+ mmap_reserve(old_addr, old_size);
+ }
} else {
- host_addr = mremap(g2h(old_addr), old_size, new_size, flags);
+ int prot = 0;
+ if (reserved_va && old_size < new_size) {
+ abi_ulong addr;
+ for (addr = old_addr + old_size;
+ addr < old_addr + new_size;
+ addr++) {
+ prot |= page_get_flags(addr);
+ }
+ }
+ if (prot == 0) {
+ host_addr = mremap(g2h(old_addr), old_size, new_size, flags);
+ if (host_addr != MAP_FAILED && reserved_va && old_size > new_size) {
+ mmap_reserve(old_addr + old_size, new_size - old_size);
+ }
+ } else {
+ errno = ENOMEM;
+ host_addr = MAP_FAILED;
+ }
/* Check if address fits target address space */
if ((unsigned long)host_addr + new_size > (abi_ulong)-1) {
/* Revert mremap() changes */
diff --git a/qemu-doc.texi b/qemu-doc.texi
index 6647b7b..e2c8e56 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -2124,7 +2124,7 @@ qemu-i386 /usr/local/qemu-i386/wine/bin/wine \
@subsection Command line options
@example
-usage: qemu-i386 [-h] [-d] [-L path] [-s size] [-cpu model] [-g port] [-B offset] program [arguments...]
+usage: qemu-i386 [-h] [-d] [-L path] [-s size] [-cpu model] [-g port] [-B offset] [-R size] program [arguments...]
@end example
@table @option
@@ -2140,6 +2140,9 @@ Select CPU model (-cpu ? for list and additional feature selection)
Offset guest address by the specified number of bytes. This is useful when
the address region rewuired by guest applications is reserved on the host.
Ths option is currently only supported on some hosts.
+ at item -R size
+Pre-allocate a guest virtual address space of the given size (in bytes).
+"G", "M", and "k" suffixes may be used when specifying the size.
@end table
Debug options:
commit 0be1d07c0e4fa7395aca5129cfc5bb9a0a94a78c
Author: Richard Henderson <rth at twiddle.net>
Date: Fri May 21 10:03:33 2010 -0700
alpha-linux-user: Fill in SI_CODE for SIGSEGV.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/linux-user/main.c b/linux-user/main.c
index b240f29..de1076b 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2433,7 +2433,8 @@ void cpu_loop (CPUState *env)
env->lock_addr = -1;
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
- info.si_code = 0; /* ??? SEGV_MAPERR vs SEGV_ACCERR. */
+ info.si_code = (page_get_flags(env->ipr[IPR_EXC_ADDR]) & PAGE_VALID
+ ? TARGET_SEGV_ACCERR : TARGET_SEGV_MAPERR);
info._sifields._sigfault._addr = env->ipr[IPR_EXC_ADDR];
queue_signal(env, info.si_signo, &info);
break;
commit 680c877af48cf5f2fb4586f34c13fd21ce33bfec
Author: Richard Henderson <rth at twiddle.net>
Date: Fri May 21 10:37:52 2010 -0700
linux-user: Use qemu-malloc.c.
Since we're no longer setting PAGE_RESERVED, there's no need to
implement qemu_malloc via mmap.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/Makefile.target b/Makefile.target
index fda5bf3..d06c679 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -85,7 +85,8 @@ $(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)
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
+ elfload.o linuxload.o uaccess.o gdbstub.o cpu-uname.o \
+ qemu-malloc.o
obj-$(TARGET_HAS_BFLT) += flatload.o
diff --git a/linux-user/mmap.c b/linux-user/mmap.c
index 9c062e7..fd315aa 100644
--- a/linux-user/mmap.c
+++ b/linux-user/mmap.c
@@ -77,58 +77,6 @@ void mmap_unlock(void)
}
#endif
-void *qemu_vmalloc(size_t size)
-{
- void *p;
-
- mmap_lock();
- /* Use map and mark the pages as used. */
- p = mmap(NULL, size, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- mmap_unlock();
- return p;
-}
-
-void *qemu_malloc(size_t size)
-{
- char * p;
- size += 16;
- p = qemu_vmalloc(size);
- *(size_t *)p = size;
- return p + 16;
-}
-
-/* We use map, which is always zero initialized. */
-void * qemu_mallocz(size_t size)
-{
- return qemu_malloc(size);
-}
-
-void qemu_free(void *ptr)
-{
- /* FIXME: We should unmark the reserved pages here. However this gets
- complicated when one target page spans multiple host pages, so we
- don't bother. */
- size_t *p;
- p = (size_t *)((char *)ptr - 16);
- munmap(p, *p);
-}
-
-void *qemu_realloc(void *ptr, size_t size)
-{
- size_t old_size, copy;
- void *new_ptr;
-
- if (!ptr)
- return qemu_malloc(size);
- old_size = *(size_t *)((char *)ptr - 16);
- copy = old_size < size ? old_size : size;
- new_ptr = qemu_malloc(size);
- memcpy(new_ptr, ptr, copy);
- qemu_free(ptr);
- return new_ptr;
-}
-
/* NOTE: all the constants are the HOST ones, but addresses are target. */
int target_mprotect(abi_ulong start, abi_ulong len, int prot)
{
commit 50401022d8fbdcdaf84d28e7b813ee94c2d47325
Author: Richard Henderson <rth at twiddle.net>
Date: Fri May 21 10:37:51 2010 -0700
Use calloc in qemu_mallocz.
Avoids the memset if the allocator has gotten new zeroed
storage from the operating system.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/qemu-malloc.c b/qemu-malloc.c
index 6cdc5de..1b33e04 100644
--- a/qemu-malloc.c
+++ b/qemu-malloc.c
@@ -69,10 +69,10 @@ void *qemu_realloc(void *ptr, size_t size)
void *qemu_mallocz(size_t size)
{
- void *ptr;
- ptr = qemu_malloc(size);
- memset(ptr, 0, size);
- return ptr;
+ if (!size && !allow_zero_malloc()) {
+ abort();
+ }
+ return oom_check(calloc(1, size ? size : 1));
}
char *qemu_strdup(const char *str)
commit 564e2fe8cd63ca6d5413408a1a4f9ee9cf471fff
Author: Riccardo Magliocchetti <riccardo.magliocchetti at gmail.com>
Date: Wed May 19 21:49:21 2010 +0200
linux-user: Fix compilation with DEBUG defined
Signed-off-by: Riccardo Magliocchetti <riccardo.magliocchetti at gmail.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/linux-user/flatload.c b/linux-user/flatload.c
index 6a2c3f9..914de1f 100644
--- a/linux-user/flatload.c
+++ b/linux-user/flatload.c
@@ -338,7 +338,7 @@ failed:
static void old_reloc(struct lib_info *libinfo, uint32_t rl)
{
#ifdef DEBUG
- char *segment[] = { "TEXT", "DATA", "BSS", "*UNKNOWN*" };
+ const char *segment[] = { "TEXT", "DATA", "BSS", "*UNKNOWN*" };
#endif
uint32_t *ptr;
uint32_t offset;
commit 82f24fccaa9ef21e369d77e32bae20bcdc915947
Author: Riccardo Magliocchetti <riccardo.magliocchetti at gmail.com>
Date: Wed May 19 18:49:30 2010 +0200
Fix hw/gt64xxx.c compilation with DEBUG defined
Use TARGET_FMT_plx as format placeholder for target_phys_addr_t
Signed-off-by: Riccardo Magliocchetti <riccardo.magliocchetti at gmail.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
index 55971b9..7691e1d 100644
--- a/hw/gt64xxx.c
+++ b/hw/gt64xxx.c
@@ -276,7 +276,7 @@ static void gt64120_isd_mapping(GT64120State *s)
check_reserved_space(&start, &length);
length = 0x1000;
/* Map new address */
- DPRINTF("ISD: %x@%x -> %x@%x, %x\n", s->ISD_length, s->ISD_start,
+ DPRINTF("ISD: "TARGET_FMT_plx"@"TARGET_FMT_plx" -> "TARGET_FMT_plx"@"TARGET_FMT_plx", %x\n", s->ISD_length, s->ISD_start,
length, start, s->ISD_handle);
s->ISD_start = start;
s->ISD_length = length;
commit 3c05613a6a51da833105c1bf3db4917d917f5a3a
Author: Riccardo Magliocchetti <riccardo.magliocchetti at gmail.com>
Date: Wed May 19 18:49:28 2010 +0200
Fix typo in balloon help
Fix launchpad #563883
Signed-off-by: Riccardo Magliocchetti <riccardo.magliocchetti at gmail.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index e30b250..f4f88df 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -987,7 +987,7 @@ ETEXI
.name = "balloon",
.args_type = "value:M",
.params = "target",
- .help = "request VM to change it's memory allocation (in MB)",
+ .help = "request VM to change its memory allocation (in MB)",
.user_print = monitor_user_noop,
.mhandler.cmd_async = do_balloon,
.async = 1,
commit c1735af1df50b1837241053393c73a5296d2cf7f
Author: Jan Kiszka <jan.kiszka at web.de>
Date: Thu May 13 15:09:58 2010 +0200
musicpal: Drop redundant reset call
Reset is now triggered after init, no need for explicit calls anymore.
Signed-off-by: Jan Kiszka <jan.kiszka at web.de>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/musicpal.c b/hw/musicpal.c
index ebd933e..d44c5a0 100644
--- a/hw/musicpal.c
+++ b/hw/musicpal.c
@@ -1295,8 +1295,6 @@ static int musicpal_gpio_init(SysBusDevice *dev)
musicpal_gpio_writefn, s);
sysbus_init_mmio(dev, MP_GPIO_SIZE, iomemtype);
- musicpal_gpio_reset(&dev->qdev);
-
qdev_init_gpio_out(&dev->qdev, s->out, ARRAY_SIZE(s->out));
qdev_init_gpio_in(&dev->qdev, musicpal_gpio_pin_event, 32);
commit d8e06f973cc8e42aa1faa1216592aa9eb671f360
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date: Wed May 12 15:10:56 2010 +0100
doc: Update monitor info subcommands
The "info blockstats" documentation was copy-pasted as "info block"
instead of "info blockstats". The documentation for "commands", "jit",
"numa", "qdm", and "roms" is missing. This patch resolves these issues
in qemu-monitor.hx.
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index b6e3467..e30b250 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -54,13 +54,15 @@ Show various information about the system state.
@table @option
@item info version
show the version of QEMU
+ at item info commands
+list QMP available commands
@item info network
show the various VLANs and the associated devices
@item info chardev
show the character devices
@item info block
show the block devices
- at item info block
+ at item info blockstats
show block device statistics
@item info registers
show the cpu registers
@@ -80,8 +82,12 @@ show virtual to physical memory mappings (i386 only)
show the active virtual memory mappings (i386 only)
@item info hpet
show state of HPET (i386 only)
+ at item info jit
+show dynamic compiler info
@item info kvm
show KVM information
+ at item info numa
+show NUMA information
@item info usb
show USB devices plugged on the virtual USB hub
@item info usbhost
@@ -114,6 +120,10 @@ show migration status
show balloon information
@item info qtree
show device tree
+ at item info qdm
+show qdev device model list
+ at item info roms
+show roms
@end table
ETEXI
commit 97679527bf2f002225d08cfb93f840cef449ac0e
Author: Avi Kivity <avi at redhat.com>
Date: Sun May 9 14:51:13 2010 +0300
Fix overflow in i440fx_init()
The ram_size parameter can be larger than an int, so it may be truncated.
Fix by using the correct type.
Signed-off-by: Avi Kivity <avi at redhat.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/pc.h b/hw/pc.h
index 73cccef..0e52933 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -135,7 +135,7 @@ int pcspk_audio_init(qemu_irq *pic);
struct PCII440FXState;
typedef struct PCII440FXState PCII440FXState;
-PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn, qemu_irq *pic, int ram_size);
+PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix_devfn, qemu_irq *pic, ram_addr_t ram_size);
void i440fx_init_memory_mappings(PCII440FXState *d);
/* piix4.c */
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index aff7f6d..d14d05e 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -216,7 +216,7 @@ static int i440fx_initfn(PCIDevice *dev)
return 0;
}
-PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn, qemu_irq *pic, int ram_size)
+PCIBus *i440fx_init(PCII440FXState **pi440fx_state, int *piix3_devfn, qemu_irq *pic, ram_addr_t ram_size)
{
DeviceState *dev;
PCIBus *b;
commit 9ba8c3f41d47f2051ea4bdb7156978f941ea7324
Author: Lars Munch <lars at segv.dk>
Date: Sat May 8 22:42:43 2010 +0200
arm: prevent coprocessor IO reset
This prevent coprocessor IO structure from being reset on cpu reset. This was
a problem for PXA which uses coprocessor 6 and 14.
Signed-off-by: Lars Munch <lars at segv.dk>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 1e34541..f3d138d 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -148,13 +148,6 @@ typedef struct CPUARMState {
int pending_exception;
} v7m;
- /* Coprocessor IO used by peripherals */
- struct {
- ARMReadCPFunc *cp_read;
- ARMWriteCPFunc *cp_write;
- void *opaque;
- } cp[15];
-
/* Thumb-2 EE state. */
uint32_t teecr;
uint32_t teehbr;
@@ -204,6 +197,13 @@ typedef struct CPUARMState {
CPU_COMMON
/* These fields after the common ones so they are preserved on reset. */
+
+ /* Coprocessor IO used by peripherals */
+ struct {
+ ARMReadCPFunc *cp_read;
+ ARMWriteCPFunc *cp_write;
+ void *opaque;
+ } cp[15];
void *nvic;
struct arm_boot_info *boot_info;
} CPUARMState;
commit 3e1dbaddbf199762deaf00e3b3308f7508671e35
Author: Richard Henderson <rth at twiddle.net>
Date: Mon May 3 16:30:48 2010 -0700
tcg: Use INDEX_op_qemu_ld32 for 32-bit results.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index bafac2b..aa436de 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -2172,12 +2172,20 @@ static inline void tcg_gen_qemu_ld16s(TCGv ret, TCGv addr, int mem_index)
static inline void tcg_gen_qemu_ld32u(TCGv ret, TCGv addr, int mem_index)
{
+#if TARGET_LONG_BITS == 32
+ tcg_gen_qemu_ldst_op(INDEX_op_qemu_ld32, ret, addr, mem_index);
+#else
tcg_gen_qemu_ldst_op(INDEX_op_qemu_ld32u, ret, addr, mem_index);
+#endif
}
static inline void tcg_gen_qemu_ld32s(TCGv ret, TCGv addr, int mem_index)
{
+#if TARGET_LONG_BITS == 32
+ tcg_gen_qemu_ldst_op(INDEX_op_qemu_ld32, ret, addr, mem_index);
+#else
tcg_gen_qemu_ldst_op(INDEX_op_qemu_ld32s, ret, addr, mem_index);
+#endif
}
static inline void tcg_gen_qemu_ld64(TCGv_i64 ret, TCGv addr, int mem_index)
commit 1a396859105c4c27fdec08180be26288b8a629a3
Author: Nicholas A. Bellinger <nab at linux-iscsi.org>
Date: Thu May 27 08:56:28 2010 -0700
block: Add missing bdrv_delete() for SG_IO BlockDriver in find_image_format()
This patch adds a missing bdrv_delete() call in find_image_format() so that a
SG_IO BlockDriver properly releases the temporary BlockDriverState *bs created
from bdrv_file_open()
Signed-off-by: Nicholas A. Bellinger <nab at linux-iscsi.org>
Reported-by: Chris Krumme <chris.krumme at windriver.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block.c b/block.c
index 24c63f6..296de89 100644
--- a/block.c
+++ b/block.c
@@ -332,8 +332,10 @@ static BlockDriver *find_image_format(const char *filename)
return NULL;
/* Return the raw BlockDriver * to scsi-generic devices */
- if (bs->sg)
+ if (bs->sg) {
+ bdrv_delete(bs);
return bdrv_find_format("raw");
+ }
ret = bdrv_pread(bs, 0, buf, sizeof(buf));
bdrv_delete(bs);
commit 86fa8da83771238de55dc44819a1a27bafef5353
Author: Kevin Wolf <kwolf at redhat.com>
Date: Fri May 28 12:21:27 2010 +0200
qcow2: Fix corruption after error in update_refcount
After it is done with updating refcounts in the cache, update_refcount writes
all changed entries to disk. If a refcount block allocation fails, however,
there was no change yet and therefore first_index = last_index = -1. Don't
treat -1 as a normal sector index (resulting in a 512 byte write!) but return
without updating anything in this case.
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 5b7cda4..22b0b45 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -417,6 +417,10 @@ static int write_refcount_block_entries(BlockDriverState *bs,
return 0;
}
+ if (first_index < 0) {
+ return 0;
+ }
+
first_index &= ~(REFCOUNTS_PER_SECTOR - 1);
last_index = (last_index + REFCOUNTS_PER_SECTOR)
& ~(REFCOUNTS_PER_SECTOR - 1);
commit 25408c09502be036e5575754fe54019ed4ed5dfa
Author: Kevin Wolf <kwolf at redhat.com>
Date: Fri May 28 12:05:45 2010 +0200
qcow2: Fix corruption after refblock allocation
Refblock allocation code needs to take into consideration that update_refcount
will load a different refcount block into the cache, so it must initialize the
cache for a new refcount block only afterwards. Not doing this means that not
only the refcount in the wrong block is updated, but also that the caller will
work on the wrong block.
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index a7f295d..5b7cda4 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -221,8 +221,6 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
/* Allocate the refcount block itself and mark it as used */
uint64_t new_block = alloc_clusters_noref(bs, s->cluster_size);
- memset(s->refcount_block_cache, 0, s->cluster_size);
- s->refcount_block_cache_offset = new_block;
#ifdef DEBUG_ALLOC2
fprintf(stderr, "qcow2: Allocate refcount block %d for %" PRIx64
@@ -231,6 +229,10 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
#endif
if (in_same_refcount_block(s, new_block, cluster_index << s->cluster_bits)) {
+ /* Zero the new refcount block before updating it */
+ memset(s->refcount_block_cache, 0, s->cluster_size);
+ s->refcount_block_cache_offset = new_block;
+
/* The block describes itself, need to update the cache */
int block_index = (new_block >> s->cluster_bits) &
((1 << (s->cluster_bits - REFCOUNT_SHIFT)) - 1);
@@ -242,6 +244,11 @@ static int64_t alloc_refcount_block(BlockDriverState *bs, int64_t cluster_index)
if (ret < 0) {
goto fail_block;
}
+
+ /* Initialize the new refcount block only after updating its refcount,
+ * update_refcount uses the refcount cache itself */
+ memset(s->refcount_block_cache, 0, s->cluster_size);
+ s->refcount_block_cache_offset = new_block;
}
/* Now the new refcount block needs to be written to disk */
commit ed0df867d93341289d085ed9e9d44907e342c7ff
Author: Kevin Wolf <kwolf at redhat.com>
Date: Fri May 28 09:47:44 2010 +0200
qcow2: Return right error code in write_refcount_block_entries
write_refcount_block_entries used to return -EIO for any errors. Change this to
return the real error code.
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index 744107c..a7f295d 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -404,6 +404,7 @@ static int write_refcount_block_entries(BlockDriverState *bs,
{
BDRVQcowState *s = bs->opaque;
size_t size;
+ int ret;
if (cache_refcount_updates) {
return 0;
@@ -414,12 +415,13 @@ static int write_refcount_block_entries(BlockDriverState *bs,
& ~(REFCOUNTS_PER_SECTOR - 1);
size = (last_index - first_index) << REFCOUNT_SHIFT;
+
BLKDBG_EVENT(bs->file, BLKDBG_REFBLOCK_UPDATE_PART);
- if (bdrv_pwrite(bs->file,
+ ret = bdrv_pwrite(bs->file,
refcount_block_offset + (first_index << REFCOUNT_SHIFT),
- &s->refcount_block_cache[first_index], size) != size)
- {
- return -EIO;
+ &s->refcount_block_cache[first_index], size);
+ if (ret < 0) {
+ return ret;
}
return 0;
@@ -460,10 +462,10 @@ static int QEMU_WARN_UNUSED_RESULT update_refcount(BlockDriverState *bs,
table_index = cluster_index >> (s->cluster_bits - REFCOUNT_SHIFT);
if ((old_table_index >= 0) && (table_index != old_table_index)) {
- if (write_refcount_block_entries(bs, refcount_block_offset,
- first_index, last_index) < 0)
- {
- return -EIO;
+ ret = write_refcount_block_entries(bs, refcount_block_offset,
+ first_index, last_index);
+ if (ret < 0) {
+ return ret;
}
first_index = -1;
@@ -505,10 +507,11 @@ fail:
/* Write last changed block to disk */
if (refcount_block_offset != 0) {
- if (write_refcount_block_entries(bs, refcount_block_offset,
- first_index, last_index) < 0)
- {
- return ret < 0 ? ret : -EIO;
+ int wret;
+ wret = write_refcount_block_entries(bs, refcount_block_offset,
+ first_index, last_index);
+ if (wret < 0) {
+ return ret < 0 ? ret : wret;
}
}
commit 55c17e9821c474d5fcdebdc82ed2fc096777d611
Author: Kevin Wolf <kwolf at redhat.com>
Date: Fri May 21 18:25:20 2010 +0200
qcow2: Change l2_load to return 0/-errno
Provide the error code to the caller instead of just indicating success/error.
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index ea98afc..03a9f25 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -157,31 +157,36 @@ static uint64_t *seek_l2_table(BDRVQcowState *s, uint64_t l2_offset)
* the image file failed.
*/
-static uint64_t *l2_load(BlockDriverState *bs, uint64_t l2_offset)
+static int l2_load(BlockDriverState *bs, uint64_t l2_offset,
+ uint64_t **l2_table)
{
BDRVQcowState *s = bs->opaque;
int min_index;
- uint64_t *l2_table;
+ int ret;
/* seek if the table for the given offset is in the cache */
- l2_table = seek_l2_table(s, l2_offset);
- if (l2_table != NULL)
- return l2_table;
+ *l2_table = seek_l2_table(s, l2_offset);
+ if (*l2_table != NULL) {
+ return 0;
+ }
/* not found: load a new entry in the least used one */
min_index = l2_cache_new_entry(bs);
- l2_table = s->l2_cache + (min_index << s->l2_bits);
+ *l2_table = s->l2_cache + (min_index << s->l2_bits);
BLKDBG_EVENT(bs->file, BLKDBG_L2_LOAD);
- if (bdrv_pread(bs->file, l2_offset, l2_table, s->l2_size * sizeof(uint64_t)) !=
- s->l2_size * sizeof(uint64_t))
- return NULL;
+ ret = bdrv_pread(bs->file, l2_offset, *l2_table,
+ s->l2_size * sizeof(uint64_t));
+ if (ret < 0) {
+ return ret;
+ }
+
s->l2_cache_offsets[min_index] = l2_offset;
s->l2_cache_counts[min_index] = 1;
- return l2_table;
+ return 0;
}
/*
@@ -440,6 +445,7 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
int l1_bits, c;
unsigned int index_in_cluster, nb_clusters;
uint64_t nb_available, nb_needed;
+ int ret;
index_in_cluster = (offset >> 9) & (s->cluster_sectors - 1);
nb_needed = *num + index_in_cluster;
@@ -478,9 +484,9 @@ int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
/* load the l2 table in memory */
l2_offset &= ~QCOW_OFLAG_COPIED;
- l2_table = l2_load(bs, l2_offset);
- if (l2_table == NULL) {
- return -EIO;
+ ret = l2_load(bs, l2_offset, &l2_table);
+ if (ret < 0) {
+ return ret;
}
/* find the cluster offset for the given disk offset */
@@ -547,9 +553,9 @@ static int get_cluster_table(BlockDriverState *bs, uint64_t offset,
if (l2_offset & QCOW_OFLAG_COPIED) {
/* load the l2 table in memory */
l2_offset &= ~QCOW_OFLAG_COPIED;
- l2_table = l2_load(bs, l2_offset);
- if (l2_table == NULL) {
- return -EIO;
+ ret = l2_load(bs, l2_offset, &l2_table);
+ if (ret < 0) {
+ return ret;
}
} else {
if (l2_offset)
commit 1c46efaa0a175e468772405385ca26a1e35dd94c
Author: Kevin Wolf <kwolf at redhat.com>
Date: Fri May 21 17:59:36 2010 +0200
qcow2: Allow qcow2_get_cluster_offset to return errors
qcow2_get_cluster_offset() looks up a given virtual disk offset and returns the
offset of the corresponding cluster in the image file. Errors (e.g. L2 table
can't be read) are currenctly indicated by a return value of 0, which is
unfortuately the same as for any unallocated cluster. So in effect we can't
check for errors.
This makes the old return value a by-reference parameter and returns the usual
0/-errno error code.
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index 244b4a7..ea98afc 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -345,7 +345,13 @@ static int qcow_read(BlockDriverState *bs, int64_t sector_num,
while (nb_sectors > 0) {
n = nb_sectors;
- cluster_offset = qcow2_get_cluster_offset(bs, sector_num << 9, &n);
+
+ ret = qcow2_get_cluster_offset(bs, sector_num << 9, &n,
+ &cluster_offset);
+ if (ret < 0) {
+ return ret;
+ }
+
index_in_cluster = sector_num & (s->cluster_sectors - 1);
if (!cluster_offset) {
if (bs->backing_hd) {
@@ -412,25 +418,25 @@ static int copy_sectors(BlockDriverState *bs, uint64_t start_sect,
/*
* get_cluster_offset
*
- * For a given offset of the disk image, return cluster offset in
- * qcow2 file.
+ * For a given offset of the disk image, find the cluster offset in
+ * qcow2 file. The offset is stored in *cluster_offset.
*
* on entry, *num is the number of contiguous clusters we'd like to
* access following offset.
*
* on exit, *num is the number of contiguous clusters we can read.
*
- * Return 1, if the offset is found
- * Return 0, otherwise.
+ * Return 0, if the offset is found
+ * Return -errno, otherwise.
*
*/
-uint64_t qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
- int *num)
+int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
+ int *num, uint64_t *cluster_offset)
{
BDRVQcowState *s = bs->opaque;
unsigned int l1_index, l2_index;
- uint64_t l2_offset, *l2_table, cluster_offset;
+ uint64_t l2_offset, *l2_table;
int l1_bits, c;
unsigned int index_in_cluster, nb_clusters;
uint64_t nb_available, nb_needed;
@@ -454,7 +460,7 @@ uint64_t qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
nb_needed = nb_available;
}
- cluster_offset = 0;
+ *cluster_offset = 0;
/* seek the the l2 offset in the l1 table */
@@ -473,16 +479,17 @@ uint64_t qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
l2_offset &= ~QCOW_OFLAG_COPIED;
l2_table = l2_load(bs, l2_offset);
- if (l2_table == NULL)
- return 0;
+ if (l2_table == NULL) {
+ return -EIO;
+ }
/* find the cluster offset for the given disk offset */
l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
- cluster_offset = be64_to_cpu(l2_table[l2_index]);
+ *cluster_offset = be64_to_cpu(l2_table[l2_index]);
nb_clusters = size_to_clusters(s, nb_needed << 9);
- if (!cluster_offset) {
+ if (!*cluster_offset) {
/* how many empty clusters ? */
c = count_contiguous_free_clusters(nb_clusters, &l2_table[l2_index]);
} else {
@@ -498,7 +505,8 @@ out:
*num = nb_available - index_in_cluster;
- return cluster_offset & ~QCOW_OFLAG_COPIED;
+ *cluster_offset &=~QCOW_OFLAG_COPIED;
+ return 0;
}
/*
diff --git a/block/qcow2.c b/block/qcow2.c
index 5b72758..33fa9a9 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -297,9 +297,15 @@ static int qcow_is_allocated(BlockDriverState *bs, int64_t sector_num,
int nb_sectors, int *pnum)
{
uint64_t cluster_offset;
+ int ret;
*pnum = nb_sectors;
- cluster_offset = qcow2_get_cluster_offset(bs, sector_num << 9, pnum);
+ /* FIXME We can get errors here, but the bdrv_is_allocated interface can't
+ * pass them on today */
+ ret = qcow2_get_cluster_offset(bs, sector_num << 9, pnum, &cluster_offset);
+ if (ret < 0) {
+ *pnum = 0;
+ }
return (cluster_offset != 0);
}
@@ -409,8 +415,12 @@ static void qcow_aio_read_cb(void *opaque, int ret)
/* prepare next AIO request */
acb->cur_nr_sectors = acb->remaining_sectors;
- acb->cluster_offset = qcow2_get_cluster_offset(bs, acb->sector_num << 9,
- &acb->cur_nr_sectors);
+ ret = qcow2_get_cluster_offset(bs, acb->sector_num << 9,
+ &acb->cur_nr_sectors, &acb->cluster_offset);
+ if (ret < 0) {
+ goto done;
+ }
+
index_in_cluster = acb->sector_num & (s->cluster_sectors - 1);
if (!acb->cluster_offset) {
diff --git a/block/qcow2.h b/block/qcow2.h
index 01053b7..c59b827 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -196,8 +196,8 @@ void qcow2_encrypt_sectors(BDRVQcowState *s, int64_t sector_num,
int nb_sectors, int enc,
const AES_KEY *key);
-uint64_t qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
- int *num);
+int qcow2_get_cluster_offset(BlockDriverState *bs, uint64_t offset,
+ int *num, uint64_t *cluster_offset);
int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
int n_start, int n_end, int *num, QCowL2Meta *m);
uint64_t qcow2_alloc_compressed_cluster_offset(BlockDriverState *bs,
commit c63782cbe8bdc2c401ea710cef427de0214c5900
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Thu May 27 15:46:55 2010 +0200
block.h: Make BDRV_SECTOR_SIZE 64 bit safe
C defaults to int, so make definition of BDRV_SECTOR_SIZE 64 bit
safe as it and BDRV_SECTOR_MASK may be used against 64 bit addresses.
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block.h b/block.h
index 9034ebb..756670d 100644
--- a/block.h
+++ b/block.h
@@ -38,7 +38,7 @@ typedef struct QEMUSnapshotInfo {
#define BDRV_O_CACHE_MASK (BDRV_O_NOCACHE | BDRV_O_CACHE_WB)
#define BDRV_SECTOR_BITS 9
-#define BDRV_SECTOR_SIZE (1 << BDRV_SECTOR_BITS)
+#define BDRV_SECTOR_SIZE (1ULL << BDRV_SECTOR_BITS)
#define BDRV_SECTOR_MASK ~(BDRV_SECTOR_SIZE - 1)
typedef enum {
commit b587a52c007efb9e100d99fa6c78461ad1901973
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date: Thu May 27 12:52:08 2010 +0100
posix-aio-compat: Expand tabs that have crept in
This patch expands tabs on a few lines so the code formats nicely and
follows the QEMU coding style.
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/posix-aio-compat.c b/posix-aio-compat.c
index b43c531..a67ffe3 100644
--- a/posix-aio-compat.c
+++ b/posix-aio-compat.c
@@ -35,7 +35,7 @@ struct qemu_paiocb {
int aio_fildes;
union {
struct iovec *aio_iov;
- void *aio_ioctl_buf;
+ void *aio_ioctl_buf;
};
int aio_niov;
size_t aio_nbytes;
@@ -119,21 +119,21 @@ static void thread_create(pthread_t *thread, pthread_attr_t *attr,
static ssize_t handle_aiocb_ioctl(struct qemu_paiocb *aiocb)
{
- int ret;
-
- ret = ioctl(aiocb->aio_fildes, aiocb->aio_ioctl_cmd, aiocb->aio_ioctl_buf);
- if (ret == -1)
- return -errno;
-
- /*
- * This looks weird, but the aio code only consideres a request
- * successfull if it has written the number full number of bytes.
- *
- * Now we overload aio_nbytes as aio_ioctl_cmd for the ioctl command,
- * so in fact we return the ioctl command here to make posix_aio_read()
- * happy..
- */
- return aiocb->aio_nbytes;
+ int ret;
+
+ ret = ioctl(aiocb->aio_fildes, aiocb->aio_ioctl_cmd, aiocb->aio_ioctl_buf);
+ if (ret == -1)
+ return -errno;
+
+ /*
+ * This looks weird, but the aio code only consideres a request
+ * successfull if it has written the number full number of bytes.
+ *
+ * Now we overload aio_nbytes as aio_ioctl_cmd for the ioctl command,
+ * so in fact we return the ioctl command here to make posix_aio_read()
+ * happy..
+ */
+ return aiocb->aio_nbytes;
}
static ssize_t handle_aiocb_flush(struct qemu_paiocb *aiocb)
@@ -249,10 +249,10 @@ static ssize_t handle_aiocb_rw(struct qemu_paiocb *aiocb)
* Try preadv/pwritev first and fall back to linearizing the
* buffer if it's not supported.
*/
- if (preadv_present) {
+ if (preadv_present) {
nbytes = handle_aiocb_rw_vector(aiocb);
if (nbytes == aiocb->aio_nbytes)
- return nbytes;
+ return nbytes;
if (nbytes < 0 && nbytes != -ENOSYS)
return nbytes;
preadv_present = 0;
@@ -335,19 +335,19 @@ static void *aio_thread(void *unused)
switch (aiocb->aio_type & QEMU_AIO_TYPE_MASK) {
case QEMU_AIO_READ:
case QEMU_AIO_WRITE:
- ret = handle_aiocb_rw(aiocb);
- break;
+ ret = handle_aiocb_rw(aiocb);
+ break;
case QEMU_AIO_FLUSH:
- ret = handle_aiocb_flush(aiocb);
- break;
+ ret = handle_aiocb_flush(aiocb);
+ break;
case QEMU_AIO_IOCTL:
- ret = handle_aiocb_ioctl(aiocb);
- break;
- default:
- fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type);
- ret = -EINVAL;
- break;
- }
+ ret = handle_aiocb_ioctl(aiocb);
+ break;
+ default:
+ fprintf(stderr, "invalid aio request (0x%x)\n", aiocb->aio_type);
+ ret = -EINVAL;
+ break;
+ }
mutex_lock(&lock);
aiocb->ret = ret;
commit dc33bb341122623105573d47fa6d71a0ba5ff15c
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Wed May 26 10:44:44 2010 +0200
drive: allow rerror, werror and readonly for if=none
When creating guest disks the qdev way using ...
-drive if=none,id=$name,args
-device $driver,drive=$name
it is not possible to specify rerror, werror and readonly arguments
for drive as drive_init allows/blocks them based on the interface (if=)
specified and none isn't white-listed there.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/vl.c b/vl.c
index 417554f..7121cd0 100644
--- a/vl.c
+++ b/vl.c
@@ -953,7 +953,7 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque,
on_write_error = BLOCK_ERR_STOP_ENOSPC;
if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
- if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO) {
+ if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
fprintf(stderr, "werror is no supported by this format\n");
return NULL;
}
@@ -966,7 +966,7 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque,
on_read_error = BLOCK_ERR_REPORT;
if ((buf = qemu_opt_get(opts, "rerror")) != NULL) {
- if (type != IF_IDE && type != IF_VIRTIO) {
+ if (type != IF_IDE && type != IF_VIRTIO && type != IF_NONE) {
fprintf(stderr, "rerror is no supported by this format\n");
return NULL;
}
@@ -1114,7 +1114,7 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque,
/* CDROM is fine for any interface, don't check. */
ro = 1;
} else if (ro == 1) {
- if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY) {
+ if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY && type != IF_NONE) {
fprintf(stderr, "qemu: readonly flag not supported for drive with this interface\n");
return NULL;
}
commit b50cbabc1bc12e6b0082089c70015c1b97db86a1
Author: MORITA Kazutaka <morita.kazutaka at lab.ntt.co.jp>
Date: Wed May 26 11:35:36 2010 +0900
add support for protocol driver create_options
This patch enables protocol drivers to use their create options which
are not supported by the format. For example, protcol drivers can use
a backing_file option with raw format.
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.c b/block.c
index 47be5ba..24c63f6 100644
--- a/block.c
+++ b/block.c
@@ -56,7 +56,6 @@ static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors);
static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
const uint8_t *buf, int nb_sectors);
-static BlockDriver *find_protocol(const char *filename);
static QTAILQ_HEAD(, BlockDriverState) bdrv_states =
QTAILQ_HEAD_INITIALIZER(bdrv_states);
@@ -210,7 +209,7 @@ int bdrv_create_file(const char* filename, QEMUOptionParameter *options)
{
BlockDriver *drv;
- drv = find_protocol(filename);
+ drv = bdrv_find_protocol(filename);
if (drv == NULL) {
drv = bdrv_find_format("file");
}
@@ -283,7 +282,7 @@ static BlockDriver *find_hdev_driver(const char *filename)
return drv;
}
-static BlockDriver *find_protocol(const char *filename)
+BlockDriver *bdrv_find_protocol(const char *filename)
{
BlockDriver *drv1;
char protocol[128];
@@ -478,7 +477,7 @@ int bdrv_file_open(BlockDriverState **pbs, const char *filename, int flags)
BlockDriver *drv;
int ret;
- drv = find_protocol(filename);
+ drv = bdrv_find_protocol(filename);
if (!drv) {
return -ENOENT;
}
diff --git a/block.h b/block.h
index 24efeb6..9034ebb 100644
--- a/block.h
+++ b/block.h
@@ -54,6 +54,7 @@ void bdrv_info_stats(Monitor *mon, QObject **ret_data);
void bdrv_init(void);
void bdrv_init_with_whitelist(void);
+BlockDriver *bdrv_find_protocol(const char *filename);
BlockDriver *bdrv_find_format(const char *format_name);
BlockDriver *bdrv_find_whitelisted_format(const char *format_name);
int bdrv_create(BlockDriver *drv, const char* filename,
diff --git a/qemu-img.c b/qemu-img.c
index cb007b7..ea091f0 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -252,8 +252,8 @@ static int img_create(int argc, char **argv)
const char *base_fmt = NULL;
const char *filename;
const char *base_filename = NULL;
- BlockDriver *drv;
- QEMUOptionParameter *param = NULL;
+ BlockDriver *drv, *proto_drv;
+ QEMUOptionParameter *param = NULL, *create_options = NULL;
char *options = NULL;
flags = 0;
@@ -286,33 +286,42 @@ static int img_create(int argc, char **argv)
}
}
+ /* Get the filename */
+ if (optind >= argc)
+ help();
+ filename = argv[optind++];
+
/* Find driver and parse its options */
drv = bdrv_find_format(fmt);
if (!drv)
error("Unknown file format '%s'", fmt);
+ proto_drv = bdrv_find_protocol(filename);
+ if (!proto_drv)
+ error("Unknown protocol '%s'", filename);
+
+ create_options = append_option_parameters(create_options,
+ drv->create_options);
+ create_options = append_option_parameters(create_options,
+ proto_drv->create_options);
+
if (options && !strcmp(options, "?")) {
- print_option_help(drv->create_options);
+ print_option_help(create_options);
return 0;
}
/* Create parameter list with default values */
- param = parse_option_parameters("", drv->create_options, param);
+ param = parse_option_parameters("", create_options, param);
set_option_parameter_int(param, BLOCK_OPT_SIZE, -1);
/* Parse -o options */
if (options) {
- param = parse_option_parameters(options, drv->create_options, param);
+ param = parse_option_parameters(options, create_options, param);
if (param == NULL) {
error("Invalid options for file format '%s'.", fmt);
}
}
- /* Get the filename */
- if (optind >= argc)
- help();
- filename = argv[optind++];
-
/* Add size to parameters */
if (optind < argc) {
set_option_parameter(param, BLOCK_OPT_SIZE, argv[optind++]);
@@ -362,6 +371,7 @@ static int img_create(int argc, char **argv)
puts("");
ret = bdrv_create(drv, filename, param);
+ free_option_parameters(create_options);
free_option_parameters(param);
if (ret < 0) {
@@ -543,14 +553,14 @@ static int img_convert(int argc, char **argv)
{
int c, ret, n, n1, bs_n, bs_i, flags, cluster_size, cluster_sectors;
const char *fmt, *out_fmt, *out_baseimg, *out_filename;
- BlockDriver *drv;
+ BlockDriver *drv, *proto_drv;
BlockDriverState **bs, *out_bs;
int64_t total_sectors, nb_sectors, sector_num, bs_offset;
uint64_t bs_sectors;
uint8_t * buf;
const uint8_t *buf1;
BlockDriverInfo bdi;
- QEMUOptionParameter *param = NULL;
+ QEMUOptionParameter *param = NULL, *create_options = NULL;
char *options = NULL;
fmt = NULL;
@@ -615,19 +625,27 @@ static int img_convert(int argc, char **argv)
if (!drv)
error("Unknown file format '%s'", out_fmt);
+ proto_drv = bdrv_find_protocol(out_filename);
+ if (!proto_drv)
+ error("Unknown protocol '%s'", out_filename);
+
+ create_options = append_option_parameters(create_options,
+ drv->create_options);
+ create_options = append_option_parameters(create_options,
+ proto_drv->create_options);
if (options && !strcmp(options, "?")) {
- print_option_help(drv->create_options);
+ print_option_help(create_options);
free(bs);
return 0;
}
if (options) {
- param = parse_option_parameters(options, drv->create_options, param);
+ param = parse_option_parameters(options, create_options, param);
if (param == NULL) {
error("Invalid options for file format '%s'.", out_fmt);
}
} else {
- param = parse_option_parameters("", drv->create_options, param);
+ param = parse_option_parameters("", create_options, param);
}
set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512);
@@ -649,6 +667,7 @@ static int img_convert(int argc, char **argv)
/* Create the new image */
ret = bdrv_create(drv, out_filename, param);
+ free_option_parameters(create_options);
free_option_parameters(param);
if (ret < 0) {
diff --git a/qemu-option.c b/qemu-option.c
index 076dddf..acd74f9 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -346,6 +346,51 @@ void free_option_parameters(QEMUOptionParameter *list)
}
/*
+ * Count valid options in list
+ */
+static size_t count_option_parameters(QEMUOptionParameter *list)
+{
+ size_t num_options = 0;
+
+ while (list && list->name) {
+ num_options++;
+ list++;
+ }
+
+ return num_options;
+}
+
+/*
+ * Append an option list (list) to an option list (dest).
+ *
+ * If dest is NULL, a new copy of list is created.
+ *
+ * Returns a pointer to the first element of dest (or the newly allocated copy)
+ */
+QEMUOptionParameter *append_option_parameters(QEMUOptionParameter *dest,
+ QEMUOptionParameter *list)
+{
+ size_t num_options, num_dest_options;
+
+ num_options = count_option_parameters(dest);
+ num_dest_options = num_options;
+
+ num_options += count_option_parameters(list);
+
+ dest = qemu_realloc(dest, (num_options + 1) * sizeof(QEMUOptionParameter));
+
+ while (list && list->name) {
+ if (get_option_parameter(dest, list->name) == NULL) {
+ dest[num_dest_options++] = *list;
+ dest[num_dest_options].name = NULL;
+ }
+ list++;
+ }
+
+ return dest;
+}
+
+/*
* Parses a parameter string (param) into an option list (dest).
*
* list is the templace is. If dest is NULL, a new copy of list is created for
@@ -365,7 +410,6 @@ void free_option_parameters(QEMUOptionParameter *list)
QEMUOptionParameter *parse_option_parameters(const char *param,
QEMUOptionParameter *list, QEMUOptionParameter *dest)
{
- QEMUOptionParameter *cur;
QEMUOptionParameter *allocated = NULL;
char name[256];
char value[256];
@@ -379,12 +423,7 @@ QEMUOptionParameter *parse_option_parameters(const char *param,
if (dest == NULL) {
// Count valid options
- num_options = 0;
- cur = list;
- while (cur->name) {
- num_options++;
- cur++;
- }
+ num_options = count_option_parameters(list);
// Create a copy of the option list to fill in values
dest = qemu_mallocz((num_options + 1) * sizeof(QEMUOptionParameter));
diff --git a/qemu-option.h b/qemu-option.h
index 58136f3..4823219 100644
--- a/qemu-option.h
+++ b/qemu-option.h
@@ -70,6 +70,8 @@ int set_option_parameter(QEMUOptionParameter *list, const char *name,
const char *value);
int set_option_parameter_int(QEMUOptionParameter *list, const char *name,
uint64_t value);
+QEMUOptionParameter *append_option_parameters(QEMUOptionParameter *dest,
+ QEMUOptionParameter *list);
QEMUOptionParameter *parse_option_parameters(const char *param,
QEMUOptionParameter *list, QEMUOptionParameter *dest);
void free_option_parameters(QEMUOptionParameter *list);
commit 776cbbbd788686e9735e8d1c008d8bc105fb1fab
Author: Kevin Wolf <kwolf at redhat.com>
Date: Fri May 21 11:37:26 2010 +0200
qemu-io: Add multiwrite command
The new multiwrite commands allows to use qemu-io for testing
bdrv_aio_multiwrite.
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/qemu-io.c b/qemu-io.c
index f39109e..72a4524 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -267,6 +267,47 @@ static int do_aio_writev(QEMUIOVector *qiov, int64_t offset, int *total)
return async_ret < 0 ? async_ret : 1;
}
+struct multiwrite_async_ret {
+ int num_done;
+ int error;
+};
+
+static void multiwrite_cb(void *opaque, int ret)
+{
+ struct multiwrite_async_ret *async_ret = opaque;
+
+ async_ret->num_done++;
+ if (ret < 0) {
+ async_ret->error = ret;
+ }
+}
+
+static int do_aio_multiwrite(BlockRequest* reqs, int num_reqs, int *total)
+{
+ int i, ret;
+ struct multiwrite_async_ret async_ret = {
+ .num_done = 0,
+ .error = 0,
+ };
+
+ *total = 0;
+ for (i = 0; i < num_reqs; i++) {
+ reqs[i].cb = multiwrite_cb;
+ reqs[i].opaque = &async_ret;
+ *total += reqs[i].qiov->size;
+ }
+
+ ret = bdrv_aio_multiwrite(bs, reqs, num_reqs);
+ if (ret < 0) {
+ return ret;
+ }
+
+ while (async_ret.num_done < num_reqs) {
+ qemu_aio_wait();
+ }
+
+ return async_ret.error < 0 ? async_ret.error : 1;
+}
static void
read_help(void)
@@ -811,6 +852,156 @@ out:
return 0;
}
+static void
+multiwrite_help(void)
+{
+ printf(
+"\n"
+" writes a range of bytes from the given offset source from multiple buffers,\n"
+" in a batch of requests that may be merged by qemu\n"
+"\n"
+" Example:\n"
+" 'multiwrite 512 1k 1k ; 4k 1k' \n"
+" writes 2 kB at 512 bytes and 1 kB at 4 kB into the open file\n"
+"\n"
+" Writes into a segment of the currently open file, using a buffer\n"
+" filled with a set pattern (0xcdcdcdcd). The pattern byte is increased\n"
+" by one for each request contained in the multiwrite command.\n"
+" -P, -- use different pattern to fill file\n"
+" -C, -- report statistics in a machine parsable format\n"
+" -q, -- quiet mode, do not show I/O statistics\n"
+"\n");
+}
+
+static int multiwrite_f(int argc, char **argv);
+
+static const cmdinfo_t multiwrite_cmd = {
+ .name = "multiwrite",
+ .cfunc = multiwrite_f,
+ .argmin = 2,
+ .argmax = -1,
+ .args = "[-Cq] [-P pattern ] off len [len..] [; off len [len..]..]",
+ .oneline = "issues multiple write requests at once",
+ .help = multiwrite_help,
+};
+
+static int
+multiwrite_f(int argc, char **argv)
+{
+ struct timeval t1, t2;
+ int Cflag = 0, qflag = 0;
+ int c, cnt;
+ char **buf;
+ int64_t offset, first_offset = 0;
+ /* Some compilers get confused and warn if this is not initialized. */
+ int total = 0;
+ int nr_iov;
+ int nr_reqs;
+ int pattern = 0xcd;
+ QEMUIOVector *qiovs;
+ int i;
+ BlockRequest *reqs;
+
+ while ((c = getopt(argc, argv, "CqP:")) != EOF) {
+ switch (c) {
+ case 'C':
+ Cflag = 1;
+ break;
+ case 'q':
+ qflag = 1;
+ break;
+ case 'P':
+ pattern = parse_pattern(optarg);
+ if (pattern < 0)
+ return 0;
+ break;
+ default:
+ return command_usage(&writev_cmd);
+ }
+ }
+
+ if (optind > argc - 2)
+ return command_usage(&writev_cmd);
+
+ nr_reqs = 1;
+ for (i = optind; i < argc; i++) {
+ if (!strcmp(argv[i], ";")) {
+ nr_reqs++;
+ }
+ }
+
+ reqs = qemu_malloc(nr_reqs * sizeof(*reqs));
+ buf = qemu_malloc(nr_reqs * sizeof(*buf));
+ qiovs = qemu_malloc(nr_reqs * sizeof(*qiovs));
+
+ for (i = 0; i < nr_reqs; i++) {
+ int j;
+
+ /* Read the offset of the request */
+ offset = cvtnum(argv[optind]);
+ if (offset < 0) {
+ printf("non-numeric offset argument -- %s\n", argv[optind]);
+ return 0;
+ }
+ optind++;
+
+ if (offset & 0x1ff) {
+ printf("offset %lld is not sector aligned\n",
+ (long long)offset);
+ return 0;
+ }
+
+ if (i == 0) {
+ first_offset = offset;
+ }
+
+ /* Read lengths for qiov entries */
+ for (j = optind; j < argc; j++) {
+ if (!strcmp(argv[j], ";")) {
+ break;
+ }
+ }
+
+ nr_iov = j - optind;
+
+ /* Build request */
+ reqs[i].qiov = &qiovs[i];
+ buf[i] = create_iovec(reqs[i].qiov, &argv[optind], nr_iov, pattern);
+ reqs[i].sector = offset >> 9;
+ reqs[i].nb_sectors = reqs[i].qiov->size >> 9;
+
+ optind = j + 1;
+
+ offset += reqs[i].qiov->size;
+ pattern++;
+ }
+
+ gettimeofday(&t1, NULL);
+ cnt = do_aio_multiwrite(reqs, nr_reqs, &total);
+ gettimeofday(&t2, NULL);
+
+ if (cnt < 0) {
+ printf("aio_multiwrite failed: %s\n", strerror(-cnt));
+ goto out;
+ }
+
+ if (qflag)
+ goto out;
+
+ /* Finally, report back -- -C gives a parsable format */
+ t2 = tsub(t2, t1);
+ print_report("wrote", &t2, first_offset, total, total, cnt, Cflag);
+out:
+ for (i = 0; i < nr_reqs; i++) {
+ qemu_io_free(buf[i]);
+ qemu_iovec_destroy(&qiovs[i]);
+ }
+ qemu_free(buf);
+ qemu_free(reqs);
+ qemu_free(qiovs);
+ return 0;
+}
+
struct aio_ctx {
QEMUIOVector qiov;
int64_t offset;
@@ -1483,6 +1674,7 @@ int main(int argc, char **argv)
add_command(&readv_cmd);
add_command(&write_cmd);
add_command(&writev_cmd);
+ add_command(&multiwrite_cmd);
add_command(&aio_read_cmd);
add_command(&aio_write_cmd);
add_command(&aio_flush_cmd);
commit cbf1dff2f1033cadcb15c0ffc9c0a3d039d8ed42
Author: Kevin Wolf <kwolf at redhat.com>
Date: Fri May 21 11:09:42 2010 +0200
block: Fix multiwrite with overlapping requests
With overlapping requests, the total number of sectors is smaller than the sum
of the nb_sectors of both requests.
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block.c b/block.c
index cd70730..47be5ba 100644
--- a/block.c
+++ b/block.c
@@ -2019,7 +2019,7 @@ static int multiwrite_merge(BlockDriverState *bs, BlockRequest *reqs,
// Add the second request
qemu_iovec_concat(qiov, reqs[i].qiov, reqs[i].qiov->size);
- reqs[outidx].nb_sectors += reqs[i].nb_sectors;
+ reqs[outidx].nb_sectors = qiov->size >> 9;
reqs[outidx].qiov = qiov;
mcb->callbacks[i].free_qiov = reqs[outidx].qiov;
commit 175e11526e2613b3dc031c23fec3107aa4a80307
Author: Kevin Wolf <kwolf at redhat.com>
Date: Wed May 12 16:23:26 2010 +0200
qcow2: Fix error handling in l2_allocate
l2_allocate has some intermediate states in which the image is inconsistent.
Change the order to write to the L1 table only after the new L2 table has
successfully been initialized.
Also reset the L2 cache in failure case, it's very likely wrong.
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index ed5c4b2..244b4a7 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -239,14 +239,6 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
return l2_offset;
}
- /* update the L1 entry */
-
- s->l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED;
- ret = write_l1_entry(bs, l1_index);
- if (ret < 0) {
- return ret;
- }
-
/* allocate a new entry in the l2 cache */
min_index = l2_cache_new_entry(bs);
@@ -261,7 +253,7 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
ret = bdrv_pread(bs->file, old_l2_offset, l2_table,
s->l2_size * sizeof(uint64_t));
if (ret < 0) {
- return ret;
+ goto fail;
}
}
/* write the l2 table to the file */
@@ -269,7 +261,14 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
ret = bdrv_pwrite(bs->file, l2_offset, l2_table,
s->l2_size * sizeof(uint64_t));
if (ret < 0) {
- return ret;
+ goto fail;
+ }
+
+ /* update the L1 entry */
+ s->l1_table[l1_index] = l2_offset | QCOW_OFLAG_COPIED;
+ ret = write_l1_entry(bs, l1_index);
+ if (ret < 0) {
+ goto fail;
}
/* update the l2 cache entry */
@@ -279,6 +278,10 @@ static int l2_allocate(BlockDriverState *bs, int l1_index, uint64_t **table)
*table = l2_table;
return 0;
+
+fail:
+ qcow2_l2_cache_reset(bs);
+ return ret;
}
static int count_contiguous_clusters(uint64_t nb_clusters, int cluster_size,
commit 1b7c801b40ce90795397bb566d019c9b76ef9c13
Author: Kevin Wolf <kwolf at redhat.com>
Date: Tue Apr 13 11:43:27 2010 +0200
qcow2: Clear L2 table cache after write error
If the L2 table was already updated in cache, but writing it to disk has
failed, we must not continue using the changed version in the cache to stay
consistent with what's on the disk.
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index c11680d..ed5c4b2 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -696,6 +696,7 @@ int qcow2_alloc_cluster_link_l2(BlockDriverState *bs, QCowL2Meta *m)
ret = write_l2_entries(bs, l2_table, l2_offset, l2_index, m->nb_clusters);
if (ret < 0) {
+ qcow2_l2_cache_reset(bs);
goto err;
}
commit 29f91781bd300b228d9c38b9f6c1e0b6a38f25fb
Author: Jes Sorensen <Jes.Sorensen at redhat.com>
Date: Thu May 27 14:26:05 2010 +0200
vhost_net.c: v2 Fix build failure introduced by 0bfcd599e3f5c5679cc7d0165a0a1822e2f60de2
Fix build failure introduced by 0bfcd599e3f5c5679cc7d0165a0a1822e2f60de2
The format statement expects unsigned long on x86_64, but receives
unsigned long long, so gcc exits with an error.
Signed-off-by: Jes Sorensen <Jes.Sorensen at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/vhost_net.c b/hw/vhost_net.c
index 26dae79..606aa0c 100644
--- a/hw/vhost_net.c
+++ b/hw/vhost_net.c
@@ -100,7 +100,7 @@ struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd)
}
if (~net->dev.features & net->dev.backend_features) {
fprintf(stderr, "vhost lacks feature mask %" PRIu64 " for backend\n",
- ~net->dev.features & net->dev.backend_features);
+ (uint64_t)(~net->dev.features & net->dev.backend_features));
vhost_dev_cleanup(&net->dev);
goto fail;
}
commit c317728872ee9de44a1514bbe1f1fc8d5f8a7aeb
Author: Alexander Graf <agraf at suse.de>
Date: Wed May 26 21:04:32 2010 +0200
Make cache=unsafe the default for -snapshot
When using -snapshot we don't care about data integrity of the cow file
at all, so let's disable flushing there and squeeze out the last drop
of performance we could possibly get.
Signed-off-by: Alexander Graf <agraf at suse.de>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/qemu-options.hx b/qemu-options.hx
index cea9b72..a6928b7 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -170,8 +170,7 @@ the storage subsystem.
Writeback caching will report data writes as completed as soon as the data is
present in the host page cache. This is safe as long as you trust your host.
If your host crashes or loses power, then the guest may experience data
-corruption. When using the @option{-snapshot} option, writeback caching is
-used by default.
+corruption.
The host page cache can be avoided entirely with @option{cache=none}. This will
attempt to do disk IO directly to the guests memory. QEMU may still perform
@@ -185,7 +184,8 @@ In case you don't care about data integrity over host failures, use
cache=unsafe. This option tells qemu that it never needs to write any data
to the disk but can instead keeps things in cache. If anything goes wrong,
like your host losing power, the disk storage getting disconnected accidently,
-etc. you're image will most probably be rendered unusable.
+etc. you're image will most probably be rendered unusable. When using
+the @option{-snapshot} option, unsafe caching is always used.
Instead of @option{-cdrom} you can use:
@example
diff --git a/vl.c b/vl.c
index bc15dd7..417554f 100644
--- a/vl.c
+++ b/vl.c
@@ -1105,9 +1105,9 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque,
return NULL;
}
if (snapshot) {
- /* always use write-back with snapshot */
+ /* always use cache=unsafe with snapshot */
bdrv_flags &= ~BDRV_O_CACHE_MASK;
- bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB);
+ bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH);
}
if (media == MEDIA_CDROM) {
commit d63baf92e3e968626e0899ec6070e747a9bf51bf
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date: Tue May 25 16:09:03 2010 +0400
sparc64: clean up pci bridge map
- remove unused host state and store pci bus pointer only
- do not map host state access into unused 1fe.10000000 range
- reorder pci region registration
- assign pci i/o region to isa_mem_base
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index 65d8ba6..b53e3c3 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -65,7 +65,7 @@ do { printf("APB: " fmt , ## __VA_ARGS__); } while (0)
typedef struct APBState {
SysBusDevice busdev;
- PCIHostState host_state;
+ PCIBus *bus;
ReadWriteHandler pci_config_handler;
uint32_t iommu[4];
uint32_t pci_control[16];
@@ -191,7 +191,7 @@ static void apb_pci_config_write(ReadWriteHandler *h, pcibus_t addr,
val = qemu_bswap_len(val, size);
APB_DPRINTF("%s: addr " TARGET_FMT_lx " val %x\n", __func__, addr, val);
- pci_data_write(s->host_state.bus, addr, val, size);
+ pci_data_write(s->bus, addr, val, size);
}
static uint32_t apb_pci_config_read(ReadWriteHandler *h, pcibus_t addr,
@@ -200,7 +200,7 @@ static uint32_t apb_pci_config_read(ReadWriteHandler *h, pcibus_t addr,
uint32_t ret;
APBState *s = container_of(h, APBState, pci_config_handler);
- ret = pci_data_read(s->host_state.bus, addr, size);
+ ret = pci_data_read(s->bus, addr, size);
ret = qemu_bswap_len(ret, size);
APB_DPRINTF("%s: addr " TARGET_FMT_lx " -> %x\n", __func__, addr, ret);
return ret;
@@ -331,37 +331,37 @@ PCIBus *pci_apb_init(target_phys_addr_t special_base,
s = sysbus_from_qdev(dev);
/* apb_config */
sysbus_mmio_map(s, 0, special_base);
+ /* PCI configuration space */
+ sysbus_mmio_map(s, 1, special_base + 0x1000000ULL);
/* pci_ioport */
- sysbus_mmio_map(s, 1, special_base + 0x2000000ULL);
- /* pci_config */
- sysbus_mmio_map(s, 2, special_base + 0x1000000ULL);
- /* mem_data */
- sysbus_mmio_map(s, 3, mem_base);
+ sysbus_mmio_map(s, 2, special_base + 0x2000000ULL);
d = FROM_SYSBUS(APBState, s);
- d->host_state.bus = pci_register_bus(&d->busdev.qdev, "pci",
+
+ d->bus = pci_register_bus(&d->busdev.qdev, "pci",
pci_apb_set_irq, pci_pbm_map_irq, d,
0, 32);
- pci_bus_set_mem_base(d->host_state.bus, mem_base);
+ pci_bus_set_mem_base(d->bus, mem_base);
for (i = 0; i < 32; i++) {
sysbus_connect_irq(s, i, pic[i]);
}
- pci_create_simple(d->host_state.bus, 0, "pbm");
+ pci_create_simple(d->bus, 0, "pbm");
+
/* APB secondary busses */
- *bus2 = pci_bridge_init(d->host_state.bus, PCI_DEVFN(1, 0),
+ *bus2 = pci_bridge_init(d->bus, PCI_DEVFN(1, 0),
PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
pci_apb_map_irq,
"Advanced PCI Bus secondary bridge 1");
apb_pci_bridge_init(*bus2);
- *bus3 = pci_bridge_init(d->host_state.bus, PCI_DEVFN(1, 1),
+ *bus3 = pci_bridge_init(d->bus, PCI_DEVFN(1, 1),
PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_SIMBA,
pci_apb_map_irq,
"Advanced PCI Bus secondary bridge 2");
apb_pci_bridge_init(*bus3);
- return d->host_state.bus;
+ return d->bus;
}
static void pci_pbm_reset(DeviceState *d)
@@ -382,7 +382,7 @@ static void pci_pbm_reset(DeviceState *d)
static int pci_pbm_init_device(SysBusDevice *dev)
{
APBState *s;
- int pci_mem_data, apb_config, pci_ioport, pci_config;
+ int pci_config, apb_config, pci_ioport;
unsigned int i;
s = FROM_SYSBUS(APBState, dev);
@@ -396,20 +396,23 @@ static int pci_pbm_init_device(SysBusDevice *dev)
/* apb_config */
apb_config = cpu_register_io_memory(apb_config_read,
apb_config_write, s);
+ /* at region 0 */
sysbus_init_mmio(dev, 0x10000ULL, apb_config);
- /* pci_ioport */
- pci_ioport = cpu_register_io_memory(pci_apb_ioread,
- pci_apb_iowrite, s);
- sysbus_init_mmio(dev, 0x10000ULL, pci_ioport);
- /* pci_config */
+
+ /* PCI configuration space */
s->pci_config_handler.read = apb_pci_config_read;
s->pci_config_handler.write = apb_pci_config_write;
pci_config = cpu_register_io_memory_simple(&s->pci_config_handler);
assert(pci_config >= 0);
+ /* at region 1 */
sysbus_init_mmio(dev, 0x1000000ULL, pci_config);
- /* mem_data */
- pci_mem_data = pci_host_data_register_mmio(&s->host_state, 1);
- sysbus_init_mmio(dev, 0x10000000ULL, pci_mem_data);
+
+ /* pci_ioport */
+ pci_ioport = cpu_register_io_memory(pci_apb_ioread,
+ pci_apb_iowrite, s);
+ /* at region 2 */
+ sysbus_init_mmio(dev, 0x10000ULL, pci_ioport);
+
return 0;
}
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 1e92900..40b5f1f 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -70,7 +70,7 @@
#define PROM_VADDR 0x000ffd00000ULL
#define APB_SPECIAL_BASE 0x1fe00000000ULL
#define APB_MEM_BASE 0x1ff00000000ULL
-#define VGA_BASE (APB_MEM_BASE + 0x400000ULL)
+#define APB_PCI_IO_BASE (APB_SPECIAL_BASE + 0x02000000ULL)
#define PROM_FILENAME "openbios-sparc64"
#define NVRAM_SIZE 0x2000
#define MAX_IDE_BUS 2
@@ -766,7 +766,7 @@ static void sun4uv_init(ram_addr_t RAM_size,
irq = qemu_allocate_irqs(cpu_set_irq, env, MAX_PILS);
pci_bus = pci_apb_init(APB_SPECIAL_BASE, APB_MEM_BASE, irq, &pci_bus2,
&pci_bus3);
- isa_mem_base = VGA_BASE;
+ isa_mem_base = APB_PCI_IO_BASE;
pci_vga_init(pci_bus, 0, 0);
// XXX Should be pci_bus3
commit 5910b047a0221170f2a8dca65f0083bbe4f2c803
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date: Tue May 25 16:08:57 2010 +0400
sparc64: rename sun4u cpu to Ultrasparc IIi
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/sun4u.c b/hw/sun4u.c
index e9a1e23..1e92900 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -859,7 +859,7 @@ enum {
static const struct hwdef hwdefs[] = {
/* Sun4u generic PC-like machine */
{
- .default_cpu_model = "TI UltraSparc II",
+ .default_cpu_model = "TI UltraSparc IIi",
.machine_id = sun4u_id,
.prom_addr = 0x1fff0000000ULL,
.console_serial_base = 0,
commit 016f5cf6ff465411733878a17c8f8febb7668321
Author: Alexander Graf <agraf at suse.de>
Date: Wed May 26 17:51:49 2010 +0200
Add cache=unsafe parameter to -drive
Usually the guest can tell the host to flush data to disk. In some cases we
don't want to flush though, but try to keep everything in cache.
So let's add a new cache value to -drive that allows us to set the cache
policy to most aggressive, disabling flushes. We call this mode "unsafe",
as guest data is not guaranteed to survive host crashes anymore.
This patch also adds a noop function for aio, so we can do nothing in AIO
fashion.
Signed-off-by: Alexander Graf <agraf at suse.de>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/block.c b/block.c
index 0b0966c..cd70730 100644
--- a/block.c
+++ b/block.c
@@ -50,6 +50,8 @@ static BlockDriverAIOCB *bdrv_aio_writev_em(BlockDriverState *bs,
BlockDriverCompletionFunc *cb, void *opaque);
static BlockDriverAIOCB *bdrv_aio_flush_em(BlockDriverState *bs,
BlockDriverCompletionFunc *cb, void *opaque);
+static BlockDriverAIOCB *bdrv_aio_noop_em(BlockDriverState *bs,
+ BlockDriverCompletionFunc *cb, void *opaque);
static int bdrv_read_em(BlockDriverState *bs, int64_t sector_num,
uint8_t *buf, int nb_sectors);
static int bdrv_write_em(BlockDriverState *bs, int64_t sector_num,
@@ -1312,6 +1314,10 @@ const char *bdrv_get_device_name(BlockDriverState *bs)
void bdrv_flush(BlockDriverState *bs)
{
+ if (bs->open_flags & BDRV_O_NO_FLUSH) {
+ return;
+ }
+
if (bs->drv && bs->drv->bdrv_flush)
bs->drv->bdrv_flush(bs);
}
@@ -2099,6 +2105,10 @@ BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs,
{
BlockDriver *drv = bs->drv;
+ if (bs->open_flags & BDRV_O_NO_FLUSH) {
+ return bdrv_aio_noop_em(bs, cb, opaque);
+ }
+
if (!drv)
return NULL;
return drv->bdrv_aio_flush(bs, cb, opaque);
@@ -2214,6 +2224,25 @@ static BlockDriverAIOCB *bdrv_aio_flush_em(BlockDriverState *bs,
return &acb->common;
}
+static BlockDriverAIOCB *bdrv_aio_noop_em(BlockDriverState *bs,
+ BlockDriverCompletionFunc *cb, void *opaque)
+{
+ BlockDriverAIOCBSync *acb;
+
+ acb = qemu_aio_get(&bdrv_em_aio_pool, bs, cb, opaque);
+ acb->is_write = 1; /* don't bounce in the completion handler */
+ acb->qiov = NULL;
+ acb->bounce = NULL;
+ acb->ret = 0;
+
+ if (!acb->bh) {
+ acb->bh = qemu_bh_new(bdrv_aio_bh_cb, acb);
+ }
+
+ qemu_bh_schedule(acb->bh);
+ return &acb->common;
+}
+
/**************************************************************/
/* sync block device emulation */
diff --git a/block.h b/block.h
index 278259c..24efeb6 100644
--- a/block.h
+++ b/block.h
@@ -33,6 +33,7 @@ typedef struct QEMUSnapshotInfo {
#define BDRV_O_CACHE_WB 0x0040 /* use write-back caching */
#define BDRV_O_NATIVE_AIO 0x0080 /* use native AIO instead of the thread pool */
#define BDRV_O_NO_BACKING 0x0100 /* don't open the backing file */
+#define BDRV_O_NO_FLUSH 0x0200 /* disable flushing on this disk */
#define BDRV_O_CACHE_MASK (BDRV_O_NOCACHE | BDRV_O_CACHE_WB)
diff --git a/qemu-config.c b/qemu-config.c
index aa376d4..5a4e61b 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -54,7 +54,7 @@ QemuOptsList qemu_drive_opts = {
},{
.name = "cache",
.type = QEMU_OPT_STRING,
- .help = "host cache usage (none, writeback, writethrough)",
+ .help = "host cache usage (none, writeback, writethrough, unsafe)",
},{
.name = "aio",
.type = QEMU_OPT_STRING,
diff --git a/qemu-options.hx b/qemu-options.hx
index 03e95fd..cea9b72 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -118,8 +118,9 @@ ETEXI
DEF("drive", HAS_ARG, QEMU_OPTION_drive,
"-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][,index=i]\n"
" [,cyls=c,heads=h,secs=s[,trans=t]][,snapshot=on|off]\n"
- " [,cache=writethrough|writeback|none][,format=f][,serial=s]\n"
- " [,addr=A][,id=name][,aio=threads|native][,readonly=on|off]\n"
+ " [,cache=writethrough|writeback|unsafe|none][,format=f]\n"
+ " [,serial=s][,addr=A][,id=name][,aio=threads|native]\n"
+ " [,readonly=on|off]\n"
" use 'file' as a drive image\n", QEMU_ARCH_ALL)
STEXI
@item -drive @var{option}[, at var{option}[, at var{option}[,...]]]
@@ -148,7 +149,7 @@ These options have the same definition as they have in @option{-hdachs}.
@item snapshot=@var{snapshot}
@var{snapshot} is "on" or "off" and allows to enable snapshot for given drive (see @option{-snapshot}).
@item cache=@var{cache}
- at var{cache} is "none", "writeback", or "writethrough" and controls how the host cache is used to access block data.
+ at var{cache} is "none", "writeback", "unsafe", or "writethrough" and controls how the host cache is used to access block data.
@item aio=@var{aio}
@var{aio} is "threads", or "native" and selects between pthread based disk I/O and native Linux AIO.
@item format=@var{format}
@@ -180,6 +181,12 @@ Some block drivers perform badly with @option{cache=writethrough}, most notably,
qcow2. If performance is more important than correctness,
@option{cache=writeback} should be used with qcow2.
+In case you don't care about data integrity over host failures, use
+cache=unsafe. This option tells qemu that it never needs to write any data
+to the disk but can instead keeps things in cache. If anything goes wrong,
+like your host losing power, the disk storage getting disconnected accidently,
+etc. you're image will most probably be rendered unusable.
+
Instead of @option{-cdrom} you can use:
@example
qemu -drive file=file,index=2,media=cdrom
diff --git a/vl.c b/vl.c
index 328395e..bc15dd7 100644
--- a/vl.c
+++ b/vl.c
@@ -913,6 +913,9 @@ DriveInfo *drive_init(QemuOpts *opts, void *opaque,
bdrv_flags |= BDRV_O_NOCACHE;
} else if (!strcmp(buf, "writeback")) {
bdrv_flags |= BDRV_O_CACHE_WB;
+ } else if (!strcmp(buf, "unsafe")) {
+ bdrv_flags |= BDRV_O_CACHE_WB;
+ bdrv_flags |= BDRV_O_NO_FLUSH;
} else if (!strcmp(buf, "writethrough")) {
/* this is the default */
} else {
commit d467b679f2993cb07fcc8112bfee6f6e8a40d093
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Fri May 21 11:54:34 2010 +0200
vnc: rich cursor support.
Uses VNC_ENCODING_RICH_CURSOR. Adding XCURSOR support should be
possible without much trouble. Shouldn't be needed though as
RICH_CURSOR is a superset of XCURSOR.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/vnc.c b/vnc.c
index 1f7ad73..11ae3e5 100644
--- a/vnc.c
+++ b/vnc.c
@@ -49,6 +49,8 @@
static VncDisplay *vnc_display; /* needed for info vnc */
static DisplayChangeListener *dcl;
+static int vnc_cursor_define(VncState *vs);
+
static char *addr_to_string(const char *format,
struct sockaddr_storage *sa,
socklen_t salen) {
@@ -549,12 +551,16 @@ static void vnc_dpy_resize(DisplayState *ds)
vnc_flush(vs);
}
}
+ if (vs->vd->cursor) {
+ vnc_cursor_define(vs);
+ }
memset(vs->dirty, 0xFF, sizeof(vs->dirty));
}
}
/* fastest code */
-static void vnc_write_pixels_copy(VncState *vs, void *pixels, int size)
+static void vnc_write_pixels_copy(VncState *vs, struct PixelFormat *pf,
+ void *pixels, int size)
{
vnc_write(vs, pixels, size);
}
@@ -604,12 +610,12 @@ void vnc_convert_pixel(VncState *vs, uint8_t *buf, uint32_t v)
}
}
-static void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size)
+static void vnc_write_pixels_generic(VncState *vs, struct PixelFormat *pf,
+ void *pixels1, int size)
{
uint8_t buf[4];
- VncDisplay *vd = vs->vd;
- if (vd->server->pf.bytes_per_pixel == 4) {
+ if (pf->bytes_per_pixel == 4) {
uint32_t *pixels = pixels1;
int n, i;
n = size >> 2;
@@ -617,7 +623,7 @@ static void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size)
vnc_convert_pixel(vs, buf, pixels[i]);
vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel);
}
- } else if (vd->server->pf.bytes_per_pixel == 2) {
+ } else if (pf->bytes_per_pixel == 2) {
uint16_t *pixels = pixels1;
int n, i;
n = size >> 1;
@@ -625,7 +631,7 @@ static void vnc_write_pixels_generic(VncState *vs, void *pixels1, int size)
vnc_convert_pixel(vs, buf, pixels[i]);
vnc_write(vs, buf, vs->clientds.pf.bytes_per_pixel);
}
- } else if (vd->server->pf.bytes_per_pixel == 1) {
+ } else if (pf->bytes_per_pixel == 1) {
uint8_t *pixels = pixels1;
int n, i;
n = size;
@@ -646,7 +652,7 @@ void vnc_raw_send_framebuffer_update(VncState *vs, int x, int y, int w, int h)
row = vd->server->data + y * ds_get_linesize(vs->ds) + x * ds_get_bytes_per_pixel(vs->ds);
for (i = 0; i < h; i++) {
- vs->write_pixels(vs, row, w * ds_get_bytes_per_pixel(vs->ds));
+ vs->write_pixels(vs, &vd->server->pf, row, w * ds_get_bytes_per_pixel(vs->ds));
row += ds_get_linesize(vs->ds);
}
}
@@ -752,6 +758,50 @@ static void vnc_dpy_copy(DisplayState *ds, int src_x, int src_y, int dst_x, int
}
}
+static void vnc_mouse_set(int x, int y, int visible)
+{
+ /* can we ask the client(s) to move the pointer ??? */
+}
+
+static int vnc_cursor_define(VncState *vs)
+{
+ QEMUCursor *c = vs->vd->cursor;
+ PixelFormat pf = qemu_default_pixelformat(32);
+ int isize;
+
+ if (vnc_has_feature(vs, VNC_FEATURE_RICH_CURSOR)) {
+ vnc_write_u8(vs, VNC_MSG_SERVER_FRAMEBUFFER_UPDATE);
+ vnc_write_u8(vs, 0); /* padding */
+ vnc_write_u16(vs, 1); /* # of rects */
+ vnc_framebuffer_update(vs, c->hot_x, c->hot_y, c->width, c->height,
+ VNC_ENCODING_RICH_CURSOR);
+ isize = c->width * c->height * vs->clientds.pf.bytes_per_pixel;
+ vnc_write_pixels_generic(vs, &pf, c->data, isize);
+ vnc_write(vs, vs->vd->cursor_mask, vs->vd->cursor_msize);
+ return 0;
+ }
+ return -1;
+}
+
+static void vnc_dpy_cursor_define(QEMUCursor *c)
+{
+ VncDisplay *vd = vnc_display;
+ VncState *vs;
+
+ cursor_put(vd->cursor);
+ qemu_free(vd->cursor_mask);
+
+ vd->cursor = c;
+ cursor_get(vd->cursor);
+ vd->cursor_msize = cursor_get_mono_bpl(c) * c->height;
+ vd->cursor_mask = qemu_mallocz(vd->cursor_msize);
+ cursor_get_mono_mask(c, 0, vd->cursor_mask);
+
+ QTAILQ_FOREACH(vs, &vd->clients, next) {
+ vnc_cursor_define(vs);
+ }
+}
+
static int find_and_clear_dirty_height(struct VncState *vs,
int y, int last_x, int x)
{
@@ -1628,6 +1678,9 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
case VNC_ENCODING_POINTER_TYPE_CHANGE:
vs->features |= VNC_FEATURE_POINTER_TYPE_CHANGE_MASK;
break;
+ case VNC_ENCODING_RICH_CURSOR:
+ vs->features |= VNC_FEATURE_RICH_CURSOR_MASK;
+ break;
case VNC_ENCODING_EXT_KEY_EVENT:
send_ext_key_event_ack(vs);
break;
@@ -1648,7 +1701,6 @@ static void set_encodings(VncState *vs, int32_t *encodings, size_t n_encodings)
break;
}
}
-
check_pointer_type_change(&vs->mouse_mode_notifier);
}
@@ -2294,6 +2346,8 @@ void vnc_display_init(DisplayState *ds)
dcl->dpy_resize = vnc_dpy_resize;
dcl->dpy_setdata = vnc_dpy_setdata;
register_displaychangelistener(ds, dcl);
+ ds->mouse_set = vnc_mouse_set;
+ ds->cursor_define = vnc_dpy_cursor_define;
}
diff --git a/vnc.h b/vnc.h
index 1aa71b0..0d39897 100644
--- a/vnc.h
+++ b/vnc.h
@@ -61,7 +61,7 @@ typedef struct VncState VncState;
typedef int VncReadEvent(VncState *vs, uint8_t *data, size_t len);
-typedef void VncWritePixels(VncState *vs, void *data, int size);
+typedef void VncWritePixels(VncState *vs, struct PixelFormat *pf, void *data, int size);
typedef void VncSendHextileTile(VncState *vs,
int x, int y, int w, int h,
@@ -101,6 +101,10 @@ struct VncDisplay
kbd_layout_t *kbd_layout;
int lock_key_sync;
+ QEMUCursor *cursor;
+ int cursor_msize;
+ uint8_t *cursor_mask;
+
struct VncSurface guest; /* guest visible surface (aka ds->surface) */
DisplaySurface *server; /* vnc server surface */
@@ -273,6 +277,7 @@ enum {
#define VNC_FEATURE_TIGHT 4
#define VNC_FEATURE_ZLIB 5
#define VNC_FEATURE_COPYRECT 6
+#define VNC_FEATURE_RICH_CURSOR 7
#define VNC_FEATURE_RESIZE_MASK (1 << VNC_FEATURE_RESIZE)
#define VNC_FEATURE_HEXTILE_MASK (1 << VNC_FEATURE_HEXTILE)
@@ -281,6 +286,7 @@ enum {
#define VNC_FEATURE_TIGHT_MASK (1 << VNC_FEATURE_TIGHT)
#define VNC_FEATURE_ZLIB_MASK (1 << VNC_FEATURE_ZLIB)
#define VNC_FEATURE_COPYRECT_MASK (1 << VNC_FEATURE_COPYRECT)
+#define VNC_FEATURE_RICH_CURSOR_MASK (1 << VNC_FEATURE_RICH_CURSOR)
/* Client -> Server message IDs */
diff --git a/vnchextile.h b/vnchextile.h
index 78ed8c4..b9f9f5e 100644
--- a/vnchextile.h
+++ b/vnchextile.h
@@ -189,16 +189,17 @@ static void CONCAT(send_hextile_tile_, NAME)(VncState *vs,
vnc_write_u8(vs, flags);
if (n_colors < 4) {
if (flags & 0x02)
- vs->write_pixels(vs, last_bg, sizeof(pixel_t));
+ vs->write_pixels(vs, &vd->server->pf, last_bg, sizeof(pixel_t));
if (flags & 0x04)
- vs->write_pixels(vs, last_fg, sizeof(pixel_t));
+ vs->write_pixels(vs, &vd->server->pf, last_fg, sizeof(pixel_t));
if (n_subtiles) {
vnc_write_u8(vs, n_subtiles);
vnc_write(vs, data, n_data);
}
} else {
for (j = 0; j < h; j++) {
- vs->write_pixels(vs, row, w * ds_get_bytes_per_pixel(vs->ds));
+ vs->write_pixels(vs, &vd->server->pf, row,
+ w * ds_get_bytes_per_pixel(vs->ds));
row += ds_get_linesize(vs->ds);
}
}
commit fbe6d7a48d71e1dd05faa380c68965da4f8de1ac
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Fri May 21 11:54:33 2010 +0200
use new cursor struct + functions for vmware vga and sdl.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index e709369..bf2a699 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -477,13 +477,43 @@ struct vmsvga_cursor_definition_s {
static inline void vmsvga_cursor_define(struct vmsvga_state_s *s,
struct vmsvga_cursor_definition_s *c)
{
- int i;
- for (i = SVGA_BITMAP_SIZE(c->width, c->height) - 1; i >= 0; i --)
- c->mask[i] = ~c->mask[i];
+ QEMUCursor *qc;
+ int i, pixels;
+
+ qc = cursor_alloc(c->width, c->height);
+ qc->hot_x = c->hot_x;
+ qc->hot_y = c->hot_y;
+ switch (c->bpp) {
+ case 1:
+ cursor_set_mono(qc, 0xffffff, 0x000000, (void*)c->image,
+ 1, (void*)c->mask);
+#ifdef DEBUG
+ cursor_print_ascii_art(qc, "vmware/mono");
+#endif
+ break;
+ case 32:
+ /* fill alpha channel from mask, set color to zero */
+ cursor_set_mono(qc, 0x000000, 0x000000, (void*)c->mask,
+ 1, (void*)c->mask);
+ /* add in rgb values */
+ pixels = c->width * c->height;
+ for (i = 0; i < pixels; i++) {
+ qc->data[i] |= c->image[i] & 0xffffff;
+ }
+#ifdef DEBUG
+ cursor_print_ascii_art(qc, "vmware/32bit");
+#endif
+ break;
+ default:
+ fprintf(stderr, "%s: unhandled bpp %d, using fallback cursor\n",
+ __FUNCTION__, c->bpp);
+ cursor_put(qc);
+ qc = cursor_builtin_left_ptr();
+ }
if (s->vga.ds->cursor_define)
- s->vga.ds->cursor_define(c->width, c->height, c->bpp, c->hot_x, c->hot_y,
- (uint8_t *) c->image, (uint8_t *) c->mask);
+ s->vga.ds->cursor_define(qc);
+ cursor_put(qc);
}
#endif
diff --git a/sdl.c b/sdl.c
index 3bdd518..0072680 100644
--- a/sdl.c
+++ b/sdl.c
@@ -778,49 +778,23 @@ static void sdl_mouse_warp(int x, int y, int on)
guest_x = x, guest_y = y;
}
-static void sdl_mouse_define(int width, int height, int bpp,
- int hot_x, int hot_y,
- uint8_t *image, uint8_t *mask)
+static void sdl_mouse_define(QEMUCursor *c)
{
- uint8_t sprite[256], *line;
- int x, y, dst, bypl, src = 0;
+ uint8_t *image, *mask;
+ int bpl;
+
if (guest_sprite)
SDL_FreeCursor(guest_sprite);
- memset(sprite, 0, 256);
- bypl = ((width * bpp + 31) >> 5) << 2;
- for (y = 0, dst = 0; y < height; y ++, image += bypl) {
- line = image;
- for (x = 0; x < width; x ++, dst ++) {
- switch (bpp) {
- case 32:
- src = *(line ++); src |= *(line ++); src |= *(line ++); line++;
- break;
- case 24:
- src = *(line ++); src |= *(line ++); src |= *(line ++);
- break;
- case 16:
- case 15:
- src = *(line ++); src |= *(line ++);
- break;
- case 8:
- src = *(line ++);
- break;
- case 4:
- src = 0xf & (line[x >> 1] >> ((x & 1)) << 2);
- break;
- case 2:
- src = 3 & (line[x >> 2] >> ((x & 3)) << 1);
- break;
- case 1:
- src = 1 & (line[x >> 3] >> (x & 7));
- break;
- }
- if (!src)
- sprite[dst >> 3] |= (1 << (~dst & 7)) & mask[dst >> 3];
- }
- }
- guest_sprite = SDL_CreateCursor(sprite, mask, width, height, hot_x, hot_y);
+ bpl = cursor_get_mono_bpl(c);
+ image = qemu_mallocz(bpl * c->height);
+ mask = qemu_mallocz(bpl * c->height);
+ cursor_get_mono_image(c, 0x000000, image);
+ cursor_get_mono_mask(c, 0, mask);
+ guest_sprite = SDL_CreateCursor(image, mask, c->width, c->height,
+ c->hot_x, c->hot_y);
+ qemu_free(image);
+ qemu_free(mask);
if (guest_cursor &&
(gui_grab || kbd_mouse_is_absolute() || absolute_enabled))
commit 254e59506e34efcc92384ef30af3c266e4633c66
Author: Gerd Hoffmann <kraxel at redhat.com>
Date: Fri May 21 11:54:32 2010 +0200
cursor: add cursor functions.
Add a new cursor type to console.h and a bunch of functions to
deal with cursors the (new) cursor.c file.
Signed-off-by: Gerd Hoffmann <kraxel at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/Makefile.objs b/Makefile.objs
index 1585101..1a942e5 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -48,7 +48,8 @@ common-obj-y = $(block-obj-y)
common-obj-y += $(net-obj-y)
common-obj-y += $(qobject-obj-y)
common-obj-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX))
-common-obj-y += readline.o console.o async.o qemu-error.o
+common-obj-y += readline.o console.o cursor.o async.o qemu-error.o
+
common-obj-y += tcg-runtime.o host-utils.o
common-obj-y += irq.o ioport.o input.o
common-obj-$(CONFIG_PTIMER) += ptimer.o
diff --git a/console.h b/console.h
index 3a75bcc..cac959f 100644
--- a/console.h
+++ b/console.h
@@ -126,6 +126,27 @@ struct DisplaySurface {
struct PixelFormat pf;
};
+/* cursor data format is 32bit RGBA */
+typedef struct QEMUCursor {
+ int width, height;
+ int hot_x, hot_y;
+ int refcount;
+ uint32_t data[];
+} QEMUCursor;
+
+QEMUCursor *cursor_alloc(int width, int height);
+void cursor_get(QEMUCursor *c);
+void cursor_put(QEMUCursor *c);
+QEMUCursor *cursor_builtin_hidden(void);
+QEMUCursor *cursor_builtin_left_ptr(void);
+void cursor_print_ascii_art(QEMUCursor *c, const char *prefix);
+int cursor_get_mono_bpl(QEMUCursor *c);
+void cursor_set_mono(QEMUCursor *c,
+ uint32_t foreground, uint32_t background, uint8_t *image,
+ int transparent, uint8_t *mask);
+void cursor_get_mono_image(QEMUCursor *c, int foreground, uint8_t *mask);
+void cursor_get_mono_mask(QEMUCursor *c, int transparent, uint8_t *mask);
+
struct DisplayChangeListener {
int idle;
uint64_t gui_timer_interval;
@@ -158,8 +179,7 @@ struct DisplayState {
struct DisplayChangeListener* listeners;
void (*mouse_set)(int x, int y, int on);
- void (*cursor_define)(int width, int height, int bpp, int hot_x, int hot_y,
- uint8_t *image, uint8_t *mask);
+ void (*cursor_define)(QEMUCursor *cursor);
struct DisplayState *next;
};
diff --git a/cursor.c b/cursor.c
new file mode 100644
index 0000000..dfb9eef
--- /dev/null
+++ b/cursor.c
@@ -0,0 +1,210 @@
+#include "qemu-common.h"
+#include "console.h"
+
+#include "cursor_hidden.xpm"
+#include "cursor_left_ptr.xpm"
+
+/* for creating built-in cursors */
+static QEMUCursor *cursor_parse_xpm(const char *xpm[])
+{
+ QEMUCursor *c;
+ uint32_t ctab[128];
+ unsigned int width, height, colors, chars;
+ unsigned int line = 0, i, r, g, b, x, y, pixel;
+ char name[16];
+ uint8_t idx;
+
+ /* parse header line: width, height, #colors, #chars */
+ if (sscanf(xpm[line], "%d %d %d %d", &width, &height, &colors, &chars) != 4) {
+ fprintf(stderr, "%s: header parse error: \"%s\"\n",
+ __FUNCTION__, xpm[line]);
+ return NULL;
+ }
+ if (chars != 1) {
+ fprintf(stderr, "%s: chars != 1 not supported\n", __FUNCTION__);
+ return NULL;
+ }
+ line++;
+
+ /* parse color table */
+ for (i = 0; i < colors; i++, line++) {
+ if (sscanf(xpm[line], "%c c %15s", &idx, name) == 2) {
+ if (sscanf(name, "#%02x%02x%02x", &r, &g, &b) == 3) {
+ ctab[idx] = (0xff << 24) | (b << 16) | (g << 8) | r;
+ continue;
+ }
+ if (strcmp(name, "None") == 0) {
+ ctab[idx] = 0x00000000;
+ continue;
+ }
+ }
+ fprintf(stderr, "%s: color parse error: \"%s\"\n",
+ __FUNCTION__, xpm[line]);
+ return NULL;
+ }
+
+ /* parse pixel data */
+ c = cursor_alloc(width, height);
+ for (pixel = 0, y = 0; y < height; y++, line++) {
+ for (x = 0; x < height; x++, pixel++) {
+ idx = xpm[line][x];
+ c->data[pixel] = ctab[idx];
+ }
+ }
+ return c;
+}
+
+/* nice for debugging */
+void cursor_print_ascii_art(QEMUCursor *c, const char *prefix)
+{
+ uint32_t *data = c->data;
+ int x,y;
+
+ for (y = 0; y < c->height; y++) {
+ fprintf(stderr, "%s: %2d: |", prefix, y);
+ for (x = 0; x < c->width; x++, data++) {
+ if ((*data & 0xff000000) != 0xff000000) {
+ fprintf(stderr, " "); /* transparent */
+ } else if ((*data & 0x00ffffff) == 0x00ffffff) {
+ fprintf(stderr, "."); /* white */
+ } else if ((*data & 0x00ffffff) == 0x00000000) {
+ fprintf(stderr, "X"); /* black */
+ } else {
+ fprintf(stderr, "o"); /* other */
+ }
+ }
+ fprintf(stderr, "|\n");
+ }
+}
+
+QEMUCursor *cursor_builtin_hidden(void)
+{
+ QEMUCursor *c;
+
+ c = cursor_parse_xpm(cursor_hidden_xpm);
+ return c;
+}
+
+QEMUCursor *cursor_builtin_left_ptr(void)
+{
+ QEMUCursor *c;
+
+ c = cursor_parse_xpm(cursor_left_ptr_xpm);
+ return c;
+}
+
+QEMUCursor *cursor_alloc(int width, int height)
+{
+ QEMUCursor *c;
+ int datasize = width * height * sizeof(uint32_t);
+
+ c = qemu_mallocz(sizeof(QEMUCursor) + datasize);
+ c->width = width;
+ c->height = height;
+ c->refcount = 1;
+ return c;
+}
+
+void cursor_get(QEMUCursor *c)
+{
+ c->refcount++;
+}
+
+void cursor_put(QEMUCursor *c)
+{
+ if (c == NULL)
+ return;
+ c->refcount--;
+ if (c->refcount)
+ return;
+ qemu_free(c);
+}
+
+int cursor_get_mono_bpl(QEMUCursor *c)
+{
+ return (c->width + 7) / 8;
+}
+
+void cursor_set_mono(QEMUCursor *c,
+ uint32_t foreground, uint32_t background, uint8_t *image,
+ int transparent, uint8_t *mask)
+{
+ uint32_t *data = c->data;
+ uint8_t bit;
+ int x,y,bpl;
+
+ bpl = cursor_get_mono_bpl(c);
+ for (y = 0; y < c->height; y++) {
+ bit = 0x80;
+ for (x = 0; x < c->width; x++, data++) {
+ if (transparent && mask[x/8] & bit) {
+ *data = 0x00000000;
+ } else if (!transparent && !(mask[x/8] & bit)) {
+ *data = 0x00000000;
+ } else if (image[x/8] & bit) {
+ *data = 0xff000000 | foreground;
+ } else {
+ *data = 0xff000000 | background;
+ }
+ bit >>= 1;
+ if (bit == 0) {
+ bit = 0x80;
+ }
+ }
+ mask += bpl;
+ image += bpl;
+ }
+}
+
+void cursor_get_mono_image(QEMUCursor *c, int foreground, uint8_t *image)
+{
+ uint32_t *data = c->data;
+ uint8_t bit;
+ int x,y,bpl;
+
+ bpl = cursor_get_mono_bpl(c);
+ memset(image, 0, bpl * c->height);
+ for (y = 0; y < c->height; y++) {
+ bit = 0x80;
+ for (x = 0; x < c->width; x++, data++) {
+ if (((*data & 0xff000000) == 0xff000000) &&
+ ((*data & 0x00ffffff) == foreground)) {
+ image[x/8] |= bit;
+ }
+ bit >>= 1;
+ if (bit == 0) {
+ bit = 0x80;
+ }
+ }
+ image += bpl;
+ }
+}
+
+void cursor_get_mono_mask(QEMUCursor *c, int transparent, uint8_t *mask)
+{
+ uint32_t *data = c->data;
+ uint8_t bit;
+ int x,y,bpl;
+
+ bpl = cursor_get_mono_bpl(c);
+ memset(mask, 0, bpl * c->height);
+ for (y = 0; y < c->height; y++) {
+ bit = 0x80;
+ for (x = 0; x < c->width; x++, data++) {
+ if ((*data & 0xff000000) != 0xff000000) {
+ if (transparent != 0) {
+ mask[x/8] |= bit;
+ }
+ } else {
+ if (transparent == 0) {
+ mask[x/8] |= bit;
+ }
+ }
+ bit >>= 1;
+ if (bit == 0) {
+ bit = 0x80;
+ }
+ }
+ mask += bpl;
+ }
+}
diff --git a/cursor_hidden.xpm b/cursor_hidden.xpm
new file mode 100644
index 0000000..354e7a9
--- /dev/null
+++ b/cursor_hidden.xpm
@@ -0,0 +1,37 @@
+/* XPM */
+static const char *cursor_hidden_xpm[] = {
+ "32 32 1 1",
+ " c None",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+};
diff --git a/cursor_left_ptr.xpm b/cursor_left_ptr.xpm
new file mode 100644
index 0000000..6c9ada9
--- /dev/null
+++ b/cursor_left_ptr.xpm
@@ -0,0 +1,39 @@
+/* XPM */
+static const char *cursor_left_ptr_xpm[] = {
+ "32 32 3 1",
+ "X c #000000",
+ ". c #ffffff",
+ " c None",
+ "X ",
+ "XX ",
+ "X.X ",
+ "X..X ",
+ "X...X ",
+ "X....X ",
+ "X.....X ",
+ "X......X ",
+ "X.......X ",
+ "X........X ",
+ "X.....XXXXX ",
+ "X..X..X ",
+ "X.X X..X ",
+ "XX X..X ",
+ "X X..X ",
+ " X..X ",
+ " X..X ",
+ " X..X ",
+ " XX ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+ " ",
+};
commit 019e78ba6ec6f402dffc6bc9683f461a11a52c28
Author: Kevin Wolf <kwolf at redhat.com>
Date: Mon May 17 10:36:47 2010 +0200
Fix error handling in qemu_read_config_file
We need to close the file even in error case. While at it, make the callers
catch all kind of errors. ENOENT is allowed for default config files, they
are optional.
Reported-by: Luiz Capitulino <lcapitulino at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/qemu-config.c b/qemu-config.c
index d500885..aa376d4 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -521,14 +521,18 @@ out:
int qemu_read_config_file(const char *filename)
{
FILE *f = fopen(filename, "r");
+ int ret;
+
if (f == NULL) {
return -errno;
}
- if (qemu_config_parse(f, vm_config_groups, filename) != 0) {
- return -EINVAL;
- }
+ ret = qemu_config_parse(f, vm_config_groups, filename);
fclose(f);
- return 0;
+ if (ret == 0) {
+ return 0;
+ } else {
+ return -EINVAL;
+ }
}
diff --git a/vl.c b/vl.c
index 8c818f0..328395e 100644
--- a/vl.c
+++ b/vl.c
@@ -2662,12 +2662,12 @@ int main(int argc, char **argv, char **envp)
int ret;
ret = qemu_read_config_file(CONFIG_QEMU_CONFDIR "/qemu.conf");
- if (ret == -EINVAL) {
+ if (ret < 0 && ret != -ENOENT) {
exit(1);
}
ret = qemu_read_config_file(arch_config_name);
- if (ret == -EINVAL) {
+ if (ret < 0 && ret != -ENOENT) {
exit(1);
}
}
commit ebbeb789351a69d58b0da526fcb77bc82d18da7b
Author: Amos Kong <akong at redhat.com>
Date: Sun May 23 10:49:10 2010 +0800
Virtio-net: Replace the hardcode 6 with defined ETN_ALEN
hw/virtio-net.h:
#define ETH_ALEN 6
ETH_ALEN was defined by commit 7967406801aa897fae83caad3278ac85a342adaa
Signed-off-by: Amos Kong <akong at redhat.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/hw/virtio-net.h b/hw/virtio-net.h
index e55119b..235f1a9 100644
--- a/hw/virtio-net.h
+++ b/hw/virtio-net.h
@@ -54,8 +54,8 @@
struct virtio_net_config
{
- /* The config defining mac address (6 bytes) */
- uint8_t mac[6];
+ /* The config defining mac address ($ETH_ALEN bytes) */
+ uint8_t mac[ETH_ALEN];
/* See VIRTIO_NET_F_STATUS and VIRTIO_NET_S_* above */
uint16_t status;
} __attribute__((packed));
commit 111f8ec99b67aeef152c71a5db12f0c0cb2422bd
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Sun May 23 10:29:34 2010 +0200
sdl: Do not disable screensaver by default
Unless we are running in full-screen mode, QEMU's SDL window should not
disable the host's screensaver. The user can still change this behaviour
by setting the environment variable SDL_VIDEO_ALLOW_SCREENSAVER as
desired.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
diff --git a/sdl.c b/sdl.c
index 16a48e9..3bdd518 100644
--- a/sdl.c
+++ b/sdl.c
@@ -855,6 +855,10 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame)
if (no_frame)
gui_noframe = 1;
+ if (!full_screen) {
+ setenv("SDL_VIDEO_ALLOW_SCREENSAVER", "1", 0);
+ }
+
flags = SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE;
if (SDL_Init (flags)) {
fprintf(stderr, "Could not initialize SDL(%s) - exiting\n",
commit 9c678ccd15e71968ba9ce3cba704f429c5c7d539
Merge: 3853528... 3e89cb0...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date: Mon May 24 10:53:41 2010 -0500
Merge remote branch 'kwolf/for-anthony' into staging
commit 3853528a913f0807170e2c78b6ea692f8515c859
Merge: 16f0441... 41836a9...
Author: Anthony Liguori <aliguori at us.ibm.com>
Date: Mon May 24 09:00:24 2010 -0500
Merge remote branch 'qmp/for-anthony' into staging
commit 16f04416175844507b20072c422d08286ebbced6
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date: Mon May 24 11:14:04 2010 +0200
microblaze: Handle new elf mach nr for sysemu.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
diff --git a/hw/elf_ops.h b/hw/elf_ops.h
index 69c0757..27d1ab9 100644
--- a/hw/elf_ops.h
+++ b/hw/elf_ops.h
@@ -216,6 +216,11 @@ static int glue(load_elf, SZ)(const char *name, int fd,
if (EM_386 != ehdr.e_machine)
goto fail;
break;
+ case EM_MICROBLAZE:
+ if (EM_MICROBLAZE != ehdr.e_machine)
+ if (EM_MICROBLAZE_OLD != ehdr.e_machine)
+ goto fail;
+ break;
default:
if (elf_machine != ehdr.e_machine)
goto fail;
commit 259d5577ae546de27e25a40710f81aa031660de8
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Fri May 21 18:44:59 2010 +0200
lsi: Fix value overflow in request tag processing
This fixes a mismerge of 64d564094cac5f72eeaeb950c442b773a00d3586 (wrong
patch version): We need to mask the tag value properly to obtain its
device ID.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c
index 9d3c44d..f5a91ba 100644
--- a/hw/lsi53c895a.c
+++ b/hw/lsi53c895a.c
@@ -543,7 +543,7 @@ static void lsi_do_dma(LSIState *s, int out)
return;
}
- id = s->current->tag >> 8;
+ id = (s->current->tag >> 8) & 0xf;
dev = s->bus.devs[id];
if (!dev) {
lsi_bad_selection(s, id);
@@ -745,7 +745,7 @@ static void lsi_do_command(LSIState *s)
s->sfbr = buf[0];
s->command_complete = 0;
- id = s->select_tag >> 8;
+ id = (s->select_tag >> 8) & 0xf;
dev = s->bus.devs[id];
if (!dev) {
lsi_bad_selection(s, id);
commit 664a65b0dbd9a4845ac7d3c21e8b103031ee57f2
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date: Sat May 22 14:52:40 2010 +0400
sparc64: flush translations on mmu context change
- two pairs of softmmu indexes bind softmmu tlb to cpu tlb in fault handlers
using value of DMMU primary and secondary context registers, so we need to
flush softmmu translations when context registers are changed
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 28224b2..edeeb44 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -2959,9 +2959,15 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
break;
case 1: // Primary context
env->dmmu.mmu_primary_context = val;
+ /* can be optimized to only flush MMU_USER_IDX
+ and MMU_KERNEL_IDX entries */
+ tlb_flush(env, 1);
break;
case 2: // Secondary context
env->dmmu.mmu_secondary_context = val;
+ /* can be optimized to only flush MMU_USER_SECONDARY_IDX
+ and MMU_KERNEL_SECONDARY_IDX entries */
+ tlb_flush(env, 1);
break;
case 5: // TSB access
DPRINTF_MMU("dmmu TSB write: 0x%016" PRIx64 " -> 0x%016"
commit 9fd1ae3a0e3328056eaa2ae950ba0023e53423b2
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date: Sat May 22 14:52:35 2010 +0400
sparc64: fix mmu context at trap levels above zero
- cpu_mmu_index return MMU_NUCLEUS_IDX if trap level is not zero
- cpu_get_tb_cpu_state: store trap level and primary context in flags
this allows to restart code translation when address translation is changed
- stop translation block after writing to pstate and tl registers
- stop translation block after writing to alternate space
this can be optimized to stop only if address translation can be changed
by write operation (e.g. by comparing with MMU ASI values)
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 4fd58e9..8f0484b 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -556,7 +556,9 @@ static inline int cpu_mmu_index(CPUState *env1)
#elif !defined(TARGET_SPARC64)
return env1->psrs;
#else
- if (cpu_hypervisor_mode(env1)) {
+ if (env1->tl > 0) {
+ return MMU_NUCLEUS_IDX;
+ } else if (cpu_hypervisor_mode(env1)) {
return MMU_HYPV_IDX;
} else if (cpu_supervisor_mode(env1)) {
return MMU_KERNEL_IDX;
@@ -636,9 +638,13 @@ static inline void cpu_get_tb_cpu_state(CPUState *env, target_ulong *pc,
*cs_base = env->npc;
#ifdef TARGET_SPARC64
// AM . Combined FPU enable bits . PRIV . DMMU enabled . IMMU enabled
- *flags = ((env->pstate & PS_AM) << 2)
- | (((env->pstate & PS_PEF) >> 1) | ((env->fprs & FPRS_FEF) << 2))
- | (env->pstate & PS_PRIV) | ((env->lsu & (DMMU_E | IMMU_E)) >> 2);
+ *flags = ((env->pstate & PS_AM) << 2) /* 5 */
+ | (((env->pstate & PS_PEF) >> 1) /* 3 */
+ | ((env->fprs & FPRS_FEF) << 2)) /* 4 */
+ | (env->pstate & PS_PRIV) /* 2 */
+ | ((env->lsu & (DMMU_E | IMMU_E)) >> 2) /* 1, 0 */
+ | ((env->tl & 0xff) << 8)
+ | (env->dmmu.mmu_primary_context << 16); /* 16... */
#else
// FPU enable . Supervisor
*flags = (env->psref << 4) | env->psrs;
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 1045c31..96a22f3 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -572,6 +572,23 @@ static int get_physical_address(CPUState *env, target_phys_addr_t *physical,
/* ??? We treat everything as a small page, then explicitly flush
everything when an entry is evicted. */
*page_size = TARGET_PAGE_SIZE;
+
+#if defined (DEBUG_MMU)
+ /* safety net to catch wrong softmmu index use from dynamic code */
+ if (env->tl > 0 && mmu_idx != MMU_NUCLEUS_IDX) {
+ DPRINTF_MMU("get_physical_address %s tl=%d mmu_idx=%d"
+ " primary context=%" PRIx64
+ " secondary context=%" PRIx64
+ " address=%" PRIx64
+ "\n",
+ (rw == 2 ? "CODE" : "DATA"),
+ env->tl, mmu_idx,
+ env->dmmu.mmu_primary_context,
+ env->dmmu.mmu_secondary_context,
+ address);
+ }
+#endif
+
if (rw == 2)
return get_physical_address_code(env, physical, prot, address,
mmu_idx);
@@ -718,7 +735,7 @@ target_phys_addr_t cpu_get_phys_page_nofault(CPUState *env, target_ulong addr,
target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
{
- return cpu_get_phys_page_nofault(env, addr, MMU_KERNEL_IDX);
+ return cpu_get_phys_page_nofault(env, addr, cpu_mmu_index(env));
}
#endif
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 86096d2..72ca0b4 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -3484,14 +3484,14 @@ static void disas_sparc_insn(DisasContext * dc)
case 6: // pstate
save_state(dc, cpu_cond);
gen_helper_wrpstate(cpu_tmp0);
- gen_op_next_insn();
- tcg_gen_exit_tb(0);
- dc->is_br = 1;
+ dc->npc = DYNAMIC_PC;
break;
case 7: // tl
+ save_state(dc, cpu_cond);
tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_tmp0);
tcg_gen_st_i32(cpu_tmp32, cpu_env,
offsetof(CPUSPARCState, tl));
+ dc->npc = DYNAMIC_PC;
break;
case 8: // pil
gen_helper_wrpil(cpu_tmp0);
@@ -4550,6 +4550,7 @@ static void disas_sparc_insn(DisasContext * dc)
#endif
save_state(dc, cpu_cond);
gen_st_asi(cpu_val, cpu_addr, insn, 4);
+ dc->npc = DYNAMIC_PC;
break;
case 0x15: /* stba, store byte alternate */
#ifndef TARGET_SPARC64
@@ -4560,6 +4561,7 @@ static void disas_sparc_insn(DisasContext * dc)
#endif
save_state(dc, cpu_cond);
gen_st_asi(cpu_val, cpu_addr, insn, 1);
+ dc->npc = DYNAMIC_PC;
break;
case 0x16: /* stha, store halfword alternate */
#ifndef TARGET_SPARC64
@@ -4570,6 +4572,7 @@ static void disas_sparc_insn(DisasContext * dc)
#endif
save_state(dc, cpu_cond);
gen_st_asi(cpu_val, cpu_addr, insn, 2);
+ dc->npc = DYNAMIC_PC;
break;
case 0x17: /* stda, store double word alternate */
#ifndef TARGET_SPARC64
@@ -4594,6 +4597,7 @@ static void disas_sparc_insn(DisasContext * dc)
case 0x1e: /* V9 stxa */
save_state(dc, cpu_cond);
gen_st_asi(cpu_val, cpu_addr, insn, 8);
+ dc->npc = DYNAMIC_PC;
break;
#endif
default:
commit e21295860883e0e1f8acc352f21eb9563b5cfd40
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date: Sat May 22 14:52:29 2010 +0400
sparc64: fix dump_mmu to look for global bit in tte value instead of tag
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 538795f..1045c31 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -653,7 +653,7 @@ void dump_mmu(CPUState *env)
env->dtlb[i].tte & 0x2? "RW": "RO",
env->dtlb[i].tte & 0x40? "locked": "unlocked",
env->dtlb[i].tag & (uint64_t)0x1fffULL,
- TTE_IS_GLOBAL(env->dtlb[i].tag)? "global" : "local");
+ TTE_IS_GLOBAL(env->dtlb[i].tte)? "global" : "local");
}
}
}
@@ -687,7 +687,7 @@ void dump_mmu(CPUState *env)
env->itlb[i].tte & 0x4? "priv": "user",
env->itlb[i].tte & 0x40? "locked": "unlocked",
env->itlb[i].tag & (uint64_t)0x1fffULL,
- TTE_IS_GLOBAL(env->itlb[i].tag)? "global" : "local");
+ TTE_IS_GLOBAL(env->itlb[i].tte)? "global" : "local");
}
}
}
commit 2aae2b8e0abd58e76d616bcbe93c6966d06d0188
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date: Sat May 22 14:52:24 2010 +0400
sparc64: fix pstate privilege bits
- refactor code to handle hpstate only if available for current cpu
- conditionally set hypervisor bit in hpstate register
- reorder softmmu indices so user accessable ones go first, translation context
macros supervisor() and hypervisor() adjusted as well
- disable sparcv8 registers for TARGET_SPARC64
- fix cpu_mmu_index to use sparcv9 bits only
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/target-sparc/cpu.h b/target-sparc/cpu.h
index 27b020b..4fd58e9 100644
--- a/target-sparc/cpu.h
+++ b/target-sparc/cpu.h
@@ -92,12 +92,14 @@
#define PSR_CARRY_SHIFT 20
#define PSR_CARRY (1 << PSR_CARRY_SHIFT)
#define PSR_ICC (PSR_NEG|PSR_ZERO|PSR_OVF|PSR_CARRY)
+#if !defined(TARGET_SPARC64)
#define PSR_EF (1<<12)
#define PSR_PIL 0xf00
#define PSR_S (1<<7)
#define PSR_PS (1<<6)
#define PSR_ET (1<<5)
#define PSR_CWP 0x1f
+#endif
#define CC_SRC (env->cc_src)
#define CC_SRC2 (env->cc_src2)
@@ -341,14 +343,16 @@ typedef struct CPUSPARCState {
uint32_t wim; /* window invalid mask */
#endif
target_ulong tbr; /* trap base register */
+#if !defined(TARGET_SPARC64)
int psrs; /* supervisor mode (extracted from PSR) */
int psrps; /* previous supervisor mode */
-#if !defined(TARGET_SPARC64)
int psret; /* enable traps */
#endif
uint32_t psrpil; /* interrupt blocking level */
uint32_t pil_in; /* incoming interrupt level bitmap */
+#if !defined(TARGET_SPARC64)
int psref; /* enable fpu */
+#endif
target_ulong version;
int interrupt_index;
uint32_t nwindows;
@@ -508,21 +512,41 @@ int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc);
#define CPU_SAVE_VERSION 6
/* MMU modes definitions */
+#if defined (TARGET_SPARC64)
+#define MMU_USER_IDX 0
#define MMU_MODE0_SUFFIX _user
-#define MMU_MODE1_SUFFIX _kernel
-#ifdef TARGET_SPARC64
-#define MMU_MODE2_SUFFIX _hypv
-#define MMU_MODE3_SUFFIX _nucleus
-#define MMU_MODE4_SUFFIX _user_secondary
-#define MMU_MODE5_SUFFIX _kernel_secondary
-#endif
+#define MMU_USER_SECONDARY_IDX 1
+#define MMU_MODE1_SUFFIX _user_secondary
+#define MMU_KERNEL_IDX 2
+#define MMU_MODE2_SUFFIX _kernel
+#define MMU_KERNEL_SECONDARY_IDX 3
+#define MMU_MODE3_SUFFIX _kernel_secondary
+#define MMU_NUCLEUS_IDX 4
+#define MMU_MODE4_SUFFIX _nucleus
+#define MMU_HYPV_IDX 5
+#define MMU_MODE5_SUFFIX _hypv
+#else
#define MMU_USER_IDX 0
+#define MMU_MODE0_SUFFIX _user
#define MMU_KERNEL_IDX 1
-#define MMU_HYPV_IDX 2
-#ifdef TARGET_SPARC64
-#define MMU_NUCLEUS_IDX 3
-#define MMU_USER_SECONDARY_IDX 4
-#define MMU_KERNEL_SECONDARY_IDX 5
+#define MMU_MODE1_SUFFIX _kernel
+#endif
+
+#if defined (TARGET_SPARC64)
+static inline int cpu_has_hypervisor(CPUState *env1)
+{
+ return env1->def->features & CPU_FEATURE_HYPV;
+}
+
+static inline int cpu_hypervisor_mode(CPUState *env1)
+{
+ return cpu_has_hypervisor(env1) && (env1->hpstate & HS_PRIV);
+}
+
+static inline int cpu_supervisor_mode(CPUState *env1)
+{
+ return env1->pstate & PS_PRIV;
+}
#endif
static inline int cpu_mmu_index(CPUState *env1)
@@ -532,12 +556,13 @@ static inline int cpu_mmu_index(CPUState *env1)
#elif !defined(TARGET_SPARC64)
return env1->psrs;
#else
- if (!env1->psrs)
- return MMU_USER_IDX;
- else if ((env1->hpstate & HS_PRIV) == 0)
- return MMU_KERNEL_IDX;
- else
+ if (cpu_hypervisor_mode(env1)) {
return MMU_HYPV_IDX;
+ } else if (cpu_supervisor_mode(env1)) {
+ return MMU_KERNEL_IDX;
+ } else {
+ return MMU_USER_IDX;
+ }
#endif
}
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 4a494de..538795f 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -746,12 +746,12 @@ void cpu_reset(CPUSPARCState *env)
#else
#if !defined(TARGET_SPARC64)
env->psret = 0;
-#endif
env->psrs = 1;
env->psrps = 1;
+#endif
#ifdef TARGET_SPARC64
env->pstate = PS_PRIV|PS_RED|PS_PEF|PS_AG;
- env->hpstate = HS_PRIV;
+ env->hpstate = cpu_has_hypervisor(env) ? HS_PRIV : 0;
env->tl = env->maxtl;
cpu_tsptr(env)->tt = TT_POWER_ON_RESET;
env->lsu = 0;
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index d0bc277..28224b2 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -1404,11 +1404,7 @@ static target_ulong get_psr(void)
(env->psrps? PSR_PS : 0) |
(env->psret? PSR_ET : 0) | env->cwp;
#else
- return env->version | (env->psr & PSR_ICC) |
- (env->psref? PSR_EF : 0) |
- (env->psrpil << 8) |
- (env->psrs? PSR_S : 0) |
- (env->psrps? PSR_PS : 0) | env->cwp;
+ return env->psr & PSR_ICC;
#endif
}
@@ -1427,17 +1423,19 @@ target_ulong cpu_get_psr(CPUState *env1)
static void put_psr(target_ulong val)
{
env->psr = val & PSR_ICC;
+#if !defined (TARGET_SPARC64)
env->psref = (val & PSR_EF)? 1 : 0;
env->psrpil = (val & PSR_PIL) >> 8;
+#endif
#if ((!defined (TARGET_SPARC64)) && !defined(CONFIG_USER_ONLY))
cpu_check_irqs(env);
#endif
+#if !defined (TARGET_SPARC64)
env->psrs = (val & PSR_S)? 1 : 0;
env->psrps = (val & PSR_PS)? 1 : 0;
-#if !defined (TARGET_SPARC64)
env->psret = (val & PSR_ET)? 1 : 0;
-#endif
set_cwp(val & PSR_CWP);
+#endif
env->cc_op = CC_OP_FLAGS;
}
@@ -2326,7 +2324,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
asi &= 0xff;
if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
- || ((env->def->features & CPU_FEATURE_HYPV)
+ || (cpu_has_hypervisor(env)
&& asi >= 0x30 && asi < 0x80
&& !(env->hpstate & HS_PRIV)))
raise_exception(TT_PRIV_ACT);
@@ -2361,8 +2359,7 @@ uint64_t helper_ld_asi(target_ulong addr, int asi, int size, int sign)
case 0xe2: // UA2007 Primary block init
case 0xe3: // UA2007 Secondary block init
if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
- if ((env->def->features & CPU_FEATURE_HYPV)
- && env->hpstate & HS_PRIV) {
+ if (cpu_hypervisor_mode(env)) {
switch(size) {
case 1:
ret = ldub_hypv(addr);
@@ -2678,7 +2675,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
asi &= 0xff;
if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
- || ((env->def->features & CPU_FEATURE_HYPV)
+ || (cpu_has_hypervisor(env)
&& asi >= 0x30 && asi < 0x80
&& !(env->hpstate & HS_PRIV)))
raise_exception(TT_PRIV_ACT);
@@ -2722,8 +2719,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
case 0xe2: // UA2007 Primary block init
case 0xe3: // UA2007 Secondary block init
if ((asi & 0x80) && (env->pstate & PS_PRIV)) {
- if ((env->def->features & CPU_FEATURE_HYPV)
- && env->hpstate & HS_PRIV) {
+ if (cpu_hypervisor_mode(env)) {
switch(size) {
case 1:
stb_hypv(addr, val);
@@ -3048,7 +3044,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
void helper_ldda_asi(target_ulong addr, int asi, int rd)
{
if ((asi < 0x80 && (env->pstate & PS_PRIV) == 0)
- || ((env->def->features & CPU_FEATURE_HYPV)
+ || (cpu_has_hypervisor(env)
&& asi >= 0x30 && asi < 0x80
&& !(env->hpstate & HS_PRIV)))
raise_exception(TT_PRIV_ACT);
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 8129b79..86096d2 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -183,9 +183,9 @@ static void gen_op_store_QT0_fpr(unsigned int dst)
#define hypervisor(dc) 0
#endif
#else
-#define supervisor(dc) (dc->mem_idx >= 1)
+#define supervisor(dc) (dc->mem_idx >= MMU_KERNEL_IDX)
#ifdef TARGET_SPARC64
-#define hypervisor(dc) (dc->mem_idx == 2)
+#define hypervisor(dc) (dc->mem_idx == MMU_HYPV_IDX)
#else
#endif
#endif
commit b8e9fc0625c49404d63b4391f6dc5cf27be8b45b
Author: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Date: Sat May 22 14:52:19 2010 +0400
sparc64: generate data access exception on RW violation
- separate PRIV and PROT handling
- DPRINTF_MMU macro to clean up debug code
- dump mmu_idx, trap level and mmu context registers
along with address translation values
Signed-off-by: Igor V. Kovalenko <igor.v.kovalenko at gmail.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 2fbbbbf..4a494de 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -30,6 +30,13 @@
//#define DEBUG_MMU
//#define DEBUG_FEATURES
+#ifdef DEBUG_MMU
+#define DPRINTF_MMU(fmt, ...) \
+ do { printf("MMU: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF_MMU(fmt, ...) do {} while (0)
+#endif
+
static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model);
/* Sparc MMU emulation */
@@ -451,42 +458,50 @@ static int get_physical_address_data(CPUState *env,
for (i = 0; i < 64; i++) {
// ctx match, vaddr match, valid?
- if (ultrasparc_tag_match(&env->dtlb[i],
- address, context, physical)) {
+ if (ultrasparc_tag_match(&env->dtlb[i], address, context, physical)) {
+
+ uint8_t fault_type = 0;
+
// access ok?
- if (((env->dtlb[i].tte & 0x4) && is_user) ||
- (!(env->dtlb[i].tte & 0x2) && (rw == 1))) {
- uint8_t fault_type = 0;
+ if ((env->dtlb[i].tte & 0x4) && is_user) {
+ fault_type |= 1; /* privilege violation */
+ env->exception_index = TT_DFAULT;
- if ((env->dtlb[i].tte & 0x4) && is_user) {
- fault_type |= 1; /* privilege violation */
- }
+ DPRINTF_MMU("DFAULT at %" PRIx64 " context %" PRIx64
+ " mmu_idx=%d tl=%d\n",
+ address, context, mmu_idx, env->tl);
+ } else if (!(env->dtlb[i].tte & 0x2) && (rw == 1)) {
+ env->exception_index = TT_DPROT;
- if (env->dmmu.sfsr & 1) /* Fault status register */
- env->dmmu.sfsr = 2; /* overflow (not read before
+ DPRINTF_MMU("DPROT at %" PRIx64 " context %" PRIx64
+ " mmu_idx=%d tl=%d\n",
+ address, context, mmu_idx, env->tl);
+ } else {
+ *prot = PAGE_READ;
+ if (env->dtlb[i].tte & 0x2)
+ *prot |= PAGE_WRITE;
+
+ TTE_SET_USED(env->dtlb[i].tte);
+
+ return 0;
+ }
+
+ if (env->dmmu.sfsr & 1) /* Fault status register */
+ env->dmmu.sfsr = 2; /* overflow (not read before
another fault) */
- env->dmmu.sfsr |= (is_user << 3) | ((rw == 1) << 2) | 1;
+ env->dmmu.sfsr |= (is_user << 3) | ((rw == 1) << 2) | 1;
- env->dmmu.sfsr |= (fault_type << 7);
+ env->dmmu.sfsr |= (fault_type << 7);
- env->dmmu.sfar = address; /* Fault address register */
- env->exception_index = TT_DFAULT;
-#ifdef DEBUG_MMU
- printf("DFAULT at 0x%" PRIx64 "\n", address);
-#endif
- return 1;
- }
- *prot = PAGE_READ;
- if (env->dtlb[i].tte & 0x2)
- *prot |= PAGE_WRITE;
- TTE_SET_USED(env->dtlb[i].tte);
- return 0;
+ env->dmmu.sfar = address; /* Fault address register */
+ return 1;
}
}
-#ifdef DEBUG_MMU
- printf("DMISS at 0x%" PRIx64 "\n", address);
-#endif
+
+ DPRINTF_MMU("DMISS at %" PRIx64 " context %" PRIx64 "\n",
+ address, context);
+
env->dmmu.tag_access = (address & ~0x1fffULL) | context;
env->exception_index = TT_DMISS;
return 1;
@@ -528,9 +543,10 @@ static int get_physical_address_code(CPUState *env,
another fault) */
env->immu.sfsr |= (is_user << 3) | 1;
env->exception_index = TT_TFAULT;
-#ifdef DEBUG_MMU
- printf("TFAULT at 0x%" PRIx64 "\n", address);
-#endif
+
+ DPRINTF_MMU("TFAULT at %" PRIx64 " context %" PRIx64 "\n",
+ address, context);
+
return 1;
}
*prot = PAGE_EXEC;
@@ -538,9 +554,10 @@ static int get_physical_address_code(CPUState *env,
return 0;
}
}
-#ifdef DEBUG_MMU
- printf("TMISS at 0x%" PRIx64 "\n", address);
-#endif
+
+ DPRINTF_MMU("TMISS at %" PRIx64 " context %" PRIx64 "\n",
+ address, context);
+
/* Context is stored in DMMU (dmmuregs[1]) also for IMMU */
env->immu.tag_access = (address & ~0x1fffULL) | context;
env->exception_index = TT_TMISS;
@@ -578,10 +595,18 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
virt_addr = address & TARGET_PAGE_MASK;
vaddr = virt_addr + ((address & TARGET_PAGE_MASK) &
(TARGET_PAGE_SIZE - 1));
-#ifdef DEBUG_MMU
- printf("Translate at 0x%" PRIx64 " -> 0x%" PRIx64 ", vaddr 0x%" PRIx64
- "\n", address, paddr, vaddr);
-#endif
+
+ DPRINTF_MMU("Translate at %" PRIx64 " -> %" PRIx64 ","
+ " vaddr %" PRIx64
+ " mmu_idx=%d"
+ " tl=%d"
+ " primary context=%" PRIx64
+ " secondary context=%" PRIx64
+ "\n",
+ address, paddr, vaddr, mmu_idx, env->tl,
+ env->dmmu.mmu_primary_context,
+ env->dmmu.mmu_secondary_context);
+
tlb_set_page(env, vaddr, paddr, prot, mmu_idx, page_size);
return 0;
}
commit 65899fe34b09ab4af4b045977460b531ec5c1f73
Author: Artyom Tarasenko <atar4qemu at googlemail.com>
Date: Sat May 22 10:38:56 2010 +0200
sparc32 protect read-only bits in DMA CSR registers
On a real hardware changing read-only bits has no effect
Use a mask common for SCSI and Ethernet registers. The crucial
bit is DMA_INTR, because setting or clearing it may produce
spurious interrupts.
This patch allows booting Solaris 2.3
Signed-off-by: Artyom Tarasenko <atar4qemu at gmail.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/sparc32_dma.c b/hw/sparc32_dma.c
index 3ceb851..b521707 100644
--- a/hw/sparc32_dma.c
+++ b/hw/sparc32_dma.c
@@ -62,6 +62,9 @@
#define DMA_DRAIN_FIFO 0x40
#define DMA_RESET 0x80
+/* XXX SCSI and ethernet should have different read-only bit masks */
+#define DMA_CSR_RO_MASK 0xfe000007
+
typedef struct DMAState DMAState;
struct DMAState {
@@ -187,7 +190,7 @@ static void dma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
switch (saddr) {
case 0:
if (val & DMA_INTREN) {
- if (val & DMA_INTR) {
+ if (s->dmaregs[0] & DMA_INTR) {
DPRINTF("Raise IRQ\n");
qemu_irq_raise(s->irq);
}
@@ -204,16 +207,17 @@ static void dma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
val &= ~DMA_DRAIN_FIFO;
} else if (val == 0)
val = DMA_DRAIN_FIFO;
- val &= 0x0fffffff;
+ val &= ~DMA_CSR_RO_MASK;
val |= DMA_VER;
+ s->dmaregs[0] = (s->dmaregs[0] & DMA_CSR_RO_MASK) | val;
break;
case 1:
s->dmaregs[0] |= DMA_LOADED;
- break;
+ /* fall through */
default:
+ s->dmaregs[saddr] = val;
break;
}
- s->dmaregs[saddr] = val;
}
static CPUReadMemoryFunc * const dma_mem_read[3] = {
commit ae6b2c4ed956c17456e70efefe13ad0ab7db31de
Author: TeLeMan <geleman at gmail.com>
Date: Wed May 12 10:28:51 2010 +0800
vmstate: fix breakage by 7e72abc382b700a72549e8147bdea413534eeedc
cirrus_post_load() will be executed twice when loading vm states and then the
wrong physical memory will be registered. This issue may lead to crash qemu.
Signed-off-by: TeLeMan <geleman at gmail.com>
Acked-by: Juan Quintela <quintela at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index 9f61a01..ba48289 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -2985,7 +2985,6 @@ static const VMStateDescription vmstate_pci_cirrus_vga = {
.version_id = 2,
.minimum_version_id = 2,
.minimum_version_id_old = 2,
- .post_load = cirrus_post_load,
.fields = (VMStateField []) {
VMSTATE_PCI_DEVICE(dev, PCICirrusVGAState),
VMSTATE_STRUCT(cirrus_vga, PCICirrusVGAState, 0,
commit 9848bbf1a8b69cc6a8497b075ce5d171f7c62f1a
Author: Markus Armbruster <armbru at redhat.com>
Date: Tue May 11 14:02:31 2010 +0200
Fix -device help and documentation
Commit 6616b2ad reverted commit 40ea285c. Looks like a mismerge to
me.
Signed-off-by: Markus Armbruster <armbru at redhat.com>
Acked-by: Stefan Weil <weil at mail.berlios.de>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/qemu-options.hx b/qemu-options.hx
index 12f6b51..03e95fd 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -464,18 +464,15 @@ DEF("device", HAS_ARG, QEMU_OPTION_device,
" add device (based on driver)\n"
" prop=value,... sets driver properties\n"
" use -device ? to print all possible drivers\n"
- " use -device driver,? to print all possible options\n"
- " use -device driver,option=? to print a help for value\n",
+ " use -device driver,? to print all possible properties\n",
QEMU_ARCH_ALL)
STEXI
- at item -device @var{driver}[, at var{option}[=@var{value}][,...]]
+ at item -device @var{driver}[, at var{prop}[=@var{value}][,...]]
@findex -device
-Add device @var{driver}. Depending on the device type,
- at var{option} (with default or given @var{value}) may be useful.
-To get a help on possible @var{driver}s, @var{option}s or @var{value}s, use
- at code{-device ?},
- at code{-device @var{driver},?} or
- at code{-device @var{driver}, at var{option}=?}.
+Add device @var{driver}. @var{prop}=@var{value} sets driver
+properties. Valid properties depend on the driver. To get help on
+possible drivers and properties, use @code{-device ?} and
+ at code{-device @var{driver},?}.
ETEXI
#ifdef CONFIG_LINUX
commit 4c0a6db01b89ff314b964ff7a9ae51276f127a34
Author: Stuart Brady <sdb at zubnet.me.uk>
Date: Wed May 12 20:42:04 2010 +0100
Fix tarbin Makefile rule
The 'tarbin' Makefile rule doesn't include qemu-system-sparc64, but
should do, now that sparc64-softmmu is in the default target list.
The rule attempts to tar up binaries that were not built if a target
list was passed to the configure script -- in which case, it will
either fail, or otherwise include binaries from previous builds.
Fix both problems once and for all by building a list of binaries to
include in the tarball, using the list of targets to be built.
Signed-off-by: Stuart Brady <sdb at zubnet.me.uk>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/Makefile b/Makefile
index 306a1a4..7986bf6 100644
--- a/Makefile
+++ b/Makefile
@@ -299,43 +299,22 @@ tar:
cd /tmp && tar zcvf ~/$(FILE).tar.gz $(FILE) --exclude CVS --exclude .git --exclude .svn
rm -rf /tmp/$(FILE)
+SYSTEM_TARGETS=$(filter %-softmmu,$(TARGET_DIRS))
+SYSTEM_PROGS=$(patsubst qemu-system-i386,qemu, \
+ $(patsubst %-softmmu,qemu-system-%, \
+ $(SYSTEM_TARGETS)))
+
+USER_TARGETS=$(filter %-user,$(TARGET_DIRS))
+USER_PROGS=$(patsubst %-bsd-user,qemu-%, \
+ $(patsubst %-darwin-user,qemu-%, \
+ $(patsubst %-linux-user,qemu-%, \
+ $(USER_TARGETS))))
+
# generate a binary distribution
tarbin:
cd / && tar zcvf ~/qemu-$(VERSION)-$(ARCH).tar.gz \
- $(bindir)/qemu \
- $(bindir)/qemu-system-x86_64 \
- $(bindir)/qemu-system-arm \
- $(bindir)/qemu-system-cris \
- $(bindir)/qemu-system-m68k \
- $(bindir)/qemu-system-microblaze \
- $(bindir)/qemu-system-mips \
- $(bindir)/qemu-system-mipsel \
- $(bindir)/qemu-system-mips64 \
- $(bindir)/qemu-system-mips64el \
- $(bindir)/qemu-system-ppc \
- $(bindir)/qemu-system-ppcemb \
- $(bindir)/qemu-system-ppc64 \
- $(bindir)/qemu-system-sh4 \
- $(bindir)/qemu-system-sh4eb \
- $(bindir)/qemu-system-sparc \
- $(bindir)/qemu-i386 \
- $(bindir)/qemu-x86_64 \
- $(bindir)/qemu-alpha \
- $(bindir)/qemu-arm \
- $(bindir)/qemu-armeb \
- $(bindir)/qemu-cris \
- $(bindir)/qemu-m68k \
- $(bindir)/qemu-microblaze \
- $(bindir)/qemu-mips \
- $(bindir)/qemu-mipsel \
- $(bindir)/qemu-ppc \
- $(bindir)/qemu-ppc64 \
- $(bindir)/qemu-ppc64abi32 \
- $(bindir)/qemu-sh4 \
- $(bindir)/qemu-sh4eb \
- $(bindir)/qemu-sparc \
- $(bindir)/qemu-sparc64 \
- $(bindir)/qemu-sparc32plus \
+ $(patsubst %,$(bindir)/%, $(SYSTEM_PROGS)) \
+ $(patsubst %,$(bindir)/%, $(USER_PROGS)) \
$(bindir)/qemu-img \
$(bindir)/qemu-nbd \
$(datadir)/bios.bin \
commit 6c913ba5f353741fc8284f54675b26943ecc7b8b
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Thu May 20 09:16:33 2010 +0200
hxtool: Add syntax error detection
Add basic imbalance detection for STEXT/ETEXI.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hxtool b/hxtool
index 0fdbc64..8f65532 100644
--- a/hxtool
+++ b/hxtool
@@ -19,11 +19,24 @@ hxtoh()
hxtotexi()
{
flag=0
+ line=1
while read -r str; do
case "$str" in
HXCOMM*)
;;
- STEXI*|ETEXI*) flag=$(($flag^1))
+ STEXI*)
+ if test $flag -eq 1 ; then
+ echo "line $line: syntax error: expected ETEXI, found $str" >&2
+ exit 1
+ fi
+ flag=1
+ ;;
+ ETEXI*)
+ if test $flag -ne 1 ; then
+ echo "line $line: syntax error: expected STEXI, found $str" >&2
+ exit 1
+ fi
+ flag=0
;;
DEFHEADING*)
echo "$(expr "$str" : "DEFHEADING(\(.*\))")"
@@ -32,6 +45,7 @@ hxtotexi()
test $flag -eq 1 && echo "$str"
;;
esac
+ line=$((line+1))
done
}
commit 3c4c32101bdb4ee939e40a8e3d3f9d2a5d0ec053
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Thu May 20 09:16:30 2010 +0200
Fix TEXI section mark imbalance in qemu-img-cmd.hx
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/qemu-img-cmds.hx b/qemu-img-cmds.hx
index c079019..c4cf3e7 100644
--- a/qemu-img-cmds.hx
+++ b/qemu-img-cmds.hx
@@ -7,7 +7,7 @@ HXCOMM HXCOMM can be used for comments, discarded from both texi and C
STEXI
@table @option
-STEXI
+ETEXI
DEF("check", img_check,
"check [-f fmt] filename")
commit a71cd2a523f9b35ffeba8de3c536e494e255e6ea
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Sat May 15 13:03:28 2010 +0200
Put dependency files in proper subdir
This seems to resolve subtle breakages of our build system:
Dependency files generated for targets like 'dir/foo.o' were saved as
'foo.d'. Now, if there was also a target 'foo.o', one of the dependency
file was overwritten. Concrete example: libhw*/macio.o vs.
libhw*/ide/macio.o. And this often left a segfaulting build result
behind when changing the "wrong" data structures".
Fix it by generating proper 'dir/foo.d'.
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Acked-by: Paolo Bonzini <pbonzini at redhat.com>
Acked-by: Juan Quintela <quintela at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/rules.mak b/rules.mak
index 7e10432..c843a13 100644
--- a/rules.mak
+++ b/rules.mak
@@ -12,7 +12,7 @@ MAKEFLAGS += -rR
%.mak:
# Flags for dependency generation
-QEMU_DGFLAGS += -MMD -MP -MT $@
+QEMU_DGFLAGS += -MMD -MP -MT $@ -MF $(*D)/$(*F).d
%.o: %.c
$(call quiet-command,$(CC) $(QEMU_CFLAGS) $(QEMU_DGFLAGS) $(CFLAGS) -c -o $@ $<," CC $(TARGET_DIR)$@")
commit b1acdd2cf1c45cf8278fe58d960a1480bf3f280e
Author: Jan Kiszka <jan.kiszka at siemens.com>
Date: Sat May 15 13:03:30 2010 +0200
Clean libhw subdirs as well
Signed-off-by: Jan Kiszka <jan.kiszka at siemens.com>
Acked-by: Paolo Bonzini <pbonzini at redhat.com>
Acked-by: Juan Quintela <quintela at redhat.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/Makefile.hw b/Makefile.hw
index be35359..b9181ab 100644
--- a/Makefile.hw
+++ b/Makefile.hw
@@ -18,7 +18,7 @@ all: $(hw-obj-y)
@true
clean:
- rm -f *.o *.d *.a *~
+ rm -f *.o */*.o *.d */*.d *.a */*.a *~ */*~
# Include automatically generated dependency files
-include $(wildcard *.d */*.d)
commit 0bfcd599e3f5c5679cc7d0165a0a1822e2f60de2
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sat May 22 08:02:12 2010 +0000
Fix %lld or %llx printf format use
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/audio/audio_template.h b/audio/audio_template.h
index 6b19848..2f5224b 100644
--- a/audio/audio_template.h
+++ b/audio/audio_template.h
@@ -541,7 +541,7 @@ uint64_t glue (AUD_get_elapsed_usec_, TYPE) (SW *sw, QEMUAudioTimeStamp *ts)
cur_ts = sw->hw->ts_helper;
old_ts = ts->old_ts;
- /* dolog ("cur %lld old %lld\n", cur_ts, old_ts); */
+ /* dolog ("cur %" PRId64 " old %" PRId64 "\n", cur_ts, old_ts); */
if (cur_ts >= old_ts) {
delta = cur_ts - old_ts;
diff --git a/block/curl.c b/block/curl.c
index b944740..407f095 100644
--- a/block/curl.c
+++ b/block/curl.c
@@ -104,10 +104,11 @@ static size_t curl_size_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
{
CURLState *s = ((CURLState*)opaque);
size_t realsize = size * nmemb;
- long long fsize;
+ size_t fsize;
- if(sscanf(ptr, "Content-Length: %lld", &fsize) == 1)
+ if(sscanf(ptr, "Content-Length: %zd", &fsize) == 1) {
s->s->len = fsize;
+ }
return realsize;
}
@@ -118,7 +119,7 @@ static size_t curl_read_cb(void *ptr, size_t size, size_t nmemb, void *opaque)
size_t realsize = size * nmemb;
int i;
- DPRINTF("CURL: Just reading %lld bytes\n", (unsigned long long)realsize);
+ DPRINTF("CURL: Just reading %zd bytes\n", realsize);
if (!s || !s->orig_buf)
goto read_end;
@@ -368,7 +369,7 @@ static int curl_open(BlockDriverState *bs, const char *filename, int flags)
s->len = (size_t)d;
else if(!s->len)
goto out;
- DPRINTF("CURL: Size = %lld\n", (long long)s->len);
+ DPRINTF("CURL: Size = %zd\n", s->len);
curl_clean_state(state);
curl_easy_cleanup(state->curl);
@@ -450,8 +451,9 @@ static BlockDriverAIOCB *curl_aio_readv(BlockDriverState *bs,
state->orig_buf = qemu_malloc(state->buf_len);
state->acb[0] = acb;
- snprintf(state->range, 127, "%lld-%lld", (long long)start, (long long)end);
- DPRINTF("CURL (AIO): Reading %d at %lld (%s)\n", (nb_sectors * SECTOR_SIZE), start, state->range);
+ snprintf(state->range, 127, "%zd-%zd", start, end);
+ DPRINTF("CURL (AIO): Reading %d at %zd (%s)\n",
+ (nb_sectors * SECTOR_SIZE), start, state->range);
curl_easy_setopt(state->curl, CURLOPT_RANGE, state->range);
curl_multi_add_handle(s->multi, state->curl);
diff --git a/block/qcow2.c b/block/qcow2.c
index 0ce7150..5b72758 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -93,8 +93,9 @@ static int qcow_read_extensions(BlockDriverState *bs, uint64_t start_offset,
#endif
if (bdrv_pread(bs->file, offset, &ext, sizeof(ext)) != sizeof(ext)) {
- fprintf(stderr, "qcow_handle_extension: ERROR: pread fail from offset %llu\n",
- (unsigned long long)offset);
+ fprintf(stderr, "qcow_handle_extension: ERROR: "
+ "pread fail from offset %" PRIu64 "\n",
+ offset);
return 1;
}
be32_to_cpus(&ext.magic);
@@ -1245,7 +1246,8 @@ static void dump_refcounts(BlockDriverState *bs)
k++;
while (k < nb_clusters && get_refcount(bs, k) == refcount)
k++;
- printf("%lld: refcount=%d nb=%lld\n", k, refcount, k - k1);
+ printf("%" PRId64 ": refcount=%d nb=%" PRId64 "\n", k, refcount,
+ k - k1);
}
}
#endif
diff --git a/darwin-user/commpage.c b/darwin-user/commpage.c
index 2b41bc5..f6aa71e 100644
--- a/darwin-user/commpage.c
+++ b/darwin-user/commpage.c
@@ -237,7 +237,7 @@ void do_compare_and_swap64(void *cpu_env, int num)
uint64_t *value = (uint64_t*)((CPUX86State*)cpu_env)->regs[R_ESI];
old = (uint64_t)((uint64_t)((CPUX86State*)cpu_env)->regs[R_EDX]) << 32 | (uint64_t)((CPUX86State*)cpu_env)->regs[R_EAX];
- DPRINTF("commpage: compare_and_swap64(%llx,new,%p)\n", old, value);
+ DPRINTF("commpage: compare_and_swap64(%" PRIx64 ",new,%p)\n", old, value);
swapped_val = tswap64(*value);
if(old == swapped_val)
diff --git a/darwin-user/syscall.c b/darwin-user/syscall.c
index d774ad3..060acc8 100644
--- a/darwin-user/syscall.c
+++ b/darwin-user/syscall.c
@@ -858,7 +858,7 @@ long no_syscall(void *cpu_env, int num);
long do_pread(uint32_t arg1, void * arg2, size_t arg3, off_t arg4)
{
- DPRINTF("0x%x, %p, 0x%lx, 0x%llx\n", arg1, arg2, arg3, arg4);
+ DPRINTF("0x%x, %p, 0x%lx, 0x%" PRIx64 "\n", arg1, arg2, arg3, arg4);
long ret = pread(arg1, arg2, arg3, arg4);
return ret;
}
diff --git a/hw/vga.c b/hw/vga.c
index 87a1bb0..01de1e1 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -232,7 +232,7 @@ static void vga_precise_update_retrace_info(VGACommonState *s)
"clocking_mode = %d\n"
"clock_sel = %d %d\n"
"dots = %d\n"
- "ticks/char = %lld\n"
+ "ticks/char = %" PRId64 "\n"
"\n",
(double) get_ticks_per_sec() / (r->ticks_per_char * r->total_chars),
htotal_chars,
diff --git a/hw/vhost_net.c b/hw/vhost_net.c
index 2e292ee..26dae79 100644
--- a/hw/vhost_net.c
+++ b/hw/vhost_net.c
@@ -99,7 +99,7 @@ struct vhost_net *vhost_net_init(VLANClientState *backend, int devfd)
goto fail;
}
if (~net->dev.features & net->dev.backend_features) {
- fprintf(stderr, "vhost lacks feature mask %llu for backend\n",
+ fprintf(stderr, "vhost lacks feature mask %" PRIu64 " for backend\n",
~net->dev.features & net->dev.backend_features);
vhost_dev_cleanup(&net->dev);
goto fail;
diff --git a/ia64-dis.c b/ia64-dis.c
index da73a98..2886df3 100644
--- a/ia64-dis.c
+++ b/ia64-dis.c
@@ -10560,11 +10560,14 @@ print_insn_ia64 (bfd_vma memaddr, struct disassemble_info *info)
if (str)
(*info->fprintf_func) (info->stream, "%s", str);
else if (odesc->flags & IA64_OPND_FLAG_DECIMAL_SIGNED)
- (*info->fprintf_func) (info->stream, "%lld", (long long) value);
+ (*info->fprintf_func) (info->stream, "%" PRId64,
+ (int64_t) value);
else if (odesc->flags & IA64_OPND_FLAG_DECIMAL_UNSIGNED)
- (*info->fprintf_func) (info->stream, "%llu", (long long) value);
+ (*info->fprintf_func) (info->stream, "%" PRIu64,
+ (uint64_t) value);
else
- (*info->fprintf_func) (info->stream, "0x%llx", (long long) value);
+ (*info->fprintf_func) (info->stream, "0x%" PRIx64,
+ (uint64_t) value);
break;
case IA64_OPND_CLASS_REL:
diff --git a/nbd.c b/nbd.c
index 337eeba..a9f295f 100644
--- a/nbd.c
+++ b/nbd.c
@@ -353,8 +353,7 @@ int nbd_init(int fd, int csock, off_t size, size_t blocksize)
return -1;
}
- TRACE("Setting size to %llu block(s)",
- (unsigned long long)(size / blocksize));
+ TRACE("Setting size to %zd block(s)", (size_t)(size / blocksize));
if (ioctl(fd, NBD_SET_SIZE_BLOCKS, size / blocksize) == -1) {
int serrno = errno;
diff --git a/qemu-img.c b/qemu-img.c
index d3c30a7..cb007b7 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -701,9 +701,9 @@ static int img_convert(int argc, char **argv)
bs_offset += bs_sectors;
bdrv_get_geometry(bs[bs_i], &bs_sectors);
bs_num = 0;
- /* printf("changing part: sector_num=%lld, "
- "bs_i=%d, bs_offset=%lld, bs_sectors=%lld\n",
- sector_num, bs_i, bs_offset, bs_sectors); */
+ /* printf("changing part: sector_num=%" PRId64 ", "
+ "bs_i=%d, bs_offset=%" PRId64 ", bs_sectors=%" PRId64
+ "\n", sector_num, bs_i, bs_offset, bs_sectors); */
}
assert (bs_num < bs_sectors);
@@ -749,8 +749,8 @@ static int img_convert(int argc, char **argv)
assert (bs_i < bs_n);
bs_offset += bs_sectors;
bdrv_get_geometry(bs[bs_i], &bs_sectors);
- /* printf("changing part: sector_num=%lld, bs_i=%d, "
- "bs_offset=%lld, bs_sectors=%lld\n",
+ /* printf("changing part: sector_num=%" PRId64 ", bs_i=%d, "
+ "bs_offset=%" PRId64 ", bs_sectors=%" PRId64 "\n",
sector_num, bs_i, bs_offset, bs_sectors); */
}
diff --git a/qemu-io.c b/qemu-io.c
index 8517b90..f39109e 100644
--- a/qemu-io.c
+++ b/qemu-io.c
@@ -84,7 +84,7 @@ dump_buffer(const void *buffer, int64_t offset, int len)
for (i = 0, p = buffer; i < len; i += 16) {
const uint8_t *s = p;
- printf("%08llx: ", (unsigned long long)offset + i);
+ printf("%08" PRIx64 ": ", offset + i);
for (j = 0; j < 16 && i + j < len; j++, p++)
printf("%02x ", *p);
printf(" ");
@@ -108,8 +108,8 @@ print_report(const char *op, struct timeval *t, int64_t offset,
if (!Cflag) {
cvtstr((double)total, s1, sizeof(s1));
cvtstr(tdiv((double)total, *t), s2, sizeof(s2));
- printf("%s %d/%d bytes at offset %lld\n",
- op, total, count, (long long)offset);
+ printf("%s %d/%d bytes at offset %" PRId64 "\n",
+ op, total, count, offset);
printf("%s, %d ops; %s (%s/sec and %.4f ops/sec)\n",
s1, cnt, ts, s2, tdiv((double)cnt, *t));
} else {/* bytes,ops,time,bytes/sec,ops/sec */
@@ -135,7 +135,7 @@ create_iovec(QEMUIOVector *qiov, char **argv, int nr_iov, int pattern)
for (i = 0; i < nr_iov; i++) {
char *arg = argv[i];
- long long len;
+ uint64_t len;
len = cvtnum(arg);
if (len < 0) {
@@ -150,8 +150,8 @@ create_iovec(QEMUIOVector *qiov, char **argv, int nr_iov, int pattern)
}
if (len & 0x1ff) {
- printf("length argument %lld is not sector aligned\n",
- len);
+ printf("length argument %" PRId64
+ " is not sector aligned\n", len);
goto fail;
}
@@ -398,8 +398,8 @@ read_f(int argc, char **argv)
if (!pflag)
if (offset & 0x1ff) {
- printf("offset %lld is not sector aligned\n",
- (long long)offset);
+ printf("offset %" PRId64 " is not sector aligned\n",
+ offset);
return 0;
if (count & 0x1ff) {
@@ -429,9 +429,9 @@ read_f(int argc, char **argv)
void* cmp_buf = malloc(pattern_count);
memset(cmp_buf, pattern, pattern_count);
if (memcmp(buf + pattern_offset, cmp_buf, pattern_count)) {
- printf("Pattern verification failed at offset %lld, "
- "%d bytes\n",
- (long long) offset + pattern_offset, pattern_count);
+ printf("Pattern verification failed at offset %"
+ PRId64 ", %d bytes\n",
+ offset + pattern_offset, pattern_count);
}
free(cmp_buf);
}
@@ -533,8 +533,8 @@ readv_f(int argc, char **argv)
optind++;
if (offset & 0x1ff) {
- printf("offset %lld is not sector aligned\n",
- (long long)offset);
+ printf("offset %" PRId64 " is not sector aligned\n",
+ offset);
return 0;
}
@@ -554,9 +554,9 @@ readv_f(int argc, char **argv)
void* cmp_buf = malloc(qiov.size);
memset(cmp_buf, pattern, qiov.size);
if (memcmp(buf, cmp_buf, qiov.size)) {
- printf("Pattern verification failed at offset %lld, "
- "%zd bytes\n",
- (long long) offset, qiov.size);
+ printf("Pattern verification failed at offset %"
+ PRId64 ", %zd bytes\n",
+ offset, qiov.size);
}
free(cmp_buf);
}
@@ -669,8 +669,8 @@ write_f(int argc, char **argv)
if (!pflag) {
if (offset & 0x1ff) {
- printf("offset %lld is not sector aligned\n",
- (long long)offset);
+ printf("offset %" PRId64 " is not sector aligned\n",
+ offset);
return 0;
}
@@ -783,8 +783,8 @@ writev_f(int argc, char **argv)
optind++;
if (offset & 0x1ff) {
- printf("offset %lld is not sector aligned\n",
- (long long)offset);
+ printf("offset %" PRId64 " is not sector aligned\n",
+ offset);
return 0;
}
@@ -868,9 +868,9 @@ aio_read_done(void *opaque, int ret)
memset(cmp_buf, ctx->pattern, ctx->qiov.size);
if (memcmp(ctx->buf, cmp_buf, ctx->qiov.size)) {
- printf("Pattern verification failed at offset %lld, "
- "%zd bytes\n",
- (long long) ctx->offset, ctx->qiov.size);
+ printf("Pattern verification failed at offset %"
+ PRId64 ", %zd bytes\n",
+ ctx->offset, ctx->qiov.size);
}
free(cmp_buf);
}
@@ -969,8 +969,8 @@ aio_read_f(int argc, char **argv)
optind++;
if (ctx->offset & 0x1ff) {
- printf("offset %lld is not sector aligned\n",
- (long long)ctx->offset);
+ printf("offset %" PRId64 " is not sector aligned\n",
+ ctx->offset);
free(ctx);
return 0;
}
@@ -1064,8 +1064,8 @@ aio_write_f(int argc, char **argv)
optind++;
if (ctx->offset & 0x1ff) {
- printf("offset %lld is not sector aligned\n",
- (long long)ctx->offset);
+ printf("offset %" PRId64 " is not sector aligned\n",
+ ctx->offset);
free(ctx);
return 0;
}
@@ -1214,8 +1214,8 @@ alloc_f(int argc, char **argv)
offset = cvtnum(argv[1]);
if (offset & 0x1ff) {
- printf("offset %lld is not sector aligned\n",
- (long long)offset);
+ printf("offset %" PRId64 " is not sector aligned\n",
+ offset);
return 0;
}
diff --git a/target-cris/translate.c b/target-cris/translate.c
index a7014fa..6c1d9e0 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -3226,14 +3226,14 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
qemu_log(
- "srch=%d pc=%x %x flg=%llx bt=%x ds=%u ccs=%x\n"
+ "srch=%d pc=%x %x flg=%" PRIx64 " bt=%x ds=%u ccs=%x\n"
"pid=%x usp=%x\n"
"%x.%x.%x.%x\n"
"%x.%x.%x.%x\n"
"%x.%x.%x.%x\n"
"%x.%x.%x.%x\n",
search_pc, dc->pc, dc->ppc,
- (unsigned long long)tb->flags,
+ (uint64_t)tb->flags,
env->btarget, (unsigned)tb->flags & 7,
env->pregs[PR_CCS],
env->pregs[PR_PID], env->pregs[PR_USP],
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 86cca51..66e1c0d 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -8918,7 +8918,7 @@ void cpu_dump_statistics (CPUState *env, FILE*f,
if (handler->count == 0)
continue;
cpu_fprintf(f, "%02x %02x %02x (%02x %04d) %16s: "
- "%016llx %lld\n",
+ "%016" PRIx64 " %" PRId64 "\n",
op1, op2, op3, op1, (op3 << 5) | op2,
handler->oname,
handler->count, handler->count);
@@ -8927,7 +8927,7 @@ void cpu_dump_statistics (CPUState *env, FILE*f,
if (handler->count == 0)
continue;
cpu_fprintf(f, "%02x %02x (%02x %04d) %16s: "
- "%016llx %lld\n",
+ "%016" PRIx64 " %" PRId64 "\n",
op1, op2, op1, op2, handler->oname,
handler->count, handler->count);
}
@@ -8935,7 +8935,8 @@ void cpu_dump_statistics (CPUState *env, FILE*f,
} else {
if (handler->count == 0)
continue;
- cpu_fprintf(f, "%02x (%02x ) %16s: %016llx %lld\n",
+ cpu_fprintf(f, "%02x (%02x ) %16s: %016" PRIx64
+ " %" PRId64 "\n",
op1, op1, handler->oname,
handler->count, handler->count);
}
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 582de10..2fbbbbf 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -1310,7 +1310,7 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
char *featurestr, *name = strtok(s, ",");
uint32_t plus_features = 0;
uint32_t minus_features = 0;
- long long iu_version;
+ uint64_t iu_version;
uint32_t fpu_version, mmu_version, nwindows;
for (i = 0; i < ARRAY_SIZE(sparc_defs); i++) {
@@ -1342,7 +1342,7 @@ static int cpu_sparc_find_by_name(sparc_def_t *cpu_def, const char *cpu_model)
}
cpu_def->iu_version = iu_version;
#ifdef DEBUG_FEATURES
- fprintf(stderr, "iu_version %llx\n", iu_version);
+ fprintf(stderr, "iu_version %" PRIx64 "\n", iu_version);
#endif
} else if (!strcmp(featurestr, "fpu_version")) {
char *err;
commit 4556bd8b2514a55d48c15b1adb17537f49657744
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sat May 22 08:00:52 2010 +0000
Compile dma only once
Use a qemu_irq to request CPU exit.
7 compilations less for the full build.
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/Makefile.objs b/Makefile.objs
index 1a33d4e..1585101 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -156,6 +156,7 @@ hw-obj-$(CONFIG_USB_UHCI) += usb-uhci.o
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
# PPC devices
hw-obj-$(CONFIG_OPENPIC) += openpic.o
diff --git a/Makefile.target b/Makefile.target
index ba5147f..fda5bf3 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -188,7 +188,6 @@ obj-y += rtl8139.o
obj-y += e1000.o
# Hardware support
-obj-i386-y = dma.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
@@ -199,7 +198,7 @@ obj-i386-y += pc_piix.o
# shared objects
obj-ppc-y = ppc.o
-obj-ppc-y += vga.o dma.o
+obj-ppc-y += vga.o
# PREP target
obj-ppc-y += i8259.o mc146818rtc.o
obj-ppc-y += ppc_prep.o
@@ -217,7 +216,7 @@ obj-ppc-$(CONFIG_FDT) += device_tree.o
obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
obj-mips-y += mips_addr.o mips_timer.o mips_int.o
-obj-mips-y += dma.o vga.o i8259.o
+obj-mips-y += vga.o i8259.o
obj-mips-y += g364fb.o jazz_led.o
obj-mips-y += gt64xxx.o mc146818rtc.o
obj-mips-y += piix4.o cirrus_vga.o
diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 852e298..ed00471 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -13,6 +13,7 @@ CONFIG_USB_UHCI=y
CONFIG_FDC=y
CONFIG_ACPI=y
CONFIG_APM=y
+CONFIG_DMA=y
CONFIG_IDE_CORE=y
CONFIG_IDE_QDEV=y
CONFIG_IDE_PCI=y
diff --git a/default-configs/mips-softmmu.mak b/default-configs/mips-softmmu.mak
index 850f226..29be52e 100644
--- a/default-configs/mips-softmmu.mak
+++ b/default-configs/mips-softmmu.mak
@@ -15,6 +15,7 @@ CONFIG_USB_UHCI=y
CONFIG_FDC=y
CONFIG_ACPI=y
CONFIG_APM=y
+CONFIG_DMA=y
CONFIG_IDE_CORE=y
CONFIG_IDE_QDEV=y
CONFIG_IDE_PCI=y
diff --git a/default-configs/mips64-softmmu.mak b/default-configs/mips64-softmmu.mak
index 21338ff..9bae8a7 100644
--- a/default-configs/mips64-softmmu.mak
+++ b/default-configs/mips64-softmmu.mak
@@ -15,6 +15,7 @@ CONFIG_USB_UHCI=y
CONFIG_FDC=y
CONFIG_ACPI=y
CONFIG_APM=y
+CONFIG_DMA=y
CONFIG_IDE_CORE=y
CONFIG_IDE_QDEV=y
CONFIG_IDE_PCI=y
diff --git a/default-configs/mips64el-softmmu.mak b/default-configs/mips64el-softmmu.mak
index 4aa88ef..b372c1d 100644
--- a/default-configs/mips64el-softmmu.mak
+++ b/default-configs/mips64el-softmmu.mak
@@ -15,6 +15,7 @@ CONFIG_USB_UHCI=y
CONFIG_FDC=y
CONFIG_ACPI=y
CONFIG_APM=y
+CONFIG_DMA=y
CONFIG_IDE_CORE=y
CONFIG_IDE_QDEV=y
CONFIG_IDE_PCI=y
diff --git a/default-configs/mipsel-softmmu.mak b/default-configs/mipsel-softmmu.mak
index a8de1eb..10ef483 100644
--- a/default-configs/mipsel-softmmu.mak
+++ b/default-configs/mipsel-softmmu.mak
@@ -15,6 +15,7 @@ CONFIG_USB_UHCI=y
CONFIG_FDC=y
CONFIG_ACPI=y
CONFIG_APM=y
+CONFIG_DMA=y
CONFIG_IDE_CORE=y
CONFIG_IDE_QDEV=y
CONFIG_IDE_PCI=y
diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
index 03cc20f..c026bbb 100644
--- a/default-configs/ppc-softmmu.mak
+++ b/default-configs/ppc-softmmu.mak
@@ -10,6 +10,7 @@ CONFIG_SERIAL=y
CONFIG_I8254=y
CONFIG_PCKBD=y
CONFIG_FDC=y
+CONFIG_DMA=y
CONFIG_OPENPIC=y
CONFIG_PREP_PCI=y
CONFIG_MACIO=y
diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak
index 8c77133..0101a28 100644
--- a/default-configs/ppc64-softmmu.mak
+++ b/default-configs/ppc64-softmmu.mak
@@ -10,6 +10,7 @@ CONFIG_SERIAL=y
CONFIG_I8254=y
CONFIG_PCKBD=y
CONFIG_FDC=y
+CONFIG_DMA=y
CONFIG_OPENPIC=y
CONFIG_PREP_PCI=y
CONFIG_MACIO=y
diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak
index 2a0210d..8ba9ac1 100644
--- a/default-configs/ppcemb-softmmu.mak
+++ b/default-configs/ppcemb-softmmu.mak
@@ -10,6 +10,7 @@ CONFIG_SERIAL=y
CONFIG_I8254=y
CONFIG_PCKBD=y
CONFIG_FDC=y
+CONFIG_DMA=y
CONFIG_OPENPIC=y
CONFIG_PREP_PCI=y
CONFIG_MACIO=y
diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index 3db8c0c..5183203 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -13,6 +13,7 @@ CONFIG_USB_UHCI=y
CONFIG_FDC=y
CONFIG_ACPI=y
CONFIG_APM=y
+CONFIG_DMA=y
CONFIG_IDE_CORE=y
CONFIG_IDE_QDEV=y
CONFIG_IDE_PCI=y
diff --git a/hw/dma.c b/hw/dma.c
index e5f7af7..5b21521 100644
--- a/hw/dma.c
+++ b/hw/dma.c
@@ -57,6 +57,7 @@ static struct dma_cont {
uint8_t flip_flop;
int dshift;
struct dma_regs regs[4];
+ qemu_irq *cpu_request_exit;
} dma_controllers[2];
enum {
@@ -444,9 +445,9 @@ int DMA_write_memory (int nchan, void *buf, int pos, int len)
/* request the emulator to transfer a new DMA memory block ASAP */
void DMA_schedule(int nchan)
{
- CPUState *env = cpu_single_env;
- if (env)
- cpu_exit(env);
+ struct dma_cont *d = &dma_controllers[nchan > 3];
+
+ qemu_irq_pulse(*d->cpu_request_exit);
}
static void dma_reset(void *opaque)
@@ -464,12 +465,14 @@ static int dma_phony_handler (void *opaque, int nchan, int dma_pos, int dma_len)
/* dshift = 0: 8 bit DMA, 1 = 16 bit DMA */
static void dma_init2(struct dma_cont *d, int base, int dshift,
- int page_base, int pageh_base)
+ int page_base, int pageh_base,
+ qemu_irq *cpu_request_exit)
{
static const int page_port_list[] = { 0x1, 0x2, 0x3, 0x7 };
int i;
d->dshift = dshift;
+ d->cpu_request_exit = cpu_request_exit;
for (i = 0; i < 8; i++) {
register_ioport_write (base + (i << dshift), 1, 1, write_chan, d);
register_ioport_read (base + (i << dshift), 1, 1, read_chan, d);
@@ -539,12 +542,12 @@ static const VMStateDescription vmstate_dma = {
}
};
-void DMA_init (int high_page_enable)
+void DMA_init(int high_page_enable, qemu_irq *cpu_request_exit)
{
dma_init2(&dma_controllers[0], 0x00, 0, 0x80,
- high_page_enable ? 0x480 : -1);
+ high_page_enable ? 0x480 : -1, cpu_request_exit);
dma_init2(&dma_controllers[1], 0xc0, 1, 0x88,
- high_page_enable ? 0x488 : -1);
+ high_page_enable ? 0x488 : -1, cpu_request_exit);
vmstate_register (0, &vmstate_dma, &dma_controllers[0]);
vmstate_register (1, &vmstate_dma, &dma_controllers[1]);
diff --git a/hw/isa.h b/hw/isa.h
index 97f69a2..aaf0272 100644
--- a/hw/isa.h
+++ b/hw/isa.h
@@ -41,7 +41,7 @@ int DMA_write_memory (int nchan, void *buf, int pos, int size);
void DMA_hold_DREQ (int nchan);
void DMA_release_DREQ (int nchan);
void DMA_schedule(int nchan);
-void DMA_init (int high_page_enable);
+void DMA_init(int high_page_enable, qemu_irq *cpu_request_exit);
void DMA_register_channel (int nchan,
DMA_transfer_handler transfer_handler,
void *opaque);
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index 6e0ec8f..ead3a00 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -114,6 +114,15 @@ static void audio_init(qemu_irq *pic)
#define MAGNUM_BIOS_SIZE_MAX 0x7e000
#define MAGNUM_BIOS_SIZE (BIOS_SIZE < MAGNUM_BIOS_SIZE_MAX ? BIOS_SIZE : MAGNUM_BIOS_SIZE_MAX)
+static void cpu_request_exit(void *opaque, int irq, int level)
+{
+ CPUState *env = cpu_single_env;
+
+ if (env && level) {
+ cpu_exit(env);
+ }
+}
+
static
void mips_jazz_init (ram_addr_t ram_size,
const char *cpu_model,
@@ -130,6 +139,7 @@ void mips_jazz_init (ram_addr_t ram_size,
PITState *pit;
DriveInfo *fds[MAX_FD];
qemu_irq esp_reset;
+ qemu_irq *cpu_exit_irq;
ram_addr_t ram_offset;
ram_addr_t bios_offset;
@@ -189,7 +199,8 @@ void mips_jazz_init (ram_addr_t ram_size,
i8259 = i8259_init(env->irq[4]);
isa_bus_new(NULL);
isa_bus_irqs(i8259);
- DMA_init(0);
+ cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
+ DMA_init(0, cpu_exit_irq);
pit = pit_init(0x40, i8259[0]);
pcspk_init(pit);
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 792709b..a8f9d15 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -763,6 +763,15 @@ static void main_cpu_reset(void *opaque)
}
}
+static void cpu_request_exit(void *opaque, int irq, int level)
+{
+ CPUState *env = cpu_single_env;
+
+ if (env && level) {
+ cpu_exit(env);
+ }
+}
+
static
void mips_malta_init (ram_addr_t ram_size,
const char *boot_device,
@@ -781,6 +790,7 @@ void mips_malta_init (ram_addr_t ram_size,
FDCtrl *floppy_controller;
MaltaFPGAState *malta_fpga;
qemu_irq *i8259;
+ qemu_irq *cpu_exit_irq;
int piix4_devfn;
uint8_t *eeprom_buf;
i2c_bus *smbus;
@@ -943,7 +953,8 @@ void mips_malta_init (ram_addr_t ram_size,
qdev_init_nofail(eeprom);
}
pit = pit_init(0x40, isa_reserve_irq(0));
- DMA_init(0);
+ cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
+ DMA_init(0, cpu_exit_irq);
/* Super I/O */
isa_dev = isa_create_simple("i8042");
diff --git a/hw/pc.c b/hw/pc.c
index d2fb9be..e7f31d3 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -914,6 +914,15 @@ void pc_vga_init(PCIBus *pci_bus)
}
}
+static void cpu_request_exit(void *opaque, int irq, int level)
+{
+ CPUState *env = cpu_single_env;
+
+ if (env && level) {
+ cpu_exit(env);
+ }
+}
+
void pc_basic_device_init(qemu_irq *isa_irq,
FDCtrl **floppy_controller,
ISADevice **rtc_state)
@@ -923,6 +932,7 @@ void pc_basic_device_init(qemu_irq *isa_irq,
PITState *pit;
qemu_irq *a20_line;
ISADevice *i8042;
+ qemu_irq *cpu_exit_irq;
register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
@@ -955,7 +965,8 @@ void pc_basic_device_init(qemu_irq *isa_irq,
i8042_setup_a20_line(i8042, a20_line);
vmmouse_init(i8042);
- DMA_init(0);
+ cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
+ DMA_init(0, cpu_exit_irq);
for(i = 0; i < MAX_FD; i++) {
fd[i] = drive_get(IF_FLOPPY, 0, i);
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 09a9881..16c9950 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -547,6 +547,15 @@ static CPUReadMemoryFunc * const PPC_prep_io_read[] = {
#define NVRAM_SIZE 0x2000
+static void cpu_request_exit(void *opaque, int irq, int level)
+{
+ CPUState *env = cpu_single_env;
+
+ if (env && level) {
+ cpu_exit(env);
+ }
+}
+
/* PowerPC PREP hardware initialisation */
static void ppc_prep_init (ram_addr_t ram_size,
const char *boot_device,
@@ -565,6 +574,7 @@ static void ppc_prep_init (ram_addr_t ram_size,
uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
PCIBus *pci_bus;
qemu_irq *i8259;
+ qemu_irq *cpu_exit_irq;
int ppc_boot_device;
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
DriveInfo *fd[MAX_FD];
@@ -719,7 +729,10 @@ static void ppc_prep_init (ram_addr_t ram_size,
hd[2 * i + 1]);
}
isa_create_simple("i8042");
- DMA_init(1);
+
+ cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
+ DMA_init(1, cpu_exit_irq);
+
// SB16_init();
for(i = 0; i < MAX_FD; i++) {
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 9a79120..7ba0f76 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -152,7 +152,11 @@ int DMA_write_memory (int nchan, void *buf, int pos, int size)
void DMA_hold_DREQ (int nchan) {}
void DMA_release_DREQ (int nchan) {}
void DMA_schedule(int nchan) {}
-void DMA_init (int high_page_enable) {}
+
+void DMA_init(int high_page_enable, qemu_irq *cpu_request_exit)
+{
+}
+
void DMA_register_channel (int nchan,
DMA_transfer_handler transfer_handler,
void *opaque)
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 24ea367..e9a1e23 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -105,7 +105,11 @@ int DMA_write_memory (int nchan, void *buf, int pos, int size)
void DMA_hold_DREQ (int nchan) {}
void DMA_release_DREQ (int nchan) {}
void DMA_schedule(int nchan) {}
-void DMA_init (int high_page_enable) {}
+
+void DMA_init(int high_page_enable, qemu_irq *cpu_request_exit)
+{
+}
+
void DMA_register_channel (int nchan,
DMA_transfer_handler transfer_handler,
void *opaque)
commit c86d2c23879da1534a257eecb572a76f1ead5d93
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sat May 22 07:59:06 2010 +0000
pckbd: improve debugging
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/pckbd.c b/hw/pckbd.c
index 5d268b4..3812284 100644
--- a/hw/pckbd.c
+++ b/hw/pckbd.c
@@ -29,6 +29,12 @@
/* debug PC keyboard */
//#define DEBUG_KBD
+#ifdef DEBUG_KBD
+#define DPRINTF(fmt, ...) \
+ do { printf("KBD: " fmt , ## __VA_ARGS__); } while (0)
+#else
+#define DPRINTF(fmt, ...)
+#endif
/* Keyboard Controller Commands */
#define KBD_CCMD_READ_MODE 0x20 /* Read mode bits */
@@ -191,9 +197,7 @@ static uint32_t kbd_read_status(void *opaque, uint32_t addr)
KBDState *s = opaque;
int val;
val = s->status;
-#if defined(DEBUG_KBD)
- printf("kbd: read status=0x%02x\n", val);
-#endif
+ DPRINTF("kbd: read status=0x%02x\n", val);
return val;
}
@@ -209,6 +213,7 @@ static void ioport92_write(void *opaque, uint32_t addr, uint32_t val)
{
KBDState *s = opaque;
+ DPRINTF("kbd: write outport=0x%02x\n", val);
s->outport = val;
if (s->a20_out) {
qemu_set_irq(*s->a20_out, (val >> 1) & 1);
@@ -221,17 +226,18 @@ static void ioport92_write(void *opaque, uint32_t addr, uint32_t val)
static uint32_t ioport92_read(void *opaque, uint32_t addr)
{
KBDState *s = opaque;
+ uint32_t ret;
- return s->outport;
+ ret = s->outport;
+ DPRINTF("kbd: read outport=0x%02x\n", ret);
+ return ret;
}
static void kbd_write_command(void *opaque, uint32_t addr, uint32_t val)
{
KBDState *s = opaque;
-#ifdef DEBUG_KBD
- printf("kbd: write cmd=0x%02x\n", val);
-#endif
+ DPRINTF("kbd: write cmd=0x%02x\n", val);
switch(val) {
case KBD_CCMD_READ_MODE:
kbd_queue(s, s->mode, 0);
@@ -307,9 +313,7 @@ static uint32_t kbd_read_data(void *opaque, uint32_t addr)
else
val = ps2_read_data(s->kbd);
-#if defined(DEBUG_KBD)
- printf("kbd: read data=0x%02x\n", val);
-#endif
+ DPRINTF("kbd: read data=0x%02x\n", val);
return val;
}
@@ -317,9 +321,7 @@ static void kbd_write_data(void *opaque, uint32_t addr, uint32_t val)
{
KBDState *s = opaque;
-#ifdef DEBUG_KBD
- printf("kbd: write data=0x%02x\n", val);
-#endif
+ DPRINTF("kbd: write data=0x%02x\n", val);
switch(s->write_cmd) {
case 0:
commit 956a3e6bb7386de48b642d4fee11f7f86a2fcf9a
Author: Blue Swirl <blauwirbel at gmail.com>
Date: Sat May 22 07:59:01 2010 +0000
Compile pckbd only once
Use a qemu_irq to indicate A20 line changes. Move I/O port 92
to pckbd.c.
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/Makefile.objs b/Makefile.objs
index acbaf22..1a33d4e 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -151,6 +151,7 @@ hw-obj-$(CONFIG_SERIAL) += serial.o
hw-obj-$(CONFIG_PARALLEL) += parallel.o
hw-obj-$(CONFIG_I8254) += i8254.o
hw-obj-$(CONFIG_PCSPK) += pcspk.o
+hw-obj-$(CONFIG_PCKBD) += pckbd.o
hw-obj-$(CONFIG_USB_UHCI) += usb-uhci.o
hw-obj-$(CONFIG_FDC) += fdc.o
hw-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o
diff --git a/Makefile.target b/Makefile.target
index a22484e..ba5147f 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -188,7 +188,7 @@ obj-y += rtl8139.o
obj-y += e1000.o
# Hardware support
-obj-i386-y = pckbd.o dma.o
+obj-i386-y = dma.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
@@ -201,7 +201,7 @@ obj-i386-y += pc_piix.o
obj-ppc-y = ppc.o
obj-ppc-y += vga.o dma.o
# PREP target
-obj-ppc-y += pckbd.o i8259.o mc146818rtc.o
+obj-ppc-y += i8259.o mc146818rtc.o
obj-ppc-y += ppc_prep.o
# OldWorld PowerMac
obj-ppc-y += ppc_oldworld.o
@@ -219,7 +219,7 @@ obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
obj-mips-y += mips_addr.o mips_timer.o mips_int.o
obj-mips-y += dma.o vga.o i8259.o
obj-mips-y += g364fb.o jazz_led.o
-obj-mips-y += gt64xxx.o pckbd.o mc146818rtc.o
+obj-mips-y += gt64xxx.o mc146818rtc.o
obj-mips-y += piix4.o cirrus_vga.o
obj-microblaze-y = petalogix_s3adsp1800_mmu.o
@@ -243,7 +243,7 @@ obj-cris-y += etraxfs_timer.o
obj-cris-y += etraxfs_ser.o
ifeq ($(TARGET_ARCH), sparc64)
-obj-sparc-y = sun4u.o pckbd.o apb_pci.o
+obj-sparc-y = sun4u.o apb_pci.o
obj-sparc-y += vga.o
obj-sparc-y += mc146818rtc.o
obj-sparc-y += cirrus_vga.o
diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 4fbd8aa..852e298 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -8,6 +8,7 @@ CONFIG_SERIAL=y
CONFIG_PARALLEL=y
CONFIG_I8254=y
CONFIG_PCSPK=y
+CONFIG_PCKBD=y
CONFIG_USB_UHCI=y
CONFIG_FDC=y
CONFIG_ACPI=y
diff --git a/default-configs/mips-softmmu.mak b/default-configs/mips-softmmu.mak
index fd6fbc1..850f226 100644
--- a/default-configs/mips-softmmu.mak
+++ b/default-configs/mips-softmmu.mak
@@ -10,6 +10,7 @@ CONFIG_SERIAL=y
CONFIG_PARALLEL=y
CONFIG_I8254=y
CONFIG_PCSPK=y
+CONFIG_PCKBD=y
CONFIG_USB_UHCI=y
CONFIG_FDC=y
CONFIG_ACPI=y
diff --git a/default-configs/mips64-softmmu.mak b/default-configs/mips64-softmmu.mak
index dfd30db..21338ff 100644
--- a/default-configs/mips64-softmmu.mak
+++ b/default-configs/mips64-softmmu.mak
@@ -10,6 +10,7 @@ CONFIG_SERIAL=y
CONFIG_PARALLEL=y
CONFIG_I8254=y
CONFIG_PCSPK=y
+CONFIG_PCKBD=y
CONFIG_USB_UHCI=y
CONFIG_FDC=y
CONFIG_ACPI=y
diff --git a/default-configs/mips64el-softmmu.mak b/default-configs/mips64el-softmmu.mak
index 6fa54a3..4aa88ef 100644
--- a/default-configs/mips64el-softmmu.mak
+++ b/default-configs/mips64el-softmmu.mak
@@ -10,6 +10,7 @@ CONFIG_SERIAL=y
CONFIG_PARALLEL=y
CONFIG_I8254=y
CONFIG_PCSPK=y
+CONFIG_PCKBD=y
CONFIG_USB_UHCI=y
CONFIG_FDC=y
CONFIG_ACPI=y
diff --git a/default-configs/mipsel-softmmu.mak b/default-configs/mipsel-softmmu.mak
index 8203997..a8de1eb 100644
--- a/default-configs/mipsel-softmmu.mak
+++ b/default-configs/mipsel-softmmu.mak
@@ -10,6 +10,7 @@ CONFIG_SERIAL=y
CONFIG_PARALLEL=y
CONFIG_I8254=y
CONFIG_PCSPK=y
+CONFIG_PCKBD=y
CONFIG_USB_UHCI=y
CONFIG_FDC=y
CONFIG_ACPI=y
diff --git a/default-configs/ppc-softmmu.mak b/default-configs/ppc-softmmu.mak
index 958bf75..03cc20f 100644
--- a/default-configs/ppc-softmmu.mak
+++ b/default-configs/ppc-softmmu.mak
@@ -8,6 +8,7 @@ CONFIG_M48T59=y
CONFIG_VGA_PCI=y
CONFIG_SERIAL=y
CONFIG_I8254=y
+CONFIG_PCKBD=y
CONFIG_FDC=y
CONFIG_OPENPIC=y
CONFIG_PREP_PCI=y
diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak
index 9896662..8c77133 100644
--- a/default-configs/ppc64-softmmu.mak
+++ b/default-configs/ppc64-softmmu.mak
@@ -8,6 +8,7 @@ CONFIG_M48T59=y
CONFIG_VGA_PCI=y
CONFIG_SERIAL=y
CONFIG_I8254=y
+CONFIG_PCKBD=y
CONFIG_FDC=y
CONFIG_OPENPIC=y
CONFIG_PREP_PCI=y
diff --git a/default-configs/ppcemb-softmmu.mak b/default-configs/ppcemb-softmmu.mak
index 2e41a94..2a0210d 100644
--- a/default-configs/ppcemb-softmmu.mak
+++ b/default-configs/ppcemb-softmmu.mak
@@ -8,6 +8,7 @@ CONFIG_M48T59=y
CONFIG_VGA_PCI=y
CONFIG_SERIAL=y
CONFIG_I8254=y
+CONFIG_PCKBD=y
CONFIG_FDC=y
CONFIG_OPENPIC=y
CONFIG_PREP_PCI=y
diff --git a/default-configs/sparc64-softmmu.mak b/default-configs/sparc64-softmmu.mak
index 514d334..1cc3f13 100644
--- a/default-configs/sparc64-softmmu.mak
+++ b/default-configs/sparc64-softmmu.mak
@@ -6,6 +6,7 @@ CONFIG_PTIMER=y
CONFIG_VGA_PCI=y
CONFIG_SERIAL=y
CONFIG_PARALLEL=y
+CONFIG_PCKBD=y
CONFIG_FDC=y
CONFIG_IDE_CORE=y
CONFIG_IDE_QDEV=y
diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index ffedfdb..3db8c0c 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -8,6 +8,7 @@ CONFIG_SERIAL=y
CONFIG_PARALLEL=y
CONFIG_I8254=y
CONFIG_PCSPK=y
+CONFIG_PCKBD=y
CONFIG_USB_UHCI=y
CONFIG_FDC=y
CONFIG_ACPI=y
diff --git a/hw/pc.c b/hw/pc.c
index 7715b17..d2fb9be 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -365,26 +365,12 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
rtc_set_memory(s, 0x39, val);
}
-void ioport_set_a20(int enable)
+static void handle_a20_line_change(void *opaque, int irq, int level)
{
- /* XXX: send to all CPUs ? */
- cpu_x86_set_a20(first_cpu, enable);
-}
-
-int ioport_get_a20(void)
-{
- return ((first_cpu->a20_mask >> 20) & 1);
-}
-
-static void ioport92_write(void *opaque, uint32_t addr, uint32_t val)
-{
- ioport_set_a20((val >> 1) & 1);
- /* XXX: bit 0 is fast reset */
-}
+ CPUState *cpu = opaque;
-static uint32_t ioport92_read(void *opaque, uint32_t addr)
-{
- return ioport_get_a20() << 1;
+ /* XXX: send to all CPUs ? */
+ cpu_x86_set_a20(cpu, level);
}
/***********************************************************/
@@ -935,6 +921,8 @@ void pc_basic_device_init(qemu_irq *isa_irq,
int i;
DriveInfo *fd[MAX_FD];
PITState *pit;
+ qemu_irq *a20_line;
+ ISADevice *i8042;
register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
@@ -944,9 +932,6 @@ void pc_basic_device_init(qemu_irq *isa_irq,
qemu_register_boot_set(pc_boot_set, *rtc_state);
- register_ioport_read(0x92, 1, 1, ioport92_read, NULL);
- register_ioport_write(0x92, 1, 1, ioport92_write, NULL);
-
pit = pit_init(0x40, isa_reserve_irq(0));
pcspk_init(pit);
if (!no_hpet) {
@@ -965,7 +950,11 @@ void pc_basic_device_init(qemu_irq *isa_irq,
}
}
- isa_create_simple("i8042");
+ a20_line = qemu_allocate_irqs(handle_a20_line_change, first_cpu, 1);
+ i8042 = isa_create_simple("i8042");
+ i8042_setup_a20_line(i8042, a20_line);
+ vmmouse_init(i8042);
+
DMA_init(0);
for(i = 0; i < MAX_FD; i++) {
diff --git a/hw/pc.h b/hw/pc.h
index 654b7b3..73cccef 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -75,6 +75,8 @@ void i8042_init(qemu_irq kbd_irq, qemu_irq mouse_irq, uint32_t io_base);
void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq,
target_phys_addr_t base, ram_addr_t size,
target_phys_addr_t mask);
+void i8042_isa_mouse_fake_event(void *opaque);
+void i8042_setup_a20_line(ISADevice *dev, qemu_irq *a20_out);
/* pc.c */
extern int fd_bootchk;
@@ -104,9 +106,6 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
FDCtrl *floppy_controller, ISADevice *s);
void pc_pci_device_init(PCIBus *pci_bus);
-void ioport_set_a20(int enable);
-int ioport_get_a20(void);
-
typedef void (*cpu_set_smm_t)(int smm, void *arg);
void cpu_smm_register(cpu_set_smm_t callback, void *arg);
diff --git a/hw/pckbd.c b/hw/pckbd.c
index e83b8a6..5d268b4 100644
--- a/hw/pckbd.c
+++ b/hw/pckbd.c
@@ -87,6 +87,12 @@
#define KBD_MODE_KCC 0x40 /* Scan code conversion to PC format */
#define KBD_MODE_RFU 0x80
+/* Output Port Bits */
+#define KBD_OUT_RESET 0x01 /* 1=normal mode, 0=reset */
+#define KBD_OUT_A20 0x02 /* x86 only */
+#define KBD_OUT_OBF 0x10 /* Keyboard output buffer full */
+#define KBD_OUT_MOUSE_OBF 0x20 /* Mouse output buffer full */
+
/* Mouse Commands */
#define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */
#define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */
@@ -116,6 +122,7 @@ typedef struct KBDState {
uint8_t write_cmd; /* if non zero, write data to port 60 is expected */
uint8_t status;
uint8_t mode;
+ uint8_t outport;
/* Bitmask of devices with data available. */
uint8_t pending;
void *kbd;
@@ -123,6 +130,7 @@ typedef struct KBDState {
qemu_irq irq_kbd;
qemu_irq irq_mouse;
+ qemu_irq *a20_out;
target_phys_addr_t mask;
} KBDState;
@@ -136,11 +144,14 @@ static void kbd_update_irq(KBDState *s)
irq_kbd_level = 0;
irq_mouse_level = 0;
s->status &= ~(KBD_STAT_OBF | KBD_STAT_MOUSE_OBF);
+ s->outport &= ~(KBD_OUT_OBF | KBD_OUT_MOUSE_OBF);
if (s->pending) {
s->status |= KBD_STAT_OBF;
+ s->outport |= KBD_OUT_OBF;
/* kbd data takes priority over aux data. */
if (s->pending == KBD_PENDING_AUX) {
s->status |= KBD_STAT_MOUSE_OBF;
+ s->outport |= KBD_OUT_MOUSE_OBF;
if (s->mode & KBD_MODE_MOUSE_INT)
irq_mouse_level = 1;
} else {
@@ -194,6 +205,26 @@ static void kbd_queue(KBDState *s, int b, int aux)
ps2_queue(s->kbd, b);
}
+static void ioport92_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ KBDState *s = opaque;
+
+ s->outport = val;
+ if (s->a20_out) {
+ qemu_set_irq(*s->a20_out, (val >> 1) & 1);
+ }
+ if (!(val & 1)) {
+ qemu_system_reset_request();
+ }
+}
+
+static uint32_t ioport92_read(void *opaque, uint32_t addr)
+{
+ KBDState *s = opaque;
+
+ return s->outport;
+}
+
static void kbd_write_command(void *opaque, uint32_t addr, uint32_t val)
{
KBDState *s = opaque;
@@ -240,26 +271,20 @@ static void kbd_write_command(void *opaque, uint32_t addr, uint32_t val)
kbd_queue(s, 0x00, 0);
break;
case KBD_CCMD_READ_OUTPORT:
- /* XXX: check that */
-#ifdef TARGET_I386
- val = 0x01 | (ioport_get_a20() << 1);
-#else
- val = 0x01;
-#endif
- if (s->status & KBD_STAT_OBF)
- val |= 0x10;
- if (s->status & KBD_STAT_MOUSE_OBF)
- val |= 0x20;
- kbd_queue(s, val, 0);
+ kbd_queue(s, s->outport, 0);
break;
-#ifdef TARGET_I386
case KBD_CCMD_ENABLE_A20:
- ioport_set_a20(1);
+ if (s->a20_out) {
+ qemu_irq_raise(*s->a20_out);
+ }
+ s->outport |= KBD_OUT_A20;
break;
case KBD_CCMD_DISABLE_A20:
- ioport_set_a20(0);
+ if (s->a20_out) {
+ qemu_irq_lower(*s->a20_out);
+ }
+ s->outport &= ~KBD_OUT_A20;
break;
-#endif
case KBD_CCMD_RESET:
qemu_system_reset_request();
break;
@@ -313,12 +338,7 @@ static void kbd_write_data(void *opaque, uint32_t addr, uint32_t val)
kbd_queue(s, val, 1);
break;
case KBD_CCMD_WRITE_OUTPORT:
-#ifdef TARGET_I386
- ioport_set_a20((val >> 1) & 1);
-#endif
- if (!(val & 1)) {
- qemu_system_reset_request();
- }
+ ioport92_write(s, 0, val);
break;
case KBD_CCMD_WRITE_MOUSE:
ps2_write_mouse(s->mouse, val);
@@ -335,6 +355,7 @@ static void kbd_reset(void *opaque)
s->mode = KBD_MODE_KBD_INT | KBD_MODE_MOUSE_INT;
s->status = KBD_STAT_CMD | KBD_STAT_UNLOCKED;
+ s->outport = KBD_OUT_RESET | KBD_OUT_A20;
}
static const VMStateDescription vmstate_kbd = {
@@ -401,9 +422,6 @@ void i8042_mm_init(qemu_irq kbd_irq, qemu_irq mouse_irq,
s->kbd = ps2_kbd_init(kbd_update_kbd_irq, s);
s->mouse = ps2_mouse_init(kbd_update_aux_irq, s);
-#ifdef TARGET_I386
- vmmouse_init(s->mouse);
-#endif
qemu_register_reset(kbd_reset, s);
}
@@ -412,6 +430,21 @@ typedef struct ISAKBDState {
KBDState kbd;
} ISAKBDState;
+void i8042_isa_mouse_fake_event(void *opaque)
+{
+ ISADevice *dev = opaque;
+ KBDState *s = &(DO_UPCAST(ISAKBDState, dev, dev)->kbd);
+
+ ps2_mouse_fake_event(s->mouse);
+}
+
+void i8042_setup_a20_line(ISADevice *dev, qemu_irq *a20_out)
+{
+ KBDState *s = &(DO_UPCAST(ISAKBDState, dev, dev)->kbd);
+
+ s->a20_out = a20_out;
+}
+
static const VMStateDescription vmstate_kbd_isa = {
.name = "pckbd",
.version_id = 3,
@@ -434,12 +467,11 @@ static int i8042_initfn(ISADevice *dev)
register_ioport_write(0x60, 1, 1, kbd_write_data, s);
register_ioport_read(0x64, 1, 1, kbd_read_status, s);
register_ioport_write(0x64, 1, 1, kbd_write_command, s);
+ register_ioport_read(0x92, 1, 1, ioport92_read, s);
+ register_ioport_write(0x92, 1, 1, ioport92_write, s);
s->kbd = ps2_kbd_init(kbd_update_kbd_irq, s);
s->mouse = ps2_mouse_init(kbd_update_aux_irq, s);
-#ifdef TARGET_I386
- vmmouse_init(s->mouse);
-#endif
qemu_register_reset(kbd_reset, s);
return 0;
}
diff --git a/hw/vmmouse.c b/hw/vmmouse.c
index bb6e605..afebad9 100644
--- a/hw/vmmouse.c
+++ b/hw/vmmouse.c
@@ -97,7 +97,7 @@ static void vmmouse_mouse_event(void *opaque, int x, int y, int dz, int buttons_
/* need to still generate PS2 events to notify driver to
read from queue */
- ps2_mouse_fake_event(s->ps2_mouse);
+ i8042_isa_mouse_fake_event(s->ps2_mouse);
}
static void vmmouse_update_handler(VMMouseState *s)
commit 9e42382fc14b999126f8cabb32761eb98153fd1b
Author: Riku Voipio <riku.voipio at nokia.com>
Date: Fri May 7 12:28:05 2010 +0000
linux-user: do not warn for missing pselect6
Libc will fallback gracefully if pselect6 is not available. Thus put
pselect6 to nowarn until the atomicity issues of the original pselect6
patch are dealt with.
Signed-off-by: Riku Voipio <riku.voipio at nokia.com>
Cc: Michael Casadevall <mcasadevall at ubuntu.com>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index bca8f70..8222cb9 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5268,6 +5268,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
}
break;
#endif
+#ifdef TARGET_NR_pselect6
+ case TARGET_NR_pselect6:
+ goto unimplemented_nowarn;
+#endif
case TARGET_NR_symlink:
{
void *p2;
commit 6781d08d2e0522c9e8ca421ad89ed9b19cf0555e
Author: Richard Henderson <rth at twiddle.net>
Date: Thu May 6 08:50:44 2010 -0700
tcg-ia64: Load GUEST_BASE into a register.
Saves one bundle per memory operation.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c
index f0196ca..905f48b 100644
--- a/tcg/ia64/tcg-target.c
+++ b/tcg/ia64/tcg-target.c
@@ -40,6 +40,12 @@ static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
};
#endif
+#ifdef CONFIG_USE_GUEST_BASE
+#define TCG_GUEST_BASE_REG TCG_REG_R55
+#else
+#define TCG_GUEST_BASE_REG TCG_REG_R0
+#endif
+
/* Branch registers */
enum {
TCG_REG_B0 = 0,
@@ -1640,9 +1646,13 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
{
+ static uint64_t const opc_ld_m1[4] = {
+ OPC_LD1_M1, OPC_LD2_M1, OPC_LD4_M1, OPC_LD8_M1
+ };
+ static uint64_t const opc_sxt_i29[4] = {
+ OPC_SXT1_I29, OPC_SXT2_I29, OPC_SXT4_I29, 0
+ };
int addr_reg, data_reg, mem_index, s_bits, bswap;
- uint64_t opc_ld_m1[4] = { OPC_LD1_M1, OPC_LD2_M1, OPC_LD4_M1, OPC_LD8_M1 };
- uint64_t opc_sxt_i29[8] = { OPC_SXT1_I29, OPC_SXT2_I29, OPC_SXT4_I29, 0 };
data_reg = *args++;
addr_reg = *args++;
@@ -1655,19 +1665,21 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
bswap = 0;
#endif
- tcg_out_bundle(s, mLX,
- tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
- tcg_opc_l2 ((tcg_target_long) GUEST_BASE),
- tcg_opc_x2 (TCG_REG_P0, OPC_MOVL_X2, TCG_REG_R2,
- GUEST_BASE));
-
#if TARGET_LONG_BITS == 32
- tcg_out_bundle(s, mII,
- tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
- tcg_opc_i29(TCG_REG_P0, OPC_ZXT4_I29,
- TCG_REG_R3, addr_reg),
- tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, TCG_REG_R2,
- TCG_REG_R2, TCG_REG_R3));
+ if (GUEST_BASE != 0) {
+ tcg_out_bundle(s, mII,
+ tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+ tcg_opc_i29(TCG_REG_P0, OPC_ZXT4_I29,
+ TCG_REG_R3, addr_reg),
+ tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, TCG_REG_R2,
+ TCG_GUEST_BASE_REG, TCG_REG_R3));
+ } else {
+ tcg_out_bundle(s, miI,
+ tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+ tcg_opc_i29(TCG_REG_P0, OPC_ZXT4_I29,
+ TCG_REG_R2, addr_reg),
+ tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0));
+ }
if (!bswap || s_bits == 0) {
if (s_bits == opc) {
@@ -1723,12 +1735,20 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
}
}
#else
- tcg_out_bundle(s, MmI,
- tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, TCG_REG_R2,
- TCG_REG_R2, addr_reg),
- tcg_opc_m1 (TCG_REG_P0, opc_ld_m1[s_bits],
- data_reg, TCG_REG_R2),
- tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0));
+ if (GUEST_BASE != 0) {
+ tcg_out_bundle(s, MmI,
+ tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, TCG_REG_R2,
+ TCG_GUEST_BASE_REG, addr_reg),
+ tcg_opc_m1 (TCG_REG_P0, opc_ld_m1[s_bits],
+ data_reg, TCG_REG_R2),
+ tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0));
+ } else {
+ tcg_out_bundle(s, mmI,
+ tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+ tcg_opc_m1 (TCG_REG_P0, opc_ld_m1[s_bits],
+ data_reg, addr_reg),
+ tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0));
+ }
if (bswap && s_bits == 1) {
tcg_out_bundle(s, mII,
@@ -1763,8 +1783,13 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
{
+ static uint64_t const opc_st_m4[4] = {
+ OPC_ST1_M4, OPC_ST2_M4, OPC_ST4_M4, OPC_ST8_M4
+ };
int addr_reg, data_reg, bswap;
- uint64_t opc_st_m4[4] = { OPC_ST1_M4, OPC_ST2_M4, OPC_ST4_M4, OPC_ST8_M4 };
+#if TARGET_LONG_BITS == 64
+ uint64_t add_guest_base;
+#endif
data_reg = *args++;
addr_reg = *args++;
@@ -1775,19 +1800,22 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
bswap = 0;
#endif
- tcg_out_bundle(s, mLX,
- tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
- tcg_opc_l2 ((tcg_target_long) GUEST_BASE),
- tcg_opc_x2 (TCG_REG_P0, OPC_MOVL_X2, TCG_REG_R2,
- GUEST_BASE));
-
#if TARGET_LONG_BITS == 32
- tcg_out_bundle(s, mII,
- tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
- tcg_opc_i29(TCG_REG_P0, OPC_ZXT4_I29,
- TCG_REG_R3, addr_reg),
- tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, TCG_REG_R2,
- TCG_REG_R2, TCG_REG_R3));
+ if (GUEST_BASE != 0) {
+ tcg_out_bundle(s, mII,
+ tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+ tcg_opc_i29(TCG_REG_P0, OPC_ZXT4_I29,
+ TCG_REG_R3, addr_reg),
+ tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, TCG_REG_R2,
+ TCG_GUEST_BASE_REG, TCG_REG_R3));
+ } else {
+ tcg_out_bundle(s, miI,
+ tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+ tcg_opc_i29(TCG_REG_P0, OPC_ZXT4_I29,
+ TCG_REG_R3, addr_reg),
+ tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0));
+ }
+
if (bswap) {
if (opc == 1) {
tcg_out_bundle(s, mII,
@@ -1820,18 +1848,24 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0));
#else
+ if (GUEST_BASE != 0) {
+ add_guest_base = tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, TCG_REG_R2,
+ TCG_GUEST_BASE_REG, addr_reg);
+ addr_reg = TCG_REG_R2;
+ } else {
+ add_guest_base = tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0);
+ }
+
if (!bswap || opc == 0) {
- tcg_out_bundle(s, MmI,
- tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, TCG_REG_R2,
- TCG_REG_R2, addr_reg),
+ tcg_out_bundle(s, (GUEST_BASE ? MmI : mmI),
+ add_guest_base,
tcg_opc_m4 (TCG_REG_P0, opc_st_m4[opc],
- data_reg, TCG_REG_R2),
+ data_reg, addr_reg),
tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0));
} else {
if (opc == 1) {
tcg_out_bundle(s, mII,
- tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, TCG_REG_R2,
- TCG_REG_R2, addr_reg),
+ add_guest_base,
tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12,
TCG_REG_R3, data_reg, 15, 15),
tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3,
@@ -1839,8 +1873,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
data_reg = TCG_REG_R3;
} else if (opc == 2) {
tcg_out_bundle(s, mII,
- tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, TCG_REG_R2,
- TCG_REG_R2, addr_reg),
+ add_guest_base,
tcg_opc_i12(TCG_REG_P0, OPC_DEP_Z_I12,
TCG_REG_R3, data_reg, 31, 31),
tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3,
@@ -1848,8 +1881,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
data_reg = TCG_REG_R3;
} else if (opc == 3) {
tcg_out_bundle(s, miI,
- tcg_opc_a1 (TCG_REG_P0, OPC_ADD_A1, TCG_REG_R2,
- TCG_REG_R2, addr_reg),
+ add_guest_base,
tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3,
TCG_REG_R3, data_reg, 0xb));
@@ -1857,7 +1889,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
}
tcg_out_bundle(s, miI,
tcg_opc_m4 (TCG_REG_P0, opc_st_m4[opc],
- data_reg, TCG_REG_R2),
+ data_reg, addr_reg),
tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0));
}
@@ -2254,6 +2286,18 @@ void tcg_target_qemu_prologue(TCGContext *s)
TCG_REG_B6, TCG_REG_R32, 0),
tcg_opc_i22(TCG_REG_P0, OPC_MOV_I22,
TCG_REG_R32, TCG_REG_B0));
+
+ /* ??? If GUEST_BASE < 0x200000, we could load the register via
+ an ADDL in the M slot of the next bundle. */
+ if (GUEST_BASE != 0) {
+ tcg_out_bundle(s, mlx,
+ tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
+ tcg_opc_l2 (GUEST_BASE),
+ tcg_opc_x2 (TCG_REG_P0, OPC_MOVL_X2,
+ TCG_GUEST_BASE_REG, GUEST_BASE));
+ tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
+ }
+
tcg_out_bundle(s, miB,
tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
tcg_opc_a4 (TCG_REG_P0, OPC_ADDS_A4,
commit 7221f058a6bda93b892f4486801908ed3c90b534
Author: Richard Henderson <rth at twiddle.net>
Date: Thu May 6 08:50:43 2010 -0700
tcg-ia64: Fix some register usage issues.
(1) The output registers were not marked call-clobbered, even though
they can be modified by called functions.
(2) The thread pointer was not marked reserved.
(3) R4-R6 are call-saved, but not saved by the prologue. Rather than
save them, mark them reserved so that we don't use them.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c
index 6e69ef4..f0196ca 100644
--- a/tcg/ia64/tcg-target.c
+++ b/tcg/ia64/tcg-target.c
@@ -2282,39 +2282,56 @@ void tcg_target_init(TCGContext *s)
0xffffffffffffffffull);
tcg_regset_set(tcg_target_available_regs[TCG_TYPE_I64],
0xffffffffffffffffull);
- tcg_regset_set(tcg_target_call_clobber_regs,
- (1 << TCG_REG_R8) |
- (1 << TCG_REG_R9) |
- (1 << TCG_REG_R10) |
- (1 << TCG_REG_R11) |
- (1 << TCG_REG_R13) |
- (1 << TCG_REG_R14) |
- (1 << TCG_REG_R15) |
- (1 << TCG_REG_R16) |
- (1 << TCG_REG_R17) |
- (1 << TCG_REG_R18) |
- (1 << TCG_REG_R19) |
- (1 << TCG_REG_R20) |
- (1 << TCG_REG_R21) |
- (1 << TCG_REG_R22) |
- (1 << TCG_REG_R23) |
- (1 << TCG_REG_R24) |
- (1 << TCG_REG_R25) |
- (1 << TCG_REG_R26) |
- (1 << TCG_REG_R27) |
- (1 << TCG_REG_R28) |
- (1 << TCG_REG_R29) |
- (1 << TCG_REG_R30) |
- (1 << TCG_REG_R31));
- tcg_regset_clear(s->reserved_regs);
+ tcg_regset_clear(tcg_target_call_clobber_regs);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R8);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R9);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R10);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R11);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R14);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R15);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R16);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R17);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R18);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R19);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R20);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R21);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R22);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R23);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R24);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R25);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R26);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R27);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R28);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R29);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R30);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R31);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R56);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R57);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R58);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R59);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R60);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R61);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R62);
+ tcg_regset_set_reg(tcg_target_call_clobber_regs, TCG_REG_R63);
+
+ tcg_regset_clear(s->reserved_regs);
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R0); /* zero register */
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R1); /* global pointer */
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R2); /* internal use */
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R3); /* internal use */
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R12); /* stack pointer */
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_R13); /* thread pointer */
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R32); /* return address */
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R33); /* PFS */
+ /* The following 3 are not in use, are call-saved, but *not* saved
+ by the prologue. Therefore we cannot use them without modifying
+ the prologue. There doesn't seem to be any good reason to use
+ these as opposed to the windowed registers. */
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_R4);
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_R5);
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_R6);
+
tcg_add_target_add_op_defs(ia64_op_defs);
}
commit 4b31713dc4fa81e9026413acc6825073b92453bc
Author: Richard Henderson <rth at twiddle.net>
Date: Thu May 6 08:50:42 2010 -0700
tcg-hppa: Load GUEST_BASE as an immediate.
Now that the prologue is generated after GUEST_BASE is fixed,
we can load it as an immediate, and also avoid reserving the
register if it isn't necessary.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index cb605f1..558c21f 100644
--- a/tcg/hppa/tcg-target.c
+++ b/tcg/hppa/tcg-target.c
@@ -1629,11 +1629,10 @@ void tcg_target_qemu_prologue(TCGContext *s)
}
#ifdef CONFIG_USE_GUEST_BASE
- /* Note that GUEST_BASE can change after the prologue is generated.
- To combat that, load the value from the variable instead of
- embedding a constant here. */
- tcg_out_ld(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG,
- TCG_REG_R0, (tcg_target_long)&guest_base);
+ if (GUEST_BASE != 0) {
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, GUEST_BASE);
+ tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
+ }
#endif
/* Jump to TB, and adjust R18 to be the return address. */
@@ -1679,9 +1678,6 @@ void tcg_target_init(TCGContext *s)
tcg_regset_set_reg(s->reserved_regs, TCG_REG_DP); /* data pointer */
tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP); /* stack pointer */
tcg_regset_set_reg(s->reserved_regs, TCG_REG_R31); /* ble link reg */
-#ifdef CONFIG_USE_GUEST_BASE
- tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
-#endif
tcg_add_target_add_op_defs(hppa_op_defs);
}
commit 9002ec794e8154ff774270cf9fac5f850a1c5751
Author: Richard Henderson <rth at twiddle.net>
Date: Thu May 6 08:50:41 2010 -0700
tcg: Initialize the prologue after GUEST_BASE is fixed.
This will allow backends to make intelligent choices about how
to implement GUEST_BASE.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/bsd-user/main.c b/bsd-user/main.c
index b1c438d..05cc3d9 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -30,7 +30,7 @@
#include "qemu-common.h"
/* For tb_lock */
#include "exec-all.h"
-
+#include "tcg.h"
#include "qemu-timer.h"
#include "envlist.h"
@@ -970,6 +970,13 @@ int main(int argc, char **argv)
syscall_init();
signal_init();
+#if defined(CONFIG_USE_GUEST_BASE)
+ /* Now that we've loaded the binary, GUEST_BASE is fixed. Delay
+ generating the prologue until now so that the prologue can take
+ the real value of GUEST_BASE into account. */
+ tcg_prologue_init(&tcg_ctx);
+#endif
+
/* build Task State */
memset(ts, 0, sizeof(TaskState));
init_task_state(ts);
diff --git a/exec.c b/exec.c
index 56b5561..bb3dcad 100644
--- a/exec.c
+++ b/exec.c
@@ -574,6 +574,11 @@ void cpu_exec_init_all(unsigned long tb_size)
#if !defined(CONFIG_USER_ONLY)
io_mem_init();
#endif
+#if !defined(CONFIG_USER_ONLY) || !defined(CONFIG_USE_GUEST_BASE)
+ /* There's no guest base to take into account, so go ahead and
+ initialize the prologue now. */
+ tcg_prologue_init(&tcg_ctx);
+#endif
}
#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
diff --git a/linux-user/main.c b/linux-user/main.c
index 5027a6d..b240f29 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -31,7 +31,7 @@
#include "cache-utils.h"
/* For tb_lock */
#include "exec-all.h"
-
+#include "tcg.h"
#include "qemu-timer.h"
#include "envlist.h"
@@ -2984,6 +2984,13 @@ int main(int argc, char **argv, char **envp)
syscall_init();
signal_init();
+#if defined(CONFIG_USE_GUEST_BASE)
+ /* Now that we've loaded the binary, GUEST_BASE is fixed. Delay
+ generating the prologue until now so that the prologue can take
+ the real value of GUEST_BASE into account. */
+ tcg_prologue_init(&tcg_ctx);
+#endif
+
#if defined(TARGET_I386)
cpu_x86_set_cpl(env, 3);
diff --git a/tcg/tcg.c b/tcg/tcg.c
index a99ecb9..880e7ce 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -240,7 +240,10 @@ void tcg_context_init(TCGContext *s)
}
tcg_target_init(s);
+}
+void tcg_prologue_init(TCGContext *s)
+{
/* init global prologue and epilogue */
s->code_buf = code_gen_prologue;
s->code_ptr = s->code_buf;
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 44856e1..5853823 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -346,6 +346,7 @@ static inline void *tcg_malloc(int size)
}
void tcg_context_init(TCGContext *s);
+void tcg_prologue_init(TCGContext *s);
void tcg_func_start(TCGContext *s);
int tcg_gen_code(TCGContext *s, uint8_t *gen_code_buf);
commit a5b3b13bedc545b5e571480b9cf47d2d378ad193
Author: Richard Henderson <rth at twiddle.net>
Date: Mon May 3 10:07:55 2010 -0700
alpha-linux-user: Fix sigprocmask.
Alpha passes oldset by value in a register, and returns the newset
as the return value; as compared to the standard implementation in
which both are passed by reference. This requires being able to
distinguish negative return values that are not errors. Do this in
the same way as the Alpha Linux kernel, by storing a zero in V0 in
the implementation of the syscall.
At the same time, fix a think-o in the regular sigprocmask path in
which we passed the target, rather than the host, HOW value.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/linux-user/main.c b/linux-user/main.c
index b158bbc..5027a6d 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2499,8 +2499,15 @@ void cpu_loop (CPUState *env)
env->ir[IR_A0], env->ir[IR_A1],
env->ir[IR_A2], env->ir[IR_A3],
env->ir[IR_A4], env->ir[IR_A5]);
- if (trapnr != TARGET_NR_sigreturn
- && trapnr != TARGET_NR_rt_sigreturn) {
+ if (trapnr == TARGET_NR_sigreturn
+ || trapnr == TARGET_NR_rt_sigreturn) {
+ break;
+ }
+ /* Syscall writes 0 to V0 to bypass error check, similar
+ to how this is handled internal to Linux kernel. */
+ if (env->ir[IR_V0] == 0) {
+ env->ir[IR_V0] = sysret;
+ } else {
env->ir[IR_V0] = (sysret < 0 ? -sysret : sysret);
env->ir[IR_A3] = (sysret < 0);
}
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index fb18b24..bca8f70 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4983,11 +4983,41 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
#ifdef TARGET_NR_sigprocmask
case TARGET_NR_sigprocmask:
{
- int how = arg1;
+#if defined(TARGET_ALPHA)
+ sigset_t set, oldset;
+ abi_ulong mask;
+ int how;
+
+ switch (arg1) {
+ case TARGET_SIG_BLOCK:
+ how = SIG_BLOCK;
+ break;
+ case TARGET_SIG_UNBLOCK:
+ how = SIG_UNBLOCK;
+ break;
+ case TARGET_SIG_SETMASK:
+ how = SIG_SETMASK;
+ break;
+ default:
+ ret = -TARGET_EINVAL;
+ goto fail;
+ }
+ mask = arg2;
+ target_to_host_old_sigset(&set, &mask);
+
+ ret = get_errno(sigprocmask(how, &set, &oldset));
+
+ if (!is_error(ret)) {
+ host_to_target_old_sigset(&mask, &oldset);
+ ret = mask;
+ ((CPUAlphaState *)cpu_env)->[IR_V0] = 0; /* force no error */
+ }
+#else
sigset_t set, oldset, *set_ptr;
+ int how;
if (arg2) {
- switch(how) {
+ switch (arg1) {
case TARGET_SIG_BLOCK:
how = SIG_BLOCK;
break;
@@ -5010,13 +5040,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
how = 0;
set_ptr = NULL;
}
- ret = get_errno(sigprocmask(arg1, set_ptr, &oldset));
+ ret = get_errno(sigprocmask(how, set_ptr, &oldset));
if (!is_error(ret) && arg3) {
if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
goto efault;
host_to_target_old_sigset(p, &oldset);
unlock_user(p, arg3, sizeof(target_sigset_t));
}
+#endif
}
break;
#endif
commit f43ce12b47323f0555ae9dfdf2f9d443346a4952
Author: Richard Henderson <rth at twiddle.net>
Date: Mon May 3 10:07:54 2010 -0700
alpha-linux-user: Fix sigsuspend parameters.
Alpha passes the signal set in a register, not by reference.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index e9e61c8..fb18b24 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -5088,10 +5088,15 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_NR_sigsuspend:
{
sigset_t set;
+#if defined(TARGET_ALPHA)
+ abi_ulong mask = arg1;
+ target_to_host_old_sigset(&set, &mask);
+#else
if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
goto efault;
target_to_host_old_sigset(&set, p);
unlock_user(p, arg1, 0);
+#endif
ret = get_errno(sigsuspend(&set));
}
break;
commit 9231733a82cfced41edc4d859c1327f7a7ae8a59
Author: Richard Henderson <rth at twiddle.net>
Date: Mon May 3 10:07:53 2010 -0700
alpha-linux-user: Fix getxpid.
Put ppid in the second return register.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 1a5e381..e9e61c8 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -4497,13 +4497,18 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_NR_lseek:
ret = get_errno(lseek(arg1, arg2, arg3));
break;
-#ifdef TARGET_NR_getxpid
+#if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA)
+ /* Alpha specific */
case TARGET_NR_getxpid:
-#else
- case TARGET_NR_getpid:
+ ((CPUAlphaState *)cpu_env)->ir[IR_A4] = getppid();
+ ret = get_errno(getpid());
+ break;
#endif
+#ifdef TARGET_NR_getpid
+ case TARGET_NR_getpid:
ret = get_errno(getpid());
break;
+#endif
case TARGET_NR_mount:
{
/* need to look at the data field */
commit fb41a66edd0c7bd652dab14db43426cbbd8514d7
Author: Richard Henderson <rth at twiddle.net>
Date: Mon May 3 10:07:52 2010 -0700
alpha-linux-user: Fix pipe return mechanism.
At the same time, tidy the code wrt MIPS and SH4 which have the
same two register return mechanism. Fix confusion between pipe
and pipe2 with an explicit flags=0, when the guest will not be
using the two register return mechanism.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 746967a..1a5e381 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -995,7 +995,8 @@ static abi_long do_pipe2(int host_pipe[], int flags)
#endif
}
-static abi_long do_pipe(void *cpu_env, abi_ulong pipedes, int flags)
+static abi_long do_pipe(void *cpu_env, abi_ulong pipedes,
+ int flags, int is_pipe2)
{
int host_pipe[2];
abi_long ret;
@@ -1003,20 +1004,25 @@ static abi_long do_pipe(void *cpu_env, abi_ulong pipedes, int flags)
if (is_error(ret))
return get_errno(ret);
-#if defined(TARGET_MIPS)
- ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] = host_pipe[1];
- ret = host_pipe[0];
-#else
-#if defined(TARGET_SH4)
- if (!flags) {
+
+ /* Several targets have special calling conventions for the original
+ pipe syscall, but didn't replicate this into the pipe2 syscall. */
+ if (!is_pipe2) {
+#if defined(TARGET_ALPHA)
+ ((CPUAlphaState *)cpu_env)->ir[IR_A4] = host_pipe[1];
+ return host_pipe[0];
+#elif defined(TARGET_MIPS)
+ ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] = host_pipe[1];
+ return host_pipe[0];
+#elif defined(TARGET_SH4)
((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
- ret = host_pipe[0];
- } else
+ return host_pipe[0];
#endif
+ }
+
if (put_user_s32(host_pipe[0], pipedes)
|| put_user_s32(host_pipe[1], pipedes + sizeof(host_pipe[0])))
return -TARGET_EFAULT;
-#endif
return get_errno(ret);
}
@@ -4706,11 +4712,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
ret = get_errno(dup(arg1));
break;
case TARGET_NR_pipe:
- ret = do_pipe(cpu_env, arg1, 0);
+ ret = do_pipe(cpu_env, arg1, 0, 0);
break;
#ifdef TARGET_NR_pipe2
case TARGET_NR_pipe2:
- ret = do_pipe(cpu_env, arg1, arg2);
+ ret = do_pipe(cpu_env, arg1, arg2, 1);
break;
#endif
case TARGET_NR_times:
commit 57f18a9515b1240280c59cf60df041f50be05493
Author: Richard Henderson <rth at twiddle.net>
Date: Mon May 3 10:07:51 2010 -0700
alpha-linux-user: Add correct sigaction constants.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 6f5a0aa..681021c 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -336,6 +336,14 @@ int do_sigaction(int sig, const struct target_sigaction *act,
#if !defined(TARGET_ABI_MIPSN32) && !defined(TARGET_ABI_MIPSN64)
#define TARGET_SA_RESTORER 0x04000000 /* Only for O32 */
#endif
+#elif defined(TARGET_ALPHA)
+#define TARGET_SA_ONSTACK 0x00000001
+#define TARGET_SA_RESTART 0x00000002
+#define TARGET_SA_NOCLDSTOP 0x00000004
+#define TARGET_SA_NODEFER 0x00000008
+#define TARGET_SA_RESETHAND 0x00000010
+#define TARGET_SA_NOCLDWAIT 0x00000020 /* not supported yet */
+#define TARGET_SA_SIGINFO 0x00000040
#else
#define TARGET_SA_NOCLDSTOP 0x00000001
#define TARGET_SA_NOCLDWAIT 0x00000002 /* not supported yet */
commit 1b6bd8c7f3fc89cff9597efed8b776687d139eb0
Author: Richard Henderson <rth at twiddle.net>
Date: Mon May 3 10:07:50 2010 -0700
alpha-linux-user: Fix siginfo.si_addr for SIGSEGV and SIGBUS.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/linux-user/main.c b/linux-user/main.c
index 99a7cde..b158bbc 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -2434,7 +2434,7 @@ void cpu_loop (CPUState *env)
info.si_signo = TARGET_SIGSEGV;
info.si_errno = 0;
info.si_code = 0; /* ??? SEGV_MAPERR vs SEGV_ACCERR. */
- info._sifields._sigfault._addr = env->pc;
+ info._sifields._sigfault._addr = env->ipr[IPR_EXC_ADDR];
queue_signal(env, info.si_signo, &info);
break;
case EXCP_DTB_MISS_PAL:
@@ -2458,7 +2458,7 @@ void cpu_loop (CPUState *env)
info.si_signo = TARGET_SIGBUS;
info.si_errno = 0;
info.si_code = TARGET_BUS_ADRALN;
- info._sifields._sigfault._addr = env->pc;
+ info._sifields._sigfault._addr = env->ipr[IPR_EXC_ADDR];
queue_signal(env, info.si_signo, &info);
break;
case EXCP_OPCDEC:
commit 7dd46c02e4b83be7fbabe81465137d7116b6add6
Author: Richard Henderson <rth at twiddle.net>
Date: Mon May 3 10:07:49 2010 -0700
alpha-linux-user: Fix brk error return.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index ce728fa..746967a 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -718,9 +718,17 @@ abi_long do_brk(abi_ulong new_brk)
PROT_READ|PROT_WRITE,
MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0));
- if (!is_error(mapped_addr))
+#if defined(TARGET_ALPHA)
+ /* We (partially) emulate OSF/1 on Alpha, which requires we
+ return a proper errno, not an unchanged brk value. */
+ if (is_error(mapped_addr)) {
+ return -TARGET_ENOMEM;
+ }
+#endif
+
+ if (!is_error(mapped_addr)) {
target_brk = new_brk;
-
+ }
return target_brk;
}
commit 7868652357a9deb32b2f2d48b8563f2aeebba775
Author: Richard Henderson <rth at twiddle.net>
Date: Fri May 21 08:30:35 2010 -0700
tcg-i386: Nuke trailing whitespace.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index abc4cdc..396a2f1 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -50,7 +50,7 @@ static const int tcg_target_call_oarg_regs[2] = { TCG_REG_EAX, TCG_REG_EDX };
static uint8_t *tb_ret_addr;
-static void patch_reloc(uint8_t *code_ptr, int type,
+static void patch_reloc(uint8_t *code_ptr, int type,
tcg_target_long value, tcg_target_long addend)
{
value += addend;
@@ -474,7 +474,7 @@ static void tcg_out_jxx(TCGContext *s, int opc, int label_index, int small)
{
int32_t val, val1;
TCGLabel *l = &s->labels[label_index];
-
+
if (l->has_value) {
val = l->u.value - (tcg_target_long)s->code_ptr;
val1 = val - 2;
@@ -733,8 +733,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
r1 = TCG_REG_EDX;
#if defined(CONFIG_SOFTMMU)
- tcg_out_mov(s, r1, addr_reg);
- tcg_out_mov(s, r0, addr_reg);
+ tcg_out_mov(s, r1, addr_reg);
+ tcg_out_mov(s, r0, addr_reg);
tcg_out_shifti(s, SHIFT_SHR, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
@@ -747,9 +747,9 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
/* cmp 0(r1), r0 */
tcg_out_modrm_offset(s, OPC_CMP_GvEv, r0, r1, 0);
-
+
tcg_out_mov(s, r0, addr_reg);
-
+
#if TARGET_LONG_BITS == 32
/* je label1 */
tcg_out8(s, OPC_JCC_short + JCC_JE);
@@ -760,7 +760,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
tcg_out8(s, OPC_JCC_short + JCC_JNE);
label3_ptr = s->code_ptr;
s->code_ptr++;
-
+
/* cmp 4(r1), addr_reg2 */
tcg_out_modrm_offset(s, OPC_CMP_GvEv, addr_reg2, r1, 4);
@@ -768,7 +768,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
tcg_out8(s, OPC_JCC_short + JCC_JE);
label1_ptr = s->code_ptr;
s->code_ptr++;
-
+
/* label3: */
*label3_ptr = s->code_ptr - label3_ptr - 1;
#endif
@@ -815,7 +815,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
tcg_out8(s, OPC_JMP_short);
label2_ptr = s->code_ptr;
s->code_ptr++;
-
+
/* label1: */
*label1_ptr = s->code_ptr - label1_ptr - 1;
@@ -925,9 +925,9 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
r1 = TCG_REG_EDX;
#if defined(CONFIG_SOFTMMU)
- tcg_out_mov(s, r1, addr_reg);
- tcg_out_mov(s, r0, addr_reg);
-
+ tcg_out_mov(s, r1, addr_reg);
+ tcg_out_mov(s, r0, addr_reg);
+
tcg_out_shifti(s, SHIFT_SHR, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
tgen_arithi(s, ARITH_AND, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
@@ -939,9 +939,9 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
/* cmp 0(r1), r0 */
tcg_out_modrm_offset(s, OPC_CMP_GvEv, r0, r1, 0);
-
+
tcg_out_mov(s, r0, addr_reg);
-
+
#if TARGET_LONG_BITS == 32
/* je label1 */
tcg_out8(s, OPC_JCC_short + JCC_JE);
@@ -952,7 +952,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
tcg_out8(s, OPC_JCC_short + JCC_JNE);
label3_ptr = s->code_ptr;
s->code_ptr++;
-
+
/* cmp 4(r1), addr_reg2 */
tcg_out_modrm_offset(s, OPC_CMP_GvEv, addr_reg2, r1, 4);
@@ -960,7 +960,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
tcg_out8(s, OPC_JCC_short + JCC_JE);
label1_ptr = s->code_ptr;
s->code_ptr++;
-
+
/* label3: */
*label3_ptr = s->code_ptr - label3_ptr - 1;
#endif
@@ -1025,7 +1025,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
tcg_out8(s, OPC_JMP_short);
label2_ptr = s->code_ptr;
s->code_ptr++;
-
+
/* label1: */
*label1_ptr = s->code_ptr - label1_ptr - 1;
@@ -1091,7 +1091,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
const TCGArg *args, const int *const_args)
{
int c;
-
+
switch(opc) {
case INDEX_op_exit_tb:
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EAX, args[0]);
@@ -1334,7 +1334,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
case INDEX_op_qemu_ld64:
tcg_out_qemu_ld(s, args, 3);
break;
-
+
case INDEX_op_qemu_st8:
tcg_out_qemu_st(s, args, 0);
break;
@@ -1447,7 +1447,7 @@ static int tcg_target_callee_save_regs[] = {
void tcg_target_qemu_prologue(TCGContext *s)
{
int i, frame_size, push_size, stack_addend;
-
+
/* TB prologue */
/* save all callee saved registers */
for(i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
@@ -1456,13 +1456,13 @@ void tcg_target_qemu_prologue(TCGContext *s)
/* reserve some stack space */
push_size = 4 + ARRAY_SIZE(tcg_target_callee_save_regs) * 4;
frame_size = push_size + TCG_STATIC_CALL_ARGS_SIZE;
- frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
+ frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
~(TCG_TARGET_STACK_ALIGN - 1);
stack_addend = frame_size - push_size;
tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, TCG_REG_EAX); /* jmp *%eax */
-
+
/* TB epilogue */
tb_ret_addr = s->code_ptr;
tcg_out_addi(s, TCG_REG_ESP, stack_addend);
commit 5d1e4e85cee8c735ae49599ba96440d29312557c
Author: Richard Henderson <rth at twiddle.net>
Date: Fri May 21 08:30:34 2010 -0700
tcg-i386: Use lea for three-operand add.
The result is shorter than the mov+add that TCG would
otherwise generate for us.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 56800ff..abc4cdc 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -1165,6 +1165,25 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
case INDEX_op_st_i32:
tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]);
break;
+ case INDEX_op_add_i32:
+ /* For 3-operand addition, use LEA. */
+ if (args[0] != args[1]) {
+ TCGArg a0 = args[0], a1 = args[1], a2 = args[2], c3 = 0;
+
+ if (const_args[2]) {
+ c3 = a2, a2 = -1;
+ } else if (a0 == a2) {
+ /* Watch out for dest = src + dest, since we've removed
+ the matching constraint on the add. */
+ tgen_arithr(s, ARITH_ADD, a0, a1);
+ break;
+ }
+
+ tcg_out_modrm_sib_offset(s, OPC_LEA, a0, a1, a2, 0, c3);
+ break;
+ }
+ c = ARITH_ADD;
+ goto gen_arith;
case INDEX_op_sub_i32:
c = ARITH_SUB;
goto gen_arith;
@@ -1177,8 +1196,6 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
case INDEX_op_xor_i32:
c = ARITH_XOR;
goto gen_arith;
- case INDEX_op_add_i32:
- c = ARITH_ADD;
gen_arith:
if (const_args[2]) {
tgen_arithi(s, c, args[0], args[2], 0);
@@ -1353,7 +1370,7 @@ static const TCGTargetOpDef x86_op_defs[] = {
{ INDEX_op_st16_i32, { "r", "r" } },
{ INDEX_op_st_i32, { "r", "r" } },
- { INDEX_op_add_i32, { "r", "0", "ri" } },
+ { INDEX_op_add_i32, { "r", "r", "ri" } },
{ INDEX_op_sub_i32, { "r", "0", "ri" } },
{ INDEX_op_mul_i32, { "r", "0", "ri" } },
{ INDEX_op_mulu2_i32, { "a", "d", "a", "r" } },
commit 34a6d0b7fcac2faf936ab92803b4ac21f809a3b9
Author: Richard Henderson <rth at twiddle.net>
Date: Fri May 21 08:30:33 2010 -0700
tcg-i386: Tidy lea.
Implement full modrm+sib addressing mode processing.
Use that in qemu_ld/st to output the LEA.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 5d5e5e4..56800ff 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -174,6 +174,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define OPC_JCC_short (0x70) /* ... plus condition code */
#define OPC_JMP_long (0xe9)
#define OPC_JMP_short (0xeb)
+#define OPC_LEA (0x8d)
#define OPC_MOVB_EvGv (0x88) /* stores, more or less */
#define OPC_MOVL_EvGv (0x89) /* stores, more or less */
#define OPC_MOVL_GvEv (0x8b) /* loads, more or less */
@@ -272,40 +273,70 @@ static inline void tcg_out_modrm(TCGContext *s, int opc, int r, int rm)
tcg_out8(s, 0xc0 | (r << 3) | rm);
}
-/* rm == -1 means no register index */
-static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r, int rm,
- int32_t offset)
+/* Output an opcode with a full "rm + (index<<shift) + offset" address mode.
+ We handle either RM and INDEX missing with a -1 value. */
+
+static void tcg_out_modrm_sib_offset(TCGContext *s, int opc, int r, int rm,
+ int index, int shift, int32_t offset)
{
+ int mod, len;
+
+ if (index == -1 && rm == -1) {
+ /* Absolute address. */
+ tcg_out_opc(s, opc);
+ tcg_out8(s, (r << 3) | 5);
+ tcg_out32(s, offset);
+ return;
+ }
+
tcg_out_opc(s, opc);
+
+ /* Find the length of the immediate addend. Note that the encoding
+ that would be used for (%ebp) indicates absolute addressing. */
if (rm == -1) {
- tcg_out8(s, 0x05 | (r << 3));
- tcg_out32(s, offset);
+ mod = 0, len = 4, rm = 5;
} else if (offset == 0 && rm != TCG_REG_EBP) {
- if (rm == TCG_REG_ESP) {
- tcg_out8(s, 0x04 | (r << 3));
- tcg_out8(s, 0x24);
- } else {
- tcg_out8(s, 0x00 | (r << 3) | rm);
- }
- } else if ((int8_t)offset == offset) {
- if (rm == TCG_REG_ESP) {
- tcg_out8(s, 0x44 | (r << 3));
- tcg_out8(s, 0x24);
- } else {
- tcg_out8(s, 0x40 | (r << 3) | rm);
- }
- tcg_out8(s, offset);
+ mod = 0, len = 0;
+ } else if (offset == (int8_t)offset) {
+ mod = 0x40, len = 1;
} else {
- if (rm == TCG_REG_ESP) {
- tcg_out8(s, 0x84 | (r << 3));
- tcg_out8(s, 0x24);
+ mod = 0x80, len = 4;
+ }
+
+ /* Use a single byte MODRM format if possible. Note that the encoding
+ that would be used for %esp is the escape to the two byte form. */
+ if (index == -1 && rm != TCG_REG_ESP) {
+ /* Single byte MODRM format. */
+ tcg_out8(s, mod | (r << 3) | rm);
+ } else {
+ /* Two byte MODRM+SIB format. */
+
+ /* Note that the encoding that would place %esp into the index
+ field indicates no index register. */
+ if (index == -1) {
+ index = 4;
} else {
- tcg_out8(s, 0x80 | (r << 3) | rm);
+ assert(index != TCG_REG_ESP);
}
+
+ tcg_out8(s, mod | (r << 3) | 4);
+ tcg_out8(s, (shift << 6) | (index << 3) | rm);
+ }
+
+ if (len == 1) {
+ tcg_out8(s, offset);
+ } else if (len == 4) {
tcg_out32(s, offset);
}
}
+/* rm == -1 means no register index */
+static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r, int rm,
+ int32_t offset)
+{
+ tcg_out_modrm_sib_offset(s, opc, r, rm, -1, 0, offset);
+}
+
/* Generate dest op= src. Uses the same ARITH_* codes as tgen_arithi. */
static inline void tgen_arithr(TCGContext *s, int subop, int dest, int src)
{
@@ -710,10 +741,9 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
tgen_arithi(s, ARITH_AND, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
tgen_arithi(s, ARITH_AND, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
- tcg_out_opc(s, 0x8d); /* lea offset(r1, %ebp), r1 */
- tcg_out8(s, 0x80 | (r1 << 3) | 0x04);
- tcg_out8(s, (5 << 3) | r1);
- tcg_out32(s, offsetof(CPUState, tlb_table[mem_index][0].addr_read));
+ tcg_out_modrm_sib_offset(s, OPC_LEA, r1, TCG_AREG0, r1, 0,
+ offsetof(CPUState,
+ tlb_table[mem_index][0].addr_read));
/* cmp 0(r1), r0 */
tcg_out_modrm_offset(s, OPC_CMP_GvEv, r0, r1, 0);
@@ -903,10 +933,9 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
tgen_arithi(s, ARITH_AND, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
tgen_arithi(s, ARITH_AND, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
- tcg_out_opc(s, 0x8d); /* lea offset(r1, %ebp), r1 */
- tcg_out8(s, 0x80 | (r1 << 3) | 0x04);
- tcg_out8(s, (5 << 3) | r1);
- tcg_out32(s, offsetof(CPUState, tlb_table[mem_index][0].addr_write));
+ tcg_out_modrm_sib_offset(s, OPC_LEA, r1, TCG_AREG0, r1, 0,
+ offsetof(CPUState,
+ tlb_table[mem_index][0].addr_write));
/* cmp 0(r1), r0 */
tcg_out_modrm_offset(s, OPC_CMP_GvEv, r0, r1, 0);
commit b3e66df71acb52f9798f3da039470952c4b4c7c3
Author: Richard Henderson <rth at twiddle.net>
Date: Fri May 21 08:30:32 2010 -0700
tcg-i386: Tidy xchg.
Define and use OPC_XCHG_ax_r32.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index bf8e9d5..5d5e5e4 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -192,6 +192,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define OPC_SHIFT_Ib (0xc1)
#define OPC_SHIFT_cl (0xd3)
#define OPC_TESTL (0x85)
+#define OPC_XCHG_ax_r32 (0x90)
#define OPC_GRP3_Ev (0xf7)
#define OPC_GRP5 (0xff)
@@ -770,7 +771,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
break;
case 3:
if (data_reg == TCG_REG_EDX) {
- tcg_out_opc(s, 0x90 + TCG_REG_EDX); /* xchg %edx, %eax */
+ /* xchg %edx, %eax */
+ tcg_out_opc(s, OPC_XCHG_ax_r32 + TCG_REG_EDX);
tcg_out_mov(s, data_reg2, TCG_REG_EAX);
} else {
tcg_out_mov(s, data_reg, TCG_REG_EAX);
commit 0566d387378fe02e89f27d3608474e216baa72d7
Author: Richard Henderson <rth at twiddle.net>
Date: Fri May 21 08:30:31 2010 -0700
tcg-i386: Tidy multiply.
Define and use OPC_IMUL_GvEv{,Ib,Iz}.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index af5ed16..bf8e9d5 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -166,6 +166,9 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define OPC_CALL_Jz (0xe8)
#define OPC_CMP_GvEv (OPC_ARITH_GvEv | (ARITH_CMP << 3))
#define OPC_DEC_r32 (0x48)
+#define OPC_IMUL_GvEv (0xaf | P_EXT)
+#define OPC_IMUL_GvEvIb (0x6b)
+#define OPC_IMUL_GvEvIz (0x69)
#define OPC_INC_r32 (0x40)
#define OPC_JCC_long (0x80 | P_EXT) /* ... plus condition code */
#define OPC_JCC_short (0x70) /* ... plus condition code */
@@ -1157,14 +1160,14 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
int32_t val;
val = args[2];
if (val == (int8_t)val) {
- tcg_out_modrm(s, 0x6b, args[0], args[0]);
+ tcg_out_modrm(s, OPC_IMUL_GvEvIb, args[0], args[0]);
tcg_out8(s, val);
} else {
- tcg_out_modrm(s, 0x69, args[0], args[0]);
+ tcg_out_modrm(s, OPC_IMUL_GvEvIz, args[0], args[0]);
tcg_out32(s, val);
}
} else {
- tcg_out_modrm(s, 0xaf | P_EXT, args[0], args[2]);
+ tcg_out_modrm(s, OPC_IMUL_GvEv, args[0], args[2]);
}
break;
case INDEX_op_mulu2_i32:
commit 9363dedbbb998949c0c851afe6597f2c97ed3c90
Author: Richard Henderson <rth at twiddle.net>
Date: Fri May 21 08:30:30 2010 -0700
tcg-i386: Tidy unary arithmetic.
Define OPC_GRP3 and EXT3_FOO to match. Use them instead of
bare constants.
Define OPC_GRP5 and rename the existing EXT_BAR to EXT5_BAR to
make it clear which extension should be used with which opcode.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 1499c81..af5ed16 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -190,7 +190,11 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define OPC_SHIFT_cl (0xd3)
#define OPC_TESTL (0x85)
-/* Group 1 opcode extensions for 0x80-0x83. */
+#define OPC_GRP3_Ev (0xf7)
+#define OPC_GRP5 (0xff)
+
+/* Group 1 opcode extensions for 0x80-0x83.
+ These are also used as modifiers for OPC_ARITH. */
#define ARITH_ADD 0
#define ARITH_OR 1
#define ARITH_ADC 2
@@ -207,9 +211,17 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define SHIFT_SHR 5
#define SHIFT_SAR 7
-/* Group 5 opcode extensions for 0xff. */
-#define EXT_CALLN_Ev 2
-#define EXT_JMPN_Ev 4
+/* Group 3 opcode extensions for 0xf6, 0xf7. To be used with OPC_GRP3. */
+#define EXT3_NOT 2
+#define EXT3_NEG 3
+#define EXT3_MUL 4
+#define EXT3_IMUL 5
+#define EXT3_DIV 6
+#define EXT3_IDIV 7
+
+/* Group 5 opcode extensions for 0xff. To be used with OPC_GRP5. */
+#define EXT5_CALLN_Ev 2
+#define EXT5_JMPN_Ev 4
/* Condition codes to be added to OPC_JCC_{long,short}. */
#define JCC_JMP (-1)
@@ -1060,7 +1072,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out32(s, 0);
} else {
/* indirect jump method */
- tcg_out_modrm_offset(s, 0xff, EXT_JMPN_Ev, -1,
+ tcg_out_modrm_offset(s, OPC_GRP5, EXT5_JMPN_Ev, -1,
(tcg_target_long)(s->tb_next + args[0]));
}
s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
@@ -1070,7 +1082,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_calli(s, args[0]);
} else {
/* call *reg */
- tcg_out_modrm(s, 0xff, EXT_CALLN_Ev, args[0]);
+ tcg_out_modrm(s, OPC_GRP5, EXT5_CALLN_Ev, args[0]);
}
break;
case INDEX_op_jmp:
@@ -1079,7 +1091,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out32(s, args[0] - (tcg_target_long)s->code_ptr - 4);
} else {
/* jmp *reg */
- tcg_out_modrm(s, 0xff, EXT_JMPN_Ev, args[0]);
+ tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, args[0]);
}
break;
case INDEX_op_br:
@@ -1156,13 +1168,13 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
}
break;
case INDEX_op_mulu2_i32:
- tcg_out_modrm(s, 0xf7, 4, args[3]);
+ tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_MUL, args[3]);
break;
case INDEX_op_div2_i32:
- tcg_out_modrm(s, 0xf7, 7, args[4]);
+ tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_IDIV, args[4]);
break;
case INDEX_op_divu2_i32:
- tcg_out_modrm(s, 0xf7, 6, args[4]);
+ tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_DIV, args[4]);
break;
case INDEX_op_shl_i32:
c = SHIFT_SHL;
@@ -1226,11 +1238,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
break;
case INDEX_op_neg_i32:
- tcg_out_modrm(s, 0xf7, 3, args[0]);
+ tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_NEG, args[0]);
break;
case INDEX_op_not_i32:
- tcg_out_modrm(s, 0xf7, 2, args[0]);
+ tcg_out_modrm(s, OPC_GRP3_Ev, EXT3_NOT, args[0]);
break;
case INDEX_op_ext8s_i32:
@@ -1398,7 +1410,7 @@ void tcg_target_qemu_prologue(TCGContext *s)
stack_addend = frame_size - push_size;
tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
- tcg_out_modrm(s, 0xff, EXT_JMPN_Ev, TCG_REG_EAX); /* jmp *%eax */
+ tcg_out_modrm(s, OPC_GRP5, EXT5_JMPN_Ev, TCG_REG_EAX); /* jmp *%eax */
/* TB epilogue */
tb_ret_addr = s->code_ptr;
commit 32a8ffb97043bc5691ebebfb219e4161a300ef8f
Author: Richard Henderson <rth at twiddle.net>
Date: Fri May 21 08:30:29 2010 -0700
tcg-i386: Tidy setcc.
Define and use OPC_SETCC.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 59f88f3..1499c81 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -184,6 +184,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define OPC_PUSH_Iv (0x68)
#define OPC_PUSH_Ib (0x6a)
#define OPC_RET (0xc3)
+#define OPC_SETCC (0x90 | P_EXT) /* ... plus condition code */
#define OPC_SHIFT_1 (0xd1)
#define OPC_SHIFT_Ib (0xc1)
#define OPC_SHIFT_cl (0xd3)
@@ -577,8 +578,7 @@ static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGArg dest,
TCGArg arg1, TCGArg arg2, int const_arg2)
{
tcg_out_cmp(s, arg1, arg2, const_arg2);
- /* setcc */
- tcg_out_modrm(s, 0x90 | tcg_cond_to_jcc[cond] | P_EXT, 0, dest);
+ tcg_out_modrm(s, OPC_SETCC | tcg_cond_to_jcc[cond], 0, dest);
tcg_out_ext8u(s, dest, dest);
}
commit 3c3accc670ec437c70557ca6f0a43111188805d8
Author: Richard Henderson <rth at twiddle.net>
Date: Fri May 21 08:30:28 2010 -0700
tcg-i386: Tidy ret.
Define and use OPC_RET.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index efc2a82..59f88f3 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -183,6 +183,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define OPC_PUSH_r32 (0x50)
#define OPC_PUSH_Iv (0x68)
#define OPC_PUSH_Ib (0x6a)
+#define OPC_RET (0xc3)
#define OPC_SHIFT_1 (0xd1)
#define OPC_SHIFT_Ib (0xc1)
#define OPC_SHIFT_cl (0xd3)
@@ -1405,7 +1406,7 @@ void tcg_target_qemu_prologue(TCGContext *s)
for(i = ARRAY_SIZE(tcg_target_callee_save_regs) - 1; i >= 0; i--) {
tcg_out_pop(s, tcg_target_callee_save_regs[i]);
}
- tcg_out8(s, 0xc3); /* ret */
+ tcg_out_opc(s, OPC_RET);
}
void tcg_target_init(TCGContext *s)
commit aadb21a4b27457710f2a62682fd040e8fe37af65
Author: Richard Henderson <rth at twiddle.net>
Date: Fri May 21 08:30:27 2010 -0700
tcg-i386: Tidy calls.
Define OPC_CALL_Jz, generated by tcg_out_calli; use the later
throughout. Unify the calls within qemu_st; adjust the stack
with a single pop if applicable.
Define and use EXT_CALLN_Ev for indirect calls.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 5557f8c..efc2a82 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -163,6 +163,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define OPC_ARITH_GvEv (0x03) /* ... plus (ARITH_FOO << 3) */
#define OPC_ADD_GvEv (OPC_ARITH_GvEv | (ARITH_ADD << 3))
#define OPC_BSWAP (0xc8 | P_EXT)
+#define OPC_CALL_Jz (0xe8)
#define OPC_CMP_GvEv (OPC_ARITH_GvEv | (ARITH_CMP << 3))
#define OPC_DEC_r32 (0x48)
#define OPC_INC_r32 (0x40)
@@ -205,6 +206,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define SHIFT_SAR 7
/* Group 5 opcode extensions for 0xff. */
+#define EXT_CALLN_Ev 2
#define EXT_JMPN_Ev 4
/* Condition codes to be added to OPC_JCC_{long,short}. */
@@ -621,6 +623,12 @@ static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
}
}
+static void tcg_out_calli(TCGContext *s, tcg_target_long dest)
+{
+ tcg_out_opc(s, OPC_CALL_Jz);
+ tcg_out32(s, dest - (tcg_target_long)s->code_ptr - 4);
+}
+
#if defined(CONFIG_SOFTMMU)
#include "../../softmmu_defs.h"
@@ -725,9 +733,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
#endif
- tcg_out8(s, 0xe8);
- tcg_out32(s, (tcg_target_long)qemu_ld_helpers[s_bits] -
- (tcg_target_long)s->code_ptr - 4);
+ tcg_out_calli(s, (tcg_target_long)qemu_ld_helpers[s_bits]);
switch(opc) {
case 0 | 4:
@@ -844,6 +850,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
{
int addr_reg, data_reg, data_reg2, r0, r1, mem_index, s_bits, bswap;
#if defined(CONFIG_SOFTMMU)
+ int stack_adjust;
uint8_t *label1_ptr, *label2_ptr;
#endif
#if TARGET_LONG_BITS == 64
@@ -917,10 +924,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
tcg_out_mov(s, TCG_REG_EDX, data_reg);
tcg_out_mov(s, TCG_REG_ECX, data_reg2);
tcg_out_pushi(s, mem_index);
- tcg_out8(s, 0xe8);
- tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] -
- (tcg_target_long)s->code_ptr - 4);
- tcg_out_addi(s, TCG_REG_ESP, 4);
+ stack_adjust = 4;
} else {
switch(opc) {
case 0:
@@ -934,9 +938,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
break;
}
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_ECX, mem_index);
- tcg_out8(s, 0xe8);
- tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] -
- (tcg_target_long)s->code_ptr - 4);
+ stack_adjust = 0;
}
#else
if (opc == 3) {
@@ -944,10 +946,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
tcg_out_pushi(s, mem_index);
tcg_out_push(s, data_reg2);
tcg_out_push(s, data_reg);
- tcg_out8(s, 0xe8);
- tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] -
- (tcg_target_long)s->code_ptr - 4);
- tcg_out_addi(s, TCG_REG_ESP, 12);
+ stack_adjust = 12;
} else {
tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
switch(opc) {
@@ -962,13 +961,19 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
break;
}
tcg_out_pushi(s, mem_index);
- tcg_out8(s, 0xe8);
- tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] -
- (tcg_target_long)s->code_ptr - 4);
- tcg_out_addi(s, TCG_REG_ESP, 4);
+ stack_adjust = 4;
}
#endif
-
+
+ tcg_out_calli(s, (tcg_target_long)qemu_st_helpers[s_bits]);
+
+ if (stack_adjust == 4) {
+ /* Pop and discard. This is 2 bytes smaller than the add. */
+ tcg_out_pop(s, TCG_REG_ECX);
+ } else if (stack_adjust != 0) {
+ tcg_out_addi(s, TCG_REG_ESP, stack_adjust);
+ }
+
/* jmp label2 */
tcg_out8(s, OPC_JMP_short);
label2_ptr = s->code_ptr;
@@ -1061,10 +1066,10 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
break;
case INDEX_op_call:
if (const_args[0]) {
- tcg_out8(s, 0xe8);
- tcg_out32(s, args[0] - (tcg_target_long)s->code_ptr - 4);
+ tcg_out_calli(s, args[0]);
} else {
- tcg_out_modrm(s, 0xff, 2, args[0]);
+ /* call *reg */
+ tcg_out_modrm(s, 0xff, EXT_CALLN_Ev, args[0]);
}
break;
case INDEX_op_jmp:
commit 6858614e6c0da6e557680a3606b32c0b8f0a093d
Author: Richard Henderson <rth at twiddle.net>
Date: Fri May 21 08:30:26 2010 -0700
tcg-i386: Tidy push/pop.
Move tcg_out_push/pop up in the file so that they can be used
by qemu_ld/st. Define a tcg_out_pushi to be used as well.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 2e32c5d..5557f8c 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -178,6 +178,10 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define OPC_MOVSWL (0xbf | P_EXT)
#define OPC_MOVZBL (0xb6 | P_EXT)
#define OPC_MOVZWL (0xb7 | P_EXT)
+#define OPC_POP_r32 (0x58)
+#define OPC_PUSH_r32 (0x50)
+#define OPC_PUSH_Iv (0x68)
+#define OPC_PUSH_Ib (0x6a)
#define OPC_SHIFT_1 (0xd1)
#define OPC_SHIFT_Ib (0xc1)
#define OPC_SHIFT_cl (0xd3)
@@ -306,6 +310,27 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type,
}
}
+static inline void tcg_out_pushi(TCGContext *s, tcg_target_long val)
+{
+ if (val == (int8_t)val) {
+ tcg_out_opc(s, OPC_PUSH_Ib);
+ tcg_out8(s, val);
+ } else {
+ tcg_out_opc(s, OPC_PUSH_Iv);
+ tcg_out32(s, val);
+ }
+}
+
+static inline void tcg_out_push(TCGContext *s, int reg)
+{
+ tcg_out_opc(s, OPC_PUSH_r32 + reg);
+}
+
+static inline void tcg_out_pop(TCGContext *s, int reg)
+{
+ tcg_out_opc(s, OPC_POP_r32 + reg);
+}
+
static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
int arg1, tcg_target_long arg2)
{
@@ -891,8 +916,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
if (opc == 3) {
tcg_out_mov(s, TCG_REG_EDX, data_reg);
tcg_out_mov(s, TCG_REG_ECX, data_reg2);
- tcg_out8(s, 0x6a); /* push Ib */
- tcg_out8(s, mem_index);
+ tcg_out_pushi(s, mem_index);
tcg_out8(s, 0xe8);
tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] -
(tcg_target_long)s->code_ptr - 4);
@@ -917,10 +941,9 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
#else
if (opc == 3) {
tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
- tcg_out8(s, 0x6a); /* push Ib */
- tcg_out8(s, mem_index);
- tcg_out_opc(s, 0x50 + data_reg2); /* push */
- tcg_out_opc(s, 0x50 + data_reg); /* push */
+ tcg_out_pushi(s, mem_index);
+ tcg_out_push(s, data_reg2);
+ tcg_out_push(s, data_reg);
tcg_out8(s, 0xe8);
tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] -
(tcg_target_long)s->code_ptr - 4);
@@ -938,8 +961,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
tcg_out_mov(s, TCG_REG_ECX, data_reg);
break;
}
- tcg_out8(s, 0x6a); /* push Ib */
- tcg_out8(s, mem_index);
+ tcg_out_pushi(s, mem_index);
tcg_out8(s, 0xe8);
tcg_out32(s, (tcg_target_long)qemu_st_helpers[s_bits] -
(tcg_target_long)s->code_ptr - 4);
@@ -1352,16 +1374,6 @@ static int tcg_target_callee_save_regs[] = {
TCG_REG_EDI,
};
-static inline void tcg_out_push(TCGContext *s, int reg)
-{
- tcg_out_opc(s, 0x50 + reg);
-}
-
-static inline void tcg_out_pop(TCGContext *s, int reg)
-{
- tcg_out_opc(s, 0x58 + reg);
-}
-
/* Generate global QEMU prologue and epilogue code */
void tcg_target_qemu_prologue(TCGContext *s)
{
commit ef10b106b62aba0d47ecffb73730d751407d1881
Author: Richard Henderson <rth at twiddle.net>
Date: Fri May 21 08:30:25 2010 -0700
tcg-i386: Tidy movi.
Define and use OPC_MOVL_Iv.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index da7c358..2e32c5d 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -173,6 +173,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define OPC_MOVB_EvGv (0x88) /* stores, more or less */
#define OPC_MOVL_EvGv (0x89) /* stores, more or less */
#define OPC_MOVL_GvEv (0x8b) /* loads, more or less */
+#define OPC_MOVL_Iv (0xb8)
#define OPC_MOVSBL (0xbe | P_EXT)
#define OPC_MOVSWL (0xbf | P_EXT)
#define OPC_MOVZBL (0xb6 | P_EXT)
@@ -300,7 +301,7 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type,
if (arg == 0) {
tgen_arithr(s, ARITH_XOR, ret, ret);
} else {
- tcg_out8(s, 0xb8 + ret);
+ tcg_out8(s, OPC_MOVL_Iv + ret);
tcg_out32(s, arg);
}
}
commit 81570a70a004cf1292a55437f83c8f89131a6c08
Author: Richard Henderson <rth at twiddle.net>
Date: Fri May 21 08:30:24 2010 -0700
tcg-i386: Tidy non-immediate arithmetic operations.
Add more OPC values, and tgen_arithr. Use the later throughout.
Note that normal reg/reg arithmetic now uses the Gv,Ev opcode form
instead of the Ev,Gv opcode form used previously. Both forms
disassemble properly, and so there's no visible change when diffing
log files before and after the change. This change makes the operand
ordering within the output routines more natural, and avoids the need
to define an OPC_ARITH_EvGv since a read-modify-write with memory is
not needed within TCG.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 5e8c58b..da7c358 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -160,7 +160,12 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define OPC_ARITH_EvIz (0x81)
#define OPC_ARITH_EvIb (0x83)
+#define OPC_ARITH_GvEv (0x03) /* ... plus (ARITH_FOO << 3) */
+#define OPC_ADD_GvEv (OPC_ARITH_GvEv | (ARITH_ADD << 3))
#define OPC_BSWAP (0xc8 | P_EXT)
+#define OPC_CMP_GvEv (OPC_ARITH_GvEv | (ARITH_CMP << 3))
+#define OPC_DEC_r32 (0x48)
+#define OPC_INC_r32 (0x40)
#define OPC_JCC_long (0x80 | P_EXT) /* ... plus condition code */
#define OPC_JCC_short (0x70) /* ... plus condition code */
#define OPC_JMP_long (0xe9)
@@ -175,6 +180,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define OPC_SHIFT_1 (0xd1)
#define OPC_SHIFT_Ib (0xc1)
#define OPC_SHIFT_cl (0xd3)
+#define OPC_TESTL (0x85)
/* Group 1 opcode extensions for 0x80-0x83. */
#define ARITH_ADD 0
@@ -275,6 +281,12 @@ static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r, int rm,
}
}
+/* Generate dest op= src. Uses the same ARITH_* codes as tgen_arithi. */
+static inline void tgen_arithr(TCGContext *s, int subop, int dest, int src)
+{
+ tcg_out_modrm(s, OPC_ARITH_GvEv + (subop << 3), dest, src);
+}
+
static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
{
if (arg != ret) {
@@ -286,8 +298,7 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type,
int ret, int32_t arg)
{
if (arg == 0) {
- /* xor r0,r0 */
- tcg_out_modrm(s, 0x01 | (ARITH_XOR << 3), ret, ret);
+ tgen_arithr(s, ARITH_XOR, ret, ret);
} else {
tcg_out8(s, 0xb8 + ret);
tcg_out32(s, arg);
@@ -353,14 +364,15 @@ static inline void tcg_out_ext16s(TCGContext *s, int dest, int src)
tcg_out_modrm(s, OPC_MOVSWL, dest, src);
}
-static inline void tgen_arithi(TCGContext *s, int c, int r0, int32_t val, int cf)
+static inline void tgen_arithi(TCGContext *s, int c, int r0,
+ int32_t val, int cf)
{
- if (!cf && ((c == ARITH_ADD && val == 1) || (c == ARITH_SUB && val == -1))) {
- /* inc */
- tcg_out_opc(s, 0x40 + r0);
- } else if (!cf && ((c == ARITH_ADD && val == -1) || (c == ARITH_SUB && val == 1))) {
- /* dec */
- tcg_out_opc(s, 0x48 + r0);
+ /* ??? While INC is 2 bytes shorter than ADDL $1, they also induce
+ partial flags update stalls on Pentium4 and are not recommended
+ by current Intel optimization manuals. */
+ if (!cf && (c == ARITH_ADD || c == ARITH_SUB) && (val == 1 || val == -1)) {
+ int opc = ((c == ARITH_ADD) ^ (val < 0) ? OPC_INC_r32 : OPC_DEC_r32);
+ tcg_out_opc(s, opc + r0);
} else if (val == (int8_t)val) {
tcg_out_modrm(s, OPC_ARITH_EvIb, c, r0);
tcg_out8(s, val);
@@ -433,12 +445,12 @@ static void tcg_out_cmp(TCGContext *s, TCGArg arg1, TCGArg arg2,
if (const_arg2) {
if (arg2 == 0) {
/* test r, r */
- tcg_out_modrm(s, 0x85, arg1, arg1);
+ tcg_out_modrm(s, OPC_TESTL, arg1, arg1);
} else {
tgen_arithi(s, ARITH_CMP, arg1, arg2, 0);
}
} else {
- tcg_out_modrm(s, 0x01 | (ARITH_CMP << 3), arg2, arg1);
+ tgen_arithr(s, ARITH_CMP, arg1, arg2);
}
}
@@ -653,7 +665,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
tcg_out32(s, offsetof(CPUState, tlb_table[mem_index][0].addr_read));
/* cmp 0(r1), r0 */
- tcg_out_modrm_offset(s, 0x3b, r0, r1, 0);
+ tcg_out_modrm_offset(s, OPC_CMP_GvEv, r0, r1, 0);
tcg_out_mov(s, r0, addr_reg);
@@ -669,7 +681,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
s->code_ptr++;
/* cmp 4(r1), addr_reg2 */
- tcg_out_modrm_offset(s, 0x3b, addr_reg2, r1, 4);
+ tcg_out_modrm_offset(s, OPC_CMP_GvEv, addr_reg2, r1, 4);
/* je label1 */
tcg_out8(s, OPC_JCC_short + JCC_JE);
@@ -728,7 +740,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
*label1_ptr = s->code_ptr - label1_ptr - 1;
/* add x(r1), r0 */
- tcg_out_modrm_offset(s, 0x03, r0, r1, offsetof(CPUTLBEntry, addend) -
+ tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
+ offsetof(CPUTLBEntry, addend) -
offsetof(CPUTLBEntry, addr_read));
#else
r0 = addr_reg;
@@ -845,7 +858,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
tcg_out32(s, offsetof(CPUState, tlb_table[mem_index][0].addr_write));
/* cmp 0(r1), r0 */
- tcg_out_modrm_offset(s, 0x3b, r0, r1, 0);
+ tcg_out_modrm_offset(s, OPC_CMP_GvEv, r0, r1, 0);
tcg_out_mov(s, r0, addr_reg);
@@ -861,7 +874,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
s->code_ptr++;
/* cmp 4(r1), addr_reg2 */
- tcg_out_modrm_offset(s, 0x3b, addr_reg2, r1, 4);
+ tcg_out_modrm_offset(s, OPC_CMP_GvEv, addr_reg2, r1, 4);
/* je label1 */
tcg_out8(s, OPC_JCC_short + JCC_JE);
@@ -942,7 +955,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
*label1_ptr = s->code_ptr - label1_ptr - 1;
/* add x(r1), r0 */
- tcg_out_modrm_offset(s, 0x03, r0, r1, offsetof(CPUTLBEntry, addend) -
+ tcg_out_modrm_offset(s, OPC_ADD_GvEv, r0, r1,
+ offsetof(CPUTLBEntry, addend) -
offsetof(CPUTLBEntry, addr_write));
#else
r0 = addr_reg;
@@ -1094,7 +1108,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
if (const_args[2]) {
tgen_arithi(s, c, args[0], args[2], 0);
} else {
- tcg_out_modrm(s, 0x01 | (c << 3), args[2], args[0]);
+ tgen_arithr(s, c, args[0], args[2]);
}
break;
case INDEX_op_mul_i32:
@@ -1144,24 +1158,28 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
goto gen_shift32;
case INDEX_op_add2_i32:
- if (const_args[4])
+ if (const_args[4]) {
tgen_arithi(s, ARITH_ADD, args[0], args[4], 1);
- else
- tcg_out_modrm(s, 0x01 | (ARITH_ADD << 3), args[4], args[0]);
- if (const_args[5])
+ } else {
+ tgen_arithr(s, ARITH_ADD, args[0], args[4]);
+ }
+ if (const_args[5]) {
tgen_arithi(s, ARITH_ADC, args[1], args[5], 1);
- else
- tcg_out_modrm(s, 0x01 | (ARITH_ADC << 3), args[5], args[1]);
+ } else {
+ tgen_arithr(s, ARITH_ADC, args[1], args[5]);
+ }
break;
case INDEX_op_sub2_i32:
- if (const_args[4])
+ if (const_args[4]) {
tgen_arithi(s, ARITH_SUB, args[0], args[4], 1);
- else
- tcg_out_modrm(s, 0x01 | (ARITH_SUB << 3), args[4], args[0]);
- if (const_args[5])
+ } else {
+ tgen_arithr(s, ARITH_SUB, args[0], args[4]);
+ }
+ if (const_args[5]) {
tgen_arithi(s, ARITH_SBB, args[1], args[5], 1);
- else
- tcg_out_modrm(s, 0x01 | (ARITH_SBB << 3), args[5], args[1]);
+ } else {
+ tgen_arithr(s, ARITH_SBB, args[1], args[5]);
+ }
break;
case INDEX_op_brcond_i32:
tcg_out_brcond(s, args[2], args[0], args[1], const_args[1],
commit a369a702a13629ec58ed483eb4a259f5b67579d7
Author: Richard Henderson <rth at twiddle.net>
Date: Fri May 21 08:30:23 2010 -0700
tcg-i386: Tidy immediate arithmetic operations.
Define OPC_ARITH_EvI[bz]; use throughout. Use tcg_out_ext8u
directly in setcond. Use tgen_arithi in qemu_ld/st.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 949e974..5e8c58b 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -158,6 +158,8 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define P_EXT 0x100 /* 0x0f opcode prefix */
+#define OPC_ARITH_EvIz (0x81)
+#define OPC_ARITH_EvIb (0x83)
#define OPC_BSWAP (0xc8 | P_EXT)
#define OPC_JCC_long (0x80 | P_EXT) /* ... plus condition code */
#define OPC_JCC_short (0x70) /* ... plus condition code */
@@ -360,14 +362,14 @@ static inline void tgen_arithi(TCGContext *s, int c, int r0, int32_t val, int cf
/* dec */
tcg_out_opc(s, 0x48 + r0);
} else if (val == (int8_t)val) {
- tcg_out_modrm(s, 0x83, c, r0);
+ tcg_out_modrm(s, OPC_ARITH_EvIb, c, r0);
tcg_out8(s, val);
} else if (c == ARITH_AND && val == 0xffu && r0 < 4) {
tcg_out_ext8u(s, r0, r0);
} else if (c == ARITH_AND && val == 0xffffu) {
tcg_out_ext16u(s, r0, r0);
} else {
- tcg_out_modrm(s, 0x81, c, r0);
+ tcg_out_modrm(s, OPC_ARITH_EvIz, c, r0);
tcg_out32(s, val);
}
}
@@ -536,7 +538,7 @@ static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGArg dest,
tcg_out_cmp(s, arg1, arg2, const_arg2);
/* setcc */
tcg_out_modrm(s, 0x90 | tcg_cond_to_jcc[cond] | P_EXT, 0, dest);
- tgen_arithi(s, ARITH_AND, dest, 0xff, 0);
+ tcg_out_ext8u(s, dest, dest);
}
static void tcg_out_setcond2(TCGContext *s, const TCGArg *args,
@@ -638,16 +640,12 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
#if defined(CONFIG_SOFTMMU)
tcg_out_mov(s, r1, addr_reg);
-
tcg_out_mov(s, r0, addr_reg);
-
+
tcg_out_shifti(s, SHIFT_SHR, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
- tcg_out_modrm(s, 0x81, 4, r0); /* andl $x, r0 */
- tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
-
- tcg_out_modrm(s, 0x81, 4, r1); /* andl $x, r1 */
- tcg_out32(s, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
+ tgen_arithi(s, ARITH_AND, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
+ tgen_arithi(s, ARITH_AND, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
tcg_out_opc(s, 0x8d); /* lea offset(r1, %ebp), r1 */
tcg_out8(s, 0x80 | (r1 << 3) | 0x04);
@@ -834,16 +832,12 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
#if defined(CONFIG_SOFTMMU)
tcg_out_mov(s, r1, addr_reg);
-
tcg_out_mov(s, r0, addr_reg);
tcg_out_shifti(s, SHIFT_SHR, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
- tcg_out_modrm(s, 0x81, 4, r0); /* andl $x, r0 */
- tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
-
- tcg_out_modrm(s, 0x81, 4, r1); /* andl $x, r1 */
- tcg_out32(s, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
+ tgen_arithi(s, ARITH_AND, r0, TARGET_PAGE_MASK | ((1 << s_bits) - 1), 0);
+ tgen_arithi(s, ARITH_AND, r1, (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS, 0);
tcg_out_opc(s, 0x8d); /* lea offset(r1, %ebp), r1 */
tcg_out8(s, 0x80 | (r1 << 3) | 0x04);
commit 6817c35598c2f58c53a9b5b7b5d6bd078a513a83
Author: Richard Henderson <rth at twiddle.net>
Date: Fri May 21 08:30:22 2010 -0700
tcg-i386: Tidy ext8s and ext16s operations.
Define OPC_MOVSBL and OPC_MOVSWL. Factor opcode emission to
separate functions.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 4497010..949e974 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -166,6 +166,8 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define OPC_MOVB_EvGv (0x88) /* stores, more or less */
#define OPC_MOVL_EvGv (0x89) /* stores, more or less */
#define OPC_MOVL_GvEv (0x8b) /* loads, more or less */
+#define OPC_MOVSBL (0xbe | P_EXT)
+#define OPC_MOVSWL (0xbf | P_EXT)
#define OPC_MOVZBL (0xb6 | P_EXT)
#define OPC_MOVZWL (0xb7 | P_EXT)
#define OPC_SHIFT_1 (0xd1)
@@ -330,12 +332,25 @@ static inline void tcg_out_ext8u(TCGContext *s, int dest, int src)
tcg_out_modrm(s, OPC_MOVZBL, dest, src);
}
+static void tcg_out_ext8s(TCGContext *s, int dest, int src)
+{
+ /* movsbl */
+ assert(src < 4);
+ tcg_out_modrm(s, OPC_MOVSBL, dest, src);
+}
+
static inline void tcg_out_ext16u(TCGContext *s, int dest, int src)
{
/* movzwl */
tcg_out_modrm(s, OPC_MOVZWL, dest, src);
}
+static inline void tcg_out_ext16s(TCGContext *s, int dest, int src)
+{
+ /* movswl */
+ tcg_out_modrm(s, OPC_MOVSWL, dest, src);
+}
+
static inline void tgen_arithi(TCGContext *s, int c, int r0, int32_t val, int cf)
{
if (!cf && ((c == ARITH_ADD && val == 1) || (c == ARITH_SUB && val == -1))) {
@@ -680,12 +695,10 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
switch(opc) {
case 0 | 4:
- /* movsbl */
- tcg_out_modrm(s, 0xbe | P_EXT, data_reg, TCG_REG_EAX);
+ tcg_out_ext8s(s, data_reg, TCG_REG_EAX);
break;
case 1 | 4:
- /* movswl */
- tcg_out_modrm(s, 0xbf | P_EXT, data_reg, TCG_REG_EAX);
+ tcg_out_ext16s(s, data_reg, TCG_REG_EAX);
break;
case 0:
tcg_out_ext8u(s, data_reg, TCG_REG_EAX);
@@ -735,7 +748,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
break;
case 0 | 4:
/* movsbl */
- tcg_out_modrm_offset(s, 0xbe | P_EXT, data_reg, r0, GUEST_BASE);
+ tcg_out_modrm_offset(s, OPC_MOVSBL, data_reg, r0, GUEST_BASE);
break;
case 1:
/* movzwl */
@@ -746,12 +759,12 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
break;
case 1 | 4:
/* movswl */
- tcg_out_modrm_offset(s, 0xbf | P_EXT, data_reg, r0, GUEST_BASE);
+ tcg_out_modrm_offset(s, OPC_MOVSWL, data_reg, r0, GUEST_BASE);
if (bswap) {
tcg_out_rolw_8(s, data_reg);
/* movswl data_reg, data_reg */
- tcg_out_modrm(s, 0xbf | P_EXT, data_reg, data_reg);
+ tcg_out_modrm(s, OPC_MOVSWL, data_reg, data_reg);
}
break;
case 2:
@@ -1044,7 +1057,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
break;
case INDEX_op_ld8s_i32:
/* movsbl */
- tcg_out_modrm_offset(s, 0xbe | P_EXT, args[0], args[1], args[2]);
+ tcg_out_modrm_offset(s, OPC_MOVSBL, args[0], args[1], args[2]);
break;
case INDEX_op_ld16u_i32:
/* movzwl */
@@ -1052,7 +1065,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
break;
case INDEX_op_ld16s_i32:
/* movswl */
- tcg_out_modrm_offset(s, 0xbf | P_EXT, args[0], args[1], args[2]);
+ tcg_out_modrm_offset(s, OPC_MOVSWL, args[0], args[1], args[2]);
break;
case INDEX_op_ld_i32:
tcg_out_ld(s, TCG_TYPE_I32, args[0], args[1], args[2]);
@@ -1180,10 +1193,10 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
break;
case INDEX_op_ext8s_i32:
- tcg_out_modrm(s, 0xbe | P_EXT, args[0], args[1]);
+ tcg_out_ext8s(s, args[0], args[1]);
break;
case INDEX_op_ext16s_i32:
- tcg_out_modrm(s, 0xbf | P_EXT, args[0], args[1]);
+ tcg_out_ext16s(s, args[0], args[1]);
break;
case INDEX_op_ext8u_i32:
tcg_out_ext8u(s, args[0], args[1]);
commit 55e082a7a592d8115f9f44dd8c79395ff4f1ce42
Author: Richard Henderson <rth at twiddle.net>
Date: Fri May 21 08:30:21 2010 -0700
tcg-i386: Tidy ext8u and ext16u operations.
Define OPC_MOVZBL and OPC_MOVZWL. Factor opcode emission to
separate functions.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 904d2e5..4497010 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -166,6 +166,8 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define OPC_MOVB_EvGv (0x88) /* stores, more or less */
#define OPC_MOVL_EvGv (0x89) /* stores, more or less */
#define OPC_MOVL_GvEv (0x8b) /* loads, more or less */
+#define OPC_MOVZBL (0xb6 | P_EXT)
+#define OPC_MOVZWL (0xb7 | P_EXT)
#define OPC_SHIFT_1 (0xd1)
#define OPC_SHIFT_Ib (0xc1)
#define OPC_SHIFT_cl (0xd3)
@@ -209,8 +211,6 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define JCC_JLE 0xe
#define JCC_JG 0xf
-#define P_EXT 0x100 /* 0x0f opcode prefix */
-
static const uint8_t tcg_cond_to_jcc[10] = {
[TCG_COND_EQ] = JCC_JE,
[TCG_COND_NE] = JCC_JNE,
@@ -323,6 +323,19 @@ static inline void tcg_out_rolw_8(TCGContext *s, int reg)
tcg_out_shifti(s, SHIFT_ROL, reg, 8);
}
+static inline void tcg_out_ext8u(TCGContext *s, int dest, int src)
+{
+ /* movzbl */
+ assert(src < 4);
+ tcg_out_modrm(s, OPC_MOVZBL, dest, src);
+}
+
+static inline void tcg_out_ext16u(TCGContext *s, int dest, int src)
+{
+ /* movzwl */
+ tcg_out_modrm(s, OPC_MOVZWL, dest, src);
+}
+
static inline void tgen_arithi(TCGContext *s, int c, int r0, int32_t val, int cf)
{
if (!cf && ((c == ARITH_ADD && val == 1) || (c == ARITH_SUB && val == -1))) {
@@ -335,11 +348,9 @@ static inline void tgen_arithi(TCGContext *s, int c, int r0, int32_t val, int cf
tcg_out_modrm(s, 0x83, c, r0);
tcg_out8(s, val);
} else if (c == ARITH_AND && val == 0xffu && r0 < 4) {
- /* movzbl */
- tcg_out_modrm(s, 0xb6 | P_EXT, r0, r0);
+ tcg_out_ext8u(s, r0, r0);
} else if (c == ARITH_AND && val == 0xffffu) {
- /* movzwl */
- tcg_out_modrm(s, 0xb7 | P_EXT, r0, r0);
+ tcg_out_ext16u(s, r0, r0);
} else {
tcg_out_modrm(s, 0x81, c, r0);
tcg_out32(s, val);
@@ -677,12 +688,10 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
tcg_out_modrm(s, 0xbf | P_EXT, data_reg, TCG_REG_EAX);
break;
case 0:
- /* movzbl */
- tcg_out_modrm(s, 0xb6 | P_EXT, data_reg, TCG_REG_EAX);
+ tcg_out_ext8u(s, data_reg, TCG_REG_EAX);
break;
case 1:
- /* movzwl */
- tcg_out_modrm(s, 0xb7 | P_EXT, data_reg, TCG_REG_EAX);
+ tcg_out_ext16u(s, data_reg, TCG_REG_EAX);
break;
case 2:
default:
@@ -722,7 +731,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
switch(opc) {
case 0:
/* movzbl */
- tcg_out_modrm_offset(s, 0xb6 | P_EXT, data_reg, r0, GUEST_BASE);
+ tcg_out_modrm_offset(s, OPC_MOVZBL, data_reg, r0, GUEST_BASE);
break;
case 0 | 4:
/* movsbl */
@@ -730,7 +739,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
break;
case 1:
/* movzwl */
- tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, GUEST_BASE);
+ tcg_out_modrm_offset(s, OPC_MOVZWL, data_reg, r0, GUEST_BASE);
if (bswap) {
tcg_out_rolw_8(s, data_reg);
}
@@ -870,12 +879,10 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
} else {
switch(opc) {
case 0:
- /* movzbl */
- tcg_out_modrm(s, 0xb6 | P_EXT, TCG_REG_EDX, data_reg);
+ tcg_out_ext8u(s, TCG_REG_EDX, data_reg);
break;
case 1:
- /* movzwl */
- tcg_out_modrm(s, 0xb7 | P_EXT, TCG_REG_EDX, data_reg);
+ tcg_out_ext16u(s, TCG_REG_EDX, data_reg);
break;
case 2:
tcg_out_mov(s, TCG_REG_EDX, data_reg);
@@ -901,12 +908,10 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
tcg_out_mov(s, TCG_REG_EDX, addr_reg2);
switch(opc) {
case 0:
- /* movzbl */
- tcg_out_modrm(s, 0xb6 | P_EXT, TCG_REG_ECX, data_reg);
+ tcg_out_ext8u(s, TCG_REG_ECX, data_reg);
break;
case 1:
- /* movzwl */
- tcg_out_modrm(s, 0xb7 | P_EXT, TCG_REG_ECX, data_reg);
+ tcg_out_ext16u(s, TCG_REG_ECX, data_reg);
break;
case 2:
tcg_out_mov(s, TCG_REG_ECX, data_reg);
@@ -1035,7 +1040,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
break;
case INDEX_op_ld8u_i32:
/* movzbl */
- tcg_out_modrm_offset(s, 0xb6 | P_EXT, args[0], args[1], args[2]);
+ tcg_out_modrm_offset(s, OPC_MOVZBL, args[0], args[1], args[2]);
break;
case INDEX_op_ld8s_i32:
/* movsbl */
@@ -1043,7 +1048,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
break;
case INDEX_op_ld16u_i32:
/* movzwl */
- tcg_out_modrm_offset(s, 0xb7 | P_EXT, args[0], args[1], args[2]);
+ tcg_out_modrm_offset(s, OPC_MOVZWL, args[0], args[1], args[2]);
break;
case INDEX_op_ld16s_i32:
/* movswl */
@@ -1181,10 +1186,10 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_modrm(s, 0xbf | P_EXT, args[0], args[1]);
break;
case INDEX_op_ext8u_i32:
- tcg_out_modrm(s, 0xb6 | P_EXT, args[0], args[1]);
+ tcg_out_ext8u(s, args[0], args[1]);
break;
case INDEX_op_ext16u_i32:
- tcg_out_modrm(s, 0xb7 | P_EXT, args[0], args[1]);
+ tcg_out_ext16u(s, args[0], args[1]);
break;
case INDEX_op_setcond_i32:
@@ -1279,8 +1284,8 @@ static const TCGTargetOpDef x86_op_defs[] = {
{ INDEX_op_ext8s_i32, { "r", "q" } },
{ INDEX_op_ext16s_i32, { "r", "r" } },
- { INDEX_op_ext8u_i32, { "r", "q"} },
- { INDEX_op_ext16u_i32, { "r", "r"} },
+ { INDEX_op_ext8u_i32, { "r", "q" } },
+ { INDEX_op_ext16u_i32, { "r", "r" } },
{ INDEX_op_setcond_i32, { "q", "r", "ri" } },
{ INDEX_op_setcond2_i32, { "r", "r", "r", "ri", "ri" } },
commit a9456998e978d86c91e58cf1d56cf42739b627e8
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date: Fri May 21 16:09:10 2010 +0200
axisdev88: Fix passing of kernel cmdline.
Signed-off-by: Edgar E. Iglesias <edgar at axis.com>
diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index 5516e42..7d59c96 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -240,13 +240,22 @@ static CPUWriteMemoryFunc * const gpio_write[] = {
#define INTMEM_SIZE (128 * 1024)
-static uint32_t bootstrap_pc;
+static struct {
+ uint32_t bootstrap_pc;
+ uint32_t regs[16];
+} loadargs;
+
static void main_cpu_reset(void *opaque)
{
+ int i;
+
CPUState *env = opaque;
cpu_reset(env);
- env->pc = bootstrap_pc;
+ env->pc = loadargs.bootstrap_pc;
+ for (i = 0; i < 16; i++) {
+ env->regs[i] = loadargs.regs[i];
+ }
}
static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
@@ -352,15 +361,15 @@ void axisdev88_init (ram_addr_t ram_size,
devboard SDK. */
kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
&entry, NULL, &high, 0, ELF_MACHINE, 0);
- bootstrap_pc = entry;
+ loadargs.bootstrap_pc = entry;
if (kernel_size < 0) {
/* Takes a kimage from the axis devboard SDK. */
kernel_size = load_image_targphys(kernel_filename, 0x40004000,
ram_size);
- bootstrap_pc = 0x40004000;
- env->regs[9] = 0x40004000 + kernel_size;
+ loadargs.bootstrap_pc = 0x40004000;
+ loadargs.regs[9] = 0x40004000 + kernel_size;
}
- env->regs[8] = 0x56902387; /* RAM init magic. */
+ loadargs.regs[8] = 0x56902387; /* RAM init magic. */
if (kernel_cmdline && (kcmdline_len = strlen(kernel_cmdline))) {
if (kcmdline_len > 256) {
@@ -368,15 +377,11 @@ void axisdev88_init (ram_addr_t ram_size,
exit(1);
}
/* Let the kernel know we are modifying the cmdline. */
- env->regs[10] = 0x87109563;
- env->regs[11] = 0x40000000;
- pstrcpy_targphys("cmdline", env->regs[11], 256, kernel_cmdline);
+ loadargs.regs[10] = 0x87109563;
+ loadargs.regs[11] = 0x40000000;
+ pstrcpy_targphys("cmdline", loadargs.regs[11], 256, kernel_cmdline);
}
}
- env->pc = bootstrap_pc;
-
- printf ("pc =%x\n", env->pc);
- printf ("ram size =%ld\n", ram_size);
}
static QEMUMachine axisdev88_machine = {
commit f6d20d0f4f1e01f293c3d3b5772926275927c661
Author: Bernhard Kauer <kauer at os.inf.tu-dresden.de>
Date: Fri May 21 14:05:55 2010 +0200
Replace \0s with spaces before sending strings to curses.
Signed-off-by: Bernhard Kauer <kauer at tudos.org>
Signed-off-by: Andrzej Zaborowski <andrew.zaborowski at intel.com>
diff --git a/console.h b/console.h
index 6def115..3a75bcc 100644
--- a/console.h
+++ b/console.h
@@ -306,6 +306,8 @@ static inline int ds_get_bytes_per_pixel(DisplayState *ds)
typedef unsigned long console_ch_t;
static inline void console_write_ch(console_ch_t *dest, uint32_t ch)
{
+ if (!(ch & 0xff))
+ ch |= ' ';
cpu_to_le32wu((uint32_t *) dest, ch);
}
commit a9cf98d939c4f6539fad7e7d812ea16d96ba3dc9
Author: Rabin Vincent <rabin at rab.in>
Date: Sun May 2 15:20:52 2010 +0530
arm_timer: fix oneshot mode
In oneshot mode, the delta needs to come from the TimerLoad register,
not the maximum limit.
Signed-off-by: Rabin Vincent <rabin at rab.in>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 5b6947a..9073ffc 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -71,7 +71,7 @@ static void arm_timer_recalibrate(arm_timer_state *s, int reload)
{
uint32_t limit;
- if ((s->control & TIMER_CTRL_PERIODIC) == 0) {
+ if ((s->control & (TIMER_CTRL_PERIODIC | TIMER_CTRL_ONESHOT)) == 0) {
/* Free running. */
if (s->control & TIMER_CTRL_32BIT)
limit = 0xffffffff;
commit d6759902cb467c002086853d2eb38fb969c29f7f
Author: Rabin Vincent <rabin at rab.in>
Date: Sun May 2 15:20:51 2010 +0530
arm_timer: reload timer when enabled
Reload the timer when TimerControl is written, if the timer is to be
enabled. Otherwise, if an earlier write to TimerLoad was done while
periodic mode was not set, s->delta may incorrectly still have the value
of the maximum limit instead of the value written to TimerLoad.
This problem is evident on versatileap on current linux-next, which
enables TIMER_CTRL_32BIT before writing to TimerLoad and then enabling
periodic mode and starting the timer. This causes the first periodic
tick to be scheduled to occur after 0xffffffff periods, leading to a
perceived hang while the kernel waits for the first timer tick.
Signed-off-by: Rabin Vincent <rabin at rab.in>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 9fef191..5b6947a 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -113,7 +113,7 @@ static void arm_timer_write(void *opaque, target_phys_addr_t offset,
case 1: freq >>= 4; break;
case 2: freq >>= 8; break;
}
- arm_timer_recalibrate(s, 0);
+ arm_timer_recalibrate(s, s->control & TIMER_CTRL_ENABLE);
ptimer_set_freq(s->timer, freq);
if (s->control & TIMER_CTRL_ENABLE) {
/* Restart the timer if still enabled. */
commit 0b2ec6fcfdad1dd9ce74c50e2d752afbb627b0d0
Author: Michael Walle <michael at walle.cc>
Date: Sat May 1 19:34:06 2010 +0200
pflash_cfi01: add device ID read command
Add support to read manufacturer and device ID. For everything else (eg.
lock bits) 0 is returned.
Signed-off-by: Michael Walle <michael at walle.cc>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c
index 20fe93d..19e13d6 100644
--- a/hw/pflash_cfi01.c
+++ b/hw/pflash_cfi01.c
@@ -166,6 +166,22 @@ static uint32_t pflash_read (pflash_t *pfl, target_phys_addr_t offset,
ret = pfl->status;
DPRINTF("%s: status %x\n", __func__, ret);
break;
+ case 0x90:
+ switch (boff) {
+ case 0:
+ ret = pfl->ident[0] << 8 | pfl->ident[1];
+ DPRINTF("%s: Manufacturer Code %04x\n", __func__, ret);
+ break;
+ case 1:
+ ret = pfl->ident[2] << 8 | pfl->ident[3];
+ DPRINTF("%s: Device ID Code %04x\n", __func__, ret);
+ break;
+ default:
+ DPRINTF("%s: Read Device Information boff=%x\n", __func__, boff);
+ ret = 0;
+ break;
+ }
+ break;
case 0x98: /* Query mode */
if (boff > pfl->cfi_len)
ret = 0;
@@ -283,6 +299,10 @@ static void pflash_write(pflash_t *pfl, target_phys_addr_t offset,
DPRINTF("%s: Read status register\n", __func__);
pfl->cmd = cmd;
return;
+ case 0x90: /* Read Device ID */
+ DPRINTF("%s: Read Device information\n", __func__);
+ pfl->cmd = cmd;
+ return;
case 0x98: /* CFI query */
DPRINTF("%s: CFI query\n", __func__);
break;
commit 3e89cb0419cf5ff8f97fe219c6faa58f4c0c8728
Author: Kevin Wolf <kwolf at redhat.com>
Date: Thu May 20 10:34:50 2010 +0200
vvfat: More build fixes with DEBUG
Casting a pointer to an int doesn't work on 64 bit platforms. Use the %p printf
conversion specifier instead.
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block/vvfat.c b/block/vvfat.c
index 13c31fa..6d61c2e 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -1244,7 +1244,7 @@ static void print_direntry(const direntry_t* direntry)
int j = 0;
char buffer[1024];
- fprintf(stderr, "direntry 0x%x: ", (int)direntry);
+ fprintf(stderr, "direntry %p: ", direntry);
if(!direntry)
return;
if(is_long_name(direntry)) {
@@ -1273,7 +1273,11 @@ static void print_direntry(const direntry_t* direntry)
static void print_mapping(const mapping_t* mapping)
{
- fprintf(stderr, "mapping (0x%x): begin, end = %d, %d, dir_index = %d, first_mapping_index = %d, name = %s, mode = 0x%x, " , (int)mapping, mapping->begin, mapping->end, mapping->dir_index, mapping->first_mapping_index, mapping->path, mapping->mode);
+ fprintf(stderr, "mapping (%p): begin, end = %d, %d, dir_index = %d, "
+ "first_mapping_index = %d, name = %s, mode = 0x%x, " ,
+ mapping, mapping->begin, mapping->end, mapping->dir_index,
+ mapping->first_mapping_index, mapping->path, mapping->mode);
+
if (mapping->mode & MODE_DIRECTORY)
fprintf(stderr, "parent_mapping_index = %d, first_dir_index = %d\n", mapping->info.dir.parent_mapping_index, mapping->info.dir.first_dir_index);
else
commit 792b45b142e6b901e1de20886bc3369211582b8c
Author: Riccardo Magliocchetti <riccardo.magliocchetti at gmail.com>
Date: Wed May 19 22:53:44 2010 +0200
vvfat: Fix compilation with DEBUG defined
gcc does not like passing a NULL where an int value is expected:
block/vvfat.c: In function âcheckpointâ:
block/vvfat.c:2868: error: passing argument 2 of âremove_mappingâ makes
integer from pointer without a cast
Signed-off-by: Riccardo Magliocchetti <riccardo.magliocchetti at gmail.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block/vvfat.c b/block/vvfat.c
index ce16bbd..13c31fa 100644
--- a/block/vvfat.c
+++ b/block/vvfat.c
@@ -2865,7 +2865,7 @@ static void checkpoint(void) {
return;
/* avoid compiler warnings: */
hexdump(NULL, 100);
- remove_mapping(vvv, NULL);
+ remove_mapping(vvv, 0);
print_mapping(NULL);
print_direntry(NULL);
}
commit 396759ad4ad5289623eb7e1993c433ad4e7b13a1
Author: Nicholas Bellinger <nab at linux-iscsi.org>
Date: Mon May 17 09:46:04 2010 -0700
block: Add SG_IO device check in refresh_total_sectors()
This patch adds a special case check for scsi-generic devices in
refresh_total_sectors() to skip the subsequent BlockDriver->bdrv_getlength()
that will be returning -ESPIPE from block/raw-posic.c:raw_getlength() for
BlockDriverState->sg=1 devices.
Signed-off-by: Nicholas A. Bellinger <nab at linux-iscsi.org>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block.c b/block.c
index 6a95768..0b0966c 100644
--- a/block.c
+++ b/block.c
@@ -361,6 +361,10 @@ static int refresh_total_sectors(BlockDriverState *bs, int64_t hint)
{
BlockDriver *drv = bs->drv;
+ /* Do not attempt drv->bdrv_getlength() on scsi-generic devices */
+ if (bs->sg)
+ return 0;
+
/* query actual device if possible, otherwise just trust the hint */
if (drv->bdrv_getlength) {
int64_t length = drv->bdrv_getlength(bs);
commit f8ea0b00e087380fa0c7309f843f67b7e2d0126a
Author: Nicholas Bellinger <nab at linux-iscsi.org>
Date: Mon May 17 09:45:57 2010 -0700
block: Make find_image_format() return 'raw' BlockDriver for SG_IO devices
This patch adds a special BlockDriverState->sg check in block.c:find_image_format()
after bdrv_file_open() -> block/raw-posix.c:hdev_open() has been called to determine
if we are dealing with a Linux host scsi-generic device.
The patch then returns the BlockDriver * from bdrv_find_format("raw"), skipping the
subsequent bdrv_read() and rest of find_image_format().
Signed-off-by: Nicholas A. Bellinger <nab at linux-iscsi.org>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/block.c b/block.c
index 89eece7..6a95768 100644
--- a/block.c
+++ b/block.c
@@ -329,6 +329,11 @@ static BlockDriver *find_image_format(const char *filename)
ret = bdrv_file_open(&bs, filename, 0);
if (ret < 0)
return NULL;
+
+ /* Return the raw BlockDriver * to scsi-generic devices */
+ if (bs->sg)
+ return bdrv_find_format("raw");
+
ret = bdrv_pread(bs, 0, buf, sizeof(buf));
bdrv_delete(bs);
if (ret < 0) {
commit 77be4366baface6613cfc312ba281f8e5860997c
Author: Christoph Hellwig <hch at lst.de>
Date: Wed May 19 20:53:10 2010 +0200
block: fix sector comparism in multiwrite_req_compare
The difference between the start sectors of two requests can be larger
than the size of the "int" type, which can lead to a not correctly
sorted multiwrite array and thus spurious I/O errors and filesystem
corruption due to incorrect request merges.
So instead of doing the cute sector arithmetics trick spell out the
exact comparisms.
Spotted by Kevin Wolf based on a testcase from Michael Tokarev.
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 bfe46e3..89eece7 100644
--- a/block.c
+++ b/block.c
@@ -1929,7 +1929,19 @@ static void multiwrite_cb(void *opaque, int ret)
static int multiwrite_req_compare(const void *a, const void *b)
{
- return (((BlockRequest*) a)->sector - ((BlockRequest*) b)->sector);
+ const BlockRequest *req1 = a, *req2 = b;
+
+ /*
+ * Note that we can't simply subtract req2->sector from req1->sector
+ * here as that could overflow the return value.
+ */
+ if (req1->sector > req2->sector) {
+ return 1;
+ } else if (req1->sector < req2->sector) {
+ return -1;
+ } else {
+ return 0;
+ }
}
/*
commit 618fbb84299780af96e3d4c4b6f2148656fe3708
Author: Christoph Hellwig <hch at lst.de>
Date: Wed May 19 12:40:09 2010 +0200
virtio-blk: fix barrier support
Before issuing the barrier to the block driver we need to flush our oustanding
queue of write requests, as the flush is supposed to be issued after them.
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 d270225..5d7f1a2 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -240,10 +240,20 @@ static void do_multiwrite(BlockDriverState *bs, BlockRequest *blkreq,
}
}
-static void virtio_blk_handle_flush(VirtIOBlockReq *req)
+static void virtio_blk_handle_flush(BlockRequest *blkreq, int *num_writes,
+ VirtIOBlockReq *req, BlockDriverState **old_bs)
{
BlockDriverAIOCB *acb;
+ /*
+ * Make sure all outstanding writes are posted to the backing device.
+ */
+ if (*old_bs != NULL) {
+ do_multiwrite(*old_bs, blkreq, *num_writes);
+ }
+ *num_writes = 0;
+ *old_bs = req->dev->bs;
+
acb = bdrv_aio_flush(req->dev->bs, virtio_blk_flush_complete, req);
if (!acb) {
virtio_blk_req_complete(req, VIRTIO_BLK_S_IOERR);
@@ -316,7 +326,8 @@ static void virtio_blk_handle_request(VirtIOBlockReq *req,
req->in = (void *)req->elem.in_sg[req->elem.in_num - 1].iov_base;
if (req->out->type & VIRTIO_BLK_T_FLUSH) {
- virtio_blk_handle_flush(req);
+ virtio_blk_handle_flush(mrb->blkreq, &mrb->num_writes,
+ req, &mrb->old_bs);
} else if (req->out->type & VIRTIO_BLK_T_SCSI_CMD) {
virtio_blk_handle_scsi(req);
} else if (req->out->type & VIRTIO_BLK_T_OUT) {
commit de6c8042ec55da18702fa51f09072fcaa315edc3
Author: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Date: Fri May 14 22:52:30 2010 +0100
virtio-blk: Avoid zeroing every request structure
The VirtIOBlockRequest structure is about 40 KB in size. This patch
avoids zeroing every request by only initializing fields that are read.
The other fields are either written to or may not be used at all.
Oprofile shows about 10% of CPU samples in memset called by
virtio_blk_alloc_request(). The workload is
dd if=/dev/vda of=/dev/null iflag=direct bs=8k running concurrently 4
times. This patch makes memset disappear to the bottom of the profile.
Signed-off-by: Stefan Hajnoczi <stefanha at linux.vnet.ibm.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/hw/virtio-blk.c b/hw/virtio-blk.c
index b05d15e..d270225 100644
--- a/hw/virtio-blk.c
+++ b/hw/virtio-blk.c
@@ -105,8 +105,10 @@ static void virtio_blk_flush_complete(void *opaque, int ret)
static VirtIOBlockReq *virtio_blk_alloc_request(VirtIOBlock *s)
{
- VirtIOBlockReq *req = qemu_mallocz(sizeof(*req));
+ VirtIOBlockReq *req = qemu_malloc(sizeof(*req));
req->dev = s;
+ req->qiov.size = 0;
+ req->next = NULL;
return req;
}
commit c53a7285b4377e91f30b7742c7e12c16d6bf86f0
Author: Avi Kivity <avi at redhat.com>
Date: Sun May 16 14:59:57 2010 +0300
block: fix aio_flush segfaults for read-only protocols (e.g. curl)
Not all block format drivers expose an io_flush method (reasonable for
read-only protocols), so calling io_flush there will immediately segfault.
Fix by checking for the method's existence before calling it.
Signed-off-by: Avi Kivity <avi at redhat.com>
Signed-off-by: Kevin Wolf <kwolf at redhat.com>
diff --git a/aio.c b/aio.c
index f164a47..2f08655 100644
--- a/aio.c
+++ b/aio.c
@@ -113,7 +113,9 @@ void qemu_aio_flush(void)
qemu_aio_wait();
QLIST_FOREACH(node, &aio_handlers, node) {
- ret |= node->io_flush(node->opaque);
+ if (node->io_flush) {
+ ret |= node->io_flush(node->opaque);
+ }
}
} while (qemu_bh_poll() || ret > 0);
}
commit 81a204e44356a4e147ee4bcfded3d25793c5a2ad
Author: Eduard - Gabriel Munteanu <eduard.munteanu at linux360.ro>
Date: Thu May 20 09:14:04 2010 +0300
pc: fix segfault introduced by 3d53f5c36ff6
Commit 3d53f5c36ff6 introduced a segfault by erroneously making fw_cfg a
'void **' and passing it around in different ways.
Signed-off-by: Eduard - Gabriel Munteanu <eduard.munteanu at linux360.ro>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/hw/pc.c b/hw/pc.c
index 20dc7fd..7715b17 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -818,7 +818,7 @@ void pc_memory_init(ram_addr_t ram_size,
ram_addr_t ram_addr, bios_offset, option_rom_offset;
ram_addr_t below_4g_mem_size, above_4g_mem_size = 0;
int bios_size, isa_bios_size;
- void **fw_cfg;
+ void *fw_cfg;
if (ram_size >= 0xe0000000 ) {
above_4g_mem_size = ram_size - 0xe0000000;
@@ -893,7 +893,7 @@ void pc_memory_init(ram_addr_t ram_size,
rom_set_fw(fw_cfg);
if (linux_boot) {
- load_linux(*fw_cfg, kernel_filename, initrd_filename, kernel_cmdline, below_4g_mem_size);
+ load_linux(fw_cfg, kernel_filename, initrd_filename, kernel_cmdline, below_4g_mem_size);
}
for (i = 0; i < nb_option_roms; i++) {
commit 70c482852aed861d728654c7bad9404eff76d9e3
Author: Richard Henderson <rth at twiddle.net>
Date: Wed May 12 11:04:27 2010 -0700
target-sparc: Inline some generation of carry for ADDX/SUBX.
Computing carry is trivial for some inputs. By avoiding an
external function call, we generate near-optimal code for
the common cases of add+addx (double-word arithmetic) and
cmp+addx (a setcc pattern).
Signed-off-by: Richard Henderson <rth at twiddle.net>
Acked-by: Artyom Tarasenko <atar4qemu at gmail.com>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index 04c1306..6f103e7 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -158,6 +158,6 @@ VIS_CMPHELPER(cmpne);
#undef VIS_HELPER
#undef VIS_CMPHELPER
DEF_HELPER_0(compute_psr, void);
-DEF_HELPER_0(compute_C_icc, tl);
+DEF_HELPER_0(compute_C_icc, i32);
#include "def-helper.h"
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 6deebd3..d0bc277 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -1347,7 +1347,7 @@ void helper_compute_psr(void)
CC_OP = CC_OP_FLAGS;
}
-target_ulong helper_compute_C_icc(void)
+uint32_t helper_compute_C_icc(void)
{
uint32_t ret;
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index ea7c71b..8129b79 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -332,24 +332,132 @@ static inline void gen_op_add_cc(TCGv dst, TCGv src1, TCGv src2)
tcg_gen_mov_tl(dst, cpu_cc_dst);
}
-static inline void gen_op_addxi_cc(TCGv dst, TCGv src1, target_long src2)
+static TCGv_i32 gen_add32_carry32(void)
{
- gen_helper_compute_C_icc(cpu_tmp0);
- tcg_gen_mov_tl(cpu_cc_src, src1);
- tcg_gen_movi_tl(cpu_cc_src2, src2);
- tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_tmp0);
- tcg_gen_addi_tl(cpu_cc_dst, cpu_cc_dst, src2);
- tcg_gen_mov_tl(dst, cpu_cc_dst);
+ TCGv_i32 carry_32, cc_src1_32, cc_src2_32;
+
+ /* Carry is computed from a previous add: (dst < src) */
+#if TARGET_LONG_BITS == 64
+ cc_src1_32 = tcg_temp_new_i32();
+ cc_src2_32 = tcg_temp_new_i32();
+ tcg_gen_trunc_i64_i32(cc_src1_32, cpu_cc_dst);
+ tcg_gen_trunc_i64_i32(cc_src2_32, cpu_cc_src);
+#else
+ cc_src1_32 = cpu_cc_dst;
+ cc_src2_32 = cpu_cc_src;
+#endif
+
+ carry_32 = tcg_temp_new_i32();
+ tcg_gen_setcond_i32(TCG_COND_LTU, carry_32, cc_src1_32, cc_src2_32);
+
+#if TARGET_LONG_BITS == 64
+ tcg_temp_free_i32(cc_src1_32);
+ tcg_temp_free_i32(cc_src2_32);
+#endif
+
+ return carry_32;
}
-static inline void gen_op_addx_cc(TCGv dst, TCGv src1, TCGv src2)
+static TCGv_i32 gen_sub32_carry32(void)
{
- gen_helper_compute_C_icc(cpu_tmp0);
- tcg_gen_mov_tl(cpu_cc_src, src1);
- tcg_gen_mov_tl(cpu_cc_src2, src2);
- tcg_gen_add_tl(cpu_cc_dst, cpu_cc_src, cpu_tmp0);
- tcg_gen_add_tl(cpu_cc_dst, cpu_cc_dst, cpu_cc_src2);
- tcg_gen_mov_tl(dst, cpu_cc_dst);
+ TCGv_i32 carry_32, cc_src1_32, cc_src2_32;
+
+ /* Carry is computed from a previous borrow: (src1 < src2) */
+#if TARGET_LONG_BITS == 64
+ cc_src1_32 = tcg_temp_new_i32();
+ cc_src2_32 = tcg_temp_new_i32();
+ tcg_gen_trunc_i64_i32(cc_src1_32, cpu_cc_src);
+ tcg_gen_trunc_i64_i32(cc_src2_32, cpu_cc_src2);
+#else
+ cc_src1_32 = cpu_cc_src;
+ cc_src2_32 = cpu_cc_src2;
+#endif
+
+ carry_32 = tcg_temp_new_i32();
+ tcg_gen_setcond_i32(TCG_COND_LTU, carry_32, cc_src1_32, cc_src2_32);
+
+#if TARGET_LONG_BITS == 64
+ tcg_temp_free_i32(cc_src1_32);
+ tcg_temp_free_i32(cc_src2_32);
+#endif
+
+ return carry_32;
+}
+
+static void gen_op_addx_int(DisasContext *dc, TCGv dst, TCGv src1,
+ TCGv src2, int update_cc)
+{
+ TCGv_i32 carry_32;
+ TCGv carry;
+
+ switch (dc->cc_op) {
+ case CC_OP_DIV:
+ case CC_OP_LOGIC:
+ /* Carry is known to be zero. Fall back to plain ADD. */
+ if (update_cc) {
+ gen_op_add_cc(dst, src1, src2);
+ } else {
+ tcg_gen_add_tl(dst, src1, src2);
+ }
+ return;
+
+ case CC_OP_ADD:
+ case CC_OP_TADD:
+ case CC_OP_TADDTV:
+#if TCG_TARGET_REG_BITS == 32 && TARGET_LONG_BITS == 32
+ {
+ /* For 32-bit hosts, we can re-use the host's hardware carry
+ generation by using an ADD2 opcode. We discard the low
+ part of the output. Ideally we'd combine this operation
+ with the add that generated the carry in the first place. */
+ TCGv dst_low = tcg_temp_new();
+ tcg_gen_op6_i32(INDEX_op_add2_i32, dst_low, dst,
+ cpu_cc_src, src1, cpu_cc_src2, src2);
+ tcg_temp_free(dst_low);
+ goto add_done;
+ }
+#endif
+ carry_32 = gen_add32_carry32();
+ break;
+
+ case CC_OP_SUB:
+ case CC_OP_TSUB:
+ case CC_OP_TSUBTV:
+ carry_32 = gen_sub32_carry32();
+ break;
+
+ default:
+ /* We need external help to produce the carry. */
+ carry_32 = tcg_temp_new_i32();
+ gen_helper_compute_C_icc(carry_32);
+ break;
+ }
+
+#if TARGET_LONG_BITS == 64
+ carry = tcg_temp_new();
+ tcg_gen_extu_i32_i64(carry, carry_32);
+#else
+ carry = carry_32;
+#endif
+
+ tcg_gen_add_tl(dst, src1, src2);
+ tcg_gen_add_tl(dst, dst, carry);
+
+ tcg_temp_free_i32(carry_32);
+#if TARGET_LONG_BITS == 64
+ tcg_temp_free(carry);
+#endif
+
+#if TCG_TARGET_REG_BITS == 32 && TARGET_LONG_BITS == 32
+ add_done:
+#endif
+ if (update_cc) {
+ tcg_gen_mov_tl(cpu_cc_src, src1);
+ tcg_gen_mov_tl(cpu_cc_src2, src2);
+ tcg_gen_mov_tl(cpu_cc_dst, dst);
+ tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADDX);
+ dc->cc_op = CC_OP_ADDX;
+ }
}
static inline void gen_op_tadd_cc(TCGv dst, TCGv src1, TCGv src2)
@@ -415,24 +523,80 @@ static inline void gen_op_sub_cc(TCGv dst, TCGv src1, TCGv src2)
tcg_gen_mov_tl(dst, cpu_cc_dst);
}
-static inline void gen_op_subxi_cc(TCGv dst, TCGv src1, target_long src2)
+static void gen_op_subx_int(DisasContext *dc, TCGv dst, TCGv src1,
+ TCGv src2, int update_cc)
{
- gen_helper_compute_C_icc(cpu_tmp0);
- tcg_gen_mov_tl(cpu_cc_src, src1);
- tcg_gen_movi_tl(cpu_cc_src2, src2);
- tcg_gen_sub_tl(cpu_cc_dst, cpu_cc_src, cpu_tmp0);
- tcg_gen_subi_tl(cpu_cc_dst, cpu_cc_dst, src2);
- tcg_gen_mov_tl(dst, cpu_cc_dst);
-}
+ TCGv_i32 carry_32;
+ TCGv carry;
-static inline void gen_op_subx_cc(TCGv dst, TCGv src1, TCGv src2)
-{
- gen_helper_compute_C_icc(cpu_tmp0);
- tcg_gen_mov_tl(cpu_cc_src, src1);
- tcg_gen_mov_tl(cpu_cc_src2, src2);
- tcg_gen_sub_tl(cpu_cc_dst, cpu_cc_src, cpu_tmp0);
- tcg_gen_sub_tl(cpu_cc_dst, cpu_cc_dst, cpu_cc_src2);
- tcg_gen_mov_tl(dst, cpu_cc_dst);
+ switch (dc->cc_op) {
+ case CC_OP_DIV:
+ case CC_OP_LOGIC:
+ /* Carry is known to be zero. Fall back to plain SUB. */
+ if (update_cc) {
+ gen_op_sub_cc(dst, src1, src2);
+ } else {
+ tcg_gen_sub_tl(dst, src1, src2);
+ }
+ return;
+
+ case CC_OP_ADD:
+ case CC_OP_TADD:
+ case CC_OP_TADDTV:
+ carry_32 = gen_add32_carry32();
+ break;
+
+ case CC_OP_SUB:
+ case CC_OP_TSUB:
+ case CC_OP_TSUBTV:
+#if TCG_TARGET_REG_BITS == 32 && TARGET_LONG_BITS == 32
+ {
+ /* For 32-bit hosts, we can re-use the host's hardware carry
+ generation by using a SUB2 opcode. We discard the low
+ part of the output. Ideally we'd combine this operation
+ with the add that generated the carry in the first place. */
+ TCGv dst_low = tcg_temp_new();
+ tcg_gen_op6_i32(INDEX_op_sub2_i32, dst_low, dst,
+ cpu_cc_src, src1, cpu_cc_src2, src2);
+ tcg_temp_free(dst_low);
+ goto sub_done;
+ }
+#endif
+ carry_32 = gen_sub32_carry32();
+ break;
+
+ default:
+ /* We need external help to produce the carry. */
+ carry_32 = tcg_temp_new_i32();
+ gen_helper_compute_C_icc(carry_32);
+ break;
+ }
+
+#if TARGET_LONG_BITS == 64
+ carry = tcg_temp_new();
+ tcg_gen_extu_i32_i64(carry, carry_32);
+#else
+ carry = carry_32;
+#endif
+
+ tcg_gen_sub_tl(dst, src1, src2);
+ tcg_gen_sub_tl(dst, dst, carry);
+
+ tcg_temp_free_i32(carry_32);
+#if TARGET_LONG_BITS == 64
+ tcg_temp_free(carry);
+#endif
+
+#if TCG_TARGET_REG_BITS == 32 && TARGET_LONG_BITS == 32
+ sub_done:
+#endif
+ if (update_cc) {
+ tcg_gen_mov_tl(cpu_cc_src, src1);
+ tcg_gen_mov_tl(cpu_cc_src2, src2);
+ tcg_gen_mov_tl(cpu_cc_dst, dst);
+ tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUBX);
+ dc->cc_op = CC_OP_SUBX;
+ }
}
static inline void gen_op_tsub_cc(TCGv dst, TCGv src1, TCGv src2)
@@ -2950,28 +3114,8 @@ static void disas_sparc_insn(DisasContext * dc)
}
break;
case 0x8: /* addx, V9 addc */
- if (IS_IMM) {
- simm = GET_FIELDs(insn, 19, 31);
- if (xop & 0x10) {
- gen_op_addxi_cc(cpu_dst, cpu_src1, simm);
- tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADDX);
- dc->cc_op = CC_OP_ADDX;
- } else {
- gen_helper_compute_C_icc(cpu_tmp0);
- tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, simm);
- tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_tmp0);
- }
- } else {
- if (xop & 0x10) {
- gen_op_addx_cc(cpu_dst, cpu_src1, cpu_src2);
- tcg_gen_movi_i32(cpu_cc_op, CC_OP_ADDX);
- dc->cc_op = CC_OP_ADDX;
- } else {
- gen_helper_compute_C_icc(cpu_tmp0);
- tcg_gen_add_tl(cpu_tmp0, cpu_src2, cpu_tmp0);
- tcg_gen_add_tl(cpu_dst, cpu_src1, cpu_tmp0);
- }
- }
+ gen_op_addx_int(dc, cpu_dst, cpu_src1, cpu_src2,
+ (xop & 0x10));
break;
#ifdef TARGET_SPARC64
case 0x9: /* V9 mulx */
@@ -3002,28 +3146,8 @@ static void disas_sparc_insn(DisasContext * dc)
}
break;
case 0xc: /* subx, V9 subc */
- if (IS_IMM) {
- simm = GET_FIELDs(insn, 19, 31);
- if (xop & 0x10) {
- gen_op_subxi_cc(cpu_dst, cpu_src1, simm);
- tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUBX);
- dc->cc_op = CC_OP_SUBX;
- } else {
- gen_helper_compute_C_icc(cpu_tmp0);
- tcg_gen_addi_tl(cpu_tmp0, cpu_tmp0, simm);
- tcg_gen_sub_tl(cpu_dst, cpu_src1, cpu_tmp0);
- }
- } else {
- if (xop & 0x10) {
- gen_op_subx_cc(cpu_dst, cpu_src1, cpu_src2);
- tcg_gen_movi_i32(cpu_cc_op, CC_OP_SUBX);
- dc->cc_op = CC_OP_SUBX;
- } else {
- gen_helper_compute_C_icc(cpu_tmp0);
- tcg_gen_add_tl(cpu_tmp0, cpu_src2, cpu_tmp0);
- tcg_gen_sub_tl(cpu_dst, cpu_src1, cpu_tmp0);
- }
- }
+ gen_op_subx_int(dc, cpu_dst, cpu_src1, cpu_src2,
+ (xop & 0x10));
break;
#ifdef TARGET_SPARC64
case 0xd: /* V9 udivx */
commit da441cffde8f593404e4187c57abf392717da2bc
Author: Richard Henderson <rth at twiddle.net>
Date: Wed Apr 14 08:26:50 2010 -0700
tcg-i386: Tidy jumps.
Define OPC_JCC*, OC_JMP*, and EXT_JMPN_Ev. Use them throughout.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 11e3661..904d2e5 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -159,6 +159,10 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define P_EXT 0x100 /* 0x0f opcode prefix */
#define OPC_BSWAP (0xc8 | P_EXT)
+#define OPC_JCC_long (0x80 | P_EXT) /* ... plus condition code */
+#define OPC_JCC_short (0x70) /* ... plus condition code */
+#define OPC_JMP_long (0xe9)
+#define OPC_JMP_short (0xeb)
#define OPC_MOVB_EvGv (0x88) /* stores, more or less */
#define OPC_MOVL_EvGv (0x89) /* stores, more or less */
#define OPC_MOVL_GvEv (0x8b) /* loads, more or less */
@@ -166,6 +170,7 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define OPC_SHIFT_Ib (0xc1)
#define OPC_SHIFT_cl (0xd3)
+/* Group 1 opcode extensions for 0x80-0x83. */
#define ARITH_ADD 0
#define ARITH_OR 1
#define ARITH_ADC 2
@@ -175,12 +180,17 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define ARITH_XOR 6
#define ARITH_CMP 7
+/* Group 2 opcode extensions for 0xc0, 0xc1, 0xd0-0xd3. */
#define SHIFT_ROL 0
#define SHIFT_ROR 1
#define SHIFT_SHL 4
#define SHIFT_SHR 5
#define SHIFT_SAR 7
+/* Group 5 opcode extensions for 0xff. */
+#define EXT_JMPN_Ev 4
+
+/* Condition codes to be added to OPC_JCC_{long,short}. */
#define JCC_JMP (-1)
#define JCC_JO 0x0
#define JCC_JNO 0x1
@@ -353,9 +363,9 @@ static void tcg_out_jxx(TCGContext *s, int opc, int label_index, int small)
val1 = val - 2;
if ((int8_t)val1 == val1) {
if (opc == -1) {
- tcg_out8(s, 0xeb);
+ tcg_out8(s, OPC_JMP_short);
} else {
- tcg_out8(s, 0x70 + opc);
+ tcg_out8(s, OPC_JCC_short + opc);
}
tcg_out8(s, val1);
} else {
@@ -363,28 +373,26 @@ static void tcg_out_jxx(TCGContext *s, int opc, int label_index, int small)
tcg_abort();
}
if (opc == -1) {
- tcg_out8(s, 0xe9);
+ tcg_out8(s, OPC_JMP_long);
tcg_out32(s, val - 5);
} else {
- tcg_out8(s, 0x0f);
- tcg_out8(s, 0x80 + opc);
+ tcg_out_opc(s, OPC_JCC_long + opc);
tcg_out32(s, val - 6);
}
}
} else if (small) {
if (opc == -1) {
- tcg_out8(s, 0xeb);
+ tcg_out8(s, OPC_JMP_short);
} else {
- tcg_out8(s, 0x70 + opc);
+ tcg_out8(s, OPC_JCC_short + opc);
}
tcg_out_reloc(s, s->code_ptr, R_386_PC8, label_index, -1);
s->code_ptr += 1;
} else {
if (opc == -1) {
- tcg_out8(s, 0xe9);
+ tcg_out8(s, OPC_JMP_long);
} else {
- tcg_out8(s, 0x0f);
- tcg_out8(s, 0x80 + opc);
+ tcg_out_opc(s, OPC_JCC_long + opc);
}
tcg_out_reloc(s, s->code_ptr, R_386_PC32, label_index, -4);
s->code_ptr += 4;
@@ -627,12 +635,12 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
#if TARGET_LONG_BITS == 32
/* je label1 */
- tcg_out8(s, 0x70 + JCC_JE);
+ tcg_out8(s, OPC_JCC_short + JCC_JE);
label1_ptr = s->code_ptr;
s->code_ptr++;
#else
/* jne label3 */
- tcg_out8(s, 0x70 + JCC_JNE);
+ tcg_out8(s, OPC_JCC_short + JCC_JNE);
label3_ptr = s->code_ptr;
s->code_ptr++;
@@ -640,7 +648,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
tcg_out_modrm_offset(s, 0x3b, addr_reg2, r1, 4);
/* je label1 */
- tcg_out8(s, 0x70 + JCC_JE);
+ tcg_out8(s, OPC_JCC_short + JCC_JE);
label1_ptr = s->code_ptr;
s->code_ptr++;
@@ -692,7 +700,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
}
/* jmp label2 */
- tcg_out8(s, 0xeb);
+ tcg_out8(s, OPC_JMP_short);
label2_ptr = s->code_ptr;
s->code_ptr++;
@@ -827,12 +835,12 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
#if TARGET_LONG_BITS == 32
/* je label1 */
- tcg_out8(s, 0x70 + JCC_JE);
+ tcg_out8(s, OPC_JCC_short + JCC_JE);
label1_ptr = s->code_ptr;
s->code_ptr++;
#else
/* jne label3 */
- tcg_out8(s, 0x70 + JCC_JNE);
+ tcg_out8(s, OPC_JCC_short + JCC_JNE);
label3_ptr = s->code_ptr;
s->code_ptr++;
@@ -840,7 +848,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
tcg_out_modrm_offset(s, 0x3b, addr_reg2, r1, 4);
/* je label1 */
- tcg_out8(s, 0x70 + JCC_JE);
+ tcg_out8(s, OPC_JCC_short + JCC_JE);
label1_ptr = s->code_ptr;
s->code_ptr++;
@@ -914,7 +922,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
#endif
/* jmp label2 */
- tcg_out8(s, 0xeb);
+ tcg_out8(s, OPC_JMP_short);
label2_ptr = s->code_ptr;
s->code_ptr++;
@@ -986,19 +994,18 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
switch(opc) {
case INDEX_op_exit_tb:
tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_EAX, args[0]);
- tcg_out8(s, 0xe9); /* jmp tb_ret_addr */
+ tcg_out8(s, OPC_JMP_long); /* jmp tb_ret_addr */
tcg_out32(s, tb_ret_addr - s->code_ptr - 4);
break;
case INDEX_op_goto_tb:
if (s->tb_jmp_offset) {
/* direct jump method */
- tcg_out8(s, 0xe9); /* jmp im */
+ tcg_out8(s, OPC_JMP_long); /* jmp im */
s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
tcg_out32(s, 0);
} else {
/* indirect jump method */
- /* jmp Ev */
- tcg_out_modrm_offset(s, 0xff, 4, -1,
+ tcg_out_modrm_offset(s, 0xff, EXT_JMPN_Ev, -1,
(tcg_target_long)(s->tb_next + args[0]));
}
s->tb_next_offset[args[0]] = s->code_ptr - s->code_buf;
@@ -1013,10 +1020,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
break;
case INDEX_op_jmp:
if (const_args[0]) {
- tcg_out8(s, 0xe9);
+ tcg_out8(s, OPC_JMP_long);
tcg_out32(s, args[0] - (tcg_target_long)s->code_ptr - 4);
} else {
- tcg_out_modrm(s, 0xff, 4, args[0]);
+ /* jmp *reg */
+ tcg_out_modrm(s, 0xff, EXT_JMPN_Ev, args[0]);
}
break;
case INDEX_op_br:
@@ -1341,7 +1349,7 @@ void tcg_target_qemu_prologue(TCGContext *s)
stack_addend = frame_size - push_size;
tcg_out_addi(s, TCG_REG_ESP, -stack_addend);
- tcg_out_modrm(s, 0xff, 4, TCG_REG_EAX); /* jmp *%eax */
+ tcg_out_modrm(s, 0xff, EXT_JMPN_Ev, TCG_REG_EAX); /* jmp *%eax */
/* TB epilogue */
tb_ret_addr = s->code_ptr;
commit a042ef9470e1111bd5f5f84def886040345baabc
Author: Richard Henderson <rth at twiddle.net>
Date: Wed Apr 14 08:06:00 2010 -0700
tcg-i386: Eliminate extra move from qemu_ld64.
If the address register overlaps one of the output registers
simply issue the clobbering load last, rather than emitting
an extra move of the address register.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 4b88138..11e3661 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -744,22 +744,20 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
}
break;
case 3:
- /* XXX: could be nicer */
- if (r0 == data_reg) {
- r1 = TCG_REG_EDX;
- if (r1 == data_reg)
- r1 = TCG_REG_EAX;
- tcg_out_mov(s, r1, r0);
- r0 = r1;
+ if (bswap) {
+ int t = data_reg;
+ data_reg = data_reg2;
+ data_reg2 = t;
}
- if (!bswap) {
+ if (r0 != data_reg) {
tcg_out_ld(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
tcg_out_ld(s, TCG_TYPE_I32, data_reg2, r0, GUEST_BASE + 4);
} else {
- tcg_out_ld(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE + 4);
+ tcg_out_ld(s, TCG_TYPE_I32, data_reg2, r0, GUEST_BASE + 4);
+ tcg_out_ld(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
+ }
+ if (bswap) {
tcg_out_bswap32(s, data_reg);
-
- tcg_out_ld(s, TCG_TYPE_I32, data_reg2, r0, GUEST_BASE);
tcg_out_bswap32(s, data_reg2);
}
break;
commit af2660894f1d71cd8c9edeb19230f0336e320bcd
Author: Richard Henderson <rth at twiddle.net>
Date: Wed Apr 14 07:58:59 2010 -0700
tcg-i386: Tidy move operations.
Define OPC_MOVB* and OPC_MOVL*; use them throughout.
Use tcg_out_ld/st instead of bare tcg_out_modrm_offset
when it makes sense.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 8987f32..4b88138 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -159,6 +159,9 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define P_EXT 0x100 /* 0x0f opcode prefix */
#define OPC_BSWAP (0xc8 | P_EXT)
+#define OPC_MOVB_EvGv (0x88) /* stores, more or less */
+#define OPC_MOVL_EvGv (0x89) /* stores, more or less */
+#define OPC_MOVL_GvEv (0x8b) /* loads, more or less */
#define OPC_SHIFT_1 (0xd1)
#define OPC_SHIFT_Ib (0xc1)
#define OPC_SHIFT_cl (0xd3)
@@ -260,8 +263,9 @@ static inline void tcg_out_modrm_offset(TCGContext *s, int opc, int r, int rm,
static inline void tcg_out_mov(TCGContext *s, int ret, int arg)
{
- if (arg != ret)
- tcg_out_modrm(s, 0x8b, ret, arg);
+ if (arg != ret) {
+ tcg_out_modrm(s, OPC_MOVL_GvEv, ret, arg);
+ }
}
static inline void tcg_out_movi(TCGContext *s, TCGType type,
@@ -279,15 +283,13 @@ static inline void tcg_out_movi(TCGContext *s, TCGType type,
static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
int arg1, tcg_target_long arg2)
{
- /* movl */
- tcg_out_modrm_offset(s, 0x8b, ret, arg1, arg2);
+ tcg_out_modrm_offset(s, OPC_MOVL_GvEv, ret, arg1, arg2);
}
static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
int arg1, tcg_target_long arg2)
{
- /* movl */
- tcg_out_modrm_offset(s, 0x89, arg, arg1, arg2);
+ tcg_out_modrm_offset(s, OPC_MOVL_EvGv, arg, arg1, arg2);
}
static void tcg_out_shifti(TCGContext *s, int subopc, int reg, int count)
@@ -736,8 +738,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
}
break;
case 2:
- /* movl (r0), data_reg */
- tcg_out_modrm_offset(s, 0x8b, data_reg, r0, GUEST_BASE);
+ tcg_out_ld(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
if (bswap) {
tcg_out_bswap32(s, data_reg);
}
@@ -752,13 +753,13 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
r0 = r1;
}
if (!bswap) {
- tcg_out_modrm_offset(s, 0x8b, data_reg, r0, GUEST_BASE);
- tcg_out_modrm_offset(s, 0x8b, data_reg2, r0, GUEST_BASE + 4);
+ tcg_out_ld(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
+ tcg_out_ld(s, TCG_TYPE_I32, data_reg2, r0, GUEST_BASE + 4);
} else {
- tcg_out_modrm_offset(s, 0x8b, data_reg, r0, GUEST_BASE + 4);
+ tcg_out_ld(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE + 4);
tcg_out_bswap32(s, data_reg);
- tcg_out_modrm_offset(s, 0x8b, data_reg2, r0, GUEST_BASE);
+ tcg_out_ld(s, TCG_TYPE_I32, data_reg2, r0, GUEST_BASE);
tcg_out_bswap32(s, data_reg2);
}
break;
@@ -936,8 +937,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
#endif
switch(opc) {
case 0:
- /* movb */
- tcg_out_modrm_offset(s, 0x88, data_reg, r0, GUEST_BASE);
+ tcg_out_modrm_offset(s, OPC_MOVB_EvGv, data_reg, r0, GUEST_BASE);
break;
case 1:
if (bswap) {
@@ -947,7 +947,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
}
/* movw */
tcg_out8(s, 0x66);
- tcg_out_modrm_offset(s, 0x89, data_reg, r0, GUEST_BASE);
+ tcg_out_modrm_offset(s, OPC_MOVL_EvGv, data_reg, r0, GUEST_BASE);
break;
case 2:
if (bswap) {
@@ -955,20 +955,19 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
tcg_out_bswap32(s, r1);
data_reg = r1;
}
- /* movl */
- tcg_out_modrm_offset(s, 0x89, data_reg, r0, GUEST_BASE);
+ tcg_out_st(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
break;
case 3:
if (bswap) {
tcg_out_mov(s, r1, data_reg2);
tcg_out_bswap32(s, r1);
- tcg_out_modrm_offset(s, 0x89, r1, r0, GUEST_BASE);
+ tcg_out_st(s, TCG_TYPE_I32, r1, r0, GUEST_BASE);
tcg_out_mov(s, r1, data_reg);
tcg_out_bswap32(s, r1);
- tcg_out_modrm_offset(s, 0x89, r1, r0, GUEST_BASE + 4);
+ tcg_out_st(s, TCG_TYPE_I32, r1, r0, GUEST_BASE + 4);
} else {
- tcg_out_modrm_offset(s, 0x89, data_reg, r0, GUEST_BASE);
- tcg_out_modrm_offset(s, 0x89, data_reg2, r0, GUEST_BASE + 4);
+ tcg_out_st(s, TCG_TYPE_I32, data_reg, r0, GUEST_BASE);
+ tcg_out_st(s, TCG_TYPE_I32, data_reg2, r0, GUEST_BASE + 4);
}
break;
default:
@@ -1045,21 +1044,19 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
tcg_out_modrm_offset(s, 0xbf | P_EXT, args[0], args[1], args[2]);
break;
case INDEX_op_ld_i32:
- /* movl */
- tcg_out_modrm_offset(s, 0x8b, args[0], args[1], args[2]);
+ tcg_out_ld(s, TCG_TYPE_I32, args[0], args[1], args[2]);
break;
case INDEX_op_st8_i32:
/* movb */
- tcg_out_modrm_offset(s, 0x88, args[0], args[1], args[2]);
+ tcg_out_modrm_offset(s, OPC_MOVB_EvGv, args[0], args[1], args[2]);
break;
case INDEX_op_st16_i32:
/* movw */
tcg_out8(s, 0x66);
- tcg_out_modrm_offset(s, 0x89, args[0], args[1], args[2]);
+ tcg_out_modrm_offset(s, OPC_MOVL_EvGv, args[0], args[1], args[2]);
break;
case INDEX_op_st_i32:
- /* movl */
- tcg_out_modrm_offset(s, 0x89, args[0], args[1], args[2]);
+ tcg_out_st(s, TCG_TYPE_I32, args[0], args[1], args[2]);
break;
case INDEX_op_sub_i32:
c = ARITH_SUB;
commit f53dba010162a5ae57776084013e2d3ae32b0889
Author: Richard Henderson <rth at twiddle.net>
Date: Wed Apr 28 10:38:04 2010 -0700
tcg-i386: Tidy shift operations.
Define OPC_SHIFT_{1,Ib,cl}. Factor opcode emission to a function.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 1ce42b9..8987f32 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -159,6 +159,9 @@ static inline int tcg_target_const_match(tcg_target_long val,
#define P_EXT 0x100 /* 0x0f opcode prefix */
#define OPC_BSWAP (0xc8 | P_EXT)
+#define OPC_SHIFT_1 (0xd1)
+#define OPC_SHIFT_Ib (0xc1)
+#define OPC_SHIFT_cl (0xd3)
#define ARITH_ADD 0
#define ARITH_OR 1
@@ -287,6 +290,16 @@ static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
tcg_out_modrm_offset(s, 0x89, arg, arg1, arg2);
}
+static void tcg_out_shifti(TCGContext *s, int subopc, int reg, int count)
+{
+ if (count == 1) {
+ tcg_out_modrm(s, OPC_SHIFT_1, subopc, reg);
+ } else {
+ tcg_out_modrm(s, OPC_SHIFT_Ib, subopc, reg);
+ tcg_out8(s, count);
+ }
+}
+
static inline void tcg_out_bswap32(TCGContext *s, int reg)
{
tcg_out_opc(s, OPC_BSWAP + reg);
@@ -295,8 +308,7 @@ static inline void tcg_out_bswap32(TCGContext *s, int reg)
static inline void tcg_out_rolw_8(TCGContext *s, int reg)
{
tcg_out8(s, 0x66);
- tcg_out_modrm(s, 0xc1, 0, reg);
- tcg_out8(s, 8);
+ tcg_out_shifti(s, SHIFT_ROL, reg, 8);
}
static inline void tgen_arithi(TCGContext *s, int c, int r0, int32_t val, int cf)
@@ -593,9 +605,8 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
tcg_out_mov(s, r0, addr_reg);
- tcg_out_modrm(s, 0xc1, 5, r1); /* shr $x, r1 */
- tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
-
+ tcg_out_shifti(s, SHIFT_SHR, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
+
tcg_out_modrm(s, 0x81, 4, r0); /* andl $x, r0 */
tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
@@ -797,9 +808,8 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
tcg_out_mov(s, r0, addr_reg);
- tcg_out_modrm(s, 0xc1, 5, r1); /* shr $x, r1 */
- tcg_out8(s, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
-
+ tcg_out_shifti(s, SHIFT_SHR, r1, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
+
tcg_out_modrm(s, 0x81, 4, r0); /* andl $x, r0 */
tcg_out32(s, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
@@ -1100,14 +1110,9 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
c = SHIFT_SHL;
gen_shift32:
if (const_args[2]) {
- if (args[2] == 1) {
- tcg_out_modrm(s, 0xd1, c, args[0]);
- } else {
- tcg_out_modrm(s, 0xc1, c, args[0]);
- tcg_out8(s, args[2]);
- }
+ tcg_out_shifti(s, c, args[0], args[2]);
} else {
- tcg_out_modrm(s, 0xd3, c, args[0]);
+ tcg_out_modrm(s, OPC_SHIFT_cl, c, args[0]);
}
break;
case INDEX_op_shr_i32:
commit fcb5dac1f79d48788d61a25630b713e1c31061cd
Author: Richard Henderson <rth at twiddle.net>
Date: Wed Apr 28 10:31:18 2010 -0700
tcg-i386: Tidy bswap operations.
Define OPC_BSWAP. Factor opcode emission to separate functions.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 4e33b25..1ce42b9 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -156,6 +156,10 @@ static inline int tcg_target_const_match(tcg_target_long val,
return 0;
}
+#define P_EXT 0x100 /* 0x0f opcode prefix */
+
+#define OPC_BSWAP (0xc8 | P_EXT)
+
#define ARITH_ADD 0
#define ARITH_OR 1
#define ARITH_ADC 2
@@ -283,6 +287,18 @@ static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
tcg_out_modrm_offset(s, 0x89, arg, arg1, arg2);
}
+static inline void tcg_out_bswap32(TCGContext *s, int reg)
+{
+ tcg_out_opc(s, OPC_BSWAP + reg);
+}
+
+static inline void tcg_out_rolw_8(TCGContext *s, int reg)
+{
+ tcg_out8(s, 0x66);
+ tcg_out_modrm(s, 0xc1, 0, reg);
+ tcg_out8(s, 8);
+}
+
static inline void tgen_arithi(TCGContext *s, int c, int r0, int32_t val, int cf)
{
if (!cf && ((c == ARITH_ADD && val == 1) || (c == ARITH_SUB && val == -1))) {
@@ -695,20 +711,14 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
/* movzwl */
tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, GUEST_BASE);
if (bswap) {
- /* rolw $8, data_reg */
- tcg_out8(s, 0x66);
- tcg_out_modrm(s, 0xc1, 0, data_reg);
- tcg_out8(s, 8);
+ tcg_out_rolw_8(s, data_reg);
}
break;
case 1 | 4:
/* movswl */
tcg_out_modrm_offset(s, 0xbf | P_EXT, data_reg, r0, GUEST_BASE);
if (bswap) {
- /* rolw $8, data_reg */
- tcg_out8(s, 0x66);
- tcg_out_modrm(s, 0xc1, 0, data_reg);
- tcg_out8(s, 8);
+ tcg_out_rolw_8(s, data_reg);
/* movswl data_reg, data_reg */
tcg_out_modrm(s, 0xbf | P_EXT, data_reg, data_reg);
@@ -718,8 +728,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
/* movl (r0), data_reg */
tcg_out_modrm_offset(s, 0x8b, data_reg, r0, GUEST_BASE);
if (bswap) {
- /* bswap */
- tcg_out_opc(s, (0xc8 + data_reg) | P_EXT);
+ tcg_out_bswap32(s, data_reg);
}
break;
case 3:
@@ -736,11 +745,10 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
tcg_out_modrm_offset(s, 0x8b, data_reg2, r0, GUEST_BASE + 4);
} else {
tcg_out_modrm_offset(s, 0x8b, data_reg, r0, GUEST_BASE + 4);
- tcg_out_opc(s, (0xc8 + data_reg) | P_EXT);
+ tcg_out_bswap32(s, data_reg);
tcg_out_modrm_offset(s, 0x8b, data_reg2, r0, GUEST_BASE);
- /* bswap */
- tcg_out_opc(s, (0xc8 + data_reg2) | P_EXT);
+ tcg_out_bswap32(s, data_reg2);
}
break;
default:
@@ -924,9 +932,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
case 1:
if (bswap) {
tcg_out_mov(s, r1, data_reg);
- tcg_out8(s, 0x66); /* rolw $8, %ecx */
- tcg_out_modrm(s, 0xc1, 0, r1);
- tcg_out8(s, 8);
+ tcg_out_rolw_8(s, r1);
data_reg = r1;
}
/* movw */
@@ -936,8 +942,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
case 2:
if (bswap) {
tcg_out_mov(s, r1, data_reg);
- /* bswap data_reg */
- tcg_out_opc(s, (0xc8 + r1) | P_EXT);
+ tcg_out_bswap32(s, r1);
data_reg = r1;
}
/* movl */
@@ -946,12 +951,10 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
case 3:
if (bswap) {
tcg_out_mov(s, r1, data_reg2);
- /* bswap data_reg */
- tcg_out_opc(s, (0xc8 + r1) | P_EXT);
+ tcg_out_bswap32(s, r1);
tcg_out_modrm_offset(s, 0x89, r1, r0, GUEST_BASE);
tcg_out_mov(s, r1, data_reg);
- /* bswap data_reg */
- tcg_out_opc(s, (0xc8 + r1) | P_EXT);
+ tcg_out_bswap32(s, r1);
tcg_out_modrm_offset(s, 0x89, r1, r0, GUEST_BASE + 4);
} else {
tcg_out_modrm_offset(s, 0x89, data_reg, r0, GUEST_BASE);
@@ -1149,12 +1152,10 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
break;
case INDEX_op_bswap16_i32:
- tcg_out8(s, 0x66);
- tcg_out_modrm(s, 0xc1, SHIFT_ROL, args[0]);
- tcg_out8(s, 8);
+ tcg_out_rolw_8(s, args[0]);
break;
case INDEX_op_bswap32_i32:
- tcg_out_opc(s, (0xc8 + args[0]) | P_EXT);
+ tcg_out_bswap32(s, args[0]);
break;
case INDEX_op_neg_i32:
commit 702a8a99c31bdec24739d1d4f9492b496d04817d
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Thu May 20 21:00:23 2010 +0200
Remove i386 from .gitignore
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/.gitignore b/.gitignore
index dfc8e5b..fdfe2f0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,7 +2,6 @@ config-devices.*
config-all-devices.*
config-host.*
config-target.*
-i386
*-softmmu
*-darwin-user
*-linux-user
commit 5a4bb580cdb10b066f9fd67658b31cac4a4ea5e5
Author: Richard Henderson <rth at twiddle.net>
Date: Wed May 12 11:04:26 2010 -0700
target-sparc: Simplify ICC generation.
Use int32 types instead of target_ulong when computing ICC. This
simplifies the generated code for 32-bit host and 64-bit guest.
Use the same simplified expressions for ICC as were already used
for XCC in carry flag generation.
Simplify the ADD carry generation to not consider a possible carry-in.
Use the more complex carry computation for ADDX only. Use the same
carry algorithm for the XCC result of ADDX. Similarly for SUB/SUBX.
Use the ADD carry generation functions for TADD/TADDTV. Similarly
for SUB and TSUB/TSUBTV.
Tidy the code with respect to CODING_STYLE.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index 26e836b..6deebd3 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -901,14 +901,15 @@ static uint32_t compute_C_flags(void)
return env->psr & PSR_CARRY;
}
-static inline uint32_t get_NZ_icc(target_ulong dst)
+static inline uint32_t get_NZ_icc(int32_t dst)
{
uint32_t ret = 0;
- if (!(dst & 0xffffffffULL))
- ret |= PSR_ZERO;
- if ((int32_t) (dst & 0xffffffffULL) < 0)
- ret |= PSR_NEG;
+ if (dst == 0) {
+ ret = PSR_ZERO;
+ } else if (dst < 0) {
+ ret = PSR_NEG;
+ }
return ret;
}
@@ -923,14 +924,15 @@ static uint32_t compute_C_flags_xcc(void)
return env->xcc & PSR_CARRY;
}
-static inline uint32_t get_NZ_xcc(target_ulong dst)
+static inline uint32_t get_NZ_xcc(target_long dst)
{
uint32_t ret = 0;
- if (!dst)
- ret |= PSR_ZERO;
- if ((int64_t)dst < 0)
- ret |= PSR_NEG;
+ if (!dst) {
+ ret = PSR_ZERO;
+ } else if (dst < 0) {
+ ret = PSR_NEG;
+ }
return ret;
}
#endif
@@ -939,8 +941,9 @@ static inline uint32_t get_V_div_icc(target_ulong src2)
{
uint32_t ret = 0;
- if (src2 != 0)
- ret |= PSR_OVF;
+ if (src2 != 0) {
+ ret = PSR_OVF;
+ }
return ret;
}
@@ -958,26 +961,35 @@ static uint32_t compute_C_div(void)
return 0;
}
-/* carry = (src1[31] & src2[31]) | ( ~dst[31] & (src1[31] | src2[31])) */
-static inline uint32_t get_C_add_icc(target_ulong dst, target_ulong src1,
- target_ulong src2)
+static inline uint32_t get_C_add_icc(uint32_t dst, uint32_t src1)
{
uint32_t ret = 0;
- if (((src1 & (1ULL << 31)) & (src2 & (1ULL << 31)))
- | ((~(dst & (1ULL << 31)))
- & ((src1 & (1ULL << 31)) | (src2 & (1ULL << 31)))))
- ret |= PSR_CARRY;
+ if (dst < src1) {
+ ret = PSR_CARRY;
+ }
return ret;
}
-static inline uint32_t get_V_add_icc(target_ulong dst, target_ulong src1,
- target_ulong src2)
+static inline uint32_t get_C_addx_icc(uint32_t dst, uint32_t src1,
+ uint32_t src2)
{
uint32_t ret = 0;
- if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 31))
- ret |= PSR_OVF;
+ if (((src1 & src2) | (~dst & (src1 | src2))) & (1U << 31)) {
+ ret = PSR_CARRY;
+ }
+ return ret;
+}
+
+static inline uint32_t get_V_add_icc(uint32_t dst, uint32_t src1,
+ uint32_t src2)
+{
+ uint32_t ret = 0;
+
+ if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1U << 31)) {
+ ret = PSR_OVF;
+ }
return ret;
}
@@ -986,8 +998,20 @@ static inline uint32_t get_C_add_xcc(target_ulong dst, target_ulong src1)
{
uint32_t ret = 0;
- if (dst < src1)
- ret |= PSR_CARRY;
+ if (dst < src1) {
+ ret = PSR_CARRY;
+ }
+ return ret;
+}
+
+static inline uint32_t get_C_addx_xcc(target_ulong dst, target_ulong src1,
+ target_ulong src2)
+{
+ uint32_t ret = 0;
+
+ if (((src1 & src2) | (~dst & (src1 | src2))) & (1ULL << 63)) {
+ ret = PSR_CARRY;
+ }
return ret;
}
@@ -996,8 +1020,9 @@ static inline uint32_t get_V_add_xcc(target_ulong dst, target_ulong src1,
{
uint32_t ret = 0;
- if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 63))
- ret |= PSR_OVF;
+ if (((src1 ^ src2 ^ -1) & (src1 ^ dst)) & (1ULL << 63)) {
+ ret = PSR_OVF;
+ }
return ret;
}
@@ -1022,14 +1047,14 @@ static uint32_t compute_all_add(void)
uint32_t ret;
ret = get_NZ_icc(CC_DST);
- ret |= get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
+ ret |= get_C_add_icc(CC_DST, CC_SRC);
ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
return ret;
}
static uint32_t compute_C_add(void)
{
- return get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
+ return get_C_add_icc(CC_DST, CC_SRC);
}
#ifdef TARGET_SPARC64
@@ -1038,8 +1063,7 @@ static uint32_t compute_all_addx_xcc(void)
uint32_t ret;
ret = get_NZ_xcc(CC_DST);
- ret |= get_C_add_xcc(CC_DST - CC_SRC2, CC_SRC);
- ret |= get_C_add_xcc(CC_DST, CC_SRC);
+ ret |= get_C_addx_xcc(CC_DST, CC_SRC, CC_SRC2);
ret |= get_V_add_xcc(CC_DST, CC_SRC, CC_SRC2);
return ret;
}
@@ -1048,18 +1072,36 @@ static uint32_t compute_C_addx_xcc(void)
{
uint32_t ret;
- ret = get_C_add_xcc(CC_DST - CC_SRC2, CC_SRC);
- ret |= get_C_add_xcc(CC_DST, CC_SRC);
+ ret = get_C_addx_xcc(CC_DST, CC_SRC, CC_SRC2);
return ret;
}
#endif
+static uint32_t compute_all_addx(void)
+{
+ uint32_t ret;
+
+ ret = get_NZ_icc(CC_DST);
+ ret |= get_C_addx_icc(CC_DST, CC_SRC, CC_SRC2);
+ ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
+ return ret;
+}
+
+static uint32_t compute_C_addx(void)
+{
+ uint32_t ret;
+
+ ret = get_C_addx_icc(CC_DST, CC_SRC, CC_SRC2);
+ return ret;
+}
+
static inline uint32_t get_V_tag_icc(target_ulong src1, target_ulong src2)
{
uint32_t ret = 0;
- if ((src1 | src2) & 0x3)
- ret |= PSR_OVF;
+ if ((src1 | src2) & 0x3) {
+ ret = PSR_OVF;
+ }
return ret;
}
@@ -1068,51 +1110,50 @@ static uint32_t compute_all_tadd(void)
uint32_t ret;
ret = get_NZ_icc(CC_DST);
- ret |= get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
+ ret |= get_C_add_icc(CC_DST, CC_SRC);
ret |= get_V_add_icc(CC_DST, CC_SRC, CC_SRC2);
ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
return ret;
}
-static uint32_t compute_C_tadd(void)
-{
- return get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
-}
-
static uint32_t compute_all_taddtv(void)
{
uint32_t ret;
ret = get_NZ_icc(CC_DST);
- ret |= get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
+ ret |= get_C_add_icc(CC_DST, CC_SRC);
return ret;
}
-static uint32_t compute_C_taddtv(void)
+static inline uint32_t get_C_sub_icc(uint32_t src1, uint32_t src2)
{
- return get_C_add_icc(CC_DST, CC_SRC, CC_SRC2);
+ uint32_t ret = 0;
+
+ if (src1 < src2) {
+ ret = PSR_CARRY;
+ }
+ return ret;
}
-/* carry = (~src1[31] & src2[31]) | ( dst[31] & (~src1[31] | src2[31])) */
-static inline uint32_t get_C_sub_icc(target_ulong dst, target_ulong src1,
- target_ulong src2)
+static inline uint32_t get_C_subx_icc(uint32_t dst, uint32_t src1,
+ uint32_t src2)
{
uint32_t ret = 0;
- if (((~(src1 & (1ULL << 31))) & (src2 & (1ULL << 31)))
- | ((dst & (1ULL << 31)) & (( ~(src1 & (1ULL << 31)))
- | (src2 & (1ULL << 31)))))
- ret |= PSR_CARRY;
+ if (((~src1 & src2) | (dst & (~src1 | src2))) & (1U << 31)) {
+ ret = PSR_CARRY;
+ }
return ret;
}
-static inline uint32_t get_V_sub_icc(target_ulong dst, target_ulong src1,
- target_ulong src2)
+static inline uint32_t get_V_sub_icc(uint32_t dst, uint32_t src1,
+ uint32_t src2)
{
uint32_t ret = 0;
- if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 31))
- ret |= PSR_OVF;
+ if (((src1 ^ src2) & (src1 ^ dst)) & (1U << 31)) {
+ ret = PSR_OVF;
+ }
return ret;
}
@@ -1122,8 +1163,20 @@ static inline uint32_t get_C_sub_xcc(target_ulong src1, target_ulong src2)
{
uint32_t ret = 0;
- if (src1 < src2)
- ret |= PSR_CARRY;
+ if (src1 < src2) {
+ ret = PSR_CARRY;
+ }
+ return ret;
+}
+
+static inline uint32_t get_C_subx_xcc(target_ulong dst, target_ulong src1,
+ target_ulong src2)
+{
+ uint32_t ret = 0;
+
+ if (((~src1 & src2) | (dst & (~src1 | src2))) & (1ULL << 63)) {
+ ret = PSR_CARRY;
+ }
return ret;
}
@@ -1132,8 +1185,9 @@ static inline uint32_t get_V_sub_xcc(target_ulong dst, target_ulong src1,
{
uint32_t ret = 0;
- if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 63))
- ret |= PSR_OVF;
+ if (((src1 ^ src2) & (src1 ^ dst)) & (1ULL << 63)) {
+ ret = PSR_OVF;
+ }
return ret;
}
@@ -1158,14 +1212,14 @@ static uint32_t compute_all_sub(void)
uint32_t ret;
ret = get_NZ_icc(CC_DST);
- ret |= get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
+ ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
return ret;
}
static uint32_t compute_C_sub(void)
{
- return get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
+ return get_C_sub_icc(CC_SRC, CC_SRC2);
}
#ifdef TARGET_SPARC64
@@ -1174,8 +1228,7 @@ static uint32_t compute_all_subx_xcc(void)
uint32_t ret;
ret = get_NZ_xcc(CC_DST);
- ret |= get_C_sub_xcc(CC_DST - CC_SRC2, CC_SRC);
- ret |= get_C_sub_xcc(CC_DST, CC_SRC2);
+ ret |= get_C_subx_xcc(CC_DST, CC_SRC, CC_SRC2);
ret |= get_V_sub_xcc(CC_DST, CC_SRC, CC_SRC2);
return ret;
}
@@ -1184,40 +1237,47 @@ static uint32_t compute_C_subx_xcc(void)
{
uint32_t ret;
- ret = get_C_sub_xcc(CC_DST - CC_SRC2, CC_SRC);
- ret |= get_C_sub_xcc(CC_DST, CC_SRC2);
+ ret = get_C_subx_xcc(CC_DST, CC_SRC, CC_SRC2);
return ret;
}
#endif
-static uint32_t compute_all_tsub(void)
+static uint32_t compute_all_subx(void)
{
uint32_t ret;
ret = get_NZ_icc(CC_DST);
- ret |= get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
+ ret |= get_C_subx_icc(CC_DST, CC_SRC, CC_SRC2);
ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
- ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
return ret;
}
-static uint32_t compute_C_tsub(void)
+static uint32_t compute_C_subx(void)
{
- return get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
+ uint32_t ret;
+
+ ret = get_C_subx_icc(CC_DST, CC_SRC, CC_SRC2);
+ return ret;
}
-static uint32_t compute_all_tsubtv(void)
+static uint32_t compute_all_tsub(void)
{
uint32_t ret;
ret = get_NZ_icc(CC_DST);
- ret |= get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
+ ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
+ ret |= get_V_sub_icc(CC_DST, CC_SRC, CC_SRC2);
+ ret |= get_V_tag_icc(CC_SRC, CC_SRC2);
return ret;
}
-static uint32_t compute_C_tsubtv(void)
+static uint32_t compute_all_tsubtv(void)
{
- return get_C_sub_icc(CC_DST, CC_SRC, CC_SRC2);
+ uint32_t ret;
+
+ ret = get_NZ_icc(CC_DST);
+ ret |= get_C_sub_icc(CC_SRC, CC_SRC2);
+ return ret;
}
static uint32_t compute_all_logic(void)
@@ -1247,13 +1307,13 @@ static const CCTable icc_table[CC_OP_NB] = {
[CC_OP_FLAGS] = { compute_all_flags, compute_C_flags },
[CC_OP_DIV] = { compute_all_div, compute_C_div },
[CC_OP_ADD] = { compute_all_add, compute_C_add },
- [CC_OP_ADDX] = { compute_all_add, compute_C_add },
- [CC_OP_TADD] = { compute_all_tadd, compute_C_tadd },
- [CC_OP_TADDTV] = { compute_all_taddtv, compute_C_taddtv },
+ [CC_OP_ADDX] = { compute_all_addx, compute_C_addx },
+ [CC_OP_TADD] = { compute_all_tadd, compute_C_add },
+ [CC_OP_TADDTV] = { compute_all_taddtv, compute_C_add },
[CC_OP_SUB] = { compute_all_sub, compute_C_sub },
- [CC_OP_SUBX] = { compute_all_sub, compute_C_sub },
- [CC_OP_TSUB] = { compute_all_tsub, compute_C_tsub },
- [CC_OP_TSUBTV] = { compute_all_tsubtv, compute_C_tsubtv },
+ [CC_OP_SUBX] = { compute_all_subx, compute_C_subx },
+ [CC_OP_TSUB] = { compute_all_tsub, compute_C_sub },
+ [CC_OP_TSUBTV] = { compute_all_tsubtv, compute_C_sub },
[CC_OP_LOGIC] = { compute_all_logic, compute_C_logic },
};
commit 4c1a0d8244116e4658b24858808c25c11bdf506a
Author: Richard Henderson <rth at twiddle.net>
Date: Wed May 12 11:04:25 2010 -0700
target-sparc: Fix compilation with --enable-debug.
Return a target_ulong from compute_C_icc to match the width of the users.
Signed-off-by: Richard Henderson <rth at twiddle.net>
Signed-off-by: Blue Swirl <blauwirbel at gmail.com>
diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index 6f103e7..04c1306 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -158,6 +158,6 @@ VIS_CMPHELPER(cmpne);
#undef VIS_HELPER
#undef VIS_CMPHELPER
DEF_HELPER_0(compute_psr, void);
-DEF_HELPER_0(compute_C_icc, i32);
+DEF_HELPER_0(compute_C_icc, tl);
#include "def-helper.h"
diff --git a/target-sparc/op_helper.c b/target-sparc/op_helper.c
index b1451d3..26e836b 100644
--- a/target-sparc/op_helper.c
+++ b/target-sparc/op_helper.c
@@ -1287,7 +1287,7 @@ void helper_compute_psr(void)
CC_OP = CC_OP_FLAGS;
}
-uint32_t helper_compute_C_icc(void)
+target_ulong helper_compute_C_icc(void)
{
uint32_t ret;
commit 02021c3f3e723d17ac5767d33d58917552650ec9
Author: Riccardo Magliocchetti <riccardo.magliocchetti at gmail.com>
Date: Wed May 19 18:49:29 2010 +0200
Fix __VA__ARGS__ typo in cris mmu.c
Fix compilation with DEBUG defined
Signed-off-by: Riccardo Magliocchetti <riccardo.magliocchetti at gmail.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
diff --git a/target-cris/mmu.c b/target-cris/mmu.c
index 2a5ded8..d09e921 100644
--- a/target-cris/mmu.c
+++ b/target-cris/mmu.c
@@ -31,7 +31,7 @@
#ifdef DEBUG
#define D(x) x
-#define D_LOG(...) qemu_log(__VA__ARGS__)
+#define D_LOG(...) qemu_log(__VA_ARGS__)
#else
#define D(x)
#define D_LOG(...) do { } while (0)
commit e476492e78d5872980f371663c1a8a89fb3ce149
Author: Aurelien Jarno <aurelien at aurel32.net>
Date: Wed May 19 18:30:53 2010 +0200
linux-user: fix 32-bit host breakage
Fix breakage introduced by commit 81bbe906c89b6b7af58a1eeb96ec5a0bfdc3386f.
Signed-off-by: Aurelien Jarno <aurelien at aurel32.net>
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 255e89c..6f5a0aa 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -670,7 +670,7 @@ struct target_rlimit {
};
#if defined(TARGET_ALPHA)
-#define TARGET_RLIM_INFINITY 0x7ffffffffffffffful
+#define TARGET_RLIM_INFINITY 0x7fffffffffffffffull
#elif defined(TARGET_MIPS) || defined(TARGET_SPARC)
#define TARGET_RLIM_INFINITY 0x7fffffffUL
#else
commit 41836a9f7e4da3a265989d79f35c44f659f7b3cf
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date: Wed May 12 16:34:42 2010 -0300
Fix qtypes' licenses
- Change from GPL to LGPL
- Add license text when missing
- Minor cosmetic changes to make all headers look the same
Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
diff --git a/check-qdict.c b/check-qdict.c
index f2b4826..2c3089f 100644
--- a/check-qdict.c
+++ b/check-qdict.c
@@ -5,6 +5,9 @@
*
* Authors:
* Luiz Capitulino <lcapitulino at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
*/
#include <check.h>
diff --git a/check-qfloat.c b/check-qfloat.c
index 3758700..b71d983 100644
--- a/check-qfloat.c
+++ b/check-qfloat.c
@@ -1,11 +1,6 @@
/*
* QFloat unit-tests.
*
- * Copyright (C) 2009 Red Hat Inc.
- *
- * Authors:
- * Luiz Capitulino <lcapitulino at redhat.com>
- *
* Copyright IBM, Corp. 2009
*
* Authors:
diff --git a/check-qint.c b/check-qint.c
index 49887bb..f3b0316 100644
--- a/check-qint.c
+++ b/check-qint.c
@@ -5,6 +5,9 @@
*
* Authors:
* Luiz Capitulino <lcapitulino at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
*/
#include <check.h>
diff --git a/check-qlist.c b/check-qlist.c
index 0117ef3..58984cb 100644
--- a/check-qlist.c
+++ b/check-qlist.c
@@ -6,8 +6,8 @@
* Authors:
* Luiz Capitulino <lcapitulino at redhat.com>
*
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
*/
#include <check.h>
diff --git a/check-qstring.c b/check-qstring.c
index c308a63..c9bafc2 100644
--- a/check-qstring.c
+++ b/check-qstring.c
@@ -5,6 +5,9 @@
*
* Authors:
* Luiz Capitulino <lcapitulino at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
*/
#include <check.h>
diff --git a/qbool.c b/qbool.c
index 5ab734c..ad4873f 100644
--- a/qbool.c
+++ b/qbool.c
@@ -1,14 +1,6 @@
/*
* QBool Module
*
- * Copyright (C) 2009 Red Hat Inc.
- *
- * Authors:
- * Luiz Capitulino <lcapitulino at redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- *
* Copyright IBM, Corp. 2009
*
* Authors:
diff --git a/qdict.c b/qdict.c
index aae57bf..175bc17 100644
--- a/qdict.c
+++ b/qdict.c
@@ -1,13 +1,13 @@
/*
- * QDict data type.
+ * QDict Module
*
* Copyright (C) 2009 Red Hat Inc.
*
* Authors:
* Luiz Capitulino <lcapitulino at redhat.com>
*
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
*/
#include "qint.h"
diff --git a/qdict.h b/qdict.h
index 579dcdd..5e5902c 100644
--- a/qdict.h
+++ b/qdict.h
@@ -1,3 +1,15 @@
+/*
+ * QDict Module
+ *
+ * Copyright (C) 2009 Red Hat Inc.
+ *
+ * Authors:
+ * Luiz Capitulino <lcapitulino at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
#ifndef QDICT_H
#define QDICT_H
diff --git a/qemu-objects.h b/qemu-objects.h
index e1d1e0c..c53fbaa 100644
--- a/qemu-objects.h
+++ b/qemu-objects.h
@@ -6,9 +6,10 @@
* Authors:
* Luiz Capitulino <lcapitulino at redhat.com>
*
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
*/
+
#ifndef QEMU_OBJECTS_H
#define QEMU_OBJECTS_H
diff --git a/qerror.c b/qerror.c
index 034c7de..44d0bf8 100644
--- a/qerror.c
+++ b/qerror.c
@@ -1,5 +1,5 @@
/*
- * QError: QEMU Error data-type.
+ * QError Module
*
* Copyright (C) 2009 Red Hat Inc.
*
diff --git a/qerror.h b/qerror.h
index c98c61a..77ae574 100644
--- a/qerror.h
+++ b/qerror.h
@@ -1,5 +1,5 @@
/*
- * QError header file.
+ * QError Module
*
* Copyright (C) 2009 Red Hat Inc.
*
diff --git a/qfloat.c b/qfloat.c
index 05215f5..f8c8a2e 100644
--- a/qfloat.c
+++ b/qfloat.c
@@ -1,14 +1,6 @@
/*
* QFloat Module
*
- * Copyright (C) 2009 Red Hat Inc.
- *
- * Authors:
- * Luiz Capitulino <lcapitulino at redhat.com>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- *
* Copyright IBM, Corp. 2009
*
* Authors:
diff --git a/qint.c b/qint.c
index 447e847..fb3823a 100644
--- a/qint.c
+++ b/qint.c
@@ -1,14 +1,15 @@
/*
- * QInt data type.
+ * QInt Module
*
* Copyright (C) 2009 Red Hat Inc.
*
* Authors:
* Luiz Capitulino <lcapitulino at redhat.com>
*
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
*/
+
#include "qint.h"
#include "qobject.h"
#include "qemu-common.h"
diff --git a/qint.h b/qint.h
index 672b321..6b1a15c 100644
--- a/qint.h
+++ b/qint.h
@@ -1,3 +1,15 @@
+/*
+ * QInt Module
+ *
+ * Copyright (C) 2009 Red Hat Inc.
+ *
+ * Authors:
+ * Luiz Capitulino <lcapitulino at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
#ifndef QINT_H
#define QINT_H
diff --git a/qlist.c b/qlist.c
index 5fccb7d..5730fb8 100644
--- a/qlist.c
+++ b/qlist.c
@@ -1,14 +1,15 @@
/*
- * QList data type.
+ * QList Module
*
* Copyright (C) 2009 Red Hat Inc.
*
* Authors:
* Luiz Capitulino <lcapitulino at redhat.com>
*
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
*/
+
#include "qlist.h"
#include "qobject.h"
#include "qemu-queue.h"
diff --git a/qlist.h b/qlist.h
index a3261e1..dbe7b92 100644
--- a/qlist.h
+++ b/qlist.h
@@ -1,14 +1,15 @@
/*
- * QList data type header.
+ * QList Module
*
* Copyright (C) 2009 Red Hat Inc.
*
* Authors:
* Luiz Capitulino <lcapitulino at redhat.com>
*
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
*/
+
#ifndef QLIST_H
#define QLIST_H
diff --git a/qobject.h b/qobject.h
index 07de211..d42386d 100644
--- a/qobject.h
+++ b/qobject.h
@@ -8,8 +8,8 @@
* Authors:
* Luiz Capitulino <lcapitulino at redhat.com>
*
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
*
* QObject Reference Counts Terminology
* ------------------------------------
diff --git a/qstring.c b/qstring.c
index 740a106..4e2ba08 100644
--- a/qstring.c
+++ b/qstring.c
@@ -1,14 +1,15 @@
/*
- * QString data type.
+ * QString Module
*
* Copyright (C) 2009 Red Hat Inc.
*
* Authors:
* Luiz Capitulino <lcapitulino at redhat.com>
*
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
*/
+
#include "qobject.h"
#include "qstring.h"
#include "qemu-common.h"
diff --git a/qstring.h b/qstring.h
index 6aaa7d5..84ccd96 100644
--- a/qstring.h
+++ b/qstring.h
@@ -1,3 +1,15 @@
+/*
+ * QString Module
+ *
+ * Copyright (C) 2009 Red Hat Inc.
+ *
+ * Authors:
+ * Luiz Capitulino <lcapitulino at redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ */
+
#ifndef QSTRING_H
#define QSTRING_H
commit 39b59d2606b3360458361ab0f5419b3262dbf46d
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date: Tue May 11 18:08:20 2010 -0300
Monitor: Return before exiting with 'quit'
This is a new version of the (now reverted) following commit:
0e8d2b5575938b8876a3c4bb66ee13c5d306fb6d
The 'quit' Monitor command (implemented by do_quit()) calls
exit() directly, this is problematic under QMP because QEMU
exits before having a chance to send the ok response.
Clients don't know if QEMU exited because of a problem or
because the 'quit' command has been executed.
This commit fixes that by making do_quit() use
qemu_system_shutdown_request(), so that we exit gracefully.
Thanks to Paolo Bonzini <pbonzini at redhat.com> for suggesting
this solution.
Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
diff --git a/monitor.c b/monitor.c
index 2e202ff..ad50f12 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1020,7 +1020,10 @@ static void do_info_cpu_stats(Monitor *mon)
*/
static int do_quit(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
- exit(0);
+ monitor_suspend(mon);
+ no_shutdown = 0;
+ qemu_system_shutdown_request();
+
return 0;
}
commit a691d41a118289e8eb8210e1a824a848497d14a9
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date: Tue May 11 18:07:04 2010 -0300
sysemu: Export 'no_shutdown'
It's a global variable already, do_quit() will use it.
Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
diff --git a/sysemu.h b/sysemu.h
index 48ee66c..879446a 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -128,6 +128,7 @@ extern int max_cpus;
extern int cursor_hide;
extern int graphic_rotate;
extern int no_quit;
+extern int no_shutdown;
extern int semihosting_enabled;
extern int old_param;
extern int boot_menu;
commit a875170167f75e63a11f68adc0a15b4e82a6c186
Author: Luiz Capitulino <lcapitulino at redhat.com>
Date: Tue May 11 17:50:50 2010 -0300
Revert "Monitor: Return before exiting with 'quit'"
This reverts commit 0e8d2b5575938b8876a3c4bb66ee13c5d306fb6d.
Next commits will do the same thing in a better way.
Signed-off-by: Luiz Capitulino <lcapitulino at redhat.com>
diff --git a/monitor.c b/monitor.c
index a1ebc5d..2e202ff 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1020,8 +1020,7 @@ static void do_info_cpu_stats(Monitor *mon)
*/
static int do_quit(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
- monitor_suspend(mon);
- qemu_system_exit_request();
+ exit(0);
return 0;
}
diff --git a/sysemu.h b/sysemu.h
index 643c0c6..48ee66c 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -45,11 +45,9 @@ void cpu_disable_ticks(void);
void qemu_system_reset_request(void);
void qemu_system_shutdown_request(void);
void qemu_system_powerdown_request(void);
-void qemu_system_exit_request(void);
int qemu_shutdown_requested(void);
int qemu_reset_requested(void);
int qemu_powerdown_requested(void);
-int qemu_exit_requested(void);
extern qemu_irq qemu_system_powerdown;
void qemu_system_reset(void);
diff --git a/vl.c b/vl.c
index d77b47c..8c818f0 100644
--- a/vl.c
+++ b/vl.c
@@ -1708,7 +1708,6 @@ static int shutdown_requested;
static int powerdown_requested;
int debug_requested;
int vmstop_requested;
-static int exit_requested;
int qemu_shutdown_requested(void)
{
@@ -1731,12 +1730,6 @@ int qemu_powerdown_requested(void)
return r;
}
-int qemu_exit_requested(void)
-{
- /* just return it, we'll exit() anyway */
- return exit_requested;
-}
-
static int qemu_debug_requested(void)
{
int r = debug_requested;
@@ -1807,12 +1800,6 @@ void qemu_system_powerdown_request(void)
qemu_notify_event();
}
-void qemu_system_exit_request(void)
-{
- exit_requested = 1;
- qemu_notify_event();
-}
-
#ifdef _WIN32
static void host_main_loop_wait(int *timeout)
{
@@ -1949,8 +1936,6 @@ static int vm_can_run(void)
return 0;
if (debug_requested)
return 0;
- if (exit_requested)
- return 0;
return 1;
}
@@ -2003,9 +1988,6 @@ static void main_loop(void)
if ((r = qemu_vmstop_requested())) {
vm_stop(r);
}
- if (qemu_exit_requested()) {
- exit(0);
- }
}
pause_all_vcpus();
}
commit b752daf03092b6720e39fdf7f4198eec95f71468
Author: Markus Armbruster <armbru at redhat.com>
Date: Wed May 12 10:53:01 2010 +0200
Revert "monitor: Convert do_pci_device_hot_remove() to QObject"
We don't want pci_del in QMP. Use device_del instead.
This reverts commit 6848d827162fea039f2658414a4adb6164a4f9b0.
Conflicts:
hw/pci-hotplug.c
sysemu.h
Signed-off-by: Markus Armbruster <armbru at redhat.com>
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index 22a7ce4..37ac015 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -277,8 +277,7 @@ int pci_device_hot_remove(Monitor *mon, const char *pci_addr)
return qdev_unplug(&d->qdev);
}
-int do_pci_device_hot_remove(Monitor *mon, const QDict *qdict,
- QObject **ret_data)
+void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict)
{
- return pci_device_hot_remove(mon, qdict_get_str(qdict, "pci_addr"));
+ pci_device_hot_remove(mon, qdict_get_str(qdict, "pci_addr"));
}
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index fba4c3f..b6e3467 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -874,8 +874,7 @@ ETEXI
.args_type = "pci_addr:s",
.params = "[[<domain>:]<bus>:]<slot>",
.help = "hot remove PCI device",
- .user_print = monitor_user_noop,
- .mhandler.cmd_new = do_pci_device_hot_remove,
+ .mhandler.cmd = do_pci_device_hot_remove,
},
#endif
diff --git a/sysemu.h b/sysemu.h
index 47975b5..643c0c6 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -204,8 +204,7 @@ DriveInfo *add_init_drive(const char *opts);
void pci_device_hot_add(Monitor *mon, const QDict *qdict);
void drive_hot_add(Monitor *mon, const QDict *qdict);
int pci_device_hot_remove(Monitor *mon, const char *pci_addr);
-int do_pci_device_hot_remove(Monitor *mon, const QDict *qdict,
- QObject **ret_data);
+void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict);
/* serial ports */
commit 6c6a58aee425338bf67ec8faffdcda56b0b82090
Author: Markus Armbruster <armbru at redhat.com>
Date: Wed May 12 10:53:00 2010 +0200
Revert "PCI: Convert pci_device_hot_add() to QObject"
Short story: We don't want pci_add in QMP. Long story follows.
pci_add can do two things:
* Hot plug a PCI NIC. device_add is more general.
* Hot plug a PCI disk controller, and a drive connected to it.
The controller is either virtio-blk-pci (if=virtio) or lsi53c895a
(if=scsi). With the latter, the drive is optional. Use drive_add to
hotplug additional SCSI drives. Except drive_add is not available in
QMP.
device_add is more general for controllers and the guest part of
drives. I'm working on a more general alternative for the host part
of drives.
Why am I proposing to remove pci_add from QMP before its replacement is
ready? I want it out sooner rather than later, because it isn't fully
functional (errors and drive_add are missing), and we do not plan to
complete the job. In other words, it's not really usable over QMP now,
and it's not what we want for QMP anyway. Since we don't want it to be
used over QMP, we should take it out, not leave it around as a trap for
the uninitiated.
Dan Berrange confirmed that libvirt has no need for pci_add & friends
over QMP.
This reverts commit 7a344f7ac7bb651d0556a933ed8060d3a9e5d949.
Conflicts:
hw/pci-hotplug.c
sysemu.h
Signed-off-by: Markus Armbruster <armbru at redhat.com>
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index cc45c50..22a7ce4 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -33,7 +33,6 @@
#include "scsi.h"
#include "virtio-blk.h"
#include "qemu-config.h"
-#include "qemu-objects.h"
#if defined(TARGET_I386)
static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
@@ -224,36 +223,7 @@ static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon,
return dev;
}
-void pci_device_hot_add_print(Monitor *mon, const QObject *data)
-{
- QDict *qdict;
-
- assert(qobject_type(data) == QTYPE_QDICT);
- qdict = qobject_to_qdict(data);
-
- monitor_printf(mon, "OK domain %d, bus %d, slot %d, function %d\n",
- (int) qdict_get_int(qdict, "domain"),
- (int) qdict_get_int(qdict, "bus"),
- (int) qdict_get_int(qdict, "slot"),
- (int) qdict_get_int(qdict, "function"));
-
-}
-
-/**
- * pci_device_hot_add(): Hot add a PCI device
- *
- * Return a QDict with the following device information:
- *
- * - "domain": domain number
- * - "bus": bus number
- * - "slot": slot number
- * - "function": function number
- *
- * Example:
- *
- * { "domain": 0, "bus": 0, "slot": 5, "function": 0 }
- */
-int pci_device_hot_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
+void pci_device_hot_add(Monitor *mon, const QDict *qdict)
{
PCIDevice *dev = NULL;
const char *pci_addr = qdict_get_str(qdict, "pci_addr");
@@ -278,20 +248,14 @@ int pci_device_hot_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
dev = qemu_pci_hot_add_storage(mon, pci_addr, opts);
} else {
monitor_printf(mon, "invalid type: %s\n", type);
- return -1;
}
if (dev) {
- *ret_data =
- qobject_from_jsonf("{ 'domain': 0, 'bus': %d, 'slot': %d, "
- "'function': %d }", pci_bus_num(dev->bus),
- PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
- } else {
+ monitor_printf(mon, "OK domain %d, bus %d, slot %d, function %d\n",
+ 0, pci_bus_num(dev->bus), PCI_SLOT(dev->devfn),
+ PCI_FUNC(dev->devfn));
+ } else
monitor_printf(mon, "failed to add %s\n", opts);
- return -1;
- }
-
- return 0;
}
#endif
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index a8f194c..fba4c3f 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -858,8 +858,7 @@ ETEXI
.args_type = "pci_addr:s,type:s,opts:s?",
.params = "auto|[[<domain>:]<bus>:]<slot> nic|storage [[vlan=n][,macaddr=addr][,model=type]] [file=file][,if=type][,bus=nr]...",
.help = "hot-add PCI device",
- .user_print = pci_device_hot_add_print,
- .mhandler.cmd_new = pci_device_hot_add,
+ .mhandler.cmd = pci_device_hot_add,
},
#endif
diff --git a/sysemu.h b/sysemu.h
index fa921df..47975b5 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -201,8 +201,7 @@ extern DriveInfo *drive_init(QemuOpts *arg, void *machine, int *fatal_error);
DriveInfo *add_init_drive(const char *opts);
/* pci-hotplug */
-void pci_device_hot_add_print(Monitor *mon, const QObject *data);
-int pci_device_hot_add(Monitor *mon, const QDict *qdict, QObject **ret_data);
+void pci_device_hot_add(Monitor *mon, const QDict *qdict);
void drive_hot_add(Monitor *mon, const QDict *qdict);
int pci_device_hot_remove(Monitor *mon, const char *pci_addr);
int do_pci_device_hot_remove(Monitor *mon, const QDict *qdict,
commit b3e5e3e6854bd3e3d642557b16f6cafb4b2fbe91
Author: Markus Armbruster <armbru at redhat.com>
Date: Mon May 10 09:16:05 2010 +0200
QMP: Add "Downstream extension of QMP" to spec
Signed-off-by: Markus Armbruster <armbru at redhat.com>
diff --git a/QMP/qmp-spec.txt b/QMP/qmp-spec.txt
index f3c0327..9d30a8c 100644
--- a/QMP/qmp-spec.txt
+++ b/QMP/qmp-spec.txt
@@ -215,3 +215,58 @@ Additionally, Clients must not assume any particular:
- Order of json-object members or json-array elements
- Amount of errors generated by a command, that is, new errors can be added
to any existing command in newer versions of the Server
+
+6. Downstream extension of QMP
+------------------------------
+
+We recommend that downstream consumers of QEMU do *not* modify QMP.
+Management tools should be able to support both upstream and downstream
+versions of QMP without special logic, and downstream extensions are
+inherently at odds with that.
+
+However, we recognize that it is sometimes impossible for downstreams to
+avoid modifying QMP. Both upstream and downstream need to take care to
+preserve long-term compatibility and interoperability.
+
+To help with that, QMP reserves JSON object member names beginning with
+'__' (double underscore) for downstream use ("downstream names"). This
+means upstream will never use any downstream names for its commands,
+arguments, errors, asynchronous events, and so forth.
+
+Any new names downstream wishes to add must begin with '__'. To
+ensure compatibility with other downstreams, it is strongly
+recommended that you prefix your downstram names with '__RFQDN_' where
+RFQDN is a valid, reverse fully qualified domain name which you
+control. For example, a qemu-kvm specific monitor command would be:
+
+ (qemu) __org.linux-kvm_enable_irqchip
+
+Downstream must not change the server greeting (section 2.2) other than
+to offer additional capabilities. But see below for why even that is
+discouraged.
+
+Section '5 Compatibility Considerations' applies to downstream as well
+as to upstream, obviously. It follows that downstream must behave
+exactly like upstream for any input not containing members with
+downstream names ("downstream members"), except it may add members
+with downstream names to its output.
+
+Thus, a client should not be able to distinguish downstream from
+upstream as long as it doesn't send input with downstream members, and
+properly ignores any downstream members in the output it receives.
+
+Advice on downstream modifications:
+
+1. Introducing new commands is okay. If you want to extend an existing
+ command, consider introducing a new one with the new behaviour
+ instead.
+
+2. Introducing new asynchronous messages is okay. If you want to extend
+ an existing message, consider adding a new one instead.
+
+3. Introducing new errors for use in new commands is okay. Adding new
+ errors to existing commands counts as extension, so 1. applies.
+
+4. New capabilities are strongly discouraged. Capabilities are for
+ evolving the basic protocol, and multiple diverging basic protocol
+ dialects are most undesirable.
commit 0d5d46993840c1e6a04c1db38a554aad4ee83835
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date: Wed May 19 15:24:17 2010 +0200
microblaze: Update elf machine nums.
189 was allocated in upstream binutils.
0xbaab was the old temporary value. Still used by some tools and the
linux kernel.
I've seen 115 in older gdb versions, but lets ignore that one.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
diff --git a/elf.h b/elf.h
index c84c8ab..eb9e3be 100644
--- a/elf.h
+++ b/elf.h
@@ -119,7 +119,8 @@ typedef int64_t Elf64_Sxword;
*/
#define EM_S390_OLD 0xA390
-#define EM_XILINX_MICROBLAZE 0xBAAB
+#define EM_MICROBLAZE 189
+#define EM_MICROBLAZE_OLD 0xBAAB
/* This is the info that is needed to parse the dynamic section of the file */
#define DT_NULL 0
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 6bc51da..1f27918 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -629,11 +629,11 @@ static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
#define ELF_START_MMAP 0x80000000
-#define elf_check_arch(x) ( (x) == EM_XILINX_MICROBLAZE )
+#define elf_check_arch(x) ( (x) == EM_MICROBLAZE || (x) == EM_MICROBLAZE_OLD)
#define ELF_CLASS ELFCLASS32
#define ELF_DATA ELFDATA2MSB
-#define ELF_ARCH EM_XILINX_MICROBLAZE
+#define ELF_ARCH EM_MICROBLAZE
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
{
diff --git a/target-microblaze/cpu.h b/target-microblaze/cpu.h
index ec2ca18..3316797 100644
--- a/target-microblaze/cpu.h
+++ b/target-microblaze/cpu.h
@@ -31,7 +31,7 @@ struct CPUMBState;
#define TARGET_HAS_ICE 1
-#define ELF_MACHINE EM_XILINX_MICROBLAZE
+#define ELF_MACHINE EM_MICROBLAZE
#define EXCP_NMI 1
#define EXCP_MMU 2
commit e4cbd44d8e86c7fb605f92b05fd9ae6b9e393c56
Author: Edgar E. Iglesias <edgar.iglesias at gmail.com>
Date: Wed May 19 15:09:28 2010 +0200
microblaze: Add linux-user core dumping support.
Signed-off-by: Edgar E. Iglesias <edgar.iglesias at gmail.com>
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 4ef77bc..6bc51da 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -644,6 +644,24 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i
#define ELF_EXEC_PAGESIZE 4096
+#define USE_ELF_CORE_DUMP
+#define ELF_NREG 38
+typedef target_elf_greg_t target_elf_gregset_t[ELF_NREG];
+
+/* See linux kernel: arch/mips/kernel/process.c:elf_dump_regs. */
+static void elf_core_copy_regs(target_elf_gregset_t *regs, const CPUState *env)
+{
+ int i, pos = 0;
+
+ for (i = 0; i < 32; i++) {
+ (*regs)[pos++] = tswapl(env->regs[i]);
+ }
+
+ for (i = 0; i < 6; i++) {
+ (*regs)[pos++] = tswapl(env->sregs[i]);
+ }
+}
+
#endif /* TARGET_MICROBLAZE */
#ifdef TARGET_SH4
More information about the Spice-commits
mailing list