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    PSW             return_psw;               /* 0x200 */
  67    uint8_t         irb[64];                  /* 0x210 */
  68    uint64_t        sync_enter_timer;         /* 0x250 */
  69    uint64_t        async_enter_timer;        /* 0x258 */
  70    uint64_t        exit_timer;               /* 0x260 */
  71    uint64_t        last_update_timer;        /* 0x268 */
  72    uint64_t        user_timer;               /* 0x270 */
  73    uint64_t        system_timer;             /* 0x278 */
  74    uint64_t        last_update_clock;        /* 0x280 */
  75    uint64_t        steal_clock;              /* 0x288 */
  76    PSW             return_mcck_psw;          /* 0x290 */
  77    uint8_t         pad9[0xc00 - 0x2a0];      /* 0x2a0 */
  78    /* System info area */
  79    uint64_t        save_area[16];            /* 0xc00 */
  80    uint8_t         pad10[0xd40 - 0xc80];     /* 0xc80 */
  81    uint64_t        kernel_stack;             /* 0xd40 */
  82    uint64_t        thread_info;              /* 0xd48 */
  83    uint64_t        async_stack;              /* 0xd50 */
  84    uint64_t        kernel_asce;              /* 0xd58 */
  85    uint64_t        user_asce;                /* 0xd60 */
  86    uint64_t        panic_stack;              /* 0xd68 */
  87    uint64_t        user_exec_asce;           /* 0xd70 */
  88    uint8_t         pad11[0xdc0 - 0xd78];     /* 0xd78 */
  89
  90    /* SMP info area: defined by DJB */
  91    uint64_t        clock_comparator;         /* 0xdc0 */
  92    uint64_t        ext_call_fast;            /* 0xdc8 */
  93    uint64_t        percpu_offset;            /* 0xdd0 */
  94    uint64_t        current_task;             /* 0xdd8 */
  95    uint32_t        softirq_pending;          /* 0xde0 */
  96    uint32_t        pad_0x0de4;               /* 0xde4 */
  97    uint64_t        int_clock;                /* 0xde8 */
  98    uint8_t         pad12[0xe00 - 0xdf0];     /* 0xdf0 */
  99
 100    /* 0xe00 is used as indicator for dump tools */
 101    /* whether the kernel died with panic() or not */
 102    uint32_t        panic_magic;              /* 0xe00 */
 103
 104    uint8_t         pad13[0x11b8 - 0xe04];    /* 0xe04 */
 105
 106    /* 64 bit extparam used for pfault, diag 250 etc  */
 107    uint64_t        ext_params2;               /* 0x11B8 */
 108
 109    uint8_t         pad14[0x1200 - 0x11C0];    /* 0x11C0 */
 110
 111    /* System info area */
 112
 113    uint64_t        floating_pt_save_area[16]; /* 0x1200 */
 114    uint64_t        gpregs_save_area[16];      /* 0x1280 */
 115    uint32_t        st_status_fixed_logout[4]; /* 0x1300 */
 116    uint8_t         pad15[0x1318 - 0x1310];    /* 0x1310 */
 117    uint32_t        prefixreg_save_area;       /* 0x1318 */
 118    uint32_t        fpt_creg_save_area;        /* 0x131c */
 119    uint8_t         pad16[0x1324 - 0x1320];    /* 0x1320 */
 120    uint32_t        tod_progreg_save_area;     /* 0x1324 */
 121    uint64_t        cpu_timer_save_area;       /* 0x1328 */
 122    uint64_t        clock_comp_save_area;      /* 0x1330 */
 123    uint8_t         pad17[0x1340 - 0x1338];    /* 0x1338 */
 124    uint32_t        access_regs_save_area[16]; /* 0x1340 */
 125    uint64_t        cregs_save_area[16];       /* 0x1380 */
 126
 127    /* align to the top of the prefix area */
 128
 129    uint8_t         pad18[0x2000 - 0x1400];    /* 0x1400 */
 130} QEMU_PACKED LowCore;
 131#endif /* CONFIG_USER_ONLY */
 132
 133#define MAX_ILEN 6
 134
 135/* While the PoO talks about ILC (a number between 1-3) what is actually
 136   stored in LowCore is shifted left one bit (an even between 2-6).  As
 137   this is the actual length of the insn and therefore more useful, that
 138   is what we want to pass around and manipulate.  To make sure that we
 139   have applied this distinction universally, rename the "ILC" to "ILEN".  */
 140static inline int get_ilen(uint8_t opc)
 141{
 142    switch (opc >> 6) {
 143    case 0:
 144        return 2;
 145    case 1:
 146    case 2:
 147        return 4;
 148    default:
 149        return 6;
 150    }
 151}
 152
 153/* Compute the ATMID field that is stored in the per_perc_atmid lowcore
 154   entry when a PER exception is triggered.  */
 155static inline uint8_t get_per_atmid(CPUS390XState *env)
 156{
 157    return ((env->psw.mask & PSW_MASK_64) ?       (1 << 7) : 0) |
 158                                                  (1 << 6)      |
 159           ((env->psw.mask & PSW_MASK_32) ?       (1 << 5) : 0) |
 160           ((env->psw.mask & PSW_MASK_DAT) ?      (1 << 4) : 0) |
 161           ((env->psw.mask & PSW_ASC_SECONDARY) ? (1 << 3) : 0) |
 162           ((env->psw.mask & PSW_ASC_ACCREG) ?    (1 << 2) : 0);
 163}
 164
 165static inline uint64_t wrap_address(CPUS390XState *env, uint64_t a)
 166{
 167    if (!(env->psw.mask & PSW_MASK_64)) {
 168        if (!(env->psw.mask & PSW_MASK_32)) {
 169            /* 24-Bit mode */
 170            a &= 0x00ffffff;
 171        } else {
 172            /* 31-Bit mode */
 173            a &= 0x7fffffff;
 174        }
 175    }
 176    return a;
 177}
 178
 179/* CC optimization */
 180
 181/* Instead of computing the condition codes after each x86 instruction,
 182 * QEMU just stores the result (called CC_DST), the type of operation
 183 * (called CC_OP) and whatever operands are needed (CC_SRC and possibly
 184 * CC_VR). When the condition codes are needed, the condition codes can
 185 * be calculated using this information. Condition codes are not generated
 186 * if they are only needed for conditional branches.
 187 */
 188enum cc_op {
 189    CC_OP_CONST0 = 0,           /* CC is 0 */
 190    CC_OP_CONST1,               /* CC is 1 */
 191    CC_OP_CONST2,               /* CC is 2 */
 192    CC_OP_CONST3,               /* CC is 3 */
 193
 194    CC_OP_DYNAMIC,              /* CC calculation defined by env->cc_op */
 195    CC_OP_STATIC,               /* CC value is env->cc_op */
 196
 197    CC_OP_NZ,                   /* env->cc_dst != 0 */
 198    CC_OP_LTGT_32,              /* signed less/greater than (32bit) */
 199    CC_OP_LTGT_64,              /* signed less/greater than (64bit) */
 200    CC_OP_LTUGTU_32,            /* unsigned less/greater than (32bit) */
 201    CC_OP_LTUGTU_64,            /* unsigned less/greater than (64bit) */
 202    CC_OP_LTGT0_32,             /* signed less/greater than 0 (32bit) */
 203    CC_OP_LTGT0_64,             /* signed less/greater than 0 (64bit) */
 204
 205    CC_OP_ADD_64,               /* overflow on add (64bit) */
 206    CC_OP_ADDU_64,              /* overflow on unsigned add (64bit) */
 207    CC_OP_ADDC_64,              /* overflow on unsigned add-carry (64bit) */
 208    CC_OP_SUB_64,               /* overflow on subtraction (64bit) */
 209    CC_OP_SUBU_64,              /* overflow on unsigned subtraction (64bit) */
 210    CC_OP_SUBB_64,              /* overflow on unsigned sub-borrow (64bit) */
 211    CC_OP_ABS_64,               /* sign eval on abs (64bit) */
 212    CC_OP_NABS_64,              /* sign eval on nabs (64bit) */
 213
 214    CC_OP_ADD_32,               /* overflow on add (32bit) */
 215    CC_OP_ADDU_32,              /* overflow on unsigned add (32bit) */
 216    CC_OP_ADDC_32,              /* overflow on unsigned add-carry (32bit) */
 217    CC_OP_SUB_32,               /* overflow on subtraction (32bit) */
 218    CC_OP_SUBU_32,              /* overflow on unsigned subtraction (32bit) */
 219    CC_OP_SUBB_32,              /* overflow on unsigned sub-borrow (32bit) */
 220    CC_OP_ABS_32,               /* sign eval on abs (64bit) */
 221    CC_OP_NABS_32,              /* sign eval on nabs (64bit) */
 222
 223    CC_OP_COMP_32,              /* complement */
 224    CC_OP_COMP_64,              /* complement */
 225
 226    CC_OP_TM_32,                /* test under mask (32bit) */
 227    CC_OP_TM_64,                /* test under mask (64bit) */
 228
 229    CC_OP_NZ_F32,               /* FP dst != 0 (32bit) */
 230    CC_OP_NZ_F64,               /* FP dst != 0 (64bit) */
 231    CC_OP_NZ_F128,              /* FP dst != 0 (128bit) */
 232
 233    CC_OP_ICM,                  /* insert characters under mask */
 234    CC_OP_SLA_32,               /* Calculate shift left signed (32bit) */
 235    CC_OP_SLA_64,               /* Calculate shift left signed (64bit) */
 236    CC_OP_FLOGR,                /* find leftmost one */
 237    CC_OP_MAX
 238};
 239
 240/* The value of the TOD clock for 1.1.1970. */
 241#define TOD_UNIX_EPOCH 0x7d91048bca000000ULL
 242
 243/* Converts ns to s390's clock format */
 244static inline uint64_t time2tod(uint64_t ns)
 245{
 246    return (ns << 9) / 125;
 247}
 248
 249/* Converts s390's clock format to ns */
 250static inline uint64_t tod2time(uint64_t t)
 251{
 252    return (t * 125) >> 9;
 253}
 254
 255static inline hwaddr decode_basedisp_s(CPUS390XState *env, uint32_t ipb,
 256                                       uint8_t *ar)
 257{
 258    hwaddr addr = 0;
 259    uint8_t reg;
 260
 261    reg = ipb >> 28;
 262    if (reg > 0) {
 263        addr = env->regs[reg];
 264    }
 265    addr += (ipb >> 16) & 0xfff;
 266    if (ar) {
 267        *ar = reg;
 268    }
 269
 270    return addr;
 271}
 272
 273/* Base/displacement are at the same locations. */
 274#define decode_basedisp_rs decode_basedisp_s
 275
 276static inline void s390_do_cpu_full_reset(CPUState *cs, run_on_cpu_data arg)
 277{
 278    cpu_reset(cs);
 279}
 280
 281
 282/* arch_dump.c */
 283int s390_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
 284                              int cpuid, void *opaque);
 285
 286
 287/* cc_helper.c */
 288const char *cc_name(enum cc_op cc_op);
 289void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr);
 290uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst,
 291                 uint64_t vr);
 292
 293
 294/* cpu.c */
 295#ifndef CONFIG_USER_ONLY
 296unsigned int s390_cpu_halt(S390CPU *cpu);
 297void s390_cpu_unhalt(S390CPU *cpu);
 298#else
 299static inline unsigned int s390_cpu_halt(S390CPU *cpu)
 300{
 301    return 0;
 302}
 303
 304static inline void s390_cpu_unhalt(S390CPU *cpu)
 305{
 306}
 307#endif /* CONFIG_USER_ONLY */
 308
 309
 310/* cpu_models.c */
 311void s390_cpu_model_register_props(Object *obj);
 312void s390_cpu_model_class_register_props(ObjectClass *oc);
 313void s390_realize_cpu_model(CPUState *cs, Error **errp);
 314ObjectClass *s390_cpu_class_by_name(const char *name);
 315
 316
 317/* excp_helper.c */
 318void s390x_cpu_debug_excp_handler(CPUState *cs);
 319void s390_cpu_do_interrupt(CPUState *cpu);
 320bool s390_cpu_exec_interrupt(CPUState *cpu, int int_req);
 321int s390_cpu_handle_mmu_fault(CPUState *cpu, vaddr address, int size, int rw,
 322                              int mmu_idx);
 323void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
 324                                   MMUAccessType access_type,
 325                                   int mmu_idx, uintptr_t retaddr);
 326
 327
 328/* fpu_helper.c */
 329uint32_t set_cc_nz_f32(float32 v);
 330uint32_t set_cc_nz_f64(float64 v);
 331uint32_t set_cc_nz_f128(float128 v);
 332
 333
 334/* gdbstub.c */
 335int s390_cpu_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
 336int s390_cpu_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 337void s390_cpu_gdb_init(CPUState *cs);
 338
 339
 340/* helper.c */
 341void s390_cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
 342                         int flags);
 343hwaddr s390_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
 344hwaddr s390_cpu_get_phys_addr_debug(CPUState *cpu, vaddr addr);
 345uint64_t get_psw_mask(CPUS390XState *env);
 346void s390_cpu_recompute_watchpoints(CPUState *cs);
 347void s390x_tod_timer(void *opaque);
 348void s390x_cpu_timer(void *opaque);
 349void do_restart_interrupt(CPUS390XState *env);
 350void s390_handle_wait(S390CPU *cpu);
 351#define S390_STORE_STATUS_DEF_ADDR offsetof(LowCore, floating_pt_save_area)
 352int s390_store_status(S390CPU *cpu, hwaddr addr, bool store_arch);
 353int s390_store_adtl_status(S390CPU *cpu, hwaddr addr, hwaddr len);
 354#ifndef CONFIG_USER_ONLY
 355LowCore *cpu_map_lowcore(CPUS390XState *env);
 356void cpu_unmap_lowcore(LowCore *lowcore);
 357#endif /* CONFIG_USER_ONLY */
 358
 359
 360/* interrupt.c */
 361void trigger_pgm_exception(CPUS390XState *env, uint32_t code, uint32_t ilen);
 362void cpu_inject_clock_comparator(S390CPU *cpu);
 363void cpu_inject_cpu_timer(S390CPU *cpu);
 364void cpu_inject_emergency_signal(S390CPU *cpu, uint16_t src_cpu_addr);
 365int cpu_inject_external_call(S390CPU *cpu, uint16_t src_cpu_addr);
 366bool s390_cpu_has_io_int(S390CPU *cpu);
 367bool s390_cpu_has_ext_int(S390CPU *cpu);
 368bool s390_cpu_has_mcck_int(S390CPU *cpu);
 369bool s390_cpu_has_int(S390CPU *cpu);
 370bool s390_cpu_has_restart_int(S390CPU *cpu);
 371bool s390_cpu_has_stop_int(S390CPU *cpu);
 372void cpu_inject_restart(S390CPU *cpu);
 373void cpu_inject_stop(S390CPU *cpu);
 374
 375
 376/* ioinst.c */
 377void ioinst_handle_xsch(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
 378void ioinst_handle_csch(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
 379void ioinst_handle_hsch(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
 380void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb,
 381                        uintptr_t ra);
 382void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb,
 383                        uintptr_t ra);
 384void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb, uintptr_t ra);
 385void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb,
 386                         uintptr_t ra);
 387int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra);
 388void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb, uintptr_t ra);
 389void ioinst_handle_schm(S390CPU *cpu, uint64_t reg1, uint64_t reg2,
 390                        uint32_t ipb, uintptr_t ra);
 391void ioinst_handle_rsch(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
 392void ioinst_handle_rchp(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
 393void ioinst_handle_sal(S390CPU *cpu, uint64_t reg1, uintptr_t ra);
 394
 395
 396/* mem_helper.c */
 397target_ulong mmu_real2abs(CPUS390XState *env, target_ulong raddr);
 398
 399
 400/* mmu_helper.c */
 401int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
 402                  target_ulong *raddr, int *flags, bool exc);
 403int mmu_translate_real(CPUS390XState *env, target_ulong raddr, int rw,
 404                       target_ulong *addr, int *flags);
 405
 406
 407/* misc_helper.c */
 408int handle_diag_288(CPUS390XState *env, uint64_t r1, uint64_t r3);
 409void handle_diag_308(CPUS390XState *env, uint64_t r1, uint64_t r3,
 410                     uintptr_t ra);
 411
 412
 413/* translate.c */
 414void s390x_translate_init(void);
 415
 416
 417/* sigp.c */
 418int handle_sigp(CPUS390XState *env, uint8_t order, uint64_t r1, uint64_t r3);
 419void do_stop_interrupt(CPUS390XState *env);
 420
 421#endif /* S390X_INTERNAL_H */
 422