VirtualBox

source: vbox/trunk/src/VBox/VMM/VMMR0/DBGFR0Bp.cpp@ 95140

Last change on this file since 95140 was 93554, checked in by vboxsync, 3 years ago

VMM: Changed PAGE_SIZE -> GUEST_PAGE_SIZE / HOST_PAGE_SIZE, PAGE_SHIFT -> GUEST_PAGE_SHIFT / HOST_PAGE_SHIFT, and PAGE_OFFSET_MASK -> GUEST_PAGE_OFFSET_MASK / HOST_PAGE_OFFSET_MASK. Also removed most usage of ASMMemIsZeroPage and ASMMemZeroPage since the host and guest page size doesn't need to be the same any more. Some work left to do in the page pool code. bugref:9898

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.3 KB
Line 
1/* $Id: DBGFR0Bp.cpp 93554 2022-02-02 22:57:02Z vboxsync $ */
2/** @file
3 * DBGF - Debugger Facility, R0 breakpoint management part.
4 */
5
6/*
7 * Copyright (C) 2020-2022 Oracle Corporation
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
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_DBGF
23#include "DBGFInternal.h"
24#include <VBox/vmm/gvm.h>
25#include <VBox/vmm/gvmm.h>
26#include <VBox/vmm/vmm.h>
27
28#include <VBox/log.h>
29#include <VBox/sup.h>
30#include <iprt/asm.h>
31#include <iprt/assert.h>
32#include <iprt/errcore.h>
33#include <iprt/ctype.h>
34#include <iprt/mem.h>
35#include <iprt/memobj.h>
36#include <iprt/process.h>
37#include <iprt/string.h>
38
39#include "dtrace/VBoxVMM.h"
40
41
42/*********************************************************************************************************************************
43* Internal Functions *
44*********************************************************************************************************************************/
45
46/**
47 * Used by DBGFR0InitPerVM() to initialize the breakpoint manager.
48 *
49 * @returns nothing.
50 * @param pGVM The global (ring-0) VM structure.
51 */
52DECLHIDDEN(void) dbgfR0BpInit(PGVM pGVM)
53{
54 pGVM->dbgfr0.s.hMemObjBpOwners = NIL_RTR0MEMOBJ;
55 pGVM->dbgfr0.s.hMapObjBpOwners = NIL_RTR0MEMOBJ;
56 //pGVM->dbgfr0.s.paBpOwnersR0 = NULL;
57
58 for (uint32_t i = 0; i < RT_ELEMENTS(pGVM->dbgfr0.s.aBpChunks); i++)
59 {
60 PDBGFBPCHUNKR0 pBpChunk = &pGVM->dbgfr0.s.aBpChunks[i];
61
62 pBpChunk->hMemObj = NIL_RTR0MEMOBJ;
63 pBpChunk->hMapObj = NIL_RTR0MEMOBJ;
64 //pBpChunk->paBpBaseSharedR0 = NULL;
65 //pBpChunk->paBpBaseR0Only = NULL;
66 }
67
68 for (uint32_t i = 0; i < RT_ELEMENTS(pGVM->dbgfr0.s.aBpL2TblChunks); i++)
69 {
70 PDBGFBPL2TBLCHUNKR0 pL2Chunk = &pGVM->dbgfr0.s.aBpL2TblChunks[i];
71
72 pL2Chunk->hMemObj = NIL_RTR0MEMOBJ;
73 pL2Chunk->hMapObj = NIL_RTR0MEMOBJ;
74 //pL2Chunk->paBpL2TblBaseSharedR0 = NULL;
75 }
76
77 pGVM->dbgfr0.s.hMemObjBpLocL1 = NIL_RTR0MEMOBJ;
78 pGVM->dbgfr0.s.hMapObjBpLocL1 = NIL_RTR0MEMOBJ;
79 pGVM->dbgfr0.s.hMemObjBpLocPortIo = NIL_RTR0MEMOBJ;
80 pGVM->dbgfr0.s.hMapObjBpLocPortIo = NIL_RTR0MEMOBJ;
81 //pGVM->dbgfr0.s.paBpLocL1R0 = NULL;
82 //pGVM->dbgfr0.s.paBpLocPortIoR0 = NULL;
83 //pGVM->dbgfr0.s.fInit = false;
84}
85
86
87/**
88 * Used by DBGFR0CleanupVM to destroy the breakpoint manager.
89 *
90 * This is done during VM cleanup so that we're sure there are no active threads
91 * using the breakpoint code.
92 *
93 * @param pGVM The global (ring-0) VM structure.
94 */
95DECLHIDDEN(void) dbgfR0BpDestroy(PGVM pGVM)
96{
97 if (pGVM->dbgfr0.s.hMemObjBpOwners != NIL_RTR0MEMOBJ)
98 {
99 Assert(pGVM->dbgfr0.s.hMapObjBpOwners != NIL_RTR0MEMOBJ);
100 AssertPtr(pGVM->dbgfr0.s.paBpOwnersR0);
101
102 RTR0MEMOBJ hMemObj = pGVM->dbgfr0.s.hMapObjBpOwners;
103 pGVM->dbgfr0.s.hMapObjBpOwners = NIL_RTR0MEMOBJ;
104 RTR0MemObjFree(hMemObj, true);
105
106 hMemObj = pGVM->dbgfr0.s.hMemObjBpOwners;
107 pGVM->dbgfr0.s.hMemObjBpOwners = NIL_RTR0MEMOBJ;
108 RTR0MemObjFree(hMemObj, true);
109 }
110
111 if (pGVM->dbgfr0.s.fInit)
112 {
113 Assert(pGVM->dbgfr0.s.hMemObjBpLocL1 != NIL_RTR0MEMOBJ);
114 AssertPtr(pGVM->dbgfr0.s.paBpLocL1R0);
115
116 /*
117 * Free all allocated memory and ring-3 mapping objects.
118 */
119 RTR0MEMOBJ hMemObj = pGVM->dbgfr0.s.hMemObjBpLocL1;
120 pGVM->dbgfr0.s.hMemObjBpLocL1 = NIL_RTR0MEMOBJ;
121 pGVM->dbgfr0.s.paBpLocL1R0 = NULL;
122 RTR0MemObjFree(hMemObj, true);
123
124 if (pGVM->dbgfr0.s.paBpLocPortIoR0)
125 {
126 Assert(pGVM->dbgfr0.s.hMemObjBpLocPortIo != NIL_RTR0MEMOBJ);
127 Assert(pGVM->dbgfr0.s.hMapObjBpLocPortIo != NIL_RTR0MEMOBJ);
128
129 hMemObj = pGVM->dbgfr0.s.hMapObjBpLocPortIo;
130 pGVM->dbgfr0.s.hMapObjBpLocPortIo = NIL_RTR0MEMOBJ;
131 RTR0MemObjFree(hMemObj, true);
132
133 hMemObj = pGVM->dbgfr0.s.hMemObjBpLocPortIo;
134 pGVM->dbgfr0.s.hMemObjBpLocPortIo = NIL_RTR0MEMOBJ;
135 pGVM->dbgfr0.s.paBpLocPortIoR0 = NULL;
136 RTR0MemObjFree(hMemObj, true);
137 }
138
139 for (uint32_t i = 0; i < RT_ELEMENTS(pGVM->dbgfr0.s.aBpChunks); i++)
140 {
141 PDBGFBPCHUNKR0 pBpChunk = &pGVM->dbgfr0.s.aBpChunks[i];
142
143 if (pBpChunk->hMemObj != NIL_RTR0MEMOBJ)
144 {
145 Assert(pBpChunk->hMapObj != NIL_RTR0MEMOBJ);
146
147 pBpChunk->paBpBaseSharedR0 = NULL;
148 pBpChunk->paBpBaseR0Only = NULL;
149
150 hMemObj = pBpChunk->hMapObj;
151 pBpChunk->hMapObj = NIL_RTR0MEMOBJ;
152 RTR0MemObjFree(hMemObj, true);
153
154 hMemObj = pBpChunk->hMemObj;
155 pBpChunk->hMemObj = NIL_RTR0MEMOBJ;
156 RTR0MemObjFree(hMemObj, true);
157 }
158 }
159
160 for (uint32_t i = 0; i < RT_ELEMENTS(pGVM->dbgfr0.s.aBpL2TblChunks); i++)
161 {
162 PDBGFBPL2TBLCHUNKR0 pL2Chunk = &pGVM->dbgfr0.s.aBpL2TblChunks[i];
163
164 if (pL2Chunk->hMemObj != NIL_RTR0MEMOBJ)
165 {
166 Assert(pL2Chunk->hMapObj != NIL_RTR0MEMOBJ);
167
168 pL2Chunk->paBpL2TblBaseSharedR0 = NULL;
169
170 hMemObj = pL2Chunk->hMapObj;
171 pL2Chunk->hMapObj = NIL_RTR0MEMOBJ;
172 RTR0MemObjFree(hMemObj, true);
173
174 hMemObj = pL2Chunk->hMemObj;
175 pL2Chunk->hMemObj = NIL_RTR0MEMOBJ;
176 RTR0MemObjFree(hMemObj, true);
177 }
178 }
179
180 pGVM->dbgfr0.s.fInit = false;
181 }
182#ifdef RT_STRICT
183 else
184 {
185 Assert(pGVM->dbgfr0.s.hMemObjBpLocL1 == NIL_RTR0MEMOBJ);
186 Assert(!pGVM->dbgfr0.s.paBpLocL1R0);
187
188 Assert(pGVM->dbgfr0.s.hMemObjBpLocPortIo == NIL_RTR0MEMOBJ);
189 Assert(!pGVM->dbgfr0.s.paBpLocPortIoR0);
190
191 for (uint32_t i = 0; i < RT_ELEMENTS(pGVM->dbgfr0.s.aBpChunks); i++)
192 {
193 PDBGFBPCHUNKR0 pBpChunk = &pGVM->dbgfr0.s.aBpChunks[i];
194
195 Assert(pBpChunk->hMemObj == NIL_RTR0MEMOBJ);
196 Assert(pBpChunk->hMapObj == NIL_RTR0MEMOBJ);
197 Assert(!pBpChunk->paBpBaseSharedR0);
198 Assert(!pBpChunk->paBpBaseR0Only);
199 }
200
201 for (uint32_t i = 0; i < RT_ELEMENTS(pGVM->dbgfr0.s.aBpL2TblChunks); i++)
202 {
203 PDBGFBPL2TBLCHUNKR0 pL2Chunk = &pGVM->dbgfr0.s.aBpL2TblChunks[i];
204
205 Assert(pL2Chunk->hMemObj == NIL_RTR0MEMOBJ);
206 Assert(pL2Chunk->hMapObj == NIL_RTR0MEMOBJ);
207 Assert(!pL2Chunk->paBpL2TblBaseSharedR0);
208 }
209 }
210#endif
211}
212
213
214/**
215 * Worker for DBGFR0BpInitReqHandler() that does the actual initialization.
216 *
217 * @returns VBox status code.
218 * @param pGVM The global (ring-0) VM structure.
219 * @param ppaBpLocL1R3 Where to return the ring-3 L1 lookup table address on success.
220 * @thread EMT(0)
221 */
222static int dbgfR0BpInitWorker(PGVM pGVM, R3PTRTYPE(volatile uint32_t *) *ppaBpLocL1R3)
223{
224 /*
225 * Figure out how much memory we need for the L1 lookup table and allocate it.
226 */
227 uint32_t const cbL1Loc = RT_ALIGN_32(UINT16_MAX * sizeof(uint32_t), HOST_PAGE_SIZE);
228
229 RTR0MEMOBJ hMemObj;
230 int rc = RTR0MemObjAllocPage(&hMemObj, cbL1Loc, false /*fExecutable*/);
231 if (RT_FAILURE(rc))
232 return rc;
233 RT_BZERO(RTR0MemObjAddress(hMemObj), cbL1Loc);
234
235 /* Map it. */
236 RTR0MEMOBJ hMapObj;
237 rc = RTR0MemObjMapUserEx(&hMapObj, hMemObj, (RTR3PTR)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE, RTR0ProcHandleSelf(),
238 0 /*offSub*/, cbL1Loc);
239 if (RT_SUCCESS(rc))
240 {
241 pGVM->dbgfr0.s.hMemObjBpLocL1 = hMemObj;
242 pGVM->dbgfr0.s.hMapObjBpLocL1 = hMapObj;
243 pGVM->dbgfr0.s.paBpLocL1R0 = (volatile uint32_t *)RTR0MemObjAddress(hMemObj);
244
245 /*
246 * We're done.
247 */
248 *ppaBpLocL1R3 = RTR0MemObjAddressR3(hMapObj);
249 pGVM->dbgfr0.s.fInit = true;
250 return rc;
251 }
252
253 RTR0MemObjFree(hMemObj, true);
254 return rc;
255}
256
257
258/**
259 * Worker for DBGFR0BpPortIoInitReqHandler() that does the actual initialization.
260 *
261 * @returns VBox status code.
262 * @param pGVM The global (ring-0) VM structure.
263 * @param ppaBpLocPortIoR3 Where to return the ring-3 L1 lookup table address on success.
264 * @thread EMT(0)
265 */
266static int dbgfR0BpPortIoInitWorker(PGVM pGVM, R3PTRTYPE(volatile uint32_t *) *ppaBpLocPortIoR3)
267{
268 /*
269 * Figure out how much memory we need for the I/O port breakpoint lookup table and allocate it.
270 */
271 uint32_t const cbPortIoLoc = RT_ALIGN_32(UINT16_MAX * sizeof(uint32_t), HOST_PAGE_SIZE);
272
273 RTR0MEMOBJ hMemObj;
274 int rc = RTR0MemObjAllocPage(&hMemObj, cbPortIoLoc, false /*fExecutable*/);
275 if (RT_FAILURE(rc))
276 return rc;
277 RT_BZERO(RTR0MemObjAddress(hMemObj), cbPortIoLoc);
278
279 /* Map it. */
280 RTR0MEMOBJ hMapObj;
281 rc = RTR0MemObjMapUserEx(&hMapObj, hMemObj, (RTR3PTR)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE, RTR0ProcHandleSelf(),
282 0 /*offSub*/, cbPortIoLoc);
283 if (RT_SUCCESS(rc))
284 {
285 pGVM->dbgfr0.s.hMemObjBpLocPortIo = hMemObj;
286 pGVM->dbgfr0.s.hMapObjBpLocPortIo = hMapObj;
287 pGVM->dbgfr0.s.paBpLocPortIoR0 = (volatile uint32_t *)RTR0MemObjAddress(hMemObj);
288
289 /*
290 * We're done.
291 */
292 *ppaBpLocPortIoR3 = RTR0MemObjAddressR3(hMapObj);
293 return rc;
294 }
295
296 RTR0MemObjFree(hMemObj, true);
297 return rc;
298}
299
300
301/**
302 * Worker for DBGFR0BpOwnerInitReqHandler() that does the actual initialization.
303 *
304 * @returns VBox status code.
305 * @param pGVM The global (ring-0) VM structure.
306 * @param ppaBpOwnerR3 Where to return the ring-3 breakpoint owner table base address on success.
307 * @thread EMT(0)
308 */
309static int dbgfR0BpOwnerInitWorker(PGVM pGVM, R3PTRTYPE(void *) *ppaBpOwnerR3)
310{
311 /*
312 * Figure out how much memory we need for the owner tables and allocate it.
313 */
314 uint32_t const cbBpOwnerR0 = RT_ALIGN_32(DBGF_BP_OWNER_COUNT_MAX * sizeof(DBGFBPOWNERINTR0), HOST_PAGE_SIZE);
315 uint32_t const cbBpOwnerR3 = RT_ALIGN_32(DBGF_BP_OWNER_COUNT_MAX * sizeof(DBGFBPOWNERINT), HOST_PAGE_SIZE);
316 uint32_t const cbTotal = RT_ALIGN_32(cbBpOwnerR0 + cbBpOwnerR3, HOST_PAGE_SIZE);
317
318 RTR0MEMOBJ hMemObj;
319 int rc = RTR0MemObjAllocPage(&hMemObj, cbTotal, false /*fExecutable*/);
320 if (RT_FAILURE(rc))
321 return rc;
322 RT_BZERO(RTR0MemObjAddress(hMemObj), cbTotal);
323
324 /* Map it. */
325 RTR0MEMOBJ hMapObj;
326 rc = RTR0MemObjMapUserEx(&hMapObj, hMemObj, (RTR3PTR)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE, RTR0ProcHandleSelf(),
327 cbBpOwnerR0 /*offSub*/, cbBpOwnerR3);
328 if (RT_SUCCESS(rc))
329 {
330 pGVM->dbgfr0.s.hMemObjBpOwners = hMemObj;
331 pGVM->dbgfr0.s.hMapObjBpOwners = hMapObj;
332 pGVM->dbgfr0.s.paBpOwnersR0 = (PDBGFBPOWNERINTR0)RTR0MemObjAddress(hMemObj);
333
334 /*
335 * We're done.
336 */
337 *ppaBpOwnerR3 = RTR0MemObjAddressR3(hMapObj);
338 return rc;
339 }
340
341 RTR0MemObjFree(hMemObj, true);
342 return rc;
343}
344
345
346/**
347 * Worker for DBGFR0BpChunkAllocReqHandler() that does the actual chunk allocation.
348 *
349 * Allocates a memory object and divides it up as follows:
350 * @verbatim
351 --------------------------------------
352 ring-0 chunk data
353 --------------------------------------
354 page alignment padding
355 --------------------------------------
356 shared chunk data
357 --------------------------------------
358 @endverbatim
359 *
360 * @returns VBox status code.
361 * @param pGVM The global (ring-0) VM structure.
362 * @param idChunk The chunk ID to allocate.
363 * @param ppBpChunkBaseR3 Where to return the ring-3 chunk base address on success.
364 * @thread EMT(0)
365 */
366static int dbgfR0BpChunkAllocWorker(PGVM pGVM, uint32_t idChunk, R3PTRTYPE(void *) *ppBpChunkBaseR3)
367{
368 /*
369 * Figure out how much memory we need for the chunk and allocate it.
370 */
371 uint32_t const cbRing0 = RT_ALIGN_32(DBGF_BP_COUNT_PER_CHUNK * sizeof(DBGFBPINTR0), HOST_PAGE_SIZE);
372 uint32_t const cbShared = RT_ALIGN_32(DBGF_BP_COUNT_PER_CHUNK * sizeof(DBGFBPINT), HOST_PAGE_SIZE);
373 uint32_t const cbTotal = cbRing0 + cbShared;
374
375 RTR0MEMOBJ hMemObj;
376 int rc = RTR0MemObjAllocPage(&hMemObj, cbTotal, false /*fExecutable*/);
377 if (RT_FAILURE(rc))
378 return rc;
379 RT_BZERO(RTR0MemObjAddress(hMemObj), cbTotal);
380
381 /* Map it. */
382 RTR0MEMOBJ hMapObj;
383 rc = RTR0MemObjMapUserEx(&hMapObj, hMemObj, (RTR3PTR)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE, RTR0ProcHandleSelf(),
384 cbRing0 /*offSub*/, cbTotal - cbRing0);
385 if (RT_SUCCESS(rc))
386 {
387 PDBGFBPCHUNKR0 pBpChunkR0 = &pGVM->dbgfr0.s.aBpChunks[idChunk];
388
389 pBpChunkR0->hMemObj = hMemObj;
390 pBpChunkR0->hMapObj = hMapObj;
391 pBpChunkR0->paBpBaseR0Only = (PDBGFBPINTR0)RTR0MemObjAddress(hMemObj);
392 pBpChunkR0->paBpBaseSharedR0 = (PDBGFBPINT)&pBpChunkR0->paBpBaseR0Only[DBGF_BP_COUNT_PER_CHUNK];
393
394 /*
395 * We're done.
396 */
397 *ppBpChunkBaseR3 = RTR0MemObjAddressR3(hMapObj);
398 return rc;
399 }
400
401 RTR0MemObjFree(hMemObj, true);
402 return rc;
403}
404
405
406/**
407 * Worker for DBGFR0BpL2TblChunkAllocReqHandler() that does the actual chunk allocation.
408 *
409 * @returns VBox status code.
410 * @param pGVM The global (ring-0) VM structure.
411 * @param idChunk The chunk ID to allocate.
412 * @param ppL2ChunkBaseR3 Where to return the ring-3 chunk base address on success.
413 * @thread EMT(0)
414 */
415static int dbgfR0BpL2TblChunkAllocWorker(PGVM pGVM, uint32_t idChunk, R3PTRTYPE(void *) *ppL2ChunkBaseR3)
416{
417 /*
418 * Figure out how much memory we need for the chunk and allocate it.
419 */
420 uint32_t const cbTotal = RT_ALIGN_32(DBGF_BP_L2_TBL_ENTRIES_PER_CHUNK * sizeof(DBGFBPL2ENTRY), HOST_PAGE_SIZE);
421
422 RTR0MEMOBJ hMemObj;
423 int rc = RTR0MemObjAllocPage(&hMemObj, cbTotal, false /*fExecutable*/);
424 if (RT_FAILURE(rc))
425 return rc;
426 RT_BZERO(RTR0MemObjAddress(hMemObj), cbTotal);
427
428 /* Map it. */
429 RTR0MEMOBJ hMapObj;
430 rc = RTR0MemObjMapUserEx(&hMapObj, hMemObj, (RTR3PTR)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE, RTR0ProcHandleSelf(),
431 0 /*offSub*/, cbTotal);
432 if (RT_SUCCESS(rc))
433 {
434 PDBGFBPL2TBLCHUNKR0 pL2ChunkR0 = &pGVM->dbgfr0.s.aBpL2TblChunks[idChunk];
435
436 pL2ChunkR0->hMemObj = hMemObj;
437 pL2ChunkR0->hMapObj = hMapObj;
438 pL2ChunkR0->paBpL2TblBaseSharedR0 = (PDBGFBPL2ENTRY)RTR0MemObjAddress(hMemObj);
439
440 /*
441 * We're done.
442 */
443 *ppL2ChunkBaseR3 = RTR0MemObjAddressR3(hMapObj);
444 return rc;
445 }
446
447 RTR0MemObjFree(hMemObj, true);
448 return rc;
449}
450
451
452/**
453 * Used by ring-3 DBGF to fully initialize the breakpoint manager for operation.
454 *
455 * @returns VBox status code.
456 * @param pGVM The global (ring-0) VM structure.
457 * @param pReq Pointer to the request buffer.
458 * @thread EMT(0)
459 */
460VMMR0_INT_DECL(int) DBGFR0BpInitReqHandler(PGVM pGVM, PDBGFBPINITREQ pReq)
461{
462 LogFlow(("DBGFR0BpInitReqHandler:\n"));
463
464 /*
465 * Validate the request.
466 */
467 AssertReturn(pReq->Hdr.cbReq == sizeof(*pReq), VERR_INVALID_PARAMETER);
468
469 int rc = GVMMR0ValidateGVMandEMT(pGVM, 0);
470 AssertRCReturn(rc, rc);
471
472 AssertReturn(!pGVM->dbgfr0.s.fInit, VERR_WRONG_ORDER);
473
474 return dbgfR0BpInitWorker(pGVM, &pReq->paBpLocL1R3);
475}
476
477
478/**
479 * Used by ring-3 DBGF to initialize the breakpoint manager for port I/O breakpoint operation.
480 *
481 * @returns VBox status code.
482 * @param pGVM The global (ring-0) VM structure.
483 * @param pReq Pointer to the request buffer.
484 * @thread EMT(0)
485 */
486VMMR0_INT_DECL(int) DBGFR0BpPortIoInitReqHandler(PGVM pGVM, PDBGFBPINITREQ pReq)
487{
488 LogFlow(("DBGFR0BpPortIoInitReqHandler:\n"));
489
490 /*
491 * Validate the request.
492 */
493 AssertReturn(pReq->Hdr.cbReq == sizeof(*pReq), VERR_INVALID_PARAMETER);
494
495 int rc = GVMMR0ValidateGVMandEMT(pGVM, 0);
496 AssertRCReturn(rc, rc);
497
498 AssertReturn(pGVM->dbgfr0.s.fInit, VERR_WRONG_ORDER);
499 AssertReturn(!pGVM->dbgfr0.s.paBpLocPortIoR0, VERR_WRONG_ORDER);
500
501 return dbgfR0BpPortIoInitWorker(pGVM, &pReq->paBpLocL1R3);
502}
503
504
505/**
506 * Used by ring-3 DBGF to initialize the breakpoint owner table for operation.
507 *
508 * @returns VBox status code.
509 * @param pGVM The global (ring-0) VM structure.
510 * @param pReq Pointer to the request buffer.
511 * @thread EMT(0)
512 */
513VMMR0_INT_DECL(int) DBGFR0BpOwnerInitReqHandler(PGVM pGVM, PDBGFBPOWNERINITREQ pReq)
514{
515 LogFlow(("DBGFR0BpOwnerInitReqHandler:\n"));
516
517 /*
518 * Validate the request.
519 */
520 AssertReturn(pReq->Hdr.cbReq == sizeof(*pReq), VERR_INVALID_PARAMETER);
521
522 int rc = GVMMR0ValidateGVMandEMT(pGVM, 0);
523 AssertRCReturn(rc, rc);
524
525 AssertReturn(!pGVM->dbgfr0.s.paBpOwnersR0, VERR_WRONG_ORDER);
526
527 return dbgfR0BpOwnerInitWorker(pGVM, &pReq->paBpOwnerR3);
528}
529
530
531/**
532 * Used by ring-3 DBGF to allocate a given chunk in the global breakpoint table.
533 *
534 * @returns VBox status code.
535 * @param pGVM The global (ring-0) VM structure.
536 * @param pReq Pointer to the request buffer.
537 * @thread EMT(0)
538 */
539VMMR0_INT_DECL(int) DBGFR0BpChunkAllocReqHandler(PGVM pGVM, PDBGFBPCHUNKALLOCREQ pReq)
540{
541 LogFlow(("DBGFR0BpChunkAllocReqHandler:\n"));
542
543 /*
544 * Validate the request.
545 */
546 AssertReturn(pReq->Hdr.cbReq == sizeof(*pReq), VERR_INVALID_PARAMETER);
547
548 uint32_t const idChunk = pReq->idChunk;
549 AssertReturn(idChunk < DBGF_BP_CHUNK_COUNT, VERR_INVALID_PARAMETER);
550
551 int rc = GVMMR0ValidateGVMandEMT(pGVM, 0);
552 AssertRCReturn(rc, rc);
553
554 AssertReturn(pGVM->dbgfr0.s.fInit, VERR_WRONG_ORDER);
555 AssertReturn(pGVM->dbgfr0.s.aBpChunks[idChunk].hMemObj == NIL_RTR0MEMOBJ, VERR_INVALID_PARAMETER);
556
557 return dbgfR0BpChunkAllocWorker(pGVM, idChunk, &pReq->pChunkBaseR3);
558}
559
560
561/**
562 * Used by ring-3 DBGF to allocate a given chunk in the global L2 lookup table.
563 *
564 * @returns VBox status code.
565 * @param pGVM The global (ring-0) VM structure.
566 * @param pReq Pointer to the request buffer.
567 * @thread EMT(0)
568 */
569VMMR0_INT_DECL(int) DBGFR0BpL2TblChunkAllocReqHandler(PGVM pGVM, PDBGFBPL2TBLCHUNKALLOCREQ pReq)
570{
571 LogFlow(("DBGFR0BpL2TblChunkAllocReqHandler:\n"));
572
573 /*
574 * Validate the request.
575 */
576 AssertReturn(pReq->Hdr.cbReq == sizeof(*pReq), VERR_INVALID_PARAMETER);
577
578 uint32_t const idChunk = pReq->idChunk;
579 AssertReturn(idChunk < DBGF_BP_L2_TBL_CHUNK_COUNT, VERR_INVALID_PARAMETER);
580
581 int rc = GVMMR0ValidateGVMandEMT(pGVM, 0);
582 AssertRCReturn(rc, rc);
583
584 AssertReturn(pGVM->dbgfr0.s.fInit, VERR_WRONG_ORDER);
585 AssertReturn(pGVM->dbgfr0.s.aBpL2TblChunks[idChunk].hMemObj == NIL_RTR0MEMOBJ, VERR_INVALID_PARAMETER);
586
587 return dbgfR0BpL2TblChunkAllocWorker(pGVM, idChunk, &pReq->pChunkBaseR3);
588}
589
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