[Spice-devel] [RFC PATCH qxl-wddm-dod 06/28] Do not use virtual functions for code that must not be paged
Dmitry Fleytman
dmitry at daynix.com
Mon Jul 18 06:33:47 UTC 2016
From: Sandy Stutsman <sstutsma at redhat.com>
There is no way to guarantee that the static vtable will be in
non-pageable memory. This patch converts 3 virtual non-pageble functions
to functions private to each device class, the parent class will make
an explicit call (based on a new device type initialized at object
creation) to the correct function.
Fixed one misspelling: HwDeviceInterface
---
qxldod/QxlDod.cpp | 114 ++++++++++++++++++++++++++++++++++++++++++------------
qxldod/QxlDod.h | 48 +++++++++++++++--------
2 files changed, 120 insertions(+), 42 deletions(-)
diff --git a/qxldod/QxlDod.cpp b/qxldod/QxlDod.cpp
index 1b3bdf1..ec960e5 100755
--- a/qxldod/QxlDod.cpp
+++ b/qxldod/QxlDod.cpp
@@ -2294,7 +2294,7 @@ VOID BltBits (
}
#pragma code_seg(pop) // End Non-Paged Code
-VgaDevice::VgaDevice(_In_ QxlDod* pQxlDod)
+VgaDevice::VgaDevice(_In_ QxlDod* pQxlDod) : HwDeviceInterface(pQxlDod)
{
m_pQxlDod = pQxlDod;
m_ModeInfo = NULL;
@@ -2302,6 +2302,7 @@ VgaDevice::VgaDevice(_In_ QxlDod* pQxlDod)
m_ModeNumbers = NULL;
m_CurrentMode = 0;
m_Id = 0;
+ m_type = VGA_DEVICE;
}
VgaDevice::~VgaDevice(void)
@@ -2881,18 +2882,18 @@ VOID VgaDevice::BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod)
#pragma code_seg()
// BEGIN: Non-Paged Code Segment
-BOOLEAN VgaDevice::InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber)
+BOOLEAN VgaDevice::HWInterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber)
{
UNREFERENCED_PARAMETER(pDxgkInterface);
UNREFERENCED_PARAMETER(MessageNumber);
return FALSE;
}
-VOID VgaDevice::DpcRoutine(PVOID)
+VOID VgaDevice::HWDpcRoutine(PDXGKRNL_INTERFACE pDxgkInterface)
{
}
-VOID VgaDevice::ResetDevice(VOID)
+VOID VgaDevice::HWResetDevice(VOID)
{
}
#pragma code_seg(pop) //end non-paged code
@@ -2916,7 +2917,7 @@ NTSTATUS VgaDevice::Escape(_In_ CONST DXGKARG_ESCAPE* pEscap)
return STATUS_NOT_IMPLEMENTED;
}
-QxlDevice::QxlDevice(_In_ QxlDod* pQxlDod)
+QxlDevice::QxlDevice(_In_ QxlDod* pQxlDod) : HwDeviceInterface(pQxlDod)
{
m_pQxlDod = pQxlDod;
m_ModeInfo = NULL;
@@ -2926,6 +2927,7 @@ QxlDevice::QxlDevice(_In_ QxlDod* pQxlDod)
m_CustomMode = 0;
m_FreeOutputs = 0;
m_Pending = 0;
+ m_type = QXL_DEVICE;
}
QxlDevice::~QxlDevice(void)
@@ -3152,7 +3154,7 @@ NTSTATUS QxlDevice::SetPowerState(_In_ DEVICE_POWER_STATE DevicePowerState, DXGK
NTSTATUS QxlDevice::HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo)
{
DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
- PDXGKRNL_INTERFACE pDxgkInterface = m_pQxlDod->GetDxgkInterrface();
+ PDXGKRNL_INTERFACE pDxgkInterface = m_pQxlDod->GetDxgkInterface();
UINT pci_range = QXL_RAM_RANGE_INDEX;
for (ULONG i = 0; i < pResList->Count; ++i)
{
@@ -3329,7 +3331,7 @@ void QxlDevice::QxlClose()
void QxlDevice::UnmapMemory(void)
{
- PDXGKRNL_INTERFACE pDxgkInterface = m_pQxlDod->GetDxgkInterrface();
+ PDXGKRNL_INTERFACE pDxgkInterface = m_pQxlDod->GetDxgkInterface();
if (m_IoMapped && m_IoBase)
{
pDxgkInterface->DxgkCbUnmapMemory( pDxgkInterface->DeviceHandle, &m_IoBase);
@@ -4498,7 +4500,8 @@ VOID QxlDevice::PushCursor(VOID)
#pragma code_seg(push)
#pragma code_seg()
// BEGIN: Non-Paged Code Segment
-BOOLEAN QxlDevice::InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber)
+
+BOOLEAN QxlDevice::HWInterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber)
{
UNREFERENCED_PARAMETER(MessageNumber);
DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
@@ -4523,10 +4526,8 @@ BOOLEAN QxlDevice::InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_
return TRUE;
}
-VOID QxlDevice::DpcRoutine(PVOID ptr)
+VOID QxlDevice::HWDpcRoutine(PDXGKRNL_INTERFACE pDxgkInterface)
{
- PDXGKRNL_INTERFACE pDxgkInterface = (PDXGKRNL_INTERFACE)ptr;
-
DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s\n", __FUNCTION__));
DPC_CB_CONTEXT ctx;
BOOLEAN dummy;
@@ -4557,13 +4558,89 @@ VOID QxlDevice::DpcRoutine(PVOID ptr)
DbgPrint(TRACE_LEVEL_INFORMATION, ("<--- %s\n", __FUNCTION__));
}
-void QxlDevice::ResetDevice(void)
+void QxlDevice::HWResetDevice(void)
{
DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
m_RamHdr->int_mask = ~0;
WRITE_PORT_UCHAR(m_IoBase + QXL_IO_MEMSLOT_ADD, 0);
DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
}
+
+// Given bits per pixel, return the pixel format at the same bpp
+D3DDDIFORMAT PixelFormatFromBPP(UINT BPP)
+{
+ switch (BPP)
+ {
+ case 8: return D3DDDIFMT_P8;
+ case 16: return D3DDDIFMT_R5G6B5;
+ case 24: return D3DDDIFMT_R8G8B8;
+ case 32: return D3DDDIFMT_X8R8G8B8;
+ default: QXL_LOG_ASSERTION1("A bit per pixel of 0x%I64x is not supported.", BPP); return D3DDDIFMT_UNKNOWN;
+ }
+}
+
+
+BOOLEAN HwDeviceInterface::InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber)
+{
+ QxlDevice * qxl_device;
+ VgaDevice * vga_device;
+
+ switch (m_type) {
+ case QXL_DEVICE:
+ qxl_device = (QxlDevice *)this;
+ return qxl_device->HWInterruptRoutine(pDxgkInterface, MessageNumber);
+ case VGA_DEVICE:
+ vga_device = (VgaDevice *)this;
+ return vga_device->HWInterruptRoutine(pDxgkInterface, MessageNumber);
+ default:
+ DbgPrint(TRACE_LEVEL_ERROR, ("%s called with invalid device type of %d\n",
+ __FUNCTION__, m_type));
+ return FALSE;
+ }
+}
+
+VOID HwDeviceInterface::DpcRoutine(PDXGKRNL_INTERFACE pDxgkInterface)
+{
+ QxlDevice * qxl_device;
+ VgaDevice * vga_device;
+
+ switch (m_type) {
+ case QXL_DEVICE:
+ qxl_device = (QxlDevice *)this;
+ qxl_device->HWDpcRoutine(pDxgkInterface);
+ return;
+ case VGA_DEVICE:
+ vga_device = (VgaDevice *)this;
+ vga_device->HWDpcRoutine(pDxgkInterface);
+ return;
+ default:
+ DbgPrint(TRACE_LEVEL_ERROR, ("%s called with invalid device type of %d\n",
+ __FUNCTION__, m_type));
+ return;
+ }
+}
+
+VOID HwDeviceInterface::ResetDevice(void)
+{
+ QxlDevice * qxl_device;
+ VgaDevice * vga_device;
+
+ switch (m_type) {
+ case QXL_DEVICE:
+ qxl_device = (QxlDevice *)this;
+ qxl_device->HWResetDevice();
+ return;
+ case VGA_DEVICE:
+ vga_device = (VgaDevice *)this;
+ vga_device->HWResetDevice();
+ return;
+ default:
+ DbgPrint(TRACE_LEVEL_ERROR, ("%s called with invalid device type of %d\n",
+ __FUNCTION__, m_type));
+ return;
+ }
+}
+
#pragma code_seg(pop) //end non-paged code
VOID QxlDevice::UpdateArea(CONST RECT* area, UINT32 surface_id)
@@ -4592,19 +4669,6 @@ VOID QxlDevice::DpcCallback(PDPC_CB_CONTEXT ctx)
}
-// Given bits per pixel, return the pixel format at the same bpp
-D3DDDIFORMAT PixelFormatFromBPP(UINT BPP)
-{
- switch (BPP)
- {
- case 8: return D3DDDIFMT_P8;
- case 16: return D3DDDIFMT_R5G6B5;
- case 24: return D3DDDIFMT_R8G8B8;
- case 32: return D3DDDIFMT_X8R8G8B8;
- default: QXL_LOG_ASSERTION1("A bit per pixel of 0x%I64x is not supported.", BPP); return D3DDDIFMT_UNKNOWN;
- }
-}
-
UINT SpiceFromPixelFormat(D3DDDIFORMAT Format)
{
switch (Format)
diff --git a/qxldod/QxlDod.h b/qxldod/QxlDod.h
index eb9bea7..db343e9 100755
--- a/qxldod/QxlDod.h
+++ b/qxldod/QxlDod.h
@@ -212,21 +212,34 @@ typedef struct _CURRENT_BDD_MODE
class QxlDod;
-class HwDeviceIntrface {
+//
+// Can't use virtual for functions that are non-pageable because there is no guarantee
+// that the vtable will not be paged out. Will test for type in the parent call and
+// cast to call in the correct device class.
+//
+
+typedef enum {
+ QXL_DEVICE,
+ VGA_DEVICE,
+ INVALID_DEVICE,
+}WIN_QXL_DEVICE_TYPE;
+
+class HwDeviceInterface {
public:
-// HwDeviceIntrface(_In_ QxlDod* pQxlDod) {;}
- virtual ~HwDeviceIntrface() {;}
+ HwDeviceInterface(_In_ QxlDod* pQxlDod) {m_type = INVALID_DEVICE;}
+ virtual ~HwDeviceInterface() {;}
virtual NTSTATUS QueryCurrentMode(PVIDEO_MODE RequestedMode) = 0;
virtual NTSTATUS SetCurrentMode(ULONG Mode) = 0;
virtual NTSTATUS GetCurrentMode(ULONG* Mode) = 0;
virtual NTSTATUS SetPowerState(DEVICE_POWER_STATE DevicePowerState, DXGK_DISPLAY_INFORMATION* pDispInfo) = 0;
virtual NTSTATUS HWInit(PCM_RESOURCE_LIST pResList, DXGK_DISPLAY_INFORMATION* pDispInfo) = 0;
virtual NTSTATUS HWClose(void) = 0;
- virtual BOOLEAN InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber) = 0;
- virtual VOID DpcRoutine(PVOID) = 0;
- virtual VOID ResetDevice(void) = 0;
-
virtual ULONG GetModeCount(void) = 0;
+
+ BOOLEAN InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber);;
+ VOID DpcRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface);
+ VOID ResetDevice(void);;
+
PVIDEO_MODE_INFORMATION GetModeInfo(UINT idx) {return &m_ModeInfo[idx];}
USHORT GetModeNumber(USHORT idx) {return m_ModeNumbers[idx];}
USHORT GetCurrentModeIndex(void) {return m_CurrentMode;}
@@ -259,10 +272,11 @@ protected:
USHORT m_CurrentMode;
USHORT m_CustomMode;
ULONG m_Id;
+ WIN_QXL_DEVICE_TYPE m_type;
};
class VgaDevice :
- public HwDeviceIntrface
+ public HwDeviceInterface
{
public:
VgaDevice(_In_ QxlDod* pQxlDod);
@@ -287,9 +301,9 @@ public:
_In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation,
_In_ const CURRENT_BDD_MODE* pModeCur);
VOID BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod);
- BOOLEAN InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber);
- VOID DpcRoutine(PVOID);
- VOID ResetDevice(VOID);
+ BOOLEAN HWInterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber);
+ VOID HWDpcRoutine(PDXGKRNL_INTERFACE pDxgkInterface);
+ VOID HWResetDevice(VOID);
NTSTATUS SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape);
NTSTATUS SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition);
NTSTATUS Escape(_In_ CONST DXGKARG_ESCAPE* pEscap);
@@ -435,7 +449,7 @@ typedef struct DpcCbContext {
#define ALIGN(a, b) (((a) + ((b) - 1)) & ~((b) - 1))
class QxlDevice :
- public HwDeviceIntrface
+ public HwDeviceInterface
{
public:
QxlDevice(_In_ QxlDod* pQxlDod);
@@ -460,9 +474,9 @@ public:
_In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation,
_In_ const CURRENT_BDD_MODE* pModeCur);
VOID BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod);
- BOOLEAN InterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber);
- VOID DpcRoutine(PVOID);
- VOID ResetDevice(VOID);
+ BOOLEAN HWInterruptRoutine(_In_ PDXGKRNL_INTERFACE pDxgkInterface, _In_ ULONG MessageNumber);
+ VOID HWDpcRoutine(PDXGKRNL_INTERFACE pDxgkInterface);
+ VOID HWResetDevice(VOID);
NTSTATUS SetPointerShape(_In_ CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape);
NTSTATUS SetPointerPosition(_In_ CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition);
NTSTATUS Escape(_In_ CONST DXGKARG_ESCAPE* pEscap);
@@ -592,7 +606,7 @@ private:
D3DDDI_VIDEO_PRESENT_SOURCE_ID m_SystemDisplaySourceId;
DXGKARG_SETPOINTERSHAPE m_PointerShape;
- HwDeviceIntrface* m_pHWDevice;
+ HwDeviceInterface* m_pHWDevice;
public:
QxlDod(_In_ DEVICE_OBJECT* pPhysicalDeviceObject);
~QxlDod(void);
@@ -685,7 +699,7 @@ public:
_In_ UINT SourceStride,
_In_ INT PositionX,
_In_ INT PositionY);
- PDXGKRNL_INTERFACE GetDxgkInterrface(void) { return &m_DxgkInterface;}
+ PDXGKRNL_INTERFACE GetDxgkInterface(void) { return &m_DxgkInterface;}
private:
VOID CleanUp(VOID);
NTSTATUS CheckHardware();
--
1.8.3.1
More information about the Spice-devel
mailing list