From patchwork Tue Sep 12 14:16:58 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Hildenbrand X-Patchwork-Id: 9949303 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id CA8506024A for ; Tue, 12 Sep 2017 14:17:10 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id BBB8C28C57 for ; Tue, 12 Sep 2017 14:17:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B052728C8F; Tue, 12 Sep 2017 14:17:10 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id F3E8B28C57 for ; Tue, 12 Sep 2017 14:17:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751413AbdILORI (ORCPT ); Tue, 12 Sep 2017 10:17:08 -0400 Received: from mx1.redhat.com ([209.132.183.28]:58876 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751395AbdILORH (ORCPT ); Tue, 12 Sep 2017 10:17:07 -0400 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 1E39E4ACB4 for ; Tue, 12 Sep 2017 14:17:07 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 1E39E4ACB4 Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx09.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=david@redhat.com Received: from t460s.redhat.com (ovpn-117-114.ams2.redhat.com [10.36.117.114]) by smtp.corp.redhat.com (Postfix) with ESMTP id 718D96FB7D; Tue, 12 Sep 2017 14:16:59 +0000 (UTC) From: David Hildenbrand To: kvm@vger.kernel.org Cc: Paolo Bonzini , =?UTF-8?q?Radim=20Kr=C4=8Dm=C3=A1=C5=99?= , david@redhat.com, Drew Jones , Laurent Vivier , Thomas Huth Subject: [kvm-unit-tests PATCH RFC] s390x: factor out running of tests into common code Date: Tue, 12 Sep 2017 16:16:58 +0200 Message-Id: <20170912141658.8146-1-david@redhat.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.15 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Tue, 12 Sep 2017 14:17:07 +0000 (UTC) Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP I want to use this in another file, so instead of replicating, factoring it out feels like the right thing to do. Let's directly provide it for all architectures, they just have to implement get_time_ms() in asm/time.h to use it. Signed-off-by: David Hildenbrand --- The next step would be allowing to add custom parameters to a test. (defining them similar to the test cases). Any other requests/nice to have? Does this make sense? lib/s390x/asm/time.h | 24 ++++++++++++ lib/testrun.c | 89 ++++++++++++++++++++++++++++++++++++++++++ lib/testrun.h | 41 ++++++++++++++++++++ s390x/Makefile | 1 + s390x/intercept.c | 106 ++++++++------------------------------------------- 5 files changed, 170 insertions(+), 91 deletions(-) create mode 100644 lib/s390x/asm/time.h create mode 100644 lib/testrun.c create mode 100644 lib/testrun.h diff --git a/lib/s390x/asm/time.h b/lib/s390x/asm/time.h new file mode 100644 index 0000000..856facd --- /dev/null +++ b/lib/s390x/asm/time.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017 Red Hat Inc + * + * Authors: + * Thomas Huth + * David Hildenbrand + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License version 2. + */ +#ifndef __ASMS390X_TIME_H +#define __ASMS390X_TIME_H + +static inline uint64_t get_clock_ms(void) +{ + uint64_t clk; + + asm volatile(" stck %0 " : : "Q"(clk) : "memory"); + + /* Bit 51 is incrememented each microsecond */ + return (clk >> (63 - 51)) / 1000; +} + +#endif diff --git a/lib/testrun.c b/lib/testrun.c new file mode 100644 index 0000000..6034767 --- /dev/null +++ b/lib/testrun.c @@ -0,0 +1,89 @@ +/* + * Utility functions for running/configuring a set of tests + * + * Copyright (c) 2017 Red Hat Inc + * + * Authors: + * Thomas Huth + * David Hildenbrand + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License version 2. + */ + +#include +#include + +void parse_test_args(const int argc, const char **argv, struct test *test) +{ + bool run_all = true; + int i, ti; + + test->iterations = 0; + test->time_to_run = 0; + + for (i = 1; i < argc; i++) { + if (!strcmp("-i", argv[i])) { + i++; + if (i >= argc) + report_abort("-i needs a parameter"); + test->iterations = atol(argv[i]); + } else if (!strcmp("-t", argv[i])) { + i++; + if (i >= argc) + report_abort("-t needs a parameter"); + test->time_to_run = atol(argv[i]); + } else for (ti = 0; test->test_cases[ti].name != NULL; ti++) { + if (!strcmp(test->test_cases[ti].name, argv[i])) { + run_all = false; + test->test_cases[ti].run_it = true; + break; + } else if (test->test_cases[ti + 1].name == NULL) { + report_abort("Unsupported parameter '%s'", + argv[i]); + } + } + } + + if (test->iterations == 0 && test->time_to_run == 0) + test->iterations = 1; + + if ((test->iterations > 1 || test->time_to_run) && + !test->multirun_supported) + report_abort("Test does not support multiruns."); + + if (run_all) { + for (ti = 0; test->test_cases[ti].name != NULL; ti++) + test->test_cases[ti].run_it = true; + } +} + +int run_test(struct test *test) +{ + unsigned long iterations = test->iterations; + unsigned long time_to_run = test->time_to_run; + uint64_t startclk; + int ti; + + report_prefix_push(test->name); + startclk = get_clock_ms(); + for (;;) { + for (ti = 0; test->test_cases[ti].name != NULL; ti++) { + report_prefix_push(test->test_cases[ti].name); + if (test->test_cases[ti].run_it) + test->test_cases[ti].func(); + report_prefix_pop(); + } + if (iterations) { + iterations -= 1; + if (iterations == 0) + break; + } + if (time_to_run) { + if (get_clock_ms() - startclk > time_to_run) + break; + } + } + report_prefix_pop(); + return report_summary(); +} diff --git a/lib/testrun.h b/lib/testrun.h new file mode 100644 index 0000000..8f9a2d7 --- /dev/null +++ b/lib/testrun.h @@ -0,0 +1,41 @@ +/* + * Utility functions for running/configuring a set of test cases + * + * Copyright (c) 2017 Red Hat Inc + * + * Authors: + * Thomas Huth + * David Hildenbrand + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU Library General Public License version 2. + */ +#ifndef __TESTRUN_H +#define __TESTRUN_H + +#include + +struct test_case { + const char *name; + void (*func)(void); + /* initialized by parse_test_args() */ + bool run_it; +}; + +#define DEFINE_TEST_CASE(_name, _func) { _name, _func, false } +#define DEFINE_TEST_CASE_END_OF_LIST() { } + +struct test { + /* to be initialized by the test */ + const char *name; + bool multirun_supported; + struct test_case *test_cases; + /* initialized by parse_test_args() */ + unsigned long iterations; + unsigned long time_to_run; +}; + +void parse_test_args(int argc, const char **argv, struct test *test); +int run_test(struct test *test); + +#endif /* __TESTRUN_H */ diff --git a/s390x/Makefile b/s390x/Makefile index bc099da..e174895 100644 --- a/s390x/Makefile +++ b/s390x/Makefile @@ -21,6 +21,7 @@ include $(SRCDIR)/scripts/asm-offsets.mak cflatobjs += lib/util.o cflatobjs += lib/alloc.o +cflatobjs += lib/testrun.o cflatobjs += lib/s390x/io.o cflatobjs += lib/s390x/stack.o cflatobjs += lib/s390x/sclp-ascii.o diff --git a/s390x/intercept.c b/s390x/intercept.c index 59e5fca..15e50f6 100644 --- a/s390x/intercept.c +++ b/s390x/intercept.c @@ -10,15 +10,13 @@ * under the terms of the GNU Library General Public License version 2. */ #include +#include #include #include #include static uint8_t pagebuf[PAGE_SIZE * 2] __attribute__((aligned(PAGE_SIZE * 2))); -static unsigned long nr_iterations; -static unsigned long time_to_run; - /* Test the STORE PREFIX instruction */ static void test_stpx(void) { @@ -159,95 +157,21 @@ static void test_testblock(void) check_pgm_int_code(PGM_INT_CODE_ADDRESSING); } -static uint64_t get_clock_ms(void) -{ - uint64_t clk; - - asm volatile(" stck %0 " : : "Q"(clk) : "memory"); - - /* Bit 51 is incrememented each microsecond */ - return (clk >> (63 - 51)) / 1000; -} - -struct { - const char *name; - void (*func)(void); - bool run_it; -} tests[] = { - { "stpx", test_stpx, false }, - { "spx", test_spx, false }, - { "stap", test_stap, false }, - { "stidp", test_stidp, false }, - { "testblock", test_testblock, false }, - { NULL, NULL, false } -}; - -static void parse_intercept_test_args(int argc, char **argv) -{ - int i, ti; - bool run_all = true; - - for (i = 1; i < argc; i++) { - if (!strcmp("-i", argv[i])) { - i++; - if (i >= argc) - report_abort("-i needs a parameter"); - nr_iterations = atol(argv[i]); - } else if (!strcmp("-t", argv[i])) { - i++; - if (i >= argc) - report_abort("-t needs a parameter"); - time_to_run = atol(argv[i]); - } else for (ti = 0; tests[ti].name != NULL; ti++) { - if (!strcmp(tests[ti].name, argv[i])) { - run_all = false; - tests[ti].run_it = true; - break; - } else if (tests[ti + 1].name == NULL) { - report_abort("Unsupported parameter '%s'", - argv[i]); - } - } - } - - if (run_all) { - for (ti = 0; tests[ti].name != NULL; ti++) - tests[ti].run_it = true; +static struct test test = { + .name = "intercept", + .multirun_supported = true, + .test_cases = (struct test_case[]) { + DEFINE_TEST_CASE("stpx", test_stpx), + DEFINE_TEST_CASE("spx", test_spx), + DEFINE_TEST_CASE("stap", test_stap), + DEFINE_TEST_CASE("stidp", test_stidp), + DEFINE_TEST_CASE("testblock", test_testblock), + DEFINE_TEST_CASE_END_OF_LIST() } -} +}; -int main(int argc, char **argv) +int main(int argc, const char **argv) { - uint64_t startclk; - int ti; - - parse_intercept_test_args(argc, argv); - - if (nr_iterations == 0 && time_to_run == 0) - nr_iterations = 1; - - report_prefix_push("intercept"); - - startclk = get_clock_ms(); - for (;;) { - for (ti = 0; tests[ti].name != NULL; ti++) { - report_prefix_push(tests[ti].name); - if (tests[ti].run_it) - tests[ti].func(); - report_prefix_pop(); - } - if (nr_iterations) { - nr_iterations -= 1; - if (nr_iterations == 0) - break; - } - if (time_to_run) { - if (get_clock_ms() - startclk > time_to_run) - break; - } - } - - report_prefix_pop(); - - return report_summary(); + parse_test_args(argc, argv, &test); + return run_test(&test); }