qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH v3 15/15] translate-all: mark updates to PageDes


From: Paolo Bonzini
Subject: Re: [Qemu-devel] [PATCH v3 15/15] translate-all: mark updates to PageDesc as atomic
Date: Mon, 3 Oct 2016 10:50:11 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.3.0


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;
> 



reply via email to

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