WinQXL

From Spice

TODO: merge / update from http://www.linux-kvm.org/page/WindowsGuestDrivers/UpdatedGuestDebugging

Contents

How to build the driver

Repository or sources available from the repositories

git clone git://anongit.freedesktop.org/spice/win32/qxl
rem install the winddk 7600.16385.0
rem start the checked environment (or the free one) - this is the contents of
rem the relevant shortcut that winddk creates (for a specific instance, i.e.
rem x86 WXP checked).
rem C:\WINDOWS\system32\cmd.exe /k C:\WinDDK\7600.16385.0\bin\setenv.bat C:\WinDDK\7600.16385.0\ chk x86 WXP
cd qxl
git submodule init
git submodule update
build -cZg

Ongoing work

Visual Studio 2013 branch plus D3D empty implementation - XDDMD3D9Status

Adding assembly (.asm) files to WinDDK

These notes are temporary since WinDDK switched to Visual Studio (with 2012 I think). But for WinDDK you need to take the following steps:

  • create a subdirectory per target architecture:
    • amd64 (only tested one since for i386 you can use inline assembly)
  • add it to the sources file via the target architecture specific sources directive:
    • AMD64_SOURCES=amd64\file.asm

AMD64 calling conventions overview

Detailed Instructions: Build QXL on Windows 7 64 bit

Prerequisites

Checkout QXL drivers. The latest include 64-bit although it says "32-bit"

You should have 3 directories inside qxl directory: Display, Miniport and Include.

  • Download Spice Protocol from http://spice-space.org
    • Now a submodule: git submodule init; git submodule update
  • Download latest version of WinDDK that support Windows 7.

http://msdn.microsoft.com/en-us/windows/hardware/gg487428

After installing the Winddk you will have to create new environment variable: Variable name: SPICE_COMMON_DIR with C:\qxl

http://www.itechtalk.com/thread3595.html

OR:

Open a Free Build x64 command prompt from the WinDDK

Type:

set SPICE_COMMON_DIR=c:\path\to\spice-protocol

Next:

Start --> All Programs --> Windows Driver Kits --> WDK 7600.16385.1 --> Build environment (pick your choice after this step) Windows 7 -> x64 Free Build Environment It will open a new DOS prompt for you to start building. (Make sure to use the "Free" and not "Checked", the "checked" is debug version)

Build

c:\WinDDK\7600.16385.1>cd \
c:\>cd qxl
c:\qxl>build -cZg

It should create 2 new files for QXL driver: qxldd.dll and qxl.sys

The 3rd file: qxl.inf which is originated from QXL driver folder.

Signing

See MSDN for more details.

Follow the steps here on how to sign the driver with a test certificate:

1. MakeCert -r -pe -ss SpiceTestCertStore -n "CN=spice-space.org(Test)" SpiceTestCert.cer

2. CertMgr /add SpiceTestCert.cer /s /r localMachine root

3. SignTool sign /v /s SpiceTestCertStore /n spice-space.org(Test) /t http://timestamp.verisign.com/scripts/timestamp.dll qxl.sys qxldd.dll

Before installing the driver on the guest, call:

bcdedit.exe -set TESTSIGNING ON

Installing

I) Copying files ( assuming [3] below )

1. Open elevated command prompt

2. bcdedit.exe -set loadoptions DDISABLE_INTEGRITY_CHECKS

3. bcdedit.exe -set TESTSIGNING ON

4. Copy qxldd.dll to c:\windows\system32\

5. Copy qxl.sys to c:\windows\system32\drivers\

6. Reboot

II) Using Device Manager

1.Putting the signed drivers & inf file in a local (temp) folder.

2. Install it from Device Manager:

     -> Display Adapters
     -> QXL/VGA
     -> Right-Click -> Update Driver Software
     -> Browse my computer for driver software (bottom)
     -> Let me pick from a list ... (bottom)
     -> Have Disk... (button)
     -> Browse (button)
     -> path-to-qxl-driver.inf -> OK
     -> Next
     -> Close
     -> Want to reboot ?  Yes
 - must reboot after qxl driver installation. 
III) using pnputil.exe

pnputil is built in to win7 and newer (it's in the default path).

pnputil -i -a qxl.inf

  • if the driver is unsigned you still get the popup red bordered dialog requiring confirmation of installing an unsigned driver.
IV) Using nsis - see http://nsis.sourceforge.net/Driver_installation_and_update

Also TODO.

Troubleshooting Installation

Code 52

Windows cannot verify the digital signature for the drivers required for this device.

