VirtualBox

source: vbox/trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp@ 86838

Last change on this file since 86838 was 86838, checked in by vboxsync, 4 years ago

Devices/Graphics: A couple of new commands; a more generic handler for creating a surface; cleaned saved state data for a surface; increased saved state version; possibility to build DX11 backend. bugref:9830

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 272.3 KB
Line 
1/* $Id: DevVGA-SVGA.cpp 86838 2020-11-09 23:16:50Z vboxsync $ */
2/** @file
3 * VMware SVGA device.
4 *
5 * Logging levels guidelines for this and related files:
6 * - Log() for normal bits.
7 * - LogFlow() for more info.
8 * - Log2 for hex dump of cursor data.
9 * - Log3 for hex dump of shader code.
10 * - Log4 for hex dumps of 3D data.
11 * - Log5 for info about GMR pages.
12 * - LogRel for the usual important stuff.
13 * - LogRel2 for cursor.
14 * - LogRel3 for 3D performance data.
15 * - LogRel4 for HW accelerated graphics output.
16 */
17
18/*
19 * Copyright (C) 2013-2020 Oracle Corporation
20 *
21 * This file is part of VirtualBox Open Source Edition (OSE), as
22 * available from http://www.virtualbox.org. This file is free software;
23 * you can redistribute it and/or modify it under the terms of the GNU
24 * General Public License (GPL) as published by the Free Software
25 * Foundation, in version 2 as it comes in the "COPYING" file of the
26 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
27 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
28 */
29
30
31/** @page pg_dev_vmsvga VMSVGA - VMware SVGA II Device Emulation
32 *
33 * This device emulation was contributed by trivirt AG. It offers an
34 * alternative to our Bochs based VGA graphics and 3d emulations. This is
35 * valuable for Xorg based guests, as there is driver support shipping with Xorg
36 * since it forked from XFree86.
37 *
38 *
39 * @section sec_dev_vmsvga_sdk The VMware SDK
40 *
41 * This is officially deprecated now, however it's still quite useful,
42 * especially for getting the old features working:
43 * http://vmware-svga.sourceforge.net/
44 *
45 * They currently point developers at the following resources.
46 * - http://cgit.freedesktop.org/xorg/driver/xf86-video-vmware/
47 * - http://cgit.freedesktop.org/mesa/mesa/tree/src/gallium/drivers/svga/
48 * - http://cgit.freedesktop.org/mesa/vmwgfx/
49 *
50 * @subsection subsec_dev_vmsvga_sdk_results Test results
51 *
52 * Test results:
53 * - 2dmark.img:
54 * + todo
55 * - backdoor-tclo.img:
56 * + todo
57 * - blit-cube.img:
58 * + todo
59 * - bunnies.img:
60 * + todo
61 * - cube.img:
62 * + todo
63 * - cubemark.img:
64 * + todo
65 * - dynamic-vertex-stress.img:
66 * + todo
67 * - dynamic-vertex.img:
68 * + todo
69 * - fence-stress.img:
70 * + todo
71 * - gmr-test.img:
72 * + todo
73 * - half-float-test.img:
74 * + todo
75 * - noscreen-cursor.img:
76 * - The CURSOR I/O and FIFO registers are not implemented, so the mouse
77 * cursor doesn't show. (Hacking the GUI a little, would make the cursor
78 * visible though.)
79 * - Cursor animation via the palette doesn't work.
80 * - During debugging, it turns out that the framebuffer content seems to
81 * be halfways ignore or something (memset(fb, 0xcc, lots)).
82 * - Trouble with way to small FIFO and the 256x256 cursor fails. Need to
83 * grow it 0x10 fold (128KB -> 2MB like in WS10).
84 * - null.img:
85 * + todo
86 * - pong.img:
87 * + todo
88 * - presentReadback.img:
89 * + todo
90 * - resolution-set.img:
91 * + todo
92 * - rt-gamma-test.img:
93 * + todo
94 * - screen-annotation.img:
95 * + todo
96 * - screen-cursor.img:
97 * + todo
98 * - screen-dma-coalesce.img:
99 * + todo
100 * - screen-gmr-discontig.img:
101 * + todo
102 * - screen-gmr-remap.img:
103 * + todo
104 * - screen-multimon.img:
105 * + todo
106 * - screen-present-clip.img:
107 * + todo
108 * - screen-render-test.img:
109 * + todo
110 * - screen-simple.img:
111 * + todo
112 * - screen-text.img:
113 * + todo
114 * - simple-shaders.img:
115 * + todo
116 * - simple_blit.img:
117 * + todo
118 * - tiny-2d-updates.img:
119 * + todo
120 * - video-formats.img:
121 * + todo
122 * - video-sync.img:
123 * + todo
124 *
125 */
126
127
128/*********************************************************************************************************************************
129* Header Files *
130*********************************************************************************************************************************/
131#define LOG_GROUP LOG_GROUP_DEV_VMSVGA
132#include <VBox/vmm/pdmdev.h>
133#include <VBox/version.h>
134#include <VBox/err.h>
135#include <VBox/log.h>
136#include <VBox/vmm/pgm.h>
137#include <VBox/sup.h>
138
139#include <iprt/assert.h>
140#include <iprt/semaphore.h>
141#include <iprt/uuid.h>
142#ifdef IN_RING3
143# include <iprt/ctype.h>
144# include <iprt/mem.h>
145# ifdef VBOX_STRICT
146# include <iprt/time.h>
147# endif
148#endif
149
150#include <VBox/AssertGuest.h>
151#include <VBox/VMMDev.h>
152#include <VBoxVideo.h>
153#include <VBox/bioslogo.h>
154
155/* should go BEFORE any other DevVGA include to make all DevVGA.h config defines be visible */
156#include "DevVGA.h"
157
158#ifdef IN_RING3
159/* Should be included after DevVGA.h/DevVGA-SVGA.h to pick all defines. */
160#include "DevVGA-SVGA-internal.h"
161#endif
162#ifdef VBOX_WITH_VMSVGA3D
163# include "DevVGA-SVGA3d.h"
164# ifdef RT_OS_DARWIN
165# include "DevVGA-SVGA3d-cocoa.h"
166# endif
167# ifdef RT_OS_LINUX
168# ifdef IN_RING3
169# include "DevVGA-SVGA3d-glLdr.h"
170# endif
171# endif
172#endif
173
174
175/*********************************************************************************************************************************
176* Defined Constants And Macros *
177*********************************************************************************************************************************/
178/**
179 * Macro for checking if a fixed FIFO register is valid according to the
180 * current FIFO configuration.
181 *
182 * @returns true / false.
183 * @param a_iIndex The fifo register index (like SVGA_FIFO_CAPABILITIES).
184 * @param a_offFifoMin A valid SVGA_FIFO_MIN value.
185 */
186#define VMSVGA_IS_VALID_FIFO_REG(a_iIndex, a_offFifoMin) ( ((a_iIndex) + 1) * sizeof(uint32_t) <= (a_offFifoMin) )
187
188
189/*********************************************************************************************************************************
190* Structures and Typedefs *
191*********************************************************************************************************************************/
192
193
194/*********************************************************************************************************************************
195* Internal Functions *
196*********************************************************************************************************************************/
197#ifdef IN_RING3
198# if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
199static FNPGMPHYSHANDLER vmsvgaR3FifoAccessHandler;
200# endif
201# ifdef DEBUG_GMR_ACCESS
202static FNPGMPHYSHANDLER vmsvgaR3GmrAccessHandler;
203# endif
204#endif
205
206
207/*********************************************************************************************************************************
208* Global Variables *
209*********************************************************************************************************************************/
210#ifdef IN_RING3
211
212/**
213 * SSM descriptor table for the VMSVGAGMRDESCRIPTOR structure.
214 */
215static SSMFIELD const g_aVMSVGAGMRDESCRIPTORFields[] =
216{
217 SSMFIELD_ENTRY_GCPHYS( VMSVGAGMRDESCRIPTOR, GCPhys),
218 SSMFIELD_ENTRY( VMSVGAGMRDESCRIPTOR, numPages),
219 SSMFIELD_ENTRY_TERM()
220};
221
222/**
223 * SSM descriptor table for the GMR structure.
224 */
225static SSMFIELD const g_aGMRFields[] =
226{
227 SSMFIELD_ENTRY( GMR, cMaxPages),
228 SSMFIELD_ENTRY( GMR, cbTotal),
229 SSMFIELD_ENTRY( GMR, numDescriptors),
230 SSMFIELD_ENTRY_IGN_HCPTR( GMR, paDesc),
231 SSMFIELD_ENTRY_TERM()
232};
233
234/**
235 * SSM descriptor table for the VMSVGASCREENOBJECT structure.
236 */
237static SSMFIELD const g_aVMSVGASCREENOBJECTFields[] =
238{
239 SSMFIELD_ENTRY( VMSVGASCREENOBJECT, fuScreen),
240 SSMFIELD_ENTRY( VMSVGASCREENOBJECT, idScreen),
241 SSMFIELD_ENTRY( VMSVGASCREENOBJECT, xOrigin),
242 SSMFIELD_ENTRY( VMSVGASCREENOBJECT, yOrigin),
243 SSMFIELD_ENTRY( VMSVGASCREENOBJECT, cWidth),
244 SSMFIELD_ENTRY( VMSVGASCREENOBJECT, cHeight),
245 SSMFIELD_ENTRY( VMSVGASCREENOBJECT, offVRAM),
246 SSMFIELD_ENTRY( VMSVGASCREENOBJECT, cbPitch),
247 SSMFIELD_ENTRY( VMSVGASCREENOBJECT, cBpp),
248 SSMFIELD_ENTRY( VMSVGASCREENOBJECT, fDefined),
249 SSMFIELD_ENTRY( VMSVGASCREENOBJECT, fModified),
250 SSMFIELD_ENTRY_VER( VMSVGASCREENOBJECT, cDpi, VGA_SAVEDSTATE_VERSION_VMSVGA_MIPLEVELS),
251 SSMFIELD_ENTRY_TERM()
252};
253
254/**
255 * SSM descriptor table for the VMSVGAR3STATE structure.
256 */
257static SSMFIELD const g_aVMSVGAR3STATEFields[] =
258{
259 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, paGMR),
260 SSMFIELD_ENTRY( VMSVGAR3STATE, GMRFB),
261 SSMFIELD_ENTRY( VMSVGAR3STATE, Cursor.fActive),
262 SSMFIELD_ENTRY( VMSVGAR3STATE, Cursor.xHotspot),
263 SSMFIELD_ENTRY( VMSVGAR3STATE, Cursor.yHotspot),
264 SSMFIELD_ENTRY( VMSVGAR3STATE, Cursor.width),
265 SSMFIELD_ENTRY( VMSVGAR3STATE, Cursor.height),
266 SSMFIELD_ENTRY( VMSVGAR3STATE, Cursor.cbData),
267 SSMFIELD_ENTRY_IGN_HCPTR( VMSVGAR3STATE, Cursor.pData),
268 SSMFIELD_ENTRY( VMSVGAR3STATE, colorAnnotation),
269 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, cBusyDelayedEmts),
270#ifdef VMSVGA_USE_EMT_HALT_CODE
271 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, BusyDelayedEmts),
272#else
273 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, hBusyDelayedEmts),
274#endif
275 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatBusyDelayEmts),
276 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dPresentProf),
277 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dDrawPrimitivesProf),
278 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceDmaProf),
279 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dBlitSurfaceToScreenProf),
280 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineGmr2),
281 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineGmr2Free),
282 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineGmr2Modify),
283 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdRemapGmr2),
284 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdRemapGmr2Modify),
285 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdInvalidCmd),
286 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdFence),
287 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdUpdate),
288 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdUpdateVerbose),
289 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineCursor),
290 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineAlphaCursor),
291 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdMoveCursor),
292 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDisplayCursor),
293 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdRectFill),
294 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdRectCopy),
295 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdRectRopCopy),
296 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdEscape),
297 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineScreen),
298 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDestroyScreen),
299 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdDefineGmrFb),
300 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdBlitGmrFbToScreen),
301 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdBlitScreentoGmrFb),
302 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdAnnotationFill),
303 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3CmdAnnotationCopy),
304 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceDefine),
305 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceDefineV2),
306 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceDestroy),
307 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceCopy),
308 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceStretchBlt),
309 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceDma),
310 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSurfaceScreen),
311 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dContextDefine),
312 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dContextDestroy),
313 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetTransform),
314 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetZRange),
315 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetRenderState),
316 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetRenderTarget),
317 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetTextureState),
318 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetMaterial),
319 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetLightData),
320 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetLightEnable),
321 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetViewPort),
322 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetClipPlane),
323 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dClear),
324 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dPresent),
325 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dPresentReadBack),
326 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dShaderDefine),
327 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dShaderDestroy),
328 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetShader),
329 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetShaderConst),
330 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dDrawPrimitives),
331 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dSetScissorRect),
332 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dBeginQuery),
333 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dEndQuery),
334 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dWaitForQuery),
335 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dGenerateMipmaps),
336 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dActivateSurface),
337 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3Cmd3dDeactivateSurface),
338
339 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3RegConfigDoneWr),
340 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3RegGmrDescriptorWr),
341 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3RegGmrDescriptorWrErrors),
342 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatR3RegGmrDescriptorWrFree),
343
344 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoCommands),
345 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoErrors),
346 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoUnkCmds),
347 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoTodoTimeout),
348 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoTodoWoken),
349 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoStalls),
350 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoExtendedSleep),
351# if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
352 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoAccessHandler),
353# endif
354 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoCursorFetchAgain),
355 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoCursorNoChange),
356 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoCursorPosition),
357 SSMFIELD_ENTRY_IGNORE( VMSVGAR3STATE, StatFifoCursorVisiblity),
358
359 SSMFIELD_ENTRY_TERM()
360};
361
362/**
363 * SSM descriptor table for the VGAState.svga structure.
364 */
365static SSMFIELD const g_aVGAStateSVGAFields[] =
366{
367 SSMFIELD_ENTRY_IGN_GCPHYS( VMSVGAState, GCPhysFIFO),
368 SSMFIELD_ENTRY_IGNORE( VMSVGAState, cbFIFO),
369 SSMFIELD_ENTRY_IGNORE( VMSVGAState, cbFIFOConfig),
370 SSMFIELD_ENTRY( VMSVGAState, u32SVGAId),
371 SSMFIELD_ENTRY( VMSVGAState, fEnabled),
372 SSMFIELD_ENTRY( VMSVGAState, fConfigured),
373 SSMFIELD_ENTRY( VMSVGAState, fBusy),
374 SSMFIELD_ENTRY( VMSVGAState, fTraces),
375 SSMFIELD_ENTRY( VMSVGAState, u32GuestId),
376 SSMFIELD_ENTRY( VMSVGAState, cScratchRegion),
377 SSMFIELD_ENTRY( VMSVGAState, au32ScratchRegion),
378 SSMFIELD_ENTRY( VMSVGAState, u32IrqStatus),
379 SSMFIELD_ENTRY( VMSVGAState, u32IrqMask),
380 SSMFIELD_ENTRY( VMSVGAState, u32PitchLock),
381 SSMFIELD_ENTRY( VMSVGAState, u32CurrentGMRId),
382 SSMFIELD_ENTRY( VMSVGAState, u32DeviceCaps),
383 SSMFIELD_ENTRY( VMSVGAState, u32IndexReg),
384 SSMFIELD_ENTRY_IGNORE( VMSVGAState, hFIFORequestSem),
385 SSMFIELD_ENTRY_IGNORE( VMSVGAState, uLastCursorUpdateCount),
386 SSMFIELD_ENTRY_IGNORE( VMSVGAState, fFIFOThreadSleeping),
387 SSMFIELD_ENTRY_VER( VMSVGAState, fGFBRegisters, VGA_SAVEDSTATE_VERSION_VMSVGA_SCREENS),
388 SSMFIELD_ENTRY( VMSVGAState, uWidth),
389 SSMFIELD_ENTRY( VMSVGAState, uHeight),
390 SSMFIELD_ENTRY( VMSVGAState, uBpp),
391 SSMFIELD_ENTRY( VMSVGAState, cbScanline),
392 SSMFIELD_ENTRY_VER( VMSVGAState, uScreenOffset, VGA_SAVEDSTATE_VERSION_VMSVGA),
393 SSMFIELD_ENTRY_VER( VMSVGAState, uCursorX, VGA_SAVEDSTATE_VERSION_VMSVGA_CURSOR),
394 SSMFIELD_ENTRY_VER( VMSVGAState, uCursorY, VGA_SAVEDSTATE_VERSION_VMSVGA_CURSOR),
395 SSMFIELD_ENTRY_VER( VMSVGAState, uCursorID, VGA_SAVEDSTATE_VERSION_VMSVGA_CURSOR),
396 SSMFIELD_ENTRY_VER( VMSVGAState, uCursorOn, VGA_SAVEDSTATE_VERSION_VMSVGA_CURSOR),
397 SSMFIELD_ENTRY( VMSVGAState, u32MaxWidth),
398 SSMFIELD_ENTRY( VMSVGAState, u32MaxHeight),
399 SSMFIELD_ENTRY( VMSVGAState, u32ActionFlags),
400 SSMFIELD_ENTRY( VMSVGAState, f3DEnabled),
401 SSMFIELD_ENTRY( VMSVGAState, fVRAMTracking),
402 SSMFIELD_ENTRY_IGNORE( VMSVGAState, u8FIFOExtCommand),
403 SSMFIELD_ENTRY_IGNORE( VMSVGAState, fFifoExtCommandWakeup),
404 SSMFIELD_ENTRY_IGNORE( VMSVGAState, cGMR),
405 SSMFIELD_ENTRY_TERM()
406};
407#endif /* IN_RING3 */
408
409
410/*********************************************************************************************************************************
411* Internal Functions *
412*********************************************************************************************************************************/
413#ifdef IN_RING3
414static void vmsvgaR3SetTraces(PPDMDEVINS pDevIns, PVGASTATE pThis, bool fTraces);
415static int vmsvgaR3LoadExecFifo(PCPDMDEVHLPR3 pHlp, PVGASTATE pThis, PVGASTATECC pThisCC, PSSMHANDLE pSSM,
416 uint32_t uVersion, uint32_t uPass);
417static int vmsvgaR3SaveExecFifo(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM);
418static void vmsvgaR3CmdBufSubmit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, RTGCPHYS GCPhysCB, SVGACBContext CBCtx);
419#endif /* IN_RING3 */
420
421
422#if defined(LOG_ENABLED)
423# define SVGA_CASE_ID2STR(idx) case idx: return #idx
424/**
425 * Index register string name lookup
426 *
427 * @returns Index register string or "UNKNOWN"
428 * @param pThis The shared VGA/VMSVGA state.
429 * @param idxReg The index register.
430 */
431static const char *vmsvgaIndexToString(PVGASTATE pThis, uint32_t idxReg)
432{
433 switch (idxReg)
434 {
435 SVGA_CASE_ID2STR(SVGA_REG_ID);
436 SVGA_CASE_ID2STR(SVGA_REG_ENABLE);
437 SVGA_CASE_ID2STR(SVGA_REG_WIDTH);
438 SVGA_CASE_ID2STR(SVGA_REG_HEIGHT);
439 SVGA_CASE_ID2STR(SVGA_REG_MAX_WIDTH);
440 SVGA_CASE_ID2STR(SVGA_REG_MAX_HEIGHT);
441 SVGA_CASE_ID2STR(SVGA_REG_DEPTH);
442 SVGA_CASE_ID2STR(SVGA_REG_BITS_PER_PIXEL); /* Current bpp in the guest */
443 SVGA_CASE_ID2STR(SVGA_REG_PSEUDOCOLOR);
444 SVGA_CASE_ID2STR(SVGA_REG_RED_MASK);
445 SVGA_CASE_ID2STR(SVGA_REG_GREEN_MASK);
446 SVGA_CASE_ID2STR(SVGA_REG_BLUE_MASK);
447 SVGA_CASE_ID2STR(SVGA_REG_BYTES_PER_LINE);
448 SVGA_CASE_ID2STR(SVGA_REG_FB_START); /* (Deprecated) */
449 SVGA_CASE_ID2STR(SVGA_REG_FB_OFFSET);
450 SVGA_CASE_ID2STR(SVGA_REG_VRAM_SIZE);
451 SVGA_CASE_ID2STR(SVGA_REG_FB_SIZE);
452
453 /* ID 0 implementation only had the above registers, then the palette */
454 SVGA_CASE_ID2STR(SVGA_REG_CAPABILITIES);
455 SVGA_CASE_ID2STR(SVGA_REG_MEM_START); /* (Deprecated) */
456 SVGA_CASE_ID2STR(SVGA_REG_MEM_SIZE);
457 SVGA_CASE_ID2STR(SVGA_REG_CONFIG_DONE); /* Set when memory area configured */
458 SVGA_CASE_ID2STR(SVGA_REG_SYNC); /* See "FIFO Synchronization Registers" */
459 SVGA_CASE_ID2STR(SVGA_REG_BUSY); /* See "FIFO Synchronization Registers" */
460 SVGA_CASE_ID2STR(SVGA_REG_GUEST_ID); /* Set guest OS identifier */
461 SVGA_CASE_ID2STR(SVGA_REG_CURSOR_ID); /* (Deprecated) */
462 SVGA_CASE_ID2STR(SVGA_REG_CURSOR_X); /* (Deprecated) */
463 SVGA_CASE_ID2STR(SVGA_REG_CURSOR_Y); /* (Deprecated) */
464 SVGA_CASE_ID2STR(SVGA_REG_CURSOR_ON); /* (Deprecated) */
465 SVGA_CASE_ID2STR(SVGA_REG_HOST_BITS_PER_PIXEL); /* (Deprecated) */
466 SVGA_CASE_ID2STR(SVGA_REG_SCRATCH_SIZE); /* Number of scratch registers */
467 SVGA_CASE_ID2STR(SVGA_REG_MEM_REGS); /* Number of FIFO registers */
468 SVGA_CASE_ID2STR(SVGA_REG_NUM_DISPLAYS); /* (Deprecated) */
469 SVGA_CASE_ID2STR(SVGA_REG_PITCHLOCK); /* Fixed pitch for all modes */
470 SVGA_CASE_ID2STR(SVGA_REG_IRQMASK); /* Interrupt mask */
471
472 /* Legacy multi-monitor support */
473 SVGA_CASE_ID2STR(SVGA_REG_NUM_GUEST_DISPLAYS); /* Number of guest displays in X/Y direction */
474 SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_ID); /* Display ID for the following display attributes */
475 SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_IS_PRIMARY); /* Whether this is a primary display */
476 SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_POSITION_X); /* The display position x */
477 SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_POSITION_Y); /* The display position y */
478 SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_WIDTH); /* The display's width */
479 SVGA_CASE_ID2STR(SVGA_REG_DISPLAY_HEIGHT); /* The display's height */
480
481 SVGA_CASE_ID2STR(SVGA_REG_GMR_ID);
482 SVGA_CASE_ID2STR(SVGA_REG_GMR_DESCRIPTOR);
483 SVGA_CASE_ID2STR(SVGA_REG_GMR_MAX_IDS);
484 SVGA_CASE_ID2STR(SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH);
485
486 SVGA_CASE_ID2STR(SVGA_REG_TRACES); /* Enable trace-based updates even when FIFO is on */
487 SVGA_CASE_ID2STR(SVGA_REG_GMRS_MAX_PAGES); /* Maximum number of 4KB pages for all GMRs */
488 SVGA_CASE_ID2STR(SVGA_REG_MEMORY_SIZE); /* Total dedicated device memory excluding FIFO */
489 SVGA_CASE_ID2STR(SVGA_REG_COMMAND_LOW); /* Lower 32 bits and submits commands */
490 SVGA_CASE_ID2STR(SVGA_REG_COMMAND_HIGH); /* Upper 32 bits of command buffer PA */
491 SVGA_CASE_ID2STR(SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM); /* Max primary memory */
492 SVGA_CASE_ID2STR(SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB); /* Suggested limit on mob mem */
493 SVGA_CASE_ID2STR(SVGA_REG_DEV_CAP); /* Write dev cap index, read value */
494 SVGA_CASE_ID2STR(SVGA_REG_CMD_PREPEND_LOW);
495 SVGA_CASE_ID2STR(SVGA_REG_iCMD_PREPEND_HIGH);
496 SVGA_CASE_ID2STR(SVGA_REG_SCREENTARGET_MAX_WIDTH);
497 SVGA_CASE_ID2STR(SVGA_REG_SCREENTARGET_MAX_HEIGHT);
498 SVGA_CASE_ID2STR(SVGA_REG_MOB_MAX_SIZE);
499 SVGA_CASE_ID2STR(SVGA_REG_TOP); /* Must be 1 more than the last register */
500
501 default:
502 if (idxReg - (uint32_t)SVGA_SCRATCH_BASE < pThis->svga.cScratchRegion)
503 return "SVGA_SCRATCH_BASE reg";
504 if (idxReg - (uint32_t)SVGA_PALETTE_BASE < (uint32_t)SVGA_NUM_PALETTE_REGS)
505 return "SVGA_PALETTE_BASE reg";
506 return "UNKNOWN";
507 }
508}
509# undef SVGA_CASE_ID2STR
510#endif /* LOG_ENABLED */
511
512
513#ifdef IN_RING3
514
515/**
516 * @interface_method_impl{PDMIDISPLAYPORT,pfnSetViewport}
517 */
518DECLCALLBACK(void) vmsvgaR3PortSetViewport(PPDMIDISPLAYPORT pInterface, uint32_t idScreen, uint32_t x, uint32_t y, uint32_t cx, uint32_t cy)
519{
520 PVGASTATECC pThisCC = RT_FROM_MEMBER(pInterface, VGASTATECC, IPort);
521 PVGASTATE pThis = PDMDEVINS_2_DATA(pThisCC->pDevIns, PVGASTATE);
522
523 Log(("vmsvgaPortSetViewPort: screen %d (%d,%d)(%d,%d)\n", idScreen, x, y, cx, cy));
524 VMSVGAVIEWPORT const OldViewport = pThis->svga.viewport;
525
526 /** @todo Test how it interacts with multiple screen objects. */
527 VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, idScreen);
528 uint32_t const uWidth = pScreen ? pScreen->cWidth : 0;
529 uint32_t const uHeight = pScreen ? pScreen->cHeight : 0;
530
531 if (x < uWidth)
532 {
533 pThis->svga.viewport.x = x;
534 pThis->svga.viewport.cx = RT_MIN(cx, uWidth - x);
535 pThis->svga.viewport.xRight = x + pThis->svga.viewport.cx;
536 }
537 else
538 {
539 pThis->svga.viewport.x = uWidth;
540 pThis->svga.viewport.cx = 0;
541 pThis->svga.viewport.xRight = uWidth;
542 }
543 if (y < uHeight)
544 {
545 pThis->svga.viewport.y = y;
546 pThis->svga.viewport.cy = RT_MIN(cy, uHeight - y);
547 pThis->svga.viewport.yLowWC = uHeight - y - pThis->svga.viewport.cy;
548 pThis->svga.viewport.yHighWC = uHeight - y;
549 }
550 else
551 {
552 pThis->svga.viewport.y = uHeight;
553 pThis->svga.viewport.cy = 0;
554 pThis->svga.viewport.yLowWC = 0;
555 pThis->svga.viewport.yHighWC = 0;
556 }
557
558# ifdef VBOX_WITH_VMSVGA3D
559 /*
560 * Now inform the 3D backend.
561 */
562 if (pThis->svga.f3DEnabled)
563 vmsvga3dUpdateHostScreenViewport(pThisCC, idScreen, &OldViewport);
564# else
565 RT_NOREF(OldViewport);
566# endif
567}
568
569
570/**
571 * Updating screen information in API
572 *
573 * @param pThis The The shared VGA/VMSVGA instance data.
574 * @param pThisCC The VGA/VMSVGA state for ring-3.
575 */
576void vmsvgaR3VBVAResize(PVGASTATE pThis, PVGASTATECC pThisCC)
577{
578 int rc;
579
580 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
581
582 for (unsigned iScreen = 0; iScreen < RT_ELEMENTS(pSVGAState->aScreens); ++iScreen)
583 {
584 VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[iScreen];
585 if (!pScreen->fModified)
586 continue;
587
588 pScreen->fModified = false;
589
590 VBVAINFOVIEW view;
591 RT_ZERO(view);
592 view.u32ViewIndex = pScreen->idScreen;
593 // view.u32ViewOffset = 0;
594 view.u32ViewSize = pThis->vram_size;
595 view.u32MaxScreenSize = pThis->vram_size;
596
597 VBVAINFOSCREEN screen;
598 RT_ZERO(screen);
599 screen.u32ViewIndex = pScreen->idScreen;
600
601 if (pScreen->fDefined)
602 {
603 if ( pScreen->cWidth == VMSVGA_VAL_UNINITIALIZED
604 || pScreen->cHeight == VMSVGA_VAL_UNINITIALIZED
605 || pScreen->cBpp == VMSVGA_VAL_UNINITIALIZED)
606 {
607 Assert(pThis->svga.fGFBRegisters);
608 continue;
609 }
610
611 screen.i32OriginX = pScreen->xOrigin;
612 screen.i32OriginY = pScreen->yOrigin;
613 screen.u32StartOffset = pScreen->offVRAM;
614 screen.u32LineSize = pScreen->cbPitch;
615 screen.u32Width = pScreen->cWidth;
616 screen.u32Height = pScreen->cHeight;
617 screen.u16BitsPerPixel = pScreen->cBpp;
618 if (!(pScreen->fuScreen & SVGA_SCREEN_DEACTIVATE))
619 screen.u16Flags = VBVA_SCREEN_F_ACTIVE;
620 if (pScreen->fuScreen & SVGA_SCREEN_BLANKING)
621 screen.u16Flags |= VBVA_SCREEN_F_BLANK2;
622 }
623 else
624 {
625 /* Screen is destroyed. */
626 screen.u16Flags = VBVA_SCREEN_F_DISABLED;
627 }
628
629 void *pvVRAM = pScreen->pvScreenBitmap ? pScreen->pvScreenBitmap : pThisCC->pbVRam;
630 rc = pThisCC->pDrv->pfnVBVAResize(pThisCC->pDrv, &view, &screen, pvVRAM, /*fResetInputMapping=*/ true);
631 AssertRC(rc);
632 }
633}
634
635
636/**
637 * @interface_method_impl{PDMIDISPLAYPORT,pfnReportMonitorPositions}
638 *
639 * Used to update screen offsets (positions) since appearently vmwgfx fails to
640 * pass correct offsets thru FIFO.
641 */
642DECLCALLBACK(void) vmsvgaR3PortReportMonitorPositions(PPDMIDISPLAYPORT pInterface, uint32_t cPositions, PCRTPOINT paPositions)
643{
644 PVGASTATECC pThisCC = RT_FROM_MEMBER(pInterface, VGASTATECC, IPort);
645 PVGASTATE pThis = PDMDEVINS_2_DATA(pThisCC->pDevIns, PVGASTATE);
646 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
647
648 AssertReturnVoid(pSVGAState);
649
650 /* We assume cPositions is the # of outputs Xserver reports and paPositions is (-1, -1) for disabled monitors. */
651 cPositions = RT_MIN(cPositions, RT_ELEMENTS(pSVGAState->aScreens));
652 for (uint32_t i = 0; i < cPositions; ++i)
653 {
654 if ( pSVGAState->aScreens[i].xOrigin == paPositions[i].x
655 && pSVGAState->aScreens[i].yOrigin == paPositions[i].y)
656 continue;
657
658 if (pSVGAState->aScreens[i].xOrigin == -1)
659 continue;
660 if (pSVGAState->aScreens[i].yOrigin == -1)
661 continue;
662
663 pSVGAState->aScreens[i].xOrigin = paPositions[i].x;
664 pSVGAState->aScreens[i].yOrigin = paPositions[i].y;
665 pSVGAState->aScreens[i].fModified = true;
666 }
667
668 vmsvgaR3VBVAResize(pThis, pThisCC);
669}
670
671#endif /* IN_RING3 */
672
673/**
674 * Read port register
675 *
676 * @returns VBox status code.
677 * @param pDevIns The device instance.
678 * @param pThis The shared VGA/VMSVGA state.
679 * @param pu32 Where to store the read value
680 */
681static int vmsvgaReadPort(PPDMDEVINS pDevIns, PVGASTATE pThis, uint32_t *pu32)
682{
683#ifdef IN_RING3
684 PVGASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
685#endif
686 int rc = VINF_SUCCESS;
687 *pu32 = 0;
688
689 /* Rough index register validation. */
690 uint32_t idxReg = pThis->svga.u32IndexReg;
691#if !defined(IN_RING3) && defined(VBOX_STRICT)
692 ASSERT_GUEST_MSG_RETURN(idxReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion, ("idxReg=%#x\n", idxReg),
693 VINF_IOM_R3_IOPORT_READ);
694#else
695 ASSERT_GUEST_MSG_STMT_RETURN(idxReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion, ("idxReg=%#x\n", idxReg),
696 STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownRd),
697 VINF_SUCCESS);
698#endif
699 RT_UNTRUSTED_VALIDATED_FENCE();
700
701 /* We must adjust the register number if we're in SVGA_ID_0 mode because the PALETTE range moved. */
702 if ( idxReg >= SVGA_REG_ID_0_TOP
703 && pThis->svga.u32SVGAId == SVGA_ID_0)
704 {
705 idxReg += SVGA_PALETTE_BASE - SVGA_REG_ID_0_TOP;
706 Log(("vmsvgaWritePort: SVGA_ID_0 reg adj %#x -> %#x\n", pThis->svga.u32IndexReg, idxReg));
707 }
708
709 switch (idxReg)
710 {
711 case SVGA_REG_ID:
712 STAM_REL_COUNTER_INC(&pThis->svga.StatRegIdRd);
713 *pu32 = pThis->svga.u32SVGAId;
714 break;
715
716 case SVGA_REG_ENABLE:
717 STAM_REL_COUNTER_INC(&pThis->svga.StatRegEnableRd);
718 *pu32 = pThis->svga.fEnabled;
719 break;
720
721 case SVGA_REG_WIDTH:
722 {
723 STAM_REL_COUNTER_INC(&pThis->svga.StatRegWidthRd);
724 if ( pThis->svga.fEnabled
725 && pThis->svga.uWidth != VMSVGA_VAL_UNINITIALIZED)
726 *pu32 = pThis->svga.uWidth;
727 else
728 {
729#ifndef IN_RING3
730 rc = VINF_IOM_R3_IOPORT_READ;
731#else
732 *pu32 = pThisCC->pDrv->cx;
733#endif
734 }
735 break;
736 }
737
738 case SVGA_REG_HEIGHT:
739 {
740 STAM_REL_COUNTER_INC(&pThis->svga.StatRegHeightRd);
741 if ( pThis->svga.fEnabled
742 && pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
743 *pu32 = pThis->svga.uHeight;
744 else
745 {
746#ifndef IN_RING3
747 rc = VINF_IOM_R3_IOPORT_READ;
748#else
749 *pu32 = pThisCC->pDrv->cy;
750#endif
751 }
752 break;
753 }
754
755 case SVGA_REG_MAX_WIDTH:
756 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMaxWidthRd);
757 *pu32 = pThis->svga.u32MaxWidth;
758 break;
759
760 case SVGA_REG_MAX_HEIGHT:
761 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMaxHeightRd);
762 *pu32 = pThis->svga.u32MaxHeight;
763 break;
764
765 case SVGA_REG_DEPTH:
766 /* This returns the color depth of the current mode. */
767 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDepthRd);
768 switch (pThis->svga.uBpp)
769 {
770 case 15:
771 case 16:
772 case 24:
773 *pu32 = pThis->svga.uBpp;
774 break;
775
776 default:
777 case 32:
778 *pu32 = 24; /* The upper 8 bits are either alpha bits or not used. */
779 break;
780 }
781 break;
782
783 case SVGA_REG_HOST_BITS_PER_PIXEL: /* (Deprecated) */
784 STAM_REL_COUNTER_INC(&pThis->svga.StatRegHostBitsPerPixelRd);
785 *pu32 = pThis->svga.uHostBpp;
786 break;
787
788 case SVGA_REG_BITS_PER_PIXEL: /* Current bpp in the guest */
789 STAM_REL_COUNTER_INC(&pThis->svga.StatRegBitsPerPixelRd);
790 *pu32 = pThis->svga.uBpp;
791 break;
792
793 case SVGA_REG_PSEUDOCOLOR:
794 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPsuedoColorRd);
795 *pu32 = pThis->svga.uBpp == 8; /* See section 6 "Pseudocolor" in svga_interface.txt. */
796 break;
797
798 case SVGA_REG_RED_MASK:
799 case SVGA_REG_GREEN_MASK:
800 case SVGA_REG_BLUE_MASK:
801 {
802 uint32_t uBpp;
803
804 if (pThis->svga.fEnabled)
805 uBpp = pThis->svga.uBpp;
806 else
807 uBpp = pThis->svga.uHostBpp;
808
809 uint32_t u32RedMask, u32GreenMask, u32BlueMask;
810 switch (uBpp)
811 {
812 case 8:
813 u32RedMask = 0x07;
814 u32GreenMask = 0x38;
815 u32BlueMask = 0xc0;
816 break;
817
818 case 15:
819 u32RedMask = 0x0000001f;
820 u32GreenMask = 0x000003e0;
821 u32BlueMask = 0x00007c00;
822 break;
823
824 case 16:
825 u32RedMask = 0x0000001f;
826 u32GreenMask = 0x000007e0;
827 u32BlueMask = 0x0000f800;
828 break;
829
830 case 24:
831 case 32:
832 default:
833 u32RedMask = 0x00ff0000;
834 u32GreenMask = 0x0000ff00;
835 u32BlueMask = 0x000000ff;
836 break;
837 }
838 switch (idxReg)
839 {
840 case SVGA_REG_RED_MASK:
841 STAM_REL_COUNTER_INC(&pThis->svga.StatRegRedMaskRd);
842 *pu32 = u32RedMask;
843 break;
844
845 case SVGA_REG_GREEN_MASK:
846 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGreenMaskRd);
847 *pu32 = u32GreenMask;
848 break;
849
850 case SVGA_REG_BLUE_MASK:
851 STAM_REL_COUNTER_INC(&pThis->svga.StatRegBlueMaskRd);
852 *pu32 = u32BlueMask;
853 break;
854 }
855 break;
856 }
857
858 case SVGA_REG_BYTES_PER_LINE:
859 {
860 STAM_REL_COUNTER_INC(&pThis->svga.StatRegBytesPerLineRd);
861 if ( pThis->svga.fEnabled
862 && pThis->svga.cbScanline)
863 *pu32 = pThis->svga.cbScanline;
864 else
865 {
866#ifndef IN_RING3
867 rc = VINF_IOM_R3_IOPORT_READ;
868#else
869 *pu32 = pThisCC->pDrv->cbScanline;
870#endif
871 }
872 break;
873 }
874
875 case SVGA_REG_VRAM_SIZE: /* VRAM size */
876 STAM_REL_COUNTER_INC(&pThis->svga.StatRegVramSizeRd);
877 *pu32 = pThis->vram_size;
878 break;
879
880 case SVGA_REG_FB_START: /* Frame buffer physical address. */
881 STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbStartRd);
882 Assert(pThis->GCPhysVRAM <= 0xffffffff);
883 *pu32 = pThis->GCPhysVRAM;
884 break;
885
886 case SVGA_REG_FB_OFFSET: /* Offset of the frame buffer in VRAM */
887 STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbOffsetRd);
888 /* Always zero in our case. */
889 *pu32 = 0;
890 break;
891
892 case SVGA_REG_FB_SIZE: /* Frame buffer size */
893 {
894#ifndef IN_RING3
895 rc = VINF_IOM_R3_IOPORT_READ;
896#else
897 STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbSizeRd);
898
899 /* VMWare testcases want at least 4 MB in case the hardware is disabled. */
900 if ( pThis->svga.fEnabled
901 && pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
902 {
903 /* Hardware enabled; return real framebuffer size .*/
904 *pu32 = (uint32_t)pThis->svga.uHeight * pThis->svga.cbScanline;
905 }
906 else
907 *pu32 = RT_MAX(0x100000, (uint32_t)pThisCC->pDrv->cy * pThisCC->pDrv->cbScanline);
908
909 *pu32 = RT_MIN(pThis->vram_size, *pu32);
910 Log(("h=%d w=%d bpp=%d\n", pThisCC->pDrv->cy, pThisCC->pDrv->cx, pThisCC->pDrv->cBits));
911#endif
912 break;
913 }
914
915 case SVGA_REG_CAPABILITIES:
916 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCapabilitesRd);
917 *pu32 = pThis->svga.u32DeviceCaps;
918 break;
919
920 case SVGA_REG_MEM_START: /* FIFO start */
921 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemStartRd);
922 Assert(pThis->svga.GCPhysFIFO <= 0xffffffff);
923 *pu32 = pThis->svga.GCPhysFIFO;
924 break;
925
926 case SVGA_REG_MEM_SIZE: /* FIFO size */
927 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemSizeRd);
928 *pu32 = pThis->svga.cbFIFO;
929 break;
930
931 case SVGA_REG_CONFIG_DONE: /* Set when memory area configured */
932 STAM_REL_COUNTER_INC(&pThis->svga.StatRegConfigDoneRd);
933 *pu32 = pThis->svga.fConfigured;
934 break;
935
936 case SVGA_REG_SYNC: /* See "FIFO Synchronization Registers" */
937 STAM_REL_COUNTER_INC(&pThis->svga.StatRegSyncRd);
938 *pu32 = 0;
939 break;
940
941 case SVGA_REG_BUSY: /* See "FIFO Synchronization Registers" */
942 STAM_REL_COUNTER_INC(&pThis->svga.StatRegBusyRd);
943 if (pThis->svga.fBusy)
944 {
945#ifndef IN_RING3
946 /* Go to ring-3 and halt the CPU. */
947 rc = VINF_IOM_R3_IOPORT_READ;
948 RT_NOREF(pDevIns);
949 break;
950#else
951# if defined(VMSVGA_USE_EMT_HALT_CODE)
952 /* The guest is basically doing a HLT via the device here, but with
953 a special wake up condition on FIFO completion. */
954 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
955 STAM_REL_PROFILE_START(&pSVGAState->StatBusyDelayEmts, EmtDelay);
956 PVM pVM = PDMDevHlpGetVM(pDevIns);
957 VMCPUID idCpu = PDMDevHlpGetCurrentCpuId(pDevIns);
958 VMCPUSET_ATOMIC_ADD(&pSVGAState->BusyDelayedEmts, idCpu);
959 ASMAtomicIncU32(&pSVGAState->cBusyDelayedEmts);
960 if (pThis->svga.fBusy)
961 {
962 PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); /* hack around lock order issue. */
963 rc = VMR3WaitForDeviceReady(pVM, idCpu);
964 PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_IGNORED);
965 }
966 ASMAtomicDecU32(&pSVGAState->cBusyDelayedEmts);
967 VMCPUSET_ATOMIC_DEL(&pSVGAState->BusyDelayedEmts, idCpu);
968# else
969
970 /* Delay the EMT a bit so the FIFO and others can get some work done.
971 This used to be a crude 50 ms sleep. The current code tries to be
972 more efficient, but the consept is still very crude. */
973 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
974 STAM_REL_PROFILE_START(&pSVGAState->StatBusyDelayEmts, EmtDelay);
975 RTThreadYield();
976 if (pThis->svga.fBusy)
977 {
978 uint32_t cRefs = ASMAtomicIncU32(&pSVGAState->cBusyDelayedEmts);
979
980 if (pThis->svga.fBusy && cRefs == 1)
981 RTSemEventMultiReset(pSVGAState->hBusyDelayedEmts);
982 if (pThis->svga.fBusy)
983 {
984 /** @todo If this code is going to stay, we need to call into the halt/wait
985 * code in VMEmt.cpp here, otherwise all kind of EMT interaction will
986 * suffer when the guest is polling on a busy FIFO. */
987 uint64_t cNsMaxWait = TMVirtualSyncGetNsToDeadline(PDMDevHlpGetVM(pDevIns));
988 if (cNsMaxWait >= RT_NS_100US)
989 RTSemEventMultiWaitEx(pSVGAState->hBusyDelayedEmts,
990 RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_NORESUME,
991 RT_MIN(cNsMaxWait, RT_NS_10MS));
992 }
993
994 ASMAtomicDecU32(&pSVGAState->cBusyDelayedEmts);
995 }
996 STAM_REL_PROFILE_STOP(&pSVGAState->StatBusyDelayEmts, EmtDelay);
997# endif
998 *pu32 = pThis->svga.fBusy != 0;
999#endif
1000 }
1001 else
1002 *pu32 = false;
1003 break;
1004
1005 case SVGA_REG_GUEST_ID: /* Set guest OS identifier */
1006 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGuestIdRd);
1007 *pu32 = pThis->svga.u32GuestId;
1008 break;
1009
1010 case SVGA_REG_SCRATCH_SIZE: /* Number of scratch registers */
1011 STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchSizeRd);
1012 *pu32 = pThis->svga.cScratchRegion;
1013 break;
1014
1015 case SVGA_REG_MEM_REGS: /* Number of FIFO registers */
1016 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemRegsRd);
1017 *pu32 = SVGA_FIFO_NUM_REGS;
1018 break;
1019
1020 case SVGA_REG_PITCHLOCK: /* Fixed pitch for all modes */
1021 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPitchLockRd);
1022 *pu32 = pThis->svga.u32PitchLock;
1023 break;
1024
1025 case SVGA_REG_IRQMASK: /* Interrupt mask */
1026 STAM_REL_COUNTER_INC(&pThis->svga.StatRegIrqMaskRd);
1027 *pu32 = pThis->svga.u32IrqMask;
1028 break;
1029
1030 /* See "Guest memory regions" below. */
1031 case SVGA_REG_GMR_ID:
1032 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrIdRd);
1033 *pu32 = pThis->svga.u32CurrentGMRId;
1034 break;
1035
1036 case SVGA_REG_GMR_DESCRIPTOR:
1037 STAM_REL_COUNTER_INC(&pThis->svga.StatRegWriteOnlyRd);
1038 /* Write only */
1039 *pu32 = 0;
1040 break;
1041
1042 case SVGA_REG_GMR_MAX_IDS:
1043 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrMaxIdsRd);
1044 *pu32 = pThis->svga.cGMR;
1045 break;
1046
1047 case SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH:
1048 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrMaxDescriptorLengthRd);
1049 *pu32 = VMSVGA_MAX_GMR_PAGES;
1050 break;
1051
1052 case SVGA_REG_TRACES: /* Enable trace-based updates even when FIFO is on */
1053 STAM_REL_COUNTER_INC(&pThis->svga.StatRegTracesRd);
1054 *pu32 = pThis->svga.fTraces;
1055 break;
1056
1057 case SVGA_REG_GMRS_MAX_PAGES: /* Maximum number of 4KB pages for all GMRs */
1058 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrsMaxPagesRd);
1059 *pu32 = VMSVGA_MAX_GMR_PAGES;
1060 break;
1061
1062 case SVGA_REG_MEMORY_SIZE: /* Total dedicated device memory excluding FIFO */
1063 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemorySizeRd);
1064 *pu32 = VMSVGA_SURFACE_SIZE;
1065 break;
1066
1067 case SVGA_REG_TOP: /* Must be 1 more than the last register */
1068 STAM_REL_COUNTER_INC(&pThis->svga.StatRegTopRd);
1069 break;
1070
1071 /* Mouse cursor support. */
1072 case SVGA_REG_CURSOR_ID:
1073 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorIdRd);
1074 *pu32 = pThis->svga.uCursorID;
1075 break;
1076
1077 case SVGA_REG_CURSOR_X:
1078 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorXRd);
1079 *pu32 = pThis->svga.uCursorX;
1080 break;
1081
1082 case SVGA_REG_CURSOR_Y:
1083 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorYRd);
1084 *pu32 = pThis->svga.uCursorY;
1085 break;
1086
1087 case SVGA_REG_CURSOR_ON:
1088 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorOnRd);
1089 *pu32 = pThis->svga.uCursorOn;
1090 break;
1091
1092 /* Legacy multi-monitor support */
1093 case SVGA_REG_NUM_GUEST_DISPLAYS:/* Number of guest displays in X/Y direction */
1094 STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumGuestDisplaysRd);
1095 *pu32 = 1;
1096 break;
1097
1098 case SVGA_REG_DISPLAY_ID: /* Display ID for the following display attributes */
1099 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIdRd);
1100 *pu32 = 0;
1101 break;
1102
1103 case SVGA_REG_DISPLAY_IS_PRIMARY:/* Whether this is a primary display */
1104 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIsPrimaryRd);
1105 *pu32 = 0;
1106 break;
1107
1108 case SVGA_REG_DISPLAY_POSITION_X:/* The display position x */
1109 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionXRd);
1110 *pu32 = 0;
1111 break;
1112
1113 case SVGA_REG_DISPLAY_POSITION_Y:/* The display position y */
1114 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionYRd);
1115 *pu32 = 0;
1116 break;
1117
1118 case SVGA_REG_DISPLAY_WIDTH: /* The display's width */
1119 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayWidthRd);
1120 *pu32 = pThis->svga.uWidth;
1121 break;
1122
1123 case SVGA_REG_DISPLAY_HEIGHT: /* The display's height */
1124 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayHeightRd);
1125 *pu32 = pThis->svga.uHeight;
1126 break;
1127
1128 case SVGA_REG_NUM_DISPLAYS: /* (Deprecated) */
1129 STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumDisplaysRd);
1130 /* We must return something sensible here otherwise the Linux driver
1131 will take a legacy code path without 3d support. This number also
1132 limits how many screens Linux guests will allow. */
1133 *pu32 = pThis->cMonitors;
1134 break;
1135
1136 /*
1137 * SVGA_CAP_GBOBJECTS+ registers.
1138 */
1139 case SVGA_REG_COMMAND_LOW:
1140 /* Lower 32 bits of command buffer physical address. */
1141 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCommandLowRd);
1142 *pu32 = pThis->svga.u32RegCommandLow;
1143 break;
1144
1145 case SVGA_REG_COMMAND_HIGH:
1146 /* Upper 32 bits of command buffer PA. */
1147 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCommandHighRd);
1148 *pu32 = pThis->svga.u32RegCommandHigh;
1149 break;
1150
1151 case SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM:
1152 /* Max primary (screen) memory. */
1153 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMaxPrimBBMemRd);
1154 *pu32 = pThis->vram_size; /** @todo Maybe half VRAM? */
1155 break;
1156
1157 case SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB:
1158 /* Suggested limit on mob mem (i.e. size of the guest mapped VRAM in KB) */
1159 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGBMemSizeRd);
1160 *pu32 = pThis->vram_size / 1024;
1161 break;
1162
1163 case SVGA_REG_DEV_CAP:
1164 /* Write dev cap index, read value */
1165 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDevCapRd);
1166 if (pThis->svga.u32DevCapIndex < RT_ELEMENTS(pThis->svga.au32DevCaps))
1167 {
1168 RT_UNTRUSTED_VALIDATED_FENCE();
1169 *pu32 = pThis->svga.au32DevCaps[pThis->svga.u32DevCapIndex];
1170 }
1171 else
1172 *pu32 = 0;
1173 break;
1174
1175 case SVGA_REG_CMD_PREPEND_LOW:
1176 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCmdPrependLowRd);
1177 *pu32 = 0; /* Not supported. */
1178 break;
1179
1180 case SVGA_REG_iCMD_PREPEND_HIGH:
1181 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCmdPrependHighRd);
1182 *pu32 = 0; /* Not supported. */
1183 break;
1184
1185 case SVGA_REG_SCREENTARGET_MAX_WIDTH:
1186 STAM_REL_COUNTER_INC(&pThis->svga.StatRegScrnTgtMaxWidthRd);
1187 *pu32 = pThis->svga.u32MaxWidth;
1188 break;
1189
1190 case SVGA_REG_SCREENTARGET_MAX_HEIGHT:
1191 STAM_REL_COUNTER_INC(&pThis->svga.StatRegScrnTgtMaxHeightRd);
1192 *pu32 = pThis->svga.u32MaxHeight;
1193 break;
1194
1195 case SVGA_REG_MOB_MAX_SIZE:
1196 /* Essentially the max texture size */
1197 STAM_REL_COUNTER_INC(&pThis->svga.StatRegMobMaxSizeRd);
1198 *pu32 = _128M; /** @todo Some actual value. Probably the mapped VRAM size. */
1199 break;
1200
1201 default:
1202 {
1203 uint32_t offReg;
1204 if ((offReg = idxReg - SVGA_SCRATCH_BASE) < pThis->svga.cScratchRegion)
1205 {
1206 STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchRd);
1207 RT_UNTRUSTED_VALIDATED_FENCE();
1208 *pu32 = pThis->svga.au32ScratchRegion[offReg];
1209 }
1210 else if ((offReg = idxReg - SVGA_PALETTE_BASE) < (uint32_t)SVGA_NUM_PALETTE_REGS)
1211 {
1212 /* Note! Using last_palette rather than palette here to preserve the VGA one. */
1213 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPaletteRd);
1214 RT_UNTRUSTED_VALIDATED_FENCE();
1215 uint32_t u32 = pThis->last_palette[offReg / 3];
1216 switch (offReg % 3)
1217 {
1218 case 0: *pu32 = (u32 >> 16) & 0xff; break; /* red */
1219 case 1: *pu32 = (u32 >> 8) & 0xff; break; /* green */
1220 case 2: *pu32 = u32 & 0xff; break; /* blue */
1221 }
1222 }
1223 else
1224 {
1225#if !defined(IN_RING3) && defined(VBOX_STRICT)
1226 rc = VINF_IOM_R3_IOPORT_READ;
1227#else
1228 STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownRd);
1229
1230 /* Do not assert. The guest might be reading all registers. */
1231 LogFunc(("Unknown reg=%#x\n", idxReg));
1232#endif
1233 }
1234 break;
1235 }
1236 }
1237 Log(("vmsvgaReadPort index=%s (%d) val=%#x rc=%x\n", vmsvgaIndexToString(pThis, idxReg), idxReg, *pu32, rc));
1238 return rc;
1239}
1240
1241#ifdef IN_RING3
1242/**
1243 * Apply the current resolution settings to change the video mode.
1244 *
1245 * @returns VBox status code.
1246 * @param pThis The shared VGA state.
1247 * @param pThisCC The ring-3 VGA state.
1248 */
1249int vmsvgaR3ChangeMode(PVGASTATE pThis, PVGASTATECC pThisCC)
1250{
1251 /* Always do changemode on FIFO thread. */
1252 Assert(RTThreadSelf() == pThisCC->svga.pFIFOIOThread->Thread);
1253
1254 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
1255
1256 pThisCC->pDrv->pfnLFBModeChange(pThisCC->pDrv, true);
1257
1258 if (pThis->svga.fGFBRegisters)
1259 {
1260 /* "For backwards compatibility, when the GFB mode registers (WIDTH,
1261 * HEIGHT, PITCHLOCK, BITS_PER_PIXEL) are modified, the SVGA device
1262 * deletes all screens other than screen #0, and redefines screen
1263 * #0 according to the specified mode. Drivers that use
1264 * SVGA_CMD_DEFINE_SCREEN should destroy or redefine screen #0."
1265 */
1266
1267 VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[0];
1268 pScreen->fDefined = true;
1269 pScreen->fModified = true;
1270 pScreen->fuScreen = SVGA_SCREEN_MUST_BE_SET | SVGA_SCREEN_IS_PRIMARY;
1271 pScreen->idScreen = 0;
1272 pScreen->xOrigin = 0;
1273 pScreen->yOrigin = 0;
1274 pScreen->offVRAM = 0;
1275 pScreen->cbPitch = pThis->svga.cbScanline;
1276 pScreen->cWidth = pThis->svga.uWidth;
1277 pScreen->cHeight = pThis->svga.uHeight;
1278 pScreen->cBpp = pThis->svga.uBpp;
1279
1280 for (unsigned iScreen = 1; iScreen < RT_ELEMENTS(pSVGAState->aScreens); ++iScreen)
1281 {
1282 /* Delete screen. */
1283 pScreen = &pSVGAState->aScreens[iScreen];
1284 if (pScreen->fDefined)
1285 {
1286 pScreen->fModified = true;
1287 pScreen->fDefined = false;
1288 }
1289 }
1290 }
1291 else
1292 {
1293 /* "If Screen Objects are supported, they can be used to fully
1294 * replace the functionality provided by the framebuffer registers
1295 * (SVGA_REG_WIDTH, HEIGHT, etc.) and by SVGA_CAP_DISPLAY_TOPOLOGY."
1296 */
1297 pThis->svga.uWidth = VMSVGA_VAL_UNINITIALIZED;
1298 pThis->svga.uHeight = VMSVGA_VAL_UNINITIALIZED;
1299 pThis->svga.uBpp = pThis->svga.uHostBpp;
1300 }
1301
1302 vmsvgaR3VBVAResize(pThis, pThisCC);
1303
1304 /* Last stuff. For the VGA device screenshot. */
1305 pThis->last_bpp = pSVGAState->aScreens[0].cBpp;
1306 pThis->last_scr_width = pSVGAState->aScreens[0].cWidth;
1307 pThis->last_scr_height = pSVGAState->aScreens[0].cHeight;
1308 pThis->last_width = pSVGAState->aScreens[0].cWidth;
1309 pThis->last_height = pSVGAState->aScreens[0].cHeight;
1310
1311 /* vmsvgaPortSetViewPort not called after state load; set sensible defaults. */
1312 if ( pThis->svga.viewport.cx == 0
1313 && pThis->svga.viewport.cy == 0)
1314 {
1315 pThis->svga.viewport.cx = pSVGAState->aScreens[0].cWidth;
1316 pThis->svga.viewport.xRight = pSVGAState->aScreens[0].cWidth;
1317 pThis->svga.viewport.cy = pSVGAState->aScreens[0].cHeight;
1318 pThis->svga.viewport.yHighWC = pSVGAState->aScreens[0].cHeight;
1319 pThis->svga.viewport.yLowWC = 0;
1320 }
1321
1322 return VINF_SUCCESS;
1323}
1324
1325int vmsvgaR3UpdateScreen(PVGASTATECC pThisCC, VMSVGASCREENOBJECT *pScreen, int x, int y, int w, int h)
1326{
1327 VBVACMDHDR cmd;
1328 cmd.x = (int16_t)(pScreen->xOrigin + x);
1329 cmd.y = (int16_t)(pScreen->yOrigin + y);
1330 cmd.w = (uint16_t)w;
1331 cmd.h = (uint16_t)h;
1332
1333 pThisCC->pDrv->pfnVBVAUpdateBegin(pThisCC->pDrv, pScreen->idScreen);
1334 pThisCC->pDrv->pfnVBVAUpdateProcess(pThisCC->pDrv, pScreen->idScreen, &cmd, sizeof(cmd));
1335 pThisCC->pDrv->pfnVBVAUpdateEnd(pThisCC->pDrv, pScreen->idScreen,
1336 pScreen->xOrigin + x, pScreen->yOrigin + y, w, h);
1337
1338 return VINF_SUCCESS;
1339}
1340
1341#endif /* IN_RING3 */
1342#if defined(IN_RING0) || defined(IN_RING3)
1343
1344/**
1345 * Safely updates the SVGA_FIFO_BUSY register (in shared memory).
1346 *
1347 * @param pThis The shared VGA/VMSVGA instance data.
1348 * @param pThisCC The VGA/VMSVGA state for the current context.
1349 * @param fState The busy state.
1350 */
1351DECLINLINE(void) vmsvgaHCSafeFifoBusyRegUpdate(PVGASTATE pThis, PVGASTATECC pThisCC, bool fState)
1352{
1353 ASMAtomicWriteU32(&pThisCC->svga.pau32FIFO[SVGA_FIFO_BUSY], fState);
1354
1355 if (RT_UNLIKELY(fState != (pThis->svga.fBusy != 0)))
1356 {
1357 /* Race / unfortunately scheduling. Highly unlikly. */
1358 uint32_t cLoops = 64;
1359 do
1360 {
1361 ASMNopPause();
1362 fState = (pThis->svga.fBusy != 0);
1363 ASMAtomicWriteU32(&pThisCC->svga.pau32FIFO[SVGA_FIFO_BUSY], fState != 0);
1364 } while (cLoops-- > 0 && fState != (pThis->svga.fBusy != 0));
1365 }
1366}
1367
1368
1369/**
1370 * Update the scanline pitch in response to the guest changing mode
1371 * width/bpp.
1372 *
1373 * @param pThis The shared VGA/VMSVGA state.
1374 * @param pThisCC The VGA/VMSVGA state for the current context.
1375 */
1376DECLINLINE(void) vmsvgaHCUpdatePitch(PVGASTATE pThis, PVGASTATECC pThisCC)
1377{
1378 uint32_t RT_UNTRUSTED_VOLATILE_GUEST *pFIFO = pThisCC->svga.pau32FIFO;
1379 uint32_t uFifoPitchLock = pFIFO[SVGA_FIFO_PITCHLOCK];
1380 uint32_t uRegPitchLock = pThis->svga.u32PitchLock;
1381 uint32_t uFifoMin = pFIFO[SVGA_FIFO_MIN];
1382
1383 /* The SVGA_FIFO_PITCHLOCK register is only valid if SVGA_FIFO_MIN points past
1384 * it. If SVGA_FIFO_MIN is small, there may well be data at the SVGA_FIFO_PITCHLOCK
1385 * location but it has a different meaning.
1386 */
1387 if ((uFifoMin / sizeof(uint32_t)) <= SVGA_FIFO_PITCHLOCK)
1388 uFifoPitchLock = 0;
1389
1390 /* Sanitize values. */
1391 if ((uFifoPitchLock < 200) || (uFifoPitchLock > 32768))
1392 uFifoPitchLock = 0;
1393 if ((uRegPitchLock < 200) || (uRegPitchLock > 32768))
1394 uRegPitchLock = 0;
1395
1396 /* Prefer the register value to the FIFO value.*/
1397 if (uRegPitchLock)
1398 pThis->svga.cbScanline = uRegPitchLock;
1399 else if (uFifoPitchLock)
1400 pThis->svga.cbScanline = uFifoPitchLock;
1401 else
1402 pThis->svga.cbScanline = pThis->svga.uWidth * (RT_ALIGN(pThis->svga.uBpp, 8) / 8);
1403
1404 if ((uFifoMin / sizeof(uint32_t)) <= SVGA_FIFO_PITCHLOCK)
1405 pThis->svga.u32PitchLock = pThis->svga.cbScanline;
1406}
1407
1408#endif /* IN_RING0 || IN_RING3 */
1409
1410#ifdef IN_RING3
1411
1412/**
1413 * Sends cursor position and visibility information from legacy
1414 * SVGA registers to the front-end.
1415 */
1416static void vmsvgaR3RegUpdateCursor(PVGASTATECC pThisCC, PVGASTATE pThis, uint32_t uCursorOn)
1417{
1418 /*
1419 * Writing the X/Y/ID registers does not trigger changes; only writing the
1420 * SVGA_REG_CURSOR_ON register does. That minimizes the overhead.
1421 * We boldly assume that guests aren't stupid and aren't writing the CURSOR_ON
1422 * register if they don't have to.
1423 */
1424 uint32_t x, y, idScreen;
1425 uint32_t fFlags = VBVA_CURSOR_VALID_DATA;
1426
1427 x = pThis->svga.uCursorX;
1428 y = pThis->svga.uCursorY;
1429 idScreen = SVGA_ID_INVALID; /* The old register interface is single screen only. */
1430
1431 /* The original values for SVGA_REG_CURSOR_ON were off (0) and on (1); later, the values
1432 * were extended as follows:
1433 *
1434 * SVGA_CURSOR_ON_HIDE 0
1435 * SVGA_CURSOR_ON_SHOW 1
1436 * SVGA_CURSOR_ON_REMOVE_FROM_FB 2 - cursor on but not in the framebuffer
1437 * SVGA_CURSOR_ON_RESTORE_TO_FB 3 - cursor on, possibly in the framebuffer
1438 *
1439 * Since we never draw the cursor into the guest's framebuffer, we do not need to
1440 * distinguish between the non-zero values but still remember them.
1441 */
1442 if (RT_BOOL(pThis->svga.uCursorOn) != RT_BOOL(uCursorOn))
1443 {
1444 LogRel2(("vmsvgaR3RegUpdateCursor: uCursorOn %d prev CursorOn %d (%d,%d)\n", uCursorOn, pThis->svga.uCursorOn, x, y));
1445 pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, RT_BOOL(uCursorOn), false, 0, 0, 0, 0, NULL);
1446 }
1447 pThis->svga.uCursorOn = uCursorOn;
1448 pThisCC->pDrv->pfnVBVAReportCursorPosition(pThisCC->pDrv, fFlags, idScreen, x, y);
1449}
1450
1451#endif /* IN_RING3 */
1452
1453
1454/**
1455 * Write port register
1456 *
1457 * @returns Strict VBox status code.
1458 * @param pDevIns The device instance.
1459 * @param pThis The shared VGA/VMSVGA state.
1460 * @param pThisCC The VGA/VMSVGA state for the current context.
1461 * @param u32 Value to write
1462 */
1463static VBOXSTRICTRC vmsvgaWritePort(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t u32)
1464{
1465#ifdef IN_RING3
1466 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
1467#endif
1468 VBOXSTRICTRC rc = VINF_SUCCESS;
1469 RT_NOREF(pThisCC);
1470
1471 /* Rough index register validation. */
1472 uint32_t idxReg = pThis->svga.u32IndexReg;
1473#if !defined(IN_RING3) && defined(VBOX_STRICT)
1474 ASSERT_GUEST_MSG_RETURN(idxReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion, ("idxReg=%#x\n", idxReg),
1475 VINF_IOM_R3_IOPORT_WRITE);
1476#else
1477 ASSERT_GUEST_MSG_STMT_RETURN(idxReg < SVGA_SCRATCH_BASE + pThis->svga.cScratchRegion, ("idxReg=%#x\n", idxReg),
1478 STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownWr),
1479 VINF_SUCCESS);
1480#endif
1481 RT_UNTRUSTED_VALIDATED_FENCE();
1482
1483 /* We must adjust the register number if we're in SVGA_ID_0 mode because the PALETTE range moved. */
1484 if ( idxReg >= SVGA_REG_ID_0_TOP
1485 && pThis->svga.u32SVGAId == SVGA_ID_0)
1486 {
1487 idxReg += SVGA_PALETTE_BASE - SVGA_REG_ID_0_TOP;
1488 Log(("vmsvgaWritePort: SVGA_ID_0 reg adj %#x -> %#x\n", pThis->svga.u32IndexReg, idxReg));
1489 }
1490 Log(("vmsvgaWritePort index=%s (%d) val=%#x\n", vmsvgaIndexToString(pThis, idxReg), idxReg, u32));
1491 /* Check if the guest uses legacy registers. See vmsvgaR3ChangeMode */
1492 switch (idxReg)
1493 {
1494 case SVGA_REG_WIDTH:
1495 case SVGA_REG_HEIGHT:
1496 case SVGA_REG_PITCHLOCK:
1497 case SVGA_REG_BITS_PER_PIXEL:
1498 pThis->svga.fGFBRegisters = true;
1499 break;
1500 default:
1501 break;
1502 }
1503
1504 switch (idxReg)
1505 {
1506 case SVGA_REG_ID:
1507 STAM_REL_COUNTER_INC(&pThis->svga.StatRegIdWr);
1508 if ( u32 == SVGA_ID_0
1509 || u32 == SVGA_ID_1
1510 || u32 == SVGA_ID_2)
1511 pThis->svga.u32SVGAId = u32;
1512 else
1513 PDMDevHlpDBGFStop(pDevIns, RT_SRC_POS, "Trying to set SVGA_REG_ID to %#x (%d)\n", u32, u32);
1514 break;
1515
1516 case SVGA_REG_ENABLE:
1517 STAM_REL_COUNTER_INC(&pThis->svga.StatRegEnableWr);
1518#ifdef IN_RING3
1519 if ( (u32 & SVGA_REG_ENABLE_ENABLE)
1520 && pThis->svga.fEnabled == false)
1521 {
1522 /* Make a backup copy of the first 512kb in order to save font data etc. */
1523 /** @todo should probably swap here, rather than copy + zero */
1524 memcpy(pThisCC->svga.pbVgaFrameBufferR3, pThisCC->pbVRam, VMSVGA_VGA_FB_BACKUP_SIZE);
1525 memset(pThisCC->pbVRam, 0, VMSVGA_VGA_FB_BACKUP_SIZE);
1526 }
1527
1528 pThis->svga.fEnabled = u32;
1529 if (pThis->svga.fEnabled)
1530 {
1531 if ( pThis->svga.uWidth == VMSVGA_VAL_UNINITIALIZED
1532 && pThis->svga.uHeight == VMSVGA_VAL_UNINITIALIZED)
1533 {
1534 /* Keep the current mode. */
1535 pThis->svga.uWidth = pThisCC->pDrv->cx;
1536 pThis->svga.uHeight = pThisCC->pDrv->cy;
1537 pThis->svga.uBpp = (pThisCC->pDrv->cBits + 7) & ~7;
1538 }
1539
1540 if ( pThis->svga.uWidth != VMSVGA_VAL_UNINITIALIZED
1541 && pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
1542 ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
1543# ifdef LOG_ENABLED
1544 uint32_t *pFIFO = pThisCC->svga.pau32FIFO;
1545 Log(("configured=%d busy=%d\n", pThis->svga.fConfigured, pFIFO[SVGA_FIFO_BUSY]));
1546 Log(("next %x stop %x\n", pFIFO[SVGA_FIFO_NEXT_CMD], pFIFO[SVGA_FIFO_STOP]));
1547# endif
1548
1549 /* Disable or enable dirty page tracking according to the current fTraces value. */
1550 vmsvgaR3SetTraces(pDevIns, pThis, !!pThis->svga.fTraces);
1551
1552 /* bird: Whatever this is was added to make screenshot work, ask sunlover should explain... */
1553 for (uint32_t idScreen = 0; idScreen < pThis->cMonitors; ++idScreen)
1554 pThisCC->pDrv->pfnVBVAEnable(pThisCC->pDrv, idScreen, NULL /*pHostFlags*/);
1555
1556 /* Make the cursor visible again as needed. */
1557 if (pSVGAState->Cursor.fActive)
1558 pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, true /*fVisible*/, false, 0, 0, 0, 0, NULL);
1559 }
1560 else
1561 {
1562 /* Make sure the cursor is off. */
1563 if (pSVGAState->Cursor.fActive)
1564 pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, false /*fVisible*/, false, 0, 0, 0, 0, NULL);
1565
1566 /* Restore the text mode backup. */
1567 memcpy(pThisCC->pbVRam, pThisCC->svga.pbVgaFrameBufferR3, VMSVGA_VGA_FB_BACKUP_SIZE);
1568
1569 pThisCC->pDrv->pfnLFBModeChange(pThisCC->pDrv, false);
1570
1571 /* Enable dirty page tracking again when going into legacy mode. */
1572 vmsvgaR3SetTraces(pDevIns, pThis, true);
1573
1574 /* bird: Whatever this is was added to make screenshot work, ask sunlover should explain... */
1575 for (uint32_t idScreen = 0; idScreen < pThis->cMonitors; ++idScreen)
1576 pThisCC->pDrv->pfnVBVADisable(pThisCC->pDrv, idScreen);
1577
1578 /* Clear the pitch lock. */
1579 pThis->svga.u32PitchLock = 0;
1580 }
1581#else /* !IN_RING3 */
1582 rc = VINF_IOM_R3_IOPORT_WRITE;
1583#endif /* !IN_RING3 */
1584 break;
1585
1586 case SVGA_REG_WIDTH:
1587 STAM_REL_COUNTER_INC(&pThis->svga.StatRegWidthWr);
1588 if (pThis->svga.uWidth != u32)
1589 {
1590#if defined(IN_RING3) || defined(IN_RING0)
1591 pThis->svga.uWidth = u32;
1592 vmsvgaHCUpdatePitch(pThis, pThisCC);
1593 if (pThis->svga.fEnabled)
1594 ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
1595#else
1596 rc = VINF_IOM_R3_IOPORT_WRITE;
1597#endif
1598 }
1599 /* else: nop */
1600 break;
1601
1602 case SVGA_REG_HEIGHT:
1603 STAM_REL_COUNTER_INC(&pThis->svga.StatRegHeightWr);
1604 if (pThis->svga.uHeight != u32)
1605 {
1606 pThis->svga.uHeight = u32;
1607 if (pThis->svga.fEnabled)
1608 ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
1609 }
1610 /* else: nop */
1611 break;
1612
1613 case SVGA_REG_DEPTH:
1614 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDepthWr);
1615 /** @todo read-only?? */
1616 break;
1617
1618 case SVGA_REG_BITS_PER_PIXEL: /* Current bpp in the guest */
1619 STAM_REL_COUNTER_INC(&pThis->svga.StatRegBitsPerPixelWr);
1620 if (pThis->svga.uBpp != u32)
1621 {
1622#if defined(IN_RING3) || defined(IN_RING0)
1623 pThis->svga.uBpp = u32;
1624 vmsvgaHCUpdatePitch(pThis, pThisCC);
1625 if (pThis->svga.fEnabled)
1626 ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
1627#else
1628 rc = VINF_IOM_R3_IOPORT_WRITE;
1629#endif
1630 }
1631 /* else: nop */
1632 break;
1633
1634 case SVGA_REG_PSEUDOCOLOR:
1635 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPseudoColorWr);
1636 break;
1637
1638 case SVGA_REG_CONFIG_DONE: /* Set when memory area configured */
1639#ifdef IN_RING3
1640 STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegConfigDoneWr);
1641 pThis->svga.fConfigured = u32;
1642 /* Disabling the FIFO enables tracing (dirty page detection) by default. */
1643 if (!pThis->svga.fConfigured)
1644 pThis->svga.fTraces = true;
1645 vmsvgaR3SetTraces(pDevIns, pThis, !!pThis->svga.fTraces);
1646#else
1647 rc = VINF_IOM_R3_IOPORT_WRITE;
1648#endif
1649 break;
1650
1651 case SVGA_REG_SYNC: /* See "FIFO Synchronization Registers" */
1652 STAM_REL_COUNTER_INC(&pThis->svga.StatRegSyncWr);
1653 if ( pThis->svga.fEnabled
1654 && pThis->svga.fConfigured)
1655 {
1656#if defined(IN_RING3) || defined(IN_RING0)
1657 Log(("SVGA_REG_SYNC: SVGA_FIFO_BUSY=%d\n", pThisCC->svga.pau32FIFO[SVGA_FIFO_BUSY]));
1658 /*
1659 * The VMSVGA_BUSY_F_EMT_FORCE flag makes sure we will check if the FIFO is empty
1660 * at least once; VMSVGA_BUSY_F_FIFO alone does not ensure that.
1661 */
1662 ASMAtomicWriteU32(&pThis->svga.fBusy, VMSVGA_BUSY_F_EMT_FORCE | VMSVGA_BUSY_F_FIFO);
1663 if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, pThisCC->svga.pau32FIFO[SVGA_FIFO_MIN]))
1664 vmsvgaHCSafeFifoBusyRegUpdate(pThis, pThisCC, true);
1665
1666 /* Kick the FIFO thread to start processing commands again. */
1667 PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
1668#else
1669 rc = VINF_IOM_R3_IOPORT_WRITE;
1670#endif
1671 }
1672 /* else nothing to do. */
1673 else
1674 Log(("Sync ignored enabled=%d configured=%d\n", pThis->svga.fEnabled, pThis->svga.fConfigured));
1675
1676 break;
1677
1678 case SVGA_REG_BUSY: /* See "FIFO Synchronization Registers" (read-only) */
1679 STAM_REL_COUNTER_INC(&pThis->svga.StatRegBusyWr);
1680 break;
1681
1682 case SVGA_REG_GUEST_ID: /* Set guest OS identifier */
1683 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGuestIdWr);
1684 pThis->svga.u32GuestId = u32;
1685 break;
1686
1687 case SVGA_REG_PITCHLOCK: /* Fixed pitch for all modes */
1688 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPitchLockWr);
1689 pThis->svga.u32PitchLock = u32;
1690 /* Should this also update the FIFO pitch lock? Unclear. */
1691 break;
1692
1693 case SVGA_REG_IRQMASK: /* Interrupt mask */
1694 STAM_REL_COUNTER_INC(&pThis->svga.StatRegIrqMaskWr);
1695 pThis->svga.u32IrqMask = u32;
1696
1697 /* Irq pending after the above change? */
1698 if (pThis->svga.u32IrqStatus & u32)
1699 {
1700 Log(("SVGA_REG_IRQMASK: Trigger interrupt with status %x\n", pThis->svga.u32IrqStatus));
1701 PDMDevHlpPCISetIrqNoWait(pDevIns, 0, 1);
1702 }
1703 else
1704 PDMDevHlpPCISetIrqNoWait(pDevIns, 0, 0);
1705 break;
1706
1707 /* Mouse cursor support */
1708 case SVGA_REG_CURSOR_ID:
1709 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorIdWr);
1710 pThis->svga.uCursorID = u32;
1711 break;
1712
1713 case SVGA_REG_CURSOR_X:
1714 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorXWr);
1715 pThis->svga.uCursorX = u32;
1716 break;
1717
1718 case SVGA_REG_CURSOR_Y:
1719 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorYWr);
1720 pThis->svga.uCursorY = u32;
1721 break;
1722
1723 case SVGA_REG_CURSOR_ON:
1724#ifdef IN_RING3
1725 /* The cursor is only updated when SVGA_REG_CURSOR_ON is written. */
1726 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorOnWr);
1727 vmsvgaR3RegUpdateCursor(pThisCC, pThis, u32);
1728#else
1729 rc = VINF_IOM_R3_IOPORT_WRITE;
1730#endif
1731 break;
1732
1733 /* Legacy multi-monitor support */
1734 case SVGA_REG_NUM_GUEST_DISPLAYS:/* Number of guest displays in X/Y direction */
1735 STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumGuestDisplaysWr);
1736 break;
1737 case SVGA_REG_DISPLAY_ID: /* Display ID for the following display attributes */
1738 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIdWr);
1739 break;
1740 case SVGA_REG_DISPLAY_IS_PRIMARY:/* Whether this is a primary display */
1741 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIsPrimaryWr);
1742 break;
1743 case SVGA_REG_DISPLAY_POSITION_X:/* The display position x */
1744 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionXWr);
1745 break;
1746 case SVGA_REG_DISPLAY_POSITION_Y:/* The display position y */
1747 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionYWr);
1748 break;
1749 case SVGA_REG_DISPLAY_WIDTH: /* The display's width */
1750 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayWidthWr);
1751 break;
1752 case SVGA_REG_DISPLAY_HEIGHT: /* The display's height */
1753 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayHeightWr);
1754 break;
1755#ifdef VBOX_WITH_VMSVGA3D
1756 /* See "Guest memory regions" below. */
1757 case SVGA_REG_GMR_ID:
1758 STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrIdWr);
1759 pThis->svga.u32CurrentGMRId = u32;
1760 break;
1761
1762 case SVGA_REG_GMR_DESCRIPTOR:
1763# ifndef IN_RING3
1764 rc = VINF_IOM_R3_IOPORT_WRITE;
1765 break;
1766# else /* IN_RING3 */
1767 {
1768 STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWr);
1769
1770 /* Validate current GMR id. */
1771 uint32_t idGMR = pThis->svga.u32CurrentGMRId;
1772 AssertBreak(idGMR < pThis->svga.cGMR);
1773 RT_UNTRUSTED_VALIDATED_FENCE();
1774
1775 /* Free the old GMR if present. */
1776 vmsvgaR3GmrFree(pThisCC, idGMR);
1777
1778 /* Just undefine the GMR? */
1779 RTGCPHYS GCPhys = (RTGCPHYS)u32 << PAGE_SHIFT;
1780 if (GCPhys == 0)
1781 {
1782 STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWrFree);
1783 break;
1784 }
1785
1786
1787 /* Never cross a page boundary automatically. */
1788 const uint32_t cMaxPages = RT_MIN(VMSVGA_MAX_GMR_PAGES, UINT32_MAX / X86_PAGE_SIZE);
1789 uint32_t cPagesTotal = 0;
1790 uint32_t iDesc = 0;
1791 PVMSVGAGMRDESCRIPTOR paDescs = NULL;
1792 uint32_t cLoops = 0;
1793 RTGCPHYS GCPhysBase = GCPhys;
1794 while (PHYS_PAGE_ADDRESS(GCPhys) == PHYS_PAGE_ADDRESS(GCPhysBase))
1795 {
1796 /* Read descriptor. */
1797 SVGAGuestMemDescriptor desc;
1798 rc = PDMDevHlpPCIPhysRead(pDevIns, GCPhys, &desc, sizeof(desc));
1799 AssertRCBreak(VBOXSTRICTRC_VAL(rc));
1800
1801 if (desc.numPages != 0)
1802 {
1803 AssertBreakStmt(desc.numPages <= cMaxPages, rc = VERR_OUT_OF_RANGE);
1804 cPagesTotal += desc.numPages;
1805 AssertBreakStmt(cPagesTotal <= cMaxPages, rc = VERR_OUT_OF_RANGE);
1806
1807 if ((iDesc & 15) == 0)
1808 {
1809 void *pvNew = RTMemRealloc(paDescs, (iDesc + 16) * sizeof(VMSVGAGMRDESCRIPTOR));
1810 AssertBreakStmt(pvNew, rc = VERR_NO_MEMORY);
1811 paDescs = (PVMSVGAGMRDESCRIPTOR)pvNew;
1812 }
1813
1814 paDescs[iDesc].GCPhys = (RTGCPHYS)desc.ppn << PAGE_SHIFT;
1815 paDescs[iDesc++].numPages = desc.numPages;
1816
1817 /* Continue with the next descriptor. */
1818 GCPhys += sizeof(desc);
1819 }
1820 else if (desc.ppn == 0)
1821 break; /* terminator */
1822 else /* Pointer to the next physical page of descriptors. */
1823 GCPhys = GCPhysBase = (RTGCPHYS)desc.ppn << PAGE_SHIFT;
1824
1825 cLoops++;
1826 AssertBreakStmt(cLoops < VMSVGA_MAX_GMR_DESC_LOOP_COUNT, rc = VERR_OUT_OF_RANGE);
1827 }
1828
1829 AssertStmt(iDesc > 0 || RT_FAILURE_NP(rc), rc = VERR_OUT_OF_RANGE);
1830 if (RT_SUCCESS(rc))
1831 {
1832 /* Commit the GMR. */
1833 pSVGAState->paGMR[idGMR].paDesc = paDescs;
1834 pSVGAState->paGMR[idGMR].numDescriptors = iDesc;
1835 pSVGAState->paGMR[idGMR].cMaxPages = cPagesTotal;
1836 pSVGAState->paGMR[idGMR].cbTotal = cPagesTotal * PAGE_SIZE;
1837 Assert((pSVGAState->paGMR[idGMR].cbTotal >> PAGE_SHIFT) == cPagesTotal);
1838 Log(("Defined new gmr %x numDescriptors=%d cbTotal=%x (%#x pages)\n",
1839 idGMR, iDesc, pSVGAState->paGMR[idGMR].cbTotal, cPagesTotal));
1840 }
1841 else
1842 {
1843 RTMemFree(paDescs);
1844 STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWrErrors);
1845 }
1846 break;
1847 }
1848# endif /* IN_RING3 */
1849#endif // VBOX_WITH_VMSVGA3D
1850
1851 case SVGA_REG_TRACES: /* Enable trace-based updates even when FIFO is on */
1852 STAM_REL_COUNTER_INC(&pThis->svga.StatRegTracesWr);
1853 if (pThis->svga.fTraces == u32)
1854 break; /* nothing to do */
1855
1856#ifdef IN_RING3
1857 vmsvgaR3SetTraces(pDevIns, pThis, !!u32);
1858#else
1859 rc = VINF_IOM_R3_IOPORT_WRITE;
1860#endif
1861 break;
1862
1863 case SVGA_REG_TOP: /* Must be 1 more than the last register */
1864 STAM_REL_COUNTER_INC(&pThis->svga.StatRegTopWr);
1865 break;
1866
1867 case SVGA_REG_NUM_DISPLAYS: /* (Deprecated) */
1868 STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumDisplaysWr);
1869 Log(("Write to deprecated register %x - val %x ignored\n", idxReg, u32));
1870 break;
1871
1872 /*
1873 * SVGA_CAP_GBOBJECTS+ registers.
1874 */
1875 case SVGA_REG_COMMAND_LOW:
1876 {
1877 /* Lower 32 bits of command buffer physical address and submit the command buffer. */
1878#ifdef IN_RING3
1879 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCommandLowWr);
1880 pThis->svga.u32RegCommandLow = u32;
1881
1882 /* "lower 6 bits are used for the SVGACBContext" */
1883 RTGCPHYS GCPhysCB = pThis->svga.u32RegCommandHigh;
1884 GCPhysCB <<= 32;
1885 GCPhysCB |= pThis->svga.u32RegCommandLow & ~SVGA_CB_CONTEXT_MASK;
1886 SVGACBContext const CBCtx = (SVGACBContext)(pThis->svga.u32RegCommandLow & SVGA_CB_CONTEXT_MASK);
1887 vmsvgaR3CmdBufSubmit(pDevIns, pThis, pThisCC, GCPhysCB, CBCtx);
1888#else
1889 rc = VINF_IOM_R3_IOPORT_WRITE;
1890#endif
1891 break;
1892 }
1893
1894 case SVGA_REG_COMMAND_HIGH:
1895 /* Upper 32 bits of command buffer PA. */
1896 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCommandHighWr);
1897 pThis->svga.u32RegCommandHigh = u32;
1898 break;
1899
1900 case SVGA_REG_DEV_CAP:
1901 /* Write dev cap index, read value */
1902 STAM_REL_COUNTER_INC(&pThis->svga.StatRegDevCapWr);
1903 pThis->svga.u32DevCapIndex = u32;
1904 break;
1905
1906 case SVGA_REG_CMD_PREPEND_LOW:
1907 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCmdPrependLowWr);
1908 /* Not supported. */
1909 break;
1910
1911 case SVGA_REG_iCMD_PREPEND_HIGH:
1912 STAM_REL_COUNTER_INC(&pThis->svga.StatRegCmdPrependHighWr);
1913 /* Not supported. */
1914 break;
1915
1916 case SVGA_REG_FB_START:
1917 case SVGA_REG_MEM_START:
1918 case SVGA_REG_HOST_BITS_PER_PIXEL:
1919 case SVGA_REG_MAX_WIDTH:
1920 case SVGA_REG_MAX_HEIGHT:
1921 case SVGA_REG_VRAM_SIZE:
1922 case SVGA_REG_FB_SIZE:
1923 case SVGA_REG_CAPABILITIES:
1924 case SVGA_REG_MEM_SIZE:
1925 case SVGA_REG_SCRATCH_SIZE: /* Number of scratch registers */
1926 case SVGA_REG_MEM_REGS: /* Number of FIFO registers */
1927 case SVGA_REG_BYTES_PER_LINE:
1928 case SVGA_REG_FB_OFFSET:
1929 case SVGA_REG_RED_MASK:
1930 case SVGA_REG_GREEN_MASK:
1931 case SVGA_REG_BLUE_MASK:
1932 case SVGA_REG_GMRS_MAX_PAGES: /* Maximum number of 4KB pages for all GMRs */
1933 case SVGA_REG_MEMORY_SIZE: /* Total dedicated device memory excluding FIFO */
1934 case SVGA_REG_GMR_MAX_IDS:
1935 case SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH:
1936 case SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM:
1937 case SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB:
1938 case SVGA_REG_SCREENTARGET_MAX_WIDTH:
1939 case SVGA_REG_SCREENTARGET_MAX_HEIGHT:
1940 case SVGA_REG_MOB_MAX_SIZE:
1941 /* Read only - ignore. */
1942 Log(("Write to R/O register %x - val %x ignored\n", idxReg, u32));
1943 STAM_REL_COUNTER_INC(&pThis->svga.StatRegReadOnlyWr);
1944 break;
1945
1946 default:
1947 {
1948 uint32_t offReg;
1949 if ((offReg = idxReg - SVGA_SCRATCH_BASE) < pThis->svga.cScratchRegion)
1950 {
1951 RT_UNTRUSTED_VALIDATED_FENCE();
1952 pThis->svga.au32ScratchRegion[offReg] = u32;
1953 STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchWr);
1954 }
1955 else if ((offReg = idxReg - SVGA_PALETTE_BASE) < (uint32_t)SVGA_NUM_PALETTE_REGS)
1956 {
1957 /* Note! Using last_palette rather than palette here to preserve the VGA one.
1958 Btw, see rgb_to_pixel32. */
1959 STAM_REL_COUNTER_INC(&pThis->svga.StatRegPaletteWr);
1960 u32 &= 0xff;
1961 RT_UNTRUSTED_VALIDATED_FENCE();
1962 uint32_t uRgb = pThis->last_palette[offReg / 3];
1963 switch (offReg % 3)
1964 {
1965 case 0: uRgb = (uRgb & UINT32_C(0x0000ffff)) | (u32 << 16); break; /* red */
1966 case 1: uRgb = (uRgb & UINT32_C(0x00ff00ff)) | (u32 << 8); break; /* green */
1967 case 2: uRgb = (uRgb & UINT32_C(0x00ffff00)) | u32 ; break; /* blue */
1968 }
1969 pThis->last_palette[offReg / 3] = uRgb;
1970 }
1971 else
1972 {
1973#if !defined(IN_RING3) && defined(VBOX_STRICT)
1974 rc = VINF_IOM_R3_IOPORT_WRITE;
1975#else
1976 STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownWr);
1977 AssertMsgFailed(("reg=%#x u32=%#x\n", idxReg, u32));
1978#endif
1979 }
1980 break;
1981 }
1982 }
1983 return rc;
1984}
1985
1986/**
1987 * @callback_method_impl{FNIOMIOPORTNEWIN}
1988 */
1989DECLCALLBACK(VBOXSTRICTRC) vmsvgaIORead(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t *pu32, unsigned cb)
1990{
1991 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
1992 RT_NOREF_PV(pvUser);
1993
1994 /* Only dword accesses. */
1995 if (cb == 4)
1996 {
1997 switch (offPort)
1998 {
1999 case SVGA_INDEX_PORT:
2000 *pu32 = pThis->svga.u32IndexReg;
2001 break;
2002
2003 case SVGA_VALUE_PORT:
2004 return vmsvgaReadPort(pDevIns, pThis, pu32);
2005
2006 case SVGA_BIOS_PORT:
2007 Log(("Ignoring BIOS port read\n"));
2008 *pu32 = 0;
2009 break;
2010
2011 case SVGA_IRQSTATUS_PORT:
2012 LogFlow(("vmsvgaIORead: SVGA_IRQSTATUS_PORT %x\n", pThis->svga.u32IrqStatus));
2013 *pu32 = pThis->svga.u32IrqStatus;
2014 break;
2015
2016 default:
2017 ASSERT_GUEST_MSG_FAILED(("vmsvgaIORead: Unknown register %u was read from.\n", offPort));
2018 *pu32 = UINT32_MAX;
2019 break;
2020 }
2021 }
2022 else
2023 {
2024 Log(("Ignoring non-dword I/O port read at %x cb=%d\n", offPort, cb));
2025 *pu32 = UINT32_MAX;
2026 }
2027 return VINF_SUCCESS;
2028}
2029
2030/**
2031 * @callback_method_impl{FNIOMIOPORTNEWOUT}
2032 */
2033DECLCALLBACK(VBOXSTRICTRC) vmsvgaIOWrite(PPDMDEVINS pDevIns, void *pvUser, RTIOPORT offPort, uint32_t u32, unsigned cb)
2034{
2035 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
2036 PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
2037 RT_NOREF_PV(pvUser);
2038
2039 /* Only dword accesses. */
2040 if (cb == 4)
2041 switch (offPort)
2042 {
2043 case SVGA_INDEX_PORT:
2044 pThis->svga.u32IndexReg = u32;
2045 break;
2046
2047 case SVGA_VALUE_PORT:
2048 return vmsvgaWritePort(pDevIns, pThis, pThisCC, u32);
2049
2050 case SVGA_BIOS_PORT:
2051 Log(("Ignoring BIOS port write (val=%x)\n", u32));
2052 break;
2053
2054 case SVGA_IRQSTATUS_PORT:
2055 Log(("vmsvgaIOWrite SVGA_IRQSTATUS_PORT %x: status %x -> %x\n", u32, pThis->svga.u32IrqStatus, pThis->svga.u32IrqStatus & ~u32));
2056 ASMAtomicAndU32(&pThis->svga.u32IrqStatus, ~u32);
2057 /* Clear the irq in case all events have been cleared. */
2058 if (!(pThis->svga.u32IrqStatus & pThis->svga.u32IrqMask))
2059 {
2060 Log(("vmsvgaIOWrite SVGA_IRQSTATUS_PORT: clearing IRQ\n"));
2061 PDMDevHlpPCISetIrqNoWait(pDevIns, 0, 0);
2062 }
2063 break;
2064
2065 default:
2066 ASSERT_GUEST_MSG_FAILED(("vmsvgaIOWrite: Unknown register %u was written to, value %#x LB %u.\n", offPort, u32, cb));
2067 break;
2068 }
2069 else
2070 Log(("Ignoring non-dword write at %x val=%x cb=%d\n", offPort, u32, cb));
2071
2072 return VINF_SUCCESS;
2073}
2074
2075#ifdef IN_RING3
2076
2077# ifdef DEBUG_FIFO_ACCESS
2078/**
2079 * Handle FIFO memory access.
2080 * @returns VBox status code.
2081 * @param pVM VM handle.
2082 * @param pThis The shared VGA/VMSVGA instance data.
2083 * @param GCPhys The access physical address.
2084 * @param fWriteAccess Read or write access
2085 */
2086static int vmsvgaR3DebugFifoAccess(PVM pVM, PVGASTATE pThis, RTGCPHYS GCPhys, bool fWriteAccess)
2087{
2088 RT_NOREF(pVM);
2089 RTGCPHYS GCPhysOffset = GCPhys - pThis->svga.GCPhysFIFO;
2090 uint32_t *pFIFO = pThisCC->svga.pau32FIFO;
2091
2092 switch (GCPhysOffset >> 2)
2093 {
2094 case SVGA_FIFO_MIN:
2095 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_MIN = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2096 break;
2097 case SVGA_FIFO_MAX:
2098 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_MAX = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2099 break;
2100 case SVGA_FIFO_NEXT_CMD:
2101 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_NEXT_CMD = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2102 break;
2103 case SVGA_FIFO_STOP:
2104 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_STOP = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2105 break;
2106 case SVGA_FIFO_CAPABILITIES:
2107 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CAPABILITIES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2108 break;
2109 case SVGA_FIFO_FLAGS:
2110 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_FLAGS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2111 break;
2112 case SVGA_FIFO_FENCE:
2113 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_FENCE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2114 break;
2115 case SVGA_FIFO_3D_HWVERSION:
2116 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_HWVERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2117 break;
2118 case SVGA_FIFO_PITCHLOCK:
2119 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_PITCHLOCK = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2120 break;
2121 case SVGA_FIFO_CURSOR_ON:
2122 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_ON = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2123 break;
2124 case SVGA_FIFO_CURSOR_X:
2125 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_X = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2126 break;
2127 case SVGA_FIFO_CURSOR_Y:
2128 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_Y = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2129 break;
2130 case SVGA_FIFO_CURSOR_COUNT:
2131 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_COUNT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2132 break;
2133 case SVGA_FIFO_CURSOR_LAST_UPDATED:
2134 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_LAST_UPDATED = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2135 break;
2136 case SVGA_FIFO_RESERVED:
2137 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_RESERVED = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2138 break;
2139 case SVGA_FIFO_CURSOR_SCREEN_ID:
2140 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_CURSOR_SCREEN_ID = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2141 break;
2142 case SVGA_FIFO_DEAD:
2143 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_DEAD = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2144 break;
2145 case SVGA_FIFO_3D_HWVERSION_REVISED:
2146 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_HWVERSION_REVISED = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2147 break;
2148 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_3D:
2149 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_3D = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2150 break;
2151 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_LIGHTS:
2152 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_LIGHTS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2153 break;
2154 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURES:
2155 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2156 break;
2157 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_CLIP_PLANES:
2158 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_CLIP_PLANES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2159 break;
2160 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_VERTEX_SHADER_VERSION:
2161 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_VERTEX_SHADER_VERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2162 break;
2163 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_VERTEX_SHADER:
2164 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_VERTEX_SHADER = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2165 break;
2166 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION:
2167 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_FRAGMENT_SHADER_VERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2168 break;
2169 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_FRAGMENT_SHADER:
2170 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_FRAGMENT_SHADER = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2171 break;
2172 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_RENDER_TARGETS:
2173 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_RENDER_TARGETS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2174 break;
2175 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_S23E8_TEXTURES:
2176 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_S23E8_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2177 break;
2178 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_S10E5_TEXTURES:
2179 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_S10E5_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2180 break;
2181 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND:
2182 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_FIXED_VERTEXBLEND = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2183 break;
2184 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_D16_BUFFER_FORMAT:
2185 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_D16_BUFFER_FORMAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2186 break;
2187 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT:
2188 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_D24S8_BUFFER_FORMAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2189 break;
2190 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT:
2191 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_D24X8_BUFFER_FORMAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2192 break;
2193 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_QUERY_TYPES:
2194 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_QUERY_TYPES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2195 break;
2196 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING:
2197 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_TEXTURE_GRADIENT_SAMPLING = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2198 break;
2199 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_POINT_SIZE:
2200 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_POINT_SIZE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2201 break;
2202 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_SHADER_TEXTURES:
2203 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_SHADER_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2204 break;
2205 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH:
2206 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_WIDTH = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2207 break;
2208 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT:
2209 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_HEIGHT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2210 break;
2211 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VOLUME_EXTENT:
2212 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VOLUME_EXTENT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2213 break;
2214 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT:
2215 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_REPEAT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2216 break;
2217 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO:
2218 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_ASPECT_RATIO = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2219 break;
2220 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY:
2221 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_TEXTURE_ANISOTROPY = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2222 break;
2223 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT:
2224 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_PRIMITIVE_COUNT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2225 break;
2226 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_INDEX:
2227 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VERTEX_INDEX = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2228 break;
2229 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS:
2230 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VERTEX_SHADER_INSTRUCTIONS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2231 break;
2232 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS:
2233 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_INSTRUCTIONS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2234 break;
2235 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS:
2236 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEMPS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2237 break;
2238 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS:
2239 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_FRAGMENT_SHADER_TEMPS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2240 break;
2241 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_TEXTURE_OPS:
2242 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_TEXTURE_OPS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2243 break;
2244 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8:
2245 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_X8R8G8B8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2246 break;
2247 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8:
2248 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A8R8G8B8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2249 break;
2250 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10:
2251 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A2R10G10B10 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2252 break;
2253 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5:
2254 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_X1R5G5B5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2255 break;
2256 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5:
2257 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A1R5G5B5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2258 break;
2259 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4:
2260 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A4R4G4B4 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2261 break;
2262 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_R5G6B5:
2263 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_R5G6B5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2264 break;
2265 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16:
2266 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2267 break;
2268 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8:
2269 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8_ALPHA8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2270 break;
2271 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ALPHA8:
2272 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ALPHA8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2273 break;
2274 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8:
2275 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_LUMINANCE8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2276 break;
2277 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D16:
2278 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2279 break;
2280 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8:
2281 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2282 break;
2283 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8:
2284 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D24X8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2285 break;
2286 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT1:
2287 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT1 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2288 break;
2289 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT2:
2290 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT2 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2291 break;
2292 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT3:
2293 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT3 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2294 break;
2295 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT4:
2296 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT4 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2297 break;
2298 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_DXT5:
2299 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_DXT5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2300 break;
2301 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8:
2302 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_BUMPX8L8V8U8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2303 break;
2304 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10:
2305 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A2W10V10U10 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2306 break;
2307 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8:
2308 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_BUMPU8V8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2309 break;
2310 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8:
2311 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Q8W8V8U8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2312 break;
2313 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_CxV8U8:
2314 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_CxV8U8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2315 break;
2316 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_R_S10E5:
2317 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_R_S10E5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2318 break;
2319 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_R_S23E8:
2320 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_R_S23E8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2321 break;
2322 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5:
2323 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_RG_S10E5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2324 break;
2325 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8:
2326 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_RG_S23E8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2327 break;
2328 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5:
2329 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ARGB_S10E5 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2330 break;
2331 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8:
2332 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ARGB_S23E8 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2333 break;
2334 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES:
2335 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_VERTEX_SHADER_TEXTURES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2336 break;
2337 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS:
2338 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_SIMULTANEOUS_RENDER_TARGETS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2339 break;
2340 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_V16U16:
2341 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_V16U16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2342 break;
2343 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_G16R16:
2344 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_G16R16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2345 break;
2346 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16:
2347 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_A16B16G16R16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2348 break;
2349 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_UYVY:
2350 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_UYVY = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2351 break;
2352 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_YUY2:
2353 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_YUY2 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2354 break;
2355 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES:
2356 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MULTISAMPLE_NONMASKABLESAMPLES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2357 break;
2358 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES:
2359 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MULTISAMPLE_MASKABLESAMPLES = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2360 break;
2361 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_ALPHATOCOVERAGE:
2362 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_ALPHATOCOVERAGE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2363 break;
2364 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SUPERSAMPLE:
2365 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SUPERSAMPLE = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2366 break;
2367 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_AUTOGENMIPMAPS:
2368 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_AUTOGENMIPMAPS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2369 break;
2370 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_NV12:
2371 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_NV12 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2372 break;
2373 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_AYUV:
2374 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_AYUV = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2375 break;
2376 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_CONTEXT_IDS:
2377 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_CONTEXT_IDS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2378 break;
2379 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_MAX_SURFACE_IDS:
2380 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_MAX_SURFACE_IDS = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2381 break;
2382 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_DF16:
2383 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_DF16 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2384 break;
2385 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_DF24:
2386 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_DF24 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2387 break;
2388 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT:
2389 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_Z_D24S8_INT = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2390 break;
2391 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ATI1:
2392 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ATI1 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2393 break;
2394 case SVGA_FIFO_3D_CAPS + SVGA3D_DEVCAP_SURFACEFMT_ATI2:
2395 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS SVGA3D_DEVCAP_SURFACEFMT_ATI2 = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2396 break;
2397 case SVGA_FIFO_3D_CAPS_LAST:
2398 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_3D_CAPS_LAST = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2399 break;
2400 case SVGA_FIFO_GUEST_3D_HWVERSION:
2401 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_GUEST_3D_HWVERSION = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2402 break;
2403 case SVGA_FIFO_FENCE_GOAL:
2404 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_FENCE_GOAL = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2405 break;
2406 case SVGA_FIFO_BUSY:
2407 Log(("vmsvgaFIFOAccess [0x%x]: %s SVGA_FIFO_BUSY = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", pFIFO[GCPhysOffset >> 2]));
2408 break;
2409 default:
2410 Log(("vmsvgaFIFOAccess [0x%x]: %s access at offset %x = %x\n", GCPhysOffset >> 2, (fWriteAccess) ? "WRITE" : "READ", GCPhysOffset, pFIFO[GCPhysOffset >> 2]));
2411 break;
2412 }
2413
2414 return VINF_EM_RAW_EMULATE_INSTR;
2415}
2416# endif /* DEBUG_FIFO_ACCESS */
2417
2418# if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
2419/**
2420 * HC access handler for the FIFO.
2421 *
2422 * @returns VINF_SUCCESS if the handler have carried out the operation.
2423 * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
2424 * @param pVM VM Handle.
2425 * @param pVCpu The cross context CPU structure for the calling EMT.
2426 * @param GCPhys The physical address the guest is writing to.
2427 * @param pvPhys The HC mapping of that address.
2428 * @param pvBuf What the guest is reading/writing.
2429 * @param cbBuf How much it's reading/writing.
2430 * @param enmAccessType The access type.
2431 * @param enmOrigin Who is making the access.
2432 * @param pvUser User argument.
2433 */
2434static DECLCALLBACK(VBOXSTRICTRC)
2435vmsvgaR3FifoAccessHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf,
2436 PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser)
2437{
2438 NOREF(pVCpu); NOREF(pvPhys); NOREF(pvBuf); NOREF(cbBuf); NOREF(enmOrigin); NOREF(enmAccessType); NOREF(GCPhys);
2439 PVGASTATE pThis = (PVGASTATE)pvUser;
2440 AssertPtr(pThis);
2441
2442# ifdef VMSVGA_USE_FIFO_ACCESS_HANDLER
2443 /*
2444 * Wake up the FIFO thread as it might have work to do now.
2445 */
2446 int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
2447 AssertLogRelRC(rc);
2448# endif
2449
2450# ifdef DEBUG_FIFO_ACCESS
2451 /*
2452 * When in debug-fifo-access mode, we do not disable the access handler,
2453 * but leave it on as we wish to catch all access.
2454 */
2455 Assert(GCPhys >= pThis->svga.GCPhysFIFO);
2456 rc = vmsvgaR3DebugFifoAccess(pVM, pThis, GCPhys, enmAccessType == PGMACCESSTYPE_WRITE);
2457# elif defined(VMSVGA_USE_FIFO_ACCESS_HANDLER)
2458 /*
2459 * Temporarily disable the access handler now that we've kicked the FIFO thread.
2460 */
2461 STAM_REL_COUNTER_INC(&pThisCC->svga.pSvgaR3State->StatFifoAccessHandler);
2462 rc = PGMHandlerPhysicalPageTempOff(pVM, pThis->svga.GCPhysFIFO, pThis->svga.GCPhysFIFO);
2463# endif
2464 if (RT_SUCCESS(rc))
2465 return VINF_PGM_HANDLER_DO_DEFAULT;
2466 AssertMsg(rc <= VINF_SUCCESS, ("rc=%Rrc\n", rc));
2467 return rc;
2468}
2469# endif /* VMSVGA_USE_FIFO_ACCESS_HANDLER || DEBUG_FIFO_ACCESS */
2470
2471#endif /* IN_RING3 */
2472
2473#ifdef DEBUG_GMR_ACCESS
2474# ifdef IN_RING3
2475
2476/**
2477 * HC access handler for GMRs.
2478 *
2479 * @returns VINF_SUCCESS if the handler have carried out the operation.
2480 * @returns VINF_PGM_HANDLER_DO_DEFAULT if the caller should carry out the access operation.
2481 * @param pVM VM Handle.
2482 * @param pVCpu The cross context CPU structure for the calling EMT.
2483 * @param GCPhys The physical address the guest is writing to.
2484 * @param pvPhys The HC mapping of that address.
2485 * @param pvBuf What the guest is reading/writing.
2486 * @param cbBuf How much it's reading/writing.
2487 * @param enmAccessType The access type.
2488 * @param enmOrigin Who is making the access.
2489 * @param pvUser User argument.
2490 */
2491static DECLCALLBACK(VBOXSTRICTRC)
2492vmsvgaR3GmrAccessHandler(PVM pVM, PVMCPU pVCpu, RTGCPHYS GCPhys, void *pvPhys, void *pvBuf, size_t cbBuf,
2493 PGMACCESSTYPE enmAccessType, PGMACCESSORIGIN enmOrigin, void *pvUser)
2494{
2495 PVGASTATE pThis = (PVGASTATE)pvUser;
2496 Assert(pThis);
2497 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
2498 NOREF(pVCpu); NOREF(pvPhys); NOREF(pvBuf); NOREF(cbBuf); NOREF(enmAccessType); NOREF(enmOrigin);
2499
2500 Log(("vmsvgaR3GmrAccessHandler: GMR access to page %RGp\n", GCPhys));
2501
2502 for (uint32_t i = 0; i < pThis->svga.cGMR; ++i)
2503 {
2504 PGMR pGMR = &pSVGAState->paGMR[i];
2505
2506 if (pGMR->numDescriptors)
2507 {
2508 for (uint32_t j = 0; j < pGMR->numDescriptors; j++)
2509 {
2510 if ( GCPhys >= pGMR->paDesc[j].GCPhys
2511 && GCPhys < pGMR->paDesc[j].GCPhys + pGMR->paDesc[j].numPages * PAGE_SIZE)
2512 {
2513 /*
2514 * Turn off the write handler for this particular page and make it R/W.
2515 * Then return telling the caller to restart the guest instruction.
2516 */
2517 int rc = PGMHandlerPhysicalPageTempOff(pVM, pGMR->paDesc[j].GCPhys, GCPhys);
2518 AssertRC(rc);
2519 return VINF_PGM_HANDLER_DO_DEFAULT;
2520 }
2521 }
2522 }
2523 }
2524
2525 return VINF_PGM_HANDLER_DO_DEFAULT;
2526}
2527
2528/** Callback handler for VMR3ReqCallWaitU */
2529static DECLCALLBACK(int) vmsvgaR3RegisterGmr(PPDMDEVINS pDevIns, uint32_t gmrId)
2530{
2531 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
2532 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
2533 PGMR pGMR = &pSVGAState->paGMR[gmrId];
2534 int rc;
2535
2536 for (uint32_t i = 0; i < pGMR->numDescriptors; i++)
2537 {
2538 rc = PGMHandlerPhysicalRegister(PDMDevHlpGetVM(pDevIns),
2539 pGMR->paDesc[i].GCPhys, pGMR->paDesc[i].GCPhys + pGMR->paDesc[i].numPages * PAGE_SIZE - 1,
2540 pThis->svga.hGmrAccessHandlerType, pThis, NIL_RTR0PTR, NIL_RTRCPTR, "VMSVGA GMR");
2541 AssertRC(rc);
2542 }
2543 return VINF_SUCCESS;
2544}
2545
2546/** Callback handler for VMR3ReqCallWaitU */
2547static DECLCALLBACK(int) vmsvgaR3DeregisterGmr(PPDMDEVINS pDevIns, uint32_t gmrId)
2548{
2549 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
2550 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
2551 PGMR pGMR = &pSVGAState->paGMR[gmrId];
2552
2553 for (uint32_t i = 0; i < pGMR->numDescriptors; i++)
2554 {
2555 int rc = PGMHandlerPhysicalDeregister(PDMDevHlpGetVM(pDevIns), pGMR->paDesc[i].GCPhys);
2556 AssertRC(rc);
2557 }
2558 return VINF_SUCCESS;
2559}
2560
2561/** Callback handler for VMR3ReqCallWaitU */
2562static DECLCALLBACK(int) vmsvgaR3ResetGmrHandlers(PVGASTATE pThis)
2563{
2564 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
2565
2566 for (uint32_t i = 0; i < pThis->svga.cGMR; ++i)
2567 {
2568 PGMR pGMR = &pSVGAState->paGMR[i];
2569
2570 if (pGMR->numDescriptors)
2571 {
2572 for (uint32_t j = 0; j < pGMR->numDescriptors; j++)
2573 {
2574 int rc = PGMHandlerPhysicalReset(PDMDevHlpGetVM(pDevIns), pGMR->paDesc[j].GCPhys);
2575 AssertRC(rc);
2576 }
2577 }
2578 }
2579 return VINF_SUCCESS;
2580}
2581
2582# endif /* IN_RING3 */
2583#endif /* DEBUG_GMR_ACCESS */
2584
2585/* -=-=-=-=-=- Ring 3 -=-=-=-=-=- */
2586
2587#ifdef IN_RING3
2588
2589
2590/*
2591 *
2592 * Command buffer submission.
2593 *
2594 * Guest submits a buffer by writing to SVGA_REG_COMMAND_LOW register.
2595 *
2596 * EMT thread appends a command buffer to the context queue (VMSVGACMDBUFCTX::listSubmitted)
2597 * and wakes up the FIFO thread.
2598 *
2599 * FIFO thread fetches the command buffer from the queue, processes the commands and writes
2600 * the buffer header back to the guest memory.
2601 *
2602 * If buffers are preempted, then the EMT thread removes all buffers from the context queue.
2603 *
2604 */
2605
2606
2607/** Update a command buffer header 'status' and 'errorOffset' fields in the guest memory.
2608 *
2609 * @param pDevIns The device instance.
2610 * @param GCPhysCB Guest physical address of the command buffer header.
2611 * @param status Command buffer status (SVGA_CB_STATUS_*).
2612 * @param errorOffset Offset to the first byte of the failing command for SVGA_CB_STATUS_COMMAND_ERROR.
2613 * errorOffset is ignored if the status is not SVGA_CB_STATUS_COMMAND_ERROR.
2614 * @thread FIFO or EMT.
2615 */
2616static void vmsvgaR3CmdBufWriteStatus(PPDMDEVINS pDevIns, RTGCPHYS GCPhysCB, SVGACBStatus status, uint32_t errorOffset)
2617{
2618 SVGACBHeader hdr;
2619 hdr.status = status;
2620 hdr.errorOffset = errorOffset;
2621 AssertCompile( RT_OFFSETOF(SVGACBHeader, status) == 0
2622 && RT_OFFSETOF(SVGACBHeader, errorOffset) == 4
2623 && RT_OFFSETOF(SVGACBHeader, id) == 8);
2624 size_t const cbWrite = status == SVGA_CB_STATUS_COMMAND_ERROR
2625 ? RT_UOFFSET_AFTER(SVGACBHeader, errorOffset) /* Both 'status' and 'errorOffset' fields. */
2626 : RT_UOFFSET_AFTER(SVGACBHeader, status); /* Only 'status' field. */
2627 PDMDevHlpPCIPhysWrite(pDevIns, GCPhysCB, &hdr, cbWrite);
2628}
2629
2630
2631/** Raise an IRQ.
2632 *
2633 * @param pDevIns The device instance.
2634 * @param pThis The shared VGA/VMSVGA state.
2635 * @param u32IrqStatus SVGA_IRQFLAG_* bits.
2636 * @thread FIFO or EMT.
2637 */
2638static void vmsvgaR3CmdBufRaiseIRQ(PPDMDEVINS pDevIns, PVGASTATE pThis, uint32_t u32IrqStatus)
2639{
2640 int rc = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_IGNORED);
2641 AssertRC(rc);
2642
2643 if (pThis->svga.u32IrqMask & u32IrqStatus)
2644 {
2645 LogFunc(("Trigger interrupt with status %#x\n", u32IrqStatus));
2646 ASMAtomicOrU32(&pThis->svga.u32IrqStatus, u32IrqStatus);
2647 PDMDevHlpPCISetIrq(pDevIns, 0, 1);
2648 }
2649
2650 PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect);
2651}
2652
2653
2654/** Allocate a command buffer structure.
2655 *
2656 * @param pCmdBufCtx The command buffer context which must allocate the buffer.
2657 * @return Pointer to the allocated command buffer structure.
2658 */
2659static PVMSVGACMDBUF vmsvgaR3CmdBufAlloc(PVMSVGACMDBUFCTX pCmdBufCtx)
2660{
2661 if (!pCmdBufCtx)
2662 return NULL;
2663
2664 PVMSVGACMDBUF pCmdBuf = (PVMSVGACMDBUF)RTMemAllocZ(sizeof(*pCmdBuf));
2665 if (pCmdBuf)
2666 {
2667 // RT_ZERO(pCmdBuf->nodeBuffer);
2668 pCmdBuf->pCmdBufCtx = pCmdBufCtx;
2669 // pCmdBuf->GCPhysCB = 0;
2670 // RT_ZERO(pCmdBuf->hdr);
2671 // pCmdBuf->pvCommands = NULL;
2672 }
2673
2674 return pCmdBuf;
2675}
2676
2677
2678/** Free a command buffer structure.
2679 *
2680 * @param pCmdBuf The command buffer pointer.
2681 */
2682static void vmsvgaR3CmdBufFree(PVMSVGACMDBUF pCmdBuf)
2683{
2684 if (pCmdBuf)
2685 RTMemFree(pCmdBuf->pvCommands);
2686 RTMemFree(pCmdBuf);
2687}
2688
2689
2690/** Initialize a command buffer context.
2691 *
2692 * @param pCmdBufCtx The command buffer context.
2693 */
2694static void vmsvgaR3CmdBufCtxInit(PVMSVGACMDBUFCTX pCmdBufCtx)
2695{
2696 RTListInit(&pCmdBufCtx->listSubmitted);
2697 pCmdBufCtx->cSubmitted = 0;
2698}
2699
2700
2701/** Destroy a command buffer context.
2702 *
2703 * @param pCmdBufCtx The command buffer context pointer.
2704 */
2705static void vmsvgaR3CmdBufCtxTerm(PVMSVGACMDBUFCTX pCmdBufCtx)
2706{
2707 if (!pCmdBufCtx)
2708 return;
2709
2710 if (pCmdBufCtx->listSubmitted.pNext)
2711 {
2712 /* If the list has been initialized. */
2713 PVMSVGACMDBUF pIter, pNext;
2714 RTListForEachSafe(&pCmdBufCtx->listSubmitted, pIter, pNext, VMSVGACMDBUF, nodeBuffer)
2715 {
2716 RTListNodeRemove(&pIter->nodeBuffer);
2717 --pCmdBufCtx->cSubmitted;
2718 vmsvgaR3CmdBufFree(pIter);
2719 }
2720 }
2721 Assert(pCmdBufCtx->cSubmitted == 0);
2722 pCmdBufCtx->cSubmitted = 0;
2723}
2724
2725
2726/** Handles SVGA_DC_CMD_START_STOP_CONTEXT command.
2727 *
2728 * @param pSvgaR3State VMSVGA R3 state.
2729 * @param pCmd The command data.
2730 * @return SVGACBStatus code.
2731 * @thread EMT
2732 */
2733static SVGACBStatus vmsvgaR3CmdBufDCStartStop(PVMSVGAR3STATE pSvgaR3State, SVGADCCmdStartStop const *pCmd)
2734{
2735 /* Create or destroy a regular command buffer context. */
2736 if (pCmd->context >= RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs))
2737 return SVGA_CB_STATUS_COMMAND_ERROR;
2738 RT_UNTRUSTED_VALIDATED_FENCE();
2739
2740 SVGACBStatus CBStatus = SVGA_CB_STATUS_COMPLETED;
2741
2742 int rc = RTCritSectEnter(&pSvgaR3State->CritSectCmdBuf);
2743 AssertRC(rc);
2744 if (pCmd->enable)
2745 {
2746 pSvgaR3State->apCmdBufCtxs[pCmd->context] = (PVMSVGACMDBUFCTX)RTMemAlloc(sizeof(VMSVGACMDBUFCTX));
2747 if (pSvgaR3State->apCmdBufCtxs[pCmd->context])
2748 vmsvgaR3CmdBufCtxInit(pSvgaR3State->apCmdBufCtxs[pCmd->context]);
2749 else
2750 CBStatus = SVGA_CB_STATUS_QUEUE_FULL;
2751 }
2752 else
2753 {
2754 vmsvgaR3CmdBufCtxTerm(pSvgaR3State->apCmdBufCtxs[pCmd->context]);
2755 pSvgaR3State->apCmdBufCtxs[pCmd->context] = NULL;
2756 }
2757 RTCritSectLeave(&pSvgaR3State->CritSectCmdBuf);
2758
2759 return CBStatus;
2760}
2761
2762
2763/** Handles SVGA_DC_CMD_PREEMPT command.
2764 *
2765 * @param pDevIns The device instance.
2766 * @param pSvgaR3State VMSVGA R3 state.
2767 * @param pCmd The command data.
2768 * @return SVGACBStatus code.
2769 * @thread EMT
2770 */
2771static SVGACBStatus vmsvgaR3CmdBufDCPreempt(PPDMDEVINS pDevIns, PVMSVGAR3STATE pSvgaR3State, SVGADCCmdPreempt const *pCmd)
2772{
2773 /* Remove buffers from the processing queue of the specified context. */
2774 if (pCmd->context >= RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs))
2775 return SVGA_CB_STATUS_COMMAND_ERROR;
2776 RT_UNTRUSTED_VALIDATED_FENCE();
2777
2778 PVMSVGACMDBUFCTX const pCmdBufCtx = pSvgaR3State->apCmdBufCtxs[pCmd->context];
2779 RTLISTANCHOR listPreempted;
2780
2781 int rc = RTCritSectEnter(&pSvgaR3State->CritSectCmdBuf);
2782 AssertRC(rc);
2783 if (pCmd->ignoreIDZero)
2784 {
2785 RTListInit(&listPreempted);
2786
2787 PVMSVGACMDBUF pIter, pNext;
2788 RTListForEachSafe(&pCmdBufCtx->listSubmitted, pIter, pNext, VMSVGACMDBUF, nodeBuffer)
2789 {
2790 if (pIter->hdr.id == 0)
2791 continue;
2792
2793 RTListNodeRemove(&pIter->nodeBuffer);
2794 --pCmdBufCtx->cSubmitted;
2795 RTListAppend(&listPreempted, &pIter->nodeBuffer);
2796 }
2797 }
2798 else
2799 {
2800 RTListMove(&listPreempted, &pCmdBufCtx->listSubmitted);
2801 }
2802 RTCritSectLeave(&pSvgaR3State->CritSectCmdBuf);
2803
2804 PVMSVGACMDBUF pIter, pNext;
2805 RTListForEachSafe(&listPreempted, pIter, pNext, VMSVGACMDBUF, nodeBuffer)
2806 {
2807 RTListNodeRemove(&pIter->nodeBuffer);
2808 vmsvgaR3CmdBufWriteStatus(pDevIns, pIter->GCPhysCB, SVGA_CB_STATUS_PREEMPTED, 0);
2809 vmsvgaR3CmdBufFree(pIter);
2810 }
2811
2812 return SVGA_CB_STATUS_COMPLETED;
2813}
2814
2815
2816/** @def VMSVGA_INC_CMD_SIZE_BREAK
2817 * Increments the size of the command cbCmd by a_cbMore.
2818 * Checks that the command buffer has at least cbCmd bytes. Will break out of the switch if it doesn't.
2819 * Used by vmsvgaR3CmdBufProcessDC and vmsvgaR3CmdBufProcessCommands.
2820 */
2821#define VMSVGA_INC_CMD_SIZE_BREAK(a_cbMore) \
2822 if (1) { \
2823 cbCmd += (a_cbMore); \
2824 ASSERT_GUEST_MSG_STMT_BREAK(cbRemain >= cbCmd, ("size=%#x remain=%#zx\n", cbCmd, (size_t)cbRemain), CBstatus = SVGA_CB_STATUS_COMMAND_ERROR); \
2825 RT_UNTRUSTED_VALIDATED_FENCE(); \
2826 } else do {} while (0)
2827
2828
2829/** Processes Device Context command buffer.
2830 *
2831 * @param pDevIns The device instance.
2832 * @param pSvgaR3State VMSVGA R3 state.
2833 * @param pvCommands Pointer to the command buffer.
2834 * @param cbCommands Size of the command buffer.
2835 * @param poffNextCmd Where to store the offset of the first unprocessed command.
2836 * @return SVGACBStatus code.
2837 * @thread EMT
2838 */
2839static SVGACBStatus vmsvgaR3CmdBufProcessDC(PPDMDEVINS pDevIns, PVMSVGAR3STATE pSvgaR3State, void const *pvCommands, uint32_t cbCommands, uint32_t *poffNextCmd)
2840{
2841 SVGACBStatus CBstatus = SVGA_CB_STATUS_COMPLETED;
2842
2843 uint8_t const *pu8Cmd = (uint8_t *)pvCommands;
2844 uint32_t cbRemain = cbCommands;
2845 while (cbRemain)
2846 {
2847 /* Command identifier is a 32 bit value. */
2848 if (cbRemain < sizeof(uint32_t))
2849 {
2850 CBstatus = SVGA_CB_STATUS_COMMAND_ERROR;
2851 break;
2852 }
2853
2854 /* Fetch the command id. */
2855 uint32_t const cmdId = *(uint32_t *)pu8Cmd;
2856 uint32_t cbCmd = sizeof(uint32_t);
2857 switch (cmdId)
2858 {
2859 case SVGA_DC_CMD_NOP:
2860 {
2861 /* NOP */
2862 break;
2863 }
2864
2865 case SVGA_DC_CMD_START_STOP_CONTEXT:
2866 {
2867 SVGADCCmdStartStop *pCmd = (SVGADCCmdStartStop *)&pu8Cmd[cbCmd];
2868 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
2869 CBstatus = vmsvgaR3CmdBufDCStartStop(pSvgaR3State, pCmd);
2870 break;
2871 }
2872
2873 case SVGA_DC_CMD_PREEMPT:
2874 {
2875 SVGADCCmdPreempt *pCmd = (SVGADCCmdPreempt *)&pu8Cmd[cbCmd];
2876 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
2877 CBstatus = vmsvgaR3CmdBufDCPreempt(pDevIns, pSvgaR3State, pCmd);
2878 break;
2879 }
2880
2881 default:
2882 {
2883 /* Unsupported command. */
2884 CBstatus = SVGA_CB_STATUS_COMMAND_ERROR;
2885 break;
2886 }
2887 }
2888
2889 if (CBstatus != SVGA_CB_STATUS_COMPLETED)
2890 break;
2891
2892 pu8Cmd += cbCmd;
2893 cbRemain -= cbCmd;
2894 }
2895
2896 Assert(cbRemain <= cbCommands);
2897 *poffNextCmd = cbCommands - cbRemain;
2898 return CBstatus;
2899}
2900
2901
2902/** Submits a device context command buffer for synchronous processing.
2903 *
2904 * @param pDevIns The device instance.
2905 * @param pThisCC The VGA/VMSVGA state for the current context.
2906 * @param ppCmdBuf Pointer to the command buffer pointer.
2907 * The function can set the command buffer pointer to NULL to prevent deallocation by the caller.
2908 * @param poffNextCmd Where to store the offset of the first unprocessed command.
2909 * @return SVGACBStatus code.
2910 * @thread EMT
2911 */
2912static SVGACBStatus vmsvgaR3CmdBufSubmitDC(PPDMDEVINS pDevIns, PVGASTATECC pThisCC, PVMSVGACMDBUF *ppCmdBuf, uint32_t *poffNextCmd)
2913{
2914 /* Synchronously process the device context commands. */
2915 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
2916 return vmsvgaR3CmdBufProcessDC(pDevIns, pSvgaR3State, (*ppCmdBuf)->pvCommands, (*ppCmdBuf)->hdr.length, poffNextCmd);
2917}
2918
2919/** Submits a command buffer for asynchronous processing by the FIFO thread.
2920 *
2921 * @param pDevIns The device instance.
2922 * @param pThis The shared VGA/VMSVGA state.
2923 * @param pThisCC The VGA/VMSVGA state for the current context.
2924 * @param ppCmdBuf Pointer to the command buffer pointer.
2925 * The function can set the command buffer pointer to NULL to prevent deallocation by the caller.
2926 * @return SVGACBStatus code.
2927 * @thread EMT
2928 */
2929static SVGACBStatus vmsvgaR3CmdBufSubmit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PVMSVGACMDBUF *ppCmdBuf)
2930{
2931 /* Command buffer submission. */
2932 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
2933
2934 SVGACBStatus CBstatus = SVGA_CB_STATUS_NONE;
2935
2936 PVMSVGACMDBUF const pCmdBuf = *ppCmdBuf;
2937 PVMSVGACMDBUFCTX const pCmdBufCtx = pCmdBuf->pCmdBufCtx;
2938
2939 int rc = RTCritSectEnter(&pSvgaR3State->CritSectCmdBuf);
2940 AssertRC(rc);
2941
2942 if (RT_LIKELY(pCmdBufCtx->cSubmitted < SVGA_CB_MAX_QUEUED_PER_CONTEXT))
2943 {
2944 RTListAppend(&pCmdBufCtx->listSubmitted, &pCmdBuf->nodeBuffer);
2945 ++pCmdBufCtx->cSubmitted;
2946 *ppCmdBuf = NULL; /* Consume the buffer. */
2947 ASMAtomicWriteU32(&pThisCC->svga.pSvgaR3State->fCmdBuf, 1);
2948 }
2949 else
2950 CBstatus = SVGA_CB_STATUS_QUEUE_FULL;
2951
2952 RTCritSectLeave(&pSvgaR3State->CritSectCmdBuf);
2953
2954 /* Inform the FIFO thread. */
2955 if (*ppCmdBuf == NULL)
2956 PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
2957
2958 return CBstatus;
2959}
2960
2961
2962/** SVGA_REG_COMMAND_LOW write handler.
2963 * Submits a command buffer to the FIFO thread or processes a device context command.
2964 *
2965 * @param pDevIns The device instance.
2966 * @param pThis The shared VGA/VMSVGA state.
2967 * @param pThisCC The VGA/VMSVGA state for the current context.
2968 * @param GCPhysCB Guest physical address of the command buffer header.
2969 * @param CBCtx Context the command buffer is submitted to.
2970 * @thread EMT
2971 */
2972static void vmsvgaR3CmdBufSubmit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, RTGCPHYS GCPhysCB, SVGACBContext CBCtx)
2973{
2974 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
2975
2976 SVGACBStatus CBstatus = SVGA_CB_STATUS_NONE;
2977 uint32_t offNextCmd = 0;
2978 uint32_t fIRQ = 0;
2979
2980 /* Get the context if the device has the capability. */
2981 PVMSVGACMDBUFCTX pCmdBufCtx = NULL;
2982 if (pThis->svga.u32DeviceCaps & SVGA_CAP_COMMAND_BUFFERS)
2983 {
2984 if (RT_LIKELY(CBCtx < RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs)))
2985 pCmdBufCtx = pSvgaR3State->apCmdBufCtxs[CBCtx];
2986 else if (CBCtx == SVGA_CB_CONTEXT_DEVICE)
2987 pCmdBufCtx = &pSvgaR3State->CmdBufCtxDC;
2988 RT_UNTRUSTED_VALIDATED_FENCE();
2989 }
2990
2991 /* Allocate a new command buffer. */
2992 PVMSVGACMDBUF pCmdBuf = vmsvgaR3CmdBufAlloc(pCmdBufCtx);
2993 if (RT_LIKELY(pCmdBuf))
2994 {
2995 pCmdBuf->GCPhysCB = GCPhysCB;
2996
2997 int rc = PDMDevHlpPCIPhysRead(pDevIns, GCPhysCB, &pCmdBuf->hdr, sizeof(pCmdBuf->hdr));
2998 if (RT_SUCCESS(rc))
2999 {
3000 /* Verify the command buffer header. */
3001 if (RT_LIKELY( pCmdBuf->hdr.status == SVGA_CB_STATUS_NONE
3002 && (pCmdBuf->hdr.flags & ~(SVGA_CB_FLAG_NO_IRQ)) == 0 /* No unexpected flags. */
3003 && pCmdBuf->hdr.length <= SVGA_CB_MAX_SIZE))
3004 {
3005 RT_UNTRUSTED_VALIDATED_FENCE();
3006
3007 /* Read the command buffer content. */
3008 pCmdBuf->pvCommands = RTMemAlloc(pCmdBuf->hdr.length);
3009 if (pCmdBuf->pvCommands)
3010 {
3011 RTGCPHYS const GCPhysCmd = (RTGCPHYS)pCmdBuf->hdr.ptr.pa;
3012 rc = PDMDevHlpPCIPhysRead(pDevIns, GCPhysCmd, pCmdBuf->pvCommands, pCmdBuf->hdr.length);
3013 if (RT_SUCCESS(rc))
3014 {
3015 /* Submit the buffer. Device context buffers will be processed synchronously. */
3016 if (RT_LIKELY(CBCtx < RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs)))
3017 /* This usually processes the CB async and sets pCmbBuf to NULL. */
3018 CBstatus = vmsvgaR3CmdBufSubmit(pDevIns, pThis, pThisCC, &pCmdBuf);
3019 else
3020 CBstatus = vmsvgaR3CmdBufSubmitDC(pDevIns, pThisCC, &pCmdBuf, &offNextCmd);
3021 }
3022 else
3023 {
3024 ASSERT_GUEST_MSG_FAILED(("Failed to read commands at %RGp\n", GCPhysCmd));
3025 CBstatus = SVGA_CB_STATUS_CB_HEADER_ERROR;
3026 fIRQ = SVGA_IRQFLAG_ERROR | SVGA_IRQFLAG_COMMAND_BUFFER;
3027 }
3028 }
3029 else
3030 {
3031 /* No memory for commands. */
3032 CBstatus = SVGA_CB_STATUS_QUEUE_FULL;
3033 }
3034 }
3035 else
3036 {
3037 ASSERT_GUEST_MSG_FAILED(("Invalid buffer header\n"));
3038 CBstatus = SVGA_CB_STATUS_CB_HEADER_ERROR;
3039 fIRQ = SVGA_IRQFLAG_ERROR | SVGA_IRQFLAG_COMMAND_BUFFER;
3040 }
3041 }
3042 else
3043 {
3044 LogFunc(("Failed to read buffer header at %RGp\n", GCPhysCB));
3045 ASSERT_GUEST_FAILED();
3046 /* Do not attempt to write the status. */
3047 }
3048
3049 /* Free the buffer if pfnCmdBufSubmit did not consume it. */
3050 vmsvgaR3CmdBufFree(pCmdBuf);
3051 }
3052 else
3053 {
3054 LogFunc(("Can't allocate buffer for context id %#x\n", CBCtx));
3055 ASSERT_GUEST_FAILED();
3056 CBstatus = SVGA_CB_STATUS_QUEUE_FULL;
3057 }
3058
3059 if (CBstatus != SVGA_CB_STATUS_NONE)
3060 {
3061 LogFunc(("Write status %#x, offNextCmd %#x (of %#x), fIRQ %#x\n", CBstatus, offNextCmd, pCmdBuf->hdr.length, fIRQ));
3062 vmsvgaR3CmdBufWriteStatus(pDevIns, GCPhysCB, CBstatus, offNextCmd);
3063 if (fIRQ)
3064 vmsvgaR3CmdBufRaiseIRQ(pDevIns, pThis, fIRQ);
3065 }
3066}
3067
3068
3069/** Checks if there are some buffers to be processed.
3070 *
3071 * @param pThisCC The VGA/VMSVGA state for the current context.
3072 * @return true if buffers must be processed.
3073 * @thread FIFO
3074 */
3075static bool vmsvgaR3CmdBufHasWork(PVGASTATECC pThisCC)
3076{
3077 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
3078 return RT_BOOL(ASMAtomicReadU32(&pSvgaR3State->fCmdBuf));
3079}
3080
3081
3082/** Processes a command buffer.
3083 *
3084 * @param pDevIns The device instance.
3085 * @param pThis The shared VGA/VMSVGA state.
3086 * @param pThisCC The VGA/VMSVGA state for the current context.
3087 * @param pvCommands Pointer to the command buffer.
3088 * @param cbCommands Size of the command buffer.
3089 * @param poffNextCmd Where to store the offset of the first unprocessed command.
3090 * @param pu32IrqStatus Where to store SVGA_IRQFLAG_ if the IRQ is generated by the last command in the buffer.
3091 * @return SVGACBStatus code.
3092 * @thread FIFO
3093 */
3094static SVGACBStatus vmsvgaR3CmdBufProcessCommands(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, void const *pvCommands, uint32_t cbCommands, uint32_t *poffNextCmd, uint32_t *pu32IrqStatus)
3095{
3096 SVGACBStatus CBstatus = SVGA_CB_STATUS_COMPLETED;
3097 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
3098
3099 uint32_t RT_UNTRUSTED_VOLATILE_GUEST * const pFIFO = pThisCC->svga.pau32FIFO;
3100
3101 uint8_t const *pu8Cmd = (uint8_t *)pvCommands;
3102 uint32_t cbRemain = cbCommands;
3103 while (cbRemain)
3104 {
3105 /* Command identifier is a 32 bit value. */
3106 if (cbRemain < sizeof(uint32_t))
3107 {
3108 CBstatus = SVGA_CB_STATUS_COMMAND_ERROR;
3109 break;
3110 }
3111
3112 /* Fetch the command id.
3113 * 'cmdId' is actually a SVGAFifoCmdId. It is treated as uint32_t in order to avoid a compiler
3114 * warning. Because we support some obsolete and deprecated commands, which are not included in
3115 * the SVGAFifoCmdId enum in the VMSVGA headers anymore.
3116 */
3117 uint32_t const cmdId = *(uint32_t *)pu8Cmd;
3118 uint32_t cbCmd = sizeof(uint32_t);
3119
3120 LogFlowFunc(("%s %d\n", vmsvgaR3FifoCmdToString(cmdId), cmdId));
3121
3122 /* At the end of the switch cbCmd is equal to the total length of the command including the cmdId.
3123 * I.e. pu8Cmd + cbCmd must point to the next command.
3124 * However if CBstatus is set to anything but SVGA_CB_STATUS_COMPLETED in the switch, then
3125 * the cbCmd value is ignored (and pu8Cmd still points to the failed command).
3126 */
3127 /** @todo This code is very similar to the FIFO loop command processing. Think about merging. */
3128 switch (cmdId)
3129 {
3130 case SVGA_CMD_INVALID_CMD:
3131 {
3132 /* Nothing to do. */
3133 STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdInvalidCmd);
3134 break;
3135 }
3136
3137 case SVGA_CMD_FENCE:
3138 {
3139 SVGAFifoCmdFence *pCmd = (SVGAFifoCmdFence *)&pu8Cmd[cbCmd];
3140 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3141 STAM_REL_COUNTER_INC(&pSvgaR3State->StatR3CmdFence);
3142 Log(("SVGA_CMD_FENCE %#x\n", pCmd->fence));
3143
3144 uint32_t const offFifoMin = pFIFO[SVGA_FIFO_MIN];
3145 if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_FENCE, offFifoMin))
3146 {
3147 pFIFO[SVGA_FIFO_FENCE] = pCmd->fence;
3148
3149 if (pThis->svga.u32IrqMask & SVGA_IRQFLAG_ANY_FENCE)
3150 {
3151 Log(("any fence irq\n"));
3152 *pu32IrqStatus |= SVGA_IRQFLAG_ANY_FENCE;
3153 }
3154 else if ( VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_FENCE_GOAL, offFifoMin)
3155 && (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FENCE_GOAL)
3156 && pFIFO[SVGA_FIFO_FENCE_GOAL] == pCmd->fence)
3157 {
3158 Log(("fence goal reached irq (fence=%#x)\n", pCmd->fence));
3159 *pu32IrqStatus |= SVGA_IRQFLAG_FENCE_GOAL;
3160 }
3161 }
3162 else
3163 Log(("SVGA_CMD_FENCE is bogus when offFifoMin is %#x!\n", offFifoMin));
3164 break;
3165 }
3166
3167 case SVGA_CMD_UPDATE:
3168 {
3169 SVGAFifoCmdUpdate *pCmd = (SVGAFifoCmdUpdate *)&pu8Cmd[cbCmd];
3170 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3171 vmsvgaR3CmdUpdate(pThis, pThisCC, pCmd);
3172 break;
3173 }
3174
3175 case SVGA_CMD_UPDATE_VERBOSE:
3176 {
3177 SVGAFifoCmdUpdateVerbose *pCmd = (SVGAFifoCmdUpdateVerbose *)&pu8Cmd[cbCmd];
3178 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3179 vmsvgaR3CmdUpdateVerbose(pThis, pThisCC, pCmd);
3180 break;
3181 }
3182
3183 case SVGA_CMD_DEFINE_CURSOR:
3184 {
3185 /* Followed by bitmap data. */
3186 SVGAFifoCmdDefineCursor *pCmd = (SVGAFifoCmdDefineCursor *)&pu8Cmd[cbCmd];
3187 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3188
3189 /* Figure out the size of the bitmap data. */
3190 ASSERT_GUEST_STMT_BREAK(pCmd->height < 2048 && pCmd->width < 2048, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
3191 ASSERT_GUEST_STMT_BREAK(pCmd->andMaskDepth <= 32, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
3192 ASSERT_GUEST_STMT_BREAK(pCmd->xorMaskDepth <= 32, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
3193 RT_UNTRUSTED_VALIDATED_FENCE();
3194
3195 uint32_t const cbAndLine = RT_ALIGN_32(pCmd->width * (pCmd->andMaskDepth + (pCmd->andMaskDepth == 15)), 32) / 8;
3196 uint32_t const cbAndMask = cbAndLine * pCmd->height;
3197 uint32_t const cbXorLine = RT_ALIGN_32(pCmd->width * (pCmd->xorMaskDepth + (pCmd->xorMaskDepth == 15)), 32) / 8;
3198 uint32_t const cbXorMask = cbXorLine * pCmd->height;
3199
3200 VMSVGA_INC_CMD_SIZE_BREAK(cbAndMask + cbXorMask);
3201 vmsvgaR3CmdDefineCursor(pThis, pThisCC, pCmd);
3202 break;
3203 }
3204
3205 case SVGA_CMD_DEFINE_ALPHA_CURSOR:
3206 {
3207 /* Followed by bitmap data. */
3208 SVGAFifoCmdDefineAlphaCursor *pCmd = (SVGAFifoCmdDefineAlphaCursor *)&pu8Cmd[cbCmd];
3209 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3210
3211 /* Figure out the size of the bitmap data. */
3212 ASSERT_GUEST_STMT_BREAK(pCmd->height < 2048 && pCmd->width < 2048, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
3213
3214 VMSVGA_INC_CMD_SIZE_BREAK(pCmd->width * pCmd->height * sizeof(uint32_t)); /* 32-bit BRGA format */
3215 vmsvgaR3CmdDefineAlphaCursor(pThis, pThisCC, pCmd);
3216 break;
3217 }
3218
3219 case SVGA_CMD_MOVE_CURSOR:
3220 {
3221 /* Deprecated; there should be no driver which *requires* this command. However, if
3222 * we do ecncounter this command, it might be useful to not get the FIFO completely out of
3223 * alignment.
3224 * May be issued by guest if SVGA_CAP_CURSOR_BYPASS is missing.
3225 */
3226 SVGAFifoCmdMoveCursor *pCmd = (SVGAFifoCmdMoveCursor *)&pu8Cmd[cbCmd];
3227 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3228 vmsvgaR3CmdMoveCursor(pThis, pThisCC, pCmd);
3229 break;
3230 }
3231
3232 case SVGA_CMD_DISPLAY_CURSOR:
3233 {
3234 /* Deprecated; there should be no driver which *requires* this command. However, if
3235 * we do ecncounter this command, it might be useful to not get the FIFO completely out of
3236 * alignment.
3237 * May be issued by guest if SVGA_CAP_CURSOR_BYPASS is missing.
3238 */
3239 SVGAFifoCmdDisplayCursor *pCmd = (SVGAFifoCmdDisplayCursor *)&pu8Cmd[cbCmd];
3240 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3241 vmsvgaR3CmdDisplayCursor(pThis, pThisCC, pCmd);
3242 break;
3243 }
3244
3245 case SVGA_CMD_RECT_FILL:
3246 {
3247 SVGAFifoCmdRectFill *pCmd = (SVGAFifoCmdRectFill *)&pu8Cmd[cbCmd];
3248 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3249 vmsvgaR3CmdRectFill(pThis, pThisCC, pCmd);
3250 break;
3251 }
3252
3253 case SVGA_CMD_RECT_COPY:
3254 {
3255 SVGAFifoCmdRectCopy *pCmd = (SVGAFifoCmdRectCopy *)&pu8Cmd[cbCmd];
3256 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3257 vmsvgaR3CmdRectCopy(pThis, pThisCC, pCmd);
3258 break;
3259 }
3260
3261 case SVGA_CMD_RECT_ROP_COPY:
3262 {
3263 SVGAFifoCmdRectRopCopy *pCmd = (SVGAFifoCmdRectRopCopy *)&pu8Cmd[cbCmd];
3264 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3265 vmsvgaR3CmdRectRopCopy(pThis, pThisCC, pCmd);
3266 break;
3267 }
3268
3269 case SVGA_CMD_ESCAPE:
3270 {
3271 /* Followed by 'size' bytes of data. */
3272 SVGAFifoCmdEscape *pCmd = (SVGAFifoCmdEscape *)&pu8Cmd[cbCmd];
3273 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3274
3275 ASSERT_GUEST_STMT_BREAK(pCmd->size < pThis->svga.cbFIFO - sizeof(SVGAFifoCmdEscape), CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
3276 RT_UNTRUSTED_VALIDATED_FENCE();
3277
3278 VMSVGA_INC_CMD_SIZE_BREAK(pCmd->size);
3279 vmsvgaR3CmdEscape(pThis, pThisCC, pCmd);
3280 break;
3281 }
3282# ifdef VBOX_WITH_VMSVGA3D
3283 case SVGA_CMD_DEFINE_GMR2:
3284 {
3285 SVGAFifoCmdDefineGMR2 *pCmd = (SVGAFifoCmdDefineGMR2 *)&pu8Cmd[cbCmd];
3286 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3287 vmsvgaR3CmdDefineGMR2(pThis, pThisCC, pCmd);
3288 break;
3289 }
3290
3291 case SVGA_CMD_REMAP_GMR2:
3292 {
3293 /* Followed by page descriptors or guest ptr. */
3294 SVGAFifoCmdRemapGMR2 *pCmd = (SVGAFifoCmdRemapGMR2 *)&pu8Cmd[cbCmd];
3295 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3296
3297 /* Calculate the size of what comes after next and fetch it. */
3298 uint32_t cbMore = 0;
3299 if (pCmd->flags & SVGA_REMAP_GMR2_VIA_GMR)
3300 cbMore = sizeof(SVGAGuestPtr);
3301 else
3302 {
3303 uint32_t const cbPageDesc = (pCmd->flags & SVGA_REMAP_GMR2_PPN64) ? sizeof(uint64_t) : sizeof(uint32_t);
3304 if (pCmd->flags & SVGA_REMAP_GMR2_SINGLE_PPN)
3305 {
3306 cbMore = cbPageDesc;
3307 pCmd->numPages = 1;
3308 }
3309 else
3310 {
3311 ASSERT_GUEST_STMT_BREAK(pCmd->numPages <= pThis->svga.cbFIFO / cbPageDesc, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
3312 cbMore = cbPageDesc * pCmd->numPages;
3313 }
3314 }
3315 VMSVGA_INC_CMD_SIZE_BREAK(cbMore);
3316 vmsvgaR3CmdRemapGMR2(pThis, pThisCC, pCmd);
3317# ifdef DEBUG_GMR_ACCESS
3318 VMR3ReqCallWaitU(PDMDevHlpGetUVM(pDevIns), VMCPUID_ANY, (PFNRT)vmsvgaR3RegisterGmr, 2, pDevIns, pCmd->gmrId);
3319# endif
3320 break;
3321 }
3322# endif /* VBOX_WITH_VMSVGA3D */
3323 case SVGA_CMD_DEFINE_SCREEN:
3324 {
3325 /* The size of this command is specified by the guest and depends on capabilities. */
3326 SVGAFifoCmdDefineScreen *pCmd = (SVGAFifoCmdDefineScreen *)&pu8Cmd[cbCmd];
3327 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(pCmd->screen.structSize));
3328 ASSERT_GUEST_STMT_BREAK(pCmd->screen.structSize < pThis->svga.cbFIFO, CBstatus = SVGA_CB_STATUS_COMMAND_ERROR);
3329 RT_UNTRUSTED_VALIDATED_FENCE();
3330
3331 VMSVGA_INC_CMD_SIZE_BREAK(RT_MAX(sizeof(pCmd->screen.structSize), pCmd->screen.structSize) - sizeof(pCmd->screen.structSize));
3332 vmsvgaR3CmdDefineScreen(pThis, pThisCC, pCmd);
3333 break;
3334 }
3335
3336 case SVGA_CMD_DESTROY_SCREEN:
3337 {
3338 SVGAFifoCmdDestroyScreen *pCmd = (SVGAFifoCmdDestroyScreen *)&pu8Cmd[cbCmd];
3339 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3340 vmsvgaR3CmdDestroyScreen(pThis, pThisCC, pCmd);
3341 break;
3342 }
3343
3344 case SVGA_CMD_DEFINE_GMRFB:
3345 {
3346 SVGAFifoCmdDefineGMRFB *pCmd = (SVGAFifoCmdDefineGMRFB *)&pu8Cmd[cbCmd];
3347 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3348 vmsvgaR3CmdDefineGMRFB(pThis, pThisCC, pCmd);
3349 break;
3350 }
3351
3352 case SVGA_CMD_BLIT_GMRFB_TO_SCREEN:
3353 {
3354 SVGAFifoCmdBlitGMRFBToScreen *pCmd = (SVGAFifoCmdBlitGMRFBToScreen *)&pu8Cmd[cbCmd];
3355 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3356 vmsvgaR3CmdBlitGMRFBToScreen(pThis, pThisCC, pCmd);
3357 break;
3358 }
3359
3360 case SVGA_CMD_BLIT_SCREEN_TO_GMRFB:
3361 {
3362 SVGAFifoCmdBlitScreenToGMRFB *pCmd = (SVGAFifoCmdBlitScreenToGMRFB *)&pu8Cmd[cbCmd];
3363 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3364 vmsvgaR3CmdBlitScreenToGMRFB(pThis, pThisCC, pCmd);
3365 break;
3366 }
3367
3368 case SVGA_CMD_ANNOTATION_FILL:
3369 {
3370 SVGAFifoCmdAnnotationFill *pCmd = (SVGAFifoCmdAnnotationFill *)&pu8Cmd[cbCmd];
3371 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3372 vmsvgaR3CmdAnnotationFill(pThis, pThisCC, pCmd);
3373 break;
3374 }
3375
3376 case SVGA_CMD_ANNOTATION_COPY:
3377 {
3378 SVGAFifoCmdAnnotationCopy *pCmd = (SVGAFifoCmdAnnotationCopy *)&pu8Cmd[cbCmd];
3379 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pCmd));
3380 vmsvgaR3CmdAnnotationCopy(pThis, pThisCC, pCmd);
3381 break;
3382 }
3383
3384 default:
3385 {
3386# ifdef VBOX_WITH_VMSVGA3D
3387 if ( cmdId >= SVGA_3D_CMD_BASE
3388 && cmdId < SVGA_3D_CMD_MAX)
3389 {
3390 RT_UNTRUSTED_VALIDATED_FENCE();
3391
3392 /* All 3d commands start with a common header, which defines the identifier and the size
3393 * of the command. The identifier has been already read. Fetch the size.
3394 */
3395 uint32_t const *pcbMore = (uint32_t const *)&pu8Cmd[cbCmd];
3396 VMSVGA_INC_CMD_SIZE_BREAK(sizeof(*pcbMore));
3397 VMSVGA_INC_CMD_SIZE_BREAK(*pcbMore);
3398 if (RT_LIKELY(pThis->svga.f3DEnabled))
3399 { /* likely */ }
3400 else
3401 {
3402 LogRelMax(8, ("VMSVGA: 3D disabled, command %d skipped\n", cmdId));
3403 break;
3404 }
3405
3406 /* Command data begins after the 32 bit command length. */
3407 int rc = vmsvgaR3Process3dCmd(pThis, pThisCC, (SVGAFifo3dCmdId)cmdId, *pcbMore, pcbMore + 1);
3408 if (RT_SUCCESS(rc))
3409 { /* likely */ }
3410 else
3411 {
3412 CBstatus = SVGA_CB_STATUS_COMMAND_ERROR;
3413 break;
3414 }
3415 }
3416 else
3417# endif /* VBOX_WITH_VMSVGA3D */
3418 {
3419 /* Unsupported command. */
3420 STAM_REL_COUNTER_INC(&pSvgaR3State->StatFifoUnkCmds);
3421 ASSERT_GUEST_MSG_FAILED(("cmdId=%d\n", cmdId));
3422 CBstatus = SVGA_CB_STATUS_COMMAND_ERROR;
3423 break;
3424 }
3425 }
3426 }
3427
3428 if (CBstatus != SVGA_CB_STATUS_COMPLETED)
3429 break;
3430
3431 pu8Cmd += cbCmd;
3432 cbRemain -= cbCmd;
3433
3434 /* If this is not the last command in the buffer, then generate IRQ, if required.
3435 * This avoids a double call to vmsvgaR3CmdBufRaiseIRQ if FENCE is the last command
3436 * in the buffer (usually the case).
3437 */
3438 if (RT_LIKELY(!(cbRemain && *pu32IrqStatus)))
3439 { /* likely */ }
3440 else
3441 {
3442 vmsvgaR3CmdBufRaiseIRQ(pDevIns, pThis, *pu32IrqStatus);
3443 *pu32IrqStatus = 0;
3444 }
3445 }
3446
3447 Assert(cbRemain <= cbCommands);
3448 *poffNextCmd = cbCommands - cbRemain;
3449 return CBstatus;
3450}
3451
3452
3453/** Process command buffers.
3454 *
3455 * @param pDevIns The device instance.
3456 * @param pThis The shared VGA/VMSVGA state.
3457 * @param pThisCC The VGA/VMSVGA state for the current context.
3458 * @param pThread Handle of the FIFO thread.
3459 * @thread FIFO
3460 */
3461static void vmsvgaR3CmdBufProcessBuffers(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PPDMTHREAD pThread)
3462{
3463 PVMSVGAR3STATE const pSvgaR3State = pThisCC->svga.pSvgaR3State;
3464
3465 for (;;)
3466 {
3467 if (pThread->enmState != PDMTHREADSTATE_RUNNING)
3468 break;
3469
3470 /* See if there is a submitted buffer. */
3471 PVMSVGACMDBUF pCmdBuf = NULL;
3472
3473 int rc = RTCritSectEnter(&pSvgaR3State->CritSectCmdBuf);
3474 AssertRC(rc);
3475
3476 /* It seems that a higher queue index has a higher priority.
3477 * See SVGACBContext in svga_reg.h from latest vmwgfx Linux driver.
3478 */
3479 for (unsigned i = RT_ELEMENTS(pSvgaR3State->apCmdBufCtxs); i > 0; --i)
3480 {
3481 PVMSVGACMDBUFCTX pCmdBufCtx = pSvgaR3State->apCmdBufCtxs[i - 1];
3482 if (pCmdBufCtx)
3483 {
3484 pCmdBuf = RTListRemoveFirst(&pCmdBufCtx->listSubmitted, VMSVGACMDBUF, nodeBuffer);
3485 if (pCmdBuf)
3486 {
3487 Assert(pCmdBufCtx->cSubmitted > 0);
3488 --pCmdBufCtx->cSubmitted;
3489 break;
3490 }
3491 }
3492 }
3493
3494 if (!pCmdBuf)
3495 {
3496 ASMAtomicWriteU32(&pSvgaR3State->fCmdBuf, 0);
3497 RTCritSectLeave(&pSvgaR3State->CritSectCmdBuf);
3498 break;
3499 }
3500
3501 RTCritSectLeave(&pSvgaR3State->CritSectCmdBuf);
3502
3503 SVGACBStatus CBstatus = SVGA_CB_STATUS_NONE;
3504 uint32_t offNextCmd = 0;
3505 uint32_t u32IrqStatus = 0;
3506
3507 /* Process one buffer. */
3508 CBstatus = vmsvgaR3CmdBufProcessCommands(pDevIns, pThis, pThisCC, pCmdBuf->pvCommands, pCmdBuf->hdr.length, &offNextCmd, &u32IrqStatus);
3509
3510 if (!RT_BOOL(pCmdBuf->hdr.flags & SVGA_CB_FLAG_NO_IRQ))
3511 u32IrqStatus |= SVGA_IRQFLAG_COMMAND_BUFFER;
3512 if (CBstatus == SVGA_CB_STATUS_COMMAND_ERROR)
3513 u32IrqStatus |= SVGA_IRQFLAG_ERROR;
3514
3515 vmsvgaR3CmdBufWriteStatus(pDevIns, pCmdBuf->GCPhysCB, CBstatus, offNextCmd);
3516 if (u32IrqStatus)
3517 vmsvgaR3CmdBufRaiseIRQ(pDevIns, pThis, u32IrqStatus);
3518
3519 vmsvgaR3CmdBufFree(pCmdBuf);
3520 }
3521}
3522
3523
3524/**
3525 * Worker for vmsvgaR3FifoThread that handles an external command.
3526 *
3527 * @param pDevIns The device instance.
3528 * @param pThis The shared VGA/VMSVGA instance data.
3529 * @param pThisCC The VGA/VMSVGA state for ring-3.
3530 */
3531static void vmsvgaR3FifoHandleExtCmd(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC)
3532{
3533 uint8_t uExtCmd = pThis->svga.u8FIFOExtCommand;
3534 switch (pThis->svga.u8FIFOExtCommand)
3535 {
3536 case VMSVGA_FIFO_EXTCMD_RESET:
3537 Log(("vmsvgaR3FifoLoop: reset the fifo thread.\n"));
3538 Assert(pThisCC->svga.pvFIFOExtCmdParam == NULL);
3539
3540 vmsvgaR3ResetScreens(pThis, pThisCC);
3541# ifdef VBOX_WITH_VMSVGA3D
3542 if (pThis->svga.f3DEnabled)
3543 {
3544 /* The 3d subsystem must be reset from the fifo thread. */
3545 vmsvga3dReset(pThisCC);
3546 }
3547# endif
3548 break;
3549
3550 case VMSVGA_FIFO_EXTCMD_POWEROFF:
3551 Log(("vmsvgaR3FifoLoop: power off.\n"));
3552 Assert(pThisCC->svga.pvFIFOExtCmdParam == NULL);
3553
3554 /* The screens must be reset on the FIFO thread, because they may use 3D resources. */
3555 vmsvgaR3ResetScreens(pThis, pThisCC);
3556 break;
3557
3558 case VMSVGA_FIFO_EXTCMD_TERMINATE:
3559 Log(("vmsvgaR3FifoLoop: terminate the fifo thread.\n"));
3560 Assert(pThisCC->svga.pvFIFOExtCmdParam == NULL);
3561# ifdef VBOX_WITH_VMSVGA3D
3562 if (pThis->svga.f3DEnabled)
3563 {
3564 /* The 3d subsystem must be shut down from the fifo thread. */
3565 vmsvga3dTerminate(pThisCC);
3566 }
3567# endif
3568 break;
3569
3570 case VMSVGA_FIFO_EXTCMD_SAVESTATE:
3571 {
3572 Log(("vmsvgaR3FifoLoop: VMSVGA_FIFO_EXTCMD_SAVESTATE.\n"));
3573 PSSMHANDLE pSSM = (PSSMHANDLE)pThisCC->svga.pvFIFOExtCmdParam;
3574 AssertLogRelMsgBreak(RT_VALID_PTR(pSSM), ("pSSM=%p\n", pSSM));
3575 vmsvgaR3SaveExecFifo(pDevIns->pHlpR3, pThisCC, pSSM);
3576# ifdef VBOX_WITH_VMSVGA3D
3577 if (pThis->svga.f3DEnabled)
3578 vmsvga3dSaveExec(pDevIns, pThisCC, pSSM);
3579# endif
3580 break;
3581 }
3582
3583 case VMSVGA_FIFO_EXTCMD_LOADSTATE:
3584 {
3585 Log(("vmsvgaR3FifoLoop: VMSVGA_FIFO_EXTCMD_LOADSTATE.\n"));
3586 PVMSVGA_STATE_LOAD pLoadState = (PVMSVGA_STATE_LOAD)pThisCC->svga.pvFIFOExtCmdParam;
3587 AssertLogRelMsgBreak(RT_VALID_PTR(pLoadState), ("pLoadState=%p\n", pLoadState));
3588 vmsvgaR3LoadExecFifo(pDevIns->pHlpR3, pThis, pThisCC, pLoadState->pSSM, pLoadState->uVersion, pLoadState->uPass);
3589# ifdef VBOX_WITH_VMSVGA3D
3590 if (pThis->svga.f3DEnabled)
3591 vmsvga3dLoadExec(pDevIns, pThis, pThisCC, pLoadState->pSSM, pLoadState->uVersion, pLoadState->uPass);
3592# endif
3593 break;
3594 }
3595
3596 case VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS:
3597 {
3598# ifdef VBOX_WITH_VMSVGA3D
3599 uint32_t sid = (uint32_t)(uintptr_t)pThisCC->svga.pvFIFOExtCmdParam;
3600 Log(("vmsvgaR3FifoLoop: VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS sid=%#x\n", sid));
3601 vmsvga3dUpdateHeapBuffersForSurfaces(pThisCC, sid);
3602# endif
3603 break;
3604 }
3605
3606
3607 default:
3608 AssertLogRelMsgFailed(("uExtCmd=%#x pvFIFOExtCmdParam=%p\n", uExtCmd, pThisCC->svga.pvFIFOExtCmdParam));
3609 break;
3610 }
3611
3612 /*
3613 * Signal the end of the external command.
3614 */
3615 pThisCC->svga.pvFIFOExtCmdParam = NULL;
3616 pThis->svga.u8FIFOExtCommand = VMSVGA_FIFO_EXTCMD_NONE;
3617 ASMMemoryFence(); /* paranoia^2 */
3618 int rc = RTSemEventSignal(pThisCC->svga.hFIFOExtCmdSem);
3619 AssertLogRelRC(rc);
3620}
3621
3622/**
3623 * Worker for vmsvgaR3Destruct, vmsvgaR3Reset, vmsvgaR3Save and vmsvgaR3Load for
3624 * doing a job on the FIFO thread (even when it's officially suspended).
3625 *
3626 * @returns VBox status code (fully asserted).
3627 * @param pDevIns The device instance.
3628 * @param pThis The shared VGA/VMSVGA instance data.
3629 * @param pThisCC The VGA/VMSVGA state for ring-3.
3630 * @param uExtCmd The command to execute on the FIFO thread.
3631 * @param pvParam Pointer to command parameters.
3632 * @param cMsWait The time to wait for the command, given in
3633 * milliseconds.
3634 */
3635static int vmsvgaR3RunExtCmdOnFifoThread(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC,
3636 uint8_t uExtCmd, void *pvParam, RTMSINTERVAL cMsWait)
3637{
3638 Assert(cMsWait >= RT_MS_1SEC * 5);
3639 AssertLogRelMsg(pThis->svga.u8FIFOExtCommand == VMSVGA_FIFO_EXTCMD_NONE,
3640 ("old=%d new=%d\n", pThis->svga.u8FIFOExtCommand, uExtCmd));
3641
3642 int rc;
3643 PPDMTHREAD pThread = pThisCC->svga.pFIFOIOThread;
3644 PDMTHREADSTATE enmState = pThread->enmState;
3645 if (enmState == PDMTHREADSTATE_SUSPENDED)
3646 {
3647 /*
3648 * The thread is suspended, we have to temporarily wake it up so it can
3649 * perform the task.
3650 * (We ASSUME not racing code here, both wrt thread state and ext commands.)
3651 */
3652 Log(("vmsvgaR3RunExtCmdOnFifoThread: uExtCmd=%d enmState=SUSPENDED\n", uExtCmd));
3653 /* Post the request. */
3654 pThis->svga.fFifoExtCommandWakeup = true;
3655 pThisCC->svga.pvFIFOExtCmdParam = pvParam;
3656 pThis->svga.u8FIFOExtCommand = uExtCmd;
3657 ASMMemoryFence(); /* paranoia^3 */
3658
3659 /* Resume the thread. */
3660 rc = PDMDevHlpThreadResume(pDevIns, pThread);
3661 AssertLogRelRC(rc);
3662 if (RT_SUCCESS(rc))
3663 {
3664 /* Wait. Take care in case the semaphore was already posted (same as below). */
3665 rc = RTSemEventWait(pThisCC->svga.hFIFOExtCmdSem, cMsWait);
3666 if ( rc == VINF_SUCCESS
3667 && pThis->svga.u8FIFOExtCommand == uExtCmd)
3668 rc = RTSemEventWait(pThisCC->svga.hFIFOExtCmdSem, cMsWait);
3669 AssertLogRelMsg(pThis->svga.u8FIFOExtCommand != uExtCmd || RT_FAILURE_NP(rc),
3670 ("%#x %Rrc\n", pThis->svga.u8FIFOExtCommand, rc));
3671
3672 /* suspend the thread */
3673 pThis->svga.fFifoExtCommandWakeup = false;
3674 int rc2 = PDMDevHlpThreadSuspend(pDevIns, pThread);
3675 AssertLogRelRC(rc2);
3676 if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
3677 rc = rc2;
3678 }
3679 pThis->svga.fFifoExtCommandWakeup = false;
3680 pThisCC->svga.pvFIFOExtCmdParam = NULL;
3681 }
3682 else if (enmState == PDMTHREADSTATE_RUNNING)
3683 {
3684 /*
3685 * The thread is running, should only happen during reset and vmsvga3dsfc.
3686 * We ASSUME not racing code here, both wrt thread state and ext commands.
3687 */
3688 Log(("vmsvgaR3RunExtCmdOnFifoThread: uExtCmd=%d enmState=RUNNING\n", uExtCmd));
3689 Assert(uExtCmd == VMSVGA_FIFO_EXTCMD_RESET || uExtCmd == VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS || uExtCmd == VMSVGA_FIFO_EXTCMD_POWEROFF);
3690
3691 /* Post the request. */
3692 pThisCC->svga.pvFIFOExtCmdParam = pvParam;
3693 pThis->svga.u8FIFOExtCommand = uExtCmd;
3694 ASMMemoryFence(); /* paranoia^2 */
3695 rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
3696 AssertLogRelRC(rc);
3697
3698 /* Wait. Take care in case the semaphore was already posted (same as above). */
3699 rc = RTSemEventWait(pThisCC->svga.hFIFOExtCmdSem, cMsWait);
3700 if ( rc == VINF_SUCCESS
3701 && pThis->svga.u8FIFOExtCommand == uExtCmd)
3702 rc = RTSemEventWait(pThisCC->svga.hFIFOExtCmdSem, cMsWait); /* it was already posted, retry the wait. */
3703 AssertLogRelMsg(pThis->svga.u8FIFOExtCommand != uExtCmd || RT_FAILURE_NP(rc),
3704 ("%#x %Rrc\n", pThis->svga.u8FIFOExtCommand, rc));
3705
3706 pThisCC->svga.pvFIFOExtCmdParam = NULL;
3707 }
3708 else
3709 {
3710 /*
3711 * Something is wrong with the thread!
3712 */
3713 AssertLogRelMsgFailed(("uExtCmd=%d enmState=%d\n", uExtCmd, enmState));
3714 rc = VERR_INVALID_STATE;
3715 }
3716 return rc;
3717}
3718
3719
3720/**
3721 * Marks the FIFO non-busy, notifying any waiting EMTs.
3722 *
3723 * @param pDevIns The device instance.
3724 * @param pThis The shared VGA/VMSVGA instance data.
3725 * @param pThisCC The VGA/VMSVGA state for ring-3.
3726 * @param pSVGAState Pointer to the ring-3 only SVGA state data.
3727 * @param offFifoMin The start byte offset of the command FIFO.
3728 */
3729static void vmsvgaR3FifoSetNotBusy(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, PVMSVGAR3STATE pSVGAState, uint32_t offFifoMin)
3730{
3731 ASMAtomicAndU32(&pThis->svga.fBusy, ~(VMSVGA_BUSY_F_FIFO | VMSVGA_BUSY_F_EMT_FORCE));
3732 if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, offFifoMin))
3733 vmsvgaHCSafeFifoBusyRegUpdate(pThis, pThisCC, pThis->svga.fBusy != 0);
3734
3735 /* Wake up any waiting EMTs. */
3736 if (pSVGAState->cBusyDelayedEmts > 0)
3737 {
3738# ifdef VMSVGA_USE_EMT_HALT_CODE
3739 PVM pVM = PDMDevHlpGetVM(pDevIns);
3740 VMCPUID idCpu = VMCpuSetFindLastPresentInternal(&pSVGAState->BusyDelayedEmts);
3741 if (idCpu != NIL_VMCPUID)
3742 {
3743 VMR3NotifyCpuDeviceReady(pVM, idCpu);
3744 while (idCpu-- > 0)
3745 if (VMCPUSET_IS_PRESENT(&pSVGAState->BusyDelayedEmts, idCpu))
3746 VMR3NotifyCpuDeviceReady(pVM, idCpu);
3747 }
3748# else
3749 int rc2 = RTSemEventMultiSignal(pSVGAState->hBusyDelayedEmts);
3750 AssertRC(rc2);
3751# endif
3752 }
3753}
3754
3755/**
3756 * Reads (more) payload into the command buffer.
3757 *
3758 * @returns pbBounceBuf on success
3759 * @retval (void *)1 if the thread was requested to stop.
3760 * @retval NULL on FIFO error.
3761 *
3762 * @param cbPayloadReq The number of bytes of payload requested.
3763 * @param pFIFO The FIFO.
3764 * @param offCurrentCmd The FIFO byte offset of the current command.
3765 * @param offFifoMin The start byte offset of the command FIFO.
3766 * @param offFifoMax The end byte offset of the command FIFO.
3767 * @param pbBounceBuf The bounch buffer. Same size as the entire FIFO, so
3768 * always sufficient size.
3769 * @param pcbAlreadyRead How much payload we've already read into the bounce
3770 * buffer. (We will NEVER re-read anything.)
3771 * @param pThread The calling PDM thread handle.
3772 * @param pThis The shared VGA/VMSVGA instance data.
3773 * @param pSVGAState Pointer to the ring-3 only SVGA state data. For
3774 * statistics collection.
3775 * @param pDevIns The device instance.
3776 */
3777static void *vmsvgaR3FifoGetCmdPayload(uint32_t cbPayloadReq, uint32_t RT_UNTRUSTED_VOLATILE_GUEST *pFIFO,
3778 uint32_t offCurrentCmd, uint32_t offFifoMin, uint32_t offFifoMax,
3779 uint8_t *pbBounceBuf, uint32_t *pcbAlreadyRead,
3780 PPDMTHREAD pThread, PVGASTATE pThis, PVMSVGAR3STATE pSVGAState, PPDMDEVINS pDevIns)
3781{
3782 Assert(pbBounceBuf);
3783 Assert(pcbAlreadyRead);
3784 Assert(offFifoMin < offFifoMax);
3785 Assert(offCurrentCmd >= offFifoMin && offCurrentCmd < offFifoMax);
3786 Assert(offFifoMax <= pThis->svga.cbFIFO);
3787
3788 /*
3789 * Check if the requested payload size has already been satisfied .
3790 * .
3791 * When called to read more, the caller is responsible for making sure the .
3792 * new command size (cbRequsted) never is smaller than what has already .
3793 * been read.
3794 */
3795 uint32_t cbAlreadyRead = *pcbAlreadyRead;
3796 if (cbPayloadReq <= cbAlreadyRead)
3797 {
3798 AssertLogRelReturn(cbPayloadReq == cbAlreadyRead, NULL);
3799 return pbBounceBuf;
3800 }
3801
3802 /*
3803 * Commands bigger than the fifo buffer are invalid.
3804 */
3805 uint32_t const cbFifoCmd = offFifoMax - offFifoMin;
3806 AssertMsgReturnStmt(cbPayloadReq <= cbFifoCmd, ("cbPayloadReq=%#x cbFifoCmd=%#x\n", cbPayloadReq, cbFifoCmd),
3807 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors),
3808 NULL);
3809
3810 /*
3811 * Move offCurrentCmd past the command dword.
3812 */
3813 offCurrentCmd += sizeof(uint32_t);
3814 if (offCurrentCmd >= offFifoMax)
3815 offCurrentCmd = offFifoMin;
3816
3817 /*
3818 * Do we have sufficient payload data available already?
3819 * The host should not read beyond [SVGA_FIFO_NEXT_CMD], therefore '>=' in the condition below.
3820 */
3821 uint32_t cbAfter, cbBefore;
3822 uint32_t offNextCmd = pFIFO[SVGA_FIFO_NEXT_CMD];
3823 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
3824 if (offNextCmd >= offCurrentCmd)
3825 {
3826 if (RT_LIKELY(offNextCmd < offFifoMax))
3827 cbAfter = offNextCmd - offCurrentCmd;
3828 else
3829 {
3830 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors);
3831 LogRelMax(16, ("vmsvgaR3FifoGetCmdPayload: Invalid offNextCmd=%#x (offFifoMin=%#x offFifoMax=%#x)\n",
3832 offNextCmd, offFifoMin, offFifoMax));
3833 cbAfter = offFifoMax - offCurrentCmd;
3834 }
3835 cbBefore = 0;
3836 }
3837 else
3838 {
3839 cbAfter = offFifoMax - offCurrentCmd;
3840 if (offNextCmd >= offFifoMin)
3841 cbBefore = offNextCmd - offFifoMin;
3842 else
3843 {
3844 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors);
3845 LogRelMax(16, ("vmsvgaR3FifoGetCmdPayload: Invalid offNextCmd=%#x (offFifoMin=%#x offFifoMax=%#x)\n",
3846 offNextCmd, offFifoMin, offFifoMax));
3847 cbBefore = 0;
3848 }
3849 }
3850 if (cbAfter + cbBefore < cbPayloadReq)
3851 {
3852 /*
3853 * Insufficient, must wait for it to arrive.
3854 */
3855/** @todo Should clear the busy flag here to maybe encourage the guest to wake us up. */
3856 STAM_REL_PROFILE_START(&pSVGAState->StatFifoStalls, Stall);
3857 for (uint32_t i = 0;; i++)
3858 {
3859 if (pThread->enmState != PDMTHREADSTATE_RUNNING)
3860 {
3861 STAM_REL_PROFILE_STOP(&pSVGAState->StatFifoStalls, Stall);
3862 return (void *)(uintptr_t)1;
3863 }
3864 Log(("Guest still copying (%x vs %x) current %x next %x stop %x loop %u; sleep a bit\n",
3865 cbPayloadReq, cbAfter + cbBefore, offCurrentCmd, offNextCmd, pFIFO[SVGA_FIFO_STOP], i));
3866
3867 PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->svga.hFIFORequestSem, i < 16 ? 1 : 2);
3868
3869 offNextCmd = pFIFO[SVGA_FIFO_NEXT_CMD];
3870 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
3871 if (offNextCmd >= offCurrentCmd)
3872 {
3873 cbAfter = RT_MIN(offNextCmd, offFifoMax) - offCurrentCmd;
3874 cbBefore = 0;
3875 }
3876 else
3877 {
3878 cbAfter = offFifoMax - offCurrentCmd;
3879 cbBefore = RT_MAX(offNextCmd, offFifoMin) - offFifoMin;
3880 }
3881
3882 if (cbAfter + cbBefore >= cbPayloadReq)
3883 break;
3884 }
3885 STAM_REL_PROFILE_STOP(&pSVGAState->StatFifoStalls, Stall);
3886 }
3887
3888 /*
3889 * Copy out the memory and update what pcbAlreadyRead points to.
3890 */
3891 if (cbAfter >= cbPayloadReq)
3892 memcpy(pbBounceBuf + cbAlreadyRead,
3893 (uint8_t *)pFIFO + offCurrentCmd + cbAlreadyRead,
3894 cbPayloadReq - cbAlreadyRead);
3895 else
3896 {
3897 LogFlow(("Split data buffer at %x (%u-%u)\n", offCurrentCmd, cbAfter, cbBefore));
3898 if (cbAlreadyRead < cbAfter)
3899 {
3900 memcpy(pbBounceBuf + cbAlreadyRead,
3901 (uint8_t *)pFIFO + offCurrentCmd + cbAlreadyRead,
3902 cbAfter - cbAlreadyRead);
3903 cbAlreadyRead = cbAfter;
3904 }
3905 memcpy(pbBounceBuf + cbAlreadyRead,
3906 (uint8_t *)pFIFO + offFifoMin + cbAlreadyRead - cbAfter,
3907 cbPayloadReq - cbAlreadyRead);
3908 }
3909 *pcbAlreadyRead = cbPayloadReq;
3910 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
3911 return pbBounceBuf;
3912}
3913
3914
3915/**
3916 * Sends cursor position and visibility information from the FIFO to the front-end.
3917 * @returns SVGA_FIFO_CURSOR_COUNT value used.
3918 */
3919static uint32_t
3920vmsvgaR3FifoUpdateCursor(PVGASTATECC pThisCC, PVMSVGAR3STATE pSVGAState, uint32_t RT_UNTRUSTED_VOLATILE_GUEST *pFIFO,
3921 uint32_t offFifoMin, uint32_t uCursorUpdateCount,
3922 uint32_t *pxLast, uint32_t *pyLast, uint32_t *pfLastVisible)
3923{
3924 /*
3925 * Check if the cursor update counter has changed and try get a stable
3926 * set of values if it has. This is race-prone, especially consindering
3927 * the screen ID, but little we can do about that.
3928 */
3929 uint32_t x, y, fVisible, idScreen;
3930 for (uint32_t i = 0; ; i++)
3931 {
3932 x = pFIFO[SVGA_FIFO_CURSOR_X];
3933 y = pFIFO[SVGA_FIFO_CURSOR_Y];
3934 fVisible = pFIFO[SVGA_FIFO_CURSOR_ON];
3935 idScreen = VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_CURSOR_SCREEN_ID, offFifoMin)
3936 ? pFIFO[SVGA_FIFO_CURSOR_SCREEN_ID] : SVGA_ID_INVALID;
3937 if ( uCursorUpdateCount == pFIFO[SVGA_FIFO_CURSOR_COUNT]
3938 || i > 3)
3939 break;
3940 if (i == 0)
3941 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoCursorFetchAgain);
3942 ASMNopPause();
3943 uCursorUpdateCount = pFIFO[SVGA_FIFO_CURSOR_COUNT];
3944 }
3945
3946 /*
3947 * Check if anything has changed, as calling into pDrv is not light-weight.
3948 */
3949 if ( *pxLast == x
3950 && *pyLast == y
3951 && (idScreen != SVGA_ID_INVALID || *pfLastVisible == fVisible))
3952 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoCursorNoChange);
3953 else
3954 {
3955 /*
3956 * Detected changes.
3957 *
3958 * We handle global, not per-screen visibility information by sending
3959 * pfnVBVAMousePointerShape without shape data.
3960 */
3961 *pxLast = x;
3962 *pyLast = y;
3963 uint32_t fFlags = VBVA_CURSOR_VALID_DATA;
3964 if (idScreen != SVGA_ID_INVALID)
3965 fFlags |= VBVA_CURSOR_SCREEN_RELATIVE;
3966 else if (*pfLastVisible != fVisible)
3967 {
3968 LogRel2(("vmsvgaR3FifoUpdateCursor: fVisible %d fLastVisible %d (%d,%d)\n", fVisible, *pfLastVisible, x, y));
3969 *pfLastVisible = fVisible;
3970 pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv, RT_BOOL(fVisible), false, 0, 0, 0, 0, NULL);
3971 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoCursorVisiblity);
3972 }
3973 pThisCC->pDrv->pfnVBVAReportCursorPosition(pThisCC->pDrv, fFlags, idScreen, x, y);
3974 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoCursorPosition);
3975 }
3976
3977 /*
3978 * Update done. Signal this to the guest.
3979 */
3980 pFIFO[SVGA_FIFO_CURSOR_LAST_UPDATED] = uCursorUpdateCount;
3981
3982 return uCursorUpdateCount;
3983}
3984
3985
3986/**
3987 * Checks if there is work to be done, either cursor updating or FIFO commands.
3988 *
3989 * @returns true if pending work, false if not.
3990 * @param pThisCC The VGA/VMSVGA state for ring-3.
3991 * @param uLastCursorCount The last cursor update counter value.
3992 */
3993DECLINLINE(bool) vmsvgaR3FifoHasWork(PVGASTATECC pThisCC, uint32_t uLastCursorCount)
3994{
3995 /* If FIFO does not exist than there is nothing to do. Command buffers also require the enabled FIFO. */
3996 uint32_t RT_UNTRUSTED_VOLATILE_GUEST * const pFIFO = pThisCC->svga.pau32FIFO;
3997 AssertReturn(pFIFO, false);
3998
3999 if (vmsvgaR3CmdBufHasWork(pThisCC))
4000 return true;
4001
4002 if (pFIFO[SVGA_FIFO_NEXT_CMD] != pFIFO[SVGA_FIFO_STOP])
4003 return true;
4004
4005 if ( uLastCursorCount != pFIFO[SVGA_FIFO_CURSOR_COUNT]
4006 && VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_CURSOR_LAST_UPDATED, pFIFO[SVGA_FIFO_MIN]))
4007 return true;
4008
4009 return false;
4010}
4011
4012
4013/**
4014 * Called by the VGA refresh timer to wake up the FIFO thread when needed.
4015 *
4016 * @param pDevIns The device instance.
4017 * @param pThis The shared VGA/VMSVGA instance data.
4018 * @param pThisCC The VGA/VMSVGA state for ring-3.
4019 */
4020void vmsvgaR3FifoWatchdogTimer(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC)
4021{
4022 /* Caller already checked pThis->svga.fFIFOThreadSleeping, so we only have
4023 to recheck it before doing the signalling. */
4024 if ( vmsvgaR3FifoHasWork(pThisCC, ASMAtomicReadU32(&pThis->svga.uLastCursorUpdateCount))
4025 && pThis->svga.fFIFOThreadSleeping)
4026 {
4027 int rc = PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
4028 AssertRC(rc);
4029 STAM_REL_COUNTER_INC(&pThisCC->svga.pSvgaR3State->StatFifoWatchdogWakeUps);
4030 }
4031}
4032
4033
4034/**
4035 * Called by the FIFO thread to process pending actions.
4036 *
4037 * @param pDevIns The device instance.
4038 * @param pThis The shared VGA/VMSVGA instance data.
4039 * @param pThisCC The VGA/VMSVGA state for ring-3.
4040 */
4041void vmsvgaR3FifoPendingActions(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC)
4042{
4043 RT_NOREF(pDevIns);
4044
4045 /* Currently just mode changes. */
4046 if (ASMBitTestAndClear(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE_BIT))
4047 {
4048 vmsvgaR3ChangeMode(pThis, pThisCC);
4049# ifdef VBOX_WITH_VMSVGA3D
4050 if (pThisCC->svga.p3dState != NULL)
4051 vmsvga3dChangeMode(pThisCC);
4052# endif
4053 }
4054}
4055
4056
4057/*
4058 * These two macros are put outside vmsvgaR3FifoLoop because doxygen gets confused,
4059 * even the latest version, and thinks we're documenting vmsvgaR3FifoLoop. Sigh.
4060 */
4061/** @def VMSVGAFIFO_GET_CMD_BUFFER_BREAK
4062 * Macro for shortening calls to vmsvgaR3FifoGetCmdPayload.
4063 *
4064 * Will break out of the switch on failure.
4065 * Will restart and quit the loop if the thread was requested to stop.
4066 *
4067 * @param a_PtrVar Request variable pointer.
4068 * @param a_Type Request typedef (not pointer) for casting.
4069 * @param a_cbPayloadReq How much payload to fetch.
4070 * @remarks Accesses a bunch of variables in the current scope!
4071 */
4072# define VMSVGAFIFO_GET_CMD_BUFFER_BREAK(a_PtrVar, a_Type, a_cbPayloadReq) \
4073 if (1) { \
4074 (a_PtrVar) = (a_Type *)vmsvgaR3FifoGetCmdPayload((a_cbPayloadReq), pFIFO, offCurrentCmd, offFifoMin, offFifoMax, \
4075 pbBounceBuf, &cbPayload, pThread, pThis, pSVGAState, pDevIns); \
4076 if (RT_UNLIKELY((uintptr_t)(a_PtrVar) < 2)) { if ((uintptr_t)(a_PtrVar) == 1) continue; break; } \
4077 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); \
4078 } else do {} while (0)
4079/* @def VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK
4080 * Macro for shortening calls to vmsvgaR3FifoGetCmdPayload for refetching the
4081 * buffer after figuring out the actual command size.
4082 *
4083 * Will break out of the switch on failure.
4084 *
4085 * @param a_PtrVar Request variable pointer.
4086 * @param a_Type Request typedef (not pointer) for casting.
4087 * @param a_cbPayloadReq How much payload to fetch.
4088 * @remarks Accesses a bunch of variables in the current scope!
4089 */
4090# define VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(a_PtrVar, a_Type, a_cbPayloadReq) \
4091 if (1) { \
4092 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(a_PtrVar, a_Type, a_cbPayloadReq); \
4093 } else do {} while (0)
4094
4095/**
4096 * @callback_method_impl{PFNPDMTHREADDEV, The async FIFO handling thread.}
4097 */
4098static DECLCALLBACK(int) vmsvgaR3FifoLoop(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
4099{
4100 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
4101 PVGASTATER3 pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
4102 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
4103 int rc;
4104
4105# if defined(VBOX_WITH_VMSVGA3D) && defined(RT_OS_LINUX)
4106 if (pThis->svga.f3DEnabled)
4107 {
4108 /* The FIFO thread may use X API for accelerated screen output. */
4109 XInitThreads();
4110 }
4111# endif
4112
4113 if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
4114 return VINF_SUCCESS;
4115
4116 /*
4117 * Special mode where we only execute an external command and the go back
4118 * to being suspended. Currently, all ext cmds ends up here, with the reset
4119 * one also being eligble for runtime execution further down as well.
4120 */
4121 if (pThis->svga.fFifoExtCommandWakeup)
4122 {
4123 vmsvgaR3FifoHandleExtCmd(pDevIns, pThis, pThisCC);
4124 while (pThread->enmState == PDMTHREADSTATE_RUNNING)
4125 if (pThis->svga.u8FIFOExtCommand == VMSVGA_FIFO_EXTCMD_NONE)
4126 PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->svga.hFIFORequestSem, RT_MS_1MIN);
4127 else
4128 vmsvgaR3FifoHandleExtCmd(pDevIns, pThis, pThisCC);
4129 return VINF_SUCCESS;
4130 }
4131
4132
4133 /*
4134 * Signal the semaphore to make sure we don't wait for 250ms after a
4135 * suspend & resume scenario (see vmsvgaR3FifoGetCmdPayload).
4136 */
4137 PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
4138
4139 /*
4140 * Allocate a bounce buffer for command we get from the FIFO.
4141 * (All code must return via the end of the function to free this buffer.)
4142 */
4143 uint8_t *pbBounceBuf = (uint8_t *)RTMemAllocZ(pThis->svga.cbFIFO);
4144 AssertReturn(pbBounceBuf, VERR_NO_MEMORY);
4145
4146 /*
4147 * Polling/sleep interval config.
4148 *
4149 * We wait for an a short interval if the guest has recently given us work
4150 * to do, but the interval increases the longer we're kept idle. Once we've
4151 * reached the refresh timer interval, we'll switch to extended waits,
4152 * depending on it or the guest to kick us into action when needed.
4153 *
4154 * Should the refresh time go fishing, we'll just continue increasing the
4155 * sleep length till we reaches the 250 ms max after about 16 seconds.
4156 */
4157 RTMSINTERVAL const cMsMinSleep = 16;
4158 RTMSINTERVAL const cMsIncSleep = 2;
4159 RTMSINTERVAL const cMsMaxSleep = 250;
4160 RTMSINTERVAL const cMsExtendedSleep = 15 * RT_MS_1SEC; /* Regular paranoia dictates that this cannot be indefinite. */
4161 RTMSINTERVAL cMsSleep = cMsMaxSleep;
4162
4163 /*
4164 * Cursor update state (SVGA_FIFO_CAP_CURSOR_BYPASS_3).
4165 *
4166 * Initialize with values that will detect an update from the guest.
4167 * Make sure that if the guest never updates the cursor position, then the device does not report it.
4168 * The guest has to change the value of uLastCursorUpdateCount, when the cursor position is actually updated.
4169 * xLastCursor, yLastCursor and fLastCursorVisible are set to report the first update.
4170 */
4171 uint32_t RT_UNTRUSTED_VOLATILE_GUEST * const pFIFO = pThisCC->svga.pau32FIFO;
4172 pThis->svga.uLastCursorUpdateCount = pFIFO[SVGA_FIFO_CURSOR_COUNT];
4173 uint32_t xLastCursor = ~pFIFO[SVGA_FIFO_CURSOR_X];
4174 uint32_t yLastCursor = ~pFIFO[SVGA_FIFO_CURSOR_Y];
4175 uint32_t fLastCursorVisible = ~pFIFO[SVGA_FIFO_CURSOR_ON];
4176
4177 /*
4178 * The FIFO loop.
4179 */
4180 LogFlow(("vmsvgaR3FifoLoop: started loop\n"));
4181 bool fBadOrDisabledFifo = false;
4182 while (pThread->enmState == PDMTHREADSTATE_RUNNING)
4183 {
4184# if defined(RT_OS_DARWIN) && defined(VBOX_WITH_VMSVGA3D)
4185 /*
4186 * Should service the run loop every so often.
4187 */
4188 if (pThis->svga.f3DEnabled)
4189 vmsvga3dCocoaServiceRunLoop();
4190# endif
4191
4192 /* First check any pending actions. */
4193 vmsvgaR3FifoPendingActions(pDevIns, pThis, pThisCC);
4194
4195 /*
4196 * Unless there's already work pending, go to sleep for a short while.
4197 * (See polling/sleep interval config above.)
4198 */
4199 if ( fBadOrDisabledFifo
4200 || !vmsvgaR3FifoHasWork(pThisCC, pThis->svga.uLastCursorUpdateCount))
4201 {
4202 ASMAtomicWriteBool(&pThis->svga.fFIFOThreadSleeping, true);
4203 Assert(pThis->cMilliesRefreshInterval > 0);
4204 if (cMsSleep < pThis->cMilliesRefreshInterval)
4205 rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->svga.hFIFORequestSem, cMsSleep);
4206 else
4207 {
4208# ifdef VMSVGA_USE_FIFO_ACCESS_HANDLER
4209 int rc2 = PGMHandlerPhysicalReset(PDMDevHlpGetVM(pDevIns), pThis->svga.GCPhysFIFO);
4210 AssertRC(rc2); /* No break. Racing EMTs unmapping and remapping the region. */
4211# endif
4212 if ( !fBadOrDisabledFifo
4213 && vmsvgaR3FifoHasWork(pThisCC, pThis->svga.uLastCursorUpdateCount))
4214 rc = VINF_SUCCESS;
4215 else
4216 {
4217 STAM_REL_PROFILE_START(&pSVGAState->StatFifoExtendedSleep, Acc);
4218 rc = PDMDevHlpSUPSemEventWaitNoResume(pDevIns, pThis->svga.hFIFORequestSem, cMsExtendedSleep);
4219 STAM_REL_PROFILE_STOP(&pSVGAState->StatFifoExtendedSleep, Acc);
4220 }
4221 }
4222 ASMAtomicWriteBool(&pThis->svga.fFIFOThreadSleeping, false);
4223 AssertBreak(RT_SUCCESS(rc) || rc == VERR_TIMEOUT || rc == VERR_INTERRUPTED);
4224 if (pThread->enmState != PDMTHREADSTATE_RUNNING)
4225 {
4226 LogFlow(("vmsvgaR3FifoLoop: thread state %x\n", pThread->enmState));
4227 break;
4228 }
4229 }
4230 else
4231 rc = VINF_SUCCESS;
4232 fBadOrDisabledFifo = false;
4233 if (rc == VERR_TIMEOUT)
4234 {
4235 if (!vmsvgaR3FifoHasWork(pThisCC, pThis->svga.uLastCursorUpdateCount))
4236 {
4237 cMsSleep = RT_MIN(cMsSleep + cMsIncSleep, cMsMaxSleep);
4238 continue;
4239 }
4240 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoTodoTimeout);
4241
4242 Log(("vmsvgaR3FifoLoop: timeout\n"));
4243 }
4244 else if (vmsvgaR3FifoHasWork(pThisCC, pThis->svga.uLastCursorUpdateCount))
4245 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoTodoWoken);
4246 cMsSleep = cMsMinSleep;
4247
4248 Log(("vmsvgaR3FifoLoop: enabled=%d configured=%d busy=%d\n", pThis->svga.fEnabled, pThis->svga.fConfigured, pFIFO[SVGA_FIFO_BUSY]));
4249 Log(("vmsvgaR3FifoLoop: min %x max %x\n", pFIFO[SVGA_FIFO_MIN], pFIFO[SVGA_FIFO_MAX]));
4250 Log(("vmsvgaR3FifoLoop: next %x stop %x\n", pFIFO[SVGA_FIFO_NEXT_CMD], pFIFO[SVGA_FIFO_STOP]));
4251
4252 /*
4253 * Handle external commands (currently only reset).
4254 */
4255 if (pThis->svga.u8FIFOExtCommand != VMSVGA_FIFO_EXTCMD_NONE)
4256 {
4257 vmsvgaR3FifoHandleExtCmd(pDevIns, pThis, pThisCC);
4258 continue;
4259 }
4260
4261 /*
4262 * The device must be enabled and configured.
4263 */
4264 if ( !pThis->svga.fEnabled
4265 || !pThis->svga.fConfigured)
4266 {
4267 vmsvgaR3FifoSetNotBusy(pDevIns, pThis, pThisCC, pSVGAState, pFIFO[SVGA_FIFO_MIN]);
4268 fBadOrDisabledFifo = true;
4269 cMsSleep = cMsMaxSleep; /* cheat */
4270 continue;
4271 }
4272
4273 /*
4274 * Get and check the min/max values. We ASSUME that they will remain
4275 * unchanged while we process requests. A further ASSUMPTION is that
4276 * the guest won't mess with SVGA_FIFO_NEXT_CMD while we're busy, so
4277 * we don't read it back while in the loop.
4278 */
4279 uint32_t const offFifoMin = pFIFO[SVGA_FIFO_MIN];
4280 uint32_t const offFifoMax = pFIFO[SVGA_FIFO_MAX];
4281 uint32_t offCurrentCmd = pFIFO[SVGA_FIFO_STOP];
4282 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
4283 if (RT_UNLIKELY( !VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_STOP, offFifoMin)
4284 || offFifoMax <= offFifoMin
4285 || offFifoMax > pThis->svga.cbFIFO
4286 || (offFifoMax & 3) != 0
4287 || (offFifoMin & 3) != 0
4288 || offCurrentCmd < offFifoMin
4289 || offCurrentCmd > offFifoMax))
4290 {
4291 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors);
4292 LogRelMax(8, ("vmsvgaR3FifoLoop: Bad fifo: min=%#x stop=%#x max=%#x\n", offFifoMin, offCurrentCmd, offFifoMax));
4293 vmsvgaR3FifoSetNotBusy(pDevIns, pThis, pThisCC, pSVGAState, offFifoMin);
4294 fBadOrDisabledFifo = true;
4295 continue;
4296 }
4297 RT_UNTRUSTED_VALIDATED_FENCE();
4298 if (RT_UNLIKELY(offCurrentCmd & 3))
4299 {
4300 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoErrors);
4301 LogRelMax(8, ("vmsvgaR3FifoLoop: Misaligned offCurrentCmd=%#x?\n", offCurrentCmd));
4302 offCurrentCmd &= ~UINT32_C(3);
4303 }
4304
4305 /*
4306 * Update the cursor position before we start on the FIFO commands.
4307 */
4308 /** @todo do we need to check whether the guest disabled the SVGA_FIFO_CAP_CURSOR_BYPASS_3 capability here? */
4309 if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_CURSOR_LAST_UPDATED, offFifoMin))
4310 {
4311 uint32_t const uCursorUpdateCount = pFIFO[SVGA_FIFO_CURSOR_COUNT];
4312 if (uCursorUpdateCount == pThis->svga.uLastCursorUpdateCount)
4313 { /* halfways likely */ }
4314 else
4315 {
4316 uint32_t const uNewCount = vmsvgaR3FifoUpdateCursor(pThisCC, pSVGAState, pFIFO, offFifoMin, uCursorUpdateCount,
4317 &xLastCursor, &yLastCursor, &fLastCursorVisible);
4318 ASMAtomicWriteU32(&pThis->svga.uLastCursorUpdateCount, uNewCount);
4319 }
4320 }
4321
4322 /*
4323 * Mark the FIFO as busy.
4324 */
4325 ASMAtomicWriteU32(&pThis->svga.fBusy, VMSVGA_BUSY_F_FIFO); // Clears VMSVGA_BUSY_F_EMT_FORCE!
4326 if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, offFifoMin))
4327 ASMAtomicWriteU32(&pFIFO[SVGA_FIFO_BUSY], true);
4328
4329 /*
4330 * Process all submitted command buffers.
4331 */
4332 vmsvgaR3CmdBufProcessBuffers(pDevIns, pThis, pThisCC, pThread);
4333
4334 /*
4335 * Execute all queued FIFO commands.
4336 * Quit if pending external command or changes in the thread state.
4337 */
4338 bool fDone = false;
4339 while ( !(fDone = (pFIFO[SVGA_FIFO_NEXT_CMD] == offCurrentCmd))
4340 && pThread->enmState == PDMTHREADSTATE_RUNNING)
4341 {
4342 uint32_t cbPayload = 0;
4343 uint32_t u32IrqStatus = 0;
4344
4345 Assert(offCurrentCmd < offFifoMax && offCurrentCmd >= offFifoMin);
4346
4347 /* First check any pending actions. */
4348 vmsvgaR3FifoPendingActions(pDevIns, pThis, pThisCC);
4349
4350 /* Check for pending external commands (reset). */
4351 if (pThis->svga.u8FIFOExtCommand != VMSVGA_FIFO_EXTCMD_NONE)
4352 break;
4353
4354 /*
4355 * Process the command.
4356 */
4357 /* 'enmCmdId' is actually a SVGAFifoCmdId. It is treated as uint32_t in order to avoid a compiler
4358 * warning. Because we implement some obsolete and deprecated commands, which are not included in
4359 * the SVGAFifoCmdId enum in the VMSVGA headers anymore.
4360 */
4361 uint32_t const enmCmdId = pFIFO[offCurrentCmd / sizeof(uint32_t)];
4362 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
4363 LogFlow(("vmsvgaR3FifoLoop: FIFO command (iCmd=0x%x) %s %d\n",
4364 offCurrentCmd / sizeof(uint32_t), vmsvgaR3FifoCmdToString(enmCmdId), enmCmdId));
4365 switch (enmCmdId)
4366 {
4367 case SVGA_CMD_INVALID_CMD:
4368 /* Nothing to do. */
4369 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdInvalidCmd);
4370 break;
4371
4372 case SVGA_CMD_FENCE:
4373 {
4374 SVGAFifoCmdFence *pCmdFence;
4375 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmdFence, SVGAFifoCmdFence, sizeof(*pCmdFence));
4376 STAM_REL_COUNTER_INC(&pSVGAState->StatR3CmdFence);
4377 if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_FENCE, offFifoMin))
4378 {
4379 Log(("vmsvgaR3FifoLoop: SVGA_CMD_FENCE %#x\n", pCmdFence->fence));
4380 pFIFO[SVGA_FIFO_FENCE] = pCmdFence->fence;
4381
4382 if (pThis->svga.u32IrqMask & SVGA_IRQFLAG_ANY_FENCE)
4383 {
4384 Log(("vmsvgaR3FifoLoop: any fence irq\n"));
4385 u32IrqStatus |= SVGA_IRQFLAG_ANY_FENCE;
4386 }
4387 else
4388 if ( VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_FENCE_GOAL, offFifoMin)
4389 && (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FENCE_GOAL)
4390 && pFIFO[SVGA_FIFO_FENCE_GOAL] == pCmdFence->fence)
4391 {
4392 Log(("vmsvgaR3FifoLoop: fence goal reached irq (fence=%#x)\n", pCmdFence->fence));
4393 u32IrqStatus |= SVGA_IRQFLAG_FENCE_GOAL;
4394 }
4395 }
4396 else
4397 Log(("SVGA_CMD_FENCE is bogus when offFifoMin is %#x!\n", offFifoMin));
4398 break;
4399 }
4400
4401 case SVGA_CMD_UPDATE:
4402 {
4403 SVGAFifoCmdUpdate *pCmd;
4404 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdUpdate, sizeof(*pCmd));
4405 vmsvgaR3CmdUpdate(pThis, pThisCC, pCmd);
4406 break;
4407 }
4408
4409 case SVGA_CMD_UPDATE_VERBOSE:
4410 {
4411 SVGAFifoCmdUpdateVerbose *pCmd;
4412 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdUpdateVerbose, sizeof(*pCmd));
4413 vmsvgaR3CmdUpdateVerbose(pThis, pThisCC, pCmd);
4414 break;
4415 }
4416
4417 case SVGA_CMD_DEFINE_CURSOR:
4418 {
4419 /* Followed by bitmap data. */
4420 SVGAFifoCmdDefineCursor *pCmd;
4421 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineCursor, sizeof(*pCmd));
4422
4423 /* Figure out the size of the bitmap data. */
4424 ASSERT_GUEST_BREAK(pCmd->height < 2048 && pCmd->width < 2048);
4425 ASSERT_GUEST_BREAK(pCmd->andMaskDepth <= 32);
4426 ASSERT_GUEST_BREAK(pCmd->xorMaskDepth <= 32);
4427 RT_UNTRUSTED_VALIDATED_FENCE();
4428
4429 uint32_t const cbAndLine = RT_ALIGN_32(pCmd->width * (pCmd->andMaskDepth + (pCmd->andMaskDepth == 15)), 32) / 8;
4430 uint32_t const cbAndMask = cbAndLine * pCmd->height;
4431 uint32_t const cbXorLine = RT_ALIGN_32(pCmd->width * (pCmd->xorMaskDepth + (pCmd->xorMaskDepth == 15)), 32) / 8;
4432 uint32_t const cbXorMask = cbXorLine * pCmd->height;
4433
4434 uint32_t const cbCmd = sizeof(SVGAFifoCmdDefineCursor) + cbAndMask + cbXorMask;
4435 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineCursor, cbCmd);
4436 vmsvgaR3CmdDefineCursor(pThis, pThisCC, pCmd);
4437 break;
4438 }
4439
4440 case SVGA_CMD_DEFINE_ALPHA_CURSOR:
4441 {
4442 /* Followed by bitmap data. */
4443 SVGAFifoCmdDefineAlphaCursor *pCmd;
4444 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineAlphaCursor, sizeof(*pCmd));
4445
4446 /* Figure out the size of the bitmap data. */
4447 ASSERT_GUEST_BREAK(pCmd->height < 2048 && pCmd->width < 2048);
4448
4449 uint32_t const cbCmd = sizeof(SVGAFifoCmdDefineAlphaCursor) + pCmd->width * pCmd->height * sizeof(uint32_t) /* 32-bit BRGA format */;
4450 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineAlphaCursor, cbCmd);
4451 vmsvgaR3CmdDefineAlphaCursor(pThis, pThisCC, pCmd);
4452 break;
4453 }
4454
4455 case SVGA_CMD_MOVE_CURSOR:
4456 {
4457 /* Deprecated; there should be no driver which *requires* this command. However, if
4458 * we do ecncounter this command, it might be useful to not get the FIFO completely out of
4459 * alignment.
4460 * May be issued by guest if SVGA_CAP_CURSOR_BYPASS is missing.
4461 */
4462 SVGAFifoCmdMoveCursor *pCmd;
4463 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdMoveCursor, sizeof(*pCmd));
4464 vmsvgaR3CmdMoveCursor(pThis, pThisCC, pCmd);
4465 break;
4466 }
4467
4468 case SVGA_CMD_DISPLAY_CURSOR:
4469 {
4470 /* Deprecated; there should be no driver which *requires* this command. However, if
4471 * we do ecncounter this command, it might be useful to not get the FIFO completely out of
4472 * alignment.
4473 * May be issued by guest if SVGA_CAP_CURSOR_BYPASS is missing.
4474 */
4475 SVGAFifoCmdDisplayCursor *pCmd;
4476 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDisplayCursor, sizeof(*pCmd));
4477 vmsvgaR3CmdDisplayCursor(pThis, pThisCC, pCmd);
4478 break;
4479 }
4480
4481 case SVGA_CMD_RECT_FILL:
4482 {
4483 SVGAFifoCmdRectFill *pCmd;
4484 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRectFill, sizeof(*pCmd));
4485 vmsvgaR3CmdRectFill(pThis, pThisCC, pCmd);
4486 break;
4487 }
4488
4489 case SVGA_CMD_RECT_COPY:
4490 {
4491 SVGAFifoCmdRectCopy *pCmd;
4492 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRectCopy, sizeof(*pCmd));
4493 vmsvgaR3CmdRectCopy(pThis, pThisCC, pCmd);
4494 break;
4495 }
4496
4497 case SVGA_CMD_RECT_ROP_COPY:
4498 {
4499 SVGAFifoCmdRectRopCopy *pCmd;
4500 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRectRopCopy, sizeof(*pCmd));
4501 vmsvgaR3CmdRectRopCopy(pThis, pThisCC, pCmd);
4502 break;
4503 }
4504
4505 case SVGA_CMD_ESCAPE:
4506 {
4507 /* Followed by 'size' bytes of data. */
4508 SVGAFifoCmdEscape *pCmd;
4509 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdEscape, sizeof(*pCmd));
4510
4511 ASSERT_GUEST_BREAK(pCmd->size < pThis->svga.cbFIFO - sizeof(SVGAFifoCmdEscape));
4512 RT_UNTRUSTED_VALIDATED_FENCE();
4513
4514 uint32_t const cbCmd = sizeof(SVGAFifoCmdEscape) + pCmd->size;
4515 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdEscape, cbCmd);
4516 vmsvgaR3CmdEscape(pThis, pThisCC, pCmd);
4517 break;
4518 }
4519# ifdef VBOX_WITH_VMSVGA3D
4520 case SVGA_CMD_DEFINE_GMR2:
4521 {
4522 SVGAFifoCmdDefineGMR2 *pCmd;
4523 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineGMR2, sizeof(*pCmd));
4524 vmsvgaR3CmdDefineGMR2(pThis, pThisCC, pCmd);
4525 break;
4526 }
4527
4528 case SVGA_CMD_REMAP_GMR2:
4529 {
4530 /* Followed by page descriptors or guest ptr. */
4531 SVGAFifoCmdRemapGMR2 *pCmd;
4532 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRemapGMR2, sizeof(*pCmd));
4533
4534 /* Calculate the size of what comes after next and fetch it. */
4535 uint32_t cbCmd = sizeof(SVGAFifoCmdRemapGMR2);
4536 if (pCmd->flags & SVGA_REMAP_GMR2_VIA_GMR)
4537 cbCmd += sizeof(SVGAGuestPtr);
4538 else
4539 {
4540 uint32_t const cbPageDesc = (pCmd->flags & SVGA_REMAP_GMR2_PPN64) ? sizeof(uint64_t) : sizeof(uint32_t);
4541 if (pCmd->flags & SVGA_REMAP_GMR2_SINGLE_PPN)
4542 {
4543 cbCmd += cbPageDesc;
4544 pCmd->numPages = 1;
4545 }
4546 else
4547 {
4548 ASSERT_GUEST_BREAK(pCmd->numPages <= pThis->svga.cbFIFO / cbPageDesc);
4549 cbCmd += cbPageDesc * pCmd->numPages;
4550 }
4551 }
4552 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdRemapGMR2, cbCmd);
4553 vmsvgaR3CmdRemapGMR2(pThis, pThisCC, pCmd);
4554# ifdef DEBUG_GMR_ACCESS
4555 VMR3ReqCallWaitU(PDMDevHlpGetUVM(pDevIns), VMCPUID_ANY, (PFNRT)vmsvgaR3RegisterGmr, 2, pDevIns, pCmd->gmrId);
4556# endif
4557 break;
4558 }
4559# endif // VBOX_WITH_VMSVGA3D
4560 case SVGA_CMD_DEFINE_SCREEN:
4561 {
4562 /* The size of this command is specified by the guest and depends on capabilities. */
4563 Assert(pFIFO[SVGA_FIFO_CAPABILITIES] & SVGA_FIFO_CAP_SCREEN_OBJECT_2);
4564
4565 SVGAFifoCmdDefineScreen *pCmd;
4566 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineScreen, sizeof(pCmd->screen.structSize));
4567 AssertBreak(pCmd->screen.structSize < pThis->svga.cbFIFO);
4568 RT_UNTRUSTED_VALIDATED_FENCE();
4569
4570 RT_BZERO(&pCmd->screen.id, sizeof(*pCmd) - RT_OFFSETOF(SVGAFifoCmdDefineScreen, screen.id));
4571 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineScreen, RT_MAX(sizeof(pCmd->screen.structSize), pCmd->screen.structSize));
4572 vmsvgaR3CmdDefineScreen(pThis, pThisCC, pCmd);
4573 break;
4574 }
4575
4576 case SVGA_CMD_DESTROY_SCREEN:
4577 {
4578 SVGAFifoCmdDestroyScreen *pCmd;
4579 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDestroyScreen, sizeof(*pCmd));
4580 vmsvgaR3CmdDestroyScreen(pThis, pThisCC, pCmd);
4581 break;
4582 }
4583
4584 case SVGA_CMD_DEFINE_GMRFB:
4585 {
4586 SVGAFifoCmdDefineGMRFB *pCmd;
4587 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdDefineGMRFB, sizeof(*pCmd));
4588 vmsvgaR3CmdDefineGMRFB(pThis, pThisCC, pCmd);
4589 break;
4590 }
4591
4592 case SVGA_CMD_BLIT_GMRFB_TO_SCREEN:
4593 {
4594 SVGAFifoCmdBlitGMRFBToScreen *pCmd;
4595 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdBlitGMRFBToScreen, sizeof(*pCmd));
4596 vmsvgaR3CmdBlitGMRFBToScreen(pThis, pThisCC, pCmd);
4597 break;
4598 }
4599
4600 case SVGA_CMD_BLIT_SCREEN_TO_GMRFB:
4601 {
4602 SVGAFifoCmdBlitScreenToGMRFB *pCmd;
4603 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdBlitScreenToGMRFB, sizeof(*pCmd));
4604 vmsvgaR3CmdBlitScreenToGMRFB(pThis, pThisCC, pCmd);
4605 break;
4606 }
4607
4608 case SVGA_CMD_ANNOTATION_FILL:
4609 {
4610 SVGAFifoCmdAnnotationFill *pCmd;
4611 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdAnnotationFill, sizeof(*pCmd));
4612 vmsvgaR3CmdAnnotationFill(pThis, pThisCC, pCmd);
4613 break;
4614 }
4615
4616 case SVGA_CMD_ANNOTATION_COPY:
4617 {
4618 SVGAFifoCmdAnnotationCopy *pCmd;
4619 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pCmd, SVGAFifoCmdAnnotationCopy, sizeof(*pCmd));
4620 vmsvgaR3CmdAnnotationCopy(pThis, pThisCC, pCmd);
4621 break;
4622 }
4623
4624 default:
4625# ifdef VBOX_WITH_VMSVGA3D
4626 if ( (int)enmCmdId >= SVGA_3D_CMD_BASE
4627 && (int)enmCmdId < SVGA_3D_CMD_MAX)
4628 {
4629 RT_UNTRUSTED_VALIDATED_FENCE();
4630
4631 /* All 3d commands start with a common header, which defines the identifier and the size
4632 * of the command. The identifier has been already read from FIFO. Fetch the size.
4633 */
4634 uint32_t *pcbCmd;
4635 VMSVGAFIFO_GET_CMD_BUFFER_BREAK(pcbCmd, uint32_t, sizeof(*pcbCmd));
4636 uint32_t const cbCmd = *pcbCmd;
4637 AssertBreak(cbCmd < pThis->svga.cbFIFO);
4638 uint32_t *pu32Cmd;
4639 VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK(pu32Cmd, uint32_t, sizeof(*pcbCmd) + cbCmd);
4640 pu32Cmd++; /* Skip the command size. */
4641
4642 if (RT_LIKELY(pThis->svga.f3DEnabled))
4643 { /* likely */ }
4644 else
4645 {
4646 LogRelMax(8, ("VMSVGA: 3D disabled, command %d skipped\n", enmCmdId));
4647 break;
4648 }
4649
4650 vmsvgaR3Process3dCmd(pThis, pThisCC, (SVGAFifo3dCmdId)enmCmdId, cbCmd, pu32Cmd);
4651 }
4652 else
4653# endif // VBOX_WITH_VMSVGA3D
4654 {
4655 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoUnkCmds);
4656 AssertMsgFailed(("enmCmdId=%d\n", enmCmdId));
4657 }
4658 }
4659
4660 /* Go to the next slot */
4661 Assert(cbPayload + sizeof(uint32_t) <= offFifoMax - offFifoMin);
4662 offCurrentCmd += RT_ALIGN_32(cbPayload + sizeof(uint32_t), sizeof(uint32_t));
4663 if (offCurrentCmd >= offFifoMax)
4664 {
4665 offCurrentCmd -= offFifoMax - offFifoMin;
4666 Assert(offCurrentCmd >= offFifoMin);
4667 Assert(offCurrentCmd < offFifoMax);
4668 }
4669 ASMAtomicWriteU32(&pFIFO[SVGA_FIFO_STOP], offCurrentCmd);
4670 STAM_REL_COUNTER_INC(&pSVGAState->StatFifoCommands);
4671
4672 /*
4673 * Raise IRQ if required. Must enter the critical section here
4674 * before making final decisions here, otherwise cubebench and
4675 * others may end up waiting forever.
4676 */
4677 if ( u32IrqStatus
4678 || (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FIFO_PROGRESS))
4679 {
4680 int rc2 = PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_IGNORED);
4681 AssertRC(rc2);
4682
4683 /* FIFO progress might trigger an interrupt. */
4684 if (pThis->svga.u32IrqMask & SVGA_IRQFLAG_FIFO_PROGRESS)
4685 {
4686 Log(("vmsvgaR3FifoLoop: fifo progress irq\n"));
4687 u32IrqStatus |= SVGA_IRQFLAG_FIFO_PROGRESS;
4688 }
4689
4690 /* Unmasked IRQ pending? */
4691 if (pThis->svga.u32IrqMask & u32IrqStatus)
4692 {
4693 Log(("vmsvgaR3FifoLoop: Trigger interrupt with status %x\n", u32IrqStatus));
4694 ASMAtomicOrU32(&pThis->svga.u32IrqStatus, u32IrqStatus);
4695 PDMDevHlpPCISetIrq(pDevIns, 0, 1);
4696 }
4697
4698 PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect);
4699 }
4700 }
4701
4702 /* If really done, clear the busy flag. */
4703 if (fDone)
4704 {
4705 Log(("vmsvgaR3FifoLoop: emptied the FIFO next=%x stop=%x\n", pFIFO[SVGA_FIFO_NEXT_CMD], offCurrentCmd));
4706 vmsvgaR3FifoSetNotBusy(pDevIns, pThis, pThisCC, pSVGAState, offFifoMin);
4707 }
4708 }
4709
4710 /*
4711 * Free the bounce buffer. (There are no returns above!)
4712 */
4713 RTMemFree(pbBounceBuf);
4714
4715 return VINF_SUCCESS;
4716}
4717
4718#undef VMSVGAFIFO_GET_MORE_CMD_BUFFER_BREAK
4719#undef VMSVGAFIFO_GET_CMD_BUFFER_BREAK
4720
4721/**
4722 * @callback_method_impl{PFNPDMTHREADWAKEUPDEV,
4723 * Unblock the FIFO I/O thread so it can respond to a state change.}
4724 */
4725static DECLCALLBACK(int) vmsvgaR3FifoLoopWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
4726{
4727 RT_NOREF(pDevIns);
4728 PVGASTATE pThis = (PVGASTATE)pThread->pvUser;
4729 Log(("vmsvgaR3FifoLoopWakeUp\n"));
4730 return PDMDevHlpSUPSemEventSignal(pDevIns, pThis->svga.hFIFORequestSem);
4731}
4732
4733/**
4734 * Enables or disables dirty page tracking for the framebuffer
4735 *
4736 * @param pDevIns The device instance.
4737 * @param pThis The shared VGA/VMSVGA instance data.
4738 * @param fTraces Enable/disable traces
4739 */
4740static void vmsvgaR3SetTraces(PPDMDEVINS pDevIns, PVGASTATE pThis, bool fTraces)
4741{
4742 if ( (!pThis->svga.fConfigured || !pThis->svga.fEnabled)
4743 && !fTraces)
4744 {
4745 //Assert(pThis->svga.fTraces);
4746 Log(("vmsvgaR3SetTraces: *not* allowed to disable dirty page tracking when the device is in legacy mode.\n"));
4747 return;
4748 }
4749
4750 pThis->svga.fTraces = fTraces;
4751 if (pThis->svga.fTraces)
4752 {
4753 unsigned cbFrameBuffer = pThis->vram_size;
4754
4755 Log(("vmsvgaR3SetTraces: enable dirty page handling for the frame buffer only (%x bytes)\n", 0));
4756 /** @todo How does this work with screens? */
4757 if (pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
4758 {
4759# ifndef DEBUG_bird /* BB-10.3.1 triggers this as it initializes everything to zero. Better just ignore it. */
4760 Assert(pThis->svga.cbScanline);
4761# endif
4762 /* Hardware enabled; return real framebuffer size .*/
4763 cbFrameBuffer = (uint32_t)pThis->svga.uHeight * pThis->svga.cbScanline;
4764 cbFrameBuffer = RT_ALIGN(cbFrameBuffer, PAGE_SIZE);
4765 }
4766
4767 if (!pThis->svga.fVRAMTracking)
4768 {
4769 Log(("vmsvgaR3SetTraces: enable frame buffer dirty page tracking. (%x bytes; vram %x)\n", cbFrameBuffer, pThis->vram_size));
4770 vgaR3RegisterVRAMHandler(pDevIns, pThis, cbFrameBuffer);
4771 pThis->svga.fVRAMTracking = true;
4772 }
4773 }
4774 else
4775 {
4776 if (pThis->svga.fVRAMTracking)
4777 {
4778 Log(("vmsvgaR3SetTraces: disable frame buffer dirty page tracking\n"));
4779 vgaR3UnregisterVRAMHandler(pDevIns, pThis);
4780 pThis->svga.fVRAMTracking = false;
4781 }
4782 }
4783}
4784
4785/**
4786 * @callback_method_impl{FNPCIIOREGIONMAP}
4787 */
4788DECLCALLBACK(int) vmsvgaR3PciIORegionFifoMapUnmap(PPDMDEVINS pDevIns, PPDMPCIDEV pPciDev, uint32_t iRegion,
4789 RTGCPHYS GCPhysAddress, RTGCPHYS cb, PCIADDRESSSPACE enmType)
4790{
4791 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
4792 int rc;
4793 RT_NOREF(pPciDev);
4794 Assert(pPciDev == pDevIns->apPciDevs[0]);
4795
4796 Log(("vmsvgaR3PciIORegionFifoMapUnmap: iRegion=%d GCPhysAddress=%RGp cb=%RGp enmType=%d\n", iRegion, GCPhysAddress, cb, enmType));
4797 AssertReturn( iRegion == pThis->pciRegions.iFIFO
4798 && ( enmType == PCI_ADDRESS_SPACE_MEM
4799 || (enmType == PCI_ADDRESS_SPACE_MEM_PREFETCH /* got wrong in 6.1.0RC1 */ && pThis->fStateLoaded))
4800 , VERR_INTERNAL_ERROR);
4801 if (GCPhysAddress != NIL_RTGCPHYS)
4802 {
4803 /*
4804 * Mapping the FIFO RAM.
4805 */
4806 AssertLogRelMsg(cb == pThis->svga.cbFIFO, ("cb=%#RGp cbFIFO=%#x\n", cb, pThis->svga.cbFIFO));
4807 rc = PDMDevHlpMmio2Map(pDevIns, pThis->hMmio2VmSvgaFifo, GCPhysAddress);
4808 AssertRC(rc);
4809
4810# if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
4811 if (RT_SUCCESS(rc))
4812 {
4813 rc = PGMHandlerPhysicalRegister(PDMDevHlpGetVM(pDevIns), GCPhysAddress,
4814# ifdef DEBUG_FIFO_ACCESS
4815 GCPhysAddress + (pThis->svga.cbFIFO - 1),
4816# else
4817 GCPhysAddress + PAGE_SIZE - 1,
4818# endif
4819 pThis->svga.hFifoAccessHandlerType, pThis, NIL_RTR0PTR, NIL_RTRCPTR,
4820 "VMSVGA FIFO");
4821 AssertRC(rc);
4822 }
4823# endif
4824 if (RT_SUCCESS(rc))
4825 {
4826 pThis->svga.GCPhysFIFO = GCPhysAddress;
4827 Log(("vmsvgaR3IORegionMap: GCPhysFIFO=%RGp cbFIFO=%#x\n", GCPhysAddress, pThis->svga.cbFIFO));
4828 }
4829 rc = VINF_PCI_MAPPING_DONE; /* caller only cares about this status, so it is okay that we overwrite errors here. */
4830 }
4831 else
4832 {
4833 Assert(pThis->svga.GCPhysFIFO);
4834# if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
4835 rc = PGMHandlerPhysicalDeregister(PDMDevHlpGetVM(pDevIns), pThis->svga.GCPhysFIFO);
4836 AssertRC(rc);
4837# else
4838 rc = VINF_SUCCESS;
4839# endif
4840 pThis->svga.GCPhysFIFO = 0;
4841 }
4842 return rc;
4843}
4844
4845# ifdef VBOX_WITH_VMSVGA3D
4846
4847/**
4848 * Used by vmsvga3dInfoSurfaceWorker to make the FIFO thread to save one or all
4849 * surfaces to VMSVGA3DMIPMAPLEVEL::pSurfaceData heap buffers.
4850 *
4851 * @param pDevIns The device instance.
4852 * @param pThis The The shared VGA/VMSVGA instance data.
4853 * @param pThisCC The VGA/VMSVGA state for ring-3.
4854 * @param sid Either UINT32_MAX or the ID of a specific surface. If
4855 * UINT32_MAX is used, all surfaces are processed.
4856 */
4857void vmsvgaR33dSurfaceUpdateHeapBuffersOnFifoThread(PPDMDEVINS pDevIns, PVGASTATE pThis, PVGASTATECC pThisCC, uint32_t sid)
4858{
4859 vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC, VMSVGA_FIFO_EXTCMD_UPDATE_SURFACE_HEAP_BUFFERS, (void *)(uintptr_t)sid,
4860 sid == UINT32_MAX ? 10 * RT_MS_1SEC : RT_MS_1MIN);
4861}
4862
4863
4864/**
4865 * @callback_method_impl{FNDBGFHANDLERDEV, "vmsvga3dsfc"}
4866 */
4867DECLCALLBACK(void) vmsvgaR3Info3dSurface(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
4868{
4869 /* There might be a specific surface ID at the start of the
4870 arguments, if not show all surfaces. */
4871 uint32_t sid = UINT32_MAX;
4872 if (pszArgs)
4873 pszArgs = RTStrStripL(pszArgs);
4874 if (pszArgs && RT_C_IS_DIGIT(*pszArgs))
4875 sid = RTStrToUInt32(pszArgs);
4876
4877 /* Verbose or terse display, we default to verbose. */
4878 bool fVerbose = true;
4879 if (RTStrIStr(pszArgs, "terse"))
4880 fVerbose = false;
4881
4882 /* The size of the ascii art (x direction, y is 3/4 of x). */
4883 uint32_t cxAscii = 80;
4884 if (RTStrIStr(pszArgs, "gigantic"))
4885 cxAscii = 300;
4886 else if (RTStrIStr(pszArgs, "huge"))
4887 cxAscii = 180;
4888 else if (RTStrIStr(pszArgs, "big"))
4889 cxAscii = 132;
4890 else if (RTStrIStr(pszArgs, "normal"))
4891 cxAscii = 80;
4892 else if (RTStrIStr(pszArgs, "medium"))
4893 cxAscii = 64;
4894 else if (RTStrIStr(pszArgs, "small"))
4895 cxAscii = 48;
4896 else if (RTStrIStr(pszArgs, "tiny"))
4897 cxAscii = 24;
4898
4899 /* Y invert the image when producing the ASCII art. */
4900 bool fInvY = false;
4901 if (RTStrIStr(pszArgs, "invy"))
4902 fInvY = true;
4903
4904 vmsvga3dInfoSurfaceWorker(pDevIns, PDMDEVINS_2_DATA(pDevIns, PVGASTATE), PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC),
4905 pHlp, sid, fVerbose, cxAscii, fInvY, NULL);
4906}
4907
4908
4909/**
4910 * @callback_method_impl{FNDBGFHANDLERDEV, "vmsvga3dsurf"}
4911 */
4912DECLCALLBACK(void) vmsvgaR3Info3dSurfaceBmp(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
4913{
4914 /* pszArg = "sid[>dir]"
4915 * Writes %dir%/info-S-sidI.bmp, where S - sequential bitmap number, I - decimal surface id.
4916 */
4917 char *pszBitmapPath = NULL;
4918 uint32_t sid = UINT32_MAX;
4919 if (pszArgs)
4920 pszArgs = RTStrStripL(pszArgs);
4921 if (pszArgs && RT_C_IS_DIGIT(*pszArgs))
4922 RTStrToUInt32Ex(pszArgs, &pszBitmapPath, 0, &sid);
4923 if ( pszBitmapPath
4924 && *pszBitmapPath == '>')
4925 ++pszBitmapPath;
4926
4927 const bool fVerbose = true;
4928 const uint32_t cxAscii = 0; /* No ASCII */
4929 const bool fInvY = false; /* Do not invert. */
4930 vmsvga3dInfoSurfaceWorker(pDevIns, PDMDEVINS_2_DATA(pDevIns, PVGASTATE), PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC),
4931 pHlp, sid, fVerbose, cxAscii, fInvY, pszBitmapPath);
4932}
4933
4934/**
4935 * @callback_method_impl{FNDBGFHANDLERDEV, "vmsvga3dctx"}
4936 */
4937DECLCALLBACK(void) vmsvgaR3Info3dContext(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
4938{
4939 /* There might be a specific surface ID at the start of the
4940 arguments, if not show all contexts. */
4941 uint32_t sid = UINT32_MAX;
4942 if (pszArgs)
4943 pszArgs = RTStrStripL(pszArgs);
4944 if (pszArgs && RT_C_IS_DIGIT(*pszArgs))
4945 sid = RTStrToUInt32(pszArgs);
4946
4947 /* Verbose or terse display, we default to verbose. */
4948 bool fVerbose = true;
4949 if (RTStrIStr(pszArgs, "terse"))
4950 fVerbose = false;
4951
4952 vmsvga3dInfoContextWorker(PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC), pHlp, sid, fVerbose);
4953}
4954# endif /* VBOX_WITH_VMSVGA3D */
4955
4956/**
4957 * @callback_method_impl{FNDBGFHANDLERDEV, "vmsvga"}
4958 */
4959static DECLCALLBACK(void) vmsvgaR3Info(PPDMDEVINS pDevIns, PCDBGFINFOHLP pHlp, const char *pszArgs)
4960{
4961 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
4962 PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
4963 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
4964 uint32_t RT_UNTRUSTED_VOLATILE_GUEST *pFIFO = pThisCC->svga.pau32FIFO;
4965 RT_NOREF(pszArgs);
4966
4967 pHlp->pfnPrintf(pHlp, "Extension enabled: %RTbool\n", pThis->svga.fEnabled);
4968 pHlp->pfnPrintf(pHlp, "Configured: %RTbool\n", pThis->svga.fConfigured);
4969 pHlp->pfnPrintf(pHlp, "Base I/O port: %#x\n",
4970 pThis->hIoPortVmSvga != NIL_IOMIOPORTHANDLE
4971 ? PDMDevHlpIoPortGetMappingAddress(pDevIns, pThis->hIoPortVmSvga) : UINT32_MAX);
4972 pHlp->pfnPrintf(pHlp, "FIFO address: %RGp\n", pThis->svga.GCPhysFIFO);
4973 pHlp->pfnPrintf(pHlp, "FIFO size: %u (%#x)\n", pThis->svga.cbFIFO, pThis->svga.cbFIFO);
4974 pHlp->pfnPrintf(pHlp, "FIFO external cmd: %#x\n", pThis->svga.u8FIFOExtCommand);
4975 pHlp->pfnPrintf(pHlp, "FIFO extcmd wakeup: %u\n", pThis->svga.fFifoExtCommandWakeup);
4976 pHlp->pfnPrintf(pHlp, "FIFO min/max: %u/%u\n", pFIFO[SVGA_FIFO_MIN], pFIFO[SVGA_FIFO_MAX]);
4977 pHlp->pfnPrintf(pHlp, "Busy: %#x\n", pThis->svga.fBusy);
4978 pHlp->pfnPrintf(pHlp, "Traces: %RTbool (effective: %RTbool)\n", pThis->svga.fTraces, pThis->svga.fVRAMTracking);
4979 pHlp->pfnPrintf(pHlp, "Guest ID: %#x (%d)\n", pThis->svga.u32GuestId, pThis->svga.u32GuestId);
4980 pHlp->pfnPrintf(pHlp, "IRQ status: %#x\n", pThis->svga.u32IrqStatus);
4981 pHlp->pfnPrintf(pHlp, "IRQ mask: %#x\n", pThis->svga.u32IrqMask);
4982 pHlp->pfnPrintf(pHlp, "Pitch lock: %#x (FIFO:%#x)\n", pThis->svga.u32PitchLock, pFIFO[SVGA_FIFO_PITCHLOCK]);
4983 pHlp->pfnPrintf(pHlp, "Current GMR ID: %#x\n", pThis->svga.u32CurrentGMRId);
4984 pHlp->pfnPrintf(pHlp, "Device Capabilites: %#x\n", pThis->svga.u32DeviceCaps);
4985 pHlp->pfnPrintf(pHlp, "Index reg: %#x\n", pThis->svga.u32IndexReg);
4986 pHlp->pfnPrintf(pHlp, "Action flags: %#x\n", pThis->svga.u32ActionFlags);
4987 pHlp->pfnPrintf(pHlp, "Max display size: %ux%u\n", pThis->svga.u32MaxWidth, pThis->svga.u32MaxHeight);
4988 pHlp->pfnPrintf(pHlp, "Display size: %ux%u %ubpp\n", pThis->svga.uWidth, pThis->svga.uHeight, pThis->svga.uBpp);
4989 pHlp->pfnPrintf(pHlp, "Scanline: %u (%#x)\n", pThis->svga.cbScanline, pThis->svga.cbScanline);
4990 pHlp->pfnPrintf(pHlp, "Viewport position: %ux%u\n", pThis->svga.viewport.x, pThis->svga.viewport.y);
4991 pHlp->pfnPrintf(pHlp, "Viewport size: %ux%u\n", pThis->svga.viewport.cx, pThis->svga.viewport.cy);
4992
4993 pHlp->pfnPrintf(pHlp, "Cursor active: %RTbool\n", pSVGAState->Cursor.fActive);
4994 pHlp->pfnPrintf(pHlp, "Cursor hotspot: %ux%u\n", pSVGAState->Cursor.xHotspot, pSVGAState->Cursor.yHotspot);
4995 pHlp->pfnPrintf(pHlp, "Cursor size: %ux%u\n", pSVGAState->Cursor.width, pSVGAState->Cursor.height);
4996 pHlp->pfnPrintf(pHlp, "Cursor byte size: %u (%#x)\n", pSVGAState->Cursor.cbData, pSVGAState->Cursor.cbData);
4997
4998 pHlp->pfnPrintf(pHlp, "FIFO cursor: state %u, screen %d\n", pFIFO[SVGA_FIFO_CURSOR_ON], pFIFO[SVGA_FIFO_CURSOR_SCREEN_ID]);
4999 pHlp->pfnPrintf(pHlp, "FIFO cursor at: %u,%u\n", pFIFO[SVGA_FIFO_CURSOR_X], pFIFO[SVGA_FIFO_CURSOR_Y]);
5000
5001 pHlp->pfnPrintf(pHlp, "Legacy cursor: ID %u, state %u\n", pThis->svga.uCursorID, pThis->svga.uCursorOn);
5002 pHlp->pfnPrintf(pHlp, "Legacy cursor at: %u,%u\n", pThis->svga.uCursorX, pThis->svga.uCursorY);
5003
5004# ifdef VBOX_WITH_VMSVGA3D
5005 pHlp->pfnPrintf(pHlp, "3D enabled: %RTbool\n", pThis->svga.f3DEnabled);
5006# endif
5007 if (pThisCC->pDrv)
5008 {
5009 pHlp->pfnPrintf(pHlp, "Driver mode: %ux%u %ubpp\n", pThisCC->pDrv->cx, pThisCC->pDrv->cy, pThisCC->pDrv->cBits);
5010 pHlp->pfnPrintf(pHlp, "Driver pitch: %u (%#x)\n", pThisCC->pDrv->cbScanline, pThisCC->pDrv->cbScanline);
5011 }
5012
5013 /* Dump screen information. */
5014 for (unsigned iScreen = 0; iScreen < RT_ELEMENTS(pSVGAState->aScreens); ++iScreen)
5015 {
5016 VMSVGASCREENOBJECT *pScreen = vmsvgaR3GetScreenObject(pThisCC, iScreen);
5017 if (pScreen)
5018 {
5019 pHlp->pfnPrintf(pHlp, "Screen %u defined (ID %u):\n", iScreen, pScreen->idScreen);
5020 pHlp->pfnPrintf(pHlp, " %u x %u x %ubpp @ %u, %u\n", pScreen->cWidth, pScreen->cHeight,
5021 pScreen->cBpp, pScreen->xOrigin, pScreen->yOrigin);
5022 pHlp->pfnPrintf(pHlp, " Pitch %u bytes, VRAM offset %X\n", pScreen->cbPitch, pScreen->offVRAM);
5023 pHlp->pfnPrintf(pHlp, " Flags %X", pScreen->fuScreen);
5024 if (pScreen->fuScreen != SVGA_SCREEN_MUST_BE_SET)
5025 {
5026 pHlp->pfnPrintf(pHlp, " (");
5027 if (pScreen->fuScreen & SVGA_SCREEN_IS_PRIMARY)
5028 pHlp->pfnPrintf(pHlp, " IS_PRIMARY");
5029 if (pScreen->fuScreen & SVGA_SCREEN_FULLSCREEN_HINT)
5030 pHlp->pfnPrintf(pHlp, " FULLSCREEN_HINT");
5031 if (pScreen->fuScreen & SVGA_SCREEN_DEACTIVATE)
5032 pHlp->pfnPrintf(pHlp, " DEACTIVATE");
5033 if (pScreen->fuScreen & SVGA_SCREEN_BLANKING)
5034 pHlp->pfnPrintf(pHlp, " BLANKING");
5035 pHlp->pfnPrintf(pHlp, " )");
5036 }
5037 pHlp->pfnPrintf(pHlp, ", %smodified\n", pScreen->fModified ? "" : "not ");
5038 }
5039 }
5040
5041}
5042
5043/**
5044 * Portion of VMSVGA state which must be loaded oin the FIFO thread.
5045 */
5046static int vmsvgaR3LoadExecFifo(PCPDMDEVHLPR3 pHlp, PVGASTATE pThis, PVGASTATECC pThisCC,
5047 PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
5048{
5049 RT_NOREF(uPass);
5050
5051 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
5052 int rc;
5053
5054 if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_SCREENS)
5055 {
5056 uint32_t cScreens = 0;
5057 rc = pHlp->pfnSSMGetU32(pSSM, &cScreens);
5058 AssertRCReturn(rc, rc);
5059 AssertLogRelMsgReturn(cScreens <= _64K, /* big enough */
5060 ("cScreens=%#x\n", cScreens),
5061 VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
5062
5063 for (uint32_t i = 0; i < cScreens; ++i)
5064 {
5065 VMSVGASCREENOBJECT screen;
5066 RT_ZERO(screen);
5067
5068 rc = pHlp->pfnSSMGetStructEx(pSSM, &screen, sizeof(screen), 0, g_aVMSVGASCREENOBJECTFields, NULL);
5069 AssertLogRelRCReturn(rc, rc);
5070
5071 if (screen.idScreen < RT_ELEMENTS(pSVGAState->aScreens))
5072 {
5073 VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[screen.idScreen];
5074 *pScreen = screen;
5075 pScreen->fModified = true;
5076 }
5077 else
5078 {
5079 LogRel(("VGA: ignored screen object %d\n", screen.idScreen));
5080 }
5081 }
5082 }
5083 else
5084 {
5085 /* Try to setup at least the first screen. */
5086 VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[0];
5087 pScreen->fDefined = true;
5088 pScreen->fModified = true;
5089 pScreen->fuScreen = SVGA_SCREEN_MUST_BE_SET | SVGA_SCREEN_IS_PRIMARY;
5090 pScreen->idScreen = 0;
5091 pScreen->xOrigin = 0;
5092 pScreen->yOrigin = 0;
5093 pScreen->offVRAM = pThis->svga.uScreenOffset;
5094 pScreen->cbPitch = pThis->svga.cbScanline;
5095 pScreen->cWidth = pThis->svga.uWidth;
5096 pScreen->cHeight = pThis->svga.uHeight;
5097 pScreen->cBpp = pThis->svga.uBpp;
5098 }
5099
5100 return VINF_SUCCESS;
5101}
5102
5103/**
5104 * @copydoc FNSSMDEVLOADEXEC
5105 */
5106int vmsvgaR3LoadExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM, uint32_t uVersion, uint32_t uPass)
5107{
5108 RT_NOREF(uPass);
5109 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
5110 PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
5111 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
5112 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
5113 int rc;
5114
5115 /* Load our part of the VGAState */
5116 rc = pHlp->pfnSSMGetStructEx(pSSM, &pThis->svga, sizeof(pThis->svga), 0, g_aVGAStateSVGAFields, NULL);
5117 AssertRCReturn(rc, rc);
5118
5119 /* Load the VGA framebuffer. */
5120 AssertCompile(VMSVGA_VGA_FB_BACKUP_SIZE >= _32K);
5121 uint32_t cbVgaFramebuffer = _32K;
5122 if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_VGA_FB_FIX)
5123 {
5124 rc = pHlp->pfnSSMGetU32(pSSM, &cbVgaFramebuffer);
5125 AssertRCReturn(rc, rc);
5126 AssertLogRelMsgReturn(cbVgaFramebuffer <= _4M && cbVgaFramebuffer >= _32K && RT_IS_POWER_OF_TWO(cbVgaFramebuffer),
5127 ("cbVgaFramebuffer=%#x - expected 32KB..4MB, power of two\n", cbVgaFramebuffer),
5128 VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
5129 AssertCompile(VMSVGA_VGA_FB_BACKUP_SIZE <= _4M);
5130 AssertCompile(RT_IS_POWER_OF_TWO(VMSVGA_VGA_FB_BACKUP_SIZE));
5131 }
5132 rc = pHlp->pfnSSMGetMem(pSSM, pThisCC->svga.pbVgaFrameBufferR3, RT_MIN(cbVgaFramebuffer, VMSVGA_VGA_FB_BACKUP_SIZE));
5133 AssertRCReturn(rc, rc);
5134 if (cbVgaFramebuffer > VMSVGA_VGA_FB_BACKUP_SIZE)
5135 pHlp->pfnSSMSkip(pSSM, cbVgaFramebuffer - VMSVGA_VGA_FB_BACKUP_SIZE);
5136 else if (cbVgaFramebuffer < VMSVGA_VGA_FB_BACKUP_SIZE)
5137 RT_BZERO(&pThisCC->svga.pbVgaFrameBufferR3[cbVgaFramebuffer], VMSVGA_VGA_FB_BACKUP_SIZE - cbVgaFramebuffer);
5138
5139 /* Load the VMSVGA state. */
5140 rc = pHlp->pfnSSMGetStructEx(pSSM, pSVGAState, sizeof(*pSVGAState), 0, g_aVMSVGAR3STATEFields, NULL);
5141 AssertRCReturn(rc, rc);
5142
5143 /* Load the active cursor bitmaps. */
5144 if (pSVGAState->Cursor.fActive)
5145 {
5146 pSVGAState->Cursor.pData = RTMemAlloc(pSVGAState->Cursor.cbData);
5147 AssertReturn(pSVGAState->Cursor.pData, VERR_NO_MEMORY);
5148
5149 rc = pHlp->pfnSSMGetMem(pSSM, pSVGAState->Cursor.pData, pSVGAState->Cursor.cbData);
5150 AssertRCReturn(rc, rc);
5151 }
5152
5153 /* Load the GMR state. */
5154 uint32_t cGMR = 256; /* Hardcoded in previous saved state versions. */
5155 if (uVersion >= VGA_SAVEDSTATE_VERSION_VMSVGA_GMR_COUNT)
5156 {
5157 rc = pHlp->pfnSSMGetU32(pSSM, &cGMR);
5158 AssertRCReturn(rc, rc);
5159 /* Numbers of GMRs was never less than 256. 1MB is a large arbitrary limit. */
5160 AssertLogRelMsgReturn(cGMR <= _1M && cGMR >= 256,
5161 ("cGMR=%#x - expected 256B..1MB\n", cGMR),
5162 VERR_SSM_DATA_UNIT_FORMAT_CHANGED);
5163 }
5164
5165 if (pThis->svga.cGMR != cGMR)
5166 {
5167 /* Reallocate GMR array. */
5168 Assert(pSVGAState->paGMR != NULL);
5169 RTMemFree(pSVGAState->paGMR);
5170 pSVGAState->paGMR = (PGMR)RTMemAllocZ(cGMR * sizeof(GMR));
5171 AssertReturn(pSVGAState->paGMR, VERR_NO_MEMORY);
5172 pThis->svga.cGMR = cGMR;
5173 }
5174
5175 for (uint32_t i = 0; i < cGMR; ++i)
5176 {
5177 PGMR pGMR = &pSVGAState->paGMR[i];
5178
5179 rc = pHlp->pfnSSMGetStructEx(pSSM, pGMR, sizeof(*pGMR), 0, g_aGMRFields, NULL);
5180 AssertRCReturn(rc, rc);
5181
5182 if (pGMR->numDescriptors)
5183 {
5184 Assert(pGMR->cMaxPages || pGMR->cbTotal);
5185 pGMR->paDesc = (PVMSVGAGMRDESCRIPTOR)RTMemAllocZ(pGMR->numDescriptors * sizeof(VMSVGAGMRDESCRIPTOR));
5186 AssertReturn(pGMR->paDesc, VERR_NO_MEMORY);
5187
5188 for (uint32_t j = 0; j < pGMR->numDescriptors; ++j)
5189 {
5190 rc = pHlp->pfnSSMGetStructEx(pSSM, &pGMR->paDesc[j], sizeof(pGMR->paDesc[j]), 0, g_aVMSVGAGMRDESCRIPTORFields, NULL);
5191 AssertRCReturn(rc, rc);
5192 }
5193 }
5194 }
5195
5196# ifdef RT_OS_DARWIN /** @todo r=bird: this is normally done on the EMT, so for DARWIN we do that when loading saved state too now. See DevVGA-SVGA3d-shared.h. */
5197 vmsvga3dPowerOn(pDevIns, pThis, PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC));
5198# endif
5199
5200 VMSVGA_STATE_LOAD LoadState;
5201 LoadState.pSSM = pSSM;
5202 LoadState.uVersion = uVersion;
5203 LoadState.uPass = uPass;
5204 rc = vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC, VMSVGA_FIFO_EXTCMD_LOADSTATE, &LoadState, RT_INDEFINITE_WAIT);
5205 AssertLogRelRCReturn(rc, rc);
5206
5207 return VINF_SUCCESS;
5208}
5209
5210/**
5211 * Reinit the video mode after the state has been loaded.
5212 */
5213int vmsvgaR3LoadDone(PPDMDEVINS pDevIns)
5214{
5215 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
5216 PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
5217 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
5218
5219 /* Set the active cursor. */
5220 if (pSVGAState->Cursor.fActive)
5221 {
5222 /* We don't store the alpha flag, but we can take a guess that if
5223 * the old register interface was used, the cursor was B&W.
5224 */
5225 bool fAlpha = pThis->svga.uCursorOn ? false : true;
5226
5227 int rc = pThisCC->pDrv->pfnVBVAMousePointerShape(pThisCC->pDrv,
5228 true /*fVisible*/,
5229 fAlpha,
5230 pSVGAState->Cursor.xHotspot,
5231 pSVGAState->Cursor.yHotspot,
5232 pSVGAState->Cursor.width,
5233 pSVGAState->Cursor.height,
5234 pSVGAState->Cursor.pData);
5235 AssertRC(rc);
5236
5237 if (pThis->svga.uCursorOn)
5238 pThisCC->pDrv->pfnVBVAReportCursorPosition(pThisCC->pDrv, VBVA_CURSOR_VALID_DATA, SVGA_ID_INVALID, pThis->svga.uCursorX, pThis->svga.uCursorY);
5239 }
5240
5241 /* If the VRAM handler should not be registered, we have to explicitly
5242 * unregister it here!
5243 */
5244 if (!pThis->svga.fVRAMTracking)
5245 {
5246 vgaR3UnregisterVRAMHandler(pDevIns, pThis);
5247 }
5248
5249 /* Let the FIFO thread deal with changing the mode. */
5250 ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
5251
5252 return VINF_SUCCESS;
5253}
5254
5255/**
5256 * Portion of SVGA state which must be saved in the FIFO thread.
5257 */
5258static int vmsvgaR3SaveExecFifo(PCPDMDEVHLPR3 pHlp, PVGASTATECC pThisCC, PSSMHANDLE pSSM)
5259{
5260 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
5261 int rc;
5262
5263 /* Save the screen objects. */
5264 /* Count defined screen object. */
5265 uint32_t cScreens = 0;
5266 for (uint32_t i = 0; i < RT_ELEMENTS(pSVGAState->aScreens); ++i)
5267 {
5268 if (pSVGAState->aScreens[i].fDefined)
5269 ++cScreens;
5270 }
5271
5272 rc = pHlp->pfnSSMPutU32(pSSM, cScreens);
5273 AssertLogRelRCReturn(rc, rc);
5274
5275 for (uint32_t i = 0; i < cScreens; ++i)
5276 {
5277 VMSVGASCREENOBJECT *pScreen = &pSVGAState->aScreens[i];
5278
5279 rc = pHlp->pfnSSMPutStructEx(pSSM, pScreen, sizeof(*pScreen), 0, g_aVMSVGASCREENOBJECTFields, NULL);
5280 AssertLogRelRCReturn(rc, rc);
5281 }
5282 return VINF_SUCCESS;
5283}
5284
5285/**
5286 * @copydoc FNSSMDEVSAVEEXEC
5287 */
5288int vmsvgaR3SaveExec(PPDMDEVINS pDevIns, PSSMHANDLE pSSM)
5289{
5290 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
5291 PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
5292 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
5293 PCPDMDEVHLPR3 pHlp = pDevIns->pHlpR3;
5294 int rc;
5295
5296 /* Save our part of the VGAState */
5297 rc = pHlp->pfnSSMPutStructEx(pSSM, &pThis->svga, sizeof(pThis->svga), 0, g_aVGAStateSVGAFields, NULL);
5298 AssertLogRelRCReturn(rc, rc);
5299
5300 /* Save the framebuffer backup. */
5301 rc = pHlp->pfnSSMPutU32(pSSM, VMSVGA_VGA_FB_BACKUP_SIZE);
5302 rc = pHlp->pfnSSMPutMem(pSSM, pThisCC->svga.pbVgaFrameBufferR3, VMSVGA_VGA_FB_BACKUP_SIZE);
5303 AssertLogRelRCReturn(rc, rc);
5304
5305 /* Save the VMSVGA state. */
5306 rc = pHlp->pfnSSMPutStructEx(pSSM, pSVGAState, sizeof(*pSVGAState), 0, g_aVMSVGAR3STATEFields, NULL);
5307 AssertLogRelRCReturn(rc, rc);
5308
5309 /* Save the active cursor bitmaps. */
5310 if (pSVGAState->Cursor.fActive)
5311 {
5312 rc = pHlp->pfnSSMPutMem(pSSM, pSVGAState->Cursor.pData, pSVGAState->Cursor.cbData);
5313 AssertLogRelRCReturn(rc, rc);
5314 }
5315
5316 /* Save the GMR state */
5317 rc = pHlp->pfnSSMPutU32(pSSM, pThis->svga.cGMR);
5318 AssertLogRelRCReturn(rc, rc);
5319 for (uint32_t i = 0; i < pThis->svga.cGMR; ++i)
5320 {
5321 PGMR pGMR = &pSVGAState->paGMR[i];
5322
5323 rc = pHlp->pfnSSMPutStructEx(pSSM, pGMR, sizeof(*pGMR), 0, g_aGMRFields, NULL);
5324 AssertLogRelRCReturn(rc, rc);
5325
5326 for (uint32_t j = 0; j < pGMR->numDescriptors; ++j)
5327 {
5328 rc = pHlp->pfnSSMPutStructEx(pSSM, &pGMR->paDesc[j], sizeof(pGMR->paDesc[j]), 0, g_aVMSVGAGMRDESCRIPTORFields, NULL);
5329 AssertLogRelRCReturn(rc, rc);
5330 }
5331 }
5332
5333 /*
5334 * Must save some state (3D in particular) in the FIFO thread.
5335 */
5336 rc = vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC, VMSVGA_FIFO_EXTCMD_SAVESTATE, pSSM, RT_INDEFINITE_WAIT);
5337 AssertLogRelRCReturn(rc, rc);
5338
5339 return VINF_SUCCESS;
5340}
5341
5342/**
5343 * Destructor for PVMSVGAR3STATE structure.
5344 *
5345 * @param pThis The shared VGA/VMSVGA instance data.
5346 * @param pSVGAState Pointer to the structure. It is not deallocated.
5347 */
5348static void vmsvgaR3StateTerm(PVGASTATE pThis, PVMSVGAR3STATE pSVGAState)
5349{
5350# ifndef VMSVGA_USE_EMT_HALT_CODE
5351 if (pSVGAState->hBusyDelayedEmts != NIL_RTSEMEVENTMULTI)
5352 {
5353 RTSemEventMultiDestroy(pSVGAState->hBusyDelayedEmts);
5354 pSVGAState->hBusyDelayedEmts = NIL_RTSEMEVENT;
5355 }
5356# endif
5357
5358 if (pSVGAState->Cursor.fActive)
5359 {
5360 RTMemFreeZ(pSVGAState->Cursor.pData, pSVGAState->Cursor.cbData);
5361 pSVGAState->Cursor.pData = NULL;
5362 pSVGAState->Cursor.fActive = false;
5363 }
5364
5365 if (pSVGAState->paGMR)
5366 {
5367 for (unsigned i = 0; i < pThis->svga.cGMR; ++i)
5368 if (pSVGAState->paGMR[i].paDesc)
5369 RTMemFree(pSVGAState->paGMR[i].paDesc);
5370
5371 RTMemFree(pSVGAState->paGMR);
5372 pSVGAState->paGMR = NULL;
5373 }
5374
5375 if (RTCritSectIsInitialized(&pSVGAState->CritSectCmdBuf))
5376 {
5377 RTCritSectEnter(&pSVGAState->CritSectCmdBuf);
5378 for (unsigned i = 0; i < RT_ELEMENTS(pSVGAState->apCmdBufCtxs); ++i)
5379 {
5380 vmsvgaR3CmdBufCtxTerm(pSVGAState->apCmdBufCtxs[i]);
5381 pSVGAState->apCmdBufCtxs[i] = NULL;
5382 }
5383 vmsvgaR3CmdBufCtxTerm(&pSVGAState->CmdBufCtxDC);
5384 RTCritSectLeave(&pSVGAState->CritSectCmdBuf);
5385 RTCritSectDelete(&pSVGAState->CritSectCmdBuf);
5386 }
5387}
5388
5389/**
5390 * Constructor for PVMSVGAR3STATE structure.
5391 *
5392 * @returns VBox status code.
5393 * @param pDevIns The PDM device instance.
5394 * @param pThis The shared VGA/VMSVGA instance data.
5395 * @param pSVGAState Pointer to the structure. It is already allocated.
5396 */
5397static int vmsvgaR3StateInit(PPDMDEVINS pDevIns, PVGASTATE pThis, PVMSVGAR3STATE pSVGAState)
5398{
5399 int rc = VINF_SUCCESS;
5400 RT_ZERO(*pSVGAState);
5401 pSVGAState->pDevIns = pDevIns;
5402
5403 pSVGAState->paGMR = (PGMR)RTMemAllocZ(pThis->svga.cGMR * sizeof(GMR));
5404 AssertReturn(pSVGAState->paGMR, VERR_NO_MEMORY);
5405
5406# ifndef VMSVGA_USE_EMT_HALT_CODE
5407 /* Create semaphore for delaying EMTs wait for the FIFO to stop being busy. */
5408 rc = RTSemEventMultiCreate(&pSVGAState->hBusyDelayedEmts);
5409 AssertRCReturn(rc, rc);
5410# endif
5411
5412 rc = RTCritSectInit(&pSVGAState->CritSectCmdBuf);
5413 AssertRCReturn(rc, rc);
5414
5415 vmsvgaR3CmdBufCtxInit(&pSVGAState->CmdBufCtxDC);
5416
5417 RTListInit(&pSVGAState->MOBLRUList);
5418 return rc;
5419}
5420
5421/**
5422 * Initializes the host capabilities: device and FIFO.
5423 *
5424 * @returns VBox status code.
5425 * @param pThis The shared VGA/VMSVGA instance data.
5426 * @param pThisCC The VGA/VMSVGA state for ring-3.
5427 */
5428static void vmsvgaR3InitCaps(PVGASTATE pThis, PVGASTATECC pThisCC)
5429{
5430 /* Device caps. */
5431 pThis->svga.u32DeviceCaps = SVGA_CAP_GMR
5432 | SVGA_CAP_GMR2
5433 | SVGA_CAP_CURSOR
5434 | SVGA_CAP_CURSOR_BYPASS
5435 | SVGA_CAP_CURSOR_BYPASS_2
5436 | SVGA_CAP_EXTENDED_FIFO
5437 | SVGA_CAP_IRQMASK
5438 | SVGA_CAP_PITCHLOCK
5439 | SVGA_CAP_RECT_COPY
5440 | SVGA_CAP_TRACES
5441 | SVGA_CAP_SCREEN_OBJECT_2
5442 | SVGA_CAP_ALPHA_CURSOR;
5443
5444 /* VGPU10 capabilities. */
5445 if (pThis->fVMSVGA10)
5446 {
5447 pThis->svga.u32DeviceCaps |= SVGA_CAP_COMMAND_BUFFERS /* Enable register based command buffer submission. */
5448// | SVGA_CAP_CMD_BUFFERS_2 /* Support for SVGA_REG_CMD_PREPEND_LOW/HIGH */
5449// | SVGA_CAP_GBOBJECTS /* Enable guest-backed objects and surfaces. */
5450// | SVGA_CAP_CMD_BUFFERS_3 /* AKA SVGA_CAP_DX. Enable support for DX commands, and command buffers in a mob. */
5451 ;
5452 }
5453
5454# ifdef VBOX_WITH_VMSVGA3D
5455 pThis->svga.u32DeviceCaps |= SVGA_CAP_3D;
5456# endif
5457
5458 /* Clear the FIFO. */
5459 RT_BZERO(pThisCC->svga.pau32FIFO, pThis->svga.cbFIFO);
5460
5461 /* Setup FIFO capabilities. */
5462 pThisCC->svga.pau32FIFO[SVGA_FIFO_CAPABILITIES] = SVGA_FIFO_CAP_FENCE
5463 | SVGA_FIFO_CAP_PITCHLOCK
5464 | SVGA_FIFO_CAP_CURSOR_BYPASS_3
5465 | SVGA_FIFO_CAP_RESERVE
5466 | SVGA_FIFO_CAP_GMR2
5467 | SVGA_FIFO_CAP_3D_HWVERSION_REVISED
5468 | SVGA_FIFO_CAP_SCREEN_OBJECT_2;
5469
5470 /* Valid with SVGA_FIFO_CAP_SCREEN_OBJECT_2 */
5471 pThisCC->svga.pau32FIFO[SVGA_FIFO_CURSOR_SCREEN_ID] = SVGA_ID_INVALID;
5472}
5473
5474# ifdef VBOX_WITH_VMSVGA3D
5475/** Names for the vmsvga 3d capabilities, prefixed with format type hint char. */
5476static const char * const g_apszVmSvgaDevCapNames[] =
5477{
5478 "x3D", /* = 0 */
5479 "xMAX_LIGHTS",
5480 "xMAX_TEXTURES",
5481 "xMAX_CLIP_PLANES",
5482 "xVERTEX_SHADER_VERSION",
5483 "xVERTEX_SHADER",
5484 "xFRAGMENT_SHADER_VERSION",
5485 "xFRAGMENT_SHADER",
5486 "xMAX_RENDER_TARGETS",
5487 "xS23E8_TEXTURES",
5488 "xS10E5_TEXTURES",
5489 "xMAX_FIXED_VERTEXBLEND",
5490 "xD16_BUFFER_FORMAT",
5491 "xD24S8_BUFFER_FORMAT",
5492 "xD24X8_BUFFER_FORMAT",
5493 "xQUERY_TYPES",
5494 "xTEXTURE_GRADIENT_SAMPLING",
5495 "rMAX_POINT_SIZE",
5496 "xMAX_SHADER_TEXTURES",
5497 "xMAX_TEXTURE_WIDTH",
5498 "xMAX_TEXTURE_HEIGHT",
5499 "xMAX_VOLUME_EXTENT",
5500 "xMAX_TEXTURE_REPEAT",
5501 "xMAX_TEXTURE_ASPECT_RATIO",
5502 "xMAX_TEXTURE_ANISOTROPY",
5503 "xMAX_PRIMITIVE_COUNT",
5504 "xMAX_VERTEX_INDEX",
5505 "xMAX_VERTEX_SHADER_INSTRUCTIONS",
5506 "xMAX_FRAGMENT_SHADER_INSTRUCTIONS",
5507 "xMAX_VERTEX_SHADER_TEMPS",
5508 "xMAX_FRAGMENT_SHADER_TEMPS",
5509 "xTEXTURE_OPS",
5510 "xSURFACEFMT_X8R8G8B8",
5511 "xSURFACEFMT_A8R8G8B8",
5512 "xSURFACEFMT_A2R10G10B10",
5513 "xSURFACEFMT_X1R5G5B5",
5514 "xSURFACEFMT_A1R5G5B5",
5515 "xSURFACEFMT_A4R4G4B4",
5516 "xSURFACEFMT_R5G6B5",
5517 "xSURFACEFMT_LUMINANCE16",
5518 "xSURFACEFMT_LUMINANCE8_ALPHA8",
5519 "xSURFACEFMT_ALPHA8",
5520 "xSURFACEFMT_LUMINANCE8",
5521 "xSURFACEFMT_Z_D16",
5522 "xSURFACEFMT_Z_D24S8",
5523 "xSURFACEFMT_Z_D24X8",
5524 "xSURFACEFMT_DXT1",
5525 "xSURFACEFMT_DXT2",
5526 "xSURFACEFMT_DXT3",
5527 "xSURFACEFMT_DXT4",
5528 "xSURFACEFMT_DXT5",
5529 "xSURFACEFMT_BUMPX8L8V8U8",
5530 "xSURFACEFMT_A2W10V10U10",
5531 "xSURFACEFMT_BUMPU8V8",
5532 "xSURFACEFMT_Q8W8V8U8",
5533 "xSURFACEFMT_CxV8U8",
5534 "xSURFACEFMT_R_S10E5",
5535 "xSURFACEFMT_R_S23E8",
5536 "xSURFACEFMT_RG_S10E5",
5537 "xSURFACEFMT_RG_S23E8",
5538 "xSURFACEFMT_ARGB_S10E5",
5539 "xSURFACEFMT_ARGB_S23E8",
5540 "xMISSING62",
5541 "xMAX_VERTEX_SHADER_TEXTURES",
5542 "xMAX_SIMULTANEOUS_RENDER_TARGETS",
5543 "xSURFACEFMT_V16U16",
5544 "xSURFACEFMT_G16R16",
5545 "xSURFACEFMT_A16B16G16R16",
5546 "xSURFACEFMT_UYVY",
5547 "xSURFACEFMT_YUY2",
5548 "xMULTISAMPLE_NONMASKABLESAMPLES",
5549 "xMULTISAMPLE_MASKABLESAMPLES",
5550 "xALPHATOCOVERAGE",
5551 "xSUPERSAMPLE",
5552 "xAUTOGENMIPMAPS",
5553 "xSURFACEFMT_NV12",
5554 "xSURFACEFMT_AYUV",
5555 "xMAX_CONTEXT_IDS",
5556 "xMAX_SURFACE_IDS",
5557 "xSURFACEFMT_Z_DF16",
5558 "xSURFACEFMT_Z_DF24",
5559 "xSURFACEFMT_Z_D24S8_INT",
5560 "xSURFACEFMT_ATI1",
5561 "xSURFACEFMT_ATI2", /* 83 */
5562 "xDEAD1",
5563 "xVIDEO_DECODE",
5564 "xVIDEO_PROCESS",
5565 "xLINE_AA",
5566 "xLINE_STIPPLE",
5567 "rMAX_LINE_WIDTH",
5568 "rMAX_AA_LINE_WIDTH",
5569 "xSURFACEFMT_YV12",
5570 "xLOGICOPS",
5571 "xTS_COLOR_KEY",
5572 "xDEAD2",
5573 "xDX",
5574 "xMAX_TEXTURE_ARRAY_SIZE",
5575 "xDX_MAX_VERTEXBUFFERS",
5576 "xDX_MAX_CONSTANT_BUFFERS",
5577 "xDX_PROVOKING_VERTEX",
5578 "xDXFMT_X8R8G8B8",
5579 "xDXFMT_A8R8G8B8",
5580 "xDXFMT_R5G6B5",
5581 "xDXFMT_X1R5G5B5",
5582 "xDXFMT_A1R5G5B5",
5583 "xDXFMT_A4R4G4B4",
5584 "xDXFMT_Z_D32",
5585 "xDXFMT_Z_D16",
5586 "xDXFMT_Z_D24S8",
5587 "xDXFMT_Z_D15S1",
5588 "xDXFMT_LUMINANCE8",
5589 "xDXFMT_LUMINANCE4_ALPHA4",
5590 "xDXFMT_LUMINANCE16",
5591 "xDXFMT_LUMINANCE8_ALPHA8",
5592 "xDXFMT_DXT1",
5593 "xDXFMT_DXT2",
5594 "xDXFMT_DXT3",
5595 "xDXFMT_DXT4",
5596 "xDXFMT_DXT5",
5597 "xDXFMT_BUMPU8V8",
5598 "xDXFMT_BUMPL6V5U5",
5599 "xDXFMT_BUMPX8L8V8U8",
5600 "xDXFMT_FORMAT_DEAD1",
5601 "xDXFMT_ARGB_S10E5",
5602 "xDXFMT_ARGB_S23E8",
5603 "xDXFMT_A2R10G10B10",
5604 "xDXFMT_V8U8",
5605 "xDXFMT_Q8W8V8U8",
5606 "xDXFMT_CxV8U8",
5607 "xDXFMT_X8L8V8U8",
5608 "xDXFMT_A2W10V10U10",
5609 "xDXFMT_ALPHA8",
5610 "xDXFMT_R_S10E5",
5611 "xDXFMT_R_S23E8",
5612 "xDXFMT_RG_S10E5",
5613 "xDXFMT_RG_S23E8",
5614 "xDXFMT_BUFFER",
5615 "xDXFMT_Z_D24X8",
5616 "xDXFMT_V16U16",
5617 "xDXFMT_G16R16",
5618 "xDXFMT_A16B16G16R16",
5619 "xDXFMT_UYVY",
5620 "xDXFMT_YUY2",
5621 "xDXFMT_NV12",
5622 "xDXFMT_AYUV",
5623 "xDXFMT_R32G32B32A32_TYPELESS",
5624 "xDXFMT_R32G32B32A32_UINT",
5625 "xDXFMT_R32G32B32A32_SINT",
5626 "xDXFMT_R32G32B32_TYPELESS",
5627 "xDXFMT_R32G32B32_FLOAT",
5628 "xDXFMT_R32G32B32_UINT",
5629 "xDXFMT_R32G32B32_SINT",
5630 "xDXFMT_R16G16B16A16_TYPELESS",
5631 "xDXFMT_R16G16B16A16_UINT",
5632 "xDXFMT_R16G16B16A16_SNORM",
5633 "xDXFMT_R16G16B16A16_SINT",
5634 "xDXFMT_R32G32_TYPELESS",
5635 "xDXFMT_R32G32_UINT",
5636 "xDXFMT_R32G32_SINT",
5637 "xDXFMT_R32G8X24_TYPELESS",
5638 "xDXFMT_D32_FLOAT_S8X24_UINT",
5639 "xDXFMT_R32_FLOAT_X8X24_TYPELESS",
5640 "xDXFMT_X32_TYPELESS_G8X24_UINT",
5641 "xDXFMT_R10G10B10A2_TYPELESS",
5642 "xDXFMT_R10G10B10A2_UINT",
5643 "xDXFMT_R11G11B10_FLOAT",
5644 "xDXFMT_R8G8B8A8_TYPELESS",
5645 "xDXFMT_R8G8B8A8_UNORM",
5646 "xDXFMT_R8G8B8A8_UNORM_SRGB",
5647 "xDXFMT_R8G8B8A8_UINT",
5648 "xDXFMT_R8G8B8A8_SINT",
5649 "xDXFMT_R16G16_TYPELESS",
5650 "xDXFMT_R16G16_UINT",
5651 "xDXFMT_R16G16_SINT",
5652 "xDXFMT_R32_TYPELESS",
5653 "xDXFMT_D32_FLOAT",
5654 "xDXFMT_R32_UINT",
5655 "xDXFMT_R32_SINT",
5656 "xDXFMT_R24G8_TYPELESS",
5657 "xDXFMT_D24_UNORM_S8_UINT",
5658 "xDXFMT_R24_UNORM_X8_TYPELESS",
5659 "xDXFMT_X24_TYPELESS_G8_UINT",
5660 "xDXFMT_R8G8_TYPELESS",
5661 "xDXFMT_R8G8_UNORM",
5662 "xDXFMT_R8G8_UINT",
5663 "xDXFMT_R8G8_SINT",
5664 "xDXFMT_R16_TYPELESS",
5665 "xDXFMT_R16_UNORM",
5666 "xDXFMT_R16_UINT",
5667 "xDXFMT_R16_SNORM",
5668 "xDXFMT_R16_SINT",
5669 "xDXFMT_R8_TYPELESS",
5670 "xDXFMT_R8_UNORM",
5671 "xDXFMT_R8_UINT",
5672 "xDXFMT_R8_SNORM",
5673 "xDXFMT_R8_SINT",
5674 "xDXFMT_P8",
5675 "xDXFMT_R9G9B9E5_SHAREDEXP",
5676 "xDXFMT_R8G8_B8G8_UNORM",
5677 "xDXFMT_G8R8_G8B8_UNORM",
5678 "xDXFMT_BC1_TYPELESS",
5679 "xDXFMT_BC1_UNORM_SRGB",
5680 "xDXFMT_BC2_TYPELESS",
5681 "xDXFMT_BC2_UNORM_SRGB",
5682 "xDXFMT_BC3_TYPELESS",
5683 "xDXFMT_BC3_UNORM_SRGB",
5684 "xDXFMT_BC4_TYPELESS",
5685 "xDXFMT_ATI1",
5686 "xDXFMT_BC4_SNORM",
5687 "xDXFMT_BC5_TYPELESS",
5688 "xDXFMT_ATI2",
5689 "xDXFMT_BC5_SNORM",
5690 "xDXFMT_R10G10B10_XR_BIAS_A2_UNORM",
5691 "xDXFMT_B8G8R8A8_TYPELESS",
5692 "xDXFMT_B8G8R8A8_UNORM_SRGB",
5693 "xDXFMT_B8G8R8X8_TYPELESS",
5694 "xDXFMT_B8G8R8X8_UNORM_SRGB",
5695 "xDXFMT_Z_DF16",
5696 "xDXFMT_Z_DF24",
5697 "xDXFMT_Z_D24S8_INT",
5698 "xDXFMT_YV12",
5699 "xDXFMT_R32G32B32A32_FLOAT",
5700 "xDXFMT_R16G16B16A16_FLOAT",
5701 "xDXFMT_R16G16B16A16_UNORM",
5702 "xDXFMT_R32G32_FLOAT",
5703 "xDXFMT_R10G10B10A2_UNORM",
5704 "xDXFMT_R8G8B8A8_SNORM",
5705 "xDXFMT_R16G16_FLOAT",
5706 "xDXFMT_R16G16_UNORM",
5707 "xDXFMT_R16G16_SNORM",
5708 "xDXFMT_R32_FLOAT",
5709 "xDXFMT_R8G8_SNORM",
5710 "xDXFMT_R16_FLOAT",
5711 "xDXFMT_D16_UNORM",
5712 "xDXFMT_A8_UNORM",
5713 "xDXFMT_BC1_UNORM",
5714 "xDXFMT_BC2_UNORM",
5715 "xDXFMT_BC3_UNORM",
5716 "xDXFMT_B5G6R5_UNORM",
5717 "xDXFMT_B5G5R5A1_UNORM",
5718 "xDXFMT_B8G8R8A8_UNORM",
5719 "xDXFMT_B8G8R8X8_UNORM",
5720 "xDXFMT_BC4_UNORM",
5721 "xDXFMT_BC5_UNORM",
5722};
5723
5724/**
5725 * Initializes the host 3D capabilities and writes them to FIFO memory.
5726 *
5727 * @returns VBox status code.
5728 * @param pThis The shared VGA/VMSVGA instance data.
5729 * @param pThisCC The VGA/VMSVGA state for ring-3.
5730 */
5731static void vmsvgaR3InitFifo3DCaps(PVGASTATE pThis, PVGASTATECC pThisCC)
5732{
5733 /* Query the capabilities and store them in the pThis->svga.au32DevCaps array. */
5734 bool const fSavedBuffering = RTLogRelSetBuffering(true);
5735
5736 for (unsigned i = 0; i < RT_ELEMENTS(pThis->svga.au32DevCaps); ++i)
5737 {
5738 uint32_t val = 0;
5739 int rc = vmsvga3dQueryCaps(pThisCC, i, &val);
5740 if (RT_SUCCESS(rc))
5741 pThis->svga.au32DevCaps[i] = val;
5742 else
5743 pThis->svga.au32DevCaps[i] = 0;
5744
5745 /* LogRel the capability value. */
5746 if (i < RT_ELEMENTS(g_apszVmSvgaDevCapNames))
5747 {
5748 if (RT_SUCCESS(rc))
5749 {
5750 if (g_apszVmSvgaDevCapNames[i][0] == 'x')
5751 LogRel(("VMSVGA3d: cap[%u]=%#010x {%s}\n", i, val, &g_apszVmSvgaDevCapNames[i][1]));
5752 else
5753 {
5754 float const fval = *(float *)&val;
5755 LogRel(("VMSVGA3d: cap[%u]=" FLOAT_FMT_STR " {%s}\n", i, FLOAT_FMT_ARGS(fval), &g_apszVmSvgaDevCapNames[i][1]));
5756 }
5757 }
5758 else
5759 LogRel(("VMSVGA3d: cap[%u]=failed rc=%Rrc {%s}\n", i, rc, &g_apszVmSvgaDevCapNames[i][1]));
5760 }
5761 else
5762 LogRel(("VMSVGA3d: new cap[%u]=%#010x rc=%Rrc\n", i, val, rc));
5763 }
5764
5765 RTLogRelSetBuffering(fSavedBuffering);
5766
5767 /* 3d hardware version; latest and greatest */
5768 pThisCC->svga.pau32FIFO[SVGA_FIFO_3D_HWVERSION_REVISED] = SVGA3D_HWVERSION_CURRENT;
5769 pThisCC->svga.pau32FIFO[SVGA_FIFO_3D_HWVERSION] = SVGA3D_HWVERSION_CURRENT;
5770
5771 /* Fill out 3d capabilities up to SVGA3D_DEVCAP_SURFACEFMT_ATI2 in the FIFO memory.
5772 * SVGA3D_DEVCAP_SURFACEFMT_ATI2 is the last capabiltiy for pre-SVGA_CAP_GBOBJECTS hardware.
5773 * If the VMSVGA device supports SVGA_CAP_GBOBJECTS capability, then the guest has to use SVGA_REG_DEV_CAP
5774 * register to query the devcaps. Older guests will still try to read the devcaps from FIFO.
5775 */
5776 SVGA3dCapsRecord *pCaps;
5777 SVGA3dCapPair *pData;
5778
5779 pCaps = (SVGA3dCapsRecord *)&pThisCC->svga.pau32FIFO[SVGA_FIFO_3D_CAPS];
5780 pCaps->header.type = SVGA3DCAPS_RECORD_DEVCAPS;
5781 pData = (SVGA3dCapPair *)&pCaps->data;
5782
5783 AssertCompile(SVGA3D_DEVCAP_DEAD1 == SVGA3D_DEVCAP_SURFACEFMT_ATI2 + 1);
5784 for (unsigned i = 0; i < SVGA3D_DEVCAP_DEAD1; ++i)
5785 {
5786 pData[i][0] = i;
5787 pData[i][1] = pThis->svga.au32DevCaps[i];
5788 }
5789 pCaps->header.length = (sizeof(pCaps->header) + SVGA3D_DEVCAP_DEAD1 * sizeof(SVGA3dCapPair)) / sizeof(uint32_t);
5790 pCaps = (SVGA3dCapsRecord *)((uint32_t *)pCaps + pCaps->header.length);
5791
5792 /* Mark end of record array (a zero word). */
5793 pCaps->header.length = 0;
5794}
5795
5796# endif
5797
5798/**
5799 * Resets the SVGA hardware state
5800 *
5801 * @returns VBox status code.
5802 * @param pDevIns The device instance.
5803 */
5804int vmsvgaR3Reset(PPDMDEVINS pDevIns)
5805{
5806 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
5807 PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
5808 PVMSVGAR3STATE pSVGAState = pThisCC->svga.pSvgaR3State;
5809
5810 /* Reset before init? */
5811 if (!pSVGAState)
5812 return VINF_SUCCESS;
5813
5814 Log(("vmsvgaR3Reset\n"));
5815
5816 /* Reset the FIFO processing as well as the 3d state (if we have one). */
5817 pThisCC->svga.pau32FIFO[SVGA_FIFO_NEXT_CMD] = pThisCC->svga.pau32FIFO[SVGA_FIFO_STOP] = 0; /** @todo should probably let the FIFO thread do this ... */
5818 int rc = vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC, VMSVGA_FIFO_EXTCMD_RESET, NULL /*pvParam*/, 10000 /*ms*/);
5819
5820 /* Reset other stuff. */
5821 pThis->svga.cScratchRegion = VMSVGA_SCRATCH_SIZE;
5822 RT_ZERO(pThis->svga.au32ScratchRegion);
5823
5824 vmsvgaR3StateTerm(pThis, pThisCC->svga.pSvgaR3State);
5825 vmsvgaR3StateInit(pDevIns, pThis, pThisCC->svga.pSvgaR3State);
5826
5827 RT_BZERO(pThisCC->svga.pbVgaFrameBufferR3, VMSVGA_VGA_FB_BACKUP_SIZE);
5828
5829 /* Initialize FIFO and register capabilities. */
5830 vmsvgaR3InitCaps(pThis, pThisCC);
5831
5832# ifdef VBOX_WITH_VMSVGA3D
5833 if (pThis->svga.f3DEnabled)
5834 vmsvgaR3InitFifo3DCaps(pThis, pThisCC);
5835# endif
5836
5837 /* VRAM tracking is enabled by default during bootup. */
5838 pThis->svga.fVRAMTracking = true;
5839 pThis->svga.fEnabled = false;
5840
5841 /* Invalidate current settings. */
5842 pThis->svga.uWidth = VMSVGA_VAL_UNINITIALIZED;
5843 pThis->svga.uHeight = VMSVGA_VAL_UNINITIALIZED;
5844 pThis->svga.uBpp = pThis->svga.uHostBpp;
5845 pThis->svga.cbScanline = 0;
5846 pThis->svga.u32PitchLock = 0;
5847
5848 return rc;
5849}
5850
5851/**
5852 * Cleans up the SVGA hardware state
5853 *
5854 * @returns VBox status code.
5855 * @param pDevIns The device instance.
5856 */
5857int vmsvgaR3Destruct(PPDMDEVINS pDevIns)
5858{
5859 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
5860 PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
5861
5862 /*
5863 * Ask the FIFO thread to terminate the 3d state and then terminate it.
5864 */
5865 if (pThisCC->svga.pFIFOIOThread)
5866 {
5867 int rc = vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC, VMSVGA_FIFO_EXTCMD_TERMINATE,
5868 NULL /*pvParam*/, 30000 /*ms*/);
5869 AssertLogRelRC(rc);
5870
5871 rc = PDMDevHlpThreadDestroy(pDevIns, pThisCC->svga.pFIFOIOThread, NULL);
5872 AssertLogRelRC(rc);
5873 pThisCC->svga.pFIFOIOThread = NULL;
5874 }
5875
5876 /*
5877 * Destroy the special SVGA state.
5878 */
5879 if (pThisCC->svga.pSvgaR3State)
5880 {
5881 vmsvgaR3StateTerm(pThis, pThisCC->svga.pSvgaR3State);
5882
5883 RTMemFree(pThisCC->svga.pSvgaR3State);
5884 pThisCC->svga.pSvgaR3State = NULL;
5885 }
5886
5887 /*
5888 * Free our resources residing in the VGA state.
5889 */
5890 if (pThisCC->svga.pbVgaFrameBufferR3)
5891 {
5892 RTMemFree(pThisCC->svga.pbVgaFrameBufferR3);
5893 pThisCC->svga.pbVgaFrameBufferR3 = NULL;
5894 }
5895 if (pThisCC->svga.hFIFOExtCmdSem != NIL_RTSEMEVENT)
5896 {
5897 RTSemEventDestroy(pThisCC->svga.hFIFOExtCmdSem);
5898 pThisCC->svga.hFIFOExtCmdSem = NIL_RTSEMEVENT;
5899 }
5900 if (pThis->svga.hFIFORequestSem != NIL_SUPSEMEVENT)
5901 {
5902 PDMDevHlpSUPSemEventClose(pDevIns, pThis->svga.hFIFORequestSem);
5903 pThis->svga.hFIFORequestSem = NIL_SUPSEMEVENT;
5904 }
5905
5906 return VINF_SUCCESS;
5907}
5908
5909/**
5910 * Initialize the SVGA hardware state
5911 *
5912 * @returns VBox status code.
5913 * @param pDevIns The device instance.
5914 */
5915int vmsvgaR3Init(PPDMDEVINS pDevIns)
5916{
5917 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
5918 PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
5919 PVMSVGAR3STATE pSVGAState;
5920 int rc;
5921
5922 pThis->svga.cScratchRegion = VMSVGA_SCRATCH_SIZE;
5923 memset(pThis->svga.au32ScratchRegion, 0, sizeof(pThis->svga.au32ScratchRegion));
5924
5925 pThis->svga.cGMR = VMSVGA_MAX_GMR_IDS;
5926
5927 /* Necessary for creating a backup of the text mode frame buffer when switching into svga mode. */
5928 pThisCC->svga.pbVgaFrameBufferR3 = (uint8_t *)RTMemAllocZ(VMSVGA_VGA_FB_BACKUP_SIZE);
5929 AssertReturn(pThisCC->svga.pbVgaFrameBufferR3, VERR_NO_MEMORY);
5930
5931 /* Create event semaphore. */
5932 rc = PDMDevHlpSUPSemEventCreate(pDevIns, &pThis->svga.hFIFORequestSem);
5933 AssertRCReturn(rc, rc);
5934
5935 /* Create event semaphore. */
5936 rc = RTSemEventCreate(&pThisCC->svga.hFIFOExtCmdSem);
5937 AssertRCReturn(rc, rc);
5938
5939 pThisCC->svga.pSvgaR3State = (PVMSVGAR3STATE)RTMemAlloc(sizeof(VMSVGAR3STATE));
5940 AssertReturn(pThisCC->svga.pSvgaR3State, VERR_NO_MEMORY);
5941
5942 rc = vmsvgaR3StateInit(pDevIns, pThis, pThisCC->svga.pSvgaR3State);
5943 AssertMsgRCReturn(rc, ("Failed to create pSvgaR3State.\n"), rc);
5944
5945 pSVGAState = pThisCC->svga.pSvgaR3State;
5946
5947 /* Initialize FIFO and register capabilities. */
5948 vmsvgaR3InitCaps(pThis, pThisCC);
5949
5950# ifdef VBOX_WITH_VMSVGA3D
5951 if (pThis->svga.f3DEnabled)
5952 {
5953 rc = vmsvga3dInit(pDevIns, pThis, pThisCC);
5954 if (RT_FAILURE(rc))
5955 {
5956 LogRel(("VMSVGA3d: 3D support disabled! (vmsvga3dInit -> %Rrc)\n", rc));
5957 pThis->svga.f3DEnabled = false;
5958 }
5959 }
5960# endif
5961 /* VRAM tracking is enabled by default during bootup. */
5962 pThis->svga.fVRAMTracking = true;
5963
5964 /* Set up the host bpp. This value is as a default for the programmable
5965 * bpp value. On old implementations, SVGA_REG_HOST_BITS_PER_PIXEL did not
5966 * exist and SVGA_REG_BITS_PER_PIXEL was read-only, returning what was later
5967 * separated as SVGA_REG_HOST_BITS_PER_PIXEL.
5968 *
5969 * NB: The driver cBits value is currently constant for the lifetime of the
5970 * VM. If that changes, the host bpp logic might need revisiting.
5971 */
5972 pThis->svga.uHostBpp = (pThisCC->pDrv->cBits + 7) & ~7;
5973
5974 /* Invalidate current settings. */
5975 pThis->svga.uWidth = VMSVGA_VAL_UNINITIALIZED;
5976 pThis->svga.uHeight = VMSVGA_VAL_UNINITIALIZED;
5977 pThis->svga.uBpp = pThis->svga.uHostBpp;
5978 pThis->svga.cbScanline = 0;
5979
5980 pThis->svga.u32MaxWidth = VBE_DISPI_MAX_YRES;
5981 pThis->svga.u32MaxHeight = VBE_DISPI_MAX_XRES;
5982 while (pThis->svga.u32MaxWidth * pThis->svga.u32MaxHeight * 4 /* 32 bpp */ > pThis->vram_size)
5983 {
5984 pThis->svga.u32MaxWidth -= 256;
5985 pThis->svga.u32MaxHeight -= 256;
5986 }
5987 Log(("VMSVGA: Maximum size (%d,%d)\n", pThis->svga.u32MaxWidth, pThis->svga.u32MaxHeight));
5988
5989# ifdef DEBUG_GMR_ACCESS
5990 /* Register the GMR access handler type. */
5991 rc = PGMR3HandlerPhysicalTypeRegister(PDMDevHlpGetVM(pDevIns), PGMPHYSHANDLERKIND_WRITE,
5992 vmsvgaR3GmrAccessHandler,
5993 NULL, NULL, NULL,
5994 NULL, NULL, NULL,
5995 "VMSVGA GMR", &pThis->svga.hGmrAccessHandlerType);
5996 AssertRCReturn(rc, rc);
5997# endif
5998
5999# if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
6000 /* Register the FIFO access handler type. In addition to
6001 debugging FIFO access, this is also used to facilitate
6002 extended fifo thread sleeps. */
6003 rc = PGMR3HandlerPhysicalTypeRegister(PDMDevHlpGetVM(pDevIns),
6004# ifdef DEBUG_FIFO_ACCESS
6005 PGMPHYSHANDLERKIND_ALL,
6006# else
6007 PGMPHYSHANDLERKIND_WRITE,
6008# endif
6009 vmsvgaR3FifoAccessHandler,
6010 NULL, NULL, NULL,
6011 NULL, NULL, NULL,
6012 "VMSVGA FIFO", &pThis->svga.hFifoAccessHandlerType);
6013 AssertRCReturn(rc, rc);
6014# endif
6015
6016 /* Create the async IO thread. */
6017 rc = PDMDevHlpThreadCreate(pDevIns, &pThisCC->svga.pFIFOIOThread, pThis, vmsvgaR3FifoLoop, vmsvgaR3FifoLoopWakeUp, 0,
6018 RTTHREADTYPE_IO, "VMSVGA FIFO");
6019 if (RT_FAILURE(rc))
6020 {
6021 AssertMsgFailed(("%s: Async IO Thread creation for FIFO handling failed rc=%d\n", __FUNCTION__, rc));
6022 return rc;
6023 }
6024
6025 /*
6026 * Statistics.
6027 */
6028# define REG_CNT(a_pvSample, a_pszName, a_pszDesc) \
6029 PDMDevHlpSTAMRegister(pDevIns, (a_pvSample), STAMTYPE_COUNTER, a_pszName, STAMUNIT_OCCURENCES, a_pszDesc)
6030# define REG_PRF(a_pvSample, a_pszName, a_pszDesc) \
6031 PDMDevHlpSTAMRegister(pDevIns, (a_pvSample), STAMTYPE_PROFILE, a_pszName, STAMUNIT_TICKS_PER_CALL, a_pszDesc)
6032# ifdef VBOX_WITH_STATISTICS
6033 REG_PRF(&pSVGAState->StatR3Cmd3dDrawPrimitivesProf, "VMSVGA/Cmd/3dDrawPrimitivesProf", "Profiling of SVGA_3D_CMD_DRAW_PRIMITIVES.");
6034 REG_PRF(&pSVGAState->StatR3Cmd3dPresentProf, "VMSVGA/Cmd/3dPresentProfBoth", "Profiling of SVGA_3D_CMD_PRESENT and SVGA_3D_CMD_PRESENT_READBACK.");
6035 REG_PRF(&pSVGAState->StatR3Cmd3dSurfaceDmaProf, "VMSVGA/Cmd/3dSurfaceDmaProf", "Profiling of SVGA_3D_CMD_SURFACE_DMA.");
6036# endif
6037 REG_PRF(&pSVGAState->StatR3Cmd3dBlitSurfaceToScreenProf, "VMSVGA/Cmd/3dBlitSurfaceToScreenProf", "Profiling of SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN.");
6038 REG_CNT(&pSVGAState->StatR3Cmd3dActivateSurface, "VMSVGA/Cmd/3dActivateSurface", "SVGA_3D_CMD_ACTIVATE_SURFACE");
6039 REG_CNT(&pSVGAState->StatR3Cmd3dBeginQuery, "VMSVGA/Cmd/3dBeginQuery", "SVGA_3D_CMD_BEGIN_QUERY");
6040 REG_CNT(&pSVGAState->StatR3Cmd3dClear, "VMSVGA/Cmd/3dClear", "SVGA_3D_CMD_CLEAR");
6041 REG_CNT(&pSVGAState->StatR3Cmd3dContextDefine, "VMSVGA/Cmd/3dContextDefine", "SVGA_3D_CMD_CONTEXT_DEFINE");
6042 REG_CNT(&pSVGAState->StatR3Cmd3dContextDestroy, "VMSVGA/Cmd/3dContextDestroy", "SVGA_3D_CMD_CONTEXT_DESTROY");
6043 REG_CNT(&pSVGAState->StatR3Cmd3dDeactivateSurface, "VMSVGA/Cmd/3dDeactivateSurface", "SVGA_3D_CMD_DEACTIVATE_SURFACE");
6044 REG_CNT(&pSVGAState->StatR3Cmd3dDrawPrimitives, "VMSVGA/Cmd/3dDrawPrimitives", "SVGA_3D_CMD_DRAW_PRIMITIVES");
6045 REG_CNT(&pSVGAState->StatR3Cmd3dEndQuery, "VMSVGA/Cmd/3dEndQuery", "SVGA_3D_CMD_END_QUERY");
6046 REG_CNT(&pSVGAState->StatR3Cmd3dGenerateMipmaps, "VMSVGA/Cmd/3dGenerateMipmaps", "SVGA_3D_CMD_GENERATE_MIPMAPS");
6047 REG_CNT(&pSVGAState->StatR3Cmd3dPresent, "VMSVGA/Cmd/3dPresent", "SVGA_3D_CMD_PRESENT");
6048 REG_CNT(&pSVGAState->StatR3Cmd3dPresentReadBack, "VMSVGA/Cmd/3dPresentReadBack", "SVGA_3D_CMD_PRESENT_READBACK");
6049 REG_CNT(&pSVGAState->StatR3Cmd3dSetClipPlane, "VMSVGA/Cmd/3dSetClipPlane", "SVGA_3D_CMD_SETCLIPPLANE");
6050 REG_CNT(&pSVGAState->StatR3Cmd3dSetLightData, "VMSVGA/Cmd/3dSetLightData", "SVGA_3D_CMD_SETLIGHTDATA");
6051 REG_CNT(&pSVGAState->StatR3Cmd3dSetLightEnable, "VMSVGA/Cmd/3dSetLightEnable", "SVGA_3D_CMD_SETLIGHTENABLE");
6052 REG_CNT(&pSVGAState->StatR3Cmd3dSetMaterial, "VMSVGA/Cmd/3dSetMaterial", "SVGA_3D_CMD_SETMATERIAL");
6053 REG_CNT(&pSVGAState->StatR3Cmd3dSetRenderState, "VMSVGA/Cmd/3dSetRenderState", "SVGA_3D_CMD_SETRENDERSTATE");
6054 REG_CNT(&pSVGAState->StatR3Cmd3dSetRenderTarget, "VMSVGA/Cmd/3dSetRenderTarget", "SVGA_3D_CMD_SETRENDERTARGET");
6055 REG_CNT(&pSVGAState->StatR3Cmd3dSetScissorRect, "VMSVGA/Cmd/3dSetScissorRect", "SVGA_3D_CMD_SETSCISSORRECT");
6056 REG_CNT(&pSVGAState->StatR3Cmd3dSetShader, "VMSVGA/Cmd/3dSetShader", "SVGA_3D_CMD_SET_SHADER");
6057 REG_CNT(&pSVGAState->StatR3Cmd3dSetShaderConst, "VMSVGA/Cmd/3dSetShaderConst", "SVGA_3D_CMD_SET_SHADER_CONST");
6058 REG_CNT(&pSVGAState->StatR3Cmd3dSetTextureState, "VMSVGA/Cmd/3dSetTextureState", "SVGA_3D_CMD_SETTEXTURESTATE");
6059 REG_CNT(&pSVGAState->StatR3Cmd3dSetTransform, "VMSVGA/Cmd/3dSetTransform", "SVGA_3D_CMD_SETTRANSFORM");
6060 REG_CNT(&pSVGAState->StatR3Cmd3dSetViewPort, "VMSVGA/Cmd/3dSetViewPort", "SVGA_3D_CMD_SETVIEWPORT");
6061 REG_CNT(&pSVGAState->StatR3Cmd3dSetZRange, "VMSVGA/Cmd/3dSetZRange", "SVGA_3D_CMD_SETZRANGE");
6062 REG_CNT(&pSVGAState->StatR3Cmd3dShaderDefine, "VMSVGA/Cmd/3dShaderDefine", "SVGA_3D_CMD_SHADER_DEFINE");
6063 REG_CNT(&pSVGAState->StatR3Cmd3dShaderDestroy, "VMSVGA/Cmd/3dShaderDestroy", "SVGA_3D_CMD_SHADER_DESTROY");
6064 REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceCopy, "VMSVGA/Cmd/3dSurfaceCopy", "SVGA_3D_CMD_SURFACE_COPY");
6065 REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceDefine, "VMSVGA/Cmd/3dSurfaceDefine", "SVGA_3D_CMD_SURFACE_DEFINE");
6066 REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceDefineV2, "VMSVGA/Cmd/3dSurfaceDefineV2", "SVGA_3D_CMD_SURFACE_DEFINE_V2");
6067 REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceDestroy, "VMSVGA/Cmd/3dSurfaceDestroy", "SVGA_3D_CMD_SURFACE_DESTROY");
6068 REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceDma, "VMSVGA/Cmd/3dSurfaceDma", "SVGA_3D_CMD_SURFACE_DMA");
6069 REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceScreen, "VMSVGA/Cmd/3dSurfaceScreen", "SVGA_3D_CMD_SURFACE_SCREEN");
6070 REG_CNT(&pSVGAState->StatR3Cmd3dSurfaceStretchBlt, "VMSVGA/Cmd/3dSurfaceStretchBlt", "SVGA_3D_CMD_SURFACE_STRETCHBLT");
6071 REG_CNT(&pSVGAState->StatR3Cmd3dWaitForQuery, "VMSVGA/Cmd/3dWaitForQuery", "SVGA_3D_CMD_WAIT_FOR_QUERY");
6072 REG_CNT(&pSVGAState->StatR3CmdAnnotationCopy, "VMSVGA/Cmd/AnnotationCopy", "SVGA_CMD_ANNOTATION_COPY");
6073 REG_CNT(&pSVGAState->StatR3CmdAnnotationFill, "VMSVGA/Cmd/AnnotationFill", "SVGA_CMD_ANNOTATION_FILL");
6074 REG_CNT(&pSVGAState->StatR3CmdBlitGmrFbToScreen, "VMSVGA/Cmd/BlitGmrFbToScreen", "SVGA_CMD_BLIT_GMRFB_TO_SCREEN");
6075 REG_CNT(&pSVGAState->StatR3CmdBlitScreentoGmrFb, "VMSVGA/Cmd/BlitScreentoGmrFb", "SVGA_CMD_BLIT_SCREEN_TO_GMRFB");
6076 REG_CNT(&pSVGAState->StatR3CmdDefineAlphaCursor, "VMSVGA/Cmd/DefineAlphaCursor", "SVGA_CMD_DEFINE_ALPHA_CURSOR");
6077 REG_CNT(&pSVGAState->StatR3CmdDefineCursor, "VMSVGA/Cmd/DefineCursor", "SVGA_CMD_DEFINE_CURSOR");
6078 REG_CNT(&pSVGAState->StatR3CmdMoveCursor, "VMSVGA/Cmd/MoveCursor", "SVGA_CMD_MOVE_CURSOR");
6079 REG_CNT(&pSVGAState->StatR3CmdDisplayCursor, "VMSVGA/Cmd/DisplayCursor", "SVGA_CMD_DISPLAY_CURSOR");
6080 REG_CNT(&pSVGAState->StatR3CmdRectFill, "VMSVGA/Cmd/RectFill", "SVGA_CMD_RECT_FILL");
6081 REG_CNT(&pSVGAState->StatR3CmdRectCopy, "VMSVGA/Cmd/RectCopy", "SVGA_CMD_RECT_COPY");
6082 REG_CNT(&pSVGAState->StatR3CmdRectRopCopy, "VMSVGA/Cmd/RectRopCopy", "SVGA_CMD_RECT_ROP_COPY");
6083 REG_CNT(&pSVGAState->StatR3CmdDefineGmr2, "VMSVGA/Cmd/DefineGmr2", "SVGA_CMD_DEFINE_GMR2");
6084 REG_CNT(&pSVGAState->StatR3CmdDefineGmr2Free, "VMSVGA/Cmd/DefineGmr2/Free", "Number of SVGA_CMD_DEFINE_GMR2 commands that only frees.");
6085 REG_CNT(&pSVGAState->StatR3CmdDefineGmr2Modify, "VMSVGA/Cmd/DefineGmr2/Modify", "Number of SVGA_CMD_DEFINE_GMR2 commands that redefines a non-free GMR.");
6086 REG_CNT(&pSVGAState->StatR3CmdDefineGmrFb, "VMSVGA/Cmd/DefineGmrFb", "SVGA_CMD_DEFINE_GMRFB");
6087 REG_CNT(&pSVGAState->StatR3CmdDefineScreen, "VMSVGA/Cmd/DefineScreen", "SVGA_CMD_DEFINE_SCREEN");
6088 REG_CNT(&pSVGAState->StatR3CmdDestroyScreen, "VMSVGA/Cmd/DestroyScreen", "SVGA_CMD_DESTROY_SCREEN");
6089 REG_CNT(&pSVGAState->StatR3CmdEscape, "VMSVGA/Cmd/Escape", "SVGA_CMD_ESCAPE");
6090 REG_CNT(&pSVGAState->StatR3CmdFence, "VMSVGA/Cmd/Fence", "SVGA_CMD_FENCE");
6091 REG_CNT(&pSVGAState->StatR3CmdInvalidCmd, "VMSVGA/Cmd/InvalidCmd", "SVGA_CMD_INVALID_CMD");
6092 REG_CNT(&pSVGAState->StatR3CmdRemapGmr2, "VMSVGA/Cmd/RemapGmr2", "SVGA_CMD_REMAP_GMR2");
6093 REG_CNT(&pSVGAState->StatR3CmdRemapGmr2Modify, "VMSVGA/Cmd/RemapGmr2/Modify", "Number of SVGA_CMD_REMAP_GMR2 commands that modifies rather than complete the definition of a GMR.");
6094 REG_CNT(&pSVGAState->StatR3CmdUpdate, "VMSVGA/Cmd/Update", "SVGA_CMD_UPDATE");
6095 REG_CNT(&pSVGAState->StatR3CmdUpdateVerbose, "VMSVGA/Cmd/UpdateVerbose", "SVGA_CMD_UPDATE_VERBOSE");
6096
6097 REG_CNT(&pSVGAState->StatR3RegConfigDoneWr, "VMSVGA/Reg/ConfigDoneWrite", "SVGA_REG_CONFIG_DONE writes");
6098 REG_CNT(&pSVGAState->StatR3RegGmrDescriptorWr, "VMSVGA/Reg/GmrDescriptorWrite", "SVGA_REG_GMR_DESCRIPTOR writes");
6099 REG_CNT(&pSVGAState->StatR3RegGmrDescriptorWrErrors, "VMSVGA/Reg/GmrDescriptorWrite/Errors", "Number of erroneous SVGA_REG_GMR_DESCRIPTOR commands.");
6100 REG_CNT(&pSVGAState->StatR3RegGmrDescriptorWrFree, "VMSVGA/Reg/GmrDescriptorWrite/Free", "Number of SVGA_REG_GMR_DESCRIPTOR commands only freeing the GMR.");
6101 REG_CNT(&pThis->svga.StatRegBitsPerPixelWr, "VMSVGA/Reg/BitsPerPixelWrite", "SVGA_REG_BITS_PER_PIXEL writes.");
6102 REG_CNT(&pThis->svga.StatRegBusyWr, "VMSVGA/Reg/BusyWrite", "SVGA_REG_BUSY writes.");
6103 REG_CNT(&pThis->svga.StatRegCursorXWr, "VMSVGA/Reg/CursorXWrite", "SVGA_REG_CURSOR_X writes.");
6104 REG_CNT(&pThis->svga.StatRegCursorYWr, "VMSVGA/Reg/CursorYWrite", "SVGA_REG_CURSOR_Y writes.");
6105 REG_CNT(&pThis->svga.StatRegCursorIdWr, "VMSVGA/Reg/CursorIdWrite", "SVGA_REG_CURSOR_ID writes.");
6106 REG_CNT(&pThis->svga.StatRegCursorOnWr, "VMSVGA/Reg/CursorOnWrite", "SVGA_REG_CURSOR_ON writes.");
6107 REG_CNT(&pThis->svga.StatRegDepthWr, "VMSVGA/Reg/DepthWrite", "SVGA_REG_DEPTH writes.");
6108 REG_CNT(&pThis->svga.StatRegDisplayHeightWr, "VMSVGA/Reg/DisplayHeightWrite", "SVGA_REG_DISPLAY_HEIGHT writes.");
6109 REG_CNT(&pThis->svga.StatRegDisplayIdWr, "VMSVGA/Reg/DisplayIdWrite", "SVGA_REG_DISPLAY_ID writes.");
6110 REG_CNT(&pThis->svga.StatRegDisplayIsPrimaryWr, "VMSVGA/Reg/DisplayIsPrimaryWrite", "SVGA_REG_DISPLAY_IS_PRIMARY writes.");
6111 REG_CNT(&pThis->svga.StatRegDisplayPositionXWr, "VMSVGA/Reg/DisplayPositionXWrite", "SVGA_REG_DISPLAY_POSITION_X writes.");
6112 REG_CNT(&pThis->svga.StatRegDisplayPositionYWr, "VMSVGA/Reg/DisplayPositionYWrite", "SVGA_REG_DISPLAY_POSITION_Y writes.");
6113 REG_CNT(&pThis->svga.StatRegDisplayWidthWr, "VMSVGA/Reg/DisplayWidthWrite", "SVGA_REG_DISPLAY_WIDTH writes.");
6114 REG_CNT(&pThis->svga.StatRegEnableWr, "VMSVGA/Reg/EnableWrite", "SVGA_REG_ENABLE writes.");
6115 REG_CNT(&pThis->svga.StatRegGmrIdWr, "VMSVGA/Reg/GmrIdWrite", "SVGA_REG_GMR_ID writes.");
6116 REG_CNT(&pThis->svga.StatRegGuestIdWr, "VMSVGA/Reg/GuestIdWrite", "SVGA_REG_GUEST_ID writes.");
6117 REG_CNT(&pThis->svga.StatRegHeightWr, "VMSVGA/Reg/HeightWrite", "SVGA_REG_HEIGHT writes.");
6118 REG_CNT(&pThis->svga.StatRegIdWr, "VMSVGA/Reg/IdWrite", "SVGA_REG_ID writes.");
6119 REG_CNT(&pThis->svga.StatRegIrqMaskWr, "VMSVGA/Reg/IrqMaskWrite", "SVGA_REG_IRQMASK writes.");
6120 REG_CNT(&pThis->svga.StatRegNumDisplaysWr, "VMSVGA/Reg/NumDisplaysWrite", "SVGA_REG_NUM_DISPLAYS writes.");
6121 REG_CNT(&pThis->svga.StatRegNumGuestDisplaysWr, "VMSVGA/Reg/NumGuestDisplaysWrite", "SVGA_REG_NUM_GUEST_DISPLAYS writes.");
6122 REG_CNT(&pThis->svga.StatRegPaletteWr, "VMSVGA/Reg/PaletteWrite", "SVGA_PALETTE_XXXX writes.");
6123 REG_CNT(&pThis->svga.StatRegPitchLockWr, "VMSVGA/Reg/PitchLockWrite", "SVGA_REG_PITCHLOCK writes.");
6124 REG_CNT(&pThis->svga.StatRegPseudoColorWr, "VMSVGA/Reg/PseudoColorWrite", "SVGA_REG_PSEUDOCOLOR writes.");
6125 REG_CNT(&pThis->svga.StatRegReadOnlyWr, "VMSVGA/Reg/ReadOnlyWrite", "Read-only SVGA_REG_XXXX writes.");
6126 REG_CNT(&pThis->svga.StatRegScratchWr, "VMSVGA/Reg/ScratchWrite", "SVGA_REG_SCRATCH_XXXX writes.");
6127 REG_CNT(&pThis->svga.StatRegSyncWr, "VMSVGA/Reg/SyncWrite", "SVGA_REG_SYNC writes.");
6128 REG_CNT(&pThis->svga.StatRegTopWr, "VMSVGA/Reg/TopWrite", "SVGA_REG_TOP writes.");
6129 REG_CNT(&pThis->svga.StatRegTracesWr, "VMSVGA/Reg/TracesWrite", "SVGA_REG_TRACES writes.");
6130 REG_CNT(&pThis->svga.StatRegUnknownWr, "VMSVGA/Reg/UnknownWrite", "Writes to unknown register.");
6131 REG_CNT(&pThis->svga.StatRegWidthWr, "VMSVGA/Reg/WidthWrite", "SVGA_REG_WIDTH writes.");
6132 REG_CNT(&pThis->svga.StatRegCommandLowWr, "VMSVGA/Reg/CommandLowWrite", "SVGA_REG_COMMAND_LOW writes.");
6133 REG_CNT(&pThis->svga.StatRegCommandHighWr, "VMSVGA/Reg/CommandHighWrite", "SVGA_REG_COMMAND_HIGH writes.");
6134 REG_CNT(&pThis->svga.StatRegDevCapWr, "VMSVGA/Reg/DevCapWrite", "SVGA_REG_DEV_CAP writes.");
6135 REG_CNT(&pThis->svga.StatRegCmdPrependLowWr, "VMSVGA/Reg/CmdPrependLowWrite", "SVGA_REG_CMD_PREPEND_LOW writes.");
6136 REG_CNT(&pThis->svga.StatRegCmdPrependHighWr, "VMSVGA/Reg/CmdPrependHighWrite", "SVGA_REG_iCMD_PREPEND_HIGH writes.");
6137
6138 REG_CNT(&pThis->svga.StatRegBitsPerPixelRd, "VMSVGA/Reg/BitsPerPixelRead", "SVGA_REG_BITS_PER_PIXEL reads.");
6139 REG_CNT(&pThis->svga.StatRegBlueMaskRd, "VMSVGA/Reg/BlueMaskRead", "SVGA_REG_BLUE_MASK reads.");
6140 REG_CNT(&pThis->svga.StatRegBusyRd, "VMSVGA/Reg/BusyRead", "SVGA_REG_BUSY reads.");
6141 REG_CNT(&pThis->svga.StatRegBytesPerLineRd, "VMSVGA/Reg/BytesPerLineRead", "SVGA_REG_BYTES_PER_LINE reads.");
6142 REG_CNT(&pThis->svga.StatRegCapabilitesRd, "VMSVGA/Reg/CapabilitesRead", "SVGA_REG_CAPABILITIES reads.");
6143 REG_CNT(&pThis->svga.StatRegConfigDoneRd, "VMSVGA/Reg/ConfigDoneRead", "SVGA_REG_CONFIG_DONE reads.");
6144 REG_CNT(&pThis->svga.StatRegCursorXRd, "VMSVGA/Reg/CursorXRead", "SVGA_REG_CURSOR_X reads.");
6145 REG_CNT(&pThis->svga.StatRegCursorYRd, "VMSVGA/Reg/CursorYRead", "SVGA_REG_CURSOR_Y reads.");
6146 REG_CNT(&pThis->svga.StatRegCursorIdRd, "VMSVGA/Reg/CursorIdRead", "SVGA_REG_CURSOR_ID reads.");
6147 REG_CNT(&pThis->svga.StatRegCursorOnRd, "VMSVGA/Reg/CursorOnRead", "SVGA_REG_CURSOR_ON reads.");
6148 REG_CNT(&pThis->svga.StatRegDepthRd, "VMSVGA/Reg/DepthRead", "SVGA_REG_DEPTH reads.");
6149 REG_CNT(&pThis->svga.StatRegDisplayHeightRd, "VMSVGA/Reg/DisplayHeightRead", "SVGA_REG_DISPLAY_HEIGHT reads.");
6150 REG_CNT(&pThis->svga.StatRegDisplayIdRd, "VMSVGA/Reg/DisplayIdRead", "SVGA_REG_DISPLAY_ID reads.");
6151 REG_CNT(&pThis->svga.StatRegDisplayIsPrimaryRd, "VMSVGA/Reg/DisplayIsPrimaryRead", "SVGA_REG_DISPLAY_IS_PRIMARY reads.");
6152 REG_CNT(&pThis->svga.StatRegDisplayPositionXRd, "VMSVGA/Reg/DisplayPositionXRead", "SVGA_REG_DISPLAY_POSITION_X reads.");
6153 REG_CNT(&pThis->svga.StatRegDisplayPositionYRd, "VMSVGA/Reg/DisplayPositionYRead", "SVGA_REG_DISPLAY_POSITION_Y reads.");
6154 REG_CNT(&pThis->svga.StatRegDisplayWidthRd, "VMSVGA/Reg/DisplayWidthRead", "SVGA_REG_DISPLAY_WIDTH reads.");
6155 REG_CNT(&pThis->svga.StatRegEnableRd, "VMSVGA/Reg/EnableRead", "SVGA_REG_ENABLE reads.");
6156 REG_CNT(&pThis->svga.StatRegFbOffsetRd, "VMSVGA/Reg/FbOffsetRead", "SVGA_REG_FB_OFFSET reads.");
6157 REG_CNT(&pThis->svga.StatRegFbSizeRd, "VMSVGA/Reg/FbSizeRead", "SVGA_REG_FB_SIZE reads.");
6158 REG_CNT(&pThis->svga.StatRegFbStartRd, "VMSVGA/Reg/FbStartRead", "SVGA_REG_FB_START reads.");
6159 REG_CNT(&pThis->svga.StatRegGmrIdRd, "VMSVGA/Reg/GmrIdRead", "SVGA_REG_GMR_ID reads.");
6160 REG_CNT(&pThis->svga.StatRegGmrMaxDescriptorLengthRd, "VMSVGA/Reg/GmrMaxDescriptorLengthRead", "SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH reads.");
6161 REG_CNT(&pThis->svga.StatRegGmrMaxIdsRd, "VMSVGA/Reg/GmrMaxIdsRead", "SVGA_REG_GMR_MAX_IDS reads.");
6162 REG_CNT(&pThis->svga.StatRegGmrsMaxPagesRd, "VMSVGA/Reg/GmrsMaxPagesRead", "SVGA_REG_GMRS_MAX_PAGES reads.");
6163 REG_CNT(&pThis->svga.StatRegGreenMaskRd, "VMSVGA/Reg/GreenMaskRead", "SVGA_REG_GREEN_MASK reads.");
6164 REG_CNT(&pThis->svga.StatRegGuestIdRd, "VMSVGA/Reg/GuestIdRead", "SVGA_REG_GUEST_ID reads.");
6165 REG_CNT(&pThis->svga.StatRegHeightRd, "VMSVGA/Reg/HeightRead", "SVGA_REG_HEIGHT reads.");
6166 REG_CNT(&pThis->svga.StatRegHostBitsPerPixelRd, "VMSVGA/Reg/HostBitsPerPixelRead", "SVGA_REG_HOST_BITS_PER_PIXEL reads.");
6167 REG_CNT(&pThis->svga.StatRegIdRd, "VMSVGA/Reg/IdRead", "SVGA_REG_ID reads.");
6168 REG_CNT(&pThis->svga.StatRegIrqMaskRd, "VMSVGA/Reg/IrqMaskRead", "SVGA_REG_IRQ_MASK reads.");
6169 REG_CNT(&pThis->svga.StatRegMaxHeightRd, "VMSVGA/Reg/MaxHeightRead", "SVGA_REG_MAX_HEIGHT reads.");
6170 REG_CNT(&pThis->svga.StatRegMaxWidthRd, "VMSVGA/Reg/MaxWidthRead", "SVGA_REG_MAX_WIDTH reads.");
6171 REG_CNT(&pThis->svga.StatRegMemorySizeRd, "VMSVGA/Reg/MemorySizeRead", "SVGA_REG_MEMORY_SIZE reads.");
6172 REG_CNT(&pThis->svga.StatRegMemRegsRd, "VMSVGA/Reg/MemRegsRead", "SVGA_REG_MEM_REGS reads.");
6173 REG_CNT(&pThis->svga.StatRegMemSizeRd, "VMSVGA/Reg/MemSizeRead", "SVGA_REG_MEM_SIZE reads.");
6174 REG_CNT(&pThis->svga.StatRegMemStartRd, "VMSVGA/Reg/MemStartRead", "SVGA_REG_MEM_START reads.");
6175 REG_CNT(&pThis->svga.StatRegNumDisplaysRd, "VMSVGA/Reg/NumDisplaysRead", "SVGA_REG_NUM_DISPLAYS reads.");
6176 REG_CNT(&pThis->svga.StatRegNumGuestDisplaysRd, "VMSVGA/Reg/NumGuestDisplaysRead", "SVGA_REG_NUM_GUEST_DISPLAYS reads.");
6177 REG_CNT(&pThis->svga.StatRegPaletteRd, "VMSVGA/Reg/PaletteRead", "SVGA_REG_PLAETTE_XXXX reads.");
6178 REG_CNT(&pThis->svga.StatRegPitchLockRd, "VMSVGA/Reg/PitchLockRead", "SVGA_REG_PITCHLOCK reads.");
6179 REG_CNT(&pThis->svga.StatRegPsuedoColorRd, "VMSVGA/Reg/PsuedoColorRead", "SVGA_REG_PSEUDOCOLOR reads.");
6180 REG_CNT(&pThis->svga.StatRegRedMaskRd, "VMSVGA/Reg/RedMaskRead", "SVGA_REG_RED_MASK reads.");
6181 REG_CNT(&pThis->svga.StatRegScratchRd, "VMSVGA/Reg/ScratchRead", "SVGA_REG_SCRATCH reads.");
6182 REG_CNT(&pThis->svga.StatRegScratchSizeRd, "VMSVGA/Reg/ScratchSizeRead", "SVGA_REG_SCRATCH_SIZE reads.");
6183 REG_CNT(&pThis->svga.StatRegSyncRd, "VMSVGA/Reg/SyncRead", "SVGA_REG_SYNC reads.");
6184 REG_CNT(&pThis->svga.StatRegTopRd, "VMSVGA/Reg/TopRead", "SVGA_REG_TOP reads.");
6185 REG_CNT(&pThis->svga.StatRegTracesRd, "VMSVGA/Reg/TracesRead", "SVGA_REG_TRACES reads.");
6186 REG_CNT(&pThis->svga.StatRegUnknownRd, "VMSVGA/Reg/UnknownRead", "SVGA_REG_UNKNOWN reads.");
6187 REG_CNT(&pThis->svga.StatRegVramSizeRd, "VMSVGA/Reg/VramSizeRead", "SVGA_REG_VRAM_SIZE reads.");
6188 REG_CNT(&pThis->svga.StatRegWidthRd, "VMSVGA/Reg/WidthRead", "SVGA_REG_WIDTH reads.");
6189 REG_CNT(&pThis->svga.StatRegWriteOnlyRd, "VMSVGA/Reg/WriteOnlyRead", "Write-only SVGA_REG_XXXX reads.");
6190 REG_CNT(&pThis->svga.StatRegCommandLowRd, "VMSVGA/Reg/CommandLowRead", "SVGA_REG_COMMAND_LOW reads.");
6191 REG_CNT(&pThis->svga.StatRegCommandHighRd, "VMSVGA/Reg/CommandHighRead", "SVGA_REG_COMMAND_HIGH reads.");
6192 REG_CNT(&pThis->svga.StatRegMaxPrimBBMemRd, "VMSVGA/Reg/MaxPrimBBMemRead", "SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM reads.");
6193 REG_CNT(&pThis->svga.StatRegGBMemSizeRd, "VMSVGA/Reg/GBMemSizeRead", "SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB reads.");
6194 REG_CNT(&pThis->svga.StatRegDevCapRd, "VMSVGA/Reg/DevCapRead", "SVGA_REG_DEV_CAP reads.");
6195 REG_CNT(&pThis->svga.StatRegCmdPrependLowRd, "VMSVGA/Reg/CmdPrependLowRead", "SVGA_REG_CMD_PREPEND_LOW reads.");
6196 REG_CNT(&pThis->svga.StatRegCmdPrependHighRd, "VMSVGA/Reg/CmdPrependHighRead", "SVGA_REG_iCMD_PREPEND_HIGH reads.");
6197 REG_CNT(&pThis->svga.StatRegScrnTgtMaxWidthRd, "VMSVGA/Reg/ScrnTgtMaxWidthRead", "SVGA_REG_SCREENTARGET_MAX_WIDTH reads.");
6198 REG_CNT(&pThis->svga.StatRegScrnTgtMaxHeightRd, "VMSVGA/Reg/ScrnTgtMaxHeightRead", "SVGA_REG_SCREENTARGET_MAX_HEIGHT reads.");
6199 REG_CNT(&pThis->svga.StatRegMobMaxSizeRd, "VMSVGA/Reg/MobMaxSizeRead", "SVGA_REG_MOB_MAX_SIZE reads.");
6200
6201 REG_PRF(&pSVGAState->StatBusyDelayEmts, "VMSVGA/EmtDelayOnBusyFifo", "Time we've delayed EMTs because of busy FIFO thread.");
6202 REG_CNT(&pSVGAState->StatFifoCommands, "VMSVGA/FifoCommands", "FIFO command counter.");
6203 REG_CNT(&pSVGAState->StatFifoErrors, "VMSVGA/FifoErrors", "FIFO error counter.");
6204 REG_CNT(&pSVGAState->StatFifoUnkCmds, "VMSVGA/FifoUnknownCommands", "FIFO unknown command counter.");
6205 REG_CNT(&pSVGAState->StatFifoTodoTimeout, "VMSVGA/FifoTodoTimeout", "Number of times we discovered pending work after a wait timeout.");
6206 REG_CNT(&pSVGAState->StatFifoTodoWoken, "VMSVGA/FifoTodoWoken", "Number of times we discovered pending work after being woken up.");
6207 REG_PRF(&pSVGAState->StatFifoStalls, "VMSVGA/FifoStalls", "Profiling of FIFO stalls (waiting for guest to finish copying data).");
6208 REG_PRF(&pSVGAState->StatFifoExtendedSleep, "VMSVGA/FifoExtendedSleep", "Profiling FIFO sleeps relying on the refresh timer and/or access handler.");
6209# if defined(VMSVGA_USE_FIFO_ACCESS_HANDLER) || defined(DEBUG_FIFO_ACCESS)
6210 REG_CNT(&pSVGAState->StatFifoAccessHandler, "VMSVGA/FifoAccessHandler", "Number of times the FIFO access handler triggered.");
6211# endif
6212 REG_CNT(&pSVGAState->StatFifoCursorFetchAgain, "VMSVGA/FifoCursorFetchAgain", "Times the cursor update counter changed while reading.");
6213 REG_CNT(&pSVGAState->StatFifoCursorNoChange, "VMSVGA/FifoCursorNoChange", "No cursor position change event though the update counter was modified.");
6214 REG_CNT(&pSVGAState->StatFifoCursorPosition, "VMSVGA/FifoCursorPosition", "Cursor position and visibility changes.");
6215 REG_CNT(&pSVGAState->StatFifoCursorVisiblity, "VMSVGA/FifoCursorVisiblity", "Cursor visibility changes.");
6216 REG_CNT(&pSVGAState->StatFifoWatchdogWakeUps, "VMSVGA/FifoWatchdogWakeUps", "Number of times the FIFO refresh poller/watchdog woke up the FIFO thread.");
6217
6218# undef REG_CNT
6219# undef REG_PRF
6220
6221 /*
6222 * Info handlers.
6223 */
6224 PDMDevHlpDBGFInfoRegister(pDevIns, "vmsvga", "Basic VMSVGA device state details", vmsvgaR3Info);
6225# ifdef VBOX_WITH_VMSVGA3D
6226 PDMDevHlpDBGFInfoRegister(pDevIns, "vmsvga3dctx", "VMSVGA 3d context details. Accepts 'terse'.", vmsvgaR3Info3dContext);
6227 PDMDevHlpDBGFInfoRegister(pDevIns, "vmsvga3dsfc",
6228 "VMSVGA 3d surface details. "
6229 "Accepts 'terse', 'invy', and one of 'tiny', 'medium', 'normal', 'big', 'huge', or 'gigantic'.",
6230 vmsvgaR3Info3dSurface);
6231 PDMDevHlpDBGFInfoRegister(pDevIns, "vmsvga3dsurf",
6232 "VMSVGA 3d surface details and bitmap: "
6233 "sid[>dir]",
6234 vmsvgaR3Info3dSurfaceBmp);
6235# endif
6236
6237 return VINF_SUCCESS;
6238}
6239
6240/**
6241 * Power On notification.
6242 *
6243 * @returns VBox status code.
6244 * @param pDevIns The device instance data.
6245 *
6246 * @remarks Caller enters the device critical section.
6247 */
6248DECLCALLBACK(void) vmsvgaR3PowerOn(PPDMDEVINS pDevIns)
6249{
6250# ifdef VBOX_WITH_VMSVGA3D
6251 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
6252 PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
6253 if (pThis->svga.f3DEnabled)
6254 {
6255 int rc = vmsvga3dPowerOn(pDevIns, pThis, pThisCC);
6256 if (RT_SUCCESS(rc))
6257 {
6258 /* Initialize FIFO 3D capabilities. */
6259 vmsvgaR3InitFifo3DCaps(pThis, pThisCC);
6260 }
6261 }
6262# else /* !VBOX_WITH_VMSVGA3D */
6263 RT_NOREF(pDevIns);
6264# endif /* !VBOX_WITH_VMSVGA3D */
6265}
6266
6267/**
6268 * Power Off notification.
6269 *
6270 * @param pDevIns The device instance data.
6271 *
6272 * @remarks Caller enters the device critical section.
6273 */
6274DECLCALLBACK(void) vmsvgaR3PowerOff(PPDMDEVINS pDevIns)
6275{
6276 PVGASTATE pThis = PDMDEVINS_2_DATA(pDevIns, PVGASTATE);
6277 PVGASTATECC pThisCC = PDMDEVINS_2_DATA_CC(pDevIns, PVGASTATECC);
6278
6279 /*
6280 * Notify the FIFO thread.
6281 */
6282 if (pThisCC->svga.pFIFOIOThread)
6283 {
6284 int rc = vmsvgaR3RunExtCmdOnFifoThread(pDevIns, pThis, pThisCC, VMSVGA_FIFO_EXTCMD_POWEROFF,
6285 NULL /*pvParam*/, 30000 /*ms*/);
6286 AssertLogRelRC(rc);
6287 }
6288}
6289
6290#endif /* IN_RING3 */
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