aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--target/s390x/helper.h2
-rw-r--r--target/s390x/mem_helper.c41
-rw-r--r--target/s390x/translate.c2
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;
}