From 2d3bb388ad93dce9a9454af67f43d3aaaa5b9b1a Mon Sep 17 00:00:00 2001 From: David Hildenbrand Date: Fri, 16 Aug 2019 10:47:07 +0200 Subject: [PATCH] s390x/mmu: Better storage key reference and change bit handling Any access sets the reference bit. In case we have a read-fault, we should not allow writes to the TLB entry if the change bit was not already set. This is a preparation for proper storage-key reference/change bit handling in TCG and a fix for KVM whereby read accesses would set the change bit (old KVM versions without the ioctl to carry out the translation). Reviewed-by: Cornelia Huck Signed-off-by: David Hildenbrand Message-Id: <20190816084708.602-6-david@redhat.com> Signed-off-by: Cornelia Huck --- target/s390x/mmu_helper.c | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/target/s390x/mmu_helper.c b/target/s390x/mmu_helper.c index 40b6c1fc36..61654e07de 100644 --- a/target/s390x/mmu_helper.c +++ b/target/s390x/mmu_helper.c @@ -421,13 +421,27 @@ nodat: return 0; } - if (*flags & PAGE_READ) { - key |= SK_R; + switch (rw) { + case MMU_DATA_LOAD: + case MMU_INST_FETCH: + /* + * The TLB entry has to remain write-protected on read-faults if + * the storage key does not indicate a change already. Otherwise + * we might miss setting the change bit on write accesses. + */ + if (!(key & SK_C)) { + *flags &= ~PAGE_WRITE; + } + break; + case MMU_DATA_STORE: + key |= SK_C; + break; + default: + g_assert_not_reached(); } - if (*flags & PAGE_WRITE) { - key |= SK_C; - } + /* Any store/fetch sets the reference bit */ + key |= SK_R; r = skeyclass->set_skeys(ss, *raddr / TARGET_PAGE_SIZE, 1, &key); if (r) {