Skip to end of metadata
Go to start of metadata

Intention/Audience

In this howto I'd like to walk you through the creation of a Xen FreeBSD guest (DomU) with full para-virtualisation (PV). I will assume that you know how to configure Xen DomUs manually, and that you have got at least some basic FreeBSD experience, because you will need to compile a custom kernel later. Furthermore I'm assuming that you don't have any FreeBSD guests running at this point (or don't want to convert any existing ones from HVM to PV).

I will show how to

  • create a HVM guest first
  • transform the guest into a PV guest
  • add full support for the pygrub bootloader

In this short tutorial I chose the HVM-to-PV transition to point out the differences between HVM and PV Xen configurations as well. That may be useful for those of you, who intend to run amd64 HVM guests.
If you are familiar enough with FreeBSD, you can build the entire image from another FreeBSD installation using loop device. I'll come to that towards the end of this tutorial.

Pre-Requisites and Limitations

You cannot use amd64 in PV mode. FreeBSD doesn't support it yet. For now PV support is limited to 32bit aka i386.
However, there's a xenified HVM kernel for amd64, which offers better performance than pure HVM. It's called XENHVM.

You will need:

  • FreeBSD 8.2 ISO (CD disc1), 32bit (as explained in the big red box up there )
  • Xen Hypervisor 3.4+ (this tutorial may work with older versions, but I can't verify myself)
  • ideally you are using LVM as the backend for your DomUs. If you prefer files, that's fine, but then please watch out for phy: and replace it with file: below

Limitations compared to other guest OS:

  • FreeBSD PV guests currently only support 32bit and less then ~850 MB Ram.
  • VNC console will, unlike for Linux DomUs, not be available for FreeBSD PV guests; you need to use xen console or SSH

Spoiler Alert: I've added a Download section at the end of this tutorial, which contains a fully functional FreeBSD PV guest image with pygrub partition and Xen configuration file.

Creating the HVM guest

I'll start showing how to create a HVM guest from scratch, with no other FreeBSD instance around.

To begin, create a Xen configuration file:

/etc/xen/freebsd

# HVM loader
kernel = "/usr/lib/xen/boot/hvmloader"
builder='hvm'
device_model = '/usr/lib/xen/bin/qemu-dm'

# memory can't be much higher than this; known limitation
memory = 850

name = "freebsd"

vif = [ 'bridge=xenbr0']

disk = [
        'phy:/dev/vg0/freebsd,hdb,w',
        'file:/root/FreeBSD-8.2-RELEASE-i386-disc1.iso,hdc:cdrom,r' 
]
# make sure we boot from cdrom here
boot="d"

vcpus = 1

vnc=1
vnclisten="0.0.0.0"
vncpasswd="passwd"
vncdisplay=5

You may have noticed, that there's no device hda in this configuration. I'm doing this on purpose, because that's where we will mount a pygrub-capabable partition later. The benefit of using hdb here is that we don't need to change anything in the DomU later.

Next, you want to create an LVM volume (or empty file) for your DomU. I'll go for 5GB here, although we won't fill all that space.

lvcreate -n freebsd -L5G vg0

Then we're ready to start:

xm create freebsd

Your VNC console can now be connected to port 5905, password is "passwd" obviously.
After boot you'll end up in the installer. Go straight to Custom in the main menu, and start with Partition.
In the Partition Manager press A and then Q to add a partition, which stretches over the whole disk. Then choose the Standard boot manager, and continue with the Labels. Create a 4GB label mounted to / and 1GB swap.
Next go to the Distributions menu and select Minimal and custom, which brings you to another sub menu, where you choos src, then in yet another sub menu base.
Then go back up two levels, and choose the media (CD/DVD), and afterwards Commit. Afterwards you can leave the menus and installer. You will be prompted to remove the CD. So let's do that before we start again:

Change your disk configuration:

/etc/xen/freebsd
[...]
#remove CDROM here:

disk = [
        'phy:/dev/vg0/freebsd,hdb,w'
]
# make sure we do not boot from cdrom any more
# boot="d"

[...]

Now destroy and restart the VM:

xm destroy freebsd
xm create freebsd

The VM will boot up, and at the login prompt you'll not be prompted for a password, as we haven't set one. Do that very soon.

At this stage you have a fully working HVM guest, of course lacking stuff like SSH etc, but you could take it from here if you wanted.

Optional: Serial Console for HVM guest

This step is absolutely irrelevant if you want to create a PV guest. However for HVM images it might be helpful to note that you can use xm console as well, if you configure the domU correctly.
Especially when you run into issues in the bootup process, it may be extremely helpful, as VNC often wouldn't connect fast enough, so that you miss stuff (and you can't copy and paste it as nicely for reference later).

