Compare commits
285 Commits
pull-ui-20
...
pull-ui-20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1185fde40c | ||
|
|
2c2311c545 | ||
|
|
4d5942332f | ||
|
|
83cf07b0b5 | ||
|
|
ec9fb41a9f | ||
|
|
0c33682d5f | ||
|
|
3327182332 | ||
|
|
a5852dc5de | ||
|
|
6886b98036 | ||
|
|
f213e72f23 | ||
|
|
75809229bb | ||
|
|
9bbbf6497a | ||
|
|
b66e10e4c9 | ||
|
|
6f50f25c82 | ||
|
|
d36ebffe94 | ||
|
|
c1a3b8b745 | ||
|
|
c503a85599 | ||
|
|
014628a705 | ||
|
|
da2a34f7f9 | ||
|
|
7dcdaeafe0 | ||
|
|
8efb2ed5ec | ||
|
|
55d539c8f7 | ||
|
|
83de9be0dc | ||
|
|
d3199a31c7 | ||
|
|
b6495fa849 | ||
|
|
b6133b8c68 | ||
|
|
515c2f431e | ||
|
|
bf18bee547 | ||
|
|
2a9170bcd4 | ||
|
|
f3c3b87dae | ||
|
|
6f6071745b | ||
|
|
107d433cbb | ||
|
|
ebd2f9e7db | ||
|
|
ad2964b4ff | ||
|
|
c1499a5e73 | ||
|
|
a620f2ae15 | ||
|
|
39ad937e16 | ||
|
|
2ffa76c2bf | ||
|
|
49a2e48348 | ||
|
|
e88a36ebad | ||
|
|
9c21a4220b | ||
|
|
5544b59f8e | ||
|
|
94d047a35b | ||
|
|
74021bc497 | ||
|
|
d05aa8bb4a | ||
|
|
cf081fca4e | ||
|
|
8b18474451 | ||
|
|
ebb718a5c7 | ||
|
|
31ad4fdf91 | ||
|
|
5a64e94251 | ||
|
|
ba142846b0 | ||
|
|
443668ca40 | ||
|
|
d3a49cbed5 | ||
|
|
78465d74c2 | ||
|
|
8080214dc8 | ||
|
|
2346b12fc5 | ||
|
|
53735f0b82 | ||
|
|
34c98c54c3 | ||
|
|
49ca6f3e24 | ||
|
|
ff6dc13079 | ||
|
|
ffb7ee796a | ||
|
|
227f02143f | ||
|
|
a6130237b8 | ||
|
|
9e518226f4 | ||
|
|
b3f8233068 | ||
|
|
2a8459892f | ||
|
|
d40ecd6618 | ||
|
|
89f9fe4452 | ||
|
|
666875306e | ||
|
|
2a3c761928 | ||
|
|
918c03ed9a | ||
|
|
977d8241c1 | ||
|
|
badd3cd880 | ||
|
|
e0156a9dc4 | ||
|
|
9e024732f5 | ||
|
|
90c0f080fe | ||
|
|
3dab9fa1ac | ||
|
|
6ed5546fa7 | ||
|
|
30f549c2f3 | ||
|
|
5029b969d1 | ||
|
|
b1b2db29bd | ||
|
|
806956834a | ||
|
|
66c68a12ae | ||
|
|
df5d1c17b6 | ||
|
|
5d61cafd0b | ||
|
|
b988a650b1 | ||
|
|
d0448de7f6 | ||
|
|
207ba7c885 | ||
|
|
13385ae168 | ||
|
|
c41a73ffaf | ||
|
|
d737b78cc1 | ||
|
|
969401fe76 | ||
|
|
db718b4b15 | ||
|
|
e0ca2ed562 | ||
|
|
7a00217d1a | ||
|
|
0d5c21f2b3 | ||
|
|
e52eeb468d | ||
|
|
aa5982e0fd | ||
|
|
030c98aff1 | ||
|
|
36a2c2d6d3 | ||
|
|
79ffb277ec | ||
|
|
df891b9197 | ||
|
|
20875332b0 | ||
|
|
b92233b329 | ||
|
|
9e87a691bd | ||
|
|
0bab0ebb17 | ||
|
|
24a6e0633a | ||
|
|
2d7fedeb54 | ||
|
|
a8d38f3b02 | ||
|
|
d9d8d452da | ||
|
|
3b7c78c83a | ||
|
|
0668a06b81 | ||
|
|
bbd908025c | ||
|
|
8913885761 | ||
|
|
9640401389 | ||
|
|
6969ec6cfd | ||
|
|
a2c5eaf7a9 | ||
|
|
c00dc6750f | ||
|
|
cd1f16f947 | ||
|
|
3498686220 | ||
|
|
e9d5150739 | ||
|
|
96165b9eb4 | ||
|
|
891f8dcd25 | ||
|
|
a5cbe92199 | ||
|
|
395fe5f241 | ||
|
|
e35916ac0f | ||
|
|
d33c8a7d46 | ||
|
|
a6210f5701 | ||
|
|
b34aee54aa | ||
|
|
40eeb397c8 | ||
|
|
79cecb3520 | ||
|
|
d5aebef884 | ||
|
|
8860eabdee | ||
|
|
c8a9fd8071 | ||
|
|
41574268b7 | ||
|
|
117bc3fa22 | ||
|
|
e3a4f91b4d | ||
|
|
a7944dfad0 | ||
|
|
3a90c4ace2 | ||
|
|
ef8875b549 | ||
|
|
3482958383 | ||
|
|
efd7556708 | ||
|
|
0d97891312 | ||
|
|
271b385e7e | ||
|
|
a70dadc7f1 | ||
|
|
7d92d34ee4 | ||
|
|
bef653d92e | ||
|
|
a0995886e2 | ||
|
|
f59ec60610 | ||
|
|
ef6a778ea2 | ||
|
|
655ed67c2a | ||
|
|
907f5fddaa | ||
|
|
8fdb9fef3d | ||
|
|
c19c1578f8 | ||
|
|
3d3efba020 | ||
|
|
2fe4fba115 | ||
|
|
b28a1f333a | ||
|
|
9eede5b69f | ||
|
|
7ec87e06c7 | ||
|
|
e902d588dc | ||
|
|
eb5525013a | ||
|
|
c02d7030c3 | ||
|
|
9f318f8f7e | ||
|
|
3c3e88a814 | ||
|
|
28213cb6a6 | ||
|
|
4678124bb9 | ||
|
|
9774ccf7cd | ||
|
|
8cc87c3179 | ||
|
|
ad9671b870 | ||
|
|
0e9b9edae7 | ||
|
|
0058c08238 | ||
|
|
eaf23bf794 | ||
|
|
6d42eefad8 | ||
|
|
15139b8ef0 | ||
|
|
53c400a6ac | ||
|
|
76bdd24ec0 | ||
|
|
ebd8ea8244 | ||
|
|
672a287227 | ||
|
|
96e3e12bff | ||
|
|
a630bb314c | ||
|
|
8edf77e497 | ||
|
|
7c2991fa11 | ||
|
|
86958d2ddd | ||
|
|
7bc6fd2464 | ||
|
|
e8977414a2 | ||
|
|
d19587db9e | ||
|
|
99a9a52a23 | ||
|
|
ed45cae391 | ||
|
|
67a1de0d19 | ||
|
|
077de81a4c | ||
|
|
0ab0c99851 | ||
|
|
553350156d | ||
|
|
d41d4da3c5 | ||
|
|
844864fbae | ||
|
|
0601d6a411 | ||
|
|
575b22b1b7 | ||
|
|
5ce9bb5937 | ||
|
|
b265620bfb | ||
|
|
6c5b5645ae | ||
|
|
3bef0451e6 | ||
|
|
4d6a0680fa | ||
|
|
c76c22d51d | ||
|
|
2f9254d964 | ||
|
|
5e31867fbd | ||
|
|
dfdd3e4362 | ||
|
|
8eb0f56372 | ||
|
|
c5a8d8f32d | ||
|
|
3dcfb74fd4 | ||
|
|
f5d9c1089f | ||
|
|
8865588133 | ||
|
|
ddd495e5e3 | ||
|
|
9207113dcc | ||
|
|
679dd415bb | ||
|
|
1c7336c5d1 | ||
|
|
1c953ba57a | ||
|
|
932ccbdd48 | ||
|
|
1ea1eefcbb | ||
|
|
71c9a3dd04 | ||
|
|
b3162f22cb | ||
|
|
acf1b6dd22 | ||
|
|
b4b6eb771a | ||
|
|
a26fdf3934 | ||
|
|
df7625d422 | ||
|
|
705124ea6d | ||
|
|
44f2e6c10e | ||
|
|
a575d9ab2e | ||
|
|
6214a11ac1 | ||
|
|
ff589551c8 | ||
|
|
4b3eec91b9 | ||
|
|
8156d48086 | ||
|
|
46e7b70699 | ||
|
|
7646240580 | ||
|
|
0c18c6c67e | ||
|
|
6e99f76261 | ||
|
|
e5fabad7cc | ||
|
|
1b6d0781c2 | ||
|
|
7bd43519da | ||
|
|
746c3b3eba | ||
|
|
4be12ea09a | ||
|
|
f0d1d2c115 | ||
|
|
578c4b2f23 | ||
|
|
869e92b5c3 | ||
|
|
7ef6e3cf8d | ||
|
|
5a50307b48 | ||
|
|
e91171e302 | ||
|
|
2a0ee672c9 | ||
|
|
0776d9679d | ||
|
|
6ed92b14f6 | ||
|
|
37d42473d1 | ||
|
|
0bf8039dca | ||
|
|
1602001195 | ||
|
|
fea8a08e16 | ||
|
|
e40c3d2e7f | ||
|
|
78f1edb19f | ||
|
|
04ce861ea5 | ||
|
|
aaa1f954d4 | ||
|
|
2a5a9abd4b | ||
|
|
280b2358cd | ||
|
|
e854d0cf78 | ||
|
|
890e48d7fc | ||
|
|
8625c3ffc8 | ||
|
|
b0491a1a17 | ||
|
|
5819e3e072 | ||
|
|
635324e83e | ||
|
|
7cde47d4a8 | ||
|
|
f314ea4e30 | ||
|
|
8762a46d36 | ||
|
|
beff62e683 | ||
|
|
af8b38b0d1 | ||
|
|
aae91ad9ae | ||
|
|
de5dca1b79 | ||
|
|
0c244e50ee | ||
|
|
4e68a0ee17 | ||
|
|
7e486f7577 | ||
|
|
c2e3c54d39 | ||
|
|
5213602678 | ||
|
|
4910e6e42e | ||
|
|
6b3532b20b | ||
|
|
defbaec160 | ||
|
|
07b9098dfc | ||
|
|
bda8d9b8b1 | ||
|
|
e19202af79 | ||
|
|
ff2df541bb | ||
|
|
e58ff62d58 | ||
|
|
fa06e5cb7b |
42
Makefile
42
Makefile
@@ -50,7 +50,7 @@ endif
|
|||||||
|
|
||||||
include $(SRC_PATH)/rules.mak
|
include $(SRC_PATH)/rules.mak
|
||||||
|
|
||||||
GENERATED_HEADERS = config-host.h qemu-options.def
|
GENERATED_HEADERS = qemu-version.h config-host.h qemu-options.def
|
||||||
GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h qapi-event.h
|
GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h qapi-event.h
|
||||||
GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c qapi-event.c
|
GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c qapi-event.c
|
||||||
GENERATED_HEADERS += qmp-introspect.h
|
GENERATED_HEADERS += qmp-introspect.h
|
||||||
@@ -82,7 +82,7 @@ Makefile: ;
|
|||||||
configure: ;
|
configure: ;
|
||||||
|
|
||||||
.PHONY: all clean cscope distclean dvi html info install install-doc \
|
.PHONY: all clean cscope distclean dvi html info install install-doc \
|
||||||
pdf recurse-all speed test dist msi
|
pdf recurse-all speed test dist msi FORCE
|
||||||
|
|
||||||
$(call set-vpath, $(SRC_PATH))
|
$(call set-vpath, $(SRC_PATH))
|
||||||
|
|
||||||
@@ -117,7 +117,7 @@ endif
|
|||||||
|
|
||||||
-include $(SUBDIR_DEVICES_MAK_DEP)
|
-include $(SUBDIR_DEVICES_MAK_DEP)
|
||||||
|
|
||||||
%/config-devices.mak: default-configs/%.mak
|
%/config-devices.mak: default-configs/%.mak $(SRC_PATH)/scripts/make_device_config.sh
|
||||||
$(call quiet-command, \
|
$(call quiet-command, \
|
||||||
$(SHELL) $(SRC_PATH)/scripts/make_device_config.sh $< $*-config-devices.mak.d $@ > $@.tmp, " GEN $@.tmp")
|
$(SHELL) $(SRC_PATH)/scripts/make_device_config.sh $< $*-config-devices.mak.d $@ > $@.tmp, " GEN $@.tmp")
|
||||||
$(call quiet-command, if test -f $@; then \
|
$(call quiet-command, if test -f $@; then \
|
||||||
@@ -162,14 +162,34 @@ dummy := $(call unnest-vars,, \
|
|||||||
common-obj-m)
|
common-obj-m)
|
||||||
|
|
||||||
ifneq ($(wildcard config-host.mak),)
|
ifneq ($(wildcard config-host.mak),)
|
||||||
include $(SRC_PATH)/tests/Makefile
|
include $(SRC_PATH)/tests/Makefile.include
|
||||||
endif
|
endif
|
||||||
|
|
||||||
all: $(DOCS) $(TOOLS) $(HELPERS-y) recurse-all modules
|
all: $(DOCS) $(TOOLS) $(HELPERS-y) recurse-all modules
|
||||||
|
|
||||||
|
qemu-version.h: FORCE
|
||||||
|
$(call quiet-command, \
|
||||||
|
(cd $(SRC_PATH); \
|
||||||
|
printf '#define QEMU_PKGVERSION '; \
|
||||||
|
if test -n "$(PKGVERSION)"; then \
|
||||||
|
printf '"$(PKGVERSION)"\n'; \
|
||||||
|
else \
|
||||||
|
if test -d .git; then \
|
||||||
|
printf '" ('; \
|
||||||
|
git describe --match 'v*' 2>/dev/null | tr -d '\n'; \
|
||||||
|
if ! git diff-index --quiet HEAD &>/dev/null; then \
|
||||||
|
printf -- '-dirty'; \
|
||||||
|
fi; \
|
||||||
|
printf ')"\n'; \
|
||||||
|
else \
|
||||||
|
printf '""\n'; \
|
||||||
|
fi; \
|
||||||
|
fi) > $@.tmp)
|
||||||
|
$(call quiet-command, cmp --quiet $@ $@.tmp || mv $@.tmp $@)
|
||||||
|
|
||||||
config-host.h: config-host.h-timestamp
|
config-host.h: config-host.h-timestamp
|
||||||
config-host.h-timestamp: config-host.mak
|
config-host.h-timestamp: config-host.mak
|
||||||
qemu-options.def: $(SRC_PATH)/qemu-options.hx
|
qemu-options.def: $(SRC_PATH)/qemu-options.hx $(SRC_PATH)/scripts/hxtool
|
||||||
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $@")
|
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $@")
|
||||||
|
|
||||||
SUBDIR_RULES=$(patsubst %,subdir-%, $(TARGET_DIRS))
|
SUBDIR_RULES=$(patsubst %,subdir-%, $(TARGET_DIRS))
|
||||||
@@ -241,7 +261,7 @@ qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o libqemuutil.a libqemustub.a
|
|||||||
fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/9p-marshal.o fsdev/9p-iov-marshal.o libqemuutil.a libqemustub.a
|
fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/9p-marshal.o fsdev/9p-iov-marshal.o libqemuutil.a libqemustub.a
|
||||||
fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap
|
fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap
|
||||||
|
|
||||||
qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
|
qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx $(SRC_PATH)/scripts/hxtool
|
||||||
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $@")
|
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $@")
|
||||||
|
|
||||||
qemu-ga$(EXESUF): LIBS = $(LIBS_QGA)
|
qemu-ga$(EXESUF): LIBS = $(LIBS_QGA)
|
||||||
@@ -524,19 +544,19 @@ TEXIFLAG=$(if $(V),,--quiet)
|
|||||||
%.pdf: %.texi
|
%.pdf: %.texi
|
||||||
$(call quiet-command,texi2pdf $(TEXIFLAG) -I . $<," GEN $@")
|
$(call quiet-command,texi2pdf $(TEXIFLAG) -I . $<," GEN $@")
|
||||||
|
|
||||||
qemu-options.texi: $(SRC_PATH)/qemu-options.hx
|
qemu-options.texi: $(SRC_PATH)/qemu-options.hx $(SRC_PATH)/scripts/hxtool
|
||||||
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@," GEN $@")
|
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@," GEN $@")
|
||||||
|
|
||||||
qemu-monitor.texi: $(SRC_PATH)/hmp-commands.hx
|
qemu-monitor.texi: $(SRC_PATH)/hmp-commands.hx $(SRC_PATH)/scripts/hxtool
|
||||||
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@," GEN $@")
|
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@," GEN $@")
|
||||||
|
|
||||||
qemu-monitor-info.texi: $(SRC_PATH)/hmp-commands-info.hx
|
qemu-monitor-info.texi: $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/scripts/hxtool
|
||||||
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@," GEN $@")
|
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@," GEN $@")
|
||||||
|
|
||||||
qmp-commands.txt: $(SRC_PATH)/qmp-commands.hx
|
qmp-commands.txt: $(SRC_PATH)/qmp-commands.hx $(SRC_PATH)/scripts/hxtool
|
||||||
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -q < $< > $@," GEN $@")
|
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -q < $< > $@," GEN $@")
|
||||||
|
|
||||||
qemu-img-cmds.texi: $(SRC_PATH)/qemu-img-cmds.hx
|
qemu-img-cmds.texi: $(SRC_PATH)/qemu-img-cmds.hx $(SRC_PATH)/scripts/hxtool
|
||||||
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@," GEN $@")
|
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -t < $< > $@," GEN $@")
|
||||||
|
|
||||||
qemu.1: qemu-doc.texi qemu-options.texi qemu-monitor.texi qemu-monitor-info.texi
|
qemu.1: qemu-doc.texi qemu-options.texi qemu-monitor.texi qemu-monitor-info.texi
|
||||||
|
|||||||
@@ -206,13 +206,13 @@ endif
|
|||||||
gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/scripts/feature_to_c.sh
|
gdbstub-xml.c: $(TARGET_XML_FILES) $(SRC_PATH)/scripts/feature_to_c.sh
|
||||||
$(call quiet-command,rm -f $@ && $(SHELL) $(SRC_PATH)/scripts/feature_to_c.sh $@ $(TARGET_XML_FILES)," GEN $(TARGET_DIR)$@")
|
$(call quiet-command,rm -f $@ && $(SHELL) $(SRC_PATH)/scripts/feature_to_c.sh $@ $(TARGET_XML_FILES)," GEN $(TARGET_DIR)$@")
|
||||||
|
|
||||||
hmp-commands.h: $(SRC_PATH)/hmp-commands.hx
|
hmp-commands.h: $(SRC_PATH)/hmp-commands.hx $(SRC_PATH)/scripts/hxtool
|
||||||
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
|
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
|
||||||
|
|
||||||
hmp-commands-info.h: $(SRC_PATH)/hmp-commands-info.hx
|
hmp-commands-info.h: $(SRC_PATH)/hmp-commands-info.hx $(SRC_PATH)/scripts/hxtool
|
||||||
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
|
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
|
||||||
|
|
||||||
qmp-commands-old.h: $(SRC_PATH)/qmp-commands.hx
|
qmp-commands-old.h: $(SRC_PATH)/qmp-commands.hx $(SRC_PATH)/scripts/hxtool
|
||||||
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
|
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $(TARGET_DIR)$@")
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
|
|||||||
@@ -781,23 +781,22 @@ static int qpa_ctl_in (HWVoiceIn *hw, int cmd, ...)
|
|||||||
|
|
||||||
pa_threaded_mainloop_lock (g->mainloop);
|
pa_threaded_mainloop_lock (g->mainloop);
|
||||||
|
|
||||||
/* FIXME: use the upcoming "set_source_output_{volume,mute}" */
|
op = pa_context_set_source_output_volume (g->context,
|
||||||
op = pa_context_set_source_volume_by_index (g->context,
|
pa_stream_get_index (pa->stream),
|
||||||
pa_stream_get_device_index (pa->stream),
|
|
||||||
&v, NULL, NULL);
|
&v, NULL, NULL);
|
||||||
if (!op) {
|
if (!op) {
|
||||||
qpa_logerr (pa_context_errno (g->context),
|
qpa_logerr (pa_context_errno (g->context),
|
||||||
"set_source_volume() failed\n");
|
"set_source_output_volume() failed\n");
|
||||||
} else {
|
} else {
|
||||||
pa_operation_unref(op);
|
pa_operation_unref(op);
|
||||||
}
|
}
|
||||||
|
|
||||||
op = pa_context_set_source_mute_by_index (g->context,
|
op = pa_context_set_source_output_mute (g->context,
|
||||||
pa_stream_get_index (pa->stream),
|
pa_stream_get_index (pa->stream),
|
||||||
sw->vol.mute, NULL, NULL);
|
sw->vol.mute, NULL, NULL);
|
||||||
if (!op) {
|
if (!op) {
|
||||||
qpa_logerr (pa_context_errno (g->context),
|
qpa_logerr (pa_context_errno (g->context),
|
||||||
"set_source_mute() failed\n");
|
"set_source_output_mute() failed\n");
|
||||||
} else {
|
} else {
|
||||||
pa_operation_unref (op);
|
pa_operation_unref (op);
|
||||||
}
|
}
|
||||||
|
|||||||
2
block.c
2
block.c
@@ -1018,7 +1018,7 @@ static int bdrv_open_common(BlockDriverState *bs, BdrvChild *file,
|
|||||||
|
|
||||||
assert(bdrv_opt_mem_align(bs) != 0);
|
assert(bdrv_opt_mem_align(bs) != 0);
|
||||||
assert(bdrv_min_mem_align(bs) != 0);
|
assert(bdrv_min_mem_align(bs) != 0);
|
||||||
assert((bs->request_alignment != 0) || bdrv_is_sg(bs));
|
assert(is_power_of_2(bs->request_alignment) || bdrv_is_sg(bs));
|
||||||
|
|
||||||
qemu_opts_del(opts);
|
qemu_opts_del(opts);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -103,11 +103,11 @@ static int coroutine_fn blkreplay_co_writev(BlockDriverState *bs,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int coroutine_fn blkreplay_co_write_zeroes(BlockDriverState *bs,
|
static int coroutine_fn blkreplay_co_pwrite_zeroes(BlockDriverState *bs,
|
||||||
int64_t sector_num, int nb_sectors, BdrvRequestFlags flags)
|
int64_t offset, int count, BdrvRequestFlags flags)
|
||||||
{
|
{
|
||||||
uint64_t reqid = request_id++;
|
uint64_t reqid = request_id++;
|
||||||
int ret = bdrv_co_write_zeroes(bs->file->bs, sector_num, nb_sectors, flags);
|
int ret = bdrv_co_pwrite_zeroes(bs->file->bs, offset, count, flags);
|
||||||
block_request_create(reqid, bs, qemu_coroutine_self());
|
block_request_create(reqid, bs, qemu_coroutine_self());
|
||||||
qemu_coroutine_yield();
|
qemu_coroutine_yield();
|
||||||
|
|
||||||
@@ -147,7 +147,7 @@ static BlockDriver bdrv_blkreplay = {
|
|||||||
.bdrv_co_readv = blkreplay_co_readv,
|
.bdrv_co_readv = blkreplay_co_readv,
|
||||||
.bdrv_co_writev = blkreplay_co_writev,
|
.bdrv_co_writev = blkreplay_co_writev,
|
||||||
|
|
||||||
.bdrv_co_write_zeroes = blkreplay_co_write_zeroes,
|
.bdrv_co_pwrite_zeroes = blkreplay_co_pwrite_zeroes,
|
||||||
.bdrv_co_discard = blkreplay_co_discard,
|
.bdrv_co_discard = blkreplay_co_discard,
|
||||||
.bdrv_co_flush = blkreplay_co_flush,
|
.bdrv_co_flush = blkreplay_co_flush,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -32,7 +32,6 @@
|
|||||||
#ifdef CONFIG_BZIP2
|
#ifdef CONFIG_BZIP2
|
||||||
#include <bzlib.h>
|
#include <bzlib.h>
|
||||||
#endif
|
#endif
|
||||||
#include <glib.h>
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
/* Limit chunk sizes to prevent unreasonable amounts of memory being used
|
/* Limit chunk sizes to prevent unreasonable amounts of memory being used
|
||||||
|
|||||||
@@ -454,14 +454,12 @@ static void qemu_gluster_reopen_abort(BDRVReopenState *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_GLUSTERFS_ZEROFILL
|
#ifdef CONFIG_GLUSTERFS_ZEROFILL
|
||||||
static coroutine_fn int qemu_gluster_co_write_zeroes(BlockDriverState *bs,
|
static coroutine_fn int qemu_gluster_co_pwrite_zeroes(BlockDriverState *bs,
|
||||||
int64_t sector_num, int nb_sectors, BdrvRequestFlags flags)
|
int64_t offset, int size, BdrvRequestFlags flags)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
GlusterAIOCB acb;
|
GlusterAIOCB acb;
|
||||||
BDRVGlusterState *s = bs->opaque;
|
BDRVGlusterState *s = bs->opaque;
|
||||||
off_t size = nb_sectors * BDRV_SECTOR_SIZE;
|
|
||||||
off_t offset = sector_num * BDRV_SECTOR_SIZE;
|
|
||||||
|
|
||||||
acb.size = size;
|
acb.size = size;
|
||||||
acb.ret = 0;
|
acb.ret = 0;
|
||||||
@@ -769,7 +767,7 @@ static BlockDriver bdrv_gluster = {
|
|||||||
.bdrv_co_discard = qemu_gluster_co_discard,
|
.bdrv_co_discard = qemu_gluster_co_discard,
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_GLUSTERFS_ZEROFILL
|
#ifdef CONFIG_GLUSTERFS_ZEROFILL
|
||||||
.bdrv_co_write_zeroes = qemu_gluster_co_write_zeroes,
|
.bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes,
|
||||||
#endif
|
#endif
|
||||||
.create_opts = &qemu_gluster_create_opts,
|
.create_opts = &qemu_gluster_create_opts,
|
||||||
};
|
};
|
||||||
@@ -796,7 +794,7 @@ static BlockDriver bdrv_gluster_tcp = {
|
|||||||
.bdrv_co_discard = qemu_gluster_co_discard,
|
.bdrv_co_discard = qemu_gluster_co_discard,
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_GLUSTERFS_ZEROFILL
|
#ifdef CONFIG_GLUSTERFS_ZEROFILL
|
||||||
.bdrv_co_write_zeroes = qemu_gluster_co_write_zeroes,
|
.bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes,
|
||||||
#endif
|
#endif
|
||||||
.create_opts = &qemu_gluster_create_opts,
|
.create_opts = &qemu_gluster_create_opts,
|
||||||
};
|
};
|
||||||
@@ -823,7 +821,7 @@ static BlockDriver bdrv_gluster_unix = {
|
|||||||
.bdrv_co_discard = qemu_gluster_co_discard,
|
.bdrv_co_discard = qemu_gluster_co_discard,
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_GLUSTERFS_ZEROFILL
|
#ifdef CONFIG_GLUSTERFS_ZEROFILL
|
||||||
.bdrv_co_write_zeroes = qemu_gluster_co_write_zeroes,
|
.bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes,
|
||||||
#endif
|
#endif
|
||||||
.create_opts = &qemu_gluster_create_opts,
|
.create_opts = &qemu_gluster_create_opts,
|
||||||
};
|
};
|
||||||
@@ -850,7 +848,7 @@ static BlockDriver bdrv_gluster_rdma = {
|
|||||||
.bdrv_co_discard = qemu_gluster_co_discard,
|
.bdrv_co_discard = qemu_gluster_co_discard,
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_GLUSTERFS_ZEROFILL
|
#ifdef CONFIG_GLUSTERFS_ZEROFILL
|
||||||
.bdrv_co_write_zeroes = qemu_gluster_co_write_zeroes,
|
.bdrv_co_pwrite_zeroes = qemu_gluster_co_pwrite_zeroes,
|
||||||
#endif
|
#endif
|
||||||
.create_opts = &qemu_gluster_create_opts,
|
.create_opts = &qemu_gluster_create_opts,
|
||||||
};
|
};
|
||||||
|
|||||||
181
block/io.c
181
block/io.c
@@ -42,8 +42,8 @@ static BlockAIOCB *bdrv_co_aio_rw_vector(BlockDriverState *bs,
|
|||||||
void *opaque,
|
void *opaque,
|
||||||
bool is_write);
|
bool is_write);
|
||||||
static void coroutine_fn bdrv_co_do_rw(void *opaque);
|
static void coroutine_fn bdrv_co_do_rw(void *opaque);
|
||||||
static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs,
|
static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
|
||||||
int64_t sector_num, int nb_sectors, BdrvRequestFlags flags);
|
int64_t offset, int count, BdrvRequestFlags flags);
|
||||||
|
|
||||||
static void bdrv_parent_drained_begin(BlockDriverState *bs)
|
static void bdrv_parent_drained_begin(BlockDriverState *bs)
|
||||||
{
|
{
|
||||||
@@ -620,18 +620,25 @@ int bdrv_write(BlockDriverState *bs, int64_t sector_num,
|
|||||||
return bdrv_rw_co(bs, sector_num, (uint8_t *)buf, nb_sectors, true, 0);
|
return bdrv_rw_co(bs, sector_num, (uint8_t *)buf, nb_sectors, true, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int bdrv_write_zeroes(BlockDriverState *bs, int64_t sector_num,
|
int bdrv_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
|
||||||
int nb_sectors, BdrvRequestFlags flags)
|
int count, BdrvRequestFlags flags)
|
||||||
{
|
{
|
||||||
return bdrv_rw_co(bs, sector_num, NULL, nb_sectors, true,
|
QEMUIOVector qiov;
|
||||||
BDRV_REQ_ZERO_WRITE | flags);
|
struct iovec iov = {
|
||||||
|
.iov_base = NULL,
|
||||||
|
.iov_len = count,
|
||||||
|
};
|
||||||
|
|
||||||
|
qemu_iovec_init_external(&qiov, &iov, 1);
|
||||||
|
return bdrv_prwv_co(bs, offset, &qiov, true,
|
||||||
|
BDRV_REQ_ZERO_WRITE | flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Completely zero out a block device with the help of bdrv_write_zeroes.
|
* Completely zero out a block device with the help of bdrv_pwrite_zeroes.
|
||||||
* The operation is sped up by checking the block status and only writing
|
* The operation is sped up by checking the block status and only writing
|
||||||
* zeroes to the device if they currently do not return zeroes. Optional
|
* zeroes to the device if they currently do not return zeroes. Optional
|
||||||
* flags are passed through to bdrv_write_zeroes (e.g. BDRV_REQ_MAY_UNMAP,
|
* flags are passed through to bdrv_pwrite_zeroes (e.g. BDRV_REQ_MAY_UNMAP,
|
||||||
* BDRV_REQ_FUA).
|
* BDRV_REQ_FUA).
|
||||||
*
|
*
|
||||||
* Returns < 0 on error, 0 on success. For error codes see bdrv_write().
|
* Returns < 0 on error, 0 on success. For error codes see bdrv_write().
|
||||||
@@ -662,7 +669,8 @@ int bdrv_make_zero(BlockDriverState *bs, BdrvRequestFlags flags)
|
|||||||
sector_num += n;
|
sector_num += n;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
ret = bdrv_write_zeroes(bs, sector_num, n, flags);
|
ret = bdrv_pwrite_zeroes(bs, sector_num << BDRV_SECTOR_BITS,
|
||||||
|
n << BDRV_SECTOR_BITS, flags);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
error_report("error writing zeroes at sector %" PRId64 ": %s",
|
error_report("error writing zeroes at sector %" PRId64 ": %s",
|
||||||
sector_num, strerror(-ret));
|
sector_num, strerror(-ret));
|
||||||
@@ -808,7 +816,9 @@ static int coroutine_fn bdrv_driver_pwritev(BlockDriverState *bs,
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (drv->bdrv_co_pwritev) {
|
if (drv->bdrv_co_pwritev) {
|
||||||
ret = drv->bdrv_co_pwritev(bs, offset, bytes, qiov, flags);
|
ret = drv->bdrv_co_pwritev(bs, offset, bytes, qiov,
|
||||||
|
flags & bs->supported_write_flags);
|
||||||
|
flags &= ~bs->supported_write_flags;
|
||||||
goto emulate_flags;
|
goto emulate_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -893,10 +903,12 @@ static int coroutine_fn bdrv_co_do_copy_on_readv(BlockDriverState *bs,
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drv->bdrv_co_write_zeroes &&
|
if (drv->bdrv_co_pwrite_zeroes &&
|
||||||
buffer_is_zero(bounce_buffer, iov.iov_len)) {
|
buffer_is_zero(bounce_buffer, iov.iov_len)) {
|
||||||
ret = bdrv_co_do_write_zeroes(bs, cluster_sector_num,
|
ret = bdrv_co_do_pwrite_zeroes(bs,
|
||||||
cluster_nb_sectors, 0);
|
cluster_sector_num * BDRV_SECTOR_SIZE,
|
||||||
|
cluster_nb_sectors * BDRV_SECTOR_SIZE,
|
||||||
|
0);
|
||||||
} else {
|
} else {
|
||||||
/* This does not change the data on the disk, it is not necessary
|
/* This does not change the data on the disk, it is not necessary
|
||||||
* to flush even in cache=writethrough mode.
|
* to flush even in cache=writethrough mode.
|
||||||
@@ -1110,36 +1122,40 @@ int coroutine_fn bdrv_co_readv(BlockDriverState *bs, int64_t sector_num,
|
|||||||
|
|
||||||
#define MAX_WRITE_ZEROES_BOUNCE_BUFFER 32768
|
#define MAX_WRITE_ZEROES_BOUNCE_BUFFER 32768
|
||||||
|
|
||||||
static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs,
|
static int coroutine_fn bdrv_co_do_pwrite_zeroes(BlockDriverState *bs,
|
||||||
int64_t sector_num, int nb_sectors, BdrvRequestFlags flags)
|
int64_t offset, int count, BdrvRequestFlags flags)
|
||||||
{
|
{
|
||||||
BlockDriver *drv = bs->drv;
|
BlockDriver *drv = bs->drv;
|
||||||
QEMUIOVector qiov;
|
QEMUIOVector qiov;
|
||||||
struct iovec iov = {0};
|
struct iovec iov = {0};
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
bool need_flush = false;
|
bool need_flush = false;
|
||||||
|
int head = 0;
|
||||||
|
int tail = 0;
|
||||||
|
|
||||||
int max_write_zeroes = MIN_NON_ZERO(bs->bl.max_write_zeroes,
|
int max_write_zeroes = MIN_NON_ZERO(bs->bl.max_pwrite_zeroes, INT_MAX);
|
||||||
BDRV_REQUEST_MAX_SECTORS);
|
int alignment = MAX(bs->bl.pwrite_zeroes_alignment ?: 1,
|
||||||
|
bs->request_alignment);
|
||||||
|
|
||||||
while (nb_sectors > 0 && !ret) {
|
assert(is_power_of_2(alignment));
|
||||||
int num = nb_sectors;
|
head = offset & (alignment - 1);
|
||||||
|
tail = (offset + count) & (alignment - 1);
|
||||||
|
max_write_zeroes &= ~(alignment - 1);
|
||||||
|
|
||||||
|
while (count > 0 && !ret) {
|
||||||
|
int num = count;
|
||||||
|
|
||||||
/* Align request. Block drivers can expect the "bulk" of the request
|
/* Align request. Block drivers can expect the "bulk" of the request
|
||||||
* to be aligned.
|
* to be aligned, and that unaligned requests do not cross cluster
|
||||||
|
* boundaries.
|
||||||
*/
|
*/
|
||||||
if (bs->bl.write_zeroes_alignment
|
if (head) {
|
||||||
&& num > bs->bl.write_zeroes_alignment) {
|
/* Make a small request up to the first aligned sector. */
|
||||||
if (sector_num % bs->bl.write_zeroes_alignment != 0) {
|
num = MIN(count, alignment - head);
|
||||||
/* Make a small request up to the first aligned sector. */
|
head = 0;
|
||||||
num = bs->bl.write_zeroes_alignment;
|
} else if (tail && num > alignment) {
|
||||||
num -= sector_num % bs->bl.write_zeroes_alignment;
|
/* Shorten the request to the last aligned sector. */
|
||||||
} else if ((sector_num + num) % bs->bl.write_zeroes_alignment != 0) {
|
num -= tail;
|
||||||
/* Shorten the request to the last aligned sector. num cannot
|
|
||||||
* underflow because num > bs->bl.write_zeroes_alignment.
|
|
||||||
*/
|
|
||||||
num -= (sector_num + num) % bs->bl.write_zeroes_alignment;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* limit request size */
|
/* limit request size */
|
||||||
@@ -1149,9 +1165,9 @@ static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs,
|
|||||||
|
|
||||||
ret = -ENOTSUP;
|
ret = -ENOTSUP;
|
||||||
/* First try the efficient write zeroes operation */
|
/* First try the efficient write zeroes operation */
|
||||||
if (drv->bdrv_co_write_zeroes) {
|
if (drv->bdrv_co_pwrite_zeroes) {
|
||||||
ret = drv->bdrv_co_write_zeroes(bs, sector_num, num,
|
ret = drv->bdrv_co_pwrite_zeroes(bs, offset, num,
|
||||||
flags & bs->supported_zero_flags);
|
flags & bs->supported_zero_flags);
|
||||||
if (ret != -ENOTSUP && (flags & BDRV_REQ_FUA) &&
|
if (ret != -ENOTSUP && (flags & BDRV_REQ_FUA) &&
|
||||||
!(bs->supported_zero_flags & BDRV_REQ_FUA)) {
|
!(bs->supported_zero_flags & BDRV_REQ_FUA)) {
|
||||||
need_flush = true;
|
need_flush = true;
|
||||||
@@ -1173,33 +1189,31 @@ static int coroutine_fn bdrv_co_do_write_zeroes(BlockDriverState *bs,
|
|||||||
write_flags &= ~BDRV_REQ_FUA;
|
write_flags &= ~BDRV_REQ_FUA;
|
||||||
need_flush = true;
|
need_flush = true;
|
||||||
}
|
}
|
||||||
num = MIN(num, max_xfer_len);
|
num = MIN(num, max_xfer_len << BDRV_SECTOR_BITS);
|
||||||
iov.iov_len = num * BDRV_SECTOR_SIZE;
|
iov.iov_len = num;
|
||||||
if (iov.iov_base == NULL) {
|
if (iov.iov_base == NULL) {
|
||||||
iov.iov_base = qemu_try_blockalign(bs, num * BDRV_SECTOR_SIZE);
|
iov.iov_base = qemu_try_blockalign(bs, num);
|
||||||
if (iov.iov_base == NULL) {
|
if (iov.iov_base == NULL) {
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
memset(iov.iov_base, 0, num * BDRV_SECTOR_SIZE);
|
memset(iov.iov_base, 0, num);
|
||||||
}
|
}
|
||||||
qemu_iovec_init_external(&qiov, &iov, 1);
|
qemu_iovec_init_external(&qiov, &iov, 1);
|
||||||
|
|
||||||
ret = bdrv_driver_pwritev(bs, sector_num * BDRV_SECTOR_SIZE,
|
ret = bdrv_driver_pwritev(bs, offset, num, &qiov, write_flags);
|
||||||
num * BDRV_SECTOR_SIZE, &qiov,
|
|
||||||
write_flags);
|
|
||||||
|
|
||||||
/* Keep bounce buffer around if it is big enough for all
|
/* Keep bounce buffer around if it is big enough for all
|
||||||
* all future requests.
|
* all future requests.
|
||||||
*/
|
*/
|
||||||
if (num < max_xfer_len) {
|
if (num < max_xfer_len << BDRV_SECTOR_BITS) {
|
||||||
qemu_vfree(iov.iov_base);
|
qemu_vfree(iov.iov_base);
|
||||||
iov.iov_base = NULL;
|
iov.iov_base = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sector_num += num;
|
offset += num;
|
||||||
nb_sectors -= num;
|
count -= num;
|
||||||
}
|
}
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
@@ -1237,7 +1251,7 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs,
|
|||||||
ret = notifier_with_return_list_notify(&bs->before_write_notifiers, req);
|
ret = notifier_with_return_list_notify(&bs->before_write_notifiers, req);
|
||||||
|
|
||||||
if (!ret && bs->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF &&
|
if (!ret && bs->detect_zeroes != BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF &&
|
||||||
!(flags & BDRV_REQ_ZERO_WRITE) && drv->bdrv_co_write_zeroes &&
|
!(flags & BDRV_REQ_ZERO_WRITE) && drv->bdrv_co_pwrite_zeroes &&
|
||||||
qemu_iovec_is_zero(qiov)) {
|
qemu_iovec_is_zero(qiov)) {
|
||||||
flags |= BDRV_REQ_ZERO_WRITE;
|
flags |= BDRV_REQ_ZERO_WRITE;
|
||||||
if (bs->detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP) {
|
if (bs->detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP) {
|
||||||
@@ -1249,7 +1263,8 @@ static int coroutine_fn bdrv_aligned_pwritev(BlockDriverState *bs,
|
|||||||
/* Do nothing, write notifier decided to fail this request */
|
/* Do nothing, write notifier decided to fail this request */
|
||||||
} else if (flags & BDRV_REQ_ZERO_WRITE) {
|
} else if (flags & BDRV_REQ_ZERO_WRITE) {
|
||||||
bdrv_debug_event(bs, BLKDBG_PWRITEV_ZERO);
|
bdrv_debug_event(bs, BLKDBG_PWRITEV_ZERO);
|
||||||
ret = bdrv_co_do_write_zeroes(bs, sector_num, nb_sectors, flags);
|
ret = bdrv_co_do_pwrite_zeroes(bs, sector_num << BDRV_SECTOR_BITS,
|
||||||
|
nb_sectors << BDRV_SECTOR_BITS, flags);
|
||||||
} else {
|
} else {
|
||||||
bdrv_debug_event(bs, BLKDBG_PWRITEV);
|
bdrv_debug_event(bs, BLKDBG_PWRITEV);
|
||||||
ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, flags);
|
ret = bdrv_driver_pwritev(bs, offset, bytes, qiov, flags);
|
||||||
@@ -1427,6 +1442,14 @@ int coroutine_fn bdrv_co_pwritev(BlockDriverState *bs,
|
|||||||
|
|
||||||
bytes += offset & (align - 1);
|
bytes += offset & (align - 1);
|
||||||
offset = offset & ~(align - 1);
|
offset = offset & ~(align - 1);
|
||||||
|
|
||||||
|
/* We have read the tail already if the request is smaller
|
||||||
|
* than one aligned block.
|
||||||
|
*/
|
||||||
|
if (bytes < align) {
|
||||||
|
qemu_iovec_add(&local_qiov, head_buf + bytes, align - bytes);
|
||||||
|
bytes = align;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((offset + bytes) & (align - 1)) {
|
if ((offset + bytes) & (align - 1)) {
|
||||||
@@ -1502,18 +1525,18 @@ int coroutine_fn bdrv_co_writev(BlockDriverState *bs, int64_t sector_num,
|
|||||||
return bdrv_co_do_writev(bs, sector_num, nb_sectors, qiov, 0);
|
return bdrv_co_do_writev(bs, sector_num, nb_sectors, qiov, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int coroutine_fn bdrv_co_write_zeroes(BlockDriverState *bs,
|
int coroutine_fn bdrv_co_pwrite_zeroes(BlockDriverState *bs,
|
||||||
int64_t sector_num, int nb_sectors,
|
int64_t offset, int count,
|
||||||
BdrvRequestFlags flags)
|
BdrvRequestFlags flags)
|
||||||
{
|
{
|
||||||
trace_bdrv_co_write_zeroes(bs, sector_num, nb_sectors, flags);
|
trace_bdrv_co_pwrite_zeroes(bs, offset, count, flags);
|
||||||
|
|
||||||
if (!(bs->open_flags & BDRV_O_UNMAP)) {
|
if (!(bs->open_flags & BDRV_O_UNMAP)) {
|
||||||
flags &= ~BDRV_REQ_MAY_UNMAP;
|
flags &= ~BDRV_REQ_MAY_UNMAP;
|
||||||
}
|
}
|
||||||
|
|
||||||
return bdrv_co_do_writev(bs, sector_num, nb_sectors, NULL,
|
return bdrv_co_pwritev(bs, offset, count, NULL,
|
||||||
BDRV_REQ_ZERO_WRITE | flags);
|
BDRV_REQ_ZERO_WRITE | flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct BdrvCoGetBlockStatusData {
|
typedef struct BdrvCoGetBlockStatusData {
|
||||||
@@ -1865,17 +1888,6 @@ BlockAIOCB *bdrv_aio_writev(BlockDriverState *bs, int64_t sector_num,
|
|||||||
cb, opaque, true);
|
cb, opaque, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockAIOCB *bdrv_aio_write_zeroes(BlockDriverState *bs,
|
|
||||||
int64_t sector_num, int nb_sectors, BdrvRequestFlags flags,
|
|
||||||
BlockCompletionFunc *cb, void *opaque)
|
|
||||||
{
|
|
||||||
trace_bdrv_aio_write_zeroes(bs, sector_num, nb_sectors, flags, opaque);
|
|
||||||
|
|
||||||
return bdrv_co_aio_rw_vector(bs, sector_num, NULL, nb_sectors,
|
|
||||||
BDRV_REQ_ZERO_WRITE | flags,
|
|
||||||
cb, opaque, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void bdrv_aio_cancel(BlockAIOCB *acb)
|
void bdrv_aio_cancel(BlockAIOCB *acb)
|
||||||
{
|
{
|
||||||
qemu_aio_ref(acb);
|
qemu_aio_ref(acb);
|
||||||
@@ -1905,6 +1917,27 @@ void bdrv_aio_cancel_async(BlockAIOCB *acb)
|
|||||||
/**************************************************************/
|
/**************************************************************/
|
||||||
/* async block device emulation */
|
/* async block device emulation */
|
||||||
|
|
||||||
|
typedef struct BlockRequest {
|
||||||
|
union {
|
||||||
|
/* Used during read, write, trim */
|
||||||
|
struct {
|
||||||
|
int64_t sector;
|
||||||
|
int nb_sectors;
|
||||||
|
int flags;
|
||||||
|
QEMUIOVector *qiov;
|
||||||
|
};
|
||||||
|
/* Used during ioctl */
|
||||||
|
struct {
|
||||||
|
int req;
|
||||||
|
void *buf;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
BlockCompletionFunc *cb;
|
||||||
|
void *opaque;
|
||||||
|
|
||||||
|
int error;
|
||||||
|
} BlockRequest;
|
||||||
|
|
||||||
typedef struct BlockAIOCBCoroutine {
|
typedef struct BlockAIOCBCoroutine {
|
||||||
BlockAIOCB common;
|
BlockAIOCB common;
|
||||||
BlockRequest req;
|
BlockRequest req;
|
||||||
@@ -2309,19 +2342,6 @@ int bdrv_discard(BlockDriverState *bs, int64_t sector_num, int nb_sectors)
|
|||||||
return rwco.ret;
|
return rwco.ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
CoroutineIOCompletion *co;
|
|
||||||
QEMUBH *bh;
|
|
||||||
} BdrvIoctlCompletionData;
|
|
||||||
|
|
||||||
static void bdrv_ioctl_bh_cb(void *opaque)
|
|
||||||
{
|
|
||||||
BdrvIoctlCompletionData *data = opaque;
|
|
||||||
|
|
||||||
bdrv_co_io_em_complete(data->co, -ENOTSUP);
|
|
||||||
qemu_bh_delete(data->bh);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int bdrv_co_do_ioctl(BlockDriverState *bs, int req, void *buf)
|
static int bdrv_co_do_ioctl(BlockDriverState *bs, int req, void *buf)
|
||||||
{
|
{
|
||||||
BlockDriver *drv = bs->drv;
|
BlockDriver *drv = bs->drv;
|
||||||
@@ -2339,11 +2359,8 @@ static int bdrv_co_do_ioctl(BlockDriverState *bs, int req, void *buf)
|
|||||||
|
|
||||||
acb = drv->bdrv_aio_ioctl(bs, req, buf, bdrv_co_io_em_complete, &co);
|
acb = drv->bdrv_aio_ioctl(bs, req, buf, bdrv_co_io_em_complete, &co);
|
||||||
if (!acb) {
|
if (!acb) {
|
||||||
BdrvIoctlCompletionData *data = g_new(BdrvIoctlCompletionData, 1);
|
co.ret = -ENOTSUP;
|
||||||
data->bh = aio_bh_new(bdrv_get_aio_context(bs),
|
goto out;
|
||||||
bdrv_ioctl_bh_cb, data);
|
|
||||||
data->co = &co;
|
|
||||||
qemu_bh_schedule(data->bh);
|
|
||||||
}
|
}
|
||||||
qemu_coroutine_yield();
|
qemu_coroutine_yield();
|
||||||
out:
|
out:
|
||||||
|
|||||||
@@ -401,18 +401,26 @@ static int64_t sector_qemu2lun(int64_t sector, IscsiLun *iscsilun)
|
|||||||
return sector * BDRV_SECTOR_SIZE / iscsilun->block_size;
|
return sector * BDRV_SECTOR_SIZE / iscsilun->block_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_request_lun_aligned(int64_t sector_num, int nb_sectors,
|
static bool is_byte_request_lun_aligned(int64_t offset, int count,
|
||||||
IscsiLun *iscsilun)
|
IscsiLun *iscsilun)
|
||||||
{
|
{
|
||||||
if ((sector_num * BDRV_SECTOR_SIZE) % iscsilun->block_size ||
|
if (offset % iscsilun->block_size || count % iscsilun->block_size) {
|
||||||
(nb_sectors * BDRV_SECTOR_SIZE) % iscsilun->block_size) {
|
error_report("iSCSI misaligned request: "
|
||||||
error_report("iSCSI misaligned request: "
|
"iscsilun->block_size %u, offset %" PRIi64
|
||||||
"iscsilun->block_size %u, sector_num %" PRIi64
|
", count %d",
|
||||||
", nb_sectors %d",
|
iscsilun->block_size, offset, count);
|
||||||
iscsilun->block_size, sector_num, nb_sectors);
|
return false;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
return 1;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool is_sector_request_lun_aligned(int64_t sector_num, int nb_sectors,
|
||||||
|
IscsiLun *iscsilun)
|
||||||
|
{
|
||||||
|
assert(nb_sectors < BDRV_REQUEST_MAX_SECTORS);
|
||||||
|
return is_byte_request_lun_aligned(sector_num << BDRV_SECTOR_BITS,
|
||||||
|
nb_sectors << BDRV_SECTOR_BITS,
|
||||||
|
iscsilun);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long *iscsi_allocationmap_init(IscsiLun *iscsilun)
|
static unsigned long *iscsi_allocationmap_init(IscsiLun *iscsilun)
|
||||||
@@ -461,7 +469,7 @@ iscsi_co_writev_flags(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
|
|||||||
if (fua) {
|
if (fua) {
|
||||||
assert(iscsilun->dpofua);
|
assert(iscsilun->dpofua);
|
||||||
}
|
}
|
||||||
if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
|
if (!is_sector_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -541,7 +549,7 @@ static int64_t coroutine_fn iscsi_co_get_block_status(BlockDriverState *bs,
|
|||||||
|
|
||||||
iscsi_co_init_iscsitask(iscsilun, &iTask);
|
iscsi_co_init_iscsitask(iscsilun, &iTask);
|
||||||
|
|
||||||
if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
|
if (!is_sector_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -638,7 +646,7 @@ static int coroutine_fn iscsi_co_readv(BlockDriverState *bs,
|
|||||||
uint64_t lba;
|
uint64_t lba;
|
||||||
uint32_t num_sectors;
|
uint32_t num_sectors;
|
||||||
|
|
||||||
if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
|
if (!is_sector_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -926,7 +934,7 @@ coroutine_fn iscsi_co_discard(BlockDriverState *bs, int64_t sector_num,
|
|||||||
struct IscsiTask iTask;
|
struct IscsiTask iTask;
|
||||||
struct unmap_list list;
|
struct unmap_list list;
|
||||||
|
|
||||||
if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
|
if (!is_sector_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -977,8 +985,8 @@ retry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
coroutine_fn iscsi_co_write_zeroes(BlockDriverState *bs, int64_t sector_num,
|
coroutine_fn iscsi_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
|
||||||
int nb_sectors, BdrvRequestFlags flags)
|
int count, BdrvRequestFlags flags)
|
||||||
{
|
{
|
||||||
IscsiLun *iscsilun = bs->opaque;
|
IscsiLun *iscsilun = bs->opaque;
|
||||||
struct IscsiTask iTask;
|
struct IscsiTask iTask;
|
||||||
@@ -986,8 +994,8 @@ coroutine_fn iscsi_co_write_zeroes(BlockDriverState *bs, int64_t sector_num,
|
|||||||
uint32_t nb_blocks;
|
uint32_t nb_blocks;
|
||||||
bool use_16_for_ws = iscsilun->use_16_for_rw;
|
bool use_16_for_ws = iscsilun->use_16_for_rw;
|
||||||
|
|
||||||
if (!is_request_lun_aligned(sector_num, nb_sectors, iscsilun)) {
|
if (!is_byte_request_lun_aligned(offset, count, iscsilun)) {
|
||||||
return -EINVAL;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags & BDRV_REQ_MAY_UNMAP) {
|
if (flags & BDRV_REQ_MAY_UNMAP) {
|
||||||
@@ -1008,8 +1016,8 @@ coroutine_fn iscsi_co_write_zeroes(BlockDriverState *bs, int64_t sector_num,
|
|||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
lba = sector_qemu2lun(sector_num, iscsilun);
|
lba = offset / iscsilun->block_size;
|
||||||
nb_blocks = sector_qemu2lun(nb_sectors, iscsilun);
|
nb_blocks = count / iscsilun->block_size;
|
||||||
|
|
||||||
if (iscsilun->zeroblock == NULL) {
|
if (iscsilun->zeroblock == NULL) {
|
||||||
iscsilun->zeroblock = g_try_malloc0(iscsilun->block_size);
|
iscsilun->zeroblock = g_try_malloc0(iscsilun->block_size);
|
||||||
@@ -1065,9 +1073,11 @@ retry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (flags & BDRV_REQ_MAY_UNMAP) {
|
if (flags & BDRV_REQ_MAY_UNMAP) {
|
||||||
iscsi_allocationmap_clear(iscsilun, sector_num, nb_sectors);
|
iscsi_allocationmap_clear(iscsilun, offset >> BDRV_SECTOR_BITS,
|
||||||
|
count >> BDRV_SECTOR_BITS);
|
||||||
} else {
|
} else {
|
||||||
iscsi_allocationmap_set(iscsilun, sector_num, nb_sectors);
|
iscsi_allocationmap_set(iscsilun, offset >> BDRV_SECTOR_BITS,
|
||||||
|
count >> BDRV_SECTOR_BITS);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1711,15 +1721,19 @@ static void iscsi_refresh_limits(BlockDriverState *bs, Error **errp)
|
|||||||
}
|
}
|
||||||
bs->bl.discard_alignment =
|
bs->bl.discard_alignment =
|
||||||
sector_limits_lun2qemu(iscsilun->bl.opt_unmap_gran, iscsilun);
|
sector_limits_lun2qemu(iscsilun->bl.opt_unmap_gran, iscsilun);
|
||||||
|
} else {
|
||||||
|
bs->bl.discard_alignment = iscsilun->block_size >> BDRV_SECTOR_BITS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iscsilun->bl.max_ws_len < 0xffffffff) {
|
if (iscsilun->bl.max_ws_len < 0xffffffff / iscsilun->block_size) {
|
||||||
bs->bl.max_write_zeroes =
|
bs->bl.max_pwrite_zeroes =
|
||||||
sector_limits_lun2qemu(iscsilun->bl.max_ws_len, iscsilun);
|
iscsilun->bl.max_ws_len * iscsilun->block_size;
|
||||||
}
|
}
|
||||||
if (iscsilun->lbp.lbpws) {
|
if (iscsilun->lbp.lbpws) {
|
||||||
bs->bl.write_zeroes_alignment =
|
bs->bl.pwrite_zeroes_alignment =
|
||||||
sector_limits_lun2qemu(iscsilun->bl.opt_unmap_gran, iscsilun);
|
iscsilun->bl.opt_unmap_gran * iscsilun->block_size;
|
||||||
|
} else {
|
||||||
|
bs->bl.pwrite_zeroes_alignment = iscsilun->block_size;
|
||||||
}
|
}
|
||||||
bs->bl.opt_transfer_length =
|
bs->bl.opt_transfer_length =
|
||||||
sector_limits_lun2qemu(iscsilun->bl.opt_xfer_len, iscsilun);
|
sector_limits_lun2qemu(iscsilun->bl.opt_xfer_len, iscsilun);
|
||||||
@@ -1852,7 +1866,7 @@ static BlockDriver bdrv_iscsi = {
|
|||||||
|
|
||||||
.bdrv_co_get_block_status = iscsi_co_get_block_status,
|
.bdrv_co_get_block_status = iscsi_co_get_block_status,
|
||||||
.bdrv_co_discard = iscsi_co_discard,
|
.bdrv_co_discard = iscsi_co_discard,
|
||||||
.bdrv_co_write_zeroes = iscsi_co_write_zeroes,
|
.bdrv_co_pwrite_zeroes = iscsi_co_pwrite_zeroes,
|
||||||
.bdrv_co_readv = iscsi_co_readv,
|
.bdrv_co_readv = iscsi_co_readv,
|
||||||
.bdrv_co_writev_flags = iscsi_co_writev_flags,
|
.bdrv_co_writev_flags = iscsi_co_writev_flags,
|
||||||
.bdrv_co_flush_to_disk = iscsi_co_flush,
|
.bdrv_co_flush_to_disk = iscsi_co_flush,
|
||||||
|
|||||||
@@ -204,13 +204,15 @@ static int64_t allocate_clusters(BlockDriverState *bs, int64_t sector_num,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
to_allocate = (sector_num + *pnum + s->tracks - 1) / s->tracks - idx;
|
to_allocate = DIV_ROUND_UP(sector_num + *pnum, s->tracks) - idx;
|
||||||
space = to_allocate * s->tracks;
|
space = to_allocate * s->tracks;
|
||||||
if (s->data_end + space > bdrv_getlength(bs->file->bs) >> BDRV_SECTOR_BITS) {
|
if (s->data_end + space > bdrv_getlength(bs->file->bs) >> BDRV_SECTOR_BITS) {
|
||||||
int ret;
|
int ret;
|
||||||
space += s->prealloc_size;
|
space += s->prealloc_size;
|
||||||
if (s->prealloc_mode == PRL_PREALLOC_MODE_FALLOCATE) {
|
if (s->prealloc_mode == PRL_PREALLOC_MODE_FALLOCATE) {
|
||||||
ret = bdrv_write_zeroes(bs->file->bs, s->data_end, space, 0);
|
ret = bdrv_pwrite_zeroes(bs->file->bs,
|
||||||
|
s->data_end << BDRV_SECTOR_BITS,
|
||||||
|
space << BDRV_SECTOR_BITS, 0);
|
||||||
} else {
|
} else {
|
||||||
ret = bdrv_truncate(bs->file->bs,
|
ret = bdrv_truncate(bs->file->bs,
|
||||||
(s->data_end + space) << BDRV_SECTOR_BITS);
|
(s->data_end + space) << BDRV_SECTOR_BITS);
|
||||||
|
|||||||
@@ -868,8 +868,8 @@ static int qcow_create(const char *filename, QemuOpts *opts, Error **errp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
tmp = g_malloc0(BDRV_SECTOR_SIZE);
|
tmp = g_malloc0(BDRV_SECTOR_SIZE);
|
||||||
for (i = 0; i < ((sizeof(uint64_t)*l1_size + BDRV_SECTOR_SIZE - 1)/
|
for (i = 0; i < DIV_ROUND_UP(sizeof(uint64_t) * l1_size, BDRV_SECTOR_SIZE);
|
||||||
BDRV_SECTOR_SIZE); i++) {
|
i++) {
|
||||||
ret = blk_pwrite(qcow_blk, header_size + BDRV_SECTOR_SIZE * i,
|
ret = blk_pwrite(qcow_blk, header_size + BDRV_SECTOR_SIZE * i,
|
||||||
tmp, BDRV_SECTOR_SIZE, 0);
|
tmp, BDRV_SECTOR_SIZE, 0);
|
||||||
if (ret != BDRV_SECTOR_SIZE) {
|
if (ret != BDRV_SECTOR_SIZE) {
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ static int qcow2_cache_entry_flush(BlockDriverState *bs, Qcow2Cache *c, int i)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c)
|
int qcow2_cache_write(BlockDriverState *bs, Qcow2Cache *c)
|
||||||
{
|
{
|
||||||
BDRVQcow2State *s = bs->opaque;
|
BDRVQcow2State *s = bs->opaque;
|
||||||
int result = 0;
|
int result = 0;
|
||||||
@@ -242,8 +242,15 @@ int qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c)
|
||||||
|
{
|
||||||
|
int result = qcow2_cache_write(bs, c);
|
||||||
|
|
||||||
if (result == 0) {
|
if (result == 0) {
|
||||||
ret = bdrv_flush(bs->file->bs);
|
int ret = bdrv_flush(bs->file->bs);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
result = ret;
|
result = ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1765,8 +1765,7 @@ static int expand_zero_clusters_in_l1(BlockDriverState *bs, uint64_t *l1_table,
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = bdrv_write_zeroes(bs->file->bs, offset / BDRV_SECTOR_SIZE,
|
ret = bdrv_pwrite_zeroes(bs->file->bs, offset, s->cluster_size, 0);
|
||||||
s->cluster_sectors, 0);
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (!preallocated) {
|
if (!preallocated) {
|
||||||
qcow2_free_clusters(bs, offset, s->cluster_size,
|
qcow2_free_clusters(bs, offset, s->cluster_size,
|
||||||
@@ -1868,8 +1867,8 @@ int qcow2_expand_zero_clusters(BlockDriverState *bs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < s->nb_snapshots; i++) {
|
for (i = 0; i < s->nb_snapshots; i++) {
|
||||||
int l1_sectors = (s->snapshots[i].l1_size * sizeof(uint64_t) +
|
int l1_sectors = DIV_ROUND_UP(s->snapshots[i].l1_size *
|
||||||
BDRV_SECTOR_SIZE - 1) / BDRV_SECTOR_SIZE;
|
sizeof(uint64_t), BDRV_SECTOR_SIZE);
|
||||||
|
|
||||||
l1_table = g_realloc(l1_table, l1_sectors * BDRV_SECTOR_SIZE);
|
l1_table = g_realloc(l1_table, l1_sectors * BDRV_SECTOR_SIZE);
|
||||||
|
|
||||||
|
|||||||
@@ -490,14 +490,12 @@ static int alloc_refcount_block(BlockDriverState *bs,
|
|||||||
uint64_t table_clusters =
|
uint64_t table_clusters =
|
||||||
size_to_clusters(s, table_size * sizeof(uint64_t));
|
size_to_clusters(s, table_size * sizeof(uint64_t));
|
||||||
blocks_clusters = 1 +
|
blocks_clusters = 1 +
|
||||||
((table_clusters + s->refcount_block_size - 1)
|
DIV_ROUND_UP(table_clusters, s->refcount_block_size);
|
||||||
/ s->refcount_block_size);
|
|
||||||
uint64_t meta_clusters = table_clusters + blocks_clusters;
|
uint64_t meta_clusters = table_clusters + blocks_clusters;
|
||||||
|
|
||||||
last_table_size = table_size;
|
last_table_size = table_size;
|
||||||
table_size = next_refcount_table_size(s, blocks_used +
|
table_size = next_refcount_table_size(s, blocks_used +
|
||||||
((meta_clusters + s->refcount_block_size - 1)
|
DIV_ROUND_UP(meta_clusters, s->refcount_block_size));
|
||||||
/ s->refcount_block_size));
|
|
||||||
|
|
||||||
} while (last_table_size != table_size);
|
} while (last_table_size != table_size);
|
||||||
|
|
||||||
|
|||||||
@@ -1193,7 +1193,7 @@ static void qcow2_refresh_limits(BlockDriverState *bs, Error **errp)
|
|||||||
{
|
{
|
||||||
BDRVQcow2State *s = bs->opaque;
|
BDRVQcow2State *s = bs->opaque;
|
||||||
|
|
||||||
bs->bl.write_zeroes_alignment = s->cluster_sectors;
|
bs->bl.pwrite_zeroes_alignment = s->cluster_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qcow2_set_key(BlockDriverState *bs, const char *key)
|
static int qcow2_set_key(BlockDriverState *bs, const char *key)
|
||||||
@@ -2406,65 +2406,55 @@ finish:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static bool is_zero_cluster(BlockDriverState *bs, int64_t start)
|
static bool is_zero_sectors(BlockDriverState *bs, int64_t start,
|
||||||
|
uint32_t count)
|
||||||
{
|
{
|
||||||
BDRVQcow2State *s = bs->opaque;
|
|
||||||
int nr;
|
int nr;
|
||||||
BlockDriverState *file;
|
BlockDriverState *file;
|
||||||
int64_t res = bdrv_get_block_status_above(bs, NULL, start,
|
int64_t res;
|
||||||
s->cluster_sectors, &nr, &file);
|
|
||||||
return res >= 0 && (res & BDRV_BLOCK_ZERO) && nr == s->cluster_sectors;
|
if (!count) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
res = bdrv_get_block_status_above(bs, NULL, start, count,
|
||||||
|
&nr, &file);
|
||||||
|
return res >= 0 && (res & BDRV_BLOCK_ZERO) && nr == count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool is_zero_cluster_top_locked(BlockDriverState *bs, int64_t start)
|
static coroutine_fn int qcow2_co_pwrite_zeroes(BlockDriverState *bs,
|
||||||
{
|
int64_t offset, int count, BdrvRequestFlags flags)
|
||||||
BDRVQcow2State *s = bs->opaque;
|
|
||||||
int nr = s->cluster_sectors;
|
|
||||||
uint64_t off;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = qcow2_get_cluster_offset(bs, start << BDRV_SECTOR_BITS, &nr, &off);
|
|
||||||
assert(nr == s->cluster_sectors);
|
|
||||||
return ret == QCOW2_CLUSTER_UNALLOCATED || ret == QCOW2_CLUSTER_ZERO;
|
|
||||||
}
|
|
||||||
|
|
||||||
static coroutine_fn int qcow2_co_write_zeroes(BlockDriverState *bs,
|
|
||||||
int64_t sector_num, int nb_sectors, BdrvRequestFlags flags)
|
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
BDRVQcow2State *s = bs->opaque;
|
BDRVQcow2State *s = bs->opaque;
|
||||||
|
|
||||||
int head = sector_num % s->cluster_sectors;
|
uint32_t head = offset % s->cluster_size;
|
||||||
int tail = (sector_num + nb_sectors) % s->cluster_sectors;
|
uint32_t tail = (offset + count) % s->cluster_size;
|
||||||
|
|
||||||
if (head != 0 || tail != 0) {
|
trace_qcow2_pwrite_zeroes_start_req(qemu_coroutine_self(), offset, count);
|
||||||
int64_t cl_end = -1;
|
|
||||||
|
|
||||||
sector_num -= head;
|
if (head || tail) {
|
||||||
nb_sectors += head;
|
int64_t cl_start = (offset - head) >> BDRV_SECTOR_BITS;
|
||||||
|
uint64_t off;
|
||||||
|
int nr;
|
||||||
|
|
||||||
if (tail != 0) {
|
assert(head + count <= s->cluster_size);
|
||||||
nb_sectors += s->cluster_sectors - tail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is_zero_cluster(bs, sector_num)) {
|
/* check whether remainder of cluster already reads as zero */
|
||||||
|
if (!(is_zero_sectors(bs, cl_start,
|
||||||
|
DIV_ROUND_UP(head, BDRV_SECTOR_SIZE)) &&
|
||||||
|
is_zero_sectors(bs, (offset + count) >> BDRV_SECTOR_BITS,
|
||||||
|
DIV_ROUND_UP(-tail & (s->cluster_size - 1),
|
||||||
|
BDRV_SECTOR_SIZE)))) {
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nb_sectors > s->cluster_sectors) {
|
|
||||||
/* Technically the request can cover 2 clusters, f.e. 4k write
|
|
||||||
at s->cluster_sectors - 2k offset. One of these cluster can
|
|
||||||
be zeroed, one unallocated */
|
|
||||||
cl_end = sector_num + nb_sectors - s->cluster_sectors;
|
|
||||||
if (!is_zero_cluster(bs, cl_end)) {
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
qemu_co_mutex_lock(&s->lock);
|
qemu_co_mutex_lock(&s->lock);
|
||||||
/* We can have new write after previous check */
|
/* We can have new write after previous check */
|
||||||
if (!is_zero_cluster_top_locked(bs, sector_num) ||
|
offset = cl_start << BDRV_SECTOR_BITS;
|
||||||
(cl_end > 0 && !is_zero_cluster_top_locked(bs, cl_end))) {
|
count = s->cluster_size;
|
||||||
|
nr = s->cluster_sectors;
|
||||||
|
ret = qcow2_get_cluster_offset(bs, offset, &nr, &off);
|
||||||
|
if (ret != QCOW2_CLUSTER_UNALLOCATED && ret != QCOW2_CLUSTER_ZERO) {
|
||||||
qemu_co_mutex_unlock(&s->lock);
|
qemu_co_mutex_unlock(&s->lock);
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
}
|
||||||
@@ -2472,8 +2462,10 @@ static coroutine_fn int qcow2_co_write_zeroes(BlockDriverState *bs,
|
|||||||
qemu_co_mutex_lock(&s->lock);
|
qemu_co_mutex_lock(&s->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trace_qcow2_pwrite_zeroes(qemu_coroutine_self(), offset, count);
|
||||||
|
|
||||||
/* Whatever is left can use real zero clusters */
|
/* Whatever is left can use real zero clusters */
|
||||||
ret = qcow2_zero_clusters(bs, sector_num << BDRV_SECTOR_BITS, nb_sectors);
|
ret = qcow2_zero_clusters(bs, offset, count >> BDRV_SECTOR_BITS);
|
||||||
qemu_co_mutex_unlock(&s->lock);
|
qemu_co_mutex_unlock(&s->lock);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -2664,8 +2656,8 @@ static int make_completely_empty(BlockDriverState *bs)
|
|||||||
/* After this call, neither the in-memory nor the on-disk refcount
|
/* After this call, neither the in-memory nor the on-disk refcount
|
||||||
* information accurately describe the actual references */
|
* information accurately describe the actual references */
|
||||||
|
|
||||||
ret = bdrv_write_zeroes(bs->file->bs, s->l1_table_offset / BDRV_SECTOR_SIZE,
|
ret = bdrv_pwrite_zeroes(bs->file->bs, s->l1_table_offset,
|
||||||
l1_clusters * s->cluster_sectors, 0);
|
l1_clusters * s->cluster_size, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
goto fail_broken_refcounts;
|
goto fail_broken_refcounts;
|
||||||
}
|
}
|
||||||
@@ -2678,9 +2670,8 @@ static int make_completely_empty(BlockDriverState *bs)
|
|||||||
* overwrite parts of the existing refcount and L1 table, which is not
|
* overwrite parts of the existing refcount and L1 table, which is not
|
||||||
* an issue because the dirty flag is set, complete data loss is in fact
|
* an issue because the dirty flag is set, complete data loss is in fact
|
||||||
* desired and partial data loss is consequently fine as well */
|
* desired and partial data loss is consequently fine as well */
|
||||||
ret = bdrv_write_zeroes(bs->file->bs, s->cluster_size / BDRV_SECTOR_SIZE,
|
ret = bdrv_pwrite_zeroes(bs->file->bs, s->cluster_size,
|
||||||
(2 + l1_clusters) * s->cluster_size /
|
(2 + l1_clusters) * s->cluster_size, 0);
|
||||||
BDRV_SECTOR_SIZE, 0);
|
|
||||||
/* This call (even if it failed overall) may have overwritten on-disk
|
/* This call (even if it failed overall) may have overwritten on-disk
|
||||||
* refcount structures; in that case, the in-memory refcount information
|
* refcount structures; in that case, the in-memory refcount information
|
||||||
* will probably differ from the on-disk information which makes the BDS
|
* will probably differ from the on-disk information which makes the BDS
|
||||||
@@ -2822,14 +2813,14 @@ static coroutine_fn int qcow2_co_flush_to_os(BlockDriverState *bs)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
qemu_co_mutex_lock(&s->lock);
|
qemu_co_mutex_lock(&s->lock);
|
||||||
ret = qcow2_cache_flush(bs, s->l2_table_cache);
|
ret = qcow2_cache_write(bs, s->l2_table_cache);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
qemu_co_mutex_unlock(&s->lock);
|
qemu_co_mutex_unlock(&s->lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qcow2_need_accurate_refcounts(s)) {
|
if (qcow2_need_accurate_refcounts(s)) {
|
||||||
ret = qcow2_cache_flush(bs, s->refcount_block_cache);
|
ret = qcow2_cache_write(bs, s->refcount_block_cache);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
qemu_co_mutex_unlock(&s->lock);
|
qemu_co_mutex_unlock(&s->lock);
|
||||||
return ret;
|
return ret;
|
||||||
@@ -3381,7 +3372,7 @@ BlockDriver bdrv_qcow2 = {
|
|||||||
.bdrv_co_writev = qcow2_co_writev,
|
.bdrv_co_writev = qcow2_co_writev,
|
||||||
.bdrv_co_flush_to_os = qcow2_co_flush_to_os,
|
.bdrv_co_flush_to_os = qcow2_co_flush_to_os,
|
||||||
|
|
||||||
.bdrv_co_write_zeroes = qcow2_co_write_zeroes,
|
.bdrv_co_pwrite_zeroes = qcow2_co_pwrite_zeroes,
|
||||||
.bdrv_co_discard = qcow2_co_discard,
|
.bdrv_co_discard = qcow2_co_discard,
|
||||||
.bdrv_truncate = qcow2_truncate,
|
.bdrv_truncate = qcow2_truncate,
|
||||||
.bdrv_write_compressed = qcow2_write_compressed,
|
.bdrv_write_compressed = qcow2_write_compressed,
|
||||||
|
|||||||
@@ -583,6 +583,7 @@ int qcow2_cache_destroy(BlockDriverState* bs, Qcow2Cache *c);
|
|||||||
void qcow2_cache_entry_mark_dirty(BlockDriverState *bs, Qcow2Cache *c,
|
void qcow2_cache_entry_mark_dirty(BlockDriverState *bs, Qcow2Cache *c,
|
||||||
void *table);
|
void *table);
|
||||||
int qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c);
|
int qcow2_cache_flush(BlockDriverState *bs, Qcow2Cache *c);
|
||||||
|
int qcow2_cache_write(BlockDriverState *bs, Qcow2Cache *c);
|
||||||
int qcow2_cache_set_dependency(BlockDriverState *bs, Qcow2Cache *c,
|
int qcow2_cache_set_dependency(BlockDriverState *bs, Qcow2Cache *c,
|
||||||
Qcow2Cache *dependency);
|
Qcow2Cache *dependency);
|
||||||
void qcow2_cache_depends_on_flush(Qcow2Cache *c);
|
void qcow2_cache_depends_on_flush(Qcow2Cache *c);
|
||||||
|
|||||||
@@ -234,8 +234,7 @@ int qed_check(BDRVQEDState *s, BdrvCheckResult *result, bool fix)
|
|||||||
}
|
}
|
||||||
|
|
||||||
check.result->bfi.total_clusters =
|
check.result->bfi.total_clusters =
|
||||||
(s->header.image_size + s->header.cluster_size - 1) /
|
DIV_ROUND_UP(s->header.image_size, s->header.cluster_size);
|
||||||
s->header.cluster_size;
|
|
||||||
ret = qed_check_l1_table(&check, s->l1_table);
|
ret = qed_check_l1_table(&check, s->l1_table);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
/* Only check for leaks if entire image was scanned successfully */
|
/* Only check for leaks if entire image was scanned successfully */
|
||||||
|
|||||||
38
block/qed.c
38
block/qed.c
@@ -143,8 +143,7 @@ static void qed_write_header(BDRVQEDState *s, BlockCompletionFunc cb,
|
|||||||
* them, and write back.
|
* them, and write back.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int nsectors = (sizeof(QEDHeader) + BDRV_SECTOR_SIZE - 1) /
|
int nsectors = DIV_ROUND_UP(sizeof(QEDHeader), BDRV_SECTOR_SIZE);
|
||||||
BDRV_SECTOR_SIZE;
|
|
||||||
size_t len = nsectors * BDRV_SECTOR_SIZE;
|
size_t len = nsectors * BDRV_SECTOR_SIZE;
|
||||||
QEDWriteHeaderCB *write_header_cb = gencb_alloc(sizeof(*write_header_cb),
|
QEDWriteHeaderCB *write_header_cb = gencb_alloc(sizeof(*write_header_cb),
|
||||||
cb, opaque);
|
cb, opaque);
|
||||||
@@ -518,7 +517,7 @@ static void bdrv_qed_refresh_limits(BlockDriverState *bs, Error **errp)
|
|||||||
{
|
{
|
||||||
BDRVQEDState *s = bs->opaque;
|
BDRVQEDState *s = bs->opaque;
|
||||||
|
|
||||||
bs->bl.write_zeroes_alignment = s->header.cluster_size >> BDRV_SECTOR_BITS;
|
bs->bl.pwrite_zeroes_alignment = s->header.cluster_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We have nothing to do for QED reopen, stubs just return
|
/* We have nothing to do for QED reopen, stubs just return
|
||||||
@@ -1419,7 +1418,7 @@ typedef struct {
|
|||||||
bool done;
|
bool done;
|
||||||
} QEDWriteZeroesCB;
|
} QEDWriteZeroesCB;
|
||||||
|
|
||||||
static void coroutine_fn qed_co_write_zeroes_cb(void *opaque, int ret)
|
static void coroutine_fn qed_co_pwrite_zeroes_cb(void *opaque, int ret)
|
||||||
{
|
{
|
||||||
QEDWriteZeroesCB *cb = opaque;
|
QEDWriteZeroesCB *cb = opaque;
|
||||||
|
|
||||||
@@ -1430,10 +1429,10 @@ static void coroutine_fn qed_co_write_zeroes_cb(void *opaque, int ret)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int coroutine_fn bdrv_qed_co_write_zeroes(BlockDriverState *bs,
|
static int coroutine_fn bdrv_qed_co_pwrite_zeroes(BlockDriverState *bs,
|
||||||
int64_t sector_num,
|
int64_t offset,
|
||||||
int nb_sectors,
|
int count,
|
||||||
BdrvRequestFlags flags)
|
BdrvRequestFlags flags)
|
||||||
{
|
{
|
||||||
BlockAIOCB *blockacb;
|
BlockAIOCB *blockacb;
|
||||||
BDRVQEDState *s = bs->opaque;
|
BDRVQEDState *s = bs->opaque;
|
||||||
@@ -1441,25 +1440,22 @@ static int coroutine_fn bdrv_qed_co_write_zeroes(BlockDriverState *bs,
|
|||||||
QEMUIOVector qiov;
|
QEMUIOVector qiov;
|
||||||
struct iovec iov;
|
struct iovec iov;
|
||||||
|
|
||||||
/* Refuse if there are untouched backing file sectors */
|
/* Fall back if the request is not aligned */
|
||||||
if (bs->backing) {
|
if (qed_offset_into_cluster(s, offset) ||
|
||||||
if (qed_offset_into_cluster(s, sector_num * BDRV_SECTOR_SIZE) != 0) {
|
qed_offset_into_cluster(s, count)) {
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
}
|
|
||||||
if (qed_offset_into_cluster(s, nb_sectors * BDRV_SECTOR_SIZE) != 0) {
|
|
||||||
return -ENOTSUP;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Zero writes start without an I/O buffer. If a buffer becomes necessary
|
/* Zero writes start without an I/O buffer. If a buffer becomes necessary
|
||||||
* then it will be allocated during request processing.
|
* then it will be allocated during request processing.
|
||||||
*/
|
*/
|
||||||
iov.iov_base = NULL,
|
iov.iov_base = NULL;
|
||||||
iov.iov_len = nb_sectors * BDRV_SECTOR_SIZE,
|
iov.iov_len = count;
|
||||||
|
|
||||||
qemu_iovec_init_external(&qiov, &iov, 1);
|
qemu_iovec_init_external(&qiov, &iov, 1);
|
||||||
blockacb = qed_aio_setup(bs, sector_num, &qiov, nb_sectors,
|
blockacb = qed_aio_setup(bs, offset >> BDRV_SECTOR_BITS, &qiov,
|
||||||
qed_co_write_zeroes_cb, &cb,
|
count >> BDRV_SECTOR_BITS,
|
||||||
|
qed_co_pwrite_zeroes_cb, &cb,
|
||||||
QED_AIOCB_WRITE | QED_AIOCB_ZERO);
|
QED_AIOCB_WRITE | QED_AIOCB_ZERO);
|
||||||
if (!blockacb) {
|
if (!blockacb) {
|
||||||
return -EIO;
|
return -EIO;
|
||||||
@@ -1664,7 +1660,7 @@ static BlockDriver bdrv_qed = {
|
|||||||
.bdrv_co_get_block_status = bdrv_qed_co_get_block_status,
|
.bdrv_co_get_block_status = bdrv_qed_co_get_block_status,
|
||||||
.bdrv_aio_readv = bdrv_qed_aio_readv,
|
.bdrv_aio_readv = bdrv_qed_aio_readv,
|
||||||
.bdrv_aio_writev = bdrv_qed_aio_writev,
|
.bdrv_aio_writev = bdrv_qed_aio_writev,
|
||||||
.bdrv_co_write_zeroes = bdrv_qed_co_write_zeroes,
|
.bdrv_co_pwrite_zeroes = bdrv_qed_co_pwrite_zeroes,
|
||||||
.bdrv_truncate = bdrv_qed_truncate,
|
.bdrv_truncate = bdrv_qed_truncate,
|
||||||
.bdrv_getlength = bdrv_qed_getlength,
|
.bdrv_getlength = bdrv_qed_getlength,
|
||||||
.bdrv_get_info = bdrv_qed_get_info,
|
.bdrv_get_info = bdrv_qed_get_info,
|
||||||
|
|||||||
@@ -729,9 +729,33 @@ static void raw_reopen_abort(BDRVReopenState *state)
|
|||||||
state->opaque = NULL;
|
state->opaque = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int hdev_get_max_transfer_length(int fd)
|
||||||
|
{
|
||||||
|
#ifdef BLKSECTGET
|
||||||
|
int max_sectors = 0;
|
||||||
|
if (ioctl(fd, BLKSECTGET, &max_sectors) == 0) {
|
||||||
|
return max_sectors;
|
||||||
|
} else {
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
return -ENOSYS;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
|
static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||||
{
|
{
|
||||||
BDRVRawState *s = bs->opaque;
|
BDRVRawState *s = bs->opaque;
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
if (!fstat(s->fd, &st)) {
|
||||||
|
if (S_ISBLK(st.st_mode)) {
|
||||||
|
int ret = hdev_get_max_transfer_length(s->fd);
|
||||||
|
if (ret >= 0) {
|
||||||
|
bs->bl.max_transfer_length = ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
raw_probe_alignment(bs, s->fd, errp);
|
raw_probe_alignment(bs, s->fd, errp);
|
||||||
bs->bl.min_mem_alignment = s->buf_align;
|
bs->bl.min_mem_alignment = s->buf_align;
|
||||||
@@ -1252,8 +1276,8 @@ static int aio_worker(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int paio_submit_co(BlockDriverState *bs, int fd,
|
static int paio_submit_co(BlockDriverState *bs, int fd,
|
||||||
int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
|
int64_t offset, QEMUIOVector *qiov,
|
||||||
int type)
|
int count, int type)
|
||||||
{
|
{
|
||||||
RawPosixAIOData *acb = g_new(RawPosixAIOData, 1);
|
RawPosixAIOData *acb = g_new(RawPosixAIOData, 1);
|
||||||
ThreadPool *pool;
|
ThreadPool *pool;
|
||||||
@@ -1262,16 +1286,16 @@ static int paio_submit_co(BlockDriverState *bs, int fd,
|
|||||||
acb->aio_type = type;
|
acb->aio_type = type;
|
||||||
acb->aio_fildes = fd;
|
acb->aio_fildes = fd;
|
||||||
|
|
||||||
acb->aio_nbytes = nb_sectors * BDRV_SECTOR_SIZE;
|
acb->aio_nbytes = count;
|
||||||
acb->aio_offset = sector_num * BDRV_SECTOR_SIZE;
|
acb->aio_offset = offset;
|
||||||
|
|
||||||
if (qiov) {
|
if (qiov) {
|
||||||
acb->aio_iov = qiov->iov;
|
acb->aio_iov = qiov->iov;
|
||||||
acb->aio_niov = qiov->niov;
|
acb->aio_niov = qiov->niov;
|
||||||
assert(qiov->size == acb->aio_nbytes);
|
assert(qiov->size == count);
|
||||||
}
|
}
|
||||||
|
|
||||||
trace_paio_submit_co(sector_num, nb_sectors, type);
|
trace_paio_submit_co(offset, count, type);
|
||||||
pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
|
pool = aio_get_thread_pool(bdrv_get_aio_context(bs));
|
||||||
return thread_pool_submit_co(pool, aio_worker, acb);
|
return thread_pool_submit_co(pool, aio_worker, acb);
|
||||||
}
|
}
|
||||||
@@ -1868,17 +1892,17 @@ static coroutine_fn BlockAIOCB *raw_aio_discard(BlockDriverState *bs,
|
|||||||
cb, opaque, QEMU_AIO_DISCARD);
|
cb, opaque, QEMU_AIO_DISCARD);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int coroutine_fn raw_co_write_zeroes(
|
static int coroutine_fn raw_co_pwrite_zeroes(
|
||||||
BlockDriverState *bs, int64_t sector_num,
|
BlockDriverState *bs, int64_t offset,
|
||||||
int nb_sectors, BdrvRequestFlags flags)
|
int count, BdrvRequestFlags flags)
|
||||||
{
|
{
|
||||||
BDRVRawState *s = bs->opaque;
|
BDRVRawState *s = bs->opaque;
|
||||||
|
|
||||||
if (!(flags & BDRV_REQ_MAY_UNMAP)) {
|
if (!(flags & BDRV_REQ_MAY_UNMAP)) {
|
||||||
return paio_submit_co(bs, s->fd, sector_num, NULL, nb_sectors,
|
return paio_submit_co(bs, s->fd, offset, NULL, count,
|
||||||
QEMU_AIO_WRITE_ZEROES);
|
QEMU_AIO_WRITE_ZEROES);
|
||||||
} else if (s->discard_zeroes) {
|
} else if (s->discard_zeroes) {
|
||||||
return paio_submit_co(bs, s->fd, sector_num, NULL, nb_sectors,
|
return paio_submit_co(bs, s->fd, offset, NULL, count,
|
||||||
QEMU_AIO_DISCARD);
|
QEMU_AIO_DISCARD);
|
||||||
}
|
}
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
@@ -1931,7 +1955,7 @@ BlockDriver bdrv_file = {
|
|||||||
.bdrv_create = raw_create,
|
.bdrv_create = raw_create,
|
||||||
.bdrv_has_zero_init = bdrv_has_zero_init_1,
|
.bdrv_has_zero_init = bdrv_has_zero_init_1,
|
||||||
.bdrv_co_get_block_status = raw_co_get_block_status,
|
.bdrv_co_get_block_status = raw_co_get_block_status,
|
||||||
.bdrv_co_write_zeroes = raw_co_write_zeroes,
|
.bdrv_co_pwrite_zeroes = raw_co_pwrite_zeroes,
|
||||||
|
|
||||||
.bdrv_aio_readv = raw_aio_readv,
|
.bdrv_aio_readv = raw_aio_readv,
|
||||||
.bdrv_aio_writev = raw_aio_writev,
|
.bdrv_aio_writev = raw_aio_writev,
|
||||||
@@ -2293,8 +2317,8 @@ static coroutine_fn BlockAIOCB *hdev_aio_discard(BlockDriverState *bs,
|
|||||||
cb, opaque, QEMU_AIO_DISCARD|QEMU_AIO_BLKDEV);
|
cb, opaque, QEMU_AIO_DISCARD|QEMU_AIO_BLKDEV);
|
||||||
}
|
}
|
||||||
|
|
||||||
static coroutine_fn int hdev_co_write_zeroes(BlockDriverState *bs,
|
static coroutine_fn int hdev_co_pwrite_zeroes(BlockDriverState *bs,
|
||||||
int64_t sector_num, int nb_sectors, BdrvRequestFlags flags)
|
int64_t offset, int count, BdrvRequestFlags flags)
|
||||||
{
|
{
|
||||||
BDRVRawState *s = bs->opaque;
|
BDRVRawState *s = bs->opaque;
|
||||||
int rc;
|
int rc;
|
||||||
@@ -2304,10 +2328,10 @@ static coroutine_fn int hdev_co_write_zeroes(BlockDriverState *bs,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
if (!(flags & BDRV_REQ_MAY_UNMAP)) {
|
if (!(flags & BDRV_REQ_MAY_UNMAP)) {
|
||||||
return paio_submit_co(bs, s->fd, sector_num, NULL, nb_sectors,
|
return paio_submit_co(bs, s->fd, offset, NULL, count,
|
||||||
QEMU_AIO_WRITE_ZEROES|QEMU_AIO_BLKDEV);
|
QEMU_AIO_WRITE_ZEROES|QEMU_AIO_BLKDEV);
|
||||||
} else if (s->discard_zeroes) {
|
} else if (s->discard_zeroes) {
|
||||||
return paio_submit_co(bs, s->fd, sector_num, NULL, nb_sectors,
|
return paio_submit_co(bs, s->fd, offset, NULL, count,
|
||||||
QEMU_AIO_DISCARD|QEMU_AIO_BLKDEV);
|
QEMU_AIO_DISCARD|QEMU_AIO_BLKDEV);
|
||||||
}
|
}
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
@@ -2379,7 +2403,7 @@ static BlockDriver bdrv_host_device = {
|
|||||||
.bdrv_reopen_abort = raw_reopen_abort,
|
.bdrv_reopen_abort = raw_reopen_abort,
|
||||||
.bdrv_create = hdev_create,
|
.bdrv_create = hdev_create,
|
||||||
.create_opts = &raw_create_opts,
|
.create_opts = &raw_create_opts,
|
||||||
.bdrv_co_write_zeroes = hdev_co_write_zeroes,
|
.bdrv_co_pwrite_zeroes = hdev_co_pwrite_zeroes,
|
||||||
|
|
||||||
.bdrv_aio_readv = raw_aio_readv,
|
.bdrv_aio_readv = raw_aio_readv,
|
||||||
.bdrv_aio_writev = raw_aio_writev,
|
.bdrv_aio_writev = raw_aio_writev,
|
||||||
|
|||||||
@@ -127,11 +127,11 @@ static int64_t coroutine_fn raw_co_get_block_status(BlockDriverState *bs,
|
|||||||
(sector_num << BDRV_SECTOR_BITS);
|
(sector_num << BDRV_SECTOR_BITS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int coroutine_fn raw_co_write_zeroes(BlockDriverState *bs,
|
static int coroutine_fn raw_co_pwrite_zeroes(BlockDriverState *bs,
|
||||||
int64_t sector_num, int nb_sectors,
|
int64_t offset, int count,
|
||||||
BdrvRequestFlags flags)
|
BdrvRequestFlags flags)
|
||||||
{
|
{
|
||||||
return bdrv_co_write_zeroes(bs->file->bs, sector_num, nb_sectors, flags);
|
return bdrv_co_pwrite_zeroes(bs->file->bs, offset, count, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int coroutine_fn raw_co_discard(BlockDriverState *bs,
|
static int coroutine_fn raw_co_discard(BlockDriverState *bs,
|
||||||
@@ -252,7 +252,7 @@ BlockDriver bdrv_raw = {
|
|||||||
.bdrv_create = &raw_create,
|
.bdrv_create = &raw_create,
|
||||||
.bdrv_co_readv = &raw_co_readv,
|
.bdrv_co_readv = &raw_co_readv,
|
||||||
.bdrv_co_writev_flags = &raw_co_writev_flags,
|
.bdrv_co_writev_flags = &raw_co_writev_flags,
|
||||||
.bdrv_co_write_zeroes = &raw_co_write_zeroes,
|
.bdrv_co_pwrite_zeroes = &raw_co_pwrite_zeroes,
|
||||||
.bdrv_co_discard = &raw_co_discard,
|
.bdrv_co_discard = &raw_co_discard,
|
||||||
.bdrv_co_get_block_status = &raw_co_get_block_status,
|
.bdrv_co_get_block_status = &raw_co_get_block_status,
|
||||||
.bdrv_truncate = &raw_truncate,
|
.bdrv_truncate = &raw_truncate,
|
||||||
|
|||||||
@@ -409,9 +409,6 @@ int bdrv_all_delete_snapshot(const char *name, BlockDriverState **first_bad_bs,
|
|||||||
if (bdrv_can_snapshot(bs) &&
|
if (bdrv_can_snapshot(bs) &&
|
||||||
bdrv_snapshot_find(bs, snapshot, name) >= 0) {
|
bdrv_snapshot_find(bs, snapshot, name) >= 0) {
|
||||||
ret = bdrv_snapshot_delete_by_id_or_name(bs, name, err);
|
ret = bdrv_snapshot_delete_by_id_or_name(bs, name, err);
|
||||||
if (ret < 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
aio_context_release(ctx);
|
aio_context_release(ctx);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
|||||||
@@ -27,7 +27,6 @@
|
|||||||
#include "migration/migration.h"
|
#include "migration/migration.h"
|
||||||
|
|
||||||
#include <uuid/uuid.h>
|
#include <uuid/uuid.h>
|
||||||
#include <glib.h>
|
|
||||||
|
|
||||||
/* Options for VHDX creation */
|
/* Options for VHDX creation */
|
||||||
|
|
||||||
|
|||||||
19
block/vmdk.c
19
block/vmdk.c
@@ -34,7 +34,6 @@
|
|||||||
#include "migration/migration.h"
|
#include "migration/migration.h"
|
||||||
#include "qemu/cutils.h"
|
#include "qemu/cutils.h"
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
#include <glib.h>
|
|
||||||
|
|
||||||
#define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D')
|
#define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D')
|
||||||
#define VMDK4_MAGIC (('K' << 24) | ('D' << 16) | ('M' << 8) | 'V')
|
#define VMDK4_MAGIC (('K' << 24) | ('D' << 16) | ('M' << 8) | 'V')
|
||||||
@@ -998,9 +997,9 @@ static void vmdk_refresh_limits(BlockDriverState *bs, Error **errp)
|
|||||||
|
|
||||||
for (i = 0; i < s->num_extents; i++) {
|
for (i = 0; i < s->num_extents; i++) {
|
||||||
if (!s->extents[i].flat) {
|
if (!s->extents[i].flat) {
|
||||||
bs->bl.write_zeroes_alignment =
|
bs->bl.pwrite_zeroes_alignment =
|
||||||
MAX(bs->bl.write_zeroes_alignment,
|
MAX(bs->bl.pwrite_zeroes_alignment,
|
||||||
s->extents[i].cluster_sectors);
|
s->extents[i].cluster_sectors << BDRV_SECTOR_BITS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1704,15 +1703,13 @@ static int vmdk_write_compressed(BlockDriverState *bs,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int coroutine_fn vmdk_co_write_zeroes(BlockDriverState *bs,
|
static int coroutine_fn vmdk_co_pwrite_zeroes(BlockDriverState *bs,
|
||||||
int64_t sector_num,
|
int64_t offset,
|
||||||
int nb_sectors,
|
int bytes,
|
||||||
BdrvRequestFlags flags)
|
BdrvRequestFlags flags)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
BDRVVmdkState *s = bs->opaque;
|
BDRVVmdkState *s = bs->opaque;
|
||||||
uint64_t offset = sector_num * BDRV_SECTOR_SIZE;
|
|
||||||
uint64_t bytes = nb_sectors * BDRV_SECTOR_SIZE;
|
|
||||||
|
|
||||||
qemu_co_mutex_lock(&s->lock);
|
qemu_co_mutex_lock(&s->lock);
|
||||||
/* write zeroes could fail if sectors not aligned to cluster, test it with
|
/* write zeroes could fail if sectors not aligned to cluster, test it with
|
||||||
@@ -2403,7 +2400,7 @@ static BlockDriver bdrv_vmdk = {
|
|||||||
.bdrv_co_preadv = vmdk_co_preadv,
|
.bdrv_co_preadv = vmdk_co_preadv,
|
||||||
.bdrv_co_pwritev = vmdk_co_pwritev,
|
.bdrv_co_pwritev = vmdk_co_pwritev,
|
||||||
.bdrv_write_compressed = vmdk_write_compressed,
|
.bdrv_write_compressed = vmdk_write_compressed,
|
||||||
.bdrv_co_write_zeroes = vmdk_co_write_zeroes,
|
.bdrv_co_pwrite_zeroes = vmdk_co_pwrite_zeroes,
|
||||||
.bdrv_close = vmdk_close,
|
.bdrv_close = vmdk_close,
|
||||||
.bdrv_create = vmdk_create,
|
.bdrv_create = vmdk_create,
|
||||||
.bdrv_co_flush_to_disk = vmdk_co_flush,
|
.bdrv_co_flush_to_disk = vmdk_co_flush,
|
||||||
|
|||||||
@@ -1960,8 +1960,7 @@ DLOG(fprintf(stderr, "check direntry %d:\n", i); print_direntry(direntries + i))
|
|||||||
/* check file size with FAT */
|
/* check file size with FAT */
|
||||||
cluster_count = get_cluster_count_for_direntry(s, direntries + i, path2);
|
cluster_count = get_cluster_count_for_direntry(s, direntries + i, path2);
|
||||||
if (cluster_count !=
|
if (cluster_count !=
|
||||||
(le32_to_cpu(direntries[i].size) + s->cluster_size
|
DIV_ROUND_UP(le32_to_cpu(direntries[i].size), s->cluster_size)) {
|
||||||
- 1) / s->cluster_size) {
|
|
||||||
DLOG(fprintf(stderr, "Cluster count mismatch\n"));
|
DLOG(fprintf(stderr, "Cluster count mismatch\n"));
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|||||||
69
blockdev.c
69
blockdev.c
@@ -56,6 +56,8 @@
|
|||||||
static QTAILQ_HEAD(, BlockDriverState) monitor_bdrv_states =
|
static QTAILQ_HEAD(, BlockDriverState) monitor_bdrv_states =
|
||||||
QTAILQ_HEAD_INITIALIZER(monitor_bdrv_states);
|
QTAILQ_HEAD_INITIALIZER(monitor_bdrv_states);
|
||||||
|
|
||||||
|
static int do_open_tray(const char *device, bool force, Error **errp);
|
||||||
|
|
||||||
static const char *const if_name[IF_COUNT] = {
|
static const char *const if_name[IF_COUNT] = {
|
||||||
[IF_NONE] = "none",
|
[IF_NONE] = "none",
|
||||||
[IF_IDE] = "ide",
|
[IF_IDE] = "ide",
|
||||||
@@ -2274,8 +2276,6 @@ exit:
|
|||||||
block_job_txn_unref(block_job_txn);
|
block_job_txn_unref(block_job_txn);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_open_tray(const char *device, bool force, Error **errp);
|
|
||||||
|
|
||||||
void qmp_eject(const char *device, bool has_force, bool force, Error **errp)
|
void qmp_eject(const char *device, bool has_force, bool force, Error **errp)
|
||||||
{
|
{
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
@@ -2286,16 +2286,11 @@ void qmp_eject(const char *device, bool has_force, bool force, Error **errp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
rc = do_open_tray(device, force, &local_err);
|
rc = do_open_tray(device, force, &local_err);
|
||||||
if (local_err) {
|
if (rc && rc != -ENOSYS) {
|
||||||
error_propagate(errp, local_err);
|
error_propagate(errp, local_err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
error_free(local_err);
|
||||||
if (rc == EINPROGRESS) {
|
|
||||||
error_setg(errp, "Device '%s' is locked and force was not specified, "
|
|
||||||
"wait for tray to open and try again", device);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
qmp_x_blockdev_remove_medium(device, errp);
|
qmp_x_blockdev_remove_medium(device, errp);
|
||||||
}
|
}
|
||||||
@@ -2324,11 +2319,16 @@ void qmp_block_passwd(bool has_device, const char *device,
|
|||||||
aio_context_release(aio_context);
|
aio_context_release(aio_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* returns -errno on fatal error, +errno for non-fatal situations.
|
* Attempt to open the tray of @device.
|
||||||
* errp will always be set when the return code is negative.
|
* If @force, ignore its tray lock.
|
||||||
* May return +ENOSYS if the device has no tray,
|
* Else, if the tray is locked, don't open it, but ask the guest to open it.
|
||||||
* or +EINPROGRESS if the tray is locked and the guest has been notified.
|
* On error, store an error through @errp and return -errno.
|
||||||
|
* If @device does not exist, return -ENODEV.
|
||||||
|
* If it has no removable media, return -ENOTSUP.
|
||||||
|
* If it has no tray, return -ENOSYS.
|
||||||
|
* If the guest was asked to open the tray, return -EINPROGRESS.
|
||||||
|
* Else, return 0.
|
||||||
*/
|
*/
|
||||||
static int do_open_tray(const char *device, bool force, Error **errp)
|
static int do_open_tray(const char *device, bool force, Error **errp)
|
||||||
{
|
{
|
||||||
@@ -2348,8 +2348,8 @@ static int do_open_tray(const char *device, bool force, Error **errp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!blk_dev_has_tray(blk)) {
|
if (!blk_dev_has_tray(blk)) {
|
||||||
/* Ignore this command on tray-less devices */
|
error_setg(errp, "Device '%s' does not have a tray", device);
|
||||||
return ENOSYS;
|
return -ENOSYS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blk_dev_is_tray_open(blk)) {
|
if (blk_dev_is_tray_open(blk)) {
|
||||||
@@ -2366,7 +2366,9 @@ static int do_open_tray(const char *device, bool force, Error **errp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (locked && !force) {
|
if (locked && !force) {
|
||||||
return EINPROGRESS;
|
error_setg(errp, "Device '%s' is locked and force was not specified, "
|
||||||
|
"wait for tray to open and try again", device);
|
||||||
|
return -EINPROGRESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -2375,10 +2377,18 @@ static int do_open_tray(const char *device, bool force, Error **errp)
|
|||||||
void qmp_blockdev_open_tray(const char *device, bool has_force, bool force,
|
void qmp_blockdev_open_tray(const char *device, bool has_force, bool force,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
|
Error *local_err = NULL;
|
||||||
|
int rc;
|
||||||
|
|
||||||
if (!has_force) {
|
if (!has_force) {
|
||||||
force = false;
|
force = false;
|
||||||
}
|
}
|
||||||
do_open_tray(device, force, errp);
|
rc = do_open_tray(device, force, &local_err);
|
||||||
|
if (rc && rc != -ENOSYS && rc != -EINPROGRESS) {
|
||||||
|
error_propagate(errp, local_err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
error_free(local_err);
|
||||||
}
|
}
|
||||||
|
|
||||||
void qmp_blockdev_close_tray(const char *device, Error **errp)
|
void qmp_blockdev_close_tray(const char *device, Error **errp)
|
||||||
@@ -3335,7 +3345,7 @@ void do_blockdev_backup(const char *device, const char *target,
|
|||||||
BlockdevOnError on_target_error,
|
BlockdevOnError on_target_error,
|
||||||
BlockJobTxn *txn, Error **errp)
|
BlockJobTxn *txn, Error **errp)
|
||||||
{
|
{
|
||||||
BlockBackend *blk, *target_blk;
|
BlockBackend *blk;
|
||||||
BlockDriverState *bs;
|
BlockDriverState *bs;
|
||||||
BlockDriverState *target_bs;
|
BlockDriverState *target_bs;
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
@@ -3366,19 +3376,22 @@ void do_blockdev_backup(const char *device, const char *target,
|
|||||||
}
|
}
|
||||||
bs = blk_bs(blk);
|
bs = blk_bs(blk);
|
||||||
|
|
||||||
target_blk = blk_by_name(target);
|
target_bs = bdrv_lookup_bs(target, target, errp);
|
||||||
if (!target_blk) {
|
if (!target_bs) {
|
||||||
error_setg(errp, "Device '%s' not found", target);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!blk_is_available(target_blk)) {
|
if (bdrv_get_aio_context(target_bs) != aio_context) {
|
||||||
error_setg(errp, "Device '%s' has no medium", target);
|
if (!bdrv_has_blk(target_bs)) {
|
||||||
goto out;
|
/* The target BDS is not attached, we can safely move it to another
|
||||||
|
* AioContext. */
|
||||||
|
bdrv_set_aio_context(target_bs, aio_context);
|
||||||
|
} else {
|
||||||
|
error_setg(errp, "Target is attached to a different thread from "
|
||||||
|
"source.");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
target_bs = blk_bs(target_blk);
|
|
||||||
|
|
||||||
bdrv_set_aio_context(target_bs, aio_context);
|
|
||||||
backup_start(bs, target_bs, speed, sync, NULL, on_source_error,
|
backup_start(bs, target_bs, speed, sync, NULL, on_source_error,
|
||||||
on_target_error, block_job_cb, bs, txn, &local_err);
|
on_target_error, block_job_cb, bs, txn, &local_err);
|
||||||
if (local_err != NULL) {
|
if (local_err != NULL) {
|
||||||
|
|||||||
238
configure
vendored
238
configure
vendored
@@ -31,6 +31,7 @@ TMPCXX="${TMPDIR1}/${TMPB}.cxx"
|
|||||||
TMPL="${TMPDIR1}/${TMPB}.lo"
|
TMPL="${TMPDIR1}/${TMPB}.lo"
|
||||||
TMPA="${TMPDIR1}/lib${TMPB}.la"
|
TMPA="${TMPDIR1}/lib${TMPB}.la"
|
||||||
TMPE="${TMPDIR1}/${TMPB}.exe"
|
TMPE="${TMPDIR1}/${TMPB}.exe"
|
||||||
|
TMPMO="${TMPDIR1}/${TMPB}.mo"
|
||||||
|
|
||||||
rm -f config.log
|
rm -f config.log
|
||||||
|
|
||||||
@@ -164,7 +165,7 @@ have_backend () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# default parameters
|
# default parameters
|
||||||
source_path=`dirname "$0"`
|
source_path=$(dirname "$0")
|
||||||
cpu=""
|
cpu=""
|
||||||
iasl="iasl"
|
iasl="iasl"
|
||||||
interp_prefix="/usr/gnemul/qemu-%M"
|
interp_prefix="/usr/gnemul/qemu-%M"
|
||||||
@@ -323,7 +324,7 @@ jemalloc="no"
|
|||||||
|
|
||||||
# parse CC options first
|
# parse CC options first
|
||||||
for opt do
|
for opt do
|
||||||
optarg=`expr "x$opt" : 'x[^=]*=\(.*\)'`
|
optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)')
|
||||||
case "$opt" in
|
case "$opt" in
|
||||||
--cross-prefix=*) cross_prefix="$optarg"
|
--cross-prefix=*) cross_prefix="$optarg"
|
||||||
;;
|
;;
|
||||||
@@ -398,7 +399,7 @@ if test "$debug_info" = "yes"; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# make source path absolute
|
# make source path absolute
|
||||||
source_path=`cd "$source_path"; pwd`
|
source_path=$(cd "$source_path"; pwd)
|
||||||
|
|
||||||
# running configure in the source tree?
|
# running configure in the source tree?
|
||||||
# we know that's the case if configure is there.
|
# we know that's the case if configure is there.
|
||||||
@@ -443,7 +444,7 @@ elif check_define __sun__ ; then
|
|||||||
elif check_define __HAIKU__ ; then
|
elif check_define __HAIKU__ ; then
|
||||||
targetos='Haiku'
|
targetos='Haiku'
|
||||||
else
|
else
|
||||||
targetos=`uname -s`
|
targetos=$(uname -s)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Some host OSes need non-standard checks for which CPU to use.
|
# Some host OSes need non-standard checks for which CPU to use.
|
||||||
@@ -461,7 +462,7 @@ Darwin)
|
|||||||
fi
|
fi
|
||||||
;;
|
;;
|
||||||
SunOS)
|
SunOS)
|
||||||
# `uname -m` returns i86pc even on an x86_64 box, so default based on isainfo
|
# $(uname -m) returns i86pc even on an x86_64 box, so default based on isainfo
|
||||||
if test -z "$cpu" && test "$(isainfo -k)" = "amd64"; then
|
if test -z "$cpu" && test "$(isainfo -k)" = "amd64"; then
|
||||||
cpu="x86_64"
|
cpu="x86_64"
|
||||||
fi
|
fi
|
||||||
@@ -507,7 +508,7 @@ elif check_define __aarch64__ ; then
|
|||||||
elif check_define __hppa__ ; then
|
elif check_define __hppa__ ; then
|
||||||
cpu="hppa"
|
cpu="hppa"
|
||||||
else
|
else
|
||||||
cpu=`uname -m`
|
cpu=$(uname -m)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
ARCH=
|
ARCH=
|
||||||
@@ -627,7 +628,7 @@ SunOS)
|
|||||||
ld="gld"
|
ld="gld"
|
||||||
smbd="${SMBD-/usr/sfw/sbin/smbd}"
|
smbd="${SMBD-/usr/sfw/sbin/smbd}"
|
||||||
needs_libsunmath="no"
|
needs_libsunmath="no"
|
||||||
solarisrev=`uname -r | cut -f2 -d.`
|
solarisrev=$(uname -r | cut -f2 -d.)
|
||||||
if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
|
if [ "$cpu" = "i386" -o "$cpu" = "x86_64" ] ; then
|
||||||
if test "$solarisrev" -le 9 ; then
|
if test "$solarisrev" -le 9 ; then
|
||||||
if test -f /opt/SUNWspro/prod/lib/libsunmath.so.1; then
|
if test -f /opt/SUNWspro/prod/lib/libsunmath.so.1; then
|
||||||
@@ -722,7 +723,7 @@ fi
|
|||||||
werror=""
|
werror=""
|
||||||
|
|
||||||
for opt do
|
for opt do
|
||||||
optarg=`expr "x$opt" : 'x[^=]*=\(.*\)'`
|
optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)')
|
||||||
case "$opt" in
|
case "$opt" in
|
||||||
--help|-h) show_help=yes
|
--help|-h) show_help=yes
|
||||||
;;
|
;;
|
||||||
@@ -846,9 +847,9 @@ for opt do
|
|||||||
;;
|
;;
|
||||||
--audio-drv-list=*) audio_drv_list="$optarg"
|
--audio-drv-list=*) audio_drv_list="$optarg"
|
||||||
;;
|
;;
|
||||||
--block-drv-rw-whitelist=*|--block-drv-whitelist=*) block_drv_rw_whitelist=`echo "$optarg" | sed -e 's/,/ /g'`
|
--block-drv-rw-whitelist=*|--block-drv-whitelist=*) block_drv_rw_whitelist=$(echo "$optarg" | sed -e 's/,/ /g')
|
||||||
;;
|
;;
|
||||||
--block-drv-ro-whitelist=*) block_drv_ro_whitelist=`echo "$optarg" | sed -e 's/,/ /g'`
|
--block-drv-ro-whitelist=*) block_drv_ro_whitelist=$(echo "$optarg" | sed -e 's/,/ /g')
|
||||||
;;
|
;;
|
||||||
--enable-debug-tcg) debug_tcg="yes"
|
--enable-debug-tcg) debug_tcg="yes"
|
||||||
;;
|
;;
|
||||||
@@ -943,7 +944,7 @@ for opt do
|
|||||||
;;
|
;;
|
||||||
--enable-cocoa)
|
--enable-cocoa)
|
||||||
cocoa="yes" ;
|
cocoa="yes" ;
|
||||||
audio_drv_list="coreaudio `echo $audio_drv_list | sed s,coreaudio,,g`"
|
audio_drv_list="coreaudio $(echo $audio_drv_list | sed s,coreaudio,,g)"
|
||||||
;;
|
;;
|
||||||
--disable-system) softmmu="no"
|
--disable-system) softmmu="no"
|
||||||
;;
|
;;
|
||||||
@@ -1388,7 +1389,7 @@ fi
|
|||||||
|
|
||||||
# Consult white-list to determine whether to enable werror
|
# Consult white-list to determine whether to enable werror
|
||||||
# by default. Only enable by default for git builds
|
# by default. Only enable by default for git builds
|
||||||
z_version=`cut -f3 -d. $source_path/VERSION`
|
z_version=$(cut -f3 -d. $source_path/VERSION)
|
||||||
|
|
||||||
if test -z "$werror" ; then
|
if test -z "$werror" ; then
|
||||||
if test -d "$source_path/.git" -a \
|
if test -d "$source_path/.git" -a \
|
||||||
@@ -1617,7 +1618,7 @@ if test "$solaris" = "yes" ; then
|
|||||||
"install fileutils from www.blastwave.org using pkg-get -i fileutils" \
|
"install fileutils from www.blastwave.org using pkg-get -i fileutils" \
|
||||||
"to get ginstall which is used by default (which lives in /opt/csw/bin)"
|
"to get ginstall which is used by default (which lives in /opt/csw/bin)"
|
||||||
fi
|
fi
|
||||||
if test "`path_of $install`" = "/usr/sbin/install" ; then
|
if test "$(path_of $install)" = "/usr/sbin/install" ; then
|
||||||
error_exit "Solaris /usr/sbin/install is not an appropriate install program." \
|
error_exit "Solaris /usr/sbin/install is not an appropriate install program." \
|
||||||
"try ginstall from the GNU fileutils available from www.blastwave.org" \
|
"try ginstall from the GNU fileutils available from www.blastwave.org" \
|
||||||
"using pkg-get -i fileutils, or use --install=/usr/ucb/install"
|
"using pkg-get -i fileutils, or use --install=/usr/ucb/install"
|
||||||
@@ -1636,7 +1637,7 @@ fi
|
|||||||
if test -z "${target_list+xxx}" ; then
|
if test -z "${target_list+xxx}" ; then
|
||||||
target_list="$default_target_list"
|
target_list="$default_target_list"
|
||||||
else
|
else
|
||||||
target_list=`echo "$target_list" | sed -e 's/,/ /g'`
|
target_list=$(echo "$target_list" | sed -e 's/,/ /g')
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check that we recognised the target name; this allows a more
|
# Check that we recognised the target name; this allows a more
|
||||||
@@ -1886,8 +1887,8 @@ if test "$seccomp" != "no" ; then
|
|||||||
|
|
||||||
if test "$libseccomp_minver" != "" &&
|
if test "$libseccomp_minver" != "" &&
|
||||||
$pkg_config --atleast-version=$libseccomp_minver libseccomp ; then
|
$pkg_config --atleast-version=$libseccomp_minver libseccomp ; then
|
||||||
libs_softmmu="$libs_softmmu `$pkg_config --libs libseccomp`"
|
libs_softmmu="$libs_softmmu $($pkg_config --libs libseccomp)"
|
||||||
QEMU_CFLAGS="$QEMU_CFLAGS `$pkg_config --cflags libseccomp`"
|
QEMU_CFLAGS="$QEMU_CFLAGS $($pkg_config --cflags libseccomp)"
|
||||||
seccomp="yes"
|
seccomp="yes"
|
||||||
else
|
else
|
||||||
if test "$seccomp" = "yes" ; then
|
if test "$seccomp" = "yes" ; then
|
||||||
@@ -2127,8 +2128,8 @@ fi
|
|||||||
x11_cflags=
|
x11_cflags=
|
||||||
x11_libs=-lX11
|
x11_libs=-lX11
|
||||||
if $pkg_config --exists "x11"; then
|
if $pkg_config --exists "x11"; then
|
||||||
x11_cflags=`$pkg_config --cflags x11`
|
x11_cflags=$($pkg_config --cflags x11)
|
||||||
x11_libs=`$pkg_config --libs x11`
|
x11_libs=$($pkg_config --libs x11)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
##########################################
|
##########################################
|
||||||
@@ -2155,9 +2156,9 @@ if test "$gtk" != "no"; then
|
|||||||
gtkversion="2.18.0"
|
gtkversion="2.18.0"
|
||||||
fi
|
fi
|
||||||
if $pkg_config --exists "$gtkpackage >= $gtkversion"; then
|
if $pkg_config --exists "$gtkpackage >= $gtkversion"; then
|
||||||
gtk_cflags=`$pkg_config --cflags $gtkpackage`
|
gtk_cflags=$($pkg_config --cflags $gtkpackage)
|
||||||
gtk_libs=`$pkg_config --libs $gtkpackage`
|
gtk_libs=$($pkg_config --libs $gtkpackage)
|
||||||
gtk_version=`$pkg_config --modversion $gtkpackage`
|
gtk_version=$($pkg_config --modversion $gtkpackage)
|
||||||
if $pkg_config --exists "$gtkx11package >= $gtkversion"; then
|
if $pkg_config --exists "$gtkx11package >= $gtkversion"; then
|
||||||
gtk_cflags="$gtk_cflags $x11_cflags"
|
gtk_cflags="$gtk_cflags $x11_cflags"
|
||||||
gtk_libs="$gtk_libs $x11_libs"
|
gtk_libs="$gtk_libs $x11_libs"
|
||||||
@@ -2195,8 +2196,8 @@ gnutls_gcrypt=no
|
|||||||
gnutls_nettle=no
|
gnutls_nettle=no
|
||||||
if test "$gnutls" != "no"; then
|
if test "$gnutls" != "no"; then
|
||||||
if gnutls_works; then
|
if gnutls_works; then
|
||||||
gnutls_cflags=`$pkg_config --cflags gnutls`
|
gnutls_cflags=$($pkg_config --cflags gnutls)
|
||||||
gnutls_libs=`$pkg_config --libs gnutls`
|
gnutls_libs=$($pkg_config --libs gnutls)
|
||||||
libs_softmmu="$gnutls_libs $libs_softmmu"
|
libs_softmmu="$gnutls_libs $libs_softmmu"
|
||||||
libs_tools="$gnutls_libs $libs_tools"
|
libs_tools="$gnutls_libs $libs_tools"
|
||||||
QEMU_CFLAGS="$QEMU_CFLAGS $gnutls_cflags"
|
QEMU_CFLAGS="$QEMU_CFLAGS $gnutls_cflags"
|
||||||
@@ -2220,7 +2221,7 @@ if test "$gnutls" != "no"; then
|
|||||||
gnutls_gcrypt=no
|
gnutls_gcrypt=no
|
||||||
gnutls_nettle=yes
|
gnutls_nettle=yes
|
||||||
elif $pkg_config --exists 'gnutls >= 2.12'; then
|
elif $pkg_config --exists 'gnutls >= 2.12'; then
|
||||||
case `$pkg_config --libs --static gnutls` in
|
case $($pkg_config --libs --static gnutls) in
|
||||||
*gcrypt*)
|
*gcrypt*)
|
||||||
gnutls_gcrypt=yes
|
gnutls_gcrypt=yes
|
||||||
gnutls_nettle=no
|
gnutls_nettle=no
|
||||||
@@ -2281,7 +2282,7 @@ has_libgcrypt_config() {
|
|||||||
|
|
||||||
if test -n "$cross_prefix"
|
if test -n "$cross_prefix"
|
||||||
then
|
then
|
||||||
host=`libgcrypt-config --host`
|
host=$(libgcrypt-config --host)
|
||||||
if test "$host-" != $cross_prefix
|
if test "$host-" != $cross_prefix
|
||||||
then
|
then
|
||||||
return 1
|
return 1
|
||||||
@@ -2293,8 +2294,8 @@ has_libgcrypt_config() {
|
|||||||
|
|
||||||
if test "$gcrypt" != "no"; then
|
if test "$gcrypt" != "no"; then
|
||||||
if has_libgcrypt_config; then
|
if has_libgcrypt_config; then
|
||||||
gcrypt_cflags=`libgcrypt-config --cflags`
|
gcrypt_cflags=$(libgcrypt-config --cflags)
|
||||||
gcrypt_libs=`libgcrypt-config --libs`
|
gcrypt_libs=$(libgcrypt-config --libs)
|
||||||
# Debian has remove -lgpg-error from libgcrypt-config
|
# Debian has remove -lgpg-error from libgcrypt-config
|
||||||
# as it "spreads unnecessary dependencies" which in
|
# as it "spreads unnecessary dependencies" which in
|
||||||
# turn breaks static builds...
|
# turn breaks static builds...
|
||||||
@@ -2334,15 +2335,16 @@ fi
|
|||||||
|
|
||||||
if test "$nettle" != "no"; then
|
if test "$nettle" != "no"; then
|
||||||
if $pkg_config --exists "nettle"; then
|
if $pkg_config --exists "nettle"; then
|
||||||
nettle_cflags=`$pkg_config --cflags nettle`
|
nettle_cflags=$($pkg_config --cflags nettle)
|
||||||
nettle_libs=`$pkg_config --libs nettle`
|
nettle_libs=$($pkg_config --libs nettle)
|
||||||
nettle_version=`$pkg_config --modversion nettle`
|
nettle_version=$($pkg_config --modversion nettle)
|
||||||
libs_softmmu="$nettle_libs $libs_softmmu"
|
libs_softmmu="$nettle_libs $libs_softmmu"
|
||||||
libs_tools="$nettle_libs $libs_tools"
|
libs_tools="$nettle_libs $libs_tools"
|
||||||
QEMU_CFLAGS="$QEMU_CFLAGS $nettle_cflags"
|
QEMU_CFLAGS="$QEMU_CFLAGS $nettle_cflags"
|
||||||
nettle="yes"
|
nettle="yes"
|
||||||
|
|
||||||
cat > $TMPC << EOF
|
cat > $TMPC << EOF
|
||||||
|
#include <stddef.h>
|
||||||
#include <nettle/pbkdf2.h>
|
#include <nettle/pbkdf2.h>
|
||||||
int main(void) {
|
int main(void) {
|
||||||
pbkdf2_hmac_sha256(8, NULL, 1000, 8, NULL, 8, NULL);
|
pbkdf2_hmac_sha256(8, NULL, 1000, 8, NULL, 8, NULL);
|
||||||
@@ -2373,8 +2375,8 @@ tasn1=yes
|
|||||||
tasn1_cflags=""
|
tasn1_cflags=""
|
||||||
tasn1_libs=""
|
tasn1_libs=""
|
||||||
if $pkg_config --exists "libtasn1"; then
|
if $pkg_config --exists "libtasn1"; then
|
||||||
tasn1_cflags=`$pkg_config --cflags libtasn1`
|
tasn1_cflags=$($pkg_config --cflags libtasn1)
|
||||||
tasn1_libs=`$pkg_config --libs libtasn1`
|
tasn1_libs=$($pkg_config --libs libtasn1)
|
||||||
else
|
else
|
||||||
tasn1=no
|
tasn1=no
|
||||||
fi
|
fi
|
||||||
@@ -2404,9 +2406,9 @@ if test "$vte" != "no"; then
|
|||||||
vteminversion="0.24.0"
|
vteminversion="0.24.0"
|
||||||
fi
|
fi
|
||||||
if $pkg_config --exists "$vtepackage >= $vteminversion"; then
|
if $pkg_config --exists "$vtepackage >= $vteminversion"; then
|
||||||
vte_cflags=`$pkg_config --cflags $vtepackage`
|
vte_cflags=$($pkg_config --cflags $vtepackage)
|
||||||
vte_libs=`$pkg_config --libs $vtepackage`
|
vte_libs=$($pkg_config --libs $vtepackage)
|
||||||
vteversion=`$pkg_config --modversion $vtepackage`
|
vteversion=$($pkg_config --modversion $vtepackage)
|
||||||
libs_softmmu="$vte_libs $libs_softmmu"
|
libs_softmmu="$vte_libs $libs_softmmu"
|
||||||
vte="yes"
|
vte="yes"
|
||||||
elif test "$vte" = "yes"; then
|
elif test "$vte" = "yes"; then
|
||||||
@@ -2447,16 +2449,16 @@ else
|
|||||||
error_exit "Unknown sdlabi $sdlabi, must be 1.2 or 2.0"
|
error_exit "Unknown sdlabi $sdlabi, must be 1.2 or 2.0"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "`basename $sdl_config`" != $sdlconfigname && ! has ${sdl_config}; then
|
if test "$(basename $sdl_config)" != $sdlconfigname && ! has ${sdl_config}; then
|
||||||
sdl_config=$sdlconfigname
|
sdl_config=$sdlconfigname
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if $pkg_config $sdlname --exists; then
|
if $pkg_config $sdlname --exists; then
|
||||||
sdlconfig="$pkg_config $sdlname"
|
sdlconfig="$pkg_config $sdlname"
|
||||||
sdlversion=`$sdlconfig --modversion 2>/dev/null`
|
sdlversion=$($sdlconfig --modversion 2>/dev/null)
|
||||||
elif has ${sdl_config}; then
|
elif has ${sdl_config}; then
|
||||||
sdlconfig="$sdl_config"
|
sdlconfig="$sdl_config"
|
||||||
sdlversion=`$sdlconfig --version`
|
sdlversion=$($sdlconfig --version)
|
||||||
else
|
else
|
||||||
if test "$sdl" = "yes" ; then
|
if test "$sdl" = "yes" ; then
|
||||||
feature_not_found "sdl" "Install SDL devel"
|
feature_not_found "sdl" "Install SDL devel"
|
||||||
@@ -2474,14 +2476,14 @@ if test "$sdl" != "no" ; then
|
|||||||
#undef main /* We don't want SDL to override our main() */
|
#undef main /* We don't want SDL to override our main() */
|
||||||
int main( void ) { return SDL_Init (SDL_INIT_VIDEO); }
|
int main( void ) { return SDL_Init (SDL_INIT_VIDEO); }
|
||||||
EOF
|
EOF
|
||||||
sdl_cflags=`$sdlconfig --cflags 2> /dev/null`
|
sdl_cflags=$($sdlconfig --cflags 2>/dev/null)
|
||||||
if test "$static" = "yes" ; then
|
if test "$static" = "yes" ; then
|
||||||
sdl_libs=`$sdlconfig --static-libs 2>/dev/null`
|
sdl_libs=$($sdlconfig --static-libs 2>/dev/null)
|
||||||
else
|
else
|
||||||
sdl_libs=`$sdlconfig --libs 2> /dev/null`
|
sdl_libs=$($sdlconfig --libs 2>/dev/null)
|
||||||
fi
|
fi
|
||||||
if compile_prog "$sdl_cflags" "$sdl_libs" ; then
|
if compile_prog "$sdl_cflags" "$sdl_libs" ; then
|
||||||
if test `echo $sdlversion | sed 's/[^0-9]//g'` -lt 121 ; then
|
if test $(echo $sdlversion | sed 's/[^0-9]//g') -lt 121 ; then
|
||||||
sdl_too_old=yes
|
sdl_too_old=yes
|
||||||
else
|
else
|
||||||
sdl=yes
|
sdl=yes
|
||||||
@@ -2490,8 +2492,8 @@ EOF
|
|||||||
# static link with sdl ? (note: sdl.pc's --static --libs is broken)
|
# static link with sdl ? (note: sdl.pc's --static --libs is broken)
|
||||||
if test "$sdl" = "yes" -a "$static" = "yes" ; then
|
if test "$sdl" = "yes" -a "$static" = "yes" ; then
|
||||||
if test $? = 0 && echo $sdl_libs | grep -- -laa > /dev/null; then
|
if test $? = 0 && echo $sdl_libs | grep -- -laa > /dev/null; then
|
||||||
sdl_libs="$sdl_libs `aalib-config --static-libs 2>/dev/null`"
|
sdl_libs="$sdl_libs $(aalib-config --static-libs 2>/dev/null)"
|
||||||
sdl_cflags="$sdl_cflags `aalib-config --cflags 2>/dev/null`"
|
sdl_cflags="$sdl_cflags $(aalib-config --cflags 2>/dev/null)"
|
||||||
fi
|
fi
|
||||||
if compile_prog "$sdl_cflags" "$sdl_libs" ; then
|
if compile_prog "$sdl_cflags" "$sdl_libs" ; then
|
||||||
:
|
:
|
||||||
@@ -2608,8 +2610,8 @@ int main(void) {
|
|||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
if $pkg_config libpng --exists; then
|
if $pkg_config libpng --exists; then
|
||||||
vnc_png_cflags=`$pkg_config libpng --cflags`
|
vnc_png_cflags=$($pkg_config libpng --cflags)
|
||||||
vnc_png_libs=`$pkg_config libpng --libs`
|
vnc_png_libs=$($pkg_config libpng --libs)
|
||||||
else
|
else
|
||||||
vnc_png_cflags=""
|
vnc_png_cflags=""
|
||||||
vnc_png_libs="-lpng"
|
vnc_png_libs="-lpng"
|
||||||
@@ -2803,7 +2805,7 @@ EOF
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
audio_drv_list=`echo "$audio_drv_list" | sed -e 's/,/ /g'`
|
audio_drv_list=$(echo "$audio_drv_list" | sed -e 's/,/ /g')
|
||||||
for drv in $audio_drv_list; do
|
for drv in $audio_drv_list; do
|
||||||
case $drv in
|
case $drv in
|
||||||
alsa)
|
alsa)
|
||||||
@@ -2813,8 +2815,8 @@ for drv in $audio_drv_list; do
|
|||||||
;;
|
;;
|
||||||
|
|
||||||
pa)
|
pa)
|
||||||
audio_drv_probe $drv pulse/mainloop.h "-lpulse" \
|
audio_drv_probe $drv pulse/pulseaudio.h "-lpulse" \
|
||||||
"pa_mainloop *m = 0; pa_mainloop_free (m); return 0;"
|
"pa_context_set_source_output_volume(NULL, 0, NULL, NULL, NULL); return 0;"
|
||||||
libs_softmmu="-lpulse $libs_softmmu"
|
libs_softmmu="-lpulse $libs_softmmu"
|
||||||
audio_pt_int="yes"
|
audio_pt_int="yes"
|
||||||
;;
|
;;
|
||||||
@@ -2915,8 +2917,8 @@ if test "$curl" != "no" ; then
|
|||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
int main(void) { curl_easy_init(); curl_multi_setopt(0, 0, 0); return 0; }
|
int main(void) { curl_easy_init(); curl_multi_setopt(0, 0, 0); return 0; }
|
||||||
EOF
|
EOF
|
||||||
curl_cflags=`$curlconfig --cflags 2>/dev/null`
|
curl_cflags=$($curlconfig --cflags 2>/dev/null)
|
||||||
curl_libs=`$curlconfig --libs 2>/dev/null`
|
curl_libs=$($curlconfig --libs 2>/dev/null)
|
||||||
if compile_prog "$curl_cflags" "$curl_libs" ; then
|
if compile_prog "$curl_cflags" "$curl_libs" ; then
|
||||||
curl=yes
|
curl=yes
|
||||||
else
|
else
|
||||||
@@ -2934,8 +2936,8 @@ if test "$bluez" != "no" ; then
|
|||||||
#include <bluetooth/bluetooth.h>
|
#include <bluetooth/bluetooth.h>
|
||||||
int main(void) { return bt_error(0); }
|
int main(void) { return bt_error(0); }
|
||||||
EOF
|
EOF
|
||||||
bluez_cflags=`$pkg_config --cflags bluez 2> /dev/null`
|
bluez_cflags=$($pkg_config --cflags bluez 2>/dev/null)
|
||||||
bluez_libs=`$pkg_config --libs bluez 2> /dev/null`
|
bluez_libs=$($pkg_config --libs bluez 2>/dev/null)
|
||||||
if compile_prog "$bluez_cflags" "$bluez_libs" ; then
|
if compile_prog "$bluez_cflags" "$bluez_libs" ; then
|
||||||
bluez=yes
|
bluez=yes
|
||||||
libs_softmmu="$bluez_libs $libs_softmmu"
|
libs_softmmu="$bluez_libs $libs_softmmu"
|
||||||
@@ -2958,8 +2960,8 @@ fi
|
|||||||
|
|
||||||
for i in $glib_modules; do
|
for i in $glib_modules; do
|
||||||
if $pkg_config --atleast-version=$glib_req_ver $i; then
|
if $pkg_config --atleast-version=$glib_req_ver $i; then
|
||||||
glib_cflags=`$pkg_config --cflags $i`
|
glib_cflags=$($pkg_config --cflags $i)
|
||||||
glib_libs=`$pkg_config --libs $i`
|
glib_libs=$($pkg_config --libs $i)
|
||||||
CFLAGS="$glib_cflags $CFLAGS"
|
CFLAGS="$glib_cflags $CFLAGS"
|
||||||
LIBS="$glib_libs $LIBS"
|
LIBS="$glib_libs $LIBS"
|
||||||
libs_qga="$glib_libs $libs_qga"
|
libs_qga="$glib_libs $libs_qga"
|
||||||
@@ -3048,8 +3050,8 @@ if test "$pixman" = "none"; then
|
|||||||
pixman_libs=
|
pixman_libs=
|
||||||
elif test "$pixman" = "system"; then
|
elif test "$pixman" = "system"; then
|
||||||
# pixman version has been checked above
|
# pixman version has been checked above
|
||||||
pixman_cflags=`$pkg_config --cflags pixman-1`
|
pixman_cflags=$($pkg_config --cflags pixman-1)
|
||||||
pixman_libs=`$pkg_config --libs pixman-1`
|
pixman_libs=$($pkg_config --libs pixman-1)
|
||||||
else
|
else
|
||||||
if test ! -d ${source_path}/pixman/pixman; then
|
if test ! -d ${source_path}/pixman/pixman; then
|
||||||
error_exit "pixman >= 0.21.8 not present. Your options:" \
|
error_exit "pixman >= 0.21.8 not present. Your options:" \
|
||||||
@@ -3165,8 +3167,8 @@ fi
|
|||||||
min_libssh2_version=1.2.8
|
min_libssh2_version=1.2.8
|
||||||
if test "$libssh2" != "no" ; then
|
if test "$libssh2" != "no" ; then
|
||||||
if $pkg_config --atleast-version=$min_libssh2_version libssh2; then
|
if $pkg_config --atleast-version=$min_libssh2_version libssh2; then
|
||||||
libssh2_cflags=`$pkg_config libssh2 --cflags`
|
libssh2_cflags=$($pkg_config libssh2 --cflags)
|
||||||
libssh2_libs=`$pkg_config libssh2 --libs`
|
libssh2_libs=$($pkg_config libssh2 --libs)
|
||||||
libssh2=yes
|
libssh2=yes
|
||||||
else
|
else
|
||||||
if test "$libssh2" = "yes" ; then
|
if test "$libssh2" = "yes" ; then
|
||||||
@@ -3417,8 +3419,8 @@ fi
|
|||||||
if test "$glusterfs" != "no" ; then
|
if test "$glusterfs" != "no" ; then
|
||||||
if $pkg_config --atleast-version=3 glusterfs-api; then
|
if $pkg_config --atleast-version=3 glusterfs-api; then
|
||||||
glusterfs="yes"
|
glusterfs="yes"
|
||||||
glusterfs_cflags=`$pkg_config --cflags glusterfs-api`
|
glusterfs_cflags=$($pkg_config --cflags glusterfs-api)
|
||||||
glusterfs_libs=`$pkg_config --libs glusterfs-api`
|
glusterfs_libs=$($pkg_config --libs glusterfs-api)
|
||||||
if $pkg_config --atleast-version=4 glusterfs-api; then
|
if $pkg_config --atleast-version=4 glusterfs-api; then
|
||||||
glusterfs_xlator_opt="yes"
|
glusterfs_xlator_opt="yes"
|
||||||
fi
|
fi
|
||||||
@@ -3798,8 +3800,8 @@ if compile_prog "" "" ; then
|
|||||||
epoll=yes
|
epoll=yes
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# epoll_create1 and epoll_pwait are later additions
|
# epoll_create1 is a later addition
|
||||||
# so we must check separately for their presence
|
# so we must check separately for its presence
|
||||||
epoll_create1=no
|
epoll_create1=no
|
||||||
cat > $TMPC << EOF
|
cat > $TMPC << EOF
|
||||||
#include <sys/epoll.h>
|
#include <sys/epoll.h>
|
||||||
@@ -3821,20 +3823,6 @@ if compile_prog "" "" ; then
|
|||||||
epoll_create1=yes
|
epoll_create1=yes
|
||||||
fi
|
fi
|
||||||
|
|
||||||
epoll_pwait=no
|
|
||||||
cat > $TMPC << EOF
|
|
||||||
#include <sys/epoll.h>
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
epoll_pwait(0, 0, 0, 0, 0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
EOF
|
|
||||||
if compile_prog "" "" ; then
|
|
||||||
epoll_pwait=yes
|
|
||||||
fi
|
|
||||||
|
|
||||||
# check for sendfile support
|
# check for sendfile support
|
||||||
sendfile=no
|
sendfile=no
|
||||||
cat > $TMPC << EOF
|
cat > $TMPC << EOF
|
||||||
@@ -4225,12 +4213,12 @@ int main(void) { return 0; }
|
|||||||
EOF
|
EOF
|
||||||
if compile_prog "" "" ; then
|
if compile_prog "" "" ; then
|
||||||
if $pkg_config lttng-ust --exists; then
|
if $pkg_config lttng-ust --exists; then
|
||||||
lttng_ust_libs=`$pkg_config --libs lttng-ust`
|
lttng_ust_libs=$($pkg_config --libs lttng-ust)
|
||||||
else
|
else
|
||||||
lttng_ust_libs="-llttng-ust"
|
lttng_ust_libs="-llttng-ust"
|
||||||
fi
|
fi
|
||||||
if $pkg_config liburcu-bp --exists; then
|
if $pkg_config liburcu-bp --exists; then
|
||||||
urcu_bp_libs=`$pkg_config --libs liburcu-bp`
|
urcu_bp_libs=$($pkg_config --libs liburcu-bp)
|
||||||
else
|
else
|
||||||
urcu_bp_libs="-lurcu-bp"
|
urcu_bp_libs="-lurcu-bp"
|
||||||
fi
|
fi
|
||||||
@@ -4526,6 +4514,38 @@ if compile_prog "" "" ; then
|
|||||||
have_fsxattr=yes
|
have_fsxattr=yes
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
##########################################
|
||||||
|
# check if rtnetlink.h exists and is useful
|
||||||
|
have_rtnetlink=no
|
||||||
|
cat > $TMPC << EOF
|
||||||
|
#include <linux/rtnetlink.h>
|
||||||
|
int main(void) {
|
||||||
|
return IFLA_PROTO_DOWN;
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
if compile_prog "" "" ; then
|
||||||
|
have_rtnetlink=yes
|
||||||
|
fi
|
||||||
|
|
||||||
|
#################################################
|
||||||
|
# Sparc implicitly links with --relax, which is
|
||||||
|
# incompatible with -r, so --no-relax should be
|
||||||
|
# given. It does no harm to give it on other
|
||||||
|
# platforms too.
|
||||||
|
|
||||||
|
# Note: the prototype is needed since QEMU_CFLAGS
|
||||||
|
# contains -Wmissing-prototypes
|
||||||
|
cat > $TMPC << EOF
|
||||||
|
extern int foo(void);
|
||||||
|
int foo(void) { return 0; }
|
||||||
|
EOF
|
||||||
|
if ! compile_object ""; then
|
||||||
|
error_exit "Failed to compile object file for LD_REL_FLAGS test"
|
||||||
|
fi
|
||||||
|
if do_cc -nostdlib -Wl,-r -Wl,--no-relax -o $TMPMO $TMPO; then
|
||||||
|
LD_REL_FLAGS="-Wl,--no-relax"
|
||||||
|
fi
|
||||||
|
|
||||||
##########################################
|
##########################################
|
||||||
# End of CC checks
|
# End of CC checks
|
||||||
# After here, no more $cc or $ld runs
|
# After here, no more $cc or $ld runs
|
||||||
@@ -4670,10 +4690,10 @@ if test "$guest_agent_msi" = "yes"; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if test "$QEMU_GA_VERSION" = ""; then
|
if test "$QEMU_GA_VERSION" = ""; then
|
||||||
QEMU_GA_VERSION=`cat $source_path/VERSION`
|
QEMU_GA_VERSION=$(cat $source_path/VERSION)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
QEMU_GA_MSI_MINGW_DLL_PATH="-D Mingw_dlls=`$pkg_config --variable=prefix glib-2.0`/bin"
|
QEMU_GA_MSI_MINGW_DLL_PATH="-D Mingw_dlls=$($pkg_config --variable=prefix glib-2.0)/bin"
|
||||||
|
|
||||||
case "$cpu" in
|
case "$cpu" in
|
||||||
x86_64)
|
x86_64)
|
||||||
@@ -4747,16 +4767,16 @@ QEMU_CFLAGS="$pixman_cflags $fdt_cflags $QEMU_CFLAGS"
|
|||||||
libs_softmmu="$pixman_libs $libs_softmmu"
|
libs_softmmu="$pixman_libs $libs_softmmu"
|
||||||
|
|
||||||
echo "Install prefix $prefix"
|
echo "Install prefix $prefix"
|
||||||
echo "BIOS directory `eval echo $qemu_datadir`"
|
echo "BIOS directory $(eval echo $qemu_datadir)"
|
||||||
echo "binary directory `eval echo $bindir`"
|
echo "binary directory $(eval echo $bindir)"
|
||||||
echo "library directory `eval echo $libdir`"
|
echo "library directory $(eval echo $libdir)"
|
||||||
echo "module directory `eval echo $qemu_moddir`"
|
echo "module directory $(eval echo $qemu_moddir)"
|
||||||
echo "libexec directory `eval echo $libexecdir`"
|
echo "libexec directory $(eval echo $libexecdir)"
|
||||||
echo "include directory `eval echo $includedir`"
|
echo "include directory $(eval echo $includedir)"
|
||||||
echo "config directory `eval echo $sysconfdir`"
|
echo "config directory $(eval echo $sysconfdir)"
|
||||||
if test "$mingw32" = "no" ; then
|
if test "$mingw32" = "no" ; then
|
||||||
echo "local state directory `eval echo $local_statedir`"
|
echo "local state directory $(eval echo $local_statedir)"
|
||||||
echo "Manual directory `eval echo $mandir`"
|
echo "Manual directory $(eval echo $mandir)"
|
||||||
echo "ELF interp prefix $interp_prefix"
|
echo "ELF interp prefix $interp_prefix"
|
||||||
else
|
else
|
||||||
echo "local state directory queried at runtime"
|
echo "local state directory queried at runtime"
|
||||||
@@ -4791,16 +4811,16 @@ if test "$darwin" = "yes" ; then
|
|||||||
echo "Cocoa support $cocoa"
|
echo "Cocoa support $cocoa"
|
||||||
fi
|
fi
|
||||||
echo "pixman $pixman"
|
echo "pixman $pixman"
|
||||||
echo "SDL support $sdl `echo_version $sdl $sdlversion`"
|
echo "SDL support $sdl $(echo_version $sdl $sdlversion)"
|
||||||
echo "GTK support $gtk `echo_version $gtk $gtk_version`"
|
echo "GTK support $gtk $(echo_version $gtk $gtk_version)"
|
||||||
echo "GTK GL support $gtk_gl"
|
echo "GTK GL support $gtk_gl"
|
||||||
echo "VTE support $vte `echo_version $vte $vteversion`"
|
echo "VTE support $vte $(echo_version $vte $vteversion)"
|
||||||
echo "GNUTLS support $gnutls"
|
echo "GNUTLS support $gnutls"
|
||||||
echo "GNUTLS hash $gnutls_hash"
|
echo "GNUTLS hash $gnutls_hash"
|
||||||
echo "GNUTLS rnd $gnutls_rnd"
|
echo "GNUTLS rnd $gnutls_rnd"
|
||||||
echo "libgcrypt $gcrypt"
|
echo "libgcrypt $gcrypt"
|
||||||
echo "libgcrypt kdf $gcrypt_kdf"
|
echo "libgcrypt kdf $gcrypt_kdf"
|
||||||
echo "nettle $nettle `echo_version $nettle $nettle_version`"
|
echo "nettle $nettle $(echo_version $nettle $nettle_version)"
|
||||||
echo "nettle kdf $nettle_kdf"
|
echo "nettle kdf $nettle_kdf"
|
||||||
echo "libtasn1 $tasn1"
|
echo "libtasn1 $tasn1"
|
||||||
echo "curses support $curses"
|
echo "curses support $curses"
|
||||||
@@ -4851,7 +4871,7 @@ echo "Trace backends $trace_backends"
|
|||||||
if have_backend "simple"; then
|
if have_backend "simple"; then
|
||||||
echo "Trace output file $trace_file-<pid>"
|
echo "Trace output file $trace_file-<pid>"
|
||||||
fi
|
fi
|
||||||
echo "spice support $spice `echo_version $spice $spice_protocol_version/$spice_server_version`"
|
echo "spice support $spice $(echo_version $spice $spice_protocol_version/$spice_server_version)"
|
||||||
echo "rbd support $rbd"
|
echo "rbd support $rbd"
|
||||||
echo "xfsctl support $xfs"
|
echo "xfsctl support $xfs"
|
||||||
echo "smartcard support $smartcard"
|
echo "smartcard support $smartcard"
|
||||||
@@ -4930,7 +4950,7 @@ if test "$bigendian" = "yes" ; then
|
|||||||
fi
|
fi
|
||||||
if test "$mingw32" = "yes" ; then
|
if test "$mingw32" = "yes" ; then
|
||||||
echo "CONFIG_WIN32=y" >> $config_host_mak
|
echo "CONFIG_WIN32=y" >> $config_host_mak
|
||||||
rc_version=`cat $source_path/VERSION`
|
rc_version=$(cat $source_path/VERSION)
|
||||||
version_major=${rc_version%%.*}
|
version_major=${rc_version%%.*}
|
||||||
rc_version=${rc_version#*.}
|
rc_version=${rc_version#*.}
|
||||||
version_minor=${rc_version%%.*}
|
version_minor=${rc_version%%.*}
|
||||||
@@ -5006,7 +5026,7 @@ if test "$cap_ng" = "yes" ; then
|
|||||||
fi
|
fi
|
||||||
echo "CONFIG_AUDIO_DRIVERS=$audio_drv_list" >> $config_host_mak
|
echo "CONFIG_AUDIO_DRIVERS=$audio_drv_list" >> $config_host_mak
|
||||||
for drv in $audio_drv_list; do
|
for drv in $audio_drv_list; do
|
||||||
def=CONFIG_`echo $drv | LC_ALL=C tr '[a-z]' '[A-Z]'`
|
def=CONFIG_$(echo $drv | LC_ALL=C tr '[a-z]' '[A-Z]')
|
||||||
echo "$def=y" >> $config_host_mak
|
echo "$def=y" >> $config_host_mak
|
||||||
done
|
done
|
||||||
if test "$audio_pt_int" = "yes" ; then
|
if test "$audio_pt_int" = "yes" ; then
|
||||||
@@ -5038,7 +5058,7 @@ fi
|
|||||||
if test "$xfs" = "yes" ; then
|
if test "$xfs" = "yes" ; then
|
||||||
echo "CONFIG_XFS=y" >> $config_host_mak
|
echo "CONFIG_XFS=y" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
qemu_version=`head $source_path/VERSION`
|
qemu_version=$(head $source_path/VERSION)
|
||||||
echo "VERSION=$qemu_version" >>$config_host_mak
|
echo "VERSION=$qemu_version" >>$config_host_mak
|
||||||
echo "PKGVERSION=$pkgversion" >>$config_host_mak
|
echo "PKGVERSION=$pkgversion" >>$config_host_mak
|
||||||
echo "SRC_PATH=$source_path" >> $config_host_mak
|
echo "SRC_PATH=$source_path" >> $config_host_mak
|
||||||
@@ -5049,7 +5069,7 @@ fi
|
|||||||
if test "$modules" = "yes"; then
|
if test "$modules" = "yes"; then
|
||||||
# $shacmd can generate a hash started with digit, which the compiler doesn't
|
# $shacmd can generate a hash started with digit, which the compiler doesn't
|
||||||
# like as an symbol. So prefix it with an underscore
|
# like as an symbol. So prefix it with an underscore
|
||||||
echo "CONFIG_STAMP=_`(echo $qemu_version; echo $pkgversion; cat $0) | $shacmd - | cut -f1 -d\ `" >> $config_host_mak
|
echo "CONFIG_STAMP=_$( (echo $qemu_version; echo $pkgversion; cat $0) | $shacmd - | cut -f1 -d\ )" >> $config_host_mak
|
||||||
echo "CONFIG_MODULES=y" >> $config_host_mak
|
echo "CONFIG_MODULES=y" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
if test "$sdl" = "yes" ; then
|
if test "$sdl" = "yes" ; then
|
||||||
@@ -5114,9 +5134,6 @@ fi
|
|||||||
if test "$epoll_create1" = "yes" ; then
|
if test "$epoll_create1" = "yes" ; then
|
||||||
echo "CONFIG_EPOLL_CREATE1=y" >> $config_host_mak
|
echo "CONFIG_EPOLL_CREATE1=y" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
if test "$epoll_pwait" = "yes" ; then
|
|
||||||
echo "CONFIG_EPOLL_PWAIT=y" >> $config_host_mak
|
|
||||||
fi
|
|
||||||
if test "$sendfile" = "yes" ; then
|
if test "$sendfile" = "yes" ; then
|
||||||
echo "CONFIG_SENDFILE=y" >> $config_host_mak
|
echo "CONFIG_SENDFILE=y" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
@@ -5461,6 +5478,10 @@ if test "$rdma" = "yes" ; then
|
|||||||
echo "CONFIG_RDMA=y" >> $config_host_mak
|
echo "CONFIG_RDMA=y" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "$have_rtnetlink" = "yes" ; then
|
||||||
|
echo "CONFIG_RTNETLINK=y" >> $config_host_mak
|
||||||
|
fi
|
||||||
|
|
||||||
# Hold two types of flag:
|
# Hold two types of flag:
|
||||||
# CONFIG_THREAD_SETNAME_BYTHREAD - we've got a way of setting the name on
|
# CONFIG_THREAD_SETNAME_BYTHREAD - we've got a way of setting the name on
|
||||||
# a thread we have a handle to
|
# a thread we have a handle to
|
||||||
@@ -5529,6 +5550,7 @@ else
|
|||||||
fi
|
fi
|
||||||
echo "LDFLAGS=$LDFLAGS" >> $config_host_mak
|
echo "LDFLAGS=$LDFLAGS" >> $config_host_mak
|
||||||
echo "LDFLAGS_NOPIE=$LDFLAGS_NOPIE" >> $config_host_mak
|
echo "LDFLAGS_NOPIE=$LDFLAGS_NOPIE" >> $config_host_mak
|
||||||
|
echo "LD_REL_FLAGS=$LD_REL_FLAGS" >> $config_host_mak
|
||||||
echo "LIBS+=$LIBS" >> $config_host_mak
|
echo "LIBS+=$LIBS" >> $config_host_mak
|
||||||
echo "LIBS_TOOLS+=$libs_tools" >> $config_host_mak
|
echo "LIBS_TOOLS+=$libs_tools" >> $config_host_mak
|
||||||
echo "EXESUF=$EXESUF" >> $config_host_mak
|
echo "EXESUF=$EXESUF" >> $config_host_mak
|
||||||
@@ -5577,7 +5599,7 @@ fi
|
|||||||
for target in $target_list; do
|
for target in $target_list; do
|
||||||
target_dir="$target"
|
target_dir="$target"
|
||||||
config_target_mak=$target_dir/config-target.mak
|
config_target_mak=$target_dir/config-target.mak
|
||||||
target_name=`echo $target | cut -d '-' -f 1`
|
target_name=$(echo $target | cut -d '-' -f 1)
|
||||||
target_bigendian="no"
|
target_bigendian="no"
|
||||||
|
|
||||||
case "$target_name" in
|
case "$target_name" in
|
||||||
@@ -5617,7 +5639,7 @@ mkdir -p $target_dir
|
|||||||
echo "# Automatically generated by configure - do not modify" > $config_target_mak
|
echo "# Automatically generated by configure - do not modify" > $config_target_mak
|
||||||
|
|
||||||
bflt="no"
|
bflt="no"
|
||||||
interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_name/g"`
|
interp_prefix1=$(echo "$interp_prefix" | sed "s/%M/$target_name/g")
|
||||||
gdb_xml_files=""
|
gdb_xml_files=""
|
||||||
|
|
||||||
TARGET_ARCH="$target_name"
|
TARGET_ARCH="$target_name"
|
||||||
@@ -5743,7 +5765,7 @@ upper() {
|
|||||||
echo "$@"| LC_ALL=C tr '[a-z]' '[A-Z]'
|
echo "$@"| LC_ALL=C tr '[a-z]' '[A-Z]'
|
||||||
}
|
}
|
||||||
|
|
||||||
target_arch_name="`upper $TARGET_ARCH`"
|
target_arch_name="$(upper $TARGET_ARCH)"
|
||||||
echo "TARGET_$target_arch_name=y" >> $config_target_mak
|
echo "TARGET_$target_arch_name=y" >> $config_target_mak
|
||||||
echo "TARGET_NAME=$target_name" >> $config_target_mak
|
echo "TARGET_NAME=$target_name" >> $config_target_mak
|
||||||
echo "TARGET_BASE_ARCH=$TARGET_BASE_ARCH" >> $config_target_mak
|
echo "TARGET_BASE_ARCH=$TARGET_BASE_ARCH" >> $config_target_mak
|
||||||
@@ -5959,11 +5981,11 @@ for bios_file in \
|
|||||||
$source_path/pc-bios/u-boot.* \
|
$source_path/pc-bios/u-boot.* \
|
||||||
$source_path/pc-bios/palcode-*
|
$source_path/pc-bios/palcode-*
|
||||||
do
|
do
|
||||||
FILES="$FILES pc-bios/`basename $bios_file`"
|
FILES="$FILES pc-bios/$(basename $bios_file)"
|
||||||
done
|
done
|
||||||
for test_file in `find $source_path/tests/acpi-test-data -type f`
|
for test_file in $(find $source_path/tests/acpi-test-data -type f)
|
||||||
do
|
do
|
||||||
FILES="$FILES tests/acpi-test-data`echo $test_file | sed -e 's/.*acpi-test-data//'`"
|
FILES="$FILES tests/acpi-test-data$(echo $test_file | sed -e 's/.*acpi-test-data//')"
|
||||||
done
|
done
|
||||||
mkdir -p $DIRS
|
mkdir -p $DIRS
|
||||||
for f in $FILES ; do
|
for f in $FILES ; do
|
||||||
|
|||||||
@@ -26,11 +26,8 @@
|
|||||||
bool exit_request;
|
bool exit_request;
|
||||||
CPUState *tcg_current_cpu;
|
CPUState *tcg_current_cpu;
|
||||||
|
|
||||||
/* exit the current TB from a signal handler. The host registers are
|
/* exit the current TB, but without causing any exception to be raised */
|
||||||
restored in a state compatible with the CPU emulator
|
void cpu_loop_exit_noexc(CPUState *cpu)
|
||||||
*/
|
|
||||||
#if defined(CONFIG_SOFTMMU)
|
|
||||||
void cpu_resume_from_signal(CPUState *cpu, void *puc)
|
|
||||||
{
|
{
|
||||||
/* XXX: restore cpu registers saved in host registers */
|
/* XXX: restore cpu registers saved in host registers */
|
||||||
|
|
||||||
@@ -38,6 +35,7 @@ void cpu_resume_from_signal(CPUState *cpu, void *puc)
|
|||||||
siglongjmp(cpu->jmp_env, 1);
|
siglongjmp(cpu->jmp_env, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(CONFIG_SOFTMMU)
|
||||||
void cpu_reloading_memory_map(void)
|
void cpu_reloading_memory_map(void)
|
||||||
{
|
{
|
||||||
if (qemu_in_vcpu_thread()) {
|
if (qemu_in_vcpu_thread()) {
|
||||||
|
|||||||
@@ -1081,8 +1081,7 @@ qcrypto_block_luks_create(QCryptoBlock *block,
|
|||||||
luks->header.key_slots[i].key_offset =
|
luks->header.key_slots[i].key_offset =
|
||||||
(QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET /
|
(QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET /
|
||||||
QCRYPTO_BLOCK_LUKS_SECTOR_SIZE) +
|
QCRYPTO_BLOCK_LUKS_SECTOR_SIZE) +
|
||||||
(ROUND_UP(((splitkeylen + (QCRYPTO_BLOCK_LUKS_SECTOR_SIZE - 1)) /
|
(ROUND_UP(DIV_ROUND_UP(splitkeylen, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE),
|
||||||
QCRYPTO_BLOCK_LUKS_SECTOR_SIZE),
|
|
||||||
(QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET /
|
(QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET /
|
||||||
QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) * i);
|
QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) * i);
|
||||||
}
|
}
|
||||||
@@ -1182,8 +1181,7 @@ qcrypto_block_luks_create(QCryptoBlock *block,
|
|||||||
luks->header.payload_offset =
|
luks->header.payload_offset =
|
||||||
(QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET /
|
(QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET /
|
||||||
QCRYPTO_BLOCK_LUKS_SECTOR_SIZE) +
|
QCRYPTO_BLOCK_LUKS_SECTOR_SIZE) +
|
||||||
(ROUND_UP(((splitkeylen + (QCRYPTO_BLOCK_LUKS_SECTOR_SIZE - 1)) /
|
(ROUND_UP(DIV_ROUND_UP(splitkeylen, QCRYPTO_BLOCK_LUKS_SECTOR_SIZE),
|
||||||
QCRYPTO_BLOCK_LUKS_SECTOR_SIZE),
|
|
||||||
(QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET /
|
(QCRYPTO_BLOCK_LUKS_KEY_SLOT_OFFSET /
|
||||||
QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) *
|
QCRYPTO_BLOCK_LUKS_SECTOR_SIZE)) *
|
||||||
QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS);
|
QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS);
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ Usage
|
|||||||
=====
|
=====
|
||||||
1. Verify both the source and destination QEMU are able
|
1. Verify both the source and destination QEMU are able
|
||||||
to support the multiple thread compression migration:
|
to support the multiple thread compression migration:
|
||||||
{qemu} info_migrate_capabilities
|
{qemu} info migrate_capabilities
|
||||||
{qemu} ... compress: off ...
|
{qemu} ... compress: off ...
|
||||||
|
|
||||||
2. Activate compression on the source:
|
2. Activate compression on the source:
|
||||||
|
|||||||
@@ -322,7 +322,7 @@ enum. The value for each branch can be of any type.
|
|||||||
|
|
||||||
A flat union definition avoids nesting on the wire, and specifies a
|
A flat union definition avoids nesting on the wire, and specifies a
|
||||||
set of common members that occur in all variants of the union. The
|
set of common members that occur in all variants of the union. The
|
||||||
'base' key must specifiy either a type name (the type must be a
|
'base' key must specify either a type name (the type must be a
|
||||||
struct, not a union), or a dictionary representing an anonymous type.
|
struct, not a union), or a dictionary representing an anonymous type.
|
||||||
All branches of the union must be complex types, and the top-level
|
All branches of the union must be complex types, and the top-level
|
||||||
members of the union dictionary on the wire will be combination of
|
members of the union dictionary on the wire will be combination of
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ the parameters for both cases:
|
|||||||
| throttling.bps-write | bps_wr |
|
| throttling.bps-write | bps_wr |
|
||||||
|-----------------------+-----------------------|
|
|-----------------------+-----------------------|
|
||||||
|
|
||||||
It is possible to set limits for both IOPS and bps and the same time,
|
It is possible to set limits for both IOPS and bps at the same time,
|
||||||
and for each case we can decide whether to have separate read and
|
and for each case we can decide whether to have separate read and
|
||||||
write limits or not, but note that if iops-total is set then neither
|
write limits or not, but note that if iops-total is set then neither
|
||||||
iops-read nor iops-write can be set. The same applies to bps-total and
|
iops-read nor iops-write can be set. The same applies to bps-total and
|
||||||
@@ -235,7 +235,7 @@ consider the following values:
|
|||||||
- Water leaks from the bucket at a rate of 100 IOPS.
|
- Water leaks from the bucket at a rate of 100 IOPS.
|
||||||
- Water can be added to the bucket at a rate of 2000 IOPS.
|
- Water can be added to the bucket at a rate of 2000 IOPS.
|
||||||
- The size of the bucket is 2000 x 60 = 120000
|
- The size of the bucket is 2000 x 60 = 120000
|
||||||
- If 'iops-total-max-length' is unset then the bucket size is 100.
|
- If 'iops-total-max' is unset then the bucket size is 100 x 60.
|
||||||
|
|
||||||
The bucket is initially empty, therefore water can be added until it's
|
The bucket is initially empty, therefore water can be added until it's
|
||||||
full at a rate of 2000 IOPS (the burst rate). Once the bucket is full
|
full at a rate of 2000 IOPS (the burst rate). Once the bucket is full
|
||||||
|
|||||||
2
exec.c
2
exec.c
@@ -2091,7 +2091,7 @@ static void check_watchpoint(int offset, int len, MemTxAttrs attrs, int flags)
|
|||||||
} else {
|
} else {
|
||||||
cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
|
cpu_get_tb_cpu_state(env, &pc, &cs_base, &cpu_flags);
|
||||||
tb_gen_code(cpu, pc, cs_base, cpu_flags, 1);
|
tb_gen_code(cpu, pc, cs_base, cpu_flags, 1);
|
||||||
cpu_resume_from_signal(cpu, NULL);
|
cpu_loop_exit_noexc(cpu);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include <glib.h>
|
|
||||||
#include <glib/gprintf.h>
|
#include <glib/gprintf.h>
|
||||||
#include <utime.h>
|
#include <utime.h>
|
||||||
#include <sys/uio.h>
|
#include <sys/uio.h>
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include <glib.h>
|
|
||||||
#include <glib/gprintf.h>
|
#include <glib/gprintf.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <utime.h>
|
#include <utime.h>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Virtio 9p
|
* 9p
|
||||||
*
|
*
|
||||||
* Copyright IBM, Corp. 2010
|
* Copyright IBM, Corp. 2010
|
||||||
*
|
*
|
||||||
@@ -118,8 +118,7 @@ struct FileOperations
|
|||||||
int, FsCred *, V9fsFidOpenState *);
|
int, FsCred *, V9fsFidOpenState *);
|
||||||
void (*rewinddir)(FsContext *, V9fsFidOpenState *);
|
void (*rewinddir)(FsContext *, V9fsFidOpenState *);
|
||||||
off_t (*telldir)(FsContext *, V9fsFidOpenState *);
|
off_t (*telldir)(FsContext *, V9fsFidOpenState *);
|
||||||
int (*readdir_r)(FsContext *, V9fsFidOpenState *,
|
struct dirent * (*readdir)(FsContext *, V9fsFidOpenState *);
|
||||||
struct dirent *, struct dirent **);
|
|
||||||
void (*seekdir)(FsContext *, V9fsFidOpenState *, off_t);
|
void (*seekdir)(FsContext *, V9fsFidOpenState *, off_t);
|
||||||
ssize_t (*preadv)(FsContext *, V9fsFidOpenState *,
|
ssize_t (*preadv)(FsContext *, V9fsFidOpenState *,
|
||||||
const struct iovec *, int, off_t);
|
const struct iovec *, int, off_t);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Virtio 9p
|
* 9p
|
||||||
*
|
*
|
||||||
* Copyright IBM, Corp. 2010
|
* Copyright IBM, Corp. 2010
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Virtio 9p
|
* 9p
|
||||||
*
|
*
|
||||||
* This work is licensed under the terms of the GNU GPL, version 2 or
|
* This work is licensed under the terms of the GNU GPL, version 2 or
|
||||||
* later. See the COPYING file in the top-level directory.
|
* later. See the COPYING file in the top-level directory.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Virtio 9p
|
* 9p
|
||||||
*
|
*
|
||||||
* Copyright IBM, Corp. 2010
|
* Copyright IBM, Corp. 2010
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Virtio 9p
|
* 9p
|
||||||
*
|
*
|
||||||
* Copyright IBM, Corp. 2010
|
* Copyright IBM, Corp. 2010
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ provide access to files beyond 9p export path.
|
|||||||
|
|
||||||
2) Running QEMU with root privilege could be a security issue.
|
2) Running QEMU with root privilege could be a security issue.
|
||||||
|
|
||||||
To overcome above issues, following approach is used: A new filesytem
|
To overcome above issues, following approach is used: A new filesystem
|
||||||
type 'proxy' is introduced. Proxy FS uses chroot + socket combination
|
type 'proxy' is introduced. Proxy FS uses chroot + socket combination
|
||||||
for securing the vulnerability known with following symbolic links.
|
for securing the vulnerability known with following symbolic links.
|
||||||
Intention of adding a new filesystem type is to allow qemu to run
|
Intention of adding a new filesystem type is to allow qemu to run
|
||||||
|
|||||||
27
gdbstub.c
27
gdbstub.c
@@ -333,7 +333,7 @@ static int get_char(GDBState *s)
|
|||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (errno == ECONNRESET)
|
if (errno == ECONNRESET)
|
||||||
s->fd = -1;
|
s->fd = -1;
|
||||||
if (errno != EINTR && errno != EAGAIN)
|
if (errno != EINTR)
|
||||||
return -1;
|
return -1;
|
||||||
} else if (ret == 0) {
|
} else if (ret == 0) {
|
||||||
close(s->fd);
|
close(s->fd);
|
||||||
@@ -394,7 +394,7 @@ static void put_buffer(GDBState *s, const uint8_t *buf, int len)
|
|||||||
while (len > 0) {
|
while (len > 0) {
|
||||||
ret = send(s->fd, buf, len, 0);
|
ret = send(s->fd, buf, len, 0);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (errno != EINTR && errno != EAGAIN)
|
if (errno != EINTR)
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
buf += ret;
|
buf += ret;
|
||||||
@@ -1493,19 +1493,6 @@ void gdb_exit(CPUArchState *env, int code)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
int
|
|
||||||
gdb_queuesig (void)
|
|
||||||
{
|
|
||||||
GDBState *s;
|
|
||||||
|
|
||||||
s = gdbserver_state;
|
|
||||||
|
|
||||||
if (gdbserver_fd < 0 || s->fd < 0)
|
|
||||||
return 0;
|
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
gdb_handlesig(CPUState *cpu, int sig)
|
gdb_handlesig(CPUState *cpu, int sig)
|
||||||
{
|
{
|
||||||
@@ -1543,9 +1530,13 @@ gdb_handlesig(CPUState *cpu, int sig)
|
|||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
gdb_read_byte(s, buf[i]);
|
gdb_read_byte(s, buf[i]);
|
||||||
}
|
}
|
||||||
} else if (n == 0 || errno != EAGAIN) {
|
} else {
|
||||||
/* XXX: Connection closed. Should probably wait for another
|
/* XXX: Connection closed. Should probably wait for another
|
||||||
connection before continuing. */
|
connection before continuing. */
|
||||||
|
if (n == 0) {
|
||||||
|
close(s->fd);
|
||||||
|
}
|
||||||
|
s->fd = -1;
|
||||||
return sig;
|
return sig;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1600,8 +1591,6 @@ static void gdb_accept(void)
|
|||||||
gdb_has_xml = false;
|
gdb_has_xml = false;
|
||||||
|
|
||||||
gdbserver_state = s;
|
gdbserver_state = s;
|
||||||
|
|
||||||
fcntl(fd, F_SETFL, O_NONBLOCK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int gdbserver_open(int port)
|
static int gdbserver_open(int port)
|
||||||
@@ -1629,7 +1618,7 @@ static int gdbserver_open(int port)
|
|||||||
close(fd);
|
close(fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
ret = listen(fd, 0);
|
ret = listen(fd, 1);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
perror("listen");
|
perror("listen");
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ static int handle_close(FsContext *ctx, V9fsFidOpenState *fs)
|
|||||||
|
|
||||||
static int handle_closedir(FsContext *ctx, V9fsFidOpenState *fs)
|
static int handle_closedir(FsContext *ctx, V9fsFidOpenState *fs)
|
||||||
{
|
{
|
||||||
return closedir(fs->dir);
|
return closedir(fs->dir.stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_open(FsContext *ctx, V9fsPath *fs_path,
|
static int handle_open(FsContext *ctx, V9fsPath *fs_path,
|
||||||
@@ -132,8 +132,8 @@ static int handle_opendir(FsContext *ctx,
|
|||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
fs->dir = fdopendir(ret);
|
fs->dir.stream = fdopendir(ret);
|
||||||
if (!fs->dir) {
|
if (!fs->dir.stream) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -141,24 +141,22 @@ static int handle_opendir(FsContext *ctx,
|
|||||||
|
|
||||||
static void handle_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
|
static void handle_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
|
||||||
{
|
{
|
||||||
rewinddir(fs->dir);
|
rewinddir(fs->dir.stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
static off_t handle_telldir(FsContext *ctx, V9fsFidOpenState *fs)
|
static off_t handle_telldir(FsContext *ctx, V9fsFidOpenState *fs)
|
||||||
{
|
{
|
||||||
return telldir(fs->dir);
|
return telldir(fs->dir.stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_readdir_r(FsContext *ctx, V9fsFidOpenState *fs,
|
static struct dirent *handle_readdir(FsContext *ctx, V9fsFidOpenState *fs)
|
||||||
struct dirent *entry,
|
|
||||||
struct dirent **result)
|
|
||||||
{
|
{
|
||||||
return readdir_r(fs->dir, entry, result);
|
return readdir(fs->dir.stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handle_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
|
static void handle_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
|
||||||
{
|
{
|
||||||
seekdir(fs->dir, off);
|
seekdir(fs->dir.stream, off);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t handle_preadv(FsContext *ctx, V9fsFidOpenState *fs,
|
static ssize_t handle_preadv(FsContext *ctx, V9fsFidOpenState *fs,
|
||||||
@@ -262,7 +260,7 @@ static int handle_fstat(FsContext *fs_ctx, int fid_type,
|
|||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if (fid_type == P9_FID_DIR) {
|
if (fid_type == P9_FID_DIR) {
|
||||||
fd = dirfd(fs->dir);
|
fd = dirfd(fs->dir.stream);
|
||||||
} else {
|
} else {
|
||||||
fd = fs->fd;
|
fd = fs->fd;
|
||||||
}
|
}
|
||||||
@@ -409,7 +407,7 @@ static int handle_fsync(FsContext *ctx, int fid_type,
|
|||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if (fid_type == P9_FID_DIR) {
|
if (fid_type == P9_FID_DIR) {
|
||||||
fd = dirfd(fs->dir);
|
fd = dirfd(fs->dir.stream);
|
||||||
} else {
|
} else {
|
||||||
fd = fs->fd;
|
fd = fs->fd;
|
||||||
}
|
}
|
||||||
@@ -681,7 +679,7 @@ FileOperations handle_ops = {
|
|||||||
.opendir = handle_opendir,
|
.opendir = handle_opendir,
|
||||||
.rewinddir = handle_rewinddir,
|
.rewinddir = handle_rewinddir,
|
||||||
.telldir = handle_telldir,
|
.telldir = handle_telldir,
|
||||||
.readdir_r = handle_readdir_r,
|
.readdir = handle_readdir,
|
||||||
.seekdir = handle_seekdir,
|
.seekdir = handle_seekdir,
|
||||||
.preadv = handle_preadv,
|
.preadv = handle_preadv,
|
||||||
.pwritev = handle_pwritev,
|
.pwritev = handle_pwritev,
|
||||||
|
|||||||
@@ -348,7 +348,7 @@ static int local_close(FsContext *ctx, V9fsFidOpenState *fs)
|
|||||||
|
|
||||||
static int local_closedir(FsContext *ctx, V9fsFidOpenState *fs)
|
static int local_closedir(FsContext *ctx, V9fsFidOpenState *fs)
|
||||||
{
|
{
|
||||||
return closedir(fs->dir);
|
return closedir(fs->dir.stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int local_open(FsContext *ctx, V9fsPath *fs_path,
|
static int local_open(FsContext *ctx, V9fsPath *fs_path,
|
||||||
@@ -370,9 +370,9 @@ static int local_opendir(FsContext *ctx,
|
|||||||
char *path = fs_path->data;
|
char *path = fs_path->data;
|
||||||
|
|
||||||
buffer = rpath(ctx, path);
|
buffer = rpath(ctx, path);
|
||||||
fs->dir = opendir(buffer);
|
fs->dir.stream = opendir(buffer);
|
||||||
g_free(buffer);
|
g_free(buffer);
|
||||||
if (!fs->dir) {
|
if (!fs->dir.stream) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -380,38 +380,40 @@ static int local_opendir(FsContext *ctx,
|
|||||||
|
|
||||||
static void local_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
|
static void local_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
|
||||||
{
|
{
|
||||||
rewinddir(fs->dir);
|
rewinddir(fs->dir.stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
static off_t local_telldir(FsContext *ctx, V9fsFidOpenState *fs)
|
static off_t local_telldir(FsContext *ctx, V9fsFidOpenState *fs)
|
||||||
{
|
{
|
||||||
return telldir(fs->dir);
|
return telldir(fs->dir.stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int local_readdir_r(FsContext *ctx, V9fsFidOpenState *fs,
|
static struct dirent *local_readdir(FsContext *ctx, V9fsFidOpenState *fs)
|
||||||
struct dirent *entry,
|
|
||||||
struct dirent **result)
|
|
||||||
{
|
{
|
||||||
int ret;
|
struct dirent *entry;
|
||||||
|
|
||||||
again:
|
again:
|
||||||
ret = readdir_r(fs->dir, entry, result);
|
entry = readdir(fs->dir.stream);
|
||||||
|
if (!entry) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (ctx->export_flags & V9FS_SM_MAPPED) {
|
if (ctx->export_flags & V9FS_SM_MAPPED) {
|
||||||
entry->d_type = DT_UNKNOWN;
|
entry->d_type = DT_UNKNOWN;
|
||||||
} else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
|
} else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
|
||||||
if (!ret && *result != NULL &&
|
if (!strcmp(entry->d_name, VIRTFS_META_DIR)) {
|
||||||
!strcmp(entry->d_name, VIRTFS_META_DIR)) {
|
|
||||||
/* skp the meta data directory */
|
/* skp the meta data directory */
|
||||||
goto again;
|
goto again;
|
||||||
}
|
}
|
||||||
entry->d_type = DT_UNKNOWN;
|
entry->d_type = DT_UNKNOWN;
|
||||||
}
|
}
|
||||||
return ret;
|
|
||||||
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void local_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
|
static void local_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
|
||||||
{
|
{
|
||||||
seekdir(fs->dir, off);
|
seekdir(fs->dir.stream, off);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t local_preadv(FsContext *ctx, V9fsFidOpenState *fs,
|
static ssize_t local_preadv(FsContext *ctx, V9fsFidOpenState *fs,
|
||||||
@@ -610,7 +612,7 @@ static int local_fstat(FsContext *fs_ctx, int fid_type,
|
|||||||
int err, fd;
|
int err, fd;
|
||||||
|
|
||||||
if (fid_type == P9_FID_DIR) {
|
if (fid_type == P9_FID_DIR) {
|
||||||
fd = dirfd(fs->dir);
|
fd = dirfd(fs->dir.stream);
|
||||||
} else {
|
} else {
|
||||||
fd = fs->fd;
|
fd = fs->fd;
|
||||||
}
|
}
|
||||||
@@ -998,7 +1000,7 @@ static int local_fsync(FsContext *ctx, int fid_type,
|
|||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if (fid_type == P9_FID_DIR) {
|
if (fid_type == P9_FID_DIR) {
|
||||||
fd = dirfd(fs->dir);
|
fd = dirfd(fs->dir.stream);
|
||||||
} else {
|
} else {
|
||||||
fd = fs->fd;
|
fd = fs->fd;
|
||||||
}
|
}
|
||||||
@@ -1254,7 +1256,7 @@ FileOperations local_ops = {
|
|||||||
.opendir = local_opendir,
|
.opendir = local_opendir,
|
||||||
.rewinddir = local_rewinddir,
|
.rewinddir = local_rewinddir,
|
||||||
.telldir = local_telldir,
|
.telldir = local_telldir,
|
||||||
.readdir_r = local_readdir_r,
|
.readdir = local_readdir,
|
||||||
.seekdir = local_seekdir,
|
.seekdir = local_seekdir,
|
||||||
.preadv = local_preadv,
|
.preadv = local_preadv,
|
||||||
.pwritev = local_pwritev,
|
.pwritev = local_pwritev,
|
||||||
|
|||||||
@@ -633,7 +633,7 @@ static int proxy_close(FsContext *ctx, V9fsFidOpenState *fs)
|
|||||||
|
|
||||||
static int proxy_closedir(FsContext *ctx, V9fsFidOpenState *fs)
|
static int proxy_closedir(FsContext *ctx, V9fsFidOpenState *fs)
|
||||||
{
|
{
|
||||||
return closedir(fs->dir);
|
return closedir(fs->dir.stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int proxy_open(FsContext *ctx, V9fsPath *fs_path,
|
static int proxy_open(FsContext *ctx, V9fsPath *fs_path,
|
||||||
@@ -652,14 +652,14 @@ static int proxy_opendir(FsContext *ctx,
|
|||||||
{
|
{
|
||||||
int serrno, fd;
|
int serrno, fd;
|
||||||
|
|
||||||
fs->dir = NULL;
|
fs->dir.stream = NULL;
|
||||||
fd = v9fs_request(ctx->private, T_OPEN, NULL, "sd", fs_path, O_DIRECTORY);
|
fd = v9fs_request(ctx->private, T_OPEN, NULL, "sd", fs_path, O_DIRECTORY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
errno = -fd;
|
errno = -fd;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
fs->dir = fdopendir(fd);
|
fs->dir.stream = fdopendir(fd);
|
||||||
if (!fs->dir) {
|
if (!fs->dir.stream) {
|
||||||
serrno = errno;
|
serrno = errno;
|
||||||
close(fd);
|
close(fd);
|
||||||
errno = serrno;
|
errno = serrno;
|
||||||
@@ -670,24 +670,22 @@ static int proxy_opendir(FsContext *ctx,
|
|||||||
|
|
||||||
static void proxy_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
|
static void proxy_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
|
||||||
{
|
{
|
||||||
rewinddir(fs->dir);
|
rewinddir(fs->dir.stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
static off_t proxy_telldir(FsContext *ctx, V9fsFidOpenState *fs)
|
static off_t proxy_telldir(FsContext *ctx, V9fsFidOpenState *fs)
|
||||||
{
|
{
|
||||||
return telldir(fs->dir);
|
return telldir(fs->dir.stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int proxy_readdir_r(FsContext *ctx, V9fsFidOpenState *fs,
|
static struct dirent *proxy_readdir(FsContext *ctx, V9fsFidOpenState *fs)
|
||||||
struct dirent *entry,
|
|
||||||
struct dirent **result)
|
|
||||||
{
|
{
|
||||||
return readdir_r(fs->dir, entry, result);
|
return readdir(fs->dir.stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void proxy_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
|
static void proxy_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
|
||||||
{
|
{
|
||||||
seekdir(fs->dir, off);
|
seekdir(fs->dir.stream, off);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t proxy_preadv(FsContext *ctx, V9fsFidOpenState *fs,
|
static ssize_t proxy_preadv(FsContext *ctx, V9fsFidOpenState *fs,
|
||||||
@@ -791,7 +789,7 @@ static int proxy_fstat(FsContext *fs_ctx, int fid_type,
|
|||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if (fid_type == P9_FID_DIR) {
|
if (fid_type == P9_FID_DIR) {
|
||||||
fd = dirfd(fs->dir);
|
fd = dirfd(fs->dir.stream);
|
||||||
} else {
|
} else {
|
||||||
fd = fs->fd;
|
fd = fs->fd;
|
||||||
}
|
}
|
||||||
@@ -936,7 +934,7 @@ static int proxy_fsync(FsContext *ctx, int fid_type,
|
|||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
if (fid_type == P9_FID_DIR) {
|
if (fid_type == P9_FID_DIR) {
|
||||||
fd = dirfd(fs->dir);
|
fd = dirfd(fs->dir.stream);
|
||||||
} else {
|
} else {
|
||||||
fd = fs->fd;
|
fd = fs->fd;
|
||||||
}
|
}
|
||||||
@@ -1192,7 +1190,7 @@ FileOperations proxy_ops = {
|
|||||||
.opendir = proxy_opendir,
|
.opendir = proxy_opendir,
|
||||||
.rewinddir = proxy_rewinddir,
|
.rewinddir = proxy_rewinddir,
|
||||||
.telldir = proxy_telldir,
|
.telldir = proxy_telldir,
|
||||||
.readdir_r = proxy_readdir_r,
|
.readdir = proxy_readdir,
|
||||||
.seekdir = proxy_seekdir,
|
.seekdir = proxy_seekdir,
|
||||||
.preadv = proxy_preadv,
|
.preadv = proxy_preadv,
|
||||||
.pwritev = proxy_pwritev,
|
.pwritev = proxy_pwritev,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Virtio 9p synthetic file system support
|
* 9p synthetic file system support
|
||||||
*
|
*
|
||||||
* Copyright IBM, Corp. 2011
|
* Copyright IBM, Corp. 2011
|
||||||
*
|
*
|
||||||
@@ -13,9 +13,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "hw/virtio/virtio.h"
|
|
||||||
#include "9p.h"
|
#include "9p.h"
|
||||||
#include "9p-xattr.h"
|
|
||||||
#include "fsdev/qemu-fsdev.h"
|
#include "fsdev/qemu-fsdev.h"
|
||||||
#include "9p-synth.h"
|
#include "9p-synth.h"
|
||||||
#include "qemu/rcu.h"
|
#include "qemu/rcu.h"
|
||||||
@@ -225,8 +223,8 @@ static void v9fs_synth_direntry(V9fsSynthNode *node,
|
|||||||
entry->d_off = off + 1;
|
entry->d_off = off + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int v9fs_synth_get_dentry(V9fsSynthNode *dir, struct dirent *entry,
|
static struct dirent *v9fs_synth_get_dentry(V9fsSynthNode *dir,
|
||||||
struct dirent **result, off_t off)
|
struct dirent *entry, off_t off)
|
||||||
{
|
{
|
||||||
int i = 0;
|
int i = 0;
|
||||||
V9fsSynthNode *node;
|
V9fsSynthNode *node;
|
||||||
@@ -242,25 +240,22 @@ static int v9fs_synth_get_dentry(V9fsSynthNode *dir, struct dirent *entry,
|
|||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
if (!node) {
|
if (!node) {
|
||||||
/* end of directory */
|
/* end of directory */
|
||||||
*result = NULL;
|
return NULL;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
v9fs_synth_direntry(node, entry, off);
|
v9fs_synth_direntry(node, entry, off);
|
||||||
*result = entry;
|
return entry;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int v9fs_synth_readdir_r(FsContext *ctx, V9fsFidOpenState *fs,
|
static struct dirent *v9fs_synth_readdir(FsContext *ctx, V9fsFidOpenState *fs)
|
||||||
struct dirent *entry, struct dirent **result)
|
|
||||||
{
|
{
|
||||||
int ret;
|
struct dirent *entry;
|
||||||
V9fsSynthOpenState *synth_open = fs->private;
|
V9fsSynthOpenState *synth_open = fs->private;
|
||||||
V9fsSynthNode *node = synth_open->node;
|
V9fsSynthNode *node = synth_open->node;
|
||||||
ret = v9fs_synth_get_dentry(node, entry, result, synth_open->offset);
|
entry = v9fs_synth_get_dentry(node, &synth_open->dent, synth_open->offset);
|
||||||
if (!ret && *result != NULL) {
|
if (entry) {
|
||||||
synth_open->offset++;
|
synth_open->offset++;
|
||||||
}
|
}
|
||||||
return ret;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int v9fs_synth_open(FsContext *ctx, V9fsPath *fs_path,
|
static int v9fs_synth_open(FsContext *ctx, V9fsPath *fs_path,
|
||||||
@@ -546,7 +541,7 @@ FileOperations synth_ops = {
|
|||||||
.opendir = v9fs_synth_opendir,
|
.opendir = v9fs_synth_opendir,
|
||||||
.rewinddir = v9fs_synth_rewinddir,
|
.rewinddir = v9fs_synth_rewinddir,
|
||||||
.telldir = v9fs_synth_telldir,
|
.telldir = v9fs_synth_telldir,
|
||||||
.readdir_r = v9fs_synth_readdir_r,
|
.readdir = v9fs_synth_readdir,
|
||||||
.seekdir = v9fs_synth_seekdir,
|
.seekdir = v9fs_synth_seekdir,
|
||||||
.preadv = v9fs_synth_preadv,
|
.preadv = v9fs_synth_preadv,
|
||||||
.pwritev = v9fs_synth_pwritev,
|
.pwritev = v9fs_synth_pwritev,
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ struct V9fsSynthNode {
|
|||||||
typedef struct V9fsSynthOpenState {
|
typedef struct V9fsSynthOpenState {
|
||||||
off_t offset;
|
off_t offset;
|
||||||
V9fsSynthNode *node;
|
V9fsSynthNode *node;
|
||||||
|
struct dirent dent;
|
||||||
} V9fsSynthOpenState;
|
} V9fsSynthOpenState;
|
||||||
|
|
||||||
extern int qemu_v9fs_synth_mkdir(V9fsSynthNode *parent, int mode,
|
extern int qemu_v9fs_synth_mkdir(V9fsSynthNode *parent, int mode,
|
||||||
|
|||||||
63
hw/9pfs/9p.c
63
hw/9pfs/9p.c
@@ -13,7 +13,6 @@
|
|||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "hw/virtio/virtio.h"
|
#include "hw/virtio/virtio.h"
|
||||||
#include "hw/i386/pc.h"
|
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "qemu/iov.h"
|
#include "qemu/iov.h"
|
||||||
@@ -232,7 +231,7 @@ static int v9fs_reopen_fid(V9fsPDU *pdu, V9fsFidState *f)
|
|||||||
} while (err == -EINTR && !pdu->cancelled);
|
} while (err == -EINTR && !pdu->cancelled);
|
||||||
}
|
}
|
||||||
} else if (f->fid_type == P9_FID_DIR) {
|
} else if (f->fid_type == P9_FID_DIR) {
|
||||||
if (f->fs.dir == NULL) {
|
if (f->fs.dir.stream == NULL) {
|
||||||
do {
|
do {
|
||||||
err = v9fs_co_opendir(pdu, f);
|
err = v9fs_co_opendir(pdu, f);
|
||||||
} while (err == -EINTR && !pdu->cancelled);
|
} while (err == -EINTR && !pdu->cancelled);
|
||||||
@@ -301,6 +300,9 @@ static V9fsFidState *alloc_fid(V9fsState *s, int32_t fid)
|
|||||||
f->next = s->fid_list;
|
f->next = s->fid_list;
|
||||||
s->fid_list = f;
|
s->fid_list = f;
|
||||||
|
|
||||||
|
v9fs_readdir_init(&f->fs.dir);
|
||||||
|
v9fs_readdir_init(&f->fs_reclaim.dir);
|
||||||
|
|
||||||
return f;
|
return f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,7 +348,7 @@ static int free_fid(V9fsPDU *pdu, V9fsFidState *fidp)
|
|||||||
retval = v9fs_co_close(pdu, &fidp->fs);
|
retval = v9fs_co_close(pdu, &fidp->fs);
|
||||||
}
|
}
|
||||||
} else if (fidp->fid_type == P9_FID_DIR) {
|
} else if (fidp->fid_type == P9_FID_DIR) {
|
||||||
if (fidp->fs.dir != NULL) {
|
if (fidp->fs.dir.stream != NULL) {
|
||||||
retval = v9fs_co_closedir(pdu, &fidp->fs);
|
retval = v9fs_co_closedir(pdu, &fidp->fs);
|
||||||
}
|
}
|
||||||
} else if (fidp->fid_type == P9_FID_XATTR) {
|
} else if (fidp->fid_type == P9_FID_XATTR) {
|
||||||
@@ -444,7 +446,7 @@ void v9fs_reclaim_fd(V9fsPDU *pdu)
|
|||||||
reclaim_count++;
|
reclaim_count++;
|
||||||
}
|
}
|
||||||
} else if (f->fid_type == P9_FID_DIR) {
|
} else if (f->fid_type == P9_FID_DIR) {
|
||||||
if (f->fs.dir != NULL) {
|
if (f->fs.dir.stream != NULL) {
|
||||||
/*
|
/*
|
||||||
* Up the reference count so that
|
* Up the reference count so that
|
||||||
* a clunk request won't free this fid
|
* a clunk request won't free this fid
|
||||||
@@ -452,8 +454,8 @@ void v9fs_reclaim_fd(V9fsPDU *pdu)
|
|||||||
f->ref++;
|
f->ref++;
|
||||||
f->rclm_lst = reclaim_list;
|
f->rclm_lst = reclaim_list;
|
||||||
reclaim_list = f;
|
reclaim_list = f;
|
||||||
f->fs_reclaim.dir = f->fs.dir;
|
f->fs_reclaim.dir.stream = f->fs.dir.stream;
|
||||||
f->fs.dir = NULL;
|
f->fs.dir.stream = NULL;
|
||||||
reclaim_count++;
|
reclaim_count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1625,7 +1627,7 @@ static int v9fs_do_readdir_with_stat(V9fsPDU *pdu,
|
|||||||
int32_t count = 0;
|
int32_t count = 0;
|
||||||
struct stat stbuf;
|
struct stat stbuf;
|
||||||
off_t saved_dir_pos;
|
off_t saved_dir_pos;
|
||||||
struct dirent *dent, *result;
|
struct dirent *dent;
|
||||||
|
|
||||||
/* save the directory position */
|
/* save the directory position */
|
||||||
saved_dir_pos = v9fs_co_telldir(pdu, fidp);
|
saved_dir_pos = v9fs_co_telldir(pdu, fidp);
|
||||||
@@ -1633,34 +1635,37 @@ static int v9fs_do_readdir_with_stat(V9fsPDU *pdu,
|
|||||||
return saved_dir_pos;
|
return saved_dir_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
dent = g_malloc(sizeof(struct dirent));
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
v9fs_path_init(&path);
|
v9fs_path_init(&path);
|
||||||
err = v9fs_co_readdir_r(pdu, fidp, dent, &result);
|
|
||||||
if (err || !result) {
|
v9fs_readdir_lock(&fidp->fs.dir);
|
||||||
|
|
||||||
|
err = v9fs_co_readdir(pdu, fidp, &dent);
|
||||||
|
if (err || !dent) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
err = v9fs_co_name_to_path(pdu, &fidp->path, dent->d_name, &path);
|
err = v9fs_co_name_to_path(pdu, &fidp->path, dent->d_name, &path);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
goto out;
|
break;
|
||||||
}
|
}
|
||||||
err = v9fs_co_lstat(pdu, &path, &stbuf);
|
err = v9fs_co_lstat(pdu, &path, &stbuf);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
goto out;
|
break;
|
||||||
}
|
}
|
||||||
err = stat_to_v9stat(pdu, &path, &stbuf, &v9stat);
|
err = stat_to_v9stat(pdu, &path, &stbuf, &v9stat);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
goto out;
|
break;
|
||||||
}
|
}
|
||||||
/* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) */
|
/* 11 = 7 + 4 (7 = start offset, 4 = space for storing count) */
|
||||||
len = pdu_marshal(pdu, 11 + count, "S", &v9stat);
|
len = pdu_marshal(pdu, 11 + count, "S", &v9stat);
|
||||||
|
|
||||||
|
v9fs_readdir_unlock(&fidp->fs.dir);
|
||||||
|
|
||||||
if ((len != (v9stat.size + 2)) || ((count + len) > max_count)) {
|
if ((len != (v9stat.size + 2)) || ((count + len) > max_count)) {
|
||||||
/* Ran out of buffer. Set dir back to old position and return */
|
/* Ran out of buffer. Set dir back to old position and return */
|
||||||
v9fs_co_seekdir(pdu, fidp, saved_dir_pos);
|
v9fs_co_seekdir(pdu, fidp, saved_dir_pos);
|
||||||
v9fs_stat_free(&v9stat);
|
v9fs_stat_free(&v9stat);
|
||||||
v9fs_path_free(&path);
|
v9fs_path_free(&path);
|
||||||
g_free(dent);
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
count += len;
|
count += len;
|
||||||
@@ -1668,8 +1673,9 @@ static int v9fs_do_readdir_with_stat(V9fsPDU *pdu,
|
|||||||
v9fs_path_free(&path);
|
v9fs_path_free(&path);
|
||||||
saved_dir_pos = dent->d_off;
|
saved_dir_pos = dent->d_off;
|
||||||
}
|
}
|
||||||
out:
|
|
||||||
g_free(dent);
|
v9fs_readdir_unlock(&fidp->fs.dir);
|
||||||
|
|
||||||
v9fs_path_free(&path);
|
v9fs_path_free(&path);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
return err;
|
return err;
|
||||||
@@ -1805,7 +1811,7 @@ static int v9fs_do_readdir(V9fsPDU *pdu,
|
|||||||
int len, err = 0;
|
int len, err = 0;
|
||||||
int32_t count = 0;
|
int32_t count = 0;
|
||||||
off_t saved_dir_pos;
|
off_t saved_dir_pos;
|
||||||
struct dirent *dent, *result;
|
struct dirent *dent;
|
||||||
|
|
||||||
/* save the directory position */
|
/* save the directory position */
|
||||||
saved_dir_pos = v9fs_co_telldir(pdu, fidp);
|
saved_dir_pos = v9fs_co_telldir(pdu, fidp);
|
||||||
@@ -1813,20 +1819,21 @@ static int v9fs_do_readdir(V9fsPDU *pdu,
|
|||||||
return saved_dir_pos;
|
return saved_dir_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
dent = g_malloc(sizeof(struct dirent));
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
err = v9fs_co_readdir_r(pdu, fidp, dent, &result);
|
v9fs_readdir_lock(&fidp->fs.dir);
|
||||||
if (err || !result) {
|
|
||||||
|
err = v9fs_co_readdir(pdu, fidp, &dent);
|
||||||
|
if (err || !dent) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
v9fs_string_init(&name);
|
v9fs_string_init(&name);
|
||||||
v9fs_string_sprintf(&name, "%s", dent->d_name);
|
v9fs_string_sprintf(&name, "%s", dent->d_name);
|
||||||
if ((count + v9fs_readdir_data_size(&name)) > max_count) {
|
if ((count + v9fs_readdir_data_size(&name)) > max_count) {
|
||||||
|
v9fs_readdir_unlock(&fidp->fs.dir);
|
||||||
|
|
||||||
/* Ran out of buffer. Set dir back to old position and return */
|
/* Ran out of buffer. Set dir back to old position and return */
|
||||||
v9fs_co_seekdir(pdu, fidp, saved_dir_pos);
|
v9fs_co_seekdir(pdu, fidp, saved_dir_pos);
|
||||||
v9fs_string_free(&name);
|
v9fs_string_free(&name);
|
||||||
g_free(dent);
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@@ -1844,17 +1851,21 @@ static int v9fs_do_readdir(V9fsPDU *pdu,
|
|||||||
len = pdu_marshal(pdu, 11 + count, "Qqbs",
|
len = pdu_marshal(pdu, 11 + count, "Qqbs",
|
||||||
&qid, dent->d_off,
|
&qid, dent->d_off,
|
||||||
dent->d_type, &name);
|
dent->d_type, &name);
|
||||||
|
|
||||||
|
v9fs_readdir_unlock(&fidp->fs.dir);
|
||||||
|
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
v9fs_co_seekdir(pdu, fidp, saved_dir_pos);
|
v9fs_co_seekdir(pdu, fidp, saved_dir_pos);
|
||||||
v9fs_string_free(&name);
|
v9fs_string_free(&name);
|
||||||
g_free(dent);
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
count += len;
|
count += len;
|
||||||
v9fs_string_free(&name);
|
v9fs_string_free(&name);
|
||||||
saved_dir_pos = dent->d_off;
|
saved_dir_pos = dent->d_off;
|
||||||
}
|
}
|
||||||
g_free(dent);
|
|
||||||
|
v9fs_readdir_unlock(&fidp->fs.dir);
|
||||||
|
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@@ -1884,7 +1895,7 @@ static void v9fs_readdir(void *opaque)
|
|||||||
retval = -EINVAL;
|
retval = -EINVAL;
|
||||||
goto out_nofid;
|
goto out_nofid;
|
||||||
}
|
}
|
||||||
if (!fidp->fs.dir) {
|
if (!fidp->fs.dir.stream) {
|
||||||
retval = -EINVAL;
|
retval = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|||||||
25
hw/9pfs/9p.h
25
hw/9pfs/9p.h
@@ -4,9 +4,6 @@
|
|||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <utime.h>
|
#include <utime.h>
|
||||||
#include <sys/resource.h>
|
#include <sys/resource.h>
|
||||||
#include <glib.h>
|
|
||||||
#include "standard-headers/linux/virtio_9p.h"
|
|
||||||
#include "hw/virtio/virtio.h"
|
|
||||||
#include "fsdev/file-op-9p.h"
|
#include "fsdev/file-op-9p.h"
|
||||||
#include "fsdev/9p-iov-marshal.h"
|
#include "fsdev/9p-iov-marshal.h"
|
||||||
#include "qemu/thread.h"
|
#include "qemu/thread.h"
|
||||||
@@ -169,13 +166,33 @@ typedef struct V9fsXattr
|
|||||||
int flags;
|
int flags;
|
||||||
} V9fsXattr;
|
} V9fsXattr;
|
||||||
|
|
||||||
|
typedef struct V9fsDir {
|
||||||
|
DIR *stream;
|
||||||
|
QemuMutex readdir_mutex;
|
||||||
|
} V9fsDir;
|
||||||
|
|
||||||
|
static inline void v9fs_readdir_lock(V9fsDir *dir)
|
||||||
|
{
|
||||||
|
qemu_mutex_lock(&dir->readdir_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void v9fs_readdir_unlock(V9fsDir *dir)
|
||||||
|
{
|
||||||
|
qemu_mutex_unlock(&dir->readdir_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void v9fs_readdir_init(V9fsDir *dir)
|
||||||
|
{
|
||||||
|
qemu_mutex_init(&dir->readdir_mutex);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Filled by fs driver on open and other
|
* Filled by fs driver on open and other
|
||||||
* calls.
|
* calls.
|
||||||
*/
|
*/
|
||||||
union V9fsFidOpenState {
|
union V9fsFidOpenState {
|
||||||
int fd;
|
int fd;
|
||||||
DIR *dir;
|
V9fsDir dir;
|
||||||
V9fsXattr xattr;
|
V9fsXattr xattr;
|
||||||
/*
|
/*
|
||||||
* private pointer for fs drivers, that
|
* private pointer for fs drivers, that
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Virtio 9p backend
|
* 9p backend
|
||||||
*
|
*
|
||||||
* Copyright IBM, Corp. 2011
|
* Copyright IBM, Corp. 2011
|
||||||
*
|
*
|
||||||
@@ -18,8 +17,7 @@
|
|||||||
#include "qemu/coroutine.h"
|
#include "qemu/coroutine.h"
|
||||||
#include "coth.h"
|
#include "coth.h"
|
||||||
|
|
||||||
int v9fs_co_readdir_r(V9fsPDU *pdu, V9fsFidState *fidp, struct dirent *dent,
|
int v9fs_co_readdir(V9fsPDU *pdu, V9fsFidState *fidp, struct dirent **dent)
|
||||||
struct dirent **result)
|
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
V9fsState *s = pdu->s;
|
V9fsState *s = pdu->s;
|
||||||
@@ -29,11 +27,14 @@ int v9fs_co_readdir_r(V9fsPDU *pdu, V9fsFidState *fidp, struct dirent *dent,
|
|||||||
}
|
}
|
||||||
v9fs_co_run_in_worker(
|
v9fs_co_run_in_worker(
|
||||||
{
|
{
|
||||||
|
struct dirent *entry;
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
err = s->ops->readdir_r(&s->ctx, &fidp->fs, dent, result);
|
entry = s->ops->readdir(&s->ctx, &fidp->fs);
|
||||||
if (!*result && errno) {
|
if (!entry && errno) {
|
||||||
err = -errno;
|
err = -errno;
|
||||||
} else {
|
} else {
|
||||||
|
*dent = entry;
|
||||||
err = 0;
|
err = 0;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Virtio 9p backend
|
* 9p backend
|
||||||
*
|
*
|
||||||
* Copyright IBM, Corp. 2011
|
* Copyright IBM, Corp. 2011
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Virtio 9p backend
|
* 9p backend
|
||||||
*
|
*
|
||||||
* Copyright IBM, Corp. 2011
|
* Copyright IBM, Corp. 2011
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
#include "block/thread-pool.h"
|
#include "block/thread-pool.h"
|
||||||
#include "qemu/coroutine.h"
|
#include "qemu/coroutine.h"
|
||||||
#include "qemu/main-loop.h"
|
|
||||||
#include "coth.h"
|
#include "coth.h"
|
||||||
|
|
||||||
/* Called from QEMU I/O thread. */
|
/* Called from QEMU I/O thread. */
|
||||||
|
|||||||
@@ -17,7 +17,8 @@
|
|||||||
|
|
||||||
#include "qemu/thread.h"
|
#include "qemu/thread.h"
|
||||||
#include "qemu/coroutine.h"
|
#include "qemu/coroutine.h"
|
||||||
#include "virtio-9p.h"
|
#include "qemu/main-loop.h"
|
||||||
|
#include "9p.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* we want to use bottom half because we want to make sure the below
|
* we want to use bottom half because we want to make sure the below
|
||||||
@@ -48,8 +49,7 @@
|
|||||||
|
|
||||||
extern void co_run_in_worker_bh(void *);
|
extern void co_run_in_worker_bh(void *);
|
||||||
extern int v9fs_co_readlink(V9fsPDU *, V9fsPath *, V9fsString *);
|
extern int v9fs_co_readlink(V9fsPDU *, V9fsPath *, V9fsString *);
|
||||||
extern int v9fs_co_readdir_r(V9fsPDU *, V9fsFidState *,
|
extern int v9fs_co_readdir(V9fsPDU *, V9fsFidState *, struct dirent **);
|
||||||
struct dirent *, struct dirent **result);
|
|
||||||
extern off_t v9fs_co_telldir(V9fsPDU *, V9fsFidState *);
|
extern off_t v9fs_co_telldir(V9fsPDU *, V9fsFidState *);
|
||||||
extern void v9fs_co_seekdir(V9fsPDU *, V9fsFidState *, off_t);
|
extern void v9fs_co_seekdir(V9fsPDU *, V9fsFidState *, off_t);
|
||||||
extern void v9fs_co_rewinddir(V9fsPDU *, V9fsFidState *);
|
extern void v9fs_co_rewinddir(V9fsPDU *, V9fsFidState *);
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Virtio 9p backend
|
* 9p backend
|
||||||
*
|
*
|
||||||
* Copyright IBM, Corp. 2011
|
* Copyright IBM, Corp. 2011
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -13,11 +13,9 @@
|
|||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "hw/virtio/virtio.h"
|
#include "hw/virtio/virtio.h"
|
||||||
#include "hw/i386/pc.h"
|
|
||||||
#include "qemu/sockets.h"
|
#include "qemu/sockets.h"
|
||||||
#include "virtio-9p.h"
|
#include "virtio-9p.h"
|
||||||
#include "fsdev/qemu-fsdev.h"
|
#include "fsdev/qemu-fsdev.h"
|
||||||
#include "9p-xattr.h"
|
|
||||||
#include "coth.h"
|
#include "coth.h"
|
||||||
#include "hw/virtio/virtio-access.h"
|
#include "hw/virtio/virtio-access.h"
|
||||||
#include "qemu/iov.h"
|
#include "qemu/iov.h"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
common-obj-$(CONFIG_ACPI_X86) += core.o piix4.o pcihp.o
|
common-obj-$(CONFIG_ACPI_X86) += core.o piix4.o pcihp.o
|
||||||
common-obj-$(CONFIG_ACPI_X86_ICH) += ich9.o tco.o
|
common-obj-$(CONFIG_ACPI_X86_ICH) += ich9.o tco.o
|
||||||
common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu_hotplug.o cpu_hotplug_acpi_table.o
|
common-obj-$(CONFIG_ACPI_CPU_HOTPLUG) += cpu_hotplug.o
|
||||||
common-obj-$(CONFIG_ACPI_MEMORY_HOTPLUG) += memory_hotplug.o memory_hotplug_acpi_table.o
|
common-obj-$(CONFIG_ACPI_MEMORY_HOTPLUG) += memory_hotplug.o memory_hotplug_acpi_table.o
|
||||||
obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o
|
obj-$(CONFIG_ACPI_NVDIMM) += nvdimm.o
|
||||||
common-obj-$(CONFIG_ACPI) += acpi_interface.o
|
common-obj-$(CONFIG_ACPI) += acpi_interface.o
|
||||||
|
|||||||
@@ -2,6 +2,15 @@
|
|||||||
#include "hw/acpi/acpi_dev_interface.h"
|
#include "hw/acpi/acpi_dev_interface.h"
|
||||||
#include "qemu/module.h"
|
#include "qemu/module.h"
|
||||||
|
|
||||||
|
void acpi_send_event(DeviceState *dev, AcpiEventStatusBits event)
|
||||||
|
{
|
||||||
|
AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(dev);
|
||||||
|
if (adevc->send_event) {
|
||||||
|
AcpiDeviceIf *adev = ACPI_DEVICE_IF(dev);
|
||||||
|
adevc->send_event(adev, event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void register_types(void)
|
static void register_types(void)
|
||||||
{
|
{
|
||||||
static const TypeInfo acpi_dev_if_info = {
|
static const TypeInfo acpi_dev_if_info = {
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
#include "hw/acpi/aml-build.h"
|
#include "hw/acpi/aml-build.h"
|
||||||
#include "qemu/bswap.h"
|
#include "qemu/bswap.h"
|
||||||
#include "qemu/bitops.h"
|
#include "qemu/bitops.h"
|
||||||
#include "hw/acpi/bios-linker-loader.h"
|
|
||||||
|
|
||||||
static GArray *build_alloc_array(void)
|
static GArray *build_alloc_array(void)
|
||||||
{
|
{
|
||||||
@@ -406,6 +405,15 @@ Aml *aml_return(Aml *val)
|
|||||||
return var;
|
return var;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ACPI 1.0b: 16.2.6.3 Debug Objects Encoding: DebugObj */
|
||||||
|
Aml *aml_debug(void)
|
||||||
|
{
|
||||||
|
Aml *var = aml_alloc();
|
||||||
|
build_append_byte(var->buf, 0x5B); /* ExtOpPrefix */
|
||||||
|
build_append_byte(var->buf, 0x31); /* DebugOp */
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ACPI 1.0b: 16.2.3 Data Objects Encoding:
|
* ACPI 1.0b: 16.2.3 Data Objects Encoding:
|
||||||
* encodes: ByteConst, WordConst, DWordConst, QWordConst, ZeroOp, OneOp
|
* encodes: ByteConst, WordConst, DWordConst, QWordConst, ZeroOp, OneOp
|
||||||
@@ -1407,6 +1415,14 @@ Aml *aml_unicode(const char *str)
|
|||||||
return var;
|
return var;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefRefOf */
|
||||||
|
Aml *aml_refof(Aml *arg)
|
||||||
|
{
|
||||||
|
Aml *var = aml_opcode(0x71 /* RefOfOp */);
|
||||||
|
aml_append(var, arg);
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
|
||||||
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefDerefOf */
|
/* ACPI 1.0b: 16.2.5.4 Type 2 Opcodes Encoding: DefDerefOf */
|
||||||
Aml *aml_derefof(Aml *arg)
|
Aml *aml_derefof(Aml *arg)
|
||||||
{
|
{
|
||||||
@@ -1473,10 +1489,12 @@ Aml *aml_concatenate(Aml *source1, Aml *source2, Aml *target)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
build_header(GArray *linker, GArray *table_data,
|
build_header(BIOSLinker *linker, GArray *table_data,
|
||||||
AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
|
AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
|
||||||
const char *oem_id, const char *oem_table_id)
|
const char *oem_id, const char *oem_table_id)
|
||||||
{
|
{
|
||||||
|
unsigned tbl_offset = (char *)h - table_data->data;
|
||||||
|
unsigned checksum_offset = (char *)&h->checksum - table_data->data;
|
||||||
memcpy(&h->signature, sig, 4);
|
memcpy(&h->signature, sig, 4);
|
||||||
h->length = cpu_to_le32(len);
|
h->length = cpu_to_le32(len);
|
||||||
h->revision = rev;
|
h->revision = rev;
|
||||||
@@ -1497,10 +1515,9 @@ build_header(GArray *linker, GArray *table_data,
|
|||||||
h->oem_revision = cpu_to_le32(1);
|
h->oem_revision = cpu_to_le32(1);
|
||||||
memcpy(h->asl_compiler_id, ACPI_BUILD_APPNAME4, 4);
|
memcpy(h->asl_compiler_id, ACPI_BUILD_APPNAME4, 4);
|
||||||
h->asl_compiler_revision = cpu_to_le32(1);
|
h->asl_compiler_revision = cpu_to_le32(1);
|
||||||
h->checksum = 0;
|
|
||||||
/* Checksum to be filled in by Guest linker */
|
/* Checksum to be filled in by Guest linker */
|
||||||
bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
|
bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
|
||||||
table_data, h, len, &h->checksum);
|
tbl_offset, len, checksum_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void *acpi_data_push(GArray *table_data, unsigned size)
|
void *acpi_data_push(GArray *table_data, unsigned size)
|
||||||
@@ -1518,7 +1535,7 @@ unsigned acpi_data_len(GArray *table)
|
|||||||
|
|
||||||
void acpi_add_table(GArray *table_offsets, GArray *table_data)
|
void acpi_add_table(GArray *table_offsets, GArray *table_data)
|
||||||
{
|
{
|
||||||
uint32_t offset = cpu_to_le32(table_data->len);
|
uint32_t offset = table_data->len;
|
||||||
g_array_append_val(table_offsets, offset);
|
g_array_append_val(table_offsets, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1532,8 +1549,7 @@ void acpi_build_tables_init(AcpiBuildTables *tables)
|
|||||||
|
|
||||||
void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
|
void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
|
||||||
{
|
{
|
||||||
void *linker_data = bios_linker_loader_cleanup(tables->linker);
|
bios_linker_loader_cleanup(tables->linker);
|
||||||
g_free(linker_data);
|
|
||||||
g_array_free(tables->rsdp, true);
|
g_array_free(tables->rsdp, true);
|
||||||
g_array_free(tables->table_data, true);
|
g_array_free(tables->table_data, true);
|
||||||
g_array_free(tables->tcpalog, mfre);
|
g_array_free(tables->tcpalog, mfre);
|
||||||
@@ -1541,24 +1557,26 @@ void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
|
|||||||
|
|
||||||
/* Build rsdt table */
|
/* Build rsdt table */
|
||||||
void
|
void
|
||||||
build_rsdt(GArray *table_data, GArray *linker, GArray *table_offsets,
|
build_rsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
|
||||||
const char *oem_id, const char *oem_table_id)
|
const char *oem_id, const char *oem_table_id)
|
||||||
{
|
{
|
||||||
AcpiRsdtDescriptorRev1 *rsdt;
|
|
||||||
size_t rsdt_len;
|
|
||||||
int i;
|
int i;
|
||||||
const int table_data_len = (sizeof(uint32_t) * table_offsets->len);
|
unsigned rsdt_entries_offset;
|
||||||
|
AcpiRsdtDescriptorRev1 *rsdt;
|
||||||
|
const unsigned table_data_len = (sizeof(uint32_t) * table_offsets->len);
|
||||||
|
const unsigned rsdt_entry_size = sizeof(rsdt->table_offset_entry[0]);
|
||||||
|
const size_t rsdt_len = sizeof(*rsdt) + table_data_len;
|
||||||
|
|
||||||
rsdt_len = sizeof(*rsdt) + table_data_len;
|
|
||||||
rsdt = acpi_data_push(table_data, rsdt_len);
|
rsdt = acpi_data_push(table_data, rsdt_len);
|
||||||
memcpy(rsdt->table_offset_entry, table_offsets->data, table_data_len);
|
rsdt_entries_offset = (char *)rsdt->table_offset_entry - table_data->data;
|
||||||
for (i = 0; i < table_offsets->len; ++i) {
|
for (i = 0; i < table_offsets->len; ++i) {
|
||||||
|
uint32_t ref_tbl_offset = g_array_index(table_offsets, uint32_t, i);
|
||||||
|
uint32_t rsdt_entry_offset = rsdt_entries_offset + rsdt_entry_size * i;
|
||||||
|
|
||||||
/* rsdt->table_offset_entry to be filled by Guest linker */
|
/* rsdt->table_offset_entry to be filled by Guest linker */
|
||||||
bios_linker_loader_add_pointer(linker,
|
bios_linker_loader_add_pointer(linker,
|
||||||
ACPI_BUILD_TABLE_FILE,
|
ACPI_BUILD_TABLE_FILE, rsdt_entry_offset, rsdt_entry_size,
|
||||||
ACPI_BUILD_TABLE_FILE,
|
ACPI_BUILD_TABLE_FILE, ref_tbl_offset);
|
||||||
table_data, &rsdt->table_offset_entry[i],
|
|
||||||
sizeof(uint32_t));
|
|
||||||
}
|
}
|
||||||
build_header(linker, table_data,
|
build_header(linker, table_data,
|
||||||
(void *)rsdt, "RSDT", rsdt_len, 1, oem_id, oem_table_id);
|
(void *)rsdt, "RSDT", rsdt_len, 1, oem_id, oem_table_id);
|
||||||
|
|||||||
@@ -96,134 +96,170 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* bios_linker_loader_init: allocate a new linker file blob array.
|
* BiosLinkerFileEntry:
|
||||||
|
*
|
||||||
|
* An internal type used for book-keeping file entries
|
||||||
|
*/
|
||||||
|
typedef struct BiosLinkerFileEntry {
|
||||||
|
char *name; /* file name */
|
||||||
|
GArray *blob; /* data accosiated with @name */
|
||||||
|
} BiosLinkerFileEntry;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bios_linker_loader_init: allocate a new linker object instance.
|
||||||
*
|
*
|
||||||
* After initialization, linker commands can be added, and will
|
* After initialization, linker commands can be added, and will
|
||||||
* be stored in the array.
|
* be stored in the linker.cmd_blob array.
|
||||||
*/
|
*/
|
||||||
GArray *bios_linker_loader_init(void)
|
BIOSLinker *bios_linker_loader_init(void)
|
||||||
{
|
{
|
||||||
return g_array_new(false, true /* clear */, 1);
|
BIOSLinker *linker = g_new(BIOSLinker, 1);
|
||||||
|
|
||||||
|
linker->cmd_blob = g_array_new(false, true /* clear */, 1);
|
||||||
|
linker->file_list = g_array_new(false, true /* clear */,
|
||||||
|
sizeof(BiosLinkerFileEntry));
|
||||||
|
return linker;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free linker wrapper and return the linker array. */
|
/* Free linker wrapper */
|
||||||
void *bios_linker_loader_cleanup(GArray *linker)
|
void bios_linker_loader_cleanup(BIOSLinker *linker)
|
||||||
{
|
{
|
||||||
return g_array_free(linker, false);
|
int i;
|
||||||
|
BiosLinkerFileEntry *entry;
|
||||||
|
|
||||||
|
g_array_free(linker->cmd_blob, true);
|
||||||
|
|
||||||
|
for (i = 0; i < linker->file_list->len; i++) {
|
||||||
|
entry = &g_array_index(linker->file_list, BiosLinkerFileEntry, i);
|
||||||
|
g_free(entry->name);
|
||||||
|
}
|
||||||
|
g_array_free(linker->file_list, true);
|
||||||
|
g_free(linker);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const BiosLinkerFileEntry *
|
||||||
|
bios_linker_find_file(const BIOSLinker *linker, const char *name)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
BiosLinkerFileEntry *entry;
|
||||||
|
|
||||||
|
for (i = 0; i < linker->file_list->len; i++) {
|
||||||
|
entry = &g_array_index(linker->file_list, BiosLinkerFileEntry, i);
|
||||||
|
if (!strcmp(entry->name, name)) {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* bios_linker_loader_alloc: ask guest to load file into guest memory.
|
* bios_linker_loader_alloc: ask guest to load file into guest memory.
|
||||||
*
|
*
|
||||||
* @linker: linker file blob array
|
* @linker: linker object instance
|
||||||
* @file: file to be loaded
|
* @file_name: name of the file blob to be loaded
|
||||||
|
* @file_blob: pointer to blob corresponding to @file_name
|
||||||
* @alloc_align: required minimal alignment in bytes. Must be a power of 2.
|
* @alloc_align: required minimal alignment in bytes. Must be a power of 2.
|
||||||
* @alloc_fseg: request allocation in FSEG zone (useful for the RSDP ACPI table)
|
* @alloc_fseg: request allocation in FSEG zone (useful for the RSDP ACPI table)
|
||||||
*
|
*
|
||||||
* Note: this command must precede any other linker command using this file.
|
* Note: this command must precede any other linker command using this file.
|
||||||
*/
|
*/
|
||||||
void bios_linker_loader_alloc(GArray *linker,
|
void bios_linker_loader_alloc(BIOSLinker *linker,
|
||||||
const char *file,
|
const char *file_name,
|
||||||
|
GArray *file_blob,
|
||||||
uint32_t alloc_align,
|
uint32_t alloc_align,
|
||||||
bool alloc_fseg)
|
bool alloc_fseg)
|
||||||
{
|
{
|
||||||
BiosLinkerLoaderEntry entry;
|
BiosLinkerLoaderEntry entry;
|
||||||
|
BiosLinkerFileEntry file = { g_strdup(file_name), file_blob};
|
||||||
|
|
||||||
assert(!(alloc_align & (alloc_align - 1)));
|
assert(!(alloc_align & (alloc_align - 1)));
|
||||||
|
|
||||||
|
assert(!bios_linker_find_file(linker, file_name));
|
||||||
|
g_array_append_val(linker->file_list, file);
|
||||||
|
|
||||||
memset(&entry, 0, sizeof entry);
|
memset(&entry, 0, sizeof entry);
|
||||||
strncpy(entry.alloc.file, file, sizeof entry.alloc.file - 1);
|
strncpy(entry.alloc.file, file_name, sizeof entry.alloc.file - 1);
|
||||||
entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_ALLOCATE);
|
entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_ALLOCATE);
|
||||||
entry.alloc.align = cpu_to_le32(alloc_align);
|
entry.alloc.align = cpu_to_le32(alloc_align);
|
||||||
entry.alloc.zone = alloc_fseg ? BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG :
|
entry.alloc.zone = alloc_fseg ? BIOS_LINKER_LOADER_ALLOC_ZONE_FSEG :
|
||||||
BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH;
|
BIOS_LINKER_LOADER_ALLOC_ZONE_HIGH;
|
||||||
|
|
||||||
/* Alloc entries must come first, so prepend them */
|
/* Alloc entries must come first, so prepend them */
|
||||||
g_array_prepend_vals(linker, &entry, sizeof entry);
|
g_array_prepend_vals(linker->cmd_blob, &entry, sizeof entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* bios_linker_loader_add_checksum: ask guest to add checksum of file data
|
* bios_linker_loader_add_checksum: ask guest to add checksum of ACPI
|
||||||
* into (same) file at the specified pointer.
|
* table in the specified file at the specified offset.
|
||||||
*
|
*
|
||||||
* Checksum calculation simply sums -X for each byte X in the range
|
* Checksum calculation simply sums -X for each byte X in the range
|
||||||
* using 8-bit math (i.e. ACPI checksum).
|
* using 8-bit math (i.e. ACPI checksum).
|
||||||
*
|
*
|
||||||
* @linker: linker file blob array
|
* @linker: linker object instance
|
||||||
* @file: file that includes the checksum to be calculated
|
* @file: file that includes the checksum to be calculated
|
||||||
* and the data to be checksummed
|
* and the data to be checksummed
|
||||||
* @table: @file blob contents
|
* @start_offset, @size: range of data in the file to checksum,
|
||||||
* @start, @size: range of data to checksum
|
* relative to the start of file blob
|
||||||
* @checksum: location of the checksum to be patched within file blob
|
* @checksum_offset: location of the checksum to be patched within file blob,
|
||||||
*
|
* relative to the start of file blob
|
||||||
* Notes:
|
|
||||||
* - checksum byte initial value must have been pushed into @table
|
|
||||||
* and reside at address @checksum.
|
|
||||||
* - @size bytes must have been pushed into @table and reside at address
|
|
||||||
* @start.
|
|
||||||
* - Guest calculates checksum of specified range of data, result is added to
|
|
||||||
* initial value at @checksum into copy of @file in Guest memory.
|
|
||||||
* - Range might include the checksum itself.
|
|
||||||
* - To avoid confusion, caller must always put 0x0 at @checksum.
|
|
||||||
* - @file must be loaded into Guest memory using bios_linker_loader_alloc
|
|
||||||
*/
|
*/
|
||||||
void bios_linker_loader_add_checksum(GArray *linker, const char *file,
|
void bios_linker_loader_add_checksum(BIOSLinker *linker, const char *file_name,
|
||||||
GArray *table,
|
unsigned start_offset, unsigned size,
|
||||||
void *start, unsigned size,
|
unsigned checksum_offset)
|
||||||
uint8_t *checksum)
|
|
||||||
{
|
{
|
||||||
BiosLinkerLoaderEntry entry;
|
BiosLinkerLoaderEntry entry;
|
||||||
ptrdiff_t checksum_offset = (gchar *)checksum - table->data;
|
const BiosLinkerFileEntry *file = bios_linker_find_file(linker, file_name);
|
||||||
ptrdiff_t start_offset = (gchar *)start - table->data;
|
|
||||||
|
|
||||||
assert(checksum_offset >= 0);
|
assert(file);
|
||||||
assert(start_offset >= 0);
|
assert(start_offset < file->blob->len);
|
||||||
assert(checksum_offset + 1 <= table->len);
|
assert(start_offset + size <= file->blob->len);
|
||||||
assert(start_offset + size <= table->len);
|
assert(checksum_offset >= start_offset);
|
||||||
assert(*checksum == 0x0);
|
assert(checksum_offset + 1 <= start_offset + size);
|
||||||
|
|
||||||
|
*(file->blob->data + checksum_offset) = 0;
|
||||||
memset(&entry, 0, sizeof entry);
|
memset(&entry, 0, sizeof entry);
|
||||||
strncpy(entry.cksum.file, file, sizeof entry.cksum.file - 1);
|
strncpy(entry.cksum.file, file_name, sizeof entry.cksum.file - 1);
|
||||||
entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM);
|
entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_ADD_CHECKSUM);
|
||||||
entry.cksum.offset = cpu_to_le32(checksum_offset);
|
entry.cksum.offset = cpu_to_le32(checksum_offset);
|
||||||
entry.cksum.start = cpu_to_le32(start_offset);
|
entry.cksum.start = cpu_to_le32(start_offset);
|
||||||
entry.cksum.length = cpu_to_le32(size);
|
entry.cksum.length = cpu_to_le32(size);
|
||||||
|
|
||||||
g_array_append_vals(linker, &entry, sizeof entry);
|
g_array_append_vals(linker->cmd_blob, &entry, sizeof entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* bios_linker_loader_add_pointer: ask guest to add address of source file
|
* bios_linker_loader_add_pointer: ask guest to patch address in
|
||||||
* into destination file at the specified pointer.
|
* destination file with a pointer to source file
|
||||||
*
|
*
|
||||||
* @linker: linker file blob array
|
* @linker: linker object instance
|
||||||
* @dest_file: destination file that must be changed
|
* @dest_file: destination file that must be changed
|
||||||
|
* @dst_patched_offset: location within destination file blob to be patched
|
||||||
|
* with the pointer to @src_file+@src_offset (i.e. source
|
||||||
|
* blob allocated in guest memory + @src_offset), in bytes
|
||||||
|
* @dst_patched_offset_size: size of the pointer to be patched
|
||||||
|
* at @dst_patched_offset in @dest_file blob, in bytes
|
||||||
* @src_file: source file who's address must be taken
|
* @src_file: source file who's address must be taken
|
||||||
* @table: @dest_file blob contents array
|
* @src_offset: location within source file blob to which
|
||||||
* @pointer: location of the pointer to be patched within destination file blob
|
* @dest_file+@dst_patched_offset will point to after
|
||||||
* @pointer_size: size of pointer to be patched, in bytes
|
* firmware's executed ADD_POINTER command
|
||||||
*
|
|
||||||
* Notes:
|
|
||||||
* - @pointer_size bytes must have been pushed into @table
|
|
||||||
* and reside at address @pointer.
|
|
||||||
* - Guest address is added to initial value at @pointer
|
|
||||||
* into copy of @dest_file in Guest memory.
|
|
||||||
* e.g. to get start of src_file in guest memory, put 0x0 there
|
|
||||||
* to get address of a field at offset 0x10 in src_file, put 0x10 there
|
|
||||||
* - Both @dest_file and @src_file must be
|
|
||||||
* loaded into Guest memory using bios_linker_loader_alloc
|
|
||||||
*/
|
*/
|
||||||
void bios_linker_loader_add_pointer(GArray *linker,
|
void bios_linker_loader_add_pointer(BIOSLinker *linker,
|
||||||
const char *dest_file,
|
const char *dest_file,
|
||||||
|
uint32_t dst_patched_offset,
|
||||||
|
uint8_t dst_patched_size,
|
||||||
const char *src_file,
|
const char *src_file,
|
||||||
GArray *table, void *pointer,
|
uint32_t src_offset)
|
||||||
uint8_t pointer_size)
|
|
||||||
{
|
{
|
||||||
|
uint64_t le_src_offset;
|
||||||
BiosLinkerLoaderEntry entry;
|
BiosLinkerLoaderEntry entry;
|
||||||
ptrdiff_t offset = (gchar *)pointer - table->data;
|
const BiosLinkerFileEntry *dst_file =
|
||||||
|
bios_linker_find_file(linker, dest_file);
|
||||||
|
const BiosLinkerFileEntry *source_file =
|
||||||
|
bios_linker_find_file(linker, src_file);
|
||||||
|
|
||||||
assert(offset >= 0);
|
assert(dst_patched_offset < dst_file->blob->len);
|
||||||
assert(offset + pointer_size <= table->len);
|
assert(dst_patched_offset + dst_patched_size <= dst_file->blob->len);
|
||||||
|
assert(src_offset < source_file->blob->len);
|
||||||
|
|
||||||
memset(&entry, 0, sizeof entry);
|
memset(&entry, 0, sizeof entry);
|
||||||
strncpy(entry.pointer.dest_file, dest_file,
|
strncpy(entry.pointer.dest_file, dest_file,
|
||||||
@@ -231,10 +267,14 @@ void bios_linker_loader_add_pointer(GArray *linker,
|
|||||||
strncpy(entry.pointer.src_file, src_file,
|
strncpy(entry.pointer.src_file, src_file,
|
||||||
sizeof entry.pointer.src_file - 1);
|
sizeof entry.pointer.src_file - 1);
|
||||||
entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_ADD_POINTER);
|
entry.command = cpu_to_le32(BIOS_LINKER_LOADER_COMMAND_ADD_POINTER);
|
||||||
entry.pointer.offset = cpu_to_le32(offset);
|
entry.pointer.offset = cpu_to_le32(dst_patched_offset);
|
||||||
entry.pointer.size = pointer_size;
|
entry.pointer.size = dst_patched_size;
|
||||||
assert(pointer_size == 1 || pointer_size == 2 ||
|
assert(dst_patched_size == 1 || dst_patched_size == 2 ||
|
||||||
pointer_size == 4 || pointer_size == 8);
|
dst_patched_size == 4 || dst_patched_size == 8);
|
||||||
|
|
||||||
g_array_append_vals(linker, &entry, sizeof entry);
|
le_src_offset = cpu_to_le64(src_offset);
|
||||||
|
memcpy(dst_file->blob->data + dst_patched_offset,
|
||||||
|
&le_src_offset, dst_patched_size);
|
||||||
|
|
||||||
|
g_array_append_vals(linker->cmd_blob, &entry, sizeof entry);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -698,7 +698,7 @@ uint32_t acpi_gpe_ioport_readb(ACPIREGS *ar, uint32_t addr)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void acpi_send_gpe_event(ACPIREGS *ar, qemu_irq irq,
|
void acpi_send_gpe_event(ACPIREGS *ar, qemu_irq irq,
|
||||||
AcpiGPEStatusBits status)
|
AcpiEventStatusBits status)
|
||||||
{
|
{
|
||||||
ar->gpe.sts[0] |= status;
|
ar->gpe.sts[0] |= status;
|
||||||
acpi_update_sci(ar, irq);
|
acpi_update_sci(ar, irq);
|
||||||
|
|||||||
@@ -14,6 +14,14 @@
|
|||||||
#include "hw/acpi/cpu_hotplug.h"
|
#include "hw/acpi/cpu_hotplug.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qom/cpu.h"
|
#include "qom/cpu.h"
|
||||||
|
#include "hw/i386/pc.h"
|
||||||
|
|
||||||
|
#define CPU_EJECT_METHOD "CPEJ"
|
||||||
|
#define CPU_MAT_METHOD "CPMA"
|
||||||
|
#define CPU_ON_BITMAP "CPON"
|
||||||
|
#define CPU_STATUS_METHOD "CPST"
|
||||||
|
#define CPU_STATUS_MAP "PRS"
|
||||||
|
#define CPU_SCAN_METHOD "PRSC"
|
||||||
|
|
||||||
static uint64_t cpu_status_read(void *opaque, hwaddr addr, unsigned int size)
|
static uint64_t cpu_status_read(void *opaque, hwaddr addr, unsigned int size)
|
||||||
{
|
{
|
||||||
@@ -54,19 +62,18 @@ static void acpi_set_cpu_present_bit(AcpiCpuHotplug *g, CPUState *cpu,
|
|||||||
g->sts[cpu_id / 8] |= (1 << (cpu_id % 8));
|
g->sts[cpu_id / 8] |= (1 << (cpu_id % 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
void acpi_cpu_plug_cb(ACPIREGS *ar, qemu_irq irq,
|
void legacy_acpi_cpu_plug_cb(HotplugHandler *hotplug_dev,
|
||||||
AcpiCpuHotplug *g, DeviceState *dev, Error **errp)
|
AcpiCpuHotplug *g, DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
acpi_set_cpu_present_bit(g, CPU(dev), errp);
|
acpi_set_cpu_present_bit(g, CPU(dev), errp);
|
||||||
if (*errp != NULL) {
|
if (*errp != NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
acpi_send_event(DEVICE(hotplug_dev), ACPI_CPU_HOTPLUG_STATUS);
|
||||||
acpi_send_gpe_event(ar, irq, ACPI_CPU_HOTPLUG_STATUS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner,
|
void legacy_acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner,
|
||||||
AcpiCpuHotplug *gpe_cpu, uint16_t base)
|
AcpiCpuHotplug *gpe_cpu, uint16_t base)
|
||||||
{
|
{
|
||||||
CPUState *cpu;
|
CPUState *cpu;
|
||||||
|
|
||||||
@@ -77,3 +84,230 @@ void acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner,
|
|||||||
gpe_cpu, "acpi-cpu-hotplug", ACPI_GPE_PROC_LEN);
|
gpe_cpu, "acpi-cpu-hotplug", ACPI_GPE_PROC_LEN);
|
||||||
memory_region_add_subregion(parent, base, &gpe_cpu->io);
|
memory_region_add_subregion(parent, base, &gpe_cpu->io);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void build_legacy_cpu_hotplug_aml(Aml *ctx, MachineState *machine,
|
||||||
|
uint16_t io_base)
|
||||||
|
{
|
||||||
|
Aml *dev;
|
||||||
|
Aml *crs;
|
||||||
|
Aml *pkg;
|
||||||
|
Aml *field;
|
||||||
|
Aml *method;
|
||||||
|
Aml *if_ctx;
|
||||||
|
Aml *else_ctx;
|
||||||
|
int i, apic_idx;
|
||||||
|
Aml *sb_scope = aml_scope("_SB");
|
||||||
|
uint8_t madt_tmpl[8] = {0x00, 0x08, 0x00, 0x00, 0x00, 0, 0, 0};
|
||||||
|
Aml *cpu_id = aml_arg(1);
|
||||||
|
Aml *apic_id = aml_arg(0);
|
||||||
|
Aml *cpu_on = aml_local(0);
|
||||||
|
Aml *madt = aml_local(1);
|
||||||
|
Aml *cpus_map = aml_name(CPU_ON_BITMAP);
|
||||||
|
Aml *zero = aml_int(0);
|
||||||
|
Aml *one = aml_int(1);
|
||||||
|
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||||
|
CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(machine);
|
||||||
|
PCMachineState *pcms = PC_MACHINE(machine);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _MAT method - creates an madt apic buffer
|
||||||
|
* apic_id = Arg0 = Local APIC ID
|
||||||
|
* cpu_id = Arg1 = Processor ID
|
||||||
|
* cpu_on = Local0 = CPON flag for this cpu
|
||||||
|
* madt = Local1 = Buffer (in madt apic form) to return
|
||||||
|
*/
|
||||||
|
method = aml_method(CPU_MAT_METHOD, 2, AML_NOTSERIALIZED);
|
||||||
|
aml_append(method,
|
||||||
|
aml_store(aml_derefof(aml_index(cpus_map, apic_id)), cpu_on));
|
||||||
|
aml_append(method,
|
||||||
|
aml_store(aml_buffer(sizeof(madt_tmpl), madt_tmpl), madt));
|
||||||
|
/* Update the processor id, lapic id, and enable/disable status */
|
||||||
|
aml_append(method, aml_store(cpu_id, aml_index(madt, aml_int(2))));
|
||||||
|
aml_append(method, aml_store(apic_id, aml_index(madt, aml_int(3))));
|
||||||
|
aml_append(method, aml_store(cpu_on, aml_index(madt, aml_int(4))));
|
||||||
|
aml_append(method, aml_return(madt));
|
||||||
|
aml_append(sb_scope, method);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _STA method - return ON status of cpu
|
||||||
|
* apic_id = Arg0 = Local APIC ID
|
||||||
|
* cpu_on = Local0 = CPON flag for this cpu
|
||||||
|
*/
|
||||||
|
method = aml_method(CPU_STATUS_METHOD, 1, AML_NOTSERIALIZED);
|
||||||
|
aml_append(method,
|
||||||
|
aml_store(aml_derefof(aml_index(cpus_map, apic_id)), cpu_on));
|
||||||
|
if_ctx = aml_if(cpu_on);
|
||||||
|
{
|
||||||
|
aml_append(if_ctx, aml_return(aml_int(0xF)));
|
||||||
|
}
|
||||||
|
aml_append(method, if_ctx);
|
||||||
|
else_ctx = aml_else();
|
||||||
|
{
|
||||||
|
aml_append(else_ctx, aml_return(zero));
|
||||||
|
}
|
||||||
|
aml_append(method, else_ctx);
|
||||||
|
aml_append(sb_scope, method);
|
||||||
|
|
||||||
|
method = aml_method(CPU_EJECT_METHOD, 2, AML_NOTSERIALIZED);
|
||||||
|
aml_append(method, aml_sleep(200));
|
||||||
|
aml_append(sb_scope, method);
|
||||||
|
|
||||||
|
method = aml_method(CPU_SCAN_METHOD, 0, AML_NOTSERIALIZED);
|
||||||
|
{
|
||||||
|
Aml *while_ctx, *if_ctx2, *else_ctx2;
|
||||||
|
Aml *bus_check_evt = aml_int(1);
|
||||||
|
Aml *remove_evt = aml_int(3);
|
||||||
|
Aml *status_map = aml_local(5); /* Local5 = active cpu bitmap */
|
||||||
|
Aml *byte = aml_local(2); /* Local2 = last read byte from bitmap */
|
||||||
|
Aml *idx = aml_local(0); /* Processor ID / APIC ID iterator */
|
||||||
|
Aml *is_cpu_on = aml_local(1); /* Local1 = CPON flag for cpu */
|
||||||
|
Aml *status = aml_local(3); /* Local3 = active state for cpu */
|
||||||
|
|
||||||
|
aml_append(method, aml_store(aml_name(CPU_STATUS_MAP), status_map));
|
||||||
|
aml_append(method, aml_store(zero, byte));
|
||||||
|
aml_append(method, aml_store(zero, idx));
|
||||||
|
|
||||||
|
/* While (idx < SizeOf(CPON)) */
|
||||||
|
while_ctx = aml_while(aml_lless(idx, aml_sizeof(cpus_map)));
|
||||||
|
aml_append(while_ctx,
|
||||||
|
aml_store(aml_derefof(aml_index(cpus_map, idx)), is_cpu_on));
|
||||||
|
|
||||||
|
if_ctx = aml_if(aml_and(idx, aml_int(0x07), NULL));
|
||||||
|
{
|
||||||
|
/* Shift down previously read bitmap byte */
|
||||||
|
aml_append(if_ctx, aml_shiftright(byte, one, byte));
|
||||||
|
}
|
||||||
|
aml_append(while_ctx, if_ctx);
|
||||||
|
|
||||||
|
else_ctx = aml_else();
|
||||||
|
{
|
||||||
|
/* Read next byte from cpu bitmap */
|
||||||
|
aml_append(else_ctx, aml_store(aml_derefof(aml_index(status_map,
|
||||||
|
aml_shiftright(idx, aml_int(3), NULL))), byte));
|
||||||
|
}
|
||||||
|
aml_append(while_ctx, else_ctx);
|
||||||
|
|
||||||
|
aml_append(while_ctx, aml_store(aml_and(byte, one, NULL), status));
|
||||||
|
if_ctx = aml_if(aml_lnot(aml_equal(is_cpu_on, status)));
|
||||||
|
{
|
||||||
|
/* State change - update CPON with new state */
|
||||||
|
aml_append(if_ctx, aml_store(status, aml_index(cpus_map, idx)));
|
||||||
|
if_ctx2 = aml_if(aml_equal(status, one));
|
||||||
|
{
|
||||||
|
aml_append(if_ctx2,
|
||||||
|
aml_call2(AML_NOTIFY_METHOD, idx, bus_check_evt));
|
||||||
|
}
|
||||||
|
aml_append(if_ctx, if_ctx2);
|
||||||
|
else_ctx2 = aml_else();
|
||||||
|
{
|
||||||
|
aml_append(else_ctx2,
|
||||||
|
aml_call2(AML_NOTIFY_METHOD, idx, remove_evt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
aml_append(if_ctx, else_ctx2);
|
||||||
|
aml_append(while_ctx, if_ctx);
|
||||||
|
|
||||||
|
aml_append(while_ctx, aml_increment(idx)); /* go to next cpu */
|
||||||
|
aml_append(method, while_ctx);
|
||||||
|
}
|
||||||
|
aml_append(sb_scope, method);
|
||||||
|
|
||||||
|
/* The current AML generator can cover the APIC ID range [0..255],
|
||||||
|
* inclusive, for VCPU hotplug. */
|
||||||
|
QEMU_BUILD_BUG_ON(ACPI_CPU_HOTPLUG_ID_LIMIT > 256);
|
||||||
|
g_assert(pcms->apic_id_limit <= ACPI_CPU_HOTPLUG_ID_LIMIT);
|
||||||
|
|
||||||
|
/* create PCI0.PRES device and its _CRS to reserve CPU hotplug MMIO */
|
||||||
|
dev = aml_device("PCI0." stringify(CPU_HOTPLUG_RESOURCE_DEVICE));
|
||||||
|
aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A06")));
|
||||||
|
aml_append(dev,
|
||||||
|
aml_name_decl("_UID", aml_string("CPU Hotplug resources"))
|
||||||
|
);
|
||||||
|
/* device present, functioning, decoding, not shown in UI */
|
||||||
|
aml_append(dev, aml_name_decl("_STA", aml_int(0xB)));
|
||||||
|
crs = aml_resource_template();
|
||||||
|
aml_append(crs,
|
||||||
|
aml_io(AML_DECODE16, io_base, io_base, 1, ACPI_GPE_PROC_LEN)
|
||||||
|
);
|
||||||
|
aml_append(dev, aml_name_decl("_CRS", crs));
|
||||||
|
aml_append(sb_scope, dev);
|
||||||
|
/* declare CPU hotplug MMIO region and PRS field to access it */
|
||||||
|
aml_append(sb_scope, aml_operation_region(
|
||||||
|
"PRST", AML_SYSTEM_IO, aml_int(io_base), ACPI_GPE_PROC_LEN));
|
||||||
|
field = aml_field("PRST", AML_BYTE_ACC, AML_NOLOCK, AML_PRESERVE);
|
||||||
|
aml_append(field, aml_named_field("PRS", 256));
|
||||||
|
aml_append(sb_scope, field);
|
||||||
|
|
||||||
|
/* build Processor object for each processor */
|
||||||
|
for (i = 0; i < apic_ids->len; i++) {
|
||||||
|
int apic_id = apic_ids->cpus[i].arch_id;
|
||||||
|
|
||||||
|
assert(apic_id < ACPI_CPU_HOTPLUG_ID_LIMIT);
|
||||||
|
|
||||||
|
dev = aml_processor(i, 0, 0, "CP%.02X", apic_id);
|
||||||
|
|
||||||
|
method = aml_method("_MAT", 0, AML_NOTSERIALIZED);
|
||||||
|
aml_append(method,
|
||||||
|
aml_return(aml_call2(CPU_MAT_METHOD, aml_int(apic_id), aml_int(i))
|
||||||
|
));
|
||||||
|
aml_append(dev, method);
|
||||||
|
|
||||||
|
method = aml_method("_STA", 0, AML_NOTSERIALIZED);
|
||||||
|
aml_append(method,
|
||||||
|
aml_return(aml_call1(CPU_STATUS_METHOD, aml_int(apic_id))));
|
||||||
|
aml_append(dev, method);
|
||||||
|
|
||||||
|
method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
|
||||||
|
aml_append(method,
|
||||||
|
aml_return(aml_call2(CPU_EJECT_METHOD, aml_int(apic_id),
|
||||||
|
aml_arg(0)))
|
||||||
|
);
|
||||||
|
aml_append(dev, method);
|
||||||
|
|
||||||
|
aml_append(sb_scope, dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* build this code:
|
||||||
|
* Method(NTFY, 2) {If (LEqual(Arg0, 0x00)) {Notify(CP00, Arg1)} ...}
|
||||||
|
*/
|
||||||
|
/* Arg0 = APIC ID */
|
||||||
|
method = aml_method(AML_NOTIFY_METHOD, 2, AML_NOTSERIALIZED);
|
||||||
|
for (i = 0; i < apic_ids->len; i++) {
|
||||||
|
int apic_id = apic_ids->cpus[i].arch_id;
|
||||||
|
|
||||||
|
if_ctx = aml_if(aml_equal(aml_arg(0), aml_int(apic_id)));
|
||||||
|
aml_append(if_ctx,
|
||||||
|
aml_notify(aml_name("CP%.02X", apic_id), aml_arg(1))
|
||||||
|
);
|
||||||
|
aml_append(method, if_ctx);
|
||||||
|
}
|
||||||
|
aml_append(sb_scope, method);
|
||||||
|
|
||||||
|
/* build "Name(CPON, Package() { One, One, ..., Zero, Zero, ... })"
|
||||||
|
*
|
||||||
|
* Note: The ability to create variable-sized packages was first
|
||||||
|
* introduced in ACPI 2.0. ACPI 1.0 only allowed fixed-size packages
|
||||||
|
* ith up to 255 elements. Windows guests up to win2k8 fail when
|
||||||
|
* VarPackageOp is used.
|
||||||
|
*/
|
||||||
|
pkg = pcms->apic_id_limit <= 255 ? aml_package(pcms->apic_id_limit) :
|
||||||
|
aml_varpackage(pcms->apic_id_limit);
|
||||||
|
|
||||||
|
for (i = 0, apic_idx = 0; i < apic_ids->len; i++) {
|
||||||
|
int apic_id = apic_ids->cpus[i].arch_id;
|
||||||
|
|
||||||
|
for (; apic_idx < apic_id; apic_idx++) {
|
||||||
|
aml_append(pkg, aml_int(0));
|
||||||
|
}
|
||||||
|
aml_append(pkg, aml_int(apic_ids->cpus[i].cpu ? 1 : 0));
|
||||||
|
apic_idx = apic_id + 1;
|
||||||
|
}
|
||||||
|
aml_append(sb_scope, aml_name_decl(CPU_ON_BITMAP, pkg));
|
||||||
|
g_free(apic_ids);
|
||||||
|
|
||||||
|
aml_append(ctx, sb_scope);
|
||||||
|
|
||||||
|
method = aml_method("\\_GPE._E02", 0, AML_NOTSERIALIZED);
|
||||||
|
aml_append(method, aml_call0("\\_SB." CPU_SCAN_METHOD));
|
||||||
|
aml_append(ctx, method);
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,136 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
|
||||||
#include "hw/acpi/cpu_hotplug.h"
|
|
||||||
|
|
||||||
void build_cpu_hotplug_aml(Aml *ctx)
|
|
||||||
{
|
|
||||||
Aml *method;
|
|
||||||
Aml *if_ctx;
|
|
||||||
Aml *else_ctx;
|
|
||||||
Aml *sb_scope = aml_scope("_SB");
|
|
||||||
uint8_t madt_tmpl[8] = {0x00, 0x08, 0x00, 0x00, 0x00, 0, 0, 0};
|
|
||||||
Aml *cpu_id = aml_arg(0);
|
|
||||||
Aml *cpu_on = aml_local(0);
|
|
||||||
Aml *madt = aml_local(1);
|
|
||||||
Aml *cpus_map = aml_name(CPU_ON_BITMAP);
|
|
||||||
Aml *zero = aml_int(0);
|
|
||||||
Aml *one = aml_int(1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* _MAT method - creates an madt apic buffer
|
|
||||||
* cpu_id = Arg0 = Processor ID = Local APIC ID
|
|
||||||
* cpu_on = Local0 = CPON flag for this cpu
|
|
||||||
* madt = Local1 = Buffer (in madt apic form) to return
|
|
||||||
*/
|
|
||||||
method = aml_method(CPU_MAT_METHOD, 1, AML_NOTSERIALIZED);
|
|
||||||
aml_append(method,
|
|
||||||
aml_store(aml_derefof(aml_index(cpus_map, cpu_id)), cpu_on));
|
|
||||||
aml_append(method,
|
|
||||||
aml_store(aml_buffer(sizeof(madt_tmpl), madt_tmpl), madt));
|
|
||||||
/* Update the processor id, lapic id, and enable/disable status */
|
|
||||||
aml_append(method, aml_store(cpu_id, aml_index(madt, aml_int(2))));
|
|
||||||
aml_append(method, aml_store(cpu_id, aml_index(madt, aml_int(3))));
|
|
||||||
aml_append(method, aml_store(cpu_on, aml_index(madt, aml_int(4))));
|
|
||||||
aml_append(method, aml_return(madt));
|
|
||||||
aml_append(sb_scope, method);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* _STA method - return ON status of cpu
|
|
||||||
* cpu_id = Arg0 = Processor ID = Local APIC ID
|
|
||||||
* cpu_on = Local0 = CPON flag for this cpu
|
|
||||||
*/
|
|
||||||
method = aml_method(CPU_STATUS_METHOD, 1, AML_NOTSERIALIZED);
|
|
||||||
aml_append(method,
|
|
||||||
aml_store(aml_derefof(aml_index(cpus_map, cpu_id)), cpu_on));
|
|
||||||
if_ctx = aml_if(cpu_on);
|
|
||||||
{
|
|
||||||
aml_append(if_ctx, aml_return(aml_int(0xF)));
|
|
||||||
}
|
|
||||||
aml_append(method, if_ctx);
|
|
||||||
else_ctx = aml_else();
|
|
||||||
{
|
|
||||||
aml_append(else_ctx, aml_return(zero));
|
|
||||||
}
|
|
||||||
aml_append(method, else_ctx);
|
|
||||||
aml_append(sb_scope, method);
|
|
||||||
|
|
||||||
method = aml_method(CPU_EJECT_METHOD, 2, AML_NOTSERIALIZED);
|
|
||||||
aml_append(method, aml_sleep(200));
|
|
||||||
aml_append(sb_scope, method);
|
|
||||||
|
|
||||||
method = aml_method(CPU_SCAN_METHOD, 0, AML_NOTSERIALIZED);
|
|
||||||
{
|
|
||||||
Aml *while_ctx, *if_ctx2, *else_ctx2;
|
|
||||||
Aml *bus_check_evt = aml_int(1);
|
|
||||||
Aml *remove_evt = aml_int(3);
|
|
||||||
Aml *status_map = aml_local(5); /* Local5 = active cpu bitmap */
|
|
||||||
Aml *byte = aml_local(2); /* Local2 = last read byte from bitmap */
|
|
||||||
Aml *idx = aml_local(0); /* Processor ID / APIC ID iterator */
|
|
||||||
Aml *is_cpu_on = aml_local(1); /* Local1 = CPON flag for cpu */
|
|
||||||
Aml *status = aml_local(3); /* Local3 = active state for cpu */
|
|
||||||
|
|
||||||
aml_append(method, aml_store(aml_name(CPU_STATUS_MAP), status_map));
|
|
||||||
aml_append(method, aml_store(zero, byte));
|
|
||||||
aml_append(method, aml_store(zero, idx));
|
|
||||||
|
|
||||||
/* While (idx < SizeOf(CPON)) */
|
|
||||||
while_ctx = aml_while(aml_lless(idx, aml_sizeof(cpus_map)));
|
|
||||||
aml_append(while_ctx,
|
|
||||||
aml_store(aml_derefof(aml_index(cpus_map, idx)), is_cpu_on));
|
|
||||||
|
|
||||||
if_ctx = aml_if(aml_and(idx, aml_int(0x07), NULL));
|
|
||||||
{
|
|
||||||
/* Shift down previously read bitmap byte */
|
|
||||||
aml_append(if_ctx, aml_shiftright(byte, one, byte));
|
|
||||||
}
|
|
||||||
aml_append(while_ctx, if_ctx);
|
|
||||||
|
|
||||||
else_ctx = aml_else();
|
|
||||||
{
|
|
||||||
/* Read next byte from cpu bitmap */
|
|
||||||
aml_append(else_ctx, aml_store(aml_derefof(aml_index(status_map,
|
|
||||||
aml_shiftright(idx, aml_int(3), NULL))), byte));
|
|
||||||
}
|
|
||||||
aml_append(while_ctx, else_ctx);
|
|
||||||
|
|
||||||
aml_append(while_ctx, aml_store(aml_and(byte, one, NULL), status));
|
|
||||||
if_ctx = aml_if(aml_lnot(aml_equal(is_cpu_on, status)));
|
|
||||||
{
|
|
||||||
/* State change - update CPON with new state */
|
|
||||||
aml_append(if_ctx, aml_store(status, aml_index(cpus_map, idx)));
|
|
||||||
if_ctx2 = aml_if(aml_equal(status, one));
|
|
||||||
{
|
|
||||||
aml_append(if_ctx2,
|
|
||||||
aml_call2(AML_NOTIFY_METHOD, idx, bus_check_evt));
|
|
||||||
}
|
|
||||||
aml_append(if_ctx, if_ctx2);
|
|
||||||
else_ctx2 = aml_else();
|
|
||||||
{
|
|
||||||
aml_append(else_ctx2,
|
|
||||||
aml_call2(AML_NOTIFY_METHOD, idx, remove_evt));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
aml_append(if_ctx, else_ctx2);
|
|
||||||
aml_append(while_ctx, if_ctx);
|
|
||||||
|
|
||||||
aml_append(while_ctx, aml_increment(idx)); /* go to next cpu */
|
|
||||||
aml_append(method, while_ctx);
|
|
||||||
}
|
|
||||||
aml_append(sb_scope, method);
|
|
||||||
|
|
||||||
aml_append(ctx, sb_scope);
|
|
||||||
}
|
|
||||||
@@ -273,8 +273,8 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm,
|
|||||||
pm->powerdown_notifier.notify = pm_powerdown_req;
|
pm->powerdown_notifier.notify = pm_powerdown_req;
|
||||||
qemu_register_powerdown_notifier(&pm->powerdown_notifier);
|
qemu_register_powerdown_notifier(&pm->powerdown_notifier);
|
||||||
|
|
||||||
acpi_cpu_hotplug_init(pci_address_space_io(lpc_pci), OBJECT(lpc_pci),
|
legacy_acpi_cpu_hotplug_init(pci_address_space_io(lpc_pci),
|
||||||
&pm->gpe_cpu, ICH9_CPU_HOTPLUG_IO_BASE);
|
OBJECT(lpc_pci), &pm->gpe_cpu, ICH9_CPU_HOTPLUG_IO_BASE);
|
||||||
|
|
||||||
if (pm->acpi_memory_hotplug.is_enabled) {
|
if (pm->acpi_memory_hotplug.is_enabled) {
|
||||||
acpi_memory_hotplug_init(pci_address_space_io(lpc_pci), OBJECT(lpc_pci),
|
acpi_memory_hotplug_init(pci_address_space_io(lpc_pci), OBJECT(lpc_pci),
|
||||||
@@ -430,39 +430,47 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm, Error **errp)
|
|||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ich9_pm_device_plug_cb(ICH9LPCPMRegs *pm, DeviceState *dev, Error **errp)
|
void ich9_pm_device_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||||
|
Error **errp)
|
||||||
{
|
{
|
||||||
if (pm->acpi_memory_hotplug.is_enabled &&
|
ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
|
||||||
|
|
||||||
|
if (lpc->pm.acpi_memory_hotplug.is_enabled &&
|
||||||
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
|
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
|
||||||
acpi_memory_plug_cb(&pm->acpi_regs, pm->irq, &pm->acpi_memory_hotplug,
|
acpi_memory_plug_cb(hotplug_dev, &lpc->pm.acpi_memory_hotplug,
|
||||||
dev, errp);
|
dev, errp);
|
||||||
} else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
|
} else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
|
||||||
acpi_cpu_plug_cb(&pm->acpi_regs, pm->irq, &pm->gpe_cpu, dev, errp);
|
legacy_acpi_cpu_plug_cb(hotplug_dev, &lpc->pm.gpe_cpu, dev, errp);
|
||||||
} else {
|
} else {
|
||||||
error_setg(errp, "acpi: device plug request for not supported device"
|
error_setg(errp, "acpi: device plug request for not supported device"
|
||||||
" type: %s", object_get_typename(OBJECT(dev)));
|
" type: %s", object_get_typename(OBJECT(dev)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ich9_pm_device_unplug_request_cb(ICH9LPCPMRegs *pm, DeviceState *dev,
|
void ich9_pm_device_unplug_request_cb(HotplugHandler *hotplug_dev,
|
||||||
Error **errp)
|
DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
if (pm->acpi_memory_hotplug.is_enabled &&
|
ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
|
||||||
|
|
||||||
|
if (lpc->pm.acpi_memory_hotplug.is_enabled &&
|
||||||
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
|
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
|
||||||
acpi_memory_unplug_request_cb(&pm->acpi_regs, pm->irq,
|
acpi_memory_unplug_request_cb(hotplug_dev,
|
||||||
&pm->acpi_memory_hotplug, dev, errp);
|
&lpc->pm.acpi_memory_hotplug, dev,
|
||||||
|
errp);
|
||||||
} else {
|
} else {
|
||||||
error_setg(errp, "acpi: device unplug request for not supported device"
|
error_setg(errp, "acpi: device unplug request for not supported device"
|
||||||
" type: %s", object_get_typename(OBJECT(dev)));
|
" type: %s", object_get_typename(OBJECT(dev)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ich9_pm_device_unplug_cb(ICH9LPCPMRegs *pm, DeviceState *dev,
|
void ich9_pm_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
{
|
{
|
||||||
if (pm->acpi_memory_hotplug.is_enabled &&
|
ICH9LPCState *lpc = ICH9_LPC_DEVICE(hotplug_dev);
|
||||||
|
|
||||||
|
if (lpc->pm.acpi_memory_hotplug.is_enabled &&
|
||||||
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
|
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
|
||||||
acpi_memory_unplug_cb(&pm->acpi_memory_hotplug, dev, errp);
|
acpi_memory_unplug_cb(&lpc->pm.acpi_memory_hotplug, dev, errp);
|
||||||
} else {
|
} else {
|
||||||
error_setg(errp, "acpi: device unplug for not supported device"
|
error_setg(errp, "acpi: device unplug for not supported device"
|
||||||
" type: %s", object_get_typename(OBJECT(dev)));
|
" type: %s", object_get_typename(OBJECT(dev)));
|
||||||
|
|||||||
@@ -228,7 +228,7 @@ acpi_memory_slot_status(MemHotplugState *mem_st,
|
|||||||
return &mem_st->devs[slot];
|
return &mem_st->devs[slot];
|
||||||
}
|
}
|
||||||
|
|
||||||
void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st,
|
void acpi_memory_plug_cb(HotplugHandler *hotplug_dev, MemHotplugState *mem_st,
|
||||||
DeviceState *dev, Error **errp)
|
DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
MemStatus *mdev;
|
MemStatus *mdev;
|
||||||
@@ -247,13 +247,11 @@ void acpi_memory_plug_cb(ACPIREGS *ar, qemu_irq irq, MemHotplugState *mem_st,
|
|||||||
mdev->is_enabled = true;
|
mdev->is_enabled = true;
|
||||||
if (dev->hotplugged) {
|
if (dev->hotplugged) {
|
||||||
mdev->is_inserting = true;
|
mdev->is_inserting = true;
|
||||||
|
acpi_send_event(DEVICE(hotplug_dev), ACPI_MEMORY_HOTPLUG_STATUS);
|
||||||
/* do ACPI magic */
|
|
||||||
acpi_send_gpe_event(ar, irq, ACPI_MEMORY_HOTPLUG_STATUS);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void acpi_memory_unplug_request_cb(ACPIREGS *ar, qemu_irq irq,
|
void acpi_memory_unplug_request_cb(HotplugHandler *hotplug_dev,
|
||||||
MemHotplugState *mem_st,
|
MemHotplugState *mem_st,
|
||||||
DeviceState *dev, Error **errp)
|
DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
@@ -265,9 +263,7 @@ void acpi_memory_unplug_request_cb(ACPIREGS *ar, qemu_irq irq,
|
|||||||
}
|
}
|
||||||
|
|
||||||
mdev->is_removing = true;
|
mdev->is_removing = true;
|
||||||
|
acpi_send_event(DEVICE(hotplug_dev), ACPI_MEMORY_HOTPLUG_STATUS);
|
||||||
/* Do ACPI magic */
|
|
||||||
acpi_send_gpe_event(ar, irq, ACPI_MEMORY_HOTPLUG_STATUS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void acpi_memory_unplug_cb(MemHotplugState *mem_st,
|
void acpi_memory_unplug_cb(MemHotplugState *mem_st,
|
||||||
|
|||||||
@@ -353,7 +353,7 @@ static GArray *nvdimm_build_device_structure(GSList *device_list)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void nvdimm_build_nfit(GSList *device_list, GArray *table_offsets,
|
static void nvdimm_build_nfit(GSList *device_list, GArray *table_offsets,
|
||||||
GArray *table_data, GArray *linker)
|
GArray *table_data, BIOSLinker *linker)
|
||||||
{
|
{
|
||||||
GArray *structures = nvdimm_build_device_structure(device_list);
|
GArray *structures = nvdimm_build_device_structure(device_list);
|
||||||
unsigned int header;
|
unsigned int header;
|
||||||
@@ -579,7 +579,8 @@ static void nvdimm_build_nvdimm_devices(GSList *device_list, Aml *root_dev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets,
|
static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets,
|
||||||
GArray *table_data, GArray *linker)
|
GArray *table_data, BIOSLinker *linker,
|
||||||
|
GArray *dsm_dma_arrea)
|
||||||
{
|
{
|
||||||
Aml *ssdt, *sb_scope, *dev, *field;
|
Aml *ssdt, *sb_scope, *dev, *field;
|
||||||
int mem_addr_offset, nvdimm_ssdt;
|
int mem_addr_offset, nvdimm_ssdt;
|
||||||
@@ -678,12 +679,12 @@ static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets,
|
|||||||
mem_addr_offset = build_append_named_dword(table_data,
|
mem_addr_offset = build_append_named_dword(table_data,
|
||||||
NVDIMM_ACPI_MEM_ADDR);
|
NVDIMM_ACPI_MEM_ADDR);
|
||||||
|
|
||||||
bios_linker_loader_alloc(linker, NVDIMM_DSM_MEM_FILE, sizeof(NvdimmDsmIn),
|
bios_linker_loader_alloc(linker,
|
||||||
false /* high memory */);
|
NVDIMM_DSM_MEM_FILE, dsm_dma_arrea,
|
||||||
bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
|
sizeof(NvdimmDsmIn), false /* high memory */);
|
||||||
NVDIMM_DSM_MEM_FILE, table_data,
|
bios_linker_loader_add_pointer(linker,
|
||||||
table_data->data + mem_addr_offset,
|
ACPI_BUILD_TABLE_FILE, mem_addr_offset, sizeof(uint32_t),
|
||||||
sizeof(uint32_t));
|
NVDIMM_DSM_MEM_FILE, 0);
|
||||||
build_header(linker, table_data,
|
build_header(linker, table_data,
|
||||||
(void *)(table_data->data + nvdimm_ssdt),
|
(void *)(table_data->data + nvdimm_ssdt),
|
||||||
"SSDT", table_data->len - nvdimm_ssdt, 1, NULL, "NVDIMM");
|
"SSDT", table_data->len - nvdimm_ssdt, 1, NULL, "NVDIMM");
|
||||||
@@ -691,7 +692,7 @@ static void nvdimm_build_ssdt(GSList *device_list, GArray *table_offsets,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
|
void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
|
||||||
GArray *linker)
|
BIOSLinker *linker, GArray *dsm_dma_arrea)
|
||||||
{
|
{
|
||||||
GSList *device_list;
|
GSList *device_list;
|
||||||
|
|
||||||
@@ -701,6 +702,7 @@ void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
nvdimm_build_nfit(device_list, table_offsets, table_data, linker);
|
nvdimm_build_nfit(device_list, table_offsets, table_data, linker);
|
||||||
nvdimm_build_ssdt(device_list, table_offsets, table_data, linker);
|
nvdimm_build_ssdt(device_list, table_offsets, table_data, linker,
|
||||||
|
dsm_dma_arrea);
|
||||||
g_slist_free(device_list);
|
g_slist_free(device_list);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ void acpi_pcihp_reset(AcpiPciHpState *s)
|
|||||||
acpi_pcihp_update(s);
|
acpi_pcihp_update(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void acpi_pcihp_device_plug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s,
|
void acpi_pcihp_device_plug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
|
||||||
DeviceState *dev, Error **errp)
|
DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
PCIDevice *pdev = PCI_DEVICE(dev);
|
PCIDevice *pdev = PCI_DEVICE(dev);
|
||||||
@@ -202,11 +202,10 @@ void acpi_pcihp_device_plug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
s->acpi_pcihp_pci_status[bsel].up |= (1U << slot);
|
s->acpi_pcihp_pci_status[bsel].up |= (1U << slot);
|
||||||
|
acpi_send_event(DEVICE(hotplug_dev), ACPI_PCI_HOTPLUG_STATUS);
|
||||||
acpi_send_gpe_event(ar, irq, ACPI_PCI_HOTPLUG_STATUS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void acpi_pcihp_device_unplug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s,
|
void acpi_pcihp_device_unplug_cb(HotplugHandler *hotplug_dev, AcpiPciHpState *s,
|
||||||
DeviceState *dev, Error **errp)
|
DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
PCIDevice *pdev = PCI_DEVICE(dev);
|
PCIDevice *pdev = PCI_DEVICE(dev);
|
||||||
@@ -219,8 +218,7 @@ void acpi_pcihp_device_unplug_cb(ACPIREGS *ar, qemu_irq irq, AcpiPciHpState *s,
|
|||||||
}
|
}
|
||||||
|
|
||||||
s->acpi_pcihp_pci_status[bsel].down |= (1U << slot);
|
s->acpi_pcihp_pci_status[bsel].down |= (1U << slot);
|
||||||
|
acpi_send_event(DEVICE(hotplug_dev), ACPI_PCI_HOTPLUG_STATUS);
|
||||||
acpi_send_gpe_event(ar, irq, ACPI_PCI_HOTPLUG_STATUS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size)
|
static uint64_t pci_read(void *opaque, hwaddr addr, unsigned int size)
|
||||||
|
|||||||
@@ -348,12 +348,11 @@ static void piix4_device_plug_cb(HotplugHandler *hotplug_dev,
|
|||||||
|
|
||||||
if (s->acpi_memory_hotplug.is_enabled &&
|
if (s->acpi_memory_hotplug.is_enabled &&
|
||||||
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
|
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
|
||||||
acpi_memory_plug_cb(&s->ar, s->irq, &s->acpi_memory_hotplug, dev, errp);
|
acpi_memory_plug_cb(hotplug_dev, &s->acpi_memory_hotplug, dev, errp);
|
||||||
} else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
|
} else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
|
||||||
acpi_pcihp_device_plug_cb(&s->ar, s->irq, &s->acpi_pci_hotplug, dev,
|
acpi_pcihp_device_plug_cb(hotplug_dev, &s->acpi_pci_hotplug, dev, errp);
|
||||||
errp);
|
|
||||||
} else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
|
} else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
|
||||||
acpi_cpu_plug_cb(&s->ar, s->irq, &s->gpe_cpu, dev, errp);
|
legacy_acpi_cpu_plug_cb(hotplug_dev, &s->gpe_cpu, dev, errp);
|
||||||
} else {
|
} else {
|
||||||
error_setg(errp, "acpi: device plug request for not supported device"
|
error_setg(errp, "acpi: device plug request for not supported device"
|
||||||
" type: %s", object_get_typename(OBJECT(dev)));
|
" type: %s", object_get_typename(OBJECT(dev)));
|
||||||
@@ -367,10 +366,10 @@ static void piix4_device_unplug_request_cb(HotplugHandler *hotplug_dev,
|
|||||||
|
|
||||||
if (s->acpi_memory_hotplug.is_enabled &&
|
if (s->acpi_memory_hotplug.is_enabled &&
|
||||||
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
|
object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) {
|
||||||
acpi_memory_unplug_request_cb(&s->ar, s->irq, &s->acpi_memory_hotplug,
|
acpi_memory_unplug_request_cb(hotplug_dev, &s->acpi_memory_hotplug,
|
||||||
dev, errp);
|
dev, errp);
|
||||||
} else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
|
} else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
|
||||||
acpi_pcihp_device_unplug_cb(&s->ar, s->irq, &s->acpi_pci_hotplug, dev,
|
acpi_pcihp_device_unplug_cb(hotplug_dev, &s->acpi_pci_hotplug, dev,
|
||||||
errp);
|
errp);
|
||||||
} else {
|
} else {
|
||||||
error_setg(errp, "acpi: device unplug request for not supported device"
|
error_setg(errp, "acpi: device unplug request for not supported device"
|
||||||
@@ -571,8 +570,8 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
|
|||||||
acpi_pcihp_init(OBJECT(s), &s->acpi_pci_hotplug, bus, parent,
|
acpi_pcihp_init(OBJECT(s), &s->acpi_pci_hotplug, bus, parent,
|
||||||
s->use_acpi_pci_hotplug);
|
s->use_acpi_pci_hotplug);
|
||||||
|
|
||||||
acpi_cpu_hotplug_init(parent, OBJECT(s), &s->gpe_cpu,
|
legacy_acpi_cpu_hotplug_init(parent, OBJECT(s), &s->gpe_cpu,
|
||||||
PIIX4_CPU_HOTPLUG_IO_BASE);
|
PIIX4_CPU_HOTPLUG_IO_BASE);
|
||||||
|
|
||||||
if (s->acpi_memory_hotplug.is_enabled) {
|
if (s->acpi_memory_hotplug.is_enabled) {
|
||||||
acpi_memory_hotplug_init(parent, OBJECT(s), &s->acpi_memory_hotplug);
|
acpi_memory_hotplug_init(parent, OBJECT(s), &s->acpi_memory_hotplug);
|
||||||
@@ -586,6 +585,13 @@ static void piix4_ospm_status(AcpiDeviceIf *adev, ACPIOSTInfoList ***list)
|
|||||||
acpi_memory_ospm_status(&s->acpi_memory_hotplug, list);
|
acpi_memory_ospm_status(&s->acpi_memory_hotplug, list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void piix4_send_gpe(AcpiDeviceIf *adev, AcpiEventStatusBits ev)
|
||||||
|
{
|
||||||
|
PIIX4PMState *s = PIIX4_PM(adev);
|
||||||
|
|
||||||
|
acpi_send_gpe_event(&s->ar, s->irq, ev);
|
||||||
|
}
|
||||||
|
|
||||||
static Property piix4_pm_properties[] = {
|
static Property piix4_pm_properties[] = {
|
||||||
DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0),
|
DEFINE_PROP_UINT32("smb_io_base", PIIX4PMState, smb_io_base, 0),
|
||||||
DEFINE_PROP_UINT8(ACPI_PM_PROP_S3_DISABLED, PIIX4PMState, disable_s3, 0),
|
DEFINE_PROP_UINT8(ACPI_PM_PROP_S3_DISABLED, PIIX4PMState, disable_s3, 0),
|
||||||
@@ -624,6 +630,7 @@ static void piix4_pm_class_init(ObjectClass *klass, void *data)
|
|||||||
hc->unplug_request = piix4_device_unplug_request_cb;
|
hc->unplug_request = piix4_device_unplug_request_cb;
|
||||||
hc->unplug = piix4_device_unplug_cb;
|
hc->unplug = piix4_device_unplug_cb;
|
||||||
adevc->ospm_status = piix4_ospm_status;
|
adevc->ospm_status = piix4_ospm_status;
|
||||||
|
adevc->send_event = piix4_send_gpe;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo piix4_pm_info = {
|
static const TypeInfo piix4_pm_info = {
|
||||||
|
|||||||
@@ -18,12 +18,14 @@
|
|||||||
#include "hw/arm/ast2400.h"
|
#include "hw/arm/ast2400.h"
|
||||||
#include "hw/char/serial.h"
|
#include "hw/char/serial.h"
|
||||||
#include "qemu/log.h"
|
#include "qemu/log.h"
|
||||||
|
#include "hw/i2c/aspeed_i2c.h"
|
||||||
|
|
||||||
#define AST2400_UART_5_BASE 0x00184000
|
#define AST2400_UART_5_BASE 0x00184000
|
||||||
#define AST2400_IOMEM_SIZE 0x00200000
|
#define AST2400_IOMEM_SIZE 0x00200000
|
||||||
#define AST2400_IOMEM_BASE 0x1E600000
|
#define AST2400_IOMEM_BASE 0x1E600000
|
||||||
#define AST2400_VIC_BASE 0x1E6C0000
|
#define AST2400_VIC_BASE 0x1E6C0000
|
||||||
#define AST2400_TIMER_BASE 0x1E782000
|
#define AST2400_TIMER_BASE 0x1E782000
|
||||||
|
#define AST2400_I2C_BASE 0x1E78A000
|
||||||
|
|
||||||
static const int uart_irqs[] = { 9, 32, 33, 34, 10 };
|
static const int uart_irqs[] = { 9, 32, 33, 34, 10 };
|
||||||
static const int timer_irqs[] = { 16, 17, 18, 35, 36, 37, 38, 39, };
|
static const int timer_irqs[] = { 16, 17, 18, 35, 36, 37, 38, 39, };
|
||||||
@@ -66,6 +68,10 @@ static void ast2400_init(Object *obj)
|
|||||||
object_initialize(&s->timerctrl, sizeof(s->timerctrl), TYPE_ASPEED_TIMER);
|
object_initialize(&s->timerctrl, sizeof(s->timerctrl), TYPE_ASPEED_TIMER);
|
||||||
object_property_add_child(obj, "timerctrl", OBJECT(&s->timerctrl), NULL);
|
object_property_add_child(obj, "timerctrl", OBJECT(&s->timerctrl), NULL);
|
||||||
qdev_set_parent_bus(DEVICE(&s->timerctrl), sysbus_get_default());
|
qdev_set_parent_bus(DEVICE(&s->timerctrl), sysbus_get_default());
|
||||||
|
|
||||||
|
object_initialize(&s->i2c, sizeof(s->i2c), TYPE_ASPEED_I2C);
|
||||||
|
object_property_add_child(obj, "i2c", OBJECT(&s->i2c), NULL);
|
||||||
|
qdev_set_parent_bus(DEVICE(&s->i2c), sysbus_get_default());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ast2400_realize(DeviceState *dev, Error **errp)
|
static void ast2400_realize(DeviceState *dev, Error **errp)
|
||||||
@@ -110,6 +116,16 @@ static void ast2400_realize(DeviceState *dev, Error **errp)
|
|||||||
serial_mm_init(&s->iomem, AST2400_UART_5_BASE, 2,
|
serial_mm_init(&s->iomem, AST2400_UART_5_BASE, 2,
|
||||||
uart5, 38400, serial_hds[0], DEVICE_LITTLE_ENDIAN);
|
uart5, 38400, serial_hds[0], DEVICE_LITTLE_ENDIAN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* I2C */
|
||||||
|
object_property_set_bool(OBJECT(&s->i2c), true, "realized", &err);
|
||||||
|
if (err) {
|
||||||
|
error_propagate(errp, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c), 0, AST2400_I2C_BASE);
|
||||||
|
sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c), 0,
|
||||||
|
qdev_get_gpio_in(DEVICE(&s->vic), 12));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ast2400_class_init(ObjectClass *oc, void *data)
|
static void ast2400_class_init(ObjectClass *oc, void *data)
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include "hw/misc/bcm2835_mbox_defs.h"
|
#include "hw/misc/bcm2835_mbox_defs.h"
|
||||||
#include "hw/arm/raspi_platform.h"
|
#include "hw/arm/raspi_platform.h"
|
||||||
#include "sysemu/char.h"
|
#include "sysemu/char.h"
|
||||||
|
#include "sysemu/sysemu.h"
|
||||||
|
|
||||||
/* Peripheral base address on the VC (GPU) system bus */
|
/* Peripheral base address on the VC (GPU) system bus */
|
||||||
#define BCM2835_VC_PERI_BASE 0x7e000000
|
#define BCM2835_VC_PERI_BASE 0x7e000000
|
||||||
@@ -106,7 +107,6 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
|
|||||||
MemoryRegion *ram;
|
MemoryRegion *ram;
|
||||||
Error *err = NULL;
|
Error *err = NULL;
|
||||||
uint32_t ram_size, vcram_size;
|
uint32_t ram_size, vcram_size;
|
||||||
CharDriverState *chr;
|
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
obj = object_property_get_link(OBJECT(dev), "ram", &err);
|
obj = object_property_get_link(OBJECT(dev), "ram", &err);
|
||||||
@@ -147,6 +147,7 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
|
|||||||
sysbus_pass_irq(SYS_BUS_DEVICE(s), SYS_BUS_DEVICE(&s->ic));
|
sysbus_pass_irq(SYS_BUS_DEVICE(s), SYS_BUS_DEVICE(&s->ic));
|
||||||
|
|
||||||
/* UART0 */
|
/* UART0 */
|
||||||
|
qdev_prop_set_chr(DEVICE(s->uart0), "chardev", serial_hds[0]);
|
||||||
object_property_set_bool(OBJECT(s->uart0), true, "realized", &err);
|
object_property_set_bool(OBJECT(s->uart0), true, "realized", &err);
|
||||||
if (err) {
|
if (err) {
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
@@ -158,17 +159,8 @@ static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp)
|
|||||||
sysbus_connect_irq(s->uart0, 0,
|
sysbus_connect_irq(s->uart0, 0,
|
||||||
qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
|
qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ,
|
||||||
INTERRUPT_UART));
|
INTERRUPT_UART));
|
||||||
|
|
||||||
/* AUX / UART1 */
|
/* AUX / UART1 */
|
||||||
/* TODO: don't call qemu_char_get_next_serial() here, instead set
|
qdev_prop_set_chr(DEVICE(&s->aux), "chardev", serial_hds[1]);
|
||||||
* chardev properties for each uart at the board level, once pl011
|
|
||||||
* (uart0) has been updated to avoid qemu_char_get_next_serial()
|
|
||||||
*/
|
|
||||||
chr = qemu_char_get_next_serial();
|
|
||||||
if (chr == NULL) {
|
|
||||||
chr = qemu_chr_new("bcm2835.uart1", "null", NULL);
|
|
||||||
}
|
|
||||||
qdev_prop_set_chr(DEVICE(&s->aux), "chardev", chr);
|
|
||||||
|
|
||||||
object_property_set_bool(OBJECT(&s->aux), true, "realized", &err);
|
object_property_set_bool(OBJECT(&s->aux), true, "realized", &err);
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -292,8 +284,6 @@ static void bcm2835_peripherals_class_init(ObjectClass *oc, void *data)
|
|||||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||||
|
|
||||||
dc->realize = bcm2835_peripherals_realize;
|
dc->realize = bcm2835_peripherals_realize;
|
||||||
/* Reason: realize() method uses qemu_char_get_next_serial() */
|
|
||||||
dc->cannot_instantiate_with_device_add_yet = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo bcm2835_peripherals_type_info = {
|
static const TypeInfo bcm2835_peripherals_type_info = {
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "hw/arm/digic.h"
|
#include "hw/arm/digic.h"
|
||||||
|
#include "sysemu/sysemu.h"
|
||||||
|
|
||||||
#define DIGIC4_TIMER_BASE(n) (0xc0210000 + (n) * 0x100)
|
#define DIGIC4_TIMER_BASE(n) (0xc0210000 + (n) * 0x100)
|
||||||
|
|
||||||
@@ -84,6 +85,7 @@ static void digic_realize(DeviceState *dev, Error **errp)
|
|||||||
sysbus_mmio_map(sbd, 0, DIGIC4_TIMER_BASE(i));
|
sysbus_mmio_map(sbd, 0, DIGIC4_TIMER_BASE(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qdev_prop_set_chr(DEVICE(&s->uart), "chardev", serial_hds[0]);
|
||||||
object_property_set_bool(OBJECT(&s->uart), true, "realized", &err);
|
object_property_set_bool(OBJECT(&s->uart), true, "realized", &err);
|
||||||
if (err != NULL) {
|
if (err != NULL) {
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "sysemu/block-backend.h"
|
#include "sysemu/block-backend.h"
|
||||||
#include "exec/address-spaces.h"
|
#include "exec/address-spaces.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
|
#include "hw/char/pl011.h"
|
||||||
|
|
||||||
#define SMP_BOOT_ADDR 0x100
|
#define SMP_BOOT_ADDR 0x100
|
||||||
#define SMP_BOOT_REG 0x40
|
#define SMP_BOOT_REG 0x40
|
||||||
@@ -326,7 +327,7 @@ static void calxeda_init(MachineState *machine, enum cxmachines machine_id)
|
|||||||
busdev = SYS_BUS_DEVICE(dev);
|
busdev = SYS_BUS_DEVICE(dev);
|
||||||
sysbus_mmio_map(busdev, 0, 0xfff34000);
|
sysbus_mmio_map(busdev, 0, 0xfff34000);
|
||||||
sysbus_connect_irq(busdev, 0, pic[18]);
|
sysbus_connect_irq(busdev, 0, pic[18]);
|
||||||
sysbus_create_simple("pl011", 0xfff36000, pic[20]);
|
pl011_create(0xfff36000, pic[20], serial_hds[0]);
|
||||||
|
|
||||||
dev = qdev_create(NULL, "highbank-regs");
|
dev = qdev_create(NULL, "highbank-regs");
|
||||||
qdev_init_nofail(dev);
|
qdev_init_nofail(dev);
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include "exec/address-spaces.h"
|
#include "exec/address-spaces.h"
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
|
#include "hw/char/pl011.h"
|
||||||
|
|
||||||
#define TYPE_INTEGRATOR_CM "integrator_core"
|
#define TYPE_INTEGRATOR_CM "integrator_core"
|
||||||
#define INTEGRATOR_CM(obj) \
|
#define INTEGRATOR_CM(obj) \
|
||||||
@@ -588,8 +589,8 @@ static void integratorcp_init(MachineState *machine)
|
|||||||
sysbus_create_varargs("integrator_pit", 0x13000000,
|
sysbus_create_varargs("integrator_pit", 0x13000000,
|
||||||
pic[5], pic[6], pic[7], NULL);
|
pic[5], pic[6], pic[7], NULL);
|
||||||
sysbus_create_simple("pl031", 0x15000000, pic[8]);
|
sysbus_create_simple("pl031", 0x15000000, pic[8]);
|
||||||
sysbus_create_simple("pl011", 0x16000000, pic[1]);
|
pl011_create(0x16000000, pic[1], serial_hds[0]);
|
||||||
sysbus_create_simple("pl011", 0x17000000, pic[2]);
|
pl011_create(0x17000000, pic[2], serial_hds[1]);
|
||||||
icp = sysbus_create_simple(TYPE_ICP_CONTROL_REGS, 0xcb000000,
|
icp = sysbus_create_simple(TYPE_ICP_CONTROL_REGS, 0xcb000000,
|
||||||
qdev_get_gpio_in(sic, 3));
|
qdev_get_gpio_in(sic, 3));
|
||||||
sysbus_create_simple("pl050_keyboard", 0x18000000, pic[3]);
|
sysbus_create_simple("pl050_keyboard", 0x18000000, pic[3]);
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include "sysemu/block-backend.h"
|
#include "sysemu/block-backend.h"
|
||||||
#include "exec/address-spaces.h"
|
#include "exec/address-spaces.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
|
#include "hw/char/pl011.h"
|
||||||
|
|
||||||
#define SMP_BOOT_ADDR 0xe0000000
|
#define SMP_BOOT_ADDR 0xe0000000
|
||||||
#define SMP_BOOTREG_ADDR 0x10000030
|
#define SMP_BOOTREG_ADDR 0x10000030
|
||||||
@@ -202,10 +203,10 @@ static void realview_init(MachineState *machine,
|
|||||||
sysbus_create_simple("pl050_keyboard", 0x10006000, pic[20]);
|
sysbus_create_simple("pl050_keyboard", 0x10006000, pic[20]);
|
||||||
sysbus_create_simple("pl050_mouse", 0x10007000, pic[21]);
|
sysbus_create_simple("pl050_mouse", 0x10007000, pic[21]);
|
||||||
|
|
||||||
sysbus_create_simple("pl011", 0x10009000, pic[12]);
|
pl011_create(0x10009000, pic[12], serial_hds[0]);
|
||||||
sysbus_create_simple("pl011", 0x1000a000, pic[13]);
|
pl011_create(0x1000a000, pic[13], serial_hds[1]);
|
||||||
sysbus_create_simple("pl011", 0x1000b000, pic[14]);
|
pl011_create(0x1000b000, pic[14], serial_hds[2]);
|
||||||
sysbus_create_simple("pl011", 0x1000c000, pic[15]);
|
pl011_create(0x1000c000, pic[15], serial_hds[3]);
|
||||||
|
|
||||||
/* DMA controller is optional, apparently. */
|
/* DMA controller is optional, apparently. */
|
||||||
sysbus_create_simple("pl081", 0x10030000, pic[24]);
|
sysbus_create_simple("pl081", 0x10030000, pic[24]);
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include "qemu/log.h"
|
#include "qemu/log.h"
|
||||||
#include "exec/address-spaces.h"
|
#include "exec/address-spaces.h"
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
|
#include "hw/char/pl011.h"
|
||||||
|
|
||||||
#define GPIO_A 0
|
#define GPIO_A 0
|
||||||
#define GPIO_B 1
|
#define GPIO_B 1
|
||||||
@@ -1303,8 +1304,9 @@ static void stellaris_init(const char *kernel_filename, const char *cpu_model,
|
|||||||
|
|
||||||
for (i = 0; i < 4; i++) {
|
for (i = 0; i < 4; i++) {
|
||||||
if (board->dc2 & (1 << i)) {
|
if (board->dc2 & (1 << i)) {
|
||||||
sysbus_create_simple("pl011_luminary", 0x4000c000 + i * 0x1000,
|
pl011_luminary_create(0x4000c000 + i * 0x1000,
|
||||||
qdev_get_gpio_in(nvic, uart_irq[i]));
|
qdev_get_gpio_in(nvic, uart_irq[i]),
|
||||||
|
serial_hds[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (board->dc2 & (1 << 4)) {
|
if (board->dc2 & (1 << 4)) {
|
||||||
|
|||||||
@@ -107,6 +107,7 @@ static void stm32f205_soc_realize(DeviceState *dev_soc, Error **errp)
|
|||||||
/* Attach UART (uses USART registers) and USART controllers */
|
/* Attach UART (uses USART registers) and USART controllers */
|
||||||
for (i = 0; i < STM_NUM_USARTS; i++) {
|
for (i = 0; i < STM_NUM_USARTS; i++) {
|
||||||
usartdev = DEVICE(&(s->usart[i]));
|
usartdev = DEVICE(&(s->usart[i]));
|
||||||
|
qdev_prop_set_chr(usartdev, "chardev", i < MAX_SERIAL_PORTS ? serial_hds[i] : NULL);
|
||||||
object_property_set_bool(OBJECT(&s->usart[i]), true, "realized", &err);
|
object_property_set_bool(OBJECT(&s->usart[i]), true, "realized", &err);
|
||||||
if (err != NULL) {
|
if (err != NULL) {
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include "exec/address-spaces.h"
|
#include "exec/address-spaces.h"
|
||||||
#include "hw/block/flash.h"
|
#include "hw/block/flash.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
|
#include "hw/char/pl011.h"
|
||||||
|
|
||||||
#define VERSATILE_FLASH_ADDR 0x34000000
|
#define VERSATILE_FLASH_ADDR 0x34000000
|
||||||
#define VERSATILE_FLASH_SIZE (64 * 1024 * 1024)
|
#define VERSATILE_FLASH_SIZE (64 * 1024 * 1024)
|
||||||
@@ -284,10 +285,10 @@ static void versatile_init(MachineState *machine, int board_id)
|
|||||||
n--;
|
n--;
|
||||||
}
|
}
|
||||||
|
|
||||||
sysbus_create_simple("pl011", 0x101f1000, pic[12]);
|
pl011_create(0x101f1000, pic[12], serial_hds[0]);
|
||||||
sysbus_create_simple("pl011", 0x101f2000, pic[13]);
|
pl011_create(0x101f2000, pic[13], serial_hds[1]);
|
||||||
sysbus_create_simple("pl011", 0x101f3000, pic[14]);
|
pl011_create(0x101f3000, pic[14], serial_hds[2]);
|
||||||
sysbus_create_simple("pl011", 0x10009000, sic[6]);
|
pl011_create(0x10009000, sic[6], serial_hds[3]);
|
||||||
|
|
||||||
sysbus_create_simple("pl080", 0x10130000, pic[17]);
|
sysbus_create_simple("pl080", 0x10130000, pic[17]);
|
||||||
sysbus_create_simple("sp804", 0x101e2000, pic[4]);
|
sysbus_create_simple("sp804", 0x101e2000, pic[4]);
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
#include "sysemu/device_tree.h"
|
#include "sysemu/device_tree.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include <libfdt.h>
|
#include <libfdt.h>
|
||||||
|
#include "hw/char/pl011.h"
|
||||||
|
|
||||||
#define VEXPRESS_BOARD_ID 0x8e0
|
#define VEXPRESS_BOARD_ID 0x8e0
|
||||||
#define VEXPRESS_FLASH_SIZE (64 * 1024 * 1024)
|
#define VEXPRESS_FLASH_SIZE (64 * 1024 * 1024)
|
||||||
@@ -631,10 +632,10 @@ static void vexpress_common_init(MachineState *machine)
|
|||||||
sysbus_create_simple("pl050_keyboard", map[VE_KMI0], pic[12]);
|
sysbus_create_simple("pl050_keyboard", map[VE_KMI0], pic[12]);
|
||||||
sysbus_create_simple("pl050_mouse", map[VE_KMI1], pic[13]);
|
sysbus_create_simple("pl050_mouse", map[VE_KMI1], pic[13]);
|
||||||
|
|
||||||
sysbus_create_simple("pl011", map[VE_UART0], pic[5]);
|
pl011_create(map[VE_UART0], pic[5], serial_hds[0]);
|
||||||
sysbus_create_simple("pl011", map[VE_UART1], pic[6]);
|
pl011_create(map[VE_UART1], pic[6], serial_hds[1]);
|
||||||
sysbus_create_simple("pl011", map[VE_UART2], pic[7]);
|
pl011_create(map[VE_UART2], pic[7], serial_hds[2]);
|
||||||
sysbus_create_simple("pl011", map[VE_UART3], pic[8]);
|
pl011_create(map[VE_UART3], pic[8], serial_hds[3]);
|
||||||
|
|
||||||
sysbus_create_simple("sp804", map[VE_TIMER01], pic[2]);
|
sysbus_create_simple("sp804", map[VE_TIMER01], pic[2]);
|
||||||
sysbus_create_simple("sp804", map[VE_TIMER23], pic[3]);
|
sysbus_create_simple("sp804", map[VE_TIMER23], pic[3]);
|
||||||
|
|||||||
@@ -231,7 +231,8 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
|
|||||||
aml_append(rbuf,
|
aml_append(rbuf,
|
||||||
aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
|
aml_qword_memory(AML_POS_DECODE, AML_MIN_FIXED, AML_MAX_FIXED,
|
||||||
AML_NON_CACHEABLE, AML_READ_WRITE, 0x0000,
|
AML_NON_CACHEABLE, AML_READ_WRITE, 0x0000,
|
||||||
base_mmio_high, base_mmio_high, 0x0000,
|
base_mmio_high,
|
||||||
|
base_mmio_high + size_mmio_high - 1, 0x0000,
|
||||||
size_mmio_high));
|
size_mmio_high));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,11 +354,14 @@ static void acpi_dsdt_add_power_button(Aml *scope)
|
|||||||
|
|
||||||
/* RSDP */
|
/* RSDP */
|
||||||
static GArray *
|
static GArray *
|
||||||
build_rsdp(GArray *rsdp_table, GArray *linker, unsigned rsdt)
|
build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt_tbl_offset)
|
||||||
{
|
{
|
||||||
AcpiRsdpDescriptor *rsdp = acpi_data_push(rsdp_table, sizeof *rsdp);
|
AcpiRsdpDescriptor *rsdp = acpi_data_push(rsdp_table, sizeof *rsdp);
|
||||||
|
unsigned rsdt_pa_size = sizeof(rsdp->rsdt_physical_address);
|
||||||
|
unsigned rsdt_pa_offset =
|
||||||
|
(char *)&rsdp->rsdt_physical_address - rsdp_table->data;
|
||||||
|
|
||||||
bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, 16,
|
bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, rsdp_table, 16,
|
||||||
true /* fseg memory */);
|
true /* fseg memory */);
|
||||||
|
|
||||||
memcpy(&rsdp->signature, "RSD PTR ", sizeof(rsdp->signature));
|
memcpy(&rsdp->signature, "RSD PTR ", sizeof(rsdp->signature));
|
||||||
@@ -365,24 +369,21 @@ build_rsdp(GArray *rsdp_table, GArray *linker, unsigned rsdt)
|
|||||||
rsdp->length = cpu_to_le32(sizeof(*rsdp));
|
rsdp->length = cpu_to_le32(sizeof(*rsdp));
|
||||||
rsdp->revision = 0x02;
|
rsdp->revision = 0x02;
|
||||||
|
|
||||||
/* Point to RSDT */
|
|
||||||
rsdp->rsdt_physical_address = cpu_to_le32(rsdt);
|
|
||||||
/* Address to be filled by Guest linker */
|
/* Address to be filled by Guest linker */
|
||||||
bios_linker_loader_add_pointer(linker, ACPI_BUILD_RSDP_FILE,
|
bios_linker_loader_add_pointer(linker,
|
||||||
ACPI_BUILD_TABLE_FILE,
|
ACPI_BUILD_RSDP_FILE, rsdt_pa_offset, rsdt_pa_size,
|
||||||
rsdp_table, &rsdp->rsdt_physical_address,
|
ACPI_BUILD_TABLE_FILE, rsdt_tbl_offset);
|
||||||
sizeof rsdp->rsdt_physical_address);
|
|
||||||
rsdp->checksum = 0;
|
|
||||||
/* Checksum to be filled by Guest linker */
|
/* Checksum to be filled by Guest linker */
|
||||||
bios_linker_loader_add_checksum(linker, ACPI_BUILD_RSDP_FILE,
|
bios_linker_loader_add_checksum(linker, ACPI_BUILD_RSDP_FILE,
|
||||||
rsdp_table, rsdp, sizeof *rsdp,
|
(char *)rsdp - rsdp_table->data, sizeof *rsdp,
|
||||||
&rsdp->checksum);
|
(char *)&rsdp->checksum - rsdp_table->data);
|
||||||
|
|
||||||
return rsdp_table;
|
return rsdp_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
build_spcr(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
|
build_spcr(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
|
||||||
{
|
{
|
||||||
AcpiSerialPortConsoleRedirection *spcr;
|
AcpiSerialPortConsoleRedirection *spcr;
|
||||||
const MemMapEntry *uart_memmap = &guest_info->memmap[VIRT_UART];
|
const MemMapEntry *uart_memmap = &guest_info->memmap[VIRT_UART];
|
||||||
@@ -415,7 +416,7 @@ build_spcr(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
build_srat(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
|
build_srat(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
|
||||||
{
|
{
|
||||||
AcpiSystemResourceAffinityTable *srat;
|
AcpiSystemResourceAffinityTable *srat;
|
||||||
AcpiSratProcessorGiccAffinity *core;
|
AcpiSratProcessorGiccAffinity *core;
|
||||||
@@ -455,13 +456,12 @@ build_srat(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
|
|||||||
mem_base += numa_info[i].node_mem;
|
mem_base += numa_info[i].node_mem;
|
||||||
}
|
}
|
||||||
|
|
||||||
build_header(linker, table_data,
|
build_header(linker, table_data, (void *)srat, "SRAT",
|
||||||
(void *)(table_data->data + srat_start), "SRAT",
|
|
||||||
table_data->len - srat_start, 3, NULL, NULL);
|
table_data->len - srat_start, 3, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
build_mcfg(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
|
build_mcfg(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
|
||||||
{
|
{
|
||||||
AcpiTableMcfg *mcfg;
|
AcpiTableMcfg *mcfg;
|
||||||
const MemMapEntry *memmap = guest_info->memmap;
|
const MemMapEntry *memmap = guest_info->memmap;
|
||||||
@@ -481,7 +481,7 @@ build_mcfg(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
|
|||||||
|
|
||||||
/* GTDT */
|
/* GTDT */
|
||||||
static void
|
static void
|
||||||
build_gtdt(GArray *table_data, GArray *linker)
|
build_gtdt(GArray *table_data, BIOSLinker *linker)
|
||||||
{
|
{
|
||||||
int gtdt_start = table_data->len;
|
int gtdt_start = table_data->len;
|
||||||
AcpiGenericTimerTable *gtdt;
|
AcpiGenericTimerTable *gtdt;
|
||||||
@@ -507,7 +507,7 @@ build_gtdt(GArray *table_data, GArray *linker)
|
|||||||
|
|
||||||
/* MADT */
|
/* MADT */
|
||||||
static void
|
static void
|
||||||
build_madt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
|
build_madt(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
|
||||||
{
|
{
|
||||||
int madt_start = table_data->len;
|
int madt_start = table_data->len;
|
||||||
const MemMapEntry *memmap = guest_info->memmap;
|
const MemMapEntry *memmap = guest_info->memmap;
|
||||||
@@ -566,9 +566,10 @@ build_madt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
|
|||||||
|
|
||||||
/* FADT */
|
/* FADT */
|
||||||
static void
|
static void
|
||||||
build_fadt(GArray *table_data, GArray *linker, unsigned dsdt)
|
build_fadt(GArray *table_data, BIOSLinker *linker, unsigned dsdt_tbl_offset)
|
||||||
{
|
{
|
||||||
AcpiFadtDescriptorRev5_1 *fadt = acpi_data_push(table_data, sizeof(*fadt));
|
AcpiFadtDescriptorRev5_1 *fadt = acpi_data_push(table_data, sizeof(*fadt));
|
||||||
|
unsigned dsdt_entry_offset = (char *)&fadt->dsdt - table_data->data;
|
||||||
|
|
||||||
/* Hardware Reduced = 1 and use PSCI 0.2+ and with HVC */
|
/* Hardware Reduced = 1 and use PSCI 0.2+ and with HVC */
|
||||||
fadt->flags = cpu_to_le32(1 << ACPI_FADT_F_HW_REDUCED_ACPI);
|
fadt->flags = cpu_to_le32(1 << ACPI_FADT_F_HW_REDUCED_ACPI);
|
||||||
@@ -578,12 +579,10 @@ build_fadt(GArray *table_data, GArray *linker, unsigned dsdt)
|
|||||||
/* ACPI v5.1 (fadt->revision.fadt->minor_revision) */
|
/* ACPI v5.1 (fadt->revision.fadt->minor_revision) */
|
||||||
fadt->minor_revision = 0x1;
|
fadt->minor_revision = 0x1;
|
||||||
|
|
||||||
fadt->dsdt = cpu_to_le32(dsdt);
|
|
||||||
/* DSDT address to be filled by Guest linker */
|
/* DSDT address to be filled by Guest linker */
|
||||||
bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
|
bios_linker_loader_add_pointer(linker,
|
||||||
ACPI_BUILD_TABLE_FILE,
|
ACPI_BUILD_TABLE_FILE, dsdt_entry_offset, sizeof(fadt->dsdt),
|
||||||
table_data, &fadt->dsdt,
|
ACPI_BUILD_TABLE_FILE, dsdt_tbl_offset);
|
||||||
sizeof fadt->dsdt);
|
|
||||||
|
|
||||||
build_header(linker, table_data,
|
build_header(linker, table_data,
|
||||||
(void *)fadt, "FACP", sizeof(*fadt), 5, NULL, NULL);
|
(void *)fadt, "FACP", sizeof(*fadt), 5, NULL, NULL);
|
||||||
@@ -591,7 +590,7 @@ build_fadt(GArray *table_data, GArray *linker, unsigned dsdt)
|
|||||||
|
|
||||||
/* DSDT */
|
/* DSDT */
|
||||||
static void
|
static void
|
||||||
build_dsdt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
|
build_dsdt(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
|
||||||
{
|
{
|
||||||
Aml *scope, *dsdt;
|
Aml *scope, *dsdt;
|
||||||
const MemMapEntry *memmap = guest_info->memmap;
|
const MemMapEntry *memmap = guest_info->memmap;
|
||||||
@@ -651,7 +650,8 @@ void virt_acpi_build(VirtGuestInfo *guest_info, AcpiBuildTables *tables)
|
|||||||
table_offsets = g_array_new(false, true /* clear */,
|
table_offsets = g_array_new(false, true /* clear */,
|
||||||
sizeof(uint32_t));
|
sizeof(uint32_t));
|
||||||
|
|
||||||
bios_linker_loader_alloc(tables->linker, ACPI_BUILD_TABLE_FILE,
|
bios_linker_loader_alloc(tables->linker,
|
||||||
|
ACPI_BUILD_TABLE_FILE, tables_blob,
|
||||||
64, false /* high memory */);
|
64, false /* high memory */);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -730,7 +730,7 @@ static void virt_acpi_build_update(void *build_opaque)
|
|||||||
|
|
||||||
acpi_ram_update(build_state->table_mr, tables.table_data);
|
acpi_ram_update(build_state->table_mr, tables.table_data);
|
||||||
acpi_ram_update(build_state->rsdp_mr, tables.rsdp);
|
acpi_ram_update(build_state->rsdp_mr, tables.rsdp);
|
||||||
acpi_ram_update(build_state->linker_mr, tables.linker);
|
acpi_ram_update(build_state->linker_mr, tables.linker->cmd_blob);
|
||||||
|
|
||||||
|
|
||||||
acpi_build_tables_cleanup(&tables, true);
|
acpi_build_tables_cleanup(&tables, true);
|
||||||
@@ -788,7 +788,8 @@ void virt_acpi_setup(VirtGuestInfo *guest_info)
|
|||||||
assert(build_state->table_mr != NULL);
|
assert(build_state->table_mr != NULL);
|
||||||
|
|
||||||
build_state->linker_mr =
|
build_state->linker_mr =
|
||||||
acpi_add_rom_blob(build_state, tables.linker, "etc/table-loader", 0);
|
acpi_add_rom_blob(build_state, tables.linker->cmd_blob,
|
||||||
|
"etc/table-loader", 0);
|
||||||
|
|
||||||
fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
|
fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
|
||||||
tables.tcpalog->data, acpi_data_len(tables.tcpalog));
|
tables.tcpalog->data, acpi_data_len(tables.tcpalog));
|
||||||
|
|||||||
@@ -525,7 +525,7 @@ static void create_gic(VirtBoardInfo *vbi, qemu_irq *pic, int type, bool secure)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic, int uart,
|
static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic, int uart,
|
||||||
MemoryRegion *mem)
|
MemoryRegion *mem, CharDriverState *chr)
|
||||||
{
|
{
|
||||||
char *nodename;
|
char *nodename;
|
||||||
hwaddr base = vbi->memmap[uart].base;
|
hwaddr base = vbi->memmap[uart].base;
|
||||||
@@ -536,6 +536,7 @@ static void create_uart(const VirtBoardInfo *vbi, qemu_irq *pic, int uart,
|
|||||||
DeviceState *dev = qdev_create(NULL, "pl011");
|
DeviceState *dev = qdev_create(NULL, "pl011");
|
||||||
SysBusDevice *s = SYS_BUS_DEVICE(dev);
|
SysBusDevice *s = SYS_BUS_DEVICE(dev);
|
||||||
|
|
||||||
|
qdev_prop_set_chr(dev, "chardev", chr);
|
||||||
qdev_init_nofail(dev);
|
qdev_init_nofail(dev);
|
||||||
memory_region_add_subregion(mem, base,
|
memory_region_add_subregion(mem, base,
|
||||||
sysbus_mmio_get_region(s, 0));
|
sysbus_mmio_get_region(s, 0));
|
||||||
@@ -1122,10 +1123,14 @@ static void machvirt_init(MachineState *machine)
|
|||||||
* KVM is not available yet
|
* KVM is not available yet
|
||||||
*/
|
*/
|
||||||
if (!gic_version) {
|
if (!gic_version) {
|
||||||
|
if (!kvm_enabled()) {
|
||||||
|
error_report("gic-version=host requires KVM");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
gic_version = kvm_arm_vgic_probe();
|
gic_version = kvm_arm_vgic_probe();
|
||||||
if (!gic_version) {
|
if (!gic_version) {
|
||||||
error_report("Unable to determine GIC version supported by host");
|
error_report("Unable to determine GIC version supported by host");
|
||||||
error_printf("KVM acceleration is probably not supported\n");
|
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1254,11 +1259,11 @@ static void machvirt_init(MachineState *machine)
|
|||||||
|
|
||||||
create_gic(vbi, pic, gic_version, vms->secure);
|
create_gic(vbi, pic, gic_version, vms->secure);
|
||||||
|
|
||||||
create_uart(vbi, pic, VIRT_UART, sysmem);
|
create_uart(vbi, pic, VIRT_UART, sysmem, serial_hds[0]);
|
||||||
|
|
||||||
if (vms->secure) {
|
if (vms->secure) {
|
||||||
create_secure_ram(vbi, secure_sysmem);
|
create_secure_ram(vbi, secure_sysmem);
|
||||||
create_uart(vbi, pic, VIRT_SECURE_UART, secure_sysmem);
|
create_uart(vbi, pic, VIRT_SECURE_UART, secure_sysmem, serial_hds[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
create_rtc(vbi, pic);
|
create_rtc(vbi, pic);
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
#include "hw/ssi/ssi.h"
|
#include "hw/ssi/ssi.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "hw/sd/sd.h"
|
#include "hw/sd/sd.h"
|
||||||
|
#include "hw/char/cadence_uart.h"
|
||||||
|
|
||||||
#define NUM_SPI_FLASHES 4
|
#define NUM_SPI_FLASHES 4
|
||||||
#define NUM_QSPI_FLASHES 2
|
#define NUM_QSPI_FLASHES 2
|
||||||
@@ -235,8 +236,8 @@ static void zynq_init(MachineState *machine)
|
|||||||
sysbus_create_simple("xlnx,ps7-usb", 0xE0002000, pic[53-IRQ_OFFSET]);
|
sysbus_create_simple("xlnx,ps7-usb", 0xE0002000, pic[53-IRQ_OFFSET]);
|
||||||
sysbus_create_simple("xlnx,ps7-usb", 0xE0003000, pic[76-IRQ_OFFSET]);
|
sysbus_create_simple("xlnx,ps7-usb", 0xE0003000, pic[76-IRQ_OFFSET]);
|
||||||
|
|
||||||
sysbus_create_simple("cadence_uart", 0xE0000000, pic[59-IRQ_OFFSET]);
|
cadence_uart_create(0xE0000000, pic[59 - IRQ_OFFSET], serial_hds[0]);
|
||||||
sysbus_create_simple("cadence_uart", 0xE0001000, pic[82-IRQ_OFFSET]);
|
cadence_uart_create(0xE0001000, pic[82 - IRQ_OFFSET], serial_hds[1]);
|
||||||
|
|
||||||
sysbus_create_varargs("cadence_ttc", 0xF8001000,
|
sysbus_create_varargs("cadence_ttc", 0xF8001000,
|
||||||
pic[42-IRQ_OFFSET], pic[43-IRQ_OFFSET], pic[44-IRQ_OFFSET], NULL);
|
pic[42-IRQ_OFFSET], pic[43-IRQ_OFFSET], pic[44-IRQ_OFFSET], NULL);
|
||||||
|
|||||||
@@ -114,3 +114,11 @@ static void xlnx_ep108_machine_init(MachineClass *mc)
|
|||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_MACHINE("xlnx-ep108", xlnx_ep108_machine_init)
|
DEFINE_MACHINE("xlnx-ep108", xlnx_ep108_machine_init)
|
||||||
|
|
||||||
|
static void xlnx_zcu102_machine_init(MachineClass *mc)
|
||||||
|
{
|
||||||
|
mc->desc = "Xilinx ZynqMP ZCU102 board";
|
||||||
|
mc->init = xlnx_ep108_init;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_MACHINE("xlnx-zcu102", xlnx_zcu102_machine_init)
|
||||||
|
|||||||
@@ -22,6 +22,8 @@
|
|||||||
#include "hw/arm/xlnx-zynqmp.h"
|
#include "hw/arm/xlnx-zynqmp.h"
|
||||||
#include "hw/intc/arm_gic_common.h"
|
#include "hw/intc/arm_gic_common.h"
|
||||||
#include "exec/address-spaces.h"
|
#include "exec/address-spaces.h"
|
||||||
|
#include "sysemu/kvm.h"
|
||||||
|
#include "kvm_arm.h"
|
||||||
|
|
||||||
#define GIC_NUM_SPI_INTR 160
|
#define GIC_NUM_SPI_INTR 160
|
||||||
|
|
||||||
@@ -83,6 +85,41 @@ static inline int arm_gic_ppi_index(int cpu_nr, int ppi_index)
|
|||||||
return GIC_NUM_SPI_INTR + cpu_nr * GIC_INTERNAL + ppi_index;
|
return GIC_NUM_SPI_INTR + cpu_nr * GIC_INTERNAL + ppi_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void xlnx_zynqmp_create_rpu(XlnxZynqMPState *s, const char *boot_cpu,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
Error *err = NULL;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < XLNX_ZYNQMP_NUM_RPU_CPUS; i++) {
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
object_initialize(&s->rpu_cpu[i], sizeof(s->rpu_cpu[i]),
|
||||||
|
"cortex-r5-" TYPE_ARM_CPU);
|
||||||
|
object_property_add_child(OBJECT(s), "rpu-cpu[*]",
|
||||||
|
OBJECT(&s->rpu_cpu[i]), &error_abort);
|
||||||
|
|
||||||
|
name = object_get_canonical_path_component(OBJECT(&s->rpu_cpu[i]));
|
||||||
|
if (strcmp(name, boot_cpu)) {
|
||||||
|
/* Secondary CPUs start in PSCI powered-down state */
|
||||||
|
object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true,
|
||||||
|
"start-powered-off", &error_abort);
|
||||||
|
} else {
|
||||||
|
s->boot_cpu_ptr = &s->rpu_cpu[i];
|
||||||
|
}
|
||||||
|
g_free(name);
|
||||||
|
|
||||||
|
object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "reset-hivecs",
|
||||||
|
&error_abort);
|
||||||
|
object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "realized",
|
||||||
|
&err);
|
||||||
|
if (err) {
|
||||||
|
error_propagate(errp, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void xlnx_zynqmp_init(Object *obj)
|
static void xlnx_zynqmp_init(Object *obj)
|
||||||
{
|
{
|
||||||
XlnxZynqMPState *s = XLNX_ZYNQMP(obj);
|
XlnxZynqMPState *s = XLNX_ZYNQMP(obj);
|
||||||
@@ -95,19 +132,12 @@ static void xlnx_zynqmp_init(Object *obj)
|
|||||||
&error_abort);
|
&error_abort);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < XLNX_ZYNQMP_NUM_RPU_CPUS; i++) {
|
|
||||||
object_initialize(&s->rpu_cpu[i], sizeof(s->rpu_cpu[i]),
|
|
||||||
"cortex-r5-" TYPE_ARM_CPU);
|
|
||||||
object_property_add_child(obj, "rpu-cpu[*]", OBJECT(&s->rpu_cpu[i]),
|
|
||||||
&error_abort);
|
|
||||||
}
|
|
||||||
|
|
||||||
object_property_add_link(obj, "ddr-ram", TYPE_MEMORY_REGION,
|
object_property_add_link(obj, "ddr-ram", TYPE_MEMORY_REGION,
|
||||||
(Object **)&s->ddr_ram,
|
(Object **)&s->ddr_ram,
|
||||||
qdev_prop_allow_set_link_before_realize,
|
qdev_prop_allow_set_link_before_realize,
|
||||||
OBJ_PROP_LINK_UNREF_ON_RELEASE, &error_abort);
|
OBJ_PROP_LINK_UNREF_ON_RELEASE, &error_abort);
|
||||||
|
|
||||||
object_initialize(&s->gic, sizeof(s->gic), TYPE_ARM_GIC);
|
object_initialize(&s->gic, sizeof(s->gic), gic_class_name());
|
||||||
qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default());
|
qdev_set_parent_bus(DEVICE(&s->gic), sysbus_get_default());
|
||||||
|
|
||||||
for (i = 0; i < XLNX_ZYNQMP_NUM_GEMS; i++) {
|
for (i = 0; i < XLNX_ZYNQMP_NUM_GEMS; i++) {
|
||||||
@@ -196,11 +226,42 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
|
|||||||
qdev_prop_set_uint32(DEVICE(&s->gic), "num-irq", GIC_NUM_SPI_INTR + 32);
|
qdev_prop_set_uint32(DEVICE(&s->gic), "num-irq", GIC_NUM_SPI_INTR + 32);
|
||||||
qdev_prop_set_uint32(DEVICE(&s->gic), "revision", 2);
|
qdev_prop_set_uint32(DEVICE(&s->gic), "revision", 2);
|
||||||
qdev_prop_set_uint32(DEVICE(&s->gic), "num-cpu", XLNX_ZYNQMP_NUM_APU_CPUS);
|
qdev_prop_set_uint32(DEVICE(&s->gic), "num-cpu", XLNX_ZYNQMP_NUM_APU_CPUS);
|
||||||
|
|
||||||
|
/* Realize APUs before realizing the GIC. KVM requires this. */
|
||||||
|
for (i = 0; i < XLNX_ZYNQMP_NUM_APU_CPUS; i++) {
|
||||||
|
char *name;
|
||||||
|
|
||||||
|
object_property_set_int(OBJECT(&s->apu_cpu[i]), QEMU_PSCI_CONDUIT_SMC,
|
||||||
|
"psci-conduit", &error_abort);
|
||||||
|
|
||||||
|
name = object_get_canonical_path_component(OBJECT(&s->apu_cpu[i]));
|
||||||
|
if (strcmp(name, boot_cpu)) {
|
||||||
|
/* Secondary CPUs start in PSCI powered-down state */
|
||||||
|
object_property_set_bool(OBJECT(&s->apu_cpu[i]), true,
|
||||||
|
"start-powered-off", &error_abort);
|
||||||
|
} else {
|
||||||
|
s->boot_cpu_ptr = &s->apu_cpu[i];
|
||||||
|
}
|
||||||
|
g_free(name);
|
||||||
|
|
||||||
|
object_property_set_bool(OBJECT(&s->apu_cpu[i]),
|
||||||
|
s->secure, "has_el3", NULL);
|
||||||
|
object_property_set_int(OBJECT(&s->apu_cpu[i]), GIC_BASE_ADDR,
|
||||||
|
"reset-cbar", &error_abort);
|
||||||
|
object_property_set_bool(OBJECT(&s->apu_cpu[i]), true, "realized",
|
||||||
|
&err);
|
||||||
|
if (err) {
|
||||||
|
error_propagate(errp, err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
|
object_property_set_bool(OBJECT(&s->gic), true, "realized", &err);
|
||||||
if (err) {
|
if (err) {
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(ARRAY_SIZE(xlnx_zynqmp_gic_regions) == XLNX_ZYNQMP_GIC_REGIONS);
|
assert(ARRAY_SIZE(xlnx_zynqmp_gic_regions) == XLNX_ZYNQMP_GIC_REGIONS);
|
||||||
for (i = 0; i < XLNX_ZYNQMP_GIC_REGIONS; i++) {
|
for (i = 0; i < XLNX_ZYNQMP_GIC_REGIONS; i++) {
|
||||||
SysBusDevice *gic = SYS_BUS_DEVICE(&s->gic);
|
SysBusDevice *gic = SYS_BUS_DEVICE(&s->gic);
|
||||||
@@ -223,29 +284,6 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
|
|||||||
|
|
||||||
for (i = 0; i < XLNX_ZYNQMP_NUM_APU_CPUS; i++) {
|
for (i = 0; i < XLNX_ZYNQMP_NUM_APU_CPUS; i++) {
|
||||||
qemu_irq irq;
|
qemu_irq irq;
|
||||||
char *name;
|
|
||||||
|
|
||||||
object_property_set_int(OBJECT(&s->apu_cpu[i]), QEMU_PSCI_CONDUIT_SMC,
|
|
||||||
"psci-conduit", &error_abort);
|
|
||||||
|
|
||||||
name = object_get_canonical_path_component(OBJECT(&s->apu_cpu[i]));
|
|
||||||
if (strcmp(name, boot_cpu)) {
|
|
||||||
/* Secondary CPUs start in PSCI powered-down state */
|
|
||||||
object_property_set_bool(OBJECT(&s->apu_cpu[i]), true,
|
|
||||||
"start-powered-off", &error_abort);
|
|
||||||
} else {
|
|
||||||
s->boot_cpu_ptr = &s->apu_cpu[i];
|
|
||||||
}
|
|
||||||
g_free(name);
|
|
||||||
|
|
||||||
object_property_set_int(OBJECT(&s->apu_cpu[i]), GIC_BASE_ADDR,
|
|
||||||
"reset-cbar", &error_abort);
|
|
||||||
object_property_set_bool(OBJECT(&s->apu_cpu[i]), true, "realized",
|
|
||||||
&err);
|
|
||||||
if (err) {
|
|
||||||
error_propagate(errp, err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i,
|
sysbus_connect_irq(SYS_BUS_DEVICE(&s->gic), i,
|
||||||
qdev_get_gpio_in(DEVICE(&s->apu_cpu[i]),
|
qdev_get_gpio_in(DEVICE(&s->apu_cpu[i]),
|
||||||
@@ -258,23 +296,8 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
|
|||||||
qdev_connect_gpio_out(DEVICE(&s->apu_cpu[i]), 1, irq);
|
qdev_connect_gpio_out(DEVICE(&s->apu_cpu[i]), 1, irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < XLNX_ZYNQMP_NUM_RPU_CPUS; i++) {
|
if (s->has_rpu) {
|
||||||
char *name;
|
xlnx_zynqmp_create_rpu(s, boot_cpu, &err);
|
||||||
|
|
||||||
name = object_get_canonical_path_component(OBJECT(&s->rpu_cpu[i]));
|
|
||||||
if (strcmp(name, boot_cpu)) {
|
|
||||||
/* Secondary CPUs start in PSCI powered-down state */
|
|
||||||
object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true,
|
|
||||||
"start-powered-off", &error_abort);
|
|
||||||
} else {
|
|
||||||
s->boot_cpu_ptr = &s->rpu_cpu[i];
|
|
||||||
}
|
|
||||||
g_free(name);
|
|
||||||
|
|
||||||
object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "reset-hivecs",
|
|
||||||
&error_abort);
|
|
||||||
object_property_set_bool(OBJECT(&s->rpu_cpu[i]), true, "realized",
|
|
||||||
&err);
|
|
||||||
if (err) {
|
if (err) {
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
return;
|
return;
|
||||||
@@ -308,6 +331,7 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < XLNX_ZYNQMP_NUM_UARTS; i++) {
|
for (i = 0; i < XLNX_ZYNQMP_NUM_UARTS; i++) {
|
||||||
|
qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", serial_hds[i]);
|
||||||
object_property_set_bool(OBJECT(&s->uart[i]), true, "realized", &err);
|
object_property_set_bool(OBJECT(&s->uart[i]), true, "realized", &err);
|
||||||
if (err) {
|
if (err) {
|
||||||
error_propagate(errp, err);
|
error_propagate(errp, err);
|
||||||
@@ -370,6 +394,8 @@ static void xlnx_zynqmp_realize(DeviceState *dev, Error **errp)
|
|||||||
|
|
||||||
static Property xlnx_zynqmp_props[] = {
|
static Property xlnx_zynqmp_props[] = {
|
||||||
DEFINE_PROP_STRING("boot-cpu", XlnxZynqMPState, boot_cpu),
|
DEFINE_PROP_STRING("boot-cpu", XlnxZynqMPState, boot_cpu),
|
||||||
|
DEFINE_PROP_BOOL("secure", XlnxZynqMPState, secure, false),
|
||||||
|
DEFINE_PROP_BOOL("has_rpu", XlnxZynqMPState, has_rpu, false),
|
||||||
DEFINE_PROP_END_OF_LIST()
|
DEFINE_PROP_END_OF_LIST()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -145,16 +145,15 @@ static const VMStateDescription vmstate_cs4231 = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static int cs4231_init1(SysBusDevice *dev)
|
static void cs4231_init(Object *obj)
|
||||||
{
|
{
|
||||||
CSState *s = CS4231(dev);
|
CSState *s = CS4231(obj);
|
||||||
|
SysBusDevice *dev = SYS_BUS_DEVICE(obj);
|
||||||
|
|
||||||
memory_region_init_io(&s->iomem, OBJECT(s), &cs_mem_ops, s, "cs4321",
|
memory_region_init_io(&s->iomem, obj, &cs_mem_ops, s, "cs4321",
|
||||||
CS_SIZE);
|
CS_SIZE);
|
||||||
sysbus_init_mmio(dev, &s->iomem);
|
sysbus_init_mmio(dev, &s->iomem);
|
||||||
sysbus_init_irq(dev, &s->irq);
|
sysbus_init_irq(dev, &s->irq);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static Property cs4231_properties[] = {
|
static Property cs4231_properties[] = {
|
||||||
@@ -164,9 +163,7 @@ static Property cs4231_properties[] = {
|
|||||||
static void cs4231_class_init(ObjectClass *klass, void *data)
|
static void cs4231_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
|
|
||||||
|
|
||||||
k->init = cs4231_init1;
|
|
||||||
dc->reset = cs_reset;
|
dc->reset = cs_reset;
|
||||||
dc->vmsd = &vmstate_cs4231;
|
dc->vmsd = &vmstate_cs4231;
|
||||||
dc->props = cs4231_properties;
|
dc->props = cs4231_properties;
|
||||||
@@ -176,6 +173,7 @@ static const TypeInfo cs4231_info = {
|
|||||||
.name = TYPE_CS4231,
|
.name = TYPE_CS4231,
|
||||||
.parent = TYPE_SYS_BUS_DEVICE,
|
.parent = TYPE_SYS_BUS_DEVICE,
|
||||||
.instance_size = sizeof(CSState),
|
.instance_size = sizeof(CSState),
|
||||||
|
.instance_init = cs4231_init,
|
||||||
.class_init = cs4231_class_init,
|
.class_init = cs4231_class_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ static void GUS_callback (void *opaque, int free)
|
|||||||
s->left = samples;
|
s->left = samples;
|
||||||
|
|
||||||
reset:
|
reset:
|
||||||
gus_irqgen (&s->emu, muldiv64 (net, 1000000, s->freq));
|
gus_irqgen (&s->emu, (uint64_t)net * 1000000 / s->freq);
|
||||||
}
|
}
|
||||||
|
|
||||||
int GUS_irqrequest (GUSEmuState *emu, int hwirq, int n)
|
int GUS_irqrequest (GUSEmuState *emu, int hwirq, int n)
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include "intel-hda.h"
|
#include "intel-hda.h"
|
||||||
#include "intel-hda-defs.h"
|
#include "intel-hda-defs.h"
|
||||||
#include "sysemu/dma.h"
|
#include "sysemu/dma.h"
|
||||||
|
#include "qapi/error.h"
|
||||||
|
|
||||||
/* --------------------------------------------------------------------- */
|
/* --------------------------------------------------------------------- */
|
||||||
/* hda bus */
|
/* hda bus */
|
||||||
@@ -50,25 +51,28 @@ void hda_codec_bus_init(DeviceState *dev, HDACodecBus *bus, size_t bus_size,
|
|||||||
bus->xfer = xfer;
|
bus->xfer = xfer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hda_codec_dev_init(DeviceState *qdev)
|
static void hda_codec_dev_realize(DeviceState *qdev, Error **errp)
|
||||||
{
|
{
|
||||||
HDACodecBus *bus = DO_UPCAST(HDACodecBus, qbus, qdev->parent_bus);
|
HDACodecBus *bus = HDA_BUS(qdev->parent_bus);
|
||||||
HDACodecDevice *dev = DO_UPCAST(HDACodecDevice, qdev, qdev);
|
HDACodecDevice *dev = HDA_CODEC_DEVICE(qdev);
|
||||||
HDACodecDeviceClass *cdc = HDA_CODEC_DEVICE_GET_CLASS(dev);
|
HDACodecDeviceClass *cdc = HDA_CODEC_DEVICE_GET_CLASS(dev);
|
||||||
|
|
||||||
if (dev->cad == -1) {
|
if (dev->cad == -1) {
|
||||||
dev->cad = bus->next_cad;
|
dev->cad = bus->next_cad;
|
||||||
}
|
}
|
||||||
if (dev->cad >= 15) {
|
if (dev->cad >= 15) {
|
||||||
return -1;
|
error_setg(errp, "HDA audio codec address is full");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
bus->next_cad = dev->cad + 1;
|
bus->next_cad = dev->cad + 1;
|
||||||
return cdc->init(dev);
|
if (cdc->init(dev) != 0) {
|
||||||
|
error_setg(errp, "HDA audio init failed");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hda_codec_dev_exit(DeviceState *qdev)
|
static int hda_codec_dev_exit(DeviceState *qdev)
|
||||||
{
|
{
|
||||||
HDACodecDevice *dev = DO_UPCAST(HDACodecDevice, qdev, qdev);
|
HDACodecDevice *dev = HDA_CODEC_DEVICE(qdev);
|
||||||
HDACodecDeviceClass *cdc = HDA_CODEC_DEVICE_GET_CLASS(dev);
|
HDACodecDeviceClass *cdc = HDA_CODEC_DEVICE_GET_CLASS(dev);
|
||||||
|
|
||||||
if (cdc->exit) {
|
if (cdc->exit) {
|
||||||
@@ -84,7 +88,7 @@ HDACodecDevice *hda_codec_find(HDACodecBus *bus, uint32_t cad)
|
|||||||
|
|
||||||
QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) {
|
QTAILQ_FOREACH(kid, &bus->qbus.children, sibling) {
|
||||||
DeviceState *qdev = kid->child;
|
DeviceState *qdev = kid->child;
|
||||||
cdev = DO_UPCAST(HDACodecDevice, qdev, qdev);
|
cdev = HDA_CODEC_DEVICE(qdev);
|
||||||
if (cdev->cad == cad) {
|
if (cdev->cad == cad) {
|
||||||
return cdev;
|
return cdev;
|
||||||
}
|
}
|
||||||
@@ -94,14 +98,14 @@ HDACodecDevice *hda_codec_find(HDACodecBus *bus, uint32_t cad)
|
|||||||
|
|
||||||
void hda_codec_response(HDACodecDevice *dev, bool solicited, uint32_t response)
|
void hda_codec_response(HDACodecDevice *dev, bool solicited, uint32_t response)
|
||||||
{
|
{
|
||||||
HDACodecBus *bus = DO_UPCAST(HDACodecBus, qbus, dev->qdev.parent_bus);
|
HDACodecBus *bus = HDA_BUS(dev->qdev.parent_bus);
|
||||||
bus->response(dev, solicited, response);
|
bus->response(dev, solicited, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hda_codec_xfer(HDACodecDevice *dev, uint32_t stnr, bool output,
|
bool hda_codec_xfer(HDACodecDevice *dev, uint32_t stnr, bool output,
|
||||||
uint8_t *buf, uint32_t len)
|
uint8_t *buf, uint32_t len)
|
||||||
{
|
{
|
||||||
HDACodecBus *bus = DO_UPCAST(HDACodecBus, qbus, dev->qdev.parent_bus);
|
HDACodecBus *bus = HDA_BUS(dev->qdev.parent_bus);
|
||||||
return bus->xfer(dev, stnr, output, buf, len);
|
return bus->xfer(dev, stnr, output, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,7 +341,7 @@ static void intel_hda_corb_run(IntelHDAState *d)
|
|||||||
|
|
||||||
static void intel_hda_response(HDACodecDevice *dev, bool solicited, uint32_t response)
|
static void intel_hda_response(HDACodecDevice *dev, bool solicited, uint32_t response)
|
||||||
{
|
{
|
||||||
HDACodecBus *bus = DO_UPCAST(HDACodecBus, qbus, dev->qdev.parent_bus);
|
HDACodecBus *bus = HDA_BUS(dev->qdev.parent_bus);
|
||||||
IntelHDAState *d = container_of(bus, IntelHDAState, codecs);
|
IntelHDAState *d = container_of(bus, IntelHDAState, codecs);
|
||||||
hwaddr addr;
|
hwaddr addr;
|
||||||
uint32_t wp, ex;
|
uint32_t wp, ex;
|
||||||
@@ -386,7 +390,7 @@ static void intel_hda_response(HDACodecDevice *dev, bool solicited, uint32_t res
|
|||||||
static bool intel_hda_xfer(HDACodecDevice *dev, uint32_t stnr, bool output,
|
static bool intel_hda_xfer(HDACodecDevice *dev, uint32_t stnr, bool output,
|
||||||
uint8_t *buf, uint32_t len)
|
uint8_t *buf, uint32_t len)
|
||||||
{
|
{
|
||||||
HDACodecBus *bus = DO_UPCAST(HDACodecBus, qbus, dev->qdev.parent_bus);
|
HDACodecBus *bus = HDA_BUS(dev->qdev.parent_bus);
|
||||||
IntelHDAState *d = container_of(bus, IntelHDAState, codecs);
|
IntelHDAState *d = container_of(bus, IntelHDAState, codecs);
|
||||||
hwaddr addr;
|
hwaddr addr;
|
||||||
uint32_t s, copy, left;
|
uint32_t s, copy, left;
|
||||||
@@ -493,7 +497,7 @@ static void intel_hda_notify_codecs(IntelHDAState *d, uint32_t stream, bool runn
|
|||||||
DeviceState *qdev = kid->child;
|
DeviceState *qdev = kid->child;
|
||||||
HDACodecDeviceClass *cdc;
|
HDACodecDeviceClass *cdc;
|
||||||
|
|
||||||
cdev = DO_UPCAST(HDACodecDevice, qdev, qdev);
|
cdev = HDA_CODEC_DEVICE(qdev);
|
||||||
cdc = HDA_CODEC_DEVICE_GET_CLASS(cdev);
|
cdc = HDA_CODEC_DEVICE_GET_CLASS(cdev);
|
||||||
if (cdc->stream) {
|
if (cdc->stream) {
|
||||||
cdc->stream(cdev, stream, running, output);
|
cdc->stream(cdev, stream, running, output);
|
||||||
@@ -1120,7 +1124,7 @@ static void intel_hda_reset(DeviceState *dev)
|
|||||||
/* reset codecs */
|
/* reset codecs */
|
||||||
QTAILQ_FOREACH(kid, &d->codecs.qbus.children, sibling) {
|
QTAILQ_FOREACH(kid, &d->codecs.qbus.children, sibling) {
|
||||||
DeviceState *qdev = kid->child;
|
DeviceState *qdev = kid->child;
|
||||||
cdev = DO_UPCAST(HDACodecDevice, qdev, qdev);
|
cdev = HDA_CODEC_DEVICE(qdev);
|
||||||
device_reset(DEVICE(cdev));
|
device_reset(DEVICE(cdev));
|
||||||
d->state_sts |= (1 << cdev->cad);
|
d->state_sts |= (1 << cdev->cad);
|
||||||
}
|
}
|
||||||
@@ -1298,7 +1302,7 @@ static const TypeInfo intel_hda_info_ich9 = {
|
|||||||
static void hda_codec_device_class_init(ObjectClass *klass, void *data)
|
static void hda_codec_device_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *k = DEVICE_CLASS(klass);
|
DeviceClass *k = DEVICE_CLASS(klass);
|
||||||
k->init = hda_codec_dev_init;
|
k->realize = hda_codec_dev_realize;
|
||||||
k->exit = hda_codec_dev_exit;
|
k->exit = hda_codec_dev_exit;
|
||||||
set_bit(DEVICE_CATEGORY_SOUND, k->categories);
|
set_bit(DEVICE_CATEGORY_SOUND, k->categories);
|
||||||
k->bus_type = TYPE_HDA_BUS;
|
k->bus_type = TYPE_HDA_BUS;
|
||||||
|
|||||||
@@ -284,16 +284,26 @@ static int ac97_post_load(void *opaque, int version_id)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int milkymist_ac97_init(SysBusDevice *dev)
|
static void milkymist_ac97_init(Object *obj)
|
||||||
{
|
{
|
||||||
MilkymistAC97State *s = MILKYMIST_AC97(dev);
|
MilkymistAC97State *s = MILKYMIST_AC97(obj);
|
||||||
|
SysBusDevice *dev = SYS_BUS_DEVICE(obj);
|
||||||
|
|
||||||
struct audsettings as;
|
|
||||||
sysbus_init_irq(dev, &s->crrequest_irq);
|
sysbus_init_irq(dev, &s->crrequest_irq);
|
||||||
sysbus_init_irq(dev, &s->crreply_irq);
|
sysbus_init_irq(dev, &s->crreply_irq);
|
||||||
sysbus_init_irq(dev, &s->dmar_irq);
|
sysbus_init_irq(dev, &s->dmar_irq);
|
||||||
sysbus_init_irq(dev, &s->dmaw_irq);
|
sysbus_init_irq(dev, &s->dmaw_irq);
|
||||||
|
|
||||||
|
memory_region_init_io(&s->regs_region, obj, &ac97_mmio_ops, s,
|
||||||
|
"milkymist-ac97", R_MAX * 4);
|
||||||
|
sysbus_init_mmio(dev, &s->regs_region);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void milkymist_ac97_realize(DeviceState *dev, Error **errp)
|
||||||
|
{
|
||||||
|
MilkymistAC97State *s = MILKYMIST_AC97(dev);
|
||||||
|
struct audsettings as;
|
||||||
|
|
||||||
AUD_register_card("Milkymist AC'97", &s->card);
|
AUD_register_card("Milkymist AC'97", &s->card);
|
||||||
|
|
||||||
as.freq = 48000;
|
as.freq = 48000;
|
||||||
@@ -305,12 +315,6 @@ static int milkymist_ac97_init(SysBusDevice *dev)
|
|||||||
"mm_ac97.in", s, ac97_in_cb, &as);
|
"mm_ac97.in", s, ac97_in_cb, &as);
|
||||||
s->voice_out = AUD_open_out(&s->card, s->voice_out,
|
s->voice_out = AUD_open_out(&s->card, s->voice_out,
|
||||||
"mm_ac97.out", s, ac97_out_cb, &as);
|
"mm_ac97.out", s, ac97_out_cb, &as);
|
||||||
|
|
||||||
memory_region_init_io(&s->regs_region, OBJECT(s), &ac97_mmio_ops, s,
|
|
||||||
"milkymist-ac97", R_MAX * 4);
|
|
||||||
sysbus_init_mmio(dev, &s->regs_region);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const VMStateDescription vmstate_milkymist_ac97 = {
|
static const VMStateDescription vmstate_milkymist_ac97 = {
|
||||||
@@ -327,9 +331,8 @@ static const VMStateDescription vmstate_milkymist_ac97 = {
|
|||||||
static void milkymist_ac97_class_init(ObjectClass *klass, void *data)
|
static void milkymist_ac97_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
|
|
||||||
|
|
||||||
k->init = milkymist_ac97_init;
|
dc->realize = milkymist_ac97_realize;
|
||||||
dc->reset = milkymist_ac97_reset;
|
dc->reset = milkymist_ac97_reset;
|
||||||
dc->vmsd = &vmstate_milkymist_ac97;
|
dc->vmsd = &vmstate_milkymist_ac97;
|
||||||
}
|
}
|
||||||
@@ -338,6 +341,7 @@ static const TypeInfo milkymist_ac97_info = {
|
|||||||
.name = TYPE_MILKYMIST_AC97,
|
.name = TYPE_MILKYMIST_AC97,
|
||||||
.parent = TYPE_SYS_BUS_DEVICE,
|
.parent = TYPE_SYS_BUS_DEVICE,
|
||||||
.instance_size = sizeof(MilkymistAC97State),
|
.instance_size = sizeof(MilkymistAC97State),
|
||||||
|
.instance_init = milkymist_ac97_init,
|
||||||
.class_init = milkymist_ac97_class_init,
|
.class_init = milkymist_ac97_class_init,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@
|
|||||||
#define PCSPK_BUF_LEN 1792
|
#define PCSPK_BUF_LEN 1792
|
||||||
#define PCSPK_SAMPLE_RATE 32000
|
#define PCSPK_SAMPLE_RATE 32000
|
||||||
#define PCSPK_MAX_FREQ (PCSPK_SAMPLE_RATE >> 1)
|
#define PCSPK_MAX_FREQ (PCSPK_SAMPLE_RATE >> 1)
|
||||||
#define PCSPK_MIN_COUNT ((PIT_FREQ + PCSPK_MAX_FREQ - 1) / PCSPK_MAX_FREQ)
|
#define PCSPK_MIN_COUNT DIV_ROUND_UP(PIT_FREQ, PCSPK_MAX_FREQ)
|
||||||
|
|
||||||
#define PC_SPEAKER(obj) OBJECT_CHECK(PCSpkState, (obj), TYPE_PC_SPEAKER)
|
#define PC_SPEAKER(obj) OBJECT_CHECK(PCSpkState, (obj), TYPE_PC_SPEAKER)
|
||||||
|
|
||||||
|
|||||||
@@ -37,8 +37,6 @@ struct VirtIOBlockDataPlane {
|
|||||||
EventNotifier *guest_notifier; /* irq */
|
EventNotifier *guest_notifier; /* irq */
|
||||||
QEMUBH *bh; /* bh for guest notification */
|
QEMUBH *bh; /* bh for guest notification */
|
||||||
|
|
||||||
Notifier insert_notifier, remove_notifier;
|
|
||||||
|
|
||||||
/* Note that these EventNotifiers are assigned by value. This is
|
/* Note that these EventNotifiers are assigned by value. This is
|
||||||
* fine as long as you do not call event_notifier_cleanup on them
|
* fine as long as you do not call event_notifier_cleanup on them
|
||||||
* (because you don't own the file descriptor or handle; you just
|
* (because you don't own the file descriptor or handle; you just
|
||||||
@@ -46,9 +44,6 @@ struct VirtIOBlockDataPlane {
|
|||||||
*/
|
*/
|
||||||
IOThread *iothread;
|
IOThread *iothread;
|
||||||
AioContext *ctx;
|
AioContext *ctx;
|
||||||
|
|
||||||
/* Operation blocker on BDS */
|
|
||||||
Error *blocker;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Raise an interrupt to signal guest, if necessary */
|
/* Raise an interrupt to signal guest, if necessary */
|
||||||
@@ -68,54 +63,6 @@ static void notify_guest_bh(void *opaque)
|
|||||||
event_notifier_set(s->guest_notifier);
|
event_notifier_set(s->guest_notifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void data_plane_set_up_op_blockers(VirtIOBlockDataPlane *s)
|
|
||||||
{
|
|
||||||
assert(!s->blocker);
|
|
||||||
error_setg(&s->blocker, "block device is in use by data plane");
|
|
||||||
blk_op_block_all(s->conf->conf.blk, s->blocker);
|
|
||||||
blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_RESIZE, s->blocker);
|
|
||||||
blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_DRIVE_DEL, s->blocker);
|
|
||||||
blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_BACKUP_SOURCE, s->blocker);
|
|
||||||
blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_CHANGE, s->blocker);
|
|
||||||
blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_COMMIT_SOURCE, s->blocker);
|
|
||||||
blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_COMMIT_TARGET, s->blocker);
|
|
||||||
blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_EJECT, s->blocker);
|
|
||||||
blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT,
|
|
||||||
s->blocker);
|
|
||||||
blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT,
|
|
||||||
s->blocker);
|
|
||||||
blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT_DELETE,
|
|
||||||
s->blocker);
|
|
||||||
blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_MIRROR_SOURCE, s->blocker);
|
|
||||||
blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_STREAM, s->blocker);
|
|
||||||
blk_op_unblock(s->conf->conf.blk, BLOCK_OP_TYPE_REPLACE, s->blocker);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void data_plane_remove_op_blockers(VirtIOBlockDataPlane *s)
|
|
||||||
{
|
|
||||||
if (s->blocker) {
|
|
||||||
blk_op_unblock_all(s->conf->conf.blk, s->blocker);
|
|
||||||
error_free(s->blocker);
|
|
||||||
s->blocker = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void data_plane_blk_insert_notifier(Notifier *n, void *data)
|
|
||||||
{
|
|
||||||
VirtIOBlockDataPlane *s = container_of(n, VirtIOBlockDataPlane,
|
|
||||||
insert_notifier);
|
|
||||||
assert(s->conf->conf.blk == data);
|
|
||||||
data_plane_set_up_op_blockers(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void data_plane_blk_remove_notifier(Notifier *n, void *data)
|
|
||||||
{
|
|
||||||
VirtIOBlockDataPlane *s = container_of(n, VirtIOBlockDataPlane,
|
|
||||||
remove_notifier);
|
|
||||||
assert(s->conf->conf.blk == data);
|
|
||||||
data_plane_remove_op_blockers(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Context: QEMU global mutex held */
|
/* Context: QEMU global mutex held */
|
||||||
void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
|
void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
|
||||||
VirtIOBlockDataPlane **dataplane,
|
VirtIOBlockDataPlane **dataplane,
|
||||||
@@ -158,13 +105,6 @@ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf,
|
|||||||
s->ctx = iothread_get_aio_context(s->iothread);
|
s->ctx = iothread_get_aio_context(s->iothread);
|
||||||
s->bh = aio_bh_new(s->ctx, notify_guest_bh, s);
|
s->bh = aio_bh_new(s->ctx, notify_guest_bh, s);
|
||||||
|
|
||||||
s->insert_notifier.notify = data_plane_blk_insert_notifier;
|
|
||||||
s->remove_notifier.notify = data_plane_blk_remove_notifier;
|
|
||||||
blk_add_insert_bs_notifier(conf->conf.blk, &s->insert_notifier);
|
|
||||||
blk_add_remove_bs_notifier(conf->conf.blk, &s->remove_notifier);
|
|
||||||
|
|
||||||
data_plane_set_up_op_blockers(s);
|
|
||||||
|
|
||||||
*dataplane = s;
|
*dataplane = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,9 +116,6 @@ void virtio_blk_data_plane_destroy(VirtIOBlockDataPlane *s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtio_blk_data_plane_stop(s);
|
virtio_blk_data_plane_stop(s);
|
||||||
data_plane_remove_op_blockers(s);
|
|
||||||
notifier_remove(&s->insert_notifier);
|
|
||||||
notifier_remove(&s->remove_notifier);
|
|
||||||
qemu_bh_delete(s->bh);
|
qemu_bh_delete(s->bh);
|
||||||
object_unref(OBJECT(s->iothread));
|
object_unref(OBJECT(s->iothread));
|
||||||
g_free(s);
|
g_free(s);
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ static void init_dev(tc58128_dev * dev, const char *filename)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Build first block with number of blocks */
|
/* Build first block with number of blocks */
|
||||||
blocks = (ret + 528 * 32 - 1) / (528 * 32);
|
blocks = DIV_ROUND_UP(ret, 528 * 32);
|
||||||
dev->flash_contents[0] = blocks & 0xff;
|
dev->flash_contents[0] = blocks & 0xff;
|
||||||
dev->flash_contents[1] = (blocks >> 8) & 0xff;
|
dev->flash_contents[1] = (blocks >> 8) & 0xff;
|
||||||
dev->flash_contents[2] = (blocks >> 16) & 0xff;
|
dev->flash_contents[2] = (blocks >> 16) & 0xff;
|
||||||
|
|||||||
@@ -468,9 +468,6 @@ static void cadence_uart_realize(DeviceState *dev, Error **errp)
|
|||||||
s->fifo_trigger_handle = timer_new_ns(QEMU_CLOCK_VIRTUAL,
|
s->fifo_trigger_handle = timer_new_ns(QEMU_CLOCK_VIRTUAL,
|
||||||
fifo_trigger_update, s);
|
fifo_trigger_update, s);
|
||||||
|
|
||||||
/* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */
|
|
||||||
s->chr = qemu_char_get_next_serial();
|
|
||||||
|
|
||||||
if (s->chr) {
|
if (s->chr) {
|
||||||
qemu_chr_add_handlers(s->chr, uart_can_receive, uart_receive,
|
qemu_chr_add_handlers(s->chr, uart_can_receive, uart_receive,
|
||||||
uart_event, s);
|
uart_event, s);
|
||||||
@@ -517,6 +514,11 @@ static const VMStateDescription vmstate_cadence_uart = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static Property cadence_uart_properties[] = {
|
||||||
|
DEFINE_PROP_CHR("chardev", CadenceUARTState, chr),
|
||||||
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
|
};
|
||||||
|
|
||||||
static void cadence_uart_class_init(ObjectClass *klass, void *data)
|
static void cadence_uart_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
@@ -524,9 +526,8 @@ static void cadence_uart_class_init(ObjectClass *klass, void *data)
|
|||||||
dc->realize = cadence_uart_realize;
|
dc->realize = cadence_uart_realize;
|
||||||
dc->vmsd = &vmstate_cadence_uart;
|
dc->vmsd = &vmstate_cadence_uart;
|
||||||
dc->reset = cadence_uart_reset;
|
dc->reset = cadence_uart_reset;
|
||||||
/* Reason: realize() method uses qemu_char_get_next_serial() */
|
dc->props = cadence_uart_properties;
|
||||||
dc->cannot_instantiate_with_device_add_yet = true;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
static const TypeInfo cadence_uart_info = {
|
static const TypeInfo cadence_uart_info = {
|
||||||
.name = TYPE_CADENCE_UART,
|
.name = TYPE_CADENCE_UART,
|
||||||
|
|||||||
@@ -145,8 +145,6 @@ static void digic_uart_realize(DeviceState *dev, Error **errp)
|
|||||||
{
|
{
|
||||||
DigicUartState *s = DIGIC_UART(dev);
|
DigicUartState *s = DIGIC_UART(dev);
|
||||||
|
|
||||||
/* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */
|
|
||||||
s->chr = qemu_char_get_next_serial();
|
|
||||||
if (s->chr) {
|
if (s->chr) {
|
||||||
qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
|
qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
|
||||||
}
|
}
|
||||||
@@ -172,6 +170,11 @@ static const VMStateDescription vmstate_digic_uart = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static Property digic_uart_properties[] = {
|
||||||
|
DEFINE_PROP_CHR("chardev", DigicUartState, chr),
|
||||||
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
|
};
|
||||||
|
|
||||||
static void digic_uart_class_init(ObjectClass *klass, void *data)
|
static void digic_uart_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
@@ -179,8 +182,7 @@ static void digic_uart_class_init(ObjectClass *klass, void *data)
|
|||||||
dc->realize = digic_uart_realize;
|
dc->realize = digic_uart_realize;
|
||||||
dc->reset = digic_uart_reset;
|
dc->reset = digic_uart_reset;
|
||||||
dc->vmsd = &vmstate_digic_uart;
|
dc->vmsd = &vmstate_digic_uart;
|
||||||
/* Reason: realize() method uses qemu_char_get_next_serial() */
|
dc->props = digic_uart_properties;
|
||||||
dc->cannot_instantiate_with_device_add_yet = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo digic_uart_info = {
|
static const TypeInfo digic_uart_info = {
|
||||||
|
|||||||
@@ -989,18 +989,13 @@ static void escc_init1(Object *obj)
|
|||||||
SysBusDevice *dev = SYS_BUS_DEVICE(obj);
|
SysBusDevice *dev = SYS_BUS_DEVICE(obj);
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
s->chn[0].disabled = s->disabled;
|
|
||||||
s->chn[1].disabled = s->disabled;
|
|
||||||
for (i = 0; i < 2; i++) {
|
for (i = 0; i < 2; i++) {
|
||||||
sysbus_init_irq(dev, &s->chn[i].irq);
|
sysbus_init_irq(dev, &s->chn[i].irq);
|
||||||
s->chn[i].chn = 1 - i;
|
s->chn[i].chn = 1 - i;
|
||||||
s->chn[i].clock = s->frequency / 2;
|
|
||||||
}
|
}
|
||||||
s->chn[0].otherchn = &s->chn[1];
|
s->chn[0].otherchn = &s->chn[1];
|
||||||
s->chn[1].otherchn = &s->chn[0];
|
s->chn[1].otherchn = &s->chn[0];
|
||||||
|
|
||||||
memory_region_init_io(&s->mmio, obj, &escc_mem_ops, s, "escc",
|
|
||||||
ESCC_SIZE << s->it_shift);
|
|
||||||
sysbus_init_mmio(dev, &s->mmio);
|
sysbus_init_mmio(dev, &s->mmio);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1009,8 +1004,15 @@ static void escc_realize(DeviceState *dev, Error **errp)
|
|||||||
ESCCState *s = ESCC(dev);
|
ESCCState *s = ESCC(dev);
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
|
s->chn[0].disabled = s->disabled;
|
||||||
|
s->chn[1].disabled = s->disabled;
|
||||||
|
|
||||||
|
memory_region_init_io(&s->mmio, OBJECT(dev), &escc_mem_ops, s, "escc",
|
||||||
|
ESCC_SIZE << s->it_shift);
|
||||||
|
|
||||||
for (i = 0; i < 2; i++) {
|
for (i = 0; i < 2; i++) {
|
||||||
if (s->chn[i].chr) {
|
if (s->chn[i].chr) {
|
||||||
|
s->chn[i].clock = s->frequency / 2;
|
||||||
qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
|
qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
|
||||||
serial_receive1, serial_event, &s->chn[i]);
|
serial_receive1, serial_event, &s->chn[i]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -274,6 +274,11 @@ static const VMStateDescription vmstate_pl011 = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static Property pl011_properties[] = {
|
||||||
|
DEFINE_PROP_CHR("chardev", PL011State, chr),
|
||||||
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
|
};
|
||||||
|
|
||||||
static void pl011_init(Object *obj)
|
static void pl011_init(Object *obj)
|
||||||
{
|
{
|
||||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||||
@@ -295,9 +300,6 @@ static void pl011_realize(DeviceState *dev, Error **errp)
|
|||||||
{
|
{
|
||||||
PL011State *s = PL011(dev);
|
PL011State *s = PL011(dev);
|
||||||
|
|
||||||
/* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */
|
|
||||||
s->chr = qemu_char_get_next_serial();
|
|
||||||
|
|
||||||
if (s->chr) {
|
if (s->chr) {
|
||||||
qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
|
qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
|
||||||
pl011_event, s);
|
pl011_event, s);
|
||||||
@@ -310,8 +312,7 @@ static void pl011_class_init(ObjectClass *oc, void *data)
|
|||||||
|
|
||||||
dc->realize = pl011_realize;
|
dc->realize = pl011_realize;
|
||||||
dc->vmsd = &vmstate_pl011;
|
dc->vmsd = &vmstate_pl011;
|
||||||
/* Reason: realize() method uses qemu_char_get_next_serial() */
|
dc->props = pl011_properties;
|
||||||
dc->cannot_instantiate_with_device_add_yet = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo pl011_arm_info = {
|
static const TypeInfo pl011_arm_info = {
|
||||||
|
|||||||
@@ -190,6 +190,11 @@ static const MemoryRegionOps stm32f2xx_usart_ops = {
|
|||||||
.endianness = DEVICE_NATIVE_ENDIAN,
|
.endianness = DEVICE_NATIVE_ENDIAN,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static Property stm32f2xx_usart_properties[] = {
|
||||||
|
DEFINE_PROP_CHR("chardev", STM32F2XXUsartState, chr),
|
||||||
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
|
};
|
||||||
|
|
||||||
static void stm32f2xx_usart_init(Object *obj)
|
static void stm32f2xx_usart_init(Object *obj)
|
||||||
{
|
{
|
||||||
STM32F2XXUsartState *s = STM32F2XX_USART(obj);
|
STM32F2XXUsartState *s = STM32F2XX_USART(obj);
|
||||||
@@ -199,9 +204,11 @@ static void stm32f2xx_usart_init(Object *obj)
|
|||||||
memory_region_init_io(&s->mmio, obj, &stm32f2xx_usart_ops, s,
|
memory_region_init_io(&s->mmio, obj, &stm32f2xx_usart_ops, s,
|
||||||
TYPE_STM32F2XX_USART, 0x2000);
|
TYPE_STM32F2XX_USART, 0x2000);
|
||||||
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
|
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
|
||||||
|
}
|
||||||
|
|
||||||
/* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */
|
static void stm32f2xx_usart_realize(DeviceState *dev, Error **errp)
|
||||||
s->chr = qemu_char_get_next_serial();
|
{
|
||||||
|
STM32F2XXUsartState *s = STM32F2XX_USART(dev);
|
||||||
|
|
||||||
if (s->chr) {
|
if (s->chr) {
|
||||||
qemu_chr_add_handlers(s->chr, stm32f2xx_usart_can_receive,
|
qemu_chr_add_handlers(s->chr, stm32f2xx_usart_can_receive,
|
||||||
@@ -214,8 +221,8 @@ static void stm32f2xx_usart_class_init(ObjectClass *klass, void *data)
|
|||||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||||
|
|
||||||
dc->reset = stm32f2xx_usart_reset;
|
dc->reset = stm32f2xx_usart_reset;
|
||||||
/* Reason: instance_init() method uses qemu_char_get_next_serial() */
|
dc->props = stm32f2xx_usart_properties;
|
||||||
dc->cannot_instantiate_with_device_add_yet = true;
|
dc->realize = stm32f2xx_usart_realize;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo stm32f2xx_usart_info = {
|
static const TypeInfo stm32f2xx_usart_info = {
|
||||||
|
|||||||
@@ -172,6 +172,11 @@ static const MemoryRegionOps uart_ops = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static Property xilinx_uartlite_properties[] = {
|
||||||
|
DEFINE_PROP_CHR("chardev", XilinxUARTLite, chr),
|
||||||
|
DEFINE_PROP_END_OF_LIST(),
|
||||||
|
};
|
||||||
|
|
||||||
static void uart_rx(void *opaque, const uint8_t *buf, int size)
|
static void uart_rx(void *opaque, const uint8_t *buf, int size)
|
||||||
{
|
{
|
||||||
XilinxUARTLite *s = opaque;
|
XilinxUARTLite *s = opaque;
|
||||||
@@ -206,8 +211,6 @@ static void xilinx_uartlite_realize(DeviceState *dev, Error **errp)
|
|||||||
{
|
{
|
||||||
XilinxUARTLite *s = XILINX_UARTLITE(dev);
|
XilinxUARTLite *s = XILINX_UARTLITE(dev);
|
||||||
|
|
||||||
/* FIXME use a qdev chardev prop instead of qemu_char_get_next_serial() */
|
|
||||||
s->chr = qemu_char_get_next_serial();
|
|
||||||
if (s->chr)
|
if (s->chr)
|
||||||
qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
|
qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
|
||||||
}
|
}
|
||||||
@@ -229,8 +232,7 @@ static void xilinx_uartlite_class_init(ObjectClass *klass, void *data)
|
|||||||
|
|
||||||
dc->reset = xilinx_uartlite_reset;
|
dc->reset = xilinx_uartlite_reset;
|
||||||
dc->realize = xilinx_uartlite_realize;
|
dc->realize = xilinx_uartlite_realize;
|
||||||
/* Reason: realize() method uses qemu_char_get_next_serial() */
|
dc->props = xilinx_uartlite_properties;
|
||||||
dc->cannot_instantiate_with_device_add_yet = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo xilinx_uartlite_info = {
|
static const TypeInfo xilinx_uartlite_info = {
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ static void ptimer_trigger(ptimer_state *s)
|
|||||||
|
|
||||||
static void ptimer_reload(ptimer_state *s)
|
static void ptimer_reload(ptimer_state *s)
|
||||||
{
|
{
|
||||||
|
uint32_t period_frac = s->period_frac;
|
||||||
|
uint64_t period = s->period;
|
||||||
|
|
||||||
if (s->delta == 0) {
|
if (s->delta == 0) {
|
||||||
ptimer_trigger(s);
|
ptimer_trigger(s);
|
||||||
s->delta = s->limit;
|
s->delta = s->limit;
|
||||||
@@ -45,10 +48,24 @@ static void ptimer_reload(ptimer_state *s)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Artificially limit timeout rate to something
|
||||||
|
* achievable under QEMU. Otherwise, QEMU spends all
|
||||||
|
* its time generating timer interrupts, and there
|
||||||
|
* is no forward progress.
|
||||||
|
* About ten microseconds is the fastest that really works
|
||||||
|
* on the current generation of host machines.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (s->enabled == 1 && (s->delta * period < 10000) && !use_icount) {
|
||||||
|
period = 10000 / s->delta;
|
||||||
|
period_frac = 0;
|
||||||
|
}
|
||||||
|
|
||||||
s->last_event = s->next_event;
|
s->last_event = s->next_event;
|
||||||
s->next_event = s->last_event + s->delta * s->period;
|
s->next_event = s->last_event + s->delta * period;
|
||||||
if (s->period_frac) {
|
if (period_frac) {
|
||||||
s->next_event += ((int64_t)s->period_frac * s->delta) >> 32;
|
s->next_event += ((int64_t)period_frac * s->delta) >> 32;
|
||||||
}
|
}
|
||||||
timer_mod(s->timer, s->next_event);
|
timer_mod(s->timer, s->next_event);
|
||||||
}
|
}
|
||||||
@@ -67,14 +84,16 @@ static void ptimer_tick(void *opaque)
|
|||||||
|
|
||||||
uint64_t ptimer_get_count(ptimer_state *s)
|
uint64_t ptimer_get_count(ptimer_state *s)
|
||||||
{
|
{
|
||||||
int64_t now;
|
|
||||||
uint64_t counter;
|
uint64_t counter;
|
||||||
|
|
||||||
if (s->enabled) {
|
if (s->enabled) {
|
||||||
now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||||
|
int64_t next = s->next_event;
|
||||||
|
bool expired = (now - next >= 0);
|
||||||
|
bool oneshot = (s->enabled == 2);
|
||||||
|
|
||||||
/* Figure out the current counter value. */
|
/* Figure out the current counter value. */
|
||||||
if (now - s->next_event > 0
|
if (s->period == 0 || (expired && (oneshot || use_icount))) {
|
||||||
|| s->period == 0) {
|
|
||||||
/* Prevent timer underflowing if it should already have
|
/* Prevent timer underflowing if it should already have
|
||||||
triggered. */
|
triggered. */
|
||||||
counter = 0;
|
counter = 0;
|
||||||
@@ -83,6 +102,13 @@ uint64_t ptimer_get_count(ptimer_state *s)
|
|||||||
uint64_t div;
|
uint64_t div;
|
||||||
int clz1, clz2;
|
int clz1, clz2;
|
||||||
int shift;
|
int shift;
|
||||||
|
uint32_t period_frac = s->period_frac;
|
||||||
|
uint64_t period = s->period;
|
||||||
|
|
||||||
|
if (!oneshot && (s->delta * period < 10000) && !use_icount) {
|
||||||
|
period = 10000 / s->delta;
|
||||||
|
period_frac = 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* We need to divide time by period, where time is stored in
|
/* We need to divide time by period, where time is stored in
|
||||||
rem (64-bit integer) and period is stored in period/period_frac
|
rem (64-bit integer) and period is stored in period/period_frac
|
||||||
@@ -94,8 +120,8 @@ uint64_t ptimer_get_count(ptimer_state *s)
|
|||||||
backwards.
|
backwards.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
rem = s->next_event - now;
|
rem = expired ? now - next : next - now;
|
||||||
div = s->period;
|
div = period;
|
||||||
|
|
||||||
clz1 = clz64(rem);
|
clz1 = clz64(rem);
|
||||||
clz2 = clz64(div);
|
clz2 = clz64(div);
|
||||||
@@ -104,16 +130,21 @@ uint64_t ptimer_get_count(ptimer_state *s)
|
|||||||
rem <<= shift;
|
rem <<= shift;
|
||||||
div <<= shift;
|
div <<= shift;
|
||||||
if (shift >= 32) {
|
if (shift >= 32) {
|
||||||
div |= ((uint64_t)s->period_frac << (shift - 32));
|
div |= ((uint64_t)period_frac << (shift - 32));
|
||||||
} else {
|
} else {
|
||||||
if (shift != 0)
|
if (shift != 0)
|
||||||
div |= (s->period_frac >> (32 - shift));
|
div |= (period_frac >> (32 - shift));
|
||||||
/* Look at remaining bits of period_frac and round div up if
|
/* Look at remaining bits of period_frac and round div up if
|
||||||
necessary. */
|
necessary. */
|
||||||
if ((uint32_t)(s->period_frac << shift))
|
if ((uint32_t)(period_frac << shift))
|
||||||
div += 1;
|
div += 1;
|
||||||
}
|
}
|
||||||
counter = rem / div;
|
counter = rem / div;
|
||||||
|
|
||||||
|
if (expired && counter != 0) {
|
||||||
|
/* Wrap around periodic counter. */
|
||||||
|
counter = s->limit - (counter - 1) % s->limit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
counter = s->delta;
|
counter = s->delta;
|
||||||
@@ -132,16 +163,17 @@ void ptimer_set_count(ptimer_state *s, uint64_t count)
|
|||||||
|
|
||||||
void ptimer_run(ptimer_state *s, int oneshot)
|
void ptimer_run(ptimer_state *s, int oneshot)
|
||||||
{
|
{
|
||||||
if (s->enabled) {
|
bool was_disabled = !s->enabled;
|
||||||
return;
|
|
||||||
}
|
if (was_disabled && s->period == 0) {
|
||||||
if (s->period == 0) {
|
|
||||||
fprintf(stderr, "Timer with period zero, disabling\n");
|
fprintf(stderr, "Timer with period zero, disabling\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
s->enabled = oneshot ? 2 : 1;
|
s->enabled = oneshot ? 2 : 1;
|
||||||
s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
if (was_disabled) {
|
||||||
ptimer_reload(s);
|
s->next_event = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
|
||||||
|
ptimer_reload(s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pause a timer. Note that this may cause it to "lose" time, even if it
|
/* Pause a timer. Note that this may cause it to "lose" time, even if it
|
||||||
@@ -159,6 +191,7 @@ void ptimer_stop(ptimer_state *s)
|
|||||||
/* Set counter increment interval in nanoseconds. */
|
/* Set counter increment interval in nanoseconds. */
|
||||||
void ptimer_set_period(ptimer_state *s, int64_t period)
|
void ptimer_set_period(ptimer_state *s, int64_t period)
|
||||||
{
|
{
|
||||||
|
s->delta = ptimer_get_count(s);
|
||||||
s->period = period;
|
s->period = period;
|
||||||
s->period_frac = 0;
|
s->period_frac = 0;
|
||||||
if (s->enabled) {
|
if (s->enabled) {
|
||||||
@@ -170,6 +203,7 @@ void ptimer_set_period(ptimer_state *s, int64_t period)
|
|||||||
/* Set counter frequency in Hz. */
|
/* Set counter frequency in Hz. */
|
||||||
void ptimer_set_freq(ptimer_state *s, uint32_t freq)
|
void ptimer_set_freq(ptimer_state *s, uint32_t freq)
|
||||||
{
|
{
|
||||||
|
s->delta = ptimer_get_count(s);
|
||||||
s->period = 1000000000ll / freq;
|
s->period = 1000000000ll / freq;
|
||||||
s->period_frac = (1000000000ll << 32) / freq;
|
s->period_frac = (1000000000ll << 32) / freq;
|
||||||
if (s->enabled) {
|
if (s->enabled) {
|
||||||
@@ -182,19 +216,6 @@ void ptimer_set_freq(ptimer_state *s, uint32_t freq)
|
|||||||
count = limit. */
|
count = limit. */
|
||||||
void ptimer_set_limit(ptimer_state *s, uint64_t limit, int reload)
|
void ptimer_set_limit(ptimer_state *s, uint64_t limit, int reload)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
* Artificially limit timeout rate to something
|
|
||||||
* achievable under QEMU. Otherwise, QEMU spends all
|
|
||||||
* its time generating timer interrupts, and there
|
|
||||||
* is no forward progress.
|
|
||||||
* About ten microseconds is the fastest that really works
|
|
||||||
* on the current generation of host machines.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (!use_icount && limit * s->period < 10000 && s->period) {
|
|
||||||
limit = 10000 / s->period;
|
|
||||||
}
|
|
||||||
|
|
||||||
s->limit = limit;
|
s->limit = limit;
|
||||||
if (reload)
|
if (reload)
|
||||||
s->delta = limit;
|
s->delta = limit;
|
||||||
@@ -204,6 +225,11 @@ void ptimer_set_limit(ptimer_state *s, uint64_t limit, int reload)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t ptimer_get_limit(ptimer_state *s)
|
||||||
|
{
|
||||||
|
return s->limit;
|
||||||
|
}
|
||||||
|
|
||||||
const VMStateDescription vmstate_ptimer = {
|
const VMStateDescription vmstate_ptimer = {
|
||||||
.name = "ptimer",
|
.name = "ptimer",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
|
|||||||
@@ -58,9 +58,6 @@ const char *qdev_fw_name(DeviceState *dev)
|
|||||||
return object_get_typename(OBJECT(dev));
|
return object_get_typename(OBJECT(dev));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
|
|
||||||
Error **errp);
|
|
||||||
|
|
||||||
static void bus_remove_child(BusState *bus, DeviceState *child)
|
static void bus_remove_child(BusState *bus, DeviceState *child)
|
||||||
{
|
{
|
||||||
BusChild *kid;
|
BusChild *kid;
|
||||||
@@ -733,13 +730,20 @@ static void qdev_get_legacy_property(Object *obj, Visitor *v,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @qdev_add_legacy_property - adds a legacy property
|
* qdev_property_add_legacy:
|
||||||
|
* @dev: Device to add the property to.
|
||||||
|
* @prop: The qdev property definition.
|
||||||
|
* @errp: location to store error information.
|
||||||
*
|
*
|
||||||
* Do not use this is new code! Properties added through this interface will
|
* Add a legacy QOM property to @dev for qdev property @prop.
|
||||||
* be given names and types in the "legacy" namespace.
|
* On error, store error in @errp.
|
||||||
*
|
*
|
||||||
* Legacy properties are string versions of other OOM properties. The format
|
* Legacy properties are string versions of QOM properties. The format of
|
||||||
* of the string depends on the property type.
|
* the string depends on the property type. Legacy properties are only
|
||||||
|
* needed for "info qtree".
|
||||||
|
*
|
||||||
|
* Do not use this is new code! QOM Properties added through this interface
|
||||||
|
* will be given names in the "legacy" namespace.
|
||||||
*/
|
*/
|
||||||
static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
|
static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
@@ -762,10 +766,14 @@ static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @qdev_property_add_static - add a @Property to a device.
|
* qdev_property_add_static:
|
||||||
|
* @dev: Device to add the property to.
|
||||||
|
* @prop: The qdev property definition.
|
||||||
|
* @errp: location to store error information.
|
||||||
*
|
*
|
||||||
* Static properties access data in a struct. The actual type of the
|
* Add a static QOM property to @dev for qdev property @prop.
|
||||||
* property and the field depends on the property type.
|
* On error, store error in @errp. Static properties access data in a struct.
|
||||||
|
* The type of the QOM property is derived from prop->info.
|
||||||
*/
|
*/
|
||||||
void qdev_property_add_static(DeviceState *dev, Property *prop,
|
void qdev_property_add_static(DeviceState *dev, Property *prop,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
|
|||||||
@@ -284,7 +284,7 @@ static void virgl_resource_attach_backing(VirtIOGPU *g,
|
|||||||
VIRTIO_GPU_FILL_CMD(att_rb);
|
VIRTIO_GPU_FILL_CMD(att_rb);
|
||||||
trace_virtio_gpu_cmd_res_back_attach(att_rb.resource_id);
|
trace_virtio_gpu_cmd_res_back_attach(att_rb.resource_id);
|
||||||
|
|
||||||
ret = virtio_gpu_create_mapping_iov(&att_rb, cmd, &res_iovs);
|
ret = virtio_gpu_create_mapping_iov(&att_rb, cmd, NULL, &res_iovs);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
|
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -22,6 +22,8 @@
|
|||||||
#include "qemu/log.h"
|
#include "qemu/log.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
|
|
||||||
|
#define VIRTIO_GPU_VM_VERSION 1
|
||||||
|
|
||||||
static struct virtio_gpu_simple_resource*
|
static struct virtio_gpu_simple_resource*
|
||||||
virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id);
|
virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id);
|
||||||
|
|
||||||
@@ -94,7 +96,7 @@ static void update_cursor_data_virgl(VirtIOGPU *g,
|
|||||||
static void update_cursor(VirtIOGPU *g, struct virtio_gpu_update_cursor *cursor)
|
static void update_cursor(VirtIOGPU *g, struct virtio_gpu_update_cursor *cursor)
|
||||||
{
|
{
|
||||||
struct virtio_gpu_scanout *s;
|
struct virtio_gpu_scanout *s;
|
||||||
bool move = cursor->hdr.type != VIRTIO_GPU_CMD_MOVE_CURSOR;
|
bool move = cursor->hdr.type == VIRTIO_GPU_CMD_MOVE_CURSOR;
|
||||||
|
|
||||||
if (cursor->pos.scanout_id >= g->conf.max_outputs) {
|
if (cursor->pos.scanout_id >= g->conf.max_outputs) {
|
||||||
return;
|
return;
|
||||||
@@ -107,7 +109,7 @@ static void update_cursor(VirtIOGPU *g, struct virtio_gpu_update_cursor *cursor)
|
|||||||
move ? "move" : "update",
|
move ? "move" : "update",
|
||||||
cursor->resource_id);
|
cursor->resource_id);
|
||||||
|
|
||||||
if (move) {
|
if (!move) {
|
||||||
if (!s->current_cursor) {
|
if (!s->current_cursor) {
|
||||||
s->current_cursor = cursor_alloc(64, 64);
|
s->current_cursor = cursor_alloc(64, 64);
|
||||||
}
|
}
|
||||||
@@ -120,6 +122,11 @@ static void update_cursor(VirtIOGPU *g, struct virtio_gpu_update_cursor *cursor)
|
|||||||
g, s, cursor->resource_id);
|
g, s, cursor->resource_id);
|
||||||
}
|
}
|
||||||
dpy_cursor_define(s->con, s->current_cursor);
|
dpy_cursor_define(s->con, s->current_cursor);
|
||||||
|
|
||||||
|
s->cursor = *cursor;
|
||||||
|
} else {
|
||||||
|
s->cursor.pos.x = cursor->pos.x;
|
||||||
|
s->cursor.pos.y = cursor->pos.y;
|
||||||
}
|
}
|
||||||
dpy_mouse_set(s->con, cursor->pos.x, cursor->pos.y,
|
dpy_mouse_set(s->con, cursor->pos.x, cursor->pos.y,
|
||||||
cursor->resource_id ? 1 : 0);
|
cursor->resource_id ? 1 : 0);
|
||||||
@@ -495,6 +502,11 @@ static void virtio_gpu_resource_flush(VirtIOGPU *g,
|
|||||||
pixman_region_fini(&flush_region);
|
pixman_region_fini(&flush_region);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void virtio_unref_resource(pixman_image_t *image, void *data)
|
||||||
|
{
|
||||||
|
pixman_image_unref(data);
|
||||||
|
}
|
||||||
|
|
||||||
static void virtio_gpu_set_scanout(VirtIOGPU *g,
|
static void virtio_gpu_set_scanout(VirtIOGPU *g,
|
||||||
struct virtio_gpu_ctrl_command *cmd)
|
struct virtio_gpu_ctrl_command *cmd)
|
||||||
{
|
{
|
||||||
@@ -571,8 +583,15 @@ static void virtio_gpu_set_scanout(VirtIOGPU *g,
|
|||||||
!= ((uint8_t *)pixman_image_get_data(res->image) + offset) ||
|
!= ((uint8_t *)pixman_image_get_data(res->image) + offset) ||
|
||||||
scanout->width != ss.r.width ||
|
scanout->width != ss.r.width ||
|
||||||
scanout->height != ss.r.height) {
|
scanout->height != ss.r.height) {
|
||||||
|
pixman_image_t *rect;
|
||||||
|
void *ptr = (uint8_t *)pixman_image_get_data(res->image) + offset;
|
||||||
|
rect = pixman_image_create_bits(format, ss.r.width, ss.r.height, ptr,
|
||||||
|
pixman_image_get_stride(res->image));
|
||||||
|
pixman_image_ref(res->image);
|
||||||
|
pixman_image_set_destroy_function(rect, virtio_unref_resource,
|
||||||
|
res->image);
|
||||||
/* realloc the surface ptr */
|
/* realloc the surface ptr */
|
||||||
scanout->ds = qemu_create_displaysurface_pixman(res->image);
|
scanout->ds = qemu_create_displaysurface_pixman(rect);
|
||||||
if (!scanout->ds) {
|
if (!scanout->ds) {
|
||||||
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
|
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
|
||||||
return;
|
return;
|
||||||
@@ -590,7 +609,7 @@ static void virtio_gpu_set_scanout(VirtIOGPU *g,
|
|||||||
|
|
||||||
int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab,
|
int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab,
|
||||||
struct virtio_gpu_ctrl_command *cmd,
|
struct virtio_gpu_ctrl_command *cmd,
|
||||||
struct iovec **iov)
|
uint64_t **addr, struct iovec **iov)
|
||||||
{
|
{
|
||||||
struct virtio_gpu_mem_entry *ents;
|
struct virtio_gpu_mem_entry *ents;
|
||||||
size_t esize, s;
|
size_t esize, s;
|
||||||
@@ -616,10 +635,16 @@ int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab,
|
|||||||
}
|
}
|
||||||
|
|
||||||
*iov = g_malloc0(sizeof(struct iovec) * ab->nr_entries);
|
*iov = g_malloc0(sizeof(struct iovec) * ab->nr_entries);
|
||||||
|
if (addr) {
|
||||||
|
*addr = g_malloc0(sizeof(uint64_t) * ab->nr_entries);
|
||||||
|
}
|
||||||
for (i = 0; i < ab->nr_entries; i++) {
|
for (i = 0; i < ab->nr_entries; i++) {
|
||||||
hwaddr len = ents[i].length;
|
hwaddr len = ents[i].length;
|
||||||
(*iov)[i].iov_len = ents[i].length;
|
(*iov)[i].iov_len = ents[i].length;
|
||||||
(*iov)[i].iov_base = cpu_physical_memory_map(ents[i].addr, &len, 1);
|
(*iov)[i].iov_base = cpu_physical_memory_map(ents[i].addr, &len, 1);
|
||||||
|
if (addr) {
|
||||||
|
(*addr)[i] = ents[i].addr;
|
||||||
|
}
|
||||||
if (!(*iov)[i].iov_base || len != ents[i].length) {
|
if (!(*iov)[i].iov_base || len != ents[i].length) {
|
||||||
qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map MMIO memory for"
|
qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to map MMIO memory for"
|
||||||
" resource %d element %d\n",
|
" resource %d element %d\n",
|
||||||
@@ -627,6 +652,10 @@ int virtio_gpu_create_mapping_iov(struct virtio_gpu_resource_attach_backing *ab,
|
|||||||
virtio_gpu_cleanup_mapping_iov(*iov, i);
|
virtio_gpu_cleanup_mapping_iov(*iov, i);
|
||||||
g_free(ents);
|
g_free(ents);
|
||||||
*iov = NULL;
|
*iov = NULL;
|
||||||
|
if (addr) {
|
||||||
|
g_free(*addr);
|
||||||
|
*addr = NULL;
|
||||||
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -650,6 +679,8 @@ static void virtio_gpu_cleanup_mapping(struct virtio_gpu_simple_resource *res)
|
|||||||
virtio_gpu_cleanup_mapping_iov(res->iov, res->iov_cnt);
|
virtio_gpu_cleanup_mapping_iov(res->iov, res->iov_cnt);
|
||||||
res->iov = NULL;
|
res->iov = NULL;
|
||||||
res->iov_cnt = 0;
|
res->iov_cnt = 0;
|
||||||
|
g_free(res->addrs);
|
||||||
|
res->addrs = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -671,7 +702,7 @@ virtio_gpu_resource_attach_backing(VirtIOGPU *g,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = virtio_gpu_create_mapping_iov(&ab, cmd, &res->iov);
|
ret = virtio_gpu_create_mapping_iov(&ab, cmd, &res->addrs, &res->iov);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
|
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
|
||||||
return;
|
return;
|
||||||
@@ -917,11 +948,163 @@ const GraphicHwOps virtio_gpu_ops = {
|
|||||||
.gl_block = virtio_gpu_gl_block,
|
.gl_block = virtio_gpu_gl_block,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const VMStateDescription vmstate_virtio_gpu_scanout = {
|
||||||
|
.name = "virtio-gpu-one-scanout",
|
||||||
|
.version_id = 1,
|
||||||
|
.fields = (VMStateField[]) {
|
||||||
|
VMSTATE_UINT32(resource_id, struct virtio_gpu_scanout),
|
||||||
|
VMSTATE_UINT32(width, struct virtio_gpu_scanout),
|
||||||
|
VMSTATE_UINT32(height, struct virtio_gpu_scanout),
|
||||||
|
VMSTATE_INT32(x, struct virtio_gpu_scanout),
|
||||||
|
VMSTATE_INT32(y, struct virtio_gpu_scanout),
|
||||||
|
VMSTATE_UINT32(cursor.resource_id, struct virtio_gpu_scanout),
|
||||||
|
VMSTATE_UINT32(cursor.hot_x, struct virtio_gpu_scanout),
|
||||||
|
VMSTATE_UINT32(cursor.hot_y, struct virtio_gpu_scanout),
|
||||||
|
VMSTATE_UINT32(cursor.pos.x, struct virtio_gpu_scanout),
|
||||||
|
VMSTATE_UINT32(cursor.pos.y, struct virtio_gpu_scanout),
|
||||||
|
VMSTATE_END_OF_LIST()
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const VMStateDescription vmstate_virtio_gpu_scanouts = {
|
||||||
|
.name = "virtio-gpu-scanouts",
|
||||||
|
.version_id = 1,
|
||||||
|
.fields = (VMStateField[]) {
|
||||||
|
VMSTATE_INT32(enable, struct VirtIOGPU),
|
||||||
|
VMSTATE_UINT32_EQUAL(conf.max_outputs, struct VirtIOGPU),
|
||||||
|
VMSTATE_STRUCT_VARRAY_UINT32(scanout, struct VirtIOGPU,
|
||||||
|
conf.max_outputs, 1,
|
||||||
|
vmstate_virtio_gpu_scanout,
|
||||||
|
struct virtio_gpu_scanout),
|
||||||
|
VMSTATE_END_OF_LIST()
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static const VMStateDescription vmstate_virtio_gpu_unmigratable = {
|
static const VMStateDescription vmstate_virtio_gpu_unmigratable = {
|
||||||
.name = "virtio-gpu",
|
.name = "virtio-gpu-with-virgl",
|
||||||
.unmigratable = 1,
|
.unmigratable = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void virtio_gpu_save(QEMUFile *f, void *opaque)
|
||||||
|
{
|
||||||
|
VirtIOGPU *g = opaque;
|
||||||
|
VirtIODevice *vdev = VIRTIO_DEVICE(g);
|
||||||
|
struct virtio_gpu_simple_resource *res;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
virtio_save(vdev, f);
|
||||||
|
|
||||||
|
/* in 2d mode we should never find unprocessed commands here */
|
||||||
|
assert(QTAILQ_EMPTY(&g->cmdq));
|
||||||
|
|
||||||
|
QTAILQ_FOREACH(res, &g->reslist, next) {
|
||||||
|
qemu_put_be32(f, res->resource_id);
|
||||||
|
qemu_put_be32(f, res->width);
|
||||||
|
qemu_put_be32(f, res->height);
|
||||||
|
qemu_put_be32(f, res->format);
|
||||||
|
qemu_put_be32(f, res->iov_cnt);
|
||||||
|
for (i = 0; i < res->iov_cnt; i++) {
|
||||||
|
qemu_put_be64(f, res->addrs[i]);
|
||||||
|
qemu_put_be32(f, res->iov[i].iov_len);
|
||||||
|
}
|
||||||
|
qemu_put_buffer(f, (void *)pixman_image_get_data(res->image),
|
||||||
|
pixman_image_get_stride(res->image) * res->height);
|
||||||
|
}
|
||||||
|
qemu_put_be32(f, 0); /* end of list */
|
||||||
|
|
||||||
|
vmstate_save_state(f, &vmstate_virtio_gpu_scanouts, g, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int virtio_gpu_load(QEMUFile *f, void *opaque, int version_id)
|
||||||
|
{
|
||||||
|
VirtIOGPU *g = opaque;
|
||||||
|
VirtIODevice *vdev = VIRTIO_DEVICE(g);
|
||||||
|
struct virtio_gpu_simple_resource *res;
|
||||||
|
struct virtio_gpu_scanout *scanout;
|
||||||
|
uint32_t resource_id, pformat;
|
||||||
|
int i, ret;
|
||||||
|
|
||||||
|
if (version_id != VIRTIO_GPU_VM_VERSION) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = virtio_load(vdev, f, version_id);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
resource_id = qemu_get_be32(f);
|
||||||
|
while (resource_id != 0) {
|
||||||
|
res = g_new0(struct virtio_gpu_simple_resource, 1);
|
||||||
|
res->resource_id = resource_id;
|
||||||
|
res->width = qemu_get_be32(f);
|
||||||
|
res->height = qemu_get_be32(f);
|
||||||
|
res->format = qemu_get_be32(f);
|
||||||
|
res->iov_cnt = qemu_get_be32(f);
|
||||||
|
|
||||||
|
/* allocate */
|
||||||
|
pformat = get_pixman_format(res->format);
|
||||||
|
if (!pformat) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
res->image = pixman_image_create_bits(pformat,
|
||||||
|
res->width, res->height,
|
||||||
|
NULL, 0);
|
||||||
|
if (!res->image) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
res->addrs = g_new(uint64_t, res->iov_cnt);
|
||||||
|
res->iov = g_new(struct iovec, res->iov_cnt);
|
||||||
|
|
||||||
|
/* read data */
|
||||||
|
for (i = 0; i < res->iov_cnt; i++) {
|
||||||
|
res->addrs[i] = qemu_get_be64(f);
|
||||||
|
res->iov[i].iov_len = qemu_get_be32(f);
|
||||||
|
}
|
||||||
|
qemu_get_buffer(f, (void *)pixman_image_get_data(res->image),
|
||||||
|
pixman_image_get_stride(res->image) * res->height);
|
||||||
|
|
||||||
|
/* restore mapping */
|
||||||
|
for (i = 0; i < res->iov_cnt; i++) {
|
||||||
|
hwaddr len = res->iov[i].iov_len;
|
||||||
|
res->iov[i].iov_base =
|
||||||
|
cpu_physical_memory_map(res->addrs[i], &len, 1);
|
||||||
|
if (!res->iov[i].iov_base || len != res->iov[i].iov_len) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QTAILQ_INSERT_HEAD(&g->reslist, res, next);
|
||||||
|
|
||||||
|
resource_id = qemu_get_be32(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* load & apply scanout state */
|
||||||
|
vmstate_load_state(f, &vmstate_virtio_gpu_scanouts, g, 1);
|
||||||
|
for (i = 0; i < g->conf.max_outputs; i++) {
|
||||||
|
scanout = &g->scanout[i];
|
||||||
|
if (!scanout->resource_id) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
res = virtio_gpu_find_resource(g, scanout->resource_id);
|
||||||
|
if (!res) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
scanout->ds = qemu_create_displaysurface_pixman(res->image);
|
||||||
|
if (!scanout->ds) {
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dpy_gfx_replace_surface(scanout->con, scanout->ds);
|
||||||
|
dpy_gfx_update(scanout->con, 0, 0, scanout->width, scanout->height);
|
||||||
|
update_cursor(g, &scanout->cursor);
|
||||||
|
res->scanout_bitmask |= (1 << i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
|
static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
|
||||||
{
|
{
|
||||||
VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
|
VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
|
||||||
@@ -979,7 +1162,12 @@ static void virtio_gpu_device_realize(DeviceState *qdev, Error **errp)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vmstate_register(qdev, -1, &vmstate_virtio_gpu_unmigratable, g);
|
if (virtio_gpu_virgl_enabled(g->conf)) {
|
||||||
|
vmstate_register(qdev, -1, &vmstate_virtio_gpu_unmigratable, g);
|
||||||
|
} else {
|
||||||
|
register_savevm(qdev, "virtio-gpu", -1, VIRTIO_GPU_VM_VERSION,
|
||||||
|
virtio_gpu_save, virtio_gpu_load, g);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void virtio_gpu_instance_init(Object *obj)
|
static void virtio_gpu_instance_init(Object *obj)
|
||||||
|
|||||||
@@ -84,6 +84,17 @@ static const GraphicHwOps virtio_vga_ops = {
|
|||||||
.gl_block = virtio_vga_gl_block,
|
.gl_block = virtio_vga_gl_block,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const VMStateDescription vmstate_virtio_vga = {
|
||||||
|
.name = "virtio-vga",
|
||||||
|
.version_id = 2,
|
||||||
|
.minimum_version_id = 2,
|
||||||
|
.fields = (VMStateField[]) {
|
||||||
|
/* no pci stuff here, saving the virtio device will handle that */
|
||||||
|
VMSTATE_STRUCT(vga, VirtIOVGA, 0, vmstate_vga_common, VGACommonState),
|
||||||
|
VMSTATE_END_OF_LIST()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/* VGA device wrapper around PCI device around virtio GPU */
|
/* VGA device wrapper around PCI device around virtio GPU */
|
||||||
static void virtio_vga_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
|
static void virtio_vga_realize(VirtIOPCIProxy *vpci_dev, Error **errp)
|
||||||
{
|
{
|
||||||
@@ -168,6 +179,7 @@ static void virtio_vga_class_init(ObjectClass *klass, void *data)
|
|||||||
set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
|
set_bit(DEVICE_CATEGORY_DISPLAY, dc->categories);
|
||||||
dc->props = virtio_vga_properties;
|
dc->props = virtio_vga_properties;
|
||||||
dc->reset = virtio_vga_reset;
|
dc->reset = virtio_vga_reset;
|
||||||
|
dc->vmsd = &vmstate_virtio_vga;
|
||||||
dc->hotpluggable = false;
|
dc->hotpluggable = false;
|
||||||
|
|
||||||
k->realize = virtio_vga_realize;
|
k->realize = virtio_vga_realize;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user