On Thu, 25 Feb 2016 22:19:13 +0100 Thomas Huth <thuth@xxxxxxxxxx> wrote: > Introduce a test for sPAPR hypercalls, starting with the two > hypercalls H_SET_SPRG0 and H_PAGE_INIT. > > Signed-off-by: Thomas Huth <thuth@xxxxxxxxxx> Reviewed-by: David Gibson <david@xxxxxxxxxxxxxxxxxxxxx> > --- > The patch has to be applied on top of Andrew Jones' ppc64 patch > series. You also need the latest QEMU development version since > the hypercalls have only been added recently. > > lib/powerpc/asm/hcall.h | 3 + > powerpc/Makefile.common | 5 +- > powerpc/spapr_hcall.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++ > powerpc/unittests.cfg | 3 + > 4 files changed, 154 insertions(+), 1 deletion(-) > create mode 100644 powerpc/spapr_hcall.c > > diff --git a/lib/powerpc/asm/hcall.h b/lib/powerpc/asm/hcall.h > index 75eac45..3fe8227 100644 > --- a/lib/powerpc/asm/hcall.h > +++ b/lib/powerpc/asm/hcall.h > @@ -11,8 +11,11 @@ > > #define H_SUCCESS 0 > #define H_HARDWARE -1 > +#define H_PARAMETER -4 > > +#define H_SET_SPRG0 0x24 > #define H_SET_DABR 0x28 > +#define H_PAGE_INIT 0x2c > #define H_PUT_TERM_CHAR 0x58 > > #ifndef __ASSEMBLY__ > diff --git a/powerpc/Makefile.common b/powerpc/Makefile.common > index 3a03ab6..6c0f47c 100644 > --- a/powerpc/Makefile.common > +++ b/powerpc/Makefile.common > @@ -9,7 +9,8 @@ ifeq ($(LOADADDR),) > endif > > tests-common = \ > - $(TEST_DIR)/selftest.elf > + $(TEST_DIR)/selftest.elf \ > + $(TEST_DIR)/spapr_hcall.elf > > all: $(TEST_DIR)/boot_rom.bin test_cases > > @@ -69,3 +70,5 @@ generated_files = $(asm-offsets) > test_cases: $(generated_files) $(tests-common) $(tests) > > $(TEST_DIR)/selftest.elf: $(cstart.o) $(reloc.o) $(TEST_DIR)/selftest.o > + > +$(TEST_DIR)/spapr_hcall.elf: $(cstart.o) $(reloc.o) $(TEST_DIR)/spapr_hcall.o > diff --git a/powerpc/spapr_hcall.c b/powerpc/spapr_hcall.c > new file mode 100644 > index 0000000..886217d > --- /dev/null > +++ b/powerpc/spapr_hcall.c > @@ -0,0 +1,144 @@ > +/* > + * Test sPAPR hypervisor calls (aka. h-calls) > + * > + * Copyright 2016 Thomas Huth, Red Hat Inc. > + * > + * This work is licensed under the terms of the GNU LGPL, version 2. > + */ > +#include <libcflat.h> > +#include <util.h> > +#include <alloc.h> > +#include <asm/hcall.h> > + > +#define PAGE_SIZE 4096 > + > +#define H_ZERO_PAGE (1 << (63-48)) > +#define H_COPY_PAGE (1 << (63-49)) > + > +#define mfspr(nr) ({ \ > + u64 ret; \ > + asm volatile("mfspr %0,%1" : "=r"(ret) : "i"(nr)); \ > + ret; \ > +}) > + > +#define SPR_SPRG0 0x110 > + > +static u64 h_set_sprg0(u64 new_sprg0) > +{ > + unsigned long in[8], out[8]; > + > + in[0] = new_sprg0; > + > + return hcall(H_SET_SPRG0, in, out); > +} > + > +/** > + * Test the H_SET_SPRG0 h-call by setting some values and > + * checking whether the SPRG0 register contains the correct > + * values afterwards > + */ > +static void test_h_set_sprg0(int argc, char **argv) > +{ > + u64 sprg0, sprg0_orig; > + int rc; > + > + if (argc > 1) > + report_abort("Unsupported argument: '%s'", argv[1]); > + > + sprg0_orig = mfspr(SPR_SPRG0); > + > + rc = h_set_sprg0(0xcafebabedeadbeefULL); > + sprg0 = mfspr(SPR_SPRG0); > + report("sprg0 = 0xcafebabedeadbeef", > + rc == H_SUCCESS && sprg0 == 0xcafebabedeadbeefULL); > + > + rc = h_set_sprg0(0xaaaaaaaa55555555ULL); > + sprg0 = mfspr(SPR_SPRG0); > + report("sprg0 = 0xaaaaaaaa55555555", > + rc == H_SUCCESS && sprg0 == 0xaaaaaaaa55555555ULL); > + > + rc = h_set_sprg0(sprg0_orig); > + sprg0 = mfspr(SPR_SPRG0); > + report("sprg0 = 0x%llx", > + rc == H_SUCCESS && sprg0 == sprg0_orig, sprg0_orig); > +} > + > +static u64 h_page_init(u64 flags, void *destination, void *source) > +{ > + unsigned long in[8], out[8]; > + > + in[0] = flags; > + in[1] = (unsigned long)destination; > + in[2] = (unsigned long)source; > + > + return hcall(H_PAGE_INIT, in, out); > +} > + > +/** > + * Test the H_PAGE_INIT h-call by using it to clear and to > + * copy a page, and by checking for the correct values in > + * the destination page afterwards > + */ > +static void test_h_page_init(int argc, char **argv) > +{ > + u8 *dst, *src; > + int rc; > + > + if (argc > 1) > + report_abort("Unsupported argument: '%s'", argv[1]); > + > + dst = memalign(PAGE_SIZE, PAGE_SIZE); > + src = memalign(PAGE_SIZE, PAGE_SIZE); > + if (!dst || !src) > + report_abort("Failed to alloc memory"); > + > + memset(dst, 0xaa, PAGE_SIZE); > + rc = h_page_init(H_ZERO_PAGE, dst, src); > + report("h_zero_page", rc == H_SUCCESS && *(u64*)dst == 0); > + > + *(u64*)src = 0xbeefc0dedeadcafeULL; > + rc = h_page_init(H_COPY_PAGE, dst, src); > + report("h_copy_page", > + rc == H_SUCCESS && *(u64*)dst == 0xbeefc0dedeadcafeULL); > + > + *(u64*)src = 0x9abcdef012345678ULL; > + rc = h_page_init(H_COPY_PAGE|H_ZERO_PAGE, dst, src); > + report("h_copy_page+h_zero_page", > + rc == H_SUCCESS && *(u64*)dst == 0x9abcdef012345678ULL); > + > + rc = h_page_init(H_ZERO_PAGE, dst + 0x123, src); > + report("h_zero_page unaligned dst", rc == H_PARAMETER); > + > + rc = h_page_init(H_COPY_PAGE, dst, src + 0x123); > + report("h_copy_page unaligned src", rc == H_PARAMETER); > +} > + > +struct { > + const char *name; > + void (*func)(int argc, char **argv); > +} hctests[] = { > + { "h_set_sprg0", test_h_set_sprg0 }, > + { "h_page_init", test_h_page_init }, > + { NULL, NULL } > +}; > + > +int main(int argc, char **argv) > +{ > + int all = 0; > + int i; > + > + report_prefix_push("hypercall"); > + > + if (!argc || (argc == 1 && !strcmp(argv[0], "all"))) > + all = 1; > + > + for (i = 0; hctests[i].name != NULL; i++) { > + report_prefix_push(hctests[i].name); > + if (all || strcmp(argv[0], hctests[i].name) == 0) { > + hctests[i].func(argc, argv); > + } > + report_prefix_pop(); > + } > + > + return report_summary(); > +} > diff --git a/powerpc/unittests.cfg b/powerpc/unittests.cfg > index 60f9be8..d858436 100644 > --- a/powerpc/unittests.cfg > +++ b/powerpc/unittests.cfg > @@ -28,3 +28,6 @@ file = selftest.elf > smp = 2 > extra_params = -m 256 -append 'setup smp=2 mem=256' > groups = selftest > + > +[spapr_hcall] > +file = spapr_hcall.elf > -- > 1.8.3.1 > -- David Gibson <dgibson@xxxxxxxxxx> Senior Software Engineer, Virtualization, Red Hat
Attachment:
pgprIAqWbi5Ec.pgp
Description: OpenPGP digital signature