diff mbox

[v1,5/6] target/s390x: add basic MSA features

Message ID 20170721125609.11117-6-david@redhat.com
State New
Headers show

Commit Message

David Hildenbrand July 21, 2017, 12:56 p.m. UTC
The STFLE bits for the MSA (extension) facilities simply indicate that
the respective instructions can be executed. The QUERY subfunction can then
be used to identify which features exactly are available.

Availability of subfunctions can also vary on real hardware. For now, we
simply implement a CPU model without any available subfunctions except
QUERY (which is always around).

As all MSA functions behave quite similarly, we can use one translation
handler for now. Prepare the code for implementation of actual subfunctions.

At least MSA is helpful for now, as older Linux kernels require this
facility when compiled for a z9 model. Allow to enable the facilities
for the qemu cpu model.

Signed-off-by: David Hildenbrand <david@redhat.com>
---
 target/s390x/Makefile.objs   |  2 +-
 target/s390x/cpu_models.c    |  4 +++
 target/s390x/crypto_helper.c | 65 ++++++++++++++++++++++++++++++++++++++++++++
 target/s390x/helper.h        |  1 +
 target/s390x/insn-data.def   | 13 +++++++++
 target/s390x/translate.c     | 56 ++++++++++++++++++++++++++++++++++++++
 6 files changed, 140 insertions(+), 1 deletion(-)
 create mode 100644 target/s390x/crypto_helper.c

Comments

Cornelia Huck Aug. 9, 2017, 1:01 p.m. UTC | #1
On Fri, 21 Jul 2017 14:56:08 +0200
David Hildenbrand <david@redhat.com> wrote:

Finally got around to that one...

> The STFLE bits for the MSA (extension) facilities simply indicate that
> the respective instructions can be executed. The QUERY subfunction can then
> be used to identify which features exactly are available.
> 
> Availability of subfunctions can also vary on real hardware. For now, we
> simply implement a CPU model without any available subfunctions except
> QUERY (which is always around).
> 
> As all MSA functions behave quite similarly, we can use one translation
> handler for now. Prepare the code for implementation of actual subfunctions.

Sounds reasonable.

> 
> At least MSA is helpful for now, as older Linux kernels require this
> facility when compiled for a z9 model. Allow to enable the facilities
> for the qemu cpu model.

Do you remember which kernels?

> 
> Signed-off-by: David Hildenbrand <david@redhat.com>
> ---
>  target/s390x/Makefile.objs   |  2 +-
>  target/s390x/cpu_models.c    |  4 +++
>  target/s390x/crypto_helper.c | 65 ++++++++++++++++++++++++++++++++++++++++++++
>  target/s390x/helper.h        |  1 +
>  target/s390x/insn-data.def   | 13 +++++++++
>  target/s390x/translate.c     | 56 ++++++++++++++++++++++++++++++++++++++
>  6 files changed, 140 insertions(+), 1 deletion(-)
>  create mode 100644 target/s390x/crypto_helper.c
> 
> diff --git a/target/s390x/Makefile.objs b/target/s390x/Makefile.objs
> index 46f6a8c..9d261ed 100644
> --- a/target/s390x/Makefile.objs
> +++ b/target/s390x/Makefile.objs
> @@ -1,4 +1,4 @@
> -obj-y += translate.o helper.o cpu.o interrupt.o
> +obj-y += translate.o helper.o cpu.o interrupt.o crypto_helper.o
>  obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o
>  obj-y += gdbstub.o cpu_models.o cpu_features.o
>  obj-$(CONFIG_SOFTMMU) += machine.o ioinst.o arch_dump.o mmu_helper.o

This doesn't apply cleanly anymore.

> diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c
> index 92120f4..45bd920 100644
> --- a/target/s390x/cpu_models.c
> +++ b/target/s390x/cpu_models.c
> @@ -792,6 +792,7 @@ static void add_qemu_cpu_model_features(S390FeatBitmap fbm)
>          S390_FEAT_STFLE,
>          S390_FEAT_EXTENDED_IMMEDIATE,
>          S390_FEAT_EXTENDED_TRANSLATION_2,
> +        S390_FEAT_MSA,
>          S390_FEAT_EXTENDED_TRANSLATION_3,
>          S390_FEAT_LONG_DISPLACEMENT,
>          S390_FEAT_LONG_DISPLACEMENT_FAST,
> @@ -808,6 +809,9 @@ static void add_qemu_cpu_model_features(S390FeatBitmap fbm)
>          S390_FEAT_STFLE_49,
>          S390_FEAT_LOCAL_TLB_CLEARING,
>          S390_FEAT_STFLE_53,
> +        S390_FEAT_MSA_EXT_5,
> +        S390_FEAT_MSA_EXT_3,
> +        S390_FEAT_MSA_EXT_4,

