Compare commits
74 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
40897c9c16 | ||
|
3439eec34f | ||
|
40d6444e91 | ||
|
ff51a738cf | ||
|
ae392c416c | ||
|
9a93b61730 | ||
|
50322249fd | ||
|
2923d34fdc | ||
|
930b588395 | ||
|
f565403949 | ||
|
1ed520c66e | ||
|
06d9260ffa | ||
|
0f15423c32 | ||
|
38e0735eb7 | ||
|
fa2756b71b | ||
|
a3baf1be67 | ||
|
1571b6cba2 | ||
|
0cd0fd0867 | ||
|
b246721614 | ||
|
5931065907 | ||
|
414c460431 | ||
|
7b863f41de | ||
|
92a114f6f8 | ||
|
e04da7c3d1 | ||
|
bc4268998d | ||
|
725e14e91f | ||
|
96d922a654 | ||
|
9643c25f8d | ||
|
b08d26b76d | ||
|
25cc4a768d | ||
|
05a86f23e5 | ||
|
54dcd0b37e | ||
|
7197390a0b | ||
|
15d4a72338 | ||
|
1e34d859d0 | ||
|
3feef8ad17 | ||
|
5afdec404e | ||
|
57285302af | ||
|
5435352ce6 | ||
|
92c93a816a | ||
|
33ebad1263 | ||
|
f3b338ef4a | ||
|
0fd76ff40b | ||
|
06b863577e | ||
|
00a01ad47a | ||
|
2c20ae11ad | ||
|
245d004947 | ||
|
7082826eb4 | ||
|
00984e3953 | ||
|
1b14254b48 | ||
|
b1beac3db2 | ||
|
599825c565 | ||
|
611b727374 | ||
|
54d50be688 | ||
|
c951d9a675 | ||
|
e6d89f8c25 | ||
|
126197214e | ||
|
4238e26416 | ||
|
b5e4946f96 | ||
|
326384d5b6 | ||
|
2a534aff30 | ||
|
771142c2a7 | ||
|
ef81522bc1 | ||
|
854e42f3e8 | ||
|
13449a6e0e | ||
|
e9d86b760c | ||
|
1864b94abb | ||
|
17bb18ce16 | ||
|
b995913853 | ||
|
09ed75f784 | ||
|
27b5979d9d | ||
|
ee2b399463 | ||
|
9df3b45dd4 | ||
|
d43b45e220 |
47
Makefile
47
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 \
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
|
16
block.c
16
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;
|
||||
|
4
block.h
4
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);
|
||||
|
@@ -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,
|
||||
};
|
||||
|
@@ -125,6 +125,8 @@ typedef struct BDRVQcowState {
|
||||
int snapshots_size;
|
||||
int nb_snapshots;
|
||||
QCowSnapshot *snapshots;
|
||||
|
||||
int flags;
|
||||
} BDRVQcowState;
|
||||
|
||||
/* XXX: use std qcow open function ? */
|
||||
|
10
block/qed.c
10
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);
|
||||
|
||||
|
@@ -164,6 +164,8 @@ typedef struct {
|
||||
|
||||
/* Periodic flush and clear need check flag */
|
||||
QEMUTimer *need_check_timer;
|
||||
|
||||
Error *migration_blocker;
|
||||
} BDRVQEDState;
|
||||
|
||||
enum {
|
||||
|
@@ -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')
|
||||
|
@@ -87,6 +87,11 @@ struct BlockDriver {
|
||||
int coroutine_fn (*bdrv_co_discard)(BlockDriverState *bs,
|
||||
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()).
|
||||
|
67
configure
vendored
67
configure
vendored
@@ -172,7 +172,7 @@ aix="no"
|
||||
blobs="yes"
|
||||
pkgversion=""
|
||||
check_utests=""
|
||||
user_pie="no"
|
||||
pie=""
|
||||
zero_malloc=""
|
||||
trace_backend="nop"
|
||||
trace_file="trace"
|
||||
@@ -701,9 +701,9 @@ for opt do
|
||||
;;
|
||||
--disable-guest-base) guest_base="no"
|
||||
;;
|
||||
--enable-user-pie) user_pie="yes"
|
||||
--enable-pie) pie="yes"
|
||||
;;
|
||||
--disable-user-pie) user_pie="no"
|
||||
--disable-pie) pie="no"
|
||||
;;
|
||||
--enable-uname-release=*) uname_release="$optarg"
|
||||
;;
|
||||
@@ -1031,8 +1031,8 @@ echo " --disable-bsd-user disable all BSD usermode emulation targets"
|
||||
echo " --enable-guest-base enable GUEST_BASE support for usermode"
|
||||
echo " emulation targets"
|
||||
echo " --disable-guest-base disable GUEST_BASE support"
|
||||
echo " --enable-user-pie build usermode emulation targets as PIE"
|
||||
echo " --disable-user-pie do not build usermode emulation targets as PIE"
|
||||
echo " --enable-pie build Position Independent Executables"
|
||||
echo " --disable-pie do not build Position Independent Executables"
|
||||
echo " --fmod-lib path to FMOD library"
|
||||
echo " --fmod-inc path to FMOD includes"
|
||||
echo " --oss-lib path to OSS library"
|
||||
@@ -1099,6 +1099,47 @@ for flag in $gcc_flags; do
|
||||
fi
|
||||
done
|
||||
|
||||
if test "$static" = "yes" ; then
|
||||
if test "$pie" = "yes" ; then
|
||||
echo "static and pie are mutually incompatible"
|
||||
exit 1
|
||||
else
|
||||
pie="no"
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "$pie" = ""; then
|
||||
case "$cpu-$targetos" in
|
||||
i386-Linux|x86_64-Linux)
|
||||
;;
|
||||
*)
|
||||
pie="no"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
if test "$pie" != "no" ; then
|
||||
cat > $TMPC << EOF
|
||||
int main(void) { return 0; }
|
||||
EOF
|
||||
if compile_prog "-fPIE -DPIE" "-pie"; then
|
||||
QEMU_CFLAGS="-fPIE -DPIE $QEMU_CFLAGS"
|
||||
LDFLAGS="-pie $LDFLAGS"
|
||||
pie="yes"
|
||||
if compile_prog "" "-Wl,-z,relro -Wl,-z,now" ; then
|
||||
LDFLAGS="-Wl,-z,relro -Wl,-z,now $LDFLAGS"
|
||||
fi
|
||||
else
|
||||
if test "$pie" = "yes"; then
|
||||
echo "PIE not available due to missing toolchain support"
|
||||
exit 1
|
||||
else
|
||||
echo "Disabling PIE due to missing toolchain support"
|
||||
pie="no"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
#
|
||||
# Solaris specific configure tool chain decisions
|
||||
#
|
||||
@@ -2200,7 +2241,7 @@ cat > $TMPC << EOF
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int efd = eventfd(0, 0);
|
||||
int efd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
|
||||
return 0;
|
||||
}
|
||||
EOF
|
||||
@@ -2765,7 +2806,7 @@ echo "Documentation $docs"
|
||||
echo "uname -r $uname_release"
|
||||
echo "NPTL support $nptl"
|
||||
echo "GUEST_BASE $guest_base"
|
||||
echo "PIE user targets $user_pie"
|
||||
echo "PIE $pie"
|
||||
echo "vde support $vde"
|
||||
echo "Linux AIO support $linux_aio"
|
||||
echo "ATTR/XATTR support $attr"
|
||||
@@ -3225,9 +3266,6 @@ for d in libdis libdis-user; do
|
||||
symlink $source_path/Makefile.dis $d/Makefile
|
||||
echo > $d/config.mak
|
||||
done
|
||||
if test "$static" = "no" -a "$user_pie" = "yes" ; then
|
||||
echo "QEMU_CFLAGS+=-fpie" > libdis-user/config.mak
|
||||
fi
|
||||
|
||||
for target in $target_list; do
|
||||
target_dir="$target"
|
||||
@@ -3646,12 +3684,6 @@ if test "$target_softmmu" = "yes" ; then
|
||||
esac
|
||||
fi
|
||||
|
||||
if test "$target_user_only" = "yes" -a "$static" = "no" -a \
|
||||
"$user_pie" = "yes" ; then
|
||||
cflags="-fpie $cflags"
|
||||
ldflags="-pie $ldflags"
|
||||
fi
|
||||
|
||||
if test "$target_softmmu" = "yes" -a \( \
|
||||
"$TARGET_ARCH" = "microblaze" -o \
|
||||
"$TARGET_ARCH" = "cris" \) ; then
|
||||
@@ -3775,9 +3807,6 @@ d=libuser
|
||||
mkdir -p $d
|
||||
mkdir -p $d/trace
|
||||
symlink $source_path/Makefile.user $d/Makefile
|
||||
if test "$static" = "no" -a "$user_pie" = "yes" ; then
|
||||
echo "QEMU_CFLAGS+=-fpie" > $d/config.mak
|
||||
fi
|
||||
|
||||
if test "$docs" = "yes" ; then
|
||||
mkdir -p QMP
|
||||
|
@@ -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,
|
||||
|
@@ -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.
|
||||
|
||||
|
14
gdbstub.c
14
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;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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) {
|
||||
|
@@ -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 },
|
||||
|
14
hw/ivshmem.c
14
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;
|
||||
@@ -694,7 +699,7 @@ static int pci_ivshmem_init(PCIDevice *dev)
|
||||
s->peers = g_malloc0(s->nb_peers * sizeof(Peer));
|
||||
|
||||
pci_register_bar(&s->dev, 2,
|
||||
PCI_BASE_ADDRESS_SPACE_MEMORY, &s->ivshmem);
|
||||
PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar);
|
||||
|
||||
s->eventfd_chr = g_malloc0(s->vectors * sizeof(CharDriverState *));
|
||||
|
||||
@@ -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);
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
48
hw/msix.c
48
hw/msix.c
@@ -79,6 +79,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;
|
||||
}
|
||||
|
||||
@@ -117,50 +118,64 @@ 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)
|
||||
static bool msix_vector_masked(PCIDevice *dev, int vector, bool fmask)
|
||||
{
|
||||
return dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] & MSIX_MASKALL_MASK;
|
||||
unsigned offset = vector * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL;
|
||||
return fmask || dev->msix_table_page[offset] & PCI_MSIX_ENTRY_CTRL_MASKBIT;
|
||||
}
|
||||
|
||||
static int msix_is_masked(PCIDevice *dev, int vector)
|
||||
static bool msix_is_masked(PCIDevice *dev, int vector)
|
||||
{
|
||||
unsigned offset =
|
||||
vector * PCI_MSIX_ENTRY_SIZE + PCI_MSIX_ENTRY_VECTOR_CTRL;
|
||||
return msix_function_masked(dev) ||
|
||||
dev->msix_table_page[offset] & PCI_MSIX_ENTRY_CTRL_MASKBIT;
|
||||
return msix_vector_masked(dev, vector, dev->msix_function_masked);
|
||||
}
|
||||
|
||||
static void msix_handle_mask_update(PCIDevice *dev, int vector)
|
||||
static void msix_handle_mask_update(PCIDevice *dev, int vector, bool was_masked)
|
||||
{
|
||||
if (!msix_is_masked(dev, vector) && msix_is_pending(dev, vector)) {
|
||||
bool is_masked = msix_is_masked(dev, vector);
|
||||
if (is_masked == was_masked) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_masked && msix_is_pending(dev, vector)) {
|
||||
msix_clr_pending(dev, vector);
|
||||
msix_notify(dev, 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;
|
||||
}
|
||||
|
||||
for (vector = 0; vector < dev->msix_entries_nr; ++vector) {
|
||||
msix_handle_mask_update(dev, vector);
|
||||
msix_handle_mask_update(dev, vector,
|
||||
msix_vector_masked(dev, vector, was_masked));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,8 +185,16 @@ static void msix_mmio_write(void *opaque, target_phys_addr_t addr,
|
||||
PCIDevice *dev = opaque;
|
||||
unsigned int offset = addr & (MSIX_PAGE_SIZE - 1) & ~0x3;
|
||||
int vector = offset / PCI_MSIX_ENTRY_SIZE;
|
||||
bool was_masked;
|
||||
|
||||
/* MSI-X page includes a read-only PBA and a writeable Vector Control. */
|
||||
if (vector >= dev->msix_entries_nr) {
|
||||
return;
|
||||
}
|
||||
|
||||
was_masked = msix_is_masked(dev, vector);
|
||||
pci_set_long(dev->msix_table_page + offset, val);
|
||||
msix_handle_mask_update(dev, vector);
|
||||
msix_handle_mask_update(dev, vector, was_masked);
|
||||
}
|
||||
|
||||
static const MemoryRegionOps msix_mmio_ops = {
|
||||
@@ -300,6 +323,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? */
|
||||
|
2
hw/pci.h
2
hw/pci.h
@@ -178,6 +178,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;
|
||||
|
||||
|
@@ -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 */
|
||||
|
128
hw/scsi-bus.c
128
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);
|
||||
|
@@ -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
|
||||
|
@@ -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,
|
||||
|
@@ -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);
|
||||
|
10
hw/spapr.c
10
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);
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
||||
|
65
hw/usb-msd.c
65
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:
|
||||
|
21
migration.c
21
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)) {
|
||||
|
15
migration.h
15
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
|
||||
|
@@ -4207,9 +4207,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);
|
||||
}
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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:
|
||||
|
||||
|
@@ -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)
|
||||
{
|
||||
}
|
||||
|
8
qerror.c
8
qerror.c
@@ -48,6 +48,10 @@ static const QErrorStringTable qerror_table[] = {
|
||||
.error_fmt = QERR_BAD_BUS_FOR_DEVICE,
|
||||
.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",
|
||||
@@ -72,6 +76,10 @@ static const QErrorStringTable qerror_table[] = {
|
||||
.error_fmt = QERR_DEVICE_IN_USE,
|
||||
.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",
|
||||
|
6
qerror.h
6
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 } }"
|
||||
|
||||
|
25
savevm.c
25
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,
|
||||
|
@@ -1845,7 +1845,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"
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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 */
|
||||
|
@@ -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) {
|
||||
if (!(mask & (PSW_MASK_IO | PSW_MASK_EXT | PSW_MASK_MCHECK))) {
|
||||
if (s390_del_running_cpu(env) == 0) {
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
qemu_system_shutdown_request();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
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 */
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@@ -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)
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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 */
|
||||
|
@@ -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);
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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)));
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
||||
|
38
tci.c
38
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);
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user