On 29.05.2017 12:06, Thomas Huth wrote: > Certain CPU instructions will cause an exit of the virtual > machine. Run some of these instructions to check whether > they are emulated right by KVM (or QEMU). > > Signed-off-by: Thomas Huth <thuth@xxxxxxxxxx> > --- > Note: This is the initial framework for running interception tests > ... more test will be added later (like testing exceptions once > we've got the infrastructure for this in place). Working on a patch for that, will post that soon. > > For running this test with QEMU TCG, you need to apply the > patch for the TEST BLOCK instruction which has not been merged yet: > https://lists.gnu.org/archive/html/qemu-devel/2017-05/msg04413.html > > s390x/Makefile | 1 + > s390x/intercept.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 100 insertions(+) > create mode 100644 s390x/intercept.c I think you should add that to s390x/unittests.cfg as well. (running all tests) > > diff --git a/s390x/Makefile b/s390x/Makefile > index e80add0..97745a1 100644 > --- a/s390x/Makefile > +++ b/s390x/Makefile > @@ -1,4 +1,5 @@ > tests = $(TEST_DIR)/selftest.elf > +tests += $(TEST_DIR)/intercept.elf > > all: directories test_cases > > diff --git a/s390x/intercept.c b/s390x/intercept.c > new file mode 100644 > index 0000000..b0057e3 > --- /dev/null > +++ b/s390x/intercept.c > @@ -0,0 +1,99 @@ > +/* > + * Interception tests - for s390x CPU instruction that cause a VM exit > + * > + * Copyright (c) 2017 Red Hat Inc > + * > + * Authors: > + * Thomas Huth <thuth@xxxxxxxxxx> > + * > + * 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 <libcflat.h> > +#include <asm/page.h> > + > +static uint8_t pagebuf[PAGE_SIZE * 2] __attribute__((aligned(PAGE_SIZE))); > + > +/* Test the SET PREFIX and STORE PREFIX instructions */ > +static void test_prefix(void) > +{ > + uint32_t old_prefix; > + uint32_t new_prefix = (uint32_t)(intptr_t)pagebuf; > + > + memset(pagebuf, 0, PAGE_SIZE * 2); > + > + /* > + * Temporarily change the prefix page to our buffer, and store > + * some facility bits there ... at least some of them should be > + * set in our buffer afterwards. > + */ > + asm volatile ( > + " stpx %0\n" > + " spx %1\n" > + " stfl 0\n" you could add another stpx to tmp_prefix here and test below if stpx actually return the correct value (e.g. not simply always 0). > + " spx %0\n" > + : "=m"(old_prefix) : "m"(new_prefix) : "memory"); > + report("spx + stfl", pagebuf[200] != 0); I have a patch that introduced the struct lowcore and generates asm-offsets, will post that soon. > +} > + > +/* Test the STORE CPU ADDRESS instruction */ > +static void test_stap(void) > +{ > + uint16_t cpuid; > + > + cpuid = 0xffff; you could initialize that directly. > + asm volatile ("stap %0\n" : "+m"(cpuid)); > + report("get cpu id", cpuid != 0xffff); > +} > + > +/* Test the TEST BLOCK instruction */ > +static void test_testblock(void) > +{ > + int cc; > + > + memset(pagebuf, 0xaa, PAGE_SIZE); > + > + asm volatile ( > + " lghi 0,0\n" > + " tb %1\n" > + " ipm %0\n" > + " srl %0,28\n" > + : "=d" (cc) > + : "a"(pagebuf + 0x123) > + : "memory", "0", "cc"); > + report("page cleared", > + cc == 0 && pagebuf[0] == 0 && pagebuf[PAGE_SIZE - 1] == 0); > +} > + > +struct { > + const char *name; > + void (*func)(void); > +} tests[] = { > + { "prefix", test_prefix }, > + { "stap", test_stap }, > + { "testblock", test_testblock }, > + { NULL, NULL } > +}; > + > +int main(int argc, char **argv) > +{ > + int all = 0; > + int i; > + > + report_prefix_push("intercept"); > + > + if (argc < 2 || (argc == 2 && !strcmp(argv[1], "all"))) > + all = 1; > + > + for (i = 0; tests[i].name != NULL; i++) { > + report_prefix_push(tests[i].name); > + if (all || strcmp(argv[1], tests[i].name) == 0) { > + tests[i].func(); > + } > + report_prefix_pop(); > + } > + > + report_prefix_pop(); > + > + return report_summary(); > +} > Looks good to me! -- Thanks, David