I first thought that this looks weird, but it is the actual sequence of
the facility bits (probably the bit for MSA_EXT_5 has been reused?)

>      };
>      int i;
>  
> diff --git a/target/s390x/crypto_helper.c b/target/s390x/crypto_helper.c
> new file mode 100644
> index 0000000..125bd9b
> --- /dev/null
> +++ b/target/s390x/crypto_helper.c
> @@ -0,0 +1,65 @@
> +/*
> + *  s390x crypto helpers
> + *
> + *  Copyright (c) 2017 Red Hat Inc
> + *
> + *  Authors:
> + *   David Hildenbrand <david@redhat.com>
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qemu/main-loop.h"
> +#include "cpu.h"
> +#include "exec/helper-proto.h"
> +#include "exec/exec-all.h"
> +#include "exec/cpu_ldst.h"
> +
> +uint32_t HELPER(msa)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t r3,
> +                     uint32_t type)
> +{
> +    const uintptr_t ra = GETPC();
> +    const uint8_t mod = env->regs[0] & 0x80ULL;
> +    const uint8_t fc = env->regs[0] & 0x7fULL;
> +    CPUState *cs = CPU(s390_env_get_cpu(env));
> +    uint8_t subfunc[16] = { 0 };
> +    uint64_t param_addr;
> +    int i;
> +
> +    switch (type) {
> +    case S390_FEAT_TYPE_KMAC:
> +    case S390_FEAT_TYPE_KIMD:
> +    case S390_FEAT_TYPE_KLMD:
> +    case S390_FEAT_TYPE_PCKMO:
> +    case S390_FEAT_TYPE_PCC:
> +        if (mod) {
> +            cpu_restore_state(cs, ra);
> +            program_interrupt(env, PGM_SPECIFICATION, 4);
> +            return 0;
> +        }
> +        break;
> +    }
> +
> +    s390_get_feat_block(type, subfunc);
> +    if (fc >= 128 || !test_be_bit(fc, subfunc)) {
> +        cpu_restore_state(cs, ra);
> +        program_interrupt(env, PGM_SPECIFICATION, 4);
> +        return 0;
> +    }
> +
> +    switch (fc) {
> +    case 0:

A comment which subfunction this is might be helpful.

> +        for (i = 0; i < 16; i++) {
> +            param_addr = wrap_address(env, env->regs[1] + i);

This does not compile for me (after massaging the Makefile above), as
wrap_address does not seem to be exported... can you do a respin,
please?

> +            cpu_stb_data_ra(env, param_addr, subfunc[i], ra);
> +        }
> +        break;
> +    default:
> +        /* we don't implement any other subfunction yet */
> +        g_assert_not_reached();
> +    }
> +
> +    return 0;
> +}
Thomas Huth Aug. 9, 2017, 1:13 p.m. UTC | #2
On 09.08.2017 15:01, Cornelia Huck wrote:
> On Fri, 21 Jul 2017 14:56:08 +0200
> David Hildenbrand <david@redhat.com> wrote:
> 
> Finally got around to that one...
> 
>> The STFLE bits for the MSA (extension) facilities simply indicate that
>> the respective instructions can be executed. The QUERY subfunction can then
>> be used to identify which features exactly are available.
>>
>> Availability of subfunctions can also vary on real hardware. For now, we
>> simply implement a CPU model without any available subfunctions except
>> QUERY (which is always around).
>>
>> As all MSA functions behave quite similarly, we can use one translation
>> handler for now. Prepare the code for implementation of actual subfunctions.
> 
> Sounds reasonable.
> 
>>
>> At least MSA is helpful for now, as older Linux kernels require this
>> facility when compiled for a z9 model. Allow to enable the facilities
>> for the qemu cpu model.
> 
> Do you remember which kernels?

Basically everything before kernel version 4.13 - the patch to lift this
requirement has just been merged very recently:

 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8aa8680aa383bf6e2ac2a7d3369097268c75f7da

 Thomas
