qubes-doc/common-tasks/pci-devices.md

148 lines
7.9 KiB
Markdown
Raw Normal View History

---
layout: doc
title: PCI Devices in Qubes R4.0
permalink: /doc/pci-devices/
redirect_from:
- /doc/pci-devices-in-qubes-R4.0/
---
PCI Devices in Qubes R4.0
2019-01-05 04:46:12 -05:00
=========================
*This page is part of [device handling in qubes]*
(In case you were looking for the [R3.2 documentation](/doc/assigning-devices/).)
**Warning:** Only dom0 exposes PCI devices. Some of them are strictly required in dom0! (e.g. host bridge)
You may end up with an unusable system by attaching the wrong PCI device to a VM.
**Security warning:** PCI passthrough should be safe by default, but none-default options may be required. Please make sure you carefully read and understood the **[security considerations]** before deviating from default behavior!
Unlike other devices ([USB], [block], mic), PCI devices need to be attached on VM-bootup. Similar to how you can't attach a new soundcard after your computer booted (and expect it to work properly), attaching PCI devices to already booted VMs isn't possible in any meaningful way.
The Qubes installer attaches all network class controllers to `sys-net` and all USB controllers to `sys-usb` by default, if you chose to create the network and USB qube during install.
While this covers most use cases, there are some occasions when you may want to manually attach one NIC to `sys-net` and another to a custom NetVM, or have some other type of PCI controller you want to manually attach.
Note that one can only attach full PCI or PCI Express devices by default.
This limit is imposed by the PC and VT-d architectures.
This means if a PCI device has multiple functions, all instances of it need to be attached to the same qube unless you have disabled the strict requirement with the `no-strict-reset` option during attachment.
In the steps below, you can tell if this is needed if you see the BDF for the same device listed multiple times with only the number after the "." changing.
While PCI device can only be used by one powered on VM at a time, it *is* possible to *assign* the same device to more than one VM at a time.
This means that you can use the device in one VM, shut that VM down, start up a different VM (to which the same device is now attached), then use the device in that VM.
This can be useful if, for example, you have only one USB controller, but you have multiple security domains which all require the use of different USB devices.
#Attaching Devices Using the GUI
The qube settings for a VM offers the "Devices"-tab. There you can attach PCI-devices to a qube.
1. To reach the settings of any qube either
- Press Alt+F3 to open the application finder, type in the VM name, select the "![appmenu]\[VM-name\]: Qube Settings" menu entry and press enter or click "Launch"!
- Select the VM in Qube Manager and click the settings-button or right-click the VM and select `Qube settings`.
- Click the Domain Manager ![device manager icon], hover the VM you want to assing a device to and select "settings" in the additional menu. (only running VMs!)
2. Select the "Devices" tab on the top bar.
3. Select a device you want to attach to the qube and click the single arrow right! (`>`)
4. You're done. If everything worked out, once the qube boots (or reboots if it's running) it will start with the pci device attached.
5. In case it doesn't work out, first try disabeling memory-balancing in the settings ("Advanced" tab). If that doesn't help, read on to learn how to disable the strict reset requirement!
#`qvm-pci` Usage
The `qvm-pci` tool allows PCI attachment and detachment. It's a shortcut for [`qvm-device pci`][qvm-device].
To figure out what device to attach, first list the available PCI devices by running (as user) in dom0:
qvm-pci
This will show you the `backend:BDF` (Bus_Device.Function) address of each PCI device.
It will look something like `dom0:00_1a.0`.
Once you've found the address of the device you want to attach, then attach it like this:
qvm-pci attach targetVM sourceVM:[BDF] --persistent
Since PCI devices have to be attached on bootup, attaching has to happen with the `--persistant` option.
For example, if `00_1a.0` is the BDF of the device you want to attach to the "work" domain, you would do this:
qvm-pci attach work dom0:00_1a.0 --persistent
#Possible Issues
##DMA Buffer Size
VMs with assigned PCI devices in Qubes have allocated a small buffer for DMA operations (called swiotlb).
By default it is 2MB, but some devices need a larger buffer.
To change this allocation, edit VM's kernel parameters (this is expressed in 512B chunks):
# qvm-prefs netvm |grep kernelopts
kernelopts : iommu=soft swiotlb=2048 (default)
# qvm-prefs -s netvm kernelopts "iommu=soft swiotlb=8192"
This is [known to be needed][ml1] for the Realtek RTL8111DL Gigabit Ethernet Controller.
##PCI Passthrough Issues
Sometimes the PCI arbitrator is too strict.
There is a way to enable permissive mode for it.
See also: [this thread][ml2] and the Xen wiki's [PCI passthrough] page.
At other times, you may instead need to disable the FLR requirement on a device.
Both can be acchieved during attachment with `qvm-pci` as described below.
#Additional Attach Options
Attaching a PCI device through the commandline offers additional options, specifiable via the `--option`/`-o` option. (Yes, confusing wording, there's an [issue for that](https://github.com/QubesOS/qubes-issues/issues/4530).)
`qvm-pci` exposes two additional options. Both are intended to fix device or driver specific issues, but both come with [heavy security implications][security considerations]! **Make sure you understand them before continuing!**
##no-strict-reset
Do not require PCI device to be reset before attaching it to another VM. This may leak usage data even without malicious intent!
usage example:
qvm-pci a work dom0:00_1a.0 --persistent -o no-strict-reset=true
##permissive
Allow write access to full PCI config space instead of whitlisted registers. This increases attack surface and possibility of [side channel attacks].
usage example:
qvm-pci a work dom0:00_1a.0 --persistent -o no-strict-reset=true
2019-01-05 05:05:46 -05:00
#Bringing PCI Devices Back to dom0
By default, when a device is detached from a VM (or when a VM with an attached PCI device is shut down), the device is *not* automatically attached back to dom0.
This is an intended feature.
A device which was previously assigned to a VM less trusted than dom0 (which, in Qubes, is *all* of them) could attack dom0 if it were automatically reassigned there.
In order to re-enable the device in dom0, either:
* Reboot the physical machine. (Best practice)
or
* Go to the sysfs (`/sys/bus/pci`), find the right device, detach it from the pciback driver, and attach it back to the original driver.
Replace `<BDF>` with your full device, for example `0000:00:1c.2`:
echo <BDF> > /sys/bus/pci/drivers/pciback/unbind
MODALIAS=`cat /sys/bus/pci/devices/<BDF>/modalias`
MOD=`modprobe -R $MODALIAS | head -n 1`
echo <BDF> > /sys/bus/pci/drivers/$MOD/bind
It is **strongly discouraged to reattach PCI devices to dom0**, especially if they don't support resetting!
<!--TODO: Is this still needed?-->
2019-01-05 04:46:12 -05:00
[device handling in qubes]: /doc/device-handling/
[security considerations]: /doc/device-considerations/#pci-security
[block]:/doc/block-devices-in-qubes-R4.0/
[USB]:/dock/usb-devices-in-qubes-R4.0/
[appmenu]: https://raw.githubusercontent.com/QubesOS/qubes-artwork/master/icons/32x32/apps/qubes-appmenu-select.png
[domain manager icon]: https://raw.githubusercontent.com/QubesOS/qubes-artwork/master/icons/32x32/apps/qubes-logo-icon.png
[qvm-device]: /doc/device-handling-in-qubes-R4.0/#general-qubes-device-widget-behavior-and-handling
[side channel attacks]: https://en.wikipedia.org/wiki/Side-channel_attack
[ml1]: https://groups.google.com/group/qubes-devel/browse_thread/thread/631c4a3a9d1186e3
[ml2]: https://groups.google.com/forum/#!topic/qubes-users/Fs94QAc3vQI
[PCI passthrough]: https://wiki.xen.org/wiki/Xen_PCI_Passthrough