diff mbox series

[kvm-unit-tests,2/4] chaos: add generic stress test

Message ID 20201223010850.111882-3-pbonzini@redhat.com (mailing list archive)
State New, archived
Headers show
Series add generic stress test | expand

Commit Message

Paolo Bonzini Dec. 23, 2020, 1:08 a.m. UTC
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 lib/x86/processor.h |   2 +-
 x86/Makefile.x86_64 |   1 +
 x86/chaos.c         | 114 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 116 insertions(+), 1 deletion(-)
 create mode 100644 x86/chaos.c
diff mbox series

Patch

diff --git a/lib/x86/processor.h b/lib/x86/processor.h
index 291d24b..a53654a 100644
--- a/lib/x86/processor.h
+++ b/lib/x86/processor.h
@@ -546,7 +546,7 @@  static inline void irq_enable(void)
     asm volatile("sti");
 }
 
-static inline void invlpg(volatile void *va)
+static inline void invlpg(const volatile void *va)
 {
 	asm volatile("invlpg (%0)" ::"r" (va) : "memory");
 }
diff --git a/x86/Makefile.x86_64 b/x86/Makefile.x86_64
index af61d85..761a1d9 100644
--- a/x86/Makefile.x86_64
+++ b/x86/Makefile.x86_64
@@ -20,6 +20,7 @@  tests += $(TEST_DIR)/tscdeadline_latency.flat
 tests += $(TEST_DIR)/intel-iommu.flat
 tests += $(TEST_DIR)/vmware_backdoors.flat
 tests += $(TEST_DIR)/rdpru.flat
+tests += $(TEST_DIR)/chaos.flat
 
 include $(SRCDIR)/$(TEST_DIR)/Makefile.common
 
diff --git a/x86/chaos.c b/x86/chaos.c
new file mode 100644
index 0000000..e723a3b
--- /dev/null
+++ b/x86/chaos.c
@@ -0,0 +1,114 @@ 
+#include "libcflat.h"
+#include "smp.h"
+#include "bitops.h"
+#include "string.h"
+#include "alloc.h"
+#include "alloc_page.h"
+#include "asm/page.h"
+#include "processor.h"
+
+#define MAX_NR_CPUS 256
+
+struct chaos_args {
+	long npages;		/* 0 for CPU workload. */
+	const char *mem;
+	int invtlb;
+};
+
+int ncpus;
+struct chaos_args all_args[MAX_NR_CPUS];
+
+static void parse_arg(struct chaos_args *args, const char *arg)
+{
+	char *s = strdup(arg);
+	char *p = s;
+
+	while (*p) {
+		char *word = p;
+		char delim = strdelim(&p, ",=");
+		long i = 0;
+		bool have_arg = false;
+		if (delim == '=') {
+			char *num = p;
+			strdelim(&p, ",");
+			if (!parse_long(num, &i))
+				printf("invalid argument for %s\n", word);
+			else
+				have_arg = true;
+		}
+
+		if (!strcmp(word, "mem")) {
+			if (!have_arg)
+				i = 12;
+			else if (i >= BITS_PER_LONG - 1 - PAGE_SHIFT) {
+				printf("mem argument too large, using 12\n");
+				i = 12;
+			}
+			args->npages = 1 << i;
+			args->mem = alloc_pages(i);
+			if (!args->mem)
+				printf("could not allocate memory\n");
+			printf("CPU %d: mem=%ld @ %p\n", smp_id(), i, args->mem);
+		} else if (!strcmp(word, "invtlb")) {
+			if (!have_arg)
+				i = 1;
+			else if (i != 0 && i != 1) {
+				printf("invtlb argument must be 0 or 1\n");
+				i = 1;
+			}
+			args->invtlb = i;
+			printf("CPU %d: invtlb=%ld\n", smp_id(), i);
+		} else {
+			printf("invalid argument %s\n", word);
+		}
+	}
+	free(s);
+}
+
+static void __attribute__((noreturn)) stress(void *data)
+{
+    const char *arg = data;
+    struct chaos_args *args = &all_args[smp_id()];
+
+    printf("starting CPU %d workload: %s\n", smp_id(), arg);
+    parse_arg(args, arg);
+
+    for (;;) {
+	    if (args->mem) {
+		    const char *s = args->mem;
+		    const char *e = s + (args->npages << PAGE_SHIFT);
+		    long i;
+		    for (i = args->npages; args->invtlb && i--; )
+			    invlpg(s + ((args->npages - i) << PAGE_SHIFT));
+		    while (s < e) {
+			    (*(unsigned long *)s)++;
+			    s += sizeof(unsigned long);
+		    }
+	    }
+    }
+}
+
+int main(int argc, char *argv[])
+{
+    int i;
+
+    setup_vm();
+    if (argc <= 1) {
+        return 1;
+    }
+
+    argv++;
+    argc--;
+    ncpus = cpu_count();
+    if (ncpus > MAX_NR_CPUS)
+	    ncpus = MAX_NR_CPUS;
+
+    for (i = 1; i < ncpus; ++i) {
+        if (i >= argc) {
+            break;
+        }
+        on_cpu_async(i, stress, argv[i]);
+    }
+
+    stress(argv[0]);
+}