Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
3263 | Serge | 1 | |
2 | #include |
||
3 | |||
4 | |||
5 | |||
6 | unsigned int *ecx, unsigned int *edx) |
||
7 | { |
||
8 | /* ecx is often an input as well as an output. */ |
||
9 | asm volatile("cpuid" |
||
10 | : "=a" (*eax), |
||
11 | "=b" (*ebx), |
||
12 | "=c" (*ecx), |
||
13 | "=d" (*edx) |
||
14 | : "0" (*eax), "2" (*ecx) |
||
15 | : "memory"); |
||
16 | } |
||
17 | |||
18 | |||
19 | static inline void cpuid_count(unsigned int op, int count, |
||
20 | unsigned int *eax, unsigned int *ebx, |
||
21 | unsigned int *ecx, unsigned int *edx) |
||
22 | { |
||
23 | *eax = op; |
||
24 | *ecx = count; |
||
25 | native_cpuid(eax, ebx, ecx, edx); |
||
26 | } |
||
27 | |||
28 | |||
29 | |||
30 | CACHE_TYPE_NULL = 0, |
||
31 | CACHE_TYPE_DATA = 1, |
||
32 | CACHE_TYPE_INST = 2, |
||
33 | CACHE_TYPE_UNIFIED = 3 |
||
34 | }; |
||
35 | |||
36 | |||
37 | |||
38 | struct { |
||
39 | enum _cache_type type:5; |
||
40 | unsigned int level:3; |
||
41 | unsigned int is_self_initializing:1; |
||
42 | unsigned int is_fully_associative:1; |
||
43 | unsigned int reserved:4; |
||
44 | unsigned int num_threads_sharing:12; |
||
45 | unsigned int num_cores_on_die:6; |
||
46 | } split; |
||
47 | uint32_t full; |
||
48 | }; |
||
49 | |||
50 | |||
51 | struct { |
||
52 | unsigned int coherency_line_size:12; |
||
53 | unsigned int physical_line_partition:10; |
||
54 | unsigned int ways_of_associativity:10; |
||
55 | } split; |
||
56 | uint32_t full; |
||
57 | }; |
||
58 | |||
59 | |||
60 | struct { |
||
61 | unsigned int number_of_sets:32; |
||
62 | } split; |
||
63 | uint32_t full; |
||
64 | }; |
||
65 | |||
66 | |||
67 | union _cpuid4_leaf_eax eax; |
||
68 | union _cpuid4_leaf_ebx ebx; |
||
69 | union _cpuid4_leaf_ecx ecx; |
||
70 | unsigned long size; |
||
71 | }; |
||
72 | |||
73 | |||
74 | cpuid4_cache_lookup_regs(int index, |
||
75 | struct _cpuid4_info_regs *this_leaf) |
||
76 | { |
||
77 | union _cpuid4_leaf_eax eax; |
||
78 | union _cpuid4_leaf_ebx ebx; |
||
79 | union _cpuid4_leaf_ecx ecx; |
||
80 | unsigned edx; |
||
81 | |||
82 | |||
83 | |||
84 | |||
85 | return -1; /* better error ? */ |
||
86 | |||
87 | |||
88 | this_leaf->ebx = ebx; |
||
89 | this_leaf->ecx = ecx; |
||
90 | this_leaf->size = (ecx.split.number_of_sets + 1) * |
||
91 | (ebx.split.coherency_line_size + 1) * |
||
92 | (ebx.split.physical_line_partition + 1) * |
||
93 | (ebx.split.ways_of_associativity + 1); |
||
94 | return 0; |
||
95 | } |
||
96 | |||
97 | |||
98 | { |
||
99 | unsigned int eax, ebx, ecx, edx, op; |
||
100 | union _cpuid4_leaf_eax cache_eax; |
||
101 | int i = -1; |
||
102 | |||
103 | |||
104 | ++i; |
||
105 | /* Do cpuid(op) loop to find out num_cache_leaves */ |
||
106 | cpuid_count(4, i, &eax, &ebx, &ecx, &edx); |
||
107 | cache_eax.full = eax; |
||
108 | } while (cache_eax.split.type != CACHE_TYPE_NULL); |
||
109 | return i; |
||
110 | }; |
||
111 | |||
112 | |||
113 | { |
||
114 | unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */ |
||
115 | unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */ |
||
116 | unsigned int num_cache_leaves; |
||
117 | |||
118 | |||
119 | |||
120 | |||
121 | { |
||
122 | struct _cpuid4_info_regs this_leaf; |
||
123 | int retval; |
||
124 | |||
125 | |||
126 | if (retval >= 0) { |
||
127 | switch (this_leaf.eax.split.level) |
||
128 | { |
||
129 | case 1: |
||
130 | if (this_leaf.eax.split.type == CACHE_TYPE_DATA) |
||
131 | new_l1d = this_leaf.size; |
||
132 | else if (this_leaf.eax.split.type == CACHE_TYPE_INST) |
||
133 | new_l1i = this_leaf.size; |
||
134 | break; |
||
135 | case 2: |
||
136 | new_l2 = this_leaf.size; |
||
137 | break; |
||
138 | case 3: |
||
139 | new_l3 = this_leaf.size; |
||
140 | break; |
||
141 | default: |
||
142 | break; |
||
143 | } |
||
144 | } |
||
145 | } |
||
146 | printf("l2 cache %d l3 cache %d\n", new_l2, new_l3); |
||
147 | |||
148 | |||
149 | };> |
||
150 |