TODO: merge / update from http://www.linux-kvm.org/page/WindowsGuestDrivers/UpdatedGuestDebugging
How to build the driver
Repository or sources available from the repositories
You need spice-protocol checked out under directory common, and to set an environment variable (can be done globally or just in the build shell):
set SPICE_COMMON_DIR=c:\common\spice-protocol mkdir c:\common cd common 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
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:
Detailed Instructions: Build QXL on Windows 7 64 bit
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
Bunzip2 --> spice-protocol-0.6.4.tar.bz2 --> copy "spice" folder where qxl_dev.h located to Display, Miniport folders. qxl expect headers to be in "spice" folder.
- Download latest version of WinDDK that support Windows 7.
After installing the Winddk you will have to create new environment variable: Variable name: SPICE_COMMON_DIR with C:\qxl
Open a Free Build x64 command prompt from the WinDDK
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)
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.
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
I) Copying files ( assuming  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\
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
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.
(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:
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
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
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).
And for any secondary cards either use:
Or set it via the device:
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).
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.
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).
This is the way I debug the driver right now:
- 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  below)
- buildvm: build vm (I use  script)
- while not build successfull:
- host: update driver code
- buildvm: build driver
- host: take down test vm
- host: update test vm drivers (see  below, and note )
- host: start test vm
- testvm: test your new code
 - 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
 - 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
 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.
 build script on the build vm (this one builds the win7 checked drivers) (it goes with  above which reads the new drivers from that directory)
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
- 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:
- 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
as admin, from cmd:
- bcdedit /debug on
- bcdedit /bootdebug on
Debugging user mode dll
using windbg, attach / run tester
- .hh xxx
- .reload /f /d
list loaded modules
- lm t n
- .restart /f
- uf CreateDXGIFactory
- 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
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.
- [http://msdn.microsoft.com/en-us/library/windows/hardware/dn265574%28v=vs.85%29.aspx How to run the HCK Test Suites in WDK 8.1}
- How to test a driver at runtime from a Command Prompt