diff options
author | David Hildenbrand <david@redhat.com> | 2021-09-03 17:55:14 +0200 |
---|---|---|
committer | Thomas Huth <thuth@redhat.com> | 2021-09-06 16:24:05 +0200 |
commit | c35622387efe39214ccd14fab0f280b6c53f1654 (patch) | |
tree | 1a905cc0ac9aac87728937fe53efff4f41b61ed1 /target/s390x | |
parent | 5227b3260144657b48c2e215f1b38f0a5a7fbcac (diff) | |
download | qemu-c35622387efe39214ccd14fab0f280b6c53f1654.zip qemu-c35622387efe39214ccd14fab0f280b6c53f1654.tar.gz qemu-c35622387efe39214ccd14fab0f280b6c53f1654.tar.bz2 |
hw/s390x/s390-skeys: lazy storage key enablement under TCG
Let's enable storage keys lazily under TCG, just as we do under KVM.
Only fairly old Linux versions actually make use of storage keys, so it
can be kind of wasteful to allocate quite some memory and track
changes and references if nobody cares.
We have to make sure to flush the TLB when enabling storage keys after
the VM was already running: otherwise it might happen that we don't
catch references or modifications afterwards.
Add proper documentation to all callbacks.
The kvm-unit-tests skey tests keeps on working with this change.
Signed-off-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Message-Id: <20210903155514.44772-14-david@redhat.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
Diffstat (limited to 'target/s390x')
-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); |