From patchwork Wed Mar 2 08:40:43 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Huth X-Patchwork-Id: 590886 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id B02E6140B0D for ; Wed, 2 Mar 2016 19:40:48 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751305AbcCBIkr (ORCPT ); Wed, 2 Mar 2016 03:40:47 -0500 Received: from mx1.redhat.com ([209.132.183.28]:44259 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751167AbcCBIkq (ORCPT ); Wed, 2 Mar 2016 03:40:46 -0500 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) by mx1.redhat.com (Postfix) with ESMTPS id 720DAD47A5; Wed, 2 Mar 2016 08:40:46 +0000 (UTC) Received: from thh440s.fritz.box (vpn1-7-238.ams2.redhat.com [10.36.7.238]) by int-mx14.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u228eiDt004405; Wed, 2 Mar 2016 03:40:44 -0500 From: Thomas Huth To: kvm@vger.kernel.org, kvm-ppc@vger.kernel.org, drjones@redhat.com Cc: dgibson@redhat.com, lvivier@redhat.com Subject: [PATCH v3] powerpc: Add tests for sPAPR h-calls Date: Wed, 2 Mar 2016 09:40:43 +0100 Message-Id: <1456908043-11184-1-git-send-email-thuth@redhat.com> X-Scanned-By: MIMEDefang 2.68 on 10.5.11.27 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Wed, 02 Mar 2016 08:40:46 +0000 (UTC) Sender: kvm-ppc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm-ppc@vger.kernel.org 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 Reviewed-by: Laurent Vivier --- 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 +#include +#include +#include + +#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)); + *val = r4; + + return r3; +} + +/** + * Test H_RANDOM by calling it a couple of times to check whether all bit + * positions really toggle (there should be no "stuck" bits in the output) + */ +static void test_h_random(int argc, char **argv) +{ + uint64_t rval, val0, val1; + int rc, i; + + if (argc > 1) + report_abort("Unsupported argument: '%s'", argv[1]); + + /* H_RANDOM is optional - so check for sane return values first */ + rc = h_random(&rval); + report_xfail("h-call available", rc == H_FUNCTION, rc == H_SUCCESS); + if (rc != H_SUCCESS) + return; + + val0 = 0ULL; + val1 = ~0ULL; + + i = 100; + do { + rc = h_random(&rval); + if (rc != H_SUCCESS) + break; + val0 |= rval; + val1 &= rval; + } while (i-- > 0 && (val0 != ~0ULL || val1 != 0ULL)); + + report("no stuck bits", rc == H_SUCCESS && val0 == ~0ULL && val1 == 0); +} + +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 }, + { "h_random", test_h_random }, + { 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