Talk:Nouveau & nvidia-drivers switching
Before creating a discussion or leaving a comment, please read about using talk pages. To create a new discussion, click here. Comments on an existing discussion should be signed using
~~~~
:
A comment [[User:Larry|Larry]] 13:52, 13 May 2024 (UTC) : A reply [[User:Sally|Sally]] 10:46, 5 November 2024 (UTC) :: Your reply ~~~~
Rondo (talk) 12:11, 13 December 2013 (UTC) The article suggests 2 kernels, why not just blacklist the nvidia/nouveau module on boot and change xorg.conf?
Switching using a single kernel and systemd (but also openrc and maybe others or maybe this is independant from the init system?)
i did successfully blacklist the nvidia-driver via the grub2 modprobe.blacklist=nvidia option and it did work with openrc. this paragraph should not mention systemd as a prerequisite to do this.
Loading modules for the kernel command line is not the issue. You need a mechanism to control switching the opengl/opencl x11 drivers in xorg.conf. The current documentation uses a systemd environment variable. Not sure if openrc supports setting any environment variables from kernel command line. You might be able to change it according to results from querying the kernel command line via /proc/cmdline
@Reuben. Thank you for the explanation. I did not go further than changing the grub to mask the driver i do not need. All the other steps like xorg.conf and opengl settings are done manually. It is sufficient for me as the biggest (timeconsuming) problem for me would be the kernel recompilation.
FireFish5000 (talk) 00:08, 31 July 2015 (UTC) I would like to first confirm that blacklisting modules works with both or is independent of init system, second we can access boot parameter with 'get_bootparam' in init scripts. This is exemplified by /etc/init.d/xdm which searches for the nox (No X) parameter.
I am adding an OpenRC single kernel version to the page. I would like to quickly explain the reasoning behind any/all changes made.
First, I moved OpenRC and Systemd versions to the top, as I imagine the majority of the users are not going to want to compile 2 kernels, and thus believe that this puts them in order from most likely to use to least likely.
I opted to keep modules blacklisted in /etc/modprobe.d/, as this removes worry of both modules being loaded if bootloader doesn't get updated or gets replaced(eg. a careless user with dispatch-config, editing grub.cfg directly and then calling update-grub). The modules can then be loaded by the script, and a default can be provided in case of the exemplified error above.
I am moving the init script to /etc/init.d/nv-selector for two reasons.
- nvidia.start seems to imply nvidia driver. I am hoping nv makes nvidia and nouveau equally likely, and selector shows we are selecting the driver. nvidia-nouveau or another name may be better.
- It was the only script in my local.d directory. Unless there is an explicit reason for separating it into local.d (some standard for loading drivers? Can't load faster since it depends on a boot-service.), I would prefer to have it grouped with all the other init scripts.
I am setting two NON-dot-conf files in /etc/X11/xorg.conf.d/ for the init script to link to. The reason being that with multihead setups, the work needed to be done may be more complex than just sed 's/nvidia/nouveau/'. We may want to change options like referesh rate, vsync, twinview, dpi, etc depending on driver for a better experience. I use it for naming the monitors which I configure in other files, because for some reason nvidia indexes the ports on 0 while nouveau starts at 1...
The two kernel method is being modified to explicitly recommend builtin nouveau support on one of them, since it makes no sense to have two kernels otherwise. (though it did make sense when written, we now know of a better way)
NOTE: The changes to the wiki proposed below are posted here partially for testing (moving to laptop to reproduce), but mostly to save the changes externaly in case something goes wrong with my computer. Still revising
Module Based Switching
With module based switching, a single kernel is setup to be used with both nvidia and nouveau modules, the bootloader is configured to specify which module to load, and an init script does everything necessary to get the driver and system to work together.
Configure the System
Before switching is possible, the system must be properly configured to support it.
To do this, first make sure the nouveau driver is built as a module:
Device Drivers --->
Graphics support --->
<*> Direct Rendering Manager (XFree86 4.1.0 and higher DRI support) --->
<M> Nouveau (nVidia) cards
Then recompile and install the kernel and kernel modules.
Next set the VIDEO_CARDS variable to support both nvidia and nouveau drivers.
VIDEO_CARDS="... nvidia nouveau ..."
After setting or altering VIDEO_CARDS values remember to update the system using the following command so the changes take effect:
root #
emerge --ask --changed-use --deep @world
And blacklist the nvidia and nouveau modules as you don't want udev to try and autoload them.
root #
echo -e "blacklist nouveau\nblacklist nvidia" >> /etc/modprobe.d/nvidia-n-nouveau.conf
If X11 is used on the system, then two config files need to be setup in /etc/X11/xorg.conf.d/. These files, /etc/X11/xorg.conf.d/00-nv.nvidia and /etc/X11/xorg.conf.d/00-nv.nouveau (name does not matter), will specify settings necessary for nvidia and nouveau drivers respectively. Note they mustn't end in '.conf', as they are not to be loaded themselves. /etc/X11/xorg.conf.d/00-nv.conf will link to the file in use.
Section "Device"
Identifier "nvidia"
Driver "nvidia"
EndSection
</nowiki>
Section "Device"
Identifier "nouveau"
Driver "nouveau"
EndSection
</nowiki>
If driver specific settings need to be supplied, these files would be the place to put them. Some options which may be of interest include TwinView(NVidia only), DPI, monitor-* on multihead systems.
With this, the system should be capable of switching between the two. However, there is nothing currently telling it to automatically load either. To get it loading one on boot, an init script is needed.
Init Scripts
These scripts check for the boot parameters that will be set in the bootloader and setup the system appropriately. Specifically, these scripts load the drivers modules, switch to it's opengl and opencl implementation, and tell xorg which driver to use. With this, driver switching can easily be done with OpenRC and Systemd based init systems. Just follow the instructions relative to the system's setup.
OpenRC
OpenRC is Gentoo's default init system, and thus the one most people will be using. Most of the scripts it uses are located in /etc/init.d/. These scripts are intended to be static, and as such, variables are usualy defined in /etc/conf.d/ in a file of the same name. This script is written keeping that in mind, so hopefully there will be no need to edit it.
#!/sbin/runscript
# Copyright 2015 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
Prefix="[NV-Driver] "
depend() {
need localmount
before xdm
}
nvidia_start() {
einfo "${Prefix}Loading NVIDIA driver"
modprobe -q nvidia
ln -f /etc/X11/xorg.conf.d/00-nv.nvidia /etc/X11/xorg.conf.d/00-nv.conf
eselect opengl set nvidia &>/dev/null
eselect opencl set nvidia &>/dev/null
echo 'nvidia' > '/CURRENT_NV_DRIVER'
einfo "${Prefix}Loaded NVIDIA driver"
}
nouveau_start() {
einfo "${Prefix}Loading NOUVEAU driver"
modprobe -q nouveau
ln -f /etc/X11/xorg.conf.d/00-nv.nouveau /etc/X11/xorg.conf.d/00-nv.conf
eselect opengl set xorg-x11 &>/dev/null
/etc/init.d/consolefont restart
# eselect opencl set mesa &>/dev/null
echo 'nouveau' > '/CURRENT_NV_DRIVER'
einfo "${Prefix}Loaded NOUVEAU driver"
}
show() {
Driver="$(cat /CURRENT_NV_DRIVER)"
if [[ -n "$Driver" ]] ; then
einfo "${Prefix}Using NV-Driver '$Driver'"
else
einfo "${Prefix}No NV-Driver Found '$Driver'"
fi
}
boot_start() {
if get_bootparam "use_nvidia" ; then
nvidia_start
else
nouveau_start
fi
eend $?
}
start() {
ebegin "${Prefix}Loading driver"
boot_start
eend $?
}
Copy it to /etc/init.d/nv-selector and set the executable bit:
root #
chmod +x /etc/init.d/nv-selector
Then add it as a boot level service.
root #
rc-update add nv-selector boot
Systemd
Add the systemd switching script
#!/bin/bash
if [[ "$GPUMOD" == "nvidia" ]] ; then
if [[ $(eselect opengl show) != nvidia ]] ; then
eselect opengl set nvidia &>/dev/null
eselect opencl set nvidia &>/dev/null
fi
cat > /etc/X11/xorg.conf.d/01-nv.conf << EOF
Section "Device"
Identifier "Device0"
Driver "nvidia"
Option "NoLogo" "True"
EndSection
EOF
else
if [[ $(eselect opengl show) != xorg-x11 ]] ; then
eselect opengl set xorg-x11 &>/dev/null
eselect opencl set mesa &>/dev/null
fi
cat > /etc/X11/xorg.conf.d/01-nv.conf << EOF
Section "Device"
Identifier "Device0"
Driver "nouveau"
EndSection
EOF
fi
Remember to set the executable bit.
root #
chmod +x /etc/local.d/nvidia.start
To have this script get called during the systemd init process, you can create a service file for it, but it's just as effective to integrate it into the currently existing xdm | gdm | kdm | other(?) display manager service file. You don't want to edit the service file directly, since that will get overwritten the next time that package is merged that the service file belongs to. Instead you create an override for the service file, placed in /etc/systemd/system/service-name.d
So for example if you use kdm.service you would create the directory /etc/systemd/system/kdm.service.d and place a file in it with a .conf file extension. Add a "[Service]" section that has an entry for ExecStartPre to call nvidia.start before kdm itself is started.
root #
mkdir /etc/systemd/system/kdm.service.d && touch /etc/systemd/system/kdm.service.d/nv.conf
[Service]
ExecStartPre=/etc/local.d/nvidia.start
Bootloader
It should be possible to pass boot parameters with most bootloader, however, the means of doing it may differ. Please read other documentation for bootloaders not specified here. Note the instructions here are made to be as simple as possible. Configurations vary, please consult the existing configuration and adapt the instructions to the system.
Grub
The grub2 menu items shown are for demonstrating the changes to be made. Hopefully you have the common sense not to just copy and paste them verbatim into your grub.cfg.
Within the grub.cfg file you need to duplicate the desired menu item and then edit the two versions to set a boot parameter.
menuentry 'Gentoo Linux' {
root=hd0,1
linux /boot/bzImage root=PARTUUID=11111111-2222-3333-4444-555555555555 init=/usr/lib/systemd/systemd console=tty1
}
menuentry 'Gentoo Linux - Nouveau' {
root=hd0,1
linux /boot/bzImage root=PARTUUID=11111111-2222-3333-4444-555555555555 init=/usr/lib/systemd/systemd console=tty1 modprobe.blacklist=nvidia systemd.setenv=GPUMOD=nouveau
}
menuentry 'Gentoo Linux - Nvidia' {
root=hd0,1
linux /boot/bzImage root=PARTUUID=11111111-2222-3333-4444-555555555555 init=/usr/lib/systemd/systemd console=tty1 modprobe.blacklist=nouveau systemd.setenv=GPUMOD=nvidia
}
Efibootmgr
Before altering anything, it is a probably good idea to read and backup the current configuration. Do this by running:
root #
efibootmgr -v | tee ~/EfiBootMgr_settings
Now, review the settings and alter accordingly. Below shows how one may be setup when there are no pre-existing boot entries.
PARTUUID can be found with ls -l /dev/disk/by-partuuid. NOT the same as UUID. root=UUID may or may not work
Note the current efi boot settings, it will aid in the process. It may be a good idea to copy them just in case something goes wrong
root #
efibootmgr -c -L "Gentoo Linux (nouveau)" --loader '\efi\partition\relitive\path\to\Kernel.efi' -u 'root=PARTUUID=01234567-89ab-cdef-0123-456789abcdef use_nouveau'
root #
efibootmgr -c -L "Gentoo Linux (nvidia)" --loader '\efi\partition\relitive\path\to\Kernel.efi' -u 'root=PARTUUID=01234567-89ab-cdef-0123-456789abcdef use_nvidia'
root #
efibootmgr --bootorder 0000,0001
Using Two Kernels
One may also setup two kernels, one with nouveau built-in and the other without it or with it built as a module. Note there is little reason to use two kernels unless nouveau is compiled-in one of them. To do this, First compile two kernels, One with Nouveau built-in
Device Drivers --->
Graphics support --->
<*> Direct Rendering Manager (XFree86 4.1.0 and higher DRI support) --->
<*> Nouveau (nVidia) cards
And one without or as a module
Device Drivers --->
Graphics support --->
<*> Direct Rendering Manager (XFree86 4.1.0 and higher DRI support) --->
< > Nouveau (nVidia) cards
Next, Follow the same steps as above for the bootloader, changing the path/name for the nvidia and nouveau entries to point to the respective kernels.
Then refer to Init systems for seting up the script which will handle loading nvidia, changing opengl, opencl, and x11 config files .
Possibility of Live (no reboot) switching
--FireFish5000 (talk) 08:29, 10 August 2015 (UTC) It may be possible, with difficulty, to switch between nouveau and nvidia drivers without a reboot (it's GNU/Linux, the real question is how practical such a solution would be).
The instructions below should lead you to the little I currently have. It works for X11(loosing console) from nouveau to nvidia. But from nvidia to nouveau, it corrupts the display completely and goes blank/freezes with x11 (though x11 does start, ie. I can type startx, open firefox and listen to youtube videos blind).
First Ensure module unloading is supported
[*] Enable loadable module support --->
[*] Module unloading
Then add/modify the nv-driver switcher.
#!/sbin/runscript
# Copyright 1999-2009 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: /var/cvsroot/gentoo-x86/x11-base/xorg-server/files/xdm-setup.initd-1,v 1.1 2010/04/13 10:07:39 scarabeus Exp $
extra_commands="nvidia nouveau show"
#extra_started_commands="nvidia"
depend() {
need localmount
before xdm
}
nvidia_start() {
einfo "[NV-Driver] Loading NVIDIA driver"
modprobe -q nvidia
ln -f /etc/X11/xorg.conf.d/00-nv.conf.DISABLED /etc/X11/xorg.conf.d/00-nvidia.conf
eselect opengl set nvidia &>/dev/null
eselect opencl set nvidia &>/dev/null
echo 'nvidia' > '/CURRENT_NV_DRIVER'
einfo "[NV-Driver] Loaded NVIDIA driver"
}
nouveau_start() {
einfo "[NV-Driver] Loading NOUVEAU driver"
modprobe -q nouveau
ln -f /etc/X11/xorg.conf.d/00-nouveau.conf.DISABLED /etc/X11/xorg.conf.d/00-nvidia.conf
eselect opengl set xorg-x11 &>/dev/null
/etc/init.d/consolefont restart
# eselect opencl set mesa &>/dev/null
echo 'nouveau' > '/CURRENT_NV_DRIVER'
einfo "[NV-Driver] Loaded NOUVEAU driver"
}
nvidia_stop() {
einfo "[NV-Driver] Unloading NVIDIA driver"
# TODO Close x11 and all using driver. Or ensure that they have closed
modprobe -q -r nvidia
einfo "[NV-Driver] Unloaded NVIDIA driver"
}
nouveau_stop() {
einfo "[NV-Driver] Unloading NOUVEAU driver"
# TODO Close x11 and all using driver. Or ensure that they have closed
echo 0 > /sys/class/vtconsole/vtcon1/bind
#modprobe -q -r nouveau ttm drm_kms_helper drm
modprobe -q -r nouveau
/etc/init.d/consolefont restart
modprobe -q -r ttm drm_kms_helper drm
einfo "[NV-Driver] Unloaded NOUVEAU driver"
}
nvidia() {
ebegin "[NV-Driver] Switching to NVIDIA driver"
nouveau_stop
nvidia_start
eend $?
}
nouveau() {
ebegin "[NV-Driver] Switching to NOUVEAU driver"
nvidia_stop
nouveau_start
eend $?
}
show() {
Driver="$(cat /CURRENT_NV_DRIVER)"
if [[ -n "$Driver" ]] ; then
einfo "Using NV-Driver '$Driver'"
else
einfo "No NV-Driver Found '$Driver'"
fi
}
boot_start() {
if get_bootparam "use_nvidia" ; then
nvidia_start
else
nouveau_start
fi
eend $?
}
start() {
if get_bootparam "use_nvidia" ; then
ebegin "[NV-Driver] Loading NVIDIA driver"
modprobe -q nvidia
ln -f /etc/X11/xorg.conf.d/00-nv.conf.DISABLED /etc/X11/xorg.conf.d/00-nvidia.conf
eselect opengl set nvidia &>/dev/null
eselect opencl set nvidia &>/dev/null
echo 'nvidia' > '/CURRENT_NV_DRIVER'
else
ebegin "[NV-Driver] Loading NOUVEAU driver"
modprobe -q nouveau
ln -f /etc/X11/xorg.conf.d/00-nouveau.conf.DISABLED /etc/X11/xorg.conf.d/00-nvidia.conf
eselect opengl set xorg-x11 &>/dev/null
# eselect opencl set mesa &>/dev/null
echo 'nouveau' > '/CURRENT_NV_DRIVER'
fi
eend $?
}
With the above script, '/etc/init.d/nv-switcher nvidia' would switch to nvidia if run from shell while x11 isn't running (Checking if in use is in TODO. lsmod seems to be a good indicator, Do NOT try this script while X11 is running or if you do not understand what it is doing). Howver, shell would be blank and '/etc/init.d/nv-switcher nouveau' Would leave you in said state where nothing shows up but blind x11 will nonetheless start. This incomplete and potential harmful script was adapted from the scripts given on this page combined with the scripts here https://askubuntu.com/questions/16998/switch-between-nvidia-current-and-nouveau-without-a-reboot/17068#17068 and the suggestion here https://askubuntu.com/questions/16998/switch-between-nvidia-current-and-nouveau-without-a-reboot/381689#381689. Perhaps someone with more experience dealing with nvidia, nouveau, kernel modules, drivers, or the kernel will have a better idea on how to accomplish this.
Again, this script does NOT currently check if drivers are in use, and WILL lead to both nvidia and Nouveau drivers being loaded if you do not know what you are doing. Don't try this unless you understand the risk.
If you know a way to do this, please tell us. If you add a check for if mods are in use/successfully unloaded, feel free to edit my script to add them.