David Hildenbrand Aug. 9, 2017, 1:25 p.m. UTC | #3
>> @@ -792,6 +792,7 @@ static void add_qemu_cpu_model_features(S390FeatBitmap fbm)
>>          S390_FEAT_STFLE,
>>          S390_FEAT_EXTENDED_IMMEDIATE,
>>          S390_FEAT_EXTENDED_TRANSLATION_2,
>> +        S390_FEAT_MSA,
>>          S390_FEAT_EXTENDED_TRANSLATION_3,
>>          S390_FEAT_LONG_DISPLACEMENT,
>>          S390_FEAT_LONG_DISPLACEMENT_FAST,
>> @@ -808,6 +809,9 @@ static void add_qemu_cpu_model_features(S390FeatBitmap fbm)
>>          S390_FEAT_STFLE_49,
>>          S390_FEAT_LOCAL_TLB_CLEARING,
>>          S390_FEAT_STFLE_53,
>> +        S390_FEAT_MSA_EXT_5,
>> +        S390_FEAT_MSA_EXT_3,
>> +        S390_FEAT_MSA_EXT_4,
> 
> I first thought that this looks weird, but it is the actual sequence of
> the facility bits (probably the bit for MSA_EXT_5 has been reused?)

Probably, or they had it reserved for something else. Another reason
could be the non-hypervisor managed vs. hypervisor managed stuff (didn't
check the facility bit numbers, but this could be a reason).

[...]
> 
> A comment which subfunction this is might be helpful.

Indeed.

/* query subfunction */

> 
>> +        for (i = 0; i < 16; i++) {
>> +            param_addr = wrap_address(env, env->regs[1] + i);
> 
> This does not compile for me (after massaging the Makefile above), as
> wrap_address does not seem to be exported... can you do a respin,
> please?
> 

Contained in patch nr4 in this series. But I'm planning to do a respin
(most likely introducing internal.h).

>> +            cpu_stb_data_ra(env, param_addr, subfunc[i], ra);
>> +        }
>> +        break;
>> +    default:
>> +        /* we don't implement any other subfunction yet */
>> +        g_assert_not_reached();
>> +    }
>> +
>> +    return 0;
>> +}

Thanks!
Cornelia Huck Aug. 9, 2017, 1:29 p.m. UTC | #4
On Wed, 9 Aug 2017 15:25:36 +0200
David Hildenbrand <david@redhat.com> wrote:

> > A comment which subfunction this is might be helpful.  
> 
> Indeed.
> 
> /* query subfunction */

Looks good!

> 
> >   
> >> +        for (i = 0; i < 16; i++) {
> >> +            param_addr = wrap_address(env, env->regs[1] + i);  
> > 
> > This does not compile for me (after massaging the Makefile above), as
> > wrap_address does not seem to be exported... can you do a respin,
> > please?
> >   
> 
> Contained in patch nr4 in this series. But I'm planning to do a respin
> (most likely introducing internal.h).

Ah yes, that issue had dropped out of my cache :)

I'll just wait for a respin of your pending patches, then.
diff mbox

Patch

diff --git a/target/s390x/Makefile.objs b/target/s390x/Makefile.objs
index 46f6a8c..9d261ed 100644
--- a/target/s390x/Makefile.objs
+++ b/target/s390x/Makefile.objs
@@ -1,4 +1,4 @@ 
-obj-y += translate.o helper.o cpu.o interrupt.o
+obj-y += translate.o helper.o cpu.o interrupt.o crypto_helper.o
 obj-y += int_helper.o fpu_helper.o cc_helper.o mem_helper.o misc_helper.o
 obj-y += gdbstub.o cpu_models.o cpu_features.o
 obj-$(CONFIG_SOFTMMU) += machine.o ioinst.o arch_dump.o mmu_helper.o
diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c
index 92120f4..45bd920 100644
--- a/target/s390x/cpu_models.c
+++ b/target/s390x/cpu_models.c
@@ -792,6 +792,7 @@  static void add_qemu_cpu_model_features(S390FeatBitmap fbm)
         S390_FEAT_STFLE,
         S390_FEAT_EXTENDED_IMMEDIATE,
         S390_FEAT_EXTENDED_TRANSLATION_2,
+        S390_FEAT_MSA,
         S390_FEAT_EXTENDED_TRANSLATION_3,
         S390_FEAT_LONG_DISPLACEMENT,
         S390_FEAT_LONG_DISPLACEMENT_FAST,
