Yocto 2.3
Move OpenBMC to Yocto 2.3(pyro).
Tested: Built and verified Witherspoon and Palmetto images
Change-Id: I50744030e771f4850afc2a93a10d3507e76d36bc
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
Resolves: openbmc/openbmc#2461
diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu-helper-native_1.0.bb b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu-helper-native_1.0.bb
index 8d27c4d..27d5315 100644
--- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu-helper-native_1.0.bb
+++ b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu-helper-native_1.0.bb
@@ -19,3 +19,7 @@
install -d ${D}${bindir}
install tunctl ${D}${bindir}/
}
+
+RM_WORK_EXCLUDE_ITEMS += "recipe-sysroot-native"
+DEPENDS += "qemu-native"
+addtask addto_recipe_sysroot after do_populate_sysroot before do_build
diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu-targets.inc b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu-targets.inc
index a3e46a8..66dd675 100644
--- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu-targets.inc
+++ b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu-targets.inc
@@ -4,8 +4,8 @@
def get_qemu_target_list(d):
import bb
- archs = d.getVar('QEMU_TARGETS', True).split()
- tos = d.getVar('HOST_OS', True)
+ archs = d.getVar('QEMU_TARGETS').split()
+ tos = d.getVar('HOST_OS')
softmmuonly = ""
for arch in ['ppcemb']:
if arch in archs:
diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu.inc b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu.inc
index b46e7f7..0e1411a 100644
--- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu.inc
+++ b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu.inc
@@ -3,35 +3,33 @@
LICENSE = "GPLv2 & LGPLv2.1"
DEPENDS = "glib-2.0 zlib pixman"
RDEPENDS_${PN}_class-target += "bash"
-RDEPENDS_${PN}-ptest = "bash make"
require qemu-targets.inc
-inherit autotools ptest
+inherit autotools pkgconfig bluetooth
BBCLASSEXTEND = "native nativesdk"
-PR = "r1"
-
# QEMU_TARGETS is overridable variable
QEMU_TARGETS ?= "arm aarch64 i386 mips mipsel mips64 mips64el ppc sh4 x86_64"
-SRC_URI = "\
- file://powerpc_rom.bin \
- file://disable-grabs.patch \
- file://exclude-some-arm-EABI-obsolete-syscalls.patch \
- file://wacom.patch \
- file://add-ptest-in-makefile.patch \
- file://run-ptest \
- file://0001-target-mips-add-24KEc-CPU-definition.patch \
+EXTRA_OECONF = " \
+ --prefix=${prefix} \
+ --bindir=${bindir} \
+ --includedir=${includedir} \
+ --libdir=${libdir} \
+ --mandir=${mandir} \
+ --datadir=${datadir} \
+ --docdir=${docdir}/${BPN} \
+ --sysconfdir=${sysconfdir} \
+ --libexecdir=${libexecdir} \
+ --localstatedir=${localstatedir} \
+ --with-confsuffix=/${BPN} \
+ --disable-strip \
+ --disable-werror \
+ --target-list=${@get_qemu_target_list(d)} \
+ --with-system-pixman \
+ --extra-cflags='${CFLAGS}' \
"
-
-SRC_URI_append_class-native = "\
- file://fix-libcap-header-issue-on-some-distro.patch \
- file://cpus.c-qemu_cpu_kick_thread_debugging.patch \
- "
-
-EXTRA_OECONF += "--target-list=${@get_qemu_target_list(d)} --disable-werror --disable-bluez --disable-libiscsi --with-system-pixman --extra-cflags='${CFLAGS}'"
-
-EXTRA_OECONF_class-nativesdk = "--target-list=${@get_qemu_target_list(d)} --disable-werror"
+EXTRA_OECONF_append_class-native = " --python=${USRBINPATH}/python2.7"
EXTRA_OEMAKE_append_class-native = " LD='${LD}' AR='${AR}' OBJCOPY='${OBJCOPY}' LDFLAGS='${LDFLAGS}'"
@@ -52,38 +50,14 @@
"${S}"/Makefile "${S}"/Makefile.target
}
-KVMENABLE = "--enable-kvm"
-KVMENABLE_darwin = "--disable-kvm"
-KVMENABLE_mingw32 = "--disable-kvm"
-
do_configure() {
- # Handle distros such as CentOS 5 32-bit that do not have kvm support
- KVMOPTS="--disable-kvm"
- if [ "${PN}" != "qemu-native" -a "${PN}" != "nativesdk-qemu" ] \
- || [ -f /usr/include/linux/kvm.h ] ; then
- KVMOPTS="${KVMENABLE}"
- fi
-
- ${S}/configure --prefix=${prefix} --sysconfdir=${sysconfdir} --libexecdir=${libexecdir} --localstatedir=${localstatedir} --disable-strip ${EXTRA_OECONF} $KVMOPTS
+ ${S}/configure ${EXTRA_OECONF}
test ! -e ${S}/target-i386/beginend_funcs.sh || chmod a+x ${S}/target-i386/beginend_funcs.sh
}
-do_compile_ptest() {
- make buildtest-TESTS
-}
-
-do_install_ptest() {
- cp -rL ${B}/tests ${D}${PTEST_PATH}
- find ${D}${PTEST_PATH}/tests -type f -name "*.[Sshcod]" | xargs -i rm -rf {}
-
- cp ${S}/tests/Makefile.include ${D}${PTEST_PATH}/tests
-}
-
do_install () {
export STRIP="true"
autotools_do_install
- install -d ${D}${datadir}/qemu
- install -m 0755 ${WORKDIR}/powerpc_rom.bin ${D}${datadir}/qemu
}
# The following fragment will create a wrapper for qemu-mips user emulation
@@ -102,11 +76,18 @@
PACKAGECONFIG ??= " \
fdt sdl \
- ${@bb.utils.contains('DISTRO_FEATURES', 'alsa', 'alsa', '', d)} \
- ${@bb.utils.contains('DISTRO_FEATURES', 'xen', 'xen', '', d)} \
+ fdt sdl kvm \
+ ${@bb.utils.filter('DISTRO_FEATURES', 'alsa xen', d)} \
"
-PACKAGECONFIG_class-native ??= "fdt alsa uuid"
-PACKAGECONFIG_class-nativesdk ??= "fdt sdl"
+PACKAGECONFIG_class-native ??= "fdt alsa kvm"
+PACKAGECONFIG_class-nativesdk ??= "fdt sdl kvm"
+
+# Handle distros such as CentOS 5 32-bit that do not have kvm support
+PACKAGECONFIG_class-native_remove = "${@'kvm' if not os.path.exists('/usr/include/linux/kvm.h') else ''}"
+
+# Disable kvm on targets that do not support it
+PACKAGECONFIG_remove_darwin = "kvm"
+PACKAGECONFIG_remove_mingw32 = "kvm"
PACKAGECONFIG[sdl] = "--enable-sdl,--disable-sdl,libsdl"
PACKAGECONFIG[virtfs] = "--enable-virtfs --enable-attr,--disable-virtfs,libcap attr,"
@@ -118,22 +99,22 @@
PACKAGECONFIG[vnc-png] = "--enable-vnc --enable-vnc-png,--disable-vnc-png,libpng,"
PACKAGECONFIG[libcurl] = "--enable-curl,--disable-curl,libcurl,"
PACKAGECONFIG[nss] = "--enable-smartcard,--disable-smartcard,nss,"
-PACKAGECONFIG[uuid] = "--enable-uuid,--disable-uuid,util-linux,"
PACKAGECONFIG[curses] = "--enable-curses,--disable-curses,ncurses,"
PACKAGECONFIG[gtk+] = "--enable-gtk --with-gtkabi=3.0 --enable-vte,--disable-gtk --disable-vte,gtk+3 vte"
PACKAGECONFIG[libcap-ng] = "--enable-cap-ng,--disable-cap-ng,libcap-ng,"
PACKAGECONFIG[ssh2] = "--enable-libssh2,--disable-libssh2,libssh2,"
-PACKAGECONFIG[gcrypt] = "--enable-gcrypt,--disable-gcrypt,gcrypt,"
+PACKAGECONFIG[gcrypt] = "--enable-gcrypt,--disable-gcrypt,libgcrypt,"
PACKAGECONFIG[nettle] = "--enable-nettle,--disable-nettle,nettle"
PACKAGECONFIG[libusb] = "--enable-libusb,--disable-libusb,libusb1"
PACKAGECONFIG[fdt] = "--enable-fdt,--disable-fdt,dtc"
-PACKAGECONFIG[alsa] = ",,alsa-lib"
+PACKAGECONFIG[alsa] = "--audio-drv-list='oss alsa',,alsa-lib"
PACKAGECONFIG[glx] = "--enable-opengl,--disable-opengl,mesa"
PACKAGECONFIG[lzo] = "--enable-lzo,--disable-lzo,lzo"
PACKAGECONFIG[numa] = "--enable-numa,--disable-numa,numactl"
PACKAGECONFIG[gnutls] = "--enable-gnutls,--disable-gnutls,gnutls"
PACKAGECONFIG[bzip2] = "--enable-bzip2,--disable-bzip2,bzip2"
-
-EXTRA_OECONF += "${@bb.utils.contains('PACKAGECONFIG', 'alsa', '--audio-drv-list=oss,alsa', '', d)}"
+PACKAGECONFIG[bluez] = "--enable-bluez,--disable-bluez,${BLUEZ}"
+PACKAGECONFIG[libiscsi] = "--enable-libiscsi,--disable-libiscsi"
+PACKAGECONFIG[kvm] = "--enable-kvm,--disable-kvm"
INSANE_SKIP_${PN} = "arch"
diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0001-Provide-support-for-the-CUSE-TPM.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0001-Provide-support-for-the-CUSE-TPM.patch
new file mode 100644
index 0000000..74dc6f5
--- /dev/null
+++ b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0001-Provide-support-for-the-CUSE-TPM.patch
@@ -0,0 +1,870 @@
+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/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0001-target-mips-add-24KEc-CPU-definition.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0001-target-mips-add-24KEc-CPU-definition.patch
deleted file mode 100644
index c4dbee7..0000000
--- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0001-target-mips-add-24KEc-CPU-definition.patch
+++ /dev/null
@@ -1,54 +0,0 @@
-From 926bc194f918d46bd93557b15da8153b6a94a1d5 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Andr=C3=A9=20Draszik?= <git@andred.net>
-Date: Mon, 25 Jul 2016 23:58:22 +0100
-Subject: [PATCH] target-mips: add 24KEc CPU definition
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-Define a new CPU definition supporting 24KEc cores, similar to
-the existing 24Kc, but with added support for DSP instructions
-and MIPS16e (and without FPU).
-
-Signed-off-by: André Draszik <git@andred.net>
----
-Upstream-Status: Submitted [http://lists.nongnu.org/archive/html/qemu-devel/2016-07/msg05778.html]
- target-mips/translate_init.c | 22 ++++++++++++++++++++++
- 1 file changed, 22 insertions(+)
-
-diff --git a/target-mips/translate_init.c b/target-mips/translate_init.c
-index 39ed5c4..6ae23e4 100644
---- a/target-mips/translate_init.c
-+++ b/target-mips/translate_init.c
-@@ -256,6 +256,28 @@ static const mips_def_t mips_defs[] =
- .mmu_type = MMU_TYPE_R4000,
- },
- {
-+ .name = "24KEc",
-+ .CP0_PRid = 0x00019600,
-+ .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
-+ (MMU_TYPE_R4000 << CP0C0_MT),
-+ .CP0_Config1 = MIPS_CONFIG1 | (15 << CP0C1_MMU) |
-+ (0 << CP0C1_IS) | (3 << CP0C1_IL) | (1 << CP0C1_IA) |
-+ (0 << CP0C1_DS) | (3 << CP0C1_DL) | (1 << CP0C1_DA) |
-+ (1 << CP0C1_CA),
-+ .CP0_Config2 = MIPS_CONFIG2,
-+ .CP0_Config3 = MIPS_CONFIG3 | (1 << CP0C3_DSPP) | (0 << CP0C3_VInt),
-+ .CP0_LLAddr_rw_bitmask = 0,
-+ .CP0_LLAddr_shift = 4,
-+ .SYNCI_Step = 32,
-+ .CCRes = 2,
-+ /* we have a DSP, but no FPU */
-+ .CP0_Status_rw_bitmask = 0x1378FF1F,
-+ .SEGBITS = 32,
-+ .PABITS = 32,
-+ .insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP,
-+ .mmu_type = MMU_TYPE_R4000,
-+ },
-+ {
- .name = "24Kf",
- .CP0_PRid = 0x00019300,
- .CP0_Config0 = MIPS_CONFIG0 | (0x1 << CP0C0_AR) |
---
-2.8.1
-
diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0001-virtio-zero-vq-inuse-in-virtio_reset.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0001-virtio-zero-vq-inuse-in-virtio_reset.patch
deleted file mode 100644
index 86955d0..0000000
--- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0001-virtio-zero-vq-inuse-in-virtio_reset.patch
+++ /dev/null
@@ -1,57 +0,0 @@
-Upstream-Status: Backport
-
-Supplementary fix of CVE-2016-5403 which is backported from:
-
-http://git.qemu.org/?p=qemu.git;a=commit;h=4b7f91e
-
-Signed-off-by: Kai Kang <kai.kang@windriver.com>
----
-From 4b7f91ed0270a371e1933efa21ba600b6da23ab9 Mon Sep 17 00:00:00 2001
-From: Stefan Hajnoczi <stefanha@redhat.com>
-Date: Wed, 7 Sep 2016 11:51:25 -0400
-Subject: [PATCH] virtio: zero vq->inuse in virtio_reset()
-
-vq->inuse must be zeroed upon device reset like most other virtqueue
-fields.
-
-In theory, virtio_reset() just needs assert(vq->inuse == 0) since
-devices must clean up in-flight requests during reset (requests cannot
-not be leaked!).
-
-In practice, it is difficult to achieve vq->inuse == 0 across reset
-because balloon, blk, 9p, etc implement various different strategies for
-cleaning up requests. Most devices call g_free(elem) directly without
-telling virtio.c that the VirtQueueElement is cleaned up. Therefore
-vq->inuse is not decremented during reset.
-
-This patch zeroes vq->inuse and trusts that devices are not leaking
-VirtQueueElements across reset.
-
-I will send a follow-up series that refactors request life-cycle across
-all devices and converts vq->inuse = 0 into assert(vq->inuse == 0) but
-this more invasive approach is not appropriate for stable trees.
-
-Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
-Cc: qemu-stable <qemu-stable@nongnu.org>
-Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
-Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
-Reviewed-by: Ladi Prosek <lprosek@redhat.com>
----
- hw/virtio/virtio.c | 1 +
- 1 file changed, 1 insertion(+)
-
-diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
-index 74c085c..e8a13a5 100644
---- a/hw/virtio/virtio.c
-+++ b/hw/virtio/virtio.c
-@@ -822,6 +822,7 @@ void virtio_reset(void *opaque)
- vdev->vq[i].signalled_used_valid = false;
- vdev->vq[i].notification = true;
- vdev->vq[i].vring.num = vdev->vq[i].vring.num_default;
-+ vdev->vq[i].inuse = 0;
- }
- }
-
---
-2.9.3
-
diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0002-Introduce-condition-to-notify-waiters-of-completed-c.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0002-Introduce-condition-to-notify-waiters-of-completed-c.patch
new file mode 100644
index 0000000..c88c98e
--- /dev/null
+++ b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0002-Introduce-condition-to-notify-waiters-of-completed-c.patch
@@ -0,0 +1,86 @@
+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/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0002-fix-CVE-2016-7423.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0002-fix-CVE-2016-7423.patch
deleted file mode 100644
index fdf58a3..0000000
--- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0002-fix-CVE-2016-7423.patch
+++ /dev/null
@@ -1,45 +0,0 @@
-Upstream-Status: Backport
-
-Backport patch to fix CVE-2016-7423 from:
-
-http://git.qemu.org/?p=qemu.git;a=commit;h=670e56d3ed
-
-CVE: CVE-2016-7423
-
-Signed-off-by: Kai Kang <kai.kang@windriver.com>
----
-From 670e56d3ed2918b3861d9216f2c0540d9e9ae0d5 Mon Sep 17 00:00:00 2001
-From: Li Qiang <liqiang6-s@360.cn>
-Date: Mon, 12 Sep 2016 18:14:11 +0530
-Subject: [PATCH] scsi: mptsas: use g_new0 to allocate MPTSASRequest object
-
-When processing IO request in mptsas, it uses g_new to allocate
-a 'req' object. If an error occurs before 'req->sreq' is
-allocated, It could lead to an OOB write in mptsas_free_request
-function. Use g_new0 to avoid it.
-
-Reported-by: Li Qiang <liqiang6-s@360.cn>
-Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
-Message-Id: <1473684251-17476-1-git-send-email-ppandit@redhat.com>
-Cc: qemu-stable@nongnu.org
-Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
----
- hw/scsi/mptsas.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/hw/scsi/mptsas.c b/hw/scsi/mptsas.c
-index 0e0a22f..eaae1bb 100644
---- a/hw/scsi/mptsas.c
-+++ b/hw/scsi/mptsas.c
-@@ -304,7 +304,7 @@ static int mptsas_process_scsi_io_request(MPTSASState *s,
- goto bad;
- }
-
-- req = g_new(MPTSASRequest, 1);
-+ req = g_new0(MPTSASRequest, 1);
- QTAILQ_INSERT_TAIL(&s->pending, req, next);
- req->scsi_io = *scsi_io;
- req->dev = s;
---
-2.9.3
-
diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0003-Introduce-condition-in-TPM-backend-for-notification.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0003-Introduce-condition-in-TPM-backend-for-notification.patch
new file mode 100644
index 0000000..e58f019
--- /dev/null
+++ b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0003-Introduce-condition-in-TPM-backend-for-notification.patch
@@ -0,0 +1,79 @@
+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/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0003-fix-CVE-2016-7908.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0003-fix-CVE-2016-7908.patch
deleted file mode 100644
index 05cc3d9..0000000
--- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0003-fix-CVE-2016-7908.patch
+++ /dev/null
@@ -1,62 +0,0 @@
-Upstream-Status: Backport
-
-Backport patch to fix CVE-2016-7908 from:
-
-http://git.qemu.org/?p=qemu.git;a=commit;h=070c4b92b8c
-
-CVE: CVE-2016-7908
-
-Signed-off-by: Kai Kang <kai.kang@windriver.com>
----
-From 070c4b92b8cd5390889716677a0b92444d6e087a Mon Sep 17 00:00:00 2001
-From: Prasad J Pandit <pjp@fedoraproject.org>
-Date: Thu, 22 Sep 2016 16:02:37 +0530
-Subject: [PATCH] net: mcf: limit buffer descriptor count
-
-ColdFire Fast Ethernet Controller uses buffer descriptors to manage
-data flow to/fro receive & transmit queues. While transmitting
-packets, it could continue to read buffer descriptors if a buffer
-descriptor has length of zero and has crafted values in bd.flags.
-Set upper limit to number of buffer descriptors.
-
-Reported-by: Li Qiang <liqiang6-s@360.cn>
-Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
-Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
-Signed-off-by: Jason Wang <jasowang@redhat.com>
----
- hw/net/mcf_fec.c | 5 +++--
- 1 file changed, 3 insertions(+), 2 deletions(-)
-
-diff --git a/hw/net/mcf_fec.c b/hw/net/mcf_fec.c
-index 0ee8ad9..d31fea1 100644
---- a/hw/net/mcf_fec.c
-+++ b/hw/net/mcf_fec.c
-@@ -23,6 +23,7 @@ do { printf("mcf_fec: " fmt , ## __VA_ARGS__); } while (0)
- #define DPRINTF(fmt, ...) do {} while(0)
- #endif
-
-+#define FEC_MAX_DESC 1024
- #define FEC_MAX_FRAME_SIZE 2032
-
- typedef struct {
-@@ -149,7 +150,7 @@ static void mcf_fec_do_tx(mcf_fec_state *s)
- uint32_t addr;
- mcf_fec_bd bd;
- int frame_size;
-- int len;
-+ int len, descnt = 0;
- uint8_t frame[FEC_MAX_FRAME_SIZE];
- uint8_t *ptr;
-
-@@ -157,7 +158,7 @@ static void mcf_fec_do_tx(mcf_fec_state *s)
- ptr = frame;
- frame_size = 0;
- addr = s->tx_descriptor;
-- while (1) {
-+ while (descnt++ < FEC_MAX_DESC) {
- mcf_fec_read_bd(&bd, addr);
- DPRINTF("tx_bd %x flags %04x len %d data %08x\n",
- addr, bd.flags, bd.length, bd.data);
---
-2.9.3
-
diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0004-Add-support-for-VM-suspend-resume-for-TPM-TIS.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0004-Add-support-for-VM-suspend-resume-for-TPM-TIS.patch
new file mode 100644
index 0000000..b8a783d
--- /dev/null
+++ b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0004-Add-support-for-VM-suspend-resume-for-TPM-TIS.patch
@@ -0,0 +1,719 @@
+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, 0,
++ 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, 0,
++ 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, 0,
++ 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/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0004-fix-CVE-2016-7909.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0004-fix-CVE-2016-7909.patch
deleted file mode 100644
index e71bbf6..0000000
--- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/0004-fix-CVE-2016-7909.patch
+++ /dev/null
@@ -1,42 +0,0 @@
-Upstream-Status: Backport [http://git.qemu.org/?p=qemu.git;a=commit;h=34e29ce]
-CVE: CVE-2016-7909
-
-Signed-off-by: Kai Kang <kai.kang@windriver.com>
----
-From 34e29ce754c02bb6b3bdd244fbb85033460feaff Mon Sep 17 00:00:00 2001
-From: Prasad J Pandit <pjp@fedoraproject.org>
-Date: Fri, 30 Sep 2016 00:27:33 +0530
-Subject: [PATCH] net: pcnet: check rx/tx descriptor ring length
-
-The AMD PC-Net II emulator has set of control and status(CSR)
-registers. Of these, CSR76 and CSR78 hold receive and transmit
-descriptor ring length respectively. This ring length could range
-from 1 to 65535. Setting ring length to zero leads to an infinite
-loop in pcnet_rdra_addr() or pcnet_transmit(). Add check to avoid it.
-
-Reported-by: Li Qiang <liqiang6-s@360.cn>
-Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
-Signed-off-by: Jason Wang <jasowang@redhat.com>
----
- hw/net/pcnet.c | 3 +++
- 1 file changed, 3 insertions(+)
-
-diff --git a/hw/net/pcnet.c b/hw/net/pcnet.c
-index 198a01f..3078de8 100644
---- a/hw/net/pcnet.c
-+++ b/hw/net/pcnet.c
-@@ -1429,8 +1429,11 @@ static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value)
- case 47: /* POLLINT */
- case 72:
- case 74:
-+ break;
- case 76: /* RCVRL */
- case 78: /* XMTRL */
-+ val = (val > 0) ? val : 512;
-+ break;
- case 112:
- if (CSR_STOP(s) || CSR_SPND(s))
- break;
---
-2.10.1
-
diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/CVE-2016-9908.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/CVE-2016-9908.patch
new file mode 100644
index 0000000..e0f7a1a
--- /dev/null
+++ b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/CVE-2016-9908.patch
@@ -0,0 +1,44 @@
+From 7139ccbc907441337b4b59cde2c5b5a54cb5b2cc Mon Sep 17 00:00:00 2001
+From: Sona Sarmadi <sona.sarmadi@enea.com>
+
+virtio-gpu: fix information leak in capset get dispatch
+
+In virgl_cmd_get_capset function, it uses g_malloc to allocate
+a response struct to the guest. As the 'resp'struct hasn't been full
+initialized it will lead the 'resp->padding' field to the guest.
+Use g_malloc0 to avoid this.
+
+Signed-off-by: Li Qiang <liqiang6-s@360.cn>
+Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
+Message-id: 58188cae.4a6ec20a.3d2d1.aff2@mx.google.com
+
+[Sona: backported from master to v2.8.0 and resolved conflict]
+
+Reference to upstream patch:
+http://git.qemu-project.org/?p=qemu.git;a=commit;h=85d9d044471f93c48c5c396f7e217b4ef12f69f8
+
+CVE: CVE-2016-9908
+Upstream-Status: Backport
+
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
+---
+ hw/display/virtio-gpu-3d.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/hw/display/virtio-gpu-3d.c b/hw/display/virtio-gpu-3d.c
+index 23f39de..d98b140 100644
+--- a/hw/display/virtio-gpu-3d.c
++++ b/hw/display/virtio-gpu-3d.c
+@@ -371,7 +371,7 @@ static void virgl_cmd_get_capset(VirtIOGPU *g,
+
+ virgl_renderer_get_cap_set(gc.capset_id, &max_ver,
+ &max_size);
+- resp = g_malloc(sizeof(*resp) + max_size);
++ resp = g_malloc0(sizeof(*resp) + max_size);
+
+ resp->hdr.type = VIRTIO_GPU_RESP_OK_CAPSET;
+ virgl_renderer_fill_caps(gc.capset_id,
+--
+1.9.1
+
diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/CVE-2016-9912.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/CVE-2016-9912.patch
new file mode 100644
index 0000000..c009ffd
--- /dev/null
+++ b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/CVE-2016-9912.patch
@@ -0,0 +1,45 @@
+From b8e23926c568f2e963af39028b71c472e3023793 Mon Sep 17 00:00:00 2001
+From: Li Qiang <liq3ea@gmail.com>
+Date: Mon, 28 Nov 2016 21:29:25 -0500
+Subject: [PATCH] virtio-gpu: call cleanup mapping function in resource destroy
+
+If the guest destroy the resource before detach banking, the 'iov'
+and 'addrs' field in resource is not freed thus leading memory
+leak issue. This patch avoid this.
+
+CVE: CVE-2016-9912
+Upstream-Status: Backport
+
+Signed-off-by: Li Qiang <liq3ea@gmail.com>
+Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
+Message-id: 1480386565-10077-1-git-send-email-liq3ea@gmail.com
+Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
+Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
+---
+ hw/display/virtio-gpu.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/hw/display/virtio-gpu.c b/hw/display/virtio-gpu.c
+index ed2b6d3..6a26258 100644
+--- a/hw/display/virtio-gpu.c
++++ b/hw/display/virtio-gpu.c
+@@ -28,6 +28,8 @@
+ static struct virtio_gpu_simple_resource*
+ virtio_gpu_find_resource(VirtIOGPU *g, uint32_t resource_id);
+
++static void virtio_gpu_cleanup_mapping(struct virtio_gpu_simple_resource *res);
++
+ #ifdef CONFIG_VIRGL
+ #include <virglrenderer.h>
+ #define VIRGL(_g, _virgl, _simple, ...) \
+@@ -364,6 +366,7 @@ static void virtio_gpu_resource_destroy(VirtIOGPU *g,
+ struct virtio_gpu_simple_resource *res)
+ {
+ pixman_image_unref(res->image);
++ virtio_gpu_cleanup_mapping(res);
+ QTAILQ_REMOVE(&g->reslist, res, next);
+ g->hostmem -= res->hostmem;
+ g_free(res);
+--
+1.9.1
+
diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/Qemu-Arm-versatilepb-Add-memory-size-checking.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/Qemu-Arm-versatilepb-Add-memory-size-checking.patch
deleted file mode 100644
index 1a6cf51..0000000
--- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/Qemu-Arm-versatilepb-Add-memory-size-checking.patch
+++ /dev/null
@@ -1,46 +0,0 @@
-From 896fa02c24347e6e9259812cfda187b1d6ca6199 Mon Sep 17 00:00:00 2001
-From: Jiang Lu <lu.jiang@windriver.com>
-Date: Wed, 13 Nov 2013 10:38:08 +0800
-Subject: [PATCH] Qemu:Arm:versatilepb: Add memory size checking
-
-The machine can not work with memory over 256M, so add a checking
-at startup. If the memory size exceed 256M, just stop emulation then
-throw out warning about memory limitation.
-
-Upstream-Status: Pending
-
-Signed-off-by: Jiang Lu <lu.jiang@windriver.com>
-
-Updated it on 2014-01-15 for rebasing
-
-Signed-off-by: Robert Yang <liezhi.yang@windriver.com>
-
-Update it when upgrade qemu to 2.2.0
-
-Signed-off-by: Kai Kang <kai.kang@windriver.com>
-Signed-off-by: Cristian Iorga <cristian.iorga@intel.com>
----
- hw/arm/versatilepb.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
-diff --git a/hw/arm/versatilepb.c b/hw/arm/versatilepb.c
-index 6c69f4e..9278d90 100644
---- a/hw/arm/versatilepb.c
-+++ b/hw/arm/versatilepb.c
-@@ -204,6 +204,13 @@ static void versatile_init(MachineState *machine, int board_id)
- exit(1);
- }
-
-+ if (machine->ram_size > (256 << 20)) {
-+ fprintf(stderr,
-+ "qemu: Too much memory for this machine: %d MB, maximum 256 MB\n",
-+ ((unsigned int)ram_size / (1 << 20)));
-+ exit(1);
-+ }
-+
- cpuobj = object_new(object_class_get_name(cpu_oc));
-
- /* By default ARM1176 CPUs have EL3 enabled. This board does not
---
-2.1.0
-
diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/exclude-some-arm-EABI-obsolete-syscalls.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/exclude-some-arm-EABI-obsolete-syscalls.patch
index 171bda7..f593cf9 100644
--- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/exclude-some-arm-EABI-obsolete-syscalls.patch
+++ b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/exclude-some-arm-EABI-obsolete-syscalls.patch
@@ -27,14 +27,14 @@
Signed-off-by: Roy.Li <rongqing.li@windriver.com>
---
- qemu-seccomp.c | 14 ++++++++------
- 1 file changed, 8 insertions(+), 6 deletions(-)
+ qemu-seccomp.c | 13 ++++++++-----
+ 1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/qemu-seccomp.c b/qemu-seccomp.c
-index caa926e..5a78502 100644
+index df75d9c..0e577f8 100644
--- a/qemu-seccomp.c
+++ b/qemu-seccomp.c
-@@ -25,15 +25,21 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = {
+@@ -35,15 +35,21 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = {
{ SCMP_SYS(timer_settime), 255 },
{ SCMP_SYS(timer_gettime), 254 },
{ SCMP_SYS(futex), 253 },
@@ -58,7 +58,7 @@
{ SCMP_SYS(mprotect), 246 },
{ SCMP_SYS(execve), 245 },
{ SCMP_SYS(open), 245 },
-@@ -48,13 +54,11 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = {
+@@ -58,7 +64,6 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = {
{ SCMP_SYS(bind), 245 },
{ SCMP_SYS(listen), 245 },
{ SCMP_SYS(semget), 245 },
@@ -66,13 +66,7 @@
{ SCMP_SYS(gettimeofday), 245 },
{ SCMP_SYS(readlink), 245 },
{ SCMP_SYS(access), 245 },
- { SCMP_SYS(prctl), 245 },
- { SCMP_SYS(signalfd), 245 },
-- { SCMP_SYS(getrlimit), 245 },
- { SCMP_SYS(set_tid_address), 245 },
- { SCMP_SYS(statfs), 245 },
- { SCMP_SYS(unlink), 245 },
-@@ -93,7 +97,6 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = {
+@@ -104,7 +109,6 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = {
{ SCMP_SYS(times), 245 },
{ SCMP_SYS(exit), 245 },
{ SCMP_SYS(clock_gettime), 245 },
@@ -80,7 +74,7 @@
{ SCMP_SYS(restart_syscall), 245 },
{ SCMP_SYS(pwrite64), 245 },
{ SCMP_SYS(nanosleep), 245 },
-@@ -182,7 +185,6 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = {
+@@ -194,7 +198,6 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = {
{ SCMP_SYS(lstat64), 241 },
{ SCMP_SYS(sendfile64), 241 },
{ SCMP_SYS(ugetrlimit), 241 },
@@ -89,5 +83,5 @@
{ SCMP_SYS(rt_sigqueueinfo), 241 },
{ SCMP_SYS(rt_tgsigqueueinfo), 241 },
--
-1.9.1
+2.1.4
diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/glibc-2.25.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/glibc-2.25.patch
new file mode 100644
index 0000000..a6908bd
--- /dev/null
+++ b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/glibc-2.25.patch
@@ -0,0 +1,88 @@
+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 -uNr qemu-2.8.0.orig/include/sysemu/os-posix.h qemu-2.8.0/include/sysemu/os-posix.h
+--- qemu-2.8.0.orig/include/sysemu/os-posix.h 2016-12-20 21:16:48.000000000 +0100
++++ qemu-2.8.0/include/sysemu/os-posix.h 2017-02-21 19:07:18.009090381 +0100
+@@ -34,6 +34,10 @@
+ #include <netdb.h>
+ #include <sys/un.h>
+
++#ifdef CONFIG_SYSMACROS
++#include <sys/sysmacros.h>
++#endif
++
+ void os_set_line_buffering(void);
+ void os_set_proc_name(const char *s);
+ void os_setup_signal_handling(void);
diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/target-ppc-fix-user-mode.patch b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/target-ppc-fix-user-mode.patch
new file mode 100644
index 0000000..ba21e71
--- /dev/null
+++ b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu/target-ppc-fix-user-mode.patch
@@ -0,0 +1,48 @@
+[Qemu-ppc] [PATCH 1/1] target-ppc, tcg: fix usermode segfault with pthread
+
+From: Sam Bobroff
+Subject: [Qemu-ppc] [PATCH 1/1] target-ppc, tcg: fix usermode segfault with pthread_create()
+Date: Mon, 30 Jan 2017 16:08:07 +1100
+Programs run under qemu-ppc64 on an x86_64 host currently segfault
+if they use pthread_create() due to the adjustment made to the NIP in
+commit bd6fefe71cec5a0c7d2be4ac96307f25db56abf9.
+
+This patch changes cpu_loop() to set the NIP back to the
+pre-incremented value before calling do_syscall(), which causes the
+correct address to be used for the new thread and corrects the fault.
+
+Signed-off-by: Sam Bobroff <address@hidden>
+
+Upstream-Status: Backport
+
+---
+
+linux-user/main.c | 4 +++-
+1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/linux-user/main.c b/linux-user/main.c
+index 30049581ef..b5dee01541 100644
+--- a/linux-user/main.c
++++ b/linux-user/main.c
+@@ -1712,18 +1712,20 @@ void cpu_loop(CPUPPCState *env)
+ * in syscalls.
+ */
+ env->crf[0] &= ~0x1;
++ env->nip += 4;
+ ret = do_syscall(env, env->gpr[0], env->gpr[3], env->gpr[4],
+ env->gpr[5], env->gpr[6], env->gpr[7],
+ env->gpr[8], 0, 0);
+ if (ret == -TARGET_ERESTARTSYS) {
++ env->nip -= 4;
+ break;
+ }
+ if (ret == (target_ulong)(-TARGET_QEMU_ESIGRETURN)) {
++ env->nip -= 4;
+ /* Returning from a successful sigreturn syscall.
+ Avoid corrupting register state. */
+ break;
+ }
+- env->nip += 4;
+ if (ret > (target_ulong)(-515)) {
+ env->crf[0] |= 0x1;
+ ret = -ret;
diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu_2.7.0.bb b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu_2.7.0.bb
deleted file mode 100644
index 85aadec..0000000
--- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu_2.7.0.bb
+++ /dev/null
@@ -1,28 +0,0 @@
-require qemu.inc
-
-LIC_FILES_CHKSUM = "file://COPYING;md5=441c28d2cf86e15a37fa47e15a72fbac \
- file://COPYING.LIB;endline=24;md5=c04def7ae38850e7d3ef548588159913"
-
-SRC_URI += "file://configure-fix-Darwin-target-detection.patch \
- file://qemu-enlarge-env-entry-size.patch \
- file://Qemu-Arm-versatilepb-Add-memory-size-checking.patch \
- file://no-valgrind.patch \
- file://pathlimit.patch \
- file://qemu-2.5.0-cflags.patch \
- file://0001-virtio-zero-vq-inuse-in-virtio_reset.patch \
- file://0002-fix-CVE-2016-7423.patch \
- file://0003-fix-CVE-2016-7908.patch \
- file://0004-fix-CVE-2016-7909.patch \
- file://04b33e21866412689f18b7ad6daf0a54d8f959a7.patch \
-"
-
-SRC_URI_prepend = "http://wiki.qemu-project.org/download/${BP}.tar.bz2"
-SRC_URI[md5sum] = "08d4d06d1cb598efecd796137f4844ab"
-SRC_URI[sha256sum] = "326e739506ba690daf69fc17bd3913a6c313d9928d743bd8eddb82f403f81e53"
-
-COMPATIBLE_HOST_class-target_mips64 = "null"
-
-do_install_append() {
- # Prevent QA warnings about installed ${localstatedir}/run
- if [ -d ${D}${localstatedir}/run ]; then rmdir ${D}${localstatedir}/run; fi
-}
diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu_2.8.0.bb b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu_2.8.0.bb
new file mode 100644
index 0000000..fa70009
--- /dev/null
+++ b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemu_2.8.0.bb
@@ -0,0 +1,65 @@
+require qemu.inc
+
+inherit ptest
+
+RDEPENDS_${PN}-ptest = "bash make"
+
+LIC_FILES_CHKSUM = "file://COPYING;md5=441c28d2cf86e15a37fa47e15a72fbac \
+ file://COPYING.LIB;endline=24;md5=c04def7ae38850e7d3ef548588159913"
+
+SRC_URI += " \
+ file://powerpc_rom.bin \
+ file://disable-grabs.patch \
+ file://exclude-some-arm-EABI-obsolete-syscalls.patch \
+ file://wacom.patch \
+ file://add-ptest-in-makefile.patch \
+ file://run-ptest \
+ file://configure-fix-Darwin-target-detection.patch \
+ file://qemu-enlarge-env-entry-size.patch \
+ file://no-valgrind.patch \
+ file://pathlimit.patch \
+ file://qemu-2.5.0-cflags.patch \
+ file://target-ppc-fix-user-mode.patch \
+ file://glibc-2.25.patch \
+ file://04b33e21866412689f18b7ad6daf0a54d8f959a7.patch \
+"
+
+SRC_URI += " \
+ file://0001-Provide-support-for-the-CUSE-TPM.patch \
+ file://0002-Introduce-condition-to-notify-waiters-of-completed-c.patch \
+ file://0003-Introduce-condition-in-TPM-backend-for-notification.patch \
+ file://0004-Add-support-for-VM-suspend-resume-for-TPM-TIS.patch \
+ file://CVE-2016-9908.patch \
+ file://CVE-2016-9912.patch \
+"
+
+SRC_URI_append_class-native = " \
+ file://fix-libcap-header-issue-on-some-distro.patch \
+ file://cpus.c-qemu_cpu_kick_thread_debugging.patch \
+ "
+
+SRC_URI =+ "http://wiki.qemu-project.org/download/${BP}.tar.bz2"
+
+SRC_URI[md5sum] = "17940dce063b6ce450a12e719a6c9c43"
+SRC_URI[sha256sum] = "dafd5d7f649907b6b617b822692f4c82e60cf29bc0fc58bc2036219b591e5e62"
+
+COMPATIBLE_HOST_mipsarchn32 = "null"
+COMPATIBLE_HOST_mipsarchn64 = "null"
+
+do_install_append() {
+ # Prevent QA warnings about installed ${localstatedir}/run
+ if [ -d ${D}${localstatedir}/run ]; then rmdir ${D}${localstatedir}/run; fi
+ install -Dm 0755 ${WORKDIR}/powerpc_rom.bin ${D}${datadir}/qemu
+}
+
+do_compile_ptest() {
+ make buildtest-TESTS
+}
+
+do_install_ptest() {
+ cp -rL ${B}/tests ${D}${PTEST_PATH}
+ find ${D}${PTEST_PATH}/tests -type f -name "*.[Sshcod]" | xargs -i rm -rf {}
+
+ cp ${S}/tests/Makefile.include ${D}${PTEST_PATH}/tests
+}
+
diff --git a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemuwrapper-cross_1.0.bb b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemuwrapper-cross_1.0.bb
index 53b302d..e40cdaf 100644
--- a/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemuwrapper-cross_1.0.bb
+++ b/import-layers/yocto-poky/meta/recipes-devtools/qemu/qemuwrapper-cross_1.0.bb
@@ -1,11 +1,14 @@
SUMMARY = "QEMU wrapper script"
LICENSE = "MIT"
-LIC_FILES_CHKSUM = "file://${COREBASE}/meta/COPYING.MIT;md5=3da9cfbcb788c80a0384361b4de20420"
S = "${WORKDIR}"
+DEPENDS += "qemu-native"
+
inherit qemu
+do_populate_sysroot[depends] = ""
+
do_install () {
install -d ${D}${bindir_crossscripts}/