qemu/target/s390x/internal.h
<<
>>
Prefs
   1/*
   2 * s390x internal definitions and helpers
   3 *
   4 * Copyright (c) 2009 Ulrich Hecht
   5 *
   6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
   7 * See the COPYING file in the top-level directory.
   8 */
   9
  10#ifndef S390X_INTERNAL_H
  11#define S390X_INTERNAL_H
  12
  13#include "cpu.h"
  14
  15#ifndef CONFIG_USER_ONLY
  16typedef struct LowCore {
  17    /* prefix area: defined by architecture */
  18    uint32_t        ccw1[2];                  /* 0x000 */
  19    uint32_t        ccw2[4];                  /* 0x008 */
  20    uint8_t         pad1[0x80 - 0x18];        /* 0x018 */
  21    uint32_t        ext_params;               /* 0x080 */
  22    uint16_t        cpu_addr;                 /* 0x084 */
  23    uint16_t        ext_int_code;             /* 0x086 */
  24    uint16_t        svc_ilen;                 /* 0x088 */
  25    uint16_t        svc_code;                 /* 0x08a */
  26    uint16_t        pgm_ilen;                 /* 0x08c */
  27    uint16_t        pgm_code;                 /* 0x08e */
  28    uint32_t        data_exc_code;            /* 0x090 */
  29    uint16_t        mon_class_num;            /* 0x094 */
  30    uint16_t        per_perc_atmid;           /* 0x096 */
  31    uint64_t        per_address;              /* 0x098 */
  32    uint8_t         exc_access_id;            /* 0x0a0 */
  33    uint8_t         per_access_id;            /* 0x0a1 */
  34    uint8_t         op_access_id;             /* 0x0a2 */
  35    uint8_t         ar_access_id;             /* 0x0a3 */
  36    uint8_t         pad2[0xA8 - 0xA4];        /* 0x0a4 */
  37    uint64_t        trans_exc_code;           /* 0x0a8 */
  38    uint64_t        monitor_code;             /* 0x0b0 */
  39    uint16_t        subchannel_id;            /* 0x0b8 */
  40    uint16_t        subchannel_nr;            /* 0x0ba */
  41    uint32_t        io_int_parm;              /* 0x0bc */
  42    uint32_t        io_int_word;              /* 0x0c0 */
  43    uint8_t         pad3[0xc8 - 0xc4];        /* 0x0c4 */
  44    uint32_t        stfl_fac_list;            /* 0x0c8 */
  45    uint8_t         pad4[0xe8 - 0xcc];        /* 0x0cc */
  46    uint64_t        mcic;                     /* 0x0e8 */
  47    uint8_t         pad5[0xf4 - 0xf0];        /* 0x0f0 */
  48    uint32_t        external_damage_code;     /* 0x0f4 */
  49    uint64_t        failing_storage_address;  /* 0x0f8 */
  50    uint8_t         pad6[0x110 - 0x100];      /* 0x100 */
  51    uint64_t        per_breaking_event_addr;  /* 0x110 */
  52    uint8_t         pad7[0x120 - 0x118];      /* 0x118 */
  53    PSW             restart_old_psw;          /* 0x120 */
  54    PSW             external_old_psw;         /* 0x130 */
  55    PSW             svc_old_psw;              /* 0x140 */
  56    PSW             program_old_psw;          /* 0x150 */
  57    PSW             mcck_old_psw;             /* 0x160 */
  58    PSW             io_old_psw;               /* 0x170 */
  59    uint8_t         pad8[0x1a0 - 0x180];      /* 0x180 */
  60    PSW             restart_new_psw;          /* 0x1a0 */
  61    PSW             external_new_psw;         /* 0x1b0 */
  62    PSW             svc_new_psw;              /* 0x1c0 */
  63    PSW             program_new_psw;          /* 0x1d0 */
  64    PSW             mcck_new_psw;             /* 0x1e0 */
  65    PSW             io_new_psw;               /* 0x1f0 */
  66    uint8_t         pad13[0x11b0 - 0x200];    /* 0x200 */
  67
  68    uint64_t        mcesad;                    /* 0x11B0 */
  69
  70    /* 64 bit extparam used for pfault, diag 250 etc  */
  71    uint64_t        ext_params2;               /* 0x11B8 */
  72
  73    uint8_t         pad14[0x1200 - 0x11C0];    /* 0x11C0 */
  74
  75    /* System info area */
  76
  77    uint64_t        floating_pt_save_area[16]; /* 0x1200 */
  78    uint64_t        gpregs_save_area[16];      /* 0x1280 */
  79    uint32_t        st_status_fixed_logout[4]; /* 0x1300 */
  80    uint8_t         pad15[0x1318 - 0x1310];    /* 0x1310 */
  81    uint32_t        prefixreg_save_area;       /* 0x1318 */
  82    uint32_t        fpt_creg_save_area;        /* 0x131c */
  83    uint8_t         pad16[0x1324 - 0x1320];    /* 0x1320 */
  84    uint32_t        tod_progreg_save_area;     /* 0x1324 */
  85    uint64_t        cpu_timer_save_area;       /* 0x1328 */
  86    uint64_t        clock_comp_save_area;      /* 0x1330 */
  87    uint8_t         pad17[0x1340 - 0x1338];    /* 0x1338 */
  88    uint32_t        access_regs_save_area[16]; /* 0x1340 */
  89    uint64_t        cregs_save_area[16];       /* 0x1380 */
  90
  91    /* align to the top of the prefix area */
  92
  93    uint8_t         pad18[0x2000 - 0x1400];    /* 0x1400 */
  94} QEMU_PACKED LowCore;
  95QEMU_BUILD_BUG_ON(sizeof(LowCore) != 8192);
  96#endif /* CONFIG_USER_ONLY */
  97
  98#define MAX_ILEN 6
  99
 100/* While the PoO talks about ILC (a number between 1-3) what is actually
 101   stored in LowCore is shifted left one bit (an even between 2-6).  As
 102   this is the actual length of the insn and therefore more useful, that
 103   is what we want to pass around and manipulate.  To make sure that we
 104   have applied this distinction universally, rename the "ILC" to "ILEN".  */
 105static inline int get_ilen(uint8_t opc)
 106{
 107    switch (opc >> 6) {
 108    case 0:
 109        return 2;
 110    case 1:
 111    case 2:
 112        return 4;
 113    default:
 114        return 6;
 115    }
 116}
 117
 118/* Compute the ATMID field that is stored in the per_perc_atmid lowcore
 119   entry when a PER exception is triggered.  */
 120static inline uint8_t get_per_atmid(CPUS390XState *env)
 121{
 122    return ((env->psw.mask & PSW_MASK_64) ?       (1 << 7) : 0) |
 123                                                  (1 << 6)      |
 124           ((env->psw.mask & PSW_MASK_32) ?       (1 << 5) : 0) |
 125           ((env->psw.mask & PSW_MASK_DAT) ?      (1 << 4) : 0) |
 126           ((env->psw.mask & PSW_ASC_SECONDARY) ? (1 << 3) : 0) |
 127           ((env->psw.mask & PSW_ASC_ACCREG) ?    (1 << 2) : 0);
 128}
 129
 130static inline uint64_t wrap_address(CPUS390XState *env, uint64_t a)
 131{
 132    if (!(env->psw.mask & PSW_MASK_64)) {
 133        if (!(env->psw.mask & PSW_MASK_32)) {
 134            /* 24-Bit mode */
 135            a &= 0x00ffffff;
 136        } else {
 137            /* 31-Bit mode */
 138            a &= 0x7fffffff;
 139        }
 140    }
 141    return a;
 142}
 143
 144/* CC optimization */
 145
 146/* Instead of computing the condition codes after each x86 instruction,
 147 * QEMU just stores the result (called CC_DST), the type of operation
 148 * (called CC_OP) and whatever operands are needed (CC_SRC and possibly
 149 * CC_VR). When the condition codes are needed, the condition codes can
 150 * be calculated using this information. Condition codes are not generated
 151 * if they are only needed for conditional branches.
 152 */
 153enum cc_op {
 154    CC_OP_CONST0 = 0,           /* CC is 0 */
 155    CC_OP_CONST1,               /* CC is 1 */
 156    CC_OP_CONST2,               /* CC is 2 */
 157    CC_OP_CONST3,               /* CC is 3 */
 158
 159    CC_OP_DYNAMIC,              /* CC calculation defined by env->cc_op */
 160    CC_OP_STATIC,               /* CC value is env->cc_op */
 161
 162    CC_OP_NZ,                   /* env->cc_dst != 0 */
 163    CC_OP_LTGT_32,              /* signed less/greater than (32bit) */
 164    CC_OP_LTGT_64,              /* signed less/greater than (64bit) */
 165    CC_OP_LTUGTU_32,            /* unsigned less/greater than (32bit) */
 166    CC_OP_LTUGTU_64,            /* unsigned less/greater than (64bit) */
 167    CC_OP_LTGT0_32,             /* signed less/greater than 0 (32bit) */
 168    CC_OP_LTGT0_64,             /* signed less/greater than 0 (64bit) */
 169
 170    CC_OP_ADD_64,               /* overflow on add (64bit) */
 171    CC_OP_ADDU_64,              /* overflow on unsigned add (64bit) */
 172    CC_OP_ADDC_64,              /* overflow on unsigned add-carry (64bit) */
 173    CC_OP_SUB_64,               /* overflow on subtraction (64bit) */
 174    CC_OP_SUBU_64,              /* overflow on unsigned subtraction (64bit) */
 175    CC_OP_SUBB_64,              /* overflow on unsigned sub-borrow (64bit) */
 176    CC_OP_ABS_64,               /* sign eval on abs (64bit) */
 177    CC_OP_NABS_64,              /* sign eval on nabs (64bit) */
 178
 179    CC_OP_ADD_32,               /* overflow on add (32bit) */
 180    CC_OP_ADDU_32,              /* overflow on unsigned add (32bit) */
 181    CC_OP_ADDC_32,              /* overflow on unsigned add-carry (32bit) */
 182    CC_OP_SUB_32,               /* overflow on subtraction (32bit) */
 183    CC_OP_SUBU_32,              /* overflow on unsigned subtraction (32bit) */
 184    CC_OP_SUBB_32,              /* overflow on unsigned sub-borrow (32bit) */
 185    CC_OP_ABS_32,               /* sign eval on abs (64bit) */
 186    CC_OP_NABS_32,              /* sign eval on nabs (64bit) */
 187
 188    CC_OP_COMP_32,              /* complement */
 189    CC_OP_COMP_64,              /* complement */
 190
 191    CC_OP_TM_32,                /* test under mask (32bit) */
 192    CC_OP_TM_64,                /* test under mask (64bit) */
 193
 194    CC_OP_NZ_F32,               /* FP dst != 0 (32bit) */
 195    CC_OP_NZ_F64,               /* FP dst != 0 (64bit) */
 196    CC_OP_NZ_F128,              /* FP dst != 0 (128bit) */
 197
 198    CC_OP_ICM,                  /* insert characters under mask */
 199    CC_OP_SLA_32,               /* Calculate shift left signed (32bit) */
 200    CC_OP_SLA_64,               /* Calculate shift left signed (64bit) */
 201    CC_OP_FLOGR,                /* find leftmost one */
 202    CC_OP_LCBB,                 /* load count to block boundary */
 203    CC_OP_MAX
 204};
 205
 206static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb,
 207                                       uint8_t *ar)
 208{
 209    hwaddr addr = 0;
 210    uint8_t reg;
 211
 212    reg = ipb >> 28;
 213    if (reg > 0) {
 214        addr = env->regs[reg];
 215    }
 216    addr += (ipb >> 16) & 0xfff;
 217    if (ar) {
 218        *ar = reg;
 219    }
 220
 221    return addr;
 222}
 223
 224/* Base/displacement are at the same locations. */
 225#define decode_basedisp_rs decode_basedisp_s
 226
 227/* arch_dump.c */
 228int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
 229                              int cpuid, void *opaque);
 230
 231
 232/* cc_helper.c */
 233const char *cc_name(enum cc_op cc_op);
 234void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr);
 235uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
 236                 uint64_t vr);
 237
 238
 239/* cpu.c */
 240#ifndef CONFIG_USER_ONLY
 241unsigned int s390_cpu_halt(S390CPU *cpu);
 242void s390_cpu_unhalt(S390CPU *cpu);
 243#else
 244static inline unsigned int s390_cpu_halt(S390CPU *cpu)
 245{
 246    return 0;
 247}
 248
 249static inline void s390_cpu_unhalt(S390CPU *cpu)
 250{
 251}
 252#endif /* CONFIG_USER_ONLY */
 253
 254
 255/* cpu_models.c */
 256void s390_cpu_model_register_props(Object *obj);
 257void s390_cpu_model_class_register_props(ObjectClass *oc);
 258void s390_realize_cpu_model(CPUState *cs, Error **errp);
 259ObjectClass *s390_cpu_class_by_name(const char *name);
 260
 261
 262/* excp_helper.c */
 263void s390x_cpu_debug_excp_handler(CPUState *cs);
 264void s390_cpu_do_interrupt(CPUState *cpu);
 265bool s390_cpu_exec_interrupt(CPUState *cpu, int int_req);
 266int s390_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw,
 267                              int mmu_idx);
 268void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
 269                                   MMUAccessType access_type,
 270                                   int mmu_idx, uintptr_t retaddr);
 271
 272
 273/* fpu_helper.c */
 274uint32_t set_cc_nz_f32(float32 v);
 275uint32_t set_cc_nz_f64(float64 v);
 276uint32_t set_cc_nz_f128(float128 v);
 277#define S390_IEEE_MASK_INVALID   0x80
 278#define S390_IEEE_MASK_DIVBYZERO 0x40
 279#define S390_IEEE_MASK_OVERFLOW  0x20
 280#define S390_IEEE_MASK_UNDERFLOW 0x10
 281#define S390_IEEE_MASK_INEXACT   0x08
 282#define S390_IEEE_MASK_QUANTUM   0x04
 283uint8_t s390_softfloat_exc_to_ieee(unsigned int exc);
 284int s390_swap_bfp_rounding_mode(CPUS390XState *env, int m3);
 285void s390_restore_bfp_rounding_mode(CPUS390XState *env, int old_mode);
 286
 287
 288/* gdbstub.c */
 289int s390_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
 290int s390_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 291void s390_cpu_gdb_init(CPUState *cs);
 292
 293
 294/* helper.c */
 295void s390_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
 296                         int flags);
 297hwaddr s390_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 298hwaddr s390_cpu_get_phys_addr_debug(CPUState *cpu, vaddr addr);
 299uint64_t get_psw_mask(CPUS390XState *env);
 300void s390_cpu_recompute_watchpoints(CPUState *cs);
 301void s390x_tod_timer(void *opaque);
 302void s390x_cpu_timer(void *opaque);
 303void do_restart_interrupt(CPUS390XState *env);
 304void s390_handle_wait(S390CPU *cpu);
 305#define S390_STORE_STATUS_DEF_ADDR offsetof(LowCore, floating_pt_save_area)
 306int s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch);
 307int s390_store_adtl_status(S390CPU *cpu, hwaddr addr, hwaddr len);
 308#ifndef CONFIG_USER_ONLY
 309LowCore *cpu_map_lowcore(CPUS390XState *env);
 310void cpu_unmap_lowcore(LowCore *lowcore);
 311#endif /* CONFIG_USER_ONLY */
 312
 313
 314/* interrupt.c */
 315void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ilen);
 316void cpu_inject_clock_comparator(S390CPU *cpu);
 317void cpu_inject_cpu_timer(S390CPU *cpu);
 318void cpu_inject_emergency_signal(S390CPU *cpu, uint16_t src_cpu_addr);
 319int cpu_inject_external_call(S390CPU *cpu, uint16_t src_cpu_addr);
 320bool s390_cpu_has_io_int(S390CPU *cpu);
 321bool s390_cpu_has_ext_int(S390CPU *cpu);
 322bool s390_cpu_has_mcck_int(S390CPU *cpu);
 323bool s390_cpu_has_int(S390CPU *cpu);
 324bool s390_cpu_has_restart_int(S390CPU *cpu);
 325bool s390_cpu_has_stop_int(S390CPU *cpu);
 326void cpu_inject_restart(S390CPU *cpu);
 327void cpu_inject_stop(S390CPU *cpu);
 328
 329
 330/* ioinst.c */
 331void ioinst_handle_xsch(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
 332void ioinst_handle_csch(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
 333void ioinst_handle_hsch(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
 334void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb,
 335                        uintptr_t ra);
 336void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb,
 337                        uintptr_t ra);
 338void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb, uintptr_t ra);
 339void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb,
 340                         uintptr_t ra);
 341int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra);
 342void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb, uintptr_t ra);
 343void ioinst_handle_schm(S390CPU *cpu, uint64_t reg1, uint64_t reg2,
 344                        uint32_t ipb, uintptr_t ra);
 345void ioinst_handle_rsch(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
 346void ioinst_handle_rchp(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
 347void ioinst_handle_sal(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
 348
 349
 350/* mem_helper.c */
 351target_ulong mmu_real2abs(CPUS390XState *env, target_ulong raddr);
 352void probe_write_access(CPUS390XState *env, uint64_t addr, uint64_t len,
 353                        uintptr_t ra);
 354
 355
 356/* mmu_helper.c */
 357int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
 358                  target_ulong *raddr, int *flags, bool exc);
 359int mmu_translate_real(CPUS390XState *env, target_ulong raddr, int rw,
 360                       target_ulong *addr, int *flags);
 361
 362
 363/* misc_helper.c */
 364int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3);
 365void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3,
 366                     uintptr_t ra);
 367
 368
 369/* translate.c */
 370void s390x_translate_init(void);
 371
 372
 373/* sigp.c */
 374int handle_sigp(CPUS390XState *env, uint8_t order, uint64_t r1, uint64_t r3);
 375void do_stop_interrupt(CPUS390XState *env);
 376
 377#endif /* S390X_INTERNAL_H */
 378