Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1c8a881daa | ||
|
|
9b12940858 | ||
|
|
d8e1f214a0 | ||
|
|
85e83264b2 | ||
|
|
7e62255a4b | ||
|
|
aea317aaa5 | ||
|
|
023ddd7431 | ||
|
|
eba90e4efc | ||
|
|
e36b369577 | ||
|
|
45009a3087 | ||
|
|
961b42b9dc | ||
|
|
c03417b438 | ||
|
|
8dddfb5531 | ||
|
|
21d4a791da | ||
|
|
c1b71a1df6 | ||
|
|
99f08100cd | ||
|
|
65f9d98673 | ||
|
|
f76e4c7f16 | ||
|
|
a425d23f8f | ||
|
|
2507718baf | ||
|
|
51711aee8c | ||
|
|
c16ada980f | ||
|
|
ad0c93328d | ||
|
|
ae0f940e6b | ||
|
|
13bd0b5026 | ||
|
|
f04303743a | ||
|
|
684a7a7459 | ||
|
|
a1fd24af4d | ||
|
|
bc75c9e50d | ||
|
|
14f40fdc98 | ||
|
|
61669f9a83 | ||
|
|
0fdd2e1d06 | ||
|
|
c7662daaa2 | ||
|
|
5bb1cbac4f | ||
|
|
6ac5f3881f | ||
|
|
3397f0cb48 | ||
|
|
612ff3d887 | ||
|
|
2bc3166c22 | ||
|
|
fc9d106c8d | ||
|
|
fd9f102c3e | ||
|
|
335b8d2068 | ||
|
|
aac882e7ce | ||
|
|
20d183b6f0 | ||
|
|
be85c90b74 | ||
|
|
4abf12f4ea | ||
|
|
be35cbbc88 | ||
|
|
f462141f18 | ||
|
|
2af2a1b8d0 | ||
|
|
e30e5eb613 | ||
|
|
c3fecea50d | ||
|
|
28b77657cf | ||
|
|
795928f61d | ||
|
|
ce4e7e4661 | ||
|
|
3a395142ba | ||
|
|
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 |
No files matched your search
+10
@@ -485,6 +485,11 @@ S: Maintained
|
||||
F: trace/
|
||||
T: git://repo.or.cz/qemu/stefanha.git tracing
|
||||
|
||||
Checkpatch
|
||||
M: Blue Swirl <blauwirbel@gmail.com>
|
||||
S: Odd Fixes
|
||||
F: scripts/checkpatch.pl
|
||||
|
||||
Usermode Emulation
|
||||
------------------
|
||||
BSD user
|
||||
@@ -554,3 +559,8 @@ SPARC target
|
||||
M: Blue Swirl <blauwirbel@gmail.com>
|
||||
S: Maintained
|
||||
F: tcg/sparc/
|
||||
|
||||
TCI target
|
||||
M: Stefan Weil <sw@weilnetz.de>
|
||||
S: Maintained
|
||||
F: tcg/tci
|
||||
@@ -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.
|
||||
@@ -167,38 +168,38 @@ check-qjson: check-qjson.o $(qobject-obj-y) $(tools-obj-y)
|
||||
test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y) $(tools-obj-y)
|
||||
|
||||
$(qapi-obj-y): $(GENERATED_HEADERS)
|
||||
qapi-dir := qapi-generated
|
||||
qapi-dir := $(BUILD_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 \
|
||||
|
||||
+2
-4
@@ -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;
|
||||
}
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "module.h"
|
||||
#include <zlib.h>
|
||||
#include "aes.h"
|
||||
#include "migration.h"
|
||||
|
||||
/**************************************************************/
|
||||
/* QEMU COW block driver with compression and encryption support */
|
||||
@@ -74,6 +75,7 @@ typedef struct BDRVQcowState {
|
||||
AES_KEY aes_encrypt_key;
|
||||
AES_KEY aes_decrypt_key;
|
||||
CoMutex lock;
|
||||
Error *migration_blocker;
|
||||
} BDRVQcowState;
|
||||
|
||||
static int decompress_cluster(BlockDriverState *bs, uint64_t cluster_offset);
|
||||
@@ -160,6 +162,12 @@ static int qcow_open(BlockDriverState *bs, int flags)
|
||||
bs->backing_file[len] = '\0';
|
||||
}
|
||||
|
||||
/* Disable migration when qcow images are used */
|
||||
error_set(&s->migration_blocker,
|
||||
QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
|
||||
"qcow", bs->device_name, "live migration");
|
||||
migrate_add_blocker(s->migration_blocker);
|
||||
|
||||
qemu_co_mutex_init(&s->lock);
|
||||
return 0;
|
||||
|
||||
@@ -604,10 +612,14 @@ static int qcow_co_writev(BlockDriverState *bs, int64_t sector_num,
|
||||
static void qcow_close(BlockDriverState *bs)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
|
||||
g_free(s->l1_table);
|
||||
g_free(s->l2_cache);
|
||||
g_free(s->cluster_cache);
|
||||
g_free(s->cluster_data);
|
||||
|
||||
migrate_del_blocker(s->migration_blocker);
|
||||
error_free(s->migration_blocker);
|
||||
}
|
||||
|
||||
static int qcow_create(const char *filename, QEMUOptionParameter *options)
|
||||
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
@@ -1116,6 +1116,7 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
|
||||
/* send a header */
|
||||
ret = do_write(s->fd, &hdr, sizeof(hdr));
|
||||
if (ret) {
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
error_report("failed to send a req, %s", strerror(errno));
|
||||
return -EIO;
|
||||
}
|
||||
@@ -1123,6 +1124,7 @@ static int coroutine_fn add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
|
||||
if (wlen) {
|
||||
ret = do_writev(s->fd, iov, wlen, aio_req->iov_offset);
|
||||
if (ret) {
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
error_report("failed to send a data, %s", strerror(errno));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
+15
@@ -52,6 +52,7 @@
|
||||
#include "qemu-common.h"
|
||||
#include "block_int.h"
|
||||
#include "module.h"
|
||||
#include "migration.h"
|
||||
|
||||
#if defined(CONFIG_UUID)
|
||||
#include <uuid/uuid.h>
|
||||
@@ -203,6 +204,8 @@ typedef struct {
|
||||
uint32_t bmap_sector;
|
||||
/* VDI header (converted to host endianness). */
|
||||
VdiHeader header;
|
||||
|
||||
Error *migration_blocker;
|
||||
} BDRVVdiState;
|
||||
|
||||
/* Change UUID from little endian (IPRT = VirtualBox format) to big endian
|
||||
@@ -454,6 +457,12 @@ static int vdi_open(BlockDriverState *bs, int flags)
|
||||
goto fail_free_bmap;
|
||||
}
|
||||
|
||||
/* Disable migration when vdi images are used */
|
||||
error_set(&s->migration_blocker,
|
||||
QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
|
||||
"vdi", bs->device_name, "live migration");
|
||||
migrate_add_blocker(s->migration_blocker);
|
||||
|
||||
return 0;
|
||||
|
||||
fail_free_bmap:
|
||||
@@ -939,6 +948,12 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options)
|
||||
|
||||
static void vdi_close(BlockDriverState *bs)
|
||||
{
|
||||
BDRVVdiState *s = bs->opaque;
|
||||
|
||||
g_free(s->bmap);
|
||||
|
||||
migrate_del_blocker(s->migration_blocker);
|
||||
error_free(s->migration_blocker);
|
||||
}
|
||||
|
||||
static coroutine_fn int vdi_co_flush(BlockDriverState *bs)
|
||||
|
||||
+16
-2
@@ -26,7 +26,8 @@
|
||||
#include "qemu-common.h"
|
||||
#include "block_int.h"
|
||||
#include "module.h"
|
||||
#include "zlib.h"
|
||||
#include "migration.h"
|
||||
#include <zlib.h>
|
||||
|
||||
#define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D')
|
||||
#define VMDK4_MAGIC (('K' << 24) | ('D' << 16) | ('M' << 8) | 'V')
|
||||
@@ -97,6 +98,7 @@ typedef struct BDRVVmdkState {
|
||||
int num_extents;
|
||||
/* Extent array with num_extents entries, ascend ordered by address */
|
||||
VmdkExtent *extents;
|
||||
Error *migration_blocker;
|
||||
} BDRVVmdkState;
|
||||
|
||||
typedef struct VmdkMetaData {
|
||||
@@ -659,7 +661,14 @@ static int vmdk_open(BlockDriverState *bs, int flags)
|
||||
}
|
||||
s->parent_cid = vmdk_read_cid(bs, 1);
|
||||
qemu_co_mutex_init(&s->lock);
|
||||
return ret;
|
||||
|
||||
/* Disable migration when VMDK images are used */
|
||||
error_set(&s->migration_blocker,
|
||||
QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
|
||||
"vmdk", bs->device_name, "live migration");
|
||||
migrate_add_blocker(s->migration_blocker);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
vmdk_free_extents(bs);
|
||||
@@ -1504,7 +1513,12 @@ exit:
|
||||
|
||||
static void vmdk_close(BlockDriverState *bs)
|
||||
{
|
||||
BDRVVmdkState *s = bs->opaque;
|
||||
|
||||
vmdk_free_extents(bs);
|
||||
|
||||
migrate_del_blocker(s->migration_blocker);
|
||||
error_free(s->migration_blocker);
|
||||
}
|
||||
|
||||
static coroutine_fn int vmdk_co_flush(BlockDriverState *bs)
|
||||
|
||||
+17
-1
@@ -25,6 +25,7 @@
|
||||
#include "qemu-common.h"
|
||||
#include "block_int.h"
|
||||
#include "module.h"
|
||||
#include "migration.h"
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
@@ -128,6 +129,8 @@ typedef struct BDRVVPCState {
|
||||
|
||||
uint64_t last_bitmap;
|
||||
#endif
|
||||
|
||||
Error *migration_blocker;
|
||||
} BDRVVPCState;
|
||||
|
||||
static uint32_t vpc_checksum(uint8_t* buf, size_t size)
|
||||
@@ -228,6 +231,13 @@ static int vpc_open(BlockDriverState *bs, int flags)
|
||||
#endif
|
||||
|
||||
qemu_co_mutex_init(&s->lock);
|
||||
|
||||
/* Disable migration when VHD images are used */
|
||||
error_set(&s->migration_blocker,
|
||||
QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
|
||||
"vpc", bs->device_name, "live migration");
|
||||
migrate_add_blocker(s->migration_blocker);
|
||||
|
||||
return 0;
|
||||
fail:
|
||||
return err;
|
||||
@@ -352,8 +362,11 @@ static int64_t alloc_block(BlockDriverState* bs, int64_t sector_num)
|
||||
|
||||
// Initialize the block's bitmap
|
||||
memset(bitmap, 0xff, s->bitmap_size);
|
||||
bdrv_pwrite_sync(bs->file, s->free_data_block_offset, bitmap,
|
||||
ret = bdrv_pwrite_sync(bs->file, s->free_data_block_offset, bitmap,
|
||||
s->bitmap_size);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Write new footer (the old one will be overwritten)
|
||||
s->free_data_block_offset += s->block_size + s->bitmap_size;
|
||||
@@ -651,6 +664,9 @@ static void vpc_close(BlockDriverState *bs)
|
||||
#ifdef CACHE
|
||||
g_free(s->pageentry_u8);
|
||||
#endif
|
||||
|
||||
migrate_del_blocker(s->migration_blocker);
|
||||
error_free(s->migration_blocker);
|
||||
}
|
||||
|
||||
static QEMUOptionParameter vpc_create_options[] = {
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "qemu-common.h"
|
||||
#include "block_int.h"
|
||||
#include "module.h"
|
||||
#include "migration.h"
|
||||
|
||||
#ifndef S_IWGRP
|
||||
#define S_IWGRP 0
|
||||
@@ -350,6 +351,8 @@ typedef struct BDRVVVFATState {
|
||||
array_t commits;
|
||||
const char* path;
|
||||
int downcase_short_names;
|
||||
|
||||
Error *migration_blocker;
|
||||
} BDRVVVFATState;
|
||||
|
||||
/* take the sector position spos and convert it to Cylinder/Head/Sector position
|
||||
@@ -1073,6 +1076,15 @@ DLOG(if (stderr == NULL) {
|
||||
|
||||
// assert(is_consistent(s));
|
||||
qemu_co_mutex_init(&s->lock);
|
||||
|
||||
/* Disable migration when vvfat is used rw */
|
||||
if (s->qcow) {
|
||||
error_set(&s->migration_blocker,
|
||||
QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED,
|
||||
"vvfat (rw)", bs->device_name, "live migration");
|
||||
migrate_add_blocker(s->migration_blocker);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2829,6 +2841,11 @@ static void vvfat_close(BlockDriverState *bs)
|
||||
array_free(&(s->directory));
|
||||
array_free(&(s->mapping));
|
||||
g_free(s->cluster_buffer);
|
||||
|
||||
if (s->qcow) {
|
||||
migrate_del_blocker(s->migration_blocker);
|
||||
error_free(s->migration_blocker);
|
||||
}
|
||||
}
|
||||
|
||||
static BlockDriver bdrv_vvfat = {
|
||||
|
||||
@@ -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()).
|
||||
|
||||
@@ -172,7 +172,7 @@ aix="no"
|
||||
blobs="yes"
|
||||
pkgversion=""
|
||||
check_utests=""
|
||||
user_pie="no"
|
||||
pie=""
|
||||
zero_malloc=""
|
||||
trace_backend="nop"
|
||||
trace_file="trace"
|
||||
@@ -569,6 +569,14 @@ for opt do
|
||||
;;
|
||||
--sysconfdir=*) sysconfdir="$optarg"
|
||||
;;
|
||||
--sbindir=*|--libexecdir=*|--sharedstatedir=*|--localstatedir=*|\
|
||||
--oldincludedir=*|--datarootdir=*|--infodir=*|--localedir=*|\
|
||||
--htmldir=*|--dvidir=*|--pdfdir=*|--psdir=*)
|
||||
# These switches are silently ignored, for compatibility with
|
||||
# autoconf-generated configure scripts. This allows QEMU's
|
||||
# configure to be used by RPM and similar macros that set
|
||||
# lots of directory switches by default.
|
||||
;;
|
||||
--disable-sdl) sdl="no"
|
||||
;;
|
||||
--enable-sdl) sdl="yes"
|
||||
@@ -701,9 +709,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"
|
||||
;;
|
||||
@@ -759,8 +767,6 @@ for opt do
|
||||
;;
|
||||
--enable-opengl) opengl="yes"
|
||||
;;
|
||||
--*dir)
|
||||
;;
|
||||
--disable-rbd) rbd="no"
|
||||
;;
|
||||
--enable-rbd) rbd="yes"
|
||||
@@ -1031,8 +1037,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 +1105,57 @@ 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
|
||||
|
||||
#ifdef __linux__
|
||||
# define THREAD __thread
|
||||
#else
|
||||
# define THREAD
|
||||
#endif
|
||||
|
||||
static THREAD int tls_var;
|
||||
|
||||
int main(void) { return tls_var; }
|
||||
|
||||
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 +2257,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 +2822,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 +3282,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 +3700,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 +3823,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
|
||||
|
||||
@@ -315,19 +315,34 @@ int fcntl_setfl(int fd, int flag)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int64_t suffix_mul(char suffix, int64_t unit)
|
||||
{
|
||||
switch (qemu_toupper(suffix)) {
|
||||
case STRTOSZ_DEFSUFFIX_B:
|
||||
return 1;
|
||||
case STRTOSZ_DEFSUFFIX_KB:
|
||||
return unit;
|
||||
case STRTOSZ_DEFSUFFIX_MB:
|
||||
return unit * unit;
|
||||
case STRTOSZ_DEFSUFFIX_GB:
|
||||
return unit * unit * unit;
|
||||
case STRTOSZ_DEFSUFFIX_TB:
|
||||
return unit * unit * unit * unit;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert string to bytes, allowing either B/b for bytes, K/k for KB,
|
||||
* M/m for MB, G/g for GB or T/t for TB. Default without any postfix
|
||||
* is MB. End pointer will be returned in *end, if not NULL. A valid
|
||||
* value must be terminated by whitespace, ',' or '\0'. Return -1 on
|
||||
* error.
|
||||
* M/m for MB, G/g for GB or T/t for TB. End pointer will be returned
|
||||
* in *end, if not NULL. Return -1 on error.
|
||||
*/
|
||||
int64_t strtosz_suffix_unit(const char *nptr, char **end,
|
||||
const char default_suffix, int64_t unit)
|
||||
{
|
||||
int64_t retval = -1;
|
||||
char *endptr;
|
||||
unsigned char c, d;
|
||||
unsigned char c;
|
||||
int mul_required = 0;
|
||||
double val, mul, integral, fraction;
|
||||
|
||||
@@ -340,58 +355,16 @@ int64_t strtosz_suffix_unit(const char *nptr, char **end,
|
||||
if (fraction != 0) {
|
||||
mul_required = 1;
|
||||
}
|
||||
/*
|
||||
* Any whitespace character is fine for terminating the number,
|
||||
* in addition we accept ',' to handle strings where the size is
|
||||
* part of a multi token argument.
|
||||
*/
|
||||
c = *endptr;
|
||||
d = c;
|
||||
if (qemu_isspace(c) || c == '\0' || c == ',') {
|
||||
c = 0;
|
||||
if (default_suffix) {
|
||||
d = default_suffix;
|
||||
} else {
|
||||
d = c;
|
||||
}
|
||||
}
|
||||
switch (qemu_toupper(d)) {
|
||||
case STRTOSZ_DEFSUFFIX_B:
|
||||
mul = 1;
|
||||
if (mul_required) {
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
case STRTOSZ_DEFSUFFIX_KB:
|
||||
mul = unit;
|
||||
break;
|
||||
case 0:
|
||||
if (mul_required) {
|
||||
goto fail;
|
||||
}
|
||||
case STRTOSZ_DEFSUFFIX_MB:
|
||||
mul = unit * unit;
|
||||
break;
|
||||
case STRTOSZ_DEFSUFFIX_GB:
|
||||
mul = unit * unit * unit;
|
||||
break;
|
||||
case STRTOSZ_DEFSUFFIX_TB:
|
||||
mul = unit * unit * unit * unit;
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
/*
|
||||
* If not terminated by whitespace, ',', or \0, increment endptr
|
||||
* to point to next character, then check that we are terminated
|
||||
* by an appropriate separating character, ie. whitespace, ',', or
|
||||
* \0. If not, we are seeing trailing garbage, thus fail.
|
||||
*/
|
||||
if (c != 0) {
|
||||
mul = suffix_mul(c, unit);
|
||||
if (mul >= 0) {
|
||||
endptr++;
|
||||
if (!qemu_isspace(*endptr) && *endptr != ',' && *endptr != 0) {
|
||||
goto fail;
|
||||
}
|
||||
} else {
|
||||
mul = suffix_mul(default_suffix, unit);
|
||||
assert(mul >= 0);
|
||||
}
|
||||
if (mul == 1 && mul_required) {
|
||||
goto fail;
|
||||
}
|
||||
if ((val * mul >= INT64_MAX) || val < 0) {
|
||||
goto fail;
|
||||
|
||||
+10
-10
@@ -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.
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -583,8 +583,7 @@ static int local_utimensat(FsContext *s, V9fsPath *fs_path,
|
||||
char buffer[PATH_MAX];
|
||||
char *path = fs_path->data;
|
||||
|
||||
return qemu_utimensat(AT_FDCWD, rpath(s, path, buffer), buf,
|
||||
AT_SYMLINK_NOFOLLOW);
|
||||
return qemu_utimens(rpath(s, path, buffer), buf);
|
||||
}
|
||||
|
||||
static int local_remove(FsContext *ctx, const char *path)
|
||||
@@ -694,6 +693,7 @@ static int local_ioc_getversion(FsContext *ctx, V9fsPath *path,
|
||||
mode_t st_mode, uint64_t *st_gen)
|
||||
{
|
||||
int err;
|
||||
#ifdef FS_IOC_GETVERSION
|
||||
V9fsFidOpenState fid_open;
|
||||
|
||||
/*
|
||||
@@ -709,15 +709,22 @@ static int local_ioc_getversion(FsContext *ctx, V9fsPath *path,
|
||||
}
|
||||
err = ioctl(fid_open.fd, FS_IOC_GETVERSION, st_gen);
|
||||
local_close(ctx, &fid_open);
|
||||
#else
|
||||
err = -ENOTTY;
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
static int local_init(FsContext *ctx)
|
||||
{
|
||||
int err;
|
||||
int err = 0;
|
||||
struct statfs stbuf;
|
||||
|
||||
ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT;
|
||||
#ifdef FS_IOC_GETVERSION
|
||||
/*
|
||||
* use ioc_getversion only if the iocl is definied
|
||||
*/
|
||||
err = statfs(ctx->fs_root, &stbuf);
|
||||
if (!err) {
|
||||
switch (stbuf.f_type) {
|
||||
@@ -729,6 +736,7 @@ static int local_init(FsContext *ctx)
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -150,6 +150,7 @@ static void ccid_card_vscard_handle_message(PassthruState *card,
|
||||
error_report("ATR size exceeds spec, ignoring");
|
||||
ccid_card_vscard_send_error(card, scr_msg_header->reader_id,
|
||||
VSC_GENERAL_ERROR);
|
||||
break;
|
||||
}
|
||||
memcpy(card->atr, data, scr_msg_header->length);
|
||||
card->atr_length = scr_msg_header->length;
|
||||
|
||||
+9
-1
@@ -976,7 +976,15 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
|
||||
case CU_STATSADDR:
|
||||
/* Load dump counters address. */
|
||||
s->statsaddr = e100_read_reg4(s, SCBPointer);
|
||||
TRACE(OTHER, logout("val=0x%02x (status address)\n", val));
|
||||
TRACE(OTHER, logout("val=0x%02x (dump counters address)\n", val));
|
||||
if (s->statsaddr & 3) {
|
||||
/* Memory must be Dword aligned. */
|
||||
logout("unaligned dump counters address\n");
|
||||
/* Handling of misaligned addresses is undefined.
|
||||
* Here we align the address by ignoring the lower bits. */
|
||||
/* TODO: Test unaligned dump counter address on real hardware. */
|
||||
s->statsaddr &= ~3;
|
||||
}
|
||||
break;
|
||||
case CU_SHOWSTATS:
|
||||
/* Dump statistical counters. */
|
||||
|
||||
+8
-12
@@ -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 },
|
||||
|
||||
+12
-2
@@ -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);
|
||||
|
||||
+5
-4
@@ -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;
|
||||
|
||||
|
||||
+2
-2
@@ -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
-1
@@ -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
|
||||
|
||||
@@ -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
-1
@@ -91,7 +91,8 @@ static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
|
||||
*/
|
||||
dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1);
|
||||
dinfo->bus = scsibus->busnr;
|
||||
scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit, false);
|
||||
scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo->bdrv, dinfo->unit,
|
||||
false, -1);
|
||||
if (!scsidev) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
+1
-13
@@ -1971,7 +1971,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s)
|
||||
cplus_tx_ring_desc += 16 * descriptor;
|
||||
|
||||
DPRINTF("+++ C+ mode reading TX descriptor %d from host memory at "
|
||||
"%08x0x%08x = 0x"DMA_ADDR_FMT"\n", descriptor, s->TxAddr[1],
|
||||
"%08x %08x = 0x"DMA_ADDR_FMT"\n", descriptor, s->TxAddr[1],
|
||||
s->TxAddr[0], cplus_tx_ring_desc);
|
||||
|
||||
uint32_t val, txdw0,txdw1,txbufLO,txbufHI;
|
||||
@@ -2713,8 +2713,6 @@ static void rtl8139_io_writeb(void *opaque, uint8_t addr, uint32_t val)
|
||||
{
|
||||
RTL8139State *s = opaque;
|
||||
|
||||
addr &= 0xff;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case MAC0 ... MAC0+5:
|
||||
@@ -2800,8 +2798,6 @@ static void rtl8139_io_writew(void *opaque, uint8_t addr, uint32_t val)
|
||||
{
|
||||
RTL8139State *s = opaque;
|
||||
|
||||
addr &= 0xfe;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case IntrMask:
|
||||
@@ -2900,8 +2896,6 @@ static void rtl8139_io_writel(void *opaque, uint8_t addr, uint32_t val)
|
||||
{
|
||||
RTL8139State *s = opaque;
|
||||
|
||||
addr &= 0xfc;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case RxMissed:
|
||||
@@ -2969,8 +2963,6 @@ static uint32_t rtl8139_io_readb(void *opaque, uint8_t addr)
|
||||
RTL8139State *s = opaque;
|
||||
int ret;
|
||||
|
||||
addr &= 0xff;
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case MAC0 ... MAC0+5:
|
||||
@@ -3043,8 +3035,6 @@ static uint32_t rtl8139_io_readw(void *opaque, uint8_t addr)
|
||||
RTL8139State *s = opaque;
|
||||
uint32_t ret;
|
||||
|
||||
addr &= 0xfe; /* mask lower bit */
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case IntrMask:
|
||||
@@ -3120,8 +3110,6 @@ static uint32_t rtl8139_io_readl(void *opaque, uint8_t addr)
|
||||
RTL8139State *s = opaque;
|
||||
uint32_t ret;
|
||||
|
||||
addr &= 0xfc; /* also mask low 2 bits */
|
||||
|
||||
switch (addr)
|
||||
{
|
||||
case RxMissed:
|
||||
|
||||
@@ -254,10 +254,7 @@ void s390_virtio_device_update_status(VirtIOS390Device *dev)
|
||||
/* Update guest supported feature bitmap */
|
||||
|
||||
features = bswap32(ldl_be_phys(dev->feat_offs));
|
||||
if (vdev->set_features) {
|
||||
vdev->set_features(vdev, features);
|
||||
}
|
||||
vdev->guest_features = features;
|
||||
virtio_set_features(vdev, features);
|
||||
}
|
||||
|
||||
VirtIOS390Device *s390_virtio_bus_console(VirtIOS390Bus *bus)
|
||||
|
||||
+44
-3
@@ -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 */
|
||||
|
||||
+114
-23
@@ -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",
|
||||
@@ -164,7 +162,7 @@ void scsi_qdev_register(SCSIDeviceInfo *info)
|
||||
|
||||
/* handle legacy '-drive if=scsi,...' cmd line args */
|
||||
SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
|
||||
int unit, bool removable)
|
||||
int unit, bool removable, int bootindex)
|
||||
{
|
||||
const char *driver;
|
||||
DeviceState *dev;
|
||||
@@ -172,6 +170,9 @@ SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
|
||||
driver = bdrv_is_sg(bdrv) ? "scsi-generic" : "scsi-disk";
|
||||
dev = qdev_create(&bus->qbus, driver);
|
||||
qdev_prop_set_uint32(dev, "scsi-id", unit);
|
||||
if (bootindex >= 0) {
|
||||
qdev_prop_set_int32(dev, "bootindex", bootindex);
|
||||
}
|
||||
if (qdev_prop_exists(dev, "removable")) {
|
||||
qdev_prop_set_bit(dev, "removable", removable);
|
||||
}
|
||||
@@ -197,7 +198,7 @@ int scsi_bus_legacy_handle_cmdline(SCSIBus *bus)
|
||||
continue;
|
||||
}
|
||||
qemu_opts_loc_restore(dinfo->opts);
|
||||
if (!scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false)) {
|
||||
if (!scsi_bus_legacy_add_drive(bus, dinfo->bdrv, unit, false, -1)) {
|
||||
res = -1;
|
||||
break;
|
||||
}
|
||||
@@ -502,7 +503,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 +650,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 +692,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 +707,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 +718,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 +727,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 +745,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 +770,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 +818,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 +837,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 +885,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 +913,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 +1114,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 +1142,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 +1179,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 +1193,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 +1202,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,8 +1370,8 @@ 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),
|
||||
d->channel, d->id, d->lun);
|
||||
snprintf(path, sizeof(path), "channel@%x/%s@%x,%x", d->channel,
|
||||
qdev_fw_name(dev), d->id, d->lun);
|
||||
|
||||
return strdup(path);
|
||||
}
|
||||
|
||||
+9
-1
@@ -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
|
||||
|
||||
+26
-11
@@ -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,
|
||||
|
||||
@@ -413,6 +413,10 @@ static int scsi_generic_initfn(SCSIDevice *s)
|
||||
/* define device state */
|
||||
s->type = scsiid.scsi_type;
|
||||
DPRINTF("device type %d\n", s->type);
|
||||
if (s->type == TYPE_DISK || s->type == TYPE_ROM) {
|
||||
add_boot_device_path(s->conf.bootindex, &s->qdev, NULL);
|
||||
}
|
||||
|
||||
switch (s->type) {
|
||||
case TYPE_TAPE:
|
||||
s->blocksize = get_stream_blocksize(s->conf.bs);
|
||||
@@ -459,6 +463,7 @@ static SCSIRequest *scsi_new_request(SCSIDevice *d, uint32_t tag, uint32_t lun,
|
||||
|
||||
static SCSIDeviceInfo scsi_generic_info = {
|
||||
.qdev.name = "scsi-generic",
|
||||
.qdev.fw_name = "disk",
|
||||
.qdev.desc = "pass through generic scsi device (/dev/sg*)",
|
||||
.qdev.size = sizeof(SCSIDevice),
|
||||
.qdev.reset = scsi_generic_reset,
|
||||
|
||||
@@ -128,7 +128,7 @@ static inline SCSIBus *scsi_bus_from_device(SCSIDevice *d)
|
||||
}
|
||||
|
||||
SCSIDevice *scsi_bus_legacy_add_drive(SCSIBus *bus, BlockDriverState *bdrv,
|
||||
int unit, bool removable);
|
||||
int unit, bool removable, int bootindex);
|
||||
int scsi_bus_legacy_handle_cmdline(SCSIBus *bus);
|
||||
|
||||
/*
|
||||
@@ -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);
|
||||
|
||||
+6
-4
@@ -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);
|
||||
|
||||
+31
-9
@@ -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;
|
||||
|
||||
+36
-3
@@ -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);
|
||||
|
||||
+1
-3
@@ -131,9 +131,7 @@ static void syborg_virtio_writel(void *opaque, target_phys_addr_t offset,
|
||||
}
|
||||
switch (offset >> 2) {
|
||||
case SYBORG_VIRTIO_GUEST_FEATURES:
|
||||
if (vdev->set_features)
|
||||
vdev->set_features(vdev, value);
|
||||
vdev->guest_features = value;
|
||||
virtio_set_features(vdev, value);
|
||||
break;
|
||||
case SYBORG_VIRTIO_QUEUE_BASE:
|
||||
if (value == 0)
|
||||
|
||||
@@ -528,6 +528,9 @@ USBDevice *usb_bt_init(HCIInfo *hci)
|
||||
if (!hci)
|
||||
return NULL;
|
||||
dev = usb_create_simple(NULL /* FIXME */, "usb-bt-dongle");
|
||||
if (!dev) {
|
||||
return NULL;
|
||||
}
|
||||
s = DO_UPCAST(struct USBBtState, dev, dev);
|
||||
s->dev.opaque = s;
|
||||
|
||||
|
||||
+24
-5
@@ -9,6 +9,7 @@ static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);
|
||||
|
||||
static char *usb_get_dev_path(DeviceState *dev);
|
||||
static char *usb_get_fw_dev_path(DeviceState *qdev);
|
||||
static int usb_qdev_exit(DeviceState *qdev);
|
||||
|
||||
static struct BusInfo usb_bus_info = {
|
||||
.name = "USB",
|
||||
@@ -75,12 +76,23 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
|
||||
dev->auto_attach = 1;
|
||||
QLIST_INIT(&dev->strings);
|
||||
rc = usb_claim_port(dev);
|
||||
if (rc == 0) {
|
||||
rc = dev->info->init(dev);
|
||||
if (rc != 0) {
|
||||
goto err;
|
||||
}
|
||||
if (rc == 0 && dev->auto_attach) {
|
||||
rc = dev->info->init(dev);
|
||||
if (rc != 0) {
|
||||
goto err;
|
||||
}
|
||||
if (dev->auto_attach) {
|
||||
rc = usb_device_attach(dev);
|
||||
if (rc != 0) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
err:
|
||||
usb_qdev_exit(qdev);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -139,10 +151,17 @@ USBDevice *usb_create(USBBus *bus, const char *name)
|
||||
USBDevice *usb_create_simple(USBBus *bus, const char *name)
|
||||
{
|
||||
USBDevice *dev = usb_create(bus, name);
|
||||
int rc;
|
||||
|
||||
if (!dev) {
|
||||
hw_error("Failed to create USB device '%s'\n", name);
|
||||
error_report("Failed to create USB device '%s'\n", name);
|
||||
return NULL;
|
||||
}
|
||||
rc = qdev_init(&dev->qdev);
|
||||
if (rc < 0) {
|
||||
error_report("Failed to initialize USB device '%s'\n", name);
|
||||
return NULL;
|
||||
}
|
||||
qdev_init_nofail(&dev->qdev);
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
+31
-28
@@ -437,37 +437,39 @@ struct EHCIState {
|
||||
} while(0)
|
||||
|
||||
static const char *ehci_state_names[] = {
|
||||
[ EST_INACTIVE ] = "INACTIVE",
|
||||
[ EST_ACTIVE ] = "ACTIVE",
|
||||
[ EST_EXECUTING ] = "EXECUTING",
|
||||
[ EST_SLEEPING ] = "SLEEPING",
|
||||
[ EST_WAITLISTHEAD ] = "WAITLISTHEAD",
|
||||
[ EST_FETCHENTRY ] = "FETCH ENTRY",
|
||||
[ EST_FETCHQH ] = "FETCH QH",
|
||||
[ EST_FETCHITD ] = "FETCH ITD",
|
||||
[ EST_ADVANCEQUEUE ] = "ADVANCEQUEUE",
|
||||
[ EST_FETCHQTD ] = "FETCH QTD",
|
||||
[ EST_EXECUTE ] = "EXECUTE",
|
||||
[ EST_WRITEBACK ] = "WRITEBACK",
|
||||
[ EST_HORIZONTALQH ] = "HORIZONTALQH",
|
||||
[EST_INACTIVE] = "INACTIVE",
|
||||
[EST_ACTIVE] = "ACTIVE",
|
||||
[EST_EXECUTING] = "EXECUTING",
|
||||
[EST_SLEEPING] = "SLEEPING",
|
||||
[EST_WAITLISTHEAD] = "WAITLISTHEAD",
|
||||
[EST_FETCHENTRY] = "FETCH ENTRY",
|
||||
[EST_FETCHQH] = "FETCH QH",
|
||||
[EST_FETCHITD] = "FETCH ITD",
|
||||
[EST_ADVANCEQUEUE] = "ADVANCEQUEUE",
|
||||
[EST_FETCHQTD] = "FETCH QTD",
|
||||
[EST_EXECUTE] = "EXECUTE",
|
||||
[EST_WRITEBACK] = "WRITEBACK",
|
||||
[EST_HORIZONTALQH] = "HORIZONTALQH",
|
||||
};
|
||||
|
||||
static const char *ehci_mmio_names[] = {
|
||||
[ CAPLENGTH ] = "CAPLENGTH",
|
||||
[ HCIVERSION ] = "HCIVERSION",
|
||||
[ HCSPARAMS ] = "HCSPARAMS",
|
||||
[ HCCPARAMS ] = "HCCPARAMS",
|
||||
[ USBCMD ] = "USBCMD",
|
||||
[ USBSTS ] = "USBSTS",
|
||||
[ USBINTR ] = "USBINTR",
|
||||
[ FRINDEX ] = "FRINDEX",
|
||||
[ PERIODICLISTBASE ] = "P-LIST BASE",
|
||||
[ ASYNCLISTADDR ] = "A-LIST ADDR",
|
||||
[ PORTSC_BEGIN ] = "PORTSC #0",
|
||||
[ PORTSC_BEGIN + 4] = "PORTSC #1",
|
||||
[ PORTSC_BEGIN + 8] = "PORTSC #2",
|
||||
[ PORTSC_BEGIN + 12] = "PORTSC #3",
|
||||
[ CONFIGFLAG ] = "CONFIGFLAG",
|
||||
[CAPLENGTH] = "CAPLENGTH",
|
||||
[HCIVERSION] = "HCIVERSION",
|
||||
[HCSPARAMS] = "HCSPARAMS",
|
||||
[HCCPARAMS] = "HCCPARAMS",
|
||||
[USBCMD] = "USBCMD",
|
||||
[USBSTS] = "USBSTS",
|
||||
[USBINTR] = "USBINTR",
|
||||
[FRINDEX] = "FRINDEX",
|
||||
[PERIODICLISTBASE] = "P-LIST BASE",
|
||||
[ASYNCLISTADDR] = "A-LIST ADDR",
|
||||
[PORTSC_BEGIN] = "PORTSC #0",
|
||||
[PORTSC_BEGIN + 4] = "PORTSC #1",
|
||||
[PORTSC_BEGIN + 8] = "PORTSC #2",
|
||||
[PORTSC_BEGIN + 12] = "PORTSC #3",
|
||||
[PORTSC_BEGIN + 16] = "PORTSC #4",
|
||||
[PORTSC_BEGIN + 20] = "PORTSC #5",
|
||||
[CONFIGFLAG] = "CONFIGFLAG",
|
||||
};
|
||||
|
||||
static const char *nr2str(const char **n, size_t len, uint32_t nr)
|
||||
@@ -2046,6 +2048,7 @@ static void ehci_advance_state(EHCIState *ehci,
|
||||
break;
|
||||
|
||||
case EST_WRITEBACK:
|
||||
assert(q != NULL);
|
||||
again = ehci_state_writeback(q, async);
|
||||
break;
|
||||
|
||||
|
||||
+19
-3
@@ -171,6 +171,8 @@ static void usb_hub_detach(USBPort *port1)
|
||||
USBHubState *s = port1->opaque;
|
||||
USBHubPort *port = &s->ports[port1->index];
|
||||
|
||||
usb_wakeup(&s->dev);
|
||||
|
||||
/* Let upstream know the device on this port is gone */
|
||||
s->dev.port->ops->child_detach(s->dev.port, port1->dev);
|
||||
|
||||
@@ -220,7 +222,22 @@ static void usb_hub_complete(USBPort *port, USBPacket *packet)
|
||||
|
||||
static void usb_hub_handle_reset(USBDevice *dev)
|
||||
{
|
||||
/* XXX: do it */
|
||||
USBHubState *s = DO_UPCAST(USBHubState, dev, dev);
|
||||
USBHubPort *port;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_PORTS; i++) {
|
||||
port = s->ports + i;
|
||||
port->wPortStatus = PORT_STAT_POWER;
|
||||
port->wPortChange = 0;
|
||||
if (port->port.dev && port->port.dev->attached) {
|
||||
port->wPortStatus |= PORT_STAT_CONNECTION;
|
||||
port->wPortChange |= PORT_STAT_C_CONNECTION;
|
||||
if (port->port.dev->speed == USB_SPEED_LOW) {
|
||||
port->wPortStatus |= PORT_STAT_LOW_SPEED;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int usb_hub_handle_control(USBDevice *dev, USBPacket *p,
|
||||
@@ -495,9 +512,8 @@ static int usb_hub_initfn(USBDevice *dev)
|
||||
&port->port, s, i, &usb_hub_port_ops,
|
||||
USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
|
||||
usb_port_location(&port->port, dev->port, i+1);
|
||||
port->wPortStatus = PORT_STAT_POWER;
|
||||
port->wPortChange = 0;
|
||||
}
|
||||
usb_hub_handle_reset(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+37
-32
@@ -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:
|
||||
@@ -541,7 +546,8 @@ static int usb_msd_initfn(USBDevice *dev)
|
||||
|
||||
usb_desc_init(dev);
|
||||
scsi_bus_new(&s->bus, &s->dev.qdev, &usb_msd_scsi_info);
|
||||
s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable);
|
||||
s->scsi_dev = scsi_bus_legacy_add_drive(&s->bus, bs, 0, !!s->removable,
|
||||
s->conf.bootindex);
|
||||
if (!s->scsi_dev) {
|
||||
return -1;
|
||||
}
|
||||
@@ -557,7 +563,6 @@ static int usb_msd_initfn(USBDevice *dev)
|
||||
}
|
||||
}
|
||||
|
||||
add_boot_device_path(s->conf.bootindex, &dev->qdev, "/disk@0,0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+4
-3
@@ -485,6 +485,7 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
|
||||
struct virtio_blk_config blkcfg;
|
||||
uint64_t capacity;
|
||||
int cylinders, heads, secs;
|
||||
int blk_size = s->conf->logical_block_size;
|
||||
|
||||
bdrv_get_geometry(s->bs, &capacity);
|
||||
bdrv_get_geometry_hint(s->bs, &cylinders, &heads, &secs);
|
||||
@@ -492,14 +493,14 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)
|
||||
stq_raw(&blkcfg.capacity, capacity);
|
||||
stl_raw(&blkcfg.seg_max, 128 - 2);
|
||||
stw_raw(&blkcfg.cylinders, cylinders);
|
||||
stl_raw(&blkcfg.blk_size, blk_size);
|
||||
stw_raw(&blkcfg.min_io_size, s->conf->min_io_size / blk_size);
|
||||
stw_raw(&blkcfg.opt_io_size, s->conf->opt_io_size / blk_size);
|
||||
blkcfg.heads = heads;
|
||||
blkcfg.sectors = secs & ~s->sector_mask;
|
||||
blkcfg.blk_size = s->conf->logical_block_size;
|
||||
blkcfg.size_max = 0;
|
||||
blkcfg.physical_block_exp = get_physical_block_exp(s->conf);
|
||||
blkcfg.alignment_offset = 0;
|
||||
blkcfg.min_io_size = s->conf->min_io_size / blkcfg.blk_size;
|
||||
blkcfg.opt_io_size = s->conf->opt_io_size / blkcfg.blk_size;
|
||||
memcpy(config, &blkcfg, sizeof(struct virtio_blk_config));
|
||||
}
|
||||
|
||||
|
||||
+2
-7
@@ -285,14 +285,9 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
|
||||
case VIRTIO_PCI_GUEST_FEATURES:
|
||||
/* Guest does not negotiate properly? We have to assume nothing. */
|
||||
if (val & (1 << VIRTIO_F_BAD_FEATURE)) {
|
||||
if (vdev->bad_features)
|
||||
val = proxy->host_features & vdev->bad_features(vdev);
|
||||
else
|
||||
val = 0;
|
||||
val = vdev->bad_features ? vdev->bad_features(vdev) : 0;
|
||||
}
|
||||
if (vdev->set_features)
|
||||
vdev->set_features(vdev, val);
|
||||
vdev->guest_features = val;
|
||||
virtio_set_features(vdev, val);
|
||||
break;
|
||||
case VIRTIO_PCI_QUEUE_PFN:
|
||||
pa = (target_phys_addr_t)val << VIRTIO_PCI_QUEUE_ADDR_SHIFT;
|
||||
|
||||
+18
-6
@@ -763,12 +763,25 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f)
|
||||
}
|
||||
}
|
||||
|
||||
int virtio_set_features(VirtIODevice *vdev, uint32_t val)
|
||||
{
|
||||
uint32_t supported_features =
|
||||
vdev->binding->get_features(vdev->binding_opaque);
|
||||
bool bad = (val & ~supported_features) != 0;
|
||||
|
||||
val &= supported_features;
|
||||
if (vdev->set_features) {
|
||||
vdev->set_features(vdev, val);
|
||||
}
|
||||
vdev->guest_features = val;
|
||||
return bad ? -1 : 0;
|
||||
}
|
||||
|
||||
int virtio_load(VirtIODevice *vdev, QEMUFile *f)
|
||||
{
|
||||
int num, i, ret;
|
||||
uint32_t features;
|
||||
uint32_t supported_features =
|
||||
vdev->binding->get_features(vdev->binding_opaque);
|
||||
uint32_t supported_features;
|
||||
|
||||
if (vdev->binding->load_config) {
|
||||
ret = vdev->binding->load_config(vdev->binding_opaque, f);
|
||||
@@ -780,14 +793,13 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
|
||||
qemu_get_8s(f, &vdev->isr);
|
||||
qemu_get_be16s(f, &vdev->queue_sel);
|
||||
qemu_get_be32s(f, &features);
|
||||
if (features & ~supported_features) {
|
||||
|
||||
if (virtio_set_features(vdev, features) < 0) {
|
||||
supported_features = vdev->binding->get_features(vdev->binding_opaque);
|
||||
error_report("Features 0x%x unsupported. Allowed features: 0x%x",
|
||||
features, supported_features);
|
||||
return -1;
|
||||
}
|
||||
if (vdev->set_features)
|
||||
vdev->set_features(vdev, features);
|
||||
vdev->guest_features = features;
|
||||
vdev->config_len = qemu_get_be32(f);
|
||||
qemu_get_buffer(f, vdev->config, vdev->config_len);
|
||||
|
||||
|
||||
@@ -185,6 +185,7 @@ void virtio_queue_set_vector(VirtIODevice *vdev, int n, uint16_t vector);
|
||||
void virtio_set_status(VirtIODevice *vdev, uint8_t val);
|
||||
void virtio_reset(void *opaque);
|
||||
void virtio_update_irq(VirtIODevice *vdev);
|
||||
int virtio_set_features(VirtIODevice *vdev, uint32_t val);
|
||||
|
||||
void virtio_bind_device(VirtIODevice *vdev, const VirtIOBindings *binding,
|
||||
void *opaque);
|
||||
|
||||
+21
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-5
@@ -305,7 +305,7 @@ void net_slirp_hostfwd_remove(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
struct in_addr host_addr = { .s_addr = INADDR_ANY };
|
||||
int host_port;
|
||||
char buf[256] = "";
|
||||
char buf[256];
|
||||
const char *src_str, *p;
|
||||
SlirpState *s;
|
||||
int is_udp = 0;
|
||||
@@ -325,11 +325,10 @@ void net_slirp_hostfwd_remove(Monitor *mon, const QDict *qdict)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!src_str || !src_str[0])
|
||||
goto fail_syntax;
|
||||
|
||||
p = src_str;
|
||||
get_str_sep(buf, sizeof(buf), &p, ':');
|
||||
if (!p || get_str_sep(buf, sizeof(buf), &p, ':') < 0) {
|
||||
goto fail_syntax;
|
||||
}
|
||||
|
||||
if (!strcmp(buf, "tcp") || buf[0] == '\0') {
|
||||
is_udp = 0;
|
||||
|
||||
+2
-3
@@ -162,8 +162,7 @@ int qemu_pipe(int pipefd[2])
|
||||
return ret;
|
||||
}
|
||||
|
||||
int qemu_utimensat(int dirfd, const char *path, const struct timespec *times,
|
||||
int flags)
|
||||
int qemu_utimens(const char *path, const struct timespec *times)
|
||||
{
|
||||
struct timeval tv[2], tv_now;
|
||||
struct stat st;
|
||||
@@ -171,7 +170,7 @@ int qemu_utimensat(int dirfd, const char *path, const struct timespec *times,
|
||||
#ifdef CONFIG_UTIMENSAT
|
||||
int ret;
|
||||
|
||||
ret = utimensat(dirfd, path, times, flags);
|
||||
ret = utimensat(AT_FDCWD, path, times, AT_SYMLINK_NOFOLLOW);
|
||||
if (ret != -1 || errno != ENOSYS) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+13
-13
@@ -106,7 +106,7 @@
|
||||
static QTAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs =
|
||||
QTAILQ_HEAD_INITIALIZER(chardevs);
|
||||
|
||||
static void qemu_chr_event(CharDriverState *s, int event)
|
||||
void qemu_chr_be_event(CharDriverState *s, int event)
|
||||
{
|
||||
/* Keep track if the char device is open */
|
||||
switch (event) {
|
||||
@@ -126,7 +126,7 @@ static void qemu_chr_event(CharDriverState *s, int event)
|
||||
static void qemu_chr_generic_open_bh(void *opaque)
|
||||
{
|
||||
CharDriverState *s = opaque;
|
||||
qemu_chr_event(s, CHR_EVENT_OPENED);
|
||||
qemu_chr_be_event(s, CHR_EVENT_OPENED);
|
||||
qemu_bh_delete(s->bh);
|
||||
s->bh = NULL;
|
||||
}
|
||||
@@ -359,7 +359,7 @@ static int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch)
|
||||
bdrv_commit_all();
|
||||
break;
|
||||
case 'b':
|
||||
qemu_chr_event(chr, CHR_EVENT_BREAK);
|
||||
qemu_chr_be_event(chr, CHR_EVENT_BREAK);
|
||||
break;
|
||||
case 'c':
|
||||
/* Switch to the next registered device */
|
||||
@@ -580,7 +580,7 @@ static void fd_chr_read(void *opaque)
|
||||
if (size == 0) {
|
||||
/* FD has been closed. Remove it from the active list. */
|
||||
qemu_set_fd_handler2(s->fd_in, NULL, NULL, NULL, NULL);
|
||||
qemu_chr_event(chr, CHR_EVENT_CLOSED);
|
||||
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
|
||||
return;
|
||||
}
|
||||
if (size > 0) {
|
||||
@@ -613,7 +613,7 @@ static void fd_chr_close(struct CharDriverState *chr)
|
||||
}
|
||||
|
||||
g_free(s);
|
||||
qemu_chr_event(chr, CHR_EVENT_CLOSED);
|
||||
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
|
||||
}
|
||||
|
||||
/* open a character device to a unix fd */
|
||||
@@ -715,7 +715,7 @@ static void stdio_read(void *opaque)
|
||||
if (size == 0) {
|
||||
/* stdin has been closed. Remove it from the active list. */
|
||||
qemu_set_fd_handler2(0, NULL, NULL, NULL, NULL);
|
||||
qemu_chr_event(chr, CHR_EVENT_CLOSED);
|
||||
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
|
||||
return;
|
||||
}
|
||||
if (size > 0) {
|
||||
@@ -977,7 +977,7 @@ static void pty_chr_close(struct CharDriverState *chr)
|
||||
qemu_del_timer(s->timer);
|
||||
qemu_free_timer(s->timer);
|
||||
g_free(s);
|
||||
qemu_chr_event(chr, CHR_EVENT_CLOSED);
|
||||
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
|
||||
}
|
||||
|
||||
static int qemu_chr_open_pty(QemuOpts *opts, CharDriverState **_chr)
|
||||
@@ -1355,7 +1355,7 @@ static void pp_close(CharDriverState *chr)
|
||||
ioctl(fd, PPRELEASE);
|
||||
close(fd);
|
||||
g_free(drv);
|
||||
qemu_chr_event(chr, CHR_EVENT_CLOSED);
|
||||
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
|
||||
}
|
||||
|
||||
static int qemu_chr_open_pp(QemuOpts *opts, CharDriverState **_chr)
|
||||
@@ -1500,7 +1500,7 @@ static void win_chr_close(CharDriverState *chr)
|
||||
else
|
||||
qemu_del_polling_cb(win_chr_poll, chr);
|
||||
|
||||
qemu_chr_event(chr, CHR_EVENT_CLOSED);
|
||||
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
|
||||
}
|
||||
|
||||
static int win_chr_init(CharDriverState *chr, const char *filename)
|
||||
@@ -2108,7 +2108,7 @@ static void udp_chr_close(CharDriverState *chr)
|
||||
closesocket(s->fd);
|
||||
}
|
||||
g_free(s);
|
||||
qemu_chr_event(chr, CHR_EVENT_CLOSED);
|
||||
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
|
||||
}
|
||||
|
||||
static int qemu_chr_open_udp(QemuOpts *opts, CharDriverState **_chr)
|
||||
@@ -2213,7 +2213,7 @@ static void tcp_chr_process_IAC_bytes(CharDriverState *chr,
|
||||
} else {
|
||||
if ((unsigned char)buf[i] == IAC_BREAK && s->do_telnetopt == 2) {
|
||||
/* Handle IAC break commands by sending a serial break */
|
||||
qemu_chr_event(chr, CHR_EVENT_BREAK);
|
||||
qemu_chr_be_event(chr, CHR_EVENT_BREAK);
|
||||
s->do_telnetopt++;
|
||||
}
|
||||
s->do_telnetopt++;
|
||||
@@ -2321,7 +2321,7 @@ static void tcp_chr_read(void *opaque)
|
||||
qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL);
|
||||
closesocket(s->fd);
|
||||
s->fd = -1;
|
||||
qemu_chr_event(chr, CHR_EVENT_CLOSED);
|
||||
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
|
||||
} else if (size > 0) {
|
||||
if (s->do_telnetopt)
|
||||
tcp_chr_process_IAC_bytes(chr, s, buf, &size);
|
||||
@@ -2433,7 +2433,7 @@ static void tcp_chr_close(CharDriverState *chr)
|
||||
closesocket(s->listen_fd);
|
||||
}
|
||||
g_free(s);
|
||||
qemu_chr_event(chr, CHR_EVENT_CLOSED);
|
||||
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
|
||||
}
|
||||
|
||||
static int qemu_chr_open_socket(QemuOpts *opts, CharDriverState **_chr)
|
||||
|
||||
+10
@@ -212,6 +212,16 @@ int qemu_chr_be_can_write(CharDriverState *s);
|
||||
*/
|
||||
void qemu_chr_be_write(CharDriverState *s, uint8_t *buf, int len);
|
||||
|
||||
|
||||
/**
|
||||
* @qemu_chr_be_event:
|
||||
*
|
||||
* Send an event from the back end to the front end.
|
||||
*
|
||||
* @event the event to send
|
||||
*/
|
||||
void qemu_chr_be_event(CharDriverState *s, int event);
|
||||
|
||||
void qemu_chr_add_handlers(CharDriverState *s,
|
||||
IOCanReadHandler *fd_can_read,
|
||||
IOReadHandler *fd_read,
|
||||
|
||||
+58
-2
@@ -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:
|
||||
|
||||
|
||||
+6
-4
@@ -332,8 +332,9 @@ static int img_create(int argc, char **argv)
|
||||
/* Get image size, if specified */
|
||||
if (optind < argc) {
|
||||
int64_t sval;
|
||||
sval = strtosz_suffix(argv[optind++], NULL, STRTOSZ_DEFSUFFIX_B);
|
||||
if (sval < 0) {
|
||||
char *end;
|
||||
sval = strtosz_suffix(argv[optind++], &end, STRTOSZ_DEFSUFFIX_B);
|
||||
if (sval < 0 || *end) {
|
||||
error_report("Invalid image size specified! You may use k, M, G or "
|
||||
"T suffixes for ");
|
||||
error_report("kilobytes, megabytes, gigabytes and terabytes.");
|
||||
@@ -710,8 +711,9 @@ static int img_convert(int argc, char **argv)
|
||||
case 'S':
|
||||
{
|
||||
int64_t sval;
|
||||
sval = strtosz_suffix(optarg, NULL, STRTOSZ_DEFSUFFIX_B);
|
||||
if (sval < 0) {
|
||||
char *end;
|
||||
sval = strtosz_suffix(optarg, &end, STRTOSZ_DEFSUFFIX_B);
|
||||
if (sval < 0 || *end) {
|
||||
error_report("Invalid minimum zero buffer size for sparse output specified");
|
||||
return 1;
|
||||
}
|
||||
|
||||
+1
-2
@@ -44,7 +44,6 @@ typedef struct timeval qemu_timeval;
|
||||
#endif
|
||||
#endif
|
||||
typedef struct timespec qemu_timespec;
|
||||
int qemu_utimensat(int dirfd, const char *path, const qemu_timespec *times,
|
||||
int flags);
|
||||
int qemu_utimens(const char *path, const qemu_timespec *times);
|
||||
|
||||
#endif
|
||||
@@ -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)
|
||||
{
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
@@ -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 } }"
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -859,7 +859,7 @@ sub annotate_values {
|
||||
$av_preprocessor = 0;
|
||||
}
|
||||
|
||||
} elsif ($cur =~ /^(\(\s*$Type\s*)\)/) {
|
||||
} elsif ($cur =~ /^(\(\s*$Type\s*)\)/ && $av_pending eq '_') {
|
||||
print "CAST($1)\n" if ($dbg_values > 1);
|
||||
push(@av_paren_type, $type);
|
||||
$type = 'C';
|
||||
|
||||
+4
-3
@@ -200,6 +200,7 @@ def basename(filename):
|
||||
return filename.split("/")[-1]
|
||||
|
||||
def guardname(filename):
|
||||
if filename.startswith('./'):
|
||||
filename = filename[2:]
|
||||
return filename.replace("/", "_").replace("-", "_").split(".")[0].upper() + '_H'
|
||||
guard = basename(filename).rsplit(".", 1)[0]
|
||||
for substr in [".", " ", "-"]:
|
||||
guard = guard.replace(substr, "_")
|
||||
return guard.upper() + '_H'
|
||||
+35
-1
@@ -69,11 +69,40 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static void vmc_state(SpiceCharDeviceInstance *sin, int connected)
|
||||
{
|
||||
SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
|
||||
|
||||
#if SPICE_SERVER_VERSION < 0x000901
|
||||
/*
|
||||
* spice-server calls the state callback for the agent channel when the
|
||||
* spice client connects / disconnects. Given that not the client but
|
||||
* the server is doing the parsing of the messages this is wrong as the
|
||||
* server is still listening. Worse, this causes the parser in the server
|
||||
* to go out of sync, so we ignore state calls for subtype vdagent
|
||||
* spicevmc chardevs. For the full story see:
|
||||
* http://lists.freedesktop.org/archives/spice-devel/2011-July/004837.html
|
||||
*/
|
||||
if (strcmp(sin->subtype, "vdagent") == 0) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if ((scd->chr->opened && connected) ||
|
||||
(!scd->chr->opened && !connected)) {
|
||||
return;
|
||||
}
|
||||
|
||||
qemu_chr_be_event(scd->chr,
|
||||
connected ? CHR_EVENT_OPENED : CHR_EVENT_CLOSED);
|
||||
}
|
||||
|
||||
static SpiceCharDeviceInterface vmc_interface = {
|
||||
.base.type = SPICE_INTERFACE_CHAR_DEVICE,
|
||||
.base.description = "spice virtual channel char device",
|
||||
.base.major_version = SPICE_INTERFACE_CHAR_DEVICE_MAJOR,
|
||||
.base.minor_version = SPICE_INTERFACE_CHAR_DEVICE_MINOR,
|
||||
.state = vmc_state,
|
||||
.write = vmc_write,
|
||||
.read = vmc_read,
|
||||
};
|
||||
@@ -197,7 +226,12 @@ int qemu_chr_open_spice(QemuOpts *opts, CharDriverState **_chr)
|
||||
chr->chr_guest_open = spice_chr_guest_open;
|
||||
chr->chr_guest_close = spice_chr_guest_close;
|
||||
|
||||
qemu_chr_generic_open(chr);
|
||||
#if SPICE_SERVER_VERSION < 0x000901
|
||||
/* See comment in vmc_state() */
|
||||
if (strcmp(subtype, "vdagent") == 0) {
|
||||
qemu_chr_generic_open(chr);
|
||||
}
|
||||
#endif
|
||||
|
||||
*_chr = chr;
|
||||
return 0;
|
||||
|
||||
+24
-5
@@ -107,14 +107,33 @@ void host_cpuid(uint32_t function, uint32_t count,
|
||||
uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
|
||||
{
|
||||
#if defined(CONFIG_KVM)
|
||||
uint32_t vec[4];
|
||||
|
||||
#ifdef __x86_64__
|
||||
asm volatile("cpuid"
|
||||
: "=a"(vec[0]), "=b"(vec[1]),
|
||||
"=c"(vec[2]), "=d"(vec[3])
|
||||
: "0"(function), "c"(count) : "cc");
|
||||
#else
|
||||
asm volatile("pusha \n\t"
|
||||
"cpuid \n\t"
|
||||
"mov %%eax, 0(%2) \n\t"
|
||||
"mov %%ebx, 4(%2) \n\t"
|
||||
"mov %%ecx, 8(%2) \n\t"
|
||||
"mov %%edx, 12(%2) \n\t"
|
||||
"popa"
|
||||
: : "a"(function), "c"(count), "S"(vec)
|
||||
: "memory", "cc");
|
||||
#endif
|
||||
|
||||
if (eax)
|
||||
*eax = kvm_arch_get_supported_cpuid(kvm_state, function, count, R_EAX);
|
||||
*eax = vec[0];
|
||||
if (ebx)
|
||||
*ebx = kvm_arch_get_supported_cpuid(kvm_state, function, count, R_EBX);
|
||||
*ebx = vec[1];
|
||||
if (ecx)
|
||||
*ecx = kvm_arch_get_supported_cpuid(kvm_state, function, count, R_ECX);
|
||||
*ecx = vec[2];
|
||||
if (edx)
|
||||
*edx = kvm_arch_get_supported_cpuid(kvm_state, function, count, R_EDX);
|
||||
*edx = vec[3];
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -692,7 +711,7 @@ static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
|
||||
|
||||
tsc_freq = strtosz_suffix_unit(val, &err,
|
||||
STRTOSZ_DEFSUFFIX_B, 1000);
|
||||
if (!*val || *err) {
|
||||
if (tsc_freq < 0 || *err) {
|
||||
fprintf(stderr, "bad numerical value %s\n", val);
|
||||
goto error;
|
||||
}
|
||||
|
||||
+1
-1
@@ -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 */
|
||||
|
||||
+24
-3
@@ -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)
|
||||
|
||||
+7
-12
@@ -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;
|
||||
|
||||
@@ -273,7 +273,7 @@ static void reset_tlb_mmu_ways56(CPUState *env,
|
||||
entry[6][ei].vaddr = ei << 29;
|
||||
entry[6][ei].paddr = ei << 29;
|
||||
entry[6][ei].asid = 1;
|
||||
entry[6][ei].attr = 2;
|
||||
entry[6][ei].attr = 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@
|
||||
.way_size = { \
|
||||
(refill_way_size), (refill_way_size), \
|
||||
(refill_way_size), (refill_way_size), \
|
||||
4, 2, 2, 1, 1, 1, \
|
||||
4, (way56) ? 4 : 2, (way56) ? 8 : 2, 1, 1, 1, \
|
||||
}, \
|
||||
.varway56 = (way56), \
|
||||
.nrefillentries = (refill_way_size) * 4, \
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Loaded 100 of 114 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user