Better Readme

pull/15/head
qaidvoid 4 years ago
parent d3b8ed8e6e
commit fe1dc347ef

@ -1,261 +0,0 @@
*** Resources from [[https://wiki.archlinux.org/index.php/PCI_passthrough_via_OVMF][ArchWiki]] and [[https://github.com/joeknock90/Single-GPU-Passthrough][joeknock's passthrough guide]]
* Set up IOMMU
** Enable IOMMU
**** Load /etc/default/grub and append "intel_iommu=on" or "amd_iommu=on" to GRUB_CMDLINE_LINUX_DEFAULT. Also, "iommu=pt".
**** Update grub configuration.
#+BEGIN_SRC bash
grub-mkconfig -o /boot/grub/grub.cfg
#+END_SRC
** Verify IOMMU is enabled successfully
**** You should see "IOMMU enabled" in output.
#+BEGIN_SRC bash
dmesg | grep -i -e DMAR -e IOMMU | grep enabled
#+END_SRC
* Set up VM
** Installation
**** Install the required packages.
#+BEGIN_SRC bash
sudo pacman -S qemu libvirt edk2-ovmf virt-manager dnsmasq ebtables iptables
#+END_SRC
**** Get virtio drivers ready
***** You can't install Windows without virtio drivers. Click [[https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso][here]] to download.
***** YOu need to add it to VM CDROM. You'll get "Media driver missing" error when installing Windows. Select '/virtio-disk/amd64/win10'
***** Install virtio drivers from CDROM after installing Windows to get everything working..
** Starting services
**** Enable and start libvirt service
#+BEGIN_SRC bash
sudo systemctl enable libvirtd
sudo systemctl start libvirtd
#+END_SRC
** Start default network
**** This may not be needed. If default network isn't started by default for you, start the network manually.
#+BEGIN_SRC bash
sudo virsh net-start default
sudo virsh net-autostart default
#+END_SRC
** Setup Guest OS
***** Launch virt-manager, and start creating guest. On final step, check "Customize before install".
***** > In the "Overview" section, set Chipset to "Q35" and firmware to "UEFI".
***** > In the "CPUs" section, change CPU model to "host-passthrough". You need to type it manually. According to Arch Wiki, this makes sure that the CPU is detected properly. Without it, some applications may complain about your CPU being of an unknown model. You might also need to setup "CPU tolpology" manually if VM only uses one core when you've assigned it more.
***** > Set Disk Bus of Storage to "virtio".
***** > Set NIC Device Model to "virtio".
***** Now, you can *Begin Installation*. You can continue installing Windows right now or after setting up Passthrough.
** Attach PCI devices
**** Remove devices such as Spice Channel, XQL video adaper, USB tablet, etc.
**** Click on "Add Hardware" and add PCI devices for GPU and HDMI Audio. For NVIDIA GPU, GPU ROM should be patched. See next section.
** NVIDIA GPU Patching
**** Dump GPU VBIOS
Using GPU-Z in Windows is the easiest method of dumping VBIOS. You can also download vBIOS from [[https://www.techpowerup.com/vgabios/][TechPowerUp]] (didn't work for me). \\
The following command didn't work for me but it's worth trying.
#+BEGIN_SRC bash
su
echo 1 > /sys/bus/pci/devices/0000:01:00.0/rom
cat /sys/bus/pci/devices/0000:01:00.0/rom > vbios.rom
echo 0 > /sys/bus/pci/devices/0000:01:00.0/rom
#+END_SRC
**** Patch VBIOS file
Use Hex Editor and search string "VIDEO", and remove everything before char *U*, i.e. HEX value *55*.
**** Using Patched VBIOS file
You need to edit configution file of VM.
#+BEGIN_SRC bash
sudo virsh edit win10
#+END_SRC
Search for *hostdev*. Add
#+BEGIN_SRC xml
<rom file="path/to/your/patched_vbios.rom"/>
#+END_SRC
before *<address>* tag.
** Keyboard/mouse Passthrough
**** You need to modify libvirt configuration.
#+BEGIN_SRC bash
sudo virsh edit win10
#+END_SRC
Modify first line
#+BEGIN_SRC xml
<domain type='kvm'>
#+END_SRC
to
#+BEGIN_SRC xml
<domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'>
#+END_SRC
**** Find your keyboard and mouse devices. Use the devices having *event* in their name.
#+BEGIN_SRC bash
ls /dev/input/by-id/
#+END_SRC
**** Verify you selected the right device by using following command. You should see output on terminal when using that device..
#+BEGIN_SRC bash
cat /dev/input/by-id/your_device
#+END_SRC
**** Add devices to the configuration. Add it before closing </domain> tag Replace "MOUSE_NAME" and "KEYBOARD_NAME" with your device id.
#+BEGIN_SRC xml
<qemu:commandline>
<qemu:arg value='-object'/>
<qemu:arg value='input-linux,id=mouse1,evdev=/dev/input/by-id/MOUSE_NAME'/>
<qemu:arg value='-object'/>
<qemu:arg value='input-linux,id=kbd1,evdev=/dev/input/by-id/KEYBOARD_NAME,grab_all=on,repeat=on'/>
</qemu:commandline>
#+END_SRC
**** Switch from PS/2 to virtio inputs. Add it before mouse/keyboard ps2 config.
#+BEGIN_SRC xml
<input type='mouse' bus='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x0e' function='0x0'/>
</input>
<input type='keyboard' bus='virtio'>
<address type='pci' domain='0x0000' bus='0x00' slot='0x0f' function='0x0'/>
</input>
#+END_SRC
**** Include these devices in qemu config. You can replace entire file.
#+BEGIN_SRC conf
user = "your_username"
group = "kvm"
cgroup_device_acl = [
"/dev/kvm",
"/dev/input/by-id/KEYBOARD_NAME",
"/dev/input/by-id/MOUSE_NAME",
"/dev/null", "/dev/full", "/dev/zero",
"/dev/random", "/dev/urandom",
"/dev/ptmx", "/dev/kvm", "/dev/kqemu",
"/dev/rtc","/dev/hpet", "/dev/sev"
]
#+END_SRC
** Add user to different groups
**** Add user to groups input, kvm, libvirt to make sure it has access to required config and devices.
#+BEGIN_SRC bash
sudo usermod -aG input,kvm,libvirt username
#+END_SRC
Restart libvirtd service
#+BEGIN_SRC bash
sudo systemctl restart libvirtd
#+END_SRC
* Libvirt Hooks
***** Libvirt hooks automates the process of running specific tasks during VM startup and shutdown.
Replace *win10* with your guestname. \\ Find GPU kernel modules using command
#+BEGIN_SRC bash
lspci -vnn | grep VGA -A 12 | grep modules
#+END_SRC
**** Create libvirt hook
#+BEGIN_SRC bash
sudo mkdir /etc/libvirt/hooks/
sudo touch /etc/libvirt/hooks/qemu
#+END_SRC
***** Add following content to the qemu hook
More at: [[https://passthroughpo.st/simple-per-vm-libvirt-hooks-with-the-vfio-tools-hook-helper/][PassthroughPost]] \\
Restart libvirtd service after creating qemu hook
#+BEGIN_SRC bash
#!/bin/bash
GUEST_NAME="$1"
HOOK_NAME="$2"
STATE_NAME="$3"
MISC="${@:4}"
BASEDIR="$(dirname $0)"
HOOKPATH="$BASEDIR/qemu.d/$GUEST_NAME/$HOOK_NAME/$STATE_NAME"
set -e # If a script exits with an error, we should as well.
if [ -f "$HOOKPATH" ]; then
eval \""$HOOKPATH"\" "$@"
elif [ -d "$HOOKPATH" ]; then
while read file; do
eval \""$file"\" "$@"
done <<< "$(find -L "$HOOKPATH" -maxdepth 1 -type f -executable -print;)"
fi
#+END_SRC
**** Create start script
Create script that gets executed by libvirt hook when you start VM. Script name can be anything..
#+BEGIN_SRC bash
sudo mkdir -p /etc/libvirt/hooks/qemu.d/win10/prepare/begin
sudo touch /etc/libvirt/hooks/qemu.d/win10/prepare/begin/start.sh
sudo chmod +x /etc/libvirt/hooks/qemu.d/win10/prepare/begin/start.sh
#+END_SRC
Add the following content to script:
#+BEGIN_SRC bash
#!/bin/bash
set -x
# Stop display manager
systemctl stop display-manager
# Unbind EFI Framebuffer
echo efi-framebuffer.0 > /sys/bus/platform/drivers/efi-framebuffer/unbind
# Unload NVIDIA kernel modules
modprobe -r nvidia_drm nvidia_modeset nvidia_uvm nvidia
# Unload AMD kernel module
# modprobe -r amdgpu
# Detach GPU devices from host
# Use your GPU VGA and Audio PCI host device
virsh nodedev-detach pci_0000_01_00_0
virsh nodedev-detach pci_0000_01_00_1
# Load vfio module
modprobe vfio-pci
#+END_SRC
**** Create stop script
Create script that gets executed by libvirt hook when you shutdown/destroy VM. Script name can be anything..
#+BEGIN_SRC bash
sudo mkdir -p /etc/libvirt/hooks/qemu.d/win10/release/end
sudo touch /etc/libvirt/hooks/qemu.d/win10/release/end/shutdown.sh
sudo chmod +x /etc/libvirt/hooks/qemu.d/win10/release/end/shutdown.sh
#+END_SRC
Add the following content to script:
#+BEGIN_SRC bash
#!/bin/bash
set -x
# Unload vfio module
modprobe -r vfio-pci
# Attach GPU devices to host
# Use your GPU VGA and Audio PCI host device
virsh nodedev-reattach pci_0000_01_00_0
virsh nodedev-reattach pci_0000_01_00_1
# Rebind framebuffer to host
echo "efi-framebuffer.0" > /sys/bus/platform/drivers/efi-framebuffer/bind
# Load NVIDIA kernel modules
modprobe nvidia_drm
modprobe nvidia_modeset
modprobe nvidia_uvm
modprobe nvidia
# Load AMD kernel module
# modprobe amdgpu
# Restart Display Manager
systemctl start display-manager
#+END_SRC
* Passing VM Audio to Host via Pulseaudio
Virtual machine's audio can be routed to host as an application using libvirt. \\
Add following config inside *<qemu:commandline>* tag we set up during keyboard/mouse passthrough.
#+BEGIN_SRC xml
<qemu:arg value="-audiodev"/>
<qemu:arg value="pa,id=snd0,server=/run/user/1000/pulse/native"/>
#+END_SRC
* Tweaks
*** Switch to full KVM mode
Add to *<features>* tag.
#+BEGIN_SRC xml
<ioapic driver='kvm'/>
#+END_SRC
*** NVIDIA Driver Error fix
NVIDIA checks if an hypervisor is running and fails if it detects one. It can be fixed by spoofing vendor_id for the hypervisor. \\
Add to *<hyperv>* tag
#+BEGIN_SRC xml
<vendor_id state='on' value='whatever'/>
#+END_SRC
Add to *<features>* tag
#+BEGIN_SRC xml
<kvm>
<hidden state='on'/>
</kvm>
#+END_SRC
Loading…
Cancel
Save