DevAPIC.cpp revision 1167f682bad8a5c086022e181da3bb4028a20ff8
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * Advanced Programmable Interrupt Controller (APIC) Device and
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * I/O Advanced Programmable Interrupt Controller (IO-APIC) Device.
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * Copyright (C) 2006-2010 Oracle Corporation
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * available from http://www.virtualbox.org. This file is free software;
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * you can redistribute it and/or modify it under the terms of the GNU
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * General Public License (GPL) as published by the Free Software
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * --------------------------------------------------------------------
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * This code is based on:
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync * apic.c revision 1.5 @@OSETODO
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync/*******************************************************************************
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync* Header Files *
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync*******************************************************************************/
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync/** The current saved state version.*/
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync/** The saved state version used by VirtualBox v3 and earlier.
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * This does not include the config. */
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync/** Some ancient version... */
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync/* version 0x14: Pentium 4, Xeon; LVT count depends on that */
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync/** @def APIC_LOCK
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync * Acquires the PDM lock. */
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync int rc2 = PDMCritSectEnter((pThis)->CTX_SUFF(pCritSect), (rcBusy)); \
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync } while (0)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync/** @def APIC_LOCK_VOID
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * Acquires the PDM lock and does not expect failure (i.e. ring-3 only!). */
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync int rc2 = PDMCritSectEnter((pThis)->CTX_SUFF(pCritSect), (rcBusy)); \
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync } while (0)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync/** @def APIC_UNLOCK
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * Releases the PDM lock. */
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync/** @def APIC_AND_TM_LOCK
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * Acquires the virtual sync clock lock as well as the PDM lock. */
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync int rc2 = TMTimerLock((a_pAcpi)->CTX_SUFF(pTimer), (rcBusy)); \
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync rc2 = PDMCritSectEnter((a_pDev)->CTX_SUFF(pCritSect), (rcBusy)); \
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync } while (0)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync/** @def APIC_AND_TM_UNLOCK
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync * Releases the PDM lock as well as the TM virtual sync clock lock. */
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync } while (0)
9c0076729ec8138e89ce8a6af9a772b68f1f8dc7vboxsync/** @def IOAPIC_LOCK
8b98c71a5a01d215eafbc3605cb7a66cc91ea774vboxsync * Acquires the PDM lock. */
return rc2; \
uint32_t i; \
code; \
apic++; \
#define DEBUG_APIC
#define DEBUG_IOAPIC
#define APIC_LVT_TIMER 0
#define APIC_DM_FIXED 0
#define APIC_TRIGGER_EDGE 0
typedef struct APICState {
int count_shift;
bool fTimerArmed;
# ifdef VBOX_WITH_STATISTICS
} APICState;
# ifdef VBOX_WITH_STATISTICS
struct IOAPICState {
# ifdef VBOX_WITH_STATISTICS
bool fIoApic;
# ifdef VBOX_WITH_STATISTICS
# ifdef VBOX_WITH_STATISTICS
#ifndef VBOX_DEVICE_STRUCT_TESTCASE
DECLINLINE(void) cpuSetInterrupt(APICDeviceInfo* dev, APICState *s, PDMAPICIRQ enmType = PDMAPICIRQ_HARDWARE)
DECLINLINE(void) cpuClearInterrupt(APICDeviceInfo* dev, APICState *s, PDMAPICIRQ enmType = PDMAPICIRQ_HARDWARE)
# ifdef IN_RING3
vector);
case PDMAPICVERSION_NONE:
case PDMAPICVERSION_APIC:
return MSR_IA32_APICBASE_ENABLE;
case PDMAPICVERSION_X2APIC:
return PDMAPICVERSION_NONE;
return PDMAPICVERSION_NONE;
return PDMAPICVERSION_APIC;
return PDMAPICVERSION_X2APIC;
LogFlow(("apic_bus_deliver mask=%x mode=%x vector=%x polarity=%x trigger_mode=%x\n", deliver_bitmask, delivery_mode, vector_num, polarity, trigger_mode));
switch (delivery_mode) {
case APIC_DM_LOWPRI:
if (deliver_bitmask)
return VINF_SUCCESS;
case APIC_DM_FIXED:
case APIC_DM_SMI:
return VINF_SUCCESS;
case APIC_DM_NMI:
return VINF_SUCCESS;
case APIC_DM_INIT:
#ifdef IN_RING3
return VINF_SUCCESS;
return VINF_IOM_HC_MMIO_READ_WRITE;
case APIC_DM_EXTINT:
return VINF_SUCCESS;
return VINF_SUCCESS;
s->apicbase =
switch (newMode)
case PDMAPICVERSION_NONE:
case PDMAPICVERSION_APIC:
case PDMAPICVERSION_X2APIC:
return s->apicbase;
return s->tpr;
static int acpiWriteRegister(APICDeviceInfo *pDev, APICState *pApic, uint32_t iReg, uint64_t u64Value,
switch (iReg)
pApic->dest_mode = u64Value >> 28; /** @todo r=bird: range? This used to be 32-bit before morphed into an MSR handler. */
if (!fMsr)
if (fMsr)
return rc;
PDMBOTHCBDECL(int) apicWriteMSR(PPDMDEVINS pDevIns, VMCPUID idCpu, uint32_t u32Reg, uint64_t u64Value)
PDMBOTHCBDECL(int) apicReadMSR(PPDMDEVINS pDevIns, VMCPUID idCpu, uint32_t u32Reg, uint64_t *pu64Value)
return VERR_EM_INTERPRETER;
switch (index)
val = 0;
val = 0;
return rc;
LogFlow(("apicBusDeliverCallback: pDevIns=%p u8Dest=%#x u8DestMode=%#x u8DeliveryMode=%#x iVector=%#x u8Polarity=%#x u8TriggerMode=%#x\n",
if (u8Level)
return VINF_SUCCESS;
switch (u8Delivery)
case APIC_DM_EXTINT:
if (u8Level)
return VINF_SUCCESS;
case APIC_DM_NMI:
return VINF_SUCCESS;
case APIC_DM_SMI:
case APIC_DM_FIXED:
static unsigned s_c = 0;
return VINF_SUCCESS;
case APIC_DM_INIT:
static unsigned s_c = 0;
AssertLogRelMsgFailed(("delivery type %d not implemented. u8Pin=%d u8Level=%d\n", u8Delivery, u8Pin, u8Level));
return VERR_INTERNAL_ERROR_4;
return VINF_SUCCESS;
if (tab[i] != 0) {
if (isrv < 0)
isrv = 0;
return ppr;
int isrv;
if (isrv < 0)
isrv = 0;
return isrv;
if (irrv < 0)
if (!dev)
if (irrv < 0)
bool fIrqIsActive = false;
bool fIrqWasActive = false;
LogFlow(("CPU%d: apic_set_irq vector=%x, trigger_mode=%x\n", s->phys_id, vector_num, trigger_mode));
if (trigger_mode)
int isrv;
if (isrv < 0)
if (dest_mode == 0)
uint32_t i;
apic++;
return mask;
#ifdef IN_RING3
for(i = 0; i < APIC_LVT_NB; i++)
s->tpr = 0;
s->log_dest = 0;
s->esr = 0;
s->divide_conf = 0;
s->initial_count = 0;
s->initial_count_load_time = 0;
s->next_time = 0;
LogFlow(("apic_deliver dest=%x dest_mode=%x dest_shorthand=%x delivery_mode=%x vector_num=%x polarity=%x trigger_mode=%x\n", dest, dest_mode, dest_shorthand, delivery_mode, vector_num, polarity, trigger_mode));
switch (dest_shorthand) {
switch (delivery_mode) {
case APIC_DM_INIT:
return VINF_SUCCESS;
case APIC_DM_SIPI:
# ifdef IN_RING3
return VINF_SUCCESS;
return VINF_IOM_HC_MMIO_WRITE;
if (!dev)
int intno;
if (intno < 0) {
return intno;
int64_t d;
s->count_shift;
if (d >= s->initial_count)
val = 0;
return val;
uHz = 0;
static void apicTimerSetInitialCount(APICDeviceInfo *dev, APICState *pThis, uint32_t u32NewInitialCount)
&& u32NewInitialCount > 0)
Log(("apicTimerSetInitialCount: cTicksNext=%'llu (%#llx) ic=%#x sh=%#x nxt=%#llx\n", cTicksNext, cTicksNext, u32NewInitialCount, pThis->count_shift, pThis->next_time));
Log(("apicTimerSetInitialCount: ic=%#x sh=%#x iclt=%#llx\n", u32NewInitialCount, pThis->count_shift, pThis->initial_count_load_time));
uint64_t cTicks = (TMTimerGet(pThis->CTX_SUFF(pTimer)) - pThis->initial_count_load_time) >> pThis->count_shift;
NextTS = ((cTicks / ((uint64_t)pThis->initial_count + 1)) + 1) * ((uint64_t)pThis->initial_count + 1);
/* Try avoid the assertion in TM.cpp... this isn't perfect! */
Log(("apicTimerSetLvt: ic=%#x sh=%#x nxt=%#llx\n", pThis->initial_count, pThis->count_shift, pThis->next_time));
# ifdef IN_RING3
Log2(("apicTimerCallback: ic=%#x sh=%#x nxt=%#llx\n", pThis->initial_count, pThis->count_shift, pThis->next_time));
int index;
switch(index) {
val = 0;
val = 0;
#ifdef DEBUG_APIC
return val;
#ifdef IN_RING3
for (i = 0; i < APIC_LVT_NB; i++) {
switch (version_id)
s->phys_id = 0;
case APIC_SAVED_STATE_VERSION:
for (i = 0; i < APIC_LVT_NB; i++) {
if (s->fTimerArmed)
uint8_t i;
for (i = 0; i < IOAPIC_NUM_PINS; i++) {
dest,
if (level) {
ioapic_service(s);
if (level) {
ioapic_service(s);
int index;
switch (s->ioregsel) {
val = 0;
#ifdef DEBUG_IOAPIC
return val;
int index;
#ifdef DEBUG_IOAPIC
switch (s->ioregsel) {
ioapic_service(s);
#ifdef IN_RING3
for (i = 0; i < IOAPIC_NUM_PINS; i++) {
for (i = 0; i < IOAPIC_NUM_PINS; i++) {
memset(s, 0, sizeof(*s));
for(i = 0; i < IOAPIC_NUM_PINS; i++)
if (pDevIns)
if (pIoApicHlp)
PDMBOTHCBDECL(int) apicMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
switch (cb)
#ifndef IN_RING3
#ifdef IN_RC
pDevIns->pHlpR0->pfnPATMSetMMIOPatchInfo(pDevIns, GCPhysAddr, pDevIns + RT_OFFSETOF(APICState, tpr));
return VINF_PATM_HC_MMIO_PATCH_READ;
return VERR_INTERNAL_ERROR;
return VINF_SUCCESS;
PDMBOTHCBDECL(int) apicMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
switch (cb)
return VERR_INTERNAL_ERROR;
return VINF_SUCCESS;
#ifdef IN_RING3
unsigned max_lvt;
unsigned divider;
return VINF_SSM_DONT_CALL_AGAIN;
return VINF_SUCCESS;
static DECLCALLBACK(int) apicLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch - cCpus: saved=%#x config=%#x"), cCpus, pThis->cCpus);
bool fIoApic;
return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch - fIoApic: saved=%RTbool config=%RTbool"), fIoApic, pThis->fIoApic);
return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Config mismatch - uApicVersion: saved=%#x config=%#x"), uApicVersion, pThis->enmVersion);
return VINF_SUCCESS;
AssertFailed();
return VINF_SUCCESS;
/* Reset should re-enable the APIC, see comment in msi.h */
/* See comment in msi.h for LAPIC base info */
if (id == 0)
for (i = 0; i < APIC_LVT_NB; i++)
int rc;
uint32_t i;
bool fIoApic;
bool fGCEnabled;
bool fR0Enabled;
Log(("APIC: cCpus=%d fR0Enabled=%RTbool fGCEnabled=%RTbool fIoApic=%RTbool\n", cCpus, fR0Enabled, fGCEnabled, fIoApic));
rc = MMHyperAlloc(pVM, cCpus * sizeof(APICState), 1, MM_TAG_PDM_DEVICE_USER, (void **)&pThis->paLapicsR3);
return VERR_NO_MEMORY;
for (i = 0; i < cCpus; i++)
if (fGCEnabled) {
if (fR0Enabled) {
return rc;
if (fGCEnabled) {
return rc;
if (fR0Enabled) {
return rc;
for (i = 0; i < cCpus; i++) {
return rc;
return rc;
#ifdef VBOX_WITH_STATISTICS
PDMDevHlpSTAMRegister(pDevIns, &pThis->StatMMIOReadGC, STAMTYPE_COUNTER, "/Devices/APIC/MMIOReadGC", STAMUNIT_OCCURENCES, "Number of APIC MMIO reads in GC.");
PDMDevHlpSTAMRegister(pDevIns, &pThis->StatMMIOReadHC, STAMTYPE_COUNTER, "/Devices/APIC/MMIOReadHC", STAMUNIT_OCCURENCES, "Number of APIC MMIO reads in HC.");
PDMDevHlpSTAMRegister(pDevIns, &pThis->StatMMIOWriteGC, STAMTYPE_COUNTER, "/Devices/APIC/MMIOWriteGC", STAMUNIT_OCCURENCES, "Number of APIC MMIO writes in GC.");
PDMDevHlpSTAMRegister(pDevIns, &pThis->StatMMIOWriteHC, STAMTYPE_COUNTER, "/Devices/APIC/MMIOWriteHC", STAMUNIT_OCCURENCES, "Number of APIC MMIO writes in HC.");
PDMDevHlpSTAMRegister(pDevIns, &pThis->StatClearedActiveIrq,STAMTYPE_COUNTER, "/Devices/APIC/MaskedActiveIRQ", STAMUNIT_OCCURENCES, "Number of cleared irqs.");
for (i = 0; i < cCpus; i++) {
PDMDevHlpSTAMRegisterF(pDevIns, &pApic->StatTimerSetInitialCount, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Calls to apicTimerSetInitialCount.", "/Devices/APIC/%u/TimerSetInitialCount", i);
PDMDevHlpSTAMRegisterF(pDevIns, &pApic->StatTimerSetInitialCountArm, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "TMTimerSetRelative calls.", "/Devices/APIC/%u/TimerSetInitialCount/Arm", i);
PDMDevHlpSTAMRegisterF(pDevIns, &pApic->StatTimerSetInitialCountDisarm, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "TMTimerStop calls.", "/Devices/APIC/%u/TimerSetInitialCount/Disasm", i);
PDMDevHlpSTAMRegisterF(pDevIns, &pApic->StatTimerSetLvt, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Calls to apicTimerSetLvt.", "/Devices/APIC/%u/TimerSetLvt", i);
PDMDevHlpSTAMRegisterF(pDevIns, &pApic->StatTimerSetLvtClearPeriodic, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Clearing APIC_LVT_TIMER_PERIODIC.", "/Devices/APIC/%u/TimerSetLvt/ClearPeriodic", i);
PDMDevHlpSTAMRegisterF(pDevIns, &pApic->StatTimerSetLvtPostponed, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "TMTimerStop postponed.", "/Devices/APIC/%u/TimerSetLvt/Postponed", i);
PDMDevHlpSTAMRegisterF(pDevIns, &pApic->StatTimerSetLvtArmed, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "TMTimerSet avoided.", "/Devices/APIC/%u/TimerSetLvt/Armed", i);
PDMDevHlpSTAMRegisterF(pDevIns, &pApic->StatTimerSetLvtArm, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "TMTimerSet necessary.", "/Devices/APIC/%u/TimerSetLvt/Arm", i);
PDMDevHlpSTAMRegisterF(pDevIns, &pApic->StatTimerSetLvtArmRetries, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "TMTimerSet retries.", "/Devices/APIC/%u/TimerSetLvt/ArmRetries", i);
PDMDevHlpSTAMRegisterF(pDevIns, &pApic->StatTimerSetLvtNoRelevantChange,STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "No relevant flags changed.", "/Devices/APIC/%u/TimerSetLvt/NoRelevantChange", i);
return VINF_SUCCESS;
PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_32_64 | PDM_DEVREG_FLAGS_PAE36 | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
sizeof(APICState),
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
PDMBOTHCBDECL(int) ioapicMMIORead(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
switch (cb) {
IOAPIC_UNLOCK(s);
return VERR_INTERNAL_ERROR;
IOAPIC_UNLOCK(s);
return VINF_SUCCESS;
PDMBOTHCBDECL(int) ioapicMMIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTGCPHYS GCPhysAddr, void *pv, unsigned cb)
switch (cb) {
IOAPIC_UNLOCK(s);
return VERR_INTERNAL_ERROR;
return VINF_SUCCESS;
dest,
#ifdef IN_RING3
unsigned max_redir;
val = s->id << 24; /* Would be nice to call ioapic_mem_readl() directly, but that's not so simple. */
val = 0;
pHlp->pfnPrintf(pHlp, " idx dst_mode dst_addr mask trigger rirr polarity dlvr_st dlvr_mode vector\n");
for (i = 0; i <= max_redir; ++i)
return VINF_SUCCESS;
static DECLCALLBACK(int) ioapicLoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
AssertFailed();
return VINF_SUCCESS;
ioapic_reset(s);
IOAPIC_UNLOCK(s);
bool fGCEnabled;
bool fR0Enabled;
int rc;
ioapic_reset(s);
return rc;
return rc;
if (fGCEnabled) {
return rc;
if (fR0Enabled) {
return rc;
return rc;
#ifdef VBOX_WITH_STATISTICS
PDMDevHlpSTAMRegister(pDevIns, &s->StatMMIOReadGC, STAMTYPE_COUNTER, "/Devices/IOAPIC/MMIOReadGC", STAMUNIT_OCCURENCES, "Number of IOAPIC MMIO reads in GC.");
PDMDevHlpSTAMRegister(pDevIns, &s->StatMMIOReadHC, STAMTYPE_COUNTER, "/Devices/IOAPIC/MMIOReadHC", STAMUNIT_OCCURENCES, "Number of IOAPIC MMIO reads in HC.");
PDMDevHlpSTAMRegister(pDevIns, &s->StatMMIOWriteGC, STAMTYPE_COUNTER, "/Devices/IOAPIC/MMIOWriteGC", STAMUNIT_OCCURENCES, "Number of IOAPIC MMIO writes in GC.");
PDMDevHlpSTAMRegister(pDevIns, &s->StatMMIOWriteHC, STAMTYPE_COUNTER, "/Devices/IOAPIC/MMIOWriteHC", STAMUNIT_OCCURENCES, "Number of IOAPIC MMIO writes in HC.");
PDMDevHlpSTAMRegister(pDevIns, &s->StatSetIrqGC, STAMTYPE_COUNTER, "/Devices/IOAPIC/SetIrqGC", STAMUNIT_OCCURENCES, "Number of IOAPIC SetIrq calls in GC.");
PDMDevHlpSTAMRegister(pDevIns, &s->StatSetIrqHC, STAMTYPE_COUNTER, "/Devices/IOAPIC/SetIrqHC", STAMUNIT_OCCURENCES, "Number of IOAPIC SetIrq calls in HC.");
return VINF_SUCCESS;
PDM_DEVREG_FLAGS_HOST_BITS_DEFAULT | PDM_DEVREG_FLAGS_GUEST_BITS_32_64 | PDM_DEVREG_FLAGS_PAE36 | PDM_DEVREG_FLAGS_RC | PDM_DEVREG_FLAGS_R0,
sizeof(IOAPICState),
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,