Various fixes for 6.0:

- include kernel-doc API reference for plugins
   - fix semihosting SYS_HEAPINFO
   - various tweaks to improve CI runtime
   - more stroz fixes
   - fix iotest CI regressions
 -----BEGIN PGP SIGNATURE-----
 
 iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAmBbTIgACgkQ+9DbCVqe
 KkTGPQf+LqwQeJswpn6/CMpNikNWM8tGZCr/mWuArQ+7yvjkDImKzrOHFBFylCbA
 /A5FJ4hbeGoDJWzgQERx9iOiwHBsJ6Co3+E5qUiZnfDTyxWW4YBHOSFyBxq4RpEt
 t/f++CIllKQ9u0QQAJnzgmdkrp+mZedrHwkhlaZlMwT3qSzWueAoEsfsc6hkja/U
 lS6uIBWA31VCSh7GS/jRkYBPLA6JjJt1BR9kvcsi6d9OC45iLDe2fUzLC0CLFjnN
 hWliIEh8amkezp+G5IL2ciXA5y0wYMig6ZWg1+8ZknfKQS7pAka6DK9Cr6pvwFaU
 8zrzF+/BqoWLi8VGm9L6kEOUgswNIQ==
 =zrEh
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/stsquad/tags/pull-6.0-rc0-fixed-240321-1' into staging

Various fixes for 6.0:

  - include kernel-doc API reference for plugins
  - fix semihosting SYS_HEAPINFO
  - various tweaks to improve CI runtime
  - more stroz fixes
  - fix iotest CI regressions

# gpg: Signature made Wed 24 Mar 2021 14:28:24 GMT
# gpg:                using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44
# gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full]
# Primary key fingerprint: 6685 AE99 E751 67BC AFC8  DF35 FBD0 DB09 5A9E 2A44

* remotes/stsquad/tags/pull-6.0-rc0-fixed-240321-1: (22 commits)
  gitlab: default to not building the documentation
  iotests: iothreads need ioeventfd
  iotests: test m68k with the virt machine
  iotests: Revert "iotests: use -ccw on s390x for 040, 139, and 182"
  blockdev: with -drive if=virtio, use generic virtio-blk
  m68k: add the virtio devices aliases
  qdev: define list of archs with virtio-pci or virtio-ccw
  gitlab: extend timeouts for CFI builds
  utils: Work around mingw strto*l bug with 0x
  utils: Tighter tests for qemu_strtosz
  cirrus.yml: Update the FreeBSD task to version 12.2
  configure: Don't use the __atomic_*_16 functions for testing 128-bit support
  gitlab-ci.yml: Merge the trace-backend testing into other jobs
  tests/tcg: add HeapInfo checking to semihosting test
  linux-user/riscv: initialise the TaskState heap/stack info
  semihosting/arm-compat-semi: don't use SET_ARG to report SYS_HEAPINFO
  semihosting/arm-compat-semi: unify GET/SET_ARG helpers
  semihosting: move semihosting tests to multiarch
  tools/virtiofsd: include --socket-group in help
  docs/devel: expand style section of memory management
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2021-03-24 14:33:33 +00:00
commit f0b6a6a1a9
43 changed files with 546 additions and 269 deletions

View File

@ -3,7 +3,7 @@ env:
freebsd_12_task:
freebsd_instance:
image_family: freebsd-12-1
image_family: freebsd-12-2
cpu: 8
memory: 8G
install_script:
@ -13,7 +13,10 @@ freebsd_12_task:
script:
- mkdir build
- cd build
- ../configure --enable-werror || { cat config.log meson-logs/meson-log.txt; exit 1; }
# TODO: Enable gnutls again once FreeBSD's libtasn1 got fixed
# See: https://gitlab.com/gnutls/libtasn1/-/merge_requests/71
- ../configure --enable-werror --disable-gnutls
|| { cat config.log meson-logs/meson-log.txt; exit 1; }
- gmake -j$(sysctl -n hw.ncpu)
- gmake -j$(sysctl -n hw.ncpu) check V=1

View File

@ -6,10 +6,10 @@
- mkdir build
- cd build
- PKG_CONFIG_PATH=$PKG_CONFIG_PATH
../configure --enable-werror $QEMU_CONFIGURE_OPTS --disable-user
--target-list-exclude="arm-softmmu cris-softmmu i386-softmmu
microblaze-softmmu mips-softmmu mipsel-softmmu mips64-softmmu
ppc-softmmu sh4-softmmu xtensa-softmmu"
../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
--disable-user --target-list-exclude="arm-softmmu cris-softmmu
i386-softmmu microblaze-softmmu mips-softmmu mipsel-softmmu
mips64-softmmu ppc-softmmu sh4-softmmu xtensa-softmmu"
- make -j$(expr $(nproc) + 1) all check-build $MAKE_CHECK_ARGS
# Job to cross-build specific accelerators.
@ -25,8 +25,8 @@
- mkdir build
- cd build
- PKG_CONFIG_PATH=$PKG_CONFIG_PATH
../configure --enable-werror $QEMU_CONFIGURE_OPTS --disable-tools
--enable-${ACCEL:-kvm} $ACCEL_CONFIGURE_OPTS
../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
--disable-tools --enable-${ACCEL:-kvm} $ACCEL_CONFIGURE_OPTS
- make -j$(expr $(nproc) + 1) all check-build
.cross_user_build_job:
@ -36,7 +36,8 @@
- mkdir build
- cd build
- PKG_CONFIG_PATH=$PKG_CONFIG_PATH
../configure --enable-werror $QEMU_CONFIGURE_OPTS --disable-system
../configure --enable-werror --disable-docs $QEMU_CONFIGURE_OPTS
--disable-system
- make -j$(expr $(nproc) + 1) all check-build $MAKE_CHECK_ARGS
cross-armel-system:

View File

@ -23,9 +23,9 @@ include:
- cd build
- if test -n "$TARGETS";
then
../configure --enable-werror $CONFIGURE_ARGS --target-list="$TARGETS" ;
../configure --enable-werror --disable-docs $CONFIGURE_ARGS --target-list="$TARGETS" ;
else
../configure --enable-werror $CONFIGURE_ARGS ;
../configure --enable-werror --disable-docs $CONFIGURE_ARGS ;
fi || { cat config.log meson-logs/meson-log.txt && exit 1; }
- if test -n "$LD_JOBS";
then
@ -87,7 +87,7 @@ build-system-alpine:
TARGETS: aarch64-softmmu alpha-softmmu cris-softmmu hppa-softmmu
moxie-softmmu microblazeel-softmmu mips64el-softmmu
MAKE_CHECK_ARGS: check-build
CONFIGURE_ARGS: --enable-docs
CONFIGURE_ARGS: --enable-docs --enable-trace-backends=log,simple,syslog
artifacts:
expire_in: 2 days
paths:
@ -119,7 +119,7 @@ build-system-ubuntu:
job: amd64-ubuntu2004-container
variables:
IMAGE: ubuntu2004
CONFIGURE_ARGS: --enable-fdt=system --enable-slirp=system
CONFIGURE_ARGS: --enable-docs --enable-fdt=system --enable-slirp=system
TARGETS: aarch64-softmmu alpha-softmmu cris-softmmu hppa-softmmu
moxie-softmmu microblazeel-softmmu mips64el-softmmu
MAKE_CHECK_ARGS: check-build
@ -502,6 +502,7 @@ build-cfi-aarch64:
--enable-safe-stack --enable-slirp=git
TARGETS: aarch64-softmmu
MAKE_CHECK_ARGS: check-build
timeout: 70m
artifacts:
expire_in: 2 days
paths:
@ -538,6 +539,7 @@ build-cfi-ppc64-s390x:
--enable-safe-stack --enable-slirp=git
TARGETS: ppc64-softmmu s390x-softmmu
MAKE_CHECK_ARGS: check-build
timeout: 70m
artifacts:
expire_in: 2 days
paths:
@ -574,6 +576,7 @@ build-cfi-x86_64:
--enable-safe-stack --enable-slirp=git
TARGETS: x86_64-softmmu
MAKE_CHECK_ARGS: check-build
timeout: 70m
artifacts:
expire_in: 2 days
paths:
@ -604,8 +607,8 @@ tsan-build:
job: amd64-ubuntu2004-container
variables:
IMAGE: ubuntu2004
CONFIGURE_ARGS: --enable-tsan --cc=clang-10 --cxx=clang++-10 --disable-docs
--enable-fdt=system --enable-slirp=system
CONFIGURE_ARGS: --enable-tsan --cc=clang-10 --cxx=clang++-10
--enable-trace-backends=ust --enable-fdt=system --enable-slirp=system
TARGETS: x86_64-softmmu ppc64-softmmu riscv64-softmmu x86_64-linux-user
MAKE_CHECK_ARGS: bench V=1
@ -616,7 +619,7 @@ build-deprecated:
job: amd64-debian-user-cross-container
variables:
IMAGE: debian-all-test-cross
CONFIGURE_ARGS: --disable-docs --disable-tools
CONFIGURE_ARGS: --disable-tools
MAKE_CHECK_ARGS: build-tcg
TARGETS: ppc64abi32-linux-user lm32-softmmu unicore32-softmmu
artifacts:
@ -702,6 +705,7 @@ build-coroutine-sigaltstack:
variables:
IMAGE: ubuntu2004
CONFIGURE_ARGS: --with-coroutine=sigaltstack --disable-tcg
--enable-trace-backends=ftrace
MAKE_CHECK_ARGS: check-unit
# Most jobs test latest gcrypt or nettle builds
@ -739,31 +743,6 @@ crypto-only-gnutls:
MAKE_CHECK_ARGS: check
# We don't need to exercise every backend with every front-end
build-trace-multi-user:
<<: *native_build_job_definition
needs:
job: amd64-ubuntu2004-container
variables:
IMAGE: ubuntu2004
CONFIGURE_ARGS: --enable-trace-backends=log,simple,syslog --disable-system
build-trace-ftrace-system:
<<: *native_build_job_definition
needs:
job: amd64-ubuntu2004-container
variables:
IMAGE: ubuntu2004
CONFIGURE_ARGS: --enable-trace-backends=ftrace --target-list=x86_64-softmmu
build-trace-ust-system:
<<: *native_build_job_definition
needs:
job: amd64-ubuntu2004-container
variables:
IMAGE: ubuntu2004
CONFIGURE_ARGS: --enable-trace-backends=ust --target-list=x86_64-softmmu
# Check our reduced build configurations
build-without-default-devices:
<<: *native_build_job_definition

