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  }