All of lore.kernel.org
 help / color / mirror / Atom feed
From: Andrew Cooper <andrew.cooper3@citrix.com>
To: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>,
	xen-devel@lists.xenproject.org, konrad@kernel.org,
	ross.lagerwall@citrix.com, mpohlack@amazon.de,
	sasha.levin@oracle.com
Cc: Kevin Tian <kevin.tian@intel.com>, Keir Fraser <keir@xen.org>,
	Suravee Suthikulpanit <suravee.suthikulpanit@amd.com>,
	Jan Beulich <jbeulich@suse.com>,
	Julien Grall <julien.grall@arm.com>,
	Stefano Stabellini <stefano.stabellini@citrix.com>,
	Jun Nakajima <jun.nakajima@intel.com>,
	Boris Ostrovsky <boris.ostrovsky@oracle.com>
Subject: Re: [PATCH v6 10/24] xsplice: Implement support for applying/reverting/replacing patches.
Date: Fri, 8 Apr 2016 17:33:35 +0100	[thread overview]
Message-ID: <5707DD5F.2030804@citrix.com> (raw)
In-Reply-To: <1460000983-28170-11-git-send-email-konrad.wilk@oracle.com>

On 07/04/16 04:49, Konrad Rzeszutek Wilk wrote:
> +void arch_xsplice_post_action(void)
> +{

/* Serialise the CPU pipeline. */

Otherwise it makes one wonder what a cpuid instruction has to do with
xsplicing.

> diff --git a/xen/common/xsplice.c b/xen/common/xsplice.c
> index 10c8166..2df879e 100644
> --- a/xen/common/xsplice.c
> +++ b/xen/common/xsplice.c
> @@ -11,17 +12,29 @@
>  #include <xen/mm.h>
>  #include <xen/sched.h>
>  #include <xen/smp.h>
> +#include <xen/softirq.h>
>  #include <xen/spinlock.h>
>  #include <xen/vmap.h>
> +#include <xen/wait.h>
>  #include <xen/xsplice_elf.h>
>  #include <xen/xsplice.h>
> +#include <xen/xsplice_patch.h>
>  
>  #include <asm/event.h>
>  #include <public/sysctl.h>
>  
> +/*
> + * Protects against payload_list operations and also allows only one
> + * caller in schedule_work.
> + */

This comment looks like it should be part of a previous patch.

>  static DEFINE_SPINLOCK(payload_lock);
>  static LIST_HEAD(payload_list);
>  
> +/*
> + * Patches which have been applied.
> + */
> +static LIST_HEAD(applied_list);
> +
>  static unsigned int payload_cnt;
>  static unsigned int payload_version = 1;
>  
> @@ -37,9 +50,35 @@ struct payload {
>      size_t ro_size;                      /* .. and its size (if any). */
>      size_t pages;                        /* Total pages for [text,rw,ro]_addr */
>      mfn_t *mfn;                          /* The MFNs backing these pages. */
> +    struct list_head applied_list;       /* Linked to 'applied_list'. */
> +    struct xsplice_patch_func_internal *funcs;    /* The array of functions to patch. */
> +    unsigned int nfuncs;                 /* Nr of functions to patch. */
>      char name[XEN_XSPLICE_NAME_SIZE];    /* Name of it. */
>  };
>  
> +/* Defines an outstanding patching action. */
> +struct xsplice_work
> +{
> +    atomic_t semaphore;          /* Used for rendezvous. */
> +    atomic_t irq_semaphore;      /* Used to signal all IRQs disabled. */
> +    uint32_t timeout;            /* Timeout to do the operation. */
> +    struct payload *data;        /* The payload on which to act. */
> +    volatile bool_t do_work;     /* Signals work to do. */
> +    volatile bool_t ready;       /* Signals all CPUs synchronized. */
> +    unsigned int cmd;                /* Action request: XSPLICE_ACTION_* */

Alignment.

> +static int schedule_work(struct payload *data, uint32_t cmd, uint32_t timeout)
> +{
> +    unsigned int cpu;
> +
> +    ASSERT(spin_is_locked(&payload_lock));
> +
> +    /* Fail if an operation is already scheduled. */
> +    if ( xsplice_work.do_work )
> +        return -EBUSY;
> +
> +    if ( !get_cpu_maps() )
> +    {
> +        printk(XENLOG_ERR XSPLICE "%s: unable to get cpu_maps lock!\n",
> +               data->name);
> +        return -EBUSY;
> +    }
> +
> +    xsplice_work.cmd = cmd;
> +    xsplice_work.data = data;
> +    xsplice_work.timeout = timeout ?: MILLISECS(30);
> +
> +    dprintk(XENLOG_DEBUG, XSPLICE "%s: timeout is %"PRI_stime"ms\n",
> +            data->name, xsplice_work.timeout / MILLISECS(1));
> +
> +    atomic_set(&xsplice_work.semaphore, -1);
> +    atomic_set(&xsplice_work.irq_semaphore, -1);
> +
> +    xsplice_work.ready = 0;
> +    smp_wmb();
> +    xsplice_work.do_work = 1;
> +    smp_wmb();
> +    /*
> +     * Above smp_wmb() gives us a compiler barrier, as we MUST do this
> +     * after setting the global structure.
> +     */
> +    for_each_online_cpu ( cpu )
> +        per_cpu(work_to_do, cpu) = 1;

This should be in reschedule_fn() to avoid dirtying the cachelines on
the current cpu and have them read by other cpus.

> +
> +    put_cpu_maps();
> +
> +    return 0;
> +}
> +
> +static void reschedule_fn(void *unused)
> +{
> +    smp_mb(); /* Synchronize with setting do_work */

You don't need the barrier here, but you do need...

> +    raise_softirq(SCHEDULE_SOFTIRQ);
> +}
> +
> +static int xsplice_spin(atomic_t *counter, s_time_t timeout,
> +                           unsigned int cpus, const char *s)
> +{
> +    int rc = 0;
> +
> +    while ( atomic_read(counter) != cpus && NOW() < timeout )
> +        cpu_relax();
> +
> +    /* Log & abort. */
> +    if ( atomic_read(counter) != cpus )
> +    {
> +        printk(XENLOG_ERR XSPLICE "%s: Timed out on %s semaphore %u/%u\n",
> +               xsplice_work.data->name, s, atomic_read(counter), cpus);
> +        rc = -EBUSY;
> +        xsplice_work.data->rc = rc;
> +        xsplice_work.do_work = 0;
> +        smp_wmb();
> +    }
> +
> +    return rc;
> +}
> +
> +/*
> + * The main function which manages the work of quiescing the system and
> + * patching code.
> + */
> +void check_for_xsplice_work(void)
> +{
> +#define ACTION(x) [XSPLICE_ACTION_##x] = #x
> +    static const char *const names[] = {
> +            ACTION(APPLY),
> +            ACTION(REVERT),
> +            ACTION(REPLACE),
> +    };
> +    unsigned int cpu = smp_processor_id();
> +    s_time_t timeout;
> +    unsigned long flags;
> +
> +    /* Fast path: no work to do. */
> +    if ( !per_cpu(work_to_do, cpu ) )
> +        return;
> +
> +    /* In case we aborted, other CPUs can skip right away. */

... an smp_rmb() here.

> +    if ( !xsplice_work.do_work )
> +    {
> +        per_cpu(work_to_do, cpu) = 0;
> +        return;
> +    }
> +
> +    ASSERT(local_irq_is_enabled());
> +
> +    /* Set at -1, so will go up to num_online_cpus - 1. */
> +    if ( atomic_inc_and_test(&xsplice_work.semaphore) )
> +    {
> +        struct payload *p;
> +        unsigned int cpus;
> +
> +        p = xsplice_work.data;
> +        if ( !get_cpu_maps() )
> +        {
> +            printk(XENLOG_ERR XSPLICE "%s: CPU%u - unable to get cpu_maps lock!\n",
> +                   p->name, cpu);
> +            per_cpu(work_to_do, cpu) = 0;
> +            xsplice_work.data->rc = -EBUSY;
> +            xsplice_work.do_work = 0;
> +            /*
> +             * Do NOT decrement semaphore down - as that may cause the other
> +             * CPU (which may be at this ready to increment it)
> +             * to assume the role of master and then needlessly time out
> +             * out (as do_work is zero).
> +             */

smp_wmb();

> +            return;
> +        }
> +        /* "Mask" NMIs. */
> +        arch_xsplice_mask();
> +
> +        barrier(); /* MUST do it after get_cpu_maps. */
> +        cpus = num_online_cpus() - 1;
> +
> +        if ( cpus )
> +        {
> +            dprintk(XENLOG_DEBUG, XSPLICE "%s: CPU%u - IPIing the other %u CPUs\n",
> +                    p->name, cpu, cpus);
> +            smp_call_function(reschedule_fn, NULL, 0);
> +        }
> +
> +        timeout = xsplice_work.timeout + NOW();
> +        if ( xsplice_spin(&xsplice_work.semaphore, timeout, cpus, "CPU") )
> +            goto abort;
> +
> +        /* All CPUs are waiting, now signal to disable IRQs. */
> +        xsplice_work.ready = 1;
> +        smp_wmb();
> +
> +        atomic_inc(&xsplice_work.irq_semaphore);
> +        if ( !xsplice_spin(&xsplice_work.irq_semaphore, timeout, cpus, "IRQ") )
> +        {
> +            local_irq_save(flags);
> +            /* Do the patching. */
> +            xsplice_do_action();
> +            /* Flush the CPU i-cache via CPUID instruction (on x86). */
> +            arch_xsplice_post_action();
> +            local_irq_restore(flags);
> +        }
> +        arch_xsplice_unmask();
> +
> + abort:
> +        per_cpu(work_to_do, cpu) = 0;
> +        xsplice_work.do_work = 0;
> +
> +        smp_wmb(); /* MUST complete writes before put_cpu_maps(). */
> +
> +        put_cpu_maps();
> +
> +        printk(XENLOG_INFO XSPLICE "%s finished %s with rc=%d\n",
> +               p->name, names[xsplice_work.cmd], p->rc);
> +    }
> +    else
> +    {
> +        /* Wait for all CPUs to rendezvous. */
> +        while ( xsplice_work.do_work && !xsplice_work.ready )
> +            cpu_relax();
> +
> +        /* Disable IRQs and signal. */
> +        local_irq_save(flags);
> +        atomic_inc(&xsplice_work.irq_semaphore);
> +
> +        /* Wait for patching to complete. */
> +        while ( xsplice_work.do_work )
> +            cpu_relax();
> +
> +        /* To flush out pipeline. */
> +        arch_xsplice_post_action();
> +        local_irq_restore(flags);
> +
> +        per_cpu(work_to_do, cpu) = 0;
> +    }
> +}
> +
> diff --git a/xen/include/xen/xsplice.h b/xen/include/xen/xsplice.h
> index b843b5f..71d7939 100644
> --- a/xen/include/xen/xsplice.h
> +++ b/xen/include/xen/xsplice.h
> @@ -11,12 +11,37 @@ struct xsplice_elf_sec;
>  struct xsplice_elf_sym;
>  struct xen_sysctl_xsplice_op;
>  
> +#include <xen/elfstructs.h>
>  #ifdef CONFIG_XSPLICE
>  
> +/*
> + * The structure which defines the patching. This is what the hypervisor
> + * expects in the '.xsplice.func' section of the ELF file.
> + *
> + * This MUST be in sync with what the tools generate. We expose
> + * for the tools the 'struct xsplice_patch_func' which does not have
> + * platform specific entries.

Shouldn't this be somewhere in the public API then? even if it is
explicitly declared as unstable due to xpatches needing to be rebuilt
from exact source?

> diff --git a/xen/include/xen/xsplice_patch.h b/xen/include/xen/xsplice_patch.h
> new file mode 100644
> index 0000000..f305826
> --- /dev/null
> +++ b/xen/include/xen/xsplice_patch.h
> @@ -0,0 +1,25 @@
> +/*
> + * Copyright (C) 2016 Citrix Systems R&D Ltd.
> + */
> +
> +#ifndef __XEN_XSPLICE_PATCH_H__
> +#define __XEN_XSPLICE_PATCH_H__
> +
> +#define XSPLICE_PAYLOAD_VERSION 1
> +/*
> + * .xsplice.funcs structure layout defined in the `Payload format`
> + * section in the xSplice design document.
> + *
> + * The size should be exactly 64 bytes.
> + */

Ditto, wrt the public API.

~Andrew

> +struct xsplice_patch_func {
> +    const char *name;       /* Name of function to be patched. */
> +    uint64_t new_addr;
> +    uint64_t old_addr;      /* Can be zero and name will be looked up. */
> +    uint32_t new_size;
> +    uint32_t old_size;
> +    uint8_t version;        /* MUST be XSPLICE_PAYLOAD_VERSION. */
> +    uint8_t pad[31];        /* MUST be zero filled. */
> +};
> +
> +#endif /* __XEN_XSPLICE_PATCH_H__ */


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

  parent reply	other threads:[~2016-04-08 16:37 UTC|newest]

Thread overview: 85+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-07  3:49 [PATCH v6] xSplice v1 design and implementation Konrad Rzeszutek Wilk
2016-04-07  3:49 ` [PATCH v6 01/24] xsplice: Design document Konrad Rzeszutek Wilk
2016-04-07 16:34   ` Ian Jackson
2016-04-07  3:49 ` [PATCH v6 02/24] xen/xsplice: Hypervisor implementation of XEN_XSPLICE_op Konrad Rzeszutek Wilk
2016-04-07 14:47   ` Andrew Cooper
2016-04-08 18:30   ` Konrad Rzeszutek Wilk
2016-04-07  3:49 ` [PATCH v6 03/24] libxc: Implementation of XEN_XSPLICE_op in libxc Konrad Rzeszutek Wilk
2016-04-07 19:53   ` Andrew Cooper
2016-04-07  3:49 ` [PATCH v6 04/24] xen-xsplice: Tool to manipulate xsplice payloads Konrad Rzeszutek Wilk
2016-04-07  3:49 ` [PATCH v6 05/24] arm/x86: Use struct virtual_region to do bug, symbol, and (x86) exception tables lookup Konrad Rzeszutek Wilk
2016-04-07 20:12   ` Andrew Cooper
2016-04-08 15:30   ` Julien Grall
2016-04-07  3:49 ` [PATCH v6 06/24] x86: Alter nmi_callback_t typedef Konrad Rzeszutek Wilk
2016-04-07 16:35   ` Ian Jackson
2016-04-07 20:13   ` Andrew Cooper
2016-04-08 20:44     ` Konrad Rzeszutek Wilk
2016-04-07  3:49 ` [PATCH v6 07/24] arm/x86/vmap: Add vmalloc_type and vm_init_type Konrad Rzeszutek Wilk
2016-04-08 14:22   ` Andrew Cooper
2016-04-08 17:19     ` Jan Beulich
2016-04-09  1:10       ` Konrad Rzeszutek Wilk
2016-04-08 15:32   ` Julien Grall
2016-04-07  3:49 ` [PATCH v6 08/24] xsplice: Add helper elf routines Konrad Rzeszutek Wilk
2016-04-07 16:19   ` Ian Jackson
2016-04-07 17:23     ` Jan Beulich
2016-04-07 20:32     ` Andrew Cooper
2016-04-08 13:26       ` Ian Jackson
2016-04-07 20:43     ` Konrad Rzeszutek Wilk
2016-04-08 14:53   ` Andrew Cooper
2016-04-08 21:26     ` Konrad Rzeszutek Wilk
2016-04-08 22:10       ` Andrew Cooper
2016-04-08 22:48         ` Jan Beulich
2016-04-07  3:49 ` [PATCH v6 09/24] xsplice: Implement payload loading Konrad Rzeszutek Wilk
2016-04-08 15:31   ` Andrew Cooper
2016-04-08 21:10     ` Konrad Rzeszutek Wilk
2016-04-08 21:18       ` Jan Beulich
2016-04-08 22:45         ` Konrad Rzeszutek Wilk
2016-04-08 22:50           ` Jan Beulich
2016-04-09  0:37             ` Konrad Rzeszutek Wilk
2016-04-09 11:48               ` Konrad Rzeszutek Wilk
2016-04-11 15:53               ` Jan Beulich
2016-04-11 16:03                 ` Konrad Rzeszutek Wilk
2016-04-11 16:34                   ` Konrad Rzeszutek Wilk
2016-04-11 16:55                     ` Jan Beulich
2016-04-11 17:08                       ` Konrad Rzeszutek Wilk
2016-04-11 17:26                         ` Jan Beulich
2016-04-11 18:21                           ` Konrad Rzeszutek Wilk
2016-04-11 18:57                             ` Konrad Rzeszutek Wilk
2016-04-08 15:35   ` Julien Grall
2016-04-07  3:49 ` [PATCH v6 10/24] xsplice: Implement support for applying/reverting/replacing patches Konrad Rzeszutek Wilk
2016-04-08 15:36   ` Julien Grall
2016-04-08 16:33   ` Andrew Cooper [this message]
2016-04-07  3:49 ` [PATCH v6 11/24] x86/xen_hello_world.xsplice: Test payload for patching 'xen_extra_version' Konrad Rzeszutek Wilk
2016-04-08 15:37   ` Julien Grall
2016-04-08 16:38   ` Andrew Cooper
2016-04-09  0:45   ` Konrad Rzeszutek Wilk
2016-04-07  3:49 ` [PATCH v6 12/24] xsplice, symbols: Implement symbol name resolution on address Konrad Rzeszutek Wilk
2016-04-08 16:55   ` Andrew Cooper
2016-04-07  3:49 ` [PATCH v6 13/24] x86, xsplice: Print payload's symbol name and payload name in backtraces Konrad Rzeszutek Wilk
2016-04-08 17:00   ` Andrew Cooper
2016-04-07  3:49 ` [PATCH v6 14/24] xsplice: Add support for bug frames Konrad Rzeszutek Wilk
2016-04-08 17:03   ` Andrew Cooper
2016-04-07  3:49 ` [PATCH v6 15/24] xsplice: Add support for exception tables Konrad Rzeszutek Wilk
2016-04-08 17:16   ` Andrew Cooper
2016-04-07  3:49 ` [PATCH v6 16/24] xsplice: Add support for alternatives Konrad Rzeszutek Wilk
2016-04-08 17:34   ` Andrew Cooper
2016-04-08 17:57     ` Jan Beulich
2016-04-07  3:49 ` [PATCH v6 17/24] build_id: Provide ld-embedded build-ids Konrad Rzeszutek Wilk
2016-04-08 15:39   ` Julien Grall
2016-04-08 18:07   ` Andrew Cooper
2016-04-08 19:34     ` Konrad Rzeszutek Wilk
2016-04-07  3:49 ` [PATCH v6 18/24] HYPERCALL_version_op: Add VERSION_build_id to retrieve build-id Konrad Rzeszutek Wilk
2016-04-08 18:07   ` Andrew Cooper
2016-04-07  3:49 ` [PATCH v6 19/24] libxl: info: Display build_id of the hypervisor using XEN_VERSION_build_id Konrad Rzeszutek Wilk
2016-04-07  3:49 ` [PATCH v6 20/24] xsplice: Print build_id in keyhandler and on bootup Konrad Rzeszutek Wilk
2016-04-08 18:12   ` Andrew Cooper
2016-04-07  3:49 ` [PATCH v6 21/24] xsplice: Stacking build-id dependency checking Konrad Rzeszutek Wilk
2016-04-08 18:19   ` Andrew Cooper
2016-04-09  1:43     ` Konrad Rzeszutek Wilk
2016-04-07  3:49 ` [PATCH v6 22/24] xsplice/xen_replace_world: Test-case for XSPLICE_ACTION_REPLACE Konrad Rzeszutek Wilk
2016-04-08 18:20   ` Andrew Cooper
2016-04-07  3:49 ` [PATCH v6 23/24] xsplice: Prevent duplicate payloads from being loaded Konrad Rzeszutek Wilk
2016-04-07 16:36   ` Ian Jackson
2016-04-08 18:21   ` Andrew Cooper
2016-04-07  3:49 ` [PATCH v6 24/24] MAINTAINERS/xsplice: Add myself and Ross as the maintainers Konrad Rzeszutek Wilk
2016-04-08 18:21   ` Andrew Cooper

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5707DD5F.2030804@citrix.com \
    --to=andrew.cooper3@citrix.com \
    --cc=boris.ostrovsky@oracle.com \
    --cc=jbeulich@suse.com \
    --cc=julien.grall@arm.com \
    --cc=jun.nakajima@intel.com \
    --cc=keir@xen.org \
    --cc=kevin.tian@intel.com \
    --cc=konrad.wilk@oracle.com \
    --cc=konrad@kernel.org \
    --cc=mpohlack@amazon.de \
    --cc=ross.lagerwall@citrix.com \
    --cc=sasha.levin@oracle.com \
    --cc=stefano.stabellini@citrix.com \
    --cc=suravee.suthikulpanit@amd.com \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.