github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/cpvmm/vmm/arch/e820_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 "file_codes.h"
    16  #define VMM_DEADLOOP()          VMM_DEADLOOP_LOG(E820_ABSTRACTION_C)
    17  #define VMM_ASSERT(__condition) VMM_ASSERT_LOG(E820_ABSTRACTION_C, __condition)
    18  #include <vmm_defs.h>
    19  #include <vmm_arch_defs.h>
    20  #include <e820_abstraction.h>
    21  #include <heap.h>
    22  #include <common_libc.h>
    23  #include "vmm_dbg.h"
    24  #ifdef ENABLE_INT15_VIRTUALIZATION
    25  #include "vmm_objects.h"
    26  #include "gpm_api.h"
    27  #include "guest_cpu.h"
    28  #include "guest.h"
    29  #include "host_memory_manager_api.h"
    30  #include "../guest/guest_cpu/unrestricted_guest.h"
    31  #ifdef JLMDEBUG
    32  #include "jlmdebug.h"
    33  #endif
    34  
    35  
    36  UINT32 g_int15_trapped_page = 0;
    37  UINT32 g_int15_orignal_vector = 0;
    38  E820MAP_STATE                   *g_emap;
    39  #endif // ENABLE_INT15_VIRTUALIZATION
    40  
    41  
    42  static INT15_E820_MEMORY_MAP* g_e820_map = NULL;
    43  
    44  // static 
    45  const char* g_int15_e820_type_name[] = {
    46      "UNKNOWN", // 0
    47      "MEMORY",  // 1
    48      "RESERVED",// 2
    49      "ACPI",    // 3
    50      "NVS",     // 4
    51      "UNUSABLE" // 5
    52  };
    53  #ifdef ENABLE_INT15_VIRTUALIZATION
    54  static UINT8 int15_handler_code[] =
    55  {
    56          0x3d,0x20,0xe8,                 // cmp ax, 0xe820
    57          0x74,0x05,                      // jz Handler
    58          0xea,0x00,0x00,0x00,0x00,       // jmp orig_handler
    59          0x0f,0x01,0xc1,                 // Handler: vmcall
    60          0xcf                            // iret
    61  };
    62                                          // conditional jump can be only
    63                                          // near jump, hence too jumps in
    64                                          // this assembly code
    65  #endif // ENABLE_INT15_VIRTUALIZATION
    66  #define E820_NAMES_COUNT (sizeof(g_int15_e820_type_name)/sizeof(const char*))
    67  
    68  #ifdef ENABLE_INT15_VIRTUALIZATION
    69  
    70  /*
    71   * This function is supposed to setup int15 handling
    72   * it will write its own handling code to vector area which is
    73   * not being used or known to not being used. So we only
    74   * handle E820 type INT15 interrupt, any other type of
    75   * INT15 will be handled by the original vector.
    76   */
    77  void update_int15_handling(void)
    78  {
    79      UINT32 int15_vector, i;
    80      UINT32 *int15_vector_offset = (UINT32*)((UINT64)INT15_VECTOR_LOCATION);
    81  
    82      // save original vector location to use in vmexit
    83      g_int15_orignal_vector = *(int15_vector_offset);
    84  
    85      int15_vector = INT15_HANDLER_ADDR; //use some location in INT vector table which is not being used
    86  
    87      g_int15_trapped_page = int15_vector; //CS:IP format vector
    88      *(int15_vector_offset) = g_int15_trapped_page; //hookup our INT15 vector(seg:offset)
    89  
    90      //patch the original vector
    91      *(UINT32*)&int15_handler_code[ORIG_HANDLER_OFFSET] = g_int15_orignal_vector;
    92  
    93      // put out warning if the vector area is being used
    94      // vectors we are using are user defined, it is possible
    95      // some user might decide to use. Nothing we could do about
    96      // but would like to through some indication that those vectors
    97      // were non-zero
    98      for (i=0; i<sizeof(int15_handler_code); i=i+4)  {
    99          if (*(UINT32*)(UINT64)(int15_vector+i) != 0)
   100              VMM_LOG(mask_anonymous, level_error, "WARNING: User defined Interrupts being over written (0x%x)\n",*(UINT32*)(UINT64)(int15_vector+i) );
   101      }
   102  
   103      //write patched code to the interrupt 15 handling location
   104      for (i=0; i<sizeof(int15_handler_code); i++)
   105          *(UINT8*)(UINT64)(int15_vector+i) = int15_handler_code[i];
   106  
   107      VMM_LOG(mask_anonymous, level_trace, "E820 Original vector:0x%x\n",g_int15_orignal_vector );
   108      VMM_LOG(mask_anonymous, level_trace, "E820 int15 handler vector:0x%x\n",g_int15_trapped_page );
   109  }
   110  #endif //ENABLE_INT15_VIRTUALIZATION
   111  #ifdef DEBUG
   112  INLINE const char* e820_get_type_name( INT15_E820_RANGE_TYPE type )
   113  {
   114      return (type < E820_NAMES_COUNT) ? g_int15_e820_type_name[type] : "UNKNOWN";
   115  }
   116  #endif
   117  
   118  BOOLEAN e820_abstraction_initialize(const INT15_E820_MEMORY_MAP* e820_memory_map)
   119  {
   120  #ifdef ENABLE_INT15_VIRTUALIZATION
   121      if(is_unrestricted_guest_supported())
   122          //initialize int15 handling vectors
   123          update_int15_handling();
   124  #endif
   125      if (e820_memory_map != NULL) {
   126          UINT32 size = e820_memory_map->memory_map_size + sizeof(e820_memory_map->memory_map_size);
   127          g_e820_map = (INT15_E820_MEMORY_MAP*)vmm_memory_alloc(size);
   128          if (g_e820_map == NULL) {
   129              return FALSE;
   130          }
   131          vmm_memcpy(g_e820_map, e820_memory_map, size);
   132          VMM_DEBUG_CODE(e820_abstraction_print_memory_map(E820_ORIGINAL_MAP));
   133          return TRUE;
   134      }
   135      return FALSE;
   136  }
   137  
   138  BOOLEAN e820_abstraction_is_initialized(void) {
   139      return (g_e820_map != NULL);
   140  }
   141  
   142  const INT15_E820_MEMORY_MAP* e820_abstraction_get_map(E820_HANDLE e820_handle) {
   143      if (e820_handle == E820_ORIGINAL_MAP) {
   144          return g_e820_map;
   145      }
   146      return (const INT15_E820_MEMORY_MAP*)e820_handle;
   147  }
   148  
   149  
   150  E820_ABSTRACTION_RANGE_ITERATOR e820_abstraction_iterator_get_first(E820_HANDLE e820_handle) {
   151      INT15_E820_MEMORY_MAP* e820_map;
   152  
   153      if (e820_handle == E820_ORIGINAL_MAP) {
   154          e820_map = g_e820_map;
   155      }
   156      else {
   157          e820_map = (INT15_E820_MEMORY_MAP*)e820_handle;
   158      }
   159  
   160      if (e820_map == NULL) {
   161          return E820_ABSTRACTION_NULL_ITERATOR;
   162      }
   163  
   164      if (e820_map->memory_map_size == 0) {
   165          return E820_ABSTRACTION_NULL_ITERATOR;
   166      }
   167  
   168      return(E820_ABSTRACTION_RANGE_ITERATOR)(&(e820_map->memory_map_entry[0]));
   169  }
   170  
   171  E820_ABSTRACTION_RANGE_ITERATOR
   172  e820_abstraction_iterator_get_next(E820_HANDLE e820_handle, E820_ABSTRACTION_RANGE_ITERATOR iter) {
   173      UINT64 iter_hva = (UINT64)iter;
   174      INT15_E820_MEMORY_MAP* e820_map;
   175      UINT64 e820_entries_hva;
   176  
   177      if (iter == (E820_ABSTRACTION_RANGE_ITERATOR)NULL) {
   178          return E820_ABSTRACTION_NULL_ITERATOR;
   179      }
   180      if (e820_handle == E820_ORIGINAL_MAP) {
   181          e820_map = g_e820_map;
   182      }
   183      else {
   184          e820_map = (INT15_E820_MEMORY_MAP*)e820_handle;
   185      }
   186      if(e820_map == NULL){
   187          return E820_ABSTRACTION_NULL_ITERATOR;
   188      }
   189      e820_entries_hva = (UINT64)(&(e820_map->memory_map_entry[0]));
   190      iter_hva += sizeof(INT15_E820_MEMORY_MAP_ENTRY_EXT);
   191      if (iter_hva >= (e820_entries_hva + e820_map->memory_map_size)) {
   192          return E820_ABSTRACTION_NULL_ITERATOR;
   193      }
   194      return (E820_ABSTRACTION_RANGE_ITERATOR*)iter_hva;
   195  }
   196  
   197  const INT15_E820_MEMORY_MAP_ENTRY_EXT*
   198  e820_abstraction_iterator_get_range_details(IN E820_ABSTRACTION_RANGE_ITERATOR iter) {
   199      if (iter == (E820_ABSTRACTION_RANGE_ITERATOR)NULL) {
   200          return NULL;
   201      }
   202      return (INT15_E820_MEMORY_MAP_ENTRY_EXT*)iter;
   203  }
   204  
   205  
   206  BOOLEAN e820_abstraction_create_new_map(OUT E820_HANDLE* handle) {
   207      INT15_E820_MEMORY_MAP* e820_map = (INT15_E820_MEMORY_MAP*)vmm_page_alloc(1);
   208      if (e820_map == NULL) {
   209          return FALSE;
   210      }
   211      e820_map->memory_map_size = 0;
   212      *handle = (E820_HANDLE)e820_map;
   213      return TRUE;
   214  }
   215  
   216  void e820_abstraction_destroy_map(IN E820_HANDLE handle) {
   217      if (handle == E820_ORIGINAL_MAP) {
   218          // Destroying of original map is forbidden
   219          VMM_ASSERT(0);
   220          return;
   221      }
   222      vmm_page_free((void*)handle);
   223  }
   224  
   225  BOOLEAN e820_abstraction_add_new_range(IN E820_HANDLE handle,
   226                    IN UINT64 base_address, IN UINT64 length,
   227                    IN INT15_E820_RANGE_TYPE  address_range_type,
   228                    IN INT15_E820_MEMORY_MAP_EXT_ATTRIBUTES extended_attributes) {
   229      INT15_E820_MEMORY_MAP* e820_map = (INT15_E820_MEMORY_MAP*)handle;
   230      INT15_E820_MEMORY_MAP_ENTRY_EXT* new_entry;
   231      UINT32 new_entry_index;
   232  
   233      if (handle == E820_ORIGINAL_MAP) {
   234          VMM_ASSERT(0);
   235          return FALSE;
   236      }
   237      if ((e820_map->memory_map_size + sizeof(INT15_E820_MEMORY_MAP_ENTRY_EXT)) >= PAGE_4KB_SIZE) {
   238          return FALSE;
   239      }
   240      if (length == 0) {
   241          return FALSE;
   242      }
   243      new_entry_index = e820_map->memory_map_size / sizeof(INT15_E820_MEMORY_MAP_ENTRY_EXT);
   244      if (new_entry_index > 0) {
   245          INT15_E820_MEMORY_MAP_ENTRY_EXT* last_entry = &(e820_map->memory_map_entry[new_entry_index - 1]);
   246          if ((last_entry->basic_entry.base_address >= base_address) ||
   247              (last_entry->basic_entry.base_address + last_entry->basic_entry.length > base_address)) {
   248              return FALSE;
   249          }
   250      }
   251      new_entry = &(e820_map->memory_map_entry[new_entry_index]);
   252      new_entry->basic_entry.base_address = base_address;
   253      new_entry->basic_entry.length = length;
   254      new_entry->basic_entry.address_range_type = address_range_type;
   255      new_entry->extended_attributes.uint32 = extended_attributes.uint32;
   256      e820_map->memory_map_size += sizeof(INT15_E820_MEMORY_MAP_ENTRY_EXT);
   257      return TRUE;
   258  }
   259  
   260  
   261  #ifdef ENABLE_INT15_VIRTUALIZATION
   262  // handle int15 from real mode code
   263  // we use CS:IP for vmcall instruction to get indication that there is int15
   264  // check for E820 function, if true, then handle it
   265  // no other int15 function should come here
   266  BOOLEAN handle_int15_vmcall(GUEST_CPU_HANDLE gcpu)
   267  {
   268      UINT16  selector=0;
   269      UINT64  base=0;
   270      UINT32  limit=0;
   271      UINT32  attr=0;
   272      UINT32 expected_lnr_addr;
   273      UINT32 vmcall_lnr_addr;
   274      volatile UINT64 r_rax=0, r_rdx=0, r_rip=0;
   275  
   276      // PE = 0? then real mode
   277      if(!(0x1 & gcpu_get_guest_visible_control_reg(gcpu, IA32_CTRL_CR0))) {
   278          //need to get CS:IP to make sure that this VMCALL from INT15 handler
   279          gcpu_get_segment_reg(gcpu,IA32_SEG_CS, &selector,&base,&limit,&attr);
   280          r_rip = gcpu_get_gp_reg(gcpu, IA32_REG_RIP);
   281  
   282          expected_lnr_addr = SEGMENT_OFFSET_TO_LINEAR(g_int15_trapped_page >> 16,
   283                                                       g_int15_trapped_page + VMCALL_OFFSET);
   284          vmcall_lnr_addr = SEGMENT_OFFSET_TO_LINEAR((UINT32)selector, (UINT32)r_rip);
   285          //check to see if the CS:IP is same as expected for VMCALL in INT15 handler
   286          if (expected_lnr_addr == vmcall_lnr_addr) {
   287              r_rax = gcpu_get_gp_reg(gcpu, IA32_REG_RAX);
   288              r_rdx = gcpu_get_gp_reg(gcpu, IA32_REG_RDX);
   289              if ((0xE820 == r_rax) && ('SMAP' == r_rdx)) {
   290                  if (g_emap == NULL) {
   291                      g_emap = vmm_malloc(sizeof(E820MAP_STATE));
   292                      VMM_ASSERT(g_emap != NULL);
   293                      vmm_memset(g_emap, 0, sizeof(E820MAP_STATE));
   294                  }
   295              e820_save_guest_state(gcpu, g_emap);
   296              g_emap->guest_handle = gcpu_guest_handle(gcpu);
   297              e820_int15_handler(g_emap);
   298              e820_restore_guest_state(gcpu, g_emap);
   299              gcpu_skip_guest_instruction(gcpu);
   300              return TRUE;
   301              } else {
   302                 VMM_LOG(mask_anonymous, level_error,"INT15 wasn't handled for function 0x%x\n", r_rax);
   303                 VMM_DEADLOOP(); // Should not get here
   304                 return FALSE;
   305              }
   306           }
   307      }
   308      return FALSE;
   309  }
   310  
   311  //save Guest state for registers we might be using
   312  // when handling INT15 E820
   313  void
   314  e820_save_guest_state(GUEST_CPU_HANDLE gcpu, E820MAP_STATE *emap)
   315  {
   316      UINT16            selector;
   317      UINT64            base;
   318      UINT32            limit;
   319      UINT32            attr;
   320      E820_GUEST_STATE *p_arch = &emap->e820_guest_state;
   321  
   322      //only registers needed for handling int15 are saved
   323      p_arch->em_rax = gcpu_get_gp_reg(gcpu, IA32_REG_RAX);
   324      p_arch->em_rbx = gcpu_get_gp_reg(gcpu, IA32_REG_RBX);
   325      p_arch->em_rcx = gcpu_get_gp_reg(gcpu, IA32_REG_RCX);
   326      p_arch->em_rdx = gcpu_get_gp_reg(gcpu, IA32_REG_RDX);
   327      p_arch->em_rdi = gcpu_get_gp_reg(gcpu, IA32_REG_RDI);
   328      p_arch->em_rsp = gcpu_get_gp_reg(gcpu, IA32_REG_RSP);
   329      p_arch->em_rflags = gcpu_get_gp_reg(gcpu, IA32_REG_RFLAGS);
   330      gcpu_get_segment_reg(gcpu,IA32_SEG_ES, &selector,&base,&limit,&attr);
   331      p_arch->em_es = selector; p_arch->es_base = base; p_arch->es_lim = limit;
   332      p_arch->es_attr = attr;
   333      gcpu_get_segment_reg(gcpu,IA32_SEG_SS, &selector,&base,&limit,&attr);
   334      p_arch->em_ss = selector; p_arch->ss_base = base; p_arch->ss_lim = limit;
   335      p_arch->ss_attr = attr;
   336  }
   337  
   338  //update VMCS state after handling INT15 E820
   339  void
   340  e820_restore_guest_state( GUEST_CPU_HANDLE gcpu, E820MAP_STATE *emap)
   341  {
   342      E820_GUEST_STATE *p_arch = &emap->e820_guest_state;
   343      GPA     sp_gpa_addr;
   344      HVA     sp_hva_addr;
   345      UINT16  sp_gpa_val;
   346  
   347      //only registers which could be modified by the handler
   348      //will be restored.
   349      gcpu_set_gp_reg(gcpu, IA32_REG_RAX,p_arch->em_rax);
   350      gcpu_set_gp_reg(gcpu, IA32_REG_RBX,p_arch->em_rbx);
   351      gcpu_set_gp_reg(gcpu, IA32_REG_RCX,p_arch->em_rcx);
   352      gcpu_set_gp_reg(gcpu, IA32_REG_RDX,p_arch->em_rdx);
   353      gcpu_set_gp_reg(gcpu, IA32_REG_RDI,p_arch->em_rdi);
   354  
   355      // we need to change the modify EFLAGS saved in stack
   356      // as when we do IRET, EFLAGS are restored from the stack
   357      //only IRET, CPU does pop IP, pop CS_Segment, Pop EFLAGS
   358      // in real mode these pos are only 2bytes
   359      sp_gpa_addr = SEGMENT_OFFSET_TO_LINEAR((UINT32)p_arch->em_ss, p_arch->em_rsp);
   360      sp_gpa_addr +=4; //RSP points to RIP:SEGMENT:EFLAGS so we increment 4 to get to EFLAGS register
   361  
   362      if (FALSE == gpm_gpa_to_hva(emap->guest_phy_memory, sp_gpa_addr, &sp_hva_addr)) {
   363           VMM_LOG(mask_anonymous, level_trace,"Translation failed for physical address %P \n", sp_gpa_addr);
   364       VMM_DEADLOOP();
   365       return;
   366     }
   367      sp_gpa_val = *(UINT16*)(UINT64)sp_hva_addr;
   368      if (p_arch->em_rflags & RFLAGS_CARRY)
   369            BITMAP_SET(sp_gpa_val, RFLAGS_CARRY);
   370      else
   371            BITMAP_CLR(sp_gpa_val, RFLAGS_CARRY);
   372      *(UINT16*)(UINT64)sp_hva_addr =   sp_gpa_val;
   373  }
   374  
   375  //handle INT15 E820 map
   376  BOOLEAN e820_int15_handler(E820MAP_STATE *emap)
   377  {
   378      UINT64 dest_gpa;
   379      E820_GUEST_STATE *p_arch = &emap->e820_guest_state;
   380      const INT15_E820_MEMORY_MAP *p_mmap=NULL;
   381  
   382      if (emap->guest_phy_memory == NULL)
   383          emap->guest_phy_memory = gcpu_get_current_gpm(emap->guest_handle);
   384      VMM_ASSERT(emap->guest_phy_memory != NULL);
   385      if (NULL == emap->emu_e820_handle) {
   386          if (FALSE == (gpm_create_e820_map(emap->guest_phy_memory, (E820_HANDLE)&emap->emu_e820_handle))) {
   387               VMM_LOG(mask_anonymous, level_error,"FATAL ERROR: No E820 Memory Map was found\n");
   388           return FALSE;
   389          }
   390          p_mmap = e820_abstraction_get_map(emap->emu_e820_handle);
   391          emap->emu_e820_memory_map = p_mmap->memory_map_entry;
   392          emap->emu_e820_memory_map_size =
   393          (UINT16) (p_mmap->memory_map_size / sizeof(INT15_E820_MEMORY_MAP_ENTRY_EXT));
   394          VMM_ASSERT(NULL != emap->emu_e820_memory_map && 0 != emap->emu_e820_memory_map_size);
   395          emap->emu_e820_continuation_value = 0;
   396          VMM_LOG(mask_anonymous, level_trace,"INT15 vmcall for E820 map initialized!\n" );
   397      }
   398     // Make sure all the arguments are valid
   399     if ((p_arch->em_rcx < sizeof(INT15_E820_MEMORY_MAP_ENTRY)) ||
   400         (p_arch->em_rbx >= emap->emu_e820_memory_map_size)    ||
   401         (p_arch->em_rbx != 0 && p_arch->em_rbx != emap->emu_e820_continuation_value)) {
   402         // Set the carry flag
   403         BITMAP_SET(p_arch->em_rflags, RFLAGS_CARRY);
   404         VMM_LOG(mask_anonymous, level_error, "ERROR>>>>> E820 INT15 rbx=0x%x rcx:0x%x\n",p_arch->em_rbx,p_arch->em_rcx);
   405     }
   406     else {
   407         HVA dest_hva=0;
   408  
   409         // CX contains number of bytes to write.
   410         // here we select between basic entry and extended
   411         p_arch->em_rcx = (p_arch->em_rcx >= sizeof(INT15_E820_MEMORY_MAP_ENTRY_EXT)) ?
   412             sizeof(INT15_E820_MEMORY_MAP_ENTRY_EXT) : sizeof(INT15_E820_MEMORY_MAP_ENTRY);
   413  
   414         // where to put the result
   415         dest_gpa = SEGMENT_OFFSET_TO_LINEAR((UINT32) p_arch->em_es, p_arch->em_rdi);
   416         if (FALSE == gpm_gpa_to_hva(emap->guest_phy_memory, dest_gpa, &dest_hva)) {
   417               VMM_LOG(mask_anonymous, level_trace,"Translation failed for physical address %P \n", dest_gpa);
   418               BITMAP_SET(p_arch->em_rflags, RFLAGS_CARRY);
   419               return FALSE;
   420         }
   421         vmm_memcpy((void*)dest_hva, (unsigned char *) &emap->emu_e820_memory_map[p_arch->em_rbx],
   422                    (unsigned int) p_arch->em_rcx);
   423  
   424         // keep, to validate next instruction
   425         emap->emu_e820_continuation_value = (UINT16) p_arch->em_rbx + 1;
   426  
   427         // prepare output parameters
   428         p_arch->em_rax = 'SMAP';
   429  
   430         // Clear the carry flag which means error absence
   431         BITMAP_CLR(p_arch->em_rflags, RFLAGS_CARRY);
   432  
   433         if (emap->emu_e820_continuation_value >= emap->emu_e820_memory_map_size) {
   434            // Clear EBX to indicate that this is the last entry in the memory map
   435             p_arch->em_rbx = 0;
   436             emap->emu_e820_continuation_value = 0;
   437         }
   438         else {
   439             // Update the EBX continuation value to indicate there are more entries
   440             p_arch->em_rbx = emap->emu_e820_continuation_value;
   441         }
   442     }
   443     return TRUE;
   444  }
   445  #endif //ENABLE_INT15_VIRTUALIZATION
   446  
   447  #ifdef DEBUG
   448  void e820_abstraction_print_memory_map(IN E820_HANDLE handle) {
   449      INT15_E820_MEMORY_MAP* e820_map = (INT15_E820_MEMORY_MAP*)handle;
   450      UINT32 num_of_entries;
   451      UINT32 i;
   452  
   453      if (e820_map == E820_ORIGINAL_MAP) {
   454          e820_map = g_e820_map;
   455      }
   456      VMM_LOG(mask_anonymous, level_trace,"\nE820 Memory Map\n");
   457      VMM_LOG(mask_anonymous, level_trace,"-------------------\n");
   458      if (e820_map == NULL) {
   459          VMM_LOG(mask_anonymous, level_trace,"DOESN'T EXIST!!!\n");
   460      }
   461      num_of_entries = e820_map->memory_map_size / sizeof(e820_map->memory_map_entry[0]);
   462      for (i = 0; i < num_of_entries; i++) {
   463          INT15_E820_MEMORY_MAP_ENTRY_EXT* entry = &(e820_map->memory_map_entry[i]);
   464          VMM_LOG(mask_anonymous, level_trace,"%2d: [%P : %P] ; type = 0x%x(%8s) ; ext_attr = 0x%x\n",
   465                  i, entry->basic_entry.base_address,
   466                  entry->basic_entry.base_address + entry->basic_entry.length,
   467                  entry->basic_entry.address_range_type,
   468                  e820_get_type_name(entry->basic_entry.address_range_type),
   469                  entry->extended_attributes.uint32);
   470      }
   471      VMM_LOG(mask_anonymous, level_trace,"-------------------\n");
   472  }
   473  #endif