PDMAll.cpp revision 13cf6cf8e0bca3f99b5c122d775bdbffde41e4b6
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync/* $Id$ */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync/** @file
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * PDM Critical Sections
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync/*
2a2b173b54c259e34320ce0acf26f18e9382ce2avboxsync * Copyright (C) 2006-2007 Sun Microsystems, Inc.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync *
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * available from http://www.virtualbox.org. This file is free software;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * you can redistribute it and/or modify it under the terms of the GNU
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * General Public License (GPL) as published by the Free Software
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync *
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync * additional information or have any questions.
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync */
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync/*******************************************************************************
0d12c7f9423f2745f8e282523d0930f91bff03b3vboxsync* Header Files *
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync*******************************************************************************/
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#define LOG_GROUP LOG_GROUP_PDM
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include "PDMInternal.h"
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <VBox/pdm.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <VBox/mm.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <VBox/vm.h>
032a52c5b2984e26e84c2961f8f7f98a3954c8f2vboxsync#include <VBox/err.h>
6ba706e9f431401d425d16817fdcd6316f83b584vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <VBox/log.h>
590bfe12ce22cd3716448fbb9f4dc51664bfe5e2vboxsync#include <iprt/asm.h>
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync#include <iprt/assert.h>
45c3e41d012100c5f4a3f77e391e4c6da8f5b97avboxsync
45c3e41d012100c5f4a3f77e391e4c6da8f5b97avboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync/**
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * Gets the pending interrupt.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync *
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * @returns VBox status code.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * @param pVCpu VMCPU handle.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * @param pu8Interrupt Where to store the interrupt on success.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsyncVMMDECL(int) PDMGetInterrupt(PVMCPU pVCpu, uint8_t *pu8Interrupt)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync{
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync PVM pVM = pVCpu->CTX_SUFF(pVM);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync pdmLock(pVM);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync /*
9939c713bffcfc4305d99d994552aa2ad9bce097vboxsync * The local APIC has a higer priority than the PIC.
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync if (VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INTERRUPT_APIC))
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync {
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_APIC);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync Assert(pVM->pdm.s.Apic.CTX_SUFF(pDevIns));
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync Assert(pVM->pdm.s.Apic.CTX_SUFF(pfnGetInterrupt));
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync int i = pVM->pdm.s.Apic.CTX_SUFF(pfnGetInterrupt)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns));
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync AssertMsg(i <= 255 && i >= 0, ("i=%d\n", i));
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync if (i >= 0)
c2046db2cc346cc299f0cd9b2d1e160179159cfcvboxsync {
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync pdmUnlock(pVM);
044af0d1e6474076366759db86f101778c5f20ccvboxsync *pu8Interrupt = (uint8_t)i;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return VINF_SUCCESS;
2d8870843ff566fee9bd3a6a5942414254106479vboxsync }
2d8870843ff566fee9bd3a6a5942414254106479vboxsync }
2d8870843ff566fee9bd3a6a5942414254106479vboxsync
2d8870843ff566fee9bd3a6a5942414254106479vboxsync /*
2d8870843ff566fee9bd3a6a5942414254106479vboxsync * Check the PIC.
2d8870843ff566fee9bd3a6a5942414254106479vboxsync */
2d8870843ff566fee9bd3a6a5942414254106479vboxsync if (VMCPU_FF_ISSET(pVCpu, VMCPU_FF_INTERRUPT_PIC))
2d8870843ff566fee9bd3a6a5942414254106479vboxsync {
2d8870843ff566fee9bd3a6a5942414254106479vboxsync VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_PIC);
2d8870843ff566fee9bd3a6a5942414254106479vboxsync Assert(pVM->pdm.s.Pic.CTX_SUFF(pDevIns));
2d8870843ff566fee9bd3a6a5942414254106479vboxsync Assert(pVM->pdm.s.Pic.CTX_SUFF(pfnGetInterrupt));
2d8870843ff566fee9bd3a6a5942414254106479vboxsync int i = pVM->pdm.s.Pic.CTX_SUFF(pfnGetInterrupt)(pVM->pdm.s.Pic.CTX_SUFF(pDevIns));
044af0d1e6474076366759db86f101778c5f20ccvboxsync AssertMsg(i <= 255 && i >= 0, ("i=%d\n", i));
044af0d1e6474076366759db86f101778c5f20ccvboxsync if (i >= 0)
044af0d1e6474076366759db86f101778c5f20ccvboxsync {
044af0d1e6474076366759db86f101778c5f20ccvboxsync pdmUnlock(pVM);
044af0d1e6474076366759db86f101778c5f20ccvboxsync *pu8Interrupt = (uint8_t)i;
044af0d1e6474076366759db86f101778c5f20ccvboxsync return VINF_SUCCESS;
044af0d1e6474076366759db86f101778c5f20ccvboxsync }
044af0d1e6474076366759db86f101778c5f20ccvboxsync }
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync /** @todo Figure out exactly why we can get here without anything being set. (REM) */
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync pdmUnlock(pVM);
044af0d1e6474076366759db86f101778c5f20ccvboxsync return VERR_NO_DATA;
044af0d1e6474076366759db86f101778c5f20ccvboxsync}
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync/**
044af0d1e6474076366759db86f101778c5f20ccvboxsync * Sets the pending interrupt.
044af0d1e6474076366759db86f101778c5f20ccvboxsync *
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @returns VBox status code.
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @param pVM VM handle.
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @param u8Irq The IRQ line.
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @param u8Level The new level.
044af0d1e6474076366759db86f101778c5f20ccvboxsync */
044af0d1e6474076366759db86f101778c5f20ccvboxsyncVMMDECL(int) PDMIsaSetIrq(PVM pVM, uint8_t u8Irq, uint8_t u8Level)
044af0d1e6474076366759db86f101778c5f20ccvboxsync{
044af0d1e6474076366759db86f101778c5f20ccvboxsync pdmLock(pVM);
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync int rc = VERR_PDM_NO_PIC_INSTANCE;
044af0d1e6474076366759db86f101778c5f20ccvboxsync if (pVM->pdm.s.Pic.CTX_SUFF(pDevIns))
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync {
044af0d1e6474076366759db86f101778c5f20ccvboxsync Assert(pVM->pdm.s.Pic.CTX_SUFF(pfnSetIrq));
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync pVM->pdm.s.Pic.CTX_SUFF(pfnSetIrq)(pVM->pdm.s.Pic.CTX_SUFF(pDevIns), u8Irq, u8Level);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync rc = VINF_SUCCESS;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync }
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync if (pVM->pdm.s.IoApic.CTX_SUFF(pDevIns))
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync {
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync Assert(pVM->pdm.s.IoApic.CTX_SUFF(pfnSetIrq));
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync pVM->pdm.s.IoApic.CTX_SUFF(pfnSetIrq)(pVM->pdm.s.IoApic.CTX_SUFF(pDevIns), u8Irq, u8Level);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync rc = VINF_SUCCESS;
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync }
044af0d1e6474076366759db86f101778c5f20ccvboxsync
044af0d1e6474076366759db86f101778c5f20ccvboxsync pdmUnlock(pVM);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return rc;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync}
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync/**
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * Sets the pending I/O APIC interrupt.
044af0d1e6474076366759db86f101778c5f20ccvboxsync *
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @returns VBox status code.
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @param pVM VM handle.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * @param u8Irq The IRQ line.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * @param u8Level The new level.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsyncVMMDECL(int) PDMIoApicSetIrq(PVM pVM, uint8_t u8Irq, uint8_t u8Level)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync{
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync if (pVM->pdm.s.IoApic.CTX_SUFF(pDevIns))
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync {
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync Assert(pVM->pdm.s.IoApic.CTX_SUFF(pfnSetIrq));
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync pdmLock(pVM);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync pVM->pdm.s.IoApic.CTX_SUFF(pfnSetIrq)(pVM->pdm.s.IoApic.CTX_SUFF(pDevIns), u8Irq, u8Level);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync pdmUnlock(pVM);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return VINF_SUCCESS;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync }
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync return VERR_PDM_NO_PIC_INSTANCE;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync}
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync/**
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * Returns presence of an IO-APIC
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync *
a1df400bbe9d64aad400442e56eb637019300a5evboxsync * @returns VBox true if IO-APIC is present
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * @param pVM VM handle.
a1df400bbe9d64aad400442e56eb637019300a5evboxsync */
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsyncVMMDECL(bool) PDMHasIoApic(PVM pVM)
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync{
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return pVM->pdm.s.IoApic.CTX_SUFF(pDevIns) != NULL;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync}
a1df400bbe9d64aad400442e56eb637019300a5evboxsync
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync
a1df400bbe9d64aad400442e56eb637019300a5evboxsync/**
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * Set the APIC base.
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync *
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * @returns VBox status code.
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @param pVM VM handle.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * @param u64Base The new base.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsyncVMMDECL(int) PDMApicSetBase(PVM pVM, uint64_t u64Base)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync{
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync if (pVM->pdm.s.Apic.CTX_SUFF(pDevIns))
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync {
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync Assert(pVM->pdm.s.Apic.CTX_SUFF(pfnSetBase));
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync pdmLock(pVM);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync pVM->pdm.s.Apic.CTX_SUFF(pfnSetBase)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns), u64Base);
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync pdmUnlock(pVM);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync return VINF_SUCCESS;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync }
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync return VERR_PDM_NO_APIC_INSTANCE;
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync}
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync/**
044af0d1e6474076366759db86f101778c5f20ccvboxsync * Get the APIC base.
044af0d1e6474076366759db86f101778c5f20ccvboxsync *
044af0d1e6474076366759db86f101778c5f20ccvboxsync * @returns VBox status code.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync * @param pVM VM handle.
ca3da10d05961c339b5180fbd40a54587d6bad35vboxsync * @param pu64Base Where to store the APIC base.
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync */
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsyncVMMDECL(int) PDMApicGetBase(PVM pVM, uint64_t *pu64Base)
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync{
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync if (pVM->pdm.s.Apic.CTX_SUFF(pDevIns))
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync {
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync Assert(pVM->pdm.s.Apic.CTX_SUFF(pfnGetBase));
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync pdmLock(pVM);
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync *pu64Base = pVM->pdm.s.Apic.CTX_SUFF(pfnGetBase)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns));
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync pdmUnlock(pVM);
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync return VINF_SUCCESS;
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync }
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync *pu64Base = 0;
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync return VERR_PDM_NO_APIC_INSTANCE;
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync}
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync/**
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync * Check if the APIC has a pending interrupt/if a TPR change would active one.
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync *
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync * @returns VINF_SUCCESS or VERR_PDM_NO_APIC_INSTANCE.
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync * @param pDevIns Device instance of the APIC.
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync * @param pfPending Pending state (out).
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync */
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsyncVMMDECL(int) PDMApicHasPendingIrq(PVM pVM, bool *pfPending)
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync{
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync if (pVM->pdm.s.Apic.CTX_SUFF(pDevIns))
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync {
7d80dfbe5d66fc4c6de6fe109ce96a081496dcd4vboxsync Assert(pVM->pdm.s.Apic.CTX_SUFF(pfnSetTPR));
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync pdmLock(pVM);
3a4a6501d0ccd629d9951b644d380c7bb2d46086vboxsync *pfPending = pVM->pdm.s.Apic.CTX_SUFF(pfnHasPendingIrq)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns));
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync pdmUnlock(pVM);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return VINF_SUCCESS;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync }
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return VERR_PDM_NO_APIC_INSTANCE;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync}
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync/**
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * Set the TPR (task priority register).
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync *
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @returns VBox status code.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param pVCpu VMCPU handle.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param u8TPR The new TPR.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param fMMIOFormat Update as if MMIO write to ApicBase + 0x80
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync */
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsyncVMMDECL(int) PDMApicSetTPREx(PVMCPU pVCpu, uint8_t u8TPR, bool fMMIOFormat)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync{
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync PVM pVM = pVCpu->CTX_SUFF(pVM);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (pVM->pdm.s.Apic.CTX_SUFF(pDevIns))
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync {
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync Assert(pVM->pdm.s.Apic.CTX_SUFF(pfnSetTPR));
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync pdmLock(pVM);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync pVM->pdm.s.Apic.CTX_SUFF(pfnSetTPR)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns), pVCpu->idCpu, u8TPR, fMMIOFormat);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync pdmUnlock(pVM);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return VINF_SUCCESS;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync }
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return VERR_PDM_NO_APIC_INSTANCE;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync}
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync/**
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * Set the TPR (task priority register).
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync *
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @returns VBox status code.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param pVCpu VMCPU handle.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param u8TPR The new TPR.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync */
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsyncVMMDECL(int) PDMApicSetTPR(PVMCPU pVCpu, uint8_t u8TPR)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync{
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return PDMApicSetTPREx(pVCpu, u8TPR, false /* TPR only */);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync}
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync/**
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * Get the TPR (task priority register).
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync *
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @returns The current TPR.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param pVCpu VMCPU handle.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param pu8TPR Where to store the TRP.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param fMMIOFormat Return as if MMIO read from ApicBase + 0x80
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param pfPending Pending interrupt state (out).
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync*/
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsyncVMMDECL(int) PDMApicGetTPREx(PVMCPU pVCpu, uint8_t *pu8TPR, bool fMMIOFormat, bool *pfPending)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync{
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync PVM pVM = pVCpu->CTX_SUFF(pVM);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (pVM->pdm.s.Apic.CTX_SUFF(pDevIns))
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync {
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync Assert(pVM->pdm.s.Apic.CTX_SUFF(pfnGetTPR));
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync pdmLock(pVM);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync *pu8TPR = pVM->pdm.s.Apic.CTX_SUFF(pfnGetTPR)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns), pVCpu->idCpu, fMMIOFormat);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (pfPending)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync *pfPending = pVM->pdm.s.Apic.CTX_SUFF(pfnHasPendingIrq)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns));
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync pdmUnlock(pVM);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return VINF_SUCCESS;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync }
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync *pu8TPR = 0;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return VERR_PDM_NO_APIC_INSTANCE;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync}
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync/**
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * Get the TPR (task priority register).
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync *
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @returns The current TPR.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param pVCpu VMCPU handle.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param pu8TPR Where to store the TRP.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param pfPending Pending interrupt state (out).
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync*/
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsyncVMMDECL(int) PDMApicGetTPR(PVMCPU pVCpu, uint8_t *pu8TPR, bool *pfPending)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync{
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return PDMApicGetTPREx(pVCpu, pu8TPR, false /* TPR only */, pfPending);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync}
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync/**
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * Write MSR in APIC range.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync *
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @returns VBox status code.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param pVM VM handle.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param iCpu Target CPU.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param u32Reg MSR to write.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param u64Value Value to write.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync */
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsyncVMMDECL(int) PDMApicWriteMSR(PVM pVM, VMCPUID iCpu, uint32_t u32Reg, uint64_t u64Value)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync{
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (pVM->pdm.s.Apic.CTX_SUFF(pDevIns))
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync {
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync Assert(pVM->pdm.s.Apic.CTX_SUFF(pfnWriteMSR));
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync pdmLock(pVM);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync pVM->pdm.s.Apic.CTX_SUFF(pfnWriteMSR)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns), iCpu, u32Reg, u64Value);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync pdmUnlock(pVM);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return VINF_SUCCESS;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync }
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return VERR_PDM_NO_APIC_INSTANCE;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync}
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync/**
0109a2240391a89f6556b1545e6cc57f9efab060vboxsync * Read MSR in APIC range.
0109a2240391a89f6556b1545e6cc57f9efab060vboxsync *
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @returns VBox status code.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param pVM VM handle.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param iCpu Target CPU.
0109a2240391a89f6556b1545e6cc57f9efab060vboxsync * @param u32Reg MSR to read.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param pu64Value Value read.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync */
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsyncVMMDECL(int) PDMApicReadMSR(PVM pVM, VMCPUID iCpu, uint32_t u32Reg, uint64_t *pu64Value)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync{
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (pVM->pdm.s.Apic.CTX_SUFF(pDevIns))
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync {
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync Assert(pVM->pdm.s.Apic.CTX_SUFF(pfnReadMSR));
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync pdmLock(pVM);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync pVM->pdm.s.Apic.CTX_SUFF(pfnReadMSR)(pVM->pdm.s.Apic.CTX_SUFF(pDevIns), iCpu, u32Reg, pu64Value);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync pdmUnlock(pVM);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return VINF_SUCCESS;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync }
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return VERR_PDM_NO_APIC_INSTANCE;
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync}
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync/**
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * Locks PDM.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * This might call back to Ring-3 in order to deal with lock contention in GC and R3.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync *
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param pVM The VM handle.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync */
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsyncvoid pdmLock(PVM pVM)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync{
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync#ifdef IN_RING3
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync int rc = PDMCritSectEnter(&pVM->pdm.s.CritSect, VERR_INTERNAL_ERROR);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync#else
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync int rc = PDMCritSectEnter(&pVM->pdm.s.CritSect, VERR_GENERAL_FAILURE);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync if (rc == VERR_GENERAL_FAILURE)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync {
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync# ifdef IN_RC
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync rc = VMMGCCallHost(pVM, VMMCALLHOST_PDM_LOCK, 0);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync# else
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync rc = VMMR0CallHost(pVM, VMMCALLHOST_PDM_LOCK, 0);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync# endif
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync }
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync#endif
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync AssertRC(rc);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync}
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync/**
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * Locks PDM but don't go to ring-3 if it's owned by someone.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync *
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @returns VINF_SUCCESS on success.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @returns rc if we're in GC or R0 and can't get the lock.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param pVM The VM handle.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param rc The RC to return in GC or R0 when we can't get the lock.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync */
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsyncint pdmLockEx(PVM pVM, int rc)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync{
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync return PDMCritSectEnter(&pVM->pdm.s.CritSect, rc);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync}
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync/**
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * Unlocks PDM.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync *
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param pVM The VM handle.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync */
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsyncvoid pdmUnlock(PVM pVM)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync{
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync PDMCritSectLeave(&pVM->pdm.s.CritSect);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync}
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync/**
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * Converts ring 3 VMM heap pointer to a guest physical address
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync *
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @returns VBox status code.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param pVM VM handle.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param pv Ring-3 pointer.
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync * @param pGCPhys GC phys address (out).
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync */
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsyncVMMDECL(int) PDMVMMDevHeapR3ToGCPhys(PVM pVM, RTR3PTR pv, RTGCPHYS *pGCPhys)
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync{
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync AssertReturn(pv >= pVM->pdm.s.pvVMMDevHeap && (RTR3UINTPTR)pv < (RTR3UINTPTR)pVM->pdm.s.pvVMMDevHeap + pVM->pdm.s.cbVMMDevHeap, VERR_INVALID_PARAMETER);
b7a07b07543924f45c1fffd2f90de582038b8ba6vboxsync
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync *pGCPhys = (pVM->pdm.s.GCPhysVMMDevHeap + ((RTR3UINTPTR)pv - (RTR3UINTPTR)pVM->pdm.s.pvVMMDevHeap));
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync return VINF_SUCCESS;
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync}
d6f8b76ab3b2ec0c270c96f9db6e2568fc41b5fevboxsync