aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2011-11-27 12:55:32 +0200
committerAvi Kivity <avi@redhat.com>2011-11-27 12:55:32 +0200
commit7e77ae149517feda42a5a5e28e2f76e892526f5c (patch)
tree81022242865552e275164f34134813c3736e52ef
parent9ac357fdfc51bac582a61f95b32565648b844878 (diff)
parent9a93b61730e3b46ef1c01ca522c6abe80ec13832 (diff)
Merge commit '9a93b61730e3b46ef1c01ca522c6abe80ec13832' into upstream-merge
* commit '9a93b61730e3b46ef1c01ca522c6abe80ec13832': (63 commits) msix: Prevent bogus mask updates on MMIO accesses msix: track function masked in pci device state Include zlib.h using #include <> 9p: pass dotl flags to the unlinkat method 9p: allow compiling the dummy virtio-9p-handle.c code on Linux qed: add migration blocker (v2) qcow2: implement bdrv_invalidate_cache (v2) block: allow migration to work with image files (v3) ivshmem: use migration blockers to prevent live migration in peer mode (v2) migrate: add migration blockers usb-linux: fix /proc/bus/usb/devices scan ehci: add assert usb-storage: don't try to send the status early. usb-storage: drop result from device state. usb-storage: drop tag from device state. usb-storage: fill status in complete callback. usb-storage: move status debug message to usb_msd_send_status. x86: fix pcmpestrm and pcmpistrm loader: Fix read_targphys() to behave when read() fails Improve "ta 0" shutdown ... Conflicts: hw/msix.c Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--Makefile47
-rw-r--r--audio/fmodaudio.c6
-rw-r--r--block-migration.c2
-rw-r--r--block.c16
-rw-r--r--block.h4
-rw-r--r--block/qcow2.c34
-rw-r--r--block/qcow2.h2
-rw-r--r--block/qed.c10
-rw-r--r--block/qed.h2
-rw-r--r--block/vmdk.c2
-rw-r--r--block_int.h5
-rw-r--r--docs/libcacard.txt20
-rw-r--r--docs/qapi-code-gen.txt2
-rw-r--r--gdbstub.c14
-rw-r--r--hw/9pfs/virtio-9p-handle.c15
-rw-r--r--hw/9pfs/virtio-9p.c10
-rw-r--r--hw/ide/atapi.c20
-rw-r--r--hw/ivshmem.c12
-rw-r--r--hw/loader.c9
-rw-r--r--hw/loader.h4
-rw-r--r--hw/mips_mipssim.c2
-rw-r--r--hw/msix.c27
-rw-r--r--hw/pci.h2
-rw-r--r--hw/s390-virtio.c47
-rw-r--r--hw/scsi-bus.c128
-rw-r--r--hw/scsi-defs.h10
-rw-r--r--hw/scsi-disk.c37
-rw-r--r--hw/scsi.h2
-rw-r--r--hw/spapr.c10
-rw-r--r--hw/spapr_vio.c40
-rw-r--r--hw/spapr_vty.c39
-rw-r--r--hw/usb-ehci.c1
-rw-r--r--hw/usb-msd.c65
-rw-r--r--migration.c21
-rw-r--r--migration.h15
-rw-r--r--monitor.c4
-rw-r--r--qapi/qmp-output-visitor.c2
-rw-r--r--qemu-doc.texi60
-rw-r--r--qemu-tool.c9
-rw-r--r--qerror.c8
-rw-r--r--qerror.h6
-rw-r--r--savevm.c25
-rw-r--r--target-i386/kvm.c2
-rw-r--r--target-i386/ops_sse.h12
-rw-r--r--target-ppc/translate.c4
-rw-r--r--target-s390x/cpu.h15
-rw-r--r--target-s390x/helper.c27
-rw-r--r--target-s390x/helpers.h1
-rw-r--r--target-s390x/kvm.c19
-rw-r--r--target-s390x/op_helper.c43
-rw-r--r--target-s390x/translate.c4
-rw-r--r--target-sparc/helper.c7
-rw-r--r--target-sparc/helper.h1
-rw-r--r--target-sparc/int32_helper.c10
-rw-r--r--target-sparc/translate.c9
-rw-r--r--tcg/arm/tcg-target.c13
-rw-r--r--tcg/arm/tcg-target.h4
-rw-r--r--tcg/hppa/tcg-target.c12
-rw-r--r--tcg/hppa/tcg-target.h4
-rw-r--r--tcg/i386/tcg-target.c13
-rw-r--r--tcg/i386/tcg-target.h4
-rw-r--r--tcg/ia64/tcg-target.c12
-rw-r--r--tcg/ia64/tcg-target.h4
-rw-r--r--tcg/mips/tcg-target.c13
-rw-r--r--tcg/mips/tcg-target.h4
-rw-r--r--tcg/ppc/tcg-target.c8
-rw-r--r--tcg/ppc/tcg-target.h4
-rw-r--r--tcg/ppc64/tcg-target.c22
-rw-r--r--tcg/ppc64/tcg-target.h4
-rw-r--r--tcg/sparc/tcg-target.c17
-rw-r--r--tcg/sparc/tcg-target.h4
-rw-r--r--tcg/tcg.c8
-rw-r--r--tcg/tci/tcg-target.c8
-rw-r--r--tcg/tci/tcg-target.h2
-rw-r--r--tci.c38
-rw-r--r--usb-linux.c7
76 files changed, 816 insertions, 339 deletions
diff --git a/Makefile b/Makefile
index 019caa3af..812c4c3ea 100644
--- a/Makefile
+++ b/Makefile
@@ -8,6 +8,7 @@ ifeq ($(TRACE_BACKEND),dtrace)
GENERATED_HEADERS += trace-dtrace.h
endif
GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h
+GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c
ifneq ($(wildcard config-host.mak),)
# Put the all: rule here so that config-host.mak can contain dependencies.
@@ -171,34 +172,34 @@ qapi-dir := qapi-generated
test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
qemu-ga$(EXESUF): LIBS = $(LIBS_QGA)
-$(qapi-dir)/test-qapi-types.c: $(qapi-dir)/test-qapi-types.h
-$(qapi-dir)/test-qapi-types.h: $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py
+$(qapi-dir)/test-qapi-types.c $(qapi-dir)/test-qapi-types.h :\
+$(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py -o "$(qapi-dir)" -p "test-" < $<, " GEN $@")
-$(qapi-dir)/test-qapi-visit.c: $(qapi-dir)/test-qapi-visit.h
-$(qapi-dir)/test-qapi-visit.h: $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-visit.py
+$(qapi-dir)/test-qapi-visit.c $(qapi-dir)/test-qapi-visit.h :\
+$(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-visit.py
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py -o "$(qapi-dir)" -p "test-" < $<, " GEN $@")
-$(qapi-dir)/test-qmp-commands.h: $(qapi-dir)/test-qmp-marshal.c
-$(qapi-dir)/test-qmp-marshal.c: $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-commands.py
+$(qapi-dir)/test-qmp-commands.h $(qapi-dir)/test-qmp-marshal.c :\
+$(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-commands.py
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py -o "$(qapi-dir)" -p "test-" < $<, " GEN $@")
-$(qapi-dir)/qga-qapi-types.c: $(qapi-dir)/qga-qapi-types.h
-$(qapi-dir)/qga-qapi-types.h: $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-types.py
+$(qapi-dir)/qga-qapi-types.c $(qapi-dir)/qga-qapi-types.h :\
+$(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-types.py
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py -o "$(qapi-dir)" -p "qga-" < $<, " GEN $@")
-$(qapi-dir)/qga-qapi-visit.c: $(qapi-dir)/qga-qapi-visit.h
-$(qapi-dir)/qga-qapi-visit.h: $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-visit.py
+$(qapi-dir)/qga-qapi-visit.c $(qapi-dir)/qga-qapi-visit.h :\
+$(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-visit.py
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py -o "$(qapi-dir)" -p "qga-" < $<, " GEN $@")
-$(qapi-dir)/qga-qmp-commands.h: $(qapi-dir)/qga-qmp-marshal.c
-$(qapi-dir)/qga-qmp-marshal.c: $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-commands.py
+$(qapi-dir)/qga-qmp-commands.h $(qapi-dir)/qga-qmp-marshal.c :\
+$(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-commands.py
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py -o "$(qapi-dir)" -p "qga-" < $<, " GEN $@")
-qapi-types.c: qapi-types.h
-qapi-types.h: $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py
+qapi-types.c qapi-types.h :\
+$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py -o "." < $<, " GEN $@")
-qapi-visit.c: qapi-visit.h
-qapi-visit.h: $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py
+qapi-visit.c qapi-visit.h :\
+$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py -o "." < $<, " GEN $@")
-qmp-commands.h: qmp-marshal.c
-qmp-marshal.c: $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py
+qmp-commands.h qmp-marshal.c :\
+$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py -m -o "." < $<, " GEN $@")
test-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
@@ -207,11 +208,12 @@ test-visitor: test-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qap
test-qmp-commands.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h test-qmp-marshal.c test-qmp-commands.h) $(qapi-obj-y)
test-qmp-commands: test-qmp-commands.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o $(qapi-dir)/test-qmp-marshal.o module.o
-QGALIB_GEN=$(addprefix $(qapi-dir)/, qga-qapi-types.c qga-qapi-types.h qga-qapi-visit.c qga-qmp-marshal.c)
-$(QGALIB_GEN): $(GENERATED_HEADERS)
-$(qga-obj-y) qemu-ga.o: $(QGALIB_GEN)
+QGALIB_OBJ=$(addprefix $(qapi-dir)/, qga-qapi-types.o qga-qapi-visit.o qga-qmp-marshal.o)
+QGALIB_GEN=$(addprefix $(qapi-dir)/, qga-qapi-types.h qga-qapi-visit.h qga-qmp-commands.h)
+$(QGALIB_OBJ): $(QGALIB_GEN) $(GENERATED_HEADERS)
+$(qga-obj-y) qemu-ga.o: $(QGALIB_GEN) $(GENERATED_HEADERS)
-qemu-ga$(EXESUF): qemu-ga.o $(qga-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qobject-obj-y) $(version-obj-y) $(addprefix $(qapi-dir)/, qga-qapi-visit.o qga-qapi-types.o qga-qmp-marshal.o)
+qemu-ga$(EXESUF): qemu-ga.o $(qga-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qobject-obj-y) $(version-obj-y) $(QGALIB_OBJ)
QEMULIBS=libhw32 libhw64 libuser libdis libdis-user
@@ -227,6 +229,7 @@ clean:
rm -f trace.c trace.h trace.c-timestamp trace.h-timestamp
rm -f trace-dtrace.dtrace trace-dtrace.dtrace-timestamp
rm -f trace-dtrace.h trace-dtrace.h-timestamp
+ rm -f $(GENERATED_SOURCES)
rm -rf $(qapi-dir)
$(MAKE) -C tests clean
for d in $(ALL_SUBDIRS) $(QEMULIBS) libcacard; do \
diff --git a/audio/fmodaudio.c b/audio/fmodaudio.c
index c34cf5356..fabf84dd3 100644
--- a/audio/fmodaudio.c
+++ b/audio/fmodaudio.c
@@ -343,7 +343,7 @@ static void fmod_fini_out (HWVoiceOut *hw)
static int fmod_init_out (HWVoiceOut *hw, struct audsettings *as)
{
- int bits16, mode, channel;
+ int mode, channel;
FMODVoiceOut *fmd = (FMODVoiceOut *) hw;
struct audsettings obt_as = *as;
@@ -374,7 +374,6 @@ static int fmod_init_out (HWVoiceOut *hw, struct audsettings *as)
/* FMOD always operates on little endian frames? */
obt_as.endianness = 0;
audio_pcm_init_info (&hw->info, &obt_as);
- bits16 = (mode & FSOUND_16BITS) != 0;
hw->samples = conf.nb_samples;
return 0;
}
@@ -405,7 +404,7 @@ static int fmod_ctl_out (HWVoiceOut *hw, int cmd, ...)
static int fmod_init_in (HWVoiceIn *hw, struct audsettings *as)
{
- int bits16, mode;
+ int mode;
FMODVoiceIn *fmd = (FMODVoiceIn *) hw;
struct audsettings obt_as = *as;
@@ -432,7 +431,6 @@ static int fmod_init_in (HWVoiceIn *hw, struct audsettings *as)
/* FMOD always operates on little endian frames? */
obt_as.endianness = 0;
audio_pcm_init_info (&hw->info, &obt_as);
- bits16 = (mode & FSOUND_16BITS) != 0;
hw->samples = conf.nb_samples;
return 0;
}
diff --git a/block-migration.c b/block-migration.c
index 0bff07538..5f1048641 100644
--- a/block-migration.c
+++ b/block-migration.c
@@ -521,7 +521,7 @@ static int is_stage2_completed(void)
if ((remaining_dirty / bwidth) <=
migrate_max_downtime()) {
- /* finish stage2 because we think that we can finish remaing work
+ /* finish stage2 because we think that we can finish remaining work
below max_downtime */
return 1;
diff --git a/block.c b/block.c
index 86910b046..d0158877d 100644
--- a/block.c
+++ b/block.c
@@ -2839,6 +2839,22 @@ int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
}
}
+void bdrv_invalidate_cache(BlockDriverState *bs)
+{
+ if (bs->drv && bs->drv->bdrv_invalidate_cache) {
+ bs->drv->bdrv_invalidate_cache(bs);
+ }
+}
+
+void bdrv_invalidate_cache_all(void)
+{
+ BlockDriverState *bs;
+
+ QTAILQ_FOREACH(bs, &bdrv_states, list) {
+ bdrv_invalidate_cache(bs);
+ }
+}
+
int bdrv_flush(BlockDriverState *bs)
{
Coroutine *co;
diff --git a/block.h b/block.h
index 051a25d8d..a82605989 100644
--- a/block.h
+++ b/block.h
@@ -197,6 +197,10 @@ BlockDriverAIOCB *bdrv_aio_ioctl(BlockDriverState *bs,
unsigned long int req, void *buf,
BlockDriverCompletionFunc *cb, void *opaque);
+/* Invalidate any cached metadata used by image formats */
+void bdrv_invalidate_cache(BlockDriverState *bs);
+void bdrv_invalidate_cache_all(void);
+
/* Ensure contents are flushed to disk. */
int bdrv_flush(BlockDriverState *bs);
int coroutine_fn bdrv_co_flush(BlockDriverState *bs);
diff --git a/block/qcow2.c b/block/qcow2.c
index 5c784eee5..d7805ce94 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -240,6 +240,7 @@ static int qcow2_open(BlockDriverState *bs, int flags)
s->cluster_data = qemu_blockalign(bs, QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size
+ 512);
s->cluster_cache_offset = -1;
+ s->flags = flags;
ret = qcow2_refcount_init(bs);
if (ret != 0) {
@@ -632,6 +633,37 @@ static void qcow2_close(BlockDriverState *bs)
qcow2_refcount_close(bs);
}
+static void qcow2_invalidate_cache(BlockDriverState *bs)
+{
+ BDRVQcowState *s = bs->opaque;
+ int flags = s->flags;
+ AES_KEY aes_encrypt_key;
+ AES_KEY aes_decrypt_key;
+ uint32_t crypt_method = 0;
+
+ /*
+ * Backing files are read-only which makes all of their metadata immutable,
+ * that means we don't have to worry about reopening them here.
+ */
+
+ if (s->crypt_method) {
+ crypt_method = s->crypt_method;
+ memcpy(&aes_encrypt_key, &s->aes_encrypt_key, sizeof(aes_encrypt_key));
+ memcpy(&aes_decrypt_key, &s->aes_decrypt_key, sizeof(aes_decrypt_key));
+ }
+
+ qcow2_close(bs);
+
+ memset(s, 0, sizeof(BDRVQcowState));
+ qcow2_open(bs, flags);
+
+ if (crypt_method) {
+ s->crypt_method = crypt_method;
+ memcpy(&s->aes_encrypt_key, &aes_encrypt_key, sizeof(aes_encrypt_key));
+ memcpy(&s->aes_decrypt_key, &aes_decrypt_key, sizeof(aes_decrypt_key));
+ }
+}
+
/*
* Updates the variable length parts of the qcow2 header, i.e. the backing file
* name and all extensions. qcow2 was not designed to allow such changes, so if
@@ -1269,6 +1301,8 @@ static BlockDriver bdrv_qcow2 = {
.bdrv_change_backing_file = qcow2_change_backing_file,
+ .bdrv_invalidate_cache = qcow2_invalidate_cache,
+
.create_options = qcow2_create_options,
.bdrv_check = qcow2_check,
};
diff --git a/block/qcow2.h b/block/qcow2.h
index 531af3948..4e44eea5e 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -125,6 +125,8 @@ typedef struct BDRVQcowState {
int snapshots_size;
int nb_snapshots;
QCowSnapshot *snapshots;
+
+ int flags;
} BDRVQcowState;
/* XXX: use std qcow open function ? */
diff --git a/block/qed.c b/block/qed.c
index d032a4574..7e22e77b9 100644
--- a/block/qed.c
+++ b/block/qed.c
@@ -16,6 +16,7 @@
#include "trace.h"
#include "qed.h"
#include "qerror.h"
+#include "migration.h"
static void qed_aio_cancel(BlockDriverAIOCB *blockacb)
{
@@ -504,6 +505,12 @@ static int bdrv_qed_open(BlockDriverState *bs, int flags)
s->need_check_timer = qemu_new_timer_ns(vm_clock,
qed_need_check_timer_cb, s);
+ error_set(&s->migration_blocker,
+ QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
+ "qed", bs->device_name, "live migration");
+ migrate_add_blocker(s->migration_blocker);
+
+
out:
if (ret) {
qed_free_l2_cache(&s->l2_cache);
@@ -516,6 +523,9 @@ static void bdrv_qed_close(BlockDriverState *bs)
{
BDRVQEDState *s = bs->opaque;
+ migrate_del_blocker(s->migration_blocker);
+ error_free(s->migration_blocker);
+
qed_cancel_need_check_timer(s);
qemu_free_timer(s->need_check_timer);
diff --git a/block/qed.h b/block/qed.h
index 388fdb376..62cbd3b89 100644
--- a/block/qed.h
+++ b/block/qed.h
@@ -164,6 +164,8 @@ typedef struct {
/* Periodic flush and clear need check flag */
QEMUTimer *need_check_timer;
+
+ Error *migration_blocker;
} BDRVQEDState;
enum {
diff --git a/block/vmdk.c b/block/vmdk.c
index e53a2f092..96f7d5d90 100644
--- a/block/vmdk.c
+++ b/block/vmdk.c
@@ -26,7 +26,7 @@
#include "qemu-common.h"
#include "block_int.h"
#include "module.h"
-#include "zlib.h"
+#include <zlib.h>
#define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D')
#define VMDK4_MAGIC (('K' << 24) | ('D' << 16) | ('M' << 8) | 'V')
diff --git a/block_int.h b/block_int.h
index 1ec4921cc..77c0187c3 100644
--- a/block_int.h
+++ b/block_int.h
@@ -88,6 +88,11 @@ struct BlockDriver {
int64_t sector_num, int nb_sectors);
/*
+ * Invalidate any cached meta-data.
+ */
+ void (*bdrv_invalidate_cache)(BlockDriverState *bs);
+
+ /*
* Flushes all data that was already written to the OS all the way down to
* the disk (for example raw-posix calls fsync()).
*/
diff --git a/docs/libcacard.txt b/docs/libcacard.txt
index 5dee6fa47..f7d7519f3 100644
--- a/docs/libcacard.txt
+++ b/docs/libcacard.txt
@@ -170,7 +170,7 @@ public entry point:
int cert_count);
The parameters for this are:
- card - the virtual card structure which will prepresent this card.
+ card - the virtual card structure which will represent this card.
flags - option flags that may be specific to this card type.
cert - array of binary certificates.
cert_len - array of lengths of each of the certificates specified in cert.
@@ -179,7 +179,7 @@ public entry point:
cert_count - number of entries in cert, cert_len, and key arrays.
Any cert, cert_len, or key with the same index are matching sets. That is
- cert[0] is cert_len[0] long and has the corresponsing private key of key[0].
+ cert[0] is cert_len[0] long and has the corresponding private key of key[0].
The card type emulator is expected to own the VCardKeys, but it should copy
any raw cert data it wants to save. It can create new applets and add them to
@@ -261,7 +261,7 @@ Prior to processing calling the card type emulator's VCardProcessAPDU function,
apdu->a_Le - The expected length of any returned data.
apdu->a_cla - The raw apdu class.
apdu->a_channel - The channel (decoded from the class).
- apdu->a_secure_messaging_type - The decoded secure messagin type
+ apdu->a_secure_messaging_type - The decoded secure messaging type
(from class).
apdu->a_type - The decode class type.
apdu->a_gen_type - the generic class type (7816, PROPRIETARY, RFU, PTS).
@@ -273,7 +273,7 @@ Creating a Response --
The expected result of any APDU call is a response. The card type emulator must
set *response with an appropriate VCardResponse value if it returns VCARD_DONE.
-Reponses could be as simple as returning a 2 byte status word response, to as
+Responses could be as simple as returning a 2 byte status word response, to as
complex as returning a block of data along with a 2 byte response. Which is
returned will depend on the semantics of the APDU. The following functions will
create card responses.
@@ -281,13 +281,13 @@ create card responses.
VCardResponse *vcard_make_response(VCard7816Status status);
This is the most basic function to get a response. This function will
- return a response the consists soley one 2 byte status code. If that status
- code is defined in card_7816t.h, then this function is guarrenteed to
+ return a response the consists solely one 2 byte status code. If that status
+ code is defined in card_7816t.h, then this function is guaranteed to
return a response with that status. If a cart type specific status code
is passed and vcard_make_response fails to allocate the appropriate memory
for that response, then vcard_make_response will return a VCardResponse
of VCARD7816_STATUS_EXC_ERROR_MEMORY. In any case, this function is
- guarrenteed to return a valid VCardResponse.
+ guaranteed to return a valid VCardResponse.
VCardResponse *vcard_response_new(unsigned char *buf, int len,
VCard7816Status status);
@@ -327,7 +327,7 @@ and applet.
int vcard_emul_get_login_count(VCard *card);
- This function returns the the number of remaing login attempts for this
+ This function returns the the number of remaining login attempts for this
card. If the card emulator does not know, or the card does not have a
way of giving this information, this function returns -1.
@@ -373,7 +373,7 @@ functions:
The options structure is built by another function in the virtual card
interface where a string of virtual card emulator specific strings are
- mapped to the options. The actual structure is defined by the virutal card
+ mapped to the options. The actual structure is defined by the virtual card
emulator and is used to determine the configuration of soft cards, or to
determine which physical cards to present to the guest.
@@ -399,7 +399,7 @@ functions:
This function will automatically generate the appropriate new reader
events and add the reader to the list.
- To create a new card, the virtual card emulator will call a similiar
+ To create a new card, the virtual card emulator will call a similar
function.
VCard *vcard_new(VCardEmul *card_emul,
diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
index c0a9325db..5831e371e 100644
--- a/docs/qapi-code-gen.txt
+++ b/docs/qapi-code-gen.txt
@@ -14,7 +14,7 @@ To map QMP-defined interfaces to the native C QAPI implementations,
a JSON-based schema is used to define types and function
signatures, and a set of scripts is used to generate types/signatures,
and marshaling/dispatch code. The QEMU Guest Agent also uses these
-scripts, paired with a seperate schema, to generate
+scripts, paired with a separate schema, to generate
marshaling/dispatch code for the guest agent server running in the
guest.
diff --git a/gdbstub.c b/gdbstub.c
index a25f40443..640cf4ee2 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1781,12 +1781,6 @@ void gdb_register_coprocessor(CPUState * env,
GDBRegisterState **p;
static int last_reg = NUM_CORE_REGS;
- s = (GDBRegisterState *)g_malloc0(sizeof(GDBRegisterState));
- s->base_reg = last_reg;
- s->num_regs = num_regs;
- s->get_reg = get_reg;
- s->set_reg = set_reg;
- s->xml = xml;
p = &env->gdb_regs;
while (*p) {
/* Check for duplicates. */
@@ -1794,6 +1788,14 @@ void gdb_register_coprocessor(CPUState * env,
return;
p = &(*p)->next;
}
+
+ s = g_new0(GDBRegisterState, 1);
+ s->base_reg = last_reg;
+ s->num_regs = num_regs;
+ s->get_reg = get_reg;
+ s->set_reg = set_reg;
+ s->xml = xml;
+
/* Add to end of list. */
last_reg += num_regs;
*p = s;
diff --git a/hw/9pfs/virtio-9p-handle.c b/hw/9pfs/virtio-9p-handle.c
index 0a778b48c..7644ae5ab 100644
--- a/hw/9pfs/virtio-9p-handle.c
+++ b/hw/9pfs/virtio-9p-handle.c
@@ -58,12 +58,16 @@ static inline int open_by_handle(int mountfd, const char *fh, int flags)
}
#else
-struct file_handle {
+struct rpl_file_handle {
unsigned int handle_bytes;
int handle_type;
unsigned char handle[0];
};
+#define file_handle rpl_file_handle
+#ifndef AT_REMOVEDIR
+#define AT_REMOVEDIR 0x200
+#endif
#ifndef AT_EMPTY_PATH
#define AT_EMPTY_PATH 0x1000 /* Allow empty relative pathname */
#endif
@@ -574,13 +578,20 @@ static int handle_unlinkat(FsContext *ctx, V9fsPath *dir,
{
int dirfd, ret;
struct handle_data *data = (struct handle_data *)ctx->private;
+ int rflags;
dirfd = open_by_handle(data->mountfd, dir->data, O_PATH);
if (dirfd < 0) {
return dirfd;
}
- ret = unlinkat(dirfd, name, flags);
+ rflags = 0;
+ if (flags & P9_DOTL_AT_REMOVEDIR) {
+ rflags |= AT_REMOVEDIR;
+ }
+
+ ret = unlinkat(dirfd, name, rflags);
+
close(dirfd);
return ret;
}
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index 01cf337e3..1b2fc5dfb 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -74,15 +74,6 @@ static int omode_to_uflags(int8_t mode)
return ret;
}
-static int dotl_to_at_flags(int flags)
-{
- int rflags = 0;
- if (flags & P9_DOTL_AT_REMOVEDIR) {
- rflags |= AT_REMOVEDIR;
- }
- return rflags;
-}
-
struct dotl_openflag_map {
int dotl_flag;
int open_flag;
@@ -2444,7 +2435,6 @@ static void v9fs_unlinkat(void *opaque)
V9fsPDU *pdu = opaque;
pdu_unmarshal(pdu, offset, "dsd", &dfid, &name, &flags);
- flags = dotl_to_at_flags(flags);
dfidp = get_fid(pdu, dfid);
if (dfidp == NULL) {
diff --git a/hw/ide/atapi.c b/hw/ide/atapi.c
index 1fed359ab..8af1cfdd7 100644
--- a/hw/ide/atapi.c
+++ b/hw/ide/atapi.c
@@ -695,12 +695,7 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
int action, code;
int max_len;
- if (buf[0] == GPCMD_MODE_SENSE_10) {
- max_len = ube16_to_cpu(buf + 7);
- } else {
- max_len = buf[4];
- }
-
+ max_len = ube16_to_cpu(buf + 7);
action = buf[2] >> 6;
code = buf[2] & 0x3f;
@@ -708,7 +703,7 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
case 0: /* current values */
switch(code) {
case MODE_PAGE_R_W_ERROR: /* error recovery */
- cpu_to_ube16(&buf[0], 16 + 6);
+ cpu_to_ube16(&buf[0], 16 - 2);
buf[2] = 0x70;
buf[3] = 0;
buf[4] = 0;
@@ -727,7 +722,7 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
ide_atapi_cmd_reply(s, 16, max_len);
break;
case MODE_PAGE_AUDIO_CTL:
- cpu_to_ube16(&buf[0], 24 + 6);
+ cpu_to_ube16(&buf[0], 24 - 2);
buf[2] = 0x70;
buf[3] = 0;
buf[4] = 0;
@@ -746,7 +741,7 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
ide_atapi_cmd_reply(s, 24, max_len);
break;
case MODE_PAGE_CAPABILITIES:
- cpu_to_ube16(&buf[0], 28 + 6);
+ cpu_to_ube16(&buf[0], 30 - 2);
buf[2] = 0x70;
buf[3] = 0;
buf[4] = 0;
@@ -755,7 +750,7 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
buf[7] = 0;
buf[8] = MODE_PAGE_CAPABILITIES;
- buf[9] = 28 - 10;
+ buf[9] = 30 - 10;
buf[10] = 0x3b; /* read CDR/CDRW/DVDROM/DVDR/DVDRAM */
buf[11] = 0x00;
@@ -777,7 +772,9 @@ static void cmd_mode_sense(IDEState *s, uint8_t *buf)
buf[25] = 0;
buf[26] = 0;
buf[27] = 0;
- ide_atapi_cmd_reply(s, 28, max_len);
+ buf[28] = 0;
+ buf[29] = 0;
+ ide_atapi_cmd_reply(s, 30, max_len);
break;
default:
goto error_cmd;
@@ -1043,7 +1040,6 @@ static const struct {
[ 0x00 ] = { cmd_test_unit_ready, CHECK_READY },
[ 0x03 ] = { cmd_request_sense, ALLOW_UA },
[ 0x12 ] = { cmd_inquiry, ALLOW_UA },
- [ 0x1a ] = { cmd_mode_sense, /* (6) */ 0 },
[ 0x1b ] = { cmd_start_stop_unit, 0 }, /* [1] */
[ 0x1e ] = { cmd_prevent_allow_medium_removal, 0 },
[ 0x25 ] = { cmd_read_cdvd_capacity, CHECK_READY },
diff --git a/hw/ivshmem.c b/hw/ivshmem.c
index 242fbea3a..a3a0e9845 100644
--- a/hw/ivshmem.c
+++ b/hw/ivshmem.c
@@ -18,6 +18,8 @@
#include "pci.h"
#include "msix.h"
#include "kvm.h"
+#include "migration.h"
+#include "qerror.h"
#include <sys/mman.h>
#include <sys/types.h>
@@ -78,6 +80,8 @@ typedef struct IVShmemState {
uint32_t features;
EventfdEntry *eventfd_table;
+ Error *migration_blocker;
+
char * shmobj;
char * sizearg;
char * role;
@@ -646,7 +650,8 @@ static int pci_ivshmem_init(PCIDevice *dev)
}
if (s->role_val == IVSHMEM_PEER) {
- register_device_unmigratable(&s->dev.qdev, "ivshmem", s);
+ error_set(&s->migration_blocker, QERR_DEVICE_FEATURE_BLOCKS_MIGRATION, "ivshmem", "peer mode");
+ migrate_add_blocker(s->migration_blocker);
}
pci_conf = s->dev.config;
@@ -741,6 +746,11 @@ static int pci_ivshmem_uninit(PCIDevice *dev)
{
IVShmemState *s = DO_UPCAST(IVShmemState, dev, dev);
+ if (s->migration_blocker) {
+ migrate_del_blocker(s->migration_blocker);
+ error_free(s->migration_blocker);
+ }
+
memory_region_destroy(&s->ivshmem_mmio);
memory_region_del_subregion(&s->bar, &s->ivshmem);
memory_region_destroy(&s->ivshmem);
diff --git a/hw/loader.c b/hw/loader.c
index 5676c1821..9bbcddd42 100644
--- a/hw/loader.c
+++ b/hw/loader.c
@@ -85,11 +85,11 @@ int load_image(const char *filename, uint8_t *addr)
}
/* read()-like version */
-int read_targphys(const char *name,
- int fd, target_phys_addr_t dst_addr, size_t nbytes)
+ssize_t read_targphys(const char *name,
+ int fd, target_phys_addr_t dst_addr, size_t nbytes)
{
uint8_t *buf;
- size_t did;
+ ssize_t did;
buf = g_malloc(nbytes);
did = read(fd, buf, nbytes);
@@ -176,7 +176,8 @@ static void bswap_ahdr(struct exec *e)
int load_aout(const char *filename, target_phys_addr_t addr, int max_sz,
int bswap_needed, target_phys_addr_t target_page_size)
{
- int fd, size, ret;
+ int fd;
+ ssize_t size, ret;
struct exec e;
uint32_t magic;
diff --git a/hw/loader.h b/hw/loader.h
index fc6bdff6b..fbcaba9f0 100644
--- a/hw/loader.h
+++ b/hw/loader.h
@@ -14,8 +14,8 @@ int load_aout(const char *filename, target_phys_addr_t addr, int max_sz,
int load_uimage(const char *filename, target_phys_addr_t *ep,
target_phys_addr_t *loadaddr, int *is_linux);
-int read_targphys(const char *name,
- int fd, target_phys_addr_t dst_addr, size_t nbytes);
+ssize_t read_targphys(const char *name,
+ int fd, target_phys_addr_t dst_addr, size_t nbytes);
void pstrcpy_targphys(const char *name,
target_phys_addr_t dest, int buf_size,
const char *source);
diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c
index 740715854..b56cba619 100644
--- a/hw/mips_mipssim.c
+++ b/hw/mips_mipssim.c
@@ -1,7 +1,7 @@
/*
* QEMU/mipssim emulation
*
- * Emulates a very simple machine model similiar to the one use by the
+ * Emulates a very simple machine model similar to the one used by the
* proprietary MIPS emulator.
*
* Copyright (c) 2007 Thiemo Seufer
diff --git a/hw/msix.c b/hw/msix.c
index 60d6d1e0c..ea7020432 100644
--- a/hw/msix.c
+++ b/hw/msix.c
@@ -174,6 +174,7 @@ static int msix_add_config(struct PCIDevice *pdev, unsigned short nentries,
/* Make flags bit writable. */
pdev->wmask[config_offset + MSIX_CONTROL_OFFSET] |= MSIX_ENABLE_MASK |
MSIX_MASKALL_MASK;
+ pdev->msix_function_masked = true;
return 0;
}
@@ -212,16 +213,11 @@ static void msix_clr_pending(PCIDevice *dev, int vector)
*msix_pending_byte(dev, vector) &= ~msix_pending_mask(vector);
}
-static int msix_function_masked(PCIDevice *dev)
-{
- return dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] & MSIX_MASKALL_MASK;
-}
-
static int msix_is_masked(PCIDevice *dev, int vector)
{
unsigned offset =
vector * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL;
- return msix_function_masked(dev) ||
+ return dev->msix_function_masked ||
dev->msix_table_page[offset] & PCI_MSIX_ENTRY_CTRL_MASKBIT;
}
@@ -233,24 +229,34 @@ static void msix_handle_mask_update(PCIDevice *dev, int vector)
}
}
+static void msix_update_function_masked(PCIDevice *dev)
+{
+ dev->msix_function_masked = !msix_enabled(dev) ||
+ (dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] & MSIX_MASKALL_MASK);
+}
+
/* Handle MSI-X capability config write. */
void msix_write_config(PCIDevice *dev, uint32_t addr,
uint32_t val, int len)
{
unsigned enable_pos = dev->msix_cap + MSIX_CONTROL_OFFSET;
int vector;
+ bool was_masked;
if (!range_covers_byte(addr, len, enable_pos)) {
return;
}
+ was_masked = dev->msix_function_masked;
+ msix_update_function_masked(dev);
+
if (!msix_enabled(dev)) {
return;
}
pci_device_deassert_intx(dev);
- if (msix_function_masked(dev)) {
+ if (dev->msix_function_masked == was_masked) {
return;
}
@@ -266,6 +272,12 @@ static void msix_mmio_write(void *opaque, target_phys_addr_t addr,
unsigned int offset = addr & (MSIX_PAGE_SIZE - 1) & ~0x3;
int vector = offset / PCI_MSIX_ENTRY_SIZE;
int was_masked = msix_is_masked(dev, vector);
+
+ /* MSI-X page includes a read-only PBA and a writeable Vector Control. */
+ if (vector >= dev->msix_entries_nr) {
+ return;
+ }
+
pci_set_long(dev->msix_table_page + offset, val);
if (kvm_enabled() && kvm_irqchip_in_kernel()) {
kvm_msix_update(dev, vector, was_masked, msix_is_masked(dev, vector));
@@ -431,6 +443,7 @@ void msix_load(PCIDevice *dev, QEMUFile *f)
msix_free_irq_entries(dev);
qemu_get_buffer(f, dev->msix_table_page, n * PCI_MSIX_ENTRY_SIZE);
qemu_get_buffer(f, dev->msix_table_page + MSIX_PAGE_PENDING, (n + 7) / 8);
+ msix_update_function_masked(dev);
}
/* Does device support MSI-X? */
diff --git a/hw/pci.h b/hw/pci.h
index 7b787b6f0..42201519b 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -182,6 +182,8 @@ struct PCIDevice {
unsigned *msix_entry_used;
/* Region including the MSI-X table */
uint32_t msix_bar_size;
+ /* MSIX function mask set or MSIX disabled */
+ bool msix_function_masked;
/* Version id needed for VMState */
int32_t version_id;
diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index 60c66e92c..61b67e8c3 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -97,6 +97,7 @@ int s390_virtio_hypercall(CPUState *env, uint64_t mem, uint64_t hypercall)
dev = s390_virtio_bus_find_mem(s390_bus, mem);
virtio_reset(dev->vdev);
+ stb_phys(dev->dev_offs + VIRTIO_DEV_OFFS_STATUS, 0);
s390_virtio_device_sync(dev);
break;
}
@@ -120,6 +121,34 @@ int s390_virtio_hypercall(CPUState *env, uint64_t mem, uint64_t hypercall)
return r;
}
+/*
+ * The number of running CPUs. On s390 a shutdown is the state of all CPUs
+ * being either stopped or disabled (for interrupts) waiting. We have to
+ * track this number to call the shutdown sequence accordingly. This
+ * number is modified either on startup or while holding the big qemu lock.
+ */
+static unsigned s390_running_cpus;
+
+void s390_add_running_cpu(CPUState *env)
+{
+ if (env->halted) {
+ s390_running_cpus++;
+ env->halted = 0;
+ env->exception_index = -1;
+ }
+}
+
+unsigned s390_del_running_cpu(CPUState *env)
+{
+ if (env->halted == 0) {
+ assert(s390_running_cpus >= 1);
+ s390_running_cpus--;
+ env->halted = 1;
+ env->exception_index = EXCP_HLT;
+ }
+ return s390_running_cpus;
+}
+
/* PC hardware initialisation */
static void s390_init(ram_addr_t my_ram_size,
const char *boot_device,
@@ -136,6 +165,9 @@ static void s390_init(ram_addr_t my_ram_size,
ram_addr_t initrd_size = 0;
int shift = 0;
uint8_t *storage_keys;
+ void *virtio_region;
+ target_phys_addr_t virtio_region_len;
+ target_phys_addr_t virtio_region_start;
int i;
/* s390x ram size detection needs a 16bit multiplier + an increment. So
@@ -155,6 +187,15 @@ static void s390_init(ram_addr_t my_ram_size,
memory_region_init_ram(ram, NULL, "s390.ram", my_ram_size);
memory_region_add_subregion(sysmem, 0, ram);
+ /* clear virtio region */
+ virtio_region_len = my_ram_size - ram_size;
+ virtio_region_start = ram_size;
+ virtio_region = cpu_physical_memory_map(virtio_region_start,
+ &virtio_region_len, true);
+ memset(virtio_region, 0, virtio_region_len);
+ cpu_physical_memory_unmap(virtio_region, virtio_region_len, 1,
+ virtio_region_len);
+
/* allocate storage keys */
storage_keys = g_malloc0(my_ram_size / TARGET_PAGE_SIZE);
@@ -178,8 +219,8 @@ static void s390_init(ram_addr_t my_ram_size,
tmp_env->storage_keys = storage_keys;
}
- env->halted = 0;
- env->exception_index = 0;
+ /* One CPU has to run */
+ s390_add_running_cpu(env);
if (kernel_filename) {
kernel_size = load_image(kernel_filename, qemu_get_ram_ptr(0));
@@ -229,7 +270,7 @@ static void s390_init(ram_addr_t my_ram_size,
if (kernel_cmdline) {
cpu_physical_memory_write(KERN_PARM_AREA, kernel_cmdline,
- strlen(kernel_cmdline));
+ strlen(kernel_cmdline) + 1);
}
/* Create VirtIO network adapters */
diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index e6ebbd594..3a2a7bb72 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -9,8 +9,6 @@
static char *scsibus_get_fw_dev_path(DeviceState *dev);
static int scsi_req_parse(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf);
static void scsi_req_dequeue(SCSIRequest *req);
-static int scsi_build_sense(uint8_t *in_buf, int in_len,
- uint8_t *buf, int len, bool fixed);
static struct BusInfo scsi_bus_info = {
.name = "SCSI",
@@ -502,7 +500,7 @@ SCSIRequest *scsi_req_new(SCSIDevice *d, uint32_t tag, uint32_t lun,
hba_private);
} else if (lun != d->lun ||
buf[0] == REPORT_LUNS ||
- buf[0] == REQUEST_SENSE) {
+ (buf[0] == REQUEST_SENSE && (d->sense_len || cmd.xfer < 4))) {
req = scsi_req_alloc(&reqops_target_command, d, tag, lun,
hba_private);
} else {
@@ -649,6 +647,31 @@ static void scsi_req_dequeue(SCSIRequest *req)
}
}
+static int scsi_get_performance_length(int num_desc, int type, int data_type)
+{
+ /* MMC-6, paragraph 6.7. */
+ switch (type) {
+ case 0:
+ if ((data_type & 3) == 0) {
+ /* Each descriptor is as in Table 295 - Nominal performance. */
+ return 16 * num_desc + 8;
+ } else {
+ /* Each descriptor is as in Table 296 - Exceptions. */
+ return 6 * num_desc + 8;
+ }
+ case 1:
+ case 4:
+ case 5:
+ return 8 * num_desc + 8;
+ case 2:
+ return 2048 * num_desc + 8;
+ case 3:
+ return 16 * num_desc + 8;
+ default:
+ return 8;
+ }
+}
+
static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
{
switch (buf[0] >> 5) {
@@ -666,11 +689,11 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
cmd->len = 10;
break;
case 4:
- cmd->xfer = ldl_be_p(&buf[10]);
+ cmd->xfer = ldl_be_p(&buf[10]) & 0xffffffffULL;
cmd->len = 16;
break;
case 5:
- cmd->xfer = ldl_be_p(&buf[6]);
+ cmd->xfer = ldl_be_p(&buf[6]) & 0xffffffffULL;
cmd->len = 12;
break;
default:
@@ -681,8 +704,9 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
case TEST_UNIT_READY:
case REWIND:
case START_STOP:
- case SEEK_6:
+ case SET_CAPACITY:
case WRITE_FILEMARKS:
+ case WRITE_FILEMARKS_16:
case SPACE:
case RESERVE:
case RELEASE:
@@ -691,6 +715,8 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
case VERIFY_10:
case SEEK_10:
case SYNCHRONIZE_CACHE:
+ case SYNCHRONIZE_CACHE_16:
+ case LOCATE_16:
case LOCK_UNLOCK_CACHE:
case LOAD_UNLOAD:
case SET_CD_SPEED:
@@ -698,6 +724,11 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
case WRITE_LONG_10:
case MOVE_MEDIUM:
case UPDATE_BLOCK:
+ case RESERVE_TRACK:
+ case SET_READ_AHEAD:
+ case PRE_FETCH:
+ case PRE_FETCH_16:
+ case ALLOW_OVERWRITE:
cmd->xfer = 0;
break;
case MODE_SENSE:
@@ -711,14 +742,13 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
case READ_BLOCK_LIMITS:
cmd->xfer = 6;
break;
- case READ_POSITION:
- cmd->xfer = 20;
- break;
case SEND_VOLUME_TAG:
- cmd->xfer *= 40;
- break;
- case MEDIUM_SCAN:
- cmd->xfer *= 8;
+ /* GPCMD_SET_STREAMING from multimedia commands. */
+ if (dev->type == TYPE_ROM) {
+ cmd->xfer = buf[10] | (buf[9] << 8);
+ } else {
+ cmd->xfer = buf[9] | (buf[8] << 8);
+ }
break;
case WRITE_10:
case WRITE_VERIFY_10:
@@ -737,9 +767,39 @@ static int scsi_req_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *buf)
case READ_16:
cmd->xfer *= dev->blocksize;
break;
+ case FORMAT_UNIT:
+ /* MMC mandates the parameter list to be 12-bytes long. Parameters
+ * for block devices are restricted to the header right now. */
+ if (dev->type == TYPE_ROM && (buf[1] & 16)) {
+ cmd->xfer = 12;
+ } else {
+ cmd->xfer = (buf[1] & 16) == 0 ? 0 : (buf[1] & 32 ? 8 : 4);
+ }
+ break;
case INQUIRY:
+ case RECEIVE_DIAGNOSTIC:
+ case SEND_DIAGNOSTIC:
cmd->xfer = buf[4] | (buf[3] << 8);
break;
+ case READ_CD:
+ case READ_BUFFER:
+ case WRITE_BUFFER:
+ case SEND_CUE_SHEET:
+ cmd->xfer = buf[8] | (buf[7] << 8) | (buf[6] << 16);
+ break;
+ case PERSISTENT_RESERVE_OUT:
+ cmd->xfer = ldl_be_p(&buf[5]) & 0xffffffffULL;
+ break;
+ case ERASE_12:
+ if (dev->type == TYPE_ROM) {
+ /* MMC command GET PERFORMANCE. */
+ cmd->xfer = scsi_get_performance_length(buf[9] | (buf[8] << 8),
+ buf[10], buf[1] & 0x1f);
+ }
+ break;
+ case MECHANISM_STATUS:
+ case READ_DVD_STRUCTURE:
+ case SEND_DVD_STRUCTURE:
case MAINTENANCE_OUT:
case MAINTENANCE_IN:
if (dev->type == TYPE_ROM) {
@@ -755,6 +815,10 @@ static int scsi_req_stream_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *bu
{
switch (buf[0]) {
/* stream commands */
+ case ERASE_12:
+ case ERASE_16:
+ cmd->xfer = 0;
+ break;
case READ_6:
case READ_REVERSE:
case RECOVER_BUFFERED_DATA:
@@ -770,6 +834,15 @@ static int scsi_req_stream_length(SCSICommand *cmd, SCSIDevice *dev, uint8_t *bu
cmd->len = 6;
cmd->xfer = 0;
break;
+ case SPACE_16:
+ cmd->xfer = buf[13] | (buf[12] << 8);
+ break;
+ case READ_POSITION:
+ cmd->xfer = buf[8] | (buf[7] << 8);
+ break;
+ case FORMAT_UNIT:
+ cmd->xfer = buf[4] | (buf[3] << 8);
+ break;
/* generic commands */
default:
return scsi_req_length(cmd, dev, buf);
@@ -809,6 +882,8 @@ static void scsi_cmd_xfer_mode(SCSICommand *cmd)
case SEARCH_LOW_12:
case MEDIUM_SCAN:
case SEND_VOLUME_TAG:
+ case SEND_CUE_SHEET:
+ case SEND_DVD_STRUCTURE:
case PERSISTENT_RESERVE_OUT:
case MAINTENANCE_OUT:
cmd->mode = SCSI_XFER_TO_DEV;
@@ -835,7 +910,7 @@ static uint64_t scsi_cmd_lba(SCSICommand *cmd)
case 1:
case 2:
case 5:
- lba = ldl_be_p(&buf[2]);
+ lba = ldl_be_p(&buf[2]) & 0xffffffffULL;
break;
case 4:
lba = ldq_be_p(&buf[2]);
@@ -1036,7 +1111,7 @@ static const char *scsi_command_name(uint8_t cmd)
[ REASSIGN_BLOCKS ] = "REASSIGN_BLOCKS",
[ READ_6 ] = "READ_6",
[ WRITE_6 ] = "WRITE_6",
- [ SEEK_6 ] = "SEEK_6",
+ [ SET_CAPACITY ] = "SET_CAPACITY",
[ READ_REVERSE ] = "READ_REVERSE",
[ WRITE_FILEMARKS ] = "WRITE_FILEMARKS",
[ SPACE ] = "SPACE",
@@ -1064,7 +1139,7 @@ static const char *scsi_command_name(uint8_t cmd)
[ SEARCH_EQUAL ] = "SEARCH_EQUAL",
[ SEARCH_LOW ] = "SEARCH_LOW",
[ SET_LIMITS ] = "SET_LIMITS",
- [ PRE_FETCH ] = "PRE_FETCH",
+ [ PRE_FETCH ] = "PRE_FETCH/READ_POSITION",
/* READ_POSITION and PRE_FETCH use the same operation code */
[ SYNCHRONIZE_CACHE ] = "SYNCHRONIZE_CACHE",
[ LOCK_UNLOCK_CACHE ] = "LOCK_UNLOCK_CACHE",
@@ -1101,9 +1176,11 @@ static const char *scsi_command_name(uint8_t cmd)
[ WRITE_16 ] = "WRITE_16",
[ WRITE_VERIFY_16 ] = "WRITE_VERIFY_16",
[ VERIFY_16 ] = "VERIFY_16",
- [ SYNCHRONIZE_CACHE_16 ] = "SYNCHRONIZE_CACHE_16",
+ [ PRE_FETCH_16 ] = "PRE_FETCH_16",
+ [ SYNCHRONIZE_CACHE_16 ] = "SPACE_16/SYNCHRONIZE_CACHE_16",
+ /* SPACE_16 and SYNCHRONIZE_CACHE_16 use the same operation code */
[ LOCATE_16 ] = "LOCATE_16",
- [ WRITE_SAME_16 ] = "WRITE_SAME_16",
+ [ WRITE_SAME_16 ] = "ERASE_16/WRITE_SAME_16",
/* ERASE_16 and WRITE_SAME_16 use the same operation code */
[ SERVICE_ACTION_IN_16 ] = "SERVICE_ACTION_IN_16",
[ WRITE_LONG_16 ] = "WRITE_LONG_16",
@@ -1113,6 +1190,8 @@ static const char *scsi_command_name(uint8_t cmd)
[ LOAD_UNLOAD ] = "LOAD_UNLOAD",
[ READ_12 ] = "READ_12",
[ WRITE_12 ] = "WRITE_12",
+ [ ERASE_12 ] = "ERASE_12/GET_PERFORMANCE",
+ /* ERASE_12 and GET_PERFORMANCE use the same operation code */
[ SERVICE_ACTION_IN_12 ] = "SERVICE_ACTION_IN_12",
[ WRITE_VERIFY_12 ] = "WRITE_VERIFY_12",
[ VERIFY_12 ] = "VERIFY_12",
@@ -1120,9 +1199,18 @@ static const char *scsi_command_name(uint8_t cmd)
[ SEARCH_EQUAL_12 ] = "SEARCH_EQUAL_12",
[ SEARCH_LOW_12 ] = "SEARCH_LOW_12",
[ READ_ELEMENT_STATUS ] = "READ_ELEMENT_STATUS",
- [ SEND_VOLUME_TAG ] = "SEND_VOLUME_TAG",
+ [ SEND_VOLUME_TAG ] = "SEND_VOLUME_TAG/SET_STREAMING",
+ /* SEND_VOLUME_TAG and SET_STREAMING use the same operation code */
+ [ READ_CD ] = "READ_CD",
[ READ_DEFECT_DATA_12 ] = "READ_DEFECT_DATA_12",
+ [ READ_DVD_STRUCTURE ] = "READ_DVD_STRUCTURE",
+ [ RESERVE_TRACK ] = "RESERVE_TRACK",
+ [ SEND_CUE_SHEET ] = "SEND_CUE_SHEET",
+ [ SEND_DVD_STRUCTURE ] = "SEND_DVD_STRUCTURE",
[ SET_CD_SPEED ] = "SET_CD_SPEED",
+ [ SET_READ_AHEAD ] = "SET_READ_AHEAD",
+ [ ALLOW_OVERWRITE ] = "ALLOW_OVERWRITE",
+ [ MECHANISM_STATUS ] = "MECHANISM_STATUS",
};
if (cmd >= ARRAY_SIZE(names) || names[cmd] == NULL)
@@ -1279,7 +1367,7 @@ static char *scsibus_get_fw_dev_path(DeviceState *dev)
SCSIDevice *d = DO_UPCAST(SCSIDevice, qdev, dev);
char path[100];
- snprintf(path, sizeof(path), "%s@%d:%d:%d", qdev_fw_name(dev),
+ snprintf(path, sizeof(path), "%s@%d,%d,%d", qdev_fw_name(dev),
d->channel, d->id, d->lun);
return strdup(path);
diff --git a/hw/scsi-defs.h b/hw/scsi-defs.h
index d0a467aab..354ed7b55 100644
--- a/hw/scsi-defs.h
+++ b/hw/scsi-defs.h
@@ -32,7 +32,7 @@
#define REASSIGN_BLOCKS 0x07
#define READ_6 0x08
#define WRITE_6 0x0a
-#define SEEK_6 0x0b
+#define SET_CAPACITY 0x0b
#define READ_REVERSE 0x0f
#define WRITE_FILEMARKS 0x10
#define SPACE 0x11
@@ -81,14 +81,17 @@
#define GET_EVENT_STATUS_NOTIFICATION 0x4a
#define LOG_SELECT 0x4c
#define LOG_SENSE 0x4d
+#define RESERVE_TRACK 0x53
#define MODE_SELECT_10 0x55
#define RESERVE_10 0x56
#define RELEASE_10 0x57
#define MODE_SENSE_10 0x5a
+#define SEND_CUE_SHEET 0x5d
#define PERSISTENT_RESERVE_IN 0x5e
#define PERSISTENT_RESERVE_OUT 0x5f
#define VARLENGTH_CDB 0x7f
#define WRITE_FILEMARKS_16 0x80
+#define ALLOW_OVERWRITE 0x82
#define EXTENDED_COPY 0x83
#define ATA_PASSTHROUGH 0x85
#define ACCESS_CONTROL_IN 0x86
@@ -98,6 +101,8 @@
#define WRITE_16 0x8a
#define WRITE_VERIFY_16 0x8e
#define VERIFY_16 0x8f
+#define PRE_FETCH_16 0x90
+#define SPACE_16 0x91
#define SYNCHRONIZE_CACHE_16 0x91
#define LOCATE_16 0x92
#define WRITE_SAME_16 0x93
@@ -110,9 +115,11 @@
#define MAINTENANCE_OUT 0xa4
#define MOVE_MEDIUM 0xa5
#define LOAD_UNLOAD 0xa6
+#define SET_READ_AHEAD 0xa7
#define READ_12 0xa8
#define WRITE_12 0xaa
#define SERVICE_ACTION_IN_12 0xab
+#define ERASE_12 0xac
#define READ_DVD_STRUCTURE 0xad
#define WRITE_VERIFY_12 0xae
#define VERIFY_12 0xaf
@@ -125,6 +132,7 @@
#define SET_CD_SPEED 0xbb
#define MECHANISM_STATUS 0xbd
#define READ_CD 0xbe
+#define SEND_DVD_STRUCTURE 0xbf
/*
* SERVICE ACTION IN subcodes
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 62f538f4f..673948c51 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -797,7 +797,7 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
break;
}
/* if a geometry hint is available, use it */
- bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs);
+ bdrv_guess_geometry(bdrv, &cylinders, &heads, &secs);
p[2] = (cylinders >> 16) & 0xff;
p[3] = (cylinders >> 8) & 0xff;
p[4] = cylinders & 0xff;
@@ -831,7 +831,7 @@ static int mode_sense_page(SCSIDiskState *s, int page, uint8_t **p_outbuf,
p[2] = 5000 >> 8;
p[3] = 5000 & 0xff;
/* if a geometry hint is available, use it */
- bdrv_get_geometry_hint(bdrv, &cylinders, &heads, &secs);
+ bdrv_guess_geometry(bdrv, &cylinders, &heads, &secs);
p[4] = heads & 0xff;
p[5] = secs & 0xff;
p[6] = s->qdev.blocksize >> 8;
@@ -956,8 +956,9 @@ static int scsi_disk_emulate_mode_sense(SCSIDiskReq *r, uint8_t *outbuf)
p += 8;
}
+ /* MMC prescribes that CD/DVD drives have no block descriptors. */
bdrv_get_geometry(s->qdev.conf.bs, &nb_sectors);
- if (!dbd && nb_sectors) {
+ if (!dbd && s->qdev.type == TYPE_DISK && nb_sectors) {
if (r->req.cmd.buf[0] == MODE_SENSE) {
outbuf[3] = 8; /* Block descriptor length */
} else { /* MODE_SENSE_10 */
@@ -1178,6 +1179,11 @@ static int scsi_disk_emulate_command(SCSIDiskReq *r)
outbuf[7] = 0;
buflen = 8;
break;
+ case REQUEST_SENSE:
+ /* Just return "NO SENSE". */
+ buflen = scsi_build_sense(NULL, 0, outbuf, r->buflen,
+ (req->cmd.buf[1] & 1) == 0);
+ break;
case MECHANISM_STATUS:
buflen = scsi_emulate_mechanism_status(s, outbuf);
if (buflen < 0) {
@@ -1312,6 +1318,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
case GET_EVENT_STATUS_NOTIFICATION:
case MECHANISM_STATUS:
case SERVICE_ACTION_IN_16:
+ case REQUEST_SENSE:
case VERIFY_10:
rc = scsi_disk_emulate_command(r);
if (rc < 0) {
@@ -1374,10 +1381,8 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
goto fail;
}
break;
- case SEEK_6:
case SEEK_10:
- DPRINTF("Seek(%d) (sector %" PRId64 ")\n", command == SEEK_6 ? 6 : 10,
- r->req.cmd.lba);
+ DPRINTF("Seek(10) (sector %" PRId64 ")\n", r->req.cmd.lba);
if (r->req.cmd.lba > s->qdev.max_lba) {
goto illegal_lba;
}
@@ -1408,8 +1413,6 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *buf)
}
break;
- case REQUEST_SENSE:
- abort();
default:
DPRINTF("Unknown SCSI command (%2.2x)\n", buf[0]);
scsi_check_condition(r, SENSE_CODE(INVALID_OPCODE));
@@ -1553,7 +1556,7 @@ static int scsi_initfn(SCSIDevice *dev)
bdrv_set_buffer_alignment(s->qdev.conf.bs, s->qdev.blocksize);
bdrv_iostatus_enable(s->qdev.conf.bs);
- add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, ",0");
+ add_boot_device_path(s->qdev.conf.bootindex, &dev->qdev, NULL);
return 0;
}
@@ -1700,8 +1703,20 @@ static SCSIRequest *scsi_block_new_request(SCSIDevice *d, uint32_t tag,
case WRITE_VERIFY_10:
case WRITE_VERIFY_12:
case WRITE_VERIFY_16:
- return scsi_req_alloc(&scsi_disk_reqops, &s->qdev, tag, lun,
- hba_private);
+ /* MMC writing cannot be done via pread/pwrite, because it sometimes
+ * involves writing beyond the maximum LBA or to negative LBA (lead-in).
+ * And once you do these writes, reading from the block device is
+ * unreliable, too. It is even possible that reads deliver random data
+ * from the host page cache (this is probably a Linux bug).
+ *
+ * We might use scsi_disk_reqops as long as no writing commands are
+ * seen, but performance usually isn't paramount on optical media. So,
+ * just make scsi-block operate the same as scsi-generic for them.
+ */
+ if (s->qdev.type != TYPE_ROM) {
+ return scsi_req_alloc(&scsi_disk_reqops, &s->qdev, tag, lun,
+ hba_private);
+ }
}
return scsi_req_alloc(&scsi_generic_req_ops, &s->qdev, tag, lun,
diff --git a/hw/scsi.h b/hw/scsi.h
index ff8fdd096..61c64d5c7 100644
--- a/hw/scsi.h
+++ b/hw/scsi.h
@@ -179,6 +179,8 @@ extern const struct SCSISense sense_code_DEVICE_INTERNAL_RESET;
#define SENSE_CODE(x) sense_code_ ## x
int scsi_sense_valid(SCSISense sense);
+int scsi_build_sense(uint8_t *in_buf, int in_len,
+ uint8_t *buf, int len, bool fixed);
SCSIRequest *scsi_req_alloc(const SCSIReqOps *reqops, SCSIDevice *d,
uint32_t tag, uint32_t lun, void *hba_private);
diff --git a/hw/spapr.c b/hw/spapr.c
index bdaa938b6..2b901f105 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -57,7 +57,7 @@
#define FW_MAX_SIZE 0x400000
#define FW_FILE_NAME "slof.bin"
-#define MIN_RAM_SLOF 512UL
+#define MIN_RMA_SLOF 128UL
#define TIMEBASE_FREQ 512000000ULL
@@ -407,7 +407,9 @@ static void ppc_spapr_init(ram_addr_t ram_size,
long pteg_shift = 17;
char *filename;
- spapr = g_malloc(sizeof(*spapr));
+ spapr = g_malloc0(sizeof(*spapr));
+ QLIST_INIT(&spapr->phbs);
+
cpu_ppc_hypercall = emulate_spapr_hypercall;
/* Allocate RMA if necessary */
@@ -560,9 +562,9 @@ static void ppc_spapr_init(ram_addr_t ram_size,
spapr->entry_point = KERNEL_LOAD_ADDR;
} else {
- if (ram_size < (MIN_RAM_SLOF << 20)) {
+ if (rma_size < (MIN_RMA_SLOF << 20)) {
fprintf(stderr, "qemu: pSeries SLOF firmware requires >= "
- "%ldM guest RAM\n", MIN_RAM_SLOF);
+ "%ldM guest RMA (Real Mode Area memory)\n", MIN_RMA_SLOF);
exit(1);
}
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, FW_FILE_NAME);
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index 25cfc9d91..2dcc0361e 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -66,11 +66,24 @@ VIOsPAPRDevice *spapr_vio_find_by_reg(VIOsPAPRBus *bus, uint32_t reg)
QTAILQ_FOREACH(qdev, &bus->bus.children, sibling) {
dev = (VIOsPAPRDevice *)qdev;
if (dev->reg == reg) {
- break;
+ return dev;
}
}
- return dev;
+ return NULL;
+}
+
+static char *vio_format_dev_name(VIOsPAPRDevice *dev)
+{
+ VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)dev->qdev.info;
+ char *name;
+
+ /* Device tree style name device@reg */
+ if (asprintf(&name, "%s@%x", info->dt_name, dev->reg) < 0) {
+ return NULL;
+ }
+
+ return name;
}
#ifdef CONFIG_FDT
@@ -78,15 +91,21 @@ static int vio_make_devnode(VIOsPAPRDevice *dev,
void *fdt)
{
VIOsPAPRDeviceInfo *info = (VIOsPAPRDeviceInfo *)dev->qdev.info;
- int vdevice_off, node_off;
- int ret;
+ int vdevice_off, node_off, ret;
+ char *dt_name;
vdevice_off = fdt_path_offset(fdt, "/vdevice");
if (vdevice_off < 0) {
return vdevice_off;
}
- node_off = fdt_add_subnode(fdt, vdevice_off, dev->qdev.id);
+ dt_name = vio_format_dev_name(dev);
+ if (!dt_name) {
+ return -ENOMEM;
+ }
+
+ node_off = fdt_add_subnode(fdt, vdevice_off, dt_name);
+ free(dt_name);
if (node_off < 0) {
return node_off;
}
@@ -608,12 +627,15 @@ static int spapr_vio_busdev_init(DeviceState *qdev, DeviceInfo *qinfo)
VIOsPAPRDevice *dev = (VIOsPAPRDevice *)qdev;
char *id;
- if (asprintf(&id, "%s@%x", info->dt_name, dev->reg) < 0) {
- return -1;
+ /* Don't overwrite ids assigned on the command line */
+ if (!dev->qdev.id) {
+ id = vio_format_dev_name(dev);
+ if (!id) {
+ return -1;
+ }
+ dev->qdev.id = id;
}
- dev->qdev.id = id;
-
dev->qirq = spapr_allocate_irq(dev->vio_irq_num, &dev->vio_irq_num);
if (!dev->qirq) {
return -1;
diff --git a/hw/spapr_vty.c b/hw/spapr_vty.c
index a9d4b035e..f23cc3623 100644
--- a/hw/spapr_vty.c
+++ b/hw/spapr_vty.c
@@ -58,12 +58,20 @@ static int spapr_vty_init(VIOsPAPRDevice *sdev)
{
VIOsPAPRVTYDevice *dev = (VIOsPAPRVTYDevice *)sdev;
+ if (!dev->chardev) {
+ fprintf(stderr, "spapr-vty: Can't create vty without a chardev!\n");
+ exit(1);
+ }
+
qemu_chr_add_handlers(dev->chardev, vty_can_receive,
vty_receive, NULL, dev);
return 0;
}
+/* Forward declaration */
+static VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg);
+
static target_ulong h_put_term_char(CPUState *env, sPAPREnvironment *spapr,
target_ulong opcode, target_ulong *args)
{
@@ -71,9 +79,10 @@ static target_ulong h_put_term_char(CPUState *env, sPAPREnvironment *spapr,
target_ulong len = args[1];
target_ulong char0_7 = args[2];
target_ulong char8_15 = args[3];
- VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+ VIOsPAPRDevice *sdev;
uint8_t buf[16];
+ sdev = vty_lookup(spapr, reg);
if (!sdev) {
return H_PARAMETER;
}
@@ -97,9 +106,10 @@ static target_ulong h_get_term_char(CPUState *env, sPAPREnvironment *spapr,
target_ulong *len = args + 0;
target_ulong *char0_7 = args + 1;
target_ulong *char8_15 = args + 2;
- VIOsPAPRDevice *sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+ VIOsPAPRDevice *sdev;
uint8_t buf[16];
+ sdev = vty_lookup(spapr, reg);
if (!sdev) {
return H_PARAMETER;
}
@@ -140,12 +150,35 @@ static VIOsPAPRDeviceInfo spapr_vty = {
.qdev.name = "spapr-vty",
.qdev.size = sizeof(VIOsPAPRVTYDevice),
.qdev.props = (Property[]) {
- DEFINE_SPAPR_PROPERTIES(VIOsPAPRVTYDevice, sdev, 0, 0),
+ DEFINE_SPAPR_PROPERTIES(VIOsPAPRVTYDevice, sdev, SPAPR_VTY_BASE_ADDRESS, 0),
DEFINE_PROP_CHR("chardev", VIOsPAPRVTYDevice, chardev),
DEFINE_PROP_END_OF_LIST(),
},
};
+static VIOsPAPRDevice *vty_lookup(sPAPREnvironment *spapr, target_ulong reg)
+{
+ VIOsPAPRDevice *sdev;
+
+ sdev = spapr_vio_find_by_reg(spapr->vio_bus, reg);
+ if (!sdev && reg == 0) {
+ DeviceState *qdev;
+
+ /* Hack for kernel early debug, which always specifies reg==0.
+ * We search all VIO devices, and grab the first available vty
+ * device. This attempts to mimic existing PowerVM behaviour
+ * (early debug does work there, despite having no vty with
+ * reg==0. */
+ QTAILQ_FOREACH(qdev, &spapr->vio_bus->bus.children, sibling) {
+ if (qdev->info == &spapr_vty.qdev) {
+ return DO_UPCAST(VIOsPAPRDevice, qdev, qdev);
+ }
+ }
+ }
+
+ return sdev;
+}
+
static void spapr_vty_register(void)
{
spapr_vio_bus_register_withprop(&spapr_vty);
diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index cdd5aae1e..3eea94d09 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -2046,6 +2046,7 @@ static void ehci_advance_state(EHCIState *ehci,
break;
case EST_WRITEBACK:
+ assert(q != NULL);
again = ehci_state_writeback(q, async);
break;
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index b7341778e..68e375678 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -38,6 +38,13 @@ enum USBMSDMode {
USB_MSDM_CSW /* Command Status. */
};
+struct usb_msd_csw {
+ uint32_t sig;
+ uint32_t tag;
+ uint32_t residue;
+ uint8_t status;
+};
+
typedef struct {
USBDevice dev;
enum USBMSDMode mode;
@@ -45,14 +52,13 @@ typedef struct {
uint8_t *scsi_buf;
uint32_t data_len;
uint32_t residue;
- uint32_t tag;
+ struct usb_msd_csw csw;
SCSIRequest *req;
SCSIBus bus;
BlockConf conf;
char *serial;
SCSIDevice *scsi_dev;
uint32_t removable;
- int result;
/* For async completion. */
USBPacket *packet;
} MSDState;
@@ -67,13 +73,6 @@ struct usb_msd_cbw {
uint8_t cmd[16];
};
-struct usb_msd_csw {
- uint32_t sig;
- uint32_t tag;
- uint32_t residue;
- uint8_t status;
-};
-
enum {
STR_MANUFACTURER = 1,
STR_PRODUCT,
@@ -191,17 +190,15 @@ static void usb_msd_copy_data(MSDState *s, USBPacket *p)
static void usb_msd_send_status(MSDState *s, USBPacket *p)
{
- struct usb_msd_csw csw;
int len;
- csw.sig = cpu_to_le32(0x53425355);
- csw.tag = cpu_to_le32(s->tag);
- csw.residue = s->residue;
- csw.status = s->result;
+ DPRINTF("Command status %d tag 0x%x, len %zd\n",
+ s->csw.status, s->csw.tag, p->iov.size);
- len = MIN(sizeof(csw), p->iov.size);
- usb_packet_copy(p, &csw, len);
- p->result = len;
+ assert(s->csw.sig == 0x53425355);
+ len = MIN(sizeof(s->csw), p->iov.size);
+ usb_packet_copy(p, &s->csw, len);
+ memset(&s->csw, 0, sizeof(s->csw));
}
static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len)
@@ -231,9 +228,14 @@ static void usb_msd_command_complete(SCSIRequest *req, uint32_t status)
MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
USBPacket *p = s->packet;
- DPRINTF("Command complete %d\n", status);
+ DPRINTF("Command complete %d tag 0x%x\n", status, req->tag);
s->residue = s->data_len;
- s->result = status != 0;
+
+ s->csw.sig = cpu_to_le32(0x53425355);
+ s->csw.tag = cpu_to_le32(req->tag);
+ s->csw.residue = s->residue;
+ s->csw.status = status != 0;
+
if (s->packet) {
if (s->data_len == 0 && s->mode == USB_MSDM_DATAOUT) {
/* A deferred packet with no write data remaining must be
@@ -334,6 +336,7 @@ static void usb_msd_cancel_io(USBDevice *dev, USBPacket *p)
static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
{
MSDState *s = (MSDState *)dev;
+ uint32_t tag;
int ret = 0;
struct usb_msd_cbw cbw;
uint8_t devep = p->devep;
@@ -360,7 +363,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
fprintf(stderr, "usb-msd: Bad LUN %d\n", cbw.lun);
goto fail;
}
- s->tag = le32_to_cpu(cbw.tag);
+ tag = le32_to_cpu(cbw.tag);
s->data_len = le32_to_cpu(cbw.data_len);
if (s->data_len == 0) {
s->mode = USB_MSDM_CSW;
@@ -370,14 +373,12 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
s->mode = USB_MSDM_DATAOUT;
}
DPRINTF("Command tag 0x%x flags %08x len %d data %d\n",
- s->tag, cbw.flags, cbw.cmd_len, s->data_len);
+ tag, cbw.flags, cbw.cmd_len, s->data_len);
s->residue = 0;
s->scsi_len = 0;
- s->req = scsi_req_new(s->scsi_dev, s->tag, 0, cbw.cmd, NULL);
+ s->req = scsi_req_new(s->scsi_dev, tag, 0, cbw.cmd, NULL);
scsi_req_enqueue(s->req);
- /* ??? Should check that USB and SCSI data transfer
- directions match. */
- if (s->mode != USB_MSDM_CSW && s->residue == 0) {
+ if (s->req && s->req->cmd.xfer != SCSI_XFER_NONE) {
scsi_req_continue(s->req);
}
ret = p->result;
@@ -432,15 +433,19 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
break;
case USB_MSDM_CSW:
- DPRINTF("Command status %d tag 0x%x, len %zd\n",
- s->result, s->tag, p->iov.size);
if (p->iov.size < 13) {
goto fail;
}
- usb_msd_send_status(s, p);
- s->mode = USB_MSDM_CBW;
- ret = 13;
+ if (s->req) {
+ /* still in flight */
+ s->packet = p;
+ ret = USB_RET_ASYNC;
+ } else {
+ usb_msd_send_status(s, p);
+ s->mode = USB_MSDM_CBW;
+ ret = 13;
+ }
break;
case USB_MSDM_DATAIN:
diff --git a/migration.c b/migration.c
index 41c3c24e0..8280d7189 100644
--- a/migration.c
+++ b/migration.c
@@ -89,6 +89,9 @@ void process_incoming_migration(QEMUFile *f)
qemu_announce_self();
DPRINTF("successfully loaded vm state\n");
+ /* Make sure all file formats flush their mutable metadata */
+ bdrv_invalidate_cache_all();
+
if (autostart) {
vm_start();
} else {
@@ -398,6 +401,18 @@ static MigrationState *migrate_init(Monitor *mon, int detach, int blk, int inc)
return s;
}
+static GSList *migration_blockers;
+
+void migrate_add_blocker(Error *reason)
+{
+ migration_blockers = g_slist_prepend(migration_blockers, reason);
+}
+
+void migrate_del_blocker(Error *reason)
+{
+ migration_blockers = g_slist_remove(migration_blockers, reason);
+}
+
int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
MigrationState *s = migrate_get_current();
@@ -417,6 +432,12 @@ int do_migrate(Monitor *mon, const QDict *qdict, QObject **ret_data)
return -1;
}
+ if (migration_blockers) {
+ Error *err = migration_blockers->data;
+ qerror_report_err(err);
+ return -1;
+ }
+
s = migrate_init(mon, detach, blk, inc);
if (strstart(uri, "tcp:", &p)) {
diff --git a/migration.h b/migration.h
index 1b8ee5853..0682179bd 100644
--- a/migration.h
+++ b/migration.h
@@ -17,6 +17,7 @@
#include "qdict.h"
#include "qemu-common.h"
#include "notify.h"
+#include "error.h"
typedef struct MigrationState MigrationState;
@@ -89,4 +90,18 @@ int ram_load(QEMUFile *f, void *opaque, int version_id);
extern int incoming_expected;
+/**
+ * @migrate_add_blocker - prevent migration from proceeding
+ *
+ * @reason - an error to be returned whenever migration is attempted
+ */
+void migrate_add_blocker(Error *reason);
+
+/**
+ * @migrate_del_blocker - remove a blocking error from migration
+ *
+ * @reason - the error blocking migration
+ */
+void migrate_del_blocker(Error *reason);
+
#endif
diff --git a/monitor.c b/monitor.c
index 0b27ca221..f956eb7e8 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4228,9 +4228,9 @@ static void file_completion(const char *input)
/* stat the file to find out if it's a directory.
* In that case add a slash to speed up typing long paths
*/
- stat(file, &sb);
- if(S_ISDIR(sb.st_mode))
+ if (stat(file, &sb) == 0 && S_ISDIR(sb.st_mode)) {
pstrcat(file, sizeof(file), "/");
+ }
readline_add_completion(cur_mon->rs, file);
}
}
diff --git a/qapi/qmp-output-visitor.c b/qapi/qmp-output-visitor.c
index d67724ea4..f76d0159c 100644
--- a/qapi/qmp-output-visitor.c
+++ b/qapi/qmp-output-visitor.c
@@ -190,7 +190,7 @@ static void qmp_output_type_enum(Visitor *v, int *obj, const char *strings[],
assert(strings);
while (strings[i++] != NULL);
- if (value >= i - 1) {
+ if (value < 0 || value >= i - 1) {
error_set(errp, QERR_INVALID_PARAMETER, name ? name : "null");
return;
}
diff --git a/qemu-doc.texi b/qemu-doc.texi
index 149e9bd28..9c3cb62ee 100644
--- a/qemu-doc.texi
+++ b/qemu-doc.texi
@@ -421,6 +421,7 @@ snapshots.
* disk_images_fat_images:: Virtual FAT disk images
* disk_images_nbd:: NBD access
* disk_images_sheepdog:: Sheepdog disk images
+* disk_images_iscsi:: iSCSI LUNs
@end menu
@node disk_images_quickstart
@@ -695,6 +696,61 @@ qemu-img create sheepdog:@var{hostname}:@var{port}:@var{image} @var{size}
qemu sheepdog:@var{hostname}:@var{port}:@var{image}
@end example
+@node disk_images_iscsi
+@subsection iSCSI LUNs
+
+iSCSI is a popular protocol used to access SCSI devices across a computer
+network.
+
+There are two different ways iSCSI devices can be used by QEMU.
+
+The first method is to mount the iSCSI LUN on the host, and make it appear as
+any other ordinary SCSI device on the host and then to access this device as a
+/dev/sd device from QEMU. How to do this differs between host OSes.
+
+The second method involves using the iSCSI initiator that is built into
+QEMU. This provides a mechanism that works the same way regardless of which
+host OS you are running QEMU on. This section will describe this second method
+of using iSCSI together with QEMU.
+
+In QEMU, iSCSI devices are described using special iSCSI URLs
+
+@example
+URL syntax:
+iscsi://[<username>[%<password>]@@]<host>[:<port>]/<target-iqn-name>/<lun>
+@end example
+
+Username and password are optional and only used if your target is set up
+using CHAP authentication for access control.
+Alternatively the username and password can also be set via environment
+variables to have these not show up in the process list
+
+@example
+export LIBISCSI_CHAP_USERNAME=<username>
+export LIBISCSI_CHAP_PASSWORD=<password>
+iscsi://<host>/<target-iqn-name>/<lun>
+@end example
+
+Howto set up a simple iSCSI target on loopback and accessing it via QEMU:
+@example
+This example shows how to set up an iSCSI target with one CDROM and one DISK
+using the Linux STGT software target. This target is available on Red Hat based
+systems as the package 'scsi-target-utils'.
+
+tgtd --iscsi portal=127.0.0.1:3260
+tgtadm --lld iscsi --op new --mode target --tid 1 -T iqn.qemu.test
+tgtadm --lld iscsi --mode logicalunit --op new --tid 1 --lun 1 \
+ -b /IMAGES/disk.img --device-type=disk
+tgtadm --lld iscsi --mode logicalunit --op new --tid 1 --lun 2 \
+ -b /IMAGES/cd.iso --device-type=cd
+tgtadm --lld iscsi --op bind --mode target --tid 1 -I ALL
+
+qemu-system-i386 -boot d -drive file=iscsi://127.0.0.1/iqn.qemu.test/1 \
+ -cdrom iscsi://127.0.0.1/iqn.qemu.test/2
+@end example
+
+
+
@node pcsys_network
@section Network emulation
@@ -1749,7 +1805,7 @@ PC Keyboard
IDE controller
@end itemize
-The mipssim pseudo board emulation provides an environment similiar
+The mipssim pseudo board emulation provides an environment similar
to what the proprietary MIPS emulator uses for running Linux.
It supports:
@@ -2141,7 +2197,7 @@ Xtensa emulator pseudo board "sim"
Avnet LX60/LX110/LX200 board
@end itemize
-The sim pseudo board emulation provides an environment similiar
+The sim pseudo board emulation provides an environment similar
to one provided by the proprietary Tensilica ISS.
It supports:
diff --git a/qemu-tool.c b/qemu-tool.c
index e9f7fe1e1..5df727974 100644
--- a/qemu-tool.c
+++ b/qemu-tool.c
@@ -15,6 +15,7 @@
#include "monitor.h"
#include "qemu-timer.h"
#include "qemu-log.h"
+#include "migration.h"
#include <sys/time.h>
@@ -92,3 +93,11 @@ int64_t qemu_get_clock_ns(QEMUClock *clock)
{
return 0;
}
+
+void migrate_add_blocker(Error *reason)
+{
+}
+
+void migrate_del_blocker(Error *reason)
+{
+}
diff --git a/qerror.c b/qerror.c
index 4b48b3966..fdf62b9e2 100644
--- a/qerror.c
+++ b/qerror.c
@@ -49,6 +49,10 @@ static const QErrorStringTable qerror_table[] = {
.desc = "Device '%(device)' can't go on a %(bad_bus_type) bus",
},
{
+ .error_fmt = QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
+ .desc = "Block format '%(format)' used by device '%(name)' does not support feature '%(feature)'",
+ },
+ {
.error_fmt = QERR_BUS_NOT_FOUND,
.desc = "Bus '%(bus)' not found",
},
@@ -73,6 +77,10 @@ static const QErrorStringTable qerror_table[] = {
.desc = "Device '%(device)' is in use",
},
{
+ .error_fmt = QERR_DEVICE_FEATURE_BLOCKS_MIGRATION,
+ .desc = "Migration is disabled when using feature '%(feature)' in device '%(device)'",
+ },
+ {
.error_fmt = QERR_DEVICE_LOCKED,
.desc = "Device '%(device)' is locked",
},
diff --git a/qerror.h b/qerror.h
index d4bfcfd16..2d3d43bed 100644
--- a/qerror.h
+++ b/qerror.h
@@ -54,6 +54,9 @@ QError *qobject_to_qerror(const QObject *obj);
#define QERR_BAD_BUS_FOR_DEVICE \
"{ 'class': 'BadBusForDevice', 'data': { 'device': %s, 'bad_bus_type': %s } }"
+#define QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED \
+ "{ 'class': 'BlockFormatFeatureNotSupported', 'data': { 'format': %s, 'name': %s, 'feature': %s } }"
+
#define QERR_BUS_NOT_FOUND \
"{ 'class': 'BusNotFound', 'data': { 'bus': %s } }"
@@ -72,6 +75,9 @@ QError *qobject_to_qerror(const QObject *obj);
#define QERR_DEVICE_IN_USE \
"{ 'class': 'DeviceInUse', 'data': { 'device': %s } }"
+#define QERR_DEVICE_FEATURE_BLOCKS_MIGRATION \
+ "{ 'class': 'DeviceFeatureBlocksMigration', 'data': { 'device': %s, 'feature': %s } }"
+
#define QERR_DEVICE_LOCKED \
"{ 'class': 'DeviceLocked', 'data': { 'device': %s } }"
diff --git a/savevm.c b/savevm.c
index bee16c0b7..f53cd4c15 100644
--- a/savevm.c
+++ b/savevm.c
@@ -1255,31 +1255,6 @@ void unregister_savevm(DeviceState *dev, const char *idstr, void *opaque)
}
}
-/* mark a device as not to be migrated, that is the device should be
- unplugged before migration */
-void register_device_unmigratable(DeviceState *dev, const char *idstr,
- void *opaque)
-{
- SaveStateEntry *se;
- char id[256] = "";
-
- if (dev && dev->parent_bus && dev->parent_bus->info->get_dev_path) {
- char *path = dev->parent_bus->info->get_dev_path(dev);
- if (path) {
- pstrcpy(id, sizeof(id), path);
- pstrcat(id, sizeof(id), "/");
- g_free(path);
- }
- }
- pstrcat(id, sizeof(id), idstr);
-
- QTAILQ_FOREACH(se, &savevm_handlers, entry) {
- if (strcmp(se->idstr, id) == 0 && se->opaque == opaque) {
- se->no_migrate = 1;
- }
- }
-}
-
int vmstate_register_with_alias_id(DeviceState *dev, int instance_id,
const VMStateDescription *vmsd,
void *opaque, int alias_id,
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 908099620..d50de9089 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1883,7 +1883,7 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
code);
if (host_supports_vmx() && code == VMX_INVALID_GUEST_STATE) {
fprintf(stderr,
- "\nIf you're runnning a guest on an Intel machine without "
+ "\nIf you're running a guest on an Intel machine without "
"unrestricted mode\n"
"support, the failure can be most likely due to the guest "
"entering an invalid\n"
diff --git a/target-i386/ops_sse.h b/target-i386/ops_sse.h
index aa41d2596..47dde78f8 100644
--- a/target-i386/ops_sse.h
+++ b/target-i386/ops_sse.h
@@ -1996,11 +1996,13 @@ void glue(helper_pcmpestrm, SUFFIX) (Reg *d, Reg *s, uint32_t ctrl)
if ((ctrl >> 6) & 1) {
if (ctrl & 1)
- for (i = 0; i <= 8; i--, res >>= 1)
+ for (i = 0; i < 8; i++, res >>= 1) {
d->W(i) = (res & 1) ? ~0 : 0;
+ }
else
- for (i = 0; i <= 16; i--, res >>= 1)
+ for (i = 0; i < 16; i++, res >>= 1) {
d->B(i) = (res & 1) ? ~0 : 0;
+ }
} else {
d->Q(1) = 0;
d->Q(0) = res;
@@ -2028,11 +2030,13 @@ void glue(helper_pcmpistrm, SUFFIX) (Reg *d, Reg *s, uint32_t ctrl)
if ((ctrl >> 6) & 1) {
if (ctrl & 1)
- for (i = 0; i <= 8; i--, res >>= 1)
+ for (i = 0; i < 8; i++, res >>= 1) {
d->W(i) = (res & 1) ? ~0 : 0;
+ }
else
- for (i = 0; i <= 16; i--, res >>= 1)
+ for (i = 0; i < 16; i++, res >>= 1) {
d->B(i) = (res & 1) ? ~0 : 0;
+ }
} else {
d->Q(1) = 0;
d->Q(0) = res;
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 99e995c7b..66eae3020 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -298,8 +298,10 @@ static inline void gen_debug_exception(DisasContext *ctx)
{
TCGv_i32 t0;
- if (ctx->exception != POWERPC_EXCP_BRANCH)
+ if ((ctx->exception != POWERPC_EXCP_BRANCH) &&
+ (ctx->exception != POWERPC_EXCP_SYNC)) {
gen_update_nip(ctx, ctx->nip);
+ }
t0 = tcg_const_i32(EXCP_DEBUG);
gen_helper_raise_exception(t0);
tcg_temp_free_i32(t0);
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index e192b50c7..202c098ee 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -309,10 +309,21 @@ static inline void kvm_s390_interrupt_internal(CPUState *env, int type,
}
#endif
CPUState *s390_cpu_addr2state(uint16_t cpu_addr);
+void s390_add_running_cpu(CPUState *env);
+unsigned s390_del_running_cpu(CPUState *env);
/* from s390-virtio-bus */
extern const target_phys_addr_t virtio_size;
+#else
+static inline void s390_add_running_cpu(CPUState *env)
+{
+}
+
+static inline unsigned s390_del_running_cpu(CPUState *env)
+{
+ return 0;
+}
#endif
void cpu_lock(void);
void cpu_unlock(void);
@@ -819,6 +830,10 @@ struct sysib_322 {
#define _PAGE_RO 0x200 /* HW read-only bit */
#define _PAGE_INVALID 0x400 /* HW invalid bit */
+#define SK_C (0x1 << 1)
+#define SK_R (0x1 << 2)
+#define SK_F (0x1 << 3)
+#define SK_ACC_MASK (0xf << 4)
/* EBCDIC handling */
diff --git a/target-s390x/helper.c b/target-s390x/helper.c
index 96dd867d7..10cc9dd5f 100644
--- a/target-s390x/helper.c
+++ b/target-s390x/helper.c
@@ -26,6 +26,9 @@
#include "gdbstub.h"
#include "qemu-common.h"
#include "qemu-timer.h"
+#ifndef CONFIG_USER_ONLY
+#include "sysemu.h"
+#endif
//#define DEBUG_S390
//#define DEBUG_S390_PTE
@@ -131,6 +134,7 @@ void cpu_reset(CPUS390XState *env)
memset(env, 0, offsetof(CPUS390XState, breakpoints));
/* FIXME: reset vector? */
tlb_flush(env, 1);
+ s390_add_running_cpu(env);
}
#ifndef CONFIG_USER_ONLY
@@ -348,6 +352,7 @@ int mmu_translate(CPUState *env, target_ulong vaddr, int rw, uint64_t asc,
target_ulong *raddr, int *flags)
{
int r = -1;
+ uint8_t *sk;
*flags = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
vaddr &= TARGET_PAGE_MASK;
@@ -390,6 +395,17 @@ out:
*raddr = *raddr + env->psa;
}
+ if (*raddr <= ram_size) {
+ sk = &env->storage_keys[*raddr / TARGET_PAGE_SIZE];
+ if (*flags & PAGE_READ) {
+ *sk |= SK_R;
+ }
+
+ if (*flags & PAGE_WRITE) {
+ *sk |= SK_C;
+ }
+ }
+
return r;
}
@@ -454,11 +470,15 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong vaddr)
void load_psw(CPUState *env, uint64_t mask, uint64_t addr)
{
if (mask & PSW_MASK_WAIT) {
- env->halted = 1;
- env->exception_index = EXCP_HLT;
if (!(mask & (PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK))) {
- /* XXX disabled wait state - CPU is dead */
+ if (s390_del_running_cpu(env) == 0) {
+#ifndef CONFIG_USER_ONLY
+ qemu_system_shutdown_request();
+#endif
+ }
}
+ env->halted = 1;
+ env->exception_index = EXCP_HLT;
}
env->psw.addr = addr;
@@ -587,6 +607,7 @@ void do_interrupt (CPUState *env)
qemu_log("%s: %d at pc=%" PRIx64 "\n", __FUNCTION__, env->exception_index,
env->psw.addr);
+ s390_add_running_cpu(env);
/* handle external interrupts */
if ((env->psw.mask & PSW_MASK_EXT) &&
env->exception_index == -1) {
diff --git a/target-s390x/helpers.h b/target-s390x/helpers.h
index 6ca48ebe0..01c8d0ea8 100644
--- a/target-s390x/helpers.h
+++ b/target-s390x/helpers.h
@@ -102,6 +102,7 @@ DEF_HELPER_3(madb, void, i32, i64, i32)
DEF_HELPER_3(maebr, void, i32, i32, i32)
DEF_HELPER_3(madbr, void, i32, i32, i32)
DEF_HELPER_3(msdbr, void, i32, i32, i32)
+DEF_HELPER_2(ldeb, void, i32, i64)
DEF_HELPER_2(lxdb, void, i32, i64)
DEF_HELPER_FLAGS_2(tceb, TCG_CALL_PURE, i32, i32, i64)
DEF_HELPER_FLAGS_2(tcdb, TCG_CALL_PURE, i32, i32, i64)
diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 4beb794cc..40b0ab192 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -185,8 +185,7 @@ void kvm_s390_interrupt_internal(CPUState *env, int type, uint32_t parm,
return;
}
- env->halted = 0;
- env->exception_index = -1;
+ s390_add_running_cpu(env);
qemu_cpu_kick(env);
kvmint.type = type;
@@ -299,8 +298,7 @@ static int handle_diag(CPUState *env, struct kvm_run *run, int ipb_code)
static int s390_cpu_restart(CPUState *env)
{
kvm_s390_interrupt(env, KVM_S390_RESTART, 0);
- env->halted = 0;
- env->exception_index = -1;
+ s390_add_running_cpu(env);
qemu_cpu_kick(env);
dprintf("DONE: SIGP cpu restart: %p\n", env);
return 0;
@@ -425,17 +423,16 @@ static int handle_intercept(CPUState *env)
r = handle_instruction(env, run);
break;
case ICPT_WAITPSW:
- /* XXX What to do on system shutdown? */
- env->halted = 1;
- env->exception_index = EXCP_HLT;
+ case ICPT_CPU_STOP:
+ if (s390_del_running_cpu(env) == 0) {
+ qemu_system_shutdown_request();
+ }
+ r = EXCP_HALTED;
break;
case ICPT_SOFT_INTERCEPT:
fprintf(stderr, "KVM unimplemented icpt SOFT\n");
exit(1);
break;
- case ICPT_CPU_STOP:
- qemu_system_shutdown_request();
- break;
case ICPT_IO:
fprintf(stderr, "KVM unimplemented icpt IO\n");
exit(1);
@@ -468,8 +465,6 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
if (ret == 0) {
ret = EXCP_INTERRUPT;
- } else if (ret > 0) {
- ret = 0;
}
return ret;
}
diff --git a/target-s390x/op_helper.c b/target-s390x/op_helper.c
index cd5767815..137bae74a 100644
--- a/target-s390x/op_helper.c
+++ b/target-s390x/op_helper.c
@@ -29,6 +29,10 @@
#include <linux/kvm.h>
#endif
+#if !defined (CONFIG_USER_ONLY)
+#include "sysemu.h"
+#endif
+
/*****************************************************************************/
/* Softmmu support */
#if !defined (CONFIG_USER_ONLY)
@@ -1631,6 +1635,15 @@ void HELPER(maebr)(uint32_t f1, uint32_t f3, uint32_t f2)
&env->fpu_status);
}
+/* convert 32-bit float to 64-bit float */
+void HELPER(ldeb)(uint32_t f1, uint64_t a2)
+{
+ uint32_t v2;
+ v2 = ldl(a2);
+ env->fregs[f1].d = float32_to_float64(v2,
+ &env->fpu_status);
+}
+
/* convert 64-bit float to 128-bit float */
void HELPER(lxdb)(uint32_t f1, uint64_t a2)
{
@@ -2752,7 +2765,6 @@ uint64_t HELPER(iske)(uint64_t r2)
return 0;
}
- /* XXX maybe use qemu's internal keys? */
return env->storage_keys[addr / TARGET_PAGE_SIZE];
}
@@ -2771,14 +2783,15 @@ void HELPER(sske)(uint32_t r1, uint64_t r2)
/* reset reference bit extended */
uint32_t HELPER(rrbe)(uint32_t r1, uint64_t r2)
{
+ uint8_t re;
+ uint8_t key;
if (r2 > ram_size) {
return 0;
}
- /* XXX implement */
-#if 0
- env->storage_keys[r2 / TARGET_PAGE_SIZE] &= ~SK_REFERENCED;
-#endif
+ key = env->storage_keys[r2 / TARGET_PAGE_SIZE];
+ re = key & (SK_R | SK_C);
+ env->storage_keys[r2 / TARGET_PAGE_SIZE] = (key & ~SK_R);
/*
* cc
@@ -2788,7 +2801,8 @@ uint32_t HELPER(rrbe)(uint32_t r1, uint64_t r2)
* 2 Reference bit one; change bit zero
* 3 Reference bit one; change bit one
*/
- return 0;
+
+ return re >> 1;
}
/* compare and swap and purge */
@@ -2891,6 +2905,16 @@ uint32_t HELPER(sigp)(uint64_t order_code, uint32_t r1, uint64_t cpu_addr)
env->regs[r1] &= 0xffffffff00000000ULL;
cc = 1;
break;
+#if !defined (CONFIG_USER_ONLY)
+ case SIGP_RESTART:
+ qemu_system_reset_request();
+ cpu_loop_exit(env);
+ break;
+ case SIGP_STOP:
+ qemu_system_shutdown_request();
+ cpu_loop_exit(env);
+ break;
+#endif
default:
/* unknown sigp */
fprintf(stderr, "XXX unknown sigp: 0x%" PRIx64 "\n", order_code);
@@ -2941,6 +2965,13 @@ void HELPER(ipte)(uint64_t pte_addr, uint64_t vaddr)
/* XXX we exploit the fact that Linux passes the exact virtual
address here - it's not obliged to! */
tlb_flush_page(env, page);
+
+ /* XXX 31-bit hack */
+ if (page & 0x80000000) {
+ tlb_flush_page(env, page & ~0x80000000);
+ } else {
+ tlb_flush_page(env, page | 0x80000000);
+ }
}
/* flush local tlb */
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index 6a22fded5..ee1567218 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -2214,6 +2214,10 @@ static void disas_ed(DisasContext *s, int op, int r1, int x2, int b2, int d2,
addr = get_address(s, x2, b2, d2);
tmp_r1 = tcg_const_i32(r1);
switch (op) {
+ case 0x4: /* LDEB R1,D2(X2,B2) [RXE] */
+ potential_page_fault(s);
+ gen_helper_ldeb(tmp_r1, addr);
+ break;
case 0x5: /* LXDB R1,D2(X2,B2) [RXE] */
potential_page_fault(s);
gen_helper_lxdb(tmp_r1, addr);
diff --git a/target-sparc/helper.c b/target-sparc/helper.c
index 18609c449..037a72ce4 100644
--- a/target-sparc/helper.c
+++ b/target-sparc/helper.c
@@ -34,13 +34,6 @@ void helper_debug(CPUState *env)
cpu_loop_exit(env);
}
-void helper_shutdown(void)
-{
-#if !defined(CONFIG_USER_ONLY)
- qemu_system_shutdown_request();
-#endif
-}
-
#ifdef TARGET_SPARC64
target_ulong helper_popc(target_ulong val)
{
diff --git a/target-sparc/helper.h b/target-sparc/helper.h
index faaf8dc7a..1f67b0806 100644
--- a/target-sparc/helper.h
+++ b/target-sparc/helper.h
@@ -79,7 +79,6 @@ DEF_HELPER_1(fcmpeq_fcc2, void, env)
DEF_HELPER_1(fcmpeq_fcc3, void, env)
#endif
DEF_HELPER_2(raise_exception, void, env, int)
-DEF_HELPER_0(shutdown, void)
#define F_HELPER_0_1(name) DEF_HELPER_1(f ## name, void, env)
DEF_HELPER_3(faddd, f64, env, f64, f64)
diff --git a/target-sparc/int32_helper.c b/target-sparc/int32_helper.c
index 3a749bf5d..ac9d01ecb 100644
--- a/target-sparc/int32_helper.c
+++ b/target-sparc/int32_helper.c
@@ -19,6 +19,7 @@
#include "cpu.h"
#include "trace.h"
+#include "sysemu.h"
//#define DEBUG_PCALL
@@ -100,8 +101,13 @@ void do_interrupt(CPUState *env)
#endif
#if !defined(CONFIG_USER_ONLY)
if (env->psret == 0) {
- cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
- env->exception_index);
+ if (env->exception_index == 0x80 &&
+ env->def->features & CPU_FEATURE_TA0_SHUTDOWN) {
+ qemu_system_shutdown_request();
+ } else {
+ cpu_abort(env, "Trap 0x%02x while interrupts disabled, Error state",
+ env->exception_index);
+ }
return;
}
#endif
diff --git a/target-sparc/translate.c b/target-sparc/translate.c
index 93185402f..d26111209 100644
--- a/target-sparc/translate.c
+++ b/target-sparc/translate.c
@@ -2518,15 +2518,8 @@ static void disas_sparc_insn(DisasContext * dc)
tcg_gen_andi_tl(cpu_dst, cpu_dst, V8_TRAP_MASK);
tcg_gen_addi_tl(cpu_dst, cpu_dst, TT_TRAP);
tcg_gen_trunc_tl_i32(cpu_tmp32, cpu_dst);
+ gen_helper_raise_exception(cpu_env, cpu_tmp32);
- if (rs2 == 0 &&
- dc->def->features & CPU_FEATURE_TA0_SHUTDOWN) {
-
- gen_helper_shutdown();
-
- } else {
- gen_helper_raise_exception(cpu_env, cpu_tmp32);
- }
} else if (cond != 0) {
TCGv r_cond = tcg_temp_new();
int l1;
diff --git a/tcg/arm/tcg-target.c b/tcg/arm/tcg-target.c
index ce4760d23..e05a64f75 100644
--- a/tcg/arm/tcg-target.c
+++ b/tcg/arm/tcg-target.c
@@ -1808,25 +1808,26 @@ static void tcg_target_init(TCGContext *s)
CPU_TEMP_BUF_NLONGS * sizeof(long));
}
-static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg,
- int arg1, tcg_target_long arg2)
+static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
+ TCGReg arg1, tcg_target_long arg2)
{
tcg_out_ld32u(s, COND_AL, arg, arg1, arg2);
}
-static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
- int arg1, tcg_target_long arg2)
+static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
+ TCGReg arg1, tcg_target_long arg2)
{
tcg_out_st32(s, COND_AL, arg, arg1, arg2);
}
-static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
+static inline void tcg_out_mov(TCGContext *s, TCGType type,
+ TCGReg ret, TCGReg arg)
{
tcg_out_dat_reg(s, COND_AL, ARITH_MOV, ret, 0, arg, SHIFT_IMM_LSL(0));
}
static inline void tcg_out_movi(TCGContext *s, TCGType type,
- int ret, tcg_target_long arg)
+ TCGReg ret, tcg_target_long arg)
{
tcg_out_movi32(s, COND_AL, ret, arg);
}
diff --git a/tcg/arm/tcg-target.h b/tcg/arm/tcg-target.h
index 33afd9789..48586c3e6 100644
--- a/tcg/arm/tcg-target.h
+++ b/tcg/arm/tcg-target.h
@@ -27,7 +27,7 @@
#undef TCG_TARGET_WORDS_BIGENDIAN
#undef TCG_TARGET_STACK_GROWSUP
-enum {
+typedef enum {
TCG_REG_R0 = 0,
TCG_REG_R1,
TCG_REG_R2,
@@ -44,7 +44,7 @@ enum {
TCG_REG_R13,
TCG_REG_R14,
TCG_REG_PC,
-};
+} TCGReg;
#define TCG_TARGET_NB_REGS 16
diff --git a/tcg/hppa/tcg-target.c b/tcg/hppa/tcg-target.c
index 71d9677ab..59d4d12ba 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, TCGType type, int ret, int arg)
+static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg 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 */
@@ -349,7 +349,7 @@ static void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
}
static void tcg_out_movi(TCGContext *s, TCGType type,
- int ret, tcg_target_long arg)
+ TCGReg ret, tcg_target_long arg)
{
if (check_fit_tl(arg, 14)) {
tcg_out32(s, INSN_LDO | INSN_R1(ret)
@@ -393,15 +393,15 @@ static void tcg_out_ldst(TCGContext *s, int ret, int addr,
}
/* This function is required by tcg.c. */
-static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
- int arg1, tcg_target_long arg2)
+static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
+ TCGReg arg1, tcg_target_long arg2)
{
tcg_out_ldst(s, ret, arg1, arg2, INSN_LDW);
}
/* This function is required by tcg.c. */
-static inline void tcg_out_st(TCGContext *s, TCGType type, int ret,
- int arg1, tcg_target_long arg2)
+static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg ret,
+ TCGReg arg1, tcg_target_long arg2)
{
tcg_out_ldst(s, ret, arg1, arg2, INSN_STW);
}
diff --git a/tcg/hppa/tcg-target.h b/tcg/hppa/tcg-target.h
index ec9a7bf25..7f3c4cc3e 100644
--- a/tcg/hppa/tcg-target.h
+++ b/tcg/hppa/tcg-target.h
@@ -32,7 +32,7 @@
#define TCG_TARGET_NB_REGS 32
-enum {
+typedef enum {
TCG_REG_R0 = 0,
TCG_REG_R1,
TCG_REG_RP,
@@ -65,7 +65,7 @@ enum {
TCG_REG_RET1,
TCG_REG_SP,
TCG_REG_R31,
-};
+} TCGReg;
#define TCG_CT_CONST_0 0x0100
#define TCG_CT_CONST_S5 0x0200
diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c
index 3069e53bc..dc81572c0 100644
--- a/tcg/i386/tcg-target.c
+++ b/tcg/i386/tcg-target.c
@@ -518,7 +518,8 @@ static inline void tgen_arithr(TCGContext *s, int subop, int dest, int src)
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)
+static inline void tcg_out_mov(TCGContext *s, TCGType type,
+ TCGReg ret, TCGReg arg)
{
if (arg != ret) {
int opc = OPC_MOVL_GvEv + (type == TCG_TYPE_I64 ? P_REXW : 0);
@@ -527,7 +528,7 @@ static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
}
static void tcg_out_movi(TCGContext *s, TCGType type,
- int ret, tcg_target_long arg)
+ TCGReg ret, tcg_target_long arg)
{
if (arg == 0) {
tgen_arithr(s, ARITH_XOR, ret, ret);
@@ -568,15 +569,15 @@ static inline void tcg_out_pop(TCGContext *s, int 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)
+static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
+ TCGReg arg1, tcg_target_long 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)
+static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
+ TCGReg arg1, tcg_target_long arg2)
{
int opc = OPC_MOVL_EvGv + (type == TCG_TYPE_I64 ? P_REXW : 0);
tcg_out_modrm_offset(s, opc, arg, arg1, arg2);
diff --git a/tcg/i386/tcg-target.h b/tcg/i386/tcg-target.h
index b9c9d4e8c..7756e7b03 100644
--- a/tcg/i386/tcg-target.h
+++ b/tcg/i386/tcg-target.h
@@ -36,7 +36,7 @@
# define TCG_TARGET_NB_REGS 8
#endif
-enum {
+typedef enum {
TCG_REG_EAX = 0,
TCG_REG_ECX,
TCG_REG_EDX,
@@ -64,7 +64,7 @@ enum {
TCG_REG_RBP = TCG_REG_EBP,
TCG_REG_RSI = TCG_REG_ESI,
TCG_REG_RDI = TCG_REG_EDI,
-};
+} TCGReg;
#define TCG_CT_CONST_S32 0x100
#define TCG_CT_CONST_U32 0x200
diff --git a/tcg/ia64/tcg-target.c b/tcg/ia64/tcg-target.c
index bb22b9abe..e3de79fdb 100644
--- a/tcg/ia64/tcg-target.c
+++ b/tcg/ia64/tcg-target.c
@@ -830,7 +830,7 @@ static inline void tcg_out_bundle(TCGContext *s, int template,
}
static inline void tcg_out_mov(TCGContext *s, TCGType type,
- TCGArg ret, TCGArg arg)
+ TCGReg ret, TCGReg arg)
{
tcg_out_bundle(s, mmI,
tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
@@ -839,7 +839,7 @@ static inline void tcg_out_mov(TCGContext *s, TCGType type,
}
static inline void tcg_out_movi(TCGContext *s, TCGType type,
- TCGArg reg, tcg_target_long arg)
+ TCGReg reg, tcg_target_long arg)
{
tcg_out_bundle(s, mLX,
tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
@@ -972,8 +972,8 @@ static inline void tcg_out_st_rel(TCGContext *s, uint64_t opc_m4, TCGArg arg,
}
}
-static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGArg arg,
- TCGArg arg1, tcg_target_long arg2)
+static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
+ TCGReg arg1, tcg_target_long arg2)
{
if (type == TCG_TYPE_I32) {
tcg_out_ld_rel(s, OPC_LD4_M1, arg, arg1, arg2);
@@ -982,8 +982,8 @@ static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGArg arg,
}
}
-static inline void tcg_out_st(TCGContext *s, TCGType type, TCGArg arg,
- TCGArg arg1, tcg_target_long arg2)
+static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
+ TCGReg arg1, tcg_target_long arg2)
{
if (type == TCG_TYPE_I32) {
tcg_out_st_rel(s, OPC_ST4_M4, arg, arg1, arg2);
diff --git a/tcg/ia64/tcg-target.h b/tcg/ia64/tcg-target.h
index 578cf2954..c38808900 100644
--- a/tcg/ia64/tcg-target.h
+++ b/tcg/ia64/tcg-target.h
@@ -26,7 +26,7 @@
/* We only map the first 64 registers */
#define TCG_TARGET_NB_REGS 64
-enum {
+typedef enum {
TCG_REG_R0 = 0,
TCG_REG_R1,
TCG_REG_R2,
@@ -91,7 +91,7 @@ enum {
TCG_REG_R61,
TCG_REG_R62,
TCG_REG_R63,
-};
+} TCGReg;
#define TCG_CT_CONST_ZERO 0x100
#define TCG_CT_CONST_S22 0x200
diff --git a/tcg/mips/tcg-target.c b/tcg/mips/tcg-target.c
index a33d21fd0..c5c32825f 100644
--- a/tcg/mips/tcg-target.c
+++ b/tcg/mips/tcg-target.c
@@ -379,13 +379,14 @@ static inline void tcg_out_nop(TCGContext *s)
tcg_out32(s, 0);
}
-static inline void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
+static inline void tcg_out_mov(TCGContext *s, TCGType type,
+ TCGReg ret, TCGReg arg)
{
tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
}
static inline void tcg_out_movi(TCGContext *s, TCGType type,
- int reg, int32_t arg)
+ TCGReg reg, tcg_target_long arg)
{
if (arg == (int16_t)arg) {
tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
@@ -480,14 +481,14 @@ static inline void tcg_out_ldst(TCGContext *s, int opc, int arg,
}
}
-static inline void tcg_out_ld(TCGContext *s, TCGType type, int arg,
- int arg1, tcg_target_long arg2)
+static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
+ TCGReg arg1, tcg_target_long arg2)
{
tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
}
-static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
- int arg1, tcg_target_long arg2)
+static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
+ TCGReg arg1, tcg_target_long arg2)
{
tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
}
diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index e2a2571f9..477bc38b0 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -31,7 +31,7 @@
#define TCG_TARGET_NB_REGS 32
-enum {
+typedef enum {
TCG_REG_ZERO = 0,
TCG_REG_AT,
TCG_REG_V0,
@@ -64,7 +64,7 @@ enum {
TCG_REG_SP,
TCG_REG_FP,
TCG_REG_RA,
-};
+} TCGReg;
#define TCG_CT_CONST_ZERO 0x100
#define TCG_CT_CONST_U16 0x200
diff --git a/tcg/ppc/tcg-target.c b/tcg/ppc/tcg-target.c
index 87cc1177f..f5d9bf3b0 100644
--- a/tcg/ppc/tcg-target.c
+++ b/tcg/ppc/tcg-target.c
@@ -436,13 +436,13 @@ 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, TCGType type, int ret, int arg)
+static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
{
tcg_out32 (s, OR | SAB (arg, ret, arg));
}
static void tcg_out_movi(TCGContext *s, TCGType type,
- int ret, tcg_target_long arg)
+ TCGReg ret, tcg_target_long arg)
{
if (arg == (int16_t) arg)
tcg_out32 (s, ADDI | RT (ret) | RA (0) | (arg & 0xffff));
@@ -961,13 +961,13 @@ static void tcg_target_qemu_prologue (TCGContext *s)
tcg_out32 (s, BCLR | BO_ALWAYS);
}
-static void tcg_out_ld (TCGContext *s, TCGType type, int ret, int arg1,
+static void tcg_out_ld (TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
tcg_target_long arg2)
{
tcg_out_ldst (s, ret, arg1, arg2, LWZ, LWZX);
}
-static void tcg_out_st (TCGContext *s, TCGType type, int arg, int arg1,
+static void tcg_out_st (TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
tcg_target_long arg2)
{
tcg_out_ldst (s, arg, arg1, arg2, STW, STWX);
diff --git a/tcg/ppc/tcg-target.h b/tcg/ppc/tcg-target.h
index 25a6ea4ed..3f22aaac9 100644
--- a/tcg/ppc/tcg-target.h
+++ b/tcg/ppc/tcg-target.h
@@ -26,7 +26,7 @@
#define TCG_TARGET_WORDS_BIGENDIAN
#define TCG_TARGET_NB_REGS 32
-enum {
+typedef enum {
TCG_REG_R0 = 0,
TCG_REG_R1,
TCG_REG_R2,
@@ -59,7 +59,7 @@ enum {
TCG_REG_R29,
TCG_REG_R30,
TCG_REG_R31
-};
+} TCGReg;
/* used for function call generation */
#define TCG_REG_CALL_STACK TCG_REG_R1
diff --git a/tcg/ppc64/tcg-target.c b/tcg/ppc64/tcg-target.c
index 3d24cd4da..44193784f 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, TCGType type, int ret, int arg)
+static void tcg_out_mov (TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
{
tcg_out32 (s, OR | SAB (arg, ret, arg));
}
@@ -459,7 +459,7 @@ static void tcg_out_movi32 (TCGContext *s, int ret, int32_t arg)
}
static void tcg_out_movi (TCGContext *s, TCGType type,
- int ret, tcg_target_long arg)
+ TCGReg ret, tcg_target_long arg)
{
int32_t arg32 = arg;
arg = type == TCG_TYPE_I32 ? arg & 0xffffffff : arg;
@@ -616,18 +616,19 @@ static void tcg_out_tlb_read (TCGContext *s, int r0, int r1, int r2,
static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
{
- int addr_reg, data_reg, r0, r1, rbase, mem_index, s_bits, bswap;
+ int addr_reg, data_reg, r0, r1, rbase, bswap;
#ifdef CONFIG_SOFTMMU
- int r2;
+ int r2, mem_index, s_bits;
void *label1_ptr, *label2_ptr;
#endif
data_reg = *args++;
addr_reg = *args++;
+
+#ifdef CONFIG_SOFTMMU
mem_index = *args;
s_bits = opc & 3;
-#ifdef CONFIG_SOFTMMU
r0 = 3;
r1 = 4;
r2 = 0;
@@ -763,17 +764,18 @@ static void tcg_out_qemu_ld (TCGContext *s, const TCGArg *args, int opc)
static void tcg_out_qemu_st (TCGContext *s, const TCGArg *args, int opc)
{
- int addr_reg, r0, r1, rbase, data_reg, mem_index, bswap;
+ int addr_reg, r0, r1, rbase, data_reg, bswap;
#ifdef CONFIG_SOFTMMU
- int r2;
+ int r2, mem_index;
void *label1_ptr, *label2_ptr;
#endif
data_reg = *args++;
addr_reg = *args++;
- mem_index = *args;
#ifdef CONFIG_SOFTMMU
+ mem_index = *args;
+
r0 = 3;
r1 = 4;
r2 = 0;
@@ -930,7 +932,7 @@ static void tcg_target_qemu_prologue (TCGContext *s)
tcg_out32 (s, BCLR | BO_ALWAYS);
}
-static void tcg_out_ld (TCGContext *s, TCGType type, int ret, int arg1,
+static void tcg_out_ld (TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
tcg_target_long arg2)
{
if (type == TCG_TYPE_I32)
@@ -939,7 +941,7 @@ static void tcg_out_ld (TCGContext *s, TCGType type, int ret, int arg1,
tcg_out_ldsta (s, ret, arg1, arg2, LD, LDX);
}
-static void tcg_out_st (TCGContext *s, TCGType type, int arg, int arg1,
+static void tcg_out_st (TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
tcg_target_long arg2)
{
if (type == TCG_TYPE_I32)
diff --git a/tcg/ppc64/tcg-target.h b/tcg/ppc64/tcg-target.h
index 8d1fb738e..97eec0843 100644
--- a/tcg/ppc64/tcg-target.h
+++ b/tcg/ppc64/tcg-target.h
@@ -26,7 +26,7 @@
#define TCG_TARGET_WORDS_BIGENDIAN
#define TCG_TARGET_NB_REGS 32
-enum {
+typedef enum {
TCG_REG_R0 = 0,
TCG_REG_R1,
TCG_REG_R2,
@@ -59,7 +59,7 @@ enum {
TCG_REG_R29,
TCG_REG_R30,
TCG_REG_R31
-};
+} TCGReg;
/* used for function call generation */
#define TCG_REG_CALL_STACK TCG_REG_R1
diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index fc3fd7ffc..5cd5a3b6f 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -306,7 +306,8 @@ 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, TCGType type, int ret, int arg)
+static inline void tcg_out_mov(TCGContext *s, TCGType type,
+ TCGReg ret, TCGReg arg)
{
tcg_out_arith(s, ret, arg, TCG_REG_G0, ARITH_OR);
}
@@ -333,7 +334,7 @@ static inline void tcg_out_movi_imm32(TCGContext *s, int ret, uint32_t arg)
}
static inline void tcg_out_movi(TCGContext *s, TCGType type,
- int ret, tcg_target_long arg)
+ TCGReg ret, tcg_target_long arg)
{
/* All 32-bit constants, as well as 64-bit constants with
no high bits set go through movi_imm32. */
@@ -398,8 +399,8 @@ static inline void tcg_out_ldst_asi(TCGContext *s, int ret, int addr,
INSN_ASI(asi) | INSN_RS2(addr));
}
-static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
- int arg1, tcg_target_long arg2)
+static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
+ TCGReg arg1, tcg_target_long arg2)
{
if (type == TCG_TYPE_I32)
tcg_out_ldst(s, ret, arg1, arg2, LDUW);
@@ -407,8 +408,8 @@ static inline void tcg_out_ld(TCGContext *s, TCGType type, int ret,
tcg_out_ldst(s, ret, arg1, arg2, LDX);
}
-static inline void tcg_out_st(TCGContext *s, TCGType type, int arg,
- int arg1, tcg_target_long arg2)
+static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
+ TCGReg arg1, tcg_target_long arg2)
{
if (type == TCG_TYPE_I32)
tcg_out_ldst(s, arg, arg1, arg2, STW);
@@ -472,11 +473,9 @@ static inline void tcg_out_nop(TCGContext *s)
static void tcg_out_branch_i32(TCGContext *s, int opc, int label_index)
{
- int32_t val;
TCGLabel *l = &s->labels[label_index];
if (l->has_value) {
- val = l->u.value - (tcg_target_long)s->code_ptr;
tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x2)
| INSN_OFF22(l->u.value - (unsigned long)s->code_ptr)));
} else {
@@ -488,11 +487,9 @@ static void tcg_out_branch_i32(TCGContext *s, int opc, int label_index)
#if TCG_TARGET_REG_BITS == 64
static void tcg_out_branch_i64(TCGContext *s, int opc, int label_index)
{
- int32_t val;
TCGLabel *l = &s->labels[label_index];
if (l->has_value) {
- val = l->u.value - (tcg_target_long)s->code_ptr;
tcg_out32(s, (INSN_OP(0) | INSN_COND(opc, 0) | INSN_OP2(0x1) |
(0x5 << 19) |
INSN_OFF19(l->u.value - (unsigned long)s->code_ptr)));
diff --git a/tcg/sparc/tcg-target.h b/tcg/sparc/tcg-target.h
index 1464ef40c..c3fe13111 100644
--- a/tcg/sparc/tcg-target.h
+++ b/tcg/sparc/tcg-target.h
@@ -27,7 +27,7 @@
#define TCG_TARGET_NB_REGS 32
-enum {
+typedef enum {
TCG_REG_G0 = 0,
TCG_REG_G1,
TCG_REG_G2,
@@ -60,7 +60,7 @@ enum {
TCG_REG_I5,
TCG_REG_I6,
TCG_REG_I7,
-};
+} TCGReg;
#define TCG_CT_CONST_S11 0x100
#define TCG_CT_CONST_S13 0x200
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 6b27d7bfa..77bd6ef74 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -71,14 +71,14 @@ static void patch_reloc(uint8_t *code_ptr, int type,
/* Forward declarations for functions declared and used in tcg-target.c. */
static int target_parse_constraint(TCGArgConstraint *ct, const char **pct_str);
-static void tcg_out_ld(TCGContext *s, TCGType type, int ret, int arg1,
+static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
tcg_target_long arg2);
-static void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg);
+static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg);
static void tcg_out_movi(TCGContext *s, TCGType type,
- int ret, tcg_target_long arg);
+ TCGReg ret, tcg_target_long arg);
static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
const int *const_args);
-static void tcg_out_st(TCGContext *s, TCGType type, int arg, int arg1,
+static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
tcg_target_long arg2);
static int tcg_target_const_match(tcg_target_long val,
const TCGArgConstraint *arg_ct);
diff --git a/tcg/tci/tcg-target.c b/tcg/tci/tcg-target.c
index e373e2a70..942910e14 100644
--- a/tcg/tci/tcg-target.c
+++ b/tcg/tci/tcg-target.c
@@ -495,7 +495,7 @@ static void tci_out_label(TCGContext *s, TCGArg arg)
}
}
-static void tcg_out_ld(TCGContext *s, TCGType type, int ret, int arg1,
+static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg1,
tcg_target_long arg2)
{
uint8_t *old_code_ptr = s->code_ptr;
@@ -519,7 +519,7 @@ static void tcg_out_ld(TCGContext *s, TCGType type, int ret, int arg1,
old_code_ptr[1] = s->code_ptr - old_code_ptr;
}
-static void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
+static void tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
{
uint8_t *old_code_ptr = s->code_ptr;
assert(ret != arg);
@@ -534,7 +534,7 @@ static void tcg_out_mov(TCGContext *s, TCGType type, int ret, int arg)
}
static void tcg_out_movi(TCGContext *s, TCGType type,
- int t0, tcg_target_long arg)
+ TCGReg t0, tcg_target_long arg)
{
uint8_t *old_code_ptr = s->code_ptr;
uint32_t arg32 = arg;
@@ -834,7 +834,7 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg *args,
old_code_ptr[1] = s->code_ptr - old_code_ptr;
}
-static void tcg_out_st(TCGContext *s, TCGType type, int arg, int arg1,
+static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg, TCGReg arg1,
tcg_target_long arg2)
{
uint8_t *old_code_ptr = s->code_ptr;
diff --git a/tcg/tci/tcg-target.h b/tcg/tci/tcg-target.h
index 81ded8695..cb5858c9c 100644
--- a/tcg/tci/tcg-target.h
+++ b/tcg/tci/tcg-target.h
@@ -150,7 +150,7 @@ typedef enum {
#endif
/* Special value UINT8_MAX is used by TCI to encode constant values. */
TCG_CONST = UINT8_MAX
-} TCGRegister;
+} TCGReg;
void tci_disas(uint8_t opc);
diff --git a/tci.c b/tci.c
index f17785dc9..a20a7142e 100644
--- a/tci.c
+++ b/tci.c
@@ -63,90 +63,90 @@ void *tci_tb_ptr;
static tcg_target_ulong tci_reg[TCG_TARGET_NB_REGS];
-static tcg_target_ulong tci_read_reg(TCGRegister index)
+static tcg_target_ulong tci_read_reg(TCGReg index)
{
assert(index < ARRAY_SIZE(tci_reg));
return tci_reg[index];
}
#if TCG_TARGET_HAS_ext8s_i32 || TCG_TARGET_HAS_ext8s_i64
-static int8_t tci_read_reg8s(TCGRegister index)
+static int8_t tci_read_reg8s(TCGReg index)
{
return (int8_t)tci_read_reg(index);
}
#endif
#if TCG_TARGET_HAS_ext16s_i32 || TCG_TARGET_HAS_ext16s_i64
-static int16_t tci_read_reg16s(TCGRegister index)
+static int16_t tci_read_reg16s(TCGReg index)
{
return (int16_t)tci_read_reg(index);
}
#endif
#if TCG_TARGET_REG_BITS == 64
-static int32_t tci_read_reg32s(TCGRegister index)
+static int32_t tci_read_reg32s(TCGReg index)
{
return (int32_t)tci_read_reg(index);
}
#endif
-static uint8_t tci_read_reg8(TCGRegister index)
+static uint8_t tci_read_reg8(TCGReg index)
{
return (uint8_t)tci_read_reg(index);
}
-static uint16_t tci_read_reg16(TCGRegister index)
+static uint16_t tci_read_reg16(TCGReg index)
{
return (uint16_t)tci_read_reg(index);
}
-static uint32_t tci_read_reg32(TCGRegister index)
+static uint32_t tci_read_reg32(TCGReg index)
{
return (uint32_t)tci_read_reg(index);
}
#if TCG_TARGET_REG_BITS == 64
-static uint64_t tci_read_reg64(TCGRegister index)
+static uint64_t tci_read_reg64(TCGReg index)
{
return tci_read_reg(index);
}
#endif
-static void tci_write_reg(TCGRegister index, tcg_target_ulong value)
+static void tci_write_reg(TCGReg index, tcg_target_ulong value)
{
assert(index < ARRAY_SIZE(tci_reg));
assert(index != TCG_AREG0);
tci_reg[index] = value;
}
-static void tci_write_reg8s(TCGRegister index, int8_t value)
+static void tci_write_reg8s(TCGReg index, int8_t value)
{
tci_write_reg(index, value);
}
-static void tci_write_reg16s(TCGRegister index, int16_t value)
+static void tci_write_reg16s(TCGReg index, int16_t value)
{
tci_write_reg(index, value);
}
#if TCG_TARGET_REG_BITS == 64
-static void tci_write_reg32s(TCGRegister index, int32_t value)
+static void tci_write_reg32s(TCGReg index, int32_t value)
{
tci_write_reg(index, value);
}
#endif
-static void tci_write_reg8(TCGRegister index, uint8_t value)
+static void tci_write_reg8(TCGReg index, uint8_t value)
{
tci_write_reg(index, value);
}
-static void tci_write_reg16(TCGRegister index, uint16_t value)
+static void tci_write_reg16(TCGReg index, uint16_t value)
{
tci_write_reg(index, value);
}
-static void tci_write_reg32(TCGRegister index, uint32_t value)
+static void tci_write_reg32(TCGReg index, uint32_t value)
{
tci_write_reg(index, value);
}
@@ -159,7 +159,7 @@ static void tci_write_reg64(uint32_t high_index, uint32_t low_index,
tci_write_reg(high_index, value >> 32);
}
#elif TCG_TARGET_REG_BITS == 64
-static void tci_write_reg64(TCGRegister index, uint64_t value)
+static void tci_write_reg64(TCGReg index, uint64_t value)
{
tci_write_reg(index, value);
}
@@ -290,7 +290,7 @@ static target_ulong tci_read_ulong(uint8_t **tb_ptr)
static tcg_target_ulong tci_read_ri(uint8_t **tb_ptr)
{
tcg_target_ulong value;
- TCGRegister r = **tb_ptr;
+ TCGReg r = **tb_ptr;
*tb_ptr += 1;
if (r == TCG_CONST) {
value = tci_read_i(tb_ptr);
@@ -304,7 +304,7 @@ static tcg_target_ulong tci_read_ri(uint8_t **tb_ptr)
static uint32_t tci_read_ri32(uint8_t **tb_ptr)
{
uint32_t value;
- TCGRegister r = **tb_ptr;
+ TCGReg r = **tb_ptr;
*tb_ptr += 1;
if (r == TCG_CONST) {
value = tci_read_i32(tb_ptr);
@@ -326,7 +326,7 @@ static uint64_t tci_read_ri64(uint8_t **tb_ptr)
static uint64_t tci_read_ri64(uint8_t **tb_ptr)
{
uint64_t value;
- TCGRegister r = **tb_ptr;
+ TCGReg r = **tb_ptr;
*tb_ptr += 1;
if (r == TCG_CONST) {
value = tci_read_i64(tb_ptr);
diff --git a/usb-linux.c b/usb-linux.c
index f086d57ed..d4426ea73 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -1568,7 +1568,12 @@ static int usb_host_scan_dev(void *opaque, USBScanFunc *func)
if (line[0] == 'T' && line[1] == ':') {
if (device_count && (vendor_id || product_id)) {
/* New device. Add the previously discovered device. */
- ret = func(opaque, bus_num, addr, 0, class_id, vendor_id,
+ if (port > 0) {
+ snprintf(buf, sizeof(buf), "%d", port);
+ } else {
+ snprintf(buf, sizeof(buf), "?");
+ }
+ ret = func(opaque, bus_num, addr, buf, class_id, vendor_id,
product_id, product_name, speed);
if (ret) {
goto the_end;