View File

@ -3286,6 +3286,7 @@ M: Alex Bennée <alex.bennee@linaro.org>
S: Maintained
F: semihosting/
F: include/semihosting/
F: tests/tcg/multiarch/arm-compat-semi/
Multi-process QEMU
M: Elena Ufimtseva <elena.ufimtseva@oracle.com>

View File

@ -962,11 +962,7 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type,
QemuOpts *devopts;
devopts = qemu_opts_create(qemu_find_opts("device"), NULL, 0,
&error_abort);
if (arch_type == QEMU_ARCH_S390X) {
qemu_opt_set(devopts, "driver", "virtio-blk-ccw", &error_abort);
} else {
qemu_opt_set(devopts, "driver", "virtio-blk-pci", &error_abort);
}
qemu_opt_set(devopts, "driver", "virtio-blk", &error_abort);
qemu_opt_set(devopts, "drive", qdict_get_str(bs_opts, "id"),
&error_abort);
}

6
configure vendored
View File

@ -4779,9 +4779,9 @@ if test "$int128" = "yes"; then
int main(void)
{
unsigned __int128 x = 0, y = 0;
y = __atomic_load_16(&x, 0);
__atomic_store_16(&x, y, 0);
__atomic_compare_exchange_16(&x, &y, x, 0, 0, 0);
y = __atomic_load(&x, 0);
__atomic_store(&x, y, 0);
__atomic_compare_exchange(&x, &y, x, 0, 0, 0);
return 0;
}
EOF

View File

@ -385,17 +385,37 @@ avoided.
Low level memory management
===========================
Use of the malloc/free/realloc/calloc/valloc/memalign/posix_memalign
Use of the ``malloc/free/realloc/calloc/valloc/memalign/posix_memalign``
APIs is not allowed in the QEMU codebase. Instead of these routines,
use the GLib memory allocation routines g_malloc/g_malloc0/g_new/
g_new0/g_realloc/g_free or QEMU's qemu_memalign/qemu_blockalign/qemu_vfree
APIs.
use the GLib memory allocation routines
``g_malloc/g_malloc0/g_new/g_new0/g_realloc/g_free``
or QEMU's ``qemu_memalign/qemu_blockalign/qemu_vfree`` APIs.
Please note that g_malloc will exit on allocation failure, so there
is no need to test for failure (as you would have to with malloc).
Calling g_malloc with a zero size is valid and will return NULL.
Please note that ``g_malloc`` will exit on allocation failure, so
there is no need to test for failure (as you would have to with
``malloc``). Generally using ``g_malloc`` on start-up is fine as the
result of a failure to allocate memory is going to be a fatal exit
anyway. There may be some start-up cases where failing is unreasonable
(for example speculatively loading a large debug symbol table).
Prefer g_new(T, n) instead of g_malloc(sizeof(T) ``*`` n) for the following
Care should be taken to avoid introducing places where the guest could
trigger an exit by causing a large allocation. For small allocations,
of the order of 4k, a failure to allocate is likely indicative of an
overloaded host and allowing ``g_malloc`` to ``exit`` is a reasonable
approach. However for larger allocations where we could realistically
fall-back to a smaller one if need be we should use functions like
``g_try_new`` and check the result. For example this is valid approach
for a time/space trade-off like ``tlb_mmu_resize_locked`` in the
SoftMMU TLB code.
If the lifetime of the allocation is within the function and there are
multiple exist paths you can also improve the readability of the code
by using ``g_autofree`` and related annotations. See :ref:`autofree-ref`
for more details.
Calling ``g_malloc`` with a zero size is valid and will return NULL.
Prefer ``g_new(T, n)`` instead of ``g_malloc(sizeof(T) * n)`` for the following
reasons:
* It catches multiplication overflowing size_t;
@ -409,8 +429,8 @@ Declarations like
are acceptable, though.
Memory allocated by qemu_memalign or qemu_blockalign must be freed with
qemu_vfree, since breaking this will cause problems on Win32.
Memory allocated by ``qemu_memalign`` or ``qemu_blockalign`` must be freed with
``qemu_vfree``, since breaking this will cause problems on Win32.
String manipulation
===================
@ -485,6 +505,8 @@ In addition, QEMU assumes that the compiler does not use the latitude
given in C99 and C11 to treat aspects of signed '<<' as undefined, as
documented in the GNU Compiler Collection manual starting at version 4.0.
.. _autofree-ref:
Automatic memory deallocation
=============================

View File

@ -63,6 +63,11 @@ valid during the lifetime of the callback so it is important that any
information that is needed is extracted during the callback and saved
by the plugin.
API
===
.. kernel-doc:: include/qemu/qemu-plugin.h
Usage
=====

View File

@ -35,4 +35,13 @@ extern const uint32_t arch_type;
int kvm_available(void);
int xen_available(void);
/* default virtio transport per architecture */
#define QEMU_ARCH_VIRTIO_PCI (QEMU_ARCH_ALPHA | QEMU_ARCH_ARM | \
QEMU_ARCH_HPPA | QEMU_ARCH_I386 | \
QEMU_ARCH_MIPS | QEMU_ARCH_PPC | \
QEMU_ARCH_RISCV | QEMU_ARCH_SH4 | \
QEMU_ARCH_SPARC | QEMU_ARCH_XTENSA)
#define QEMU_ARCH_VIRTIO_CCW (QEMU_ARCH_S390X)
#define QEMU_ARCH_VIRTIO_MMIO (QEMU_ARCH_M68K)
#endif

View File

@ -135,4 +135,9 @@ void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
error_report("Incompatible ELF: RVE cpu requires RVE ABI binary");
exit(EXIT_FAILURE);
}
ts->stack_base = info->start_stack;
ts->heap_base = info->brk;
/* This will be filled in on the first SYS_HEAPINFO call. */
ts->heap_limit = 0;
}

View File

@ -1745,6 +1745,9 @@ sub dump_function($$) {
)+
\)\)\s+//x;
# Strip QEMU specific compiler annotations
$prototype =~ s/QEMU_[A-Z_]+ +//;
# Yes, this truly is vile. We are looking for:
# 1. Return type (may be nothing if we're looking at a macro)
# 2. Function name

View File

