NVidia multiseat

From Multiseat

Jump to: navigation, search
Languages Languages: 

English


Contents

Introduction

There are three drivers for nVidia hardware. Two are opensource: nv and nouveau, and one is proprietary, closed source: nvidia driver. Currently, the nvidia driver provides more functionality than the open source drivers.

nv is part of the standard xorg distribution. nouveau is still highly experimental and is available only in bleeding edge packages for a few distributions or git.

My goal is to get multi-seat running on top of the binary closed source driver. This page is my documentation in progress for this effort.

Who needs this page?

If you are using single-head cards then you really don't need this page at all. Follow the regular mdm installation instructions. Install the nvidia driver as you would normally. Hand-edit /etc/mdm/xorg.conf.mdm to replace

driver "nv"

with

driver "nvidia"

and you should be all set.

You only need this page if you have multi-head nvidia based cards. CAVEAT: I've only tried this my own nVidia Quadro 285 based cards. I expect any hardware that uses the binary blob driver from nVidia would work the same.

Configuring Xorg

I am running Debian Lenny, which is about to go into stable. Since Xephyr has seen a lot of changes, and I really want to use Xephyr 1.5, I am running xorg from experimental.

sudo echo deb http://ftp.debian.org/debian/ experimental main contrib non-free >> /etc/apt/sources.list
sudo apt-get update
sudo apt-get upgrade
sudo apt-get -t experimental install xserver-xorg xserver-xorg-core

This should install a whole bunch of xorg packages. You also probably want to clean up any unused packages:

sudo apt-get autoremove

This may well hose your system. Please make sure you know how to recover if the packages trash something on your system.

Configuring xorg.conf.mdm

First, install the appropriate nVidia driver for your hardware, distro, and kernel. There are plenty of HOWTOs and other documentation on this. I will assume you have a working nVidia Xsession to start with, with GLX support, on one head.

nVidia provides a utility, nvidia-settings, that will build an appropriate xorg.conf file for multihead. This will not work from inside a Xephyr session.

First, back up your /etc/X11/xorg.conf. Then start X and nvidia-settings. Configure all your hardware for the monitors you have attached. Make sure you select 'Separate X sessions'. When you save the file, de-select the 'Merge xorg.conf' option. You want the new file with nothing carried over from the old file.

NOTE: nvidia-settings will ignore any cards or outputs that don't have monitors attached.

WARNING: This will wipe out your existing xorg.conf file. This is why you need to back it!

Restart X to make sure all your screens come up. You will have a single login, and depending on your window manager, your menus and panels may be spread all over the screens.

Now copy /etc/X11/xorg.conf to /etc/mdm/xorg.conf.mdm.

Make sure you set RECREATE_XORG_CONF='no' in the /etc/mdm/mdm.conf

Shut down your X session, make sure [kgx]dm is stopped, and start mdm.

You should see a login screen on each attached head.

My system has three video cards:

01:00.0 VGA compatible controller: nVidia Corporation NV44 [Quadro NVS 285] (rev a1)
04:00.0 VGA compatible controller: nVidia Corporation NV34GL [Quadro NVS 280 PCI] (rev a1)
04:02.0 VGA compatible controller: nVidia Corporation NV34GL [Quadro NVS 280 PCI] (rev a1)

The Quadro 285 is a dual head card; the others are single head. I can connect a total of 4 monitors to this system.

My xorg.conf.mdm file:

# nvidia-settings: X configuration file generated by nvidia-settings
# nvidia-settings:  version 1.0  (buildmeister@builder58)  Thu Jul 17 18:39:42 PDT 2008

Section "ServerLayout"
    Identifier     "Layout0"
    Screen      0  "Screen0" 0 0
    Screen      1  "Screen1" RightOf "Screen0"
    Screen      2  "Screen2" RightOf "Screen1"
    Screen      3  "Screen3" RightOf "Screen2"
    InputDevice    "Keyboard0" "CoreKeyboard"
    InputDevice    "Mouse0" "CorePointer"
