From patchwork Wed Mar 28 07:39:37 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Huth X-Patchwork-Id: 10312467 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 3EC4D60467 for ; Wed, 28 Mar 2018 07:40:12 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2F39828A0F for ; Wed, 28 Mar 2018 07:40:12 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 241412940F; Wed, 28 Mar 2018 07:40:12 +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 6FED328A0F for ; Wed, 28 Mar 2018 07:40:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753475AbeC1Hjv (ORCPT ); Wed, 28 Mar 2018 03:39:51 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:53918 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1753356AbeC1Hju (ORCPT ); Wed, 28 Mar 2018 03:39:50 -0400 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 83B0681A813C; Wed, 28 Mar 2018 07:39:49 +0000 (UTC) Received: from thh440s.str.redhat.com (dhcp-192-189.str.redhat.com [10.33.192.189]) by smtp.corp.redhat.com (Postfix) with ESMTP id A4D8510B2B38; Wed, 28 Mar 2018 07:39:48 +0000 (UTC) From: Thomas Huth To: Paolo Bonzini , =?UTF-8?q?Radim=20Kr=C4=8Dm=C3=A1=C5=99?= Cc: kvm@vger.kernel.org, David Hildenbrand , Janosch Frank Subject: [kvm-unit-tests PULL 1/8] s390x: Add sthyi tests Date: Wed, 28 Mar 2018 09:39:37 +0200 Message-Id: <1522222784-7709-2-git-send-email-thuth@redhat.com> In-Reply-To: <1522222784-7709-1-git-send-email-thuth@redhat.com> References: <1522222784-7709-1-git-send-email-thuth@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Wed, 28 Mar 2018 07:39:49 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Wed, 28 Mar 2018 07:39:49 +0000 (UTC) for IP:'10.11.54.3' DOMAIN:'int-mx03.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'thuth@redhat.com' RCPT:'' Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Janosch Frank The Store Hypervisor Information (STHYI) instruction provides system information like available CPU resources on each system level. The instruction is fully emulated by the hypervisor. Signed-off-by: Janosch Frank Reviewed-by: Thomas Huth Signed-off-by: Thomas Huth --- s390x/Makefile | 1 + s390x/sthyi.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++ s390x/sthyi.h | 131 ++++++++++++++++++++++++++++++++++++++++ s390x/unittests.cfg | 3 + 4 files changed, 304 insertions(+) create mode 100644 s390x/sthyi.c create mode 100644 s390x/sthyi.h diff --git a/s390x/Makefile b/s390x/Makefile index fe92f65..f68d8a7 100644 --- a/s390x/Makefile +++ b/s390x/Makefile @@ -2,6 +2,7 @@ tests = $(TEST_DIR)/selftest.elf tests += $(TEST_DIR)/intercept.elf tests += $(TEST_DIR)/emulator.elf tests += $(TEST_DIR)/sieve.elf +tests += $(TEST_DIR)/sthyi.elf all: directories test_cases diff --git a/s390x/sthyi.c b/s390x/sthyi.c new file mode 100644 index 0000000..0b1b4ec --- /dev/null +++ b/s390x/sthyi.c @@ -0,0 +1,169 @@ +/* + * Tests exceptions and data validity for the emulated sthyi + * instruction. + * + * Copyright 2018 IBM Corp. + * + * Authors: + * Janosch Frank + * + * 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 +#include +#include +#include + +#include "sthyi.h" + +static uint8_t pagebuf[PAGE_SIZE] __attribute__((aligned(PAGE_SIZE))); +static char null_buf[32] = {}; + +static inline int sthyi(uint64_t vaddr, uint64_t fcode, uint64_t *rc, + unsigned int r1, unsigned int r2) +{ + register uint64_t code asm("0") = fcode; + register uint64_t addr asm("2") = vaddr; + register uint64_t rc3 asm("3") = 0; + int cc = 0; + + asm volatile(".insn rre,0xB2560000,%[r1],%[r2]\n" + "ipm %[cc]\n" + "srl %[cc],28\n" + : [cc] "=d" (cc) + : [code] "d" (code), [addr] "a" (addr), [r1] "i" (r1), + [r2] "i" (r2) + : "memory", "cc", "r3"); + if (rc) + *rc = rc3; + return cc; +} + +static void test_exception_addr(void) +{ + report_prefix_push("Illegal address check"); + expect_pgm_int(); + sthyi(42042, 0, NULL, 0, 2); + check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); + report_prefix_pop(); +} + +static void test_exception_reg_odd(void) +{ + report_prefix_push("Register check odd"); + expect_pgm_int(); + sthyi((uint64_t)pagebuf, 0, NULL, 1, 2); + check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); + expect_pgm_int(); + sthyi((uint64_t)pagebuf, 0, NULL, 0, 3); + check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); + report_prefix_pop(); +} + +static void test_exception_reg_equal(void) +{ + report_prefix_push("Register check equal"); + expect_pgm_int(); + sthyi((uint64_t)pagebuf, 0, NULL, 0, 0); + check_pgm_int_code(PGM_INT_CODE_SPECIFICATION); + report_prefix_pop(); +} + +static void test_function_code(uint64_t addr) +{ + uint64_t urc = 0; + int cc = sthyi((uint64_t)pagebuf, 42, &urc, 0, 2); + + report("Ill. fcode", cc == 3 && urc == CODE_UNSUPP); +} + +static void test_fcode0_hdr(struct sthyi_hdr_sctn *hdr) +{ + report("HDR length", (hdr->INFHDLN >= sizeof(*hdr) + && !(hdr->INFHDLN % 8))); + report("MACH sctn length", (hdr->INFMLEN >= sizeof(struct sthyi_mach_sctn) + && !(hdr->INFMLEN % 8))); + report("PAR sctn length", (hdr->INFPLEN >= sizeof(struct sthyi_par_sctn) + && !(hdr->INFPLEN % 8))); + + report("MACH offset", hdr->INFMOFF >= hdr->INFHDLN); + report("PAR offset", hdr->INFPOFF >= hdr->INFHDLN); +} + +static void test_fcode0_mach(struct sthyi_mach_sctn *mach) +{ + int sum = mach->INFMSCPS + mach->INFMDCPS + mach->INFMSIFL + mach->INFMDIFL; + + if (mach->INFMVAL1 & MACH_ID_VLD) { + report("MACH type", memcmp(mach->INFMTYPE, null_buf, sizeof(mach->INFMTYPE))); + report("MACH manu", memcmp(mach->INFMMANU, null_buf, sizeof(mach->INFMMANU))); + report("MACH seq", memcmp(mach->INFMSEQ, null_buf, sizeof(mach->INFMSEQ))); + report("MACH plant", memcmp(mach->INFMPMAN, null_buf, sizeof(mach->INFMPMAN))); + } + + if (mach->INFMVAL1 & MACH_NAME_VLD) + report("MACH name", memcmp(mach->INFMNAME, null_buf, + sizeof(mach->INFMNAME))); + + if (mach->INFMVAL1 & MACH_CNT_VLD) + report("MACH core counts", sum); +} + +static void test_fcode0_par(struct sthyi_par_sctn *par) +{ + int sum = par->INFPSCPS + par->INFPDCPS + par->INFPSIFL + par->INFPDIFL; + + if (par->INFPVAL1 & PART_CNT_VLD) + report("PAR core counts", sum); + + if (par->INFPVAL1 & PART_STSI_SUC) { + report("PAR number", par->INFPPNUM); + report("PAR name", memcmp(par->INFPPNAM, null_buf, sizeof(par->INFPPNAM))); + } +} + +static void test_fcode0(void) +{ + struct sthyi_hdr_sctn *hdr; + struct sthyi_mach_sctn *mach; + struct sthyi_par_sctn *par; + + /* Zero destination memory. */ + memset(pagebuf, 0, PAGE_SIZE); + + sthyi((uint64_t)pagebuf, 0, NULL, 0, 2); + hdr = (void *)pagebuf; + mach = (void *)pagebuf + hdr->INFMOFF; + par = (void *)pagebuf + hdr->INFPOFF; + + test_fcode0_hdr(hdr); + test_fcode0_mach(mach); + test_fcode0_par(par); +} + +int main(void) +{ + bool has_sthyi = test_facility(74); + + report_prefix_push("sthyi"); + + /* Test for availability */ + report_xfail("STHYI available", !has_sthyi, has_sthyi); + if (!has_sthyi) + goto done; + + /* Test register/argument checking. */ + test_exception_addr(); + test_exception_reg_odd(); + test_exception_reg_equal(); + test_function_code((uint64_t) pagebuf); + + /* Test function code 0 - CP and IFL Capacity Information */ + test_fcode0(); + +done: + report_prefix_pop(); + return report_summary(); +} diff --git a/s390x/sthyi.h b/s390x/sthyi.h new file mode 100644 index 0000000..06f757f --- /dev/null +++ b/s390x/sthyi.h @@ -0,0 +1,131 @@ +/* + * STHYI related flags and structure definitions. + * + * Copyright 2018 IBM Corp. + * + * Authors: + * Janosch Frank + * + * 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 _STHYI_H_ +#define _STHYI_H_ + +#include + +enum sthyi_rtn_code { + CODE_UNSUPP = 0x04, /* with cc = 3 */ + CODE_SUCCES = 0x00, /* with cc = 0 */ +}; + +enum sthyi_hdr_flags { + HDR_PERF_UNAV = 0x80, + HDR_STSI_UNAV = 0x40, + HDR_STACK_INCM = 0x20, + HDR_NOT_LPAR = 0x10, +}; + +enum sthyi_mach_validity { + MACH_CNT_VLD = 0x80, + MACH_ID_VLD = 0x40, + MACH_NAME_VLD = 0x20, +}; + +enum sthyi_par_flag { + PART_MT_EN = 0x80, +}; + +enum sthyi_par_validity { + PART_CNT_VLD = 0x80, + PART_WGHT_CAP = 0x40, + PART_ABS_CAP = 0x20, + PART_STSI_SUC = 0x10, + PART_GRP_VLD = 0x08, +}; + +struct sthyi_hdr_sctn { + uint8_t INFHFLG1; + uint8_t INFHFLG2; /* reserved */ + uint8_t INFHVAL1; /* reserved */ + uint8_t INFHVAL2; /* reserved */ + uint8_t reserved[3]; + uint8_t INFHYGCT; + uint16_t INFHTOTL; + uint16_t INFHDLN; + uint16_t INFMOFF; + uint16_t INFMLEN; + uint16_t INFPOFF; + uint16_t INFPLEN; + uint16_t INFHOFF1; + uint16_t INFHLEN1; + uint16_t INFGOFF1; + uint16_t INFGLEN1; + uint16_t INFHOFF2; + uint16_t INFHLEN2; + uint16_t INFGOFF2; + uint16_t INFGLEN2; + uint16_t INFHOFF3; + uint16_t INFHLEN3; + uint16_t INFGOFF3; + uint16_t INFGLEN3; + uint8_t reserved2[4]; +} __attribute__((packed)); + +struct sthyi_mach_sctn { + uint8_t INFMFLG1; /* reserved */ + uint8_t INFMFLG2; /* reserved */ + uint8_t INFMVAL1; + uint8_t INFMVAL2; /* reserved */ + uint16_t INFMSCPS; + uint16_t INFMDCPS; + uint16_t INFMSIFL; + uint16_t INFMDIFL; + char INFMNAME[8]; + char INFMTYPE[4]; + char INFMMANU[16]; + char INFMSEQ[16]; + char INFMPMAN[4]; + uint8_t reserved[4]; +} __attribute__((packed)); + +struct sthyi_par_sctn { + uint8_t INFPFLG1; + uint8_t INFPFLG2; /* reserved */ + uint8_t INFPVAL1; + uint8_t INFPVAL2; /* reserved */ + uint16_t INFPPNUM; + uint16_t INFPSCPS; + uint16_t INFPDCPS; + uint16_t INFPSIFL; + uint16_t INFPDIFL; + uint16_t reserved; + char INFPPNAM[8]; + uint32_t INFPWBCP; + uint32_t INFPABCP; + uint32_t INFPWBIF; + uint32_t INFPABIF; +} __attribute__((packed)); + +struct sthyi_par_sctn_ext { + uint8_t INFPFLG1; + uint8_t INFPFLG2; /* reserved */ + uint8_t INFPVAL1; + uint8_t INFPVAL2; /* reserved */ + uint16_t INFPPNUM; + uint16_t INFPSCPS; + uint16_t INFPDCPS; + uint16_t INFPSIFL; + uint16_t INFPDIFL; + uint16_t reserved; + char INFPPNAM[8]; + uint32_t INFPWBCP; + uint32_t INFPABCP; + uint32_t INFPWBIF; + uint32_t INFPABIF; + char INFPLGNM[8]; + uint32_t INFPLGCP; + uint32_t INFPLGIF; +} __attribute__((packed)); + +#endif diff --git a/s390x/unittests.cfg b/s390x/unittests.cfg index 7506d06..258189e 100644 --- a/s390x/unittests.cfg +++ b/s390x/unittests.cfg @@ -34,3 +34,6 @@ file = sieve.elf groups = selftest # can take fairly long when KVM is nested inside z/VM timeout = 600 + +[sthyi] +file = sthyi.elf