KVM Passthrough

This post describes how to pass through the host operating system, in order to expose a real piece of hardware device to a KVM virtual machine.

1. Install Qemu-KVM[1]

1.1 Enable the virtualization settings in BIOS.

1.2 Check KVM installation environment.

1
2
3
4
5
$ sudo apt-get update
$ sudo apt-get install cpu-checker
$ sudo modprobe kvm_intel
$ sudo modprobe kvm
$ kvm-ok

1.3 If everything is okay, you can install the qemu-kvm packages.

1
2
3
4
5
$ sudo apt-get install qemu-kvm libvirt-bin ubuntu-vm-builder bridge-utils
$ sudo adduser `id -un` libvirtd
$ sudo chmod 777 /var/run/libvirt/libvirt-sock
$ sudo chown root:libvirtd /dev/kvm
$ virsh -c qemu:///system list 

1.4 If the command below shows you an empty list of virtual machines, the installation is successful. You may now install the virt-manager. which is the GUI tool for KVM.

1
$ sudo apt-get install virt-manager

2. Enable IOMMU support

1
$ sudo vi /etc/default/grub

and add intel_iommu=on in GRUB_CMDLINE_LINUX_DEFAULT parameter.

Regenerate the grub list:

1
$ sudo update-grub

After reboot, you can verify the IOMMU support by type in

1
$ dmesg | grep -e DMAR -e IOMMU

If you are using an Intel machine. For AMD, check here.

3. Modify KVM kernel [2]

I skipped this step.

4. Verify the PCI that you need to attach to the virtual machine.

In the host os, type:

1
$ lspci

Suppose we are interested in passing through this device:

1
20:00.0 VGA compatible controller: Advanced Micro Devices [AMD] nee ATI Caicos [Radeon HD 6450]

which is a PCI-Express Graphics Card. This PCI device 20:00.0 will be the example device in the following steps.

1
2
3
4
$ lspci -n
...
20:00.0 0300: 1002:6779
...

Note down the device ID 1002:6779 .

5. Unbind and bind

5.1 Load the PCI stub module.

1
$ sudo modprobe pci_stub

5.2 Unbind the device from the host kernel, and bind it to pci stub. (need root access)

1
2
3
# echo "1002 6779" > /sys/bus/pci/drivers/pci-stub/new_id 
# echo 0000:20:00.0 > /sys/bus/pci/devices/0000\:20\:00.0/driver/unbind
# echo 0000:20:00.0 > /sys/bus/pci/drivers/pci-stub/bind

6. Assign device

Add extra parameters as below after the usual kvm command.

1
$ kvm ... -device pci-assign,host=20:00.0

If you see errors, check the following section.

7. Necessary permission modifications [3]

According to my experience, you might encounter an error saying:

1
Device 'pci-assign' could not be initialized.

Before you try any solution, first make sure that modules such as kvm, kvm_intel, pci_stub are loaded. Also make sure that intel_iommu=on is in your grub configuration file (even if you see IOMMU from dmesg, it doesn’t ensure that INTEL_IOMMU is enabled). Then if the error is still there, try the following command:

1
# echo 1 > /sys/module/kvm/parameters/allow_unsafe_assigned_interrupts

But I did try something else before the command above, so I suppose that if this command doesn’t work, try the following:

1
# vi  /etc/libvirt/qemu.conf

Uncomment and set user and group to root. Set clear_emulator_capabilites = 0. Set relaxed_acs_check = 1.

Besides, if you are using a RPM-based system such as Fedora, you also need to set SELinux to permissive.

Then run kvm again as root.

1
# kvm ... -device pci-assign,host=20:00.0

8. Done.

In the guest OS, run lspci, and check if you can see the assigned pci device there.

References

[1] https://help.ubuntu.com/community/KVM/Installation

[2] http://www.linux-kvm.org/page/How_to_assign_devices_with_VT-d_in_KVM

[3] http://comments.gmane.org/gmane.comp.emulators.libvirt.user/2945

Porting Android-x86 Onto Qemu-KVM

Before you start, you need to install a lot of packages. Please refer to

https://help.ubuntu.com/community/KVM/Installation

1. Creating a new virtual machine

1
$ qemu-img create android-4.0.img 4G

2. Install the system from the cd image (the iso file).

1
$ kvm -m 2047 -cdrom your_iso_file.iso -hda android-4.0.img -boot d

Install the os to the disk as usual.

After creating a faked SD, do not reboot. Shut down the window.

4. Start the virtual machine.

1
$ sudo kvm -m 2047 -hda android-4.0.img -net nic,model=pcnet -net tap

For the memory size, the numbers matter, so don’t be stingy.

Notice the net model should be pcnet and the second -net parameter should betap, which requires root privilege.

If you don’t have a public bridge yet, you need to set up one first. Please refer to

http://www.linux-kvm.org/page/Networking

Briefly, if you are using Ubuntu, the network configuration can be done by doing the follows: (on the host)

1
2
3
4
5
6
7
8
9
10
11
12
# vi /etc/network/interfaces

  # Replace old eth0 config with br0
  auto eth0 br0
  # Use old eth0 config for br0, plus bridge stuff
  iface br0 inet dhcp
          bridge_ports    eth0
          bridge_stp      off
          bridge_maxwait  0
          bridge_fd       0

# /etc/init.d/networking restart

On the guest because you are actually using a virtual eth0 device, you need to modify your /etc/network/interfaces file to configure eth0.

HowTo - Building Android Kernel Modules (bcm4329.ko)

This post describes the process of building an individual kernel module for Android without compiling the whole kernel.

In order to do this, you need to make sure you already have your Android kernel source compiled, and the version of your module should be the same with the version of your kernel.

Here are some good links for compiling a whole Android kernel: Kernel source (CyanogenMod version) Building kernel from source Integrate kernel into image

After you compile a whole kernel and installed it into your device, if you just want to modify some driver and recompile the specific module, you don’t need to recompile the kernel again. Here is how to compile and install a single module for Android kernel.

In this example, we are interested in buiding the wireless driver module for Google Nexus One – bcm4329.ko. Suppose you are now under the kernel source directory. Here we go:

1. Include the arm-eabi- tool directory into the path.

1
$ export PATH=$PATH:~/android/prebuilt/linux-x86/toolchain/arm-eabi-4.4.3/bin/

2. Generate the configuration file.

(1) Use herring_defconfig as the default configuration file.

1
$ make ARCH=arm herring_defconfig

(2) Modify the configuration file .config with the following changes.

1
2
3
CONFIG_CROSS_COMPILE = "arm-eabi-"
CONFIG_LOCAL_VERSION = "-cyanogenmod"
#CONFIG_LOCALVERSION_AUTO

And set all CONFIG_BCM* to m .

(3) Change another file (and I don’t know why)

1
$ vi scripts/setlocalversion

Locate the following line:

1
2
if $short; then
echo "+"

and change echo "+" to echo "".

3. Set building architecture to be arm.

1
$ export ARCH=arm

4. Make

1
$ make modules

5. Push the new module into the phone.

(1) Remount to be writable.

1
$ adb remount

(2) Push into the device.

1
$ adb push drivers/net/wireless/bcm4329/bcm4320.ko /system/modules

Reference: Compiling kernel modules (tun.ko) for Android