DevACPI.cpp revision 689a05012d7f4988aa5e320b22fd1dc3df6c7ca4
616c4e73368513b3c835881ff9f2386083afad01vboxsync * DevACPI - Advanced Configuration and Power Interface (ACPI) Device.
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync * Copyright (C) 2006-2009 Sun Microsystems, Inc.
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync * available from http://www.virtualbox.org. This file is free software;
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync * you can redistribute it and/or modify it under the terms of the GNU
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync * General Public License (GPL) as published by the Free Software
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync * additional information or have any questions.
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync/*******************************************************************************
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync* Header Files *
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync*******************************************************************************/
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync#endif /* IN_RING3 */
616c4e73368513b3c835881ff9f2386083afad01vboxsync#if defined(IN_RING3) && !defined(VBOX_DEVICE_STRUCT_TESTCASE)
616c4e73368513b3c835881ff9f2386083afad01vboxsyncint acpiPrepareDsdt(PPDMDEVINS pDevIns, void* *ppPtr, size_t *puDsdtLen);
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsyncint acpiCleanupDsdt(PPDMDEVINS pDevIns, void* pPtr);
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync#endif /* !IN_RING3 */
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync/*******************************************************************************
7f8a04081173dbe3c72bddd0ffeb237e7f9070b0vboxsync* Defined Constants And Macros *
616c4e73368513b3c835881ff9f2386083afad01vboxsync*******************************************************************************/
ecb074924ed761fe89e91113482db5b7374441b0vboxsync/* Default base for PM PIIX4 device */
ecb074924ed761fe89e91113482db5b7374441b0vboxsync/* Port offsets in PM device */
3854599844436d009da0f32760d657fc7690a5a8vboxsync/* PM1x status register bits */
616c4e73368513b3c835881ff9f2386083afad01vboxsync#define RSR1_STS (RT_BIT(1) | RT_BIT(2) | RT_BIT(3))
ecb074924ed761fe89e91113482db5b7374441b0vboxsync#define RSR3_STS (RT_BIT(12) | RT_BIT(13) | RT_BIT(14))
616c4e73368513b3c835881ff9f2386083afad01vboxsync/* PM1x enable register bits */
ecb074924ed761fe89e91113482db5b7374441b0vboxsync#define RSR1_EN (RT_BIT(1) | RT_BIT(2) | RT_BIT(3) | RT_BIT(4))
ecb074924ed761fe89e91113482db5b7374441b0vboxsync#define RSR3_EN (RT_BIT(11) | RT_BIT(12) | RT_BIT(13) | RT_BIT(14) | RT_BIT(15))
616c4e73368513b3c835881ff9f2386083afad01vboxsync/* PM1x control register bits */
ecb074924ed761fe89e91113482db5b7374441b0vboxsync#define RSR1_CNT (RT_BIT(3) | RT_BIT(4) | RT_BIT(5) | RT_BIT(6) | RT_BIT(7) | RT_BIT(8))
ecb074924ed761fe89e91113482db5b7374441b0vboxsync BAT_STATUS_PRESENT_RATE = 0x01, /**< BST battery present rate */
ecb074924ed761fe89e91113482db5b7374441b0vboxsync BAT_STATUS_REMAINING_CAPACITY = 0x02, /**< BST battery remaining capacity */
ecb074924ed761fe89e91113482db5b7374441b0vboxsync BAT_STATUS_PRESENT_VOLTAGE = 0x03, /**< BST battery present voltage */
ecb074924ed761fe89e91113482db5b7374441b0vboxsync BAT_INFO_DESIGN_CAPACITY = 0x05, /**< BIF design capacity */
ecb074924ed761fe89e91113482db5b7374441b0vboxsync BAT_INFO_LAST_FULL_CHARGE_CAPACITY = 0x06, /**< BIF last full charge capacity */
ecb074924ed761fe89e91113482db5b7374441b0vboxsync BAT_INFO_TECHNOLOGY = 0x07, /**< BIF battery technology */
ecb074924ed761fe89e91113482db5b7374441b0vboxsync BAT_INFO_DESIGN_VOLTAGE = 0x08, /**< BIF design voltage */
ecb074924ed761fe89e91113482db5b7374441b0vboxsync BAT_INFO_DESIGN_CAPACITY_OF_WARNING = 0x09, /**< BIF design capacity of warning */
ecb074924ed761fe89e91113482db5b7374441b0vboxsync BAT_INFO_DESIGN_CAPACITY_OF_LOW = 0x0A, /**< BIF design capacity of low */
ecb074924ed761fe89e91113482db5b7374441b0vboxsync BAT_INFO_CAPACITY_GRANULARITY_1 = 0x0B, /**< BIF battery capacity granularity 1 */
616c4e73368513b3c835881ff9f2386083afad01vboxsync BAT_INFO_CAPACITY_GRANULARITY_2 = 0x0C, /**< BIF battery capacity granularity 2 */
ecb074924ed761fe89e91113482db5b7374441b0vboxsync BAT_DEVICE_STATUS = 0x0D, /**< STA device status */
typedef struct ACPIState
unsigned int uBatteryIndex;
unsigned int uSystemInfoIndex;
bool fUseFdc;
bool fUseHpet;
bool fUseSmc;
bool fPowerButtonHandled;
bool fShowCpu;
bool fShowRtc;
bool fGCEnabled;
bool fR0Enabled;
bool fCpuHotPlug;
} 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 ACPITBLHPET
class AcpiTableMADT
return m_pbData;
#pragma pack()
PDMBOTHCBDECL(int) acpiPMTmrRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
#ifdef IN_RING3
PDMBOTHCBDECL(int) acpiPm1aEnRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
PDMBOTHCBDECL(int) acpiPM1aEnWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
PDMBOTHCBDECL(int) acpiPm1aStsRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
PDMBOTHCBDECL(int) acpiPM1aStsWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
PDMBOTHCBDECL(int) acpiPm1aCtlRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
PDMBOTHCBDECL(int) acpiPM1aCtlWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
PDMBOTHCBDECL(int) acpiSmiWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
PDMBOTHCBDECL(int) acpiBatIndexWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
PDMBOTHCBDECL(int) acpiBatDataRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
PDMBOTHCBDECL(int) acpiSysInfoDataRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
PDMBOTHCBDECL(int) acpiSysInfoDataWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
PDMBOTHCBDECL(int) acpiGpe0EnRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
PDMBOTHCBDECL(int) acpiGpe0EnWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
PDMBOTHCBDECL(int) acpiGpe0StsRead( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb);
PDMBOTHCBDECL(int) acpiGpe0StsWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
PDMBOTHCBDECL(int) acpiResetWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
# ifdef DEBUG_ACPI
PDMBOTHCBDECL(int) acpiDhexWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
PDMBOTHCBDECL(int) acpiDchrWrite( PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb);
#ifdef IN_RING3
return -sum;
static void acpiSetupFADT(ACPIState *s, RTGCPHYS32 GCPhysAcpi1, RTGCPHYS32 GCPhysAcpi2, RTGCPHYS32 GCPhysFacs, RTGCPHYS GCPhysDsdt)
if (s->fCpuHotPlug)
if (!rsdt)
for (unsigned int i = 0; i < nb_entries; ++i)
return VINF_SUCCESS;
if (!xsdt)
return VERR_NO_TMP_MEMORY;
for (unsigned int i = 0; i < nb_entries; ++i)
return VINF_SUCCESS;
lapic++;
if (gpe0_level(s))
if (pm1a_level(s))
return rc;
#define IACPIPORT_2_ACPISTATE(pInterface) ( (ACPIState*)((uintptr_t)pInterface - RT_OFFSETOF(ACPIState, IACPIPort)) )
s->fPowerButtonHandled = false;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
return val;
return val;
return val;
switch (uSleepState)
return acpiPowerDown(s);
return VINF_SUCCESS;
return val;
return val;
# ifndef IN_RING3
return rc;
return VINF_SUCCESS;
acpiPMTimerReset(s);
int rc;
if (!s->pDrv)
return VINF_SUCCESS;
return VINF_SUCCESS;
return VINF_SUCCESS;
int rc;
if (!s->pDrv)
return fPresent
if (!s->pDrv)
return AC_ONLINE;
PDMBOTHCBDECL(int) acpiBatIndexWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
switch (cb)
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiBatDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
switch (cb)
switch (s->uBatteryIndex)
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:
return VERR_IOM_IOPORT_UNUSED;
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiSysInfoIndexWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
switch (cb)
if (s->u8IndexShift == 0)
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiSysInfoDataRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
switch (cb)
switch (s->uSystemInfoIndex)
*pu32 = 0;
return VERR_IOM_IOPORT_UNUSED;
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiSysInfoDataWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
switch (s->uSystemInfoIndex)
s->u8IndexShift = 0;
case SYSTEM_INFO_INDEX_VALID:
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiPm1aEnRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
switch (cb)
return VERR_IOM_IOPORT_UNUSED;
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiPm1aStsRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
switch (cb)
return VERR_IOM_IOPORT_UNUSED;
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiPm1aCtlRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
switch (cb)
return VERR_IOM_IOPORT_UNUSED;
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiPM1aEnWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
switch (cb)
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiPM1aStsWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
switch (cb)
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiPM1aCtlWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
switch (cb)
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiPMTmrRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
return VINF_SUCCESS;
return VERR_IOM_IOPORT_UNUSED;
#ifdef IN_RING3
PDMBOTHCBDECL(int) acpiGpe0StsRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
switch (cb)
return VERR_IOM_IOPORT_UNUSED;
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiGpe0EnRead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t *pu32, unsigned cb)
switch (cb)
return VERR_IOM_IOPORT_UNUSED;
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiGpe0StsWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
switch (cb)
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiGpe0EnWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
switch (cb)
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiSmiWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
switch (cb)
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiResetWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
switch (cb)
return VINF_SUCCESS;
#ifdef DEBUG_ACPI
PDMBOTHCBDECL(int) acpiDhexWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
switch (cb)
return VINF_SUCCESS;
PDMBOTHCBDECL(int) acpiDchrWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT Port, uint32_t u32, unsigned cb)
switch (cb)
return VINF_SUCCESS;
rc = PDMDevHlpIOPortRegister(pThis->pDevIns, acpiPmPort(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;
switch (uVersion)
return rc;
return rc;
return rc;
return rc;
return rc;
return NULL;
int rc;
RTGCPHYS32 GCPhysCur, GCPhysRsdt, GCPhysXsdt, GCPhysFadtAcpi1, GCPhysFadtAcpi2, GCPhysFacs, GCPhysDsdt;
if (s->u8UseIOApic)
if (s->fUseHpet)
rc = CFGMR3QueryU32Def(s->pDevIns->pCfgHandle, "RamHoleSize", &cbRamHole, MM_RAM_HOLE_SIZE_DEFAULT);
/* Note: This is also enforced by DevPcBios.cpp. */
GCPhysCur = 0;
if (s->u8UseIOApic)
if (s->fUseHpet)
return rc;
Log(("FACS 0x%08X FADT (1.0) 0x%08X, FADT (2+) 0x%08X\n", GCPhysFacs + addend, GCPhysFadtAcpi1 + addend, GCPhysFadtAcpi2 + addend));
if (s->u8UseIOApic)
if (s->fUseHpet)
acpiSetupFADT(s, GCPhysFadtAcpi1 + addend, GCPhysFadtAcpi2 + addend, GCPhysFacs + addend, GCPhysDsdt + addend);
if (s->u8UseIOApic)
if (s->fUseHpet)
return rc;
int rc;
return rc;
return rc;
return rc;
return VINF_SUCCESS;
static void acpiPciConfigWrite(PPCIDEVICE pPciDev, uint32_t Address, uint32_t u32Value, unsigned cb)
int rc;
return VINF_SUCCESS;
return rc;
AssertMsgReturnVoid(!(VMCPUSET_IS_PRESENT(&s->CpuSetLocked, iLUN)), ("CPU is still locked by the guest\n"));
s->pm1a_en = 0;
s->pm1a_sts = 0;
s->pm1a_ctl = 0;
acpiPMTimerReset(s);
s->uBatteryIndex = 0;
s->uSystemInfoIndex = 0;
s->gpe0_en = 0;
s->gpe0_sts = 0;
s->uSleepState = 0;
acpiPlantTables(s);
s->fGCEnabled = true;
s->fR0Enabled = true;
if (s->fCpuHotPlug)
if (s->fUseSmc)
s->fUseFdc = false;
if (!GCPhysRsdp)
return rc;
return rc;
return rc;
return rc; \
#ifdef DEBUG_ACPI
#undef R
return rc;
acpiPMTimerReset(s);
return rc;
return rc;
if (!s->pDrv)
return rc;
sizeof(ACPIState),
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,