From: Venkatesh Srinivas Date: Sat, 18 Dec 2010 15:24:58 +0000 (-0800) Subject: kernel -- Add MONITOR and MWAIT routine to i386 kernel. X-Git-Tag: v2.11.0~448 X-Git-Url: https://gitweb.dragonflybsd.org/~nant/dragonfly.git/commitdiff_plain/2a06bc07b3de833a671be012eeebb1121ce9da8a kernel -- Add MONITOR and MWAIT routine to i386 kernel. Provides cpu_mmw_spin() and cpu_mmw_mwait(), both of which wait for a given memory cell to contain a value different from an expected value. _spin() merely spins on the cell; _mwait() uses the SSE3 MONITOR/MWAIT isns. --- diff --git a/sys/cpu/i386/misc/monitor.s b/sys/cpu/i386/misc/monitor.s new file mode 100644 index 0000000000..497e388c8b --- /dev/null +++ b/sys/cpu/i386/misc/monitor.s @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2010 The DragonFly Project. All rights reserved. + * All rights reserved. + * + * This code is derived from software contributed to The DragonFly Project + * by Venkatesh Srinivas + * + * 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. + * 3. Neither the name of The DragonFly Project nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 REGENTS 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 +#include +#include +#include + +#include "assym.s" + + .text + +/* + * int cpu_mmw_spin(int *addr, int oldval) + * + * Spin on addr, waiting for it to no longer contain oldval; + * return newval. + */ +ENTRY(cpu_mmw_spin) + movl 4(%esp), %eax + movl 8(%esp), %edx + + .align 4 +1: + movl (%eax), %ecx + cmpl %ecx, %edx + pause + je 1b + + movl %ecx, %eax + ret + +/* + * int cpu_mmw_mwait(int *addr, int oldval) + * + * Spin on addr, waiting for it to no longer contain oldval; + * return newval. Use the MONITOR/MWAIT instructions to wait + * for a state-change on the address. + * + * WARN 1: We receive wakeup events for much larger windows + * than a single address; CPUID EAX = 0x05 reports the + * windows; on an Intel Atom they seem to cacheline-sized. + * Synchronization variables should probably be + * cacheline-aligned to avoid false wakeups. + * + * WARN 2: This routine can be racy; when we wake from MWAIT, we must + * load the contents of the address; in the meantime, it + * is possible that it was swapped to the prior (or some other) + * value; care must be used -- CMPXCHG for wakeup, for example. + * + * WARN 3: Use this routine only when cpu_mi_features & CPU_MI_MONITOR + */ +ENTRY(cpu_mmw_mwait) + pushl %ebx + movl 8(%esp), %eax + movl 12(%esp), %ebx + xorl %ecx, %ecx + xorl %edx, %edx + + .align 4 +1: + monitor + movl (%eax), %ecx + cmpl %ebx, %ecx + jne 2f + mwait + jmp 1b + + .align 4 +2: + movl %ecx, %eax + popl %ebx + ret + diff --git a/sys/platform/pc32/conf/files b/sys/platform/pc32/conf/files index 4036f387a1..e77ac5d6e4 100644 --- a/sys/platform/pc32/conf/files +++ b/sys/platform/pc32/conf/files @@ -154,6 +154,7 @@ cpu/i386/misc/ktr.c optional ktr cpu/i386/misc/db_disasm.c optional ddb cpu/i386/misc/i386-gdbstub.c optional ddb cpu/i386/misc/bzeront.s standard +cpu/i386/misc/monitor.s standard platform/pc32/i386/autoconf.c standard platform/pc32/i386/bios.c standard platform/pc32/i386/bioscall.s standard diff --git a/sys/platform/pc32/i386/identcpu.c b/sys/platform/pc32/i386/identcpu.c index 17145e4d9c..c5345637a2 100644 --- a/sys/platform/pc32/i386/identcpu.c +++ b/sys/platform/pc32/i386/identcpu.c @@ -1259,6 +1259,8 @@ finish: if (cpu_feature & CPUID_SSE2) cpu_mi_feature |= CPU_MI_BZERONT; + if (cpu_feature2 & CPUID2_MON) + cpu_mi_feature |= CPU_MI_MONITOR; } static u_int diff --git a/sys/sys/param.h b/sys/sys/param.h index 10c9107c04..b750f274c3 100644 --- a/sys/sys/param.h +++ b/sys/sys/param.h @@ -156,6 +156,7 @@ * cpu_mi_feature bits */ #define CPU_MI_BZERONT 0x00000001 +#define CPU_MI_MONITOR 0x00000010 /* * File system parameters and macros. diff --git a/sys/sys/systm.h b/sys/sys/systm.h index ca580db5e1..df0355fda0 100644 --- a/sys/sys/systm.h +++ b/sys/sys/systm.h @@ -315,6 +315,8 @@ void setsofttq (void); void schedsofttty (void); void splz (void); void splz_check (void); +int cpu_mmw_spin(int *, int); +int cpu_mmw_mwait(int *, int); #endif /* __i386__ */ /*