Compare commits
76 Commits
v0.15.1-qe
...
v0.14.1
Author | SHA1 | Date | |
---|---|---|---|
|
56a60dd6d6 | ||
|
76c9b330e3 | ||
|
9b33410d3b | ||
|
419f1c3503 | ||
|
fc5c4a7a63 | ||
|
22da30fc28 | ||
|
f8a4bf59fe | ||
|
b3d657bce4 | ||
|
a0af597d00 | ||
|
d4b4ba03e8 | ||
|
6f162b368f | ||
|
b25a1bbcda | ||
|
3d19c4e338 | ||
|
2288eb3af2 | ||
|
ecebecffe3 | ||
|
6f9cace17a | ||
|
57c864b1f3 | ||
|
4b35dfea68 | ||
|
cdd8152e56 | ||
|
74b121a007 | ||
|
8d610b6ba2 | ||
|
0850f81099 | ||
|
6a7999b222 | ||
|
e3c8fc83aa | ||
|
bd2483faf1 | ||
|
7083b66b45 | ||
|
9de12c453d | ||
|
c7e9df3bc6 | ||
|
038a866f81 | ||
|
64a216f58e | ||
|
12597b0608 | ||
|
e37dcdfb8d | ||
|
5c9596112c | ||
|
16e07bc282 | ||
|
607a375709 | ||
|
ac12a5af0b | ||
|
b03088c32f | ||
|
eee37d310c | ||
|
28637533d6 | ||
|
23e4cff984 | ||
|
0893194783 | ||
|
e5f1c19665 | ||
|
343c1de916 | ||
|
b75568889f | ||
|
a3dfab563e | ||
|
c1f1ffff21 | ||
|
44d631a001 | ||
|
28b0e1cd0e | ||
|
ddebe9d473 | ||
|
f17f8b687c | ||
|
d27dd7e1a2 | ||
|
c3a965c943 | ||
|
abc9997416 | ||
|
ed97a4f2cf | ||
|
8f7dfd6bda | ||
|
e81c113d28 | ||
|
d4e6590ab8 | ||
|
f188c02db7 | ||
|
7edb1c3a51 | ||
|
fd08f20c23 | ||
|
8798240196 | ||
|
ffbda4e682 | ||
|
81cd8f6047 | ||
|
1299aa0d03 | ||
|
8faaf42a4c | ||
|
f05929b182 | ||
|
bc3aaac57b | ||
|
602c075070 | ||
|
cb5281b199 | ||
|
9a121a2fbf | ||
|
366c2452b1 | ||
|
bbd9827cc7 | ||
|
d7f88b4bbd | ||
|
ea01a58014 | ||
|
0833073edf | ||
|
0e1272f22b |
12
.gitignore
vendored
12
.gitignore
vendored
@@ -15,7 +15,6 @@ libdis*
|
||||
libhw32
|
||||
libhw64
|
||||
libuser
|
||||
qapi-generated
|
||||
qemu-doc.html
|
||||
qemu-tech.html
|
||||
qemu-doc.info
|
||||
@@ -33,7 +32,6 @@ qemu-options.texi
|
||||
qemu-img-cmds.texi
|
||||
qemu-img-cmds.h
|
||||
qemu-io
|
||||
qemu-ga
|
||||
qemu-monitor.texi
|
||||
QMP/qmp-commands.txt
|
||||
.gdbinit
|
||||
@@ -46,9 +44,6 @@ QMP/qmp-commands.txt
|
||||
*.ky
|
||||
*.log
|
||||
*.pdf
|
||||
*.cps
|
||||
*.fns
|
||||
*.kys
|
||||
*.pg
|
||||
*.pyc
|
||||
*.toc
|
||||
@@ -56,8 +51,6 @@ QMP/qmp-commands.txt
|
||||
*.vr
|
||||
*.d
|
||||
*.o
|
||||
*.swp
|
||||
*.orig
|
||||
.pc
|
||||
patches
|
||||
pc-bios/bios-pq/status
|
||||
@@ -65,10 +58,5 @@ pc-bios/vgabios-pq/status
|
||||
pc-bios/optionrom/linuxboot.bin
|
||||
pc-bios/optionrom/multiboot.bin
|
||||
pc-bios/optionrom/multiboot.raw
|
||||
pc-bios/optionrom/extboot.bin
|
||||
pc-bios/optionrom/vapic.bin
|
||||
.stgit-*
|
||||
cscope.*
|
||||
tags
|
||||
TAGS
|
||||
*~
|
||||
|
8
.gitmodules
vendored
8
.gitmodules
vendored
@@ -1,12 +1,6 @@
|
||||
[submodule "roms/vgabios"]
|
||||
path = roms/vgabios
|
||||
url = git://git.kernel.org/pub/scm/virt/kvm/vgabios.git/
|
||||
url = git://git.qemu.org/vgabios.git/
|
||||
[submodule "roms/seabios"]
|
||||
path = roms/seabios
|
||||
url = git://git.qemu.org/seabios.git/
|
||||
[submodule "roms/SLOF"]
|
||||
path = roms/SLOF
|
||||
url = git://git.qemu.org/SLOF.git
|
||||
[submodule "roms/ipxe"]
|
||||
path = roms/ipxe
|
||||
url = git://git.qemu.org/ipxe.git
|
||||
|
@@ -1,9 +1,3 @@
|
||||
This file documents changes for QEMU releases 0.12 and earlier.
|
||||
For changelog information for later releases, see
|
||||
http://wiki.qemu.org/ChangeLog or look at the git history for
|
||||
more detailed information.
|
||||
|
||||
|
||||
version 0.12.0:
|
||||
|
||||
- Update to SeaBIOS 0.5.0
|
||||
@@ -531,7 +525,7 @@ version 0.1.5:
|
||||
|
||||
- ppc64 support + personality() patch (Rusty Russell)
|
||||
- first Alpha CPU patches (Falk Hueffner)
|
||||
- removed bfd.h dependency
|
||||
- removed bfd.h dependancy
|
||||
- fixed shrd, shld, idivl and divl on PowerPC.
|
||||
- fixed buggy glibc PowerPC rint() function (test-i386 passes now on PowerPC).
|
||||
|
||||
|
3
HACKING
3
HACKING
@@ -120,3 +120,6 @@ gcc's printf attribute directive in the prototype.
|
||||
This makes it so gcc's -Wformat and -Wformat-security options can do
|
||||
their jobs and cross-check format strings with the number and types
|
||||
of arguments.
|
||||
|
||||
Currently many functions in QEMU are not following this rule but
|
||||
patches to add the attribute would be very much appreciated.
|
||||
|
23
MAINTAINERS
23
MAINTAINERS
@@ -56,8 +56,8 @@ M: Paul Brook <paul@codesourcery.com>
|
||||
Guest CPU cores (TCG):
|
||||
----------------------
|
||||
Alpha
|
||||
M: Richard Henderson <rth@twiddle.net>
|
||||
S: Maintained
|
||||
M: qemu-devel@nongnu.org
|
||||
S: Orphan
|
||||
F: target-alpha/
|
||||
|
||||
ARM
|
||||
@@ -70,11 +70,6 @@ M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
|
||||
S: Maintained
|
||||
F: target-cris/
|
||||
|
||||
LM32
|
||||
M: Michael Walle <michael@walle.cc>
|
||||
S: Maintained
|
||||
F: target-lm32/
|
||||
|
||||
M68K
|
||||
M: Paul Brook <paul@codesourcery.com>
|
||||
S: Maintained
|
||||
@@ -207,18 +202,6 @@ M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
|
||||
S: Maintained
|
||||
F: hw/etraxfs.c
|
||||
|
||||
LM32 Machines
|
||||
-------------
|
||||
EVR32 and uclinux BSP
|
||||
M: Michael Walle <michael@walle.cc>
|
||||
S: Maintained
|
||||
F: hw/lm32_boards.c
|
||||
|
||||
milkymist
|
||||
M: Michael Walle <michael@walle.cc>
|
||||
S: Maintained
|
||||
F: hw/milkymist.c
|
||||
|
||||
M68K Machines
|
||||
-------------
|
||||
an5206
|
||||
@@ -480,7 +463,7 @@ S: Maintained
|
||||
F: tcg/ia64/
|
||||
|
||||
MIPS target
|
||||
M: Aurelien Jarno <aurelien@aurel32.net>
|
||||
M: Aurelien Jarno <aurelien@aurel32.ne>
|
||||
S: Maintained
|
||||
F: tcg/mips/
|
||||
|
||||
|
144
Makefile
144
Makefile
@@ -88,8 +88,6 @@ include $(SRC_PATH)/Makefile.objs
|
||||
endif
|
||||
|
||||
$(common-obj-y): $(GENERATED_HEADERS)
|
||||
subdir-libcacard: $(oslib-obj-y) $(trace-obj-y) qemu-malloc.o qemu-timer-common.o
|
||||
|
||||
$(filter %-softmmu,$(SUBDIR_RULES)): $(trace-obj-y) $(common-obj-y) subdir-libdis
|
||||
|
||||
$(filter %-user,$(SUBDIR_RULES)): $(GENERATED_HEADERS) $(trace-obj-y) subdir-libdis-user subdir-libuser
|
||||
@@ -106,8 +104,6 @@ audio/audio.o audio/fmodaudio.o: QEMU_CFLAGS += $(FMOD_CFLAGS)
|
||||
|
||||
QEMU_CFLAGS+=$(CURL_CFLAGS)
|
||||
|
||||
QEMU_CFLAGS+=$(GLIB_CFLAGS)
|
||||
|
||||
ui/cocoa.o: ui/cocoa.m
|
||||
|
||||
ui/sdl.o audio/sdlaudio.o ui/sdl_zoom.o baum.o: QEMU_CFLAGS += $(SDL_CFLAGS)
|
||||
@@ -116,31 +112,46 @@ ui/vnc.o: QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
|
||||
|
||||
bt-host.o: QEMU_CFLAGS += $(BLUEZ_CFLAGS)
|
||||
|
||||
ifeq ($(TRACE_BACKEND),dtrace)
|
||||
trace.h: trace.h-timestamp trace-dtrace.h
|
||||
else
|
||||
trace.h: trace.h-timestamp
|
||||
endif
|
||||
trace.h-timestamp: $(SRC_PATH)/trace-events config-host.mak
|
||||
$(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -h < $< > $@," GEN trace.h")
|
||||
@cmp -s $@ trace.h || cp $@ trace.h
|
||||
|
||||
trace.c: trace.c-timestamp
|
||||
trace.c-timestamp: $(SRC_PATH)/trace-events config-host.mak
|
||||
$(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -c < $< > $@," GEN trace.c")
|
||||
@cmp -s $@ trace.c || cp $@ trace.c
|
||||
|
||||
trace.o: trace.c $(GENERATED_HEADERS)
|
||||
|
||||
trace-dtrace.h: trace-dtrace.dtrace
|
||||
$(call quiet-command,dtrace -o $@ -h -s $<, " GEN trace-dtrace.h")
|
||||
|
||||
# Normal practice is to name DTrace probe file with a '.d' extension
|
||||
# but that gets picked up by QEMU's Makefile as an external dependancy
|
||||
# rule file. So we use '.dtrace' instead
|
||||
trace-dtrace.dtrace: trace-dtrace.dtrace-timestamp
|
||||
trace-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events config-host.mak
|
||||
$(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -d < $< > $@," GEN trace-dtrace.dtrace")
|
||||
@cmp -s $@ trace-dtrace.dtrace || cp $@ trace-dtrace.dtrace
|
||||
|
||||
trace-dtrace.o: trace-dtrace.dtrace $(GENERATED_HEADERS)
|
||||
$(call quiet-command,dtrace -o $@ -G -s $<, " GEN trace-dtrace.o")
|
||||
|
||||
simpletrace.o: simpletrace.c $(GENERATED_HEADERS)
|
||||
|
||||
version.o: $(SRC_PATH)/version.rc config-host.mak
|
||||
$(call quiet-command,$(WINDRES) -I. -o $@ $<," RC $(TARGET_DIR)$@")
|
||||
|
||||
version-obj-$(CONFIG_WIN32) += version.o
|
||||
######################################################################
|
||||
# Support building shared library libcacard
|
||||
|
||||
.PHONY: libcacard.la install-libcacard
|
||||
ifeq ($(LIBTOOL),)
|
||||
libcacard.la:
|
||||
@echo "libtool is missing, please install and rerun configure"; exit 1
|
||||
|
||||
install-libcacard:
|
||||
@echo "libtool is missing, please install and rerun configure"; exit 1
|
||||
else
|
||||
libcacard.la: $(GENERATED_HEADERS) $(oslib-obj-y) qemu-malloc.o qemu-timer-common.o $(addsuffix .lo, $(basename $(trace-obj-y)))
|
||||
$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C libcacard V="$(V)" TARGET_DIR="$*/" libcacard.la,)
|
||||
|
||||
install-libcacard: libcacard.la
|
||||
$(call quiet-command,$(MAKE) $(SUBDIR_MAKEFLAGS) -C libcacard V="$(V)" TARGET_DIR="$*/" install-libcacard,)
|
||||
endif
|
||||
######################################################################
|
||||
|
||||
qemu-img.o: qemu-img-cmds.h
|
||||
qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o cmd.o qemu-ga.o: $(GENERATED_HEADERS)
|
||||
qemu-img.o qemu-tool.o qemu-nbd.o qemu-io.o cmd.o: $(GENERATED_HEADERS)
|
||||
|
||||
qemu-img$(EXESUF): qemu-img.o qemu-tool.o qemu-error.o $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) qemu-timer-common.o
|
||||
|
||||
@@ -153,67 +164,27 @@ qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
|
||||
|
||||
check-qint.o check-qstring.o check-qdict.o check-qlist.o check-qfloat.o check-qjson.o: $(GENERATED_HEADERS)
|
||||
|
||||
CHECK_PROG_DEPS = qemu-malloc.o $(oslib-obj-y) $(trace-obj-y) qemu-tool.o
|
||||
CHECK_PROG_DEPS = qemu-malloc.o $(oslib-obj-y) $(trace-obj-y)
|
||||
|
||||
check-qint: check-qint.o qint.o $(CHECK_PROG_DEPS)
|
||||
check-qstring: check-qstring.o qstring.o $(CHECK_PROG_DEPS)
|
||||
check-qdict: check-qdict.o qdict.o qfloat.o qint.o qstring.o qbool.o qlist.o $(CHECK_PROG_DEPS)
|
||||
check-qlist: check-qlist.o qlist.o qint.o $(CHECK_PROG_DEPS)
|
||||
check-qfloat: check-qfloat.o qfloat.o $(CHECK_PROG_DEPS)
|
||||
check-qjson: check-qjson.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o qjson.o json-streamer.o json-lexer.o json-parser.o error.o qerror.o qemu-error.o $(CHECK_PROG_DEPS)
|
||||
|
||||
$(qapi-obj-y): $(GENERATED_HEADERS)
|
||||
qapi-dir := qapi-generated
|
||||
test-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
|
||||
|
||||
$(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
|
||||
$(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
|
||||
$(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
|
||||
$(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
|
||||
$(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
|
||||
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py -o "$(qapi-dir)" -p "qga-" < $<, " GEN $@")
|
||||
$(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 $@")
|
||||
|
||||
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)
|
||||
test-visitor: test-visitor.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o $(qapi-obj-y) error.o osdep.o qemu-malloc.o $(oslib-obj-y) qjson.o json-streamer.o json-lexer.o json-parser.o qerror.o qemu-error.o qemu-tool.o $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
|
||||
|
||||
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 qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o $(qapi-obj-y) error.o osdep.o qemu-malloc.o $(oslib-obj-y) qjson.o json-streamer.o json-lexer.o json-parser.o qerror.o qemu-error.o qemu-tool.o $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o $(qapi-dir)/test-qmp-marshal.o module.o
|
||||
|
||||
QGALIB=qga/guest-agent-command-state.o qga/guest-agent-commands.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)
|
||||
$(QGALIB) qemu-ga.o: $(QGALIB_GEN) $(qapi-obj-y)
|
||||
qemu-ga$(EXESUF): qemu-ga.o $(QGALIB) qemu-tool.o qemu-error.o error.o $(oslib-obj-y) $(trace-obj-y) $(block-obj-y) $(qobject-obj-y) $(version-obj-y) $(qapi-obj-y) qemu-timer-common.o qemu-sockets.o module.o qapi/qmp-dispatch.o qapi/qmp-registry.o $(qapi-dir)/qga-qapi-visit.o $(qapi-dir)/qga-qapi-types.o $(qapi-dir)/qga-qmp-marshal.o
|
||||
|
||||
QEMULIBS=libhw32 libhw64 libuser libdis libdis-user
|
||||
check-qjson: check-qjson.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o qjson.o json-streamer.o json-lexer.o json-parser.o $(CHECK_PROG_DEPS)
|
||||
|
||||
clean:
|
||||
# avoid old build problems by removing potentially incorrect old files
|
||||
rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
|
||||
rm -f qemu-options.def
|
||||
rm -f *.o *.d *.a *.lo $(TOOLS) qemu-ga TAGS cscope.* *.pod *~ */*~
|
||||
rm -Rf .libs
|
||||
rm -f slirp/*.o slirp/*.d audio/*.o audio/*.d block/*.o block/*.d net/*.o net/*.d fsdev/*.o fsdev/*.d ui/*.o ui/*.d qapi/*.o qapi/*.d qga/*.o qga/*.d
|
||||
rm -f *.o *.d *.a $(TOOLS) TAGS cscope.* *.pod *~ */*~
|
||||
rm -f slirp/*.o slirp/*.d audio/*.o audio/*.d block/*.o block/*.d net/*.o net/*.d fsdev/*.o fsdev/*.d ui/*.o ui/*.d
|
||||
rm -f qemu-img-cmds.h
|
||||
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 -rf $(qapi-dir)
|
||||
$(MAKE) -C tests clean
|
||||
for d in $(ALL_SUBDIRS) $(QEMULIBS) libcacard; do \
|
||||
for d in $(ALL_SUBDIRS) libhw32 libhw64 libuser libdis libdis-user; do \
|
||||
if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \
|
||||
rm -f $$d/qemu-options.def; \
|
||||
done
|
||||
@@ -222,12 +193,9 @@ distclean: clean
|
||||
rm -f config-host.mak config-host.h* config-host.ld $(DOCS) qemu-options.texi qemu-img-cmds.texi qemu-monitor.texi
|
||||
rm -f config-all-devices.mak
|
||||
rm -f roms/seabios/config.mak roms/vgabios/config.mak
|
||||
rm -f qemu-doc.info qemu-doc.aux qemu-doc.cp qemu-doc.cps qemu-doc.dvi
|
||||
rm -f qemu-doc.fn qemu-doc.fns qemu-doc.info qemu-doc.ky qemu-doc.kys
|
||||
rm -f qemu-doc.log qemu-doc.pdf qemu-doc.pg qemu-doc.toc qemu-doc.tp
|
||||
rm -f qemu-doc.vr
|
||||
rm -f qemu-doc.info qemu-doc.aux qemu-doc.cp qemu-doc.dvi qemu-doc.fn qemu-doc.info qemu-doc.ky qemu-doc.log qemu-doc.pdf qemu-doc.pg qemu-doc.toc qemu-doc.tp qemu-doc.vr
|
||||
rm -f qemu-tech.info qemu-tech.aux qemu-tech.cp qemu-tech.dvi qemu-tech.fn qemu-tech.info qemu-tech.ky qemu-tech.log qemu-tech.pdf qemu-tech.pg qemu-tech.toc qemu-tech.tp qemu-tech.vr
|
||||
for d in $(TARGET_DIRS) $(QEMULIBS); do \
|
||||
for d in $(TARGET_DIRS) libhw32 libhw64 libuser libdis libdis-user; do \
|
||||
rm -rf $$d || exit 1 ; \
|
||||
done
|
||||
|
||||
@@ -239,15 +207,13 @@ ifdef INSTALL_BLOBS
|
||||
BLOBS=bios.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 \
|
||||
pxe-pcnet.rom pxe-rtl8139.rom pxe-virtio.rom \
|
||||
bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
|
||||
mpc8544ds.dtb \
|
||||
gpxe-eepro100-80861209.rom \
|
||||
pxe-e1000.bin \
|
||||
pxe-ne2k_pci.bin pxe-pcnet.bin \
|
||||
pxe-rtl8139.bin pxe-virtio.bin \
|
||||
bamboo.dtb petalogix-s3adsp1800.dtb \
|
||||
multiboot.bin linuxboot.bin \
|
||||
s390-zipl.rom \
|
||||
spapr-rtas.bin slof.bin
|
||||
BLOBS += extboot.bin
|
||||
BLOBS += vapic.bin
|
||||
s390-zipl.rom
|
||||
else
|
||||
BLOBS=
|
||||
endif
|
||||
@@ -274,12 +240,7 @@ endif
|
||||
ifneq ($(BLOBS),)
|
||||
$(INSTALL_DIR) "$(DESTDIR)$(datadir)"
|
||||
set -e; for x in $(BLOBS); do \
|
||||
if [ -f $(SRC_PATH)/pc-bios/$$x ];then \
|
||||
$(INSTALL_DATA) $(SRC_PATH)/pc-bios/$$x "$(DESTDIR)$(datadir)"; \
|
||||
fi \
|
||||
; if [ -f pc-bios/optionrom/$$x ];then \
|
||||
$(INSTALL_DATA) pc-bios/optionrom/$$x "$(DESTDIR)$(datadir)"; \
|
||||
fi \
|
||||
done
|
||||
endif
|
||||
$(INSTALL_DIR) "$(DESTDIR)$(datadir)/keymaps"
|
||||
@@ -394,13 +355,10 @@ tarbin:
|
||||
$(datadir)/openbios-sparc32 \
|
||||
$(datadir)/openbios-sparc64 \
|
||||
$(datadir)/openbios-ppc \
|
||||
$(datadir)/pxe-e1000.rom \
|
||||
$(datadir)/pxe-eepro100.rom \
|
||||
$(datadir)/pxe-ne2k_pci.rom \
|
||||
$(datadir)/pxe-pcnet.rom \
|
||||
$(datadir)/pxe-rtl8139.rom \
|
||||
$(datadir)/pxe-virtio.rom \
|
||||
$(datadir)/extboot.bin \
|
||||
$(datadir)/pxe-ne2k_pci.bin \
|
||||
$(datadir)/pxe-rtl8139.bin \
|
||||
$(datadir)/pxe-pcnet.bin \
|
||||
$(datadir)/pxe-e1000.bin \
|
||||
$(docdir)/qemu-doc.html \
|
||||
$(docdir)/qemu-tech.html \
|
||||
$(mandir)/man1/qemu.1 \
|
||||
@@ -408,4 +366,4 @@ tarbin:
|
||||
$(mandir)/man8/qemu-nbd.8
|
||||
|
||||
# Include automatically generated dependency files
|
||||
-include $(wildcard *.d audio/*.d slirp/*.d block/*.d net/*.d ui/*.d qapi/*.d qga/*.d)
|
||||
-include $(wildcard *.d audio/*.d slirp/*.d block/*.d net/*.d ui/*.d)
|
||||
|
135
Makefile.objs
135
Makefile.objs
@@ -2,22 +2,21 @@
|
||||
# QObject
|
||||
qobject-obj-y = qint.o qstring.o qdict.o qlist.o qfloat.o qbool.o
|
||||
qobject-obj-y += qjson.o json-lexer.o json-streamer.o json-parser.o
|
||||
qobject-obj-y += qerror.o error.o
|
||||
qobject-obj-y += qerror.o
|
||||
|
||||
#######################################################################
|
||||
# oslib-obj-y is code depending on the OS (win32 vs posix)
|
||||
oslib-obj-y = osdep.o
|
||||
oslib-obj-$(CONFIG_WIN32) += oslib-win32.o qemu-thread-win32.o
|
||||
oslib-obj-$(CONFIG_POSIX) += oslib-posix.o qemu-thread-posix.o
|
||||
oslib-obj-$(CONFIG_WIN32) += oslib-win32.o
|
||||
oslib-obj-$(CONFIG_POSIX) += oslib-posix.o
|
||||
|
||||
#######################################################################
|
||||
# block-obj-y is code used by both qemu system emulation and qemu-img
|
||||
|
||||
block-obj-y = cutils.o cache-utils.o qemu-malloc.o qemu-option.o module.o async.o
|
||||
block-obj-y += nbd.o block.o aio.o aes.o qemu-config.o qemu-progress.o qemu-sockets.o
|
||||
block-obj-y = cutils.o cache-utils.o qemu-malloc.o qemu-option.o module.o
|
||||
block-obj-y += nbd.o block.o aio.o aes.o qemu-config.o
|
||||
block-obj-$(CONFIG_POSIX) += posix-aio-compat.o
|
||||
block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
|
||||
block-obj-$(CONFIG_POSIX) += compatfd.o
|
||||
|
||||
block-nested-y += raw.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vvfat.o
|
||||
block-nested-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o
|
||||
@@ -46,14 +45,12 @@ net-nested-$(CONFIG_SLIRP) += slirp.o
|
||||
net-nested-$(CONFIG_VDE) += vde.o
|
||||
net-obj-y += $(addprefix net/, $(net-nested-y))
|
||||
|
||||
ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy)
|
||||
ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS),yy)
|
||||
# Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add.
|
||||
# only pull in the actual virtio-9p device if we also enabled virtio.
|
||||
CONFIG_REALLY_VIRTFS=y
|
||||
fsdev-nested-y = qemu-fsdev.o
|
||||
else
|
||||
fsdev-nested-y = qemu-fsdev-dummy.o
|
||||
endif
|
||||
fsdev-nested-$(CONFIG_VIRTFS) = qemu-fsdev.o
|
||||
fsdev-obj-$(CONFIG_VIRTFS) += $(addprefix fsdev/, $(fsdev-nested-y))
|
||||
|
||||
######################################################################
|
||||
@@ -66,7 +63,7 @@ common-obj-y = $(block-obj-y) blockdev.o
|
||||
common-obj-y += $(net-obj-y)
|
||||
common-obj-y += $(qobject-obj-y)
|
||||
common-obj-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX))
|
||||
common-obj-y += readline.o console.o cursor.o qemu-error.o
|
||||
common-obj-y += readline.o console.o cursor.o async.o qemu-error.o
|
||||
common-obj-y += $(oslib-obj-y)
|
||||
common-obj-$(CONFIG_WIN32) += os-win32.o
|
||||
common-obj-$(CONFIG_POSIX) += os-posix.o
|
||||
@@ -97,13 +94,12 @@ common-obj-$(CONFIG_SSI_SD) += ssi-sd.o
|
||||
common-obj-$(CONFIG_SD) += sd.o
|
||||
common-obj-y += bt.o bt-host.o bt-vhci.o bt-l2cap.o bt-sdp.o bt-hci.o bt-hid.o usb-bt.o
|
||||
common-obj-y += bt-hci-csr.o
|
||||
common-obj-y += buffered_file.o migration.o migration-tcp.o
|
||||
common-obj-y += buffered_file.o migration.o migration-tcp.o qemu-sockets.o
|
||||
common-obj-y += qemu-char.o savevm.o #aio.o
|
||||
common-obj-y += msmouse.o ps2.o
|
||||
common-obj-y += qdev.o qdev-properties.o
|
||||
common-obj-y += block-migration.o iohandler.o
|
||||
common-obj-y += block-migration.o
|
||||
common-obj-y += pflib.o
|
||||
common-obj-y += bitmap.o bitops.o
|
||||
|
||||
common-obj-$(CONFIG_BRLAPI) += baum.o
|
||||
common-obj-$(CONFIG_POSIX) += migration-exec.o migration-unix.o migration-fd.o
|
||||
@@ -129,24 +125,23 @@ common-obj-y += $(addprefix audio/, $(audio-obj-y))
|
||||
|
||||
ui-obj-y += keymaps.o
|
||||
ui-obj-$(CONFIG_SDL) += sdl.o sdl_zoom.o x_keymap.o
|
||||
ui-obj-$(CONFIG_COCOA) += cocoa.o
|
||||
ui-obj-$(CONFIG_CURSES) += curses.o
|
||||
vnc-obj-y += vnc.o d3des.o
|
||||
vnc-obj-y += vnc-enc-zlib.o vnc-enc-hextile.o
|
||||
vnc-obj-y += vnc-enc-tight.o vnc-palette.o
|
||||
vnc-obj-y += vnc-enc-zrle.o
|
||||
vnc-obj-$(CONFIG_VNC_TLS) += vnc-tls.o vnc-auth-vencrypt.o
|
||||
vnc-obj-$(CONFIG_VNC_SASL) += vnc-auth-sasl.o
|
||||
ui-obj-y += vnc.o d3des.o
|
||||
ui-obj-y += vnc-enc-zlib.o vnc-enc-hextile.o
|
||||
ui-obj-y += vnc-enc-tight.o vnc-palette.o
|
||||
ui-obj-$(CONFIG_VNC_TLS) += vnc-tls.o vnc-auth-vencrypt.o
|
||||
ui-obj-$(CONFIG_VNC_SASL) += vnc-auth-sasl.o
|
||||
ui-obj-$(CONFIG_COCOA) += cocoa.o
|
||||
ifdef CONFIG_VNC_THREAD
|
||||
vnc-obj-y += vnc-jobs-async.o
|
||||
ui-obj-y += vnc-jobs-async.o
|
||||
else
|
||||
vnc-obj-y += vnc-jobs-sync.o
|
||||
ui-obj-y += vnc-jobs-sync.o
|
||||
endif
|
||||
common-obj-y += $(addprefix ui/, $(ui-obj-y))
|
||||
common-obj-$(CONFIG_VNC) += $(addprefix ui/, $(vnc-obj-y))
|
||||
|
||||
common-obj-y += iov.o acl.o
|
||||
#common-obj-$(CONFIG_POSIX) += compatfd.o
|
||||
common-obj-$(CONFIG_THREAD) += qemu-thread.o
|
||||
common-obj-$(CONFIG_IOTHREAD) += compatfd.o
|
||||
common-obj-y += notify.o event_notifier.o
|
||||
common-obj-y += qemu-timer.o qemu-timer-common.o
|
||||
|
||||
@@ -156,8 +151,8 @@ slirp-obj-y += tcp_subr.o tcp_timer.o udp.o bootp.o tftp.o
|
||||
common-obj-$(CONFIG_SLIRP) += $(addprefix slirp/, $(slirp-obj-y))
|
||||
|
||||
# xen backend driver support
|
||||
common-obj-$(CONFIG_XEN_BACKEND) += xen_backend.o xen_devconfig.o
|
||||
common-obj-$(CONFIG_XEN_BACKEND) += xen_console.o xenfb.o xen_disk.o xen_nic.o
|
||||
common-obj-$(CONFIG_XEN) += xen_backend.o xen_devconfig.o
|
||||
common-obj-$(CONFIG_XEN) += xen_console.o xenfb.o xen_disk.o xen_nic.o
|
||||
|
||||
######################################################################
|
||||
# libuser
|
||||
@@ -171,11 +166,10 @@ user-obj-y += cutils.o cache-utils.o
|
||||
# libhw
|
||||
|
||||
hw-obj-y =
|
||||
hw-obj-y += loader.o
|
||||
hw-obj-$(CONFIG_VIRTIO) += virtio-console.o
|
||||
hw-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
|
||||
hw-obj-y += vl.o loader.o
|
||||
hw-obj-$(CONFIG_VIRTIO) += virtio.o virtio-console.o
|
||||
hw-obj-y += fw_cfg.o
|
||||
hw-obj-$(CONFIG_PCI) += pci_bridge.o
|
||||
hw-obj-$(CONFIG_PCI) += pci.o pci_bridge.o
|
||||
hw-obj-$(CONFIG_PCI) += msix.o msi.o
|
||||
hw-obj-$(CONFIG_PCI) += pci_host.o pcie_host.o
|
||||
hw-obj-$(CONFIG_PCI) += ioh3420.o xio3130_upstream.o xio3130_downstream.o
|
||||
@@ -192,23 +186,15 @@ hw-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o
|
||||
|
||||
hw-obj-$(CONFIG_SERIAL) += serial.o
|
||||
hw-obj-$(CONFIG_PARALLEL) += parallel.o
|
||||
# Moved back to Makefile.target due to #include qemu-kvm.h:
|
||||
#hw-obj-$(CONFIG_I8254) += i8254.o
|
||||
#hw-obj-$(CONFIG_PCSPK) += pcspk.o
|
||||
hw-obj-$(CONFIG_I8254) += i8254.o
|
||||
hw-obj-$(CONFIG_PCSPK) += pcspk.o
|
||||
hw-obj-$(CONFIG_PCKBD) += pckbd.o
|
||||
hw-obj-$(CONFIG_USB_UHCI) += usb-uhci.o
|
||||
hw-obj-$(CONFIG_USB_OHCI) += usb-ohci.o
|
||||
hw-obj-$(CONFIG_USB_EHCI) += usb-ehci.o
|
||||
hw-obj-$(CONFIG_FDC) += fdc.o
|
||||
# needs fixes for cpu hotplug, so moved to Makefile.target:
|
||||
# hw-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o
|
||||
hw-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o
|
||||
hw-obj-$(CONFIG_APM) += pm_smbus.o apm.o
|
||||
hw-obj-$(CONFIG_DMA) += dma.o
|
||||
hw-obj-$(CONFIG_HPET) += hpet.o
|
||||
hw-obj-$(CONFIG_APPLESMC) += applesmc.o
|
||||
hw-obj-$(CONFIG_SMARTCARD) += usb-ccid.o ccid-card-passthru.o
|
||||
hw-obj-$(CONFIG_SMARTCARD_NSS) += ccid-card-emulated.o
|
||||
hw-obj-$(CONFIG_USB_REDIR) += usb-redir.o
|
||||
|
||||
# PPC devices
|
||||
hw-obj-$(CONFIG_OPENPIC) += openpic.o
|
||||
@@ -249,7 +235,7 @@ hw-obj-$(CONFIG_LAN9118) += lan9118.o
|
||||
hw-obj-$(CONFIG_NE2000_ISA) += ne2000-isa.o
|
||||
|
||||
# IDE
|
||||
hw-obj-$(CONFIG_IDE_CORE) += ide/core.o ide/atapi.o
|
||||
hw-obj-$(CONFIG_IDE_CORE) += ide/core.o
|
||||
hw-obj-$(CONFIG_IDE_QDEV) += ide/qdev.o
|
||||
hw-obj-$(CONFIG_IDE_PCI) += ide/pci.o
|
||||
hw-obj-$(CONFIG_IDE_ISA) += ide/isa.o
|
||||
@@ -272,7 +258,6 @@ hw-obj-$(CONFIG_VGA_PCI) += vga-pci.o
|
||||
hw-obj-$(CONFIG_VGA_ISA) += vga-isa.o
|
||||
hw-obj-$(CONFIG_VGA_ISA_MM) += vga-isa-mm.o
|
||||
hw-obj-$(CONFIG_VMWARE_VGA) += vmware_vga.o
|
||||
hw-obj-$(CONFIG_VMMOUSE) += vmmouse.o
|
||||
|
||||
hw-obj-$(CONFIG_RC4030) += rc4030.o
|
||||
hw-obj-$(CONFIG_DP8393X) += dp8393x.o
|
||||
@@ -292,12 +277,9 @@ sound-obj-$(CONFIG_HDA) += intel-hda.o hda-audio.o
|
||||
adlib.o fmopl.o: QEMU_CFLAGS += -DBUILD_Y8950=0
|
||||
hw-obj-$(CONFIG_SOUND) += $(sound-obj-y)
|
||||
|
||||
9pfs-nested-$(CONFIG_VIRTFS) = virtio-9p.o virtio-9p-debug.o
|
||||
9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-local.o virtio-9p-xattr.o
|
||||
9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-xattr-user.o virtio-9p-posix-acl.o
|
||||
|
||||
hw-obj-$(CONFIG_REALLY_VIRTFS) += $(addprefix 9pfs/, $(9pfs-nested-y))
|
||||
|
||||
hw-obj-$(CONFIG_REALLY_VIRTFS) += virtio-9p-debug.o
|
||||
hw-obj-$(CONFIG_VIRTFS) += virtio-9p-local.o virtio-9p-xattr.o
|
||||
hw-obj-$(CONFIG_VIRTFS) += virtio-9p-xattr-user.o virtio-9p-posix-acl.o
|
||||
|
||||
######################################################################
|
||||
# libdis
|
||||
@@ -321,46 +303,6 @@ libdis-$(CONFIG_SPARC_DIS) += sparc-dis.o
|
||||
######################################################################
|
||||
# trace
|
||||
|
||||
ifeq ($(TRACE_BACKEND),dtrace)
|
||||
trace.h: trace.h-timestamp trace-dtrace.h
|
||||
else
|
||||
trace.h: trace.h-timestamp
|
||||
endif
|
||||
trace.h-timestamp: $(SRC_PATH)/trace-events config-host.mak
|
||||
$(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -h < $< > $@," GEN trace.h")
|
||||
@cmp -s $@ trace.h || cp $@ trace.h
|
||||
|
||||
trace.c: trace.c-timestamp
|
||||
trace.c-timestamp: $(SRC_PATH)/trace-events config-host.mak
|
||||
$(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -c < $< > $@," GEN trace.c")
|
||||
@cmp -s $@ trace.c || cp $@ trace.c
|
||||
|
||||
trace.o: trace.c $(GENERATED_HEADERS)
|
||||
|
||||
trace-dtrace.h: trace-dtrace.dtrace
|
||||
$(call quiet-command,dtrace -o $@ -h -s $<, " GEN trace-dtrace.h")
|
||||
|
||||
# Normal practice is to name DTrace probe file with a '.d' extension
|
||||
# but that gets picked up by QEMU's Makefile as an external dependency
|
||||
# rule file. So we use '.dtrace' instead
|
||||
trace-dtrace.dtrace: trace-dtrace.dtrace-timestamp
|
||||
trace-dtrace.dtrace-timestamp: $(SRC_PATH)/trace-events config-host.mak
|
||||
$(call quiet-command,sh $(SRC_PATH)/scripts/tracetool --$(TRACE_BACKEND) -d < $< > $@," GEN trace-dtrace.dtrace")
|
||||
@cmp -s $@ trace-dtrace.dtrace || cp $@ trace-dtrace.dtrace
|
||||
|
||||
trace-dtrace.o: trace-dtrace.dtrace $(GENERATED_HEADERS)
|
||||
$(call quiet-command,dtrace -o $@ -G -s $<, " GEN trace-dtrace.o")
|
||||
|
||||
ifeq ($(LIBTOOL),)
|
||||
trace-dtrace.lo: trace-dtrace.dtrace
|
||||
@echo "missing libtool. please install and rerun configure."; exit 1
|
||||
else
|
||||
trace-dtrace.lo: trace-dtrace.dtrace
|
||||
$(call quiet-command,libtool --mode=compile --tag=CC dtrace -o $@ -G -s $<, " lt GEN trace-dtrace.o")
|
||||
endif
|
||||
|
||||
simpletrace.o: simpletrace.c $(GENERATED_HEADERS)
|
||||
|
||||
ifeq ($(TRACE_BACKEND),dtrace)
|
||||
trace-obj-y = trace-dtrace.o
|
||||
else
|
||||
@@ -371,20 +313,7 @@ user-obj-y += qemu-timer-common.o
|
||||
endif
|
||||
endif
|
||||
|
||||
######################################################################
|
||||
# smartcard
|
||||
|
||||
libcacard-y = cac.o event.o vcard.o vreader.o vcard_emul_nss.o vcard_emul_type.o card_7816.o
|
||||
|
||||
######################################################################
|
||||
# qapi
|
||||
|
||||
qapi-nested-y = qapi-visit-core.o qmp-input-visitor.o qmp-output-visitor.o qapi-dealloc-visitor.o
|
||||
qapi-nested-y += qmp-registry.o qmp-dispatch.o
|
||||
qapi-obj-y = $(addprefix qapi/, $(qapi-nested-y))
|
||||
|
||||
vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
|
||||
|
||||
vl.o: QEMU_CFLAGS+=$(SDL_CFLAGS)
|
||||
|
||||
vl.o: QEMU_CFLAGS+=$(GLIB_CFLAGS)
|
||||
|
128
Makefile.target
128
Makefile.target
@@ -3,7 +3,6 @@
|
||||
GENERATED_HEADERS = config-target.h
|
||||
CONFIG_NO_PCI = $(if $(subst n,,$(CONFIG_PCI)),n,y)
|
||||
CONFIG_NO_KVM = $(if $(subst n,,$(CONFIG_KVM)),n,y)
|
||||
CONFIG_NO_XEN = $(if $(subst n,,$(CONFIG_XEN)),n,y)
|
||||
|
||||
include ../config-host.mak
|
||||
include config-devices.mak
|
||||
@@ -15,10 +14,7 @@ endif
|
||||
|
||||
TARGET_PATH=$(SRC_PATH)/target-$(TARGET_BASE_ARCH)
|
||||
$(call set-vpath, $(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw)
|
||||
ifdef CONFIG_LINUX
|
||||
QEMU_CFLAGS += -I../linux-headers
|
||||
endif
|
||||
QEMU_CFLAGS += -I.. -I$(TARGET_PATH) -DNEED_CPU_H
|
||||
QEMU_CFLAGS+= -I.. -I$(TARGET_PATH) -DNEED_CPU_H
|
||||
|
||||
include $(SRC_PATH)/Makefile.objs
|
||||
|
||||
@@ -41,6 +37,8 @@ ifndef CONFIG_HAIKU
|
||||
LIBS+=-lm
|
||||
endif
|
||||
|
||||
kvm.o kvm-all.o vhost.o vhost_net.o: QEMU_CFLAGS+=$(KVM_CFLAGS)
|
||||
|
||||
config-target.h: config-target.h-timestamp
|
||||
config-target.h-timestamp: config-target.mak
|
||||
|
||||
@@ -71,19 +69,15 @@ all: $(PROGS) stap
|
||||
|
||||
#########################################################
|
||||
# cpu emulator library
|
||||
libobj-y = exec.o cpu-exec.o
|
||||
libobj-$(CONFIG_NO_CPU_EMULATION) += fake-exec.o
|
||||
libobj-$(CONFIG_CPU_EMULATION) += translate-all.o translate.o
|
||||
libobj-$(CONFIG_CPU_EMULATION) += tcg/tcg.o
|
||||
libobj-y += fpu/softfloat.o
|
||||
libobj-y = exec.o translate-all.o cpu-exec.o translate.o
|
||||
libobj-y += tcg/tcg.o
|
||||
libobj-$(CONFIG_SOFTFLOAT) += fpu/softfloat.o
|
||||
libobj-$(CONFIG_NOSOFTFLOAT) += fpu/softfloat-native.o
|
||||
libobj-y += op_helper.o helper.o
|
||||
ifeq ($(TARGET_BASE_ARCH), i386)
|
||||
libobj-y += cpuid.o
|
||||
endif
|
||||
libobj-$(CONFIG_NEED_MMU) += mmu.o
|
||||
|
||||
libobj-$(CONFIG_KVM) += kvm-tpr-opt.o
|
||||
|
||||
libobj-$(TARGET_ARM) += neon_helper.o iwmmxt_helper.o
|
||||
|
||||
libobj-y += disas.o
|
||||
@@ -100,10 +94,10 @@ tcg/tcg.o: cpu.h
|
||||
|
||||
# HELPER_CFLAGS is used for all the code compiled with static register
|
||||
# variables
|
||||
op_helper.o user-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
|
||||
op_helper.o cpu-exec.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
|
||||
|
||||
# Note: this is a workaround. The real fix is to avoid compiling
|
||||
# cpu_signal_handler() in user-exec.c.
|
||||
# cpu_signal_handler() in cpu-exec.c.
|
||||
signal.o: QEMU_CFLAGS += $(HELPER_CFLAGS)
|
||||
|
||||
#########################################################
|
||||
@@ -113,10 +107,10 @@ ifdef CONFIG_LINUX_USER
|
||||
|
||||
$(call set-vpath, $(SRC_PATH)/linux-user:$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR))
|
||||
|
||||
QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR) -I$(SRC_PATH)/linux-user
|
||||
QEMU_CFLAGS+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ABI_DIR)
|
||||
obj-y = main.o syscall.o strace.o mmap.o signal.o thunk.o \
|
||||
elfload.o linuxload.o uaccess.o gdbstub.o cpu-uname.o \
|
||||
qemu-malloc.o user-exec.o $(oslib-obj-y)
|
||||
qemu-malloc.o $(oslib-obj-y)
|
||||
|
||||
obj-$(TARGET_HAS_BFLT) += flatload.o
|
||||
|
||||
@@ -154,7 +148,7 @@ LDFLAGS+=-Wl,-segaddr,__STD_PROG_ZONE,0x1000 -image_base 0x0e000000
|
||||
LIBS+=-lmx
|
||||
|
||||
obj-y = main.o commpage.o machload.o mmap.o signal.o syscall.o thunk.o \
|
||||
gdbstub.o user-exec.o
|
||||
gdbstub.o
|
||||
|
||||
obj-i386-y += ioport-user.o
|
||||
|
||||
@@ -176,7 +170,7 @@ $(call set-vpath, $(SRC_PATH)/bsd-user)
|
||||
QEMU_CFLAGS+=-I$(SRC_PATH)/bsd-user -I$(SRC_PATH)/bsd-user/$(TARGET_ARCH)
|
||||
|
||||
obj-y = main.o bsdload.o elfload.o mmap.o signal.o strace.o syscall.o \
|
||||
gdbstub.o uaccess.o user-exec.o
|
||||
gdbstub.o uaccess.o
|
||||
|
||||
obj-i386-y += ioport-user.o
|
||||
|
||||
@@ -192,15 +186,15 @@ endif #CONFIG_BSD_USER
|
||||
# System emulator target
|
||||
ifdef CONFIG_SOFTMMU
|
||||
|
||||
obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o vl.o balloon.o
|
||||
obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o balloon.o
|
||||
# virtio has to be here due to weird dependency between PCI and virtio-net.
|
||||
# need to fix this properly
|
||||
obj-$(CONFIG_NO_PCI) += pci-stub.o
|
||||
obj-$(CONFIG_PCI) += pci.o
|
||||
obj-$(CONFIG_VIRTIO) += virtio.o virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
|
||||
obj-$(CONFIG_VIRTIO) += virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
|
||||
obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
|
||||
obj-y += vhost_net.o
|
||||
obj-$(CONFIG_VHOST_NET) += vhost.o
|
||||
obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p-device.o
|
||||
obj-$(CONFIG_REALLY_VIRTFS) += virtio-9p.o
|
||||
obj-y += rwhandler.o
|
||||
obj-$(CONFIG_KVM) += kvm.o kvm-all.o
|
||||
obj-$(CONFIG_NO_KVM) += kvm-stub.o
|
||||
@@ -210,47 +204,22 @@ QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
|
||||
QEMU_CFLAGS += $(VNC_SASL_CFLAGS)
|
||||
QEMU_CFLAGS += $(VNC_JPEG_CFLAGS)
|
||||
QEMU_CFLAGS += $(VNC_PNG_CFLAGS)
|
||||
QEMU_CFLAGS += $(GLIB_CFLAGS)
|
||||
|
||||
# xen support
|
||||
obj-$(CONFIG_XEN) += xen-all.o xen_machine_pv.o xen_domainbuild.o xen-mapcache.o
|
||||
obj-$(CONFIG_NO_XEN) += xen-stub.o
|
||||
|
||||
obj-i386-$(CONFIG_XEN) += xen_platform.o
|
||||
# xen backend driver support
|
||||
obj-$(CONFIG_XEN) += xen_machine_pv.o xen_domainbuild.o
|
||||
|
||||
# Inter-VM PCI shared memory
|
||||
CONFIG_IVSHMEM =
|
||||
ifeq ($(CONFIG_KVM), y)
|
||||
ifeq ($(CONFIG_PCI), y)
|
||||
CONFIG_IVSHMEM = y
|
||||
endif
|
||||
endif
|
||||
obj-$(CONFIG_IVSHMEM) += ivshmem.o
|
||||
obj-$(CONFIG_KVM) += ivshmem.o
|
||||
|
||||
# Hardware support
|
||||
obj-i386-y += vga.o
|
||||
obj-i386-y += mc146818rtc.o i8259.o pc.o
|
||||
obj-i386-y += cirrus_vga.o sga.o apic.o ioapic.o piix_pci.o
|
||||
obj-i386-y += vmport.o
|
||||
obj-i386-y += cirrus_vga.o apic.o ioapic.o piix_pci.o
|
||||
obj-i386-y += vmmouse.o vmport.o hpet.o applesmc.o
|
||||
obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
|
||||
obj-i386-y += extboot.o
|
||||
obj-i386-y += debugcon.o multiboot.o
|
||||
obj-i386-y += pc_piix.o
|
||||
obj-i386-$(CONFIG_KVM) += kvmclock.o
|
||||
obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
|
||||
obj-i386-y += testdev.o
|
||||
obj-i386-y += acpi.o acpi_piix4.o
|
||||
|
||||
obj-i386-y += pcspk.o i8254.o
|
||||
obj-i386-$(CONFIG_KVM_PIT) += i8254-kvm.o
|
||||
obj-i386-$(CONFIG_KVM_DEVICE_ASSIGNMENT) += device-assignment.o
|
||||
|
||||
# Hardware support
|
||||
obj-ia64-y += ide.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
|
||||
obj-ia64-y += fdc.o mc146818rtc.o serial.o i8259.o ipf.o
|
||||
obj-ia64-y += cirrus_vga.o parallel.o acpi.o piix_pci.o
|
||||
obj-ia64-y += usb-uhci.o
|
||||
obj-ia64-$(CONFIG_KVM_DEVICE_ASSIGNMENT) += device-assignment.o
|
||||
|
||||
# shared objects
|
||||
obj-ppc-y = ppc.o
|
||||
@@ -262,16 +231,11 @@ obj-ppc-y += ppc_prep.o
|
||||
obj-ppc-y += ppc_oldworld.o
|
||||
# NewWorld PowerMac
|
||||
obj-ppc-y += ppc_newworld.o
|
||||
# IBM pSeries (sPAPR)
|
||||
ifeq ($(CONFIG_FDT)$(TARGET_PPC64),yy)
|
||||
obj-ppc-y += spapr.o spapr_hcall.o spapr_rtas.o spapr_vio.o
|
||||
obj-ppc-y += xics.o spapr_vty.o spapr_llan.o spapr_vscsi.o
|
||||
endif
|
||||
# PowerPC 4xx boards
|
||||
obj-ppc-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
|
||||
obj-ppc-y += ppc440.o ppc440_bamboo.o
|
||||
# PowerPC E500 boards
|
||||
obj-ppc-y += ppce500_mpc8544ds.o mpc8544_guts.o
|
||||
obj-ppc-y += ppce500_mpc8544ds.o
|
||||
# PowerPC 440 Xilinx ML507 reference board.
|
||||
obj-ppc-y += virtex_ml507.o
|
||||
obj-ppc-$(CONFIG_KVM) += kvm_ppc.o
|
||||
@@ -283,31 +247,7 @@ obj-ppc-y += xilinx_timer.o
|
||||
obj-ppc-y += xilinx_uartlite.o
|
||||
obj-ppc-y += xilinx_ethlite.o
|
||||
|
||||
# LM32 boards
|
||||
obj-lm32-y += lm32_boards.o
|
||||
obj-lm32-y += milkymist.o
|
||||
|
||||
# LM32 peripherals
|
||||
obj-lm32-y += lm32_pic.o
|
||||
obj-lm32-y += lm32_juart.o
|
||||
obj-lm32-y += lm32_timer.o
|
||||
obj-lm32-y += lm32_uart.o
|
||||
obj-lm32-y += lm32_sys.o
|
||||
obj-lm32-y += milkymist-ac97.o
|
||||
obj-lm32-y += milkymist-hpdmc.o
|
||||
obj-lm32-y += milkymist-memcard.o
|
||||
obj-lm32-y += milkymist-minimac2.o
|
||||
obj-lm32-y += milkymist-pfpu.o
|
||||
obj-lm32-y += milkymist-softusb.o
|
||||
obj-lm32-y += milkymist-sysctl.o
|
||||
obj-lm32-$(CONFIG_OPENGL) += milkymist-tmu2.o
|
||||
obj-lm32-y += milkymist-uart.o
|
||||
obj-lm32-y += milkymist-vgafb.o
|
||||
obj-lm32-y += framebuffer.o
|
||||
|
||||
obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
|
||||
obj-mips-y += pcspk.o i8254.o
|
||||
obj-mips-y += acpi.o acpi_piix4.o
|
||||
obj-mips-y += mips_addr.o mips_timer.o mips_int.o
|
||||
obj-mips-y += vga.o i8259.o
|
||||
obj-mips-y += g364fb.o jazz_led.o
|
||||
@@ -316,15 +256,12 @@ obj-mips-y += cirrus_vga.o
|
||||
obj-mips-$(CONFIG_FULONG) += bonito.o vt82c686.o mips_fulong2e.o
|
||||
|
||||
obj-microblaze-y = petalogix_s3adsp1800_mmu.o
|
||||
obj-microblaze-y += petalogix_ml605_mmu.o
|
||||
|
||||
obj-microblaze-y += microblaze_pic_cpu.o
|
||||
obj-microblaze-y += xilinx_intc.o
|
||||
obj-microblaze-y += xilinx_timer.o
|
||||
obj-microblaze-y += xilinx_uartlite.o
|
||||
obj-microblaze-y += xilinx_ethlite.o
|
||||
obj-microblaze-y += xilinx_axidma.o
|
||||
obj-microblaze-y += xilinx_axienet.o
|
||||
|
||||
obj-microblaze-$(CONFIG_FDT) += device_tree.o
|
||||
|
||||
@@ -378,9 +315,6 @@ obj-arm-y += framebuffer.o
|
||||
obj-arm-y += syborg.o syborg_fb.o syborg_interrupt.o syborg_keyboard.o
|
||||
obj-arm-y += syborg_serial.o syborg_timer.o syborg_pointer.o syborg_rtc.o
|
||||
obj-arm-y += syborg_virtio.o
|
||||
obj-arm-y += vexpress.o
|
||||
obj-arm-y += strongarm.o
|
||||
obj-arm-y += collie.o
|
||||
|
||||
obj-sh4-y = shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o
|
||||
obj-sh4-y += sh_timer.o sh_serial.o sh_intc.o sh_pci.o sm501.o
|
||||
@@ -391,13 +325,7 @@ obj-m68k-y += m68k-semi.o dummy_m68k.o
|
||||
|
||||
obj-s390x-y = s390-virtio-bus.o s390-virtio.o
|
||||
|
||||
obj-alpha-y = i8259.o mc146818rtc.o
|
||||
obj-alpha-y += vga.o cirrus_vga.o
|
||||
|
||||
ifeq ($(TARGET_ARCH), ia64)
|
||||
firmware.o: firmware.c
|
||||
$(CC) $(HELPER_CFLAGS) $(CPPFLAGS) $(BASE_CFLAGS) -c -o $@ $<
|
||||
endif
|
||||
obj-alpha-y = alpha_palcode.o
|
||||
|
||||
main.o: QEMU_CFLAGS+=$(GPROF_CFLAGS)
|
||||
|
||||
@@ -412,12 +340,6 @@ obj-y += $(addprefix $(HWDIR)/, $(hw-obj-y))
|
||||
|
||||
endif # CONFIG_SOFTMMU
|
||||
|
||||
ifndef CONFIG_LINUX_USER
|
||||
# libcacard needs qemu-thread support, and besides is only needed by devices
|
||||
# so not requires with linux-user targets
|
||||
obj-$(CONFIG_SMARTCARD_NSS) += $(addprefix ../libcacard/, $(libcacard-y))
|
||||
endif # CONFIG_LINUX_USER
|
||||
|
||||
obj-y += $(addprefix ../, $(trace-obj-y))
|
||||
obj-$(CONFIG_GDBSTUB_XML) += gdbstub-xml.o
|
||||
|
||||
@@ -436,7 +358,7 @@ qmp-commands.h: $(SRC_PATH)/qmp-commands.hx
|
||||
|
||||
clean:
|
||||
rm -f *.o *.a *~ $(PROGS) nwfpe/*.o fpu/*.o
|
||||
rm -f *.d */*.d tcg/*.o ide/*.o 9pfs/*.o
|
||||
rm -f *.d */*.d tcg/*.o ide/*.o
|
||||
rm -f hmp-commands.h qmp-commands.h gdbstub-xml.c
|
||||
ifdef CONFIG_SYSTEMTAP_TRACE
|
||||
rm -f *.stp
|
||||
|
54
QMP/qmp.py
54
QMP/qmp.py
@@ -22,24 +22,19 @@ class QMPCapabilitiesError(QMPError):
|
||||
pass
|
||||
|
||||
class QEMUMonitorProtocol:
|
||||
def __init__(self, address, server=False):
|
||||
def __init__(self, address):
|
||||
"""
|
||||
Create a QEMUMonitorProtocol class.
|
||||
|
||||
@param address: QEMU address, can be either a unix socket path (string)
|
||||
or a tuple in the form ( address, port ) for a TCP
|
||||
connection
|
||||
@param server: server mode listens on the socket (bool)
|
||||
@raise socket.error on socket connection errors
|
||||
@note No connection is established, this is done by the connect() or
|
||||
accept() methods
|
||||
@note No connection is established, this is done by the connect() method
|
||||
"""
|
||||
self.__events = []
|
||||
self.__address = address
|
||||
self.__sock = self.__get_sock()
|
||||
if server:
|
||||
self.__sock.bind(self.__address)
|
||||
self.__sock.listen(1)
|
||||
self.__sockfile = self.__sock.makefile()
|
||||
|
||||
def __get_sock(self):
|
||||
if isinstance(self.__address, tuple):
|
||||
@@ -48,18 +43,7 @@ class QEMUMonitorProtocol:
|
||||
family = socket.AF_UNIX
|
||||
return socket.socket(family, socket.SOCK_STREAM)
|
||||
|
||||
def __negotiate_capabilities(self):
|
||||
self.__sockfile = self.__sock.makefile()
|
||||
greeting = self.__json_read()
|
||||
if greeting is None or not greeting.has_key('QMP'):
|
||||
raise QMPConnectError
|
||||
# Greeting seems ok, negotiate capabilities
|
||||
resp = self.cmd('qmp_capabilities')
|
||||
if "return" in resp:
|
||||
return greeting
|
||||
raise QMPCapabilitiesError
|
||||
|
||||
def __json_read(self, only_event=False):
|
||||
def __json_read(self):
|
||||
while True:
|
||||
data = self.__sockfile.readline()
|
||||
if not data:
|
||||
@@ -67,8 +51,7 @@ class QEMUMonitorProtocol:
|
||||
resp = json.loads(data)
|
||||
if 'event' in resp:
|
||||
self.__events.append(resp)
|
||||
if not only_event:
|
||||
continue
|
||||
continue
|
||||
return resp
|
||||
|
||||
error = socket.error
|
||||
@@ -83,19 +66,14 @@ class QEMUMonitorProtocol:
|
||||
@raise QMPCapabilitiesError if fails to negotiate capabilities
|
||||
"""
|
||||
self.__sock.connect(self.__address)
|
||||
return self.__negotiate_capabilities()
|
||||
|
||||
def accept(self):
|
||||
"""
|
||||
Await connection from QMP Monitor and perform capabilities negotiation.
|
||||
|
||||
@return QMP greeting dict
|
||||
@raise socket.error on socket connection errors
|
||||
@raise QMPConnectError if the greeting is not received
|
||||
@raise QMPCapabilitiesError if fails to negotiate capabilities
|
||||
"""
|
||||
self.__sock, _ = self.__sock.accept()
|
||||
return self.__negotiate_capabilities()
|
||||
greeting = self.__json_read()
|
||||
if greeting is None or not greeting.has_key('QMP'):
|
||||
raise QMPConnectError
|
||||
# Greeting seems ok, negotiate capabilities
|
||||
resp = self.cmd('qmp_capabilities')
|
||||
if "return" in resp:
|
||||
return greeting
|
||||
raise QMPCapabilitiesError
|
||||
|
||||
def cmd_obj(self, qmp_cmd):
|
||||
"""
|
||||
@@ -128,11 +106,9 @@ class QEMUMonitorProtocol:
|
||||
qmp_cmd['id'] = id
|
||||
return self.cmd_obj(qmp_cmd)
|
||||
|
||||
def get_events(self, wait=False):
|
||||
def get_events(self):
|
||||
"""
|
||||
Get a list of available QMP events.
|
||||
|
||||
@param wait: block until an event is available (bool)
|
||||
"""
|
||||
self.__sock.setblocking(0)
|
||||
try:
|
||||
@@ -142,8 +118,6 @@ class QEMUMonitorProtocol:
|
||||
# No data available
|
||||
pass
|
||||
self.__sock.setblocking(1)
|
||||
if not self.__events and wait:
|
||||
self.__json_read(only_event=True)
|
||||
return self.__events
|
||||
|
||||
def clear_events(self):
|
||||
|
1
acl.c
1
acl.c
@@ -24,6 +24,7 @@
|
||||
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "sysemu.h"
|
||||
#include "acl.h"
|
||||
|
||||
#ifdef CONFIG_FNMATCH
|
||||
|
@@ -238,6 +238,10 @@ extern const unsigned alpha_num_operands;
|
||||
#define AXP_REG_SP 30
|
||||
#define AXP_REG_ZERO 31
|
||||
|
||||
#define bfd_mach_alpha_ev4 0x10
|
||||
#define bfd_mach_alpha_ev5 0x20
|
||||
#define bfd_mach_alpha_ev6 0x30
|
||||
|
||||
enum bfd_reloc_code_real {
|
||||
BFD_RELOC_23_PCREL_S2,
|
||||
BFD_RELOC_ALPHA_HINT
|
||||
|
@@ -64,8 +64,6 @@ const char arch_config_name[] = CONFIG_QEMU_CONFDIR "/target-" TARGET_ARCH ".con
|
||||
#define QEMU_ARCH QEMU_ARCH_I386
|
||||
#elif defined(TARGET_M68K)
|
||||
#define QEMU_ARCH QEMU_ARCH_M68K
|
||||
#elif defined(TARGET_LM32)
|
||||
#define QEMU_ARCH QEMU_ARCH_LM32
|
||||
#elif defined(TARGET_MICROBLAZE)
|
||||
#define QEMU_ARCH QEMU_ARCH_MICROBLAZE
|
||||
#elif defined(TARGET_MIPS)
|
||||
@@ -709,11 +707,6 @@ int audio_available(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
int tcg_available(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int kvm_available(void)
|
||||
{
|
||||
#ifdef CONFIG_KVM
|
||||
|
16
arch_init.h
16
arch_init.h
@@ -10,24 +10,24 @@ enum {
|
||||
QEMU_ARCH_CRIS = 4,
|
||||
QEMU_ARCH_I386 = 8,
|
||||
QEMU_ARCH_M68K = 16,
|
||||
QEMU_ARCH_LM32 = 32,
|
||||
QEMU_ARCH_MICROBLAZE = 64,
|
||||
QEMU_ARCH_MIPS = 128,
|
||||
QEMU_ARCH_PPC = 256,
|
||||
QEMU_ARCH_S390X = 512,
|
||||
QEMU_ARCH_SH4 = 1024,
|
||||
QEMU_ARCH_SPARC = 2048,
|
||||
QEMU_ARCH_MICROBLAZE = 32,
|
||||
QEMU_ARCH_MIPS = 64,
|
||||
QEMU_ARCH_PPC = 128,
|
||||
QEMU_ARCH_S390X = 256,
|
||||
QEMU_ARCH_SH4 = 512,
|
||||
QEMU_ARCH_SPARC = 1024,
|
||||
};
|
||||
|
||||
extern const uint32_t arch_type;
|
||||
|
||||
void select_soundhw(const char *optarg);
|
||||
int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque);
|
||||
int ram_load(QEMUFile *f, void *opaque, int version_id);
|
||||
void do_acpitable_option(const char *optarg);
|
||||
void do_smbios_option(const char *optarg);
|
||||
void cpudef_init(void);
|
||||
int audio_available(void);
|
||||
void audio_init(qemu_irq *isa_pic, PCIBus *pci_bus);
|
||||
int tcg_available(void);
|
||||
int kvm_available(void);
|
||||
int xen_available(void);
|
||||
|
||||
|
123
arm-semi.c
123
arm-semi.c
@@ -33,8 +33,8 @@
|
||||
#define ARM_ANGEL_HEAP_SIZE (128 * 1024 * 1024)
|
||||
#else
|
||||
#include "qemu-common.h"
|
||||
#include "sysemu.h"
|
||||
#include "gdbstub.h"
|
||||
#include "hw/arm-misc.h"
|
||||
#endif
|
||||
|
||||
#define SYS_OPEN 0x01
|
||||
@@ -370,88 +370,68 @@ uint32_t do_arm_semihosting(CPUState *env)
|
||||
return syscall_err;
|
||||
#endif
|
||||
case SYS_GET_CMDLINE:
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
/* Build a commandline from the original argv. */
|
||||
{
|
||||
/* Build a command-line from the original argv.
|
||||
*
|
||||
* The inputs are:
|
||||
* * ARG(0), pointer to a buffer of at least the size
|
||||
* specified in ARG(1).
|
||||
* * ARG(1), size of the buffer pointed to by ARG(0) in
|
||||
* bytes.
|
||||
*
|
||||
* The outputs are:
|
||||
* * ARG(0), pointer to null-terminated string of the
|
||||
* command line.
|
||||
* * ARG(1), length of the string pointed to by ARG(0).
|
||||
*/
|
||||
char *arm_cmdline_buffer;
|
||||
const char *host_cmdline_buffer;
|
||||
|
||||
char *output_buffer;
|
||||
size_t input_size = ARG(1);
|
||||
size_t output_size;
|
||||
int status = 0;
|
||||
|
||||
/* Compute the size of the output string. */
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
output_size = strlen(ts->boot_info->kernel_filename)
|
||||
+ 1 /* Separating space. */
|
||||
+ strlen(ts->boot_info->kernel_cmdline)
|
||||
+ 1; /* Terminating null byte. */
|
||||
#else
|
||||
unsigned int i;
|
||||
unsigned int arm_cmdline_len = ARG(1);
|
||||
unsigned int host_cmdline_len =
|
||||
ts->info->arg_end-ts->info->arg_start;
|
||||
|
||||
output_size = ts->info->arg_end - ts->info->arg_start;
|
||||
if (!output_size) {
|
||||
if (!arm_cmdline_len || host_cmdline_len > arm_cmdline_len) {
|
||||
return -1; /* not enough space to store command line */
|
||||
}
|
||||
|
||||
if (!host_cmdline_len) {
|
||||
/* We special-case the "empty command line" case (argc==0).
|
||||
Just provide the terminating 0. */
|
||||
output_size = 1;
|
||||
}
|
||||
#endif
|
||||
arm_cmdline_buffer = lock_user(VERIFY_WRITE, ARG(0), 1, 0);
|
||||
arm_cmdline_buffer[0] = 0;
|
||||
unlock_user(arm_cmdline_buffer, ARG(0), 1);
|
||||
|
||||
if (output_size > input_size) {
|
||||
/* Not enough space to store command-line arguments. */
|
||||
return -1;
|
||||
/* Adjust the commandline length argument. */
|
||||
SET_ARG(1, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Adjust the command-line length. */
|
||||
SET_ARG(1, output_size - 1);
|
||||
/* lock the buffers on the ARM side */
|
||||
arm_cmdline_buffer =
|
||||
lock_user(VERIFY_WRITE, ARG(0), host_cmdline_len, 0);
|
||||
host_cmdline_buffer =
|
||||
lock_user(VERIFY_READ, ts->info->arg_start,
|
||||
host_cmdline_len, 1);
|
||||
|
||||
/* Lock the buffer on the ARM side. */
|
||||
output_buffer = lock_user(VERIFY_WRITE, ARG(0), output_size, 0);
|
||||
if (!output_buffer) {
|
||||
return -1;
|
||||
}
|
||||
if (arm_cmdline_buffer && host_cmdline_buffer)
|
||||
{
|
||||
/* the last argument is zero-terminated;
|
||||
no need for additional termination */
|
||||
memcpy(arm_cmdline_buffer, host_cmdline_buffer,
|
||||
host_cmdline_len);
|
||||
|
||||
/* Copy the command-line arguments. */
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
pstrcpy(output_buffer, output_size, ts->boot_info->kernel_filename);
|
||||
pstrcat(output_buffer, output_size, " ");
|
||||
pstrcat(output_buffer, output_size, ts->boot_info->kernel_cmdline);
|
||||
#else
|
||||
if (output_size == 1) {
|
||||
/* Empty command-line. */
|
||||
output_buffer[0] = '\0';
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (copy_from_user(output_buffer, ts->info->arg_start,
|
||||
output_size)) {
|
||||
status = -1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Separate arguments by white spaces. */
|
||||
for (i = 0; i < output_size - 1; i++) {
|
||||
if (output_buffer[i] == 0) {
|
||||
output_buffer[i] = ' ';
|
||||
/* separate arguments by white spaces */
|
||||
for (i = 0; i < host_cmdline_len-1; i++) {
|
||||
if (arm_cmdline_buffer[i] == 0) {
|
||||
arm_cmdline_buffer[i] = ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
out:
|
||||
#endif
|
||||
/* Unlock the buffer on the ARM side. */
|
||||
unlock_user(output_buffer, ARG(0), output_size);
|
||||
|
||||
return status;
|
||||
/* Adjust the commandline length argument. */
|
||||
SET_ARG(1, host_cmdline_len-1);
|
||||
}
|
||||
|
||||
/* Unlock the buffers on the ARM side. */
|
||||
unlock_user(arm_cmdline_buffer, ARG(0), host_cmdline_len);
|
||||
unlock_user((void*)host_cmdline_buffer, ts->info->arg_start, 0);
|
||||
|
||||
/* Return success if we could return a commandline. */
|
||||
return (arm_cmdline_buffer && host_cmdline_buffer) ? 0 : -1;
|
||||
}
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
case SYS_HEAPINFO:
|
||||
{
|
||||
uint32_t *ptr;
|
||||
@@ -461,16 +441,15 @@ uint32_t do_arm_semihosting(CPUState *env)
|
||||
/* Some C libraries assume the heap immediately follows .bss, so
|
||||
allocate it using sbrk. */
|
||||
if (!ts->heap_limit) {
|
||||
abi_ulong ret;
|
||||
long ret;
|
||||
|
||||
ts->heap_base = do_brk(0);
|
||||
limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE;
|
||||
/* Try a big heap, and reduce the size if that fails. */
|
||||
for (;;) {
|
||||
ret = do_brk(limit);
|
||||
if (ret >= limit) {
|
||||
if (ret != -1)
|
||||
break;
|
||||
}
|
||||
limit = (ts->heap_base >> 1) + (limit >> 1);
|
||||
}
|
||||
ts->heap_limit = limit;
|
||||
|
12
arm.ld
12
arm.ld
@@ -71,23 +71,23 @@ SECTIONS
|
||||
.data1 : { *(.data1) }
|
||||
.preinit_array :
|
||||
{
|
||||
PROVIDE (__preinit_array_start = .);
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP (*(.preinit_array))
|
||||
PROVIDE (__preinit_array_end = .);
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
}
|
||||
.init_array :
|
||||
{
|
||||
PROVIDE (__init_array_start = .);
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(SORT(.init_array.*)))
|
||||
KEEP (*(.init_array))
|
||||
PROVIDE (__init_array_end = .);
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
}
|
||||
.fini_array :
|
||||
{
|
||||
PROVIDE (__fini_array_start = .);
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP (*(.fini_array))
|
||||
KEEP (*(SORT(.fini_array.*)))
|
||||
PROVIDE (__fini_array_end = .);
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
}
|
||||
.ctors :
|
||||
{
|
||||
|
5
async.c
5
async.c
@@ -137,12 +137,11 @@ QEMUBH *qemu_bh_new(QEMUBHFunc *cb, void *opaque)
|
||||
|
||||
int qemu_bh_poll(void)
|
||||
{
|
||||
QEMUBH *bh, **bhp, *next;
|
||||
QEMUBH *bh, **bhp;
|
||||
int ret;
|
||||
|
||||
ret = 0;
|
||||
for (bh = async_context->first_bh; bh; bh = next) {
|
||||
next = bh->next;
|
||||
for (bh = async_context->first_bh; bh; bh = bh->next) {
|
||||
if (!bh->deleted && bh->scheduled) {
|
||||
bh->scheduled = 0;
|
||||
if (!bh->idle)
|
||||
|
@@ -1114,7 +1114,7 @@ static int audio_is_timer_needed (void)
|
||||
static void audio_reset_timer (AudioState *s)
|
||||
{
|
||||
if (audio_is_timer_needed ()) {
|
||||
qemu_mod_timer (s->ts, qemu_get_clock_ns (vm_clock) + 1);
|
||||
qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + 1);
|
||||
}
|
||||
else {
|
||||
qemu_del_timer (s->ts);
|
||||
@@ -1820,7 +1820,7 @@ static void audio_init (void)
|
||||
QLIST_INIT (&s->cap_head);
|
||||
atexit (audio_atexit);
|
||||
|
||||
s->ts = qemu_new_timer_ns (vm_clock, audio_timer, s);
|
||||
s->ts = qemu_new_timer (vm_clock, audio_timer, s);
|
||||
if (!s->ts) {
|
||||
hw_error("Could not create audio timer\n");
|
||||
}
|
||||
|
@@ -6,6 +6,8 @@
|
||||
#include "audio_int.h"
|
||||
#include "audio_pt_int.h"
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
static void GCC_FMT_ATTR(3, 4) logerr (struct audio_pt *pt, int err,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
|
@@ -56,7 +56,7 @@ typedef struct coreaudioVoiceOut {
|
||||
|
||||
static void coreaudio_logstatus (OSStatus status)
|
||||
{
|
||||
const char *str = "BUG";
|
||||
char *str = "BUG";
|
||||
|
||||
switch(status) {
|
||||
case kAudioHardwareNoError:
|
||||
@@ -104,7 +104,7 @@ static void coreaudio_logstatus (OSStatus status)
|
||||
break;
|
||||
|
||||
default:
|
||||
AUD_log (AUDIO_CAP, "Reason: status code %" PRId32 "\n", (int32_t)status);
|
||||
AUD_log (AUDIO_CAP, "Reason: status code %ld\n", status);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -360,8 +360,8 @@ static int coreaudio_init_out (HWVoiceOut *hw, struct audsettings *as)
|
||||
&core->audioDevicePropertyBufferFrameSize);
|
||||
if (status != kAudioHardwareNoError) {
|
||||
coreaudio_logerr2 (status, typ,
|
||||
"Could not set device buffer frame size %" PRIu32 "\n",
|
||||
(uint32_t)core->audioDevicePropertyBufferFrameSize);
|
||||
"Could not set device buffer frame size %ld\n",
|
||||
core->audioDevicePropertyBufferFrameSize);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@@ -46,7 +46,7 @@ static mixeng_real inline glue (conv_, ET) (IN_T v)
|
||||
#endif
|
||||
#else /* !RECIPROCAL */
|
||||
#ifdef SIGNED
|
||||
return nv / (mixeng_real) ((mixeng_real) IN_MAX - IN_MIN);
|
||||
return nv / (mixeng_real) (IN_MAX - IN_MIN);
|
||||
#else
|
||||
return (nv - HALF) / (mixeng_real) IN_MAX;
|
||||
#endif
|
||||
@@ -63,7 +63,7 @@ static IN_T inline glue (clip_, ET) (mixeng_real v)
|
||||
}
|
||||
|
||||
#ifdef SIGNED
|
||||
return ENDIAN_CONVERT ((IN_T) (v * ((mixeng_real) IN_MAX - IN_MIN)));
|
||||
return ENDIAN_CONVERT ((IN_T) (v * (IN_MAX - IN_MIN)));
|
||||
#else
|
||||
return ENDIAN_CONVERT ((IN_T) ((v * IN_MAX) + HALF));
|
||||
#endif
|
||||
|
@@ -46,7 +46,7 @@ static int no_run_out (HWVoiceOut *hw, int live)
|
||||
int64_t ticks;
|
||||
int64_t bytes;
|
||||
|
||||
now = qemu_get_clock_ns (vm_clock);
|
||||
now = qemu_get_clock (vm_clock);
|
||||
ticks = now - no->old_ticks;
|
||||
bytes = muldiv64 (ticks, hw->info.bytes_per_second, get_ticks_per_sec ());
|
||||
bytes = audio_MIN (bytes, INT_MAX);
|
||||
@@ -102,7 +102,7 @@ static int no_run_in (HWVoiceIn *hw)
|
||||
int samples = 0;
|
||||
|
||||
if (dead) {
|
||||
int64_t now = qemu_get_clock_ns (vm_clock);
|
||||
int64_t now = qemu_get_clock (vm_clock);
|
||||
int64_t ticks = now - no->old_ticks;
|
||||
int64_t bytes =
|
||||
muldiv64 (ticks, hw->info.bytes_per_second, get_ticks_per_sec ());
|
||||
|
@@ -32,6 +32,7 @@
|
||||
#elif defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#define AUDIO_CAP "sdl"
|
||||
@@ -138,36 +139,36 @@ static int aud_to_sdlfmt (audfmt_e fmt)
|
||||
}
|
||||
}
|
||||
|
||||
static int sdl_to_audfmt(int sdlfmt, audfmt_e *fmt, int *endianness)
|
||||
static int sdl_to_audfmt (int sdlfmt, audfmt_e *fmt, int *endianess)
|
||||
{
|
||||
switch (sdlfmt) {
|
||||
case AUDIO_S8:
|
||||
*endianness = 0;
|
||||
*endianess = 0;
|
||||
*fmt = AUD_FMT_S8;
|
||||
break;
|
||||
|
||||
case AUDIO_U8:
|
||||
*endianness = 0;
|
||||
*endianess = 0;
|
||||
*fmt = AUD_FMT_U8;
|
||||
break;
|
||||
|
||||
case AUDIO_S16LSB:
|
||||
*endianness = 0;
|
||||
*endianess = 0;
|
||||
*fmt = AUD_FMT_S16;
|
||||
break;
|
||||
|
||||
case AUDIO_U16LSB:
|
||||
*endianness = 0;
|
||||
*endianess = 0;
|
||||
*fmt = AUD_FMT_U16;
|
||||
break;
|
||||
|
||||
case AUDIO_S16MSB:
|
||||
*endianness = 1;
|
||||
*endianess = 1;
|
||||
*fmt = AUD_FMT_S16;
|
||||
break;
|
||||
|
||||
case AUDIO_U16MSB:
|
||||
*endianness = 1;
|
||||
*endianess = 1;
|
||||
*fmt = AUD_FMT_U16;
|
||||
break;
|
||||
|
||||
@@ -337,7 +338,7 @@ static int sdl_init_out (HWVoiceOut *hw, struct audsettings *as)
|
||||
SDLVoiceOut *sdl = (SDLVoiceOut *) hw;
|
||||
SDLAudioState *s = &glob_sdl;
|
||||
SDL_AudioSpec req, obt;
|
||||
int endianness;
|
||||
int endianess;
|
||||
int err;
|
||||
audfmt_e effective_fmt;
|
||||
struct audsettings obt_as;
|
||||
@@ -353,7 +354,7 @@ static int sdl_init_out (HWVoiceOut *hw, struct audsettings *as)
|
||||
return -1;
|
||||
}
|
||||
|
||||
err = sdl_to_audfmt(obt.format, &effective_fmt, &endianness);
|
||||
err = sdl_to_audfmt (obt.format, &effective_fmt, &endianess);
|
||||
if (err) {
|
||||
sdl_close (s);
|
||||
return -1;
|
||||
@@ -362,7 +363,7 @@ static int sdl_init_out (HWVoiceOut *hw, struct audsettings *as)
|
||||
obt_as.freq = obt.freq;
|
||||
obt_as.nchannels = obt.channels;
|
||||
obt_as.fmt = effective_fmt;
|
||||
obt_as.endianness = endianness;
|
||||
obt_as.endianness = endianess;
|
||||
|
||||
audio_pcm_init_info (&hw->info, &obt_as);
|
||||
hw->samples = obt.samples;
|
||||
|
@@ -81,7 +81,7 @@ static void spice_audio_fini (void *opaque)
|
||||
static void rate_start (SpiceRateCtl *rate)
|
||||
{
|
||||
memset (rate, 0, sizeof (*rate));
|
||||
rate->start_ticks = qemu_get_clock_ns (vm_clock);
|
||||
rate->start_ticks = qemu_get_clock (vm_clock);
|
||||
}
|
||||
|
||||
static int rate_get_samples (struct audio_pcm_info *info, SpiceRateCtl *rate)
|
||||
@@ -91,7 +91,7 @@ static int rate_get_samples (struct audio_pcm_info *info, SpiceRateCtl *rate)
|
||||
int64_t bytes;
|
||||
int64_t samples;
|
||||
|
||||
now = qemu_get_clock_ns (vm_clock);
|
||||
now = qemu_get_clock (vm_clock);
|
||||
ticks = now - rate->start_ticks;
|
||||
bytes = muldiv64 (ticks, info->bytes_per_second, get_ticks_per_sec ());
|
||||
samples = (bytes - rate->bytes_sent) >> info->shift;
|
||||
|
@@ -52,7 +52,7 @@ static int wav_run_out (HWVoiceOut *hw, int live)
|
||||
int rpos, decr, samples;
|
||||
uint8_t *dst;
|
||||
struct st_sample *src;
|
||||
int64_t now = qemu_get_clock_ns (vm_clock);
|
||||
int64_t now = qemu_get_clock (vm_clock);
|
||||
int64_t ticks = now - wav->old_ticks;
|
||||
int64_t bytes =
|
||||
muldiv64 (ticks, hw->info.bytes_per_second, get_ticks_per_sec ());
|
||||
|
62
balloon.c
62
balloon.c
@@ -1,9 +1,7 @@
|
||||
/*
|
||||
* Generic Balloon handlers and management
|
||||
* QEMU System Emulator
|
||||
*
|
||||
* Copyright (c) 2003-2008 Fabrice Bellard
|
||||
* Copyright (C) 2011 Red Hat, Inc.
|
||||
* Copyright (C) 2011 Amit Shah <amit.shah@redhat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
@@ -24,6 +22,7 @@
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "sysemu.h"
|
||||
#include "monitor.h"
|
||||
#include "qjson.h"
|
||||
#include "qint.h"
|
||||
@@ -32,53 +31,44 @@
|
||||
#include "balloon.h"
|
||||
#include "trace.h"
|
||||
|
||||
static QEMUBalloonEvent *balloon_event_fn;
|
||||
static QEMUBalloonStatus *balloon_stat_fn;
|
||||
static void *balloon_opaque;
|
||||
|
||||
int qemu_add_balloon_handler(QEMUBalloonEvent *event_func,
|
||||
QEMUBalloonStatus *stat_func, void *opaque)
|
||||
static QEMUBalloonEvent *qemu_balloon_event;
|
||||
void *qemu_balloon_event_opaque;
|
||||
|
||||
void qemu_add_balloon_handler(QEMUBalloonEvent *func, void *opaque)
|
||||
{
|
||||
if (balloon_event_fn || balloon_stat_fn || balloon_opaque) {
|
||||
/* We're already registered one balloon handler. How many can
|
||||
* a guest really have?
|
||||
*/
|
||||
error_report("Another balloon device already registered");
|
||||
return -1;
|
||||
}
|
||||
balloon_event_fn = event_func;
|
||||
balloon_stat_fn = stat_func;
|
||||
balloon_opaque = opaque;
|
||||
return 0;
|
||||
qemu_balloon_event = func;
|
||||
qemu_balloon_event_opaque = opaque;
|
||||
}
|
||||
|
||||
static int qemu_balloon(ram_addr_t target)
|
||||
int qemu_balloon(ram_addr_t target, MonitorCompletion cb, void *opaque)
|
||||
{
|
||||
if (!balloon_event_fn) {
|
||||
if (qemu_balloon_event) {
|
||||
trace_balloon_event(qemu_balloon_event_opaque, target);
|
||||
qemu_balloon_event(qemu_balloon_event_opaque, target, cb, opaque);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
trace_balloon_event(balloon_opaque, target);
|
||||
balloon_event_fn(balloon_opaque, target);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int qemu_balloon_status(MonitorCompletion cb, void *opaque)
|
||||
int qemu_balloon_status(MonitorCompletion cb, void *opaque)
|
||||
{
|
||||
if (!balloon_stat_fn) {
|
||||
if (qemu_balloon_event) {
|
||||
qemu_balloon_event(qemu_balloon_event_opaque, 0, cb, opaque);
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
balloon_stat_fn(balloon_opaque, cb, opaque);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void print_balloon_stat(const char *key, QObject *obj, void *opaque)
|
||||
{
|
||||
Monitor *mon = opaque;
|
||||
|
||||
if (strcmp(key, "actual")) {
|
||||
if (strcmp(key, "actual"))
|
||||
monitor_printf(mon, ",%s=%" PRId64, key,
|
||||
qint_get_int(qobject_to_qint(obj)));
|
||||
}
|
||||
}
|
||||
|
||||
void monitor_print_balloon(Monitor *mon, const QObject *data)
|
||||
@@ -86,9 +76,9 @@ void monitor_print_balloon(Monitor *mon, const QObject *data)
|
||||
QDict *qdict;
|
||||
|
||||
qdict = qobject_to_qdict(data);
|
||||
if (!qdict_haskey(qdict, "actual")) {
|
||||
if (!qdict_haskey(qdict, "actual"))
|
||||
return;
|
||||
}
|
||||
|
||||
monitor_printf(mon, "balloon: actual=%" PRId64,
|
||||
qdict_get_int(qdict, "actual") >> 20);
|
||||
qdict_iter(qdict, print_balloon_stat, mon);
|
||||
@@ -140,7 +130,6 @@ int do_info_balloon(Monitor *mon, MonitorCompletion cb, void *opaque)
|
||||
int do_balloon(Monitor *mon, const QDict *params,
|
||||
MonitorCompletion cb, void *opaque)
|
||||
{
|
||||
int64_t target;
|
||||
int ret;
|
||||
|
||||
if (kvm_enabled() && !kvm_has_sync_mmu()) {
|
||||
@@ -148,12 +137,7 @@ int do_balloon(Monitor *mon, const QDict *params,
|
||||
return -1;
|
||||
}
|
||||
|
||||
target = qdict_get_int(params, "value");
|
||||
if (target <= 0) {
|
||||
qerror_report(QERR_INVALID_PARAMETER_VALUE, "target", "a size");
|
||||
return -1;
|
||||
}
|
||||
ret = qemu_balloon(target);
|
||||
ret = qemu_balloon(qdict_get_int(params, "value"), cb, opaque);
|
||||
if (ret == 0) {
|
||||
qerror_report(QERR_DEVICE_NOT_ACTIVE, "balloon");
|
||||
return -1;
|
||||
|
12
balloon.h
12
balloon.h
@@ -16,12 +16,14 @@
|
||||
|
||||
#include "monitor.h"
|
||||
|
||||
typedef void (QEMUBalloonEvent)(void *opaque, ram_addr_t target);
|
||||
typedef void (QEMUBalloonStatus)(void *opaque, MonitorCompletion cb,
|
||||
void *cb_data);
|
||||
typedef void (QEMUBalloonEvent)(void *opaque, ram_addr_t target,
|
||||
MonitorCompletion cb, void *cb_data);
|
||||
|
||||
int qemu_add_balloon_handler(QEMUBalloonEvent *event_func,
|
||||
QEMUBalloonStatus *stat_func, void *opaque);
|
||||
void qemu_add_balloon_handler(QEMUBalloonEvent *func, void *opaque);
|
||||
|
||||
int qemu_balloon(ram_addr_t target, MonitorCompletion cb, void *opaque);
|
||||
|
||||
int qemu_balloon_status(MonitorCompletion cb, void *opaque);
|
||||
|
||||
void monitor_print_balloon(Monitor *mon, const QObject *data);
|
||||
int do_info_balloon(Monitor *mon, MonitorCompletion cb, void *opaque);
|
||||
|
256
bitmap.c
256
bitmap.c
@@ -1,256 +0,0 @@
|
||||
/*
|
||||
* Bitmap Module
|
||||
*
|
||||
* Stolen from linux/src/lib/bitmap.c
|
||||
*
|
||||
* Copyright (C) 2010 Corentin Chary
|
||||
*
|
||||
* This source code is licensed under the GNU General Public License,
|
||||
* Version 2.
|
||||
*/
|
||||
|
||||
#include "bitops.h"
|
||||
#include "bitmap.h"
|
||||
|
||||
/*
|
||||
* bitmaps provide an array of bits, implemented using an an
|
||||
* array of unsigned longs. The number of valid bits in a
|
||||
* given bitmap does _not_ need to be an exact multiple of
|
||||
* BITS_PER_LONG.
|
||||
*
|
||||
* The possible unused bits in the last, partially used word
|
||||
* of a bitmap are 'don't care'. The implementation makes
|
||||
* no particular effort to keep them zero. It ensures that
|
||||
* their value will not affect the results of any operation.
|
||||
* The bitmap operations that return Boolean (bitmap_empty,
|
||||
* for example) or scalar (bitmap_weight, for example) results
|
||||
* carefully filter out these unused bits from impacting their
|
||||
* results.
|
||||
*
|
||||
* These operations actually hold to a slightly stronger rule:
|
||||
* if you don't input any bitmaps to these ops that have some
|
||||
* unused bits set, then they won't output any set unused bits
|
||||
* in output bitmaps.
|
||||
*
|
||||
* The byte ordering of bitmaps is more natural on little
|
||||
* endian architectures.
|
||||
*/
|
||||
|
||||
int slow_bitmap_empty(const unsigned long *bitmap, int bits)
|
||||
{
|
||||
int k, lim = bits/BITS_PER_LONG;
|
||||
|
||||
for (k = 0; k < lim; ++k) {
|
||||
if (bitmap[k]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (bits % BITS_PER_LONG) {
|
||||
if (bitmap[k] & BITMAP_LAST_WORD_MASK(bits)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int slow_bitmap_full(const unsigned long *bitmap, int bits)
|
||||
{
|
||||
int k, lim = bits/BITS_PER_LONG;
|
||||
|
||||
for (k = 0; k < lim; ++k) {
|
||||
if (~bitmap[k]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (bits % BITS_PER_LONG) {
|
||||
if (~bitmap[k] & BITMAP_LAST_WORD_MASK(bits)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int slow_bitmap_equal(const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, int bits)
|
||||
{
|
||||
int k, lim = bits/BITS_PER_LONG;
|
||||
|
||||
for (k = 0; k < lim; ++k) {
|
||||
if (bitmap1[k] != bitmap2[k]) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (bits % BITS_PER_LONG) {
|
||||
if ((bitmap1[k] ^ bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void slow_bitmap_complement(unsigned long *dst, const unsigned long *src,
|
||||
int bits)
|
||||
{
|
||||
int k, lim = bits/BITS_PER_LONG;
|
||||
|
||||
for (k = 0; k < lim; ++k) {
|
||||
dst[k] = ~src[k];
|
||||
}
|
||||
|
||||
if (bits % BITS_PER_LONG) {
|
||||
dst[k] = ~src[k] & BITMAP_LAST_WORD_MASK(bits);
|
||||
}
|
||||
}
|
||||
|
||||
int slow_bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, int bits)
|
||||
{
|
||||
int k;
|
||||
int nr = BITS_TO_LONGS(bits);
|
||||
unsigned long result = 0;
|
||||
|
||||
for (k = 0; k < nr; k++) {
|
||||
result |= (dst[k] = bitmap1[k] & bitmap2[k]);
|
||||
}
|
||||
return result != 0;
|
||||
}
|
||||
|
||||
void slow_bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, int bits)
|
||||
{
|
||||
int k;
|
||||
int nr = BITS_TO_LONGS(bits);
|
||||
|
||||
for (k = 0; k < nr; k++) {
|
||||
dst[k] = bitmap1[k] | bitmap2[k];
|
||||
}
|
||||
}
|
||||
|
||||
void slow_bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, int bits)
|
||||
{
|
||||
int k;
|
||||
int nr = BITS_TO_LONGS(bits);
|
||||
|
||||
for (k = 0; k < nr; k++) {
|
||||
dst[k] = bitmap1[k] ^ bitmap2[k];
|
||||
}
|
||||
}
|
||||
|
||||
int slow_bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, int bits)
|
||||
{
|
||||
int k;
|
||||
int nr = BITS_TO_LONGS(bits);
|
||||
unsigned long result = 0;
|
||||
|
||||
for (k = 0; k < nr; k++) {
|
||||
result |= (dst[k] = bitmap1[k] & ~bitmap2[k]);
|
||||
}
|
||||
return result != 0;
|
||||
}
|
||||
|
||||
#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG))
|
||||
|
||||
void bitmap_set(unsigned long *map, int start, int nr)
|
||||
{
|
||||
unsigned long *p = map + BIT_WORD(start);
|
||||
const int size = start + nr;
|
||||
int bits_to_set = BITS_PER_LONG - (start % BITS_PER_LONG);
|
||||
unsigned long mask_to_set = BITMAP_FIRST_WORD_MASK(start);
|
||||
|
||||
while (nr - bits_to_set >= 0) {
|
||||
*p |= mask_to_set;
|
||||
nr -= bits_to_set;
|
||||
bits_to_set = BITS_PER_LONG;
|
||||
mask_to_set = ~0UL;
|
||||
p++;
|
||||
}
|
||||
if (nr) {
|
||||
mask_to_set &= BITMAP_LAST_WORD_MASK(size);
|
||||
*p |= mask_to_set;
|
||||
}
|
||||
}
|
||||
|
||||
void bitmap_clear(unsigned long *map, int start, int nr)
|
||||
{
|
||||
unsigned long *p = map + BIT_WORD(start);
|
||||
const int size = start + nr;
|
||||
int bits_to_clear = BITS_PER_LONG - (start % BITS_PER_LONG);
|
||||
unsigned long mask_to_clear = BITMAP_FIRST_WORD_MASK(start);
|
||||
|
||||
while (nr - bits_to_clear >= 0) {
|
||||
*p &= ~mask_to_clear;
|
||||
nr -= bits_to_clear;
|
||||
bits_to_clear = BITS_PER_LONG;
|
||||
mask_to_clear = ~0UL;
|
||||
p++;
|
||||
}
|
||||
if (nr) {
|
||||
mask_to_clear &= BITMAP_LAST_WORD_MASK(size);
|
||||
*p &= ~mask_to_clear;
|
||||
}
|
||||
}
|
||||
|
||||
#define ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
|
||||
|
||||
/**
|
||||
* bitmap_find_next_zero_area - find a contiguous aligned zero area
|
||||
* @map: The address to base the search on
|
||||
* @size: The bitmap size in bits
|
||||
* @start: The bitnumber to start searching at
|
||||
* @nr: The number of zeroed bits we're looking for
|
||||
* @align_mask: Alignment mask for zero area
|
||||
*
|
||||
* The @align_mask should be one less than a power of 2; the effect is that
|
||||
* the bit offset of all zero areas this function finds is multiples of that
|
||||
* power of 2. A @align_mask of 0 means no alignment is required.
|
||||
*/
|
||||
unsigned long bitmap_find_next_zero_area(unsigned long *map,
|
||||
unsigned long size,
|
||||
unsigned long start,
|
||||
unsigned int nr,
|
||||
unsigned long align_mask)
|
||||
{
|
||||
unsigned long index, end, i;
|
||||
again:
|
||||
index = find_next_zero_bit(map, size, start);
|
||||
|
||||
/* Align allocation */
|
||||
index = ALIGN_MASK(index, align_mask);
|
||||
|
||||
end = index + nr;
|
||||
if (end > size) {
|
||||
return end;
|
||||
}
|
||||
i = find_next_bit(map, end, index);
|
||||
if (i < end) {
|
||||
start = i + 1;
|
||||
goto again;
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
int slow_bitmap_intersects(const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, int bits)
|
||||
{
|
||||
int k, lim = bits/BITS_PER_LONG;
|
||||
|
||||
for (k = 0; k < lim; ++k) {
|
||||
if (bitmap1[k] & bitmap2[k]) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (bits % BITS_PER_LONG) {
|
||||
if ((bitmap1[k] & bitmap2[k]) & BITMAP_LAST_WORD_MASK(bits)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
222
bitmap.h
222
bitmap.h
@@ -1,222 +0,0 @@
|
||||
/*
|
||||
* Bitmap Module
|
||||
*
|
||||
* Copyright (C) 2010 Corentin Chary <corentin.chary@gmail.com>
|
||||
*
|
||||
* Mostly inspired by (stolen from) linux/bitmap.h and linux/bitops.h
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef BITMAP_H
|
||||
#define BITMAP_H
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "bitops.h"
|
||||
|
||||
/*
|
||||
* The available bitmap operations and their rough meaning in the
|
||||
* case that the bitmap is a single unsigned long are thus:
|
||||
*
|
||||
* Note that nbits should be always a compile time evaluable constant.
|
||||
* Otherwise many inlines will generate horrible code.
|
||||
*
|
||||
* bitmap_zero(dst, nbits) *dst = 0UL
|
||||
* bitmap_fill(dst, nbits) *dst = ~0UL
|
||||
* bitmap_copy(dst, src, nbits) *dst = *src
|
||||
* bitmap_and(dst, src1, src2, nbits) *dst = *src1 & *src2
|
||||
* bitmap_or(dst, src1, src2, nbits) *dst = *src1 | *src2
|
||||
* bitmap_xor(dst, src1, src2, nbits) *dst = *src1 ^ *src2
|
||||
* bitmap_andnot(dst, src1, src2, nbits) *dst = *src1 & ~(*src2)
|
||||
* bitmap_complement(dst, src, nbits) *dst = ~(*src)
|
||||
* bitmap_equal(src1, src2, nbits) Are *src1 and *src2 equal?
|
||||
* bitmap_intersects(src1, src2, nbits) Do *src1 and *src2 overlap?
|
||||
* bitmap_empty(src, nbits) Are all bits zero in *src?
|
||||
* bitmap_full(src, nbits) Are all bits set in *src?
|
||||
* bitmap_set(dst, pos, nbits) Set specified bit area
|
||||
* bitmap_clear(dst, pos, nbits) Clear specified bit area
|
||||
* bitmap_find_next_zero_area(buf, len, pos, n, mask) Find bit free area
|
||||
*/
|
||||
|
||||
/*
|
||||
* Also the following operations apply to bitmaps.
|
||||
*
|
||||
* set_bit(bit, addr) *addr |= bit
|
||||
* clear_bit(bit, addr) *addr &= ~bit
|
||||
* change_bit(bit, addr) *addr ^= bit
|
||||
* test_bit(bit, addr) Is bit set in *addr?
|
||||
* test_and_set_bit(bit, addr) Set bit and return old value
|
||||
* test_and_clear_bit(bit, addr) Clear bit and return old value
|
||||
* test_and_change_bit(bit, addr) Change bit and return old value
|
||||
* find_first_zero_bit(addr, nbits) Position first zero bit in *addr
|
||||
* find_first_bit(addr, nbits) Position first set bit in *addr
|
||||
* find_next_zero_bit(addr, nbits, bit) Position next zero bit in *addr >= bit
|
||||
* find_next_bit(addr, nbits, bit) Position next set bit in *addr >= bit
|
||||
*/
|
||||
|
||||
#define BITMAP_LAST_WORD_MASK(nbits) \
|
||||
( \
|
||||
((nbits) % BITS_PER_LONG) ? \
|
||||
(1UL<<((nbits) % BITS_PER_LONG))-1 : ~0UL \
|
||||
)
|
||||
|
||||
#define DECLARE_BITMAP(name,bits) \
|
||||
unsigned long name[BITS_TO_LONGS(bits)]
|
||||
|
||||
#define small_nbits(nbits) \
|
||||
((nbits) <= BITS_PER_LONG)
|
||||
|
||||
int slow_bitmap_empty(const unsigned long *bitmap, int bits);
|
||||
int slow_bitmap_full(const unsigned long *bitmap, int bits);
|
||||
int slow_bitmap_equal(const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, int bits);
|
||||
void slow_bitmap_complement(unsigned long *dst, const unsigned long *src,
|
||||
int bits);
|
||||
void slow_bitmap_shift_right(unsigned long *dst,
|
||||
const unsigned long *src, int shift, int bits);
|
||||
void slow_bitmap_shift_left(unsigned long *dst,
|
||||
const unsigned long *src, int shift, int bits);
|
||||
int slow_bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, int bits);
|
||||
void slow_bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, int bits);
|
||||
void slow_bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, int bits);
|
||||
int slow_bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, int bits);
|
||||
int slow_bitmap_intersects(const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, int bits);
|
||||
|
||||
static inline unsigned long *bitmap_new(int nbits)
|
||||
{
|
||||
int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
|
||||
return qemu_mallocz(len);
|
||||
}
|
||||
|
||||
static inline void bitmap_zero(unsigned long *dst, int nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
*dst = 0UL;
|
||||
} else {
|
||||
int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
|
||||
memset(dst, 0, len);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void bitmap_fill(unsigned long *dst, int nbits)
|
||||
{
|
||||
size_t nlongs = BITS_TO_LONGS(nbits);
|
||||
if (!small_nbits(nbits)) {
|
||||
int len = (nlongs - 1) * sizeof(unsigned long);
|
||||
memset(dst, 0xff, len);
|
||||
}
|
||||
dst[nlongs - 1] = BITMAP_LAST_WORD_MASK(nbits);
|
||||
}
|
||||
|
||||
static inline void bitmap_copy(unsigned long *dst, const unsigned long *src,
|
||||
int nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
*dst = *src;
|
||||
} else {
|
||||
int len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
|
||||
memcpy(dst, src, len);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int bitmap_and(unsigned long *dst, const unsigned long *src1,
|
||||
const unsigned long *src2, int nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
return (*dst = *src1 & *src2) != 0;
|
||||
}
|
||||
return slow_bitmap_and(dst, src1, src2, nbits);
|
||||
}
|
||||
|
||||
static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
|
||||
const unsigned long *src2, int nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
*dst = *src1 | *src2;
|
||||
} else {
|
||||
slow_bitmap_or(dst, src1, src2, nbits);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void bitmap_xor(unsigned long *dst, const unsigned long *src1,
|
||||
const unsigned long *src2, int nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
*dst = *src1 ^ *src2;
|
||||
} else {
|
||||
slow_bitmap_xor(dst, src1, src2, nbits);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int bitmap_andnot(unsigned long *dst, const unsigned long *src1,
|
||||
const unsigned long *src2, int nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
return (*dst = *src1 & ~(*src2)) != 0;
|
||||
}
|
||||
return slow_bitmap_andnot(dst, src1, src2, nbits);
|
||||
}
|
||||
|
||||
static inline void bitmap_complement(unsigned long *dst, const unsigned long *src,
|
||||
int nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
*dst = ~(*src) & BITMAP_LAST_WORD_MASK(nbits);
|
||||
} else {
|
||||
slow_bitmap_complement(dst, src, nbits);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int bitmap_equal(const unsigned long *src1,
|
||||
const unsigned long *src2, int nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
return ! ((*src1 ^ *src2) & BITMAP_LAST_WORD_MASK(nbits));
|
||||
} else {
|
||||
return slow_bitmap_equal(src1, src2, nbits);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int bitmap_empty(const unsigned long *src, int nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
return ! (*src & BITMAP_LAST_WORD_MASK(nbits));
|
||||
} else {
|
||||
return slow_bitmap_empty(src, nbits);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int bitmap_full(const unsigned long *src, int nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
return ! (~(*src) & BITMAP_LAST_WORD_MASK(nbits));
|
||||
} else {
|
||||
return slow_bitmap_full(src, nbits);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int bitmap_intersects(const unsigned long *src1,
|
||||
const unsigned long *src2, int nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
return ((*src1 & *src2) & BITMAP_LAST_WORD_MASK(nbits)) != 0;
|
||||
} else {
|
||||
return slow_bitmap_intersects(src1, src2, nbits);
|
||||
}
|
||||
}
|
||||
|
||||
void bitmap_set(unsigned long *map, int i, int len);
|
||||
void bitmap_clear(unsigned long *map, int start, int nr);
|
||||
unsigned long bitmap_find_next_zero_area(unsigned long *map,
|
||||
unsigned long size,
|
||||
unsigned long start,
|
||||
unsigned int nr,
|
||||
unsigned long align_mask);
|
||||
|
||||
#endif /* BITMAP_H */
|
142
bitops.c
142
bitops.c
@@ -1,142 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
|
||||
* Written by David Howells (dhowells@redhat.com)
|
||||
* Copyright (C) 2008 IBM Corporation
|
||||
* Written by Rusty Russell <rusty@rustcorp.com.au>
|
||||
* (Inspired by David Howell's find_next_bit implementation)
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version
|
||||
* 2 of the License, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include "bitops.h"
|
||||
|
||||
#define BITOP_WORD(nr) ((nr) / BITS_PER_LONG)
|
||||
|
||||
/*
|
||||
* Find the next set bit in a memory region.
|
||||
*/
|
||||
unsigned long find_next_bit(const unsigned long *addr, unsigned long size,
|
||||
unsigned long offset)
|
||||
{
|
||||
const unsigned long *p = addr + BITOP_WORD(offset);
|
||||
unsigned long result = offset & ~(BITS_PER_LONG-1);
|
||||
unsigned long tmp;
|
||||
|
||||
if (offset >= size) {
|
||||
return size;
|
||||
}
|
||||
size -= result;
|
||||
offset %= BITS_PER_LONG;
|
||||
if (offset) {
|
||||
tmp = *(p++);
|
||||
tmp &= (~0UL << offset);
|
||||
if (size < BITS_PER_LONG) {
|
||||
goto found_first;
|
||||
}
|
||||
if (tmp) {
|
||||
goto found_middle;
|
||||
}
|
||||
size -= BITS_PER_LONG;
|
||||
result += BITS_PER_LONG;
|
||||
}
|
||||
while (size & ~(BITS_PER_LONG-1)) {
|
||||
if ((tmp = *(p++))) {
|
||||
goto found_middle;
|
||||
}
|
||||
result += BITS_PER_LONG;
|
||||
size -= BITS_PER_LONG;
|
||||
}
|
||||
if (!size) {
|
||||
return result;
|
||||
}
|
||||
tmp = *p;
|
||||
|
||||
found_first:
|
||||
tmp &= (~0UL >> (BITS_PER_LONG - size));
|
||||
if (tmp == 0UL) { /* Are any bits set? */
|
||||
return result + size; /* Nope. */
|
||||
}
|
||||
found_middle:
|
||||
return result + bitops_ffsl(tmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* This implementation of find_{first,next}_zero_bit was stolen from
|
||||
* Linus' asm-alpha/bitops.h.
|
||||
*/
|
||||
unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size,
|
||||
unsigned long offset)
|
||||
{
|
||||
const unsigned long *p = addr + BITOP_WORD(offset);
|
||||
unsigned long result = offset & ~(BITS_PER_LONG-1);
|
||||
unsigned long tmp;
|
||||
|
||||
if (offset >= size) {
|
||||
return size;
|
||||
}
|
||||
size -= result;
|
||||
offset %= BITS_PER_LONG;
|
||||
if (offset) {
|
||||
tmp = *(p++);
|
||||
tmp |= ~0UL >> (BITS_PER_LONG - offset);
|
||||
if (size < BITS_PER_LONG) {
|
||||
goto found_first;
|
||||
}
|
||||
if (~tmp) {
|
||||
goto found_middle;
|
||||
}
|
||||
size -= BITS_PER_LONG;
|
||||
result += BITS_PER_LONG;
|
||||
}
|
||||
while (size & ~(BITS_PER_LONG-1)) {
|
||||
if (~(tmp = *(p++))) {
|
||||
goto found_middle;
|
||||
}
|
||||
result += BITS_PER_LONG;
|
||||
size -= BITS_PER_LONG;
|
||||
}
|
||||
if (!size) {
|
||||
return result;
|
||||
}
|
||||
tmp = *p;
|
||||
|
||||
found_first:
|
||||
tmp |= ~0UL << size;
|
||||
if (tmp == ~0UL) { /* Are any bits zero? */
|
||||
return result + size; /* Nope. */
|
||||
}
|
||||
found_middle:
|
||||
return result + ffz(tmp);
|
||||
}
|
||||
|
||||
unsigned long find_last_bit(const unsigned long *addr, unsigned long size)
|
||||
{
|
||||
unsigned long words;
|
||||
unsigned long tmp;
|
||||
|
||||
/* Start at final word. */
|
||||
words = size / BITS_PER_LONG;
|
||||
|
||||
/* Partial final word? */
|
||||
if (size & (BITS_PER_LONG-1)) {
|
||||
tmp = (addr[words] & (~0UL >> (BITS_PER_LONG
|
||||
- (size & (BITS_PER_LONG-1)))));
|
||||
if (tmp) {
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
|
||||
while (words) {
|
||||
tmp = addr[--words];
|
||||
if (tmp) {
|
||||
found:
|
||||
return words * BITS_PER_LONG + bitops_flsl(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Not found */
|
||||
return size;
|
||||
}
|
272
bitops.h
272
bitops.h
@@ -1,272 +0,0 @@
|
||||
/*
|
||||
* Bitops Module
|
||||
*
|
||||
* Copyright (C) 2010 Corentin Chary <corentin.chary@gmail.com>
|
||||
*
|
||||
* Mostly inspired by (stolen from) linux/bitmap.h and linux/bitops.h
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef BITOPS_H
|
||||
#define BITOPS_H
|
||||
|
||||
#include "qemu-common.h"
|
||||
|
||||
#define BITS_PER_BYTE CHAR_BIT
|
||||
#define BITS_PER_LONG (sizeof (unsigned long) * BITS_PER_BYTE)
|
||||
|
||||
#define BIT(nr) (1UL << (nr))
|
||||
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
|
||||
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
|
||||
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
|
||||
|
||||
/**
|
||||
* bitops_ffs - find first bit in word.
|
||||
* @word: The word to search
|
||||
*
|
||||
* Undefined if no bit exists, so code should check against 0 first.
|
||||
*/
|
||||
static unsigned long bitops_ffsl(unsigned long word)
|
||||
{
|
||||
int num = 0;
|
||||
|
||||
#if LONG_MAX > 0x7FFFFFFF
|
||||
if ((word & 0xffffffff) == 0) {
|
||||
num += 32;
|
||||
word >>= 32;
|
||||
}
|
||||
#endif
|
||||
if ((word & 0xffff) == 0) {
|
||||
num += 16;
|
||||
word >>= 16;
|
||||
}
|
||||
if ((word & 0xff) == 0) {
|
||||
num += 8;
|
||||
word >>= 8;
|
||||
}
|
||||
if ((word & 0xf) == 0) {
|
||||
num += 4;
|
||||
word >>= 4;
|
||||
}
|
||||
if ((word & 0x3) == 0) {
|
||||
num += 2;
|
||||
word >>= 2;
|
||||
}
|
||||
if ((word & 0x1) == 0) {
|
||||
num += 1;
|
||||
}
|
||||
return num;
|
||||
}
|
||||
|
||||
/**
|
||||
* bitops_fls - find last (most-significant) set bit in a long word
|
||||
* @word: the word to search
|
||||
*
|
||||
* Undefined if no set bit exists, so code should check against 0 first.
|
||||
*/
|
||||
static inline unsigned long bitops_flsl(unsigned long word)
|
||||
{
|
||||
int num = BITS_PER_LONG - 1;
|
||||
|
||||
#if LONG_MAX > 0x7FFFFFFF
|
||||
if (!(word & (~0ul << 32))) {
|
||||
num -= 32;
|
||||
word <<= 32;
|
||||
}
|
||||
#endif
|
||||
if (!(word & (~0ul << (BITS_PER_LONG-16)))) {
|
||||
num -= 16;
|
||||
word <<= 16;
|
||||
}
|
||||
if (!(word & (~0ul << (BITS_PER_LONG-8)))) {
|
||||
num -= 8;
|
||||
word <<= 8;
|
||||
}
|
||||
if (!(word & (~0ul << (BITS_PER_LONG-4)))) {
|
||||
num -= 4;
|
||||
word <<= 4;
|
||||
}
|
||||
if (!(word & (~0ul << (BITS_PER_LONG-2)))) {
|
||||
num -= 2;
|
||||
|
||||
word <<= 2;
|
||||
}
|
||||
if (!(word & (~0ul << (BITS_PER_LONG-1))))
|
||||
num -= 1;
|
||||
return num;
|
||||
}
|
||||
|
||||
/**
|
||||
* ffz - find first zero in word.
|
||||
* @word: The word to search
|
||||
*
|
||||
* Undefined if no zero exists, so code should check against ~0UL first.
|
||||
*/
|
||||
static inline unsigned long ffz(unsigned long word)
|
||||
{
|
||||
return bitops_ffsl(~word);
|
||||
}
|
||||
|
||||
/**
|
||||
* set_bit - Set a bit in memory
|
||||
* @nr: the bit to set
|
||||
* @addr: the address to start counting from
|
||||
*/
|
||||
static inline void set_bit(int nr, volatile unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
|
||||
|
||||
*p |= mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* clear_bit - Clears a bit in memory
|
||||
* @nr: Bit to clear
|
||||
* @addr: Address to start counting from
|
||||
*/
|
||||
static inline void clear_bit(int nr, volatile unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
|
||||
|
||||
*p &= ~mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* change_bit - Toggle a bit in memory
|
||||
* @nr: Bit to change
|
||||
* @addr: Address to start counting from
|
||||
*/
|
||||
static inline void change_bit(int nr, volatile unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
|
||||
|
||||
*p ^= mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_set_bit - Set a bit and return its old value
|
||||
* @nr: Bit to set
|
||||
* @addr: Address to count from
|
||||
*/
|
||||
static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
|
||||
unsigned long old = *p;
|
||||
|
||||
*p = old | mask;
|
||||
return (old & mask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_clear_bit - Clear a bit and return its old value
|
||||
* @nr: Bit to clear
|
||||
* @addr: Address to count from
|
||||
*/
|
||||
static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
|
||||
unsigned long old = *p;
|
||||
|
||||
*p = old & ~mask;
|
||||
return (old & mask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_change_bit - Change a bit and return its old value
|
||||
* @nr: Bit to change
|
||||
* @addr: Address to count from
|
||||
*/
|
||||
static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
|
||||
unsigned long old = *p;
|
||||
|
||||
*p = old ^ mask;
|
||||
return (old & mask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* test_bit - Determine whether a bit is set
|
||||
* @nr: bit number to test
|
||||
* @addr: Address to start counting from
|
||||
*/
|
||||
static inline int test_bit(int nr, const volatile unsigned long *addr)
|
||||
{
|
||||
return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
|
||||
}
|
||||
|
||||
/**
|
||||
* find_last_bit - find the last set bit in a memory region
|
||||
* @addr: The address to start the search at
|
||||
* @size: The maximum size to search
|
||||
*
|
||||
* Returns the bit number of the first set bit, or size.
|
||||
*/
|
||||
unsigned long find_last_bit(const unsigned long *addr,
|
||||
unsigned long size);
|
||||
|
||||
/**
|
||||
* find_next_bit - find the next set bit in a memory region
|
||||
* @addr: The address to base the search on
|
||||
* @offset: The bitnumber to start searching at
|
||||
* @size: The bitmap size in bits
|
||||
*/
|
||||
unsigned long find_next_bit(const unsigned long *addr,
|
||||
unsigned long size, unsigned long offset);
|
||||
|
||||
/**
|
||||
* find_next_zero_bit - find the next cleared bit in a memory region
|
||||
* @addr: The address to base the search on
|
||||
* @offset: The bitnumber to start searching at
|
||||
* @size: The bitmap size in bits
|
||||
*/
|
||||
|
||||
unsigned long find_next_zero_bit(const unsigned long *addr,
|
||||
unsigned long size,
|
||||
unsigned long offset);
|
||||
|
||||
/**
|
||||
* find_first_bit - find the first set bit in a memory region
|
||||
* @addr: The address to start the search at
|
||||
* @size: The maximum size to search
|
||||
*
|
||||
* Returns the bit number of the first set bit.
|
||||
*/
|
||||
static inline unsigned long find_first_bit(const unsigned long *addr,
|
||||
unsigned long size)
|
||||
{
|
||||
return find_next_bit(addr, size, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* find_first_zero_bit - find the first cleared bit in a memory region
|
||||
* @addr: The address to start the search at
|
||||
* @size: The maximum size to search
|
||||
*
|
||||
* Returns the bit number of the first cleared bit.
|
||||
*/
|
||||
static inline unsigned long find_first_zero_bit(const unsigned long *addr,
|
||||
unsigned long size)
|
||||
{
|
||||
return find_next_zero_bit(addr, size, 0);
|
||||
}
|
||||
|
||||
static inline unsigned long hweight_long(unsigned long w)
|
||||
{
|
||||
unsigned long count;
|
||||
|
||||
for (count = 0; w; w >>= 1) {
|
||||
count += w & 1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
#endif
|
@@ -62,6 +62,7 @@ typedef struct BlkMigBlock {
|
||||
QEMUIOVector qiov;
|
||||
BlockDriverAIOCB *aiocb;
|
||||
int ret;
|
||||
int64_t time;
|
||||
QSIMPLEQ_ENTRY(BlkMigBlock) entry;
|
||||
} BlkMigBlock;
|
||||
|
||||
@@ -77,7 +78,6 @@ typedef struct BlkMigState {
|
||||
int prev_progress;
|
||||
int bulk_completed;
|
||||
long double total_time;
|
||||
long double prev_time_offset;
|
||||
int reads;
|
||||
} BlkMigState;
|
||||
|
||||
@@ -131,10 +131,16 @@ uint64_t blk_mig_bytes_total(void)
|
||||
return sum << BDRV_SECTOR_BITS;
|
||||
}
|
||||
|
||||
static inline void add_avg_read_time(int64_t time)
|
||||
{
|
||||
block_mig_state.reads++;
|
||||
block_mig_state.total_time += time;
|
||||
}
|
||||
|
||||
static inline long double compute_read_bwidth(void)
|
||||
{
|
||||
assert(block_mig_state.total_time != 0);
|
||||
return (block_mig_state.reads / block_mig_state.total_time) * BLOCK_SIZE;
|
||||
return (block_mig_state.reads * BLOCK_SIZE)/ block_mig_state.total_time;
|
||||
}
|
||||
|
||||
static int bmds_aio_inflight(BlkMigDevState *bmds, int64_t sector)
|
||||
@@ -185,14 +191,13 @@ static void alloc_aio_bitmap(BlkMigDevState *bmds)
|
||||
|
||||
static void blk_mig_read_cb(void *opaque, int ret)
|
||||
{
|
||||
long double curr_time = qemu_get_clock_ns(rt_clock);
|
||||
BlkMigBlock *blk = opaque;
|
||||
|
||||
blk->ret = ret;
|
||||
|
||||
block_mig_state.reads++;
|
||||
block_mig_state.total_time += (curr_time - block_mig_state.prev_time_offset);
|
||||
block_mig_state.prev_time_offset = curr_time;
|
||||
blk->time = qemu_get_clock_ns(rt_clock) - blk->time;
|
||||
|
||||
add_avg_read_time(blk->time);
|
||||
|
||||
QSIMPLEQ_INSERT_TAIL(&block_mig_state.blk_list, blk, entry);
|
||||
bmds_set_aio_inflight(blk->bmds, blk->sector, blk->nr_sectors, 0);
|
||||
@@ -245,9 +250,7 @@ static int mig_save_device_bulk(Monitor *mon, QEMUFile *f,
|
||||
blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
|
||||
qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
|
||||
|
||||
if (block_mig_state.submitted == 0) {
|
||||
block_mig_state.prev_time_offset = qemu_get_clock_ns(rt_clock);
|
||||
}
|
||||
blk->time = qemu_get_clock_ns(rt_clock);
|
||||
|
||||
blk->aiocb = bdrv_aio_readv(bs, cur_sector, &blk->qiov,
|
||||
nr_sectors, blk_mig_read_cb, blk);
|
||||
@@ -406,9 +409,7 @@ static int mig_save_device_dirty(Monitor *mon, QEMUFile *f,
|
||||
blk->iov.iov_len = nr_sectors * BDRV_SECTOR_SIZE;
|
||||
qemu_iovec_init_external(&blk->qiov, &blk->iov, 1);
|
||||
|
||||
if (block_mig_state.submitted == 0) {
|
||||
block_mig_state.prev_time_offset = qemu_get_clock_ns(rt_clock);
|
||||
}
|
||||
blk->time = qemu_get_clock_ns(rt_clock);
|
||||
|
||||
blk->aiocb = bdrv_aio_readv(bmds->bs, sector, &blk->qiov,
|
||||
nr_sectors, blk_mig_read_cb, blk);
|
||||
@@ -671,7 +672,7 @@ static int block_load(QEMUFile *f, void *opaque, int version_id)
|
||||
bs_prev = bs;
|
||||
total_sectors = bdrv_getlength(bs) >> BDRV_SECTOR_BITS;
|
||||
if (total_sectors <= 0) {
|
||||
error_report("Error getting length of block device %s",
|
||||
error_report("Error getting length of block device %s\n",
|
||||
device_name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
181
block.c
181
block.c
@@ -439,7 +439,13 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename,
|
||||
bs->drv = drv;
|
||||
bs->opaque = qemu_mallocz(drv->instance_size);
|
||||
|
||||
if (flags & BDRV_O_CACHE_WB)
|
||||
/*
|
||||
* Yes, BDRV_O_NOCACHE aka O_DIRECT means we have to present a
|
||||
* write cache to the guest. We do need the fdatasync to flush
|
||||
* out transactions for block allocations, and we maybe have a
|
||||
* volatile write cache in our backing device to deal with.
|
||||
*/
|
||||
if (flags & (BDRV_O_CACHE_WB|BDRV_O_NOCACHE))
|
||||
bs->enable_write_cache = 1;
|
||||
|
||||
/*
|
||||
@@ -449,7 +455,7 @@ static int bdrv_open_common(BlockDriverState *bs, const char *filename,
|
||||
open_flags = flags & ~(BDRV_O_SNAPSHOT | BDRV_O_NO_BACKING);
|
||||
|
||||
/*
|
||||
* Snapshots should be writable.
|
||||
* Snapshots should be writeable.
|
||||
*/
|
||||
if (bs->is_temporary) {
|
||||
open_flags |= BDRV_O_RDWR;
|
||||
@@ -741,7 +747,7 @@ DeviceState *bdrv_get_attached(BlockDriverState *bs)
|
||||
* Run consistency checks on an image
|
||||
*
|
||||
* Returns 0 if the check could be completed (it doesn't mean that the image is
|
||||
* free of errors) or -errno when an internal error occurred. The results of the
|
||||
* free of errors) or -errno when an internal error occured. The results of the
|
||||
* check are stored in res.
|
||||
*/
|
||||
int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res)
|
||||
@@ -1146,25 +1152,6 @@ int bdrv_truncate(BlockDriverState *bs, int64_t offset)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Length of a allocated file in bytes. Sparse files are counted by actual
|
||||
* allocated space. Return < 0 if error or unknown.
|
||||
*/
|
||||
int64_t bdrv_get_allocated_file_size(BlockDriverState *bs)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
if (!drv) {
|
||||
return -ENOMEDIUM;
|
||||
}
|
||||
if (drv->bdrv_get_allocated_file_size) {
|
||||
return drv->bdrv_get_allocated_file_size(bs);
|
||||
}
|
||||
if (bs->file) {
|
||||
return bdrv_get_allocated_file_size(bs->file);
|
||||
}
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Length of a file in bytes. Return < 0 if error or unknown.
|
||||
*/
|
||||
@@ -1174,12 +1161,14 @@ int64_t bdrv_getlength(BlockDriverState *bs)
|
||||
if (!drv)
|
||||
return -ENOMEDIUM;
|
||||
|
||||
if (bs->growable || bs->removable) {
|
||||
if (drv->bdrv_getlength) {
|
||||
return drv->bdrv_getlength(bs);
|
||||
}
|
||||
/* Fixed size devices use the total_sectors value for speed instead of
|
||||
issuing a length query (like lseek) on each call. Also, legacy block
|
||||
drivers don't provide a bdrv_getlength function and must use
|
||||
total_sectors. */
|
||||
if (!bs->growable || !drv->bdrv_getlength) {
|
||||
return bs->total_sectors * BDRV_SECTOR_SIZE;
|
||||
}
|
||||
return bs->total_sectors * BDRV_SECTOR_SIZE;
|
||||
return drv->bdrv_getlength(bs);
|
||||
}
|
||||
|
||||
/* return 0 as number of sectors if no device present or error */
|
||||
@@ -1318,6 +1307,13 @@ void bdrv_set_geometry_hint(BlockDriverState *bs,
|
||||
bs->secs = secs;
|
||||
}
|
||||
|
||||
void bdrv_set_type_hint(BlockDriverState *bs, int type)
|
||||
{
|
||||
bs->type = type;
|
||||
bs->removable = ((type == BDRV_TYPE_CDROM ||
|
||||
type == BDRV_TYPE_FLOPPY));
|
||||
}
|
||||
|
||||
void bdrv_set_translation_hint(BlockDriverState *bs, int translation)
|
||||
{
|
||||
bs->translation = translation;
|
||||
@@ -1331,107 +1327,9 @@ void bdrv_get_geometry_hint(BlockDriverState *bs,
|
||||
*psecs = bs->secs;
|
||||
}
|
||||
|
||||
/* Recognize floppy formats */
|
||||
typedef struct FDFormat {
|
||||
FDriveType drive;
|
||||
uint8_t last_sect;
|
||||
uint8_t max_track;
|
||||
uint8_t max_head;
|
||||
} FDFormat;
|
||||
|
||||
static const FDFormat fd_formats[] = {
|
||||
/* First entry is default format */
|
||||
/* 1.44 MB 3"1/2 floppy disks */
|
||||
{ FDRIVE_DRV_144, 18, 80, 1, },
|
||||
{ FDRIVE_DRV_144, 20, 80, 1, },
|
||||
{ FDRIVE_DRV_144, 21, 80, 1, },
|
||||
{ FDRIVE_DRV_144, 21, 82, 1, },
|
||||
{ FDRIVE_DRV_144, 21, 83, 1, },
|
||||
{ FDRIVE_DRV_144, 22, 80, 1, },
|
||||
{ FDRIVE_DRV_144, 23, 80, 1, },
|
||||
{ FDRIVE_DRV_144, 24, 80, 1, },
|
||||
/* 2.88 MB 3"1/2 floppy disks */
|
||||
{ FDRIVE_DRV_288, 36, 80, 1, },
|
||||
{ FDRIVE_DRV_288, 39, 80, 1, },
|
||||
{ FDRIVE_DRV_288, 40, 80, 1, },
|
||||
{ FDRIVE_DRV_288, 44, 80, 1, },
|
||||
{ FDRIVE_DRV_288, 48, 80, 1, },
|
||||
/* 720 kB 3"1/2 floppy disks */
|
||||
{ FDRIVE_DRV_144, 9, 80, 1, },
|
||||
{ FDRIVE_DRV_144, 10, 80, 1, },
|
||||
{ FDRIVE_DRV_144, 10, 82, 1, },
|
||||
{ FDRIVE_DRV_144, 10, 83, 1, },
|
||||
{ FDRIVE_DRV_144, 13, 80, 1, },
|
||||
{ FDRIVE_DRV_144, 14, 80, 1, },
|
||||
/* 1.2 MB 5"1/4 floppy disks */
|
||||
{ FDRIVE_DRV_120, 15, 80, 1, },
|
||||
{ FDRIVE_DRV_120, 18, 80, 1, },
|
||||
{ FDRIVE_DRV_120, 18, 82, 1, },
|
||||
{ FDRIVE_DRV_120, 18, 83, 1, },
|
||||
{ FDRIVE_DRV_120, 20, 80, 1, },
|
||||
/* 720 kB 5"1/4 floppy disks */
|
||||
{ FDRIVE_DRV_120, 9, 80, 1, },
|
||||
{ FDRIVE_DRV_120, 11, 80, 1, },
|
||||
/* 360 kB 5"1/4 floppy disks */
|
||||
{ FDRIVE_DRV_120, 9, 40, 1, },
|
||||
{ FDRIVE_DRV_120, 9, 40, 0, },
|
||||
{ FDRIVE_DRV_120, 10, 41, 1, },
|
||||
{ FDRIVE_DRV_120, 10, 42, 1, },
|
||||
/* 320 kB 5"1/4 floppy disks */
|
||||
{ FDRIVE_DRV_120, 8, 40, 1, },
|
||||
{ FDRIVE_DRV_120, 8, 40, 0, },
|
||||
/* 360 kB must match 5"1/4 better than 3"1/2... */
|
||||
{ FDRIVE_DRV_144, 9, 80, 0, },
|
||||
/* end */
|
||||
{ FDRIVE_DRV_NONE, -1, -1, 0, },
|
||||
};
|
||||
|
||||
void bdrv_get_floppy_geometry_hint(BlockDriverState *bs, int *nb_heads,
|
||||
int *max_track, int *last_sect,
|
||||
FDriveType drive_in, FDriveType *drive)
|
||||
int bdrv_get_type_hint(BlockDriverState *bs)
|
||||
{
|
||||
const FDFormat *parse;
|
||||
uint64_t nb_sectors, size;
|
||||
int i, first_match, match;
|
||||
|
||||
bdrv_get_geometry_hint(bs, nb_heads, max_track, last_sect);
|
||||
if (*nb_heads != 0 && *max_track != 0 && *last_sect != 0) {
|
||||
/* User defined disk */
|
||||
} else {
|
||||
bdrv_get_geometry(bs, &nb_sectors);
|
||||
match = -1;
|
||||
first_match = -1;
|
||||
for (i = 0; ; i++) {
|
||||
parse = &fd_formats[i];
|
||||
if (parse->drive == FDRIVE_DRV_NONE) {
|
||||
break;
|
||||
}
|
||||
if (drive_in == parse->drive ||
|
||||
drive_in == FDRIVE_DRV_NONE) {
|
||||
size = (parse->max_head + 1) * parse->max_track *
|
||||
parse->last_sect;
|
||||
if (nb_sectors == size) {
|
||||
match = i;
|
||||
break;
|
||||
}
|
||||
if (first_match == -1) {
|
||||
first_match = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (match == -1) {
|
||||
if (first_match == -1) {
|
||||
match = 1;
|
||||
} else {
|
||||
match = first_match;
|
||||
}
|
||||
parse = &fd_formats[match];
|
||||
}
|
||||
*nb_heads = parse->max_head + 1;
|
||||
*max_track = parse->max_track;
|
||||
*last_sect = parse->last_sect;
|
||||
*drive = parse->drive;
|
||||
}
|
||||
return bs->type;
|
||||
}
|
||||
|
||||
int bdrv_get_translation_hint(BlockDriverState *bs)
|
||||
@@ -1705,8 +1603,9 @@ static void bdrv_print_dict(QObject *obj, void *opaque)
|
||||
|
||||
bs_dict = qobject_to_qdict(obj);
|
||||
|
||||
monitor_printf(mon, "%s: removable=%d",
|
||||
monitor_printf(mon, "%s: type=%s removable=%d",
|
||||
qdict_get_str(bs_dict, "device"),
|
||||
qdict_get_str(bs_dict, "type"),
|
||||
qdict_get_bool(bs_dict, "removable"));
|
||||
|
||||
if (qdict_get_bool(bs_dict, "removable")) {
|
||||
@@ -1747,10 +1646,23 @@ void bdrv_info(Monitor *mon, QObject **ret_data)
|
||||
|
||||
QTAILQ_FOREACH(bs, &bdrv_states, list) {
|
||||
QObject *bs_obj;
|
||||
const char *type = "unknown";
|
||||
|
||||
bs_obj = qobject_from_jsonf("{ 'device': %s, 'type': 'unknown', "
|
||||
switch(bs->type) {
|
||||
case BDRV_TYPE_HD:
|
||||
type = "hd";
|
||||
break;
|
||||
case BDRV_TYPE_CDROM:
|
||||
type = "cdrom";
|
||||
break;
|
||||
case BDRV_TYPE_FLOPPY:
|
||||
type = "floppy";
|
||||
break;
|
||||
}
|
||||
|
||||
bs_obj = qobject_from_jsonf("{ 'device': %s, 'type': %s, "
|
||||
"'removable': %i, 'locked': %i }",
|
||||
bs->device_name, bs->removable,
|
||||
bs->device_name, type, bs->removable,
|
||||
bs->locked);
|
||||
|
||||
if (bs->drv) {
|
||||
@@ -2478,8 +2390,6 @@ BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs,
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
|
||||
trace_bdrv_aio_flush(bs, opaque);
|
||||
|
||||
if (bs->open_flags & BDRV_O_NO_FLUSH) {
|
||||
return bdrv_aio_noop_em(bs, cb, opaque);
|
||||
}
|
||||
@@ -2802,8 +2712,6 @@ void bdrv_set_locked(BlockDriverState *bs, int locked)
|
||||
{
|
||||
BlockDriver *drv = bs->drv;
|
||||
|
||||
trace_bdrv_set_locked(bs, locked);
|
||||
|
||||
bs->locked = locked;
|
||||
if (drv && drv->bdrv_set_locked) {
|
||||
drv->bdrv_set_locked(bs, locked);
|
||||
@@ -2900,7 +2808,7 @@ int bdrv_img_create(const char *filename, const char *fmt,
|
||||
char *options, uint64_t img_size, int flags)
|
||||
{
|
||||
QEMUOptionParameter *param = NULL, *create_options = NULL;
|
||||
QEMUOptionParameter *backing_fmt, *backing_file, *size;
|
||||
QEMUOptionParameter *backing_fmt, *backing_file;
|
||||
BlockDriverState *bs = NULL;
|
||||
BlockDriver *drv, *proto_drv;
|
||||
BlockDriver *backing_drv = NULL;
|
||||
@@ -2983,8 +2891,7 @@ int bdrv_img_create(const char *filename, const char *fmt,
|
||||
|
||||
// The size for the image must always be specified, with one exception:
|
||||
// If we are using a backing file, we can obtain the size from there
|
||||
size = get_option_parameter(param, BLOCK_OPT_SIZE);
|
||||
if (size && size->value.n == -1) {
|
||||
if (get_option_parameter(param, BLOCK_OPT_SIZE)->value.n == -1) {
|
||||
if (backing_file && backing_file->value.s) {
|
||||
uint64_t size;
|
||||
char buf[32];
|
||||
|
22
block.h
22
block.h
@@ -89,7 +89,6 @@ int bdrv_write_sync(BlockDriverState *bs, int64_t sector_num,
|
||||
const uint8_t *buf, int nb_sectors);
|
||||
int bdrv_truncate(BlockDriverState *bs, int64_t offset);
|
||||
int64_t bdrv_getlength(BlockDriverState *bs);
|
||||
int64_t bdrv_get_allocated_file_size(BlockDriverState *bs);
|
||||
void bdrv_get_geometry(BlockDriverState *bs, uint64_t *nb_sectors_ptr);
|
||||
void bdrv_guess_geometry(BlockDriverState *bs, int *pcyls, int *pheads, int *psecs);
|
||||
int bdrv_commit(BlockDriverState *bs);
|
||||
@@ -111,7 +110,7 @@ int bdrv_check(BlockDriverState *bs, BdrvCheckResult *res);
|
||||
typedef struct BlockDriverAIOCB BlockDriverAIOCB;
|
||||
typedef void BlockDriverCompletionFunc(void *opaque, int ret);
|
||||
typedef void BlockDriverDirtyHandler(BlockDriverState *bs, int64_t sector,
|
||||
int sector_num);
|
||||
int sector_num);
|
||||
BlockDriverAIOCB *bdrv_aio_readv(BlockDriverState *bs, int64_t sector_num,
|
||||
QEMUIOVector *iov, int nb_sectors,
|
||||
BlockDriverCompletionFunc *cb, void *opaque);
|
||||
@@ -119,7 +118,7 @@ BlockDriverAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
|
||||
QEMUIOVector *iov, int nb_sectors,
|
||||
BlockDriverCompletionFunc *cb, void *opaque);
|
||||
BlockDriverAIOCB *bdrv_aio_flush(BlockDriverState *bs,
|
||||
BlockDriverCompletionFunc *cb, void *opaque);
|
||||
BlockDriverCompletionFunc *cb, void *opaque);
|
||||
void bdrv_aio_cancel(BlockDriverAIOCB *acb);
|
||||
|
||||
typedef struct BlockRequest {
|
||||
@@ -151,8 +150,11 @@ void bdrv_close_all(void);
|
||||
int bdrv_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors);
|
||||
int bdrv_has_zero_init(BlockDriverState *bs);
|
||||
int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
|
||||
int *pnum);
|
||||
int *pnum);
|
||||
|
||||
#define BDRV_TYPE_HD 0
|
||||
#define BDRV_TYPE_CDROM 1
|
||||
#define BDRV_TYPE_FLOPPY 2
|
||||
#define BIOS_ATA_TRANSLATION_AUTO 0
|
||||
#define BIOS_ATA_TRANSLATION_NONE 1
|
||||
#define BIOS_ATA_TRANSLATION_LBA 2
|
||||
@@ -161,19 +163,11 @@ int bdrv_is_allocated(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
|
||||
|
||||
void bdrv_set_geometry_hint(BlockDriverState *bs,
|
||||
int cyls, int heads, int secs);
|
||||
void bdrv_set_type_hint(BlockDriverState *bs, int type);
|
||||
void bdrv_set_translation_hint(BlockDriverState *bs, int translation);
|
||||
void bdrv_get_geometry_hint(BlockDriverState *bs,
|
||||
int *pcyls, int *pheads, int *psecs);
|
||||
typedef enum FDriveType {
|
||||
FDRIVE_DRV_144 = 0x00, /* 1.44 MB 3"5 drive */
|
||||
FDRIVE_DRV_288 = 0x01, /* 2.88 MB 3"5 drive */
|
||||
FDRIVE_DRV_120 = 0x02, /* 1.2 MB 5"25 drive */
|
||||
FDRIVE_DRV_NONE = 0x03, /* No drive connected */
|
||||
} FDriveType;
|
||||
|
||||
void bdrv_get_floppy_geometry_hint(BlockDriverState *bs, int *nb_heads,
|
||||
int *max_track, int *last_sect,
|
||||
FDriveType drive_in, FDriveType *drive);
|
||||
int bdrv_get_type_hint(BlockDriverState *bs);
|
||||
int bdrv_get_translation_hint(BlockDriverState *bs);
|
||||
void bdrv_set_on_error(BlockDriverState *bs, BlockErrorAction on_read_error,
|
||||
BlockErrorAction on_write_error);
|
||||
|
209
block/nbd.c
209
block/nbd.c
@@ -29,152 +29,96 @@
|
||||
#include "qemu-common.h"
|
||||
#include "nbd.h"
|
||||
#include "module.h"
|
||||
#include "qemu_socket.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define EN_OPTSTR ":exportname="
|
||||
|
||||
/* #define DEBUG_NBD */
|
||||
|
||||
#if defined(DEBUG_NBD)
|
||||
#define logout(fmt, ...) \
|
||||
fprintf(stderr, "nbd\t%-24s" fmt, __func__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define logout(fmt, ...) ((void)0)
|
||||
#endif
|
||||
|
||||
typedef struct BDRVNBDState {
|
||||
int sock;
|
||||
off_t size;
|
||||
size_t blocksize;
|
||||
char *export_name; /* An NBD server may export several devices */
|
||||
|
||||
/* If it begins with '/', this is a UNIX domain socket. Otherwise,
|
||||
* it's a string of the form <hostname|ip4|\[ip6\]>:port
|
||||
*/
|
||||
char *host_spec;
|
||||
} BDRVNBDState;
|
||||
|
||||
static int nbd_config(BDRVNBDState *s, const char *filename, int flags)
|
||||
{
|
||||
char *file;
|
||||
char *export_name;
|
||||
const char *host_spec;
|
||||
const char *unixpath;
|
||||
int err = -EINVAL;
|
||||
|
||||
file = qemu_strdup(filename);
|
||||
|
||||
export_name = strstr(file, EN_OPTSTR);
|
||||
if (export_name) {
|
||||
if (export_name[strlen(EN_OPTSTR)] == 0) {
|
||||
goto out;
|
||||
}
|
||||
export_name[0] = 0; /* truncate 'file' */
|
||||
export_name += strlen(EN_OPTSTR);
|
||||
s->export_name = qemu_strdup(export_name);
|
||||
}
|
||||
|
||||
/* extract the host_spec - fail if it's not nbd:... */
|
||||
if (!strstart(file, "nbd:", &host_spec)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* are we a UNIX or TCP socket? */
|
||||
if (strstart(host_spec, "unix:", &unixpath)) {
|
||||
if (unixpath[0] != '/') { /* We demand an absolute path*/
|
||||
goto out;
|
||||
}
|
||||
s->host_spec = qemu_strdup(unixpath);
|
||||
} else {
|
||||
s->host_spec = qemu_strdup(host_spec);
|
||||
}
|
||||
|
||||
err = 0;
|
||||
|
||||
out:
|
||||
qemu_free(file);
|
||||
if (err != 0) {
|
||||
qemu_free(s->export_name);
|
||||
qemu_free(s->host_spec);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nbd_establish_connection(BlockDriverState *bs)
|
||||
{
|
||||
BDRVNBDState *s = bs->opaque;
|
||||
int sock;
|
||||
int ret;
|
||||
off_t size;
|
||||
size_t blocksize;
|
||||
uint32_t nbdflags;
|
||||
|
||||
if (s->host_spec[0] == '/') {
|
||||
sock = unix_socket_outgoing(s->host_spec);
|
||||
} else {
|
||||
sock = tcp_socket_outgoing_spec(s->host_spec);
|
||||
}
|
||||
|
||||
/* Failed to establish connection */
|
||||
if (sock == -1) {
|
||||
logout("Failed to establish connection to NBD server\n");
|
||||
return -errno;
|
||||
}
|
||||
|
||||
/* NBD handshake */
|
||||
ret = nbd_receive_negotiate(sock, s->export_name, &nbdflags, &size,
|
||||
&blocksize);
|
||||
if (ret == -1) {
|
||||
logout("Failed to negotiate with the NBD server\n");
|
||||
closesocket(sock);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
/* Now that we're connected, set the socket to be non-blocking */
|
||||
socket_set_nonblock(sock);
|
||||
|
||||
s->sock = sock;
|
||||
s->size = size;
|
||||
s->blocksize = blocksize;
|
||||
|
||||
logout("Established connection with NBD server\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nbd_teardown_connection(BlockDriverState *bs)
|
||||
{
|
||||
BDRVNBDState *s = bs->opaque;
|
||||
struct nbd_request request;
|
||||
|
||||
request.type = NBD_CMD_DISC;
|
||||
request.handle = (uint64_t)(intptr_t)bs;
|
||||
request.from = 0;
|
||||
request.len = 0;
|
||||
nbd_send_request(s->sock, &request);
|
||||
|
||||
closesocket(s->sock);
|
||||
}
|
||||
|
||||
static int nbd_open(BlockDriverState *bs, const char* filename, int flags)
|
||||
{
|
||||
BDRVNBDState *s = bs->opaque;
|
||||
int result;
|
||||
uint32_t nbdflags;
|
||||
|
||||
/* Pop the config into our state object. Exit if invalid. */
|
||||
result = nbd_config(s, filename, flags);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
char *file;
|
||||
char *name;
|
||||
const char *host;
|
||||
const char *unixpath;
|
||||
int sock;
|
||||
off_t size;
|
||||
size_t blocksize;
|
||||
int ret;
|
||||
int err = -EINVAL;
|
||||
|
||||
file = qemu_strdup(filename);
|
||||
|
||||
name = strstr(file, EN_OPTSTR);
|
||||
if (name) {
|
||||
if (name[strlen(EN_OPTSTR)] == 0) {
|
||||
goto out;
|
||||
}
|
||||
name[0] = 0;
|
||||
name += strlen(EN_OPTSTR);
|
||||
}
|
||||
|
||||
/* establish TCP connection, return error if it fails
|
||||
* TODO: Configurable retry-until-timeout behaviour.
|
||||
*/
|
||||
result = nbd_establish_connection(bs);
|
||||
if (!strstart(file, "nbd:", &host)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
return result;
|
||||
if (strstart(host, "unix:", &unixpath)) {
|
||||
|
||||
if (unixpath[0] != '/') {
|
||||
goto out;
|
||||
}
|
||||
|
||||
sock = unix_socket_outgoing(unixpath);
|
||||
|
||||
} else {
|
||||
uint16_t port = NBD_DEFAULT_PORT;
|
||||
char *p, *r;
|
||||
char hostname[128];
|
||||
|
||||
pstrcpy(hostname, 128, host);
|
||||
|
||||
p = strchr(hostname, ':');
|
||||
if (p != NULL) {
|
||||
*p = '\0';
|
||||
p++;
|
||||
|
||||
port = strtol(p, &r, 0);
|
||||
if (r == p) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
sock = tcp_socket_outgoing(hostname, port);
|
||||
}
|
||||
|
||||
if (sock == -1) {
|
||||
err = -errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = nbd_receive_negotiate(sock, name, &nbdflags, &size, &blocksize);
|
||||
if (ret == -1) {
|
||||
err = -errno;
|
||||
goto out;
|
||||
}
|
||||
|
||||
s->sock = sock;
|
||||
s->size = size;
|
||||
s->blocksize = blocksize;
|
||||
err = 0;
|
||||
|
||||
out:
|
||||
qemu_free(file);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int nbd_read(BlockDriverState *bs, int64_t sector_num,
|
||||
@@ -240,10 +184,15 @@ static int nbd_write(BlockDriverState *bs, int64_t sector_num,
|
||||
static void nbd_close(BlockDriverState *bs)
|
||||
{
|
||||
BDRVNBDState *s = bs->opaque;
|
||||
qemu_free(s->export_name);
|
||||
qemu_free(s->host_spec);
|
||||
struct nbd_request request;
|
||||
|
||||
nbd_teardown_connection(bs);
|
||||
request.type = NBD_CMD_DISC;
|
||||
request.handle = (uint64_t)(intptr_t)bs;
|
||||
request.from = 0;
|
||||
request.len = 0;
|
||||
nbd_send_request(s->sock, &request);
|
||||
|
||||
close(s->sock);
|
||||
}
|
||||
|
||||
static int64_t nbd_getlength(BlockDriverState *bs)
|
||||
|
74
block/qcow.c
74
block/qcow.c
@@ -496,8 +496,6 @@ typedef struct QCowAIOCB {
|
||||
uint64_t cluster_offset;
|
||||
uint8_t *cluster_data;
|
||||
struct iovec hd_iov;
|
||||
bool is_write;
|
||||
QEMUBH *bh;
|
||||
QEMUIOVector hd_qiov;
|
||||
BlockDriverAIOCB *hd_aiocb;
|
||||
} QCowAIOCB;
|
||||
@@ -527,8 +525,6 @@ static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs,
|
||||
acb->hd_aiocb = NULL;
|
||||
acb->sector_num = sector_num;
|
||||
acb->qiov = qiov;
|
||||
acb->is_write = is_write;
|
||||
|
||||
if (qiov->niov > 1) {
|
||||
acb->buf = acb->orig_buf = qemu_blockalign(bs, qiov->size);
|
||||
if (is_write)
|
||||
@@ -542,38 +538,6 @@ static QCowAIOCB *qcow_aio_setup(BlockDriverState *bs,
|
||||
return acb;
|
||||
}
|
||||
|
||||
static void qcow_aio_read_cb(void *opaque, int ret);
|
||||
static void qcow_aio_write_cb(void *opaque, int ret);
|
||||
|
||||
static void qcow_aio_rw_bh(void *opaque)
|
||||
{
|
||||
QCowAIOCB *acb = opaque;
|
||||
qemu_bh_delete(acb->bh);
|
||||
acb->bh = NULL;
|
||||
|
||||
if (acb->is_write) {
|
||||
qcow_aio_write_cb(opaque, 0);
|
||||
} else {
|
||||
qcow_aio_read_cb(opaque, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static int qcow_schedule_bh(QEMUBHFunc *cb, QCowAIOCB *acb)
|
||||
{
|
||||
if (acb->bh) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
acb->bh = qemu_bh_new(cb, acb);
|
||||
if (!acb->bh) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
qemu_bh_schedule(acb->bh);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void qcow_aio_read_cb(void *opaque, int ret)
|
||||
{
|
||||
QCowAIOCB *acb = opaque;
|
||||
@@ -625,10 +589,8 @@ static void qcow_aio_read_cb(void *opaque, int ret)
|
||||
qemu_iovec_init_external(&acb->hd_qiov, &acb->hd_iov, 1);
|
||||
acb->hd_aiocb = bdrv_aio_readv(bs->backing_hd, acb->sector_num,
|
||||
&acb->hd_qiov, acb->n, qcow_aio_read_cb, acb);
|
||||
if (acb->hd_aiocb == NULL) {
|
||||
ret = -EIO;
|
||||
if (acb->hd_aiocb == NULL)
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
/* Note: in this case, no need to wait */
|
||||
memset(acb->buf, 0, 512 * acb->n);
|
||||
@@ -636,10 +598,8 @@ static void qcow_aio_read_cb(void *opaque, int ret)
|
||||
}
|
||||
} else if (acb->cluster_offset & QCOW_OFLAG_COMPRESSED) {
|
||||
/* add AIO support for compressed blocks ? */
|
||||
if (decompress_cluster(bs, acb->cluster_offset) < 0) {
|
||||
ret = -EIO;
|
||||
if (decompress_cluster(bs, acb->cluster_offset) < 0)
|
||||
goto done;
|
||||
}
|
||||
memcpy(acb->buf,
|
||||
s->cluster_cache + index_in_cluster * 512, 512 * acb->n);
|
||||
goto redo;
|
||||
@@ -654,10 +614,8 @@ static void qcow_aio_read_cb(void *opaque, int ret)
|
||||
acb->hd_aiocb = bdrv_aio_readv(bs->file,
|
||||
(acb->cluster_offset >> 9) + index_in_cluster,
|
||||
&acb->hd_qiov, acb->n, qcow_aio_read_cb, acb);
|
||||
if (acb->hd_aiocb == NULL) {
|
||||
ret = -EIO;
|
||||
if (acb->hd_aiocb == NULL)
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -676,21 +634,12 @@ static BlockDriverAIOCB *qcow_aio_readv(BlockDriverState *bs,
|
||||
BlockDriverCompletionFunc *cb, void *opaque)
|
||||
{
|
||||
QCowAIOCB *acb;
|
||||
int ret;
|
||||
|
||||
acb = qcow_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
|
||||
if (!acb)
|
||||
return NULL;
|
||||
|
||||
ret = qcow_schedule_bh(qcow_aio_rw_bh, acb);
|
||||
if (ret < 0) {
|
||||
if (acb->qiov->niov > 1) {
|
||||
qemu_vfree(acb->orig_buf);
|
||||
}
|
||||
qemu_aio_release(acb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qcow_aio_read_cb(acb, 0);
|
||||
return &acb->common;
|
||||
}
|
||||
|
||||
@@ -751,10 +700,8 @@ static void qcow_aio_write_cb(void *opaque, int ret)
|
||||
(cluster_offset >> 9) + index_in_cluster,
|
||||
&acb->hd_qiov, acb->n,
|
||||
qcow_aio_write_cb, acb);
|
||||
if (acb->hd_aiocb == NULL) {
|
||||
ret = -EIO;
|
||||
if (acb->hd_aiocb == NULL)
|
||||
goto done;
|
||||
}
|
||||
return;
|
||||
|
||||
done:
|
||||
@@ -770,7 +717,6 @@ static BlockDriverAIOCB *qcow_aio_writev(BlockDriverState *bs,
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
QCowAIOCB *acb;
|
||||
int ret;
|
||||
|
||||
s->cluster_cache_offset = -1; /* disable compressed cache */
|
||||
|
||||
@@ -779,15 +725,7 @@ static BlockDriverAIOCB *qcow_aio_writev(BlockDriverState *bs,
|
||||
return NULL;
|
||||
|
||||
|
||||
ret = qcow_schedule_bh(qcow_aio_rw_bh, acb);
|
||||
if (ret < 0) {
|
||||
if (acb->qiov->niov > 1) {
|
||||
qemu_vfree(acb->orig_buf);
|
||||
}
|
||||
qemu_aio_release(acb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qcow_aio_write_cb(acb, 0);
|
||||
return &acb->common;
|
||||
}
|
||||
|
||||
|
@@ -312,15 +312,3 @@ found:
|
||||
c->entries[i].dirty = true;
|
||||
}
|
||||
|
||||
bool qcow2_cache_set_writethrough(BlockDriverState *bs, Qcow2Cache *c,
|
||||
bool enable)
|
||||
{
|
||||
bool old = c->writethrough;
|
||||
|
||||
if (!old && enable) {
|
||||
qcow2_cache_flush(bs, c);
|
||||
}
|
||||
|
||||
c->writethrough = enable;
|
||||
return old;
|
||||
}
|
||||
|
@@ -70,7 +70,7 @@ int qcow2_grow_l1_table(BlockDriverState *bs, int min_size, bool exact_size)
|
||||
|
||||
ret = qcow2_cache_flush(bs, s->refcount_block_cache);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
return ret;
|
||||
}
|
||||
|
||||
BLKDBG_EVENT(bs->file, BLKDBG_L1_GROW_WRITE_TABLE);
|
||||
@@ -796,8 +796,8 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
|
||||
m->depends_on = old_alloc;
|
||||
m->nb_clusters = 0;
|
||||
*num = 0;
|
||||
|
||||
goto out_wait_dependency;
|
||||
ret = 0;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -812,6 +812,7 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
|
||||
|
||||
cluster_offset = qcow2_alloc_clusters(bs, nb_clusters * s->cluster_size);
|
||||
if (cluster_offset < 0) {
|
||||
QLIST_REMOVE(m, next_in_flight);
|
||||
ret = cluster_offset;
|
||||
goto fail;
|
||||
}
|
||||
@@ -824,7 +825,7 @@ int qcow2_alloc_cluster_offset(BlockDriverState *bs, uint64_t offset,
|
||||
out:
|
||||
ret = qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
|
||||
if (ret < 0) {
|
||||
goto fail_put;
|
||||
return ret;
|
||||
}
|
||||
|
||||
m->nb_available = MIN(nb_clusters << (s->cluster_bits - 9), n_end);
|
||||
@@ -834,13 +835,8 @@ out:
|
||||
|
||||
return 0;
|
||||
|
||||
out_wait_dependency:
|
||||
return qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
|
||||
|
||||
fail:
|
||||
qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
|
||||
fail_put:
|
||||
QLIST_REMOVE(m, next_in_flight);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@@ -705,15 +705,8 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
uint64_t *l1_table, *l2_table, l2_offset, offset, l1_size2, l1_allocated;
|
||||
int64_t old_offset, old_l2_offset;
|
||||
int i, j, l1_modified = 0, nb_csectors, refcount;
|
||||
int i, j, l1_modified, nb_csectors, refcount;
|
||||
int ret;
|
||||
bool old_l2_writethrough, old_refcount_writethrough;
|
||||
|
||||
/* Switch caches to writeback mode during update */
|
||||
old_l2_writethrough =
|
||||
qcow2_cache_set_writethrough(bs, s->l2_table_cache, false);
|
||||
old_refcount_writethrough =
|
||||
qcow2_cache_set_writethrough(bs, s->refcount_block_cache, false);
|
||||
|
||||
l2_table = NULL;
|
||||
l1_table = NULL;
|
||||
@@ -727,11 +720,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
|
||||
l1_allocated = 1;
|
||||
if (bdrv_pread(bs->file, l1_table_offset,
|
||||
l1_table, l1_size2) != l1_size2)
|
||||
{
|
||||
ret = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
for(i = 0;i < l1_size; i++)
|
||||
be64_to_cpus(&l1_table[i]);
|
||||
} else {
|
||||
@@ -740,6 +729,7 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
|
||||
l1_allocated = 0;
|
||||
}
|
||||
|
||||
l1_modified = 0;
|
||||
for(i = 0; i < l1_size; i++) {
|
||||
l2_offset = l1_table[i];
|
||||
if (l2_offset) {
|
||||
@@ -783,7 +773,6 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
|
||||
}
|
||||
|
||||
if (refcount < 0) {
|
||||
ret = -EIO;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
@@ -814,7 +803,6 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
|
||||
refcount = get_refcount(bs, l2_offset >> s->cluster_bits);
|
||||
}
|
||||
if (refcount < 0) {
|
||||
ret = -EIO;
|
||||
goto fail;
|
||||
} else if (refcount == 1) {
|
||||
l2_offset |= QCOW_OFLAG_COPIED;
|
||||
@@ -825,18 +813,6 @@ int qcow2_update_snapshot_refcount(BlockDriverState *bs,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
fail:
|
||||
if (l2_table) {
|
||||
qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
|
||||
}
|
||||
|
||||
/* Enable writethrough cache mode again */
|
||||
qcow2_cache_set_writethrough(bs, s->l2_table_cache, old_l2_writethrough);
|
||||
qcow2_cache_set_writethrough(bs, s->refcount_block_cache,
|
||||
old_refcount_writethrough);
|
||||
|
||||
if (l1_modified) {
|
||||
for(i = 0; i < l1_size; i++)
|
||||
cpu_to_be64s(&l1_table[i]);
|
||||
@@ -848,7 +824,15 @@ fail:
|
||||
}
|
||||
if (l1_allocated)
|
||||
qemu_free(l1_table);
|
||||
return ret;
|
||||
return 0;
|
||||
fail:
|
||||
if (l2_table) {
|
||||
qcow2_cache_put(bs, s->l2_table_cache, (void**) &l2_table);
|
||||
}
|
||||
|
||||
if (l1_allocated)
|
||||
qemu_free(l1_table);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
|
||||
@@ -1079,7 +1063,7 @@ fail:
|
||||
* Checks an image for refcount consistency.
|
||||
*
|
||||
* Returns 0 if no errors are found, the number of errors in case the image is
|
||||
* detected as corrupted, and -errno when an internal error occurred.
|
||||
* detected as corrupted, and -errno when an internal error occured.
|
||||
*/
|
||||
int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res)
|
||||
{
|
||||
@@ -1102,7 +1086,7 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res)
|
||||
ret = check_refcounts_l1(bs, res, refcount_table, nb_clusters,
|
||||
s->l1_table_offset, s->l1_size, 1);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* snapshots */
|
||||
@@ -1111,7 +1095,7 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res)
|
||||
ret = check_refcounts_l1(bs, res, refcount_table, nb_clusters,
|
||||
sn->l1_table_offset, sn->l1_size, 0);
|
||||
if (ret < 0) {
|
||||
goto fail;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
inc_refcounts(bs, res, refcount_table, nb_clusters,
|
||||
@@ -1175,11 +1159,8 @@ int qcow2_check_refcounts(BlockDriverState *bs, BdrvCheckResult *res)
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
fail:
|
||||
qemu_free(refcount_table);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -317,8 +317,7 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
QCowSnapshot *sn;
|
||||
int i, snapshot_index;
|
||||
int cur_l1_bytes, sn_l1_bytes;
|
||||
int i, snapshot_index, l1_size2;
|
||||
|
||||
snapshot_index = find_snapshot_by_id_or_name(bs, snapshot_id);
|
||||
if (snapshot_index < 0)
|
||||
@@ -331,19 +330,14 @@ int qcow2_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
|
||||
if (qcow2_grow_l1_table(bs, sn->l1_size, true) < 0)
|
||||
goto fail;
|
||||
|
||||
cur_l1_bytes = s->l1_size * sizeof(uint64_t);
|
||||
sn_l1_bytes = sn->l1_size * sizeof(uint64_t);
|
||||
|
||||
if (cur_l1_bytes > sn_l1_bytes) {
|
||||
memset(s->l1_table + sn->l1_size, 0, cur_l1_bytes - sn_l1_bytes);
|
||||
}
|
||||
|
||||
s->l1_size = sn->l1_size;
|
||||
l1_size2 = s->l1_size * sizeof(uint64_t);
|
||||
/* copy the snapshot l1 table to the current l1 table */
|
||||
if (bdrv_pread(bs->file, sn->l1_table_offset,
|
||||
s->l1_table, sn_l1_bytes) < 0)
|
||||
s->l1_table, l1_size2) != l1_size2)
|
||||
goto fail;
|
||||
if (bdrv_pwrite_sync(bs->file, s->l1_table_offset,
|
||||
s->l1_table, cur_l1_bytes) < 0)
|
||||
s->l1_table, l1_size2) < 0)
|
||||
goto fail;
|
||||
for(i = 0;i < s->l1_size; i++) {
|
||||
be64_to_cpus(&s->l1_table[i]);
|
||||
|
@@ -229,7 +229,7 @@ static int qcow2_open(BlockDriverState *bs, int flags)
|
||||
}
|
||||
|
||||
/* alloc L2 table/refcount block cache */
|
||||
writethrough = ((flags & BDRV_O_CACHE_WB) == 0);
|
||||
writethrough = ((flags & BDRV_O_CACHE_MASK) == 0);
|
||||
s->l2_table_cache = qcow2_cache_create(bs, L2_CACHE_SIZE, writethrough);
|
||||
s->refcount_block_cache = qcow2_cache_create(bs, REFCOUNT_CACHE_SIZE,
|
||||
writethrough);
|
||||
@@ -378,7 +378,6 @@ typedef struct QCowAIOCB {
|
||||
uint64_t bytes_done;
|
||||
uint64_t cluster_offset;
|
||||
uint8_t *cluster_data;
|
||||
bool is_write;
|
||||
BlockDriverAIOCB *hd_aiocb;
|
||||
QEMUIOVector hd_qiov;
|
||||
QEMUBH *bh;
|
||||
@@ -400,19 +399,12 @@ static AIOPool qcow2_aio_pool = {
|
||||
};
|
||||
|
||||
static void qcow2_aio_read_cb(void *opaque, int ret);
|
||||
static void qcow2_aio_write_cb(void *opaque, int ret);
|
||||
|
||||
static void qcow2_aio_rw_bh(void *opaque)
|
||||
static void qcow2_aio_read_bh(void *opaque)
|
||||
{
|
||||
QCowAIOCB *acb = opaque;
|
||||
qemu_bh_delete(acb->bh);
|
||||
acb->bh = NULL;
|
||||
|
||||
if (acb->is_write) {
|
||||
qcow2_aio_write_cb(opaque, 0);
|
||||
} else {
|
||||
qcow2_aio_read_cb(opaque, 0);
|
||||
}
|
||||
qcow2_aio_read_cb(opaque, 0);
|
||||
}
|
||||
|
||||
static int qcow2_schedule_bh(QEMUBHFunc *cb, QCowAIOCB *acb)
|
||||
@@ -501,14 +493,14 @@ static void qcow2_aio_read_cb(void *opaque, int ret)
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
ret = qcow2_schedule_bh(qcow2_aio_rw_bh, acb);
|
||||
ret = qcow2_schedule_bh(qcow2_aio_read_bh, acb);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
/* Note: in this case, no need to wait */
|
||||
qemu_iovec_memset(&acb->hd_qiov, 0, 512 * acb->cur_nr_sectors);
|
||||
ret = qcow2_schedule_bh(qcow2_aio_rw_bh, acb);
|
||||
ret = qcow2_schedule_bh(qcow2_aio_read_bh, acb);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
}
|
||||
@@ -523,7 +515,7 @@ static void qcow2_aio_read_cb(void *opaque, int ret)
|
||||
s->cluster_cache + index_in_cluster * 512,
|
||||
512 * acb->cur_nr_sectors);
|
||||
|
||||
ret = qcow2_schedule_bh(qcow2_aio_rw_bh, acb);
|
||||
ret = qcow2_schedule_bh(qcow2_aio_read_bh, acb);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
} else {
|
||||
@@ -580,7 +572,6 @@ static QCowAIOCB *qcow2_aio_setup(BlockDriverState *bs, int64_t sector_num,
|
||||
acb->hd_aiocb = NULL;
|
||||
acb->sector_num = sector_num;
|
||||
acb->qiov = qiov;
|
||||
acb->is_write = is_write;
|
||||
|
||||
qemu_iovec_init(&acb->hd_qiov, qiov->niov);
|
||||
|
||||
@@ -600,22 +591,17 @@ static BlockDriverAIOCB *qcow2_aio_readv(BlockDriverState *bs,
|
||||
void *opaque)
|
||||
{
|
||||
QCowAIOCB *acb;
|
||||
int ret;
|
||||
|
||||
acb = qcow2_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
|
||||
if (!acb)
|
||||
return NULL;
|
||||
|
||||
ret = qcow2_schedule_bh(qcow2_aio_rw_bh, acb);
|
||||
if (ret < 0) {
|
||||
qemu_iovec_destroy(&acb->hd_qiov);
|
||||
qemu_aio_release(acb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qcow2_aio_read_cb(acb, 0);
|
||||
return &acb->common;
|
||||
}
|
||||
|
||||
static void qcow2_aio_write_cb(void *opaque, int ret);
|
||||
|
||||
static void run_dependent_requests(QCowL2Meta *m)
|
||||
{
|
||||
QCowAIOCB *req;
|
||||
@@ -738,7 +724,6 @@ static BlockDriverAIOCB *qcow2_aio_writev(BlockDriverState *bs,
|
||||
{
|
||||
BDRVQcowState *s = bs->opaque;
|
||||
QCowAIOCB *acb;
|
||||
int ret;
|
||||
|
||||
s->cluster_cache_offset = -1; /* disable compressed cache */
|
||||
|
||||
@@ -746,13 +731,7 @@ static BlockDriverAIOCB *qcow2_aio_writev(BlockDriverState *bs,
|
||||
if (!acb)
|
||||
return NULL;
|
||||
|
||||
ret = qcow2_schedule_bh(qcow2_aio_rw_bh, acb);
|
||||
if (ret < 0) {
|
||||
qemu_iovec_destroy(&acb->hd_qiov);
|
||||
qemu_aio_release(acb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
qcow2_aio_write_cb(acb, 0);
|
||||
return &acb->common;
|
||||
}
|
||||
|
||||
@@ -936,7 +915,7 @@ static int qcow2_create2(const char *filename, int64_t total_size,
|
||||
(1 << cluster_bits) != cluster_size)
|
||||
{
|
||||
error_report(
|
||||
"Cluster size must be a power of two between %d and %dk",
|
||||
"Cluster size must be a power of two between %d and %dk\n",
|
||||
1 << MIN_CLUSTER_BITS, 1 << (MAX_CLUSTER_BITS - 10));
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1057,7 +1036,7 @@ static int qcow2_create(const char *filename, QEMUOptionParameter *options)
|
||||
const char *backing_fmt = NULL;
|
||||
uint64_t sectors = 0;
|
||||
int flags = 0;
|
||||
size_t cluster_size = DEFAULT_CLUSTER_SIZE;
|
||||
size_t cluster_size = 65536;
|
||||
int prealloc = 0;
|
||||
|
||||
/* Read out options */
|
||||
@@ -1364,8 +1343,7 @@ static QEMUOptionParameter qcow2_create_options[] = {
|
||||
{
|
||||
.name = BLOCK_OPT_CLUSTER_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.help = "qcow2 cluster size",
|
||||
.value = { .n = DEFAULT_CLUSTER_SIZE },
|
||||
.help = "qcow2 cluster size"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_PREALLOC,
|
||||
|
@@ -54,8 +54,6 @@
|
||||
/* Must be at least 4 to cover all cases of refcount table growth */
|
||||
#define REFCOUNT_CACHE_SIZE 4
|
||||
|
||||
#define DEFAULT_CLUSTER_SIZE 65536
|
||||
|
||||
typedef struct QCowHeader {
|
||||
uint32_t magic;
|
||||
uint32_t version;
|
||||
@@ -228,8 +226,6 @@ int qcow2_read_snapshots(BlockDriverState *bs);
|
||||
Qcow2Cache *qcow2_cache_create(BlockDriverState *bs, int num_tables,
|
||||
bool writethrough);
|
||||
int qcow2_cache_destroy(BlockDriverState* bs, Qcow2Cache *c);
|
||||
bool qcow2_cache_set_writethrough(BlockDriverState *bs, Qcow2Cache *c,
|
||||
bool enable);
|
||||
|
||||
void qcow2_cache_entry_mark_dirty(Qcow2Cache *c, void *table);
|
||||
int qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c);
|
||||
|
@@ -72,8 +72,7 @@ static unsigned int qed_check_l2_table(QEDCheck *check, QEDTable *table)
|
||||
for (i = 0; i < s->table_nelems; i++) {
|
||||
uint64_t offset = table->offsets[i];
|
||||
|
||||
if (qed_offset_is_unalloc_cluster(offset) ||
|
||||
qed_offset_is_zero_cluster(offset)) {
|
||||
if (!offset) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -112,7 +111,7 @@ static int qed_check_l1_table(QEDCheck *check, QEDTable *table)
|
||||
unsigned int num_invalid_l2;
|
||||
uint64_t offset = table->offsets[i];
|
||||
|
||||
if (qed_offset_is_unalloc_cluster(offset)) {
|
||||
if (!offset) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@@ -23,8 +23,7 @@
|
||||
* @n: Maximum number of clusters
|
||||
* @offset: Set to first cluster offset
|
||||
*
|
||||
* This function scans tables for contiguous clusters. A contiguous run of
|
||||
* clusters may be allocated, unallocated, or zero.
|
||||
* This function scans tables for contiguous allocated or free clusters.
|
||||
*/
|
||||
static unsigned int qed_count_contiguous_clusters(BDRVQEDState *s,
|
||||
QEDTable *table,
|
||||
@@ -39,14 +38,9 @@ static unsigned int qed_count_contiguous_clusters(BDRVQEDState *s,
|
||||
*offset = last;
|
||||
|
||||
for (i = index + 1; i < end; i++) {
|
||||
if (qed_offset_is_unalloc_cluster(last)) {
|
||||
/* Counting unallocated clusters */
|
||||
if (!qed_offset_is_unalloc_cluster(table->offsets[i])) {
|
||||
break;
|
||||
}
|
||||
} else if (qed_offset_is_zero_cluster(last)) {
|
||||
/* Counting zero clusters */
|
||||
if (!qed_offset_is_zero_cluster(table->offsets[i])) {
|
||||
if (last == 0) {
|
||||
/* Counting free clusters */
|
||||
if (table->offsets[i] != 0) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
@@ -93,19 +87,14 @@ static void qed_find_cluster_cb(void *opaque, int ret)
|
||||
n = qed_count_contiguous_clusters(s, request->l2_table->table,
|
||||
index, n, &offset);
|
||||
|
||||
if (qed_offset_is_unalloc_cluster(offset)) {
|
||||
ret = QED_CLUSTER_L2;
|
||||
} else if (qed_offset_is_zero_cluster(offset)) {
|
||||
ret = QED_CLUSTER_ZERO;
|
||||
} else if (qed_check_cluster_offset(s, offset)) {
|
||||
ret = QED_CLUSTER_FOUND;
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
ret = offset ? QED_CLUSTER_FOUND : QED_CLUSTER_L2;
|
||||
len = MIN(find_cluster_cb->len, n * s->header.cluster_size -
|
||||
qed_offset_into_cluster(s, find_cluster_cb->pos));
|
||||
|
||||
if (offset && !qed_check_cluster_offset(s, offset)) {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
|
||||
out:
|
||||
find_cluster_cb->cb(find_cluster_cb->opaque, ret, offset, len);
|
||||
qemu_free(find_cluster_cb);
|
||||
@@ -143,7 +132,7 @@ void qed_find_cluster(BDRVQEDState *s, QEDRequest *request, uint64_t pos,
|
||||
len = MIN(len, (((pos >> s->l1_shift) + 1) << s->l1_shift) - pos);
|
||||
|
||||
l2_offset = s->l1_table->offsets[qed_l1_index(s, pos)];
|
||||
if (qed_offset_is_unalloc_cluster(l2_offset)) {
|
||||
if (!l2_offset) {
|
||||
cb(opaque, QED_CLUSTER_L1, 0, len);
|
||||
return;
|
||||
}
|
||||
|
@@ -230,21 +230,21 @@ static void qed_read_l2_table_cb(void *opaque, int ret)
|
||||
QEDRequest *request = read_l2_table_cb->request;
|
||||
BDRVQEDState *s = read_l2_table_cb->s;
|
||||
CachedL2Table *l2_table = request->l2_table;
|
||||
uint64_t l2_offset = read_l2_table_cb->l2_offset;
|
||||
|
||||
if (ret) {
|
||||
/* can't trust loaded L2 table anymore */
|
||||
qed_unref_l2_cache_entry(l2_table);
|
||||
request->l2_table = NULL;
|
||||
} else {
|
||||
l2_table->offset = l2_offset;
|
||||
l2_table->offset = read_l2_table_cb->l2_offset;
|
||||
|
||||
qed_commit_l2_cache_entry(&s->l2_cache, l2_table);
|
||||
|
||||
/* This is guaranteed to succeed because we just committed the entry
|
||||
* to the cache.
|
||||
*/
|
||||
request->l2_table = qed_find_l2_cache_entry(&s->l2_cache, l2_offset);
|
||||
request->l2_table = qed_find_l2_cache_entry(&s->l2_cache,
|
||||
l2_table->offset);
|
||||
assert(request->l2_table != NULL);
|
||||
}
|
||||
|
||||
|
154
block/qed.c
154
block/qed.c
@@ -12,7 +12,6 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu-timer.h"
|
||||
#include "trace.h"
|
||||
#include "qed.h"
|
||||
#include "qerror.h"
|
||||
@@ -292,88 +291,6 @@ static CachedL2Table *qed_new_l2_table(BDRVQEDState *s)
|
||||
|
||||
static void qed_aio_next_io(void *opaque, int ret);
|
||||
|
||||
static void qed_plug_allocating_write_reqs(BDRVQEDState *s)
|
||||
{
|
||||
assert(!s->allocating_write_reqs_plugged);
|
||||
|
||||
s->allocating_write_reqs_plugged = true;
|
||||
}
|
||||
|
||||
static void qed_unplug_allocating_write_reqs(BDRVQEDState *s)
|
||||
{
|
||||
QEDAIOCB *acb;
|
||||
|
||||
assert(s->allocating_write_reqs_plugged);
|
||||
|
||||
s->allocating_write_reqs_plugged = false;
|
||||
|
||||
acb = QSIMPLEQ_FIRST(&s->allocating_write_reqs);
|
||||
if (acb) {
|
||||
qed_aio_next_io(acb, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void qed_finish_clear_need_check(void *opaque, int ret)
|
||||
{
|
||||
/* Do nothing */
|
||||
}
|
||||
|
||||
static void qed_flush_after_clear_need_check(void *opaque, int ret)
|
||||
{
|
||||
BDRVQEDState *s = opaque;
|
||||
|
||||
bdrv_aio_flush(s->bs, qed_finish_clear_need_check, s);
|
||||
|
||||
/* No need to wait until flush completes */
|
||||
qed_unplug_allocating_write_reqs(s);
|
||||
}
|
||||
|
||||
static void qed_clear_need_check(void *opaque, int ret)
|
||||
{
|
||||
BDRVQEDState *s = opaque;
|
||||
|
||||
if (ret) {
|
||||
qed_unplug_allocating_write_reqs(s);
|
||||
return;
|
||||
}
|
||||
|
||||
s->header.features &= ~QED_F_NEED_CHECK;
|
||||
qed_write_header(s, qed_flush_after_clear_need_check, s);
|
||||
}
|
||||
|
||||
static void qed_need_check_timer_cb(void *opaque)
|
||||
{
|
||||
BDRVQEDState *s = opaque;
|
||||
|
||||
/* The timer should only fire when allocating writes have drained */
|
||||
assert(!QSIMPLEQ_FIRST(&s->allocating_write_reqs));
|
||||
|
||||
trace_qed_need_check_timer_cb(s);
|
||||
|
||||
qed_plug_allocating_write_reqs(s);
|
||||
|
||||
/* Ensure writes are on disk before clearing flag */
|
||||
bdrv_aio_flush(s->bs, qed_clear_need_check, s);
|
||||
}
|
||||
|
||||
static void qed_start_need_check_timer(BDRVQEDState *s)
|
||||
{
|
||||
trace_qed_start_need_check_timer(s);
|
||||
|
||||
/* Use vm_clock so we don't alter the image file while suspended for
|
||||
* migration.
|
||||
*/
|
||||
qemu_mod_timer(s->need_check_timer, qemu_get_clock_ns(vm_clock) +
|
||||
get_ticks_per_sec() * QED_NEED_CHECK_TIMEOUT);
|
||||
}
|
||||
|
||||
/* It's okay to call this multiple times or when no timer is started */
|
||||
static void qed_cancel_need_check_timer(BDRVQEDState *s)
|
||||
{
|
||||
trace_qed_cancel_need_check_timer(s);
|
||||
qemu_del_timer(s->need_check_timer);
|
||||
}
|
||||
|
||||
static int bdrv_qed_open(BlockDriverState *bs, int flags)
|
||||
{
|
||||
BDRVQEDState *s = bs->opaque;
|
||||
@@ -489,10 +406,7 @@ static int bdrv_qed_open(BlockDriverState *bs, int flags)
|
||||
BdrvCheckResult result = {0};
|
||||
|
||||
ret = qed_check(s, &result, true);
|
||||
if (ret) {
|
||||
goto out;
|
||||
}
|
||||
if (!result.corruptions && !result.check_errors) {
|
||||
if (!ret && !result.corruptions && !result.check_errors) {
|
||||
/* Ensure fixes reach storage before clearing check bit */
|
||||
bdrv_flush(s->bs);
|
||||
|
||||
@@ -502,9 +416,6 @@ 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);
|
||||
|
||||
out:
|
||||
if (ret) {
|
||||
qed_free_l2_cache(&s->l2_cache);
|
||||
@@ -517,9 +428,6 @@ static void bdrv_qed_close(BlockDriverState *bs)
|
||||
{
|
||||
BDRVQEDState *s = bs->opaque;
|
||||
|
||||
qed_cancel_need_check_timer(s);
|
||||
qemu_free_timer(s->need_check_timer);
|
||||
|
||||
/* Ensure writes reach stable storage */
|
||||
bdrv_flush(bs->file);
|
||||
|
||||
@@ -665,7 +573,7 @@ static void qed_is_allocated_cb(void *opaque, int ret, uint64_t offset, size_t l
|
||||
{
|
||||
QEDIsAllocatedCB *cb = opaque;
|
||||
*cb->pnum = len / BDRV_SECTOR_SIZE;
|
||||
cb->is_allocated = (ret == QED_CLUSTER_FOUND || ret == QED_CLUSTER_ZERO);
|
||||
cb->is_allocated = ret == QED_CLUSTER_FOUND;
|
||||
}
|
||||
|
||||
static int bdrv_qed_is_allocated(BlockDriverState *bs, int64_t sector_num,
|
||||
@@ -837,10 +745,7 @@ static void qed_copy_from_backing_file(BDRVQEDState *s, uint64_t pos,
|
||||
* @table: L2 table
|
||||
* @index: First cluster index
|
||||
* @n: Number of contiguous clusters
|
||||
* @cluster: First cluster offset
|
||||
*
|
||||
* The cluster offset may be an allocated byte offset in the image file, the
|
||||
* zero cluster marker, or the unallocated cluster marker.
|
||||
* @cluster: First cluster byte offset in image file
|
||||
*/
|
||||
static void qed_update_l2_table(BDRVQEDState *s, QEDTable *table, int index,
|
||||
unsigned int n, uint64_t cluster)
|
||||
@@ -848,10 +753,7 @@ static void qed_update_l2_table(BDRVQEDState *s, QEDTable *table, int index,
|
||||
int i;
|
||||
for (i = index; i < index + n; i++) {
|
||||
table->offsets[i] = cluster;
|
||||
if (!qed_offset_is_unalloc_cluster(cluster) &&
|
||||
!qed_offset_is_zero_cluster(cluster)) {
|
||||
cluster += s->header.cluster_size;
|
||||
}
|
||||
cluster += s->header.cluster_size;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -901,8 +803,6 @@ static void qed_aio_complete(QEDAIOCB *acb, int ret)
|
||||
acb = QSIMPLEQ_FIRST(&s->allocating_write_reqs);
|
||||
if (acb) {
|
||||
qed_aio_next_io(acb, 0);
|
||||
} else if (s->header.features & QED_F_NEED_CHECK) {
|
||||
qed_start_need_check_timer(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -915,14 +815,14 @@ static void qed_commit_l2_update(void *opaque, int ret)
|
||||
QEDAIOCB *acb = opaque;
|
||||
BDRVQEDState *s = acb_to_s(acb);
|
||||
CachedL2Table *l2_table = acb->request.l2_table;
|
||||
uint64_t l2_offset = l2_table->offset;
|
||||
|
||||
qed_commit_l2_cache_entry(&s->l2_cache, l2_table);
|
||||
|
||||
/* This is guaranteed to succeed because we just committed the entry to the
|
||||
* cache.
|
||||
*/
|
||||
acb->request.l2_table = qed_find_l2_cache_entry(&s->l2_cache, l2_offset);
|
||||
acb->request.l2_table = qed_find_l2_cache_entry(&s->l2_cache,
|
||||
l2_table->offset);
|
||||
assert(acb->request.l2_table != NULL);
|
||||
|
||||
qed_aio_next_io(opaque, ret);
|
||||
@@ -1108,17 +1008,11 @@ static void qed_aio_write_alloc(QEDAIOCB *acb, size_t len)
|
||||
{
|
||||
BDRVQEDState *s = acb_to_s(acb);
|
||||
|
||||
/* Cancel timer when the first allocating request comes in */
|
||||
if (QSIMPLEQ_EMPTY(&s->allocating_write_reqs)) {
|
||||
qed_cancel_need_check_timer(s);
|
||||
}
|
||||
|
||||
/* Freeze this request if another allocating write is in progress */
|
||||
if (acb != QSIMPLEQ_FIRST(&s->allocating_write_reqs)) {
|
||||
QSIMPLEQ_INSERT_TAIL(&s->allocating_write_reqs, acb, next);
|
||||
}
|
||||
if (acb != QSIMPLEQ_FIRST(&s->allocating_write_reqs) ||
|
||||
s->allocating_write_reqs_plugged) {
|
||||
if (acb != QSIMPLEQ_FIRST(&s->allocating_write_reqs)) {
|
||||
return; /* wait for existing request to finish */
|
||||
}
|
||||
|
||||
@@ -1181,7 +1075,6 @@ static void qed_aio_write_data(void *opaque, int ret,
|
||||
|
||||
case QED_CLUSTER_L2:
|
||||
case QED_CLUSTER_L1:
|
||||
case QED_CLUSTER_ZERO:
|
||||
qed_aio_write_alloc(acb, len);
|
||||
break;
|
||||
|
||||
@@ -1221,12 +1114,8 @@ static void qed_aio_read_data(void *opaque, int ret,
|
||||
|
||||
qemu_iovec_copy(&acb->cur_qiov, acb->qiov, acb->qiov_offset, len);
|
||||
|
||||
/* Handle zero cluster and backing file reads */
|
||||
if (ret == QED_CLUSTER_ZERO) {
|
||||
qemu_iovec_memset(&acb->cur_qiov, 0, acb->cur_qiov.size);
|
||||
qed_aio_next_io(acb, 0);
|
||||
return;
|
||||
} else if (ret != QED_CLUSTER_FOUND) {
|
||||
/* Handle backing file and unallocated sparse hole reads */
|
||||
if (ret != QED_CLUSTER_FOUND) {
|
||||
qed_read_backing_file(s, acb->cur_pos, &acb->cur_qiov,
|
||||
qed_aio_next_io, acb);
|
||||
return;
|
||||
@@ -1333,27 +1222,7 @@ static BlockDriverAIOCB *bdrv_qed_aio_flush(BlockDriverState *bs,
|
||||
|
||||
static int bdrv_qed_truncate(BlockDriverState *bs, int64_t offset)
|
||||
{
|
||||
BDRVQEDState *s = bs->opaque;
|
||||
uint64_t old_image_size;
|
||||
int ret;
|
||||
|
||||
if (!qed_is_image_size_valid(offset, s->header.cluster_size,
|
||||
s->header.table_size)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Shrinking is currently not supported */
|
||||
if ((uint64_t)offset < s->header.image_size) {
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
old_image_size = s->header.image_size;
|
||||
s->header.image_size = offset;
|
||||
ret = qed_write_header_sync(s);
|
||||
if (ret < 0) {
|
||||
s->header.image_size = old_image_size;
|
||||
}
|
||||
return ret;
|
||||
return -ENOTSUP;
|
||||
}
|
||||
|
||||
static int64_t bdrv_qed_getlength(BlockDriverState *bs)
|
||||
@@ -1464,8 +1333,7 @@ static QEMUOptionParameter qed_create_options[] = {
|
||||
}, {
|
||||
.name = BLOCK_OPT_CLUSTER_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.help = "Cluster size (in bytes)",
|
||||
.value = { .n = QED_DEFAULT_CLUSTER_SIZE },
|
||||
.help = "Cluster size (in bytes)"
|
||||
}, {
|
||||
.name = BLOCK_OPT_TABLE_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
|
33
block/qed.h
33
block/qed.h
@@ -78,9 +78,6 @@ enum {
|
||||
QED_MIN_TABLE_SIZE = 1, /* in clusters */
|
||||
QED_MAX_TABLE_SIZE = 16,
|
||||
QED_DEFAULT_TABLE_SIZE = 4,
|
||||
|
||||
/* Delay to flush and clean image after last allocating write completes */
|
||||
QED_NEED_CHECK_TIMEOUT = 5, /* in seconds */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
@@ -160,15 +157,10 @@ typedef struct {
|
||||
|
||||
/* Allocating write request queue */
|
||||
QSIMPLEQ_HEAD(, QEDAIOCB) allocating_write_reqs;
|
||||
bool allocating_write_reqs_plugged;
|
||||
|
||||
/* Periodic flush and clear need check flag */
|
||||
QEMUTimer *need_check_timer;
|
||||
} BDRVQEDState;
|
||||
|
||||
enum {
|
||||
QED_CLUSTER_FOUND, /* cluster found */
|
||||
QED_CLUSTER_ZERO, /* zero cluster found */
|
||||
QED_CLUSTER_L2, /* cluster missing in L2 */
|
||||
QED_CLUSTER_L1, /* cluster missing in L1 */
|
||||
};
|
||||
@@ -306,29 +298,4 @@ static inline bool qed_check_table_offset(BDRVQEDState *s, uint64_t offset)
|
||||
qed_check_cluster_offset(s, end_offset);
|
||||
}
|
||||
|
||||
static inline bool qed_offset_is_cluster_aligned(BDRVQEDState *s,
|
||||
uint64_t offset)
|
||||
{
|
||||
if (qed_offset_into_cluster(s, offset)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool qed_offset_is_unalloc_cluster(uint64_t offset)
|
||||
{
|
||||
if (offset == 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool qed_offset_is_zero_cluster(uint64_t offset)
|
||||
{
|
||||
if (offset == 1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif /* BLOCK_QED_H */
|
||||
|
@@ -43,17 +43,17 @@
|
||||
|
||||
#ifdef __sun__
|
||||
#define _POSIX_PTHREAD_SEMANTICS 1
|
||||
#include <signal.h>
|
||||
#include <sys/dkio.h>
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/param.h>
|
||||
#include <linux/cdrom.h>
|
||||
#include <linux/fd.h>
|
||||
#endif
|
||||
#if defined (__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
#include <signal.h>
|
||||
#include <sys/disk.h>
|
||||
#include <sys/cdio.h>
|
||||
#endif
|
||||
@@ -64,13 +64,6 @@
|
||||
#include <sys/dkio.h>
|
||||
#endif
|
||||
|
||||
#ifdef __NetBSD__
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/dkio.h>
|
||||
#include <sys/disk.h>
|
||||
#endif
|
||||
|
||||
#ifdef __DragonFly__
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/diskslice.h>
|
||||
@@ -143,55 +136,12 @@ static int64_t raw_getlength(BlockDriverState *bs);
|
||||
static int cdrom_reopen(BlockDriverState *bs);
|
||||
#endif
|
||||
|
||||
#if defined(__NetBSD__)
|
||||
static int raw_normalize_devicepath(const char **filename)
|
||||
{
|
||||
static char namebuf[PATH_MAX];
|
||||
const char *dp, *fname;
|
||||
struct stat sb;
|
||||
|
||||
fname = *filename;
|
||||
dp = strrchr(fname, '/');
|
||||
if (lstat(fname, &sb) < 0) {
|
||||
fprintf(stderr, "%s: stat failed: %s\n",
|
||||
fname, strerror(errno));
|
||||
return -errno;
|
||||
}
|
||||
|
||||
if (!S_ISBLK(sb.st_mode)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (dp == NULL) {
|
||||
snprintf(namebuf, PATH_MAX, "r%s", fname);
|
||||
} else {
|
||||
snprintf(namebuf, PATH_MAX, "%.*s/r%s",
|
||||
(int)(dp - fname), fname, dp + 1);
|
||||
}
|
||||
fprintf(stderr, "%s is a block device", fname);
|
||||
*filename = namebuf;
|
||||
fprintf(stderr, ", using %s\n", *filename);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int raw_normalize_devicepath(const char **filename)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int raw_open_common(BlockDriverState *bs, const char *filename,
|
||||
int bdrv_flags, int open_flags)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
int fd, ret;
|
||||
|
||||
ret = raw_normalize_devicepath(&filename);
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
s->open_flags = open_flags | O_BINARY;
|
||||
s->open_flags &= ~O_ACCMODE;
|
||||
if (bdrv_flags & BDRV_O_RDWR) {
|
||||
@@ -204,7 +154,7 @@ static int raw_open_common(BlockDriverState *bs, const char *filename,
|
||||
* and O_DIRECT for no caching. */
|
||||
if ((bdrv_flags & BDRV_O_NOCACHE))
|
||||
s->open_flags |= O_DIRECT;
|
||||
if (!(bdrv_flags & BDRV_O_CACHE_WB))
|
||||
else if (!(bdrv_flags & BDRV_O_CACHE_WB))
|
||||
s->open_flags |= O_DSYNC;
|
||||
|
||||
s->fd = -1;
|
||||
@@ -672,31 +622,6 @@ static int64_t raw_getlength(BlockDriverState *bs)
|
||||
} else
|
||||
return st.st_size;
|
||||
}
|
||||
#elif defined(__NetBSD__)
|
||||
static int64_t raw_getlength(BlockDriverState *bs)
|
||||
{
|
||||
BDRVRawState *s = bs->opaque;
|
||||
int fd = s->fd;
|
||||
struct stat st;
|
||||
|
||||
if (fstat(fd, &st))
|
||||
return -1;
|
||||
if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
|
||||
struct dkwedge_info dkw;
|
||||
|
||||
if (ioctl(fd, DIOCGWEDGEINFO, &dkw) != -1) {
|
||||
return dkw.dkw_size * 512;
|
||||
} else {
|
||||
struct disklabel dl;
|
||||
|
||||
if (ioctl(fd, DIOCGDINFO, &dl))
|
||||
return -1;
|
||||
return (uint64_t)dl.d_secsize *
|
||||
dl.d_partitions[DISKPART(st.st_rdev)].p_size;
|
||||
}
|
||||
} else
|
||||
return st.st_size;
|
||||
}
|
||||
#elif defined(__sun__)
|
||||
static int64_t raw_getlength(BlockDriverState *bs)
|
||||
{
|
||||
@@ -793,17 +718,6 @@ static int64_t raw_getlength(BlockDriverState *bs)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
|
||||
{
|
||||
struct stat st;
|
||||
BDRVRawState *s = bs->opaque;
|
||||
|
||||
if (fstat(s->fd, &st) < 0) {
|
||||
return -errno;
|
||||
}
|
||||
return (int64_t)st.st_blocks * 512;
|
||||
}
|
||||
|
||||
static int raw_create(const char *filename, QEMUOptionParameter *options)
|
||||
{
|
||||
int fd;
|
||||
@@ -899,8 +813,6 @@ static BlockDriver bdrv_file = {
|
||||
|
||||
.bdrv_truncate = raw_truncate,
|
||||
.bdrv_getlength = raw_getlength,
|
||||
.bdrv_get_allocated_file_size
|
||||
= raw_get_allocated_file_size,
|
||||
|
||||
.create_options = raw_create_options,
|
||||
};
|
||||
@@ -1169,8 +1081,6 @@ static BlockDriver bdrv_host_device = {
|
||||
.bdrv_read = raw_read,
|
||||
.bdrv_write = raw_write,
|
||||
.bdrv_getlength = raw_getlength,
|
||||
.bdrv_get_allocated_file_size
|
||||
= raw_get_allocated_file_size,
|
||||
|
||||
/* generic scsi device */
|
||||
#ifdef __linux__
|
||||
@@ -1205,7 +1115,6 @@ static int floppy_probe_device(const char *filename)
|
||||
int fd, ret;
|
||||
int prio = 0;
|
||||
struct floppy_struct fdparam;
|
||||
struct stat st;
|
||||
|
||||
if (strstart(filename, "/dev/fd", NULL))
|
||||
prio = 50;
|
||||
@@ -1214,17 +1123,12 @@ static int floppy_probe_device(const char *filename)
|
||||
if (fd < 0) {
|
||||
goto out;
|
||||
}
|
||||
ret = fstat(fd, &st);
|
||||
if (ret == -1 || !S_ISBLK(st.st_mode)) {
|
||||
goto outc;
|
||||
}
|
||||
|
||||
/* Attempt to detect via a floppy specific ioctl */
|
||||
ret = ioctl(fd, FDGETPRM, &fdparam);
|
||||
if (ret >= 0)
|
||||
prio = 100;
|
||||
|
||||
outc:
|
||||
close(fd);
|
||||
out:
|
||||
return prio;
|
||||
@@ -1292,8 +1196,6 @@ static BlockDriver bdrv_host_floppy = {
|
||||
.bdrv_read = raw_read,
|
||||
.bdrv_write = raw_write,
|
||||
.bdrv_getlength = raw_getlength,
|
||||
.bdrv_get_allocated_file_size
|
||||
= raw_get_allocated_file_size,
|
||||
|
||||
/* removable device support */
|
||||
.bdrv_is_inserted = floppy_is_inserted,
|
||||
@@ -1315,23 +1217,17 @@ static int cdrom_probe_device(const char *filename)
|
||||
{
|
||||
int fd, ret;
|
||||
int prio = 0;
|
||||
struct stat st;
|
||||
|
||||
fd = open(filename, O_RDONLY | O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
goto out;
|
||||
}
|
||||
ret = fstat(fd, &st);
|
||||
if (ret == -1 || !S_ISBLK(st.st_mode)) {
|
||||
goto outc;
|
||||
}
|
||||
|
||||
/* Attempt to detect via a CDROM specific ioctl */
|
||||
ret = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
|
||||
if (ret >= 0)
|
||||
prio = 100;
|
||||
|
||||
outc:
|
||||
close(fd);
|
||||
out:
|
||||
return prio;
|
||||
@@ -1397,8 +1293,6 @@ static BlockDriver bdrv_host_cdrom = {
|
||||
.bdrv_read = raw_read,
|
||||
.bdrv_write = raw_write,
|
||||
.bdrv_getlength = raw_getlength,
|
||||
.bdrv_get_allocated_file_size
|
||||
= raw_get_allocated_file_size,
|
||||
|
||||
/* removable device support */
|
||||
.bdrv_is_inserted = cdrom_is_inserted,
|
||||
@@ -1522,8 +1416,6 @@ static BlockDriver bdrv_host_cdrom = {
|
||||
.bdrv_read = raw_read,
|
||||
.bdrv_write = raw_write,
|
||||
.bdrv_getlength = raw_getlength,
|
||||
.bdrv_get_allocated_file_size
|
||||
= raw_get_allocated_file_size,
|
||||
|
||||
/* removable device support */
|
||||
.bdrv_is_inserted = cdrom_is_inserted,
|
||||
|
@@ -88,9 +88,9 @@ static int raw_open(BlockDriverState *bs, const char *filename, int flags)
|
||||
}
|
||||
|
||||
overlapped = FILE_ATTRIBUTE_NORMAL;
|
||||
if (flags & BDRV_O_NOCACHE)
|
||||
overlapped |= FILE_FLAG_NO_BUFFERING;
|
||||
if (!(flags & BDRV_O_CACHE_WB))
|
||||
if ((flags & BDRV_O_NOCACHE))
|
||||
overlapped |= FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH;
|
||||
else if (!(flags & BDRV_O_CACHE_WB))
|
||||
overlapped |= FILE_FLAG_WRITE_THROUGH;
|
||||
s->hfile = CreateFile(filename, access_flags,
|
||||
FILE_SHARE_READ, NULL,
|
||||
@@ -213,31 +213,6 @@ static int64_t raw_getlength(BlockDriverState *bs)
|
||||
return l.QuadPart;
|
||||
}
|
||||
|
||||
static int64_t raw_get_allocated_file_size(BlockDriverState *bs)
|
||||
{
|
||||
typedef DWORD (WINAPI * get_compressed_t)(const char *filename,
|
||||
DWORD * high);
|
||||
get_compressed_t get_compressed;
|
||||
struct _stati64 st;
|
||||
const char *filename = bs->filename;
|
||||
/* WinNT support GetCompressedFileSize to determine allocate size */
|
||||
get_compressed =
|
||||
(get_compressed_t) GetProcAddress(GetModuleHandle("kernel32"),
|
||||
"GetCompressedFileSizeA");
|
||||
if (get_compressed) {
|
||||
DWORD high, low;
|
||||
low = get_compressed(filename, &high);
|
||||
if (low != 0xFFFFFFFFlu || GetLastError() == NO_ERROR) {
|
||||
return (((int64_t) high) << 32) + low;
|
||||
}
|
||||
}
|
||||
|
||||
if (_stati64(filename, &st) < 0) {
|
||||
return -1;
|
||||
}
|
||||
return st.st_size;
|
||||
}
|
||||
|
||||
static int raw_create(const char *filename, QEMUOptionParameter *options)
|
||||
{
|
||||
int fd;
|
||||
@@ -282,8 +257,6 @@ static BlockDriver bdrv_file = {
|
||||
.bdrv_write = raw_write,
|
||||
.bdrv_truncate = raw_truncate,
|
||||
.bdrv_getlength = raw_getlength,
|
||||
.bdrv_get_allocated_file_size
|
||||
= raw_get_allocated_file_size,
|
||||
|
||||
.create_options = raw_create_options,
|
||||
};
|
||||
@@ -376,9 +349,9 @@ static int hdev_open(BlockDriverState *bs, const char *filename, int flags)
|
||||
create_flags = OPEN_EXISTING;
|
||||
|
||||
overlapped = FILE_ATTRIBUTE_NORMAL;
|
||||
if (flags & BDRV_O_NOCACHE)
|
||||
overlapped |= FILE_FLAG_NO_BUFFERING;
|
||||
if (!(flags & BDRV_O_CACHE_WB))
|
||||
if ((flags & BDRV_O_NOCACHE))
|
||||
overlapped |= FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH;
|
||||
else if (!(flags & BDRV_O_CACHE_WB))
|
||||
overlapped |= FILE_FLAG_WRITE_THROUGH;
|
||||
s->hfile = CreateFile(filename, access_flags,
|
||||
FILE_SHARE_READ, NULL,
|
||||
@@ -446,8 +419,6 @@ static BlockDriver bdrv_host_device = {
|
||||
.bdrv_read = raw_read,
|
||||
.bdrv_write = raw_write,
|
||||
.bdrv_getlength = raw_getlength,
|
||||
.bdrv_get_allocated_file_size
|
||||
= raw_get_allocated_file_size,
|
||||
};
|
||||
|
||||
static void bdrv_file_init(void)
|
||||
|
922
block/rbd.c
922
block/rbd.c
File diff suppressed because it is too large
Load Diff
71
block/rbd_types.h
Normal file
71
block/rbd_types.h
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Ceph - scalable distributed file system
|
||||
*
|
||||
* Copyright (C) 2004-2010 Sage Weil <sage@newdream.net>
|
||||
*
|
||||
* This is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License version 2.1, as published by the Free Software
|
||||
* Foundation. See file COPYING.LIB.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CEPH_RBD_TYPES_H
|
||||
#define CEPH_RBD_TYPES_H
|
||||
|
||||
|
||||
/*
|
||||
* rbd image 'foo' consists of objects
|
||||
* foo.rbd - image metadata
|
||||
* foo.00000000
|
||||
* foo.00000001
|
||||
* ... - data
|
||||
*/
|
||||
|
||||
#define RBD_SUFFIX ".rbd"
|
||||
#define RBD_DIRECTORY "rbd_directory"
|
||||
#define RBD_INFO "rbd_info"
|
||||
|
||||
#define RBD_DEFAULT_OBJ_ORDER 22 /* 4MB */
|
||||
|
||||
#define RBD_MAX_OBJ_NAME_SIZE 96
|
||||
#define RBD_MAX_BLOCK_NAME_SIZE 24
|
||||
#define RBD_MAX_SEG_NAME_SIZE 128
|
||||
|
||||
#define RBD_COMP_NONE 0
|
||||
#define RBD_CRYPT_NONE 0
|
||||
|
||||
#define RBD_HEADER_TEXT "<<< Rados Block Device Image >>>\n"
|
||||
#define RBD_HEADER_SIGNATURE "RBD"
|
||||
#define RBD_HEADER_VERSION "001.005"
|
||||
|
||||
struct rbd_info {
|
||||
uint64_t max_id;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct rbd_obj_snap_ondisk {
|
||||
uint64_t id;
|
||||
uint64_t image_size;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct rbd_obj_header_ondisk {
|
||||
char text[40];
|
||||
char block_name[RBD_MAX_BLOCK_NAME_SIZE];
|
||||
char signature[4];
|
||||
char version[8];
|
||||
struct {
|
||||
uint8_t order;
|
||||
uint8_t crypt_type;
|
||||
uint8_t comp_type;
|
||||
uint8_t unused;
|
||||
} __attribute__((packed)) options;
|
||||
uint64_t image_size;
|
||||
uint64_t snap_seq;
|
||||
uint32_t snap_count;
|
||||
uint32_t reserved;
|
||||
uint64_t snap_names_len;
|
||||
struct rbd_obj_snap_ondisk snaps[0];
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
#endif
|
182
block/sheepdog.c
182
block/sheepdog.c
@@ -13,7 +13,6 @@
|
||||
#include "qemu-error.h"
|
||||
#include "qemu_socket.h"
|
||||
#include "block_int.h"
|
||||
#include "bitops.h"
|
||||
|
||||
#define SD_PROTO_VER 0x01
|
||||
|
||||
@@ -196,7 +195,7 @@ static inline uint64_t fnv_64a_buf(void *buf, size_t len, uint64_t hval)
|
||||
return hval;
|
||||
}
|
||||
|
||||
static inline int is_data_obj_writable(SheepdogInode *inode, unsigned int idx)
|
||||
static inline int is_data_obj_writeable(SheepdogInode *inode, unsigned int idx)
|
||||
{
|
||||
return inode->vdi_id == inode->data_vdi_id[idx];
|
||||
}
|
||||
@@ -444,12 +443,18 @@ static SheepdogAIOCB *sd_aio_setup(BlockDriverState *bs, QEMUIOVector *qiov,
|
||||
static int sd_schedule_bh(QEMUBHFunc *cb, SheepdogAIOCB *acb)
|
||||
{
|
||||
if (acb->bh) {
|
||||
error_report("bug: %d %d", acb->aiocb_type, acb->aiocb_type);
|
||||
error_report("bug: %d %d\n", acb->aiocb_type, acb->aiocb_type);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
acb->bh = qemu_bh_new(cb, acb);
|
||||
if (!acb->bh) {
|
||||
error_report("oom: %d %d\n", acb->aiocb_type, acb->aiocb_type);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
qemu_bh_schedule(acb->bh);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -496,7 +501,7 @@ static ssize_t recvmsg(int s, struct msghdr *msg, int flags)
|
||||
}
|
||||
buf = qemu_malloc(size);
|
||||
|
||||
ret = qemu_recv(s, buf, size, flags);
|
||||
ret = recv(s, buf, size, flags);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
@@ -592,7 +597,7 @@ static int connect_to_sdog(const char *addr, const char *port)
|
||||
|
||||
ret = getaddrinfo(addr, port, &hints, &res0);
|
||||
if (ret) {
|
||||
error_report("unable to get address info %s, %s",
|
||||
error_report("unable to get address info %s, %s\n",
|
||||
addr, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
@@ -622,7 +627,7 @@ static int connect_to_sdog(const char *addr, const char *port)
|
||||
goto success;
|
||||
}
|
||||
fd = -1;
|
||||
error_report("failed connect to %s:%s", addr, port);
|
||||
error_report("failed connect to %s:%s\n", addr, port);
|
||||
success:
|
||||
freeaddrinfo(res0);
|
||||
return fd;
|
||||
@@ -638,7 +643,7 @@ again:
|
||||
if (errno == EINTR || errno == EAGAIN) {
|
||||
goto again;
|
||||
}
|
||||
error_report("failed to recv a rsp, %s", strerror(errno));
|
||||
error_report("failed to recv a rsp, %s\n", strerror(errno));
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -697,7 +702,7 @@ static int send_req(int sockfd, SheepdogReq *hdr, void *data,
|
||||
|
||||
ret = do_writev(sockfd, iov, sizeof(*hdr) + *wlen, 0);
|
||||
if (ret) {
|
||||
error_report("failed to send a req, %s", strerror(errno));
|
||||
error_report("failed to send a req, %s\n", strerror(errno));
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
@@ -717,7 +722,7 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data,
|
||||
|
||||
ret = do_read(sockfd, hdr, sizeof(*hdr));
|
||||
if (ret) {
|
||||
error_report("failed to get a rsp, %s", strerror(errno));
|
||||
error_report("failed to get a rsp, %s\n", strerror(errno));
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
@@ -729,7 +734,7 @@ static int do_req(int sockfd, SheepdogReq *hdr, void *data,
|
||||
if (*rlen) {
|
||||
ret = do_read(sockfd, data, *rlen);
|
||||
if (ret) {
|
||||
error_report("failed to get the data, %s", strerror(errno));
|
||||
error_report("failed to get the data, %s\n", strerror(errno));
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
@@ -766,7 +771,7 @@ static void send_pending_req(BDRVSheepdogState *s, uint64_t oid, uint32_t id)
|
||||
ret = add_aio_request(s, aio_req, acb->qiov->iov,
|
||||
acb->qiov->niov, 0, acb->aiocb_type);
|
||||
if (ret < 0) {
|
||||
error_report("add_aio_request is failed");
|
||||
error_report("add_aio_request is failed\n");
|
||||
free_aio_req(s, aio_req);
|
||||
if (QLIST_EMPTY(&acb->aioreq_head)) {
|
||||
sd_finish_aiocb(acb);
|
||||
@@ -799,7 +804,7 @@ static void aio_read_response(void *opaque)
|
||||
/* read a header */
|
||||
ret = do_read(fd, &rsp, sizeof(rsp));
|
||||
if (ret) {
|
||||
error_report("failed to get the header, %s", strerror(errno));
|
||||
error_report("failed to get the header, %s\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -810,7 +815,7 @@ static void aio_read_response(void *opaque)
|
||||
}
|
||||
}
|
||||
if (!aio_req) {
|
||||
error_report("cannot find aio_req %x", rsp.id);
|
||||
error_report("cannot find aio_req %x\n", rsp.id);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -846,7 +851,7 @@ static void aio_read_response(void *opaque)
|
||||
ret = do_readv(fd, acb->qiov->iov, rsp.data_length,
|
||||
aio_req->iov_offset);
|
||||
if (ret) {
|
||||
error_report("failed to get the data, %s", strerror(errno));
|
||||
error_report("failed to get the data, %s\n", strerror(errno));
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -854,7 +859,7 @@ static void aio_read_response(void *opaque)
|
||||
|
||||
if (rsp.result != SD_RES_SUCCESS) {
|
||||
acb->ret = -EIO;
|
||||
error_report("%s", sd_strerror(rsp.result));
|
||||
error_report("%s\n", sd_strerror(rsp.result));
|
||||
}
|
||||
|
||||
rest = free_aio_req(s, aio_req);
|
||||
@@ -911,7 +916,7 @@ static int get_sheep_fd(BDRVSheepdogState *s)
|
||||
|
||||
fd = connect_to_sdog(s->addr, s->port);
|
||||
if (fd < 0) {
|
||||
error_report("%s", strerror(errno));
|
||||
error_report("%s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -919,7 +924,7 @@ static int get_sheep_fd(BDRVSheepdogState *s)
|
||||
|
||||
ret = set_nodelay(fd);
|
||||
if (ret) {
|
||||
error_report("%s", strerror(errno));
|
||||
error_report("%s\n", strerror(errno));
|
||||
closesocket(fd);
|
||||
return -1;
|
||||
}
|
||||
@@ -1035,7 +1040,7 @@ static int find_vdi_name(BDRVSheepdogState *s, char *filename, uint32_t snapid,
|
||||
}
|
||||
|
||||
if (rsp->result != SD_RES_SUCCESS) {
|
||||
error_report("cannot get vdi info, %s, %s %d %s",
|
||||
error_report("cannot get vdi info, %s, %s %d %s\n",
|
||||
sd_strerror(rsp->result), filename, snapid, tag);
|
||||
ret = -1;
|
||||
goto out;
|
||||
@@ -1063,7 +1068,7 @@ static int add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
|
||||
uint64_t old_oid = aio_req->base_oid;
|
||||
|
||||
if (!nr_copies) {
|
||||
error_report("bug");
|
||||
error_report("bug\n");
|
||||
}
|
||||
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
@@ -1096,14 +1101,14 @@ static int add_aio_request(BDRVSheepdogState *s, AIOReq *aio_req,
|
||||
/* send a header */
|
||||
ret = do_write(s->fd, &hdr, sizeof(hdr));
|
||||
if (ret) {
|
||||
error_report("failed to send a req, %s", strerror(errno));
|
||||
error_report("failed to send a req, %s\n", strerror(errno));
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (wlen) {
|
||||
ret = do_writev(s->fd, iov, wlen, aio_req->iov_offset);
|
||||
if (ret) {
|
||||
error_report("failed to send a data, %s", strerror(errno));
|
||||
error_report("failed to send a data, %s\n", strerror(errno));
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
@@ -1145,7 +1150,7 @@ static int read_write_object(int fd, char *buf, uint64_t oid, int copies,
|
||||
|
||||
ret = do_req(fd, (SheepdogReq *)&hdr, buf, &wlen, &rlen);
|
||||
if (ret) {
|
||||
error_report("failed to send a request to the sheep");
|
||||
error_report("failed to send a request to the sheep\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -1153,7 +1158,7 @@ static int read_write_object(int fd, char *buf, uint64_t oid, int copies,
|
||||
case SD_RES_SUCCESS:
|
||||
return 0;
|
||||
default:
|
||||
error_report("%s", sd_strerror(rsp->result));
|
||||
error_report("%s\n", sd_strerror(rsp->result));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -1206,7 +1211,7 @@ static int sd_open(BlockDriverState *bs, const char *filename, int flags)
|
||||
|
||||
fd = connect_to_sdog(s->addr, s->port);
|
||||
if (fd < 0) {
|
||||
error_report("failed to connect");
|
||||
error_report("failed to connect\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1275,7 +1280,7 @@ static int do_sd_create(char *filename, int64_t vdi_size,
|
||||
}
|
||||
|
||||
if (rsp->result != SD_RES_SUCCESS) {
|
||||
error_report("%s, %s", sd_strerror(rsp->result), filename);
|
||||
error_report("%s, %s\n", sd_strerror(rsp->result), filename);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -1286,49 +1291,6 @@ static int do_sd_create(char *filename, int64_t vdi_size,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sd_prealloc(const char *filename)
|
||||
{
|
||||
BlockDriverState *bs = NULL;
|
||||
uint32_t idx, max_idx;
|
||||
int64_t vdi_size;
|
||||
void *buf = qemu_mallocz(SD_DATA_OBJ_SIZE);
|
||||
int ret;
|
||||
|
||||
ret = bdrv_file_open(&bs, filename, BDRV_O_RDWR);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
vdi_size = bdrv_getlength(bs);
|
||||
if (vdi_size < 0) {
|
||||
ret = vdi_size;
|
||||
goto out;
|
||||
}
|
||||
max_idx = DIV_ROUND_UP(vdi_size, SD_DATA_OBJ_SIZE);
|
||||
|
||||
for (idx = 0; idx < max_idx; idx++) {
|
||||
/*
|
||||
* The created image can be a cloned image, so we need to read
|
||||
* a data from the source image.
|
||||
*/
|
||||
ret = bdrv_pread(bs, idx * SD_DATA_OBJ_SIZE, buf, SD_DATA_OBJ_SIZE);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
ret = bdrv_pwrite(bs, idx * SD_DATA_OBJ_SIZE, buf, SD_DATA_OBJ_SIZE);
|
||||
if (ret < 0) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
out:
|
||||
if (bs) {
|
||||
bdrv_delete(bs);
|
||||
}
|
||||
qemu_free(buf);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sd_create(const char *filename, QEMUOptionParameter *options)
|
||||
{
|
||||
int ret;
|
||||
@@ -1338,16 +1300,14 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
|
||||
BDRVSheepdogState s;
|
||||
char vdi[SD_MAX_VDI_LEN], tag[SD_MAX_VDI_TAG_LEN];
|
||||
uint32_t snapid;
|
||||
int prealloc = 0;
|
||||
const char *vdiname;
|
||||
|
||||
strstart(filename, "sheepdog:", &vdiname);
|
||||
strstart(filename, "sheepdog:", (const char **)&filename);
|
||||
|
||||
memset(&s, 0, sizeof(s));
|
||||
memset(vdi, 0, sizeof(vdi));
|
||||
memset(tag, 0, sizeof(tag));
|
||||
if (parse_vdiname(&s, vdiname, vdi, &snapid, tag) < 0) {
|
||||
error_report("invalid filename");
|
||||
if (parse_vdiname(&s, filename, vdi, &snapid, tag) < 0) {
|
||||
error_report("invalid filename\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -1356,22 +1316,12 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
|
||||
vdi_size = options->value.n;
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_BACKING_FILE)) {
|
||||
backing_file = options->value.s;
|
||||
} else if (!strcmp(options->name, BLOCK_OPT_PREALLOC)) {
|
||||
if (!options->value.s || !strcmp(options->value.s, "off")) {
|
||||
prealloc = 0;
|
||||
} else if (!strcmp(options->value.s, "full")) {
|
||||
prealloc = 1;
|
||||
} else {
|
||||
error_report("Invalid preallocation mode: '%s'",
|
||||
options->value.s);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
options++;
|
||||
}
|
||||
|
||||
if (vdi_size > SD_MAX_VDI_SIZE) {
|
||||
error_report("too big image size");
|
||||
error_report("too big image size\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -1383,7 +1333,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
|
||||
/* Currently, only Sheepdog backing image is supported. */
|
||||
drv = bdrv_find_protocol(backing_file);
|
||||
if (!drv || strcmp(drv->protocol_name, "sheepdog") != 0) {
|
||||
error_report("backing_file must be a sheepdog image");
|
||||
error_report("backing_file must be a sheepdog image\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -1394,7 +1344,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
|
||||
s = bs->opaque;
|
||||
|
||||
if (!is_snapshot(&s->inode)) {
|
||||
error_report("cannot clone from a non snapshot vdi");
|
||||
error_report("cannot clone from a non snapshot vdi\n");
|
||||
bdrv_delete(bs);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1403,12 +1353,7 @@ static int sd_create(const char *filename, QEMUOptionParameter *options)
|
||||
bdrv_delete(bs);
|
||||
}
|
||||
|
||||
ret = do_sd_create(vdi, vdi_size, base_vid, &vid, 0, s.addr, s.port);
|
||||
if (!prealloc || ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return sd_prealloc(filename);
|
||||
return do_sd_create((char *)vdi, vdi_size, base_vid, &vid, 0, s.addr, s.port);
|
||||
}
|
||||
|
||||
static void sd_close(BlockDriverState *bs)
|
||||
@@ -1439,7 +1384,7 @@ static void sd_close(BlockDriverState *bs)
|
||||
|
||||
if (!ret && rsp->result != SD_RES_SUCCESS &&
|
||||
rsp->result != SD_RES_VDI_NOT_LOCKED) {
|
||||
error_report("%s, %s", sd_strerror(rsp->result), s->name);
|
||||
error_report("%s, %s\n", sd_strerror(rsp->result), s->name);
|
||||
}
|
||||
|
||||
qemu_aio_set_fd_handler(s->fd, NULL, NULL, NULL, NULL, NULL);
|
||||
@@ -1461,10 +1406,10 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
|
||||
unsigned int datalen;
|
||||
|
||||
if (offset < s->inode.vdi_size) {
|
||||
error_report("shrinking is not supported");
|
||||
error_report("shrinking is not supported\n");
|
||||
return -EINVAL;
|
||||
} else if (offset > SD_MAX_VDI_SIZE) {
|
||||
error_report("too big image size");
|
||||
error_report("too big image size\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -1481,7 +1426,7 @@ static int sd_truncate(BlockDriverState *bs, int64_t offset)
|
||||
close(fd);
|
||||
|
||||
if (ret < 0) {
|
||||
error_report("failed to update an inode.");
|
||||
error_report("failed to update an inode.\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
@@ -1554,7 +1499,7 @@ static int sd_create_branch(BDRVSheepdogState *s)
|
||||
|
||||
fd = connect_to_sdog(s->addr, s->port);
|
||||
if (fd < 0) {
|
||||
error_report("failed to connect");
|
||||
error_report("failed to connect\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1631,7 +1576,7 @@ static void sd_readv_writev_bh_cb(void *p)
|
||||
|
||||
create = 1;
|
||||
} else if (acb->aiocb_type == AIOCB_WRITE_UDATA
|
||||
&& !is_data_obj_writable(inode, idx)) {
|
||||
&& !is_data_obj_writeable(inode, idx)) {
|
||||
/* Copy-On-Write */
|
||||
create = 1;
|
||||
old_oid = oid;
|
||||
@@ -1672,7 +1617,7 @@ static void sd_readv_writev_bh_cb(void *p)
|
||||
ret = add_aio_request(s, aio_req, acb->qiov->iov, acb->qiov->niov,
|
||||
create, acb->aiocb_type);
|
||||
if (ret < 0) {
|
||||
error_report("add_aio_request is failed");
|
||||
error_report("add_aio_request is failed\n");
|
||||
free_aio_req(s, aio_req);
|
||||
acb->ret = -EIO;
|
||||
goto out;
|
||||
@@ -1749,7 +1694,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
|
||||
|
||||
if (s->is_snapshot) {
|
||||
error_report("You can't create a snapshot of a snapshot VDI, "
|
||||
"%s (%" PRIu32 ").", s->name, s->inode.vdi_id);
|
||||
"%s (%" PRIu32 ").\n", s->name, s->inode.vdi_id);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1772,7 +1717,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
|
||||
ret = write_object(fd, (char *)&s->inode, vid_to_vdi_oid(s->inode.vdi_id),
|
||||
s->inode.nr_copies, datalen, 0, 0);
|
||||
if (ret < 0) {
|
||||
error_report("failed to write snapshot's inode.");
|
||||
error_report("failed to write snapshot's inode.\n");
|
||||
ret = -EIO;
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -1780,7 +1725,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
|
||||
ret = do_sd_create(s->name, s->inode.vdi_size, s->inode.vdi_id, &new_vid, 1,
|
||||
s->addr, s->port);
|
||||
if (ret < 0) {
|
||||
error_report("failed to create inode for snapshot. %s",
|
||||
error_report("failed to create inode for snapshot. %s\n",
|
||||
strerror(errno));
|
||||
ret = -EIO;
|
||||
goto cleanup;
|
||||
@@ -1792,7 +1737,7 @@ static int sd_snapshot_create(BlockDriverState *bs, QEMUSnapshotInfo *sn_info)
|
||||
s->inode.nr_copies, datalen, 0);
|
||||
|
||||
if (ret < 0) {
|
||||
error_report("failed to read new inode info. %s", strerror(errno));
|
||||
error_report("failed to read new inode info. %s\n", strerror(errno));
|
||||
ret = -EIO;
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -1831,14 +1776,14 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
|
||||
|
||||
ret = find_vdi_name(s, vdi, snapid, tag, &vid, 1);
|
||||
if (ret) {
|
||||
error_report("Failed to find_vdi_name");
|
||||
error_report("Failed to find_vdi_name\n");
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
fd = connect_to_sdog(s->addr, s->port);
|
||||
if (fd < 0) {
|
||||
error_report("failed to connect");
|
||||
error_report("failed to connect\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -1856,7 +1801,7 @@ static int sd_snapshot_goto(BlockDriverState *bs, const char *snapshot_id)
|
||||
memcpy(&s->inode, buf, sizeof(s->inode));
|
||||
|
||||
if (!s->inode.vm_state_size) {
|
||||
error_report("Invalid snapshot");
|
||||
error_report("Invalid snapshot\n");
|
||||
ret = -ENOENT;
|
||||
goto out;
|
||||
}
|
||||
@@ -1873,7 +1818,7 @@ out:
|
||||
qemu_free(buf);
|
||||
qemu_free(old_s);
|
||||
|
||||
error_report("failed to open. recover old bdrv_sd_state.");
|
||||
error_report("failed to open. recover old bdrv_sd_state.\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1884,6 +1829,20 @@ static int sd_snapshot_delete(BlockDriverState *bs, const char *snapshot_id)
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
|
||||
#define BITS_PER_BYTE 8
|
||||
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
|
||||
#define DECLARE_BITMAP(name,bits) \
|
||||
unsigned long name[BITS_TO_LONGS(bits)]
|
||||
|
||||
#define BITS_PER_LONG (BITS_PER_BYTE * sizeof(long))
|
||||
|
||||
static inline int test_bit(unsigned int nr, const unsigned long *addr)
|
||||
{
|
||||
return ((1UL << (nr % BITS_PER_LONG)) &
|
||||
(((unsigned long *)addr)[nr / BITS_PER_LONG])) != 0;
|
||||
}
|
||||
|
||||
static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
|
||||
{
|
||||
BDRVSheepdogState *s = bs->opaque;
|
||||
@@ -1928,7 +1887,7 @@ static int sd_snapshot_list(BlockDriverState *bs, QEMUSnapshotInfo **psn_tab)
|
||||
|
||||
fd = connect_to_sdog(s->addr, s->port);
|
||||
if (fd < 0) {
|
||||
error_report("failed to connect");
|
||||
error_report("failed to connect\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -2002,7 +1961,7 @@ static int do_load_save_vmstate(BDRVSheepdogState *s, uint8_t *data,
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
error_report("failed to save vmstate %s", strerror(errno));
|
||||
error_report("failed to save vmstate %s\n", strerror(errno));
|
||||
ret = -EIO;
|
||||
goto cleanup;
|
||||
}
|
||||
@@ -2044,11 +2003,6 @@ static QEMUOptionParameter sd_create_options[] = {
|
||||
.type = OPT_STRING,
|
||||
.help = "File name of a base image"
|
||||
},
|
||||
{
|
||||
.name = BLOCK_OPT_PREALLOC,
|
||||
.type = OPT_STRING,
|
||||
.help = "Preallocation mode (allowed values: off, full)"
|
||||
},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
|
56
block/vdi.c
56
block/vdi.c
@@ -87,7 +87,6 @@ void uuid_unparse(const uuid_t uu, char *out);
|
||||
#define MiB (KiB * KiB)
|
||||
|
||||
#define SECTOR_SIZE 512
|
||||
#define DEFAULT_CLUSTER_SIZE (1 * MiB)
|
||||
|
||||
#if defined(CONFIG_VDI_DEBUG)
|
||||
#define logout(fmt, ...) \
|
||||
@@ -114,7 +113,7 @@ void uuid_unparse(const uuid_t uu, char *out);
|
||||
*/
|
||||
#define VDI_TEXT "<<< QEMU VM Virtual Disk Image >>>\n"
|
||||
|
||||
/* Unallocated blocks use this index (no need to convert endianness). */
|
||||
/* Unallocated blocks use this index (no need to convert endianess). */
|
||||
#define VDI_UNALLOCATED UINT32_MAX
|
||||
|
||||
#if !defined(CONFIG_UUID)
|
||||
@@ -152,7 +151,6 @@ typedef struct {
|
||||
/* Buffer for new allocated block. */
|
||||
void *block_buffer;
|
||||
void *orig_buf;
|
||||
bool is_write;
|
||||
int header_modified;
|
||||
BlockDriverAIOCB *hd_aiocb;
|
||||
struct iovec hd_iov;
|
||||
@@ -196,7 +194,7 @@ typedef struct {
|
||||
uint32_t block_sectors;
|
||||
/* First sector of block map. */
|
||||
uint32_t bmap_sector;
|
||||
/* VDI header (converted to host endianness). */
|
||||
/* VDI header (converted to host endianess). */
|
||||
VdiHeader header;
|
||||
} BDRVVdiState;
|
||||
|
||||
@@ -505,8 +503,6 @@ static VdiAIOCB *vdi_aio_setup(BlockDriverState *bs, int64_t sector_num,
|
||||
acb->hd_aiocb = NULL;
|
||||
acb->sector_num = sector_num;
|
||||
acb->qiov = qiov;
|
||||
acb->is_write = is_write;
|
||||
|
||||
if (qiov->niov > 1) {
|
||||
acb->buf = qemu_blockalign(bs, qiov->size);
|
||||
acb->orig_buf = acb->buf;
|
||||
@@ -545,20 +541,14 @@ static int vdi_schedule_bh(QEMUBHFunc *cb, VdiAIOCB *acb)
|
||||
}
|
||||
|
||||
static void vdi_aio_read_cb(void *opaque, int ret);
|
||||
static void vdi_aio_write_cb(void *opaque, int ret);
|
||||
|
||||
static void vdi_aio_rw_bh(void *opaque)
|
||||
static void vdi_aio_read_bh(void *opaque)
|
||||
{
|
||||
VdiAIOCB *acb = opaque;
|
||||
logout("\n");
|
||||
qemu_bh_delete(acb->bh);
|
||||
acb->bh = NULL;
|
||||
|
||||
if (acb->is_write) {
|
||||
vdi_aio_write_cb(opaque, 0);
|
||||
} else {
|
||||
vdi_aio_read_cb(opaque, 0);
|
||||
}
|
||||
vdi_aio_read_cb(opaque, 0);
|
||||
}
|
||||
|
||||
static void vdi_aio_read_cb(void *opaque, int ret)
|
||||
@@ -606,7 +596,7 @@ static void vdi_aio_read_cb(void *opaque, int ret)
|
||||
if (bmap_entry == VDI_UNALLOCATED) {
|
||||
/* Block not allocated, return zeros, no need to wait. */
|
||||
memset(acb->buf, 0, n_sectors * SECTOR_SIZE);
|
||||
ret = vdi_schedule_bh(vdi_aio_rw_bh, acb);
|
||||
ret = vdi_schedule_bh(vdi_aio_read_bh, acb);
|
||||
if (ret < 0) {
|
||||
goto done;
|
||||
}
|
||||
@@ -620,7 +610,6 @@ static void vdi_aio_read_cb(void *opaque, int ret)
|
||||
acb->hd_aiocb = bdrv_aio_readv(bs->file, offset, &acb->hd_qiov,
|
||||
n_sectors, vdi_aio_read_cb, acb);
|
||||
if (acb->hd_aiocb == NULL) {
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
@@ -639,23 +628,12 @@ static BlockDriverAIOCB *vdi_aio_readv(BlockDriverState *bs,
|
||||
BlockDriverCompletionFunc *cb, void *opaque)
|
||||
{
|
||||
VdiAIOCB *acb;
|
||||
int ret;
|
||||
|
||||
logout("\n");
|
||||
acb = vdi_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 0);
|
||||
if (!acb) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = vdi_schedule_bh(vdi_aio_rw_bh, acb);
|
||||
if (ret < 0) {
|
||||
if (acb->qiov->niov > 1) {
|
||||
qemu_vfree(acb->orig_buf);
|
||||
}
|
||||
qemu_aio_release(acb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vdi_aio_read_cb(acb, 0);
|
||||
return &acb->common;
|
||||
}
|
||||
|
||||
@@ -695,7 +673,6 @@ static void vdi_aio_write_cb(void *opaque, int ret)
|
||||
acb->hd_aiocb = bdrv_aio_writev(bs->file, 0, &acb->hd_qiov, 1,
|
||||
vdi_aio_write_cb, acb);
|
||||
if (acb->hd_aiocb == NULL) {
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
return;
|
||||
@@ -725,7 +702,6 @@ static void vdi_aio_write_cb(void *opaque, int ret)
|
||||
acb->hd_aiocb = bdrv_aio_writev(bs->file, offset, &acb->hd_qiov,
|
||||
n_sectors, vdi_aio_write_cb, acb);
|
||||
if (acb->hd_aiocb == NULL) {
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
return;
|
||||
@@ -776,7 +752,6 @@ static void vdi_aio_write_cb(void *opaque, int ret)
|
||||
&acb->hd_qiov, s->block_sectors,
|
||||
vdi_aio_write_cb, acb);
|
||||
if (acb->hd_aiocb == NULL) {
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
@@ -789,7 +764,6 @@ static void vdi_aio_write_cb(void *opaque, int ret)
|
||||
acb->hd_aiocb = bdrv_aio_writev(bs->file, offset, &acb->hd_qiov,
|
||||
n_sectors, vdi_aio_write_cb, acb);
|
||||
if (acb->hd_aiocb == NULL) {
|
||||
ret = -EIO;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
@@ -809,23 +783,12 @@ static BlockDriverAIOCB *vdi_aio_writev(BlockDriverState *bs,
|
||||
BlockDriverCompletionFunc *cb, void *opaque)
|
||||
{
|
||||
VdiAIOCB *acb;
|
||||
int ret;
|
||||
|
||||
logout("\n");
|
||||
acb = vdi_aio_setup(bs, sector_num, qiov, nb_sectors, cb, opaque, 1);
|
||||
if (!acb) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = vdi_schedule_bh(vdi_aio_rw_bh, acb);
|
||||
if (ret < 0) {
|
||||
if (acb->qiov->niov > 1) {
|
||||
qemu_vfree(acb->orig_buf);
|
||||
}
|
||||
qemu_aio_release(acb);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vdi_aio_write_cb(acb, 0);
|
||||
return &acb->common;
|
||||
}
|
||||
|
||||
@@ -835,7 +798,7 @@ static int vdi_create(const char *filename, QEMUOptionParameter *options)
|
||||
int result = 0;
|
||||
uint64_t bytes = 0;
|
||||
uint32_t blocks;
|
||||
size_t block_size = DEFAULT_CLUSTER_SIZE;
|
||||
size_t block_size = 1 * MiB;
|
||||
uint32_t image_type = VDI_TYPE_DYNAMIC;
|
||||
VdiHeader header;
|
||||
size_t i;
|
||||
@@ -953,8 +916,7 @@ static QEMUOptionParameter vdi_create_options[] = {
|
||||
{
|
||||
.name = BLOCK_OPT_CLUSTER_SIZE,
|
||||
.type = OPT_SIZE,
|
||||
.help = "VDI cluster (block) size",
|
||||
.value = { .n = DEFAULT_CLUSTER_SIZE },
|
||||
.help = "VDI cluster (block) size"
|
||||
},
|
||||
#endif
|
||||
#if defined(CONFIG_VDI_STATIC_IMAGE)
|
||||
|
1367
block/vmdk.c
1367
block/vmdk.c
File diff suppressed because it is too large
Load Diff
@@ -505,8 +505,12 @@ static int vpc_create(const char *filename, QEMUOptionParameter *options)
|
||||
int ret = -EIO;
|
||||
|
||||
// Read out options
|
||||
total_sectors = get_option_parameter(options, BLOCK_OPT_SIZE)->value.n /
|
||||
BDRV_SECTOR_SIZE;
|
||||
while (options && options->name) {
|
||||
if (!strcmp(options->name, "size")) {
|
||||
total_sectors = options->value.n / 512;
|
||||
}
|
||||
options++;
|
||||
}
|
||||
|
||||
// Create the file
|
||||
fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, 0644);
|
||||
|
@@ -39,7 +39,6 @@
|
||||
#define BLOCK_OPT_CLUSTER_SIZE "cluster_size"
|
||||
#define BLOCK_OPT_TABLE_SIZE "table_size"
|
||||
#define BLOCK_OPT_PREALLOC "preallocation"
|
||||
#define BLOCK_OPT_SUBFMT "subformat"
|
||||
|
||||
typedef struct AIOPool {
|
||||
void (*cancel)(BlockDriverAIOCB *acb);
|
||||
@@ -86,7 +85,6 @@ struct BlockDriver {
|
||||
const char *protocol_name;
|
||||
int (*bdrv_truncate)(BlockDriverState *bs, int64_t offset);
|
||||
int64_t (*bdrv_getlength)(BlockDriverState *bs);
|
||||
int64_t (*bdrv_get_allocated_file_size)(BlockDriverState *bs);
|
||||
int (*bdrv_write_compressed)(BlockDriverState *bs, int64_t sector_num,
|
||||
const uint8_t *buf, int nb_sectors);
|
||||
|
||||
@@ -196,6 +194,7 @@ struct BlockDriverState {
|
||||
/* NOTE: the following infos are only hints for real hardware
|
||||
drivers. They are not used by the block driver */
|
||||
int cyls, heads, secs, translation;
|
||||
int type;
|
||||
BlockErrorAction on_read_error, on_write_error;
|
||||
char device_name[32];
|
||||
unsigned long *dirty_bitmap;
|
||||
@@ -205,8 +204,8 @@ struct BlockDriverState {
|
||||
void *private;
|
||||
};
|
||||
|
||||
#define CHANGE_MEDIA 0x01
|
||||
#define CHANGE_SIZE 0x02
|
||||
#define CHANGE_MEDIA 0x01
|
||||
#define CHANGE_SIZE 0x02
|
||||
|
||||
struct BlockDriverAIOCB {
|
||||
AIOPool *pool;
|
||||
|
65
blockdev.c
65
blockdev.c
@@ -17,8 +17,6 @@
|
||||
#include "hw/qdev.h"
|
||||
#include "block_int.h"
|
||||
|
||||
DriveInfo *extboot_drive = NULL;
|
||||
|
||||
static QTAILQ_HEAD(drivelist, DriveInfo) drives = QTAILQ_HEAD_INITIALIZER(drives);
|
||||
|
||||
static const char *const if_name[IF_COUNT] = {
|
||||
@@ -238,11 +236,18 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
|
||||
int on_read_error, on_write_error;
|
||||
const char *devaddr;
|
||||
DriveInfo *dinfo;
|
||||
int is_extboot = 0;
|
||||
int snapshot = 0;
|
||||
int ret;
|
||||
|
||||
translation = BIOS_ATA_TRANSLATION_AUTO;
|
||||
|
||||
if (default_to_scsi) {
|
||||
type = IF_SCSI;
|
||||
pstrcpy(devname, sizeof(devname), "scsi");
|
||||
} else {
|
||||
type = IF_IDE;
|
||||
pstrcpy(devname, sizeof(devname), "ide");
|
||||
}
|
||||
media = MEDIA_DISK;
|
||||
|
||||
/* extract parameters */
|
||||
@@ -268,11 +273,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
|
||||
error_report("unsupported bus type '%s'", buf);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
type = default_to_scsi ? IF_SCSI : IF_IDE;
|
||||
pstrcpy(devname, sizeof(devname), if_name[type]);
|
||||
}
|
||||
|
||||
max_devs = if_max_devs[type];
|
||||
|
||||
if (cyls || heads || secs) {
|
||||
@@ -292,7 +293,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
|
||||
|
||||
if ((buf = qemu_opt_get(opts, "trans")) != NULL) {
|
||||
if (!cyls) {
|
||||
error_report("'%s' trans must be used with cyls, heads and secs",
|
||||
error_report("'%s' trans must be used with cyls,heads and secs",
|
||||
buf);
|
||||
return NULL;
|
||||
}
|
||||
@@ -313,7 +314,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
|
||||
media = MEDIA_DISK;
|
||||
} else if (!strcmp(buf, "cdrom")) {
|
||||
if (cyls || secs || heads) {
|
||||
error_report("CHS can't be set with media=%s", buf);
|
||||
error_report("'%s' invalid physical CHS format", buf);
|
||||
return NULL;
|
||||
}
|
||||
media = MEDIA_CDROM;
|
||||
@@ -325,7 +326,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
|
||||
|
||||
if ((buf = qemu_opt_get(opts, "cache")) != NULL) {
|
||||
if (!strcmp(buf, "off") || !strcmp(buf, "none")) {
|
||||
bdrv_flags |= BDRV_O_NOCACHE | BDRV_O_CACHE_WB;
|
||||
bdrv_flags |= BDRV_O_NOCACHE;
|
||||
} else if (!strcmp(buf, "writeback")) {
|
||||
bdrv_flags |= BDRV_O_CACHE_WB;
|
||||
} else if (!strcmp(buf, "unsafe")) {
|
||||
@@ -366,12 +367,6 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
|
||||
}
|
||||
}
|
||||
|
||||
is_extboot = qemu_opt_get_bool(opts, "boot", 0);
|
||||
if (is_extboot && extboot_drive) {
|
||||
fprintf(stderr, "qemu: two bootable drives specified\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
on_write_error = BLOCK_ERR_STOP_ENOSPC;
|
||||
if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
|
||||
if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
|
||||
@@ -477,10 +472,6 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
|
||||
strncpy(dinfo->serial, serial, sizeof(dinfo->serial) - 1);
|
||||
QTAILQ_INSERT_TAIL(&drives, dinfo, next);
|
||||
|
||||
if (is_extboot) {
|
||||
extboot_drive = dinfo;
|
||||
}
|
||||
|
||||
bdrv_set_on_error(dinfo->bdrv, on_read_error, on_write_error);
|
||||
|
||||
switch(type) {
|
||||
@@ -496,8 +487,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
|
||||
}
|
||||
break;
|
||||
case MEDIA_CDROM:
|
||||
bdrv_set_removable(dinfo->bdrv, 1);
|
||||
dinfo->media_cd = 1;
|
||||
bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_CDROM);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -505,7 +495,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
|
||||
/* FIXME: This isn't really a floppy, but it's a reasonable
|
||||
approximation. */
|
||||
case IF_FLOPPY:
|
||||
bdrv_set_removable(dinfo->bdrv, 1);
|
||||
bdrv_set_type_hint(dinfo->bdrv, BDRV_TYPE_FLOPPY);
|
||||
break;
|
||||
case IF_PFLASH:
|
||||
case IF_MTD:
|
||||
@@ -513,7 +503,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
|
||||
case IF_VIRTIO:
|
||||
/* add virtio block device */
|
||||
opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
|
||||
qemu_opt_set(opts, "driver", "virtio-blk");
|
||||
qemu_opt_set(opts, "driver", "virtio-blk-pci");
|
||||
qemu_opt_set(opts, "drive", dinfo->id);
|
||||
if (devaddr)
|
||||
qemu_opt_set(opts, "addr", devaddr);
|
||||
@@ -581,16 +571,15 @@ void do_commit(Monitor *mon, const QDict *qdict)
|
||||
int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||
{
|
||||
const char *device = qdict_get_str(qdict, "device");
|
||||
const char *filename = qdict_get_try_str(qdict, "snapshot-file");
|
||||
const char *filename = qdict_get_try_str(qdict, "snapshot_file");
|
||||
const char *format = qdict_get_try_str(qdict, "format");
|
||||
BlockDriverState *bs;
|
||||
BlockDriver *drv, *old_drv, *proto_drv;
|
||||
BlockDriver *drv, *proto_drv;
|
||||
int ret = 0;
|
||||
int flags;
|
||||
char old_filename[1024];
|
||||
|
||||
if (!filename) {
|
||||
qerror_report(QERR_MISSING_PARAMETER, "snapshot-file");
|
||||
qerror_report(QERR_MISSING_PARAMETER, "snapshot_file");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
@@ -602,11 +591,6 @@ int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||
goto out;
|
||||
}
|
||||
|
||||
pstrcpy(old_filename, sizeof(old_filename), bs->filename);
|
||||
|
||||
old_drv = bs->drv;
|
||||
flags = bs->open_flags;
|
||||
|
||||
if (!format) {
|
||||
format = "qcow2";
|
||||
}
|
||||
@@ -626,7 +610,7 @@ int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||
}
|
||||
|
||||
ret = bdrv_img_create(filename, format, bs->filename,
|
||||
bs->drv->format_name, NULL, -1, flags);
|
||||
bs->drv->format_name, NULL, -1, bs->open_flags);
|
||||
if (ret) {
|
||||
goto out;
|
||||
}
|
||||
@@ -634,20 +618,15 @@ int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||
qemu_aio_flush();
|
||||
bdrv_flush(bs);
|
||||
|
||||
flags = bs->open_flags;
|
||||
bdrv_close(bs);
|
||||
ret = bdrv_open(bs, filename, flags, drv);
|
||||
/*
|
||||
* If reopening the image file we just created fails, fall back
|
||||
* and try to re-open the original image. If that fails too, we
|
||||
* are in serious trouble.
|
||||
* If reopening the image file we just created fails, we really
|
||||
* are in trouble :(
|
||||
*/
|
||||
if (ret != 0) {
|
||||
ret = bdrv_open(bs, old_filename, flags, old_drv);
|
||||
if (ret != 0) {
|
||||
qerror_report(QERR_OPEN_FILE_FAILED, old_filename);
|
||||
} else {
|
||||
qerror_report(QERR_OPEN_FILE_FAILED, filename);
|
||||
}
|
||||
abort();
|
||||
}
|
||||
out:
|
||||
if (ret) {
|
||||
|
@@ -33,7 +33,6 @@ struct DriveInfo {
|
||||
int bus;
|
||||
int unit;
|
||||
int auto_del; /* see blockdev_mark_auto_del() */
|
||||
int media_cd;
|
||||
QemuOpts *opts;
|
||||
char serial[BLOCK_SERIAL_STRLEN + 1];
|
||||
QTAILQ_ENTRY(DriveInfo) next;
|
||||
@@ -66,6 +65,4 @@ int do_drive_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
|
||||
int do_snapshot_blkdev(Monitor *mon, const QDict *qdict, QObject **ret_data);
|
||||
int do_block_resize(Monitor *mon, const QDict *qdict, QObject **ret_data);
|
||||
|
||||
extern DriveInfo *extboot_drive;
|
||||
|
||||
#endif
|
||||
|
@@ -29,7 +29,7 @@
|
||||
#include "qemu.h"
|
||||
#include "qemu-common.h"
|
||||
/* For tb_lock */
|
||||
#include "cpu.h"
|
||||
#include "exec-all.h"
|
||||
#include "tcg.h"
|
||||
#include "qemu-timer.h"
|
||||
#include "envlist.h"
|
||||
@@ -237,7 +237,7 @@ void cpu_loop(CPUX86State *env)
|
||||
break;
|
||||
#ifndef TARGET_ABI32
|
||||
case EXCP_SYSCALL:
|
||||
/* syscall from syscall instruction */
|
||||
/* syscall from syscall intruction */
|
||||
if (bsd_type == target_freebsd)
|
||||
env->regs[R_EAX] = do_freebsd_syscall(env,
|
||||
env->regs[R_EAX],
|
||||
@@ -690,8 +690,7 @@ static void usage(void)
|
||||
"-bsd type select emulated BSD type FreeBSD/NetBSD/OpenBSD (default)\n"
|
||||
"\n"
|
||||
"Debug options:\n"
|
||||
"-d options activate log (default logfile=%s)\n"
|
||||
"-D logfile override default logfile location\n"
|
||||
"-d options activate log (logfile=%s)\n"
|
||||
"-p pagesize set the host page size to 'pagesize'\n"
|
||||
"-singlestep always run in singlestep mode\n"
|
||||
"-strace log system calls\n"
|
||||
@@ -732,8 +731,6 @@ int main(int argc, char **argv)
|
||||
{
|
||||
const char *filename;
|
||||
const char *cpu_model;
|
||||
const char *log_file = DEBUG_LOGFILE;
|
||||
const char *log_mask = NULL;
|
||||
struct target_pt_regs regs1, *regs = ®s1;
|
||||
struct image_info info1, *info = &info1;
|
||||
TaskState ts1, *ts = &ts1;
|
||||
@@ -748,6 +745,9 @@ int main(int argc, char **argv)
|
||||
if (argc <= 1)
|
||||
usage();
|
||||
|
||||
/* init debug */
|
||||
cpu_set_log_filename(DEBUG_LOGFILE);
|
||||
|
||||
if ((envlist = envlist_create()) == NULL) {
|
||||
(void) fprintf(stderr, "Unable to allocate envlist\n");
|
||||
exit(1);
|
||||
@@ -775,15 +775,22 @@ int main(int argc, char **argv)
|
||||
if (!strcmp(r, "-")) {
|
||||
break;
|
||||
} else if (!strcmp(r, "d")) {
|
||||
if (optind >= argc) {
|
||||
int mask;
|
||||
const CPULogItem *item;
|
||||
|
||||
if (optind >= argc)
|
||||
break;
|
||||
|
||||
r = argv[optind++];
|
||||
mask = cpu_str_to_log_mask(r);
|
||||
if (!mask) {
|
||||
printf("Log items (comma separated):\n");
|
||||
for(item = cpu_log_items; item->mask != 0; item++) {
|
||||
printf("%-10s %s\n", item->name, item->help);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
log_mask = argv[optind++];
|
||||
} else if (!strcmp(r, "D")) {
|
||||
if (optind >= argc) {
|
||||
break;
|
||||
}
|
||||
log_file = argv[optind++];
|
||||
cpu_set_log(mask);
|
||||
} else if (!strcmp(r, "E")) {
|
||||
r = argv[optind++];
|
||||
if (envlist_setenv(envlist, r) != 0)
|
||||
@@ -856,27 +863,8 @@ int main(int argc, char **argv)
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
/* init debug */
|
||||
cpu_set_log_filename(log_file);
|
||||
if (log_mask) {
|
||||
int mask;
|
||||
const CPULogItem *item;
|
||||
|
||||
mask = cpu_str_to_log_mask(log_mask);
|
||||
if (!mask) {
|
||||
printf("Log items (comma separated):\n");
|
||||
for (item = cpu_log_items; item->mask != 0; item++) {
|
||||
printf("%-10s %s\n", item->name, item->help);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
cpu_set_log(mask);
|
||||
}
|
||||
|
||||
if (optind >= argc) {
|
||||
if (optind >= argc)
|
||||
usage();
|
||||
}
|
||||
filename = argv[optind];
|
||||
|
||||
/* Zero out regs */
|
||||
|
@@ -323,7 +323,7 @@ abi_long copy_from_user(void *hptr, abi_ulong gaddr, size_t len);
|
||||
abi_long copy_to_user(abi_ulong gaddr, void *hptr, size_t len);
|
||||
|
||||
/* Functions for accessing guest memory. The tget and tput functions
|
||||
read/write single values, byteswapping as necessary. The lock_user
|
||||
read/write single values, byteswapping as neccessary. The lock_user
|
||||
gets a pointer to a contiguous area of guest memory, but does not perform
|
||||
and byteswapping. lock_user may return either a pointer to the guest
|
||||
memory, or a temporary buffer. */
|
||||
|
@@ -31,6 +31,7 @@
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <signal.h>
|
||||
#include <utime.h>
|
||||
|
||||
#include "qemu.h"
|
||||
|
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "qemu-char.h"
|
||||
#include "sysemu.h"
|
||||
#include "net.h"
|
||||
#include "bt-host.h"
|
||||
|
||||
|
@@ -19,6 +19,7 @@
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "qemu-char.h"
|
||||
#include "sysemu.h"
|
||||
#include "net.h"
|
||||
#include "hw/bt.h"
|
||||
|
||||
|
@@ -14,6 +14,7 @@
|
||||
#include "qemu-common.h"
|
||||
#include "hw/hw.h"
|
||||
#include "qemu-timer.h"
|
||||
#include "sysemu.h"
|
||||
#include "qemu-char.h"
|
||||
#include "buffered_file.h"
|
||||
|
||||
@@ -237,7 +238,7 @@ static void buffered_rate_tick(void *opaque)
|
||||
return;
|
||||
}
|
||||
|
||||
qemu_mod_timer(s->timer, qemu_get_clock_ms(rt_clock) + 100);
|
||||
qemu_mod_timer(s->timer, qemu_get_clock(rt_clock) + 100);
|
||||
|
||||
if (s->freeze_output)
|
||||
return;
|
||||
@@ -273,9 +274,9 @@ QEMUFile *qemu_fopen_ops_buffered(void *opaque,
|
||||
buffered_set_rate_limit,
|
||||
buffered_get_rate_limit);
|
||||
|
||||
s->timer = qemu_new_timer_ms(rt_clock, buffered_rate_tick, s);
|
||||
s->timer = qemu_new_timer(rt_clock, buffered_rate_tick, s);
|
||||
|
||||
qemu_mod_timer(s->timer, qemu_get_clock_ms(rt_clock) + 100);
|
||||
qemu_mod_timer(s->timer, qemu_get_clock(rt_clock) + 100);
|
||||
|
||||
return s->file;
|
||||
}
|
||||
|
@@ -34,28 +34,7 @@ static inline void flush_icache_range(unsigned long start, unsigned long stop)
|
||||
asm volatile ("isync" : : : "memory");
|
||||
}
|
||||
|
||||
/*
|
||||
* Is this correct for PPC?
|
||||
*/
|
||||
static inline void dma_flush_range(unsigned long start, unsigned long stop)
|
||||
{
|
||||
}
|
||||
|
||||
#elif defined(__ia64__)
|
||||
static inline void flush_icache_range(unsigned long start, unsigned long stop)
|
||||
{
|
||||
while (start < stop) {
|
||||
asm volatile ("fc %0" :: "r"(start));
|
||||
start += 32;
|
||||
}
|
||||
asm volatile (";;sync.i;;srlz.i;;");
|
||||
}
|
||||
#define dma_flush_range(start, end) flush_icache_range(start, end)
|
||||
#define qemu_cache_utils_init(envp) do { (void) (envp); } while (0)
|
||||
#else
|
||||
static inline void dma_flush_range(unsigned long start, unsigned long stop)
|
||||
{
|
||||
}
|
||||
#define qemu_cache_utils_init(envp) do { (void) (envp); } while (0)
|
||||
#endif
|
||||
|
||||
|
@@ -267,9 +267,8 @@ static QString *read_line(FILE *file, char *key)
|
||||
{
|
||||
char value[128];
|
||||
|
||||
if (fscanf(file, "%127s%127s", key, value) == EOF) {
|
||||
if (fscanf(file, "%s%s", key, value) == EOF)
|
||||
return NULL;
|
||||
}
|
||||
remove_dots(key);
|
||||
return qstring_from_str(value);
|
||||
}
|
||||
|
@@ -33,8 +33,7 @@ START_TEST(escaped_string)
|
||||
{ "\"\\n\"", "\n" },
|
||||
{ "\"\\r\"", "\r" },
|
||||
{ "\"\\t\"", "\t" },
|
||||
{ "\"/\"", "/" },
|
||||
{ "\"\\/\"", "/", .skip = 1 },
|
||||
{ "\"\\/\"", "\\/" },
|
||||
{ "\"\\\\\"", "\\" },
|
||||
{ "\"\\\"\"", "\"" },
|
||||
{ "\"hello world \\\"embedded string\\\"\"",
|
||||
|
6
cmd.c
6
cmd.c
@@ -486,7 +486,7 @@ timestr(
|
||||
snprintf(ts, size, "%u:%02u.%02u",
|
||||
(unsigned int) MINUTES(tv->tv_sec),
|
||||
(unsigned int) SECONDS(tv->tv_sec),
|
||||
(unsigned int) (usec * 100));
|
||||
(unsigned int) usec * 100);
|
||||
return;
|
||||
}
|
||||
format |= VERBOSE_FIXED_TIME; /* fallback if hours needed */
|
||||
@@ -497,9 +497,9 @@ timestr(
|
||||
(unsigned int) HOURS(tv->tv_sec),
|
||||
(unsigned int) MINUTES(tv->tv_sec),
|
||||
(unsigned int) SECONDS(tv->tv_sec),
|
||||
(unsigned int) (usec * 100));
|
||||
(unsigned int) usec * 100);
|
||||
} else {
|
||||
snprintf(ts, size, "0.%04u sec", (unsigned int) (usec * 10000));
|
||||
snprintf(ts, size, "0.%04u sec", (unsigned int) usec * 10000);
|
||||
}
|
||||
}
|
||||
|
||||
|
49
compatfd.c
49
compatfd.c
@@ -26,45 +26,45 @@ struct sigfd_compat_info
|
||||
static void *sigwait_compat(void *opaque)
|
||||
{
|
||||
struct sigfd_compat_info *info = opaque;
|
||||
int err;
|
||||
sigset_t all;
|
||||
|
||||
sigfillset(&all);
|
||||
pthread_sigmask(SIG_BLOCK, &all, NULL);
|
||||
sigprocmask(SIG_BLOCK, &all, NULL);
|
||||
|
||||
while (1) {
|
||||
int sig;
|
||||
int err;
|
||||
do {
|
||||
siginfo_t siginfo;
|
||||
|
||||
err = sigwait(&info->mask, &sig);
|
||||
if (err != 0) {
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
struct qemu_signalfd_siginfo buffer;
|
||||
err = sigwaitinfo(&info->mask, &siginfo);
|
||||
if (err == -1 && errno == EINTR) {
|
||||
err = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (err > 0) {
|
||||
char buffer[128];
|
||||
size_t offset = 0;
|
||||
|
||||
memset(&buffer, 0, sizeof(buffer));
|
||||
buffer.ssi_signo = sig;
|
||||
|
||||
memcpy(buffer, &err, sizeof(err));
|
||||
while (offset < sizeof(buffer)) {
|
||||
ssize_t len;
|
||||
|
||||
len = write(info->fd, (char *)&buffer + offset,
|
||||
len = write(info->fd, buffer + offset,
|
||||
sizeof(buffer) - offset);
|
||||
if (len == -1 && errno == EINTR)
|
||||
continue;
|
||||
|
||||
if (len <= 0) {
|
||||
return NULL;
|
||||
err = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
offset += len;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (err >= 0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int qemu_signalfd_compat(const sigset_t *mask)
|
||||
@@ -115,14 +115,3 @@ int qemu_signalfd(const sigset_t *mask)
|
||||
|
||||
return qemu_signalfd_compat(mask);
|
||||
}
|
||||
|
||||
bool qemu_signalfd_available(void)
|
||||
{
|
||||
#ifdef CONFIG_SIGNALFD
|
||||
errno = 0;
|
||||
syscall(SYS_signalfd, -1, NULL, _NSIG / 8);
|
||||
return errno != ENOSYS;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
@@ -39,6 +39,5 @@ struct qemu_signalfd_siginfo {
|
||||
};
|
||||
|
||||
int qemu_signalfd(const sigset_t *mask);
|
||||
bool qemu_signalfd_available(void);
|
||||
|
||||
#endif
|
||||
|
34
compiler.h
34
compiler.h
@@ -1,34 +0,0 @@
|
||||
/* public domain */
|
||||
|
||||
#ifndef COMPILER_H
|
||||
#define COMPILER_H
|
||||
|
||||
#include "config-host.h"
|
||||
|
||||
#define QEMU_NORETURN __attribute__ ((__noreturn__))
|
||||
#ifdef CONFIG_GCC_ATTRIBUTE_WARN_UNUSED_RESULT
|
||||
#define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
||||
#else
|
||||
#define QEMU_WARN_UNUSED_RESULT
|
||||
#endif
|
||||
|
||||
#define QEMU_BUILD_BUG_ON(x) \
|
||||
typedef char qemu_build_bug_on__##__LINE__[(x)?-1:1];
|
||||
|
||||
#if defined __GNUC__
|
||||
# if (__GNUC__ < 4) || \
|
||||
defined(__GNUC_MINOR__) && (__GNUC__ == 4) && (__GNUC_MINOR__ < 4)
|
||||
/* gcc versions before 4.4.x don't support gnu_printf, so use printf. */
|
||||
# define GCC_ATTR __attribute__((__unused__, format(printf, 1, 2)))
|
||||
# define GCC_FMT_ATTR(n, m) __attribute__((format(printf, n, m)))
|
||||
# else
|
||||
/* Use gnu_printf when supported (qemu uses standard format strings). */
|
||||
# define GCC_ATTR __attribute__((__unused__, format(gnu_printf, 1, 2)))
|
||||
# define GCC_FMT_ATTR(n, m) __attribute__((format(gnu_printf, n, m)))
|
||||
# endif
|
||||
#else
|
||||
#define GCC_ATTR /**/
|
||||
#define GCC_FMT_ATTR(n, m)
|
||||
#endif
|
||||
|
||||
#endif /* COMPILER_H */
|
69
console.c
69
console.c
@@ -180,7 +180,7 @@ void vga_hw_screen_dump(const char *filename)
|
||||
active_console = consoles[0];
|
||||
/* There is currently no way of specifying which screen we want to dump,
|
||||
so always dump the first one. */
|
||||
if (consoles[0] && consoles[0]->hw_screen_dump)
|
||||
if (consoles[0]->hw_screen_dump)
|
||||
consoles[0]->hw_screen_dump(consoles[0]->hw, filename);
|
||||
active_console = previous_active_console;
|
||||
}
|
||||
@@ -1135,7 +1135,7 @@ static void kbd_send_chars(void *opaque)
|
||||
/* characters are pending: we send them a bit later (XXX:
|
||||
horrible, should change char device API) */
|
||||
if (s->out_fifo.count > 0) {
|
||||
qemu_mod_timer(s->kbd_timer, qemu_get_clock_ms(rt_clock) + 1);
|
||||
qemu_mod_timer(s->kbd_timer, qemu_get_clock(rt_clock) + 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1278,40 +1278,38 @@ static DisplaySurface* defaultallocator_create_displaysurface(int width, int hei
|
||||
{
|
||||
DisplaySurface *surface = (DisplaySurface*) qemu_mallocz(sizeof(DisplaySurface));
|
||||
|
||||
int linesize = width * 4;
|
||||
qemu_alloc_display(surface, width, height, linesize,
|
||||
qemu_default_pixelformat(32), 0);
|
||||
surface->width = width;
|
||||
surface->height = height;
|
||||
surface->linesize = width * 4;
|
||||
surface->pf = qemu_default_pixelformat(32);
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
|
||||
#else
|
||||
surface->flags = QEMU_ALLOCATED_FLAG;
|
||||
#endif
|
||||
surface->data = (uint8_t*) qemu_mallocz(surface->linesize * surface->height);
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
static DisplaySurface* defaultallocator_resize_displaysurface(DisplaySurface *surface,
|
||||
int width, int height)
|
||||
{
|
||||
int linesize = width * 4;
|
||||
qemu_alloc_display(surface, width, height, linesize,
|
||||
qemu_default_pixelformat(32), 0);
|
||||
return surface;
|
||||
}
|
||||
|
||||
void qemu_alloc_display(DisplaySurface *surface, int width, int height,
|
||||
int linesize, PixelFormat pf, int newflags)
|
||||
{
|
||||
void *data;
|
||||
surface->width = width;
|
||||
surface->height = height;
|
||||
surface->linesize = linesize;
|
||||
surface->pf = pf;
|
||||
if (surface->flags & QEMU_ALLOCATED_FLAG) {
|
||||
data = qemu_realloc(surface->data,
|
||||
surface->linesize * surface->height);
|
||||
} else {
|
||||
data = qemu_malloc(surface->linesize * surface->height);
|
||||
}
|
||||
surface->data = (uint8_t *)data;
|
||||
surface->flags = newflags | QEMU_ALLOCATED_FLAG;
|
||||
surface->linesize = width * 4;
|
||||
surface->pf = qemu_default_pixelformat(32);
|
||||
if (surface->flags & QEMU_ALLOCATED_FLAG)
|
||||
surface->data = (uint8_t*) qemu_realloc(surface->data, surface->linesize * surface->height);
|
||||
else
|
||||
surface->data = (uint8_t*) qemu_malloc(surface->linesize * surface->height);
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
surface->flags |= QEMU_BIG_ENDIAN_FLAG;
|
||||
surface->flags = QEMU_ALLOCATED_FLAG | QEMU_BIG_ENDIAN_FLAG;
|
||||
#else
|
||||
surface->flags = QEMU_ALLOCATED_FLAG;
|
||||
#endif
|
||||
|
||||
return surface;
|
||||
}
|
||||
|
||||
DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
|
||||
@@ -1349,15 +1347,8 @@ static struct DisplayAllocator default_allocator = {
|
||||
static void dumb_display_init(void)
|
||||
{
|
||||
DisplayState *ds = qemu_mallocz(sizeof(DisplayState));
|
||||
int width = 640;
|
||||
int height = 480;
|
||||
|
||||
ds->allocator = &default_allocator;
|
||||
if (is_fixedsize_console()) {
|
||||
width = active_console->g_width;
|
||||
height = active_console->g_height;
|
||||
}
|
||||
ds->surface = qemu_create_displaysurface(ds, width, height);
|
||||
ds->surface = qemu_create_displaysurface(ds, 640, 480);
|
||||
register_displaystate(ds);
|
||||
}
|
||||
|
||||
@@ -1466,7 +1457,7 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
|
||||
|
||||
s->out_fifo.buf = s->out_fifo_buf;
|
||||
s->out_fifo.buf_size = sizeof(s->out_fifo_buf);
|
||||
s->kbd_timer = qemu_new_timer_ms(rt_clock, kbd_send_chars, s);
|
||||
s->kbd_timer = qemu_new_timer(rt_clock, kbd_send_chars, s);
|
||||
s->ds = ds;
|
||||
|
||||
if (!color_inited) {
|
||||
@@ -1514,7 +1505,7 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
|
||||
chr->init(chr);
|
||||
}
|
||||
|
||||
int text_console_init(QemuOpts *opts, CharDriverState **_chr)
|
||||
CharDriverState *text_console_init(QemuOpts *opts)
|
||||
{
|
||||
CharDriverState *chr;
|
||||
TextConsole *s;
|
||||
@@ -1546,7 +1537,7 @@ int text_console_init(QemuOpts *opts, CharDriverState **_chr)
|
||||
|
||||
if (!s) {
|
||||
free(chr);
|
||||
return -EBUSY;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
s->chr = chr;
|
||||
@@ -1554,9 +1545,7 @@ int text_console_init(QemuOpts *opts, CharDriverState **_chr)
|
||||
s->g_height = height;
|
||||
chr->opaque = s;
|
||||
chr->chr_set_echo = text_console_set_echo;
|
||||
|
||||
*_chr = chr;
|
||||
return 0;
|
||||
return chr;
|
||||
}
|
||||
|
||||
void text_consoles_set_display(DisplayState *ds)
|
||||
|
31
console.h
31
console.h
@@ -4,8 +4,6 @@
|
||||
#include "qemu-char.h"
|
||||
#include "qdict.h"
|
||||
#include "notify.h"
|
||||
#include "qerror.h"
|
||||
#include "monitor.h"
|
||||
|
||||
/* keyboard/mouse support */
|
||||
|
||||
@@ -191,8 +189,6 @@ void register_displaystate(DisplayState *ds);
|
||||
DisplayState *get_displaystate(void);
|
||||
DisplaySurface* qemu_create_displaysurface_from(int width, int height, int bpp,
|
||||
int linesize, uint8_t *data);
|
||||
void qemu_alloc_display(DisplaySurface *surface, int width, int height,
|
||||
int linesize, PixelFormat pf, int newflags);
|
||||
PixelFormat qemu_different_endianness_pixelformat(int bpp);
|
||||
PixelFormat qemu_default_pixelformat(int bpp);
|
||||
|
||||
@@ -354,7 +350,7 @@ void vga_hw_text_update(console_ch_t *chardata);
|
||||
|
||||
int is_graphic_console(void);
|
||||
int is_fixedsize_console(void);
|
||||
int text_console_init(QemuOpts *opts, CharDriverState **_chr);
|
||||
CharDriverState *text_console_init(QemuOpts *opts);
|
||||
void text_consoles_set_display(DisplayState *ds);
|
||||
void console_select(unsigned int index);
|
||||
void console_color_init(DisplayState *ds);
|
||||
@@ -372,33 +368,12 @@ void cocoa_display_init(DisplayState *ds, int full_screen);
|
||||
void vnc_display_init(DisplayState *ds);
|
||||
void vnc_display_close(DisplayState *ds);
|
||||
int vnc_display_open(DisplayState *ds, const char *display);
|
||||
void vnc_display_add_client(DisplayState *ds, int csock, int skipauth);
|
||||
int vnc_display_disable_login(DisplayState *ds);
|
||||
char *vnc_display_local_addr(DisplayState *ds);
|
||||
#ifdef CONFIG_VNC
|
||||
int vnc_display_password(DisplayState *ds, const char *password);
|
||||
int vnc_display_disable_login(DisplayState *ds);
|
||||
int vnc_display_pw_expire(DisplayState *ds, time_t expires);
|
||||
void do_info_vnc_print(Monitor *mon, const QObject *data);
|
||||
void do_info_vnc(Monitor *mon, QObject **ret_data);
|
||||
#else
|
||||
static inline int vnc_display_password(DisplayState *ds, const char *password)
|
||||
{
|
||||
qerror_report(QERR_FEATURE_DISABLED, "vnc");
|
||||
return -ENODEV;
|
||||
}
|
||||
static inline int vnc_display_pw_expire(DisplayState *ds, time_t expires)
|
||||
{
|
||||
qerror_report(QERR_FEATURE_DISABLED, "vnc");
|
||||
return -ENODEV;
|
||||
};
|
||||
static inline void do_info_vnc(Monitor *mon, QObject **ret_data)
|
||||
{
|
||||
};
|
||||
static inline void do_info_vnc_print(Monitor *mon, const QObject *data)
|
||||
{
|
||||
monitor_printf(mon, "VNC support disabled\n");
|
||||
};
|
||||
#endif
|
||||
char *vnc_display_local_addr(DisplayState *ds);
|
||||
|
||||
/* curses.c */
|
||||
void curses_display_init(DisplayState *ds, int full_screen);
|
||||
|
106
cpu-all.h
106
cpu-all.h
@@ -123,7 +123,8 @@ typedef union {
|
||||
endian ! */
|
||||
typedef union {
|
||||
float64 d;
|
||||
#if defined(HOST_WORDS_BIGENDIAN)
|
||||
#if defined(HOST_WORDS_BIGENDIAN) \
|
||||
|| (defined(__arm__) && !defined(__VFP_FP__) && !defined(CONFIG_SOFTFLOAT))
|
||||
struct {
|
||||
uint32_t upper;
|
||||
uint32_t lower;
|
||||
@@ -137,17 +138,11 @@ typedef union {
|
||||
uint64_t ll;
|
||||
} CPU_DoubleU;
|
||||
|
||||
typedef union {
|
||||
floatx80 d;
|
||||
struct {
|
||||
uint64_t lower;
|
||||
uint16_t upper;
|
||||
} l;
|
||||
} CPU_LDoubleU;
|
||||
|
||||
#ifdef TARGET_SPARC
|
||||
typedef union {
|
||||
float128 q;
|
||||
#if defined(HOST_WORDS_BIGENDIAN)
|
||||
#if defined(HOST_WORDS_BIGENDIAN) \
|
||||
|| (defined(__arm__) && !defined(__VFP_FP__) && !defined(CONFIG_SOFTFLOAT))
|
||||
struct {
|
||||
uint32_t upmost;
|
||||
uint32_t upper;
|
||||
@@ -171,6 +166,7 @@ typedef union {
|
||||
} ll;
|
||||
#endif
|
||||
} CPU_QuadU;
|
||||
#endif
|
||||
|
||||
/* CPU memory access without any memory or io remapping */
|
||||
|
||||
@@ -781,73 +777,25 @@ void QEMU_NORETURN cpu_abort(CPUState *env, const char *fmt, ...)
|
||||
extern CPUState *first_cpu;
|
||||
extern CPUState *cpu_single_env;
|
||||
|
||||
/* Flags for use in ENV->INTERRUPT_PENDING.
|
||||
|
||||
The numbers assigned here are non-sequential in order to preserve
|
||||
binary compatibility with the vmstate dump. Bit 0 (0x0001) was
|
||||
previously used for CPU_INTERRUPT_EXIT, and is cleared when loading
|
||||
the vmstate dump. */
|
||||
|
||||
/* External hardware interrupt pending. This is typically used for
|
||||
interrupts from devices. */
|
||||
#define CPU_INTERRUPT_HARD 0x0002
|
||||
|
||||
/* Exit the current TB. This is typically used when some system-level device
|
||||
makes some change to the memory mapping. E.g. the a20 line change. */
|
||||
#define CPU_INTERRUPT_EXITTB 0x0004
|
||||
|
||||
/* Halt the CPU. */
|
||||
#define CPU_INTERRUPT_HALT 0x0020
|
||||
|
||||
/* Debug event pending. */
|
||||
#define CPU_INTERRUPT_DEBUG 0x0080
|
||||
|
||||
/* Several target-specific external hardware interrupts. Each target/cpu.h
|
||||
should define proper names based on these defines. */
|
||||
#define CPU_INTERRUPT_TGT_EXT_0 0x0008
|
||||
#define CPU_INTERRUPT_TGT_EXT_1 0x0010
|
||||
#define CPU_INTERRUPT_TGT_EXT_2 0x0040
|
||||
#define CPU_INTERRUPT_TGT_EXT_3 0x0200
|
||||
#define CPU_INTERRUPT_TGT_EXT_4 0x1000
|
||||
|
||||
/* Several target-specific internal interrupts. These differ from the
|
||||
preceeding target-specific interrupts in that they are intended to
|
||||
originate from within the cpu itself, typically in response to some
|
||||
instruction being executed. These, therefore, are not masked while
|
||||
single-stepping within the debugger. */
|
||||
#define CPU_INTERRUPT_TGT_INT_0 0x0100
|
||||
#define CPU_INTERRUPT_TGT_INT_1 0x0400
|
||||
#define CPU_INTERRUPT_TGT_INT_2 0x0800
|
||||
|
||||
/* First unused bit: 0x2000. */
|
||||
|
||||
/* The set of all bits that should be masked when single-stepping. */
|
||||
#define CPU_INTERRUPT_SSTEP_MASK \
|
||||
(CPU_INTERRUPT_HARD \
|
||||
| CPU_INTERRUPT_TGT_EXT_0 \
|
||||
| CPU_INTERRUPT_TGT_EXT_1 \
|
||||
| CPU_INTERRUPT_TGT_EXT_2 \
|
||||
| CPU_INTERRUPT_TGT_EXT_3 \
|
||||
| CPU_INTERRUPT_TGT_EXT_4)
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
typedef void (*CPUInterruptHandler)(CPUState *, int);
|
||||
|
||||
extern CPUInterruptHandler cpu_interrupt_handler;
|
||||
|
||||
static inline void cpu_interrupt(CPUState *s, int mask)
|
||||
{
|
||||
cpu_interrupt_handler(s, mask);
|
||||
}
|
||||
#else /* USER_ONLY */
|
||||
void cpu_interrupt(CPUState *env, int mask);
|
||||
#endif /* USER_ONLY */
|
||||
#define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */
|
||||
#define CPU_INTERRUPT_EXITTB 0x04 /* exit the current TB (use for x86 a20 case) */
|
||||
#define CPU_INTERRUPT_TIMER 0x08 /* internal timer exception pending */
|
||||
#define CPU_INTERRUPT_FIQ 0x10 /* Fast interrupt pending. */
|
||||
#define CPU_INTERRUPT_HALT 0x20 /* CPU halt wanted */
|
||||
#define CPU_INTERRUPT_SMI 0x40 /* (x86 only) SMI interrupt pending */
|
||||
#define CPU_INTERRUPT_DEBUG 0x80 /* Debug event occured. */
|
||||
#define CPU_INTERRUPT_VIRQ 0x100 /* virtual interrupt pending. */
|
||||
#define CPU_INTERRUPT_NMI 0x200 /* NMI pending. */
|
||||
#define CPU_INTERRUPT_INIT 0x400 /* INIT pending. */
|
||||
#define CPU_INTERRUPT_SIPI 0x800 /* SIPI pending. */
|
||||
#define CPU_INTERRUPT_MCE 0x1000 /* (x86 only) MCE pending. */
|
||||
|
||||
void cpu_interrupt(CPUState *s, int mask);
|
||||
void cpu_reset_interrupt(CPUState *env, int mask);
|
||||
|
||||
void cpu_exit(CPUState *s);
|
||||
|
||||
bool qemu_cpu_has_work(CPUState *env);
|
||||
int qemu_cpu_has_work(CPUState *env);
|
||||
|
||||
/* Breakpoint/watchpoint flags */
|
||||
#define BP_MEM_READ 0x01
|
||||
@@ -915,14 +863,10 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr);
|
||||
extern int phys_ram_fd;
|
||||
extern ram_addr_t ram_size;
|
||||
|
||||
/* RAM is pre-allocated and passed into qemu_ram_alloc_from_ptr */
|
||||
#define RAM_PREALLOC_MASK (1 << 0)
|
||||
|
||||
typedef struct RAMBlock {
|
||||
uint8_t *host;
|
||||
ram_addr_t offset;
|
||||
ram_addr_t length;
|
||||
uint32_t flags;
|
||||
char idstr[256];
|
||||
QLIST_ENTRY(RAMBlock) next;
|
||||
#if defined(__linux__) && !defined(TARGET_S390X)
|
||||
@@ -1015,16 +959,14 @@ int cpu_physical_memory_get_dirty_tracking(void);
|
||||
int cpu_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
|
||||
target_phys_addr_t end_addr);
|
||||
|
||||
int cpu_physical_log_start(target_phys_addr_t start_addr,
|
||||
ram_addr_t size);
|
||||
|
||||
int cpu_physical_log_stop(target_phys_addr_t start_addr,
|
||||
ram_addr_t size);
|
||||
|
||||
void dump_exec_info(FILE *f, fprintf_function cpu_fprintf);
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
|
||||
uint8_t *buf, int len, int is_write);
|
||||
|
||||
void cpu_inject_x86_mce(CPUState *cenv, int bank, uint64_t status,
|
||||
uint64_t mcg_status, uint64_t addr, uint64_t misc,
|
||||
int broadcast);
|
||||
|
||||
#endif /* CPU_ALL_H */
|
||||
|
53
cpu-common.h
53
cpu-common.h
@@ -34,21 +34,10 @@ typedef unsigned long ram_addr_t;
|
||||
typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t value);
|
||||
typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr);
|
||||
|
||||
void cpu_register_physical_memory_log(target_phys_addr_t start_addr,
|
||||
ram_addr_t size,
|
||||
ram_addr_t phys_offset,
|
||||
ram_addr_t region_offset,
|
||||
bool log_dirty);
|
||||
|
||||
static inline void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
|
||||
ram_addr_t size,
|
||||
ram_addr_t phys_offset,
|
||||
ram_addr_t region_offset)
|
||||
{
|
||||
cpu_register_physical_memory_log(start_addr, size, phys_offset,
|
||||
region_offset, false);
|
||||
}
|
||||
|
||||
void cpu_register_physical_memory_offset(target_phys_addr_t start_addr,
|
||||
ram_addr_t size,
|
||||
ram_addr_t phys_offset,
|
||||
ram_addr_t region_offset);
|
||||
static inline void cpu_register_physical_memory(target_phys_addr_t start_addr,
|
||||
ram_addr_t size,
|
||||
ram_addr_t phys_offset)
|
||||
@@ -61,15 +50,11 @@ ram_addr_t qemu_ram_alloc_from_ptr(DeviceState *dev, const char *name,
|
||||
ram_addr_t size, void *host);
|
||||
ram_addr_t qemu_ram_alloc(DeviceState *dev, const char *name, ram_addr_t size);
|
||||
void qemu_ram_free(ram_addr_t addr);
|
||||
void qemu_ram_free_from_ptr(ram_addr_t addr);
|
||||
void qemu_ram_remap(ram_addr_t addr, ram_addr_t length);
|
||||
/* This should only be used for ram local to a device. */
|
||||
void *qemu_get_ram_ptr(ram_addr_t addr);
|
||||
void *qemu_ram_ptr_length(ram_addr_t addr, ram_addr_t *size);
|
||||
/* Same but slower, to use for migration, where the order of
|
||||
* RAMBlocks must not change. */
|
||||
void *qemu_safe_ram_ptr(ram_addr_t addr);
|
||||
void qemu_put_ram_ptr(void *addr);
|
||||
/* This should not be used by devices. */
|
||||
int qemu_ram_addr_from_host(void *ptr, ram_addr_t *ram_addr);
|
||||
ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr);
|
||||
@@ -82,14 +67,14 @@ void cpu_unregister_io_memory(int table_address);
|
||||
void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
|
||||
int len, int is_write);
|
||||
static inline void cpu_physical_memory_read(target_phys_addr_t addr,
|
||||
void *buf, int len)
|
||||
uint8_t *buf, int len)
|
||||
{
|
||||
cpu_physical_memory_rw(addr, buf, len, 0);
|
||||
}
|
||||
static inline void cpu_physical_memory_write(target_phys_addr_t addr,
|
||||
const void *buf, int len)
|
||||
const uint8_t *buf, int len)
|
||||
{
|
||||
cpu_physical_memory_rw(addr, (void *)buf, len, 1);
|
||||
cpu_physical_memory_rw(addr, (uint8_t *)buf, len, 1);
|
||||
}
|
||||
void *cpu_physical_memory_map(target_phys_addr_t addr,
|
||||
target_phys_addr_t *plen,
|
||||
@@ -105,17 +90,12 @@ struct CPUPhysMemoryClient {
|
||||
void (*set_memory)(struct CPUPhysMemoryClient *client,
|
||||
target_phys_addr_t start_addr,
|
||||
ram_addr_t size,
|
||||
ram_addr_t phys_offset,
|
||||
bool log_dirty);
|
||||
ram_addr_t phys_offset);
|
||||
int (*sync_dirty_bitmap)(struct CPUPhysMemoryClient *client,
|
||||
target_phys_addr_t start_addr,
|
||||
target_phys_addr_t end_addr);
|
||||
int (*migration_log)(struct CPUPhysMemoryClient *client,
|
||||
int enable);
|
||||
int (*log_start)(struct CPUPhysMemoryClient *client,
|
||||
target_phys_addr_t phys_addr, ram_addr_t size);
|
||||
int (*log_stop)(struct CPUPhysMemoryClient *client,
|
||||
target_phys_addr_t phys_addr, ram_addr_t size);
|
||||
QLIST_ENTRY(CPUPhysMemoryClient) list;
|
||||
};
|
||||
|
||||
@@ -134,30 +114,15 @@ void qemu_unregister_coalesced_mmio(target_phys_addr_t addr, ram_addr_t size);
|
||||
void qemu_flush_coalesced_mmio_buffer(void);
|
||||
|
||||
uint32_t ldub_phys(target_phys_addr_t addr);
|
||||
uint32_t lduw_le_phys(target_phys_addr_t addr);
|
||||
uint32_t lduw_be_phys(target_phys_addr_t addr);
|
||||
uint32_t ldl_le_phys(target_phys_addr_t addr);
|
||||
uint32_t ldl_be_phys(target_phys_addr_t addr);
|
||||
uint64_t ldq_le_phys(target_phys_addr_t addr);
|
||||
uint64_t ldq_be_phys(target_phys_addr_t addr);
|
||||
void stb_phys(target_phys_addr_t addr, uint32_t val);
|
||||
void stw_le_phys(target_phys_addr_t addr, uint32_t val);
|
||||
void stw_be_phys(target_phys_addr_t addr, uint32_t val);
|
||||
void stl_le_phys(target_phys_addr_t addr, uint32_t val);
|
||||
void stl_be_phys(target_phys_addr_t addr, uint32_t val);
|
||||
void stq_le_phys(target_phys_addr_t addr, uint64_t val);
|
||||
void stq_be_phys(target_phys_addr_t addr, uint64_t val);
|
||||
|
||||
#ifdef NEED_CPU_H
|
||||
uint32_t lduw_phys(target_phys_addr_t addr);
|
||||
uint32_t ldl_phys(target_phys_addr_t addr);
|
||||
uint64_t ldq_phys(target_phys_addr_t addr);
|
||||
void stl_phys_notdirty(target_phys_addr_t addr, uint32_t val);
|
||||
void stq_phys_notdirty(target_phys_addr_t addr, uint64_t val);
|
||||
void stb_phys(target_phys_addr_t addr, uint32_t val);
|
||||
void stw_phys(target_phys_addr_t addr, uint32_t val);
|
||||
void stl_phys(target_phys_addr_t addr, uint32_t val);
|
||||
void stq_phys(target_phys_addr_t addr, uint64_t val);
|
||||
#endif
|
||||
|
||||
void cpu_physical_memory_write_rom(target_phys_addr_t addr,
|
||||
const uint8_t *buf, int len);
|
||||
|
16
cpu-defs.h
16
cpu-defs.h
@@ -37,22 +37,16 @@
|
||||
|
||||
#define TARGET_LONG_SIZE (TARGET_LONG_BITS / 8)
|
||||
|
||||
typedef int16_t target_short __attribute__ ((aligned(TARGET_SHORT_ALIGNMENT)));
|
||||
typedef uint16_t target_ushort __attribute__((aligned(TARGET_SHORT_ALIGNMENT)));
|
||||
typedef int32_t target_int __attribute__((aligned(TARGET_INT_ALIGNMENT)));
|
||||
typedef uint32_t target_uint __attribute__((aligned(TARGET_INT_ALIGNMENT)));
|
||||
typedef int64_t target_llong __attribute__((aligned(TARGET_LLONG_ALIGNMENT)));
|
||||
typedef uint64_t target_ullong __attribute__((aligned(TARGET_LLONG_ALIGNMENT)));
|
||||
/* target_ulong is the type of a virtual address */
|
||||
#if TARGET_LONG_SIZE == 4
|
||||
typedef int32_t target_long __attribute__((aligned(TARGET_LONG_ALIGNMENT)));
|
||||
typedef uint32_t target_ulong __attribute__((aligned(TARGET_LONG_ALIGNMENT)));
|
||||
typedef int32_t target_long;
|
||||
typedef uint32_t target_ulong;
|
||||
#define TARGET_FMT_lx "%08x"
|
||||
#define TARGET_FMT_ld "%d"
|
||||
#define TARGET_FMT_lu "%u"
|
||||
#elif TARGET_LONG_SIZE == 8
|
||||
typedef int64_t target_long __attribute__((aligned(TARGET_LONG_ALIGNMENT)));
|
||||
typedef uint64_t target_ulong __attribute__((aligned(TARGET_LONG_ALIGNMENT)));
|
||||
typedef int64_t target_long;
|
||||
typedef uint64_t target_ulong;
|
||||
#define TARGET_FMT_lx "%016" PRIx64
|
||||
#define TARGET_FMT_ld "%" PRId64
|
||||
#define TARGET_FMT_lu "%" PRIu64
|
||||
@@ -203,7 +197,6 @@ typedef struct CPUWatchpoint {
|
||||
int nr_cores; /* number of cores within this CPU package */ \
|
||||
int nr_threads;/* number of threads within this CPU */ \
|
||||
int running; /* Nonzero if cpu is currently running(usermode). */ \
|
||||
int thread_id; \
|
||||
/* user data */ \
|
||||
void *opaque; \
|
||||
\
|
||||
@@ -212,7 +205,6 @@ typedef struct CPUWatchpoint {
|
||||
uint32_t stopped; /* Artificially stopped */ \
|
||||
struct QemuThread *thread; \
|
||||
struct QemuCond *halt_cond; \
|
||||
int thread_kicked; \
|
||||
struct qemu_work_item *queued_work_first, *queued_work_last; \
|
||||
const char *cpu_model_str; \
|
||||
struct KVMState *kvm_state; \
|
||||
|
884
cpu-exec.c
884
cpu-exec.c
File diff suppressed because it is too large
Load Diff
9
cpus.h
9
cpus.h
@@ -6,21 +6,16 @@ int qemu_init_main_loop(void);
|
||||
void qemu_main_loop_start(void);
|
||||
void resume_all_vcpus(void);
|
||||
void pause_all_vcpus(void);
|
||||
void cpu_stop_current(void);
|
||||
bool qemu_system_is_ready(void);
|
||||
|
||||
void cpu_synchronize_all_states(void);
|
||||
void cpu_synchronize_all_post_reset(void);
|
||||
void cpu_synchronize_all_post_init(void);
|
||||
|
||||
/* vl.c */
|
||||
extern int smp_cores;
|
||||
extern int smp_threads;
|
||||
extern int debug_requested;
|
||||
extern int vmstop_requested;
|
||||
void vm_state_notify(int running, int reason);
|
||||
bool cpu_exec_all(void);
|
||||
void set_numa_modes(void);
|
||||
void set_cpu_log(const char *optarg);
|
||||
void set_cpu_log_filename(const char *optarg);
|
||||
void list_cpus(FILE *f, fprintf_function cpu_fprintf, const char *optarg);
|
||||
|
||||
#endif
|
||||
|
@@ -211,7 +211,7 @@ void do_compare_and_swap32(void *cpu_env, int num)
|
||||
uint32_t *value = (uint32_t*)((CPUX86State*)cpu_env)->regs[R_ECX];
|
||||
DPRINTF("commpage: compare_and_swap32(%x,new,%p)\n", old, value);
|
||||
|
||||
if(old == tswap32(*value))
|
||||
if(value && old == tswap32(*value))
|
||||
{
|
||||
uint32_t new = ((CPUX86State*)cpu_env)->regs[R_EDX];
|
||||
*value = tswap32(new);
|
||||
|
@@ -738,8 +738,6 @@ TaskState *first_task_state;
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *filename;
|
||||
const char *log_file = DEBUG_LOGFILE;
|
||||
const char *log_mask = NULL;
|
||||
struct target_pt_regs regs1, *regs = ®s1;
|
||||
TaskState ts1, *ts = &ts1;
|
||||
CPUState *env;
|
||||
@@ -751,6 +749,9 @@ int main(int argc, char **argv)
|
||||
if (argc <= 1)
|
||||
usage();
|
||||
|
||||
/* init debug */
|
||||
cpu_set_log_filename(DEBUG_LOGFILE);
|
||||
|
||||
optind = 1;
|
||||
for(;;) {
|
||||
if (optind >= argc)
|
||||
@@ -763,15 +764,22 @@ int main(int argc, char **argv)
|
||||
if (!strcmp(r, "-")) {
|
||||
break;
|
||||
} else if (!strcmp(r, "d")) {
|
||||
if (optind >= argc) {
|
||||
break;
|
||||
int mask;
|
||||
CPULogItem *item;
|
||||
|
||||
if (optind >= argc)
|
||||
break;
|
||||
|
||||
r = argv[optind++];
|
||||
mask = cpu_str_to_log_mask(r);
|
||||
if (!mask) {
|
||||
printf("Log items (comma separated):\n");
|
||||
for(item = cpu_log_items; item->mask != 0; item++) {
|
||||
printf("%-10s %s\n", item->name, item->help);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
log_mask = argv[optind++];
|
||||
} else if (!strcmp(r, "D")) {
|
||||
if (optind >= argc) {
|
||||
break;
|
||||
}
|
||||
log_file = argv[optind++];
|
||||
cpu_set_log(mask);
|
||||
} else if (!strcmp(r, "s")) {
|
||||
r = argv[optind++];
|
||||
stack_size = strtol(r, (char **)&r, 0);
|
||||
@@ -809,27 +817,8 @@ int main(int argc, char **argv)
|
||||
usage();
|
||||
}
|
||||
}
|
||||
|
||||
/* init debug */
|
||||
cpu_set_log_filename(log_file);
|
||||
if (log_mask) {
|
||||
int mask;
|
||||
CPULogItem *item;
|
||||
|
||||
mask = cpu_str_to_log_mask(log_mask);
|
||||
if (!mask) {
|
||||
printf("Log items (comma separated):\n");
|
||||
for (item = cpu_log_items; item->mask != 0; item++) {
|
||||
printf("%-10s %s\n", item->name, item->help);
|
||||
}
|
||||
exit(1);
|
||||
}
|
||||
cpu_set_log(mask);
|
||||
}
|
||||
|
||||
if (optind >= argc) {
|
||||
if (optind >= argc)
|
||||
usage();
|
||||
}
|
||||
filename = argv[optind];
|
||||
|
||||
/* Zero out regs */
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <errno.h>
|
||||
#include <sys/ucontext.h>
|
||||
|
||||
@@ -31,6 +32,8 @@
|
||||
#undef uc_link
|
||||
#endif
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include "qemu.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
|
@@ -977,7 +977,7 @@ long do_unix_syscall_indirect(void *cpu_env, int num)
|
||||
#elif TARGET_PPC
|
||||
{
|
||||
int i;
|
||||
/* XXX: not really needed those regs are volatile across calls */
|
||||
/* XXX: not really needed those regs are volatile accross calls */
|
||||
uint32_t **regs = ((CPUPPCState*)cpu_env)->gpr;
|
||||
for(i = 11; i > 3; i--)
|
||||
*regs[i] = *regs[i-1];
|
||||
|
@@ -1,9 +0,0 @@
|
||||
# Default configuration for alpha-softmmu
|
||||
|
||||
include pci.mak
|
||||
CONFIG_SERIAL=y
|
||||
CONFIG_I8254=y
|
||||
CONFIG_VGA_PCI=y
|
||||
CONFIG_IDE_CORE=y
|
||||
CONFIG_IDE_QDEV=y
|
||||
CONFIG_VMWARE_VGA=y
|
@@ -4,7 +4,6 @@ include pci.mak
|
||||
CONFIG_VGA_PCI=y
|
||||
CONFIG_VGA_ISA=y
|
||||
CONFIG_VMWARE_VGA=y
|
||||
CONFIG_VMMOUSE=y
|
||||
CONFIG_SERIAL=y
|
||||
CONFIG_PARALLEL=y
|
||||
CONFIG_I8254=y
|
||||
@@ -19,5 +18,3 @@ CONFIG_IDE_PIIX=y
|
||||
CONFIG_NE2000_ISA=y
|
||||
CONFIG_PIIX_PCI=y
|
||||
CONFIG_SOUND=y
|
||||
CONFIG_HPET=y
|
||||
CONFIG_APPLESMC=y
|
||||
|
@@ -1,6 +0,0 @@
|
||||
# Default configuration for lm32-softmmu
|
||||
|
||||
CONFIG_PTIMER=y
|
||||
CONFIG_PFLASH_CFI01=y
|
||||
CONFIG_PFLASH_CFI02=y
|
||||
CONFIG_SD=y
|
@@ -2,4 +2,3 @@
|
||||
|
||||
CONFIG_PTIMER=y
|
||||
CONFIG_PFLASH_CFI01=y
|
||||
CONFIG_SERIAL=y
|
||||
|
@@ -1 +0,0 @@
|
||||
# Default configuration for microblazeel-linux-user
|
@@ -1,5 +0,0 @@
|
||||
# Default configuration for microblazeel-softmmu
|
||||
|
||||
CONFIG_PTIMER=y
|
||||
CONFIG_PFLASH_CFI01=y
|
||||
CONFIG_SERIAL=y
|
@@ -3,7 +3,6 @@ CONFIG_VIRTIO_PCI=y
|
||||
CONFIG_VIRTIO=y
|
||||
CONFIG_USB_UHCI=y
|
||||
CONFIG_USB_OHCI=y
|
||||
CONFIG_USB_EHCI=y
|
||||
CONFIG_NE2000_PCI=y
|
||||
CONFIG_EEPRO100_PCI=y
|
||||
CONFIG_PCNET_PCI=y
|
||||
|
@@ -1 +0,0 @@
|
||||
# Default configuration for s390x-linux-user
|
@@ -1 +0,0 @@
|
||||
# Default configuration for unicore32-linux-user
|
@@ -4,7 +4,6 @@ include pci.mak
|
||||
CONFIG_VGA_PCI=y
|
||||
CONFIG_VGA_ISA=y
|
||||
CONFIG_VMWARE_VGA=y
|
||||
CONFIG_VMMOUSE=y
|
||||
CONFIG_SERIAL=y
|
||||
CONFIG_PARALLEL=y
|
||||
CONFIG_I8254=y
|
||||
@@ -19,5 +18,3 @@ CONFIG_IDE_PIIX=y
|
||||
CONFIG_NE2000_ISA=y
|
||||
CONFIG_PIIX_PCI=y
|
||||
CONFIG_SOUND=y
|
||||
CONFIG_HPET=y
|
||||
CONFIG_APPLESMC=y
|
||||
|
@@ -20,6 +20,7 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "qemu-common.h"
|
||||
#include "sysemu.h"
|
||||
#include "device_tree.h"
|
||||
#include "hw/loader.h"
|
||||
|
||||
@@ -73,7 +74,7 @@ fail:
|
||||
}
|
||||
|
||||
int qemu_devtree_setprop(void *fdt, const char *node_path,
|
||||
const char *property, void *val_array, int size)
|
||||
const char *property, uint32_t *val_array, int size)
|
||||
{
|
||||
int offset;
|
||||
|
||||
|
@@ -17,7 +17,7 @@
|
||||
void *load_device_tree(const char *filename_path, int *sizep);
|
||||
|
||||
int qemu_devtree_setprop(void *fdt, const char *node_path,
|
||||
const char *property, void *val_array, int size);
|
||||
const char *property, uint32_t *val_array, int size);
|
||||
int qemu_devtree_setprop_cell(void *fdt, const char *node_path,
|
||||
const char *property, uint32_t val);
|
||||
int qemu_devtree_setprop_string(void *fdt, const char *node_path,
|
||||
|
@@ -184,9 +184,6 @@ enum bfd_architecture
|
||||
#define bfd_mach_sh5 0x50
|
||||
bfd_arch_alpha, /* Dec Alpha */
|
||||
#define bfd_mach_alpha 1
|
||||
#define bfd_mach_alpha_ev4 0x10
|
||||
#define bfd_mach_alpha_ev5 0x20
|
||||
#define bfd_mach_alpha_ev6 0x30
|
||||
bfd_arch_arm, /* Advanced Risc Machines ARM */
|
||||
#define bfd_mach_arm_unknown 0
|
||||
#define bfd_mach_arm_2 1
|
||||
|
11
disas.c
11
disas.c
@@ -5,6 +5,7 @@
|
||||
#include <errno.h>
|
||||
|
||||
#include "cpu.h"
|
||||
#include "exec-all.h"
|
||||
#include "disas.h"
|
||||
|
||||
/* Filled in by elfload.c. Simplistic, but will do for now. */
|
||||
@@ -204,7 +205,7 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
|
||||
disasm_info.mach = bfd_mach_sh4;
|
||||
print_insn = print_insn_sh;
|
||||
#elif defined(TARGET_ALPHA)
|
||||
disasm_info.mach = bfd_mach_alpha_ev6;
|
||||
disasm_info.mach = bfd_mach_alpha;
|
||||
print_insn = print_insn_alpha;
|
||||
#elif defined(TARGET_CRIS)
|
||||
if (flags != 32) {
|
||||
@@ -214,9 +215,6 @@ void target_disas(FILE *out, target_ulong code, target_ulong size, int flags)
|
||||
disasm_info.mach = bfd_mach_cris_v32;
|
||||
print_insn = print_insn_crisv32;
|
||||
}
|
||||
#elif defined(TARGET_S390X)
|
||||
disasm_info.mach = bfd_mach_s390_64;
|
||||
print_insn = print_insn_s390;
|
||||
#elif defined(TARGET_MICROBLAZE)
|
||||
disasm_info.mach = bfd_arch_microblaze;
|
||||
print_insn = print_insn_microblaze;
|
||||
@@ -344,7 +342,7 @@ monitor_read_memory (bfd_vma memaddr, bfd_byte *myaddr, int length,
|
||||
struct disassemble_info *info)
|
||||
{
|
||||
if (monitor_disas_is_physical) {
|
||||
cpu_physical_memory_read(memaddr, myaddr, length);
|
||||
cpu_physical_memory_rw(memaddr, myaddr, length, 0);
|
||||
} else {
|
||||
cpu_memory_rw_debug(monitor_disas_env, memaddr,myaddr, length, 0);
|
||||
}
|
||||
@@ -416,9 +414,6 @@ void monitor_disas(Monitor *mon, CPUState *env,
|
||||
#elif defined(TARGET_SH4)
|
||||
disasm_info.mach = bfd_mach_sh4;
|
||||
print_insn = print_insn_sh;
|
||||
#elif defined(TARGET_S390X)
|
||||
disasm_info.mach = bfd_mach_s390_64;
|
||||
print_insn = print_insn_s390;
|
||||
#else
|
||||
monitor_printf(mon, "0x" TARGET_FMT_lx
|
||||
": Asm output not supported on this arch\n", pc);
|
||||
|
@@ -47,7 +47,6 @@ typedef struct {
|
||||
target_phys_addr_t sg_cur_byte;
|
||||
QEMUIOVector iov;
|
||||
QEMUBH *bh;
|
||||
DMAIOFunc *io_func;
|
||||
} DMAAIOCB;
|
||||
|
||||
static void dma_bdrv_cb(void *opaque, int ret);
|
||||
@@ -117,8 +116,13 @@ static void dma_bdrv_cb(void *opaque, int ret)
|
||||
return;
|
||||
}
|
||||
|
||||
dbs->acb = dbs->io_func(dbs->bs, dbs->sector_num, &dbs->iov,
|
||||
dbs->iov.size / 512, dma_bdrv_cb, dbs);
|
||||
if (dbs->is_write) {
|
||||
dbs->acb = bdrv_aio_writev(dbs->bs, dbs->sector_num, &dbs->iov,
|
||||
dbs->iov.size / 512, dma_bdrv_cb, dbs);
|
||||
} else {
|
||||
dbs->acb = bdrv_aio_readv(dbs->bs, dbs->sector_num, &dbs->iov,
|
||||
dbs->iov.size / 512, dma_bdrv_cb, dbs);
|
||||
}
|
||||
if (!dbs->acb) {
|
||||
dma_bdrv_unmap(dbs);
|
||||
qemu_iovec_destroy(&dbs->iov);
|
||||
@@ -140,12 +144,12 @@ static AIOPool dma_aio_pool = {
|
||||
.cancel = dma_aio_cancel,
|
||||
};
|
||||
|
||||
BlockDriverAIOCB *dma_bdrv_io(
|
||||
static BlockDriverAIOCB *dma_bdrv_io(
|
||||
BlockDriverState *bs, QEMUSGList *sg, uint64_t sector_num,
|
||||
DMAIOFunc *io_func, BlockDriverCompletionFunc *cb,
|
||||
void *opaque, int is_write)
|
||||
BlockDriverCompletionFunc *cb, void *opaque,
|
||||
int is_write)
|
||||
{
|
||||
DMAAIOCB *dbs = qemu_aio_get(&dma_aio_pool, bs, cb, opaque);
|
||||
DMAAIOCB *dbs = qemu_aio_get(&dma_aio_pool, bs, cb, opaque);
|
||||
|
||||
dbs->acb = NULL;
|
||||
dbs->bs = bs;
|
||||
@@ -154,7 +158,6 @@ BlockDriverAIOCB *dma_bdrv_io(
|
||||
dbs->sg_cur_index = 0;
|
||||
dbs->sg_cur_byte = 0;
|
||||
dbs->is_write = is_write;
|
||||
dbs->io_func = io_func;
|
||||
dbs->bh = NULL;
|
||||
qemu_iovec_init(&dbs->iov, sg->nsg);
|
||||
dma_bdrv_cb(dbs, 0);
|
||||
@@ -170,12 +173,12 @@ BlockDriverAIOCB *dma_bdrv_read(BlockDriverState *bs,
|
||||
QEMUSGList *sg, uint64_t sector,
|
||||
void (*cb)(void *opaque, int ret), void *opaque)
|
||||
{
|
||||
return dma_bdrv_io(bs, sg, sector, bdrv_aio_readv, cb, opaque, 0);
|
||||
return dma_bdrv_io(bs, sg, sector, cb, opaque, 0);
|
||||
}
|
||||
|
||||
BlockDriverAIOCB *dma_bdrv_write(BlockDriverState *bs,
|
||||
QEMUSGList *sg, uint64_t sector,
|
||||
void (*cb)(void *opaque, int ret), void *opaque)
|
||||
{
|
||||
return dma_bdrv_io(bs, sg, sector, bdrv_aio_writev, cb, opaque, 1);
|
||||
return dma_bdrv_io(bs, sg, sector, cb, opaque, 1);
|
||||
}
|
||||
|
8
dma.h
8
dma.h
@@ -32,14 +32,6 @@ void qemu_sglist_add(QEMUSGList *qsg, target_phys_addr_t base,
|
||||
target_phys_addr_t len);
|
||||
void qemu_sglist_destroy(QEMUSGList *qsg);
|
||||
|
||||
typedef BlockDriverAIOCB *DMAIOFunc(BlockDriverState *bs, int64_t sector_num,
|
||||
QEMUIOVector *iov, int nb_sectors,
|
||||
BlockDriverCompletionFunc *cb, void *opaque);
|
||||
|
||||
BlockDriverAIOCB *dma_bdrv_io(BlockDriverState *bs,
|
||||
QEMUSGList *sg, uint64_t sector_num,
|
||||
DMAIOFunc *io_func, BlockDriverCompletionFunc *cb,
|
||||
void *opaque, int is_write);
|
||||
BlockDriverAIOCB *dma_bdrv_read(BlockDriverState *bs,
|
||||
QEMUSGList *sg, uint64_t sector,
|
||||
BlockDriverCompletionFunc *cb, void *opaque);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user