EndSection

Section "Files"
#    RgbPath         "/usr/X11R6/lib/X11/rgb"
EndSection

Section "Module"
    Load           "dbe"
    Load           "extmod"
    Load           "type1"
    Load           "freetype"
    Load           "glx"
EndSection

Section "ServerFlags"
    Option         "Xinerama" "0"
EndSection

Section "InputDevice"
    # generated from default
    Identifier     "Mouse0"
    Driver         "mouse"
    Option         "Protocol" "auto"
    Option         "Device" "/dev/psaux"
    Option         "Emulate3Buttons" "no"
    Option         "ZAxisMapping" "4 5"
EndSection

Section "InputDevice"
    # generated from default
    Identifier     "Keyboard0"
    Driver         "kbd"
EndSection

Section "Monitor"
    # HorizSync source: edid, VertRefresh source: edid
    Identifier     "Monitor0"
    VendorName     "Unknown"
    ModelName      "ViewSonic"
    HorizSync       31.5 - 64.0
    VertRefresh     60.0 - 75.0
    Option         "DPMS"
EndSection

Section "Monitor"
    # HorizSync source: edid, VertRefresh source: edid
    Identifier     "Monitor1"
    VendorName     "Unknown"
    ModelName      "Optiquest"
    HorizSync       31.5 - 93.8
    VertRefresh     56.0 - 85.0
    Option         "DPMS"
EndSection

Section "Monitor"
    # HorizSync source: edid, VertRefresh source: edid
    Identifier     "Monitor2"
    VendorName     "Unknown"
    ModelName      "PNR PX212M"
    HorizSync       31.0 - 92.0
    VertRefresh     56.0 - 86.0
    Option         "DPMS"
EndSection

Section "Monitor"
    # HorizSync source: edid, VertRefresh source: edid
    Identifier     "Monitor3"
    VendorName     "Unknown"
    ModelName      "PNR PX212M"
    HorizSync       31.0 - 92.0
    VertRefresh     56.0 - 86.0
    Option         "DPMS"
EndSection

Section "Device"
    Identifier     "Videocard0"
    Driver         "nvidia"
    VendorName     "NVIDIA Corporation"
    BoardName      "Quadro NVS 285"
    BusID          "PCI:1:0:0"
    Screen          0
EndSection

Section "Device"
    Identifier     "Videocard1"
    Driver         "nvidia"
    VendorName     "NVIDIA Corporation"
    BoardName      "Quadro NVS 285"
    BusID          "PCI:1:0:0"
    Screen          1
EndSection

Section "Device"
    Identifier     "Videocard2"
    Driver         "nvidia"
    VendorName     "NVIDIA Corporation"
    BoardName      "Quadro NVS 55/280 PCI"
    BusID          "PCI:4:0:0"
EndSection

Section "Device"
    Identifier     "Videocard3"
    Driver         "nvidia"
    VendorName     "NVIDIA Corporation"
    BoardName      "Quadro NVS 55/280 PCI"
    BusID          "PCI:4:2:0"
EndSection

Section "Screen"
    Identifier     "Screen0"
    Device         "Videocard0"
    Monitor        "Monitor0"
    DefaultDepth    24
    Option         "TwinView" "0"
    Option         "TwinViewXineramaInfoOrder" "CRT-0"
    Option         "metamodes" "CRT-0: 1024x768 +0+0"
    SubSection     "Display"
        Depth       24
    EndSubSection
EndSection

Section "Screen"
    Identifier     "Screen1"
    Device         "Videocard1"
    Monitor        "Monitor1"
    DefaultDepth    24
    Option         "TwinView" "0"
    Option         "metamodes" "CRT-1: 1152x864 +0+0"
    SubSection     "Display"
        Depth       24
    EndSubSection
EndSection

Section "Screen"
    Identifier     "Screen2"
    Device         "Videocard2"
    Monitor        "Monitor2"
    DefaultDepth    24
    Option         "TwinView" "0"
    Option         "metamodes" "1024x768 +0+0"
    SubSection     "Display"
        Depth       24
    EndSubSection
