|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v3 20/25] x86emul: correctly handle CMPXCHG* comparison failures
On 07/12/17 14:15, Jan Beulich wrote:
> If the ->cmpxchg() hook finds a mismatch, we should deal with this the
> same way as when the "manual" comparison reports a mismatch.
>
> This involves reverting bfce0e62c3 ("x86/emul: Drop
> X86EMUL_CMPXCHG_FAILED"), albeit with X86EMUL_CMPXCHG_FAILED now
> becoming a value distinct from X86EMUL_RETRY.
>
> In order to not leave mixed code also fully switch affected functions
> from paddr_t to intpte_t.
>
> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
> ---
> v3: New.
> ---
> The code could be further simplified if we could rely on all
> ->cmpxchg() hooks always using CMPXCHG, but for now we need to cope
> with them using plain writes (and hence accept the double reads if
> CMPXCHG is actually being used).
> Note that the patch doesn't address the incorrectness of there not
> being a memory write even in the comparison-failed case.
>
> --- a/xen/arch/x86/mm/shadow/common.c
> +++ b/xen/arch/x86/mm/shadow/common.c
> @@ -302,8 +302,12 @@ hvm_emulate_cmpxchg(enum x86_segment seg
> memcpy(&old, p_old, bytes);
> memcpy(&new, p_new, bytes);
>
> - return v->arch.paging.mode->shadow.x86_emulate_cmpxchg(
> - v, addr, old, new, bytes, sh_ctxt);
> + rc = v->arch.paging.mode->shadow.x86_emulate_cmpxchg(
> + v, addr, &old, new, bytes, sh_ctxt);
> +
> + memcpy(p_old, &old, bytes);
This is redundant with ...
> +
> + return rc;
> }
>
> static const struct x86_emulate_ops hvm_shadow_emulator_ops = {
> --- a/xen/arch/x86/mm/shadow/multi.c
> +++ b/xen/arch/x86/mm/shadow/multi.c
> @@ -4741,11 +4741,11 @@ sh_x86_emulate_write(struct vcpu *v, uns
>
> static int
> sh_x86_emulate_cmpxchg(struct vcpu *v, unsigned long vaddr,
> - unsigned long old, unsigned long new,
> - unsigned int bytes, struct sh_emulate_ctxt *sh_ctxt)
> + unsigned long *p_old, unsigned long new,
> + unsigned int bytes, struct sh_emulate_ctxt *sh_ctxt)
> {
> void *addr;
> - unsigned long prev;
> + unsigned long prev, old = *p_old;
> int rv = X86EMUL_OKAY;
>
> /* Unaligned writes are only acceptable on HVM */
> @@ -4769,7 +4769,10 @@ sh_x86_emulate_cmpxchg(struct vcpu *v, u
> }
>
> if ( prev != old )
> - rv = X86EMUL_RETRY;
> + {
> + *p_old = prev;
... this, is it not?
> + rv = X86EMUL_CMPXCHG_FAILED;
> + }
>
> SHADOW_DEBUG(EMULATE, "va %#lx was %#lx expected %#lx"
> " wanted %#lx now %#lx bytes %u\n",
> --- a/xen/arch/x86/pv/ro-page-fault.c
> +++ b/xen/arch/x86/pv/ro-page-fault.c
> @@ -65,14 +65,16 @@ static int ptwr_emulated_read(enum x86_s
> return X86EMUL_OKAY;
> }
>
> -static int ptwr_emulated_update(unsigned long addr, paddr_t old, paddr_t val,
> - unsigned int bytes, unsigned int do_cmpxchg,
> +static int ptwr_emulated_update(unsigned long addr, intpte_t *p_old,
> + intpte_t val, unsigned int bytes,
> struct x86_emulate_ctxt *ctxt)
> {
> unsigned long mfn;
> unsigned long unaligned_addr = addr;
> struct page_info *page;
> l1_pgentry_t pte, ol1e, nl1e, *pl1e;
> + intpte_t old = p_old ? *p_old : 0;
> + unsigned int offset = 0;
I really think this conversion to intpte needs splitting out into a
separate patch. You're making multiple changes in this function which
aren't at commit message at all, including introducing the distinction
I've just noted of *p_old being NULL meaning a write rather than cmpxchg.
On that note specifically, it would be clearer to have "const bool
do_cmpxchg = *p_old; /* cmpxchg, or write? */". If you don't want to do
it, then there needs to be a comment with the function explaining the
semantics of p_old.
~Andrew
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |