diff options
Diffstat (limited to 'target')
-rw-r--r-- | target/s390x/mmu_helper.c | 8 | ||||
-rw-r--r-- | target/s390x/tcg/mem_helper.c | 9 |
2 files changed, 17 insertions, 0 deletions
diff --git a/target/s390x/mmu_helper.c b/target/s390x/mmu_helper.c index e2b372e..b04b57c 100644 --- a/target/s390x/mmu_helper.c +++ b/target/s390x/mmu_helper.c @@ -314,6 +314,14 @@ static void mmu_handle_skey(target_ulong addr, int rw, int *flags) } /* + * Don't enable storage keys if they are still disabled, i.e., no actual + * storage key instruction was issued yet. + */ + if (!skeyclass->skeys_are_enabled(ss)) { + return; + } + + /* * Whenever we create a new TLB entry, we set the storage key reference * bit. In case we allow write accesses, we set the storage key change * bit. Whenever the guest changes the storage key, we have to flush the diff --git a/target/s390x/tcg/mem_helper.c b/target/s390x/tcg/mem_helper.c index 4f9f3e1..0bf775a 100644 --- a/target/s390x/tcg/mem_helper.c +++ b/target/s390x/tcg/mem_helper.c @@ -2186,6 +2186,9 @@ uint64_t HELPER(iske)(CPUS390XState *env, uint64_t r2) if (unlikely(!ss)) { ss = s390_get_skeys_device(); skeyclass = S390_SKEYS_GET_CLASS(ss); + if (skeyclass->enable_skeys && !skeyclass->enable_skeys(ss)) { + tlb_flush_all_cpus_synced(env_cpu(env)); + } } rc = skeyclass->get_skeys(ss, addr / TARGET_PAGE_SIZE, 1, &key); @@ -2213,6 +2216,9 @@ void HELPER(sske)(CPUS390XState *env, uint64_t r1, uint64_t r2) if (unlikely(!ss)) { ss = s390_get_skeys_device(); skeyclass = S390_SKEYS_GET_CLASS(ss); + if (skeyclass->enable_skeys && !skeyclass->enable_skeys(ss)) { + tlb_flush_all_cpus_synced(env_cpu(env)); + } } key = r1 & 0xfe; @@ -2244,6 +2250,9 @@ uint32_t HELPER(rrbe)(CPUS390XState *env, uint64_t r2) if (unlikely(!ss)) { ss = s390_get_skeys_device(); skeyclass = S390_SKEYS_GET_CLASS(ss); + if (skeyclass->enable_skeys && !skeyclass->enable_skeys(ss)) { + tlb_flush_all_cpus_synced(env_cpu(env)); + } } rc = skeyclass->get_skeys(ss, addr / TARGET_PAGE_SIZE, 1, &key); |