This is a list of steps I went through to get a Linux 2.6.6 UML kernel working in a Linux 2.6.6 host kernel. I initially tried a pre-built Fedora Core 1 host kernel, but abandoned it quickly after realizing that the separate kernel address space (skas) patch is vital for performance.
To make things clear, this is what I did and it worked for me. (Just for sanity, there has to be a better way) As we all know, even the smallest change in hardware or software may render some steps invalid for your system. I used the documentation on the UML website as the basis for all of these steps.
I would love to improve my installation and/or this documentation, so if you have any suggestions or better a way of doing things, feel free to send me an email.
If you want your UMLs to run fast, you should consider recompiling your host kernel using the SKAS patch available at the User-mode Linux site.More information about SKAS can be found here: http://user-mode-linux.sourceforge.net/skas.html The patch can be found here
Now configure the kernel (without ARCH=um, this is a host kernel) enable:make menuconfig/make xconfig make make modules_install
host# make && make install
$ dd if=/dev/zero of=swap_fs bs=1M count=1 seek=127 $ /sbin/mkswap swap_fs
UMLs will create a temporary memory file with the size of the UML's memory ( mem option) in the directory denoted by $TMPDIR . It is recommended to use a tmpfs file system for $TMPDIR as it reduces system load significantly and thus improves overall performance.
To set up a tmpfs directory, create a directory and mount it as type tmpfs . The start script shown later in this document will set the TMPDIR environment variable before booting the kernel. Note, that it is not a good idea to use /tmp with tmpfs as this might break some applications.
You must be root to mount the tmpfs directory. Adjust the size option as needed (Should be as large as the sum of memory assigned to UMLs).
# mkdir umltmpfs # mount -t tmpfs -o mode=1777,size=512M none /usr/src/uml/temp_fs
It is also possible to add the tmpfs directory to the host's fstab to mount it during host system boot.
none /usr/src/uml/temp_fs tmpfs mode=1777,size=512M 0 0
There are several different approaches to allow UMLs to access the network. A description of the possibilites can be found at http://user-mode-linux.sourceforge.net/networking.html. I found the best way to get your host and UML both on the net is to use a bridge and use TUN/TAP. I'm sure the others work, but I had less success. I also found this less confusing as you do not need separate IP addresses for each side of the TUN/TAP setup. I find enabling your UML to access the outside world useful if only to be able to use apt to update the bare bones file systems that are available for download with UML.
On the host where:
The first step is configure your host with a bridge and a tap device. By doing this, neither your ethX or tapX device has an IP address, only the bridge. The commands to execute are: tunctl -u dhildebz brctl addbr br0 ifconfig eth0 0.0.0.0 promisc up ifconfig tap1 0.0.0.0 promisc up ifconfig br0 132.175.21.58 netmask 255.255.255.0 broadcast 132.175.21.255 up brctl stp br0 off brctl setfd br0 1 brctl sethello br0 1 brctl addif br0 eth0 brctl addif br0 tap1 chmod 666 /dev/net/tun Before you change your routing tables, you may need to delete some old entries. route add -net 132.175.21.0 netmask 255.255.255.0 dev br0 route add default gw 132.175.21.1 dev br0 You will need to edit the /etc/sysconfig/network-scripts/ifcfg-eth0 to no longer set the IP address. Here is mine: DEVICE=eth0 BOOTPROTO=static ONBOOT=yes TYPE=Ethernet One thing I haven't done yet is get all of this stuff to automatically load on a reboot of the host (right now I manually run a script, I need to get it into /etc/rc.d or something) If you don't want that tap device any more, you can make it non-persistent with host# tunctl -d tap device Finally, tunctl has a -b (for brief mode) switch which causes it to output only the name of the tap device it created. This makes it suitable for capture by a script: host# TAP=`tunctl -u 1000 -b`
In UML
Once you have succesfully booted UML (as described below), eth0 may be initially configured to some random incorrect value. Edit /etc/sysconfig/network-scripts/ifcfg-eth0 with values for the UML instance. Here is mine: DEVICE=eth0 ONBOOT=YES IPADDR=132.175.21.63 GATEWAY=132.175.21.1 NETMASK=255.255.255.0 NETWORK=132.175.21.0 BROADCAST=132.175.21.255 TYPE=Ethernet Edit /etc/resolv.conf so that it looks like the version on the host. Restart the network (/etc/init.d/network restart) Execute the following to get the routing tables correct. (rebooting the UML kernel will probably also correct the routing table automatically) Essentially it should be the same as the host. route add -net 132.175.21.0 netmask 255.255.255.0 dev eth0 route add default gw 132.175.21.1 dev eth0
First, unpack the kernel and apply both UML-patch's listed here. Then configure the kernel and compile the linux binary and the modules. Do not forget the ARCH=um! I heard rumours of having to perform a make distclean if you forget it.
$ make menuconfig ARCH=umNow you must fix the config as the default doesn't even include networking. Here are some tips:
Make sure that the following is set: CONFIG_FD_CHAN=y CONFIG_NULL_CHAN=y CONFIG_PORT_CHAN=y CONFIG_PTY_CHAN=y CONFIG_TTY_CHAN=y CONFIG_XTERM_CHAN=y CONFIG_CON_ZERO_CHAN="fd:0,fd:1" CONFIG_CON_CHAN="xterm" CONFIG_SSL_CHAN="pty"
$ make linux modules ARCH=um
You now want to mount the root file system and install the modules into it.
mount root_fs mnt -o loop make modules_install INSTALL_MOD_PATH=/path/to/uml/mnt ARCH=um umount mnt
# Run gettys in standard runlevels c0:1235:respawn:/sbin/agetty 38400 console linux #1:2345:respawn:/sbin/agetty ttys/1 VC linux #0:2345:respawn:/sbin/mingetty vc/0 #0:2345:respawn:/sbin/mingetty ttys/0 #1:2345:respawn:/sbin/mingetty ttys/1 #2:2345:respawn:/sbin/mingetty ttys/2 #c:2345:respawn:/sbin/mingetty serial/0 The UML mailing list lists about 10,000 different ways of doing this, but this one worked for me. Also make sure 'console' is in /etc/securetty
e2fsck -f filename dd if=/dev/zero of=filename bs=1 count=1 seek=newsize conv=notrunc resize2fs -p filename e2fsck -f filename
mount root_fs mnt -o loop mv /mnt/lib/tls /mnt/lib/tls.disabled umount mnt
echo "0" >/proc/sys/kernel/exec-shield-randomize
ulimit -n 'file-max'in the xterm I started UML in and in the UML kernel and haven't seen the problem again. (file max from /proc/sys/fs/file-max)
The root file system is now prepared for the first boot. If you intend to create multiple UMLs, I would first get 1 fully working and then copy the root file system for the others. You can use the same temp_fs for all UML instances, but its size must equal the sum of all 'mem=' params set on the command line. (I'm currently only running 1 instance)
Below is an example script to start the UML. The script requires the root_fs and swap_fs files, the configured TUN device and the linux kernel binary.
#!/bin/sh mem=128M fs=/usr/src/uml/root_fs.rh-9-full.pristine.20030724 swapfs=/usr/src/uml/swap_fs # change this path to point to correct tmpfs dir export TMPDIR=/usr/src/uml/temp_fs echo "Checking root file system..." /sbin/e2fsck -C -p $fs if [ $? -gt 1 ]; then echo "*** An error occured during the root filesystem check. ***" exit 1 fi echo "Starting kernel..." ./linux-2.6.6-uml-nfsv4-build/linux \ ubd0=$fs ubd1=$swapfs \ con=pty con0=fd:0,fd:1 \ mem=$mem \ eth0=tuntap,tap1 # If you want an xterm to appear instead of the console, chang the console line to # con0=xterm con1=xterm con=/dev/null \
mknod 8 b 98 16with the correct minor number. I guess ubd 2-7 can be deleted...
/dev/ubd/8 swap swap sw
none /mnt/host hostfs defaults 0 0