DevACPI.cpp revision 70118d62d01079551f31eaf0a3b2227290ddf3ee
af062818b47340eef15700d2f0211576ba3506eevboxsync * DevACPI - Advanced Configuration and Power Interface (ACPI) Device.
af062818b47340eef15700d2f0211576ba3506eevboxsync * Copyright (C) 2006-2013 Oracle Corporation
af062818b47340eef15700d2f0211576ba3506eevboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
af062818b47340eef15700d2f0211576ba3506eevboxsync * available from http://www.virtualbox.org. This file is free software;
af062818b47340eef15700d2f0211576ba3506eevboxsync * you can redistribute it and/or modify it under the terms of the GNU
af062818b47340eef15700d2f0211576ba3506eevboxsync * General Public License (GPL) as published by the Free Software
af062818b47340eef15700d2f0211576ba3506eevboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
af062818b47340eef15700d2f0211576ba3506eevboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
af062818b47340eef15700d2f0211576ba3506eevboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
af062818b47340eef15700d2f0211576ba3506eevboxsync/*******************************************************************************
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsync* Header Files *
b955672b950093ff7416d1269dd4d3b69983bd8fvboxsync*******************************************************************************/
af062818b47340eef15700d2f0211576ba3506eevboxsync#endif /* IN_RING3 */
af062818b47340eef15700d2f0211576ba3506eevboxsync/*******************************************************************************
af062818b47340eef15700d2f0211576ba3506eevboxsync* Defined Constants And Macros *
af062818b47340eef15700d2f0211576ba3506eevboxsync*******************************************************************************/
af062818b47340eef15700d2f0211576ba3506eevboxsync/** Locks the device state, ring-3 only. */
af062818b47340eef15700d2f0211576ba3506eevboxsync int rcLock = PDMCritSectEnter(&(a_pThis)->CritSect, VERR_IGNORED); \
af062818b47340eef15700d2f0211576ba3506eevboxsync } while (0)
af062818b47340eef15700d2f0211576ba3506eevboxsync/** Unlocks the device state (all contexts). */
af062818b47340eef15700d2f0211576ba3506eevboxsync do { PDMCritSectLeave(&(a_pThis)->CritSect); } while (0)
af062818b47340eef15700d2f0211576ba3506eevboxsync/* Default base for PM PIIX4 device */
af062818b47340eef15700d2f0211576ba3506eevboxsync/* Port offsets in PM device */
af062818b47340eef15700d2f0211576ba3506eevboxsync/* PM1x status register bits */
af062818b47340eef15700d2f0211576ba3506eevboxsync#define RSR1_STS (RT_BIT(1) | RT_BIT(2) | RT_BIT(3))
af062818b47340eef15700d2f0211576ba3506eevboxsync#define RSR3_STS (RT_BIT(12) | RT_BIT(13) | RT_BIT(14))
af062818b47340eef15700d2f0211576ba3506eevboxsync/* PM1x enable register bits */
af062818b47340eef15700d2f0211576ba3506eevboxsync#define RSR1_EN (RT_BIT(1) | RT_BIT(2) | RT_BIT(3) | RT_BIT(4))
af062818b47340eef15700d2f0211576ba3506eevboxsync#define RSR3_EN (RT_BIT(11) | RT_BIT(12) | RT_BIT(13) | RT_BIT(14) | RT_BIT(15))
af062818b47340eef15700d2f0211576ba3506eevboxsync/* PM1x control register bits */
af062818b47340eef15700d2f0211576ba3506eevboxsync#define RSR1_CNT (RT_BIT(3) | RT_BIT(4) | RT_BIT(5) | RT_BIT(6) | RT_BIT(7) | RT_BIT(8))
af062818b47340eef15700d2f0211576ba3506eevboxsync BAT_STATUS_PRESENT_RATE = 0x01, /**< BST battery present rate */
af062818b47340eef15700d2f0211576ba3506eevboxsync BAT_STATUS_REMAINING_CAPACITY = 0x02, /**< BST battery remaining capacity */
af062818b47340eef15700d2f0211576ba3506eevboxsync BAT_STATUS_PRESENT_VOLTAGE = 0x03, /**< BST battery present voltage */
af062818b47340eef15700d2f0211576ba3506eevboxsync BAT_INFO_DESIGN_CAPACITY = 0x05, /**< BIF design capacity */
af062818b47340eef15700d2f0211576ba3506eevboxsync BAT_INFO_LAST_FULL_CHARGE_CAPACITY = 0x06, /**< BIF last full charge capacity */
af062818b47340eef15700d2f0211576ba3506eevboxsync BAT_INFO_TECHNOLOGY = 0x07, /**< BIF battery technology */
af062818b47340eef15700d2f0211576ba3506eevboxsync BAT_INFO_DESIGN_VOLTAGE = 0x08, /**< BIF design voltage */
af062818b47340eef15700d2f0211576ba3506eevboxsync BAT_INFO_DESIGN_CAPACITY_OF_WARNING = 0x09, /**< BIF design capacity of warning */
af062818b47340eef15700d2f0211576ba3506eevboxsync BAT_INFO_DESIGN_CAPACITY_OF_LOW = 0x0A, /**< BIF design capacity of low */
af062818b47340eef15700d2f0211576ba3506eevboxsync BAT_INFO_CAPACITY_GRANULARITY_1 = 0x0B, /**< BIF battery capacity granularity 1 */
af062818b47340eef15700d2f0211576ba3506eevboxsync BAT_INFO_CAPACITY_GRANULARITY_2 = 0x0C, /**< BIF battery capacity granularity 2 */
af062818b47340eef15700d2f0211576ba3506eevboxsync BAT_DEVICE_STATUS = 0x0D, /**< STA device status */
af062818b47340eef15700d2f0211576ba3506eevboxsync CPU_EVENT_TYPE_REMOVE = 0x03 /**< Event type remove */
af062818b47340eef15700d2f0211576ba3506eevboxsync SYSTEM_INFO_INDEX_CPU0_STATUS = 5, /**< For compatibility with older saved states. */
af062818b47340eef15700d2f0211576ba3506eevboxsync SYSTEM_INFO_INDEX_CPU1_STATUS = 6, /**< For compatibility with older saved states. */
af062818b47340eef15700d2f0211576ba3506eevboxsync SYSTEM_INFO_INDEX_CPU2_STATUS = 7, /**< For compatibility with older saved states. */
af062818b47340eef15700d2f0211576ba3506eevboxsync SYSTEM_INFO_INDEX_CPU3_STATUS = 8, /**< For compatibility with older saved states. */
af062818b47340eef15700d2f0211576ba3506eevboxsync SYSTEM_INFO_INDEX_CPU_LOCKED = 11, /**< Contains a flag indicating whether the CPU is locked or not */
af062818b47340eef15700d2f0211576ba3506eevboxsync SYSTEM_INFO_INDEX_CPU_LOCK_CHECK = 12, /**< For which CPU the lock status should be checked */
af062818b47340eef15700d2f0211576ba3506eevboxsync SYSTEM_INFO_INDEX_CPU_EVENT_TYPE = 13, /**< Type of the CPU hot-plug event */
af062818b47340eef15700d2f0211576ba3506eevboxsync SYSTEM_INFO_INDEX_CPU_EVENT = 14, /**< The CPU id the event is for */
af062818b47340eef15700d2f0211576ba3506eevboxsync SYSTEM_INFO_INDEX_NIC_ADDRESS = 15, /**< NIC PCI address, or 0 */
af062818b47340eef15700d2f0211576ba3506eevboxsync SYSTEM_INFO_INDEX_AUDIO_ADDRESS = 16, /**< Audio card PCI address, or 0 */
af062818b47340eef15700d2f0211576ba3506eevboxsync SYSTEM_INFO_INDEX_IOC_ADDRESS = 18, /**< IO controller PCI address */
af062818b47340eef15700d2f0211576ba3506eevboxsync SYSTEM_INFO_INDEX_HBC_ADDRESS = 19, /**< host bus controller PCI address */
af062818b47340eef15700d2f0211576ba3506eevboxsync SYSTEM_INFO_INDEX_PCI_BASE = 20, /**< PCI bus MCFG MMIO range base */
af062818b47340eef15700d2f0211576ba3506eevboxsync SYSTEM_INFO_INDEX_PCI_LENGTH = 21, /**< PCI bus MCFG MMIO range length */
af062818b47340eef15700d2f0211576ba3506eevboxsync#define STA_DEVICE_PRESENT_MASK RT_BIT(0) /**< present */
af062818b47340eef15700d2f0211576ba3506eevboxsync#define STA_DEVICE_ENABLED_MASK RT_BIT(1) /**< enabled and decodes its resources */
typedef struct ACPIState
bool fUseFdc;
bool fUseHpet;
bool fUseSmc;
bool fPowerButtonHandled;
bool fShowCpu;
bool fShowRtc;
bool fGCEnabled;
bool fR0Enabled;
bool fCpuHotPlug;
bool fUseMcfg;
bool fS1Enabled;
bool fS4Enabled;
bool fSuspendToSavedState;
bool fSetWakeupOnResume;
bool fUseCust;
} ACPIState;
struct ACPIGENADDR
struct ACPITBLRSDP
struct ACPITBLHEADER
struct ACPITBLRSDT
struct ACPITBLXSDT
struct ACPITBLFADT
#define GPE1_BLK_LEN 0
#define GPE1_BASE 0
struct ACPITBLFACS
struct ACPITBLLAPIC
struct ACPITBLIOAPIC
struct ACPITBLISO
struct ACPITBLHPET
typedef struct ACPITBLMCFG
} ACPITBLMCFG;
typedef struct ACPITBLMCFGENTRY
struct ACPITBLCUST
#pragma pack()
PDMBOTHCBDECL(int) acpiPMTmrRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
#ifdef IN_RING3
#ifdef IN_RING3
return rc;
int rc;
LogRel(("ACPI: PDMDevHlpVMSuspendSaveAndPowerOff is not supported, falling back to suspend-only\n"));
return rc;
Log(("acpiR3Port_PowerButtonPress: handled=%d status=%x\n", pThis->fPowerButtonHandled, pThis->pm1a_sts));
return VINF_SUCCESS;
static DECLCALLBACK(int) acpiR3Port_GetPowerButtonHandled(PPDMIACPIPORT pInterface, bool *pfHandled)
return VINF_SUCCESS;
static DECLCALLBACK(int) acpiR3Port_GetGuestEnteredACPIMode(PPDMIACPIPORT pInterface, bool *pfEntered)
return VINF_SUCCESS;
static DECLCALLBACK(int) acpiR3Port_GetCpuStatus(PPDMIACPIPORT pInterface, unsigned uCpu, bool *pfLocked)
return VINF_SUCCESS;
return VINF_SUCCESS;
int rc;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
int rc;
return fPresent
return AC_ONLINE;
PDMBOTHCBDECL(int) acpiR3BatIndexWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiR3BatDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
return VERR_IOM_IOPORT_UNUSED;
case BAT_STATUS_STATE:
case BAT_STATUS_PRESENT_RATE:
case BAT_INFO_UNITS:
case BAT_INFO_DESIGN_CAPACITY:
case BAT_INFO_TECHNOLOGY:
case BAT_INFO_DESIGN_VOLTAGE:
case BAT_DEVICE_STATUS:
case BAT_POWER_SOURCE:
rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u idx=%u\n", cb, Port, pThis->uBatteryIndex);
return rc;
PDMBOTHCBDECL(int) acpiR3SysInfoIndexWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiR3SysInfoDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
return VERR_IOM_IOPORT_UNUSED;
switch (uSystemInfoIndex)
rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "CPU lock check protocol violation (idCpuLockCheck=%#x)\n",
case SYSTEM_INFO_INDEX_END:
*pu32 = 0;
rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u idx=%u\n", cb, Port, pThis->uBatteryIndex);
return rc;
PDMBOTHCBDECL(int) acpiR3SysInfoDataWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
return PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x idx=%u\n", cb, Port, u32, pThis->uSystemInfoIndex);
case SYSTEM_INFO_INDEX_VALID:
rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "cb=%d Port=%u u32=%#x idx=%u\n", cb, Port, u32, pThis->uSystemInfoIndex);
return rc;
PDMBOTHCBDECL(int) acpiR3Pm1aEnRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
return VERR_IOM_IOPORT_UNUSED;
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiR3PM1aEnWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiR3Pm1aStsRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiR3PM1aStsWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
pThis->fPowerButtonHandled = true; /* Remember that the guest handled the last power button event */
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiR3Pm1aCtlRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiR3PM1aCtlWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
switch (uSleepState)
rc = PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "Unknown sleep state %#x (u32=%#x)\n", uSleepState, u32);
return rc;
PDMBOTHCBDECL(int) acpiPMTmrRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
return VERR_IOM_IOPORT_UNUSED;
*pu32 = ASMMultU64ByU32DivByU32(u64Elapsed, PM_TMR_FREQ, TMTimerGetFreq(pThis->CTX_SUFF(pPmTimer)));
return rc;
#ifdef IN_RING3
PDMBOTHCBDECL(int) acpiR3Gpe0StsRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiR3Gpe0StsWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiR3Gpe0EnRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiR3Gpe0EnWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiR3SmiWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiR3ResetWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
return rc;
# ifdef DEBUG_ACPI
PDMBOTHCBDECL(int) acpiR3DhexWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
switch (cb)
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiR3DchrWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
switch (cb)
return VINF_SUCCESS;
rc = PDMDevHlpIOPortRegister(pThis->pDevIns, acpiR3CalcPmPort(pThis, offset), cnt, pThis, writer, reader, \
return rc; \
#undef L
#undef R
return rc;
U(GPE0_OFFSET + L, L);
U(GPE0_OFFSET, L);
#undef L
#undef U
return VINF_SUCCESS;
return rc;
return rc;
return rc;
return VINF_SUCCESS;
static DECLCALLBACK(int) acpiR3LoadState(PPDMDEVINS pDevIns, PSSMHANDLE pSSMHandle, uint32_t uVersion, uint32_t uPass)
return rc;
switch (uVersion)
return rc;
return rc;
return rc;
return rc;
return NULL;
return -uSum;
DECLINLINE(void) acpiR3PhysCopy(ACPIState *pThis, RTGCPHYS32 GCPhys32Dst, const void *pvSrc, size_t cbToCopy)
static int acpiR3SetupRsdt(ACPIState *pThis, RTGCPHYS32 addr, unsigned int nb_entries, uint32_t *addrs)
if (!rsdt)
for (unsigned int i = 0; i < nb_entries; ++i)
return VINF_SUCCESS;
static int acpiR3SetupXsdt(ACPIState *pThis, RTGCPHYS32 addr, unsigned int nb_entries, uint32_t *addrs)
if (!xsdt)
return VERR_NO_TMP_MEMORY;
acpiR3PrepareHeader(pThis, &xsdt->header, "XSDT", (uint32_t)size, 1 /* according to ACPI 3.0 specs */);
for (unsigned int i = 0; i < nb_entries; ++i)
return VINF_SUCCESS;
static void acpiR3SetupRsdp(ACPIState *pThis, ACPITBLRSDP *rsdp, RTGCPHYS32 GCPhysRsdt, RTGCPHYS GCPhysXsdt)
class AcpiTableMadt
return m_pbData;
lapic++;
} tbl;
int rc;
RTGCPHYS32 GCPhysCur, GCPhysRsdt, GCPhysXsdt, GCPhysFadtAcpi1, GCPhysFadtAcpi2, GCPhysFacs, GCPhysDsdt;
/* Note: This is also enforced by DevPcBios.cpp. */
GCPhysCur = 0;
GCPhysCur = RT_ALIGN_32(GCPhysCur + AcpiTableMadt::sizeFor(pThis, NUMBER_OF_IRQ_SOURCE_OVERRIDES), 16);
return rc;
return rc;
Log(("FACS 0x%08X FADT (1.0) 0x%08X, FADT (2+) 0x%08X\n", GCPhysFacs + addend, GCPhysFadtAcpi1 + addend, GCPhysFadtAcpi2 + addend));
acpiR3SetupRsdp(pThis, (ACPITBLRSDP *)pThis->au8RSDPPage, GCPhysRsdt + addend, GCPhysXsdt + addend);
acpiR3SetupFadt(pThis, GCPhysFadtAcpi1 + addend, GCPhysFadtAcpi2 + addend, GCPhysFacs + addend, GCPhysDsdt + addend);
return rc;
static DECLCALLBACK(uint32_t) acpiR3PciConfigRead(PPCIDEVICE pPciDev, uint32_t Address, unsigned cb)
static DECLCALLBACK(void) acpiR3PciConfigWrite(PPCIDEVICE pPciDev, uint32_t Address, uint32_t u32Value, unsigned cb)
Log(("acpi: ignore interrupt line settings: %d, we'll use hardcoded value %d\n", u32Value, SCI_INT));
return rc;
return VINF_SUCCESS;
rc = CFGMR3QueryU32Def(pThis->pDevIns->pCfg, "AcpiCreatorRev", &pThis->u32CreatorRev, RT_H2LE_U32(0x61));
char *pszCustBinFile;
else if (!*pszCustBinFile)
if (pszCustBinFile)
LogRel(("Reading custom ACPI table from file '%s' (%d bytes)\n", pszCustBinFile, pThis->cbCustBin));
if (!GCPhysRsdp)
return rc;
return rc;
return rc;
return rc; \
#ifdef DEBUG_ACPI
#undef R
return rc;
return rc;
return rc;
sizeof(ACPIState),
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,