aboutsummaryrefslogtreecommitdiff
path: root/target/s390x
diff options
context:
space:
mode:
authorDavid Hildenbrand <david@redhat.com>2021-09-03 17:55:14 +0200
committerThomas Huth <thuth@redhat.com>2021-09-06 16:24:05 +0200
commitc35622387efe39214ccd14fab0f280b6c53f1654 (patch)
tree1a905cc0ac9aac87728937fe53efff4f41b61ed1 /target/s390x
parent5227b3260144657b48c2e215f1b38f0a5a7fbcac (diff)
downloadqemu-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.c8
-rw-r--r--target/s390x/tcg/mem_helper.c9
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);