Anyways, it's very easy to get that sorted. In /etc/xen/freebsd add this line:

serial='pty'

In the FreeBSD guest, the serial console setup is absolutely identical to a normal non-Xen console. The important bits, taken from The FreeBSD Handbook:

/etc/ttys
# change this:
ttyu0   "/usr/libexec/getty std.9600"   dialup  off secure

# to this:
ttyu0   "/usr/libexec/getty std.9600"   vt100 on  secure

And finally, also in the guest, run this:

 echo 'console="comconsole"' >> /boot/loader.conf

That's all. Now your serial console will be activated very early in the boot process and you can watch the (very fast) startup progress.
Next time you can start your guest with xm create freebsd -c (note the -c) or connect to a running HVM guest with xm console freebsd, and you'll see and be able to use the serial console.

If you are interested only in HVM guests, you can basically stop reading here. However, it's advisable to use amd64 in that case and compile the XENHVM kernel (not available for i386). That gives you para-virtualised block and network drivers, which are noticeably faster. For the rest of this howto, you must use i386. I can't emphasise that often enough.

Transforming the guest from HVM to PV

However, this tutorial is about PV guests, so let's continue. First you need to get the kernel sources. FreeBSD uses CVSup for that, or csup (minus the 'v') more precisely.

We haven't got networking yet, so here we go:

ifconfig re0 <IP> up
route add default <gateway IP>
echo "nameserver <nameserverIP>" > /etc/resolv.conf
ping sysconfig.org.uk

Now let's get the sources...

csup -L2 -h cvsup2.de.freebsd.org /usr/share/examples/cvsup/stable-supfile

This will take a while. Depending on where you are, you might want to change the hostname to something closer.

After it's completed downloading, we need to build a xen kernel:

cd /usr/src
echo "options  EXT2FS" >> sys/i386/conf/XEN
mkdir /root/myboot
make KERNCONF=XEN DESTDIR=/root/myboot kernel

I'm adding ext2 support here for later, so that we can create a partition for pygrub, which we can then add in as hda. Also that will enable us to write new kernels directly into an area, where the DomU can access it. It will become clearer in the next step, why this is convenient.
In the command above I chose /root/myboot as the destination, because I want to avoid overwriting the kernel in /boot, just in case something goes wrong, we can still easily boot in HVM mode later, which would otherwise be trickier (via boot menu, but you gotta be quick connecting VNC etc).

Now that we're done, you need to copy the kernel into the Dom0, for example via SCP:

scp /root/myboot/boot/kernel/kernel <domOIP>:/root/kernel-freebsd-pv

We'll need that again later. Now let's give some finishing touches. For example you could configure your rc.conf properly to set network details, enable SSH etc, so something like this at the very least (replace appropriate values):

/etc/rc.conf
hostname="domU"
defaultrouter="10.0.0.1"
sshd_enable="YES"

ifconfig_re0="inet 10.0.0.111/24 up"
ifconfig_xn0="inet 10.0.0.111/24 up"

Huh? Same IP twice for re0 and xn0? Indeed! re0 is the interface in HVM mode. In PV mode it will be called xn0 (xen network). Due to that fact, only one of the two can be present at any time, and therefore the IPs won't clash. Even better: Should you want to use the VM in HVM again later, for whatever reason, you will have connectivity as well.

