119 lines
4.0 KiB
C++
119 lines
4.0 KiB
C++
/////////////////////////////////////////////////////////////////////////
|
|
// $Id$
|
|
/////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Copyright (c) 2012 Stanislav Shwartsman
|
|
// Written by Stanislav Shwartsman [sshwarts at sourceforge net]
|
|
//
|
|
// This library is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU Lesser General Public
|
|
// License as published by the Free Software Foundation; either
|
|
// version 2 of the License, or (at your option) any later version.
|
|
//
|
|
// This library is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
// Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public
|
|
// License along with this library; if not, write to the Free Software
|
|
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA B 02110-1301 USA
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////
|
|
|
|
#define NEED_CPU_REG_SHORTCUTS 1
|
|
#include "bochs.h"
|
|
#include "cpu.h"
|
|
#define LOG_THIS BX_CPU_THIS_PTR
|
|
|
|
#if BX_SUPPORT_VMX && BX_SUPPORT_X86_64
|
|
|
|
bx_bool BX_CPP_AttrRegparmN(1) BX_CPU_C::is_virtual_apic_page(bx_phy_address paddr)
|
|
{
|
|
if (BX_CPU_THIS_PTR in_vmx_guest) {
|
|
VMCS_CACHE *vm = &BX_CPU_THIS_PTR vmcs;
|
|
if (SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_VIRTUALIZE_APIC_ACCESSES))
|
|
if (PPFOf(paddr) == PPFOf(vm->apic_access_page)) return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
Bit32u BX_CPU_C::VMX_Read_Virtual_APIC(unsigned offset)
|
|
{
|
|
bx_phy_address pAddr = BX_CPU_THIS_PTR vmcs.virtual_apic_page_addr + offset;
|
|
Bit32u field32;
|
|
access_read_physical(pAddr, 4, (Bit8u*)(&field32));
|
|
BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 4, BX_READ, BX_VMX_VAPIC_ACCESS, (Bit8u*)(&field32));
|
|
return field32;
|
|
}
|
|
|
|
void BX_CPU_C::VMX_Write_Virtual_APIC(unsigned offset, Bit32u val32)
|
|
{
|
|
bx_phy_address pAddr = BX_CPU_THIS_PTR vmcs.virtual_apic_page_addr + offset;
|
|
access_write_physical(pAddr, 4, (Bit8u*)(&val32));
|
|
BX_NOTIFY_PHY_MEMORY_ACCESS(pAddr, 4, BX_WRITE, BX_VMX_VAPIC_ACCESS, (Bit8u*)(&val32));
|
|
}
|
|
|
|
void BX_CPU_C::VMX_Write_VTPR(Bit8u vtpr)
|
|
{
|
|
VMX_Write_Virtual_APIC(BX_LAPIC_TPR, vtpr);
|
|
|
|
signal_event(BX_EVENT_VMX_VTPR_UPDATE);
|
|
}
|
|
|
|
void BX_CPU_C::VMX_Virtual_Apic_Read(bx_phy_address paddr, unsigned len, void *data)
|
|
{
|
|
BX_ASSERT(SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_VIRTUALIZE_APIC_ACCESSES));
|
|
|
|
Bit32u offset = PAGE_OFFSET(paddr);
|
|
|
|
// access is not instruction fetch because cpu::prefetch will crash them
|
|
if (VMEXIT(VMX_VM_EXEC_CTRL2_TPR_SHADOW) && offset == BX_LAPIC_TPR && len <= 4) {
|
|
// VTPR access
|
|
Bit32u vtpr = VMX_Read_Virtual_APIC(BX_LAPIC_TPR);
|
|
if (len == 1)
|
|
*((Bit8u *) data) = vtpr & 0xff;
|
|
else if (len == 2)
|
|
*((Bit16u *) data) = vtpr & 0xffff;
|
|
else if (len == 4)
|
|
*((Bit32u *) data) = vtpr;
|
|
else
|
|
BX_PANIC(("PANIC: Unsupported Virtual APIC access len = 3 !"));
|
|
return;
|
|
}
|
|
|
|
Bit32u qualification = offset |
|
|
((BX_CPU_THIS_PTR in_event) ? VMX_APIC_ACCESS_DURING_EVENT_DELIVERY : VMX_APIC_READ_INSTRUCTION_EXECUTION);
|
|
VMexit(VMX_VMEXIT_APIC_ACCESS, qualification);
|
|
}
|
|
|
|
void BX_CPU_C::VMX_Virtual_Apic_Write(bx_phy_address paddr, unsigned len, void *data)
|
|
{
|
|
BX_ASSERT(SECONDARY_VMEXEC_CONTROL(VMX_VM_EXEC_CTRL3_VIRTUALIZE_APIC_ACCESSES));
|
|
|
|
Bit32u offset = PAGE_OFFSET(paddr);
|
|
|
|
if (VMEXIT(VMX_VM_EXEC_CTRL2_TPR_SHADOW) && offset == BX_LAPIC_TPR && len <= 4) {
|
|
// VTPR access
|
|
VMX_Write_VTPR(*((Bit8u *) data));
|
|
return;
|
|
}
|
|
|
|
Bit32u qualification = offset |
|
|
((BX_CPU_THIS_PTR in_event) ? VMX_APIC_ACCESS_DURING_EVENT_DELIVERY : VMX_APIC_WRITE_INSTRUCTION_EXECUTION);
|
|
VMexit(VMX_VMEXIT_APIC_ACCESS, qualification);
|
|
}
|
|
|
|
void BX_CPU_C::VMX_TPR_Virtualization(void)
|
|
{
|
|
Bit8u vtpr = (Bit8u) VMX_Read_Virtual_APIC(BX_LAPIC_TPR);
|
|
|
|
Bit8u tpr_shadow = vtpr >> 4;
|
|
if (tpr_shadow < BX_CPU_THIS_PTR vmcs.vm_tpr_threshold) {
|
|
VMexit(VMX_VMEXIT_TPR_THRESHOLD, 0);
|
|
}
|
|
}
|
|
|
|
#endif // BX_SUPPORT_VMX && BX_SUPPORT_X86_64
|