@ -767,15 +767,28 @@ static const GuestFDFunctions guestfd_fns[] = {
},
};
/* Read the input value from the argument block; fail the semihosting
* call if the memory read fails.
/*
* Read the input value from the argument block; fail the semihosting
* call if the memory read fails. Eventually we could use a generic
* CPUState helper function here.
*/
#ifdef TARGET_ARM
static inline bool is_64bit_semihosting(CPUArchState *env)
{
#if defined(TARGET_ARM)
return is_a64(env);
#elif defined(TARGET_RISCV)
return !riscv_cpu_is_32bit(env);
#else
#error un-handled architecture
#endif
}
#define GET_ARG(n) do { \
if (is_a64(env)) { \
if (is_64bit_semihosting(env)) { \
if (get_user_u64(arg ## n, args + (n) * 8)) { \
errno = EFAULT; \
return set_swi_errno(cs, -1); \
return set_swi_errno(cs, -1); \
} \
} else { \
if (get_user_u32(arg ## n, args + (n) * 4)) { \
@ -786,41 +799,10 @@ static const GuestFDFunctions guestfd_fns[] = {
} while (0)
#define SET_ARG(n, val) \
(is_a64(env) ? \
(is_64bit_semihosting(env) ? \
put_user_u64(val, args + (n) * 8) : \
put_user_u32(val, args + (n) * 4))
#endif
#ifdef TARGET_RISCV
/*
* get_user_ual is defined as get_user_u32 in softmmu-semi.h,
* we need a macro that fetches a target_ulong
*/
#define get_user_utl(arg, p) \
((sizeof(target_ulong) == 8) ? \
get_user_u64(arg, p) : \
get_user_u32(arg, p))
/*
* put_user_ual is defined as put_user_u32 in softmmu-semi.h,
* we need a macro that stores a target_ulong
*/
#define put_user_utl(arg, p) \
((sizeof(target_ulong) == 8) ? \
put_user_u64(arg, p) : \
put_user_u32(arg, p))
#define GET_ARG(n) do { \
if (get_user_utl(arg ## n, args + (n) * sizeof(target_ulong))) { \
errno = EFAULT; \
return set_swi_errno(cs, -1); \
} \
} while (0)
#define SET_ARG(n, val) \
put_user_utl(val, args + (n) * sizeof(target_ulong))
#endif
/*
* Do a semihosting call.
@ -1232,7 +1214,11 @@ target_ulong do_common_semihosting(CPUState *cs)
for (i = 0; i < ARRAY_SIZE(retvals); i++) {
bool fail;
fail = SET_ARG(i, retvals[i]);
if (is_64bit_semihosting(env)) {
fail = put_user_u64(retvals[i], arg0 + i * 8);
} else {
fail = put_user_u32(retvals[i], arg0 + i * 4);
}
if (fail) {
/* Couldn't write back to argument block */

View File

@ -60,34 +60,43 @@ static const QDevAlias qdev_alias_table[] = {
{ "ES1370", "es1370" }, /* -soundhw name */
{ "ich9-ahci", "ahci" },
{ "lsi53c895a", "lsi" },
{ "virtio-9p-ccw", "virtio-9p", QEMU_ARCH_S390X },
{ "virtio-9p-pci", "virtio-9p", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
{ "virtio-balloon-ccw", "virtio-balloon", QEMU_ARCH_S390X },
{ "virtio-balloon-pci", "virtio-balloon",
QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
{ "virtio-blk-ccw", "virtio-blk", QEMU_ARCH_S390X },
{ "virtio-blk-pci", "virtio-blk", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
{ "virtio-gpu-ccw", "virtio-gpu", QEMU_ARCH_S390X },
{ "virtio-gpu-pci", "virtio-gpu", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
{ "virtio-input-host-ccw", "virtio-input-host", QEMU_ARCH_S390X },
{ "virtio-input-host-pci", "virtio-input-host",
QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
{ "virtio-iommu-pci", "virtio-iommu", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
{ "virtio-keyboard-ccw", "virtio-keyboard", QEMU_ARCH_S390X },
{ "virtio-keyboard-pci", "virtio-keyboard",
QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
{ "virtio-mouse-ccw", "virtio-mouse", QEMU_ARCH_S390X },
{ "virtio-mouse-pci", "virtio-mouse", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
{ "virtio-net-ccw", "virtio-net", QEMU_ARCH_S390X },
{ "virtio-net-pci", "virtio-net", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
{ "virtio-rng-ccw", "virtio-rng", QEMU_ARCH_S390X },
{ "virtio-rng-pci", "virtio-rng", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
{ "virtio-scsi-ccw", "virtio-scsi", QEMU_ARCH_S390X },
{ "virtio-scsi-pci", "virtio-scsi", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
{ "virtio-serial-ccw", "virtio-serial", QEMU_ARCH_S390X },
{ "virtio-serial-pci", "virtio-serial", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
{ "virtio-tablet-ccw", "virtio-tablet", QEMU_ARCH_S390X },
{ "virtio-tablet-pci", "virtio-tablet", QEMU_ARCH_ALL & ~QEMU_ARCH_S390X },
{ "virtio-9p-device", "virtio-9p", QEMU_ARCH_VIRTIO_MMIO },
{ "virtio-9p-ccw", "virtio-9p", QEMU_ARCH_VIRTIO_CCW },
{ "virtio-9p-pci", "virtio-9p", QEMU_ARCH_VIRTIO_PCI },
{ "virtio-balloon-device", "virtio-balloon", QEMU_ARCH_VIRTIO_MMIO },
{ "virtio-balloon-ccw", "virtio-balloon", QEMU_ARCH_VIRTIO_CCW },
{ "virtio-balloon-pci", "virtio-balloon", QEMU_ARCH_VIRTIO_PCI },
{ "virtio-blk-device", "virtio-blk", QEMU_ARCH_VIRTIO_MMIO },
{ "virtio-blk-ccw", "virtio-blk", QEMU_ARCH_VIRTIO_CCW },
{ "virtio-blk-pci", "virtio-blk", QEMU_ARCH_VIRTIO_PCI },
{ "virtio-gpu-device", "virtio-gpu", QEMU_ARCH_VIRTIO_MMIO },
{ "virtio-gpu-ccw", "virtio-gpu", QEMU_ARCH_VIRTIO_CCW },
{ "virtio-gpu-pci", "virtio-gpu", QEMU_ARCH_VIRTIO_PCI },
{ "virtio-input-host-device", "virtio-input-host", QEMU_ARCH_VIRTIO_MMIO },
{ "virtio-input-host-ccw", "virtio-input-host", QEMU_ARCH_VIRTIO_CCW },
{ "virtio-input-host-pci", "virtio-input-host", QEMU_ARCH_VIRTIO_PCI },
{ "virtio-iommu-pci", "virtio-iommu", QEMU_ARCH_VIRTIO_PCI },
{ "virtio-keyboard-device", "virtio-keyboard", QEMU_ARCH_VIRTIO_MMIO },
{ "virtio-keyboard-ccw", "virtio-keyboard", QEMU_ARCH_VIRTIO_CCW },
{ "virtio-keyboard-pci", "virtio-keyboard", QEMU_ARCH_VIRTIO_PCI },
{ "virtio-mouse-device", "virtio-mouse", QEMU_ARCH_VIRTIO_MMIO },
{ "virtio-mouse-ccw", "virtio-mouse", QEMU_ARCH_VIRTIO_CCW },
{ "virtio-mouse-pci", "virtio-mouse", QEMU_ARCH_VIRTIO_PCI },
{ "virtio-net-device", "virtio-net", QEMU_ARCH_VIRTIO_MMIO },
{ "virtio-net-ccw", "virtio-net", QEMU_ARCH_VIRTIO_CCW },
{ "virtio-net-pci", "virtio-net", QEMU_ARCH_VIRTIO_PCI },
{ "virtio-rng-device", "virtio-rng", QEMU_ARCH_VIRTIO_MMIO },
{ "virtio-rng-ccw", "virtio-rng", QEMU_ARCH_VIRTIO_CCW },
{ "virtio-rng-pci", "virtio-rng", QEMU_ARCH_VIRTIO_PCI },
{ "virtio-scsi-device", "virtio-scsi", QEMU_ARCH_VIRTIO_MMIO },
{ "virtio-scsi-ccw", "virtio-scsi", QEMU_ARCH_VIRTIO_CCW },
{ "virtio-scsi-pci", "virtio-scsi", QEMU_ARCH_VIRTIO_PCI },
{ "virtio-serial-device", "virtio-serial", QEMU_ARCH_VIRTIO_MMIO },
{ "virtio-serial-ccw", "virtio-serial", QEMU_ARCH_VIRTIO_CCW },
{ "virtio-serial-pci", "virtio-serial", QEMU_ARCH_VIRTIO_PCI},
{ "virtio-tablet-device", "virtio-tablet", QEMU_ARCH_VIRTIO_MMIO },
{ "virtio-tablet-ccw", "virtio-tablet", QEMU_ARCH_VIRTIO_CCW },
{ "virtio-tablet-pci", "virtio-tablet", QEMU_ARCH_VIRTIO_PCI },
{ }
};

View File

@ -89,7 +89,7 @@ class TestSingleDrive(ImageCommitTestCase):
qemu_io('-f', 'raw', '-c', 'write -P 0xab 0 524288', backing_img)
qemu_io('-f', iotests.imgfmt, '-c', 'write -P 0xef 524288 524288', mid_img)
self.vm = iotests.VM().add_drive(test_img, "node-name=top,backing.node-name=mid,backing.backing.node-name=base", interface="none")
self.vm.add_device(iotests.get_virtio_scsi_device())
self.vm.add_device('virtio-scsi')
self.vm.add_device("scsi-hd,id=scsi0,drive=drive0")
self.vm.launch()
self.has_quit = False

View File

@ -119,17 +119,7 @@ echo
echo === Device without drive ===
echo
case "$QEMU_DEFAULT_MACHINE" in
s390-ccw-virtio)
virtio_scsi=virtio-scsi-ccw
;;
*)
virtio_scsi=virtio-scsi-pci
;;
esac
run_qemu -device $virtio_scsi -device scsi-hd |
sed -e "s/$virtio_scsi/VIRTIO_SCSI/"
run_qemu -device virtio-scsi -device scsi-hd
echo
echo === Overriding backing file ===

View File

@ -72,7 +72,7 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,node-name=foo#12: Invalid node name
=== Device without drive ===
Testing: -device VIRTIO_SCSI -device scsi-hd
Testing: -device virtio-scsi -device scsi-hd
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) QEMU_PROG: -device scsi-hd: drive property not set

View File

@ -72,7 +72,7 @@ QEMU_PROG: -drive file=TEST_DIR/t.qcow2,node-name=foo#12: Invalid node-name: 'fo
=== Device without drive ===
Testing: -device VIRTIO_SCSI -device scsi-hd
Testing: -device virtio-scsi -device scsi-hd
QEMU X.Y.Z monitor - type 'help' for more information
(qemu) QEMU_PROG: -device scsi-hd: drive property not set

View File

@ -49,11 +49,9 @@ IMG_SIZE=128K
case "$QEMU_DEFAULT_MACHINE" in
s390-ccw-virtio)
platform_parm="-no-shutdown"
hba=virtio-scsi-ccw
;;
*)
platform_parm=""
hba=virtio-scsi-pci
;;
esac
@ -61,7 +59,7 @@ _qemu()
{
$QEMU $platform_parm -nographic -monitor stdio -serial none \
-drive if=none,id=drive0,file="$TEST_IMG",format="$IMGFMT" \
-device $hba,id=hba0 \
-device virtio-scsi,id=hba0 \
-device scsi-hd,drive=drive0 \
"$@" |\
_filter_qemu | _filter_hmp

View File

@ -371,8 +371,7 @@ class ThrottleTestGroupNames(iotests.QMPTestCase):
class ThrottleTestRemovableMedia(iotests.QMPTestCase):
def setUp(self):
self.vm = iotests.VM()
self.vm.add_device("{},id=virtio-scsi".format(
iotests.get_virtio_scsi_device()))
self.vm.add_device("{},id=virtio-scsi".format('virtio-scsi'))
self.vm.launch()
def tearDown(self):

View File

@ -44,7 +44,8 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
_supported_fmt qcow2
_supported_proto file fuse
_require_devices virtio-scsi scsi-hd
_require_devices scsi-hd
_require_one_device_of virtio-scsi-pci virtio-scsi-ccw
IMG_SIZE=64K

View File

@ -26,18 +26,13 @@ import time
base_img = os.path.join(iotests.test_dir, 'base.img')
new_img = os.path.join(iotests.test_dir, 'new.img')
if iotests.qemu_default_machine == 's390-ccw-virtio':
default_virtio_blk = 'virtio-blk-ccw'
else:
default_virtio_blk = 'virtio-blk-pci'
class TestBlockdevDel(iotests.QMPTestCase):
def setUp(self):
iotests.qemu_img('create', '-f', iotests.imgfmt, base_img, '1M')
self.vm = iotests.VM()
self.vm.add_device("{},id=virtio-scsi".format(
iotests.get_virtio_scsi_device()))
self.vm.add_device("{},id=virtio-scsi".format('virtio-scsi'))
self.vm.launch()
def tearDown(self):
@ -93,7 +88,7 @@ class TestBlockdevDel(iotests.QMPTestCase):
self.checkBlockDriverState(node, expect_error)
# Add a device model
def addDeviceModel(self, device, backend, driver = default_virtio_blk):
def addDeviceModel(self, device, backend, driver = 'virtio-blk'):
result = self.vm.qmp('device_add', id = device,
driver = driver, drive = backend)
self.assert_qmp(result, 'return', {})

View File

@ -46,26 +46,17 @@ _supported_proto file
size=32M
case "$QEMU_DEFAULT_MACHINE" in
s390-ccw-virtio)
virtioblk=virtio-blk-ccw
;;
*)
virtioblk=virtio-blk-pci
;;
esac
_make_test_img $size
echo "Starting QEMU"
_launch_qemu -drive file=$TEST_IMG,if=none,id=drive0,file.locking=on \
-device $virtioblk,drive=drive0
-device virtio-blk,drive=drive0
echo
echo "Starting a second QEMU using the same image should fail"
echo 'quit' | $QEMU -nographic -monitor stdio \
-drive file=$TEST_IMG,if=none,id=drive0,file.locking=on \
-device $virtioblk,drive=drive0 2>&1 | _filter_testdir 2>&1 |
-device virtio-blk,drive=drive0 2>&1 | _filter_testdir 2>&1 |
_filter_qemu |
sed -e '/falling back to POSIX file/d' \
-e '/locks can be lost unexpectedly/d'

View File

@ -26,14 +26,12 @@ from iotests import log
iotests.script_initialize()
virtio_scsi_device = iotests.get_virtio_scsi_device()
vm = iotests.VM()
vm.launch()
log(vm.qmp('blockdev-add', node_name='hd0', driver='null-co', read_zeroes=True))
log(vm.qmp('object-add', qom_type='iothread', id='iothread0'))
log(vm.qmp('device_add', id='scsi0', driver=virtio_scsi_device, iothread='iothread0'))
log(vm.qmp('device_add', id='scsi0', driver='virtio-scsi', iothread='iothread0'))
log(vm.qmp('device_add', id='scsi-hd0', driver='scsi-hd', drive='hd0'))
log(vm.qmp('block_set_io_throttle', id='scsi-hd0', bps=0, bps_rd=0, bps_wr=0,
iops=1000, iops_rd=0, iops_wr=0, conv_keys=False))

View File

@ -42,7 +42,7 @@ class TestCase(iotests.QMPTestCase):
iotests.log('==Unplug a SCSI disk and then plug it again==')
self.vm.qmp_log('blockdev-add', driver='null-co', read_zeroes=True, node_name='hd0')
self.vm.qmp_log('object-add', qom_type='iothread', id="iothread0")
self.vm.qmp_log('device_add', id='scsi0', driver=iotests.get_virtio_scsi_device(), iothread='iothread0', filters=[iotests.filter_qmp_virtio_scsi])
self.vm.qmp_log('device_add', id='scsi0', driver='virtio-scsi', iothread='iothread0', filters=[iotests.filter_qmp_virtio_scsi])
self.vm.qmp_log('device_add', id='scsi-hd0', driver='scsi-hd', drive='hd0')
self.vm.qmp_log('device_del', id='scsi-hd0')
self.vm.event_wait('DEVICE_DELETED')
@ -55,7 +55,7 @@ class TestCase(iotests.QMPTestCase):
iotests.log('==Attach two SCSI disks using the same block device and the same iothread==')
self.vm.qmp_log('blockdev-add', driver='null-co', read_zeroes=True, node_name='hd0', read_only=True)
self.vm.qmp_log('object-add', qom_type='iothread', id="iothread0")
self.vm.qmp_log('device_add', id='scsi0', driver=iotests.get_virtio_scsi_device(), iothread='iothread0', filters=[iotests.filter_qmp_virtio_scsi])
self.vm.qmp_log('device_add', id='scsi0', driver='virtio-scsi', iothread='iothread0', filters=[iotests.filter_qmp_virtio_scsi])
self.vm.qmp_log('device_add', id='scsi-hd0', driver='scsi-hd', drive='hd0')
self.vm.qmp_log('device_add', id='scsi-hd1', driver='scsi-hd', drive='hd0')
@ -73,8 +73,8 @@ class TestCase(iotests.QMPTestCase):
self.vm.qmp_log('object-add', qom_type='iothread', id="iothread0")
self.vm.qmp_log('object-add', qom_type='iothread', id="iothread1")
self.vm.qmp_log('device_add', id='scsi0', driver=iotests.get_virtio_scsi_device(), iothread='iothread0', filters=[iotests.filter_qmp_virtio_scsi])
self.vm.qmp_log('device_add', id='scsi1', driver=iotests.get_virtio_scsi_device(), iothread='iothread1', filters=[iotests.filter_qmp_virtio_scsi])
self.vm.qmp_log('device_add', id='scsi0', driver='virtio-scsi', iothread='iothread0', filters=[iotests.filter_qmp_virtio_scsi])
self.vm.qmp_log('device_add', id='scsi1', driver='virtio-scsi', iothread='iothread1', filters=[iotests.filter_qmp_virtio_scsi])
self.vm.qmp_log('device_add', id='scsi-hd0', driver='scsi-hd', drive='hd0', bus="scsi0.0")
self.vm.qmp_log('device_add', id='scsi-hd1', driver='scsi-hd', drive='hd0', bus="scsi1.0")
@ -99,7 +99,7 @@ class TestCase(iotests.QMPTestCase):
self.vm.qmp_log('nbd-server-add', device='hd0')
self.vm.qmp_log('object-add', qom_type='iothread', id="iothread0")
self.vm.qmp_log('device_add', id='scsi0', driver=iotests.get_virtio_scsi_device(), iothread='iothread0', filters=[iotests.filter_qmp_virtio_scsi])
self.vm.qmp_log('device_add', id='scsi0', driver='virtio-scsi', iothread='iothread0', filters=[iotests.filter_qmp_virtio_scsi])
self.vm.qmp_log('device_add', id='scsi-hd0', driver='scsi-hd', drive='hd0')
if __name__ == '__main__':

View File

@ -24,6 +24,8 @@ import os
import iotests
from iotests import log
iotests._verify_virtio_scsi_pci_or_ccw()
iotests.script_initialize(supported_fmts=['qcow2'])
size = 64 * 1024 * 1024
@ -61,8 +63,8 @@ with iotests.FilePath('img0') as img0_path, \
log('--- Preparing images & VM ---\n')
vm.add_object('iothread,id=iothread0')
vm.add_object('iothread,id=iothread1')
vm.add_device('virtio-scsi-pci,id=scsi0,iothread=iothread0')
vm.add_device('virtio-scsi-pci,id=scsi1,iothread=iothread1')
vm.add_device('virtio-scsi,id=scsi0,iothread=iothread0')
vm.add_device('virtio-scsi,id=scsi1,iothread=iothread1')
iotests.qemu_img_create('-f', iotests.imgfmt, img0_path, str(size))
iotests.qemu_img_create('-f', iotests.imgfmt, img1_path, str(size))
vm.add_drive(img0_path, interface='none')

View File

@ -292,7 +292,7 @@ def test_bitmap_sync(bsync_mode, msync_mode='bitmap', failure=None):
log('--- Preparing image & VM ---\n')
drive0 = Drive(img_path, vm=vm)
drive0.img_create(iotests.imgfmt, SIZE)
vm.add_device("{},id=scsi0".format(iotests.get_virtio_scsi_device()))
vm.add_device("{},id=scsi0".format('virtio-scsi'))
vm.launch()
file_config = {
@ -449,7 +449,7 @@ def test_backup_api():
log('--- Preparing image & VM ---\n')
drive0 = Drive(img_path, vm=vm)
drive0.img_create(iotests.imgfmt, SIZE)
vm.add_device("{},id=scsi0".format(iotests.get_virtio_scsi_device()))
vm.add_device("{},id=scsi0".format('virtio-scsi'))
vm.launch()
file_config = {

View File

@ -40,13 +40,11 @@ with iotests.FilePath('image') as img, \
iotests.log('=== Launch VM ===')
virtio_scsi_device = iotests.get_virtio_scsi_device()
vm.add_object('iothread,id=iothread0')
vm.add_blockdev(f'file,filename={img},node-name=file')
vm.add_blockdev(f'{iotests.imgfmt},file=file,node-name=fmt')
vm.add_blockdev('raw,file=file,node-name=ro,read-only=on')
vm.add_device(f'id=scsi0,driver={virtio_scsi_device},iothread=iothread0')
vm.add_device(f'id=scsi0,driver=virtio-scsi,iothread=iothread0')
vm.launch()
vm.qmp_log('nbd-server-start',

View File

@ -977,5 +977,18 @@ _require_devices()
done
}
_require_one_device_of()
{
available=$($QEMU -M none -device help | \
grep ^name | sed -e 's/^name "//' -e 's/".*$//')
for device
do
if echo "$available" | grep -q "$device" ; then
return
fi
done
_notrun "$* not available"
}
# make sure this script returns success
true

View File

@ -234,11 +234,6 @@ def qemu_io_silent_check(*args):
stderr=subprocess.STDOUT)
return exitcode == 0
def get_virtio_scsi_device():
if qemu_default_machine == 's390-ccw-virtio':
return 'virtio-scsi-ccw'
return 'virtio-scsi-pci'
class QemuIoInteractive:
def __init__(self, *args):
self.args = qemu_io_args_no_fmt + list(args)
@ -1151,6 +1146,11 @@ def _verify_virtio_blk() -> None:
if 'virtio-blk' not in out:
notrun('Missing virtio-blk in QEMU binary')
def _verify_virtio_scsi_pci_or_ccw() -> None:
out = qemu_pipe('-M', 'none', '-device', 'help')
if 'virtio-scsi-pci' not in out and 'virtio-scsi-ccw' not in out:
notrun('Missing virtio-scsi-pci or virtio-scsi-ccw in QEMU binary')
def supports_quorum():
return 'quorum' in qemu_img_pipe('--help')

View File

@ -208,6 +208,7 @@ class TestEnv(ContextManager['TestEnv']):
('arm', 'virt'),
('aarch64', 'virt'),
('avr', 'mega2560'),
('m68k', 'virt'),
('rx', 'gdbsim-r5f562n8'),
('tricore', 'tricore_testboard')
)

View File

@ -32,6 +32,9 @@
all:
-include ../../../config-host.mak
-include ../config-$(TARGET).mak
ifeq ($(CONFIG_USER_ONLY),y)
-include $(SRC_PATH)/default-configs/targets/$(TARGET).mak
endif
# for including , in command strings
COMMA := ,

View File

@ -41,24 +41,6 @@ AARCH64_TESTS += mte-1 mte-2 mte-3 mte-4
mte-%: CFLAGS += -march=armv8.5-a+memtag
endif
# Semihosting smoke test for linux-user
AARCH64_TESTS += semihosting
run-semihosting: semihosting
$(call run-test,$<,$(QEMU) $< 2> $<.err, "$< on $(TARGET_NAME)")
run-plugin-semihosting-with-%:
$(call run-test, $@, $(QEMU) $(QEMU_OPTS) \
-plugin $(PLUGIN_LIB)/$(call extract-plugin,$@) \
$(call strip-plugin,$<) 2> $<.err, \
"$< on $(TARGET_NAME) with $*")
AARCH64_TESTS += semiconsole
run-semiconsole: semiconsole
$(call skip-test, $<, "MANUAL ONLY")
run-plugin-semiconsole-with-%:
$(call skip-test, $<, "MANUAL ONLY")
ifneq ($(DOCKER_IMAGE)$(CROSS_CC_HAS_SVE),)
# System Registers Tests
AARCH64_TESTS += sysregs

View File

@ -0,0 +1,18 @@
/*
* Semihosting Tests - AArch64 helper
*
* Copyright (c) 2019
* Written by Alex Bennée <alex.bennee@linaro.org>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
uintptr_t __semi_call(uintptr_t type, uintptr_t arg0)
{
register uintptr_t t asm("x0") = type;
register uintptr_t a0 asm("x1") = arg0;
asm("hlt 0xf000"
: "=r" (t)
: "r" (t), "r" (a0));
return t;
}

View File

@ -29,37 +29,31 @@ run-fcvt: fcvt
$(call run-test,fcvt,$(QEMU) $<,"$< on $(TARGET_NAME)")
$(call diff-out,fcvt,$(ARM_SRC)/fcvt.ref)
ifeq ($(CONFIG_ARM_COMPATIBLE_SEMIHOSTING),y)
# Semihosting smoke test for linux-user
ARM_TESTS += semihosting
semihosting: CFLAGS += -mthumb
run-semihosting: semihosting
$(call run-test,$<,$(QEMU) $< 2> $<.err, "$< on $(TARGET_NAME)")
ARM_TESTS += semihosting-arm
semihosting-arm: CFLAGS += -marm
semihosting-arm: CFLAGS += -marm -I$(SRC_PATH)/tests/tcg/$(TARGET_NAME)
semihosting-arm: semihosting.c
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS)
run-semihosting-arm: semihosting-arm
$(call run-test,$<,$(QEMU) $< 2> $<.err, "$< on $(TARGET_NAME)")
run-plugin-semihosting-with-%:
run-plugin-semihosting-arm-with-%:
$(call run-test, $@, $(QEMU) $(QEMU_OPTS) \
-plugin $(PLUGIN_LIB)/$(call extract-plugin,$@) \
$(call strip-plugin,$<) 2> $<.err, \
"$< on $(TARGET_NAME) with $*")
ARM_TESTS += semiconsole semiconsole-arm
ARM_TESTS += semiconsole-arm
semiconsole: CFLAGS += -mthumb
run-semiconsole: semiconsole
$(call skip-test, $<, "MANUAL ONLY")
run-plugin-semiconsole-with-%:
$(call skip-test, $<, "MANUAL ONLY")
semiconsole-arm: CFLAGS += -marm
semiconsole-arm: semiconsole.c
semiconsole-arm: CFLAGS += -marm -I$(SRC_PATH)/tests/tcg/$(TARGET_NAME)
semiconsole-arm: semihosting.c
$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS)
run-semiconsole-arm: semiconsole-arm
@ -68,6 +62,8 @@ run-semiconsole-arm: semiconsole-arm
run-plugin-semiconsole-arm-with-%:
$(call skip-test, $<, "MANUAL ONLY")
endif
ARM_TESTS += commpage
TESTS += $(ARM_TESTS)

View File

@ -1,5 +1,5 @@
/*
* Semihosting Tests
* Semihosting Tests - ARM Helper
*
* Copyright (c) 2019
* Written by Alex Bennée <alex.bennee@linaro.org>
@ -7,13 +7,8 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#define SYS_WRITE0 0x04
#define SYS_READC 0x07
#define SYS_REPORTEXC 0x18
uintptr_t __semi_call(uintptr_t type, uintptr_t arg0)
{
#if defined(__arm__)
register uintptr_t t asm("r0") = type;
register uintptr_t a0 asm("r1") = arg0;
#ifdef __thumb__
@ -23,13 +18,5 @@ uintptr_t __semi_call(uintptr_t type, uintptr_t arg0)
#endif
asm(SVC : "=r" (t)
: "r" (t), "r" (a0));
#else
register uintptr_t t asm("x0") = type;
register uintptr_t a0 asm("x1") = arg0;
asm("hlt 0xf000"
: "=r" (t)
: "r" (t), "r" (a0));
#endif
return t;
}

View File

@ -1,26 +0,0 @@
/*
* linux-user semihosting checks
*
* Copyright (c) 2019
* Written by Alex Bennée <alex.bennee@linaro.org>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#include <stdint.h>
#include "semicall.h"
int main(int argc, char *argv[argc])
{
#if defined(__arm__)
uintptr_t exit_code = 0x20026;
#else
uintptr_t exit_block[2] = {0x20026, 0};
uintptr_t exit_code = (uintptr_t) &exit_block;
#endif
__semi_call(SYS_WRITE0, (uintptr_t) "Hello World");
__semi_call(SYS_REPORTEXC, exit_code);
/* if we get here we failed */
return -1;
}

View File

@ -69,6 +69,37 @@ run-gdbstub-%:
endif
EXTRA_RUNS += run-gdbstub-sha1 run-gdbstub-qxfer-auxv-read
# ARM Compatible Semi Hosting Tests
#
# Despite having ARM in the name we actually have several
# architectures that implement it. We gate the tests on the feature
# appearing in config.
#
ifeq ($(CONFIG_ARM_COMPATIBLE_SEMIHOSTING),y)
VPATH += $(MULTIARCH_SRC)/arm-compat-semi
# Add -I path back to TARGET_NAME for semicall.h
semihosting: CFLAGS+=-I$(SRC_PATH)/tests/tcg/$(TARGET_NAME)
run-semihosting: semihosting
$(call run-test,$<,$(QEMU) $< 2> $<.err, "$< on $(TARGET_NAME)")
run-plugin-semihosting-with-%:
$(call run-test, $@, $(QEMU) $(QEMU_OPTS) \
-plugin $(PLUGIN_LIB)/$(call extract-plugin,$@) \
$(call strip-plugin,$<) 2> $<.err, \
"$< on $(TARGET_NAME) with $*")
semiconsole: CFLAGS+=-I$(SRC_PATH)/tests/tcg/$(TARGET_NAME)
run-semiconsole: semiconsole
$(call skip-test, $<, "MANUAL ONLY")
run-plugin-semiconsole-with-%:
$(call skip-test, $<, "MANUAL ONLY")
TESTS += semihosting semiconsole
endif
# Update TESTS
TESTS += $(MULTIARCH_TESTS)

View File

@ -7,6 +7,8 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#define SYS_READC 0x07
#include <stdio.h>
#include <stdint.h>
#include "semicall.h"

View File

@ -0,0 +1,82 @@
/*
* linux-user semihosting checks
*
* Copyright (c) 2019
* Written by Alex Bennée <alex.bennee@linaro.org>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
#define SYS_WRITE0 0x04
#define SYS_HEAPINFO 0x16
#define SYS_REPORTEXC 0x18
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "semicall.h"
int main(int argc, char *argv[argc])
{
#if UINTPTR_MAX == UINT32_MAX
uintptr_t exit_code = 0x20026;
#else
uintptr_t exit_block[2] = {0x20026, 0};
uintptr_t exit_code = (uintptr_t) &exit_block;
#endif
struct {
void *heap_base;
void *heap_limit;
void *stack_base;
void *stack_limit;
} info;
void *ptr_to_info = (void *) &info;
__semi_call(SYS_WRITE0, (uintptr_t) "Checking HeapInfo\n");
memset(&info, 0, sizeof(info));
__semi_call(SYS_HEAPINFO, (uintptr_t) &ptr_to_info);
if (info.heap_base == NULL || info.heap_limit == NULL) {
printf("null heap: %p -> %p\n", info.heap_base, info.heap_limit);
exit(1);
}
/* Error if heap base is above limit */
if ((uintptr_t) info.heap_base >= (uintptr_t) info.heap_limit) {
printf("heap base %p >= heap_limit %p\n",
info.heap_base, info.heap_limit);
exit(2);
}
if (info.stack_base == NULL || info.stack_limit) {
printf("null stack: %p -> %p\n", info.stack_base, info.stack_limit);
exit(3);
}
/* check our local variables are indeed inside the reported stack */
if (ptr_to_info > info.stack_base) {
printf("info appears to be above stack: %p > %p\n", ptr_to_info,
info.stack_base);
exit(4);
} else if (ptr_to_info < info.stack_limit) {
printf("info appears to be outside stack: %p < %p\n", ptr_to_info,
info.stack_limit);
exit(5);
}
if (ptr_to_info > info.heap_base && ptr_to_info < info.heap_limit) {
printf("info appears to be inside the heap: %p in %p:%p\n",
ptr_to_info, info.heap_base, info.heap_limit);
exit(6);
}
printf("heap: %p -> %p\n", info.heap_base, info.heap_limit);
printf("stack: %p -> %p\n", info.stack_base, info.stack_limit);
__semi_call(SYS_WRITE0, (uintptr_t) "Passed HeapInfo checks");
__semi_call(SYS_REPORTEXC, exit_code);
/* if we get here we failed */
return -1;
}

View File

@ -0,0 +1,22 @@
/*
* Semihosting Tests - RiscV64 Helper
*
* Copyright (c) 2021
* Written by Alex Bennée <alex.bennee@linaro.org>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
uintptr_t __semi_call(uintptr_t type, uintptr_t arg0)
{
register uintptr_t t asm("a0") = type;
register uintptr_t a0 asm("a1") = arg0;
asm(".option norvc\n\t"
".balign 16\n\t"
"slli zero, zero, 0x1f\n\t"
"ebreak\n\t"
"srai zero, zero, 0x7\n\t"
: "=r" (t)
: "r" (t), "r" (a0));
return t;
}

View File

@ -378,6 +378,15 @@ static void test_qemu_strtoi_hex(void)
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 0x123);
g_assert(endptr == str + strlen(str));
str = "0x";
res = 999;
endptr = &f;
err = qemu_strtoi(str, &endptr, 16, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 0);
g_assert(endptr == str + 1);
}
static void test_qemu_strtoi_max(void)
@ -669,6 +678,15 @@ static void test_qemu_strtoui_hex(void)
g_assert_cmpint(err, ==, 0);
g_assert_cmphex(res, ==, 0x123);
g_assert(endptr == str + strlen(str));
str = "0x";
res = 999;
endptr = &f;
err = qemu_strtoui(str, &endptr, 16, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmphex(res, ==, 0);
g_assert(endptr == str + 1);
}
static void test_qemu_strtoui_max(void)
@ -955,6 +973,15 @@ static void test_qemu_strtol_hex(void)
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 0x123);
g_assert(endptr == str + strlen(str));
str = "0x";
res = 999;
endptr = &f;
err = qemu_strtol(str, &endptr, 16, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 0);
g_assert(endptr == str + 1);
}
static void test_qemu_strtol_max(void)
@ -1244,6 +1271,15 @@ static void test_qemu_strtoul_hex(void)
g_assert_cmpint(err, ==, 0);
g_assert_cmphex(res, ==, 0x123);
g_assert(endptr == str + strlen(str));
str = "0x";
res = 999;
endptr = &f;
err = qemu_strtoul(str, &endptr, 16, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmphex(res, ==, 0);
g_assert(endptr == str + 1);
}
static void test_qemu_strtoul_max(void)
@ -1528,6 +1564,15 @@ static void test_qemu_strtoi64_hex(void)
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 0x123);
g_assert(endptr == str + strlen(str));
str = "0x";
endptr = &f;
res = 999;
err = qemu_strtoi64(str, &endptr, 16, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 0);
g_assert(endptr == str + 1);
}
static void test_qemu_strtoi64_max(void)
@ -1815,6 +1860,15 @@ static void test_qemu_strtou64_hex(void)
g_assert_cmpint(err, ==, 0);
g_assert_cmphex(res, ==, 0x123);
g_assert(endptr == str + strlen(str));
str = "0x";
endptr = &f;
res = 999;
err = qemu_strtou64(str, &endptr, 16, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmphex(res, ==, 0);
g_assert(endptr == str + 1);
}
static void test_qemu_strtou64_max(void)
@ -1952,9 +2006,11 @@ static void test_qemu_strtosz_simple(void)
const char *str;
const char *endptr;
int err;
uint64_t res = 0xbaadf00d;
uint64_t res;
str = "0";
endptr = str;
res = 0xbaadf00d;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 0);
@ -1962,6 +2018,8 @@ static void test_qemu_strtosz_simple(void)
/* Leading 0 gives decimal results, not octal */
str = "08";
endptr = str;
res = 0xbaadf00d;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 8);
@ -1969,46 +2027,61 @@ static void test_qemu_strtosz_simple(void)
/* Leading space is ignored */
str = " 12345";
endptr = str;
res = 0xbaadf00d;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 12345);
g_assert(endptr == str + 6);
res = 0xbaadf00d;
err = qemu_strtosz(str, NULL, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 12345);
str = "9007199254740991"; /* 2^53-1 */
endptr = str;
res = 0xbaadf00d;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 0x1fffffffffffff);
g_assert(endptr == str + 16);
str = "9007199254740992"; /* 2^53 */
endptr = str;
res = 0xbaadf00d;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 0x20000000000000);
g_assert(endptr == str + 16);
str = "9007199254740993"; /* 2^53+1 */
endptr = str;
res = 0xbaadf00d;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 0x20000000000001);
g_assert(endptr == str + 16);
str = "18446744073709549568"; /* 0xfffffffffffff800 (53 msbs set) */
endptr = str;
res = 0xbaadf00d;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 0xfffffffffffff800);
g_assert(endptr == str + 20);
str = "18446744073709550591"; /* 0xfffffffffffffbff */
endptr = str;
res = 0xbaadf00d;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 0xfffffffffffffbff);
g_assert(endptr == str + 20);
str = "18446744073709551615"; /* 0xffffffffffffffff */
endptr = str;
res = 0xbaadf00d;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 0xffffffffffffffff);
@ -2020,21 +2093,27 @@ static void test_qemu_strtosz_hex(void)
const char *str;
const char *endptr;
int err;
uint64_t res = 0xbaadf00d;
uint64_t res;
str = "0x0";
endptr = str;
res = 0xbaadf00d;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 0);
g_assert(endptr == str + 3);
str = "0xab";
endptr = str;
res = 0xbaadf00d;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 171);
g_assert(endptr == str + 4);
str = "0xae";
endptr = str;
res = 0xbaadf00d;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 174);
@ -2053,44 +2132,60 @@ static void test_qemu_strtosz_units(void)
const char *e = "1E";
int err;
const char *endptr;
uint64_t res = 0xbaadf00d;
uint64_t res;
/* default is M */
endptr = NULL;
res = 0xbaadf00d;
err = qemu_strtosz_MiB(none, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, MiB);
g_assert(endptr == none + 1);
endptr = NULL;
res = 0xbaadf00d;
err = qemu_strtosz(b, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 1);
g_assert(endptr == b + 2);
endptr = NULL;
res = 0xbaadf00d;
err = qemu_strtosz(k, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, KiB);
g_assert(endptr == k + 2);
endptr = NULL;
res = 0xbaadf00d;
err = qemu_strtosz(m, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, MiB);
g_assert(endptr == m + 2);
endptr = NULL;
res = 0xbaadf00d;
err = qemu_strtosz(g, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, GiB);
g_assert(endptr == g + 2);
endptr = NULL;
res = 0xbaadf00d;
err = qemu_strtosz(t, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, TiB);
g_assert(endptr == t + 2);
endptr = NULL;
res = 0xbaadf00d;
err = qemu_strtosz(p, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, PiB);
g_assert(endptr == p + 2);
endptr = NULL;
res = 0xbaadf00d;
err = qemu_strtosz(e, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, EiB);
@ -2102,9 +2197,11 @@ static void test_qemu_strtosz_float(void)
const char *str;
int err;
const char *endptr;
uint64_t res = 0xbaadf00d;
uint64_t res;
str = "0.5E";
endptr = str;
res = 0xbaadf00d;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, EiB / 2);
@ -2112,6 +2209,8 @@ static void test_qemu_strtosz_float(void)
/* For convenience, a fraction of 0 is tolerated even on bytes */
str = "1.0B";
endptr = str;
res = 0xbaadf00d;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 1);
@ -2119,6 +2218,8 @@ static void test_qemu_strtosz_float(void)
/* An empty fraction is tolerated */
str = "1.k";
endptr = str;
res = 0xbaadf00d;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 1024);
@ -2126,6 +2227,8 @@ static void test_qemu_strtosz_float(void)
/* For convenience, we permit values that are not byte-exact */
str = "12.345M";
endptr = str;
res = 0xbaadf00d;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, (uint64_t) (12.345 * MiB + 0.5));
@ -2140,67 +2243,91 @@ static void test_qemu_strtosz_invalid(void)
uint64_t res = 0xbaadf00d;
str = "";
endptr = NULL;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, -EINVAL);
g_assert_cmpint(res, ==, 0xbaadf00d);
g_assert(endptr == str);
str = " \t ";
endptr = NULL;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, -EINVAL);
g_assert_cmpint(res, ==, 0xbaadf00d);
g_assert(endptr == str);
str = "crap";
endptr = NULL;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, -EINVAL);
g_assert_cmpint(res, ==, 0xbaadf00d);
g_assert(endptr == str);
str = "inf";
endptr = NULL;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, -EINVAL);
g_assert_cmpint(res, ==, 0xbaadf00d);
g_assert(endptr == str);
str = "NaN";
endptr = NULL;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, -EINVAL);
g_assert_cmpint(res, ==, 0xbaadf00d);
g_assert(endptr == str);
/* Fractional values require scale larger than bytes */
str = "1.1B";
endptr = NULL;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, -EINVAL);
g_assert_cmpint(res, ==, 0xbaadf00d);
g_assert(endptr == str);
str = "1.1";
endptr = NULL;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, -EINVAL);
g_assert_cmpint(res, ==, 0xbaadf00d);
g_assert(endptr == str);
/* No floating point exponents */
str = "1.5e1k";
endptr = NULL;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, -EINVAL);
g_assert_cmpint(res, ==, 0xbaadf00d);
g_assert(endptr == str);
str = "1.5E+0k";
endptr = NULL;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, -EINVAL);
g_assert_cmpint(res, ==, 0xbaadf00d);
g_assert(endptr == str);
/* No hex fractions */
str = "0x1.8k";
endptr = NULL;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, -EINVAL);
g_assert_cmpint(res, ==, 0xbaadf00d);
g_assert(endptr == str);
/* No negative values */
str = "-0";
endptr = NULL;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, -EINVAL);
g_assert_cmpint(res, ==, 0xbaadf00d);
g_assert(endptr == str);
str = "-1";
endptr = NULL;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, -EINVAL);
g_assert_cmpint(res, ==, 0xbaadf00d);
g_assert(endptr == str);
}
@ -2209,48 +2336,72 @@ static void test_qemu_strtosz_trailing(void)
const char *str;
const char *endptr;
int err;
uint64_t res = 0xbaadf00d;
uint64_t res;
str = "123xxx";
endptr = NULL;
res = 0xbaadf00d;
err = qemu_strtosz_MiB(str, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 123 * MiB);
g_assert(endptr == str + 3);
res = 0xbaadf00d;
err = qemu_strtosz(str, NULL, &res);
g_assert_cmpint(err, ==, -EINVAL);
g_assert_cmpint(res, ==, 0xbaadf00d);
str = "1kiB";
endptr = NULL;
res = 0xbaadf00d;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 1024);
g_assert(endptr == str + 2);
res = 0xbaadf00d;
err = qemu_strtosz(str, NULL, &res);
g_assert_cmpint(err, ==, -EINVAL);
g_assert_cmpint(res, ==, 0xbaadf00d);
str = "0x";
endptr = NULL;
res = 0xbaadf00d;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 0);
g_assert(endptr == str + 1);
res = 0xbaadf00d;
err = qemu_strtosz(str, NULL, &res);
g_assert_cmpint(err, ==, -EINVAL);
g_assert_cmpint(res, ==, 0xbaadf00d);
str = "0.NaN";
endptr = NULL;
res = 0xbaadf00d;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 0);
g_assert(endptr == str + 2);
res = 0xbaadf00d;
err = qemu_strtosz(str, NULL, &res);
g_assert_cmpint(err, ==, -EINVAL);
g_assert_cmpint(res, ==, 0xbaadf00d);
str = "123-45";
endptr = NULL;
res = 0xbaadf00d;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 123);
g_assert(endptr == str + 3);
res = 0xbaadf00d;
err = qemu_strtosz(str, NULL, &res);
g_assert_cmpint(err, ==, -EINVAL);
g_assert_cmpint(res, ==, 0xbaadf00d);
}
static void test_qemu_strtosz_erange(void)
@ -2261,13 +2412,17 @@ static void test_qemu_strtosz_erange(void)
uint64_t res = 0xbaadf00d;
str = "18446744073709551616"; /* 2^64; see strtosz_simple for 2^64-1 */
endptr = NULL;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, -ERANGE);
g_assert_cmpint(res, ==, 0xbaadf00d);
g_assert(endptr == str + 20);
str = "20E";
endptr = NULL;
err = qemu_strtosz(str, &endptr, &res);
g_assert_cmpint(err, ==, -ERANGE);
g_assert_cmpint(res, ==, 0xbaadf00d);
g_assert(endptr == str + 3);
}
@ -2276,15 +2431,19 @@ static void test_qemu_strtosz_metric(void)
const char *str;
int err;
const char *endptr;
uint64_t res = 0xbaadf00d;
uint64_t res;
str = "12345k";
endptr = str;
res = 0xbaadf00d;
err = qemu_strtosz_metric(str, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 12345000);
g_assert(endptr == str + 6);
str = "12.345M";
endptr = str;
res = 0xbaadf00d;
err = qemu_strtosz_metric(str, &endptr, &res);
g_assert_cmpint(err, ==, 0);
g_assert_cmpint(res, ==, 12345000);

