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 <che...@zyx.in> + * + * 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); + } +}