diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/plugin/bb.c | 6 | ||||
-rw-r--r-- | tests/plugin/howvec.c | 26 | ||||
-rw-r--r-- | tests/plugin/insn.c | 3 | ||||
-rwxr-xr-x | tests/qemu-iotests/214 | 4 | ||||
-rw-r--r-- | tests/rcutorture.c | 74 | ||||
-rw-r--r-- | tests/tcg/Makefile.target | 4 | ||||
-rw-r--r-- | tests/tcg/aarch64/Makefile.softmmu-target | 2 | ||||
-rw-r--r-- | tests/tcg/aarch64/pauth-4.c | 54 | ||||
-rwxr-xr-x | tests/tcg/configure.sh | 2 |
9 files changed, 116 insertions, 59 deletions
diff --git a/tests/plugin/bb.c b/tests/plugin/bb.c index f30bea0..df19fd3 100644 --- a/tests/plugin/bb.c +++ b/tests/plugin/bb.c @@ -22,9 +22,9 @@ static bool do_inline; static void plugin_exit(qemu_plugin_id_t id, void *p) { - g_autofree gchar *out; - out = g_strdup_printf("bb's: %" PRIu64", insns: %" PRIu64 "\n", - bb_count, insn_count); + g_autofree gchar *out = g_strdup_printf( + "bb's: %" PRIu64", insns: %" PRIu64 "\n", + bb_count, insn_count); qemu_plugin_outs(out); } diff --git a/tests/plugin/howvec.c b/tests/plugin/howvec.c index 4ca555e..3b9a693 100644 --- a/tests/plugin/howvec.c +++ b/tests/plugin/howvec.c @@ -163,6 +163,13 @@ static gint cmp_exec_count(gconstpointer a, gconstpointer b) return ea->count > eb->count ? -1 : 1; } +static void free_record(gpointer data) +{ + InsnExecCount *rec = (InsnExecCount *) data; + g_free(rec->insn); + g_free(rec); +} + static void plugin_exit(qemu_plugin_id_t id, void *p) { g_autoptr(GString) report = g_string_new("Instruction Classes:\n"); @@ -195,30 +202,31 @@ static void plugin_exit(qemu_plugin_id_t id, void *p) counts = g_hash_table_get_values(insns); if (counts && g_list_next(counts)) { - GList *it; - g_string_append_printf(report,"Individual Instructions:\n"); + counts = g_list_sort(counts, cmp_exec_count); - it = g_list_sort(counts, cmp_exec_count); - - for (i = 0; i < limit && it->next; i++, it = it->next) { - InsnExecCount *rec = (InsnExecCount *) it->data; - g_string_append_printf(report, "Instr: %-24s\t(%ld hits)\t(op=%#08x/%s)\n", + for (i = 0; i < limit && g_list_next(counts); + i++, counts = g_list_next(counts)) { + InsnExecCount *rec = (InsnExecCount *) counts->data; + g_string_append_printf(report, + "Instr: %-24s\t(%ld hits)\t(op=%#08x/%s)\n", rec->insn, rec->count, rec->opcode, rec->class ? rec->class->class : "un-categorised"); } - g_list_free(it); + g_list_free(counts); } + g_hash_table_destroy(insns); + qemu_plugin_outs(report->str); } static void plugin_init(void) { - insns = g_hash_table_new(NULL, g_direct_equal); + insns = g_hash_table_new_full(NULL, g_direct_equal, NULL, &free_record); } static void vcpu_insn_exec_before(unsigned int cpu_index, void *udata) diff --git a/tests/plugin/insn.c b/tests/plugin/insn.c index 0a8f5a0..a9a6e41 100644 --- a/tests/plugin/insn.c +++ b/tests/plugin/insn.c @@ -44,8 +44,7 @@ static void vcpu_tb_trans(qemu_plugin_id_t id, struct qemu_plugin_tb *tb) static void plugin_exit(qemu_plugin_id_t id, void *p) { - g_autofree gchar *out; - out = g_strdup_printf("insns: %" PRIu64 "\n", insn_count); + g_autofree gchar *out = g_strdup_printf("insns: %" PRIu64 "\n", insn_count); qemu_plugin_outs(out); } diff --git a/tests/qemu-iotests/214 b/tests/qemu-iotests/214 index 3500e0c..af677d9 100755 --- a/tests/qemu-iotests/214 +++ b/tests/qemu-iotests/214 @@ -125,9 +125,9 @@ $QEMU_IO -c "write -P 0xcc $offset $data_size" "json:{\ sizeB=$($QEMU_IMG info --output=json "$TEST_IMG" | sed -n '/"actual-size":/ s/[^0-9]//gp') -if [ $sizeA -le $sizeB ] +if [ $sizeA -lt $sizeB ] then - echo "Compression ERROR" + echo "Compression ERROR ($sizeA < $sizeB)" fi $QEMU_IMG check --output=json "$TEST_IMG" | diff --git a/tests/rcutorture.c b/tests/rcutorture.c index 49311c8..732f03a 100644 --- a/tests/rcutorture.c +++ b/tests/rcutorture.c @@ -65,8 +65,6 @@ #include "qemu/rcu.h" #include "qemu/thread.h" -long long n_reads = 0LL; -long n_updates = 0L; int nthreadsrunning; #define GOFLAG_INIT 0 @@ -78,11 +76,20 @@ static volatile int goflag = GOFLAG_INIT; #define RCU_READ_RUN 1000 #define NR_THREADS 100 -static QemuMutex counts_mutex; static QemuThread threads[NR_THREADS]; static struct rcu_reader_data *data[NR_THREADS]; static int n_threads; +/* + * Statistical counts + * + * These are the sum of local counters at the end of a run. + * Updates are protected by a mutex. + */ +static QemuMutex counts_mutex; +long long n_reads = 0LL; +long n_updates = 0L; + static void create_thread(void *(*func)(void *)) { if (n_threads >= NR_THREADS) { @@ -223,15 +230,15 @@ static void uperftest(int nupdaters, int duration) #define RCU_STRESS_PIPE_LEN 10 struct rcu_stress { - int pipe_count; + int age; /* how many update cycles while not rcu_stress_current */ int mbtest; }; struct rcu_stress rcu_stress_array[RCU_STRESS_PIPE_LEN] = { { 0 } }; struct rcu_stress *rcu_stress_current; -int rcu_stress_idx; - int n_mberror; + +/* Updates protected by counts_mutex */ long long rcu_stress_count[RCU_STRESS_PIPE_LEN + 1]; @@ -253,7 +260,7 @@ static void *rcu_read_stress_test(void *arg) while (goflag == GOFLAG_RUN) { rcu_read_lock(); p = atomic_rcu_read(&rcu_stress_current); - if (p->mbtest == 0) { + if (atomic_read(&p->mbtest) == 0) { n_mberror++; } rcu_read_lock(); @@ -261,7 +268,7 @@ static void *rcu_read_stress_test(void *arg) garbage++; } rcu_read_unlock(); - pc = p->pipe_count; + pc = atomic_read(&p->age); rcu_read_unlock(); if ((pc > RCU_STRESS_PIPE_LEN) || (pc < 0)) { pc = RCU_STRESS_PIPE_LEN; @@ -280,32 +287,52 @@ static void *rcu_read_stress_test(void *arg) return NULL; } +/* + * Stress Test Updater + * + * The updater cycles around updating rcu_stress_current to point at + * one of the rcu_stress_array_entries and resets it's age. It + * then increments the age of all the other entries. The age + * will be read under an rcu_read_lock() and distribution of values + * calculated. The final result gives an indication of how many + * previously current rcu_stress entries are in flight until the RCU + * cycle complete. + */ static void *rcu_update_stress_test(void *arg) { - int i; - struct rcu_stress *p; + int i, rcu_stress_idx = 0; + struct rcu_stress *cp = atomic_read(&rcu_stress_current); rcu_register_thread(); - *(struct rcu_reader_data **)arg = &rcu_reader; + while (goflag == GOFLAG_INIT) { g_usleep(1000); } + while (goflag == GOFLAG_RUN) { - i = rcu_stress_idx + 1; - if (i >= RCU_STRESS_PIPE_LEN) { - i = 0; + struct rcu_stress *p; + rcu_stress_idx++; + if (rcu_stress_idx >= RCU_STRESS_PIPE_LEN) { + rcu_stress_idx = 0; } - p = &rcu_stress_array[i]; - p->mbtest = 0; + p = &rcu_stress_array[rcu_stress_idx]; + /* catching up with ourselves would be a bug */ + assert(p != cp); + atomic_set(&p->mbtest, 0); smp_mb(); - p->pipe_count = 0; - p->mbtest = 1; + atomic_set(&p->age, 0); + atomic_set(&p->mbtest, 1); atomic_rcu_set(&rcu_stress_current, p); - rcu_stress_idx = i; + cp = p; + /* + * New RCU structure is now live, update pipe counts on old + * ones. + */ for (i = 0; i < RCU_STRESS_PIPE_LEN; i++) { if (i != rcu_stress_idx) { - rcu_stress_array[i].pipe_count++; + atomic_set(&rcu_stress_array[i].age, + rcu_stress_array[i].age + 1); } } synchronize_rcu(); @@ -338,7 +365,7 @@ static void stresstest(int nreaders, int duration) int i; rcu_stress_current = &rcu_stress_array[0]; - rcu_stress_current->pipe_count = 0; + rcu_stress_current->age = 0; rcu_stress_current->mbtest = 1; for (i = 0; i < nreaders; i++) { create_thread(rcu_read_stress_test); @@ -368,7 +395,7 @@ static void gtest_stress(int nreaders, int duration) int i; rcu_stress_current = &rcu_stress_array[0]; - rcu_stress_current->pipe_count = 0; + rcu_stress_current->age = 0; rcu_stress_current->mbtest = 1; for (i = 0; i < nreaders; i++) { create_thread(rcu_read_stress_test); @@ -413,7 +440,8 @@ static void gtest_stress_10_5(void) static void usage(int argc, char *argv[]) { - fprintf(stderr, "Usage: %s [nreaders [ perf | stress ] ]\n", argv[0]); + fprintf(stderr, "Usage: %s [nreaders [ [r|u]perf | stress [duration]]\n", + argv[0]); exit(-1); } diff --git a/tests/tcg/Makefile.target b/tests/tcg/Makefile.target index 3c7421a..b3cff3c 100644 --- a/tests/tcg/Makefile.target +++ b/tests/tcg/Makefile.target @@ -79,7 +79,7 @@ QEMU_OPTS= # If TCG debugging is enabled things are a lot slower ifeq ($(CONFIG_DEBUG_TCG),y) -TIMEOUT=45 +TIMEOUT=60 else TIMEOUT=15 endif @@ -137,7 +137,7 @@ PLUGINS=$(notdir $(wildcard $(PLUGIN_DIR)/*.so)) $(foreach p,$(PLUGINS), \ $(foreach t,$(TESTS),\ $(eval run-plugin-$(t)-with-$(p): $t $p) \ - $(eval run-plugin-$(t)-with-$(p): TIMEOUT=30) \ + $(eval run-plugin-$(t)-with-$(p): TIMEOUT=60) \ $(eval RUN_TESTS+=run-plugin-$(t)-with-$(p)))) endif diff --git a/tests/tcg/aarch64/Makefile.softmmu-target b/tests/tcg/aarch64/Makefile.softmmu-target index d2299b9..71f72cf 100644 --- a/tests/tcg/aarch64/Makefile.softmmu-target +++ b/tests/tcg/aarch64/Makefile.softmmu-target @@ -70,4 +70,6 @@ pauth-3: $(call skip-test, "BUILD of $@", "missing compiler support") run-pauth-3: $(call skip-test, "RUN of pauth-3", "not built") +run-plugin-pauth-3-with-%: + $(call skip-test, "RUN of pauth-3 ($*)", "not built") endif diff --git a/tests/tcg/aarch64/pauth-4.c b/tests/tcg/aarch64/pauth-4.c index 1040e92..24a639e 100644 --- a/tests/tcg/aarch64/pauth-4.c +++ b/tests/tcg/aarch64/pauth-4.c @@ -1,25 +1,45 @@ #include <stdint.h> #include <assert.h> +#include <stdio.h> +#include <stdlib.h> + +#define TESTS 1000 int main() { - uintptr_t x, y; + int i, count = 0; + float perc; + void *base = malloc(TESTS); + + for (i = 0; i < TESTS; i++) { + uintptr_t in, x, y; + + in = i + (uintptr_t) base; + + asm("mov %0, %[in]\n\t" + "pacia %0, sp\n\t" /* sigill if pauth not supported */ + "eor %0, %0, #4\n\t" /* corrupt single bit */ + "mov %1, %0\n\t" + "autia %1, sp\n\t" /* validate corrupted pointer */ + "xpaci %0\n\t" /* strip pac from corrupted pointer */ + : /* out */ "=r"(x), "=r"(y) + : /* in */ [in] "r" (in) + : /* clobbers */); - asm("mov %0, lr\n\t" - "pacia %0, sp\n\t" /* sigill if pauth not supported */ - "eor %0, %0, #4\n\t" /* corrupt single bit */ - "mov %1, %0\n\t" - "autia %1, sp\n\t" /* validate corrupted pointer */ - "xpaci %0\n\t" /* strip pac from corrupted pointer */ - : "=r"(x), "=r"(y)); + /* + * Once stripped, the corrupted pointer is of the form 0x0000...wxyz. + * We expect the autia to indicate failure, producing a pointer of the + * form 0x000e....wxyz. Use xpaci and != for the test, rather than + * extracting explicit bits from the top, because the location of the + * error code "e" depends on the configuration of virtual memory. + */ + if (x != y) { + count++; + } - /* - * Once stripped, the corrupted pointer is of the form 0x0000...wxyz. - * We expect the autia to indicate failure, producing a pointer of the - * form 0x000e....wxyz. Use xpaci and != for the test, rather than - * extracting explicit bits from the top, because the location of the - * error code "e" depends on the configuration of virtual memory. - */ - assert(x != y); - return 0; + } + perc = (float) count / (float) TESTS; + printf("Checks Passed: %0.2f%%", perc * 100.0); + assert(perc > 0.95); + return 0; } diff --git a/tests/tcg/configure.sh b/tests/tcg/configure.sh index 9eb6ba3..eaaaff6 100755 --- a/tests/tcg/configure.sh +++ b/tests/tcg/configure.sh @@ -228,7 +228,7 @@ for target in $target_list; do echo "CROSS_CC_HAS_SVE=y" >> $config_target_mak fi if do_compiler "$target_compiler" $target_compiler_cflags \ - -march=-march=armv8.3-a -o $TMPE $TMPC; then + -march=armv8.3-a -o $TMPE $TMPC; then echo "CROSS_CC_HAS_ARMV8_3=y" >> $config_target_mak fi ;; |