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 | ||
|
|
3f5bd4e1b8 | ||
|
|
3827cdb1c3 | ||
|
|
e1556ad5b8 | ||
|
|
371572dff4 | ||
|
|
326384d5b6 | ||
|
|
2a534aff30 | ||
|
|
771142c2a7 | ||
|
|
ef81522bc1 | ||
|
|
854e42f3e8 | ||
|
|
13449a6e0e | ||
|
|
e9d86b760c | ||
|
|
1864b94abb | ||
|
|
17bb18ce16 | ||
|
|
b995913853 | ||
|
|
09ed75f784 | ||
|
|
27b5979d9d | ||
|
|
a3efecb847 | ||
|
|
3fc3abf7ec | ||
|
|
b2887c43ee | ||
|
|
7c64d297f9 | ||
|
|
e7852674d5 | ||
|
|
88365e47dd | ||
|
|
74d33d5ce4 | ||
|
|
0abe905d29 | ||
|
|
ee71c98434 | ||
|
|
afd4a65225 | ||
|
|
b78c2b3aad | ||
|
|
35914dc724 | ||
|
|
7dd47667b9 | ||
|
|
096685fc2a | ||
|
|
1bbd1592c8 | ||
|
|
095ed5be7b | ||
|
|
9d94747262 | ||
|
|
f2d3476eba | ||
|
|
a4e2604852 | ||
|
|
1299c63168 | ||
|
|
f2338fb48a | ||
|
|
ee2b399463 | ||
|
|
9df3b45dd4 | ||
|
|
d43b45e220 | ||
|
|
d423675c94 | ||
|
|
ca716364f0 | ||
|
|
eb489bb1ec | ||
|
|
c68b89acd6 | ||
|
|
980bda8ba2 | ||
|
|
78439f6af1 | ||
|
|
802ddc375a | ||
|
|
f1ef5555c2 | ||
|
|
c1f8fdc362 | ||
|
|
a517e88baa | ||
|
|
b32f6c28d5 | ||
|
|
bb345110f0 | ||
|
|
74624688b3 | ||
|
|
4480de19d9 | ||
|
|
2df0a3a308 | ||
|
|
025ccaa7f9 | ||
|
|
7704df98b0 | ||
|
|
0e3b800e71 | ||
|
|
04c5b17a74 | ||
|
|
99e1dec06f | ||
|
|
d3c481b357 | ||
|
|
302d9d6fd8 | ||
|
|
542379f426 | ||
|
|
235e510cfd | ||
|
|
27c8efcb5d | ||
|
|
4f61927a41 | ||
|
|
c0465d1a1d | ||
|
|
95117be5a3 | ||
|
|
66e3dd9282 | ||
|
|
4f26f2b6f2 | ||
|
|
1bf6ccd372 | ||
|
|
bfc763fcfa | ||
|
|
cca5de7389 | ||
|
|
9770b91252 | ||
|
|
1d769ceda6 | ||
|
|
439229c7cb | ||
|
|
f54c556c08 | ||
|
|
47113ab6b8 | ||
|
|
f67ab77a43 | ||
|
|
25a21c94c0 | ||
|
|
19857e625a | ||
|
|
6023d83248 | ||
|
|
6329866f81 | ||
|
|
2963e65a4e | ||
|
|
ca062aaed0 | ||
|
|
e7b48c97fe | ||
|
|
8af42882a5 | ||
|
|
47e8dd8fe9 | ||
|
|
ba7806ad92 | ||
|
|
81beeec429 | ||
|
|
41bf234d8e | ||
|
|
273e4e03b3 | ||
|
|
d71cff42e4 | ||
|
|
5a742b5557 | ||
|
|
aad37c06dd | ||
|
|
e654bfe4c1 | ||
|
|
2b6a43a835 | ||
|
|
756f51e408 | ||
|
|
5b47b7c3d3 | ||
|
|
acae6f1c4c | ||
|
|
67403dbba7 | ||
|
|
f2360620fb | ||
|
|
932eacc158 | ||
|
|
c51d9cb5b6 | ||
|
|
42dfb09510 | ||
|
|
0e9a2ea2e4 | ||
|
|
f2209eb854 | ||
|
|
18ebcc86f2 | ||
|
|
5bb2392776 | ||
|
|
779b5b04fd | ||
|
|
556ba66845 | ||
|
|
292627bb5e | ||
|
|
82b25dc8b0 | ||
|
|
6b814719b4 | ||
|
|
0c852e171b | ||
|
|
53a72dfda5 | ||
|
|
9195b2c2b1 | ||
|
|
5826e51917 | ||
|
|
7657f4bf68 | ||
|
|
7316329aa5 | ||
|
|
2a24374ab6 | ||
|
|
ce285b1754 | ||
|
|
08dafab4bd | ||
|
|
b7cd3db6f4 |
No files matched your search
@@ -16,3 +16,6 @@
|
||||
[submodule "roms/qemu-palcode"]
|
||||
path = roms/qemu-palcode
|
||||
url = git://repo.or.cz/qemu-palcode.git
|
||||
[submodule "roms/sgabios"]
|
||||
path = roms/sgabios
|
||||
url = git://git.qemu.org/sgabios.git
|
||||
+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 \
|
||||
@@ -253,7 +256,7 @@ ar de en-us fi fr-be hr it lv nl pl ru th \
|
||||
common de-ch es fo fr-ca hu ja mk nl-be pt sl tr
|
||||
|
||||
ifdef INSTALL_BLOBS
|
||||
BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin \
|
||||
BLOBS=bios.bin sgabios.bin vgabios.bin vgabios-cirrus.bin \
|
||||
vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin \
|
||||
ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc \
|
||||
pxe-e1000.rom pxe-eepro100.rom pxe-ne2k_pci.rom \
|
||||
|
||||
@@ -69,6 +69,7 @@ all: $(PROGS) stap
|
||||
# cpu emulator library
|
||||
libobj-y = exec.o translate-all.o cpu-exec.o translate.o
|
||||
libobj-y += tcg/tcg.o tcg/optimize.o
|
||||
libobj-$(CONFIG_TCG_INTERPRETER) += tci.o
|
||||
libobj-y += fpu/softfloat.o
|
||||
libobj-y += op_helper.o helper.o
|
||||
ifeq ($(TARGET_BASE_ARCH), i386)
|
||||
@@ -85,6 +86,9 @@ libobj-$(TARGET_SPARC) += int32_helper.o
|
||||
libobj-$(TARGET_SPARC64) += int64_helper.o
|
||||
|
||||
libobj-y += disas.o
|
||||
libobj-$(CONFIG_TCI_DIS) += tci-dis.o
|
||||
|
||||
tci-dis.o: QEMU_CFLAGS += -I$(SRC_PATH)/tcg -I$(SRC_PATH)/tcg/tci
|
||||
|
||||
$(libobj-y): $(GENERATED_HEADERS)
|
||||
|
||||
|
||||
+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;
|
||||
|
||||
@@ -816,6 +816,13 @@ bool bdrv_dev_has_removable_media(BlockDriverState *bs)
|
||||
return !bs->dev || (bs->dev_ops && bs->dev_ops->change_media_cb);
|
||||
}
|
||||
|
||||
void bdrv_dev_eject_request(BlockDriverState *bs, bool force)
|
||||
{
|
||||
if (bs->dev_ops && bs->dev_ops->eject_request_cb) {
|
||||
bs->dev_ops->eject_request_cb(bs->dev_opaque, force);
|
||||
}
|
||||
}
|
||||
|
||||
bool bdrv_dev_is_tray_open(BlockDriverState *bs)
|
||||
{
|
||||
if (bs->dev_ops && bs->dev_ops->is_tray_open) {
|
||||
@@ -2782,12 +2789,27 @@ static void coroutine_fn bdrv_flush_co_entry(void *opaque)
|
||||
|
||||
int coroutine_fn bdrv_co_flush(BlockDriverState *bs)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!bs->drv) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Write back cached data to the OS even with cache=unsafe */
|
||||
if (bs->drv->bdrv_co_flush_to_os) {
|
||||
ret = bs->drv->bdrv_co_flush_to_os(bs);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* But don't actually force it to the disk with cache=unsafe */
|
||||
if (bs->open_flags & BDRV_O_NO_FLUSH) {
|
||||
return 0;
|
||||
} else if (!bs->drv) {
|
||||
return 0;
|
||||
} else if (bs->drv->bdrv_co_flush) {
|
||||
return bs->drv->bdrv_co_flush(bs);
|
||||
}
|
||||
|
||||
if (bs->drv->bdrv_co_flush_to_disk) {
|
||||
return bs->drv->bdrv_co_flush_to_disk(bs);
|
||||
} else if (bs->drv->bdrv_aio_flush) {
|
||||
BlockDriverAIOCB *acb;
|
||||
CoroutineIOCompletion co = {
|
||||
@@ -2817,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;
|
||||
|
||||
@@ -38,6 +38,15 @@ typedef struct BlockDevOps {
|
||||
* Device models with removable media must implement this callback.
|
||||
*/
|
||||
void (*change_media_cb)(void *opaque, bool load);
|
||||
/*
|
||||
* Runs when an eject request is issued from the monitor, the tray
|
||||
* is closed, and the medium is locked.
|
||||
* Device models that do not implement is_medium_locked will not need
|
||||
* this callback. Device models that can lock the medium or tray might
|
||||
* want to implement the callback and unlock the tray when "force" is
|
||||
* true, even if they do not support eject requests.
|
||||
*/
|
||||
void (*eject_request_cb)(void *opaque, bool force);
|
||||
/*
|
||||
* Is the virtual tray open?
|
||||
* Device models implement this only when the device has a tray.
|
||||
@@ -111,6 +120,7 @@ void bdrv_detach_dev(BlockDriverState *bs, void *dev);
|
||||
void *bdrv_get_attached_dev(BlockDriverState *bs);
|
||||
void bdrv_set_dev_ops(BlockDriverState *bs, const BlockDevOps *ops,
|
||||
void *opaque);
|
||||
void bdrv_dev_eject_request(BlockDriverState *bs, bool force);
|
||||
bool bdrv_dev_has_removable_media(BlockDriverState *bs);
|
||||
bool bdrv_dev_is_tray_open(BlockDriverState *bs);
|
||||
bool bdrv_dev_is_medium_locked(BlockDriverState *bs);
|
||||
@@ -187,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);
|
||||
|
||||
+64
-53
@@ -30,7 +30,7 @@ typedef struct BDRVCloopState {
|
||||
CoMutex lock;
|
||||
uint32_t block_size;
|
||||
uint32_t n_blocks;
|
||||
uint64_t* offsets;
|
||||
uint64_t *offsets;
|
||||
uint32_t sectors_per_block;
|
||||
uint32_t current_block;
|
||||
uint8_t *compressed_block;
|
||||
@@ -40,21 +40,23 @@ typedef struct BDRVCloopState {
|
||||
|
||||
static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename)
|
||||
{
|
||||
const char* magic_version_2_0="#!/bin/sh\n"
|
||||
"#V2.0 Format\n"
|
||||
"modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n";
|
||||
int length=strlen(magic_version_2_0);
|
||||
if(length>buf_size)
|
||||
length=buf_size;
|
||||
if(!memcmp(magic_version_2_0,buf,length))
|
||||
return 2;
|
||||
const char *magic_version_2_0 = "#!/bin/sh\n"
|
||||
"#V2.0 Format\n"
|
||||
"modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n";
|
||||
int length = strlen(magic_version_2_0);
|
||||
if (length > buf_size) {
|
||||
length = buf_size;
|
||||
}
|
||||
if (!memcmp(magic_version_2_0, buf, length)) {
|
||||
return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cloop_open(BlockDriverState *bs, int flags)
|
||||
{
|
||||
BDRVCloopState *s = bs->opaque;
|
||||
uint32_t offsets_size,max_compressed_block_size=1,i;
|
||||
uint32_t offsets_size, max_compressed_block_size = 1, i;
|
||||
|
||||
bs->read_only = 1;
|
||||
|
||||
@@ -74,26 +76,28 @@ static int cloop_open(BlockDriverState *bs, int flags)
|
||||
s->offsets = g_malloc(offsets_size);
|
||||
if (bdrv_pread(bs->file, 128 + 4 + 4, s->offsets, offsets_size) <
|
||||
offsets_size) {
|
||||
goto cloop_close;
|
||||
goto cloop_close;
|
||||
}
|
||||
for(i=0;i<s->n_blocks;i++) {
|
||||
s->offsets[i]=be64_to_cpu(s->offsets[i]);
|
||||
if(i>0) {
|
||||
uint32_t size=s->offsets[i]-s->offsets[i-1];
|
||||
if(size>max_compressed_block_size)
|
||||
max_compressed_block_size=size;
|
||||
}
|
||||
s->offsets[i] = be64_to_cpu(s->offsets[i]);
|
||||
if (i > 0) {
|
||||
uint32_t size = s->offsets[i] - s->offsets[i - 1];
|
||||
if (size > max_compressed_block_size) {
|
||||
max_compressed_block_size = size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* initialize zlib engine */
|
||||
s->compressed_block = g_malloc(max_compressed_block_size+1);
|
||||
s->compressed_block = g_malloc(max_compressed_block_size + 1);
|
||||
s->uncompressed_block = g_malloc(s->block_size);
|
||||
if(inflateInit(&s->zstream) != Z_OK)
|
||||
goto cloop_close;
|
||||
s->current_block=s->n_blocks;
|
||||
if (inflateInit(&s->zstream) != Z_OK) {
|
||||
goto cloop_close;
|
||||
}
|
||||
s->current_block = s->n_blocks;
|
||||
|
||||
s->sectors_per_block = s->block_size/512;
|
||||
bs->total_sectors = s->n_blocks*s->sectors_per_block;
|
||||
bs->total_sectors = s->n_blocks * s->sectors_per_block;
|
||||
qemu_co_mutex_init(&s->lock);
|
||||
return 0;
|
||||
|
||||
@@ -105,27 +109,30 @@ static inline int cloop_read_block(BlockDriverState *bs, int block_num)
|
||||
{
|
||||
BDRVCloopState *s = bs->opaque;
|
||||
|
||||
if(s->current_block != block_num) {
|
||||
int ret;
|
||||
uint32_t bytes = s->offsets[block_num+1]-s->offsets[block_num];
|
||||
if (s->current_block != block_num) {
|
||||
int ret;
|
||||
uint32_t bytes = s->offsets[block_num + 1] - s->offsets[block_num];
|
||||
|
||||
ret = bdrv_pread(bs->file, s->offsets[block_num], s->compressed_block,
|
||||
bytes);
|
||||
if (ret != bytes)
|
||||
if (ret != bytes) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
s->zstream.next_in = s->compressed_block;
|
||||
s->zstream.avail_in = bytes;
|
||||
s->zstream.next_out = s->uncompressed_block;
|
||||
s->zstream.avail_out = s->block_size;
|
||||
ret = inflateReset(&s->zstream);
|
||||
if(ret != Z_OK)
|
||||
return -1;
|
||||
ret = inflate(&s->zstream, Z_FINISH);
|
||||
if(ret != Z_STREAM_END || s->zstream.total_out != s->block_size)
|
||||
return -1;
|
||||
s->zstream.next_in = s->compressed_block;
|
||||
s->zstream.avail_in = bytes;
|
||||
s->zstream.next_out = s->uncompressed_block;
|
||||
s->zstream.avail_out = s->block_size;
|
||||
ret = inflateReset(&s->zstream);
|
||||
if (ret != Z_OK) {
|
||||
return -1;
|
||||
}
|
||||
ret = inflate(&s->zstream, Z_FINISH);
|
||||
if (ret != Z_STREAM_END || s->zstream.total_out != s->block_size) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
s->current_block = block_num;
|
||||
s->current_block = block_num;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -136,12 +143,15 @@ static int cloop_read(BlockDriverState *bs, int64_t sector_num,
|
||||
BDRVCloopState *s = bs->opaque;
|
||||
int i;
|
||||
|
||||
for(i=0;i<nb_sectors;i++) {
|
||||
uint32_t sector_offset_in_block=((sector_num+i)%s->sectors_per_block),
|
||||
block_num=(sector_num+i)/s->sectors_per_block;
|
||||
if(cloop_read_block(bs, block_num) != 0)
|
||||
return -1;
|
||||
memcpy(buf+i*512,s->uncompressed_block+sector_offset_in_block*512,512);
|
||||
for (i = 0; i < nb_sectors; i++) {
|
||||
uint32_t sector_offset_in_block =
|
||||
((sector_num + i) % s->sectors_per_block),
|
||||
block_num = (sector_num + i) / s->sectors_per_block;
|
||||
if (cloop_read_block(bs, block_num) != 0) {
|
||||
return -1;
|
||||
}
|
||||
memcpy(buf + i * 512,
|
||||
s->uncompressed_block + sector_offset_in_block * 512, 512);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -160,20 +170,21 @@ static coroutine_fn int cloop_co_read(BlockDriverState *bs, int64_t sector_num,
|
||||
static void cloop_close(BlockDriverState *bs)
|
||||
{
|
||||
BDRVCloopState *s = bs->opaque;
|
||||
if(s->n_blocks>0)
|
||||
free(s->offsets);
|
||||
free(s->compressed_block);
|
||||
free(s->uncompressed_block);
|
||||
if (s->n_blocks > 0) {
|
||||
g_free(s->offsets);
|
||||
}
|
||||
g_free(s->compressed_block);
|
||||
g_free(s->uncompressed_block);
|
||||
inflateEnd(&s->zstream);
|
||||
}
|
||||
|
||||
static BlockDriver bdrv_cloop = {
|
||||
.format_name = "cloop",
|
||||
.instance_size = sizeof(BDRVCloopState),
|
||||
.bdrv_probe = cloop_probe,
|
||||
.bdrv_open = cloop_open,
|
||||
.bdrv_read = cloop_co_read,
|
||||
.bdrv_close = cloop_close,
|
||||
.format_name = "cloop",
|
||||
.instance_size = sizeof(BDRVCloopState),
|
||||
.bdrv_probe = cloop_probe,
|
||||
.bdrv_open = cloop_open,
|
||||
.bdrv_read = cloop_co_read,
|
||||
.bdrv_close = cloop_close,
|
||||
};
|
||||
|
||||
static void bdrv_cloop_init(void)
|
||||
|
||||
+12
-10
@@ -326,16 +326,18 @@ static QEMUOptionParameter cow_create_options[] = {
|
||||
};
|
||||
|
||||
static BlockDriver bdrv_cow = {
|
||||
.format_name = "cow",
|
||||
.instance_size = sizeof(BDRVCowState),
|
||||
.bdrv_probe = cow_probe,
|
||||
.bdrv_open = cow_open,
|
||||
.bdrv_read = cow_co_read,
|
||||
.bdrv_write = cow_co_write,
|
||||
.bdrv_close = cow_close,
|
||||
.bdrv_create = cow_create,
|
||||
.bdrv_co_flush = cow_co_flush,
|
||||
.bdrv_is_allocated = cow_is_allocated,
|
||||
.format_name = "cow",
|
||||
.instance_size = sizeof(BDRVCowState),
|
||||
|
||||
.bdrv_probe = cow_probe,
|
||||
.bdrv_open = cow_open,
|
||||
.bdrv_close = cow_close,
|
||||
.bdrv_create = cow_create,
|
||||
|
||||
.bdrv_read = cow_co_read,
|
||||
.bdrv_write = cow_co_write,
|
||||
.bdrv_co_flush_to_disk = cow_co_flush,
|
||||
.bdrv_is_allocated = cow_is_allocated,
|
||||
|
||||
.create_options = cow_create_options,
|
||||
};
|
||||
|
||||
+22
-8
@@ -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)
|
||||
@@ -828,14 +840,16 @@ static BlockDriver bdrv_qcow = {
|
||||
.bdrv_open = qcow_open,
|
||||
.bdrv_close = qcow_close,
|
||||
.bdrv_create = qcow_create,
|
||||
.bdrv_is_allocated = qcow_is_allocated,
|
||||
.bdrv_set_key = qcow_set_key,
|
||||
.bdrv_make_empty = qcow_make_empty,
|
||||
.bdrv_co_readv = qcow_co_readv,
|
||||
.bdrv_co_writev = qcow_co_writev,
|
||||
.bdrv_co_flush = qcow_co_flush,
|
||||
.bdrv_write_compressed = qcow_write_compressed,
|
||||
.bdrv_get_info = qcow_get_info,
|
||||
|
||||
.bdrv_co_readv = qcow_co_readv,
|
||||
.bdrv_co_writev = qcow_co_writev,
|
||||
.bdrv_co_flush_to_disk = qcow_co_flush,
|
||||
.bdrv_is_allocated = qcow_is_allocated,
|
||||
|
||||
.bdrv_set_key = qcow_set_key,
|
||||
.bdrv_make_empty = qcow_make_empty,
|
||||
.bdrv_write_compressed = qcow_write_compressed,
|
||||
.bdrv_get_info = qcow_get_info,
|
||||
|
||||
.create_options = qcow_create_options,
|
||||
};
|
||||
|
||||
+44
-4
@@ -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
|
||||
@@ -1105,7 +1137,7 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qcow2_co_flush(BlockDriverState *bs)
|
||||
static int qcow2_co_flush_to_os(BlockDriverState *bs)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
int ret;
|
||||
@@ -1124,6 +1156,11 @@ static int qcow2_co_flush(BlockDriverState *bs)
|
||||
}
|
||||
qemu_co_mutex_unlock(&s->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qcow2_co_flush_to_disk(BlockDriverState *bs)
|
||||
{
|
||||
return bdrv_co_flush(bs->file);
|
||||
}
|
||||
|
||||
@@ -1243,9 +1280,10 @@ static BlockDriver bdrv_qcow2 = {
|
||||
.bdrv_set_key = qcow2_set_key,
|
||||
.bdrv_make_empty = qcow2_make_empty,
|
||||
|
||||
.bdrv_co_readv = qcow2_co_readv,
|
||||
.bdrv_co_writev = qcow2_co_writev,
|
||||
.bdrv_co_flush = qcow2_co_flush,
|
||||
.bdrv_co_readv = qcow2_co_readv,
|
||||
.bdrv_co_writev = qcow2_co_writev,
|
||||
.bdrv_co_flush_to_os = qcow2_co_flush_to_os,
|
||||
.bdrv_co_flush_to_disk = qcow2_co_flush_to_disk,
|
||||
|
||||
.bdrv_co_discard = qcow2_co_discard,
|
||||
.bdrv_truncate = qcow2_truncate,
|
||||
@@ -1263,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 {
|
||||
|
||||
+9
-6
@@ -281,9 +281,11 @@ static BlockDriver bdrv_file = {
|
||||
.bdrv_file_open = raw_open,
|
||||
.bdrv_close = raw_close,
|
||||
.bdrv_create = raw_create,
|
||||
.bdrv_co_flush = raw_flush,
|
||||
.bdrv_read = raw_read,
|
||||
.bdrv_write = raw_write,
|
||||
|
||||
.bdrv_read = raw_read,
|
||||
.bdrv_write = raw_write,
|
||||
.bdrv_co_flush_to_disk = raw_flush,
|
||||
|
||||
.bdrv_truncate = raw_truncate,
|
||||
.bdrv_getlength = raw_getlength,
|
||||
.bdrv_get_allocated_file_size
|
||||
@@ -409,11 +411,12 @@ static BlockDriver bdrv_host_device = {
|
||||
.bdrv_probe_device = hdev_probe_device,
|
||||
.bdrv_file_open = hdev_open,
|
||||
.bdrv_close = raw_close,
|
||||
.bdrv_co_flush = raw_flush,
|
||||
.bdrv_has_zero_init = hdev_has_zero_init,
|
||||
|
||||
.bdrv_read = raw_read,
|
||||
.bdrv_write = raw_write,
|
||||
.bdrv_read = raw_read,
|
||||
.bdrv_write = raw_write,
|
||||
.bdrv_co_flush_to_disk = raw_flush,
|
||||
|
||||
.bdrv_getlength = raw_getlength,
|
||||
.bdrv_get_allocated_file_size
|
||||
= raw_get_allocated_file_size,
|
||||
|
||||
+4
-4
@@ -111,10 +111,10 @@ static BlockDriver bdrv_raw = {
|
||||
.bdrv_open = raw_open,
|
||||
.bdrv_close = raw_close,
|
||||
|
||||
.bdrv_co_readv = raw_co_readv,
|
||||
.bdrv_co_writev = raw_co_writev,
|
||||
.bdrv_co_flush = raw_co_flush,
|
||||
.bdrv_co_discard = raw_co_discard,
|
||||
.bdrv_co_readv = raw_co_readv,
|
||||
.bdrv_co_writev = raw_co_writev,
|
||||
.bdrv_co_flush_to_disk = raw_co_flush,
|
||||
.bdrv_co_discard = raw_co_discard,
|
||||
|
||||
.bdrv_probe = raw_probe,
|
||||
.bdrv_getlength = raw_getlength,
|
||||
|
||||
+5
-5
@@ -851,18 +851,18 @@ static BlockDriver bdrv_rbd = {
|
||||
.bdrv_file_open = qemu_rbd_open,
|
||||
.bdrv_close = qemu_rbd_close,
|
||||
.bdrv_create = qemu_rbd_create,
|
||||
.bdrv_co_flush = qemu_rbd_co_flush,
|
||||
.bdrv_get_info = qemu_rbd_getinfo,
|
||||
.create_options = qemu_rbd_create_options,
|
||||
.bdrv_getlength = qemu_rbd_getlength,
|
||||
.bdrv_truncate = qemu_rbd_truncate,
|
||||
.protocol_name = "rbd",
|
||||
|
||||
.bdrv_aio_readv = qemu_rbd_aio_readv,
|
||||
.bdrv_aio_writev = qemu_rbd_aio_writev,
|
||||
.bdrv_aio_readv = qemu_rbd_aio_readv,
|
||||
.bdrv_aio_writev = qemu_rbd_aio_writev,
|
||||
.bdrv_co_flush_to_disk = qemu_rbd_co_flush,
|
||||
|
||||
.bdrv_snapshot_create = qemu_rbd_snap_create,
|
||||
.bdrv_snapshot_list = qemu_rbd_snap_list,
|
||||
.bdrv_snapshot_create = qemu_rbd_snap_create,
|
||||
.bdrv_snapshot_list = qemu_rbd_snap_list,
|
||||
};
|
||||
|
||||
static void bdrv_rbd_init(void)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+16
-1
@@ -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)
|
||||
@@ -980,7 +995,7 @@ static BlockDriver bdrv_vdi = {
|
||||
.bdrv_open = vdi_open,
|
||||
.bdrv_close = vdi_close,
|
||||
.bdrv_create = vdi_create,
|
||||
.bdrv_co_flush = vdi_co_flush,
|
||||
.bdrv_co_flush_to_disk = vdi_co_flush,
|
||||
.bdrv_is_allocated = vdi_is_allocated,
|
||||
.bdrv_make_empty = vdi_make_empty,
|
||||
|
||||
|
||||
+18
-4
@@ -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)
|
||||
@@ -1581,8 +1595,8 @@ static BlockDriver bdrv_vmdk = {
|
||||
.bdrv_write = vmdk_co_write,
|
||||
.bdrv_close = vmdk_close,
|
||||
.bdrv_create = vmdk_create,
|
||||
.bdrv_co_flush = vmdk_co_flush,
|
||||
.bdrv_is_allocated = vmdk_is_allocated,
|
||||
.bdrv_co_flush_to_disk = vmdk_co_flush,
|
||||
.bdrv_is_allocated = vmdk_is_allocated,
|
||||
.bdrv_get_allocated_file_size = vmdk_get_allocated_file_size,
|
||||
|
||||
.create_options = vmdk_create_options,
|
||||
|
||||
+27
-5
@@ -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;
|
||||
@@ -617,7 +630,11 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options)
|
||||
|
||||
memcpy(dyndisk_header->magic, "cxsparse", 8);
|
||||
|
||||
dyndisk_header->data_offset = be64_to_cpu(0xFFFFFFFF);
|
||||
/*
|
||||
* Note: The spec is actually wrong here for data_offset, it says
|
||||
* 0xFFFFFFFF, but MS tools expect all 64 bits to be set.
|
||||
*/
|
||||
dyndisk_header->data_offset = be64_to_cpu(0xFFFFFFFFFFFFFFFFULL);
|
||||
dyndisk_header->table_offset = be64_to_cpu(3 * 512);
|
||||
dyndisk_header->version = be32_to_cpu(0x00010000);
|
||||
dyndisk_header->block_size = be32_to_cpu(block_size);
|
||||
@@ -647,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[] = {
|
||||
@@ -661,14 +681,16 @@ static QEMUOptionParameter vpc_create_options[] = {
|
||||
static BlockDriver bdrv_vpc = {
|
||||
.format_name = "vpc",
|
||||
.instance_size = sizeof(BDRVVPCState),
|
||||
|
||||
.bdrv_probe = vpc_probe,
|
||||
.bdrv_open = vpc_open,
|
||||
.bdrv_read = vpc_co_read,
|
||||
.bdrv_write = vpc_co_write,
|
||||
.bdrv_co_flush = vpc_co_flush,
|
||||
.bdrv_close = vpc_close,
|
||||
.bdrv_create = vpc_create,
|
||||
|
||||
.bdrv_read = vpc_co_read,
|
||||
.bdrv_write = vpc_co_write,
|
||||
.bdrv_co_flush_to_disk = vpc_co_flush,
|
||||
|
||||
.create_options = vpc_create_options,
|
||||
};
|
||||
|
||||
|
||||
+73
-48
@@ -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
|
||||
@@ -799,6 +802,7 @@ static int read_directory(BDRVVVFATState* s, int mapping_index)
|
||||
/* root directory */
|
||||
int cur = s->directory.next;
|
||||
array_ensure_allocated(&(s->directory), ROOT_ENTRIES - 1);
|
||||
s->directory.next = ROOT_ENTRIES;
|
||||
memset(array_get(&(s->directory), cur), 0,
|
||||
(ROOT_ENTRIES - cur) * sizeof(direntry_t));
|
||||
}
|
||||
@@ -915,11 +919,8 @@ static int init_directories(BDRVVVFATState* s,
|
||||
cluster = mapping->end;
|
||||
|
||||
if(cluster > s->cluster_count) {
|
||||
fprintf(stderr,"Directory does not fit in FAT%d (capacity %s)\n",
|
||||
s->fat_type,
|
||||
s->fat_type == 12 ? s->sector_count == 2880 ? "1.44 MB"
|
||||
: "2.88 MB"
|
||||
: "504MB");
|
||||
fprintf(stderr,"Directory does not fit in FAT%d (capacity %.2f MB)\n",
|
||||
s->fat_type, s->sector_count / 2000.0);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -953,7 +954,7 @@ static int init_directories(BDRVVVFATState* s,
|
||||
bootsector->number_of_fats=0x2; /* number of FATs */
|
||||
bootsector->root_entries=cpu_to_le16(s->sectors_of_root_directory*0x10);
|
||||
bootsector->total_sectors16=s->sector_count>0xffff?0:cpu_to_le16(s->sector_count);
|
||||
bootsector->media_type=(s->fat_type!=12?0xf8:s->sector_count==5760?0xf9:0xf8); /* media descriptor */
|
||||
bootsector->media_type=(s->first_sectors_number>1?0xf8:0xf0); /* media descriptor (f8=hd, f0=3.5 fd)*/
|
||||
s->fat.pointer[0] = bootsector->media_type;
|
||||
bootsector->sectors_per_fat=cpu_to_le16(s->sectors_per_fat);
|
||||
bootsector->sectors_per_track=cpu_to_le16(s->bs->secs);
|
||||
@@ -962,7 +963,7 @@ static int init_directories(BDRVVVFATState* s,
|
||||
bootsector->total_sectors=cpu_to_le32(s->sector_count>0xffff?s->sector_count:0);
|
||||
|
||||
/* LATER TODO: if FAT32, this is wrong */
|
||||
bootsector->u.fat16.drive_number=s->fat_type==12?0:0x80; /* assume this is hda (TODO) */
|
||||
bootsector->u.fat16.drive_number=s->first_sectors_number==1?0:0x80; /* fda=0, hda=0x80 */
|
||||
bootsector->u.fat16.current_head=0;
|
||||
bootsector->u.fat16.signature=0x29;
|
||||
bootsector->u.fat16.id=cpu_to_le32(0xfabe1afd);
|
||||
@@ -984,7 +985,6 @@ static int is_consistent(BDRVVVFATState *s);
|
||||
static int vvfat_open(BlockDriverState *bs, const char* dirname, int flags)
|
||||
{
|
||||
BDRVVVFATState *s = bs->opaque;
|
||||
int floppy = 0;
|
||||
int i;
|
||||
|
||||
#ifdef DEBUG
|
||||
@@ -998,11 +998,8 @@ DLOG(if (stderr == NULL) {
|
||||
|
||||
s->bs = bs;
|
||||
|
||||
s->fat_type=16;
|
||||
/* LATER TODO: if FAT32, adjust */
|
||||
s->sectors_per_cluster=0x10;
|
||||
/* 504MB disk*/
|
||||
bs->cyls=1024; bs->heads=16; bs->secs=63;
|
||||
|
||||
s->current_cluster=0xffffffff;
|
||||
|
||||
@@ -1017,16 +1014,6 @@ DLOG(if (stderr == NULL) {
|
||||
if (!strstart(dirname, "fat:", NULL))
|
||||
return -1;
|
||||
|
||||
if (strstr(dirname, ":floppy:")) {
|
||||
floppy = 1;
|
||||
s->fat_type = 12;
|
||||
s->first_sectors_number = 1;
|
||||
s->sectors_per_cluster=2;
|
||||
bs->cyls = 80; bs->heads = 2; bs->secs = 36;
|
||||
}
|
||||
|
||||
s->sector_count=bs->cyls*bs->heads*bs->secs;
|
||||
|
||||
if (strstr(dirname, ":32:")) {
|
||||
fprintf(stderr, "Big fat greek warning: FAT32 has not been tested. You are welcome to do so!\n");
|
||||
s->fat_type = 32;
|
||||
@@ -1034,9 +1021,31 @@ DLOG(if (stderr == NULL) {
|
||||
s->fat_type = 16;
|
||||
} else if (strstr(dirname, ":12:")) {
|
||||
s->fat_type = 12;
|
||||
s->sector_count=2880;
|
||||
}
|
||||
|
||||
if (strstr(dirname, ":floppy:")) {
|
||||
/* 1.44MB or 2.88MB floppy. 2.88MB can be FAT12 (default) or FAT16. */
|
||||
if (!s->fat_type) {
|
||||
s->fat_type = 12;
|
||||
bs->secs = 36;
|
||||
s->sectors_per_cluster=2;
|
||||
} else {
|
||||
bs->secs=(s->fat_type == 12 ? 18 : 36);
|
||||
s->sectors_per_cluster=1;
|
||||
}
|
||||
s->first_sectors_number = 1;
|
||||
bs->cyls=80; bs->heads=2;
|
||||
} else {
|
||||
/* 32MB or 504MB disk*/
|
||||
if (!s->fat_type) {
|
||||
s->fat_type = 16;
|
||||
}
|
||||
bs->cyls=(s->fat_type == 12 ? 64 : 1024);
|
||||
bs->heads=16; bs->secs=63;
|
||||
}
|
||||
|
||||
s->sector_count=bs->cyls*bs->heads*bs->secs-(s->first_sectors_number-1);
|
||||
|
||||
if (strstr(dirname, ":rw:")) {
|
||||
if (enable_write_target(s))
|
||||
return -1;
|
||||
@@ -1060,13 +1069,22 @@ DLOG(if (stderr == NULL) {
|
||||
|
||||
if(s->first_sectors_number==0x40)
|
||||
init_mbr(s);
|
||||
|
||||
/* for some reason or other, MS-DOS does not like to know about CHS... */
|
||||
if (floppy)
|
||||
else {
|
||||
/* MS-DOS does not like to know about CHS (?). */
|
||||
bs->heads = bs->cyls = bs->secs = 0;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
@@ -1244,19 +1262,19 @@ static int vvfat_read(BlockDriverState *bs, int64_t sector_num,
|
||||
int i;
|
||||
|
||||
for(i=0;i<nb_sectors;i++,sector_num++) {
|
||||
if (sector_num >= s->sector_count)
|
||||
if (sector_num >= bs->total_sectors)
|
||||
return -1;
|
||||
if (s->qcow) {
|
||||
int n;
|
||||
if (s->qcow->drv->bdrv_is_allocated(s->qcow,
|
||||
sector_num, nb_sectors-i, &n)) {
|
||||
if (bdrv_is_allocated(s->qcow, sector_num, nb_sectors-i, &n)) {
|
||||
DLOG(fprintf(stderr, "sectors %d+%d allocated\n", (int)sector_num, n));
|
||||
if (s->qcow->drv->bdrv_read(s->qcow, sector_num, buf+i*0x200, n))
|
||||
return -1;
|
||||
i += n - 1;
|
||||
sector_num += n - 1;
|
||||
continue;
|
||||
}
|
||||
if (bdrv_read(s->qcow, sector_num, buf + i*0x200, n)) {
|
||||
return -1;
|
||||
}
|
||||
i += n - 1;
|
||||
sector_num += n - 1;
|
||||
continue;
|
||||
}
|
||||
DLOG(fprintf(stderr, "sector %d not allocated\n", (int)sector_num));
|
||||
}
|
||||
if(sector_num<s->faked_sectors) {
|
||||
@@ -1270,7 +1288,7 @@ DLOG(fprintf(stderr, "sector %d not allocated\n", (int)sector_num));
|
||||
uint32_t sector=sector_num-s->faked_sectors,
|
||||
sector_offset_in_cluster=(sector%s->sectors_per_cluster),
|
||||
cluster_num=sector/s->sectors_per_cluster;
|
||||
if(read_cluster(s, cluster_num) != 0) {
|
||||
if(cluster_num > s->cluster_count || read_cluster(s, cluster_num) != 0) {
|
||||
/* LATER TODO: strict: return -1; */
|
||||
memset(buf+i*0x200,0,0x200);
|
||||
continue;
|
||||
@@ -1510,7 +1528,7 @@ static inline int cluster_was_modified(BDRVVVFATState* s, uint32_t cluster_num)
|
||||
return 0;
|
||||
|
||||
for (i = 0; !was_modified && i < s->sectors_per_cluster; i++)
|
||||
was_modified = s->qcow->drv->bdrv_is_allocated(s->qcow,
|
||||
was_modified = bdrv_is_allocated(s->qcow,
|
||||
cluster2sector(s, cluster_num) + i, 1, &dummy);
|
||||
|
||||
return was_modified;
|
||||
@@ -1659,16 +1677,16 @@ static uint32_t get_cluster_count_for_direntry(BDRVVVFATState* s,
|
||||
int64_t offset = cluster2sector(s, cluster_num);
|
||||
|
||||
vvfat_close_current_file(s);
|
||||
for (i = 0; i < s->sectors_per_cluster; i++)
|
||||
if (!s->qcow->drv->bdrv_is_allocated(s->qcow,
|
||||
offset + i, 1, &dummy)) {
|
||||
if (vvfat_read(s->bs,
|
||||
offset, s->cluster_buffer, 1))
|
||||
return -1;
|
||||
if (s->qcow->drv->bdrv_write(s->qcow,
|
||||
offset, s->cluster_buffer, 1))
|
||||
return -2;
|
||||
}
|
||||
for (i = 0; i < s->sectors_per_cluster; i++) {
|
||||
if (!bdrv_is_allocated(s->qcow, offset + i, 1, &dummy)) {
|
||||
if (vvfat_read(s->bs, offset, s->cluster_buffer, 1)) {
|
||||
return -1;
|
||||
}
|
||||
if (bdrv_write(s->qcow, offset, s->cluster_buffer, 1)) {
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2613,7 +2631,9 @@ static int do_commit(BDRVVVFATState* s)
|
||||
return ret;
|
||||
}
|
||||
|
||||
s->qcow->drv->bdrv_make_empty(s->qcow);
|
||||
if (s->qcow->drv->bdrv_make_empty) {
|
||||
s->qcow->drv->bdrv_make_empty(s->qcow);
|
||||
}
|
||||
|
||||
memset(s->used_clusters, 0, sector2cluster(s, s->sector_count));
|
||||
|
||||
@@ -2708,7 +2728,7 @@ DLOG(checkpoint());
|
||||
* Use qcow backend. Commit later.
|
||||
*/
|
||||
DLOG(fprintf(stderr, "Write to qcow backend: %d + %d\n", (int)sector_num, nb_sectors));
|
||||
ret = s->qcow->drv->bdrv_write(s->qcow, sector_num, buf, nb_sectors);
|
||||
ret = bdrv_write(s->qcow, sector_num, buf, nb_sectors);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error writing to qcow backend\n");
|
||||
return ret;
|
||||
@@ -2821,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 = {
|
||||
|
||||
+18
-1
@@ -84,10 +84,27 @@ struct BlockDriver {
|
||||
int64_t sector_num, int nb_sectors, QEMUIOVector *qiov);
|
||||
int coroutine_fn (*bdrv_co_writev)(BlockDriverState *bs,
|
||||
int64_t sector_num, int nb_sectors, QEMUIOVector *qiov);
|
||||
int coroutine_fn (*bdrv_co_flush)(BlockDriverState *bs);
|
||||
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()).
|
||||
*/
|
||||
int coroutine_fn (*bdrv_co_flush_to_disk)(BlockDriverState *bs);
|
||||
|
||||
/*
|
||||
* Flushes all internal caches to the OS. The data may still sit in a
|
||||
* writeback cache of the host OS, but it will survive a crash of the qemu
|
||||
* process.
|
||||
*/
|
||||
int coroutine_fn (*bdrv_co_flush_to_os)(BlockDriverState *bs);
|
||||
|
||||
int (*bdrv_aio_multiwrite)(BlockDriverState *bs, BlockRequest *reqs,
|
||||
int num_reqs);
|
||||
int (*bdrv_merge_requests)(BlockDriverState *bs, BlockRequest* a,
|
||||
|
||||
+6
-4
@@ -635,10 +635,12 @@ static int eject_device(Monitor *mon, BlockDriverState *bs, int force)
|
||||
qerror_report(QERR_DEVICE_NOT_REMOVABLE, bdrv_get_device_name(bs));
|
||||
return -1;
|
||||
}
|
||||
if (!force && !bdrv_dev_is_tray_open(bs)
|
||||
&& bdrv_dev_is_medium_locked(bs)) {
|
||||
qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs));
|
||||
return -1;
|
||||
if (bdrv_dev_is_medium_locked(bs) && !bdrv_dev_is_tray_open(bs)) {
|
||||
bdrv_dev_eject_request(bs, force);
|
||||
if (!force) {
|
||||
qerror_report(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
bdrv_close(bs);
|
||||
return 0;
|
||||
|
||||
@@ -45,13 +45,11 @@ compare(const void *a, const void *b)
|
||||
((const cmdinfo_t *)b)->name);
|
||||
}
|
||||
|
||||
void
|
||||
add_command(
|
||||
const cmdinfo_t *ci)
|
||||
void add_command(const cmdinfo_t *ci)
|
||||
{
|
||||
cmdtab = realloc((void *)cmdtab, ++ncmds * sizeof(*cmdtab));
|
||||
cmdtab[ncmds - 1] = *ci;
|
||||
qsort(cmdtab, ncmds, sizeof(*cmdtab), compare);
|
||||
cmdtab = g_realloc((void *)cmdtab, ++ncmds * sizeof(*cmdtab));
|
||||
cmdtab[ncmds - 1] = *ci;
|
||||
qsort(cmdtab, ncmds, sizeof(*cmdtab), compare);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -122,16 +120,10 @@ find_command(
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
add_user_command(char *optarg)
|
||||
void add_user_command(char *optarg)
|
||||
{
|
||||
ncmdline++;
|
||||
cmdline = realloc(cmdline, sizeof(char*) * (ncmdline));
|
||||
if (!cmdline) {
|
||||
perror("realloc");
|
||||
exit(1);
|
||||
}
|
||||
cmdline[ncmdline-1] = optarg;
|
||||
cmdline = g_realloc(cmdline, ++ncmdline * sizeof(char *));
|
||||
cmdline[ncmdline-1] = optarg;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -160,45 +152,44 @@ static void prep_fetchline(void *opaque)
|
||||
|
||||
static char *get_prompt(void);
|
||||
|
||||
void
|
||||
command_loop(void)
|
||||
void command_loop(void)
|
||||
{
|
||||
int c, i, j = 0, done = 0, fetchable = 0, prompted = 0;
|
||||
char *input;
|
||||
char **v;
|
||||
const cmdinfo_t *ct;
|
||||
int c, i, j = 0, done = 0, fetchable = 0, prompted = 0;
|
||||
char *input;
|
||||
char **v;
|
||||
const cmdinfo_t *ct;
|
||||
|
||||
for (i = 0; !done && i < ncmdline; i++) {
|
||||
input = strdup(cmdline[i]);
|
||||
if (!input) {
|
||||
fprintf(stderr,
|
||||
_("cannot strdup command '%s': %s\n"),
|
||||
cmdline[i], strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
v = breakline(input, &c);
|
||||
if (c) {
|
||||
ct = find_command(v[0]);
|
||||
if (ct) {
|
||||
if (ct->flags & CMD_FLAG_GLOBAL)
|
||||
done = command(ct, c, v);
|
||||
else {
|
||||
j = 0;
|
||||
while (!done && (j = args_command(j)))
|
||||
done = command(ct, c, v);
|
||||
}
|
||||
} else
|
||||
fprintf(stderr, _("command \"%s\" not found\n"),
|
||||
v[0]);
|
||||
}
|
||||
doneline(input, v);
|
||||
}
|
||||
if (cmdline) {
|
||||
free(cmdline);
|
||||
return;
|
||||
for (i = 0; !done && i < ncmdline; i++) {
|
||||
input = strdup(cmdline[i]);
|
||||
if (!input) {
|
||||
fprintf(stderr, _("cannot strdup command '%s': %s\n"),
|
||||
cmdline[i], strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
v = breakline(input, &c);
|
||||
if (c) {
|
||||
ct = find_command(v[0]);
|
||||
if (ct) {
|
||||
if (ct->flags & CMD_FLAG_GLOBAL) {
|
||||
done = command(ct, c, v);
|
||||
} else {
|
||||
j = 0;
|
||||
while (!done && (j = args_command(j))) {
|
||||
done = command(ct, c, v);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, _("command \"%s\" not found\n"), v[0]);
|
||||
}
|
||||
}
|
||||
doneline(input, v);
|
||||
}
|
||||
if (cmdline) {
|
||||
g_free(cmdline);
|
||||
return;
|
||||
}
|
||||
|
||||
while (!done) {
|
||||
while (!done) {
|
||||
if (!prompted) {
|
||||
printf("%s", get_prompt());
|
||||
fflush(stdout);
|
||||
@@ -212,22 +203,24 @@ command_loop(void)
|
||||
if (!fetchable) {
|
||||
continue;
|
||||
}
|
||||
if ((input = fetchline()) == NULL)
|
||||
break;
|
||||
v = breakline(input, &c);
|
||||
if (c) {
|
||||
ct = find_command(v[0]);
|
||||
if (ct)
|
||||
done = command(ct, c, v);
|
||||
else
|
||||
fprintf(stderr, _("command \"%s\" not found\n"),
|
||||
v[0]);
|
||||
}
|
||||
doneline(input, v);
|
||||
input = fetchline();
|
||||
if (input == NULL) {
|
||||
break;
|
||||
}
|
||||
v = breakline(input, &c);
|
||||
if (c) {
|
||||
ct = find_command(v[0]);
|
||||
if (ct) {
|
||||
done = command(ct, c, v);
|
||||
} else {
|
||||
fprintf(stderr, _("command \"%s\" not found\n"), v[0]);
|
||||
}
|
||||
}
|
||||
doneline(input, v);
|
||||
|
||||
prompted = 0;
|
||||
fetchable = 0;
|
||||
}
|
||||
}
|
||||
qemu_aio_set_fd_handler(STDIN_FILENO, NULL, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
@@ -331,29 +324,32 @@ static char *qemu_strsep(char **input, const char *delim)
|
||||
return result;
|
||||
}
|
||||
|
||||
char **
|
||||
breakline(
|
||||
char *input,
|
||||
int *count)
|
||||
char **breakline(char *input, int *count)
|
||||
{
|
||||
int c = 0;
|
||||
char *p;
|
||||
char **rval = calloc(sizeof(char *), 1);
|
||||
int c = 0;
|
||||
char *p;
|
||||
char **rval = calloc(sizeof(char *), 1);
|
||||
char **tmp;
|
||||
|
||||
while (rval && (p = qemu_strsep(&input, " ")) != NULL) {
|
||||
if (!*p)
|
||||
continue;
|
||||
c++;
|
||||
rval = realloc(rval, sizeof(*rval) * (c + 1));
|
||||
if (!rval) {
|
||||
c = 0;
|
||||
break;
|
||||
}
|
||||
rval[c - 1] = p;
|
||||
rval[c] = NULL;
|
||||
}
|
||||
*count = c;
|
||||
return rval;
|
||||
while (rval && (p = qemu_strsep(&input, " ")) != NULL) {
|
||||
if (!*p) {
|
||||
continue;
|
||||
}
|
||||
c++;
|
||||
tmp = realloc(rval, sizeof(*rval) * (c + 1));
|
||||
if (!tmp) {
|
||||
free(rval);
|
||||
rval = NULL;
|
||||
c = 0;
|
||||
break;
|
||||
} else {
|
||||
rval = tmp;
|
||||
}
|
||||
rval[c - 1] = p;
|
||||
rval[c] = NULL;
|
||||
}
|
||||
*count = c;
|
||||
return rval;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -129,6 +129,7 @@ xen=""
|
||||
xen_ctrl_version=""
|
||||
linux_aio=""
|
||||
attr=""
|
||||
libattr=""
|
||||
xfs=""
|
||||
|
||||
vhost_net="no"
|
||||
@@ -138,6 +139,7 @@ debug_tcg="no"
|
||||
debug_mon="no"
|
||||
debug="no"
|
||||
strip_opt="yes"
|
||||
tcg_interpreter="no"
|
||||
bigendian="no"
|
||||
mingw32="no"
|
||||
EXESUF=""
|
||||
@@ -170,7 +172,7 @@ aix="no"
|
||||
blobs="yes"
|
||||
pkgversion=""
|
||||
check_utests=""
|
||||
user_pie="no"
|
||||
pie=""
|
||||
zero_malloc=""
|
||||
trace_backend="nop"
|
||||
trace_file="trace"
|
||||
@@ -567,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"
|
||||
@@ -654,6 +664,10 @@ for opt do
|
||||
;;
|
||||
--enable-kvm) kvm="yes"
|
||||
;;
|
||||
--disable-tcg-interpreter) tcg_interpreter="no"
|
||||
;;
|
||||
--enable-tcg-interpreter) tcg_interpreter="yes"
|
||||
;;
|
||||
--disable-spice) spice="no"
|
||||
;;
|
||||
--enable-spice) spice="yes"
|
||||
@@ -695,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"
|
||||
;;
|
||||
@@ -753,8 +767,6 @@ for opt do
|
||||
;;
|
||||
--enable-opengl) opengl="yes"
|
||||
;;
|
||||
--*dir)
|
||||
;;
|
||||
--disable-rbd) rbd="no"
|
||||
;;
|
||||
--enable-rbd) rbd="yes"
|
||||
@@ -1009,6 +1021,7 @@ echo " --enable-bluez enable bluez stack connectivity"
|
||||
echo " --disable-slirp disable SLIRP userspace network connectivity"
|
||||
echo " --disable-kvm disable KVM acceleration support"
|
||||
echo " --enable-kvm enable KVM acceleration support"
|
||||
echo " --enable-tcg-interpreter enable TCG with bytecode interpreter (TCI)"
|
||||
echo " --disable-nptl disable usermode NPTL support"
|
||||
echo " --enable-nptl enable usermode NPTL support"
|
||||
echo " --enable-system enable all system emulation targets"
|
||||
@@ -1024,12 +1037,13 @@ 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"
|
||||
echo " --enable-uname-release=R Return R for uname -r in usermode emulation"
|
||||
echo " --cpu=CPU Build for host CPU [$cpu]"
|
||||
echo " --sparc_cpu=V Build qemu for Sparc architecture v7, v8, v8plus, v8plusa, v9"
|
||||
echo " --disable-uuid disable uuid support"
|
||||
echo " --enable-uuid enable uuid support"
|
||||
@@ -1091,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
|
||||
#
|
||||
@@ -1955,12 +2020,20 @@ if test "$attr" != "no" ; then
|
||||
cat > $TMPC <<EOF
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef CONFIG_LIBATTR
|
||||
#include <attr/xattr.h>
|
||||
#else
|
||||
#include <sys/xattr.h>
|
||||
#endif
|
||||
int main(void) { getxattr(NULL, NULL, NULL, 0); setxattr(NULL, NULL, NULL, 0, 0); return 0; }
|
||||
EOF
|
||||
if compile_prog "" "-lattr" ; then
|
||||
if compile_prog "" "" ; then
|
||||
attr=yes
|
||||
# Older distros have <attr/xattr.h>, and need -lattr:
|
||||
elif compile_prog "-DCONFIG_LIBATTR" "-lattr" ; then
|
||||
attr=yes
|
||||
LIBS="-lattr $LIBS"
|
||||
libattr=yes
|
||||
else
|
||||
if test "$attr" = "yes" ; then
|
||||
feature_not_found "ATTR"
|
||||
@@ -2184,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
|
||||
@@ -2749,12 +2822,13 @@ 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"
|
||||
echo "Install blobs $blobs"
|
||||
echo "KVM support $kvm"
|
||||
echo "TCG interpreter $tcg_interpreter"
|
||||
echo "fdt support $fdt"
|
||||
echo "preadv support $preadv"
|
||||
echo "fdatasync $fdatasync"
|
||||
@@ -2803,6 +2877,15 @@ case "$cpu" in
|
||||
armv4b|armv4l)
|
||||
ARCH=arm
|
||||
;;
|
||||
*)
|
||||
if test "$tcg_interpreter" = "yes" ; then
|
||||
echo "Unsupported CPU = $cpu, will use TCG with TCI (experimental)"
|
||||
ARCH=tci
|
||||
else
|
||||
echo "Unsupported CPU = $cpu, try --enable-tcg-interpreter"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
echo "ARCH=$ARCH" >> $config_host_mak
|
||||
if test "$debug_tcg" = "yes" ; then
|
||||
@@ -3016,6 +3099,9 @@ fi
|
||||
if test "$attr" = "yes" ; then
|
||||
echo "CONFIG_ATTR=y" >> $config_host_mak
|
||||
fi
|
||||
if test "$libattr" = "yes" ; then
|
||||
echo "CONFIG_LIBATTR=y" >> $config_host_mak
|
||||
fi
|
||||
if test "$linux" = "yes" ; then
|
||||
if test "$attr" = "yes" ; then
|
||||
echo "CONFIG_VIRTFS=y" >> $config_host_mak
|
||||
@@ -3036,6 +3122,9 @@ fi
|
||||
if test "$signalfd" = "yes" ; then
|
||||
echo "CONFIG_SIGNALFD=y" >> $config_host_mak
|
||||
fi
|
||||
if test "$tcg_interpreter" = "yes" ; then
|
||||
echo "CONFIG_TCG_INTERPRETER=y" >> $config_host_mak
|
||||
fi
|
||||
if test "$need_offsetof" = "yes" ; then
|
||||
echo "CONFIG_NEED_OFFSETOF=y" >> $config_host_mak
|
||||
fi
|
||||
@@ -3193,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"
|
||||
@@ -3509,7 +3595,9 @@ cflags=""
|
||||
includes=""
|
||||
ldflags=""
|
||||
|
||||
if test "$ARCH" = "sparc64" ; then
|
||||
if test "$tcg_interpreter" = "yes"; then
|
||||
includes="-I\$(SRC_PATH)/tcg/tci $includes"
|
||||
elif test "$ARCH" = "sparc64" ; then
|
||||
includes="-I\$(SRC_PATH)/tcg/sparc $includes"
|
||||
elif test "$ARCH" = "s390x" ; then
|
||||
includes="-I\$(SRC_PATH)/tcg/s390 $includes"
|
||||
@@ -3586,6 +3674,10 @@ for i in $ARCH $TARGET_BASE_ARCH ; do
|
||||
;;
|
||||
esac
|
||||
done
|
||||
if test "$tcg_interpreter" = "yes" ; then
|
||||
echo "CONFIG_TCI_DIS=y" >> $config_target_mak
|
||||
echo "CONFIG_TCI_DIS=y" >> $libdis_config_mak
|
||||
fi
|
||||
|
||||
case "$ARCH" in
|
||||
alpha)
|
||||
@@ -3608,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
|
||||
@@ -3632,7 +3718,12 @@ if test "$gprof" = "yes" ; then
|
||||
fi
|
||||
fi
|
||||
|
||||
linker_script="-Wl,-T../config-host.ld -Wl,-T,\$(SRC_PATH)/\$(ARCH).ld"
|
||||
if test "$ARCH" = "tci"; then
|
||||
linker_script=""
|
||||
else
|
||||
linker_script="-Wl,-T../config-host.ld -Wl,-T,\$(SRC_PATH)/\$(ARCH).ld"
|
||||
fi
|
||||
|
||||
if test "$target_linux_user" = "yes" -o "$target_bsd_user" = "yes" ; then
|
||||
case "$ARCH" in
|
||||
sparc)
|
||||
@@ -3732,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
|
||||
|
||||
@@ -467,7 +467,7 @@ static void vga_putcharxy(DisplayState *ds, int x, int y, int ch,
|
||||
font_data = *font_ptr++;
|
||||
if (t_attrib->uline
|
||||
&& ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
|
||||
font_data = 0xFFFF;
|
||||
font_data = 0xFF;
|
||||
}
|
||||
((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
|
||||
((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
|
||||
@@ -480,7 +480,7 @@ static void vga_putcharxy(DisplayState *ds, int x, int y, int ch,
|
||||
font_data = *font_ptr++;
|
||||
if (t_attrib->uline
|
||||
&& ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
|
||||
font_data = 0xFFFF;
|
||||
font_data = 0xFF;
|
||||
}
|
||||
((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol;
|
||||
((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol;
|
||||
@@ -493,7 +493,7 @@ static void vga_putcharxy(DisplayState *ds, int x, int y, int ch,
|
||||
for(i = 0; i < FONT_HEIGHT; i++) {
|
||||
font_data = *font_ptr++;
|
||||
if (t_attrib->uline && ((i == FONT_HEIGHT - 2) || (i == FONT_HEIGHT - 3))) {
|
||||
font_data = 0xFFFF;
|
||||
font_data = 0xFF;
|
||||
}
|
||||
((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
|
||||
((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
|
||||
|
||||
@@ -891,6 +891,7 @@ void resume_all_vcpus(void)
|
||||
{
|
||||
CPUState *penv = first_cpu;
|
||||
|
||||
qemu_clock_enable(vm_clock, true);
|
||||
while (penv) {
|
||||
penv->stop = 0;
|
||||
penv->stopped = 0;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -2,3 +2,4 @@
|
||||
|
||||
CONFIG_SERIAL=y
|
||||
CONFIG_OPENCORES_ETH=y
|
||||
CONFIG_PFLASH_CFI01=y
|
||||
@@ -2,3 +2,4 @@
|
||||
|
||||
CONFIG_SERIAL=y
|
||||
CONFIG_OPENCORES_ETH=y
|
||||
CONFIG_PFLASH_CFI01=y
|
||||
@@ -365,6 +365,7 @@ typedef struct disassemble_info {
|
||||
target address. Return number of bytes processed. */
|
||||
typedef int (*disassembler_ftype) (bfd_vma, disassemble_info *);
|
||||
|
||||
int print_insn_tci(bfd_vma, disassemble_info*);
|
||||
int print_insn_big_mips (bfd_vma, disassemble_info*);
|
||||
int print_insn_little_mips (bfd_vma, disassemble_info*);
|
||||
int print_insn_i386 (bfd_vma, disassemble_info*);
|
||||
|
||||
@@ -273,7 +273,9 @@ void disas(FILE *out, void *code, unsigned long size)
|
||||
#else
|
||||
disasm_info.endian = BFD_ENDIAN_LITTLE;
|
||||
#endif
|
||||
#if defined(__i386__)
|
||||
#if defined(CONFIG_TCG_INTERPRETER)
|
||||
print_insn = print_insn_tci;
|
||||
#elif defined(__i386__)
|
||||
disasm_info.mach = bfd_mach_i386_i386;
|
||||
print_insn = print_insn_i386;
|
||||
#elif defined(__x86_64__)
|
||||
|
||||
+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.
|
||||
|
||||
|
||||
+11
-1
@@ -19,7 +19,12 @@
|
||||
#if !defined(__DYNGEN_EXEC_H__)
|
||||
#define __DYNGEN_EXEC_H__
|
||||
|
||||
#if defined(__i386__)
|
||||
#if defined(CONFIG_TCG_INTERPRETER)
|
||||
/* The TCG interpreter does not need a special register AREG0,
|
||||
* but it is possible to use one by defining AREG0.
|
||||
* On i386, register edi seems to work. */
|
||||
/* Run without special register AREG0 or use a value defined elsewhere. */
|
||||
#elif defined(__i386__)
|
||||
#define AREG0 "ebp"
|
||||
#elif defined(__x86_64__)
|
||||
#define AREG0 "r14"
|
||||
@@ -55,6 +60,11 @@
|
||||
#error unsupported CPU
|
||||
#endif
|
||||
|
||||
#if defined(AREG0)
|
||||
register CPUState *env asm(AREG0);
|
||||
#else
|
||||
/* TODO: Try env = cpu_single_env. */
|
||||
extern CPUState *env;
|
||||
#endif
|
||||
|
||||
#endif /* !defined(__DYNGEN_EXEC_H__) */
|
||||
+20
-2
@@ -122,6 +122,8 @@ void tlb_set_page(CPUState *env, target_ulong vaddr,
|
||||
|
||||
#if defined(_ARCH_PPC) || defined(__x86_64__) || defined(__arm__) || defined(__i386__)
|
||||
#define USE_DIRECT_JUMP
|
||||
#elif defined(CONFIG_TCG_INTERPRETER)
|
||||
#define USE_DIRECT_JUMP
|
||||
#endif
|
||||
|
||||
struct TranslationBlock {
|
||||
@@ -189,7 +191,14 @@ extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
|
||||
|
||||
#if defined(USE_DIRECT_JUMP)
|
||||
|
||||
#if defined(_ARCH_PPC)
|
||||
#if defined(CONFIG_TCG_INTERPRETER)
|
||||
static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
|
||||
{
|
||||
/* patch the branch destination */
|
||||
*(uint32_t *)jmp_addr = addr - (jmp_addr + 4);
|
||||
/* no need to flush icache explicitly */
|
||||
}
|
||||
#elif defined(_ARCH_PPC)
|
||||
void ppc_tb_set_jmp_target(unsigned long jmp_addr, unsigned long addr);
|
||||
#define tb_set_jmp_target1 ppc_tb_set_jmp_target
|
||||
#elif defined(__i386__) || defined(__x86_64__)
|
||||
@@ -223,6 +232,8 @@ static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr
|
||||
__asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg));
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
#error tb_set_jmp_target1 is missing
|
||||
#endif
|
||||
|
||||
static inline void tb_set_jmp_target(TranslationBlock *tb,
|
||||
@@ -269,7 +280,14 @@ extern int tb_invalidated_flag;
|
||||
|
||||
/* The return address may point to the start of the next instruction.
|
||||
Subtracting one gets us the call instruction itself. */
|
||||
#if defined(__s390__) && !defined(__s390x__)
|
||||
#if defined(CONFIG_TCG_INTERPRETER)
|
||||
/* Alpha and SH4 user mode emulations and Softmmu call GETPC().
|
||||
For all others, GETPC remains undefined (which makes TCI a little faster. */
|
||||
# if defined(CONFIG_SOFTMMU) || defined(TARGET_ALPHA) || defined(TARGET_SH4)
|
||||
extern void *tci_tb_ptr;
|
||||
# define GETPC() tci_tb_ptr
|
||||
# endif
|
||||
#elif defined(__s390__) && !defined(__s390x__)
|
||||
# define GETPC() ((void*)(((unsigned long)__builtin_return_address(0) & 0x7fffffffUL) - 1))
|
||||
#elif defined(__arm__)
|
||||
/* Thumb return addresses have the low bit set, so we need to subtract two.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include <grp.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <attr/xattr.h>
|
||||
#include "qemu-xattr.h"
|
||||
#include <unistd.h>
|
||||
#include <linux/fs.h>
|
||||
#ifdef CONFIG_LINUX_MAGIC_H
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include <grp.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <attr/xattr.h>
|
||||
#include "qemu-xattr.h"
|
||||
#include <linux/fs.h>
|
||||
#ifdef CONFIG_LINUX_MAGIC_H
|
||||
#include <linux/magic.h>
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <attr/xattr.h>
|
||||
#include "qemu-xattr.h"
|
||||
#include "hw/virtio.h"
|
||||
#include "virtio-9p.h"
|
||||
#include "fsdev/file-op-9p.h"
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#ifndef _QEMU_VIRTIO_9P_XATTR_H
|
||||
#define _QEMU_VIRTIO_9P_XATTR_H
|
||||
|
||||
#include <attr/xattr.h>
|
||||
#include "qemu-xattr.h"
|
||||
|
||||
typedef struct xattr_operations
|
||||
{
|
||||
|
||||
+4
-109
@@ -11,6 +11,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
#include <glib/gprintf.h>
|
||||
|
||||
#include "hw/virtio.h"
|
||||
#include "hw/pc.h"
|
||||
#include "qemu_socket.h"
|
||||
@@ -71,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;
|
||||
@@ -161,114 +155,16 @@ void v9fs_string_null(V9fsString *str)
|
||||
v9fs_string_free(str);
|
||||
}
|
||||
|
||||
static int number_to_string(void *arg, char type)
|
||||
{
|
||||
unsigned int ret = 0;
|
||||
|
||||
switch (type) {
|
||||
case 'u': {
|
||||
unsigned int num = *(unsigned int *)arg;
|
||||
|
||||
do {
|
||||
ret++;
|
||||
num = num/10;
|
||||
} while (num);
|
||||
break;
|
||||
}
|
||||
case 'U': {
|
||||
unsigned long num = *(unsigned long *)arg;
|
||||
do {
|
||||
ret++;
|
||||
num = num/10;
|
||||
} while (num);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printf("Number_to_string: Unknown number format\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int GCC_FMT_ATTR(2, 0)
|
||||
v9fs_string_alloc_printf(char **strp, const char *fmt, va_list ap)
|
||||
{
|
||||
va_list ap2;
|
||||
char *iter = (char *)fmt;
|
||||
int len = 0;
|
||||
int nr_args = 0;
|
||||
char *arg_char_ptr;
|
||||
unsigned int arg_uint;
|
||||
unsigned long arg_ulong;
|
||||
|
||||
/* Find the number of %'s that denotes an argument */
|
||||
for (iter = strstr(iter, "%"); iter; iter = strstr(iter, "%")) {
|
||||
nr_args++;
|
||||
iter++;
|
||||
}
|
||||
|
||||
len = strlen(fmt) - 2*nr_args;
|
||||
|
||||
if (!nr_args) {
|
||||
goto alloc_print;
|
||||
}
|
||||
|
||||
va_copy(ap2, ap);
|
||||
|
||||
iter = (char *)fmt;
|
||||
|
||||
/* Now parse the format string */
|
||||
for (iter = strstr(iter, "%"); iter; iter = strstr(iter, "%")) {
|
||||
iter++;
|
||||
switch (*iter) {
|
||||
case 'u':
|
||||
arg_uint = va_arg(ap2, unsigned int);
|
||||
len += number_to_string((void *)&arg_uint, 'u');
|
||||
break;
|
||||
case 'l':
|
||||
if (*++iter == 'u') {
|
||||
arg_ulong = va_arg(ap2, unsigned long);
|
||||
len += number_to_string((void *)&arg_ulong, 'U');
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
arg_char_ptr = va_arg(ap2, char *);
|
||||
len += strlen(arg_char_ptr);
|
||||
break;
|
||||
case 'c':
|
||||
len += 1;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,
|
||||
"v9fs_string_alloc_printf:Incorrect format %c", *iter);
|
||||
return -1;
|
||||
}
|
||||
iter++;
|
||||
}
|
||||
|
||||
alloc_print:
|
||||
*strp = g_malloc((len + 1) * sizeof(**strp));
|
||||
|
||||
return vsprintf(*strp, fmt, ap);
|
||||
}
|
||||
|
||||
void GCC_FMT_ATTR(2, 3)
|
||||
v9fs_string_sprintf(V9fsString *str, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int err;
|
||||
|
||||
v9fs_string_free(str);
|
||||
|
||||
va_start(ap, fmt);
|
||||
err = v9fs_string_alloc_printf(&str->data, fmt, ap);
|
||||
BUG_ON(err == -1);
|
||||
str->size = g_vasprintf(&str->data, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
str->size = err;
|
||||
}
|
||||
|
||||
void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs)
|
||||
@@ -2539,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 @@ typedef struct AC97BusMasterRegs {
|
||||
typedef struct AC97LinkState {
|
||||
PCIDevice dev;
|
||||
QEMUSoundCard card;
|
||||
uint32_t use_broken_id;
|
||||
uint32_t glob_cnt;
|
||||
uint32_t glob_sta;
|
||||
uint32_t cas;
|
||||
@@ -1305,11 +1306,12 @@ static int ac97_initfn (PCIDevice *dev)
|
||||
c[PCI_BASE_ADDRESS_0 + 6] = 0x00;
|
||||
c[PCI_BASE_ADDRESS_0 + 7] = 0x00;
|
||||
|
||||
c[PCI_SUBSYSTEM_VENDOR_ID] = 0x86; /* svid subsystem vendor id rwo */
|
||||
c[PCI_SUBSYSTEM_VENDOR_ID + 1] = 0x80;
|
||||
|
||||
c[PCI_SUBSYSTEM_ID] = 0x00; /* sid subsystem id rwo */
|
||||
c[PCI_SUBSYSTEM_ID + 1] = 0x00;
|
||||
if (s->use_broken_id) {
|
||||
c[PCI_SUBSYSTEM_VENDOR_ID] = 0x86;
|
||||
c[PCI_SUBSYSTEM_VENDOR_ID + 1] = 0x80;
|
||||
c[PCI_SUBSYSTEM_ID] = 0x00;
|
||||
c[PCI_SUBSYSTEM_ID + 1] = 0x00;
|
||||
}
|
||||
|
||||
c[PCI_INTERRUPT_LINE] = 0x00; /* intr_ln interrupt line rw */
|
||||
c[PCI_INTERRUPT_PIN] = 0x01; /* intr_pn interrupt pin ro */
|
||||
@@ -1350,6 +1352,10 @@ static PCIDeviceInfo ac97_info = {
|
||||
.device_id = PCI_DEVICE_ID_INTEL_82801AA_5,
|
||||
.revision = 0x01,
|
||||
.class_id = PCI_CLASS_MULTIMEDIA_AUDIO,
|
||||
.qdev.props = (Property[]) {
|
||||
DEFINE_PROP_UINT32("use_broken_id", AC97LinkState, use_broken_id, 0),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
}
|
||||
};
|
||||
|
||||
static void ac97_register (void)
|
||||
|
||||
+20
-15
@@ -37,9 +37,8 @@ static const uint8_t gic_id[] =
|
||||
|
||||
typedef struct gic_irq_state
|
||||
{
|
||||
/* ??? The documentation seems to imply the enable bits are global, even
|
||||
for per-cpu interrupts. This seems strange. */
|
||||
unsigned enabled:1;
|
||||
/* The enable bits are only banked for per-cpu interrupts. */
|
||||
unsigned enabled:NCPU;
|
||||
unsigned pending:NCPU;
|
||||
unsigned active:NCPU;
|
||||
unsigned level:NCPU;
|
||||
@@ -54,9 +53,9 @@ typedef struct gic_irq_state
|
||||
#define NUM_CPU(s) 1
|
||||
#endif
|
||||
|
||||
#define GIC_SET_ENABLED(irq) s->irq_state[irq].enabled = 1
|
||||
#define GIC_CLEAR_ENABLED(irq) s->irq_state[irq].enabled = 0
|
||||
#define GIC_TEST_ENABLED(irq) s->irq_state[irq].enabled
|
||||
#define GIC_SET_ENABLED(irq, cm) s->irq_state[irq].enabled |= (cm)
|
||||
#define GIC_CLEAR_ENABLED(irq, cm) s->irq_state[irq].enabled &= ~(cm)
|
||||
#define GIC_TEST_ENABLED(irq, cm) ((s->irq_state[irq].enabled & (cm)) != 0)
|
||||
#define GIC_SET_PENDING(irq, cm) s->irq_state[irq].pending |= (cm)
|
||||
#define GIC_CLEAR_PENDING(irq, cm) s->irq_state[irq].pending &= ~(cm)
|
||||
#define GIC_TEST_PENDING(irq, cm) ((s->irq_state[irq].pending & (cm)) != 0)
|
||||
@@ -128,7 +127,7 @@ static void gic_update(gic_state *s)
|
||||
best_prio = 0x100;
|
||||
best_irq = 1023;
|
||||
for (irq = 0; irq < GIC_NIRQ; irq++) {
|
||||
if (GIC_TEST_ENABLED(irq) && GIC_TEST_PENDING(irq, cm)) {
|
||||
if (GIC_TEST_ENABLED(irq, cm) && GIC_TEST_PENDING(irq, cm)) {
|
||||
if (GIC_GET_PRIORITY(irq, cpu) < best_prio) {
|
||||
best_prio = GIC_GET_PRIORITY(irq, cpu);
|
||||
best_irq = irq;
|
||||
@@ -171,7 +170,7 @@ static void gic_set_irq(void *opaque, int irq, int level)
|
||||
|
||||
if (level) {
|
||||
GIC_SET_LEVEL(irq, ALL_CPU_MASK);
|
||||
if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq)) {
|
||||
if (GIC_TEST_TRIGGER(irq) || GIC_TEST_ENABLED(irq, ALL_CPU_MASK)) {
|
||||
DPRINTF("Set %d pending mask %x\n", irq, GIC_TARGET(irq));
|
||||
GIC_SET_PENDING(irq, GIC_TARGET(irq));
|
||||
}
|
||||
@@ -221,7 +220,7 @@ static void gic_complete_irq(gic_state * s, int cpu, int irq)
|
||||
if (irq != 1023) {
|
||||
/* Mark level triggered interrupts as pending if they are still
|
||||
raised. */
|
||||
if (!GIC_TEST_TRIGGER(irq) && GIC_TEST_ENABLED(irq)
|
||||
if (!GIC_TEST_TRIGGER(irq) && GIC_TEST_ENABLED(irq, cm)
|
||||
&& GIC_TEST_LEVEL(irq, cm) && (GIC_TARGET(irq) & cm) != 0) {
|
||||
DPRINTF("Set %d pending mask %x\n", irq, cm);
|
||||
GIC_SET_PENDING(irq, cm);
|
||||
@@ -280,7 +279,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
|
||||
goto bad_reg;
|
||||
res = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (GIC_TEST_ENABLED(irq + i)) {
|
||||
if (GIC_TEST_ENABLED(irq + i, cm)) {
|
||||
res |= (1 << i);
|
||||
}
|
||||
}
|
||||
@@ -412,9 +411,12 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (value & (1 << i)) {
|
||||
int mask = (irq < 32) ? (1 << cpu) : GIC_TARGET(irq);
|
||||
if (!GIC_TEST_ENABLED(irq + i))
|
||||
int cm = (irq < 32) ? (1 << cpu) : ALL_CPU_MASK;
|
||||
|
||||
if (!GIC_TEST_ENABLED(irq + i, cm)) {
|
||||
DPRINTF("Enabled IRQ %d\n", irq + i);
|
||||
GIC_SET_ENABLED(irq + i);
|
||||
}
|
||||
GIC_SET_ENABLED(irq + i, cm);
|
||||
/* If a raised level triggered IRQ enabled then mark
|
||||
is as pending. */
|
||||
if (GIC_TEST_LEVEL(irq + i, mask)
|
||||
@@ -433,9 +435,12 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
|
||||
value = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (value & (1 << i)) {
|
||||
if (GIC_TEST_ENABLED(irq + i))
|
||||
int cm = (irq < 32) ? (1 << cpu) : ALL_CPU_MASK;
|
||||
|
||||
if (GIC_TEST_ENABLED(irq + i, cm)) {
|
||||
DPRINTF("Disabled IRQ %d\n", irq + i);
|
||||
GIC_CLEAR_ENABLED(irq + i);
|
||||
}
|
||||
GIC_CLEAR_ENABLED(irq + i, cm);
|
||||
}
|
||||
}
|
||||
} else if (offset < 0x280) {
|
||||
@@ -638,7 +643,7 @@ static void gic_reset(gic_state *s)
|
||||
#endif
|
||||
}
|
||||
for (i = 0; i < 16; i++) {
|
||||
GIC_SET_ENABLED(i);
|
||||
GIC_SET_ENABLED(i, ALL_CPU_MASK);
|
||||
GIC_SET_TRIGGER(i);
|
||||
}
|
||||
#ifdef NVIC
|
||||
|
||||
+21
-6
@@ -231,15 +231,30 @@ static void arm_sysctl_write(void *opaque, target_phys_addr_t offset,
|
||||
s->nvflags &= ~val;
|
||||
break;
|
||||
case 0x40: /* RESETCTL */
|
||||
if (board_id(s) == BOARD_ID_VEXPRESS) {
|
||||
switch (board_id(s)) {
|
||||
case BOARD_ID_PB926:
|
||||
if (s->lockval == LOCK_VALUE) {
|
||||
s->resetlevel = val;
|
||||
if (val & 0x100) {
|
||||
qemu_system_reset_request();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BOARD_ID_PBX:
|
||||
case BOARD_ID_PBA8:
|
||||
if (s->lockval == LOCK_VALUE) {
|
||||
s->resetlevel = val;
|
||||
if (val & 0x04) {
|
||||
qemu_system_reset_request();
|
||||
}
|
||||
}
|
||||
break;
|
||||
case BOARD_ID_VEXPRESS:
|
||||
case BOARD_ID_EB:
|
||||
default:
|
||||
/* reserved: RAZ/WI */
|
||||
break;
|
||||
}
|
||||
if (s->lockval == LOCK_VALUE) {
|
||||
s->resetlevel = val;
|
||||
if (val & 0x100)
|
||||
qemu_system_reset_request ();
|
||||
}
|
||||
break;
|
||||
case 0x44: /* PCICTL */
|
||||
/* nothing to do. */
|
||||
|
||||
+2
-2
@@ -269,7 +269,7 @@ static uint64_t icp_pit_read(void *opaque, target_phys_addr_t offset,
|
||||
|
||||
/* ??? Don't know the PrimeCell ID for this device. */
|
||||
n = offset >> 8;
|
||||
if (n > 3) {
|
||||
if (n > 2) {
|
||||
hw_error("sp804_read: Bad timer %d\n", n);
|
||||
}
|
||||
|
||||
@@ -283,7 +283,7 @@ static void icp_pit_write(void *opaque, target_phys_addr_t offset,
|
||||
int n;
|
||||
|
||||
n = offset >> 8;
|
||||
if (n > 3) {
|
||||
if (n > 2) {
|
||||
hw_error("sp804_write: Bad timer %d\n", n);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -358,6 +358,14 @@ static void DMA_run (void)
|
||||
struct dma_cont *d;
|
||||
int icont, ichan;
|
||||
int rearm = 0;
|
||||
static int running = 0;
|
||||
|
||||
if (running) {
|
||||
rearm = 1;
|
||||
goto out;
|
||||
} else {
|
||||
running = 1;
|
||||
}
|
||||
|
||||
d = dma_controllers;
|
||||
|
||||
@@ -374,6 +382,8 @@ static void DMA_run (void)
|
||||
}
|
||||
}
|
||||
|
||||
running = 0;
|
||||
out:
|
||||
if (rearm)
|
||||
qemu_bh_schedule_idle(dma_bh);
|
||||
}
|
||||
|
||||
+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. */
|
||||
|
||||
@@ -157,14 +157,14 @@ static inline uint64_t hpet_calculate_diff(HPETTimer *t, uint64_t current)
|
||||
|
||||
cmp = (uint32_t)t->cmp;
|
||||
diff = cmp - (uint32_t)current;
|
||||
diff = (int32_t)diff > 0 ? diff : (uint32_t)0;
|
||||
diff = (int32_t)diff > 0 ? diff : (uint32_t)1;
|
||||
return (uint64_t)diff;
|
||||
} else {
|
||||
uint64_t diff, cmp;
|
||||
|
||||
cmp = t->cmp;
|
||||
diff = cmp - current;
|
||||
diff = (int64_t)diff > 0 ? diff : (uint64_t)0;
|
||||
diff = (int64_t)diff > 0 ? diff : (uint64_t)1;
|
||||
return diff;
|
||||
}
|
||||
}
|
||||
|
||||
+16
-15
@@ -516,9 +516,14 @@ static unsigned int event_status_media(IDEState *s,
|
||||
|
||||
/* Event notification descriptor */
|
||||
event_code = MEC_NO_CHANGE;
|
||||
if (media_status != MS_TRAY_OPEN && s->events.new_media) {
|
||||
event_code = MEC_NEW_MEDIA;
|
||||
s->events.new_media = false;
|
||||
if (media_status != MS_TRAY_OPEN) {
|
||||
if (s->events.new_media) {
|
||||
event_code = MEC_NEW_MEDIA;
|
||||
s->events.new_media = false;
|
||||
} else if (s->events.eject_request) {
|
||||
event_code = MEC_EJECT_REQUESTED;
|
||||
s->events.eject_request = false;
|
||||
}
|
||||
}
|
||||
|
||||
buf[4] = event_code;
|
||||
@@ -690,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;
|
||||
|
||||
@@ -703,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;
|
||||
@@ -722,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;
|
||||
@@ -741,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;
|
||||
@@ -750,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;
|
||||
|
||||
@@ -772,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;
|
||||
@@ -1038,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 },
|
||||
|
||||
@@ -804,6 +804,18 @@ static void ide_cd_change_cb(void *opaque, bool load)
|
||||
*/
|
||||
s->cdrom_changed = 1;
|
||||
s->events.new_media = true;
|
||||
s->events.eject_request = false;
|
||||
ide_set_irq(s->bus);
|
||||
}
|
||||
|
||||
static void ide_cd_eject_request_cb(void *opaque, bool force)
|
||||
{
|
||||
IDEState *s = opaque;
|
||||
|
||||
s->events.eject_request = true;
|
||||
if (force) {
|
||||
s->tray_locked = false;
|
||||
}
|
||||
ide_set_irq(s->bus);
|
||||
}
|
||||
|
||||
@@ -1811,6 +1823,7 @@ static bool ide_cd_is_medium_locked(void *opaque)
|
||||
|
||||
static const BlockDevOps ide_cd_block_ops = {
|
||||
.change_media_cb = ide_cd_change_cb,
|
||||
.eject_request_cb = ide_cd_eject_request_cb,
|
||||
.is_tray_open = ide_cd_is_tray_open,
|
||||
.is_medium_locked = ide_cd_is_medium_locked,
|
||||
};
|
||||
|
||||
+1
-1
@@ -402,7 +402,7 @@ static bool intel_hda_xfer(HDACodecDevice *dev, uint32_t stnr, bool output,
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (st == NULL) {
|
||||
if (s == 4) {
|
||||
return false;
|
||||
}
|
||||
if (st->bpl == NULL) {
|
||||
|
||||
+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);
|
||||
|
||||
@@ -863,6 +863,7 @@ static void lan9118_eeprom_cmd(lan9118_state *s, int cmd, int addr)
|
||||
} else {
|
||||
DPRINTF("EEPROM Write All (ignored)\n");
|
||||
}
|
||||
break;
|
||||
case 5: /* ERASE */
|
||||
if (s->eeprom_writable) {
|
||||
s->eeprom[addr] = 0xff;
|
||||
|
||||
+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? */
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
# include "flash.h"
|
||||
# include "blockdev.h"
|
||||
# include "sysbus.h"
|
||||
#include "qemu-error.h"
|
||||
|
||||
# define NAND_CMD_READ0 0x00
|
||||
# define NAND_CMD_READ1 0x01
|
||||
@@ -384,18 +385,23 @@ static int nand_device_init(SysBusDevice *dev)
|
||||
nand_init_2048(s);
|
||||
break;
|
||||
default:
|
||||
hw_error("%s: Unsupported NAND block size.\n", __func__);
|
||||
error_report("Unsupported NAND block size");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pagesize = 1 << s->oob_shift;
|
||||
s->mem_oob = 1;
|
||||
if (s->bdrv && bdrv_getlength(s->bdrv) >=
|
||||
(s->pages << s->page_shift) + (s->pages << s->oob_shift)) {
|
||||
pagesize = 0;
|
||||
s->mem_oob = 0;
|
||||
}
|
||||
|
||||
if (!s->bdrv) {
|
||||
if (s->bdrv) {
|
||||
if (bdrv_is_read_only(s->bdrv)) {
|
||||
error_report("Can't use a read-only drive");
|
||||
return -1;
|
||||
}
|
||||
if (bdrv_getlength(s->bdrv) >=
|
||||
(s->pages << s->page_shift) + (s->pages << s->oob_shift)) {
|
||||
pagesize = 0;
|
||||
s->mem_oob = 0;
|
||||
}
|
||||
} else {
|
||||
pagesize += 1 << s->page_shift;
|
||||
}
|
||||
if (pagesize) {
|
||||
|
||||
+5
-4
@@ -389,10 +389,11 @@ static void omap_disc_write(void *opaque, target_phys_addr_t addr,
|
||||
s->dig.enable = (value >> 1) & 1;
|
||||
s->lcd.enable = (value >> 0) & 1;
|
||||
if (value & (1 << 12)) /* OVERLAY_OPTIMIZATION */
|
||||
if (~((s->dispc.l[1].attr | s->dispc.l[2].attr) & 1))
|
||||
fprintf(stderr, "%s: Overlay Optimization when no overlay "
|
||||
"region effectively exists leads to "
|
||||
"unpredictable behaviour!\n", __FUNCTION__);
|
||||
if (!((s->dispc.l[1].attr | s->dispc.l[2].attr) & 1)) {
|
||||
fprintf(stderr, "%s: Overlay Optimization when no overlay "
|
||||
"region effectively exists leads to "
|
||||
"unpredictable behaviour!\n", __func__);
|
||||
}
|
||||
if (value & (1 << 6)) { /* GODIGITAL */
|
||||
/* XXX: Shadowed fields are:
|
||||
* s->dispc.config
|
||||
|
||||
+1
-1
@@ -510,7 +510,7 @@ static void omap2_gpio_module_write(void *opaque, target_phys_addr_t addr,
|
||||
|
||||
static uint32_t omap2_gpio_module_readp(void *opaque, target_phys_addr_t addr)
|
||||
{
|
||||
return omap2_gpio_module_readp(opaque, addr) >> ((addr & 3) << 3);
|
||||
return omap2_gpio_module_read(opaque, addr & ~3) >> ((addr & 3) << 3);
|
||||
}
|
||||
|
||||
static void omap2_gpio_module_writep(void *opaque, target_phys_addr_t addr,
|
||||
|
||||
@@ -180,6 +180,7 @@ static void omap_nand_setio(DeviceState *dev, uint64_t value,
|
||||
nand_setio(dev, (value >> 24) & 0xff);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case OMAP_GPMC_16BIT:
|
||||
switch (size) {
|
||||
case 1:
|
||||
@@ -195,6 +196,7 @@ static void omap_nand_setio(DeviceState *dev, uint64_t value,
|
||||
nand_setio(dev, (value >> 16) & 0xffff);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -398,6 +398,9 @@ static uint64_t omap2_inth_read(void *opaque, target_phys_addr_t addr,
|
||||
if (bank_no < s->nbanks) {
|
||||
offset &= ~0x60;
|
||||
bank = &s->bank[bank_no];
|
||||
} else {
|
||||
OMAP_BAD_REG(addr);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -476,6 +479,9 @@ static void omap2_inth_write(void *opaque, target_phys_addr_t addr,
|
||||
if (bank_no < s->nbanks) {
|
||||
offset &= ~0x60;
|
||||
bank = &s->bank[bank_no];
|
||||
} else {
|
||||
OMAP_BAD_REG(addr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "memory.h"
|
||||
#include "exec-memory.h"
|
||||
#include "sysbus.h"
|
||||
#include "qemu-error.h"
|
||||
|
||||
/* 11 for 2kB-page OneNAND ("2nd generation") and 10 for 1kB-page chips */
|
||||
#define PAGE_SHIFT 11
|
||||
@@ -772,6 +773,10 @@ static int onenand_initfn(SysBusDevice *dev)
|
||||
s->image = memset(g_malloc(size + (size >> 5)),
|
||||
0xff, size + (size >> 5));
|
||||
} else {
|
||||
if (bdrv_is_read_only(s->bdrv)) {
|
||||
error_report("Can't use a read-only drive");
|
||||
return -1;
|
||||
}
|
||||
s->bdrv_cur = s->bdrv;
|
||||
}
|
||||
s->otp = memset(g_malloc((64 + 2) << PAGE_SHIFT),
|
||||
|
||||
@@ -335,7 +335,7 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
|
||||
ISADevice *s)
|
||||
{
|
||||
int val, nb, nb_heads, max_track, last_sect, i;
|
||||
FDriveType fd_type[2];
|
||||
FDriveType fd_type[2] = { FDRIVE_DRV_NONE, FDRIVE_DRV_NONE };
|
||||
BlockDriverState *fd[MAX_FD];
|
||||
static pc_cmos_init_late_arg arg;
|
||||
|
||||
@@ -385,8 +385,6 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
|
||||
bdrv_get_floppy_geometry_hint(fd[i], &nb_heads, &max_track,
|
||||
&last_sect, FDRIVE_DRV_NONE,
|
||||
&fd_type[i]);
|
||||
} else {
|
||||
fd_type[i] = FDRIVE_DRV_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -941,7 +939,6 @@ static CPUState *pc_new_cpu(const char *cpu_model)
|
||||
exit(1);
|
||||
}
|
||||
if ((env->cpuid_features & CPUID_APIC) || smp_cpus > 1) {
|
||||
env->cpuid_apic_id = env->cpu_index;
|
||||
env->apic_state = apic_init(env, env->cpuid_apic_id);
|
||||
}
|
||||
qemu_register_reset(pc_cpu_reset, env);
|
||||
@@ -1104,15 +1101,6 @@ void pc_vga_init(PCIBus *pci_bus)
|
||||
isa_vga_init();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sga does not suppress normal vga output. So a machine can have both a
|
||||
* vga card and sga manually enabled. Output will be seen on both.
|
||||
* For nographic case, sga is enabled at all times
|
||||
*/
|
||||
if (display_type == DT_NOGRAPHIC) {
|
||||
isa_create_simple("sga");
|
||||
}
|
||||
}
|
||||
|
||||
static void cpu_request_exit(void *opaque, int irq, int level)
|
||||
|
||||
+39
-3
@@ -297,8 +297,8 @@ static void pc_xen_hvm_init(ram_addr_t ram_size,
|
||||
}
|
||||
#endif
|
||||
|
||||
static QEMUMachine pc_machine = {
|
||||
.name = "pc-0.14",
|
||||
static QEMUMachine pc_machine_v1_0 = {
|
||||
.name = "pc-1.0",
|
||||
.alias = "pc",
|
||||
.desc = "Standard PC",
|
||||
.init = pc_init_pci,
|
||||
@@ -306,6 +306,25 @@ static QEMUMachine pc_machine = {
|
||||
.is_default = 1,
|
||||
};
|
||||
|
||||
static QEMUMachine pc_machine_v0_14 = {
|
||||
.name = "pc-0.14",
|
||||
.desc = "Standard PC",
|
||||
.init = pc_init_pci,
|
||||
.max_cpus = 255,
|
||||
.compat_props = (GlobalProperty[]) {
|
||||
{
|
||||
.driver = "qxl",
|
||||
.property = "revision",
|
||||
.value = stringify(2),
|
||||
},{
|
||||
.driver = "qxl-vga",
|
||||
.property = "revision",
|
||||
.value = stringify(2),
|
||||
},
|
||||
{ /* end of list */ }
|
||||
},
|
||||
};
|
||||
|
||||
static QEMUMachine pc_machine_v0_13 = {
|
||||
.name = "pc-0.13",
|
||||
.desc = "Standard PC",
|
||||
@@ -340,6 +359,10 @@ static QEMUMachine pc_machine_v0_13 = {
|
||||
.driver = "virtio-net-pci",
|
||||
.property = "event_idx",
|
||||
.value = "off",
|
||||
},{
|
||||
.driver = "AC97",
|
||||
.property = "use_broken_id",
|
||||
.value = stringify(1),
|
||||
},
|
||||
{ /* end of list */ }
|
||||
},
|
||||
@@ -383,6 +406,10 @@ static QEMUMachine pc_machine_v0_12 = {
|
||||
.driver = "virtio-net-pci",
|
||||
.property = "event_idx",
|
||||
.value = "off",
|
||||
},{
|
||||
.driver = "AC97",
|
||||
.property = "use_broken_id",
|
||||
.value = stringify(1),
|
||||
},
|
||||
{ /* end of list */ }
|
||||
}
|
||||
@@ -434,6 +461,10 @@ static QEMUMachine pc_machine_v0_11 = {
|
||||
.driver = "virtio-net-pci",
|
||||
.property = "event_idx",
|
||||
.value = "off",
|
||||
},{
|
||||
.driver = "AC97",
|
||||
.property = "use_broken_id",
|
||||
.value = stringify(1),
|
||||
},
|
||||
{ /* end of list */ }
|
||||
}
|
||||
@@ -497,6 +528,10 @@ static QEMUMachine pc_machine_v0_10 = {
|
||||
.driver = "virtio-net-pci",
|
||||
.property = "event_idx",
|
||||
.value = "off",
|
||||
},{
|
||||
.driver = "AC97",
|
||||
.property = "use_broken_id",
|
||||
.value = stringify(1),
|
||||
},
|
||||
{ /* end of list */ }
|
||||
},
|
||||
@@ -521,7 +556,8 @@ static QEMUMachine xenfv_machine = {
|
||||
|
||||
static void pc_machine_init(void)
|
||||
{
|
||||
qemu_register_machine(&pc_machine);
|
||||
qemu_register_machine(&pc_machine_v1_0);
|
||||
qemu_register_machine(&pc_machine_v0_14);
|
||||
qemu_register_machine(&pc_machine_v0_13);
|
||||
qemu_register_machine(&pc_machine_v0_12);
|
||||
qemu_register_machine(&pc_machine_v0_11);
|
||||
|
||||
+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
-1
@@ -103,7 +103,7 @@ static void pl061_update(pl061_state *s)
|
||||
s->old_data = out;
|
||||
for (i = 0; i < 8; i++) {
|
||||
mask = 1 << i;
|
||||
if ((changed & mask) && s->out) {
|
||||
if (changed & mask) {
|
||||
DPRINTF("Set output %d = %d\n", i, (out & mask) != 0);
|
||||
qemu_set_irq(s->out[i], (out & mask) != 0);
|
||||
}
|
||||
|
||||
+4
-1
@@ -114,7 +114,10 @@ static void pxa2xx_pm_write(void *opaque, target_phys_addr_t addr,
|
||||
|
||||
switch (addr) {
|
||||
case PMCR:
|
||||
s->pm_regs[addr >> 2] &= 0x15 & ~(value & 0x2a);
|
||||
/* Clear the write-one-to-clear bits... */
|
||||
s->pm_regs[addr >> 2] &= ~(value & 0x2a);
|
||||
/* ...and set the plain r/w bits */
|
||||
s->pm_regs[addr >> 2] &= ~0x15;
|
||||
s->pm_regs[addr >> 2] |= value & 0x15;
|
||||
break;
|
||||
|
||||
|
||||
@@ -186,7 +186,7 @@ int qdev_device_help(QemuOpts *opts)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!qemu_opt_get(opts, "?")) {
|
||||
if (!driver || !qemu_opt_get(opts, "?")) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -896,6 +896,20 @@ static void qxl_vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
|
||||
vga_ioport_write(opaque, addr, val);
|
||||
}
|
||||
|
||||
static const MemoryRegionPortio qxl_vga_portio_list[] = {
|
||||
{ 0x04, 2, 1, .read = vga_ioport_read,
|
||||
.write = qxl_vga_ioport_write }, /* 3b4 */
|
||||
{ 0x0a, 1, 1, .read = vga_ioport_read,
|
||||
.write = qxl_vga_ioport_write }, /* 3ba */
|
||||
{ 0x10, 16, 1, .read = vga_ioport_read,
|
||||
.write = qxl_vga_ioport_write }, /* 3c0 */
|
||||
{ 0x24, 2, 1, .read = vga_ioport_read,
|
||||
.write = qxl_vga_ioport_write }, /* 3d4 */
|
||||
{ 0x2a, 1, 1, .read = vga_ioport_read,
|
||||
.write = qxl_vga_ioport_write }, /* 3da */
|
||||
PORTIO_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void qxl_add_memslot(PCIQXLDevice *d, uint32_t slot_id, uint64_t delta,
|
||||
qxl_async_io async)
|
||||
{
|
||||
@@ -1595,6 +1609,7 @@ static int qxl_init_primary(PCIDevice *dev)
|
||||
PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev);
|
||||
VGACommonState *vga = &qxl->vga;
|
||||
ram_addr_t ram_size = msb_mask(qxl->vga.vram_size * 2 - 1);
|
||||
PortioList *qxl_vga_port_list = g_new(PortioList, 1);
|
||||
|
||||
qxl->id = 0;
|
||||
|
||||
@@ -1603,11 +1618,8 @@ static int qxl_init_primary(PCIDevice *dev)
|
||||
}
|
||||
vga_common_init(vga, ram_size);
|
||||
vga_init(vga, pci_address_space(dev), pci_address_space_io(dev), false);
|
||||
register_ioport_write(0x3c0, 16, 1, qxl_vga_ioport_write, vga);
|
||||
register_ioport_write(0x3b4, 2, 1, qxl_vga_ioport_write, vga);
|
||||
register_ioport_write(0x3d4, 2, 1, qxl_vga_ioport_write, vga);
|
||||
register_ioport_write(0x3ba, 1, 1, qxl_vga_ioport_write, vga);
|
||||
register_ioport_write(0x3da, 1, 1, qxl_vga_ioport_write, vga);
|
||||
portio_list_init(qxl_vga_port_list, qxl_vga_portio_list, vga, "vga");
|
||||
portio_list_add(qxl_vga_port_list, pci_address_space_io(dev), 0x3b0);
|
||||
|
||||
vga->ds = graphic_console_init(qxl_hw_update, qxl_hw_invalidate,
|
||||
qxl_hw_screen_dump, qxl_hw_text_update, qxl);
|
||||
|
||||
+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
|
||||
|
||||
+47
-14
@@ -65,6 +65,7 @@ struct SCSIDiskState
|
||||
uint32_t removable;
|
||||
bool media_changed;
|
||||
bool media_event;
|
||||
bool eject_request;
|
||||
QEMUBH *bh;
|
||||
char *version;
|
||||
char *serial;
|
||||
@@ -671,9 +672,14 @@ static int scsi_event_status_media(SCSIDiskState *s, uint8_t *outbuf)
|
||||
|
||||
/* Event notification descriptor */
|
||||
event_code = MEC_NO_CHANGE;
|
||||
if (media_status != MS_TRAY_OPEN && s->media_event) {
|
||||
event_code = MEC_NEW_MEDIA;
|
||||
s->media_event = false;
|
||||
if (media_status != MS_TRAY_OPEN) {
|
||||
if (s->media_event) {
|
||||
event_code = MEC_NEW_MEDIA;
|
||||
s->media_event = false;
|
||||
} else if (s->eject_request) {
|
||||
event_code = MEC_EJECT_REQUESTED;
|
||||
s->eject_request = false;
|
||||
}
|
||||
}
|
||||
|
||||
outbuf[0] = event_code;
|
||||
@@ -791,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;
|
||||
@@ -825,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;
|
||||
@@ -950,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 */
|
||||
@@ -1172,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) {
|
||||
@@ -1306,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) {
|
||||
@@ -1368,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;
|
||||
}
|
||||
@@ -1402,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));
|
||||
@@ -1470,6 +1479,17 @@ static void scsi_cd_change_media_cb(void *opaque, bool load)
|
||||
s->tray_open = !load;
|
||||
s->qdev.unit_attention = SENSE_CODE(UNIT_ATTENTION_NO_MEDIUM);
|
||||
s->media_event = true;
|
||||
s->eject_request = false;
|
||||
}
|
||||
|
||||
static void scsi_cd_eject_request_cb(void *opaque, bool force)
|
||||
{
|
||||
SCSIDiskState *s = opaque;
|
||||
|
||||
s->eject_request = true;
|
||||
if (force) {
|
||||
s->tray_locked = false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool scsi_cd_is_tray_open(void *opaque)
|
||||
@@ -1484,6 +1504,7 @@ static bool scsi_cd_is_medium_locked(void *opaque)
|
||||
|
||||
static const BlockDevOps scsi_cd_block_ops = {
|
||||
.change_media_cb = scsi_cd_change_media_cb,
|
||||
.eject_request_cb = scsi_cd_eject_request_cb,
|
||||
.is_tray_open = scsi_cd_is_tray_open,
|
||||
.is_medium_locked = scsi_cd_is_medium_locked,
|
||||
};
|
||||
@@ -1535,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;
|
||||
}
|
||||
|
||||
@@ -1682,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)
|
||||
|
||||
+1
-5
@@ -30,12 +30,8 @@ static void init_dev(tc58128_dev * dev, const char *filename)
|
||||
int ret, blocks;
|
||||
|
||||
dev->state = WAIT;
|
||||
dev->flash_contents = g_malloc0(FLASH_SIZE);
|
||||
dev->flash_contents = g_malloc(FLASH_SIZE);
|
||||
memset(dev->flash_contents, 0xff, FLASH_SIZE);
|
||||
if (!dev->flash_contents) {
|
||||
fprintf(stderr, "could not alloc memory for flash\n");
|
||||
exit(1);
|
||||
}
|
||||
if (filename) {
|
||||
/* Load flash image skipping the first block */
|
||||
ret = load_image(filename, dev->flash_contents + 528 * 32);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -202,7 +202,6 @@ static void virtex_init(ram_addr_t ram_size,
|
||||
cpu_model = "440-Xilinx";
|
||||
}
|
||||
|
||||
memset(clk_setup, 0, sizeof(clk_setup));
|
||||
env = ppc440_init_xilinx(&ram_size, 1, cpu_model, 400000000);
|
||||
qemu_register_reset(main_cpu_reset, env);
|
||||
|
||||
|
||||
+19
-4
@@ -16,6 +16,7 @@
|
||||
#include "trace.h"
|
||||
#include "blockdev.h"
|
||||
#include "virtio-blk.h"
|
||||
#include "scsi-defs.h"
|
||||
#ifdef __linux__
|
||||
# include <scsi/sg.h>
|
||||
#endif
|
||||
@@ -231,7 +232,20 @@ static void virtio_blk_handle_scsi(VirtIOBlockReq *req)
|
||||
status = VIRTIO_BLK_S_OK;
|
||||
}
|
||||
|
||||
stl_p(&req->scsi->errors, hdr.status);
|
||||
/*
|
||||
* From SCSI-Generic-HOWTO: "Some lower level drivers (e.g. ide-scsi)
|
||||
* clear the masked_status field [hence status gets cleared too, see
|
||||
* block/scsi_ioctl.c] even when a CHECK_CONDITION or COMMAND_TERMINATED
|
||||
* status has occurred. However they do set DRIVER_SENSE in driver_status
|
||||
* field. Also a (sb_len_wr > 0) indicates there is a sense buffer.
|
||||
*/
|
||||
if (hdr.status == 0 && hdr.sb_len_wr > 0) {
|
||||
hdr.status = CHECK_CONDITION;
|
||||
}
|
||||
|
||||
stl_p(&req->scsi->errors,
|
||||
hdr.status | (hdr.msg_status << 8) |
|
||||
(hdr.host_status << 16) | (hdr.driver_status << 24));
|
||||
stl_p(&req->scsi->residual, hdr.resid);
|
||||
stl_p(&req->scsi->sense_len, hdr.sb_len_wr);
|
||||
stl_p(&req->scsi->data_len, hdr.dxfer_len);
|
||||
@@ -471,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);
|
||||
@@ -478,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);
|
||||
|
||||
+9
-9
@@ -113,7 +113,7 @@ static void platform_fixed_ioport_writew(void *opaque, uint32_t addr, uint32_t v
|
||||
{
|
||||
PCIXenPlatformState *s = opaque;
|
||||
|
||||
switch (addr - XEN_PLATFORM_IOPORT) {
|
||||
switch (addr) {
|
||||
case 0:
|
||||
/* Unplug devices. Value is a bitmask of which devices to
|
||||
unplug, with bit 0 the IDE devices, bit 1 the network
|
||||
@@ -152,7 +152,7 @@ static void platform_fixed_ioport_writew(void *opaque, uint32_t addr, uint32_t v
|
||||
static void platform_fixed_ioport_writel(void *opaque, uint32_t addr,
|
||||
uint32_t val)
|
||||
{
|
||||
switch (addr - XEN_PLATFORM_IOPORT) {
|
||||
switch (addr) {
|
||||
case 0:
|
||||
/* PV driver version */
|
||||
break;
|
||||
@@ -163,7 +163,7 @@ static void platform_fixed_ioport_writeb(void *opaque, uint32_t addr, uint32_t v
|
||||
{
|
||||
PCIXenPlatformState *s = opaque;
|
||||
|
||||
switch (addr - XEN_PLATFORM_IOPORT) {
|
||||
switch (addr) {
|
||||
case 0: /* Platform flags */ {
|
||||
hvmmem_type_t mem_type = (val & PFFLAG_ROM_LOCK) ?
|
||||
HVMMEM_ram_ro : HVMMEM_ram_rw;
|
||||
@@ -186,7 +186,7 @@ static uint32_t platform_fixed_ioport_readw(void *opaque, uint32_t addr)
|
||||
{
|
||||
PCIXenPlatformState *s = opaque;
|
||||
|
||||
switch (addr - XEN_PLATFORM_IOPORT) {
|
||||
switch (addr) {
|
||||
case 0:
|
||||
if (s->drivers_blacklisted) {
|
||||
/* The drivers will recognise this magic number and refuse
|
||||
@@ -205,7 +205,7 @@ static uint32_t platform_fixed_ioport_readb(void *opaque, uint32_t addr)
|
||||
{
|
||||
PCIXenPlatformState *s = opaque;
|
||||
|
||||
switch (addr - XEN_PLATFORM_IOPORT) {
|
||||
switch (addr) {
|
||||
case 0:
|
||||
/* Platform flags */
|
||||
return s->flags;
|
||||
@@ -221,7 +221,7 @@ static void platform_fixed_ioport_reset(void *opaque)
|
||||
{
|
||||
PCIXenPlatformState *s = opaque;
|
||||
|
||||
platform_fixed_ioport_writeb(s, XEN_PLATFORM_IOPORT, 0);
|
||||
platform_fixed_ioport_writeb(s, 0, 0);
|
||||
}
|
||||
|
||||
const MemoryRegionPortio xen_platform_ioport[] = {
|
||||
@@ -251,7 +251,7 @@ static void platform_fixed_ioport_init(PCIXenPlatformState* s)
|
||||
static uint32_t xen_platform_ioport_readb(void *opaque, uint32_t addr)
|
||||
{
|
||||
if (addr == 0) {
|
||||
return platform_fixed_ioport_readb(opaque, XEN_PLATFORM_IOPORT);
|
||||
return platform_fixed_ioport_readb(opaque, 0);
|
||||
} else {
|
||||
return ~0u;
|
||||
}
|
||||
@@ -263,7 +263,7 @@ static void xen_platform_ioport_writeb(void *opaque, uint32_t addr, uint32_t val
|
||||
|
||||
switch (addr) {
|
||||
case 0: /* Platform flags */
|
||||
platform_fixed_ioport_writeb(opaque, XEN_PLATFORM_IOPORT, val);
|
||||
platform_fixed_ioport_writeb(opaque, 0, val);
|
||||
break;
|
||||
case 8:
|
||||
log_writeb(s, val);
|
||||
@@ -321,7 +321,7 @@ static int xen_platform_post_load(void *opaque, int version_id)
|
||||
{
|
||||
PCIXenPlatformState *s = opaque;
|
||||
|
||||
platform_fixed_ioport_writeb(s, XEN_PLATFORM_IOPORT, s->flags);
|
||||
platform_fixed_ioport_writeb(s, 0, s->flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Loaded 100 of 186 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user