EndSection

Section "Screen"
    Identifier     "Screen3"
    Device         "Videocard3"
    Monitor        "Monitor3"
    DefaultDepth    24
    Option         "TwinView" "0"
    Option         "metamodes" "1024x768 +0+0"
    SubSection     "Display"
        Depth       24
    EndSubSection
EndSection

Here's a more sophisticated xorg.conf file, showing how to override the nvidia auto-detection for resolution. This computer has 2 dual-head Quadro 285 cards.

# nvidia-settings: X configuration file generated by nvidia-settings
# nvidia-settings:  version 1.0  (buildmeister@builder62)  Mon Aug 11 12:30:09 PDT 2008

Section "ServerLayout"
    Identifier     "Layout0"
    Screen      0  "Screen0" 0 0
    Screen      1  "Screen1" RightOf "Screen0"
    Screen      2  "Screen2" RightOf "Screen1"
    InputDevice    "Keyboard0" "CoreKeyboard"
    InputDevice    "Mouse0" "CorePointer"
EndSection

Section "Files"
EndSection

Section "Module"
    Load           "dbe"
    Load           "extmod"
    Load           "type1"
    Load           "freetype"
    Load           "glx"
EndSection

Section "ServerFlags"
    Option         "Xinerama" "0"
EndSection

Section "InputDevice"
    # generated from default
    Identifier     "Mouse0"
    Driver         "mouse"
    Option         "Protocol" "auto"
    Option         "Device" "/dev/psaux"
    Option         "Emulate3Buttons" "no"
    Option         "ZAxisMapping" "4 5"
EndSection

Section "InputDevice"
    # generated from default
    Identifier     "Keyboard0"
    Driver         "kbd"
EndSection

Section "Monitor"
    # HorizSync source: edid, VertRefresh source: edid
    Identifier     "Monitor0"
    VendorName     "Unknown"
    ModelName      "Niko-1906R"
    HorizSync       30.0 - 83.0
    VertRefresh     50.0 - 76.0
    Option         "DPMS"
EndSection

Section "Monitor"
    # HorizSync source: edid, VertRefresh source: edid
    Identifier     "Monitor1"
    VendorName     "Unknown"
    ModelName      "PNR PX212M"
    HorizSync       31.0 - 92.0
    VertRefresh     56.0 - 72.0
    Modeline "1280x1024@60"   108   1280 1328 1440 1688   1024 1025 1028 1066  +hsync +vsync
    Modeline "1024x768@75"   78.75  1024 1040 1136 1312  768 769 772 800 +hsync +vsync
    Modeline "1024x768@70"   75.00  1024 1048 1184 1328  768 771 777 806 -hsync -vsync
    Modeline "1024x768@60"   65.00  1024 1048 1184 1344  768 771 777 806 -hsync -vsync
    Option         "DPMS"
EndSection

Section "Monitor"
    # HorizSync source: edid, VertRefresh source: edid
    Identifier     "Monitor2"
    VendorName     "Unknown"
    ModelName      "HSD CY199"
    HorizSync       24.0 - 80.0
    VertRefresh     56.0 - 75.0
    Option         "DPMS"
EndSection

Section "Monitor"
    # HorizSync source: edid, VertRefresh source: edid
    Identifier     "Monitor3"
    VendorName     "Unknown"
    ModelName      "Sharp 37U"
    HorizSync       31.0 - 92.0
    VertRefresh     56.0 - 72.0
    ModeLine       "1368x720@60" 79.7 1264 1416 1456 1752 688 722 724 758
    Option         "DPMS"
EndSection

Section "Device"
    Identifier     "Device0"
    Driver         "nvidia"
    VendorName     "NVIDIA Corporation"
    BoardName      "Quadro NVS 285"
    BusID          "PCI:2:0:0"
    Screen          0
EndSection

