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 12/25] xen: Add support for preemption
Date: Mon, 23 Apr 2007 14:56:50 -0700	[thread overview]
Message-ID: <20070423215711.414711879@goop.org> (raw)
In-Reply-To: 20070423215638.563901986@goop.org

[-- Attachment #1: xen-preempt.patch --]
[-- Type: text/plain, Size: 9359 bytes --]

Add Xen support for preemption.  This is mostly a cleanup of existing
preempt_enable/disable calls, or just comments to explain the current
usage.

Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com>

---
 arch/i386/xen/Kconfig      |    2 
 arch/i386/xen/enlighten.c  |   93 ++++++++++++++++++++++++++++----------------
 arch/i386/xen/mmu.c        |    4 +
 arch/i386/xen/multicalls.c |   11 ++---
 arch/i386/xen/time.c       |   22 ++++++++--
 5 files changed, 88 insertions(+), 44 deletions(-)

===================================================================
--- a/arch/i386/xen/Kconfig
+++ b/arch/i386/xen/Kconfig
@@ -4,7 +4,7 @@
 
 config XEN
 	bool "Enable support for Xen hypervisor"
-	depends on PARAVIRT && !PREEMPT
+	depends on PARAVIRT
 	default y
 	help
 	  This is the Linux Xen port.
===================================================================
--- a/arch/i386/xen/enlighten.c
+++ b/arch/i386/xen/enlighten.c
@@ -2,6 +2,7 @@
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <linux/preempt.h>
+#include <linux/hardirq.h>
 #include <linux/percpu.h>
 #include <linux/delay.h>
 #include <linux/start_kernel.h>
@@ -92,11 +93,10 @@ static unsigned long xen_save_fl(void)
 	struct vcpu_info *vcpu;
 	unsigned long flags;
 
-	preempt_disable();
 	vcpu = x86_read_percpu(xen_vcpu);
+
 	/* flag has opposite sense of mask */
 	flags = !vcpu->evtchn_upcall_mask;
-	preempt_enable();
 
 	/* convert to IF type flag
 	   -0 -> 0x00000000
@@ -109,41 +109,56 @@ static void xen_restore_fl(unsigned long
 {
 	struct vcpu_info *vcpu;
 
-	preempt_disable();
-
 	/* convert from IF type flag */
 	flags = !(flags & X86_EFLAGS_IF);
+
+	/* There's a one instruction preempt window here.  We need to
+	   make sure we're don't switch CPUs between getting the vcpu
+	   pointer and updating the mask. */
+	preempt_disable();
 	vcpu = x86_read_percpu(xen_vcpu);
 	vcpu->evtchn_upcall_mask = flags;
+	preempt_enable_no_resched();
+
+	/* Doesn't matter if we get preempted here, because any
+	   pending event will get dealt with anyway. */
+
 	if (flags == 0) {
+		preempt_check_resched();
 		barrier(); /* unmask then check (avoid races) */
 		if (unlikely(vcpu->evtchn_upcall_pending))
 			force_evtchn_callback();
-		preempt_enable();
-	} else
-		preempt_enable_no_resched();
+	}
 }
 
 static void xen_irq_disable(void)
 {
+	/* There's a one instruction preempt window here.  We need to
+	   make sure we're don't switch CPUs between getting the vcpu
+	   pointer and updating the mask. */
+	preempt_disable();
+	x86_read_percpu(xen_vcpu)->evtchn_upcall_mask = 1;
+	preempt_enable_no_resched();
+}
+
+static void xen_irq_enable(void)
+{
 	struct vcpu_info *vcpu;
-	preempt_disable();
-	vcpu = x86_read_percpu(xen_vcpu);
-	vcpu->evtchn_upcall_mask = 1;
-	preempt_enable_no_resched();
-}
-
-static void xen_irq_enable(void)
-{
-	struct vcpu_info *vcpu;
-
+
+	/* There's a one instruction preempt window here.  We need to
+	   make sure we're don't switch CPUs between getting the vcpu
+	   pointer and updating the mask. */
 	preempt_disable();
 	vcpu = x86_read_percpu(xen_vcpu);
 	vcpu->evtchn_upcall_mask = 0;
+	preempt_enable_no_resched();
+
+	/* Doesn't matter if we get preempted here, because any
+	   pending event will get dealt with anyway. */
+
 	barrier(); /* unmask then check (avoid races) */
 	if (unlikely(vcpu->evtchn_upcall_pending))
 		force_evtchn_callback();
-	preempt_enable();
 }
 
 static void xen_safe_halt(void)
