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

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:
    • AMD64_SOURCES=amd64\file.asm

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.

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.

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

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.