Section "Device"
    Identifier     "Device1"
    Driver         "nvidia"
    VendorName     "NVIDIA Corporation"
    BoardName      "Quadro NVS 285"
    BusID          "PCI:2:0:0"
    Screen          1
EndSection

Section "Device"
    Identifier     "Device2"
    Driver         "nvidia"
    VendorName     "NVIDIA Corporation"
    BoardName      "Quadro NVS 285"
    BusID          "PCI:6:0:0"
    Screen          0
EndSection

Section "Device"
    Identifier     "Device3"
    Driver         "nvidia"
    VendorName     "NVIDIA Corporation"
    BoardName      "Quadro NVS 285"
    BusID          "PCI:6:0:0"
    Screen          1
EndSection

Section "Screen"
    Identifier     "Screen0"
    Device         "Device0"
    Monitor        "Monitor0"
    DefaultDepth    24
    Option         "TwinView" "0"
    Option         "metamodes" "DFP-1: nvidia-auto-select +0+0"
    SubSection     "Display"
        Depth       24
    EndSubSection
EndSection

Section "Screen"
    Identifier     "Screen1"
    Device         "Device1"
    Monitor        "Monitor1"
    DefaultDepth    24
    Option         "TwinView" "0"
    Option	   "IgnoreEDID" "True"
    Option	   "ExactModeTimingsDVI" "True"
    Option	   "ModeValidation" "NoDFPNativeResolutionCheck"
    Option         "metamodes" "DFP-0: 1024x768@60 +0+0"
    SubSection     "Display"
        Depth       24
        Modes      "1024x768@60"
    EndSubSection
EndSection

Section "Screen"
    Identifier     "Screen2"
    Device         "Device2"
    Monitor        "Monitor2"
    DefaultDepth    24
    Option         "TwinView" "0"
    Option         "metamodes" "nvidia-auto-select +0+0"
    SubSection     "Display"
        Depth       24
    EndSubSection
EndSection

Section "Screen"
    Identifier     "Screen3"
    Device         "Device3"
    Monitor        "Monitor3"
    DefaultDepth    24
    Option         "TwinView" "0"
    Option	   "IgnoreEDID" "True"
    Option	   "ExactModeTimingsDVI" "True"
    Option	   "ModeValidation" "NoDFPNativeResolutionCheck"
    Option         "metamodes" "DFP-0: 1368x720@60 +0+0"
    SubSection     "Display"
        Depth       24
	Modes      "1368x720@60"
    EndSubSection
EndSection

Patching mdm scripts for nvidia compatibility

From what I understand the nvidia driver doesn't support randr 1.2, so mdm's autodetection of heads doesn't work. Instead, the nvidia driver creates 'virutal' video cards, one for each head. These cards are created when X is started, so mdm's discover-devices script fails to detect them. In order to correctly detect all monitors on all heads, you will need to patch discover-devices, mdm-start-seat, mdm-bin, and create a small utility, nvidia-discover-screens, in /usr/local/bin/.

Don't expect these patches to make it into mainline. The nvidia binary drivers are not supported by Xorg, and making changes to accommodate one closed source vendor is not in the best interest of mdm's developers.

Patch for discover-devices:

