aboutsummaryrefslogtreecommitdiff
path: root/target-s390x/mmu_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-s390x/mmu_helper.c')
-rw-r--r--target-s390x/mmu_helper.c28
1 files changed, 23 insertions, 5 deletions
diff --git a/target-s390x/mmu_helper.c b/target-s390x/mmu_helper.c
index 1ea6d812c2..058a37013b 100644
--- a/target-s390x/mmu_helper.c
+++ b/target-s390x/mmu_helper.c
@@ -19,6 +19,8 @@
#include "exec/address-spaces.h"
#include "cpu.h"
#include "sysemu/kvm.h"
+#include "trace.h"
+#include "hw/s390x/storage-keys.h"
/* #define DEBUG_S390 */
/* #define DEBUG_S390_PTE */
@@ -309,8 +311,15 @@ static int mmu_translate_asce(CPUS390XState *env, target_ulong vaddr,
int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
target_ulong *raddr, int *flags, bool exc)
{
+ static S390SKeysState *ss;
+ static S390SKeysClass *skeyclass;
int r = -1;
- uint8_t *sk;
+ uint8_t key;
+
+ if (unlikely(!ss)) {
+ ss = s390_get_skeys_device();
+ skeyclass = S390_SKEYS_GET_CLASS(ss);
+ }
*flags = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
vaddr &= TARGET_PAGE_MASK;
@@ -358,14 +367,23 @@ int mmu_translate(CPUS390XState *env, target_ulong vaddr, int rw, uint64_t asc,
/* Convert real address -> absolute address */
*raddr = mmu_real2abs(env, *raddr);
- if (*raddr < ram_size) {
- sk = &env->storage_keys[*raddr / TARGET_PAGE_SIZE];
+ if (r == 0 && *raddr < ram_size) {
+ if (skeyclass->get_skeys(ss, *raddr / TARGET_PAGE_SIZE, 1, &key)) {
+ trace_get_skeys_nonzero(r);
+ return 0;
+ }
+
if (*flags & PAGE_READ) {
- *sk |= SK_R;
+ key |= SK_R;
}
if (*flags & PAGE_WRITE) {
- *sk |= SK_C;
+ key |= SK_C;
+ }
+
+ if (skeyclass->set_skeys(ss, *raddr / TARGET_PAGE_SIZE, 1, &key)) {
+ trace_set_skeys_nonzero(r);
+ return 0;
}
}