Now we're almost there. As xen uses a consoled called xc0 (in PV mode only), this needs to be added to the configuration, and all ttyv* consoles need to be disabled to avoid nasty warnings:

/etc/ttys
xc0    "/usr/libexec/getty Pc"         cons25  on     secure
#ttyv0  "/usr/libexec/getty Pc"         cons25  on  secure
# Virtual terminals
#ttyv1  "/usr/libexec/getty Pc"         cons25  on  secure
#ttyv2  "/usr/libexec/getty Pc"         cons25  on  secure
#ttyv3  "/usr/libexec/getty Pc"         cons25  on  secure
#ttyv4  "/usr/libexec/getty Pc"         cons25  on  secure
#ttyv5  "/usr/libexec/getty Pc"         cons25  on  secure
#ttyv6  "/usr/libexec/getty Pc"         cons25  on  secure
#ttyv7  "/usr/libexec/getty Pc"         cons25  on  secure
#ttyv8  "/usr/local/bin/xdm -nodaemon"  xterm   off secure

That's it. You'd probably expect changes to /etc/fstab or other tweaks. Well, there aren't any at this stage.
If you've "evacuated" your kernel into Dom0, then you're ready to do this: shutdown -h now

Final touches for the PV configuration

Let's change the guest configuration file first:

/etc/xen/freebsd
kernel="/root/kernel-freebsd-pv"
extra = " vfs.root.mountfrom=ufs:ad1s1a,machdep.idle_mwait=0,boot_verbose=1,kern.hz=100"

# memory can't be much higher than this; known limitation
memory = 850

name = "freebsd"

vif = [ 'bridge=xenbr0']

disk = [
        'phy:/dev/vg0/freebsd,hdb,w'
]

vcpus = 1

You notice that the HVM-related instructions and VNC have gone. Instead we've added the "evacuated" kernel and its parameters.
In particular vfs.root.mountfrom=ufs:ad1s1a is important here, because it describes the slice/label where our installation sits. ad1s1a is the first label in the first slice of hdb

We'll refine that a bit more later. First let's make sure that our setup works.

xm create freebsd -c

Note: the -c tells xm to open a console, which is only possible in PV mode, and sadly the only option, because FreeBSD can't use both VNC and console at the same time for some reason.
Don't panic if the startup hangs for a moment after "starting sshd". That's normal.

If you get to the login and can actually log in, you can shut down the guest again. We'll do some more cosmetics.

Using pygrub

Using pygrub has the advantage that the kernel can reside within the DomU. This step is entirely optional.

First, create another LVM volume (or file, if you choose to), and format it with ext2, prepare directories, and throw your kernel in:

lvcreate -L100M -n freebsd-boot vg0
mkfs -t ext2 /dev/vg0/freebsd-boot
mount /dev/vg0/freebsd-boot /mnt
mkdir -p /mnt/boot/{grub,kernel}
cp /root/kernel-freebsd-pv /mnt/boot/kernel

And now, the last step, adding a grub menu file. That's rather unusual for FreeBSD, but pygrub requires it. So here it goes:

/mnt/boot/grub/menu.lst
timeout=2
default=0

title FreeBSD
        root (hd0,0)
        kernel /boot/kernel/kernel-freebsd-pv vfs.root.mountfrom=ufs:ad1s1a,kern.hz=100,boot_verbose=1,machdep.idle_mwait=0

