diff --git a/src/cpu/p6/l2_cache.c b/src/cpu/p6/l2_cache.c index ba6fc0b812..2ae7674a74 100644 --- a/src/cpu/p6/l2_cache.c +++ b/src/cpu/p6/l2_cache.c @@ -34,20 +34,18 @@ #include /* Include debugging code and outputs */ -#define DEBUG +#define DEBUG static int signal_l2(unsigned int address_high, - unsigned int address_low, + unsigned int address_low, unsigned int data_high, - unsigned int data_low, - int way, int command); + unsigned int data_low, int way, int command); static int read_l2(unsigned int address); static int write_l2(unsigned int address, int data); -static int write_l2_2(unsigned int address, - unsigned int data1, - unsigned int data2); +static int write_l2_2(unsigned int address, + unsigned int data1, unsigned int data2); static int test_l2_address_alias(unsigned int address1, - unsigned int address2, + unsigned int address2, unsigned int data_high, unsigned int data_low); static int calculate_l2_latency(void); @@ -72,8 +70,7 @@ static void cache_disable(void) "orl $0x40000000, %0\n\t" "wbinvd\n\t" "movl %0, %%cr0\n\t" - "wbinvd\n\t" - : "=r" (tmp) : : "memory"); + "wbinvd\n\t":"=r" (tmp)::"memory"); } static void cache_enable(void) @@ -82,10 +79,9 @@ static void cache_enable(void) asm volatile ("movl %%cr0, %0\n\t" "andl $0x9fffffff, %0\n\t" - "movl %0, %%cr0\n\t" - : "=r" (tmp) : : "memory"); + "movl %0, %%cr0\n\t":"=r" (tmp)::"memory"); } - + int intel_l2_configure() { unsigned int eax, ebx, ecx, edx; @@ -94,8 +90,7 @@ int intel_l2_configure() intel_cpuid(0, &eax, &ebx, &ecx, &edx); - if (ebx != 0x756e6547 || edx != 0x49656e69 || - ecx != 0x6c65746e) { + if (ebx != 0x756e6547 || edx != 0x49656e69 || ecx != 0x6c65746e) { printk(KERN_ERR "Not 'GenuineIntel' Processor\n"); return -1; } @@ -110,8 +105,9 @@ int intel_l2_configure() } if (signature < 0x630 || signature >= 0x680) { - DBG("CPU signature of %x so no need for L2 cache configuration\n", - signature); + DBG + ("CPU signature of %x so no need for L2 cache configuration\n", + signature); return 0; } @@ -122,17 +118,19 @@ int intel_l2_configure() DBG("L2 Hardware disabled\n"); return 0; } - + if (signature == 0x630) { /* 0x630 signature setup */ /* Read EBL_CR_POWERON */ rdmsr(0x2a, eax, edx); - + /* Mask out [22-24] Clock frequency ratio */ eax &= 0x1c00000; if (eax == 0xc00000 || eax == 0x1000000) { - printk(KERN_ERR "Incorrect clock frequency ratio %x\n", eax); + printk(KERN_ERR + "Incorrect clock frequency ratio %x\n", + eax); return -1; } @@ -170,7 +168,9 @@ int intel_l2_configure() /* Mask out [22-24] Clock frequency ratio */ eax &= 0x3c00000; if (eax == 0xc00000 || eax == 0x3000000) { - printk(KERN_ERR "Incorrect clock frequency ratio %x\n", eax); + printk(KERN_ERR + "Incorrect clock frequency ratio %x\n", + eax); return -1; } @@ -245,7 +245,8 @@ int intel_l2_configure() } if (calculate_l2_physical_address_range() != 0) { - printk(KERN_ERR "Failed to calculate L2 physical address range\n"); + printk(KERN_ERR + "Failed to calculate L2 physical address range\n"); return -1; } @@ -257,7 +258,7 @@ int intel_l2_configure() /* Turn on cache. Only L1 is active at this time. */ cache_enable(); - /* Get the calculated cache size from BBL_CR_CTL3 [17:13]*/ + /* Get the calculated cache size from BBL_CR_CTL3 [17:13] */ rdmsr(0x11e, eax, edx); cache_size = (eax & 0x3e000); if (cache_size == 0) @@ -265,22 +266,23 @@ int intel_l2_configure() cache_size = cache_size << 3; /* Cache is 4 way for each address */ - DBG("L2 Cache size is %dK\n", cache_size*4/1024); + DBG("L2 Cache size is %dK\n", cache_size * 4 / 1024); /* Write to all cache lines to initialize */ - while(cache_size > 0) { + while (cache_size > 0) { int way; /* Each Cache line in 32 bytes */ cache_size -= 0x20; /* Update each way */ - for(way = 0; way < 4; way++) { + for (way = 0; way < 4; way++) { /* Send Tag Write w/Data Write (TWW) to L2 controller * MESI = Invalid */ if (signal_l2(0, cache_size, 0, 0, way, 0x1c) != 0) { - printk(KERN_ERR "Failed on signal_l2(%x, %x)\n", + printk(KERN_ERR + "Failed on signal_l2(%x, %x)\n", cache_size, way); return -1; } @@ -291,156 +293,150 @@ int intel_l2_configure() /* Disable cache */ cache_disable(); - /* Set L2 cache configured in BBL_CR_CTL3 */ - rdmsr(0x11e, eax, edx); - eax |= 0x1; - wrmsr(0x11e, eax, edx); - - /* Invalidate cache and discard unsaved writes */ - asm volatile("invd"); - - /* Write 0 to L2 control register 5 */ - if (write_l2(5, 0) != 0) - { - printk(KERN_ERR "write_l2(5, 0) failed\n"); - return 0; - } - - if (signature == 0x650 || signature == 0x670) - { - /* Change the L2 latency to 0101 then back to - * original value. I don't know why this is needed - dpd - */ - int old_eax; + /* Set L2 cache configured in BBL_CR_CTL3 */ rdmsr(0x11e, eax, edx); - old_eax = eax; - eax &= 0xffffffe1; - eax |= 0x0000000a; + eax |= 0x1; wrmsr(0x11e, eax, edx); - wrmsr(0x11e, old_eax, edx); - } - - /* Set L2 enabled in BBL_CR_CTL3 */ - rdmsr(0x11e, eax, edx); - eax |= 0x00000100; - wrmsr(0x11e, eax, edx); - - /* Turn on cache. Both L1 and L2 are now active. Wahoo! */ - cache_enable(); - - return 0; + + /* Invalidate cache and discard unsaved writes */ + asm volatile ("invd"); + + /* Write 0 to L2 control register 5 */ + if (write_l2(5, 0) != 0) { + printk(KERN_ERR "write_l2(5, 0) failed\n"); + return 0; + } + + if (signature == 0x650 || signature == 0x670) { + /* Change the L2 latency to 0101 then back to + * original value. I don't know why this is needed - dpd + */ + int old_eax; + rdmsr(0x11e, eax, edx); + old_eax = eax; + eax &= 0xffffffe1; + eax |= 0x0000000a; + wrmsr(0x11e, eax, edx); + wrmsr(0x11e, old_eax, edx); + } + + /* Set L2 enabled in BBL_CR_CTL3 */ + rdmsr(0x11e, eax, edx); + eax |= 0x00000100; + wrmsr(0x11e, eax, edx); + + /* Turn on cache. Both L1 and L2 are now active. Wahoo! */ + cache_enable(); + + return 0; } /* Setup address_high:address_low, data_high:data_low into the L2 * control registers and then issue command with correct cache way */ -int signal_l2(unsigned int address_high, unsigned int address_low, - unsigned int data_high, unsigned int data_low, - int way, int command) +int signal_l2(unsigned int address_high, unsigned int address_low, + unsigned int data_high, unsigned int data_low, + int way, int command) { - unsigned int eax, edx; - int i; + unsigned int eax, edx; + int i; - /* Write L2 Address to BBL_CR_ADDR */ - wrmsr(0x116, address_low, address_high); - - /* Write data to BBL_CR_D[0-3] */ - for(i = 0; i < 4; i++) - wrmsr(0x88 + i, data_low, data_high); - - /* Put the command into BBL_CR_CTL */ - rdmsr(0x119, eax, edx); - edx = 0; - eax &= 0xfffffce0; - eax |= command; - eax |= way << 8; - wrmsr(0x119, eax, edx); + /* Write L2 Address to BBL_CR_ADDR */ + wrmsr(0x116, address_low, address_high); - /* Write to BBL_CR_TRIG to trigger L2 controller */ - wrmsr(0x11a, 0, 0); - - /* Poll the controller to see when done */ - for(i = 0; i < 0x100; i++) - { - /* Read BBL_CR_BUSY */ - rdmsr(0x11b, eax, edx); - /* If not busy then return */ - if ((eax & 1) == 0) - return 0; - } - - /* Return timeout code */ - return -1; + /* Write data to BBL_CR_D[0-3] */ + for (i = 0; i < 4; i++) + wrmsr(0x88 + i, data_low, data_high); + + /* Put the command into BBL_CR_CTL */ + rdmsr(0x119, eax, edx); + edx = 0; + eax &= 0xfffffce0; + eax |= command; + eax |= way << 8; + wrmsr(0x119, eax, edx); + + /* Write to BBL_CR_TRIG to trigger L2 controller */ + wrmsr(0x11a, 0, 0); + + /* Poll the controller to see when done */ + for (i = 0; i < 0x100; i++) { + /* Read BBL_CR_BUSY */ + rdmsr(0x11b, eax, edx); + /* If not busy then return */ + if ((eax & 1) == 0) + return 0; + } + + /* Return timeout code */ + return -1; } /* Read the L2 Cache controller register at given address */ static int read_l2(unsigned int address) { - unsigned int eax, edx; - - address = address << 5; - - /* Send a L2 Control Register Read to L2 controller */ - if (signal_l2(0, address, 0, 0, 0, 2) != 0) - return -1; + unsigned int eax, edx; - /* If OK then get the result from BBL_CR_ADDR */ - rdmsr(0x116, eax, edx); + address = address << 5; - eax = eax >> 0x15; - - return eax; + /* Send a L2 Control Register Read to L2 controller */ + if (signal_l2(0, address, 0, 0, 0, 2) != 0) + return -1; + + /* If OK then get the result from BBL_CR_ADDR */ + rdmsr(0x116, eax, edx); + + eax = eax >> 0x15; + + return eax; } /* data1 = eax, data2 = ebx */ -static int write_l2_2(unsigned int address, - unsigned int data1, - unsigned int data2) +static int write_l2_2(unsigned int address, + unsigned int data1, unsigned int data2) { - data1 &= 0xff; - data1 = data1 << 0x15; + data1 &= 0xff; + data1 = data1 << 0x15; - data2 = data2 << 0x0b; - data2 &= 0x1800; - data1 |= data2; + data2 = data2 << 0x0b; + data2 &= 0x1800; + data1 |= data2; - data2 = data2 >> 6; - data2 &= 0x20000; - data1 |= data2; + data2 = data2 >> 6; + data2 &= 0x20000; + data1 |= data2; - address = address << 5; - address |= data1; + address = address << 5; + address |= data1; - /* L2 Control Register Write */ - return signal_l2(0, address, 0, 0, 0, 3); + /* L2 Control Register Write */ + return signal_l2(0, address, 0, 0, 0, 3); } /* Write data into the L2 controller register at address */ static int write_l2(unsigned int address, int data) { - int v1, v2, i; + int v1, v2, i; - v1 = read_l2(0); - if (v1 < 0) - return -1; - - v2 = read_l2(2); - if (v2 < 0) - return -1; - - if ((v1 & 0x20) == 0) - { - v2 &= 0x3; - v2++; - } - else - v2 &= 0x7; + v1 = read_l2(0); + if (v1 < 0) + return -1; - for(i = 0; i < v2; i++) - if (write_l2_2(address, data, i) != 0) - return -1; - - return 0; + v2 = read_l2(2); + if (v2 < 0) + return -1; + + if ((v1 & 0x20) == 0) { + v2 &= 0x3; + v2++; + } else + v2 &= 0x7; + + for (i = 0; i < v2; i++) + if (write_l2_2(address, data, i) != 0) + return -1; + + return 0; } /* Write data_high:data_low into the cache at address1. Test address2 @@ -449,462 +445,439 @@ static int write_l2(unsigned int address, int data) * on error */ static int test_l2_address_alias(unsigned int address1, - unsigned int address2, + unsigned int address2, unsigned int data_high, unsigned int data_low) { - unsigned int eax, edx; - int d; + unsigned int eax, edx; + int d; - /* Tag Write with Data Write for L2 */ - if (signal_l2(0, address1, data_high, data_low, 0, 0x1c) != 0) - return -1; + /* Tag Write with Data Write for L2 */ + if (signal_l2(0, address1, data_high, data_low, 0, 0x1c) != 0) + return -1; - /* Tag Read with Data Read for L2 */ - if (signal_l2(0, address2, 0, 0, 0, 0xe) != 0) - return -1; - - /* Read data from BBL_CR_D[0-3] */ - for(d = 0x88; d <= 0x8b; d++) - { - rdmsr(d, eax, edx); + /* Tag Read with Data Read for L2 */ + if (signal_l2(0, address2, 0, 0, 0, 0xe) != 0) + return -1; - if (eax != data_low || edx != data_high) - return (eax & 0xffff); - } + /* Read data from BBL_CR_D[0-3] */ + for (d = 0x88; d <= 0x8b; d++) { + rdmsr(d, eax, edx); - return 0; + if (eax != data_low || edx != data_high) + return (eax & 0xffff); + } + + return 0; } /* Latency Tables */ -struct latency_entry -{ - unsigned char key; - unsigned char value; +struct latency_entry { + unsigned char key; + unsigned char value; }; -static const struct latency_entry latency_650_t0[] = -{ - { 0x10, 0x02 }, { 0x50, 0x02 }, { 0x20, 0x04 }, { 0x60, 0x06 }, - { 0x00, 0x08 }, { 0x40, 0x0C }, { 0x12, 0x06 }, { 0x52, 0x0A }, - { 0x22, 0x0E }, { 0x62, 0x10 }, { 0x02, 0x10 }, { 0xFF, 0x00 } +static const struct latency_entry latency_650_t0[] = { + {0x10, 0x02}, {0x50, 0x02}, {0x20, 0x04}, {0x60, 0x06}, + {0x00, 0x08}, {0x40, 0x0C}, {0x12, 0x06}, {0x52, 0x0A}, + {0x22, 0x0E}, {0x62, 0x10}, {0x02, 0x10}, {0xFF, 0x00} }; -static const struct latency_entry latency_650_t1[] = -{ - { 0x12, 0x14 }, { 0x52, 0x16 }, { 0x22, 0x16 }, { 0x62, 0x16 }, - { 0xFF, 0x00 } +static const struct latency_entry latency_650_t1[] = { + {0x12, 0x14}, {0x52, 0x16}, {0x22, 0x16}, {0x62, 0x16}, + {0xFF, 0x00} }; -static const struct latency_entry latency_670_t0[] = -{ - { 0x60, 0x06 }, { 0x00, 0x08 }, { 0x12, 0x06 }, { 0x52, 0x0A }, - { 0x22, 0x0E }, { 0x62, 0x10 }, { 0x02, 0x10 }, { 0x42, 0x02 }, - { 0x11, 0x0E }, { 0x51, 0x0C }, { 0x21, 0x02 }, { 0x61, 0x10 }, - { 0x01, 0x10 }, { 0x41, 0x02 }, { 0xFF, 0x00 } +static const struct latency_entry latency_670_t0[] = { + {0x60, 0x06}, {0x00, 0x08}, {0x12, 0x06}, {0x52, 0x0A}, + {0x22, 0x0E}, {0x62, 0x10}, {0x02, 0x10}, {0x42, 0x02}, + {0x11, 0x0E}, {0x51, 0x0C}, {0x21, 0x02}, {0x61, 0x10}, + {0x01, 0x10}, {0x41, 0x02}, {0xFF, 0x00} }; -static const struct latency_entry latency_670_t1[] = -{ - { 0x22, 0x18 }, { 0x62, 0x18 }, { 0x02, 0x1A }, { 0x11, 0x18 }, - { 0xFF, 0x00 } +static const struct latency_entry latency_670_t1[] = { + {0x22, 0x18}, {0x62, 0x18}, {0x02, 0x1A}, {0x11, 0x18}, + {0xFF, 0x00} }; -static const struct latency_entry latency_670_t2[] = -{ - { 0x22, 0x12 }, { 0x62, 0x14 }, { 0x02, 0x16 }, { 0x42, 0x1E }, - { 0x11, 0x12 }, { 0x51, 0x16 }, { 0x21, 0x1E }, { 0x61, 0x14 }, - { 0x01, 0x16 }, { 0x41, 0x1E }, { 0xFF, 0x00 } +static const struct latency_entry latency_670_t2[] = { + {0x22, 0x12}, {0x62, 0x14}, {0x02, 0x16}, {0x42, 0x1E}, + {0x11, 0x12}, {0x51, 0x16}, {0x21, 0x1E}, {0x61, 0x14}, + {0x01, 0x16}, {0x41, 0x1E}, {0xFF, 0x00} }; /* Latency tables for 650 model/type */ -static const struct latency_entry *latency_650[] = -{ - latency_650_t0, latency_650_t1, latency_650_t1 +static const struct latency_entry *latency_650[] = { + latency_650_t0, latency_650_t1, latency_650_t1 }; /* Latency tables for 670 model/type */ -static const struct latency_entry *latency_670[] = -{ - latency_670_t0, latency_670_t1, latency_670_t2 +static const struct latency_entry *latency_670[] = { + latency_670_t0, latency_670_t1, latency_670_t2 }; static int calculate_l2_latency(void) { - unsigned int eax, ebx, ecx, edx; - int l; - const struct latency_entry *latency_table, *le; + unsigned int eax, ebx, ecx, edx; + int l; + const struct latency_entry *latency_table, *le; - /* Read an undocumented MSR */ - rdmsr(0x17, eax, edx); + /* Read an undocumented MSR */ + rdmsr(0x17, eax, edx); - DBG("rdmsr(0x17) = %x, %x\n", eax, edx); + DBG("rdmsr(0x17) = %x, %x\n", eax, edx); - /* Mask out [23:20] in EDX. Are Intel trying to hide this?? */ - edx &= 0x1e00000; + /* Mask out [23:20] in EDX. Are Intel trying to hide this?? */ + edx &= 0x1e00000; - if (edx != 0) - { - /* Get latency value directly from edx */ - l = edx >> 20; - } - else - { - /* Look up the latency from tables */ - int t, a; + if (edx != 0) { + /* Get latency value directly from edx */ + l = edx >> 20; + } else { + /* Look up the latency from tables */ + int t, a; - /* Read L2 register 0 */ - a = read_l2(0); - if (a < 0) - return -1; + /* Read L2 register 0 */ + a = read_l2(0); + if (a < 0) + return -1; - /* Mask out [7:4] */ - a &= 0xf0; + /* Mask out [7:4] */ + a &= 0xf0; - if ((a & 0x20) == 0) - t = 0; - else if (a == 0x20) - t = 1; - else if (a == 0x30) - t = 2; - else - return -1; - - intel_cpuid(1, &eax, &ebx, &ecx, &edx); + if ((a & 0x20) == 0) + t = 0; + else if (a == 0x20) + t = 1; + else if (a == 0x30) + t = 2; + else + return -1; - /* Mask out Model/Type */ - eax &= 0xfff0; + intel_cpuid(1, &eax, &ebx, &ecx, &edx); - DBG("L2 latency type = %x\n", t); + /* Mask out Model/Type */ + eax &= 0xfff0; - if (eax == 0x650) - { - /* Read EBL_CR_POWERON */ - rdmsr(0x2a, eax, edx); - - /* Mask [25:22] [19] Clock frequency Ratio & reserved */ - eax &= 0x3c80000; + DBG("L2 latency type = %x\n", t); - /* Shift to [7:4] [1] */ - eax >>= 18; + if (eax == 0x650) { + /* Read EBL_CR_POWERON */ + rdmsr(0x2a, eax, edx); - latency_table = latency_650[t]; - } - else if (eax == 0x670) - { - /* Read EBL_CR_POWERON */ - rdmsr(0x2a, eax, edx); - - /* Mask [25:22] [19:18] Clock frequency Ratio & reserved */ - eax &= 0x3cc0000; + /* Mask [25:22] [19] Clock frequency Ratio & reserved */ + eax &= 0x3c80000; - /* Shift to [7:4] [1:0] */ - eax >>= 18; + /* Shift to [7:4] [1] */ + eax >>= 18; - latency_table = latency_670[t]; - } - else - return -1; + latency_table = latency_650[t]; + } else if (eax == 0x670) { + /* Read EBL_CR_POWERON */ + rdmsr(0x2a, eax, edx); - DBG("Searching for key %x\n", eax); + /* Mask [25:22] [19:18] Clock frequency Ratio & reserved */ + eax &= 0x3cc0000; - /* Search table for matching entry */ - for(le = latency_table; le->key != eax; le++) - { - /* Fail if we get to the end of the table */ - if (le->key == 0xff) - { - printk(KERN_ERR "Could not find key %x in latency table\n", - eax); - return -1; - } + /* Shift to [7:4] [1:0] */ + eax >>= 18; + + latency_table = latency_670[t]; + } else + return -1; + + DBG("Searching for key %x\n", eax); + + /* Search table for matching entry */ + for (le = latency_table; le->key != eax; le++) { + /* Fail if we get to the end of the table */ + if (le->key == 0xff) { + printk(KERN_ERR + "Could not find key %x in latency table\n", + eax); + return -1; + } + } + + l = le->value; } - l = le->value; - } + DBG("L2 Cache latency is %d\n", l / 2); - DBG("L2 Cache latency is %d\n", l/2); + /* Read BBL_CR_CTL3 */ + rdmsr(0x11e, eax, edx); - /* Read BBL_CR_CTL3 */ - rdmsr(0x11e, eax, edx); + /* Mask out the latency */ + eax &= 0xffffffe1; - /* Mask out the latency */ - eax &= 0xffffffe1; + /* Or in the new value */ + eax |= l; - /* Or in the new value */ - eax |= l; + /* Write BBL_CR_CTL3 */ + wrmsr(0x11e, eax, edx); - /* Write BBL_CR_CTL3 */ - wrmsr(0x11e, eax, edx); - - return 0; + return 0; } /* Pass some infomation into the L2 controller register 4*/ static int set_l2_register4(int l) { - int a; + int a; - /* Mask out all but lower 2 bits in l */ - l &= 3; + /* Mask out all but lower 2 bits in l */ + l &= 3; - /* Read L2 register 4 */ - a = read_l2(4); - if (a < 0) - return -1; + /* Read L2 register 4 */ + a = read_l2(4); + if (a < 0) + return -1; - /* Mask off the lower 2 bits */ - a &= 0xfffc; + /* Mask off the lower 2 bits */ + a &= 0xfffc; - /* Or in the new latency */ - a |= l; + /* Or in the new latency */ + a |= l; - /* Write L2 register 4 */ - if (write_l2(4, a) != 0) - return -1; + /* Write L2 register 4 */ + if (write_l2(4, a) != 0) + return -1; - return 0; + return 0; } static int calculate_l2_cache_size(void) { - unsigned int eax, edx; - int v; - - v = read_l2(0); - if (v < 0) - return -1; - if ((v & 0x20) == 0) - { - unsigned int cache_setting; + unsigned int eax, edx; int v; - unsigned int address, size; - - /* Read BBL_CR_CTL3 */ - rdmsr(0x11e, eax, edx); - - /* Check sizes from 256KB up to 4MB */ - for(cache_setting = 0x2000; - cache_setting <= 0x20000; - cache_setting <<= 1) - { - unsigned int new_eax; - - /* Mask out the cache size */ - eax &= 0xfffc1fff; - - /* Or in the current setting */ - eax |= cache_setting; - - new_eax = eax; - - /* Write new value into BBL_CR_CTL3 and read it back */ - wrmsr(0x11e, eax, edx); - rdmsr(0x11e, eax, edx); - - /* If the value didn't change then break */ - if (eax != new_eax) - break; - } - - /* Reset to the last value that worked */ - cache_setting >>= 1; - - /* Mask to just the cache setting bits */ - cache_setting &= 0x3e000; - - /* Mask out cache size from eax */ - eax &= 0xfffc1fff; - - /* Or in the correct setting */ - eax |= cache_setting; - - /* Write new value into BBL_CR_CTL3 */ - wrmsr(0x11e, eax, edx); - - DBG("Maximum cache mask is %x\n", cache_setting); - - /* Write aaaaaaaa:aaaaaaaa to address 0 in the l2 cache */ - v = test_l2_address_alias(0, 0, 0xaaaaaaaa, 0xaaaaaaaa); - if (v != 0) - return -1; - - size = 1; - address = 0x8000; - - while(1) - { - v = test_l2_address_alias(address, 0, 0x55555555, 0x55555555); - if (v < 0) - return -1; - else if (v == 0) - break; - - size <<= 1; - address <<= 1; - - if (address > 0x200000) - return -1; - } - - /* Mask size */ - size &= 0x3e; - - /* Shift to [17:13] */ - size <<= 12; - - /* Read BBL_CR_CTL3 */ - rdmsr(0x11e, eax, edx); - - /* Mask out the cache_setting */ - eax &= 0xfffc1fff; - - /* Or in the calculated value */ - eax |= size; - - /* Write cache size into BBL_CR_CTL3 */ - wrmsr(0x11e, eax, edx); - - DBG("L2 Cache Mask is %x\n", size); - - /* Shift to [6:2] */ - size >>= 11; - - v = read_l2(2); - - DBG("read_l2(2) = %x\n", v); + v = read_l2(0); if (v < 0) - return -1; + return -1; + if ((v & 0x20) == 0) { + unsigned int cache_setting; + int v; + unsigned int address, size; - v &= 0x3; + /* Read BBL_CR_CTL3 */ + rdmsr(0x11e, eax, edx); - /* Shift size right by v */ - size >>= v; + /* Check sizes from 256KB up to 4MB */ + for (cache_setting = 0x2000; + cache_setting <= 0x20000; cache_setting <<= 1) { + unsigned int new_eax; - /* Or in this size */ - v |= size; + /* Mask out the cache size */ + eax &= 0xfffc1fff; - DBG("write_l2(2) = %x\n", v); + /* Or in the current setting */ + eax |= cache_setting; - if (write_l2(2, v) != 0) - return -1; - } - else - { - int a, b, c; + new_eax = eax; - a = read_l2(2); + /* Write new value into BBL_CR_CTL3 and read it back */ + wrmsr(0x11e, eax, edx); + rdmsr(0x11e, eax, edx); - DBG("read_l2(2) = %x\n", a); + /* If the value didn't change then break */ + if (eax != new_eax) + break; + } - if (a < 0) - return -1; - - b = a & 0x7; - c = a >> 6; + /* Reset to the last value that worked */ + cache_setting >>= 1; - a = 1< 0x200000) + return -1; + } + + /* Mask size */ + size &= 0x3e; + + /* Shift to [17:13] */ + size <<= 12; + + /* Read BBL_CR_CTL3 */ + rdmsr(0x11e, eax, edx); + + /* Mask out the cache_setting */ + eax &= 0xfffc1fff; + + /* Or in the calculated value */ + eax |= size; + + /* Write cache size into BBL_CR_CTL3 */ + wrmsr(0x11e, eax, edx); + + DBG("L2 Cache Mask is %x\n", size); + + /* Shift to [6:2] */ + size >>= 11; + + v = read_l2(2); + + DBG("read_l2(2) = %x\n", v); + + if (v < 0) + return -1; + + v &= 0x3; + + /* Shift size right by v */ + size >>= v; + + /* Or in this size */ + v |= size; + + DBG("write_l2(2) = %x\n", v); + + if (write_l2(2, v) != 0) + return -1; + } else { + int a, b, c; + + a = read_l2(2); + + DBG("read_l2(2) = %x\n", a); + + if (a < 0) + return -1; + + b = a & 0x7; + c = a >> 6; + + a = 1 << c * b; + + a &= 0xf; + + DBG("Calculated a = %x\n", a); + + if (a == 0) + return -1; + + /* Shift to 17:14 */ + a <<= 14; + + /* Read BBL_CR_CTL3 */ + rdmsr(0x11e, eax, edx); + + /* Mask out the cache */ + eax &= 0xfffc1fff; + + /* Or in the calculated value */ + eax |= a; + + /* Write cache size into BBL_CR_CTL3 */ + wrmsr(0x11e, eax, edx); + } + + return 0; } static int calculate_l2_physical_address_range(void) { - unsigned int eax, edx; - int r0, r3; + unsigned int eax, edx; + int r0, r3; - r3 = read_l2(3); - if (r3 < 0) - return -1; + r3 = read_l2(3); + if (r3 < 0) + return -1; - r0 = read_l2(0); - if (r0 < 0) - return -1; + r0 = read_l2(0); + if (r0 < 0) + return -1; - if (r0 & 0x20) - r3 = 0x7; - else - r3 &= 0x7; + if (r0 & 0x20) + r3 = 0x7; + else + r3 &= 0x7; - DBG("L2 Physical Address Range is %dM\n", (1<