diff mbox

[v2,1/9] target-s390: Add facilities data to env

Message ID 1380647845-16793-2-git-send-email-rth@twiddle.net
State New
Headers show

Commit Message

Richard Henderson Oct. 1, 2013, 5:17 p.m. UTC
Name the facilities bits, collect the set of bits for tcg and the various
real processor revisions.  Update the set of facilities reported for TCG.
Validate the insns we execute against the facilities enabled.  Report the
correct facilities via STFL.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 target-s390x/cpu.c       | 67 ++++++++++++++++++++++++++++++++++++++++++++++++
 target-s390x/cpu.h       | 60 +++++++++++++++++++++++++++++++++++++++++++
 target-s390x/translate.c | 66 +++++++++++++++++++++++++++--------------------
 3 files changed, 165 insertions(+), 28 deletions(-)
diff mbox

Patch

diff --git a/target-s390x/cpu.c b/target-s390x/cpu.c
index 3c89f8a..0cdddd3 100644
--- a/target-s390x/cpu.c
+++ b/target-s390x/cpu.c
@@ -152,6 +152,70 @@  static void s390_cpu_realizefn(DeviceState *dev, Error **errp)
     scc->parent_realize(dev, errp);
 }
 
+#define FAC0_TCG \
+    ( FAC_BIT(0, FAC_N3) \
+    | FAC_BIT(0, FAC_ZARCH) \
+    | FAC_BIT(0, FAC_ZARCH_ACTIVE) \
+    | FAC_BIT(0, FAC_STFLE) \
+    | FAC_BIT(0, FAC_LONG_DISPLACEMENT) \
+    | FAC_BIT(0, FAC_LONG_DISPLACEMENT_FAST) \
+    | FAC_BIT(0, FAC_EXTENDED_IMMEDIATE) \
+    | FAC_BIT(0, FAC_GENERAL_INSTRUCTIONS_EXT) \
+    | FAC_BIT(0, FAC_FLOATING_POINT_EXT) \
+    | FAC_BIT(0, FAC_FLOATING_POINT_SUPPPORT_ENH))
+    /* ??? We may have most of the collection of facilities at bit 45.  */
+
+/* ??? These lists of facilities gleaned from arch/s390/kernel/head.S.  */
+#define FAC0_Z900 \
+    ( FAC_BIT(0, FAC_N3) \
+    | FAC_BIT(0, FAC_ZARCH) \
+    | FAC_BIT(0, FAC_ZARCH_ACTIVE))
+
+#define FAC0_Z990 \
+    ( FAC0_Z900 \
+    | FAC_BIT(0, FAC_LONG_DISPLACEMENT) \
+    | FAC_BIT(0, FAC_LONG_DISPLACEMENT_FAST))
+
+#define FAC0_Z9_109 \
+    ( FAC0_Z990 \
+    | FAC_BIT(0, FAC_STFLE) \
+    | FAC_BIT(0, FAC_EXTENDED_TRANSLATION_2) \
+    | FAC_BIT(0, FAC_MESSAGE_SECURITY_ASSIST) \
+    | FAC_BIT(0, FAC_LONG_DISPLACEMENT) \
+    | FAC_BIT(0, FAC_LONG_DISPLACEMENT_FAST) \
+    | FAC_BIT(0, FAC_HFP_MADDSUB) \
+    | FAC_BIT(0, FAC_EXTENDED_IMMEDIATE) \
+    | FAC_BIT(0, FAC_EXTENDED_TRANSLATION_3) \
+    | FAC_BIT(0, FAC_HFP_UNNORMALIZED_EXT) \
+    | FAC_BIT(0, FAC_ETF2_ENH) \
+    | FAC_BIT(0, FAC_STORE_CLOCK_FAST) \
+    | FAC_BIT(0, FAC_ETF3_ENH) \
+    | FAC_BIT(0, FAC_EXTRACT_CPU_TIME))
+
+#define FAC0_Z10 \
+    ( FAC0_Z9_109 \
+    | FAC_BIT(0, FAC_COMPARE_AND_SWAP_AND_STORE) \
+    | FAC_BIT(0, FAC_COMPARE_AND_SWAP_AND_STORE_2) \
+    | FAC_BIT(0, FAC_GENERAL_INSTRUCTIONS_EXT) \
+    | FAC_BIT(0, FAC_EXECUTE_EXT) \
+    | FAC_BIT(0, FAC_FLOATING_POINT_SUPPPORT_ENH) \
+    | FAC_BIT(0, FAC_DFP) \
+    | FAC_BIT(0, FAC_PFPO))
+
+#define FAC0_Z196 \
+    ( FAC0_Z10 \
+    | FAC_BIT(0, FAC_FLOATING_POINT_EXT) \
+    | FAC_BIT(0, FAC_MULTI_45))
+
+#define FAC0_ZEC12 \
+    ( FAC0_Z196 \
+    | FAC_BIT(0, FAC_DFP_ZONED_CONVERSION) \
+    | FAC_BIT(0, FAC_MULTI_49) \
+    | FAC_BIT(0, FAC_CONSTRAINT_TRANSACTIONAL_EXE))
+#define FAC1_ZEC12 \
+    FAC_BIT(1, FAC_TRANSACTIONAL_EXE)
+
+
 static void s390_cpu_initfn(Object *obj)
 {
     CPUState *cs = CPU(obj);
@@ -181,6 +245,9 @@  static void s390_cpu_initfn(Object *obj)
     env->cpu_num = cpu_num++;
     env->ext_index = -1;
 
+    env->facilities[0] = FAC0_TCG;
+    env->facilities[1] = 0;
+
     if (tcg_enabled() && !inited) {
         inited = true;
         s390x_translate_init();
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h
index a2c077b..382c691 100644
--- a/target-s390x/cpu.h
+++ b/target-s390x/cpu.h
@@ -83,6 +83,65 @@  typedef struct MchkQueue {
 #define KVM_S390_RUNTIME_DIRTY_PARTIAL  1
 #define KVM_S390_RUNTIME_DIRTY_FULL     2
 
+typedef enum {
+    FAC_N3                              = 0,
+    FAC_ZARCH                           = 1,
+    FAC_ZARCH_ACTIVE                    = 2,
+    FAC_DAT_ENH                         = 3,
+    FAC_ASN_LX_REUSE                    = 6,
+    FAC_STFLE                           = 7,
+    FAC_ENHANCED_DAT_1                  = 8,
+    FAC_SENSE_RUNNING_STATUS            = 9,
+    FAC_CONDITIONAL_SSKE                = 10,
+    FAC_CONFIGURATION_TOPOLOGY          = 11,
+    FAC_IPTE_RANGE                      = 13,
+    FAC_NONQ_KEY_SETTING                = 14,
+    FAC_EXTENDED_TRANSLATION_2          = 16,
+    FAC_MESSAGE_SECURITY_ASSIST         = 17,
+    FAC_LONG_DISPLACEMENT               = 18,
+    FAC_LONG_DISPLACEMENT_FAST          = 19,
+    FAC_HFP_MADDSUB                     = 20,
+    FAC_EXTENDED_IMMEDIATE              = 21,
+    FAC_EXTENDED_TRANSLATION_3          = 22,
+    FAC_HFP_UNNORMALIZED_EXT            = 23,
+    FAC_ETF2_ENH                        = 24,
+    FAC_STORE_CLOCK_FAST                = 25,
+    FAC_PARSING_ENH                     = 26,
+    FAC_MOVE_WITH_OPTIONAL_SPEC         = 27,
+    FAC_TOD_CLOCK_STEERING              = 28,
+    FAC_ETF3_ENH                        = 30,
+    FAC_EXTRACT_CPU_TIME                = 31,
+    FAC_COMPARE_AND_SWAP_AND_STORE      = 32,
+    FAC_COMPARE_AND_SWAP_AND_STORE_2    = 33,
+    FAC_GENERAL_INSTRUCTIONS_EXT        = 34,
+    FAC_EXECUTE_EXT                     = 35,
+    FAC_ENHANCED_MONITOR                = 36,
+    FAC_FLOATING_POINT_EXT              = 37,
+    FAC_SET_PROGRAM_PARAMETERS          = 40,
+    FAC_FLOATING_POINT_SUPPPORT_ENH     = 41,
+    FAC_DFP                             = 42,
+    FAC_DFP_FAST                        = 43,
+    FAC_PFPO                            = 44,
+    FAC_MULTI_45                        = 45,
+    FAC_CMPSC_ENH                       = 47,
+    FAC_DFP_ZONED_CONVERSION            = 48,
+    FAC_MULTI_49                        = 49,
+    FAC_CONSTRAINT_TRANSACTIONAL_EXE    = 50,
+    FAC_LOCAL_TLB_CLEARING              = 51,
+    FAC_INTERLOCKED_ACCESS_2            = 52,
+    FAC_RESET_REFERENCE_BITS_MULTIPLE   = 66,
+    FAC_CPU_MEASUREMENT_COUNTER         = 67,
+    FAC_CPU_MEASUREMENT_SAMPLING        = 68,
+    FAC_TRANSACTIONAL_EXE               = 73,
+    FAC_ACCESS_EXCEPTION_FS_INDICATION  = 75,
+    FAC_MESSAGE_SECURITY_ASSIST_3       = 76,
+    FAC_MESSAGE_SECURITY_ASSIST_4       = 77,
+    FAC_ENHANCED_DAT_2                  = 78,
+} S390Facility;
+
+#define FAC_BIT(WORD, BIT)  (BIT / 64 == WORD ? 1ull << (63 - BIT % 64) : 0)
+
+
 typedef struct CPUS390XState {
     uint64_t regs[16];     /* GP registers */
     CPU_DoubleU fregs[16]; /* FP registers */
@@ -136,6 +195,7 @@  typedef struct CPUS390XState {
     CPU_COMMON
 
     /* reset does memset(0) up to here */
+    uint64_t facilities[2];
 
     int cpu_num;
     uint8_t *storage_keys;
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index afe90eb..2d555e2 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -53,6 +53,7 @@  struct DisasContext {
     const DisasInsn *insn;
     DisasFields *fields;
     uint64_t pc, next_pc;
+    uint64_t fac0;
     enum cc_op cc_op;
     bool singlestep_enabled;
 };
@@ -1102,33 +1103,10 @@  typedef enum {
     EXIT_NORETURN,
 } ExitStatus;
 
-typedef enum DisasFacility {
-    FAC_Z,                  /* zarch (default) */
-    FAC_CASS,               /* compare and swap and store */
-    FAC_CASS2,              /* compare and swap and store 2*/
-    FAC_DFP,                /* decimal floating point */
-    FAC_DFPR,               /* decimal floating point rounding */
-    FAC_DO,                 /* distinct operands */
-    FAC_EE,                 /* execute extensions */
-    FAC_EI,                 /* extended immediate */
-    FAC_FPE,                /* floating point extension */
-    FAC_FPSSH,              /* floating point support sign handling */
-    FAC_FPRGR,              /* FPR-GR transfer */
-    FAC_GIE,                /* general instructions extension */
-    FAC_HFP_MA,             /* HFP multiply-and-add/subtract */
-    FAC_HW,                 /* high-word */
-    FAC_IEEEE_SIM,          /* IEEE exception sumilation */
-    FAC_LOC,                /* load/store on condition */
-    FAC_LD,                 /* long displacement */
-    FAC_PC,                 /* population count */
-    FAC_SCF,                /* store clock fast */
-    FAC_SFLE,               /* store facility list extended */
-} DisasFacility;
-
 struct DisasInsn {
     unsigned opc:16;
     DisasFormat fmt:8;
-    DisasFacility fac:8;
+    S390Facility fac:8;
     unsigned spec:8;
 
     const char *name;
@@ -3231,10 +3209,9 @@  static ExitStatus op_spt(DisasContext *s, DisasOps *o)
 static ExitStatus op_stfl(DisasContext *s, DisasOps *o)
 {
     TCGv_i64 f, a;
-    /* We really ought to have more complete indication of facilities
-       that we implement.  Address this when STFLE is implemented.  */
+
     check_privileged(s);
-    f = tcg_const_i64(0xc0000000);
+    f = tcg_const_i64(s->fac0 >> 32);
     a = tcg_const_i64(200);
     tcg_gen_qemu_st32(f, a, get_mem_index(s));
     tcg_temp_free_i64(f);
@@ -4434,6 +4411,28 @@  static void in2_i2_32u_shl(DisasContext *s, DisasFields *f, DisasOps *o)
 
 /* ====================================================================== */
 
+/* Abbreviations for facilities used in the table.  */
+#define DFAC_Z               FAC_ZARCH
+#define DFAC_CASS            FAC_COMPARE_AND_SWAP_AND_STORE
+#define DFAC_CASS2           FAC_COMPARE_AND_SWAP_AND_STORE_2
+#define DFAC_DFP             FAC_DFP
+#define DFAC_DFPR            FAC_FLOATING_POINT_SUPPPORT_ENH
+#define DFAC_DO              FAC_MULTI_45
+#define DFAC_EE              FAC_EXECUTE_EXT
+#define DFAC_EI              FAC_EXTENDED_IMMEDIATE
+#define DFAC_FPE             FAC_FLOATING_POINT_EXT
+#define DFAC_FPSSH           FAC_FLOATING_POINT_SUPPPORT_ENH
+#define DFAC_FPRGR           FAC_FLOATING_POINT_SUPPPORT_ENH
+#define DFAC_GIE             FAC_GENERAL_INSTRUCTIONS_EXT
+#define DFAC_HFP_MA          FAC_HFP_MADDSUB
+#define DFAC_HW              FAC_MULTI_45
+#define DFAC_IEEEE_SIM       FAC_FLOATING_POINT_SUPPPORT_ENH
+#define DFAC_LOC             FAC_MULTI_45
+#define DFAC_LD              FAC_LONG_DISPLACEMENT
+#define DFAC_PC              FAC_MULTI_45
+#define DFAC_SCF             FAC_STORE_CLOCK_FAST
+#define DFAC_SFLE            FAC_STFLE
+
 /* Find opc within the table of insns.  This is formulated as a switch
    statement so that (1) we get compile-time notice of cut-paste errors
    for duplicated opcodes, and (2) the compiler generates the binary
@@ -4452,7 +4451,7 @@  enum DisasInsnEnum {
 #define D(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D) {                       \
     .opc = OPC,                                                             \
     .fmt = FMT_##FT,                                                        \
-    .fac = FAC_##FC,                                                        \
+    .fac = DFAC_##FC,                                                        \
     .spec = SPEC_in1_##I1 | SPEC_in2_##I2 | SPEC_prep_##P | SPEC_wout_##W,  \
     .name = #NM,                                                            \
     .help_in1 = in1_##I1,                                                   \
@@ -4644,6 +4643,16 @@  static ExitStatus translate_one(CPUS390XState *env, DisasContext *s)
         return EXIT_NORETURN;
     }
 
+    /* Check for operation exceptions for insns that have been disabled.
+       Do this by shifting the facilities word0 up by the IBM big-endian
+       bit numbering, leaving the bit to be tested in the sign bit.
+       Note that TCG does not currently support any facilities in word1.  */
+    assert(insn->fac < 64);
+    if ((int64_t)(s->fac0 << insn->fac) >= 0) {
+        gen_program_exception(s, PGM_OPERATION);
+        return EXIT_NORETURN;
+    }
+
     /* Check for insn specification exceptions.  */
     if (insn->spec) {
         int spec = insn->spec, excp = 0, r;
@@ -4762,6 +4771,7 @@  static inline void gen_intermediate_code_internal(S390CPU *cpu,
     dc.tb = tb;
     dc.pc = pc_start;
     dc.cc_op = CC_OP_DYNAMIC;
+    dc.fac0 = env->facilities[0];
     do_debug = dc.singlestep_enabled = cs->singlestep_enabled;
 
     gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;