You can omit timeout=2 at this point, but I tend to keep it in there, just to have the option to load other kernels, if I have to.
Maybe you wonder (if you haven't before) where all the modules are. That's simple. The XEN kernel comes with all necessary stuff compiled in. There aren't any modules. That doesn't keep you from adding any, though.

Unmount /mnt and change your guest configuration a last time:

/etc/xen/freebsd

bootloader="/usr/bin/pygrub"

# memory can't be much higher than this; known limitation
memory = 850

name = "freebsd"

vif = [ 'bridge=xenbr0']

disk = [
        'phy:/dev/vg0/freebsd-boot,hda,w',
        'phy:/dev/vg0/freebsd,hdb,w'
]

vcpus = 1

You see, the kernel references are gone, and pygrub appeared instead. Also, the new boot volume has been inserted as hda.

Now fire it up again. You'll notice the boot menu flashing up (unless you removed the timeout), and apart from that it will boot as it did before.

xm create freebsd -c

Well done!

In the guest you can now use /dev/ad0, which is the boot volume, and update your kernel or grub configuration as you please.

mount -t ext2fs /dev/ad0 /mnt

Networking

If you set up your rc.conf for networking, and chances are that you want to have nice network performance, then you should use this rather undocumented sysctl setting, which unleashes full networking power. Otherwise throughput seems highly limited between PV guests on the same physical box. Strangely it does not affect traffic between different boxes. It's not really documented anywhere, but I stumbled upon it a while ago in the freebsd-xen mailing list:

/etc/sysctl.conf
[...]
net.inet.tcp.tso=0
[...]

Why this changes networking performance so drastically, is beyond my knowledge, but at least for me it works. (YMMY)

Create a PV guest - Fast Track

If you have created your first guest like outlined in this tutorial, or are a bit more advanced FreeBSD user, you may want to make your life easier when you create your next guests. Let me very briefly show you how you would go about creating a guest from within a guest.

You should have:

  • current sources for base and kernel (csup /usr/share/examples/cvsup/standard-supfile)
  • enough space on disk within the DomU to hold a file large enough to accommodate your new DomU (absolute minimum is 200MB, but you're better off with quite a bit more)
  • alternatively a LVM partition or empty VM image file, which you can attach to the current DomU (FreeBSD PV supports hotplug via xm block-attach)

Create and Mount Target Image (File)

# truncate -s 256M freebsd.img
# mdconfig -f freebsd.img

# fdisk -BI md0
# bsdlabel -wB md0s1
# newfs -U md0s1a
# mount /dev/md0s1a /mnt

Create and Mount Target Image (hot-plugged block device: LVM or file from Dom0)

As an alternative you can use xm block-attach in Dom0 to use a file or LVM partition as a disk in your DomU. (In this example called ad4)

# fdisk -BI /dev/ad4
# bsdlabel -wB /dev/ad4s1
# newfs -U /dev/ad4s1a
# mount /dev/ad4s1a

Populate the empty Image

It's extremely easy to install an entire FreeBSD. But it takes time to finish, so get a coffee and cookies and then run this (or the other way round )

# cd /usr/src; make buildworld && make buildkernel KERNCONF=XEN
# setenv DESTDIR /mnt && make installworld && make installkernel KERNCONF=XEN && cd etc && make distribution

Then edit /mnt/etc/fstab:

/dev/ad1s1a       /               ufs     rw              1       1

Some tutorials suggested to use /dev/xbd0. I found this not to apply any more. Xen 4.1.1 and FreeBSD 8.2 map xbd0 correctly to common block device names.

Next, change /mnt/etc/ttys. Add the following line and comment all ttyv* lines:

xc0     "/usr/libexec/getty Pc"         cons25   on  secure

That's it already. unmount /mnt and you're ready to use your image. The Xen configuration file can easily be derived from the previous sections. Keep in mind that I'm always using ad1 or hdb, in other words the second block device, for the root partition. This allows adding in a pygrub-capable first block device as described earlier, or to temporarily insert a completely different guest, rescue image or whatever without having to tweak your fstab over and over again. At the end of the day it's a matter of taste, but don't complain if it doesn't work for you, because you insisted on doing it your way

Download

If you'd like to have a copy of the PV DomU, which I created while writing this tutorial, you can find it here:

FreeBSD 8.2 32bit PV DomU for Xen 4.1 w/ pygrub - 186.5MB - Aug 10th, 2011

The tar.gz expands to:

  • README
  • Xen configuration file
  • pygrub-enabled boot partition (50M)
  • FreeBSD root partition (750M)

References

Shortcuts



Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.