pci, pc, virtio: fixes, cleanups, tests

Lots of work on tests: BiosTablesTest UEFI app,
 vhost-user testing for non-Linux hosts.
 Misc cleanups and fixes all over the place
 
 Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 
 iQEcBAABAgAGBQJccBqMAAoJECgfDbjSjVRpvSEIAKYPRNdCBX/SSS/L/tmJS5Zt
 8IyU/HW1YJ249vO+aT6z4Q3QPgqNC3KjXC3brx/WRoPZnRroen4rv2Kqnk6SayPa
 a52d2ubXKWxb3swdG1CAVzFRhq/ABpgAPx0dr1JW+RXgo2lxpJ4GNYxKMosQTaPE
 hRNeXl1XlcIK525kJhFH3Hlij9mTRuY6T7ydpPQd8dUq2dBRaL9RrzZRrkZxCy6l
 gQPUqNzPhG0XXyOiJmwYyVX0zGzbYrMLrMQAor2SBIYmU+zv2eZGPJUYxoMTUMzt
 YR0WCpvkvPITlAryaBoozAIDYVz8PxBRT1KRwpDal+2rzlm6o+veKDiF8R46gn0=
 =GzUz
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging

pci, pc, virtio: fixes, cleanups, tests

Lots of work on tests: BiosTablesTest UEFI app,
vhost-user testing for non-Linux hosts.
Misc cleanups and fixes all over the place

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

# gpg: Signature made Fri 22 Feb 2019 15:51:40 GMT
# gpg:                using RSA key 281F0DB8D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>" [full]
# gpg:                 aka "Michael S. Tsirkin <mst@redhat.com>" [full]
# Primary key fingerprint: 0270 606B 6F3C DF3D 0B17  0970 C350 3912 AFBE 8E67
#      Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA  8A0D 281F 0DB8 D28D 5469

* remotes/mst/tags/for_upstream: (26 commits)
  pci: Sanity test minimum downstream LNKSTA
  hw/smbios: fix offset of type 3 sku field
  pci: Move NVIDIA vendor id to the rest of ids
  virtio-balloon: Safely handle BALLOON_PAGE_SIZE < host page size
  virtio-balloon: Use ram_block_discard_range() instead of raw madvise()
  virtio-balloon: Rework ballon_page() interface
  virtio-balloon: Corrections to address verification
  virtio-balloon: Remove unnecessary MADV_WILLNEED on deflate
  i386/kvm: ignore masked irqs when update msi routes
  contrib/vhost-user-blk: fix the compilation issue
  Revert "contrib/vhost-user-blk: fix the compilation issue"
  pc-dimm: use same mechanism for [get|set]_addr
  tests/data: introduce "uefi-boot-images" with the "bios-tables-test" ISOs
  tests/uefi-test-tools: add build scripts
  tests: introduce "uefi-test-tools" with the BiosTablesTest UEFI app
  roms: build the EfiRom utility from the roms/edk2 submodule
  roms: add the edk2 project as a git submodule
  vhost-user-test: create a temporary directory per TestServer
  vhost-user-test: small changes to init_hugepagefs
  vhost-user-test: create a main loop per TestServer
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2019-03-04 11:04:31 +00:00
commit 1d31f1872b
42 changed files with 1051 additions and 248 deletions

3
.gitmodules vendored
View File

@ -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

View File

@ -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

View File

@ -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

102
configure vendored
View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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

92
hw/net/vhost_net-stub.c Normal file
View File

@ -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;
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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:

View File

@ -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

View File

@ -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;

View File

@ -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
}
/*

View File

@ -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"

View File

@ -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);
}

View File

@ -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

View File

@ -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;

View File

@ -271,4 +271,6 @@
#define PCI_VENDOR_ID_SYNOPSYS 0x16C3
#define PCI_VENDOR_ID_NVIDIA 0x10de
#endif

View File

@ -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

View File

@ -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

View File

@ -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

23
net/vhost-user-stub.c Normal file
View File

@ -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;
}

View File

@ -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,

View File

@ -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

1
roms/edk2 Submodule

@ -0,0 +1 @@
Subproject commit 85588389222a3636baf0f9ed8227f2434af4c3f9

View File

@ -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)

3
tests/uefi-test-tools/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
Build
Conf
log

View File

@ -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.

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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__

View File

@ -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}}

View File

@ -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

145
tests/uefi-test-tools/build.sh Executable file
View File

@ -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"

View File

@ -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();
}