@@ -808,6 +809,9 @@  static void add_qemu_cpu_model_features(S390FeatBitmap fbm)
         S390_FEAT_STFLE_49,
         S390_FEAT_LOCAL_TLB_CLEARING,
         S390_FEAT_STFLE_53,
+        S390_FEAT_MSA_EXT_5,
+        S390_FEAT_MSA_EXT_3,
+        S390_FEAT_MSA_EXT_4,
     };
     int i;
 
diff --git a/target/s390x/crypto_helper.c b/target/s390x/crypto_helper.c
new file mode 100644
index 0000000..125bd9b
--- /dev/null
+++ b/target/s390x/crypto_helper.c
@@ -0,0 +1,65 @@ 
+/*
+ *  s390x crypto helpers
+ *
+ *  Copyright (c) 2017 Red Hat Inc
+ *
+ *  Authors:
+ *   David Hildenbrand <david@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/main-loop.h"
+#include "cpu.h"
+#include "exec/helper-proto.h"
+#include "exec/exec-all.h"
+#include "exec/cpu_ldst.h"
+
+uint32_t HELPER(msa)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t r3,
+                     uint32_t type)
+{
+    const uintptr_t ra = GETPC();
+    const uint8_t mod = env->regs[0] & 0x80ULL;
+    const uint8_t fc = env->regs[0] & 0x7fULL;
+    CPUState *cs = CPU(s390_env_get_cpu(env));
+    uint8_t subfunc[16] = { 0 };
+    uint64_t param_addr;
+    int i;
+
+    switch (type) {
+    case S390_FEAT_TYPE_KMAC:
+    case S390_FEAT_TYPE_KIMD:
+    case S390_FEAT_TYPE_KLMD:
+    case S390_FEAT_TYPE_PCKMO:
+    case S390_FEAT_TYPE_PCC:
+        if (mod) {
+            cpu_restore_state(cs, ra);
+            program_interrupt(env, PGM_SPECIFICATION, 4);
+            return 0;
+        }
+        break;
+    }
+
+    s390_get_feat_block(type, subfunc);
+    if (fc >= 128 || !test_be_bit(fc, subfunc)) {
+        cpu_restore_state(cs, ra);
+        program_interrupt(env, PGM_SPECIFICATION, 4);
+        return 0;
+    }
+
+    switch (fc) {
+    case 0:
+        for (i = 0; i < 16; i++) {
+            param_addr = wrap_address(env, env->regs[1] + i);
+            cpu_stb_data_ra(env, param_addr, subfunc[i], ra);
+        }
+        break;
+    default:
+        /* we don't implement any other subfunction yet */
+        g_assert_not_reached();
+    }
+
+    return 0;
+}
diff --git a/target/s390x/helper.h b/target/s390x/helper.h
index 4b02907..75ba04f 100644
--- a/target/s390x/helper.h
+++ b/target/s390x/helper.h
@@ -115,6 +115,7 @@  DEF_HELPER_4(cu21, i32, env, i32, i32, i32)
 DEF_HELPER_4(cu24, i32, env, i32, i32, i32)
 DEF_HELPER_4(cu41, i32, env, i32, i32, i32)
 DEF_HELPER_4(cu42, i32, env, i32, i32, i32)
+DEF_HELPER_5(msa, i32, env, i32, i32, i32, i32)
 
 #ifndef CONFIG_USER_ONLY
 DEF_HELPER_3(servc, i32, env, i64, i64)
diff --git a/target/s390x/insn-data.def b/target/s390x/insn-data.def
index 84233a4..d09f2ed 100644
--- a/target/s390x/insn-data.def
+++ b/target/s390x/insn-data.def
@@ -941,6 +941,19 @@ 
 /* UNPACK UNICODE */
     C(0xe200, UNPKU,   SS_a,  E2,  la1, a2, 0, 0, unpku, 0)
 
