/* D-cache control on an 21064A Just compile it with gcc -O -c toggle_dc_16k.c and invoke it with insmod toggle_dc_16k.o Never mind the error message. To see the result, invoke dmesg |tail which should contain a message like "D-cache size: 16KB; abox_ctl=0x942c" or "D-cache size: 8KB; abox_ctl=0x842c", which indicates the new status. Invoke the module again to toggle the state. When you try to install this module, it toggles the state of the D-cache between 8K and 16K and then prints the resulting value of the ABOX_CTL register in hex. If bit 12 (mask: 0x1000) is set, the D-cache is 16KB, if it is clear, the D-cache is 8KB. The module produces an error, but the effect is there nevertheless. It produces an error to avoid being installed, so you don't need un rmmod it before invoking it again. Warnings: You should only invoke this module if you have an 21064A (aka EV45); it does not check the processor, because there is no reliable way to do this from the kernel (e.g., what /proc/cpuinfo says is not reliable), and it is unknow what this does on other CPUs. This module will do its job, if you booted using MILO, but AFAIK not if you boot with SRM without MILO (it uses the cserve palcode which depends on the console); but with the SRM you are probably using 16K D-Cache anyway. This module works on one of our cabriolets (the other is too critical to try this); the present version reportedly works on an Avanti (earlier versions had severe problems). More experience reports are welcome. Cache consistency appears to be handled in hardware (tested with http://www.complang.tuwien.ac.at/anton/toggle_dc_16k/mapcheck.c). Acknowledgements: Thanks to Nikita Schmidt, Richard Rogers, Richard Henderson, and "Solar Designer" for feedback and helpful suggestions. */ #define MODULE #define __KERNEL__ #include #include static long rd_abox_ctl() { long abox_ctl; asm("mov 3, $18; call_pal 9; mov $0, %0": "=r" (abox_ctl): /* no inputs */ : "$0","$16","$17","$18"); /* read abox_ctl register */ return abox_ctl; } static void wr_abox_ctl(long abox_ctl) { asm("mov 6, $18; mov %0, $16; call_pal 9": : "r" (abox_ctl) : "$0","$16","$17","$18"); /* write abox_ctl register */ } #define ABOX_M_DC_16K 0x1000 #define ABOX_M_DC_ENA 0x0400 #define ABOX_M_DOUBLE_INVAL 0x8000 /* hardware request invalidates both cache blocks addressed by bits 12:5 */ /* toggle bit 12 of the ABOX_CTL register; this bit controls whether the Dache is 8KB or 16KB (virtually-indexed in the latter case) */ static void toggle_dc_16k() { long new; new = (rd_abox_ctl() ^ ABOX_M_DC_16K) | ABOX_M_DOUBLE_INVAL; /* do DOUBLE_INVAL in any case; with 8K D-cache this should be irrelevant, with 16K it is necessary for Avanti; the performance impact on the Cabriolet (which does not need this) appears to be minimal. */ wr_abox_ctl(new & ~ABOX_M_DC_ENA); /* flush D-Cache */ wr_abox_ctl(new | ABOX_M_DC_ENA); /* enable D-Cache in new mode */ } int init_module() { long abox_ctl; toggle_dc_16k(); abox_ctl=rd_abox_ctl(); printk("D-cache size: %dKB; abox_ctl=0x%x\n", (abox_ctl&ABOX_M_DC_16K)?16:8,abox_ctl); return 1; /* device or resource busy, so the module is not installed */ } void cleanup_module() { }