VirtualBox

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

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

VMM,VBoxDbg: SMP refactoring, part 1.

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