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