VirtualBox

source: vbox/trunk/src/VBox/VMM/DBGFAddr.cpp@ 19253

Last change on this file since 19253 was 19182, checked in by vboxsync, 16 years ago

DBGFAddr: Three new APIs for address conversion that takes threading into account.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 12.4 KB
Line 
1/* $Id: DBGFAddr.cpp 19182 2009-04-24 18:37:47Z vboxsync $ */
2/** @file
3 * DBGF - Debugger Facility, Mixed Address Methods.
4 */
5
6/*
7 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
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 (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
18 * Clara, CA 95054 USA or visit http://www.sun.com if you need
19 * additional information or have any questions.
20 */
21
22
23/*******************************************************************************
24* Header Files *
25*******************************************************************************/
26#define LOG_GROUP LOG_GROUP_DBGF
27#include <VBox/dbgf.h>
28#include <VBox/pgm.h>
29#include <VBox/selm.h>
30#include <VBox/mm.h>
31#include "DBGFInternal.h"
32#include <VBox/vm.h>
33#include <VBox/param.h>
34#include <VBox/err.h>
35#include <VBox/log.h>
36
37
38
39/**
40 * Checks if an address is in the HMA or not.
41 * @returns true if it's inside the HMA.
42 * @returns flase if it's not inside the HMA.
43 * @param pVM The VM handle.
44 * @param FlatPtr The address in question.
45 */
46DECLINLINE(bool) dbgfR3IsHMA(PVM pVM, RTGCUINTPTR FlatPtr)
47{
48 return MMHyperIsInsideArea(pVM, FlatPtr);
49}
50
51
52/**
53 * Creates a mixed address from a Sel:off pair.
54 *
55 * @returns VBox status code.
56 * @param pVM The VM handle.
57 * @param pAddress Where to store the mixed address.
58 * @param Sel The selector part.
59 * @param off The offset part.
60 */
61VMMR3DECL(int) DBGFR3AddrFromSelOff(PVM pVM, PDBGFADDRESS pAddress, RTSEL Sel, RTUINTPTR off)
62{
63 pAddress->Sel = Sel;
64 pAddress->off = off;
65 if (Sel != DBGF_SEL_FLAT)
66 {
67 /* @todo SMP support!! */
68 PVMCPU pVCpu = &pVM->aCpus[0];
69
70 SELMSELINFO SelInfo;
71 int rc = SELMR3GetSelectorInfo(pVM, pVCpu, Sel, &SelInfo);
72 if (RT_FAILURE(rc))
73 return rc;
74
75 /* check limit. */
76 if (SELMSelInfoIsExpandDown(&SelInfo))
77 {
78 if ( !SelInfo.Raw.Gen.u1Granularity
79 && off > UINT32_C(0xffff))
80 return VERR_OUT_OF_SELECTOR_BOUNDS;
81 if (off <= SelInfo.cbLimit)
82 return VERR_OUT_OF_SELECTOR_BOUNDS;
83 }
84 else if (off > SelInfo.cbLimit)
85 return VERR_OUT_OF_SELECTOR_BOUNDS;
86
87 pAddress->FlatPtr = SelInfo.GCPtrBase + off;
88 /** @todo fix this flat selector test! */
89 if ( !SelInfo.GCPtrBase
90 && SelInfo.Raw.Gen.u1Granularity
91 && SelInfo.Raw.Gen.u1DefBig)
92 pAddress->fFlags = DBGFADDRESS_FLAGS_FLAT;
93 else if (SelInfo.cbLimit <= UINT32_C(0xffff))
94 pAddress->fFlags = DBGFADDRESS_FLAGS_FAR16;
95 else if (SelInfo.cbLimit <= UINT32_C(0xffffffff))
96 pAddress->fFlags = DBGFADDRESS_FLAGS_FAR32;
97 else
98 pAddress->fFlags = DBGFADDRESS_FLAGS_FAR64;
99 }
100 else
101 {
102 pAddress->FlatPtr = off;
103 pAddress->fFlags = DBGFADDRESS_FLAGS_FLAT;
104 }
105 pAddress->fFlags |= DBGFADDRESS_FLAGS_VALID;
106 if (dbgfR3IsHMA(pVM, pAddress->FlatPtr))
107 pAddress->fFlags |= DBGFADDRESS_FLAGS_HMA;
108
109 return VINF_SUCCESS;
110}
111
112
113/**
114 * Creates a mixed address from a flat address.
115 *
116 * @param pVM The VM handle.
117 * @param pAddress Where to store the mixed address.
118 * @param FlatPtr The flat pointer.
119 */
120VMMR3DECL(PDBGFADDRESS) DBGFR3AddrFromFlat(PVM pVM, PDBGFADDRESS pAddress, RTGCUINTPTR FlatPtr)
121{
122 pAddress->Sel = DBGF_SEL_FLAT;
123 pAddress->off = FlatPtr;
124 pAddress->FlatPtr = FlatPtr;
125 pAddress->fFlags = DBGFADDRESS_FLAGS_FLAT | DBGFADDRESS_FLAGS_VALID;
126 if (dbgfR3IsHMA(pVM, pAddress->FlatPtr))
127 pAddress->fFlags |= DBGFADDRESS_FLAGS_HMA;
128 return pAddress;
129}
130
131
132/**
133 * Creates a mixed address from a guest physical address.
134 *
135 * @param pVM The VM handle.
136 * @param pAddress Where to store the mixed address.
137 * @param PhysAddr The guest physical address.
138 */
139VMMR3DECL(void) DBGFR3AddrFromPhys(PVM pVM, PDBGFADDRESS pAddress, RTGCPHYS PhysAddr)
140{
141 pAddress->Sel = DBGF_SEL_FLAT;
142 pAddress->off = PhysAddr;
143 pAddress->FlatPtr = PhysAddr;
144 pAddress->fFlags = DBGFADDRESS_FLAGS_PHYS | DBGFADDRESS_FLAGS_VALID;
145}
146
147
148/**
149 * Checks if the specified address is valid (checks the structure pointer too).
150 *
151 * @returns true if valid.
152 * @returns false if invalid.
153 * @param pVM The VM handle.
154 * @param pAddress The address to validate.
155 */
156VMMR3DECL(bool) DBGFR3AddrIsValid(PVM pVM, PCDBGFADDRESS pAddress)
157{
158 if (!VALID_PTR(pAddress))
159 return false;
160 if (!DBGFADDRESS_IS_VALID(pAddress))
161 return false;
162 /* more? */
163 return true;
164}
165
166
167/**
168 * Called on the EMT for the VCpu.
169 *
170 * @returns VBox status code.
171 * @param pVCpu The virtual CPU handle.
172 * @param pAddress The address.
173 * @param pGCPhys Where to return the physical address.
174 */
175static DECLCALLBACK(int) dbgfR3AddrToPhysOnVCpu(PVMCPU pVCpu, PDBGFADDRESS pAddress, PRTGCPHYS pGCPhys)
176{
177 VMCPU_ASSERT_EMT(pVCpu);
178 /* This is just a wrapper because we cannot pass FlatPtr thru VMR3ReqCall directly. */
179 return PGMGstGetPage(pVCpu, pAddress->FlatPtr, NULL, pGCPhys);
180}
181
182
183/**
184 * Converts an address to a guest physical address.
185 *
186 * @returns VBox status code.
187 * @retval VINF_SUCCESS
188 * @retval VERR_INVALID_PARAMETER if the address is invalid.
189 * @retval VERR_INVALID_STATE if the VM is being terminated or if the virtual
190 * CPU handle is invalid.
191 * @retval VERR_NOT_SUPPORTED is the type of address cannot be converted.
192 * @retval VERR_PAGE_NOT_PRESENT
193 * @retval VERR_PAGE_TABLE_NOT_PRESENT
194 * @retval VERR_PAGE_DIRECTORY_PTR_NOT_PRESENT
195 * @retval VERR_PAGE_MAP_LEVEL4_NOT_PRESENT
196 *
197 * @param pVCpu The virtual CPU handle.
198 * @param pAddress The address.
199 * @param pGCPhys Where to return the physical address.
200 */
201VMMR3DECL(int) DBGFR3AddrToPhys(PVMCPU pVCpu, PDBGFADDRESS pAddress, PRTGCPHYS pGCPhys)
202{
203 /*
204 * Parameter validation.
205 */
206 AssertPtr(pGCPhys);
207 *pGCPhys = NIL_RTGCPHYS;
208 AssertPtr(pAddress);
209 AssertReturn(DBGFADDRESS_IS_VALID(pAddress), VERR_INVALID_PARAMETER);
210 VMCPU_ASSERT_VALID_EXT_RETURN(pVCpu->pVMR3, VERR_INVALID_STATE);
211
212 /*
213 * Convert by address type.
214 */
215 int rc;
216 if (pAddress->fFlags & DBGFADDRESS_FLAGS_HMA)
217 rc = VERR_NOT_SUPPORTED;
218 else if (pAddress->fFlags & DBGFADDRESS_FLAGS_PHYS)
219 {
220 *pGCPhys = pAddress->FlatPtr;
221 rc = VINF_SUCCESS;
222 }
223 else if (VMCPU_IS_EMT(pVCpu))
224 rc = dbgfR3AddrToPhysOnVCpu(pVCpu, pAddress, pGCPhys);
225 else
226 {
227 PVMREQ pReq = NULL;
228 rc = VMR3ReqCall(pVCpu->pVMR3, VMREQDEST_FROM_VMCPU(pVCpu), &pReq, RT_INDEFINITE_WAIT,
229 (PFNRT)dbgfR3AddrToPhysOnVCpu, 3, pVCpu, pAddress, pGCPhys);
230 if (RT_SUCCESS(rc))
231 {
232 rc = pReq->iStatus;
233 VMR3ReqFree(pReq);
234 }
235 }
236 return rc;
237}
238
239
240/**
241 * Converts an address to a host physical address.
242 *
243 * @returns VBox status code.
244 * @retval VINF_SUCCESS
245 * @retval VERR_INVALID_PARAMETER if the address is invalid.
246 * @retval VERR_INVALID_STATE if the VM is being terminated or if the virtual
247 * CPU handle is invalid.
248 * @retval VERR_NOT_SUPPORTED is the type of address cannot be converted.
249 * @retval VERR_PAGE_NOT_PRESENT
250 * @retval VERR_PAGE_TABLE_NOT_PRESENT
251 * @retval VERR_PAGE_DIRECTORY_PTR_NOT_PRESENT
252 * @retval VERR_PAGE_MAP_LEVEL4_NOT_PRESENT
253 * @retval VERR_PGM_PHYS_PAGE_RESERVED
254 * @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS
255 *
256 * @param pVCpu The virtual CPU handle.
257 * @param pAddress The address.
258 * @param pHCPhys Where to return the physical address.
259 */
260VMMR3DECL(int) DBGFR3AddrToHostPhys(PVMCPU pVCpu, PDBGFADDRESS pAddress, PRTHCPHYS pHCPhys)
261{
262 /*
263 * Parameter validation.
264 */
265 AssertPtr(pHCPhys);
266 *pHCPhys = NIL_RTHCPHYS;
267 AssertPtr(pAddress);
268 AssertReturn(DBGFADDRESS_IS_VALID(pAddress), VERR_INVALID_PARAMETER);
269 VMCPU_ASSERT_VALID_EXT_RETURN(pVCpu->pVMR3, VERR_INVALID_STATE);
270
271 /*
272 * Convert it if we can.
273 */
274 int rc;
275 if (pAddress->fFlags & DBGFADDRESS_FLAGS_HMA)
276 rc = VERR_NOT_SUPPORTED; /** @todo implement this */
277 else
278 {
279 RTGCPHYS GCPhys;
280 rc = DBGFR3AddrToPhys(pVCpu, pAddress, &GCPhys);
281 if (RT_SUCCESS(rc))
282 rc = PGMPhysGCPhys2HCPhys(pVCpu->pVMR3, pAddress->FlatPtr, pHCPhys);
283 }
284 return rc;
285}
286
287
288/**
289 * Called on the EMT for the VCpu.
290 *
291 * @returns VBox status code.
292 * @param pVCpu The virtual CPU handle.
293 * @param pAddress The address.
294 * @param fReadOnly Whether returning a read-only page is fine or not.
295 * @param ppvR3Ptr Where to return the address.
296 */
297static DECLCALLBACK(int) dbgfR3AddrToVolatileR3PtrOnVCpu(PVMCPU pVCpu, PDBGFADDRESS pAddress, bool fReadOnly, void **ppvR3Ptr)
298{
299 VMCPU_ASSERT_EMT(pVCpu);
300
301 int rc;
302 PVM pVM = pVCpu->CTX_SUFF(pVM);
303 if (pAddress->fFlags & DBGFADDRESS_FLAGS_HMA)
304 {
305 rc = VERR_NOT_SUPPORTED; /** @todo create some dedicated errors for this stuff. */
306 /** @todo this may assert, create a debug version of this which doesn't. */
307 if (MMHyperIsInsideArea(pVM, pAddress->FlatPtr))
308 {
309 void *pv = MMHyperRCToCC(pVM, (RTRCPTR)pAddress->FlatPtr);
310 if (pv)
311 {
312 *ppvR3Ptr = pv;
313 rc = VINF_SUCCESS;
314 }
315 }
316 }
317 else
318 {
319 /*
320 * This is a tad ugly, but it gets the job done.
321 */
322 PGMPAGEMAPLOCK Lock;
323 if (pAddress->fFlags & DBGFADDRESS_FLAGS_PHYS)
324 {
325 if (fReadOnly)
326 rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, pAddress->FlatPtr, (void const **)ppvR3Ptr, &Lock);
327 else
328 rc = PGMPhysGCPhys2CCPtr(pVM, pAddress->FlatPtr, ppvR3Ptr, &Lock);
329 }
330 else
331 {
332 if (fReadOnly)
333 rc = PGMPhysGCPtr2CCPtrReadOnly(pVCpu, pAddress->FlatPtr, (void const **)ppvR3Ptr, &Lock);
334 else
335 rc = PGMPhysGCPtr2CCPtr(pVCpu, pAddress->FlatPtr, ppvR3Ptr, &Lock);
336 }
337 if (RT_SUCCESS(rc))
338 PGMPhysReleasePageMappingLock(pVM, &Lock);
339 }
340 return rc;
341}
342
343
344
345
346/**
347 * Converts an address to a volatile host virtual address.
348 *
349 * @returns VBox status code.
350 * @retval VINF_SUCCESS
351 * @retval VERR_INVALID_PARAMETER if the address is invalid.
352 * @retval VERR_INVALID_STATE if the VM is being terminated or if the virtual
353 * CPU handle is invalid.
354 * @retval VERR_NOT_SUPPORTED is the type of address cannot be converted.
355 * @retval VERR_PAGE_NOT_PRESENT
356 * @retval VERR_PAGE_TABLE_NOT_PRESENT
357 * @retval VERR_PAGE_DIRECTORY_PTR_NOT_PRESENT
358 * @retval VERR_PAGE_MAP_LEVEL4_NOT_PRESENT
359 * @retval VERR_PGM_PHYS_PAGE_RESERVED
360 * @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS
361 *
362 * @param pVCpu The virtual CPU handle.
363 * @param pAddress The address.
364 * @param fReadOnly Whether returning a read-only page is fine or not.
365 * If set to thru the page may have to be made writable
366 * before we return.
367 * @param ppvR3Ptr Where to return the address.
368 */
369VMMR3DECL(int) DBGFR3AddrToVolatileR3Ptr(PVMCPU pVCpu, PDBGFADDRESS pAddress, bool fReadOnly, void **ppvR3Ptr)
370{
371 /*
372 * Parameter validation.
373 */
374 AssertPtr(ppvR3Ptr);
375 *ppvR3Ptr = NULL;
376 AssertPtr(pAddress);
377 AssertReturn(DBGFADDRESS_IS_VALID(pAddress), VERR_INVALID_PARAMETER);
378 VMCPU_ASSERT_VALID_EXT_RETURN(pVCpu->pVMR3, VERR_INVALID_STATE);
379
380 /*
381 * Convert it.
382 */
383 int rc;
384 if (VMCPU_IS_EMT(pVCpu))
385 rc = dbgfR3AddrToVolatileR3PtrOnVCpu(pVCpu, pAddress, fReadOnly, ppvR3Ptr);
386 else
387 {
388 PVMREQ pReq = NULL;
389 rc = VMR3ReqCall(pVCpu->pVMR3, VMREQDEST_FROM_VMCPU(pVCpu), &pReq, RT_INDEFINITE_WAIT,
390 (PFNRT)dbgfR3AddrToVolatileR3PtrOnVCpu, 4, pVCpu, pAddress, fReadOnly, ppvR3Ptr);
391 if (RT_SUCCESS(rc))
392 {
393 rc = pReq->iStatus;
394 VMR3ReqFree(pReq);
395 }
396 }
397
398 return rc;
399}
400
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