VirtualBox

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

Last change on this file since 21990 was 19463, checked in by vboxsync, 15 years ago

dbgfsel.h,VMM,DBGC: Named the union containing the raw data to shut up gcc warnings.

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