aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitmodules3
-rw-r--r--Makefile6
-rw-r--r--backends/Makefile.objs5
-rwxr-xr-xconfigure102
-rw-r--r--default-configs/virtio.mak4
-rw-r--r--hw/mem/pc-dimm.c4
-rw-r--r--hw/net/Makefile.objs4
-rw-r--r--hw/net/vhost_net-stub.c92
-rw-r--r--hw/net/vhost_net.c85
-rw-r--r--hw/pci/pcie.c13
-rw-r--r--hw/smbios/smbios.c1
-rw-r--r--hw/vfio/pci-quirks.c2
-rw-r--r--hw/virtio/Makefile.objs8
-rw-r--r--hw/virtio/vhost-backend.c12
-rw-r--r--hw/virtio/vhost-user.c13
-rw-r--r--hw/virtio/vhost.c2
-rw-r--r--hw/virtio/virtio-balloon.c102
-rw-r--r--include/exec/poison.h1
-rw-r--r--include/hw/firmware/smbios.h1
-rw-r--r--include/hw/pci/pci_ids.h2
-rw-r--r--include/hw/virtio/virtio-balloon.h3
-rw-r--r--net/Makefile.objs4
-rw-r--r--net/net.c2
-rw-r--r--net/vhost-user-stub.c23
-rw-r--r--net/vhost-user.c13
-rw-r--r--roms/Makefile13
m---------roms/edk20
-rw-r--r--tests/Makefile.include5
-rw-r--r--tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2bin0 -> 11776 bytes
-rw-r--r--tests/data/uefi-boot-images/bios-tables-test.arm.iso.qcow2bin0 -> 11776 bytes
-rw-r--r--tests/data/uefi-boot-images/bios-tables-test.i386.iso.qcow2bin0 -> 12800 bytes
-rw-r--r--tests/data/uefi-boot-images/bios-tables-test.x86_64.iso.qcow2bin0 -> 13312 bytes
-rw-r--r--tests/uefi-test-tools/.gitignore3
-rw-r--r--tests/uefi-test-tools/LICENSE25
-rw-r--r--tests/uefi-test-tools/Makefile106
-rw-r--r--tests/uefi-test-tools/UefiTestToolsPkg/BiosTablesTest/BiosTablesTest.c130
-rw-r--r--tests/uefi-test-tools/UefiTestToolsPkg/BiosTablesTest/BiosTablesTest.inf41
-rw-r--r--tests/uefi-test-tools/UefiTestToolsPkg/Include/Guid/BiosTablesTest.h67
-rw-r--r--tests/uefi-test-tools/UefiTestToolsPkg/UefiTestToolsPkg.dec27
-rw-r--r--tests/uefi-test-tools/UefiTestToolsPkg/UefiTestToolsPkg.dsc69
-rwxr-xr-xtests/uefi-test-tools/build.sh145
-rw-r--r--tests/vhost-user-test.c160
42 files changed, 1050 insertions, 248 deletions
diff --git a/.gitmodules b/.gitmodules
index 6b91176098..ceafb0ee29 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -49,3 +49,6 @@
[submodule "tests/fp/berkeley-softfloat-3"]
path = tests/fp/berkeley-softfloat-3
url = https://github.com/cota/berkeley-softfloat-3
+[submodule "roms/edk2"]
+ path = roms/edk2
+ url = https://github.com/tianocore/edk2.git
diff --git a/Makefile b/Makefile
index 7fa04e0821..2208bde419 100644
--- a/Makefile
+++ b/Makefile
@@ -609,7 +609,11 @@ clean:
rm -f config.mak op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
rm -f qemu-options.def
rm -f *.msi
- find . \( -name '*.so' -o -name '*.dll' -o -name '*.mo' -o -name '*.[oda]' \) -type f -exec rm {} +
+ find . \( -name '*.so' -o -name '*.dll' -o -name '*.mo' -o -name '*.[oda]' \) -type f \
+ ! -path ./roms/edk2/ArmPkg/Library/GccLto/liblto-aarch64.a \
+ ! -path ./roms/edk2/ArmPkg/Library/GccLto/liblto-arm.a \
+ ! -path ./roms/edk2/BaseTools/Source/Python/UPT/Dll/sqlite3.dll \
+ -exec rm {} +
rm -f $(filter-out %.tlb,$(TOOLS)) $(HELPERS-y) qemu-ga TAGS cscope.* *.pod *~ */*~
rm -f fsdev/*.pod scsi/*.pod
rm -f qemu-img-cmds.h
diff --git a/backends/Makefile.objs b/backends/Makefile.objs
index 717fcbdae4..ff619d31b4 100644
--- a/backends/Makefile.objs
+++ b/backends/Makefile.objs
@@ -9,10 +9,9 @@ common-obj-$(CONFIG_POSIX) += hostmem-file.o
common-obj-y += cryptodev.o
common-obj-y += cryptodev-builtin.o
-ifeq ($(CONFIG_VIRTIO),y)
+ifeq ($(CONFIG_VIRTIO_CRYPTO),y)
common-obj-y += cryptodev-vhost.o
-common-obj-$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX)) += \
- cryptodev-vhost-user.o
+common-obj-$(CONFIG_VHOST_CRYPTO) += cryptodev-vhost-user.o
endif
common-obj-$(CONFIG_LINUX) += hostmem-memfd.o
diff --git a/configure b/configure
index 540bee19ba..cefeb8fcce 100755
--- a/configure
+++ b/configure
@@ -368,10 +368,10 @@ libattr=""
xfs=""
tcg="yes"
membarrier=""
-vhost_net="no"
-vhost_crypto="no"
-vhost_scsi="no"
-vhost_vsock="no"
+vhost_net=""
+vhost_crypto=""
+vhost_scsi=""
+vhost_vsock=""
vhost_user=""
kvm="no"
hax="no"
@@ -783,6 +783,7 @@ case $targetos in
MINGW32*)
mingw32="yes"
hax="yes"
+ vhost_user="no"
audio_possible_drivers="dsound sdl"
if check_include dsound.h; then
audio_drv_list="dsound"
@@ -884,10 +885,6 @@ Linux)
linux="yes"
linux_user="yes"
kvm="yes"
- vhost_net="yes"
- vhost_crypto="yes"
- vhost_scsi="yes"
- vhost_vsock="yes"
QEMU_INCLUDES="-I\$(SRC_PATH)/linux-headers -I$PWD/linux-headers $QEMU_INCLUDES"
supported_os="yes"
libudev="yes"
@@ -1263,11 +1260,7 @@ for opt do
;;
--disable-vhost-crypto) vhost_crypto="no"
;;
- --enable-vhost-crypto)
- vhost_crypto="yes"
- if test "$mingw32" = "yes"; then
- error_exit "vhost-crypto isn't available on win32"
- fi
+ --enable-vhost-crypto) vhost_crypto="yes"
;;
--disable-vhost-scsi) vhost_scsi="no"
;;
@@ -1476,11 +1469,11 @@ for opt do
;;
--disable-vhost-user) vhost_user="no"
;;
- --enable-vhost-user)
- vhost_user="yes"
- if test "$mingw32" = "yes"; then
- error_exit "vhost-user isn't available on win32"
- fi
+ --enable-vhost-user) vhost_user="yes"
+ ;;
+ --disable-vhost-kernel) vhost_kernel="no"
+ ;;
+ --enable-vhost-kernel) vhost_kernel="yes"
;;
--disable-capstone) capstone="no"
;;
@@ -1512,14 +1505,6 @@ for opt do
esac
done
-if test "$vhost_user" = ""; then
- if test "$mingw32" = "yes"; then
- vhost_user="no"
- else
- vhost_user="yes"
- fi
-fi
-
case "$cpu" in
ppc)
CPU_CFLAGS="-m32"
@@ -1743,8 +1728,12 @@ disabled with --disable-FEATURE, default is enabled if available:
linux-aio Linux AIO support
cap-ng libcap-ng support
attr attr and xattr support
- vhost-net vhost-net acceleration support
- vhost-crypto vhost-crypto acceleration support
+ vhost-net vhost-net kernel acceleration support
+ vhost-vsock virtio sockets device support
+ vhost-scsi vhost-scsi kernel target support
+ vhost-crypto vhost-user-crypto backend support
+ vhost-kernel vhost kernel backend support
+ vhost-user vhost-user backend support
spice spice
rbd rados block device (rbd)
libiscsi iscsi support
@@ -1770,7 +1759,6 @@ disabled with --disable-FEATURE, default is enabled if available:
jemalloc jemalloc support
avx2 AVX2 optimization support
replication replication support
- vhost-vsock virtio sockets device support
opengl opengl support
virglrenderer virgl rendering support
xfsctl xfsctl support
@@ -1787,7 +1775,6 @@ disabled with --disable-FEATURE, default is enabled if available:
parallels parallels image format support
sheepdog sheepdog block driver support
crypto-afalg Linux AF_ALG crypto backend driver
- vhost-user vhost-user support
capstone capstone disassembler support
debug-mutex mutex debugging support
libpmem libpmem support
@@ -2177,6 +2164,45 @@ else
l2tpv3=no
fi
+#########################################
+# vhost interdependencies and host support
+
+# vhost backends
+test "$vhost_user" = "" && vhost_user=yes
+if test "$vhost_user" = "yes" && test "$mingw32" = "yes"; then
+ error_exit "vhost-user isn't available on win32"
+fi
+test "$vhost_kernel" = "" && vhost_kernel=$linux
+if test "$vhost_kernel" = "yes" && test "$linux" != "yes"; then
+ error_exit "vhost-kernel is only available on Linux"
+fi
+
+# vhost-kernel devices
+test "$vhost_scsi" = "" && vhost_scsi=$vhost_kernel
+if test "$vhost_scsi" = "yes" && test "$vhost_kernel" != "yes"; then
+ error_exit "--enable-vhost-scsi requires --enable-vhost-kernel"
+fi
+test "$vhost_vsock" = "" && vhost_vsock=$vhost_kernel
+if test "$vhost_vsock" = "yes" && test "$vhost_kernel" != "yes"; then
+ error_exit "--enable-vhost-vsock requires --enable-vhost-kernel"
+fi
+
+# vhost-user backends
+test "$vhost_net_user" = "" && vhost_net_user=$vhost_user
+if test "$vhost_net_user" = "yes" && test "$vhost_user" = "no"; then
+ error_exit "--enable-vhost-net-user requires --enable-vhost-user"
+fi
+test "$vhost_crypto" = "" && vhost_crypto=$vhost_user
+if test "$vhost_crypto" = "yes" && test "$vhost_user" = "no"; then
+ error_exit "--enable-vhost-crypto requires --enable-vhost-user"
+fi
+
+# OR the vhost-kernel and vhost-user values for simplicity
+if test "$vhost_net" = ""; then
+ test "$vhost_net_user" = "yes" && vhost_net=yes
+ test "$vhost_kernel" = "yes" && vhost_net=yes
+fi
+
##########################################
# MinGW / Mingw-w64 localtime_r/gmtime_r check
@@ -6622,8 +6648,11 @@ fi
if test "$vhost_scsi" = "yes" ; then
echo "CONFIG_VHOST_SCSI=y" >> $config_host_mak
fi
-if test "$vhost_net" = "yes" && test "$vhost_user" = "yes"; then
- echo "CONFIG_VHOST_NET_USED=y" >> $config_host_mak
+if test "$vhost_net" = "yes" ; then
+ echo "CONFIG_VHOST_NET=y" >> $config_host_mak
+fi
+if test "$vhost_net_user" = "yes" ; then
+ echo "CONFIG_VHOST_NET_USER=y" >> $config_host_mak
fi
if test "$vhost_crypto" = "yes" ; then
echo "CONFIG_VHOST_CRYPTO=y" >> $config_host_mak
@@ -6631,6 +6660,9 @@ fi
if test "$vhost_vsock" = "yes" ; then
echo "CONFIG_VHOST_VSOCK=y" >> $config_host_mak
fi
+if test "$vhost_kernel" = "yes" ; then
+ echo "CONFIG_VHOST_KERNEL=y" >> $config_host_mak
+fi
if test "$vhost_user" = "yes" ; then
echo "CONFIG_VHOST_USER=y" >> $config_host_mak
fi
@@ -7401,12 +7433,6 @@ if supported_xen_target $target; then
fi
if supported_kvm_target $target; then
echo "CONFIG_KVM=y" >> $config_target_mak
- if test "$vhost_net" = "yes" ; then
- echo "CONFIG_VHOST_NET=y" >> $config_target_mak
- if test "$vhost_user" = "yes" ; then
- echo "CONFIG_VHOST_USER_NET_TEST_$target_name=y" >> $config_host_mak
- fi
- fi
fi
if supported_hax_target $target; then
echo "CONFIG_HAX=y" >> $config_target_mak
diff --git a/default-configs/virtio.mak b/default-configs/virtio.mak
index ecb4420e74..b653aa06b1 100644
--- a/default-configs/virtio.mak
+++ b/default-configs/virtio.mak
@@ -1,5 +1,5 @@
-CONFIG_VHOST_USER_SCSI=$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX))
-CONFIG_VHOST_USER_BLK=$(call land,$(CONFIG_VHOST_USER),$(CONFIG_LINUX))
+CONFIG_VHOST_USER_SCSI=$(CONFIG_VHOST_USER)
+CONFIG_VHOST_USER_BLK=$(CONFIG_VHOST_USER)
CONFIG_VIRTIO=y
CONFIG_VIRTIO_9P=$(CONFIG_VIRTFS)
CONFIG_VIRTIO_BALLOON=y
diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
index 0c9b9e8292..152400b1fc 100644
--- a/hw/mem/pc-dimm.c
+++ b/hw/mem/pc-dimm.c
@@ -204,9 +204,7 @@ static MemoryRegion *pc_dimm_get_memory_region(PCDIMMDevice *dimm, Error **errp)
static uint64_t pc_dimm_md_get_addr(const MemoryDeviceState *md)
{
- const PCDIMMDevice *dimm = PC_DIMM(md);
-
- return dimm->addr;
+ return object_property_get_uint(OBJECT(md), PC_DIMM_ADDR_PROP, &error_abort);
}
static void pc_dimm_md_set_addr(MemoryDeviceState *md, uint64_t addr,
diff --git a/hw/net/Makefile.objs b/hw/net/Makefile.objs
index a43351aa04..ea63715780 100644
--- a/hw/net/Makefile.objs
+++ b/hw/net/Makefile.objs
@@ -37,7 +37,9 @@ obj-$(CONFIG_PSERIES) += spapr_llan.o
obj-$(CONFIG_XILINX_ETHLITE) += xilinx_ethlite.o
obj-$(CONFIG_VIRTIO_NET) += virtio-net.o
-obj-y += vhost_net.o
+common-obj-$(call land,$(CONFIG_VIRTIO_NET),$(CONFIG_VHOST_NET)) += vhost_net.o
+common-obj-$(call lnot,$(call land,$(CONFIG_VIRTIO_NET),$(CONFIG_VHOST_NET))) += vhost_net-stub.o
+common-obj-$(CONFIG_ALL) += vhost_net-stub.o
obj-$(CONFIG_ETSEC) += fsl_etsec/etsec.o fsl_etsec/registers.o \
fsl_etsec/rings.o fsl_etsec/miim.o
diff --git a/hw/net/vhost_net-stub.c b/hw/net/vhost_net-stub.c
new file mode 100644
index 0000000000..aac0e98228
--- /dev/null
+++ b/hw/net/vhost_net-stub.c
@@ -0,0 +1,92 @@
+/*
+ * vhost-net support
+ *
+ * Copyright Red Hat, Inc. 2010
+ *
+ * Authors:
+ * Michael S. Tsirkin <mst@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "net/net.h"
+#include "net/tap.h"
+#include "net/vhost-user.h"
+
+#include "hw/virtio/virtio-net.h"
+#include "net/vhost_net.h"
+#include "qemu/error-report.h"
+
+
+uint64_t vhost_net_get_max_queues(VHostNetState *net)
+{
+ return 1;
+}
+
+struct vhost_net *vhost_net_init(VhostNetOptions *options)
+{
+ error_report("vhost-net support is not compiled in");
+ return NULL;
+}
+
+int vhost_net_start(VirtIODevice *dev,
+ NetClientState *ncs,
+ int total_queues)
+{
+ return -ENOSYS;
+}
+void vhost_net_stop(VirtIODevice *dev,
+ NetClientState *ncs,
+ int total_queues)
+{
+}
+
+void vhost_net_cleanup(struct vhost_net *net)
+{
+}
+
+uint64_t vhost_net_get_features(struct vhost_net *net, uint64_t features)
+{
+ return features;
+}
+
+void vhost_net_ack_features(struct vhost_net *net, uint64_t features)
+{
+}
+
+uint64_t vhost_net_get_acked_features(VHostNetState *net)
+{
+ return 0;
+}
+
+bool vhost_net_virtqueue_pending(VHostNetState *net, int idx)
+{
+ return false;
+}
+
+void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev,
+ int idx, bool mask)
+{
+}
+
+int vhost_net_notify_migration_done(struct vhost_net *net, char* mac_addr)
+{
+ return -1;
+}
+
+VHostNetState *get_vhost_net(NetClientState *nc)
+{
+ return 0;
+}
+
+int vhost_set_vring_enable(NetClientState *nc, int enable)
+{
+ return 0;
+}
+
+int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu)
+{
+ return 0;
+}
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index e037db63a3..be3cc88370 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -18,17 +18,13 @@
#include "net/tap.h"
#include "net/vhost-user.h"
+#include "standard-headers/linux/vhost_types.h"
#include "hw/virtio/virtio-net.h"
#include "net/vhost_net.h"
#include "qemu/error-report.h"
-#ifdef CONFIG_VHOST_NET
-#include <linux/vhost.h>
#include <sys/socket.h>
-#include <linux/kvm.h>
-#include <netpacket/packet.h>
-#include <net/ethernet.h>
#include <net/if.h>
#include <netinet/in.h>
@@ -136,7 +132,7 @@ static int vhost_net_get_fd(NetClientState *backend)
return tap_get_fd(backend);
default:
fprintf(stderr, "vhost-net requires tap backend\n");
- return -EBADFD;
+ return -ENOSYS;
}
}
@@ -194,6 +190,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
}
/* Set sane init value. Override when guest acks. */
+#ifdef CONFIG_VHOST_NET_USER
if (net->nc->info->type == NET_CLIENT_DRIVER_VHOST_USER) {
features = vhost_user_get_acked_features(net->nc);
if (~net->dev.features & features) {
@@ -203,6 +200,7 @@ struct vhost_net *vhost_net_init(VhostNetOptions *options)
goto fail;
}
}
+#endif
vhost_net_ack_features(net, features);
@@ -414,10 +412,12 @@ VHostNetState *get_vhost_net(NetClientState *nc)
case NET_CLIENT_DRIVER_TAP:
vhost_net = tap_get_vhost_net(nc);
break;
+#ifdef CONFIG_VHOST_NET_USER
case NET_CLIENT_DRIVER_VHOST_USER:
vhost_net = vhost_user_get_vhost_net(nc);
assert(vhost_net);
break;
+#endif
default:
break;
}
@@ -449,76 +449,3 @@ int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu)
return vhost_ops->vhost_net_set_mtu(&net->dev, mtu);
}
-
-#else
-uint64_t vhost_net_get_max_queues(VHostNetState *net)
-{
- return 1;
-}
-
-struct vhost_net *vhost_net_init(VhostNetOptions *options)
-{
- error_report("vhost-net support is not compiled in");
- return NULL;
-}
-
-int vhost_net_start(VirtIODevice *dev,
- NetClientState *ncs,
- int total_queues)
-{
- return -ENOSYS;
-}
-void vhost_net_stop(VirtIODevice *dev,
- NetClientState *ncs,
- int total_queues)
-{
-}
-
-void vhost_net_cleanup(struct vhost_net *net)
-{
-}
-
-uint64_t vhost_net_get_features(struct vhost_net *net, uint64_t features)
-{
- return features;
-}
-
-void vhost_net_ack_features(struct vhost_net *net, uint64_t features)
-{
-}
-
-uint64_t vhost_net_get_acked_features(VHostNetState *net)
-{
- return 0;
-}
-
-bool vhost_net_virtqueue_pending(VHostNetState *net, int idx)
-{
- return false;
-}
-
-void vhost_net_virtqueue_mask(VHostNetState *net, VirtIODevice *dev,
- int idx, bool mask)
-{
-}
-
-int vhost_net_notify_migration_done(struct vhost_net *net, char* mac_addr)
-{
- return -1;
-}
-
-VHostNetState *get_vhost_net(NetClientState *nc)
-{
- return 0;
-}
-
-int vhost_set_vring_enable(NetClientState *nc, int enable)
-{
- return 0;
-}
-
-int vhost_net_set_mtu(struct vhost_net *net, uint16_t mtu)
-{
- return 0;
-}
-#endif
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index 3f7c366093..3618d6ab2e 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -834,9 +834,12 @@ void pcie_add_capability(PCIDevice *dev,
/*
* Sync the PCIe Link Status negotiated speed and width of a bridge with the
* downstream device. If downstream device is not present, re-write with the
- * Link Capability fields. Limit width and speed to bridge capabilities for
- * compatibility. Use config_read to access the downstream device since it
- * could be an assigned device with volatile link information.
+ * Link Capability fields. If downstream device reports invalid width or
+ * speed, replace with minimum values (LnkSta fields are RsvdZ on VFs but such
+ * values interfere with PCIe native hotplug detecting new devices). Limit
+ * width and speed to bridge capabilities for compatibility. Use config_read
+ * to access the downstream device since it could be an assigned device with
+ * volatile link information.
*/
void pcie_sync_bridge_lnk(PCIDevice *bridge_dev)
{
@@ -856,11 +859,15 @@ void pcie_sync_bridge_lnk(PCIDevice *bridge_dev)
if ((lnksta & PCI_EXP_LNKSTA_NLW) > (lnkcap & PCI_EXP_LNKCAP_MLW)) {
lnksta &= ~PCI_EXP_LNKSTA_NLW;
lnksta |= lnkcap & PCI_EXP_LNKCAP_MLW;
+ } else if (!(lnksta & PCI_EXP_LNKSTA_NLW)) {
+ lnksta |= QEMU_PCI_EXP_LNKSTA_NLW(QEMU_PCI_EXP_LNK_X1);
}
if ((lnksta & PCI_EXP_LNKSTA_CLS) > (lnkcap & PCI_EXP_LNKCAP_SLS)) {
lnksta &= ~PCI_EXP_LNKSTA_CLS;
lnksta |= lnkcap & PCI_EXP_LNKCAP_SLS;
+ } else if (!(lnksta & PCI_EXP_LNKSTA_CLS)) {
+ lnksta |= QEMU_PCI_EXP_LNKSTA_CLS(QEMU_PCI_EXP_LNK_2_5GT);
}
}
diff --git a/hw/smbios/smbios.c b/hw/smbios/smbios.c
index 818be8a838..47be9071fa 100644
--- a/hw/smbios/smbios.c
+++ b/hw/smbios/smbios.c
@@ -563,6 +563,7 @@ static void smbios_build_type_3_table(void)
t->height = 0;
t->number_of_power_cords = 0;
t->contained_element_count = 0;
+ t->contained_element_record_length = 0;
SMBIOS_TABLE_SET_STR(3, sku_number_str, type3.sku);
SMBIOS_BUILD_TABLE_POST;
diff --git a/hw/vfio/pci-quirks.c b/hw/vfio/pci-quirks.c
index eae31c74d6..40a12001f5 100644
--- a/hw/vfio/pci-quirks.c
+++ b/hw/vfio/pci-quirks.c
@@ -526,8 +526,6 @@ static void vfio_probe_ati_bar2_quirk(VFIOPCIDevice *vdev, int nr)
* note it for future reference.
*/
-#define PCI_VENDOR_ID_NVIDIA 0x10de
-
/*
* Nvidia has several different methods to get to config space, the
* nouveu project has several of these documented here:
diff --git a/hw/virtio/Makefile.objs b/hw/virtio/Makefile.objs
index d335dd0a6a..a3eb8ed866 100644
--- a/hw/virtio/Makefile.objs
+++ b/hw/virtio/Makefile.objs
@@ -2,15 +2,18 @@ ifeq ($(CONFIG_VIRTIO),y)
common-obj-y += virtio-bus.o
obj-y += virtio.o
+obj-$(call lor,$(CONFIG_VHOST_USER),$(CONFIG_VHOST_KERNEL)) += vhost.o vhost-backend.o
+common-obj-$(call lnot,$(call lor,$(CONFIG_VHOST_USER),$(CONFIG_VHOST_KERNEL))) += vhost-stub.o
+obj-$(CONFIG_VHOST_USER) += vhost-user.o
+
common-obj-$(CONFIG_VIRTIO_RNG) += virtio-rng.o
common-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
common-obj-$(CONFIG_VIRTIO_MMIO) += virtio-mmio.o
obj-$(CONFIG_VIRTIO_BALLOON) += virtio-balloon.o
obj-$(CONFIG_VIRTIO_CRYPTO) += virtio-crypto.o
obj-$(call land,$(CONFIG_VIRTIO_CRYPTO),$(CONFIG_VIRTIO_PCI)) += virtio-crypto-pci.o
-
-obj-$(CONFIG_LINUX) += vhost.o vhost-backend.o vhost-user.o
obj-$(CONFIG_VHOST_VSOCK) += vhost-vsock.o
+
ifeq ($(CONFIG_VIRTIO_PCI),y)
obj-$(CONFIG_VHOST_VSOCK) += vhost-vsock-pci.o
obj-$(CONFIG_VHOST_USER_BLK) += vhost-user-blk-pci.o
@@ -28,5 +31,4 @@ obj-$(CONFIG_VIRTIO_SERIAL) += virtio-serial-pci.o
endif
endif
-common-obj-$(call lnot,$(call land,$(CONFIG_VIRTIO),$(CONFIG_LINUX))) += vhost-stub.o
common-obj-$(CONFIG_ALL) += vhost-stub.o
diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c
index 7f09efab8b..96b8d3c95d 100644
--- a/hw/virtio/vhost-backend.c
+++ b/hw/virtio/vhost-backend.c
@@ -9,11 +9,14 @@
*/
#include "qemu/osdep.h"
-#include <linux/vhost.h>
-#include <sys/ioctl.h>
#include "hw/virtio/vhost.h"
#include "hw/virtio/vhost-backend.h"
#include "qemu/error-report.h"
+#include "standard-headers/linux/vhost_types.h"
+
+#ifdef CONFIG_VHOST_KERNEL
+#include <linux/vhost.h>
+#include <sys/ioctl.h>
static int vhost_kernel_call(struct vhost_dev *dev, unsigned long int request,
void *arg)
@@ -265,18 +268,23 @@ static const VhostOps kernel_ops = {
.vhost_set_iotlb_callback = vhost_kernel_set_iotlb_callback,
.vhost_send_device_iotlb_msg = vhost_kernel_send_device_iotlb_msg,
};
+#endif
int vhost_set_backend_type(struct vhost_dev *dev, VhostBackendType backend_type)
{
int r = 0;
switch (backend_type) {
+#ifdef CONFIG_VHOST_KERNEL
case VHOST_BACKEND_TYPE_KERNEL:
dev->vhost_ops = &kernel_ops;
break;
+#endif
+#ifdef CONFIG_VHOST_USER
case VHOST_BACKEND_TYPE_USER:
dev->vhost_ops = &user_ops;
break;
+#endif
default:
error_report("Unknown vhost backend type");
r = -1;
diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c
index 564a31d12c..0d6c64e5ca 100644
--- a/hw/virtio/vhost-user.c
+++ b/hw/virtio/vhost-user.c
@@ -27,8 +27,12 @@
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/un.h>
-#include <linux/vhost.h>
+
+#include "standard-headers/linux/vhost_types.h"
+
+#ifdef CONFIG_LINUX
#include <linux/userfaultfd.h>
+#endif
#define VHOST_MEMORY_MAX_NREGIONS 8
#define VHOST_USER_F_PROTOCOL_FEATURES 30
@@ -1110,6 +1114,7 @@ out:
return ret;
}
+#ifdef CONFIG_LINUX
/*
* Called back from the postcopy fault thread when a fault is received on our
* ufd.
@@ -1177,6 +1182,7 @@ static int vhost_user_postcopy_waker(struct PostCopyFD *pcfd, RAMBlock *rb,
trace_vhost_user_postcopy_waker_nomatch(qemu_ram_get_idstr(rb), offset);
return 0;
}
+#endif
/*
* Called at the start of an inbound postcopy on reception of the
@@ -1184,6 +1190,7 @@ static int vhost_user_postcopy_waker(struct PostCopyFD *pcfd, RAMBlock *rb,
*/
static int vhost_user_postcopy_advise(struct vhost_dev *dev, Error **errp)
{
+#ifdef CONFIG_LINUX
struct vhost_user *u = dev->opaque;
CharBackend *chr = u->user->chr;
int ufd;
@@ -1227,6 +1234,10 @@ static int vhost_user_postcopy_advise(struct vhost_dev *dev, Error **errp)
u->postcopy_fd.idstr = "vhost-user"; /* Need to find unique name */
postcopy_register_shared_ufd(&u->postcopy_fd);
return 0;
+#else
+ error_setg(errp, "Postcopy not supported on non-Linux systems");
+ return -1;
+#endif
}
/*
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index 569c4053ea..311432f190 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -21,7 +21,7 @@
#include "qemu/range.h"
#include "qemu/error-report.h"
#include "qemu/memfd.h"
-#include <linux/vhost.h>
+#include "standard-headers/linux/vhost_types.h"
#include "exec/address-spaces.h"
#include "hw/virtio/virtio-bus.h"
#include "hw/virtio/virtio-access.h"
diff --git a/hw/virtio/virtio-balloon.c b/hw/virtio/virtio-balloon.c
index a12677d4d5..d3f2913a85 100644
--- a/hw/virtio/virtio-balloon.c
+++ b/hw/virtio/virtio-balloon.c
@@ -33,11 +33,81 @@
#define BALLOON_PAGE_SIZE (1 << VIRTIO_BALLOON_PFN_SHIFT)
-static void balloon_page(void *addr, int deflate)
+struct PartiallyBalloonedPage {
+ RAMBlock *rb;
+ ram_addr_t base;
+ unsigned long bitmap[];
+};
+
+static void balloon_inflate_page(VirtIOBalloon *balloon,
+ MemoryRegion *mr, hwaddr offset)
{
- if (!qemu_balloon_is_inhibited()) {
- qemu_madvise(addr, BALLOON_PAGE_SIZE,
- deflate ? QEMU_MADV_WILLNEED : QEMU_MADV_DONTNEED);
+ void *addr = memory_region_get_ram_ptr(mr) + offset;
+ RAMBlock *rb;
+ size_t rb_page_size;
+ int subpages;
+ ram_addr_t ram_offset, host_page_base;
+
+ /* XXX is there a better way to get to the RAMBlock than via a
+ * host address? */
+ rb = qemu_ram_block_from_host(addr, false, &ram_offset);
+ rb_page_size = qemu_ram_pagesize(rb);
+ host_page_base = ram_offset & ~(rb_page_size - 1);
+
+ if (rb_page_size == BALLOON_PAGE_SIZE) {
+ /* Easy case */
+
+ ram_block_discard_range(rb, ram_offset, rb_page_size);
+ /* We ignore errors from ram_block_discard_range(), because it
+ * has already reported them, and failing to discard a balloon
+ * page is not fatal */
+ return;
+ }
+
+ /* Hard case
+ *
+ * We've put a piece of a larger host page into the balloon - we
+ * need to keep track until we have a whole host page to
+ * discard
+ */
+ warn_report_once(
+"Balloon used with backing page size > 4kiB, this may not be reliable");
+
+ subpages = rb_page_size / BALLOON_PAGE_SIZE;
+
+ if (balloon->pbp
+ && (rb != balloon->pbp->rb
+ || host_page_base != balloon->pbp->base)) {
+ /* We've partially ballooned part of a host page, but now
+ * we're trying to balloon part of a different one. Too hard,
+ * give up on the old partial page */
+ free(balloon->pbp);
+ balloon->pbp = NULL;
+ }
+
+ if (!balloon->pbp) {
+ /* Starting on a new host page */
+ size_t bitlen = BITS_TO_LONGS(subpages) * sizeof(unsigned long);
+ balloon->pbp = g_malloc0(sizeof(PartiallyBalloonedPage) + bitlen);
+ balloon->pbp->rb = rb;
+ balloon->pbp->base = host_page_base;
+ }
+
+ bitmap_set(balloon->pbp->bitmap,
+ (ram_offset - balloon->pbp->base) / BALLOON_PAGE_SIZE,
+ subpages);
+
+ if (bitmap_full(balloon->pbp->bitmap, subpages)) {
+ /* We've accumulated a full host page, we can actually discard
+ * it now */
+
+ ram_block_discard_range(rb, balloon->pbp->base, rb_page_size);
+ /* We ignore errors from ram_block_discard_range(), because it
+ * has already reported them, and failing to discard a balloon
+ * page is not fatal */
+
+ free(balloon->pbp);
+ balloon->pbp = NULL;
}
}
@@ -222,17 +292,19 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
}
while (iov_to_buf(elem->out_sg, elem->out_num, offset, &pfn, 4) == 4) {
- ram_addr_t pa;
- ram_addr_t addr;
+ hwaddr pa;
int p = virtio_ldl_p(vdev, &pfn);
- pa = (ram_addr_t) p << VIRTIO_BALLOON_PFN_SHIFT;
+ pa = (hwaddr) p << VIRTIO_BALLOON_PFN_SHIFT;
offset += 4;
- /* FIXME: remove get_system_memory(), but how? */
- section = memory_region_find(get_system_memory(), pa, 1);
- if (!int128_nz(section.size) ||
- !memory_region_is_ram(section.mr) ||
+ section = memory_region_find(get_system_memory(), pa,
+ BALLOON_PAGE_SIZE);
+ if (!section.mr) {
+ trace_virtio_balloon_bad_addr(pa);
+ continue;
+ }
+ if (!memory_region_is_ram(section.mr) ||
memory_region_is_rom(section.mr) ||
memory_region_is_romd(section.mr)) {
trace_virtio_balloon_bad_addr(pa);
@@ -242,11 +314,9 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
trace_virtio_balloon_handle_output(memory_region_name(section.mr),
pa);
- /* Using memory_region_get_ram_ptr is bending the rules a bit, but
- should be OK because we only want a single page. */
- addr = section.offset_within_region;
- balloon_page(memory_region_get_ram_ptr(section.mr) + addr,
- !!(vq == s->dvq));
+ if (!qemu_balloon_is_inhibited() && vq != s->dvq) {
+ balloon_inflate_page(s, section.mr, section.offset_within_region);
+ }
memory_region_unref(section.mr);
}
diff --git a/include/exec/poison.h b/include/exec/poison.h
index ecdc83c147..1a7a57baae 100644
--- a/include/exec/poison.h
+++ b/include/exec/poison.h
@@ -86,7 +86,6 @@
#pragma GCC poison CONFIG_XTENSA_DIS
#pragma GCC poison CONFIG_LINUX_USER
-#pragma GCC poison CONFIG_VHOST_NET
#pragma GCC poison CONFIG_KVM
#pragma GCC poison CONFIG_SOFTMMU
diff --git a/include/hw/firmware/smbios.h b/include/hw/firmware/smbios.h
index eeb5a4d7b6..6fef32a3c9 100644
--- a/include/hw/firmware/smbios.h
+++ b/include/hw/firmware/smbios.h
@@ -162,6 +162,7 @@ struct smbios_type_3 {
uint8_t height;
uint8_t number_of_power_cords;
uint8_t contained_element_count;
+ uint8_t contained_element_record_length;
uint8_t sku_number_str;
/* contained elements follow */
} QEMU_PACKED;
diff --git a/include/hw/pci/pci_ids.h b/include/hw/pci/pci_ids.h
index eeb33018ad..0abe27a53a 100644
--- a/include/hw/pci/pci_ids.h
+++ b/include/hw/pci/pci_ids.h
@@ -271,4 +271,6 @@
#define PCI_VENDOR_ID_SYNOPSYS 0x16C3
+#define PCI_VENDOR_ID_NVIDIA 0x10de
+
#endif
diff --git a/include/hw/virtio/virtio-balloon.h b/include/hw/virtio/virtio-balloon.h
index e0df3528c8..99dcd6d105 100644
--- a/include/hw/virtio/virtio-balloon.h
+++ b/include/hw/virtio/virtio-balloon.h
@@ -30,6 +30,8 @@ typedef struct virtio_balloon_stat_modern {
uint64_t val;
} VirtIOBalloonStatModern;
+typedef struct PartiallyBalloonedPage PartiallyBalloonedPage;
+
typedef struct VirtIOBalloon {
VirtIODevice parent_obj;
VirtQueue *ivq, *dvq, *svq;
@@ -42,6 +44,7 @@ typedef struct VirtIOBalloon {
int64_t stats_last_update;
int64_t stats_poll_interval;
uint32_t host_features;
+ PartiallyBalloonedPage *pbp;
} VirtIOBalloon;
#endif
diff --git a/net/Makefile.objs b/net/Makefile.objs
index b2bf88a0ef..df2b409066 100644
--- a/net/Makefile.objs
+++ b/net/Makefile.objs
@@ -3,7 +3,9 @@ common-obj-y += socket.o
common-obj-y += dump.o
common-obj-y += eth.o
common-obj-$(CONFIG_L2TPV3) += l2tpv3.o
-common-obj-$(CONFIG_POSIX) += vhost-user.o
+common-obj-$(call land,$(CONFIG_VIRTIO_NET),$(CONFIG_VHOST_NET_USER)) += vhost-user.o
+common-obj-$(call land,$(call lnot,$(CONFIG_VIRTIO_NET)),$(CONFIG_VHOST_NET_USER)) += vhost-user-stub.o
+common-obj-$(CONFIG_ALL) += vhost-user-stub.o
common-obj-$(CONFIG_SLIRP) += slirp.o
common-obj-$(CONFIG_VDE) += vde.o
common-obj-$(CONFIG_NETMAP) += netmap.o
diff --git a/net/net.c b/net/net.c
index 5dcff7fe2a..f3a3c5444c 100644
--- a/net/net.c
+++ b/net/net.c
@@ -961,7 +961,7 @@ static int (* const net_client_init_fun[NET_CLIENT_DRIVER__MAX])(
[NET_CLIENT_DRIVER_BRIDGE] = net_init_bridge,
#endif
[NET_CLIENT_DRIVER_HUBPORT] = net_init_hubport,
-#ifdef CONFIG_VHOST_NET_USED
+#ifdef CONFIG_VHOST_NET_USER
[NET_CLIENT_DRIVER_VHOST_USER] = net_init_vhost_user,
#endif
#ifdef CONFIG_L2TPV3
diff --git a/net/vhost-user-stub.c b/net/vhost-user-stub.c
new file mode 100644
index 0000000000..52ab4e13f1
--- /dev/null
+++ b/net/vhost-user-stub.c
@@ -0,0 +1,23 @@
+/*
+ * vhost-user-stub.c
+ *
+ * Copyright (c) 2018 Red Hat, Inc.
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "clients.h"
+#include "net/vhost_net.h"
+#include "net/vhost-user.h"
+#include "qemu/error-report.h"
+#include "qapi/error.h"
+
+int net_init_vhost_user(const Netdev *netdev, const char *name,
+ NetClientState *peer, Error **errp)
+{
+ error_setg(errp, "vhost-user requires frontend driver virtio-net-*");
+ return -1;
+}
diff --git a/net/vhost-user.c b/net/vhost-user.c
index a39f9c9974..cd9659df87 100644
--- a/net/vhost-user.c
+++ b/net/vhost-user.c
@@ -172,6 +172,17 @@ static void net_vhost_user_cleanup(NetClientState *nc)
qemu_purge_queued_packets(nc);
}
+static int vhost_user_set_vnet_endianness(NetClientState *nc,
+ bool enable)
+{
+ /* Nothing to do. If the server supports
+ * VHOST_USER_PROTOCOL_F_CROSS_ENDIAN, it will get the
+ * vnet header endianness from there. If it doesn't, negotiation
+ * fails.
+ */
+ return 0;
+}
+
static bool vhost_user_has_vnet_hdr(NetClientState *nc)
{
assert(nc->info->type == NET_CLIENT_DRIVER_VHOST_USER);
@@ -193,6 +204,8 @@ static NetClientInfo net_vhost_user_info = {
.cleanup = net_vhost_user_cleanup,
.has_vnet_hdr = vhost_user_has_vnet_hdr,
.has_ufo = vhost_user_has_ufo,
+ .set_vnet_be = vhost_user_set_vnet_endianness,
+ .set_vnet_le = vhost_user_set_vnet_endianness,
};
static gboolean net_vhost_user_watch(GIOChannel *chan, GIOCondition cond,
diff --git a/roms/Makefile b/roms/Makefile
index a6043eff37..78d5dd18c3 100644
--- a/roms/Makefile
+++ b/roms/Makefile
@@ -47,10 +47,7 @@ SEABIOS_EXTRAVERSION="-prebuilt.qemu.org"
# We need that to combine multiple images (legacy bios,
# efi ia32, efi x64) into a single rom binary.
#
-# We try to find it in the path. You can also pass the location on
-# the command line, i.e. "make EFIROM=/path/to/EfiRom efirom"
-#
-EFIROM ?= $(shell which EfiRom 2>/dev/null)
+EFIROM = edk2/BaseTools/Source/C/bin/EfiRom
default:
@echo "nothing is build by default"
@@ -59,8 +56,7 @@ default:
@echo " vgabios -- update vgabios binaries (seabios)"
@echo " sgabios -- update sgabios binaries"
@echo " pxerom -- update nic roms (bios only)"
- @echo " efirom -- update nic roms (bios+efi, this needs"
- @echo " the EfiRom utility from edk2 / tianocore)"
+ @echo " efirom -- update nic roms (bios+efi)"
@echo " slof -- update slof.bin"
@echo " skiboot -- update skiboot.lid"
@echo " u-boot.e500 -- update u-boot.e500"
@@ -106,7 +102,7 @@ pxe-rom-%: build-pxe-roms
efirom: $(patsubst %,efi-rom-%,$(pxerom_variants))
-efi-rom-%: build-pxe-roms build-efi-roms
+efi-rom-%: build-pxe-roms build-efi-roms $(EFIROM)
$(EFIROM) -f "0x$(VID)" -i "0x$(DID)" -l 0x02 \
-b ipxe/src/bin/$(VID)$(DID).rom \
-ec ipxe/src/bin-i386-efi/$(VID)$(DID).efidrv \
@@ -124,6 +120,8 @@ build-efi-roms: build-pxe-roms
$(patsubst %,bin-i386-efi/%.efidrv,$(pxerom_targets)) \
$(patsubst %,bin-x86_64-efi/%.efidrv,$(pxerom_targets))
+$(EFIROM):
+ $(MAKE) -C edk2/BaseTools
slof:
$(MAKE) -C SLOF CROSS=$(powerpc64_cross_prefix) qemu
@@ -150,6 +148,7 @@ clean:
$(MAKE) -C sgabios clean
rm -f sgabios/.depend
$(MAKE) -C ipxe/src veryclean
+ $(MAKE) -C edk2/BaseTools clean
$(MAKE) -C SLOF clean
rm -rf u-boot/build.e500
$(MAKE) -C u-boot-sam460ex distclean
diff --git a/roms/edk2 b/roms/edk2
new file mode 160000
+Subproject 85588389222a3636baf0f9ed8227f2434af4c3f
diff --git a/tests/Makefile.include b/tests/Makefile.include
index ca0166f4f3..c2ac4b8d4c 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -216,10 +216,7 @@ check-qtest-i386-$(CONFIG_USB_XHCI_NEC) += tests/usb-hcd-xhci-test$(EXESUF)
check-qtest-i386-y += tests/cpu-plug-test$(EXESUF)
check-qtest-i386-y += tests/q35-test$(EXESUF)
check-qtest-i386-y += tests/vmgenid-test$(EXESUF)
-check-qtest-i386-$(CONFIG_VHOST_USER_NET_TEST_i386) += tests/vhost-user-test$(EXESUF)
-ifeq ($(CONFIG_VHOST_USER_NET_TEST_i386),)
-check-qtest-x86_64-$(CONFIG_VHOST_USER_NET_TEST_x86_64) += tests/vhost-user-test$(EXESUF)
-endif
+check-qtest-i386-$(CONFIG_VHOST_NET_USER) += tests/vhost-user-test$(EXESUF)
check-qtest-i386-$(CONFIG_TPM_CRB) += tests/tpm-crb-swtpm-test$(EXESUF)
check-qtest-i386-$(CONFIG_TPM_CRB) += tests/tpm-crb-test$(EXESUF)
check-qtest-i386-$(CONFIG_TPM_TIS) += tests/tpm-tis-swtpm-test$(EXESUF)
diff --git a/tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2 b/tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2
new file mode 100644
index 0000000000..ac0b7b1b8f
--- /dev/null
+++ b/tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2
Binary files differ
diff --git a/tests/data/uefi-boot-images/bios-tables-test.arm.iso.qcow2 b/tests/data/uefi-boot-images/bios-tables-test.arm.iso.qcow2
new file mode 100644
index 0000000000..d20fa7c819
--- /dev/null
+++ b/tests/data/uefi-boot-images/bios-tables-test.arm.iso.qcow2
Binary files differ
diff --git a/tests/data/uefi-boot-images/bios-tables-test.i386.iso.qcow2 b/tests/data/uefi-boot-images/bios-tables-test.i386.iso.qcow2
new file mode 100644
index 0000000000..26c882baea
--- /dev/null
+++ b/tests/data/uefi-boot-images/bios-tables-test.i386.iso.qcow2
Binary files differ
diff --git a/tests/data/uefi-boot-images/bios-tables-test.x86_64.iso.qcow2 b/tests/data/uefi-boot-images/bios-tables-test.x86_64.iso.qcow2
new file mode 100644
index 0000000000..9ec3c1f20b
--- /dev/null
+++ b/tests/data/uefi-boot-images/bios-tables-test.x86_64.iso.qcow2
Binary files differ
diff --git a/tests/uefi-test-tools/.gitignore b/tests/uefi-test-tools/.gitignore
new file mode 100644
index 0000000000..9f246701de
--- /dev/null
+++ b/tests/uefi-test-tools/.gitignore
@@ -0,0 +1,3 @@
+Build
+Conf
+log
diff --git a/tests/uefi-test-tools/LICENSE b/tests/uefi-test-tools/LICENSE
new file mode 100644
index 0000000000..38b78aecdb
--- /dev/null
+++ b/tests/uefi-test-tools/LICENSE
@@ -0,0 +1,25 @@
+All the files in this directory and subdirectories are released under the
+2-Clause BSD License (see header in each file).
+
+Copyright (C) 2019, Red Hat, Inc.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/tests/uefi-test-tools/Makefile b/tests/uefi-test-tools/Makefile
new file mode 100644
index 0000000000..1d78bc14d5
--- /dev/null
+++ b/tests/uefi-test-tools/Makefile
@@ -0,0 +1,106 @@
+# Makefile for the test helper UEFI applications that run in guests.
+#
+# Copyright (C) 2019, Red Hat, Inc.
+#
+# This program and the accompanying materials are licensed and made available
+# under the terms and conditions of the BSD License that accompanies this
+# distribution. The full text of the license may be found at
+# <http://opensource.org/licenses/bsd-license.php>.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+# WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+edk2_dir := ../../roms/edk2
+images_dir := ../data/uefi-boot-images
+emulation_targets := arm aarch64 i386 x86_64
+uefi_binaries := bios-tables-test
+intermediate_suffixes := .efi .fat .iso.raw
+
+images: $(foreach binary,$(uefi_binaries), \
+ $(foreach target,$(emulation_targets), \
+ $(images_dir)/$(binary).$(target).iso.qcow2))
+
+# Preserve all intermediate targets if the build succeeds.
+# - Intermediate targets help with development & debugging.
+# - Preserving intermediate targets also keeps spurious changes out of the
+# final build products, in case the user re-runs "make" without any changes
+# to the UEFI source code. Normally, the intermediate files would have been
+# removed by the last "make" invocation, hence the re-run would rebuild them
+# from the unchanged UEFI sources. Unfortunately, the "mkdosfs" and
+# "genisoimage" utilities embed timestamp-based information in their outputs,
+# which causes git to report differences for the tracked qcow2 ISO images.
+.SECONDARY: $(foreach binary,$(uefi_binaries), \
+ $(foreach target,$(emulation_targets), \
+ $(foreach suffix,$(intermediate_suffixes), \
+ Build/$(binary).$(target)$(suffix))))
+
+# In the pattern rules below, the stem (%, $*) stands for
+# "$(binary).$(target)".
+
+# Convert the raw ISO image to a qcow2 one, enabling compression, and using a
+# small cluster size. This allows for small binary files under git control,
+# hence for small binary patches.
+$(images_dir)/%.iso.qcow2: Build/%.iso.raw
+ mkdir -p -- $(images_dir)
+ $${QTEST_QEMU_IMG:-qemu-img} convert -f raw -O qcow2 -c \
+ -o cluster_size=512 -- $< $@
+
+# Embed the "UEFI system partition" into an ISO9660 file system as an ElTorito
+# boot image.
+Build/%.iso.raw: Build/%.fat
+ genisoimage -input-charset ASCII -efi-boot $(notdir $<) -no-emul-boot \
+ -quiet -o $@ -- $<
+
+# Define chained macros in order to map QEMU system emulation targets to
+# *short* UEFI architecture identifiers. Periods are allowed in, and ultimately
+# stripped from, the argument.
+map_arm_to_uefi = $(subst arm,ARM,$(1))
+map_aarch64_to_uefi = $(subst aarch64,AA64,$(call map_arm_to_uefi,$(1)))
+map_i386_to_uefi = $(subst i386,IA32,$(call map_aarch64_to_uefi,$(1)))
+map_x86_64_to_uefi = $(subst x86_64,X64,$(call map_i386_to_uefi,$(1)))
+map_to_uefi = $(subst .,,$(call map_x86_64_to_uefi,$(1)))
+
+# Format a "UEFI system partition", using the UEFI binary as the default boot
+# loader. Add 10% size for filesystem metadata, round up to the next KB, and
+# make sure the size is large enough for a FAT filesystem. Name the filesystem
+# after the UEFI binary. (Excess characters are automatically dropped from the
+# filesystem label.)
+Build/%.fat: Build/%.efi
+ rm -f -- $@
+ uefi_bin_b=$$(stat --format=%s -- $<) && \
+ uefi_fat_kb=$$(( (uefi_bin_b * 11 / 10 + 1023) / 1024 )) && \
+ uefi_fat_kb=$$(( uefi_fat_kb >= 64 ? uefi_fat_kb : 64 )) && \
+ mkdosfs -C $@ -n $(basename $(@F)) -- $$uefi_fat_kb
+ MTOOLS_SKIP_CHECK=1 mmd -i $@ ::EFI
+ MTOOLS_SKIP_CHECK=1 mmd -i $@ ::EFI/BOOT
+ MTOOLS_SKIP_CHECK=1 mcopy -i $@ -- $< \
+ ::EFI/BOOT/BOOT$(call map_to_uefi,$(suffix $*)).EFI
+
+# In the pattern rules below, the stem (%, $*) stands for "$(target)" only. The
+# association between the UEFI binary (such as "bios-tables-test") and the
+# component name from the edk2 platform DSC file (such as "BiosTablesTest") is
+# explicit in each rule.
+
+# "build.sh" invokes the "build" utility of edk2 BaseTools. In any given edk2
+# workspace, at most one "build" instance may be operating at a time. Therefore
+# we must serialize the rebuilding of targets in this Makefile.
+.NOTPARALLEL:
+
+# In turn, the "build" utility of edk2 BaseTools invokes another "make".
+# Although the outer "make" process advertizes its job server to all child
+# processes via MAKEFLAGS in the environment, the outer "make" closes the job
+# server file descriptors (exposed in MAKEFLAGS) before executing a recipe --
+# unless the recipe is recognized as a recursive "make" recipe. Recipes that
+# call $(MAKE) are classified automatically as recursive; for "build.sh" below,
+# we must mark the recipe manually as recursive, by using the "+" indicator.
+# This way, when the inner "make" starts a parallel build of the target edk2
+# module, it can communicate with the outer "make"'s job server.
+Build/bios-tables-test.%.efi: build-edk2-tools
+ +./build.sh $(edk2_dir) BiosTablesTest $* $@
+
+build-edk2-tools:
+ $(MAKE) -C $(edk2_dir)/BaseTools
+
+clean:
+ rm -rf Build Conf log
+ $(MAKE) -C $(edk2_dir)/BaseTools clean
diff --git a/tests/uefi-test-tools/UefiTestToolsPkg/BiosTablesTest/BiosTablesTest.c b/tests/uefi-test-tools/UefiTestToolsPkg/BiosTablesTest/BiosTablesTest.c
new file mode 100644
index 0000000000..b208e17fb0
--- /dev/null
+++ b/tests/uefi-test-tools/UefiTestToolsPkg/BiosTablesTest/BiosTablesTest.c
@@ -0,0 +1,130 @@
+/** @file
+ Populate the BIOS_TABLES_TEST structure.
+
+ Copyright (C) 2019, Red Hat, Inc.
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License that accompanies this
+ distribution. The full text of the license may be found at
+ <http://opensource.org/licenses/bsd-license.php>.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include <Guid/Acpi.h>
+#include <Guid/BiosTablesTest.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+/**
+ Wait for a keypress with a message that the application is about to exit.
+**/
+STATIC
+VOID
+WaitForExitKeyPress (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Idx;
+ EFI_INPUT_KEY Key;
+
+ if (gST->ConIn == NULL) {
+ return;
+ }
+ AsciiPrint ("%a: press any key to exit\n", gEfiCallerBaseName);
+ Status = gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &Idx);
+ if (EFI_ERROR (Status)) {
+ return;
+ }
+ gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+}
+
+EFI_STATUS
+EFIAPI
+BiosTablesTestMain (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ VOID *Pages;
+ volatile BIOS_TABLES_TEST *BiosTablesTest;
+ CONST VOID *Rsdp10;
+ CONST VOID *Rsdp20;
+ CONST EFI_CONFIGURATION_TABLE *ConfigTable;
+ CONST EFI_CONFIGURATION_TABLE *ConfigTablesEnd;
+ volatile EFI_GUID *InverseSignature;
+ UINTN Idx;
+
+ Pages = AllocateAlignedPages (EFI_SIZE_TO_PAGES (sizeof *BiosTablesTest),
+ SIZE_1MB);
+ if (Pages == NULL) {
+ AsciiErrorPrint ("%a: AllocateAlignedPages() failed\n",
+ gEfiCallerBaseName);
+ //
+ // Assuming the application was launched by the boot manager as a boot
+ // loader, exiting with error will cause the boot manager to proceed with
+ // the remaining boot options. If there are no other boot options, the boot
+ // manager menu will be pulled up. Give the user a chance to read the error
+ // message.
+ //
+ WaitForExitKeyPress ();
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Locate both gEfiAcpi10TableGuid and gEfiAcpi20TableGuid config tables in
+ // one go.
+ //
+ Rsdp10 = NULL;
+ Rsdp20 = NULL;
+ ConfigTable = gST->ConfigurationTable;
+ ConfigTablesEnd = gST->ConfigurationTable + gST->NumberOfTableEntries;
+ while ((Rsdp10 == NULL || Rsdp20 == NULL) && ConfigTable < ConfigTablesEnd) {
+ if (CompareGuid (&ConfigTable->VendorGuid, &gEfiAcpi10TableGuid)) {
+ Rsdp10 = ConfigTable->VendorTable;
+ } else if (CompareGuid (&ConfigTable->VendorGuid, &gEfiAcpi20TableGuid)) {
+ Rsdp20 = ConfigTable->VendorTable;
+ }
+ ++ConfigTable;
+ }
+
+ AsciiPrint ("%a: BiosTablesTest=%p Rsdp10=%p Rsdp20=%p\n",
+ gEfiCallerBaseName, Pages, Rsdp10, Rsdp20);
+
+ //
+ // Store the RSD PTR address(es) first, then the signature second.
+ //
+ BiosTablesTest = Pages;
+ BiosTablesTest->Rsdp10 = (UINTN)Rsdp10;
+ BiosTablesTest->Rsdp20 = (UINTN)Rsdp20;
+
+ MemoryFence();
+
+ InverseSignature = &BiosTablesTest->InverseSignatureGuid;
+ InverseSignature->Data1 = gBiosTablesTestGuid.Data1;
+ InverseSignature->Data1 ^= MAX_UINT32;
+ InverseSignature->Data2 = gBiosTablesTestGuid.Data2;
+ InverseSignature->Data2 ^= MAX_UINT16;
+ InverseSignature->Data3 = gBiosTablesTestGuid.Data3;
+ InverseSignature->Data3 ^= MAX_UINT16;
+ for (Idx = 0; Idx < sizeof InverseSignature->Data4; ++Idx) {
+ InverseSignature->Data4[Idx] = gBiosTablesTestGuid.Data4[Idx];
+ InverseSignature->Data4[Idx] ^= MAX_UINT8;
+ }
+
+ //
+ // The wait below has dual purpose. First, it blocks the application without
+ // wasting VCPU cycles while the hypervisor is scanning guest RAM. Second,
+ // assuming the application was launched by the boot manager as a boot
+ // loader, exiting the app with success causes the boot manager to pull up
+ // the boot manager menu at once (regardless of other boot options); the wait
+ // gives the user a chance to read the info printed above.
+ //
+ WaitForExitKeyPress ();
+ return EFI_SUCCESS;
+}
diff --git a/tests/uefi-test-tools/UefiTestToolsPkg/BiosTablesTest/BiosTablesTest.inf b/tests/uefi-test-tools/UefiTestToolsPkg/BiosTablesTest/BiosTablesTest.inf
new file mode 100644
index 0000000000..924d8a80d0
--- /dev/null
+++ b/tests/uefi-test-tools/UefiTestToolsPkg/BiosTablesTest/BiosTablesTest.inf
@@ -0,0 +1,41 @@
+## @file
+# Populate the BIOS_TABLES_TEST structure.
+#
+# Copyright (C) 2019, Red Hat, Inc.
+#
+# This program and the accompanying materials are licensed and made available
+# under the terms and conditions of the BSD License that accompanies this
+# distribution. The full text of the license may be found at
+# <http://opensource.org/licenses/bsd-license.php>.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+# WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+ INF_VERSION = 1.27
+ BASE_NAME = BiosTablesTest
+ UEFI_SPECIFICATION_VERSION = 2.31
+ FILE_GUID = 87f00433-3b7c-45c3-ae78-a56495bd4e62
+ MODULE_TYPE = UEFI_APPLICATION
+ ENTRY_POINT = BiosTablesTestMain
+
+[Sources]
+ BiosTablesTest.c
+
+[LibraryClasses]
+ BaseLib
+ BaseMemoryLib
+ MemoryAllocationLib
+ UefiApplicationEntryPoint
+ UefiBootServicesTableLib
+ UefiLib
+
+[Guids]
+ gBiosTablesTestGuid
+ gEfiAcpi10TableGuid
+ gEfiAcpi20TableGuid
+
+[Packages]
+ MdePkg/MdePkg.dec
+ UefiTestToolsPkg/UefiTestToolsPkg.dec
diff --git a/tests/uefi-test-tools/UefiTestToolsPkg/Include/Guid/BiosTablesTest.h b/tests/uefi-test-tools/UefiTestToolsPkg/Include/Guid/BiosTablesTest.h
new file mode 100644
index 0000000000..0b72c61254
--- /dev/null
+++ b/tests/uefi-test-tools/UefiTestToolsPkg/Include/Guid/BiosTablesTest.h
@@ -0,0 +1,67 @@
+/** @file
+ Expose the address(es) of the ACPI RSD PTR table(s) in a MB-aligned structure
+ to the hypervisor.
+
+ The hypervisor locates the MB-aligned structure based on the signature GUID
+ that is at offset 0 in the structure. Once the RSD PTR address(es) are
+ retrieved, the hypervisor may perform various ACPI checks.
+
+ This feature is a development aid, for supporting ACPI table unit tests in
+ hypervisors. Do not enable in production builds.
+
+ Copyright (C) 2019, Red Hat, Inc.
+
+ This program and the accompanying materials are licensed and made available
+ under the terms and conditions of the BSD License that accompanies this
+ distribution. The full text of the license may be found at
+ <http://opensource.org/licenses/bsd-license.php>.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+ WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#ifndef __BIOS_TABLES_TEST_H__
+#define __BIOS_TABLES_TEST_H__
+
+#include <Uefi/UefiBaseType.h>
+
+#define BIOS_TABLES_TEST_GUID \
+ { \
+ 0x5478594e, \
+ 0xdfcb, \
+ 0x425f, \
+ { 0x8e, 0x42, 0xc8, 0xaf, 0xf8, 0x8a, 0x88, 0x7a } \
+ }
+
+extern EFI_GUID gBiosTablesTestGuid;
+
+//
+// The following structure must be allocated in Boot Services Data type memory,
+// aligned at a 1MB boundary.
+//
+#pragma pack (1)
+typedef struct {
+ //
+ // The signature GUID is written to the MB-aligned structure from
+ // gBiosTablesTestGuid, but with all bits inverted. That's the actual GUID
+ // value that the hypervisor should look for at each MB boundary, looping
+ // over all guest RAM pages with that alignment, until a match is found. The
+ // bit-flipping occurs in order not to store the actual GUID in any UEFI
+ // executable, which might confuse guest memory analysis. Note that EFI_GUID
+ // has little endian representation.
+ //
+ EFI_GUID InverseSignatureGuid;
+ //
+ // The Rsdp10 and Rsdp20 fields may be read when the signature GUID matches.
+ // Rsdp10 is the guest-physical address of the ACPI 1.0 specification RSD PTR
+ // table, in 8-byte little endian representation. Rsdp20 is the same, for the
+ // ACPI 2.0 or later specification RSD PTR table. Each of these fields may be
+ // zero (independently of the other) if the UEFI System Table does not
+ // provide the corresponding UEFI Configuration Table.
+ //
+ EFI_PHYSICAL_ADDRESS Rsdp10;
+ EFI_PHYSICAL_ADDRESS Rsdp20;
+} BIOS_TABLES_TEST;
+#pragma pack ()
+
+#endif // __BIOS_TABLES_TEST_H__
diff --git a/tests/uefi-test-tools/UefiTestToolsPkg/UefiTestToolsPkg.dec b/tests/uefi-test-tools/UefiTestToolsPkg/UefiTestToolsPkg.dec
new file mode 100644
index 0000000000..ed3a2fe110
--- /dev/null
+++ b/tests/uefi-test-tools/UefiTestToolsPkg/UefiTestToolsPkg.dec
@@ -0,0 +1,27 @@
+## @file
+# edk2 package declaration for the test helper UEFI applications that run in
+# guests.
+#
+# Copyright (C) 2019, Red Hat, Inc.
+#
+# This program and the accompanying materials are licensed and made available
+# under the terms and conditions of the BSD License that accompanies this
+# distribution. The full text of the license may be found at
+# <http://opensource.org/licenses/bsd-license.php>.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+# WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+ DEC_SPECIFICATION = 1.27
+ PACKAGE_NAME = UefiTestToolsPkg
+ PACKAGE_GUID = 7b3f1794-0c85-4b27-a536-44dbf0b0669c
+ PACKAGE_VERSION = 0.1
+
+[Includes]
+ Include
+
+[Guids]
+ gBiosTablesTestGuid = {0x5478594e, 0xdfcb, 0x425f, {0x8e, 0x42, 0xc8, 0xaf, 0xf8, 0x8a, 0x88, 0x7a}}
+
diff --git a/tests/uefi-test-tools/UefiTestToolsPkg/UefiTestToolsPkg.dsc b/tests/uefi-test-tools/UefiTestToolsPkg/UefiTestToolsPkg.dsc
new file mode 100644
index 0000000000..c8511cd732
--- /dev/null
+++ b/tests/uefi-test-tools/UefiTestToolsPkg/UefiTestToolsPkg.dsc
@@ -0,0 +1,69 @@
+## @file
+# edk2 platform description for the test helper UEFI applications that run in
+# guests.
+#
+# Copyright (C) 2019, Red Hat, Inc.
+#
+# This program and the accompanying materials are licensed and made available
+# under the terms and conditions of the BSD License that accompanies this
+# distribution. The full text of the license may be found at
+# <http://opensource.org/licenses/bsd-license.php>.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+# WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+##
+
+[Defines]
+ DSC_SPECIFICATION = 1.28
+ PLATFORM_GUID = 6750ccc1-8365-49f0-8437-948e516a9f55
+ PLATFORM_VERSION = 0.1
+ PLATFORM_NAME = UefiTestTools
+ SKUID_IDENTIFIER = DEFAULT
+ SUPPORTED_ARCHITECTURES = ARM|AARCH64|IA32|X64
+ BUILD_TARGETS = DEBUG
+
+[BuildOptions.IA32]
+ GCC:*_*_IA32_CC_FLAGS = -mno-mmx -mno-sse
+
+[BuildOptions.X64]
+ GCC:*_*_X64_CC_FLAGS = -mno-mmx -mno-sse
+
+[BuildOptions.ARM.EDKII.UEFI_APPLICATION]
+ GCC:*_*_ARM_DLINK_FLAGS = -z common-page-size=0x1000
+
+[BuildOptions.AARCH64.EDKII.UEFI_APPLICATION]
+ GCC:*_*_AARCH64_DLINK_FLAGS = -z common-page-size=0x1000
+
+[BuildOptions]
+ GCC:*_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
+
+[SkuIds]
+ 0|DEFAULT
+
+[LibraryClasses]
+ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+ DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+ DevicePathLib|MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
+ UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
+ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
+ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
+
+[LibraryClasses.ARM, LibraryClasses.AARCH64]
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLibOptDxe/BaseMemoryLibOptDxe.inf
+ NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
+ NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
+
+[LibraryClasses.IA32, LibraryClasses.X64]
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.inf
+
+[PcdsFixedAtBuild]
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPrintErrorLevel|0x8040004F
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x2F
+
+[Components]
+ UefiTestToolsPkg/BiosTablesTest/BiosTablesTest.inf
diff --git a/tests/uefi-test-tools/build.sh b/tests/uefi-test-tools/build.sh
new file mode 100755
index 0000000000..155cb75c4d
--- /dev/null
+++ b/tests/uefi-test-tools/build.sh
@@ -0,0 +1,145 @@
+#!/bin/bash
+
+# Build script that determines the edk2 toolchain to use, invokes the edk2
+# "build" utility, and copies the built UEFI binary to the requested location.
+#
+# Copyright (C) 2019, Red Hat, Inc.
+#
+# This program and the accompanying materials are licensed and made available
+# under the terms and conditions of the BSD License that accompanies this
+# distribution. The full text of the license may be found at
+# <http://opensource.org/licenses/bsd-license.php>.
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
+# WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+set -e -u -C
+
+# Save the command line arguments. We need to reset $# to 0 before sourcing
+# "edksetup.sh", as it will inherit $@.
+program_name=$(basename -- "$0")
+edk2_dir=$1
+dsc_component=$2
+emulation_target=$3
+uefi_binary=$4
+shift 4
+
+# Set up the environment for edk2 building.
+export PACKAGES_PATH=$(realpath -- "$edk2_dir")
+export WORKSPACE=$PWD
+mkdir -p Conf
+
+# Source "edksetup.sh" carefully.
+set +e +u +C
+source "$PACKAGES_PATH/edksetup.sh"
+ret=$?
+set -e -u -C
+if [ $ret -ne 0 ]; then
+ exit $ret
+fi
+
+# Map the QEMU system emulation target to the following types of architecture
+# identifiers:
+# - edk2,
+# - gcc cross-compilation.
+# Cover only those targets that are supported by the UEFI spec and edk2.
+case "$emulation_target" in
+ (arm)
+ edk2_arch=ARM
+ gcc_arch=arm
+ ;;
+ (aarch64)
+ edk2_arch=AARCH64
+ gcc_arch=aarch64
+ ;;
+ (i386)
+ edk2_arch=IA32
+ gcc_arch=i686
+ ;;
+ (x86_64)
+ edk2_arch=X64
+ gcc_arch=x86_64
+ ;;
+ (*)
+ printf '%s: unknown/unsupported QEMU system emulation target "%s"\n' \
+ "$program_name" "$emulation_target" >&2
+ exit 1
+ ;;
+esac
+
+# Check if cross-compilation is needed.
+host_arch=$(uname -m)
+if [ "$gcc_arch" == "$host_arch" ] ||
+ ( [ "$gcc_arch" == i686 ] && [ "$host_arch" == x86_64 ] ); then
+ cross_prefix=
+else
+ cross_prefix=${gcc_arch}-linux-gnu-
+fi
+
+# Expose cross_prefix (which is possibly empty) to the edk2 tools. While at it,
+# determine the suitable edk2 toolchain as well.
+# - For ARM and AARCH64, edk2 only offers the GCC5 toolchain tag, which covers
+# the gcc-5+ releases.
+# - For IA32 and X64, edk2 offers the GCC44 through GCC49 toolchain tags, in
+# addition to GCC5. Unfortunately, the mapping between the toolchain tags and
+# the actual gcc releases isn't entirely trivial. Run "git-blame" on
+# "OvmfPkg/build.sh" in edk2 for more information.
+# And, because the above is too simple, we have to assign cross_prefix to an
+# edk2 build variable that is specific to both the toolchain tag and the target
+# architecture.
+case "$edk2_arch" in
+ (ARM)
+ edk2_toolchain=GCC5
+ export GCC5_ARM_PREFIX=$cross_prefix
+ ;;
+ (AARCH64)
+ edk2_toolchain=GCC5
+ export GCC5_AARCH64_PREFIX=$cross_prefix
+ ;;
+ (IA32|X64)
+ gcc_version=$("${cross_prefix}gcc" -v 2>&1 | tail -1 | awk '{print $3}')
+ case "$gcc_version" in
+ ([1-3].*|4.[0-3].*)
+ printf '%s: unsupported gcc version "%s"\n' \
+ "$program_name" "$gcc_version" >&2
+ exit 1
+ ;;
+ (4.4.*)
+ edk2_toolchain=GCC44
+ ;;
+ (4.5.*)
+ edk2_toolchain=GCC45
+ ;;
+ (4.6.*)
+ edk2_toolchain=GCC46
+ ;;
+ (4.7.*)
+ edk2_toolchain=GCC47
+ ;;
+ (4.8.*)
+ edk2_toolchain=GCC48
+ ;;
+ (4.9.*|6.[0-2].*)
+ edk2_toolchain=GCC49
+ ;;
+ (*)
+ edk2_toolchain=GCC5
+ ;;
+ esac
+ eval "export ${edk2_toolchain}_BIN=\$cross_prefix"
+ ;;
+esac
+
+# Build the UEFI binary
+mkdir -p log
+build \
+ --arch="$edk2_arch" \
+ --buildtarget=DEBUG \
+ --platform=UefiTestToolsPkg/UefiTestToolsPkg.dsc \
+ --tagname="$edk2_toolchain" \
+ --module="UefiTestToolsPkg/$dsc_component/$dsc_component.inf" \
+ --log="log/$dsc_component.$edk2_arch.log" \
+ --report-file="log/$dsc_component.$edk2_arch.report"
+cp -a -- \
+ "Build/UefiTestTools/DEBUG_${edk2_toolchain}/$edk2_arch/$dsc_component.efi" \
+ "$uefi_binary"
diff --git a/tests/vhost-user-test.c b/tests/vhost-user-test.c
index d961bd09d1..4cd0a97f13 100644
--- a/tests/vhost-user-test.c
+++ b/tests/vhost-user-test.c
@@ -27,10 +27,13 @@
#include "libqos/malloc-pc.h"
#include "hw/virtio/virtio-net.h"
-#include <linux/vhost.h>
-#include <linux/virtio_ids.h>
-#include <linux/virtio_net.h>
+#include "standard-headers/linux/vhost_types.h"
+#include "standard-headers/linux/virtio_ids.h"
+#include "standard-headers/linux/virtio_net.h"
+
+#ifdef CONFIG_LINUX
#include <sys/vfs.h>
+#endif
#define QEMU_CMD_MEM " -m %d -object memory-backend-file,id=mem,size=%dM," \
@@ -139,10 +142,15 @@ typedef struct TestServer {
gchar *socket_path;
gchar *mig_path;
gchar *chr_name;
+ const gchar *mem_path;
+ gchar *tmpfs;
CharBackend chr;
int fds_num;
int fds[VHOST_MEMORY_MAX_NREGIONS];
VhostUserMemory memory;
+ GMainContext *context;
+ GMainLoop *loop;
+ GThread *thread;
GMutex data_mutex;
GCond data_cond;
int log_fd;
@@ -157,9 +165,6 @@ static TestServer *test_server_new(const gchar *name);
static void test_server_free(TestServer *server);
static void test_server_listen(TestServer *server);
-static const char *tmpfs;
-static const char *root;
-
enum test_memfd {
TEST_MEMFD_AUTO,
TEST_MEMFD_YES,
@@ -167,7 +172,7 @@ enum test_memfd {
};
static char *get_qemu_cmd(TestServer *s,
- int mem, enum test_memfd memfd, const char *mem_path,
+ int mem, enum test_memfd memfd,
const char *chr_opts, const char *extra)
{
if (memfd == TEST_MEMFD_AUTO && qemu_memfd_check(0)) {
@@ -182,7 +187,7 @@ static char *get_qemu_cmd(TestServer *s,
} else {
return g_strdup_printf(QEMU_CMD_MEM QEMU_CMD_CHR
QEMU_CMD_NETDEV QEMU_CMD_NET "%s", mem, mem,
- mem_path, s->chr_name, s->socket_path,
+ s->mem_path, s->chr_name, s->socket_path,
chr_opts, s->chr_name, extra);
}
}
@@ -459,13 +464,20 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
g_mutex_unlock(&s->data_mutex);
}
-static const char *init_hugepagefs(const char *path)
+static const char *init_hugepagefs(void)
{
+#ifdef CONFIG_LINUX
+ const char *path = getenv("QTEST_HUGETLBFS_PATH");
struct statfs fs;
int ret;
+ if (!path) {
+ return NULL;
+ }
+
if (access(path, R_OK | W_OK | X_OK)) {
g_test_message("access on path (%s): %s\n", path, strerror(errno));
+ abort();
return NULL;
}
@@ -475,21 +487,42 @@ static const char *init_hugepagefs(const char *path)
if (ret != 0) {
g_test_message("statfs on path (%s): %s\n", path, strerror(errno));
+ abort();
return NULL;
}
if (fs.f_type != HUGETLBFS_MAGIC) {
g_test_message("Warning: path not on HugeTLBFS: %s\n", path);
+ abort();
return NULL;
}
return path;
+#else
+ return NULL;
+#endif
}
static TestServer *test_server_new(const gchar *name)
{
TestServer *server = g_new0(TestServer, 1);
+ char template[] = "/tmp/vhost-test-XXXXXX";
+ const char *tmpfs;
+
+ server->context = g_main_context_new();
+ server->loop = g_main_loop_new(server->context, FALSE);
+
+ /* run the main loop thread so the chardev may operate */
+ server->thread = g_thread_new(NULL, thread_function, server->loop);
+
+ tmpfs = mkdtemp(template);
+ if (!tmpfs) {
+ g_test_message("mkdtemp on path (%s): %s", template, strerror(errno));
+ }
+ g_assert(tmpfs);
+ server->tmpfs = g_strdup(tmpfs);
+ server->mem_path = init_hugepagefs() ? : server->tmpfs;
server->socket_path = g_strdup_printf("%s/%s.sock", tmpfs, name);
server->mig_path = g_strdup_printf("%s/%s.mig", tmpfs, name);
server->chr_name = g_strdup_printf("chr-%s", name);
@@ -519,13 +552,13 @@ static void test_server_create_chr(TestServer *server, const gchar *opt)
Chardev *chr;
chr_path = g_strdup_printf("unix:%s%s", server->socket_path, opt);
- chr = qemu_chr_new(server->chr_name, chr_path, NULL);
+ chr = qemu_chr_new(server->chr_name, chr_path, server->context);
g_free(chr_path);
g_assert_nonnull(chr);
qemu_chr_fe_init(&server->chr, chr, &error_abort);
qemu_chr_fe_set_handlers(&server->chr, chr_can_read, chr_read,
- chr_event, NULL, server, NULL, true);
+ chr_event, NULL, server, server->context, true);
}
static void test_server_listen(TestServer *server)
@@ -533,9 +566,28 @@ static void test_server_listen(TestServer *server)
test_server_create_chr(server, ",server,nowait");
}
-static gboolean _test_server_free(TestServer *server)
+static void test_server_free(TestServer *server)
{
- int i;
+ int i, ret;
+
+ /* finish the helper thread and dispatch pending sources */
+ g_main_loop_quit(server->loop);
+ g_thread_join(server->thread);
+ while (g_main_context_pending(NULL)) {
+ g_main_context_iteration(NULL, TRUE);
+ }
+
+ unlink(server->socket_path);
+ g_free(server->socket_path);
+
+ unlink(server->mig_path);
+ g_free(server->mig_path);
+
+ ret = rmdir(server->tmpfs);
+ if (ret != 0) {
+ g_test_message("unable to rmdir: path (%s): %s",
+ server->tmpfs, strerror(errno));
+ }
qemu_chr_fe_deinit(&server->chr, true);
@@ -547,24 +599,13 @@ static gboolean _test_server_free(TestServer *server)
close(server->log_fd);
}
- unlink(server->socket_path);
- g_free(server->socket_path);
-
- unlink(server->mig_path);
- g_free(server->mig_path);
-
g_free(server->chr_name);
g_assert(server->bus);
qpci_free_pc(server->bus);
+ g_main_loop_unref(server->loop);
+ g_main_context_unref(server->context);
g_free(server);
-
- return FALSE;
-}
-
-static void test_server_free(TestServer *server)
-{
- g_idle_add((GSourceFunc)_test_server_free, server);
}
static void wait_for_log_fd(TestServer *s)
@@ -665,7 +706,7 @@ static void test_read_guest_mem(const void *arg)
"read-guest-memfd" : "read-guest-mem");
test_server_listen(server);
- qemu_cmd = get_qemu_cmd(server, 512, memfd, root, "", "");
+ qemu_cmd = get_qemu_cmd(server, 512, memfd, "", "");
s = qtest_start(qemu_cmd);
g_free(qemu_cmd);
@@ -700,7 +741,7 @@ static void test_migrate(void)
test_server_listen(s);
test_server_listen(dest);
- cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, root, "", "");
+ cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, "", "");
from = qtest_start(cmd);
g_free(cmd);
@@ -713,7 +754,7 @@ static void test_migrate(void)
g_assert_cmpint(size, ==, (2 * 1024 * 1024) / (VHOST_LOG_PAGE * 8));
tmp = g_strdup_printf(" -incoming %s", uri);
- cmd = get_qemu_cmd(dest, 2, TEST_MEMFD_AUTO, root, "", tmp);
+ cmd = get_qemu_cmd(dest, 2, TEST_MEMFD_AUTO, "", tmp);
g_free(tmp);
to = qtest_init(cmd);
g_free(cmd);
@@ -723,7 +764,7 @@ static void test_migrate(void)
sizeof(TestMigrateSource));
((TestMigrateSource *)source)->src = s;
((TestMigrateSource *)source)->dest = dest;
- g_source_attach(source, NULL);
+ g_source_attach(source, s->context);
/* slow down migration to have time to fiddle with log */
/* TODO: qtest could learn to break on some places */
@@ -820,10 +861,11 @@ connect_thread(gpointer data)
static void test_reconnect_subprocess(void)
{
TestServer *s = test_server_new("reconnect");
+ GSource *src;
char *cmd;
g_thread_new("connect", connect_thread, s);
- cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, root, ",server", "");
+ cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, ",server", "");
qtest_start(cmd);
g_free(cmd);
@@ -837,7 +879,10 @@ static void test_reconnect_subprocess(void)
/* reconnect */
s->fds_num = 0;
s->rings = 0;
- g_idle_add(reconnect_cb, s);
+ src = g_idle_source_new();
+ g_source_set_callback(src, reconnect_cb, s, NULL);
+ g_source_attach(src, s->context);
+ g_source_unref(src);
g_assert(wait_for_fds(s));
wait_for_rings_started(s, 2);
@@ -865,7 +910,7 @@ static void test_connect_fail_subprocess(void)
s->test_fail = true;
g_thread_new("connect", connect_thread, s);
- cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, root, ",server", "");
+ cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, ",server", "");
qtest_start(cmd);
g_free(cmd);
@@ -898,7 +943,7 @@ static void test_flags_mismatch_subprocess(void)
s->test_flags = TEST_FLAGS_DISCONNECT;
g_thread_new("connect", connect_thread, s);
- cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, root, ",server", "");
+ cmd = get_qemu_cmd(s, 2, TEST_MEMFD_AUTO, ",server", "");
qtest_start(cmd);
g_free(cmd);
@@ -946,7 +991,7 @@ static void test_multiqueue(void)
cmd = g_strdup_printf(
QEMU_CMD_MEM QEMU_CMD_CHR QEMU_CMD_NETDEV ",queues=%d "
"-device virtio-net-pci,netdev=net0,mq=on,vectors=%d",
- 512, 512, root, s->chr_name,
+ 512, 512, s->mem_path, s->chr_name,
s->socket_path, "", s->chr_name,
s->queues, s->queues * 2 + 2);
}
@@ -966,35 +1011,11 @@ static void test_multiqueue(void)
int main(int argc, char **argv)
{
- const char *hugefs;
- int ret;
- char template[] = "/tmp/vhost-test-XXXXXX";
- GMainLoop *loop;
- GThread *thread;
-
g_test_init(&argc, &argv, NULL);
module_call_init(MODULE_INIT_QOM);
qemu_add_opts(&qemu_chardev_opts);
- tmpfs = mkdtemp(template);
- if (!tmpfs) {
- g_test_message("mkdtemp on path (%s): %s\n", template, strerror(errno));
- }
- g_assert(tmpfs);
-
- hugefs = getenv("QTEST_HUGETLBFS_PATH");
- if (hugefs) {
- root = init_hugepagefs(hugefs);
- g_assert(root);
- } else {
- root = tmpfs;
- }
-
- loop = g_main_loop_new(NULL, FALSE);
- /* run the main loop thread so the chardev may operate */
- thread = g_thread_new(NULL, thread_function, loop);
-
if (qemu_memfd_check(0)) {
qtest_add_data_func("/vhost-user/read-guest-mem/memfd",
GINT_TO_POINTER(TEST_MEMFD_YES),
@@ -1018,24 +1039,5 @@ int main(int argc, char **argv)
qtest_add_func("/vhost-user/flags-mismatch", test_flags_mismatch);
}
- ret = g_test_run();
-
- /* cleanup */
-
- /* finish the helper thread and dispatch pending sources */
- g_main_loop_quit(loop);
- g_thread_join(thread);
- while (g_main_context_pending(NULL)) {
- g_main_context_iteration (NULL, TRUE);
- }
- g_main_loop_unref(loop);
-
- ret = rmdir(tmpfs);
- if (ret != 0) {
- g_test_message("unable to rmdir: path (%s): %s\n",
- tmpfs, strerror(errno));
- }
- g_assert_cmpint(ret, ==, 0);
-
- return ret;
+ return g_test_run();
}