@@ -163,6 +178,8 @@ static void xen_halt(void)
 
 static void xen_set_lazy_mode(enum paravirt_lazy_mode mode)
 {
+	BUG_ON(preemptible());
+
 	switch(mode) {
 	case PARAVIRT_LAZY_NONE:
 		BUG_ON(x86_read_percpu(xen_lazy_mode) == PARAVIRT_LAZY_NONE);
@@ -262,12 +279,17 @@ static void xen_write_ldt_entry(struct d
 	xmaddr_t mach_lp = virt_to_machine(lp);
 	u64 entry = (u64)high << 32 | low;
 
+	preempt_disable();
+
 	xen_mc_flush();
 	if (HYPERVISOR_update_descriptor(mach_lp.maddr, entry))
 		BUG();
-}
-
-static int cvt_gate_to_trap(int vector, u32 low, u32 high, struct trap_info *info)
+
+	preempt_enable();
+}
+
+static int cvt_gate_to_trap(int vector, u32 low, u32 high,
+			    struct trap_info *info)
 {
 	u8 type, dpl;
 
@@ -295,11 +317,13 @@ static DEFINE_PER_CPU(struct Xgt_desc_st
    also update Xen. */
 static void xen_write_idt_entry(struct desc_struct *dt, int entrynum, u32 low, u32 high)
 {
-
-	int cpu = smp_processor_id();
 	unsigned long p = (unsigned long)&dt[entrynum];
-	unsigned long start = per_cpu(idt_desc, cpu).address;
-	unsigned long end = start + per_cpu(idt_desc, cpu).size + 1;
+	unsigned long start, end;
+
+	preempt_disable();
+
+	start = __get_cpu_var(idt_desc).address;
+	end = start + __get_cpu_var(idt_desc).size + 1;
 
 	xen_mc_flush();
 
@@ -314,6 +338,8 @@ static void xen_write_idt_entry(struct d
 			if (HYPERVISOR_set_trap_table(info))
 				BUG();
 	}
+
+	preempt_enable();
 }
 
 static void xen_convert_trap_info(const struct Xgt_desc_struct *desc,
@@ -335,11 +361,9 @@ static void xen_convert_trap_info(const 
 
 void xen_copy_trap_info(struct trap_info *traps)
 {
-	const struct Xgt_desc_struct *desc = &get_cpu_var(idt_desc);
+	const struct Xgt_desc_struct *desc = &__get_cpu_var(idt_desc);
 
 	xen_convert_trap_info(desc, traps);
-
-	put_cpu_var(idt_desc);
 }
 
 /* Load a new IDT into Xen.  In principle this can be per-CPU, so we
@@ -349,11 +373,10 @@ static void xen_load_idt(const struct Xg
 {
 	static DEFINE_SPINLOCK(lock);
 	static struct trap_info traps[257];
-	int cpu = smp_processor_id();
-
-	per_cpu(idt_desc, cpu) = *desc;
 
 	spin_lock(&lock);
+
+	__get_cpu_var(idt_desc) = *desc;
 
 	xen_convert_trap_info(desc, traps);
 
@@ -368,6 +391,8 @@ static void xen_load_idt(const struct Xg
    they're handled differently. */
 static void xen_write_gdt_entry(struct desc_struct *dt, int entry, u32 low, u32 high)
 {
+	preempt_disable();
+
 	switch ((high >> 8) & 0xff) {
 	case DESCTYPE_LDT:
 	case DESCTYPE_TSS:
@@ -384,10 +409,12 @@ static void xen_write_gdt_entry(struct d
 	}
 
 	}
+
+	preempt_enable();
 }
 
 static void xen_load_esp0(struct tss_struct *tss,
-				   struct thread_struct *thread)
+			  struct thread_struct *thread)
 {
 	struct multicall_space mcs = xen_mc_entry(0);
 	MULTI_stack_switch(mcs.mc, __KERNEL_DS, thread->esp0);
@@ -493,6 +520,8 @@ static unsigned long xen_read_cr3(void)
 
 static void xen_write_cr3(unsigned long cr3)
 {
+	BUG_ON(preemptible());
+
 	if (cr3 == x86_read_percpu(xen_cr3)) {
 		/* just a simple tlb flush */
 		xen_flush_tlb();
===================================================================
--- a/arch/i386/xen/mmu.c
+++ b/arch/i386/xen/mmu.c
@@ -481,5 +481,7 @@ void xen_exit_mmap(struct mm_struct *mm)
 
 	preempt_enable();
 
+	spin_lock(&mm->page_table_lock);
 	xen_pgd_unpin(mm->pgd);
-}
+	spin_unlock(&mm->page_table_lock);
+}
===================================================================
--- a/arch/i386/xen/multicalls.c
+++ b/arch/i386/xen/multicalls.c
@@ -1,4 +1,5 @@
 #include <linux/percpu.h>
+#include <linux/hardirq.h>
 
 #include <asm/xen/hypercall.h>
 
@@ -18,9 +19,11 @@ DEFINE_PER_CPU(unsigned long, xen_mc_irq
 
 void xen_mc_flush(void)
 {
-	struct mc_buffer *b = &get_cpu_var(mc_buffer);
+	struct mc_buffer *b = &__get_cpu_var(mc_buffer);
 	int ret = 0;
 	unsigned long flags;
+
+	BUG_ON(preemptible());
 
 	/* Disable interrupts in case someone comes in and queues
 	   something in the middle */
@@ -39,7 +42,6 @@ void xen_mc_flush(void)
 	} else
 		BUG_ON(b->argidx != 0);
 
-	put_cpu_var(mc_buffer);
 	local_irq_restore(flags);
 
 	BUG_ON(ret);
@@ -47,10 +49,11 @@ void xen_mc_flush(void)
 
 struct multicall_space __xen_mc_entry(size_t args)
 {
-	struct mc_buffer *b = &get_cpu_var(mc_buffer);
+	struct mc_buffer *b = &__get_cpu_var(mc_buffer);
 	struct multicall_space ret;
 	unsigned argspace = (args + sizeof(u64) - 1) / sizeof(u64);
 
+	BUG_ON(preemptible());
 	BUG_ON(argspace > MC_ARGS);
 
 	if (b->mcidx == MC_BATCH ||
@@ -62,7 +65,5 @@ struct multicall_space __xen_mc_entry(si
 	ret.args = &b->args[b->argidx];
 	b->argidx += argspace;
 
-	put_cpu_var(mc_buffer);
-
 	return ret;
 }
===================================================================
--- a/arch/i386/xen/time.c
+++ b/arch/i386/xen/time.c
@@ -48,7 +48,7 @@ static void get_runstate_snapshot(struct
 	u64 state_time;
 	struct vcpu_runstate_info *state;
 
-	preempt_disable();
+	BUG_ON(preemptible());
 
 	state = &__get_cpu_var(runstate);
 
@@ -58,8 +58,6 @@ static void get_runstate_snapshot(struct
 		*res = *state;
 		barrier();
 	} while(state->state_entry_time != state_time);
-
-	preempt_enable();
 }
 
 static void setup_runstate_info(void)
@@ -128,15 +126,29 @@ unsigned long long xen_sched_clock(void)
 unsigned long long xen_sched_clock(void)
 {
 	struct vcpu_runstate_info state;
-	cycle_t now = xen_clocksource_read();
+	cycle_t now;
+	unsigned long long ret;
+
+	/*
+	 * Ideally sched_clock should be called on a per-cpu basis
+	 * anyway, so preempt should already be disabled, but that's
+	 * not current practice at the moment.
+	 */
+	preempt_disable();
+
+	now = xen_clocksource_read();
 
 	get_runstate_snapshot(&state);
 
 	WARN_ON(state.state != RUNSTATE_running);
 
-	return state.time[RUNSTATE_blocked] +
+	ret = state.time[RUNSTATE_blocked] +
 		state.time[RUNSTATE_running] +
 		(now - state.state_entry_time);
+
+	preempt_enable();
+
+	return ret;
 }
 
 

-- 

  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 ` [PATCH 08/25] xen: xen: fix multicall batching Jeremy Fitzhardinge
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 ` Jeremy Fitzhardinge [this message]
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=20070423215711.414711879@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).