virtualization.lists.linux-foundation.org archive mirror
 help / color / mirror / Atom feed
From: Jeremy Fitzhardinge <jeremy@goop.org>
To: Andi Kleen <ak@suse.de>
Cc: virtualization@lists.osdl.org,
	Andrew Morton <akpm@linux-foundation.org>,
	lkml <linux-kernel@vger.kernel.org>
Subject: [PATCH 08/25] xen: xen: fix multicall batching
Date: Mon, 23 Apr 2007 14:56:46 -0700	[thread overview]
Message-ID: <20070423215710.683563417@goop.org> (raw)
In-Reply-To: 20070423215638.563901986@goop.org

[-- Attachment #1: xen-fix-multicall.patch --]
[-- Type: text/plain, Size: 7805 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
@@ -160,13 +160,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)
@@ -193,7 +208,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)
@@ -217,7 +232,7 @@ static void xen_load_gdt(const struct Xg
 
 	MULTI_set_gdt(mcs.mc, frames, size/8);
 
-	xen_mc_issue();
+	xen_mc_issue(PARAVIRT_LAZY_CPU);
 }
 
 static void load_TLS_descriptor(struct thread_struct *t,
@@ -225,18 +240,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)
@@ -356,13 +373,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)
@@ -452,7 +465,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
@@ -344,7 +344,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;
 
@@ -364,10 +364,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
@@ -378,7 +380,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
@@ -402,7 +404,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),
@@ -416,7 +418,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;
@@ -426,7 +432,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
@@ -14,11 +14,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;
@@ -34,11 +40,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);
 }
 
 

-- 

  parent reply	other threads:[~2007-04-23 21:56 UTC|newest]

