From c35622387efe39214ccd14fab0f280b6c53f1654 Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Fri, 3 Sep 2021 17:55:14 +0200 Subject: 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 Reviewed-by: Thomas Huth Message-Id: <20210903155514.44772-14-david@redhat.com> Signed-off-by: Thomas Huth --- target/s390x/mmu_helper.c | 8 ++++++++ target/s390x/tcg/mem_helper.c | 9 +++++++++ 2 files changed, 17 insertions(+) (limited to 'target/s390x') 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); -- cgit v1.1