* [kvm-unit-tests PATCH v1 0/5] s390x: IPM/SPM and MSA tests
@ 2017-09-19 14:50 David Hildenbrand
2017-09-19 14:50 ` [kvm-unit-tests PATCH v1 1/5] s390x: add a test case for the ipm + spm instructions David Hildenbrand
` (5 more replies)
0 siblings, 6 replies; 7+ messages in thread
From: David Hildenbrand @ 2017-09-19 14:50 UTC (permalink / raw)
To: kvm
Cc: Paolo Bonzini, Radim Krčmář, david, Thomas Huth,
Cornelia Huck, Christian Borntraeger
Developed while working on:
https://lists.gnu.org/archive/html/qemu-devel/2017-09/msg05133.html
Only the basics for MSA instructions are tested (basically everything QEMU
also implements), but no real en/decryption.
All tests seem to pass under KVM.
For TCG, only the usual low address protection tests fail.
To run under TCG, the feature have to be enabled explicitly for now:
./s390x-run s390x/emulator.elf \
-cpu qemu,msa-base=on,msa3-base=on,msa4-base=on,msa5-base=on,stfle=on
David Hildenbrand (5):
s390x: add a test case for the ipm + spm instructions
s390x: add cpacf.h from Linux
s390x: make sure cpacf.h can be used
s390x: query and store STFL(E) facilitites
s390x: test for various MSA instructions
lib/s390x/asm/cpacf.h | 472 +++++++++++++++++++++++++++++++++++++++++++++++
lib/s390x/asm/facility.h | 48 +++++
lib/s390x/io.c | 3 +
s390x/Makefile | 1 +
s390x/emulator.c | 292 +++++++++++++++++++++++++++++
s390x/unittests.cfg | 3 +
6 files changed, 819 insertions(+)
create mode 100644 lib/s390x/asm/cpacf.h
create mode 100644 lib/s390x/asm/facility.h
create mode 100644 s390x/emulator.c
--
2.13.5
^ permalink raw reply [flat|nested] 7+ messages in thread
* [kvm-unit-tests PATCH v1 1/5] s390x: add a test case for the ipm + spm instructions
2017-09-19 14:50 [kvm-unit-tests PATCH v1 0/5] s390x: IPM/SPM and MSA tests David Hildenbrand
@ 2017-09-19 14:50 ` David Hildenbrand
2017-09-19 14:50 ` [kvm-unit-tests PATCH v1 2/5] s390x: add cpacf.h from Linux David Hildenbrand
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: David Hildenbrand @ 2017-09-19 14:50 UTC (permalink / raw)
To: kvm
Cc: Paolo Bonzini, Radim Krčmář, david, Thomas Huth,
Cornelia Huck, Christian Borntraeger
Add a new file "emulator.c" and keep running tests simple for now
(no support for multiple iterations and such stuff). We will get this
for free once we switch to a new, general API for running/defining
tests.
Signed-off-by: David Hildenbrand <david@redhat.com>
---
s390x/Makefile | 1 +
s390x/emulator.c | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++
s390x/unittests.cfg | 3 +++
3 files changed, 69 insertions(+)
create mode 100644 s390x/emulator.c
diff --git a/s390x/Makefile b/s390x/Makefile
index bc099da..573cba2 100644
--- a/s390x/Makefile
+++ b/s390x/Makefile
@@ -1,5 +1,6 @@
tests = $(TEST_DIR)/selftest.elf
tests += $(TEST_DIR)/intercept.elf
+tests += $(TEST_DIR)/emulator.elf
all: directories test_cases
diff --git a/s390x/emulator.c b/s390x/emulator.c
new file mode 100644
index 0000000..7854498
--- /dev/null
+++ b/s390x/emulator.c
@@ -0,0 +1,65 @@
+/*
+ * Emulator tests - for s390x CPU instructions that are usually interpreted
+ * by the hardware
+ *
+ * Copyright (c) 2017 Red Hat Inc
+ *
+ * Authors:
+ * David Hildenbrand <david@redhat.com>
+ *
+ * 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>
+
+static inline void __test_spm_ipm(uint8_t cc, uint8_t key)
+{
+ uint64_t in = (cc << 28) | (key << 24);
+ uint64_t out = ~0ULL;
+
+ report_prefix_pushf("cc=%d,key=%x", cc, key);
+
+ asm volatile ("spm %1\n"
+ "ipm %0\n"
+ : "+r"(out) : "r"(in) : "cc");
+
+ report("bit 32 and 33 set to zero", !(out & 0xc0000000UL));
+ report("bit 0-31, 40-63 unchanged",
+ (out & ~0xff000000ULL) == ~0xff000000ULL);
+ report("cc and key applied", !((in ^ out) & 0x3f000000UL));
+
+ report_prefix_pop();
+}
+
+/* Test the SET PROGRAM PARAMETER and INSERT PROGRAM PARAMETER instruction */
+static void test_spm_ipm(void)
+{
+ __test_spm_ipm(0, 0xf);
+ __test_spm_ipm(1, 0x9);
+ __test_spm_ipm(2, 0x5);
+ __test_spm_ipm(3, 0x3);
+ __test_spm_ipm(0, 0);
+}
+
+static struct {
+ const char *name;
+ void (*func)(void);
+} tests[] = {
+ { "spm/ipm", test_spm_ipm },
+ { NULL, NULL }
+};
+
+int main(int argc, char**argv)
+{
+ int i;
+
+ report_prefix_push("emulator");
+ for (i = 0; tests[i].name; i++) {
+ report_prefix_push(tests[i].name);
+ tests[i].func();
+ report_prefix_pop();
+ }
+ report_prefix_pop();
+
+ return report_summary();
+}
diff --git a/s390x/unittests.cfg b/s390x/unittests.cfg
index 3b6b892..1343a19 100644
--- a/s390x/unittests.cfg
+++ b/s390x/unittests.cfg
@@ -25,3 +25,6 @@ extra_params = -append 'test 123'
[intercept]
file = intercept.elf
+
+[emulator]
+file = emulator.elf
--
2.13.5
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [kvm-unit-tests PATCH v1 2/5] s390x: add cpacf.h from Linux
2017-09-19 14:50 [kvm-unit-tests PATCH v1 0/5] s390x: IPM/SPM and MSA tests David Hildenbrand
2017-09-19 14:50 ` [kvm-unit-tests PATCH v1 1/5] s390x: add a test case for the ipm + spm instructions David Hildenbrand
@ 2017-09-19 14:50 ` David Hildenbrand
2017-09-19 14:50 ` [kvm-unit-tests PATCH v1 3/5] s390x: make sure cpacf.h can be used David Hildenbrand
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: David Hildenbrand @ 2017-09-19 14:50 UTC (permalink / raw)
To: kvm
Cc: Paolo Bonzini, Radim Krčmář, david, Thomas Huth,
Cornelia Huck, Christian Borntraeger
Add arch/s390/include/asm/cpacf.h from Linux v4.13.
Signed-off-by: David Hildenbrand <david@redhat.com>
---
lib/s390x/asm/cpacf.h | 472 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 472 insertions(+)
create mode 100644 lib/s390x/asm/cpacf.h
diff --git a/lib/s390x/asm/cpacf.h b/lib/s390x/asm/cpacf.h
new file mode 100644
index 0000000..e06f255
--- /dev/null
+++ b/lib/s390x/asm/cpacf.h
@@ -0,0 +1,472 @@
+/*
+ * CP Assist for Cryptographic Functions (CPACF)
+ *
+ * Copyright IBM Corp. 2003, 2016
+ * Author(s): Thomas Spatzier
+ * Jan Glauber
+ * Harald Freudenberger (freude@de.ibm.com)
+ * Martin Schwidefsky <schwidefsky@de.ibm.com>
+ */
+#ifndef _ASM_S390_CPACF_H
+#define _ASM_S390_CPACF_H
+
+#include <asm/facility.h>
+
+/*
+ * Instruction opcodes for the CPACF instructions
+ */
+#define CPACF_KMAC 0xb91e /* MSA */
+#define CPACF_KM 0xb92e /* MSA */
+#define CPACF_KMC 0xb92f /* MSA */
+#define CPACF_KIMD 0xb93e /* MSA */
+#define CPACF_KLMD 0xb93f /* MSA */
+#define CPACF_PCKMO 0xb928 /* MSA3 */
+#define CPACF_KMF 0xb92a /* MSA4 */
+#define CPACF_KMO 0xb92b /* MSA4 */
+#define CPACF_PCC 0xb92c /* MSA4 */
+#define CPACF_KMCTR 0xb92d /* MSA4 */
+#define CPACF_PRNO 0xb93c /* MSA5 */
+#define CPACF_KMA 0xb929 /* MSA8 */
+
+/*
+ * En/decryption modifier bits
+ */
+#define CPACF_ENCRYPT 0x00
+#define CPACF_DECRYPT 0x80
+
+/*
+ * Function codes for the KM (CIPHER MESSAGE) instruction
+ */
+#define CPACF_KM_QUERY 0x00
+#define CPACF_KM_DEA 0x01
+#define CPACF_KM_TDEA_128 0x02
+#define CPACF_KM_TDEA_192 0x03
+#define CPACF_KM_AES_128 0x12
+#define CPACF_KM_AES_192 0x13
+#define CPACF_KM_AES_256 0x14
+#define CPACF_KM_PAES_128 0x1a
+#define CPACF_KM_PAES_192 0x1b
+#define CPACF_KM_PAES_256 0x1c
+#define CPACF_KM_XTS_128 0x32
+#define CPACF_KM_XTS_256 0x34
+#define CPACF_KM_PXTS_128 0x3a
+#define CPACF_KM_PXTS_256 0x3c
+
+/*
+ * Function codes for the KMC (CIPHER MESSAGE WITH CHAINING)
+ * instruction
+ */
+#define CPACF_KMC_QUERY 0x00
+#define CPACF_KMC_DEA 0x01
+#define CPACF_KMC_TDEA_128 0x02
+#define CPACF_KMC_TDEA_192 0x03
+#define CPACF_KMC_AES_128 0x12
+#define CPACF_KMC_AES_192 0x13
+#define CPACF_KMC_AES_256 0x14
+#define CPACF_KMC_PAES_128 0x1a
+#define CPACF_KMC_PAES_192 0x1b
+#define CPACF_KMC_PAES_256 0x1c
+#define CPACF_KMC_PRNG 0x43
+
+/*
+ * Function codes for the KMCTR (CIPHER MESSAGE WITH COUNTER)
+ * instruction
+ */
+#define CPACF_KMCTR_QUERY 0x00
+#define CPACF_KMCTR_DEA 0x01
+#define CPACF_KMCTR_TDEA_128 0x02
+#define CPACF_KMCTR_TDEA_192 0x03
+#define CPACF_KMCTR_AES_128 0x12
+#define CPACF_KMCTR_AES_192 0x13
+#define CPACF_KMCTR_AES_256 0x14
+#define CPACF_KMCTR_PAES_128 0x1a
+#define CPACF_KMCTR_PAES_192 0x1b
+#define CPACF_KMCTR_PAES_256 0x1c
+
+/*
+ * Function codes for the KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST)
+ * instruction
+ */
+#define CPACF_KIMD_QUERY 0x00
+#define CPACF_KIMD_SHA_1 0x01
+#define CPACF_KIMD_SHA_256 0x02
+#define CPACF_KIMD_SHA_512 0x03
+#define CPACF_KIMD_GHASH 0x41
+
+/*
+ * Function codes for the KLMD (COMPUTE LAST MESSAGE DIGEST)
+ * instruction
+ */
+#define CPACF_KLMD_QUERY 0x00
+#define CPACF_KLMD_SHA_1 0x01
+#define CPACF_KLMD_SHA_256 0x02
+#define CPACF_KLMD_SHA_512 0x03
+
+/*
+ * function codes for the KMAC (COMPUTE MESSAGE AUTHENTICATION CODE)
+ * instruction
+ */
+#define CPACF_KMAC_QUERY 0x00
+#define CPACF_KMAC_DEA 0x01
+#define CPACF_KMAC_TDEA_128 0x02
+#define CPACF_KMAC_TDEA_192 0x03
+
+/*
+ * Function codes for the PCKMO (PERFORM CRYPTOGRAPHIC KEY MANAGEMENT)
+ * instruction
+ */
+#define CPACF_PCKMO_QUERY 0x00
+#define CPACF_PCKMO_ENC_DES_KEY 0x01
+#define CPACF_PCKMO_ENC_TDES_128_KEY 0x02
+#define CPACF_PCKMO_ENC_TDES_192_KEY 0x03
+#define CPACF_PCKMO_ENC_AES_128_KEY 0x12
+#define CPACF_PCKMO_ENC_AES_192_KEY 0x13
+#define CPACF_PCKMO_ENC_AES_256_KEY 0x14
+
+/*
+ * Function codes for the PRNO (PERFORM RANDOM NUMBER OPERATION)
+ * instruction
+ */
+#define CPACF_PRNO_QUERY 0x00
+#define CPACF_PRNO_SHA512_DRNG_GEN 0x03
+#define CPACF_PRNO_SHA512_DRNG_SEED 0x83
+#define CPACF_PRNO_TRNG_Q_R2C_RATIO 0x70
+#define CPACF_PRNO_TRNG 0x72
+
+typedef struct { unsigned char bytes[16]; } cpacf_mask_t;
+
+/**
+ * cpacf_query() - check if a specific CPACF function is available
+ * @opcode: the opcode of the crypto instruction
+ * @func: the function code to test for
+ *
+ * Executes the query function for the given crypto instruction @opcode
+ * and checks if @func is available
+ *
+ * Returns 1 if @func is available for @opcode, 0 otherwise
+ */
+static inline void __cpacf_query(unsigned int opcode, cpacf_mask_t *mask)
+{
+ register unsigned long r0 asm("0") = 0; /* query function */
+ register unsigned long r1 asm("1") = (unsigned long) mask;
+
+ asm volatile(
+ " spm 0\n" /* pckmo doesn't change the cc */
+ /* Parameter regs are ignored, but must be nonzero and unique */
+ "0: .insn rrf,%[opc] << 16,2,4,6,0\n"
+ " brc 1,0b\n" /* handle partial completion */
+ : "=m" (*mask)
+ : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (opcode)
+ : "cc");
+}
+
+static inline int __cpacf_check_opcode(unsigned int opcode)
+{
+ switch (opcode) {
+ case CPACF_KMAC:
+ case CPACF_KM:
+ case CPACF_KMC:
+ case CPACF_KIMD:
+ case CPACF_KLMD:
+ return test_facility(17); /* check for MSA */
+ case CPACF_PCKMO:
+ return test_facility(76); /* check for MSA3 */
+ case CPACF_KMF:
+ case CPACF_KMO:
+ case CPACF_PCC:
+ case CPACF_KMCTR:
+ return test_facility(77); /* check for MSA4 */
+ case CPACF_PRNO:
+ return test_facility(57); /* check for MSA5 */
+ default:
+ BUG();
+ }
+}
+
+static inline int cpacf_query(unsigned int opcode, cpacf_mask_t *mask)
+{
+ if (__cpacf_check_opcode(opcode)) {
+ __cpacf_query(opcode, mask);
+ return 1;
+ }
+ memset(mask, 0, sizeof(*mask));
+ return 0;
+}
+
+static inline int cpacf_test_func(cpacf_mask_t *mask, unsigned int func)
+{
+ return (mask->bytes[func >> 3] & (0x80 >> (func & 7))) != 0;
+}
+
+static inline int cpacf_query_func(unsigned int opcode, unsigned int func)
+{
+ cpacf_mask_t mask;
+
+ if (cpacf_query(opcode, &mask))
+ return cpacf_test_func(&mask, func);
+ return 0;
+}
+
+/**
+ * cpacf_km() - executes the KM (CIPHER MESSAGE) instruction
+ * @func: the function code passed to KM; see CPACF_KM_xxx defines
+ * @param: address of parameter block; see POP for details on each func
+ * @dest: address of destination memory area
+ * @src: address of source memory area
+ * @src_len: length of src operand in bytes
+ *
+ * Returns 0 for the query func, number of processed bytes for
+ * encryption/decryption funcs
+ */
+static inline int cpacf_km(unsigned long func, void *param,
+ u8 *dest, const u8 *src, long src_len)
+{
+ register unsigned long r0 asm("0") = (unsigned long) func;
+ register unsigned long r1 asm("1") = (unsigned long) param;
+ register unsigned long r2 asm("2") = (unsigned long) src;
+ register unsigned long r3 asm("3") = (unsigned long) src_len;
+ register unsigned long r4 asm("4") = (unsigned long) dest;
+
+ asm volatile(
+ "0: .insn rre,%[opc] << 16,%[dst],%[src]\n"
+ " brc 1,0b\n" /* handle partial completion */
+ : [src] "+a" (r2), [len] "+d" (r3), [dst] "+a" (r4)
+ : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_KM)
+ : "cc", "memory");
+
+ return src_len - r3;
+}
+
+/**
+ * cpacf_kmc() - executes the KMC (CIPHER MESSAGE WITH CHAINING) instruction
+ * @func: the function code passed to KM; see CPACF_KMC_xxx defines
+ * @param: address of parameter block; see POP for details on each func
+ * @dest: address of destination memory area
+ * @src: address of source memory area
+ * @src_len: length of src operand in bytes
+ *
+ * Returns 0 for the query func, number of processed bytes for
+ * encryption/decryption funcs
+ */
+static inline int cpacf_kmc(unsigned long func, void *param,
+ u8 *dest, const u8 *src, long src_len)
+{
+ register unsigned long r0 asm("0") = (unsigned long) func;
+ register unsigned long r1 asm("1") = (unsigned long) param;
+ register unsigned long r2 asm("2") = (unsigned long) src;
+ register unsigned long r3 asm("3") = (unsigned long) src_len;
+ register unsigned long r4 asm("4") = (unsigned long) dest;
+
+ asm volatile(
+ "0: .insn rre,%[opc] << 16,%[dst],%[src]\n"
+ " brc 1,0b\n" /* handle partial completion */
+ : [src] "+a" (r2), [len] "+d" (r3), [dst] "+a" (r4)
+ : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_KMC)
+ : "cc", "memory");
+
+ return src_len - r3;
+}
+
+/**
+ * cpacf_kimd() - executes the KIMD (COMPUTE INTERMEDIATE MESSAGE DIGEST)
+ * instruction
+ * @func: the function code passed to KM; see CPACF_KIMD_xxx defines
+ * @param: address of parameter block; see POP for details on each func
+ * @src: address of source memory area
+ * @src_len: length of src operand in bytes
+ */
+static inline void cpacf_kimd(unsigned long func, void *param,
+ const u8 *src, long src_len)
+{
+ register unsigned long r0 asm("0") = (unsigned long) func;
+ register unsigned long r1 asm("1") = (unsigned long) param;
+ register unsigned long r2 asm("2") = (unsigned long) src;
+ register unsigned long r3 asm("3") = (unsigned long) src_len;
+
+ asm volatile(
+ "0: .insn rre,%[opc] << 16,0,%[src]\n"
+ " brc 1,0b\n" /* handle partial completion */
+ : [src] "+a" (r2), [len] "+d" (r3)
+ : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_KIMD)
+ : "cc", "memory");
+}
+
+/**
+ * cpacf_klmd() - executes the KLMD (COMPUTE LAST MESSAGE DIGEST) instruction
+ * @func: the function code passed to KM; see CPACF_KLMD_xxx defines
+ * @param: address of parameter block; see POP for details on each func
+ * @src: address of source memory area
+ * @src_len: length of src operand in bytes
+ */
+static inline void cpacf_klmd(unsigned long func, void *param,
+ const u8 *src, long src_len)
+{
+ register unsigned long r0 asm("0") = (unsigned long) func;
+ register unsigned long r1 asm("1") = (unsigned long) param;
+ register unsigned long r2 asm("2") = (unsigned long) src;
+ register unsigned long r3 asm("3") = (unsigned long) src_len;
+
+ asm volatile(
+ "0: .insn rre,%[opc] << 16,0,%[src]\n"
+ " brc 1,0b\n" /* handle partial completion */
+ : [src] "+a" (r2), [len] "+d" (r3)
+ : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_KLMD)
+ : "cc", "memory");
+}
+
+/**
+ * cpacf_kmac() - executes the KMAC (COMPUTE MESSAGE AUTHENTICATION CODE)
+ * instruction
+ * @func: the function code passed to KM; see CPACF_KMAC_xxx defines
+ * @param: address of parameter block; see POP for details on each func
+ * @src: address of source memory area
+ * @src_len: length of src operand in bytes
+ *
+ * Returns 0 for the query func, number of processed bytes for digest funcs
+ */
+static inline int cpacf_kmac(unsigned long func, void *param,
+ const u8 *src, long src_len)
+{
+ register unsigned long r0 asm("0") = (unsigned long) func;
+ register unsigned long r1 asm("1") = (unsigned long) param;
+ register unsigned long r2 asm("2") = (unsigned long) src;
+ register unsigned long r3 asm("3") = (unsigned long) src_len;
+
+ asm volatile(
+ "0: .insn rre,%[opc] << 16,0,%[src]\n"
+ " brc 1,0b\n" /* handle partial completion */
+ : [src] "+a" (r2), [len] "+d" (r3)
+ : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_KMAC)
+ : "cc", "memory");
+
+ return src_len - r3;
+}
+
+/**
+ * cpacf_kmctr() - executes the KMCTR (CIPHER MESSAGE WITH COUNTER) instruction
+ * @func: the function code passed to KMCTR; see CPACF_KMCTR_xxx defines
+ * @param: address of parameter block; see POP for details on each func
+ * @dest: address of destination memory area
+ * @src: address of source memory area
+ * @src_len: length of src operand in bytes
+ * @counter: address of counter value
+ *
+ * Returns 0 for the query func, number of processed bytes for
+ * encryption/decryption funcs
+ */
+static inline int cpacf_kmctr(unsigned long func, void *param, u8 *dest,
+ const u8 *src, long src_len, u8 *counter)
+{
+ register unsigned long r0 asm("0") = (unsigned long) func;
+ register unsigned long r1 asm("1") = (unsigned long) param;
+ register unsigned long r2 asm("2") = (unsigned long) src;
+ register unsigned long r3 asm("3") = (unsigned long) src_len;
+ register unsigned long r4 asm("4") = (unsigned long) dest;
+ register unsigned long r6 asm("6") = (unsigned long) counter;
+
+ asm volatile(
+ "0: .insn rrf,%[opc] << 16,%[dst],%[src],%[ctr],0\n"
+ " brc 1,0b\n" /* handle partial completion */
+ : [src] "+a" (r2), [len] "+d" (r3),
+ [dst] "+a" (r4), [ctr] "+a" (r6)
+ : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_KMCTR)
+ : "cc", "memory");
+
+ return src_len - r3;
+}
+
+/**
+ * cpacf_prno() - executes the PRNO (PERFORM RANDOM NUMBER OPERATION)
+ * instruction
+ * @func: the function code passed to PRNO; see CPACF_PRNO_xxx defines
+ * @param: address of parameter block; see POP for details on each func
+ * @dest: address of destination memory area
+ * @dest_len: size of destination memory area in bytes
+ * @seed: address of seed data
+ * @seed_len: size of seed data in bytes
+ */
+static inline void cpacf_prno(unsigned long func, void *param,
+ u8 *dest, unsigned long dest_len,
+ const u8 *seed, unsigned long seed_len)
+{
+ register unsigned long r0 asm("0") = (unsigned long) func;
+ register unsigned long r1 asm("1") = (unsigned long) param;
+ register unsigned long r2 asm("2") = (unsigned long) dest;
+ register unsigned long r3 asm("3") = (unsigned long) dest_len;
+ register unsigned long r4 asm("4") = (unsigned long) seed;
+ register unsigned long r5 asm("5") = (unsigned long) seed_len;
+
+ asm volatile (
+ "0: .insn rre,%[opc] << 16,%[dst],%[seed]\n"
+ " brc 1,0b\n" /* handle partial completion */
+ : [dst] "+a" (r2), [dlen] "+d" (r3)
+ : [fc] "d" (r0), [pba] "a" (r1),
+ [seed] "a" (r4), [slen] "d" (r5), [opc] "i" (CPACF_PRNO)
+ : "cc", "memory");
+}
+
+/**
+ * cpacf_trng() - executes the TRNG subfunction of the PRNO instruction
+ * @ucbuf: buffer for unconditioned data
+ * @ucbuf_len: amount of unconditioned data to fetch in bytes
+ * @cbuf: buffer for conditioned data
+ * @cbuf_len: amount of conditioned data to fetch in bytes
+ */
+static inline void cpacf_trng(u8 *ucbuf, unsigned long ucbuf_len,
+ u8 *cbuf, unsigned long cbuf_len)
+{
+ register unsigned long r0 asm("0") = (unsigned long) CPACF_PRNO_TRNG;
+ register unsigned long r2 asm("2") = (unsigned long) ucbuf;
+ register unsigned long r3 asm("3") = (unsigned long) ucbuf_len;
+ register unsigned long r4 asm("4") = (unsigned long) cbuf;
+ register unsigned long r5 asm("5") = (unsigned long) cbuf_len;
+
+ asm volatile (
+ "0: .insn rre,%[opc] << 16,%[ucbuf],%[cbuf]\n"
+ " brc 1,0b\n" /* handle partial completion */
+ : [ucbuf] "+a" (r2), [ucbuflen] "+d" (r3),
+ [cbuf] "+a" (r4), [cbuflen] "+d" (r5)
+ : [fc] "d" (r0), [opc] "i" (CPACF_PRNO)
+ : "cc", "memory");
+}
+
+/**
+ * cpacf_pcc() - executes the PCC (PERFORM CRYPTOGRAPHIC COMPUTATION)
+ * instruction
+ * @func: the function code passed to PCC; see CPACF_KM_xxx defines
+ * @param: address of parameter block; see POP for details on each func
+ */
+static inline void cpacf_pcc(unsigned long func, void *param)
+{
+ register unsigned long r0 asm("0") = (unsigned long) func;
+ register unsigned long r1 asm("1") = (unsigned long) param;
+
+ asm volatile(
+ "0: .insn rre,%[opc] << 16,0,0\n" /* PCC opcode */
+ " brc 1,0b\n" /* handle partial completion */
+ :
+ : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_PCC)
+ : "cc", "memory");
+}
+
+/**
+ * cpacf_pckmo() - executes the PCKMO (PERFORM CRYPTOGRAPHIC KEY
+ * MANAGEMENT) instruction
+ * @func: the function code passed to PCKMO; see CPACF_PCKMO_xxx defines
+ * @param: address of parameter block; see POP for details on each func
+ *
+ * Returns 0.
+ */
+static inline void cpacf_pckmo(long func, void *param)
+{
+ register unsigned long r0 asm("0") = (unsigned long) func;
+ register unsigned long r1 asm("1") = (unsigned long) param;
+
+ asm volatile(
+ " .insn rre,%[opc] << 16,0,0\n" /* PCKMO opcode */
+ :
+ : [fc] "d" (r0), [pba] "a" (r1), [opc] "i" (CPACF_PCKMO)
+ : "cc", "memory");
+}
+
+#endif /* _ASM_S390_CPACF_H */
--
2.13.5
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [kvm-unit-tests PATCH v1 3/5] s390x: make sure cpacf.h can be used
2017-09-19 14:50 [kvm-unit-tests PATCH v1 0/5] s390x: IPM/SPM and MSA tests David Hildenbrand
2017-09-19 14:50 ` [kvm-unit-tests PATCH v1 1/5] s390x: add a test case for the ipm + spm instructions David Hildenbrand
2017-09-19 14:50 ` [kvm-unit-tests PATCH v1 2/5] s390x: add cpacf.h from Linux David Hildenbrand
@ 2017-09-19 14:50 ` David Hildenbrand
2017-09-19 14:50 ` [kvm-unit-tests PATCH v1 4/5] s390x: query and store STFL(E) facilitites David Hildenbrand
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: David Hildenbrand @ 2017-09-19 14:50 UTC (permalink / raw)
To: kvm
Cc: Paolo Bonzini, Radim Krčmář, david, Thomas Huth,
Cornelia Huck, Christian Borntraeger
We don't define BUG(), just use a return instead.
Signed-off-by: David Hildenbrand <david@redhat.com>
---
lib/s390x/asm/cpacf.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/s390x/asm/cpacf.h b/lib/s390x/asm/cpacf.h
index e06f255..ae2ec53 100644
--- a/lib/s390x/asm/cpacf.h
+++ b/lib/s390x/asm/cpacf.h
@@ -179,7 +179,7 @@ static inline int __cpacf_check_opcode(unsigned int opcode)
case CPACF_PRNO:
return test_facility(57); /* check for MSA5 */
default:
- BUG();
+ return 0;
}
}
--
2.13.5
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [kvm-unit-tests PATCH v1 4/5] s390x: query and store STFL(E) facilitites
2017-09-19 14:50 [kvm-unit-tests PATCH v1 0/5] s390x: IPM/SPM and MSA tests David Hildenbrand
` (2 preceding siblings ...)
2017-09-19 14:50 ` [kvm-unit-tests PATCH v1 3/5] s390x: make sure cpacf.h can be used David Hildenbrand
@ 2017-09-19 14:50 ` David Hildenbrand
2017-09-19 14:50 ` [kvm-unit-tests PATCH v1 5/5] s390x: test for various MSA instructions David Hildenbrand
2017-09-20 7:25 ` [kvm-unit-tests PATCH v1 0/5] s390x: IPM/SPM and MSA tests Paolo Bonzini
5 siblings, 0 replies; 7+ messages in thread
From: David Hildenbrand @ 2017-09-19 14:50 UTC (permalink / raw)
To: kvm
Cc: Paolo Bonzini, Radim Krčmář, david, Thomas Huth,
Cornelia Huck, Christian Borntraeger
cpacf.h will require the test_facility() function, so let's properly
query and store the STFL(E) facilities.
STFLE requires double word alignment.
Signed-off-by: David Hildenbrand <david@redhat.com>
---
lib/s390x/asm/facility.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
lib/s390x/io.c | 3 +++
2 files changed, 51 insertions(+)
create mode 100644 lib/s390x/asm/facility.h
diff --git a/lib/s390x/asm/facility.h b/lib/s390x/asm/facility.h
new file mode 100644
index 0000000..5103dd4
--- /dev/null
+++ b/lib/s390x/asm/facility.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2017 Red Hat Inc
+ *
+ * Authors:
+ * David Hildenbrand <david@redhat.com>
+ *
+ * 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 _ASM_S390X_FACILITY_H_
+#define _ASM_S390X_FACILITY_H_
+
+#include <libcflat.h>
+#include <asm/facility.h>
+#include <asm/arch_def.h>
+
+#define NR_STFL_BYTES 256
+extern uint8_t stfl_bytes[];
+
+static inline bool test_facility(int nr)
+{
+ return stfl_bytes[nr / 8] & (0x80U >> (nr % 8));
+}
+
+static inline void stfl(void)
+{
+ asm volatile(" stfl 0(0)\n");
+}
+
+static inline void stfle(uint8_t *fac, unsigned int len)
+{
+ register unsigned long r0 asm("0") = len - 1;
+
+ asm volatile(" .insn s,0xb2b00000,0(%1)\n"
+ : "+d" (r0) : "a" (fac) : "memory", "cc");
+}
+
+static inline void setup_facilities(void)
+{
+ struct lowcore *lc = NULL;
+
+ stfl();
+ memcpy(stfl_bytes, &lc->stfl, sizeof(lc->stfl));
+ if (test_facility(7))
+ stfle(stfl_bytes, NR_STFL_BYTES);
+}
+
+#endif
diff --git a/lib/s390x/io.c b/lib/s390x/io.c
index 4ab5bd9..12f9d26 100644
--- a/lib/s390x/io.c
+++ b/lib/s390x/io.c
@@ -13,9 +13,11 @@
#include <libcflat.h>
#include <argv.h>
#include <asm/spinlock.h>
+#include <asm/facility.h>
#include "sclp.h"
extern char ipl_args[];
+uint8_t stfl_bytes[NR_STFL_BYTES] __attribute__((aligned(8)));
static struct spinlock lock;
@@ -39,6 +41,7 @@ static void sigp_stop()
void setup()
{
setup_args_progname(ipl_args);
+ setup_facilities();
sclp_setup();
}
--
2.13.5
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [kvm-unit-tests PATCH v1 5/5] s390x: test for various MSA instructions
2017-09-19 14:50 [kvm-unit-tests PATCH v1 0/5] s390x: IPM/SPM and MSA tests David Hildenbrand
` (3 preceding siblings ...)
2017-09-19 14:50 ` [kvm-unit-tests PATCH v1 4/5] s390x: query and store STFL(E) facilitites David Hildenbrand
@ 2017-09-19 14:50 ` David Hildenbrand
2017-09-20 7:25 ` [kvm-unit-tests PATCH v1 0/5] s390x: IPM/SPM and MSA tests Paolo Bonzini
5 siblings, 0 replies; 7+ messages in thread
From: David Hildenbrand @ 2017-09-19 14:50 UTC (permalink / raw)
To: kvm
Cc: Paolo Bonzini, Radim Krčmář, david, Thomas Huth,
Cornelia Huck, Christian Borntraeger
Test the parameter checks and if the query function correctly works.
Tests will only be executed if the corresponding stfl(e) bit for an
instruction is indicated.
Signed-off-by: David Hildenbrand <david@redhat.com>
---
s390x/emulator.c | 227 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 227 insertions(+)
diff --git a/s390x/emulator.c b/s390x/emulator.c
index 7854498..a8b4212 100644
--- a/s390x/emulator.c
+++ b/s390x/emulator.c
@@ -11,6 +11,8 @@
* under the terms of the GNU Library General Public License version 2.
*/
#include <libcflat.h>
+#include <asm/cpacf.h>
+#include <asm/interrupt.h>
static inline void __test_spm_ipm(uint8_t cc, uint8_t key)
{
@@ -41,11 +43,236 @@ static void test_spm_ipm(void)
__test_spm_ipm(0, 0);
}
+static inline void __test_cpacf(unsigned int opcode, unsigned long func,
+ unsigned int r1, unsigned int r2,
+ unsigned int r3)
+{
+ register unsigned long gr0 asm("0") = func;
+ cpacf_mask_t mask;
+ register unsigned long gr1 asm("1") = (unsigned long)&mask;
+
+ asm volatile(".insn rrf,%[opc] << 16,%[r1],%[r2],%[r3],0\n"
+ : : "d" (gr0), "d" (gr1), [opc] "i" (opcode),
+ [r1] "i" (r1), [r2] "i" (r2), [r3] "i" (r3));
+}
+
+static inline void __test_cpacf_r1_odd(unsigned int opcode)
+{
+ report_prefix_push("r1 odd");
+ expect_pgm_int();
+ __test_cpacf(opcode, 0, 1, 4, 6);
+ check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
+ report_prefix_pop();
+}
+
+static inline void __test_cpacf_r1_null(unsigned int opcode)
+{
+ report_prefix_push("r1 null");
+ expect_pgm_int();
+ __test_cpacf(opcode, 0, 0, 4, 6);
+ check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
+ report_prefix_pop();
+}
+
+static inline void __test_cpacf_r2_odd(unsigned int opcode)
+{
+ report_prefix_push("r2 odd");
+ expect_pgm_int();
+ __test_cpacf(opcode, 0, 2, 3, 6);
+ check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
+ report_prefix_pop();
+}
+
+static inline void __test_cpacf_r2_null(unsigned int opcode)
+{
+ report_prefix_push("r2 null");
+ expect_pgm_int();
+ __test_cpacf(opcode, 0, 2, 0, 6);
+ check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
+ report_prefix_pop();
+}
+
+static inline void __test_cpacf_r3_odd(unsigned int opcode)
+{
+ report_prefix_push("r3 odd");
+ expect_pgm_int();
+ __test_cpacf(opcode, 0, 2, 4, 5);
+ check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
+ report_prefix_pop();
+}
+
+static inline void __test_cpacf_r3_null(unsigned int opcode)
+{
+ report_prefix_push("r3 null");
+ expect_pgm_int();
+ __test_cpacf(opcode, 0, 2, 4, 0);
+ check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
+ report_prefix_pop();
+}
+
+static inline void __test_cpacf_mod_bit(unsigned int opcode)
+{
+ report_prefix_push("mod bit");
+ expect_pgm_int();
+ __test_cpacf(opcode, CPACF_DECRYPT, 2, 4, 6);
+ check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
+ report_prefix_pop();
+}
+
+static inline void __test_cpacf_invalid_func(unsigned int opcode)
+{
+ report_prefix_push("invalid subfunction");
+ expect_pgm_int();
+ /* 127 is unassigned for now. We don't simply use any, as HW
+ * might simply mask valid codes in query but they might still work */
+ if (cpacf_query_func(opcode, 127)) {
+ report_skip("127 not invalid");
+ } else {
+ __test_cpacf(opcode, 127, 2, 4, 6);
+ }
+ check_pgm_int_code(PGM_INT_CODE_SPECIFICATION);
+ report_prefix_pop();
+}
+
+static inline void __test_cpacf_invalid_parm(unsigned int opcode)
+{
+ report_prefix_push("invalid parm address");
+ expect_pgm_int();
+ __cpacf_query(opcode, (void *) -1);
+ check_pgm_int_code(PGM_INT_CODE_ADDRESSING);
+ report_prefix_pop();
+}
+
+static inline void __test_cpacf_protected_parm(unsigned int opcode)
+{
+ report_prefix_push("protected parm address");
+ expect_pgm_int();
+ low_prot_enable();
+ __cpacf_query(opcode, (void *) 8);
+ low_prot_disable();
+ check_pgm_int_code(PGM_INT_CODE_PROTECTION);
+ report_prefix_pop();
+}
+
+static inline void __test_basic_cpacf_opcode(unsigned int opcode)
+{
+ bool mod_bit_allowed = false;
+
+ if (!__cpacf_check_opcode(opcode)) {
+ report_skip("not available");
+ return;
+ }
+ report("query indicated in query", cpacf_query_func(opcode, 0));
+
+ switch (opcode) {
+ case CPACF_KMCTR:
+ __test_cpacf_r3_odd(opcode);
+ __test_cpacf_r3_null(opcode);
+ /* FALL THROUGH */
+ case CPACF_PRNO:
+ case CPACF_KMF:
+ case CPACF_KMC:
+ case CPACF_KMO:
+ case CPACF_KM:
+ __test_cpacf_r1_odd(opcode);
+ __test_cpacf_r1_null(opcode);
+ mod_bit_allowed = true;
+ /* FALL THROUGH */
+ case CPACF_KMAC:
+ case CPACF_KIMD:
+ case CPACF_KLMD:
+ __test_cpacf_r2_odd(opcode);
+ __test_cpacf_r2_null(opcode);
+ break;
+ }
+ if (!mod_bit_allowed)
+ __test_cpacf_mod_bit(opcode);
+ __test_cpacf_invalid_func(opcode);
+ __test_cpacf_invalid_parm(opcode);
+ __test_cpacf_protected_parm(opcode);
+}
+
+/* COMPUTE MESSAGE AUTHENTICATION CODE */
+static void test_kmac(void)
+{
+ __test_basic_cpacf_opcode(CPACF_KMAC);
+}
+
+/* CIPHER MESSAGE */
+static void test_km(void)
+{
+ __test_basic_cpacf_opcode(CPACF_KM);
+}
+/* CIPHER MESSAGE WITH CHAINING */
+static void test_kmc(void)
+{
+ __test_basic_cpacf_opcode(CPACF_KMC);
+}
+
+/* COMPUTE INTERMEDIATE MESSAGE DIGEST */
+static void test_kimd(void)
+{
+ __test_basic_cpacf_opcode(CPACF_KIMD);
+}
+
+/* COMPUTE LAST MESSAGE DIGEST */
+static void test_klmd(void)
+{
+ __test_basic_cpacf_opcode(CPACF_KLMD);
+}
+
+/* PERFORM CRYPTOGRAPHIC KEY MANAGEMENT OPERATION */
+static void test_pckmo(void)
+{
+ __test_basic_cpacf_opcode(CPACF_PCKMO);
+}
+
+/* CIPHER MESSAGE WITH CIPHER FEEDBACK */
+static void test_kmf(void)
+{
+ __test_basic_cpacf_opcode(CPACF_KMF);
+}
+
+/* PERFORM CRYPTOGRAPHIC KEY MANAGEMENT OPERATION */
+static void test_kmo(void)
+{
+ __test_basic_cpacf_opcode(CPACF_KMO);
+}
+
+/* PERFORM CRYPTOGRAPHIC COMPUTATION */
+static void test_pcc(void)
+{
+ __test_basic_cpacf_opcode(CPACF_PCC);
+}
+
+/* CIPHER MESSAGE WITH COUNTER */
+static void test_kmctr(void)
+{
+ __test_basic_cpacf_opcode(CPACF_KMCTR);
+}
+
+/* PERFORM RANDOM NUMBER OPERATION (formerly PPNO) */
+static void test_prno(void)
+{
+ __test_basic_cpacf_opcode(CPACF_PRNO);
+}
+
static struct {
const char *name;
void (*func)(void);
} tests[] = {
{ "spm/ipm", test_spm_ipm },
+ { "kmac", test_kmac },
+ { "km", test_km },
+ { "kmc", test_kmc },
+ { "kimd", test_kimd },
+ { "klmd", test_klmd },
+ { "pckmo", test_pckmo },
+ { "kmf", test_kmf },
+ { "kmo", test_kmo },
+ { "pcc", test_pcc },
+ { "kmctr", test_kmctr },
+ { "prno", test_prno },
{ NULL, NULL }
};
--
2.13.5
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [kvm-unit-tests PATCH v1 0/5] s390x: IPM/SPM and MSA tests
2017-09-19 14:50 [kvm-unit-tests PATCH v1 0/5] s390x: IPM/SPM and MSA tests David Hildenbrand
` (4 preceding siblings ...)
2017-09-19 14:50 ` [kvm-unit-tests PATCH v1 5/5] s390x: test for various MSA instructions David Hildenbrand
@ 2017-09-20 7:25 ` Paolo Bonzini
5 siblings, 0 replies; 7+ messages in thread
From: Paolo Bonzini @ 2017-09-20 7:25 UTC (permalink / raw)
To: David Hildenbrand, kvm
Cc: Radim Krčmář, Thomas Huth, Cornelia Huck,
Christian Borntraeger
On 19/09/2017 16:50, David Hildenbrand wrote:
> Developed while working on:
> https://lists.gnu.org/archive/html/qemu-devel/2017-09/msg05133.html
>
> Only the basics for MSA instructions are tested (basically everything QEMU
> also implements), but no real en/decryption.
>
> All tests seem to pass under KVM.
>
> For TCG, only the usual low address protection tests fail.
> To run under TCG, the feature have to be enabled explicitly for now:
>
> ./s390x-run s390x/emulator.elf \
> -cpu qemu,msa-base=on,msa3-base=on,msa4-base=on,msa5-base=on,stfle=on
>
>
> David Hildenbrand (5):
> s390x: add a test case for the ipm + spm instructions
> s390x: add cpacf.h from Linux
> s390x: make sure cpacf.h can be used
> s390x: query and store STFL(E) facilitites
> s390x: test for various MSA instructions
>
> lib/s390x/asm/cpacf.h | 472 +++++++++++++++++++++++++++++++++++++++++++++++
> lib/s390x/asm/facility.h | 48 +++++
> lib/s390x/io.c | 3 +
> s390x/Makefile | 1 +
> s390x/emulator.c | 292 +++++++++++++++++++++++++++++
> s390x/unittests.cfg | 3 +
> 6 files changed, 819 insertions(+)
> create mode 100644 lib/s390x/asm/cpacf.h
> create mode 100644 lib/s390x/asm/facility.h
> create mode 100644 s390x/emulator.c
>
Applied, thanks.
Paolo
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2017-09-20 7:25 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-09-19 14:50 [kvm-unit-tests PATCH v1 0/5] s390x: IPM/SPM and MSA tests David Hildenbrand
2017-09-19 14:50 ` [kvm-unit-tests PATCH v1 1/5] s390x: add a test case for the ipm + spm instructions David Hildenbrand
2017-09-19 14:50 ` [kvm-unit-tests PATCH v1 2/5] s390x: add cpacf.h from Linux David Hildenbrand
2017-09-19 14:50 ` [kvm-unit-tests PATCH v1 3/5] s390x: make sure cpacf.h can be used David Hildenbrand
2017-09-19 14:50 ` [kvm-unit-tests PATCH v1 4/5] s390x: query and store STFL(E) facilitites David Hildenbrand
2017-09-19 14:50 ` [kvm-unit-tests PATCH v1 5/5] s390x: test for various MSA instructions David Hildenbrand
2017-09-20 7:25 ` [kvm-unit-tests PATCH v1 0/5] s390x: IPM/SPM and MSA tests Paolo Bonzini
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox