On 30/09/2016 23:31, Alex Bennée wrote: > 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.
Again, this is only necessary for the initial load-acquire operation. Everything else synchronizes indirectly, so: > + PageDesc *pd = atomic_rcu_read(lp); Using atomics here is correct, but I'd write: void *p = atomic_rcu_read(lp); and then assign from p into either "p" or "pp". > > - if (*lp == NULL) { > - return; Unnecessary and causes indentation changes elsewhere. Just use "if (p == 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); Right. > + 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); Should not be necessary, p->flags is only accessed under mmap_lock (or is it)? Paolo > } > } > > 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; >