summaryrefslogtreecommitdiff
path: root/target/s390x/mem_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/s390x/mem_helper.c')
-rw-r--r--target/s390x/mem_helper.c41
1 files changed, 39 insertions, 2 deletions
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;
}