Final fixes for 5.1-rc0
- minor documentation nit - docker.py bootstrap fixes - tweak containers.yml wildcards - fix float16 nan detection - conditional use of -Wpsabi - fix missing iotlb data for plugins - proper locking for helper based bb count - drop ppc64abi32 from the plugin check-tcg test -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAl8O4XwACgkQ+9DbCVqe KkQacQgAhAFT5KszapViBuKR78KacFWmGbeOYvwwxW/YMmtAJmABaxS6E2mJxUgw 8Bgc8nHiQ1V3M4EBzOKT+AEdCGoHYAHnpDnuYQ1M9b82Zf5Tmkg9pBL5TvucQ20w M7X1Z3UJtau1sMhH+k3Nc3OhZg4dqiOMWven7kefXjA+13kuu/40+hI/bohw58L9 OAWae2PUevxR2S01q5n6w4frUCnI+IPZoGLQZjSCbcakZqsuCFrc/Z20cfOIQM76 pe0Rm8VRHQ9XCuPGvZ9OOaCJQ7QF22MHMZmxNnlWJ4+zzsP32RjO273XknfFOmBN Af5eTZ8lKLBOxywXTXQ/ehSHf7FQ9Q== =rQef -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/stsquad/tags/pull-misc-for-rc0-150720-3' into staging Final fixes for 5.1-rc0 - minor documentation nit - docker.py bootstrap fixes - tweak containers.yml wildcards - fix float16 nan detection - conditional use of -Wpsabi - fix missing iotlb data for plugins - proper locking for helper based bb count - drop ppc64abi32 from the plugin check-tcg test # gpg: Signature made Wed 15 Jul 2020 11:59:08 BST # 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-misc-for-rc0-150720-3: .travis.yml: skip ppc64abi32-linux-user with plugins plugins: expand the bb plugin to be thread safe and track per-cpu cputlb: ensure we save the IOTLB data in case of reset tests/plugins: don't unconditionally add -Wpsabi fpu/softfloat: fix up float16 nan recognition gitlab-ci/containers: Add missing wildcard where we should look for changes docker.py: fix fetching of FROM layers tests/docker: Remove the libssh workaround from the ubuntu 20.04 image docs/devel: fix grammar in multi-thread-tcg Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
dfcade7cef
@ -24,6 +24,7 @@
|
||||
- changes:
|
||||
- .gitlab-ci.d/containers.yml
|
||||
- tests/docker/*
|
||||
- tests/docker/dockerfiles/*
|
||||
- if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
|
||||
- if: '$CI_COMMIT_REF_NAME == "testing/next"'
|
||||
|
||||
|
@ -350,9 +350,10 @@ jobs:
|
||||
# Run check-tcg against linux-user (with plugins)
|
||||
# we skip sparc64-linux-user until it has been fixed somewhat
|
||||
# we skip cris-linux-user as it doesn't use the common run loop
|
||||
# we skip ppc64abi32-linux-user as it seems to have a broken libc
|
||||
- name: "GCC plugins check-tcg (user)"
|
||||
env:
|
||||
- CONFIG="--disable-system --enable-plugins --enable-debug-tcg --target-list-exclude=sparc64-linux-user,cris-linux-user"
|
||||
- CONFIG="--disable-system --enable-plugins --enable-debug-tcg --target-list-exclude=sparc64-linux-user,cris-linux-user,ppc64abi32-linux-user"
|
||||
- TEST_BUILD_CMD="make build-tcg"
|
||||
- TEST_CMD="make check-tcg"
|
||||
- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-debug-tcg"
|
||||
|
@ -1073,6 +1073,24 @@ static uint64_t io_readx(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
|
||||
return val;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save a potentially trashed IOTLB entry for later lookup by plugin.
|
||||
*
|
||||
* We also need to track the thread storage address because the RCU
|
||||
* cleanup that runs when we leave the critical region (the current
|
||||
* execution) is actually in a different thread.
|
||||
*/
|
||||
static void save_iotlb_data(CPUState *cs, hwaddr addr,
|
||||
MemoryRegionSection *section, hwaddr mr_offset)
|
||||
{
|
||||
#ifdef CONFIG_PLUGIN
|
||||
SavedIOTLB *saved = &cs->saved_iotlb;
|
||||
saved->addr = addr;
|
||||
saved->section = section;
|
||||
saved->mr_offset = mr_offset;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
|
||||
int mmu_idx, uint64_t val, target_ulong addr,
|
||||
uintptr_t retaddr, MemOp op)
|
||||
@ -1092,6 +1110,12 @@ static void io_writex(CPUArchState *env, CPUIOTLBEntry *iotlbentry,
|
||||
}
|
||||
cpu->mem_io_pc = retaddr;
|
||||
|
||||
/*
|
||||
* The memory_region_dispatch may trigger a flush/resize
|
||||
* so for plugins we save the iotlb_data just in case.
|
||||
*/
|
||||
save_iotlb_data(cpu, iotlbentry->addr, section, mr_offset);
|
||||
|
||||
if (mr->global_locking && !qemu_mutex_iothread_locked()) {
|
||||
qemu_mutex_lock_iothread();
|
||||
locked = true;
|
||||
@ -1381,8 +1405,11 @@ void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
|
||||
* in the softmmu lookup code (or helper). We don't handle re-fills or
|
||||
* checking the victim table. This is purely informational.
|
||||
*
|
||||
* This should never fail as the memory access being instrumented
|
||||
* should have just filled the TLB.
|
||||
* This almost never fails as the memory access being instrumented
|
||||
* should have just filled the TLB. The one corner case is io_writex
|
||||
* which can cause TLB flushes and potential resizing of the TLBs
|
||||
* loosing the information we need. In those cases we need to recover
|
||||
* data from a copy of the io_tlb entry.
|
||||
*/
|
||||
|
||||
bool tlb_plugin_lookup(CPUState *cpu, target_ulong addr, int mmu_idx,
|
||||
@ -1406,8 +1433,13 @@ bool tlb_plugin_lookup(CPUState *cpu, target_ulong addr, int mmu_idx,
|
||||
data->v.ram.hostaddr = addr + tlbe->addend;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
SavedIOTLB *saved = &cpu->saved_iotlb;
|
||||
data->is_io = true;
|
||||
data->v.io.section = saved->section;
|
||||
data->v.io.offset = saved->mr_offset;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
3
configure
vendored
3
configure
vendored
@ -7115,6 +7115,9 @@ echo "GIT_UPDATE=$git_update" >> $config_host_mak
|
||||
|
||||
echo "ARCH=$ARCH" >> $config_host_mak
|
||||
|
||||
echo "GLIB_CFLAGS=$glib_cflags" >> $config_host_mak
|
||||
echo "GLIB_LDFLAGS=$glib_ldflags" >> $config_host_mak
|
||||
|
||||
if test "$default_devices" = "yes" ; then
|
||||
echo "CONFIG_MINIKCONF_MODE=--defconfig" >> $config_host_mak
|
||||
else
|
||||
|
@ -107,7 +107,7 @@ including:
|
||||
|
||||
- debugging operations (breakpoint insertion/removal)
|
||||
- some CPU helper functions
|
||||
- linux-user spawning it's first thread
|
||||
- linux-user spawning its first thread
|
||||
|
||||
This is done with the async_safe_run_on_cpu() mechanism to ensure all
|
||||
vCPUs are quiescent when changes are being made to shared global
|
||||
|
@ -254,7 +254,7 @@ bool float16_is_quiet_nan(float16 a_, float_status *status)
|
||||
if (snan_bit_is_one(status)) {
|
||||
return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
|
||||
} else {
|
||||
return ((a & ~0x8000) >= 0x7C80);
|
||||
return ((a >> 9) & 0x3F) == 0x3F;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -271,7 +271,7 @@ bool float16_is_signaling_nan(float16 a_, float_status *status)
|
||||
#else
|
||||
uint16_t a = float16_val(a_);
|
||||
if (snan_bit_is_one(status)) {
|
||||
return ((a & ~0x8000) >= 0x7C80);
|
||||
return ((a >> 9) & 0x3F) == 0x3F;
|
||||
} else {
|
||||
return (((a >> 9) & 0x3F) == 0x3E) && (a & 0x1FF);
|
||||
}
|
||||
|
@ -259,6 +259,18 @@ struct CPUWatchpoint {
|
||||
QTAILQ_ENTRY(CPUWatchpoint) entry;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PLUGIN
|
||||
/*
|
||||
* For plugins we sometime need to save the resolved iotlb data before
|
||||
* the memory regions get moved around by io_writex.
|
||||
*/
|
||||
typedef struct SavedIOTLB {
|
||||
hwaddr addr;
|
||||
MemoryRegionSection *section;
|
||||
hwaddr mr_offset;
|
||||
} SavedIOTLB;
|
||||
#endif
|
||||
|
||||
struct KVMState;
|
||||
struct kvm_run;
|
||||
|
||||
@ -417,7 +429,11 @@ struct CPUState {
|
||||
|
||||
DECLARE_BITMAP(plugin_mask, QEMU_PLUGIN_EV_MAX);
|
||||
|
||||
#ifdef CONFIG_PLUGIN
|
||||
GArray *plugin_mem_cbs;
|
||||
/* saved iotlb data from io_writex */
|
||||
SavedIOTLB saved_iotlb;
|
||||
#endif
|
||||
|
||||
/* TODO Move common fields from CPUArchState here. */
|
||||
int cpu_index;
|
||||
|
@ -116,6 +116,7 @@ typedef struct QObject QObject;
|
||||
typedef struct QString QString;
|
||||
typedef struct RAMBlock RAMBlock;
|
||||
typedef struct Range Range;
|
||||
typedef struct SavedIOTLB SavedIOTLB;
|
||||
typedef struct SHPCDevice SHPCDevice;
|
||||
typedef struct SSIBus SSIBus;
|
||||
typedef struct VirtIODevice VirtIODevice;
|
||||
|
@ -306,14 +306,18 @@ class Docker(object):
|
||||
checksum = _text_checksum(_dockerfile_preprocess(dockerfile))
|
||||
|
||||
if registry is not None:
|
||||
# see if we can fetch a cache copy, may fail...
|
||||
pull_args = ["pull", "%s/%s" % (registry, tag)]
|
||||
if self._do(pull_args, quiet=quiet) == 0:
|
||||
sources = re.findall("FROM qemu\/(.*)", dockerfile)
|
||||
# Fetch any cache layers we can, may fail
|
||||
for s in sources:
|
||||
pull_args = ["pull", "%s/qemu/%s" % (registry, s)]
|
||||
if self._do(pull_args, quiet=quiet) != 0:
|
||||
registry = None
|
||||
break
|
||||
# Make substitutions
|
||||
if registry is not None:
|
||||
dockerfile = dockerfile.replace("FROM qemu/",
|
||||
"FROM %s/qemu/" %
|
||||
(registry))
|
||||
else:
|
||||
registry = None
|
||||
|
||||
tmp_df = tempfile.NamedTemporaryFile(mode="w+t",
|
||||
encoding='utf-8',
|
||||
@ -339,6 +343,8 @@ class Docker(object):
|
||||
build_args += ["--build-arg", "BUILDKIT_INLINE_CACHE=1"]
|
||||
|
||||
if registry is not None:
|
||||
pull_args = ["pull", "%s/%s" % (registry, tag)]
|
||||
self._do(pull_args, quiet=quiet)
|
||||
cache = "%s/%s" % (registry, tag)
|
||||
build_args += ["--cache-from", cache]
|
||||
build_args += argv
|
||||
|
@ -65,9 +65,6 @@ RUN apt-get update && \
|
||||
RUN dpkg -l $PACKAGES | sort > /packages.txt
|
||||
ENV FEATURES clang tsan pyyaml sdl2
|
||||
|
||||
# https://bugs.launchpad.net/qemu/+bug/1838763
|
||||
ENV QEMU_CONFIGURE_OPTS --disable-libssh
|
||||
|
||||
# Apply patch https://reviews.llvm.org/D75820
|
||||
# This is required for TSan in clang-10 to compile with QEMU.
|
||||
RUN sed -i 's/^const/static const/g' /usr/lib/llvm-10/lib/clang/10.0.0/include/sanitizer/tsan_interface.h
|
||||
|
@ -1,9 +1,16 @@
|
||||
# -*- Mode: makefile -*-
|
||||
#
|
||||
# This Makefile example is fairly independent from the main makefile
|
||||
# so users can take and adapt it for their build. We only really
|
||||
# include config-host.mak so we don't have to repeat probing for
|
||||
# cflags that the main configure has already done for us.
|
||||
#
|
||||
|
||||
BUILD_DIR := $(CURDIR)/../..
|
||||
|
||||
include $(BUILD_DIR)/config-host.mak
|
||||
include $(SRC_PATH)/rules.mak
|
||||
|
||||
$(call set-vpath, $(SRC_PATH)/tests/plugin)
|
||||
VPATH += $(SRC_PATH)/tests/plugin
|
||||
|
||||
NAMES :=
|
||||
NAMES += bb
|
||||
@ -17,11 +24,18 @@ NAMES += lockstep
|
||||
|
||||
SONAMES := $(addsuffix .so,$(addprefix lib,$(NAMES)))
|
||||
|
||||
QEMU_CFLAGS += -fPIC -Wpsabi
|
||||
QEMU_CFLAGS += -I$(SRC_PATH)/include/qemu
|
||||
# The main QEMU uses Glib extensively so it's perfectly fine to use it
|
||||
# in plugins (which many example do).
|
||||
CFLAGS = $(GLIB_CFLAGS)
|
||||
CFLAGS += -fPIC
|
||||
CFLAGS += $(if $(findstring no-psabi,$(QEMU_CFLAGS)),-Wpsabi)
|
||||
CFLAGS += -I$(SRC_PATH)/include/qemu
|
||||
|
||||
all: $(SONAMES)
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
lib%.so: %.o
|
||||
$(CC) -shared -Wl,-soname,$@ -o $@ $^ $(LDLIBS)
|
||||
|
||||
|
@ -16,24 +16,67 @@
|
||||
|
||||
QEMU_PLUGIN_EXPORT int qemu_plugin_version = QEMU_PLUGIN_VERSION;
|
||||
|
||||
static uint64_t bb_count;
|
||||
static uint64_t insn_count;
|
||||
typedef struct {
|
||||
GMutex lock;
|
||||
int index;
|
||||
uint64_t bb_count;
|
||||
uint64_t insn_count;
|
||||
} CPUCount;
|
||||
|
||||
/* Used by the inline & linux-user counts */
|
||||
static bool do_inline;
|
||||
static CPUCount inline_count;
|
||||
|
||||
/* Dump running CPU total on idle? */
|
||||
static bool idle_report;
|
||||
static GPtrArray *counts;
|
||||
static int max_cpus;
|
||||
|
||||
static void gen_one_cpu_report(CPUCount *count, GString *report)
|
||||
{
|
||||
if (count->bb_count) {
|
||||
g_string_append_printf(report, "CPU%d: "
|
||||
"bb's: %" PRIu64", insns: %" PRIu64 "\n",
|
||||
count->index,
|
||||
count->bb_count, count->insn_count);
|
||||
}
|
||||
}
|
||||
|
||||
static void plugin_exit(qemu_plugin_id_t id, void *p)
|
||||
{
|
||||
g_autofree gchar *out = g_strdup_printf(
|
||||
"bb's: %" PRIu64", insns: %" PRIu64 "\n",
|
||||
bb_count, insn_count);
|
||||
qemu_plugin_outs(out);
|
||||
g_autoptr(GString) report = g_string_new("");
|
||||
|
||||
if (do_inline || !max_cpus) {
|
||||
g_string_printf(report, "bb's: %" PRIu64", insns: %" PRIu64 "\n",
|
||||
inline_count.bb_count, inline_count.insn_count);
|
||||
} else {
|
||||
g_ptr_array_foreach(counts, (GFunc) gen_one_cpu_report, report);
|
||||
}
|
||||
qemu_plugin_outs(report->str);
|
||||
}
|
||||
|
||||
static void vcpu_idle(qemu_plugin_id_t id, unsigned int cpu_index)
|
||||
{
|
||||
CPUCount *count = g_ptr_array_index(counts, cpu_index);
|
||||
g_autoptr(GString) report = g_string_new("");
|
||||
gen_one_cpu_report(count, report);
|
||||
|
||||
if (report->len > 0) {
|
||||
g_string_prepend(report, "Idling ");
|
||||
qemu_plugin_outs(report->str);
|
||||
}
|
||||
}
|
||||
|
||||
static void vcpu_tb_exec(unsigned int cpu_index, void *udata)
|
||||
{
|
||||
unsigned long n_insns = (unsigned long)udata;
|
||||
CPUCount *count = max_cpus ?
|
||||
g_ptr_array_index(counts, cpu_index) : &inline_count;
|
||||
|
||||
insn_count += n_insns;
|
||||
bb_count++;
|
||||
unsigned long n_insns = (unsigned long)udata;
|
||||
g_mutex_lock(&count->lock);
|
||||
count->insn_count += n_insns;
|
||||
count->bb_count++;
|
||||
g_mutex_unlock(&count->lock);
|
||||
}
|
||||
|
||||
static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
|
||||
@ -42,9 +85,10 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb)
|
||||
|
||||
if (do_inline) {
|
||||
qemu_plugin_register_vcpu_tb_exec_inline(tb, QEMU_PLUGIN_INLINE_ADD_U64,
|
||||
&bb_count, 1);
|
||||
&inline_count.bb_count, 1);
|
||||
qemu_plugin_register_vcpu_tb_exec_inline(tb, QEMU_PLUGIN_INLINE_ADD_U64,
|
||||
&insn_count, n_insns);
|
||||
&inline_count.insn_count,
|
||||
n_insns);
|
||||
} else {
|
||||
qemu_plugin_register_vcpu_tb_exec_cb(tb, vcpu_tb_exec,
|
||||
QEMU_PLUGIN_CB_NO_REGS,
|
||||
@ -56,8 +100,35 @@ QEMU_PLUGIN_EXPORT int qemu_plugin_install(qemu_plugin_id_t id,
|
||||
const qemu_info_t *info,
|
||||
int argc, char **argv)
|
||||
{
|
||||
if (argc && strcmp(argv[0], "inline") == 0) {
|
||||
do_inline = true;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < argc; i++) {
|
||||
char *opt = argv[i];
|
||||
if (g_strcmp0(opt, "inline") == 0) {
|
||||
do_inline = true;
|
||||
} else if (g_strcmp0(opt, "idle") == 0) {
|
||||
idle_report = true;
|
||||
} else {
|
||||
fprintf(stderr, "option parsing failed: %s\n", opt);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (info->system_emulation && !do_inline) {
|
||||
max_cpus = info->system.max_vcpus;
|
||||
counts = g_ptr_array_new();
|
||||
for (i = 0; i < max_cpus; i++) {
|
||||
CPUCount *count = g_new0(CPUCount, 1);
|
||||
g_mutex_init(&count->lock);
|
||||
count->index = i;
|
||||
g_ptr_array_add(counts, count);
|
||||
}
|
||||
} else if (!do_inline) {
|
||||
g_mutex_init(&inline_count.lock);
|
||||
}
|
||||
|
||||
if (idle_report) {
|
||||
qemu_plugin_register_vcpu_idle_cb(id, vcpu_idle);
|
||||
}
|
||||
|
||||
qemu_plugin_register_vcpu_tb_trans_cb(id, vcpu_tb_trans);
|
||||
|
Loading…
Reference in New Issue
Block a user