diff options
Diffstat (limited to 'meta/recipes-devtools/qemu/qemu')
40 files changed, 1786 insertions, 2624 deletions
diff --git a/meta/recipes-devtools/qemu/qemu/0001-Provide-support-for-the-CUSE-TPM.patch b/meta/recipes-devtools/qemu/qemu/0001-Provide-support-for-the-CUSE-TPM.patch deleted file mode 100644 index 74dc6f5df8..0000000000 --- a/meta/recipes-devtools/qemu/qemu/0001-Provide-support-for-the-CUSE-TPM.patch +++ /dev/null @@ -1,870 +0,0 @@ -From 8737eef18f39ed087fd911d0a0886e8174d0468c Mon Sep 17 00:00:00 2001 -From: Stefan Berger <stefanb@linux.vnet.ibm.com> -Date: Sat, 31 Dec 2016 11:23:32 -0500 -Subject: [PATCH 1/4] Provide support for the CUSE TPM - -Rather than integrating TPM functionality into QEMU directly -using the TPM emulation of libtpms, we now integrate an external -emulated TPM device. This device is expected to implement a Linux -CUSE interface (CUSE = character device in userspace). - -QEMU talks to the CUSE TPM using much functionality of the -passthrough driver. For example, the TPM commands and responses -are sent to the CUSE TPM using the read()/write() interface. -However, some out-of-band control needs to be done using the CUSE -TPM's ioctls. The CUSE TPM currently defines and implements 15 -different ioctls for controlling certain life-cycle aspects of -the emulated TPM. The ioctls can be regarded as a replacement for -direct function calls to a TPM emulator if the TPM were to be -directly integrated into QEMU. - -One of the ioctls allows to get a bitmask of supported capabilities. -Each returned bit indicates which capabilities have been implemented. -An include file defining the various ioctls is added to QEMU. - -The CUSE TPM and associated tools can be found here: - -https://github.com/stefanberger/swtpm - -(please use the latest version) - -To use the external CUSE TPM, the CUSE TPM should be started as follows: - -/usr/bin/swtpm_ioctl -s /dev/vtpm-test - -/usr/bin/swtpm_cuse -n vtpm-test - -QEMU can then be started using the following parameters: - -qemu-system-x86_64 \ - [...] \ - -tpmdev cuse-tpm,id=tpm0,cancel-path=/dev/null,path=/dev/vtpm-test \ - -device tpm-tis,id=tpm0,tpmdev=tpm0 \ - [...] - -Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com> -Cc: Eric Blake <eblake@redhat.com> - -Conflicts: - docs/qmp-commands.txt - -Patch cherry-picked from https://github.com/stefanberger/qemu-tpm, branch v2.8.0+tpm, -commit 27d6cd856d5a14061955df7a93ee490697a7a174. Applied cleanly except for -docs/qmp-commands.txt which did not exist yet in qemu 2.7. - -Upstream-Status: Pending [https://lists.nongnu.org/archive/html/qemu-devel/2016-06/msg00252.html] -Signed-off-by: Patrick Ohly <patrick.ohly@intel.com> ---- - hmp.c | 6 ++ - hw/tpm/tpm_int.h | 1 + - hw/tpm/tpm_ioctl.h | 215 +++++++++++++++++++++++++++++++++++++ - hw/tpm/tpm_passthrough.c | 274 +++++++++++++++++++++++++++++++++++++++++++++-- - qapi-schema.json | 18 +++- - qemu-options.hx | 21 +++- - tpm.c | 11 +- - 7 files changed, 529 insertions(+), 17 deletions(-) - create mode 100644 hw/tpm/tpm_ioctl.h - -diff --git a/hmp.c b/hmp.c -index cc2056e9e2..277b45ef5a 100644 ---- a/hmp.c -+++ b/hmp.c -@@ -883,6 +883,12 @@ void hmp_info_tpm(Monitor *mon, const QDict *qdict) - tpo->has_cancel_path ? ",cancel-path=" : "", - tpo->has_cancel_path ? tpo->cancel_path : ""); - break; -+ case TPM_TYPE_OPTIONS_KIND_CUSE_TPM: -+ tpo = ti->options->u.passthrough.data; -+ monitor_printf(mon, "%s%s", -+ tpo->has_path ? ",path=" : "", -+ tpo->has_path ? tpo->path : ""); -+ break; - case TPM_TYPE_OPTIONS_KIND__MAX: - break; - } -diff --git a/hw/tpm/tpm_int.h b/hw/tpm/tpm_int.h -index f2f285b3cc..6b2c9c953a 100644 ---- a/hw/tpm/tpm_int.h -+++ b/hw/tpm/tpm_int.h -@@ -61,6 +61,7 @@ struct tpm_resp_hdr { - #define TPM_TAG_RSP_AUTH1_COMMAND 0xc5 - #define TPM_TAG_RSP_AUTH2_COMMAND 0xc6 - -+#define TPM_SUCCESS 0 - #define TPM_FAIL 9 - - #define TPM_ORD_ContinueSelfTest 0x53 -diff --git a/hw/tpm/tpm_ioctl.h b/hw/tpm/tpm_ioctl.h -new file mode 100644 -index 0000000000..a341e15741 ---- /dev/null -+++ b/hw/tpm/tpm_ioctl.h -@@ -0,0 +1,215 @@ -+/* -+ * tpm_ioctl.h -+ * -+ * (c) Copyright IBM Corporation 2014, 2015. -+ * -+ * This file is licensed under the terms of the 3-clause BSD license -+ */ -+#ifndef _TPM_IOCTL_H_ -+#define _TPM_IOCTL_H_ -+ -+#include <stdint.h> -+#include <sys/uio.h> -+#include <sys/types.h> -+#include <sys/ioctl.h> -+ -+/* -+ * Every response from a command involving a TPM command execution must hold -+ * the ptm_res as the first element. -+ * ptm_res corresponds to the error code of a command executed by the TPM. -+ */ -+ -+typedef uint32_t ptm_res; -+ -+/* PTM_GET_TPMESTABLISHED: get the establishment bit */ -+struct ptm_est { -+ union { -+ struct { -+ ptm_res tpm_result; -+ unsigned char bit; /* TPM established bit */ -+ } resp; /* response */ -+ } u; -+}; -+ -+/* PTM_RESET_TPMESTABLISHED: reset establishment bit */ -+struct ptm_reset_est { -+ union { -+ struct { -+ uint8_t loc; /* locality to use */ -+ } req; /* request */ -+ struct { -+ ptm_res tpm_result; -+ } resp; /* response */ -+ } u; -+}; -+ -+/* PTM_INIT */ -+struct ptm_init { -+ union { -+ struct { -+ uint32_t init_flags; /* see definitions below */ -+ } req; /* request */ -+ struct { -+ ptm_res tpm_result; -+ } resp; /* response */ -+ } u; -+}; -+ -+/* above init_flags */ -+#define PTM_INIT_FLAG_DELETE_VOLATILE (1 << 0) -+ /* delete volatile state file after reading it */ -+ -+/* PTM_SET_LOCALITY */ -+struct ptm_loc { -+ union { -+ struct { -+ uint8_t loc; /* locality to set */ -+ } req; /* request */ -+ struct { -+ ptm_res tpm_result; -+ } resp; /* response */ -+ } u; -+}; -+ -+/* PTM_HASH_DATA: hash given data */ -+struct ptm_hdata { -+ union { -+ struct { -+ uint32_t length; -+ uint8_t data[4096]; -+ } req; /* request */ -+ struct { -+ ptm_res tpm_result; -+ } resp; /* response */ -+ } u; -+}; -+ -+/* -+ * size of the TPM state blob to transfer; x86_64 can handle 8k, -+ * ppc64le only ~7k; keep the response below a 4k page size -+ */ -+#define PTM_STATE_BLOB_SIZE (3 * 1024) -+ -+/* -+ * The following is the data structure to get state blobs from the TPM. -+ * If the size of the state blob exceeds the PTM_STATE_BLOB_SIZE, multiple reads -+ * with this ioctl and with adjusted offset are necessary. All bytes -+ * must be transferred and the transfer is done once the last byte has been -+ * returned. -+ * It is possible to use the read() interface for reading the data; however, -+ * the first bytes of the state blob will be part of the response to the ioctl(); -+ * a subsequent read() is only necessary if the total length (totlength) exceeds -+ * the number of received bytes. seek() is not supported. -+ */ -+struct ptm_getstate { -+ union { -+ struct { -+ uint32_t state_flags; /* may be: PTM_STATE_FLAG_DECRYPTED */ -+ uint32_t type; /* which blob to pull */ -+ uint32_t offset; /* offset from where to read */ -+ } req; /* request */ -+ struct { -+ ptm_res tpm_result; -+ uint32_t state_flags; /* may be: PTM_STATE_FLAG_ENCRYPTED */ -+ uint32_t totlength; /* total length that will be transferred */ -+ uint32_t length; /* number of bytes in following buffer */ -+ uint8_t data[PTM_STATE_BLOB_SIZE]; -+ } resp; /* response */ -+ } u; -+}; -+ -+/* TPM state blob types */ -+#define PTM_BLOB_TYPE_PERMANENT 1 -+#define PTM_BLOB_TYPE_VOLATILE 2 -+#define PTM_BLOB_TYPE_SAVESTATE 3 -+ -+/* state_flags above : */ -+#define PTM_STATE_FLAG_DECRYPTED 1 /* on input: get decrypted state */ -+#define PTM_STATE_FLAG_ENCRYPTED 2 /* on output: state is encrypted */ -+ -+/* -+ * The following is the data structure to set state blobs in the TPM. -+ * If the size of the state blob exceeds the PTM_STATE_BLOB_SIZE, multiple -+ * 'writes' using this ioctl are necessary. The last packet is indicated -+ * by the length being smaller than the PTM_STATE_BLOB_SIZE. -+ * The very first packet may have a length indicator of '0' enabling -+ * a write() with all the bytes from a buffer. If the write() interface -+ * is used, a final ioctl with a non-full buffer must be made to indicate -+ * that all data were transferred (a write with 0 bytes would not work). -+ */ -+struct ptm_setstate { -+ union { -+ struct { -+ uint32_t state_flags; /* may be PTM_STATE_FLAG_ENCRYPTED */ -+ uint32_t type; /* which blob to set */ -+ uint32_t length; /* length of the data; -+ use 0 on the first packet to -+ transfer using write() */ -+ uint8_t data[PTM_STATE_BLOB_SIZE]; -+ } req; /* request */ -+ struct { -+ ptm_res tpm_result; -+ } resp; /* response */ -+ } u; -+}; -+ -+/* -+ * PTM_GET_CONFIG: Data structure to get runtime configuration information -+ * such as which keys are applied. -+ */ -+struct ptm_getconfig { -+ union { -+ struct { -+ ptm_res tpm_result; -+ uint32_t flags; -+ } resp; /* response */ -+ } u; -+}; -+ -+#define PTM_CONFIG_FLAG_FILE_KEY 0x1 -+#define PTM_CONFIG_FLAG_MIGRATION_KEY 0x2 -+ -+ -+typedef uint64_t ptm_cap; -+typedef struct ptm_est ptm_est; -+typedef struct ptm_reset_est ptm_reset_est; -+typedef struct ptm_loc ptm_loc; -+typedef struct ptm_hdata ptm_hdata; -+typedef struct ptm_init ptm_init; -+typedef struct ptm_getstate ptm_getstate; -+typedef struct ptm_setstate ptm_setstate; -+typedef struct ptm_getconfig ptm_getconfig; -+ -+/* capability flags returned by PTM_GET_CAPABILITY */ -+#define PTM_CAP_INIT (1) -+#define PTM_CAP_SHUTDOWN (1<<1) -+#define PTM_CAP_GET_TPMESTABLISHED (1<<2) -+#define PTM_CAP_SET_LOCALITY (1<<3) -+#define PTM_CAP_HASHING (1<<4) -+#define PTM_CAP_CANCEL_TPM_CMD (1<<5) -+#define PTM_CAP_STORE_VOLATILE (1<<6) -+#define PTM_CAP_RESET_TPMESTABLISHED (1<<7) -+#define PTM_CAP_GET_STATEBLOB (1<<8) -+#define PTM_CAP_SET_STATEBLOB (1<<9) -+#define PTM_CAP_STOP (1<<10) -+#define PTM_CAP_GET_CONFIG (1<<11) -+ -+enum { -+ PTM_GET_CAPABILITY = _IOR('P', 0, ptm_cap), -+ PTM_INIT = _IOWR('P', 1, ptm_init), -+ PTM_SHUTDOWN = _IOR('P', 2, ptm_res), -+ PTM_GET_TPMESTABLISHED = _IOR('P', 3, ptm_est), -+ PTM_SET_LOCALITY = _IOWR('P', 4, ptm_loc), -+ PTM_HASH_START = _IOR('P', 5, ptm_res), -+ PTM_HASH_DATA = _IOWR('P', 6, ptm_hdata), -+ PTM_HASH_END = _IOR('P', 7, ptm_res), -+ PTM_CANCEL_TPM_CMD = _IOR('P', 8, ptm_res), -+ PTM_STORE_VOLATILE = _IOR('P', 9, ptm_res), -+ PTM_RESET_TPMESTABLISHED = _IOWR('P', 10, ptm_reset_est), -+ PTM_GET_STATEBLOB = _IOWR('P', 11, ptm_getstate), -+ PTM_SET_STATEBLOB = _IOWR('P', 12, ptm_setstate), -+ PTM_STOP = _IOR('P', 13, ptm_res), -+ PTM_GET_CONFIG = _IOR('P', 14, ptm_getconfig), -+}; -+ -+#endif /* _TPM_IOCTL_H */ -diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c -index e88c0d20bc..050f2ba850 100644 ---- a/hw/tpm/tpm_passthrough.c -+++ b/hw/tpm/tpm_passthrough.c -@@ -33,6 +33,7 @@ - #include "sysemu/tpm_backend_int.h" - #include "tpm_tis.h" - #include "tpm_util.h" -+#include "tpm_ioctl.h" - - #define DEBUG_TPM 0 - -@@ -45,6 +46,7 @@ - #define TYPE_TPM_PASSTHROUGH "tpm-passthrough" - #define TPM_PASSTHROUGH(obj) \ - OBJECT_CHECK(TPMPassthruState, (obj), TYPE_TPM_PASSTHROUGH) -+#define TYPE_TPM_CUSE "tpm-cuse" - - static const TPMDriverOps tpm_passthrough_driver; - -@@ -71,12 +73,18 @@ struct TPMPassthruState { - bool had_startup_error; - - TPMVersion tpm_version; -+ ptm_cap cuse_cap; /* capabilities of the CUSE TPM */ -+ uint8_t cur_locty_number; /* last set locality */ - }; - - typedef struct TPMPassthruState TPMPassthruState; - - #define TPM_PASSTHROUGH_DEFAULT_DEVICE "/dev/tpm0" - -+#define TPM_PASSTHROUGH_USES_CUSE_TPM(tpm_pt) (tpm_pt->cuse_cap != 0) -+ -+#define TPM_CUSE_IMPLEMENTS_ALL(S, cap) (((S)->cuse_cap & (cap)) == (cap)) -+ - /* functions */ - - static void tpm_passthrough_cancel_cmd(TPMBackend *tb); -@@ -148,7 +156,28 @@ static bool tpm_passthrough_is_selftest(const uint8_t *in, uint32_t in_len) - return false; - } - -+static int tpm_passthrough_set_locality(TPMPassthruState *tpm_pt, -+ uint8_t locty_number) -+{ -+ ptm_loc loc; -+ -+ if (TPM_PASSTHROUGH_USES_CUSE_TPM(tpm_pt)) { -+ if (tpm_pt->cur_locty_number != locty_number) { -+ loc.u.req.loc = locty_number; -+ if (ioctl(tpm_pt->tpm_fd, PTM_SET_LOCALITY, &loc) < 0) { -+ error_report("tpm_cuse: could not set locality on " -+ "CUSE TPM: %s", -+ strerror(errno)); -+ return -1; -+ } -+ tpm_pt->cur_locty_number = locty_number; -+ } -+ } -+ return 0; -+} -+ - static int tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt, -+ uint8_t locality_number, - const uint8_t *in, uint32_t in_len, - uint8_t *out, uint32_t out_len, - bool *selftest_done) -@@ -157,6 +186,11 @@ static int tpm_passthrough_unix_tx_bufs(TPMPassthruState *tpm_pt, - bool is_selftest; - const struct tpm_resp_hdr *hdr; - -+ ret = tpm_passthrough_set_locality(tpm_pt, locality_number); -+ if (ret < 0) { -+ goto err_exit; -+ } -+ - tpm_pt->tpm_op_canceled = false; - tpm_pt->tpm_executing = true; - *selftest_done = false; -@@ -207,10 +241,12 @@ err_exit: - } - - static int tpm_passthrough_unix_transfer(TPMPassthruState *tpm_pt, -+ uint8_t locality_number, - const TPMLocality *locty_data, - bool *selftest_done) - { - return tpm_passthrough_unix_tx_bufs(tpm_pt, -+ locality_number, - locty_data->w_buffer.buffer, - locty_data->w_offset, - locty_data->r_buffer.buffer, -@@ -231,6 +267,7 @@ static void tpm_passthrough_worker_thread(gpointer data, - switch (cmd) { - case TPM_BACKEND_CMD_PROCESS_CMD: - tpm_passthrough_unix_transfer(tpm_pt, -+ thr_parms->tpm_state->locty_number, - thr_parms->tpm_state->locty_data, - &selftest_done); - -@@ -247,6 +284,93 @@ static void tpm_passthrough_worker_thread(gpointer data, - } - - /* -+ * Gracefully shut down the external CUSE TPM -+ */ -+static void tpm_passthrough_shutdown(TPMPassthruState *tpm_pt) -+{ -+ ptm_res res; -+ -+ if (TPM_PASSTHROUGH_USES_CUSE_TPM(tpm_pt)) { -+ if (ioctl(tpm_pt->tpm_fd, PTM_SHUTDOWN, &res) < 0) { -+ error_report("tpm_cuse: Could not cleanly shut down " -+ "the CUSE TPM: %s", -+ strerror(errno)); -+ } -+ } -+} -+ -+/* -+ * Probe for the CUSE TPM by sending an ioctl() requesting its -+ * capability flags. -+ */ -+static int tpm_passthrough_cuse_probe(TPMPassthruState *tpm_pt) -+{ -+ int rc = 0; -+ -+ if (ioctl(tpm_pt->tpm_fd, PTM_GET_CAPABILITY, &tpm_pt->cuse_cap) < 0) { -+ error_report("Error: CUSE TPM was requested, but probing failed"); -+ rc = -1; -+ } -+ -+ return rc; -+} -+ -+static int tpm_passthrough_cuse_check_caps(TPMPassthruState *tpm_pt) -+{ -+ int rc = 0; -+ ptm_cap caps = 0; -+ const char *tpm = NULL; -+ -+ /* check for min. required capabilities */ -+ switch (tpm_pt->tpm_version) { -+ case TPM_VERSION_1_2: -+ caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN | PTM_CAP_GET_TPMESTABLISHED | -+ PTM_CAP_SET_LOCALITY; -+ tpm = "1.2"; -+ break; -+ case TPM_VERSION_2_0: -+ caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN | PTM_CAP_GET_TPMESTABLISHED | -+ PTM_CAP_SET_LOCALITY | PTM_CAP_RESET_TPMESTABLISHED; -+ tpm = "2"; -+ break; -+ case TPM_VERSION_UNSPEC: -+ error_report("tpm_cuse: %s: TPM version has not been set", -+ __func__); -+ return -1; -+ } -+ -+ if (!TPM_CUSE_IMPLEMENTS_ALL(tpm_pt, caps)) { -+ error_report("tpm_cuse: TPM does not implement minimum set of required " -+ "capabilities for TPM %s (0x%x)", tpm, (int)caps); -+ rc = -1; -+ } -+ -+ return rc; -+} -+ -+/* -+ * Initialize the external CUSE TPM -+ */ -+static int tpm_passthrough_cuse_init(TPMPassthruState *tpm_pt) -+{ -+ int rc = 0; -+ ptm_init init = { -+ .u.req.init_flags = PTM_INIT_FLAG_DELETE_VOLATILE, -+ }; -+ -+ if (TPM_PASSTHROUGH_USES_CUSE_TPM(tpm_pt)) { -+ if (ioctl(tpm_pt->tpm_fd, PTM_INIT, &init) < 0) { -+ error_report("tpm_cuse: Detected CUSE TPM but could not " -+ "send INIT: %s", -+ strerror(errno)); -+ rc = -1; -+ } -+ } -+ -+ return rc; -+} -+ -+/* - * Start the TPM (thread). If it had been started before, then terminate - * and start it again. - */ -@@ -261,6 +385,8 @@ static int tpm_passthrough_startup_tpm(TPMBackend *tb) - tpm_passthrough_worker_thread, - &tpm_pt->tpm_thread_params); - -+ tpm_passthrough_cuse_init(tpm_pt); -+ - return 0; - } - -@@ -291,14 +417,43 @@ static int tpm_passthrough_init(TPMBackend *tb, TPMState *s, - - static bool tpm_passthrough_get_tpm_established_flag(TPMBackend *tb) - { -+ TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); -+ ptm_est est; -+ -+ if (TPM_PASSTHROUGH_USES_CUSE_TPM(tpm_pt)) { -+ if (ioctl(tpm_pt->tpm_fd, PTM_GET_TPMESTABLISHED, &est) < 0) { -+ error_report("tpm_cuse: Could not get the TPM established " -+ "flag from the CUSE TPM: %s", -+ strerror(errno)); -+ return false; -+ } -+ return (est.u.resp.bit != 0); -+ } - return false; - } - - static int tpm_passthrough_reset_tpm_established_flag(TPMBackend *tb, - uint8_t locty) - { -+ TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); -+ int rc = 0; -+ ptm_reset_est ptmreset_est; -+ - /* only a TPM 2.0 will support this */ -- return 0; -+ if (tpm_pt->tpm_version == TPM_VERSION_2_0) { -+ if (TPM_PASSTHROUGH_USES_CUSE_TPM(tpm_pt)) { -+ ptmreset_est.u.req.loc = tpm_pt->cur_locty_number; -+ -+ if (ioctl(tpm_pt->tpm_fd, PTM_RESET_TPMESTABLISHED, -+ &ptmreset_est) < 0) { -+ error_report("tpm_cuse: Could not reset the establishment bit " -+ "failed: %s", -+ strerror(errno)); -+ rc = -1; -+ } -+ } -+ } -+ return rc; - } - - static bool tpm_passthrough_get_startup_error(TPMBackend *tb) -@@ -329,7 +484,8 @@ static void tpm_passthrough_deliver_request(TPMBackend *tb) - static void tpm_passthrough_cancel_cmd(TPMBackend *tb) - { - TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); -- int n; -+ ptm_res res; -+ static bool error_printed; - - /* - * As of Linux 3.7 the tpm_tis driver does not properly cancel -@@ -338,17 +494,34 @@ static void tpm_passthrough_cancel_cmd(TPMBackend *tb) - * command, e.g., a command executed on the host. - */ - if (tpm_pt->tpm_executing) { -- if (tpm_pt->cancel_fd >= 0) { -- n = write(tpm_pt->cancel_fd, "-", 1); -- if (n != 1) { -- error_report("Canceling TPM command failed: %s", -- strerror(errno)); -- } else { -- tpm_pt->tpm_op_canceled = true; -+ if (TPM_PASSTHROUGH_USES_CUSE_TPM(tpm_pt)) { -+ if (TPM_CUSE_IMPLEMENTS_ALL(tpm_pt, PTM_CAP_CANCEL_TPM_CMD)) { -+ if (ioctl(tpm_pt->tpm_fd, PTM_CANCEL_TPM_CMD, &res) < 0) { -+ error_report("tpm_cuse: Could not cancel command on " -+ "CUSE TPM: %s", -+ strerror(errno)); -+ } else if (res != TPM_SUCCESS) { -+ if (!error_printed) { -+ error_report("TPM error code from command " -+ "cancellation of CUSE TPM: 0x%x", res); -+ error_printed = true; -+ } -+ } else { -+ tpm_pt->tpm_op_canceled = true; -+ } - } - } else { -- error_report("Cannot cancel TPM command due to missing " -- "TPM sysfs cancel entry"); -+ if (tpm_pt->cancel_fd >= 0) { -+ if (write(tpm_pt->cancel_fd, "-", 1) != 1) { -+ error_report("Canceling TPM command failed: %s", -+ strerror(errno)); -+ } else { -+ tpm_pt->tpm_op_canceled = true; -+ } -+ } else { -+ error_report("Cannot cancel TPM command due to missing " -+ "TPM sysfs cancel entry"); -+ } - } - } - } -@@ -378,6 +551,11 @@ static int tpm_passthrough_open_sysfs_cancel(TPMBackend *tb) - char *dev; - char path[PATH_MAX]; - -+ if (TPM_PASSTHROUGH_USES_CUSE_TPM(tpm_pt)) { -+ /* not needed, but so we have a fd */ -+ return qemu_open("/dev/null", O_WRONLY); -+ } -+ - if (tb->cancel_path) { - fd = qemu_open(tb->cancel_path, O_WRONLY); - if (fd < 0) { -@@ -412,12 +590,22 @@ static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb) - { - TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); - const char *value; -+ bool have_cuse = false; -+ -+ value = qemu_opt_get(opts, "type"); -+ if (value != NULL && !strcmp("cuse-tpm", value)) { -+ have_cuse = true; -+ } - - value = qemu_opt_get(opts, "cancel-path"); - tb->cancel_path = g_strdup(value); - - value = qemu_opt_get(opts, "path"); - if (!value) { -+ if (have_cuse) { -+ error_report("Missing path to access CUSE TPM"); -+ goto err_free_parameters; -+ } - value = TPM_PASSTHROUGH_DEFAULT_DEVICE; - } - -@@ -432,15 +620,36 @@ static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb) - goto err_free_parameters; - } - -+ tpm_pt->cur_locty_number = ~0; -+ -+ if (have_cuse) { -+ if (tpm_passthrough_cuse_probe(tpm_pt)) { -+ goto err_close_tpmdev; -+ } -+ /* init TPM for probing */ -+ if (tpm_passthrough_cuse_init(tpm_pt)) { -+ goto err_close_tpmdev; -+ } -+ } -+ - if (tpm_util_test_tpmdev(tpm_pt->tpm_fd, &tpm_pt->tpm_version)) { - error_report("'%s' is not a TPM device.", - tpm_pt->tpm_dev); - goto err_close_tpmdev; - } - -+ if (have_cuse) { -+ if (tpm_passthrough_cuse_check_caps(tpm_pt)) { -+ goto err_close_tpmdev; -+ } -+ } -+ -+ - return 0; - - err_close_tpmdev: -+ tpm_passthrough_shutdown(tpm_pt); -+ - qemu_close(tpm_pt->tpm_fd); - tpm_pt->tpm_fd = -1; - -@@ -491,6 +700,8 @@ static void tpm_passthrough_destroy(TPMBackend *tb) - - tpm_backend_thread_end(&tpm_pt->tbt); - -+ tpm_passthrough_shutdown(tpm_pt); -+ - qemu_close(tpm_pt->tpm_fd); - qemu_close(tpm_pt->cancel_fd); - -@@ -564,3 +775,44 @@ static void tpm_passthrough_register(void) - } - - type_init(tpm_passthrough_register) -+ -+/* CUSE TPM */ -+static const char *tpm_passthrough_cuse_create_desc(void) -+{ -+ return "CUSE TPM backend driver"; -+} -+ -+static const TPMDriverOps tpm_cuse_driver = { -+ .type = TPM_TYPE_CUSE_TPM, -+ .opts = tpm_passthrough_cmdline_opts, -+ .desc = tpm_passthrough_cuse_create_desc, -+ .create = tpm_passthrough_create, -+ .destroy = tpm_passthrough_destroy, -+ .init = tpm_passthrough_init, -+ .startup_tpm = tpm_passthrough_startup_tpm, -+ .realloc_buffer = tpm_passthrough_realloc_buffer, -+ .reset = tpm_passthrough_reset, -+ .had_startup_error = tpm_passthrough_get_startup_error, -+ .deliver_request = tpm_passthrough_deliver_request, -+ .cancel_cmd = tpm_passthrough_cancel_cmd, -+ .get_tpm_established_flag = tpm_passthrough_get_tpm_established_flag, -+ .reset_tpm_established_flag = tpm_passthrough_reset_tpm_established_flag, -+ .get_tpm_version = tpm_passthrough_get_tpm_version, -+}; -+ -+static const TypeInfo tpm_cuse_info = { -+ .name = TYPE_TPM_CUSE, -+ .parent = TYPE_TPM_BACKEND, -+ .instance_size = sizeof(TPMPassthruState), -+ .class_init = tpm_passthrough_class_init, -+ .instance_init = tpm_passthrough_inst_init, -+ .instance_finalize = tpm_passthrough_inst_finalize, -+}; -+ -+static void tpm_cuse_register(void) -+{ -+ type_register_static(&tpm_cuse_info); -+ tpm_register_driver(&tpm_cuse_driver); -+} -+ -+type_init(tpm_cuse_register) -diff --git a/qapi-schema.json b/qapi-schema.json -index 5658723b37..53120d0f63 100644 ---- a/qapi-schema.json -+++ b/qapi-schema.json -@@ -3522,10 +3522,12 @@ - # An enumeration of TPM types - # - # @passthrough: TPM passthrough type -+# @cuse-tpm: CUSE TPM type -+# Since: 2.6 - # - # Since: 1.5 - ## --{ 'enum': 'TpmType', 'data': [ 'passthrough' ] } -+{ 'enum': 'TpmType', 'data': [ 'passthrough', 'cuse-tpm' ] } - - ## - # @query-tpm-types: -@@ -3554,6 +3556,17 @@ - '*cancel-path' : 'str'} } - - ## -+# @TPMCuseOptions: -+# -+# Information about the CUSE TPM type -+# -+# @path: string describing the path used for accessing the TPM device -+# -+# Since: 2.6 -+## -+{ 'struct': 'TPMCuseOptions', 'data': { 'path' : 'str'}} -+ -+## - # @TpmTypeOptions: - # - # A union referencing different TPM backend types' configuration options -@@ -3563,7 +3576,8 @@ - # Since: 1.5 - ## - { 'union': 'TpmTypeOptions', -- 'data': { 'passthrough' : 'TPMPassthroughOptions' } } -+ 'data': { 'passthrough' : 'TPMPassthroughOptions', -+ 'cuse-tpm' : 'TPMCuseOptions' } } - - ## - # @TpmInfo: -diff --git a/qemu-options.hx b/qemu-options.hx -index a71aaf8ea8..e0f1d8e676 100644 ---- a/qemu-options.hx -+++ b/qemu-options.hx -@@ -2763,7 +2763,10 @@ DEF("tpmdev", HAS_ARG, QEMU_OPTION_tpmdev, \ - "-tpmdev passthrough,id=id[,path=path][,cancel-path=path]\n" - " use path to provide path to a character device; default is /dev/tpm0\n" - " use cancel-path to provide path to TPM's cancel sysfs entry; if\n" -- " not provided it will be searched for in /sys/class/misc/tpm?/device\n", -+ " not provided it will be searched for in /sys/class/misc/tpm?/device\n" -+ "-tpmdev cuse-tpm,id=id,path=path\n" -+ " use path to provide path to a character device to talk to the\n" -+ " TPM emulator providing a CUSE interface\n", - QEMU_ARCH_ALL) - STEXI - -@@ -2772,8 +2775,8 @@ The general form of a TPM device option is: - - @item -tpmdev @var{backend} ,id=@var{id} [,@var{options}] - @findex -tpmdev --Backend type must be: --@option{passthrough}. -+Backend type must be either one of the following: -+@option{passthrough}, @option{cuse-tpm}. - - The specific backend type will determine the applicable options. - The @code{-tpmdev} option creates the TPM backend and requires a -@@ -2823,6 +2826,18 @@ To create a passthrough TPM use the following two options: - Note that the @code{-tpmdev} id is @code{tpm0} and is referenced by - @code{tpmdev=tpm0} in the device option. - -+@item -tpmdev cuse-tpm, id=@var{id}, path=@var{path} -+ -+(Linux-host only) Enable access to a TPM emulator with a CUSE interface. -+ -+@option{path} specifies the path to the CUSE TPM character device. -+ -+To create a backend device accessing the CUSE TPM emulator using /dev/vtpm -+use the following two options: -+@example -+-tpmdev cuse-tpm,id=tpm0,path=/dev/vtpm -device tpm-tis,tpmdev=tpm0 -+@end example -+ - @end table - - ETEXI -diff --git a/tpm.c b/tpm.c -index 9a7c7114d3..5ec2373286 100644 ---- a/tpm.c -+++ b/tpm.c -@@ -25,7 +25,7 @@ static QLIST_HEAD(, TPMBackend) tpm_backends = - - - #define TPM_MAX_MODELS 1 --#define TPM_MAX_DRIVERS 1 -+#define TPM_MAX_DRIVERS 2 - - static TPMDriverOps const *be_drivers[TPM_MAX_DRIVERS] = { - NULL, -@@ -272,6 +272,15 @@ static TPMInfo *qmp_query_tpm_inst(TPMBackend *drv) - tpo->has_cancel_path = true; - } - break; -+ case TPM_TYPE_CUSE_TPM: -+ res->options->type = TPM_TYPE_OPTIONS_KIND_CUSE_TPM; -+ tpo = g_new0(TPMPassthroughOptions, 1); -+ res->options->u.passthrough.data = tpo; -+ if (drv->path) { -+ tpo->path = g_strdup(drv->path); -+ tpo->has_path = true; -+ } -+ break; - case TPM_TYPE__MAX: - break; - } --- -2.11.0 - diff --git a/meta/recipes-devtools/qemu/qemu/0001-linux-user-x86_64-Handle-the-vsyscall-page-in-open_s.patch b/meta/recipes-devtools/qemu/qemu/0001-linux-user-x86_64-Handle-the-vsyscall-page-in-open_s.patch new file mode 100644 index 0000000000..2eaebe883c --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/0001-linux-user-x86_64-Handle-the-vsyscall-page-in-open_s.patch @@ -0,0 +1,56 @@ +From 4517e2046610722879761bcdb60edbb2b929c848 Mon Sep 17 00:00:00 2001 +From: Richard Henderson <richard.henderson@linaro.org> +Date: Wed, 28 Feb 2024 10:25:14 -1000 +Subject: [PATCH 1/5] linux-user/x86_64: Handle the vsyscall page in + open_self_maps_{2,4} + +This is the only case in which we expect to have no host memory backing +for a guest memory page, because in general linux user processes cannot +map any pages in the top half of the 64-bit address space. + +Upstream-Status: Submitted [https://www.mail-archive.com/qemu-devel@nongnu.org/msg1026793.html] + +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/2170 +Signed-off-by: Richard Henderson <richard.henderson@linaro.org> +Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> +--- + linux-user/syscall.c | 16 ++++++++++++++++ + 1 file changed, 16 insertions(+) + +diff --git a/linux-user/syscall.c b/linux-user/syscall.c +index a114f29a8..8307a8a61 100644 +--- a/linux-user/syscall.c ++++ b/linux-user/syscall.c +@@ -7922,6 +7922,10 @@ static void open_self_maps_4(const struct open_self_maps_data *d, + path = "[heap]"; + } else if (start == info->vdso) { + path = "[vdso]"; ++#ifdef TARGET_X86_64 ++ } else if (start == TARGET_VSYSCALL_PAGE) { ++ path = "[vsyscall]"; ++#endif + } + + /* Except null device (MAP_ANON), adjust offset for this fragment. */ +@@ -8010,6 +8014,18 @@ static int open_self_maps_2(void *opaque, target_ulong guest_start, + uintptr_t host_start = (uintptr_t)g2h_untagged(guest_start); + uintptr_t host_last = (uintptr_t)g2h_untagged(guest_end - 1); + ++#ifdef TARGET_X86_64 ++ /* ++ * Because of the extremely high position of the page within the guest ++ * virtual address space, this is not backed by host memory at all. ++ * Therefore the loop below would fail. This is the only instance ++ * of not having host backing memory. ++ */ ++ if (guest_start == TARGET_VSYSCALL_PAGE) { ++ return open_self_maps_3(opaque, guest_start, guest_end, flags); ++ } ++#endif ++ + while (1) { + IntervalTreeNode *n = + interval_tree_iter_first(d->host_maps, host_start, host_start); +-- +2.34.1 + diff --git a/meta/recipes-devtools/qemu/qemu/0001-qemu-Add-addition-environment-space-to-boot-loader-q.patch b/meta/recipes-devtools/qemu/qemu/0001-qemu-Add-addition-environment-space-to-boot-loader-q.patch new file mode 100644 index 0000000000..c65508017d --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/0001-qemu-Add-addition-environment-space-to-boot-loader-q.patch @@ -0,0 +1,33 @@ +From de64af82950a6908f9407dfc92b83c17e2af3eab Mon Sep 17 00:00:00 2001 +From: Jason Wessel <jason.wessel@windriver.com> +Date: Fri, 28 Mar 2014 17:42:43 +0800 +Subject: [PATCH 01/12] qemu: Add addition environment space to boot loader + qemu-system-mips + +Upstream-Status: Inappropriate - OE uses deep paths + +If you create a project with very long directory names like 128 characters +deep and use NFS, the kernel arguments will be truncated. The kernel will +accept longer strings such as 1024 bytes, but the qemu boot loader defaulted +to only 256 bytes. This patch expands the limit. + +Signed-off-by: Jason Wessel <jason.wessel@windriver.com> +Signed-off-by: Roy Li <rongqing.li@windriver.com> + +--- + hw/mips/malta.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: qemu-8.0.0/hw/mips/malta.c +=================================================================== +--- qemu-8.0.0.orig/hw/mips/malta.c ++++ qemu-8.0.0/hw/mips/malta.c +@@ -64,7 +64,7 @@ + #define ENVP_PADDR 0x2000 + #define ENVP_VADDR cpu_mips_phys_to_kseg0(NULL, ENVP_PADDR) + #define ENVP_NB_ENTRIES 16 +-#define ENVP_ENTRY_SIZE 256 ++#define ENVP_ENTRY_SIZE 1024 + + /* Hardware addresses */ + #define FLASH_ADDRESS 0x1e000000ULL diff --git a/meta/recipes-devtools/qemu/qemu/0002-Introduce-condition-to-notify-waiters-of-completed-c.patch b/meta/recipes-devtools/qemu/qemu/0002-Introduce-condition-to-notify-waiters-of-completed-c.patch deleted file mode 100644 index c88c98e565..0000000000 --- a/meta/recipes-devtools/qemu/qemu/0002-Introduce-condition-to-notify-waiters-of-completed-c.patch +++ /dev/null @@ -1,86 +0,0 @@ -From b5ffd3aa4e9bd4edb09cc84c46f78da72697a946 Mon Sep 17 00:00:00 2001 -From: Stefan Berger <stefanb@linux.vnet.ibm.com> -Date: Sat, 31 Dec 2016 11:23:32 -0500 -Subject: [PATCH 2/4] Introduce condition to notify waiters of completed - command - -Introduce a lock and a condition to notify anyone waiting for the completion -of the execution of a TPM command by the backend (thread). The backend -uses the condition to signal anyone waiting for command completion. -We need to place the condition in two locations: one is invoked by the -backend thread, the other by the bottom half thread. -We will use the signalling to wait for command completion before VM -suspend. - -Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com> - -Upstream-Status: Pending [https://lists.nongnu.org/archive/html/qemu-devel/2016-06/msg00252.html] -Signed-off-by: Patrick Ohly <patrick.ohly@intel.com> ---- - hw/tpm/tpm_int.h | 3 +++ - hw/tpm/tpm_tis.c | 14 ++++++++++++++ - 2 files changed, 17 insertions(+) - -diff --git a/hw/tpm/tpm_int.h b/hw/tpm/tpm_int.h -index 6b2c9c953a..70be1ad8d9 100644 ---- a/hw/tpm/tpm_int.h -+++ b/hw/tpm/tpm_int.h -@@ -30,6 +30,9 @@ struct TPMState { - char *backend; - TPMBackend *be_driver; - TPMVersion be_tpm_version; -+ -+ QemuMutex state_lock; -+ QemuCond cmd_complete; - }; - - #define TPM(obj) OBJECT_CHECK(TPMState, (obj), TYPE_TPM_TIS) -diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c -index 381e7266ea..14d9e83ea2 100644 ---- a/hw/tpm/tpm_tis.c -+++ b/hw/tpm/tpm_tis.c -@@ -368,6 +368,8 @@ static void tpm_tis_receive_bh(void *opaque) - TPMTISEmuState *tis = &s->s.tis; - uint8_t locty = s->locty_number; - -+ qemu_mutex_lock(&s->state_lock); -+ - tpm_tis_sts_set(&tis->loc[locty], - TPM_TIS_STS_VALID | TPM_TIS_STS_DATA_AVAILABLE); - tis->loc[locty].state = TPM_TIS_STATE_COMPLETION; -@@ -384,6 +386,10 @@ static void tpm_tis_receive_bh(void *opaque) - tpm_tis_raise_irq(s, locty, - TPM_TIS_INT_DATA_AVAILABLE | TPM_TIS_INT_STS_VALID); - #endif -+ -+ /* notify of completed command */ -+ qemu_cond_signal(&s->cmd_complete); -+ qemu_mutex_unlock(&s->state_lock); - } - - /* -@@ -403,6 +409,11 @@ static void tpm_tis_receive_cb(TPMState *s, uint8_t locty, - } - } - -+ qemu_mutex_lock(&s->state_lock); -+ /* notify of completed command */ -+ qemu_cond_signal(&s->cmd_complete); -+ qemu_mutex_unlock(&s->state_lock); -+ - qemu_bh_schedule(tis->bh); - } - -@@ -1072,6 +1083,9 @@ static void tpm_tis_initfn(Object *obj) - memory_region_init_io(&s->mmio, OBJECT(s), &tpm_tis_memory_ops, - s, "tpm-tis-mmio", - TPM_TIS_NUM_LOCALITIES << TPM_TIS_LOCALITY_SHIFT); -+ -+ qemu_mutex_init(&s->state_lock); -+ qemu_cond_init(&s->cmd_complete); - } - - static void tpm_tis_class_init(ObjectClass *klass, void *data) --- -2.11.0 - diff --git a/meta/recipes-devtools/qemu/qemu/0002-linux-user-Replace-use-of-lfs64-related-functions-an.patch b/meta/recipes-devtools/qemu/qemu/0002-linux-user-Replace-use-of-lfs64-related-functions-an.patch new file mode 100644 index 0000000000..ceae67be64 --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/0002-linux-user-Replace-use-of-lfs64-related-functions-an.patch @@ -0,0 +1,355 @@ +From 71f14902256e3c3529710b713e1ea43100bf4c40 Mon Sep 17 00:00:00 2001 +From: Khem Raj <raj.khem@gmail.com> +Date: Sat, 17 Dec 2022 08:37:46 -0800 +Subject: [PATCH 2/2] linux-user: Replace use of lfs64 related functions and + macros + +Builds defines -D_FILE_OFFSET_BITS=64 which makes the original functions +anf macros behave same as their 64 suffixed counterparts. This also +helps in compiling with latest musl C library, where these macros and +functions are no more available under _GNU_SOURCE feature macro + +Upstream-Status: Submitted [https://lists.gnu.org/archive/html/qemu-devel/2022-12/msg02841.html] +Signed-off-by: Khem Raj <raj.khem@gmail.com> +Cc: Laurent Vivier <laurent@vivier.eu> +--- + linux-user/syscall.c | 153 +++++++++++-------------------------------- + 1 file changed, 39 insertions(+), 114 deletions(-) + +Index: qemu-8.0.0/linux-user/syscall.c +=================================================================== +--- qemu-8.0.0.orig/linux-user/syscall.c ++++ qemu-8.0.0/linux-user/syscall.c +@@ -761,8 +761,8 @@ safe_syscall6(ssize_t, copy_file_range, + */ + #define safe_ioctl(...) safe_syscall(__NR_ioctl, __VA_ARGS__) + /* Similarly for fcntl. Note that callers must always: +- * pass the F_GETLK64 etc constants rather than the unsuffixed F_GETLK +- * use the flock64 struct rather than unsuffixed flock ++ * pass the F_GETLK etc constants rather than the unsuffixed F_GETLK ++ * use the flock struct rather than unsuffixed flock + * This will then work and use a 64-bit offset for both 32-bit and 64-bit hosts. + */ + #ifdef __NR_fcntl64 +@@ -6813,13 +6813,13 @@ static int target_to_host_fcntl_cmd(int + ret = cmd; + break; + case TARGET_F_GETLK: +- ret = F_GETLK64; ++ ret = F_GETLK; + break; + case TARGET_F_SETLK: +- ret = F_SETLK64; ++ ret = F_SETLK; + break; + case TARGET_F_SETLKW: +- ret = F_SETLKW64; ++ ret = F_SETLKW; + break; + case TARGET_F_GETOWN: + ret = F_GETOWN; +@@ -6833,17 +6833,6 @@ static int target_to_host_fcntl_cmd(int + case TARGET_F_SETSIG: + ret = F_SETSIG; + break; +-#if TARGET_ABI_BITS == 32 +- case TARGET_F_GETLK64: +- ret = F_GETLK64; +- break; +- case TARGET_F_SETLK64: +- ret = F_SETLK64; +- break; +- case TARGET_F_SETLKW64: +- ret = F_SETLKW64; +- break; +-#endif + case TARGET_F_SETLEASE: + ret = F_SETLEASE; + break; +@@ -6895,8 +6884,8 @@ static int target_to_host_fcntl_cmd(int + * them to 5, 6 and 7 before making the syscall(). Since we make the + * syscall directly, adjust to what is supported by the kernel. + */ +- if (ret >= F_GETLK64 && ret <= F_SETLKW64) { +- ret -= F_GETLK64 - 5; ++ if (ret >= F_GETLK && ret <= F_SETLKW) { ++ ret -= F_GETLK - 5; + } + #endif + +@@ -6929,55 +6918,11 @@ static int host_to_target_flock(int type + return type; + } + +-static inline abi_long copy_from_user_flock(struct flock64 *fl, +- abi_ulong target_flock_addr) +-{ +- struct target_flock *target_fl; +- int l_type; +- +- if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) { +- return -TARGET_EFAULT; +- } +- +- __get_user(l_type, &target_fl->l_type); +- l_type = target_to_host_flock(l_type); +- if (l_type < 0) { +- return l_type; +- } +- fl->l_type = l_type; +- __get_user(fl->l_whence, &target_fl->l_whence); +- __get_user(fl->l_start, &target_fl->l_start); +- __get_user(fl->l_len, &target_fl->l_len); +- __get_user(fl->l_pid, &target_fl->l_pid); +- unlock_user_struct(target_fl, target_flock_addr, 0); +- return 0; +-} +- +-static inline abi_long copy_to_user_flock(abi_ulong target_flock_addr, +- const struct flock64 *fl) +-{ +- struct target_flock *target_fl; +- short l_type; +- +- if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) { +- return -TARGET_EFAULT; +- } +- +- l_type = host_to_target_flock(fl->l_type); +- __put_user(l_type, &target_fl->l_type); +- __put_user(fl->l_whence, &target_fl->l_whence); +- __put_user(fl->l_start, &target_fl->l_start); +- __put_user(fl->l_len, &target_fl->l_len); +- __put_user(fl->l_pid, &target_fl->l_pid); +- unlock_user_struct(target_fl, target_flock_addr, 1); +- return 0; +-} +- +-typedef abi_long from_flock64_fn(struct flock64 *fl, abi_ulong target_addr); +-typedef abi_long to_flock64_fn(abi_ulong target_addr, const struct flock64 *fl); ++typedef abi_long from_flock_fn(struct flock *fl, abi_ulong target_addr); ++typedef abi_long to_flock_fn(abi_ulong target_addr, const struct flock *fl); + + #if defined(TARGET_ARM) && TARGET_ABI_BITS == 32 +-struct target_oabi_flock64 { ++struct target_oabi_flock { + abi_short l_type; + abi_short l_whence; + abi_llong l_start; +@@ -6985,10 +6930,10 @@ struct target_oabi_flock64 { + abi_int l_pid; + } QEMU_PACKED; + +-static inline abi_long copy_from_user_oabi_flock64(struct flock64 *fl, ++static inline abi_long copy_from_user_oabi_flock(struct flock *fl, + abi_ulong target_flock_addr) + { +- struct target_oabi_flock64 *target_fl; ++ struct target_oabi_flock *target_fl; + int l_type; + + if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) { +@@ -7009,10 +6954,10 @@ static inline abi_long copy_from_user_oa + return 0; + } + +-static inline abi_long copy_to_user_oabi_flock64(abi_ulong target_flock_addr, +- const struct flock64 *fl) ++static inline abi_long copy_to_user_oabi_flock(abi_ulong target_flock_addr, ++ const struct flock *fl) + { +- struct target_oabi_flock64 *target_fl; ++ struct target_oabi_flock *target_fl; + short l_type; + + if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) { +@@ -7030,10 +6975,10 @@ static inline abi_long copy_to_user_oabi + } + #endif + +-static inline abi_long copy_from_user_flock64(struct flock64 *fl, ++static inline abi_long copy_from_user_flock(struct flock *fl, + abi_ulong target_flock_addr) + { +- struct target_flock64 *target_fl; ++ struct target_flock *target_fl; + int l_type; + + if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) { +@@ -7054,10 +6999,10 @@ static inline abi_long copy_from_user_fl + return 0; + } + +-static inline abi_long copy_to_user_flock64(abi_ulong target_flock_addr, +- const struct flock64 *fl) ++static inline abi_long copy_to_user_flock(abi_ulong target_flock_addr, ++ const struct flock *fl) + { +- struct target_flock64 *target_fl; ++ struct target_flock *target_fl; + short l_type; + + if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) { +@@ -7076,7 +7021,7 @@ static inline abi_long copy_to_user_floc + + static abi_long do_fcntl(int fd, int cmd, abi_ulong arg) + { +- struct flock64 fl64; ++ struct flock fl64; + #ifdef F_GETOWN_EX + struct f_owner_ex fox; + struct target_f_owner_ex *target_fox; +@@ -7089,6 +7034,7 @@ static abi_long do_fcntl(int fd, int cmd + + switch(cmd) { + case TARGET_F_GETLK: ++ case TARGET_F_OFD_GETLK: + ret = copy_from_user_flock(&fl64, arg); + if (ret) { + return ret; +@@ -7098,32 +7044,11 @@ static abi_long do_fcntl(int fd, int cmd + ret = copy_to_user_flock(arg, &fl64); + } + break; +- + case TARGET_F_SETLK: + case TARGET_F_SETLKW: +- ret = copy_from_user_flock(&fl64, arg); +- if (ret) { +- return ret; +- } +- ret = get_errno(safe_fcntl(fd, host_cmd, &fl64)); +- break; +- +- case TARGET_F_GETLK64: +- case TARGET_F_OFD_GETLK: +- ret = copy_from_user_flock64(&fl64, arg); +- if (ret) { +- return ret; +- } +- ret = get_errno(safe_fcntl(fd, host_cmd, &fl64)); +- if (ret == 0) { +- ret = copy_to_user_flock64(arg, &fl64); +- } +- break; +- case TARGET_F_SETLK64: +- case TARGET_F_SETLKW64: + case TARGET_F_OFD_SETLK: + case TARGET_F_OFD_SETLKW: +- ret = copy_from_user_flock64(&fl64, arg); ++ ret = copy_from_user_flock(&fl64, arg); + if (ret) { + return ret; + } +@@ -7348,7 +7273,7 @@ static inline abi_long target_truncate64 + arg2 = arg3; + arg3 = arg4; + } +- return get_errno(truncate64(arg1, target_offset64(arg2, arg3))); ++ return get_errno(truncate(arg1, target_offset64(arg2, arg3))); + } + #endif + +@@ -7362,7 +7287,7 @@ static inline abi_long target_ftruncate6 + arg2 = arg3; + arg3 = arg4; + } +- return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3))); ++ return get_errno(ftruncate(arg1, target_offset64(arg2, arg3))); + } + #endif + +@@ -8598,7 +8523,7 @@ static int do_getdents(abi_long dirfd, a + void *tdirp; + int hlen, hoff, toff; + int hreclen, treclen; +- off64_t prev_diroff = 0; ++ off_t prev_diroff = 0; + + hdirp = g_try_malloc(count); + if (!hdirp) { +@@ -8651,7 +8576,7 @@ static int do_getdents(abi_long dirfd, a + * Return what we have, resetting the file pointer to the + * location of the first record not returned. + */ +- lseek64(dirfd, prev_diroff, SEEK_SET); ++ lseek(dirfd, prev_diroff, SEEK_SET); + break; + } + +@@ -8685,7 +8610,7 @@ static int do_getdents64(abi_long dirfd, + void *tdirp; + int hlen, hoff, toff; + int hreclen, treclen; +- off64_t prev_diroff = 0; ++ off_t prev_diroff = 0; + + hdirp = g_try_malloc(count); + if (!hdirp) { +@@ -8727,7 +8652,7 @@ static int do_getdents64(abi_long dirfd, + * Return what we have, resetting the file pointer to the + * location of the first record not returned. + */ +- lseek64(dirfd, prev_diroff, SEEK_SET); ++ lseek(dirfd, prev_diroff, SEEK_SET); + break; + } + +@@ -11158,7 +11083,7 @@ static abi_long do_syscall1(CPUArchState + return -TARGET_EFAULT; + } + } +- ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5))); ++ ret = get_errno(pread(arg1, p, arg3, target_offset64(arg4, arg5))); + unlock_user(p, arg2, ret); + return ret; + case TARGET_NR_pwrite64: +@@ -11175,7 +11100,7 @@ static abi_long do_syscall1(CPUArchState + return -TARGET_EFAULT; + } + } +- ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5))); ++ ret = get_errno(pwrite(arg1, p, arg3, target_offset64(arg4, arg5))); + unlock_user(p, arg2, 0); + return ret; + #endif +@@ -11998,14 +11923,14 @@ static abi_long do_syscall1(CPUArchState + case TARGET_NR_fcntl64: + { + int cmd; +- struct flock64 fl; +- from_flock64_fn *copyfrom = copy_from_user_flock64; +- to_flock64_fn *copyto = copy_to_user_flock64; ++ struct flock fl; ++ from_flock_fn *copyfrom = copy_from_user_flock; ++ to_flock_fn *copyto = copy_to_user_flock; + + #ifdef TARGET_ARM + if (!cpu_env->eabi) { +- copyfrom = copy_from_user_oabi_flock64; +- copyto = copy_to_user_oabi_flock64; ++ copyfrom = copy_from_user_oabi_flock; ++ copyto = copy_to_user_oabi_flock; + } + #endif + +@@ -12015,7 +11940,7 @@ static abi_long do_syscall1(CPUArchState + } + + switch(arg2) { +- case TARGET_F_GETLK64: ++ case TARGET_F_GETLK: + ret = copyfrom(&fl, arg3); + if (ret) { + break; +@@ -12026,8 +11951,8 @@ static abi_long do_syscall1(CPUArchState + } + break; + +- case TARGET_F_SETLK64: +- case TARGET_F_SETLKW64: ++ case TARGET_F_SETLK: ++ case TARGET_F_SETLKW: + ret = copyfrom(&fl, arg3); + if (ret) { + break; diff --git a/meta/recipes-devtools/qemu/qemu/0002-linux-user-loongarch64-Remove-TARGET_FORCE_SHMLBA.patch b/meta/recipes-devtools/qemu/qemu/0002-linux-user-loongarch64-Remove-TARGET_FORCE_SHMLBA.patch new file mode 100644 index 0000000000..3f01aaa644 --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/0002-linux-user-loongarch64-Remove-TARGET_FORCE_SHMLBA.patch @@ -0,0 +1,43 @@ +From 5bf65b24414d3ff8339f6f1beb221c7c35c91e5d Mon Sep 17 00:00:00 2001 +From: Richard Henderson <richard.henderson@linaro.org> +Date: Wed, 28 Feb 2024 10:25:15 -1000 +Subject: [PATCH 2/5] linux-user/loongarch64: Remove TARGET_FORCE_SHMLBA + +The kernel abi was changed with + + commit d23b77953f5a4fbf94c05157b186aac2a247ae32 + Author: Huacai Chen <chenhuacai@kernel.org> + Date: Wed Jan 17 12:43:08 2024 +0800 + + LoongArch: Change SHMLBA from SZ_64K to PAGE_SIZE + +during the v6.8 cycle. + +Upstream-Status: Submitted [https://www.mail-archive.com/qemu-devel@nongnu.org/msg1026793.html] + +Reviewed-by: Song Gao <gaosong@loongson.cn> +Signed-off-by: Richard Henderson <richard.henderson@linaro.org> +Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> +--- + linux-user/loongarch64/target_syscall.h | 7 ------- + 1 file changed, 7 deletions(-) + +diff --git a/linux-user/loongarch64/target_syscall.h b/linux-user/loongarch64/target_syscall.h +index 8b5de5212..39f229bb9 100644 +--- a/linux-user/loongarch64/target_syscall.h ++++ b/linux-user/loongarch64/target_syscall.h +@@ -38,11 +38,4 @@ struct target_pt_regs { + #define TARGET_MCL_FUTURE 2 + #define TARGET_MCL_ONFAULT 4 + +-#define TARGET_FORCE_SHMLBA +- +-static inline abi_ulong target_shmlba(CPULoongArchState *env) +-{ +- return 64 * KiB; +-} +- + #endif +-- +2.34.1 + diff --git a/meta/recipes-devtools/qemu/qemu/0003-Introduce-condition-in-TPM-backend-for-notification.patch b/meta/recipes-devtools/qemu/qemu/0003-Introduce-condition-in-TPM-backend-for-notification.patch deleted file mode 100644 index e58f019062..0000000000 --- a/meta/recipes-devtools/qemu/qemu/0003-Introduce-condition-in-TPM-backend-for-notification.patch +++ /dev/null @@ -1,79 +0,0 @@ -From 732a8e046948fd62b32cd1dd76a6798eb1caf4d6 Mon Sep 17 00:00:00 2001 -From: Stefan Berger <stefanb@linux.vnet.ibm.com> -Date: Sat, 31 Dec 2016 11:23:32 -0500 -Subject: [PATCH 3/4] Introduce condition in TPM backend for notification - -TPM backends will suspend independently of the frontends. Also -here we need to be able to wait for the TPM command to have been -completely processed. - -Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com> - -Upstream-Status: Pending [https://lists.nongnu.org/archive/html/qemu-devel/2016-06/msg00252.html] -Signed-off-by: Patrick Ohly <patrick.ohly@intel.com> ---- - hw/tpm/tpm_passthrough.c | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - -diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c -index 050f2ba850..44739ebad2 100644 ---- a/hw/tpm/tpm_passthrough.c -+++ b/hw/tpm/tpm_passthrough.c -@@ -75,6 +75,10 @@ struct TPMPassthruState { - TPMVersion tpm_version; - ptm_cap cuse_cap; /* capabilities of the CUSE TPM */ - uint8_t cur_locty_number; /* last set locality */ -+ -+ QemuMutex state_lock; -+ QemuCond cmd_complete; /* singnaled once tpm_busy is false */ -+ bool tpm_busy; - }; - - typedef struct TPMPassthruState TPMPassthruState; -@@ -274,6 +278,11 @@ static void tpm_passthrough_worker_thread(gpointer data, - thr_parms->recv_data_callback(thr_parms->tpm_state, - thr_parms->tpm_state->locty_number, - selftest_done); -+ /* result delivered */ -+ qemu_mutex_lock(&tpm_pt->state_lock); -+ tpm_pt->tpm_busy = false; -+ qemu_cond_signal(&tpm_pt->cmd_complete); -+ qemu_mutex_unlock(&tpm_pt->state_lock); - break; - case TPM_BACKEND_CMD_INIT: - case TPM_BACKEND_CMD_END: -@@ -401,6 +410,7 @@ static void tpm_passthrough_reset(TPMBackend *tb) - tpm_backend_thread_end(&tpm_pt->tbt); - - tpm_pt->had_startup_error = false; -+ tpm_pt->tpm_busy = false; - } - - static int tpm_passthrough_init(TPMBackend *tb, TPMState *s, -@@ -478,6 +488,11 @@ static void tpm_passthrough_deliver_request(TPMBackend *tb) - { - TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); - -+ /* TPM considered busy once TPM Request scheduled for processing */ -+ qemu_mutex_lock(&tpm_pt->state_lock); -+ tpm_pt->tpm_busy = true; -+ qemu_mutex_unlock(&tpm_pt->state_lock); -+ - tpm_backend_thread_deliver_request(&tpm_pt->tbt); - } - -@@ -746,6 +761,11 @@ static const TPMDriverOps tpm_passthrough_driver = { - - static void tpm_passthrough_inst_init(Object *obj) - { -+ TPMBackend *tb = TPM_BACKEND(obj); -+ TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); -+ -+ qemu_mutex_init(&tpm_pt->state_lock); -+ qemu_cond_init(&tpm_pt->cmd_complete); - } - - static void tpm_passthrough_inst_finalize(Object *obj) --- -2.11.0 - diff --git a/meta/recipes-devtools/qemu/qemu/apic-fixup-fallthrough-to-PIC.patch b/meta/recipes-devtools/qemu/qemu/0003-apic-fixup-fallthrough-to-PIC.patch index 9bbbc6f76d..e85f8202e9 100644 --- a/meta/recipes-devtools/qemu/qemu/apic-fixup-fallthrough-to-PIC.patch +++ b/meta/recipes-devtools/qemu/qemu/0003-apic-fixup-fallthrough-to-PIC.patch @@ -1,7 +1,7 @@ -From bef93bb81588b5323a52d2e1886f2a77b64a976b Mon Sep 17 00:00:00 2001 +From dc2a8ccd440ee3741b61606eafed3f7e092f4312 Mon Sep 17 00:00:00 2001 From: Mark Asselstine <mark.asselstine@windriver.com> Date: Tue, 26 Feb 2013 11:43:28 -0500 -Subject: [PATCH 03/18] apic: fixup fallthrough to PIC +Subject: [PATCH 03/12] apic: fixup fallthrough to PIC Commit 0e21e12bb311c4c1095d0269dc2ef81196ccb60a [Don't route PIC interrupts through the local APIC if the local APIC config says so.] @@ -24,16 +24,17 @@ serviced, is -1. Signed-off-by: Mark Asselstine <mark.asselstine@windriver.com> Upstream-Status: Submitted [https://lists.gnu.org/archive/html/qemu-devel/2013-04/msg00878.html] Signed-off-by: He Zhe <zhe.he@windriver.com> + --- hw/intc/apic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -diff --git a/hw/intc/apic.c b/hw/intc/apic.c -index 45887d99..c5ae4087 100644 ---- a/hw/intc/apic.c -+++ b/hw/intc/apic.c -@@ -587,7 +587,7 @@ int apic_accept_pic_intr(DeviceState *dev) - APICCommonState *s = APIC_COMMON(dev); +Index: qemu-8.0.0/hw/intc/apic.c +=================================================================== +--- qemu-8.0.0.orig/hw/intc/apic.c ++++ qemu-8.0.0/hw/intc/apic.c +@@ -607,7 +607,7 @@ int apic_accept_pic_intr(DeviceState *de + APICCommonState *s = APIC(dev); uint32_t lvt0; - if (!s) @@ -41,6 +42,3 @@ index 45887d99..c5ae4087 100644 return -1; lvt0 = s->lvt[APIC_LVT_LINT0]; --- -2.11.0 - diff --git a/meta/recipes-devtools/qemu/qemu/0003-linux-user-Add-strace-for-shmat.patch b/meta/recipes-devtools/qemu/qemu/0003-linux-user-Add-strace-for-shmat.patch new file mode 100644 index 0000000000..0c601c804a --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/0003-linux-user-Add-strace-for-shmat.patch @@ -0,0 +1,71 @@ +From e8f06676c6c88e12cd5f4f81a839b7111c683596 Mon Sep 17 00:00:00 2001 +From: Richard Henderson <richard.henderson@linaro.org> +Date: Wed, 28 Feb 2024 10:25:16 -1000 +Subject: [PATCH 3/5] linux-user: Add strace for shmat + +Upstream-Status: Submitted [https://www.mail-archive.com/qemu-devel@nongnu.org/msg1026793.html] + +Signed-off-by: Richard Henderson <richard.henderson@linaro.org> +Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> +--- + linux-user/strace.c | 23 +++++++++++++++++++++++ + linux-user/strace.list | 2 +- + 2 files changed, 24 insertions(+), 1 deletion(-) + +diff --git a/linux-user/strace.c b/linux-user/strace.c +index cf26e5526..47d6ec326 100644 +--- a/linux-user/strace.c ++++ b/linux-user/strace.c +@@ -670,6 +670,25 @@ print_semctl(CPUArchState *cpu_env, const struct syscallname *name, + } + #endif + ++static void ++print_shmat(CPUArchState *cpu_env, const struct syscallname *name, ++ abi_long arg0, abi_long arg1, abi_long arg2, ++ abi_long arg3, abi_long arg4, abi_long arg5) ++{ ++ static const struct flags shmat_flags[] = { ++ FLAG_GENERIC(SHM_RND), ++ FLAG_GENERIC(SHM_REMAP), ++ FLAG_GENERIC(SHM_RDONLY), ++ FLAG_GENERIC(SHM_EXEC), ++ }; ++ ++ print_syscall_prologue(name); ++ print_raw_param(TARGET_ABI_FMT_ld, arg0, 0); ++ print_pointer(arg1, 0); ++ print_flags(shmat_flags, arg2, 1); ++ print_syscall_epilogue(name); ++} ++ + #ifdef TARGET_NR_ipc + static void + print_ipc(CPUArchState *cpu_env, const struct syscallname *name, +@@ -683,6 +702,10 @@ print_ipc(CPUArchState *cpu_env, const struct syscallname *name, + print_ipc_cmd(arg3); + qemu_log(",0x" TARGET_ABI_FMT_lx ")", arg4); + break; ++ case IPCOP_shmat: ++ print_shmat(cpu_env, &(const struct syscallname){ .name = "shmat" }, ++ arg1, arg4, arg2, 0, 0, 0); ++ break; + default: + qemu_log(("%s(" + TARGET_ABI_FMT_ld "," +diff --git a/linux-user/strace.list b/linux-user/strace.list +index 6655d4f26..dfd4237d1 100644 +--- a/linux-user/strace.list ++++ b/linux-user/strace.list +@@ -1398,7 +1398,7 @@ + { TARGET_NR_sgetmask, "sgetmask" , NULL, NULL, NULL }, + #endif + #ifdef TARGET_NR_shmat +-{ TARGET_NR_shmat, "shmat" , NULL, NULL, print_syscall_ret_addr }, ++{ TARGET_NR_shmat, "shmat" , NULL, print_shmat, print_syscall_ret_addr }, + #endif + #ifdef TARGET_NR_shmctl + { TARGET_NR_shmctl, "shmctl" , NULL, NULL, NULL }, +-- +2.34.1 + diff --git a/meta/recipes-devtools/qemu/qemu/0004-Add-support-for-VM-suspend-resume-for-TPM-TIS-v2.9.patch b/meta/recipes-devtools/qemu/qemu/0004-Add-support-for-VM-suspend-resume-for-TPM-TIS-v2.9.patch deleted file mode 100644 index f1dbaffeac..0000000000 --- a/meta/recipes-devtools/qemu/qemu/0004-Add-support-for-VM-suspend-resume-for-TPM-TIS-v2.9.patch +++ /dev/null @@ -1,719 +0,0 @@ -From 5e9dd9063f514447ea4f54046793f4f01c297ed4 Mon Sep 17 00:00:00 2001 -From: Stefan Berger <stefanb@linux.vnet.ibm.com> -Date: Sat, 31 Dec 2016 11:23:32 -0500 -Subject: [PATCH 4/4] Add support for VM suspend/resume for TPM TIS - -Extend the TPM TIS code to support suspend/resume. In case a command -is being processed by the external TPM when suspending, wait for the command -to complete to catch the result. In case the bottom half did not run, -run the one function the bottom half is supposed to run. This then -makes the resume operation work. - -The passthrough backend does not support suspend/resume operation -and is therefore blocked from suspend/resume and migration. - -The CUSE TPM's supported capabilities are tested and if sufficient -capabilities are implemented, suspend/resume, snapshotting and -migration are supported by the CUSE TPM. - -Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com> - -Upstream-Status: Pending [https://lists.nongnu.org/archive/html/qemu-devel/2016-06/msg00252.html] -Signed-off-by: Patrick Ohly <patrick.ohly@intel.com> ---- - hw/tpm/tpm_passthrough.c | 130 +++++++++++++++++++++++-- - hw/tpm/tpm_tis.c | 137 +++++++++++++++++++++++++- - hw/tpm/tpm_tis.h | 2 + - hw/tpm/tpm_util.c | 223 +++++++++++++++++++++++++++++++++++++++++++ - hw/tpm/tpm_util.h | 7 ++ - include/sysemu/tpm_backend.h | 12 +++ - 6 files changed, 503 insertions(+), 8 deletions(-) - -diff --git a/hw/tpm/tpm_passthrough.c b/hw/tpm/tpm_passthrough.c -index 44739ebad2..bc8072d0bc 100644 ---- a/hw/tpm/tpm_passthrough.c -+++ b/hw/tpm/tpm_passthrough.c -@@ -34,6 +34,8 @@ - #include "tpm_tis.h" - #include "tpm_util.h" - #include "tpm_ioctl.h" -+#include "migration/migration.h" -+#include "qapi/error.h" - - #define DEBUG_TPM 0 - -@@ -49,6 +51,7 @@ - #define TYPE_TPM_CUSE "tpm-cuse" - - static const TPMDriverOps tpm_passthrough_driver; -+static const VMStateDescription vmstate_tpm_cuse; - - /* data structures */ - typedef struct TPMPassthruThreadParams { -@@ -79,6 +82,10 @@ struct TPMPassthruState { - QemuMutex state_lock; - QemuCond cmd_complete; /* singnaled once tpm_busy is false */ - bool tpm_busy; -+ -+ Error *migration_blocker; -+ -+ TPMBlobBuffers tpm_blobs; - }; - - typedef struct TPMPassthruState TPMPassthruState; -@@ -306,6 +313,10 @@ static void tpm_passthrough_shutdown(TPMPassthruState *tpm_pt) - strerror(errno)); - } - } -+ if (tpm_pt->migration_blocker) { -+ migrate_del_blocker(tpm_pt->migration_blocker); -+ error_free(tpm_pt->migration_blocker); -+ } - } - - /* -@@ -360,12 +371,14 @@ static int tpm_passthrough_cuse_check_caps(TPMPassthruState *tpm_pt) - /* - * Initialize the external CUSE TPM - */ --static int tpm_passthrough_cuse_init(TPMPassthruState *tpm_pt) -+static int tpm_passthrough_cuse_init(TPMPassthruState *tpm_pt, -+ bool is_resume) - { - int rc = 0; -- ptm_init init = { -- .u.req.init_flags = PTM_INIT_FLAG_DELETE_VOLATILE, -- }; -+ ptm_init init; -+ if (is_resume) { -+ init.u.req.init_flags = PTM_INIT_FLAG_DELETE_VOLATILE; -+ } - - if (TPM_PASSTHROUGH_USES_CUSE_TPM(tpm_pt)) { - if (ioctl(tpm_pt->tpm_fd, PTM_INIT, &init) < 0) { -@@ -394,7 +407,7 @@ static int tpm_passthrough_startup_tpm(TPMBackend *tb) - tpm_passthrough_worker_thread, - &tpm_pt->tpm_thread_params); - -- tpm_passthrough_cuse_init(tpm_pt); -+ tpm_passthrough_cuse_init(tpm_pt, false); - - return 0; - } -@@ -466,6 +479,32 @@ static int tpm_passthrough_reset_tpm_established_flag(TPMBackend *tb, - return rc; - } - -+static int tpm_cuse_get_state_blobs(TPMBackend *tb, -+ bool decrypted_blobs, -+ TPMBlobBuffers *tpm_blobs) -+{ -+ TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); -+ -+ assert(TPM_PASSTHROUGH_USES_CUSE_TPM(tpm_pt)); -+ -+ return tpm_util_cuse_get_state_blobs(tpm_pt->tpm_fd, decrypted_blobs, -+ tpm_blobs); -+} -+ -+static int tpm_cuse_set_state_blobs(TPMBackend *tb, -+ TPMBlobBuffers *tpm_blobs) -+{ -+ TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); -+ -+ assert(TPM_PASSTHROUGH_USES_CUSE_TPM(tpm_pt)); -+ -+ if (tpm_util_cuse_set_state_blobs(tpm_pt->tpm_fd, tpm_blobs)) { -+ return 1; -+ } -+ -+ return tpm_passthrough_cuse_init(tpm_pt, true); -+} -+ - static bool tpm_passthrough_get_startup_error(TPMBackend *tb) - { - TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); -@@ -488,7 +527,7 @@ static void tpm_passthrough_deliver_request(TPMBackend *tb) - { - TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); - -- /* TPM considered busy once TPM Request scheduled for processing */ -+ /* TPM considered busy once TPM request scheduled for processing */ - qemu_mutex_lock(&tpm_pt->state_lock); - tpm_pt->tpm_busy = true; - qemu_mutex_unlock(&tpm_pt->state_lock); -@@ -601,6 +640,25 @@ static int tpm_passthrough_open_sysfs_cancel(TPMBackend *tb) - return fd; - } - -+static void tpm_passthrough_block_migration(TPMPassthruState *tpm_pt) -+{ -+ ptm_cap caps; -+ -+ if (TPM_PASSTHROUGH_USES_CUSE_TPM(tpm_pt)) { -+ caps = PTM_CAP_GET_STATEBLOB | PTM_CAP_SET_STATEBLOB | -+ PTM_CAP_STOP; -+ if (!TPM_CUSE_IMPLEMENTS_ALL(tpm_pt, caps)) { -+ error_setg(&tpm_pt->migration_blocker, -+ "Migration disabled: CUSE TPM lacks necessary capabilities"); -+ migrate_add_blocker(tpm_pt->migration_blocker); -+ } -+ } else { -+ error_setg(&tpm_pt->migration_blocker, -+ "Migration disabled: Passthrough TPM does not support migration"); -+ migrate_add_blocker(tpm_pt->migration_blocker); -+ } -+} -+ - static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb) - { - TPMPassthruState *tpm_pt = TPM_PASSTHROUGH(tb); -@@ -642,7 +700,7 @@ static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb) - goto err_close_tpmdev; - } - /* init TPM for probing */ -- if (tpm_passthrough_cuse_init(tpm_pt)) { -+ if (tpm_passthrough_cuse_init(tpm_pt, false)) { - goto err_close_tpmdev; - } - } -@@ -659,6 +717,7 @@ static int tpm_passthrough_handle_device_opts(QemuOpts *opts, TPMBackend *tb) - } - } - -+ tpm_passthrough_block_migration(tpm_pt); - - return 0; - -@@ -766,10 +825,13 @@ static void tpm_passthrough_inst_init(Object *obj) - - qemu_mutex_init(&tpm_pt->state_lock); - qemu_cond_init(&tpm_pt->cmd_complete); -+ -+ vmstate_register(NULL, -1, &vmstate_tpm_cuse, obj); - } - - static void tpm_passthrough_inst_finalize(Object *obj) - { -+ vmstate_unregister(NULL, &vmstate_tpm_cuse, obj); - } - - static void tpm_passthrough_class_init(ObjectClass *klass, void *data) -@@ -802,6 +864,60 @@ static const char *tpm_passthrough_cuse_create_desc(void) - return "CUSE TPM backend driver"; - } - -+static void tpm_cuse_pre_save(void *opaque) -+{ -+ TPMPassthruState *tpm_pt = opaque; -+ TPMBackend *tb = &tpm_pt->parent; -+ -+ qemu_mutex_lock(&tpm_pt->state_lock); -+ /* wait for TPM to finish processing */ -+ if (tpm_pt->tpm_busy) { -+ qemu_cond_wait(&tpm_pt->cmd_complete, &tpm_pt->state_lock); -+ } -+ qemu_mutex_unlock(&tpm_pt->state_lock); -+ -+ /* get the decrypted state blobs from the TPM */ -+ tpm_cuse_get_state_blobs(tb, TRUE, &tpm_pt->tpm_blobs); -+} -+ -+static int tpm_cuse_post_load(void *opaque, -+ int version_id __attribute__((unused))) -+{ -+ TPMPassthruState *tpm_pt = opaque; -+ TPMBackend *tb = &tpm_pt->parent; -+ -+ return tpm_cuse_set_state_blobs(tb, &tpm_pt->tpm_blobs); -+} -+ -+static const VMStateDescription vmstate_tpm_cuse = { -+ .name = "cuse-tpm", -+ .version_id = 1, -+ .minimum_version_id = 0, -+ .minimum_version_id_old = 0, -+ .pre_save = tpm_cuse_pre_save, -+ .post_load = tpm_cuse_post_load, -+ .fields = (VMStateField[]) { -+ VMSTATE_UINT32(tpm_blobs.permanent_flags, TPMPassthruState), -+ VMSTATE_UINT32(tpm_blobs.permanent.size, TPMPassthruState), -+ VMSTATE_VBUFFER_ALLOC_UINT32(tpm_blobs.permanent.buffer, -+ TPMPassthruState, 1, NULL, -+ tpm_blobs.permanent.size), -+ -+ VMSTATE_UINT32(tpm_blobs.volatil_flags, TPMPassthruState), -+ VMSTATE_UINT32(tpm_blobs.volatil.size, TPMPassthruState), -+ VMSTATE_VBUFFER_ALLOC_UINT32(tpm_blobs.volatil.buffer, -+ TPMPassthruState, 1, NULL, -+ tpm_blobs.volatil.size), -+ -+ VMSTATE_UINT32(tpm_blobs.savestate_flags, TPMPassthruState), -+ VMSTATE_UINT32(tpm_blobs.savestate.size, TPMPassthruState), -+ VMSTATE_VBUFFER_ALLOC_UINT32(tpm_blobs.savestate.buffer, -+ TPMPassthruState, 1, NULL, -+ tpm_blobs.savestate.size), -+ VMSTATE_END_OF_LIST() -+ } -+}; -+ - static const TPMDriverOps tpm_cuse_driver = { - .type = TPM_TYPE_CUSE_TPM, - .opts = tpm_passthrough_cmdline_opts, -diff --git a/hw/tpm/tpm_tis.c b/hw/tpm/tpm_tis.c -index 14d9e83ea2..9b660cf737 100644 ---- a/hw/tpm/tpm_tis.c -+++ b/hw/tpm/tpm_tis.c -@@ -368,6 +368,8 @@ static void tpm_tis_receive_bh(void *opaque) - TPMTISEmuState *tis = &s->s.tis; - uint8_t locty = s->locty_number; - -+ tis->bh_scheduled = false; -+ - qemu_mutex_lock(&s->state_lock); - - tpm_tis_sts_set(&tis->loc[locty], -@@ -415,6 +417,8 @@ static void tpm_tis_receive_cb(TPMState *s, uint8_t locty, - qemu_mutex_unlock(&s->state_lock); - - qemu_bh_schedule(tis->bh); -+ -+ tis->bh_scheduled = true; - } - - /* -@@ -1030,9 +1034,140 @@ static void tpm_tis_reset(DeviceState *dev) - tpm_tis_do_startup_tpm(s); - } - -+ -+/* persistent state handling */ -+ -+static void tpm_tis_pre_save(void *opaque) -+{ -+ TPMState *s = opaque; -+ TPMTISEmuState *tis = &s->s.tis; -+ uint8_t locty = tis->active_locty; -+ -+ DPRINTF("tpm_tis: suspend: locty = %d : r_offset = %d, w_offset = %d\n", -+ locty, tis->loc[0].r_offset, tis->loc[0].w_offset); -+#ifdef DEBUG_TIS -+ tpm_tis_dump_state(opaque, 0); -+#endif -+ -+ qemu_mutex_lock(&s->state_lock); -+ -+ /* wait for outstanding request to complete */ -+ if (TPM_TIS_IS_VALID_LOCTY(locty) && -+ tis->loc[locty].state == TPM_TIS_STATE_EXECUTION) { -+ /* -+ * If we get here when the bh is scheduled but did not run, -+ * we won't get notified... -+ */ -+ if (!tis->bh_scheduled) { -+ /* backend thread to notify us */ -+ qemu_cond_wait(&s->cmd_complete, &s->state_lock); -+ } -+ if (tis->loc[locty].state == TPM_TIS_STATE_EXECUTION) { -+ /* bottom half did not run - run its function */ -+ qemu_mutex_unlock(&s->state_lock); -+ tpm_tis_receive_bh(opaque); -+ qemu_mutex_lock(&s->state_lock); -+ } -+ } -+ -+ qemu_mutex_unlock(&s->state_lock); -+ -+ /* copy current active read or write buffer into the buffer -+ written to disk */ -+ if (TPM_TIS_IS_VALID_LOCTY(locty)) { -+ switch (tis->loc[locty].state) { -+ case TPM_TIS_STATE_RECEPTION: -+ memcpy(tis->buf, -+ tis->loc[locty].w_buffer.buffer, -+ MIN(sizeof(tis->buf), -+ tis->loc[locty].w_buffer.size)); -+ tis->offset = tis->loc[locty].w_offset; -+ break; -+ case TPM_TIS_STATE_COMPLETION: -+ memcpy(tis->buf, -+ tis->loc[locty].r_buffer.buffer, -+ MIN(sizeof(tis->buf), -+ tis->loc[locty].r_buffer.size)); -+ tis->offset = tis->loc[locty].r_offset; -+ break; -+ default: -+ /* leak nothing */ -+ memset(tis->buf, 0x0, sizeof(tis->buf)); -+ break; -+ } -+ } -+} -+ -+static int tpm_tis_post_load(void *opaque, -+ int version_id __attribute__((unused))) -+{ -+ TPMState *s = opaque; -+ TPMTISEmuState *tis = &s->s.tis; -+ -+ uint8_t locty = tis->active_locty; -+ -+ if (TPM_TIS_IS_VALID_LOCTY(locty)) { -+ switch (tis->loc[locty].state) { -+ case TPM_TIS_STATE_RECEPTION: -+ memcpy(tis->loc[locty].w_buffer.buffer, -+ tis->buf, -+ MIN(sizeof(tis->buf), -+ tis->loc[locty].w_buffer.size)); -+ tis->loc[locty].w_offset = tis->offset; -+ break; -+ case TPM_TIS_STATE_COMPLETION: -+ memcpy(tis->loc[locty].r_buffer.buffer, -+ tis->buf, -+ MIN(sizeof(tis->buf), -+ tis->loc[locty].r_buffer.size)); -+ tis->loc[locty].r_offset = tis->offset; -+ break; -+ default: -+ break; -+ } -+ } -+ -+ DPRINTF("tpm_tis: resume : locty = %d : r_offset = %d, w_offset = %d\n", -+ locty, tis->loc[0].r_offset, tis->loc[0].w_offset); -+ -+ return 0; -+} -+ -+static const VMStateDescription vmstate_locty = { -+ .name = "loc", -+ .version_id = 1, -+ .minimum_version_id = 0, -+ .minimum_version_id_old = 0, -+ .fields = (VMStateField[]) { -+ VMSTATE_UINT32(state, TPMLocality), -+ VMSTATE_UINT32(inte, TPMLocality), -+ VMSTATE_UINT32(ints, TPMLocality), -+ VMSTATE_UINT8(access, TPMLocality), -+ VMSTATE_UINT32(sts, TPMLocality), -+ VMSTATE_UINT32(iface_id, TPMLocality), -+ VMSTATE_END_OF_LIST(), -+ } -+}; -+ - static const VMStateDescription vmstate_tpm_tis = { - .name = "tpm", -- .unmigratable = 1, -+ .version_id = 1, -+ .minimum_version_id = 0, -+ .minimum_version_id_old = 0, -+ .pre_save = tpm_tis_pre_save, -+ .post_load = tpm_tis_post_load, -+ .fields = (VMStateField[]) { -+ VMSTATE_UINT32(s.tis.offset, TPMState), -+ VMSTATE_BUFFER(s.tis.buf, TPMState), -+ VMSTATE_UINT8(s.tis.active_locty, TPMState), -+ VMSTATE_UINT8(s.tis.aborting_locty, TPMState), -+ VMSTATE_UINT8(s.tis.next_locty, TPMState), -+ -+ VMSTATE_STRUCT_ARRAY(s.tis.loc, TPMState, TPM_TIS_NUM_LOCALITIES, 1, -+ vmstate_locty, TPMLocality), -+ -+ VMSTATE_END_OF_LIST() -+ } - }; - - static Property tpm_tis_properties[] = { -diff --git a/hw/tpm/tpm_tis.h b/hw/tpm/tpm_tis.h -index a1df41fa21..b7fc0ea1a9 100644 ---- a/hw/tpm/tpm_tis.h -+++ b/hw/tpm/tpm_tis.h -@@ -54,6 +54,8 @@ typedef struct TPMLocality { - - typedef struct TPMTISEmuState { - QEMUBH *bh; -+ bool bh_scheduled; /* bh scheduled but did not run yet */ -+ - uint32_t offset; - uint8_t buf[TPM_TIS_BUFFER_MAX]; - -diff --git a/hw/tpm/tpm_util.c b/hw/tpm/tpm_util.c -index 7b35429725..b6ff74d946 100644 ---- a/hw/tpm/tpm_util.c -+++ b/hw/tpm/tpm_util.c -@@ -22,6 +22,17 @@ - #include "qemu/osdep.h" - #include "tpm_util.h" - #include "tpm_int.h" -+#include "tpm_ioctl.h" -+#include "qemu/error-report.h" -+ -+#define DEBUG_TPM 0 -+ -+#define DPRINTF(fmt, ...) do { \ -+ if (DEBUG_TPM) { \ -+ fprintf(stderr, fmt, ## __VA_ARGS__); \ -+ } \ -+} while (0) -+ - - /* - * A basic test of a TPM device. We expect a well formatted response header -@@ -125,3 +136,215 @@ int tpm_util_test_tpmdev(int tpm_fd, TPMVersion *tpm_version) - - return 1; - } -+ -+static void tpm_sized_buffer_reset(TPMSizedBuffer *tsb) -+{ -+ g_free(tsb->buffer); -+ tsb->buffer = NULL; -+ tsb->size = 0; -+} -+ -+/* -+ * Transfer a TPM state blob from the TPM into a provided buffer. -+ * -+ * @fd: file descriptor to talk to the CUSE TPM -+ * @type: the type of blob to transfer -+ * @decrypted_blob: whether we request to receive decrypted blobs -+ * @tsb: the TPMSizeBuffer to fill with the blob -+ * @flags: the flags to return to the caller -+ */ -+static int tpm_util_cuse_get_state_blob(int fd, -+ uint8_t type, -+ bool decrypted_blob, -+ TPMSizedBuffer *tsb, -+ uint32_t *flags) -+{ -+ ptm_getstate pgs; -+ uint16_t offset = 0; -+ ptm_res res; -+ ssize_t n; -+ size_t to_read; -+ -+ tpm_sized_buffer_reset(tsb); -+ -+ pgs.u.req.state_flags = (decrypted_blob) ? PTM_STATE_FLAG_DECRYPTED : 0; -+ pgs.u.req.type = type; -+ pgs.u.req.offset = offset; -+ -+ if (ioctl(fd, PTM_GET_STATEBLOB, &pgs) < 0) { -+ error_report("CUSE TPM PTM_GET_STATEBLOB ioctl failed: %s", -+ strerror(errno)); -+ goto err_exit; -+ } -+ res = pgs.u.resp.tpm_result; -+ if (res != 0 && (res & 0x800) == 0) { -+ error_report("Getting the stateblob (type %d) failed with a TPM " -+ "error 0x%x", type, res); -+ goto err_exit; -+ } -+ -+ *flags = pgs.u.resp.state_flags; -+ -+ tsb->buffer = g_malloc(pgs.u.resp.totlength); -+ memcpy(tsb->buffer, pgs.u.resp.data, pgs.u.resp.length); -+ tsb->size = pgs.u.resp.length; -+ -+ /* if there are bytes left to get use read() interface */ -+ while (tsb->size < pgs.u.resp.totlength) { -+ to_read = pgs.u.resp.totlength - tsb->size; -+ if (unlikely(to_read > SSIZE_MAX)) { -+ to_read = SSIZE_MAX; -+ } -+ -+ n = read(fd, &tsb->buffer[tsb->size], to_read); -+ if (n != to_read) { -+ error_report("Could not read stateblob (type %d) : %s", -+ type, strerror(errno)); -+ goto err_exit; -+ } -+ tsb->size += to_read; -+ } -+ -+ DPRINTF("tpm_util: got state blob type %d, %d bytes, flags 0x%08x, " -+ "decrypted=%d\n", type, tsb->size, *flags, decrypted_blob); -+ -+ return 0; -+ -+err_exit: -+ return 1; -+} -+ -+int tpm_util_cuse_get_state_blobs(int tpm_fd, -+ bool decrypted_blobs, -+ TPMBlobBuffers *tpm_blobs) -+{ -+ if (tpm_util_cuse_get_state_blob(tpm_fd, PTM_BLOB_TYPE_PERMANENT, -+ decrypted_blobs, -+ &tpm_blobs->permanent, -+ &tpm_blobs->permanent_flags) || -+ tpm_util_cuse_get_state_blob(tpm_fd, PTM_BLOB_TYPE_VOLATILE, -+ decrypted_blobs, -+ &tpm_blobs->volatil, -+ &tpm_blobs->volatil_flags) || -+ tpm_util_cuse_get_state_blob(tpm_fd, PTM_BLOB_TYPE_SAVESTATE, -+ decrypted_blobs, -+ &tpm_blobs->savestate, -+ &tpm_blobs->savestate_flags)) { -+ goto err_exit; -+ } -+ -+ return 0; -+ -+ err_exit: -+ tpm_sized_buffer_reset(&tpm_blobs->volatil); -+ tpm_sized_buffer_reset(&tpm_blobs->permanent); -+ tpm_sized_buffer_reset(&tpm_blobs->savestate); -+ -+ return 1; -+} -+ -+static int tpm_util_cuse_do_set_stateblob_ioctl(int fd, -+ uint32_t flags, -+ uint32_t type, -+ uint32_t length) -+{ -+ ptm_setstate pss; -+ -+ pss.u.req.state_flags = flags; -+ pss.u.req.type = type; -+ pss.u.req.length = length; -+ -+ if (ioctl(fd, PTM_SET_STATEBLOB, &pss) < 0) { -+ error_report("CUSE TPM PTM_SET_STATEBLOB ioctl failed: %s", -+ strerror(errno)); -+ return 1; -+ } -+ -+ if (pss.u.resp.tpm_result != 0) { -+ error_report("Setting the stateblob (type %d) failed with a TPM " -+ "error 0x%x", type, pss.u.resp.tpm_result); -+ return 1; -+ } -+ -+ return 0; -+} -+ -+ -+/* -+ * Transfer a TPM state blob to the CUSE TPM. -+ * -+ * @fd: file descriptor to talk to the CUSE TPM -+ * @type: the type of TPM state blob to transfer -+ * @tsb: TPMSizeBuffer containing the TPM state blob -+ * @flags: Flags describing the (encryption) state of the TPM state blob -+ */ -+static int tpm_util_cuse_set_state_blob(int fd, -+ uint32_t type, -+ TPMSizedBuffer *tsb, -+ uint32_t flags) -+{ -+ uint32_t offset = 0; -+ ssize_t n; -+ size_t to_write; -+ -+ /* initiate the transfer to the CUSE TPM */ -+ if (tpm_util_cuse_do_set_stateblob_ioctl(fd, flags, type, 0)) { -+ return 1; -+ } -+ -+ /* use the write() interface for transferring the state blob */ -+ while (offset < tsb->size) { -+ to_write = tsb->size - offset; -+ if (unlikely(to_write > SSIZE_MAX)) { -+ to_write = SSIZE_MAX; -+ } -+ -+ n = write(fd, &tsb->buffer[offset], to_write); -+ if (n != to_write) { -+ error_report("Writing the stateblob (type %d) failed: %s", -+ type, strerror(errno)); -+ goto err_exit; -+ } -+ offset += to_write; -+ } -+ -+ /* inidicate that the transfer is finished */ -+ if (tpm_util_cuse_do_set_stateblob_ioctl(fd, flags, type, 0)) { -+ goto err_exit; -+ } -+ -+ DPRINTF("tpm_util: set the state blob type %d, %d bytes, flags 0x%08x\n", -+ type, tsb->size, flags); -+ -+ return 0; -+ -+err_exit: -+ return 1; -+} -+ -+int tpm_util_cuse_set_state_blobs(int tpm_fd, -+ TPMBlobBuffers *tpm_blobs) -+{ -+ ptm_res res; -+ -+ if (ioctl(tpm_fd, PTM_STOP, &res) < 0) { -+ error_report("tpm_passthrough: Could not stop " -+ "the CUSE TPM: %s (%i)", -+ strerror(errno), errno); -+ return 1; -+ } -+ -+ if (tpm_util_cuse_set_state_blob(tpm_fd, PTM_BLOB_TYPE_PERMANENT, -+ &tpm_blobs->permanent, -+ tpm_blobs->permanent_flags) || -+ tpm_util_cuse_set_state_blob(tpm_fd, PTM_BLOB_TYPE_VOLATILE, -+ &tpm_blobs->volatil, -+ tpm_blobs->volatil_flags) || -+ tpm_util_cuse_set_state_blob(tpm_fd, PTM_BLOB_TYPE_SAVESTATE, -+ &tpm_blobs->savestate, -+ tpm_blobs->savestate_flags)) { -+ return 1; -+ } -+ -+ return 0; -+} -diff --git a/hw/tpm/tpm_util.h b/hw/tpm/tpm_util.h -index df76245e6e..c24071d812 100644 ---- a/hw/tpm/tpm_util.h -+++ b/hw/tpm/tpm_util.h -@@ -26,4 +26,11 @@ - - int tpm_util_test_tpmdev(int tpm_fd, TPMVersion *tpm_version); - -+int tpm_util_cuse_get_state_blobs(int tpm_fd, -+ bool decrypted_blobs, -+ TPMBlobBuffers *tpm_blobs); -+ -+int tpm_util_cuse_set_state_blobs(int tpm_fd, -+ TPMBlobBuffers *tpm_blobs); -+ - #endif /* TPM_TPM_UTIL_H */ -diff --git a/include/sysemu/tpm_backend.h b/include/sysemu/tpm_backend.h -index b58f52d39f..3403821b9d 100644 ---- a/include/sysemu/tpm_backend.h -+++ b/include/sysemu/tpm_backend.h -@@ -62,6 +62,18 @@ typedef struct TPMSizedBuffer { - uint8_t *buffer; - } TPMSizedBuffer; - -+/* blobs from the TPM; part of VM state when migrating */ -+typedef struct TPMBlobBuffers { -+ uint32_t permanent_flags; -+ TPMSizedBuffer permanent; -+ -+ uint32_t volatil_flags; -+ TPMSizedBuffer volatil; -+ -+ uint32_t savestate_flags; -+ TPMSizedBuffer savestate; -+} TPMBlobBuffers; -+ - struct TPMDriverOps { - enum TpmType type; - const QemuOptDesc *opts; --- -2.11.0 - diff --git a/meta/recipes-devtools/qemu/qemu/0004-configure-Add-pkg-config-handling-for-libgcrypt.patch b/meta/recipes-devtools/qemu/qemu/0004-configure-Add-pkg-config-handling-for-libgcrypt.patch new file mode 100644 index 0000000000..f981a64a54 --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/0004-configure-Add-pkg-config-handling-for-libgcrypt.patch @@ -0,0 +1,29 @@ +From d8265abdce5dc2bf74b3fccdf2b7257b4f3894f0 Mon Sep 17 00:00:00 2001 +From: He Zhe <zhe.he@windriver.com> +Date: Wed, 28 Aug 2019 19:56:28 +0800 +Subject: [PATCH 04/12] configure: Add pkg-config handling for libgcrypt + +libgcrypt may also be controlled by pkg-config, this patch adds pkg-config +handling for libgcrypt. + +Upstream-Status: Denied [https://lists.nongnu.org/archive/html/qemu-devel/2019-08/msg06333.html] + +Signed-off-by: He Zhe <zhe.he@windriver.com> + +--- + meson.build | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: qemu-8.1.0/meson.build +=================================================================== +--- qemu-8.1.0.orig/meson.build ++++ qemu-8.1.0/meson.build +@@ -1481,7 +1481,7 @@ endif + if not gnutls_crypto.found() + if (not get_option('gcrypt').auto() or have_system) and not get_option('nettle').enabled() + gcrypt = dependency('libgcrypt', version: '>=1.8', +- method: 'config-tool', ++ method: 'pkg-config', + required: get_option('gcrypt')) + # Debian has removed -lgpg-error from libgcrypt-config + # as it "spreads unnecessary dependencies" which in diff --git a/meta/recipes-devtools/qemu/qemu/0004-linux-user-Rewrite-target_shmat.patch b/meta/recipes-devtools/qemu/qemu/0004-linux-user-Rewrite-target_shmat.patch new file mode 100644 index 0000000000..88c3ed40b0 --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/0004-linux-user-Rewrite-target_shmat.patch @@ -0,0 +1,236 @@ +From cb48d5d1592e63ebd0d4a3e300ef98e38e6306d7 Mon Sep 17 00:00:00 2001 +From: Richard Henderson <richard.henderson@linaro.org> +Date: Wed, 28 Feb 2024 10:25:17 -1000 +Subject: [PATCH 4/5] linux-user: Rewrite target_shmat + +Handle combined host and guest alignment requirements. +Handle host and guest page size differences. +Handle SHM_EXEC. + +Upstream-Status: Submitted [https://www.mail-archive.com/qemu-devel@nongnu.org/msg1026793.html] + +Resolves: https://gitlab.com/qemu-project/qemu/-/issues/115 +Signed-off-by: Richard Henderson <richard.henderson@linaro.org> +Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> +--- + linux-user/mmap.c | 166 +++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 133 insertions(+), 33 deletions(-) + +diff --git a/linux-user/mmap.c b/linux-user/mmap.c +index 18fb3aaf7..6a2f649bb 100644 +--- a/linux-user/mmap.c ++++ b/linux-user/mmap.c +@@ -1062,69 +1062,161 @@ static inline abi_ulong target_shmlba(CPUArchState *cpu_env) + } + #endif + ++#if defined(__arm__) || defined(__mips__) || defined(__sparc__) ++#define HOST_FORCE_SHMLBA 1 ++#else ++#define HOST_FORCE_SHMLBA 0 ++#endif ++ + abi_ulong target_shmat(CPUArchState *cpu_env, int shmid, + abi_ulong shmaddr, int shmflg) + { + CPUState *cpu = env_cpu(cpu_env); +- abi_ulong raddr; + struct shmid_ds shm_info; + int ret; +- abi_ulong shmlba; ++ int h_pagesize; ++ int t_shmlba, h_shmlba, m_shmlba; ++ size_t t_len, h_len, m_len; + + /* shmat pointers are always untagged */ + +- /* find out the length of the shared memory segment */ ++ /* ++ * Because we can't use host shmat() unless the address is sufficiently ++ * aligned for the host, we'll need to check both. ++ * TODO: Could be fixed with softmmu. ++ */ ++ t_shmlba = target_shmlba(cpu_env); ++ h_pagesize = qemu_real_host_page_size(); ++ h_shmlba = (HOST_FORCE_SHMLBA ? SHMLBA : h_pagesize); ++ m_shmlba = MAX(t_shmlba, h_shmlba); ++ ++ if (shmaddr) { ++ if (shmaddr & (m_shmlba - 1)) { ++ if (shmflg & SHM_RND) { ++ /* ++ * The guest is allowing the kernel to round the address. ++ * Assume that the guest is ok with us rounding to the ++ * host required alignment too. Anyway if we don't, we'll ++ * get an error from the kernel. ++ */ ++ shmaddr &= ~(m_shmlba - 1); ++ if (shmaddr == 0 && (shmflg & SHM_REMAP)) { ++ return -TARGET_EINVAL; ++ } ++ } else { ++ int require = TARGET_PAGE_SIZE; ++#ifdef TARGET_FORCE_SHMLBA ++ require = t_shmlba; ++#endif ++ /* ++ * Include host required alignment, as otherwise we cannot ++ * use host shmat at all. ++ */ ++ require = MAX(require, h_shmlba); ++ if (shmaddr & (require - 1)) { ++ return -TARGET_EINVAL; ++ } ++ } ++ } ++ } else { ++ if (shmflg & SHM_REMAP) { ++ return -TARGET_EINVAL; ++ } ++ } ++ /* All rounding now manually concluded. */ ++ shmflg &= ~SHM_RND; ++ ++ /* Find out the length of the shared memory segment. */ + ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info)); + if (is_error(ret)) { + /* can't get length, bail out */ + return ret; + } ++ t_len = TARGET_PAGE_ALIGN(shm_info.shm_segsz); ++ h_len = ROUND_UP(shm_info.shm_segsz, h_pagesize); ++ m_len = MAX(t_len, h_len); + +- shmlba = target_shmlba(cpu_env); +- +- if (shmaddr & (shmlba - 1)) { +- if (shmflg & SHM_RND) { +- shmaddr &= ~(shmlba - 1); +- } else { +- return -TARGET_EINVAL; +- } +- } +- if (!guest_range_valid_untagged(shmaddr, shm_info.shm_segsz)) { ++ if (!guest_range_valid_untagged(shmaddr, m_len)) { + return -TARGET_EINVAL; + } + + WITH_MMAP_LOCK_GUARD() { +- void *host_raddr; ++ bool mapped = false; ++ void *want, *test; + abi_ulong last; + +- if (shmaddr) { +- host_raddr = shmat(shmid, (void *)g2h_untagged(shmaddr), shmflg); ++ if (!shmaddr) { ++ shmaddr = mmap_find_vma(0, m_len, m_shmlba); ++ if (shmaddr == -1) { ++ return -TARGET_ENOMEM; ++ } ++ mapped = !reserved_va; ++ } else if (shmflg & SHM_REMAP) { ++ /* ++ * If host page size > target page size, the host shmat may map ++ * more memory than the guest expects. Reject a mapping that ++ * would replace memory in the unexpected gap. ++ * TODO: Could be fixed with softmmu. ++ */ ++ if (t_len < h_len && ++ !page_check_range_empty(shmaddr + t_len, ++ shmaddr + h_len - 1)) { ++ return -TARGET_EINVAL; ++ } + } else { +- abi_ulong mmap_start; ++ if (!page_check_range_empty(shmaddr, shmaddr + m_len - 1)) { ++ return -TARGET_EINVAL; ++ } ++ } + +- /* In order to use the host shmat, we need to honor host SHMLBA. */ +- mmap_start = mmap_find_vma(0, shm_info.shm_segsz, +- MAX(SHMLBA, shmlba)); ++ /* All placement is now complete. */ ++ want = (void *)g2h_untagged(shmaddr); + +- if (mmap_start == -1) { +- return -TARGET_ENOMEM; ++ /* ++ * Map anonymous pages across the entire range, then remap with ++ * the shared memory. This is required for a number of corner ++ * cases for which host and guest page sizes differ. ++ */ ++ if (h_len != t_len) { ++ int mmap_p = PROT_READ | (shmflg & SHM_RDONLY ? 0 : PROT_WRITE); ++ int mmap_f = MAP_PRIVATE | MAP_ANONYMOUS ++ | (reserved_va || (shmflg & SHM_REMAP) ++ ? MAP_FIXED : MAP_FIXED_NOREPLACE); ++ ++ test = mmap(want, m_len, mmap_p, mmap_f, -1, 0); ++ if (unlikely(test != want)) { ++ /* shmat returns EINVAL not EEXIST like mmap. */ ++ ret = (test == MAP_FAILED && errno != EEXIST ++ ? get_errno(-1) : -TARGET_EINVAL); ++ if (mapped) { ++ do_munmap(want, m_len); ++ } ++ return ret; + } +- host_raddr = shmat(shmid, g2h_untagged(mmap_start), +- shmflg | SHM_REMAP); ++ mapped = true; + } + +- if (host_raddr == (void *)-1) { +- return get_errno(-1); ++ if (reserved_va || mapped) { ++ shmflg |= SHM_REMAP; ++ } ++ test = shmat(shmid, want, shmflg); ++ if (test == MAP_FAILED) { ++ ret = get_errno(-1); ++ if (mapped) { ++ do_munmap(want, m_len); ++ } ++ return ret; + } +- raddr = h2g(host_raddr); +- last = raddr + shm_info.shm_segsz - 1; ++ assert(test == want); + +- page_set_flags(raddr, last, ++ last = shmaddr + m_len - 1; ++ page_set_flags(shmaddr, last, + PAGE_VALID | PAGE_RESET | PAGE_READ | +- (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE)); ++ (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE) | ++ (shmflg & SHM_EXEC ? PAGE_EXEC : 0)); + +- shm_region_rm_complete(raddr, last); +- shm_region_add(raddr, last); ++ shm_region_rm_complete(shmaddr, last); ++ shm_region_add(shmaddr, last); + } + + /* +@@ -1138,7 +1230,15 @@ abi_ulong target_shmat(CPUArchState *cpu_env, int shmid, + tb_flush(cpu); + } + +- return raddr; ++ if (qemu_loglevel_mask(CPU_LOG_PAGE)) { ++ FILE *f = qemu_log_trylock(); ++ if (f) { ++ fprintf(f, "page layout changed following shmat\n"); ++ page_dump(f); ++ qemu_log_unlock(f); ++ } ++ } ++ return shmaddr; + } + + abi_long target_shmdt(abi_ulong shmaddr) +-- +2.34.1 + diff --git a/meta/recipes-devtools/qemu/qemu/0005-qemu-Do-not-include-file-if-not-exists.patch b/meta/recipes-devtools/qemu/qemu/0005-qemu-Do-not-include-file-if-not-exists.patch new file mode 100644 index 0000000000..38aa4c3bbe --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/0005-qemu-Do-not-include-file-if-not-exists.patch @@ -0,0 +1,32 @@ +From f39e7bfc5ed07b5ecaeb705c4eae4855ca120d47 Mon Sep 17 00:00:00 2001 +From: Oleksiy Obitotskyy <oobitots@cisco.com> +Date: Wed, 25 Mar 2020 21:21:35 +0200 +Subject: [PATCH 05/12] qemu: Do not include file if not exists + +Script configure checks for if_alg.h and check failed but +if_alg.h still included. + +Upstream-Status: Submitted [https://lists.gnu.org/archive/html/qemu-devel/2020-03/msg07188.html] +Signed-off-by: Oleksiy Obitotskyy <oobitots@cisco.com> + +[update patch context] +Signed-off-by: Sakib Sajal <sakib.sajal@windriver.com> + +--- + linux-user/syscall.c | 2 ++ + 1 file changed, 2 insertions(+) + +Index: qemu-8.0.0/linux-user/syscall.c +=================================================================== +--- qemu-8.0.0.orig/linux-user/syscall.c ++++ qemu-8.0.0/linux-user/syscall.c +@@ -115,7 +115,9 @@ + #include <linux/blkpg.h> + #include <netpacket/packet.h> + #include <linux/netlink.h> ++#if defined(CONFIG_AF_ALG) + #include <linux/if_alg.h> ++#endif + #include <linux/rtc.h> + #include <sound/asound.h> + #ifdef HAVE_BTRFS_H diff --git a/meta/recipes-devtools/qemu/qemu/0005-tests-tcg-Check-that-shmat-does-not-break-proc-self-.patch b/meta/recipes-devtools/qemu/qemu/0005-tests-tcg-Check-that-shmat-does-not-break-proc-self-.patch new file mode 100644 index 0000000000..5afb35ea0c --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/0005-tests-tcg-Check-that-shmat-does-not-break-proc-self-.patch @@ -0,0 +1,85 @@ +From 1234063488134ad1f541f56dd30caa7896905f06 Mon Sep 17 00:00:00 2001 +From: Ilya Leoshkevich <iii@linux.ibm.com> +Date: Wed, 28 Feb 2024 10:25:18 -1000 +Subject: [PATCH 5/5] tests/tcg: Check that shmat() does not break + /proc/self/maps + +Add a regression test for a recently fixed issue, where shmat() +desynced the guest and the host view of the address space and caused +open("/proc/self/maps") to SEGV. + +Upstream-Status: Submitted [https://www.mail-archive.com/qemu-devel@nongnu.org/msg1026793.html] + +Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> +Message-Id: <jwyuvao4apydvykmsnvacwshdgy3ixv7qvkh4dbxm3jkwgnttw@k4wpaayou7oq> +Signed-off-by: Richard Henderson <richard.henderson@linaro.org> +Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> +--- + tests/tcg/multiarch/linux/linux-shmat-maps.c | 55 ++++++++++++++++++++ + 1 file changed, 55 insertions(+) + create mode 100644 tests/tcg/multiarch/linux/linux-shmat-maps.c + +diff --git a/tests/tcg/multiarch/linux/linux-shmat-maps.c b/tests/tcg/multiarch/linux/linux-shmat-maps.c +new file mode 100644 +index 000000000..0ccf7a973 +--- /dev/null ++++ b/tests/tcg/multiarch/linux/linux-shmat-maps.c +@@ -0,0 +1,55 @@ ++/* ++ * Test that shmat() does not break /proc/self/maps. ++ * ++ * SPDX-License-Identifier: GPL-2.0-or-later ++ */ ++#include <assert.h> ++#include <fcntl.h> ++#include <stdlib.h> ++#include <sys/ipc.h> ++#include <sys/shm.h> ++#include <unistd.h> ++ ++int main(void) ++{ ++ char buf[128]; ++ int err, fd; ++ int shmid; ++ ssize_t n; ++ void *p; ++ ++ shmid = shmget(IPC_PRIVATE, 1, IPC_CREAT | 0600); ++ assert(shmid != -1); ++ ++ /* ++ * The original bug required a non-NULL address, which skipped the ++ * mmap_find_vma step, which could result in a host mapping smaller ++ * than the target mapping. Choose an address at random. ++ */ ++ p = shmat(shmid, (void *)0x800000, SHM_RND); ++ if (p == (void *)-1) { ++ /* ++ * Because we are now running the testcase for all guests for which ++ * we have a cross-compiler, the above random address might conflict ++ * with the guest executable in some way. Rather than stopping, ++ * continue with a system supplied address, which should never fail. ++ */ ++ p = shmat(shmid, NULL, 0); ++ assert(p != (void *)-1); ++ } ++ ++ fd = open("/proc/self/maps", O_RDONLY); ++ assert(fd != -1); ++ do { ++ n = read(fd, buf, sizeof(buf)); ++ assert(n >= 0); ++ } while (n != 0); ++ close(fd); ++ ++ err = shmdt(p); ++ assert(err == 0); ++ err = shmctl(shmid, IPC_RMID, NULL); ++ assert(err == 0); ++ ++ return EXIT_SUCCESS; ++} +-- +2.34.1 + diff --git a/meta/recipes-devtools/qemu/qemu/0006-qemu-Add-some-user-space-mmap-tweaks-to-address-musl.patch b/meta/recipes-devtools/qemu/qemu/0006-qemu-Add-some-user-space-mmap-tweaks-to-address-musl.patch new file mode 100644 index 0000000000..5d1d7c6881 --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/0006-qemu-Add-some-user-space-mmap-tweaks-to-address-musl.patch @@ -0,0 +1,49 @@ +From 375cae3dd6151ef33cae8f243f6a2c2da6c0c356 Mon Sep 17 00:00:00 2001 +From: Richard Purdie <richard.purdie@linuxfoundation.org> +Date: Fri, 8 Jan 2021 17:27:06 +0000 +Subject: [PATCH 06/12] qemu: Add some user space mmap tweaks to address musl + 32 bit + +When using qemu-i386 to build qemux86 webkitgtk on musl, it sits in an +infinite loop of mremap calls of ever decreasing/increasing addresses. + +I suspect something in the musl memory allocation code loops indefinitely +if it only sees ENOMEM and only exits when it hits EFAULT. + +According to the docs, trying to mremap outside the address space +can/should return EFAULT and changing this allows the build to succeed. + +A better return value for the other cases of invalid addresses is EINVAL +rather than ENOMEM so adjust the other part of the test to this. + +Upstream-Status: Submitted [https://lists.gnu.org/archive/html/qemu-devel/2021-01/msg01355.html] +Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org + +--- + linux-user/mmap.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +Index: qemu-8.0.0/linux-user/mmap.c +=================================================================== +--- qemu-8.0.0.orig/linux-user/mmap.c ++++ qemu-8.0.0/linux-user/mmap.c +@@ -776,12 +776,16 @@ abi_long target_mremap(abi_ulong old_add + int prot; + void *host_addr; + +- if (!guest_range_valid_untagged(old_addr, old_size) || +- ((flags & MREMAP_FIXED) && ++ if (!guest_range_valid_untagged(old_addr, old_size)) { ++ errno = EFAULT; ++ return -1; ++ } ++ ++ if (((flags & MREMAP_FIXED) && + !guest_range_valid_untagged(new_addr, new_size)) || + ((flags & MREMAP_MAYMOVE) == 0 && + !guest_range_valid_untagged(old_addr, new_size))) { +- errno = ENOMEM; ++ errno = EINVAL; + return -1; + } + diff --git a/meta/recipes-devtools/qemu/qemu/0007-qemu-Determinism-fixes.patch b/meta/recipes-devtools/qemu/qemu/0007-qemu-Determinism-fixes.patch new file mode 100644 index 0000000000..d3f965e070 --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/0007-qemu-Determinism-fixes.patch @@ -0,0 +1,31 @@ +From 50bab5c2605b609ea7ea154f57a9be96d656725a Mon Sep 17 00:00:00 2001 +From: Richard Purdie <richard.purdie@linuxfoundation.org> +Date: Mon, 1 Mar 2021 13:00:47 +0000 +Subject: [PATCH 07/12] qemu: Determinism fixes + +When sources are included within debug information, a couple of areas of the +qemu build are not reproducible due to either full buildpaths or timestamps. + +Replace the full paths with relative ones. I couldn't figure out how to get +meson to pass relative paths but we can fix that in the script. + +Upstream-Status: Pending [some version of all/part of this may be accepted] +RP 2021/3/1 + +--- + scripts/decodetree.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +Index: qemu-8.0.0/scripts/decodetree.py +=================================================================== +--- qemu-8.0.0.orig/scripts/decodetree.py ++++ qemu-8.0.0/scripts/decodetree.py +@@ -1328,7 +1328,7 @@ def main(): + toppat = ExcMultiPattern(0) + + for filename in args: +- input_file = filename ++ input_file = os.path.relpath(filename) + f = open(filename, 'rt', encoding='utf-8') + parse_file(f, toppat) + f.close() diff --git a/meta/recipes-devtools/qemu/qemu/0008-tests-meson.build-use-relative-path-to-refer-to-file.patch b/meta/recipes-devtools/qemu/qemu/0008-tests-meson.build-use-relative-path-to-refer-to-file.patch new file mode 100644 index 0000000000..a84364ccc1 --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/0008-tests-meson.build-use-relative-path-to-refer-to-file.patch @@ -0,0 +1,41 @@ +From 2bf9388b801d4389e2d57e95a7897bfc1c42786e Mon Sep 17 00:00:00 2001 +From: Changqing Li <changqing.li@windriver.com> +Date: Thu, 14 Jan 2021 06:33:04 +0000 +Subject: [PATCH 08/12] tests/meson.build: use relative path to refer to files + +Fix error like: +Fatal error: can't create tests/ptimer-test.p/..._qemu-5.2.0_hw_core_ptimer.c.o: File name too long + +when build path is too long, use meson.source_root() will make this +filename too long. Fixed by using relative path to refer to files + +Upstream-Status: Submitted [send to qemu-devel] + +Signed-off-by: Changqing Li <changqing.li@windriver.com> + +--- + tests/unit/meson.build | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +Index: qemu-8.0.0/tests/unit/meson.build +=================================================================== +--- qemu-8.0.0.orig/tests/unit/meson.build ++++ qemu-8.0.0/tests/unit/meson.build +@@ -46,7 +46,7 @@ tests = { + 'test-keyval': [testqapi], + 'test-logging': [], + 'test-uuid': [], +- 'ptimer-test': ['ptimer-test-stubs.c', meson.project_source_root() / 'hw/core/ptimer.c'], ++ 'ptimer-test': ['ptimer-test-stubs.c', '../../hw/core/ptimer.c'], + 'test-qapi-util': [], + 'test-interval-tree': [], + 'test-xs-node': [qom], +@@ -136,7 +136,7 @@ if have_system + 'test-util-sockets': ['socket-helpers.c'], + 'test-base64': [], + 'test-bufferiszero': [], +- 'test-smp-parse': [qom, meson.project_source_root() / 'hw/core/machine-smp.c'], ++ 'test-smp-parse': [qom, '../../hw/core/machine-smp.c'], + 'test-vmstate': [migration, io], + 'test-yank': ['socket-helpers.c', qom, io, chardev] + } diff --git a/meta/recipes-devtools/qemu/qemu/0009-Define-MAP_SYNC-and-MAP_SHARED_VALIDATE-on-needed-li.patch b/meta/recipes-devtools/qemu/qemu/0009-Define-MAP_SYNC-and-MAP_SHARED_VALIDATE-on-needed-li.patch new file mode 100644 index 0000000000..4de6cc2445 --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/0009-Define-MAP_SYNC-and-MAP_SHARED_VALIDATE-on-needed-li.patch @@ -0,0 +1,46 @@ +From ebf4bb2f51da83af0c61480414cfa156f7308b34 Mon Sep 17 00:00:00 2001 +From: Khem Raj <raj.khem@gmail.com> +Date: Mon, 21 Mar 2022 10:09:38 -0700 +Subject: [PATCH 09/12] Define MAP_SYNC and MAP_SHARED_VALIDATE on needed linux + systems + +linux only wires MAP_SYNC and MAP_SHARED_VALIDATE for architectures +which include asm-generic/mman.h and mips/powerpc are not including this +file in linux/mman.h, therefore these should be defined for such +architectures on Linux as well. This fixes build on mips/musl/linux + +Upstream-Status: Submitted [https://lists.nongnu.org/archive/html/qemu-devel/2022-03/msg05298.html] +Signed-off-by: Khem Raj <raj.khem@gmail.com> +Cc: Zhang Yi <yi.z.zhang@linux.intel.com> +Cc: Michael S. Tsirkin <mst@redhat.com> + +--- + util/mmap-alloc.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +Index: qemu-8.0.0/util/mmap-alloc.c +=================================================================== +--- qemu-8.0.0.orig/util/mmap-alloc.c ++++ qemu-8.0.0/util/mmap-alloc.c +@@ -10,14 +10,18 @@ + * later. See the COPYING file in the top-level directory. + */ + ++#include "qemu/osdep.h" + #ifdef CONFIG_LINUX + #include <linux/mman.h> +-#else /* !CONFIG_LINUX */ ++#endif /* CONFIG_LINUX */ ++ ++#ifndef MAP_SYNC + #define MAP_SYNC 0x0 ++#endif /* MAP_SYNC */ ++#ifndef MAP_SHARED_VALIDATE + #define MAP_SHARED_VALIDATE 0x0 +-#endif /* CONFIG_LINUX */ ++#endif /* MAP_SHARED_VALIDATE */ + +-#include "qemu/osdep.h" + #include "qemu/mmap-alloc.h" + #include "qemu/host-utils.h" + #include "qemu/cutils.h" diff --git a/meta/recipes-devtools/qemu/qemu/0010-hw-pvrdma-Protect-against-buggy-or-malicious-guest-d.patch b/meta/recipes-devtools/qemu/qemu/0010-hw-pvrdma-Protect-against-buggy-or-malicious-guest-d.patch new file mode 100644 index 0000000000..6caf35b634 --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/0010-hw-pvrdma-Protect-against-buggy-or-malicious-guest-d.patch @@ -0,0 +1,40 @@ +CVE: CVE-2022-1050 +Upstream-Status: Submitted [https://lore.kernel.org/qemu-devel/20220403095234.2210-1-yuval.shaia.ml@gmail.com/] +Signed-off-by: Ross Burton <ross.burton@arm.com> + +From dbdef95c272e8f3ec037c3db4197c66002e30995 Mon Sep 17 00:00:00 2001 +From: Yuval Shaia <yuval.shaia.ml@gmail.com> +Date: Sun, 3 Apr 2022 12:52:34 +0300 +Subject: [PATCH] hw/pvrdma: Protect against buggy or malicious guest driver + +Guest driver might execute HW commands when shared buffers are not yet +allocated. +This could happen on purpose (malicious guest) or because of some other +guest/host address mapping error. +We need to protect againts such case. + +Fixes: CVE-2022-1050 + +Reported-by: Raven <wxhusst@gmail.com> +Signed-off-by: Yuval Shaia <yuval.shaia.ml@gmail.com> +--- + hw/rdma/vmw/pvrdma_cmd.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +Index: qemu-8.0.0/hw/rdma/vmw/pvrdma_cmd.c +=================================================================== +--- qemu-8.0.0.orig/hw/rdma/vmw/pvrdma_cmd.c ++++ qemu-8.0.0/hw/rdma/vmw/pvrdma_cmd.c +@@ -782,6 +782,12 @@ int pvrdma_exec_cmd(PVRDMADev *dev) + goto out; + } + ++ if (!dsr_info->dsr) { ++ /* Buggy or malicious guest driver */ ++ rdma_error_report("Exec command without dsr, req or rsp buffers"); ++ goto out; ++ } ++ + if (dsr_info->req->hdr.cmd >= sizeof(cmd_handlers) / + sizeof(struct cmd_handler)) { + rdma_error_report("Unsupported command"); diff --git a/meta/recipes-devtools/qemu/qemu/0011-linux-user-workaround-for-missing-MAP_FIXED_NOREPLAC.patch b/meta/recipes-devtools/qemu/qemu/0011-linux-user-workaround-for-missing-MAP_FIXED_NOREPLAC.patch new file mode 100644 index 0000000000..cc53b1eedd --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/0011-linux-user-workaround-for-missing-MAP_FIXED_NOREPLAC.patch @@ -0,0 +1,282 @@ +From fa9bcabe2387bb230ef82d62827ad6f93b8a1e61 Mon Sep 17 00:00:00 2001 +From: Frederic Konrad <fkonrad@amd.com> +Date: Wed, 17 Jan 2024 18:15:06 +0000 +Subject: [PATCH 1/2] linux-user/*: workaround for missing MAP_FIXED_NOREPLACE + +QEMU v8.1.0 recently requires MAP_FIXED_NOREPLACE flags implementation for mmap. + +This is missing from ubuntu 18.04, thus this patch catches the mmap calls which +could use that new flag and forwards them to mmap when MAP_FIXED_NOREPLACE +flag isn't set or emulates them by checking the returned address w.r.t the +requested address. + +Signed-off-by: Frederic Konrad <fkonrad@amd.com> +Signed-off-by: Francisco Iglesias <francisco.iglesias@amd.com> + +Upstream-Status: Inappropriate [OE specific] + +The upstream only supports the last two major releases of an OS. The ones +they have declared all have kernel 4.17 or newer. + +See: +https://xilinx.slack.com/archives/D04G2647CTV/p1705074697942019 + +https://www.qemu.org/docs/master/about/build-platforms.html + + The project aims to support the most recent major version at all times for up + to five years after its initial release. Support for the previous major + version will be dropped 2 years after the new major version is released or + when the vendor itself drops support, whichever comes first. + +Signed-off-by: Mark Hatle <mark.hatle@amd.com> +--- + linux-user/elfload.c | 7 +++-- + linux-user/meson.build | 1 + + linux-user/mmap-fixed.c | 63 +++++++++++++++++++++++++++++++++++++++++ + linux-user/mmap-fixed.h | 39 +++++++++++++++++++++++++ + linux-user/mmap.c | 31 +++++++++++--------- + linux-user/syscall.c | 1 + + 6 files changed, 125 insertions(+), 17 deletions(-) + create mode 100644 linux-user/mmap-fixed.c + create mode 100644 linux-user/mmap-fixed.h + +Index: qemu-8.2.1/linux-user/elfload.c +=================================================================== +--- qemu-8.2.1.orig/linux-user/elfload.c ++++ qemu-8.2.1/linux-user/elfload.c +@@ -22,6 +22,7 @@ + #include "qemu/error-report.h" + #include "target_signal.h" + #include "accel/tcg/debuginfo.h" ++#include "mmap-fixed.h" + + #ifdef TARGET_ARM + #include "target/arm/cpu-features.h" +@@ -2765,9 +2766,9 @@ static abi_ulong create_elf_tables(abi_u + static int pgb_try_mmap(uintptr_t addr, uintptr_t addr_last, bool keep) + { + size_t size = addr_last - addr + 1; +- void *p = mmap((void *)addr, size, PROT_NONE, +- MAP_ANONYMOUS | MAP_PRIVATE | +- MAP_NORESERVE | MAP_FIXED_NOREPLACE, -1, 0); ++ void *p = mmap_fixed_noreplace((void *)addr, size, PROT_NONE, ++ MAP_ANONYMOUS | MAP_PRIVATE | ++ MAP_NORESERVE | MAP_FIXED_NOREPLACE, -1, 0); + int ret; + + if (p == MAP_FAILED) { +Index: qemu-8.2.1/linux-user/meson.build +=================================================================== +--- qemu-8.2.1.orig/linux-user/meson.build ++++ qemu-8.2.1/linux-user/meson.build +@@ -14,6 +14,7 @@ linux_user_ss.add(files( + 'linuxload.c', + 'main.c', + 'mmap.c', ++ 'mmap-fixed.c', + 'signal.c', + 'strace.c', + 'syscall.c', +Index: qemu-8.2.1/linux-user/mmap-fixed.c +=================================================================== +--- /dev/null ++++ qemu-8.2.1/linux-user/mmap-fixed.c +@@ -0,0 +1,63 @@ ++/* ++ * Workaround for MAP_FIXED_NOREPLACE ++ * ++ * Copyright (c) 2024, Advanced Micro Devices, Inc. ++ * Developed by Fred Konrad <fkonrad@amd.com> ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++ ++#include <sys/mman.h> ++#include <errno.h> ++ ++#ifndef MAP_FIXED_NOREPLACE ++#include "mmap-fixed.h" ++ ++void *mmap_fixed_noreplace(void *addr, size_t len, int prot, int flags, ++ int fd, off_t offset) ++{ ++ void *retaddr; ++ ++ if (!(flags & MAP_FIXED_NOREPLACE)) { ++ /* General case, use the regular mmap. */ ++ return mmap(addr, len, prot, flags, fd, offset); ++ } ++ ++ /* Since MAP_FIXED_NOREPLACE is not implemented, try to emulate it. */ ++ flags = flags & ~(MAP_FIXED_NOREPLACE | MAP_FIXED); ++ retaddr = mmap(addr, len, prot, flags, fd, offset); ++ if ((retaddr == addr) || (retaddr == MAP_FAILED)) { ++ /* ++ * Either the map worked and we get the good address so it can be ++ * returned, or it failed and would have failed the same with ++ * MAP_FIXED*, in which case return MAP_FAILED. ++ */ ++ return retaddr; ++ } else { ++ /* ++ * Page has been mapped but not at the requested address.. unmap it and ++ * return EEXIST. ++ */ ++ munmap(retaddr, len); ++ errno = EEXIST; ++ return MAP_FAILED; ++ } ++} ++ ++#endif +Index: qemu-8.2.1/linux-user/mmap-fixed.h +=================================================================== +--- /dev/null ++++ qemu-8.2.1/linux-user/mmap-fixed.h +@@ -0,0 +1,39 @@ ++/* ++ * Workaround for MAP_FIXED_NOREPLACE ++ * ++ * Copyright (c) 2024, Advanced Micro Devices, Inc. ++ * Developed by Fred Konrad <fkonrad@amd.com> ++ * ++ * Permission is hereby granted, free of charge, to any person obtaining a copy ++ * of this software and associated documentation files (the "Software"), to deal ++ * in the Software without restriction, including without limitation the rights ++ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell ++ * copies of the Software, and to permit persons to whom the Software is ++ * furnished to do so, subject to the following conditions: ++ * ++ * The above copyright notice and this permission notice shall be included in ++ * all copies or substantial portions of the Software. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ++ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ++ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ++ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER ++ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, ++ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ++ * THE SOFTWARE. ++ */ ++ ++#ifndef MMAP_FIXED_H ++#define MMAP_FIXED_H ++ ++#ifndef MAP_FIXED_NOREPLACE ++#define MAP_FIXED_NOREPLACE 0x100000 ++ ++void *mmap_fixed_noreplace(void *addr, size_t len, int prot, int flags, ++ int fd, off_t offset); ++ ++#else /* MAP_FIXED_NOREPLACE */ ++#define mmap_fixed_noreplace mmap ++#endif /* MAP_FIXED_NOREPLACE */ ++ ++#endif /* MMAP_FIXED_H */ +Index: qemu-8.2.1/linux-user/mmap.c +=================================================================== +--- qemu-8.2.1.orig/linux-user/mmap.c ++++ qemu-8.2.1/linux-user/mmap.c +@@ -25,6 +25,7 @@ + #include "user-mmap.h" + #include "target_mman.h" + #include "qemu/interval-tree.h" ++#include "mmap-fixed.h" + + #ifdef TARGET_ARM + #include "target/arm/cpu-features.h" +@@ -273,7 +274,7 @@ int target_mprotect(abi_ulong start, abi + static int do_munmap(void *addr, size_t len) + { + if (reserved_va) { +- void *ptr = mmap(addr, len, PROT_NONE, ++ void *ptr = mmap_fixed_noreplace(addr, len, PROT_NONE, + MAP_FIXED | MAP_ANONYMOUS + | MAP_PRIVATE | MAP_NORESERVE, -1, 0); + return ptr == addr ? 0 : -1; +@@ -319,9 +320,9 @@ static bool mmap_frag(abi_ulong real_sta + * outside of the fragment we need to map. Allocate a new host + * page to cover, discarding whatever else may have been present. + */ +- void *p = mmap(host_start, qemu_host_page_size, +- target_to_host_prot(prot), +- flags | MAP_ANONYMOUS, -1, 0); ++ void *p = mmap_fixed_noreplace(host_start, qemu_host_page_size, ++ target_to_host_prot(prot), ++ flags | MAP_ANONYMOUS, -1, 0); + if (p != host_start) { + if (p != MAP_FAILED) { + munmap(p, qemu_host_page_size); +@@ -420,8 +421,9 @@ abi_ulong mmap_find_vma(abi_ulong start, + * - mremap() with MREMAP_FIXED flag + * - shmat() with SHM_REMAP flag + */ +- ptr = mmap(g2h_untagged(addr), size, PROT_NONE, +- MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0); ++ ptr = mmap_fixed_noreplace(g2h_untagged(addr), size, PROT_NONE, ++ MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, ++ -1, 0); + + /* ENOMEM, if host address space has no memory */ + if (ptr == MAP_FAILED) { +@@ -615,16 +617,16 @@ abi_long target_mmap(abi_ulong start, ab + * especially important if qemu_host_page_size > + * qemu_real_host_page_size. + */ +- p = mmap(g2h_untagged(start), host_len, host_prot, +- flags | MAP_FIXED | MAP_ANONYMOUS, -1, 0); ++ p = mmap_fixed_noreplace(g2h_untagged(start), host_len, host_prot, ++ flags | MAP_FIXED | MAP_ANONYMOUS, -1, 0); + if (p == MAP_FAILED) { + goto fail; + } + /* update start so that it points to the file position at 'offset' */ + host_start = (uintptr_t)p; + if (!(flags & MAP_ANONYMOUS)) { +- p = mmap(g2h_untagged(start), len, host_prot, +- flags | MAP_FIXED, fd, host_offset); ++ p = mmap_fixed_noreplace(g2h_untagged(start), len, host_prot, ++ flags | MAP_FIXED, fd, host_offset); + if (p == MAP_FAILED) { + munmap(g2h_untagged(start), host_len); + goto fail; +@@ -749,8 +751,9 @@ abi_long target_mmap(abi_ulong start, ab + len1 = real_last - real_start + 1; + want_p = g2h_untagged(real_start); + +- p = mmap(want_p, len1, target_to_host_prot(target_prot), +- flags, fd, offset1); ++ p = mmap_fixed_noreplace(want_p, len1, ++ target_to_host_prot(target_prot), ++ flags, fd, offset1); + if (p != want_p) { + if (p != MAP_FAILED) { + munmap(p, len1); +Index: qemu-8.2.1/linux-user/syscall.c +=================================================================== +--- qemu-8.2.1.orig/linux-user/syscall.c ++++ qemu-8.2.1/linux-user/syscall.c +@@ -145,6 +145,7 @@ + #include "qapi/error.h" + #include "fd-trans.h" + #include "cpu_loop-common.h" ++#include "mmap-fixed.h" + + #ifndef CLONE_IO + #define CLONE_IO 0x80000000 /* Clone io context */ diff --git a/meta/recipes-devtools/qemu/qemu/0012-linux-user-workaround-for-missing-MAP_SHARED_VALIDAT.patch b/meta/recipes-devtools/qemu/qemu/0012-linux-user-workaround-for-missing-MAP_SHARED_VALIDAT.patch new file mode 100644 index 0000000000..48034a4680 --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/0012-linux-user-workaround-for-missing-MAP_SHARED_VALIDAT.patch @@ -0,0 +1,51 @@ +From 5c73e53997df800a742f9cd7355f3045861984bb Mon Sep 17 00:00:00 2001 +From: Frederic Konrad <fkonrad@amd.com> +Date: Thu, 18 Jan 2024 10:43:44 +0000 +Subject: [PATCH 2/2] linux-user/*: workaround for missing MAP_SHARED_VALIDATE + +QEMU v8.1.0 recently requires MAP_SHARED_VALIDATE flags implementation for mmap. + +This is missing from the Ubuntu 18.04 compiler but looks like to be in the +kernel source. + +Signed-off-by: Frederic Konrad <fkonrad@amd.com> +Signed-off-by: Francisco Iglesias <francisco.iglesias@amd.com> + +Upstream-Status: Inappropriate [OE specific] + +The upstream only supports the last two major releases of an OS. The ones +they have declared all have kernel 4.17 or newer. + +See: +https://xilinx.slack.com/archives/D04G2647CTV/p1705074697942019 + +https://www.qemu.org/docs/master/about/build-platforms.html + + The project aims to support the most recent major version at all times for up + to five years after its initial release. Support for the previous major + version will be dropped 2 years after the new major version is released or + when the vendor itself drops support, whichever comes first. + +Signed-off-by: Mark Hatle <mark.hatle@amd.com> +--- + linux-user/mmap-fixed.h | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/linux-user/mmap-fixed.h b/linux-user/mmap-fixed.h +index ef6eef5114..ec86586c1f 100644 +--- a/linux-user/mmap-fixed.h ++++ b/linux-user/mmap-fixed.h +@@ -26,6 +26,10 @@ + #ifndef MMAP_FIXED_H + #define MMAP_FIXED_H + ++#ifndef MAP_SHARED_VALIDATE ++#define MAP_SHARED_VALIDATE 0x03 ++#endif ++ + #ifndef MAP_FIXED_NOREPLACE + #define MAP_FIXED_NOREPLACE 0x100000 + +-- +2.34.1 + diff --git a/meta/recipes-devtools/qemu/qemu/4a8579ad8629b57a43daa62e46cc7af6e1078116.patch b/meta/recipes-devtools/qemu/qemu/4a8579ad8629b57a43daa62e46cc7af6e1078116.patch new file mode 100644 index 0000000000..5ad859ebe6 --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/4a8579ad8629b57a43daa62e46cc7af6e1078116.patch @@ -0,0 +1,60 @@ +From 4a8579ad8629b57a43daa62e46cc7af6e1078116 Mon Sep 17 00:00:00 2001 +From: Richard Henderson <richard.henderson@linaro.org> +Date: Tue, 13 Feb 2024 10:20:27 -1000 +Subject: [PATCH] linux-user: Split out do_munmap +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Upstream-Status: Submitted [https://gitlab.com/rth7680/qemu/-/commit/4a8579ad8629b57a43daa62e46cc7af6e1078116] + +Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> +Signed-off-by: Richard Henderson <richard.henderson@linaro.org> +--- + linux-user/mmap.c | 23 ++++++++++++++++------- + 1 file changed, 16 insertions(+), 7 deletions(-) + +diff --git a/linux-user/mmap.c b/linux-user/mmap.c +index 1bbfeb25b14..8ebcca44444 100644 +--- a/linux-user/mmap.c ++++ b/linux-user/mmap.c +@@ -267,6 +267,21 @@ int target_mprotect(abi_ulong start, abi_ulong len, int target_prot) + return ret; + } + ++/* ++ * Perform munmap on behalf of the target, with host parameters. ++ * If reserved_va, we must replace the memory reservation. ++ */ ++static int do_munmap(void *addr, size_t len) ++{ ++ if (reserved_va) { ++ void *ptr = mmap(addr, len, PROT_NONE, ++ MAP_FIXED | MAP_ANONYMOUS ++ | MAP_PRIVATE | MAP_NORESERVE, -1, 0); ++ return ptr == addr ? 0 : -1; ++ } ++ return munmap(addr, len); ++} ++ + /* map an incomplete host page */ + static bool mmap_frag(abi_ulong real_start, abi_ulong start, abi_ulong last, + int prot, int flags, int fd, off_t offset) +@@ -854,13 +869,7 @@ static int mmap_reserve_or_unmap(abi_ulong start, abi_ulong len) + real_len = real_last - real_start + 1; + host_start = g2h_untagged(real_start); + +- if (reserved_va) { +- void *ptr = mmap(host_start, real_len, PROT_NONE, +- MAP_FIXED | MAP_ANONYMOUS +- | MAP_PRIVATE | MAP_NORESERVE, -1, 0); +- return ptr == host_start ? 0 : -1; +- } +- return munmap(host_start, real_len); ++ return do_munmap(host_start, real_len); + } + + int target_munmap(abi_ulong start, abi_ulong len) +-- +GitLab + diff --git a/meta/recipes-devtools/qemu/qemu/CVE-2023-6683.patch b/meta/recipes-devtools/qemu/qemu/CVE-2023-6683.patch new file mode 100644 index 0000000000..732cb6af18 --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/CVE-2023-6683.patch @@ -0,0 +1,91 @@ +From 405484b29f6548c7b86549b0f961b906337aa68a Mon Sep 17 00:00:00 2001 +From: Fiona Ebner <f.ebner@proxmox.com> +Date: Wed, 24 Jan 2024 11:57:48 +0100 +Subject: [PATCH] ui/clipboard: mark type as not available when there is no + data +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +With VNC, a client can send a non-extended VNC_MSG_CLIENT_CUT_TEXT +message with len=0. In qemu_clipboard_set_data(), the clipboard info +will be updated setting data to NULL (because g_memdup(data, size) +returns NULL when size is 0). If the client does not set the +VNC_ENCODING_CLIPBOARD_EXT feature when setting up the encodings, then +the 'request' callback for the clipboard peer is not initialized. +Later, because data is NULL, qemu_clipboard_request() can be reached +via vdagent_chr_write() and vdagent_clipboard_recv_request() and +there, the clipboard owner's 'request' callback will be attempted to +be called, but that is a NULL pointer. + +In particular, this can happen when using the KRDC (22.12.3) VNC +client. + +Another scenario leading to the same issue is with two clients (say +noVNC and KRDC): + +The noVNC client sets the extension VNC_FEATURE_CLIPBOARD_EXT and +initializes its cbpeer. + +The KRDC client does not, but triggers a vnc_client_cut_text() (note +it's not the _ext variant)). There, a new clipboard info with it as +the 'owner' is created and via qemu_clipboard_set_data() is called, +which in turn calls qemu_clipboard_update() with that info. + +In qemu_clipboard_update(), the notifier for the noVNC client will be +called, i.e. vnc_clipboard_notify() and also set vs->cbinfo for the +noVNC client. The 'owner' in that clipboard info is the clipboard peer +for the KRDC client, which did not initialize the 'request' function. +That sounds correct to me, it is the owner of that clipboard info. + +Then when noVNC sends a VNC_MSG_CLIENT_CUT_TEXT message (it did set +the VNC_FEATURE_CLIPBOARD_EXT feature correctly, so a check for it +passes), that clipboard info is passed to qemu_clipboard_request() and +the original segfault still happens. + +Fix the issue by handling updates with size 0 differently. In +particular, mark in the clipboard info that the type is not available. + +While at it, switch to g_memdup2(), because g_memdup() is deprecated. + +Cc: qemu-stable@nongnu.org +Fixes: CVE-2023-6683 +Reported-by: Markus Frank <m.frank@proxmox.com> +Suggested-by: Marc-André Lureau <marcandre.lureau@redhat.com> +Signed-off-by: Fiona Ebner <f.ebner@proxmox.com> +Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> +Tested-by: Markus Frank <m.frank@proxmox.com> +Message-ID: <20240124105749.204610-1-f.ebner@proxmox.com> + +CVE: CVE-2023-6683 + +Upstream-Status: Backport [https://github.com/qemu/qemu/commit/405484b29f6548c7b86549b0f961b906337aa68a] +Signed-off-by: Simone Weiß <simone.p.weiss@posteo.com> + +--- + ui/clipboard.c | 12 +++++++++--- + 1 file changed, 9 insertions(+), 3 deletions(-) + +diff --git a/ui/clipboard.c b/ui/clipboard.c +index 3d14bffaf80f..b3f6fa3c9e1f 100644 +--- a/ui/clipboard.c ++++ b/ui/clipboard.c +@@ -163,9 +163,15 @@ void qemu_clipboard_set_data(QemuClipboardPeer *peer, + } + + g_free(info->types[type].data); +- info->types[type].data = g_memdup(data, size); +- info->types[type].size = size; +- info->types[type].available = true; ++ if (size) { ++ info->types[type].data = g_memdup2(data, size); ++ info->types[type].size = size; ++ info->types[type].available = true; ++ } else { ++ info->types[type].data = NULL; ++ info->types[type].size = 0; ++ info->types[type].available = false; ++ } + + if (update) { + qemu_clipboard_update(info); diff --git a/meta/recipes-devtools/qemu/qemu/add-ptest-in-makefile-v10.patch b/meta/recipes-devtools/qemu/qemu/add-ptest-in-makefile-v10.patch deleted file mode 100644 index e9639820be..0000000000 --- a/meta/recipes-devtools/qemu/qemu/add-ptest-in-makefile-v10.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 4201a5791fc4798a45a9b9f881602d7bacb74ed1 Mon Sep 17 00:00:00 2001 -From: Juro Bystricky <juro.bystricky@intel.com> -Date: Thu, 31 Aug 2017 11:06:56 -0700 -Subject: Add subpackage -ptest which runs all unit test cases for qemu. - -Upstream-Status: Pending - -Signed-off-by: Kai Kang <kai.kang@windriver.com> - -Signed-off-by: Juro Bystricky <juro.bystricky@intel.com> - -diff --git a/tests/Makefile.include b/tests/Makefile.include -index f08b741..3d1b3e9 100644 ---- a/tests/Makefile.include -+++ b/tests/Makefile.include -@@ -924,4 +924,12 @@ all: $(QEMU_IOTESTS_HELPERS-y) - -include $(wildcard tests/*.d) - -include $(wildcard tests/libqos/*.d) - -+buildtest-TESTS: $(check-unit-y) -+ -+runtest-TESTS: -+ for f in $(check-unit-y); do \ -+ nf=$$(echo $$f | sed 's/tests\//\.\//g'); \ -+ $$nf; \ -+ done -+ - endif diff --git a/meta/recipes-devtools/qemu/qemu/cpus.c-qemu_cpu_kick_thread_debugging.patch b/meta/recipes-devtools/qemu/qemu/cpus.c-qemu_cpu_kick_thread_debugging.patch deleted file mode 100644 index 6822132541..0000000000 --- a/meta/recipes-devtools/qemu/qemu/cpus.c-qemu_cpu_kick_thread_debugging.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 697a834c35d19447b7dcdb9e1d9434bc6ce17c21 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?An=C3=ADbal=20Lim=C3=B3n?= <anibal.limon@linux.intel.com> -Date: Wed, 12 Aug 2015 15:11:30 -0500 -Subject: [PATCH] cpus.c: Add error messages when qemi_cpu_kick_thread fails. -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Add custom_debug.h with function for print backtrace information. -When pthread_kill fails in qemu_cpu_kick_thread display backtrace and -current cpu information. - -Upstream-Status: Inappropriate -Signed-off-by: Aníbal Limón <anibal.limon@linux.intel.com> ---- - cpus.c | 5 +++++ - custom_debug.h | 24 ++++++++++++++++++++++++ - 2 files changed, 29 insertions(+) - create mode 100644 custom_debug.h - -diff --git a/cpus.c b/cpus.c -index a822ce3..7e4786e 100644 ---- a/cpus.c -+++ b/cpus.c -@@ -1080,6 +1080,8 @@ static void *qemu_tcg_cpu_thread_fn(void *arg) - return NULL; - } - -+#include "custom_debug.h" -+ - static void qemu_cpu_kick_thread(CPUState *cpu) - { - #ifndef _WIN32 -@@ -1088,6 +1090,9 @@ static void qemu_cpu_kick_thread(CPUState *cpu) - err = pthread_kill(cpu->thread->thread, SIG_IPI); - if (err) { - fprintf(stderr, "qemu:%s: %s", __func__, strerror(err)); -+ fprintf(stderr, "CPU #%d:\n", cpu->cpu_index); -+ cpu_dump_state(cpu, stderr, fprintf, 0); -+ backtrace_print(); - exit(1); - } - #else /* _WIN32 */ -diff --git a/custom_debug.h b/custom_debug.h -new file mode 100644 -index 0000000..f029e45 ---- /dev/null -+++ b/custom_debug.h -@@ -0,0 +1,24 @@ -+#include <execinfo.h> -+#include <stdio.h> -+#define BACKTRACE_MAX 128 -+static void backtrace_print(void) -+{ -+ int nfuncs = 0; -+ void *buf[BACKTRACE_MAX]; -+ char **symbols; -+ int i; -+ -+ nfuncs = backtrace(buf, BACKTRACE_MAX); -+ -+ symbols = backtrace_symbols(buf, nfuncs); -+ if (symbols == NULL) { -+ fprintf(stderr, "backtrace_print failed to get symbols"); -+ return; -+ } -+ -+ fprintf(stderr, "Backtrace ...\n"); -+ for (i = 0; i < nfuncs; i++) -+ fprintf(stderr, "%s\n", symbols[i]); -+ -+ free(symbols); -+} --- -1.9.1 - diff --git a/meta/recipes-devtools/qemu/qemu/disable-grabs.patch b/meta/recipes-devtools/qemu/qemu/disable-grabs.patch deleted file mode 100644 index 123833f824..0000000000 --- a/meta/recipes-devtools/qemu/qemu/disable-grabs.patch +++ /dev/null @@ -1,72 +0,0 @@ -When the pointer enters the Qemu window it calls SDL_WM_GrabInput, which calls -XGrabPointer in a busyloop until it returns GrabSuccess. However if there's already -a pointer grab (screen is locked, a menu is open) then qemu will hang until the -grab can be taken. In the specific case of a headless X server on an autobuilder, once -the screensaver has kicked in any qemu instance that appears underneath the -pointer will hang. - -I'm not entirely sure why pointer grabs are required (the documentation -explicitly says it doesn't do grabs when using a tablet, which we are) so wrap -them in a conditional that can be set by the autobuilder environment, preserving -the current grabbing behaviour for everyone else. - -Upstream-Status: Pending -Signed-off-by: Ross Burton <ross.burton@intel.com> - -From 4b1988ecb01a178269ec0513a75f2ec620c7ef6a Mon Sep 17 00:00:00 2001 -From: Ross Burton <ross.burton@intel.com> -Date: Wed, 18 Sep 2013 14:04:54 +0100 -Subject: [PATCH] sdl.c: allow user to disable pointer grabs - -Signed-off-by: Ross Burton <ross.burton@intel.com> -Signed-off-by: Eric Bénard <eric@eukrea.com> ---- - ui/sdl.c | 12 ++++++++++-- - 1 file changed, 10 insertions(+), 2 deletions(-) - -diff --git a/ui/sdl.c b/ui/sdl.c -index 39a42d6..9b8abe5 100644 ---- a/ui/sdl.c -+++ b/ui/sdl.c -@@ -59,6 +59,10 @@ static SDL_Cursor *guest_sprite = NULL; - static int scaling_active = 0; - static Notifier mouse_mode_notifier; - static int idle_counter; -+#ifndef True -+#define True 1 -+#endif -+static doing_grabs = True; - - static void sdl_update(DisplayChangeListener *dcl, - int x, int y, int w, int h) -@@ -384,14 +388,16 @@ static void sdl_grab_start(void) - } - } else - sdl_hide_cursor(); -- SDL_WM_GrabInput(SDL_GRAB_ON); -+ if (doing_grabs) -+ SDL_WM_GrabInput(SDL_GRAB_ON); - gui_grab = 1; - sdl_update_caption(); - } - - static void sdl_grab_end(void) - { -- SDL_WM_GrabInput(SDL_GRAB_OFF); -+ if (doing_grabs) -+ SDL_WM_GrabInput(SDL_GRAB_OFF); - gui_grab = 0; - sdl_show_cursor(); - sdl_update_caption(); -@@ -909,6 +915,8 @@ void sdl_display_init(DisplayState *ds, int full_screen, int no_frame) - * This requires SDL >= 1.2.14. */ - setenv("SDL_DISABLE_LOCK_KEYS", "1", 1); - -+ doing_grabs = (getenv("QEMU_DONT_GRAB") == NULL); -+ - flags = SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE; - if (SDL_Init (flags)) { - fprintf(stderr, "Could not initialize SDL(%s) - exiting\n", --- -1.8.3.1 - diff --git a/meta/recipes-devtools/qemu/qemu/exclude-some-arm-EABI-obsolete-syscalls.patch b/meta/recipes-devtools/qemu/qemu/exclude-some-arm-EABI-obsolete-syscalls.patch deleted file mode 100644 index f593cf9ae0..0000000000 --- a/meta/recipes-devtools/qemu/qemu/exclude-some-arm-EABI-obsolete-syscalls.patch +++ /dev/null @@ -1,87 +0,0 @@ -[PATCH] exclude some arm EABI obsolete syscalls - -Upstream-Status: Pending - -some syscalls are obsolete and no longer available for EABI, exclude them to -fix the below error: - In file included from qemu-seccomp.c:16:0: - qemu-seccomp.c:28:7: error: '__NR_select' undeclared here (not in a function) - { SCMP_SYS(select), 252 }, - ^ - qemu-seccomp.c:36:7: error: '__NR_mmap' undeclared here (not in a function) - { SCMP_SYS(mmap), 247 }, - ^ - qemu-seccomp.c:57:7: error: '__NR_getrlimit' undeclared here (not in a function) - { SCMP_SYS(getrlimit), 245 }, - ^ - qemu-seccomp.c:96:7: error: '__NR_time' undeclared here (not in a function) - { SCMP_SYS(time), 245 }, - ^ - qemu-seccomp.c:185:7: error: '__NR_alarm' undeclared here (not in a function) - { SCMP_SYS(alarm), 241 }, - -please refer source files: - arch/arm/include/uapi/asm/unistd.h -or kernel header: - /usr/include/asm/unistd.h - -Signed-off-by: Roy.Li <rongqing.li@windriver.com> ---- - qemu-seccomp.c | 13 ++++++++----- - 1 file changed, 8 insertions(+), 5 deletions(-) - -diff --git a/qemu-seccomp.c b/qemu-seccomp.c -index df75d9c..0e577f8 100644 ---- a/qemu-seccomp.c -+++ b/qemu-seccomp.c -@@ -35,15 +35,21 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = { - { SCMP_SYS(timer_settime), 255 }, - { SCMP_SYS(timer_gettime), 254 }, - { SCMP_SYS(futex), 253 }, -+#if !defined(__ARM_EABI__) - { SCMP_SYS(select), 252 }, -+ { SCMP_SYS(time), 245 }, -+ { SCMP_SYS(alarm), 241 }, -+ { SCMP_SYS(getrlimit), 245 }, -+ { SCMP_SYS(mmap), 247 }, -+ { SCMP_SYS(socketcall), 250 }, -+ { SCMP_SYS(ipc), 245 }, -+#endif - { SCMP_SYS(recvfrom), 251 }, - { SCMP_SYS(sendto), 250 }, -- { SCMP_SYS(socketcall), 250 }, - { SCMP_SYS(read), 249 }, - { SCMP_SYS(io_submit), 249 }, - { SCMP_SYS(brk), 248 }, - { SCMP_SYS(clone), 247 }, -- { SCMP_SYS(mmap), 247 }, - { SCMP_SYS(mprotect), 246 }, - { SCMP_SYS(execve), 245 }, - { SCMP_SYS(open), 245 }, -@@ -58,7 +64,6 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = { - { SCMP_SYS(bind), 245 }, - { SCMP_SYS(listen), 245 }, - { SCMP_SYS(semget), 245 }, -- { SCMP_SYS(ipc), 245 }, - { SCMP_SYS(gettimeofday), 245 }, - { SCMP_SYS(readlink), 245 }, - { SCMP_SYS(access), 245 }, -@@ -104,7 +109,6 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = { - { SCMP_SYS(times), 245 }, - { SCMP_SYS(exit), 245 }, - { SCMP_SYS(clock_gettime), 245 }, -- { SCMP_SYS(time), 245 }, - { SCMP_SYS(restart_syscall), 245 }, - { SCMP_SYS(pwrite64), 245 }, - { SCMP_SYS(nanosleep), 245 }, -@@ -194,7 +198,6 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = { - { SCMP_SYS(lstat64), 241 }, - { SCMP_SYS(sendfile64), 241 }, - { SCMP_SYS(ugetrlimit), 241 }, -- { SCMP_SYS(alarm), 241 }, - { SCMP_SYS(rt_sigsuspend), 241 }, - { SCMP_SYS(rt_sigqueueinfo), 241 }, - { SCMP_SYS(rt_tgsigqueueinfo), 241 }, --- -2.1.4 - diff --git a/meta/recipes-devtools/qemu/qemu/fix-libcap-header-issue-on-some-distro.patch b/meta/recipes-devtools/qemu/qemu/fix-libcap-header-issue-on-some-distro.patch deleted file mode 100644 index cee6a676ab..0000000000 --- a/meta/recipes-devtools/qemu/qemu/fix-libcap-header-issue-on-some-distro.patch +++ /dev/null @@ -1,84 +0,0 @@ -fix libcap header issue on some distro - -1, When build qemu-native on SLED 11.2, there is an error: -... -| In file included from /usr/include/bits/sigcontext.h:28, -| from /usr/include/signal.h:339, -| from /buildarea2/tmp/work/i686-linux/qemu-native/1.4.0-r0/ -qemu-1.4.0/include/qemu-common.h:42, -| from fsdev/virtfs-proxy-helper.c:23: -| /usr/include/asm/sigcontext.h:28: error: expected specifier- -qualifier-list before '__u64' -| /usr/include/asm/sigcontext.h:191: error: expected specifier- -qualifier-list before '__u64' -... - -2, The virtfs-proxy-helper.c includes <sys/capability.h> and -qemu-common.h in sequence. The header include map is: -(`-->' presents `include') -... -"virtfs-proxy-helper.c" --> <sys/capability.h> -... -"virtfs-proxy-helper.c" --> "qemu-common.h" --> <signal.h> --> -<bits/sigcontext.h> --> <asm/sigcontext.h> --> <linux/types.h> --> -<asm/types.h> --> <asm-generic/types.h> --> <asm-generic/int-ll64.h> -... - -3, The bug is found on SLED 11.2 x86. In libcap header file -/usr/include/sys/capability.h, it does evil stuff like this: -... - 25 /* - 26 * Make sure we can be included from userland by preventing - 27 * capability.h from including other kernel headers - 28 */ - 29 #define _LINUX_TYPES_H - 30 #define _LINUX_FS_H - 31 #define __LINUX_COMPILER_H - 32 #define __user - 33 - 34 typedef unsigned int __u32; - 35 typedef __u32 __le32; -... -This completely prevents including /usr/include/linux/types.h. -The above `<asm/sigcontext.h> --> <linux/types.h>' is prevented, -and '__u64' is defined in <asm-generic/int-ll64.h>. - -4, Modify virtfs-proxy-helper.c to include <sys/capability.h> -last to workaround the issue. - -http://www.linuxtv.org/pipermail/vdr/2009-August/021194.html -http://patchwork.linuxtv.org/patch/12748/ - -Upstream-Status: Pending -Signed-off-by: Hongxu Jia <hongxu.jia@windriver.com> ---- - fsdev/virtfs-proxy-helper.c | 7 +++++-- - 1 file changed, 5 insertions(+), 2 deletions(-) - -diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c ---- a/fsdev/virtfs-proxy-helper.c -+++ b/fsdev/virtfs-proxy-helper.c -@@ -12,7 +12,6 @@ - #include <sys/resource.h> - #include <getopt.h> - #include <syslog.h> --#include <sys/capability.h> - #include <sys/fsuid.h> - #include <sys/vfs.h> - #include <sys/ioctl.h> -@@ -26,7 +25,11 @@ - #include "9p-iov-marshal.h" - #include "hw/9pfs/9p-proxy.h" - #include "fsdev/9p-iov-marshal.h" -- -+/* -+ * Include this one last due to some versions of it being buggy: -+ * http://www.linuxtv.org/pipermail/vdr/2009-August/021194.html -+ */ -+#include <sys/capability.h> - #define PROGNAME "virtfs-proxy-helper" - - #ifndef XFS_SUPER_MAGIC --- -1.7.10.4 - diff --git a/meta/recipes-devtools/qemu/qemu/fixedmeson.patch b/meta/recipes-devtools/qemu/qemu/fixedmeson.patch new file mode 100644 index 0000000000..9047f66dc3 --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/fixedmeson.patch @@ -0,0 +1,20 @@ +Upstream-Status: Inappropriate [workaround, would need a real fix for upstream] + +Index: qemu-8.2.0/configure +=================================================================== +--- qemu-8.2.0.orig/configure ++++ qemu-8.2.0/configure +@@ -955,12 +955,7 @@ fi + $mkvenv ensuregroup --dir "${source_path}/python/wheels" \ + ${source_path}/pythondeps.toml meson || exit 1 + +-# At this point, we expect Meson to be installed and available. +-# We expect mkvenv or pip to have created pyvenv/bin/meson for us. +-# We ignore PATH completely here: we want to use the venv's Meson +-# *exclusively*. +- +-meson="$(cd pyvenv/bin; pwd)/meson" ++meson=`which meson` + + # Conditionally ensure Sphinx is installed. + diff --git a/meta/recipes-devtools/qemu/qemu/glibc-2.25.patch b/meta/recipes-devtools/qemu/qemu/glibc-2.25.patch deleted file mode 100644 index 25569449e4..0000000000 --- a/meta/recipes-devtools/qemu/qemu/glibc-2.25.patch +++ /dev/null @@ -1,74 +0,0 @@ -From: Christopher Covington -Date: Wed, 28 Dec 2016 15:04:33 -0500 -Subject: [Qemu-devel] [PATCH v3] build: include sys/sysmacros.h for major() and minor()a - -The definition of the major() and minor() macros are moving within glibc to -<sys/sysmacros.h>. Include this header when it is available to avoid the -following sorts of build-stopping messages: - -qga/commands-posix.c: In function ‘dev_major_minor’: -qga/commands-posix.c:656:13: error: In the GNU C Library, "major" is defined - by <sys/sysmacros.h>. For historical compatibility, it is - currently defined by <sys/types.h> as well, but we plan to - remove this soon. To use "major", include <sys/sysmacros.h> - directly. If you did not intend to use a system-defined macro - "major", you should undefine it after including <sys/types.h>. [-Werror] - *devmajor = major(st.st_rdev); - ^~~~~~~~~~~~~~~~~~~~~~~~~~ - -qga/commands-posix.c:657:13: error: In the GNU C Library, "minor" is defined - by <sys/sysmacros.h>. For historical compatibility, it is - currently defined by <sys/types.h> as well, but we plan to - remove this soon. To use "minor", include <sys/sysmacros.h> - directly. If you did not intend to use a system-defined macro - "minor", you should undefine it after including <sys/types.h>. [-Werror] - *devminor = minor(st.st_rdev); - ^~~~~~~~~~~~~~~~~~~~~~~~~~ - -The additional include allows the build to complete on Fedora 26 (Rawhide) -with glibc version 2.24.90. - -Signed-off-by: Christopher Covington <address@hidden> -Signed-off-by: Martin Jansa <Martin.Jansa@gmail.com> - -Upstream-Status: Submitted https://lists.gnu.org/archive/html/qemu-devel/2016-12/msg03548.html - -diff -uNr qemu-2.8.0.orig/configure qemu-2.8.0/configure ---- qemu-2.8.0.orig/configure 2017-02-21 19:05:13.180094708 +0100 -+++ qemu-2.8.0/configure 2017-02-21 19:08:53.114087084 +0100 -@@ -4727,6 +4727,20 @@ - then - fi - - ########################################## -+# check for sysmacros.h -+ -+have_sysmacros=no -+cat > $TMPC << EOF -+#include <sys/sysmacros.h> -+int main(void) { -+ return makedev(0, 0); -+} -+EOF -+if compile_prog "" "" ; then -+ have_sysmacros=yes -+fi -+ -+########################################## - # End of CC checks - # After here, no more $cc or $ld runs - -diff -uNr qemu-2.8.0.orig/configure qemu-2.8.0/configure ---- qemu-2.8.0.orig/configure 2017-02-21 19:05:13.180094708 +0100 -+++ qemu-2.8.0/configure 2017-02-21 19:08:53.114087084 +0100 -@@ -5695,6 +5709,10 @@ - echo "CONFIG_AF_VSOCK=y" >> $config_host_mak - fi - -+if test "$have_sysmacros" = "yes" ; then -+ echo "CONFIG_SYSMACROS=y" >> $config_host_mak -+fi -+ - # Hold two types of flag: - # CONFIG_THREAD_SETNAME_BYTHREAD - we've got a way of setting the name on - # a thread we have a handle to diff --git a/meta/recipes-devtools/qemu/qemu/no-pip.patch b/meta/recipes-devtools/qemu/qemu/no-pip.patch new file mode 100644 index 0000000000..92b2edbe9f --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/no-pip.patch @@ -0,0 +1,45 @@ +qemu: Ensure pip and the python venv aren't used for meson + +Qemu wants to use a supported python version and a specific meson version +to "help" users and uses pip and creates a venv to do this. This is a nightmare +for us. Our versions stay up to date and should be supported so we don't +really need/want this wrapping. Tweak things to disable it. + +There was breakage from the wrapper shown by: + +bitbake qemu-system-native +<add DISTRO_FEATURES:remove = "opengl" to local.conf> +bitbake qemu-system-native -c configure + +which would crash. The issue is the change in configuration removes pieces +from the sysroot but pyc files remainm as do pieces of pip which causes +problems. + +Ideally we'd convince upstream to allow some way to disable the venv on +the understanding that if/when it breaks, we keep the pieces. The patch +as it stands is a workaround. + +Upstream-Status: Inappropriate [oe specific] +Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> + +Index: qemu-8.2.0/configure +=================================================================== +--- qemu-8.2.0.orig/configure ++++ qemu-8.2.0/configure +@@ -937,7 +937,7 @@ python="$(command -v "$python")" + echo "python determined to be '$python'" + echo "python version: $($python --version)" + +-python="$($python -B "${source_path}/python/scripts/mkvenv.py" create pyvenv)" ++python=python3 + if test "$?" -ne 0 ; then + error_exit "python venv creation failed" + fi +@@ -945,6 +945,7 @@ fi + # Suppress writing compiled files + python="$python -B" + mkvenv="$python ${source_path}/python/scripts/mkvenv.py" ++mkvenv=true + + # Finish preparing the virtual environment using vendored .whl files + diff --git a/meta/recipes-devtools/qemu/qemu/no-valgrind.patch b/meta/recipes-devtools/qemu/qemu/no-valgrind.patch deleted file mode 100644 index 91f728042d..0000000000 --- a/meta/recipes-devtools/qemu/qemu/no-valgrind.patch +++ /dev/null @@ -1,19 +0,0 @@ -There isn't an option to enable or disable valgrind support, so disable it to avoid non-deterministic builds. - -Upstream-Status: Inappropriate -Signed-off-by: Ross Burton <ross.burton@intel.com> - -diff --git a/configure b/configure -index b3c4f51..4d3929e 100755 ---- a/configure -+++ b/configure -@@ -4193,9 +4192,0 @@ valgrind_h=no --cat > $TMPC << EOF --#include <valgrind/valgrind.h> --int main(void) { -- return 0; --} --EOF --if compile_prog "" "" ; then -- valgrind_h=yes --fi diff --git a/meta/recipes-devtools/qemu/qemu/pathlimit.patch b/meta/recipes-devtools/qemu/qemu/pathlimit.patch deleted file mode 100644 index 57ab981c61..0000000000 --- a/meta/recipes-devtools/qemu/qemu/pathlimit.patch +++ /dev/null @@ -1,137 +0,0 @@ -By default qemu builds a complete list of directories within the user -emulation sysroot (-L option). The OE sysroot directory is large and -this is confusing, for example it indexes all pkgdata. In particular this -confuses strace of qemu binaries with tons of irrelevant paths. - -This patch stops the code indexing up front and instead only indexes -things if/as/when it needs to. This drastically reduces the files it -reads and reduces memory usage and cleans up strace. - -It would also avoid the infinite directory traversal bug in [YOCTO #6996] -although the code could still be vulnerable if it parsed those specific -paths. - -RP -2016/3/9 -Upstream-Status: Pending - -Index: qemu-2.5.0/util/path.c -=================================================================== ---- qemu-2.5.0.orig/util/path.c -+++ qemu-2.5.0/util/path.c -@@ -19,6 +19,7 @@ struct pathelem - char *name; - /* Full path name, eg. /usr/gnemul/x86-linux/lib. */ - char *pathname; -+ int populated_entries; - struct pathelem *parent; - /* Children */ - unsigned int num_entries; -@@ -49,6 +50,7 @@ static struct pathelem *new_entry(const - new->name = g_strdup(name); - new->pathname = g_strdup_printf("%s/%s", root, name); - new->num_entries = 0; -+ new->populated_entries = 0; - return new; - } - -@@ -57,15 +59,16 @@ static struct pathelem *new_entry(const - /* Not all systems provide this feature */ - #if defined(DT_DIR) && defined(DT_UNKNOWN) && defined(DT_LNK) - # define dirent_type(dirent) ((dirent)->d_type) --# define is_dir_maybe(type) \ -- ((type) == DT_DIR || (type) == DT_UNKNOWN || (type) == DT_LNK) -+# define is_not_dir(type) \ -+ ((type) != DT_DIR && (type) != DT_UNKNOWN && (type) != DT_LNK) - #else - # define dirent_type(dirent) (1) --# define is_dir_maybe(type) (type) -+# define is_not_dir(type) (0) - #endif - - static struct pathelem *add_dir_maybe(struct pathelem *path) - { -+ unsigned int i; - DIR *dir; - - if ((dir = opendir(path->pathname)) != NULL) { -@@ -78,6 +81,11 @@ static struct pathelem *add_dir_maybe(st - } - closedir(dir); - } -+ -+ for (i = 0; i < path->num_entries; i++) -+ (path->entries[i])->parent = path; -+ -+ path->populated_entries = 1; - return path; - } - -@@ -93,26 +101,16 @@ static struct pathelem *add_entry(struct - e = &root->entries[root->num_entries-1]; - - *e = new_entry(root->pathname, root, name); -- if (is_dir_maybe(type)) { -- *e = add_dir_maybe(*e); -+ if (is_not_dir(type)) { -+ (*e)->populated_entries = 1; - } - - return root; - } - --/* This needs to be done after tree is stabilized (ie. no more reallocs!). */ --static void set_parents(struct pathelem *child, struct pathelem *parent) --{ -- unsigned int i; -- -- child->parent = parent; -- for (i = 0; i < child->num_entries; i++) -- set_parents(child->entries[i], child); --} -- - /* FIXME: Doesn't handle DIR/.. where DIR is not in emulated dir. */ - static const char * --follow_path(const struct pathelem *cursor, const char *name) -+follow_path(struct pathelem *cursor, struct pathelem **source, const char *name) - { - unsigned int i, namelen; - -@@ -123,14 +121,18 @@ follow_path(const struct pathelem *curso - return cursor->pathname; - - if (strneq(name, namelen, "..")) -- return follow_path(cursor->parent, name + namelen); -+ return follow_path(cursor->parent, &cursor->parent, name + namelen); - - if (strneq(name, namelen, ".")) -- return follow_path(cursor, name + namelen); -+ return follow_path(cursor, source, name + namelen); -+ -+ if (!cursor->populated_entries) -+ *source = add_dir_maybe(cursor); -+ cursor = *source; - - for (i = 0; i < cursor->num_entries; i++) - if (strneq(name, namelen, cursor->entries[i]->name)) -- return follow_path(cursor->entries[i], name + namelen); -+ return follow_path(cursor->entries[i], &cursor->entries[i], name + namelen); - - /* Not found */ - return NULL; -@@ -164,8 +166,6 @@ void init_paths(const char *prefix) - g_free(base->name); - g_free(base); - base = NULL; -- } else { -- set_parents(base, base); - } - } - -@@ -177,5 +177,5 @@ const char *path(const char *name) - if (!base || !name || name[0] != '/') - return name; - -- return follow_path(base, name) ?: name; -+ return follow_path(base, &base, name) ?: name; - } diff --git a/meta/recipes-devtools/qemu/qemu/ppc_locking.patch b/meta/recipes-devtools/qemu/qemu/ppc_locking.patch deleted file mode 100644 index 6f722433d4..0000000000 --- a/meta/recipes-devtools/qemu/qemu/ppc_locking.patch +++ /dev/null @@ -1,105 +0,0 @@ -I've tracked down what I think is a problem causing qemu-system-ppc -to hang whilst booting images. - -I believe the decrementer timer stops receiving interrupts so -tasks in our images hang indefinitely as the timer stopped. - -It can be summed up with this line of debug: - -ppc_set_irq: 0x55b4e0d562f0 n_IRQ 8 level 1 => pending 00000100req 00000004 - -It should normally read: - -ppc_set_irq: 0x55b4e0d562f0 n_IRQ 8 level 1 => pending 00000100req 00000002 - -The question is why CPU_INTERRUPT_EXITTB ends up being set when the -lines above this log message clearly sets CPU_INTERRUPT_HARD (via -cpu_interrupt() ). - -I note in cpu.h: - - /* updates protected by BQL */ - uint32_t interrupt_request; - -(for struct CPUState) - -The ppc code does "cs->interrupt_request |= CPU_INTERRUPT_EXITTB" in 5 -places, 3 in excp_helper.c and 2 in helper_regs.h. In all cases, -g_assert(qemu_mutex_iothread_locked()); fails. If I do something like: - -if (!qemu_mutex_iothread_locked()) { - qemu_mutex_lock_iothread(); - cpu_interrupt(cs, CPU_INTERRUPT_EXITTB); - qemu_mutex_unlock_iothread(); -} else { - cpu_interrupt(cs, CPU_INTERRUPT_EXITTB); -} - -in these call sites then I can no longer lock qemu up with my test -case. - -I suspect the _HARD setting gets overwritten which stops the -decrementer interrupts being delivered. - -Upstream-Status: Submitted [Issue discussed on qemu mailing list 2017/11/20] -RP 2017/11/20 - -Index: qemu-2.10.1/target/ppc/excp_helper.c -=================================================================== ---- qemu-2.10.1.orig/target/ppc/excp_helper.c -+++ qemu-2.10.1/target/ppc/excp_helper.c -@@ -207,7 +207,9 @@ static inline void powerpc_excp(PowerPCC - "Entering checkstop state\n"); - } - cs->halted = 1; -- cs->interrupt_request |= CPU_INTERRUPT_EXITTB; -+ qemu_mutex_lock_iothread(); -+ cpu_interrupt(cs, CPU_INTERRUPT_EXITTB); -+ qemu_mutex_unlock_iothread(); - } - if (env->msr_mask & MSR_HVB) { - /* ISA specifies HV, but can be delivered to guest with HV clear -@@ -940,7 +942,9 @@ void helper_store_msr(CPUPPCState *env, - - if (excp != 0) { - CPUState *cs = CPU(ppc_env_get_cpu(env)); -- cs->interrupt_request |= CPU_INTERRUPT_EXITTB; -+ qemu_mutex_lock_iothread(); -+ cpu_interrupt(cs, CPU_INTERRUPT_EXITTB); -+ qemu_mutex_unlock_iothread(); - raise_exception(env, excp); - } - } -@@ -995,7 +999,9 @@ static inline void do_rfi(CPUPPCState *e - /* No need to raise an exception here, - * as rfi is always the last insn of a TB - */ -- cs->interrupt_request |= CPU_INTERRUPT_EXITTB; -+ qemu_mutex_lock_iothread(); -+ cpu_interrupt(cs, CPU_INTERRUPT_EXITTB); -+ qemu_mutex_unlock_iothread(); - - /* Reset the reservation */ - env->reserve_addr = -1; -Index: qemu-2.10.1/target/ppc/helper_regs.h -=================================================================== ---- qemu-2.10.1.orig/target/ppc/helper_regs.h -+++ qemu-2.10.1/target/ppc/helper_regs.h -@@ -114,11 +114,15 @@ static inline int hreg_store_msr(CPUPPCS - } - if (((value >> MSR_IR) & 1) != msr_ir || - ((value >> MSR_DR) & 1) != msr_dr) { -- cs->interrupt_request |= CPU_INTERRUPT_EXITTB; -+ qemu_mutex_lock_iothread(); -+ cpu_interrupt(cs, CPU_INTERRUPT_EXITTB); -+ qemu_mutex_unlock_iothread(); - } - if ((env->mmu_model & POWERPC_MMU_BOOKE) && - ((value >> MSR_GS) & 1) != msr_gs) { -- cs->interrupt_request |= CPU_INTERRUPT_EXITTB; -+ qemu_mutex_lock_iothread(); -+ cpu_interrupt(cs, CPU_INTERRUPT_EXITTB); -+ qemu_mutex_unlock_iothread(); - } - if (unlikely((env->flags & POWERPC_FLAG_TGPR) && - ((value ^ env->msr) & (1 << MSR_TGPR)))) { diff --git a/meta/recipes-devtools/qemu/qemu/qemu-2.5.0-cflags.patch b/meta/recipes-devtools/qemu/qemu/qemu-2.5.0-cflags.patch deleted file mode 100644 index eb99d14639..0000000000 --- a/meta/recipes-devtools/qemu/qemu/qemu-2.5.0-cflags.patch +++ /dev/null @@ -1,15 +0,0 @@ -Upstream-Status: Pending - ---- a/configure -+++ b/configure -@@ -4468,10 +4468,6 @@ fi - if test "$gcov" = "yes" ; then - CFLAGS="-fprofile-arcs -ftest-coverage -g $CFLAGS" - LDFLAGS="-fprofile-arcs -ftest-coverage $LDFLAGS" --elif test "$fortify_source" = "yes" ; then -- CFLAGS="-O2 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 $CFLAGS" --elif test "$debug" = "no"; then -- CFLAGS="-O2 $CFLAGS" - fi - - ########################################## diff --git a/meta/recipes-devtools/qemu/qemu/qemu-enlarge-env-entry-size.patch b/meta/recipes-devtools/qemu/qemu/qemu-enlarge-env-entry-size.patch deleted file mode 100644 index c7425ab8d4..0000000000 --- a/meta/recipes-devtools/qemu/qemu/qemu-enlarge-env-entry-size.patch +++ /dev/null @@ -1,31 +0,0 @@ -qemu: Add addition environment space to boot loader qemu-system-mips - -Upstream-Status: Inappropriate - OE uses deep paths - -If you create a project with very long directory names like 128 characters -deep and use NFS, the kernel arguments will be truncated. The kernel will -accept longer strings such as 1024 bytes, but the qemu boot loader defaulted -to only 256 bytes. This patch expands the limit. - -Signed-off-by: Jason Wessel <jason.wessel@windriver.com> -Signed-off-by: Roy Li <rongqing.li@windriver.com> ---- - hw/mips/mips_malta.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c -index 9d521cc..17c0391 100644 ---- a/hw/mips/mips_malta.c -+++ b/hw/mips/mips_malta.c -@@ -53,7 +53,7 @@ - - #define ENVP_ADDR 0x80002000l - #define ENVP_NB_ENTRIES 16 --#define ENVP_ENTRY_SIZE 256 -+#define ENVP_ENTRY_SIZE 1024 - - /* Hardware addresses */ - #define FLASH_ADDRESS 0x1e000000ULL --- -1.7.10.4 - diff --git a/meta/recipes-devtools/qemu/qemu/qemu-guest-agent.init b/meta/recipes-devtools/qemu/qemu/qemu-guest-agent.init new file mode 100644 index 0000000000..5ebaaddeae --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/qemu-guest-agent.init @@ -0,0 +1,75 @@ +# SPDX-License-Identifier: GPL-2.0-only +# Initially written by: Michael Tokarev <mjt@tls.msk.ru> +# For QEMU Debian downstream package + +set -e + +. /etc/init.d/functions + +PATH=/sbin:/usr/sbin:/bin:/usr/bin +DESC="QEMU Guest Agent" +NAME=qemu-ga +DAEMON=@bindir@/$NAME +PIDFILE=/var/run/$NAME.pid + +# config +DAEMON_ARGS="" +# default transport +TRANSPORT=virtio-serial:/dev/virtio-ports/org.qemu.guest_agent.0 +NO_START=0 + +test ! -r /etc/default/qemu-guest-agent || . /etc/default/qemu-guest-agent +test "$NO_START" = "0" || exit 0 +test -x "$DAEMON" || exit 0 + +# +# Function that checks whenever system has necessary environment +# It also splits $TRANSPORT into $method and $path +# +do_check_transport() { + method=${TRANSPORT%%:*}; + path=${TRANSPORT#*:} + case "$method" in + virtio-serial | isa-serial) + if [ ! -e "$path" ]; then + echo "$NAME: transport endpoint not found, not starting" + return 1 + fi + ;; + esac +} + +case "$1" in + start) + do_check_transport || exit 0 + echo -n "Starting $DESC: " + start-stop-daemon -S -p $PIDFILE -x "$DAEMON" -- \ + $DAEMON_ARGS -d -m "$method" -p "$path" + echo "$NAME." + ;; + stop) + echo -n "Stopping $DESC: " + start-stop-daemon -K -x "$DAEMON" -p $PIDFILE + echo "$NAME." + ;; + status) + status "$DAEMON" + exit $? + ;; + restart|force-reload) + do_check_transport || exit 0 + echo -n "Restarting $DESC: " + start-stop-daemon -K -x "$DAEMON" -p $PIDFILE + sleep 1 + start-stop-daemon -S -p $PIDFILE -x "$DAEMON" -- \ + $DAEMON_ARGS -d -m "$method" -p "$path" + echo "$NAME." + ;; + *) + N=/etc/init.d/$NAME + echo "Usage: $N {start|stop|status|restart|force-reload}" >&2 + exit 1 + ;; +esac + +exit 0 diff --git a/meta/recipes-devtools/qemu/qemu/qemu-guest-agent.udev b/meta/recipes-devtools/qemu/qemu/qemu-guest-agent.udev new file mode 100644 index 0000000000..47097057e3 --- /dev/null +++ b/meta/recipes-devtools/qemu/qemu/qemu-guest-agent.udev @@ -0,0 +1,2 @@ +SUBSYSTEM=="virtio-ports", ATTR{name}=="org.qemu.guest_agent.0", \ + TAG+="systemd", ENV{SYSTEMD_WANTS}="qemu-guest-agent.service" diff --git a/meta/recipes-devtools/qemu/qemu/run-ptest b/meta/recipes-devtools/qemu/qemu/run-ptest index 2206b31922..f9a4e8fb2b 100644 --- a/meta/recipes-devtools/qemu/qemu/run-ptest +++ b/meta/recipes-devtools/qemu/qemu/run-ptest @@ -7,4 +7,7 @@ ptestdir=$(dirname "$(readlink -f "$0")") export SRC_PATH=$ptestdir cd $ptestdir/tests -make -f Makefile.include -k runtest-TESTS | sed '/: OK/ s/^/PASS: /g' +tests=$(find . -name "test-*" ! -name "*.p") +for f in $tests; do + $f | sed '/^ok/ s/ok/PASS:/g' +done diff --git a/meta/recipes-devtools/qemu/qemu/wacom.patch b/meta/recipes-devtools/qemu/qemu/wacom.patch deleted file mode 100644 index cd06aa4ac6..0000000000 --- a/meta/recipes-devtools/qemu/qemu/wacom.patch +++ /dev/null @@ -1,130 +0,0 @@ -The USB wacom device is missing a HID descriptor which causes it -to fail to operate with recent kernels (e.g. 3.17). - -This patch adds a HID desriptor to the device, based upon one from -real wcom device. - -Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> - -Upstream-Status: Submitted -2014/11/27 - -Index: qemu-2.1.0/hw/usb/dev-wacom.c -=================================================================== ---- qemu-2.1.0.orig/hw/usb/dev-wacom.c 2014-08-01 15:12:17.000000000 +0100 -+++ qemu-2.1.0/hw/usb/dev-wacom.c 2014-10-12 12:13:30.540306042 +0100 -@@ -68,6 +68,89 @@ - [STR_SERIALNUMBER] = "1", - }; - -+static const uint8_t qemu_tablet_hid_report_descriptor[] = { -+ 0x05, 0x01, /* Usage Page (Generic Desktop) */ -+ 0x09, 0x02, /* Usage (Mouse) */ -+ 0xa1, 0x01, /* Collection (Application) */ -+ 0x85, 0x01, /* Report ID (1) */ -+ 0x09, 0x01, /* Usage (Pointer) */ -+ 0xa1, 0x00, /* Collection (Physical) */ -+ 0x05, 0x09, /* Usage Page (Button) */ -+ 0x19, 0x01, /* Usage Minimum (1) */ -+ 0x29, 0x05, /* Usage Maximum (5) */ -+ 0x15, 0x00, /* Logical Minimum (0) */ -+ 0x25, 0x01, /* Logical Maximum (1) */ -+ 0x95, 0x05, /* Report Count (5) */ -+ 0x75, 0x01, /* Report Size (1) */ -+ 0x81, 0x02, /* Input (Data, Variable, Absolute) */ -+ 0x95, 0x01, /* Report Count (1) */ -+ 0x75, 0x03, /* Report Size (3) */ -+ 0x81, 0x01, /* Input (Constant) */ -+ 0x05, 0x01, /* Usage Page (Generic Desktop) */ -+ 0x09, 0x30, /* Usage (X) */ -+ 0x09, 0x31, /* Usage (Y) */ -+ 0x15, 0x81, /* Logical Minimum (-127) */ -+ 0x25, 0x7f, /* Logical Maximum (127) */ -+ 0x75, 0x08, /* Report Size (8) */ -+ 0x95, 0x02, /* Report Count (2) */ -+ 0x81, 0x06, /* Input (Data, Variable, Relative) */ -+ 0xc0, /* End Collection */ -+ 0xc0, /* End Collection */ -+ 0x05, 0x0d, /* Usage Page (Digitizer) */ -+ 0x09, 0x01, /* Usage (Digitizer) */ -+ 0xa1, 0x01, /* Collection (Application) */ -+ 0x85, 0x02, /* Report ID (2) */ -+ 0xa1, 0x00, /* Collection (Physical) */ -+ 0x06, 0x00, 0xff, /* Usage Page (Vendor 0xff00) */ -+ 0x09, 0x01, /* Usage (Digitizer) */ -+ 0x15, 0x00, /* Logical Minimum (0) */ -+ 0x26, 0xff, 0x00, /* Logical Maximum (255) */ -+ 0x75, 0x08, /* Report Size (8) */ -+ 0x95, 0x08, /* Report Count (8) */ -+ 0x81, 0x02, /* Input (Data, Variable, Absolute) */ -+ 0xc0, /* End Collection */ -+ 0x09, 0x01, /* Usage (Digitizer) */ -+ 0x85, 0x02, /* Report ID (2) */ -+ 0x95, 0x01, /* Report Count (1) */ -+ 0xb1, 0x02, /* FEATURE (2) */ -+ 0xc0, /* End Collection */ -+ 0x06, 0x00, 0xff, /* Usage Page (Vendor 0xff00) */ -+ 0x09, 0x01, /* Usage (Digitizer) */ -+ 0xa1, 0x01, /* Collection (Application) */ -+ 0x85, 0x02, /* Report ID (2) */ -+ 0x05, 0x0d, /* Usage Page (Digitizer) */ -+ 0x09, 0x22, /* Usage (Finger) */ -+ 0xa1, 0x00, /* Collection (Physical) */ -+ 0x06, 0x00, 0xff, /* Usage Page (Vendor 0xff00) */ -+ 0x09, 0x01, /* Usage (Digitizer) */ -+ 0x15, 0x00, /* Logical Minimum (0) */ -+ 0x26, 0xff, 0x00, /* Logical Maximum */ -+ 0x75, 0x08, /* Report Size (8) */ -+ 0x95, 0x02, /* Report Count (2) */ -+ 0x81, 0x02, /* Input (Data, Variable, Absolute) */ -+ 0x05, 0x01, /* Usage Page (Generic Desktop) */ -+ 0x09, 0x30, /* Usage (X) */ -+ 0x35, 0x00, /* Physical Minimum */ -+ 0x46, 0xe0, 0x2e, /* Physical Maximum */ -+ 0x26, 0xe0, 0x01, /* Logical Maximum */ -+ 0x75, 0x10, /* Report Size (16) */ -+ 0x95, 0x01, /* Report Count (1) */ -+ 0x81, 0x02, /* Input (Data, Variable, Absolute) */ -+ 0x09, 0x31, /* Usage (Y) */ -+ 0x46, 0x40, 0x1f, /* Physical Maximum */ -+ 0x26, 0x40, 0x01, /* Logical Maximum */ -+ 0x81, 0x02, /* Input (Data, Variable, Absolute) */ -+ 0x06, 0x00, 0xff, /* Usage Page (Vendor 0xff00) */ -+ 0x09, 0x01, /* Usage (Digitizer) */ -+ 0x26, 0xff, 0x00, /* Logical Maximum */ -+ 0x75, 0x08, /* Report Size (8) */ -+ 0x95, 0x0d, /* Report Count (13) */ -+ 0x81, 0x02, /* Input (Data, Variable, Absolute) */ -+ 0xc0, /* End Collection */ -+ 0xc0, /* End Collection */ -+}; -+ -+ - static const USBDescIface desc_iface_wacom = { - .bInterfaceNumber = 0, - .bNumEndpoints = 1, -@@ -85,7 +168,7 @@ - 0x00, /* u8 country_code */ - 0x01, /* u8 num_descriptors */ - 0x22, /* u8 type: Report */ -- 0x6e, 0, /* u16 len */ -+ sizeof(qemu_tablet_hid_report_descriptor), 0, /* u16 len */ - }, - }, - }, -@@ -265,6 +350,15 @@ - } - - switch (request) { -+ case InterfaceRequest | USB_REQ_GET_DESCRIPTOR: -+ switch (value >> 8) { -+ case 0x22: -+ memcpy(data, qemu_tablet_hid_report_descriptor, -+ sizeof(qemu_tablet_hid_report_descriptor)); -+ p->actual_length = sizeof(qemu_tablet_hid_report_descriptor); -+ break; -+ } -+ break; - case WACOM_SET_REPORT: - if (s->mouse_grabbed) { - qemu_remove_mouse_event_handler(s->eh_entry); |