diff options
-rw-r--r-- | target/s390x/helper.h | 2 | ||||
-rw-r--r-- | target/s390x/mem_helper.c | 41 | ||||
-rw-r--r-- | target/s390x/translate.c | 2 |
3 files changed, 41 insertions, 4 deletions
diff --git a/target/s390x/helper.h b/target/s390x/helper.h index 2f17b62d3d..26c1b07b44 100644 --- a/target/s390x/helper.h +++ b/target/s390x/helper.h @@ -137,7 +137,7 @@ DEF_HELPER_FLAGS_4(lctlg, TCG_CALL_NO_WG, void, env, i32, i64, i32) DEF_HELPER_FLAGS_4(stctl, TCG_CALL_NO_WG, void, env, i32, i64, i32) DEF_HELPER_FLAGS_4(stctg, TCG_CALL_NO_WG, void, env, i32, i64, i32) DEF_HELPER_FLAGS_2(testblock, TCG_CALL_NO_WG, i32, env, i64) -DEF_HELPER_FLAGS_2(tprot, TCG_CALL_NO_RWG, i32, i64, i64) +DEF_HELPER_FLAGS_3(tprot, TCG_CALL_NO_RWG, i32, env, 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, i64, i64) DEF_HELPER_FLAGS_2(rrbe, TCG_CALL_NO_RWG, i32, env, i64) diff --git a/target/s390x/mem_helper.c b/target/s390x/mem_helper.c index 2625d843b3..359e446c6f 100644 --- a/target/s390x/mem_helper.c +++ b/target/s390x/mem_helper.c @@ -1717,9 +1717,46 @@ uint32_t HELPER(testblock)(CPUS390XState *env, uint64_t real_addr) return 0; } -uint32_t HELPER(tprot)(uint64_t a1, uint64_t a2) +uint32_t HELPER(tprot)(CPUS390XState *env, uint64_t a1, uint64_t a2) { - /* XXX implement */ + S390CPU *cpu = s390_env_get_cpu(env); + CPUState *cs = CPU(cpu); + + /* + * TODO: we currently don't handle all access protection types + * (including access-list and key-controlled) as well as AR mode. + */ + if (!s390_cpu_virt_mem_check_write(cpu, a1, 0, 1)) { + /* Fetching permitted; storing permitted */ + return 0; + } + switch (env->int_pgm_code) { + case PGM_PROTECTION: + /* Fetching permitted; storing not permitted */ + cs->exception_index = 0; + return 1; + case PGM_ADDRESSING: + /* Fetching not permitted; storing not permitted */ + cs->exception_index = 0; + return 2; + case PGM_ASCE_TYPE: + case PGM_REG_FIRST_TRANS: + case PGM_REG_SEC_TRANS: + case PGM_REG_THIRD_TRANS: + case PGM_SEGMENT_TRANS: + case PGM_PAGE_TRANS: + case PGM_ALET_SPEC: + case PGM_ALEN_SPEC: + case PGM_ALE_SEQ: + case PGM_ASTE_VALID: + case PGM_ASTE_SEQ: + case PGM_EXT_AUTH: + /* Translation not available */ + cs->exception_index = 0; + return 3; + } + /* any other exception is forwarded to the guest */ + s390_cpu_virt_mem_handle_exc(cpu, GETPC()); return 0; } diff --git a/target/s390x/translate.c b/target/s390x/translate.c index ac55886792..df0b41606d 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -4532,7 +4532,7 @@ static ExitStatus op_testblock(DisasContext *s, DisasOps *o) static ExitStatus op_tprot(DisasContext *s, DisasOps *o) { - gen_helper_tprot(cc_op, o->addr1, o->in2); + gen_helper_tprot(cc_op, cpu_env, o->addr1, o->in2); set_cc_static(s); return NO_EXIT; } |