VirtualBox

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

Last change on this file since 98103 was 98103, checked in by vboxsync, 16 months ago

Copyright year updates by scm.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use