PDMAll.cpp revision 4915cd7ab1f70c7024219733e5536270b2a9d9de
/* $Id$ */
/** @file
* PDM Critical Sections
*/
/*
* Copyright (C) 2006-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#define LOG_GROUP LOG_GROUP_PDM
#include "PDMInternal.h"
#include "PDMInline.h"
/**
* Gets the pending interrupt.
*
* @returns VBox status code.
* @param pVCpu Pointer to the VMCPU.
* @param pu8Interrupt Where to store the interrupt on success.
*/
{
/*
* The local APIC has a higher priority than the PIC.
*/
{
int i = pVM->pdm.s.Apic.CTX_SUFF(pfnGetInterrupt)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns), pVCpu->idCpu, &uTagSrc);
if (i >= 0)
{
*pu8Interrupt = (uint8_t)i;
return VINF_SUCCESS;
}
}
/*
* Check the PIC.
*/
{
if (i >= 0)
{
*pu8Interrupt = (uint8_t)i;
return VINF_SUCCESS;
}
}
/** @todo Figure out exactly why we can get here without anything being set. (REM) */
return VERR_NO_DATA;
}
/**
* Sets the pending interrupt coming from ISA source or HPET.
*
* @returns VBox status code.
* @param pVM Pointer to the VM.
* @param u8Irq The IRQ line.
* @param u8Level The new level.
* @param uTagSrc The IRQ tag and source tracer ID.
*/
{
/** @todo put the IRQ13 code elsewhere to avoid this unnecessary bloat. */
{
if (u8Level == PDM_IRQ_LEVEL_HIGH)
else
}
int rc = VERR_PDM_NO_PIC_INSTANCE;
{
rc = VINF_SUCCESS;
}
{
/*
* Apply Interrupt Source Override rules.
* See ACPI 4.0 specification 5.2.12.4 and 5.2.12.5 for details on
* interrupt source override.
* Shortly, ISA IRQ0 is electically connected to pin 2 on IO-APIC, and some OSes,
* notably recent OS X rely upon this configuration.
* If changing, also update override rules in MADT and MPS.
*/
/* ISA IRQ0 routed to pin 2, all others ISA sources are identity mapped */
if (u8Irq == 0)
u8Irq = 2;
pVM->pdm.s.IoApic.CTX_SUFF(pfnSetIrq)(pVM->pdm.s.IoApic.CTX_SUFF(pDevIns), u8Irq, u8Level, uTagSrc);
rc = VINF_SUCCESS;
}
return rc;
}
/**
* Sets the pending I/O APIC interrupt.
*
* @returns VBox status code.
* @param pVM Pointer to the VM.
* @param u8Irq The IRQ line.
* @param u8Level The new level.
* @param uTagSrc The IRQ tag and source tracer ID.
*/
{
{
pVM->pdm.s.IoApic.CTX_SUFF(pfnSetIrq)(pVM->pdm.s.IoApic.CTX_SUFF(pDevIns), u8Irq, u8Level, uTagSrc);
return VINF_SUCCESS;
}
return VERR_PDM_NO_PIC_INSTANCE;
}
/**
* Send a MSI to an I/O APIC.
*
* @returns VBox status code.
* @param pVM Pointer to the VM.
* @param GCAddr Request address.
* @param u8Value Request value.
* @param uTagSrc The IRQ tag and source tracer ID.
*/
{
{
pVM->pdm.s.IoApic.CTX_SUFF(pfnSendMsi)(pVM->pdm.s.IoApic.CTX_SUFF(pDevIns), GCAddr, uValue, uTagSrc);
return VINF_SUCCESS;
}
return VERR_PDM_NO_PIC_INSTANCE;
}
/**
* Returns presence of an IO-APIC
*
* @returns VBox true if IO-APIC is present
* @param pVM Pointer to the VM.
*/
{
}
/**
* Returns presence of an IO-APIC
*
* @returns VBox true if IO-APIC is present
* @param pVM Pointer to the VM.
*/
{
}
/**
* Set the APIC base.
*
* @returns VBox status code.
* @param pVM Pointer to the VMCPU.
* @param u64Base The new base.
*/
{
{
/* Update CPUM's copy of the APIC base. */
pCtx->msrApicBase = pVM->pdm.s.Apic.CTX_SUFF(pfnGetBase)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns), pVCpu->idCpu);
return VINF_SUCCESS;
}
return VERR_PDM_NO_APIC_INSTANCE;
}
/**
* Get the APIC base from the APIC device. This is slow and involves
* taking the PDM lock, this is currently only used by CPUM to cache the APIC
* PDMApicGetBase() and not this function.
*
* @returns VBox status code.
* @param pVM Pointer to the VMCPU.
* @param pu64Base Where to store the APIC base.
*/
{
{
return VINF_SUCCESS;
}
*pu64Base = 0;
return VERR_PDM_NO_APIC_INSTANCE;
}
/**
*
* @returns VINF_SUCCESS or VERR_PDM_NO_APIC_INSTANCE.
* @param pVCpu Pointer to the VMCPU.
* @param pfPending Pending state (out).
*/
{
{
*pfPending = pVM->pdm.s.Apic.CTX_SUFF(pfnHasPendingIrq)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns), pVCpu->idCpu,
NULL /* pu8PendingIrq */);
return VINF_SUCCESS;
}
return VERR_PDM_NO_APIC_INSTANCE;
}
/**
* Set the TPR (task priority register?).
*
* @returns VBox status code.
* @param pVCpu Pointer to the VMCPU.
* @param u8TPR The new TPR.
*/
{
{
return VINF_SUCCESS;
}
return VERR_PDM_NO_APIC_INSTANCE;
}
/**
* Get the TPR (task priority register).
*
* @returns VINF_SUCCESS or VERR_PDM_NO_APIC_INSTANCE.
* @param pVCpu Pointer to the VMCPU.
* @param pu8TPR Where to store the TRP.
* @param pfPending Pending interrupt state (out, optional).
* @param pu8PendingIrq Where to store the highest-priority pending IRQ
* (out, optional).
*
* @remarks No-long-jump zone!!!
*/
{
if (pApicIns)
{
/*
* Note! We don't acquire the PDM lock here as we're just reading
* information. Doing so causes massive contention as this
* function is called very often by each and every VCPU.
*/
if (pfPending)
return VINF_SUCCESS;
}
*pu8TPR = 0;
return VERR_PDM_NO_APIC_INSTANCE;
}
/**
* Write a MSR in APIC range.
*
* @returns VBox status code.
* @param pVM Pointer to the VM.
* @param iCpu Target CPU.
* @param u32Reg MSR to write.
* @param u64Value Value to write.
*/
{
{
return pVM->pdm.s.Apic.CTX_SUFF(pfnWriteMSR)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns), iCpu, u32Reg, u64Value);
}
return VERR_PDM_NO_APIC_INSTANCE;
}
/**
* Read a MSR in APIC range.
*
* @returns VBox status code.
* @param pVM Pointer to the VM.
* @param iCpu Target CPU.
* @param u32Reg MSR to read.
* @param pu64Value Value read.
*/
{
{
int rc = pVM->pdm.s.Apic.CTX_SUFF(pfnReadMSR)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns), iCpu, u32Reg, pu64Value);
return rc;
}
return VERR_PDM_NO_APIC_INSTANCE;
}
/**
* Locks PDM.
* This might call back to Ring-3 in order to deal with lock contention in GC and R3.
*
* @param pVM Pointer to the VM.
*/
{
#ifdef IN_RING3
#else
if (rc == VERR_GENERAL_FAILURE)
#endif
}
/**
* Locks PDM but don't go to ring-3 if it's owned by someone.
*
* @returns VINF_SUCCESS on success.
* @returns rc if we're in GC or R0 and can't get the lock.
* @param pVM Pointer to the VM.
* @param rc The RC to return in GC or R0 when we can't get the lock.
*/
{
}
/**
* Unlocks PDM.
*
* @param pVM Pointer to the VM.
*/
{
}
/**
* Converts ring 3 VMM heap pointer to a guest physical address
*
* @returns VBox status code.
* @param pVM Pointer to the VM.
* @param pv Ring-3 pointer.
* @param pGCPhys GC phys address (out).
*/
{
/* Don't assert here as this is called before we can catch ring-0 assertions. */
{
Log(("PDMVmmDevHeapR3ToGCPhys: pv=%p pvVMMDevHeap=%p cbVMMDevHeap=%#x\n",
return VERR_PDM_DEV_HEAP_R3_TO_GCPHYS;
}
*pGCPhys = (pVM->pdm.s.GCPhysVMMDevHeap + ((RTR3UINTPTR)pv - (RTR3UINTPTR)pVM->pdm.s.pvVMMDevHeap));
return VINF_SUCCESS;
}
/**
* Checks if the vmm device heap is enabled (== vmm device's pci region mapped)
*
* @param pVM Pointer to the VM.
*/
{
}