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:
Peter Maydell 2020-07-15 17:16:39 +01:00
commit dfcade7cef
12 changed files with 174 additions and 32 deletions

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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