This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / arch / i386 / kernel / cpu / intel_cacheinfo.c
1 #include <linux/init.h>
2 #include <asm/processor.h>
3
4 #define LVL_1_INST      1
5 #define LVL_1_DATA      2
6 #define LVL_2           3
7 #define LVL_3           4
8 #define LVL_TRACE       5
9
10 struct _cache_table
11 {
12         unsigned char descriptor;
13         char cache_type;
14         short size;
15 };
16
17 /* all the cache descriptor types we care about (no TLB or trace cache entries) */
18 static struct _cache_table cache_table[] __initdata =
19 {
20         { 0x06, LVL_1_INST, 8 },        /* 4-way set assoc, 32 byte line size */
21         { 0x08, LVL_1_INST, 16 },       /* 4-way set assoc, 32 byte line size */
22         { 0x0a, LVL_1_DATA, 8 },        /* 2 way set assoc, 32 byte line size */
23         { 0x0c, LVL_1_DATA, 16 },       /* 4-way set assoc, 32 byte line size */
24         { 0x22, LVL_3,      512 },      /* 4-way set assoc, sectored cache, 64 byte line size */
25         { 0x23, LVL_3,      1024 },     /* 8-way set assoc, sectored cache, 64 byte line size */
26         { 0x25, LVL_3,      2048 },     /* 8-way set assoc, sectored cache, 64 byte line size */
27         { 0x29, LVL_3,      4096 },     /* 8-way set assoc, sectored cache, 64 byte line size */
28         { 0x2c, LVL_1_DATA, 32 },       /* 8-way set assoc, 64 byte line size */
29         { 0x30, LVL_1_INST, 32 },       /* 8-way set assoc, 64 byte line size */
30         { 0x39, LVL_2,      128 },      /* 4-way set assoc, sectored cache, 64 byte line size */
31         { 0x3b, LVL_2,      128 },      /* 2-way set assoc, sectored cache, 64 byte line size */
32         { 0x3c, LVL_2,      256 },      /* 4-way set assoc, sectored cache, 64 byte line size */
33         { 0x41, LVL_2,      128 },      /* 4-way set assoc, 32 byte line size */
34         { 0x42, LVL_2,      256 },      /* 4-way set assoc, 32 byte line size */
35         { 0x43, LVL_2,      512 },      /* 4-way set assoc, 32 byte line size */
36         { 0x44, LVL_2,      1024 },     /* 4-way set assoc, 32 byte line size */
37         { 0x45, LVL_2,      2048 },     /* 4-way set assoc, 32 byte line size */
38         { 0x60, LVL_1_DATA, 16 },       /* 8-way set assoc, sectored cache, 64 byte line size */
39         { 0x66, LVL_1_DATA, 8 },        /* 4-way set assoc, sectored cache, 64 byte line size */
40         { 0x67, LVL_1_DATA, 16 },       /* 4-way set assoc, sectored cache, 64 byte line size */
41         { 0x68, LVL_1_DATA, 32 },       /* 4-way set assoc, sectored cache, 64 byte line size */
42         { 0x70, LVL_TRACE,  12 },       /* 8-way set assoc */
43         { 0x71, LVL_TRACE,  16 },       /* 8-way set assoc */
44         { 0x72, LVL_TRACE,  32 },       /* 8-way set assoc */
45         { 0x78, LVL_2,    1024 },       /* 4-way set assoc, 64 byte line size */
46         { 0x79, LVL_2,     128 },       /* 8-way set assoc, sectored cache, 64 byte line size */
47         { 0x7a, LVL_2,     256 },       /* 8-way set assoc, sectored cache, 64 byte line size */
48         { 0x7b, LVL_2,     512 },       /* 8-way set assoc, sectored cache, 64 byte line size */
49         { 0x7c, LVL_2,    1024 },       /* 8-way set assoc, sectored cache, 64 byte line size */
50         { 0x7d, LVL_2,    2048 },       /* 8-way set assoc, 64 byte line size */
51         { 0x7f, LVL_2,     512 },       /* 2-way set assoc, 64 byte line size */
52         { 0x82, LVL_2,     256 },       /* 8-way set assoc, 32 byte line size */
53         { 0x83, LVL_2,     512 },       /* 8-way set assoc, 32 byte line size */
54         { 0x84, LVL_2,    1024 },       /* 8-way set assoc, 32 byte line size */
55         { 0x85, LVL_2,    2048 },       /* 8-way set assoc, 32 byte line size */
56         { 0x86, LVL_2,     512 },       /* 4-way set assoc, 64 byte line size */
57         { 0x87, LVL_2,    1024 },       /* 8-way set assoc, 64 byte line size */
58         { 0x00, 0, 0}
59 };
60
61 unsigned int init_intel_cacheinfo(struct cpuinfo_x86 *c)
62 {
63         unsigned int trace = 0, l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */
64
65         if (c->cpuid_level > 1) {
66                 /* supports eax=2  call */
67                 int i, j, n;
68                 int regs[4];
69                 unsigned char *dp = (unsigned char *)regs;
70
71                 /* Number of times to iterate */
72                 n = cpuid_eax(2) & 0xFF;
73
74                 for ( i = 0 ; i < n ; i++ ) {
75                         cpuid(2, &regs[0], &regs[1], &regs[2], &regs[3]);
76
77                         /* If bit 31 is set, this is an unknown format */
78                         for ( j = 0 ; j < 3 ; j++ ) {
79                                 if ( regs[j] < 0 ) regs[j] = 0;
80                         }
81
82                         /* Byte 0 is level count, not a descriptor */
83                         for ( j = 1 ; j < 16 ; j++ ) {
84                                 unsigned char des = dp[j];
85                                 unsigned char k = 0;
86
87                                 /* look up this descriptor in the table */
88                                 while (cache_table[k].descriptor != 0)
89                                 {
90                                         if (cache_table[k].descriptor == des) {
91                                                 switch (cache_table[k].cache_type) {
92                                                 case LVL_1_INST:
93                                                         l1i += cache_table[k].size;
94                                                         break;
95                                                 case LVL_1_DATA:
96                                                         l1d += cache_table[k].size;
97                                                         break;
98                                                 case LVL_2:
99                                                         l2 += cache_table[k].size;
100                                                         break;
101                                                 case LVL_3:
102                                                         l3 += cache_table[k].size;
103                                                         break;
104                                                 case LVL_TRACE:
105                                                         trace += cache_table[k].size;
106                                                         break;
107                                                 }
108
109                                                 break;
110                                         }
111
112                                         k++;
113                                 }
114                         }
115                 }
116
117                 if ( trace )
118                         printk (KERN_INFO "CPU: Trace cache: %dK uops", trace);
119                 else if ( l1i )
120                         printk (KERN_INFO "CPU: L1 I cache: %dK", l1i);
121                 if ( l1d )
122                         printk(", L1 D cache: %dK\n", l1d);
123                 else
124                         printk("\n");
125                 if ( l2 )
126                         printk(KERN_INFO "CPU: L2 cache: %dK\n", l2);
127                 if ( l3 )
128                         printk(KERN_INFO "CPU: L3 cache: %dK\n", l3);
129
130                 /*
131                  * This assumes the L3 cache is shared; it typically lives in
132                  * the northbridge.  The L1 caches are included by the L2
133                  * cache, and so should not be included for the purpose of
134                  * SMP switching weights.
135                  */
136                 c->x86_cache_size = l2 ? l2 : (l1i+l1d);
137         }
138
139         return l2;
140 }