From 6f5cf2dbcc876c82db5cd870ef21104b7b83c838 Mon Sep 17 00:00:00 2001 From: Yonit Halperin Date: Wed, 17 Aug 2011 14:48:39 +0300 Subject: miniport: map vram to virtual address only once, #722954 DrvSurface calls IOCTL_VIDEO_MAP/UNMAP_VIDEO_MEMORY respectively. These calls make the miniport map/unmap the vram to/from system space. The BSOD occurred since with qxl revision 2, the driver assumes that as long as it is loaded the vram stays (and all the other mem slots) valid and in the same place. However, the miniport's call to VideoPortMapMemory (in IOCTL_VIDEO_MAP_VIDEO_MEMORY) is not guaranteed to map the vram to the same virtual address. As a result, when the driver accessed to an mspace instance that was initialized with a no longer valid virtual address, we got BSOD. Since we don't change the size of the vram, I see no point in mapping and unmapping it more then once. For qxl revision 3 this problem is not relevant since between DrvAssertMode(disable) to DrvAssertMode(enable) we clear the pci ram and initialize all the data structure that are related to it (mspace, caches, etc.) I didn't remove the calls to IOCTL_VIDEO_MAP/UNMAP_VIDEO_MEMORY since I think they would be useful for supporting dynamically changing the size of the memslots according to the current resolution. Which I think is the real purpose of IOCTL_VIDEO_MAP/UNMAP_VIDEO_MEMORY. Today, the size of the frame buffer (surface0) is static -> the maximal resolution we support. --- miniport/qxl.c | 75 +++++++++++++++++++++++----------------------------------- 1 file changed, 30 insertions(+), 45 deletions(-) diff --git a/miniport/qxl.c b/miniport/qxl.c index 40e8379..7006adf 100644 --- a/miniport/qxl.c +++ b/miniport/qxl.c @@ -324,6 +324,11 @@ VP_STATUS InitVRAM(QXLExtension *dev, PVIDEO_ACCESS_RANGE range); VP_STATUS InitVRAM(QXLExtension *dev, PVIDEO_ACCESS_RANGE range) { + UINT8 *vram_addr = NULL; + ULONG vram_mapped_size = range->RangeLength; + ULONG io_space = VIDEO_MEMORY_SPACE_MEMORY; + VP_STATUS error; + PAGED_CODE(); DEBUG_PRINT((dev, 0, "%s\n", __FUNCTION__)); @@ -332,10 +337,24 @@ VP_STATUS InitVRAM(QXLExtension *dev, PVIDEO_ACCESS_RANGE range) return ERROR_INVALID_DATA; } + if ((error = VideoPortMapMemory(dev, range->RangeStart, + &vram_mapped_size, + &io_space, + &vram_addr))) { + DEBUG_PRINT((dev, 0, "%s: map vram failed\n", __FUNCTION__)); + return error; + } + + if (vram_mapped_size < range->RangeLength) { + DEBUG_PRINT((dev, 0, "%s: vram shrinked\n", __FUNCTION__)); + VideoPortUnmapMemory(dev, vram_addr, NULL); + return ERROR_NOT_ENOUGH_MEMORY; + } dev->vram_physical = range->RangeStart; + dev->vram_start = vram_addr; dev->vram_size = range->RangeLength; - DEBUG_PRINT((dev, 0, "%s: OK, vram 0x%lx size %lu\n", - __FUNCTION__, (ULONG)range->RangeStart.QuadPart, range->RangeLength)); + DEBUG_PRINT((dev, 0, "%s: OK, vram 0x%lx size %lu vaddr 0x%lx\n", __FUNCTION__, + (ULONG)range->RangeStart.QuadPart, range->RangeLength, dev->vram_start)); return NO_ERROR; } @@ -577,6 +596,10 @@ void DevExternsionCleanup(QXLExtension *dev) VideoPortUnmapMemory(dev, dev->ram_start, NULL); } + if (dev->vram_start) { + VideoPortUnmapMemory(dev, dev->vram_start, NULL); + } + if (dev->modes) { VideoPortFreePool(dev, dev->modes); } @@ -966,7 +989,6 @@ BOOLEAN StartIO(PVOID dev_extension, PVIDEO_REQUEST_PACKET packet) break; case IOCTL_VIDEO_MAP_VIDEO_MEMORY: { PVIDEO_MEMORY_INFORMATION mem_info; - ULONG fb_io_space; DEBUG_PRINT((dev_ext, 0, "%s: IOCTL_VIDEO_MAP_VIDEO_MEMORY\n", __FUNCTION__)); @@ -976,36 +998,11 @@ BOOLEAN StartIO(PVOID dev_extension, PVIDEO_REQUEST_PACKET packet) error = ERROR_INSUFFICIENT_BUFFER; goto err; } - mem_info = packet->OutputBuffer; - mem_info->VideoRamBase = - ((PVIDEO_MEMORY)(packet->InputBuffer))->RequestedVirtualAddress; - ASSERT(mem_info->VideoRamBase == NULL); - mem_info->VideoRamLength = dev_ext->vram_size; - fb_io_space = VIDEO_MEMORY_SPACE_MEMORY; - - if ((error = VideoPortMapMemory(dev_ext, dev_ext->vram_physical, - &mem_info->VideoRamLength, - &fb_io_space, &mem_info->VideoRamBase)) != NO_ERROR) { - DEBUG_PRINT((dev_ext, 0, "%s: map filed\n", __FUNCTION__)); - goto err; - } - dev_ext->vram_start = mem_info->VideoRamBase; - DEBUG_PRINT((dev_ext, 0, "%s: vram size %lu ret size %lu fb vaddr 0x%lx\n", - __FUNCTION__, - dev_ext->vram_size, - mem_info->VideoRamLength, - mem_info->VideoRamBase)); - if (mem_info->VideoRamLength < dev_ext->vram_size) { - DEBUG_PRINT((dev_ext, 0, "%s: fb shrink\n", __FUNCTION__)); - VideoPortUnmapMemory(dev_ext, mem_info->VideoRamBase, NULL); - mem_info->VideoRamBase = NULL; - mem_info->VideoRamLength = 0; - error = ERROR_NOT_ENOUGH_MEMORY; - goto err; - } - mem_info->FrameBufferBase = mem_info->VideoRamBase; - mem_info->FrameBufferLength = mem_info->VideoRamLength; + ASSERT(((PVIDEO_MEMORY)(packet->InputBuffer))->RequestedVirtualAddress == NULL); + mem_info = packet->OutputBuffer; + mem_info->VideoRamBase = mem_info->FrameBufferBase = dev_ext->vram_start; + mem_info->VideoRamLength = mem_info->FrameBufferLength = dev_ext->vram_size; #if 0 #ifdef DBG DEBUG_PRINT((dev, 0, "%s: zap\n", __FUNCTION__)); @@ -1016,19 +1013,7 @@ BOOLEAN StartIO(PVOID dev_extension, PVIDEO_REQUEST_PACKET packet) } break; case IOCTL_VIDEO_UNMAP_VIDEO_MEMORY: { - PVOID addr; - - DEBUG_PRINT((dev_ext, 0, "%s: IOCTL_VIDEO_UNMAP_VIDEO_MEMORY\n", __FUNCTION__)); - - if (packet->InputBufferLength < sizeof(VIDEO_MEMORY)) { - error = ERROR_INSUFFICIENT_BUFFER; - goto err; - } - addr = ((PVIDEO_MEMORY)(packet->InputBuffer))->RequestedVirtualAddress; - if ((error = VideoPortUnmapMemory(dev_ext, addr, NULL)) != NO_ERROR) { - DEBUG_PRINT((dev_ext, 0, "%s: unmap failed\n", __FUNCTION__)); - } - dev_ext->vram_start = NULL; + DEBUG_PRINT((dev_ext, 0, "%s: IOCTL_VIDEO_UNMAP_VIDEO_MEMORY (do nothing) \n", __FUNCTION__)); } break; case IOCTL_VIDEO_RESET_DEVICE: -- cgit v1.2.3