From: Sir Richard Date: Thu, 28 Jan 2010 20:43:25 +0000 (+0000) Subject: [NTOS]: Fix L1/L2 cache detection and write out the size and associativity. Now that... X-Git-Tag: backups/jcatena-branch@60647~14^2~36 X-Git-Url: https://git.reactos.org/?p=reactos.git;a=commitdiff_plain;h=55c5579b1d510856e4cef1731d746aeef64528a8 [NTOS]: Fix L1/L2 cache detection and write out the size and associativity. Now that KeGetCurrentProcessorNumber doesn't think your L2 cache is the number of CPUs, this can be safely done. svn path=/trunk/; revision=45300 --- diff --git a/reactos/ntoskrnl/ke/i386/cpu.c b/reactos/ntoskrnl/ke/i386/cpu.c index b8d9853e6a8..21d49c90123 100644 --- a/reactos/ntoskrnl/ke/i386/cpu.c +++ b/reactos/ntoskrnl/ke/i386/cpu.c @@ -40,6 +40,7 @@ ULONG KeLargestCacheLine = 0x40; ULONG KeDcacheFlushCount = 0; ULONG KeIcacheFlushCount = 0; ULONG KiDmaIoCoherency = 0; +ULONG KePrefetchNTAGranularity = 32; CHAR KeNumberProcessors; KAFFINITY KeActiveProcessors = 1; BOOLEAN KiI386PentiumLockErrataPresent; @@ -453,6 +454,7 @@ KiGetCacheInformation(VOID) ULONG CacheRequests = 0, i; ULONG CurrentRegister; UCHAR RegisterByte; + ULONG Size, Associativity = 0, CacheLine = 64, CurrentSize = 0; BOOLEAN FirstPass = TRUE; /* Set default L2 size */ @@ -517,17 +519,144 @@ KiGetCacheInformation(VOID) * (32MB), or from 0x80 to 0x89 (same size but * 8-way associative. */ - if (((RegisterByte > 0x40) && - (RegisterByte <= 0x49)) || - ((RegisterByte > 0x80) && - (RegisterByte <= 0x89))) + if (((RegisterByte > 0x40) && (RegisterByte <= 0x47)) || + ((RegisterByte > 0x78) && (RegisterByte <= 0x7C)) || + ((RegisterByte > 0x80) && (RegisterByte <= 0x85))) { + /* Compute associativity */ + Associativity = 4; + if (RegisterByte >= 0x79) Associativity = 8; + /* Mask out only the first nibble */ - RegisterByte &= 0x0F; - - /* Set the L2 Cache Size */ - Pcr->SecondLevelCacheSize = 0x10000 << - RegisterByte; + RegisterByte &= 0x07; + + /* Check if this cache is bigger than the last */ + Size = 0x10000 << RegisterByte; + if ((Size / Associativity) > CurrentSize) + { + /* Set the L2 Cache Size and Associativity */ + CurrentSize = Size / Associativity; + Pcr->SecondLevelCacheSize = Size; + Pcr->SecondLevelCacheAssociativity = Associativity; + } + } + else if ((RegisterByte > 0x21) && (RegisterByte <= 0x29)) + { + /* Set minimum cache line size */ + if (CacheLine < 128) CacheLine = 128; + + /* Hard-code size/associativity */ + Associativity = 8; + switch (RegisterByte) + { + case 0x22: + Size = 512 * 1024; + Associativity = 4; + break; + + case 0x23: + Size = 1024 * 1024; + break; + + case 0x25: + Size = 2048 * 1024; + break; + + case 0x29: + Size = 4096 * 1024; + break; + + default: + Size = 0; + break; + } + + /* Check if this cache is bigger than the last */ + if ((Size / Associativity) > CurrentSize) + { + /* Set the L2 Cache Size and Associativity */ + CurrentSize = Size / Associativity; + Pcr->SecondLevelCacheSize = Size; + Pcr->SecondLevelCacheAssociativity = Associativity; + } + } + else if (((RegisterByte > 0x65) && (RegisterByte < 0x69)) || + (RegisterByte == 0x2C) || (RegisterByte == 0xF0)) + { + /* Indicates L1 cache line of 64 bytes */ + KePrefetchNTAGranularity = 64; + } + else if (RegisterByte == 0xF1) + { + /* Indicates L1 cache line of 128 bytes */ + KePrefetchNTAGranularity = 128; + } + else if (((RegisterByte >= 0x4A) && (RegisterByte <= 0x4C)) || + (RegisterByte == 0x78) || + (RegisterByte == 0x7D) || + (RegisterByte == 0x7F) || + (RegisterByte == 0x86) || + (RegisterByte == 0x87)) + { + /* Set minimum cache line size */ + if (CacheLine < 64) CacheLine = 64; + + /* Hard-code size/associativity */ + switch (RegisterByte) + { + case 0x4A: + Size = 4 * 1024 * 1024; + Associativity = 8; + break; + + case 0x4B: + Size = 6 * 1024 * 1024; + Associativity = 12; + break; + + case 0x4C: + Size = 8 * 1024 * 1024; + Associativity = 16; + break; + + case 0x78: + Size = 1 * 1024 * 1024; + Associativity = 4; + break; + + case 0x7D: + Size = 2 * 1024 * 1024; + Associativity = 8; + break; + + case 0x7F: + Size = 512 * 1024; + Associativity = 2; + break; + + case 0x86: + Size = 512 * 1024; + Associativity = 4; + break; + + case 0x87: + Size = 1 * 1024 * 1024; + Associativity = 8; + break; + + default: + Size = 0; + break; + } + + /* Check if this cache is bigger than the last */ + if ((Size / Associativity) > CurrentSize) + { + /* Set the L2 Cache Size and Associativity */ + CurrentSize = Size / Associativity; + Pcr->SecondLevelCacheSize = Size; + Pcr->SecondLevelCacheAssociativity = Associativity; + } } } } @@ -537,15 +666,65 @@ KiGetCacheInformation(VOID) case CPU_AMD: - /* Check if we support CPUID 0x80000006 */ - CPUID(0x80000000, &Data[0], &Dummy, &Dummy, &Dummy); - if (Data[0] >= 6) + /* Check if we support CPUID 0x80000005 */ + CPUID(0x80000000, &Data[0], &Data[1], &Data[2], &Data[3]); + if (Data[0] >= 0x80000006) { - /* Get 2nd level cache and tlb size */ - CPUID(0x80000006, &Dummy, &Dummy, &Data[2], &Dummy); + /* Get L1 size first */ + CPUID(0x80000005, &Data[0], &Data[1], &Data[2], &Data[3]); + KePrefetchNTAGranularity = Data[2] & 0xFF; + + /* Check if we support CPUID 0x80000006 */ + CPUID(0x80000000, &Data[0], &Data[1], &Data[2], &Data[3]); + if (Data[0] >= 0x80000006) + { + /* Get 2nd level cache and tlb size */ + CPUID(0x80000006, &Data[0], &Data[1], &Data[2], &Data[3]); + + /* Cache line size */ + CacheLine = Data[2] & 0xFF; + + /* Hardcode associativity */ + RegisterByte = Data[2] >> 12; + switch (RegisterByte) + { + case 2: + Associativity = 2; + break; + + case 4: + Associativity = 4; + break; + + case 6: + Associativity = 8; + break; + + case 8: + case 15: + Associativity = 16; + break; + + default: + Associativity = 1; + break; + } + + /* Compute size */ + Size = (Data[2] >> 16) << 10; + + /* Hack for Model 6, Steping 300 */ + if ((KeGetCurrentPrcb()->CpuType == 6) && + (KeGetCurrentPrcb()->CpuStep == 0x300)) + { + /* Stick 64K in there */ + Size = 64 * 1024; + } - /* Set the L2 Cache Size */ - Pcr->SecondLevelCacheSize = (Data[2] & 0xFFFF0000) >> 6; + /* Set the L2 Cache Size and associativity */ + Pcr->SecondLevelCacheSize = Size; + Pcr->SecondLevelCacheAssociativity = Associativity; + } } break; @@ -557,6 +736,14 @@ KiGetCacheInformation(VOID) /* FIXME */ break; } + + /* Set the cache line */ + if (CacheLine > KeLargestCacheLine) KeLargestCacheLine = CacheLine; + DPRINT1("Prefetch Cache: %d bytes\tL2 Cache: %d bytes\tL2 Cache Line: %d bytes\tL2 Cache Associativity: %d\n", + KePrefetchNTAGranularity, + Pcr->SecondLevelCacheSize, + KeLargestCacheLine, + Pcr->SecondLevelCacheAssociativity); } VOID