diff --git a/mdm/src/discover-devices b/mdm/src/discover-devices
index 2309cc7..fd4a94e 100755
--- a/mdm/src/discover-devices
+++ b/mdm/src/discover-devices
@@ -47,7 +47,6 @@ function discover_input () {
 
 # Prints bus address and drivers of the video cards.
 function video_cards () {
-
     # calling discover is way toooooo slow!
     OUTPUT=$($DISCOVER -t display --vendor-id --model-id)
     VENDOR_IDS=($(echo "$OUTPUT" | cut -d' ' -f1))
@@ -55,6 +54,7 @@ function video_cards () {
     # There can be empty lines on "drivers"
     DRIVERS=($($DISCOVER -t display --data-path=xfree86/server/device/driver \
 	       | sed 's/^$/vesa/g'))
+    NVIDIA=0
 
     for (( i = 0; i < ${#VENDOR_IDS[@]}; i++)); do
         # If there are multiple cards with the same IDs, lspci will print
@@ -71,8 +71,12 @@ function video_cards () {
 
 	BUS_IDS[i]=$(lspci -d ${VENDOR_IDS[i]}:${MODEL_IDS[i]} | 
 		     cut -d' ' -f1 | head -n $((TIMES_USED+1)) | tail -n 1)
+
+	ADRIVER=`lspci -n -k -s ${BUS_IDS[i]} | grep driver | sed 's/^.*: //'`
+	if [[ -n $ADRIVER && $ADRIVER == "nvidia" ]] ; then NVIDIA=1 ; fi
     done
 
+
     for (( i=0 ; i < ${#BUS_IDS[@]}; i++ )) ; do
         # busid from lspci is in format 00:00.00
         # below we split in 00 and 00.00
@@ -83,12 +87,14 @@ function video_cards () {
                   awk 'BEGIN {FS="."}{print toupper($1), toupper($2)}'`)
 	# now, we convert the numbers from hexa to decimal base 
         echo -e "bus\t`echo "obase=10;ibase=16;${NUMS[0]};${SEC_NUMS[0]};${SEC_NUMS[1]};" | bc | paste -s -d":"`"
-
-    done
-    
-    for i in ${DRIVERS[@]}; do
-        echo -e "driver\t$i"
     done
+    if [[ $NVIDIA == 1 ]] ; then
+	/usr/local/bin/nvidia-discover-screens drivers
+    else
+    	for i in ${DRIVERS[@]}; do
+        	echo -e "driver\t$i"
+    	done
+    fi
 } # video_cards
 
 # ******************** MAIN *************************

Patch for mdm-bin

diff --git a/mdm/src/mdm-bin b/mdm/src/mdm-bin
index 79c88c9..2a8d514 100755
--- a/mdm/src/mdm-bin
+++ b/mdm/src/mdm-bin
@@ -86,6 +86,14 @@ function exec_start() {
     else
 	display_manager_start_underneath_xserver >> $MY_LOG 2>&1
 
+        log --log-file-only "re-detecting cards"
+        VIDEO_CARDS=`$DISCOVER_DEVICES driver | wc -l`
+        log --log-file-only "$VIDEO_CARDS video cards detected"
+        # find out how many seats we actually have
+        OUTPUTS_PER_CARD=$(grep "SCREEN_AMOUNT" $XRANDR_INFO_FILE | cut -d'=' -f2)
+        SEATS=$(echo $OUTPUTS_PER_CARD | sed 's/\s/+/g' | bc)
+        log --log-file-only "$SEATS seats detected"
+
         for ((i=0; i < $VIDEO_CARDS; i++)); do
             export DISPLAY=:0.$i
 	    xrandr_configure_layout

mdm-start-seat

diff --git a/mdm/src/mdm-start-seat b/mdm/src/mdm-start-seat
index e7a9f1b..6edc31a 100755
--- a/mdm/src/mdm-start-seat
+++ b/mdm/src/mdm-start-seat
@@ -89,7 +89,7 @@ function parse_config_file () {
     else
         MY_XKB_LAYOUT=$DEFAULT_XKB_LAYOUT
     fi
-    if [ ! -z ${MODE[SEAT_NUMBER]} ]; then
+    if [[ -n ${MODE[SEAT_DISPLAY]} ]]; then
         MY_SCREEN_SIZE=${MODE[VIDEO_CARD_NUMBER]}
     else
         MY_SCREEN_SIZE=$DEFAULT_MODE
@@ -97,7 +97,7 @@ function parse_config_file () {
 }
 
 function select_keyboard () {
-    if [ -e "${MDM_DEVICES}/keyboard${SEAT_DISPLAY}" ]; then
+    if [[ -e "${MDM_DEVICES}/keyboard${SEAT_DISPLAY}" ]]; then
 	return
     fi

Discovering nvidia screens

The helper script, nvidia-discover-devices, creates the xrandr.info file and also returns the number of virtual video cards. To use this script, first put it in /usr/local/bin. At this point, it helps to be working with a laptop that lets you ssh into the multiterminal machine.

ssh into your target machine and kill gdm and all running X sessions. Then start X using the xorg.conf from /etc/mdm:

athena:~# X -config /etc/mdm/xorg.conf.mdm

You will get a mottled gray screen on all your displays. Now run nvidia-discover-screens. You should get a xrandr.info file. Once you've verified it, you can place it into /etc/mdm:

athena:~# nvidia-discover-screens > /etc/mdm/xrandr.info

Kill X and start mdm; you should be all set.

athena:~# killall X
athena:~# /etc/init.d/mdm start
#!/bin/sh

#Xrandr info file generated on: Sat Sep 20 07:58:12 PDT 2008

#DISPLAY=:0.0
#SCREEN_AMOUNT=1
#OUTPUT_NAMES=default
#SCREEN_SIZES=1024x768
#SCREEN_X_ORIGIN=0
#------------ end ------------


XAUTHORITY=/var/lib/gdm/:0.Xauth
export XAUTHORITY
SCREENS=`nvidia-settings --display :0 --ctrl-display :0 -query screens | grep '[.*]' | sed -e 's/(.*)//g' -e 's/\[.*\]//g' -e 's/.*://g'`
#echo $SCREENS

if [ $1 == 'drivers' ] ; then
	for screen in $SCREENS ; do
		echo driver nvidia
	done
else

	echo Xrandr info file generated on: `date`
	for screen in $SCREENS; do
		RES=`nvidia-settings --ctrl-display :$screen -query FrontendResolution | grep Attribute | sed -e 's/^.*): //' -e 's/\.//' -e 's/,/x/'`
		echo 
		echo DISPLAY=$screen
		echo SCREEN_AMOUNT=1
		echo OUTPUT_NAMES=default
		echo SCREEN_SIZES=$RES
		echo SCREEN_X_ORIGIN=0
		echo ------------ end ------------
	done
fi


Problems, issues, and troubleshooting

Black or gray screen on boot

I've had a problem with cold booting the system. The screens will come up either black or with the default X mottley gray background.

If you experience problems with black or gray screens on boot, try adding a longer delay to xephyr-gdm.

athena:~# vi /usr/share/mdm/modes/xephyr-gdm

and find the display_manager_start_underneath_xserver function near the top. The script ships with a delay of 5 seconds. On my system changing the

sleep 5

to

sleep 15

appears to have solved the black screen problem.

function display_manager_start_underneath_xserver () {
    # In case we're using nested xservers (like Xephyr), we'll need to start an
    # xserver to run the nested servers on top of it
    # Don't put login screen on this server!
    # We assume $DISPLAY is already set here.

    $GDMDYNAMIC -a 0=XNotHandled
    $GDMDYNAMIC -r 0
    # XXX: find a better way to wait for X to start
    sleep 15;
}

Xephyr starts with no devices

If the xephyrs start but keyboard and mouse don't respond, check to see if ps shows Xephyr starting with no mouse and keyboard device specified.

athena:~# ps auxwww | grep Xephyr
Xephyr :1 -br :1 -parent 0x200003 -mouse evdev,,device= -keybd evdev,,device=,xkbmodel=evdev,xkblayout=us -auth /var/lib/gdm/:1.Xauth -nolisten tcp vt9

Note the device= entries. Make sure that /etc/mdm/mdm.conf is configured to reconfigure input:

# Reconfigure the input devices every time (re-creating the links)
# Values: 'yes', 'no'.
RECONFIGURE_INPUT='yes'

This should be fixed in future releases.

mdm appears to start but nothing happens

You issue a

/etc/init.d/mdm start

command and the system comes back to a command prompt but X doesn't start up.

While there may be lots of reasons for this, I found that in my case, this is apparently due to the nVidia hardware not being included in /usr/share/xserver-xorg/pci.

This is fixed in the latest discover-devices script. Update from git and use that script.

Personal tools
Communication