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
next prev 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).