cvs commit: src/sys/kern kern_spinlock.c src/sys/platform/vkernel/i386 cpu_regs.c src/sys/sys systm.h src/sys/platform/pc32/i386 machdep.c

Michal Belczyk belczyk at bsd.krakow.pl
Mon Jul 2 13:47:15 PDT 2007


On Mon, Jul 02, 2007 at 01:27:26PM -0700, Matthew Dillon wrote:
> 
> :> Very nice.  I've been meaning to do this.  We could use monitor/mwait on core2duo CPUs for power reduction for example (also when waiting for the mplock/scheduler changes in the idle loop).
> :
> :On my core2duo laptop replacing cpu_idle_hook() with one using mwait to enter
> :enhanced halt states resulted in lowering the maximal cpu temperature from
> :above 60 to below 55 degrees and made the cpu fan run less often.  I even made
> :some graphs representing the cpu temperature in time[1] on an idle system.
> :However, I believe that lowering cpu voltage and frequency via EST and estd
> :should give better results.  Some time ago I wrote a kernel module
> :implementing EST for those cpus[2] in an ACPI-independent way.  Nice thing is
> :that one can set voltage and frequency idependently of each other, at least on
> :my cpu ;-)  And it was working with estd.  Now it's probably non-compilable
> :after some SYSINIT-related macros had been renamed.
> :Note that it's based only on intel docs and my own experiments so there might
> :be bugs in it.
> :
> :[1] http://bsd.krakow.pl/df/CxE/
> :[2] http://bsd.krakow.pl/df/est_core.tgz
> :
> :-- 
> :Michal Belczyk
> 
>     This is very close to being deployable.  All you need is a little logic
>     to detect the core-duo cpu (similar to how the current EST module does
>     it, by getting the info from the hw.model sysctl) and make it error
>     out if the system isn't a core-duo, and a little logic to replace
>     the hook function.

I'll work on it and let you know when I'm done.  Fortunately I've got more
time now since I finished my master thesis and basically I'm done with my
studies :D


>     Could you post your changes to the hook function too? 

I changed the hook to point to the function below though I'm not sure if it's
correct.

static int Cx = 1;
static int CxE = 1;
static int state = 0;

static void *monitor_data = NULL;
static void (*cpu_idle_old_hook) = NULL;

static void
cpu_idle_xxx_hook(void)
{       
        
        __asm __volatile (
                "movl %0, %%eax\n"
                "movl $0, %%ecx\n"
                "movl $0, %%edx\n"
                "monitor\n"
                "movl %1, %%eax\n"
                /* "movl $0x00, %%eax\n" C1 */
                /* "movl $0x01, %%eax\n" C1E */
                /* "movl $0x10, %%eax\n" C2 */
                /* "movl $0x11, %%eax\n" C2E */
                /* "movl $0x20, %%eax\n" C3 */
                /* "movl $0x21, %%eax\n" C3E */
                /* "movl $0x31, %%eax\n" C4E */
                "movl $0, %%ecx\n"
                "sti\n"
                "mwait\n"
                :
                : "r"(monitor_data), "r"(((Cx << 4) & 0xf0) | (CxE & 0x0f))
                : "%eax", "%ecx", "edx");
}

static int
core_load(void)
{             

	/* ... */
        do_cpuid(0x05, regs);

        kprintf("core: CPUID(0x05): EAX = %x, EBX = %x, ECX = %x, EDX = %x\n",
                        regs[0], regs[1], regs[2], regs[3]);

        kprintf("core: Smallest monitor-line size is %d bytes\n",
                        regs[0] & 0xffff);
        kprintf("core: Largest monitor-line size is %d bytes\n",
                        regs[1] & 0xffff);

        if ((regs[2] & 0x00000001) == 0)
                return (EOPNOTSUPP);
        kprintf("core: Enumeration of Monitor-Wait extensions supported\n");

        if ((regs[2] & 0x00000002) == 0)
                return (EOPNOTSUPP);
        kprintf("core: Supports treating interrupts as break-event for MWAIT, "
                "even when interrupts disabled\n");

        kprintf("core: %d C0 sub C-states\n", regs[3] & 0x0000000f);
        kprintf("core: %d C1 sub C-states\n", (regs[3] & 0x000000f0) >> 4);
        kprintf("core: %d C2 sub C-states\n", (regs[3] & 0x00000f00) >> 8);
        kprintf("core: %d C3 sub C-states\n", (regs[3] & 0x0000f000) >> 12);
        kprintf("core: %d C4 sub C-states\n", (regs[3] & 0x000f0000) >> 16);

	/* ... */
        state = ((Cx << 4) & 0xf0) | (CxE & 0x0f);
        kprintf("core: using C%d%s idle hook via MWAIT\n",
                        Cx + 1, CxE ? "E" : "");
        cpu_idle_old_hook = cpu_idle_hook;
        cpu_idle_hook = cpu_idle_xxx_hook;
        do_cpuid(0x00, regs);
        kprintf("core: new idle hook installed\n");

	/* ... */
}

-- 
Michal Belczyk





More information about the Commits mailing list