Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
e97deaae59
22
MAINTAINERS
22
MAINTAINERS
@ -324,7 +324,7 @@ F: disas/sparc.c
|
|||||||
X86 TCG CPUs
|
X86 TCG CPUs
|
||||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
M: Richard Henderson <richard.henderson@linaro.org>
|
M: Richard Henderson <richard.henderson@linaro.org>
|
||||||
M: Eduardo Habkost <ehabkost@redhat.com>
|
M: Eduardo Habkost <eduardo@habkost.net>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: target/i386/tcg/
|
F: target/i386/tcg/
|
||||||
F: tests/tcg/i386/
|
F: tests/tcg/i386/
|
||||||
@ -1628,7 +1628,7 @@ F: include/hw/i386/microvm.h
|
|||||||
F: pc-bios/bios-microvm.bin
|
F: pc-bios/bios-microvm.bin
|
||||||
|
|
||||||
Machine core
|
Machine core
|
||||||
M: Eduardo Habkost <ehabkost@redhat.com>
|
M: Eduardo Habkost <eduardo@habkost.net>
|
||||||
M: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
|
M: Marcel Apfelbaum <marcel.apfelbaum@gmail.com>
|
||||||
R: Philippe Mathieu-Daudé <philmd@redhat.com>
|
R: Philippe Mathieu-Daudé <philmd@redhat.com>
|
||||||
S: Supported
|
S: Supported
|
||||||
@ -2648,13 +2648,13 @@ F: backends/cryptodev*.c
|
|||||||
Python library
|
Python library
|
||||||
M: John Snow <jsnow@redhat.com>
|
M: John Snow <jsnow@redhat.com>
|
||||||
M: Cleber Rosa <crosa@redhat.com>
|
M: Cleber Rosa <crosa@redhat.com>
|
||||||
R: Eduardo Habkost <ehabkost@redhat.com>
|
R: Eduardo Habkost <eduardo@habkost.net>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: python/
|
F: python/
|
||||||
T: git https://gitlab.com/jsnow/qemu.git python
|
T: git https://gitlab.com/jsnow/qemu.git python
|
||||||
|
|
||||||
Python scripts
|
Python scripts
|
||||||
M: Eduardo Habkost <ehabkost@redhat.com>
|
M: Eduardo Habkost <eduardo@habkost.net>
|
||||||
M: Cleber Rosa <crosa@redhat.com>
|
M: Cleber Rosa <crosa@redhat.com>
|
||||||
S: Odd Fixes
|
S: Odd Fixes
|
||||||
F: scripts/*.py
|
F: scripts/*.py
|
||||||
@ -2730,7 +2730,7 @@ T: git https://github.com/mdroth/qemu.git qga
|
|||||||
QOM
|
QOM
|
||||||
M: Paolo Bonzini <pbonzini@redhat.com>
|
M: Paolo Bonzini <pbonzini@redhat.com>
|
||||||
R: Daniel P. Berrange <berrange@redhat.com>
|
R: Daniel P. Berrange <berrange@redhat.com>
|
||||||
R: Eduardo Habkost <ehabkost@redhat.com>
|
R: Eduardo Habkost <eduardo@habkost.net>
|
||||||
S: Supported
|
S: Supported
|
||||||
F: docs/qdev-device-use.txt
|
F: docs/qdev-device-use.txt
|
||||||
F: hw/core/qdev*
|
F: hw/core/qdev*
|
||||||
@ -2750,7 +2750,7 @@ F: tests/unit/check-qom-proplist.c
|
|||||||
F: tests/unit/test-qdev-global-props.c
|
F: tests/unit/test-qdev-global-props.c
|
||||||
|
|
||||||
QOM boilerplate conversion script
|
QOM boilerplate conversion script
|
||||||
M: Eduardo Habkost <ehabkost@redhat.com>
|
M: Eduardo Habkost <eduardo@habkost.net>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: scripts/codeconverter/
|
F: scripts/codeconverter/
|
||||||
|
|
||||||
@ -3469,7 +3469,7 @@ M: Alex Bennée <alex.bennee@linaro.org>
|
|||||||
M: Philippe Mathieu-Daudé <f4bug@amsat.org>
|
M: Philippe Mathieu-Daudé <f4bug@amsat.org>
|
||||||
M: Thomas Huth <thuth@redhat.com>
|
M: Thomas Huth <thuth@redhat.com>
|
||||||
R: Wainer dos Santos Moschetta <wainersm@redhat.com>
|
R: Wainer dos Santos Moschetta <wainersm@redhat.com>
|
||||||
R: Willian Rampazzo <willianr@redhat.com>
|
R: Beraldo Leal <bleal@redhat.com>
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: .github/lockdown.yml
|
F: .github/lockdown.yml
|
||||||
F: .gitlab-ci.yml
|
F: .gitlab-ci.yml
|
||||||
@ -3507,10 +3507,16 @@ W: https://trello.com/b/6Qi1pxVn/avocado-qemu
|
|||||||
R: Cleber Rosa <crosa@redhat.com>
|
R: Cleber Rosa <crosa@redhat.com>
|
||||||
R: Philippe Mathieu-Daudé <philmd@redhat.com>
|
R: Philippe Mathieu-Daudé <philmd@redhat.com>
|
||||||
R: Wainer dos Santos Moschetta <wainersm@redhat.com>
|
R: Wainer dos Santos Moschetta <wainersm@redhat.com>
|
||||||
R: Willian Rampazzo <willianr@redhat.com>
|
R: Beraldo Leal <bleal@redhat.com>
|
||||||
S: Odd Fixes
|
S: Odd Fixes
|
||||||
F: tests/avocado/
|
F: tests/avocado/
|
||||||
|
|
||||||
|
GitLab custom runner (Works On Arm Sponsored)
|
||||||
|
M: Alex Bennée <alex.bennee@linaro.org>
|
||||||
|
M: Philippe Mathieu-Daudé <f4bug@amsat.org>
|
||||||
|
S: Maintained
|
||||||
|
F: .gitlab-ci.d/custom-runners/ubuntu-20.04-aarch64.yml
|
||||||
|
|
||||||
Documentation
|
Documentation
|
||||||
-------------
|
-------------
|
||||||
Build system architecture
|
Build system architecture
|
||||||
|
@ -733,6 +733,15 @@ static inline bool need_replay_interrupt(int interrupt_request)
|
|||||||
static inline bool cpu_handle_interrupt(CPUState *cpu,
|
static inline bool cpu_handle_interrupt(CPUState *cpu,
|
||||||
TranslationBlock **last_tb)
|
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
|
/* Clear the interrupt flag now since we're processing
|
||||||
* cpu->interrupt_request and cpu->exit_request.
|
* cpu->interrupt_request and cpu->exit_request.
|
||||||
* Ensure zeroing happens before reading cpu->exit_request or
|
* Ensure zeroing happens before reading cpu->exit_request or
|
||||||
|
@ -2243,7 +2243,7 @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages,
|
|||||||
if (current_tb_modified) {
|
if (current_tb_modified) {
|
||||||
page_collection_unlock(pages);
|
page_collection_unlock(pages);
|
||||||
/* Force execution of one insn next time. */
|
/* 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();
|
mmap_unlock();
|
||||||
cpu_loop_exit_noexc(cpu);
|
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
|
#ifdef TARGET_HAS_PRECISE_SMC
|
||||||
if (current_tb_modified) {
|
if (current_tb_modified) {
|
||||||
/* Force execution of one insn next time. */
|
/* 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;
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1279,8 +1279,18 @@ static int vvfat_open(BlockDriverState *bs, QDict *options, int flags,
|
|||||||
|
|
||||||
qemu_co_mutex_init(&s->lock);
|
qemu_co_mutex_init(&s->lock);
|
||||||
|
|
||||||
ret = 0;
|
qemu_opts_del(opts);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
fail:
|
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);
|
qemu_opts_del(opts);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -3118,7 +3128,7 @@ static int enable_write_target(BlockDriverState *bs, Error **errp)
|
|||||||
int size = sector2cluster(s, s->sector_count);
|
int size = sector2cluster(s, s->sector_count);
|
||||||
QDict *options;
|
QDict *options;
|
||||||
|
|
||||||
s->used_clusters = calloc(size, 1);
|
s->used_clusters = g_malloc0(size);
|
||||||
|
|
||||||
array_init(&(s->commits), sizeof(commit_t));
|
array_init(&(s->commits), sizeof(commit_t));
|
||||||
|
|
||||||
@ -3166,8 +3176,6 @@ static int enable_write_target(BlockDriverState *bs, Error **errp)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
g_free(s->qcow_filename);
|
|
||||||
s->qcow_filename = NULL;
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,7 +320,6 @@ static void wctablet_chr_finalize(Object *obj)
|
|||||||
TabletChardev *tablet = WCTABLET_CHARDEV(obj);
|
TabletChardev *tablet = WCTABLET_CHARDEV(obj);
|
||||||
|
|
||||||
qemu_input_handler_unregister(tablet->hs);
|
qemu_input_handler_unregister(tablet->hs);
|
||||||
g_free(tablet);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wctablet_chr_open(Chardev *chr,
|
static void wctablet_chr_open(Chardev *chr,
|
||||||
|
106
docs/COLO-FT.txt
106
docs/COLO-FT.txt
@ -209,9 +209,9 @@ children.0=childs0 \
|
|||||||
|
|
||||||
|
|
||||||
3. On Secondary VM's QEMU monitor, issue command
|
3. On Secondary VM's QEMU monitor, issue command
|
||||||
{'execute':'qmp_capabilities'}
|
{"execute":"qmp_capabilities"}
|
||||||
{'execute': 'nbd-server-start', 'arguments': {'addr': {'type': 'inet', 'data': {'host': '0.0.0.0', 'port': '9999'} } } }
|
{"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": "nbd-server-add", "arguments": {"device": "parent0", "writable": true } }
|
||||||
|
|
||||||
Note:
|
Note:
|
||||||
a. The qmp command nbd-server-start and nbd-server-add must be run
|
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.
|
will be merged into the parent disk on failover.
|
||||||
|
|
||||||
4. On Primary VM's QEMU monitor, issue command:
|
4. On Primary VM's QEMU monitor, issue command:
|
||||||
{'execute':'qmp_capabilities'}
|
{"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": "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": "x-blockdev-change", "arguments":{"parent": "colo-disk0", "node": "replication0" } }
|
||||||
{'execute': 'migrate-set-capabilities', 'arguments': {'capabilities': [ {'capability': 'x-colo', 'state': true } ] } }
|
{"execute": "migrate-set-capabilities", "arguments": {"capabilities": [ {"capability": "x-colo", "state": true } ] } }
|
||||||
{'execute': 'migrate', 'arguments': {'uri': 'tcp:127.0.0.2:9998' } }
|
{"execute": "migrate", "arguments": {"uri": "tcp:127.0.0.2:9998" } }
|
||||||
|
|
||||||
Note:
|
Note:
|
||||||
a. There should be only one NBD Client for each primary disk.
|
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 ==
|
== Primary Failover ==
|
||||||
The Secondary died, resume on the Primary
|
The Secondary died, resume on the Primary
|
||||||
|
|
||||||
{'execute': 'x-blockdev-change', 'arguments':{ 'parent': 'colo-disk0', 'child': 'children.1'} }
|
{"execute": "x-blockdev-change", "arguments":{ "parent": "colo-disk0", "child": "children.1"} }
|
||||||
{'execute': 'human-monitor-command', 'arguments':{ 'command-line': 'drive_del replication0' } }
|
{"execute": "human-monitor-command", "arguments":{ "command-line": "drive_del replication0" } }
|
||||||
{'execute': 'object-del', 'arguments':{ 'id': 'comp0' } }
|
{"execute": "object-del", "arguments":{ "id": "comp0" } }
|
||||||
{'execute': 'object-del', 'arguments':{ 'id': 'iothread1' } }
|
{"execute": "object-del", "arguments":{ "id": "iothread1" } }
|
||||||
{'execute': 'object-del', 'arguments':{ 'id': 'm0' } }
|
{"execute": "object-del", "arguments":{ "id": "m0" } }
|
||||||
{'execute': 'object-del', 'arguments':{ 'id': 'redire0' } }
|
{"execute": "object-del", "arguments":{ "id": "redire0" } }
|
||||||
{'execute': 'object-del', 'arguments':{ 'id': 'redire1' } }
|
{"execute": "object-del", "arguments":{ "id": "redire1" } }
|
||||||
{'execute': 'x-colo-lost-heartbeat' }
|
{"execute": "x-colo-lost-heartbeat" }
|
||||||
|
|
||||||
== Secondary Failover ==
|
== Secondary Failover ==
|
||||||
The Primary died, resume on the Secondary and prepare to become the new Primary
|
The Primary died, resume on the Secondary and prepare to become the new Primary
|
||||||
|
|
||||||
{'execute': 'nbd-server-stop'}
|
{"execute": "nbd-server-stop"}
|
||||||
{'execute': 'x-colo-lost-heartbeat'}
|
{"execute": "x-colo-lost-heartbeat"}
|
||||||
|
|
||||||
{'execute': 'object-del', 'arguments':{ 'id': 'f2' } }
|
{"execute": "object-del", "arguments":{ "id": "f2" } }
|
||||||
{'execute': 'object-del', 'arguments':{ 'id': 'f1' } }
|
{"execute": "object-del", "arguments":{ "id": "f1" } }
|
||||||
{'execute': 'chardev-remove', 'arguments':{ 'id': 'red1' } }
|
{"execute": "chardev-remove", "arguments":{ "id": "red1" } }
|
||||||
{'execute': 'chardev-remove', 'arguments':{ 'id': 'red0' } }
|
{"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": "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": "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", "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": "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_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": "compare_out0", "backend": {"type": "socket", "data": {"addr": { "type": "inet", "data": { "host": "127.0.0.1", "port": "9005" } }, "server": false } } } }
|
||||||
|
|
||||||
== Primary resume replication ==
|
== Primary resume replication ==
|
||||||
Resume replication after new Secondary is up.
|
Resume replication after new Secondary is up.
|
||||||
|
|
||||||
Start the new Secondary (Steps 2 and 3 above), then on the Primary:
|
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:
|
Wait until disk is synced, then:
|
||||||
{'execute': 'stop'}
|
{"execute": "stop"}
|
||||||
{'execute': 'block-job-cancel', 'arguments':{ 'device': 'resync'} }
|
{"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": "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": "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-mirror", "id": "m0", "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": "redire0", "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": "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": "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": "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-set-capabilities", "arguments":{ "capabilities": [ {"capability": "x-colo", "state": true } ] } }
|
||||||
{'execute': 'migrate', 'arguments':{ 'uri': 'tcp:127.0.0.2:9998' } }
|
{"execute": "migrate", "arguments":{ "uri": "tcp:127.0.0.2:9998" } }
|
||||||
|
|
||||||
Note:
|
Note:
|
||||||
If this Primary previously was a Secondary, then we need to insert the
|
If this Primary previously was a Secondary, then we need to insert the
|
||||||
filters before the filter-rewriter by using 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 ==
|
== Secondary resume replication ==
|
||||||
Become Primary and resume replication after new Secondary is up. Note
|
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),
|
Start the new Secondary (Steps 2 and 3 above, but with primary_ip=127.0.0.2),
|
||||||
then on the old Secondary:
|
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:
|
Wait until disk is synced, then:
|
||||||
{'execute': 'stop'}
|
{"execute": "stop"}
|
||||||
{'execute': 'block-job-cancel', 'arguments':{ 'device': 'resync' } }
|
{"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": "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": "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-mirror", "id": "m0", "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": "redire0", "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": "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": "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": "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-set-capabilities", "arguments":{ "capabilities": [ {"capability": "x-colo", "state": true } ] } }
|
||||||
{'execute': 'migrate', 'arguments':{ 'uri': 'tcp:127.0.0.1:9998' } }
|
{"execute": "migrate", "arguments":{ "uri": "tcp:127.0.0.1:9998" } }
|
||||||
|
|
||||||
== TODO ==
|
== TODO ==
|
||||||
1. Support shared storage.
|
1. Support shared storage.
|
||||||
|
@ -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``
|
However, short-form booleans are deprecated and full explicit ``arg_name=on``
|
||||||
form is preferred.
|
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
|
QEMU Machine Protocol (QMP) commands
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
@ -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
|
backing file is missing or an incorrect format was specified) is an
|
||||||
error when ``-u`` is not used.
|
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
|
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
|
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
|
before or after the remaining changes being performed by amend, as
|
||||||
appropriate.
|
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
|
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
|
convert`` to create or modify an image that depends on a backing file
|
||||||
|
@ -156,15 +156,15 @@ Primary:
|
|||||||
children.0.driver=raw
|
children.0.driver=raw
|
||||||
|
|
||||||
Run qmp command in primary qemu:
|
Run qmp command in primary qemu:
|
||||||
{ 'execute': 'human-monitor-command',
|
{ "execute": "human-monitor-command",
|
||||||
'arguments': {
|
"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'
|
"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',
|
{ "execute": "x-blockdev-change",
|
||||||
'arguments': {
|
"arguments": {
|
||||||
'parent': 'colo1',
|
"parent": "colo1",
|
||||||
'node': 'nbd_client1'
|
"node": "nbd_client1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Note:
|
Note:
|
||||||
@ -189,21 +189,21 @@ Secondary:
|
|||||||
vote-threshold=1,children.0=childs1
|
vote-threshold=1,children.0=childs1
|
||||||
|
|
||||||
Then run qmp command in secondary qemu:
|
Then run qmp command in secondary qemu:
|
||||||
{ 'execute': 'nbd-server-start',
|
{ "execute": "nbd-server-start",
|
||||||
'arguments': {
|
"arguments": {
|
||||||
'addr': {
|
"addr": {
|
||||||
'type': 'inet',
|
"type": "inet",
|
||||||
'data': {
|
"data": {
|
||||||
'host': 'xxx',
|
"host": "xxx",
|
||||||
'port': 'xxx'
|
"port": "xxx"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{ 'execute': 'nbd-server-add',
|
{ "execute": "nbd-server-add",
|
||||||
'arguments': {
|
"arguments": {
|
||||||
'device': 'colo1',
|
"device": "colo1",
|
||||||
'writable': true
|
"writable": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -223,22 +223,22 @@ After Failover:
|
|||||||
Primary:
|
Primary:
|
||||||
The secondary host is down, so we should run the following qmp command
|
The secondary host is down, so we should run the following qmp command
|
||||||
to remove the nbd child from the quorum:
|
to remove the nbd child from the quorum:
|
||||||
{ 'execute': 'x-blockdev-change',
|
{ "execute": "x-blockdev-change",
|
||||||
'arguments': {
|
"arguments": {
|
||||||
'parent': 'colo1',
|
"parent": "colo1",
|
||||||
'child': 'children.1'
|
"child": "children.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
{ 'execute': 'human-monitor-command',
|
{ "execute": "human-monitor-command",
|
||||||
'arguments': {
|
"arguments": {
|
||||||
'command-line': 'drive_del xxxx'
|
"command-line": "drive_del xxxx"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Note: there is no qmp command to remove the blockdev now
|
Note: there is no qmp command to remove the blockdev now
|
||||||
|
|
||||||
Secondary:
|
Secondary:
|
||||||
The primary host is down, so we should do the following thing:
|
The primary host is down, so we should do the following thing:
|
||||||
{ 'execute': 'nbd-server-stop' }
|
{ "execute": "nbd-server-stop" }
|
||||||
|
|
||||||
Promote Secondary to Primary:
|
Promote Secondary to Primary:
|
||||||
see COLO-FT.txt
|
see COLO-FT.txt
|
||||||
|
@ -121,11 +121,11 @@ process for:
|
|||||||
|
|
||||||
1) executables, which include:
|
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
|
- Unit tests
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
============
|
============
|
||||||
Qemu modules
|
QEMU modules
|
||||||
============
|
============
|
||||||
|
|
||||||
.. kernel-doc:: include/qemu/module.h
|
.. kernel-doc:: include/qemu/module.h
|
||||||
|
@ -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.
|
access the files or devices the VM it's running on behalf of can access.
|
||||||
#### qemu-io model
|
#### qemu-io model
|
||||||
|
|
||||||
Qemu-io is a test harness used to test changes to the QEMU block backend
|
``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
|
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
|
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
|
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
|
QEMU one. This could be useful for disk device emulation, since its
|
||||||
emulation applications will need to include the QEMU block objects.
|
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 |
|
| rid | range MMIO is within |
|
||||||
+----------+------------------------+
|
+----------+------------------------+
|
||||||
| offset | offset withing *rid* |
|
| offset | offset within *rid* |
|
||||||
+----------+------------------------+
|
+----------+------------------------+
|
||||||
| type | e.g., load or store |
|
| type | e.g., load or store |
|
||||||
+----------+------------------------+
|
+----------+------------------------+
|
||||||
|
@ -228,7 +228,7 @@ Emulated hardware state
|
|||||||
|
|
||||||
Currently thanks to KVM work any access to IO memory is automatically
|
Currently thanks to KVM work any access to IO memory is automatically
|
||||||
protected by the global iothread mutex, also known as the BQL (Big
|
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.
|
do its own locking.
|
||||||
|
|
||||||
However IO memory isn't the only way emulated hardware state can be
|
However IO memory isn't the only way emulated hardware state can be
|
||||||
|
@ -14,7 +14,7 @@ support that device.
|
|||||||
Using only libqos APIs, the test has to manually take care of
|
Using only libqos APIs, the test has to manually take care of
|
||||||
covering all the setups, and build the correct command line.
|
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
|
line name is changed, all tests that use that will not work
|
||||||
properly anymore and need to be adjusted.
|
properly anymore and need to be adjusted.
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
.. _stable-process:
|
||||||
|
|
||||||
QEMU and the stable process
|
QEMU and the stable process
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
.. _coding-style:
|
||||||
|
|
||||||
=================
|
=================
|
||||||
QEMU 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
|
especially when (occasionally) the representation doesn't contain any letters
|
||||||
and especially in one line with other decimal numbers. Number groups are allowed
|
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
|
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
|
'#' printf flag
|
||||||
---------------
|
---------------
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
.. _submitting-a-patch:
|
||||||
|
|
||||||
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
|
should not be posted on the bug tracker, posted on forums, or
|
||||||
externally hosted and linked to. (We have other mailing lists too,
|
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
|
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
|
list.) ``git send-email`` (`step-by-step setup
|
||||||
mangling it (`hints for setting it
|
guide <https://git-send-email.io/>`__ and `hints and
|
||||||
up <http://lxr.free-electrons.com/source/Documentation/process/email-clients.rst>`__),
|
tips <https://elixir.bootlin.com/linux/latest/source/Documentation/process/email-clients.rst>`__)
|
||||||
but attachments can be used as a last resort on a first-time
|
works best for delivering the patch without mangling it, but
|
||||||
submission.
|
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.
|
- 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
|
Note, however, that maintainers are often willing to manually fix up
|
||||||
first-time contributions, since there is a learning curve involved in
|
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
|
the basic requirements. Use the table of contents as a reference, and
|
||||||
read the parts that you have doubts about.
|
read the parts that you have doubts about.
|
||||||
|
|
||||||
|
.. contents:: Table of Contents
|
||||||
|
|
||||||
.. _writing_your_patches:
|
.. _writing_your_patches:
|
||||||
|
|
||||||
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
|
that ``checkpatch.pl`` is not infallible, though, especially where C
|
||||||
preprocessor macros are involved; use some common sense too. See also:
|
preprocessor macros are involved; use some common sense too. See also:
|
||||||
|
|
||||||
- `QEMU Coding Style
|
- :ref:`coding-style`
|
||||||
<https://qemu-project.gitlab.io/qemu/devel/style.html>`__
|
|
||||||
|
|
||||||
- `Automate a checkpatch run on
|
- `Automate a checkpatch run on
|
||||||
commit <http://blog.vmsplice.net/2011/03/how-to-automatically-run-checkpatchpl.html>`__
|
commit <https://blog.vmsplice.net/2011/03/how-to-automatically-run-checkpatchpl.html>`__
|
||||||
|
|
||||||
.. _base_patches_against_current_git_master:
|
.. _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
|
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.
|
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 <http://patchew.org/QEMU/>`__, you should `add a
|
||||||
|
tag <https://lists.gnu.org/archive/html/qemu-devel/2017-08/msg01288.html>`__
|
||||||
|
line ``Based-on: $MESSAGE_ID`` to your cover letter to make the series
|
||||||
|
dependency obvious.
|
||||||
|
|
||||||
.. _split_up_long_patches:
|
.. _split_up_long_patches:
|
||||||
|
|
||||||
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
|
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
|
making the refactoring easier to review. Split up the series so that
|
||||||
semantic changes (or even function renames) are done in a separate patch
|
semantic changes (or even function renames) are done in a separate patch
|
||||||
from the raw code motion. Use a one-time setup of
|
from the raw code motion. Use a one-time setup of ``git config
|
||||||
``git config diff.renames true; git config diff.algorithm patience``
|
diff.renames true;`` ``git config diff.algorithm patience`` (refer to
|
||||||
(Refer to `git-config <http://git-scm.com/docs/git-config>`__.) The
|
`git-config <http://git-scm.com/docs/git-config>`__). The 'diff.renames'
|
||||||
``diff.renames`` property ensures file rename patches will be given in a
|
property ensures file rename patches will be given in a more compact
|
||||||
more compact representation that focuses only on the differences across
|
representation that focuses only on the differences across the file
|
||||||
the file rename, instead of showing the entire old file as a deletion
|
rename, instead of showing the entire old file as a deletion and the new
|
||||||
and the new file as an insertion. Meanwhile, the 'diff.algorithm'
|
file as an insertion. Meanwhile, the 'diff.algorithm' property ensures
|
||||||
property ensures that extracting a non-contiguous subset of one file
|
that extracting a non-contiguous subset of one file into a new file, but
|
||||||
into a new file, but where all extracted parts occur in the same order
|
where all extracted parts occur in the same order both before and after
|
||||||
both before and after the patch, will reduce churn in trying to treat
|
the patch, will reduce churn in trying to treat unrelated ``}`` lines in
|
||||||
unrelated ``}`` lines in the original file as separating hunks of
|
the original file as separating hunks of changes.
|
||||||
changes.
|
|
||||||
|
|
||||||
Ideally, a code motion patch can be reviewed by doing::
|
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.
|
same patch as your bug fix.
|
||||||
|
|
||||||
For smaller patches in less frequently changed areas of QEMU, consider
|
For smaller patches in less frequently changed areas of QEMU, consider
|
||||||
using the `trivial patches process
|
using the :ref:`trivial-patches` process.
|
||||||
<https://qemu-project.gitlab.io/qemu/devel/style.html>`__.
|
|
||||||
|
|
||||||
.. _write_a_meaningful_commit_message:
|
.. _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
|
(which becomes the email subject line) is "subsystem: single line
|
||||||
summary of change". Whether the "single line summary of change" starts
|
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
|
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
|
subject lines. Then there is a blank line and a more detailed
|
||||||
description of the patch, another blank and your Signed-off-by: line.
|
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
|
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
|
starts with "... so that" as a continuation of the subject line is
|
||||||
harder to follow).
|
harder to follow).
|
||||||
|
|
||||||
|
If your patch fixes a commit that is already in the repository, please
|
||||||
|
add an additional line with "Fixes: <at-least-12-digits-of-SHA-commit-id>
|
||||||
|
("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: <URL-of-the-bug>" 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: <URL-of-the-bug>" 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 <Testing#Continuous_Integration>`__ 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 <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:
|
||||||
|
|
||||||
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 <https://sourcehut.org/>`__ 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 <https://meta.sr.ht/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
|
||||||
|
<https://spacepub.space/videos/watch/ad258d23-0ac6-488c-83fc-2bacf578de3a>`__
|
||||||
|
shows the web-based ``git-send-email`` workflow. Documentation is
|
||||||
|
available `here
|
||||||
|
<https://man.sr.ht/git.sr.ht/#sending-patches-upstream>`__.
|
||||||
|
|
||||||
.. _cc_the_relevant_maintainer:
|
.. _cc_the_relevant_maintainer:
|
||||||
|
|
||||||
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
|
letter, with shallow threading (all patches in the series are
|
||||||
in-reply-to the cover letter, but not to each other); single unrelated
|
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,
|
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
|
Patches are easier to find if they start a new top-level thread, rather
|
||||||
than being buried in-reply-to another existing thread.
|
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:
|
||||||
|
|
||||||
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
|
||||||
<http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/SubmittingPatches?id=f6f94e2ab1b33f0082ac22d71f66385a60d8157f#n296>`__.
|
<http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/SubmittingPatches?id=f6f94e2ab1b33f0082ac22d71f66385a60d8157f#n297>`__.
|
||||||
This is vital or we will not be able to apply your patch! Please use
|
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).
|
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
|
Include a meaningful cover letter
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
This usually applies only to a series that includes multiple patches;
|
This is a requirement for any series with multiple patches (as it aids
|
||||||
the cover letter explains the overall goal of such a series.
|
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 <http://git-scm.com/docs/git-config>`__) will generate the
|
||||||
|
cover letter as needed.
|
||||||
|
|
||||||
When reviewers don't know your goal at the start of their review, they
|
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
|
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
|
of the patchset you're looking for review on, and why reviewers
|
||||||
should care
|
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:
|
||||||
|
|
||||||
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
|
For later versions of patches, include a summary of changes from
|
||||||
previous versions, but not in the commit message itself. In an email
|
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
|
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
|
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
|
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
|
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
|
diffstat here) is a good place to put remarks for people reading the
|
||||||
patch email, and this is where the "changes since previous version"
|
patch email, and this is where the "changes since previous version"
|
||||||
summary belongs. The
|
summary belongs. The `git-publish
|
||||||
`git-publish <https://github.com/stefanha/git-publish>`__ script can
|
<https://github.com/stefanha/git-publish>`__ script can help with
|
||||||
help with tracking a good summary across versions. Also, the
|
tracking a good summary across versions. Also, the `git-backport-diff
|
||||||
`git-backport-diff <https://github.com/codyprime/git-scripts>`__ script
|
<https://github.com/codyprime/git-scripts>`__ script can help focus
|
||||||
can help focus reviewers on what changed between revisions.
|
reviewers on what changed between revisions.
|
||||||
|
|
||||||
.. _tips_and_tricks:
|
.. _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
|
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,
|
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
|
including the word "ping" and ideally also a link to the page for the
|
||||||
patch on
|
patch on `patchew <https://patchew.org/QEMU/>`__ or
|
||||||
`patchwork <http://patchwork.ozlabs.org/project/qemu-devel/list/>`__ or
|
`lore.kernel.org <https://lore.kernel.org/qemu-devel/>`__. It's worth
|
||||||
GMANE. It's worth double-checking for reasons why your patch might have
|
double-checking for reasons why your patch might have been ignored
|
||||||
been ignored (forgot to CC the maintainer? annoyed people by failing to
|
(forgot to CC the maintainer? annoyed people by failing to respond to
|
||||||
respond to review comments on an earlier version?), but often for
|
review comments on an earlier version?), but often for less-maintained
|
||||||
less-maintained areas of QEMU patches do just slip through the cracks.
|
areas of QEMU patches do just slip through the cracks. If your ping is
|
||||||
If your ping is also ignored, ping again after another week or so. As
|
also ignored, ping again after another week or so. As the submitter, you
|
||||||
the submitter, you are the person with the most motivation to get your
|
are the person with the most motivation to get your patch applied, so
|
||||||
patch applied, so you have to be persistent.
|
you have to be persistent.
|
||||||
|
|
||||||
.. _is_my_patch_in:
|
.. _is_my_patch_in:
|
||||||
|
|
||||||
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
|
||||||
|
<http://patchew.org/QEMU/>`__ 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
|
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
|
area of code will send notification to the list that they are including
|
||||||
your patch in a particular staging branch. Periodically, the maintainer
|
your patch in a particular staging branch. Periodically, the maintainer
|
||||||
then sends a `pull request
|
then takes care of :ref:`submitting-a-pull-request`
|
||||||
<https://qemu-project.gitlab.io/qemu/devel/submitting-a-pull-request.html>`__
|
for aggregating topic branches into mainline QEMU. Generally, you do not
|
||||||
for aggregating topic branches into mainline qemu. Generally, you do not
|
|
||||||
need to send a pull request unless you have contributed enough patches
|
need to send a pull request unless you have contributed enough patches
|
||||||
to become a maintainer over a particular section of code. Maintainers
|
to become a maintainer over a particular section of code. Maintainers
|
||||||
may further modify your commit, by resolving simple merge conflicts or
|
may further modify your commit, by resolving simple merge conflicts or
|
||||||
|
@ -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
|
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
|
sent as simple patch emails to the mailing list (see our page on
|
||||||
`submitting a patch
|
:ref:`submitting-a-patch`
|
||||||
<https://qemu-project.gitlab.io/qemu/devel/submitting-a-patch.html>`__
|
|
||||||
for more details). Generally only existing submaintainers of a tree
|
for more details). Generally only existing submaintainers of a tree
|
||||||
will need to submit pull requests, although occasionally for a large
|
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
|
patch series we might ask a submitter to send a pull request. This page
|
||||||
|
@ -564,11 +564,11 @@ exploiting a QEMU security bug to compromise the host.
|
|||||||
QEMU binaries
|
QEMU binaries
|
||||||
~~~~~~~~~~~~~
|
~~~~~~~~~~~~~
|
||||||
|
|
||||||
By default, qemu-system-x86_64 is searched in $PATH to run the guest. If there
|
By default, ``qemu-system-x86_64`` is searched in $PATH to run the guest. If
|
||||||
isn't one, or if it is older than 2.10, the test won't work. In this case,
|
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+``.
|
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
|
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
|
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.
|
changing the ``-c`` option.
|
||||||
|
|
||||||
Integration tests using the Avocado Framework
|
Integration tests using the Avocado Framework
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
.. _trivial-patches:
|
||||||
|
|
||||||
Trivial Patches
|
Trivial Patches
|
||||||
===============
|
===============
|
||||||
|
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
=================
|
=================
|
||||||
Qemu UI subsystem
|
QEMU UI subsystem
|
||||||
=================
|
=================
|
||||||
|
|
||||||
Qemu Clipboard
|
QEMU Clipboard
|
||||||
--------------
|
--------------
|
||||||
|
|
||||||
.. kernel-doc:: include/ui/clipboard.h
|
.. kernel-doc:: include/ui/clipboard.h
|
||||||
|
@ -677,7 +677,7 @@ return a single text string::
|
|||||||
|
|
||||||
The ``HumanReadableText`` struct is intended to be used for all
|
The ``HumanReadableText`` struct is intended to be used for all
|
||||||
commands, under the ``x-`` name prefix that are returning unstructured
|
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.
|
the ``x-`` name prefix, as those should be using structured QAPI types.
|
||||||
|
|
||||||
Implementing the QMP command
|
Implementing the QMP command
|
||||||
|
@ -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
|
Normally, Hyper-V SynIC disables these hardware feature and suggests the guest
|
||||||
to use paravirtualized AutoEOI feature.
|
to use paravirtualized AutoEOI feature.
|
||||||
Note: enabling this feature on old hardware (without APICv/AVIC support) may
|
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
|
3.19. hv-no-nonarch-coresharing=on/off/auto
|
||||||
===========================================
|
===========================================
|
||||||
|
@ -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
|
For comprehensive test results, please, set up your test environment
|
||||||
properly.
|
properly.
|
||||||
|
|
||||||
Paths to binaries under test (SUTs) qemu-img and qemu-io are retrieved from
|
Paths to binaries under test (SUTs) ``qemu-img`` and ``qemu-io`` are retrieved
|
||||||
environment variables. If the environment check fails the runner will
|
from environment variables. If the environment check fails the runner will
|
||||||
use SUTs installed in system paths.
|
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.
|
the related environment variable if it's not installed in the system path.
|
||||||
For details about environment variables see qemu-iotests/check.
|
For details about environment variables see qemu-iotests/check.
|
||||||
|
|
||||||
|
@ -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
|
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
|
external NBD server tool (see qemu-nbd.c). The common code is placed
|
||||||
in nbd/*.
|
in nbd/*.
|
||||||
@ -7,11 +7,11 @@ The NBD protocol is specified here:
|
|||||||
https://github.com/NetworkBlockDevice/nbd/blob/master/doc/proto.md
|
https://github.com/NetworkBlockDevice/nbd/blob/master/doc/proto.md
|
||||||
|
|
||||||
The following paragraphs describe some specific properties of NBD
|
The following paragraphs describe some specific properties of NBD
|
||||||
protocol realization in Qemu.
|
protocol realization in QEMU.
|
||||||
|
|
||||||
= Metadata namespaces =
|
= 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
|
NBD protocol specification, and also defines an additional metadata
|
||||||
namespace "qemu".
|
namespace "qemu".
|
||||||
|
|
||||||
|
@ -313,7 +313,7 @@ The fields of the bitmaps extension are:
|
|||||||
The number of bitmaps contained in the image. Must be
|
The number of bitmaps contained in the image. Must be
|
||||||
greater than or equal to 1.
|
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.
|
image.
|
||||||
|
|
||||||
4 - 7: Reserved, must be zero.
|
4 - 7: Reserved, must be zero.
|
||||||
@ -775,7 +775,7 @@ Structure of a bitmap directory entry:
|
|||||||
2: extra_data_compatible
|
2: extra_data_compatible
|
||||||
This flags is meaningful when the extra data is
|
This flags is meaningful when the extra data is
|
||||||
unknown to the software (currently any 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
|
If it is set, the bitmap may be used as expected, extra
|
||||||
data must be left as is.
|
data must be left as is.
|
||||||
If it is not set, the bitmap must not be used, but
|
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
|
17: granularity_bits
|
||||||
Granularity bits. Valid values: 0 - 63.
|
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 is calculated as
|
||||||
granularity = 1 << granularity_bits
|
granularity = 1 << granularity_bits
|
||||||
@ -804,7 +804,7 @@ Structure of a bitmap directory entry:
|
|||||||
18 - 19: name_size
|
18 - 19: name_size
|
||||||
Size of the bitmap name. Must be non-zero.
|
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.
|
1023.
|
||||||
|
|
||||||
20 - 23: extra_data_size
|
20 - 23: extra_data_size
|
||||||
|
@ -123,7 +123,7 @@ Background info is here:
|
|||||||
guest side with pci-bridge-seat
|
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
|
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
|
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
|
is the pci id. We can match the pci id instead of the device path
|
||||||
|
@ -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.
|
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
|
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,
|
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
|
to prepare a downloaded Armbian image, first extract it and then increase
|
||||||
its size to one gigabyte as follows:
|
its size to one gigabyte as follows:
|
||||||
|
@ -77,11 +77,9 @@ To create an instance of this driver via QMP:
|
|||||||
"arguments": {
|
"arguments": {
|
||||||
"qom-type": "authz-simple",
|
"qom-type": "authz-simple",
|
||||||
"id": "authz0",
|
"id": "authz0",
|
||||||
"props": {
|
|
||||||
"identity": "fred"
|
"identity": "fred"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Or via the command line
|
Or via the command line
|
||||||
@ -110,7 +108,6 @@ To create an instance of this class via QMP:
|
|||||||
"arguments": {
|
"arguments": {
|
||||||
"qom-type": "authz-list",
|
"qom-type": "authz-list",
|
||||||
"id": "authz0",
|
"id": "authz0",
|
||||||
"props": {
|
|
||||||
"rules": [
|
"rules": [
|
||||||
{ "match": "fred", "policy": "allow", "format": "exact" },
|
{ "match": "fred", "policy": "allow", "format": "exact" },
|
||||||
{ "match": "bob", "policy": "allow", "format": "exact" },
|
{ "match": "bob", "policy": "allow", "format": "exact" },
|
||||||
@ -120,7 +117,6 @@ To create an instance of this class via QMP:
|
|||||||
"policy": "deny"
|
"policy": "deny"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Due to the way this driver requires setting nested properties, creating
|
Due to the way this driver requires setting nested properties, creating
|
||||||
@ -143,12 +139,10 @@ To create an instance of this class via QMP:
|
|||||||
"arguments": {
|
"arguments": {
|
||||||
"qom-type": "authz-list-file",
|
"qom-type": "authz-list-file",
|
||||||
"id": "authz0",
|
"id": "authz0",
|
||||||
"props": {
|
|
||||||
"filename": "/etc/qemu/myvm-vnc.acl",
|
"filename": "/etc/qemu/myvm-vnc.acl",
|
||||||
"refresh": true
|
"refresh": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
If ``refresh`` is ``yes``, inotify is used to monitor for changes
|
If ``refresh`` is ``yes``, inotify is used to monitor for changes
|
||||||
|
@ -49,7 +49,7 @@ future OS and toolchains are likely to target newer ABIs. The
|
|||||||
table that follows illustrates which ABI compatibility levels
|
table that follows illustrates which ABI compatibility levels
|
||||||
can be satisfied by the QEMU CPU models. Note that the table only
|
can be satisfied by the QEMU CPU models. Note that the table only
|
||||||
lists the long term stable CPU model versions (eg Haswell-v4).
|
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,
|
aliases which resolve to a different CPU model version,
|
||||||
depending on the machine type is in use.
|
depending on the machine type is in use.
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ These are specified using a special URL syntax.
|
|||||||
'iqn.2008-11.org.linux-kvm[:<name>]' but this can also be set from
|
'iqn.2008-11.org.linux-kvm[:<name>]' but this can also be set from
|
||||||
the command line or a configuration file.
|
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
|
timeout to detect stalled requests and force a reestablishment of the
|
||||||
session. The timeout is specified in seconds. The default is 0 which
|
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
|
means no timeout. Libiscsi 1.15.0 or greater is required for this
|
||||||
|
@ -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
|
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
|
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:
|
There are a number of parameters available:
|
||||||
|
|
||||||
|
@ -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
|
separate "inferior", where each CPU within the cluster is a separate
|
||||||
"thread". Most QEMU machine types have identical CPUs, so there is a
|
"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
|
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
|
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
|
U54 cores. Here the E51 is the only thread in the first inferior, and
|
||||||
the U54 cores are all threads in the second inferior.
|
the U54 cores are all threads in the second inferior.
|
||||||
|
@ -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
|
reporting the same CPUID guest is able to use full capacity of SGX, and KVM
|
||||||
doesn't need to emulate those info.
|
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.
|
notify such info to it before it can initialize SGX for guest.
|
||||||
|
|
||||||
Virtual EPC
|
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
|
requires explicit allocation of EPC to the VM. Similar to other specialized
|
||||||
memory types, e.g. hugetlbfs, EPC is exposed as a memory backend.
|
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
|
devices are parsed and realized. This limitation means that EPC does not
|
||||||
require -maxmem as EPC is not treated as {cold,hot}plugged memory.
|
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
|
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
|
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
|
that some kernels may not recognize all EPC sections, e.g. the Linux SGX driver
|
||||||
is hardwired to support only 8 EPC sections.
|
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::
|
to the VM and an additional 28M mapped but not allocated::
|
||||||
|
|
||||||
-object memory-backend-epc,id=mem1,size=64M,prealloc=on \
|
-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
|
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
|
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
|
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.
|
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
|
To simplify the implementation, EPC is always located above 4g in the guest
|
||||||
physical address space.
|
physical address space.
|
||||||
@ -62,7 +62,7 @@ physical address space.
|
|||||||
Migration
|
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
|
perspective, SGX doesn't support live migration, since both EPC and the SGX
|
||||||
key hierarchy are bound to the physical platform. However live migration
|
key hierarchy are bound to the physical platform. However live migration
|
||||||
can be supported in the sense if guest software stack can support recreating
|
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
|
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
|
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,
|
host CPU model, or explicitly enable SGX when using a built-in CPU model,
|
||||||
e.g. via ``-cpu <model>,+sgx`` or ``-cpu <model>,+sgx,+sgxlc``.
|
e.g. via ``-cpu <model>,+sgx`` or ``-cpu <model>,+sgx,+sgxlc``.
|
||||||
@ -101,7 +101,7 @@ controlled via -cpu are prefixed with "sgx", e.g.::
|
|||||||
sgx2
|
sgx2
|
||||||
sgxlc
|
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::
|
the provision and EINIT token keys::
|
||||||
|
|
||||||
-cpu host,-sgx-provisionkey,-sgx-tokenkey
|
-cpu host,-sgx-provisionkey,-sgx-tokenkey
|
||||||
@ -112,11 +112,11 @@ in hardware cannot be forced on via '-cpu'.
|
|||||||
Virtualize SGX Launch Control
|
Virtualize SGX Launch Control
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
Qemu SGX support for Launch Control (LC) is passive, in the sense that it
|
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
|
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
|
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
|
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
|
directly modify the LC configuration. Similar to hardware behavior, locking
|
||||||
the LC configuration to a non-Intel value is left to guest firmware. Unlike
|
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
|
host bios setting for SGX launch control(LC), there is no special bios setting
|
||||||
@ -126,7 +126,7 @@ creating VM with SGX.
|
|||||||
Feature Control
|
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,
|
(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,
|
i.e. existing guest firmware will automatically set SGX and SGX LC accordingly,
|
||||||
assuming said firmware supports fw_cfg.msr_feature_control.
|
assuming said firmware supports fw_cfg.msr_feature_control.
|
||||||
|
@ -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
|
kilobytes. You can add an ``M`` suffix to give the size in megabytes and
|
||||||
a ``G`` suffix for gigabytes.
|
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:
|
.. _disk_005fimages_005fsnapshot_005fmode:
|
||||||
|
|
||||||
|
@ -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
|
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
|
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
|
U-Boot's built-in "bootm" command, hence a legacy uImage format is required in
|
||||||
such senario.
|
such scenario.
|
||||||
|
|
||||||
Running Linux kernel
|
Running Linux kernel
|
||||||
--------------------
|
--------------------
|
||||||
|
@ -511,13 +511,13 @@ of an inet socket:
|
|||||||
|
|
||||||
|qemu_system| linux.img -hdb nbd+unix://?socket=/tmp/my_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::
|
.. parsed-literal::
|
||||||
|
|
||||||
qemu-nbd --socket=/tmp/my_socket my_disk.qcow2
|
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::
|
.. 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| linux1.img -hdb nbd+unix://?socket=/tmp/my_socket
|
||||||
|qemu_system| linux2.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:
|
own embedded NBD server), you must specify an export name in the URI:
|
||||||
|
|
||||||
.. parsed-literal::
|
.. parsed-literal::
|
||||||
|
@ -45,7 +45,7 @@ Shakti SDK can be used to generate the baremetal example UART applications.
|
|||||||
Binary would be generated in:
|
Binary would be generated in:
|
||||||
software/examples/uart_applns/loopback/output/loopback.shakti
|
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.
|
commands.
|
||||||
|
|
||||||
.. code-block:: bash
|
.. code-block:: bash
|
||||||
|
@ -311,7 +311,7 @@ containing one or more usernames and random keys::
|
|||||||
mkdir -m 0700 /tmp/keys
|
mkdir -m 0700 /tmp/keys
|
||||||
psktool -u rich -p /tmp/keys/keys.psk
|
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 \
|
qemu-nbd \
|
||||||
-t -x / \
|
-t -x / \
|
||||||
|
@ -273,14 +273,12 @@ A group can be created using the object-add QMP function:
|
|||||||
"arguments": {
|
"arguments": {
|
||||||
"qom-type": "throttle-group",
|
"qom-type": "throttle-group",
|
||||||
"id": "group0",
|
"id": "group0",
|
||||||
"props": {
|
|
||||||
"limits" : {
|
"limits" : {
|
||||||
"iops-total": 1000
|
"iops-total": 1000,
|
||||||
"bps-write": 2097152
|
"bps-write": 2097152
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
throttle-group has a 'limits' property (of type ThrottleLimits as
|
throttle-group has a 'limits' property (of type ThrottleLimits as
|
||||||
defined in qapi/block-core.json) which can be set on creation or later
|
defined in qapi/block-core.json) which can be set on creation or later
|
||||||
|
@ -127,9 +127,9 @@ by the used format or see the format descriptions below for details.
|
|||||||
.. option:: -S SIZE
|
.. option:: -S SIZE
|
||||||
|
|
||||||
Indicates the consecutive number of bytes that must contain only zeros
|
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
|
for ``qemu-img`` to create a sparse image during conversion. This value is
|
||||||
down to the nearest 512 bytes. You may use the common size suffixes like
|
rounded down to the nearest 512 bytes. You may use the common size suffixes
|
||||||
``k`` for kilobytes.
|
like ``k`` for kilobytes.
|
||||||
|
|
||||||
.. option:: -t CACHE
|
.. option:: -t CACHE
|
||||||
|
|
||||||
@ -431,7 +431,7 @@ Command description:
|
|||||||
suppressed from the destination image.
|
suppressed from the destination image.
|
||||||
|
|
||||||
*SPARSE_SIZE* indicates the consecutive number of bytes (defaults to 4k)
|
*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
|
conversion. If *SPARSE_SIZE* is 0, the source will not be scanned for
|
||||||
unallocated or zero sectors, and the destination image will always be
|
unallocated or zero sectors, and the destination image will always be
|
||||||
fully allocated.
|
fully allocated.
|
||||||
@ -447,7 +447,7 @@ Command description:
|
|||||||
If the ``-n`` option is specified, the target volume creation will be
|
If the ``-n`` option is specified, the target volume creation will be
|
||||||
skipped. This is useful for formats such as ``rbd`` if the target
|
skipped. This is useful for formats such as ``rbd`` if the target
|
||||||
volume has already been created with site specific options that cannot
|
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.
|
Out of order writes can be enabled with ``-W`` to improve performance.
|
||||||
This is only recommended for preallocated devices like host devices or other
|
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
|
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
|
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
|
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
|
If a relative path name is given, the backing file is looked up relative to
|
||||||
the directory containing *FILENAME*.
|
the directory containing *FILENAME*.
|
||||||
@ -684,7 +684,7 @@ Command description:
|
|||||||
|
|
||||||
Safe mode
|
Safe mode
|
||||||
This is the default mode and performs a real rebase operation. The
|
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*
|
will take care of keeping the guest-visible content of *FILENAME*
|
||||||
unchanged.
|
unchanged.
|
||||||
|
|
||||||
@ -697,7 +697,7 @@ Command description:
|
|||||||
exists.
|
exists.
|
||||||
|
|
||||||
Unsafe mode
|
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
|
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
|
without any checks on the file contents. The user must take care of
|
||||||
specifying the correct new backing file, or the guest-visible
|
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!
|
sizes accordingly. Failure to do so will result in data loss!
|
||||||
|
|
||||||
When shrinking images, the ``--shrink`` option must be given. This informs
|
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.
|
image's end.
|
||||||
|
|
||||||
After using this command to grow a disk image, you must use file system and
|
After using this command to grow a disk image, you must use file system and
|
||||||
|
@ -31,14 +31,14 @@ driver options if ``--image-opts`` is specified.
|
|||||||
|
|
||||||
*dev* is an NBD device.
|
*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*.
|
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
|
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
|
supported. The common object types that it makes sense to define are the
|
||||||
``secret`` object, which is used to supply passwords and/or encryption
|
``secret`` object, which is used to supply passwords and/or encryption
|
||||||
keys, and the ``tls-creds`` object, which is used to supply TLS
|
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
|
.. option:: -p, --port=PORT
|
||||||
|
|
||||||
@ -238,7 +238,7 @@ daemon:
|
|||||||
Expose the guest-visible contents of a qcow2 file via a block device
|
Expose the guest-visible contents of a qcow2 file via a block device
|
||||||
/dev/nbd0 (and possibly creating /dev/nbd0p1 and friends for
|
/dev/nbd0 (and possibly creating /dev/nbd0p1 and friends for
|
||||||
partitions found within), then disconnect the device when done.
|
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``
|
privileges, and may also require the execution of ``modprobe nbd``
|
||||||
to enable the kernel NBD client module. *CAUTION*: Do not use
|
to enable the kernel NBD client module. *CAUTION*: Do not use
|
||||||
this method to mount filesystems from an untrusted guest image - a
|
this method to mount filesystems from an untrusted guest image - a
|
||||||
|
@ -10,9 +10,10 @@ Synopsis
|
|||||||
Description
|
Description
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
qemu-storage-daemon provides disk image functionality from QEMU, qemu-img, and
|
``qemu-storage-daemon`` provides disk image functionality from QEMU,
|
||||||
qemu-nbd in a long-running process controlled via QMP commands without running
|
``qemu-img``, and ``qemu-nbd`` in a long-running process controlled via QMP
|
||||||
a virtual machine. It can export disk images, run block job operations, and
|
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
|
perform other disk-related operations. The daemon is controlled via a QMP
|
||||||
monitor and initial configuration from the command-line.
|
monitor and initial configuration from the command-line.
|
||||||
|
|
||||||
|
@ -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
|
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
|
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
|
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
|
``virtiofsd`` is running in a container with restricted privileges where it
|
||||||
access some attributes.
|
cannot access some attributes.
|
||||||
|
|
||||||
Mapping syntax
|
Mapping syntax
|
||||||
~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~
|
||||||
|
@ -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
|
protocol. In case of a USB U2F security key, it is a USB HID device
|
||||||
that implements the U2F protocol.
|
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:
|
guest USB FIDO/U2F security keys operating in two possible modes:
|
||||||
pass-through and emulated.
|
pass-through and emulated.
|
||||||
|
|
||||||
|
@ -94,7 +94,7 @@ static inline int cpu_gdb_index(CPUState *cpu)
|
|||||||
{
|
{
|
||||||
#if defined(CONFIG_USER_ONLY)
|
#if defined(CONFIG_USER_ONLY)
|
||||||
TaskState *ts = (TaskState *) cpu->opaque;
|
TaskState *ts = (TaskState *) cpu->opaque;
|
||||||
return ts->ts_tid;
|
return ts ? ts->ts_tid : -1;
|
||||||
#else
|
#else
|
||||||
return cpu->cpu_index + 1;
|
return cpu->cpu_index + 1;
|
||||||
#endif
|
#endif
|
||||||
|
@ -222,12 +222,30 @@ static void acpi_pcihp_eject_slot(AcpiPciHpState *s, unsigned bsel, unsigned slo
|
|||||||
PCIDevice *dev = PCI_DEVICE(qdev);
|
PCIDevice *dev = PCI_DEVICE(qdev);
|
||||||
if (PCI_SLOT(dev->devfn) == slot) {
|
if (PCI_SLOT(dev->devfn) == slot) {
|
||||||
if (!acpi_pcihp_pc_no_hotplug(s, dev)) {
|
if (!acpi_pcihp_pc_no_hotplug(s, dev)) {
|
||||||
|
/*
|
||||||
|
* 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_ctrl = qdev_get_hotplug_handler(qdev);
|
||||||
hotplug_handler_unplug(hotplug_ctrl, qdev, &error_abort);
|
hotplug_handler_unplug(hotplug_ctrl, qdev, &error_abort);
|
||||||
object_unparent(OBJECT(qdev));
|
object_unparent(OBJECT(qdev));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void acpi_pcihp_update_hotplug_bus(AcpiPciHpState *s, int bsel)
|
static void acpi_pcihp_update_hotplug_bus(AcpiPciHpState *s, int bsel)
|
||||||
@ -396,6 +414,12 @@ void acpi_pcihp_device_unplug_request_cb(HotplugHandler *hotplug_dev,
|
|||||||
return;
|
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);
|
s->acpi_pcihp_pci_status[bsel].down |= (1U << slot);
|
||||||
acpi_send_event(DEVICE(hotplug_dev), ACPI_PCI_HOTPLUG_STATUS);
|
acpi_send_event(DEVICE(hotplug_dev), ACPI_PCI_HOTPLUG_STATUS);
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
#include "sysemu/runstate.h"
|
#include "sysemu/runstate.h"
|
||||||
#include "sysemu/tpm.h"
|
#include "sysemu/tpm.h"
|
||||||
#include "sysemu/kvm.h"
|
#include "sysemu/kvm.h"
|
||||||
|
#include "sysemu/hvf.h"
|
||||||
#include "hw/loader.h"
|
#include "hw/loader.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qemu/bitops.h"
|
#include "qemu/bitops.h"
|
||||||
@ -1969,15 +1970,17 @@ static void machvirt_init(MachineState *machine)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vms->virt && kvm_enabled()) {
|
if (vms->virt && (kvm_enabled() || hvf_enabled())) {
|
||||||
error_report("mach-virt: KVM does not support providing "
|
error_report("mach-virt: %s does not support providing "
|
||||||
"Virtualization extensions to the guest CPU");
|
"Virtualization extensions to the guest CPU",
|
||||||
|
kvm_enabled() ? "KVM" : "HVF");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vms->mte && kvm_enabled()) {
|
if (vms->mte && (kvm_enabled() || hvf_enabled())) {
|
||||||
error_report("mach-virt: KVM does not support providing "
|
error_report("mach-virt: %s does not support providing "
|
||||||
"MTE to the guest CPU");
|
"MTE to the guest CPU",
|
||||||
|
kvm_enabled() ? "KVM" : "HVF");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,6 +61,12 @@
|
|||||||
} while (0)
|
} 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 */
|
/* qdev floppy bus */
|
||||||
|
|
||||||
@ -486,8 +492,7 @@ static void floppy_drive_realize(DeviceState *qdev, Error **errp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!dev->conf.blk) {
|
if (!dev->conf.blk) {
|
||||||
/* Anonymous BlockBackend for an empty drive */
|
dev->conf.blk = blk_create_empty_drive();
|
||||||
dev->conf.blk = blk_new(qemu_get_aio_context(), 0, BLK_PERM_ALL);
|
|
||||||
ret = blk_attach_dev(dev->conf.blk, qdev);
|
ret = blk_attach_dev(dev->conf.blk, qdev);
|
||||||
assert(ret == 0);
|
assert(ret == 0);
|
||||||
|
|
||||||
@ -1161,7 +1166,19 @@ static FDrive *get_drv(FDCtrl *fdctrl, int unit)
|
|||||||
|
|
||||||
static FDrive *get_cur_drv(FDCtrl *fdctrl)
|
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) */
|
/* Status A register : 0x00 (read-only) */
|
||||||
|
@ -354,6 +354,17 @@ static void escc_reset(DeviceState *d)
|
|||||||
cs->rregs[j] = 0;
|
cs->rregs[j] = 0;
|
||||||
cs->wregs[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);
|
escc_reset_chn(cs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -575,6 +586,20 @@ static void escc_mem_write(void *opaque, hwaddr addr,
|
|||||||
s->wregs[s->reg] = val;
|
s->wregs[s->reg] = val;
|
||||||
break;
|
break;
|
||||||
case W_TXCTRL1:
|
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:
|
case W_TXCTRL2:
|
||||||
s->wregs[s->reg] = val;
|
s->wregs[s->reg] = val;
|
||||||
escc_update_parameters(s);
|
escc_update_parameters(s);
|
||||||
|
@ -3629,6 +3629,12 @@ static void vtd_init(IntelIOMMUState *s)
|
|||||||
vtd_spte_rsvd_large[3] = VTD_SPTE_LPAGE_L3_RSVD_MASK(s->aw_bits,
|
vtd_spte_rsvd_large[3] = VTD_SPTE_LPAGE_L3_RSVD_MASK(s->aw_bits,
|
||||||
x86_iommu->dt_supported);
|
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)) {
|
if (x86_iommu_ir_supported(x86_iommu)) {
|
||||||
s->ecap |= VTD_ECAP_IR | VTD_ECAP_MHMV;
|
s->ecap |= VTD_ECAP_IR | VTD_ECAP_MHMV;
|
||||||
if (s->intr_eim == ON_OFF_AUTO_ON) {
|
if (s->intr_eim == ON_OFF_AUTO_ON) {
|
||||||
|
@ -388,6 +388,8 @@ typedef union VTDInvDesc VTDInvDesc;
|
|||||||
#define VTD_INV_DESC_DEVICE_IOTLB_RSVD_LO 0xffff0000ffe0fff8
|
#define VTD_INV_DESC_DEVICE_IOTLB_RSVD_LO 0xffff0000ffe0fff8
|
||||||
|
|
||||||
/* Rsvd field masks for spte */
|
/* Rsvd field masks for spte */
|
||||||
|
#define VTD_SPTE_SNP 0x800ULL
|
||||||
|
|
||||||
#define VTD_SPTE_PAGE_L1_RSVD_MASK(aw, dt_supported) \
|
#define VTD_SPTE_PAGE_L1_RSVD_MASK(aw, dt_supported) \
|
||||||
dt_supported ? \
|
dt_supported ? \
|
||||||
(0x800ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM | VTD_SL_TM)) : \
|
(0x800ULL | ~(VTD_HAW_MASK(aw) | VTD_SL_IGN_COM | VTD_SL_TM)) : \
|
||||||
|
@ -143,6 +143,8 @@ static void dt_add_pcie(MicrovmMachineState *mms)
|
|||||||
nr_pcie_buses = PCIE_ECAM_SIZE / PCIE_MMCFG_SIZE_MIN;
|
nr_pcie_buses = PCIE_ECAM_SIZE / PCIE_MMCFG_SIZE_MIN;
|
||||||
qemu_fdt_setprop_cells(mms->fdt, nodename, "bus-range", 0,
|
qemu_fdt_setprop_cells(mms->fdt, nodename, "bus-range", 0,
|
||||||
nr_pcie_buses - 1);
|
nr_pcie_buses - 1);
|
||||||
|
|
||||||
|
g_free(nodename);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dt_add_ioapic(MicrovmMachineState *mms, SysBusDevice *dev)
|
static void dt_add_ioapic(MicrovmMachineState *mms, SysBusDevice *dev)
|
||||||
@ -327,12 +329,17 @@ void dt_setup_microvm(MicrovmMachineState *mms)
|
|||||||
dt_setup_sys_bus(mms);
|
dt_setup_sys_bus(mms);
|
||||||
|
|
||||||
/* add to fw_cfg */
|
/* add to fw_cfg */
|
||||||
|
if (debug) {
|
||||||
fprintf(stderr, "%s: add etc/fdt to fw_cfg\n", __func__);
|
fprintf(stderr, "%s: add etc/fdt to fw_cfg\n", __func__);
|
||||||
|
}
|
||||||
fw_cfg_add_file(x86ms->fw_cfg, "etc/fdt", mms->fdt, size);
|
fw_cfg_add_file(x86ms->fw_cfg, "etc/fdt", mms->fdt, size);
|
||||||
|
|
||||||
if (debug) {
|
if (debug) {
|
||||||
fprintf(stderr, "%s: writing microvm.fdt\n", __func__);
|
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");
|
int ret = system("dtc -I dtb -O dts microvm.fdt");
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
fprintf(stderr, "%s: oops, dtc not installed?\n", __func__);
|
fprintf(stderr, "%s: oops, dtc not installed?\n", __func__);
|
||||||
|
@ -186,7 +186,9 @@ static void gicv3_redist_update_noirqset(GICv3CPUState *cs)
|
|||||||
* interrupt has reduced in priority and any other interrupt could
|
* interrupt has reduced in priority and any other interrupt could
|
||||||
* now be the new best one).
|
* 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);
|
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.
|
* pending interrupt, but don't set IRQ or FIQ lines.
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < s->num_cpu; i++) {
|
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);
|
gicv3_full_update_noirqset(s);
|
||||||
/* Repopulate the cache of GICv3CPUState pointers for target CPUs */
|
/* Repopulate the cache of GICv3CPUState pointers for target CPUs */
|
||||||
|
@ -653,7 +653,7 @@ static uint64_t icv_iar_read(CPUARMState *env, const ARMCPRegInfo *ri)
|
|||||||
|
|
||||||
if (thisgrp == grp && icv_hppi_can_preempt(cs, lr)) {
|
if (thisgrp == grp && icv_hppi_can_preempt(cs, lr)) {
|
||||||
intid = ich_lr_vintid(lr);
|
intid = ich_lr_vintid(lr);
|
||||||
if (intid < INTID_SECURE) {
|
if (!gicv3_intid_is_special(intid)) {
|
||||||
icv_activate_irq(cs, idx, grp);
|
icv_activate_irq(cs, idx, grp);
|
||||||
} else {
|
} else {
|
||||||
/* Interrupt goes from Pending to Invalid */
|
/* 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);
|
intid = icc_hppir0_value(cs, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(intid >= INTID_SECURE && intid <= INTID_SPURIOUS)) {
|
if (!gicv3_intid_is_special(intid)) {
|
||||||
icc_activate_irq(cs, 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);
|
intid = icc_hppir1_value(cs, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(intid >= INTID_SECURE && intid <= INTID_SPURIOUS)) {
|
if (!gicv3_intid_is_special(intid)) {
|
||||||
icc_activate_irq(cs, 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,
|
trace_gicv3_icv_eoir_write(ri->crm == 8 ? 0 : 1,
|
||||||
gicv3_redist_affid(cs), value);
|
gicv3_redist_affid(cs), value);
|
||||||
|
|
||||||
if (irq >= GICV3_MAXIRQ) {
|
if (gicv3_intid_is_special(irq)) {
|
||||||
/* Also catches special interrupt numbers and LPIs */
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -896,13 +896,14 @@ static bool its_writel(GICv3ITSState *s, hwaddr offset,
|
|||||||
|
|
||||||
switch (offset) {
|
switch (offset) {
|
||||||
case GITS_CTLR:
|
case GITS_CTLR:
|
||||||
s->ctlr |= (value & ~(s->ctlr));
|
if (value & R_GITS_CTLR_ENABLED_MASK) {
|
||||||
|
s->ctlr |= ITS_CTLR_ENABLED;
|
||||||
if (s->ctlr & ITS_CTLR_ENABLED) {
|
|
||||||
extract_table_params(s);
|
extract_table_params(s);
|
||||||
extract_cmdq_params(s);
|
extract_cmdq_params(s);
|
||||||
s->creadr = 0;
|
s->creadr = 0;
|
||||||
process_cmdq(s);
|
process_cmdq(s);
|
||||||
|
} else {
|
||||||
|
s->ctlr &= ~ITS_CTLR_ENABLED;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case GITS_CBASER:
|
case GITS_CBASER:
|
||||||
|
@ -50,8 +50,6 @@ static int gicv3_its_post_load(void *opaque, int version_id)
|
|||||||
|
|
||||||
static const VMStateDescription vmstate_its = {
|
static const VMStateDescription vmstate_its = {
|
||||||
.name = "arm_gicv3_its",
|
.name = "arm_gicv3_its",
|
||||||
.version_id = 1,
|
|
||||||
.minimum_version_id = 1,
|
|
||||||
.pre_save = gicv3_its_pre_save,
|
.pre_save = gicv3_its_pre_save,
|
||||||
.post_load = gicv3_its_post_load,
|
.post_load = gicv3_its_post_load,
|
||||||
.priority = MIG_PRI_GICV3_ITS,
|
.priority = MIG_PRI_GICV3_ITS,
|
||||||
|
@ -256,9 +256,10 @@ static MemTxResult gicr_writel(GICv3CPUState *cs, hwaddr offset,
|
|||||||
cs->gicr_ctlr |= GICR_CTLR_ENABLE_LPIS;
|
cs->gicr_ctlr |= GICR_CTLR_ENABLE_LPIS;
|
||||||
/* Check for any pending interr in pending table */
|
/* Check for any pending interr in pending table */
|
||||||
gicv3_redist_update_lpi(cs);
|
gicv3_redist_update_lpi(cs);
|
||||||
gicv3_redist_update(cs);
|
|
||||||
} else {
|
} else {
|
||||||
cs->gicr_ctlr &= ~GICR_CTLR_ENABLE_LPIS;
|
cs->gicr_ctlr &= ~GICR_CTLR_ENABLE_LPIS;
|
||||||
|
/* cs->hppi might have been an LPI; recalculate */
|
||||||
|
gicv3_redist_update(cs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return MEMTX_OK;
|
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
|
* 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)
|
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) {
|
if (level) {
|
||||||
gicv3_redist_check_lpi_priority(cs, irq);
|
gicv3_redist_check_lpi_priority(cs, irq);
|
||||||
|
gicv3_redist_update(cs);
|
||||||
} else {
|
} else {
|
||||||
if (irq == cs->hpplpi.irq) {
|
if (irq == cs->hpplpi.irq) {
|
||||||
gicv3_redist_update_lpi(cs);
|
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 */
|
/* set/clear the pending bit for this irq */
|
||||||
gicv3_redist_lpi_pending(cs, irq, level);
|
gicv3_redist_lpi_pending(cs, irq, level);
|
||||||
|
|
||||||
gicv3_redist_update(cs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level)
|
void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level)
|
||||||
|
@ -411,6 +411,19 @@ FIELD(MAPC, RDBASE, 16, 32)
|
|||||||
|
|
||||||
/* Functions internal to the emulated GICv3 */
|
/* 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:
|
* gicv3_redist_update:
|
||||||
* @cs: GICv3CPUState for this redistributor
|
* @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_set_irq(GICv3CPUState *cs, int irq, int level);
|
||||||
void gicv3_redist_process_lpi(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);
|
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);
|
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_redist_send_sgi(GICv3CPUState *cs, int grp, int irq, bool ns);
|
||||||
void gicv3_init_cpuif(GICv3State *s);
|
void gicv3_init_cpuif(GICv3State *s);
|
||||||
|
|
||||||
|
@ -718,6 +718,7 @@ static const VMStateDescription vmstate_pmu = {
|
|||||||
},
|
},
|
||||||
.subsections = (const VMStateDescription * []) {
|
.subsections = (const VMStateDescription * []) {
|
||||||
&vmstate_pmu_adb,
|
&vmstate_pmu_adb,
|
||||||
|
NULL
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -209,7 +209,14 @@ static void sifive_u_otp_realize(DeviceState *dev, Error **errp)
|
|||||||
TYPE_SIFIVE_U_OTP, SIFIVE_U_OTP_REG_SIZE);
|
TYPE_SIFIVE_U_OTP, SIFIVE_U_OTP_REG_SIZE);
|
||||||
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
|
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
|
||||||
|
|
||||||
|
dinfo = drive_get_next(IF_PFLASH);
|
||||||
|
if (!dinfo) {
|
||||||
dinfo = drive_get_next(IF_NONE);
|
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) {
|
if (dinfo) {
|
||||||
int ret;
|
int ret;
|
||||||
uint64_t perm;
|
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) {
|
if (blk_pread(s->blk, 0, s->fuse, filesize) != filesize) {
|
||||||
error_setg(errp, "failed to read the initial flash content");
|
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 */
|
/* Initialize all fuses' initial value to 0xFFs */
|
||||||
memset(s->fuse, 0xff, sizeof(s->fuse));
|
memset(s->fuse, 0xff, sizeof(s->fuse));
|
||||||
@ -259,13 +262,15 @@ static void sifive_u_otp_reset(DeviceState *dev)
|
|||||||
serial_data = s->serial;
|
serial_data = s->serial;
|
||||||
if (blk_pwrite(s->blk, index * SIFIVE_U_OTP_FUSE_WORD,
|
if (blk_pwrite(s->blk, index * SIFIVE_U_OTP_FUSE_WORD,
|
||||||
&serial_data, SIFIVE_U_OTP_FUSE_WORD, 0) < 0) {
|
&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);
|
serial_data = ~(s->serial);
|
||||||
if (blk_pwrite(s->blk, (index + 1) * SIFIVE_U_OTP_FUSE_WORD,
|
if (blk_pwrite(s->blk, (index + 1) * SIFIVE_U_OTP_FUSE_WORD,
|
||||||
&serial_data, SIFIVE_U_OTP_FUSE_WORD, 0) < 0) {
|
&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);
|
device_class_set_props(dc, sifive_u_otp_properties);
|
||||||
dc->realize = sifive_u_otp_realize;
|
dc->realize = sifive_u_otp_realize;
|
||||||
dc->reset = sifive_u_otp_reset;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const TypeInfo sifive_u_otp_info = {
|
static const TypeInfo sifive_u_otp_info = {
|
||||||
|
@ -929,8 +929,8 @@ void pcie_add_capability(PCIDevice *dev,
|
|||||||
uint16_t offset, uint16_t size)
|
uint16_t offset, uint16_t size)
|
||||||
{
|
{
|
||||||
assert(offset >= PCI_CONFIG_SPACE_SIZE);
|
assert(offset >= PCI_CONFIG_SPACE_SIZE);
|
||||||
assert(offset < offset + size);
|
assert(offset < (uint16_t)(offset + size));
|
||||||
assert(offset + size <= PCIE_CONFIG_SPACE_SIZE);
|
assert((uint16_t)(offset + size) <= PCIE_CONFIG_SPACE_SIZE);
|
||||||
assert(size >= 8);
|
assert(size >= 8);
|
||||||
assert(pci_is_express(dev));
|
assert(pci_is_express(dev));
|
||||||
|
|
||||||
|
@ -1414,7 +1414,7 @@ void spapr_store_hpte(PowerPCCPU *cpu, hwaddr ptex,
|
|||||||
kvmppc_write_hpte(ptex, pte0, pte1);
|
kvmppc_write_hpte(ptex, pte0, pte1);
|
||||||
} else {
|
} else {
|
||||||
if (pte0 & HPTE64_V_VALID) {
|
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
|
* When setting valid, we write PTE1 first. This ensures
|
||||||
* proper synchronization with the reading code in
|
* proper synchronization with the reading code in
|
||||||
@ -1430,7 +1430,7 @@ void spapr_store_hpte(PowerPCCPU *cpu, hwaddr ptex,
|
|||||||
* ppc_hash64_pteg_search()
|
* ppc_hash64_pteg_search()
|
||||||
*/
|
*/
|
||||||
smp_wmb();
|
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,
|
static void spapr_hpte_set_c(PPCVirtualHypervisor *vhyp, hwaddr ptex,
|
||||||
uint64_t pte1)
|
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);
|
SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
|
||||||
|
|
||||||
if (!spapr->htab) {
|
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,
|
static void spapr_hpte_set_r(PPCVirtualHypervisor *vhyp, hwaddr ptex,
|
||||||
uint64_t pte1)
|
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);
|
SpaprMachineState *spapr = SPAPR_MACHINE(vhyp);
|
||||||
|
|
||||||
if (!spapr->htab) {
|
if (!spapr->htab) {
|
||||||
|
@ -426,7 +426,7 @@ static void new_hpte_store(void *htab, uint64_t pteg, int slot,
|
|||||||
addr += slot * HASH_PTE_SIZE_64;
|
addr += slot * HASH_PTE_SIZE_64;
|
||||||
|
|
||||||
stq_p(addr, pte0);
|
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,
|
static int rehash_hpte(PowerPCCPU *cpu,
|
||||||
|
@ -894,6 +894,7 @@ void esp_hard_reset(ESPState *s)
|
|||||||
memset(s->wregs, 0, ESP_REGS);
|
memset(s->wregs, 0, ESP_REGS);
|
||||||
s->tchi_written = 0;
|
s->tchi_written = 0;
|
||||||
s->ti_size = 0;
|
s->ti_size = 0;
|
||||||
|
s->async_len = 0;
|
||||||
fifo8_reset(&s->fifo);
|
fifo8_reset(&s->fifo);
|
||||||
fifo8_reset(&s->cmdfifo);
|
fifo8_reset(&s->cmdfifo);
|
||||||
s->dma = 0;
|
s->dma = 0;
|
||||||
|
@ -231,7 +231,7 @@ static void balloon_stats_poll_cb(void *opaque)
|
|||||||
return;
|
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);
|
virtio_notify(vdev, s->svq);
|
||||||
g_free(s->stats_vq_elem);
|
g_free(s->stats_vq_elem);
|
||||||
s->stats_vq_elem = NULL;
|
s->stats_vq_elem = NULL;
|
||||||
@ -438,7 +438,7 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
|
|||||||
memory_region_unref(section.mr);
|
memory_region_unref(section.mr);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtqueue_push(vq, elem, offset);
|
virtqueue_push(vq, elem, 0);
|
||||||
virtio_notify(vdev, vq);
|
virtio_notify(vdev, vq);
|
||||||
g_free(elem);
|
g_free(elem);
|
||||||
virtio_balloon_pbp_free(&pbp);
|
virtio_balloon_pbp_free(&pbp);
|
||||||
@ -510,6 +510,7 @@ static bool get_free_page_hints(VirtIOBalloon *dev)
|
|||||||
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
|
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
|
||||||
VirtQueue *vq = dev->free_page_vq;
|
VirtQueue *vq = dev->free_page_vq;
|
||||||
bool ret = true;
|
bool ret = true;
|
||||||
|
int i;
|
||||||
|
|
||||||
while (dev->block_iothread) {
|
while (dev->block_iothread) {
|
||||||
qemu_cond_wait(&dev->free_page_cond, &dev->free_page_lock);
|
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) {
|
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,
|
for (i = 0; i < elem->in_num; i++) {
|
||||||
elem->in_sg[0].iov_len);
|
qemu_guest_free_page_hint(elem->in_sg[i].iov_base,
|
||||||
|
elem->in_sg[i].iov_len);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
virtqueue_push(vq, elem, 1);
|
virtqueue_push(vq, elem, 0);
|
||||||
g_free(elem);
|
g_free(elem);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -817,6 +817,17 @@ static char *virtio_mmio_bus_get_dev_path(DeviceState *dev)
|
|||||||
return path;
|
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)
|
static void virtio_mmio_bus_class_init(ObjectClass *klass, void *data)
|
||||||
{
|
{
|
||||||
BusClass *bus_class = BUS_CLASS(klass);
|
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_enabled = virtio_mmio_ioeventfd_enabled;
|
||||||
k->ioeventfd_assign = virtio_mmio_ioeventfd_assign;
|
k->ioeventfd_assign = virtio_mmio_ioeventfd_assign;
|
||||||
k->pre_plugged = virtio_mmio_pre_plugged;
|
k->pre_plugged = virtio_mmio_pre_plugged;
|
||||||
|
k->vmstate_change = virtio_mmio_vmstate_change;
|
||||||
k->has_variable_vring_alignment = true;
|
k->has_variable_vring_alignment = true;
|
||||||
bus_class->max_dev = 1;
|
bus_class->max_dev = 1;
|
||||||
bus_class->get_dev_path = virtio_mmio_bus_get_dev_path;
|
bus_class->get_dev_path = virtio_mmio_bus_get_dev_path;
|
||||||
|
@ -503,6 +503,7 @@ struct TranslationBlock {
|
|||||||
#define CF_USE_ICOUNT 0x00020000
|
#define CF_USE_ICOUNT 0x00020000
|
||||||
#define CF_INVALID 0x00040000 /* TB is stale. Set with @jmp_lock held */
|
#define CF_INVALID 0x00040000 /* TB is stale. Set with @jmp_lock held */
|
||||||
#define CF_PARALLEL 0x00080000 /* Generate code for a parallel context */
|
#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_MASK 0xff000000 /* Top 8 bits are cluster ID */
|
||||||
#define CF_CLUSTER_SHIFT 24
|
#define CF_CLUSTER_SHIFT 24
|
||||||
|
|
||||||
|
@ -21,7 +21,6 @@ static inline void gen_tb_start(const TranslationBlock *tb)
|
|||||||
{
|
{
|
||||||
TCGv_i32 count;
|
TCGv_i32 count;
|
||||||
|
|
||||||
tcg_ctx->exitreq_label = gen_new_label();
|
|
||||||
if (tb_cflags(tb) & CF_USE_ICOUNT) {
|
if (tb_cflags(tb) & CF_USE_ICOUNT) {
|
||||||
count = tcg_temp_local_new_i32();
|
count = tcg_temp_local_new_i32();
|
||||||
} else {
|
} else {
|
||||||
@ -42,7 +41,19 @@ static inline void gen_tb_start(const TranslationBlock *tb)
|
|||||||
icount_start_insn = tcg_last_op();
|
icount_start_insn = tcg_last_op();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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);
|
tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, tcg_ctx->exitreq_label);
|
||||||
|
}
|
||||||
|
|
||||||
if (tb_cflags(tb) & CF_USE_ICOUNT) {
|
if (tb_cflags(tb) & CF_USE_ICOUNT) {
|
||||||
tcg_gen_st16_i32(count, cpu_env,
|
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)));
|
tcgv_i32_arg(tcg_constant_i32(num_insns)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tcg_ctx->exitreq_label) {
|
||||||
gen_set_label(tcg_ctx->exitreq_label);
|
gen_set_label(tcg_ctx->exitreq_label);
|
||||||
tcg_gen_exit_tb(tb, TB_EXIT_REQUESTED);
|
tcg_gen_exit_tb(tb, TB_EXIT_REQUESTED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -3254,9 +3254,13 @@ int load_elf_binary(struct linux_binprm *bprm, struct image_info *info)
|
|||||||
* Otherwise, allocate a private page to hold them.
|
* Otherwise, allocate a private page to hold them.
|
||||||
*/
|
*/
|
||||||
if (TARGET_ARCH_HAS_SIGTRAMP_PAGE) {
|
if (TARGET_ARCH_HAS_SIGTRAMP_PAGE) {
|
||||||
abi_ulong tramp_page = target_mmap(0, TARGET_PAGE_SIZE,
|
abi_long tramp_page = target_mmap(0, TARGET_PAGE_SIZE,
|
||||||
PROT_READ | PROT_WRITE,
|
PROT_READ | PROT_WRITE,
|
||||||
MAP_PRIVATE | MAP_ANON, -1, 0);
|
MAP_PRIVATE | MAP_ANON, -1, 0);
|
||||||
|
if (tramp_page == -1) {
|
||||||
|
return -errno;
|
||||||
|
}
|
||||||
|
|
||||||
setup_sigtramp(tramp_page);
|
setup_sigtramp(tramp_page);
|
||||||
target_mprotect(tramp_page, TARGET_PAGE_SIZE, PROT_READ | PROT_EXEC);
|
target_mprotect(tramp_page, TARGET_PAGE_SIZE, PROT_READ | PROT_EXEC);
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,11 @@ static inline uintptr_t host_signal_pc(ucontext_t *uc)
|
|||||||
return uc->uc_mcontext.pc;
|
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)
|
static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc)
|
||||||
{
|
{
|
||||||
struct _aarch64_ctx *hdr;
|
struct _aarch64_ctx *hdr;
|
||||||
|
@ -15,24 +15,4 @@
|
|||||||
/* We have a safe-syscall.inc.S */
|
/* We have a safe-syscall.inc.S */
|
||||||
#define HAVE_SAFE_SYSCALL
|
#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
|
#endif
|
||||||
|
@ -16,6 +16,11 @@ static inline uintptr_t host_signal_pc(ucontext_t *uc)
|
|||||||
return uc->uc_mcontext.sc_pc;
|
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)
|
static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc)
|
||||||
{
|
{
|
||||||
uint32_t *pc = (uint32_t *)host_signal_pc(uc);
|
uint32_t *pc = (uint32_t *)host_signal_pc(uc);
|
||||||
|
@ -16,6 +16,11 @@ static inline uintptr_t host_signal_pc(ucontext_t *uc)
|
|||||||
return uc->uc_mcontext.arm_pc;
|
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)
|
static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -15,24 +15,4 @@
|
|||||||
/* We have a safe-syscall.inc.S */
|
/* We have a safe-syscall.inc.S */
|
||||||
#define HAVE_SAFE_SYSCALL
|
#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
|
#endif
|
||||||
|
@ -16,6 +16,11 @@ static inline uintptr_t host_signal_pc(ucontext_t *uc)
|
|||||||
return uc->uc_mcontext.gregs[REG_EIP];
|
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)
|
static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc)
|
||||||
{
|
{
|
||||||
return uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe
|
return uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe
|
||||||
|
@ -15,24 +15,4 @@
|
|||||||
/* We have a safe-syscall.inc.S */
|
/* We have a safe-syscall.inc.S */
|
||||||
#define HAVE_SAFE_SYSCALL
|
#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
|
#endif
|
||||||
|
@ -16,6 +16,11 @@ static inline uintptr_t host_signal_pc(ucontext_t *uc)
|
|||||||
return uc->uc_mcontext.pc;
|
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)
|
#if defined(__misp16) || defined(__mips_micromips)
|
||||||
#error "Unsupported encoding"
|
#error "Unsupported encoding"
|
||||||
#endif
|
#endif
|
||||||
|
@ -16,6 +16,11 @@ static inline uintptr_t host_signal_pc(ucontext_t *uc)
|
|||||||
return uc->uc_mcontext.regs->nip;
|
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)
|
static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc)
|
||||||
{
|
{
|
||||||
return uc->uc_mcontext.regs->trap != 0x400
|
return uc->uc_mcontext.regs->trap != 0x400
|
||||||
|
@ -15,24 +15,4 @@
|
|||||||
/* We have a safe-syscall.inc.S */
|
/* We have a safe-syscall.inc.S */
|
||||||
#define HAVE_SAFE_SYSCALL
|
#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
|
#endif
|
||||||
|
@ -16,6 +16,11 @@ static inline uintptr_t host_signal_pc(ucontext_t *uc)
|
|||||||
return uc->uc_mcontext.__gregs[REG_PC];
|
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)
|
static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
@ -11,24 +11,4 @@
|
|||||||
/* We have a safe-syscall.inc.S */
|
/* We have a safe-syscall.inc.S */
|
||||||
#define HAVE_SAFE_SYSCALL
|
#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
|
#endif
|
||||||
|
@ -16,6 +16,11 @@ static inline uintptr_t host_signal_pc(ucontext_t *uc)
|
|||||||
return uc->uc_mcontext.psw.addr;
|
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)
|
static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc)
|
||||||
{
|
{
|
||||||
uint16_t *pinsn = (uint16_t *)host_signal_pc(uc);
|
uint16_t *pinsn = (uint16_t *)host_signal_pc(uc);
|
||||||
|
@ -15,24 +15,4 @@
|
|||||||
/* We have a safe-syscall.inc.S */
|
/* We have a safe-syscall.inc.S */
|
||||||
#define HAVE_SAFE_SYSCALL
|
#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
|
#endif
|
||||||
|
@ -20,6 +20,15 @@ static inline uintptr_t host_signal_pc(ucontext_t *uc)
|
|||||||
#endif
|
#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)
|
static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc)
|
||||||
{
|
{
|
||||||
uint32_t insn = *(uint32_t *)host_signal_pc(uc);
|
uint32_t insn = *(uint32_t *)host_signal_pc(uc);
|
||||||
|
@ -15,6 +15,11 @@ static inline uintptr_t host_signal_pc(ucontext_t *uc)
|
|||||||
return uc->uc_mcontext.gregs[REG_RIP];
|
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)
|
static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc)
|
||||||
{
|
{
|
||||||
return uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe
|
return uc->uc_mcontext.gregs[REG_TRAPNO] == 0xe
|
||||||
|
@ -15,24 +15,4 @@
|
|||||||
/* We have a safe-syscall.inc.S */
|
/* We have a safe-syscall.inc.S */
|
||||||
#define HAVE_SAFE_SYSCALL
|
#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
|
#endif
|
||||||
|
@ -637,6 +637,10 @@
|
|||||||
IOCTL(LOOP_SET_STATUS64, IOC_W, MK_PTR(MK_STRUCT(STRUCT_loop_info64)))
|
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_GET_STATUS64, IOC_R, MK_PTR(MK_STRUCT(STRUCT_loop_info64)))
|
||||||
IOCTL(LOOP_CHANGE_FD, 0, TYPE_INT)
|
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_ADD, 0, TYPE_INT)
|
||||||
IOCTL(LOOP_CTL_REMOVE, 0, TYPE_INT)
|
IOCTL(LOOP_CTL_REMOVE, 0, TYPE_INT)
|
||||||
|
@ -96,6 +96,8 @@ struct loop_info64 {
|
|||||||
#define LOOP_CHANGE_FD 0x4C06
|
#define LOOP_CHANGE_FD 0x4C06
|
||||||
#define LOOP_SET_CAPACITY 0x4C07
|
#define LOOP_SET_CAPACITY 0x4C07
|
||||||
#define LOOP_SET_DIRECT_IO 0x4C08
|
#define LOOP_SET_DIRECT_IO 0x4C08
|
||||||
|
#define LOOP_SET_BLOCK_SIZE 0x4C09
|
||||||
|
#define LOOP_CONFIGURE 0x4C0A
|
||||||
|
|
||||||
/* /dev/loop-control interface */
|
/* /dev/loop-control interface */
|
||||||
#define LOOP_CTL_ADD 0x4C80
|
#define LOOP_CTL_ADD 0x4C80
|
||||||
|
@ -127,6 +127,9 @@
|
|||||||
#ifdef HAVE_SAFE_SYSCALL
|
#ifdef HAVE_SAFE_SYSCALL
|
||||||
/* The core part of this function is implemented in assembly */
|
/* The core part of this function is implemented in assembly */
|
||||||
extern long safe_syscall_base(int *pending, long number, ...);
|
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(...) \
|
#define safe_syscall(...) \
|
||||||
({ \
|
({ \
|
||||||
|
@ -31,6 +31,7 @@
|
|||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "signal-common.h"
|
#include "signal-common.h"
|
||||||
#include "host-signal.h"
|
#include "host-signal.h"
|
||||||
|
#include "safe-syscall.h"
|
||||||
|
|
||||||
static struct target_sigaction sigact_table[TARGET_NSIG];
|
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 */
|
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)
|
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
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void host_signal_handler(int host_sig, siginfo_t *info, void *puc)
|
static void host_signal_handler(int host_sig, siginfo_t *info, void *puc)
|
||||||
{
|
{
|
||||||
|
@ -197,8 +197,10 @@
|
|||||||
//#define DEBUG_ERESTARTSYS
|
//#define DEBUG_ERESTARTSYS
|
||||||
|
|
||||||
//#include <linux/msdos_fs.h>
|
//#include <linux/msdos_fs.h>
|
||||||
#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct linux_dirent [2])
|
#define VFAT_IOCTL_READDIR_BOTH \
|
||||||
#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct linux_dirent [2])
|
_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 _syscall0
|
||||||
#undef _syscall1
|
#undef _syscall1
|
||||||
@ -8154,6 +8156,159 @@ static int host_to_target_cpu_mask(const unsigned long *host_mask,
|
|||||||
return 0;
|
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)
|
#if defined(TARGET_NR_pivot_root) && defined(__NR_pivot_root)
|
||||||
_syscall2(int, pivot_root, const char *, new_root, const char *, put_old)
|
_syscall2(int, pivot_root, const char *, new_root, const char *, put_old)
|
||||||
#endif
|
#endif
|
||||||
@ -10244,162 +10399,11 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
|
|||||||
#endif
|
#endif
|
||||||
#ifdef TARGET_NR_getdents
|
#ifdef TARGET_NR_getdents
|
||||||
case TARGET_NR_getdents:
|
case TARGET_NR_getdents:
|
||||||
#ifdef EMULATE_GETDENTS_WITH_GETDENTS
|
return do_getdents(arg1, arg2, arg3);
|
||||||
#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;
|
|
||||||
#endif /* TARGET_NR_getdents */
|
#endif /* TARGET_NR_getdents */
|
||||||
#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
|
#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
|
||||||
case TARGET_NR_getdents64:
|
case TARGET_NR_getdents64:
|
||||||
{
|
return do_getdents64(arg1, arg2, arg3);
|
||||||
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;
|
|
||||||
#endif /* TARGET_NR_getdents64 */
|
#endif /* TARGET_NR_getdents64 */
|
||||||
#if defined(TARGET_NR__newselect)
|
#if defined(TARGET_NR__newselect)
|
||||||
case TARGET_NR__newselect:
|
case TARGET_NR__newselect:
|
||||||
|
@ -437,11 +437,11 @@ struct target_dirent {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct target_dirent64 {
|
struct target_dirent64 {
|
||||||
uint64_t d_ino;
|
abi_ullong d_ino;
|
||||||
int64_t d_off;
|
abi_llong d_off;
|
||||||
unsigned short d_reclen;
|
abi_ushort d_reclen;
|
||||||
unsigned char d_type;
|
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_SET_STATUS64 0x4C04
|
||||||
#define TARGET_LOOP_GET_STATUS64 0x4C05
|
#define TARGET_LOOP_GET_STATUS64 0x4C05
|
||||||
#define TARGET_LOOP_CHANGE_FD 0x4C06
|
#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_ADD 0x4C80
|
||||||
#define TARGET_LOOP_CTL_REMOVE 0x4C81
|
#define TARGET_LOOP_CTL_REMOVE 0x4C81
|
||||||
@ -2714,7 +2718,7 @@ struct linux_dirent {
|
|||||||
long d_ino;
|
long d_ino;
|
||||||
unsigned long d_off;
|
unsigned long d_off;
|
||||||
unsigned short d_reclen;
|
unsigned short d_reclen;
|
||||||
char d_name[256]; /* We must not include limits.h! */
|
char d_name[];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct linux_dirent64 {
|
struct linux_dirent64 {
|
||||||
@ -2722,7 +2726,7 @@ struct linux_dirent64 {
|
|||||||
int64_t d_off;
|
int64_t d_off;
|
||||||
unsigned short d_reclen;
|
unsigned short d_reclen;
|
||||||
unsigned char d_type;
|
unsigned char d_type;
|
||||||
char d_name[256];
|
char d_name[];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct target_mq_attr {
|
struct target_mq_attr {
|
||||||
|
@ -201,6 +201,12 @@ STRUCT(loop_info64,
|
|||||||
MK_ARRAY(TYPE_CHAR, 32), /* lo_encrypt_key */
|
MK_ARRAY(TYPE_CHAR, 32), /* lo_encrypt_key */
|
||||||
MK_ARRAY(TYPE_ULONGLONG, 2)) /* lo_init */
|
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 */
|
/* mag tape ioctls */
|
||||||
STRUCT(mtop, TYPE_SHORT, TYPE_INT)
|
STRUCT(mtop, TYPE_SHORT, TYPE_INT)
|
||||||
STRUCT(mtget, TYPE_LONG, TYPE_LONG, TYPE_LONG, TYPE_LONG, TYPE_LONG,
|
STRUCT(mtget, TYPE_LONG, TYPE_LONG, TYPE_LONG, TYPE_LONG, TYPE_LONG,
|
||||||
|
31
meson.build
31
meson.build
@ -329,9 +329,7 @@ if not get_option('hax').disabled()
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
if targetos == 'netbsd'
|
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'))
|
nvmm = cc.find_library('nvmm', required: get_option('nvmm'))
|
||||||
endif
|
|
||||||
if nvmm.found()
|
if nvmm.found()
|
||||||
accelerators += 'CONFIG_NVMM'
|
accelerators += 'CONFIG_NVMM'
|
||||||
endif
|
endif
|
||||||
@ -681,6 +679,9 @@ iconv = not_found
|
|||||||
curses = not_found
|
curses = not_found
|
||||||
if have_system and not get_option('curses').disabled()
|
if have_system and not get_option('curses').disabled()
|
||||||
curses_test = '''
|
curses_test = '''
|
||||||
|
#if defined(__APPLE__) || defined(__OpenBSD__)
|
||||||
|
#define _XOPEN_SOURCE_EXTENDED 1
|
||||||
|
#endif
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <curses.h>
|
#include <curses.h>
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
@ -704,7 +705,7 @@ if have_system and not get_option('curses').disabled()
|
|||||||
endif
|
endif
|
||||||
endforeach
|
endforeach
|
||||||
msg = get_option('curses').enabled() ? 'curses library not found' : ''
|
msg = get_option('curses').enabled() ? 'curses library not found' : ''
|
||||||
curses_compile_args = ['-DNCURSES_WIDECHAR']
|
curses_compile_args = ['-DNCURSES_WIDECHAR=1']
|
||||||
if curses.found()
|
if curses.found()
|
||||||
if cc.links(curses_test, args: curses_compile_args, dependencies: [curses])
|
if cc.links(curses_test, args: curses_compile_args, dependencies: [curses])
|
||||||
curses = declare_dependency(compile_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'))
|
cc.has_header_symbol('sys/inotify.h', 'inotify_init'))
|
||||||
config_host_data.set('CONFIG_INOTIFY1',
|
config_host_data.set('CONFIG_INOTIFY1',
|
||||||
cc.has_header_symbol('sys/inotify.h', 'inotify_init1'))
|
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',
|
config_host_data.set('CONFIG_MACHINE_BSWAP_H',
|
||||||
cc.has_header_symbol('machine/bswap.h', 'bswap32',
|
cc.has_header_symbol('machine/bswap.h', 'bswap32',
|
||||||
prefix: '''#include <sys/endian.h>
|
prefix: '''#include <sys/endian.h>
|
||||||
@ -1567,8 +1566,6 @@ config_host_data.set('CONFIG_SYSMACROS',
|
|||||||
cc.has_header_symbol('sys/sysmacros.h', 'makedev'))
|
cc.has_header_symbol('sys/sysmacros.h', 'makedev'))
|
||||||
config_host_data.set('HAVE_OPTRESET',
|
config_host_data.set('HAVE_OPTRESET',
|
||||||
cc.has_header_symbol('getopt.h', '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',
|
config_host_data.set('HAVE_IPPROTO_MPTCP',
|
||||||
cc.has_header_symbol('netinet/in.h', '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',
|
cc.has_member('struct stat', 'st_atim',
|
||||||
prefix: '#include <sys/stat.h>'))
|
prefix: '#include <sys/stat.h>'))
|
||||||
|
|
||||||
|
# has_type
|
||||||
|
config_host_data.set('CONFIG_IOVEC',
|
||||||
|
cc.has_type('struct iovec',
|
||||||
|
prefix: '#include <sys/uio.h>'))
|
||||||
|
config_host_data.set('HAVE_UTMPX',
|
||||||
|
cc.has_type('struct utmpx',
|
||||||
|
prefix: '#include <utmpx.h>'))
|
||||||
|
|
||||||
config_host_data.set('CONFIG_EVENTFD', cc.links('''
|
config_host_data.set('CONFIG_EVENTFD', cc.links('''
|
||||||
#include <sys/eventfd.h>
|
#include <sys/eventfd.h>
|
||||||
int main(void) { return eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); }'''))
|
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 <stddef.h>
|
#include <stddef.h>
|
||||||
int main(void) { return posix_madvise(NULL, 0, POSIX_MADV_DONTNEED); }'''))
|
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 <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
static void *f(void *p) { return NULL; }
|
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");
|
pthread_setname_np(thread, "QEMU");
|
||||||
return 0;
|
return 0;
|
||||||
}''', dependencies: threads))
|
}''', 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 <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
static void *f(void *p) { pthread_setname_np("QEMU"); return NULL; }
|
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
|
have_l2tpv3 = false
|
||||||
if not get_option('l2tpv3').disabled() and have_system
|
if not get_option('l2tpv3').disabled() and have_system
|
||||||
have_l2tpv3 = (cc.has_header_symbol('sys/socket.h', 'struct mmsghdr')
|
have_l2tpv3 = cc.has_type('struct mmsghdr',
|
||||||
and cc.has_header('linux/ip.h'))
|
prefix: gnu_source_prefix + '''
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <linux/ip.h>''')
|
||||||
endif
|
endif
|
||||||
config_host_data.set('CONFIG_L2TPV3', have_l2tpv3)
|
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
|
# xfs headers will not try to redefine structs from linux headers
|
||||||
# if this macro is set.
|
# if this macro is set.
|
||||||
config_host_data.set('HAVE_FSXATTR', cc.links('''
|
config_host_data.set('HAVE_FSXATTR', cc.links('''
|
||||||
#include <linux/fs.h>'
|
#include <linux/fs.h>
|
||||||
struct fsxattr foo;
|
struct fsxattr foo;
|
||||||
int main(void) {
|
int main(void) {
|
||||||
return 0;
|
return 0;
|
||||||
|
26
nbd/server.c
26
nbd/server.c
@ -1418,6 +1418,9 @@ static int nbd_receive_request(NBDClient *client, NBDRequest *request,
|
|||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
if (ret == 0) {
|
||||||
|
return -EIO;
|
||||||
|
}
|
||||||
|
|
||||||
/* Request
|
/* Request
|
||||||
[ 0 .. 3] magic (NBD_REQUEST_MAGIC)
|
[ 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) {
|
if (request->flags & NBD_CMD_FLAG_FAST_ZERO) {
|
||||||
flags |= BDRV_REQ_NO_FALLBACK;
|
flags |= BDRV_REQ_NO_FALLBACK;
|
||||||
}
|
}
|
||||||
ret = 0;
|
ret = blk_pwrite_zeroes(exp->common.blk, request->from, request->len,
|
||||||
/* FIXME simplify this when blk_pwrite_zeroes switches to 64-bit */
|
flags);
|
||||||
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;
|
|
||||||
}
|
|
||||||
return nbd_send_generic_reply(client, request->handle, ret,
|
return nbd_send_generic_reply(client, request->handle, ret,
|
||||||
"writing to file failed", errp);
|
"writing to file failed", errp);
|
||||||
|
|
||||||
@ -2529,16 +2524,7 @@ static coroutine_fn int nbd_handle_request(NBDClient *client,
|
|||||||
"flush failed", errp);
|
"flush failed", errp);
|
||||||
|
|
||||||
case NBD_CMD_TRIM:
|
case NBD_CMD_TRIM:
|
||||||
ret = 0;
|
ret = blk_co_pdiscard(exp->common.blk, request->from, request->len);
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
if (ret >= 0 && request->flags & NBD_CMD_FLAG_FUA) {
|
if (ret >= 0 && request->flags & NBD_CMD_FLAG_FUA) {
|
||||||
ret = blk_co_flush(exp->common.blk);
|
ret = blk_co_flush(exp->common.blk);
|
||||||
}
|
}
|
||||||
|
@ -170,9 +170,17 @@ static bool vhost_vdpa_check_peer_type(NetClientState *nc, ObjectClass *oc,
|
|||||||
return true;
|
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 = {
|
static NetClientInfo net_vhost_vdpa_info = {
|
||||||
.type = NET_CLIENT_DRIVER_VHOST_VDPA,
|
.type = NET_CLIENT_DRIVER_VHOST_VDPA,
|
||||||
.size = sizeof(VhostVDPAState),
|
.size = sizeof(VhostVDPAState),
|
||||||
|
.receive = vhost_vdpa_receive,
|
||||||
.cleanup = vhost_vdpa_cleanup,
|
.cleanup = vhost_vdpa_cleanup,
|
||||||
.has_vnet_hdr = vhost_vdpa_has_vnet_hdr,
|
.has_vnet_hdr = vhost_vdpa_has_vnet_hdr,
|
||||||
.has_ufo = vhost_vdpa_has_ufo,
|
.has_ufo = vhost_vdpa_has_ufo,
|
||||||
|
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user