VirtualBox

Changeset 82081 in vbox


Ignore:
Timestamp:
Nov 21, 2019 3:33:01 PM (5 years ago)
Author:
vboxsync
Message:

DevVGA: style nits. bugref:9218

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp

    r82079 r82081  
    794794    switch (idxReg)
    795795    {
    796     case SVGA_REG_ID:
    797         STAM_REL_COUNTER_INC(&pThis->svga.StatRegIdRd);
    798         *pu32 = pThis->svga.u32SVGAId;
    799         break;
    800 
    801     case SVGA_REG_ENABLE:
    802         STAM_REL_COUNTER_INC(&pThis->svga.StatRegEnableRd);
    803         *pu32 = pThis->svga.fEnabled;
    804         break;
    805 
    806     case SVGA_REG_WIDTH:
    807     {
    808         STAM_REL_COUNTER_INC(&pThis->svga.StatRegWidthRd);
    809         if (    pThis->svga.fEnabled
    810             &&  pThis->svga.uWidth != VMSVGA_VAL_UNINITIALIZED)
     796        case SVGA_REG_ID:
     797            STAM_REL_COUNTER_INC(&pThis->svga.StatRegIdRd);
     798            *pu32 = pThis->svga.u32SVGAId;
     799            break;
     800
     801        case SVGA_REG_ENABLE:
     802            STAM_REL_COUNTER_INC(&pThis->svga.StatRegEnableRd);
     803            *pu32 = pThis->svga.fEnabled;
     804            break;
     805
     806        case SVGA_REG_WIDTH:
    811807        {
    812             *pu32 = pThis->svga.uWidth;
     808            STAM_REL_COUNTER_INC(&pThis->svga.StatRegWidthRd);
     809            if (    pThis->svga.fEnabled
     810                &&  pThis->svga.uWidth != VMSVGA_VAL_UNINITIALIZED)
     811            {
     812                *pu32 = pThis->svga.uWidth;
     813            }
     814            else
     815            {
     816#ifndef IN_RING3
     817                rc = VINF_IOM_R3_IOPORT_READ;
     818#else
     819                *pu32 = pThis->pDrv->cx;
     820#endif
     821            }
     822            break;
    813823        }
    814         else
     824
     825        case SVGA_REG_HEIGHT:
     826        {
     827            STAM_REL_COUNTER_INC(&pThis->svga.StatRegHeightRd);
     828            if (    pThis->svga.fEnabled
     829                &&  pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
     830            {
     831                *pu32 = pThis->svga.uHeight;
     832            }
     833            else
     834            {
     835#ifndef IN_RING3
     836                rc = VINF_IOM_R3_IOPORT_READ;
     837#else
     838                *pu32 = pThis->pDrv->cy;
     839#endif
     840            }
     841            break;
     842        }
     843
     844        case SVGA_REG_MAX_WIDTH:
     845            STAM_REL_COUNTER_INC(&pThis->svga.StatRegMaxWidthRd);
     846            *pu32 = pThis->svga.u32MaxWidth;
     847            break;
     848
     849        case SVGA_REG_MAX_HEIGHT:
     850            STAM_REL_COUNTER_INC(&pThis->svga.StatRegMaxHeightRd);
     851            *pu32 = pThis->svga.u32MaxHeight;
     852            break;
     853
     854        case SVGA_REG_DEPTH:
     855            /* This returns the color depth of the current mode. */
     856            STAM_REL_COUNTER_INC(&pThis->svga.StatRegDepthRd);
     857            switch (pThis->svga.uBpp)
     858            {
     859            case 15:
     860            case 16:
     861            case 24:
     862                *pu32 = pThis->svga.uBpp;
     863                break;
     864
     865            default:
     866            case 32:
     867                *pu32 = 24; /* The upper 8 bits are either alpha bits or not used. */
     868                break;
     869            }
     870            break;
     871
     872        case SVGA_REG_HOST_BITS_PER_PIXEL: /* (Deprecated) */
     873            STAM_REL_COUNTER_INC(&pThis->svga.StatRegHostBitsPerPixelRd);
     874            if (    pThis->svga.fEnabled
     875                &&  pThis->svga.uBpp != VMSVGA_VAL_UNINITIALIZED)
     876            {
     877                *pu32 = pThis->svga.uBpp;
     878            }
     879            else
     880            {
     881#ifndef IN_RING3
     882                rc = VINF_IOM_R3_IOPORT_READ;
     883#else
     884                *pu32 = pThis->pDrv->cBits;
     885#endif
     886            }
     887            break;
     888
     889        case SVGA_REG_BITS_PER_PIXEL:      /* Current bpp in the guest */
     890            STAM_REL_COUNTER_INC(&pThis->svga.StatRegBitsPerPixelRd);
     891            if (    pThis->svga.fEnabled
     892                &&  pThis->svga.uBpp != VMSVGA_VAL_UNINITIALIZED)
     893            {
     894                *pu32 = (pThis->svga.uBpp + 7) & ~7;
     895            }
     896            else
     897            {
     898#ifndef IN_RING3
     899                rc = VINF_IOM_R3_IOPORT_READ;
     900#else
     901                *pu32 = (pThis->pDrv->cBits + 7) & ~7;
     902#endif
     903            }
     904            break;
     905
     906        case SVGA_REG_PSEUDOCOLOR:
     907            STAM_REL_COUNTER_INC(&pThis->svga.StatRegPsuedoColorRd);
     908            *pu32 = pThis->svga.uBpp == 8; /* See section 6 "Pseudocolor" in svga_interface.txt. */
     909            break;
     910
     911        case SVGA_REG_RED_MASK:
     912        case SVGA_REG_GREEN_MASK:
     913        case SVGA_REG_BLUE_MASK:
     914        {
     915            uint32_t uBpp;
     916
     917            if (    pThis->svga.fEnabled
     918                &&  pThis->svga.uBpp != VMSVGA_VAL_UNINITIALIZED)
     919            {
     920                uBpp = pThis->svga.uBpp;
     921            }
     922            else
     923            {
     924#ifndef IN_RING3
     925                rc = VINF_IOM_R3_IOPORT_READ;
     926                break;
     927#else
     928                uBpp = pThis->pDrv->cBits;
     929#endif
     930            }
     931            uint32_t u32RedMask, u32GreenMask, u32BlueMask;
     932            switch (uBpp)
     933            {
     934                case 8:
     935                    u32RedMask   = 0x07;
     936                    u32GreenMask = 0x38;
     937                    u32BlueMask  = 0xc0;
     938                    break;
     939
     940                case 15:
     941                    u32RedMask   = 0x0000001f;
     942                    u32GreenMask = 0x000003e0;
     943                    u32BlueMask  = 0x00007c00;
     944                    break;
     945
     946                case 16:
     947                    u32RedMask   = 0x0000001f;
     948                    u32GreenMask = 0x000007e0;
     949                    u32BlueMask  = 0x0000f800;
     950                    break;
     951
     952                case 24:
     953                case 32:
     954                default:
     955                    u32RedMask   = 0x00ff0000;
     956                    u32GreenMask = 0x0000ff00;
     957                    u32BlueMask  = 0x000000ff;
     958                    break;
     959            }
     960            switch (idxReg)
     961            {
     962                case SVGA_REG_RED_MASK:
     963                    STAM_REL_COUNTER_INC(&pThis->svga.StatRegRedMaskRd);
     964                    *pu32 = u32RedMask;
     965                    break;
     966
     967                case SVGA_REG_GREEN_MASK:
     968                    STAM_REL_COUNTER_INC(&pThis->svga.StatRegGreenMaskRd);
     969                    *pu32 = u32GreenMask;
     970                    break;
     971
     972                case SVGA_REG_BLUE_MASK:
     973                    STAM_REL_COUNTER_INC(&pThis->svga.StatRegBlueMaskRd);
     974                    *pu32 = u32BlueMask;
     975                    break;
     976            }
     977            break;
     978        }
     979
     980        case SVGA_REG_BYTES_PER_LINE:
     981        {
     982            STAM_REL_COUNTER_INC(&pThis->svga.StatRegBytesPerLineRd);
     983            if (    pThis->svga.fEnabled
     984                &&  pThis->svga.cbScanline)
     985            {
     986                *pu32 = pThis->svga.cbScanline;
     987            }
     988            else
     989            {
     990#ifndef IN_RING3
     991                rc = VINF_IOM_R3_IOPORT_READ;
     992#else
     993                *pu32 = pThis->pDrv->cbScanline;
     994#endif
     995            }
     996            break;
     997        }
     998
     999        case SVGA_REG_VRAM_SIZE:            /* VRAM size */
     1000            STAM_REL_COUNTER_INC(&pThis->svga.StatRegVramSizeRd);
     1001            *pu32 = pThis->vram_size;
     1002            break;
     1003
     1004        case SVGA_REG_FB_START:             /* Frame buffer physical address. */
     1005            STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbStartRd);
     1006            Assert(pThis->GCPhysVRAM <= 0xffffffff);
     1007            *pu32 = pThis->GCPhysVRAM;
     1008            break;
     1009
     1010        case SVGA_REG_FB_OFFSET:            /* Offset of the frame buffer in VRAM */
     1011            STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbOffsetRd);
     1012            /* Always zero in our case. */
     1013            *pu32 = 0;
     1014            break;
     1015
     1016        case SVGA_REG_FB_SIZE:              /* Frame buffer size */
    8151017        {
    8161018#ifndef IN_RING3
    8171019            rc = VINF_IOM_R3_IOPORT_READ;
    8181020#else
    819             *pu32 = pThis->pDrv->cx;
     1021            STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbSizeRd);
     1022
     1023            /* VMWare testcases want at least 4 MB in case the hardware is disabled. */
     1024            if (    pThis->svga.fEnabled
     1025                &&  pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
     1026            {
     1027                /* Hardware enabled; return real framebuffer size .*/
     1028                *pu32 = (uint32_t)pThis->svga.uHeight * pThis->svga.cbScanline;
     1029            }
     1030            else
     1031                *pu32 = RT_MAX(0x100000, (uint32_t)pThis->pDrv->cy * pThis->pDrv->cbScanline);
     1032
     1033            *pu32 = RT_MIN(pThis->vram_size, *pu32);
     1034            Log(("h=%d w=%d bpp=%d\n", pThis->pDrv->cy, pThis->pDrv->cx, pThis->pDrv->cBits));
    8201035#endif
     1036            break;
    8211037        }
    822         break;
    823     }
    824 
    825     case SVGA_REG_HEIGHT:
    826     {
    827         STAM_REL_COUNTER_INC(&pThis->svga.StatRegHeightRd);
    828         if (    pThis->svga.fEnabled
    829             &&  pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
    830         {
    831             *pu32 = pThis->svga.uHeight;
    832         }
    833         else
    834         {
     1038
     1039        case SVGA_REG_CAPABILITIES:
     1040            STAM_REL_COUNTER_INC(&pThis->svga.StatRegCapabilitesRd);
     1041            *pu32 = pThis->svga.u32RegCaps;
     1042            break;
     1043
     1044        case SVGA_REG_MEM_START:           /* FIFO start */
     1045            STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemStartRd);
     1046            Assert(pThis->svga.GCPhysFIFO <= 0xffffffff);
     1047            *pu32 = pThis->svga.GCPhysFIFO;
     1048            break;
     1049
     1050        case SVGA_REG_MEM_SIZE:            /* FIFO size */
     1051            STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemSizeRd);
     1052            *pu32 = pThis->svga.cbFIFO;
     1053            break;
     1054
     1055        case SVGA_REG_CONFIG_DONE:         /* Set when memory area configured */
     1056            STAM_REL_COUNTER_INC(&pThis->svga.StatRegConfigDoneRd);
     1057            *pu32 = pThis->svga.fConfigured;
     1058            break;
     1059
     1060        case SVGA_REG_SYNC:                /* See "FIFO Synchronization Registers" */
     1061            STAM_REL_COUNTER_INC(&pThis->svga.StatRegSyncRd);
     1062            *pu32 = 0;
     1063            break;
     1064
     1065        case SVGA_REG_BUSY:                /* See "FIFO Synchronization Registers" */
     1066            STAM_REL_COUNTER_INC(&pThis->svga.StatRegBusyRd);
     1067            if (pThis->svga.fBusy)
     1068            {
    8351069#ifndef IN_RING3
    836             rc = VINF_IOM_R3_IOPORT_READ;
    837 #else
    838             *pu32 = pThis->pDrv->cy;
    839 #endif
    840         }
    841         break;
    842     }
    843 
    844     case SVGA_REG_MAX_WIDTH:
    845         STAM_REL_COUNTER_INC(&pThis->svga.StatRegMaxWidthRd);
    846         *pu32 = pThis->svga.u32MaxWidth;
    847         break;
    848 
    849     case SVGA_REG_MAX_HEIGHT:
    850         STAM_REL_COUNTER_INC(&pThis->svga.StatRegMaxHeightRd);
    851         *pu32 = pThis->svga.u32MaxHeight;
    852         break;
    853 
    854     case SVGA_REG_DEPTH:
    855         /* This returns the color depth of the current mode. */
    856         STAM_REL_COUNTER_INC(&pThis->svga.StatRegDepthRd);
    857         switch (pThis->svga.uBpp)
    858         {
    859         case 15:
    860         case 16:
    861         case 24:
    862             *pu32 = pThis->svga.uBpp;
    863             break;
    864 
    865         default:
    866         case 32:
    867             *pu32 = 24; /* The upper 8 bits are either alpha bits or not used. */
    868             break;
    869         }
    870         break;
    871 
    872     case SVGA_REG_HOST_BITS_PER_PIXEL: /* (Deprecated) */
    873         STAM_REL_COUNTER_INC(&pThis->svga.StatRegHostBitsPerPixelRd);
    874         if (    pThis->svga.fEnabled
    875             &&  pThis->svga.uBpp != VMSVGA_VAL_UNINITIALIZED)
    876         {
    877             *pu32 = pThis->svga.uBpp;
    878         }
    879         else
    880         {
    881 #ifndef IN_RING3
    882             rc = VINF_IOM_R3_IOPORT_READ;
    883 #else
    884             *pu32 = pThis->pDrv->cBits;
    885 #endif
    886         }
    887         break;
    888 
    889     case SVGA_REG_BITS_PER_PIXEL:      /* Current bpp in the guest */
    890         STAM_REL_COUNTER_INC(&pThis->svga.StatRegBitsPerPixelRd);
    891         if (    pThis->svga.fEnabled
    892             &&  pThis->svga.uBpp != VMSVGA_VAL_UNINITIALIZED)
    893         {
    894             *pu32 = (pThis->svga.uBpp + 7) & ~7;
    895         }
    896         else
    897         {
    898 #ifndef IN_RING3
    899             rc = VINF_IOM_R3_IOPORT_READ;
    900 #else
    901             *pu32 = (pThis->pDrv->cBits + 7) & ~7;
    902 #endif
    903         }
    904         break;
    905 
    906     case SVGA_REG_PSEUDOCOLOR:
    907         STAM_REL_COUNTER_INC(&pThis->svga.StatRegPsuedoColorRd);
    908         *pu32 = pThis->svga.uBpp == 8; /* See section 6 "Pseudocolor" in svga_interface.txt. */
    909         break;
    910 
    911     case SVGA_REG_RED_MASK:
    912     case SVGA_REG_GREEN_MASK:
    913     case SVGA_REG_BLUE_MASK:
    914     {
    915         uint32_t uBpp;
    916 
    917         if (    pThis->svga.fEnabled
    918             &&  pThis->svga.uBpp != VMSVGA_VAL_UNINITIALIZED)
    919         {
    920             uBpp = pThis->svga.uBpp;
    921         }
    922         else
    923         {
    924 #ifndef IN_RING3
    925             rc = VINF_IOM_R3_IOPORT_READ;
    926             break;
    927 #else
    928             uBpp = pThis->pDrv->cBits;
    929 #endif
    930         }
    931         uint32_t u32RedMask, u32GreenMask, u32BlueMask;
    932         switch (uBpp)
    933         {
    934         case 8:
    935             u32RedMask   = 0x07;
    936             u32GreenMask = 0x38;
    937             u32BlueMask  = 0xc0;
    938             break;
    939 
    940         case 15:
    941             u32RedMask   = 0x0000001f;
    942             u32GreenMask = 0x000003e0;
    943             u32BlueMask  = 0x00007c00;
    944             break;
    945 
    946         case 16:
    947             u32RedMask   = 0x0000001f;
    948             u32GreenMask = 0x000007e0;
    949             u32BlueMask  = 0x0000f800;
    950             break;
    951 
    952         case 24:
    953         case 32:
    954         default:
    955             u32RedMask   = 0x00ff0000;
    956             u32GreenMask = 0x0000ff00;
    957             u32BlueMask  = 0x000000ff;
    958             break;
    959         }
    960         switch (idxReg)
    961         {
    962         case SVGA_REG_RED_MASK:
    963             STAM_REL_COUNTER_INC(&pThis->svga.StatRegRedMaskRd);
    964             *pu32 = u32RedMask;
    965             break;
    966 
    967         case SVGA_REG_GREEN_MASK:
    968             STAM_REL_COUNTER_INC(&pThis->svga.StatRegGreenMaskRd);
    969             *pu32 = u32GreenMask;
    970             break;
    971 
    972         case SVGA_REG_BLUE_MASK:
    973             STAM_REL_COUNTER_INC(&pThis->svga.StatRegBlueMaskRd);
    974             *pu32 = u32BlueMask;
    975             break;
    976         }
    977         break;
    978     }
    979 
    980     case SVGA_REG_BYTES_PER_LINE:
    981     {
    982         STAM_REL_COUNTER_INC(&pThis->svga.StatRegBytesPerLineRd);
    983         if (    pThis->svga.fEnabled
    984             &&  pThis->svga.cbScanline)
    985         {
    986             *pu32 = pThis->svga.cbScanline;
    987         }
    988         else
    989         {
    990 #ifndef IN_RING3
    991             rc = VINF_IOM_R3_IOPORT_READ;
    992 #else
    993             *pu32 = pThis->pDrv->cbScanline;
    994 #endif
    995         }
    996         break;
    997     }
    998 
    999     case SVGA_REG_VRAM_SIZE:            /* VRAM size */
    1000         STAM_REL_COUNTER_INC(&pThis->svga.StatRegVramSizeRd);
    1001         *pu32 = pThis->vram_size;
    1002         break;
    1003 
    1004     case SVGA_REG_FB_START:             /* Frame buffer physical address. */
    1005         STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbStartRd);
    1006         Assert(pThis->GCPhysVRAM <= 0xffffffff);
    1007         *pu32 = pThis->GCPhysVRAM;
    1008         break;
    1009 
    1010     case SVGA_REG_FB_OFFSET:            /* Offset of the frame buffer in VRAM */
    1011         STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbOffsetRd);
    1012         /* Always zero in our case. */
    1013         *pu32 = 0;
    1014         break;
    1015 
    1016     case SVGA_REG_FB_SIZE:              /* Frame buffer size */
    1017     {
    1018 #ifndef IN_RING3
    1019         rc = VINF_IOM_R3_IOPORT_READ;
    1020 #else
    1021         STAM_REL_COUNTER_INC(&pThis->svga.StatRegFbSizeRd);
    1022 
    1023         /* VMWare testcases want at least 4 MB in case the hardware is disabled. */
    1024         if (    pThis->svga.fEnabled
    1025             &&  pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED)
    1026         {
    1027             /* Hardware enabled; return real framebuffer size .*/
    1028             *pu32 = (uint32_t)pThis->svga.uHeight * pThis->svga.cbScanline;
    1029         }
    1030         else
    1031             *pu32 = RT_MAX(0x100000, (uint32_t)pThis->pDrv->cy * pThis->pDrv->cbScanline);
    1032 
    1033         *pu32 = RT_MIN(pThis->vram_size, *pu32);
    1034         Log(("h=%d w=%d bpp=%d\n", pThis->pDrv->cy, pThis->pDrv->cx, pThis->pDrv->cBits));
    1035 #endif
    1036         break;
    1037     }
    1038 
    1039     case SVGA_REG_CAPABILITIES:
    1040         STAM_REL_COUNTER_INC(&pThis->svga.StatRegCapabilitesRd);
    1041         *pu32 = pThis->svga.u32RegCaps;
    1042         break;
    1043 
    1044     case SVGA_REG_MEM_START:           /* FIFO start */
    1045         STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemStartRd);
    1046         Assert(pThis->svga.GCPhysFIFO <= 0xffffffff);
    1047         *pu32 = pThis->svga.GCPhysFIFO;
    1048         break;
    1049 
    1050     case SVGA_REG_MEM_SIZE:            /* FIFO size */
    1051         STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemSizeRd);
    1052         *pu32 = pThis->svga.cbFIFO;
    1053         break;
    1054 
    1055     case SVGA_REG_CONFIG_DONE:         /* Set when memory area configured */
    1056         STAM_REL_COUNTER_INC(&pThis->svga.StatRegConfigDoneRd);
    1057         *pu32 = pThis->svga.fConfigured;
    1058         break;
    1059 
    1060     case SVGA_REG_SYNC:                /* See "FIFO Synchronization Registers" */
    1061         STAM_REL_COUNTER_INC(&pThis->svga.StatRegSyncRd);
    1062         *pu32 = 0;
    1063         break;
    1064 
    1065     case SVGA_REG_BUSY:                /* See "FIFO Synchronization Registers" */
    1066         STAM_REL_COUNTER_INC(&pThis->svga.StatRegBusyRd);
    1067         if (pThis->svga.fBusy)
    1068         {
    1069 #ifndef IN_RING3
    1070             /* Go to ring-3 and halt the CPU. */
    1071             rc = VINF_IOM_R3_IOPORT_READ;
    1072             RT_NOREF(pDevIns);
    1073             break;
     1070                /* Go to ring-3 and halt the CPU. */
     1071                rc = VINF_IOM_R3_IOPORT_READ;
     1072                RT_NOREF(pDevIns);
     1073                break;
    10741074#else
    10751075# if defined(VMSVGA_USE_EMT_HALT_CODE)
    1076             /* The guest is basically doing a HLT via the device here, but with
    1077                a special wake up condition on FIFO completion. */
    1078             PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
    1079             STAM_REL_PROFILE_START(&pSVGAState->StatBusyDelayEmts, EmtDelay);
    1080             PVM         pVM   = PDMDevHlpGetVM(pThis->pDevInsR3);
    1081             VMCPUID     idCpu = PDMDevHlpGetCurrentCpuId(pThis->pDevInsR3);
    1082             VMCPUSET_ATOMIC_ADD(&pSVGAState->BusyDelayedEmts, idCpu);
    1083             ASMAtomicIncU32(&pSVGAState->cBusyDelayedEmts);
    1084             if (pThis->svga.fBusy)
    1085             {
    1086                 PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); /* hack around lock order issue. */
    1087                 rc = VMR3WaitForDeviceReady(pVM, idCpu);
    1088                 PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_IGNORED);
    1089             }
    1090             ASMAtomicDecU32(&pSVGAState->cBusyDelayedEmts);
    1091             VMCPUSET_ATOMIC_DEL(&pSVGAState->BusyDelayedEmts, idCpu);
    1092 # else
    1093 
    1094             /* Delay the EMT a bit so the FIFO and others can get some work done.
    1095                This used to be a crude 50 ms sleep. The current code tries to be
    1096                more efficient, but the consept is still very crude. */
    1097             PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
    1098             STAM_REL_PROFILE_START(&pSVGAState->StatBusyDelayEmts, EmtDelay);
    1099             RTThreadYield();
    1100             if (pThis->svga.fBusy)
    1101             {
    1102                 uint32_t cRefs = ASMAtomicIncU32(&pSVGAState->cBusyDelayedEmts);
    1103 
    1104                 if (pThis->svga.fBusy && cRefs == 1)
    1105                     RTSemEventMultiReset(pSVGAState->hBusyDelayedEmts);
     1076                /* The guest is basically doing a HLT via the device here, but with
     1077                   a special wake up condition on FIFO completion. */
     1078                PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
     1079                STAM_REL_PROFILE_START(&pSVGAState->StatBusyDelayEmts, EmtDelay);
     1080                PVM         pVM   = PDMDevHlpGetVM(pThis->pDevInsR3);
     1081                VMCPUID     idCpu = PDMDevHlpGetCurrentCpuId(pThis->pDevInsR3);
     1082                VMCPUSET_ATOMIC_ADD(&pSVGAState->BusyDelayedEmts, idCpu);
     1083                ASMAtomicIncU32(&pSVGAState->cBusyDelayedEmts);
    11061084                if (pThis->svga.fBusy)
    11071085                {
    1108                     /** @todo If this code is going to stay, we need to call into the halt/wait
    1109                      *        code in VMEmt.cpp here, otherwise all kind of EMT interaction will
    1110                      *        suffer when the guest is polling on a busy FIFO. */
    1111                     uint64_t cNsMaxWait = TMVirtualSyncGetNsToDeadline(PDMDevHlpGetVM(pThis->pDevInsR3));
    1112                     if (cNsMaxWait >= RT_NS_100US)
    1113                         RTSemEventMultiWaitEx(pSVGAState->hBusyDelayedEmts,
    1114                                               RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_NORESUME,
    1115                                               RT_MIN(cNsMaxWait, RT_NS_10MS));
     1086                    PDMDevHlpCritSectLeave(pDevIns, &pThis->CritSect); /* hack around lock order issue. */
     1087                    rc = VMR3WaitForDeviceReady(pVM, idCpu);
     1088                    PDMDevHlpCritSectEnter(pDevIns, &pThis->CritSect, VERR_IGNORED);
    11161089                }
    1117 
    11181090                ASMAtomicDecU32(&pSVGAState->cBusyDelayedEmts);
    1119             }
    1120             STAM_REL_PROFILE_STOP(&pSVGAState->StatBusyDelayEmts, EmtDelay);
     1091                VMCPUSET_ATOMIC_DEL(&pSVGAState->BusyDelayedEmts, idCpu);
     1092# else
     1093
     1094                /* Delay the EMT a bit so the FIFO and others can get some work done.
     1095                   This used to be a crude 50 ms sleep. The current code tries to be
     1096                   more efficient, but the consept is still very crude. */
     1097                PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
     1098                STAM_REL_PROFILE_START(&pSVGAState->StatBusyDelayEmts, EmtDelay);
     1099                RTThreadYield();
     1100                if (pThis->svga.fBusy)
     1101                {
     1102                    uint32_t cRefs = ASMAtomicIncU32(&pSVGAState->cBusyDelayedEmts);
     1103
     1104                    if (pThis->svga.fBusy && cRefs == 1)
     1105                        RTSemEventMultiReset(pSVGAState->hBusyDelayedEmts);
     1106                    if (pThis->svga.fBusy)
     1107                    {
     1108                        /** @todo If this code is going to stay, we need to call into the halt/wait
     1109                         *        code in VMEmt.cpp here, otherwise all kind of EMT interaction will
     1110                         *        suffer when the guest is polling on a busy FIFO. */
     1111                        uint64_t cNsMaxWait = TMVirtualSyncGetNsToDeadline(PDMDevHlpGetVM(pThis->pDevInsR3));
     1112                        if (cNsMaxWait >= RT_NS_100US)
     1113                            RTSemEventMultiWaitEx(pSVGAState->hBusyDelayedEmts,
     1114                                                  RTSEMWAIT_FLAGS_NANOSECS | RTSEMWAIT_FLAGS_RELATIVE | RTSEMWAIT_FLAGS_NORESUME,
     1115                                                  RT_MIN(cNsMaxWait, RT_NS_10MS));
     1116                    }
     1117
     1118                    ASMAtomicDecU32(&pSVGAState->cBusyDelayedEmts);
     1119                }
     1120                STAM_REL_PROFILE_STOP(&pSVGAState->StatBusyDelayEmts, EmtDelay);
    11211121# endif
    1122             *pu32 = pThis->svga.fBusy != 0;
     1122                *pu32 = pThis->svga.fBusy != 0;
    11231123#endif
     1124            }
     1125            else
     1126                *pu32 = false;
     1127            break;
     1128
     1129        case SVGA_REG_GUEST_ID:            /* Set guest OS identifier */
     1130            STAM_REL_COUNTER_INC(&pThis->svga.StatRegGuestIdRd);
     1131            *pu32 = pThis->svga.u32GuestId;
     1132            break;
     1133
     1134        case SVGA_REG_SCRATCH_SIZE:        /* Number of scratch registers */
     1135            STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchSizeRd);
     1136            *pu32 = pThis->svga.cScratchRegion;
     1137            break;
     1138
     1139        case SVGA_REG_MEM_REGS:            /* Number of FIFO registers */
     1140            STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemRegsRd);
     1141            *pu32 = SVGA_FIFO_NUM_REGS;
     1142            break;
     1143
     1144        case SVGA_REG_PITCHLOCK:           /* Fixed pitch for all modes */
     1145            STAM_REL_COUNTER_INC(&pThis->svga.StatRegPitchLockRd);
     1146            *pu32 = pThis->svga.u32PitchLock;
     1147            break;
     1148
     1149        case SVGA_REG_IRQMASK:             /* Interrupt mask */
     1150            STAM_REL_COUNTER_INC(&pThis->svga.StatRegIrqMaskRd);
     1151            *pu32 = pThis->svga.u32IrqMask;
     1152            break;
     1153
     1154        /* See "Guest memory regions" below. */
     1155        case SVGA_REG_GMR_ID:
     1156            STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrIdRd);
     1157            *pu32 = pThis->svga.u32CurrentGMRId;
     1158            break;
     1159
     1160        case SVGA_REG_GMR_DESCRIPTOR:
     1161            STAM_REL_COUNTER_INC(&pThis->svga.StatRegWriteOnlyRd);
     1162            /* Write only */
     1163            *pu32 = 0;
     1164            break;
     1165
     1166        case SVGA_REG_GMR_MAX_IDS:
     1167            STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrMaxIdsRd);
     1168            *pu32 = pThis->svga.cGMR;
     1169            break;
     1170
     1171        case SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH:
     1172            STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrMaxDescriptorLengthRd);
     1173            *pu32 = VMSVGA_MAX_GMR_PAGES;
     1174            break;
     1175
     1176        case SVGA_REG_TRACES:            /* Enable trace-based updates even when FIFO is on */
     1177            STAM_REL_COUNTER_INC(&pThis->svga.StatRegTracesRd);
     1178            *pu32 = pThis->svga.fTraces;
     1179            break;
     1180
     1181        case SVGA_REG_GMRS_MAX_PAGES:    /* Maximum number of 4KB pages for all GMRs */
     1182            STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrsMaxPagesRd);
     1183            *pu32 = VMSVGA_MAX_GMR_PAGES;
     1184            break;
     1185
     1186        case SVGA_REG_MEMORY_SIZE:       /* Total dedicated device memory excluding FIFO */
     1187            STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemorySizeRd);
     1188            *pu32 = VMSVGA_SURFACE_SIZE;
     1189            break;
     1190
     1191        case SVGA_REG_TOP:               /* Must be 1 more than the last register */
     1192            STAM_REL_COUNTER_INC(&pThis->svga.StatRegTopRd);
     1193            break;
     1194
     1195        /* Mouse cursor support. */
     1196        case SVGA_REG_CURSOR_ID:
     1197        case SVGA_REG_CURSOR_X:
     1198        case SVGA_REG_CURSOR_Y:
     1199        case SVGA_REG_CURSOR_ON:
     1200            STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorXxxxRd);
     1201            break;
     1202
     1203        /* Legacy multi-monitor support */
     1204        case SVGA_REG_NUM_GUEST_DISPLAYS:/* Number of guest displays in X/Y direction */
     1205            STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumGuestDisplaysRd);
     1206            *pu32 = 1;
     1207            break;
     1208
     1209        case SVGA_REG_DISPLAY_ID:        /* Display ID for the following display attributes */
     1210            STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIdRd);
     1211            *pu32 = 0;
     1212            break;
     1213
     1214        case SVGA_REG_DISPLAY_IS_PRIMARY:/* Whether this is a primary display */
     1215            STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIsPrimaryRd);
     1216            *pu32 = 0;
     1217            break;
     1218
     1219        case SVGA_REG_DISPLAY_POSITION_X:/* The display position x */
     1220            STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionXRd);
     1221            *pu32 = 0;
     1222            break;
     1223
     1224        case SVGA_REG_DISPLAY_POSITION_Y:/* The display position y */
     1225            STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionYRd);
     1226            *pu32 = 0;
     1227            break;
     1228
     1229        case SVGA_REG_DISPLAY_WIDTH:     /* The display's width */
     1230            STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayWidthRd);
     1231            *pu32 = pThis->svga.uWidth;
     1232            break;
     1233
     1234        case SVGA_REG_DISPLAY_HEIGHT:    /* The display's height */
     1235            STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayHeightRd);
     1236            *pu32 = pThis->svga.uHeight;
     1237            break;
     1238
     1239        case SVGA_REG_NUM_DISPLAYS:        /* (Deprecated) */
     1240            STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumDisplaysRd);
     1241            /* We must return something sensible here otherwise the Linux driver
     1242               will take a legacy code path without 3d support.  This number also
     1243               limits how many screens Linux guests will allow. */
     1244            *pu32 = pThis->cMonitors;
     1245            break;
     1246
     1247        default:
     1248        {
     1249            uint32_t offReg;
     1250            if ((offReg = idxReg - SVGA_SCRATCH_BASE) < pThis->svga.cScratchRegion)
     1251            {
     1252                RT_UNTRUSTED_VALIDATED_FENCE();
     1253                *pu32 = pThis->svga.au32ScratchRegion[offReg];
     1254                STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchRd);
     1255            }
     1256            else if ((offReg = idxReg - SVGA_PALETTE_BASE) < (uint32_t)SVGA_NUM_PALETTE_REGS)
     1257            {
     1258                /* Note! Using last_palette rather than palette here to preserve the VGA one. */
     1259                STAM_REL_COUNTER_INC(&pThis->svga.StatRegPaletteRd);
     1260                RT_UNTRUSTED_VALIDATED_FENCE();
     1261                uint32_t u32 = pThis->last_palette[offReg / 3];
     1262                switch (offReg % 3)
     1263                {
     1264                    case 0: *pu32 = (u32 >> 16) & 0xff; break; /* red */
     1265                    case 1: *pu32 = (u32 >>  8) & 0xff; break; /* green */
     1266                    case 2: *pu32 =  u32        & 0xff; break; /* blue */
     1267                }
     1268            }
     1269            else
     1270            {
     1271#if !defined(IN_RING3) && defined(VBOX_STRICT)
     1272                rc = VINF_IOM_R3_IOPORT_READ;
     1273#else
     1274                STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownRd);
     1275
     1276                /* Do not assert. The guest might be reading all registers. */
     1277                LogFunc(("Unknown reg=%#x\n", idxReg));
     1278#endif
     1279            }
     1280            break;
    11241281        }
    1125         else
    1126             *pu32 = false;
    1127         break;
    1128 
    1129     case SVGA_REG_GUEST_ID:            /* Set guest OS identifier */
    1130         STAM_REL_COUNTER_INC(&pThis->svga.StatRegGuestIdRd);
    1131         *pu32 = pThis->svga.u32GuestId;
    1132         break;
    1133 
    1134     case SVGA_REG_SCRATCH_SIZE:        /* Number of scratch registers */
    1135         STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchSizeRd);
    1136         *pu32 = pThis->svga.cScratchRegion;
    1137         break;
    1138 
    1139     case SVGA_REG_MEM_REGS:            /* Number of FIFO registers */
    1140         STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemRegsRd);
    1141         *pu32 = SVGA_FIFO_NUM_REGS;
    1142         break;
    1143 
    1144     case SVGA_REG_PITCHLOCK:           /* Fixed pitch for all modes */
    1145         STAM_REL_COUNTER_INC(&pThis->svga.StatRegPitchLockRd);
    1146         *pu32 = pThis->svga.u32PitchLock;
    1147         break;
    1148 
    1149     case SVGA_REG_IRQMASK:             /* Interrupt mask */
    1150         STAM_REL_COUNTER_INC(&pThis->svga.StatRegIrqMaskRd);
    1151         *pu32 = pThis->svga.u32IrqMask;
    1152         break;
    1153 
    1154     /* See "Guest memory regions" below. */
    1155     case SVGA_REG_GMR_ID:
    1156         STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrIdRd);
    1157         *pu32 = pThis->svga.u32CurrentGMRId;
    1158         break;
    1159 
    1160     case SVGA_REG_GMR_DESCRIPTOR:
    1161         STAM_REL_COUNTER_INC(&pThis->svga.StatRegWriteOnlyRd);
    1162         /* Write only */
    1163         *pu32 = 0;
    1164         break;
    1165 
    1166     case SVGA_REG_GMR_MAX_IDS:
    1167         STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrMaxIdsRd);
    1168         *pu32 = pThis->svga.cGMR;
    1169         break;
    1170 
    1171     case SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH:
    1172         STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrMaxDescriptorLengthRd);
    1173         *pu32 = VMSVGA_MAX_GMR_PAGES;
    1174         break;
    1175 
    1176     case SVGA_REG_TRACES:            /* Enable trace-based updates even when FIFO is on */
    1177         STAM_REL_COUNTER_INC(&pThis->svga.StatRegTracesRd);
    1178         *pu32 = pThis->svga.fTraces;
    1179         break;
    1180 
    1181     case SVGA_REG_GMRS_MAX_PAGES:    /* Maximum number of 4KB pages for all GMRs */
    1182         STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrsMaxPagesRd);
    1183         *pu32 = VMSVGA_MAX_GMR_PAGES;
    1184         break;
    1185 
    1186     case SVGA_REG_MEMORY_SIZE:       /* Total dedicated device memory excluding FIFO */
    1187         STAM_REL_COUNTER_INC(&pThis->svga.StatRegMemorySizeRd);
    1188         *pu32 = VMSVGA_SURFACE_SIZE;
    1189         break;
    1190 
    1191     case SVGA_REG_TOP:               /* Must be 1 more than the last register */
    1192         STAM_REL_COUNTER_INC(&pThis->svga.StatRegTopRd);
    1193         break;
    1194 
    1195     /* Mouse cursor support. */
    1196     case SVGA_REG_CURSOR_ID:
    1197     case SVGA_REG_CURSOR_X:
    1198     case SVGA_REG_CURSOR_Y:
    1199     case SVGA_REG_CURSOR_ON:
    1200         STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorXxxxRd);
    1201         break;
    1202 
    1203     /* Legacy multi-monitor support */
    1204     case SVGA_REG_NUM_GUEST_DISPLAYS:/* Number of guest displays in X/Y direction */
    1205         STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumGuestDisplaysRd);
    1206         *pu32 = 1;
    1207         break;
    1208 
    1209     case SVGA_REG_DISPLAY_ID:        /* Display ID for the following display attributes */
    1210         STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIdRd);
    1211         *pu32 = 0;
    1212         break;
    1213 
    1214     case SVGA_REG_DISPLAY_IS_PRIMARY:/* Whether this is a primary display */
    1215         STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIsPrimaryRd);
    1216         *pu32 = 0;
    1217         break;
    1218 
    1219     case SVGA_REG_DISPLAY_POSITION_X:/* The display position x */
    1220         STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionXRd);
    1221         *pu32 = 0;
    1222         break;
    1223 
    1224     case SVGA_REG_DISPLAY_POSITION_Y:/* The display position y */
    1225         STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionYRd);
    1226         *pu32 = 0;
    1227         break;
    1228 
    1229     case SVGA_REG_DISPLAY_WIDTH:     /* The display's width */
    1230         STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayWidthRd);
    1231         *pu32 = pThis->svga.uWidth;
    1232         break;
    1233 
    1234     case SVGA_REG_DISPLAY_HEIGHT:    /* The display's height */
    1235         STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayHeightRd);
    1236         *pu32 = pThis->svga.uHeight;
    1237         break;
    1238 
    1239     case SVGA_REG_NUM_DISPLAYS:        /* (Deprecated) */
    1240         STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumDisplaysRd);
    1241         /* We must return something sensible here otherwise the Linux driver
    1242            will take a legacy code path without 3d support.  This number also
    1243            limits how many screens Linux guests will allow. */
    1244         *pu32 = pThis->cMonitors;
    1245         break;
    1246 
    1247     default:
    1248     {
    1249         uint32_t offReg;
    1250         if ((offReg = idxReg - SVGA_SCRATCH_BASE) < pThis->svga.cScratchRegion)
    1251         {
    1252             RT_UNTRUSTED_VALIDATED_FENCE();
    1253             *pu32 = pThis->svga.au32ScratchRegion[offReg];
    1254             STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchRd);
    1255         }
    1256         else if ((offReg = idxReg - SVGA_PALETTE_BASE) < (uint32_t)SVGA_NUM_PALETTE_REGS)
    1257         {
    1258             /* Note! Using last_palette rather than palette here to preserve the VGA one. */
    1259             STAM_REL_COUNTER_INC(&pThis->svga.StatRegPaletteRd);
    1260             RT_UNTRUSTED_VALIDATED_FENCE();
    1261             uint32_t u32 = pThis->last_palette[offReg / 3];
    1262             switch (offReg % 3)
    1263             {
    1264                 case 0: *pu32 = (u32 >> 16) & 0xff; break; /* red */
    1265                 case 1: *pu32 = (u32 >>  8) & 0xff; break; /* green */
    1266                 case 2: *pu32 =  u32        & 0xff; break; /* blue */
    1267             }
    1268         }
    1269         else
    1270         {
    1271 #if !defined(IN_RING3) && defined(VBOX_STRICT)
    1272             rc = VINF_IOM_R3_IOPORT_READ;
    1273 #else
    1274             STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownRd);
    1275 
    1276             /* Do not assert. The guest might be reading all registers. */
    1277             LogFunc(("Unknown reg=%#x\n", idxReg));
    1278 #endif
    1279         }
    1280         break;
    1281     }
    12821282    }
    12831283    Log(("vmsvgaReadPort index=%s (%d) val=%#x rc=%x\n", vmsvgaIndexToString(pThis, idxReg), idxReg, *pu32, rc));
     
    15061506 * Write port register
    15071507 *
    1508  * @returns VBox status code.
     1508 * @returns Strict VBox status code.
    15091509 * @param   pThis       VMSVGA State
    15101510 * @param   u32         Value to write
    15111511 */
    1512 static int vmsvgaWritePort(PVGASTATE pThis, uint32_t u32)
     1512static VBOXSTRICTRC vmsvgaWritePort(PVGASTATE pThis, uint32_t u32)
    15131513{
    15141514#ifdef IN_RING3
    15151515    PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State;
    15161516#endif
    1517     int            rc = VINF_SUCCESS;
     1517    VBOXSTRICTRC rc = VINF_SUCCESS;
    15181518
    15191519    /* Rough index register validation. */
     
    15521552    switch (idxReg)
    15531553    {
    1554     case SVGA_REG_ID:
    1555         STAM_REL_COUNTER_INC(&pThis->svga.StatRegIdWr);
    1556         if (   u32 == SVGA_ID_0
    1557             || u32 == SVGA_ID_1
    1558             || u32 == SVGA_ID_2)
    1559             pThis->svga.u32SVGAId = u32;
    1560         else
    1561             PDMDevHlpDBGFStop(pThis->CTX_SUFF(pDevIns), RT_SRC_POS, "Trying to set SVGA_REG_ID to %#x (%d)\n", u32, u32);
    1562         break;
    1563 
    1564     case SVGA_REG_ENABLE:
    1565         STAM_REL_COUNTER_INC(&pThis->svga.StatRegEnableWr);
     1554        case SVGA_REG_ID:
     1555            STAM_REL_COUNTER_INC(&pThis->svga.StatRegIdWr);
     1556            if (   u32 == SVGA_ID_0
     1557                || u32 == SVGA_ID_1
     1558                || u32 == SVGA_ID_2)
     1559                pThis->svga.u32SVGAId = u32;
     1560            else
     1561                PDMDevHlpDBGFStop(pThis->CTX_SUFF(pDevIns), RT_SRC_POS, "Trying to set SVGA_REG_ID to %#x (%d)\n", u32, u32);
     1562            break;
     1563
     1564        case SVGA_REG_ENABLE:
     1565            STAM_REL_COUNTER_INC(&pThis->svga.StatRegEnableWr);
    15661566#ifdef IN_RING3
    1567         if (    (u32 & SVGA_REG_ENABLE_ENABLE)
    1568             &&  pThis->svga.fEnabled == false)
    1569         {
    1570             /* Make a backup copy of the first 512kb in order to save font data etc. */
    1571             /** @todo should probably swap here, rather than copy + zero */
    1572             memcpy(pThis->svga.pbVgaFrameBufferR3, pThis->vram_ptrR3, VMSVGA_VGA_FB_BACKUP_SIZE);
    1573             memset(pThis->vram_ptrR3, 0, VMSVGA_VGA_FB_BACKUP_SIZE);
    1574         }
    1575 
    1576         pThis->svga.fEnabled = u32;
    1577         if (pThis->svga.fEnabled)
    1578         {
    1579             if (    pThis->svga.uWidth  == VMSVGA_VAL_UNINITIALIZED
    1580                 &&  pThis->svga.uHeight == VMSVGA_VAL_UNINITIALIZED
    1581                 &&  pThis->svga.uBpp    == VMSVGA_VAL_UNINITIALIZED)
    1582             {
    1583                 /* Keep the current mode. */
    1584                 pThis->svga.uWidth  = pThis->pDrv->cx;
    1585                 pThis->svga.uHeight = pThis->pDrv->cy;
    1586                 pThis->svga.uBpp    = (pThis->pDrv->cBits + 7) & ~7;
    1587             }
    1588 
    1589             if (    pThis->svga.uWidth  != VMSVGA_VAL_UNINITIALIZED
    1590                 &&  pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED
    1591                 &&  pThis->svga.uBpp    != VMSVGA_VAL_UNINITIALIZED)
    1592             {
    1593                 ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
    1594             }
     1567            if (    (u32 & SVGA_REG_ENABLE_ENABLE)
     1568                &&  pThis->svga.fEnabled == false)
     1569            {
     1570                /* Make a backup copy of the first 512kb in order to save font data etc. */
     1571                /** @todo should probably swap here, rather than copy + zero */
     1572                memcpy(pThis->svga.pbVgaFrameBufferR3, pThis->vram_ptrR3, VMSVGA_VGA_FB_BACKUP_SIZE);
     1573                memset(pThis->vram_ptrR3, 0, VMSVGA_VGA_FB_BACKUP_SIZE);
     1574            }
     1575
     1576            pThis->svga.fEnabled = u32;
     1577            if (pThis->svga.fEnabled)
     1578            {
     1579                if (    pThis->svga.uWidth  == VMSVGA_VAL_UNINITIALIZED
     1580                    &&  pThis->svga.uHeight == VMSVGA_VAL_UNINITIALIZED
     1581                    &&  pThis->svga.uBpp    == VMSVGA_VAL_UNINITIALIZED)
     1582                {
     1583                    /* Keep the current mode. */
     1584                    pThis->svga.uWidth  = pThis->pDrv->cx;
     1585                    pThis->svga.uHeight = pThis->pDrv->cy;
     1586                    pThis->svga.uBpp    = (pThis->pDrv->cBits + 7) & ~7;
     1587                }
     1588
     1589                if (    pThis->svga.uWidth  != VMSVGA_VAL_UNINITIALIZED
     1590                    &&  pThis->svga.uHeight != VMSVGA_VAL_UNINITIALIZED
     1591                    &&  pThis->svga.uBpp    != VMSVGA_VAL_UNINITIALIZED)
     1592                    ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
    15951593# ifdef LOG_ENABLED
    1596             uint32_t *pFIFO = pThis->svga.pFIFOR3;
    1597             Log(("configured=%d busy=%d\n", pThis->svga.fConfigured, pFIFO[SVGA_FIFO_BUSY]));
    1598             Log(("next %x stop %x\n", pFIFO[SVGA_FIFO_NEXT_CMD], pFIFO[SVGA_FIFO_STOP]));
     1594                uint32_t *pFIFO = pThis->svga.pFIFOR3;
     1595                Log(("configured=%d busy=%d\n", pThis->svga.fConfigured, pFIFO[SVGA_FIFO_BUSY]));
     1596                Log(("next %x stop %x\n", pFIFO[SVGA_FIFO_NEXT_CMD], pFIFO[SVGA_FIFO_STOP]));
    15991597# endif
    16001598
    1601             /* Disable or enable dirty page tracking according to the current fTraces value. */
     1599                /* Disable or enable dirty page tracking according to the current fTraces value. */
     1600                vmsvgaSetTraces(pThis, !!pThis->svga.fTraces);
     1601
     1602                /* bird: Whatever this is was added to make screenshot work, ask sunlover should explain... */
     1603                for (uint32_t idScreen = 0; idScreen < pThis->cMonitors; ++idScreen)
     1604                    pThis->pDrv->pfnVBVAEnable(pThis->pDrv, idScreen, NULL /*pHostFlags*/);
     1605            }
     1606            else
     1607            {
     1608                /* Restore the text mode backup. */
     1609                memcpy(pThis->vram_ptrR3, pThis->svga.pbVgaFrameBufferR3, VMSVGA_VGA_FB_BACKUP_SIZE);
     1610
     1611                pThis->pDrv->pfnLFBModeChange(pThis->pDrv, false);
     1612
     1613                /* Enable dirty page tracking again when going into legacy mode. */
     1614                vmsvgaSetTraces(pThis, true);
     1615
     1616                /* bird: Whatever this is was added to make screenshot work, ask sunlover should explain... */
     1617                for (uint32_t idScreen = 0; idScreen < pThis->cMonitors; ++idScreen)
     1618                    pThis->pDrv->pfnVBVADisable(pThis->pDrv, idScreen);
     1619
     1620                /* Clear the pitch lock. */
     1621                pThis->svga.u32PitchLock = 0;
     1622            }
     1623#else  /* !IN_RING3 */
     1624            rc = VINF_IOM_R3_IOPORT_WRITE;
     1625#endif /* !IN_RING3 */
     1626            break;
     1627
     1628        case SVGA_REG_WIDTH:
     1629            STAM_REL_COUNTER_INC(&pThis->svga.StatRegWidthWr);
     1630            if (pThis->svga.uWidth != u32)
     1631            {
     1632#if defined(IN_RING3) || defined(IN_RING0)
     1633                pThis->svga.uWidth = u32;
     1634                vmsvgaUpdatePitch(pThis);
     1635                if (pThis->svga.fEnabled)
     1636                    ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
     1637#else
     1638                rc = VINF_IOM_R3_IOPORT_WRITE;
     1639#endif
     1640            }
     1641            /* else: nop */
     1642            break;
     1643
     1644        case SVGA_REG_HEIGHT:
     1645            STAM_REL_COUNTER_INC(&pThis->svga.StatRegHeightWr);
     1646            if (pThis->svga.uHeight != u32)
     1647            {
     1648                pThis->svga.uHeight = u32;
     1649                if (pThis->svga.fEnabled)
     1650                    ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
     1651            }
     1652            /* else: nop */
     1653            break;
     1654
     1655        case SVGA_REG_DEPTH:
     1656            STAM_REL_COUNTER_INC(&pThis->svga.StatRegDepthWr);
     1657            /** @todo read-only?? */
     1658            break;
     1659
     1660        case SVGA_REG_BITS_PER_PIXEL:      /* Current bpp in the guest */
     1661            STAM_REL_COUNTER_INC(&pThis->svga.StatRegBitsPerPixelWr);
     1662            if (pThis->svga.uBpp != u32)
     1663            {
     1664#if defined(IN_RING3) || defined(IN_RING0)
     1665                pThis->svga.uBpp = u32;
     1666                vmsvgaUpdatePitch(pThis);
     1667                if (pThis->svga.fEnabled)
     1668                    ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
     1669#else
     1670                rc = VINF_IOM_R3_IOPORT_WRITE;
     1671#endif
     1672            }
     1673            /* else: nop */
     1674            break;
     1675
     1676        case SVGA_REG_PSEUDOCOLOR:
     1677            STAM_REL_COUNTER_INC(&pThis->svga.StatRegPseudoColorWr);
     1678            break;
     1679
     1680        case SVGA_REG_CONFIG_DONE:         /* Set when memory area configured */
     1681#ifdef IN_RING3
     1682            STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegConfigDoneWr);
     1683            pThis->svga.fConfigured = u32;
     1684            /* Disabling the FIFO enables tracing (dirty page detection) by default. */
     1685            if (!pThis->svga.fConfigured)
     1686                pThis->svga.fTraces = true;
    16021687            vmsvgaSetTraces(pThis, !!pThis->svga.fTraces);
    1603 
    1604             /* bird: Whatever this is was added to make screenshot work, ask sunlover should explain... */
    1605             for (uint32_t idScreen = 0; idScreen < pThis->cMonitors; ++idScreen)
    1606                 pThis->pDrv->pfnVBVAEnable(pThis->pDrv, idScreen, NULL /*pHostFlags*/);
    1607         }
    1608         else
    1609         {
    1610             /* Restore the text mode backup. */
    1611             memcpy(pThis->vram_ptrR3, pThis->svga.pbVgaFrameBufferR3, VMSVGA_VGA_FB_BACKUP_SIZE);
    1612 
    1613             pThis->pDrv->pfnLFBModeChange(pThis->pDrv, false);
    1614 
    1615             /* Enable dirty page tracking again when going into legacy mode. */
    1616             vmsvgaSetTraces(pThis, true);
    1617 
    1618             /* bird: Whatever this is was added to make screenshot work, ask sunlover should explain... */
    1619             for (uint32_t idScreen = 0; idScreen < pThis->cMonitors; ++idScreen)
    1620                 pThis->pDrv->pfnVBVADisable(pThis->pDrv, idScreen);
    1621 
    1622             /* Clear the pitch lock. */
    1623             pThis->svga.u32PitchLock = 0;
    1624         }
    1625 #else  /* !IN_RING3 */
    1626         rc = VINF_IOM_R3_IOPORT_WRITE;
    1627 #endif /* !IN_RING3 */
    1628         break;
    1629 
    1630     case SVGA_REG_WIDTH:
    1631         STAM_REL_COUNTER_INC(&pThis->svga.StatRegWidthWr);
    1632         if (pThis->svga.uWidth != u32)
    1633         {
    1634 #if defined(IN_RING3) || defined(IN_RING0)
    1635             pThis->svga.uWidth = u32;
    1636             vmsvgaUpdatePitch(pThis);
    1637             if (pThis->svga.fEnabled)
    1638             {
    1639                 ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
    1640             }
    16411688#else
    16421689            rc = VINF_IOM_R3_IOPORT_WRITE;
    16431690#endif
     1691            break;
     1692
     1693        case SVGA_REG_SYNC:                /* See "FIFO Synchronization Registers" */
     1694            STAM_REL_COUNTER_INC(&pThis->svga.StatRegSyncWr);
     1695            if (    pThis->svga.fEnabled
     1696                &&  pThis->svga.fConfigured)
     1697            {
     1698#if defined(IN_RING3) || defined(IN_RING0)
     1699                Log(("SVGA_REG_SYNC: SVGA_FIFO_BUSY=%d\n", pThis->svga.CTX_SUFF(pFIFO)[SVGA_FIFO_BUSY]));
     1700                ASMAtomicWriteU32(&pThis->svga.fBusy, VMSVGA_BUSY_F_EMT_FORCE | VMSVGA_BUSY_F_FIFO);
     1701                if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, pThis->svga.CTX_SUFF(pFIFO)[SVGA_FIFO_MIN]))
     1702                    vmsvgaSafeFifoBusyRegUpdate(pThis, true);
     1703
     1704                /* Kick the FIFO thread to start processing commands again. */
     1705                SUPSemEventSignal(pThis->svga.pSupDrvSession, pThis->svga.FIFORequestSem);
     1706#else
     1707                rc = VINF_IOM_R3_IOPORT_WRITE;
     1708#endif
     1709            }
     1710            /* else nothing to do. */
     1711            else
     1712                Log(("Sync ignored enabled=%d configured=%d\n", pThis->svga.fEnabled, pThis->svga.fConfigured));
     1713
     1714            break;
     1715
     1716        case SVGA_REG_BUSY:                /* See "FIFO Synchronization Registers" (read-only) */
     1717            STAM_REL_COUNTER_INC(&pThis->svga.StatRegBusyWr);
     1718            break;
     1719
     1720        case SVGA_REG_GUEST_ID:            /* Set guest OS identifier */
     1721            STAM_REL_COUNTER_INC(&pThis->svga.StatRegGuestIdWr);
     1722            pThis->svga.u32GuestId = u32;
     1723            break;
     1724
     1725        case SVGA_REG_PITCHLOCK:           /* Fixed pitch for all modes */
     1726            STAM_REL_COUNTER_INC(&pThis->svga.StatRegPitchLockWr);
     1727            pThis->svga.u32PitchLock = u32;
     1728            /* Should this also update the FIFO pitch lock? Unclear. */
     1729            break;
     1730
     1731        case SVGA_REG_IRQMASK:             /* Interrupt mask */
     1732            STAM_REL_COUNTER_INC(&pThis->svga.StatRegIrqMaskWr);
     1733            pThis->svga.u32IrqMask = u32;
     1734
     1735            /* Irq pending after the above change? */
     1736            if (pThis->svga.u32IrqStatus & u32)
     1737            {
     1738                Log(("SVGA_REG_IRQMASK: Trigger interrupt with status %x\n", pThis->svga.u32IrqStatus));
     1739                PDMDevHlpPCISetIrqNoWait(pThis->CTX_SUFF(pDevIns), 0, 1);
     1740            }
     1741            else
     1742                PDMDevHlpPCISetIrqNoWait(pThis->CTX_SUFF(pDevIns), 0, 0);
     1743            break;
     1744
     1745        /* Mouse cursor support */
     1746        case SVGA_REG_CURSOR_ID:
     1747        case SVGA_REG_CURSOR_X:
     1748        case SVGA_REG_CURSOR_Y:
     1749        case SVGA_REG_CURSOR_ON:
     1750            STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorXxxxWr);
     1751            break;
     1752
     1753        /* Legacy multi-monitor support */
     1754        case SVGA_REG_NUM_GUEST_DISPLAYS:/* Number of guest displays in X/Y direction */
     1755            STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumGuestDisplaysWr);
     1756            break;
     1757        case SVGA_REG_DISPLAY_ID:        /* Display ID for the following display attributes */
     1758            STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIdWr);
     1759            break;
     1760        case SVGA_REG_DISPLAY_IS_PRIMARY:/* Whether this is a primary display */
     1761            STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIsPrimaryWr);
     1762            break;
     1763        case SVGA_REG_DISPLAY_POSITION_X:/* The display position x */
     1764            STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionXWr);
     1765            break;
     1766        case SVGA_REG_DISPLAY_POSITION_Y:/* The display position y */
     1767            STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionYWr);
     1768            break;
     1769        case SVGA_REG_DISPLAY_WIDTH:     /* The display's width */
     1770            STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayWidthWr);
     1771            break;
     1772        case SVGA_REG_DISPLAY_HEIGHT:    /* The display's height */
     1773            STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayHeightWr);
     1774            break;
     1775#ifdef VBOX_WITH_VMSVGA3D
     1776        /* See "Guest memory regions" below. */
     1777        case SVGA_REG_GMR_ID:
     1778            STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrIdWr);
     1779            pThis->svga.u32CurrentGMRId = u32;
     1780            break;
     1781
     1782        case SVGA_REG_GMR_DESCRIPTOR:
     1783# ifndef IN_RING3
     1784            rc = VINF_IOM_R3_IOPORT_WRITE;
     1785            break;
     1786# else /* IN_RING3 */
     1787        {
     1788            STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWr);
     1789
     1790            /* Validate current GMR id. */
     1791            uint32_t idGMR = pThis->svga.u32CurrentGMRId;
     1792            AssertBreak(idGMR < pThis->svga.cGMR);
     1793            RT_UNTRUSTED_VALIDATED_FENCE();
     1794
     1795            /* Free the old GMR if present. */
     1796            vmsvgaGMRFree(pThis, idGMR);
     1797
     1798            /* Just undefine the GMR? */
     1799            RTGCPHYS GCPhys = (RTGCPHYS)u32 << PAGE_SHIFT;
     1800            if (GCPhys == 0)
     1801            {
     1802                STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWrFree);
     1803                break;
     1804            }
     1805
     1806
     1807            /* Never cross a page boundary automatically. */
     1808            const uint32_t          cMaxPages   = RT_MIN(VMSVGA_MAX_GMR_PAGES, UINT32_MAX / X86_PAGE_SIZE);
     1809            uint32_t                cPagesTotal = 0;
     1810            uint32_t                iDesc       = 0;
     1811            PVMSVGAGMRDESCRIPTOR    paDescs     = NULL;
     1812            uint32_t                cLoops      = 0;
     1813            RTGCPHYS                GCPhysBase  = GCPhys;
     1814            while (PHYS_PAGE_ADDRESS(GCPhys) == PHYS_PAGE_ADDRESS(GCPhysBase))
     1815            {
     1816                /* Read descriptor. */
     1817                SVGAGuestMemDescriptor desc;
     1818                rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, &desc, sizeof(desc));
     1819                AssertRCBreak(VBOXSTRICTRC_VAL(rc));
     1820
     1821                if (desc.numPages != 0)
     1822                {
     1823                    AssertBreakStmt(desc.numPages <= cMaxPages, rc = VERR_OUT_OF_RANGE);
     1824                    cPagesTotal += desc.numPages;
     1825                    AssertBreakStmt(cPagesTotal   <= cMaxPages, rc = VERR_OUT_OF_RANGE);
     1826
     1827                    if ((iDesc & 15) == 0)
     1828                    {
     1829                        void *pvNew = RTMemRealloc(paDescs, (iDesc + 16) * sizeof(VMSVGAGMRDESCRIPTOR));
     1830                        AssertBreakStmt(pvNew, rc = VERR_NO_MEMORY);
     1831                        paDescs = (PVMSVGAGMRDESCRIPTOR)pvNew;
     1832                    }
     1833
     1834                    paDescs[iDesc].GCPhys     = (RTGCPHYS)desc.ppn << PAGE_SHIFT;
     1835                    paDescs[iDesc++].numPages = desc.numPages;
     1836
     1837                    /* Continue with the next descriptor. */
     1838                    GCPhys += sizeof(desc);
     1839                }
     1840                else if (desc.ppn == 0)
     1841                    break;  /* terminator */
     1842                else /* Pointer to the next physical page of descriptors. */
     1843                    GCPhys = GCPhysBase = (RTGCPHYS)desc.ppn << PAGE_SHIFT;
     1844
     1845                cLoops++;
     1846                AssertBreakStmt(cLoops < VMSVGA_MAX_GMR_DESC_LOOP_COUNT, rc = VERR_OUT_OF_RANGE);
     1847            }
     1848
     1849            AssertStmt(iDesc > 0 || RT_FAILURE_NP(rc), rc = VERR_OUT_OF_RANGE);
     1850            if (RT_SUCCESS(rc))
     1851            {
     1852                /* Commit the GMR. */
     1853                pSVGAState->paGMR[idGMR].paDesc         = paDescs;
     1854                pSVGAState->paGMR[idGMR].numDescriptors = iDesc;
     1855                pSVGAState->paGMR[idGMR].cMaxPages      = cPagesTotal;
     1856                pSVGAState->paGMR[idGMR].cbTotal        = cPagesTotal * PAGE_SIZE;
     1857                Assert((pSVGAState->paGMR[idGMR].cbTotal >> PAGE_SHIFT) == cPagesTotal);
     1858                Log(("Defined new gmr %x numDescriptors=%d cbTotal=%x (%#x pages)\n",
     1859                     idGMR, iDesc, pSVGAState->paGMR[idGMR].cbTotal, cPagesTotal));
     1860            }
     1861            else
     1862            {
     1863                RTMemFree(paDescs);
     1864                STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWrErrors);
     1865            }
     1866            break;
    16441867        }
    1645         /* else: nop */
    1646         break;
    1647 
    1648     case SVGA_REG_HEIGHT:
    1649         STAM_REL_COUNTER_INC(&pThis->svga.StatRegHeightWr);
    1650         if (pThis->svga.uHeight != u32)
    1651         {
    1652             pThis->svga.uHeight = u32;
    1653             if (pThis->svga.fEnabled)
    1654             {
    1655                 ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
    1656             }
    1657         }
    1658         /* else: nop */
    1659         break;
    1660 
    1661     case SVGA_REG_DEPTH:
    1662         STAM_REL_COUNTER_INC(&pThis->svga.StatRegDepthWr);
    1663         /** @todo read-only?? */
    1664         break;
    1665 
    1666     case SVGA_REG_BITS_PER_PIXEL:      /* Current bpp in the guest */
    1667         STAM_REL_COUNTER_INC(&pThis->svga.StatRegBitsPerPixelWr);
    1668         if (pThis->svga.uBpp != u32)
    1669         {
    1670 #if defined(IN_RING3) || defined(IN_RING0)
    1671             pThis->svga.uBpp = u32;
    1672             vmsvgaUpdatePitch(pThis);
    1673             if (pThis->svga.fEnabled)
    1674             {
    1675                 ASMAtomicOrU32(&pThis->svga.u32ActionFlags, VMSVGA_ACTION_CHANGEMODE);
    1676             }
     1868# endif /* IN_RING3 */
     1869#endif // VBOX_WITH_VMSVGA3D
     1870
     1871        case SVGA_REG_TRACES:            /* Enable trace-based updates even when FIFO is on */
     1872            STAM_REL_COUNTER_INC(&pThis->svga.StatRegTracesWr);
     1873            if (pThis->svga.fTraces == u32)
     1874                break; /* nothing to do */
     1875
     1876#ifdef IN_RING3
     1877            vmsvgaSetTraces(pThis, !!u32);
    16771878#else
    16781879            rc = VINF_IOM_R3_IOPORT_WRITE;
    16791880#endif
     1881            break;
     1882
     1883        case SVGA_REG_TOP:               /* Must be 1 more than the last register */
     1884            STAM_REL_COUNTER_INC(&pThis->svga.StatRegTopWr);
     1885            break;
     1886
     1887        case SVGA_REG_NUM_DISPLAYS:        /* (Deprecated) */
     1888            STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumDisplaysWr);
     1889            Log(("Write to deprecated register %x - val %x ignored\n", idxReg, u32));
     1890            break;
     1891
     1892        case SVGA_REG_FB_START:
     1893        case SVGA_REG_MEM_START:
     1894        case SVGA_REG_HOST_BITS_PER_PIXEL:
     1895        case SVGA_REG_MAX_WIDTH:
     1896        case SVGA_REG_MAX_HEIGHT:
     1897        case SVGA_REG_VRAM_SIZE:
     1898        case SVGA_REG_FB_SIZE:
     1899        case SVGA_REG_CAPABILITIES:
     1900        case SVGA_REG_MEM_SIZE:
     1901        case SVGA_REG_SCRATCH_SIZE:        /* Number of scratch registers */
     1902        case SVGA_REG_MEM_REGS:            /* Number of FIFO registers */
     1903        case SVGA_REG_BYTES_PER_LINE:
     1904        case SVGA_REG_FB_OFFSET:
     1905        case SVGA_REG_RED_MASK:
     1906        case SVGA_REG_GREEN_MASK:
     1907        case SVGA_REG_BLUE_MASK:
     1908        case SVGA_REG_GMRS_MAX_PAGES:    /* Maximum number of 4KB pages for all GMRs */
     1909        case SVGA_REG_MEMORY_SIZE:       /* Total dedicated device memory excluding FIFO */
     1910        case SVGA_REG_GMR_MAX_IDS:
     1911        case SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH:
     1912            /* Read only - ignore. */
     1913            Log(("Write to R/O register %x - val %x ignored\n", idxReg, u32));
     1914            STAM_REL_COUNTER_INC(&pThis->svga.StatRegReadOnlyWr);
     1915            break;
     1916
     1917        default:
     1918        {
     1919            uint32_t offReg;
     1920            if ((offReg = idxReg - SVGA_SCRATCH_BASE) < pThis->svga.cScratchRegion)
     1921            {
     1922                RT_UNTRUSTED_VALIDATED_FENCE();
     1923                pThis->svga.au32ScratchRegion[offReg] = u32;
     1924                STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchWr);
     1925            }
     1926            else if ((offReg = idxReg - SVGA_PALETTE_BASE) < (uint32_t)SVGA_NUM_PALETTE_REGS)
     1927            {
     1928                /* Note! Using last_palette rather than palette here to preserve the VGA one.
     1929                         Btw, see rgb_to_pixel32.  */
     1930                STAM_REL_COUNTER_INC(&pThis->svga.StatRegPaletteWr);
     1931                u32 &= 0xff;
     1932                RT_UNTRUSTED_VALIDATED_FENCE();
     1933                uint32_t uRgb = pThis->last_palette[offReg / 3];
     1934                switch (offReg % 3)
     1935                {
     1936                    case 0: uRgb = (uRgb & UINT32_C(0x0000ffff)) | (u32 << 16); break; /* red */
     1937                    case 1: uRgb = (uRgb & UINT32_C(0x00ff00ff)) | (u32 <<  8); break; /* green */
     1938                    case 2: uRgb = (uRgb & UINT32_C(0x00ffff00)) |  u32       ; break; /* blue */
     1939                }
     1940                pThis->last_palette[offReg / 3] = uRgb;
     1941            }
     1942            else
     1943            {
     1944#if !defined(IN_RING3) && defined(VBOX_STRICT)
     1945                rc = VINF_IOM_R3_IOPORT_WRITE;
     1946#else
     1947                STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownWr);
     1948                AssertMsgFailed(("reg=%#x u32=%#x\n", idxReg, u32));
     1949#endif
     1950            }
     1951            break;
    16801952        }
    1681         /* else: nop */
    1682         break;
    1683 
    1684     case SVGA_REG_PSEUDOCOLOR:
    1685         STAM_REL_COUNTER_INC(&pThis->svga.StatRegPseudoColorWr);
    1686         break;
    1687 
    1688     case SVGA_REG_CONFIG_DONE:         /* Set when memory area configured */
    1689 #ifdef IN_RING3
    1690         STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegConfigDoneWr);
    1691         pThis->svga.fConfigured = u32;
    1692         /* Disabling the FIFO enables tracing (dirty page detection) by default. */
    1693         if (!pThis->svga.fConfigured)
    1694         {
    1695             pThis->svga.fTraces = true;
    1696         }
    1697         vmsvgaSetTraces(pThis, !!pThis->svga.fTraces);
    1698 #else
    1699         rc = VINF_IOM_R3_IOPORT_WRITE;
    1700 #endif
    1701         break;
    1702 
    1703     case SVGA_REG_SYNC:                /* See "FIFO Synchronization Registers" */
    1704         STAM_REL_COUNTER_INC(&pThis->svga.StatRegSyncWr);
    1705         if (    pThis->svga.fEnabled
    1706             &&  pThis->svga.fConfigured)
    1707         {
    1708 #if defined(IN_RING3) || defined(IN_RING0)
    1709             Log(("SVGA_REG_SYNC: SVGA_FIFO_BUSY=%d\n", pThis->svga.CTX_SUFF(pFIFO)[SVGA_FIFO_BUSY]));
    1710             ASMAtomicWriteU32(&pThis->svga.fBusy, VMSVGA_BUSY_F_EMT_FORCE | VMSVGA_BUSY_F_FIFO);
    1711             if (VMSVGA_IS_VALID_FIFO_REG(SVGA_FIFO_BUSY, pThis->svga.CTX_SUFF(pFIFO)[SVGA_FIFO_MIN]))
    1712                 vmsvgaSafeFifoBusyRegUpdate(pThis, true);
    1713 
    1714             /* Kick the FIFO thread to start processing commands again. */
    1715             SUPSemEventSignal(pThis->svga.pSupDrvSession, pThis->svga.FIFORequestSem);
    1716 #else
    1717             rc = VINF_IOM_R3_IOPORT_WRITE;
    1718 #endif
    1719         }
    1720         /* else nothing to do. */
    1721         else
    1722             Log(("Sync ignored enabled=%d configured=%d\n", pThis->svga.fEnabled, pThis->svga.fConfigured));
    1723 
    1724         break;
    1725 
    1726     case SVGA_REG_BUSY:                /* See "FIFO Synchronization Registers" (read-only) */
    1727         STAM_REL_COUNTER_INC(&pThis->svga.StatRegBusyWr);
    1728         break;
    1729 
    1730     case SVGA_REG_GUEST_ID:            /* Set guest OS identifier */
    1731         STAM_REL_COUNTER_INC(&pThis->svga.StatRegGuestIdWr);
    1732         pThis->svga.u32GuestId = u32;
    1733         break;
    1734 
    1735     case SVGA_REG_PITCHLOCK:           /* Fixed pitch for all modes */
    1736         STAM_REL_COUNTER_INC(&pThis->svga.StatRegPitchLockWr);
    1737         pThis->svga.u32PitchLock = u32;
    1738         /* Should this also update the FIFO pitch lock? Unclear. */
    1739         break;
    1740 
    1741     case SVGA_REG_IRQMASK:             /* Interrupt mask */
    1742         STAM_REL_COUNTER_INC(&pThis->svga.StatRegIrqMaskWr);
    1743         pThis->svga.u32IrqMask = u32;
    1744 
    1745         /* Irq pending after the above change? */
    1746         if (pThis->svga.u32IrqStatus & u32)
    1747         {
    1748             Log(("SVGA_REG_IRQMASK: Trigger interrupt with status %x\n", pThis->svga.u32IrqStatus));
    1749             PDMDevHlpPCISetIrqNoWait(pThis->CTX_SUFF(pDevIns), 0, 1);
    1750         }
    1751         else
    1752             PDMDevHlpPCISetIrqNoWait(pThis->CTX_SUFF(pDevIns), 0, 0);
    1753         break;
    1754 
    1755     /* Mouse cursor support */
    1756     case SVGA_REG_CURSOR_ID:
    1757     case SVGA_REG_CURSOR_X:
    1758     case SVGA_REG_CURSOR_Y:
    1759     case SVGA_REG_CURSOR_ON:
    1760         STAM_REL_COUNTER_INC(&pThis->svga.StatRegCursorXxxxWr);
    1761         break;
    1762 
    1763     /* Legacy multi-monitor support */
    1764     case SVGA_REG_NUM_GUEST_DISPLAYS:/* Number of guest displays in X/Y direction */
    1765         STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumGuestDisplaysWr);
    1766         break;
    1767     case SVGA_REG_DISPLAY_ID:        /* Display ID for the following display attributes */
    1768         STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIdWr);
    1769         break;
    1770     case SVGA_REG_DISPLAY_IS_PRIMARY:/* Whether this is a primary display */
    1771         STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayIsPrimaryWr);
    1772         break;
    1773     case SVGA_REG_DISPLAY_POSITION_X:/* The display position x */
    1774         STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionXWr);
    1775         break;
    1776     case SVGA_REG_DISPLAY_POSITION_Y:/* The display position y */
    1777         STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayPositionYWr);
    1778         break;
    1779     case SVGA_REG_DISPLAY_WIDTH:     /* The display's width */
    1780         STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayWidthWr);
    1781         break;
    1782     case SVGA_REG_DISPLAY_HEIGHT:    /* The display's height */
    1783         STAM_REL_COUNTER_INC(&pThis->svga.StatRegDisplayHeightWr);
    1784         break;
    1785 #ifdef VBOX_WITH_VMSVGA3D
    1786     /* See "Guest memory regions" below. */
    1787     case SVGA_REG_GMR_ID:
    1788         STAM_REL_COUNTER_INC(&pThis->svga.StatRegGmrIdWr);
    1789         pThis->svga.u32CurrentGMRId = u32;
    1790         break;
    1791 
    1792     case SVGA_REG_GMR_DESCRIPTOR:
    1793 # ifndef IN_RING3
    1794         rc = VINF_IOM_R3_IOPORT_WRITE;
    1795         break;
    1796 # else /* IN_RING3 */
    1797     {
    1798         STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWr);
    1799 
    1800         /* Validate current GMR id. */
    1801         uint32_t idGMR = pThis->svga.u32CurrentGMRId;
    1802         AssertBreak(idGMR < pThis->svga.cGMR);
    1803         RT_UNTRUSTED_VALIDATED_FENCE();
    1804 
    1805         /* Free the old GMR if present. */
    1806         vmsvgaGMRFree(pThis, idGMR);
    1807 
    1808         /* Just undefine the GMR? */
    1809         RTGCPHYS GCPhys = (RTGCPHYS)u32 << PAGE_SHIFT;
    1810         if (GCPhys == 0)
    1811         {
    1812             STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWrFree);
    1813             break;
    1814         }
    1815 
    1816 
    1817         /* Never cross a page boundary automatically. */
    1818         const uint32_t          cMaxPages   = RT_MIN(VMSVGA_MAX_GMR_PAGES, UINT32_MAX / X86_PAGE_SIZE);
    1819         uint32_t                cPagesTotal = 0;
    1820         uint32_t                iDesc       = 0;
    1821         PVMSVGAGMRDESCRIPTOR    paDescs     = NULL;
    1822         uint32_t                cLoops      = 0;
    1823         RTGCPHYS                GCPhysBase  = GCPhys;
    1824         while (PHYS_PAGE_ADDRESS(GCPhys) == PHYS_PAGE_ADDRESS(GCPhysBase))
    1825         {
    1826             /* Read descriptor. */
    1827             SVGAGuestMemDescriptor desc;
    1828             rc = PDMDevHlpPhysRead(pThis->CTX_SUFF(pDevIns), GCPhys, &desc, sizeof(desc));
    1829             AssertRCBreak(rc);
    1830 
    1831             if (desc.numPages != 0)
    1832             {
    1833                 AssertBreakStmt(desc.numPages <= cMaxPages, rc = VERR_OUT_OF_RANGE);
    1834                 cPagesTotal += desc.numPages;
    1835                 AssertBreakStmt(cPagesTotal   <= cMaxPages, rc = VERR_OUT_OF_RANGE);
    1836 
    1837                 if ((iDesc & 15) == 0)
    1838                 {
    1839                     void *pvNew = RTMemRealloc(paDescs, (iDesc + 16) * sizeof(VMSVGAGMRDESCRIPTOR));
    1840                     AssertBreakStmt(pvNew, rc = VERR_NO_MEMORY);
    1841                     paDescs = (PVMSVGAGMRDESCRIPTOR)pvNew;
    1842                 }
    1843 
    1844                 paDescs[iDesc].GCPhys     = (RTGCPHYS)desc.ppn << PAGE_SHIFT;
    1845                 paDescs[iDesc++].numPages = desc.numPages;
    1846 
    1847                 /* Continue with the next descriptor. */
    1848                 GCPhys += sizeof(desc);
    1849             }
    1850             else if (desc.ppn == 0)
    1851                 break;  /* terminator */
    1852             else /* Pointer to the next physical page of descriptors. */
    1853                 GCPhys = GCPhysBase = (RTGCPHYS)desc.ppn << PAGE_SHIFT;
    1854 
    1855             cLoops++;
    1856             AssertBreakStmt(cLoops < VMSVGA_MAX_GMR_DESC_LOOP_COUNT, rc = VERR_OUT_OF_RANGE);
    1857         }
    1858 
    1859         AssertStmt(iDesc > 0 || RT_FAILURE_NP(rc), rc = VERR_OUT_OF_RANGE);
    1860         if (RT_SUCCESS(rc))
    1861         {
    1862             /* Commit the GMR. */
    1863             pSVGAState->paGMR[idGMR].paDesc         = paDescs;
    1864             pSVGAState->paGMR[idGMR].numDescriptors = iDesc;
    1865             pSVGAState->paGMR[idGMR].cMaxPages      = cPagesTotal;
    1866             pSVGAState->paGMR[idGMR].cbTotal        = cPagesTotal * PAGE_SIZE;
    1867             Assert((pSVGAState->paGMR[idGMR].cbTotal >> PAGE_SHIFT) == cPagesTotal);
    1868             Log(("Defined new gmr %x numDescriptors=%d cbTotal=%x (%#x pages)\n",
    1869                  idGMR, iDesc, pSVGAState->paGMR[idGMR].cbTotal, cPagesTotal));
    1870         }
    1871         else
    1872         {
    1873             RTMemFree(paDescs);
    1874             STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWrErrors);
    1875         }
    1876         break;
    1877     }
    1878 # endif /* IN_RING3 */
    1879 #endif // VBOX_WITH_VMSVGA3D
    1880 
    1881     case SVGA_REG_TRACES:            /* Enable trace-based updates even when FIFO is on */
    1882         STAM_REL_COUNTER_INC(&pThis->svga.StatRegTracesWr);
    1883         if (pThis->svga.fTraces == u32)
    1884             break; /* nothing to do */
    1885 
    1886 #ifdef IN_RING3
    1887         vmsvgaSetTraces(pThis, !!u32);
    1888 #else
    1889         rc = VINF_IOM_R3_IOPORT_WRITE;
    1890 #endif
    1891         break;
    1892 
    1893     case SVGA_REG_TOP:               /* Must be 1 more than the last register */
    1894         STAM_REL_COUNTER_INC(&pThis->svga.StatRegTopWr);
    1895         break;
    1896 
    1897     case SVGA_REG_NUM_DISPLAYS:        /* (Deprecated) */
    1898         STAM_REL_COUNTER_INC(&pThis->svga.StatRegNumDisplaysWr);
    1899         Log(("Write to deprecated register %x - val %x ignored\n", idxReg, u32));
    1900         break;
    1901 
    1902     case SVGA_REG_FB_START:
    1903     case SVGA_REG_MEM_START:
    1904     case SVGA_REG_HOST_BITS_PER_PIXEL:
    1905     case SVGA_REG_MAX_WIDTH:
    1906     case SVGA_REG_MAX_HEIGHT:
    1907     case SVGA_REG_VRAM_SIZE:
    1908     case SVGA_REG_FB_SIZE:
    1909     case SVGA_REG_CAPABILITIES:
    1910     case SVGA_REG_MEM_SIZE:
    1911     case SVGA_REG_SCRATCH_SIZE:        /* Number of scratch registers */
    1912     case SVGA_REG_MEM_REGS:            /* Number of FIFO registers */
    1913     case SVGA_REG_BYTES_PER_LINE:
    1914     case SVGA_REG_FB_OFFSET:
    1915     case SVGA_REG_RED_MASK:
    1916     case SVGA_REG_GREEN_MASK:
    1917     case SVGA_REG_BLUE_MASK:
    1918     case SVGA_REG_GMRS_MAX_PAGES:    /* Maximum number of 4KB pages for all GMRs */
    1919     case SVGA_REG_MEMORY_SIZE:       /* Total dedicated device memory excluding FIFO */
    1920     case SVGA_REG_GMR_MAX_IDS:
    1921     case SVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH:
    1922         /* Read only - ignore. */
    1923         Log(("Write to R/O register %x - val %x ignored\n", idxReg, u32));
    1924         STAM_REL_COUNTER_INC(&pThis->svga.StatRegReadOnlyWr);
    1925         break;
    1926 
    1927     default:
    1928     {
    1929         uint32_t offReg;
    1930         if ((offReg = idxReg - SVGA_SCRATCH_BASE) < pThis->svga.cScratchRegion)
    1931         {
    1932             RT_UNTRUSTED_VALIDATED_FENCE();
    1933             pThis->svga.au32ScratchRegion[offReg] = u32;
    1934             STAM_REL_COUNTER_INC(&pThis->svga.StatRegScratchWr);
    1935         }
    1936         else if ((offReg = idxReg - SVGA_PALETTE_BASE) < (uint32_t)SVGA_NUM_PALETTE_REGS)
    1937         {
    1938             /* Note! Using last_palette rather than palette here to preserve the VGA one.
    1939                      Btw, see rgb_to_pixel32.  */
    1940             STAM_REL_COUNTER_INC(&pThis->svga.StatRegPaletteWr);
    1941             u32 &= 0xff;
    1942             RT_UNTRUSTED_VALIDATED_FENCE();
    1943             uint32_t uRgb = pThis->last_palette[offReg / 3];
    1944             switch (offReg % 3)
    1945             {
    1946                 case 0: uRgb = (uRgb & UINT32_C(0x0000ffff)) | (u32 << 16); break; /* red */
    1947                 case 1: uRgb = (uRgb & UINT32_C(0x00ff00ff)) | (u32 <<  8); break; /* green */
    1948                 case 2: uRgb = (uRgb & UINT32_C(0x00ffff00)) |  u32       ; break; /* blue */
    1949             }
    1950             pThis->last_palette[offReg / 3] = uRgb;
    1951         }
    1952         else
    1953         {
    1954 #if !defined(IN_RING3) && defined(VBOX_STRICT)
    1955             rc = VINF_IOM_R3_IOPORT_WRITE;
    1956 #else
    1957             STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownWr);
    1958             AssertMsgFailed(("reg=%#x u32=%#x\n", idxReg, u32));
    1959 #endif
    1960         }
    1961         break;
    1962     }
    19631953    }
    19641954    return rc;
Note: See TracChangeset for help on using the changeset viewer.

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