Thread overview: 67+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-04-23 21:56 [PATCH 00/25] xen: Xen implementation for paravirt_ops Jeremy Fitzhardinge
2007-04-23 21:56 ` [PATCH 01/25] xen: Add apply_to_page_range() which applies a function to a pte range Jeremy Fitzhardinge
2007-04-23 21:56 ` [PATCH 02/25] xen: Allocate and free vmalloc areas Jeremy Fitzhardinge
2007-04-23 21:56 ` [PATCH 03/25] xen: Add nosegneg capability to the vsyscall page notes Jeremy Fitzhardinge
2007-04-23 23:29   ` Roland McGrath
2007-04-24  1:24     ` Jeremy Fitzhardinge
2007-04-24  4:26       ` Roland McGrath
2007-04-24  6:19         ` Jeremy Fitzhardinge
2007-04-23 21:56 ` [PATCH 04/25] xen: Add XEN config options Jeremy Fitzhardinge
2007-04-23 23:00   ` Andi Kleen
2007-04-23 23:11     ` Jeremy Fitzhardinge
2007-04-24 19:45       ` Andi Kleen
2007-04-23 21:56 ` [PATCH 05/25] xen: Add Xen interface header files Jeremy Fitzhardinge
2007-04-23 21:56 ` [PATCH 06/25] xen: Core Xen implementation Jeremy Fitzhardinge
2007-04-24 21:25   ` Andi Kleen
2007-04-25  2:02     ` Jeremy Fitzhardinge
2007-04-25  9:12     ` Andi Kleen
2007-04-25 19:41       ` Jeremy Fitzhardinge
2007-04-25 19:43         ` Andi Kleen
2007-04-25 19:44           ` [PATCH 06/25] xen: Core Xen implementation II Andi Kleen
2007-04-25 20:03           ` [PATCH 06/25] xen: Core Xen implementation Jeremy Fitzhardinge
2007-04-25 20:17             ` Andi Kleen
2007-04-25 20:20               ` Jeremy Fitzhardinge
2007-04-27  7:08     ` Jeremy Fitzhardinge
2007-04-27  7:31       ` Keir Fraser
2007-04-23 21:56 ` [PATCH 07/25] xen: Complete pagetable pinning for Xen Jeremy Fitzhardinge
2007-04-23 21:56 ` Jeremy Fitzhardinge [this message]
2007-04-23 21:56 ` [PATCH 09/25] xen: Account for time stolen by Xen Jeremy Fitzhardinge
2007-04-25  9:15   ` Andi Kleen
2007-04-25 18:13     ` Jeremy Fitzhardinge
2007-04-25 18:15       ` Andi Kleen
2007-04-25 18:40         ` Jeremy Fitzhardinge
2007-04-23 21:56 ` [PATCH 10/25] xen: Implement xen_sched_clock Jeremy Fitzhardinge
2007-04-23 21:56 ` [PATCH 11/25] xen: Xen SMP guest support Jeremy Fitzhardinge
2007-04-25  9:24   ` Andi Kleen
2007-04-25 18:45     ` Jeremy Fitzhardinge
2007-04-27  6:46     ` Jeremy Fitzhardinge
2007-04-27  9:10       ` Andi Kleen
2007-04-23 21:56 ` [PATCH 12/25] xen: Add support for preemption Jeremy Fitzhardinge
2007-04-23 21:56 ` [PATCH 13/25] xen: xen: lazy-mmu operations Jeremy Fitzhardinge
2007-04-23 21:56 ` [PATCH 14/25] xen: xen: deal with negative stolen time Jeremy Fitzhardinge
2007-04-23 21:56 ` [PATCH 15/25] xen: xen time fixups Jeremy Fitzhardinge
2007-04-23 21:56 ` [PATCH 16/25] xen: Use the hvc console infrastructure for Xen console Jeremy Fitzhardinge
2007-04-24  1:21   ` Olof Johansson
2007-04-24 20:01     ` Jeremy Fitzhardinge
2007-04-23 21:56 ` [PATCH 17/25] xen: Add early printk support via hvc console Jeremy Fitzhardinge
2007-04-23 21:56 ` [PATCH 18/25] xen: Add Xen grant table support Jeremy Fitzhardinge
2007-04-23 21:56 ` [PATCH 19/25] xen: Add the Xenbus sysfs and virtual device hotplug driver Jeremy Fitzhardinge
2007-04-23 21:56 ` [PATCH 20/25] xen: Add Xen virtual block device driver Jeremy Fitzhardinge
2007-04-23 21:56 ` [PATCH 21/25] xen: Add the Xen virtual network " Jeremy Fitzhardinge
2007-04-23 21:57 ` [PATCH 22/25] xen: xen-netfront: use skb.cb for storing private data Jeremy Fitzhardinge
2007-04-24  1:45   ` Herbert Xu
2007-04-24  4:34     ` Jeremy Fitzhardinge
2007-04-24  5:57       ` Herbert Xu
2007-04-27 22:19         ` Jeremy Fitzhardinge
2007-04-27 22:37           ` Herbert Xu
2007-04-27 23:27             ` Jeremy Fitzhardinge
2007-04-28  6:28               ` Herbert Xu
2007-04-29  7:43                 ` Jeremy Fitzhardinge
2007-04-29  8:05                   ` Herbert Xu
2007-04-23 21:57 ` [PATCH 23/25] xen: Lockdep fixes for xen-netfront Jeremy Fitzhardinge
2007-04-24  3:22   ` Herbert Xu
2007-04-24  4:36     ` Jeremy Fitzhardinge
2007-04-23 21:57 ` [PATCH 24/25] xen: xen: diddle netfront Jeremy Fitzhardinge
2007-04-23 21:57 ` [PATCH 25/25] xen: Xen machine operations Jeremy Fitzhardinge
2007-04-23 22:50 ` [PATCH 00/25] xen: Xen implementation for paravirt_ops Andi Kleen
2007-04-23 23:09   ` 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=20070423215710.683563417@goop.org \
    --to=jeremy@goop.org \
    --cc=ak@suse.de \
    --cc=akpm@linux-foundation.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).