Module Name: src
Committed By: cherry
Date: Wed Aug 10 11:39:46 UTC 2011
Modified Files:
src/sys/arch/amd64/amd64: fpu.c machdep.c
src/sys/arch/i386/isa: npx.c
src/sys/arch/x86/x86: x86_machdep.c
src/sys/arch/xen/conf: files.xen
src/sys/arch/xen/include: intr.h
Added Files:
src/sys/arch/xen/x86: xen_ipi.c
Log Message:
xen ipi infrastructure
To generate a diff of this commit:
cvs rdiff -u -r1.35 -r1.36 src/sys/arch/amd64/amd64/fpu.c
cvs rdiff -u -r1.162 -r1.163 src/sys/arch/amd64/amd64/machdep.c
cvs rdiff -u -r1.140 -r1.141 src/sys/arch/i386/isa/npx.c
cvs rdiff -u -r1.53 -r1.54 src/sys/arch/x86/x86/x86_machdep.c
cvs rdiff -u -r1.121 -r1.122 src/sys/arch/xen/conf/files.xen
cvs rdiff -u -r1.31 -r1.32 src/sys/arch/xen/include/intr.h
cvs rdiff -u -r0 -r1.2 src/sys/arch/xen/x86/xen_ipi.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/amd64/amd64/fpu.c
diff -u src/sys/arch/amd64/amd64/fpu.c:1.35 src/sys/arch/amd64/amd64/fpu.c:1.36
--- src/sys/arch/amd64/amd64/fpu.c:1.35 Fri Jul 1 19:24:14 2011
+++ src/sys/arch/amd64/amd64/fpu.c Wed Aug 10 11:39:44 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: fpu.c,v 1.35 2011/07/01 19:24:14 dyoung Exp $ */
+/* $NetBSD: fpu.c,v 1.36 2011/08/10 11:39:44 cherry Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc. All
@@ -100,7 +100,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.35 2011/07/01 19:24:14 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fpu.c,v 1.36 2011/08/10 11:39:44 cherry Exp $");
#include "opt_multiprocessor.h"
@@ -406,7 +406,11 @@
break;
}
splx(s);
+#ifdef XEN
+ xen_send_ipi(oci, XEN_IPI_SYNCH_FPU);
+#else /* XEN */
x86_send_ipi(oci, X86_IPI_SYNCH_FPU);
+#endif
while (pcb->pcb_fpcpu == oci && ticks == hardclock_ticks) {
x86_pause();
spins++;
Index: src/sys/arch/amd64/amd64/machdep.c
diff -u src/sys/arch/amd64/amd64/machdep.c:1.162 src/sys/arch/amd64/amd64/machdep.c:1.163
--- src/sys/arch/amd64/amd64/machdep.c:1.162 Sun Jul 17 15:16:58 2011
+++ src/sys/arch/amd64/amd64/machdep.c Wed Aug 10 11:39:45 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: machdep.c,v 1.162 2011/07/17 15:16:58 jym Exp $ */
+/* $NetBSD: machdep.c,v 1.163 2011/08/10 11:39:45 cherry Exp $ */
/*-
* Copyright (c) 1996, 1997, 1998, 2000, 2006, 2007, 2008
@@ -107,7 +107,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.162 2011/07/17 15:16:58 jym Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.163 2011/08/10 11:39:45 cherry Exp $");
/* #define XENDEBUG_LOW */
@@ -719,7 +719,11 @@
#endif /* XEN */
}
+#ifdef XEN
+ xen_broadcast_ipi(XEN_IPI_HALT);
+#else /* XEN */
x86_broadcast_ipi(X86_IPI_HALT);
+#endif
if (howto & RB_HALT) {
#if NACPICA > 0
Index: src/sys/arch/i386/isa/npx.c
diff -u src/sys/arch/i386/isa/npx.c:1.140 src/sys/arch/i386/isa/npx.c:1.141
--- src/sys/arch/i386/isa/npx.c:1.140 Tue Jun 7 14:53:03 2011
+++ src/sys/arch/i386/isa/npx.c Wed Aug 10 11:39:45 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: npx.c,v 1.140 2011/06/07 14:53:03 bouyer Exp $ */
+/* $NetBSD: npx.c,v 1.141 2011/08/10 11:39:45 cherry Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -96,7 +96,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: npx.c,v 1.140 2011/06/07 14:53:03 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: npx.c,v 1.141 2011/08/10 11:39:45 cherry Exp $");
#if 0
#define IPRINTF(x) printf x
@@ -719,7 +719,11 @@
break;
}
splx(s);
+#ifdef XEN
+ xen_send_ipi(oci, XEN_IPI_SYNCH_FPU);
+#else /* XEN */
x86_send_ipi(oci, X86_IPI_SYNCH_FPU);
+#endif
while (pcb->pcb_fpcpu == oci &&
ticks == hardclock_ticks) {
x86_pause();
Index: src/sys/arch/x86/x86/x86_machdep.c
diff -u src/sys/arch/x86/x86/x86_machdep.c:1.53 src/sys/arch/x86/x86/x86_machdep.c:1.54
--- src/sys/arch/x86/x86/x86_machdep.c:1.53 Mon Aug 1 11:26:31 2011
+++ src/sys/arch/x86/x86/x86_machdep.c Wed Aug 10 11:39:45 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: x86_machdep.c,v 1.53 2011/08/01 11:26:31 jmcneill Exp $ */
+/* $NetBSD: x86_machdep.c,v 1.54 2011/08/10 11:39:45 cherry Exp $ */
/*-
* Copyright (c) 2002, 2006, 2007 YAMAMOTO Takashi,
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: x86_machdep.c,v 1.53 2011/08/01 11:26:31 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: x86_machdep.c,v 1.54 2011/08/10 11:39:45 cherry Exp $");
#include "opt_modular.h"
#include "opt_physmem.h"
@@ -204,10 +204,13 @@
if (l == ci->ci_data.cpu_idlelwp) {
if (ci == cur)
return;
-#ifndef XEN /* XXX review when Xen gets MP support */
- if (x86_cpu_idle_ipi != false)
+ if (x86_cpu_idle_ipi != false) {
+#ifdef XEN
+ xen_send_ipi(ci, XEN_IPI_KICK);
+#else /* XEN */
x86_send_ipi(ci, 0);
-#endif
+#endif /* XEN */
+ }
return;
}
@@ -228,7 +231,11 @@
return;
}
if ((flags & RESCHED_IMMED) != 0) {
+#ifdef XEN
+ xen_send_ipi(ci, XEN_IPI_KICK);
+#else /* XEN */
x86_send_ipi(ci, 0);
+#endif /* XEN */
}
}
@@ -239,7 +246,11 @@
KASSERT(kpreempt_disabled());
aston(l, X86_AST_GENERIC);
if (l->l_cpu != curcpu())
+#ifdef XEN
+ xen_send_ipi(l->l_cpu, XEN_IPI_KICK);
+#else /* XEN */
x86_send_ipi(l->l_cpu, 0);
+#endif /* XEN */
}
void
@@ -363,7 +374,7 @@
else
x86_cpu_idle_set(x86_cpu_idle_mwait, "mwait", false);
#else
- x86_cpu_idle_set(x86_cpu_idle_xen, "xen", false);
+ x86_cpu_idle_set(x86_cpu_idle_xen, "xen", true);
#endif
}
Index: src/sys/arch/xen/conf/files.xen
diff -u src/sys/arch/xen/conf/files.xen:1.121 src/sys/arch/xen/conf/files.xen:1.122
--- src/sys/arch/xen/conf/files.xen:1.121 Mon Jun 13 00:53:15 2011
+++ src/sys/arch/xen/conf/files.xen Wed Aug 10 11:39:45 2011
@@ -1,4 +1,4 @@
-# $NetBSD: files.xen,v 1.121 2011/06/13 00:53:15 pgoyette Exp $
+# $NetBSD: files.xen,v 1.122 2011/08/10 11:39:45 cherry Exp $
# NetBSD: files.x86,v 1.10 2003/10/08 17:30:00 bouyer Exp
# NetBSD: files.i386,v 1.254 2004/03/25 23:32:10 jmc Exp
@@ -56,7 +56,6 @@
file arch/i386/i386/trap.c
file arch/i386/i386/lock_stubs.S
-file arch/i386/i386/mptramp.S multiprocessor
file arch/i386/i386/pmc.c perfctrs
@@ -82,7 +81,6 @@
file arch/amd64/amd64/trap.c
file arch/amd64/amd64/fpu.c
file arch/amd64/amd64/lock_stubs.S
-file arch/amd64/amd64/mptramp.S multiprocessor
endif
file kern/subr_disk_mbr.c disk
@@ -129,7 +127,7 @@
file arch/xen/x86/consinit.c
file arch/x86/x86/identcpu.c
file arch/xen/x86/intr.c
-file arch/x86/x86/ipi.c
+file arch/xen/x86/xen_ipi.c multiprocessor
file arch/x86/x86/pmap.c
file arch/x86/x86/pmap_tlb.c
file arch/x86/x86/procfs_machdep.c procfs
Index: src/sys/arch/xen/include/intr.h
diff -u src/sys/arch/xen/include/intr.h:1.31 src/sys/arch/xen/include/intr.h:1.32
--- src/sys/arch/xen/include/intr.h:1.31 Wed Jul 29 12:02:06 2009
+++ src/sys/arch/xen/include/intr.h Wed Aug 10 11:39:45 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: intr.h,v 1.31 2009/07/29 12:02:06 cegger Exp $ */
+/* $NetBSD: intr.h,v 1.32 2011/08/10 11:39:45 cherry Exp $ */
/* NetBSD intr.h,v 1.15 2004/10/31 10:39:34 yamt Exp */
/*-
@@ -175,9 +175,15 @@
struct pic *intr_findpic(int);
void intr_add_pcibus(struct pcibus_attach_args *);
-int x86_send_ipi(struct cpu_info *, int);
-void x86_broadcast_ipi(int);
-void x86_multicast_ipi(int, int);
+#ifdef MULTIPROCESSOR
+void xen_ipi_init(void);
+int xen_send_ipi(struct cpu_info *, uint32_t);
+void xen_broadcast_ipi(uint32_t);
+#else
+#define xen_ipi_init(_1) do {} while(0) /* nothing */
+#define xen_send_ipi(_i1, _i2) do {} while(0) /* nothing */
+#define xen_broadcast_ipi(_i1) do {} while(0) /* nothing */
+#endif /* MULTIPROCESSOR */
#endif /* !_LOCORE */
Added files:
Index: src/sys/arch/xen/x86/xen_ipi.c
diff -u /dev/null src/sys/arch/xen/x86/xen_ipi.c:1.2
--- /dev/null Wed Aug 10 11:39:46 2011
+++ src/sys/arch/xen/x86/xen_ipi.c Wed Aug 10 11:39:46 2011
@@ -0,0 +1,311 @@
+/* $NetBSD: xen_ipi.c,v 1.2 2011/08/10 11:39:46 cherry Exp $ */
+
+/*-
+ * Copyright (c) 2011 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Cherry G. Mathew <[email protected]>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h> /* RCS ID macro */
+
+/*
+ * Based on: x86/ipi.c
+ * __KERNEL_RCSID(0, "$NetBSD: xen_ipi.c,v 1.2 2011/08/10 11:39:46 cherry Exp $");
+ */
+
+__KERNEL_RCSID(0, "$NetBSD: xen_ipi.c,v 1.2 2011/08/10 11:39:46 cherry Exp $");
+
+#include <sys/types.h>
+
+#include <sys/atomic.h>
+#include <sys/mutex.h>
+#include <sys/cpu.h>
+#include <sys/device.h>
+#include <sys/xcall.h>
+#include <sys/errno.h>
+#include <sys/systm.h>
+
+#include <machine/cpu.h>
+#ifdef __x86_64__
+#include <machine/fpu.h>
+#else
+#include <machine/npx.h>
+#endif /* __x86_64__ */
+#include <machine/frame.h>
+#include <machine/segments.h>
+
+#include <xen/intr.h>
+#include <xen/intrdefs.h>
+#include <xen/hypervisor.h>
+#include <xen/xen3-public/vcpu.h>
+
+#ifdef __x86_64__
+extern void ddb_ipi(struct trapframe);
+#else
+extern void ddb_ipi(int, struct trapframe);
+#endif /* __x86_64__ */
+
+static void xen_ipi_halt(struct cpu_info *, struct intrframe *);
+static void xen_ipi_synch_fpu(struct cpu_info *, struct intrframe *);
+static void xen_ipi_ddb(struct cpu_info *, struct intrframe *);
+static void xen_ipi_xcall(struct cpu_info *, struct intrframe *);
+
+static void (*ipifunc[XEN_NIPIS])(struct cpu_info *, struct intrframe *) =
+{ /* In order of priority (see: xen/include/intrdefs.h */
+ xen_ipi_halt,
+ xen_ipi_synch_fpu,
+ xen_ipi_ddb,
+ xen_ipi_xcall
+};
+
+static void
+xen_ipi_handler(struct cpu_info *ci, struct intrframe *regs)
+{
+ uint32_t pending;
+ int bit;
+
+ pending = atomic_swap_32(&ci->ci_ipis, 0);
+
+ KDASSERT((pending >> XEN_NIPIS) == 0);
+ while ((bit = ffs(pending)) != 0) {
+ bit--;
+ pending &= ~(1 << bit);
+ ci->ci_ipi_events[bit].ev_count++;
+ if (ipifunc[bit] != NULL) {
+ (*ipifunc[bit])(ci, regs);
+ }
+ else {
+ panic("ipifunc[%d] unsupported!\n", bit);
+ /* NOTREACHED */
+ }
+ }
+
+ return;
+}
+
+/* Must be called once for every cpu that expects to send/recv ipis */
+void
+xen_ipi_init(void)
+{
+ cpuid_t vcpu;
+ evtchn_port_t evtchn;
+ struct cpu_info *ci;
+
+ ci = curcpu();
+
+ vcpu = ci->ci_cpuid;
+ KASSERT(vcpu < MAX_VIRT_CPUS);
+
+ evtchn = ci->ci_ipi_evtchn = bind_vcpu_to_evtch(vcpu);
+
+ KASSERT(evtchn != -1 && evtchn < NR_EVENT_CHANNELS);
+
+ if (0 != event_set_handler(evtchn, (int (*)(void *))xen_ipi_handler,
+ ci, IPL_HIGH, "ipi")) {
+ panic("event_set_handler(...) KPI violation\n");
+ /* NOTREACHED */
+ }
+
+ hypervisor_enable_event(evtchn);
+ return;
+}
+
+/* prefer this to global variable */
+static inline u_int max_cpus(void)
+{
+ return maxcpus;
+}
+
+static inline bool /* helper */
+valid_ipimask(uint32_t ipimask)
+{
+ uint32_t masks = XEN_IPI_XCALL | XEN_IPI_DDB |
+ XEN_IPI_SYNCH_FPU | XEN_IPI_HALT |
+ XEN_IPI_KICK;
+
+ if (ipimask & ~masks) {
+ return false;
+ }
+ else {
+ return true;
+ }
+
+}
+
+int
+xen_send_ipi(struct cpu_info *ci, uint32_t ipimask)
+{
+ evtchn_port_t evtchn;
+
+ KASSERT(ci != NULL || ci != curcpu());
+
+ if (!(ci->ci_flags & CPUF_RUNNING)) {
+ return ENOENT;
+ }
+
+ evtchn = ci->ci_ipi_evtchn;
+ if (false == valid_ipimask(ipimask)) {
+ panic("xen_send_ipi() called with invalid ipimask\n");
+ /* NOTREACHED */
+ }
+
+ atomic_or_32(&ci->ci_ipis, ipimask);
+ hypervisor_notify_via_evtchn(evtchn);
+
+ return 0;
+}
+
+void
+xen_broadcast_ipi(uint32_t ipimask)
+{
+ struct cpu_info *ci, *self = curcpu();
+ CPU_INFO_ITERATOR cii;
+
+ if (false == valid_ipimask(ipimask)) {
+ panic("xen_broadcast_ipi() called with invalid ipimask\n");
+ /* NOTREACHED */
+ }
+
+ /*
+ * XXX-cherry: there's an implicit broadcast sending order
+ * which I dislike. Randomise this ? :-)
+ */
+
+ for (CPU_INFO_FOREACH(cii, ci)) {
+ if (ci == NULL)
+ continue;
+ if (ci == self)
+ continue;
+ if (ci->ci_data.cpu_idlelwp == NULL)
+ continue;
+ if ((ci->ci_flags & CPUF_PRESENT) == 0)
+ continue;
+ if (ci->ci_flags & (CPUF_RUNNING)) {
+ if (0 != xen_send_ipi(ci, ipimask)) {
+ panic("xen_ipi of %x from %s to %s failed\n",
+ ipimask, cpu_name(curcpu()),
+ cpu_name(ci));
+ }
+ }
+ }
+
+ return;
+ /* NOTREACHED */
+}
+
+/* MD wrapper for the xcall(9) callback. */
+#define PRIuCPUID "lu" /* XXX: move this somewhere more appropriate */
+
+static void
+xen_ipi_halt(struct cpu_info *ci, struct intrframe *intrf)
+{
+ KASSERT(ci == curcpu());
+ KASSERT(ci != NULL);
+ if (HYPERVISOR_vcpu_op(VCPUOP_down, ci->ci_cpuid, NULL)) {
+ panic("vcpu%" PRIuCPUID "shutdown failed.\n", ci->ci_cpuid);
+ }
+
+ return;
+}
+
+static void
+xen_ipi_synch_fpu(struct cpu_info *ci, struct intrframe *intrf)
+{
+ KASSERT(ci != NULL);
+ KASSERT(intrf != NULL);
+
+#ifdef __x86_64__
+ fpusave_cpu(true);
+#else
+ npxsave_cpu(true);
+#endif /* __x86_64__ */
+ return;
+}
+
+static void
+xen_ipi_ddb(struct cpu_info *ci, struct intrframe *intrf)
+{
+ KASSERT(ci != NULL);
+ KASSERT(intrf != NULL);
+
+#ifdef __x86_64__
+ ddb_ipi(intrf->if_tf);
+#else
+ struct trapframe tf;
+ tf.tf_gs = intrf->if_gs;
+ tf.tf_fs = intrf->if_fs;
+ tf.tf_es = intrf->if_es;
+ tf.tf_ds = intrf->if_ds;
+ tf.tf_edi = intrf->if_edi;
+ tf.tf_esi = intrf->if_esi;
+ tf.tf_ebp = intrf->if_ebp;
+ tf.tf_ebx = intrf->if_ebx;
+ tf.tf_ecx = intrf->if_ecx;
+ tf.tf_eax = intrf->if_eax;
+ tf.tf_trapno = intrf->__if_trapno;
+ tf.tf_err = intrf->__if_err;
+ tf.tf_eip = intrf->if_eip;
+ tf.tf_cs = intrf->if_cs;
+ tf.tf_eflags = intrf->if_eflags;
+ tf.tf_esp = intrf->if_esp;
+ tf.tf_ss = intrf->if_ss;
+
+ /* XXX: does i386/Xen have vm86 support ?
+ tf.tf_vm86_es;
+ tf.tf_vm86_ds;
+ tf.tf_vm86_fs;
+ tf.tf_vm86_gs;
+ :XXX */
+
+ ddb_ipi(SEL_KPL, tf);
+#endif
+}
+
+static void
+xen_ipi_xcall(struct cpu_info *ci, struct intrframe *intrf)
+{
+ KASSERT(ci != NULL);
+ KASSERT(intrf != NULL);
+
+ xc_ipi_handler();
+ return;
+}
+
+void
+xc_send_ipi(struct cpu_info *ci)
+{
+
+ KASSERT(kpreempt_disabled());
+ KASSERT(curcpu() != ci);
+ printf("xc_send_ipi called \n");
+ if (ci) {
+ if (0 != xen_send_ipi(ci, XEN_IPI_XCALL)) {
+ panic("xen_send_ipi(XEN_IPI_XCALL) failed\n");
+ };
+ } else {
+ xen_broadcast_ipi(XEN_IPI_XCALL);
+ }
+}