diff --git a/MAINTAINERS b/MAINTAINERS index d3879aa3c1..7543eb4d59 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -324,7 +324,7 @@ F: disas/sparc.c X86 TCG CPUs M: Paolo Bonzini M: Richard Henderson -M: Eduardo Habkost +M: Eduardo Habkost S: Maintained F: target/i386/tcg/ F: tests/tcg/i386/ @@ -1628,7 +1628,7 @@ F: include/hw/i386/microvm.h F: pc-bios/bios-microvm.bin Machine core -M: Eduardo Habkost +M: Eduardo Habkost M: Marcel Apfelbaum R: Philippe Mathieu-Daudé S: Supported @@ -2648,13 +2648,13 @@ F: backends/cryptodev*.c Python library M: John Snow M: Cleber Rosa -R: Eduardo Habkost +R: Eduardo Habkost S: Maintained F: python/ T: git https://gitlab.com/jsnow/qemu.git python Python scripts -M: Eduardo Habkost +M: Eduardo Habkost M: Cleber Rosa S: Odd Fixes F: scripts/*.py @@ -2730,7 +2730,7 @@ T: git https://github.com/mdroth/qemu.git qga QOM M: Paolo Bonzini R: Daniel P. Berrange -R: Eduardo Habkost +R: Eduardo Habkost S: Supported F: docs/qdev-device-use.txt F: hw/core/qdev* @@ -2750,7 +2750,7 @@ F: tests/unit/check-qom-proplist.c F: tests/unit/test-qdev-global-props.c QOM boilerplate conversion script -M: Eduardo Habkost +M: Eduardo Habkost S: Maintained F: scripts/codeconverter/ @@ -3469,7 +3469,7 @@ M: Alex Bennée M: Philippe Mathieu-Daudé M: Thomas Huth R: Wainer dos Santos Moschetta -R: Willian Rampazzo +R: Beraldo Leal S: Maintained F: .github/lockdown.yml F: .gitlab-ci.yml @@ -3507,10 +3507,16 @@ W: https://trello.com/b/6Qi1pxVn/avocado-qemu R: Cleber Rosa R: Philippe Mathieu-Daudé R: Wainer dos Santos Moschetta -R: Willian Rampazzo +R: Beraldo Leal S: Odd Fixes F: tests/avocado/ +GitLab custom runner (Works On Arm Sponsored) +M: Alex Bennée +M: Philippe Mathieu-Daudé +S: Maintained +F: .gitlab-ci.d/custom-runners/ubuntu-20.04-aarch64.yml + Documentation ------------- Build system architecture diff --git a/VERSION b/VERSION index 61d04b724a..cbd3fe98d1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -6.2.91 +6.1.93 diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c index 504342ddf2..201565e55c 100644 --- a/accel/tcg/cpu-exec.c +++ b/accel/tcg/cpu-exec.c @@ -733,6 +733,15 @@ static inline bool need_replay_interrupt(int interrupt_request) static inline bool cpu_handle_interrupt(CPUState *cpu, TranslationBlock **last_tb) { + /* + * If we have requested custom cflags with CF_NOIRQ we should + * skip checking here. Any pending interrupts will get picked up + * by the next TB we execute under normal cflags. + */ + if (cpu->cflags_next_tb != -1 && cpu->cflags_next_tb & CF_NOIRQ) { + return false; + } + /* Clear the interrupt flag now since we're processing * cpu->interrupt_request and cpu->exit_request. * Ensure zeroing happens before reading cpu->exit_request or diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c index c89e1a0819..1879a35654 100644 --- a/accel/tcg/translate-all.c +++ b/accel/tcg/translate-all.c @@ -2243,7 +2243,7 @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages, if (current_tb_modified) { page_collection_unlock(pages); /* Force execution of one insn next time. */ - cpu->cflags_next_tb = 1 | curr_cflags(cpu); + cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(cpu); mmap_unlock(); cpu_loop_exit_noexc(cpu); } @@ -2411,7 +2411,7 @@ static bool tb_invalidate_phys_page(tb_page_addr_t addr, uintptr_t pc) #ifdef TARGET_HAS_PRECISE_SMC if (current_tb_modified) { /* Force execution of one insn next time. */ - cpu->cflags_next_tb = 1 | curr_cflags(cpu); + cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(cpu); return true; } #endif diff --git a/block/vvfat.c b/block/vvfat.c index 05e78e3c27..5dacc6cfac 100644 --- a/block/vvfat.c +++ b/block/vvfat.c @@ -1279,8 +1279,18 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags, qemu_co_mutex_init(&s->lock); - ret = 0; + qemu_opts_del(opts); + + return 0; + fail: + g_free(s->qcow_filename); + s->qcow_filename = NULL; + g_free(s->cluster_buffer); + s->cluster_buffer = NULL; + g_free(s->used_clusters); + s->used_clusters = NULL; + qemu_opts_del(opts); return ret; } @@ -3118,7 +3128,7 @@ static int enable_write_target(BlockDriverState *bs, Error **errp) int size = sector2cluster(s, s->sector_count); QDict *options; - s->used_clusters = calloc(size, 1); + s->used_clusters = g_malloc0(size); array_init(&(s->commits), sizeof(commit_t)); @@ -3166,8 +3176,6 @@ static int enable_write_target(BlockDriverState *bs, Error **errp) return 0; err: - g_free(s->qcow_filename); - s->qcow_filename = NULL; return ret; } diff --git a/chardev/wctablet.c b/chardev/wctablet.c index 95e005f5a5..e8b292c43c 100644 --- a/chardev/wctablet.c +++ b/chardev/wctablet.c @@ -320,7 +320,6 @@ static void wctablet_chr_finalize(Object *obj) TabletChardev *tablet = WCTABLET_CHARDEV(obj); qemu_input_handler_unregister(tablet->hs); - g_free(tablet); } static void wctablet_chr_open(Chardev *chr, diff --git a/docs/COLO-FT.txt b/docs/COLO-FT.txt index 8d6d53a5a2..8ec653f81c 100644 --- a/docs/COLO-FT.txt +++ b/docs/COLO-FT.txt @@ -209,9 +209,9 @@ children.0=childs0 \ 3. On Secondary VM's QEMU monitor, issue command -{'execute':'qmp_capabilities'} -{'execute': 'nbd-server-start', 'arguments': {'addr': {'type': 'inet', 'data': {'host': '0.0.0.0', 'port': '9999'} } } } -{'execute': 'nbd-server-add', 'arguments': {'device': 'parent0', 'writable': true } } +{"execute":"qmp_capabilities"} +{"execute": "nbd-server-start", "arguments": {"addr": {"type": "inet", "data": {"host": "0.0.0.0", "port": "9999"} } } } +{"execute": "nbd-server-add", "arguments": {"device": "parent0", "writable": true } } Note: a. The qmp command nbd-server-start and nbd-server-add must be run @@ -222,11 +222,11 @@ Note: will be merged into the parent disk on failover. 4. On Primary VM's QEMU monitor, issue command: -{'execute':'qmp_capabilities'} -{'execute': 'human-monitor-command', 'arguments': {'command-line': 'drive_add -n buddy driver=replication,mode=primary,file.driver=nbd,file.host=127.0.0.2,file.port=9999,file.export=parent0,node-name=replication0'}} -{'execute': 'x-blockdev-change', 'arguments':{'parent': 'colo-disk0', 'node': 'replication0' } } -{'execute': 'migrate-set-capabilities', 'arguments': {'capabilities': [ {'capability': 'x-colo', 'state': true } ] } } -{'execute': 'migrate', 'arguments': {'uri': 'tcp:127.0.0.2:9998' } } +{"execute":"qmp_capabilities"} +{"execute": "human-monitor-command", "arguments": {"command-line": "drive_add -n buddy driver=replication,mode=primary,file.driver=nbd,file.host=127.0.0.2,file.port=9999,file.export=parent0,node-name=replication0"}} +{"execute": "x-blockdev-change", "arguments":{"parent": "colo-disk0", "node": "replication0" } } +{"execute": "migrate-set-capabilities", "arguments": {"capabilities": [ {"capability": "x-colo", "state": true } ] } } +{"execute": "migrate", "arguments": {"uri": "tcp:127.0.0.2:9998" } } Note: a. There should be only one NBD Client for each primary disk. @@ -249,59 +249,59 @@ if you want to resume the replication, follow "Secondary resume replication" == Primary Failover == The Secondary died, resume on the Primary -{'execute': 'x-blockdev-change', 'arguments':{ 'parent': 'colo-disk0', 'child': 'children.1'} } -{'execute': 'human-monitor-command', 'arguments':{ 'command-line': 'drive_del replication0' } } -{'execute': 'object-del', 'arguments':{ 'id': 'comp0' } } -{'execute': 'object-del', 'arguments':{ 'id': 'iothread1' } } -{'execute': 'object-del', 'arguments':{ 'id': 'm0' } } -{'execute': 'object-del', 'arguments':{ 'id': 'redire0' } } -{'execute': 'object-del', 'arguments':{ 'id': 'redire1' } } -{'execute': 'x-colo-lost-heartbeat' } +{"execute": "x-blockdev-change", "arguments":{ "parent": "colo-disk0", "child": "children.1"} } +{"execute": "human-monitor-command", "arguments":{ "command-line": "drive_del replication0" } } +{"execute": "object-del", "arguments":{ "id": "comp0" } } +{"execute": "object-del", "arguments":{ "id": "iothread1" } } +{"execute": "object-del", "arguments":{ "id": "m0" } } +{"execute": "object-del", "arguments":{ "id": "redire0" } } +{"execute": "object-del", "arguments":{ "id": "redire1" } } +{"execute": "x-colo-lost-heartbeat" } == Secondary Failover == The Primary died, resume on the Secondary and prepare to become the new Primary -{'execute': 'nbd-server-stop'} -{'execute': 'x-colo-lost-heartbeat'} +{"execute": "nbd-server-stop"} +{"execute": "x-colo-lost-heartbeat"} -{'execute': 'object-del', 'arguments':{ 'id': 'f2' } } -{'execute': 'object-del', 'arguments':{ 'id': 'f1' } } -{'execute': 'chardev-remove', 'arguments':{ 'id': 'red1' } } -{'execute': 'chardev-remove', 'arguments':{ 'id': 'red0' } } +{"execute": "object-del", "arguments":{ "id": "f2" } } +{"execute": "object-del", "arguments":{ "id": "f1" } } +{"execute": "chardev-remove", "arguments":{ "id": "red1" } } +{"execute": "chardev-remove", "arguments":{ "id": "red0" } } -{'execute': 'chardev-add', 'arguments':{ 'id': 'mirror0', 'backend': {'type': 'socket', 'data': {'addr': { 'type': 'inet', 'data': { 'host': '0.0.0.0', 'port': '9003' } }, 'server': true } } } } -{'execute': 'chardev-add', 'arguments':{ 'id': 'compare1', 'backend': {'type': 'socket', 'data': {'addr': { 'type': 'inet', 'data': { 'host': '0.0.0.0', 'port': '9004' } }, 'server': true } } } } -{'execute': 'chardev-add', 'arguments':{ 'id': 'compare0', 'backend': {'type': 'socket', 'data': {'addr': { 'type': 'inet', 'data': { 'host': '127.0.0.1', 'port': '9001' } }, 'server': true } } } } -{'execute': 'chardev-add', 'arguments':{ 'id': 'compare0-0', 'backend': {'type': 'socket', 'data': {'addr': { 'type': 'inet', 'data': { 'host': '127.0.0.1', 'port': '9001' } }, 'server': false } } } } -{'execute': 'chardev-add', 'arguments':{ 'id': 'compare_out', 'backend': {'type': 'socket', 'data': {'addr': { 'type': 'inet', 'data': { 'host': '127.0.0.1', 'port': '9005' } }, 'server': true } } } } -{'execute': 'chardev-add', 'arguments':{ 'id': 'compare_out0', 'backend': {'type': 'socket', 'data': {'addr': { 'type': 'inet', 'data': { 'host': '127.0.0.1', 'port': '9005' } }, 'server': false } } } } +{"execute": "chardev-add", "arguments":{ "id": "mirror0", "backend": {"type": "socket", "data": {"addr": { "type": "inet", "data": { "host": "0.0.0.0", "port": "9003" } }, "server": true } } } } +{"execute": "chardev-add", "arguments":{ "id": "compare1", "backend": {"type": "socket", "data": {"addr": { "type": "inet", "data": { "host": "0.0.0.0", "port": "9004" } }, "server": true } } } } +{"execute": "chardev-add", "arguments":{ "id": "compare0", "backend": {"type": "socket", "data": {"addr": { "type": "inet", "data": { "host": "127.0.0.1", "port": "9001" } }, "server": true } } } } +{"execute": "chardev-add", "arguments":{ "id": "compare0-0", "backend": {"type": "socket", "data": {"addr": { "type": "inet", "data": { "host": "127.0.0.1", "port": "9001" } }, "server": false } } } } +{"execute": "chardev-add", "arguments":{ "id": "compare_out", "backend": {"type": "socket", "data": {"addr": { "type": "inet", "data": { "host": "127.0.0.1", "port": "9005" } }, "server": true } } } } +{"execute": "chardev-add", "arguments":{ "id": "compare_out0", "backend": {"type": "socket", "data": {"addr": { "type": "inet", "data": { "host": "127.0.0.1", "port": "9005" } }, "server": false } } } } == Primary resume replication == Resume replication after new Secondary is up. Start the new Secondary (Steps 2 and 3 above), then on the Primary: -{'execute': 'drive-mirror', 'arguments':{ 'device': 'colo-disk0', 'job-id': 'resync', 'target': 'nbd://127.0.0.2:9999/parent0', 'mode': 'existing', 'format': 'raw', 'sync': 'full'} } +{"execute": "drive-mirror", "arguments":{ "device": "colo-disk0", "job-id": "resync", "target": "nbd://127.0.0.2:9999/parent0", "mode": "existing", "format": "raw", "sync": "full"} } Wait until disk is synced, then: -{'execute': 'stop'} -{'execute': 'block-job-cancel', 'arguments':{ 'device': 'resync'} } +{"execute": "stop"} +{"execute": "block-job-cancel", "arguments":{ "device": "resync"} } -{'execute': 'human-monitor-command', 'arguments':{ 'command-line': 'drive_add -n buddy driver=replication,mode=primary,file.driver=nbd,file.host=127.0.0.2,file.port=9999,file.export=parent0,node-name=replication0'}} -{'execute': 'x-blockdev-change', 'arguments':{ 'parent': 'colo-disk0', 'node': 'replication0' } } +{"execute": "human-monitor-command", "arguments":{ "command-line": "drive_add -n buddy driver=replication,mode=primary,file.driver=nbd,file.host=127.0.0.2,file.port=9999,file.export=parent0,node-name=replication0"}} +{"execute": "x-blockdev-change", "arguments":{ "parent": "colo-disk0", "node": "replication0" } } -{'execute': 'object-add', 'arguments':{ 'qom-type': 'filter-mirror', 'id': 'm0', 'props': { 'netdev': 'hn0', 'queue': 'tx', 'outdev': 'mirror0' } } } -{'execute': 'object-add', 'arguments':{ 'qom-type': 'filter-redirector', 'id': 'redire0', 'props': { 'netdev': 'hn0', 'queue': 'rx', 'indev': 'compare_out' } } } -{'execute': 'object-add', 'arguments':{ 'qom-type': 'filter-redirector', 'id': 'redire1', 'props': { 'netdev': 'hn0', 'queue': 'rx', 'outdev': 'compare0' } } } -{'execute': 'object-add', 'arguments':{ 'qom-type': 'iothread', 'id': 'iothread1' } } -{'execute': 'object-add', 'arguments':{ 'qom-type': 'colo-compare', 'id': 'comp0', 'props': { 'primary_in': 'compare0-0', 'secondary_in': 'compare1', 'outdev': 'compare_out0', 'iothread': 'iothread1' } } } +{"execute": "object-add", "arguments":{ "qom-type": "filter-mirror", "id": "m0", "netdev": "hn0", "queue": "tx", "outdev": "mirror0" } } +{"execute": "object-add", "arguments":{ "qom-type": "filter-redirector", "id": "redire0", "netdev": "hn0", "queue": "rx", "indev": "compare_out" } } +{"execute": "object-add", "arguments":{ "qom-type": "filter-redirector", "id": "redire1", "netdev": "hn0", "queue": "rx", "outdev": "compare0" } } +{"execute": "object-add", "arguments":{ "qom-type": "iothread", "id": "iothread1" } } +{"execute": "object-add", "arguments":{ "qom-type": "colo-compare", "id": "comp0", "primary_in": "compare0-0", "secondary_in": "compare1", "outdev": "compare_out0", "iothread": "iothread1" } } -{'execute': 'migrate-set-capabilities', 'arguments':{ 'capabilities': [ {'capability': 'x-colo', 'state': true } ] } } -{'execute': 'migrate', 'arguments':{ 'uri': 'tcp:127.0.0.2:9998' } } +{"execute": "migrate-set-capabilities", "arguments":{ "capabilities": [ {"capability": "x-colo", "state": true } ] } } +{"execute": "migrate", "arguments":{ "uri": "tcp:127.0.0.2:9998" } } Note: If this Primary previously was a Secondary, then we need to insert the filters before the filter-rewriter by using the -"'insert': 'before', 'position': 'id=rew0'" Options. See below. +""insert": "before", "position": "id=rew0"" Options. See below. == Secondary resume replication == Become Primary and resume replication after new Secondary is up. Note @@ -309,23 +309,23 @@ that now 127.0.0.1 is the Secondary and 127.0.0.2 is the Primary. Start the new Secondary (Steps 2 and 3 above, but with primary_ip=127.0.0.2), then on the old Secondary: -{'execute': 'drive-mirror', 'arguments':{ 'device': 'colo-disk0', 'job-id': 'resync', 'target': 'nbd://127.0.0.1:9999/parent0', 'mode': 'existing', 'format': 'raw', 'sync': 'full'} } +{"execute": "drive-mirror", "arguments":{ "device": "colo-disk0", "job-id": "resync", "target": "nbd://127.0.0.1:9999/parent0", "mode": "existing", "format": "raw", "sync": "full"} } Wait until disk is synced, then: -{'execute': 'stop'} -{'execute': 'block-job-cancel', 'arguments':{ 'device': 'resync' } } +{"execute": "stop"} +{"execute": "block-job-cancel", "arguments":{ "device": "resync" } } -{'execute': 'human-monitor-command', 'arguments':{ 'command-line': 'drive_add -n buddy driver=replication,mode=primary,file.driver=nbd,file.host=127.0.0.1,file.port=9999,file.export=parent0,node-name=replication0'}} -{'execute': 'x-blockdev-change', 'arguments':{ 'parent': 'colo-disk0', 'node': 'replication0' } } +{"execute": "human-monitor-command", "arguments":{ "command-line": "drive_add -n buddy driver=replication,mode=primary,file.driver=nbd,file.host=127.0.0.1,file.port=9999,file.export=parent0,node-name=replication0"}} +{"execute": "x-blockdev-change", "arguments":{ "parent": "colo-disk0", "node": "replication0" } } -{'execute': 'object-add', 'arguments':{ 'qom-type': 'filter-mirror', 'id': 'm0', 'props': { 'insert': 'before', 'position': 'id=rew0', 'netdev': 'hn0', 'queue': 'tx', 'outdev': 'mirror0' } } } -{'execute': 'object-add', 'arguments':{ 'qom-type': 'filter-redirector', 'id': 'redire0', 'props': { 'insert': 'before', 'position': 'id=rew0', 'netdev': 'hn0', 'queue': 'rx', 'indev': 'compare_out' } } } -{'execute': 'object-add', 'arguments':{ 'qom-type': 'filter-redirector', 'id': 'redire1', 'props': { 'insert': 'before', 'position': 'id=rew0', 'netdev': 'hn0', 'queue': 'rx', 'outdev': 'compare0' } } } -{'execute': 'object-add', 'arguments':{ 'qom-type': 'iothread', 'id': 'iothread1' } } -{'execute': 'object-add', 'arguments':{ 'qom-type': 'colo-compare', 'id': 'comp0', 'props': { 'primary_in': 'compare0-0', 'secondary_in': 'compare1', 'outdev': 'compare_out0', 'iothread': 'iothread1' } } } +{"execute": "object-add", "arguments":{ "qom-type": "filter-mirror", "id": "m0", "insert": "before", "position": "id=rew0", "netdev": "hn0", "queue": "tx", "outdev": "mirror0" } } +{"execute": "object-add", "arguments":{ "qom-type": "filter-redirector", "id": "redire0", "insert": "before", "position": "id=rew0", "netdev": "hn0", "queue": "rx", "indev": "compare_out" } } +{"execute": "object-add", "arguments":{ "qom-type": "filter-redirector", "id": "redire1", "insert": "before", "position": "id=rew0", "netdev": "hn0", "queue": "rx", "outdev": "compare0" } } +{"execute": "object-add", "arguments":{ "qom-type": "iothread", "id": "iothread1" } } +{"execute": "object-add", "arguments":{ "qom-type": "colo-compare", "id": "comp0", "primary_in": "compare0-0", "secondary_in": "compare1", "outdev": "compare_out0", "iothread": "iothread1" } } -{'execute': 'migrate-set-capabilities', 'arguments':{ 'capabilities': [ {'capability': 'x-colo', 'state': true } ] } } -{'execute': 'migrate', 'arguments':{ 'uri': 'tcp:127.0.0.1:9998' } } +{"execute": "migrate-set-capabilities", "arguments":{ "capabilities": [ {"capability": "x-colo", "state": true } ] } } +{"execute": "migrate", "arguments":{ "uri": "tcp:127.0.0.1:9998" } } == TODO == 1. Support shared storage. diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index c03fcf951f..ff7488cb63 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -192,6 +192,12 @@ as short-form boolean values, and passed to plugins as ``arg_name=on``. However, short-form booleans are deprecated and full explicit ``arg_name=on`` form is preferred. +``-drive if=none`` for the sifive_u OTP device (since 6.2) +'''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +Using ``-drive if=none`` to configure the OTP device of the sifive_u +RISC-V machine is deprecated. Use ``-drive if=pflash`` instead. + QEMU Machine Protocol (QMP) commands ------------------------------------ diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst index 9d0d90c90d..d42c3341de 100644 --- a/docs/about/removed-features.rst +++ b/docs/about/removed-features.rst @@ -658,8 +658,8 @@ enforce that any failure to open the backing image (including if the backing file is missing or an incorrect format was specified) is an error when ``-u`` is not used. -qemu-img amend to adjust backing file (removed in 6.1) -'''''''''''''''''''''''''''''''''''''''''''''''''''''' +``qemu-img amend`` to adjust backing file (removed in 6.1) +'''''''''''''''''''''''''''''''''''''''''''''''''''''''''' The use of ``qemu-img amend`` to modify the name or format of a qcow2 backing image was never fully documented or tested, and interferes @@ -670,8 +670,8 @@ backing chain should be performed with ``qemu-img rebase -u`` either before or after the remaining changes being performed by amend, as appropriate. -qemu-img backing file without format (removed in 6.1) -''''''''''''''''''''''''''''''''''''''''''''''''''''' +``qemu-img`` backing file without format (removed in 6.1) +''''''''''''''''''''''''''''''''''''''''''''''''''''''''' The use of ``qemu-img create``, ``qemu-img rebase``, or ``qemu-img convert`` to create or modify an image that depends on a backing file diff --git a/docs/block-replication.txt b/docs/block-replication.txt index 59eb2b33b3..b0f23761c6 100644 --- a/docs/block-replication.txt +++ b/docs/block-replication.txt @@ -156,15 +156,15 @@ Primary: children.0.driver=raw Run qmp command in primary qemu: - { 'execute': 'human-monitor-command', - 'arguments': { - 'command-line': 'drive_add -n buddy driver=replication,mode=primary,file.driver=nbd,file.host=xxxx,file.port=xxxx,file.export=colo1,node-name=nbd_client1' + { "execute": "human-monitor-command", + "arguments": { + "command-line": "drive_add -n buddy driver=replication,mode=primary,file.driver=nbd,file.host=xxxx,file.port=xxxx,file.export=colo1,node-name=nbd_client1" } } - { 'execute': 'x-blockdev-change', - 'arguments': { - 'parent': 'colo1', - 'node': 'nbd_client1' + { "execute": "x-blockdev-change", + "arguments": { + "parent": "colo1", + "node": "nbd_client1" } } Note: @@ -189,21 +189,21 @@ Secondary: vote-threshold=1,children.0=childs1 Then run qmp command in secondary qemu: - { 'execute': 'nbd-server-start', - 'arguments': { - 'addr': { - 'type': 'inet', - 'data': { - 'host': 'xxx', - 'port': 'xxx' + { "execute": "nbd-server-start", + "arguments": { + "addr": { + "type": "inet", + "data": { + "host": "xxx", + "port": "xxx" } } } } - { 'execute': 'nbd-server-add', - 'arguments': { - 'device': 'colo1', - 'writable': true + { "execute": "nbd-server-add", + "arguments": { + "device": "colo1", + "writable": true } } @@ -223,22 +223,22 @@ After Failover: Primary: The secondary host is down, so we should run the following qmp command to remove the nbd child from the quorum: - { 'execute': 'x-blockdev-change', - 'arguments': { - 'parent': 'colo1', - 'child': 'children.1' + { "execute": "x-blockdev-change", + "arguments": { + "parent": "colo1", + "child": "children.1" } } - { 'execute': 'human-monitor-command', - 'arguments': { - 'command-line': 'drive_del xxxx' + { "execute": "human-monitor-command", + "arguments": { + "command-line": "drive_del xxxx" } } Note: there is no qmp command to remove the blockdev now Secondary: The primary host is down, so we should do the following thing: - { 'execute': 'nbd-server-stop' } + { "execute": "nbd-server-stop" } Promote Secondary to Primary: see COLO-FT.txt diff --git a/docs/devel/build-system.rst b/docs/devel/build-system.rst index 7a83f5fc0d..431caba7aa 100644 --- a/docs/devel/build-system.rst +++ b/docs/devel/build-system.rst @@ -121,11 +121,11 @@ process for: 1) executables, which include: - - Tools - qemu-img, qemu-nbd, qga (guest agent), etc + - Tools - ``qemu-img``, ``qemu-nbd``, ``qga`` (guest agent), etc - - System emulators - qemu-system-$ARCH + - System emulators - ``qemu-system-$ARCH`` - - Userspace emulators - qemu-$ARCH + - Userspace emulators - ``qemu-$ARCH`` - Unit tests diff --git a/docs/devel/modules.rst b/docs/devel/modules.rst index 066f347b89..8e999c4fa4 100644 --- a/docs/devel/modules.rst +++ b/docs/devel/modules.rst @@ -1,5 +1,5 @@ ============ -Qemu modules +QEMU modules ============ .. kernel-doc:: include/qemu/module.h diff --git a/docs/devel/multi-process.rst b/docs/devel/multi-process.rst index e5758a79ab..e4801751f2 100644 --- a/docs/devel/multi-process.rst +++ b/docs/devel/multi-process.rst @@ -187,9 +187,9 @@ desired, in which the emulation application should only be allowed to access the files or devices the VM it's running on behalf of can access. #### qemu-io model -Qemu-io is a test harness used to test changes to the QEMU block backend -object code. (e.g., the code that implements disk images for disk driver -emulation) Qemu-io is not a device emulation application per se, but it +``qemu-io`` is a test harness used to test changes to the QEMU block backend +object code (e.g., the code that implements disk images for disk driver +emulation). ``qemu-io`` is not a device emulation application per se, but it does compile the QEMU block objects into a separate binary from the main QEMU one. This could be useful for disk device emulation, since its emulation applications will need to include the QEMU block objects. @@ -641,7 +641,7 @@ the CPU that issued the MMIO. +==========+========================+ | rid | range MMIO is within | +----------+------------------------+ -| offset | offset withing *rid* | +| offset | offset within *rid* | +----------+------------------------+ | type | e.g., load or store | +----------+------------------------+ diff --git a/docs/devel/multi-thread-tcg.rst b/docs/devel/multi-thread-tcg.rst index 5b446ee08b..c9541a7b20 100644 --- a/docs/devel/multi-thread-tcg.rst +++ b/docs/devel/multi-thread-tcg.rst @@ -228,7 +228,7 @@ Emulated hardware state Currently thanks to KVM work any access to IO memory is automatically protected by the global iothread mutex, also known as the BQL (Big -Qemu Lock). Any IO region that doesn't use global mutex is expected to +QEMU Lock). Any IO region that doesn't use global mutex is expected to do its own locking. However IO memory isn't the only way emulated hardware state can be diff --git a/docs/devel/qgraph.rst b/docs/devel/qgraph.rst index db44d71002..43342d9d65 100644 --- a/docs/devel/qgraph.rst +++ b/docs/devel/qgraph.rst @@ -14,7 +14,7 @@ support that device. Using only libqos APIs, the test has to manually take care of covering all the setups, and build the correct command line. -This also introduces backward compability issues: if a device/driver command +This also introduces backward compatibility issues: if a device/driver command line name is changed, all tests that use that will not work properly anymore and need to be adjusted. diff --git a/docs/devel/stable-process.rst b/docs/devel/stable-process.rst index e541b983fa..c21fb86645 100644 --- a/docs/devel/stable-process.rst +++ b/docs/devel/stable-process.rst @@ -1,3 +1,5 @@ +.. _stable-process: + QEMU and the stable process =========================== diff --git a/docs/devel/style.rst b/docs/devel/style.rst index 260e3263fa..9c5c0fffd9 100644 --- a/docs/devel/style.rst +++ b/docs/devel/style.rst @@ -1,3 +1,5 @@ +.. _coding-style: + ================= QEMU Coding Style ================= @@ -686,7 +688,7 @@ Rationale: hex numbers are hard to read in logs when there is no 0x prefix, especially when (occasionally) the representation doesn't contain any letters and especially in one line with other decimal numbers. Number groups are allowed to not use '0x' because for some things notations like %x.%x.%x are used not -only in Qemu. Also dumping raw data bytes with '0x' is less readable. +only in QEMU. Also dumping raw data bytes with '0x' is less readable. '#' printf flag --------------- diff --git a/docs/devel/submitting-a-patch.rst b/docs/devel/submitting-a-patch.rst index 6fefc67d52..e51259eb9c 100644 --- a/docs/devel/submitting-a-patch.rst +++ b/docs/devel/submitting-a-patch.rst @@ -1,3 +1,5 @@ +.. _submitting-a-patch: + Submitting a Patch ================== @@ -20,11 +22,11 @@ one-shot fix, the bare minimum we ask is that: should not be posted on the bug tracker, posted on forums, or externally hosted and linked to. (We have other mailing lists too, but all patches must go to qemu-devel, possibly with a Cc: to another - list.) ``git send-email`` works best for delivering the patch without - mangling it (`hints for setting it - up `__), - but attachments can be used as a last resort on a first-time - submission. + list.) ``git send-email`` (`step-by-step setup + guide `__ and `hints and + tips `__) + works best for delivering the patch without mangling it, but + attachments can be used as a last resort on a first-time submission. - You must read replies to your message, and be willing to act on them. Note, however, that maintainers are often willing to manually fix up first-time contributions, since there is a learning curve involved in @@ -45,6 +47,8 @@ Reading the table of contents below should already give you an idea of the basic requirements. Use the table of contents as a reference, and read the parts that you have doubts about. +.. contents:: Table of Contents + .. _writing_your_patches: Writing your Patches @@ -60,11 +64,9 @@ check that you are in compliance with our coding standards. Be aware that ``checkpatch.pl`` is not infallible, though, especially where C preprocessor macros are involved; use some common sense too. See also: -- `QEMU Coding Style - `__ - +- :ref:`coding-style` - `Automate a checkpatch run on - commit `__ + commit `__ .. _base_patches_against_current_git_master: @@ -76,6 +78,13 @@ of QEMU because development will have moved on from then and it probably won't even apply to master. We only apply selected bugfixes to release branches and then only as backports once the code has gone into master. +It is also okay to base patches on top of other on-going work that is +not yet part of the git master branch. To aid continuous integration +tools, such as `patchew `__, you should `add a +tag `__ +line ``Based-on: $MESSAGE_ID`` to your cover letter to make the series +dependency obvious. + .. _split_up_long_patches: Split up long patches @@ -104,18 +113,17 @@ Make code motion patches easy to review If a series requires large blocks of code motion, there are tricks for making the refactoring easier to review. Split up the series so that semantic changes (or even function renames) are done in a separate patch -from the raw code motion. Use a one-time setup of -``git config diff.renames true; git config diff.algorithm patience`` -(Refer to `git-config `__.) The -``diff.renames`` property ensures file rename patches will be given in a -more compact representation that focuses only on the differences across -the file rename, instead of showing the entire old file as a deletion -and the new file as an insertion. Meanwhile, the 'diff.algorithm' -property ensures that extracting a non-contiguous subset of one file -into a new file, but where all extracted parts occur in the same order -both before and after the patch, will reduce churn in trying to treat -unrelated ``}`` lines in the original file as separating hunks of -changes. +from the raw code motion. Use a one-time setup of ``git config +diff.renames true;`` ``git config diff.algorithm patience`` (refer to +`git-config `__). The 'diff.renames' +property ensures file rename patches will be given in a more compact +representation that focuses only on the differences across the file +rename, instead of showing the entire old file as a deletion and the new +file as an insertion. Meanwhile, the 'diff.algorithm' property ensures +that extracting a non-contiguous subset of one file into a new file, but +where all extracted parts occur in the same order both before and after +the patch, will reduce churn in trying to treat unrelated ``}`` lines in +the original file as separating hunks of changes. Ideally, a code motion patch can be reviewed by doing:: @@ -138,8 +146,7 @@ as a separate patch which makes no semantic changes; don't put it in the same patch as your bug fix. For smaller patches in less frequently changed areas of QEMU, consider -using the `trivial patches process -`__. +using the :ref:`trivial-patches` process. .. _write_a_meaningful_commit_message: @@ -154,7 +161,7 @@ QEMU follows the usual standard for git commit messages: the first line (which becomes the email subject line) is "subsystem: single line summary of change". Whether the "single line summary of change" starts with a capital is a matter of taste, but we prefer that the summary does -not end in ".". Look at ``git shortlog -30`` for an idea of sample +not end in a dot. Look at ``git shortlog -30`` for an idea of sample subject lines. Then there is a blank line and a more detailed description of the patch, another blank and your Signed-off-by: line. Please do not use lines that are longer than 76 characters in your @@ -170,11 +177,79 @@ displays the subject line some distance apart (that is, a body that starts with "... so that" as a continuation of the subject line is harder to follow). +If your patch fixes a commit that is already in the repository, please +add an additional line with "Fixes: +("Fixed commit subject")" below the patch description / before your +"Signed-off-by:" line in the commit message. + +If your patch fixes a bug in the gitlab bug tracker, please add a line +with "Resolves: " to the commit message, too. Gitlab can +close bugs automatically once commits with the "Resolved:" keyword get +merged into the master branch of the project. And if your patch addresses +a bug in another public bug tracker, you can also use a line with +"Buglink: " for reference here, too. + +Example:: + + Fixes: 14055ce53c2d ("s390x/tcg: avoid overflows in time2tod/tod2time") + Resolves: https://gitlab.com/qemu-project/qemu/-/issues/42 + Buglink: https://bugs.launchpad.net/qemu/+bug/1804323`` + +Some other tags that are used in commit messages include "Message-Id:" +"Tested-by:", "Acked-by:", "Reported-by:", "Suggested-by:". See ``git +log`` for these keywords for example usage. + +.. _test_your_patches: + +Test your patches +~~~~~~~~~~~~~~~~~ + +Although QEMU has `continuous integration +services `__ that attempt to test +patches submitted to the list, it still saves everyone time if you have +already tested that your patch compiles and works. Because QEMU is such +a large project, it's okay to use configure arguments to limit what is +built for faster turnaround during your development time; but it is +still wise to also check that your patches work with a full build before +submitting a series, especially if your changes might have an unintended +effect on other areas of the code you don't normally experiment with. +See `Testing `__ for more details on what tests are available. +Also, it is a wise idea to include a testsuite addition as part of your +patches - either to ensure that future changes won't regress your new +feature, or to add a test which exposes the bug that the rest of your +series fixes. Keeping separate commits for the test and the fix allows +reviewers to rebase the test to occur first to prove it catches the +problem, then again to place it last in the series so that bisection +doesn't land on a known-broken state. + .. _submitting_your_patches: Submitting your Patches ----------------------- +.. _if_you_cannot_send_patch_emails: + +If you cannot send patch emails +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In rare cases it may not be possible to send properly formatted patch +emails. You can use `sourcehut `__ to send your +patches to the QEMU mailing list by following these steps: + +#. Register or sign in to your account +#. Add your SSH public key in `meta \| + keys `__. +#. Publish your git branch using **git push git@git.sr.ht:~USERNAME/qemu + HEAD** +#. Send your patches to the QEMU mailing list using the web-based + ``git-send-email`` UI at https://git.sr.ht/~USERNAME/qemu/send-email + +`This video +`__ +shows the web-based ``git-send-email`` workflow. Documentation is +available `here +`__. + .. _cc_the_relevant_maintainer: CC the relevant maintainer @@ -219,17 +294,26 @@ such as 'git-email' on Fedora-based systems.) Patch series need a cover letter, with shallow threading (all patches in the series are in-reply-to the cover letter, but not to each other); single unrelated patches do not need a cover letter (but if you do send a cover letter, -use --numbered so the cover and the patch have distinct subject lines). +use ``--numbered`` so the cover and the patch have distinct subject lines). Patches are easier to find if they start a new top-level thread, rather than being buried in-reply-to another existing thread. +.. _avoid_posting_large_binary_blob: + +Avoid posting large binary blob +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you added binaries to the repository, consider producing the patch +emails using ``git format-patch --no-binary`` and include a link to a +git repository to fetch the original commit. + .. _patch_emails_must_include_a_signed_off_by_line: Patch emails must include a ``Signed-off-by:`` line ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -For more information see `1.12) Sign your work -`__. +For more information see `SubmittingPatches 1.12 +`__. This is vital or we will not be able to apply your patch! Please use your real name to sign a patch (not an alias or acronym). @@ -246,8 +330,13 @@ that author's Signed-off-by: line is mandatory, with the same spelling. Include a meaningful cover letter ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -This usually applies only to a series that includes multiple patches; -the cover letter explains the overall goal of such a series. +This is a requirement for any series with multiple patches (as it aids +continuous integration), but optional for an isolated patch. The cover +letter explains the overall goal of such a series, and also provides a +convenient 0/N email for others to reply to the series as a whole. A +one-time setup of ``git config format.coverletter auto`` (refer to +`git-config `__) will generate the +cover letter as needed. When reviewers don't know your goal at the start of their review, they may object to early changes that don't make sense until the end of the @@ -288,6 +377,18 @@ it's best to: of the patchset you're looking for review on, and why reviewers should care +.. _consider_whether_your_patch_is_applicable_for_stable: + +Consider whether your patch is applicable for stable +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If your patch fixes a severe issue or a regression, it may be applicable +for stable. In that case, consider adding ``Cc: qemu-stable@nongnu.org`` +to your patch to notify the stable maintainers. + +For more details on how QEMU's stable process works, refer to the +:ref:`stable-process` page. + .. _participating_in_code_review: Participating in Code Review @@ -367,19 +468,19 @@ Include version history in patchset revisions For later versions of patches, include a summary of changes from previous versions, but not in the commit message itself. In an email -formatted as a git patch, the commit message is the part above the "---" +formatted as a git patch, the commit message is the part above the ``---`` line, and this will go into the git changelog when the patch is committed. This part should be a self-contained description of what this version of the patch does, written to make sense to anybody who comes back to look at this commit in git in six months' time. The part below -the "---" line and above the patch proper (git format-patch puts the +the ``---`` line and above the patch proper (git format-patch puts the diffstat here) is a good place to put remarks for people reading the patch email, and this is where the "changes since previous version" -summary belongs. The -`git-publish `__ script can -help with tracking a good summary across versions. Also, the -`git-backport-diff `__ script -can help focus reviewers on what changed between revisions. +summary belongs. The `git-publish +`__ script can help with +tracking a good summary across versions. Also, the `git-backport-diff +`__ script can help focus +reviewers on what changed between revisions. .. _tips_and_tricks: @@ -411,27 +512,32 @@ If your patch seems to have been ignored If your patchset has received no replies you should "ping" it after a week or two, by sending an email as a reply-to-all to the patch mail, including the word "ping" and ideally also a link to the page for the -patch on -`patchwork `__ or -GMANE. It's worth double-checking for reasons why your patch might have -been ignored (forgot to CC the maintainer? annoyed people by failing to -respond to review comments on an earlier version?), but often for -less-maintained areas of QEMU patches do just slip through the cracks. -If your ping is also ignored, ping again after another week or so. As -the submitter, you are the person with the most motivation to get your -patch applied, so you have to be persistent. +patch on `patchew `__ or +`lore.kernel.org `__. It's worth +double-checking for reasons why your patch might have been ignored +(forgot to CC the maintainer? annoyed people by failing to respond to +review comments on an earlier version?), but often for less-maintained +areas of QEMU patches do just slip through the cracks. If your ping is +also ignored, ping again after another week or so. As the submitter, you +are the person with the most motivation to get your patch applied, so +you have to be persistent. .. _is_my_patch_in: Is my patch in? ~~~~~~~~~~~~~~~ +QEMU has some Continuous Integration machines that try to catch patch +submission problems as soon as possible. `patchew +`__ includes a web interface for tracking the +status of various threads that have been posted to the list, and may +send you an automated mail if it detected a problem with your patch. + Once your patch has had enough review on list, the maintainer for that area of code will send notification to the list that they are including your patch in a particular staging branch. Periodically, the maintainer -then sends a `pull request -`__ -for aggregating topic branches into mainline qemu. Generally, you do not +then takes care of :ref:`submitting-a-pull-request` +for aggregating topic branches into mainline QEMU. Generally, you do not need to send a pull request unless you have contributed enough patches to become a maintainer over a particular section of code. Maintainers may further modify your commit, by resolving simple merge conflicts or diff --git a/docs/devel/submitting-a-pull-request.rst b/docs/devel/submitting-a-pull-request.rst index 8729d29036..c9d1e8afd9 100644 --- a/docs/devel/submitting-a-pull-request.rst +++ b/docs/devel/submitting-a-pull-request.rst @@ -1,10 +1,11 @@ -Submit a Pull Request -===================== +.. _submitting-a-pull-request: + +Submitting a Pull Request +========================= QEMU welcomes contributions of code, but we generally expect these to be sent as simple patch emails to the mailing list (see our page on -`submitting a patch -`__ +:ref:`submitting-a-patch` for more details). Generally only existing submaintainers of a tree will need to submit pull requests, although occasionally for a large patch series we might ask a submitter to send a pull request. This page diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst index 60c59023e5..755343c7dd 100644 --- a/docs/devel/testing.rst +++ b/docs/devel/testing.rst @@ -564,11 +564,11 @@ exploiting a QEMU security bug to compromise the host. QEMU binaries ~~~~~~~~~~~~~ -By default, qemu-system-x86_64 is searched in $PATH to run the guest. If there -isn't one, or if it is older than 2.10, the test won't work. In this case, +By default, ``qemu-system-x86_64`` is searched in $PATH to run the guest. If +there isn't one, or if it is older than 2.10, the test won't work. In this case, provide the QEMU binary in env var: ``QEMU=/path/to/qemu-2.10+``. -Likewise the path to qemu-img can be set in QEMU_IMG environment variable. +Likewise the path to ``qemu-img`` can be set in QEMU_IMG environment variable. Make jobs ~~~~~~~~~ @@ -650,7 +650,7 @@ supported. To start the fuzzer, run tests/image-fuzzer/runner.py -c '[["qemu-img", "info", "$test_img"]]' /tmp/test qcow2 -Alternatively, some command different from "qemu-img info" can be tested, by +Alternatively, some command different from ``qemu-img info`` can be tested, by changing the ``-c`` option. Integration tests using the Avocado Framework diff --git a/docs/devel/trivial-patches.rst b/docs/devel/trivial-patches.rst index db3f2001da..9380c730f7 100644 --- a/docs/devel/trivial-patches.rst +++ b/docs/devel/trivial-patches.rst @@ -1,3 +1,5 @@ +.. _trivial-patches: + Trivial Patches =============== diff --git a/docs/devel/ui.rst b/docs/devel/ui.rst index 06c7d622ce..17fb667dec 100644 --- a/docs/devel/ui.rst +++ b/docs/devel/ui.rst @@ -1,8 +1,8 @@ ================= -Qemu UI subsystem +QEMU UI subsystem ================= -Qemu Clipboard +QEMU Clipboard -------------- .. kernel-doc:: include/ui/clipboard.h diff --git a/docs/devel/writing-monitor-commands.rst b/docs/devel/writing-monitor-commands.rst index b3e2c8481d..1693822f8f 100644 --- a/docs/devel/writing-monitor-commands.rst +++ b/docs/devel/writing-monitor-commands.rst @@ -677,7 +677,7 @@ return a single text string:: The ``HumanReadableText`` struct is intended to be used for all commands, under the ``x-`` name prefix that are returning unstructured -text targetted at humans. It should never be used for commands outside +text targeted at humans. It should never be used for commands outside the ``x-`` name prefix, as those should be using structured QAPI types. Implementing the QMP command diff --git a/docs/hyperv.txt b/docs/hyperv.txt index 5d99fd9a72..0417c183a3 100644 --- a/docs/hyperv.txt +++ b/docs/hyperv.txt @@ -195,7 +195,7 @@ The enlightenment allows to use Hyper-V SynIC with hardware APICv/AVIC enabled. Normally, Hyper-V SynIC disables these hardware feature and suggests the guest to use paravirtualized AutoEOI feature. Note: enabling this feature on old hardware (without APICv/AVIC support) may -have negative effect on guest's performace. +have negative effect on guest's performance. 3.19. hv-no-nonarch-coresharing=on/off/auto =========================================== diff --git a/docs/image-fuzzer.txt b/docs/image-fuzzer.txt index 3e23ebec33..279cc8c807 100644 --- a/docs/image-fuzzer.txt +++ b/docs/image-fuzzer.txt @@ -51,10 +51,10 @@ assumes that core dumps will be generated in the current working directory. For comprehensive test results, please, set up your test environment properly. -Paths to binaries under test (SUTs) qemu-img and qemu-io are retrieved from -environment variables. If the environment check fails the runner will +Paths to binaries under test (SUTs) ``qemu-img`` and ``qemu-io`` are retrieved +from environment variables. If the environment check fails the runner will use SUTs installed in system paths. -qemu-img is required for creation of backing files, so it's mandatory to set +``qemu-img`` is required for creation of backing files, so it's mandatory to set the related environment variable if it's not installed in the system path. For details about environment variables see qemu-iotests/check. diff --git a/docs/interop/nbd.txt b/docs/interop/nbd.txt index 10ce098a29..bdb0f2a41a 100644 --- a/docs/interop/nbd.txt +++ b/docs/interop/nbd.txt @@ -1,4 +1,4 @@ -Qemu supports the NBD protocol, and has an internal NBD client (see +QEMU supports the NBD protocol, and has an internal NBD client (see block/nbd.c), an internal NBD server (see blockdev-nbd.c), and an external NBD server tool (see qemu-nbd.c). The common code is placed in nbd/*. @@ -7,11 +7,11 @@ The NBD protocol is specified here: https://github.com/NetworkBlockDevice/nbd/blob/master/doc/proto.md The following paragraphs describe some specific properties of NBD -protocol realization in Qemu. +protocol realization in QEMU. = Metadata namespaces = -Qemu supports the "base:allocation" metadata context as defined in the +QEMU supports the "base:allocation" metadata context as defined in the NBD protocol specification, and also defines an additional metadata namespace "qemu". diff --git a/docs/interop/qcow2.txt b/docs/interop/qcow2.txt index 0463f761ef..f7dc304ff6 100644 --- a/docs/interop/qcow2.txt +++ b/docs/interop/qcow2.txt @@ -313,7 +313,7 @@ The fields of the bitmaps extension are: The number of bitmaps contained in the image. Must be greater than or equal to 1. - Note: Qemu currently only supports up to 65535 bitmaps per + Note: QEMU currently only supports up to 65535 bitmaps per image. 4 - 7: Reserved, must be zero. @@ -775,7 +775,7 @@ Structure of a bitmap directory entry: 2: extra_data_compatible This flags is meaningful when the extra data is unknown to the software (currently any extra data is - unknown to Qemu). + unknown to QEMU). If it is set, the bitmap may be used as expected, extra data must be left as is. If it is not set, the bitmap must not be used, but @@ -793,7 +793,7 @@ Structure of a bitmap directory entry: 17: granularity_bits Granularity bits. Valid values: 0 - 63. - Note: Qemu currently supports only values 9 - 31. + Note: QEMU currently supports only values 9 - 31. Granularity is calculated as granularity = 1 << granularity_bits @@ -804,7 +804,7 @@ Structure of a bitmap directory entry: 18 - 19: name_size Size of the bitmap name. Must be non-zero. - Note: Qemu currently doesn't support values greater than + Note: QEMU currently doesn't support values greater than 1023. 20 - 23: extra_data_size diff --git a/docs/multiseat.txt b/docs/multiseat.txt index 11850c96ff..2b297e979d 100644 --- a/docs/multiseat.txt +++ b/docs/multiseat.txt @@ -123,7 +123,7 @@ Background info is here: guest side with pci-bridge-seat ------------------------------- -Qemu version 2.4 and newer has a new pci-bridge-seat device which +QEMU version 2.4 and newer has a new pci-bridge-seat device which can be used instead of pci-bridge. Just swap the device name in the qemu command line above. The only difference between the two devices is the pci id. We can match the pci id instead of the device path diff --git a/docs/system/arm/orangepi.rst b/docs/system/arm/orangepi.rst index c55694dd91..83c7445197 100644 --- a/docs/system/arm/orangepi.rst +++ b/docs/system/arm/orangepi.rst @@ -128,7 +128,7 @@ Alternatively, you can also choose to build you own image with buildroot using the orangepi_pc_defconfig. Also see https://buildroot.org for more information. When using an image as an SD card, it must be resized to a power of two. This can be -done with the qemu-img command. It is recommended to only increase the image size +done with the ``qemu-img`` command. It is recommended to only increase the image size instead of shrinking it to a power of two, to avoid loss of data. For example, to prepare a downloaded Armbian image, first extract it and then increase its size to one gigabyte as follows: diff --git a/docs/system/authz.rst b/docs/system/authz.rst index 942af39602..55b7315e49 100644 --- a/docs/system/authz.rst +++ b/docs/system/authz.rst @@ -77,9 +77,7 @@ To create an instance of this driver via QMP: "arguments": { "qom-type": "authz-simple", "id": "authz0", - "props": { - "identity": "fred" - } + "identity": "fred" } } @@ -110,15 +108,13 @@ To create an instance of this class via QMP: "arguments": { "qom-type": "authz-list", "id": "authz0", - "props": { - "rules": [ - { "match": "fred", "policy": "allow", "format": "exact" }, - { "match": "bob", "policy": "allow", "format": "exact" }, - { "match": "danb", "policy": "deny", "format": "exact" }, - { "match": "dan*", "policy": "allow", "format": "glob" } - ], - "policy": "deny" - } + "rules": [ + { "match": "fred", "policy": "allow", "format": "exact" }, + { "match": "bob", "policy": "allow", "format": "exact" }, + { "match": "danb", "policy": "deny", "format": "exact" }, + { "match": "dan*", "policy": "allow", "format": "glob" } + ], + "policy": "deny" } } @@ -143,10 +139,8 @@ To create an instance of this class via QMP: "arguments": { "qom-type": "authz-list-file", "id": "authz0", - "props": { - "filename": "/etc/qemu/myvm-vnc.acl", - "refresh": true - } + "filename": "/etc/qemu/myvm-vnc.acl", + "refresh": true } } diff --git a/docs/system/cpu-models-x86.rst.inc b/docs/system/cpu-models-x86.rst.inc index 6e8be7d79b..7f6368f999 100644 --- a/docs/system/cpu-models-x86.rst.inc +++ b/docs/system/cpu-models-x86.rst.inc @@ -49,7 +49,7 @@ future OS and toolchains are likely to target newer ABIs. The table that follows illustrates which ABI compatibility levels can be satisfied by the QEMU CPU models. Note that the table only lists the long term stable CPU model versions (eg Haswell-v4). -In addition to whats listed, there are also many CPU model +In addition to what is listed, there are also many CPU model aliases which resolve to a different CPU model version, depending on the machine type is in use. diff --git a/docs/system/device-url-syntax.rst.inc b/docs/system/device-url-syntax.rst.inc index d15a021508..7dbc525fa8 100644 --- a/docs/system/device-url-syntax.rst.inc +++ b/docs/system/device-url-syntax.rst.inc @@ -15,7 +15,7 @@ These are specified using a special URL syntax. 'iqn.2008-11.org.linux-kvm[:]' but this can also be set from the command line or a configuration file. - Since version Qemu 2.4 it is possible to specify a iSCSI request + Since version QEMU 2.4 it is possible to specify a iSCSI request timeout to detect stalled requests and force a reestablishment of the session. The timeout is specified in seconds. The default is 0 which means no timeout. Libiscsi 1.15.0 or greater is required for this diff --git a/docs/system/devices/nvme.rst b/docs/system/devices/nvme.rst index a1c0db01f6..b5acb2a9c1 100644 --- a/docs/system/devices/nvme.rst +++ b/docs/system/devices/nvme.rst @@ -70,7 +70,7 @@ namespaces and additional features, the ``nvme-ns`` device must be used. The namespaces defined by the ``nvme-ns`` device will attach to the most recently defined ``nvme-bus`` that is created by the ``nvme`` device. Namespace -identifers are allocated automatically, starting from ``1``. +identifiers are allocated automatically, starting from ``1``. There are a number of parameters available: diff --git a/docs/system/gdb.rst b/docs/system/gdb.rst index bdb42dae2f..453eb73f6c 100644 --- a/docs/system/gdb.rst +++ b/docs/system/gdb.rst @@ -56,7 +56,7 @@ machine has more than one CPU, QEMU exposes each CPU cluster as a separate "inferior", where each CPU within the cluster is a separate "thread". Most QEMU machine types have identical CPUs, so there is a single cluster which has all the CPUs in it. A few machine types are -heterogenous and have multiple clusters: for example the ``sifive_u`` +heterogeneous and have multiple clusters: for example the ``sifive_u`` machine has a cluster with one E51 core and a second cluster with four U54 cores. Here the E51 is the only thread in the first inferior, and the U54 cores are all threads in the second inferior. diff --git a/docs/system/i386/sgx.rst b/docs/system/i386/sgx.rst index 9aa161af1a..f8fade5ac2 100644 --- a/docs/system/i386/sgx.rst +++ b/docs/system/i386/sgx.rst @@ -20,13 +20,13 @@ report the same CPUID info to guest as on host for most of SGX CPUID. With reporting the same CPUID guest is able to use full capacity of SGX, and KVM doesn't need to emulate those info. -The guest's EPC base and size are determined by Qemu, and KVM needs Qemu to +The guest's EPC base and size are determined by QEMU, and KVM needs QEMU to notify such info to it before it can initialize SGX for guest. Virtual EPC ~~~~~~~~~~~ -By default, Qemu does not assign EPC to a VM, i.e. fully enabling SGX in a VM +By default, QEMU does not assign EPC to a VM, i.e. fully enabling SGX in a VM requires explicit allocation of EPC to the VM. Similar to other specialized memory types, e.g. hugetlbfs, EPC is exposed as a memory backend. @@ -35,12 +35,12 @@ prior to realizing the vCPUs themselves, which occurs long before generic devices are parsed and realized. This limitation means that EPC does not require -maxmem as EPC is not treated as {cold,hot}plugged memory. -Qemu does not artificially restrict the number of EPC sections exposed to a -guest, e.g. Qemu will happily allow you to create 64 1M EPC sections. Be aware +QEMU does not artificially restrict the number of EPC sections exposed to a +guest, e.g. QEMU will happily allow you to create 64 1M EPC sections. Be aware that some kernels may not recognize all EPC sections, e.g. the Linux SGX driver is hardwired to support only 8 EPC sections. -The following Qemu snippet creates two EPC sections, with 64M pre-allocated +The following QEMU snippet creates two EPC sections, with 64M pre-allocated to the VM and an additional 28M mapped but not allocated:: -object memory-backend-epc,id=mem1,size=64M,prealloc=on \ @@ -54,7 +54,7 @@ to physical EPC. Because physical EPC is protected via range registers, the size of the physical EPC must be a power of two (though software sees a subset of the full EPC, e.g. 92M or 128M) and the EPC must be naturally aligned. KVM SGX's virtual EPC is purely a software construct and only -requires the size and location to be page aligned. Qemu enforces the EPC +requires the size and location to be page aligned. QEMU enforces the EPC size is a multiple of 4k and will ensure the base of the EPC is 4k aligned. To simplify the implementation, EPC is always located above 4g in the guest physical address space. @@ -62,7 +62,7 @@ physical address space. Migration ~~~~~~~~~ -Qemu/KVM doesn't prevent live migrating SGX VMs, although from hardware's +QEMU/KVM doesn't prevent live migrating SGX VMs, although from hardware's perspective, SGX doesn't support live migration, since both EPC and the SGX key hierarchy are bound to the physical platform. However live migration can be supported in the sense if guest software stack can support recreating @@ -76,7 +76,7 @@ CPUID ~~~~~ Due to its myriad dependencies, SGX is currently not listed as supported -in any of Qemu's built-in CPU configuration. To expose SGX (and SGX Launch +in any of QEMU's built-in CPU configuration. To expose SGX (and SGX Launch Control) to a guest, you must either use ``-cpu host`` to pass-through the host CPU model, or explicitly enable SGX when using a built-in CPU model, e.g. via ``-cpu ,+sgx`` or ``-cpu ,+sgx,+sgxlc``. @@ -101,7 +101,7 @@ controlled via -cpu are prefixed with "sgx", e.g.:: sgx2 sgxlc -The following Qemu snippet passes through the host CPU but restricts access to +The following QEMU snippet passes through the host CPU but restricts access to the provision and EINIT token keys:: -cpu host,-sgx-provisionkey,-sgx-tokenkey @@ -112,11 +112,11 @@ in hardware cannot be forced on via '-cpu'. Virtualize SGX Launch Control ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Qemu SGX support for Launch Control (LC) is passive, in the sense that it -does not actively change the LC configuration. Qemu SGX provides the user +QEMU SGX support for Launch Control (LC) is passive, in the sense that it +does not actively change the LC configuration. QEMU SGX provides the user the ability to set/clear the CPUID flag (and by extension the associated IA32_FEATURE_CONTROL MSR bit in fw_cfg) and saves/restores the LE Hash MSRs -when getting/putting guest state, but Qemu does not add new controls to +when getting/putting guest state, but QEMU does not add new controls to directly modify the LC configuration. Similar to hardware behavior, locking the LC configuration to a non-Intel value is left to guest firmware. Unlike host bios setting for SGX launch control(LC), there is no special bios setting @@ -126,7 +126,7 @@ creating VM with SGX. Feature Control ~~~~~~~~~~~~~~~ -Qemu SGX updates the ``etc/msr_feature_control`` fw_cfg entry to set the SGX +QEMU SGX updates the ``etc/msr_feature_control`` fw_cfg entry to set the SGX (bit 18) and SGX LC (bit 17) flags based on their respective CPUID support, i.e. existing guest firmware will automatically set SGX and SGX LC accordingly, assuming said firmware supports fw_cfg.msr_feature_control. diff --git a/docs/system/images.rst b/docs/system/images.rst index 3d9144e625..d000bd6b6f 100644 --- a/docs/system/images.rst +++ b/docs/system/images.rst @@ -20,7 +20,7 @@ where myimage.img is the disk image filename and mysize is its size in kilobytes. You can add an ``M`` suffix to give the size in megabytes and a ``G`` suffix for gigabytes. -See the qemu-img invocation documentation for more information. +See the ``qemu-img`` invocation documentation for more information. .. _disk_005fimages_005fsnapshot_005fmode: diff --git a/docs/system/ppc/ppce500.rst b/docs/system/ppc/ppce500.rst index afc58f60f5..9beef39171 100644 --- a/docs/system/ppc/ppce500.rst +++ b/docs/system/ppc/ppce500.rst @@ -75,7 +75,7 @@ as the BIOS. QEMU follows below truth table to select which payload to execute: When both -bios and -kernel are present, QEMU loads U-Boot and U-Boot in turns automatically loads the kernel image specified by the -kernel parameter via U-Boot's built-in "bootm" command, hence a legacy uImage format is required in -such senario. +such scenario. Running Linux kernel -------------------- diff --git a/docs/system/qemu-block-drivers.rst.inc b/docs/system/qemu-block-drivers.rst.inc index 16225710eb..e313784426 100644 --- a/docs/system/qemu-block-drivers.rst.inc +++ b/docs/system/qemu-block-drivers.rst.inc @@ -511,13 +511,13 @@ of an inet socket: |qemu_system| linux.img -hdb nbd+unix://?socket=/tmp/my_socket -In this case, the block device must be exported using qemu-nbd: +In this case, the block device must be exported using ``qemu-nbd``: .. parsed-literal:: qemu-nbd --socket=/tmp/my_socket my_disk.qcow2 -The use of qemu-nbd allows sharing of a disk between several guests: +The use of ``qemu-nbd`` allows sharing of a disk between several guests: .. parsed-literal:: @@ -530,7 +530,7 @@ and then you can use it with two guests: |qemu_system| linux1.img -hdb nbd+unix://?socket=/tmp/my_socket |qemu_system| linux2.img -hdb nbd+unix://?socket=/tmp/my_socket -If the nbd-server uses named exports (supported since NBD 2.9.18, or with QEMU's +If the ``nbd-server`` uses named exports (supported since NBD 2.9.18, or with QEMU's own embedded NBD server), you must specify an export name in the URI: .. parsed-literal:: diff --git a/docs/system/riscv/shakti-c.rst b/docs/system/riscv/shakti-c.rst index a6035d42b0..fea57f7b6b 100644 --- a/docs/system/riscv/shakti-c.rst +++ b/docs/system/riscv/shakti-c.rst @@ -45,7 +45,7 @@ Shakti SDK can be used to generate the baremetal example UART applications. Binary would be generated in: software/examples/uart_applns/loopback/output/loopback.shakti -You could also download the precompiled example applicatons using below +You could also download the precompiled example applications using below commands. .. code-block:: bash diff --git a/docs/system/tls.rst b/docs/system/tls.rst index b0973afe1b..1a04674362 100644 --- a/docs/system/tls.rst +++ b/docs/system/tls.rst @@ -311,7 +311,7 @@ containing one or more usernames and random keys:: mkdir -m 0700 /tmp/keys psktool -u rich -p /tmp/keys/keys.psk -TLS-enabled servers such as qemu-nbd can use this directory like so:: +TLS-enabled servers such as ``qemu-nbd`` can use this directory like so:: qemu-nbd \ -t -x / \ diff --git a/docs/throttle.txt b/docs/throttle.txt index b5b78b7326..0a0453a5ee 100644 --- a/docs/throttle.txt +++ b/docs/throttle.txt @@ -273,11 +273,9 @@ A group can be created using the object-add QMP function: "arguments": { "qom-type": "throttle-group", "id": "group0", - "props": { - "limits" : { - "iops-total": 1000 - "bps-write": 2097152 - } + "limits" : { + "iops-total": 1000, + "bps-write": 2097152 } } } diff --git a/docs/tools/qemu-img.rst b/docs/tools/qemu-img.rst index c0a4443146..d663dd92bd 100644 --- a/docs/tools/qemu-img.rst +++ b/docs/tools/qemu-img.rst @@ -127,9 +127,9 @@ by the used format or see the format descriptions below for details. .. option:: -S SIZE Indicates the consecutive number of bytes that must contain only zeros - for qemu-img to create a sparse image during conversion. This value is rounded - down to the nearest 512 bytes. You may use the common size suffixes like - ``k`` for kilobytes. + for ``qemu-img`` to create a sparse image during conversion. This value is + rounded down to the nearest 512 bytes. You may use the common size suffixes + like ``k`` for kilobytes. .. option:: -t CACHE @@ -431,7 +431,7 @@ Command description: suppressed from the destination image. *SPARSE_SIZE* indicates the consecutive number of bytes (defaults to 4k) - that must contain only zeros for qemu-img to create a sparse image during + that must contain only zeros for ``qemu-img`` to create a sparse image during conversion. If *SPARSE_SIZE* is 0, the source will not be scanned for unallocated or zero sectors, and the destination image will always be fully allocated. @@ -447,7 +447,7 @@ Command description: If the ``-n`` option is specified, the target volume creation will be skipped. This is useful for formats such as ``rbd`` if the target volume has already been created with site specific options that cannot - be supplied through qemu-img. + be supplied through ``qemu-img``. Out of order writes can be enabled with ``-W`` to improve performance. This is only recommended for preallocated devices like host devices or other @@ -472,7 +472,7 @@ Command description: If the option *BACKING_FILE* is specified, then the image will record only the differences from *BACKING_FILE*. No size needs to be specified in this case. *BACKING_FILE* will never be modified unless you use the - ``commit`` monitor command (or qemu-img commit). + ``commit`` monitor command (or ``qemu-img commit``). If a relative path name is given, the backing file is looked up relative to the directory containing *FILENAME*. @@ -684,7 +684,7 @@ Command description: Safe mode This is the default mode and performs a real rebase operation. The - new backing file may differ from the old one and qemu-img rebase + new backing file may differ from the old one and ``qemu-img rebase`` will take care of keeping the guest-visible content of *FILENAME* unchanged. @@ -697,7 +697,7 @@ Command description: exists. Unsafe mode - qemu-img uses the unsafe mode if ``-u`` is specified. In this + ``qemu-img`` uses the unsafe mode if ``-u`` is specified. In this mode, only the backing file name and format of *FILENAME* is changed without any checks on the file contents. The user must take care of specifying the correct new backing file, or the guest-visible @@ -735,7 +735,7 @@ Command description: sizes accordingly. Failure to do so will result in data loss! When shrinking images, the ``--shrink`` option must be given. This informs - qemu-img that the user acknowledges all loss of data beyond the truncated + ``qemu-img`` that the user acknowledges all loss of data beyond the truncated image's end. After using this command to grow a disk image, you must use file system and diff --git a/docs/tools/qemu-nbd.rst b/docs/tools/qemu-nbd.rst index 56e54cd441..6031f96893 100644 --- a/docs/tools/qemu-nbd.rst +++ b/docs/tools/qemu-nbd.rst @@ -31,14 +31,14 @@ driver options if ``--image-opts`` is specified. *dev* is an NBD device. -.. option:: --object type,id=ID,...props... +.. option:: --object type,id=ID,... Define a new instance of the *type* object class identified by *ID*. See the :manpage:`qemu(1)` manual page for full details of the properties supported. The common object types that it makes sense to define are the ``secret`` object, which is used to supply passwords and/or encryption keys, and the ``tls-creds`` object, which is used to supply TLS - credentials for the qemu-nbd server or client. + credentials for the ``qemu-nbd`` server or client. .. option:: -p, --port=PORT @@ -238,7 +238,7 @@ daemon: Expose the guest-visible contents of a qcow2 file via a block device /dev/nbd0 (and possibly creating /dev/nbd0p1 and friends for partitions found within), then disconnect the device when done. -Access to bind qemu-nbd to an /dev/nbd device generally requires root +Access to bind ``qemu-nbd`` to a /dev/nbd device generally requires root privileges, and may also require the execution of ``modprobe nbd`` to enable the kernel NBD client module. *CAUTION*: Do not use this method to mount filesystems from an untrusted guest image - a diff --git a/docs/tools/qemu-storage-daemon.rst b/docs/tools/qemu-storage-daemon.rst index b8ef4486f1..3e5a9dc032 100644 --- a/docs/tools/qemu-storage-daemon.rst +++ b/docs/tools/qemu-storage-daemon.rst @@ -10,9 +10,10 @@ Synopsis Description ----------- -qemu-storage-daemon provides disk image functionality from QEMU, qemu-img, and -qemu-nbd in a long-running process controlled via QMP commands without running -a virtual machine. It can export disk images, run block job operations, and +``qemu-storage-daemon`` provides disk image functionality from QEMU, +``qemu-img``, and ``qemu-nbd`` in a long-running process controlled via QMP +commands without running a virtual machine. +It can export disk images, run block job operations, and perform other disk-related operations. The daemon is controlled via a QMP monitor and initial configuration from the command-line. diff --git a/docs/tools/virtiofsd.rst b/docs/tools/virtiofsd.rst index cc31402830..07ac0be551 100644 --- a/docs/tools/virtiofsd.rst +++ b/docs/tools/virtiofsd.rst @@ -136,8 +136,8 @@ Extended attribute (xattr) mapping By default the name of xattr's used by the client are passed through to the server file system. This can be a problem where either those xattr names are used by something on the server (e.g. selinux client/server confusion) or if the -virtiofsd is running in a container with restricted privileges where it cannot -access some attributes. +``virtiofsd`` is running in a container with restricted privileges where it +cannot access some attributes. Mapping syntax ~~~~~~~~~~~~~~ diff --git a/docs/u2f.txt b/docs/u2f.txt index 8f44994818..7f5813a0b7 100644 --- a/docs/u2f.txt +++ b/docs/u2f.txt @@ -21,7 +21,7 @@ The second factor is materialized by a device implementing the U2F protocol. In case of a USB U2F security key, it is a USB HID device that implements the U2F protocol. -In Qemu, the USB U2F key device offers a dedicated support of U2F, allowing +In QEMU, the USB U2F key device offers a dedicated support of U2F, allowing guest USB FIDO/U2F security keys operating in two possible modes: pass-through and emulated. diff --git a/gdbstub.c b/gdbstub.c index 23baaef40e..141d7bc4ec 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -94,7 +94,7 @@ static inline int cpu_gdb_index(CPUState *cpu) { #if defined(CONFIG_USER_ONLY) TaskState *ts = (TaskState *) cpu->opaque; - return ts->ts_tid; + return ts ? ts->ts_tid : -1; #else return cpu->cpu_index + 1; #endif diff --git a/hw/acpi/pcihp.c b/hw/acpi/pcihp.c index f610a25d2e..30405b5113 100644 --- a/hw/acpi/pcihp.c +++ b/hw/acpi/pcihp.c @@ -222,9 +222,27 @@ static void acpi_pcihp_eject_slot(AcpiPciHpState *s, unsigned bsel, unsigned slo PCIDevice *dev = PCI_DEVICE(qdev); if (PCI_SLOT(dev->devfn) == slot) { if (!acpi_pcihp_pc_no_hotplug(s, dev)) { - hotplug_ctrl = qdev_get_hotplug_handler(qdev); - hotplug_handler_unplug(hotplug_ctrl, qdev, &error_abort); - object_unparent(OBJECT(qdev)); + /* + * partially_hotplugged is used by virtio-net failover: + * failover has asked the guest OS to unplug the device + * but we need to keep some references to the device + * to be able to plug it back in case of failure so + * we don't execute hotplug_handler_unplug(). + */ + if (dev->partially_hotplugged) { + /* + * pending_deleted_event is set to true when + * virtio-net failover asks to unplug the device, + * and set to false here when the operation is done + * This is used by the migration loop to detect the + * end of the operation and really start the migration. + */ + qdev->pending_deleted_event = false; + } else { + hotplug_ctrl = qdev_get_hotplug_handler(qdev); + hotplug_handler_unplug(hotplug_ctrl, qdev, &error_abort); + object_unparent(OBJECT(qdev)); + } } } } @@ -396,6 +414,12 @@ void acpi_pcihp_device_unplug_request_cb(HotplugHandler *hotplug_dev, return; } + /* + * pending_deleted_event is used by virtio-net failover to detect the + * end of the unplug operation, the flag is set to false in + * acpi_pcihp_eject_slot() when the operation is completed. + */ + pdev->qdev.pending_deleted_event = true; s->acpi_pcihp_pci_status[bsel].down |= (1U << slot); acpi_send_event(DEVICE(hotplug_dev), ACPI_PCI_HOTPLUG_STATUS); } diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 369552ad45..30da05dfe0 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -49,6 +49,7 @@ #include "sysemu/runstate.h" #include "sysemu/tpm.h" #include "sysemu/kvm.h" +#include "sysemu/hvf.h" #include "hw/loader.h" #include "qapi/error.h" #include "qemu/bitops.h" @@ -1969,15 +1970,17 @@ static void machvirt_init(MachineState *machine) exit(1); } - if (vms->virt && kvm_enabled()) { - error_report("mach-virt: KVM does not support providing " - "Virtualization extensions to the guest CPU"); + if (vms->virt && (kvm_enabled() || hvf_enabled())) { + error_report("mach-virt: %s does not support providing " + "Virtualization extensions to the guest CPU", + kvm_enabled() ? "KVM" : "HVF"); exit(1); } - if (vms->mte && kvm_enabled()) { - error_report("mach-virt: KVM does not support providing " - "MTE to the guest CPU"); + if (vms->mte && (kvm_enabled() || hvf_enabled())) { + error_report("mach-virt: %s does not support providing " + "MTE to the guest CPU", + kvm_enabled() ? "KVM" : "HVF"); exit(1); } diff --git a/hw/block/fdc.c b/hw/block/fdc.c index fa933cd326..21d18ac2e3 100644 --- a/hw/block/fdc.c +++ b/hw/block/fdc.c @@ -61,6 +61,12 @@ } while (0) +/* Anonymous BlockBackend for empty drive */ +static BlockBackend *blk_create_empty_drive(void) +{ + return blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL); +} + /********************************************************/ /* qdev floppy bus */ @@ -486,8 +492,7 @@ static void floppy_drive_realize(DeviceState *qdev, Error **errp) } if (!dev->conf.blk) { - /* Anonymous BlockBackend for an empty drive */ - dev->conf.blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL); + dev->conf.blk = blk_create_empty_drive(); ret = blk_attach_dev(dev->conf.blk, qdev); assert(ret == 0); @@ -1161,7 +1166,19 @@ static FDrive *get_drv(FDCtrl *fdctrl, int unit) static FDrive *get_cur_drv(FDCtrl *fdctrl) { - return get_drv(fdctrl, fdctrl->cur_drv); + FDrive *cur_drv = get_drv(fdctrl, fdctrl->cur_drv); + + if (!cur_drv->blk) { + /* + * Kludge: empty drive line selected. Create an anonymous + * BlockBackend to avoid NULL deref with various BlockBackend + * API calls within this model (CVE-2021-20196). + * Due to the controller QOM model limitations, we don't + * attach the created to the controller device. + */ + cur_drv->blk = blk_create_empty_drive(); + } + return cur_drv; } /* Status A register : 0x00 (read-only) */ diff --git a/hw/char/escc.c b/hw/char/escc.c index 0fce4f6324..8755d8d34f 100644 --- a/hw/char/escc.c +++ b/hw/char/escc.c @@ -354,6 +354,17 @@ static void escc_reset(DeviceState *d) cs->rregs[j] = 0; cs->wregs[j] = 0; } + + /* + * ...but there is an exception. The "Transmit Interrupts and Transmit + * Buffer Empty Bit" section on page 50 of the ESCC datasheet says of + * the STATUS_TXEMPTY bit in R_STATUS: "After a hardware reset + * (including a hardware reset by software), or a channel reset, this + * bit is set to 1". The Sun PROM checks this bit early on startup and + * gets stuck in an infinite loop if it is not set. + */ + cs->rregs[R_STATUS] |= STATUS_TXEMPTY; + escc_reset_chn(cs); } } @@ -575,6 +586,20 @@ static void escc_mem_write(void *opaque, hwaddr addr, s->wregs[s->reg] = val; break; case W_TXCTRL1: + s->wregs[s->reg] = val; + /* + * The ESCC datasheet states that SPEC_ALLSENT is always set in + * sync mode, and set in async mode when all characters have + * cleared the transmitter. Since writes to SERIAL_DATA use the + * blocking qemu_chr_fe_write_all() function to write each + * character, the guest can never see the state when async data + * is in the process of being transmitted so we can set this bit + * unconditionally regardless of the state of the W_TXCTRL1 mode + * bits. + */ + s->rregs[R_SPEC] |= SPEC_ALLSENT; + escc_update_parameters(s); + break; case W_TXCTRL2: s->wregs[s->reg] = val; escc_update_parameters(s); diff --git a/hw/i386/intel_iommu.c b/hw/i386/intel_iommu.c index 294499ee20..f584449d8d 100644 --- a/hw/i386/intel_iommu.c +++ b/hw/i386/intel_iommu.c @@ -3629,6 +3629,12 @@ static void vtd_init(IntelIOMMUState *s) vtd_spte_rsvd_large[3] = VTD_SPTE_LPAGE_L3_RSVD_MASK(s->aw_bits, x86_iommu->dt_supported); + if (s->scalable_mode) { + vtd_spte_rsvd[1] &= ~VTD_SPTE_SNP; + vtd_spte_rsvd_large[2] &= ~VTD_SPTE_SNP; + vtd_spte_rsvd_large[3] &= ~VTD_SPTE_SNP; + } + if (x86_iommu_ir_supported(x86_iommu)) { s->ecap |= VTD_ECAP_IR | VTD_ECAP_MHMV; if (s->intr_eim == ON_OFF_AUTO_ON) { diff --git a/hw/i386/intel_iommu_internal.h b/hw/i386/intel_iommu_internal.h index 3d5487fe2c..a6c788049b 100644 --- a/hw/i386/intel_iommu_internal.h +++ b/hw/i386/intel_iommu_internal.h @@ -388,6 +388,8 @@ typedef union VTDInvDesc VTDInvDesc; #define VTD_INV_DESC_DEVICE_IOTLB_RSVD_LO 0xffff0000ffe0fff8 /* Rsvd field masks for spte */ +#define VTD_SPTE_SNP 0x800ULL + #define VTD_SPTE_PAGE_L1_RSVD_MASK(aw, dt_supported) \ dt_supported ? \ (0x800ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM | VTD_SL_TM)) : \ diff --git a/hw/i386/microvm-dt.c b/hw/i386/microvm-dt.c index 875ba91963..9c3c4995b4 100644 --- a/hw/i386/microvm-dt.c +++ b/hw/i386/microvm-dt.c @@ -143,6 +143,8 @@ static void dt_add_pcie(MicrovmMachineState *mms) nr_pcie_buses = PCIE_ECAM_SIZE / PCIE_MMCFG_SIZE_MIN; qemu_fdt_setprop_cells(mms->fdt, nodename, "bus-range", 0, nr_pcie_buses - 1); + + g_free(nodename); } static void dt_add_ioapic(MicrovmMachineState *mms, SysBusDevice *dev) @@ -327,12 +329,17 @@ void dt_setup_microvm(MicrovmMachineState *mms) dt_setup_sys_bus(mms); /* add to fw_cfg */ - fprintf(stderr, "%s: add etc/fdt to fw_cfg\n", __func__); + if (debug) { + fprintf(stderr, "%s: add etc/fdt to fw_cfg\n", __func__); + } fw_cfg_add_file(x86ms->fw_cfg, "etc/fdt", mms->fdt, size); if (debug) { fprintf(stderr, "%s: writing microvm.fdt\n", __func__); - g_file_set_contents("microvm.fdt", mms->fdt, size, NULL); + if (!g_file_set_contents("microvm.fdt", mms->fdt, size, NULL)) { + fprintf(stderr, "%s: writing microvm.fdt failed\n", __func__); + return; + } int ret = system("dtc -I dtb -O dts microvm.fdt"); if (ret != 0) { fprintf(stderr, "%s: oops, dtc not installed?\n", __func__); diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c index c6282984b1..9f5f815db9 100644 --- a/hw/intc/arm_gicv3.c +++ b/hw/intc/arm_gicv3.c @@ -186,7 +186,9 @@ static void gicv3_redist_update_noirqset(GICv3CPUState *cs) * interrupt has reduced in priority and any other interrupt could * now be the new best one). */ - if (!seenbetter && cs->hppi.prio != 0xff && cs->hppi.irq < GIC_INTERNAL) { + if (!seenbetter && cs->hppi.prio != 0xff && + (cs->hppi.irq < GIC_INTERNAL || + cs->hppi.irq >= GICV3_LPI_INTID_START)) { gicv3_full_update_noirqset(cs->gic); } } @@ -354,7 +356,7 @@ static void arm_gicv3_post_load(GICv3State *s) * pending interrupt, but don't set IRQ or FIQ lines. */ for (i = 0; i < s->num_cpu; i++) { - gicv3_redist_update_lpi(&s->cpu[i]); + gicv3_redist_update_lpi_only(&s->cpu[i]); } gicv3_full_update_noirqset(s); /* Repopulate the cache of GICv3CPUState pointers for target CPUs */ diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c index 3fe5de8ad7..7fba931450 100644 --- a/hw/intc/arm_gicv3_cpuif.c +++ b/hw/intc/arm_gicv3_cpuif.c @@ -653,7 +653,7 @@ static uint64_t icv_iar_read(CPUARMState *env, const ARMCPRegInfo *ri) if (thisgrp == grp && icv_hppi_can_preempt(cs, lr)) { intid = ich_lr_vintid(lr); - if (intid < INTID_SECURE) { + if (!gicv3_intid_is_special(intid)) { icv_activate_irq(cs, idx, grp); } else { /* Interrupt goes from Pending to Invalid */ @@ -997,7 +997,7 @@ static uint64_t icc_iar0_read(CPUARMState *env, const ARMCPRegInfo *ri) intid = icc_hppir0_value(cs, env); } - if (!(intid >= INTID_SECURE && intid <= INTID_SPURIOUS)) { + if (!gicv3_intid_is_special(intid)) { icc_activate_irq(cs, intid); } @@ -1020,7 +1020,7 @@ static uint64_t icc_iar1_read(CPUARMState *env, const ARMCPRegInfo *ri) intid = icc_hppir1_value(cs, env); } - if (!(intid >= INTID_SECURE && intid <= INTID_SPURIOUS)) { + if (!gicv3_intid_is_special(intid)) { icc_activate_irq(cs, intid); } @@ -1265,8 +1265,7 @@ static void icv_eoir_write(CPUARMState *env, const ARMCPRegInfo *ri, trace_gicv3_icv_eoir_write(ri->crm == 8 ? 0 : 1, gicv3_redist_affid(cs), value); - if (irq >= GICV3_MAXIRQ) { - /* Also catches special interrupt numbers and LPIs */ + if (gicv3_intid_is_special(irq)) { return; } diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c index 84bcbb5f56..c929a9cb5c 100644 --- a/hw/intc/arm_gicv3_its.c +++ b/hw/intc/arm_gicv3_its.c @@ -896,13 +896,14 @@ static bool its_writel(GICv3ITSState *s, hwaddr offset, switch (offset) { case GITS_CTLR: - s->ctlr |= (value & ~(s->ctlr)); - - if (s->ctlr & ITS_CTLR_ENABLED) { + if (value & R_GITS_CTLR_ENABLED_MASK) { + s->ctlr |= ITS_CTLR_ENABLED; extract_table_params(s); extract_cmdq_params(s); s->creadr = 0; process_cmdq(s); + } else { + s->ctlr &= ~ITS_CTLR_ENABLED; } break; case GITS_CBASER: diff --git a/hw/intc/arm_gicv3_its_common.c b/hw/intc/arm_gicv3_its_common.c index 7d7f3882e7..90b85f1e25 100644 --- a/hw/intc/arm_gicv3_its_common.c +++ b/hw/intc/arm_gicv3_its_common.c @@ -50,8 +50,6 @@ static int gicv3_its_post_load(void *opaque, int version_id) static const VMStateDescription vmstate_its = { .name = "arm_gicv3_its", - .version_id = 1, - .minimum_version_id = 1, .pre_save = gicv3_its_pre_save, .post_load = gicv3_its_post_load, .priority = MIG_PRI_GICV3_ITS, diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c index 424e7e28a8..c8ff3eca08 100644 --- a/hw/intc/arm_gicv3_redist.c +++ b/hw/intc/arm_gicv3_redist.c @@ -256,9 +256,10 @@ static MemTxResult gicr_writel(GICv3CPUState *cs, hwaddr offset, cs->gicr_ctlr |= GICR_CTLR_ENABLE_LPIS; /* Check for any pending interr in pending table */ gicv3_redist_update_lpi(cs); - gicv3_redist_update(cs); } else { cs->gicr_ctlr &= ~GICR_CTLR_ENABLE_LPIS; + /* cs->hppi might have been an LPI; recalculate */ + gicv3_redist_update(cs); } } return MEMTX_OK; @@ -571,7 +572,7 @@ static void gicv3_redist_check_lpi_priority(GICv3CPUState *cs, int irq) } } -void gicv3_redist_update_lpi(GICv3CPUState *cs) +void gicv3_redist_update_lpi_only(GICv3CPUState *cs) { /* * This function scans the LPI pending table and for each pending @@ -614,6 +615,12 @@ void gicv3_redist_update_lpi(GICv3CPUState *cs) } } +void gicv3_redist_update_lpi(GICv3CPUState *cs) +{ + gicv3_redist_update_lpi_only(cs); + gicv3_redist_update(cs); +} + void gicv3_redist_lpi_pending(GICv3CPUState *cs, int irq, int level) { /* @@ -651,6 +658,7 @@ void gicv3_redist_lpi_pending(GICv3CPUState *cs, int irq, int level) */ if (level) { gicv3_redist_check_lpi_priority(cs, irq); + gicv3_redist_update(cs); } else { if (irq == cs->hpplpi.irq) { gicv3_redist_update_lpi(cs); @@ -673,8 +681,6 @@ void gicv3_redist_process_lpi(GICv3CPUState *cs, int irq, int level) /* set/clear the pending bit for this irq */ gicv3_redist_lpi_pending(cs, irq, level); - - gicv3_redist_update(cs); } void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level) diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h index a0369dace7..b9c37453b0 100644 --- a/hw/intc/gicv3_internal.h +++ b/hw/intc/gicv3_internal.h @@ -411,6 +411,19 @@ FIELD(MAPC, RDBASE, 16, 32) /* Functions internal to the emulated GICv3 */ +/** + * gicv3_intid_is_special: + * @intid: interrupt ID + * + * Return true if @intid is a special interrupt ID (1020 to + * 1023 inclusive). This corresponds to the GIC spec pseudocode + * IsSpecial() function. + */ +static inline bool gicv3_intid_is_special(int intid) +{ + return intid >= INTID_SECURE && intid <= INTID_SPURIOUS; +} + /** * gicv3_redist_update: * @cs: GICv3CPUState for this redistributor @@ -463,7 +476,24 @@ void gicv3_dist_set_irq(GICv3State *s, int irq, int level); void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level); void gicv3_redist_process_lpi(GICv3CPUState *cs, int irq, int level); void gicv3_redist_lpi_pending(GICv3CPUState *cs, int irq, int level); +/** + * gicv3_redist_update_lpi: + * @cs: GICv3CPUState + * + * Scan the LPI pending table and recalculate the highest priority + * pending LPI and also the overall highest priority pending interrupt. + */ void gicv3_redist_update_lpi(GICv3CPUState *cs); +/** + * gicv3_redist_update_lpi_only: + * @cs: GICv3CPUState + * + * Scan the LPI pending table and recalculate cs->hpplpi only, + * without calling gicv3_redist_update() to recalculate the overall + * highest priority pending interrupt. This should be called after + * an incoming migration has loaded new state. + */ +void gicv3_redist_update_lpi_only(GICv3CPUState *cs); void gicv3_redist_send_sgi(GICv3CPUState *cs, int grp, int irq, bool ns); void gicv3_init_cpuif(GICv3State *s); diff --git a/hw/misc/macio/pmu.c b/hw/misc/macio/pmu.c index 4ad4f50e08..eb39c64694 100644 --- a/hw/misc/macio/pmu.c +++ b/hw/misc/macio/pmu.c @@ -718,6 +718,7 @@ static const VMStateDescription vmstate_pmu = { }, .subsections = (const VMStateDescription * []) { &vmstate_pmu_adb, + NULL } }; diff --git a/hw/misc/sifive_u_otp.c b/hw/misc/sifive_u_otp.c index 18aa0bd55d..52fdb750c0 100644 --- a/hw/misc/sifive_u_otp.c +++ b/hw/misc/sifive_u_otp.c @@ -209,7 +209,14 @@ static void sifive_u_otp_realize(DeviceState *dev, Error **errp) TYPE_SIFIVE_U_OTP, SIFIVE_U_OTP_REG_SIZE); sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio); - dinfo = drive_get_next(IF_NONE); + dinfo = drive_get_next(IF_PFLASH); + if (!dinfo) { + dinfo = drive_get_next(IF_NONE); + if (dinfo) { + warn_report("using \"-drive if=none\" for the OTP is deprecated, " + "use \"-drive if=pflash\" instead."); + } + } if (dinfo) { int ret; uint64_t perm; @@ -235,14 +242,10 @@ static void sifive_u_otp_realize(DeviceState *dev, Error **errp) if (blk_pread(s->blk, 0, s->fuse, filesize) != filesize) { error_setg(errp, "failed to read the initial flash content"); + return; } } } -} - -static void sifive_u_otp_reset(DeviceState *dev) -{ - SiFiveUOTPState *s = SIFIVE_U_OTP(dev); /* Initialize all fuses' initial value to 0xFFs */ memset(s->fuse, 0xff, sizeof(s->fuse)); @@ -259,13 +262,15 @@ static void sifive_u_otp_reset(DeviceState *dev) serial_data = s->serial; if (blk_pwrite(s->blk, index * SIFIVE_U_OTP_FUSE_WORD, &serial_data, SIFIVE_U_OTP_FUSE_WORD, 0) < 0) { - error_report("write error index<%d>", index); + error_setg(errp, "failed to write index<%d>", index); + return; } serial_data = ~(s->serial); if (blk_pwrite(s->blk, (index + 1) * SIFIVE_U_OTP_FUSE_WORD, &serial_data, SIFIVE_U_OTP_FUSE_WORD, 0) < 0) { - error_report("write error index<%d>", index + 1); + error_setg(errp, "failed to write index<%d>", index + 1); + return; } } @@ -279,7 +284,6 @@ static void sifive_u_otp_class_init(ObjectClass *klass, void *data) device_class_set_props(dc, sifive_u_otp_properties); dc->realize = sifive_u_otp_realize; - dc->reset = sifive_u_otp_reset; } static const TypeInfo sifive_u_otp_info = { diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index c5ed266337..d7d73a31e4 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -929,8 +929,8 @@ void pcie_add_capability(PCIDevice *dev, uint16_t offset, uint16_t size) { assert(offset >= PCI_CONFIG_SPACE_SIZE); - assert(offset < offset + size); - assert(offset + size <= PCIE_CONFIG_SPACE_SIZE); + assert(offset < (uint16_t)(offset + size)); + assert((uint16_t)(offset + size) <= PCIE_CONFIG_SPACE_SIZE); assert(size >= 8); assert(pci_is_express(dev)); diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 163c90388a..3b5fd749be 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1414,7 +1414,7 @@ void spapr_store_hpte(PowerPCCPU *cpu, hwaddr ptex, kvmppc_write_hpte(ptex, pte0, pte1); } else { if (pte0 & HPTE64_V_VALID) { - stq_p(spapr->htab + offset + HASH_PTE_SIZE_64 / 2, pte1); + stq_p(spapr->htab + offset + HPTE64_DW1, pte1); /* * When setting valid, we write PTE1 first. This ensures * proper synchronization with the reading code in @@ -1430,7 +1430,7 @@ void spapr_store_hpte(PowerPCCPU *cpu, hwaddr ptex, * ppc_hash64_pteg_search() */ smp_wmb(); - stq_p(spapr->htab + offset + HASH_PTE_SIZE_64 / 2, pte1); + stq_p(spapr->htab + offset + HPTE64_DW1, pte1); } } } @@ -1438,7 +1438,7 @@ void spapr_store_hpte(PowerPCCPU *cpu, hwaddr ptex, static void spapr_hpte_set_c(PPCVirtualHypervisor *vhyp, hwaddr ptex, uint64_t pte1) { - hwaddr offset = ptex * HASH_PTE_SIZE_64 + 15; + hwaddr offset = ptex * HASH_PTE_SIZE_64 + HPTE64_DW1_C; SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); if (!spapr->htab) { @@ -1454,7 +1454,7 @@ static void spapr_hpte_set_c(PPCVirtualHypervisor *vhyp, hwaddr ptex, static void spapr_hpte_set_r(PPCVirtualHypervisor *vhyp, hwaddr ptex, uint64_t pte1) { - hwaddr offset = ptex * HASH_PTE_SIZE_64 + 14; + hwaddr offset = ptex * HASH_PTE_SIZE_64 + HPTE64_DW1_R; SpaprMachineState *spapr = SPAPR_MACHINE(vhyp); if (!spapr->htab) { diff --git a/hw/ppc/spapr_softmmu.c b/hw/ppc/spapr_softmmu.c index f8924270ef..4ee03c83e4 100644 --- a/hw/ppc/spapr_softmmu.c +++ b/hw/ppc/spapr_softmmu.c @@ -426,7 +426,7 @@ static void new_hpte_store(void *htab, uint64_t pteg, int slot, addr += slot * HASH_PTE_SIZE_64; stq_p(addr, pte0); - stq_p(addr + HASH_PTE_SIZE_64 / 2, pte1); + stq_p(addr + HPTE64_DW1, pte1); } static int rehash_hpte(PowerPCCPU *cpu, diff --git a/hw/scsi/esp.c b/hw/scsi/esp.c index 84f935b549..58d0edbd56 100644 --- a/hw/scsi/esp.c +++ b/hw/scsi/esp.c @@ -894,6 +894,7 @@ void esp_hard_reset(ESPState *s) memset(s->wregs, 0, ESP_REGS); s->tchi_written = 0; s->ti_size = 0; + s->async_len = 0; fifo8_reset(&s->fifo); fifo8_reset(&s->cmdfifo); s->dma = 0; diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c index c6962fcbfe..9a4f491b54 100644 --- a/hw/virtio/virtio-balloon.c +++ b/hw/virtio/virtio-balloon.c @@ -231,7 +231,7 @@ static void balloon_stats_poll_cb(void *opaque) return; } - virtqueue_push(s->svq, s->stats_vq_elem, s->stats_vq_offset); + virtqueue_push(s->svq, s->stats_vq_elem, 0); virtio_notify(vdev, s->svq); g_free(s->stats_vq_elem); s->stats_vq_elem = NULL; @@ -438,7 +438,7 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq) memory_region_unref(section.mr); } - virtqueue_push(vq, elem, offset); + virtqueue_push(vq, elem, 0); virtio_notify(vdev, vq); g_free(elem); virtio_balloon_pbp_free(&pbp); @@ -510,6 +510,7 @@ static bool get_free_page_hints(VirtIOBalloon *dev) VirtIODevice *vdev = VIRTIO_DEVICE(dev); VirtQueue *vq = dev->free_page_vq; bool ret = true; + int i; while (dev->block_iothread) { qemu_cond_wait(&dev->free_page_cond, &dev->free_page_lock); @@ -544,12 +545,14 @@ static bool get_free_page_hints(VirtIOBalloon *dev) } if (elem->in_num && dev->free_page_hint_status == FREE_PAGE_HINT_S_START) { - qemu_guest_free_page_hint(elem->in_sg[0].iov_base, - elem->in_sg[0].iov_len); + for (i = 0; i < elem->in_num; i++) { + qemu_guest_free_page_hint(elem->in_sg[i].iov_base, + elem->in_sg[i].iov_len); + } } out: - virtqueue_push(vq, elem, 1); + virtqueue_push(vq, elem, 0); g_free(elem); return ret; } diff --git a/hw/virtio/virtio-mmio.c b/hw/virtio/virtio-mmio.c index 7b3ebca178..72da12fea5 100644 --- a/hw/virtio/virtio-mmio.c +++ b/hw/virtio/virtio-mmio.c @@ -817,6 +817,17 @@ static char *virtio_mmio_bus_get_dev_path(DeviceState *dev) return path; } +static void virtio_mmio_vmstate_change(DeviceState *d, bool running) +{ + VirtIOMMIOProxy *proxy = VIRTIO_MMIO(d); + + if (running) { + virtio_mmio_start_ioeventfd(proxy); + } else { + virtio_mmio_stop_ioeventfd(proxy); + } +} + static void virtio_mmio_bus_class_init(ObjectClass *klass, void *data) { BusClass *bus_class = BUS_CLASS(klass); @@ -832,6 +843,7 @@ static void virtio_mmio_bus_class_init(ObjectClass *klass, void *data) k->ioeventfd_enabled = virtio_mmio_ioeventfd_enabled; k->ioeventfd_assign = virtio_mmio_ioeventfd_assign; k->pre_plugged = virtio_mmio_pre_plugged; + k->vmstate_change = virtio_mmio_vmstate_change; k->has_variable_vring_alignment = true; bus_class->max_dev = 1; bus_class->get_dev_path = virtio_mmio_bus_get_dev_path; diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 6bb2a0f7ec..35d8e93976 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -503,6 +503,7 @@ struct TranslationBlock { #define CF_USE_ICOUNT 0x00020000 #define CF_INVALID 0x00040000 /* TB is stale. Set with @jmp_lock held */ #define CF_PARALLEL 0x00080000 /* Generate code for a parallel context */ +#define CF_NOIRQ 0x00100000 /* Generate an uninterruptible TB */ #define CF_CLUSTER_MASK 0xff000000 /* Top 8 bits are cluster ID */ #define CF_CLUSTER_SHIFT 24 diff --git a/include/exec/gen-icount.h b/include/exec/gen-icount.h index 610cba58fe..c57204ddad 100644 --- a/include/exec/gen-icount.h +++ b/include/exec/gen-icount.h @@ -21,7 +21,6 @@ static inline void gen_tb_start(const TranslationBlock *tb) { TCGv_i32 count; - tcg_ctx->exitreq_label = gen_new_label(); if (tb_cflags(tb) & CF_USE_ICOUNT) { count = tcg_temp_local_new_i32(); } else { @@ -42,7 +41,19 @@ static inline void gen_tb_start(const TranslationBlock *tb) icount_start_insn = tcg_last_op(); } - tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, tcg_ctx->exitreq_label); + /* + * Emit the check against icount_decr.u32 to see if we should exit + * unless we suppress the check with CF_NOIRQ. If we are using + * icount and have suppressed interruption the higher level code + * should have ensured we don't run more instructions than the + * budget. + */ + if (tb_cflags(tb) & CF_NOIRQ) { + tcg_ctx->exitreq_label = NULL; + } else { + tcg_ctx->exitreq_label = gen_new_label(); + tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, tcg_ctx->exitreq_label); + } if (tb_cflags(tb) & CF_USE_ICOUNT) { tcg_gen_st16_i32(count, cpu_env, @@ -74,8 +85,10 @@ static inline void gen_tb_end(const TranslationBlock *tb, int num_insns) tcgv_i32_arg(tcg_constant_i32(num_insns))); } - gen_set_label(tcg_ctx->exitreq_label); - tcg_gen_exit_tb(tb, TB_EXIT_REQUESTED); + if (tcg_ctx->exitreq_label) { + gen_set_label(tcg_ctx->exitreq_label); + tcg_gen_exit_tb(tb, TB_EXIT_REQUESTED); + } } #endif diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 5da8c02d08..767f54c76d 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -3254,9 +3254,13 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info) * Otherwise, allocate a private page to hold them. */ if (TARGET_ARCH_HAS_SIGTRAMP_PAGE) { - abi_ulong tramp_page = target_mmap(0, TARGET_PAGE_SIZE, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON, -1, 0); + abi_long tramp_page = target_mmap(0, TARGET_PAGE_SIZE, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + if (tramp_page == -1) { + return -errno; + } + setup_sigtramp(tramp_page); target_mprotect(tramp_page, TARGET_PAGE_SIZE, PROT_READ | PROT_EXEC); } diff --git a/linux-user/host/aarch64/host-signal.h b/linux-user/host/aarch64/host-signal.h index 0c0b08383a..9770b36dc1 100644 --- a/linux-user/host/aarch64/host-signal.h +++ b/linux-user/host/aarch64/host-signal.h @@ -35,6 +35,11 @@ static inline uintptr_t host_signal_pc(ucontext_t *uc) return uc->uc_mcontext.pc; } +static inline void host_signal_set_pc(ucontext_t *uc, uintptr_t pc) +{ + uc->uc_mcontext.pc = pc; +} + static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc) { struct _aarch64_ctx *hdr; diff --git a/linux-user/host/aarch64/hostdep.h b/linux-user/host/aarch64/hostdep.h index a8d41a21ad..39299d798a 100644 --- a/linux-user/host/aarch64/hostdep.h +++ b/linux-user/host/aarch64/hostdep.h @@ -15,24 +15,4 @@ /* We have a safe-syscall.inc.S */ #define HAVE_SAFE_SYSCALL -#ifndef __ASSEMBLER__ - -/* These are defined by the safe-syscall.inc.S file */ -extern char safe_syscall_start[]; -extern char safe_syscall_end[]; - -/* Adjust the signal context to rewind out of safe-syscall if we're in it */ -static inline void rewind_if_in_safe_syscall(void *puc) -{ - ucontext_t *uc = puc; - __u64 *pcreg = &uc->uc_mcontext.pc; - - if (*pcreg > (uintptr_t)safe_syscall_start - && *pcreg < (uintptr_t)safe_syscall_end) { - *pcreg = (uintptr_t)safe_syscall_start; - } -} - -#endif /* __ASSEMBLER__ */ - #endif diff --git a/linux-user/host/alpha/host-signal.h b/linux-user/host/alpha/host-signal.h index e080be412f..f4c942948a 100644 --- a/linux-user/host/alpha/host-signal.h +++ b/linux-user/host/alpha/host-signal.h @@ -16,6 +16,11 @@ static inline uintptr_t host_signal_pc(ucontext_t *uc) return uc->uc_mcontext.sc_pc; } +static inline void host_signal_set_pc(ucontext_t *uc, uintptr_t pc) +{ + uc->uc_mcontext.sc_pc = pc; +} + static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc) { uint32_t *pc = (uint32_t *)host_signal_pc(uc); diff --git a/linux-user/host/arm/host-signal.h b/linux-user/host/arm/host-signal.h index efb165c0c5..6c095773c0 100644 --- a/linux-user/host/arm/host-signal.h +++ b/linux-user/host/arm/host-signal.h @@ -16,6 +16,11 @@ static inline uintptr_t host_signal_pc(ucontext_t *uc) return uc->uc_mcontext.arm_pc; } +static inline void host_signal_set_pc(ucontext_t *uc, uintptr_t pc) +{ + uc->uc_mcontext.arm_pc = pc; +} + static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc) { /* diff --git a/linux-user/host/arm/hostdep.h b/linux-user/host/arm/hostdep.h index 9276fe6ceb..86b137875a 100644 --- a/linux-user/host/arm/hostdep.h +++ b/linux-user/host/arm/hostdep.h @@ -15,24 +15,4 @@ /* We have a safe-syscall.inc.S */ #define HAVE_SAFE_SYSCALL -#ifndef __ASSEMBLER__ - -/* These are defined by the safe-syscall.inc.S file */ -extern char safe_syscall_start[]; -extern char safe_syscall_end[]; - -/* Adjust the signal context to rewind out of safe-syscall if we're in it */ -static inline void rewind_if_in_safe_syscall(void *puc) -{ - ucontext_t *uc = puc; - unsigned long *pcreg = &uc->uc_mcontext.arm_pc; - - if (*pcreg > (uintptr_t)safe_syscall_start - && *pcreg < (uintptr_t)safe_syscall_end) { - *pcreg = (uintptr_t)safe_syscall_start; - } -} - -#endif /* __ASSEMBLER__ */ - #endif diff --git a/linux-user/host/i386/host-signal.h b/linux-user/host/i386/host-signal.h index 4c8eef99ce..abe1ece5c9 100644 --- a/linux-user/host/i386/host-signal.h +++ b/linux-user/host/i386/host-signal.h @@ -16,6 +16,11 @@ static inline uintptr_t host_signal_pc(ucontext_t *uc) return uc->uc_mcontext.gregs[REG_EIP]; } +static inline void host_signal_set_pc(ucontext_t *uc, uintptr_t pc) +{ + uc->uc_mcontext.gregs[REG_EIP] = pc; +} + static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc) { return uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe diff --git a/linux-user/host/i386/hostdep.h b/linux-user/host/i386/hostdep.h index 073be74d87..ce7136501f 100644 --- a/linux-user/host/i386/hostdep.h +++ b/linux-user/host/i386/hostdep.h @@ -15,24 +15,4 @@ /* We have a safe-syscall.inc.S */ #define HAVE_SAFE_SYSCALL -#ifndef __ASSEMBLER__ - -/* These are defined by the safe-syscall.inc.S file */ -extern char safe_syscall_start[]; -extern char safe_syscall_end[]; - -/* Adjust the signal context to rewind out of safe-syscall if we're in it */ -static inline void rewind_if_in_safe_syscall(void *puc) -{ - ucontext_t *uc = puc; - greg_t *pcreg = &uc->uc_mcontext.gregs[REG_EIP]; - - if (*pcreg > (uintptr_t)safe_syscall_start - && *pcreg < (uintptr_t)safe_syscall_end) { - *pcreg = (uintptr_t)safe_syscall_start; - } -} - -#endif /* __ASSEMBLER__ */ - #endif diff --git a/linux-user/host/mips/host-signal.h b/linux-user/host/mips/host-signal.h index ef341f7c20..c666ed8c3f 100644 --- a/linux-user/host/mips/host-signal.h +++ b/linux-user/host/mips/host-signal.h @@ -16,6 +16,11 @@ static inline uintptr_t host_signal_pc(ucontext_t *uc) return uc->uc_mcontext.pc; } +static inline void host_signal_set_pc(ucontext_t *uc, uintptr_t pc) +{ + uc->uc_mcontext.pc = pc; +} + #if defined(__misp16) || defined(__mips_micromips) #error "Unsupported encoding" #endif diff --git a/linux-user/host/ppc/host-signal.h b/linux-user/host/ppc/host-signal.h index a491c413dc..1d8e658ff7 100644 --- a/linux-user/host/ppc/host-signal.h +++ b/linux-user/host/ppc/host-signal.h @@ -16,6 +16,11 @@ static inline uintptr_t host_signal_pc(ucontext_t *uc) return uc->uc_mcontext.regs->nip; } +static inline void host_signal_set_pc(ucontext_t *uc, uintptr_t pc) +{ + uc->uc_mcontext.regs->nip = pc; +} + static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc) { return uc->uc_mcontext.regs->trap != 0x400 diff --git a/linux-user/host/ppc64/hostdep.h b/linux-user/host/ppc64/hostdep.h index 98979ad917..0c290dd904 100644 --- a/linux-user/host/ppc64/hostdep.h +++ b/linux-user/host/ppc64/hostdep.h @@ -15,24 +15,4 @@ /* We have a safe-syscall.inc.S */ #define HAVE_SAFE_SYSCALL -#ifndef __ASSEMBLER__ - -/* These are defined by the safe-syscall.inc.S file */ -extern char safe_syscall_start[]; -extern char safe_syscall_end[]; - -/* Adjust the signal context to rewind out of safe-syscall if we're in it */ -static inline void rewind_if_in_safe_syscall(void *puc) -{ - ucontext_t *uc = puc; - unsigned long *pcreg = &uc->uc_mcontext.gp_regs[PT_NIP]; - - if (*pcreg > (uintptr_t)safe_syscall_start - && *pcreg < (uintptr_t)safe_syscall_end) { - *pcreg = (uintptr_t)safe_syscall_start; - } -} - -#endif /* __ASSEMBLER__ */ - #endif diff --git a/linux-user/host/riscv/host-signal.h b/linux-user/host/riscv/host-signal.h index 3b168cb58b..a4f170efb0 100644 --- a/linux-user/host/riscv/host-signal.h +++ b/linux-user/host/riscv/host-signal.h @@ -16,6 +16,11 @@ static inline uintptr_t host_signal_pc(ucontext_t *uc) return uc->uc_mcontext.__gregs[REG_PC]; } +static inline void host_signal_set_pc(ucontext_t *uc, uintptr_t pc) +{ + uc->uc_mcontext.__gregs[REG_PC] = pc; +} + static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc) { /* diff --git a/linux-user/host/riscv/hostdep.h b/linux-user/host/riscv/hostdep.h index 2ba07456ae..7f67c22868 100644 --- a/linux-user/host/riscv/hostdep.h +++ b/linux-user/host/riscv/hostdep.h @@ -11,24 +11,4 @@ /* We have a safe-syscall.inc.S */ #define HAVE_SAFE_SYSCALL -#ifndef __ASSEMBLER__ - -/* These are defined by the safe-syscall.inc.S file */ -extern char safe_syscall_start[]; -extern char safe_syscall_end[]; - -/* Adjust the signal context to rewind out of safe-syscall if we're in it */ -static inline void rewind_if_in_safe_syscall(void *puc) -{ - ucontext_t *uc = puc; - unsigned long *pcreg = &uc->uc_mcontext.__gregs[REG_PC]; - - if (*pcreg > (uintptr_t)safe_syscall_start - && *pcreg < (uintptr_t)safe_syscall_end) { - *pcreg = (uintptr_t)safe_syscall_start; - } -} - -#endif /* __ASSEMBLER__ */ - #endif diff --git a/linux-user/host/s390/host-signal.h b/linux-user/host/s390/host-signal.h index 26990e4893..a524f2ab00 100644 --- a/linux-user/host/s390/host-signal.h +++ b/linux-user/host/s390/host-signal.h @@ -16,6 +16,11 @@ static inline uintptr_t host_signal_pc(ucontext_t *uc) return uc->uc_mcontext.psw.addr; } +static inline void host_signal_set_pc(ucontext_t *uc, uintptr_t pc) +{ + uc->uc_mcontext.psw.addr = pc; +} + static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc) { uint16_t *pinsn = (uint16_t *)host_signal_pc(uc); diff --git a/linux-user/host/s390x/hostdep.h b/linux-user/host/s390x/hostdep.h index 4f0171f36f..d801145854 100644 --- a/linux-user/host/s390x/hostdep.h +++ b/linux-user/host/s390x/hostdep.h @@ -15,24 +15,4 @@ /* We have a safe-syscall.inc.S */ #define HAVE_SAFE_SYSCALL -#ifndef __ASSEMBLER__ - -/* These are defined by the safe-syscall.inc.S file */ -extern char safe_syscall_start[]; -extern char safe_syscall_end[]; - -/* Adjust the signal context to rewind out of safe-syscall if we're in it */ -static inline void rewind_if_in_safe_syscall(void *puc) -{ - ucontext_t *uc = puc; - unsigned long *pcreg = &uc->uc_mcontext.psw.addr; - - if (*pcreg > (uintptr_t)safe_syscall_start - && *pcreg < (uintptr_t)safe_syscall_end) { - *pcreg = (uintptr_t)safe_syscall_start; - } -} - -#endif /* __ASSEMBLER__ */ - #endif diff --git a/linux-user/host/sparc/host-signal.h b/linux-user/host/sparc/host-signal.h index 5e71d33f8e..7342936071 100644 --- a/linux-user/host/sparc/host-signal.h +++ b/linux-user/host/sparc/host-signal.h @@ -20,6 +20,15 @@ static inline uintptr_t host_signal_pc(ucontext_t *uc) #endif } +static inline void host_signal_set_pc(ucontext_t *uc, uintptr_t pc) +{ +#ifdef __arch64__ + uc->uc_mcontext.mc_gregs[MC_PC] = pc; +#else + uc->uc_mcontext.gregs[REG_PC] = pc; +#endif +} + static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc) { uint32_t insn = *(uint32_t *)host_signal_pc(uc); diff --git a/linux-user/host/x86_64/host-signal.h b/linux-user/host/x86_64/host-signal.h index 883d2fcf65..c71d597eb2 100644 --- a/linux-user/host/x86_64/host-signal.h +++ b/linux-user/host/x86_64/host-signal.h @@ -15,6 +15,11 @@ static inline uintptr_t host_signal_pc(ucontext_t *uc) return uc->uc_mcontext.gregs[REG_RIP]; } +static inline void host_signal_set_pc(ucontext_t *uc, uintptr_t pc) +{ + uc->uc_mcontext.gregs[REG_RIP] = pc; +} + static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc) { return uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe diff --git a/linux-user/host/x86_64/hostdep.h b/linux-user/host/x86_64/hostdep.h index a4fefb5114..9c62bd26bd 100644 --- a/linux-user/host/x86_64/hostdep.h +++ b/linux-user/host/x86_64/hostdep.h @@ -15,24 +15,4 @@ /* We have a safe-syscall.inc.S */ #define HAVE_SAFE_SYSCALL -#ifndef __ASSEMBLER__ - -/* These are defined by the safe-syscall.inc.S file */ -extern char safe_syscall_start[]; -extern char safe_syscall_end[]; - -/* Adjust the signal context to rewind out of safe-syscall if we're in it */ -static inline void rewind_if_in_safe_syscall(void *puc) -{ - ucontext_t *uc = puc; - greg_t *pcreg = &uc->uc_mcontext.gregs[REG_RIP]; - - if (*pcreg > (uintptr_t)safe_syscall_start - && *pcreg < (uintptr_t)safe_syscall_end) { - *pcreg = (uintptr_t)safe_syscall_start; - } -} - -#endif /* __ASSEMBLER__ */ - #endif diff --git a/linux-user/ioctls.h b/linux-user/ioctls.h index 7193c3b226..f182d40190 100644 --- a/linux-user/ioctls.h +++ b/linux-user/ioctls.h @@ -637,6 +637,10 @@ IOCTL(LOOP_SET_STATUS64, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info64))) IOCTL(LOOP_GET_STATUS64, IOC_R, MK_PTR(MK_STRUCT(STRUCT_loop_info64))) IOCTL(LOOP_CHANGE_FD, 0, TYPE_INT) + IOCTL(LOOP_SET_CAPACITY, 0, TYPE_INT) + IOCTL(LOOP_SET_DIRECT_IO, 0, TYPE_INT) + IOCTL(LOOP_SET_BLOCK_SIZE, 0, TYPE_INT) + IOCTL(LOOP_CONFIGURE, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_config))) IOCTL(LOOP_CTL_ADD, 0, TYPE_INT) IOCTL(LOOP_CTL_REMOVE, 0, TYPE_INT) diff --git a/linux-user/linux_loop.h b/linux-user/linux_loop.h index c69fea11e4..f80b96f1ff 100644 --- a/linux-user/linux_loop.h +++ b/linux-user/linux_loop.h @@ -96,6 +96,8 @@ struct loop_info64 { #define LOOP_CHANGE_FD 0x4C06 #define LOOP_SET_CAPACITY 0x4C07 #define LOOP_SET_DIRECT_IO 0x4C08 +#define LOOP_SET_BLOCK_SIZE 0x4C09 +#define LOOP_CONFIGURE 0x4C0A /* /dev/loop-control interface */ #define LOOP_CTL_ADD 0x4C80 diff --git a/linux-user/safe-syscall.h b/linux-user/safe-syscall.h index 6bc0390262..aaa9ffc0e2 100644 --- a/linux-user/safe-syscall.h +++ b/linux-user/safe-syscall.h @@ -127,6 +127,9 @@ #ifdef HAVE_SAFE_SYSCALL /* The core part of this function is implemented in assembly */ extern long safe_syscall_base(int *pending, long number, ...); +/* These are defined by the safe-syscall.inc.S file */ +extern char safe_syscall_start[]; +extern char safe_syscall_end[]; #define safe_syscall(...) \ ({ \ diff --git a/linux-user/signal.c b/linux-user/signal.c index 81c45bfce9..6d5e5b698c 100644 --- a/linux-user/signal.c +++ b/linux-user/signal.c @@ -31,6 +31,7 @@ #include "trace.h" #include "signal-common.h" #include "host-signal.h" +#include "safe-syscall.h" static struct target_sigaction sigact_table[TARGET_NSIG]; @@ -793,12 +794,20 @@ int queue_signal(CPUArchState *env, int sig, int si_type, return 1; /* indicates that the signal was queued */ } -#ifndef HAVE_SAFE_SYSCALL + +/* Adjust the signal context to rewind out of safe-syscall if we're in it */ static inline void rewind_if_in_safe_syscall(void *puc) { - /* Default version: never rewind */ -} +#ifdef HAVE_SAFE_SYSCALL + ucontext_t *uc = (ucontext_t *)puc; + uintptr_t pcreg = host_signal_pc(uc); + + if (pcreg > (uintptr_t)safe_syscall_start + && pcreg < (uintptr_t)safe_syscall_end) { + host_signal_set_pc(uc, (uintptr_t)safe_syscall_start); + } #endif +} static void host_signal_handler(int host_sig, siginfo_t *info, void *puc) { diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 32dd3f2e27..185b133983 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -197,8 +197,10 @@ //#define DEBUG_ERESTARTSYS //#include -#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct linux_dirent [2]) -#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct linux_dirent [2]) +#define VFAT_IOCTL_READDIR_BOTH \ + _IOC(_IOC_READ, 'r', 1, (sizeof(struct linux_dirent) + 256) * 2) +#define VFAT_IOCTL_READDIR_SHORT \ + _IOC(_IOC_READ, 'r', 2, (sizeof(struct linux_dirent) + 256) * 2) #undef _syscall0 #undef _syscall1 @@ -8154,6 +8156,159 @@ static int host_to_target_cpu_mask(const unsigned long *host_mask, return 0; } +#ifdef TARGET_NR_getdents +static int do_getdents(abi_long dirfd, abi_long arg2, abi_long count) +{ + g_autofree void *hdirp = NULL; + void *tdirp; + int hlen, hoff, toff; + int hreclen, treclen; + off64_t prev_diroff = 0; + + hdirp = g_try_malloc(count); + if (!hdirp) { + return -TARGET_ENOMEM; + } + +#ifdef EMULATE_GETDENTS_WITH_GETDENTS + hlen = sys_getdents(dirfd, hdirp, count); +#else + hlen = sys_getdents64(dirfd, hdirp, count); +#endif + + hlen = get_errno(hlen); + if (is_error(hlen)) { + return hlen; + } + + tdirp = lock_user(VERIFY_WRITE, arg2, count, 0); + if (!tdirp) { + return -TARGET_EFAULT; + } + + for (hoff = toff = 0; hoff < hlen; hoff += hreclen, toff += treclen) { +#ifdef EMULATE_GETDENTS_WITH_GETDENTS + struct linux_dirent *hde = hdirp + hoff; +#else + struct linux_dirent64 *hde = hdirp + hoff; +#endif + struct target_dirent *tde = tdirp + toff; + int namelen; + uint8_t type; + + namelen = strlen(hde->d_name); + hreclen = hde->d_reclen; + treclen = offsetof(struct target_dirent, d_name) + namelen + 2; + treclen = QEMU_ALIGN_UP(treclen, __alignof(struct target_dirent)); + + if (toff + treclen > count) { + /* + * If the host struct is smaller than the target struct, or + * requires less alignment and thus packs into less space, + * then the host can return more entries than we can pass + * on to the guest. + */ + if (toff == 0) { + toff = -TARGET_EINVAL; /* result buffer is too small */ + break; + } + /* + * Return what we have, resetting the file pointer to the + * location of the first record not returned. + */ + lseek64(dirfd, prev_diroff, SEEK_SET); + break; + } + + prev_diroff = hde->d_off; + tde->d_ino = tswapal(hde->d_ino); + tde->d_off = tswapal(hde->d_off); + tde->d_reclen = tswap16(treclen); + memcpy(tde->d_name, hde->d_name, namelen + 1); + + /* + * The getdents type is in what was formerly a padding byte at the + * end of the structure. + */ +#ifdef EMULATE_GETDENTS_WITH_GETDENTS + type = *((uint8_t *)hde + hreclen - 1); +#else + type = hde->d_type; +#endif + *((uint8_t *)tde + treclen - 1) = type; + } + + unlock_user(tdirp, arg2, toff); + return toff; +} +#endif /* TARGET_NR_getdents */ + +#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64) +static int do_getdents64(abi_long dirfd, abi_long arg2, abi_long count) +{ + g_autofree void *hdirp = NULL; + void *tdirp; + int hlen, hoff, toff; + int hreclen, treclen; + off64_t prev_diroff = 0; + + hdirp = g_try_malloc(count); + if (!hdirp) { + return -TARGET_ENOMEM; + } + + hlen = get_errno(sys_getdents64(dirfd, hdirp, count)); + if (is_error(hlen)) { + return hlen; + } + + tdirp = lock_user(VERIFY_WRITE, arg2, count, 0); + if (!tdirp) { + return -TARGET_EFAULT; + } + + for (hoff = toff = 0; hoff < hlen; hoff += hreclen, toff += treclen) { + struct linux_dirent64 *hde = hdirp + hoff; + struct target_dirent64 *tde = tdirp + toff; + int namelen; + + namelen = strlen(hde->d_name) + 1; + hreclen = hde->d_reclen; + treclen = offsetof(struct target_dirent64, d_name) + namelen; + treclen = QEMU_ALIGN_UP(treclen, __alignof(struct target_dirent64)); + + if (toff + treclen > count) { + /* + * If the host struct is smaller than the target struct, or + * requires less alignment and thus packs into less space, + * then the host can return more entries than we can pass + * on to the guest. + */ + if (toff == 0) { + toff = -TARGET_EINVAL; /* result buffer is too small */ + break; + } + /* + * Return what we have, resetting the file pointer to the + * location of the first record not returned. + */ + lseek64(dirfd, prev_diroff, SEEK_SET); + break; + } + + prev_diroff = hde->d_off; + tde->d_ino = tswap64(hde->d_ino); + tde->d_off = tswap64(hde->d_off); + tde->d_reclen = tswap16(treclen); + tde->d_type = hde->d_type; + memcpy(tde->d_name, hde->d_name, namelen); + } + + unlock_user(tdirp, arg2, toff); + return toff; +} +#endif /* TARGET_NR_getdents64 */ + #if defined(TARGET_NR_pivot_root) && defined(__NR_pivot_root) _syscall2(int, pivot_root, const char *, new_root, const char *, put_old) #endif @@ -10244,162 +10399,11 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_getdents case TARGET_NR_getdents: -#ifdef EMULATE_GETDENTS_WITH_GETDENTS -#if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64 - { - struct target_dirent *target_dirp; - struct linux_dirent *dirp; - abi_long count = arg3; - - dirp = g_try_malloc(count); - if (!dirp) { - return -TARGET_ENOMEM; - } - - ret = get_errno(sys_getdents(arg1, dirp, count)); - if (!is_error(ret)) { - struct linux_dirent *de; - struct target_dirent *tde; - int len = ret; - int reclen, treclen; - int count1, tnamelen; - - count1 = 0; - de = dirp; - if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0))) - return -TARGET_EFAULT; - tde = target_dirp; - while (len > 0) { - reclen = de->d_reclen; - tnamelen = reclen - offsetof(struct linux_dirent, d_name); - assert(tnamelen >= 0); - treclen = tnamelen + offsetof(struct target_dirent, d_name); - assert(count1 + treclen <= count); - tde->d_reclen = tswap16(treclen); - tde->d_ino = tswapal(de->d_ino); - tde->d_off = tswapal(de->d_off); - memcpy(tde->d_name, de->d_name, tnamelen); - de = (struct linux_dirent *)((char *)de + reclen); - len -= reclen; - tde = (struct target_dirent *)((char *)tde + treclen); - count1 += treclen; - } - ret = count1; - unlock_user(target_dirp, arg2, ret); - } - g_free(dirp); - } -#else - { - struct linux_dirent *dirp; - abi_long count = arg3; - - if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0))) - return -TARGET_EFAULT; - ret = get_errno(sys_getdents(arg1, dirp, count)); - if (!is_error(ret)) { - struct linux_dirent *de; - int len = ret; - int reclen; - de = dirp; - while (len > 0) { - reclen = de->d_reclen; - if (reclen > len) - break; - de->d_reclen = tswap16(reclen); - tswapls(&de->d_ino); - tswapls(&de->d_off); - de = (struct linux_dirent *)((char *)de + reclen); - len -= reclen; - } - } - unlock_user(dirp, arg2, ret); - } -#endif -#else - /* Implement getdents in terms of getdents64 */ - { - struct linux_dirent64 *dirp; - abi_long count = arg3; - - dirp = lock_user(VERIFY_WRITE, arg2, count, 0); - if (!dirp) { - return -TARGET_EFAULT; - } - ret = get_errno(sys_getdents64(arg1, dirp, count)); - if (!is_error(ret)) { - /* Convert the dirent64 structs to target dirent. We do this - * in-place, since we can guarantee that a target_dirent is no - * larger than a dirent64; however this means we have to be - * careful to read everything before writing in the new format. - */ - struct linux_dirent64 *de; - struct target_dirent *tde; - int len = ret; - int tlen = 0; - - de = dirp; - tde = (struct target_dirent *)dirp; - while (len > 0) { - int namelen, treclen; - int reclen = de->d_reclen; - uint64_t ino = de->d_ino; - int64_t off = de->d_off; - uint8_t type = de->d_type; - - namelen = strlen(de->d_name); - treclen = offsetof(struct target_dirent, d_name) - + namelen + 2; - treclen = QEMU_ALIGN_UP(treclen, sizeof(abi_long)); - - memmove(tde->d_name, de->d_name, namelen + 1); - tde->d_ino = tswapal(ino); - tde->d_off = tswapal(off); - tde->d_reclen = tswap16(treclen); - /* The target_dirent type is in what was formerly a padding - * byte at the end of the structure: - */ - *(((char *)tde) + treclen - 1) = type; - - de = (struct linux_dirent64 *)((char *)de + reclen); - tde = (struct target_dirent *)((char *)tde + treclen); - len -= reclen; - tlen += treclen; - } - ret = tlen; - } - unlock_user(dirp, arg2, ret); - } -#endif - return ret; + return do_getdents(arg1, arg2, arg3); #endif /* TARGET_NR_getdents */ #if defined(TARGET_NR_getdents64) && defined(__NR_getdents64) case TARGET_NR_getdents64: - { - struct linux_dirent64 *dirp; - abi_long count = arg3; - if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0))) - return -TARGET_EFAULT; - ret = get_errno(sys_getdents64(arg1, dirp, count)); - if (!is_error(ret)) { - struct linux_dirent64 *de; - int len = ret; - int reclen; - de = dirp; - while (len > 0) { - reclen = de->d_reclen; - if (reclen > len) - break; - de->d_reclen = tswap16(reclen); - tswap64s((uint64_t *)&de->d_ino); - tswap64s((uint64_t *)&de->d_off); - de = (struct linux_dirent64 *)((char *)de + reclen); - len -= reclen; - } - } - unlock_user(dirp, arg2, ret); - } - return ret; + return do_getdents64(arg1, arg2, arg3); #endif /* TARGET_NR_getdents64 */ #if defined(TARGET_NR__newselect) case TARGET_NR__newselect: diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index a5ce487dcc..0b13975937 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -437,11 +437,11 @@ struct target_dirent { }; struct target_dirent64 { - uint64_t d_ino; - int64_t d_off; - unsigned short d_reclen; + abi_ullong d_ino; + abi_llong d_off; + abi_ushort d_reclen; unsigned char d_type; - char d_name[256]; + char d_name[]; }; @@ -1219,6 +1219,10 @@ struct target_rtc_pll_info { #define TARGET_LOOP_SET_STATUS64 0x4C04 #define TARGET_LOOP_GET_STATUS64 0x4C05 #define TARGET_LOOP_CHANGE_FD 0x4C06 +#define TARGET_LOOP_SET_CAPACITY 0x4C07 +#define TARGET_LOOP_SET_DIRECT_IO 0x4C08 +#define TARGET_LOOP_SET_BLOCK_SIZE 0x4C09 +#define TARGET_LOOP_CONFIGURE 0x4C0A #define TARGET_LOOP_CTL_ADD 0x4C80 #define TARGET_LOOP_CTL_REMOVE 0x4C81 @@ -2714,7 +2718,7 @@ struct linux_dirent { long d_ino; unsigned long d_off; unsigned short d_reclen; - char d_name[256]; /* We must not include limits.h! */ + char d_name[]; }; struct linux_dirent64 { @@ -2722,7 +2726,7 @@ struct linux_dirent64 { int64_t d_off; unsigned short d_reclen; unsigned char d_type; - char d_name[256]; + char d_name[]; }; struct target_mq_attr { diff --git a/linux-user/syscall_types.h b/linux-user/syscall_types.h index ba2c1518eb..c3b43f8022 100644 --- a/linux-user/syscall_types.h +++ b/linux-user/syscall_types.h @@ -201,6 +201,12 @@ STRUCT(loop_info64, MK_ARRAY(TYPE_CHAR, 32), /* lo_encrypt_key */ MK_ARRAY(TYPE_ULONGLONG, 2)) /* lo_init */ +STRUCT(loop_config, + TYPE_INT, /* fd */ + TYPE_INT, /* block_size */ + MK_STRUCT(STRUCT_loop_info64), /* info */ + MK_ARRAY(TYPE_ULONGLONG, 8)) /* __reserved */ + /* mag tape ioctls */ STRUCT(mtop, TYPE_SHORT, TYPE_INT) STRUCT(mtget, TYPE_LONG, TYPE_LONG, TYPE_LONG, TYPE_LONG, TYPE_LONG, diff --git a/meson.build b/meson.build index 643166dcf1..32799ce312 100644 --- a/meson.build +++ b/meson.build @@ -329,9 +329,7 @@ if not get_option('hax').disabled() endif endif if targetos == 'netbsd' - if cc.has_header_symbol('nvmm.h', 'nvmm_cpu_stop', required: get_option('nvmm')) - nvmm = cc.find_library('nvmm', required: get_option('nvmm')) - endif + nvmm = cc.find_library('nvmm', required: get_option('nvmm')) if nvmm.found() accelerators += 'CONFIG_NVMM' endif @@ -681,6 +679,9 @@ iconv = not_found curses = not_found if have_system and not get_option('curses').disabled() curses_test = ''' + #if defined(__APPLE__) || defined(__OpenBSD__) + #define _XOPEN_SOURCE_EXTENDED 1 + #endif #include #include #include @@ -704,7 +705,7 @@ if have_system and not get_option('curses').disabled() endif endforeach msg = get_option('curses').enabled() ? 'curses library not found' : '' - curses_compile_args = ['-DNCURSES_WIDECHAR'] + curses_compile_args = ['-DNCURSES_WIDECHAR=1'] if curses.found() if cc.links(curses_test, args: curses_compile_args, dependencies: [curses]) curses = declare_dependency(compile_args: curses_compile_args, dependencies: [curses]) @@ -1553,8 +1554,6 @@ config_host_data.set('CONFIG_INOTIFY', cc.has_header_symbol('sys/inotify.h', 'inotify_init')) config_host_data.set('CONFIG_INOTIFY1', cc.has_header_symbol('sys/inotify.h', 'inotify_init1')) -config_host_data.set('CONFIG_IOVEC', - cc.has_header_symbol('sys/uio.h', 'struct iovec')) config_host_data.set('CONFIG_MACHINE_BSWAP_H', cc.has_header_symbol('machine/bswap.h', 'bswap32', prefix: '''#include @@ -1567,8 +1566,6 @@ config_host_data.set('CONFIG_SYSMACROS', cc.has_header_symbol('sys/sysmacros.h', 'makedev')) config_host_data.set('HAVE_OPTRESET', cc.has_header_symbol('getopt.h', 'optreset')) -config_host_data.set('HAVE_UTMPX', - cc.has_header_symbol('utmpx.h', 'struct utmpx')) config_host_data.set('HAVE_IPPROTO_MPTCP', cc.has_header_symbol('netinet/in.h', 'IPPROTO_MPTCP')) @@ -1580,6 +1577,14 @@ config_host_data.set('HAVE_STRUCT_STAT_ST_ATIM', cc.has_member('struct stat', 'st_atim', prefix: '#include ')) +# has_type +config_host_data.set('CONFIG_IOVEC', + cc.has_type('struct iovec', + prefix: '#include ')) +config_host_data.set('HAVE_UTMPX', + cc.has_type('struct utmpx', + prefix: '#include ')) + config_host_data.set('CONFIG_EVENTFD', cc.links(''' #include int main(void) { return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); }''')) @@ -1621,7 +1626,7 @@ config_host_data.set('CONFIG_POSIX_MADVISE', cc.links(gnu_source_prefix + ''' #include int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }''')) -config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_W_TID', cc.links(''' +config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_W_TID', cc.links(gnu_source_prefix + ''' #include static void *f(void *p) { return NULL; } @@ -1632,7 +1637,7 @@ config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_W_TID', cc.links(''' pthread_setname_np(thread, "QEMU"); return 0; }''', dependencies: threads)) -config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_WO_TID', cc.links(''' +config_host_data.set('CONFIG_PTHREAD_SETNAME_NP_WO_TID', cc.links(gnu_source_prefix + ''' #include static void *f(void *p) { pthread_setname_np("QEMU"); return NULL; } @@ -1668,8 +1673,10 @@ config_host_data.set('HAVE_MLOCKALL', cc.links(gnu_source_prefix + ''' have_l2tpv3 = false if not get_option('l2tpv3').disabled() and have_system - have_l2tpv3 = (cc.has_header_symbol('sys/socket.h', 'struct mmsghdr') - and cc.has_header('linux/ip.h')) + have_l2tpv3 = cc.has_type('struct mmsghdr', + prefix: gnu_source_prefix + ''' + #include + #include ''') endif config_host_data.set('CONFIG_L2TPV3', have_l2tpv3) @@ -1695,7 +1702,7 @@ config_host_data.set('CONFIG_NETMAP', have_netmap) # xfs headers will not try to redefine structs from linux headers # if this macro is set. config_host_data.set('HAVE_FSXATTR', cc.links(''' - #include ' + #include struct fsxattr foo; int main(void) { return 0; diff --git a/nbd/server.c b/nbd/server.c index d9164ee6d0..4630dd7322 100644 --- a/nbd/server.c +++ b/nbd/server.c @@ -1418,6 +1418,9 @@ static int nbd_receive_request(NBDClient *client, NBDRequest *request, if (ret < 0) { return ret; } + if (ret == 0) { + return -EIO; + } /* Request [ 0 .. 3] magic (NBD_REQUEST_MAGIC) @@ -2506,16 +2509,8 @@ static coroutine_fn int nbd_handle_request(NBDClient *client, if (request->flags & NBD_CMD_FLAG_FAST_ZERO) { flags |= BDRV_REQ_NO_FALLBACK; } - ret = 0; - /* FIXME simplify this when blk_pwrite_zeroes switches to 64-bit */ - while (ret >= 0 && request->len) { - int align = client->check_align ?: 1; - int len = MIN(request->len, QEMU_ALIGN_DOWN(BDRV_REQUEST_MAX_BYTES, - align)); - ret = blk_pwrite_zeroes(exp->common.blk, request->from, len, flags); - request->len -= len; - request->from += len; - } + ret = blk_pwrite_zeroes(exp->common.blk, request->from, request->len, + flags); return nbd_send_generic_reply(client, request->handle, ret, "writing to file failed", errp); @@ -2529,16 +2524,7 @@ static coroutine_fn int nbd_handle_request(NBDClient *client, "flush failed", errp); case NBD_CMD_TRIM: - ret = 0; - /* FIXME simplify this when blk_co_pdiscard switches to 64-bit */ - while (ret >= 0 && request->len) { - int align = client->check_align ?: 1; - int len = MIN(request->len, QEMU_ALIGN_DOWN(BDRV_REQUEST_MAX_BYTES, - align)); - ret = blk_co_pdiscard(exp->common.blk, request->from, len); - request->len -= len; - request->from += len; - } + ret = blk_co_pdiscard(exp->common.blk, request->from, request->len); if (ret >= 0 && request->flags & NBD_CMD_FLAG_FUA) { ret = blk_co_flush(exp->common.blk); } diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c index 2e3c22a8c7..25dd6dd975 100644 --- a/net/vhost-vdpa.c +++ b/net/vhost-vdpa.c @@ -170,9 +170,17 @@ static bool vhost_vdpa_check_peer_type(NetClientState *nc, ObjectClass *oc, return true; } +/** Dummy receive in case qemu falls back to userland tap networking */ +static ssize_t vhost_vdpa_receive(NetClientState *nc, const uint8_t *buf, + size_t size) +{ + return 0; +} + static NetClientInfo net_vhost_vdpa_info = { .type = NET_CLIENT_DRIVER_VHOST_VDPA, .size = sizeof(VhostVDPAState), + .receive = vhost_vdpa_receive, .cleanup = vhost_vdpa_cleanup, .has_vnet_hdr = vhost_vdpa_has_vnet_hdr, .has_ufo = vhost_vdpa_has_ufo, diff --git a/pc-bios/bios-256k.bin b/pc-bios/bios-256k.bin index dea01da468..26f863b609 100644 Binary files a/pc-bios/bios-256k.bin and b/pc-bios/bios-256k.bin differ diff --git a/pc-bios/bios-microvm.bin b/pc-bios/bios-microvm.bin index ca6375d65c..ddeb24391d 100644 Binary files a/pc-bios/bios-microvm.bin and b/pc-bios/bios-microvm.bin differ diff --git a/pc-bios/bios.bin b/pc-bios/bios.bin index e9fa99f006..6e6cde8c7f 100644 Binary files a/pc-bios/bios.bin and b/pc-bios/bios.bin differ diff --git a/pc-bios/vgabios-ati.bin b/pc-bios/vgabios-ati.bin index 0de9c0d3c1..fe497ea4f2 100644 Binary files a/pc-bios/vgabios-ati.bin and b/pc-bios/vgabios-ati.bin differ diff --git a/pc-bios/vgabios-bochs-display.bin b/pc-bios/vgabios-bochs-display.bin index 76e076f029..7ca04402e9 100644 Binary files a/pc-bios/vgabios-bochs-display.bin and b/pc-bios/vgabios-bochs-display.bin differ diff --git a/pc-bios/vgabios-cirrus.bin b/pc-bios/vgabios-cirrus.bin index 0f16ad199d..020dfe6c56 100644 Binary files a/pc-bios/vgabios-cirrus.bin and b/pc-bios/vgabios-cirrus.bin differ diff --git a/pc-bios/vgabios-qxl.bin b/pc-bios/vgabios-qxl.bin index 420f9ed331..0cc20678a3 100644 Binary files a/pc-bios/vgabios-qxl.bin and b/pc-bios/vgabios-qxl.bin differ diff --git a/pc-bios/vgabios-ramfb.bin b/pc-bios/vgabios-ramfb.bin index b9b2e230a5..a7c5ae7c8f 100644 Binary files a/pc-bios/vgabios-ramfb.bin and b/pc-bios/vgabios-ramfb.bin differ diff --git a/pc-bios/vgabios-stdvga.bin b/pc-bios/vgabios-stdvga.bin index b59256572d..abeea373d3 100644 Binary files a/pc-bios/vgabios-stdvga.bin and b/pc-bios/vgabios-stdvga.bin differ diff --git a/pc-bios/vgabios-virtio.bin b/pc-bios/vgabios-virtio.bin index c00414ab83..806647a009 100644 Binary files a/pc-bios/vgabios-virtio.bin and b/pc-bios/vgabios-virtio.bin differ diff --git a/pc-bios/vgabios-vmware.bin b/pc-bios/vgabios-vmware.bin index 5454aceda8..39e3093667 100644 Binary files a/pc-bios/vgabios-vmware.bin and b/pc-bios/vgabios-vmware.bin differ diff --git a/pc-bios/vgabios.bin b/pc-bios/vgabios.bin index ae82887d73..c3a66af50e 100644 Binary files a/pc-bios/vgabios.bin and b/pc-bios/vgabios.bin differ diff --git a/plugins/meson.build b/plugins/meson.build index aeb386ebae..b3de57853b 100644 --- a/plugins/meson.build +++ b/plugins/meson.build @@ -2,9 +2,9 @@ plugin_ldflags = [] # Modules need more symbols than just those in plugins/qemu-plugins.symbols if not enable_modules if 'CONFIG_HAS_LD_DYNAMIC_LIST' in config_host - plugin_ldflags = ['-Wl,--dynamic-list=' + (meson.project_build_root() / 'qemu-plugins-ld.symbols')] + plugin_ldflags = ['-Wl,--dynamic-list=qemu-plugins-ld.symbols'] elif 'CONFIG_HAS_LD_EXPORTED_SYMBOLS_LIST' in config_host - plugin_ldflags = ['-Wl,-exported_symbols_list,' + (meson.project_build_root() / 'qemu-plugins-ld64.symbols')] + plugin_ldflags = ['-Wl,-exported_symbols_list,qemu-plugins-ld64.symbols'] endif endif diff --git a/python/qemu/aqmp/qmp_client.py b/python/qemu/aqmp/qmp_client.py index f987da02eb..8105e29fa8 100644 --- a/python/qemu/aqmp/qmp_client.py +++ b/python/qemu/aqmp/qmp_client.py @@ -639,9 +639,12 @@ class QMPClient(AsyncProtocol[Message], Events): if sock.family != socket.AF_UNIX: raise AQMPError("Sending file descriptors requires a UNIX socket.") - # Void the warranty sticker. - # Access to sendmsg in asyncio is scheduled for removal in Python 3.11. - sock = sock._sock # pylint: disable=protected-access + if not hasattr(sock, 'sendmsg'): + # We need to void the warranty sticker. + # Access to sendmsg is scheduled for removal in Python 3.11. + # Find the real backing socket to use it anyway. + sock = sock._sock # pylint: disable=protected-access + sock.sendmsg( [b' '], [(socket.SOL_SOCKET, socket.SCM_RIGHTS, struct.pack('@i', fd))] diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py index a487c39745..67ab06ca2b 100644 --- a/python/qemu/machine/machine.py +++ b/python/qemu/machine/machine.py @@ -133,19 +133,18 @@ class QEMUMachine: self._wrapper = wrapper self._qmp_timer = qmp_timer - self._name = name or "qemu-%d" % os.getpid() + self._name = name or f"qemu-{os.getpid()}-{id(self):02x}" + self._temp_dir: Optional[str] = None self._base_temp_dir = base_temp_dir - self._sock_dir = sock_dir or self._base_temp_dir + self._sock_dir = sock_dir self._log_dir = log_dir if monitor_address is not None: self._monitor_address = monitor_address - self._remove_monitor_sockfile = False else: self._monitor_address = os.path.join( - self._sock_dir, f"{self._name}-monitor.sock" + self.sock_dir, f"{self._name}-monitor.sock" ) - self._remove_monitor_sockfile = True self._console_log_path = console_log if self._console_log_path: @@ -163,14 +162,13 @@ class QEMUMachine: self._qmp_set = True # Enable QMP monitor by default. self._qmp_connection: Optional[QEMUMonitorProtocol] = None self._qemu_full_args: Tuple[str, ...] = () - self._temp_dir: Optional[str] = None self._launched = False self._machine: Optional[str] = None self._console_index = 0 self._console_set = False self._console_device_type: Optional[str] = None self._console_address = os.path.join( - self._sock_dir, f"{self._name}-console.sock" + self.sock_dir, f"{self._name}-console.sock" ) self._console_socket: Optional[socket.socket] = None self._remove_files: List[str] = [] @@ -315,8 +313,7 @@ class QEMUMachine: self._remove_files.append(self._console_address) if self._qmp_set: - if self._remove_monitor_sockfile: - assert isinstance(self._monitor_address, str) + if isinstance(self._monitor_address, str): self._remove_files.append(self._monitor_address) self._qmp_connection = QEMUMonitorProtocol( self._monitor_address, @@ -330,6 +327,14 @@ class QEMUMachine: self._qemu_log_path = os.path.join(self.log_dir, self._name + ".log") self._qemu_log_file = open(self._qemu_log_path, 'wb') + self._iolog = None + self._qemu_full_args = tuple(chain( + self._wrapper, + [self._binary], + self._base_args, + self._args + )) + def _post_launch(self) -> None: if self._qmp_connection: self._qmp.accept(self._qmp_timer) @@ -344,9 +349,6 @@ class QEMUMachine: Called to cleanup the VM instance after the process has exited. May also be called after a failed launch. """ - # Comprehensive reset for the failed launch case: - self._early_cleanup() - try: self._close_qmp_connection() except Exception as err: # pylint: disable=broad-except @@ -393,13 +395,18 @@ class QEMUMachine: if self._launched: raise QEMUMachineError('VM already launched') - self._iolog = None - self._qemu_full_args = () try: self._launch() - self._launched = True except: - self._post_shutdown() + # We may have launched the process but it may + # have exited before we could connect via QMP. + # Assume the VM didn't launch or is exiting. + # If we don't wait for the process, exitcode() may still be + # 'None' by the time control is ceded back to the caller. + if self._launched: + self.wait() + else: + self._post_shutdown() LOG.debug('Error launching VM') if self._qemu_full_args: @@ -413,12 +420,6 @@ class QEMUMachine: Launch the VM and establish a QMP connection """ self._pre_launch() - self._qemu_full_args = tuple( - chain(self._wrapper, - [self._binary], - self._base_args, - self._args) - ) LOG.debug('VM launch command: %r', ' '.join(self._qemu_full_args)) # Cleaning up of this subprocess is guaranteed by _do_shutdown. @@ -429,6 +430,7 @@ class QEMUMachine: stderr=subprocess.STDOUT, shell=False, close_fds=False) + self._launched = True self._post_launch() def _close_qmp_connection(self) -> None: @@ -460,8 +462,8 @@ class QEMUMachine: """ Perform any cleanup that needs to happen before the VM exits. - May be invoked by both soft and hard shutdown in failover scenarios. - Called additionally by _post_shutdown for comprehensive cleanup. + This method may be called twice upon shutdown, once each by soft + and hard shutdown in failover scenarios. """ # If we keep the console socket open, we may deadlock waiting # for QEMU to exit, while QEMU is waiting for the socket to @@ -816,6 +818,15 @@ class QEMUMachine: dir=self._base_temp_dir) return self._temp_dir + @property + def sock_dir(self) -> str: + """ + Returns the directory used for sockfiles by this machine. + """ + if self._sock_dir: + return self._sock_dir + return self.temp_dir + @property def log_dir(self) -> str: """ diff --git a/roms/seabios b/roms/seabios index 64f37cc530..2dd4b9b3f8 160000 --- a/roms/seabios +++ b/roms/seabios @@ -1 +1 @@ -Subproject commit 64f37cc530f144e53c190c9e8209a51b58fd5c43 +Subproject commit 2dd4b9b3f84019668719344b40dba79d681be41c diff --git a/scripts/device-crash-test b/scripts/device-crash-test index 1c73dac93e..7fbd99158b 100755 --- a/scripts/device-crash-test +++ b/scripts/device-crash-test @@ -353,7 +353,7 @@ def checkOneCase(args, testcase): '-device', qemuOptsEscape(device)] cmdline = ' '.join([binary] + args) dbg("will launch QEMU: %s", cmdline) - vm = QEMUMachine(binary=binary, args=args) + vm = QEMUMachine(binary=binary, args=args, qmp_timer=15) exc = None exc_traceback = None diff --git a/softmmu/physmem.c b/softmmu/physmem.c index 314f8b439c..3524c04c2a 100644 --- a/softmmu/physmem.c +++ b/softmmu/physmem.c @@ -912,7 +912,7 @@ void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len, */ if (!cpu->can_do_io) { /* Force execution of one insn next time. */ - cpu->cflags_next_tb = 1 | CF_LAST_IO | curr_cflags(cpu); + cpu->cflags_next_tb = 1 | CF_LAST_IO | CF_NOIRQ | curr_cflags(cpu); cpu_loop_exit_restore(cpu, ra); } /* @@ -946,7 +946,7 @@ void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len, cpu_loop_exit(cpu); } else { /* Force execution of one insn next time. */ - cpu->cflags_next_tb = 1 | CF_LAST_IO | curr_cflags(cpu); + cpu->cflags_next_tb = 1 | CF_LAST_IO | CF_NOIRQ | curr_cflags(cpu); mmap_unlock(); cpu_loop_exit_noexc(cpu); } diff --git a/softmmu/vl.c b/softmmu/vl.c index 1159a64bce..620a1f1367 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -3766,6 +3766,7 @@ void qemu_init(int argc, char **argv, char **envp) if (vmstate_dump_file) { /* dump and exit */ + module_load_qom_all(); dump_vmstate_json_to_file(vmstate_dump_file); exit(0); } diff --git a/target/arm/psci.c b/target/arm/psci.c index b279c0b9a4..6709e28013 100644 --- a/target/arm/psci.c +++ b/target/arm/psci.c @@ -27,13 +27,15 @@ bool arm_is_psci_call(ARMCPU *cpu, int excp_type) { - /* - * Return true if the exception type matches the configured PSCI conduit. - * This is called before the SMC/HVC instruction is executed, to decide - * whether we should treat it as a PSCI call or with the architecturally + /* Return true if the r0/x0 value indicates a PSCI call and + * the exception type matches the configured PSCI conduit. This is + * called before the SMC/HVC instruction is executed, to decide whether + * we should treat it as a PSCI call or with the architecturally * defined behaviour for an SMC or HVC (which might be UNDEF or trap * to EL2 or to EL3). */ + CPUARMState *env = &cpu->env; + uint64_t param = is_a64(env) ? env->xregs[0] : env->regs[0]; switch (excp_type) { case EXCP_HVC: @@ -50,7 +52,27 @@ bool arm_is_psci_call(ARMCPU *cpu, int excp_type) return false; } - return true; + switch (param) { + case QEMU_PSCI_0_2_FN_PSCI_VERSION: + case QEMU_PSCI_0_2_FN_MIGRATE_INFO_TYPE: + case QEMU_PSCI_0_2_FN_AFFINITY_INFO: + case QEMU_PSCI_0_2_FN64_AFFINITY_INFO: + case QEMU_PSCI_0_2_FN_SYSTEM_RESET: + case QEMU_PSCI_0_2_FN_SYSTEM_OFF: + case QEMU_PSCI_0_1_FN_CPU_ON: + case QEMU_PSCI_0_2_FN_CPU_ON: + case QEMU_PSCI_0_2_FN64_CPU_ON: + case QEMU_PSCI_0_1_FN_CPU_OFF: + case QEMU_PSCI_0_2_FN_CPU_OFF: + case QEMU_PSCI_0_1_FN_CPU_SUSPEND: + case QEMU_PSCI_0_2_FN_CPU_SUSPEND: + case QEMU_PSCI_0_2_FN64_CPU_SUSPEND: + case QEMU_PSCI_0_1_FN_MIGRATE: + case QEMU_PSCI_0_2_FN_MIGRATE: + return true; + default: + return false; + } } void arm_handle_psci_call(ARMCPU *cpu) @@ -172,9 +194,10 @@ void arm_handle_psci_call(ARMCPU *cpu) break; case QEMU_PSCI_0_1_FN_MIGRATE: case QEMU_PSCI_0_2_FN_MIGRATE: - default: ret = QEMU_PSCI_RET_NOT_SUPPORTED; break; + default: + g_assert_not_reached(); } err: diff --git a/target/i386/nvmm/nvmm-all.c b/target/i386/nvmm/nvmm-all.c index 14c996f968..9af261eea3 100644 --- a/target/i386/nvmm/nvmm-all.c +++ b/target/i386/nvmm/nvmm-all.c @@ -750,7 +750,11 @@ nvmm_vcpu_loop(CPUState *cpu) nvmm_vcpu_pre_run(cpu); if (qatomic_read(&cpu->exit_request)) { +#if NVMM_USER_VERSION >= 2 nvmm_vcpu_stop(vcpu); +#else + qemu_cpu_kick_self(); +#endif } /* Read exit_request before the kernel reads the immediate exit flag */ @@ -767,6 +771,7 @@ nvmm_vcpu_loop(CPUState *cpu) switch (exit->reason) { case NVMM_VCPU_EXIT_NONE: break; +#if NVMM_USER_VERSION >= 2 case NVMM_VCPU_EXIT_STOPPED: /* * The kernel cleared the immediate exit flag; cpu->exit_request @@ -775,6 +780,7 @@ nvmm_vcpu_loop(CPUState *cpu) smp_wmb(); qcpu->stop = true; break; +#endif case NVMM_VCPU_EXIT_MEMORY: ret = nvmm_handle_mem(mach, vcpu); break; @@ -888,8 +894,12 @@ nvmm_ipi_signal(int sigcpu) { if (current_cpu) { struct qemu_vcpu *qcpu = get_qemu_vcpu(current_cpu); +#if NVMM_USER_VERSION >= 2 struct nvmm_vcpu *vcpu = &qcpu->vcpu; nvmm_vcpu_stop(vcpu); +#else + qcpu->stop = true; +#endif } } diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c index 19832c4b46..da9fe99ff8 100644 --- a/target/ppc/mmu-hash64.c +++ b/target/ppc/mmu-hash64.c @@ -786,7 +786,7 @@ static void ppc_hash64_set_dsi(CPUState *cs, int mmu_idx, uint64_t dar, uint64_t static void ppc_hash64_set_r(PowerPCCPU *cpu, hwaddr ptex, uint64_t pte1) { - hwaddr base, offset = ptex * HASH_PTE_SIZE_64 + 16; + hwaddr base, offset = ptex * HASH_PTE_SIZE_64 + HPTE64_DW1_R; if (cpu->vhyp) { PPCVirtualHypervisorClass *vhc = @@ -803,7 +803,7 @@ static void ppc_hash64_set_r(PowerPCCPU *cpu, hwaddr ptex, uint64_t pte1) static void ppc_hash64_set_c(PowerPCCPU *cpu, hwaddr ptex, uint64_t pte1) { - hwaddr base, offset = ptex * HASH_PTE_SIZE_64 + 15; + hwaddr base, offset = ptex * HASH_PTE_SIZE_64 + HPTE64_DW1_C; if (cpu->vhyp) { PPCVirtualHypervisorClass *vhc = diff --git a/target/ppc/mmu-hash64.h b/target/ppc/mmu-hash64.h index c5b2f97ff7..1496955d38 100644 --- a/target/ppc/mmu-hash64.h +++ b/target/ppc/mmu-hash64.h @@ -97,6 +97,11 @@ void ppc_hash64_finalize(PowerPCCPU *cpu); #define HPTE64_V_1TB_SEG 0x4000000000000000ULL #define HPTE64_V_VRMA_MASK 0x4001ffffff000000ULL +/* PTE offsets */ +#define HPTE64_DW1 (HASH_PTE_SIZE_64 / 2) +#define HPTE64_DW1_R (HPTE64_DW1 + 6) +#define HPTE64_DW1_C (HPTE64_DW1 + 7) + /* Format changes for ARCH v3 */ #define HPTE64_V_COMMON_BITS 0x000fffffffffffffULL #define HPTE64_R_3_0_SSIZE_SHIFT 58 diff --git a/tests/avocado/tcg_plugins.py b/tests/avocado/tcg_plugins.py index 9ca1515c3b..642d2e49e3 100644 --- a/tests/avocado/tcg_plugins.py +++ b/tests/avocado/tcg_plugins.py @@ -131,7 +131,7 @@ class PluginKernelNormal(PluginKernelBase): suffix=".log") self.run_vm(kernel_path, kernel_command_line, - "tests/plugin/libmem.so,arg=both", plugin_log.name, + "tests/plugin/libmem.so,inline=true,callback=true", plugin_log.name, console_pattern, args=('-icount', 'shift=1')) diff --git a/tests/plugin/syscall.c b/tests/plugin/syscall.c index 484b48de49..96040c578f 100644 --- a/tests/plugin/syscall.c +++ b/tests/plugin/syscall.c @@ -70,19 +70,17 @@ static void vcpu_syscall_ret(qemu_plugin_id_t id, unsigned int vcpu_idx, } g_mutex_unlock(&lock); } else { - g_autofree gchar *out; - out = g_strdup_printf("syscall #%" PRIi64 " returned -> %" PRIi64 "\n", - num, ret); + g_autofree gchar *out = g_strdup_printf( + "syscall #%" PRIi64 " returned -> %" PRIi64 "\n", num, ret); qemu_plugin_outs(out); } } static void print_entry(gpointer val, gpointer user_data) { - g_autofree gchar *out; SyscallStats *entry = (SyscallStats *) val; int64_t syscall_num = entry->num; - out = g_strdup_printf( + g_autofree gchar *out = g_strdup_printf( "%-13" PRIi64 "%-6" PRIi64 " %" PRIi64 "\n", syscall_num, entry->calls, entry->errors); qemu_plugin_outs(out); diff --git a/tests/qemu-iotests/149 b/tests/qemu-iotests/149 index 328fd05a4c..d49646ca60 100755 --- a/tests/qemu-iotests/149 +++ b/tests/qemu-iotests/149 @@ -230,6 +230,18 @@ def create_image(config, size_mb): fn.truncate(size_mb * 1024 * 1024) +def check_cipher_support(config, output): + """Check the output of qemu-img or qemu-io for mention of the respective + cipher algorithm being unsupported, and if so, skip this test. + (Returns `output` for convenience.)""" + + if 'Unsupported cipher algorithm' in output: + iotests.notrun('Unsupported cipher algorithm ' + f'{config.cipher}-{config.keylen}-{config.mode}; ' + 'consider configuring qemu with a different crypto ' + 'backend') + return output + def qemu_img_create(config, size_mb): """Create and format a disk image with LUKS using qemu-img""" @@ -253,7 +265,8 @@ def qemu_img_create(config, size_mb): "%dM" % size_mb] iotests.log("qemu-img " + " ".join(args), filters=[iotests.filter_test_dir]) - iotests.log(iotests.qemu_img_pipe(*args), filters=[iotests.filter_test_dir]) + iotests.log(check_cipher_support(config, iotests.qemu_img_pipe(*args)), + filters=[iotests.filter_test_dir]) def qemu_io_image_args(config, dev=False): """Get the args for access an image or device with qemu-io""" @@ -279,8 +292,8 @@ def qemu_io_write_pattern(config, pattern, offset_mb, size_mb, dev=False): args = ["-c", "write -P 0x%x %dM %dM" % (pattern, offset_mb, size_mb)] args.extend(qemu_io_image_args(config, dev)) iotests.log("qemu-io " + " ".join(args), filters=[iotests.filter_test_dir]) - iotests.log(iotests.qemu_io(*args), filters=[iotests.filter_test_dir, - iotests.filter_qemu_io]) + iotests.log(check_cipher_support(config, iotests.qemu_io(*args)), + filters=[iotests.filter_test_dir, iotests.filter_qemu_io]) def qemu_io_read_pattern(config, pattern, offset_mb, size_mb, dev=False): @@ -291,8 +304,8 @@ def qemu_io_read_pattern(config, pattern, offset_mb, size_mb, dev=False): args = ["-c", "read -P 0x%x %dM %dM" % (pattern, offset_mb, size_mb)] args.extend(qemu_io_image_args(config, dev)) iotests.log("qemu-io " + " ".join(args), filters=[iotests.filter_test_dir]) - iotests.log(iotests.qemu_io(*args), filters=[iotests.filter_test_dir, - iotests.filter_qemu_io]) + iotests.log(check_cipher_support(config, iotests.qemu_io(*args)), + filters=[iotests.filter_test_dir, iotests.filter_qemu_io]) def test_once(config, qemu_img=False): diff --git a/tests/qemu-iotests/206 b/tests/qemu-iotests/206 index c3cdad4ce4..10eff343f7 100755 --- a/tests/qemu-iotests/206 +++ b/tests/qemu-iotests/206 @@ -162,8 +162,8 @@ with iotests.FilePath('t.qcow2') as disk_path, \ 'encrypt': { 'format': 'luks', 'key-secret': 'keysec0', - 'cipher-alg': 'twofish-128', - 'cipher-mode': 'ctr', + 'cipher-alg': 'aes-128', + 'cipher-mode': 'cbc', 'ivgen-alg': 'plain64', 'ivgen-hash-alg': 'md5', 'hash-alg': 'sha1', diff --git a/tests/qemu-iotests/206.out b/tests/qemu-iotests/206.out index 3593e8e9c2..80cd274223 100644 --- a/tests/qemu-iotests/206.out +++ b/tests/qemu-iotests/206.out @@ -97,7 +97,7 @@ Format specific information: === Successful image creation (encrypted) === -{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "encrypt": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "format": "luks", "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0"}, "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"driver": "qcow2", "encrypt": {"cipher-alg": "aes-128", "cipher-mode": "cbc", "format": "luks", "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0"}, "file": {"driver": "file", "filename": "TEST_DIR/PID-t.qcow2"}, "size": 33554432}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -115,10 +115,10 @@ Format specific information: encrypt: ivgen alg: plain64 hash alg: sha1 - cipher alg: twofish-128 + cipher alg: aes-128 uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX format: luks - cipher mode: ctr + cipher mode: cbc slots: [0]: active: true diff --git a/tests/qemu-iotests/210 b/tests/qemu-iotests/210 index 5a62ed4dd1..a4dcc5fe59 100755 --- a/tests/qemu-iotests/210 +++ b/tests/qemu-iotests/210 @@ -83,8 +83,8 @@ with iotests.FilePath('t.luks') as disk_path, \ }, 'size': size, 'key-secret': 'keysec0', - 'cipher-alg': 'twofish-128', - 'cipher-mode': 'ctr', + 'cipher-alg': 'aes-128', + 'cipher-mode': 'cbc', 'ivgen-alg': 'plain64', 'ivgen-hash-alg': 'md5', 'hash-alg': 'sha1', diff --git a/tests/qemu-iotests/210.out b/tests/qemu-iotests/210.out index 55c0844370..96d9f749dd 100644 --- a/tests/qemu-iotests/210.out +++ b/tests/qemu-iotests/210.out @@ -59,7 +59,7 @@ Format specific information: {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} -{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cipher-alg": "twofish-128", "cipher-mode": "ctr", "driver": "luks", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.luks"}, "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0", "size": 67108864}}} +{"execute": "blockdev-create", "arguments": {"job-id": "job0", "options": {"cipher-alg": "aes-128", "cipher-mode": "cbc", "driver": "luks", "file": {"driver": "file", "filename": "TEST_DIR/PID-t.luks"}, "hash-alg": "sha1", "iter-time": 10, "ivgen-alg": "plain64", "ivgen-hash-alg": "md5", "key-secret": "keysec0", "size": 67108864}}} {"return": {}} {"execute": "job-dismiss", "arguments": {"id": "job0"}} {"return": {}} @@ -71,9 +71,9 @@ encrypted: yes Format specific information: ivgen alg: plain64 hash alg: sha1 - cipher alg: twofish-128 + cipher alg: aes-128 uuid: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX - cipher mode: ctr + cipher mode: cbc slots: [0]: active: true diff --git a/tests/qtest/am53c974-test.c b/tests/qtest/am53c974-test.c index 9b1e4211bd..d214a912b3 100644 --- a/tests/qtest/am53c974-test.c +++ b/tests/qtest/am53c974-test.c @@ -223,6 +223,34 @@ static void test_inflight_cancel_ok(void) qtest_quit(s); } +static void test_reset_before_transfer_ok(void) +{ + QTestState *s = qtest_init( + "-device am53c974,id=scsi " + "-device scsi-hd,drive=disk0 -drive " + "id=disk0,if=none,file=null-co://,format=raw -nodefaults"); + + qtest_outl(s, 0xcf8, 0x80001010); + qtest_outl(s, 0xcfc, 0xc000); + qtest_outl(s, 0xcf8, 0x80001004); + qtest_outw(s, 0xcfc, 0x01); + qtest_outl(s, 0xc007, 0x2500); + qtest_outl(s, 0xc00a, 0x410000); + qtest_outl(s, 0xc00a, 0x410000); + qtest_outw(s, 0xc00b, 0x0200); + qtest_outw(s, 0xc040, 0x03); + qtest_outw(s, 0xc009, 0x00); + qtest_outw(s, 0xc00b, 0x00); + qtest_outw(s, 0xc009, 0x00); + qtest_outw(s, 0xc00b, 0x00); + qtest_outw(s, 0xc009, 0x00); + qtest_outw(s, 0xc003, 0x1000); + qtest_outw(s, 0xc00b, 0x1000); + qtest_outl(s, 0xc00b, 0x9000); + qtest_outw(s, 0xc00b, 0x1000); + qtest_quit(s); +} + int main(int argc, char **argv) { const char *arch = qtest_get_arch(); @@ -248,6 +276,8 @@ int main(int argc, char **argv) test_cancelled_request_ok); qtest_add_func("am53c974/test_inflight_cancel_ok", test_inflight_cancel_ok); + qtest_add_func("am53c974/test_reset_before_transfer_ok", + test_reset_before_transfer_ok); } return g_test_run(); diff --git a/tests/qtest/fdc-test.c b/tests/qtest/fdc-test.c index 26b69f7c5c..8f6eee84a4 100644 --- a/tests/qtest/fdc-test.c +++ b/tests/qtest/fdc-test.c @@ -32,6 +32,9 @@ /* TODO actually test the results and get rid of this */ #define qmp_discard_response(...) qobject_unref(qmp(__VA_ARGS__)) +#define DRIVE_FLOPPY_BLANK \ + "-drive if=floppy,file=null-co://,file.read-zeroes=on,format=raw,size=1440k" + #define TEST_IMAGE_SIZE 1440 * 1024 #define FLOPPY_BASE 0x3f0 @@ -546,6 +549,40 @@ static void fuzz_registers(void) } } +static bool qtest_check_clang_sanitizer(void) +{ +#if defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer) + return true; +#else + g_test_skip("QEMU not configured using --enable-sanitizers"); + return false; +#endif +} +static void test_cve_2021_20196(void) +{ + QTestState *s; + + if (!qtest_check_clang_sanitizer()) { + return; + } + + s = qtest_initf("-nographic -m 32M -nodefaults " DRIVE_FLOPPY_BLANK); + + qtest_outw(s, 0x3f4, 0x0500); + qtest_outb(s, 0x3f5, 0x00); + qtest_outb(s, 0x3f5, 0x00); + qtest_outw(s, 0x3f4, 0x0000); + qtest_outb(s, 0x3f5, 0x00); + qtest_outw(s, 0x3f1, 0x0400); + qtest_outw(s, 0x3f4, 0x0000); + qtest_outw(s, 0x3f4, 0x0000); + qtest_outb(s, 0x3f5, 0x00); + qtest_outb(s, 0x3f5, 0x01); + qtest_outw(s, 0x3f1, 0x0500); + qtest_outb(s, 0x3f5, 0x00); + qtest_quit(s); +} + int main(int argc, char **argv) { int fd; @@ -576,6 +613,7 @@ int main(int argc, char **argv) qtest_add_func("/fdc/read_no_dma_18", test_read_no_dma_18); qtest_add_func("/fdc/read_no_dma_19", test_read_no_dma_19); qtest_add_func("/fdc/fuzz-registers", fuzz_registers); + qtest_add_func("/fdc/fuzz/cve_2021_20196", test_cve_2021_20196); ret = g_test_run(); diff --git a/tests/tcg/ppc64le/Makefile.target b/tests/tcg/ppc64le/Makefile.target index 5e65b1590d..ba2fde5ff1 100644 --- a/tests/tcg/ppc64le/Makefile.target +++ b/tests/tcg/ppc64le/Makefile.target @@ -9,18 +9,12 @@ PPC64LE_TESTS=bcdsub endif bcdsub: CFLAGS += -mpower8-vector -PPC64LE_TESTS += byte_reverse ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_POWER10),) +PPC64LE_TESTS += byte_reverse +endif +byte_reverse: CFLAGS += -mcpu=power10 run-byte_reverse: QEMU_OPTS+=-cpu POWER10 run-plugin-byte_reverse-with-%: QEMU_OPTS+=-cpu POWER10 -else -byte_reverse: - $(call skip-test, "BUILD of $@", "missing compiler support") -run-byte_reverse: - $(call skip-test, "RUN of byte_reverse", "not built") -run-plugin-byte_reverse-with-%: - $(call skip-test, "RUN of byte_reverse ($*)", "not built") -endif PPC64LE_TESTS += signal_save_restore_xer diff --git a/ui/curses.c b/ui/curses.c index e4f9588c3e..861d63244c 100644 --- a/ui/curses.c +++ b/ui/curses.c @@ -38,6 +38,10 @@ #include "ui/input.h" #include "sysemu/sysemu.h" +#if defined(__APPLE__) || defined(__OpenBSD__) +#define _XOPEN_SOURCE_EXTENDED 1 +#endif + /* KEY_EVENT is defined in wincon.h and in curses.h. Avoid redefinition. */ #undef KEY_EVENT #include diff --git a/ui/gtk-gl-area.c b/ui/gtk-gl-area.c index 461da7712f..01e4e74ee3 100644 --- a/ui/gtk-gl-area.c +++ b/ui/gtk-gl-area.c @@ -41,15 +41,16 @@ void gd_gl_area_draw(VirtualConsole *vc) #ifdef CONFIG_GBM QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; #endif - int ww, wh, y1, y2; + int ww, wh, ws, y1, y2; if (!vc->gfx.gls) { return; } gtk_gl_area_make_current(GTK_GL_AREA(vc->gfx.drawing_area)); - ww = gtk_widget_get_allocated_width(vc->gfx.drawing_area); - wh = gtk_widget_get_allocated_height(vc->gfx.drawing_area); + ws = gdk_window_get_scale_factor(gtk_widget_get_window(vc->gfx.drawing_area)); + ww = gtk_widget_get_allocated_width(vc->gfx.drawing_area) * ws; + wh = gtk_widget_get_allocated_height(vc->gfx.drawing_area) * ws; if (vc->gfx.scanout_mode) { if (!vc->gfx.guest_fb.framebuffer) { diff --git a/ui/gtk.c b/ui/gtk.c index d2892ea6b4..428f02f2df 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -589,11 +589,11 @@ void gd_hw_gl_flushed(void *vcon) VirtualConsole *vc = vcon; QemuDmaBuf *dmabuf = vc->gfx.guest_fb.dmabuf; - graphic_hw_gl_block(vc->gfx.dcl.con, false); - graphic_hw_gl_flushed(vc->gfx.dcl.con); qemu_set_fd_handler(dmabuf->fence_fd, NULL, NULL, NULL); close(dmabuf->fence_fd); dmabuf->fence_fd = -1; + graphic_hw_gl_block(vc->gfx.dcl.con, false); + graphic_hw_gl_flushed(vc->gfx.dcl.con); } /** DisplayState Callbacks (opengl version) **/ @@ -838,10 +838,11 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion, { VirtualConsole *vc = opaque; GtkDisplayState *s = vc->s; + GdkWindow *window; int x, y; int mx, my; int fbh, fbw; - int ww, wh; + int ww, wh, ws; if (!vc->gfx.ds) { return TRUE; @@ -850,8 +851,10 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion, fbw = surface_width(vc->gfx.ds) * vc->gfx.scale_x; fbh = surface_height(vc->gfx.ds) * vc->gfx.scale_y; - ww = gdk_window_get_width(gtk_widget_get_window(vc->gfx.drawing_area)); - wh = gdk_window_get_height(gtk_widget_get_window(vc->gfx.drawing_area)); + window = gtk_widget_get_window(vc->gfx.drawing_area); + ww = gdk_window_get_width(window); + wh = gdk_window_get_height(window); + ws = gdk_window_get_scale_factor(window); mx = my = 0; if (ww > fbw) { @@ -861,8 +864,8 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion, my = (wh - fbh) / 2; } - x = (motion->x - mx) / vc->gfx.scale_x; - y = (motion->y - my) / vc->gfx.scale_y; + x = (motion->x - mx) / vc->gfx.scale_x * ws; + y = (motion->y - my) / vc->gfx.scale_y * ws; if (qemu_input_is_absolute()) { if (x < 0 || y < 0 || diff --git a/ui/vnc-clipboard.c b/ui/vnc-clipboard.c index 9f077965d0..67284b556c 100644 --- a/ui/vnc-clipboard.c +++ b/ui/vnc-clipboard.c @@ -316,8 +316,10 @@ void vnc_server_cut_text_caps(VncState *vs) caps[1] = 0; vnc_clipboard_send(vs, 2, caps); - vs->cbpeer.name = "vnc"; - vs->cbpeer.update.notify = vnc_clipboard_notify; - vs->cbpeer.request = vnc_clipboard_request; - qemu_clipboard_peer_register(&vs->cbpeer); + if (!vs->cbpeer.update.notify) { + vs->cbpeer.name = "vnc"; + vs->cbpeer.update.notify = vnc_clipboard_notify; + vs->cbpeer.request = vnc_clipboard_request; + qemu_clipboard_peer_register(&vs->cbpeer); + } }