From: Jeremy Fitzhardinge <jeremy@goop.org>
To: Andi Kleen <ak@suse.de>
Cc: Andrew Morton <akpm@linux-foundation.org>,
virtualization@lists.osdl.org,
lkml <linux-kernel@vger.kernel.org>,
Chris Wright <chrisw@sous-sol.org>
Subject: [patch 12/32] xen: fix multicall batching
Date: Sun, 29 Apr 2007 10:28:47 -0700 [thread overview]
Message-ID: <20070429172912.853990000@goop.org> (raw)
In-Reply-To: 20070429172835.284784000@goop.org
[-- Attachment #1: xen-fix-multicall.patch --]
[-- Type: text/plain, Size: 7832 bytes --]
Disable interrupts between allocating a multicall entry and actually
issuing it, to prevent an interrupt from coming in, allocating and
initializing further multicall entries, and then issuing them all,
including the partially completed one.
Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com>
---
arch/i386/xen/enlighten.c | 44 +++++++++++++++++++++++++++-----------------
arch/i386/xen/mmu.c | 18 ++++++++++++------
arch/i386/xen/multicalls.c | 9 ++++++++-
arch/i386/xen/multicalls.h | 27 +++++++++++++++++++++++----
arch/i386/xen/xen-ops.h | 5 +----
5 files changed, 71 insertions(+), 32 deletions(-)
===================================================================
--- a/arch/i386/xen/enlighten.c
+++ b/arch/i386/xen/enlighten.c
@@ -187,13 +187,25 @@ static void xen_halt(void)
static void xen_set_lazy_mode(enum paravirt_lazy_mode mode)
{
- enum paravirt_lazy_mode *lazy = &get_cpu_var(xen_lazy_mode);
+ switch(mode) {
+ case PARAVIRT_LAZY_NONE:
+ BUG_ON(x86_read_percpu(xen_lazy_mode) == PARAVIRT_LAZY_NONE);
+ break;
+
+ case PARAVIRT_LAZY_MMU:
+ case PARAVIRT_LAZY_CPU:
+ BUG_ON(x86_read_percpu(xen_lazy_mode) != PARAVIRT_LAZY_NONE);
+ break;
+
+ case PARAVIRT_LAZY_FLUSH:
+ /* flush if necessary, but don't change state */
+ if (x86_read_percpu(xen_lazy_mode) != PARAVIRT_LAZY_NONE)
+ xen_mc_flush();
+ return;
+ }
xen_mc_flush();
-
- *lazy = mode;
-
- put_cpu_var(xen_lazy_mode);
+ x86_write_percpu(xen_lazy_mode, mode);
}
static unsigned long xen_store_tr(void)
@@ -220,7 +232,7 @@ static void xen_set_ldt(const void *addr
MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
- xen_mc_issue();
+ xen_mc_issue(PARAVIRT_LAZY_CPU);
}
static void xen_load_gdt(const struct Xgt_desc_struct *dtr)
@@ -248,7 +260,7 @@ static void xen_load_gdt(const struct Xg
MULTI_set_gdt(mcs.mc, frames, size / sizeof(struct desc_struct));
- xen_mc_issue();
+ xen_mc_issue(PARAVIRT_LAZY_CPU);
}
static void load_TLS_descriptor(struct thread_struct *t,
@@ -256,18 +268,20 @@ static void load_TLS_descriptor(struct t
{
struct desc_struct *gdt = get_cpu_gdt_table(cpu);
xmaddr_t maddr = virt_to_machine(&gdt[GDT_ENTRY_TLS_MIN+i]);
- struct multicall_space mc = xen_mc_entry(0);
+ struct multicall_space mc = __xen_mc_entry(0);
MULTI_update_descriptor(mc.mc, maddr.maddr, t->tls_array[i]);
}
static void xen_load_tls(struct thread_struct *t, unsigned int cpu)
{
+ xen_mc_batch();
+
load_TLS_descriptor(t, cpu, 0);
load_TLS_descriptor(t, cpu, 1);
load_TLS_descriptor(t, cpu, 2);
- xen_mc_issue();
+ xen_mc_issue(PARAVIRT_LAZY_CPU);
}
static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum, u32 low, u32 high)
@@ -387,13 +401,9 @@ static void xen_load_esp0(struct tss_str
static void xen_load_esp0(struct tss_struct *tss,
struct thread_struct *thread)
{
- if (xen_get_lazy_mode() != PARAVIRT_LAZY_CPU) {
- if (HYPERVISOR_stack_switch(__KERNEL_DS, thread->esp0))
- BUG();
- } else {
- struct multicall_space mcs = xen_mc_entry(0);
- MULTI_stack_switch(mcs.mc, __KERNEL_DS, thread->esp0);
- }
+ struct multicall_space mcs = xen_mc_entry(0);
+ MULTI_stack_switch(mcs.mc, __KERNEL_DS, thread->esp0);
+ xen_mc_issue(PARAVIRT_LAZY_CPU);
}
static void xen_set_iopl_mask(unsigned mask)
@@ -485,7 +495,7 @@ static void xen_write_cr3(unsigned long
MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
- xen_mc_issue();
+ xen_mc_issue(PARAVIRT_LAZY_CPU);
}
}
===================================================================
--- a/arch/i386/xen/mmu.c
+++ b/arch/i386/xen/mmu.c
@@ -366,7 +366,7 @@ static int pin_page(struct page *page, u
else {
void *pt = lowmem_page_address(page);
unsigned long pfn = page_to_pfn(page);
- struct multicall_space mcs = xen_mc_entry(0);
+ struct multicall_space mcs = __xen_mc_entry(0);
flush = 0;
@@ -386,10 +386,12 @@ void xen_pgd_pin(pgd_t *pgd)
struct multicall_space mcs;
struct mmuext_op *op;
+ xen_mc_batch();
+
if (pgd_walk(pgd, pin_page, TASK_SIZE))
kmap_flush_unused();
- mcs = xen_mc_entry(sizeof(*op));
+ mcs = __xen_mc_entry(sizeof(*op));
op = mcs.args;
#ifdef CONFIG_X86_PAE
@@ -400,7 +402,7 @@ void xen_pgd_pin(pgd_t *pgd)
op->arg1.mfn = pfn_to_mfn(PFN_DOWN(__pa(pgd)));
MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
- xen_mc_flush();
+ xen_mc_issue(0);
}
/* The init_mm pagetable is really pinned as soon as its created, but
@@ -424,7 +426,7 @@ static int unpin_page(struct page *page,
if (pgfl && !PageHighMem(page)) {
void *pt = lowmem_page_address(page);
unsigned long pfn = page_to_pfn(page);
- struct multicall_space mcs = xen_mc_entry(0);
+ struct multicall_space mcs = __xen_mc_entry(0);
MULTI_update_va_mapping(mcs.mc, (unsigned long)pt,
pfn_pte(pfn, PAGE_KERNEL),
@@ -438,7 +440,11 @@ static void xen_pgd_unpin(pgd_t *pgd)
static void xen_pgd_unpin(pgd_t *pgd)
{
struct mmuext_op *op;
- struct multicall_space mcs = xen_mc_entry(sizeof(*op));
+ struct multicall_space mcs;
+
+ xen_mc_batch();
+
+ mcs = __xen_mc_entry(sizeof(*op));
op = mcs.args;
op->cmd = MMUEXT_UNPIN_TABLE;
@@ -448,7 +454,7 @@ static void xen_pgd_unpin(pgd_t *pgd)
pgd_walk(pgd, unpin_page, TASK_SIZE);
- xen_mc_flush();
+ xen_mc_issue(0);
}
===================================================================
--- a/arch/i386/xen/multicalls.c
+++ b/arch/i386/xen/multicalls.c
@@ -35,11 +35,17 @@ struct mc_buffer {
};
static DEFINE_PER_CPU(struct mc_buffer, mc_buffer);
+DEFINE_PER_CPU(unsigned long, xen_mc_irq_flags);
void xen_mc_flush(void)
{
struct mc_buffer *b = &get_cpu_var(mc_buffer);
int ret = 0;
+ unsigned long flags;
+
+ /* Disable interrupts in case someone comes in and queues
+ something in the middle */
+ local_irq_save(flags);
if (b->mcidx) {
int i;
@@ -55,11 +61,12 @@ void xen_mc_flush(void)
BUG_ON(b->argidx != 0);
put_cpu_var(mc_buffer);
+ local_irq_restore(flags);
BUG_ON(ret);
}
-struct multicall_space xen_mc_entry(size_t args)
+struct multicall_space __xen_mc_entry(size_t args)
{
struct mc_buffer *b = &get_cpu_var(mc_buffer);
struct multicall_space ret;
===================================================================
--- a/arch/i386/xen/multicalls.h
+++ b/arch/i386/xen/multicalls.h
@@ -11,16 +11,35 @@ struct multicall_space
};
/* Allocate room for a multicall and its args */
-struct multicall_space xen_mc_entry(size_t args);
+struct multicall_space __xen_mc_entry(size_t args);
+
+DECLARE_PER_CPU(unsigned long, xen_mc_irq_flags);
+
+/* Call to start a batch of multiple __xen_mc_entry()s. Must be
+ paired with xen_mc_issue() */
+static inline void xen_mc_batch(void)
+{
+ /* need to disable interrupts until this entry is complete */
+ local_irq_save(__get_cpu_var(xen_mc_irq_flags));
+}
+
+static inline struct multicall_space xen_mc_entry(size_t args)
+{
+ xen_mc_batch();
+ return __xen_mc_entry(args);
+}
/* Flush all pending multicalls */
void xen_mc_flush(void);
-/* Issue a multicall if we're not in lazy mode */
-static inline void xen_mc_issue(void)
+/* Issue a multicall if we're not in a lazy mode */
+static inline void xen_mc_issue(unsigned mode)
{
- if (xen_get_lazy_mode() == PARAVIRT_LAZY_NONE)
+ if ((xen_get_lazy_mode() & mode) == 0)
xen_mc_flush();
+
+ /* restore flags saved in xen_mc_batch */
+ local_irq_restore(x86_read_percpu(xen_mc_irq_flags));
}
#endif /* _XEN_MULTICALLS_H */
===================================================================
--- a/arch/i386/xen/xen-ops.h
+++ b/arch/i386/xen/xen-ops.h
@@ -26,10 +26,7 @@ DECLARE_PER_CPU(enum paravirt_lazy_mode,
static inline unsigned xen_get_lazy_mode(void)
{
- unsigned ret = get_cpu_var(xen_lazy_mode);
- put_cpu_var(xen_lazy_mode);
-
- return ret;
+ return x86_read_percpu(xen_lazy_mode);
}
--
next prev parent reply other threads:[~2007-04-29 17:28 UTC|newest]
Thread overview: 44+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-04-29 17:28 [patch 00/32] xen: Xen implementation for paravirt_ops Jeremy Fitzhardinge
2007-04-29 17:28 ` [patch 01/32] xen: Add apply_to_page_range() which applies a function to a pte range Jeremy Fitzhardinge
2007-04-29 17:28 ` [patch 02/32] xen: Allocate and free vmalloc areas Jeremy Fitzhardinge
2007-04-29 17:28 ` [patch 03/32] xen: Add nosegneg capability to the vsyscall page notes Jeremy Fitzhardinge
2007-04-29 19:08 ` Roland McGrath
2007-04-30 4:54 ` Jeremy Fitzhardinge
2007-04-29 17:28 ` [patch 04/32] xen: Add Xen interface header files Jeremy Fitzhardinge
2007-04-29 17:28 ` [patch 05/32] xen: Core Xen implementation Jeremy Fitzhardinge
2007-04-29 17:28 ` [patch 06/32] xen: Xen virtual mmu Jeremy Fitzhardinge
2007-04-29 17:28 ` [patch 07/32] xen: xen event channels Jeremy Fitzhardinge
2007-04-29 17:28 ` [patch 08/32] xen: xen time implementation Jeremy Fitzhardinge
2007-04-29 17:28 ` [patch 09/32] xen: xen configuration Jeremy Fitzhardinge
2007-04-30 22:36 ` Zachary Amsden
2007-05-01 3:37 ` Andi Kleen
2007-04-29 17:28 ` [patch 10/32] xen: Complete pagetable pinning for Xen Jeremy Fitzhardinge
2007-04-29 17:28 ` [patch 11/32] xen: ignore RW mapping of RO pages in pagetable_init Jeremy Fitzhardinge
2007-04-29 17:28 ` Jeremy Fitzhardinge [this message]
2007-04-29 17:28 ` [patch 13/32] xen: Account for time stolen by Xen Jeremy Fitzhardinge
2007-04-29 17:28 ` [patch 14/32] xen: Implement xen_sched_clock Jeremy Fitzhardinge
2007-04-29 17:28 ` [patch 15/32] xen: Xen SMP guest support Jeremy Fitzhardinge
2007-04-29 17:28 ` [patch 16/32] xen: Add support for preemption Jeremy Fitzhardinge
2007-04-29 17:28 ` [patch 17/32] xen: lazy-mmu operations Jeremy Fitzhardinge
2007-04-29 17:28 ` [patch 18/32] xen: deal with negative stolen time Jeremy Fitzhardinge
2007-04-29 17:28 ` [patch 19/32] xen: xen time fixups Jeremy Fitzhardinge
2007-04-29 17:28 ` [patch 20/32] xen: Use the hvc console infrastructure for Xen console Jeremy Fitzhardinge
2007-04-29 17:28 ` [patch 21/32] xen: Add early printk support via hvc console Jeremy Fitzhardinge
2007-04-29 17:28 ` [patch 22/32] xen: Add Xen grant table support Jeremy Fitzhardinge
2007-04-29 17:28 ` [patch 23/32] xen: Add the Xenbus sysfs and virtual device hotplug driver Jeremy Fitzhardinge
2007-04-29 17:28 ` [patch 24/32] xen: use xenbus_watch_pathfmt rather than watch_path2 Jeremy Fitzhardinge
2007-04-29 17:29 ` [patch 25/32] xen: rename dev_changed to xenbus_dev_changed Jeremy Fitzhardinge
2007-04-29 17:29 ` [patch 26/32] xen: Add Xen virtual block device driver Jeremy Fitzhardinge
2007-04-29 18:16 ` Christoph Hellwig
2007-04-30 18:52 ` Jeremy Fitzhardinge
2007-04-29 17:29 ` [patch 27/32] xen: Add the Xen virtual network " Jeremy Fitzhardinge
2007-04-29 17:59 ` Christoph Hellwig
2007-04-30 18:11 ` Jeremy Fitzhardinge
2007-04-29 17:29 ` [patch 28/32] xen: xen-netfront: use skb.cb for storing private data Jeremy Fitzhardinge
2007-04-29 17:29 ` [patch 29/32] xen: Lockdep fixes for xen-netfront Jeremy Fitzhardinge
2007-04-29 17:29 ` [patch 30/32] xen: diddle netfront Jeremy Fitzhardinge
2007-04-29 17:29 ` [patch 31/32] xen: --- drivers/net/xen-netfront.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) Jeremy Fitzhardinge
2007-05-02 6:33 ` Herbert Xu
2007-05-02 6:45 ` Chris Wright
2007-05-02 6:48 ` Jeremy Fitzhardinge
2007-04-29 17:29 ` [patch 32/32] xen: Xen machine operations Jeremy Fitzhardinge
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=20070429172912.853990000@goop.org \
--to=jeremy@goop.org \
--cc=ak@suse.de \
--cc=akpm@linux-foundation.org \
--cc=chrisw@sous-sol.org \
--cc=linux-kernel@vger.kernel.org \
--cc=virtualization@lists.osdl.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).