Changeset 82081 in vbox
- Timestamp:
- Nov 21, 2019 3:33:01 PM (5 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Graphics/DevVGA-SVGA.cpp
r82079 r82081 794 794 switch (idxReg) 795 795 { 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: 811 807 { 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; 813 823 } 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 */ 815 1017 { 816 1018 #ifndef IN_RING3 817 1019 rc = VINF_IOM_R3_IOPORT_READ; 818 1020 #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)); 820 1035 #endif 1036 break; 821 1037 } 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 { 835 1069 #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; 1074 1074 #else 1075 1075 # 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); 1106 1084 if (pThis->svga.fBusy) 1107 1085 { 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); 1116 1089 } 1117 1118 1090 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); 1121 1121 # endif 1122 *pu32 = pThis->svga.fBusy != 0;1122 *pu32 = pThis->svga.fBusy != 0; 1123 1123 #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; 1124 1281 } 1125 else1126 *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 driver1242 will take a legacy code path without 3d support. This number also1243 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 else1270 {1271 #if !defined(IN_RING3) && defined(VBOX_STRICT)1272 rc = VINF_IOM_R3_IOPORT_READ;1273 #else1274 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 #endif1279 }1280 break;1281 }1282 1282 } 1283 1283 Log(("vmsvgaReadPort index=%s (%d) val=%#x rc=%x\n", vmsvgaIndexToString(pThis, idxReg), idxReg, *pu32, rc)); … … 1506 1506 * Write port register 1507 1507 * 1508 * @returns VBox status code.1508 * @returns Strict VBox status code. 1509 1509 * @param pThis VMSVGA State 1510 1510 * @param u32 Value to write 1511 1511 */ 1512 static intvmsvgaWritePort(PVGASTATE pThis, uint32_t u32)1512 static VBOXSTRICTRC vmsvgaWritePort(PVGASTATE pThis, uint32_t u32) 1513 1513 { 1514 1514 #ifdef IN_RING3 1515 1515 PVMSVGAR3STATE pSVGAState = pThis->svga.pSvgaR3State; 1516 1516 #endif 1517 intrc = VINF_SUCCESS;1517 VBOXSTRICTRC rc = VINF_SUCCESS; 1518 1518 1519 1519 /* Rough index register validation. */ … … 1552 1552 switch (idxReg) 1553 1553 { 1554 case SVGA_REG_ID:1555 STAM_REL_COUNTER_INC(&pThis->svga.StatRegIdWr);1556 if ( u32 == SVGA_ID_01557 || u32 == SVGA_ID_11558 || u32 == SVGA_ID_2)1559 pThis->svga.u32SVGAId = u32;1560 else1561 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); 1566 1566 #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); 1595 1593 # 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])); 1599 1597 # endif 1600 1598 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; 1602 1687 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 else1609 {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 }1641 1688 #else 1642 1689 rc = VINF_IOM_R3_IOPORT_WRITE; 1643 1690 #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; 1644 1867 } 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); 1677 1878 #else 1678 1879 rc = VINF_IOM_R3_IOPORT_WRITE; 1679 1880 #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; 1680 1952 } 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_RING31690 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 #else1699 rc = VINF_IOM_R3_IOPORT_WRITE;1700 #endif1701 break;1702 1703 case SVGA_REG_SYNC: /* See "FIFO Synchronization Registers" */1704 STAM_REL_COUNTER_INC(&pThis->svga.StatRegSyncWr);1705 if ( pThis->svga.fEnabled1706 && 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 #else1717 rc = VINF_IOM_R3_IOPORT_WRITE;1718 #endif1719 }1720 /* else nothing to do. */1721 else1722 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 else1752 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_VMSVGA3D1786 /* 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_RING31794 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 else1872 {1873 RTMemFree(paDescs);1874 STAM_REL_COUNTER_INC(&pSVGAState->StatR3RegGmrDescriptorWrErrors);1875 }1876 break;1877 }1878 # endif /* IN_RING3 */1879 #endif // VBOX_WITH_VMSVGA3D1880 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_RING31887 vmsvgaSetTraces(pThis, !!u32);1888 #else1889 rc = VINF_IOM_R3_IOPORT_WRITE;1890 #endif1891 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 else1953 {1954 #if !defined(IN_RING3) && defined(VBOX_STRICT)1955 rc = VINF_IOM_R3_IOPORT_WRITE;1956 #else1957 STAM_REL_COUNTER_INC(&pThis->svga.StatRegUnknownWr);1958 AssertMsgFailed(("reg=%#x u32=%#x\n", idxReg, u32));1959 #endif1960 }1961 break;1962 }1963 1953 } 1964 1954 return rc;
Note:
See TracChangeset
for help on using the changeset viewer.