VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMAll/PDMAll.cpp@ 5006

Last change on this file since 5006 was 4071, checked in by vboxsync, 17 years ago

Biggest check-in ever. New source code headers for all (C) innotek files.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 7.4 KB
Line 
1/* $Id: PDMAll.cpp 4071 2007-08-07 17:07:59Z vboxsync $ */
2/** @file
3 * PDM Critical Sections
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP LOG_GROUP_PDM
23#include "PDMInternal.h"
24#include <VBox/pdm.h>
25#include <VBox/mm.h>
26#include <VBox/vm.h>
27#include <VBox/err.h>
28
29#include <VBox/log.h>
30#include <iprt/asm.h>
31#include <iprt/assert.h>
32
33
34/**
35 * Gets the pending interrupt.
36 *
37 * @returns VBox status code.
38 * @param pVM VM handle.
39 * @param pu8Interrupt Where to store the interrupt on success.
40 */
41PDMDECL(int) PDMGetInterrupt(PVM pVM, uint8_t *pu8Interrupt)
42{
43 pdmLock(pVM);
44
45 /*
46 * The local APIC has a higer priority than the PIC.
47 */
48 if (VM_FF_ISSET(pVM, VM_FF_INTERRUPT_APIC))
49 {
50 VM_FF_CLEAR(pVM, VM_FF_INTERRUPT_APIC);
51 Assert(pVM->pdm.s.Apic.CTXALLSUFF(pDevIns));
52 Assert(pVM->pdm.s.Apic.CTXALLSUFF(pfnGetInterrupt));
53 int i = pVM->pdm.s.Apic.CTXALLSUFF(pfnGetInterrupt)(pVM->pdm.s.Apic.CTXALLSUFF(pDevIns));
54 AssertMsg(i <= 255 && i >= 0, ("i=%d\n", i));
55 if (i >= 0)
56 {
57 pdmUnlock(pVM);
58 *pu8Interrupt = (uint8_t)i;
59 return VINF_SUCCESS;
60 }
61 }
62
63 /*
64 * Check the PIC.
65 */
66 if (VM_FF_ISSET(pVM, VM_FF_INTERRUPT_PIC))
67 {
68 VM_FF_CLEAR(pVM, VM_FF_INTERRUPT_PIC);
69 Assert(pVM->pdm.s.Pic.CTXALLSUFF(pDevIns));
70 Assert(pVM->pdm.s.Pic.CTXALLSUFF(pfnGetInterrupt));
71 int i = pVM->pdm.s.Pic.CTXALLSUFF(pfnGetInterrupt)(pVM->pdm.s.Pic.CTXALLSUFF(pDevIns));
72 AssertMsg(i <= 255 && i >= 0, ("i=%d\n", i));
73 if (i >= 0)
74 {
75 pdmUnlock(pVM);
76 *pu8Interrupt = (uint8_t)i;
77 return VINF_SUCCESS;
78 }
79 }
80
81#ifndef VBOX_WITH_PDM_LOCK /** @todo Figure out exactly why we can get here without anything being set. (REM) */
82 /* Shouldn't get here! Noone should call us without cause. */
83 Assert(VM_FF_ISPENDING(pVM, VM_FF_INTERRUPT_APIC | VM_FF_INTERRUPT_PIC));
84#endif
85 pdmUnlock(pVM);
86 return VERR_NO_DATA;
87}
88
89
90/**
91 * Sets the pending interrupt.
92 *
93 * @returns VBox status code.
94 * @param pVM VM handle.
95 * @param u8Irq The IRQ line.
96 * @param u8Level The new level.
97 */
98PDMDECL(int) PDMIsaSetIrq(PVM pVM, uint8_t u8Irq, uint8_t u8Level)
99{
100 pdmLock(pVM);
101
102 int rc = VERR_PDM_NO_PIC_INSTANCE;
103 if (pVM->pdm.s.Pic.CTXALLSUFF(pDevIns))
104 {
105 Assert(pVM->pdm.s.Pic.CTXALLSUFF(pfnSetIrq));
106 pVM->pdm.s.Pic.CTXALLSUFF(pfnSetIrq)(pVM->pdm.s.Pic.CTXALLSUFF(pDevIns), u8Irq, u8Level);
107 rc = VINF_SUCCESS;
108 }
109
110 if (pVM->pdm.s.IoApic.CTXALLSUFF(pDevIns))
111 {
112 Assert(pVM->pdm.s.IoApic.CTXALLSUFF(pfnSetIrq));
113 pVM->pdm.s.IoApic.CTXALLSUFF(pfnSetIrq)(pVM->pdm.s.IoApic.CTXALLSUFF(pDevIns), u8Irq, u8Level);
114 rc = VINF_SUCCESS;
115 }
116
117 pdmUnlock(pVM);
118 return rc;
119}
120
121
122/**
123 * Sets the pending I/O APIC interrupt.
124 *
125 * @returns VBox status code.
126 * @param pVM VM handle.
127 * @param u8Irq The IRQ line.
128 * @param u8Level The new level.
129 */
130PDMDECL(int) PDMIoApicSetIrq(PVM pVM, uint8_t u8Irq, uint8_t u8Level)
131{
132 if (pVM->pdm.s.IoApic.CTXALLSUFF(pDevIns))
133 {
134 Assert(pVM->pdm.s.IoApic.CTXALLSUFF(pfnSetIrq));
135 pdmLock(pVM);
136 pVM->pdm.s.IoApic.CTXALLSUFF(pfnSetIrq)(pVM->pdm.s.IoApic.CTXALLSUFF(pDevIns), u8Irq, u8Level);
137 pdmUnlock(pVM);
138 return VINF_SUCCESS;
139 }
140 return VERR_PDM_NO_PIC_INSTANCE;
141}
142
143
144/**
145 * Set the APIC base.
146 *
147 * @returns VBox status code.
148 * @param pVM VM handle.
149 * @param u64Base The new base.
150 */
151PDMDECL(int) PDMApicSetBase(PVM pVM, uint64_t u64Base)
152{
153 if (pVM->pdm.s.Apic.CTXALLSUFF(pDevIns))
154 {
155 Assert(pVM->pdm.s.Apic.CTXALLSUFF(pfnSetBase));
156 pdmLock(pVM);
157 pVM->pdm.s.Apic.CTXALLSUFF(pfnSetBase)(pVM->pdm.s.Apic.CTXALLSUFF(pDevIns), u64Base);
158 pdmUnlock(pVM);
159 return VINF_SUCCESS;
160 }
161 return VERR_PDM_NO_APIC_INSTANCE;
162}
163
164
165/**
166 * Get the APIC base.
167 *
168 * @returns VBox status code.
169 * @param pVM VM handle.
170 * @param pu64Base Where to store the APIC base.
171 */
172PDMDECL(int) PDMApicGetBase(PVM pVM, uint64_t *pu64Base)
173{
174 if (pVM->pdm.s.Apic.CTXALLSUFF(pDevIns))
175 {
176 Assert(pVM->pdm.s.Apic.CTXALLSUFF(pfnGetBase));
177 pdmLock(pVM);
178 *pu64Base = pVM->pdm.s.Apic.CTXALLSUFF(pfnGetBase)(pVM->pdm.s.Apic.CTXALLSUFF(pDevIns));
179 pdmUnlock(pVM);
180 return VINF_SUCCESS;
181 }
182 *pu64Base = 0;
183 return VERR_PDM_NO_APIC_INSTANCE;
184}
185
186
187/**
188 * Set the TPR (task priority register?).
189 *
190 * @returns VBox status code.
191 * @param pVM VM handle.
192 * @param u8TPR The new TPR.
193 */
194PDMDECL(int) PDMApicSetTPR(PVM pVM, uint8_t u8TPR)
195{
196 if (pVM->pdm.s.Apic.CTXALLSUFF(pDevIns))
197 {
198 Assert(pVM->pdm.s.Apic.CTXALLSUFF(pfnSetTPR));
199 pdmLock(pVM);
200 pVM->pdm.s.Apic.CTXALLSUFF(pfnSetTPR)(pVM->pdm.s.Apic.CTXALLSUFF(pDevIns), u8TPR);
201 pdmUnlock(pVM);
202 return VINF_SUCCESS;
203 }
204 return VERR_PDM_NO_APIC_INSTANCE;
205}
206
207
208/**
209 * Get the TPR (task priority register?).
210 *
211 * @returns The current TPR.
212 * @param pVM VM handle.
213 * @param pu8TPR Where to store the TRP.
214 */
215PDMDECL(int) PDMApicGetTPR(PVM pVM, uint8_t *pu8TPR)
216{
217 if (pVM->pdm.s.Apic.CTXALLSUFF(pDevIns))
218 {
219 Assert(pVM->pdm.s.Apic.CTXALLSUFF(pfnGetTPR));
220 pdmLock(pVM);
221 *pu8TPR = pVM->pdm.s.Apic.CTXALLSUFF(pfnGetTPR)(pVM->pdm.s.Apic.CTXALLSUFF(pDevIns));
222 pdmUnlock(pVM);
223 return VINF_SUCCESS;
224 }
225 *pu8TPR = 0;
226 return VERR_PDM_NO_APIC_INSTANCE;
227}
228
229
230#ifdef VBOX_WITH_PDM_LOCK
231/**
232 * Locks PDM.
233 * This might call back to Ring-3 in order to deal with lock contention in GC and R3.
234 *
235 * @param pVM The VM handle.
236 */
237void pdmLock(PVM pVM)
238{
239#ifdef IN_RING3
240 int rc = PDMCritSectEnter(&pVM->pdm.s.CritSect, VERR_INTERNAL_ERROR);
241#else
242 int rc = PDMCritSectEnter(&pVM->pdm.s.CritSect, VERR_GENERAL_FAILURE);
243 if (rc == VERR_GENERAL_FAILURE)
244 {
245# ifdef IN_GC
246 rc = VMMGCCallHost(pVM, VMMCALLHOST_PDM_LOCK, 0);
247#else
248 rc = VMMR0CallHost(pVM, VMMCALLHOST_PDM_LOCK, 0);
249#endif
250 }
251#endif
252 AssertRC(rc);
253}
254
255
256/**
257 * Locks PDM but don't go to ring-3 if it's owned by someone.
258 *
259 * @returns VINF_SUCCESS on success.
260 * @returns rc if we're in GC or R0 and can't get the lock.
261 * @param pVM The VM handle.
262 * @param rc The RC to return in GC or R0 when we can't get the lock.
263 */
264int pdmLockEx(PVM pVM, int rc)
265{
266 return PDMCritSectEnter(&pVM->pdm.s.CritSect, rc);
267}
268
269
270/**
271 * Unlocks PDM.
272 *
273 * @param pVM The VM handle.
274 */
275void pdmUnlock(PVM pVM)
276{
277 PDMCritSectLeave(&pVM->pdm.s.CritSect);
278}
279#endif /* VBOX_WITH_PDM_LOCK */
280
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette