VirtualBox

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

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

DBGFAddr.cpp: todo.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 14.2 KB
Line 
1/* $Id: DBGFAddr.cpp 19307 2009-05-03 01:22:23Z 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.215389.xyz. 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 idCpu The CPU ID.
58 * @param pAddress Where to store the mixed address.
59 * @param Sel The selector part.
60 * @param off The offset part.
61 */
62VMMR3DECL(int) DBGFR3AddrFromSelOff(PVM pVM, VMCPUID idCpu, PDBGFADDRESS pAddress, RTSEL Sel, RTUINTPTR off)
63{
64 AssertReturn(idCpu < pVM->cCPUs, VERR_INVALID_PARAMETER);
65
66 pAddress->Sel = Sel;
67 pAddress->off = off;
68 if (Sel != DBGF_SEL_FLAT)
69 {
70 /** @todo cannot call this on a foreign thread. */
71 SELMSELINFO SelInfo;
72 int rc = SELMR3GetSelectorInfo(pVM, VMMGetCpuById(pVM, idCpu), Sel, &SelInfo);
73 if (RT_FAILURE(rc))
74 return rc;
75
76 /* check limit. */
77 if (SELMSelInfoIsExpandDown(&SelInfo))
78 {
79 if ( !SelInfo.Raw.Gen.u1Granularity
80 && off > UINT32_C(0xffff))
81 return VERR_OUT_OF_SELECTOR_BOUNDS;
82 if (off <= SelInfo.cbLimit)
83 return VERR_OUT_OF_SELECTOR_BOUNDS;
84 }
85 else if (off > SelInfo.cbLimit)
86 return VERR_OUT_OF_SELECTOR_BOUNDS;
87
88 pAddress->FlatPtr = SelInfo.GCPtrBase + off;
89 /** @todo fix this flat selector test! */
90 if ( !SelInfo.GCPtrBase
91 && SelInfo.Raw.Gen.u1Granularity
92 && SelInfo.Raw.Gen.u1DefBig)
93 pAddress->fFlags = DBGFADDRESS_FLAGS_FLAT;
94 else if (SelInfo.cbLimit <= UINT32_C(0xffff))
95 pAddress->fFlags = DBGFADDRESS_FLAGS_FAR16;
96 else if (SelInfo.cbLimit <= UINT32_C(0xffffffff))
97 pAddress->fFlags = DBGFADDRESS_FLAGS_FAR32;
98 else
99 pAddress->fFlags = DBGFADDRESS_FLAGS_FAR64;
100 }
101 else
102 {
103 pAddress->FlatPtr = off;
104 pAddress->fFlags = DBGFADDRESS_FLAGS_FLAT;
105 }
106 pAddress->fFlags |= DBGFADDRESS_FLAGS_VALID;
107 if (dbgfR3IsHMA(pVM, pAddress->FlatPtr))
108 pAddress->fFlags |= DBGFADDRESS_FLAGS_HMA;
109
110 return VINF_SUCCESS;
111}
112
113
114/**
115 * Creates a mixed address from a flat address.
116 *
117 * @returns pAddress.
118 * @param pVM The VM handle.
119 * @param pAddress Where to store the mixed address.
120 * @param FlatPtr The flat pointer.
121 */
122VMMR3DECL(PDBGFADDRESS) DBGFR3AddrFromFlat(PVM pVM, PDBGFADDRESS pAddress, RTGCUINTPTR FlatPtr)
123{
124 pAddress->Sel = DBGF_SEL_FLAT;
125 pAddress->off = FlatPtr;
126 pAddress->FlatPtr = FlatPtr;
127 pAddress->fFlags = DBGFADDRESS_FLAGS_FLAT | DBGFADDRESS_FLAGS_VALID;
128 if (dbgfR3IsHMA(pVM, pAddress->FlatPtr))
129 pAddress->fFlags |= DBGFADDRESS_FLAGS_HMA;
130 return pAddress;
131}
132
133
134/**
135 * Creates a mixed address from a guest physical address.
136 *
137 * @returns pAddress.
138 * @param pVM The VM handle.
139 * @param pAddress Where to store the mixed address.
140 * @param PhysAddr The guest physical address.
141 */
142VMMR3DECL(PDBGFADDRESS) DBGFR3AddrFromPhys(PVM pVM, PDBGFADDRESS pAddress, RTGCPHYS PhysAddr)
143{
144 pAddress->Sel = DBGF_SEL_FLAT;
145 pAddress->off = PhysAddr;
146 pAddress->FlatPtr = PhysAddr;
147 pAddress->fFlags = DBGFADDRESS_FLAGS_PHYS | DBGFADDRESS_FLAGS_VALID;
148 return pAddress;
149}
150
151
152/**
153 * Checks if the specified address is valid (checks the structure pointer too).
154 *
155 * @returns true if valid.
156 * @returns false if invalid.
157 * @param pVM The VM handle.
158 * @param pAddress The address to validate.
159 */
160VMMR3DECL(bool) DBGFR3AddrIsValid(PVM pVM, PCDBGFADDRESS pAddress)
161{
162 if (!VALID_PTR(pAddress))
163 return false;
164 if (!DBGFADDRESS_IS_VALID(pAddress))
165 return false;
166 /* more? */
167 return true;
168}
169
170
171/**
172 * Called on the EMT for the VCpu.
173 *
174 * @returns VBox status code.
175 * @param pVCpu The virtual CPU handle.
176 * @param pAddress The address.
177 * @param pGCPhys Where to return the physical address.
178 */
179static DECLCALLBACK(int) dbgfR3AddrToPhysOnVCpu(PVMCPU pVCpu, PDBGFADDRESS pAddress, PRTGCPHYS pGCPhys)
180{
181 VMCPU_ASSERT_EMT(pVCpu);
182 /* This is just a wrapper because we cannot pass FlatPtr thru VMR3ReqCall directly. */
183 return PGMGstGetPage(pVCpu, pAddress->FlatPtr, NULL, pGCPhys);
184}
185
186
187/**
188 * Converts an address to a guest physical address.
189 *
190 * @returns VBox status code.
191 * @retval VINF_SUCCESS
192 * @retval VERR_INVALID_PARAMETER if the address is invalid.
193 * @retval VERR_INVALID_STATE if the VM is being terminated or if the virtual
194 * CPU handle is invalid.
195 * @retval VERR_NOT_SUPPORTED is the type of address cannot be converted.
196 * @retval VERR_PAGE_NOT_PRESENT
197 * @retval VERR_PAGE_TABLE_NOT_PRESENT
198 * @retval VERR_PAGE_DIRECTORY_PTR_NOT_PRESENT
199 * @retval VERR_PAGE_MAP_LEVEL4_NOT_PRESENT
200 *
201 * @param pVM The VM handle.
202 * @param idCpu The ID of the CPU context to convert virtual
203 * addresses.
204 * @param pAddress The address.
205 * @param pGCPhys Where to return the physical address.
206 */
207VMMR3DECL(int) DBGFR3AddrToPhys(PVM pVM, VMCPUID idCpu, PDBGFADDRESS pAddress, PRTGCPHYS pGCPhys)
208{
209 /*
210 * Parameter validation.
211 */
212 AssertPtr(pGCPhys);
213 *pGCPhys = NIL_RTGCPHYS;
214 AssertPtr(pAddress);
215 AssertReturn(DBGFADDRESS_IS_VALID(pAddress), VERR_INVALID_PARAMETER);
216 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_STATE);
217 AssertReturn(idCpu < pVM->cCPUs, VERR_INVALID_PARAMETER);
218
219 /*
220 * Convert by address type.
221 */
222 int rc;
223 if (pAddress->fFlags & DBGFADDRESS_FLAGS_HMA)
224 rc = VERR_NOT_SUPPORTED;
225 else if (pAddress->fFlags & DBGFADDRESS_FLAGS_PHYS)
226 {
227 *pGCPhys = pAddress->FlatPtr;
228 rc = VINF_SUCCESS;
229 }
230 else
231 {
232 PVMCPU pVCpu = VMMGetCpuById(pVM, idCpu);
233 if (VMCPU_IS_EMT(pVCpu))
234 rc = dbgfR3AddrToPhysOnVCpu(pVCpu, pAddress, pGCPhys);
235 else
236 {
237 PVMREQ pReq = NULL;
238 rc = VMR3ReqCall(pVCpu->pVMR3, pVCpu->idCpu, &pReq, RT_INDEFINITE_WAIT,
239 (PFNRT)dbgfR3AddrToPhysOnVCpu, 3, pVCpu, pAddress, pGCPhys);
240 if (RT_SUCCESS(rc))
241 {
242 rc = pReq->iStatus;
243 VMR3ReqFree(pReq);
244 }
245 }
246 }
247 return rc;
248}
249
250
251/**
252 * Converts an address to a host physical address.
253 *
254 * @returns VBox status code.
255 * @retval VINF_SUCCESS
256 * @retval VERR_INVALID_PARAMETER if the address is invalid.
257 * @retval VERR_INVALID_STATE if the VM is being terminated or if the virtual
258 * CPU handle is invalid.
259 * @retval VERR_NOT_SUPPORTED is the type of address cannot be converted.
260 * @retval VERR_PAGE_NOT_PRESENT
261 * @retval VERR_PAGE_TABLE_NOT_PRESENT
262 * @retval VERR_PAGE_DIRECTORY_PTR_NOT_PRESENT
263 * @retval VERR_PAGE_MAP_LEVEL4_NOT_PRESENT
264 * @retval VERR_PGM_PHYS_PAGE_RESERVED
265 * @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS
266 *
267 * @param pVM The VM handle.
268 * @param idCpu The ID of the CPU context to convert virtual
269 * addresses.
270 * @param pAddress The address.
271 * @param pHCPhys Where to return the physical address.
272 */
273VMMR3DECL(int) DBGFR3AddrToHostPhys(PVM pVM, VMCPUID idCpu, PDBGFADDRESS pAddress, PRTHCPHYS pHCPhys)
274{
275 /*
276 * Parameter validation.
277 */
278 AssertPtr(pHCPhys);
279 *pHCPhys = NIL_RTHCPHYS;
280 AssertPtr(pAddress);
281 AssertReturn(DBGFADDRESS_IS_VALID(pAddress), VERR_INVALID_PARAMETER);
282 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_STATE);
283 AssertReturn(idCpu < pVM->cCPUs, VERR_INVALID_PARAMETER);
284
285 /*
286 * Convert it if we can.
287 */
288 int rc;
289 if (pAddress->fFlags & DBGFADDRESS_FLAGS_HMA)
290 rc = VERR_NOT_SUPPORTED; /** @todo implement this */
291 else
292 {
293 RTGCPHYS GCPhys;
294 rc = DBGFR3AddrToPhys(pVM, idCpu, pAddress, &GCPhys);
295 if (RT_SUCCESS(rc))
296 rc = PGMPhysGCPhys2HCPhys(pVM, pAddress->FlatPtr, pHCPhys);
297 }
298 return rc;
299}
300
301
302/**
303 * Called on the EMT for the VCpu.
304 *
305 * @returns VBox status code.
306 *
307 * @param pVM The VM handle.
308 * @param idCpu The ID of the CPU context.
309 * @param pAddress The address.
310 * @param fReadOnly Whether returning a read-only page is fine or not.
311 * @param ppvR3Ptr Where to return the address.
312 */
313static DECLCALLBACK(int) dbgfR3AddrToVolatileR3PtrOnVCpu(PVM pVM, VMCPUID idCpu, PDBGFADDRESS pAddress, bool fReadOnly, void **ppvR3Ptr)
314{
315 Assert(idCpu == VMMGetCpuId(pVM));
316
317 int rc;
318 if (pAddress->fFlags & DBGFADDRESS_FLAGS_HMA)
319 {
320 rc = VERR_NOT_SUPPORTED; /** @todo create some dedicated errors for this stuff. */
321 /** @todo this may assert, create a debug version of this which doesn't. */
322 if (MMHyperIsInsideArea(pVM, pAddress->FlatPtr))
323 {
324 void *pv = MMHyperRCToCC(pVM, (RTRCPTR)pAddress->FlatPtr);
325 if (pv)
326 {
327 *ppvR3Ptr = pv;
328 rc = VINF_SUCCESS;
329 }
330 }
331 }
332 else
333 {
334 /*
335 * This is a tad ugly, but it gets the job done.
336 */
337 PGMPAGEMAPLOCK Lock;
338 if (pAddress->fFlags & DBGFADDRESS_FLAGS_PHYS)
339 {
340 if (fReadOnly)
341 rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, pAddress->FlatPtr, (void const **)ppvR3Ptr, &Lock);
342 else
343 rc = PGMPhysGCPhys2CCPtr(pVM, pAddress->FlatPtr, ppvR3Ptr, &Lock);
344 }
345 else
346 {
347 PVMCPU pVCpu = VMMGetCpuById(pVM, idCpu);
348 if (fReadOnly)
349 rc = PGMPhysGCPtr2CCPtrReadOnly(pVCpu, pAddress->FlatPtr, (void const **)ppvR3Ptr, &Lock);
350 else
351 rc = PGMPhysGCPtr2CCPtr(pVCpu, pAddress->FlatPtr, ppvR3Ptr, &Lock);
352 }
353 if (RT_SUCCESS(rc))
354 PGMPhysReleasePageMappingLock(pVM, &Lock);
355 }
356 return rc;
357}
358
359
360
361
362/**
363 * Converts an address to a volatile host virtual address.
364 *
365 * @returns VBox status code.
366 * @retval VINF_SUCCESS
367 * @retval VERR_INVALID_PARAMETER if the address is invalid.
368 * @retval VERR_INVALID_STATE if the VM is being terminated or if the virtual
369 * CPU handle is invalid.
370 * @retval VERR_NOT_SUPPORTED is the type of address cannot be converted.
371 * @retval VERR_PAGE_NOT_PRESENT
372 * @retval VERR_PAGE_TABLE_NOT_PRESENT
373 * @retval VERR_PAGE_DIRECTORY_PTR_NOT_PRESENT
374 * @retval VERR_PAGE_MAP_LEVEL4_NOT_PRESENT
375 * @retval VERR_PGM_PHYS_PAGE_RESERVED
376 * @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS
377 *
378 * @param pVM The VM handle.
379 * @param idCpu The ID of the CPU context to convert virtual
380 * addresses.
381 * @param pAddress The address.
382 * @param fReadOnly Whether returning a read-only page is fine or not.
383 * If set to thru the page may have to be made writable
384 * before we return.
385 * @param ppvR3Ptr Where to return the address.
386 */
387VMMR3DECL(int) DBGFR3AddrToVolatileR3Ptr(PVM pVM, VMCPUID idCpu, PDBGFADDRESS pAddress, bool fReadOnly, void **ppvR3Ptr)
388{
389 /*
390 * Parameter validation.
391 */
392 AssertPtr(ppvR3Ptr);
393 *ppvR3Ptr = NULL;
394 AssertPtr(pAddress);
395 AssertReturn(DBGFADDRESS_IS_VALID(pAddress), VERR_INVALID_PARAMETER);
396 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_STATE);
397 AssertReturn(idCpu < pVM->cCPUs, VERR_INVALID_PARAMETER);
398
399 /*
400 * Convert it.
401 */
402 PVMREQ pReq = NULL;
403 int rc = VMR3ReqCall(pVM, idCpu, &pReq, RT_INDEFINITE_WAIT,
404 (PFNRT)dbgfR3AddrToVolatileR3PtrOnVCpu, 5, pVM, idCpu, pAddress, fReadOnly, ppvR3Ptr);
405 if (RT_SUCCESS(rc))
406 {
407 rc = pReq->iStatus;
408 VMR3ReqFree(pReq);
409 }
410
411 return rc;
412}
413
414
415/**
416 * Adds an offset to an address.
417 *
418 * @returns pAddress.
419 *
420 * @param pAddress The address.
421 * @param uAddend How much to add.
422 *
423 * @remarks No address space or segment limit checks are performed,
424 */
425VMMR3DECL(PDBGFADDRESS) DBGFR3AddrAdd(PDBGFADDRESS pAddress, RTGCUINTPTR uAddend)
426{
427 /*
428 * Parameter validation.
429 */
430 AssertPtrReturn(pAddress, NULL);
431 AssertReturn(DBGFADDRESS_IS_VALID(pAddress), NULL);
432
433 /*
434 * Add the stuff.
435 */
436 pAddress->off += uAddend;
437 pAddress->FlatPtr += uAddend;
438
439 return pAddress;
440}
441
442
443/**
444 * Subtracts an offset from an address.
445 *
446 * @returns VINF_SUCCESS on success.
447 *
448 * @param pAddress The address.
449 * @param uSubtrahend How much to subtract.
450 *
451 * @remarks No address space or segment limit checks are performed,
452 */
453VMMR3DECL(PDBGFADDRESS) DBGFR3AddrSub(PDBGFADDRESS pAddress, RTGCUINTPTR uSubtrahend)
454{
455 /*
456 * Parameter validation.
457 */
458 AssertPtrReturn(pAddress, NULL);
459 AssertReturn(DBGFADDRESS_IS_VALID(pAddress), NULL);
460
461 /*
462 * Add the stuff.
463 */
464 pAddress->off -= uSubtrahend;
465 pAddress->FlatPtr -= uSubtrahend;
466
467 return pAddress;
468}
469
Note: See TracBrowser for help on using the repository browser.

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