AMD K6 WriteBack Optimisations

From OSDev Wiki
Jump to: navigation, search

This article is a stub! This page or section is a stub. You can help the wiki by accurately contributing to it.

This page or section refers to its readers or editors using I, my, we or us. It should be edited to be in an encyclopedic tone.

I wrote and tested this on my own K6 (k6-200) and it works ok, but I was unable to find anyone with a K6-2 (CXT core) or K6-3 since there is two different methods for enabling writeback mode. It should work fine on k6-2 CXT and K6-3 processors.

With some tweaking, can be put into anyone's OS.

You call AMD_K6_writeback with the CPUID results family, model and stepping, only when you are sure you have an AMD cpu.

void AMD_K6_writeback(int family, int model, int stepping)
{
    /* mem_end == top of memory in bytes */
    int mem=(mem_end>>20)/4; /* turn into 4mb aligned pages */
    int c;
    union REGS regs;
 
    if(family==5)
    {
        c=model;
 
        /* model 8 stepping 0-7 use old style, 8-F use new style */
        if(model==8)
        {
            if(stepping<8)
                c=7;
            else
                c=9;
        }
 
        switch(c)
        {
        /* old style write back */
        case 6:
        case 7:
            AMD_K6_read_msr(0xC0000082, &regs);
            if(((regs.x.eax>>1)&0x7F)==0)
                kprintf("AMD K6 : WriteBack currently disabled\n");
            else
                kprintf("AMD K6 : WriteBack currently enabled (%luMB)\n",
                    ((regs.x.eax>>1)&0x7F)*4);
 
            kprintf("AMD K6 : Enabling WriteBack to %luMB\n", mem*4);
            AMD_K6_write_msr(0xC0000082, ((mem<<1)&0x7F), 0, &regs);
            break;
 
        /* new style write back */
        case 9:
            AMD_K6_read_msr(0xC0000082, &regs);
            if(((regs.x.eax>>22)&0x3FF)==0)
                kprintf("AMD K6 : WriteBack Disabled\n");
            else
                kprintf("AMD K6 : WriteBack Enabled (%luMB)\n",
                    ((regs.x.eax>>22)&0x3FF)*4);
 
            kprintf("AMD K6 : Enabled WriteBack (%luMB)\n", mem*4);
            AMD_K6_write_msr(0xC0000082, ((mem<<22)&0x3FF), 0, &regs);
            break;
        default:    /* dont set it on Unknowns + k5's */
            break;
        }
    }
}
 
void AMD_K6_write_msr(ULONG msr, ULONG v1, ULONG v2, union REGS *regs)
{
    asm __volatile__ (
        "pushfl\n"
        "cli\n"
        "wbinvd\n"
        "wrmsr\n"
        "popfl\n"
        : "=a" (regs->x.eax),
          "=b" (regs->x.ebx),
          "=c" (regs->x.ecx),
          "=d" (regs->x.edx)
        : "a" (v1),
          "d" (v2),
          "c" (msr)
        : "eax",
          "ecx",
          "edx",
          "ebx",
          "memory");
}
 
void AMD_K6_read_msr(ULONG msr, union REGS *regs)
{
    asm __volatile__ (
        "pushfl\n"
        "cli\n"
        "wbinvd\n"
        "xorl %%eax, %%eax\n"
        "xorl %%edx, %%edx\n"
        "rdmsr\n"
        "popfl\n"
        : "=a" (regs->x.eax),
          "=b" (regs->x.ebx),
          "=c" (regs->x.ecx),
          "=d" (regs->x.edx)
        : "c" (msr)
        : "eax",
          "ecx",
          "edx",
          "ebx",
          "memory");
}
Personal tools
Namespaces
Variants
Actions
Navigation
About
Toolbox