The driver certificate chain isn't rooted in a trusted certificate. This is expected since these drivers have not passed WHQL. You need to answer "yes" to the big red dialog that says you should not say yes.

Generic Advice

(How is this different then debugging? this is for installation errors)

Installation can fail for many reasons:

  • signature lacking
  • newer version driver and you didn't force usage of your driver

Writing detailed procedure is ToDo, but for information collection purposes you should look for setupapi logs:

windows xp:

  • c:\Windows\setupapi.log

windows 7:

  • c:\Windows\inf\setupapi.dev.log

In both cases it is helpful to:

  • delete / rename the current log file
  • do the install/update again (which fails)
  • send as attachment / fpaste and put on irc the resulting log file

Debugging

Nice to have rant

Unlike the nice virtio drivers we don't have an option to enable logging in the guest from device properties (yet). (what we do have is the option to log to the host via an io port, QXL_IO_LOG, which is neat too).

qemu options to turn on

guestdebug

The driver reads a guestdebug parameter from the rom, that is settable during the creation of the machine (we used to have a monitor command but it was dropped during upstream, yet another todo). This uses the QXL_IO_DEBUG io out, so each debug print will cause a vmexit (in practice it's still way faster then a debugger. probably slower then having a logging mechanism in the guest like the nice to have rant above).

-global qxl-vga.guestdebug=3

And for any secondary cards either use:

-global qxl.guestdebug=3

Or set it via the device:

-device qxl,guestdebug=3

You can go up to 12 (or more, look for DEBUG_PRINT in the driver), you get really a lot of debug information. Interesting values are:

  • 3 - will give you all the highlevel commands (DrvCopyBits, DrvBitBlt, etc.)
  • 6 - will also show QXLGetBitMap
  • 11 - will show caching of images (this is a driver cache, not to be confused with the server<->client shared cache).

cmdlog

This will dump all the commands passing through the ringbuffer on the device side. It is driver and hence guest agnostic. Defaults to 0. Just two values, 1 to enable, 0 to disable.

-global qxl-vga.cmdlog=1

Random notes

Notice that sometimes the driver gets uninstalled when you kill a vm uncleanly (not a shutdown), via the restore mechanisem of windows 7 in the next reboot (it returns to a last known working configuration).

Debug Cycle

This is the way I debug the driver right now:

Setup:

  • have a build vm with ddk installed. (update: winddk works with wine, except for makecert, so all of this can be done from linux with wine).
  • have a checkout of the source on my linux development machine (which also hosts the vms and runs the clients)
  • have a samba share with the sources.
  • have that share visible to the build vm.

You can install the drivers from a running vm, but since they tend to give you bluescreens during development, and since you need a reboot to get the new ones anyway, the following flow works for me:

Update driver work flow

  • host: (using \$EDITOR): update driver code
  • host: update revision of driver (see [1] below)
  • buildvm: build vm (I use [4] script)
  • while not build successfull:
    • host: update driver code
    • buildvm: build driver
  • host: take down test vm
  • host: update test vm drivers (see [2] below, and note [3])
  • host: start test vm
  • testvm: test your new code

[1] - update revision scriptlet

#!/bin/bash
TAG=`date +%Y%m%d_%H%M%S`
for f in miniport/qxl.inf miniport/qxl.rc display/driver.rc; do
    sed -i -e "s/alon\..*/alon.$TAG\"/" $f
done

[2] - update driver scriptlet

#!/bin/bash
guestfish <<_EOF_
add /store/images/win7x86_qxl_tests.img
lcd /store/images
run
mount /dev/vda2 /
upload /store/shared_win/spice_upstream/qxl/install_win7/qxldd.dll /Windows/System32/qxldd.dll
upload /store/shared_win/spice_upstream/qxl/install_win7/qxl.sys /Windows/System32/drivers/qxl.sys
checksum md5 /Windows/System32/qxldd.dll
checksum md5 /Windows/System32/drivers/qxl.sys
_EOF_
md5sum /store/shared_win/spice_upstream/qxl/install_win7/qxldd.dll
md5sum /store/shared_win/spice_upstream/qxl/install_win7/qxl.sys

[3] This assumes you have installed a version of the drivers using the normal installation procedure first. because that script doesn't do anything except replace the existing qxldd.dll and qxl.sys, so it doesn't touch the registry.

[4] build script on the build vm (this one builds the win7 checked drivers) (it goes with [2] above which reads the new drivers from that directory)

cd miniport
build -cZg
cd ../display
build -cZg
cd ../
copy display\objchk_win7_x86\i386\qxldd.dll install_win7
copy miniport\objchk_win7_x86\i386\qxl.sys install_win7
copy miniport\qxl.inf install_win7
copy display\objchk_win7_x86\i386\qxldd.pdb install_win7
copy miniport\objchk_win7_x86\i386\qxl.pdb install_win7

Running WinDBG

setup:

  • target vm: running windows and the driver under development, setup for kernel debug
  • windbg vm: running any windows version with windbg

connection via emulated serial port over

  • target vm qemu command line: (it will open the windbg vm's tcp port, i.e. be a tcp client)
    • qemu... -serial tcp:0.0.0.0:4442
  • To debug boot process start it in suspended mode with a stdio monitor interface (you could also automate this with qmp, left as an exercise for the reader) and wait until you connect with windbg before executing 'cont' on the monitor.
  • windbg vm qemu command line:
    • qemu ... -chardev socket,id=test,host=localhost,port=4442,server,nowait -monitor stdio -device isa-serial,chardev=test

Kernel Debug setup

This depends on your target os:

winxp

  • edit c:\boot.ini, place the following contents:
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Windows XP Professional (Debug COM1)"
/noexecute=optin /fastdetect /debug /debugport=COM1 /baudrate=115200

Windows 7

as admin, from cmd:

  • bcdedit /debug on
  • bcdedit /bootdebug on

WDDM debugging

Debugging user mode dll

using windbg, attach / run tester

help

  • .hh xxx

load symbols

list loaded modules

  • lm t n

go

  • g

restart

  • .restart /f

stack backtrace

  • kb

registers

  • r

display ascii

  • da

unassamble

  • u
  • uf CreateDXGIFactory

breakpoints

  • bp qxlum.dll!OpenAdapter10

break on loading of user mode dll:

  • sxe ld:qxlum.dll
  • step until next call: pc
  • step over: p
  • step into: t
  • step out: gu

HCK Status

Note 1: Currently running HCK on the [XPDM ] driver only.

Note 2: Obviously this should not be in a wiki but in some automated process (not that you can't have both ;)

Status collection notes

Running from VS2013 (example):

  • type "C:\Users\spice-win7-32\AppData\Roaming\Microsoft\DriverTest\TestRepository\Results\TestTextlog 00305.log" | find "ERROR" > \\192.168.100.1\public\errors.txt
  • cat errors.txt | sed -e 's/^/\* /' | xsel
    • TODO use pre (add a space instead of an asterisk) and edit css to add 'overflow-x: scroll ; width: 600' to pre tags
  • paste here

XPDM Status

Surprise Removal - fail

  • WDTF_SIMPLE_IO  : ERROR : - PerformIO(Red Hat QXL GPU PCI\VEN_1B36&DEV_0100&SUBSYS_11001AF4&REV_04\3&13C0B0C5&0&10 ) Failed : Image comparison failed HRESULT=0x80004005 Count 1
  • WDTF_PNP  : ERROR : Result: Failed to receive IRP_MN_REMOVE_DEVICE after receiving IRP_MN_SURPRISE_REMOVAL. Ensure that there are no open handles or references to the test device (in user mode or in kernel mode) preventing IRP_MN_REMOVE_DEVICE from being sent. You may need to terminate any processes or services that may have open user mode handles to this device. ( 80004005 ).
  • WDTF_PNP  : ERROR : Result: Successful , but device not started, ( Status=1802002 (DN_DRIVER_LOADED DN_DISABLEABLE DN_NT_ENUMERATOR DN_NT_DRIVER ) Problem=0 () )..
  • WDTF_SIMPLE_IO  : ERROR : - PerformIO(Red Hat QXL GPU PCI\VEN_1B36&DEV_0100&SUBSYS_11001AF4&REV_04\3&13C0B0C5&0&10 ) Failed : Image comparison failed HRESULT=0x80004005 Count 1
  • WDTF_TARGET  : ERROR : WDTF.ConcurrentIO.1 SetTarget() ERROR : CWDTFConcurrentIOImpl::SetTarget() Failed to open the EDT device Win32=1 - Incorrect function.
  • WDTF_TARGET  : ERROR : WDTF.ConcurrentIO.1 SetTarget() ERROR : CWDTFConcurrentIOImpl::SetTarget() Failed to open the EDT device Win32=1 - Incorrect function.

HCK and Visual Studio 2013

Microsoft has a test suite for drivers, actually passing the tests is mandatory. Installing the whole test suite takes a lot of time/space but there is an alternative of running the tests from the command line.

You should run the tests from Visual Studio 2013. It is much easier, and very useful during development, plus you should already be using Visual Studio 2013 for the development and deployment, and that's the same setup required for launching tests that are part of the HCK.