Annotation of sys/arch/amd64/amd64/cacheinfo.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: cacheinfo.c,v 1.3 2006/05/09 13:02:29 mickey Exp $ */
2:
3: /*-
4: * Copyright (c) 2000 The NetBSD Foundation, Inc.
5: * All rights reserved.
6: *
7: * This code is derived from software contributed to The NetBSD Foundation
8: * by Jason R. Thorpe.
9: *
10: * Redistribution and use in source and binary forms, with or without
11: * modification, are permitted provided that the following conditions
12: * are met:
13: * 1. Redistributions of source code must retain the above copyright
14: * notice, this list of conditions and the following disclaimer.
15: * 2. Redistributions in binary form must reproduce the above copyright
16: * notice, this list of conditions and the following disclaimer in the
17: * documentation and/or other materials provided with the distribution.
18: * 3. All advertising materials mentioning features or use of this software
19: * must display the following acknowledgement:
20: * This product includes software developed by the NetBSD
21: * Foundation, Inc. and its contributors.
22: * 4. Neither the name of The NetBSD Foundation nor the names of its
23: * contributors may be used to endorse or promote products derived
24: * from this software without specific prior written permission.
25: *
26: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36: * POSSIBILITY OF SUCH DAMAGE.
37: */
38:
39: #include <sys/param.h>
40: #include <sys/systm.h>
41:
42: #include <machine/cpu.h>
43: #include <machine/specialreg.h>
44:
45: static char *print_cache_config(struct cpu_info *, int, char *, char *);
46: static char *print_tlb_config(struct cpu_info *, int, char *, char *);
47:
48: static char *
49: print_cache_config(struct cpu_info *ci, int cache_tag, char *name, char *sep)
50: {
51: struct x86_cache_info *cai = &ci->ci_cinfo[cache_tag];
52:
53: if (cai->cai_totalsize == 0)
54: return sep;
55:
56: if (sep == NULL)
57: printf("%s: ", ci->ci_dev->dv_xname);
58: else
59: printf("%s", sep);
60:
61: if (cai->cai_string != NULL)
62: printf("%s ", cai->cai_string);
63: else if (cai->cai_totalsize >= 1024*1024)
64: printf("%dMB %db/line ", cai->cai_totalsize / 1024 / 1024,
65: cai->cai_linesize);
66: else
67: printf("%dKB %db/line ", cai->cai_totalsize / 1024,
68: cai->cai_linesize);
69:
70: switch (cai->cai_associativity) {
71: case 0:
72: printf("disabled");
73: break;
74: case 1:
75: printf("direct-mapped");
76: break;
77: case 0xff:
78: printf("fully associative");
79: break;
80: default:
81: printf("%d-way", cai->cai_associativity);
82: break;
83: }
84:
85: if (name != NULL)
86: printf(" %s", name);
87:
88: return ", ";
89: }
90:
91: static char *
92: print_tlb_config(struct cpu_info *ci, int cache_tag, char *name, char *sep)
93: {
94: struct x86_cache_info *cai = &ci->ci_cinfo[cache_tag];
95:
96: if (cai->cai_totalsize == 0)
97: return sep;
98:
99: if (sep == NULL)
100: printf("%s: ", ci->ci_dev->dv_xname);
101: else
102: printf("%s", sep);
103: if (name != NULL)
104: printf("%s ", name);
105:
106: if (cai->cai_string != NULL) {
107: printf("%s", cai->cai_string);
108: } else {
109: if (cai->cai_linesize >= 1024*1024)
110: printf("%d %dMB entries ", cai->cai_totalsize,
111: cai->cai_linesize / 1024 / 1024);
112: else
113: printf("%d %dKB entries ", cai->cai_totalsize,
114: cai->cai_linesize / 1024);
115: switch (cai->cai_associativity) {
116: case 0:
117: printf("disabled");
118: break;
119: case 1:
120: printf("direct-mapped");
121: break;
122: case 0xff:
123: printf("fully associative");
124: break;
125: default:
126: printf("%d-way", cai->cai_associativity);
127: break;
128: }
129: }
130: return ", ";
131: }
132:
133: const struct x86_cache_info *
134: cache_info_lookup(const struct x86_cache_info *cai, u_int8_t desc)
135: {
136: int i;
137:
138: for (i = 0; cai[i].cai_desc != 0; i++) {
139: if (cai[i].cai_desc == desc)
140: return (&cai[i]);
141: }
142:
143: return (NULL);
144: }
145:
146:
147: static const struct x86_cache_info amd_cpuid_l2cache_assoc_info[] = {
148: { 0, 0x01, 1 },
149: { 0, 0x02, 2 },
150: { 0, 0x04, 4 },
151: { 0, 0x06, 8 },
152: { 0, 0x08, 16 },
153: { 0, 0x0f, 0xff },
154: { 0, 0x00, 0 },
155: };
156:
157: void
158: amd_cpu_cacheinfo(struct cpu_info *ci)
159: {
160: const struct x86_cache_info *cp;
161: struct x86_cache_info *cai;
162: int family, model;
163: u_int descs[4];
164: u_int lfunc;
165:
166: family = (ci->ci_signature >> 8) & 15;
167: model = CPUID2MODEL(ci->ci_signature);
168:
169: /*
170: * K5 model 0 has none of this info.
171: */
172: if (family == 5 && model == 0)
173: return;
174:
175: /*
176: * Get extended values for K8 and up.
177: */
178: if (family == 0xf) {
179: family += (ci->ci_signature >> 20) & 0xff;
180: model += (ci->ci_signature >> 16) & 0xf;
181: }
182:
183: /*
184: * Determine the largest extended function value.
185: */
186: CPUID(0x80000000, descs[0], descs[1], descs[2], descs[3]);
187: lfunc = descs[0];
188:
189: /*
190: * Determine L1 cache/TLB info.
191: */
192: if (lfunc < 0x80000005) {
193: /* No L1 cache info available. */
194: return;
195: }
196:
197: CPUID(0x80000005, descs[0], descs[1], descs[2], descs[3]);
198:
199: /*
200: * K6-III and higher have large page TLBs.
201: */
202: if ((family == 5 && model >= 9) || family >= 6) {
203: cai = &ci->ci_cinfo[CAI_ITLB2];
204: cai->cai_totalsize = AMD_L1_EAX_ITLB_ENTRIES(descs[0]);
205: cai->cai_associativity = AMD_L1_EAX_ITLB_ASSOC(descs[0]);
206: cai->cai_linesize = (4 * 1024 * 1024);
207:
208: cai = &ci->ci_cinfo[CAI_DTLB2];
209: cai->cai_totalsize = AMD_L1_EAX_DTLB_ENTRIES(descs[0]);
210: cai->cai_associativity = AMD_L1_EAX_DTLB_ASSOC(descs[0]);
211: cai->cai_linesize = (4 * 1024 * 1024);
212: }
213:
214: cai = &ci->ci_cinfo[CAI_ITLB];
215: cai->cai_totalsize = AMD_L1_EBX_ITLB_ENTRIES(descs[1]);
216: cai->cai_associativity = AMD_L1_EBX_ITLB_ASSOC(descs[1]);
217: cai->cai_linesize = (4 * 1024);
218:
219: cai = &ci->ci_cinfo[CAI_DTLB];
220: cai->cai_totalsize = AMD_L1_EBX_DTLB_ENTRIES(descs[1]);
221: cai->cai_associativity = AMD_L1_EBX_DTLB_ASSOC(descs[1]);
222: cai->cai_linesize = (4 * 1024);
223:
224: cai = &ci->ci_cinfo[CAI_DCACHE];
225: cai->cai_totalsize = AMD_L1_ECX_DC_SIZE(descs[2]);
226: cai->cai_associativity = AMD_L1_ECX_DC_ASSOC(descs[2]);
227: cai->cai_linesize = AMD_L1_EDX_IC_LS(descs[2]);
228:
229: cai = &ci->ci_cinfo[CAI_ICACHE];
230: cai->cai_totalsize = AMD_L1_EDX_IC_SIZE(descs[3]);
231: cai->cai_associativity = AMD_L1_EDX_IC_ASSOC(descs[3]);
232: cai->cai_linesize = AMD_L1_EDX_IC_LS(descs[3]);
233:
234: /*
235: * Determine L2 cache/TLB info.
236: */
237: if (lfunc < 0x80000006) {
238: /* No L2 cache info available. */
239: return;
240: }
241:
242: CPUID(0x80000006, descs[0], descs[1], descs[2], descs[3]);
243:
244: cai = &ci->ci_cinfo[CAI_L2CACHE];
245: cai->cai_totalsize = AMD_L2_ECX_C_SIZE(descs[2]);
246: cai->cai_associativity = AMD_L2_ECX_C_ASSOC(descs[2]);
247: cai->cai_linesize = AMD_L2_ECX_C_LS(descs[2]);
248:
249: cp = cache_info_lookup(amd_cpuid_l2cache_assoc_info,
250: cai->cai_associativity);
251: if (cp != NULL)
252: cai->cai_associativity = cp->cai_associativity;
253: else
254: cai->cai_associativity = 0; /* XXX Unknown/reserved */
255: }
256:
257: void
258: x86_print_cacheinfo(struct cpu_info *ci)
259: {
260: char *sep;
261:
262: sep = NULL;
263: if (ci->ci_cinfo[CAI_ICACHE].cai_totalsize != 0 ||
264: ci->ci_cinfo[CAI_DCACHE].cai_totalsize != 0) {
265: sep = print_cache_config(ci, CAI_ICACHE, "I-cache", NULL);
266: sep = print_cache_config(ci, CAI_DCACHE, "D-cache", sep);
267: }
268: if (ci->ci_cinfo[CAI_L2CACHE].cai_totalsize != 0) {
269: sep = print_cache_config(ci, CAI_L2CACHE, "L2 cache", sep);
270: if (sep != NULL)
271: printf("\n");
272: }
273: if (ci->ci_cinfo[CAI_ITLB].cai_totalsize != 0) {
274: sep = print_tlb_config(ci, CAI_ITLB, "ITLB", NULL);
275: sep = print_tlb_config(ci, CAI_ITLB2, NULL, sep);
276: if (sep != NULL)
277: printf("\n");
278: }
279: if (ci->ci_cinfo[CAI_DTLB].cai_totalsize != 0) {
280: sep = print_tlb_config(ci, CAI_DTLB, "DTLB", NULL);
281: sep = print_tlb_config(ci, CAI_DTLB2, NULL, sep);
282: if (sep != NULL)
283: printf("\n");
284: }
285: }
CVSweb