Compare commits
69 Commits
master
...
stable-6.0
Author | SHA1 | Date |
---|---|---|
Michael Roth | 9654e55a74 | |
Jessica Clarke | db882c5c18 | |
Helge Deller | 62a012b0f4 | |
David Hildenbrand | 487a0956a1 | |
Xueming Li | c18bc855ad | |
Marcel Apfelbaum | 27c6f20d9d | |
Marcel Apfelbaum | 46d3c9e9f5 | |
Marcel Apfelbaum | d25db58213 | |
Li Qiang | 4787501893 | |
Li Qiang | 07daff4a9a | |
Li Qiang | 4dda63d7ed | |
Li Qiang | 457053998d | |
Li Qiang | 6ae68dfd10 | |
Li Qiang | c5300b8a94 | |
Li Qiang | 168299eb7d | |
Gerd Hoffmann | e204dca909 | |
Gerd Hoffmann | 606f618b3c | |
Gerd Hoffmann | 36403e8788 | |
David Hildenbrand | 5a964fe8d9 | |
Markus Armbruster | f22c225e23 | |
Nir Soffer | 916372e48f | |
Jason Wang | 5881d76ff4 | |
Peter Maydell | 2ae61d81a5 | |
Dr. David Alan Gilbert | 4fca33b4be | |
Philippe Mathieu-Daudé | 978c11b013 | |
Philippe Mathieu-Daudé | 21611dd0a5 | |
Pavel Pisa | 4d3cfb2f6b | |
David Hildenbrand | 7999d5b12f | |
Klaus Jensen | 6576f6ab87 | |
Klaus Jensen | bef905cd8a | |
Gollu Appalanaidu | aa99651295 | |
Igor Mammedov | 765ed56e76 | |
Igor Mammedov | b989641145 | |
Igor Mammedov | e23fe27ed9 | |
Leonardo Bras | 22de6752c1 | |
Philippe Mathieu-Daudé | 747fd3cb13 | |
Philippe Mathieu-Daudé | 43844c2fb2 | |
Philippe Mathieu-Daudé | a1c966bdf4 | |
Philippe Mathieu-Daudé | 0a7e2c99f9 | |
Philippe Mathieu-Daudé | 8d5c255a25 | |
Philippe Mathieu-Daudé | 738ff4bf07 | |
Philippe Mathieu-Daudé | 7e84d58e8b | |
Philippe Mathieu-Daudé | 072a8d3693 | |
Philippe Mathieu-Daudé | 0a579d4389 | |
Richard Henderson | 059ad82f38 | |
Richard Henderson | 1a0a1c4964 | |
Zhenzhong Duan | cdb8a71e2e | |
Kunkun Jiang | 5b55370e28 | |
Peng Liang | d1000ee07b | |
Mark Cave-Ayland | b6f5c02f5f | |
Mark Cave-Ayland | 44e5878ce3 | |
Jason Wang | 8d719825d9 | |
Paolo Bonzini | ad8c49081a | |
Kevin Wolf | fcfe1509a1 | |
Stefan Hajnoczi | 9b0ee423a1 | |
Paolo Bonzini | 5b96b36a61 | |
Paolo Bonzini | c675ba821c | |
Paolo Bonzini | 203f0ba144 | |
Paolo Bonzini | 701ff59cc4 | |
Paolo Bonzini | 4e1eef8611 | |
Max Filippov | ab33188125 | |
Paolo Bonzini | b20eff3ba4 | |
Giuseppe Musacchio | 59ac5e6d61 | |
Richard Henderson | e2258e5279 | |
Li Zhijian | fdf58b451b | |
Stefan Reiter | 318b076356 | |
Greg Kurz | c1d1c0b4c3 | |
Richard Henderson | 5d0c78455e | |
Zenghui Yu | 1513997aa2 |
|
@ -1621,10 +1621,20 @@ void audio_cleanup(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool vmstate_audio_needed(void *opaque)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Never needed, this vmstate only exists in case
|
||||||
|
* an old qemu sends it to us.
|
||||||
|
*/
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static const VMStateDescription vmstate_audio = {
|
static const VMStateDescription vmstate_audio = {
|
||||||
.name = "audio",
|
.name = "audio",
|
||||||
.version_id = 1,
|
.version_id = 1,
|
||||||
.minimum_version_id = 1,
|
.minimum_version_id = 1,
|
||||||
|
.needed = vmstate_audio_needed,
|
||||||
.fields = (VMStateField[]) {
|
.fields = (VMStateField[]) {
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
}
|
}
|
||||||
|
|
|
@ -2163,9 +2163,9 @@ static QCryptoTLSCreds *nbd_get_tls_creds(const char *id, Error **errp)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) {
|
if (!qcrypto_tls_creds_check_endpoint(creds,
|
||||||
error_setg(errp,
|
QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT,
|
||||||
"Expecting TLS credentials with a client endpoint");
|
errp)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
object_ref(obj);
|
object_ref(obj);
|
||||||
|
|
22
block/nvme.c
22
block/nvme.c
|
@ -1030,7 +1030,29 @@ try_map:
|
||||||
r = qemu_vfio_dma_map(s->vfio,
|
r = qemu_vfio_dma_map(s->vfio,
|
||||||
qiov->iov[i].iov_base,
|
qiov->iov[i].iov_base,
|
||||||
len, true, &iova);
|
len, true, &iova);
|
||||||
|
if (r == -ENOSPC) {
|
||||||
|
/*
|
||||||
|
* In addition to the -ENOMEM error, the VFIO_IOMMU_MAP_DMA
|
||||||
|
* ioctl returns -ENOSPC to signal the user exhausted the DMA
|
||||||
|
* mappings available for a container since Linux kernel commit
|
||||||
|
* 492855939bdb ("vfio/type1: Limit DMA mappings per container",
|
||||||
|
* April 2019, see CVE-2019-3882).
|
||||||
|
*
|
||||||
|
* This block driver already handles this error path by checking
|
||||||
|
* for the -ENOMEM error, so we directly replace -ENOSPC by
|
||||||
|
* -ENOMEM. Beside, -ENOSPC has a specific meaning for blockdev
|
||||||
|
* coroutines: it triggers BLOCKDEV_ON_ERROR_ENOSPC and
|
||||||
|
* BLOCK_ERROR_ACTION_STOP which stops the VM, asking the operator
|
||||||
|
* to add more storage to the blockdev. Not something we can do
|
||||||
|
* easily with an IOMMU :)
|
||||||
|
*/
|
||||||
|
r = -ENOMEM;
|
||||||
|
}
|
||||||
if (r == -ENOMEM && retry) {
|
if (r == -ENOMEM && retry) {
|
||||||
|
/*
|
||||||
|
* We exhausted the DMA mappings available for our container:
|
||||||
|
* recycle the volatile IOVA mappings.
|
||||||
|
*/
|
||||||
retry = false;
|
retry = false;
|
||||||
trace_nvme_dma_flush_queue_wait(s);
|
trace_nvme_dma_flush_queue_wait(s);
|
||||||
if (s->dma_map_count) {
|
if (s->dma_map_count) {
|
||||||
|
|
|
@ -108,9 +108,9 @@ static QCryptoTLSCreds *nbd_get_tls_creds(const char *id, Error **errp)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
|
if (!qcrypto_tls_creds_check_endpoint(creds,
|
||||||
error_setg(errp,
|
QCRYPTO_TLS_CREDS_ENDPOINT_SERVER,
|
||||||
"Expecting TLS credentials with a server endpoint");
|
errp)) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
object_ref(obj);
|
object_ref(obj);
|
||||||
|
|
|
@ -1402,18 +1402,12 @@ static void qmp_chardev_open_socket(Chardev *chr,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
object_ref(OBJECT(s->tls_creds));
|
object_ref(OBJECT(s->tls_creds));
|
||||||
if (is_listen) {
|
if (!qcrypto_tls_creds_check_endpoint(s->tls_creds,
|
||||||
if (s->tls_creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
|
is_listen
|
||||||
error_setg(errp, "%s",
|
? QCRYPTO_TLS_CREDS_ENDPOINT_SERVER
|
||||||
"Expected TLS credentials for server endpoint");
|
: QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT,
|
||||||
return;
|
errp)) {
|
||||||
}
|
return;
|
||||||
} else {
|
|
||||||
if (s->tls_creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) {
|
|
||||||
error_setg(errp, "%s",
|
|
||||||
"Expected TLS credentials for client endpoint");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s->tls_authz = g_strdup(sock->tls_authz);
|
s->tls_authz = g_strdup(sock->tls_authz);
|
||||||
|
|
|
@ -2192,9 +2192,11 @@ static THREAD int tls_var;
|
||||||
int main(void) { return tls_var; }
|
int main(void) { return tls_var; }
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
# Check we support --no-pie first; we will need this for building ROMs.
|
# Check we support -fno-pie and -no-pie first; we will need the former for
|
||||||
|
# building ROMs, and both for everything if --disable-pie is passed.
|
||||||
if compile_prog "-Werror -fno-pie" "-no-pie"; then
|
if compile_prog "-Werror -fno-pie" "-no-pie"; then
|
||||||
CFLAGS_NOPIE="-fno-pie"
|
CFLAGS_NOPIE="-fno-pie"
|
||||||
|
LDFLAGS_NOPIE="-no-pie"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "$static" = "yes"; then
|
if test "$static" = "yes"; then
|
||||||
|
@ -2210,6 +2212,7 @@ if test "$static" = "yes"; then
|
||||||
fi
|
fi
|
||||||
elif test "$pie" = "no"; then
|
elif test "$pie" = "no"; then
|
||||||
CONFIGURE_CFLAGS="$CFLAGS_NOPIE $CONFIGURE_CFLAGS"
|
CONFIGURE_CFLAGS="$CFLAGS_NOPIE $CONFIGURE_CFLAGS"
|
||||||
|
CONFIGURE_LDFLAGS="$LDFLAGS_NOPIE $CONFIGURE_LDFLAGS"
|
||||||
elif compile_prog "-Werror -fPIE -DPIE" "-pie"; then
|
elif compile_prog "-Werror -fPIE -DPIE" "-pie"; then
|
||||||
CONFIGURE_CFLAGS="-fPIE -DPIE $CONFIGURE_CFLAGS"
|
CONFIGURE_CFLAGS="-fPIE -DPIE $CONFIGURE_CFLAGS"
|
||||||
CONFIGURE_LDFLAGS="-pie $CONFIGURE_LDFLAGS"
|
CONFIGURE_LDFLAGS="-pie $CONFIGURE_LDFLAGS"
|
||||||
|
@ -3331,7 +3334,7 @@ if ! test "$gio" = "no"; then
|
||||||
gio_cflags=$($pkg_config --cflags gio-2.0)
|
gio_cflags=$($pkg_config --cflags gio-2.0)
|
||||||
gio_libs=$($pkg_config --libs gio-2.0)
|
gio_libs=$($pkg_config --libs gio-2.0)
|
||||||
gdbus_codegen=$($pkg_config --variable=gdbus_codegen gio-2.0)
|
gdbus_codegen=$($pkg_config --variable=gdbus_codegen gio-2.0)
|
||||||
if [ ! -x "$gdbus_codegen" ]; then
|
if ! has "$gdbus_codegen"; then
|
||||||
gdbus_codegen=
|
gdbus_codegen=
|
||||||
fi
|
fi
|
||||||
# Check that the libraries actually work -- Ubuntu 18.04 ships
|
# Check that the libraries actually work -- Ubuntu 18.04 ships
|
||||||
|
@ -5678,6 +5681,8 @@ if test "$gio" = "yes" ; then
|
||||||
echo "CONFIG_GIO=y" >> $config_host_mak
|
echo "CONFIG_GIO=y" >> $config_host_mak
|
||||||
echo "GIO_CFLAGS=$gio_cflags" >> $config_host_mak
|
echo "GIO_CFLAGS=$gio_cflags" >> $config_host_mak
|
||||||
echo "GIO_LIBS=$gio_libs" >> $config_host_mak
|
echo "GIO_LIBS=$gio_libs" >> $config_host_mak
|
||||||
|
fi
|
||||||
|
if test "$gdbus_codegen" != "" ; then
|
||||||
echo "GDBUS_CODEGEN=$gdbus_codegen" >> $config_host_mak
|
echo "GDBUS_CODEGEN=$gdbus_codegen" >> $config_host_mak
|
||||||
fi
|
fi
|
||||||
echo "CONFIG_TLS_PRIORITY=\"$tls_priority\"" >> $config_host_mak
|
echo "CONFIG_TLS_PRIORITY=\"$tls_priority\"" >> $config_host_mak
|
||||||
|
|
|
@ -349,6 +349,7 @@ vg_resource_create_2d(VuGpu *g,
|
||||||
g_critical("%s: resource creation failed %d %d %d",
|
g_critical("%s: resource creation failed %d %d %d",
|
||||||
__func__, c2d.resource_id, c2d.width, c2d.height);
|
__func__, c2d.resource_id, c2d.width, c2d.height);
|
||||||
g_free(res);
|
g_free(res);
|
||||||
|
vugbm_buffer_destroy(&res->buffer);
|
||||||
cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY;
|
cmd->error = VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -399,6 +400,7 @@ vg_resource_destroy(VuGpu *g,
|
||||||
}
|
}
|
||||||
|
|
||||||
vugbm_buffer_destroy(&res->buffer);
|
vugbm_buffer_destroy(&res->buffer);
|
||||||
|
g_free(res->iov);
|
||||||
pixman_image_unref(res->image);
|
pixman_image_unref(res->image);
|
||||||
QTAILQ_REMOVE(&g->reslist, res, next);
|
QTAILQ_REMOVE(&g->reslist, res, next);
|
||||||
g_free(res);
|
g_free(res);
|
||||||
|
@ -488,6 +490,11 @@ vg_resource_attach_backing(VuGpu *g,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (res->iov) {
|
||||||
|
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ret = vg_create_mapping_iov(g, &ab, cmd, &res->iov);
|
ret = vg_create_mapping_iov(g, &ab, cmd, &res->iov);
|
||||||
if (ret != 0) {
|
if (ret != 0) {
|
||||||
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
|
cmd->error = VIRTIO_GPU_RESP_ERR_UNSPEC;
|
||||||
|
|
|
@ -108,9 +108,16 @@ virgl_cmd_resource_unref(VuGpu *g,
|
||||||
struct virtio_gpu_ctrl_command *cmd)
|
struct virtio_gpu_ctrl_command *cmd)
|
||||||
{
|
{
|
||||||
struct virtio_gpu_resource_unref unref;
|
struct virtio_gpu_resource_unref unref;
|
||||||
|
struct iovec *res_iovs = NULL;
|
||||||
|
int num_iovs = 0;
|
||||||
|
|
||||||
VUGPU_FILL_CMD(unref);
|
VUGPU_FILL_CMD(unref);
|
||||||
|
|
||||||
|
virgl_renderer_resource_detach_iov(unref.resource_id,
|
||||||
|
&res_iovs,
|
||||||
|
&num_iovs);
|
||||||
|
g_free(res_iovs);
|
||||||
|
|
||||||
virgl_renderer_resource_unref(unref.resource_id);
|
virgl_renderer_resource_unref(unref.resource_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,6 +135,7 @@ virgl_cmd_get_capset_info(VuGpu *g,
|
||||||
|
|
||||||
VUGPU_FILL_CMD(info);
|
VUGPU_FILL_CMD(info);
|
||||||
|
|
||||||
|
memset(&resp, 0, sizeof(resp));
|
||||||
if (info.capset_index == 0) {
|
if (info.capset_index == 0) {
|
||||||
resp.capset_id = VIRTIO_GPU_CAPSET_VIRGL;
|
resp.capset_id = VIRTIO_GPU_CAPSET_VIRGL;
|
||||||
virgl_renderer_get_cap_set(resp.capset_id,
|
virgl_renderer_get_cap_set(resp.capset_id,
|
||||||
|
@ -169,6 +177,10 @@ virgl_cmd_get_capset(VuGpu *g,
|
||||||
|
|
||||||
virgl_renderer_get_cap_set(gc.capset_id, &max_ver,
|
virgl_renderer_get_cap_set(gc.capset_id, &max_ver,
|
||||||
&max_size);
|
&max_size);
|
||||||
|
if (!max_size) {
|
||||||
|
cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
|
||||||
|
return;
|
||||||
|
}
|
||||||
resp = g_malloc0(sizeof(*resp) + max_size);
|
resp = g_malloc0(sizeof(*resp) + max_size);
|
||||||
|
|
||||||
resp->hdr.type = VIRTIO_GPU_RESP_OK_CAPSET;
|
resp->hdr.type = VIRTIO_GPU_RESP_OK_CAPSET;
|
||||||
|
@ -279,8 +291,11 @@ virgl_resource_attach_backing(VuGpu *g,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
virgl_renderer_resource_attach_iov(att_rb.resource_id,
|
ret = virgl_renderer_resource_attach_iov(att_rb.resource_id,
|
||||||
res_iovs, att_rb.nr_entries);
|
res_iovs, att_rb.nr_entries);
|
||||||
|
if (ret != 0) {
|
||||||
|
g_free(res_iovs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -14,8 +14,15 @@
|
||||||
#include "crypto/tlscreds.h"
|
#include "crypto/tlscreds.h"
|
||||||
#include "crypto/tls-cipher-suites.h"
|
#include "crypto/tls-cipher-suites.h"
|
||||||
#include "hw/nvram/fw_cfg.h"
|
#include "hw/nvram/fw_cfg.h"
|
||||||
|
#include "tlscredspriv.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
|
||||||
|
struct QCryptoTLSCipherSuites {
|
||||||
|
/* <private> */
|
||||||
|
QCryptoTLSCreds parent_obj;
|
||||||
|
/* <public> */
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IANA registered TLS ciphers:
|
* IANA registered TLS ciphers:
|
||||||
* https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4
|
* https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
|
#include "qapi-types-crypto.h"
|
||||||
#include "qemu/module.h"
|
#include "qemu/module.h"
|
||||||
#include "tlscredspriv.h"
|
#include "tlscredspriv.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
@ -259,6 +260,17 @@ qcrypto_tls_creds_finalize(Object *obj)
|
||||||
g_free(creds->priority);
|
g_free(creds->priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool qcrypto_tls_creds_check_endpoint(QCryptoTLSCreds *creds,
|
||||||
|
QCryptoTLSCredsEndpoint endpoint,
|
||||||
|
Error **errp)
|
||||||
|
{
|
||||||
|
if (creds->endpoint != endpoint) {
|
||||||
|
error_setg(errp, "Expected TLS credentials for a %s endpoint",
|
||||||
|
QCryptoTLSCredsEndpoint_str(endpoint));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static const TypeInfo qcrypto_tls_creds_info = {
|
static const TypeInfo qcrypto_tls_creds_info = {
|
||||||
.parent = TYPE_OBJECT,
|
.parent = TYPE_OBJECT,
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
|
|
||||||
#ifdef CONFIG_GNUTLS
|
#ifdef CONFIG_GNUTLS
|
||||||
|
|
||||||
|
#include <gnutls/gnutls.h>
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
qcrypto_tls_creds_anon_load(QCryptoTLSCredsAnon *creds,
|
qcrypto_tls_creds_anon_load(QCryptoTLSCredsAnon *creds,
|
||||||
|
|
|
@ -23,6 +23,51 @@
|
||||||
|
|
||||||
#include "crypto/tlscreds.h"
|
#include "crypto/tlscreds.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_GNUTLS
|
||||||
|
#include <gnutls/gnutls.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct QCryptoTLSCreds {
|
||||||
|
Object parent_obj;
|
||||||
|
char *dir;
|
||||||
|
QCryptoTLSCredsEndpoint endpoint;
|
||||||
|
#ifdef CONFIG_GNUTLS
|
||||||
|
gnutls_dh_params_t dh_params;
|
||||||
|
#endif
|
||||||
|
bool verifyPeer;
|
||||||
|
char *priority;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QCryptoTLSCredsAnon {
|
||||||
|
QCryptoTLSCreds parent_obj;
|
||||||
|
#ifdef CONFIG_GNUTLS
|
||||||
|
union {
|
||||||
|
gnutls_anon_server_credentials_t server;
|
||||||
|
gnutls_anon_client_credentials_t client;
|
||||||
|
} data;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QCryptoTLSCredsPSK {
|
||||||
|
QCryptoTLSCreds parent_obj;
|
||||||
|
char *username;
|
||||||
|
#ifdef CONFIG_GNUTLS
|
||||||
|
union {
|
||||||
|
gnutls_psk_server_credentials_t server;
|
||||||
|
gnutls_psk_client_credentials_t client;
|
||||||
|
} data;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
struct QCryptoTLSCredsX509 {
|
||||||
|
QCryptoTLSCreds parent_obj;
|
||||||
|
#ifdef CONFIG_GNUTLS
|
||||||
|
gnutls_certificate_credentials_t data;
|
||||||
|
#endif
|
||||||
|
bool sanityCheck;
|
||||||
|
char *passwordid;
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_GNUTLS
|
#ifdef CONFIG_GNUTLS
|
||||||
|
|
||||||
int qcrypto_tls_creds_get_path(QCryptoTLSCreds *creds,
|
int qcrypto_tls_creds_get_path(QCryptoTLSCreds *creds,
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
|
|
||||||
#ifdef CONFIG_GNUTLS
|
#ifdef CONFIG_GNUTLS
|
||||||
|
|
||||||
|
#include <gnutls/gnutls.h>
|
||||||
|
|
||||||
static int
|
static int
|
||||||
lookup_key(const char *pskfile, const char *username, gnutls_datum_t *key,
|
lookup_key(const char *pskfile, const char *username, gnutls_datum_t *key,
|
||||||
Error **errp)
|
Error **errp)
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#ifdef CONFIG_GNUTLS
|
#ifdef CONFIG_GNUTLS
|
||||||
|
|
||||||
|
#include <gnutls/gnutls.h>
|
||||||
#include <gnutls/x509.h>
|
#include <gnutls/x509.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "crypto/tlscredsx509.h"
|
#include "crypto/tlscredsx509.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "authz/base.h"
|
#include "authz/base.h"
|
||||||
|
#include "tlscredspriv.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
|
|
||||||
#ifdef CONFIG_GNUTLS
|
#ifdef CONFIG_GNUTLS
|
||||||
|
|
|
@ -285,6 +285,12 @@ The RISC-V no MMU cpus have been removed. The two CPUs: ``rv32imacu-nommu`` and
|
||||||
``rv64imacu-nommu`` can no longer be used. Instead the MMU status can be specified
|
``rv64imacu-nommu`` can no longer be used. Instead the MMU status can be specified
|
||||||
via the CPU ``mmu`` option when using the ``rv32`` or ``rv64`` CPUs.
|
via the CPU ``mmu`` option when using the ``rv32`` or ``rv64`` CPUs.
|
||||||
|
|
||||||
|
``compat`` property of server class POWER CPUs (removed in 6.0)
|
||||||
|
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||||
|
|
||||||
|
The ``max-cpu-compat`` property of the ``pseries`` machine type should be used
|
||||||
|
instead.
|
||||||
|
|
||||||
System emulator machines
|
System emulator machines
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
|
|
|
@ -98,8 +98,10 @@ driver options if ``--image-opts`` is specified.
|
||||||
|
|
||||||
.. option:: --cache=CACHE
|
.. option:: --cache=CACHE
|
||||||
|
|
||||||
The cache mode to be used with the file. See the documentation of
|
The cache mode to be used with the file. Valid values are:
|
||||||
the emulator's ``-drive cache=...`` option for allowed values.
|
``none``, ``writeback`` (the default), ``writethrough``,
|
||||||
|
``directsync`` and ``unsafe``. See the documentation of
|
||||||
|
the emulator's ``-drive cache=...`` option for more info.
|
||||||
|
|
||||||
.. option:: -n, --nocache
|
.. option:: -n, --nocache
|
||||||
|
|
||||||
|
|
|
@ -303,7 +303,7 @@ static void nvme_ns_init_zoned(NvmeNamespace *ns)
|
||||||
|
|
||||||
id_ns_z = g_malloc0(sizeof(NvmeIdNsZoned));
|
id_ns_z = g_malloc0(sizeof(NvmeIdNsZoned));
|
||||||
|
|
||||||
/* MAR/MOR are zeroes-based, 0xffffffff means no limit */
|
/* MAR/MOR are zeroes-based, FFFFFFFFFh means no limit */
|
||||||
id_ns_z->mar = cpu_to_le32(ns->params.max_active_zones - 1);
|
id_ns_z->mar = cpu_to_le32(ns->params.max_active_zones - 1);
|
||||||
id_ns_z->mor = cpu_to_le32(ns->params.max_open_zones - 1);
|
id_ns_z->mor = cpu_to_le32(ns->params.max_open_zones - 1);
|
||||||
id_ns_z->zoc = 0;
|
id_ns_z->zoc = 0;
|
||||||
|
|
|
@ -12,10 +12,19 @@
|
||||||
* Reference Specs: http://www.nvmexpress.org, 1.4, 1.3, 1.2, 1.1, 1.0e
|
* Reference Specs: http://www.nvmexpress.org, 1.4, 1.3, 1.2, 1.1, 1.0e
|
||||||
*
|
*
|
||||||
* https://nvmexpress.org/developers/nvme-specification/
|
* https://nvmexpress.org/developers/nvme-specification/
|
||||||
*/
|
*
|
||||||
|
*
|
||||||
/**
|
* Notes on coding style
|
||||||
* Usage: add options:
|
* ---------------------
|
||||||
|
* While QEMU coding style prefers lowercase hexadecimals in constants, the
|
||||||
|
* NVMe subsystem use thes format from the NVMe specifications in the comments
|
||||||
|
* (i.e. 'h' suffix instead of '0x' prefix).
|
||||||
|
*
|
||||||
|
* Usage
|
||||||
|
* -----
|
||||||
|
* See docs/system/nvme.rst for extensive documentation.
|
||||||
|
*
|
||||||
|
* Add options:
|
||||||
* -drive file=<file>,if=none,id=<drive_id>
|
* -drive file=<file>,if=none,id=<drive_id>
|
||||||
* -device nvme-subsys,id=<subsys_id>,nqn=<nqn_id>
|
* -device nvme-subsys,id=<subsys_id>,nqn=<nqn_id>
|
||||||
* -device nvme,serial=<serial>,id=<bus_name>, \
|
* -device nvme,serial=<serial>,id=<bus_name>, \
|
||||||
|
@ -460,7 +469,9 @@ static void nvme_irq_deassert(NvmeCtrl *n, NvmeCQueue *cq)
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
assert(cq->vector < 32);
|
assert(cq->vector < 32);
|
||||||
n->irq_status &= ~(1 << cq->vector);
|
if (!n->cq_pending) {
|
||||||
|
n->irq_status &= ~(1 << cq->vector);
|
||||||
|
}
|
||||||
nvme_irq_check(n);
|
nvme_irq_check(n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1253,6 +1264,7 @@ static void nvme_post_cqes(void *opaque)
|
||||||
NvmeCQueue *cq = opaque;
|
NvmeCQueue *cq = opaque;
|
||||||
NvmeCtrl *n = cq->ctrl;
|
NvmeCtrl *n = cq->ctrl;
|
||||||
NvmeRequest *req, *next;
|
NvmeRequest *req, *next;
|
||||||
|
bool pending = cq->head != cq->tail;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
QTAILQ_FOREACH_SAFE(req, &cq->req_list, entry, next) {
|
QTAILQ_FOREACH_SAFE(req, &cq->req_list, entry, next) {
|
||||||
|
@ -1282,6 +1294,10 @@ static void nvme_post_cqes(void *opaque)
|
||||||
QTAILQ_INSERT_TAIL(&sq->req_list, req, entry);
|
QTAILQ_INSERT_TAIL(&sq->req_list, req, entry);
|
||||||
}
|
}
|
||||||
if (cq->tail != cq->head) {
|
if (cq->tail != cq->head) {
|
||||||
|
if (cq->irq_enabled && !pending) {
|
||||||
|
n->cq_pending++;
|
||||||
|
}
|
||||||
|
|
||||||
nvme_irq_assert(n, cq);
|
nvme_irq_assert(n, cq);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3607,18 +3623,18 @@ static uint16_t nvme_io_cmd(NvmeCtrl *n, NvmeRequest *req)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* In the base NVM command set, Flush may apply to all namespaces
|
* In the base NVM command set, Flush may apply to all namespaces
|
||||||
* (indicated by NSID being set to 0xFFFFFFFF). But if that feature is used
|
* (indicated by NSID being set to FFFFFFFFh). But if that feature is used
|
||||||
* along with TP 4056 (Namespace Types), it may be pretty screwed up.
|
* along with TP 4056 (Namespace Types), it may be pretty screwed up.
|
||||||
*
|
*
|
||||||
* If NSID is indeed set to 0xFFFFFFFF, we simply cannot associate the
|
* If NSID is indeed set to FFFFFFFFh, we simply cannot associate the
|
||||||
* opcode with a specific command since we cannot determine a unique I/O
|
* opcode with a specific command since we cannot determine a unique I/O
|
||||||
* command set. Opcode 0x0 could have any other meaning than something
|
* command set. Opcode 0h could have any other meaning than something
|
||||||
* equivalent to flushing and say it DOES have completely different
|
* equivalent to flushing and say it DOES have completely different
|
||||||
* semantics in some other command set - does an NSID of 0xFFFFFFFF then
|
* semantics in some other command set - does an NSID of FFFFFFFFh then
|
||||||
* mean "for all namespaces, apply whatever command set specific command
|
* mean "for all namespaces, apply whatever command set specific command
|
||||||
* that uses the 0x0 opcode?" Or does it mean "for all namespaces, apply
|
* that uses the 0h opcode?" Or does it mean "for all namespaces, apply
|
||||||
* whatever command that uses the 0x0 opcode if, and only if, it allows
|
* whatever command that uses the 0h opcode if, and only if, it allows NSID
|
||||||
* NSID to be 0xFFFFFFFF"?
|
* to be FFFFFFFFh"?
|
||||||
*
|
*
|
||||||
* Anyway (and luckily), for now, we do not care about this since the
|
* Anyway (and luckily), for now, we do not care about this since the
|
||||||
* device only supports namespace types that includes the NVM Flush command
|
* device only supports namespace types that includes the NVM Flush command
|
||||||
|
@ -3934,7 +3950,7 @@ static uint16_t nvme_changed_nslist(NvmeCtrl *n, uint8_t rae, uint32_t buf_len,
|
||||||
NVME_CHANGED_NSID_SIZE) {
|
NVME_CHANGED_NSID_SIZE) {
|
||||||
/*
|
/*
|
||||||
* If more than 1024 namespaces, the first entry in the log page should
|
* If more than 1024 namespaces, the first entry in the log page should
|
||||||
* be set to 0xffffffff and the others to 0 as spec.
|
* be set to FFFFFFFFh and the others to 0 as spec.
|
||||||
*/
|
*/
|
||||||
if (i == ARRAY_SIZE(nslist)) {
|
if (i == ARRAY_SIZE(nslist)) {
|
||||||
memset(nslist, 0x0, sizeof(nslist));
|
memset(nslist, 0x0, sizeof(nslist));
|
||||||
|
@ -4082,6 +4098,11 @@ static uint16_t nvme_del_cq(NvmeCtrl *n, NvmeRequest *req)
|
||||||
trace_pci_nvme_err_invalid_del_cq_notempty(qid);
|
trace_pci_nvme_err_invalid_del_cq_notempty(qid);
|
||||||
return NVME_INVALID_QUEUE_DEL;
|
return NVME_INVALID_QUEUE_DEL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cq->irq_enabled && cq->tail != cq->head) {
|
||||||
|
n->cq_pending--;
|
||||||
|
}
|
||||||
|
|
||||||
nvme_irq_deassert(n, cq);
|
nvme_irq_deassert(n, cq);
|
||||||
trace_pci_nvme_del_cq(qid);
|
trace_pci_nvme_del_cq(qid);
|
||||||
nvme_free_cq(cq, n);
|
nvme_free_cq(cq, n);
|
||||||
|
@ -4332,7 +4353,7 @@ static uint16_t nvme_identify_nslist(NvmeCtrl *n, NvmeRequest *req,
|
||||||
trace_pci_nvme_identify_nslist(min_nsid);
|
trace_pci_nvme_identify_nslist(min_nsid);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Both 0xffffffff (NVME_NSID_BROADCAST) and 0xfffffffe are invalid values
|
* Both FFFFFFFFh (NVME_NSID_BROADCAST) and FFFFFFFFEh are invalid values
|
||||||
* since the Active Namespace ID List should return namespaces with ids
|
* since the Active Namespace ID List should return namespaces with ids
|
||||||
* *higher* than the NSID specified in the command. This is also specified
|
* *higher* than the NSID specified in the command. This is also specified
|
||||||
* in the spec (NVM Express v1.3d, Section 5.15.4).
|
* in the spec (NVM Express v1.3d, Section 5.15.4).
|
||||||
|
@ -4379,7 +4400,7 @@ static uint16_t nvme_identify_nslist_csi(NvmeCtrl *n, NvmeRequest *req,
|
||||||
trace_pci_nvme_identify_nslist_csi(min_nsid, c->csi);
|
trace_pci_nvme_identify_nslist_csi(min_nsid, c->csi);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Same as in nvme_identify_nslist(), 0xffffffff/0xfffffffe are invalid.
|
* Same as in nvme_identify_nslist(), FFFFFFFFh/FFFFFFFFEh are invalid.
|
||||||
*/
|
*/
|
||||||
if (min_nsid >= NVME_NSID_BROADCAST - 1) {
|
if (min_nsid >= NVME_NSID_BROADCAST - 1) {
|
||||||
return NVME_INVALID_NSID | NVME_DNR;
|
return NVME_INVALID_NSID | NVME_DNR;
|
||||||
|
@ -4446,7 +4467,7 @@ static uint16_t nvme_identify_ns_descr_list(NvmeCtrl *n, NvmeRequest *req)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Because the NGUID and EUI64 fields are 0 in the Identify Namespace data
|
* Because the NGUID and EUI64 fields are 0 in the Identify Namespace data
|
||||||
* structure, a Namespace UUID (nidt = 0x3) must be reported in the
|
* structure, a Namespace UUID (nidt = 3h) must be reported in the
|
||||||
* Namespace Identification Descriptor. Add the namespace UUID here.
|
* Namespace Identification Descriptor. Add the namespace UUID here.
|
||||||
*/
|
*/
|
||||||
ns_descrs->uuid.hdr.nidt = NVME_NIDT_UUID;
|
ns_descrs->uuid.hdr.nidt = NVME_NIDT_UUID;
|
||||||
|
@ -4595,7 +4616,7 @@ static uint16_t nvme_get_feature(NvmeCtrl *n, NvmeRequest *req)
|
||||||
/*
|
/*
|
||||||
* The Reservation Notification Mask and Reservation Persistence
|
* The Reservation Notification Mask and Reservation Persistence
|
||||||
* features require a status code of Invalid Field in Command when
|
* features require a status code of Invalid Field in Command when
|
||||||
* NSID is 0xFFFFFFFF. Since the device does not support those
|
* NSID is FFFFFFFFh. Since the device does not support those
|
||||||
* features we can always return Invalid Namespace or Format as we
|
* features we can always return Invalid Namespace or Format as we
|
||||||
* should do for all other features.
|
* should do for all other features.
|
||||||
*/
|
*/
|
||||||
|
@ -4847,15 +4868,15 @@ static uint16_t nvme_set_feature(NvmeCtrl *n, NvmeRequest *req)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NVMe v1.3, Section 5.21.1.7: 0xffff is not an allowed value for NCQR
|
* NVMe v1.3, Section 5.21.1.7: FFFFh is not an allowed value for NCQR
|
||||||
* and NSQR.
|
* and NSQR.
|
||||||
*/
|
*/
|
||||||
if ((dw11 & 0xffff) == 0xffff || ((dw11 >> 16) & 0xffff) == 0xffff) {
|
if ((dw11 & 0xffff) == 0xffff || ((dw11 >> 16) & 0xffff) == 0xffff) {
|
||||||
return NVME_INVALID_FIELD | NVME_DNR;
|
return NVME_INVALID_FIELD | NVME_DNR;
|
||||||
}
|
}
|
||||||
|
|
||||||
trace_pci_nvme_setfeat_numq((dw11 & 0xFFFF) + 1,
|
trace_pci_nvme_setfeat_numq((dw11 & 0xffff) + 1,
|
||||||
((dw11 >> 16) & 0xFFFF) + 1,
|
((dw11 >> 16) & 0xffff) + 1,
|
||||||
n->params.max_ioqpairs,
|
n->params.max_ioqpairs,
|
||||||
n->params.max_ioqpairs);
|
n->params.max_ioqpairs);
|
||||||
req->cqe.result = cpu_to_le32((n->params.max_ioqpairs - 1) |
|
req->cqe.result = cpu_to_le32((n->params.max_ioqpairs - 1) |
|
||||||
|
@ -5493,7 +5514,7 @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data,
|
||||||
n->bar.cc = data;
|
n->bar.cc = data;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x1C: /* CSTS */
|
case 0x1c: /* CSTS */
|
||||||
if (data & (1 << 4)) {
|
if (data & (1 << 4)) {
|
||||||
NVME_GUEST_ERR(pci_nvme_ub_mmiowr_ssreset_w1c_unsupported,
|
NVME_GUEST_ERR(pci_nvme_ub_mmiowr_ssreset_w1c_unsupported,
|
||||||
"attempted to W1C CSTS.NSSRO"
|
"attempted to W1C CSTS.NSSRO"
|
||||||
|
@ -5505,7 +5526,7 @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x20: /* NSSR */
|
case 0x20: /* NSSR */
|
||||||
if (data == 0x4E564D65) {
|
if (data == 0x4e564d65) {
|
||||||
trace_pci_nvme_ub_mmiowr_ssreset_unsupported();
|
trace_pci_nvme_ub_mmiowr_ssreset_unsupported();
|
||||||
} else {
|
} else {
|
||||||
/* The spec says that writes of other values have no effect */
|
/* The spec says that writes of other values have no effect */
|
||||||
|
@ -5575,11 +5596,15 @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data,
|
||||||
n->bar.cmbmsc = (n->bar.cmbmsc & 0xffffffff) | (data << 32);
|
n->bar.cmbmsc = (n->bar.cmbmsc & 0xffffffff) | (data << 32);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case 0xE00: /* PMRCAP */
|
case 0xe00: /* PMRCAP */
|
||||||
NVME_GUEST_ERR(pci_nvme_ub_mmiowr_pmrcap_readonly,
|
NVME_GUEST_ERR(pci_nvme_ub_mmiowr_pmrcap_readonly,
|
||||||
"invalid write to PMRCAP register, ignored");
|
"invalid write to PMRCAP register, ignored");
|
||||||
return;
|
return;
|
||||||
case 0xE04: /* PMRCTL */
|
case 0xe04: /* PMRCTL */
|
||||||
|
if (!NVME_CAP_PMRS(n->bar.cap)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
n->bar.pmrctl = data;
|
n->bar.pmrctl = data;
|
||||||
if (NVME_PMRCTL_EN(data)) {
|
if (NVME_PMRCTL_EN(data)) {
|
||||||
memory_region_set_enabled(&n->pmr.dev->mr, true);
|
memory_region_set_enabled(&n->pmr.dev->mr, true);
|
||||||
|
@ -5590,19 +5615,19 @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data,
|
||||||
n->pmr.cmse = false;
|
n->pmr.cmse = false;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
case 0xE08: /* PMRSTS */
|
case 0xe08: /* PMRSTS */
|
||||||
NVME_GUEST_ERR(pci_nvme_ub_mmiowr_pmrsts_readonly,
|
NVME_GUEST_ERR(pci_nvme_ub_mmiowr_pmrsts_readonly,
|
||||||
"invalid write to PMRSTS register, ignored");
|
"invalid write to PMRSTS register, ignored");
|
||||||
return;
|
return;
|
||||||
case 0xE0C: /* PMREBS */
|
case 0xe0C: /* PMREBS */
|
||||||
NVME_GUEST_ERR(pci_nvme_ub_mmiowr_pmrebs_readonly,
|
NVME_GUEST_ERR(pci_nvme_ub_mmiowr_pmrebs_readonly,
|
||||||
"invalid write to PMREBS register, ignored");
|
"invalid write to PMREBS register, ignored");
|
||||||
return;
|
return;
|
||||||
case 0xE10: /* PMRSWTP */
|
case 0xe10: /* PMRSWTP */
|
||||||
NVME_GUEST_ERR(pci_nvme_ub_mmiowr_pmrswtp_readonly,
|
NVME_GUEST_ERR(pci_nvme_ub_mmiowr_pmrswtp_readonly,
|
||||||
"invalid write to PMRSWTP register, ignored");
|
"invalid write to PMRSWTP register, ignored");
|
||||||
return;
|
return;
|
||||||
case 0xE14: /* PMRMSCL */
|
case 0xe14: /* PMRMSCL */
|
||||||
if (!NVME_CAP_PMRS(n->bar.cap)) {
|
if (!NVME_CAP_PMRS(n->bar.cap)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -5622,7 +5647,7 @@ static void nvme_write_bar(NvmeCtrl *n, hwaddr offset, uint64_t data,
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
case 0xE18: /* PMRMSCU */
|
case 0xe18: /* PMRMSCU */
|
||||||
if (!NVME_CAP_PMRS(n->bar.cap)) {
|
if (!NVME_CAP_PMRS(n->bar.cap)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -5664,7 +5689,7 @@ static uint64_t nvme_mmio_read(void *opaque, hwaddr addr, unsigned size)
|
||||||
* from PMRSTS should ensure prior writes
|
* from PMRSTS should ensure prior writes
|
||||||
* made it to persistent media
|
* made it to persistent media
|
||||||
*/
|
*/
|
||||||
if (addr == 0xE08 &&
|
if (addr == 0xe08 &&
|
||||||
(NVME_PMRCAP_PMRWBM(n->bar.pmrcap) & 0x02)) {
|
(NVME_PMRCAP_PMRWBM(n->bar.pmrcap) & 0x02)) {
|
||||||
memory_region_msync(&n->pmr.dev->mr, 0, n->pmr.dev->size);
|
memory_region_msync(&n->pmr.dev->mr, 0, n->pmr.dev->size);
|
||||||
}
|
}
|
||||||
|
@ -5755,6 +5780,10 @@ static void nvme_process_db(NvmeCtrl *n, hwaddr addr, int val)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cq->tail == cq->head) {
|
if (cq->tail == cq->head) {
|
||||||
|
if (cq->irq_enabled) {
|
||||||
|
n->cq_pending--;
|
||||||
|
}
|
||||||
|
|
||||||
nvme_irq_deassert(n, cq);
|
nvme_irq_deassert(n, cq);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -171,6 +171,7 @@ typedef struct NvmeCtrl {
|
||||||
uint32_t max_q_ents;
|
uint32_t max_q_ents;
|
||||||
uint8_t outstanding_aers;
|
uint8_t outstanding_aers;
|
||||||
uint32_t irq_status;
|
uint32_t irq_status;
|
||||||
|
int cq_pending;
|
||||||
uint64_t host_timestamp; /* Timestamp sent by the host */
|
uint64_t host_timestamp; /* Timestamp sent by the host */
|
||||||
uint64_t timestamp_set_qemu_clock_ms; /* QEMU clock time */
|
uint64_t timestamp_set_qemu_clock_ms; /* QEMU clock time */
|
||||||
uint64_t starttime_ms;
|
uint64_t starttime_ms;
|
||||||
|
|
|
@ -1170,8 +1170,8 @@ static void artist_vram_write(void *opaque, hwaddr addr, uint64_t val,
|
||||||
}
|
}
|
||||||
|
|
||||||
buf = vram_write_buffer(s);
|
buf = vram_write_buffer(s);
|
||||||
posy = ADDR_TO_Y(addr);
|
posy = ADDR_TO_Y(addr >> 2);
|
||||||
posx = ADDR_TO_X(addr);
|
posx = ADDR_TO_X(addr >> 2);
|
||||||
|
|
||||||
if (!buf->size) {
|
if (!buf->size) {
|
||||||
return;
|
return;
|
||||||
|
@ -1232,8 +1232,8 @@ static uint64_t artist_vram_read(void *opaque, hwaddr addr, unsigned size)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
posy = ADDR_TO_Y(addr);
|
posy = ADDR_TO_Y(addr >> 2);
|
||||||
posx = ADDR_TO_X(addr);
|
posx = ADDR_TO_X(addr >> 2);
|
||||||
|
|
||||||
if (posy > buf->height || posx > buf->width) {
|
if (posy > buf->height || posx > buf->width) {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -432,11 +432,15 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus,
|
||||||
aml_append(dev, aml_name_decl("_ADR", aml_int(slot << 16)));
|
aml_append(dev, aml_name_decl("_ADR", aml_int(slot << 16)));
|
||||||
|
|
||||||
if (bsel) {
|
if (bsel) {
|
||||||
aml_append(dev, aml_name_decl("_SUN", aml_int(slot)));
|
/*
|
||||||
|
* Can't declare _SUN here for every device as it changes 'slot'
|
||||||
|
* enumeration order in linux kernel, so use another variable for it
|
||||||
|
*/
|
||||||
|
aml_append(dev, aml_name_decl("ASUN", aml_int(slot)));
|
||||||
method = aml_method("_DSM", 4, AML_SERIALIZED);
|
method = aml_method("_DSM", 4, AML_SERIALIZED);
|
||||||
aml_append(method, aml_return(
|
aml_append(method, aml_return(
|
||||||
aml_call6("PDSM", aml_arg(0), aml_arg(1), aml_arg(2),
|
aml_call6("PDSM", aml_arg(0), aml_arg(1), aml_arg(2),
|
||||||
aml_arg(3), aml_name("BSEL"), aml_name("_SUN"))
|
aml_arg(3), aml_name("BSEL"), aml_name("ASUN"))
|
||||||
));
|
));
|
||||||
aml_append(dev, method);
|
aml_append(dev, method);
|
||||||
}
|
}
|
||||||
|
@ -463,6 +467,7 @@ static void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus,
|
||||||
aml_append(method, aml_return(aml_int(s3d)));
|
aml_append(method, aml_return(aml_int(s3d)));
|
||||||
aml_append(dev, method);
|
aml_append(dev, method);
|
||||||
} else if (hotplug_enabled_dev) {
|
} else if (hotplug_enabled_dev) {
|
||||||
|
aml_append(dev, aml_name_decl("_SUN", aml_int(slot)));
|
||||||
/* add _EJ0 to make slot hotpluggable */
|
/* add _EJ0 to make slot hotpluggable */
|
||||||
method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
|
method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
|
||||||
aml_append(method,
|
aml_append(method,
|
||||||
|
|
|
@ -275,6 +275,10 @@ static void buff2frame_pel(const uint8_t *buff, qemu_can_frame *frame)
|
||||||
}
|
}
|
||||||
frame->can_dlc = buff[0] & 0x0f;
|
frame->can_dlc = buff[0] & 0x0f;
|
||||||
|
|
||||||
|
if (frame->can_dlc > 8) {
|
||||||
|
frame->can_dlc = 8;
|
||||||
|
}
|
||||||
|
|
||||||
if (buff[0] & 0x80) { /* Extended */
|
if (buff[0] & 0x80) { /* Extended */
|
||||||
frame->can_id |= QEMU_CAN_EFF_FLAG;
|
frame->can_id |= QEMU_CAN_EFF_FLAG;
|
||||||
frame->can_id |= buff[1] << 21; /* ID.28~ID.21 */
|
frame->can_id |= buff[1] << 21; /* ID.28~ID.21 */
|
||||||
|
@ -311,6 +315,10 @@ static void buff2frame_bas(const uint8_t *buff, qemu_can_frame *frame)
|
||||||
}
|
}
|
||||||
frame->can_dlc = buff[1] & 0x0f;
|
frame->can_dlc = buff[1] & 0x0f;
|
||||||
|
|
||||||
|
if (frame->can_dlc > 8) {
|
||||||
|
frame->can_dlc = 8;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < frame->can_dlc; i++) {
|
for (i = 0; i < frame->can_dlc; i++) {
|
||||||
frame->data[i] = buff[2 + i];
|
frame->data[i] = buff[2 + i];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1659,10 +1659,13 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
|
||||||
VirtIONet *n = qemu_get_nic_opaque(nc);
|
VirtIONet *n = qemu_get_nic_opaque(nc);
|
||||||
VirtIONetQueue *q = virtio_net_get_subqueue(nc);
|
VirtIONetQueue *q = virtio_net_get_subqueue(nc);
|
||||||
VirtIODevice *vdev = VIRTIO_DEVICE(n);
|
VirtIODevice *vdev = VIRTIO_DEVICE(n);
|
||||||
|
VirtQueueElement *elems[VIRTQUEUE_MAX_SIZE];
|
||||||
|
size_t lens[VIRTQUEUE_MAX_SIZE];
|
||||||
struct iovec mhdr_sg[VIRTQUEUE_MAX_SIZE];
|
struct iovec mhdr_sg[VIRTQUEUE_MAX_SIZE];
|
||||||
struct virtio_net_hdr_mrg_rxbuf mhdr;
|
struct virtio_net_hdr_mrg_rxbuf mhdr;
|
||||||
unsigned mhdr_cnt = 0;
|
unsigned mhdr_cnt = 0;
|
||||||
size_t offset, i, guest_offset;
|
size_t offset, i, guest_offset, j;
|
||||||
|
ssize_t err;
|
||||||
|
|
||||||
if (!virtio_net_can_receive(nc)) {
|
if (!virtio_net_can_receive(nc)) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1693,6 +1696,12 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
|
||||||
|
|
||||||
total = 0;
|
total = 0;
|
||||||
|
|
||||||
|
if (i == VIRTQUEUE_MAX_SIZE) {
|
||||||
|
virtio_error(vdev, "virtio-net unexpected long buffer chain");
|
||||||
|
err = size;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
elem = virtqueue_pop(q->rx_vq, sizeof(VirtQueueElement));
|
elem = virtqueue_pop(q->rx_vq, sizeof(VirtQueueElement));
|
||||||
if (!elem) {
|
if (!elem) {
|
||||||
if (i) {
|
if (i) {
|
||||||
|
@ -1704,7 +1713,8 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
|
||||||
n->guest_hdr_len, n->host_hdr_len,
|
n->guest_hdr_len, n->host_hdr_len,
|
||||||
vdev->guest_features);
|
vdev->guest_features);
|
||||||
}
|
}
|
||||||
return -1;
|
err = -1;
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (elem->in_num < 1) {
|
if (elem->in_num < 1) {
|
||||||
|
@ -1712,7 +1722,8 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
|
||||||
"virtio-net receive queue contains no in buffers");
|
"virtio-net receive queue contains no in buffers");
|
||||||
virtqueue_detach_element(q->rx_vq, elem, 0);
|
virtqueue_detach_element(q->rx_vq, elem, 0);
|
||||||
g_free(elem);
|
g_free(elem);
|
||||||
return -1;
|
err = -1;
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
sg = elem->in_sg;
|
sg = elem->in_sg;
|
||||||
|
@ -1749,12 +1760,13 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
|
||||||
if (!n->mergeable_rx_bufs && offset < size) {
|
if (!n->mergeable_rx_bufs && offset < size) {
|
||||||
virtqueue_unpop(q->rx_vq, elem, total);
|
virtqueue_unpop(q->rx_vq, elem, total);
|
||||||
g_free(elem);
|
g_free(elem);
|
||||||
return size;
|
err = size;
|
||||||
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* signal other side */
|
elems[i] = elem;
|
||||||
virtqueue_fill(q->rx_vq, elem, total, i++);
|
lens[i] = total;
|
||||||
g_free(elem);
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mhdr_cnt) {
|
if (mhdr_cnt) {
|
||||||
|
@ -1764,10 +1776,23 @@ static ssize_t virtio_net_receive_rcu(NetClientState *nc, const uint8_t *buf,
|
||||||
&mhdr.num_buffers, sizeof mhdr.num_buffers);
|
&mhdr.num_buffers, sizeof mhdr.num_buffers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (j = 0; j < i; j++) {
|
||||||
|
/* signal other side */
|
||||||
|
virtqueue_fill(q->rx_vq, elems[j], lens[j], j);
|
||||||
|
g_free(elems[j]);
|
||||||
|
}
|
||||||
|
|
||||||
virtqueue_flush(q->rx_vq, i);
|
virtqueue_flush(q->rx_vq, i);
|
||||||
virtio_notify(vdev, q->rx_vq);
|
virtio_notify(vdev, q->rx_vq);
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
|
|
||||||
|
err:
|
||||||
|
for (j = 0; j < i; j++) {
|
||||||
|
g_free(elems[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t virtio_net_do_receive(NetClientState *nc, const uint8_t *buf,
|
static ssize_t virtio_net_do_receive(NetClientState *nc, const uint8_t *buf,
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
|
#include "qemu/log.h"
|
||||||
#include "hw/i386/pc.h"
|
#include "hw/i386/pc.h"
|
||||||
#include "hw/pci-host/q35.h"
|
#include "hw/pci-host/q35.h"
|
||||||
#include "hw/qdev-properties.h"
|
#include "hw/qdev-properties.h"
|
||||||
|
@ -318,6 +319,8 @@ static void mch_update_pciexbar(MCHPCIState *mch)
|
||||||
addr_mask |= MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK;
|
addr_mask |= MCH_HOST_BRIDGE_PCIEXBAR_64ADMSK;
|
||||||
break;
|
break;
|
||||||
case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_RVD:
|
case MCH_HOST_BRIDGE_PCIEXBAR_LENGTH_RVD:
|
||||||
|
qemu_log_mask(LOG_GUEST_ERROR, "Q35: Reserved PCIEXBAR LENGTH\n");
|
||||||
|
return;
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,13 @@ static void *pvrdma_map_to_pdir(PCIDevice *pdev, uint64_t pdir_dma,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
length = ROUND_UP(length, TARGET_PAGE_SIZE);
|
||||||
|
if (nchunks * TARGET_PAGE_SIZE != length) {
|
||||||
|
rdma_error_report("Invalid nchunks/length (%u, %lu)", nchunks,
|
||||||
|
(unsigned long)length);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
dir = rdma_pci_dma_map(pdev, pdir_dma, TARGET_PAGE_SIZE);
|
dir = rdma_pci_dma_map(pdev, pdir_dma, TARGET_PAGE_SIZE);
|
||||||
if (!dir) {
|
if (!dir) {
|
||||||
rdma_error_report("Failed to map to page directory");
|
rdma_error_report("Failed to map to page directory");
|
||||||
|
|
|
@ -41,7 +41,7 @@ int pvrdma_ring_init(PvrdmaRing *ring, const char *name, PCIDevice *dev,
|
||||||
qatomic_set(&ring->ring_state->cons_head, 0);
|
qatomic_set(&ring->ring_state->cons_head, 0);
|
||||||
*/
|
*/
|
||||||
ring->npages = npages;
|
ring->npages = npages;
|
||||||
ring->pages = g_malloc(npages * sizeof(void *));
|
ring->pages = g_malloc0(npages * sizeof(void *));
|
||||||
|
|
||||||
for (i = 0; i < npages; i++) {
|
for (i = 0; i < npages; i++) {
|
||||||
if (!tbl[i]) {
|
if (!tbl[i]) {
|
||||||
|
|
|
@ -92,6 +92,11 @@ static int init_dev_ring(PvrdmaRing *ring, PvrdmaRingState **ring_state,
|
||||||
uint64_t *dir, *tbl;
|
uint64_t *dir, *tbl;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
|
if (!num_pages) {
|
||||||
|
rdma_error_report("Ring pages count must be strictly positive");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
dir = rdma_pci_dma_map(pci_dev, dir_addr, TARGET_PAGE_SIZE);
|
dir = rdma_pci_dma_map(pci_dev, dir_addr, TARGET_PAGE_SIZE);
|
||||||
if (!dir) {
|
if (!dir) {
|
||||||
rdma_error_report("Failed to map to page directory (ring %s)", name);
|
rdma_error_report("Failed to map to page directory (ring %s)", name);
|
||||||
|
|
|
@ -42,10 +42,9 @@ void remote_sysmem_reconfig(MPQemuMsg *msg, Error **errp)
|
||||||
|
|
||||||
remote_sysmem_reset();
|
remote_sysmem_reset();
|
||||||
|
|
||||||
for (region = 0; region < msg->num_fds; region++) {
|
for (region = 0; region < msg->num_fds; region++, suffix++) {
|
||||||
g_autofree char *name;
|
g_autofree char *name = g_strdup_printf("remote-mem-%u", suffix);
|
||||||
subregion = g_new(MemoryRegion, 1);
|
subregion = g_new(MemoryRegion, 1);
|
||||||
name = g_strdup_printf("remote-mem-%u", suffix++);
|
|
||||||
memory_region_init_ram_from_fd(subregion, NULL,
|
memory_region_init_ram_from_fd(subregion, NULL,
|
||||||
name, sysmem_info->sizes[region],
|
name, sysmem_info->sizes[region],
|
||||||
true, msg->fds[region],
|
true, msg->fds[region],
|
||||||
|
|
|
@ -347,13 +347,12 @@ static void probe_pci_info(PCIDevice *dev, Error **errp)
|
||||||
PCI_BASE_ADDRESS_SPACE_IO : PCI_BASE_ADDRESS_SPACE_MEMORY;
|
PCI_BASE_ADDRESS_SPACE_IO : PCI_BASE_ADDRESS_SPACE_MEMORY;
|
||||||
|
|
||||||
if (size) {
|
if (size) {
|
||||||
g_autofree char *name;
|
g_autofree char *name = g_strdup_printf("bar-region-%d", i);
|
||||||
pdev->region[i].dev = pdev;
|
pdev->region[i].dev = pdev;
|
||||||
pdev->region[i].present = true;
|
pdev->region[i].present = true;
|
||||||
if (type == PCI_BASE_ADDRESS_SPACE_MEMORY) {
|
if (type == PCI_BASE_ADDRESS_SPACE_MEMORY) {
|
||||||
pdev->region[i].memory = true;
|
pdev->region[i].memory = true;
|
||||||
}
|
}
|
||||||
name = g_strdup_printf("bar-region-%d", i);
|
|
||||||
memory_region_init_io(&pdev->region[i].mr, OBJECT(pdev),
|
memory_region_init_io(&pdev->region[i].mr, OBJECT(pdev),
|
||||||
&proxy_mr_ops, &pdev->region[i],
|
&proxy_mr_ops, &pdev->region[i],
|
||||||
name, size);
|
name, size);
|
||||||
|
|
|
@ -213,7 +213,7 @@ static int esp_select(ESPState *s)
|
||||||
if (!s->current_dev) {
|
if (!s->current_dev) {
|
||||||
/* No such drive */
|
/* No such drive */
|
||||||
s->rregs[ESP_RSTAT] = 0;
|
s->rregs[ESP_RSTAT] = 0;
|
||||||
s->rregs[ESP_RINTR] |= INTR_DC;
|
s->rregs[ESP_RINTR] = INTR_DC;
|
||||||
s->rregs[ESP_RSEQ] = SEQ_0;
|
s->rregs[ESP_RSEQ] = SEQ_0;
|
||||||
esp_raise_irq(s);
|
esp_raise_irq(s);
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -481,7 +481,6 @@ static void esp_dma_done(ESPState *s)
|
||||||
{
|
{
|
||||||
s->rregs[ESP_RSTAT] |= STAT_TC;
|
s->rregs[ESP_RSTAT] |= STAT_TC;
|
||||||
s->rregs[ESP_RINTR] |= INTR_BS;
|
s->rregs[ESP_RINTR] |= INTR_BS;
|
||||||
s->rregs[ESP_RSEQ] = 0;
|
|
||||||
s->rregs[ESP_RFLAGS] = 0;
|
s->rregs[ESP_RFLAGS] = 0;
|
||||||
esp_set_tc(s, 0);
|
esp_set_tc(s, 0);
|
||||||
esp_raise_irq(s);
|
esp_raise_irq(s);
|
||||||
|
@ -917,7 +916,15 @@ uint64_t esp_reg_read(ESPState *s, uint32_t saddr)
|
||||||
val = s->rregs[ESP_RINTR];
|
val = s->rregs[ESP_RINTR];
|
||||||
s->rregs[ESP_RINTR] = 0;
|
s->rregs[ESP_RINTR] = 0;
|
||||||
s->rregs[ESP_RSTAT] &= ~STAT_TC;
|
s->rregs[ESP_RSTAT] &= ~STAT_TC;
|
||||||
s->rregs[ESP_RSEQ] = SEQ_0;
|
/*
|
||||||
|
* According to the datasheet ESP_RSEQ should be cleared, but as the
|
||||||
|
* emulation currently defers information transfers to the next TI
|
||||||
|
* command leave it for now so that pedantic guests such as the old
|
||||||
|
* Linux 2.6 driver see the correct flags before the next SCSI phase
|
||||||
|
* transition.
|
||||||
|
*
|
||||||
|
* s->rregs[ESP_RSEQ] = SEQ_0;
|
||||||
|
*/
|
||||||
esp_lower_irq(s);
|
esp_lower_irq(s);
|
||||||
break;
|
break;
|
||||||
case ESP_TCHI:
|
case ESP_TCHI:
|
||||||
|
|
|
@ -821,8 +821,15 @@ static uint32_t sd_wpbits(SDState *sd, uint64_t addr)
|
||||||
wpnum = sd_addr_to_wpnum(addr);
|
wpnum = sd_addr_to_wpnum(addr);
|
||||||
|
|
||||||
for (i = 0; i < 32; i++, wpnum++, addr += WPGROUP_SIZE) {
|
for (i = 0; i < 32; i++, wpnum++, addr += WPGROUP_SIZE) {
|
||||||
|
if (addr >= sd->size) {
|
||||||
|
/*
|
||||||
|
* If the addresses of the last groups are outside the valid range,
|
||||||
|
* then the corresponding write protection bits shall be set to 0.
|
||||||
|
*/
|
||||||
|
continue;
|
||||||
|
}
|
||||||
assert(wpnum < sd->wpgrps_size);
|
assert(wpnum < sd->wpgrps_size);
|
||||||
if (addr < sd->size && test_bit(wpnum, sd->wp_groups)) {
|
if (test_bit(wpnum, sd->wp_groups)) {
|
||||||
ret |= (1 << i);
|
ret |= (1 << i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -171,7 +171,9 @@ void usb_ep_combine_input_packets(USBEndpoint *ep)
|
||||||
if ((p->iov.size % ep->max_packet_size) != 0 || !p->short_not_ok ||
|
if ((p->iov.size % ep->max_packet_size) != 0 || !p->short_not_ok ||
|
||||||
next == NULL ||
|
next == NULL ||
|
||||||
/* Work around for Linux usbfs bulk splitting + migration */
|
/* Work around for Linux usbfs bulk splitting + migration */
|
||||||
(totalsize == (16 * KiB - 36) && p->int_req)) {
|
(totalsize == (16 * KiB - 36) && p->int_req) ||
|
||||||
|
/* Next package may grow combined package over 1MiB */
|
||||||
|
totalsize > 1 * MiB - ep->max_packet_size) {
|
||||||
usb_device_handle_data(ep->dev, first);
|
usb_device_handle_data(ep->dev, first);
|
||||||
assert(first->status == USB_RET_ASYNC);
|
assert(first->status == USB_RET_ASYNC);
|
||||||
if (first->combined) {
|
if (first->combined) {
|
||||||
|
|
|
@ -840,6 +840,9 @@ static void usb_uas_handle_data(USBDevice *dev, USBPacket *p)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case UAS_PIPE_ID_STATUS:
|
case UAS_PIPE_ID_STATUS:
|
||||||
|
if (p->stream > UAS_MAX_STREAMS) {
|
||||||
|
goto err_stream;
|
||||||
|
}
|
||||||
if (p->stream) {
|
if (p->stream) {
|
||||||
QTAILQ_FOREACH(st, &uas->results, next) {
|
QTAILQ_FOREACH(st, &uas->results, next) {
|
||||||
if (st->stream == p->stream) {
|
if (st->stream == p->stream) {
|
||||||
|
@ -867,6 +870,9 @@ static void usb_uas_handle_data(USBDevice *dev, USBPacket *p)
|
||||||
break;
|
break;
|
||||||
case UAS_PIPE_ID_DATA_IN:
|
case UAS_PIPE_ID_DATA_IN:
|
||||||
case UAS_PIPE_ID_DATA_OUT:
|
case UAS_PIPE_ID_DATA_OUT:
|
||||||
|
if (p->stream > UAS_MAX_STREAMS) {
|
||||||
|
goto err_stream;
|
||||||
|
}
|
||||||
if (p->stream) {
|
if (p->stream) {
|
||||||
req = usb_uas_find_request(uas, p->stream);
|
req = usb_uas_find_request(uas, p->stream);
|
||||||
} else {
|
} else {
|
||||||
|
@ -902,6 +908,11 @@ static void usb_uas_handle_data(USBDevice *dev, USBPacket *p)
|
||||||
p->status = USB_RET_STALL;
|
p->status = USB_RET_STALL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err_stream:
|
||||||
|
error_report("%s: invalid stream %d", __func__, p->stream);
|
||||||
|
p->status = USB_RET_STALL;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usb_uas_unrealize(USBDevice *dev)
|
static void usb_uas_unrealize(USBDevice *dev)
|
||||||
|
|
|
@ -620,7 +620,7 @@ static void usbredir_handle_iso_data(USBRedirDevice *dev, USBPacket *p,
|
||||||
.endpoint = ep,
|
.endpoint = ep,
|
||||||
.length = p->iov.size
|
.length = p->iov.size
|
||||||
};
|
};
|
||||||
uint8_t buf[p->iov.size];
|
g_autofree uint8_t *buf = g_malloc(p->iov.size);
|
||||||
/* No id, we look at the ep when receiving a status back */
|
/* No id, we look at the ep when receiving a status back */
|
||||||
usb_packet_copy(p, buf, p->iov.size);
|
usb_packet_copy(p, buf, p->iov.size);
|
||||||
usbredirparser_send_iso_packet(dev->parser, 0, &iso_packet,
|
usbredirparser_send_iso_packet(dev->parser, 0, &iso_packet,
|
||||||
|
@ -818,7 +818,7 @@ static void usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p,
|
||||||
usbredirparser_send_bulk_packet(dev->parser, p->id,
|
usbredirparser_send_bulk_packet(dev->parser, p->id,
|
||||||
&bulk_packet, NULL, 0);
|
&bulk_packet, NULL, 0);
|
||||||
} else {
|
} else {
|
||||||
uint8_t buf[size];
|
g_autofree uint8_t *buf = g_malloc(size);
|
||||||
usb_packet_copy(p, buf, size);
|
usb_packet_copy(p, buf, size);
|
||||||
usbredir_log_data(dev, "bulk data out:", buf, size);
|
usbredir_log_data(dev, "bulk data out:", buf, size);
|
||||||
usbredirparser_send_bulk_packet(dev->parser, p->id,
|
usbredirparser_send_bulk_packet(dev->parser, p->id,
|
||||||
|
@ -923,7 +923,7 @@ static void usbredir_handle_interrupt_out_data(USBRedirDevice *dev,
|
||||||
USBPacket *p, uint8_t ep)
|
USBPacket *p, uint8_t ep)
|
||||||
{
|
{
|
||||||
struct usb_redir_interrupt_packet_header interrupt_packet;
|
struct usb_redir_interrupt_packet_header interrupt_packet;
|
||||||
uint8_t buf[p->iov.size];
|
g_autofree uint8_t *buf = g_malloc(p->iov.size);
|
||||||
|
|
||||||
DPRINTF("interrupt-out ep %02X len %zd id %"PRIu64"\n", ep,
|
DPRINTF("interrupt-out ep %02X len %zd id %"PRIu64"\n", ep,
|
||||||
p->iov.size, p->id);
|
p->iov.size, p->id);
|
||||||
|
|
|
@ -893,6 +893,7 @@ void vfio_migration_finalize(VFIODevice *vbasedev)
|
||||||
|
|
||||||
remove_migration_state_change_notifier(&migration->migration_state);
|
remove_migration_state_change_notifier(&migration->migration_state);
|
||||||
qemu_del_vm_change_state_handler(migration->vm_state);
|
qemu_del_vm_change_state_handler(migration->vm_state);
|
||||||
|
unregister_savevm(VMSTATE_IF(vbasedev->dev), "vfio", vbasedev);
|
||||||
vfio_migration_exit(vbasedev);
|
vfio_migration_exit(vbasedev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1465,8 +1465,9 @@ static int vhost_user_slave_handle_vring_host_notifier(struct vhost_dev *dev,
|
||||||
|
|
||||||
name = g_strdup_printf("vhost-user/host-notifier@%p mmaps[%d]",
|
name = g_strdup_printf("vhost-user/host-notifier@%p mmaps[%d]",
|
||||||
user, queue_idx);
|
user, queue_idx);
|
||||||
memory_region_init_ram_device_ptr(&n->mr, OBJECT(vdev), name,
|
if (!n->mr.ram) /* Don't init again after suspend. */
|
||||||
page_size, addr);
|
memory_region_init_ram_device_ptr(&n->mr, OBJECT(vdev), name,
|
||||||
|
page_size, addr);
|
||||||
g_free(name);
|
g_free(name);
|
||||||
|
|
||||||
if (virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, true)) {
|
if (virtio_queue_set_host_notifier_mr(vdev, queue_idx, &n->mr, true)) {
|
||||||
|
|
|
@ -275,15 +275,12 @@ static void vhost_vdpa_add_status(struct vhost_dev *dev, uint8_t status)
|
||||||
static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque)
|
static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque)
|
||||||
{
|
{
|
||||||
struct vhost_vdpa *v;
|
struct vhost_vdpa *v;
|
||||||
uint64_t features;
|
|
||||||
assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_VDPA);
|
assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_VDPA);
|
||||||
trace_vhost_vdpa_init(dev, opaque);
|
trace_vhost_vdpa_init(dev, opaque);
|
||||||
|
|
||||||
v = opaque;
|
v = opaque;
|
||||||
v->dev = dev;
|
v->dev = dev;
|
||||||
dev->opaque = opaque ;
|
dev->opaque = opaque ;
|
||||||
vhost_vdpa_call(dev, VHOST_GET_FEATURES, &features);
|
|
||||||
dev->backend_features = features;
|
|
||||||
v->listener = vhost_vdpa_memory_listener;
|
v->listener = vhost_vdpa_memory_listener;
|
||||||
v->msg_type = VHOST_IOTLB_MSG_V2;
|
v->msg_type = VHOST_IOTLB_MSG_V2;
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
#include "migration/misc.h"
|
#include "migration/misc.h"
|
||||||
|
#include "migration/migration.h"
|
||||||
|
|
||||||
#include "hw/virtio/virtio-bus.h"
|
#include "hw/virtio/virtio-bus.h"
|
||||||
#include "hw/virtio/virtio-access.h"
|
#include "hw/virtio/virtio-access.h"
|
||||||
|
@ -662,6 +663,18 @@ virtio_balloon_free_page_hint_notify(NotifierWithReturn *n, void *data)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pages hinted via qemu_guest_free_page_hint() are cleared from the dirty
|
||||||
|
* bitmap and will not get migrated, especially also not when the postcopy
|
||||||
|
* destination starts using them and requests migration from the source; the
|
||||||
|
* faulting thread will stall until postcopy migration finishes and
|
||||||
|
* all threads are woken up. Let's not start free page hinting if postcopy
|
||||||
|
* is possible.
|
||||||
|
*/
|
||||||
|
if (migrate_postcopy_ram()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
switch (pnd->reason) {
|
switch (pnd->reason) {
|
||||||
case PRECOPY_NOTIFY_SETUP:
|
case PRECOPY_NOTIFY_SETUP:
|
||||||
precopy_enable_free_page_optimization();
|
precopy_enable_free_page_optimization();
|
||||||
|
|
|
@ -88,13 +88,8 @@ static void virtio_mem_pci_size_change_notify(Notifier *notifier, void *data)
|
||||||
size_change_notifier);
|
size_change_notifier);
|
||||||
DeviceState *dev = DEVICE(pci_mem);
|
DeviceState *dev = DEVICE(pci_mem);
|
||||||
const uint64_t * const size_p = data;
|
const uint64_t * const size_p = data;
|
||||||
const char *id = NULL;
|
|
||||||
|
|
||||||
if (dev->id) {
|
qapi_event_send_memory_device_size_change(!!dev->id, dev->id, *size_p);
|
||||||
id = g_strdup(dev->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
qapi_event_send_memory_device_size_change(!!id, id, *size_p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void virtio_mem_pci_class_init(ObjectClass *klass, void *data)
|
static void virtio_mem_pci_class_init(ObjectClass *klass, void *data)
|
||||||
|
|
|
@ -848,8 +848,8 @@ enum NvmeStatusCodes {
|
||||||
NVME_FW_REQ_SUSYSTEM_RESET = 0x0110,
|
NVME_FW_REQ_SUSYSTEM_RESET = 0x0110,
|
||||||
NVME_NS_ALREADY_ATTACHED = 0x0118,
|
NVME_NS_ALREADY_ATTACHED = 0x0118,
|
||||||
NVME_NS_PRIVATE = 0x0119,
|
NVME_NS_PRIVATE = 0x0119,
|
||||||
NVME_NS_NOT_ATTACHED = 0x011A,
|
NVME_NS_NOT_ATTACHED = 0x011a,
|
||||||
NVME_NS_CTRL_LIST_INVALID = 0x011C,
|
NVME_NS_CTRL_LIST_INVALID = 0x011c,
|
||||||
NVME_CONFLICTING_ATTRS = 0x0180,
|
NVME_CONFLICTING_ATTRS = 0x0180,
|
||||||
NVME_INVALID_PROT_INFO = 0x0181,
|
NVME_INVALID_PROT_INFO = 0x0181,
|
||||||
NVME_WRITE_TO_RO = 0x0182,
|
NVME_WRITE_TO_RO = 0x0182,
|
||||||
|
@ -1409,9 +1409,9 @@ typedef enum NvmeZoneState {
|
||||||
NVME_ZONE_STATE_IMPLICITLY_OPEN = 0x02,
|
NVME_ZONE_STATE_IMPLICITLY_OPEN = 0x02,
|
||||||
NVME_ZONE_STATE_EXPLICITLY_OPEN = 0x03,
|
NVME_ZONE_STATE_EXPLICITLY_OPEN = 0x03,
|
||||||
NVME_ZONE_STATE_CLOSED = 0x04,
|
NVME_ZONE_STATE_CLOSED = 0x04,
|
||||||
NVME_ZONE_STATE_READ_ONLY = 0x0D,
|
NVME_ZONE_STATE_READ_ONLY = 0x0d,
|
||||||
NVME_ZONE_STATE_FULL = 0x0E,
|
NVME_ZONE_STATE_FULL = 0x0e,
|
||||||
NVME_ZONE_STATE_OFFLINE = 0x0F,
|
NVME_ZONE_STATE_OFFLINE = 0x0f,
|
||||||
} NvmeZoneState;
|
} NvmeZoneState;
|
||||||
|
|
||||||
static inline void _nvme_check_size(void)
|
static inline void _nvme_check_size(void)
|
||||||
|
|
|
@ -20,8 +20,6 @@ void qdict_join(QDict *dest, QDict *src, bool overwrite);
|
||||||
void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start);
|
void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start);
|
||||||
void qdict_array_split(QDict *src, QList **dst);
|
void qdict_array_split(QDict *src, QList **dst);
|
||||||
int qdict_array_entries(QDict *src, const char *subqdict);
|
int qdict_array_entries(QDict *src, const char *subqdict);
|
||||||
QObject *qdict_crumple(const QDict *src, Error **errp);
|
|
||||||
void qdict_flatten(QDict *qdict);
|
|
||||||
|
|
||||||
typedef struct QDictRenames {
|
typedef struct QDictRenames {
|
||||||
const char *from;
|
const char *from;
|
||||||
|
|
|
@ -19,12 +19,6 @@ typedef struct QCryptoTLSCipherSuites QCryptoTLSCipherSuites;
|
||||||
DECLARE_INSTANCE_CHECKER(QCryptoTLSCipherSuites, QCRYPTO_TLS_CIPHER_SUITES,
|
DECLARE_INSTANCE_CHECKER(QCryptoTLSCipherSuites, QCRYPTO_TLS_CIPHER_SUITES,
|
||||||
TYPE_QCRYPTO_TLS_CIPHER_SUITES)
|
TYPE_QCRYPTO_TLS_CIPHER_SUITES)
|
||||||
|
|
||||||
struct QCryptoTLSCipherSuites {
|
|
||||||
/* <private> */
|
|
||||||
QCryptoTLSCreds parent_obj;
|
|
||||||
/* <public> */
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qcrypto_tls_cipher_suites_get_data:
|
* qcrypto_tls_cipher_suites_get_data:
|
||||||
* @obj: pointer to a TLS cipher suites object
|
* @obj: pointer to a TLS cipher suites object
|
||||||
|
|
|
@ -24,10 +24,6 @@
|
||||||
#include "qapi/qapi-types-crypto.h"
|
#include "qapi/qapi-types-crypto.h"
|
||||||
#include "qom/object.h"
|
#include "qom/object.h"
|
||||||
|
|
||||||
#ifdef CONFIG_GNUTLS
|
|
||||||
#include <gnutls/gnutls.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define TYPE_QCRYPTO_TLS_CREDS "tls-creds"
|
#define TYPE_QCRYPTO_TLS_CREDS "tls-creds"
|
||||||
typedef struct QCryptoTLSCreds QCryptoTLSCreds;
|
typedef struct QCryptoTLSCreds QCryptoTLSCreds;
|
||||||
typedef struct QCryptoTLSCredsClass QCryptoTLSCredsClass;
|
typedef struct QCryptoTLSCredsClass QCryptoTLSCredsClass;
|
||||||
|
@ -48,22 +44,24 @@ typedef bool (*CryptoTLSCredsReload)(QCryptoTLSCreds *, Error **);
|
||||||
* certificate credentials.
|
* certificate credentials.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct QCryptoTLSCreds {
|
|
||||||
Object parent_obj;
|
|
||||||
char *dir;
|
|
||||||
QCryptoTLSCredsEndpoint endpoint;
|
|
||||||
#ifdef CONFIG_GNUTLS
|
|
||||||
gnutls_dh_params_t dh_params;
|
|
||||||
#endif
|
|
||||||
bool verifyPeer;
|
|
||||||
char *priority;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct QCryptoTLSCredsClass {
|
struct QCryptoTLSCredsClass {
|
||||||
ObjectClass parent_class;
|
ObjectClass parent_class;
|
||||||
CryptoTLSCredsReload reload;
|
CryptoTLSCredsReload reload;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* qcrypto_tls_creds_check_endpoint:
|
||||||
|
* @creds: pointer to a TLS credentials object
|
||||||
|
* @endpoint: type of network endpoint that will be using the credentials
|
||||||
|
* @errp: pointer to a NULL-initialized error object
|
||||||
|
*
|
||||||
|
* Check whether the credentials is setup according to
|
||||||
|
* the type of @endpoint argument.
|
||||||
|
*
|
||||||
|
* Returns true if the credentials is setup for the endpoint, false otherwise
|
||||||
|
*/
|
||||||
|
bool qcrypto_tls_creds_check_endpoint(QCryptoTLSCreds *creds,
|
||||||
|
QCryptoTLSCredsEndpoint endpoint,
|
||||||
|
Error **errp);
|
||||||
|
|
||||||
#endif /* QCRYPTO_TLSCREDS_H */
|
#endif /* QCRYPTO_TLSCREDS_H */
|
||||||
|
|
|
@ -92,18 +92,6 @@ typedef struct QCryptoTLSCredsAnonClass QCryptoTLSCredsAnonClass;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
struct QCryptoTLSCredsAnon {
|
|
||||||
QCryptoTLSCreds parent_obj;
|
|
||||||
#ifdef CONFIG_GNUTLS
|
|
||||||
union {
|
|
||||||
gnutls_anon_server_credentials_t server;
|
|
||||||
gnutls_anon_client_credentials_t client;
|
|
||||||
} data;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct QCryptoTLSCredsAnonClass {
|
struct QCryptoTLSCredsAnonClass {
|
||||||
QCryptoTLSCredsClass parent_class;
|
QCryptoTLSCredsClass parent_class;
|
||||||
};
|
};
|
||||||
|
|
|
@ -87,18 +87,6 @@ typedef struct QCryptoTLSCredsPSKClass QCryptoTLSCredsPSKClass;
|
||||||
* The PSK file can be created and managed using psktool.
|
* The PSK file can be created and managed using psktool.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct QCryptoTLSCredsPSK {
|
|
||||||
QCryptoTLSCreds parent_obj;
|
|
||||||
char *username;
|
|
||||||
#ifdef CONFIG_GNUTLS
|
|
||||||
union {
|
|
||||||
gnutls_psk_server_credentials_t server;
|
|
||||||
gnutls_psk_client_credentials_t client;
|
|
||||||
} data;
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct QCryptoTLSCredsPSKClass {
|
struct QCryptoTLSCredsPSKClass {
|
||||||
QCryptoTLSCredsClass parent_class;
|
QCryptoTLSCredsClass parent_class;
|
||||||
};
|
};
|
||||||
|
|
|
@ -96,16 +96,6 @@ typedef struct QCryptoTLSCredsX509Class QCryptoTLSCredsX509Class;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct QCryptoTLSCredsX509 {
|
|
||||||
QCryptoTLSCreds parent_obj;
|
|
||||||
#ifdef CONFIG_GNUTLS
|
|
||||||
gnutls_certificate_credentials_t data;
|
|
||||||
#endif
|
|
||||||
bool sanityCheck;
|
|
||||||
char *passwordid;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct QCryptoTLSCredsX509Class {
|
struct QCryptoTLSCredsX509Class {
|
||||||
QCryptoTLSCredsClass parent_class;
|
QCryptoTLSCredsClass parent_class;
|
||||||
};
|
};
|
||||||
|
|
|
@ -64,4 +64,7 @@ const char *qdict_get_try_str(const QDict *qdict, const char *key);
|
||||||
|
|
||||||
QDict *qdict_clone_shallow(const QDict *src);
|
QDict *qdict_clone_shallow(const QDict *src);
|
||||||
|
|
||||||
|
QObject *qdict_crumple(const QDict *src, Error **errp);
|
||||||
|
void qdict_flatten(QDict *qdict);
|
||||||
|
|
||||||
#endif /* QDICT_H */
|
#endif /* QDICT_H */
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
#ifndef QEMU_CONFIG_FILE_H
|
#ifndef QEMU_CONFIG_FILE_H
|
||||||
#define QEMU_CONFIG_FILE_H
|
#define QEMU_CONFIG_FILE_H
|
||||||
|
|
||||||
|
typedef void QEMUConfigCB(const char *group, QDict *qdict, void *opaque, Error **errp);
|
||||||
|
|
||||||
|
void qemu_load_module_for_opts(const char *group);
|
||||||
QemuOptsList *qemu_find_opts(const char *group);
|
QemuOptsList *qemu_find_opts(const char *group);
|
||||||
QemuOptsList *qemu_find_opts_err(const char *group, Error **errp);
|
QemuOptsList *qemu_find_opts_err(const char *group, Error **errp);
|
||||||
QemuOpts *qemu_find_opts_singleton(const char *group);
|
QemuOpts *qemu_find_opts_singleton(const char *group);
|
||||||
|
@ -14,7 +16,10 @@ void qemu_config_write(FILE *fp);
|
||||||
int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname,
|
int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname,
|
||||||
Error **errp);
|
Error **errp);
|
||||||
|
|
||||||
int qemu_read_config_file(const char *filename, Error **errp);
|
/* A default callback for qemu_read_config_file(). */
|
||||||
|
void qemu_config_do_parse(const char *group, QDict *qdict, void *opaque, Error **errp);
|
||||||
|
|
||||||
|
int qemu_read_config_file(const char *filename, QEMUConfigCB *f, Error **errp);
|
||||||
|
|
||||||
/* Parse QDict options as a replacement for a config file (allowing multiple
|
/* Parse QDict options as a replacement for a config file (allowing multiple
|
||||||
enumerated (0..(n-1)) configuration "sections") */
|
enumerated (0..(n-1)) configuration "sections") */
|
||||||
|
|
|
@ -586,6 +586,16 @@ enum {
|
||||||
ARM_HWCAP2_A64_SVESM4 = 1 << 6,
|
ARM_HWCAP2_A64_SVESM4 = 1 << 6,
|
||||||
ARM_HWCAP2_A64_FLAGM2 = 1 << 7,
|
ARM_HWCAP2_A64_FLAGM2 = 1 << 7,
|
||||||
ARM_HWCAP2_A64_FRINT = 1 << 8,
|
ARM_HWCAP2_A64_FRINT = 1 << 8,
|
||||||
|
ARM_HWCAP2_A64_SVEI8MM = 1 << 9,
|
||||||
|
ARM_HWCAP2_A64_SVEF32MM = 1 << 10,
|
||||||
|
ARM_HWCAP2_A64_SVEF64MM = 1 << 11,
|
||||||
|
ARM_HWCAP2_A64_SVEBF16 = 1 << 12,
|
||||||
|
ARM_HWCAP2_A64_I8MM = 1 << 13,
|
||||||
|
ARM_HWCAP2_A64_BF16 = 1 << 14,
|
||||||
|
ARM_HWCAP2_A64_DGH = 1 << 15,
|
||||||
|
ARM_HWCAP2_A64_RNG = 1 << 16,
|
||||||
|
ARM_HWCAP2_A64_BTI = 1 << 17,
|
||||||
|
ARM_HWCAP2_A64_MTE = 1 << 18,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define ELF_HWCAP get_elf_hwcap()
|
#define ELF_HWCAP get_elf_hwcap()
|
||||||
|
@ -640,6 +650,9 @@ static uint32_t get_elf_hwcap2(void)
|
||||||
GET_FEATURE_ID(aa64_dcpodp, ARM_HWCAP2_A64_DCPODP);
|
GET_FEATURE_ID(aa64_dcpodp, ARM_HWCAP2_A64_DCPODP);
|
||||||
GET_FEATURE_ID(aa64_condm_5, ARM_HWCAP2_A64_FLAGM2);
|
GET_FEATURE_ID(aa64_condm_5, ARM_HWCAP2_A64_FLAGM2);
|
||||||
GET_FEATURE_ID(aa64_frint, ARM_HWCAP2_A64_FRINT);
|
GET_FEATURE_ID(aa64_frint, ARM_HWCAP2_A64_FRINT);
|
||||||
|
GET_FEATURE_ID(aa64_rndr, ARM_HWCAP2_A64_RNG);
|
||||||
|
GET_FEATURE_ID(aa64_bti, ARM_HWCAP2_A64_BTI);
|
||||||
|
GET_FEATURE_ID(aa64_mte, ARM_HWCAP2_A64_MTE);
|
||||||
|
|
||||||
return hwcaps;
|
return hwcaps;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,18 +38,19 @@ void migration_channel_process_incoming(QIOChannel *ioc)
|
||||||
trace_migration_set_incoming_channel(
|
trace_migration_set_incoming_channel(
|
||||||
ioc, object_get_typename(OBJECT(ioc)));
|
ioc, object_get_typename(OBJECT(ioc)));
|
||||||
|
|
||||||
if (object_dynamic_cast(OBJECT(ioc), TYPE_QIO_CHANNEL_SOCKET)) {
|
|
||||||
yank_register_function(MIGRATION_YANK_INSTANCE,
|
|
||||||
migration_yank_iochannel,
|
|
||||||
QIO_CHANNEL(ioc));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s->parameters.tls_creds &&
|
if (s->parameters.tls_creds &&
|
||||||
*s->parameters.tls_creds &&
|
*s->parameters.tls_creds &&
|
||||||
!object_dynamic_cast(OBJECT(ioc),
|
!object_dynamic_cast(OBJECT(ioc),
|
||||||
TYPE_QIO_CHANNEL_TLS)) {
|
TYPE_QIO_CHANNEL_TLS)) {
|
||||||
migration_tls_channel_process_incoming(s, ioc, &local_err);
|
migration_tls_channel_process_incoming(s, ioc, &local_err);
|
||||||
} else {
|
} else {
|
||||||
|
if (object_dynamic_cast(OBJECT(ioc), TYPE_QIO_CHANNEL_SOCKET) ||
|
||||||
|
object_dynamic_cast(OBJECT(ioc), TYPE_QIO_CHANNEL_TLS)) {
|
||||||
|
yank_register_function(MIGRATION_YANK_INSTANCE,
|
||||||
|
migration_yank_iochannel,
|
||||||
|
QIO_CHANNEL(ioc));
|
||||||
|
}
|
||||||
|
|
||||||
migration_ioc_process_incoming(ioc, &local_err);
|
migration_ioc_process_incoming(ioc, &local_err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,12 +77,6 @@ void migration_channel_connect(MigrationState *s,
|
||||||
ioc, object_get_typename(OBJECT(ioc)), hostname, error);
|
ioc, object_get_typename(OBJECT(ioc)), hostname, error);
|
||||||
|
|
||||||
if (!error) {
|
if (!error) {
|
||||||
if (object_dynamic_cast(OBJECT(ioc), TYPE_QIO_CHANNEL_SOCKET)) {
|
|
||||||
yank_register_function(MIGRATION_YANK_INSTANCE,
|
|
||||||
migration_yank_iochannel,
|
|
||||||
QIO_CHANNEL(ioc));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s->parameters.tls_creds &&
|
if (s->parameters.tls_creds &&
|
||||||
*s->parameters.tls_creds &&
|
*s->parameters.tls_creds &&
|
||||||
!object_dynamic_cast(OBJECT(ioc),
|
!object_dynamic_cast(OBJECT(ioc),
|
||||||
|
@ -99,6 +94,13 @@ void migration_channel_connect(MigrationState *s,
|
||||||
} else {
|
} else {
|
||||||
QEMUFile *f = qemu_fopen_channel_output(ioc);
|
QEMUFile *f = qemu_fopen_channel_output(ioc);
|
||||||
|
|
||||||
|
if (object_dynamic_cast(OBJECT(ioc), TYPE_QIO_CHANNEL_SOCKET) ||
|
||||||
|
object_dynamic_cast(OBJECT(ioc), TYPE_QIO_CHANNEL_TLS)) {
|
||||||
|
yank_register_function(MIGRATION_YANK_INSTANCE,
|
||||||
|
migration_yank_iochannel,
|
||||||
|
QIO_CHANNEL(ioc));
|
||||||
|
}
|
||||||
|
|
||||||
qemu_mutex_lock(&s->qemu_file_lock);
|
qemu_mutex_lock(&s->qemu_file_lock);
|
||||||
s->to_dst_file = f;
|
s->to_dst_file = f;
|
||||||
qemu_mutex_unlock(&s->qemu_file_lock);
|
qemu_mutex_unlock(&s->qemu_file_lock);
|
||||||
|
|
|
@ -987,7 +987,8 @@ int multifd_load_cleanup(Error **errp)
|
||||||
for (i = 0; i < migrate_multifd_channels(); i++) {
|
for (i = 0; i < migrate_multifd_channels(); i++) {
|
||||||
MultiFDRecvParams *p = &multifd_recv_state->params[i];
|
MultiFDRecvParams *p = &multifd_recv_state->params[i];
|
||||||
|
|
||||||
if (object_dynamic_cast(OBJECT(p->c), TYPE_QIO_CHANNEL_SOCKET)
|
if ((object_dynamic_cast(OBJECT(p->c), TYPE_QIO_CHANNEL_SOCKET) ||
|
||||||
|
object_dynamic_cast(OBJECT(p->c), TYPE_QIO_CHANNEL_TLS))
|
||||||
&& OBJECT(p->c)->ref == 1) {
|
&& OBJECT(p->c)->ref == 1) {
|
||||||
yank_unregister_function(MIGRATION_YANK_INSTANCE,
|
yank_unregister_function(MIGRATION_YANK_INSTANCE,
|
||||||
migration_yank_iochannel,
|
migration_yank_iochannel,
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "qemu-file-channel.h"
|
#include "qemu-file-channel.h"
|
||||||
#include "qemu-file.h"
|
#include "qemu-file.h"
|
||||||
#include "io/channel-socket.h"
|
#include "io/channel-socket.h"
|
||||||
|
#include "io/channel-tls.h"
|
||||||
#include "qemu/iov.h"
|
#include "qemu/iov.h"
|
||||||
#include "qemu/yank.h"
|
#include "qemu/yank.h"
|
||||||
#include "yank_functions.h"
|
#include "yank_functions.h"
|
||||||
|
@ -106,7 +107,8 @@ static int channel_close(void *opaque, Error **errp)
|
||||||
int ret;
|
int ret;
|
||||||
QIOChannel *ioc = QIO_CHANNEL(opaque);
|
QIOChannel *ioc = QIO_CHANNEL(opaque);
|
||||||
ret = qio_channel_close(ioc, errp);
|
ret = qio_channel_close(ioc, errp);
|
||||||
if (object_dynamic_cast(OBJECT(ioc), TYPE_QIO_CHANNEL_SOCKET)
|
if ((object_dynamic_cast(OBJECT(ioc), TYPE_QIO_CHANNEL_SOCKET) ||
|
||||||
|
object_dynamic_cast(OBJECT(ioc), TYPE_QIO_CHANNEL_TLS))
|
||||||
&& OBJECT(ioc)->ref == 1) {
|
&& OBJECT(ioc)->ref == 1) {
|
||||||
yank_unregister_function(MIGRATION_YANK_INSTANCE,
|
yank_unregister_function(MIGRATION_YANK_INSTANCE,
|
||||||
migration_yank_iochannel,
|
migration_yank_iochannel,
|
||||||
|
|
|
@ -2497,7 +2497,6 @@ static int qemu_rdma_connect(RDMAContext *rdma, Error **errp)
|
||||||
if (ret) {
|
if (ret) {
|
||||||
perror("rdma_get_cm_event after rdma_connect");
|
perror("rdma_get_cm_event after rdma_connect");
|
||||||
ERROR(errp, "connecting to destination!");
|
ERROR(errp, "connecting to destination!");
|
||||||
rdma_ack_cm_event(cm_event);
|
|
||||||
goto err_rdma_source_connect;
|
goto err_rdma_source_connect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,11 +49,7 @@ migration_tls_get_creds(MigrationState *s,
|
||||||
s->parameters.tls_creds);
|
s->parameters.tls_creds);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (ret->endpoint != endpoint) {
|
if (!qcrypto_tls_creds_check_endpoint(ret, endpoint, errp)) {
|
||||||
error_setg(errp,
|
|
||||||
"Expected TLS credentials for a %s endpoint",
|
|
||||||
endpoint == QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT ?
|
|
||||||
"client" : "server");
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1133,7 +1133,7 @@ void hmp_loadvm(Monitor *mon, const QDict *qdict)
|
||||||
|
|
||||||
vm_stop(RUN_STATE_RESTORE_VM);
|
vm_stop(RUN_STATE_RESTORE_VM);
|
||||||
|
|
||||||
if (!load_snapshot(name, NULL, false, NULL, &err) && saved_vm_running) {
|
if (load_snapshot(name, NULL, false, NULL, &err) && saved_vm_running) {
|
||||||
vm_start();
|
vm_start();
|
||||||
}
|
}
|
||||||
hmp_handle_error(mon, err);
|
hmp_handle_error(mon, err);
|
||||||
|
@ -1492,7 +1492,7 @@ void hmp_change(Monitor *mon, const QDict *qdict)
|
||||||
}
|
}
|
||||||
if (strcmp(target, "passwd") == 0 ||
|
if (strcmp(target, "passwd") == 0 ||
|
||||||
strcmp(target, "password") == 0) {
|
strcmp(target, "password") == 0) {
|
||||||
if (arg) {
|
if (!arg) {
|
||||||
MonitorHMP *hmp_mon = container_of(mon, MonitorHMP, common);
|
MonitorHMP *hmp_mon = container_of(mon, MonitorHMP, common);
|
||||||
monitor_read_password(hmp_mon, hmp_change_read_arg, NULL);
|
monitor_read_password(hmp_mon, hmp_change_read_arg, NULL);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -257,24 +257,6 @@ void coroutine_fn monitor_qmp_dispatcher_co(void *data)
|
||||||
trace_monitor_qmp_in_band_dequeue(req_obj,
|
trace_monitor_qmp_in_band_dequeue(req_obj,
|
||||||
req_obj->mon->qmp_requests->length);
|
req_obj->mon->qmp_requests->length);
|
||||||
|
|
||||||
if (qatomic_xchg(&qmp_dispatcher_co_busy, true) == true) {
|
|
||||||
/*
|
|
||||||
* Someone rescheduled us (probably because a new requests
|
|
||||||
* came in), but we didn't actually yield. Do that now,
|
|
||||||
* only to be immediately reentered and removed from the
|
|
||||||
* list of scheduled coroutines.
|
|
||||||
*/
|
|
||||||
qemu_coroutine_yield();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Move the coroutine from iohandler_ctx to qemu_aio_context for
|
|
||||||
* executing the command handler so that it can make progress if it
|
|
||||||
* involves an AIO_WAIT_WHILE().
|
|
||||||
*/
|
|
||||||
aio_co_schedule(qemu_get_aio_context(), qmp_dispatcher_co);
|
|
||||||
qemu_coroutine_yield();
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @req_obj has a request, we hold req_obj->mon->qmp_queue_lock
|
* @req_obj has a request, we hold req_obj->mon->qmp_queue_lock
|
||||||
*/
|
*/
|
||||||
|
@ -298,8 +280,30 @@ void coroutine_fn monitor_qmp_dispatcher_co(void *data)
|
||||||
monitor_resume(&mon->common);
|
monitor_resume(&mon->common);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Drop the queue mutex now, before yielding, otherwise we might
|
||||||
|
* deadlock if the main thread tries to lock it.
|
||||||
|
*/
|
||||||
qemu_mutex_unlock(&mon->qmp_queue_lock);
|
qemu_mutex_unlock(&mon->qmp_queue_lock);
|
||||||
|
|
||||||
|
if (qatomic_xchg(&qmp_dispatcher_co_busy, true) == true) {
|
||||||
|
/*
|
||||||
|
* Someone rescheduled us (probably because a new requests
|
||||||
|
* came in), but we didn't actually yield. Do that now,
|
||||||
|
* only to be immediately reentered and removed from the
|
||||||
|
* list of scheduled coroutines.
|
||||||
|
*/
|
||||||
|
qemu_coroutine_yield();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Move the coroutine from iohandler_ctx to qemu_aio_context for
|
||||||
|
* executing the command handler so that it can make progress if it
|
||||||
|
* involves an AIO_WAIT_WHILE().
|
||||||
|
*/
|
||||||
|
aio_co_schedule(qemu_get_aio_context(), qmp_dispatcher_co);
|
||||||
|
qemu_coroutine_yield();
|
||||||
|
|
||||||
/* Process request */
|
/* Process request */
|
||||||
if (req_obj->req) {
|
if (req_obj->req) {
|
||||||
if (trace_event_get_state(TRACE_MONITOR_QMP_CMD_IN_BAND)) {
|
if (trace_event_get_state(TRACE_MONITOR_QMP_CMD_IN_BAND)) {
|
||||||
|
|
25
qemu-nbd.c
25
qemu-nbd.c
|
@ -43,6 +43,7 @@
|
||||||
#include "io/channel-socket.h"
|
#include "io/channel-socket.h"
|
||||||
#include "io/net-listener.h"
|
#include "io/net-listener.h"
|
||||||
#include "crypto/init.h"
|
#include "crypto/init.h"
|
||||||
|
#include "crypto/tlscreds.h"
|
||||||
#include "trace/control.h"
|
#include "trace/control.h"
|
||||||
#include "qemu-version.h"
|
#include "qemu-version.h"
|
||||||
|
|
||||||
|
@ -134,7 +135,9 @@ static void usage(const char *name)
|
||||||
" 'snapshot.id=[ID],snapshot.name=[NAME]', or\n"
|
" 'snapshot.id=[ID],snapshot.name=[NAME]', or\n"
|
||||||
" '[ID_OR_NAME]'\n"
|
" '[ID_OR_NAME]'\n"
|
||||||
" -n, --nocache disable host cache\n"
|
" -n, --nocache disable host cache\n"
|
||||||
" --cache=MODE set cache mode (none, writeback, ...)\n"
|
" --cache=MODE set cache mode used to access the disk image, the\n"
|
||||||
|
" valid options are: 'none', 'writeback' (default),\n"
|
||||||
|
" 'writethrough', 'directsync' and 'unsafe'\n"
|
||||||
" --aio=MODE set AIO mode (native, io_uring or threads)\n"
|
" --aio=MODE set AIO mode (native, io_uring or threads)\n"
|
||||||
" --discard=MODE set discard mode (ignore, unmap)\n"
|
" --discard=MODE set discard mode (ignore, unmap)\n"
|
||||||
" --detect-zeroes=MODE set detect-zeroes mode (off, on, unmap)\n"
|
" --detect-zeroes=MODE set detect-zeroes mode (off, on, unmap)\n"
|
||||||
|
@ -422,18 +425,12 @@ static QCryptoTLSCreds *nbd_get_tls_creds(const char *id, bool list,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list) {
|
if (!qcrypto_tls_creds_check_endpoint(creds,
|
||||||
if (creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT) {
|
list
|
||||||
error_setg(errp,
|
? QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT
|
||||||
"Expecting TLS credentials with a client endpoint");
|
: QCRYPTO_TLS_CREDS_ENDPOINT_SERVER,
|
||||||
return NULL;
|
errp)) {
|
||||||
}
|
return NULL;
|
||||||
} else {
|
|
||||||
if (creds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
|
|
||||||
error_setg(errp,
|
|
||||||
"Expecting TLS credentials with a server endpoint");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
object_ref(obj);
|
object_ref(obj);
|
||||||
return creds;
|
return creds;
|
||||||
|
@ -557,7 +554,7 @@ int main(int argc, char **argv)
|
||||||
bool alloc_depth = false;
|
bool alloc_depth = false;
|
||||||
const char *tlscredsid = NULL;
|
const char *tlscredsid = NULL;
|
||||||
bool imageOpts = false;
|
bool imageOpts = false;
|
||||||
bool writethrough = true;
|
bool writethrough = false; /* Client will flush as needed. */
|
||||||
bool fork_process = false;
|
bool fork_process = false;
|
||||||
bool list = false;
|
bool list = false;
|
||||||
int old_stderr = -1;
|
int old_stderr = -1;
|
||||||
|
|
|
@ -746,7 +746,7 @@ static void qemu_run_exit_notifiers(void)
|
||||||
|
|
||||||
void qemu_init_subsystems(void)
|
void qemu_init_subsystems(void)
|
||||||
{
|
{
|
||||||
Error *err;
|
Error *err = NULL;
|
||||||
|
|
||||||
os_set_line_buffering();
|
os_set_line_buffering();
|
||||||
|
|
||||||
|
|
130
softmmu/vl.c
130
softmmu/vl.c
|
@ -122,6 +122,7 @@
|
||||||
#include "qapi/qapi-commands-misc.h"
|
#include "qapi/qapi-commands-misc.h"
|
||||||
#include "qapi/qapi-visit-qom.h"
|
#include "qapi/qapi-visit-qom.h"
|
||||||
#include "qapi/qapi-commands-ui.h"
|
#include "qapi/qapi-commands-ui.h"
|
||||||
|
#include "qapi/qmp/qdict.h"
|
||||||
#include "qapi/qmp/qerror.h"
|
#include "qapi/qmp/qerror.h"
|
||||||
#include "sysemu/iothread.h"
|
#include "sysemu/iothread.h"
|
||||||
#include "qemu/guest-random.h"
|
#include "qemu/guest-random.h"
|
||||||
|
@ -1708,9 +1709,15 @@ static void object_option_foreach_add(bool (*type_opt_predicate)(const char *))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void object_option_add_visitor(Visitor *v)
|
||||||
|
{
|
||||||
|
ObjectOption *opt = g_new0(ObjectOption, 1);
|
||||||
|
visit_type_ObjectOptions(v, NULL, &opt->opts, &error_fatal);
|
||||||
|
QTAILQ_INSERT_TAIL(&object_opts, opt, next);
|
||||||
|
}
|
||||||
|
|
||||||
static void object_option_parse(const char *optarg)
|
static void object_option_parse(const char *optarg)
|
||||||
{
|
{
|
||||||
ObjectOption *opt;
|
|
||||||
QemuOpts *opts;
|
QemuOpts *opts;
|
||||||
const char *type;
|
const char *type;
|
||||||
Visitor *v;
|
Visitor *v;
|
||||||
|
@ -1738,11 +1745,8 @@ static void object_option_parse(const char *optarg)
|
||||||
v = opts_visitor_new(opts);
|
v = opts_visitor_new(opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
opt = g_new0(ObjectOption, 1);
|
object_option_add_visitor(v);
|
||||||
visit_type_ObjectOptions(v, NULL, &opt->opts, &error_fatal);
|
|
||||||
visit_free(v);
|
visit_free(v);
|
||||||
|
|
||||||
QTAILQ_INSERT_TAIL(&object_opts, opt, next);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2025,8 +2029,6 @@ static void set_memory_options(MachineClass *mc)
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* store value for the future use */
|
|
||||||
qemu_opt_set_number(opts, "size", ram_size, &error_abort);
|
|
||||||
maxram_size = ram_size;
|
maxram_size = ram_size;
|
||||||
|
|
||||||
if (qemu_opt_get(opts, "maxmem")) {
|
if (qemu_opt_get(opts, "maxmem")) {
|
||||||
|
@ -2115,13 +2117,62 @@ static int global_init_func(void *opaque, QemuOpts *opts, Error **errp)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return whether configuration group @group is stored in QemuOpts, or
|
||||||
|
* recorded as one or more QDicts by qemu_record_config_group.
|
||||||
|
*/
|
||||||
|
static bool is_qemuopts_group(const char *group)
|
||||||
|
{
|
||||||
|
if (g_str_equal(group, "object")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void qemu_record_config_group(const char *group, QDict *dict,
|
||||||
|
bool from_json, Error **errp)
|
||||||
|
{
|
||||||
|
if (g_str_equal(group, "object")) {
|
||||||
|
Visitor *v = qobject_input_visitor_new_keyval(QOBJECT(dict));
|
||||||
|
object_option_add_visitor(v);
|
||||||
|
visit_free(v);
|
||||||
|
} else {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse non-QemuOpts config file groups, pass the rest to
|
||||||
|
* qemu_config_do_parse.
|
||||||
|
*/
|
||||||
|
static void qemu_parse_config_group(const char *group, QDict *qdict,
|
||||||
|
void *opaque, Error **errp)
|
||||||
|
{
|
||||||
|
QObject *crumpled;
|
||||||
|
if (is_qemuopts_group(group)) {
|
||||||
|
qemu_config_do_parse(group, qdict, opaque, errp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
crumpled = qdict_crumple(qdict, errp);
|
||||||
|
if (!crumpled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (qobject_type(crumpled) != QTYPE_QDICT) {
|
||||||
|
assert(qobject_type(crumpled) == QTYPE_QLIST);
|
||||||
|
error_setg(errp, "Lists cannot be at top level of a configuration section");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qemu_record_config_group(group, qobject_to(QDict, crumpled), false, errp);
|
||||||
|
}
|
||||||
|
|
||||||
static void qemu_read_default_config_file(Error **errp)
|
static void qemu_read_default_config_file(Error **errp)
|
||||||
{
|
{
|
||||||
ERRP_GUARD();
|
ERRP_GUARD();
|
||||||
int ret;
|
int ret;
|
||||||
g_autofree char *file = get_relocated_path(CONFIG_QEMU_CONFDIR "/qemu.conf");
|
g_autofree char *file = get_relocated_path(CONFIG_QEMU_CONFDIR "/qemu.conf");
|
||||||
|
|
||||||
ret = qemu_read_config_file(file, errp);
|
ret = qemu_read_config_file(file, qemu_parse_config_group, errp);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (ret == -ENOENT) {
|
if (ret == -ENOENT) {
|
||||||
error_free(*errp);
|
error_free(*errp);
|
||||||
|
@ -2130,9 +2181,8 @@ static void qemu_read_default_config_file(Error **errp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int qemu_set_option(const char *str)
|
static void qemu_set_option(const char *str, Error **errp)
|
||||||
{
|
{
|
||||||
Error *local_err = NULL;
|
|
||||||
char group[64], id[64], arg[64];
|
char group[64], id[64], arg[64];
|
||||||
QemuOptsList *list;
|
QemuOptsList *list;
|
||||||
QemuOpts *opts;
|
QemuOpts *opts;
|
||||||
|
@ -2140,27 +2190,23 @@ static int qemu_set_option(const char *str)
|
||||||
|
|
||||||
rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset);
|
rc = sscanf(str, "%63[^.].%63[^.].%63[^=]%n", group, id, arg, &offset);
|
||||||
if (rc < 3 || str[offset] != '=') {
|
if (rc < 3 || str[offset] != '=') {
|
||||||
error_report("can't parse: \"%s\"", str);
|
error_setg(errp, "can't parse: \"%s\"", str);
|
||||||
return -1;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
list = qemu_find_opts(group);
|
if (!is_qemuopts_group(group)) {
|
||||||
if (list == NULL) {
|
error_setg(errp, "-set is not supported with %s", group);
|
||||||
return -1;
|
} else {
|
||||||
|
list = qemu_find_opts_err(group, errp);
|
||||||
|
if (list) {
|
||||||
|
opts = qemu_opts_find(list, id);
|
||||||
|
if (!opts) {
|
||||||
|
error_setg(errp, "there is no %s \"%s\" defined", group, id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
qemu_opt_set(opts, arg, str + offset + 1, errp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
opts = qemu_opts_find(list, id);
|
|
||||||
if (!opts) {
|
|
||||||
error_report("there is no %s \"%s\" defined",
|
|
||||||
list->name, id);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!qemu_opt_set(opts, arg, str + offset + 1, &local_err)) {
|
|
||||||
error_report_err(local_err);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void user_register_global_props(void)
|
static void user_register_global_props(void)
|
||||||
|
@ -2462,7 +2508,7 @@ static void qemu_process_help_options(void)
|
||||||
|
|
||||||
static void qemu_maybe_daemonize(const char *pid_file)
|
static void qemu_maybe_daemonize(const char *pid_file)
|
||||||
{
|
{
|
||||||
Error *err;
|
Error *err = NULL;
|
||||||
|
|
||||||
os_daemonize();
|
os_daemonize();
|
||||||
rcu_disable_atfork();
|
rcu_disable_atfork();
|
||||||
|
@ -2615,6 +2661,23 @@ void qmp_x_exit_preconfig(Error **errp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_MODULES
|
||||||
|
void qemu_load_module_for_opts(const char *group)
|
||||||
|
{
|
||||||
|
static bool spice_tried;
|
||||||
|
if (g_str_equal(group, "spice") && !spice_tried) {
|
||||||
|
ui_module_load_one("spice-core");
|
||||||
|
spice_tried = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool iscsi_tried;
|
||||||
|
if (g_str_equal(group, "iscsi") && !iscsi_tried) {
|
||||||
|
block_module_load_one("iscsi");
|
||||||
|
iscsi_tried = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void qemu_init(int argc, char **argv, char **envp)
|
void qemu_init(int argc, char **argv, char **envp)
|
||||||
{
|
{
|
||||||
QemuOpts *opts;
|
QemuOpts *opts;
|
||||||
|
@ -2737,8 +2800,7 @@ void qemu_init(int argc, char **argv, char **envp)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_set:
|
case QEMU_OPTION_set:
|
||||||
if (qemu_set_option(optarg) != 0)
|
qemu_set_option(optarg, &error_fatal);
|
||||||
exit(1);
|
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_global:
|
case QEMU_OPTION_global:
|
||||||
if (qemu_global_option(optarg) != 0)
|
if (qemu_global_option(optarg) != 0)
|
||||||
|
@ -3370,14 +3432,10 @@ void qemu_init(int argc, char **argv, char **envp)
|
||||||
qemu_plugin_opt_parse(optarg, &plugin_list);
|
qemu_plugin_opt_parse(optarg, &plugin_list);
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_readconfig:
|
case QEMU_OPTION_readconfig:
|
||||||
qemu_read_config_file(optarg, &error_fatal);
|
qemu_read_config_file(optarg, qemu_parse_config_group, &error_fatal);
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_spice:
|
case QEMU_OPTION_spice:
|
||||||
olist = qemu_find_opts_err("spice", NULL);
|
olist = qemu_find_opts_err("spice", NULL);
|
||||||
if (!olist) {
|
|
||||||
ui_module_load_one("spice-core");
|
|
||||||
olist = qemu_find_opts("spice");
|
|
||||||
}
|
|
||||||
if (!olist) {
|
if (!olist) {
|
||||||
error_report("spice support is disabled");
|
error_report("spice support is disabled");
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
|
@ -22,6 +22,7 @@ stub_ss.add(files('isa-bus.c'))
|
||||||
stub_ss.add(files('is-daemonized.c'))
|
stub_ss.add(files('is-daemonized.c'))
|
||||||
stub_ss.add(when: 'CONFIG_LINUX_AIO', if_true: files('linux-aio.c'))
|
stub_ss.add(when: 'CONFIG_LINUX_AIO', if_true: files('linux-aio.c'))
|
||||||
stub_ss.add(files('migr-blocker.c'))
|
stub_ss.add(files('migr-blocker.c'))
|
||||||
|
stub_ss.add(files('module-opts.c'))
|
||||||
stub_ss.add(files('monitor.c'))
|
stub_ss.add(files('monitor.c'))
|
||||||
stub_ss.add(files('monitor-core.c'))
|
stub_ss.add(files('monitor-core.c'))
|
||||||
stub_ss.add(files('pci-bus.c'))
|
stub_ss.add(files('pci-bus.c'))
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
#include "qemu/osdep.h"
|
||||||
|
#include "qemu/config-file.h"
|
||||||
|
|
||||||
|
void qemu_load_module_for_opts(const char *group)
|
||||||
|
{
|
||||||
|
}
|
|
@ -816,6 +816,7 @@ vu_rem_mem_reg(VuDev *dev, VhostUserMsg *vmsg) {
|
||||||
shadow_regions[j].gpa = dev->regions[i].gpa;
|
shadow_regions[j].gpa = dev->regions[i].gpa;
|
||||||
shadow_regions[j].size = dev->regions[i].size;
|
shadow_regions[j].size = dev->regions[i].size;
|
||||||
shadow_regions[j].qva = dev->regions[i].qva;
|
shadow_regions[j].qva = dev->regions[i].qva;
|
||||||
|
shadow_regions[j].mmap_addr = dev->regions[i].mmap_addr;
|
||||||
shadow_regions[j].mmap_offset = dev->regions[i].mmap_offset;
|
shadow_regions[j].mmap_offset = dev->regions[i].mmap_offset;
|
||||||
j++;
|
j++;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -265,12 +265,15 @@ static void arm_cpu_reset(DeviceState *dev)
|
||||||
env->uncached_cpsr = ARM_CPU_MODE_SVC;
|
env->uncached_cpsr = ARM_CPU_MODE_SVC;
|
||||||
}
|
}
|
||||||
env->daif = PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F;
|
env->daif = PSTATE_D | PSTATE_A | PSTATE_I | PSTATE_F;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (arm_feature(env, ARM_FEATURE_M)) {
|
if (arm_feature(env, ARM_FEATURE_M)) {
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
uint32_t initial_msp; /* Loaded from 0x0 */
|
uint32_t initial_msp; /* Loaded from 0x0 */
|
||||||
uint32_t initial_pc; /* Loaded from 0x4 */
|
uint32_t initial_pc; /* Loaded from 0x4 */
|
||||||
uint8_t *rom;
|
uint8_t *rom;
|
||||||
uint32_t vecbase;
|
uint32_t vecbase;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (cpu_isar_feature(aa32_lob, cpu)) {
|
if (cpu_isar_feature(aa32_lob, cpu)) {
|
||||||
/*
|
/*
|
||||||
|
@ -324,6 +327,8 @@ static void arm_cpu_reset(DeviceState *dev)
|
||||||
env->v7m.fpccr[M_REG_S] = R_V7M_FPCCR_ASPEN_MASK |
|
env->v7m.fpccr[M_REG_S] = R_V7M_FPCCR_ASPEN_MASK |
|
||||||
R_V7M_FPCCR_LSPEN_MASK | R_V7M_FPCCR_S_MASK;
|
R_V7M_FPCCR_LSPEN_MASK | R_V7M_FPCCR_S_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
/* Unlike A/R profile, M profile defines the reset LR value */
|
/* Unlike A/R profile, M profile defines the reset LR value */
|
||||||
env->regs[14] = 0xffffffff;
|
env->regs[14] = 0xffffffff;
|
||||||
|
|
||||||
|
@ -351,8 +356,22 @@ static void arm_cpu_reset(DeviceState *dev)
|
||||||
env->regs[13] = initial_msp & 0xFFFFFFFC;
|
env->regs[13] = initial_msp & 0xFFFFFFFC;
|
||||||
env->regs[15] = initial_pc & ~1;
|
env->regs[15] = initial_pc & ~1;
|
||||||
env->thumb = initial_pc & 1;
|
env->thumb = initial_pc & 1;
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* For user mode we run non-secure and with access to the FPU.
|
||||||
|
* The FPU context is active (ie does not need further setup)
|
||||||
|
* and is owned by non-secure.
|
||||||
|
*/
|
||||||
|
env->v7m.secure = false;
|
||||||
|
env->v7m.nsacr = 0xcff;
|
||||||
|
env->v7m.cpacr[M_REG_NS] = 0xf0ffff;
|
||||||
|
env->v7m.fpccr[M_REG_S] &=
|
||||||
|
~(R_V7M_FPCCR_LSPEN_MASK | R_V7M_FPCCR_S_MASK);
|
||||||
|
env->v7m.control[M_REG_S] |= R_V7M_CONTROL_FPCA_MASK;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
/* AArch32 has a hard highvec setting of 0xFFFF0000. If we are currently
|
/* AArch32 has a hard highvec setting of 0xFFFF0000. If we are currently
|
||||||
* executing as AArch32 then check if highvecs are enabled and
|
* executing as AArch32 then check if highvecs are enabled and
|
||||||
* adjust the PC accordingly.
|
* adjust the PC accordingly.
|
||||||
|
|
|
@ -7198,6 +7198,8 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
|
||||||
gen_helper_rdmsr(cpu_env);
|
gen_helper_rdmsr(cpu_env);
|
||||||
} else {
|
} else {
|
||||||
gen_helper_wrmsr(cpu_env);
|
gen_helper_wrmsr(cpu_env);
|
||||||
|
gen_jmp_im(s, s->pc - s->cs_base);
|
||||||
|
gen_eob(s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -139,7 +139,7 @@ static void gen_lxvwsx(DisasContext *ctx)
|
||||||
gen_addr_reg_index(ctx, EA);
|
gen_addr_reg_index(ctx, EA);
|
||||||
|
|
||||||
data = tcg_temp_new_i32();
|
data = tcg_temp_new_i32();
|
||||||
tcg_gen_qemu_ld_i32(data, EA, ctx->mem_idx, MO_TEUL);
|
tcg_gen_qemu_ld_i32(data, EA, ctx->mem_idx, DEF_MEMOP(MO_UL));
|
||||||
tcg_gen_gvec_dup_i32(MO_UL, vsr_full_offset(xT(ctx->opcode)), 16, 16, data);
|
tcg_gen_gvec_dup_i32(MO_UL, vsr_full_offset(xT(ctx->opcode)), 16, 16, data);
|
||||||
|
|
||||||
tcg_temp_free(EA);
|
tcg_temp_free(EA);
|
||||||
|
@ -162,7 +162,7 @@ static void gen_lxvdsx(DisasContext *ctx)
|
||||||
gen_addr_reg_index(ctx, EA);
|
gen_addr_reg_index(ctx, EA);
|
||||||
|
|
||||||
data = tcg_temp_new_i64();
|
data = tcg_temp_new_i64();
|
||||||
tcg_gen_qemu_ld_i64(data, EA, ctx->mem_idx, MO_TEQ);
|
tcg_gen_qemu_ld_i64(data, EA, ctx->mem_idx, DEF_MEMOP(MO_Q));
|
||||||
tcg_gen_gvec_dup_i64(MO_Q, vsr_full_offset(xT(ctx->opcode)), 16, 16, data);
|
tcg_gen_gvec_dup_i64(MO_Q, vsr_full_offset(xT(ctx->opcode)), 16, 16, data);
|
||||||
|
|
||||||
tcg_temp_free(EA);
|
tcg_temp_free(EA);
|
||||||
|
|
|
@ -1817,7 +1817,7 @@ static void translate_l32ex(DisasContext *dc, const OpcodeArg arg[],
|
||||||
tcg_gen_mov_i32(addr, arg[1].in);
|
tcg_gen_mov_i32(addr, arg[1].in);
|
||||||
gen_load_store_alignment(dc, 2, addr, true);
|
gen_load_store_alignment(dc, 2, addr, true);
|
||||||
gen_check_exclusive(dc, addr, false);
|
gen_check_exclusive(dc, addr, false);
|
||||||
tcg_gen_qemu_ld_i32(arg[0].out, addr, dc->ring, MO_TEUL);
|
tcg_gen_qemu_ld_i32(arg[0].out, addr, dc->cring, MO_TEUL);
|
||||||
tcg_gen_mov_i32(cpu_exclusive_addr, addr);
|
tcg_gen_mov_i32(cpu_exclusive_addr, addr);
|
||||||
tcg_gen_mov_i32(cpu_exclusive_val, arg[0].out);
|
tcg_gen_mov_i32(cpu_exclusive_val, arg[0].out);
|
||||||
tcg_temp_free(addr);
|
tcg_temp_free(addr);
|
||||||
|
|
|
@ -987,14 +987,18 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
||||||
{
|
{
|
||||||
int tmp_buf_size, frame_size;
|
int tmp_buf_size, frame_size;
|
||||||
|
|
||||||
/* The TCG temp buffer is at the top of the frame, immediately
|
/*
|
||||||
below the frame pointer. */
|
* The TCG temp buffer is at the top of the frame, immediately
|
||||||
|
* below the frame pointer. Use the logical (aligned) offset here;
|
||||||
|
* the stack bias is applied in temp_allocate_frame().
|
||||||
|
*/
|
||||||
tmp_buf_size = CPU_TEMP_BUF_NLONGS * (int)sizeof(long);
|
tmp_buf_size = CPU_TEMP_BUF_NLONGS * (int)sizeof(long);
|
||||||
tcg_set_frame(s, TCG_REG_I6, TCG_TARGET_STACK_BIAS - tmp_buf_size,
|
tcg_set_frame(s, TCG_REG_I6, -tmp_buf_size, tmp_buf_size);
|
||||||
tmp_buf_size);
|
|
||||||
|
|
||||||
/* TCG_TARGET_CALL_STACK_OFFSET includes the stack bias, but is
|
/*
|
||||||
otherwise the minimal frame usable by callees. */
|
* TCG_TARGET_CALL_STACK_OFFSET includes the stack bias, but is
|
||||||
|
* otherwise the minimal frame usable by callees.
|
||||||
|
*/
|
||||||
frame_size = TCG_TARGET_CALL_STACK_OFFSET - TCG_TARGET_STACK_BIAS;
|
frame_size = TCG_TARGET_CALL_STACK_OFFSET - TCG_TARGET_STACK_BIAS;
|
||||||
frame_size += TCG_STATIC_CALL_ARGS_SIZE + tmp_buf_size;
|
frame_size += TCG_STATIC_CALL_ARGS_SIZE + tmp_buf_size;
|
||||||
frame_size += TCG_TARGET_STACK_ALIGN - 1;
|
frame_size += TCG_TARGET_STACK_ALIGN - 1;
|
||||||
|
|
40
tcg/tcg.c
40
tcg/tcg.c
|
@ -3489,20 +3489,38 @@ static void check_regs(TCGContext *s)
|
||||||
|
|
||||||
static void temp_allocate_frame(TCGContext *s, TCGTemp *ts)
|
static void temp_allocate_frame(TCGContext *s, TCGTemp *ts)
|
||||||
{
|
{
|
||||||
#if !(defined(__sparc__) && TCG_TARGET_REG_BITS == 64)
|
intptr_t off, size, align;
|
||||||
/* Sparc64 stack is accessed with offset of 2047 */
|
|
||||||
s->current_frame_offset = (s->current_frame_offset +
|
switch (ts->type) {
|
||||||
(tcg_target_long)sizeof(tcg_target_long) - 1) &
|
case TCG_TYPE_I32:
|
||||||
~(sizeof(tcg_target_long) - 1);
|
size = align = 4;
|
||||||
#endif
|
break;
|
||||||
if (s->current_frame_offset + (tcg_target_long)sizeof(tcg_target_long) >
|
case TCG_TYPE_I64:
|
||||||
s->frame_end) {
|
case TCG_TYPE_V64:
|
||||||
tcg_abort();
|
size = align = 8;
|
||||||
|
break;
|
||||||
|
case TCG_TYPE_V128:
|
||||||
|
size = align = 16;
|
||||||
|
break;
|
||||||
|
case TCG_TYPE_V256:
|
||||||
|
/* Note that we do not require aligned storage for V256. */
|
||||||
|
size = 32, align = 16;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
ts->mem_offset = s->current_frame_offset;
|
|
||||||
|
assert(align <= TCG_TARGET_STACK_ALIGN);
|
||||||
|
off = ROUND_UP(s->current_frame_offset, align);
|
||||||
|
assert(off + size <= s->frame_end);
|
||||||
|
s->current_frame_offset = off + size;
|
||||||
|
|
||||||
|
ts->mem_offset = off;
|
||||||
|
#if defined(__sparc__)
|
||||||
|
ts->mem_offset += TCG_TARGET_STACK_BIAS;
|
||||||
|
#endif
|
||||||
ts->mem_base = s->frame_temp;
|
ts->mem_base = s->frame_temp;
|
||||||
ts->mem_allocated = 1;
|
ts->mem_allocated = 1;
|
||||||
s->current_frame_offset += sizeof(tcg_target_long);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void temp_load(TCGContext *, TCGTemp *, TCGRegSet, TCGRegSet, TCGRegSet);
|
static void temp_load(TCGContext *, TCGTemp *, TCGRegSet, TCGRegSet, TCGRegSet);
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
7
ui/vnc.c
7
ui/vnc.c
|
@ -45,6 +45,7 @@
|
||||||
#include "qapi/qapi-commands-ui.h"
|
#include "qapi/qapi-commands-ui.h"
|
||||||
#include "ui/input.h"
|
#include "ui/input.h"
|
||||||
#include "crypto/hash.h"
|
#include "crypto/hash.h"
|
||||||
|
#include "crypto/tlscreds.h"
|
||||||
#include "crypto/tlscredsanon.h"
|
#include "crypto/tlscredsanon.h"
|
||||||
#include "crypto/tlscredsx509.h"
|
#include "crypto/tlscredsx509.h"
|
||||||
#include "crypto/random.h"
|
#include "crypto/random.h"
|
||||||
|
@ -4071,9 +4072,9 @@ void vnc_display_open(const char *id, Error **errp)
|
||||||
}
|
}
|
||||||
object_ref(OBJECT(vd->tlscreds));
|
object_ref(OBJECT(vd->tlscreds));
|
||||||
|
|
||||||
if (vd->tlscreds->endpoint != QCRYPTO_TLS_CREDS_ENDPOINT_SERVER) {
|
if (!qcrypto_tls_creds_check_endpoint(vd->tlscreds,
|
||||||
error_setg(errp,
|
QCRYPTO_TLS_CREDS_ENDPOINT_SERVER,
|
||||||
"Expecting TLS credentials with a server endpoint");
|
errp)) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include "block/qdict.h" /* for qdict_extract_subqdict() */
|
#include "block/qdict.h" /* for qdict_extract_subqdict() */
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "qapi/qapi-commands-misc.h"
|
#include "qapi/qapi-commands-misc.h"
|
||||||
|
#include "qapi/qmp/qerror.h"
|
||||||
#include "qapi/qmp/qdict.h"
|
#include "qapi/qmp/qdict.h"
|
||||||
#include "qapi/qmp/qlist.h"
|
#include "qapi/qmp/qlist.h"
|
||||||
#include "qemu/error-report.h"
|
#include "qemu/error-report.h"
|
||||||
|
@ -16,6 +17,7 @@ static QemuOptsList *find_list(QemuOptsList **lists, const char *group,
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
qemu_load_module_for_opts(group);
|
||||||
for (i = 0; lists[i] != NULL; i++) {
|
for (i = 0; lists[i] != NULL; i++) {
|
||||||
if (strcmp(lists[i]->name, group) == 0)
|
if (strcmp(lists[i]->name, group) == 0)
|
||||||
break;
|
break;
|
||||||
|
@ -350,19 +352,19 @@ void qemu_config_write(FILE *fp)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns number of config groups on success, -errno on error */
|
/* Returns number of config groups on success, -errno on error */
|
||||||
int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error **errp)
|
static int qemu_config_foreach(FILE *fp, QEMUConfigCB *cb, void *opaque,
|
||||||
|
const char *fname, Error **errp)
|
||||||
{
|
{
|
||||||
char line[1024], group[64], id[64], arg[64], value[1024];
|
char line[1024], prev_group[64], group[64], arg[64], value[1024];
|
||||||
Location loc;
|
Location loc;
|
||||||
QemuOptsList *list = NULL;
|
|
||||||
Error *local_err = NULL;
|
Error *local_err = NULL;
|
||||||
QemuOpts *opts = NULL;
|
QDict *qdict = NULL;
|
||||||
int res = -EINVAL, lno = 0;
|
int res = -EINVAL, lno = 0;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
loc_push_none(&loc);
|
loc_push_none(&loc);
|
||||||
while (fgets(line, sizeof(line), fp) != NULL) {
|
while (fgets(line, sizeof(line), fp) != NULL) {
|
||||||
loc_set_file(fname, ++lno);
|
++lno;
|
||||||
if (line[0] == '\n') {
|
if (line[0] == '\n') {
|
||||||
/* skip empty lines */
|
/* skip empty lines */
|
||||||
continue;
|
continue;
|
||||||
|
@ -371,39 +373,39 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error *
|
||||||
/* comment */
|
/* comment */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) {
|
if (line[0] == '[') {
|
||||||
/* group with id */
|
QDict *prev = qdict;
|
||||||
list = find_list(lists, group, &local_err);
|
if (sscanf(line, "[%63s \"%63[^\"]\"]", group, value) == 2) {
|
||||||
if (local_err) {
|
qdict = qdict_new();
|
||||||
error_propagate(errp, local_err);
|
qdict_put_str(qdict, "id", value);
|
||||||
goto out;
|
count++;
|
||||||
|
} else if (sscanf(line, "[%63[^]]]", group) == 1) {
|
||||||
|
qdict = qdict_new();
|
||||||
|
count++;
|
||||||
}
|
}
|
||||||
opts = qemu_opts_create(list, id, 1, NULL);
|
if (qdict != prev) {
|
||||||
count++;
|
if (prev) {
|
||||||
continue;
|
cb(prev_group, prev, opaque, &local_err);
|
||||||
}
|
qobject_unref(prev);
|
||||||
if (sscanf(line, "[%63[^]]]", group) == 1) {
|
if (local_err) {
|
||||||
/* group without id */
|
error_propagate(errp, local_err);
|
||||||
list = find_list(lists, group, &local_err);
|
goto out;
|
||||||
if (local_err) {
|
}
|
||||||
error_propagate(errp, local_err);
|
}
|
||||||
goto out;
|
strcpy(prev_group, group);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
opts = qemu_opts_create(list, NULL, 0, &error_abort);
|
|
||||||
count++;
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
loc_set_file(fname, lno);
|
||||||
value[0] = '\0';
|
value[0] = '\0';
|
||||||
if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2 ||
|
if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2 ||
|
||||||
sscanf(line, " %63s = \"\"", arg) == 1) {
|
sscanf(line, " %63s = \"\"", arg) == 1) {
|
||||||
/* arg = value */
|
/* arg = value */
|
||||||
if (opts == NULL) {
|
if (qdict == NULL) {
|
||||||
error_setg(errp, "no group defined");
|
error_setg(errp, "no group defined");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (!qemu_opt_set(opts, arg, value, errp)) {
|
qdict_put_str(qdict, arg, value);
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
error_setg(errp, "parse error");
|
error_setg(errp, "parse error");
|
||||||
|
@ -416,11 +418,48 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error *
|
||||||
}
|
}
|
||||||
res = count;
|
res = count;
|
||||||
out:
|
out:
|
||||||
|
if (qdict) {
|
||||||
|
cb(group, qdict, opaque, errp);
|
||||||
|
qobject_unref(qdict);
|
||||||
|
}
|
||||||
loc_pop(&loc);
|
loc_pop(&loc);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int qemu_read_config_file(const char *filename, Error **errp)
|
void qemu_config_do_parse(const char *group, QDict *qdict, void *opaque, Error **errp)
|
||||||
|
{
|
||||||
|
QemuOptsList **lists = opaque;
|
||||||
|
const char *id = qdict_get_try_str(qdict, "id");
|
||||||
|
QemuOptsList *list;
|
||||||
|
QemuOpts *opts;
|
||||||
|
const QDictEntry *unrecognized;
|
||||||
|
|
||||||
|
list = find_list(lists, group, errp);
|
||||||
|
if (!list) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
opts = qemu_opts_create(list, id, 1, errp);
|
||||||
|
if (!opts) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!qemu_opts_absorb_qdict(opts, qdict, errp)) {
|
||||||
|
qemu_opts_del(opts);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unrecognized = qdict_first(qdict);
|
||||||
|
if (unrecognized) {
|
||||||
|
error_setg(errp, QERR_INVALID_PARAMETER, unrecognized->key);
|
||||||
|
qemu_opts_del(opts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname, Error **errp)
|
||||||
|
{
|
||||||
|
return qemu_config_foreach(fp, qemu_config_do_parse, lists, fname, errp);
|
||||||
|
}
|
||||||
|
|
||||||
|
int qemu_read_config_file(const char *filename, QEMUConfigCB *cb, Error **errp)
|
||||||
{
|
{
|
||||||
FILE *f = fopen(filename, "r");
|
FILE *f = fopen(filename, "r");
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -430,7 +469,7 @@ int qemu_read_config_file(const char *filename, Error **errp)
|
||||||
return -errno;
|
return -errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = qemu_config_parse(f, vm_config_groups, filename, errp);
|
ret = qemu_config_foreach(f, cb, vm_config_groups, filename, errp);
|
||||||
fclose(f);
|
fclose(f);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1056,7 +1056,8 @@ bool qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp)
|
||||||
while (entry != NULL) {
|
while (entry != NULL) {
|
||||||
next = qdict_next(qdict, entry);
|
next = qdict_next(qdict, entry);
|
||||||
|
|
||||||
if (find_desc_by_name(opts->list->desc, entry->key)) {
|
if (opts_accepts_any(opts->list) ||
|
||||||
|
find_desc_by_name(opts->list->desc, entry->key)) {
|
||||||
if (!qemu_opts_from_qdict_entry(opts, entry, errp)) {
|
if (!qemu_opts_from_qdict_entry(opts, entry, errp)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1116,14 +1116,10 @@ fail:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int socket_get_fd(const char *fdstr, int num, Error **errp)
|
static int socket_get_fd(const char *fdstr, Error **errp)
|
||||||
{
|
{
|
||||||
Monitor *cur_mon = monitor_cur();
|
Monitor *cur_mon = monitor_cur();
|
||||||
int fd;
|
int fd;
|
||||||
if (num != 1) {
|
|
||||||
error_setg_errno(errp, EINVAL, "socket_get_fd: too many connections");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (cur_mon) {
|
if (cur_mon) {
|
||||||
fd = monitor_get_fd(cur_mon, fdstr, errp);
|
fd = monitor_get_fd(cur_mon, fdstr, errp);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
|
@ -1159,7 +1155,7 @@ int socket_connect(SocketAddress *addr, Error **errp)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SOCKET_ADDRESS_TYPE_FD:
|
case SOCKET_ADDRESS_TYPE_FD:
|
||||||
fd = socket_get_fd(addr->u.fd.str, 1, errp);
|
fd = socket_get_fd(addr->u.fd.str, errp);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SOCKET_ADDRESS_TYPE_VSOCK:
|
case SOCKET_ADDRESS_TYPE_VSOCK:
|
||||||
|
@ -1187,7 +1183,26 @@ int socket_listen(SocketAddress *addr, int num, Error **errp)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SOCKET_ADDRESS_TYPE_FD:
|
case SOCKET_ADDRESS_TYPE_FD:
|
||||||
fd = socket_get_fd(addr->u.fd.str, num, errp);
|
fd = socket_get_fd(addr->u.fd.str, errp);
|
||||||
|
if (fd < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the socket is not yet in the listen state, then transition it to
|
||||||
|
* the listen state now.
|
||||||
|
*
|
||||||
|
* If it's already listening then this updates the backlog value as
|
||||||
|
* requested.
|
||||||
|
*
|
||||||
|
* If this socket cannot listen because it's already in another state
|
||||||
|
* (e.g. unbound or connected) then we'll catch the error here.
|
||||||
|
*/
|
||||||
|
if (listen(fd, num) != 0) {
|
||||||
|
error_setg_errno(errp, errno, "Failed to listen on fd socket");
|
||||||
|
closesocket(fd);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SOCKET_ADDRESS_TYPE_VSOCK:
|
case SOCKET_ADDRESS_TYPE_VSOCK:
|
||||||
|
|
Loading…
Reference in New Issue