+/* MSA Instructions */
+    D(0xb91e, KMAC,    RRE,   MSA,  0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_KMAC)
+    D(0xb928, PCKMO,   RRE,   MSA3, 0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_PCKMO)
+    D(0xb92a, KMF,     RRE,   MSA4, 0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_KMF)
+    D(0xb92b, KMO,     RRE,   MSA4, 0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_KMO)
+    D(0xb92c, PCC,     RRE,   MSA4, 0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_PCC)
+    D(0xb92d, KMCTR,   RRF_b, MSA4, 0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_KMCTR)
+    D(0xb92e, KM,      RRE,   MSA,  0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_KM)
+    D(0xb92f, KMC,     RRE,   MSA,  0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_KMC)
+    D(0xb93c, PPNO,    RRE,   MSA5, 0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_PPNO)
+    D(0xb93e, KIMD,    RRE,   MSA,  0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_KIMD)
+    D(0xb93f, KLMD,    RRE,   MSA,  0, 0, 0, 0, msa, 0, S390_FEAT_TYPE_KLMD)
+
 #ifndef CONFIG_USER_ONLY
 /* COMPARE AND SWAP AND PURGE */
     D(0xb250, CSP,     RRE,   Z,   r1_32u, ra2, r1_P, 0, csp, 0, MO_TEUL)
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index 7fc07a4..2d975b4 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -2480,6 +2480,58 @@  static ExitStatus op_iske(DisasContext *s, DisasOps *o)
 }
 #endif
 
+static ExitStatus op_msa(DisasContext *s, DisasOps *o)
+{
+    int r1 = have_field(s->fields, r1) ? get_field(s->fields, r1) : 0;
+    int r2 = have_field(s->fields, r2) ? get_field(s->fields, r2) : 0;
+    int r3 = have_field(s->fields, r3) ? get_field(s->fields, r3) : 0;
+    TCGv_i32 t_r1, t_r2, t_r3, type;
+
+    switch (s->insn->data) {
+    case S390_FEAT_TYPE_KMCTR:
+        if (r3 & 1 || !r3) {
+            gen_program_exception(s, PGM_SPECIFICATION);
+            return EXIT_NORETURN;
+        }
+        /* FALL THROUGH */
+    case S390_FEAT_TYPE_PPNO:
+    case S390_FEAT_TYPE_KMF:
+    case S390_FEAT_TYPE_KMC:
+    case S390_FEAT_TYPE_KMO:
+    case S390_FEAT_TYPE_KM:
+        if (r1 & 1 || !r1) {
+            gen_program_exception(s, PGM_SPECIFICATION);
+            return EXIT_NORETURN;
+        }
+        /* FALL THROUGH */
+    case S390_FEAT_TYPE_KMAC:
+    case S390_FEAT_TYPE_KIMD:
+    case S390_FEAT_TYPE_KLMD:
+        if (r2 & 1 || !r2) {
+            gen_program_exception(s, PGM_SPECIFICATION);
+            return EXIT_NORETURN;
+        }
+        /* FALL THROUGH */
+    case S390_FEAT_TYPE_PCKMO:
+    case S390_FEAT_TYPE_PCC:
+        break;
+    default:
+        g_assert_not_reached();
+    };
+
+    t_r1 = tcg_const_i32(r1);
+    t_r2 = tcg_const_i32(r2);
+    t_r3 = tcg_const_i32(r3);
+    type = tcg_const_i32(s->insn->data);
+    gen_helper_msa(cc_op, cpu_env, t_r1, t_r2, t_r3, type);
+    set_cc_static(s);
+    tcg_temp_free_i32(t_r1);
+    tcg_temp_free_i32(t_r2);
+    tcg_temp_free_i32(t_r3);
+    tcg_temp_free_i32(type);
+    return NO_EXIT;
+}
+
 static ExitStatus op_keb(DisasContext *s, DisasOps *o)
 {
     gen_helper_keb(cc_op, cpu_env, o->in1, o->in2);
@@ -5571,6 +5623,10 @@  enum DisasInsnEnum {
 #define FAC_PPA         S390_FEAT_STFLE_49 /* processor-assist */
 #define FAC_LZRB        S390_FEAT_STFLE_53 /* load-and-zero-rightmost-byte */
 #define FAC_ETF3        S390_FEAT_EXTENDED_TRANSLATION_3
+#define FAC_MSA         S390_FEAT_MSA /* message-security-assist facility */
+#define FAC_MSA3        S390_FEAT_MSA_EXT_3 /* msa-extension-3 facility */
+#define FAC_MSA4        S390_FEAT_MSA_EXT_4 /* msa-extension-4 facility */
+#define FAC_MSA5        S390_FEAT_MSA_EXT_5 /* msa-extension-5 facility */
 
 static const DisasInsn insn_info[] = {
 #include "insn-data.def"