diff mbox

[v3,15/15] translate-all: mark updates to PageDesc as atomic

Message ID 20160930213106.20186-16-alex.bennee@linaro.org
State New
Headers show

Commit Message

Alex Bennée Sept. 30, 2016, 9:31 p.m. UTC
Updates to the internal page table are protected by the mmap_lock.
However for defined C11 semantics things that are access across threads
need to accessed using at least relaxed atomics.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>

---
 translate-all.c | 67 +++++++++++++++++++++++++++++----------------------------
 1 file changed, 34 insertions(+), 33 deletions(-)

-- 
2.9.3
diff mbox

Patch

diff --git a/translate-all.c b/translate-all.c
index a6262ae..2d6c0e8 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -805,22 +805,21 @@  static inline void invalidate_page_bitmap(PageDesc *p)
 static void page_flush_tb_1(int level, void **lp)
 {
     int i;
+    PageDesc *pd = atomic_rcu_read(lp);
 
-    if (*lp == NULL) {
-        return;
-    }
-    if (level == 0) {
-        PageDesc *pd = *lp;
+    if (pd) {
+        if (level == 0) {
 
-        for (i = 0; i < V_L2_SIZE; ++i) {
-            pd[i].first_tb = NULL;
-            invalidate_page_bitmap(pd + i);
-        }
-    } else {
-        void **pp = *lp;
+            for (i = 0; i < V_L2_SIZE; ++i) {
+                atomic_set(&pd[i].first_tb, NULL);
+                invalidate_page_bitmap(pd + i);
+            }
+        } else {
+            void **pp = (void **) pd;
 
-        for (i = 0; i < V_L2_SIZE; ++i) {
-            page_flush_tb_1(level - 1, pp + i);
+            for (i = 0; i < V_L2_SIZE; ++i) {
+                page_flush_tb_1(level - 1, pp + i);
+            }
         }
     }
 }
@@ -1360,7 +1359,7 @@  void tb_invalidate_phys_page_range(tb_page_addr_t start, tb_page_addr_t end,
     /* we remove all the TBs in the range [start, end[ */
     /* XXX: see if in some cases it could be faster to invalidate all
        the code */
-    tb = p->first_tb;
+    tb = atomic_read(&p->first_tb);
     while (tb != NULL) {
         n = (uintptr_t)tb & 3;
         tb = (TranslationBlock *)((uintptr_t)tb & ~3);
@@ -1968,16 +1967,15 @@  void page_set_flags(target_ulong start, target_ulong end, int flags)
            the code inside.  */
         if (!(p->flags & PAGE_WRITE) &&
             (flags & PAGE_WRITE) &&
-            p->first_tb) {
+            atomic_read(&p->first_tb)) {
             tb_invalidate_phys_page(addr, 0);
         }
-        p->flags = flags;
+        atomic_set(&p->flags, flags);
     }
 }
 
 int page_check_range(target_ulong start, target_ulong len, int flags)
 {
-    PageDesc *p;
     target_ulong end;
     target_ulong addr;
 
@@ -2003,28 +2001,31 @@  int page_check_range(target_ulong start, target_ulong len, int flags)
     for (addr = start, len = end - start;
          len != 0;
          len -= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) {
-        p = page_find(addr >> TARGET_PAGE_BITS);
-        if (!p) {
-            return -1;
-        }
-        if (!(p->flags & PAGE_VALID)) {
-            return -1;
-        }
+        PageDesc *p = page_find(addr >> TARGET_PAGE_BITS);
+        if (p) {
+            int cur_flags = atomic_read(&p->flags);
 
-        if ((flags & PAGE_READ) && !(p->flags & PAGE_READ)) {
-            return -1;
-        }
-        if (flags & PAGE_WRITE) {
-            if (!(p->flags & PAGE_WRITE_ORG)) {
+            if (!(cur_flags & PAGE_VALID)) {
                 return -1;
             }
-            /* unprotect the page if it was put read-only because it
-               contains translated code */
-            if (!(p->flags & PAGE_WRITE)) {
-                if (!page_unprotect(addr, 0)) {
+
+            if ((flags & PAGE_READ) && !(cur_flags & PAGE_READ)) {
+                return -1;
+            }
+            if (flags & PAGE_WRITE) {
+                if (!(cur_flags & PAGE_WRITE_ORG)) {
                     return -1;
                 }
+                /* unprotect the page if it was put read-only because it
+                   contains translated code */
+                if (!(cur_flags & PAGE_WRITE)) {
+                    if (!page_unprotect(addr, 0)) {
+                        return -1;
+                    }
+                }
             }
+        } else {
+            return -1;
         }
     }
     return 0;