VirtualBox

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

Last change on this file was 99739, checked in by vboxsync, 12 months ago

*: doxygen corrections (mostly about removing @returns from functions returning void).

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

© 2023 Oracle
ContactPrivacy policyTerms of Use