View File

@ -2450,6 +2450,7 @@ void fuse_lowlevel_help(void)
printf(
" -o allow_root allow access by root\n"
" --socket-path=PATH path for the vhost-user socket\n"
" --socket-group=GRNAME name of group for the vhost-user socket\n"
" --fd=FDNUM fd number of vhost-user socket\n"
" --thread-pool-size=NUM thread pool size limit (default %d)\n",
THREAD_POOL_SIZE);

View File

@ -362,7 +362,6 @@ static int do_strtosz(const char *nptr, const char **end,
}
}
*result = val;
retval = 0;
out:
@ -371,6 +370,9 @@ out:
} else if (*endptr) {
retval = -EINVAL;
}
if (retval == 0) {
*result = val;
}
return retval;
}
@ -394,9 +396,22 @@ int qemu_strtosz_metric(const char *nptr, const char **end, uint64_t *result)
* Helper function for error checking after strtol() and the like
*/
static int check_strtox_error(const char *nptr, char *ep,
const char **endptr, int libc_errno)
const char **endptr, bool check_zero,
int libc_errno)
{
assert(ep >= nptr);
/* Windows has a bug in that it fails to parse 0 from "0x" in base 16 */
if (check_zero && ep == nptr && libc_errno == 0) {
char *tmp;
errno = 0;
if (strtol(nptr, &tmp, 10) == 0 && errno == 0 &&
(*tmp == 'x' || *tmp == 'X')) {
ep = tmp;
}
}
if (endptr) {
*endptr = ep;
}
@ -463,7 +478,7 @@ int qemu_strtoi(const char *nptr, const char **endptr, int base,
} else {
*result = lresult;
}
return check_strtox_error(nptr, ep, endptr, errno);
return check_strtox_error(nptr, ep, endptr, lresult == 0, errno);
}
/**
@ -522,7 +537,7 @@ int qemu_strtoui(const char *nptr, const char **endptr, int base,
*result = lresult;
}
}
return check_strtox_error(nptr, ep, endptr, errno);
return check_strtox_error(nptr, ep, endptr, lresult == 0, errno);
}
/**
@ -564,7 +579,7 @@ int qemu_strtol(const char *nptr, const char **endptr, int base,
errno = 0;
*result = strtol(nptr, &ep, base);
return check_strtox_error(nptr, ep, endptr, errno);
return check_strtox_error(nptr, ep, endptr, *result == 0, errno);
}
/**
@ -611,7 +626,7 @@ int qemu_strtoul(const char *nptr, const char **endptr, int base,
if (errno == ERANGE) {
*result = -1;
}
return check_strtox_error(nptr, ep, endptr, errno);
return check_strtox_error(nptr, ep, endptr, *result == 0, errno);
}
/**
@ -637,7 +652,7 @@ int qemu_strtoi64(const char *nptr, const char **endptr, int base,
QEMU_BUILD_BUG_ON(sizeof(int64_t) != sizeof(long long));
errno = 0;
*result = strtoll(nptr, &ep, base);
return check_strtox_error(nptr, ep, endptr, errno);
return check_strtox_error(nptr, ep, endptr, *result == 0, errno);
}
/**
@ -666,7 +681,7 @@ int qemu_strtou64(const char *nptr, const char **endptr, int base,
if (errno == ERANGE) {
*result = -1;
}
return check_strtox_error(nptr, ep, endptr, errno);
return check_strtox_error(nptr, ep, endptr, *result == 0, errno);
}
/**
@ -706,7 +721,7 @@ int qemu_strtod(const char *nptr, const char **endptr, double *result)
errno = 0;
*result = strtod(nptr, &ep);
return check_strtox_error(nptr, ep, endptr, errno);
return check_strtox_error(nptr, ep, endptr, false, errno);
}
/**