void vt_ept_violation (bool write, u64 gphys) { static int count = 0; mmio_lock (); #ifdef CONFIG_SSLAB { U64_t index; struct memory_ownership_table_entry_t entry; HPA_t hpa = gpaToHPA(gphys, 0); if(hpa) { index = getMemoryOwnershipTableIndex(hpa); entry = getMemoryOwnershipTableEntry(index); if(entry.state == CLOSED) { printf("SSLAB : closed\n"); } mmio_unlock (); return; } } #endif if (!mmio_access_page (gphys, true)) vt_ept_map_page (write, gphys); mmio_unlock (); }
void read_gphys_b (u64 phys, void *data, u32 attr) { attr = cache_get_attr (phys, attr); mmio_lock (); if (!mmio_access_memory (phys, false, data, 1, attr)) { phys = current->gmm.gp2hp (phys, NULL); read_hphys_b (phys, data, attr); } mmio_unlock (); }
void vt_ept_map_1mb (void) { ulong gphys; vt_ept_clear_all (); for (gphys = 0; gphys < 0x100000; gphys += PAGESIZE) { mmio_lock (); if (!mmio_access_page (gphys, false)) vt_ept_map_page (false, gphys); mmio_unlock (); } }
void write_gphys_b (u64 phys, u32 data, u32 attr) { bool fakerom; attr = cache_get_attr (phys, attr); mmio_lock (); if (!mmio_access_memory (phys, true, &data, 1, attr)) { phys = current->gmm.gp2hp (phys, &fakerom); if (fakerom) panic ("write_gphys_b modifying VMM memory."); write_hphys_b (phys, data, attr); } mmio_unlock (); }
void read_gphys_w (u64 phys, void *data, u32 attr) { if ((phys & 0xFFF) == 0xFFF) { read_gphys_b (phys + 0, ((u8 *)data) + 0, attr); read_gphys_b (phys + 1, ((u8 *)data) + 1, attr); return; } attr = cache_get_attr (phys, attr); mmio_lock (); if (!mmio_access_memory (phys, false, data, 2, attr)) { phys = current->gmm.gp2hp (phys, NULL); read_hphys_w (phys, data, attr); } mmio_unlock (); }
bool cmpxchg_gphys_q (u64 phys, u64 *olddata, u64 data, u32 attr) { bool fakerom; if ((phys & 0xFFF) >= 0xFF9) panic ("cmpxchg_gphys_q: bad physical address"); attr = cache_get_attr (phys, attr); mmio_lock (); if (mmio_access_memory (phys, false, olddata, 8, attr)) panic ("CMPXCHG MMIO!"); mmio_unlock (); phys = current->gmm.gp2hp (phys, &fakerom); if (fakerom) panic ("cmpxchg_gphys_q modifying VMM memory."); return cmpxchg_hphys_q (phys, olddata, data, attr); }
void write_gphys_w (u64 phys, u32 data, u32 attr) { bool fakerom; if ((phys & 0xFFF) == 0xFFF) { write_gphys_b (phys + 0, *(((u8 *)&data) + 0), attr); write_gphys_b (phys + 1, *(((u8 *)&data) + 1), attr); return; } attr = cache_get_attr (phys, attr); mmio_lock (); if (!mmio_access_memory (phys, true, &data, 2, attr)) { phys = current->gmm.gp2hp (phys, &fakerom); if (fakerom) panic ("write_gphys_w modifying VMM memory."); write_hphys_w (phys, data, attr); } mmio_unlock (); }
/* Microcode updates cannot be loaded in VMX non-root operation on * Intel CPUs. This function loads the updates in VMX root * operation. */ static bool ia32_bios_updt (virt_t addr) { u64 vmm_addr = PAGESIZE | (addr & PAGESIZE_MASK); phys_t phys, mm_phys; struct msrarg m; int num; ulong cr2, lastcr2 = 0, guest_addr; int levels; enum vmmerr r; u64 entries[5]; u64 efer; ulong cr0, cr3, cr4; phys_t hphys, gphys; int in_mmio_range; bool ret = false; m.msrindex = MSR_IA32_BIOS_UPDT_TRIG; m.msrdata = &vmm_addr; current->vmctl.read_control_reg (CONTROL_REG_CR0, &cr0); current->vmctl.read_control_reg (CONTROL_REG_CR3, &cr3); current->vmctl.read_control_reg (CONTROL_REG_CR4, &cr4); current->vmctl.read_msr (MSR_IA32_EFER, &efer); if (0) printf ("CPU%d: old IA32_BIOS_SIGN_ID %016llX\n", get_cpu_id (), get_ia32_bios_sign_id ()); /* Allocate an empty page directory for address 0-0x3FFFFFFF * and switch to it. */ if (mm_process_alloc (&phys) < 0) panic ("%s: mm_process_alloc failed", __func__); mm_phys = mm_process_switch (phys); for (;;) { /* Do update! */ num = callfunc_and_getint (do_write_msr_sub, &m); if (num == -1) /* Success */ break; if (num == EXCEPTION_GP) { ret = true; break; } if (num != EXCEPTION_PF) panic ("%s: exception %d", __func__, num); /* Handle a page fault. Get the guest physical * address of the page. */ /* FIXME: Set access bit in PTE */ asm_rdcr2 (&cr2); if (lastcr2 == cr2) /* check to avoid infinite loop */ panic ("%s: second page fault at 0x%lX", __func__, cr2); else lastcr2 = cr2; guest_addr = (addr & ~PAGESIZE_MASK) + (cr2 - PAGESIZE); r = cpu_mmu_get_pte (guest_addr, cr0, cr3, cr4, efer, false, false, false, entries, &levels); if (r == VMMERR_PAGE_NOT_PRESENT) { ret = true; if (0) printf ("%s: guest page fault at 0x%lX\n", __func__, guest_addr); current->vmctl.generate_pagefault (0, guest_addr); break; } if (r != VMMERR_SUCCESS) panic ("%s: cpu_mmu_get_pte failed %d", __func__, r); gphys = entries[0] & current->pte_addr_mask; /* Find MMIO hooks. */ mmio_lock (); in_mmio_range = mmio_access_page (gphys, false); mmio_unlock (); if (in_mmio_range) panic ("%s: mmio check failed cr2=0x%lX ent=0x%llX", __func__, cr2, entries[0]); /* Convert the address and map it. */ /* FIXME: Handle cache flags in the PTE. */ hphys = current->gmm.gp2hp (gphys, NULL); ASSERT (!(hphys & PAGESIZE_MASK)); if (mm_process_map_shared_physpage (cr2, hphys, false)) panic ("%s: mm_process_map_shared_physpage failed" " cr2=0x%lX guest=0x%lX ent=0x%llX", __func__, cr2, guest_addr, entries[0]); if (0) printf ("%s: cr2=0x%lX guest=0x%lX ent=0x%llX\n", __func__, cr2, guest_addr, entries[0]); } /* Free page tables, switch to previous address space and free * the page directory. */ mm_process_unmapall (); mm_process_switch (mm_phys); mm_process_free (phys); if (0) printf ("CPU%d: new IA32_BIOS_SIGN_ID %016llX\n", get_cpu_id (), get_ia32_bios_sign_id ()); return ret; }