diff options
Diffstat (limited to 'target-s390x')
-rw-r--r-- | target-s390x/cpu.h | 13 | ||||
-rw-r--r-- | target-s390x/helper.h | 76 | ||||
-rw-r--r-- | target-s390x/kvm.c | 117 | ||||
-rw-r--r-- | target-s390x/misc_helper.c | 45 |
4 files changed, 133 insertions, 118 deletions
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 9997765dd1..5be6e83528 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -596,17 +596,6 @@ static inline const char *cc_name(int cc_op) return cc_names[cc_op]; } -/* SCLP PV interface defines */ -#define SCLP_CMDW_READ_SCP_INFO 0x00020001 -#define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001 - -#define SCP_LENGTH 0x00 -#define SCP_FUNCTION_CODE 0x02 -#define SCP_CONTROL_MASK 0x03 -#define SCP_RESPONSE_CODE 0x06 -#define SCP_MEM_CODE 0x08 -#define SCP_INCREMENT 0x0a - typedef struct LowCore { /* prefix area: defined by architecture */ @@ -955,7 +944,7 @@ static inline void ebcdic_put(uint8_t *p, const char *ascii, int len) void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr); int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc, target_ulong *raddr, int *flags); -int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code); +int sclp_service_call(uint32_t sccb, uint64_t code); uint32_t calc_cc(CPUS390XState *env, uint32_t cc_op, uint64_t src, uint64_t dst, uint64_t vr); diff --git a/target-s390x/helper.h b/target-s390x/helper.h index 5419f37dca..ac44eabd53 100644 --- a/target-s390x/helper.h +++ b/target-s390x/helper.h @@ -7,21 +7,21 @@ DEF_HELPER_4(xc, i32, env, i32, i64, i64) DEF_HELPER_4(mvc, void, env, i32, i64, i64) DEF_HELPER_4(clc, i32, env, i32, i64, i64) DEF_HELPER_3(mvcl, i32, env, i32, i32) -DEF_HELPER_FLAGS_1(set_cc_comp_s32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32) -DEF_HELPER_FLAGS_1(set_cc_comp_s64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64) -DEF_HELPER_FLAGS_2(set_cc_icm, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32) +DEF_HELPER_FLAGS_1(set_cc_comp_s32, TCG_CALL_NO_RWG_SE, i32, s32) +DEF_HELPER_FLAGS_1(set_cc_comp_s64, TCG_CALL_NO_RWG_SE, i32, s64) +DEF_HELPER_FLAGS_2(set_cc_icm, TCG_CALL_NO_RWG_SE, i32, i32, i32) DEF_HELPER_4(clm, i32, env, i32, i32, i64) DEF_HELPER_4(stcm, void, env, i32, i32, i64) DEF_HELPER_3(mlg, void, env, i32, i64) DEF_HELPER_3(dlg, void, env, i32, i64) -DEF_HELPER_FLAGS_3(set_cc_add64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64, s64, s64) -DEF_HELPER_FLAGS_3(set_cc_addu64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64) -DEF_HELPER_FLAGS_3(set_cc_add32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32, s32, s32) -DEF_HELPER_FLAGS_3(set_cc_addu32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32, i32) -DEF_HELPER_FLAGS_3(set_cc_sub64, TCG_CALL_PURE|TCG_CALL_CONST, i32, s64, s64, s64) -DEF_HELPER_FLAGS_3(set_cc_subu64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64) -DEF_HELPER_FLAGS_3(set_cc_sub32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32, s32, s32) -DEF_HELPER_FLAGS_3(set_cc_subu32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32, i32) +DEF_HELPER_FLAGS_3(set_cc_add64, TCG_CALL_NO_RWG_SE, i32, s64, s64, s64) +DEF_HELPER_FLAGS_3(set_cc_addu64, TCG_CALL_NO_RWG_SE, i32, i64, i64, i64) +DEF_HELPER_FLAGS_3(set_cc_add32, TCG_CALL_NO_RWG_SE, i32, s32, s32, s32) +DEF_HELPER_FLAGS_3(set_cc_addu32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) +DEF_HELPER_FLAGS_3(set_cc_sub64, TCG_CALL_NO_RWG_SE, i32, s64, s64, s64) +DEF_HELPER_FLAGS_3(set_cc_subu64, TCG_CALL_NO_RWG_SE, i32, i64, i64, i64) +DEF_HELPER_FLAGS_3(set_cc_sub32, TCG_CALL_NO_RWG_SE, i32, s32, s32, s32) +DEF_HELPER_FLAGS_3(set_cc_subu32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) DEF_HELPER_4(srst, i32, env, i32, i32, i32) DEF_HELPER_4(clst, i32, env, i32, i32, i32) DEF_HELPER_4(mvpg, void, env, i64, i64, i64) @@ -30,15 +30,15 @@ DEF_HELPER_4(csg, i32, env, i32, i64, i32) DEF_HELPER_4(cdsg, i32, env, i32, i64, i32) DEF_HELPER_4(cs, i32, env, i32, i64, i32) DEF_HELPER_5(ex, i32, env, i32, i64, i64, i64) -DEF_HELPER_FLAGS_1(abs_i32, TCG_CALL_PURE|TCG_CALL_CONST, i32, s32) -DEF_HELPER_FLAGS_1(nabs_i32, TCG_CALL_PURE|TCG_CALL_CONST, s32, s32) -DEF_HELPER_FLAGS_1(abs_i64, TCG_CALL_PURE|TCG_CALL_CONST, i64, s64) -DEF_HELPER_FLAGS_1(nabs_i64, TCG_CALL_PURE|TCG_CALL_CONST, s64, s64) +DEF_HELPER_FLAGS_1(abs_i32, TCG_CALL_NO_RWG_SE, i32, s32) +DEF_HELPER_FLAGS_1(nabs_i32, TCG_CALL_NO_RWG_SE, s32, s32) +DEF_HELPER_FLAGS_1(abs_i64, TCG_CALL_NO_RWG_SE, i64, s64) +DEF_HELPER_FLAGS_1(nabs_i64, TCG_CALL_NO_RWG_SE, s64, s64) DEF_HELPER_4(stcmh, void, env, i32, i64, i32) DEF_HELPER_4(icmh, i32, env, i32, i64, i32) DEF_HELPER_3(ipm, void, env, i32, i32) -DEF_HELPER_FLAGS_3(addc_u32, TCG_CALL_PURE|TCG_CALL_CONST, i32, i32, i32, i32) -DEF_HELPER_FLAGS_3(set_cc_addc_u64, TCG_CALL_PURE|TCG_CALL_CONST, i32, i64, i64, i64) +DEF_HELPER_FLAGS_3(addc_u32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32) +DEF_HELPER_FLAGS_3(set_cc_addc_u64, TCG_CALL_NO_RWG_SE, i32, i64, i64, i64) DEF_HELPER_4(stam, void, env, i32, i64, i32) DEF_HELPER_4(lam, void, env, i32, i64, i32) DEF_HELPER_4(mvcle, i32, env, i32, i64, i32) @@ -82,9 +82,9 @@ DEF_HELPER_3(seb, void, env, i32, i32) DEF_HELPER_3(sdb, i32, env, i32, i64) DEF_HELPER_3(mdb, void, env, i32, i64) DEF_HELPER_3(ddb, void, env, i32, i64) -DEF_HELPER_FLAGS_3(cebr, TCG_CALL_PURE, i32, env, i32, i32) -DEF_HELPER_FLAGS_3(cdbr, TCG_CALL_PURE, i32, env, i32, i32) -DEF_HELPER_FLAGS_3(cxbr, TCG_CALL_PURE, i32, env, i32, i32) +DEF_HELPER_FLAGS_3(cebr, TCG_CALL_NO_SE, i32, env, i32, i32) +DEF_HELPER_FLAGS_3(cdbr, TCG_CALL_NO_SE, i32, env, i32, i32) +DEF_HELPER_FLAGS_3(cxbr, TCG_CALL_NO_SE, i32, env, i32, i32) DEF_HELPER_4(cgebr, i32, env, i32, i32, i32) DEF_HELPER_4(cgdbr, i32, env, i32, i32, i32) DEF_HELPER_4(cgxbr, i32, env, i32, i32, i32) @@ -104,12 +104,12 @@ DEF_HELPER_4(madbr, void, env, i32, i32, i32) DEF_HELPER_4(msdbr, void, env, i32, i32, i32) DEF_HELPER_3(ldeb, void, env, i32, i64) DEF_HELPER_3(lxdb, void, env, i32, i64) -DEF_HELPER_FLAGS_3(tceb, TCG_CALL_PURE, i32, env, i32, i64) -DEF_HELPER_FLAGS_3(tcdb, TCG_CALL_PURE, i32, env, i32, i64) -DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_PURE, i32, env, i32, i64) +DEF_HELPER_FLAGS_3(tceb, TCG_CALL_NO_SE, i32, env, i32, i64) +DEF_HELPER_FLAGS_3(tcdb, TCG_CALL_NO_SE, i32, env, i32, i64) +DEF_HELPER_FLAGS_3(tcxb, TCG_CALL_NO_SE, i32, env, i32, i64) DEF_HELPER_3(flogr, i32, env, i32, i64) DEF_HELPER_3(sqdbr, void, env, i32, i32) -DEF_HELPER_FLAGS_1(cvd, TCG_CALL_PURE|TCG_CALL_CONST, i64, s32) +DEF_HELPER_FLAGS_1(cvd, TCG_CALL_NO_RWG_SE, i64, s32) DEF_HELPER_4(unpk, void, env, i32, i64, i64) DEF_HELPER_4(tr, void, env, i32, i64, i64) @@ -117,36 +117,36 @@ DEF_HELPER_3(servc, i32, env, i32, i64) DEF_HELPER_4(diag, i64, env, i32, i64, i64) DEF_HELPER_3(load_psw, void, env, i64, i64) DEF_HELPER_1(program_interrupt, void, i32) -DEF_HELPER_FLAGS_2(stidp, TCG_CALL_CONST, void, env, i64) -DEF_HELPER_FLAGS_2(spx, TCG_CALL_CONST, void, env, i64) -DEF_HELPER_FLAGS_1(sck, TCG_CALL_CONST, i32, i64) +DEF_HELPER_FLAGS_2(stidp, TCG_CALL_NO_RWG, void, env, i64) +DEF_HELPER_FLAGS_2(spx, TCG_CALL_NO_RWG, void, env, i64) +DEF_HELPER_FLAGS_1(sck, TCG_CALL_NO_RWG, i32, i64) DEF_HELPER_2(stck, i32, env, i64) DEF_HELPER_2(stcke, i32, env, i64) -DEF_HELPER_FLAGS_2(sckc, TCG_CALL_CONST, void, env, i64) -DEF_HELPER_FLAGS_2(stckc, TCG_CALL_CONST, void, env, i64) -DEF_HELPER_FLAGS_2(spt, TCG_CALL_CONST, void, env, i64) -DEF_HELPER_FLAGS_2(stpt, TCG_CALL_CONST, void, env, i64) +DEF_HELPER_FLAGS_2(sckc, TCG_CALL_NO_RWG, void, env, i64) +DEF_HELPER_FLAGS_2(stckc, TCG_CALL_NO_RWG, void, env, i64) +DEF_HELPER_FLAGS_2(spt, TCG_CALL_NO_RWG, void, env, i64) +DEF_HELPER_FLAGS_2(stpt, TCG_CALL_NO_RWG, void, env, i64) DEF_HELPER_4(stsi, i32, env, i64, i32, i32) DEF_HELPER_4(lctl, void, env, i32, i64, i32) DEF_HELPER_4(lctlg, void, env, i32, i64, i32) DEF_HELPER_4(stctl, void, env, i32, i64, i32) DEF_HELPER_4(stctg, void, env, i32, i64, i32) -DEF_HELPER_FLAGS_2(tprot, TCG_CALL_CONST, i32, i64, i64) -DEF_HELPER_FLAGS_2(iske, TCG_CALL_PURE|TCG_CALL_CONST, i64, env, i64) -DEF_HELPER_FLAGS_3(sske, TCG_CALL_CONST, void, env, i32, i64) -DEF_HELPER_FLAGS_3(rrbe, TCG_CALL_CONST, i32, env, i32, i64) +DEF_HELPER_FLAGS_2(tprot, TCG_CALL_NO_RWG, i32, i64, i64) +DEF_HELPER_FLAGS_2(iske, TCG_CALL_NO_RWG_SE, i64, env, i64) +DEF_HELPER_FLAGS_3(sske, TCG_CALL_NO_RWG, void, env, i32, i64) +DEF_HELPER_FLAGS_3(rrbe, TCG_CALL_NO_RWG, i32, env, i32, i64) DEF_HELPER_3(csp, i32, env, i32, i32) DEF_HELPER_4(mvcs, i32, env, i64, i64, i64) DEF_HELPER_4(mvcp, i32, env, i64, i64, i64) DEF_HELPER_4(sigp, i32, env, i64, i32, i64) DEF_HELPER_2(sacf, void, env, i64) -DEF_HELPER_FLAGS_3(ipte, TCG_CALL_CONST, void, env, i64, i64) -DEF_HELPER_FLAGS_1(ptlb, TCG_CALL_CONST, void, env) +DEF_HELPER_FLAGS_3(ipte, TCG_CALL_NO_RWG, void, env, i64, i64) +DEF_HELPER_FLAGS_1(ptlb, TCG_CALL_NO_RWG, void, env) DEF_HELPER_3(lra, i32, env, i64, i32) DEF_HELPER_3(stura, void, env, i64, i32) DEF_HELPER_3(cksm, void, env, i32, i32) -DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_PURE|TCG_CALL_CONST, +DEF_HELPER_FLAGS_5(calc_cc, TCG_CALL_NO_RWG_SE, i32, env, i32, i64, i64, i64) #include "def-helper.h" diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c index 07edf93690..a66ac4341c 100644 --- a/target-s390x/kvm.c +++ b/target-s390x/kvm.c @@ -60,15 +60,15 @@ #define SIGP_STORE_STATUS_ADDR 0x0e #define SIGP_SET_ARCH 0x12 -#define SCLP_CMDW_READ_SCP_INFO 0x00020001 -#define SCLP_CMDW_READ_SCP_INFO_FORCED 0x00120001 - const KVMCapabilityInfo kvm_arch_required_capabilities[] = { KVM_CAP_LAST_INFO }; +static int cap_sync_regs; + int kvm_arch_init(KVMState *s) { + cap_sync_regs = kvm_check_extension(s, KVM_CAP_SYNC_REGS); return 0; } @@ -90,47 +90,116 @@ void kvm_arch_reset_vcpu(CPUS390XState *env) int kvm_arch_put_registers(CPUS390XState *env, int level) { + struct kvm_sregs sregs; struct kvm_regs regs; int ret; int i; - ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s); - if (ret < 0) { - return ret; - } + /* always save the PSW and the GPRS*/ + env->kvm_run->psw_addr = env->psw.addr; + env->kvm_run->psw_mask = env->psw.mask; - for (i = 0; i < 16; i++) { - regs.gprs[i] = env->regs[i]; + if (cap_sync_regs && env->kvm_run->kvm_valid_regs & KVM_SYNC_GPRS) { + for (i = 0; i < 16; i++) { + env->kvm_run->s.regs.gprs[i] = env->regs[i]; + env->kvm_run->kvm_dirty_regs |= KVM_SYNC_GPRS; + } + } else { + for (i = 0; i < 16; i++) { + regs.gprs[i] = env->regs[i]; + } + ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, ®s); + if (ret < 0) { + return ret; + } } - ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, ®s); - if (ret < 0) { - return ret; + /* Do we need to save more than that? */ + if (level == KVM_PUT_RUNTIME_STATE) { + return 0; } - env->kvm_run->psw_addr = env->psw.addr; - env->kvm_run->psw_mask = env->psw.mask; + if (cap_sync_regs && + env->kvm_run->kvm_valid_regs & KVM_SYNC_ACRS && + env->kvm_run->kvm_valid_regs & KVM_SYNC_CRS) { + for (i = 0; i < 16; i++) { + env->kvm_run->s.regs.acrs[i] = env->aregs[i]; + env->kvm_run->s.regs.crs[i] = env->cregs[i]; + } + env->kvm_run->kvm_dirty_regs |= KVM_SYNC_ACRS; + env->kvm_run->kvm_dirty_regs |= KVM_SYNC_CRS; + } else { + for (i = 0; i < 16; i++) { + sregs.acrs[i] = env->aregs[i]; + sregs.crs[i] = env->cregs[i]; + } + ret = kvm_vcpu_ioctl(env, KVM_SET_SREGS, &sregs); + if (ret < 0) { + return ret; + } + } - return ret; + /* Finally the prefix */ + if (cap_sync_regs && env->kvm_run->kvm_valid_regs & KVM_SYNC_PREFIX) { + env->kvm_run->s.regs.prefix = env->psa; + env->kvm_run->kvm_dirty_regs |= KVM_SYNC_PREFIX; + } else { + /* prefix is only supported via sync regs */ + } + return 0; } int kvm_arch_get_registers(CPUS390XState *env) { - int ret; + struct kvm_sregs sregs; struct kvm_regs regs; + int ret; int i; - ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s); - if (ret < 0) { - return ret; + /* get the PSW */ + env->psw.addr = env->kvm_run->psw_addr; + env->psw.mask = env->kvm_run->psw_mask; + + /* the GPRS */ + if (cap_sync_regs && env->kvm_run->kvm_valid_regs & KVM_SYNC_GPRS) { + for (i = 0; i < 16; i++) { + env->regs[i] = env->kvm_run->s.regs.gprs[i]; + } + } else { + ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, ®s); + if (ret < 0) { + return ret; + } + for (i = 0; i < 16; i++) { + env->regs[i] = regs.gprs[i]; + } } - for (i = 0; i < 16; i++) { - env->regs[i] = regs.gprs[i]; + /* The ACRS and CRS */ + if (cap_sync_regs && + env->kvm_run->kvm_valid_regs & KVM_SYNC_ACRS && + env->kvm_run->kvm_valid_regs & KVM_SYNC_CRS) { + for (i = 0; i < 16; i++) { + env->aregs[i] = env->kvm_run->s.regs.acrs[i]; + env->cregs[i] = env->kvm_run->s.regs.crs[i]; + } + } else { + ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs); + if (ret < 0) { + return ret; + } + for (i = 0; i < 16; i++) { + env->aregs[i] = sregs.acrs[i]; + env->cregs[i] = sregs.crs[i]; + } } - env->psw.addr = env->kvm_run->psw_addr; - env->psw.mask = env->kvm_run->psw_mask; + /* Finally the prefix */ + if (cap_sync_regs && env->kvm_run->kvm_valid_regs & KVM_SYNC_PREFIX) { + env->psa = env->kvm_run->s.regs.prefix; + } else { + /* no prefix without sync regs */ + } return 0; } @@ -272,7 +341,7 @@ static int kvm_sclp_service_call(CPUS390XState *env, struct kvm_run *run, sccb = env->regs[ipbh0 & 0xf]; code = env->regs[(ipbh0 & 0xf0) >> 4]; - r = sclp_service_call(env, sccb, code); + r = sclp_service_call(sccb, code); if (r < 0) { enter_pgmcheck(env, -r); } diff --git a/target-s390x/misc_helper.c b/target-s390x/misc_helper.c index fdccd58e3d..38d8f2a627 100644 --- a/target-s390x/misc_helper.c +++ b/target-s390x/misc_helper.c @@ -67,55 +67,12 @@ void program_interrupt(CPUS390XState *env, uint32_t code, int ilc) } } -/* - * ret < 0 indicates program check, ret = 0, 1, 2, 3 -> cc - */ -int sclp_service_call(CPUS390XState *env, uint32_t sccb, uint64_t code) -{ - int r = 0; - int shift = 0; - -#ifdef DEBUG_HELPER - printf("sclp(0x%x, 0x%" PRIx64 ")\n", sccb, code); -#endif - - /* basic checks */ - if (cpu_physical_memory_is_io(sccb)) { - return -PGM_ADDRESSING; - } - if (sccb & ~0x7ffffff8ul) { - return -PGM_SPECIFICATION; - } - - switch (code) { - case SCLP_CMDW_READ_SCP_INFO: - case SCLP_CMDW_READ_SCP_INFO_FORCED: - while ((ram_size >> (20 + shift)) > 65535) { - shift++; - } - stw_phys(sccb + SCP_MEM_CODE, ram_size >> (20 + shift)); - stb_phys(sccb + SCP_INCREMENT, 1 << shift); - stw_phys(sccb + SCP_RESPONSE_CODE, 0x10); - - s390_sclp_extint(sccb & ~3); - break; - default: -#ifdef DEBUG_HELPER - printf("KVM: invalid sclp call 0x%x / 0x%" PRIx64 "x\n", sccb, code); -#endif - r = 3; - break; - } - - return r; -} - /* SCLP service call */ uint32_t HELPER(servc)(CPUS390XState *env, uint32_t r1, uint64_t r2) { int r; - r = sclp_service_call(env, r1, r2); + r = sclp_service_call(r1, r2); if (r < 0) { program_interrupt(env, -r, 4); return 0; |