On Wed, 2 Mar 2016 11:07:55 +0100 Laurent Vivier <lvivier@xxxxxxxxxx> wrote: > On 02/03/2016 09:40, Thomas Huth wrote: > > Introduce a test for sPAPR hypercalls, starting with the > > three hypercalls H_SET_SPRG0, H_PAGE_INIT and H_RANDOM. > > > > Signed-off-by: Thomas Huth <thuth@xxxxxxxxxx> > > --- > > v3: > > - Use report_xfail() in H_RANDOM test to report whether the > > h-call is available or not > > > > v2: > > - Rebased to the final version of Andrew's initial ppc64 > > support patches that got merged yesterday > > - Added a test for the H_RANDOM hypercall > > > > Please note that you need the latest QEMU development version > > since some of the hypercalls have only been added recently. > > > > In case somebody wants to review the description of the h-calls, you > > can find them in LoPAPR, chapters 14.5.4.3.1, 14.5.4.3.3 and 14.15.1. > > See: https://members.openpowerfoundation.org/document/dl/469 > > > > lib/powerpc/asm/hcall.h | 3 + > > powerpc/Makefile.common | 5 +- > > powerpc/spapr_hcall.c | 167 ++++++++++++++++++++++++++++++++++++++++++++++++ > > powerpc/unittests.cfg | 3 + > > 4 files changed, 177 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 750c655..f6f9ea8 100644 > > --- a/lib/powerpc/asm/hcall.h > > +++ b/lib/powerpc/asm/hcall.h > > @@ -15,8 +15,11 @@ > > #define H_PRIVILEGE -3 > > #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 > > +#define H_RANDOM 0x300 > > > > #ifndef __ASSEMBLY__ > > /* > > diff --git a/powerpc/Makefile.common b/powerpc/Makefile.common > > index b526668..2ce6494 100644 > > --- a/powerpc/Makefile.common > > +++ b/powerpc/Makefile.common > > @@ -5,7 +5,8 @@ > > # > > > > tests-common = \ > > - $(TEST_DIR)/selftest.elf > > + $(TEST_DIR)/selftest.elf \ > > + $(TEST_DIR)/spapr_hcall.elf > > > > all: $(TEST_DIR)/boot_rom.bin test_cases > > > > @@ -63,3 +64,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..46731e1 > > --- /dev/null > > +++ b/powerpc/spapr_hcall.c > > @@ -0,0 +1,167 @@ > > +/* > > + * 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 (1UL << (63-48)) > > +#define H_COPY_PAGE (1UL << (63-49)) > > + > > +#define mfspr(nr) ({ \ > > + uint64_t ret; \ > > + asm volatile("mfspr %0,%1" : "=r"(ret) : "i"(nr)); \ > > + ret; \ > > +}) > > + > > +#define SPR_SPRG0 0x110 > > + > > +/** > > + * 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) > > +{ > > + uint64_t sprg0, sprg0_orig; > > + int rc; > > + > > + if (argc > 1) > > + report_abort("Unsupported argument: '%s'", argv[1]); > > + > > + sprg0_orig = mfspr(SPR_SPRG0); > > + > > + rc = hcall(H_SET_SPRG0, 0xcafebabedeadbeefULL); > > + sprg0 = mfspr(SPR_SPRG0); > > + report("sprg0 = 0xcafebabedeadbeef", > > + rc == H_SUCCESS && sprg0 == 0xcafebabedeadbeefULL); > > + > > + rc = hcall(H_SET_SPRG0, 0xaaaaaaaa55555555ULL); > > + sprg0 = mfspr(SPR_SPRG0); > > + report("sprg0 = 0xaaaaaaaa55555555", > > + rc == H_SUCCESS && sprg0 == 0xaaaaaaaa55555555ULL); > > + > > + rc = hcall(H_SET_SPRG0, sprg0_orig); > > + sprg0 = mfspr(SPR_SPRG0); > > + report("sprg0 = 0x%llx", > > + rc == H_SUCCESS && sprg0 == sprg0_orig, sprg0_orig); > > +} > > + > > +/** > > + * 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 = hcall(H_PAGE_INIT, H_ZERO_PAGE, dst, src); > > + report("h_zero_page", rc == H_SUCCESS && *(uint64_t*)dst == 0); > > + > > + *(uint64_t*)src = 0xbeefc0dedeadcafeULL; > > + rc = hcall(H_PAGE_INIT, H_COPY_PAGE, dst, src); > > + report("h_copy_page", > > + rc == H_SUCCESS && *(uint64_t*)dst == 0xbeefc0dedeadcafeULL); > > + > > + *(uint64_t*)src = 0x9abcdef012345678ULL; > > + rc = hcall(H_PAGE_INIT, H_COPY_PAGE|H_ZERO_PAGE, dst, src); > > + report("h_copy_page+h_zero_page", > > + rc == H_SUCCESS && *(uint64_t*)dst == 0x9abcdef012345678ULL); > > + > > + rc = hcall(H_PAGE_INIT, H_ZERO_PAGE, dst + 0x123, src); > > + report("h_zero_page unaligned dst", rc == H_PARAMETER); > > + > > + rc = hcall(H_PAGE_INIT, H_COPY_PAGE, dst, src + 0x123); > > + report("h_copy_page unaligned src", rc == H_PARAMETER); > > +} > > + > > +static int h_random(uint64_t *val) > > +{ > > + register uint64_t r3 asm("r3") = H_RANDOM; > > + register uint64_t r4 asm("r4"); > > + > > + asm volatile (" sc 1 " : "+r"(r3), "=r"(r4) : "r"(r3)); > > as you use "+r" with r3 in the output operands field, I think you don't > have to declare it in the input operands field. More importantly, I think a hypercall is allowed to clobber any of the volatile registers (r0 & r3..r12), so they probably need to be declared in the clobbers as well. -- David Gibson <dgibson@xxxxxxxxxx> Senior Software Engineer, Virtualization, Red Hat
Attachment:
pgp3crdrdrr9B.pgp
Description: OpenPGP digital signature