/* k6mod */

/* Sets write allocation on AMD K6(-2) processor */
/* Won't work with the new K6-2/-3 core */

/* (w) Kurt Garloff <K.Garloff@ping.de> 9/98,12/98
 * (c) GNU GPL */

/* Compile with
 * gcc -O2 -fomit-frame-pointer -D__KERNEL__ -I/usr/src/linux/include -c k6mod.c
 * 
 * If you have versioned symbols enabled, you need to add -DMODVERSIONS
 * 
 * Insmod with insmod k6mod.o 
 * or 
 * copy to /lib/modules/2.X.YYY/misc
 * and depmod -a and modprobe k6mod
 */ 

#define MODULE
#include <linux/module.h>
#include <linux/kernel.h>

#ifdef MODVERSIONS
# include <linux/modversions.h>
#endif

/* If your binutils don't accept this: upgrade! */
#define rdmsr(msr,val1,val2) \
	__asm__ __volatile__("rdmsr" \
	: "=a" (val1), "=d" (val2) \
	: "c" (msr))

#define wrmsr(msr,val1,val2) \
	__asm__ __volatile__("wrmsr" \
	: /* no outputs */ \
	: "c" (msr), "a" (val1), "d" (val2))


/* Save old values */
unsigned k6_old_efer, k6_old_whcr;

int init_module (void)
{
   unsigned v1, v2;
   printk (KERN_INFO "Inserting K6 module ... \n");
   rdmsr (0xc0000080, v1, v2); k6_old_efer = v1;
   printk (KERN_INFO " EFER: %08x -> ", v1);
   /* Syscall Extension (not currently used) */
   v1 |= 1;
   wrmsr (0xc0000080, v1, v2);
   rdmsr (0xc0000080, v1, v2);
   printk ("%08x\n", v1);
   
   rdmsr (0xc0000082, v1, v2); k6_old_whcr = v1;
   printk (KERN_INFO " WHCR: %08x -> ", v1);
   /* 508 MB Write Allocation w/o 15M mem. hole */
   v1 = 0xff;
   wrmsr (0xc0000082, v1, v2);
   rdmsr (0xc0000082, v1, v2);
   printk ("%08x\n", v1);

   return 0;
};

/* Restore old values */
void cleanup_module (void)
{
   unsigned v1, v2;
   printk (KERN_INFO "Removing K6 module ... \n");
   rdmsr (0xc0000080, v1, v2);
   printk (KERN_INFO " EFER: %08x -> ", v1);
   v1 = k6_old_efer;
   wrmsr (0xc0000080, v1, v2);
   rdmsr (0xc0000080, v1, v2);
   printk ("%08x\n", v1);
   
   rdmsr (0xc0000082, v1, v2);
   printk (KERN_INFO " WHCR: %08x -> ", v1);
   v1 = k6_old_whcr;
   wrmsr (0xc0000082, v1, v2);
   rdmsr (0xc0000082, v1, v2);
   printk ("%08x\n", v1);
};
   
