diff options
Diffstat (limited to 'target-s390x')
-rw-r--r-- | target-s390x/cpu.h | 2 | ||||
-rw-r--r-- | target-s390x/mem_helper.c | 46 | ||||
-rw-r--r-- | target-s390x/mmu_helper.c | 28 |
3 files changed, 63 insertions, 13 deletions
diff --git a/target-s390x/cpu.h b/target-s390x/cpu.h index 63aebf4846..b650890130 100644 --- a/target-s390x/cpu.h +++ b/target-s390x/cpu.h @@ -143,8 +143,6 @@ typedef struct CPUS390XState { uint32_t cpu_num; uint32_t machine_type; - uint8_t *storage_keys; - uint64_t tod_offset; uint64_t tod_basetime; QEMUTimer *tod_timer; diff --git a/target-s390x/mem_helper.c b/target-s390x/mem_helper.c index 6f8bd796ad..84bf198e2b 100644 --- a/target-s390x/mem_helper.c +++ b/target-s390x/mem_helper.c @@ -21,6 +21,7 @@ #include "cpu.h" #include "exec/helper-proto.h" #include "exec/cpu_ldst.h" +#include "hw/s390x/storage-keys.h" /*****************************************************************************/ /* Softmmu support */ @@ -937,40 +938,73 @@ uint32_t HELPER(tprot)(uint64_t a1, uint64_t a2) /* insert storage key extended */ uint64_t HELPER(iske)(CPUS390XState *env, uint64_t r2) { + static S390SKeysState *ss; + static S390SKeysClass *skeyclass; uint64_t addr = get_address(env, 0, 0, r2); + uint8_t key; if (addr > ram_size) { return 0; } - return env->storage_keys[addr / TARGET_PAGE_SIZE]; + if (unlikely(!ss)) { + ss = s390_get_skeys_device(); + skeyclass = S390_SKEYS_GET_CLASS(ss); + } + + if (skeyclass->get_skeys(ss, addr / TARGET_PAGE_SIZE, 1, &key)) { + return 0; + } + return key; } /* set storage key extended */ void HELPER(sske)(CPUS390XState *env, uint64_t r1, uint64_t r2) { + static S390SKeysState *ss; + static S390SKeysClass *skeyclass; uint64_t addr = get_address(env, 0, 0, r2); + uint8_t key; if (addr > ram_size) { return; } - env->storage_keys[addr / TARGET_PAGE_SIZE] = r1; + if (unlikely(!ss)) { + ss = s390_get_skeys_device(); + skeyclass = S390_SKEYS_GET_CLASS(ss); + } + + key = (uint8_t) r1; + skeyclass->set_skeys(ss, addr / TARGET_PAGE_SIZE, 1, &key); } /* reset reference bit extended */ uint32_t HELPER(rrbe)(CPUS390XState *env, uint64_t r2) { - uint8_t re; - uint8_t key; + static S390SKeysState *ss; + static S390SKeysClass *skeyclass; + uint8_t re, key; if (r2 > ram_size) { return 0; } - key = env->storage_keys[r2 / TARGET_PAGE_SIZE]; + if (unlikely(!ss)) { + ss = s390_get_skeys_device(); + skeyclass = S390_SKEYS_GET_CLASS(ss); + } + + if (skeyclass->get_skeys(ss, r2 / TARGET_PAGE_SIZE, 1, &key)) { + return 0; + } + re = key & (SK_R | SK_C); - env->storage_keys[r2 / TARGET_PAGE_SIZE] = (key & ~SK_R); + key &= ~SK_R; + + if (skeyclass->set_skeys(ss, r2 / TARGET_PAGE_SIZE, 1, &key)) { + return 0; + } /* * cc 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; } } |