From: Jeremy Fitzhardinge <jeremy@goop.org>
To: Andi Kleen <ak@suse.de>
Cc: Chris Wright <chrisw@sous-sol.org>,
virtualization@lists.osdl.org,
Andrew Morton <akpm@linux-foundation.org>,
lkml <linux-kernel@vger.kernel.org>
Subject: [patch 16/29] xen: Add support for preemption
Date: Fri, 04 May 2007 16:21:07 -0700 [thread overview]
Message-ID: <20070504232120.599172076@goop.org> (raw)
In-Reply-To: 20070504232051.411946839@goop.org
[-- Attachment #1: xen-preempt.patch --]
[-- Type: text/plain, Size: 9795 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>
Acked-by: Chris Wright <chrisw@sous-sol.org>
---
arch/i386/xen/Kconfig | 2
arch/i386/xen/enlighten.c | 105 +++++++++++++++++++++++++-------------------
arch/i386/xen/mmu.c | 4 +
arch/i386/xen/multicalls.c | 11 ++--
arch/i386/xen/time.c | 22 +++++++--
5 files changed, 89 insertions(+), 55 deletions(-)
===================================================================
--- a/arch/i386/xen/Kconfig
+++ b/arch/i386/xen/Kconfig
@@ -4,6 +4,6 @@
config XEN
bool "Enable support for Xen hypervisor"
- depends on PARAVIRT && !PREEMPT
+ depends on PARAVIRT
help
This is the Linux Xen port.
===================================================================
--- a/arch/i386/xen/enlighten.c
+++ b/arch/i386/xen/enlighten.c
@@ -15,6 +15,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>
@@ -108,11 +109,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
@@ -125,51 +125,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) {
- /* Unmask then check (avoid races). We're only protecting
- against updates by this CPU, so there's no need for
- anything stronger. */
- barrier();
-
+ 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;
-
- /* Unmask then check (avoid races). We're only protecting
- against updates by this CPU, so there's no need for
- anything stronger. */
- barrier();
-
+ 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)
@@ -189,6 +194,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);
@@ -292,12 +299,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;
@@ -325,11 +337,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();
@@ -344,6 +358,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,
@@ -365,11 +381,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
@@ -379,11 +393,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);
@@ -398,6 +411,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:
@@ -414,10 +429,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);
@@ -523,6 +540,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
@@ -520,5 +520,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
@@ -20,6 +20,7 @@
* Jeremy Fitzhardinge <jeremy@xensource.com>, XenSource Inc, 2007
*/
#include <linux/percpu.h>
+#include <linux/hardirq.h>
#include <asm/xen/hypercall.h>
@@ -39,9 +40,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 */
@@ -60,7 +63,6 @@ void xen_mc_flush(void)
} else
BUG_ON(b->argidx != 0);
- put_cpu_var(mc_buffer);
local_irq_restore(flags);
BUG_ON(ret);
@@ -68,10 +70,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 ||
@@ -83,7 +86,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
@@ -57,7 +57,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);
@@ -72,8 +72,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)
@@ -142,15 +140,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;
}
--
next prev parent reply other threads:[~2007-05-04 23:21 UTC|newest]
Thread overview: 55+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-05-04 23:20 [patch 00/29] xen: Xen implementation for paravirt_ops Jeremy Fitzhardinge
2007-05-04 23:20 ` [patch 01/29] xen: Add apply_to_page_range() which applies a function to a pte range Jeremy Fitzhardinge
2007-05-04 23:20 ` [patch 02/29] xen: Allocate and free vmalloc areas Jeremy Fitzhardinge
2007-05-04 23:20 ` [patch 03/29] xen: Add nosegneg capability to the vsyscall page notes Jeremy Fitzhardinge
2007-05-04 23:20 ` [patch 04/29] xen: Add Xen interface header files Jeremy Fitzhardinge
2007-05-04 23:20 ` [patch 05/29] xen: Core Xen implementation Jeremy Fitzhardinge
2007-05-04 23:20 ` [patch 06/29] xen: Xen virtual mmu Jeremy Fitzhardinge
2007-05-04 23:20 ` [patch 07/29] xen: xen event channels Jeremy Fitzhardinge
2007-05-04 23:20 ` [patch 08/29] xen: xen time implementation Jeremy Fitzhardinge
2007-05-04 23:21 ` [patch 09/29] xen: xen configuration Jeremy Fitzhardinge
2007-05-04 23:21 ` [patch 10/29] xen: Complete pagetable pinning for Xen Jeremy Fitzhardinge
2007-05-04 23:21 ` [patch 11/29] xen: ignore RW mapping of RO pages in pagetable_init Jeremy Fitzhardinge
2007-05-04 23:21 ` [patch 12/29] xen: fix multicall batching Jeremy Fitzhardinge
2007-05-04 23:21 ` [patch 13/29] xen: Account for time stolen by Xen Jeremy Fitzhardinge
2007-05-04 23:21 ` [patch 14/29] xen: Implement xen_sched_clock Jeremy Fitzhardinge
2007-05-04 23:21 ` [patch 15/29] xen: Xen SMP guest support Jeremy Fitzhardinge
2007-05-04 23:21 ` Jeremy Fitzhardinge [this message]
2007-05-04 23:21 ` [patch 17/29] xen: lazy-mmu operations Jeremy Fitzhardinge
2007-05-04 23:21 ` [patch 18/29] xen: deal with negative stolen time Jeremy Fitzhardinge
2007-05-04 23:21 ` [patch 19/29] xen: Use the hvc console infrastructure for Xen console Jeremy Fitzhardinge
2007-05-06 16:31 ` Olof Johansson
2007-05-04 23:21 ` [patch 20/29] xen: Add early printk support via hvc console Jeremy Fitzhardinge
2007-05-04 23:21 ` [patch 21/29] xen: Add Xen grant table support Jeremy Fitzhardinge
2007-05-04 23:21 ` [patch 22/29] xen: Add the Xenbus sysfs and virtual device hotplug driver Jeremy Fitzhardinge
2007-05-04 23:21 ` [patch 23/29] xen: Add Xen virtual block device driver Jeremy Fitzhardinge
2007-05-04 23:21 ` [patch 24/29] xen: rename xen netif_ structures to xen_netif_ Jeremy Fitzhardinge
2007-05-04 23:21 ` [patch 25/29] xen: Add the Xen virtual network device driver Jeremy Fitzhardinge
2007-05-05 9:16 ` Christoph Hellwig
2007-05-05 10:05 ` Jeremy Fitzhardinge
2007-05-05 10:23 ` Herbert Xu
2007-05-07 21:10 ` Jeremy Fitzhardinge
2007-05-08 12:13 ` [1/2] [NET] link_watch: Move link watch list into net_device Herbert Xu
2007-05-08 12:16 ` [2/2] [NET] link_watch: Remove delay for up even when we're down Herbert Xu
2007-05-09 1:36 ` David Miller
2007-05-08 20:19 ` [1/2] [NET] link_watch: Move link watch list into net_device Jeremy Fitzhardinge
2007-05-09 1:49 ` Herbert Xu
2007-05-09 1:35 ` David Miller
2007-05-10 22:00 ` Jeremy Fitzhardinge
2007-05-10 22:07 ` David Miller
2007-05-10 22:12 ` Jeremy Fitzhardinge
2007-05-10 22:14 ` Andrew Morton
2007-05-10 22:22 ` Jeremy Fitzhardinge
2007-05-10 22:25 ` David Miller
2007-05-10 22:45 ` Jeremy Fitzhardinge
2007-05-10 22:53 ` Chris Wright
2007-05-10 22:53 ` David Miller
2007-05-05 10:16 ` [patch 25/29] xen: Add the Xen virtual network device driver Rusty Russell
2007-05-07 21:11 ` Jeremy Fitzhardinge
2007-05-07 22:35 ` Rusty Russell
2007-05-08 6:30 ` Jeremy Fitzhardinge
2007-05-08 6:42 ` Rusty Russell
2007-05-04 23:21 ` [patch 26/29] xen: fix netfront checksums Jeremy Fitzhardinge
2007-05-04 23:21 ` [patch 27/29] xen: Xen machine operations Jeremy Fitzhardinge
2007-05-04 23:21 ` [patch 28/29] xen: Place vcpu_info structure into per-cpu memory, if possible Jeremy Fitzhardinge
2007-05-04 23:21 ` [patch 29/29] xen: Attempt to patch inline versions of common 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=20070504232120.599172076@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).