Various testing and logging updates
- test tci with Travis - enable multiarch testing in Travis - default to out-of-tree builds - make changing logfile safe via RCU - remove redundant tests - remove gtester test from docker - convert DEBUG_MMAP to tracepoints - remove hand rolled glob function - trigger tcg re-configure when needed -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAl37M6gACgkQ+9DbCVqe KkQ0Rwf/d0lGDPQN1Uf0zqZRQQmDCqWVuqHhZJ5xWDjbyVT2eUwR07TvNZeUKEWX iO+u6S7Tv91oLjZN5WjhaiuSjtJaEzCdcpkIJAWXLP/lzse37HEwvLBsdg71y+46 LNvBrJRPpQotdb7fjr8RgCwc1qg2Bz15ekSn7XIA175zTMmUsshLJBVhLbGNqrVm F2UmjB9oFJ0+nzrcEnpFmWw7xvVrX1dImZXv5C2pvuHF7efSjGwiFviTRZgDjOGs V7HiWRV1QcgTigncncxTMbhMTKTVKK+e7O+y0DZWt/NSrT/yLDy5rcwySpmvu6C+ cRmh/0tMo1KAhiz8Xy8LookhVj6hdA== =OAkV -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/stsquad/tags/pull-tesing-and-misc-191219-1' into staging Various testing and logging updates - test tci with Travis - enable multiarch testing in Travis - default to out-of-tree builds - make changing logfile safe via RCU - remove redundant tests - remove gtester test from docker - convert DEBUG_MMAP to tracepoints - remove hand rolled glob function - trigger tcg re-configure when needed # gpg: Signature made Thu 19 Dec 2019 08:24:08 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-tesing-and-misc-191219-1: (25 commits) tests/tcg: ensure we re-configure if configure.sh is updated trace: replace hand-crafted pattern_glob with g_pattern_match_simple linux-user: convert target_munmap debug to a tracepoint linux-user: log page table changes under -d page linux-user: add target_mmap_complete tracepoint linux-user: convert target_mmap debug to tracepoint linux-user: convert target_mprotect debug to tracepoint travis.yml: Remove the redundant clang-with-MAIN_SOFTMMU_TARGETS entry docker: gtester is no longer used Added tests for close and change of logfile. Add use of RCU for qemu_logfile. qemu_log_lock/unlock now preserves the qemu_logfile handle. Add a mutex to guarantee single writer to qemu_logfile handle. Cleaned up flow of code in qemu_set_log(), to simplify and clarify. Fix double free issue in qemu_set_log_filename(). ci: build out-of-tree travis.yml: Enable builds on arm64, ppc64le and s390x tests/test-util-filemonitor: Skip test on non-x86 Travis containers tests/hd-geo-test: Skip test when images can not be created iotests: Skip test 079 if it is not possible to create large files ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
f59b31e6d0
@ -22,7 +22,9 @@ macos_task:
|
||||
install_script:
|
||||
- brew install pkg-config python gnu-sed glib pixman make sdl2
|
||||
script:
|
||||
- ./configure --python=/usr/local/bin/python3 || { cat config.log; exit 1; }
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --python=/usr/local/bin/python3 || { cat config.log; exit 1; }
|
||||
- gmake -j$(sysctl -n hw.ncpu)
|
||||
- gmake check -j$(sysctl -n hw.ncpu)
|
||||
|
||||
@ -33,6 +35,8 @@ macos_xcode_task:
|
||||
install_script:
|
||||
- brew install pkg-config gnu-sed glib pixman make sdl2
|
||||
script:
|
||||
- ./configure --cc=clang || { cat config.log; exit 1; }
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --cc=clang || { cat config.log; exit 1; }
|
||||
- gmake -j$(sysctl -n hw.ncpu)
|
||||
- gmake check -j$(sysctl -n hw.ncpu)
|
||||
|
@ -6,7 +6,9 @@ build-system1:
|
||||
script:
|
||||
- apt-get install -y -qq libgtk-3-dev libvte-dev nettle-dev libcacard-dev
|
||||
libusb-dev libvde-dev libspice-protocol-dev libgl1-mesa-dev libvdeplug-dev
|
||||
- ./configure --enable-werror --target-list="aarch64-softmmu alpha-softmmu
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-werror --target-list="aarch64-softmmu alpha-softmmu
|
||||
cris-softmmu hppa-softmmu lm32-softmmu moxie-softmmu microblazeel-softmmu
|
||||
mips64el-softmmu m68k-softmmu ppc-softmmu riscv64-softmmu sparc-softmmu"
|
||||
- make -j2
|
||||
@ -16,7 +18,9 @@ build-system2:
|
||||
script:
|
||||
- apt-get install -y -qq libsdl2-dev libgcrypt-dev libbrlapi-dev libaio-dev
|
||||
libfdt-dev liblzo2-dev librdmacm-dev libibverbs-dev libibumad-dev
|
||||
- ./configure --enable-werror --target-list="tricore-softmmu unicore32-softmmu
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-werror --target-list="tricore-softmmu unicore32-softmmu
|
||||
microblaze-softmmu mips-softmmu riscv32-softmmu s390x-softmmu sh4-softmmu
|
||||
sparc64-softmmu x86_64-softmmu xtensa-softmmu nios2-softmmu or1k-softmmu"
|
||||
- make -j2
|
||||
@ -24,7 +28,9 @@ build-system2:
|
||||
|
||||
build-disabled:
|
||||
script:
|
||||
- ./configure --enable-werror --disable-rdma --disable-slirp --disable-curl
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-werror --disable-rdma --disable-slirp --disable-curl
|
||||
--disable-capstone --disable-live-block-migration --disable-glusterfs
|
||||
--disable-replication --disable-coroutine-pool --disable-smartcard
|
||||
--disable-guest-agent --disable-curses --disable-libxml2 --disable-tpm
|
||||
@ -37,7 +43,9 @@ build-disabled:
|
||||
build-tcg-disabled:
|
||||
script:
|
||||
- apt-get install -y -qq clang libgtk-3-dev libusb-dev
|
||||
- ./configure --cc=clang --enable-werror --disable-tcg --audio-drv-list=""
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --cc=clang --enable-werror --disable-tcg --audio-drv-list=""
|
||||
- make -j2
|
||||
- make check-unit
|
||||
- make check-qapi-schema
|
||||
@ -52,7 +60,9 @@ build-tcg-disabled:
|
||||
|
||||
build-user:
|
||||
script:
|
||||
- ./configure --enable-werror --disable-system --disable-guest-agent
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-werror --disable-system --disable-guest-agent
|
||||
--disable-capstone --disable-slirp --disable-fdt
|
||||
- make -j2
|
||||
- make run-tcg-tests-i386-linux-user run-tcg-tests-x86_64-linux-user
|
||||
@ -61,7 +71,9 @@ build-clang:
|
||||
script:
|
||||
- apt-get install -y -qq clang libsdl2-dev libattr1-dev libcap-ng-dev
|
||||
xfslibs-dev libiscsi-dev libnfs-dev libseccomp-dev gnutls-dev librbd-dev
|
||||
- ./configure --cc=clang --cxx=clang++ --enable-werror
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --cc=clang --cxx=clang++ --enable-werror
|
||||
--target-list="alpha-softmmu arm-softmmu m68k-softmmu mips64-softmmu
|
||||
ppc-softmmu s390x-softmmu x86_64-softmmu arm-linux-user"
|
||||
- make -j2
|
||||
@ -70,7 +82,9 @@ build-clang:
|
||||
build-tci:
|
||||
script:
|
||||
- TARGETS="aarch64 alpha arm hppa m68k microblaze moxie ppc64 s390x x86_64"
|
||||
- ./configure --enable-tcg-interpreter
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure --enable-tcg-interpreter
|
||||
--target-list="$(for tg in $TARGETS; do echo -n ${tg}'-softmmu '; done)"
|
||||
- make -j2
|
||||
- make tests/boot-serial-test tests/cdrom-test tests/pxe-test
|
||||
|
@ -35,5 +35,7 @@ build:
|
||||
options: "-e HOME=/root"
|
||||
ci:
|
||||
- unset CC
|
||||
- ./configure ${QEMU_CONFIGURE_OPTS} --target-list=${TARGET_LIST}
|
||||
- mkdir build
|
||||
- cd build
|
||||
- ../configure ${QEMU_CONFIGURE_OPTS} --target-list=${TARGET_LIST}
|
||||
- make -j$(($(getconf _NPROCESSORS_ONLN) + 1))
|
||||
|
112
.travis.yml
112
.travis.yml
@ -73,8 +73,8 @@ notifications:
|
||||
|
||||
env:
|
||||
global:
|
||||
- SRC_DIR="."
|
||||
- BUILD_DIR="."
|
||||
- SRC_DIR=".."
|
||||
- BUILD_DIR="build"
|
||||
- BASE_CONFIG="--disable-docs --disable-tools"
|
||||
- TEST_CMD="make check V=1"
|
||||
# This is broadly a list of "mainline" softmmu targets which have support across the major distros
|
||||
@ -180,18 +180,13 @@ matrix:
|
||||
compiler: clang
|
||||
|
||||
|
||||
- env:
|
||||
- CONFIG="--disable-user --target-list=${MAIN_SOFTMMU_TARGETS}"
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-clang-default"
|
||||
compiler: clang
|
||||
|
||||
|
||||
- env:
|
||||
- CONFIG="--target-list=${MAIN_SOFTMMU_TARGETS} "
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-clang-sanitize"
|
||||
compiler: clang
|
||||
before_script:
|
||||
- ./configure ${CONFIG} --extra-cflags="-fsanitize=undefined -Werror" || { cat config.log && exit 1; }
|
||||
- mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR}
|
||||
- ${SRC_DIR}/configure ${CONFIG} --extra-cflags="-fsanitize=undefined -Werror" || { cat config.log && exit 1; }
|
||||
|
||||
|
||||
- env:
|
||||
@ -214,10 +209,11 @@ matrix:
|
||||
- TEST_CMD=""
|
||||
|
||||
|
||||
# We manually include builds which we disable "make check" for
|
||||
# Check the TCG interpreter (TCI)
|
||||
- env:
|
||||
- CONFIG="--enable-debug --enable-tcg-interpreter"
|
||||
- TEST_CMD=""
|
||||
- CONFIG="--enable-debug-tcg --enable-tcg-interpreter --disable-kvm --disable-containers
|
||||
--target-list=alpha-softmmu,arm-softmmu,hppa-softmmu,m68k-softmmu,microblaze-softmmu,moxie-softmmu,ppc-softmmu,s390x-softmmu,x86_64-softmmu"
|
||||
- TEST_CMD="make check-qtest check-tcg V=1"
|
||||
|
||||
|
||||
# We don't need to exercise every backend with every front-end
|
||||
@ -322,7 +318,8 @@ matrix:
|
||||
- CONFIG="--cc=gcc-9 --cxx=g++-9 --disable-pie --disable-linux-user"
|
||||
- TEST_CMD=""
|
||||
before_script:
|
||||
- ./configure ${CONFIG} --extra-cflags="-g3 -O0 -Wno-error=stringop-truncation -fsanitize=thread -fuse-ld=gold" || { cat config.log && exit 1; }
|
||||
- mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR}
|
||||
- ${SRC_DIR}/configure ${CONFIG} --extra-cflags="-g3 -O0 -Wno-error=stringop-truncation -fsanitize=thread -fuse-ld=gold" || { cat config.log && exit 1; }
|
||||
|
||||
|
||||
# Run check-tcg against linux-user
|
||||
@ -353,6 +350,92 @@ matrix:
|
||||
- TEST_CMD="make -j3 check-tcg V=1"
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-debug-tcg"
|
||||
|
||||
- arch: arm64
|
||||
dist: xenial
|
||||
addons:
|
||||
apt_packages:
|
||||
- libaio-dev
|
||||
- libattr1-dev
|
||||
- libbrlapi-dev
|
||||
- libcap-ng-dev
|
||||
- libgcrypt20-dev
|
||||
- libgnutls28-dev
|
||||
- libgtk-3-dev
|
||||
- libiscsi-dev
|
||||
- liblttng-ust-dev
|
||||
- libncurses5-dev
|
||||
- libnfs-dev
|
||||
- libnss3-dev
|
||||
- libpixman-1-dev
|
||||
- libpng-dev
|
||||
- librados-dev
|
||||
- libsdl2-dev
|
||||
- libseccomp-dev
|
||||
- liburcu-dev
|
||||
- libusb-1.0-0-dev
|
||||
- libvdeplug-dev
|
||||
- libvte-2.91-dev
|
||||
env:
|
||||
- TEST_CMD="make check check-tcg V=1"
|
||||
- CONFIG="--disable-containers --target-list=${MAIN_SOFTMMU_TARGETS}"
|
||||
|
||||
- arch: ppc64le
|
||||
dist: xenial
|
||||
addons:
|
||||
apt_packages:
|
||||
- libaio-dev
|
||||
- libattr1-dev
|
||||
- libbrlapi-dev
|
||||
- libcap-ng-dev
|
||||
- libgcrypt20-dev
|
||||
- libgnutls28-dev
|
||||
- libgtk-3-dev
|
||||
- libiscsi-dev
|
||||
- liblttng-ust-dev
|
||||
- libncurses5-dev
|
||||
- libnfs-dev
|
||||
- libnss3-dev
|
||||
- libpixman-1-dev
|
||||
- libpng-dev
|
||||
- librados-dev
|
||||
- libsdl2-dev
|
||||
- libseccomp-dev
|
||||
- liburcu-dev
|
||||
- libusb-1.0-0-dev
|
||||
- libvdeplug-dev
|
||||
- libvte-2.91-dev
|
||||
env:
|
||||
- TEST_CMD="make check check-tcg V=1"
|
||||
- CONFIG="--disable-containers --target-list=${MAIN_SOFTMMU_TARGETS},ppc64le-linux-user"
|
||||
|
||||
- arch: s390x
|
||||
dist: bionic
|
||||
addons:
|
||||
apt_packages:
|
||||
- libaio-dev
|
||||
- libattr1-dev
|
||||
- libbrlapi-dev
|
||||
- libcap-ng-dev
|
||||
- libgcrypt20-dev
|
||||
- libgnutls28-dev
|
||||
- libgtk-3-dev
|
||||
- libiscsi-dev
|
||||
- liblttng-ust-dev
|
||||
- libncurses5-dev
|
||||
- libnfs-dev
|
||||
- libnss3-dev
|
||||
- libpixman-1-dev
|
||||
- libpng-dev
|
||||
- librados-dev
|
||||
- libsdl2-dev
|
||||
- libseccomp-dev
|
||||
- liburcu-dev
|
||||
- libusb-1.0-0-dev
|
||||
- libvdeplug-dev
|
||||
- libvte-2.91-dev
|
||||
env:
|
||||
- TEST_CMD="make check check-tcg V=1"
|
||||
- CONFIG="--disable-containers --target-list=${MAIN_SOFTMMU_TARGETS},s390x-linux-user"
|
||||
|
||||
# Release builds
|
||||
# The make-release script expect a QEMU version, so our tag must start with a 'v'.
|
||||
@ -373,5 +456,6 @@ matrix:
|
||||
- make -C ${SRC_DIR} qemu-${QEMU_VERSION}.tar.bz2
|
||||
- ls -l ${SRC_DIR}/qemu-${QEMU_VERSION}.tar.bz2
|
||||
- tar -xf ${SRC_DIR}/qemu-${QEMU_VERSION}.tar.bz2 && cd qemu-${QEMU_VERSION}
|
||||
- ./configure ${BASE_CONFIG} ${CONFIG} || { cat config.log && exit 1; }
|
||||
- mkdir -p release-build && cd release-build
|
||||
- ../configure ${BASE_CONFIG} ${CONFIG} || { cat config.log && exit 1; }
|
||||
- make install
|
||||
|
@ -156,7 +156,7 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, TranslationBlock *itb)
|
||||
#if defined(DEBUG_DISAS)
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_CPU)
|
||||
&& qemu_log_in_addr_range(itb->pc)) {
|
||||
qemu_log_lock();
|
||||
FILE *logfile = qemu_log_lock();
|
||||
int flags = 0;
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_FPU)) {
|
||||
flags |= CPU_DUMP_FPU;
|
||||
@ -165,7 +165,7 @@ static inline tcg_target_ulong cpu_tb_exec(CPUState *cpu, TranslationBlock *itb)
|
||||
flags |= CPU_DUMP_CCOP;
|
||||
#endif
|
||||
log_cpu_state(cpu, flags);
|
||||
qemu_log_unlock();
|
||||
qemu_log_unlock(logfile);
|
||||
}
|
||||
#endif /* DEBUG_DISAS */
|
||||
|
||||
|
@ -1804,7 +1804,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||
#ifdef DEBUG_DISAS
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM) &&
|
||||
qemu_log_in_addr_range(tb->pc)) {
|
||||
qemu_log_lock();
|
||||
FILE *logfile = qemu_log_lock();
|
||||
qemu_log("OUT: [size=%d]\n", gen_code_size);
|
||||
if (tcg_ctx->data_gen_ptr) {
|
||||
size_t code_size = tcg_ctx->data_gen_ptr - tb->tc.ptr;
|
||||
@ -1829,7 +1829,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||
}
|
||||
qemu_log("\n");
|
||||
qemu_log_flush();
|
||||
qemu_log_unlock();
|
||||
qemu_log_unlock(logfile);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -138,11 +138,11 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
|
||||
#ifdef DEBUG_DISAS
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
|
||||
&& qemu_log_in_addr_range(db->pc_first)) {
|
||||
qemu_log_lock();
|
||||
FILE *logfile = qemu_log_lock();
|
||||
qemu_log("----------------\n");
|
||||
ops->disas_log(db, cpu);
|
||||
qemu_log("\n");
|
||||
qemu_log_unlock();
|
||||
qemu_log_unlock(logfile);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -963,7 +963,7 @@ int main(int argc, char **argv)
|
||||
|
||||
if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
|
||||
qemu_log("guest_base 0x%lx\n", guest_base);
|
||||
log_page_dump();
|
||||
log_page_dump("binary load");
|
||||
|
||||
qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
|
||||
qemu_log("end_code 0x" TARGET_ABI_FMT_lx "\n", info->end_code);
|
||||
|
9
configure
vendored
9
configure
vendored
@ -302,6 +302,7 @@ audio_win_int=""
|
||||
libs_qga=""
|
||||
debug_info="yes"
|
||||
stack_protector=""
|
||||
use_containers="yes"
|
||||
|
||||
if test -e "$source_path/.git"
|
||||
then
|
||||
@ -1535,6 +1536,10 @@ for opt do
|
||||
;;
|
||||
--disable-plugins) plugins="no"
|
||||
;;
|
||||
--enable-containers) use_containers="yes"
|
||||
;;
|
||||
--disable-containers) use_containers="no"
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: unknown option $opt"
|
||||
echo "Try '$0 --help' for more information"
|
||||
@ -1718,6 +1723,7 @@ Advanced options (experts only):
|
||||
track the maximum stack usage of stacks created by qemu_alloc_stack
|
||||
--enable-plugins
|
||||
enable plugins via shared library loading
|
||||
--disable-containers don't use containers for cross-building
|
||||
|
||||
Optional features, enabled with --enable-FEATURE and
|
||||
disabled with --disable-FEATURE, default is enabled if available:
|
||||
@ -6399,6 +6405,7 @@ else
|
||||
echo "local state directory queried at runtime"
|
||||
echo "Windows SDK $win_sdk"
|
||||
fi
|
||||
echo "Build directory $(pwd)"
|
||||
echo "Source path $source_path"
|
||||
echo "GIT binary $git"
|
||||
echo "GIT submodules $git_submodules"
|
||||
@ -7996,7 +8003,7 @@ done
|
||||
(for i in $cross_cc_vars; do
|
||||
export $i
|
||||
done
|
||||
export target_list source_path
|
||||
export target_list source_path use_containers
|
||||
$source_path/tests/tcg/configure.sh)
|
||||
|
||||
# temporary config to build submodules
|
||||
|
@ -418,13 +418,15 @@ access, so they SHOULD NOT be exposed to external interfaces if you are
|
||||
concerned about attackers taking control of the guest and potentially
|
||||
exploiting a QEMU security bug to compromise the host.
|
||||
|
||||
QEMU binary
|
||||
-----------
|
||||
QEMU binaries
|
||||
-------------
|
||||
|
||||
By default, qemu-system-x86_64 is searched in $PATH to run the guest. If there
|
||||
isn't one, or if it is older than 2.10, the test won't work. In this case,
|
||||
provide the QEMU binary in env var: ``QEMU=/path/to/qemu-2.10+``.
|
||||
|
||||
Likewise the path to qemu-img can be set in QEMU_IMG environment variable.
|
||||
|
||||
Make jobs
|
||||
---------
|
||||
|
||||
|
4
exec.c
4
exec.c
@ -1225,13 +1225,13 @@ void cpu_abort(CPUState *cpu, const char *fmt, ...)
|
||||
fprintf(stderr, "\n");
|
||||
cpu_dump_state(cpu, stderr, CPU_DUMP_FPU | CPU_DUMP_CCOP);
|
||||
if (qemu_log_separate()) {
|
||||
qemu_log_lock();
|
||||
FILE *logfile = qemu_log_lock();
|
||||
qemu_log("qemu: fatal: ");
|
||||
qemu_log_vprintf(fmt, ap2);
|
||||
qemu_log("\n");
|
||||
log_cpu_state(cpu, CPU_DUMP_FPU | CPU_DUMP_CCOP);
|
||||
qemu_log_flush();
|
||||
qemu_log_unlock();
|
||||
qemu_log_unlock(logfile);
|
||||
qemu_log_close();
|
||||
}
|
||||
va_end(ap2);
|
||||
|
@ -247,8 +247,8 @@ int can_sja_accept_filter(CanSJA1000State *s,
|
||||
static void can_display_msg(const char *prefix, const qemu_can_frame *msg)
|
||||
{
|
||||
int i;
|
||||
FILE *logfile = qemu_log_lock();
|
||||
|
||||
qemu_log_lock();
|
||||
qemu_log("%s%03X [%01d] %s %s",
|
||||
prefix,
|
||||
msg->can_id & QEMU_CAN_EFF_MASK,
|
||||
@ -261,7 +261,7 @@ static void can_display_msg(const char *prefix, const qemu_can_frame *msg)
|
||||
}
|
||||
qemu_log("\n");
|
||||
qemu_log_flush();
|
||||
qemu_log_unlock();
|
||||
qemu_log_unlock(logfile);
|
||||
}
|
||||
|
||||
static void buff2frame_pel(const uint8_t *buff, qemu_can_frame *frame)
|
||||
|
@ -15,8 +15,15 @@
|
||||
*/
|
||||
static inline void log_cpu_state(CPUState *cpu, int flags)
|
||||
{
|
||||
QemuLogFile *logfile;
|
||||
|
||||
if (qemu_log_enabled()) {
|
||||
cpu_dump_state(cpu, qemu_logfile, flags);
|
||||
rcu_read_lock();
|
||||
logfile = atomic_rcu_read(&qemu_logfile);
|
||||
if (logfile) {
|
||||
cpu_dump_state(cpu, logfile->fd, flags);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
@ -40,19 +47,36 @@ static inline void log_cpu_state_mask(int mask, CPUState *cpu, int flags)
|
||||
static inline void log_target_disas(CPUState *cpu, target_ulong start,
|
||||
target_ulong len)
|
||||
{
|
||||
target_disas(qemu_logfile, cpu, start, len);
|
||||
QemuLogFile *logfile;
|
||||
rcu_read_lock();
|
||||
logfile = atomic_rcu_read(&qemu_logfile);
|
||||
if (logfile) {
|
||||
target_disas(logfile->fd, cpu, start, len);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static inline void log_disas(void *code, unsigned long size)
|
||||
{
|
||||
disas(qemu_logfile, code, size);
|
||||
QemuLogFile *logfile;
|
||||
rcu_read_lock();
|
||||
logfile = atomic_rcu_read(&qemu_logfile);
|
||||
if (logfile) {
|
||||
disas(logfile->fd, code, size);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
/* page_dump() output to the log file: */
|
||||
static inline void log_page_dump(void)
|
||||
static inline void log_page_dump(const char *operation)
|
||||
{
|
||||
page_dump(qemu_logfile);
|
||||
FILE *logfile = qemu_log_lock();
|
||||
if (logfile) {
|
||||
qemu_log("page layout changed following %s\n", operation);
|
||||
page_dump(logfile);
|
||||
}
|
||||
qemu_log_unlock(logfile);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
@ -3,9 +3,16 @@
|
||||
|
||||
/* A small part of this API is split into its own header */
|
||||
#include "qemu/log-for-trace.h"
|
||||
#include "qemu/rcu.h"
|
||||
|
||||
typedef struct QemuLogFile {
|
||||
struct rcu_head rcu;
|
||||
FILE *fd;
|
||||
} QemuLogFile;
|
||||
|
||||
/* Private global variable, don't use */
|
||||
extern FILE *qemu_logfile;
|
||||
extern QemuLogFile *qemu_logfile;
|
||||
|
||||
|
||||
/*
|
||||
* The new API:
|
||||
@ -25,7 +32,16 @@ static inline bool qemu_log_enabled(void)
|
||||
*/
|
||||
static inline bool qemu_log_separate(void)
|
||||
{
|
||||
return qemu_logfile != NULL && qemu_logfile != stderr;
|
||||
QemuLogFile *logfile;
|
||||
bool res = false;
|
||||
|
||||
rcu_read_lock();
|
||||
logfile = atomic_rcu_read(&qemu_logfile);
|
||||
if (logfile && logfile->fd != stderr) {
|
||||
res = true;
|
||||
}
|
||||
rcu_read_unlock();
|
||||
return res;
|
||||
}
|
||||
|
||||
#define CPU_LOG_TB_OUT_ASM (1 << 0)
|
||||
@ -53,14 +69,25 @@ static inline bool qemu_log_separate(void)
|
||||
* qemu_loglevel is never set when qemu_logfile is unset.
|
||||
*/
|
||||
|
||||
static inline void qemu_log_lock(void)
|
||||
static inline FILE *qemu_log_lock(void)
|
||||
{
|
||||
qemu_flockfile(qemu_logfile);
|
||||
QemuLogFile *logfile;
|
||||
rcu_read_lock();
|
||||
logfile = atomic_rcu_read(&qemu_logfile);
|
||||
if (logfile) {
|
||||
qemu_flockfile(logfile->fd);
|
||||
return logfile->fd;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void qemu_log_unlock(void)
|
||||
static inline void qemu_log_unlock(FILE *fd)
|
||||
{
|
||||
qemu_funlockfile(qemu_logfile);
|
||||
if (fd) {
|
||||
qemu_funlockfile(fd);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
/* Logging functions: */
|
||||
@ -70,9 +97,14 @@ static inline void qemu_log_unlock(void)
|
||||
static inline void GCC_FMT_ATTR(1, 0)
|
||||
qemu_log_vprintf(const char *fmt, va_list va)
|
||||
{
|
||||
if (qemu_logfile) {
|
||||
vfprintf(qemu_logfile, fmt, va);
|
||||
QemuLogFile *logfile;
|
||||
|
||||
rcu_read_lock();
|
||||
logfile = atomic_rcu_read(&qemu_logfile);
|
||||
if (logfile) {
|
||||
vfprintf(logfile->fd, fmt, va);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
/* log only if a bit is set on the current loglevel mask:
|
||||
|
@ -826,7 +826,7 @@ int main(int argc, char **argv, char **envp)
|
||||
|
||||
if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
|
||||
qemu_log("guest_base 0x%lx\n", guest_base);
|
||||
log_page_dump();
|
||||
log_page_dump("binary load");
|
||||
|
||||
qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
|
||||
qemu_log("end_code 0x" TARGET_ABI_FMT_lx "\n", info->end_code);
|
||||
|
@ -17,11 +17,10 @@
|
||||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include "trace.h"
|
||||
#include "exec/log.h"
|
||||
#include "qemu.h"
|
||||
|
||||
//#define DEBUG_MMAP
|
||||
|
||||
static pthread_mutex_t mmap_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static __thread int mmap_lock_count;
|
||||
|
||||
@ -66,13 +65,7 @@ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
|
||||
abi_ulong end, host_start, host_end, addr;
|
||||
int prot1, ret;
|
||||
|
||||
#ifdef DEBUG_MMAP
|
||||
printf("mprotect: start=0x" TARGET_ABI_FMT_lx
|
||||
"len=0x" TARGET_ABI_FMT_lx " prot=%c%c%c\n", start, len,
|
||||
prot & PROT_READ ? 'r' : '-',
|
||||
prot & PROT_WRITE ? 'w' : '-',
|
||||
prot & PROT_EXEC ? 'x' : '-');
|
||||
#endif
|
||||
trace_target_mprotect(start, len, prot);
|
||||
|
||||
if ((start & ~TARGET_PAGE_MASK) != 0)
|
||||
return -TARGET_EINVAL;
|
||||
@ -369,32 +362,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
||||
abi_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len;
|
||||
|
||||
mmap_lock();
|
||||
#ifdef DEBUG_MMAP
|
||||
{
|
||||
printf("mmap: start=0x" TARGET_ABI_FMT_lx
|
||||
" len=0x" TARGET_ABI_FMT_lx " prot=%c%c%c flags=",
|
||||
start, len,
|
||||
prot & PROT_READ ? 'r' : '-',
|
||||
prot & PROT_WRITE ? 'w' : '-',
|
||||
prot & PROT_EXEC ? 'x' : '-');
|
||||
if (flags & MAP_FIXED)
|
||||
printf("MAP_FIXED ");
|
||||
if (flags & MAP_ANONYMOUS)
|
||||
printf("MAP_ANON ");
|
||||
switch(flags & MAP_TYPE) {
|
||||
case MAP_PRIVATE:
|
||||
printf("MAP_PRIVATE ");
|
||||
break;
|
||||
case MAP_SHARED:
|
||||
printf("MAP_SHARED ");
|
||||
break;
|
||||
default:
|
||||
printf("[MAP_TYPE=0x%x] ", flags & MAP_TYPE);
|
||||
break;
|
||||
}
|
||||
printf("fd=%d offset=" TARGET_ABI_FMT_lx "\n", fd, offset);
|
||||
}
|
||||
#endif
|
||||
trace_target_mmap(start, len, prot, flags, fd, offset);
|
||||
|
||||
if (!len) {
|
||||
errno = EINVAL;
|
||||
@ -569,11 +537,10 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
|
||||
the_end1:
|
||||
page_set_flags(start, start + len, prot | PAGE_VALID);
|
||||
the_end:
|
||||
#ifdef DEBUG_MMAP
|
||||
printf("ret=0x" TARGET_ABI_FMT_lx "\n", start);
|
||||
page_dump(stdout);
|
||||
printf("\n");
|
||||
#endif
|
||||
trace_target_mmap_complete(start);
|
||||
if (qemu_loglevel_mask(CPU_LOG_PAGE)) {
|
||||
log_page_dump(__func__);
|
||||
}
|
||||
tb_invalidate_phys_range(start, start + len);
|
||||
mmap_unlock();
|
||||
return start;
|
||||
@ -628,11 +595,8 @@ int target_munmap(abi_ulong start, abi_ulong len)
|
||||
abi_ulong end, real_start, real_end, addr;
|
||||
int prot, ret;
|
||||
|
||||
#ifdef DEBUG_MMAP
|
||||
printf("munmap: start=0x" TARGET_ABI_FMT_lx " len=0x"
|
||||
TARGET_ABI_FMT_lx "\n",
|
||||
start, len);
|
||||
#endif
|
||||
trace_target_munmap(start, len);
|
||||
|
||||
if (start & ~TARGET_PAGE_MASK)
|
||||
return -TARGET_EINVAL;
|
||||
len = TARGET_PAGE_ALIGN(len);
|
||||
|
@ -11,3 +11,9 @@ user_handle_signal(void *env, int target_sig) "env=%p signal %d"
|
||||
user_host_signal(void *env, int host_sig, int target_sig) "env=%p signal %d (target %d("
|
||||
user_queue_signal(void *env, int target_sig) "env=%p signal %d"
|
||||
user_s390x_restore_sigregs(void *env, uint64_t sc_psw_addr, uint64_t env_psw_addr) "env=%p frame psw.addr 0x%"PRIx64 " current psw.addr 0x%"PRIx64
|
||||
|
||||
# mmap.c
|
||||
target_mprotect(uint64_t start, uint64_t len, int flags) "start=0x%"PRIx64 " len=0x%"PRIx64 " prot=0x%x"
|
||||
target_mmap(uint64_t start, uint64_t len, int pflags, int mflags, int fd, uint64_t offset) "start=0x%"PRIx64 " len=0x%"PRIx64 " prot=0x%x flags=0x%x fd=%d offset=0x%"PRIx64
|
||||
target_mmap_complete(uint64_t retaddr) "retaddr=0x%"PRIx64
|
||||
target_munmap(uint64_t start, uint64_t len) "start=0x%"PRIx64" len=0x%"PRIx64
|
||||
|
@ -76,8 +76,7 @@ QEMU_BUILD_BUG_ON(offsetof(qemu_can_frame, data)
|
||||
static void can_host_socketcan_display_msg(struct qemu_can_frame *msg)
|
||||
{
|
||||
int i;
|
||||
|
||||
qemu_log_lock();
|
||||
FILE *logfile = qemu_log_lock();
|
||||
qemu_log("[cansocketcan]: %03X [%01d] %s %s",
|
||||
msg->can_id & QEMU_CAN_EFF_MASK,
|
||||
msg->can_dlc,
|
||||
@ -89,7 +88,7 @@ static void can_host_socketcan_display_msg(struct qemu_can_frame *msg)
|
||||
}
|
||||
qemu_log("\n");
|
||||
qemu_log_flush();
|
||||
qemu_log_unlock();
|
||||
qemu_log_unlock(logfile);
|
||||
}
|
||||
|
||||
static void can_host_socketcan_read(void *opaque)
|
||||
|
@ -3273,11 +3273,11 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
|
||||
#if !DISAS_CRIS
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
|
||||
&& qemu_log_in_addr_range(pc_start)) {
|
||||
qemu_log_lock();
|
||||
FILE *logfile = qemu_log_lock();
|
||||
qemu_log("--------------\n");
|
||||
qemu_log("IN: %s\n", lookup_symbol(pc_start));
|
||||
log_target_disas(cs, pc_start, dc->pc - pc_start);
|
||||
qemu_log_unlock();
|
||||
qemu_log_unlock(logfile);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
@ -2502,14 +2502,15 @@ static void gen_unknown_opcode(CPUX86State *env, DisasContext *s)
|
||||
gen_illegal_opcode(s);
|
||||
|
||||
if (qemu_loglevel_mask(LOG_UNIMP)) {
|
||||
FILE *logfile = qemu_log_lock();
|
||||
target_ulong pc = s->pc_start, end = s->pc;
|
||||
qemu_log_lock();
|
||||
|
||||
qemu_log("ILLOPC: " TARGET_FMT_lx ":", pc);
|
||||
for (; pc < end; ++pc) {
|
||||
qemu_log(" %02x", cpu_ldub_code(env, pc));
|
||||
}
|
||||
qemu_log("\n");
|
||||
qemu_log_unlock();
|
||||
qemu_log_unlock(logfile);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1137,10 +1137,10 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
|
||||
#ifdef DEBUG_DISAS
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
|
||||
&& qemu_log_in_addr_range(pc_start)) {
|
||||
qemu_log_lock();
|
||||
FILE *logfile = qemu_log_lock();
|
||||
qemu_log("\n");
|
||||
log_target_disas(cs, pc_start, dc->pc - pc_start);
|
||||
qemu_log_unlock();
|
||||
qemu_log_unlock(logfile);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -1765,10 +1765,10 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
|
||||
#if !SIM_COMPAT
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
|
||||
&& qemu_log_in_addr_range(pc_start)) {
|
||||
qemu_log_lock();
|
||||
FILE *logfile = qemu_log_lock();
|
||||
qemu_log("--------------\n");
|
||||
log_target_disas(cs, pc_start, dc->pc - pc_start);
|
||||
qemu_log_unlock();
|
||||
qemu_log_unlock(logfile);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
@ -892,11 +892,11 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
|
||||
#ifdef DEBUG_DISAS
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
|
||||
&& qemu_log_in_addr_range(tb->pc)) {
|
||||
qemu_log_lock();
|
||||
FILE *logfile = qemu_log_lock();
|
||||
qemu_log("IN: %s\n", lookup_symbol(tb->pc));
|
||||
log_target_disas(cs, tb->pc, dc->pc - tb->pc);
|
||||
qemu_log("\n");
|
||||
qemu_log_unlock();
|
||||
qemu_log_unlock(logfile);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@ -2388,7 +2388,6 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
|
||||
dc->zero = NULL;
|
||||
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
|
||||
qemu_log_lock();
|
||||
qemu_log("IN: %s\n", lookup_symbol(pc_start));
|
||||
}
|
||||
gen_tb_start(tb);
|
||||
@ -2417,11 +2416,6 @@ void gen_intermediate_code(CPUState *cs, TranslationBlock *tb, int max_insns)
|
||||
gen_tb_end(tb, num_insns);
|
||||
tb->size = dc->pc - pc_start;
|
||||
tb->icount = num_insns;
|
||||
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
|
||||
qemu_log("\n");
|
||||
qemu_log_unlock();
|
||||
}
|
||||
}
|
||||
|
||||
void restore_state_to_opc(CPUTLGState *env, TranslationBlock *tb,
|
||||
|
@ -1994,12 +1994,12 @@ done_generating:
|
||||
#ifdef DEBUG_DISAS
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)
|
||||
&& qemu_log_in_addr_range(pc_start)) {
|
||||
qemu_log_lock();
|
||||
FILE *logfile = qemu_log_lock();
|
||||
qemu_log("----------------\n");
|
||||
qemu_log("IN: %s\n", lookup_symbol(pc_start));
|
||||
log_target_disas(cs, pc_start, dc->pc - pc_start);
|
||||
qemu_log("\n");
|
||||
qemu_log_unlock();
|
||||
qemu_log_unlock(logfile);
|
||||
}
|
||||
#endif
|
||||
tb->size = dc->pc - pc_start;
|
||||
|
28
tcg/tcg.c
28
tcg/tcg.c
@ -1085,7 +1085,7 @@ void tcg_prologue_init(TCGContext *s)
|
||||
|
||||
#ifdef DEBUG_DISAS
|
||||
if (qemu_loglevel_mask(CPU_LOG_TB_OUT_ASM)) {
|
||||
qemu_log_lock();
|
||||
FILE *logfile = qemu_log_lock();
|
||||
qemu_log("PROLOGUE: [size=%zu]\n", prologue_size);
|
||||
if (s->data_gen_ptr) {
|
||||
size_t code_size = s->data_gen_ptr - buf0;
|
||||
@ -1110,7 +1110,7 @@ void tcg_prologue_init(TCGContext *s)
|
||||
}
|
||||
qemu_log("\n");
|
||||
qemu_log_flush();
|
||||
qemu_log_unlock();
|
||||
qemu_log_unlock(logfile);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -2114,9 +2114,17 @@ static void tcg_dump_ops(TCGContext *s, bool have_prefs)
|
||||
}
|
||||
|
||||
if (have_prefs || op->life) {
|
||||
for (; col < 40; ++col) {
|
||||
putc(' ', qemu_logfile);
|
||||
|
||||
QemuLogFile *logfile;
|
||||
|
||||
rcu_read_lock();
|
||||
logfile = atomic_rcu_read(&qemu_logfile);
|
||||
if (logfile) {
|
||||
for (; col < 40; ++col) {
|
||||
putc(' ', logfile->fd);
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
if (op->life) {
|
||||
@ -4041,11 +4049,11 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
|
||||
#ifdef DEBUG_DISAS
|
||||
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP)
|
||||
&& qemu_log_in_addr_range(tb->pc))) {
|
||||
qemu_log_lock();
|
||||
FILE *logfile = qemu_log_lock();
|
||||
qemu_log("OP:\n");
|
||||
tcg_dump_ops(s, false);
|
||||
qemu_log("\n");
|
||||
qemu_log_unlock();
|
||||
qemu_log_unlock(logfile);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -4086,11 +4094,11 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
|
||||
#ifdef DEBUG_DISAS
|
||||
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_IND)
|
||||
&& qemu_log_in_addr_range(tb->pc))) {
|
||||
qemu_log_lock();
|
||||
FILE *logfile = qemu_log_lock();
|
||||
qemu_log("OP before indirect lowering:\n");
|
||||
tcg_dump_ops(s, false);
|
||||
qemu_log("\n");
|
||||
qemu_log_unlock();
|
||||
qemu_log_unlock(logfile);
|
||||
}
|
||||
#endif
|
||||
/* Replace indirect temps with direct temps. */
|
||||
@ -4107,11 +4115,11 @@ int tcg_gen_code(TCGContext *s, TranslationBlock *tb)
|
||||
#ifdef DEBUG_DISAS
|
||||
if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP_OPT)
|
||||
&& qemu_log_in_addr_range(tb->pc))) {
|
||||
qemu_log_lock();
|
||||
FILE *logfile = qemu_log_lock();
|
||||
qemu_log("OP after optimization and liveness analysis:\n");
|
||||
tcg_dump_ops(s, true);
|
||||
qemu_log("\n");
|
||||
qemu_log_unlock();
|
||||
qemu_log_unlock(logfile);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -53,12 +53,7 @@ check_qemu()
|
||||
INVOCATION="$@"
|
||||
fi
|
||||
|
||||
if command -v gtester > /dev/null 2>&1 && \
|
||||
gtester --version > /dev/null 2>&1; then
|
||||
make $MAKEFLAGS $INVOCATION
|
||||
else
|
||||
echo "No working gtester, skipping make $INVOCATION"
|
||||
fi
|
||||
make $MAKEFLAGS $INVOCATION
|
||||
}
|
||||
|
||||
test_fail()
|
||||
|
@ -34,8 +34,13 @@ static char *create_test_img(int secs)
|
||||
fd = mkstemp(template);
|
||||
g_assert(fd >= 0);
|
||||
ret = ftruncate(fd, (off_t)secs * 512);
|
||||
g_assert(ret == 0);
|
||||
close(fd);
|
||||
|
||||
if (ret) {
|
||||
free(template);
|
||||
template = NULL;
|
||||
}
|
||||
|
||||
return template;
|
||||
}
|
||||
|
||||
@ -934,6 +939,10 @@ int main(int argc, char **argv)
|
||||
for (i = 0; i < backend_last; i++) {
|
||||
if (img_secs[i] >= 0) {
|
||||
img_file_name[i] = create_test_img(img_secs[i]);
|
||||
if (!img_file_name[i]) {
|
||||
g_test_message("Could not create test images.");
|
||||
goto test_add_done;
|
||||
}
|
||||
} else {
|
||||
img_file_name[i] = NULL;
|
||||
}
|
||||
@ -965,6 +974,7 @@ int main(int argc, char **argv)
|
||||
"skipping hd-geo/override/* tests");
|
||||
}
|
||||
|
||||
test_add_done:
|
||||
ret = g_test_run();
|
||||
|
||||
for (i = 0; i < backend_last; i++) {
|
||||
|
@ -59,10 +59,7 @@ fi
|
||||
# Sanity check: For raw, we require a file system that permits the creation
|
||||
# of a HUGE (but very sparse) file. Check we can create it before continuing.
|
||||
if [ "$IMGFMT" = "raw" ]; then
|
||||
if ! truncate --size=5T "$TEST_IMG"; then
|
||||
_notrun "file system on $TEST_DIR does not support large enough files"
|
||||
fi
|
||||
rm "$TEST_IMG"
|
||||
_require_large_file 5T
|
||||
fi
|
||||
|
||||
echo
|
||||
|
@ -49,6 +49,9 @@ _supported_fmt qcow2
|
||||
_supported_proto file
|
||||
_supported_os Linux
|
||||
|
||||
# The repair process will create a large file - so check for availability first
|
||||
_require_large_file 64G
|
||||
|
||||
rt_offset=65536 # 0x10000 (XXX: just an assumption)
|
||||
rb_offset=131072 # 0x20000 (XXX: just an assumption)
|
||||
l1_offset=196608 # 0x30000 (XXX: just an assumption)
|
||||
|
@ -39,6 +39,9 @@ trap "_cleanup; exit \$status" 0 1 2 3 15
|
||||
_supported_fmt qcow2
|
||||
_supported_proto file nfs
|
||||
|
||||
# Some containers (e.g. non-x86 on Travis) do not allow large files
|
||||
_require_large_file 4G
|
||||
|
||||
echo "=== Check option preallocation and cluster_size ==="
|
||||
echo
|
||||
cluster_sizes="16384 32768 65536 131072 262144 524288 1048576 2097152 4194304"
|
||||
|
@ -42,10 +42,8 @@ echo "== Creating huge file =="
|
||||
|
||||
# Sanity check: We require a file system that permits the creation
|
||||
# of a HUGE (but very sparse) file. tmpfs works, ext4 does not.
|
||||
if ! truncate --size=513T "$TEST_IMG"; then
|
||||
_notrun "file system on $TEST_DIR does not support large enough files"
|
||||
fi
|
||||
rm "$TEST_IMG"
|
||||
_require_large_file 513T
|
||||
|
||||
IMGOPTS='cluster_size=2M,refcount_bits=1' _make_test_img 513T
|
||||
|
||||
echo "== Populating refcounts =="
|
||||
|
@ -643,5 +643,15 @@ _require_drivers()
|
||||
done
|
||||
}
|
||||
|
||||
# Check that we have a file system that allows huge (but very sparse) files
|
||||
#
|
||||
_require_large_file()
|
||||
{
|
||||
if ! truncate --size="$1" "$TEST_IMG"; then
|
||||
_notrun "file system on $TEST_DIR does not support large enough files"
|
||||
fi
|
||||
rm "$TEST_IMG"
|
||||
}
|
||||
|
||||
# make sure this script returns success
|
||||
true
|
||||
|
@ -13,6 +13,6 @@ DOCKER_IMAGE:=
|
||||
|
||||
ifneq ($(DOCKER_IMAGE),)
|
||||
build-tcg-tests-$(PROBE_TARGET): docker-image-$(DOCKER_IMAGE)
|
||||
endif
|
||||
$(BUILD_DIR)/tests/tcg/config_$(PROBE_TARGET).mak: config-host.mak
|
||||
config-host.mak: $(SRC_PATH)/tests/tcg/configure.sh
|
||||
endif
|
||||
|
@ -36,8 +36,10 @@ TMPC="${TMPDIR1}/qemu-conf.c"
|
||||
TMPE="${TMPDIR1}/qemu-conf.exe"
|
||||
|
||||
container="no"
|
||||
if has "docker" || has "podman"; then
|
||||
container=$($python $source_path/tests/docker/docker.py probe)
|
||||
if test $use_containers = "yes"; then
|
||||
if has "docker" || has "podman"; then
|
||||
container=$($python $source_path/tests/docker/docker.py probe)
|
||||
fi
|
||||
fi
|
||||
|
||||
# cross compilers defaults, can be overridden with --cross-cc-ARCH
|
||||
|
@ -108,6 +108,82 @@ static void test_parse_path(gconstpointer data)
|
||||
error_free_or_abort(&err);
|
||||
}
|
||||
|
||||
static void test_logfile_write(gconstpointer data)
|
||||
{
|
||||
QemuLogFile *logfile;
|
||||
QemuLogFile *logfile2;
|
||||
gchar const *dir = data;
|
||||
Error *err = NULL;
|
||||
g_autofree gchar *file_path;
|
||||
g_autofree gchar *file_path1;
|
||||
FILE *orig_fd;
|
||||
|
||||
/*
|
||||
* Before starting test, set log flags, to ensure the file gets
|
||||
* opened below with the call to qemu_set_log_filename().
|
||||
* In cases where a logging backend other than log is used,
|
||||
* this is needed.
|
||||
*/
|
||||
qemu_set_log(CPU_LOG_TB_OUT_ASM);
|
||||
file_path = g_build_filename(dir, "qemu_test_log_write0.log", NULL);
|
||||
file_path1 = g_build_filename(dir, "qemu_test_log_write1.log", NULL);
|
||||
|
||||
/*
|
||||
* Test that even if an open file handle is changed,
|
||||
* our handle remains valid due to RCU.
|
||||
*/
|
||||
qemu_set_log_filename(file_path, &err);
|
||||
g_assert(!err);
|
||||
rcu_read_lock();
|
||||
logfile = atomic_rcu_read(&qemu_logfile);
|
||||
orig_fd = logfile->fd;
|
||||
g_assert(logfile && logfile->fd);
|
||||
fprintf(logfile->fd, "%s 1st write to file\n", __func__);
|
||||
fflush(logfile->fd);
|
||||
|
||||
/* Change the logfile and ensure that the handle is still valid. */
|
||||
qemu_set_log_filename(file_path1, &err);
|
||||
g_assert(!err);
|
||||
logfile2 = atomic_rcu_read(&qemu_logfile);
|
||||
g_assert(logfile->fd == orig_fd);
|
||||
g_assert(logfile2->fd != logfile->fd);
|
||||
fprintf(logfile->fd, "%s 2nd write to file\n", __func__);
|
||||
fflush(logfile->fd);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static void test_logfile_lock(gconstpointer data)
|
||||
{
|
||||
FILE *logfile;
|
||||
gchar const *dir = data;
|
||||
Error *err = NULL;
|
||||
g_autofree gchar *file_path;
|
||||
|
||||
file_path = g_build_filename(dir, "qemu_test_logfile_lock0.log", NULL);
|
||||
|
||||
/*
|
||||
* Test the use of the logfile lock, such
|
||||
* that even if an open file handle is closed,
|
||||
* our handle remains valid for use due to RCU.
|
||||
*/
|
||||
qemu_set_log_filename(file_path, &err);
|
||||
logfile = qemu_log_lock();
|
||||
g_assert(logfile);
|
||||
fprintf(logfile, "%s 1st write to file\n", __func__);
|
||||
fflush(logfile);
|
||||
|
||||
/*
|
||||
* Initiate a close file and make sure our handle remains
|
||||
* valid since we still have the logfile lock.
|
||||
*/
|
||||
qemu_log_close();
|
||||
fprintf(logfile, "%s 2nd write to file\n", __func__);
|
||||
fflush(logfile);
|
||||
qemu_log_unlock(logfile);
|
||||
|
||||
g_assert(!err);
|
||||
}
|
||||
|
||||
/* Remove a directory and all its entries (non-recursive). */
|
||||
static void rmdir_full(gchar const *root)
|
||||
{
|
||||
@ -134,6 +210,10 @@ int main(int argc, char **argv)
|
||||
|
||||
g_test_add_func("/logging/parse_range", test_parse_range);
|
||||
g_test_add_data_func("/logging/parse_path", tmp_path, test_parse_path);
|
||||
g_test_add_data_func("/logging/logfile_write_path",
|
||||
tmp_path, test_logfile_write);
|
||||
g_test_add_data_func("/logging/logfile_lock_path",
|
||||
tmp_path, test_logfile_lock);
|
||||
|
||||
rc = g_test_run();
|
||||
|
||||
|
@ -406,10 +406,21 @@ test_file_monitor_events(void)
|
||||
char *pathdst = NULL;
|
||||
QFileMonitorTestData data;
|
||||
GHashTable *ids = g_hash_table_new(g_int64_hash, g_int64_equal);
|
||||
char *travis_arch;
|
||||
|
||||
qemu_mutex_init(&data.lock);
|
||||
data.records = NULL;
|
||||
|
||||
/*
|
||||
* This test does not work on Travis LXD containers since some
|
||||
* syscalls are blocked in that environment.
|
||||
*/
|
||||
travis_arch = getenv("TRAVIS_ARCH");
|
||||
if (travis_arch && !g_str_equal(travis_arch, "x86_64")) {
|
||||
g_test_skip("Test does not work on non-x86 Travis containers.");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* The file monitor needs the main loop running in
|
||||
* order to receive events from inotify. We must
|
||||
|
@ -34,6 +34,7 @@ vm-help vm-test:
|
||||
@echo " DEBUG=1 - Enable verbose output on host and interactive debugging"
|
||||
@echo " V=1 - Enable verbose ouput on host and guest commands"
|
||||
@echo " QEMU=/path/to/qemu - Change path to QEMU binary"
|
||||
@echo " QEMU_IMG=/path/to/qemu-img - Change path to qemu-img tool"
|
||||
|
||||
vm-build-all: $(addprefix vm-build-, $(IMAGES))
|
||||
|
||||
|
@ -152,6 +152,11 @@ class BaseVM(object):
|
||||
def build_image(self, img):
|
||||
raise NotImplementedError
|
||||
|
||||
def exec_qemu_img(self, *args):
|
||||
cmd = [os.environ.get("QEMU_IMG", "qemu-img")]
|
||||
cmd.extend(list(args))
|
||||
subprocess.check_call(cmd)
|
||||
|
||||
def add_source_dir(self, src_dir):
|
||||
name = "data-" + hashlib.sha1(src_dir.encode("utf-8")).hexdigest()[:5]
|
||||
tarfile = os.path.join(self._tmpdir, name + ".tar")
|
||||
|
@ -68,7 +68,7 @@ class CentosVM(basevm.BaseVM):
|
||||
sys.stderr.write("Extracting the image...\n")
|
||||
subprocess.check_call(["ln", "-f", cimg, img_tmp + ".xz"])
|
||||
subprocess.check_call(["xz", "--keep", "-dvf", img_tmp + ".xz"])
|
||||
subprocess.check_call(["qemu-img", "resize", img_tmp, "50G"])
|
||||
self.exec_qemu_img("resize", img_tmp, "50G")
|
||||
self.boot(img_tmp, extra_args = ["-cdrom", self._gen_cloud_init_iso()])
|
||||
self.wait_ssh()
|
||||
self.ssh_root_check("touch /etc/cloud/cloud-init.disabled")
|
||||
|
@ -74,9 +74,7 @@ class FedoraVM(basevm.BaseVM):
|
||||
|
||||
self.print_step("Preparing iso and disk image")
|
||||
subprocess.check_call(["cp", "-f", cimg, iso])
|
||||
subprocess.check_call(["qemu-img", "create", "-f", "qcow2",
|
||||
img_tmp, self.size])
|
||||
|
||||
self.exec_qemu_img("create", "-f", "qcow2", img_tmp, self.size)
|
||||
self.print_step("Booting installer")
|
||||
self.boot(img_tmp, extra_args = [
|
||||
"-bios", "pc-bios/bios-256k.bin",
|
||||
|
@ -82,8 +82,7 @@ class FreeBSDVM(basevm.BaseVM):
|
||||
self.print_step("Preparing iso and disk image")
|
||||
subprocess.check_call(["cp", "-f", cimg, iso_xz])
|
||||
subprocess.check_call(["xz", "-dvf", iso_xz])
|
||||
subprocess.check_call(["qemu-img", "create", "-f", "qcow2",
|
||||
img_tmp, self.size])
|
||||
self.exec_qemu_img("create", "-f", "qcow2", img_tmp, self.size)
|
||||
|
||||
self.print_step("Booting installer")
|
||||
self.boot(img_tmp, extra_args = [
|
||||
|
@ -77,8 +77,7 @@ class NetBSDVM(basevm.BaseVM):
|
||||
|
||||
self.print_step("Preparing iso and disk image")
|
||||
subprocess.check_call(["ln", "-f", cimg, iso])
|
||||
subprocess.check_call(["qemu-img", "create", "-f", "qcow2",
|
||||
img_tmp, self.size])
|
||||
self.exec_qemu_img("create", "-f", "qcow2", img_tmp, self.size)
|
||||
|
||||
self.print_step("Booting installer")
|
||||
self.boot(img_tmp, extra_args = [
|
||||
|
@ -73,8 +73,7 @@ class OpenBSDVM(basevm.BaseVM):
|
||||
|
||||
self.print_step("Preparing iso and disk image")
|
||||
subprocess.check_call(["cp", "-f", cimg, iso])
|
||||
subprocess.check_call(["qemu-img", "create", "-f", "qcow2",
|
||||
img_tmp, self.size])
|
||||
self.exec_qemu_img("create", "-f", "qcow2", img_tmp, self.size)
|
||||
|
||||
self.print_step("Booting installer")
|
||||
self.boot(img_tmp, extra_args = [
|
||||
|
@ -70,7 +70,7 @@ class UbuntuX86VM(basevm.BaseVM):
|
||||
sha256sum="28969840626d1ea80bb249c08eef1a4533e8904aa51a327b40f37ac4b4ff04ef")
|
||||
img_tmp = img + ".tmp"
|
||||
subprocess.check_call(["cp", "-f", cimg, img_tmp])
|
||||
subprocess.check_call(["qemu-img", "resize", img_tmp, "50G"])
|
||||
self.exec_qemu_img("resize", img_tmp, "50G")
|
||||
self.boot(img_tmp, extra_args = ["-cdrom", self._gen_cloud_init_iso()])
|
||||
self.wait_ssh()
|
||||
self.ssh_root_check("touch /etc/cloud/cloud-init.disabled")
|
||||
|
@ -98,38 +98,6 @@ TraceEvent *trace_event_name(const char *name)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool pattern_glob(const char *pat, const char *ev)
|
||||
{
|
||||
while (*pat != '\0' && *ev != '\0') {
|
||||
if (*pat == *ev) {
|
||||
pat++;
|
||||
ev++;
|
||||
}
|
||||
else if (*pat == '*') {
|
||||
if (pattern_glob(pat, ev+1)) {
|
||||
return true;
|
||||
} else if (pattern_glob(pat+1, ev)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
while (*pat == '*') {
|
||||
pat++;
|
||||
}
|
||||
|
||||
if (*pat == '\0' && *ev == '\0') {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void trace_event_iter_init(TraceEventIter *iter, const char *pattern)
|
||||
{
|
||||
iter->event = 0;
|
||||
@ -148,8 +116,7 @@ TraceEvent *trace_event_iter_next(TraceEventIter *iter)
|
||||
iter->group++;
|
||||
}
|
||||
if (!iter->pattern ||
|
||||
pattern_glob(iter->pattern,
|
||||
trace_event_get_name(ev))) {
|
||||
g_pattern_match_simple(iter->pattern, trace_event_get_name(ev))) {
|
||||
return ev;
|
||||
}
|
||||
}
|
||||
|
100
util/log.c
100
util/log.c
@ -24,9 +24,11 @@
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "trace/control.h"
|
||||
#include "qemu/thread.h"
|
||||
|
||||
static char *logfilename;
|
||||
FILE *qemu_logfile;
|
||||
static QemuMutex qemu_logfile_mutex;
|
||||
QemuLogFile *qemu_logfile;
|
||||
int qemu_loglevel;
|
||||
static int log_append = 0;
|
||||
static GArray *debug_regions;
|
||||
@ -35,10 +37,14 @@ static GArray *debug_regions;
|
||||
int qemu_log(const char *fmt, ...)
|
||||
{
|
||||
int ret = 0;
|
||||
if (qemu_logfile) {
|
||||
QemuLogFile *logfile;
|
||||
|
||||
rcu_read_lock();
|
||||
logfile = atomic_rcu_read(&qemu_logfile);
|
||||
if (logfile) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
ret = vfprintf(qemu_logfile, fmt, ap);
|
||||
ret = vfprintf(logfile->fd, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
/* Don't pass back error results. */
|
||||
@ -46,57 +52,91 @@ int qemu_log(const char *fmt, ...)
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __attribute__((__constructor__)) qemu_logfile_init(void)
|
||||
{
|
||||
qemu_mutex_init(&qemu_logfile_mutex);
|
||||
}
|
||||
|
||||
static void qemu_logfile_free(QemuLogFile *logfile)
|
||||
{
|
||||
g_assert(logfile);
|
||||
|
||||
if (logfile->fd != stderr) {
|
||||
fclose(logfile->fd);
|
||||
}
|
||||
g_free(logfile);
|
||||
}
|
||||
|
||||
static bool log_uses_own_buffers;
|
||||
|
||||
/* enable or disable low levels log */
|
||||
void qemu_set_log(int log_flags)
|
||||
{
|
||||
bool need_to_open_file = false;
|
||||
QemuLogFile *logfile;
|
||||
|
||||
qemu_loglevel = log_flags;
|
||||
#ifdef CONFIG_TRACE_LOG
|
||||
qemu_loglevel |= LOG_TRACE;
|
||||
#endif
|
||||
if (!qemu_logfile &&
|
||||
(is_daemonized() ? logfilename != NULL : qemu_loglevel)) {
|
||||
/*
|
||||
* In all cases we only log if qemu_loglevel is set.
|
||||
* Also:
|
||||
* If not daemonized we will always log either to stderr
|
||||
* or to a file (if there is a logfilename).
|
||||
* If we are daemonized,
|
||||
* we will only log if there is a logfilename.
|
||||
*/
|
||||
if (qemu_loglevel && (!is_daemonized() || logfilename)) {
|
||||
need_to_open_file = true;
|
||||
}
|
||||
qemu_mutex_lock(&qemu_logfile_mutex);
|
||||
if (qemu_logfile && !need_to_open_file) {
|
||||
logfile = qemu_logfile;
|
||||
atomic_rcu_set(&qemu_logfile, NULL);
|
||||
call_rcu(logfile, qemu_logfile_free, rcu);
|
||||
} else if (!qemu_logfile && need_to_open_file) {
|
||||
logfile = g_new0(QemuLogFile, 1);
|
||||
if (logfilename) {
|
||||
qemu_logfile = fopen(logfilename, log_append ? "a" : "w");
|
||||
if (!qemu_logfile) {
|
||||
logfile->fd = fopen(logfilename, log_append ? "a" : "w");
|
||||
if (!logfile->fd) {
|
||||
g_free(logfile);
|
||||
perror(logfilename);
|
||||
_exit(1);
|
||||
}
|
||||
/* In case we are a daemon redirect stderr to logfile */
|
||||
if (is_daemonized()) {
|
||||
dup2(fileno(qemu_logfile), STDERR_FILENO);
|
||||
fclose(qemu_logfile);
|
||||
dup2(fileno(logfile->fd), STDERR_FILENO);
|
||||
fclose(logfile->fd);
|
||||
/* This will skip closing logfile in qemu_log_close() */
|
||||
qemu_logfile = stderr;
|
||||
logfile->fd = stderr;
|
||||
}
|
||||
} else {
|
||||
/* Default to stderr if no log file specified */
|
||||
assert(!is_daemonized());
|
||||
qemu_logfile = stderr;
|
||||
logfile->fd = stderr;
|
||||
}
|
||||
/* must avoid mmap() usage of glibc by setting a buffer "by hand" */
|
||||
if (log_uses_own_buffers) {
|
||||
static char logfile_buf[4096];
|
||||
|
||||
setvbuf(qemu_logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
|
||||
setvbuf(logfile->fd, logfile_buf, _IOLBF, sizeof(logfile_buf));
|
||||
} else {
|
||||
#if defined(_WIN32)
|
||||
/* Win32 doesn't support line-buffering, so use unbuffered output. */
|
||||
setvbuf(qemu_logfile, NULL, _IONBF, 0);
|
||||
setvbuf(logfile->fd, NULL, _IONBF, 0);
|
||||
#else
|
||||
setvbuf(qemu_logfile, NULL, _IOLBF, 0);
|
||||
setvbuf(logfile->fd, NULL, _IOLBF, 0);
|
||||
#endif
|
||||
log_append = 1;
|
||||
}
|
||||
atomic_rcu_set(&qemu_logfile, logfile);
|
||||
}
|
||||
if (qemu_logfile &&
|
||||
(is_daemonized() ? logfilename == NULL : !qemu_loglevel)) {
|
||||
qemu_log_close();
|
||||
}
|
||||
qemu_mutex_unlock(&qemu_logfile_mutex);
|
||||
}
|
||||
|
||||
void qemu_log_needs_buffers(void)
|
||||
@ -113,6 +153,7 @@ void qemu_set_log_filename(const char *filename, Error **errp)
|
||||
{
|
||||
char *pidstr;
|
||||
g_free(logfilename);
|
||||
logfilename = NULL;
|
||||
|
||||
pidstr = strstr(filename, "%");
|
||||
if (pidstr) {
|
||||
@ -224,18 +265,29 @@ out:
|
||||
/* fflush() the log file */
|
||||
void qemu_log_flush(void)
|
||||
{
|
||||
fflush(qemu_logfile);
|
||||
QemuLogFile *logfile;
|
||||
|
||||
rcu_read_lock();
|
||||
logfile = atomic_rcu_read(&qemu_logfile);
|
||||
if (logfile) {
|
||||
fflush(logfile->fd);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
/* Close the log file */
|
||||
void qemu_log_close(void)
|
||||
{
|
||||
if (qemu_logfile) {
|
||||
if (qemu_logfile != stderr) {
|
||||
fclose(qemu_logfile);
|
||||
}
|
||||
qemu_logfile = NULL;
|
||||
QemuLogFile *logfile;
|
||||
|
||||
qemu_mutex_lock(&qemu_logfile_mutex);
|
||||
logfile = qemu_logfile;
|
||||
|
||||
if (logfile) {
|
||||
atomic_rcu_set(&qemu_logfile, NULL);
|
||||
call_rcu(logfile, qemu_logfile_free, rcu);
|
||||
}
|
||||
qemu_mutex_unlock(&qemu_logfile_mutex);
|
||||
}
|
||||
|
||||
const QEMULogItem qemu_log_items[] = {
|
||||
|
Loading…
Reference in New Issue
Block a user