static int copy_to_gva(guest_cpu_handle_t gcpu, uint64_t gva, uint32_t size, uint64_t hva) { uint64_t dst_gva = gva; uint64_t src_hva = 0; uint8_t *local_ptr = (uint8_t *)hva; uint32_t size_remaining = size; uint32_t size_copied = 0; while (size_remaining) { if (!gcpu_gva_to_hva(gcpu, dst_gva, &src_hva)) { MON_LOG(mask_mon, level_error, "%s: Invalid guest pointer address %P\n", __FUNCTION__, gva); return -1; } /* Copy until end */ if (dst_gva > (UINT64_ALL_ONES - size_remaining)) { MON_LOG(mask_mon, level_error, "Error: size bounds exceeded\n"); return -1; } if ((dst_gva + size_remaining) <= (dst_gva | PAGE_4KB_MASK)) { mon_memcpy((void *)src_hva, (void *)local_ptr, size_remaining); return 0; } else { /* Copy until end of page */ size_copied = (uint32_t) (((dst_gva + PAGE_4KB_SIZE) & ~PAGE_4KB_MASK) - dst_gva); mon_memcpy((void *)src_hva, (void *)local_ptr, size_copied); /* Adjust size and pointers for next copy */ size_remaining -= size_copied; local_ptr += size_copied; dst_gva += size_copied; } } return 0; }
boolean_t e820_abstraction_initialize(const int15_e820_memory_map_t * e820_memory_map, uint32_t int15_handler_address) { /* INT15 handling is only required for pre-OS launch and is not * required for post-OS launch */ if (!g_is_post_launch && mon_is_unrestricted_guest_supported()) { /* initialize int15 handling vectors */ update_int15_handling(int15_handler_address); } if (e820_memory_map != NULL) { uint32_t size = e820_memory_map->memory_map_size + sizeof(e820_memory_map->memory_map_size); g_e820_map = (int15_e820_memory_map_t *)mon_memory_alloc(size); if (g_e820_map == NULL) { return FALSE; } mon_memcpy(g_e820_map, e820_memory_map, size); MON_DEBUG_CODE(e820_abstraction_print_memory_map( E820_ORIGINAL_MAP)); return TRUE; } return FALSE; }
void CDECL mon_memcpy_assuming_mmio(uint8_t *dst, uint8_t *src, int32_t count) { switch (count) { case 0: break; case 1: *dst = *src; break; case 2: *(uint16_t *)dst = *(uint16_t *)src; break; case 4: *(uint32_t *)dst = *(uint32_t *)src; break; case 8: *(uint64_t *)dst = *(uint64_t *)src; break; case 16: *(uint64_t *)dst = *(uint64_t *)src; dst += sizeof(uint64_t); src += sizeof(uint64_t); *(uint64_t *)dst = *(uint64_t *)src; break; default: mon_memcpy(dst, src, count); break; } }
size_t mem_image_read(gen_image_access_t *ia, void *dest, size_t src_offset, size_t bytes_to_read) { mem_image_access_t *mia = (mem_image_access_t *)ia; if ((src_offset + bytes_to_read) > mia->size) { bytes_to_read = mia->size - src_offset; /* read no more than size */ } mon_memcpy(dest, mia->image + src_offset, bytes_to_read); return bytes_to_read; }
int copy_e820_table_from_efi(xmon_desc_t *td, uint64_t *e820_addr) { mon_guest_cpu_startup_state_t *s; int15_e820_memory_map_t *e820; void *inf; s = (mon_guest_cpu_startup_state_t *)GUEST1_BASE(td); inf = (void *)((uint32_t)(s->gp.reg[IA32_REG_RBX])); e820 = (int15_e820_memory_map_t *)mon_page_alloc(1); if (e820 == NULL) { return -1; } mon_memcpy(e820, inf, 4096); *e820_addr = (uint64_t)(uint32_t)e820; return 0; }
/* * copy e820 memory info to other address, and hide some memories in e820 table. */ boolean_t hide_runtime_memory(multiboot_info_t *mbi, uint32_t hide_mem_addr, uint32_t hide_mem_size) { uint32_t num_of_entries, entry_idx; multiboot_memory_map_t *newmmap_addr; /* Are mmap_* valid? */ if (!(mbi->flags & MBI_MEMMAP)) { return FALSE; } multiboot_memory_map_t *mmap; /* add space for two more entries for boundary case. */ num_of_entries = mbi->mmap_length / sizeof(multiboot_memory_map_t) + 2; newmmap_addr = (multiboot_memory_map_t *) allocate_memory( sizeof(multiboot_memory_map_t) * num_of_entries); if (!newmmap_addr) { return FALSE; } for (entry_idx = 0, mmap = (multiboot_memory_map_t *)mbi->mmap_addr; (unsigned long)mmap < mbi->mmap_addr + mbi->mmap_length; entry_idx++, mmap = (multiboot_memory_map_t *) ((unsigned long)mmap + mmap->size + sizeof(mmap->size))) { if (((mmap->addr + mmap->len) <= hide_mem_addr) || ((hide_mem_addr + hide_mem_size) <= mmap->addr)) { /* do not modify it */ mon_memcpy(&newmmap_addr[entry_idx], mmap, sizeof(multiboot_memory_map_t)); } else { /* input address range to be hidden needs to be of type AVAILABLE. */ if (mmap->type != MULTIBOOT_MEMORY_AVAILABLE) { print_string( "ERROR: the type of memory to hide is not AVAILABLE in e820 table!!\n"); return FALSE; } newmmap_addr[entry_idx].size = mmap->size; newmmap_addr[entry_idx].addr = mmap->addr; newmmap_addr[entry_idx].len = hide_mem_addr - mmap->addr; newmmap_addr[entry_idx].type = mmap->type; entry_idx++; newmmap_addr[entry_idx].size = mmap->size; newmmap_addr[entry_idx].addr = hide_mem_addr; newmmap_addr[entry_idx].len = hide_mem_size; newmmap_addr[entry_idx].type = MULTIBOOT_MEMORY_RESERVED; if ((hide_mem_addr + hide_mem_size) > (mmap->addr + mmap->len)) { print_string( "ERROR: hide_mem_addr+hide_mem_size crossing two E820 entries!!\n"); return FALSE; } if ((hide_mem_addr + hide_mem_size) < (mmap->addr + mmap->len)) { /* need one more entry */ entry_idx++; newmmap_addr[entry_idx].size = mmap->size; newmmap_addr[entry_idx].addr = hide_mem_addr + hide_mem_size; newmmap_addr[entry_idx].len = (mmap->addr + mmap->len) - (hide_mem_addr + hide_mem_size); newmmap_addr[entry_idx].type = mmap->type; } else { /* no need one more entry */ } } } /* update map addr and len (entry_idx, using the exact entry num value) */ mbi->mmap_addr = (uint32_t)newmmap_addr; mbi->mmap_length = sizeof(multiboot_memory_map_t) * entry_idx; /* do not use num_of_entries*/ return TRUE; }