github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/cpvmm/vmm/arch/mtrrs_abstraction.c (about) 1 /* 2 * Copyright (c) 2013 Intel Corporation 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * Unless required by applicable law or agreed to in writing, software 9 * distributed under the License is distributed on an "AS IS" BASIS, 10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 * See the License for the specific language governing permissions and 12 * limitations under the License. 13 */ 14 15 #include <mtrrs_abstraction.h> 16 #include <hw_utils.h> 17 #include <common_libc.h> 18 #include "vmm_dbg.h" 19 #include "address.h" 20 #include "file_codes.h" 21 #define VMM_DEADLOOP() VMM_DEADLOOP_LOG(MTRRS_ABSTRACTION_C) 22 #define VMM_ASSERT(__condition) VMM_ASSERT_LOG(MTRRS_ABSTRACTION_C, __condition) 23 #ifdef JLMDEBUG 24 #include "jlmdebug.h" 25 #endif 26 27 #pragma warning( disable : 4214 ) 28 29 #define MTRRS_ABS_NUM_OF_SUB_RANGES 8 30 #define MTRRS_ABS_NUM_OF_FIXED_RANGE_MTRRS 11 31 #define MTRRS_ABS_NUM_OF_VAR_RANGE_MTRRS 10 32 #define MTRRS_ABS_HIGH_ADDR_SHIFT 32 33 #define MTRRS_ABS_ADDR_BASE_SHIFT 12 34 35 36 typedef union IA32_MTRRCAP_REG_U { 37 struct { 38 UINT32 39 vcnt :8, 40 fix :1, 41 res0 :1, 42 wc :1, 43 res1 :21; 44 UINT32 45 res2 :32; 46 } bits; 47 UINT64 value; 48 } IA32_MTRRCAP_REG; 49 50 typedef union IA32_MTRR_DEF_TYPE_REG_U { 51 struct { 52 UINT32 53 type : 8, 54 res0 : 2, 55 fixed_range_enable : 1, 56 enable : 1, 57 res1 : 20; 58 UINT32 59 res2 : 32; 60 } bits; 61 UINT64 value; 62 } IA32_MTRR_DEF_TYPE_REG; 63 64 typedef union IA32_FIXED_RANGE_MTRR_U { 65 UINT8 type[MTRRS_ABS_NUM_OF_SUB_RANGES]; 66 UINT64 value; 67 } IA32_FIXED_RANGE_MTRR; 68 69 typedef union IA32_MTRR_PHYSBASE_REG_U { 70 struct { 71 UINT32 72 type : 8, 73 res0 : 4, 74 phys_base_low : 20; 75 UINT32 76 phys_base_high : 20, 77 res1 : 12; 78 } bits; 79 UINT64 value; 80 } IA32_MTRR_PHYSBASE_REG; 81 82 typedef union IA32_MTRR_PHYSMASK_REG_U { 83 struct { 84 UINT32 85 res0 : 11, 86 valid : 1, 87 phys_mask_low : 20; 88 UINT32 89 phys_mask_high : 20, 90 res1 : 12; 91 } bits; 92 UINT64 value; 93 } IA32_MTRR_PHYSMASK_REG; 94 95 typedef struct MTRRS_ABS_FIXED_RANGE_DESC_S { 96 UINT32 start_addr; 97 UINT32 end_addr; 98 } MTRRS_ABS_FIXED_RANGE_DESC; 99 100 101 typedef struct MTRRS_ABSTRACTION_CACHED_INFO_S { 102 IA32_MTRRCAP_REG ia32_mtrrcap_reg; 103 IA32_MTRR_DEF_TYPE_REG ia32_mtrr_def_type; 104 IA32_FIXED_RANGE_MTRR ia32_mtrr_fix64k_00000; 105 IA32_FIXED_RANGE_MTRR ia32_mtrr_fix16k_80000; 106 IA32_FIXED_RANGE_MTRR ia32_mtrr_fix16k_A0000; 107 IA32_FIXED_RANGE_MTRR ia32_mtrr_fix4k_C0000; 108 IA32_FIXED_RANGE_MTRR ia32_mtrr_fix4k_C8000; 109 IA32_FIXED_RANGE_MTRR ia32_mtrr_fix4k_D0000; 110 IA32_FIXED_RANGE_MTRR ia32_mtrr_fix4k_D8000; 111 IA32_FIXED_RANGE_MTRR ia32_mtrr_fix4k_E0000; 112 IA32_FIXED_RANGE_MTRR ia32_mtrr_fix4k_E8000; 113 IA32_FIXED_RANGE_MTRR ia32_mtrr_fix4k_F0000; 114 IA32_FIXED_RANGE_MTRR ia32_mtrr_fix4k_F8000; 115 IA32_FIXED_RANGE_MTRR ia32_mtrr_fix[MTRRS_ABS_NUM_OF_FIXED_RANGE_MTRRS]; 116 MTRRS_ABS_FIXED_RANGE_DESC ia32_mtrr_fix_range[MTRRS_ABS_NUM_OF_FIXED_RANGE_MTRRS]; 117 IA32_MTRR_PHYSBASE_REG ia32_mtrr_var_phys_base[MTRRS_ABS_NUM_OF_VAR_RANGE_MTRRS]; 118 IA32_MTRR_PHYSMASK_REG ia32_mtrr_var_phys_mask[MTRRS_ABS_NUM_OF_VAR_RANGE_MTRRS]; 119 BOOLEAN is_initialized; 120 UINT32 padding; // not used 121 } MTRRS_ABSTRACTION_CACHED_INFO; 122 123 static MTRRS_ABSTRACTION_CACHED_INFO mtrrs_cached_info; 124 UINT64 remsize = 0; 125 UINT64 MTRR_MSBs=0; 126 127 UINT32 mtrrs_abstraction_get_num_of_variable_range_regs(void) { 128 UINT64 num = mtrrs_cached_info.ia32_mtrrcap_reg.bits.vcnt; 129 return (UINT32)num; 130 } 131 132 INLINE BOOLEAN mtrrs_abstraction_are_fixed_regs_supported(void) { 133 return (mtrrs_cached_info.ia32_mtrrcap_reg.bits.fix != 0); 134 } 135 136 INLINE BOOLEAN mtrrs_abstraction_are_mtrrs_enabled(void) { 137 return (mtrrs_cached_info.ia32_mtrr_def_type.bits.enable != 0); 138 } 139 140 INLINE BOOLEAN mtrrs_abstraction_are_fixed_ranged_mtrrs_enabled(void) { 141 return (mtrrs_cached_info.ia32_mtrr_def_type.bits.fixed_range_enable != 0); 142 } 143 144 INLINE VMM_PHYS_MEM_TYPE mtrrs_abstraction_get_default_memory_type(void) { 145 UINT64 type = mtrrs_cached_info.ia32_mtrr_def_type.bits.type; 146 return (VMM_PHYS_MEM_TYPE)type; 147 } 148 149 INLINE BOOLEAN mtrrs_abstraction_is_var_reg_valid(UINT32 index) { 150 return (mtrrs_cached_info.ia32_mtrr_var_phys_mask[index].bits.valid != 0); 151 } 152 153 INLINE UINT64 mtrrs_abstraction_get_address_from_reg(UINT32 reg_index) { 154 UINT32 addr_base_low = mtrrs_cached_info.ia32_mtrr_var_phys_base[reg_index].bits.phys_base_low << MTRRS_ABS_ADDR_BASE_SHIFT; 155 UINT32 addr_base_high = mtrrs_cached_info.ia32_mtrr_var_phys_base[reg_index].bits.phys_base_high; 156 UINT64 addr = ((UINT64)addr_base_high << MTRRS_ABS_HIGH_ADDR_SHIFT) | addr_base_low; 157 158 return addr; 159 } 160 161 INLINE UINT64 mtrrs_abstraction_get_mask_from_reg(UINT32 reg_index) { 162 UINT32 addr_mask_low = mtrrs_cached_info.ia32_mtrr_var_phys_mask[reg_index].bits.phys_mask_low << MTRRS_ABS_ADDR_BASE_SHIFT; 163 UINT32 addr_mask_high = mtrrs_cached_info.ia32_mtrr_var_phys_mask[reg_index].bits.phys_mask_high; 164 UINT64 addr_mask = ((UINT64)addr_mask_high << MTRRS_ABS_HIGH_ADDR_SHIFT) | addr_mask_low; 165 166 return addr_mask; 167 } 168 169 INLINE BOOLEAN mtrrs_abstraction_is_addr_covered_by_var_reg( 170 HPA address, UINT32 reg_index) { 171 UINT64 phys_base = mtrrs_abstraction_get_address_from_reg(reg_index); 172 UINT64 phys_mask = mtrrs_abstraction_get_mask_from_reg(reg_index); 173 UINT64 mask_base = phys_base & phys_mask; 174 UINT64 mask_target = phys_mask & address; 175 if (mask_base == mask_target) { 176 remsize = (phys_base & phys_mask) + (~(phys_mask | MTRR_MSBs)) + 1 - address; 177 178 } 179 return (mask_base == mask_target); 180 } 181 182 INLINE BOOLEAN mttrs_abstraction_is_type_valid(UINT64 type) { 183 switch (type) { 184 case VMM_PHYS_MEM_UNCACHABLE: 185 case VMM_PHYS_MEM_WRITE_COMBINING: 186 case VMM_PHYS_MEM_WRITE_THROUGH: 187 case VMM_PHYS_MEM_WRITE_PROTECTED: 188 case VMM_PHYS_MEM_WRITE_BACK: 189 return TRUE; 190 } 191 return FALSE; 192 } 193 194 INLINE BOOLEAN mtrrs_abstraction_is_IA32_MTRR_DEF_TYPE_valid(UINT64 value) { 195 IA32_MTRR_DEF_TYPE_REG reg; 196 reg.value = value; 197 return ((reg.bits.res0 == 0) && (reg.bits.res1 == 0) && mttrs_abstraction_is_type_valid(reg.bits.type)); 198 } 199 200 INLINE BOOLEAN mtrrs_abstraction_is_IA32_MTRR_PHYSBASE_REG_valid(UINT64 value) { 201 IA32_MTRR_PHYSBASE_REG reg; 202 reg.value = value; 203 return ((reg.bits.res0 == 0) && (reg.bits.res1 == 0) && mttrs_abstraction_is_type_valid(reg.bits.type)); 204 } 205 206 INLINE BOOLEAN mtrrs_abstraction_is_IA32_MTRR_PHYSMASK_REG_valid(UINT64 value) { 207 IA32_MTRR_PHYSMASK_REG reg; 208 reg.value = value; 209 return ((reg.bits.res0 == 0) && (reg.bits.res1 == 0)); 210 } 211 212 INLINE BOOLEAN mtrrs_abstraction_is_IA32_FIXED_RANGE_REG_valid(UINT64 value) { 213 IA32_FIXED_RANGE_MTRR reg; 214 UINT32 i; 215 reg.value = value; 216 for (i = 0; i < MTRRS_ABS_NUM_OF_SUB_RANGES; i++) { 217 if (!mttrs_abstraction_is_type_valid(reg.type[i])) { 218 return FALSE; 219 } 220 } 221 return TRUE; 222 } 223 224 BOOLEAN mtrrs_is_variable_mtrrr_supported(UINT32 msr_id) { 225 /* 226 * IA32_MTRR_PHYSBASE8 - supported only if IA32_MTRR_CAP[7:0] > 8 227 * IA32_MTRR_PHYSMASK8 - supported only if IA32_MTRR_CAP[7:0] > 8 228 * IA32_MTRR_PHYSBASE9 - supported only if IA32_MTRR_CAP[7:0] > 9 229 * IA32_MTRR_PHYSMASK9 - supported only if IA32_MTRR_CAP[7:0] > 9 230 */ 231 UINT32 index, i; 232 233 /* Check if MSR is within unsupported variable MTRR range */ 234 if(msr_id >= IA32_MTRR_PHYSBASE8_ADDR && msr_id <= IA32_MTRR_MAX_PHYSMASK_ADDR) { 235 for(index = IA32_MTRR_MAX_PHYSMASK_ADDR, i = 1; index > IA32_MTRR_PHYSBASE8_ADDR; 236 index -= 2, i++) { 237 if( ((index == msr_id) || (index - 1 == msr_id)) ) { 238 if (mtrrs_abstraction_get_num_of_variable_range_regs() > (MTRRS_ABS_NUM_OF_VAR_RANGE_MTRRS - i) ) { 239 return TRUE; 240 } else { 241 return FALSE; 242 } 243 } 244 } 245 return TRUE; // dummy added to suppress warning, should never get here 246 } else // MSR is not within unsupported variable MTRR range. 247 return TRUE; 248 } 249 250 251 BOOLEAN mtrrs_abstraction_bsp_initialize(void) { 252 UINT32 msr_addr; 253 UINT32 index; 254 255 vmm_memset(&mtrrs_cached_info, 0, sizeof(mtrrs_cached_info)); 256 mtrrs_cached_info.ia32_mtrrcap_reg.value = hw_read_msr(IA32_MTRRCAP_ADDR); 257 mtrrs_cached_info.ia32_mtrr_def_type.value = hw_read_msr(IA32_MTRR_DEF_TYPE_ADDR); 258 259 if (mtrrs_abstraction_are_fixed_regs_supported()) { 260 mtrrs_cached_info.ia32_mtrr_fix[0].value = hw_read_msr(IA32_MTRR_FIX64K_00000_ADDR); 261 mtrrs_cached_info.ia32_mtrr_fix_range[0].start_addr = 0x0; 262 mtrrs_cached_info.ia32_mtrr_fix_range[0].end_addr = 0x7ffff; 263 264 mtrrs_cached_info.ia32_mtrr_fix[1].value = hw_read_msr(IA32_MTRR_FIX16K_80000_ADDR); 265 mtrrs_cached_info.ia32_mtrr_fix_range[1].start_addr = 0x80000; 266 mtrrs_cached_info.ia32_mtrr_fix_range[1].end_addr = 0x9ffff; 267 268 mtrrs_cached_info.ia32_mtrr_fix[2].value = hw_read_msr(IA32_MTRR_FIX16K_A0000_ADDR); 269 mtrrs_cached_info.ia32_mtrr_fix_range[2].start_addr = 0xa0000; 270 mtrrs_cached_info.ia32_mtrr_fix_range[2].end_addr = 0xbffff; 271 272 mtrrs_cached_info.ia32_mtrr_fix[3].value = hw_read_msr(IA32_MTRR_FIX4K_C0000_ADDR); 273 mtrrs_cached_info.ia32_mtrr_fix_range[3].start_addr = 0xc0000; 274 mtrrs_cached_info.ia32_mtrr_fix_range[3].end_addr = 0xc7fff; 275 276 mtrrs_cached_info.ia32_mtrr_fix[4].value = hw_read_msr(IA32_MTRR_FIX4K_C8000_ADDR); 277 mtrrs_cached_info.ia32_mtrr_fix_range[4].start_addr = 0xc8000; 278 mtrrs_cached_info.ia32_mtrr_fix_range[4].end_addr = 0xcffff; 279 280 mtrrs_cached_info.ia32_mtrr_fix[5].value = hw_read_msr(IA32_MTRR_FIX4K_D0000_ADDR); 281 mtrrs_cached_info.ia32_mtrr_fix_range[5].start_addr = 0xd0000; 282 mtrrs_cached_info.ia32_mtrr_fix_range[5].end_addr = 0xd7fff; 283 284 mtrrs_cached_info.ia32_mtrr_fix[6].value = hw_read_msr(IA32_MTRR_FIX4K_D8000_ADDR); 285 mtrrs_cached_info.ia32_mtrr_fix_range[6].start_addr = 0xd8000; 286 mtrrs_cached_info.ia32_mtrr_fix_range[6].end_addr = 0xdffff; 287 288 mtrrs_cached_info.ia32_mtrr_fix[7].value = hw_read_msr(IA32_MTRR_FIX4K_E0000_ADDR); 289 mtrrs_cached_info.ia32_mtrr_fix_range[7].start_addr = 0xe0000; 290 mtrrs_cached_info.ia32_mtrr_fix_range[7].end_addr = 0xe7fff; 291 292 mtrrs_cached_info.ia32_mtrr_fix[8].value = hw_read_msr(IA32_MTRR_FIX4K_E8000_ADDR); 293 mtrrs_cached_info.ia32_mtrr_fix_range[8].start_addr = 0xe8000; 294 mtrrs_cached_info.ia32_mtrr_fix_range[8].end_addr = 0xeffff; 295 296 mtrrs_cached_info.ia32_mtrr_fix[9].value = hw_read_msr(IA32_MTRR_FIX4K_F0000_ADDR); 297 mtrrs_cached_info.ia32_mtrr_fix_range[9].start_addr = 0xf0000; 298 mtrrs_cached_info.ia32_mtrr_fix_range[9].end_addr = 0xf7fff; 299 300 mtrrs_cached_info.ia32_mtrr_fix[10].value = hw_read_msr(IA32_MTRR_FIX4K_F8000_ADDR); 301 mtrrs_cached_info.ia32_mtrr_fix_range[10].start_addr = 0xf8000; 302 mtrrs_cached_info.ia32_mtrr_fix_range[10].end_addr = 0xfffff; 303 304 } 305 306 for (msr_addr = IA32_MTRR_PHYSBASE0_ADDR, index = 0; index < mtrrs_abstraction_get_num_of_variable_range_regs(); msr_addr += 2, index++) { 307 if (msr_addr > IA32_MTRR_MAX_PHYSMASK_ADDR) { 308 VMM_LOG(mask_uvmm,level_error, "BSP: ERROR: MTRRs Abstraction: Variable MTRRs count > %d", MTRRS_ABS_NUM_OF_VAR_RANGE_MTRRS); 309 VMM_DEADLOOP(); 310 } 311 mtrrs_cached_info.ia32_mtrr_var_phys_base[index].value = hw_read_msr(msr_addr); 312 mtrrs_cached_info.ia32_mtrr_var_phys_mask[index].value = hw_read_msr(msr_addr + 1); 313 } 314 MTRR_MSBs = ~((UINT64)(((UINT64)1 << addr_get_physical_address_size()) - 1)); 315 mtrrs_cached_info.is_initialized = TRUE; 316 return TRUE; 317 } 318 319 BOOLEAN mtrrs_abstraction_ap_initialize(void) { 320 UINT32 msr_addr; 321 UINT32 index; 322 323 if (!mtrrs_cached_info.is_initialized) { 324 VMM_LOG(mask_anonymous, level_error,"ERROR: MTRRs Abstraction: Initializing AP before BSP\n"); 325 goto failed; 326 } 327 if (mtrrs_cached_info.ia32_mtrrcap_reg.value != hw_read_msr(IA32_MTRRCAP_ADDR)) { 328 VMM_LOG(mask_anonymous, level_error,"ERROR: MTRRs Abstraction: IA32_MTRRCAP doesn't match\n"); 329 goto failed; 330 } 331 if (mtrrs_cached_info.ia32_mtrr_def_type.value != hw_read_msr(IA32_MTRR_DEF_TYPE_ADDR)) { 332 VMM_LOG(mask_anonymous, level_error,"ERROR: MTRRs Abstraction: IA32_MTRR_DEF_TYPE doesn't match\n"); 333 goto failed; 334 } 335 if (mtrrs_abstraction_are_fixed_regs_supported()) { 336 if((mtrrs_cached_info.ia32_mtrr_fix[0].value!=hw_read_msr(IA32_MTRR_FIX64K_00000_ADDR))|| 337 (mtrrs_cached_info.ia32_mtrr_fix[1].value!=hw_read_msr(IA32_MTRR_FIX16K_80000_ADDR))|| 338 (mtrrs_cached_info.ia32_mtrr_fix[2].value!=hw_read_msr(IA32_MTRR_FIX16K_A0000_ADDR))|| 339 (mtrrs_cached_info.ia32_mtrr_fix[3].value!=hw_read_msr(IA32_MTRR_FIX4K_C0000_ADDR))|| 340 (mtrrs_cached_info.ia32_mtrr_fix[4].value!=hw_read_msr(IA32_MTRR_FIX4K_C8000_ADDR))|| 341 (mtrrs_cached_info.ia32_mtrr_fix[5].value!=hw_read_msr(IA32_MTRR_FIX4K_D0000_ADDR))|| 342 (mtrrs_cached_info.ia32_mtrr_fix[6].value!=hw_read_msr(IA32_MTRR_FIX4K_D8000_ADDR))|| 343 (mtrrs_cached_info.ia32_mtrr_fix[7].value!=hw_read_msr(IA32_MTRR_FIX4K_E0000_ADDR))|| 344 (mtrrs_cached_info.ia32_mtrr_fix[8].value!=hw_read_msr(IA32_MTRR_FIX4K_E8000_ADDR))|| 345 (mtrrs_cached_info.ia32_mtrr_fix[9].value!=hw_read_msr(IA32_MTRR_FIX4K_F0000_ADDR))|| 346 (mtrrs_cached_info.ia32_mtrr_fix[10].value!=hw_read_msr(IA32_MTRR_FIX4K_F8000_ADDR))){ 347 348 VMM_LOG(mask_anonymous, level_error, 349 "ERROR: MTRRs Abstraction: One (or more) of the fixed range MTRRs doesn't match\n"); 350 goto failed; 351 } 352 } 353 354 for (msr_addr = IA32_MTRR_PHYSBASE0_ADDR, index = 0; index < mtrrs_abstraction_get_num_of_variable_range_regs(); msr_addr += 2, index++) { 355 if (msr_addr > IA32_MTRR_MAX_PHYSMASK_ADDR) { 356 VMM_LOG(mask_uvmm,level_error, 357 "AP: ERROR: MTRRs Abstraction: Variable MTRRs count > %d", 358 MTRRS_ABS_NUM_OF_VAR_RANGE_MTRRS); 359 VMM_DEADLOOP(); 360 } 361 if((mtrrs_cached_info.ia32_mtrr_var_phys_base[index].value!=hw_read_msr(msr_addr)) || 362 (mtrrs_cached_info.ia32_mtrr_var_phys_mask[index].value!=hw_read_msr(msr_addr+1))) { 363 VMM_LOG(mask_anonymous, level_error, 364 "ERROR: MTRRs Abstraction of the variable range MTRRs doesn't match\n"); 365 goto failed; 366 } 367 } 368 return TRUE; 369 370 failed: 371 VMM_ASSERT(0); 372 return FALSE; 373 } 374 375 376 VMM_PHYS_MEM_TYPE mtrrs_abstraction_get_memory_type(HPA address) { 377 UINT32 index; 378 UINT32 var_mtrr_match_bitmap; 379 VMM_PHYS_MEM_TYPE type = VMM_PHYS_MEM_UNDEFINED; 380 UINT64 remsize_back = 0, range_base = 0; 381 VMM_PHYS_MEM_TYPE type_back = VMM_PHYS_MEM_UNDEFINED; 382 383 remsize = 0; 384 VMM_ASSERT(mtrrs_cached_info.is_initialized); 385 if (!mtrrs_abstraction_are_mtrrs_enabled()) { 386 return VMM_PHYS_MEM_UNCACHABLE; 387 } 388 if (mtrrs_abstraction_are_fixed_regs_supported() && 389 mtrrs_abstraction_are_fixed_ranged_mtrrs_enabled() && 390 (address <= mtrrs_cached_info.ia32_mtrr_fix_range[MTRRS_ABS_NUM_OF_FIXED_RANGE_MTRRS - 1].end_addr)) { 391 392 // Find proper fixed range MTRR 393 for (index = 0; index < MTRRS_ABS_NUM_OF_FIXED_RANGE_MTRRS; index++) { 394 if (address <= mtrrs_cached_info.ia32_mtrr_fix_range[index].end_addr) { 395 // Find proper sub-range 396 UINT64 offset= address-mtrrs_cached_info.ia32_mtrr_fix_range[index].start_addr; 397 UINT32 size = mtrrs_cached_info.ia32_mtrr_fix_range[index].end_addr + 1 - mtrrs_cached_info.ia32_mtrr_fix_range[index].start_addr; 398 UINT32 sub_range_size = size / MTRRS_ABS_NUM_OF_SUB_RANGES; 399 UINT64 sub_range_index = offset / sub_range_size; 400 remsize = (sub_range_index+1) * sub_range_size - offset; 401 VMM_ASSERT((size % MTRRS_ABS_NUM_OF_SUB_RANGES) == 0); 402 VMM_ASSERT(sub_range_index < MTRRS_ABS_NUM_OF_SUB_RANGES); 403 return (VMM_PHYS_MEM_TYPE)mtrrs_cached_info.ia32_mtrr_fix[index].type[sub_range_index]; 404 } 405 } 406 VMM_ASSERT(0); // mustn't reach here 407 } 408 409 var_mtrr_match_bitmap = 0; 410 for (index = 0; index < mtrrs_abstraction_get_num_of_variable_range_regs(); index++) { 411 if (index >= MTRRS_ABS_NUM_OF_VAR_RANGE_MTRRS) { 412 break; 413 } 414 if (!mtrrs_abstraction_is_var_reg_valid(index)) { 415 continue; 416 } 417 if (mtrrs_abstraction_is_addr_covered_by_var_reg(address, index)) { 418 type = (VMM_PHYS_MEM_TYPE)mtrrs_cached_info.ia32_mtrr_var_phys_base[index].bits.type; 419 BIT_SET(var_mtrr_match_bitmap, type); 420 if (remsize_back > 0) { 421 if (type == VMM_PHYS_MEM_UNCACHABLE || type_back == VMM_PHYS_MEM_UNCACHABLE) { 422 if (type_back != VMM_PHYS_MEM_UNCACHABLE) { 423 remsize_back = remsize; 424 } 425 if (type != VMM_PHYS_MEM_UNCACHABLE) { 426 remsize =0; 427 } 428 if (type == VMM_PHYS_MEM_UNCACHABLE && type_back == VMM_PHYS_MEM_UNCACHABLE) 429 remsize_back = (remsize_back > remsize) ? remsize_back : remsize; 430 type_back = VMM_PHYS_MEM_UNCACHABLE; 431 remsize =0; 432 } 433 else { 434 remsize_back = (remsize_back > remsize) ? remsize : remsize_back; 435 type_back = type; 436 remsize = 0; 437 } 438 } 439 else { 440 remsize_back = remsize; 441 remsize = 0; 442 type_back = type; 443 } 444 } 445 else { 446 range_base = mtrrs_abstraction_get_address_from_reg(index); 447 448 if (address < range_base && address + remsize_back > range_base) { 449 remsize_back = range_base - address; 450 } 451 } 452 } 453 remsize = remsize_back; 454 455 if (0 == var_mtrr_match_bitmap) { 456 // not described by any MTRR, return default memory type 457 return mtrrs_abstraction_get_default_memory_type(); 458 } 459 else if (IS_POW_OF_2(var_mtrr_match_bitmap)) { 460 // described by single MTRR, type contains the proper value 461 return type; 462 } 463 else if (BIT_GET(var_mtrr_match_bitmap, VMM_PHYS_MEM_UNCACHABLE)) { 464 // fall in multiple ranges, UC wins 465 return VMM_PHYS_MEM_UNCACHABLE; 466 } 467 else if ((BIT_VALUE64(VMM_PHYS_MEM_WRITE_THROUGH) | BIT_VALUE64(VMM_PHYS_MEM_WRITE_BACK)) 468 == var_mtrr_match_bitmap) { 469 // fall in WT + WB, WT wins. 470 return VMM_PHYS_MEM_WRITE_THROUGH; 471 } 472 473 // improper MTRR setting 474 VMM_LOG(mask_anonymous, level_error, 475 "FATAL: MTRRs Abstraction: Overlapping variable MTRRs have confilting types\n"); 476 VMM_DEADLOOP(); 477 return VMM_PHYS_MEM_UNDEFINED; 478 } 479 480 VMM_PHYS_MEM_TYPE mtrrs_abstraction_get_range_memory_type(HPA address, OUT UINT64 *size,UINT64 totalsize) 481 { 482 VMM_PHYS_MEM_TYPE first_page_mem_type, mem_type; 483 UINT64 range_size = 0; 484 remsize=0; 485 486 first_page_mem_type = mtrrs_abstraction_get_memory_type(address); 487 for(mem_type = first_page_mem_type; 488 (mem_type == first_page_mem_type) && (range_size<totalsize); 489 mem_type = mtrrs_abstraction_get_memory_type(address + range_size)) { 490 if (remsize != 0) 491 range_size += remsize; 492 else 493 range_size += 4 KILOBYTES; 494 } 495 if(size != NULL) { 496 *size = range_size; 497 } 498 return first_page_mem_type; 499 } 500 501 BOOLEAN mtrrs_abstraction_track_mtrr_update(UINT32 mtrr_index, UINT64 value) { 502 if (mtrr_index == IA32_MTRR_DEF_TYPE_ADDR) { 503 if (!mtrrs_abstraction_is_IA32_MTRR_DEF_TYPE_valid(value)) { 504 return FALSE; 505 } 506 mtrrs_cached_info.ia32_mtrr_def_type.value = value; 507 return TRUE; 508 } 509 if ((mtrr_index>=IA32_MTRR_FIX64K_00000_ADDR) && (mtrr_index <= IA32_MTRR_FIX4K_F8000_ADDR)) { 510 UINT32 fixed_index = (~((UINT32)0)); 511 switch(mtrr_index) { 512 513 case IA32_MTRR_FIX64K_00000_ADDR: 514 fixed_index = 0; 515 break; 516 case IA32_MTRR_FIX16K_80000_ADDR: 517 fixed_index = 1; 518 break; 519 case IA32_MTRR_FIX16K_A0000_ADDR: 520 fixed_index = 2; 521 break; 522 case IA32_MTRR_FIX4K_C0000_ADDR: 523 fixed_index = 3; 524 break; 525 case IA32_MTRR_FIX4K_C8000_ADDR: 526 fixed_index = 4; 527 break; 528 case IA32_MTRR_FIX4K_D0000_ADDR: 529 fixed_index = 5; 530 break; 531 case IA32_MTRR_FIX4K_D8000_ADDR: 532 fixed_index = 6; 533 break; 534 case IA32_MTRR_FIX4K_E0000_ADDR: 535 fixed_index = 7; 536 break; 537 case IA32_MTRR_FIX4K_E8000_ADDR: 538 fixed_index = 8; 539 break; 540 case IA32_MTRR_FIX4K_F0000_ADDR: 541 fixed_index = 9; 542 break; 543 case IA32_MTRR_FIX4K_F8000_ADDR: 544 fixed_index = 10; 545 break; 546 default: 547 VMM_ASSERT(0); 548 return FALSE; 549 } 550 if (!mtrrs_abstraction_is_IA32_FIXED_RANGE_REG_valid(value)) { 551 return FALSE; 552 } 553 mtrrs_cached_info.ia32_mtrr_fix[fixed_index].value = value; 554 return TRUE; 555 } 556 if ((mtrr_index >= IA32_MTRR_PHYSBASE0_ADDR) && (mtrr_index <= IA32_MTRR_MAX_PHYSMASK_ADDR)){ 557 BOOLEAN is_phys_base = ((mtrr_index % 2) == 0); 558 if (is_phys_base) { 559 UINT32 phys_base_index = (mtrr_index - IA32_MTRR_PHYSBASE0_ADDR) / 2; 560 if (!mtrrs_abstraction_is_IA32_MTRR_PHYSBASE_REG_valid(value)) { 561 return FALSE; 562 } 563 mtrrs_cached_info.ia32_mtrr_var_phys_base[phys_base_index].value = value; 564 } 565 else { 566 UINT32 phys_mask_index = (mtrr_index - IA32_MTRR_PHYSMASK0_ADDR) / 2; 567 if (!mtrrs_abstraction_is_IA32_MTRR_PHYSMASK_REG_valid(value)) { 568 return FALSE; 569 } 570 mtrrs_cached_info.ia32_mtrr_var_phys_mask[phys_mask_index].value = value; 571 } 572 return TRUE; 573 } 574 return FALSE; 575 }