VirtualBox

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

最後變更 在這個檔案從45752是 45752,由 vboxsync 提交於 12 年 前

Don't call MMHyperIsInsideArea if we're using HM to execute code, it will return bogus results!

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id Revision
檔案大小: 16.2 KB
 
1/* $Id: DBGFAddr.cpp 45752 2013-04-26 01:32:02Z vboxsync $ */
2/** @file
3 * DBGF - Debugger Facility, Mixed Address Methods.
4 */
5
6/*
7 * Copyright (C) 2006-2013 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.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
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP LOG_GROUP_DBGF
23#include <VBox/vmm/dbgf.h>
24#include <VBox/vmm/pgm.h>
25#include <VBox/vmm/selm.h>
26#include <VBox/vmm/mm.h>
27#include "DBGFInternal.h"
28#include <VBox/vmm/vm.h>
29#include <VBox/vmm/uvm.h>
30
31#include <VBox/param.h>
32#include <VBox/err.h>
33#include <VBox/log.h>
34#include "internal/pgm.h"
35
36
37
38/**
39 * Checks if an address is in the HMA or not.
40 *
41 * @retval true if it's inside the HMA.
42 * @retval flase if it's not inside the HMA.
43 *
44 * @param pUVM The user mode VM handle.
45 * @param FlatPtr The address in question.
46 */
47DECLINLINE(bool) dbgfR3IsHMA(PUVM pUVM, RTGCUINTPTR FlatPtr)
48{
49 return !HMIsEnabled(pVM)
50 && MMHyperIsInsideArea(pUVM->pVM, FlatPtr);
51}
52
53
54/**
55 * Common worker for DBGFR3AddrFromSelOff and DBGFR3AddrFromSelInfoOff.
56 */
57static int dbgfR3AddrFromSelInfoOffWorker(PDBGFADDRESS pAddress, PCDBGFSELINFO pSelInfo, RTUINTPTR off)
58{
59 if (pSelInfo->fFlags & (DBGFSELINFO_FLAGS_INVALID | DBGFSELINFO_FLAGS_NOT_PRESENT))
60 return pSelInfo->fFlags & DBGFSELINFO_FLAGS_NOT_PRESENT
61 ? VERR_SELECTOR_NOT_PRESENT
62 : VERR_INVALID_SELECTOR;
63
64 /** @todo This all goes voodoo in long mode. */
65 /* check limit. */
66 if (DBGFSelInfoIsExpandDown(pSelInfo))
67 {
68 if ( !pSelInfo->u.Raw.Gen.u1Granularity
69 && off > UINT32_C(0xffff))
70 return VERR_OUT_OF_SELECTOR_BOUNDS;
71 if (off <= pSelInfo->cbLimit)
72 return VERR_OUT_OF_SELECTOR_BOUNDS;
73 }
74 else if (off > pSelInfo->cbLimit)
75 return VERR_OUT_OF_SELECTOR_BOUNDS;
76
77 pAddress->FlatPtr = pSelInfo->GCPtrBase + off;
78
79 /** @todo fix all these selector tests! */
80 if ( !pSelInfo->GCPtrBase
81 && pSelInfo->u.Raw.Gen.u1Granularity
82 && pSelInfo->u.Raw.Gen.u1DefBig)
83 pAddress->fFlags = DBGFADDRESS_FLAGS_FLAT;
84 else if (pSelInfo->cbLimit <= UINT32_C(0xffff))
85 pAddress->fFlags = DBGFADDRESS_FLAGS_FAR16;
86 else if (pSelInfo->cbLimit <= UINT32_C(0xffffffff))
87 pAddress->fFlags = DBGFADDRESS_FLAGS_FAR32;
88 else
89 pAddress->fFlags = DBGFADDRESS_FLAGS_FAR64;
90
91 return VINF_SUCCESS;
92}
93
94
95/**
96 * Creates a mixed address from a Sel:off pair.
97 *
98 * @returns VBox status code.
99 * @param pUVM The user mode VM handle.
100 * @param idCpu The CPU ID.
101 * @param pAddress Where to store the mixed address.
102 * @param Sel The selector part.
103 * @param off The offset part.
104 */
105VMMR3DECL(int) DBGFR3AddrFromSelOff(PUVM pUVM, VMCPUID idCpu, PDBGFADDRESS pAddress, RTSEL Sel, RTUINTPTR off)
106{
107 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
108 VM_ASSERT_VALID_EXT_RETURN(pUVM->pVM, VERR_INVALID_VM_HANDLE);
109 AssertReturn(idCpu < pUVM->cCpus, VERR_INVALID_PARAMETER);
110
111 pAddress->Sel = Sel;
112 pAddress->off = off;
113 if (Sel != DBGF_SEL_FLAT)
114 {
115 DBGFSELINFO SelInfo;
116 int rc = DBGFR3SelQueryInfo(pUVM, idCpu, Sel, DBGFSELQI_FLAGS_DT_GUEST | DBGFSELQI_FLAGS_DT_ADJ_64BIT_MODE, &SelInfo);
117 if (RT_FAILURE(rc))
118 return rc;
119 rc = dbgfR3AddrFromSelInfoOffWorker(pAddress, &SelInfo, off);
120 if (RT_FAILURE(rc))
121 return rc;
122 }
123 else
124 {
125 pAddress->FlatPtr = off;
126 pAddress->fFlags = DBGFADDRESS_FLAGS_FLAT;
127 }
128 pAddress->fFlags |= DBGFADDRESS_FLAGS_VALID;
129 if (dbgfR3IsHMA(pUVM, pAddress->FlatPtr))
130 pAddress->fFlags |= DBGFADDRESS_FLAGS_HMA;
131
132 return VINF_SUCCESS;
133}
134
135
136/**
137 * Creates a mixed address from selector info and an offset into the segment
138 * described by it.
139 *
140 * @returns VBox status code.
141 * @param pUVM The user mode VM handle.
142 * @param idCpu The CPU ID.
143 * @param pAddress Where to store the mixed address.
144 * @param pSelInfo The selector info.
145 * @param off The offset part.
146 */
147VMMR3DECL(int) DBGFR3AddrFromSelInfoOff(PUVM pUVM, PDBGFADDRESS pAddress, PCDBGFSELINFO pSelInfo, RTUINTPTR off)
148{
149 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_VM_HANDLE);
150 VM_ASSERT_VALID_EXT_RETURN(pUVM->pVM, VERR_INVALID_VM_HANDLE);
151
152 pAddress->Sel = pSelInfo->Sel;
153 pAddress->off = off;
154 int rc = dbgfR3AddrFromSelInfoOffWorker(pAddress, pSelInfo, off);
155 if (RT_FAILURE(rc))
156 return rc;
157
158 pAddress->fFlags |= DBGFADDRESS_FLAGS_VALID;
159 if (dbgfR3IsHMA(pUVM, pAddress->FlatPtr))
160 pAddress->fFlags |= DBGFADDRESS_FLAGS_HMA;
161
162 return VINF_SUCCESS;
163}
164
165
166/**
167 * Creates a mixed address from a flat address.
168 *
169 * @returns pAddress.
170 * @param pUVM The user mode VM handle.
171 * @param pAddress Where to store the mixed address.
172 * @param FlatPtr The flat pointer.
173 */
174VMMR3DECL(PDBGFADDRESS) DBGFR3AddrFromFlat(PUVM pUVM, PDBGFADDRESS pAddress, RTGCUINTPTR FlatPtr)
175{
176 UVM_ASSERT_VALID_EXT_RETURN(pUVM, NULL);
177 VM_ASSERT_VALID_EXT_RETURN(pUVM->pVM, NULL);
178 pAddress->Sel = DBGF_SEL_FLAT;
179 pAddress->off = FlatPtr;
180 pAddress->FlatPtr = FlatPtr;
181 pAddress->fFlags = DBGFADDRESS_FLAGS_FLAT | DBGFADDRESS_FLAGS_VALID;
182 if (dbgfR3IsHMA(pUVM, pAddress->FlatPtr))
183 pAddress->fFlags |= DBGFADDRESS_FLAGS_HMA;
184 return pAddress;
185}
186
187
188/**
189 * Creates a mixed address from a guest physical address.
190 *
191 * @returns pAddress.
192 * @param pUVM The user mode VM handle.
193 * @param pAddress Where to store the mixed address.
194 * @param PhysAddr The guest physical address.
195 */
196VMMR3DECL(PDBGFADDRESS) DBGFR3AddrFromPhys(PUVM pUVM, PDBGFADDRESS pAddress, RTGCPHYS PhysAddr)
197{
198 UVM_ASSERT_VALID_EXT_RETURN(pUVM, NULL);
199 pAddress->Sel = DBGF_SEL_FLAT;
200 pAddress->off = PhysAddr;
201 pAddress->FlatPtr = PhysAddr;
202 pAddress->fFlags = DBGFADDRESS_FLAGS_PHYS | DBGFADDRESS_FLAGS_VALID;
203 return pAddress;
204}
205
206
207/**
208 * Checks if the specified address is valid (checks the structure pointer too).
209 *
210 * @returns true if valid.
211 * @returns false if invalid.
212 * @param pUVM The user mode VM handle.
213 * @param pAddress The address to validate.
214 */
215VMMR3DECL(bool) DBGFR3AddrIsValid(PUVM pUVM, PCDBGFADDRESS pAddress)
216{
217 UVM_ASSERT_VALID_EXT_RETURN(pUVM, false);
218 if (!VALID_PTR(pAddress))
219 return false;
220 if (!DBGFADDRESS_IS_VALID(pAddress))
221 return false;
222 /* more? */
223 return true;
224}
225
226
227/**
228 * Called on the EMT for the VCpu.
229 *
230 * @returns VBox status code.
231 * @param pVCpu Pointer to the VMCPU.
232 * @param pAddress The address.
233 * @param pGCPhys Where to return the physical address.
234 */
235static DECLCALLBACK(int) dbgfR3AddrToPhysOnVCpu(PVMCPU pVCpu, PDBGFADDRESS pAddress, PRTGCPHYS pGCPhys)
236{
237 VMCPU_ASSERT_EMT(pVCpu);
238 /* This is just a wrapper because we cannot pass FlatPtr thru VMR3ReqCall directly. */
239 return PGMGstGetPage(pVCpu, pAddress->FlatPtr, NULL, pGCPhys);
240}
241
242
243/**
244 * Converts an address to a guest physical address.
245 *
246 * @returns VBox status code.
247 * @retval VINF_SUCCESS
248 * @retval VERR_INVALID_PARAMETER if the address is invalid.
249 * @retval VERR_INVALID_STATE if the VM is being terminated or if the virtual
250 * CPU handle is invalid.
251 * @retval VERR_NOT_SUPPORTED is the type of address cannot be converted.
252 * @retval VERR_PAGE_NOT_PRESENT
253 * @retval VERR_PAGE_TABLE_NOT_PRESENT
254 * @retval VERR_PAGE_DIRECTORY_PTR_NOT_PRESENT
255 * @retval VERR_PAGE_MAP_LEVEL4_NOT_PRESENT
256 *
257 * @param pUVM The user mode VM handle.
258 * @param idCpu The ID of the CPU context to convert virtual
259 * addresses.
260 * @param pAddress The address.
261 * @param pGCPhys Where to return the physical address.
262 */
263VMMR3DECL(int) DBGFR3AddrToPhys(PUVM pUVM, VMCPUID idCpu, PDBGFADDRESS pAddress, PRTGCPHYS pGCPhys)
264{
265 /*
266 * Parameter validation.
267 */
268 AssertPtr(pGCPhys);
269 *pGCPhys = NIL_RTGCPHYS;
270 AssertPtr(pAddress);
271 AssertReturn(DBGFADDRESS_IS_VALID(pAddress), VERR_INVALID_PARAMETER);
272 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_STATE);
273 PVM pVM = pUVM->pVM;
274 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
275 AssertReturn(idCpu < pUVM->cCpus, VERR_INVALID_PARAMETER);
276
277 /*
278 * Convert by address type.
279 */
280 int rc;
281 if (pAddress->fFlags & DBGFADDRESS_FLAGS_HMA)
282 rc = VERR_NOT_SUPPORTED;
283 else if (pAddress->fFlags & DBGFADDRESS_FLAGS_PHYS)
284 {
285 *pGCPhys = pAddress->FlatPtr;
286 rc = VINF_SUCCESS;
287 }
288 else
289 {
290 PVMCPU pVCpu = VMMGetCpuById(pVM, idCpu);
291 if (VMCPU_IS_EMT(pVCpu))
292 rc = dbgfR3AddrToPhysOnVCpu(pVCpu, pAddress, pGCPhys);
293 else
294 rc = VMR3ReqPriorityCallWaitU(pUVM, pVCpu->idCpu,
295 (PFNRT)dbgfR3AddrToPhysOnVCpu, 3, pVCpu, pAddress, pGCPhys);
296 }
297 return rc;
298}
299
300
301/**
302 * Converts an address to a host physical address.
303 *
304 * @returns VBox status code.
305 * @retval VINF_SUCCESS
306 * @retval VERR_INVALID_PARAMETER if the address is invalid.
307 * @retval VERR_INVALID_STATE if the VM is being terminated or if the virtual
308 * CPU handle is invalid.
309 * @retval VERR_NOT_SUPPORTED is the type of address cannot be converted.
310 * @retval VERR_PAGE_NOT_PRESENT
311 * @retval VERR_PAGE_TABLE_NOT_PRESENT
312 * @retval VERR_PAGE_DIRECTORY_PTR_NOT_PRESENT
313 * @retval VERR_PAGE_MAP_LEVEL4_NOT_PRESENT
314 * @retval VERR_PGM_PHYS_PAGE_RESERVED
315 * @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS
316 *
317 * @param pUVM The user mode VM handle.
318 * @param idCpu The ID of the CPU context to convert virtual
319 * addresses.
320 * @param pAddress The address.
321 * @param pHCPhys Where to return the physical address.
322 */
323VMMR3DECL(int) DBGFR3AddrToHostPhys(PUVM pUVM, VMCPUID idCpu, PDBGFADDRESS pAddress, PRTHCPHYS pHCPhys)
324{
325 /*
326 * Parameter validation.
327 */
328 AssertPtr(pHCPhys);
329 *pHCPhys = NIL_RTHCPHYS;
330 AssertPtr(pAddress);
331 AssertReturn(DBGFADDRESS_IS_VALID(pAddress), VERR_INVALID_PARAMETER);
332 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_STATE);
333 PVM pVM = pUVM->pVM;
334 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
335 AssertReturn(idCpu < pUVM->cCpus, VERR_INVALID_PARAMETER);
336
337 /*
338 * Convert it if we can.
339 */
340 int rc;
341 if (pAddress->fFlags & DBGFADDRESS_FLAGS_HMA)
342 rc = VERR_NOT_SUPPORTED; /** @todo implement this */
343 else
344 {
345 RTGCPHYS GCPhys;
346 rc = DBGFR3AddrToPhys(pUVM, idCpu, pAddress, &GCPhys);
347 if (RT_SUCCESS(rc))
348 rc = PGMPhysGCPhys2HCPhys(pVM, pAddress->FlatPtr, pHCPhys);
349 }
350 return rc;
351}
352
353
354/**
355 * Called on the EMT for the VCpu.
356 *
357 * @returns VBox status code.
358 *
359 * @param pUVM The user mode VM handle.
360 * @param idCpu The ID of the CPU context.
361 * @param pAddress The address.
362 * @param fReadOnly Whether returning a read-only page is fine or not.
363 * @param ppvR3Ptr Where to return the address.
364 */
365static DECLCALLBACK(int) dbgfR3AddrToVolatileR3PtrOnVCpu(PUVM pUVM, VMCPUID idCpu, PDBGFADDRESS pAddress, bool fReadOnly,
366 void **ppvR3Ptr)
367{
368 PVM pVM = pUVM->pVM;
369 VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
370 Assert(idCpu == VMMGetCpuId(pVM));
371
372 int rc;
373 if (pAddress->fFlags & DBGFADDRESS_FLAGS_HMA)
374 {
375 rc = VERR_NOT_SUPPORTED; /** @todo create some dedicated errors for this stuff. */
376 /** @todo this may assert, create a debug version of this which doesn't. */
377 if ( !HMIsEnabled(pVM)
378 && MMHyperIsInsideArea(pVM, pAddress->FlatPtr))
379 {
380 void *pv = MMHyperRCToCC(pVM, (RTRCPTR)pAddress->FlatPtr);
381 if (pv)
382 {
383 *ppvR3Ptr = pv;
384 rc = VINF_SUCCESS;
385 }
386 }
387 }
388 else
389 {
390 /*
391 * This is a tad ugly, but it gets the job done.
392 */
393 PGMPAGEMAPLOCK Lock;
394 if (pAddress->fFlags & DBGFADDRESS_FLAGS_PHYS)
395 {
396 if (fReadOnly)
397 rc = PGMPhysGCPhys2CCPtrReadOnly(pVM, pAddress->FlatPtr, (void const **)ppvR3Ptr, &Lock);
398 else
399 rc = PGMPhysGCPhys2CCPtr(pVM, pAddress->FlatPtr, ppvR3Ptr, &Lock);
400 }
401 else
402 {
403 PVMCPU pVCpu = VMMGetCpuById(pVM, idCpu);
404 if (fReadOnly)
405 rc = PGMPhysGCPtr2CCPtrReadOnly(pVCpu, pAddress->FlatPtr, (void const **)ppvR3Ptr, &Lock);
406 else
407 rc = PGMPhysGCPtr2CCPtr(pVCpu, pAddress->FlatPtr, ppvR3Ptr, &Lock);
408 }
409 if (RT_SUCCESS(rc))
410 PGMPhysReleasePageMappingLock(pVM, &Lock);
411 }
412 return rc;
413}
414
415
416
417
418/**
419 * Converts an address to a volatile host virtual address.
420 *
421 * @returns VBox status code.
422 * @retval VINF_SUCCESS
423 * @retval VERR_INVALID_PARAMETER if the address is invalid.
424 * @retval VERR_INVALID_STATE if the VM is being terminated or if the virtual
425 * CPU handle is invalid.
426 * @retval VERR_NOT_SUPPORTED is the type of address cannot be converted.
427 * @retval VERR_PAGE_NOT_PRESENT
428 * @retval VERR_PAGE_TABLE_NOT_PRESENT
429 * @retval VERR_PAGE_DIRECTORY_PTR_NOT_PRESENT
430 * @retval VERR_PAGE_MAP_LEVEL4_NOT_PRESENT
431 * @retval VERR_PGM_PHYS_PAGE_RESERVED
432 * @retval VERR_PGM_INVALID_GC_PHYSICAL_ADDRESS
433 *
434 * @param pUVM The user mode VM handle.
435 * @param idCpu The ID of the CPU context to convert virtual
436 * addresses.
437 * @param pAddress The address.
438 * @param fReadOnly Whether returning a read-only page is fine or not.
439 * If set to thru the page may have to be made writable
440 * before we return.
441 * @param ppvR3Ptr Where to return the address.
442 */
443VMMR3DECL(int) DBGFR3AddrToVolatileR3Ptr(PUVM pUVM, VMCPUID idCpu, PDBGFADDRESS pAddress, bool fReadOnly, void **ppvR3Ptr)
444{
445 /*
446 * Parameter validation.
447 */
448 AssertPtr(ppvR3Ptr);
449 *ppvR3Ptr = NULL;
450 AssertPtr(pAddress);
451 AssertReturn(DBGFADDRESS_IS_VALID(pAddress), VERR_INVALID_PARAMETER);
452 UVM_ASSERT_VALID_EXT_RETURN(pUVM, VERR_INVALID_STATE);
453 AssertReturn(idCpu < pUVM->cCpus, VERR_INVALID_PARAMETER);
454
455 /*
456 * Convert it.
457 */
458 return VMR3ReqPriorityCallWaitU(pUVM, idCpu, (PFNRT)dbgfR3AddrToVolatileR3PtrOnVCpu, 5,
459 pUVM, idCpu, pAddress, fReadOnly, ppvR3Ptr);
460}
461
462
463/**
464 * Adds an offset to an address.
465 *
466 * @returns pAddress.
467 *
468 * @param pAddress The address.
469 * @param uAddend How much to add.
470 *
471 * @remarks No address space or segment limit checks are performed,
472 */
473VMMR3DECL(PDBGFADDRESS) DBGFR3AddrAdd(PDBGFADDRESS pAddress, RTGCUINTPTR uAddend)
474{
475 /*
476 * Parameter validation.
477 */
478 AssertPtrReturn(pAddress, NULL);
479 AssertReturn(DBGFADDRESS_IS_VALID(pAddress), NULL);
480
481 /*
482 * Add the stuff.
483 */
484 pAddress->off += uAddend;
485 pAddress->FlatPtr += uAddend;
486
487 return pAddress;
488}
489
490
491/**
492 * Subtracts an offset from an address.
493 *
494 * @returns VINF_SUCCESS on success.
495 *
496 * @param pAddress The address.
497 * @param uSubtrahend How much to subtract.
498 *
499 * @remarks No address space or segment limit checks are performed,
500 */
501VMMR3DECL(PDBGFADDRESS) DBGFR3AddrSub(PDBGFADDRESS pAddress, RTGCUINTPTR uSubtrahend)
502{
503 /*
504 * Parameter validation.
505 */
506 AssertPtrReturn(pAddress, NULL);
507 AssertReturn(DBGFADDRESS_IS_VALID(pAddress), NULL);
508
509 /*
510 * Add the stuff.
511 */
512 pAddress->off -= uSubtrahend;
513 pAddress->FlatPtr -= uSubtrahend;
514
515 return pAddress;
516}
517
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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