qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PULL 6/7] s390x/mmu: Better storage key reference and chan


From: Cornelia Huck
Subject: [Qemu-devel] [PULL 6/7] s390x/mmu: Better storage key reference and change bit handling
Date: Thu, 22 Aug 2019 15:58:38 +0200

From: David Hildenbrand <address@hidden>

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 <address@hidden>
Signed-off-by: David Hildenbrand <address@hidden>
Message-Id: <address@hidden>
Signed-off-by: Cornelia Huck <address@hidden>
---
 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 40b6c1fc36a9..61654e07dec8 100644
--- a/target/s390x/mmu_helper.c
+++ b/target/s390x/mmu_helper.c
@@ -421,14 +421,28 @@ nodat:
             return 0;
         }
 
-        if (*flags & PAGE_READ) {
-            key |= SK_R;
-        }
-
-        if (*flags & PAGE_WRITE) {
+        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();
         }
 
+        /* Any store/fetch sets the reference bit */
+        key |= SK_R;
+
         r = skeyclass->set_skeys(ss, *raddr / TARGET_PAGE_SIZE, 1, &key);
         if (r) {
             trace_set_skeys_nonzero(r);
-- 
2.20.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]