1/* 2 * Copyright (c) 2015 ETH Zurich. 3 * All rights reserved. 4 * 5 * This file is distributed under the terms in the attached LICENSE file. 6 * If you do not find this file, copies can be found by writing to: 7 * ETH Zurich D-INFK, Universitaetsstrasse 6, CH-8092 Zurich. Attn: Systems Group. 8 */ 9 10#include <cpuid_internal.h> 11 12#include <dev/cpuid_intel_dev.h> 13 14static uint8_t cache_info_in_leaf_4 = 0; 15 16/* 17 * =============================================================================== 18 * basic processor information 19 * =============================================================================== 20 */ 21 22static errval_t proc_name(char *buf, size_t len) 23{ 24 // check if this operation is supported 25 if (cpuid_g_max_input_extended < 4) { 26 return CPUID_ERR_UNSUPPORTED_FUNCTION; 27 } 28 29 size_t written; 30 31 struct cpuid_regs reg = CPUID_REGS_INITIAL(0x80000002, 0); 32 cpuid_exec(®); 33 written = snprintf(buf, len, "%s", (char *)®.eax); 34 len -= written; 35 buf += written; 36 37 reg.eax = 0x80000003; 38 reg.ecx = 0x0; 39 cpuid_exec(®); 40 written = snprintf(buf, len, "%s", (char *)®.eax); 41 len -= written; 42 buf += written; 43 44 reg.eax = 0x80000004; 45 reg.ecx = 0x0; 46 cpuid_exec(®); 47 written = snprintf(buf, len, "%s", (char *)®.eax); 48 len -= written; 49 buf += written; 50 51 return SYS_ERR_OK; 52} 53 54static errval_t proc_family(struct cpuid_proc_family *family) 55{ 56 if (cpuid_g_max_input_basic < 1) { 57 return CPUID_ERR_UNSUPPORTED_FUNCTION; 58 } 59 60 struct cpuid_regs reg = CPUID_REGS_INITIAL(1, 0); 61 cpuid_exec(®); 62 63 cpuid_intel_family_t f = (cpuid_intel_family_t)®.eax; 64 65 family->stepping = cpuid_intel_family_stepping_extract(f); 66 family->family = cpuid_intel_family_family_extract(f); 67 family->model = cpuid_intel_family_model_extract(f); 68 family->type = cpuid_intel_family_proctype_extract(f); 69 70 if (family->family == 0x06 || family->family == 0x0f) { 71 uint16_t model = cpuid_intel_family_extmodel_extract(f); 72 family->model += (model << 4); 73 } 74 75 /* if family is zero we have to consider the extended family id */ 76 if (family->family != 0x0f) { 77 family->family += cpuid_intel_family_extfamily_extract(f); 78 } 79 80 return SYS_ERR_OK; 81} 82 83static uint32_t proc_max_input_basic(void) 84{ 85 struct cpuid_regs reg = CPUID_REGS_INITIAL(0, 0); 86 cpuid_exec(®); 87 88 return reg.eax; 89} 90 91static uint32_t proc_max_input_extended(void) 92{ 93 struct cpuid_regs reg = CPUID_REGS_INITIAL(0x80000000, 0); 94 cpuid_exec(®); 95 96 return reg.eax; 97} 98 99static errval_t frequency_info(struct cpuid_freqinfo *fi) 100{ 101 if (cpuid_g_max_input_basic < 0x16) { 102 return CPUID_ERR_UNSUPPORTED_FUNCTION; 103 } 104 105 struct cpuid_regs reg = CPUID_REGS_INITIAL(0x16, 0); 106 cpuid_exec(®); 107 108 cpuid_intel_frequency_t fq = (cpuid_intel_frequency_t)®.eax; 109 fi->base = cpuid_intel_frequency_mhz_extract(fq); 110 111 fq = (cpuid_intel_frequency_t)®.ebx; 112 fi->max = cpuid_intel_frequency_mhz_extract(fq); 113 114 fq = (cpuid_intel_frequency_t)®.ecx; 115 fi->bus = cpuid_intel_frequency_mhz_extract(fq); 116 117 return SYS_ERR_OK; 118} 119 120/* 121 * =============================================================================== 122 * cache topology information 123 * =============================================================================== 124 */ 125 126#define CPUID_FILL_TLB(_val,_tci, _assoc, _entries, _level, _type, _pgsz) \ 127 case _val: \ 128 _tci->is_tlb = 1; \ 129 _tci->ti.associativity = _assoc; \ 130 _tci->ti.entries = _entries; \ 131 _tci->ti.level = _level; \ 132 _tci->ti.type = _type; \ 133 _tci->ti.pagesize = _pgsz;\ 134 return SYS_ERR_OK; 135 136#define CPUID_FILL_CACHE(_val,_tci, _assoc, _size, _level, _type, _shared, _linesize) \ 137 case _val: \ 138 _tci->is_tlb = 0; \ 139 _tci->ci.linesize = _linesize;\ 140 _tci->ci.associativity = _assoc; \ 141 _tci->ci.sets = _size / _assoc / _tci->ci.linesize; \ 142 _tci->ci.level = _level; \ 143 _tci->ci.type = _type; \ 144 _tci->ci.size = _size; \ 145 _tci->ci.shared = _shared;\ 146 _tci->ci.name = cpuid_cache_names[_tci->ci.level][_tci->ci.type]; \ 147 _tci->ci.inclusive=1; \ 148 return SYS_ERR_OK; 149 150struct tlb_cache_info { 151 uint8_t is_tlb; 152 union { 153 struct cpuid_cacheinfo ci; 154 struct cpuid_tlbinfo ti; 155 }; 156}; 157 158static errval_t cache_info_lookup(struct tlb_cache_info *tci, uint8_t value) 159{ 160 switch(value) { 161 case 0x00: 162 //GeneralNull descriptor, this byte contains no information 163 break; 164 //TLB Instruction TLB: 4 KByte pages, 4-way set associative, 32 entries 165 CPUID_FILL_TLB(0x01, tci, 4, 32, 1, CPUID_CACHE_TYPE_INSTR, BASE_PAGE_SIZE); 166 CPUID_FILL_TLB(0x02, tci, 0xff, 2, 1, CPUID_CACHE_TYPE_INSTR, LARGE_PAGE_SIZE); 167 CPUID_FILL_TLB(0x03, tci, 4, 64, 1, CPUID_CACHE_TYPE_DATA, BASE_PAGE_SIZE); 168 CPUID_FILL_TLB(0x04, tci, 4, 8, 1, CPUID_CACHE_TYPE_DATA, LARGE_PAGE_SIZE); 169 CPUID_FILL_TLB(0x05, tci, 4, 32, 1, CPUID_CACHE_TYPE_DATA, LARGE_PAGE_SIZE); 170 //Cache 1st-level instruction cache: 8 KBytes, 4-way set associative, 32 byte line size 171 CPUID_FILL_CACHE(0x06,tci, 4, 8*1024, 1, CPUID_CACHE_TYPE_INSTR, 1, 32) 172 //Cache 1st-level instruction cache: 16 KBytes, 4-way set associative, 32 byte line size 173 CPUID_FILL_CACHE(0x08,tci, 4, 16*1024, 1, CPUID_CACHE_TYPE_INSTR, 1, 32) 174 //Cache 1st-level instruction cache: 32KBytes, 4-way set associative, 64 byte line size 175 CPUID_FILL_CACHE(0x09,tci, 4, 32*1024, 1, CPUID_CACHE_TYPE_INSTR, 1, 64) 176 //Cache 1st-level data cache: 8 KBytes, 2-way set associative, 32 byte line size 177 CPUID_FILL_CACHE(0x0a,tci, 2, 8*1024, 1, CPUID_CACHE_TYPE_DATA, 1, 32) 178 // Instruction TLB: 4 MByte pages, 4-way set associative, 4 entries 179 CPUID_FILL_TLB(0x0b, tci, 4, 4, 1, CPUID_CACHE_TYPE_INSTR, LARGE_PAGE_SIZE); 180 //Cache 1st-level data cache: 16 KBytes, 4-way set associative, 32 byte line size 181 CPUID_FILL_CACHE(0x0c,tci, 4, 16*1024, 1, CPUID_CACHE_TYPE_DATA, 1, 32) 182 //Cache 1st-level data cache: 16 KBytes, 4-way set associative, 64 byte line size 183 CPUID_FILL_CACHE(0x0d,tci, 4, 16*1024, 1, CPUID_CACHE_TYPE_DATA, 1, 64) 184 //Cache 1st-level data cache: 24 KBytes, 6-way set associative, 64 byte line size 185 CPUID_FILL_CACHE(0x0e,tci, 6, 24*1024, 1, CPUID_CACHE_TYPE_DATA, 1, 64) 186 //Cache 2nd-level cache: 128 KBytes, 2-way set associative, 64 byte line size 187 CPUID_FILL_CACHE(0x1d,tci, 2, 128*1024, 2, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 188 //Cache 2nd-level cache: 256 KBytes, 8-way set associative, 64 byte line size 189 CPUID_FILL_CACHE(0x21,tci, 2, 128*1024, 2, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 190 //Cache 3rd-level cache: 512 KBytes, 4-way set associative, 64 byte line size, 2 lines per sector 191 CPUID_FILL_CACHE(0x22,tci, 4, 512*1024, 3, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 192 //Cache 3rd-level cache: 1 MBytes, 8-way set associative, 64 byte line size, 2 lines per sector 193 CPUID_FILL_CACHE(0x23,tci, 8, 1*1024*1024, 3, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 194 //Cache 2nd-level cache: 1 MBytes, 16-way set associative, 64 byte line size 195 CPUID_FILL_CACHE(0x24,tci, 16, 1*1024*1024, 2, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 196 //Cache 3rd-level cache: 2 MBytes, 8-way set associative, 64 byte line size, 2 lines per sector 197 CPUID_FILL_CACHE(0x25,tci, 8, 2*1024*1024, 3, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 198 //Cache 3rd-level cache: 4 MBytes, 8-way set associative, 64 byte line size, 2 lines per sector 199 CPUID_FILL_CACHE(0x29,tci, 8, 4*1024*1024, 3, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 200 //Cache 1st-level data cache: 32 KBytes, 8-way set associative, 64 byte line size 201 CPUID_FILL_CACHE(0x2c,tci, 8, 32*1024, 1, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 202 //Cache 1st-level instruction cache: 32 KBytes, 8-way set associative, 64 byte line size 203 CPUID_FILL_CACHE(0x30,tci, 8, 32*1024, 1, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 204 //Cache No 2nd-level cache or, if processor contains a valid 2nd-level cache, no 3rd-level cache 205 case 40: 206 break; 207 //Cache 2nd-level cache: 128 KBytes, 4-way set associative, 32 byte line size 208 CPUID_FILL_CACHE(0x41,tci, 4, 128*1024, 2, CPUID_CACHE_TYPE_UNIFIED, 1, 32) 209 //Cache 2nd-level cache: 256 KBytes, 4-way set associative, 32 byte line size 210 CPUID_FILL_CACHE(0x42,tci, 4, 256*1024, 2, CPUID_CACHE_TYPE_UNIFIED, 1, 32) 211 //Cache 2nd-level cache: 512 KBytes, 4-way set associative, 32 byte line size 212 CPUID_FILL_CACHE(0x43,tci, 4, 512*1024, 2, CPUID_CACHE_TYPE_UNIFIED, 1, 32) 213 //Cache 2nd-level cache: 1 MByte, 4-way set associative, 32 byte line size 214 CPUID_FILL_CACHE(0x44,tci, 4, 1024*1024, 2, CPUID_CACHE_TYPE_UNIFIED, 1, 32) 215 //Cache 2nd-level cache: 2 MByte, 4-way set associative, 32 byte line size 216 CPUID_FILL_CACHE(0x45,tci, 4, 2*1024*1024, 2, CPUID_CACHE_TYPE_UNIFIED, 1, 32) 217 //Cache 3rd-level cache: 4 MByte, 4-way set associative, 64 byte line size 218 CPUID_FILL_CACHE(0x46,tci, 4, 4*1024*1024, 3, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 219 //Cache 3rd-level cache: 8 MByte, 8-way set associative, 64 byte line size 220 CPUID_FILL_CACHE(0x47,tci, 8, 8*1024*1024, 3, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 221 //Cache 2nd-level cache: 3MByte, 12-way set associative, 64 byte line size 222 CPUID_FILL_CACHE(0x48,tci, 12, 3*1024*1024, 2, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 223 //Cache 3rd-level cache: 4MB, 16-way set associative, 64-byte line size (Intel Xeon processor MP, Family 0FH, Model 06H); 2nd-level cache: 4 MByte, 16-way set associative, 64 byte line size 224 CPUID_FILL_CACHE(0x49,tci, 16, 4*1024*1024, 3, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 225 //Cache 3rd-level cache: 6MByte, 12-way set associative, 64 byte line size 226 CPUID_FILL_CACHE(0x4a,tci, 12, 6*1024*1024, 3, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 227 //Cache 3rd-level cache: 8MByte, 16-way set associative, 64 byte line size 228 CPUID_FILL_CACHE(0x4b,tci, 16, 8*1024*1024, 3, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 229 //Cache 3rd-level cache: 12MByte, 12-way set associative, 64 byte line size 230 CPUID_FILL_CACHE(0x4c,tci, 12, 12*1024*1024, 3, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 231 //Cache 3rd-level cache: 16MByte, 16-way set associative, 64 byte line size 232 CPUID_FILL_CACHE(0x4d,tci, 16, 16*1024*1024, 3, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 233 //Cache 2nd-level cache: 6MByte, 24-way set associative, 64 byte line size 234 CPUID_FILL_CACHE(0x4e,tci, 24, 24*1024*1024, 2, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 235 //TLB Instruction TLB: 4 KByte pages, 32 entries 236 CPUID_FILL_TLB(0x4f, tci, 0xff, 32, 1, CPUID_CACHE_TYPE_INSTR, BASE_PAGE_SIZE); 237 //TLB Instruction TLB: 4 KByte and 2-MByte or 4-MByte pages, 64 entries 238 CPUID_FILL_TLB(0x50, tci, 0xff, 64, 1, CPUID_CACHE_TYPE_INSTR, LARGE_PAGE_SIZE); 239 //TLB Instruction TLB: 4 KByte and 2-MByte or 4-MByte pages, 128 entries 240 CPUID_FILL_TLB(0x51, tci, 0xff, 128, 1, CPUID_CACHE_TYPE_INSTR, LARGE_PAGE_SIZE); 241 //TLB Instruction TLB: 4 KByte and 2-MByte or 4-MByte pages, 256 entries 242 CPUID_FILL_TLB(0x52, tci, 0xff, 256, 1, CPUID_CACHE_TYPE_INSTR, BASE_PAGE_SIZE); 243 //TLB Instruction TLB: 2-MByte or 4-MByte pages, fully associative, 7 entries 244 CPUID_FILL_TLB(0x55, tci, 0xff, 7, 1, CPUID_CACHE_TYPE_INSTR, LARGE_PAGE_SIZE); 245 //TLB Data TLB0: 4 MByte pages, 4-way set associative, 16 entries 246 CPUID_FILL_TLB(0x56, tci, 4, 16, 1, CPUID_CACHE_TYPE_DATA, LARGE_PAGE_SIZE); 247 //TLB Data TLB0: 4 KByte pages, 4-way associative, 16 entries 248 CPUID_FILL_TLB(0x57, tci, 4, 16, 1, CPUID_CACHE_TYPE_DATA, BASE_PAGE_SIZE); 249 //TLB Data TLB0: 4 KByte pages, fully associative, 16 entries 250 CPUID_FILL_TLB(0x59, tci, 0xff, 16, 1, CPUID_CACHE_TYPE_DATA, BASE_PAGE_SIZE); 251 //TLB Data TLB0: 2-MByte or 4 MByte pages, 4-way set associative, 32 entries 252 CPUID_FILL_TLB(0x5a, tci, 4, 32, 1, CPUID_CACHE_TYPE_DATA, LARGE_PAGE_SIZE); 253 //TLB Data TLB: 4 KByte and 4 MByte pages, 64 entries 254 CPUID_FILL_TLB(0x5b, tci, 0xff, 64, 1, CPUID_CACHE_TYPE_DATA, BASE_PAGE_SIZE); 255 //TLB Data TLB: 4 KByte and 4 MByte pages,128 entries 256 CPUID_FILL_TLB(0x5c, tci, 0xff, 128, 1, CPUID_CACHE_TYPE_DATA, BASE_PAGE_SIZE); 257 //TLB Data TLB: 4 KByte and 4 MByte pages,256 entries 258 CPUID_FILL_TLB(0x5d, tci, 0xff, 256, 1, CPUID_CACHE_TYPE_DATA, BASE_PAGE_SIZE); 259 case 0x60: 260 //Cache 1st-level data cache: 16 KByte, 8-way set associative, 64 byte line size 261 break; 262 //TLB Instruction TLB: 4 KByte pages, fully associative, 48 entries 263 CPUID_FILL_TLB(0x61, tci, 0xff, 48, 1, CPUID_CACHE_TYPE_INSTR, BASE_PAGE_SIZE); 264 //TLB Data TLB: 1 GByte pages, 4-way set associative, 4 entries 265 CPUID_FILL_TLB(0x63, tci, 4, 4, 1, CPUID_CACHE_TYPE_INSTR, HUGE_PAGE_SIZE); 266 //Cache 1st-level data cache: 8 KByte, 4-way set associative, 64 byte line size 267 CPUID_FILL_CACHE(0x66,tci, 4, 8*1024, 1, CPUID_CACHE_TYPE_DATA, 1, 64) 268 //Cache 1st-level data cache: 16 KByte, 4-way set associative, 64 byte line size 269 CPUID_FILL_CACHE(0x67,tci, 4, 16*1024, 1, CPUID_CACHE_TYPE_DATA, 1, 64) 270 //Cache 1st-level data cache: 32 KByte, 4-way set associative, 64 byte line size 271 CPUID_FILL_CACHE(0x68,tci, 4, 32*1024, 1, CPUID_CACHE_TYPE_DATA, 1, 64) 272 case 0x70: 273 //Cache Trace cache: 12 K-��op, 8-way set associative 274 case 0x71: 275 //Cache Trace cache: 16 K-��op, 8-way set associative 276 case 0x72: 277 //Cache Trace cache: 32 K-��op, 8-way set associative 278 break; 279 //TLB Instruction TLB: 2M/4M pages, fully associative, 8 entries 280 CPUID_FILL_TLB(0x76, tci, 0xff, 8, 1, CPUID_CACHE_TYPE_INSTR, LARGE_PAGE_SIZE); 281 //Cache 2nd-level cache: 1 MByte, 4-way set associative, 64byte line size 282 CPUID_FILL_CACHE(0x78,tci, 4, 1*1024*1024, 2, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 283 //Cache 2nd-level cache: 128 KByte, 8-way set associative, 64 byte line size, 2 lines per sector 284 CPUID_FILL_CACHE(0x79,tci, 8, 128*1024, 2, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 285 //Cache 2nd-level cache: 256 KByte, 8-way set associative, 64 byte line size, 2 lines per sector 286 CPUID_FILL_CACHE(0x7a,tci, 8, 256*1024, 2, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 287 //Cache 2nd-level cache: 512 KByte, 8-way set associative, 64 byte line size, 2 lines per sector 288 CPUID_FILL_CACHE(0x7b,tci, 8, 512*1024, 2, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 289 //Cache 2nd-level cache: 1 MByte, 8-way set associative, 64 byte line size, 2 lines per sector 290 CPUID_FILL_CACHE(0x7c,tci, 8, 1024*1024, 2, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 291 //Cache 2nd-level cache: 2 MByte, 8-way set associative, 64byte line size 292 CPUID_FILL_CACHE(0x7d,tci, 8, 2*1024*1024, 2, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 293 //Cache 2nd-level cache: 512 KByte, 2-way set associative, 64-byte line size 294 CPUID_FILL_CACHE(0x7f,tci, 2, 512*1024, 2, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 295 //Cache 2nd-level cache: 512 KByte, 8-way set associative, 64-byte line size 296 CPUID_FILL_CACHE(0x80,tci, 8, 512*1024, 2, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 297 //Cache 2nd-level cache: 256 KByte, 8-way set associative, 32 byte line size 298 CPUID_FILL_CACHE(0x82,tci, 8, 256*1024, 2, CPUID_CACHE_TYPE_UNIFIED, 1, 32) 299 //Cache 2nd-level cache: 512 KByte, 8-way set associative, 32 byte line size 300 CPUID_FILL_CACHE(0x83,tci, 8, 512*1024, 2, CPUID_CACHE_TYPE_UNIFIED, 1, 32) 301 //Cache 2nd-level cache: 1 MByte, 8-way set associative, 32 byte line size 302 CPUID_FILL_CACHE(0x84,tci, 8, 1024*1024, 2, CPUID_CACHE_TYPE_UNIFIED, 1, 32) 303 //Cache 2nd-level cache: 2 MByte, 8-way set associative, 32 byte line size 304 CPUID_FILL_CACHE(0x85,tci, 8, 2*1024*1024, 2, CPUID_CACHE_TYPE_UNIFIED, 1, 32) 305 //Cache 2nd-level cache: 512 KByte, 4-way set associative, 64 byte line size 306 CPUID_FILL_CACHE(0x86,tci, 4, 512*1024, 2, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 307 //Cache 2nd-level cache: 1 MByte, 8-way set associative, 64 byte line size 308 CPUID_FILL_CACHE(0x87,tci, 8, 1*1024*1024, 2, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 309 //DTLB DTLB: 4k pages, fully associative, 32 entries 310 CPUID_FILL_TLB(0xa0, tci, 0xff, 32, 1, CPUID_CACHE_TYPE_DATA, BASE_PAGE_SIZE); 311 //TLB Instruction TLB: 4 KByte pages, 4-way set associative, 128 entries 312 CPUID_FILL_TLB(0xb0, tci, 0x4, 128, 1, CPUID_CACHE_TYPE_INSTR, BASE_PAGE_SIZE); 313 //TLB Instruction TLB: 2M pages, 4-way, 8 entries or 4M pages, 4-way, 4 entries 314 CPUID_FILL_TLB(0xb1, tci, 0x4, 8, 1, CPUID_CACHE_TYPE_INSTR, LARGE_PAGE_SIZE); 315 //TLB Instruction TLB: 4KByte pages, 4-way set associative, 64 entries 316 CPUID_FILL_TLB(0xb2, tci, 0x4, 64, 1, CPUID_CACHE_TYPE_INSTR, BASE_PAGE_SIZE); 317 //TLB Data TLB: 4 KByte pages, 4-way set associative, 128 entries 318 CPUID_FILL_TLB(0xb3, tci, 0x4, 128, 1, CPUID_CACHE_TYPE_DATA, BASE_PAGE_SIZE); 319 //TLB Data TLB1: 4 KByte pages, 4-way associative, 256 entries 320 CPUID_FILL_TLB(0xb4, tci, 0x4, 256, 1, CPUID_CACHE_TYPE_DATA, BASE_PAGE_SIZE); 321 //TLB Instruction TLB: 4KByte pages, 8-way set associative, 64 entries 322 CPUID_FILL_TLB(0xb5, tci, 0x8, 64, 1, CPUID_CACHE_TYPE_INSTR, BASE_PAGE_SIZE); 323 //TLB Instruction TLB: 4KByte pages, 8-way set associative, 128 entries 324 CPUID_FILL_TLB(0xb6, tci, 0x8, 128, 1, CPUID_CACHE_TYPE_INSTR, BASE_PAGE_SIZE); 325 //TLB Data TLB1: 4 KByte pages, 4-way associative, 64 entries 326 CPUID_FILL_TLB(0xba, tci, 0x4, 64, 1, CPUID_CACHE_TYPE_DATA, BASE_PAGE_SIZE); 327 //TLB Data TLB: 4 KByte and 4 MByte pages, 4-way associative, 8 entries 328 CPUID_FILL_TLB(0xc0, tci, 0x4, 8, 1, CPUID_CACHE_TYPE_DATA, LARGE_PAGE_SIZE + BASE_PAGE_SIZE); 329 //STLB Shared 2nd-Level TLB: 4 KByte/2MByte pages, 8-way associative, 1024 entries 330 CPUID_FILL_TLB(0xc1, tci, 0x8, 1024, 2, CPUID_CACHE_TYPE_UNIFIED, LARGE_PAGE_SIZE + BASE_PAGE_SIZE); 331 //DTLB DTLB: 4 KByte/2 MByte pages, 4-way associative, 16 entries 332 CPUID_FILL_TLB(0xc2, tci, 0x4, 16, 1, CPUID_CACHE_TYPE_DATA, LARGE_PAGE_SIZE + BASE_PAGE_SIZE); 333 //STLB Shared 2nd-Level TLB: 4 KByte /2 MByte pages, 6-way associative, 1536 entries. Also 1GBbyte pages, 4-way, 16 entries. 334 CPUID_FILL_TLB(0xc3, tci, 0x6, 1536, 2, CPUID_CACHE_TYPE_UNIFIED, BASE_PAGE_SIZE); 335 //STLB Shared 2nd-Level TLB: 4 KByte pages, 4-way associative, 512 entries 336 CPUID_FILL_TLB(0xca, tci, 0x4, 512, 2, CPUID_CACHE_TYPE_UNIFIED, BASE_PAGE_SIZE); 337 //Cache 3rd-level cache: 512 KByte, 4-way set associative, 64 byte line size 338 CPUID_FILL_CACHE(0xd0,tci, 4, 512*1024, 3, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 339 //Cache 3rd-level cache: 1 MByte, 4-way set associative, 64 byte line size 340 CPUID_FILL_CACHE(0xd1,tci, 4, 1*1024*1024, 3, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 341 //Cache 3rd-level cache: 2 MByte, 4-way set associative, 64 byte line size 342 CPUID_FILL_CACHE(0xd2,tci, 4, 2*1024*1024, 3, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 343 //Cache 3rd-level cache: 1 MByte, 8-way set associative, 64 byte line size 344 CPUID_FILL_CACHE(0xd6,tci, 8, 1*1024*1024, 3, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 345 //Cache 3rd-level cache: 2 MByte, 8-way set associative, 64 byte line size 346 CPUID_FILL_CACHE(0xd7,tci, 8, 2*1024*1024, 3, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 347 //Cache 3rd-level cache: 4 MByte, 8-way set associative, 64 byte line size 348 CPUID_FILL_CACHE(0xd8,tci, 8, 4*1024*1024, 3, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 349 //Cache 3rd-level cache: 1.5 MByte, 12-way set associative, 64 byte line size 350 CPUID_FILL_CACHE(0xdc,tci, 12, 512*1024 + 1024*1024, 3, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 351 //Cache 3rd-level cache: 3 MByte, 12-way set associative, 64 byte line size 352 CPUID_FILL_CACHE(0xdd,tci, 12, 3*1024*1024, 3, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 353 //Cache 3rd-level cache: 6 MByte, 12-way set associative, 64 byte line size 354 CPUID_FILL_CACHE(0xde,tci, 12, 6*1024*1024, 3, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 355 //Cache 3rd-level cache: 2 MByte, 16-way set associative, 64 byte line size 356 CPUID_FILL_CACHE(0xe2,tci, 16, 2*1024*1024, 3, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 357 //Cache 3rd-level cache: 4 MByte, 16-way set associative, 64 byte line size 358 CPUID_FILL_CACHE(0xe3,tci, 16, 4*1024*1024, 3, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 359 //Cache 3rd-level cache: 8 MByte, 16-way set associative, 64 byte line size 360 CPUID_FILL_CACHE(0xe4,tci, 16, 8*1024*1024, 3, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 361 //Cache 3rd-level cache: 12MByte, 24-way set associative, 64 byte line size 362 CPUID_FILL_CACHE(0xea,tci, 24, 12*1024*1024, 3, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 363 //Cache 3rd-level cache: 18MByte, 24-way set associative, 64 byte line size 364 CPUID_FILL_CACHE(0xeb,tci, 24, 18*1024*1024, 3, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 365 //Cache 3rd-level cache: 24MByte, 24-way set associative, 64 byte line size 366 CPUID_FILL_CACHE(0xec,tci, 24, 24*1024*1024, 3, CPUID_CACHE_TYPE_UNIFIED, 1, 64) 367 case 0xF0: 368 //Prefetch: 64byte prefetching 369 case 0xF1: 370 //Prefetching 128-Byte prefetching 371 case 0xFF: 372 //General CPUID leaf 2 does not report cache descriptor information, use CPUID leaf 4 to query cache parameters 373 default: 374 break; 375 } 376 377 return CPUID_ERR_INVALID_INDEX; 378} 379 380 381static errval_t cache_info_alternate(struct cpuid_cacheinfo *ci, uint32_t idx) 382{ 383 if (cpuid_g_max_input_basic < 4) { 384 return CPUID_ERR_UNSUPPORTED_FUNCTION; 385 } 386 387 struct cpuid_regs reg = CPUID_REGS_INITIAL(4, idx); 388 cpuid_exec(®); 389 390 cpuid_intel_cache_info_basic_t ci_a = (cpuid_intel_cache_info_basic_t) ®.eax; 391 cpuid_intel_cache_info_ebx_t ci_b = (cpuid_intel_cache_info_ebx_t) ®.ebx; 392 393 ci->level = cpuid_intel_cache_info_basic_level_extract(ci_a); 394 395 switch (cpuid_intel_cache_info_basic_ctype_extract(ci_a)) { 396 case cpuid_intel_cache_type_data : 397 /* data cache */ 398 ci->type = CPUID_CACHE_TYPE_DATA; 399 break; 400 case cpuid_intel_cache_type_instr : 401 /* instruction cache */ 402 ci->type = CPUID_CACHE_TYPE_INSTR; 403 break; 404 case cpuid_intel_cache_type_unified : 405 ci->type = CPUID_CACHE_TYPE_UNIFIED; 406 /* unified cache */ 407 break; 408 default: 409 /* no more cache */ 410 ci->type = CPUID_CACHE_TYPE_INVALID; 411 return CPUID_ERR_INVALID_INDEX; 412 break; 413 } 414 415 ci->name = cpuid_cache_names[ci->level][ci->type]; 416 ci->linesize = cpuid_intel_cache_info_ebx_coherency_extract(ci_b)+1; 417 418 /* the the number of sets */ 419 ci->sets = reg.ecx + 1; 420 421 if (cpuid_intel_cache_info_basic_fullyassoc_extract(ci_a)) { 422 ci->size = (size_t)ci->linesize * ci->sets; 423 ci->associativity = 0xff; 424 } else { 425 ci->associativity = cpuid_intel_cache_info_ebx_assoc_extract(ci_b)+1; 426 ci->size = (size_t)ci->linesize * ci->sets * ci->associativity; 427 } 428 429 ci->shared = cpuid_intel_cache_info_basic_maxlog_extract(ci_a) +1; 430 431 cpuid_intel_cache_info_edx_t ci_d = (cpuid_intel_cache_info_edx_t) ®.edx; 432 ci->inclusive = cpuid_intel_cache_info_edx_inclusive_extract(ci_d); 433 434 return SYS_ERR_OK; 435} 436 437 438static errval_t cache_info(struct cpuid_cacheinfo *cinfo, uint32_t idx) 439{ 440 if (cpuid_g_max_input_basic < 2) { 441 return CPUID_ERR_UNSUPPORTED_FUNCTION; 442 } 443 444 if (cache_info_in_leaf_4) { 445 return cache_info_alternate(cinfo, idx); 446 } 447 448 struct cpuid_regs reg = CPUID_REGS_INITIAL(2, 0); 449 cpuid_exec(®); 450 451 cpuid_intel_cache_info_t ci = (cpuid_intel_cache_info_t)®.eax; 452 assert(cpuid_intel_cache_info_d0_extract(ci) == 0x01); 453 454 uint32_t *values = ®.eax; 455 uint8_t *cval; 456 uint32_t currentidx = 0; 457 for (int i = 0; i < 4; ++i) { 458 ci = (cpuid_intel_cache_info_t)(values + i); 459 460 /* check for validity */ 461 if (cpuid_intel_cache_info_v0_extract(ci)) { 462 continue; 463 } 464 465 cval = (uint8_t *)ci; 466 for (int j = (i == 0); j < 4; ++j) { 467 struct tlb_cache_info tci; 468 if (cval[j] == 0x00) { 469 continue; 470 } else if (cval[j] == 0xff) { 471 /* 472 * a value of 0xff indicates that the cache values are reported 473 * in leaf 4 of cpuid 474 */ 475 cache_info_in_leaf_4 = 0x1; 476 return cache_info_alternate(cinfo, idx); 477 } 478 479 if (err_is_ok(cache_info_lookup(&tci, cval[j]))) { 480 if (!tci.is_tlb) { 481 if (currentidx == idx) { 482 *cinfo = tci.ci; 483 return SYS_ERR_OK; 484 } 485 currentidx++; 486 } 487 } 488 489 } 490 } 491 492 return CPUID_ERR_INVALID_INDEX; 493 494} 495 496static uint16_t cache_line_size(void) 497{ 498 if (cpuid_g_max_input_basic < 1) { 499 return CPUID_ERR_UNSUPPORTED_FUNCTION; 500 } 501 502 struct cpuid_regs reg = CPUID_REGS_INITIAL(1, 0); 503 cpuid_exec(®); 504 505 cpuid_intel_miscinfo_t mi = (cpuid_intel_miscinfo_t)®.ebx; 506 507 return cpuid_intel_miscinfo_cflush_sz_extract(mi) * 8; 508} 509 510static errval_t tlb_info(struct cpuid_tlbinfo *ti, uint32_t idx) 511{ 512 if (cpuid_g_max_input_basic < 2) { 513 return CPUID_ERR_UNSUPPORTED_FUNCTION; 514 } 515 516 struct cpuid_regs reg = CPUID_REGS_INITIAL(2, 0); 517 cpuid_exec(®); 518 519 cpuid_intel_cache_info_t ci = (cpuid_intel_cache_info_t)®.eax; 520 assert(cpuid_intel_cache_info_d0_extract(ci) == 0x01); 521 522 uint32_t *values = ®.eax; 523 uint8_t *cval; 524 uint32_t currentidx = 0; 525 for (int i = 0; i < 4; ++i) { 526 ci = (cpuid_intel_cache_info_t)(values + i); 527 528 /* check for validity */ 529 if (cpuid_intel_cache_info_v0_extract(ci)) { 530 continue; 531 } 532 533 cval = (uint8_t *)ci; 534 for (int j = (i == 0); j < 4; ++j) { 535 struct tlb_cache_info tci; 536 if (cval[j] == 0x00) { 537 continue; 538 } 539 if (err_is_ok(cache_info_lookup(&tci, cval[j]))) { 540 if (tci.is_tlb) { 541 if (currentidx == idx) { 542 *ti = tci.ti; 543 return SYS_ERR_OK; 544 } 545 currentidx++; 546 } 547 } 548 549 } 550 } 551 552 return CPUID_ERR_INVALID_INDEX; 553 554} 555 556/* 557 * =============================================================================== 558 * thread and topology information 559 * =============================================================================== 560 */ 561 562static errval_t thread_info(struct cpuid_threadinfo *ti) 563{ 564 if (cpuid_g_max_input_basic < 4) { 565 return CPUID_ERR_UNSUPPORTED_FUNCTION; 566 } 567 568 struct cpuid_regs reg = CPUID_REGS_INITIAL(0x1, 0); 569 570 cpuid_exec(®); 571 572 if (!((reg.edx >> 28) & 0x1)) { 573 /* TODO: the cpu supports no hyperthreading */ 574 ti->hyperthread = 0; 575 USER_PANIC("NYI"); 576 return SYS_ERR_OK; 577 } 578 579 cpuid_intel_miscinfo_t f = (cpuid_intel_miscinfo_t)®.ebx; 580 581 coreid_t logical_cores = cpuid_intel_miscinfo_max_log_proc_extract(f); 582 coreid_t apic_id = cpuid_intel_miscinfo_init_apicid_extract(f); 583 584 reg.eax = 0x4; 585 reg.ecx = 0; 586 cpuid_exec(®); 587 588 cpuid_intel_cache_info_basic_t ci = (cpuid_intel_cache_info_basic_t)®.eax; 589 coreid_t cores_per_package = cpuid_intel_cache_info_basic_maxphys_extract(ci); 590 coreid_t ht = logical_cores / cores_per_package; 591 592 uint8_t ht_shift = cpuid_bits_needed(ht - 1); 593 uint8_t ht_mask = (1 << ht_shift) - 1; 594 uint8_t core_shift = cpuid_bits_needed(cores_per_package - 1); 595 uint8_t core_mask = (1 << core_shift) - 1; 596 597 ti->core = (apic_id >> (ht_shift)) & core_mask; 598 ti->package = apic_id >> (ht_shift + core_shift); 599 ti->hyperthread = apic_id & ht_mask; 600 601 return SYS_ERR_OK; 602} 603 604static errval_t topology_info(struct cpuid_topologyinfo *topo, uint8_t idx) 605{ 606 struct cpuid_regs reg = CPUID_REGS_INITIAL(0xb, idx); 607 cpuid_exec(®); 608 609 printf("getting the topology information %u\n", idx); 610 611 cpuid_intel_topology_ecx_t ta = (cpuid_intel_topology_eax_t)®.eax; 612 cpuid_intel_topology_ebx_t tb = (cpuid_intel_topology_ebx_t)®.ebx; 613 614 printf("getting the topology information %u, %u\n", idx, cpuid_intel_topology_eax_x2apic_shift_extract(ta)); 615 616 cpuid_intel_topology_ecx_t tc = (cpuid_intel_topology_ecx_t)®.ecx; 617 switch (cpuid_intel_topology_ecx_level_type_extract(tc)) { 618 case cpuid_intel_topology_level_smt: 619 printf("found smt at level %u\n", idx); 620 break; 621 case cpuid_intel_topology_level_core: 622 printf("found core at level %u\n", idx); 623 break; 624 case cpuid_intel_topology_level_invalid: 625 printf("level invalid %u\n", idx); 626 return CPUID_ERR_INVALID_INDEX; 627 break; 628 default: 629 printf("level u %u\n", idx); 630 return CPUID_ERR_INVALID_INDEX; 631 break; 632 } 633 634 635 printf("Level numer=%u, logical proc=%u\n", cpuid_intel_topology_ecx_level_number_extract(tc), cpuid_intel_topology_ebx_logical_proc_extract(tb)); 636 637 638 topo->nextshift = cpuid_intel_topology_eax_x2apic_shift_extract(ta); 639 topo->x2apic = reg.edx; 640 641 return SYS_ERR_OK; 642} 643 644static errval_t feature_info(struct cpuid_featureinfo *fi) 645{ 646 if (cpuid_g_max_input_basic < 0x1) { 647 return CPUID_ERR_UNSUPPORTED_FUNCTION; 648 } 649 650 struct cpuid_regs reg = CPUID_REGS_INITIAL(0x1, 0); 651 cpuid_exec(®); 652 653 cpuid_intel_features_t ft = (cpuid_intel_features_t)®.ecx; 654 /* CPU features */ 655 656 fi->htt = cpuid_intel_features_htt_extract(ft); 657 fi->apic = cpuid_intel_features_apic_extract(ft); 658 fi->x2apic = cpuid_intel_features_x2apic_extract(ft); 659 fi->tsc = cpuid_intel_features_tsc_extract(ft); 660 fi->dca = cpuid_intel_features_dca_extract(ft); 661 662 /* instructions */ 663 fi->monitor = cpuid_intel_features_monitor_extract(ft); 664 fi->cmov = cpuid_intel_features_cmov_extract(ft); 665 666 /* virtual memory */ 667 fi->pse36 = cpuid_intel_features_pse36_extract(ft); 668 fi->pse = cpuid_intel_features_pse_extract(ft); 669 fi->pae = cpuid_intel_features_pae_extract(ft); 670 fi->pat = cpuid_intel_features_pat_extract(ft); 671 fi->pge = cpuid_intel_features_pge_extract(ft); 672 fi->mtrr = cpuid_intel_features_mtrr_extract(ft); 673 674 fi->page2M = 1; 675 676 677 /* cache control */ 678 fi->clsh = cpuid_intel_features_clfsh_extract(ft); 679 fi->cnxt_id = cpuid_intel_features_cntx_id_extract(ft); 680 681 /* virtualization technology */ 682 fi->vmx = cpuid_intel_features_vmx_extract(ft); 683 fi->vme = cpuid_intel_features_vme_extract(ft); 684 fi->svm = 0; 685 686 /* vector instructions */ 687 fi->mmx = cpuid_intel_features_mmx_extract(ft); 688 fi->sse = cpuid_intel_features_sse_extract(ft); 689 fi->sse2 = cpuid_intel_features_sse2_extract(ft); 690 fi->sse3 = cpuid_intel_features_sse3_extract(ft); 691 fi->sse41 = cpuid_intel_features_sse4_1_extract(ft); 692 fi->sse42 = cpuid_intel_features_sse4_2_extract(ft); 693 fi->avx = cpuid_intel_features_avx_extract(ft); 694 695 if (CPUID_EXTENDED_INPUT_MASK(cpuid_g_max_input_extended) < 0x1) { 696 return SYS_ERR_OK; 697 } 698 699 reg.eax = 0x80000001; 700 reg.ecx = 0; 701 cpuid_exec(®); 702 703 cpuid_intel_features_ext_edx_t ft2 = (cpuid_intel_features_ext_edx_t)®.edx; 704 fi->nx = cpuid_intel_features_ext_edx_nx_extract(ft2); 705 fi->page1G = cpuid_intel_features_ext_edx_page1G_extract(ft2);; 706 fi->lm = cpuid_intel_features_ext_edx_lm_extract(ft2); 707 708 return SYS_ERR_OK; 709} 710 711static errval_t address_space_info(struct cpuid_adressspaceinfo *ai) 712{ 713 if (CPUID_EXTENDED_INPUT_MASK(cpuid_g_max_input_extended) < 0x8) { 714 return CPUID_ERR_UNSUPPORTED_FUNCTION; 715 } 716 717 struct cpuid_regs reg = CPUID_REGS_INITIAL(0x80000008, 0); 718 cpuid_exec(®); 719 720 cpuid_intel_addrspace_t as = (cpuid_intel_addrspace_t)®.eax; 721 722 ai->physical = cpuid_intel_addrspace_physical_extract(as); 723 ai->virtual = cpuid_intel_addrspace_linear_extract(as); 724 /* this information is not provided by intel*/ 725 ai->guest_physical = 0; 726 727 return SYS_ERR_OK; 728} 729 730/* 731 * =============================================================================== 732 * backend initialization 733 * =============================================================================== 734 */ 735 736/** 737 * \brief fills the vendor specific handler functions 738 * 739 * \param fn_tab function pointer table to be filled 740 */ 741void cpuid_intel_set_handlers(struct cpuid_functions *fn_tab) 742{ 743 fn_tab->proc_name = proc_name; 744 fn_tab->proc_family = proc_family; 745 fn_tab->proc_max_input_basic = proc_max_input_basic; 746 fn_tab->proc_max_input_extended = proc_max_input_extended; 747 fn_tab->frequency_info = frequency_info; 748 749 fn_tab->cache_info = cache_info; 750 fn_tab->cache_line_size = cache_line_size; 751 752 fn_tab->tlb_info = tlb_info; 753 754 fn_tab->thread_info = thread_info; 755 fn_tab->topology_info = topology_info; 756 757 fn_tab->feature_info = feature_info; 758 759 fn_tab->address_space_info = address_space_info; 760} 761